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 * Current window size, set by cadet_notify_window_change()
171 * Is the connection established?
176 * Is the remote peer admitted to the group?
177 * @see enum JoinStatus
182 * Number of messages waiting to be sent to CADET.
184 uint8_t msgs_pending;
188 * @see enum ChannelDirection
195 * List of connected clients.
199 struct ClientList *prev;
200 struct ClientList *next;
201 struct GNUNET_SERVICE_Client *client;
206 * Client context for an origin or member.
210 struct ClientList *clients_head;
211 struct ClientList *clients_tail;
214 * Public key of the group.
216 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
219 * Hash of @a pub_key.
221 struct GNUNET_HashCode pub_key_hash;
226 struct GNUNET_HashCode cadet_port_hash;
229 * Is the client disconnected? #GNUNET_YES or #GNUNET_NO
231 uint8_t disconnected;
234 * Is this an origin (#GNUNET_YES), or member (#GNUNET_NO)?
239 struct Origin *origin;
240 struct Member *member;
246 * Client context for a group's origin.
253 * Private key of the group.
255 struct GNUNET_CRYPTO_EddsaPrivateKey priv_key;
260 struct GNUNET_CADET_Port *cadet_port;
263 * Last message fragment ID sent to the group.
265 uint64_t max_fragment_id;
270 * Client context for a group member.
277 * Private key of the member.
279 struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key;
282 * Public key of the member.
284 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
287 * Hash of @a pub_key.
289 struct GNUNET_HashCode pub_key_hash;
292 * Join request sent to the origin / members.
294 struct MulticastJoinRequestMessage *join_req;
297 * Join decision sent in reply to our request.
299 * Only a positive decision is stored here, in case of a negative decision the
300 * client is disconnected.
302 struct MulticastJoinDecisionMessageHeader *join_dcsn;
305 * CADET channel to the origin.
307 struct Channel *origin_channel;
310 * Peer identity of origin.
312 struct GNUNET_PeerIdentity origin;
315 * Peer identity of relays (other members to connect).
317 struct GNUNET_PeerIdentity *relays;
320 * Last request fragment ID sent to the origin.
322 uint64_t max_fragment_id;
325 * Number of @a relays.
327 uint32_t relay_count;
335 struct GNUNET_SERVICE_Client *client;
340 struct ReplayRequestKey
342 uint64_t fragment_id;
344 uint64_t fragment_offset;
349 static struct Channel *
350 cadet_channel_create (struct Group *grp, struct GNUNET_PeerIdentity *peer);
353 cadet_channel_destroy (struct Channel *chn);
356 client_send_join_decision (struct Member *mem,
357 const struct MulticastJoinDecisionMessageHeader *hdcsn);
361 * Task run during shutdown.
366 shutdown_task (void *cls)
370 GNUNET_CADET_disconnect (cadet);
375 GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
378 /* FIXME: do more clean up here */
383 * Clean up origin data structures after a client disconnected.
386 cleanup_origin (struct Origin *orig)
388 struct Group *grp = &orig->group;
389 GNUNET_CONTAINER_multihashmap_remove (origins, &grp->pub_key_hash, orig);
390 if (NULL != orig->cadet_port)
392 GNUNET_CADET_close_port (orig->cadet_port);
393 orig->cadet_port = NULL;
400 * Clean up member data structures after a client disconnected.
403 cleanup_member (struct Member *mem)
405 struct Group *grp = &mem->group;
406 struct GNUNET_CONTAINER_MultiHashMap *
407 grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members,
409 GNUNET_assert (NULL != grp_mem);
410 GNUNET_CONTAINER_multihashmap_remove (grp_mem, &mem->pub_key_hash, mem);
412 if (0 == GNUNET_CONTAINER_multihashmap_size (grp_mem))
414 GNUNET_CONTAINER_multihashmap_remove (group_members, &grp->pub_key_hash,
416 GNUNET_CONTAINER_multihashmap_destroy (grp_mem);
418 if (NULL != mem->join_dcsn)
420 GNUNET_free (mem->join_dcsn);
421 mem->join_dcsn = NULL;
423 GNUNET_CONTAINER_multihashmap_remove (members, &grp->pub_key_hash, mem);
429 * Clean up group data structures after a client disconnected.
432 cleanup_group (struct Group *grp)
434 (GNUNET_YES == grp->is_origin)
435 ? cleanup_origin (grp->origin)
436 : cleanup_member (grp->member);
441 replay_key_hash (uint64_t fragment_id, uint64_t message_id,
442 uint64_t fragment_offset, uint64_t flags,
443 struct GNUNET_HashCode *key_hash)
445 struct ReplayRequestKey key = {
446 .fragment_id = fragment_id,
447 .message_id = message_id,
448 .fragment_offset = fragment_offset,
451 GNUNET_CRYPTO_hash (&key, sizeof (key), key_hash);
456 * Remove channel from replay request hashmap.
461 * @return #GNUNET_YES if there are more entries to process,
462 * #GNUNET_NO when reached end of hashmap.
465 replay_req_remove_cadet (struct Channel *chn)
467 struct GNUNET_CONTAINER_MultiHashMap *
468 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
469 &chn->group->pub_key_hash);
470 if (NULL == grp_replay_req)
473 struct GNUNET_CONTAINER_MultiHashMapIterator *
474 it = GNUNET_CONTAINER_multihashmap_iterator_create (grp_replay_req);
475 struct GNUNET_HashCode key;
476 const struct Channel *c;
478 == GNUNET_CONTAINER_multihashmap_iterator_next (it, &key,
483 GNUNET_CONTAINER_multihashmap_remove (grp_replay_req, &key, chn);
484 GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
488 GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
494 * Remove client from replay request hashmap.
499 * @return #GNUNET_YES if there are more entries to process,
500 * #GNUNET_NO when reached end of hashmap.
503 replay_req_remove_client (struct Group *grp, struct GNUNET_SERVICE_Client *client)
505 struct GNUNET_CONTAINER_MultiHashMap *
506 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
508 if (NULL == grp_replay_req)
511 struct GNUNET_CONTAINER_MultiHashMapIterator *
512 it = GNUNET_CONTAINER_multihashmap_iterator_create (grp_replay_req);
513 struct GNUNET_HashCode key;
514 const struct GNUNET_SERVICE_Client *c;
516 == GNUNET_CONTAINER_multihashmap_iterator_next (it, &key,
521 GNUNET_CONTAINER_multihashmap_remove (grp_replay_req, &key, client);
522 GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
526 GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
532 * Send message to a client.
535 client_send (struct GNUNET_SERVICE_Client *client,
536 const struct GNUNET_MessageHeader *msg)
538 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
539 "%p Sending message to client.\n", client);
541 struct GNUNET_MQ_Envelope *
542 env = GNUNET_MQ_msg_copy (msg);
544 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
550 * Send message to all clients connected to the group.
553 client_send_group (const struct Group *grp,
554 const struct GNUNET_MessageHeader *msg)
556 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
557 "%p Sending message to all clients of the group.\n", grp);
559 struct ClientList *cl = grp->clients_head;
562 struct GNUNET_MQ_Envelope *
563 env = GNUNET_MQ_msg_copy (msg);
565 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (cl->client),
573 * Iterator callback for sending a message to origin clients.
576 client_send_origin_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
579 const struct GNUNET_MessageHeader *msg = cls;
580 struct Member *orig = origin;
582 client_send_group (&orig->group, msg);
588 * Iterator callback for sending a message to member clients.
591 client_send_member_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
594 const struct GNUNET_MessageHeader *msg = cls;
595 struct Member *mem = member;
597 if (NULL != mem->join_dcsn)
598 { /* Only send message to admitted members */
599 client_send_group (&mem->group, msg);
606 * Send message to all origin and member clients connected to the group.
608 * @param pub_key_hash
609 * H(key_pub) of the group.
614 client_send_all (struct GNUNET_HashCode *pub_key_hash,
615 const struct GNUNET_MessageHeader *msg)
618 n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash,
619 client_send_origin_cb,
621 n += GNUNET_CONTAINER_multihashmap_get_multiple (members, pub_key_hash,
622 client_send_member_cb,
629 * Send message to a random origin client or a random member client.
631 * @param grp The group to send @a msg to.
632 * @param msg Message to send.
635 client_send_random (struct GNUNET_HashCode *pub_key_hash,
636 const struct GNUNET_MessageHeader *msg)
639 n = GNUNET_CONTAINER_multihashmap_get_random (origins, client_send_origin_cb,
642 n = GNUNET_CONTAINER_multihashmap_get_random (members, client_send_member_cb,
649 * Send message to all origin clients connected to the group.
651 * @param pub_key_hash
652 * H(key_pub) of the group.
657 client_send_origin (struct GNUNET_HashCode *pub_key_hash,
658 const struct GNUNET_MessageHeader *msg)
661 n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash,
662 client_send_origin_cb,
669 * Send fragment acknowledgement to all clients of the channel.
671 * @param pub_key_hash
672 * H(key_pub) of the group.
675 client_send_ack (struct GNUNET_HashCode *pub_key_hash)
677 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
678 "Sending message ACK to client.\n");
680 static struct GNUNET_MessageHeader *msg = NULL;
683 msg = GNUNET_malloc (sizeof (*msg));
684 msg->type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_FRAGMENT_ACK);
685 msg->size = htons (sizeof (*msg));
687 client_send_all (pub_key_hash, msg);
691 struct CadetTransmitClosure
694 const struct GNUNET_MessageHeader *msg;
699 * Send a message to a CADET channel.
701 * @param chn Channel.
702 * @param msg Message.
705 cadet_send_channel (struct Channel *chn, const struct GNUNET_MessageHeader *msg)
707 struct GNUNET_MQ_Envelope *
708 env = GNUNET_MQ_msg_copy (msg);
710 GNUNET_MQ_send (GNUNET_CADET_get_mq (chn->channel), env);
712 if (0 < chn->window_size)
714 client_send_ack (&chn->group_pub_hash);
719 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
720 "%p Queuing message. Pending messages: %u\n",
721 chn, chn->msgs_pending);
727 * Create CADET channel and send a join request.
730 cadet_send_join_request (struct Member *mem)
732 mem->origin_channel = cadet_channel_create (&mem->group, &mem->origin);
733 cadet_send_channel (mem->origin_channel, &mem->join_req->header);
736 for (i = 0; i < mem->relay_count; i++)
739 chn = cadet_channel_create (&mem->group, &mem->relays[i]);
740 cadet_send_channel (chn, &mem->join_req->header);
746 cadet_send_join_decision_cb (void *cls,
747 const struct GNUNET_HashCode *group_pub_hash,
750 const struct MulticastJoinDecisionMessageHeader *hdcsn = cls;
751 struct Channel *chn = channel;
753 const struct MulticastJoinDecisionMessage *dcsn =
754 (struct MulticastJoinDecisionMessage *) &hdcsn[1];
756 if (0 == memcmp (&hdcsn->member_pub_key, &chn->member_pub_key, sizeof (chn->member_pub_key))
757 && 0 == memcmp (&hdcsn->peer, &chn->peer, sizeof (chn->peer)))
759 if (GNUNET_YES == ntohl (dcsn->is_admitted))
761 chn->join_status = JOIN_ADMITTED;
765 chn->join_status = JOIN_REFUSED;
768 cadet_send_channel (chn, &hdcsn->header);
776 * Send join decision to a remote peer.
779 cadet_send_join_decision (struct Group *grp,
780 const struct MulticastJoinDecisionMessageHeader *hdcsn)
782 GNUNET_CONTAINER_multihashmap_get_multiple (channels_in, &grp->pub_key_hash,
783 &cadet_send_join_decision_cb,
789 * Iterator callback for sending a message to origin clients.
792 cadet_send_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
795 const struct GNUNET_MessageHeader *msg = cls;
796 struct Channel *chn = channel;
797 if (JOIN_ADMITTED == chn->join_status)
798 cadet_send_channel (chn, msg);
804 * Send message to all connected children.
807 cadet_send_children (struct GNUNET_HashCode *pub_key_hash,
808 const struct GNUNET_MessageHeader *msg)
811 if (channels_in != NULL)
812 n += GNUNET_CONTAINER_multihashmap_get_multiple (channels_in, pub_key_hash,
813 cadet_send_cb, (void *) msg);
818 #if 0 // unused as yet
820 * Send message to all connected parents.
823 cadet_send_parents (struct GNUNET_HashCode *pub_key_hash,
824 const struct GNUNET_MessageHeader *msg)
827 if (channels_in != NULL)
828 n += GNUNET_CONTAINER_multihashmap_get_multiple (channels_out, pub_key_hash,
829 cadet_send_cb, (void *) msg);
836 * CADET channel connect handler.
838 * @see GNUNET_CADET_ConnectEventHandler()
841 cadet_notify_connect (void *cls,
842 struct GNUNET_CADET_Channel *channel,
843 const struct GNUNET_PeerIdentity *source)
845 struct Channel *chn = GNUNET_malloc (sizeof *chn);
847 chn->channel = channel;
848 chn->direction = DIR_INCOMING;
849 chn->join_status = JOIN_NOT_ASKED;
851 GNUNET_CONTAINER_multihashmap_put (channels_in, &chn->group_pub_hash, chn,
852 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
858 * CADET window size change handler.
860 * @see GNUNET_CADET_WindowSizeEventHandler()
863 cadet_notify_window_change (void *cls,
864 const struct GNUNET_CADET_Channel *channel,
867 struct Channel *chn = cls;
869 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
870 "%p Window size changed to %d. Pending messages: %u\n",
871 chn, window_size, chn->msgs_pending);
873 chn->is_connected = GNUNET_YES;
874 chn->window_size = (int32_t) window_size;
876 for (int i = 0; i < window_size; i++)
878 if (0 < chn->msgs_pending)
880 client_send_ack (&chn->group_pub_hash);
892 * CADET channel disconnect handler.
894 * @see GNUNET_CADET_DisconnectEventHandler()
897 cadet_notify_disconnect (void *cls,
898 const struct GNUNET_CADET_Channel *channel)
903 struct Channel *chn = cls;
904 if (NULL != chn->group)
906 if (GNUNET_NO == chn->group->is_origin)
908 struct Member *mem = (struct Member *) chn->group;
909 if (chn == mem->origin_channel)
910 mem->origin_channel = NULL;
917 ret = replay_req_remove_cadet (chn);
919 while (GNUNET_YES == ret);
926 check_cadet_join_request (void *cls,
927 const struct MulticastJoinRequestMessage *req)
929 struct Channel *chn = cls;
932 || JOIN_NOT_ASKED != chn->join_status)
934 return GNUNET_SYSERR;
937 uint16_t size = ntohs (req->header.size);
938 if (size < sizeof (*req))
941 return GNUNET_SYSERR;
943 if (ntohl (req->purpose.size) != (size
944 - sizeof (req->header)
945 - sizeof (req->reserved)
946 - sizeof (req->signature)))
949 return GNUNET_SYSERR;
952 GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST,
953 &req->purpose, &req->signature,
954 &req->member_pub_key))
957 return GNUNET_SYSERR;
965 * Incoming join request message from CADET.
968 handle_cadet_join_request (void *cls,
969 const struct MulticastJoinRequestMessage *req)
971 struct Channel *chn = cls;
972 GNUNET_CADET_receive_done (chn->channel);
974 struct GNUNET_HashCode group_pub_hash;
975 GNUNET_CRYPTO_hash (&req->group_pub_key, sizeof (req->group_pub_key), &group_pub_hash);
976 chn->group_pub_key = req->group_pub_key;
977 chn->group_pub_hash = group_pub_hash;
978 chn->member_pub_key = req->member_pub_key;
979 chn->peer = req->peer;
980 chn->join_status = JOIN_WAITING;
982 client_send_all (&group_pub_hash, &req->header);
987 check_cadet_join_decision (void *cls,
988 const struct MulticastJoinDecisionMessageHeader *hdcsn)
990 uint16_t size = ntohs (hdcsn->header.size);
991 if (size < sizeof (struct MulticastJoinDecisionMessageHeader) +
992 sizeof (struct MulticastJoinDecisionMessage))
995 return GNUNET_SYSERR;
998 struct Channel *chn = cls;
1002 return GNUNET_SYSERR;
1004 if (NULL == chn->group || GNUNET_NO != chn->group->is_origin)
1007 return GNUNET_SYSERR;
1009 switch (chn->join_status)
1012 return GNUNET_SYSERR;
1017 case JOIN_NOT_ASKED:
1027 * Incoming join decision message from CADET.
1030 handle_cadet_join_decision (void *cls,
1031 const struct MulticastJoinDecisionMessageHeader *hdcsn)
1033 const struct MulticastJoinDecisionMessage *
1034 dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1];
1036 struct Channel *chn = cls;
1037 GNUNET_CADET_receive_done (chn->channel);
1039 // FIXME: do we need to copy chn->peer or compare it with hdcsn->peer?
1040 struct Member *mem = (struct Member *) chn->group;
1041 client_send_join_decision (mem, hdcsn);
1042 if (GNUNET_YES == ntohl (dcsn->is_admitted))
1044 chn->join_status = JOIN_ADMITTED;
1048 chn->join_status = JOIN_REFUSED;
1049 cadet_channel_destroy (chn);
1055 check_cadet_message (void *cls,
1056 const struct GNUNET_MULTICAST_MessageHeader *msg)
1058 uint16_t size = ntohs (msg->header.size);
1059 if (size < sizeof (*msg))
1061 GNUNET_break_op (0);
1062 return GNUNET_SYSERR;
1065 struct Channel *chn = cls;
1069 return GNUNET_SYSERR;
1071 if (ntohl (msg->purpose.size) != (size
1072 - sizeof (msg->header)
1073 - sizeof (msg->hop_counter)
1074 - sizeof (msg->signature)))
1076 GNUNET_break_op (0);
1077 return GNUNET_SYSERR;
1080 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE,
1081 &msg->purpose, &msg->signature,
1082 &chn->group_pub_key))
1084 GNUNET_break_op (0);
1085 return GNUNET_SYSERR;
1093 * Incoming multicast message from CADET.
1096 handle_cadet_message (void *cls,
1097 const struct GNUNET_MULTICAST_MessageHeader *msg)
1099 struct Channel *chn = cls;
1100 GNUNET_CADET_receive_done (chn->channel);
1101 client_send_all (&chn->group_pub_hash, &msg->header);
1106 check_cadet_request (void *cls,
1107 const struct GNUNET_MULTICAST_RequestHeader *req)
1109 uint16_t size = ntohs (req->header.size);
1110 if (size < sizeof (*req))
1112 GNUNET_break_op (0);
1113 return GNUNET_SYSERR;
1116 struct Channel *chn = cls;
1120 return GNUNET_SYSERR;
1122 if (ntohl (req->purpose.size) != (size
1123 - sizeof (req->header)
1124 - sizeof (req->member_pub_key)
1125 - sizeof (req->signature)))
1127 GNUNET_break_op (0);
1128 return GNUNET_SYSERR;
1131 GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST,
1132 &req->purpose, &req->signature,
1133 &req->member_pub_key))
1135 GNUNET_break_op (0);
1136 return GNUNET_SYSERR;
1144 * Incoming multicast request message from CADET.
1147 handle_cadet_request (void *cls,
1148 const struct GNUNET_MULTICAST_RequestHeader *req)
1150 struct Channel *chn = cls;
1151 GNUNET_CADET_receive_done (chn->channel);
1152 client_send_origin (&chn->group_pub_hash, &req->header);
1157 check_cadet_replay_request (void *cls,
1158 const struct MulticastReplayRequestMessage *req)
1160 uint16_t size = ntohs (req->header.size);
1161 if (size < sizeof (*req))
1163 GNUNET_break_op (0);
1164 return GNUNET_SYSERR;
1167 struct Channel *chn = cls;
1170 GNUNET_break_op (0);
1171 return GNUNET_SYSERR;
1179 * Incoming multicast replay request from CADET.
1182 handle_cadet_replay_request (void *cls,
1183 const struct MulticastReplayRequestMessage *req)
1185 struct Channel *chn = cls;
1186 GNUNET_CADET_receive_done (chn->channel);
1188 struct MulticastReplayRequestMessage rep = *req;
1189 GNUNET_memcpy (&rep.member_pub_key, &chn->member_pub_key, sizeof (chn->member_pub_key));
1191 struct GNUNET_CONTAINER_MultiHashMap *
1192 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
1193 &chn->group->pub_key_hash);
1194 if (NULL == grp_replay_req)
1196 grp_replay_req = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1197 GNUNET_CONTAINER_multihashmap_put (replay_req_cadet,
1198 &chn->group->pub_key_hash, grp_replay_req,
1199 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1201 struct GNUNET_HashCode key_hash;
1202 replay_key_hash (rep.fragment_id, rep.message_id, rep.fragment_offset,
1203 rep.flags, &key_hash);
1204 GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, chn,
1205 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1207 client_send_random (&chn->group_pub_hash, &rep.header);
1212 check_cadet_replay_response (void *cls,
1213 const struct MulticastReplayResponseMessage *res)
1215 struct Channel *chn = cls;
1219 return GNUNET_SYSERR;
1226 * Incoming multicast replay response from CADET.
1229 handle_cadet_replay_response (void *cls,
1230 const struct MulticastReplayResponseMessage *res)
1232 struct Channel *chn = cls;
1233 GNUNET_CADET_receive_done (chn->channel);
1235 /* @todo FIXME: got replay error response, send request to other members */
1240 group_set_cadet_port_hash (struct Group *grp)
1243 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
1247 GNUNET_APPLICATION_TYPE_MULTICAST,
1249 GNUNET_CRYPTO_hash (&port, sizeof (port), &grp->cadet_port_hash);
1255 * Create new outgoing CADET channel.
1258 * Peer to connect to.
1259 * @param group_pub_key
1260 * Public key of group the channel belongs to.
1261 * @param group_pub_hash
1262 * Hash of @a group_pub_key.
1266 static struct Channel *
1267 cadet_channel_create (struct Group *grp, struct GNUNET_PeerIdentity *peer)
1269 struct Channel *chn = GNUNET_malloc (sizeof (*chn));
1271 chn->group_pub_key = grp->pub_key;
1272 chn->group_pub_hash = grp->pub_key_hash;
1274 chn->direction = DIR_OUTGOING;
1275 chn->is_connected = GNUNET_NO;
1276 chn->join_status = JOIN_WAITING;
1278 struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
1279 GNUNET_MQ_hd_var_size (cadet_message,
1280 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE,
1281 struct GNUNET_MULTICAST_MessageHeader,
1284 GNUNET_MQ_hd_var_size (cadet_join_decision,
1285 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION,
1286 struct MulticastJoinDecisionMessageHeader,
1289 GNUNET_MQ_hd_var_size (cadet_replay_request,
1290 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
1291 struct MulticastReplayRequestMessage,
1294 GNUNET_MQ_hd_var_size (cadet_replay_response,
1295 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE,
1296 struct MulticastReplayResponseMessage,
1299 GNUNET_MQ_handler_end ()
1302 chn->channel = GNUNET_CADET_channel_creatE (cadet, chn, &chn->peer,
1303 &grp->cadet_port_hash,
1304 GNUNET_CADET_OPTION_RELIABLE,
1305 cadet_notify_window_change,
1306 cadet_notify_disconnect,
1308 GNUNET_CONTAINER_multihashmap_put (channels_out, &chn->group_pub_hash, chn,
1309 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1315 * Destroy outgoing CADET channel.
1318 cadet_channel_destroy (struct Channel *chn)
1320 GNUNET_CADET_channel_destroy (chn->channel);
1321 GNUNET_CONTAINER_multihashmap_remove_all (channels_out, &chn->group_pub_hash);
1326 * Handle a connecting client starting an origin.
1329 handle_client_origin_start (void *cls,
1330 const struct MulticastOriginStartMessage *msg)
1332 struct Client *c = cls;
1333 struct GNUNET_SERVICE_Client *client = c->client;
1335 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
1336 struct GNUNET_HashCode pub_key_hash;
1338 GNUNET_CRYPTO_eddsa_key_get_public (&msg->group_key, &pub_key);
1339 GNUNET_CRYPTO_hash (&pub_key, sizeof (pub_key), &pub_key_hash);
1342 orig = GNUNET_CONTAINER_multihashmap_get (origins, &pub_key_hash);
1347 orig = GNUNET_new (struct Origin);
1348 orig->priv_key = msg->group_key;
1349 orig->max_fragment_id = GNUNET_ntohll (msg->max_fragment_id);
1351 grp = c->group = &orig->group;
1353 grp->is_origin = GNUNET_YES;
1354 grp->pub_key = pub_key;
1355 grp->pub_key_hash = pub_key_hash;
1357 GNUNET_CONTAINER_multihashmap_put (origins, &grp->pub_key_hash, orig,
1358 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1360 group_set_cadet_port_hash (grp);
1362 struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
1363 GNUNET_MQ_hd_var_size (cadet_message,
1364 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE,
1365 struct GNUNET_MULTICAST_MessageHeader,
1368 GNUNET_MQ_hd_var_size (cadet_request,
1369 GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST,
1370 struct GNUNET_MULTICAST_RequestHeader,
1373 GNUNET_MQ_hd_var_size (cadet_join_request,
1374 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST,
1375 struct MulticastJoinRequestMessage,
1378 GNUNET_MQ_hd_var_size (cadet_replay_request,
1379 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
1380 struct MulticastReplayRequestMessage,
1383 GNUNET_MQ_hd_var_size (cadet_replay_response,
1384 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE,
1385 struct MulticastReplayResponseMessage,
1388 GNUNET_MQ_handler_end ()
1392 orig->cadet_port = GNUNET_CADET_open_porT (cadet,
1393 &grp->cadet_port_hash,
1394 cadet_notify_connect,
1396 cadet_notify_window_change,
1397 cadet_notify_disconnect,
1405 struct ClientList *cl = GNUNET_new (struct ClientList);
1406 cl->client = client;
1407 GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl);
1409 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1410 "%p Client connected as origin to group %s.\n",
1411 orig, GNUNET_h2s (&grp->pub_key_hash));
1412 GNUNET_SERVICE_client_continue (client);
1417 check_client_member_join (void *cls,
1418 const struct MulticastMemberJoinMessage *msg)
1420 uint16_t msg_size = ntohs (msg->header.size);
1421 struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1];
1422 uint32_t relay_count = ntohl (msg->relay_count);
1423 uint16_t relay_size = relay_count * sizeof (*relays);
1424 struct GNUNET_MessageHeader *join_msg = NULL;
1425 uint16_t join_msg_size = 0;
1426 if (sizeof (*msg) + relay_size + sizeof (struct GNUNET_MessageHeader)
1429 join_msg = (struct GNUNET_MessageHeader *)
1430 (((char *) &msg[1]) + relay_size);
1431 join_msg_size = ntohs (join_msg->size);
1434 msg_size == (sizeof (*msg) + relay_size + join_msg_size)
1441 * Handle a connecting client joining a group.
1444 handle_client_member_join (void *cls,
1445 const struct MulticastMemberJoinMessage *msg)
1447 struct Client *c = cls;
1448 struct GNUNET_SERVICE_Client *client = c->client;
1450 uint16_t msg_size = ntohs (msg->header.size);
1452 struct GNUNET_CRYPTO_EcdsaPublicKey mem_pub_key;
1453 struct GNUNET_HashCode pub_key_hash, mem_pub_key_hash;
1455 GNUNET_CRYPTO_ecdsa_key_get_public (&msg->member_key, &mem_pub_key);
1456 GNUNET_CRYPTO_hash (&mem_pub_key, sizeof (mem_pub_key), &mem_pub_key_hash);
1457 GNUNET_CRYPTO_hash (&msg->group_pub_key, sizeof (msg->group_pub_key), &pub_key_hash);
1459 struct GNUNET_CONTAINER_MultiHashMap *
1460 grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members, &pub_key_hash);
1461 struct Member *mem = NULL;
1464 if (NULL != grp_mem)
1466 mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &mem_pub_key_hash);
1470 mem = GNUNET_new (struct Member);
1471 mem->origin = msg->origin;
1472 mem->priv_key = msg->member_key;
1473 mem->pub_key = mem_pub_key;
1474 mem->pub_key_hash = mem_pub_key_hash;
1475 mem->max_fragment_id = 0; // FIXME
1477 grp = c->group = &mem->group;
1479 grp->is_origin = GNUNET_NO;
1480 grp->pub_key = msg->group_pub_key;
1481 grp->pub_key_hash = pub_key_hash;
1482 group_set_cadet_port_hash (grp);
1484 if (NULL == grp_mem)
1486 grp_mem = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1487 GNUNET_CONTAINER_multihashmap_put (group_members, &grp->pub_key_hash, grp_mem,
1488 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1490 GNUNET_CONTAINER_multihashmap_put (grp_mem, &mem->pub_key_hash, mem,
1491 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1492 GNUNET_CONTAINER_multihashmap_put (members, &grp->pub_key_hash, mem,
1493 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1500 struct ClientList *cl = GNUNET_new (struct ClientList);
1501 cl->client = client;
1502 GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl);
1504 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1505 "%p Client connected to group %s..\n",
1506 mem, GNUNET_h2s (&grp->pub_key_hash));
1507 char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&mem->pub_key);
1508 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1509 "%p ..as member %s (%s).\n",
1510 mem, GNUNET_h2s (&mem->pub_key_hash), str);
1513 if (NULL != mem->join_dcsn)
1514 { /* Already got a join decision, send it to client. */
1515 struct GNUNET_MQ_Envelope *
1516 env = GNUNET_MQ_msg_copy (&mem->join_dcsn->header);
1518 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
1522 { /* First client of the group, send join request. */
1523 struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1];
1524 uint32_t relay_count = ntohl (msg->relay_count);
1525 uint16_t relay_size = relay_count * sizeof (*relays);
1526 struct GNUNET_MessageHeader *join_msg = NULL;
1527 uint16_t join_msg_size = 0;
1528 if (sizeof (*msg) + relay_size + sizeof (struct GNUNET_MessageHeader)
1531 join_msg = (struct GNUNET_MessageHeader *)
1532 (((char *) &msg[1]) + relay_size);
1533 join_msg_size = ntohs (join_msg->size);
1536 uint16_t req_msg_size = sizeof (struct MulticastJoinRequestMessage) + join_msg_size;
1537 struct MulticastJoinRequestMessage *
1538 req = GNUNET_malloc (req_msg_size);
1539 req->header.size = htons (req_msg_size);
1540 req->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST);
1541 req->group_pub_key = grp->pub_key;
1542 req->peer = this_peer;
1543 GNUNET_CRYPTO_ecdsa_key_get_public (&mem->priv_key, &req->member_pub_key);
1544 if (0 < join_msg_size)
1545 GNUNET_memcpy (&req[1], join_msg, join_msg_size);
1547 req->member_pub_key = mem->pub_key;
1548 req->purpose.size = htonl (req_msg_size
1549 - sizeof (req->header)
1550 - sizeof (req->reserved)
1551 - sizeof (req->signature));
1552 req->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
1554 if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (&mem->priv_key, &req->purpose,
1557 /* FIXME: handle error */
1561 if (NULL != mem->join_req)
1562 GNUNET_free (mem->join_req);
1563 mem->join_req = req;
1565 if (0 == client_send_origin (&grp->pub_key_hash, &mem->join_req->header))
1566 { /* No local origins, send to remote origin */
1567 cadet_send_join_request (mem);
1570 GNUNET_SERVICE_client_continue (client);
1575 client_send_join_decision (struct Member *mem,
1576 const struct MulticastJoinDecisionMessageHeader *hdcsn)
1578 client_send_group (&mem->group, &hdcsn->header);
1580 const struct MulticastJoinDecisionMessage *
1581 dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1];
1582 if (GNUNET_YES == ntohl (dcsn->is_admitted))
1583 { /* Member admitted, store join_decision. */
1584 uint16_t dcsn_size = ntohs (dcsn->header.size);
1585 mem->join_dcsn = GNUNET_malloc (dcsn_size);
1586 GNUNET_memcpy (mem->join_dcsn, dcsn, dcsn_size);
1589 { /* Refused entry, but replay would be still possible for past members. */
1595 check_client_join_decision (void *cls,
1596 const struct MulticastJoinDecisionMessageHeader *hdcsn)
1603 * Join decision from client.
1606 handle_client_join_decision (void *cls,
1607 const struct MulticastJoinDecisionMessageHeader *hdcsn)
1609 struct Client *c = cls;
1610 struct GNUNET_SERVICE_Client *client = c->client;
1611 struct Group *grp = c->group;
1616 GNUNET_SERVICE_client_drop (client);
1619 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1620 "%p Got join decision from client for group %s..\n",
1621 grp, GNUNET_h2s (&grp->pub_key_hash));
1623 struct GNUNET_CONTAINER_MultiHashMap *
1624 grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members,
1625 &grp->pub_key_hash);
1626 struct Member *mem = NULL;
1627 if (NULL != grp_mem)
1629 struct GNUNET_HashCode member_key_hash;
1630 GNUNET_CRYPTO_hash (&hdcsn->member_pub_key, sizeof (hdcsn->member_pub_key),
1632 mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &member_key_hash);
1633 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1634 "%p ..and member %s: %p\n",
1635 grp, GNUNET_h2s (&member_key_hash), mem);
1638 { /* Found local member */
1639 client_send_join_decision (mem, hdcsn);
1642 { /* Look for remote member */
1643 cadet_send_join_decision (grp, hdcsn);
1645 GNUNET_SERVICE_client_continue (client);
1650 check_client_multicast_message (void *cls,
1651 const struct GNUNET_MULTICAST_MessageHeader *msg)
1658 * Incoming message from a client.
1661 handle_client_multicast_message (void *cls,
1662 const struct GNUNET_MULTICAST_MessageHeader *msg)
1664 struct Client *c = cls;
1665 struct GNUNET_SERVICE_Client *client = c->client;
1666 struct Group *grp = c->group;
1671 GNUNET_SERVICE_client_drop (client);
1674 GNUNET_assert (GNUNET_YES == grp->is_origin);
1675 struct Origin *orig = grp->origin;
1677 /* FIXME: yucky, should use separate message structs for P2P and CS! */
1678 struct GNUNET_MULTICAST_MessageHeader *
1679 out = (struct GNUNET_MULTICAST_MessageHeader *) GNUNET_copy_message (&msg->header);
1680 out->fragment_id = GNUNET_htonll (++orig->max_fragment_id);
1681 out->purpose.size = htonl (ntohs (out->header.size)
1682 - sizeof (out->header)
1683 - sizeof (out->hop_counter)
1684 - sizeof (out->signature));
1685 out->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE);
1687 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_sign (&orig->priv_key, &out->purpose,
1693 client_send_all (&grp->pub_key_hash, &out->header);
1694 cadet_send_children (&grp->pub_key_hash, &out->header);
1695 client_send_ack (&grp->pub_key_hash);
1698 GNUNET_SERVICE_client_continue (client);
1703 check_client_multicast_request (void *cls,
1704 const struct GNUNET_MULTICAST_RequestHeader *req)
1711 * Incoming request from a client.
1714 handle_client_multicast_request (void *cls,
1715 const struct GNUNET_MULTICAST_RequestHeader *req)
1717 struct Client *c = cls;
1718 struct GNUNET_SERVICE_Client *client = c->client;
1719 struct Group *grp = c->group;
1724 GNUNET_SERVICE_client_drop (client);
1727 GNUNET_assert (GNUNET_NO == grp->is_origin);
1728 struct Member *mem = grp->member;
1730 /* FIXME: yucky, should use separate message structs for P2P and CS! */
1731 struct GNUNET_MULTICAST_RequestHeader *
1732 out = (struct GNUNET_MULTICAST_RequestHeader *) GNUNET_copy_message (&req->header);
1733 out->member_pub_key = mem->pub_key;
1734 out->fragment_id = GNUNET_ntohll (++mem->max_fragment_id);
1735 out->purpose.size = htonl (ntohs (out->header.size)
1736 - sizeof (out->header)
1737 - sizeof (out->member_pub_key)
1738 - sizeof (out->signature));
1739 out->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
1741 if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (&mem->priv_key, &out->purpose,
1747 uint8_t send_ack = GNUNET_YES;
1748 if (0 == client_send_origin (&grp->pub_key_hash, &out->header))
1749 { /* No local origins, send to remote origin */
1750 if (NULL != mem->origin_channel)
1752 cadet_send_channel (mem->origin_channel, &out->header);
1753 send_ack = GNUNET_NO;
1757 /* FIXME: not yet connected to origin */
1758 GNUNET_SERVICE_client_drop (client);
1763 if (GNUNET_YES == send_ack)
1765 client_send_ack (&grp->pub_key_hash);
1768 GNUNET_SERVICE_client_continue (client);
1773 * Incoming replay request from a client.
1776 handle_client_replay_request (void *cls,
1777 const struct MulticastReplayRequestMessage *rep)
1779 struct Client *c = cls;
1780 struct GNUNET_SERVICE_Client *client = c->client;
1781 struct Group *grp = c->group;
1786 GNUNET_SERVICE_client_drop (client);
1789 GNUNET_assert (GNUNET_NO == grp->is_origin);
1790 struct Member *mem = grp->member;
1792 struct GNUNET_CONTAINER_MultiHashMap *
1793 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
1794 &grp->pub_key_hash);
1795 if (NULL == grp_replay_req)
1797 grp_replay_req = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1798 GNUNET_CONTAINER_multihashmap_put (replay_req_client,
1799 &grp->pub_key_hash, grp_replay_req,
1800 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1803 struct GNUNET_HashCode key_hash;
1804 replay_key_hash (rep->fragment_id, rep->message_id, rep->fragment_offset,
1805 rep->flags, &key_hash);
1806 GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, client,
1807 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1809 if (0 == client_send_origin (&grp->pub_key_hash, &rep->header))
1810 { /* No local origin, replay from remote members / origin. */
1811 if (NULL != mem->origin_channel)
1813 cadet_send_channel (mem->origin_channel, &rep->header);
1817 /* FIXME: not yet connected to origin */
1818 GNUNET_SERVICE_client_drop (client);
1822 GNUNET_SERVICE_client_continue (client);
1827 cadet_send_replay_response_cb (void *cls,
1828 const struct GNUNET_HashCode *key_hash,
1831 struct Channel *chn = value;
1832 struct GNUNET_MessageHeader *msg = cls;
1834 cadet_send_channel (chn, msg);
1840 client_send_replay_response_cb (void *cls,
1841 const struct GNUNET_HashCode *key_hash,
1844 struct GNUNET_SERVICE_Client *client = value;
1845 struct GNUNET_MessageHeader *msg = cls;
1847 client_send (client, msg);
1853 check_client_replay_response_end (void *cls,
1854 const struct MulticastReplayResponseMessage *res)
1861 * End of replay response from a client.
1864 handle_client_replay_response_end (void *cls,
1865 const struct MulticastReplayResponseMessage *res)
1867 struct Client *c = cls;
1868 struct GNUNET_SERVICE_Client *client = c->client;
1869 struct Group *grp = c->group;
1874 GNUNET_SERVICE_client_drop (client);
1878 struct GNUNET_HashCode key_hash;
1879 replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset,
1880 res->flags, &key_hash);
1882 struct GNUNET_CONTAINER_MultiHashMap *
1883 grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
1884 &grp->pub_key_hash);
1885 if (NULL != grp_replay_req_cadet)
1887 GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_cadet, &key_hash);
1889 struct GNUNET_CONTAINER_MultiHashMap *
1890 grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
1891 &grp->pub_key_hash);
1892 if (NULL != grp_replay_req_client)
1894 GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_client, &key_hash);
1896 GNUNET_SERVICE_client_continue (client);
1901 check_client_replay_response (void *cls,
1902 const struct MulticastReplayResponseMessage *res)
1904 const struct GNUNET_MessageHeader *msg = &res->header;
1905 if (GNUNET_MULTICAST_REC_OK == res->error_code)
1907 msg = GNUNET_MQ_extract_nested_mh (res);
1910 return GNUNET_SYSERR;
1918 * Incoming replay response from a client.
1920 * Respond with a multicast message on success, or otherwise with an error code.
1923 handle_client_replay_response (void *cls,
1924 const struct MulticastReplayResponseMessage *res)
1926 struct Client *c = cls;
1927 struct GNUNET_SERVICE_Client *client = c->client;
1928 struct Group *grp = c->group;
1933 GNUNET_SERVICE_client_drop (client);
1937 const struct GNUNET_MessageHeader *msg = &res->header;
1938 if (GNUNET_MULTICAST_REC_OK == res->error_code)
1940 msg = GNUNET_MQ_extract_nested_mh (res);
1943 struct GNUNET_HashCode key_hash;
1944 replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset,
1945 res->flags, &key_hash);
1947 struct GNUNET_CONTAINER_MultiHashMap *
1948 grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
1949 &grp->pub_key_hash);
1950 if (NULL != grp_replay_req_cadet)
1952 GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_cadet, &key_hash,
1953 cadet_send_replay_response_cb,
1956 if (GNUNET_MULTICAST_REC_OK == res->error_code)
1958 struct GNUNET_CONTAINER_MultiHashMap *
1959 grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
1960 &grp->pub_key_hash);
1961 if (NULL != grp_replay_req_client)
1963 GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_client, &key_hash,
1964 client_send_replay_response_cb,
1970 handle_client_replay_response_end (c, res);
1973 GNUNET_SERVICE_client_continue (client);
1978 * A new client connected.
1981 * @param client client to add
1982 * @param mq message queue for @a client
1986 client_notify_connect (void *cls,
1987 struct GNUNET_SERVICE_Client *client,
1988 struct GNUNET_MQ_Handle *mq)
1990 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client connected: %p\n", client);
1991 /* FIXME: send connect ACK */
1993 struct Client *c = GNUNET_new (struct Client);
2001 * Called whenever a client is disconnected.
2002 * Frees our resources associated with that client.
2004 * @param cls closure
2005 * @param client identification of the client
2006 * @param app_ctx must match @a client
2009 client_notify_disconnect (void *cls,
2010 struct GNUNET_SERVICE_Client *client,
2013 struct Client *c = app_ctx;
2014 struct Group *grp = c->group;
2019 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2020 "%p User context is NULL in client_disconnect()\n", grp);
2025 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2026 "%p Client (%s) disconnected from group %s\n",
2027 grp, (GNUNET_YES == grp->is_origin) ? "origin" : "member",
2028 GNUNET_h2s (&grp->pub_key_hash));
2030 struct ClientList *cl = grp->clients_head;
2033 if (cl->client == client)
2035 GNUNET_CONTAINER_DLL_remove (grp->clients_head, grp->clients_tail, cl);
2042 while (GNUNET_YES == replay_req_remove_client (grp, client));
2044 if (NULL == grp->clients_head)
2045 { /* Last client disconnected. */
2047 if (NULL != grp->tmit_head)
2048 { /* Send pending messages via CADET before cleanup. */
2049 transmit_message (grp);
2054 cleanup_group (grp);
2063 * @param cls closure
2064 * @param server the initialized server
2065 * @param cfg configuration to use
2069 const struct GNUNET_CONFIGURATION_Handle *c,
2070 struct GNUNET_SERVICE_Handle *svc)
2074 GNUNET_CRYPTO_get_peer_identity (cfg, &this_peer);
2076 stats = GNUNET_STATISTICS_create ("multicast", cfg);
2077 origins = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
2078 members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
2079 group_members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
2080 channels_in = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
2081 channels_out = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
2082 replay_req_cadet = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
2083 replay_req_client = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
2085 cadet = GNUNET_CADET_connecT (cfg);
2087 GNUNET_assert (NULL != cadet);
2089 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
2095 * Define "main" method using service macro.
2099 GNUNET_SERVICE_OPTION_NONE,
2101 client_notify_connect,
2102 client_notify_disconnect,
2104 GNUNET_MQ_hd_fixed_size (client_origin_start,
2105 GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START,
2106 struct MulticastOriginStartMessage,
2108 GNUNET_MQ_hd_var_size (client_member_join,
2109 GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_JOIN,
2110 struct MulticastMemberJoinMessage,
2112 GNUNET_MQ_hd_var_size (client_join_decision,
2113 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION,
2114 struct MulticastJoinDecisionMessageHeader,
2116 GNUNET_MQ_hd_var_size (client_multicast_message,
2117 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE,
2118 struct GNUNET_MULTICAST_MessageHeader,
2120 GNUNET_MQ_hd_var_size (client_multicast_request,
2121 GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST,
2122 struct GNUNET_MULTICAST_RequestHeader,
2124 GNUNET_MQ_hd_fixed_size (client_replay_request,
2125 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
2126 struct MulticastReplayRequestMessage,
2128 GNUNET_MQ_hd_var_size (client_replay_response,
2129 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE,
2130 struct MulticastReplayResponseMessage,
2132 GNUNET_MQ_hd_var_size (client_replay_response_end,
2133 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE_END,
2134 struct MulticastReplayResponseMessage,
2137 /* end of gnunet-service-multicast.c */