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_keep_envelope (const struct Group *grp,
557 struct GNUNET_MQ_Envelope *env)
559 struct ClientList *cli = grp->clients_head;
561 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
562 "%p Sending message of type %u to all clients of the group.\n",
564 ntohs (env->mh->type));
567 GNUNET_MQ_send_copy (GNUNET_SERVICE_client_get_mq (cli->client),
575 * Send message to all clients connected to the group and
576 * takes care of freeing @env.
579 client_send_group (const struct Group *grp,
580 struct GNUNET_MQ_Envelope *env)
582 client_send_group_keep_envelope (grp, env);
583 GNUNET_MQ_discard (env);
588 * Iterator callback for sending a message to origin clients.
591 client_send_origin_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
594 struct GNUNET_MQ_Envelope *env = cls;
595 struct Member *orig = origin;
597 client_send_group_keep_envelope (&orig->group, env);
603 * Iterator callback for sending a message to member clients.
606 client_send_member_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
609 struct GNUNET_MQ_Envelope *env = cls;
610 struct Member *mem = member;
612 if (NULL != mem->join_dcsn)
613 { /* Only send message to admitted members */
614 client_send_group_keep_envelope (&mem->group, env);
621 * Send message to all origin and member clients connected to the group.
623 * @param pub_key_hash
624 * H(key_pub) of the group.
629 client_send_all (struct GNUNET_HashCode *pub_key_hash,
630 struct GNUNET_MQ_Envelope *env)
633 n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash,
634 client_send_origin_cb,
636 n += GNUNET_CONTAINER_multihashmap_get_multiple (members, pub_key_hash,
637 client_send_member_cb,
639 GNUNET_MQ_discard (env);
645 * Send message to a random origin client or a random member client.
647 * @param grp The group to send @a msg to.
648 * @param msg Message to send.
651 client_send_random (struct GNUNET_HashCode *pub_key_hash,
652 struct GNUNET_MQ_Envelope *env)
655 n = GNUNET_CONTAINER_multihashmap_get_random (origins, client_send_origin_cb,
658 n = GNUNET_CONTAINER_multihashmap_get_random (members, client_send_member_cb,
665 * Send message to all origin clients connected to the group.
667 * @param pub_key_hash
668 * H(key_pub) of the group.
673 client_send_origin (struct GNUNET_HashCode *pub_key_hash,
674 struct GNUNET_MQ_Envelope *env)
677 n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash,
678 client_send_origin_cb,
685 * Send fragment acknowledgement to all clients of the channel.
687 * @param pub_key_hash
688 * H(key_pub) of the group.
691 client_send_ack (struct GNUNET_HashCode *pub_key_hash)
693 struct GNUNET_MQ_Envelope *env;
695 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
696 "Sending message ACK to client.\n");
697 env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_MULTICAST_FRAGMENT_ACK);
698 client_send_all (pub_key_hash, env);
702 struct CadetTransmitClosure
705 const struct GNUNET_MessageHeader *msg;
710 * Send a message to a CADET channel.
712 * @param chn Channel.
713 * @param msg Message.
716 cadet_send_channel (struct Channel *chn, const struct GNUNET_MessageHeader *msg)
718 struct GNUNET_MQ_Envelope *
719 env = GNUNET_MQ_msg_copy (msg);
721 GNUNET_MQ_send (GNUNET_CADET_get_mq (chn->channel), env);
723 if (0 < chn->window_size)
725 client_send_ack (&chn->group_pub_hash);
730 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
731 "%p Queuing message. Pending messages: %u\n",
732 chn, chn->msgs_pending);
738 * Create CADET channel and send a join request.
741 cadet_send_join_request (struct Member *mem)
743 mem->origin_channel = cadet_channel_create (&mem->group, &mem->origin);
744 cadet_send_channel (mem->origin_channel, &mem->join_req->header);
747 for (i = 0; i < mem->relay_count; i++)
750 chn = cadet_channel_create (&mem->group, &mem->relays[i]);
751 cadet_send_channel (chn, &mem->join_req->header);
757 cadet_send_join_decision_cb (void *cls,
758 const struct GNUNET_HashCode *group_pub_hash,
761 const struct MulticastJoinDecisionMessageHeader *hdcsn = cls;
762 struct Channel *chn = channel;
764 const struct MulticastJoinDecisionMessage *dcsn =
765 (struct MulticastJoinDecisionMessage *) &hdcsn[1];
767 if (0 == memcmp (&hdcsn->member_pub_key, &chn->member_pub_key, sizeof (chn->member_pub_key))
768 && 0 == memcmp (&hdcsn->peer, &chn->peer, sizeof (chn->peer)))
770 if (GNUNET_YES == ntohl (dcsn->is_admitted))
772 chn->join_status = JOIN_ADMITTED;
776 chn->join_status = JOIN_REFUSED;
778 cadet_send_channel (chn, &hdcsn->header);
782 // return GNUNET_YES to continue the multihashmap_get iteration
788 * Send join decision to a remote peer.
791 cadet_send_join_decision (struct Group *grp,
792 const struct MulticastJoinDecisionMessageHeader *hdcsn)
794 GNUNET_CONTAINER_multihashmap_get_multiple (channels_in, &grp->pub_key_hash,
795 &cadet_send_join_decision_cb,
801 * Iterator callback for sending a message to origin clients.
804 cadet_send_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
807 const struct GNUNET_MessageHeader *msg = cls;
808 struct Channel *chn = channel;
809 if (JOIN_ADMITTED == chn->join_status)
810 cadet_send_channel (chn, msg);
816 * Send message to all connected children.
819 cadet_send_children (struct GNUNET_HashCode *pub_key_hash,
820 const struct GNUNET_MessageHeader *msg)
823 if (channels_in != NULL)
824 n += GNUNET_CONTAINER_multihashmap_get_multiple (channels_in, pub_key_hash,
825 cadet_send_cb, (void *) msg);
830 #if 0 // unused as yet
832 * Send message to all connected parents.
835 cadet_send_parents (struct GNUNET_HashCode *pub_key_hash,
836 const struct GNUNET_MessageHeader *msg)
839 if (channels_in != NULL)
840 n += GNUNET_CONTAINER_multihashmap_get_multiple (channels_out, pub_key_hash,
841 cadet_send_cb, (void *) msg);
848 * CADET channel connect handler.
850 * @see GNUNET_CADET_ConnectEventHandler()
853 cadet_notify_connect (void *cls,
854 struct GNUNET_CADET_Channel *channel,
855 const struct GNUNET_PeerIdentity *source)
857 struct Channel *chn = GNUNET_malloc (sizeof (struct Channel));
859 chn->channel = channel;
860 chn->direction = DIR_INCOMING;
861 chn->join_status = JOIN_NOT_ASKED;
863 GNUNET_CONTAINER_multihashmap_put (channels_in, &chn->group->pub_key_hash, chn,
864 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
870 * CADET window size change handler.
872 * @see GNUNET_CADET_WindowSizeEventHandler()
875 cadet_notify_window_change (void *cls,
876 const struct GNUNET_CADET_Channel *channel,
879 struct Channel *chn = cls;
881 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
882 "%p Window size changed to %d. Pending messages: %u\n",
883 chn, window_size, chn->msgs_pending);
885 chn->is_connected = GNUNET_YES;
886 chn->window_size = (int32_t) window_size;
888 for (int i = 0; i < window_size; i++)
890 if (0 < chn->msgs_pending)
892 client_send_ack (&chn->group_pub_hash);
904 * CADET channel disconnect handler.
906 * @see GNUNET_CADET_DisconnectEventHandler()
909 cadet_notify_disconnect (void *cls,
910 const struct GNUNET_CADET_Channel *channel)
915 struct Channel *chn = cls;
916 if (NULL != chn->group)
918 if (GNUNET_NO == chn->group->is_origin)
920 struct Member *mem = (struct Member *) chn->group;
921 if (chn == mem->origin_channel)
922 mem->origin_channel = NULL;
929 ret = replay_req_remove_cadet (chn);
931 while (GNUNET_YES == ret);
938 check_cadet_join_request (void *cls,
939 const struct MulticastJoinRequestMessage *req)
941 struct Channel *chn = cls;
944 || JOIN_NOT_ASKED != chn->join_status)
946 return GNUNET_SYSERR;
949 uint16_t size = ntohs (req->header.size);
950 if (size < sizeof (*req))
953 return GNUNET_SYSERR;
955 if (ntohl (req->purpose.size) != (size
956 - sizeof (req->header)
957 - sizeof (req->reserved)
958 - sizeof (req->signature)))
961 return GNUNET_SYSERR;
964 GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST,
965 &req->purpose, &req->signature,
966 &req->member_pub_key))
969 return GNUNET_SYSERR;
977 * Incoming join request message from CADET.
980 handle_cadet_join_request (void *cls,
981 const struct MulticastJoinRequestMessage *req)
983 struct Channel *chn = cls;
984 GNUNET_CADET_receive_done (chn->channel);
986 struct GNUNET_HashCode group_pub_hash;
987 GNUNET_CRYPTO_hash (&req->group_pub_key, sizeof (req->group_pub_key), &group_pub_hash);
988 chn->group_pub_key = req->group_pub_key;
989 chn->group_pub_hash = group_pub_hash;
990 chn->member_pub_key = req->member_pub_key;
991 chn->peer = req->peer;
992 chn->join_status = JOIN_WAITING;
994 client_send_all (&group_pub_hash,
995 GNUNET_MQ_msg_copy (&req->header));
1000 check_cadet_join_decision (void *cls,
1001 const struct MulticastJoinDecisionMessageHeader *hdcsn)
1003 uint16_t size = ntohs (hdcsn->header.size);
1004 if (size < sizeof (struct MulticastJoinDecisionMessageHeader) +
1005 sizeof (struct MulticastJoinDecisionMessage))
1007 GNUNET_break_op (0);
1008 return GNUNET_SYSERR;
1011 struct Channel *chn = cls;
1015 return GNUNET_SYSERR;
1017 if (NULL == chn->group || GNUNET_NO != chn->group->is_origin)
1020 return GNUNET_SYSERR;
1022 switch (chn->join_status)
1025 return GNUNET_SYSERR;
1030 case JOIN_NOT_ASKED:
1040 * Incoming join decision message from CADET.
1043 handle_cadet_join_decision (void *cls,
1044 const struct MulticastJoinDecisionMessageHeader *hdcsn)
1046 const struct MulticastJoinDecisionMessage *
1047 dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1];
1049 struct Channel *chn = cls;
1050 GNUNET_CADET_receive_done (chn->channel);
1052 // FIXME: do we need to copy chn->peer or compare it with hdcsn->peer?
1053 struct Member *mem = (struct Member *) chn->group;
1054 client_send_join_decision (mem, hdcsn);
1055 if (GNUNET_YES == ntohl (dcsn->is_admitted))
1057 chn->join_status = JOIN_ADMITTED;
1061 chn->join_status = JOIN_REFUSED;
1062 cadet_channel_destroy (chn);
1068 check_cadet_message (void *cls,
1069 const struct GNUNET_MULTICAST_MessageHeader *msg)
1071 uint16_t size = ntohs (msg->header.size);
1072 if (size < sizeof (*msg))
1074 GNUNET_break_op (0);
1075 return GNUNET_SYSERR;
1078 struct Channel *chn = cls;
1082 return GNUNET_SYSERR;
1084 if (ntohl (msg->purpose.size) != (size
1085 - sizeof (msg->header)
1086 - sizeof (msg->hop_counter)
1087 - sizeof (msg->signature)))
1089 GNUNET_break_op (0);
1090 return GNUNET_SYSERR;
1093 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE,
1094 &msg->purpose, &msg->signature,
1095 &chn->group_pub_key))
1097 GNUNET_break_op (0);
1098 return GNUNET_SYSERR;
1106 * Incoming multicast message from CADET.
1109 handle_cadet_message (void *cls,
1110 const struct GNUNET_MULTICAST_MessageHeader *msg)
1112 struct Channel *chn = cls;
1113 GNUNET_CADET_receive_done (chn->channel);
1114 client_send_all (&chn->group_pub_hash,
1115 GNUNET_MQ_msg_copy (&msg->header));
1120 check_cadet_request (void *cls,
1121 const struct GNUNET_MULTICAST_RequestHeader *req)
1123 uint16_t size = ntohs (req->header.size);
1124 if (size < sizeof (*req))
1126 GNUNET_break_op (0);
1127 return GNUNET_SYSERR;
1130 struct Channel *chn = cls;
1134 return GNUNET_SYSERR;
1136 if (ntohl (req->purpose.size) != (size
1137 - sizeof (req->header)
1138 - sizeof (req->member_pub_key)
1139 - sizeof (req->signature)))
1141 GNUNET_break_op (0);
1142 return GNUNET_SYSERR;
1145 GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST,
1146 &req->purpose, &req->signature,
1147 &req->member_pub_key))
1149 GNUNET_break_op (0);
1150 return GNUNET_SYSERR;
1158 * Incoming multicast request message from CADET.
1161 handle_cadet_request (void *cls,
1162 const struct GNUNET_MULTICAST_RequestHeader *req)
1164 struct Channel *chn = cls;
1165 GNUNET_CADET_receive_done (chn->channel);
1166 client_send_origin (&chn->group_pub_hash,
1167 GNUNET_MQ_msg_copy (&req->header));
1171 // FIXME: do checks in handle_cadet_replay_request
1173 //check_cadet_replay_request (void *cls,
1174 // const struct MulticastReplayRequestMessage *req)
1176 // uint16_t size = ntohs (req->header.size);
1177 // if (size < sizeof (*req))
1179 // GNUNET_break_op (0);
1180 // return GNUNET_SYSERR;
1183 // struct Channel *chn = cls;
1186 // GNUNET_break_op (0);
1187 // return GNUNET_SYSERR;
1190 // return GNUNET_OK;
1195 * Incoming multicast replay request from CADET.
1198 handle_cadet_replay_request (void *cls,
1199 const struct MulticastReplayRequestMessage *req)
1201 struct Channel *chn = cls;
1203 GNUNET_CADET_receive_done (chn->channel);
1205 struct MulticastReplayRequestMessage rep = *req;
1206 GNUNET_memcpy (&rep.member_pub_key, &chn->member_pub_key, sizeof (chn->member_pub_key));
1208 struct GNUNET_CONTAINER_MultiHashMap *
1209 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
1210 &chn->group->pub_key_hash);
1211 if (NULL == grp_replay_req)
1213 grp_replay_req = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1214 GNUNET_CONTAINER_multihashmap_put (replay_req_cadet,
1215 &chn->group->pub_key_hash, grp_replay_req,
1216 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1218 struct GNUNET_HashCode key_hash;
1219 replay_key_hash (rep.fragment_id,
1221 rep.fragment_offset,
1224 GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, chn,
1225 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1227 client_send_random (&chn->group_pub_hash,
1228 GNUNET_MQ_msg_copy (&rep.header));
1233 check_cadet_replay_response (void *cls,
1234 const struct MulticastReplayResponseMessage *res)
1236 struct Channel *chn = cls;
1240 return GNUNET_SYSERR;
1247 * Incoming multicast replay response from CADET.
1250 handle_cadet_replay_response (void *cls,
1251 const struct MulticastReplayResponseMessage *res)
1253 struct Channel *chn = cls;
1254 GNUNET_CADET_receive_done (chn->channel);
1256 /* @todo FIXME: got replay error response, send request to other members */
1261 group_set_cadet_port_hash (struct Group *grp)
1264 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
1268 GNUNET_APPLICATION_TYPE_MULTICAST,
1270 GNUNET_CRYPTO_hash (&port, sizeof (port), &grp->cadet_port_hash);
1276 * Create new outgoing CADET channel.
1279 * Peer to connect to.
1280 * @param group_pub_key
1281 * Public key of group the channel belongs to.
1282 * @param group_pub_hash
1283 * Hash of @a group_pub_key.
1287 static struct Channel *
1288 cadet_channel_create (struct Group *grp, struct GNUNET_PeerIdentity *peer)
1290 struct Channel *chn = GNUNET_malloc (sizeof (*chn));
1292 chn->group_pub_key = grp->pub_key;
1293 chn->group_pub_hash = grp->pub_key_hash;
1295 chn->direction = DIR_OUTGOING;
1296 chn->is_connected = GNUNET_NO;
1297 chn->join_status = JOIN_WAITING;
1299 struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
1300 GNUNET_MQ_hd_var_size (cadet_message,
1301 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE,
1302 struct GNUNET_MULTICAST_MessageHeader,
1305 GNUNET_MQ_hd_var_size (cadet_join_decision,
1306 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION,
1307 struct MulticastJoinDecisionMessageHeader,
1310 GNUNET_MQ_hd_fixed_size (cadet_replay_request,
1311 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
1312 struct MulticastReplayRequestMessage,
1315 GNUNET_MQ_hd_var_size (cadet_replay_response,
1316 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE,
1317 struct MulticastReplayResponseMessage,
1320 GNUNET_MQ_handler_end ()
1323 chn->channel = GNUNET_CADET_channel_create (cadet, chn, &chn->peer,
1324 &grp->cadet_port_hash,
1325 GNUNET_CADET_OPTION_RELIABLE,
1326 cadet_notify_window_change,
1327 cadet_notify_disconnect,
1329 GNUNET_CONTAINER_multihashmap_put (channels_out, &chn->group_pub_hash, chn,
1330 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1336 * Destroy outgoing CADET channel.
1339 cadet_channel_destroy (struct Channel *chn)
1341 GNUNET_CADET_channel_destroy (chn->channel);
1342 GNUNET_CONTAINER_multihashmap_remove_all (channels_out, &chn->group_pub_hash);
1347 * Handle a connecting client starting an origin.
1350 handle_client_origin_start (void *cls,
1351 const struct MulticastOriginStartMessage *msg)
1353 struct Client *c = cls;
1354 struct GNUNET_SERVICE_Client *client = c->client;
1356 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
1357 struct GNUNET_HashCode pub_key_hash;
1359 GNUNET_CRYPTO_eddsa_key_get_public (&msg->group_key, &pub_key);
1360 GNUNET_CRYPTO_hash (&pub_key, sizeof (pub_key), &pub_key_hash);
1363 orig = GNUNET_CONTAINER_multihashmap_get (origins, &pub_key_hash);
1368 orig = GNUNET_new (struct Origin);
1369 orig->priv_key = msg->group_key;
1370 orig->max_fragment_id = GNUNET_ntohll (msg->max_fragment_id);
1372 grp = c->group = &orig->group;
1374 grp->is_origin = GNUNET_YES;
1375 grp->pub_key = pub_key;
1376 grp->pub_key_hash = pub_key_hash;
1378 GNUNET_CONTAINER_multihashmap_put (origins, &grp->pub_key_hash, orig,
1379 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1381 group_set_cadet_port_hash (grp);
1383 struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
1384 GNUNET_MQ_hd_var_size (cadet_message,
1385 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE,
1386 struct GNUNET_MULTICAST_MessageHeader,
1389 GNUNET_MQ_hd_var_size (cadet_request,
1390 GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST,
1391 struct GNUNET_MULTICAST_RequestHeader,
1394 GNUNET_MQ_hd_var_size (cadet_join_request,
1395 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST,
1396 struct MulticastJoinRequestMessage,
1399 GNUNET_MQ_hd_fixed_size (cadet_replay_request,
1400 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
1401 struct MulticastReplayRequestMessage,
1404 GNUNET_MQ_hd_var_size (cadet_replay_response,
1405 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE,
1406 struct MulticastReplayResponseMessage,
1409 GNUNET_MQ_handler_end ()
1413 orig->cadet_port = GNUNET_CADET_open_port (cadet,
1414 &grp->cadet_port_hash,
1415 cadet_notify_connect,
1417 cadet_notify_window_change,
1418 cadet_notify_disconnect,
1426 struct ClientList *cl = GNUNET_new (struct ClientList);
1427 cl->client = client;
1428 GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl);
1430 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1431 "%p Client connected as origin to group %s.\n",
1432 orig, GNUNET_h2s (&grp->pub_key_hash));
1433 GNUNET_SERVICE_client_continue (client);
1438 check_client_member_join (void *cls,
1439 const struct MulticastMemberJoinMessage *msg)
1441 uint16_t msg_size = ntohs (msg->header.size);
1442 struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1];
1443 uint32_t relay_count = ntohl (msg->relay_count);
1444 uint16_t relay_size = relay_count * sizeof (*relays);
1445 struct GNUNET_MessageHeader *join_msg = NULL;
1446 uint16_t join_msg_size = 0;
1447 if (sizeof (*msg) + relay_size + sizeof (struct GNUNET_MessageHeader)
1450 join_msg = (struct GNUNET_MessageHeader *)
1451 (((char *) &msg[1]) + relay_size);
1452 join_msg_size = ntohs (join_msg->size);
1455 msg_size == (sizeof (*msg) + relay_size + join_msg_size)
1462 * Handle a connecting client joining a group.
1465 handle_client_member_join (void *cls,
1466 const struct MulticastMemberJoinMessage *msg)
1468 struct Client *c = cls;
1469 struct GNUNET_SERVICE_Client *client = c->client;
1471 uint16_t msg_size = ntohs (msg->header.size);
1473 struct GNUNET_CRYPTO_EcdsaPublicKey mem_pub_key;
1474 struct GNUNET_HashCode pub_key_hash, mem_pub_key_hash;
1476 GNUNET_CRYPTO_ecdsa_key_get_public (&msg->member_key, &mem_pub_key);
1477 GNUNET_CRYPTO_hash (&mem_pub_key, sizeof (mem_pub_key), &mem_pub_key_hash);
1478 GNUNET_CRYPTO_hash (&msg->group_pub_key, sizeof (msg->group_pub_key), &pub_key_hash);
1480 struct GNUNET_CONTAINER_MultiHashMap *
1481 grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members, &pub_key_hash);
1482 struct Member *mem = NULL;
1485 if (NULL != grp_mem)
1487 mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &mem_pub_key_hash);
1492 mem = GNUNET_new (struct Member);
1493 mem->origin = msg->origin;
1494 mem->priv_key = msg->member_key;
1495 mem->pub_key = mem_pub_key;
1496 mem->pub_key_hash = mem_pub_key_hash;
1497 mem->max_fragment_id = 0; // FIXME
1499 grp = c->group = &mem->group;
1501 grp->is_origin = GNUNET_NO;
1502 grp->pub_key = msg->group_pub_key;
1503 grp->pub_key_hash = pub_key_hash;
1504 group_set_cadet_port_hash (grp);
1506 if (NULL == grp_mem)
1508 grp_mem = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1509 GNUNET_CONTAINER_multihashmap_put (group_members, &grp->pub_key_hash, grp_mem,
1510 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1512 GNUNET_CONTAINER_multihashmap_put (grp_mem, &mem->pub_key_hash, mem,
1513 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1515 // FIXME: should the members hash map have option UNIQUE_FAST?
1516 GNUNET_CONTAINER_multihashmap_put (members, &grp->pub_key_hash, mem,
1517 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1524 struct ClientList *cl = GNUNET_new (struct ClientList);
1525 cl->client = client;
1526 GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl);
1528 char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&mem->pub_key);
1529 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1530 "Client connected to group %s as member %s (%s). size = %d\n",
1531 GNUNET_h2s (&grp->pub_key_hash),
1532 GNUNET_h2s2 (&mem->pub_key_hash),
1534 GNUNET_CONTAINER_multihashmap_size (members));
1537 if (NULL != mem->join_dcsn)
1538 { /* Already got a join decision, send it to client. */
1539 struct GNUNET_MQ_Envelope *
1540 env = GNUNET_MQ_msg_copy (&mem->join_dcsn->header);
1542 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
1546 { /* First client of the group, send join request. */
1547 struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1];
1548 uint32_t relay_count = ntohl (msg->relay_count);
1549 uint16_t relay_size = relay_count * sizeof (*relays);
1550 struct GNUNET_MessageHeader *join_msg = NULL;
1551 uint16_t join_msg_size = 0;
1552 if (sizeof (*msg) + relay_size + sizeof (struct GNUNET_MessageHeader)
1555 join_msg = (struct GNUNET_MessageHeader *)
1556 (((char *) &msg[1]) + relay_size);
1557 join_msg_size = ntohs (join_msg->size);
1560 uint16_t req_msg_size = sizeof (struct MulticastJoinRequestMessage) + join_msg_size;
1561 struct MulticastJoinRequestMessage *
1562 req = GNUNET_malloc (req_msg_size);
1563 req->header.size = htons (req_msg_size);
1564 req->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST);
1565 req->group_pub_key = grp->pub_key;
1566 req->peer = this_peer;
1567 GNUNET_CRYPTO_ecdsa_key_get_public (&mem->priv_key, &req->member_pub_key);
1568 if (0 < join_msg_size)
1569 GNUNET_memcpy (&req[1], join_msg, join_msg_size);
1571 req->member_pub_key = mem->pub_key;
1572 req->purpose.size = htonl (req_msg_size
1573 - sizeof (req->header)
1574 - sizeof (req->reserved)
1575 - sizeof (req->signature));
1576 req->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
1578 if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (&mem->priv_key, &req->purpose,
1581 /* FIXME: handle error */
1585 if (NULL != mem->join_req)
1586 GNUNET_free (mem->join_req);
1587 mem->join_req = req;
1590 client_send_origin (&grp->pub_key_hash,
1591 GNUNET_MQ_msg_copy (&mem->join_req->header)))
1592 { /* No local origins, send to remote origin */
1593 cadet_send_join_request (mem);
1596 GNUNET_SERVICE_client_continue (client);
1601 client_send_join_decision (struct Member *mem,
1602 const struct MulticastJoinDecisionMessageHeader *hdcsn)
1604 client_send_group (&mem->group, GNUNET_MQ_msg_copy (&hdcsn->header));
1606 const struct MulticastJoinDecisionMessage *
1607 dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1];
1608 if (GNUNET_YES == ntohl (dcsn->is_admitted))
1609 { /* Member admitted, store join_decision. */
1610 uint16_t dcsn_size = ntohs (dcsn->header.size);
1611 mem->join_dcsn = GNUNET_malloc (dcsn_size);
1612 GNUNET_memcpy (mem->join_dcsn, dcsn, dcsn_size);
1615 { /* Refused entry, but replay would be still possible for past members. */
1621 check_client_join_decision (void *cls,
1622 const struct MulticastJoinDecisionMessageHeader *hdcsn)
1629 * Join decision from client.
1632 handle_client_join_decision (void *cls,
1633 const struct MulticastJoinDecisionMessageHeader *hdcsn)
1635 struct Client *c = cls;
1636 struct GNUNET_SERVICE_Client *client = c->client;
1637 struct Group *grp = c->group;
1642 GNUNET_SERVICE_client_drop (client);
1645 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1646 "%p got join decision from client for group %s..\n",
1647 grp, GNUNET_h2s (&grp->pub_key_hash));
1649 struct GNUNET_CONTAINER_MultiHashMap *
1650 grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members,
1651 &grp->pub_key_hash);
1652 struct Member *mem = NULL;
1653 if (NULL != grp_mem)
1655 struct GNUNET_HashCode member_key_hash;
1656 GNUNET_CRYPTO_hash (&hdcsn->member_pub_key, sizeof (hdcsn->member_pub_key),
1658 mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &member_key_hash);
1659 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1660 "%p ..and member %s: %p\n",
1661 grp, GNUNET_h2s (&member_key_hash), mem);
1665 { /* Found local member */
1666 client_send_join_decision (mem, hdcsn);
1669 { /* Look for remote member */
1670 cadet_send_join_decision (grp, hdcsn);
1672 GNUNET_SERVICE_client_continue (client);
1677 handle_client_part_request (void *cls,
1678 const struct GNUNET_MessageHeader *msg)
1680 struct Client *c = cls;
1681 struct GNUNET_SERVICE_Client *client = c->client;
1682 struct Group *grp = c->group;
1683 struct GNUNET_MQ_Envelope *env;
1688 GNUNET_SERVICE_client_drop (client);
1691 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1692 "%p got part request from client for group %s.\n",
1693 grp, GNUNET_h2s (&grp->pub_key_hash));
1694 env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_MULTICAST_PART_ACK);
1695 client_send_group (grp, env);
1696 GNUNET_SERVICE_client_continue (client);
1701 check_client_multicast_message (void *cls,
1702 const struct GNUNET_MULTICAST_MessageHeader *msg)
1709 * Incoming message from a client.
1712 handle_client_multicast_message (void *cls,
1713 const struct GNUNET_MULTICAST_MessageHeader *msg)
1715 struct Client *c = cls;
1716 struct GNUNET_SERVICE_Client *client = c->client;
1717 struct Group *grp = c->group;
1722 GNUNET_SERVICE_client_drop (client);
1725 GNUNET_assert (GNUNET_YES == grp->is_origin);
1726 struct Origin *orig = grp->origin;
1728 // FIXME: use GNUNET_MQ_msg_copy
1729 /* FIXME: yucky, should use separate message structs for P2P and CS! */
1730 struct GNUNET_MULTICAST_MessageHeader *
1731 out = (struct GNUNET_MULTICAST_MessageHeader *) GNUNET_copy_message (&msg->header);
1732 out->fragment_id = GNUNET_htonll (++orig->max_fragment_id);
1733 out->purpose.size = htonl (ntohs (out->header.size)
1734 - sizeof (out->header)
1735 - sizeof (out->hop_counter)
1736 - sizeof (out->signature));
1737 out->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE);
1739 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_sign (&orig->priv_key, &out->purpose,
1745 client_send_all (&grp->pub_key_hash, GNUNET_MQ_msg_copy (&out->header));
1746 cadet_send_children (&grp->pub_key_hash, &out->header);
1747 client_send_ack (&grp->pub_key_hash);
1750 GNUNET_SERVICE_client_continue (client);
1755 check_client_multicast_request (void *cls,
1756 const struct GNUNET_MULTICAST_RequestHeader *req)
1763 * Incoming request from a client.
1766 handle_client_multicast_request (void *cls,
1767 const struct GNUNET_MULTICAST_RequestHeader *req)
1769 struct Client *c = cls;
1770 struct GNUNET_SERVICE_Client *client = c->client;
1771 struct Group *grp = c->group;
1776 GNUNET_SERVICE_client_drop (client);
1779 GNUNET_assert (GNUNET_NO == grp->is_origin);
1780 struct Member *mem = grp->member;
1782 /* FIXME: yucky, should use separate message structs for P2P and CS! */
1783 struct GNUNET_MULTICAST_RequestHeader *
1784 out = (struct GNUNET_MULTICAST_RequestHeader *) GNUNET_copy_message (&req->header);
1785 out->member_pub_key = mem->pub_key;
1786 out->fragment_id = GNUNET_ntohll (++mem->max_fragment_id);
1787 out->purpose.size = htonl (ntohs (out->header.size)
1788 - sizeof (out->header)
1789 - sizeof (out->member_pub_key)
1790 - sizeof (out->signature));
1791 out->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
1793 if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (&mem->priv_key, &out->purpose,
1799 uint8_t send_ack = GNUNET_YES;
1801 client_send_origin (&grp->pub_key_hash,
1802 GNUNET_MQ_msg_copy (&out->header)))
1803 { /* No local origins, send to remote origin */
1804 if (NULL != mem->origin_channel)
1806 cadet_send_channel (mem->origin_channel, &out->header);
1807 send_ack = GNUNET_NO;
1811 /* FIXME: not yet connected to origin */
1812 GNUNET_SERVICE_client_drop (client);
1817 if (GNUNET_YES == send_ack)
1819 client_send_ack (&grp->pub_key_hash);
1822 GNUNET_SERVICE_client_continue (client);
1827 * Incoming replay request from a client.
1830 handle_client_replay_request (void *cls,
1831 const struct MulticastReplayRequestMessage *rep)
1833 struct Client *c = cls;
1834 struct GNUNET_SERVICE_Client *client = c->client;
1835 struct Group *grp = c->group;
1840 GNUNET_SERVICE_client_drop (client);
1843 GNUNET_assert (GNUNET_NO == grp->is_origin);
1844 struct Member *mem = grp->member;
1846 struct GNUNET_CONTAINER_MultiHashMap *
1847 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
1848 &grp->pub_key_hash);
1849 if (NULL == grp_replay_req)
1851 grp_replay_req = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1852 GNUNET_CONTAINER_multihashmap_put (replay_req_client,
1853 &grp->pub_key_hash, grp_replay_req,
1854 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1857 struct GNUNET_HashCode key_hash;
1858 replay_key_hash (rep->fragment_id, rep->message_id, rep->fragment_offset,
1859 rep->flags, &key_hash);
1860 GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, client,
1861 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1864 client_send_origin (&grp->pub_key_hash,
1865 GNUNET_MQ_msg_copy (&rep->header)))
1866 { /* No local origin, replay from remote members / origin. */
1867 if (NULL != mem->origin_channel)
1869 cadet_send_channel (mem->origin_channel, &rep->header);
1873 /* FIXME: not yet connected to origin */
1875 GNUNET_SERVICE_client_drop (client);
1879 GNUNET_SERVICE_client_continue (client);
1884 cadet_send_replay_response_cb (void *cls,
1885 const struct GNUNET_HashCode *key_hash,
1888 struct Channel *chn = value;
1889 struct GNUNET_MessageHeader *msg = cls;
1891 cadet_send_channel (chn, msg);
1897 client_send_replay_response_cb (void *cls,
1898 const struct GNUNET_HashCode *key_hash,
1901 struct GNUNET_SERVICE_Client *client = value;
1902 struct GNUNET_MessageHeader *msg = cls;
1904 client_send (client, msg);
1910 check_client_replay_response_end (void *cls,
1911 const struct MulticastReplayResponseMessage *res)
1918 * End of replay response from a client.
1921 handle_client_replay_response_end (void *cls,
1922 const struct MulticastReplayResponseMessage *res)
1924 struct Client *c = cls;
1925 struct GNUNET_SERVICE_Client *client = c->client;
1926 struct Group *grp = c->group;
1931 GNUNET_SERVICE_client_drop (client);
1935 struct GNUNET_HashCode key_hash;
1936 replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset,
1937 res->flags, &key_hash);
1939 struct GNUNET_CONTAINER_MultiHashMap *
1940 grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
1941 &grp->pub_key_hash);
1942 if (NULL != grp_replay_req_cadet)
1944 GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_cadet, &key_hash);
1946 struct GNUNET_CONTAINER_MultiHashMap *
1947 grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
1948 &grp->pub_key_hash);
1949 if (NULL != grp_replay_req_client)
1951 GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_client, &key_hash);
1953 GNUNET_SERVICE_client_continue (client);
1958 check_client_replay_response (void *cls,
1959 const struct MulticastReplayResponseMessage *res)
1961 const struct GNUNET_MessageHeader *msg = &res->header;
1962 if (GNUNET_MULTICAST_REC_OK == res->error_code)
1964 msg = GNUNET_MQ_extract_nested_mh (res);
1967 return GNUNET_SYSERR;
1975 * Incoming replay response from a client.
1977 * Respond with a multicast message on success, or otherwise with an error code.
1980 handle_client_replay_response (void *cls,
1981 const struct MulticastReplayResponseMessage *res)
1983 struct Client *c = cls;
1984 struct GNUNET_SERVICE_Client *client = c->client;
1985 struct Group *grp = c->group;
1990 GNUNET_SERVICE_client_drop (client);
1994 const struct GNUNET_MessageHeader *msg = &res->header;
1995 if (GNUNET_MULTICAST_REC_OK == res->error_code)
1997 msg = GNUNET_MQ_extract_nested_mh (res);
2000 struct GNUNET_HashCode key_hash;
2001 replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset,
2002 res->flags, &key_hash);
2004 struct GNUNET_CONTAINER_MultiHashMap *
2005 grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
2006 &grp->pub_key_hash);
2007 if (NULL != grp_replay_req_cadet)
2009 GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_cadet, &key_hash,
2010 cadet_send_replay_response_cb,
2013 if (GNUNET_MULTICAST_REC_OK == res->error_code)
2015 struct GNUNET_CONTAINER_MultiHashMap *
2016 grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
2017 &grp->pub_key_hash);
2018 if (NULL != grp_replay_req_client)
2020 GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_client, &key_hash,
2021 client_send_replay_response_cb,
2027 handle_client_replay_response_end (c, res);
2030 GNUNET_SERVICE_client_continue (client);
2035 * A new client connected.
2038 * @param client client to add
2039 * @param mq message queue for @a client
2043 client_notify_connect (void *cls,
2044 struct GNUNET_SERVICE_Client *client,
2045 struct GNUNET_MQ_Handle *mq)
2047 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client connected: %p\n", client);
2048 /* FIXME: send connect ACK */
2050 struct Client *c = GNUNET_new (struct Client);
2058 * Called whenever a client is disconnected.
2059 * Frees our resources associated with that client.
2061 * @param cls closure
2062 * @param client identification of the client
2063 * @param app_ctx must match @a client
2066 client_notify_disconnect (void *cls,
2067 struct GNUNET_SERVICE_Client *client,
2070 struct Client *c = app_ctx;
2071 struct Group *grp = c->group;
2076 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2077 "%p User context is NULL in client_disconnect()\n", grp);
2082 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2083 "%p Client (%s) disconnected from group %s\n",
2084 grp, (GNUNET_YES == grp->is_origin) ? "origin" : "member",
2085 GNUNET_h2s (&grp->pub_key_hash));
2087 // FIXME (due to protocol change): here we must not remove all clients,
2088 // only the one we were notified about!
2089 struct ClientList *cl = grp->clients_head;
2092 if (cl->client == client)
2094 GNUNET_CONTAINER_DLL_remove (grp->clients_head, grp->clients_tail, cl);
2101 while (GNUNET_YES == replay_req_remove_client (grp, client));
2103 if (NULL == grp->clients_head)
2104 { /* Last client disconnected. */
2106 if (NULL != grp->tmit_head)
2107 { /* Send pending messages via CADET before cleanup. */
2108 transmit_message (grp);
2113 cleanup_group (grp);
2122 * @param cls closure
2123 * @param server the initialized server
2124 * @param cfg configuration to use
2128 const struct GNUNET_CONFIGURATION_Handle *c,
2129 struct GNUNET_SERVICE_Handle *svc)
2133 GNUNET_CRYPTO_get_peer_identity (cfg, &this_peer);
2135 stats = GNUNET_STATISTICS_create ("multicast", cfg);
2136 origins = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
2137 members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
2138 group_members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
2139 channels_in = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
2140 channels_out = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
2141 replay_req_cadet = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
2142 replay_req_client = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
2144 cadet = GNUNET_CADET_connect (cfg);
2146 GNUNET_assert (NULL != cadet);
2148 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
2154 * Define "main" method using service macro.
2158 GNUNET_SERVICE_OPTION_NONE,
2160 client_notify_connect,
2161 client_notify_disconnect,
2163 GNUNET_MQ_hd_fixed_size (client_origin_start,
2164 GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START,
2165 struct MulticastOriginStartMessage,
2167 GNUNET_MQ_hd_var_size (client_member_join,
2168 GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_JOIN,
2169 struct MulticastMemberJoinMessage,
2171 GNUNET_MQ_hd_var_size (client_join_decision,
2172 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION,
2173 struct MulticastJoinDecisionMessageHeader,
2175 GNUNET_MQ_hd_fixed_size (client_part_request,
2176 GNUNET_MESSAGE_TYPE_MULTICAST_PART_REQUEST,
2177 struct GNUNET_MessageHeader,
2179 GNUNET_MQ_hd_var_size (client_multicast_message,
2180 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE,
2181 struct GNUNET_MULTICAST_MessageHeader,
2183 GNUNET_MQ_hd_var_size (client_multicast_request,
2184 GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST,
2185 struct GNUNET_MULTICAST_RequestHeader,
2187 GNUNET_MQ_hd_fixed_size (client_replay_request,
2188 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
2189 struct MulticastReplayRequestMessage,
2191 GNUNET_MQ_hd_var_size (client_replay_response,
2192 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE,
2193 struct MulticastReplayResponseMessage,
2195 GNUNET_MQ_hd_var_size (client_replay_response_end,
2196 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE_END,
2197 struct MulticastReplayResponseMessage,
2200 /* end of gnunet-service-multicast.c */