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 it
6 under the terms of the GNU General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
17 * @file multicast/gnunet-service-multicast.c
18 * @brief program that does multicast
19 * @author Christian Grothoff
22 #include "gnunet_util_lib.h"
23 #include "gnunet_signatures.h"
24 #include "gnunet_applications.h"
25 #include "gnunet_statistics_service.h"
26 #include "gnunet_cadet_service.h"
27 #include "gnunet_multicast_service.h"
28 #include "multicast.h"
31 * Handle to our current configuration.
33 static const struct GNUNET_CONFIGURATION_Handle *cfg;
38 static struct GNUNET_SERVICE_Handle *service;
43 static struct GNUNET_CADET_Handle *cadet;
46 * Identity of this peer.
48 static struct GNUNET_PeerIdentity this_peer;
51 * Handle to the statistics service.
53 static struct GNUNET_STATISTICS_Handle *stats;
56 * All connected origin clients.
57 * Group's pub_key_hash -> struct Origin * (uniq)
59 static struct GNUNET_CONTAINER_MultiHashMap *origins;
62 * All connected member clients.
63 * Group's pub_key_hash -> struct Member * (multi)
65 static struct GNUNET_CONTAINER_MultiHashMap *members;
68 * Connected member clients per group.
69 * Group's pub_key_hash -> Member's pub_key_hash (uniq) -> struct Member * (uniq)
71 static struct GNUNET_CONTAINER_MultiHashMap *group_members;
74 * Incoming CADET channels with connected children in the tree.
75 * Group's pub_key_hash -> struct Channel * (multi)
77 static struct GNUNET_CONTAINER_MultiHashMap *channels_in;
80 * Outgoing CADET channels connecting to parents in the tree.
81 * Group's pub_key_hash -> struct Channel * (multi)
83 static struct GNUNET_CONTAINER_MultiHashMap *channels_out;
86 * Incoming replay requests from CADET.
87 * Group's pub_key_hash ->
88 * H(fragment_id, message_id, fragment_offset, flags) -> struct Channel *
90 static struct GNUNET_CONTAINER_MultiHashMap *replay_req_cadet;
93 * Incoming replay requests from clients.
94 * Group's pub_key_hash ->
95 * H(fragment_id, message_id, fragment_offset, flags) -> struct GNUNET_SERVICE_Client *
97 static struct GNUNET_CONTAINER_MultiHashMap *replay_req_client;
101 * Join status of a remote peer.
111 enum ChannelDirection
119 * Context for a CADET channel.
124 * Group the channel belongs to.
126 * Only set for outgoing channels.
133 struct GNUNET_CADET_Channel *channel;
137 * CADET transmission handle.
139 struct GNUNET_CADET_TransmitHandle *tmit_handle;
142 * Public key of the target group.
144 struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key;
147 * Hash of @a group_pub_key.
149 struct GNUNET_HashCode group_pub_hash;
152 * Public key of the joining member.
154 struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key;
157 * Remote peer identity.
159 struct GNUNET_PeerIdentity peer;
162 * Current window size, set by cadet_notify_window_change()
167 * Is the connection established?
172 * Is the remote peer admitted to the group?
173 * @see enum JoinStatus
178 * Number of messages waiting to be sent to CADET.
180 uint8_t msgs_pending;
184 * @see enum ChannelDirection
191 * List of connected clients.
195 struct ClientList *prev;
196 struct ClientList *next;
197 struct GNUNET_SERVICE_Client *client;
202 * Client context for an origin or member.
206 struct ClientList *clients_head;
207 struct ClientList *clients_tail;
210 * Public key of the group.
212 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
215 * Hash of @a pub_key.
217 struct GNUNET_HashCode pub_key_hash;
222 struct GNUNET_HashCode cadet_port_hash;
225 * Is the client disconnected? #GNUNET_YES or #GNUNET_NO
227 uint8_t is_disconnected;
230 * Is this an origin (#GNUNET_YES), or member (#GNUNET_NO)?
235 struct Origin *origin;
236 struct Member *member;
242 * Client context for a group's origin.
249 * Private key of the group.
251 struct GNUNET_CRYPTO_EddsaPrivateKey priv_key;
256 struct GNUNET_CADET_Port *cadet_port;
259 * Last message fragment ID sent to the group.
261 uint64_t max_fragment_id;
266 * Client context for a group member.
273 * Private key of the member.
275 struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key;
278 * Public key of the member.
280 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
283 * Hash of @a pub_key.
285 struct GNUNET_HashCode pub_key_hash;
288 * Join request sent to the origin / members.
290 struct MulticastJoinRequestMessage *join_req;
293 * Join decision sent in reply to our request.
295 * Only a positive decision is stored here, in case of a negative decision the
296 * client is disconnected.
298 struct MulticastJoinDecisionMessageHeader *join_dcsn;
301 * CADET channel to the origin.
303 struct Channel *origin_channel;
306 * Peer identity of origin.
308 struct GNUNET_PeerIdentity origin;
311 * Peer identity of relays (other members to connect).
313 struct GNUNET_PeerIdentity *relays;
316 * Last request fragment ID sent to the origin.
318 uint64_t max_fragment_id;
321 * Number of @a relays.
323 uint32_t relay_count;
331 struct GNUNET_SERVICE_Client *client;
336 struct ReplayRequestKey
338 uint64_t fragment_id;
340 uint64_t fragment_offset;
345 static struct Channel *
346 cadet_channel_create (struct Group *grp, struct GNUNET_PeerIdentity *peer);
349 cadet_channel_destroy (struct Channel *chn);
352 client_send_join_decision (struct Member *mem,
353 const struct MulticastJoinDecisionMessageHeader *hdcsn);
357 * Task run during shutdown.
362 shutdown_task (void *cls)
364 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
368 GNUNET_CADET_disconnect (cadet);
373 GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
376 /* FIXME: do more clean up here */
381 * Clean up origin data structures after a client disconnected.
384 cleanup_origin (struct Origin *orig)
386 struct Group *grp = &orig->group;
387 GNUNET_CONTAINER_multihashmap_remove (origins, &grp->pub_key_hash, orig);
388 if (NULL != orig->cadet_port)
390 GNUNET_CADET_close_port (orig->cadet_port);
391 orig->cadet_port = NULL;
398 * Clean up member data structures after a client disconnected.
401 cleanup_member (struct Member *mem)
403 struct Group *grp = &mem->group;
404 struct GNUNET_CONTAINER_MultiHashMap *
405 grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members,
407 GNUNET_assert (NULL != grp_mem);
408 GNUNET_CONTAINER_multihashmap_remove (grp_mem, &mem->pub_key_hash, mem);
410 if (0 == GNUNET_CONTAINER_multihashmap_size (grp_mem))
412 GNUNET_CONTAINER_multihashmap_remove (group_members, &grp->pub_key_hash,
414 GNUNET_CONTAINER_multihashmap_destroy (grp_mem);
416 if (NULL != mem->join_dcsn)
418 GNUNET_free (mem->join_dcsn);
419 mem->join_dcsn = NULL;
421 if (NULL != mem->origin_channel)
423 GNUNET_CADET_channel_destroy (mem->origin_channel->channel);
424 mem->origin_channel = NULL;
426 GNUNET_CONTAINER_multihashmap_remove (members, &grp->pub_key_hash, mem);
432 * Clean up group data structures after a client disconnected.
435 cleanup_group (struct Group *grp)
437 (GNUNET_YES == grp->is_origin)
438 ? cleanup_origin (grp->origin)
439 : cleanup_member (grp->member);
444 replay_key_hash (uint64_t fragment_id, uint64_t message_id,
445 uint64_t fragment_offset, uint64_t flags,
446 struct GNUNET_HashCode *key_hash)
448 struct ReplayRequestKey key = {
449 .fragment_id = fragment_id,
450 .message_id = message_id,
451 .fragment_offset = fragment_offset,
454 GNUNET_CRYPTO_hash (&key, sizeof (key), key_hash);
459 * Remove channel from replay request hashmap.
464 * @return #GNUNET_YES if there are more entries to process,
465 * #GNUNET_NO when reached end of hashmap.
468 replay_req_remove_cadet (struct Channel *chn)
470 if (NULL == chn || NULL == chn->group)
471 return GNUNET_SYSERR;
473 struct GNUNET_CONTAINER_MultiHashMap *
474 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
475 &chn->group->pub_key_hash);
476 if (NULL == grp_replay_req)
479 struct GNUNET_CONTAINER_MultiHashMapIterator *
480 it = GNUNET_CONTAINER_multihashmap_iterator_create (grp_replay_req);
481 struct GNUNET_HashCode key;
482 const struct Channel *c;
484 == GNUNET_CONTAINER_multihashmap_iterator_next (it, &key,
489 GNUNET_CONTAINER_multihashmap_remove (grp_replay_req, &key, chn);
490 GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
494 GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
500 * Remove client from replay request hashmap.
505 * @return #GNUNET_YES if there are more entries to process,
506 * #GNUNET_NO when reached end of hashmap.
509 replay_req_remove_client (struct Group *grp, struct GNUNET_SERVICE_Client *client)
511 struct GNUNET_CONTAINER_MultiHashMap *
512 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
514 if (NULL == grp_replay_req)
517 struct GNUNET_CONTAINER_MultiHashMapIterator *
518 it = GNUNET_CONTAINER_multihashmap_iterator_create (grp_replay_req);
519 struct GNUNET_HashCode key;
520 const struct GNUNET_SERVICE_Client *c;
522 == GNUNET_CONTAINER_multihashmap_iterator_next (it, &key,
527 GNUNET_CONTAINER_multihashmap_remove (grp_replay_req, &key, client);
528 GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
532 GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
538 * Send message to a client.
541 client_send (struct GNUNET_SERVICE_Client *client,
542 const struct GNUNET_MessageHeader *msg)
544 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
545 "%p Sending message to client.\n", client);
547 struct GNUNET_MQ_Envelope *
548 env = GNUNET_MQ_msg_copy (msg);
550 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
556 * Send message to all clients connected to the group.
559 client_send_group_keep_envelope (const struct Group *grp,
560 struct GNUNET_MQ_Envelope *env)
562 struct ClientList *cli = grp->clients_head;
564 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
565 "%p Sending message to all clients of the group.\n",
569 GNUNET_MQ_send_copy (GNUNET_SERVICE_client_get_mq (cli->client),
577 * Send message to all clients connected to the group and
578 * takes care of freeing @env.
581 client_send_group (const struct Group *grp,
582 struct GNUNET_MQ_Envelope *env)
584 client_send_group_keep_envelope (grp, env);
585 GNUNET_MQ_discard (env);
590 * Iterator callback for sending a message to origin clients.
593 client_send_origin_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
596 struct GNUNET_MQ_Envelope *env = cls;
597 struct Member *orig = origin;
599 client_send_group_keep_envelope (&orig->group, env);
605 * Iterator callback for sending a message to member clients.
608 client_send_member_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
611 struct GNUNET_MQ_Envelope *env = cls;
612 struct Member *mem = member;
614 if (NULL != mem->join_dcsn)
615 { /* Only send message to admitted members */
616 client_send_group_keep_envelope (&mem->group, env);
623 * Send message to all origin and member clients connected to the group.
625 * @param pub_key_hash
626 * H(key_pub) of the group.
631 client_send_all (struct GNUNET_HashCode *pub_key_hash,
632 struct GNUNET_MQ_Envelope *env)
635 n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash,
636 client_send_origin_cb,
638 n += GNUNET_CONTAINER_multihashmap_get_multiple (members, pub_key_hash,
639 client_send_member_cb,
641 GNUNET_MQ_discard (env);
647 * Send message to a random origin client or a random member client.
649 * @param grp The group to send @a msg to.
650 * @param msg Message to send.
653 client_send_random (struct GNUNET_HashCode *pub_key_hash,
654 struct GNUNET_MQ_Envelope *env)
657 n = GNUNET_CONTAINER_multihashmap_get_random (origins, client_send_origin_cb,
660 n = GNUNET_CONTAINER_multihashmap_get_random (members, client_send_member_cb,
662 GNUNET_MQ_discard (env);
668 * Send message to all origin clients connected to the group.
670 * @param pub_key_hash
671 * H(key_pub) of the group.
676 client_send_origin (struct GNUNET_HashCode *pub_key_hash,
677 struct GNUNET_MQ_Envelope *env)
680 n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash,
681 client_send_origin_cb,
688 * Send fragment acknowledgement to all clients of the channel.
690 * @param pub_key_hash
691 * H(key_pub) of the group.
694 client_send_ack (struct GNUNET_HashCode *pub_key_hash)
696 struct GNUNET_MQ_Envelope *env;
698 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
699 "Sending message ACK to client.\n");
700 env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_MULTICAST_FRAGMENT_ACK);
701 client_send_all (pub_key_hash, env);
705 struct CadetTransmitClosure
708 const struct GNUNET_MessageHeader *msg;
713 * Send a message to a CADET channel.
715 * @param chn Channel.
716 * @param msg Message.
719 cadet_send_channel (struct Channel *chn, const struct GNUNET_MessageHeader *msg)
721 struct GNUNET_MQ_Envelope *
722 env = GNUNET_MQ_msg_copy (msg);
724 GNUNET_MQ_send (GNUNET_CADET_get_mq (chn->channel), env);
726 if (0 < chn->window_size)
728 client_send_ack (&chn->group_pub_hash);
733 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
734 "%p Queuing message. Pending messages: %u\n",
735 chn, chn->msgs_pending);
741 * Create CADET channel and send a join request.
744 cadet_send_join_request (struct Member *mem)
746 mem->origin_channel = cadet_channel_create (&mem->group, &mem->origin);
747 cadet_send_channel (mem->origin_channel, &mem->join_req->header);
750 for (i = 0; i < mem->relay_count; i++)
753 chn = cadet_channel_create (&mem->group, &mem->relays[i]);
754 cadet_send_channel (chn, &mem->join_req->header);
760 cadet_send_join_decision_cb (void *cls,
761 const struct GNUNET_HashCode *group_pub_hash,
764 const struct MulticastJoinDecisionMessageHeader *hdcsn = cls;
765 struct Channel *chn = channel;
767 const struct MulticastJoinDecisionMessage *dcsn =
768 (struct MulticastJoinDecisionMessage *) &hdcsn[1];
770 if (0 == memcmp (&hdcsn->member_pub_key, &chn->member_pub_key, sizeof (chn->member_pub_key))
771 && 0 == memcmp (&hdcsn->peer, &chn->peer, sizeof (chn->peer)))
773 if (GNUNET_YES == ntohl (dcsn->is_admitted))
775 chn->join_status = JOIN_ADMITTED;
779 chn->join_status = JOIN_REFUSED;
781 cadet_send_channel (chn, &hdcsn->header);
785 // return GNUNET_YES to continue the multihashmap_get iteration
791 * Send join decision to a remote peer.
794 cadet_send_join_decision (struct Group *grp,
795 const struct MulticastJoinDecisionMessageHeader *hdcsn)
797 GNUNET_CONTAINER_multihashmap_get_multiple (channels_in, &grp->pub_key_hash,
798 &cadet_send_join_decision_cb,
804 * Iterator callback for sending a message to origin clients.
807 cadet_send_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
810 const struct GNUNET_MessageHeader *msg = cls;
811 struct Channel *chn = channel;
812 if (JOIN_ADMITTED == chn->join_status)
813 cadet_send_channel (chn, msg);
819 * Send message to all connected children.
822 cadet_send_children (struct GNUNET_HashCode *pub_key_hash,
823 const struct GNUNET_MessageHeader *msg)
826 if (channels_in != NULL)
827 n += GNUNET_CONTAINER_multihashmap_get_multiple (channels_in, pub_key_hash,
828 cadet_send_cb, (void *) msg);
833 #if 0 // unused as yet
835 * Send message to all connected parents.
838 cadet_send_parents (struct GNUNET_HashCode *pub_key_hash,
839 const struct GNUNET_MessageHeader *msg)
842 if (channels_in != NULL)
843 n += GNUNET_CONTAINER_multihashmap_get_multiple (channels_out, pub_key_hash,
844 cadet_send_cb, (void *) msg);
851 * CADET channel connect handler.
853 * @see GNUNET_CADET_ConnectEventHandler()
856 cadet_notify_connect (void *cls,
857 struct GNUNET_CADET_Channel *channel,
858 const struct GNUNET_PeerIdentity *source)
860 struct Channel *chn = GNUNET_malloc (sizeof (struct Channel));
862 chn->channel = channel;
863 chn->direction = DIR_INCOMING;
864 chn->join_status = JOIN_NOT_ASKED;
866 GNUNET_CONTAINER_multihashmap_put (channels_in, &chn->group->pub_key_hash, chn,
867 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
873 * CADET window size change handler.
875 * @see GNUNET_CADET_WindowSizeEventHandler()
878 cadet_notify_window_change (void *cls,
879 const struct GNUNET_CADET_Channel *channel,
882 struct Channel *chn = cls;
884 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
885 "%p Window size changed to %d. Pending messages: %u\n",
886 chn, window_size, chn->msgs_pending);
888 chn->is_connected = GNUNET_YES;
889 chn->window_size = (int32_t) window_size;
891 for (int i = 0; i < window_size; i++)
893 if (0 < chn->msgs_pending)
895 client_send_ack (&chn->group_pub_hash);
907 * CADET channel disconnect handler.
909 * @see GNUNET_CADET_DisconnectEventHandler()
912 cadet_notify_disconnect (void *cls,
913 const struct GNUNET_CADET_Channel *channel)
918 struct Channel *chn = cls;
919 if (NULL != chn->group)
921 if (GNUNET_NO == chn->group->is_origin)
923 struct Member *mem = (struct Member *) chn->group;
924 if (chn == mem->origin_channel)
925 mem->origin_channel = NULL;
932 ret = replay_req_remove_cadet (chn);
934 while (GNUNET_YES == ret);
941 check_cadet_join_request (void *cls,
942 const struct MulticastJoinRequestMessage *req)
944 struct Channel *chn = cls;
947 || JOIN_NOT_ASKED != chn->join_status)
949 return GNUNET_SYSERR;
952 uint16_t size = ntohs (req->header.size);
953 if (size < sizeof (*req))
956 return GNUNET_SYSERR;
958 if (ntohl (req->purpose.size) != (size
959 - sizeof (req->header)
960 - sizeof (req->reserved)
961 - sizeof (req->signature)))
964 return GNUNET_SYSERR;
967 GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST,
968 &req->purpose, &req->signature,
969 &req->member_pub_key))
972 return GNUNET_SYSERR;
980 * Incoming join request message from CADET.
983 handle_cadet_join_request (void *cls,
984 const struct MulticastJoinRequestMessage *req)
986 struct Channel *chn = cls;
987 GNUNET_CADET_receive_done (chn->channel);
989 struct GNUNET_HashCode group_pub_hash;
990 GNUNET_CRYPTO_hash (&req->group_pub_key, sizeof (req->group_pub_key), &group_pub_hash);
991 chn->group_pub_key = req->group_pub_key;
992 chn->group_pub_hash = group_pub_hash;
993 chn->member_pub_key = req->member_pub_key;
994 chn->peer = req->peer;
995 chn->join_status = JOIN_WAITING;
997 client_send_all (&group_pub_hash,
998 GNUNET_MQ_msg_copy (&req->header));
1003 check_cadet_join_decision (void *cls,
1004 const struct MulticastJoinDecisionMessageHeader *hdcsn)
1006 uint16_t size = ntohs (hdcsn->header.size);
1007 if (size < sizeof (struct MulticastJoinDecisionMessageHeader) +
1008 sizeof (struct MulticastJoinDecisionMessage))
1010 GNUNET_break_op (0);
1011 return GNUNET_SYSERR;
1014 struct Channel *chn = cls;
1018 return GNUNET_SYSERR;
1020 if (NULL == chn->group || GNUNET_NO != chn->group->is_origin)
1023 return GNUNET_SYSERR;
1025 switch (chn->join_status)
1028 return GNUNET_SYSERR;
1033 case JOIN_NOT_ASKED:
1043 * Incoming join decision message from CADET.
1046 handle_cadet_join_decision (void *cls,
1047 const struct MulticastJoinDecisionMessageHeader *hdcsn)
1049 const struct MulticastJoinDecisionMessage *
1050 dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1];
1052 struct Channel *chn = cls;
1053 GNUNET_CADET_receive_done (chn->channel);
1055 // FIXME: do we need to copy chn->peer or compare it with hdcsn->peer?
1056 struct Member *mem = (struct Member *) chn->group;
1057 client_send_join_decision (mem, hdcsn);
1058 if (GNUNET_YES == ntohl (dcsn->is_admitted))
1060 chn->join_status = JOIN_ADMITTED;
1064 chn->join_status = JOIN_REFUSED;
1065 cadet_channel_destroy (chn);
1071 check_cadet_message (void *cls,
1072 const struct GNUNET_MULTICAST_MessageHeader *msg)
1074 uint16_t size = ntohs (msg->header.size);
1075 if (size < sizeof (*msg))
1077 GNUNET_break_op (0);
1078 return GNUNET_SYSERR;
1081 struct Channel *chn = cls;
1085 return GNUNET_SYSERR;
1087 if (ntohl (msg->purpose.size) != (size
1088 - sizeof (msg->header)
1089 - sizeof (msg->hop_counter)
1090 - sizeof (msg->signature)))
1092 GNUNET_break_op (0);
1093 return GNUNET_SYSERR;
1096 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE,
1097 &msg->purpose, &msg->signature,
1098 &chn->group_pub_key))
1100 GNUNET_break_op (0);
1101 return GNUNET_SYSERR;
1109 * Incoming multicast message from CADET.
1112 handle_cadet_message (void *cls,
1113 const struct GNUNET_MULTICAST_MessageHeader *msg)
1115 struct Channel *chn = cls;
1116 GNUNET_CADET_receive_done (chn->channel);
1117 client_send_all (&chn->group_pub_hash,
1118 GNUNET_MQ_msg_copy (&msg->header));
1123 check_cadet_request (void *cls,
1124 const struct GNUNET_MULTICAST_RequestHeader *req)
1126 uint16_t size = ntohs (req->header.size);
1127 if (size < sizeof (*req))
1129 GNUNET_break_op (0);
1130 return GNUNET_SYSERR;
1133 struct Channel *chn = cls;
1137 return GNUNET_SYSERR;
1139 if (ntohl (req->purpose.size) != (size
1140 - sizeof (req->header)
1141 - sizeof (req->member_pub_key)
1142 - sizeof (req->signature)))
1144 GNUNET_break_op (0);
1145 return GNUNET_SYSERR;
1148 GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST,
1149 &req->purpose, &req->signature,
1150 &req->member_pub_key))
1152 GNUNET_break_op (0);
1153 return GNUNET_SYSERR;
1161 * Incoming multicast request message from CADET.
1164 handle_cadet_request (void *cls,
1165 const struct GNUNET_MULTICAST_RequestHeader *req)
1167 struct Channel *chn = cls;
1168 GNUNET_CADET_receive_done (chn->channel);
1169 client_send_origin (&chn->group_pub_hash,
1170 GNUNET_MQ_msg_copy (&req->header));
1174 // FIXME: do checks in handle_cadet_replay_request
1176 //check_cadet_replay_request (void *cls,
1177 // const struct MulticastReplayRequestMessage *req)
1179 // uint16_t size = ntohs (req->header.size);
1180 // if (size < sizeof (*req))
1182 // GNUNET_break_op (0);
1183 // return GNUNET_SYSERR;
1186 // struct Channel *chn = cls;
1189 // GNUNET_break_op (0);
1190 // return GNUNET_SYSERR;
1193 // return GNUNET_OK;
1198 * Incoming multicast replay request from CADET.
1201 handle_cadet_replay_request (void *cls,
1202 const struct MulticastReplayRequestMessage *req)
1204 struct Channel *chn = cls;
1206 GNUNET_CADET_receive_done (chn->channel);
1208 struct MulticastReplayRequestMessage rep = *req;
1209 GNUNET_memcpy (&rep.member_pub_key, &chn->member_pub_key, sizeof (chn->member_pub_key));
1211 struct GNUNET_CONTAINER_MultiHashMap *
1212 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
1213 &chn->group->pub_key_hash);
1214 if (NULL == grp_replay_req)
1216 grp_replay_req = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1217 GNUNET_CONTAINER_multihashmap_put (replay_req_cadet,
1218 &chn->group->pub_key_hash, grp_replay_req,
1219 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1221 struct GNUNET_HashCode key_hash;
1222 replay_key_hash (rep.fragment_id,
1224 rep.fragment_offset,
1227 GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, chn,
1228 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1230 client_send_random (&chn->group_pub_hash,
1231 GNUNET_MQ_msg_copy (&rep.header));
1236 check_cadet_replay_response (void *cls,
1237 const struct MulticastReplayResponseMessage *res)
1239 struct Channel *chn = cls;
1243 return GNUNET_SYSERR;
1250 * Incoming multicast replay response from CADET.
1253 handle_cadet_replay_response (void *cls,
1254 const struct MulticastReplayResponseMessage *res)
1256 struct Channel *chn = cls;
1257 GNUNET_CADET_receive_done (chn->channel);
1259 /* @todo FIXME: got replay error response, send request to other members */
1264 group_set_cadet_port_hash (struct Group *grp)
1267 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
1271 GNUNET_APPLICATION_TYPE_MULTICAST,
1273 GNUNET_CRYPTO_hash (&port, sizeof (port), &grp->cadet_port_hash);
1279 * Create new outgoing CADET channel.
1282 * Peer to connect to.
1283 * @param group_pub_key
1284 * Public key of group the channel belongs to.
1285 * @param group_pub_hash
1286 * Hash of @a group_pub_key.
1290 static struct Channel *
1291 cadet_channel_create (struct Group *grp, struct GNUNET_PeerIdentity *peer)
1293 struct Channel *chn = GNUNET_malloc (sizeof (*chn));
1295 chn->group_pub_key = grp->pub_key;
1296 chn->group_pub_hash = grp->pub_key_hash;
1298 chn->direction = DIR_OUTGOING;
1299 chn->is_connected = GNUNET_NO;
1300 chn->join_status = JOIN_WAITING;
1302 struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
1303 GNUNET_MQ_hd_var_size (cadet_message,
1304 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE,
1305 struct GNUNET_MULTICAST_MessageHeader,
1308 GNUNET_MQ_hd_var_size (cadet_join_decision,
1309 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION,
1310 struct MulticastJoinDecisionMessageHeader,
1313 GNUNET_MQ_hd_fixed_size (cadet_replay_request,
1314 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
1315 struct MulticastReplayRequestMessage,
1318 GNUNET_MQ_hd_var_size (cadet_replay_response,
1319 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE,
1320 struct MulticastReplayResponseMessage,
1323 GNUNET_MQ_handler_end ()
1326 chn->channel = GNUNET_CADET_channel_create (cadet, chn, &chn->peer,
1327 &grp->cadet_port_hash,
1328 GNUNET_CADET_OPTION_RELIABLE,
1329 cadet_notify_window_change,
1330 cadet_notify_disconnect,
1332 GNUNET_CONTAINER_multihashmap_put (channels_out, &chn->group_pub_hash, chn,
1333 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1339 * Destroy outgoing CADET channel.
1342 cadet_channel_destroy (struct Channel *chn)
1344 GNUNET_CADET_channel_destroy (chn->channel);
1345 GNUNET_CONTAINER_multihashmap_remove_all (channels_out, &chn->group_pub_hash);
1350 * Handle a connecting client starting an origin.
1353 handle_client_origin_start (void *cls,
1354 const struct MulticastOriginStartMessage *msg)
1356 struct Client *c = cls;
1357 struct GNUNET_SERVICE_Client *client = c->client;
1359 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
1360 struct GNUNET_HashCode pub_key_hash;
1362 GNUNET_CRYPTO_eddsa_key_get_public (&msg->group_key, &pub_key);
1363 GNUNET_CRYPTO_hash (&pub_key, sizeof (pub_key), &pub_key_hash);
1366 orig = GNUNET_CONTAINER_multihashmap_get (origins, &pub_key_hash);
1371 orig = GNUNET_new (struct Origin);
1372 orig->priv_key = msg->group_key;
1373 orig->max_fragment_id = GNUNET_ntohll (msg->max_fragment_id);
1375 grp = c->group = &orig->group;
1377 grp->is_origin = GNUNET_YES;
1378 grp->pub_key = pub_key;
1379 grp->pub_key_hash = pub_key_hash;
1380 grp->is_disconnected = GNUNET_NO;
1382 GNUNET_CONTAINER_multihashmap_put (origins, &grp->pub_key_hash, orig,
1383 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1385 group_set_cadet_port_hash (grp);
1387 struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
1388 GNUNET_MQ_hd_var_size (cadet_message,
1389 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE,
1390 struct GNUNET_MULTICAST_MessageHeader,
1393 GNUNET_MQ_hd_var_size (cadet_request,
1394 GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST,
1395 struct GNUNET_MULTICAST_RequestHeader,
1398 GNUNET_MQ_hd_var_size (cadet_join_request,
1399 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST,
1400 struct MulticastJoinRequestMessage,
1403 GNUNET_MQ_hd_fixed_size (cadet_replay_request,
1404 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
1405 struct MulticastReplayRequestMessage,
1408 GNUNET_MQ_hd_var_size (cadet_replay_response,
1409 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE,
1410 struct MulticastReplayResponseMessage,
1413 GNUNET_MQ_handler_end ()
1417 orig->cadet_port = GNUNET_CADET_open_port (cadet,
1418 &grp->cadet_port_hash,
1419 cadet_notify_connect,
1421 cadet_notify_window_change,
1422 cadet_notify_disconnect,
1430 struct ClientList *cl = GNUNET_new (struct ClientList);
1431 cl->client = client;
1432 GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl);
1434 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1435 "%p Client connected as origin to group %s.\n",
1436 orig, GNUNET_h2s (&grp->pub_key_hash));
1437 GNUNET_SERVICE_client_continue (client);
1442 check_client_member_join (void *cls,
1443 const struct MulticastMemberJoinMessage *msg)
1445 uint16_t msg_size = ntohs (msg->header.size);
1446 struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1];
1447 uint32_t relay_count = ntohl (msg->relay_count);
1448 if (UINT32_MAX / relay_count < sizeof (*relays)){
1449 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1450 "relay_count (%lu) * sizeof (*relays) (%lu) exceeds UINT32_MAX!\n",
1451 (unsigned long)relay_count,
1453 return GNUNET_SYSERR;
1455 uint32_t relay_size = relay_count * sizeof (*relays);
1456 struct GNUNET_MessageHeader *join_msg = NULL;
1457 uint16_t join_msg_size = 0;
1458 if (sizeof (*msg) + relay_size + sizeof (struct GNUNET_MessageHeader)
1461 join_msg = (struct GNUNET_MessageHeader *)
1462 (((char *) &msg[1]) + relay_size);
1463 join_msg_size = ntohs (join_msg->size);
1464 if (UINT16_MAX - join_msg_size < sizeof (struct MulticastJoinRequestMessage)){
1465 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1466 "join_msg_size (%u) + sizeof (struct MulticastJoinRequestMessage) (%lu) exceeds UINT16_MAX!\n",
1467 (unsigned)join_msg_size,
1468 (unsigned long)sizeof (struct MulticastJoinRequestMessage));
1469 return GNUNET_SYSERR;
1472 if (msg_size != (sizeof (*msg) + relay_size + join_msg_size)){
1473 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1474 "msg_size does not match real size of message!\n");
1475 return GNUNET_SYSERR;
1483 * Handle a connecting client joining a group.
1486 handle_client_member_join (void *cls,
1487 const struct MulticastMemberJoinMessage *msg)
1489 struct Client *c = cls;
1490 struct GNUNET_SERVICE_Client *client = c->client;
1492 uint16_t msg_size = ntohs (msg->header.size);
1494 struct GNUNET_CRYPTO_EcdsaPublicKey mem_pub_key;
1495 struct GNUNET_HashCode pub_key_hash, mem_pub_key_hash;
1497 GNUNET_CRYPTO_ecdsa_key_get_public (&msg->member_key, &mem_pub_key);
1498 GNUNET_CRYPTO_hash (&mem_pub_key, sizeof (mem_pub_key), &mem_pub_key_hash);
1499 GNUNET_CRYPTO_hash (&msg->group_pub_key, sizeof (msg->group_pub_key), &pub_key_hash);
1501 struct GNUNET_CONTAINER_MultiHashMap *
1502 grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members, &pub_key_hash);
1503 struct Member *mem = NULL;
1506 if (NULL != grp_mem)
1508 mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &mem_pub_key_hash);
1513 mem = GNUNET_new (struct Member);
1514 mem->origin = msg->origin;
1515 mem->priv_key = msg->member_key;
1516 mem->pub_key = mem_pub_key;
1517 mem->pub_key_hash = mem_pub_key_hash;
1518 mem->max_fragment_id = 0; // FIXME
1520 grp = c->group = &mem->group;
1522 grp->is_origin = GNUNET_NO;
1523 grp->pub_key = msg->group_pub_key;
1524 grp->pub_key_hash = pub_key_hash;
1525 grp->is_disconnected = GNUNET_NO;
1526 group_set_cadet_port_hash (grp);
1528 if (NULL == grp_mem)
1530 grp_mem = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1531 GNUNET_CONTAINER_multihashmap_put (group_members, &grp->pub_key_hash, grp_mem,
1532 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1534 GNUNET_CONTAINER_multihashmap_put (grp_mem, &mem->pub_key_hash, mem,
1535 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1537 // FIXME: should the members hash map have option UNIQUE_FAST?
1538 GNUNET_CONTAINER_multihashmap_put (members, &grp->pub_key_hash, mem,
1539 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1546 struct ClientList *cl = GNUNET_new (struct ClientList);
1547 cl->client = client;
1548 GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl);
1550 char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&mem->pub_key);
1551 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1552 "Client connected to group %s as member %s (%s). size = %d\n",
1553 GNUNET_h2s (&grp->pub_key_hash),
1554 GNUNET_h2s2 (&mem->pub_key_hash),
1556 GNUNET_CONTAINER_multihashmap_size (members));
1559 if (NULL != mem->join_dcsn)
1560 { /* Already got a join decision, send it to client. */
1561 struct GNUNET_MQ_Envelope *
1562 env = GNUNET_MQ_msg_copy (&mem->join_dcsn->header);
1564 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
1568 { /* First client of the group, send join request. */
1569 struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1];
1570 uint32_t relay_count = ntohl (msg->relay_count);
1571 uint16_t relay_size = relay_count * sizeof (*relays);
1572 struct GNUNET_MessageHeader *join_msg = NULL;
1573 uint16_t join_msg_size = 0;
1574 if (sizeof (*msg) + relay_size + sizeof (struct GNUNET_MessageHeader)
1577 join_msg = (struct GNUNET_MessageHeader *)
1578 (((char *) &msg[1]) + relay_size);
1579 join_msg_size = ntohs (join_msg->size);
1582 uint16_t req_msg_size = sizeof (struct MulticastJoinRequestMessage) + join_msg_size;
1583 struct MulticastJoinRequestMessage *
1584 req = GNUNET_malloc (req_msg_size);
1585 req->header.size = htons (req_msg_size);
1586 req->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST);
1587 req->group_pub_key = grp->pub_key;
1588 req->peer = this_peer;
1589 GNUNET_CRYPTO_ecdsa_key_get_public (&mem->priv_key, &req->member_pub_key);
1590 if (0 < join_msg_size)
1591 GNUNET_memcpy (&req[1], join_msg, join_msg_size);
1593 req->member_pub_key = mem->pub_key;
1594 req->purpose.size = htonl (req_msg_size
1595 - sizeof (req->header)
1596 - sizeof (req->reserved)
1597 - sizeof (req->signature));
1598 req->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
1600 if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (&mem->priv_key, &req->purpose,
1603 /* FIXME: handle error */
1607 if (NULL != mem->join_req)
1608 GNUNET_free (mem->join_req);
1609 mem->join_req = req;
1612 client_send_origin (&grp->pub_key_hash,
1613 GNUNET_MQ_msg_copy (&mem->join_req->header)))
1614 { /* No local origins, send to remote origin */
1615 cadet_send_join_request (mem);
1618 GNUNET_SERVICE_client_continue (client);
1623 client_send_join_decision (struct Member *mem,
1624 const struct MulticastJoinDecisionMessageHeader *hdcsn)
1626 client_send_group (&mem->group, GNUNET_MQ_msg_copy (&hdcsn->header));
1628 const struct MulticastJoinDecisionMessage *
1629 dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1];
1630 if (GNUNET_YES == ntohl (dcsn->is_admitted))
1631 { /* Member admitted, store join_decision. */
1632 uint16_t dcsn_size = ntohs (dcsn->header.size);
1633 mem->join_dcsn = GNUNET_malloc (dcsn_size);
1634 GNUNET_memcpy (mem->join_dcsn, dcsn, dcsn_size);
1637 { /* Refused entry, but replay would be still possible for past members. */
1643 check_client_join_decision (void *cls,
1644 const struct MulticastJoinDecisionMessageHeader *hdcsn)
1651 * Join decision from client.
1654 handle_client_join_decision (void *cls,
1655 const struct MulticastJoinDecisionMessageHeader *hdcsn)
1657 struct Client *c = cls;
1658 struct GNUNET_SERVICE_Client *client = c->client;
1659 struct Group *grp = c->group;
1664 GNUNET_SERVICE_client_drop (client);
1667 GNUNET_assert (GNUNET_NO == grp->is_disconnected);
1668 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1669 "%p got join decision from client for group %s..\n",
1670 grp, GNUNET_h2s (&grp->pub_key_hash));
1672 struct GNUNET_CONTAINER_MultiHashMap *
1673 grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members,
1674 &grp->pub_key_hash);
1675 struct Member *mem = NULL;
1676 if (NULL != grp_mem)
1678 struct GNUNET_HashCode member_key_hash;
1679 GNUNET_CRYPTO_hash (&hdcsn->member_pub_key, sizeof (hdcsn->member_pub_key),
1681 mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &member_key_hash);
1682 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1683 "%p ..and member %s: %p\n",
1684 grp, GNUNET_h2s (&member_key_hash), mem);
1688 { /* Found local member */
1689 client_send_join_decision (mem, hdcsn);
1692 { /* Look for remote member */
1693 cadet_send_join_decision (grp, hdcsn);
1695 GNUNET_SERVICE_client_continue (client);
1700 handle_client_part_request (void *cls,
1701 const struct GNUNET_MessageHeader *msg)
1703 struct Client *c = cls;
1704 struct GNUNET_SERVICE_Client *client = c->client;
1705 struct Group *grp = c->group;
1706 struct GNUNET_MQ_Envelope *env;
1711 GNUNET_SERVICE_client_drop (client);
1714 GNUNET_assert (GNUNET_NO == grp->is_disconnected);
1715 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1716 "%p got part request from client for group %s.\n",
1717 grp, GNUNET_h2s (&grp->pub_key_hash));
1718 grp->is_disconnected = GNUNET_YES;
1719 env = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_MULTICAST_PART_ACK);
1720 client_send_group (grp, env);
1721 GNUNET_SERVICE_client_continue (client);
1726 check_client_multicast_message (void *cls,
1727 const struct GNUNET_MULTICAST_MessageHeader *msg)
1734 * Incoming message from a client.
1737 handle_client_multicast_message (void *cls,
1738 const struct GNUNET_MULTICAST_MessageHeader *msg)
1740 // FIXME: what if GNUNET_YES == grp->is_disconnected? Do we allow sending messages?
1741 struct Client *c = cls;
1742 struct GNUNET_SERVICE_Client *client = c->client;
1743 struct Group *grp = c->group;
1748 GNUNET_SERVICE_client_drop (client);
1751 GNUNET_assert (GNUNET_YES == grp->is_origin);
1752 struct Origin *orig = grp->origin;
1754 // FIXME: use GNUNET_MQ_msg_copy
1755 /* FIXME: yucky, should use separate message structs for P2P and CS! */
1756 struct GNUNET_MULTICAST_MessageHeader *
1757 out = (struct GNUNET_MULTICAST_MessageHeader *) GNUNET_copy_message (&msg->header);
1758 out->fragment_id = GNUNET_htonll (++orig->max_fragment_id);
1759 out->purpose.size = htonl (ntohs (out->header.size)
1760 - sizeof (out->header)
1761 - sizeof (out->hop_counter)
1762 - sizeof (out->signature));
1763 out->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE);
1765 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_sign (&orig->priv_key, &out->purpose,
1771 client_send_all (&grp->pub_key_hash, GNUNET_MQ_msg_copy (&out->header));
1772 cadet_send_children (&grp->pub_key_hash, &out->header);
1773 client_send_ack (&grp->pub_key_hash);
1776 GNUNET_SERVICE_client_continue (client);
1781 check_client_multicast_request (void *cls,
1782 const struct GNUNET_MULTICAST_RequestHeader *req)
1789 * Incoming request from a client.
1792 handle_client_multicast_request (void *cls,
1793 const struct GNUNET_MULTICAST_RequestHeader *req)
1795 struct Client *c = cls;
1796 struct GNUNET_SERVICE_Client *client = c->client;
1797 struct Group *grp = c->group;
1802 GNUNET_SERVICE_client_drop (client);
1805 GNUNET_assert (GNUNET_NO == grp->is_disconnected);
1806 GNUNET_assert (GNUNET_NO == grp->is_origin);
1807 struct Member *mem = grp->member;
1809 /* FIXME: yucky, should use separate message structs for P2P and CS! */
1810 struct GNUNET_MULTICAST_RequestHeader *
1811 out = (struct GNUNET_MULTICAST_RequestHeader *) GNUNET_copy_message (&req->header);
1812 out->member_pub_key = mem->pub_key;
1813 out->fragment_id = GNUNET_ntohll (++mem->max_fragment_id);
1814 out->purpose.size = htonl (ntohs (out->header.size)
1815 - sizeof (out->header)
1816 - sizeof (out->member_pub_key)
1817 - sizeof (out->signature));
1818 out->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
1820 if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (&mem->priv_key, &out->purpose,
1826 uint8_t send_ack = GNUNET_YES;
1828 client_send_origin (&grp->pub_key_hash,
1829 GNUNET_MQ_msg_copy (&out->header)))
1830 { /* No local origins, send to remote origin */
1831 if (NULL != mem->origin_channel)
1833 cadet_send_channel (mem->origin_channel, &out->header);
1834 send_ack = GNUNET_NO;
1838 /* FIXME: not yet connected to origin */
1839 GNUNET_SERVICE_client_drop (client);
1844 if (GNUNET_YES == send_ack)
1846 client_send_ack (&grp->pub_key_hash);
1849 GNUNET_SERVICE_client_continue (client);
1854 * Incoming replay request from a client.
1857 handle_client_replay_request (void *cls,
1858 const struct MulticastReplayRequestMessage *rep)
1860 struct Client *c = cls;
1861 struct GNUNET_SERVICE_Client *client = c->client;
1862 struct Group *grp = c->group;
1867 GNUNET_SERVICE_client_drop (client);
1870 GNUNET_assert (GNUNET_NO == grp->is_disconnected);
1871 GNUNET_assert (GNUNET_NO == grp->is_origin);
1872 struct Member *mem = grp->member;
1874 struct GNUNET_CONTAINER_MultiHashMap *
1875 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
1876 &grp->pub_key_hash);
1877 if (NULL == grp_replay_req)
1879 grp_replay_req = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1880 GNUNET_CONTAINER_multihashmap_put (replay_req_client,
1881 &grp->pub_key_hash, grp_replay_req,
1882 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1885 struct GNUNET_HashCode key_hash;
1886 replay_key_hash (rep->fragment_id, rep->message_id, rep->fragment_offset,
1887 rep->flags, &key_hash);
1888 GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, client,
1889 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1892 client_send_origin (&grp->pub_key_hash,
1893 GNUNET_MQ_msg_copy (&rep->header)))
1894 { /* No local origin, replay from remote members / origin. */
1895 if (NULL != mem->origin_channel)
1897 cadet_send_channel (mem->origin_channel, &rep->header);
1901 /* FIXME: not yet connected to origin */
1904 GNUNET_SERVICE_client_drop (client);
1908 GNUNET_SERVICE_client_continue (client);
1913 cadet_send_replay_response_cb (void *cls,
1914 const struct GNUNET_HashCode *key_hash,
1917 struct Channel *chn = value;
1918 struct GNUNET_MessageHeader *msg = cls;
1920 cadet_send_channel (chn, msg);
1926 client_send_replay_response_cb (void *cls,
1927 const struct GNUNET_HashCode *key_hash,
1930 struct GNUNET_SERVICE_Client *client = value;
1931 struct GNUNET_MessageHeader *msg = cls;
1933 client_send (client, msg);
1939 check_client_replay_response_end (void *cls,
1940 const struct MulticastReplayResponseMessage *res)
1947 * End of replay response from a client.
1950 handle_client_replay_response_end (void *cls,
1951 const struct MulticastReplayResponseMessage *res)
1953 struct Client *c = cls;
1954 struct GNUNET_SERVICE_Client *client = c->client;
1955 struct Group *grp = c->group;
1960 GNUNET_SERVICE_client_drop (client);
1963 GNUNET_assert (GNUNET_NO == grp->is_disconnected);
1965 struct GNUNET_HashCode key_hash;
1966 replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset,
1967 res->flags, &key_hash);
1969 struct GNUNET_CONTAINER_MultiHashMap *
1970 grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
1971 &grp->pub_key_hash);
1972 if (NULL != grp_replay_req_cadet)
1974 GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_cadet, &key_hash);
1976 struct GNUNET_CONTAINER_MultiHashMap *
1977 grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
1978 &grp->pub_key_hash);
1979 if (NULL != grp_replay_req_client)
1981 GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_client, &key_hash);
1983 GNUNET_SERVICE_client_continue (client);
1988 check_client_replay_response (void *cls,
1989 const struct MulticastReplayResponseMessage *res)
1991 const struct GNUNET_MessageHeader *msg;
1992 if (GNUNET_MULTICAST_REC_OK == res->error_code)
1994 msg = GNUNET_MQ_extract_nested_mh (res);
1997 return GNUNET_SYSERR;
2005 * Incoming replay response from a client.
2007 * Respond with a multicast message on success, or otherwise with an error code.
2010 handle_client_replay_response (void *cls,
2011 const struct MulticastReplayResponseMessage *res)
2013 struct Client *c = cls;
2014 struct GNUNET_SERVICE_Client *client = c->client;
2015 struct Group *grp = c->group;
2020 GNUNET_SERVICE_client_drop (client);
2023 GNUNET_assert (GNUNET_NO == grp->is_disconnected);
2025 const struct GNUNET_MessageHeader *msg = &res->header;
2026 if (GNUNET_MULTICAST_REC_OK == res->error_code)
2028 msg = GNUNET_MQ_extract_nested_mh (res);
2031 struct GNUNET_HashCode key_hash;
2032 replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset,
2033 res->flags, &key_hash);
2035 struct GNUNET_CONTAINER_MultiHashMap *
2036 grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
2037 &grp->pub_key_hash);
2038 if (NULL != grp_replay_req_cadet)
2040 GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_cadet, &key_hash,
2041 cadet_send_replay_response_cb,
2044 if (GNUNET_MULTICAST_REC_OK == res->error_code)
2046 struct GNUNET_CONTAINER_MultiHashMap *
2047 grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
2048 &grp->pub_key_hash);
2049 if (NULL != grp_replay_req_client)
2051 GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_client, &key_hash,
2052 client_send_replay_response_cb,
2058 handle_client_replay_response_end (c, res);
2061 GNUNET_SERVICE_client_continue (client);
2066 * A new client connected.
2069 * @param client client to add
2070 * @param mq message queue for @a client
2074 client_notify_connect (void *cls,
2075 struct GNUNET_SERVICE_Client *client,
2076 struct GNUNET_MQ_Handle *mq)
2078 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client connected: %p\n", client);
2079 /* FIXME: send connect ACK */
2081 struct Client *c = GNUNET_new (struct Client);
2089 * Called whenever a client is disconnected.
2090 * Frees our resources associated with that client.
2092 * @param cls closure
2093 * @param client identification of the client
2094 * @param app_ctx must match @a client
2097 client_notify_disconnect (void *cls,
2098 struct GNUNET_SERVICE_Client *client,
2101 struct Client *c = app_ctx;
2102 struct Group *grp = c->group;
2107 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2108 "%p User context is NULL in client_disconnect()\n", grp);
2113 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2114 "%p Client (%s) disconnected from group %s\n",
2115 grp, (GNUNET_YES == grp->is_origin) ? "origin" : "member",
2116 GNUNET_h2s (&grp->pub_key_hash));
2118 // FIXME (due to protocol change): here we must not remove all clients,
2119 // only the one we were notified about!
2120 struct ClientList *cl = grp->clients_head;
2123 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2124 "iterating clients for group %p\n",
2126 if (cl->client == client)
2128 GNUNET_CONTAINER_DLL_remove (grp->clients_head, grp->clients_tail, cl);
2135 while (GNUNET_YES == replay_req_remove_client (grp, client));
2137 if (NULL == grp->clients_head)
2138 { /* Last client disconnected. */
2139 cleanup_group (grp);
2147 * @param cls closure
2148 * @param server the initialized server
2149 * @param cfg configuration to use
2153 const struct GNUNET_CONFIGURATION_Handle *c,
2154 struct GNUNET_SERVICE_Handle *svc)
2158 GNUNET_CRYPTO_get_peer_identity (cfg, &this_peer);
2160 stats = GNUNET_STATISTICS_create ("multicast", cfg);
2161 origins = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
2162 members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
2163 group_members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
2164 channels_in = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
2165 channels_out = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
2166 replay_req_cadet = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
2167 replay_req_client = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
2169 cadet = GNUNET_CADET_connect (cfg);
2171 GNUNET_assert (NULL != cadet);
2173 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
2179 * Define "main" method using service macro.
2183 GNUNET_SERVICE_OPTION_NONE,
2185 &client_notify_connect,
2186 &client_notify_disconnect,
2188 GNUNET_MQ_hd_fixed_size (client_origin_start,
2189 GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START,
2190 struct MulticastOriginStartMessage,
2192 GNUNET_MQ_hd_var_size (client_member_join,
2193 GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_JOIN,
2194 struct MulticastMemberJoinMessage,
2196 GNUNET_MQ_hd_var_size (client_join_decision,
2197 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION,
2198 struct MulticastJoinDecisionMessageHeader,
2200 GNUNET_MQ_hd_fixed_size (client_part_request,
2201 GNUNET_MESSAGE_TYPE_MULTICAST_PART_REQUEST,
2202 struct GNUNET_MessageHeader,
2204 GNUNET_MQ_hd_var_size (client_multicast_message,
2205 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE,
2206 struct GNUNET_MULTICAST_MessageHeader,
2208 GNUNET_MQ_hd_var_size (client_multicast_request,
2209 GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST,
2210 struct GNUNET_MULTICAST_RequestHeader,
2212 GNUNET_MQ_hd_fixed_size (client_replay_request,
2213 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST,
2214 struct MulticastReplayRequestMessage,
2216 GNUNET_MQ_hd_var_size (client_replay_response,
2217 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE,
2218 struct MulticastReplayResponseMessage,
2220 GNUNET_MQ_hd_var_size (client_replay_response_end,
2221 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE_END,
2222 struct MulticastReplayResponseMessage,
2225 /* end of gnunet-service-multicast.c */