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 if (NULL == chn || NULL == chn->group)
468 return GNUNET_SYSERR;
470 struct GNUNET_CONTAINER_MultiHashMap *
471 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
472 &chn->group->pub_key_hash);
473 if (NULL == grp_replay_req)
476 struct GNUNET_CONTAINER_MultiHashMapIterator *
477 it = GNUNET_CONTAINER_multihashmap_iterator_create (grp_replay_req);
478 struct GNUNET_HashCode key;
479 const struct Channel *c;
481 == GNUNET_CONTAINER_multihashmap_iterator_next (it, &key,
486 GNUNET_CONTAINER_multihashmap_remove (grp_replay_req, &key, chn);
487 GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
491 GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
497 * Remove client from replay request hashmap.
502 * @return #GNUNET_YES if there are more entries to process,
503 * #GNUNET_NO when reached end of hashmap.
506 replay_req_remove_client (struct Group *grp, struct GNUNET_SERVICE_Client *client)
508 struct GNUNET_CONTAINER_MultiHashMap *
509 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
511 if (NULL == grp_replay_req)
514 struct GNUNET_CONTAINER_MultiHashMapIterator *
515 it = GNUNET_CONTAINER_multihashmap_iterator_create (grp_replay_req);
516 struct GNUNET_HashCode key;
517 const struct GNUNET_SERVICE_Client *c;
519 == GNUNET_CONTAINER_multihashmap_iterator_next (it, &key,
524 GNUNET_CONTAINER_multihashmap_remove (grp_replay_req, &key, client);
525 GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
529 GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
535 * Send message to a client.
538 client_send (struct GNUNET_SERVICE_Client *client,
539 const struct GNUNET_MessageHeader *msg)
541 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
542 "%p Sending message to client.\n", client);
544 struct GNUNET_MQ_Envelope *
545 env = GNUNET_MQ_msg_copy (msg);
547 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
553 * Send message to all clients connected to the group.
556 client_send_group (const struct Group *grp,
557 const struct GNUNET_MessageHeader *msg)
559 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
560 "%p Sending message to all clients of the group.\n", grp);
562 struct ClientList *cl = grp->clients_head;
565 struct GNUNET_MQ_Envelope *
566 env = GNUNET_MQ_msg_copy (msg);
568 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (cl->client),
576 * Iterator callback for sending a message to origin clients.
579 client_send_origin_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
582 const struct GNUNET_MessageHeader *msg = cls;
583 struct Member *orig = origin;
585 client_send_group (&orig->group, msg);
591 * Iterator callback for sending a message to member clients.
594 client_send_member_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
597 const struct GNUNET_MessageHeader *msg = cls;
598 struct Member *mem = member;
600 if (NULL != mem->join_dcsn)
601 { /* Only send message to admitted members */
602 client_send_group (&mem->group, msg);
609 * Send message to all origin and member clients connected to the group.
611 * @param pub_key_hash
612 * H(key_pub) of the group.
617 client_send_all (struct GNUNET_HashCode *pub_key_hash,
618 const struct GNUNET_MessageHeader *msg)
621 n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash,
622 client_send_origin_cb,
624 n += GNUNET_CONTAINER_multihashmap_get_multiple (members, pub_key_hash,
625 client_send_member_cb,
632 * Send message to a random origin client or a random member client.
634 * @param grp The group to send @a msg to.
635 * @param msg Message to send.
638 client_send_random (struct GNUNET_HashCode *pub_key_hash,
639 const struct GNUNET_MessageHeader *msg)
642 n = GNUNET_CONTAINER_multihashmap_get_random (origins, client_send_origin_cb,
645 n = GNUNET_CONTAINER_multihashmap_get_random (members, client_send_member_cb,
652 * Send message to all origin clients connected to the group.
654 * @param pub_key_hash
655 * H(key_pub) of the group.
660 client_send_origin (struct GNUNET_HashCode *pub_key_hash,
661 const struct GNUNET_MessageHeader *msg)
664 n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash,
665 client_send_origin_cb,
672 * Send fragment acknowledgement to all clients of the channel.
674 * @param pub_key_hash
675 * H(key_pub) of the group.
678 client_send_ack (struct GNUNET_HashCode *pub_key_hash)
680 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
681 "Sending message ACK to client.\n");
683 static struct GNUNET_MessageHeader *msg = NULL;
686 msg = GNUNET_malloc (sizeof (*msg));
687 msg->type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_FRAGMENT_ACK);
688 msg->size = htons (sizeof (*msg));
690 client_send_all (pub_key_hash, msg);
694 struct CadetTransmitClosure
697 const struct GNUNET_MessageHeader *msg;
702 * Send a message to a CADET channel.
704 * @param chn Channel.
705 * @param msg Message.
708 cadet_send_channel (struct Channel *chn, const struct GNUNET_MessageHeader *msg)
710 struct GNUNET_MQ_Envelope *
711 env = GNUNET_MQ_msg_copy (msg);
713 GNUNET_MQ_send (GNUNET_CADET_get_mq (chn->channel), env);
715 if (0 < chn->window_size)
717 client_send_ack (&chn->group_pub_hash);
722 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
723 "%p Queuing message. Pending messages: %u\n",
724 chn, chn->msgs_pending);
730 * Create CADET channel and send a join request.
733 cadet_send_join_request (struct Member *mem)
735 mem->origin_channel = cadet_channel_create (&mem->group, &mem->origin);
736 cadet_send_channel (mem->origin_channel, &mem->join_req->header);
739 for (i = 0; i < mem->relay_count; i++)
742 chn = cadet_channel_create (&mem->group, &mem->relays[i]);
743 cadet_send_channel (chn, &mem->join_req->header);
749 cadet_send_join_decision_cb (void *cls,
750 const struct GNUNET_HashCode *group_pub_hash,
753 const struct MulticastJoinDecisionMessageHeader *hdcsn = cls;
754 struct Channel *chn = channel;
756 const struct MulticastJoinDecisionMessage *dcsn =
757 (struct MulticastJoinDecisionMessage *) &hdcsn[1];
759 if (0 == memcmp (&hdcsn->member_pub_key, &chn->member_pub_key, sizeof (chn->member_pub_key))
760 && 0 == memcmp (&hdcsn->peer, &chn->peer, sizeof (chn->peer)))
762 if (GNUNET_YES == ntohl (dcsn->is_admitted))
764 chn->join_status = JOIN_ADMITTED;
768 chn->join_status = JOIN_REFUSED;
770 cadet_send_channel (chn, &hdcsn->header);
774 // return GNUNET_YES to continue the multihashmap_get iteration
780 * Send join decision to a remote peer.
783 cadet_send_join_decision (struct Group *grp,
784 const struct MulticastJoinDecisionMessageHeader *hdcsn)
786 GNUNET_CONTAINER_multihashmap_get_multiple (channels_in, &grp->pub_key_hash,
787 &cadet_send_join_decision_cb,
793 * Iterator callback for sending a message to origin clients.
796 cadet_send_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
799 const struct GNUNET_MessageHeader *msg = cls;
800 struct Channel *chn = channel;
801 if (JOIN_ADMITTED == chn->join_status)
802 cadet_send_channel (chn, msg);
808 * Send message to all connected children.
811 cadet_send_children (struct GNUNET_HashCode *pub_key_hash,
812 const struct GNUNET_MessageHeader *msg)
815 if (channels_in != NULL)
816 n += GNUNET_CONTAINER_multihashmap_get_multiple (channels_in, pub_key_hash,
817 cadet_send_cb, (void *) msg);
822 #if 0 // unused as yet
824 * Send message to all connected parents.
827 cadet_send_parents (struct GNUNET_HashCode *pub_key_hash,
828 const struct GNUNET_MessageHeader *msg)
831 if (channels_in != NULL)
832 n += GNUNET_CONTAINER_multihashmap_get_multiple (channels_out, pub_key_hash,
833 cadet_send_cb, (void *) msg);
840 * CADET channel connect handler.
842 * @see GNUNET_CADET_ConnectEventHandler()
845 cadet_notify_connect (void *cls,
846 struct GNUNET_CADET_Channel *channel,
847 const struct GNUNET_PeerIdentity *source)
849 struct Channel *chn = GNUNET_malloc (sizeof (struct Channel));
851 chn->channel = channel;
852 chn->direction = DIR_INCOMING;
853 chn->join_status = JOIN_NOT_ASKED;
855 GNUNET_CONTAINER_multihashmap_put (channels_in, &chn->group->pub_key_hash, chn,
856 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
862 * CADET window size change handler.
864 * @see GNUNET_CADET_WindowSizeEventHandler()
867 cadet_notify_window_change (void *cls,
868 const struct GNUNET_CADET_Channel *channel,
871 struct Channel *chn = cls;
873 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
874 "%p Window size changed to %d. Pending messages: %u\n",
875 chn, window_size, chn->msgs_pending);
877 chn->is_connected = GNUNET_YES;
878 chn->window_size = (int32_t) window_size;
880 for (int i = 0; i < window_size; i++)
882 if (0 < chn->msgs_pending)
884 client_send_ack (&chn->group_pub_hash);
896 * CADET channel disconnect handler.
898 * @see GNUNET_CADET_DisconnectEventHandler()
901 cadet_notify_disconnect (void *cls,
902 const struct GNUNET_CADET_Channel *channel)
907 struct Channel *chn = cls;
908 if (NULL != chn->group)
910 if (GNUNET_NO == chn->group->is_origin)
912 struct Member *mem = (struct Member *) chn->group;
913 if (chn == mem->origin_channel)
914 mem->origin_channel = NULL;
921 ret = replay_req_remove_cadet (chn);
923 while (GNUNET_YES == ret);
930 check_cadet_join_request (void *cls,
931 const struct MulticastJoinRequestMessage *req)
933 struct Channel *chn = cls;
936 || JOIN_NOT_ASKED != chn->join_status)
938 return GNUNET_SYSERR;
941 uint16_t size = ntohs (req->header.size);
942 if (size < sizeof (*req))
945 return GNUNET_SYSERR;
947 if (ntohl (req->purpose.size) != (size
948 - sizeof (req->header)
949 - sizeof (req->reserved)
950 - sizeof (req->signature)))
953 return GNUNET_SYSERR;
956 GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST,
957 &req->purpose, &req->signature,
958 &req->member_pub_key))
961 return GNUNET_SYSERR;
969 * Incoming join request message from CADET.
972 handle_cadet_join_request (void *cls,
973 const struct MulticastJoinRequestMessage *req)
975 struct Channel *chn = cls;
976 GNUNET_CADET_receive_done (chn->channel);
978 struct GNUNET_HashCode group_pub_hash;
979 GNUNET_CRYPTO_hash (&req->group_pub_key, sizeof (req->group_pub_key), &group_pub_hash);
980 chn->group_pub_key = req->group_pub_key;
981 chn->group_pub_hash = group_pub_hash;
982 chn->member_pub_key = req->member_pub_key;
983 chn->peer = req->peer;
984 chn->join_status = JOIN_WAITING;
986 client_send_all (&group_pub_hash, &req->header);
991 check_cadet_join_decision (void *cls,
992 const struct MulticastJoinDecisionMessageHeader *hdcsn)
994 uint16_t size = ntohs (hdcsn->header.size);
995 if (size < sizeof (struct MulticastJoinDecisionMessageHeader) +
996 sizeof (struct MulticastJoinDecisionMessage))
999 return GNUNET_SYSERR;
1002 struct Channel *chn = cls;
1006 return GNUNET_SYSERR;
1008 if (NULL == chn->group || GNUNET_NO != chn->group->is_origin)
1011 return GNUNET_SYSERR;
1013 switch (chn->join_status)
1016 return GNUNET_SYSERR;
1021 case JOIN_NOT_ASKED:
1031 * Incoming join decision message from CADET.
1034 handle_cadet_join_decision (void *cls,
1035 const struct MulticastJoinDecisionMessageHeader *hdcsn)
1037 const struct MulticastJoinDecisionMessage *
1038 dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1];
1040 struct Channel *chn = cls;
1041 GNUNET_CADET_receive_done (chn->channel);
1043 // FIXME: do we need to copy chn->peer or compare it with hdcsn->peer?
1044 struct Member *mem = (struct Member *) chn->group;
1045 client_send_join_decision (mem, hdcsn);
1046 if (GNUNET_YES == ntohl (dcsn->is_admitted))
1048 chn->join_status = JOIN_ADMITTED;
1052 chn->join_status = JOIN_REFUSED;
1053 cadet_channel_destroy (chn);
1059 check_cadet_message (void *cls,
1060 const struct GNUNET_MULTICAST_MessageHeader *msg)
1062 uint16_t size = ntohs (msg->header.size);
1063 if (size < sizeof (*msg))
1065 GNUNET_break_op (0);
1066 return GNUNET_SYSERR;
1069 struct Channel *chn = cls;
1073 return GNUNET_SYSERR;
1075 if (ntohl (msg->purpose.size) != (size
1076 - sizeof (msg->header)
1077 - sizeof (msg->hop_counter)
1078 - sizeof (msg->signature)))
1080 GNUNET_break_op (0);
1081 return GNUNET_SYSERR;
1084 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE,
1085 &msg->purpose, &msg->signature,
1086 &chn->group_pub_key))
1088 GNUNET_break_op (0);
1089 return GNUNET_SYSERR;
1097 * Incoming multicast message from CADET.
1100 handle_cadet_message (void *cls,
1101 const struct GNUNET_MULTICAST_MessageHeader *msg)
1103 struct Channel *chn = cls;
1104 GNUNET_CADET_receive_done (chn->channel);
1105 client_send_all (&chn->group_pub_hash, &msg->header);
1110 check_cadet_request (void *cls,
1111 const struct GNUNET_MULTICAST_RequestHeader *req)
1113 uint16_t size = ntohs (req->header.size);
1114 if (size < sizeof (*req))
1116 GNUNET_break_op (0);
1117 return GNUNET_SYSERR;
1120 struct Channel *chn = cls;
1124 return GNUNET_SYSERR;
1126 if (ntohl (req->purpose.size) != (size
1127 - sizeof (req->header)
1128 - sizeof (req->member_pub_key)
1129 - sizeof (req->signature)))
1131 GNUNET_break_op (0);
1132 return GNUNET_SYSERR;
1135 GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST,
1136 &req->purpose, &req->signature,
1137 &req->member_pub_key))
1139 GNUNET_break_op (0);
1140 return GNUNET_SYSERR;
1148 * Incoming multicast request message from CADET.
1151 handle_cadet_request (void *cls,
1152 const struct GNUNET_MULTICAST_RequestHeader *req)
1154 struct Channel *chn = cls;
1155 GNUNET_CADET_receive_done (chn->channel);
1156 client_send_origin (&chn->group_pub_hash, &req->header);
1161 check_cadet_replay_request (void *cls,
1162 const struct MulticastReplayRequestMessage *req)
1164 uint16_t size = ntohs (req->header.size);
1165 if (size < sizeof (*req))
1167 GNUNET_break_op (0);
1168 return GNUNET_SYSERR;
1171 struct Channel *chn = cls;
1174 GNUNET_break_op (0);
1175 return GNUNET_SYSERR;
1183 * Incoming multicast replay request from CADET.
1186 handle_cadet_replay_request (void *cls,
1187 const struct MulticastReplayRequestMessage *req)
1189 struct Channel *chn = cls;
1190 GNUNET_CADET_receive_done (chn->channel);
1192 struct MulticastReplayRequestMessage rep = *req;
1193 GNUNET_memcpy (&rep.member_pub_key, &chn->member_pub_key, sizeof (chn->member_pub_key));
1195 struct GNUNET_CONTAINER_MultiHashMap *
1196 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
1197 &chn->group->pub_key_hash);
1198 if (NULL == grp_replay_req)
1200 grp_replay_req = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1201 GNUNET_CONTAINER_multihashmap_put (replay_req_cadet,
1202 &chn->group->pub_key_hash, grp_replay_req,
1203 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1205 struct GNUNET_HashCode key_hash;
1206 replay_key_hash (rep.fragment_id, rep.message_id, rep.fragment_offset,
1207 rep.flags, &key_hash);
1208 GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, chn,
1209 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1211 client_send_random (&chn->group_pub_hash, &rep.header);
1216 check_cadet_replay_response (void *cls,
1217 const struct MulticastReplayResponseMessage *res)
1219 struct Channel *chn = cls;
1223 return GNUNET_SYSERR;
1230 * Incoming multicast replay response from CADET.
1233 handle_cadet_replay_response (void *cls,
1234 const struct MulticastReplayResponseMessage *res)
1236 struct Channel *chn = cls;
1237 GNUNET_CADET_receive_done (chn->channel);
1239 /* @todo FIXME: got replay error response, send request to other members */
1244 group_set_cadet_port_hash (struct Group *grp)
1247 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
1251 GNUNET_APPLICATION_TYPE_MULTICAST,
1253 GNUNET_CRYPTO_hash (&port, sizeof (port), &grp->cadet_port_hash);
1259 * Create new outgoing CADET channel.
1262 * Peer to connect to.
1263 * @param group_pub_key
1264 * Public key of group the channel belongs to.
1265 * @param group_pub_hash
1266 * Hash of @a group_pub_key.
1270 static struct Channel *
1271 cadet_channel_create (struct Group *grp, struct GNUNET_PeerIdentity *peer)
1273 struct Channel *chn = GNUNET_malloc (sizeof (*chn));
1275 chn->group_pub_key = grp->pub_key;
1276 chn->group_pub_hash = grp->pub_key_hash;
1278 chn->direction = DIR_OUTGOING;
1279 chn->is_connected = GNUNET_NO;
1280 chn->join_status = JOIN_WAITING;
1282 struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
1283 GNUNET_MQ_hd_var_size (cadet_message,
1284 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE,
1285 struct GNUNET_MULTICAST_MessageHeader,
1288 GNUNET_MQ_hd_var_size (cadet_join_decision,
1289 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION,
1290 struct MulticastJoinDecisionMessageHeader,
1293 GNUNET_MQ_hd_var_size (cadet_replay_request,
1294 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
1295 struct MulticastReplayRequestMessage,
1298 GNUNET_MQ_hd_var_size (cadet_replay_response,
1299 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE,
1300 struct MulticastReplayResponseMessage,
1303 GNUNET_MQ_handler_end ()
1306 chn->channel = GNUNET_CADET_channel_create (cadet, chn, &chn->peer,
1307 &grp->cadet_port_hash,
1308 GNUNET_CADET_OPTION_RELIABLE,
1309 cadet_notify_window_change,
1310 cadet_notify_disconnect,
1312 GNUNET_CONTAINER_multihashmap_put (channels_out, &chn->group_pub_hash, chn,
1313 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1319 * Destroy outgoing CADET channel.
1322 cadet_channel_destroy (struct Channel *chn)
1324 GNUNET_CADET_channel_destroy (chn->channel);
1325 GNUNET_CONTAINER_multihashmap_remove_all (channels_out, &chn->group_pub_hash);
1330 * Handle a connecting client starting an origin.
1333 handle_client_origin_start (void *cls,
1334 const struct MulticastOriginStartMessage *msg)
1336 struct Client *c = cls;
1337 struct GNUNET_SERVICE_Client *client = c->client;
1339 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
1340 struct GNUNET_HashCode pub_key_hash;
1342 GNUNET_CRYPTO_eddsa_key_get_public (&msg->group_key, &pub_key);
1343 GNUNET_CRYPTO_hash (&pub_key, sizeof (pub_key), &pub_key_hash);
1346 orig = GNUNET_CONTAINER_multihashmap_get (origins, &pub_key_hash);
1351 orig = GNUNET_new (struct Origin);
1352 orig->priv_key = msg->group_key;
1353 orig->max_fragment_id = GNUNET_ntohll (msg->max_fragment_id);
1355 grp = c->group = &orig->group;
1357 grp->is_origin = GNUNET_YES;
1358 grp->pub_key = pub_key;
1359 grp->pub_key_hash = pub_key_hash;
1361 GNUNET_CONTAINER_multihashmap_put (origins, &grp->pub_key_hash, orig,
1362 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1364 group_set_cadet_port_hash (grp);
1366 struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
1367 GNUNET_MQ_hd_var_size (cadet_message,
1368 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE,
1369 struct GNUNET_MULTICAST_MessageHeader,
1372 GNUNET_MQ_hd_var_size (cadet_request,
1373 GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST,
1374 struct GNUNET_MULTICAST_RequestHeader,
1377 GNUNET_MQ_hd_var_size (cadet_join_request,
1378 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST,
1379 struct MulticastJoinRequestMessage,
1382 GNUNET_MQ_hd_var_size (cadet_replay_request,
1383 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
1384 struct MulticastReplayRequestMessage,
1387 GNUNET_MQ_hd_var_size (cadet_replay_response,
1388 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE,
1389 struct MulticastReplayResponseMessage,
1392 GNUNET_MQ_handler_end ()
1396 orig->cadet_port = GNUNET_CADET_open_port (cadet,
1397 &grp->cadet_port_hash,
1398 cadet_notify_connect,
1400 cadet_notify_window_change,
1401 cadet_notify_disconnect,
1409 struct ClientList *cl = GNUNET_new (struct ClientList);
1410 cl->client = client;
1411 GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl);
1413 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1414 "%p Client connected as origin to group %s.\n",
1415 orig, GNUNET_h2s (&grp->pub_key_hash));
1416 GNUNET_SERVICE_client_continue (client);
1421 check_client_member_join (void *cls,
1422 const struct MulticastMemberJoinMessage *msg)
1424 uint16_t msg_size = ntohs (msg->header.size);
1425 struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1];
1426 uint32_t relay_count = ntohl (msg->relay_count);
1427 uint16_t relay_size = relay_count * sizeof (*relays);
1428 struct GNUNET_MessageHeader *join_msg = NULL;
1429 uint16_t join_msg_size = 0;
1430 if (sizeof (*msg) + relay_size + sizeof (struct GNUNET_MessageHeader)
1433 join_msg = (struct GNUNET_MessageHeader *)
1434 (((char *) &msg[1]) + relay_size);
1435 join_msg_size = ntohs (join_msg->size);
1438 msg_size == (sizeof (*msg) + relay_size + join_msg_size)
1445 * Handle a connecting client joining a group.
1448 handle_client_member_join (void *cls,
1449 const struct MulticastMemberJoinMessage *msg)
1451 struct Client *c = cls;
1452 struct GNUNET_SERVICE_Client *client = c->client;
1454 uint16_t msg_size = ntohs (msg->header.size);
1456 struct GNUNET_CRYPTO_EcdsaPublicKey mem_pub_key;
1457 struct GNUNET_HashCode pub_key_hash, mem_pub_key_hash;
1459 GNUNET_CRYPTO_ecdsa_key_get_public (&msg->member_key, &mem_pub_key);
1460 GNUNET_CRYPTO_hash (&mem_pub_key, sizeof (mem_pub_key), &mem_pub_key_hash);
1461 GNUNET_CRYPTO_hash (&msg->group_pub_key, sizeof (msg->group_pub_key), &pub_key_hash);
1463 struct GNUNET_CONTAINER_MultiHashMap *
1464 grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members, &pub_key_hash);
1465 struct Member *mem = NULL;
1468 if (NULL != grp_mem)
1470 mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &mem_pub_key_hash);
1475 mem = GNUNET_new (struct Member);
1476 mem->origin = msg->origin;
1477 mem->priv_key = msg->member_key;
1478 mem->pub_key = mem_pub_key;
1479 mem->pub_key_hash = mem_pub_key_hash;
1480 mem->max_fragment_id = 0; // FIXME
1482 grp = c->group = &mem->group;
1484 grp->is_origin = GNUNET_NO;
1485 grp->pub_key = msg->group_pub_key;
1486 grp->pub_key_hash = pub_key_hash;
1487 group_set_cadet_port_hash (grp);
1489 if (NULL == grp_mem)
1491 grp_mem = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1492 GNUNET_CONTAINER_multihashmap_put (group_members, &grp->pub_key_hash, grp_mem,
1493 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1495 GNUNET_CONTAINER_multihashmap_put (grp_mem, &mem->pub_key_hash, mem,
1496 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1498 GNUNET_CONTAINER_multihashmap_put (members, &grp->pub_key_hash, mem,
1499 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1506 struct ClientList *cl = GNUNET_new (struct ClientList);
1507 cl->client = client;
1508 GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl);
1510 char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&mem->pub_key);
1511 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1512 "Client connected to group %s as member %s (%s).\n",
1513 GNUNET_h2s (&grp->pub_key_hash),
1514 GNUNET_h2s2 (&mem->pub_key_hash),
1518 if (NULL != mem->join_dcsn)
1519 { /* Already got a join decision, send it to client. */
1520 struct GNUNET_MQ_Envelope *
1521 env = GNUNET_MQ_msg_copy (&mem->join_dcsn->header);
1523 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
1527 { /* First client of the group, send join request. */
1528 struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1];
1529 uint32_t relay_count = ntohl (msg->relay_count);
1530 uint16_t relay_size = relay_count * sizeof (*relays);
1531 struct GNUNET_MessageHeader *join_msg = NULL;
1532 uint16_t join_msg_size = 0;
1533 if (sizeof (*msg) + relay_size + sizeof (struct GNUNET_MessageHeader)
1536 join_msg = (struct GNUNET_MessageHeader *)
1537 (((char *) &msg[1]) + relay_size);
1538 join_msg_size = ntohs (join_msg->size);
1541 uint16_t req_msg_size = sizeof (struct MulticastJoinRequestMessage) + join_msg_size;
1542 struct MulticastJoinRequestMessage *
1543 req = GNUNET_malloc (req_msg_size);
1544 req->header.size = htons (req_msg_size);
1545 req->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST);
1546 req->group_pub_key = grp->pub_key;
1547 req->peer = this_peer;
1548 GNUNET_CRYPTO_ecdsa_key_get_public (&mem->priv_key, &req->member_pub_key);
1549 if (0 < join_msg_size)
1550 GNUNET_memcpy (&req[1], join_msg, join_msg_size);
1552 req->member_pub_key = mem->pub_key;
1553 req->purpose.size = htonl (req_msg_size
1554 - sizeof (req->header)
1555 - sizeof (req->reserved)
1556 - sizeof (req->signature));
1557 req->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
1559 if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (&mem->priv_key, &req->purpose,
1562 /* FIXME: handle error */
1566 if (NULL != mem->join_req)
1567 GNUNET_free (mem->join_req);
1568 mem->join_req = req;
1570 if (0 == client_send_origin (&grp->pub_key_hash, &mem->join_req->header))
1571 { /* No local origins, send to remote origin */
1572 cadet_send_join_request (mem);
1575 GNUNET_SERVICE_client_continue (client);
1580 client_send_join_decision (struct Member *mem,
1581 const struct MulticastJoinDecisionMessageHeader *hdcsn)
1583 client_send_group (&mem->group, &hdcsn->header);
1585 const struct MulticastJoinDecisionMessage *
1586 dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1];
1587 if (GNUNET_YES == ntohl (dcsn->is_admitted))
1588 { /* Member admitted, store join_decision. */
1589 uint16_t dcsn_size = ntohs (dcsn->header.size);
1590 mem->join_dcsn = GNUNET_malloc (dcsn_size);
1591 GNUNET_memcpy (mem->join_dcsn, dcsn, dcsn_size);
1594 { /* Refused entry, but replay would be still possible for past members. */
1600 check_client_join_decision (void *cls,
1601 const struct MulticastJoinDecisionMessageHeader *hdcsn)
1608 * Join decision from client.
1611 handle_client_join_decision (void *cls,
1612 const struct MulticastJoinDecisionMessageHeader *hdcsn)
1614 struct Client *c = cls;
1615 struct GNUNET_SERVICE_Client *client = c->client;
1616 struct Group *grp = c->group;
1621 GNUNET_SERVICE_client_drop (client);
1624 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1625 "%p Got join decision from client for group %s..\n",
1626 grp, GNUNET_h2s (&grp->pub_key_hash));
1628 struct GNUNET_CONTAINER_MultiHashMap *
1629 grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members,
1630 &grp->pub_key_hash);
1631 struct Member *mem = NULL;
1632 if (NULL != grp_mem)
1634 struct GNUNET_HashCode member_key_hash;
1635 GNUNET_CRYPTO_hash (&hdcsn->member_pub_key, sizeof (hdcsn->member_pub_key),
1637 mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &member_key_hash);
1638 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1639 "%p ..and member %s: %p\n",
1640 grp, GNUNET_h2s (&member_key_hash), mem);
1644 { /* Found local member */
1645 client_send_join_decision (mem, hdcsn);
1648 { /* Look for remote member */
1649 cadet_send_join_decision (grp, hdcsn);
1651 GNUNET_SERVICE_client_continue (client);
1656 check_client_multicast_message (void *cls,
1657 const struct GNUNET_MULTICAST_MessageHeader *msg)
1664 * Incoming message from a client.
1667 handle_client_multicast_message (void *cls,
1668 const struct GNUNET_MULTICAST_MessageHeader *msg)
1670 struct Client *c = cls;
1671 struct GNUNET_SERVICE_Client *client = c->client;
1672 struct Group *grp = c->group;
1677 GNUNET_SERVICE_client_drop (client);
1680 GNUNET_assert (GNUNET_YES == grp->is_origin);
1681 struct Origin *orig = grp->origin;
1683 /* FIXME: yucky, should use separate message structs for P2P and CS! */
1684 struct GNUNET_MULTICAST_MessageHeader *
1685 out = (struct GNUNET_MULTICAST_MessageHeader *) GNUNET_copy_message (&msg->header);
1686 out->fragment_id = GNUNET_htonll (++orig->max_fragment_id);
1687 out->purpose.size = htonl (ntohs (out->header.size)
1688 - sizeof (out->header)
1689 - sizeof (out->hop_counter)
1690 - sizeof (out->signature));
1691 out->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE);
1693 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_sign (&orig->priv_key, &out->purpose,
1699 client_send_all (&grp->pub_key_hash, &out->header);
1700 cadet_send_children (&grp->pub_key_hash, &out->header);
1701 client_send_ack (&grp->pub_key_hash);
1704 GNUNET_SERVICE_client_continue (client);
1709 check_client_multicast_request (void *cls,
1710 const struct GNUNET_MULTICAST_RequestHeader *req)
1717 * Incoming request from a client.
1720 handle_client_multicast_request (void *cls,
1721 const struct GNUNET_MULTICAST_RequestHeader *req)
1723 struct Client *c = cls;
1724 struct GNUNET_SERVICE_Client *client = c->client;
1725 struct Group *grp = c->group;
1730 GNUNET_SERVICE_client_drop (client);
1733 GNUNET_assert (GNUNET_NO == grp->is_origin);
1734 struct Member *mem = grp->member;
1736 /* FIXME: yucky, should use separate message structs for P2P and CS! */
1737 struct GNUNET_MULTICAST_RequestHeader *
1738 out = (struct GNUNET_MULTICAST_RequestHeader *) GNUNET_copy_message (&req->header);
1739 out->member_pub_key = mem->pub_key;
1740 out->fragment_id = GNUNET_ntohll (++mem->max_fragment_id);
1741 out->purpose.size = htonl (ntohs (out->header.size)
1742 - sizeof (out->header)
1743 - sizeof (out->member_pub_key)
1744 - sizeof (out->signature));
1745 out->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
1747 if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (&mem->priv_key, &out->purpose,
1753 uint8_t send_ack = GNUNET_YES;
1754 if (0 == client_send_origin (&grp->pub_key_hash, &out->header))
1755 { /* No local origins, send to remote origin */
1756 if (NULL != mem->origin_channel)
1758 cadet_send_channel (mem->origin_channel, &out->header);
1759 send_ack = GNUNET_NO;
1763 /* FIXME: not yet connected to origin */
1764 GNUNET_SERVICE_client_drop (client);
1769 if (GNUNET_YES == send_ack)
1771 client_send_ack (&grp->pub_key_hash);
1774 GNUNET_SERVICE_client_continue (client);
1779 * Incoming replay request from a client.
1782 handle_client_replay_request (void *cls,
1783 const struct MulticastReplayRequestMessage *rep)
1785 struct Client *c = cls;
1786 struct GNUNET_SERVICE_Client *client = c->client;
1787 struct Group *grp = c->group;
1792 GNUNET_SERVICE_client_drop (client);
1795 GNUNET_assert (GNUNET_NO == grp->is_origin);
1796 struct Member *mem = grp->member;
1798 struct GNUNET_CONTAINER_MultiHashMap *
1799 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
1800 &grp->pub_key_hash);
1801 if (NULL == grp_replay_req)
1803 grp_replay_req = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1804 GNUNET_CONTAINER_multihashmap_put (replay_req_client,
1805 &grp->pub_key_hash, grp_replay_req,
1806 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1809 struct GNUNET_HashCode key_hash;
1810 replay_key_hash (rep->fragment_id, rep->message_id, rep->fragment_offset,
1811 rep->flags, &key_hash);
1812 GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, client,
1813 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1815 if (0 == client_send_origin (&grp->pub_key_hash, &rep->header))
1816 { /* No local origin, replay from remote members / origin. */
1817 if (NULL != mem->origin_channel)
1819 cadet_send_channel (mem->origin_channel, &rep->header);
1823 /* FIXME: not yet connected to origin */
1824 GNUNET_SERVICE_client_drop (client);
1828 GNUNET_SERVICE_client_continue (client);
1833 cadet_send_replay_response_cb (void *cls,
1834 const struct GNUNET_HashCode *key_hash,
1837 struct Channel *chn = value;
1838 struct GNUNET_MessageHeader *msg = cls;
1840 cadet_send_channel (chn, msg);
1846 client_send_replay_response_cb (void *cls,
1847 const struct GNUNET_HashCode *key_hash,
1850 struct GNUNET_SERVICE_Client *client = value;
1851 struct GNUNET_MessageHeader *msg = cls;
1853 client_send (client, msg);
1859 check_client_replay_response_end (void *cls,
1860 const struct MulticastReplayResponseMessage *res)
1867 * End of replay response from a client.
1870 handle_client_replay_response_end (void *cls,
1871 const struct MulticastReplayResponseMessage *res)
1873 struct Client *c = cls;
1874 struct GNUNET_SERVICE_Client *client = c->client;
1875 struct Group *grp = c->group;
1880 GNUNET_SERVICE_client_drop (client);
1884 struct GNUNET_HashCode key_hash;
1885 replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset,
1886 res->flags, &key_hash);
1888 struct GNUNET_CONTAINER_MultiHashMap *
1889 grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
1890 &grp->pub_key_hash);
1891 if (NULL != grp_replay_req_cadet)
1893 GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_cadet, &key_hash);
1895 struct GNUNET_CONTAINER_MultiHashMap *
1896 grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
1897 &grp->pub_key_hash);
1898 if (NULL != grp_replay_req_client)
1900 GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_client, &key_hash);
1902 GNUNET_SERVICE_client_continue (client);
1907 check_client_replay_response (void *cls,
1908 const struct MulticastReplayResponseMessage *res)
1910 const struct GNUNET_MessageHeader *msg = &res->header;
1911 if (GNUNET_MULTICAST_REC_OK == res->error_code)
1913 msg = GNUNET_MQ_extract_nested_mh (res);
1916 return GNUNET_SYSERR;
1924 * Incoming replay response from a client.
1926 * Respond with a multicast message on success, or otherwise with an error code.
1929 handle_client_replay_response (void *cls,
1930 const struct MulticastReplayResponseMessage *res)
1932 struct Client *c = cls;
1933 struct GNUNET_SERVICE_Client *client = c->client;
1934 struct Group *grp = c->group;
1939 GNUNET_SERVICE_client_drop (client);
1943 const struct GNUNET_MessageHeader *msg = &res->header;
1944 if (GNUNET_MULTICAST_REC_OK == res->error_code)
1946 msg = GNUNET_MQ_extract_nested_mh (res);
1949 struct GNUNET_HashCode key_hash;
1950 replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset,
1951 res->flags, &key_hash);
1953 struct GNUNET_CONTAINER_MultiHashMap *
1954 grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
1955 &grp->pub_key_hash);
1956 if (NULL != grp_replay_req_cadet)
1958 GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_cadet, &key_hash,
1959 cadet_send_replay_response_cb,
1962 if (GNUNET_MULTICAST_REC_OK == res->error_code)
1964 struct GNUNET_CONTAINER_MultiHashMap *
1965 grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
1966 &grp->pub_key_hash);
1967 if (NULL != grp_replay_req_client)
1969 GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_client, &key_hash,
1970 client_send_replay_response_cb,
1976 handle_client_replay_response_end (c, res);
1979 GNUNET_SERVICE_client_continue (client);
1984 * A new client connected.
1987 * @param client client to add
1988 * @param mq message queue for @a client
1992 client_notify_connect (void *cls,
1993 struct GNUNET_SERVICE_Client *client,
1994 struct GNUNET_MQ_Handle *mq)
1996 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client connected: %p\n", client);
1997 /* FIXME: send connect ACK */
1999 struct Client *c = GNUNET_new (struct Client);
2007 * Called whenever a client is disconnected.
2008 * Frees our resources associated with that client.
2010 * @param cls closure
2011 * @param client identification of the client
2012 * @param app_ctx must match @a client
2015 client_notify_disconnect (void *cls,
2016 struct GNUNET_SERVICE_Client *client,
2019 struct Client *c = app_ctx;
2020 struct Group *grp = c->group;
2025 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2026 "%p User context is NULL in client_disconnect()\n", grp);
2031 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2032 "%p Client (%s) disconnected from group %s\n",
2033 grp, (GNUNET_YES == grp->is_origin) ? "origin" : "member",
2034 GNUNET_h2s (&grp->pub_key_hash));
2036 struct ClientList *cl = grp->clients_head;
2039 if (cl->client == client)
2041 GNUNET_CONTAINER_DLL_remove (grp->clients_head, grp->clients_tail, cl);
2048 while (GNUNET_YES == replay_req_remove_client (grp, client));
2050 if (NULL == grp->clients_head)
2051 { /* Last client disconnected. */
2053 if (NULL != grp->tmit_head)
2054 { /* Send pending messages via CADET before cleanup. */
2055 transmit_message (grp);
2060 cleanup_group (grp);
2069 * @param cls closure
2070 * @param server the initialized server
2071 * @param cfg configuration to use
2075 const struct GNUNET_CONFIGURATION_Handle *c,
2076 struct GNUNET_SERVICE_Handle *svc)
2080 GNUNET_CRYPTO_get_peer_identity (cfg, &this_peer);
2082 stats = GNUNET_STATISTICS_create ("multicast", cfg);
2083 origins = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
2084 members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
2085 group_members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
2086 channels_in = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
2087 channels_out = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
2088 replay_req_cadet = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
2089 replay_req_client = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
2091 cadet = GNUNET_CADET_connect (cfg);
2093 GNUNET_assert (NULL != cadet);
2095 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
2101 * Define "main" method using service macro.
2105 GNUNET_SERVICE_OPTION_NONE,
2107 client_notify_connect,
2108 client_notify_disconnect,
2110 GNUNET_MQ_hd_fixed_size (client_origin_start,
2111 GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START,
2112 struct MulticastOriginStartMessage,
2114 GNUNET_MQ_hd_var_size (client_member_join,
2115 GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_JOIN,
2116 struct MulticastMemberJoinMessage,
2118 GNUNET_MQ_hd_var_size (client_join_decision,
2119 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION,
2120 struct MulticastJoinDecisionMessageHeader,
2122 GNUNET_MQ_hd_var_size (client_multicast_message,
2123 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE,
2124 struct GNUNET_MULTICAST_MessageHeader,
2126 GNUNET_MQ_hd_var_size (client_multicast_request,
2127 GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST,
2128 struct GNUNET_MULTICAST_RequestHeader,
2130 GNUNET_MQ_hd_fixed_size (client_replay_request,
2131 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
2132 struct MulticastReplayRequestMessage,
2134 GNUNET_MQ_hd_var_size (client_replay_response,
2135 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE,
2136 struct MulticastReplayResponseMessage,
2138 GNUNET_MQ_hd_var_size (client_replay_response_end,
2139 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE_END,
2140 struct MulticastReplayResponseMessage,
2143 /* end of gnunet-service-multicast.c */