2 This file is part of GNUnet.
3 Copyright (C) 2009 GNUnet e.V.
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.
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.
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.
22 * @file multicast/gnunet-service-multicast.c
23 * @brief program that does multicast
24 * @author Christian Grothoff
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_cadet_service.h"
32 #include "gnunet_multicast_service.h"
33 #include "multicast.h"
36 * Handle to our current configuration.
38 static const struct GNUNET_CONFIGURATION_Handle *cfg;
43 static struct GNUNET_SERVICE_Handle *service;
48 static struct GNUNET_CADET_Handle *cadet;
51 * Identity of this peer.
53 static struct GNUNET_PeerIdentity this_peer;
56 * Handle to the statistics service.
58 static struct GNUNET_STATISTICS_Handle *stats;
61 * All connected origin clients.
62 * Group's pub_key_hash -> struct Origin * (uniq)
64 static struct GNUNET_CONTAINER_MultiHashMap *origins;
67 * All connected member clients.
68 * Group's pub_key_hash -> struct Member * (multi)
70 static struct GNUNET_CONTAINER_MultiHashMap *members;
73 * Connected member clients per group.
74 * Group's pub_key_hash -> Member's pub_key_hash (uniq) -> struct Member * (uniq)
76 static struct GNUNET_CONTAINER_MultiHashMap *group_members;
79 * Incoming CADET channels with connected children in the tree.
80 * Group's pub_key_hash -> struct Channel * (multi)
82 static struct GNUNET_CONTAINER_MultiHashMap *channels_in;
85 * Outgoing CADET channels connecting to parents in the tree.
86 * Group's pub_key_hash -> struct Channel * (multi)
88 static struct GNUNET_CONTAINER_MultiHashMap *channels_out;
91 * Incoming replay requests from CADET.
92 * Group's pub_key_hash ->
93 * H(fragment_id, message_id, fragment_offset, flags) -> struct Channel *
95 static struct GNUNET_CONTAINER_MultiHashMap *replay_req_cadet;
98 * Incoming replay requests from clients.
99 * Group's pub_key_hash ->
100 * H(fragment_id, message_id, fragment_offset, flags) -> struct GNUNET_SERVICE_Client *
102 static struct GNUNET_CONTAINER_MultiHashMap *replay_req_client;
106 * Join status of a remote peer.
116 enum ChannelDirection
124 * Context for a CADET channel.
129 * Group the channel belongs to.
131 * Only set for outgoing channels.
138 struct GNUNET_CADET_Channel *channel;
141 * CADET transmission handle.
143 struct GNUNET_CADET_TransmitHandle *tmit_handle;
146 * Public key of the target group.
148 struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key;
151 * Hash of @a group_pub_key.
153 struct GNUNET_HashCode group_pub_hash;
156 * Public key of the joining member.
158 struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key;
161 * Remote peer identity.
163 struct GNUNET_PeerIdentity peer;
166 * Is the remote peer admitted to the group?
167 * @see enum JoinStatus
172 * Number of messages waiting to be sent to CADET.
174 uint8_t msgs_pending;
178 * @see enum ChannelDirection
185 * List of connected clients.
189 struct ClientList *prev;
190 struct ClientList *next;
191 struct GNUNET_SERVICE_Client *client;
196 * Client context for an origin or member.
200 struct ClientList *clients_head;
201 struct ClientList *clients_tail;
204 * Public key of the group.
206 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
209 * Hash of @a pub_key.
211 struct GNUNET_HashCode pub_key_hash;
216 struct GNUNET_HashCode cadet_port_hash;
219 * Is the client disconnected? #GNUNET_YES or #GNUNET_NO
221 uint8_t disconnected;
224 * Is this an origin (#GNUNET_YES), or member (#GNUNET_NO)?
229 struct Origin *origin;
230 struct Member *member;
236 * Client context for a group's origin.
243 * Private key of the group.
245 struct GNUNET_CRYPTO_EddsaPrivateKey priv_key;
250 struct GNUNET_CADET_Port *cadet_port;
253 * Last message fragment ID sent to the group.
255 uint64_t max_fragment_id;
260 * Client context for a group member.
267 * Private key of the member.
269 struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key;
272 * Public key of the member.
274 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
277 * Hash of @a pub_key.
279 struct GNUNET_HashCode pub_key_hash;
282 * Join request sent to the origin / members.
284 struct MulticastJoinRequestMessage *join_req;
287 * Join decision sent in reply to our request.
289 * Only a positive decision is stored here, in case of a negative decision the
290 * client is disconnected.
292 struct MulticastJoinDecisionMessageHeader *join_dcsn;
295 * CADET channel to the origin.
297 struct Channel *origin_channel;
300 * Peer identity of origin.
302 struct GNUNET_PeerIdentity origin;
305 * Peer identity of relays (other members to connect).
307 struct GNUNET_PeerIdentity *relays;
310 * Last request fragment ID sent to the origin.
312 uint64_t max_fragment_id;
315 * Number of @a relays.
317 uint32_t relay_count;
325 struct GNUNET_SERVICE_Client *client;
330 struct ReplayRequestKey
332 uint64_t fragment_id;
334 uint64_t fragment_offset;
340 * Task run during shutdown.
345 shutdown_task (void *cls)
349 GNUNET_CADET_disconnect (cadet);
354 GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
357 /* FIXME: do more clean up here */
362 * Clean up origin data structures after a client disconnected.
365 cleanup_origin (struct Origin *orig)
367 struct Group *grp = &orig->group;
368 GNUNET_CONTAINER_multihashmap_remove (origins, &grp->pub_key_hash, orig);
369 if (NULL != orig->cadet_port)
371 GNUNET_CADET_close_port (orig->cadet_port);
372 orig->cadet_port = NULL;
379 * Clean up member data structures after a client disconnected.
382 cleanup_member (struct Member *mem)
384 struct Group *grp = &mem->group;
385 struct GNUNET_CONTAINER_MultiHashMap *
386 grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members,
388 GNUNET_assert (NULL != grp_mem);
389 GNUNET_CONTAINER_multihashmap_remove (grp_mem, &mem->pub_key_hash, mem);
391 if (0 == GNUNET_CONTAINER_multihashmap_size (grp_mem))
393 GNUNET_CONTAINER_multihashmap_remove (group_members, &grp->pub_key_hash,
395 GNUNET_CONTAINER_multihashmap_destroy (grp_mem);
397 if (NULL != mem->join_dcsn)
399 GNUNET_free (mem->join_dcsn);
400 mem->join_dcsn = NULL;
402 GNUNET_CONTAINER_multihashmap_remove (members, &grp->pub_key_hash, mem);
408 * Clean up group data structures after a client disconnected.
411 cleanup_group (struct Group *grp)
413 (GNUNET_YES == grp->is_origin)
414 ? cleanup_origin (grp->origin)
415 : cleanup_member (grp->member);
420 replay_key_hash (uint64_t fragment_id, uint64_t message_id,
421 uint64_t fragment_offset, uint64_t flags,
422 struct GNUNET_HashCode *key_hash)
424 struct ReplayRequestKey key = {
425 .fragment_id = fragment_id,
426 .message_id = message_id,
427 .fragment_offset = fragment_offset,
430 GNUNET_CRYPTO_hash (&key, sizeof (key), key_hash);
435 * Remove channel from replay request hashmap.
440 * @return #GNUNET_YES if there are more entries to process,
441 * #GNUNET_NO when reached end of hashmap.
444 replay_req_remove_cadet (struct Channel *chn)
446 struct GNUNET_CONTAINER_MultiHashMap *
447 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
448 &chn->group->pub_key_hash);
449 if (NULL == grp_replay_req)
452 struct GNUNET_CONTAINER_MultiHashMapIterator *
453 it = GNUNET_CONTAINER_multihashmap_iterator_create (grp_replay_req);
454 struct GNUNET_HashCode key;
455 const struct Channel *c;
457 == GNUNET_CONTAINER_multihashmap_iterator_next (it, &key,
462 GNUNET_CONTAINER_multihashmap_remove (grp_replay_req, &key, chn);
463 GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
467 GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
473 * Remove client from replay request hashmap.
478 * @return #GNUNET_YES if there are more entries to process,
479 * #GNUNET_NO when reached end of hashmap.
482 replay_req_remove_client (struct Group *grp, struct GNUNET_SERVICE_Client *client)
484 struct GNUNET_CONTAINER_MultiHashMap *
485 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
487 if (NULL == grp_replay_req)
490 struct GNUNET_CONTAINER_MultiHashMapIterator *
491 it = GNUNET_CONTAINER_multihashmap_iterator_create (grp_replay_req);
492 struct GNUNET_HashCode key;
493 const struct GNUNET_SERVICE_Client *c;
495 == GNUNET_CONTAINER_multihashmap_iterator_next (it, &key,
500 GNUNET_CONTAINER_multihashmap_remove (replay_req_client, &key, client);
501 GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
505 GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
511 * Send message to a client.
514 client_send (struct GNUNET_SERVICE_Client *client,
515 const struct GNUNET_MessageHeader *msg)
517 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
518 "%p Sending message to client.\n", client);
520 struct GNUNET_MQ_Envelope *
521 env = GNUNET_MQ_msg_copy (msg);
523 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
529 * Send message to all clients connected to the group.
532 client_send_group (const struct Group *grp,
533 const struct GNUNET_MessageHeader *msg)
535 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
536 "%p Sending message to all clients of the group.\n", grp);
538 struct ClientList *cl = grp->clients_head;
541 struct GNUNET_MQ_Envelope *
542 env = GNUNET_MQ_msg_copy (msg);
544 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (cl->client),
552 * Iterator callback for sending a message to origin clients.
555 client_send_origin_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
558 const struct GNUNET_MessageHeader *msg = cls;
559 struct Member *orig = origin;
561 client_send_group (&orig->group, msg);
567 * Iterator callback for sending a message to member clients.
570 client_send_member_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
573 const struct GNUNET_MessageHeader *msg = cls;
574 struct Member *mem = member;
576 if (NULL != mem->join_dcsn)
577 { /* Only send message to admitted members */
578 client_send_group (&mem->group, msg);
585 * Send message to all origin and member clients connected to the group.
587 * @param pub_key_hash
588 * H(key_pub) of the group.
593 client_send_all (struct GNUNET_HashCode *pub_key_hash,
594 const struct GNUNET_MessageHeader *msg)
597 n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash,
598 client_send_origin_cb,
600 n += GNUNET_CONTAINER_multihashmap_get_multiple (members, pub_key_hash,
601 client_send_member_cb,
608 * Send message to a random origin client or a random member client.
610 * @param grp The group to send @a msg to.
611 * @param msg Message to send.
614 client_send_random (struct GNUNET_HashCode *pub_key_hash,
615 const struct GNUNET_MessageHeader *msg)
618 n = GNUNET_CONTAINER_multihashmap_get_random (origins, client_send_origin_cb,
621 n = GNUNET_CONTAINER_multihashmap_get_random (members, client_send_member_cb,
628 * Send message to all origin clients connected to the group.
630 * @param pub_key_hash
631 * H(key_pub) of the group.
636 client_send_origin (struct GNUNET_HashCode *pub_key_hash,
637 const struct GNUNET_MessageHeader *msg)
640 n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash,
641 client_send_origin_cb,
648 * Send fragment acknowledgement to all clients of the channel.
650 * @param pub_key_hash
651 * H(key_pub) of the group.
654 client_send_ack (struct GNUNET_HashCode *pub_key_hash)
656 static struct GNUNET_MessageHeader *msg = NULL;
659 msg = GNUNET_malloc (sizeof (*msg));
660 msg->type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_FRAGMENT_ACK);
661 msg->size = htons (sizeof (*msg));
663 client_send_all (pub_key_hash, msg);
667 struct CadetTransmitClosure
670 const struct GNUNET_MessageHeader *msg;
675 * CADET is ready to transmit a message.
678 cadet_notify_transmit_ready (void *cls, size_t buf_size, void *buf)
682 /* FIXME: connection closed */
685 struct CadetTransmitClosure *tcls = cls;
686 struct Channel *chn = tcls->chn;
687 uint16_t msg_size = ntohs (tcls->msg->size);
688 GNUNET_assert (msg_size <= buf_size);
689 GNUNET_memcpy (buf, tcls->msg, msg_size);
692 if (0 == chn->msgs_pending)
696 else if (0 == --chn->msgs_pending)
698 client_send_ack (&chn->group_pub_hash);
705 * Send a message to a CADET channel.
707 * @param chn Channel.
708 * @param msg Message.
711 cadet_send_channel (struct Channel *chn, const struct GNUNET_MessageHeader *msg)
713 uint16_t msg_size = ntohs (msg->size);
714 struct GNUNET_MessageHeader *msg_copy = GNUNET_malloc (msg_size);
715 GNUNET_memcpy (msg_copy, msg, msg_size);
717 struct CadetTransmitClosure *tcls = GNUNET_malloc (sizeof (*tcls));
719 tcls->msg = msg_copy;
723 = GNUNET_CADET_notify_transmit_ready (chn->channel, GNUNET_NO,
724 GNUNET_TIME_UNIT_FOREVER_REL,
726 &cadet_notify_transmit_ready,
728 GNUNET_assert (NULL != chn->tmit_handle);
733 * Create new outgoing CADET channel.
736 * Peer to connect to.
737 * @param group_pub_key
738 * Public key of group the channel belongs to.
739 * @param group_pub_hash
740 * Hash of @a group_pub_key.
744 static struct Channel *
745 cadet_channel_create (struct Group *grp, struct GNUNET_PeerIdentity *peer)
747 struct Channel *chn = GNUNET_malloc (sizeof (*chn));
749 chn->group_pub_key = grp->pub_key;
750 chn->group_pub_hash = grp->pub_key_hash;
752 chn->direction = DIR_OUTGOING;
753 chn->join_status = JOIN_WAITING;
754 chn->channel = GNUNET_CADET_channel_create (cadet, chn, &chn->peer,
755 &grp->cadet_port_hash,
756 GNUNET_CADET_OPTION_RELIABLE);
757 GNUNET_CONTAINER_multihashmap_put (channels_out, &chn->group_pub_hash, chn,
758 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
764 * Create CADET channel and send a join request.
767 cadet_send_join_request (struct Member *mem)
769 mem->origin_channel = cadet_channel_create (&mem->group, &mem->origin);
770 cadet_send_channel (mem->origin_channel, &mem->join_req->header);
773 for (i = 0; i < mem->relay_count; i++)
776 chn = cadet_channel_create (&mem->group, &mem->relays[i]);
777 cadet_send_channel (chn, &mem->join_req->header);
783 cadet_send_join_decision_cb (void *cls,
784 const struct GNUNET_HashCode *group_pub_hash,
787 const struct MulticastJoinDecisionMessageHeader *hdcsn = cls;
788 struct Channel *chn = channel;
790 const struct MulticastJoinDecisionMessage *dcsn =
791 (struct MulticastJoinDecisionMessage *) &hdcsn[1];
793 if (0 == memcmp (&hdcsn->member_pub_key, &chn->member_pub_key, sizeof (chn->member_pub_key))
794 && 0 == memcmp (&hdcsn->peer, &chn->peer, sizeof (chn->peer)))
796 if (GNUNET_YES == ntohl (dcsn->is_admitted))
798 chn->join_status = JOIN_ADMITTED;
802 chn->join_status = JOIN_REFUSED;
805 cadet_send_channel (chn, &hdcsn->header);
813 * Send join decision to a remote peer.
816 cadet_send_join_decision (struct Group *grp,
817 const struct MulticastJoinDecisionMessageHeader *hdcsn)
819 GNUNET_CONTAINER_multihashmap_get_multiple (channels_in, &grp->pub_key_hash,
820 &cadet_send_join_decision_cb,
826 * Iterator callback for sending a message to origin clients.
829 cadet_send_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
832 const struct GNUNET_MessageHeader *msg = cls;
833 struct Channel *chn = channel;
834 if (JOIN_ADMITTED == chn->join_status)
835 cadet_send_channel (chn, msg);
841 * Send message to all connected children.
844 cadet_send_children (struct GNUNET_HashCode *pub_key_hash,
845 const struct GNUNET_MessageHeader *msg)
848 if (channels_in != NULL)
849 n += GNUNET_CONTAINER_multihashmap_get_multiple (channels_in, pub_key_hash,
850 cadet_send_cb, (void *) msg);
855 #if 0 // unused as yet
857 * Send message to all connected parents.
860 cadet_send_parents (struct GNUNET_HashCode *pub_key_hash,
861 const struct GNUNET_MessageHeader *msg)
864 if (channels_in != NULL)
865 n += GNUNET_CONTAINER_multihashmap_get_multiple (channels_out, pub_key_hash,
866 cadet_send_cb, (void *) msg);
873 * New incoming CADET channel.
876 cadet_notify_channel_new (void *cls,
877 struct GNUNET_CADET_Channel *channel,
878 const struct GNUNET_PeerIdentity *initiator,
879 const struct GNUNET_HashCode *port,
880 enum GNUNET_CADET_ChannelOption options)
887 * CADET channel is being destroyed.
890 cadet_notify_channel_end (void *cls,
891 const struct GNUNET_CADET_Channel *channel,
897 struct Channel *chn = ctx;
898 if (NULL != chn->group)
900 if (GNUNET_NO == chn->group->is_origin)
902 struct Member *mem = (struct Member *) chn->group;
903 if (chn == mem->origin_channel)
904 mem->origin_channel = NULL;
908 while (GNUNET_YES == replay_req_remove_cadet (chn));
915 group_set_cadet_port_hash (struct Group *grp)
918 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
922 GNUNET_APPLICATION_TYPE_MULTICAST,
924 GNUNET_CRYPTO_hash (&port, sizeof (port), &grp->cadet_port_hash);
929 * Handle a connecting client starting an origin.
932 handle_client_origin_start (void *cls,
933 const struct MulticastOriginStartMessage *msg)
935 struct Client *c = cls;
936 struct GNUNET_SERVICE_Client *client = c->client;
938 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
939 struct GNUNET_HashCode pub_key_hash;
941 GNUNET_CRYPTO_eddsa_key_get_public (&msg->group_key, &pub_key);
942 GNUNET_CRYPTO_hash (&pub_key, sizeof (pub_key), &pub_key_hash);
945 orig = GNUNET_CONTAINER_multihashmap_get (origins, &pub_key_hash);
950 orig = GNUNET_new (struct Origin);
951 orig->priv_key = msg->group_key;
952 orig->max_fragment_id = GNUNET_ntohll (msg->max_fragment_id);
954 grp = c->group = &orig->group;
956 grp->is_origin = GNUNET_YES;
957 grp->pub_key = pub_key;
958 grp->pub_key_hash = pub_key_hash;
960 GNUNET_CONTAINER_multihashmap_put (origins, &grp->pub_key_hash, orig,
961 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
963 group_set_cadet_port_hash (grp);
964 orig->cadet_port = GNUNET_CADET_open_port (cadet, &grp->cadet_port_hash,
965 cadet_notify_channel_new, NULL);
972 struct ClientList *cl = GNUNET_new (struct ClientList);
974 GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl);
976 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
977 "%p Client connected as origin to group %s.\n",
978 orig, GNUNET_h2s (&grp->pub_key_hash));
979 GNUNET_SERVICE_client_continue (client);
984 check_client_member_join (void *cls,
985 const struct MulticastMemberJoinMessage *msg)
987 uint16_t msg_size = ntohs (msg->header.size);
988 struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1];
989 uint32_t relay_count = ntohl (msg->relay_count);
990 uint16_t relay_size = relay_count * sizeof (*relays);
991 struct GNUNET_MessageHeader *join_msg = NULL;
992 uint16_t join_msg_size = 0;
993 if (sizeof (*msg) + relay_size + sizeof (struct GNUNET_MessageHeader)
996 join_msg = (struct GNUNET_MessageHeader *)
997 (((char *) &msg[1]) + relay_size);
998 join_msg_size = ntohs (join_msg->size);
1001 msg_size == (sizeof (*msg) + relay_size + join_msg_size)
1008 * Handle a connecting client joining a group.
1011 handle_client_member_join (void *cls,
1012 const struct MulticastMemberJoinMessage *msg)
1014 struct Client *c = cls;
1015 struct GNUNET_SERVICE_Client *client = c->client;
1017 uint16_t msg_size = ntohs (msg->header.size);
1019 struct GNUNET_CRYPTO_EcdsaPublicKey mem_pub_key;
1020 struct GNUNET_HashCode pub_key_hash, mem_pub_key_hash;
1022 GNUNET_CRYPTO_ecdsa_key_get_public (&msg->member_key, &mem_pub_key);
1023 GNUNET_CRYPTO_hash (&mem_pub_key, sizeof (mem_pub_key), &mem_pub_key_hash);
1024 GNUNET_CRYPTO_hash (&msg->group_pub_key, sizeof (msg->group_pub_key), &pub_key_hash);
1026 struct GNUNET_CONTAINER_MultiHashMap *
1027 grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members, &pub_key_hash);
1028 struct Member *mem = NULL;
1031 if (NULL != grp_mem)
1033 mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &mem_pub_key_hash);
1037 mem = GNUNET_new (struct Member);
1038 mem->origin = msg->origin;
1039 mem->priv_key = msg->member_key;
1040 mem->pub_key = mem_pub_key;
1041 mem->pub_key_hash = mem_pub_key_hash;
1042 mem->max_fragment_id = 0; // FIXME
1044 grp = c->group = &mem->group;
1046 grp->is_origin = GNUNET_NO;
1047 grp->pub_key = msg->group_pub_key;
1048 grp->pub_key_hash = pub_key_hash;
1049 group_set_cadet_port_hash (grp);
1051 if (NULL == grp_mem)
1053 grp_mem = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1054 GNUNET_CONTAINER_multihashmap_put (group_members, &grp->pub_key_hash, grp_mem,
1055 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1057 GNUNET_CONTAINER_multihashmap_put (grp_mem, &mem->pub_key_hash, mem,
1058 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1059 GNUNET_CONTAINER_multihashmap_put (members, &grp->pub_key_hash, mem,
1060 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1067 struct ClientList *cl = GNUNET_new (struct ClientList);
1068 cl->client = client;
1069 GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl);
1071 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1072 "%p Client connected to group %s..\n",
1073 mem, GNUNET_h2s (&grp->pub_key_hash));
1074 char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&mem->pub_key);
1075 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1076 "%p ..as member %s (%s).\n",
1077 mem, GNUNET_h2s (&mem->pub_key_hash), str);
1080 if (NULL != mem->join_dcsn)
1081 { /* Already got a join decision, send it to client. */
1082 struct GNUNET_MQ_Envelope *
1083 env = GNUNET_MQ_msg_copy (&mem->join_dcsn->header);
1085 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
1089 { /* First client of the group, send join request. */
1090 struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1];
1091 uint32_t relay_count = ntohl (msg->relay_count);
1092 uint16_t relay_size = relay_count * sizeof (*relays);
1093 struct GNUNET_MessageHeader *join_msg = NULL;
1094 uint16_t join_msg_size = 0;
1095 if (sizeof (*msg) + relay_size + sizeof (struct GNUNET_MessageHeader)
1098 join_msg = (struct GNUNET_MessageHeader *)
1099 (((char *) &msg[1]) + relay_size);
1100 join_msg_size = ntohs (join_msg->size);
1103 uint16_t req_msg_size = sizeof (struct MulticastJoinRequestMessage) + join_msg_size;
1104 struct MulticastJoinRequestMessage *
1105 req = GNUNET_malloc (req_msg_size);
1106 req->header.size = htons (req_msg_size);
1107 req->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST);
1108 req->group_pub_key = grp->pub_key;
1109 req->peer = this_peer;
1110 GNUNET_CRYPTO_ecdsa_key_get_public (&mem->priv_key, &req->member_pub_key);
1111 if (0 < join_msg_size)
1112 GNUNET_memcpy (&req[1], join_msg, join_msg_size);
1114 req->member_pub_key = mem->pub_key;
1115 req->purpose.size = htonl (req_msg_size
1116 - sizeof (req->header)
1117 - sizeof (req->reserved)
1118 - sizeof (req->signature));
1119 req->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
1121 if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (&mem->priv_key, &req->purpose,
1124 /* FIXME: handle error */
1128 if (NULL != mem->join_req)
1129 GNUNET_free (mem->join_req);
1130 mem->join_req = req;
1132 if (0 == client_send_origin (&grp->pub_key_hash, &mem->join_req->header))
1133 { /* No local origins, send to remote origin */
1134 cadet_send_join_request (mem);
1137 GNUNET_SERVICE_client_continue (client);
1142 client_send_join_decision (struct Member *mem,
1143 const struct MulticastJoinDecisionMessageHeader *hdcsn)
1145 client_send_group (&mem->group, &hdcsn->header);
1147 const struct MulticastJoinDecisionMessage *
1148 dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1];
1149 if (GNUNET_YES == ntohl (dcsn->is_admitted))
1150 { /* Member admitted, store join_decision. */
1151 uint16_t dcsn_size = ntohs (dcsn->header.size);
1152 mem->join_dcsn = GNUNET_malloc (dcsn_size);
1153 GNUNET_memcpy (mem->join_dcsn, dcsn, dcsn_size);
1156 { /* Refused entry, but replay would be still possible for past members. */
1162 check_client_join_decision (void *cls,
1163 const struct MulticastJoinDecisionMessageHeader *hdcsn)
1170 * Join decision from client.
1173 handle_client_join_decision (void *cls,
1174 const struct MulticastJoinDecisionMessageHeader *hdcsn)
1176 struct Client *c = cls;
1177 struct GNUNET_SERVICE_Client *client = c->client;
1178 struct Group *grp = c->group;
1183 GNUNET_SERVICE_client_drop (client);
1186 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1187 "%p Got join decision from client for group %s..\n",
1188 grp, GNUNET_h2s (&grp->pub_key_hash));
1190 struct GNUNET_CONTAINER_MultiHashMap *
1191 grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members,
1192 &grp->pub_key_hash);
1193 struct Member *mem = NULL;
1194 if (NULL != grp_mem)
1196 struct GNUNET_HashCode member_key_hash;
1197 GNUNET_CRYPTO_hash (&hdcsn->member_pub_key, sizeof (hdcsn->member_pub_key),
1199 mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &member_key_hash);
1200 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1201 "%p ..and member %s: %p\n",
1202 grp, GNUNET_h2s (&member_key_hash), mem);
1205 { /* Found local member */
1206 client_send_join_decision (mem, hdcsn);
1209 { /* Look for remote member */
1210 cadet_send_join_decision (grp, hdcsn);
1212 GNUNET_SERVICE_client_continue (client);
1217 check_client_multicast_message (void *cls,
1218 const struct GNUNET_MULTICAST_MessageHeader *msg)
1225 * Incoming message from a client.
1228 handle_client_multicast_message (void *cls,
1229 const struct GNUNET_MULTICAST_MessageHeader *msg)
1231 struct Client *c = cls;
1232 struct GNUNET_SERVICE_Client *client = c->client;
1233 struct Group *grp = c->group;
1238 GNUNET_SERVICE_client_drop (client);
1241 GNUNET_assert (GNUNET_YES == grp->is_origin);
1242 struct Origin *orig = grp->origin;
1244 /* FIXME: yucky, should use separate message structs for P2P and CS! */
1245 struct GNUNET_MULTICAST_MessageHeader *
1246 out = (struct GNUNET_MULTICAST_MessageHeader *) GNUNET_copy_message (&msg->header);
1247 out->fragment_id = GNUNET_htonll (++orig->max_fragment_id);
1248 out->purpose.size = htonl (ntohs (out->header.size)
1249 - sizeof (out->header)
1250 - sizeof (out->hop_counter)
1251 - sizeof (out->signature));
1252 out->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE);
1254 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_sign (&orig->priv_key, &out->purpose,
1260 client_send_all (&grp->pub_key_hash, &out->header);
1261 if (0 == cadet_send_children (&grp->pub_key_hash, &out->header))
1263 client_send_ack (&grp->pub_key_hash);
1267 GNUNET_SERVICE_client_continue (client);
1272 check_client_multicast_request (void *cls,
1273 const struct GNUNET_MULTICAST_RequestHeader *req)
1280 * Incoming request from a client.
1283 handle_client_multicast_request (void *cls,
1284 const struct GNUNET_MULTICAST_RequestHeader *req)
1286 struct Client *c = cls;
1287 struct GNUNET_SERVICE_Client *client = c->client;
1288 struct Group *grp = c->group;
1293 GNUNET_SERVICE_client_drop (client);
1296 GNUNET_assert (GNUNET_NO == grp->is_origin);
1297 struct Member *mem = grp->member;
1299 /* FIXME: yucky, should use separate message structs for P2P and CS! */
1300 struct GNUNET_MULTICAST_RequestHeader *
1301 out = (struct GNUNET_MULTICAST_RequestHeader *) GNUNET_copy_message (&req->header);
1302 out->member_pub_key = mem->pub_key;
1303 out->fragment_id = GNUNET_ntohll (++mem->max_fragment_id);
1304 out->purpose.size = htonl (ntohs (out->header.size)
1305 - sizeof (out->header)
1306 - sizeof (out->member_pub_key)
1307 - sizeof (out->signature));
1308 out->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
1310 if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (&mem->priv_key, &out->purpose,
1316 uint8_t send_ack = GNUNET_YES;
1317 if (0 == client_send_origin (&grp->pub_key_hash, &out->header))
1318 { /* No local origins, send to remote origin */
1319 if (NULL != mem->origin_channel)
1321 cadet_send_channel (mem->origin_channel, &out->header);
1322 send_ack = GNUNET_NO;
1326 /* FIXME: not yet connected to origin */
1327 GNUNET_SERVICE_client_drop (client);
1332 if (GNUNET_YES == send_ack)
1334 client_send_ack (&grp->pub_key_hash);
1337 GNUNET_SERVICE_client_continue (client);
1342 * Incoming replay request from a client.
1345 handle_client_replay_request (void *cls,
1346 const struct MulticastReplayRequestMessage *rep)
1348 struct Client *c = cls;
1349 struct GNUNET_SERVICE_Client *client = c->client;
1350 struct Group *grp = c->group;
1355 GNUNET_SERVICE_client_drop (client);
1358 GNUNET_assert (GNUNET_NO == grp->is_origin);
1359 struct Member *mem = grp->member;
1361 struct GNUNET_CONTAINER_MultiHashMap *
1362 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
1363 &grp->pub_key_hash);
1364 if (NULL == grp_replay_req)
1366 grp_replay_req = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1367 GNUNET_CONTAINER_multihashmap_put (replay_req_client,
1368 &grp->pub_key_hash, grp_replay_req,
1369 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1372 struct GNUNET_HashCode key_hash;
1373 replay_key_hash (rep->fragment_id, rep->message_id, rep->fragment_offset,
1374 rep->flags, &key_hash);
1375 GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, client,
1376 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1378 if (0 == client_send_origin (&grp->pub_key_hash, &rep->header))
1379 { /* No local origin, replay from remote members / origin. */
1380 if (NULL != mem->origin_channel)
1382 cadet_send_channel (mem->origin_channel, &rep->header);
1386 /* FIXME: not yet connected to origin */
1387 GNUNET_SERVICE_client_drop (client);
1391 GNUNET_SERVICE_client_continue (client);
1396 cadet_send_replay_response_cb (void *cls,
1397 const struct GNUNET_HashCode *key_hash,
1400 struct Channel *chn = value;
1401 struct GNUNET_MessageHeader *msg = cls;
1403 cadet_send_channel (chn, msg);
1409 client_send_replay_response_cb (void *cls,
1410 const struct GNUNET_HashCode *key_hash,
1413 struct GNUNET_SERVICE_Client *client = value;
1414 struct GNUNET_MessageHeader *msg = cls;
1416 client_send (client, msg);
1422 check_client_replay_response_end (void *cls,
1423 const struct MulticastReplayResponseMessage *res)
1430 * End of replay response from a client.
1433 handle_client_replay_response_end (void *cls,
1434 const struct MulticastReplayResponseMessage *res)
1436 struct Client *c = cls;
1437 struct GNUNET_SERVICE_Client *client = c->client;
1438 struct Group *grp = c->group;
1443 GNUNET_SERVICE_client_drop (client);
1447 struct GNUNET_HashCode key_hash;
1448 replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset,
1449 res->flags, &key_hash);
1451 struct GNUNET_CONTAINER_MultiHashMap *
1452 grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
1453 &grp->pub_key_hash);
1454 if (NULL != grp_replay_req_cadet)
1456 GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_cadet, &key_hash);
1458 struct GNUNET_CONTAINER_MultiHashMap *
1459 grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
1460 &grp->pub_key_hash);
1461 if (NULL != grp_replay_req_client)
1463 GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_client, &key_hash);
1465 GNUNET_SERVICE_client_continue (client);
1470 check_client_replay_response (void *cls,
1471 const struct MulticastReplayResponseMessage *res)
1473 const struct GNUNET_MessageHeader *msg = &res->header;
1474 if (GNUNET_MULTICAST_REC_OK == res->error_code)
1476 msg = GNUNET_MQ_extract_nested_mh (res);
1479 return GNUNET_SYSERR;
1487 * Incoming replay response from a client.
1489 * Respond with a multicast message on success, or otherwise with an error code.
1492 handle_client_replay_response (void *cls,
1493 const struct MulticastReplayResponseMessage *res)
1495 struct Client *c = cls;
1496 struct GNUNET_SERVICE_Client *client = c->client;
1497 struct Group *grp = c->group;
1502 GNUNET_SERVICE_client_drop (client);
1506 const struct GNUNET_MessageHeader *msg = &res->header;
1507 if (GNUNET_MULTICAST_REC_OK == res->error_code)
1509 msg = GNUNET_MQ_extract_nested_mh (res);
1512 struct GNUNET_HashCode key_hash;
1513 replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset,
1514 res->flags, &key_hash);
1516 struct GNUNET_CONTAINER_MultiHashMap *
1517 grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
1518 &grp->pub_key_hash);
1519 if (NULL != grp_replay_req_cadet)
1521 GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_cadet, &key_hash,
1522 cadet_send_replay_response_cb,
1525 if (GNUNET_MULTICAST_REC_OK == res->error_code)
1527 struct GNUNET_CONTAINER_MultiHashMap *
1528 grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
1529 &grp->pub_key_hash);
1530 if (NULL != grp_replay_req_client)
1532 GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_client, &key_hash,
1533 client_send_replay_response_cb,
1539 handle_client_replay_response_end (c, res);
1542 GNUNET_SERVICE_client_continue (client);
1547 * Incoming join request message from CADET.
1550 cadet_recv_join_request (void *cls,
1551 struct GNUNET_CADET_Channel *channel,
1553 const struct GNUNET_MessageHeader *m)
1555 GNUNET_CADET_receive_done(channel);
1556 const struct MulticastJoinRequestMessage *
1557 req = (const struct MulticastJoinRequestMessage *) m;
1558 uint16_t size = ntohs (m->size);
1559 if (size < sizeof (*req))
1561 GNUNET_break_op (0);
1562 return GNUNET_SYSERR;
1566 GNUNET_break_op (0);
1567 return GNUNET_SYSERR;
1569 if (ntohl (req->purpose.size) != (size
1570 - sizeof (req->header)
1571 - sizeof (req->reserved)
1572 - sizeof (req->signature)))
1574 GNUNET_break_op (0);
1575 return GNUNET_SYSERR;
1578 GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST,
1579 &req->purpose, &req->signature,
1580 &req->member_pub_key))
1582 GNUNET_break_op (0);
1583 return GNUNET_SYSERR;
1586 struct GNUNET_HashCode group_pub_hash;
1587 GNUNET_CRYPTO_hash (&req->group_pub_key, sizeof (req->group_pub_key), &group_pub_hash);
1589 struct Channel *chn = GNUNET_malloc (sizeof *chn);
1590 chn->channel = channel;
1591 chn->group_pub_key = req->group_pub_key;
1592 chn->group_pub_hash = group_pub_hash;
1593 chn->member_pub_key = req->member_pub_key;
1594 chn->peer = req->peer;
1595 chn->join_status = JOIN_WAITING;
1596 GNUNET_CONTAINER_multihashmap_put (channels_in, &chn->group_pub_hash, chn,
1597 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1600 client_send_all (&group_pub_hash, m);
1606 * Incoming join decision message from CADET.
1609 cadet_recv_join_decision (void *cls,
1610 struct GNUNET_CADET_Channel *channel,
1612 const struct GNUNET_MessageHeader *m)
1614 GNUNET_CADET_receive_done (channel);
1615 const struct MulticastJoinDecisionMessageHeader *
1616 hdcsn = (const struct MulticastJoinDecisionMessageHeader *) m;
1617 const struct MulticastJoinDecisionMessage *
1618 dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1];
1619 uint16_t size = ntohs (m->size);
1620 if (size < sizeof (struct MulticastJoinDecisionMessageHeader) +
1621 sizeof (struct MulticastJoinDecisionMessage))
1623 GNUNET_break_op (0);
1624 return GNUNET_SYSERR;
1626 struct Channel *chn = *ctx;
1629 GNUNET_break_op (0);
1630 return GNUNET_SYSERR;
1632 if (NULL == chn->group || GNUNET_NO != chn->group->is_origin)
1634 GNUNET_break_op (0);
1635 return GNUNET_SYSERR;
1637 switch (chn->join_status)
1640 return GNUNET_SYSERR;
1645 case JOIN_NOT_ASKED:
1650 // FIXME: do we need to copy chn->peer or compare it with hdcsn->peer?
1651 struct Member *mem = (struct Member *) chn->group;
1652 client_send_join_decision (mem, hdcsn);
1653 if (GNUNET_YES == ntohl (dcsn->is_admitted))
1655 chn->join_status = JOIN_ADMITTED;
1660 chn->join_status = JOIN_REFUSED;
1661 return GNUNET_SYSERR;
1666 * Incoming multicast message from CADET.
1669 cadet_recv_message (void *cls,
1670 struct GNUNET_CADET_Channel *channel,
1672 const struct GNUNET_MessageHeader *m)
1674 GNUNET_CADET_receive_done(channel);
1675 const struct GNUNET_MULTICAST_MessageHeader *
1676 msg = (const struct GNUNET_MULTICAST_MessageHeader *) m;
1677 uint16_t size = ntohs (m->size);
1678 if (size < sizeof (*msg))
1680 GNUNET_break_op (0);
1681 return GNUNET_SYSERR;
1683 struct Channel *chn = *ctx;
1686 GNUNET_break_op (0);
1687 return GNUNET_SYSERR;
1689 if (ntohl (msg->purpose.size) != (size
1690 - sizeof (msg->header)
1691 - sizeof (msg->hop_counter)
1692 - sizeof (msg->signature)))
1694 GNUNET_break_op (0);
1695 return GNUNET_SYSERR;
1698 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE,
1699 &msg->purpose, &msg->signature,
1700 &chn->group_pub_key))
1702 GNUNET_break_op (0);
1703 return GNUNET_SYSERR;
1706 client_send_all (&chn->group_pub_hash, m);
1712 * Incoming multicast request message from CADET.
1715 cadet_recv_request (void *cls,
1716 struct GNUNET_CADET_Channel *channel,
1718 const struct GNUNET_MessageHeader *m)
1720 GNUNET_CADET_receive_done(channel);
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))
1726 GNUNET_break_op (0);
1727 return GNUNET_SYSERR;
1729 struct Channel *chn = *ctx;
1732 GNUNET_break_op (0);
1733 return GNUNET_SYSERR;
1735 if (ntohl (req->purpose.size) != (size
1736 - sizeof (req->header)
1737 - sizeof (req->member_pub_key)
1738 - sizeof (req->signature)))
1740 GNUNET_break_op (0);
1741 return GNUNET_SYSERR;
1744 GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST,
1745 &req->purpose, &req->signature,
1746 &req->member_pub_key))
1748 GNUNET_break_op (0);
1749 return GNUNET_SYSERR;
1752 client_send_origin (&chn->group_pub_hash, m);
1758 * Incoming multicast replay request from CADET.
1761 cadet_recv_replay_request (void *cls,
1762 struct GNUNET_CADET_Channel *channel,
1764 const struct GNUNET_MessageHeader *m)
1766 GNUNET_CADET_receive_done(channel);
1767 struct MulticastReplayRequestMessage rep;
1768 uint16_t size = ntohs (m->size);
1769 if (size < sizeof (rep))
1771 GNUNET_break_op (0);
1772 return GNUNET_SYSERR;
1774 struct Channel *chn = *ctx;
1776 GNUNET_memcpy (&rep, m, sizeof (rep));
1777 GNUNET_memcpy (&rep.member_pub_key, &chn->member_pub_key, sizeof (chn->member_pub_key));
1779 struct GNUNET_CONTAINER_MultiHashMap *
1780 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
1781 &chn->group->pub_key_hash);
1782 if (NULL == grp_replay_req)
1784 grp_replay_req = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1785 GNUNET_CONTAINER_multihashmap_put (replay_req_cadet,
1786 &chn->group->pub_key_hash, grp_replay_req,
1787 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1789 struct GNUNET_HashCode key_hash;
1790 replay_key_hash (rep.fragment_id, rep.message_id, rep.fragment_offset,
1791 rep.flags, &key_hash);
1792 GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, chn,
1793 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1795 client_send_random (&chn->group_pub_hash, &rep.header);
1801 * Incoming multicast replay response from CADET.
1804 cadet_recv_replay_response (void *cls,
1805 struct GNUNET_CADET_Channel *channel,
1807 const struct GNUNET_MessageHeader *m)
1809 GNUNET_CADET_receive_done(channel);
1810 //struct Channel *chn = *ctx;
1812 /* @todo FIXME: got replay error response, send request to other members */
1819 * A new client connected.
1822 * @param client client to add
1823 * @param mq message queue for @a client
1827 client_notify_connect (void *cls,
1828 struct GNUNET_SERVICE_Client *client,
1829 struct GNUNET_MQ_Handle *mq)
1831 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client connected: %p\n", client);
1832 /* FIXME: send connect ACK */
1834 struct Client *c = GNUNET_new (struct Client);
1842 * Called whenever a client is disconnected.
1843 * Frees our resources associated with that client.
1845 * @param cls closure
1846 * @param client identification of the client
1847 * @param app_ctx must match @a client
1850 client_notify_disconnect (void *cls,
1851 struct GNUNET_SERVICE_Client *client,
1854 struct Client *c = app_ctx;
1855 struct Group *grp = c->group;
1860 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1861 "%p User context is NULL in client_disconnect()\n", grp);
1866 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1867 "%p Client (%s) disconnected from group %s\n",
1868 grp, (GNUNET_YES == grp->is_origin) ? "origin" : "member",
1869 GNUNET_h2s (&grp->pub_key_hash));
1871 struct ClientList *cl = grp->clients_head;
1874 if (cl->client == client)
1876 GNUNET_CONTAINER_DLL_remove (grp->clients_head, grp->clients_tail, cl);
1883 while (GNUNET_YES == replay_req_remove_client (grp, client));
1885 if (NULL == grp->clients_head)
1886 { /* Last client disconnected. */
1888 if (NULL != grp->tmit_head)
1889 { /* Send pending messages via CADET before cleanup. */
1890 transmit_message (grp);
1895 cleanup_group (grp);
1902 * Message handlers for CADET.
1904 static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
1905 { cadet_recv_join_request,
1906 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST, 0 },
1908 { cadet_recv_join_decision,
1909 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION, 0 },
1911 { cadet_recv_message,
1912 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, 0 },
1914 { cadet_recv_request,
1915 GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST, 0 },
1917 { cadet_recv_replay_request,
1918 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST, 0 },
1920 { cadet_recv_replay_response,
1921 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE, 0 },
1930 * @param cls closure
1931 * @param server the initialized server
1932 * @param cfg configuration to use
1936 const struct GNUNET_CONFIGURATION_Handle *c,
1937 struct GNUNET_SERVICE_Handle *svc)
1941 GNUNET_CRYPTO_get_peer_identity (cfg, &this_peer);
1943 stats = GNUNET_STATISTICS_create ("multicast", cfg);
1944 origins = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1945 members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1946 group_members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1947 channels_in = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1948 channels_out = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1949 replay_req_cadet = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1950 replay_req_client = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1952 cadet = GNUNET_CADET_connect (cfg, NULL,
1953 cadet_notify_channel_end,
1955 GNUNET_assert (NULL != cadet);
1957 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
1963 * Define "main" method using service macro.
1967 GNUNET_SERVICE_OPTION_NONE,
1969 client_notify_connect,
1970 client_notify_disconnect,
1972 GNUNET_MQ_hd_fixed_size (client_origin_start,
1973 GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START,
1974 struct MulticastOriginStartMessage,
1976 GNUNET_MQ_hd_var_size (client_member_join,
1977 GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_JOIN,
1978 struct MulticastMemberJoinMessage,
1980 GNUNET_MQ_hd_var_size (client_join_decision,
1981 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION,
1982 struct MulticastJoinDecisionMessageHeader,
1984 GNUNET_MQ_hd_var_size (client_multicast_message,
1985 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE,
1986 struct GNUNET_MULTICAST_MessageHeader,
1988 GNUNET_MQ_hd_var_size (client_multicast_request,
1989 GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST,
1990 struct GNUNET_MULTICAST_RequestHeader,
1992 GNUNET_MQ_hd_fixed_size (client_replay_request,
1993 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
1994 struct MulticastReplayRequestMessage,
1996 GNUNET_MQ_hd_var_size (client_replay_response,
1997 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE,
1998 struct MulticastReplayResponseMessage,
2000 GNUNET_MQ_hd_var_size (client_replay_response_end,
2001 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE_END,
2002 struct MulticastReplayResponseMessage,
2005 /* end of gnunet-service-multicast.c */