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_core_service.h"
32 #include "gnunet_cadet_service.h"
33 #include "gnunet_multicast_service.h"
34 #include "multicast.h"
37 * Handle to our current configuration.
39 static const struct GNUNET_CONFIGURATION_Handle *cfg;
44 static struct GNUNET_SERVER_Handle *server;
48 * Only used during initialization.
50 static struct GNUNET_CORE_Handle *core;
55 static struct GNUNET_CADET_Handle *cadet;
58 * Identity of this peer.
60 static struct GNUNET_PeerIdentity this_peer;
63 * Handle to the statistics service.
65 static struct GNUNET_STATISTICS_Handle *stats;
68 * Notification context, simplifies client broadcasts.
70 static struct GNUNET_SERVER_NotificationContext *nc;
73 * All connected origin clients.
74 * Group's pub_key_hash -> struct Origin * (uniq)
76 static struct GNUNET_CONTAINER_MultiHashMap *origins;
79 * All connected member clients.
80 * Group's pub_key_hash -> struct Member * (multi)
82 static struct GNUNET_CONTAINER_MultiHashMap *members;
85 * Connected member clients per group.
86 * Group's pub_key_hash -> Member's pub_key_hash (uniq) -> struct Member * (uniq)
88 static struct GNUNET_CONTAINER_MultiHashMap *group_members;
91 * Incoming CADET channels with connected children in the tree.
92 * Group's pub_key_hash -> struct Channel * (multi)
94 static struct GNUNET_CONTAINER_MultiHashMap *channels_in;
97 * Outgoing CADET channels connecting to parents in the tree.
98 * Group's pub_key_hash -> struct Channel * (multi)
100 static struct GNUNET_CONTAINER_MultiHashMap *channels_out;
103 * Incoming replay requests from CADET.
104 * Group's pub_key_hash ->
105 * H(fragment_id, message_id, fragment_offset, flags) -> struct Channel *
107 static struct GNUNET_CONTAINER_MultiHashMap *replay_req_cadet;
110 * Incoming replay requests from clients.
111 * Group's pub_key_hash ->
112 * H(fragment_id, message_id, fragment_offset, flags) -> struct GNUNET_SERVER_Client *
114 static struct GNUNET_CONTAINER_MultiHashMap *replay_req_client;
118 * Join status of a remote peer.
128 enum ChannelDirection
136 * Context for a CADET channel.
141 * Group the channel belongs to.
143 * Only set for outgoing channels.
150 struct GNUNET_CADET_Channel *channel;
153 * CADET transmission handle.
155 struct GNUNET_CADET_TransmitHandle *tmit_handle;
158 * Public key of the target group.
160 struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key;
163 * Hash of @a group_pub_key.
165 struct GNUNET_HashCode group_pub_hash;
168 * Public key of the joining member.
170 struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key;
173 * Remote peer identity.
175 struct GNUNET_PeerIdentity peer;
178 * Is the remote peer admitted to the group?
179 * @see enum JoinStatus
184 * Number of messages waiting to be sent to CADET.
186 uint8_t msgs_pending;
190 * @see enum ChannelDirection
197 * List of connected clients.
201 struct ClientList *prev;
202 struct ClientList *next;
203 struct GNUNET_SERVER_Client *client;
207 * Common part of the client context for both an origin and member.
211 struct ClientList *clients_head;
212 struct ClientList *clients_tail;
215 * Public key of the group.
217 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
220 * Hash of @a pub_key.
222 struct GNUNET_HashCode pub_key_hash;
227 struct GNUNET_HashCode cadet_port_hash;
230 * Is this an origin (#GNUNET_YES), or member (#GNUNET_NO)?
235 * Is the client disconnected? #GNUNET_YES or #GNUNET_NO
237 uint8_t disconnected;
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;
327 struct ReplayRequestKey
329 uint64_t fragment_id;
331 uint64_t fragment_offset;
337 * Task run during shutdown.
342 shutdown_task (void *cls)
346 GNUNET_CORE_disconnecT (core);
351 GNUNET_CADET_disconnect (cadet);
356 GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
359 /* FIXME: do more clean up here */
364 * Clean up origin data structures after a client disconnected.
367 cleanup_origin (struct Origin *orig)
369 struct Group *grp = &orig->grp;
370 GNUNET_CONTAINER_multihashmap_remove (origins, &grp->pub_key_hash, orig);
371 if (NULL != orig->cadet_port)
373 GNUNET_CADET_close_port (orig->cadet_port);
374 orig->cadet_port = NULL;
381 * Clean up member data structures after a client disconnected.
384 cleanup_member (struct Member *mem)
386 struct Group *grp = &mem->grp;
387 struct GNUNET_CONTAINER_MultiHashMap *
388 grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members,
390 GNUNET_assert (NULL != grp_mem);
391 GNUNET_CONTAINER_multihashmap_remove (grp_mem, &mem->pub_key_hash, mem);
393 if (0 == GNUNET_CONTAINER_multihashmap_size (grp_mem))
395 GNUNET_CONTAINER_multihashmap_remove (group_members, &grp->pub_key_hash,
397 GNUNET_CONTAINER_multihashmap_destroy (grp_mem);
399 if (NULL != mem->join_dcsn)
401 GNUNET_free (mem->join_dcsn);
402 mem->join_dcsn = NULL;
404 GNUNET_CONTAINER_multihashmap_remove (members, &grp->pub_key_hash, mem);
410 * Clean up group data structures after a client disconnected.
413 cleanup_group (struct Group *grp)
415 (GNUNET_YES == grp->is_origin)
416 ? cleanup_origin ((struct Origin *) grp)
417 : cleanup_member ((struct Member *) grp);
422 replay_key_hash (uint64_t fragment_id, uint64_t message_id,
423 uint64_t fragment_offset, uint64_t flags,
424 struct GNUNET_HashCode *key_hash)
426 struct ReplayRequestKey key = {
427 .fragment_id = fragment_id,
428 .message_id = message_id,
429 .fragment_offset = fragment_offset,
432 GNUNET_CRYPTO_hash (&key, sizeof (key), key_hash);
437 * Remove channel from replay request hashmap.
442 * @return #GNUNET_YES if there are more entries to process,
443 * #GNUNET_NO when reached end of hashmap.
446 replay_req_remove_cadet (struct Channel *chn)
448 struct GNUNET_CONTAINER_MultiHashMap *
449 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
450 &chn->grp->pub_key_hash);
451 if (NULL == grp_replay_req)
454 struct GNUNET_CONTAINER_MultiHashMapIterator *
455 it = GNUNET_CONTAINER_multihashmap_iterator_create (grp_replay_req);
456 struct GNUNET_HashCode key;
457 const struct Channel *c;
459 == GNUNET_CONTAINER_multihashmap_iterator_next (it, &key,
464 GNUNET_CONTAINER_multihashmap_remove (grp_replay_req, &key, chn);
465 GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
469 GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
475 * Remove client from replay request hashmap.
480 * @return #GNUNET_YES if there are more entries to process,
481 * #GNUNET_NO when reached end of hashmap.
484 replay_req_remove_client (struct Group *grp, struct GNUNET_SERVER_Client *client)
486 struct GNUNET_CONTAINER_MultiHashMap *
487 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
489 if (NULL == grp_replay_req)
492 struct GNUNET_CONTAINER_MultiHashMapIterator *
493 it = GNUNET_CONTAINER_multihashmap_iterator_create (grp_replay_req);
494 struct GNUNET_HashCode key;
495 const struct GNUNET_SERVER_Client *c;
497 == GNUNET_CONTAINER_multihashmap_iterator_next (it, &key,
502 GNUNET_CONTAINER_multihashmap_remove (replay_req_client, &key, client);
503 GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
507 GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
513 * Called whenever a client is disconnected.
515 * Frees our resources associated with that client.
517 * @param cls Closure.
518 * @param client Client handle.
521 client_notify_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
527 = GNUNET_SERVER_client_get_user_context (client, struct Group);
531 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
532 "%p User context is NULL in client_disconnect()\n", grp);
537 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
538 "%p Client (%s) disconnected from group %s\n",
539 grp, (GNUNET_YES == grp->is_origin) ? "origin" : "member",
540 GNUNET_h2s (&grp->pub_key_hash));
542 struct ClientList *cl = grp->clients_head;
545 if (cl->client == client)
547 GNUNET_CONTAINER_DLL_remove (grp->clients_head, grp->clients_tail, cl);
554 while (GNUNET_YES == replay_req_remove_client (grp, client));
556 if (NULL == grp->clients_head)
557 { /* Last client disconnected. */
559 if (NULL != grp->tmit_head)
560 { /* Send pending messages via CADET before cleanup. */
561 transmit_message (grp);
573 * Send message to a client.
576 client_send (struct GNUNET_SERVER_Client *client,
577 const struct GNUNET_MessageHeader *msg)
579 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
580 "%p Sending message to client.\n", client);
582 GNUNET_SERVER_notification_context_add (nc, client);
583 GNUNET_SERVER_notification_context_unicast (nc, client, msg, GNUNET_NO);
588 * Send message to all clients connected to the group.
591 client_send_group (const struct Group *grp,
592 const struct GNUNET_MessageHeader *msg)
594 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
595 "%p Sending message to all clients of the group.\n", grp);
597 struct ClientList *cl = grp->clients_head;
600 GNUNET_SERVER_notification_context_add (nc, cl->client);
601 GNUNET_SERVER_notification_context_unicast (nc, cl->client, msg, GNUNET_NO);
608 * Iterator callback for sending a message to origin clients.
611 client_send_origin_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
614 const struct GNUNET_MessageHeader *msg = cls;
615 struct Member *orig = origin;
617 client_send_group (&orig->grp, msg);
623 * Iterator callback for sending a message to member clients.
626 client_send_member_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
629 const struct GNUNET_MessageHeader *msg = cls;
630 struct Member *mem = member;
632 if (NULL != mem->join_dcsn)
633 { /* Only send message to admitted members */
634 client_send_group (&mem->grp, msg);
641 * Send message to all origin and member clients connected to the group.
643 * @param pub_key_hash
644 * H(key_pub) of the group.
649 client_send_all (struct GNUNET_HashCode *pub_key_hash,
650 const struct GNUNET_MessageHeader *msg)
653 n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash,
654 client_send_origin_cb,
656 n += GNUNET_CONTAINER_multihashmap_get_multiple (members, pub_key_hash,
657 client_send_member_cb,
664 * Send message to a random origin client or a random member client.
666 * @param grp The group to send @a msg to.
667 * @param msg Message to send.
670 client_send_random (struct GNUNET_HashCode *pub_key_hash,
671 const struct GNUNET_MessageHeader *msg)
674 n = GNUNET_CONTAINER_multihashmap_get_random (origins, client_send_origin_cb,
677 n = GNUNET_CONTAINER_multihashmap_get_random (members, client_send_member_cb,
684 * Send message to all origin clients connected to the group.
686 * @param pub_key_hash
687 * H(key_pub) of the group.
692 client_send_origin (struct GNUNET_HashCode *pub_key_hash,
693 const struct GNUNET_MessageHeader *msg)
696 n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash,
697 client_send_origin_cb,
704 * Send fragment acknowledgement to all clients of the channel.
706 * @param pub_key_hash
707 * H(key_pub) of the group.
710 client_send_ack (struct GNUNET_HashCode *pub_key_hash)
712 static struct GNUNET_MessageHeader *msg = NULL;
715 msg = GNUNET_malloc (sizeof (*msg));
716 msg->type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_FRAGMENT_ACK);
717 msg->size = htons (sizeof (*msg));
719 client_send_all (pub_key_hash, msg);
723 struct CadetTransmitClosure
726 const struct GNUNET_MessageHeader *msg;
731 * CADET is ready to transmit a message.
734 cadet_notify_transmit_ready (void *cls, size_t buf_size, void *buf)
738 /* FIXME: connection closed */
741 struct CadetTransmitClosure *tcls = cls;
742 struct Channel *chn = tcls->chn;
743 uint16_t msg_size = ntohs (tcls->msg->size);
744 GNUNET_assert (msg_size <= buf_size);
745 GNUNET_memcpy (buf, tcls->msg, msg_size);
748 if (0 == chn->msgs_pending)
752 else if (0 == --chn->msgs_pending)
754 client_send_ack (&chn->group_pub_hash);
761 * Send a message to a CADET channel.
763 * @param chn Channel.
764 * @param msg Message.
767 cadet_send_channel (struct Channel *chn, const struct GNUNET_MessageHeader *msg)
769 struct CadetTransmitClosure *tcls = GNUNET_malloc (sizeof (*tcls));
775 = GNUNET_CADET_notify_transmit_ready (chn->channel, GNUNET_NO,
776 GNUNET_TIME_UNIT_FOREVER_REL,
778 &cadet_notify_transmit_ready,
780 GNUNET_assert (NULL != chn->tmit_handle);
785 * Create new outgoing CADET channel.
788 * Peer to connect to.
789 * @param group_pub_key
790 * Public key of group the channel belongs to.
791 * @param group_pub_hash
792 * Hash of @a group_pub_key.
796 static struct Channel *
797 cadet_channel_create (struct Group *grp, struct GNUNET_PeerIdentity *peer)
799 struct Channel *chn = GNUNET_malloc (sizeof (*chn));
801 chn->group_pub_key = grp->pub_key;
802 chn->group_pub_hash = grp->pub_key_hash;
804 chn->direction = DIR_OUTGOING;
805 chn->join_status = JOIN_WAITING;
806 chn->channel = GNUNET_CADET_channel_create (cadet, chn, &chn->peer,
807 &grp->cadet_port_hash,
808 GNUNET_CADET_OPTION_RELIABLE);
809 GNUNET_CONTAINER_multihashmap_put (channels_out, &chn->group_pub_hash, chn,
810 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
816 * Create CADET channel and send a join request.
819 cadet_send_join_request (struct Member *mem)
821 mem->origin_channel = cadet_channel_create (&mem->grp, &mem->origin);
822 cadet_send_channel (mem->origin_channel, &mem->join_req->header);
825 for (i = 0; i < mem->relay_count; i++)
828 chn = cadet_channel_create (&mem->grp, &mem->relays[i]);
829 cadet_send_channel (chn, &mem->join_req->header);
835 cadet_send_join_decision_cb (void *cls,
836 const struct GNUNET_HashCode *group_pub_hash,
839 const struct MulticastJoinDecisionMessageHeader *hdcsn = cls;
840 struct Channel *chn = channel;
842 if (0 == memcmp (&hdcsn->member_pub_key, &chn->member_pub_key, sizeof (chn->member_pub_key))
843 && 0 == memcmp (&hdcsn->peer, &chn->peer, sizeof (chn->peer)))
845 cadet_send_channel (chn, &hdcsn->header);
853 * Send join decision to a remote peer.
856 cadet_send_join_decision (struct Group *grp,
857 const struct MulticastJoinDecisionMessageHeader *hdcsn)
859 GNUNET_CONTAINER_multihashmap_get_multiple (channels_in, &grp->pub_key_hash,
860 &cadet_send_join_decision_cb,
866 * Iterator callback for sending a message to origin clients.
869 cadet_send_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
872 const struct GNUNET_MessageHeader *msg = cls;
873 struct Channel *chn = channel;
874 if (JOIN_ADMITTED == chn->join_status)
875 cadet_send_channel (chn, msg);
881 * Send message to all connected children.
884 cadet_send_children (struct GNUNET_HashCode *pub_key_hash,
885 const struct GNUNET_MessageHeader *msg)
888 if (channels_in != NULL)
889 n += GNUNET_CONTAINER_multihashmap_get_multiple (channels_in, pub_key_hash,
890 cadet_send_cb, (void *) msg);
895 #if 0 // unused as yet
897 * Send message to all connected parents.
900 cadet_send_parents (struct GNUNET_HashCode *pub_key_hash,
901 const struct GNUNET_MessageHeader *msg)
904 if (channels_in != NULL)
905 n += GNUNET_CONTAINER_multihashmap_get_multiple (channels_out, pub_key_hash,
906 cadet_send_cb, (void *) msg);
913 * New incoming CADET channel.
916 cadet_notify_channel_new (void *cls,
917 struct GNUNET_CADET_Channel *channel,
918 const struct GNUNET_PeerIdentity *initiator,
919 const struct GNUNET_HashCode *port,
920 enum GNUNET_CADET_ChannelOption options)
927 * CADET channel is being destroyed.
930 cadet_notify_channel_end (void *cls,
931 const struct GNUNET_CADET_Channel *channel,
937 struct Channel *chn = ctx;
938 if (NULL != chn->grp)
940 if (GNUNET_NO == chn->grp->is_origin)
942 struct Member *mem = (struct Member *) chn->grp;
943 if (chn == mem->origin_channel)
944 mem->origin_channel = NULL;
948 while (GNUNET_YES == replay_req_remove_cadet (chn));
955 group_set_cadet_port_hash (struct Group *grp)
958 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
962 GNUNET_APPLICATION_TYPE_MULTICAST,
964 GNUNET_CRYPTO_hash (&port, sizeof (port), &grp->cadet_port_hash);
969 * Handle a connecting client starting an origin.
972 client_recv_origin_start (void *cls, struct GNUNET_SERVER_Client *client,
973 const struct GNUNET_MessageHeader *m)
975 const struct MulticastOriginStartMessage *
976 msg = (const struct MulticastOriginStartMessage *) m;
978 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
979 struct GNUNET_HashCode pub_key_hash;
981 GNUNET_CRYPTO_eddsa_key_get_public (&msg->group_key, &pub_key);
982 GNUNET_CRYPTO_hash (&pub_key, sizeof (pub_key), &pub_key_hash);
985 orig = GNUNET_CONTAINER_multihashmap_get (origins, &pub_key_hash);
990 orig = GNUNET_new (struct Origin);
991 orig->priv_key = msg->group_key;
992 orig->max_fragment_id = GNUNET_ntohll (msg->max_fragment_id);
994 grp->is_origin = GNUNET_YES;
995 grp->pub_key = pub_key;
996 grp->pub_key_hash = pub_key_hash;
998 GNUNET_CONTAINER_multihashmap_put (origins, &grp->pub_key_hash, orig,
999 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1001 group_set_cadet_port_hash (grp);
1002 orig->cadet_port = GNUNET_CADET_open_port (cadet, &grp->cadet_port_hash,
1003 cadet_notify_channel_new, NULL);
1010 struct ClientList *cl = GNUNET_new (struct ClientList);
1011 cl->client = client;
1012 GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl);
1014 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1015 "%p Client connected as origin to group %s.\n",
1016 orig, GNUNET_h2s (&grp->pub_key_hash));
1018 GNUNET_SERVER_client_set_user_context (client, grp);
1019 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1024 * Handle a connecting client joining a group.
1027 client_recv_member_join (void *cls, struct GNUNET_SERVER_Client *client,
1028 const struct GNUNET_MessageHeader *m)
1030 const struct MulticastMemberJoinMessage *
1031 msg = (const struct MulticastMemberJoinMessage *) m;
1032 uint16_t msg_size = ntohs (msg->header.size);
1034 struct GNUNET_CRYPTO_EcdsaPublicKey mem_pub_key;
1035 struct GNUNET_HashCode pub_key_hash, mem_pub_key_hash;
1037 GNUNET_CRYPTO_ecdsa_key_get_public (&msg->member_key, &mem_pub_key);
1038 GNUNET_CRYPTO_hash (&mem_pub_key, sizeof (mem_pub_key), &mem_pub_key_hash);
1039 GNUNET_CRYPTO_hash (&msg->group_pub_key, sizeof (msg->group_pub_key), &pub_key_hash);
1041 struct GNUNET_CONTAINER_MultiHashMap *
1042 grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members, &pub_key_hash);
1043 struct Member *mem = NULL;
1046 if (NULL != grp_mem)
1048 mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &mem_pub_key_hash);
1052 mem = GNUNET_new (struct Member);
1053 mem->priv_key = msg->member_key;
1054 mem->pub_key = mem_pub_key;
1055 mem->pub_key_hash = mem_pub_key_hash;
1056 mem->max_fragment_id = 0; // FIXME
1059 grp->is_origin = GNUNET_NO;
1060 grp->pub_key = msg->group_pub_key;
1061 grp->pub_key_hash = pub_key_hash;
1062 group_set_cadet_port_hash (grp);
1064 if (NULL == grp_mem)
1066 grp_mem = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1067 GNUNET_CONTAINER_multihashmap_put (group_members, &grp->pub_key_hash, grp_mem,
1068 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1070 GNUNET_CONTAINER_multihashmap_put (grp_mem, &mem->pub_key_hash, mem,
1071 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1072 GNUNET_CONTAINER_multihashmap_put (members, &grp->pub_key_hash, mem,
1073 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1080 struct ClientList *cl = GNUNET_new (struct ClientList);
1081 cl->client = client;
1082 GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl);
1084 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1085 "%p Client connected to group %s..\n",
1086 mem, GNUNET_h2s (&grp->pub_key_hash));
1087 char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&mem->pub_key);
1088 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1089 "%p ..as member %s (%s).\n",
1090 mem, GNUNET_h2s (&mem->pub_key_hash), str);
1093 GNUNET_SERVER_client_set_user_context (client, grp);
1095 if (NULL != mem->join_dcsn)
1096 { /* Already got a join decision, send it to client. */
1097 GNUNET_SERVER_notification_context_add (nc, client);
1098 GNUNET_SERVER_notification_context_unicast (nc, client,
1099 (struct GNUNET_MessageHeader *)
1104 { /* First client of the group, send join request. */
1105 struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1];
1106 uint32_t relay_count = ntohl (msg->relay_count);
1107 uint16_t relay_size = relay_count * sizeof (*relays);
1108 struct GNUNET_MessageHeader *join_msg = NULL;
1109 uint16_t join_msg_size = 0;
1110 if (sizeof (*msg) + relay_size + sizeof (struct GNUNET_MessageHeader)
1113 join_msg = (struct GNUNET_MessageHeader *)
1114 (((char *) &msg[1]) + relay_size);
1115 join_msg_size = ntohs (join_msg->size);
1117 if (sizeof (*msg) + relay_size + join_msg_size != msg_size)
1120 GNUNET_SERVER_client_disconnect (client);
1124 struct MulticastJoinRequestMessage *
1125 req = GNUNET_malloc (sizeof (*req) + join_msg_size);
1126 req->header.size = htons (sizeof (*req) + join_msg_size);
1127 req->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST);
1128 req->group_pub_key = grp->pub_key;
1129 req->peer = this_peer;
1130 GNUNET_CRYPTO_ecdsa_key_get_public (&mem->priv_key, &req->member_pub_key);
1131 if (0 < join_msg_size)
1132 GNUNET_memcpy (&req[1], join_msg, join_msg_size);
1134 req->member_pub_key = mem->pub_key;
1135 req->purpose.size = htonl (msg_size
1136 - sizeof (req->header)
1137 - sizeof (req->reserved)
1138 - sizeof (req->signature));
1139 req->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
1141 if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (&mem->priv_key, &req->purpose,
1144 /* FIXME: handle error */
1148 if (NULL != mem->join_req)
1149 GNUNET_free (mem->join_req);
1150 mem->join_req = req;
1152 if (0 == client_send_origin (&grp->pub_key_hash, &mem->join_req->header))
1153 { /* No local origins, send to remote origin */
1154 cadet_send_join_request (mem);
1157 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1162 client_send_join_decision (struct Member *mem,
1163 const struct MulticastJoinDecisionMessageHeader *hdcsn)
1165 client_send_group (&mem->grp, &hdcsn->header);
1167 const struct MulticastJoinDecisionMessage *
1168 dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1];
1169 if (GNUNET_YES == ntohl (dcsn->is_admitted))
1170 { /* Member admitted, store join_decision. */
1171 uint16_t dcsn_size = ntohs (dcsn->header.size);
1172 mem->join_dcsn = GNUNET_malloc (dcsn_size);
1173 GNUNET_memcpy (mem->join_dcsn, dcsn, dcsn_size);
1176 { /* Refused entry, but replay would be still possible for past members. */
1182 * Join decision from client.
1185 client_recv_join_decision (void *cls, struct GNUNET_SERVER_Client *client,
1186 const struct GNUNET_MessageHeader *m)
1189 grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
1190 const struct MulticastJoinDecisionMessageHeader *
1191 hdcsn = (const struct MulticastJoinDecisionMessageHeader *) m;
1196 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1199 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1200 "%p Got join decision from client for group %s..\n",
1201 grp, GNUNET_h2s (&grp->pub_key_hash));
1203 struct GNUNET_CONTAINER_MultiHashMap *
1204 grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members,
1205 &grp->pub_key_hash);
1206 struct Member *mem = NULL;
1207 if (NULL != grp_mem)
1209 struct GNUNET_HashCode member_key_hash;
1210 GNUNET_CRYPTO_hash (&hdcsn->member_pub_key, sizeof (hdcsn->member_pub_key),
1212 mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &member_key_hash);
1213 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1214 "%p ..and member %s: %p\n",
1215 grp, GNUNET_h2s (&member_key_hash), mem);
1218 { /* Found local member */
1219 client_send_join_decision (mem, hdcsn);
1222 { /* Look for remote member */
1223 cadet_send_join_decision (grp, hdcsn);
1225 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1230 * Incoming message from a client.
1233 client_recv_multicast_message (void *cls, struct GNUNET_SERVER_Client *client,
1234 const struct GNUNET_MessageHeader *m)
1237 grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
1238 struct GNUNET_MULTICAST_MessageHeader *out;
1239 struct Origin *orig;
1244 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1247 GNUNET_assert (GNUNET_YES == grp->is_origin);
1248 orig = (struct Origin *) grp;
1250 /* FIXME: yucky, should use separate message structs for P2P and CS! */
1251 out = (struct GNUNET_MULTICAST_MessageHeader *) GNUNET_copy_message (m);
1252 out->fragment_id = GNUNET_htonll (++orig->max_fragment_id);
1253 out->purpose.size = htonl (ntohs (out->header.size)
1254 - sizeof (out->header)
1255 - sizeof (out->hop_counter)
1256 - sizeof (out->signature));
1257 out->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE);
1259 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_sign (&orig->priv_key, &out->purpose,
1265 client_send_all (&grp->pub_key_hash, &out->header);
1266 if (0 == cadet_send_children (&grp->pub_key_hash, &out->header))
1268 client_send_ack (&grp->pub_key_hash);
1272 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1277 * Incoming request from a client.
1280 client_recv_multicast_request (void *cls, struct GNUNET_SERVER_Client *client,
1281 const struct GNUNET_MessageHeader *m)
1283 struct Group *grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
1285 struct GNUNET_MULTICAST_RequestHeader *out;
1289 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1292 GNUNET_assert (GNUNET_NO == grp->is_origin);
1293 mem = (struct Member *) grp;
1295 /* FIXME: yucky, should use separate message structs for P2P and CS! */
1296 out = (struct GNUNET_MULTICAST_RequestHeader *) GNUNET_copy_message (m);
1297 out->member_pub_key = mem->pub_key;
1298 out->fragment_id = GNUNET_ntohll (++mem->max_fragment_id);
1299 out->purpose.size = htonl (ntohs (out->header.size)
1300 - sizeof (out->header)
1301 - sizeof (out->member_pub_key)
1302 - sizeof (out->signature));
1303 out->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
1305 if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (&mem->priv_key, &out->purpose,
1311 uint8_t send_ack = GNUNET_YES;
1312 if (0 == client_send_origin (&grp->pub_key_hash, &out->header))
1313 { /* No local origins, send to remote origin */
1314 if (NULL != mem->origin_channel)
1316 cadet_send_channel (mem->origin_channel, &out->header);
1317 send_ack = GNUNET_NO;
1321 /* FIXME: not yet connected to origin */
1322 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1327 if (GNUNET_YES == send_ack)
1329 client_send_ack (&grp->pub_key_hash);
1332 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1337 * Incoming replay request from a client.
1340 client_recv_replay_request (void *cls, struct GNUNET_SERVER_Client *client,
1341 const struct GNUNET_MessageHeader *m)
1343 struct Group *grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
1348 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1351 GNUNET_assert (GNUNET_NO == grp->is_origin);
1352 mem = (struct Member *) grp;
1354 struct GNUNET_CONTAINER_MultiHashMap *
1355 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
1356 &grp->pub_key_hash);
1357 if (NULL == grp_replay_req)
1359 grp_replay_req = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1360 GNUNET_CONTAINER_multihashmap_put (replay_req_client,
1361 &grp->pub_key_hash, grp_replay_req,
1362 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1364 struct MulticastReplayRequestMessage *
1365 rep = (struct MulticastReplayRequestMessage *) m;
1366 struct GNUNET_HashCode key_hash;
1367 replay_key_hash (rep->fragment_id, rep->message_id, rep->fragment_offset,
1368 rep->flags, &key_hash);
1369 GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, client,
1370 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1372 if (0 == client_send_origin (&grp->pub_key_hash, m))
1373 { /* No local origin, replay from remote members / origin. */
1374 if (NULL != mem->origin_channel)
1376 cadet_send_channel (mem->origin_channel, m);
1380 /* FIXME: not yet connected to origin */
1381 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1385 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1390 cadet_send_replay_response_cb (void *cls,
1391 const struct GNUNET_HashCode *key_hash,
1394 struct Channel *chn = value;
1395 struct GNUNET_MessageHeader *msg = cls;
1397 cadet_send_channel (chn, msg);
1403 client_send_replay_response_cb (void *cls,
1404 const struct GNUNET_HashCode *key_hash,
1407 struct GNUNET_SERVER_Client *client = value;
1408 struct GNUNET_MessageHeader *msg = cls;
1410 client_send (client, msg);
1416 * End of replay response from a client.
1419 client_recv_replay_response_end (void *cls, struct GNUNET_SERVER_Client *client,
1420 const struct GNUNET_MessageHeader *m)
1422 struct Group *grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
1426 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1430 struct MulticastReplayResponseMessage *
1431 res = (struct MulticastReplayResponseMessage *) m;
1433 struct GNUNET_HashCode key_hash;
1434 replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset,
1435 res->flags, &key_hash);
1437 struct GNUNET_CONTAINER_MultiHashMap *
1438 grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
1439 &grp->pub_key_hash);
1440 if (NULL != grp_replay_req_cadet)
1442 GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_cadet, &key_hash);
1444 struct GNUNET_CONTAINER_MultiHashMap *
1445 grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
1446 &grp->pub_key_hash);
1447 if (NULL != grp_replay_req_client)
1449 GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_client, &key_hash);
1451 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1456 * Incoming replay response from a client.
1458 * Respond with a multicast message on success, or otherwise with an error code.
1461 client_recv_replay_response (void *cls, struct GNUNET_SERVER_Client *client,
1462 const struct GNUNET_MessageHeader *m)
1464 struct Group *grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
1468 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1472 struct MulticastReplayResponseMessage *
1473 res = (struct MulticastReplayResponseMessage *) m;
1475 const struct GNUNET_MessageHeader *msg = m;
1476 if (GNUNET_MULTICAST_REC_OK == res->error_code)
1478 msg = (struct GNUNET_MessageHeader *) &res[1];
1481 struct GNUNET_HashCode key_hash;
1482 replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset,
1483 res->flags, &key_hash);
1485 struct GNUNET_CONTAINER_MultiHashMap *
1486 grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
1487 &grp->pub_key_hash);
1488 if (NULL != grp_replay_req_cadet)
1490 GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_cadet, &key_hash,
1491 cadet_send_replay_response_cb,
1494 if (GNUNET_MULTICAST_REC_OK == res->error_code)
1496 struct GNUNET_CONTAINER_MultiHashMap *
1497 grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
1498 &grp->pub_key_hash);
1499 if (NULL != grp_replay_req_client)
1501 GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_client, &key_hash,
1502 client_send_replay_response_cb,
1508 client_recv_replay_response_end (cls, client, m);
1511 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1516 * A new client connected.
1519 client_notify_connect (void *cls, struct GNUNET_SERVER_Client *client)
1521 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client connected: %p\n", client);
1522 /* FIXME: send connect ACK */
1527 * Message handlers for the server.
1529 static const struct GNUNET_SERVER_MessageHandler server_handlers[] = {
1530 { client_recv_origin_start, NULL,
1531 GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START, 0 },
1533 { client_recv_member_join, NULL,
1534 GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_JOIN, 0 },
1536 { client_recv_join_decision, NULL,
1537 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION, 0 },
1539 { client_recv_multicast_message, NULL,
1540 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, 0 },
1542 { client_recv_multicast_request, NULL,
1543 GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST, 0 },
1545 { client_recv_replay_request, NULL,
1546 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST, 0 },
1548 { client_recv_replay_response, NULL,
1549 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE, 0 },
1551 { client_recv_replay_response_end, NULL,
1552 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE_END, 0 },
1554 { NULL, NULL, 0, 0 }
1559 * Incoming join request message from CADET.
1562 cadet_recv_join_request (void *cls,
1563 struct GNUNET_CADET_Channel *channel,
1565 const struct GNUNET_MessageHeader *m)
1567 const struct MulticastJoinRequestMessage *
1568 req = (const struct MulticastJoinRequestMessage *) m;
1569 uint16_t size = ntohs (m->size);
1570 if (size < sizeof (*req))
1572 GNUNET_break_op (0);
1573 return GNUNET_SYSERR;
1577 GNUNET_break_op (0);
1578 return GNUNET_SYSERR;
1580 if (ntohl (req->purpose.size) != (size
1581 - sizeof (req->header)
1582 - sizeof (req->reserved)
1583 - sizeof (req->signature)))
1585 GNUNET_break_op (0);
1586 return GNUNET_SYSERR;
1589 GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST,
1590 &req->purpose, &req->signature,
1591 &req->member_pub_key))
1593 GNUNET_break_op (0);
1594 return GNUNET_SYSERR;
1597 struct GNUNET_HashCode group_pub_hash;
1598 GNUNET_CRYPTO_hash (&req->group_pub_key, sizeof (req->group_pub_key), &group_pub_hash);
1600 struct Channel *chn = GNUNET_malloc (sizeof *chn);
1601 chn->channel = channel;
1602 chn->group_pub_key = req->group_pub_key;
1603 chn->group_pub_hash = group_pub_hash;
1604 chn->member_pub_key = req->member_pub_key;
1605 chn->peer = req->peer;
1606 chn->join_status = JOIN_WAITING;
1607 GNUNET_CONTAINER_multihashmap_put (channels_in, &chn->group_pub_hash, chn,
1608 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1610 client_send_all (&group_pub_hash, m);
1616 * Incoming join decision message from CADET.
1619 cadet_recv_join_decision (void *cls,
1620 struct GNUNET_CADET_Channel *channel,
1622 const struct GNUNET_MessageHeader *m)
1624 const struct MulticastJoinDecisionMessage *
1625 dcsn = (const struct MulticastJoinDecisionMessage *) m;
1626 uint16_t size = ntohs (m->size);
1627 if (size < sizeof (*dcsn))
1629 GNUNET_break_op (0);
1630 return GNUNET_SYSERR;
1632 struct Channel *chn = *ctx;
1635 GNUNET_break_op (0);
1636 return GNUNET_SYSERR;
1638 if (NULL == chn->grp || GNUNET_NO != chn->grp->is_origin)
1640 GNUNET_break_op (0);
1641 return GNUNET_SYSERR;
1643 switch (chn->join_status)
1646 return GNUNET_SYSERR;
1651 case JOIN_NOT_ASKED:
1656 struct MulticastJoinDecisionMessageHeader *
1657 hdcsn = GNUNET_malloc (sizeof (*hdcsn) + size);
1658 hdcsn->peer = chn->peer;
1659 GNUNET_memcpy (&hdcsn[1], dcsn, sizeof (*hdcsn) + size);
1661 struct Member *mem = (struct Member *) chn->grp;
1662 client_send_join_decision (mem, hdcsn);
1663 GNUNET_free (hdcsn);
1664 if (GNUNET_YES == ntohs (dcsn->is_admitted))
1666 chn->join_status = JOIN_ADMITTED;
1671 chn->join_status = JOIN_REFUSED;
1672 return GNUNET_SYSERR;
1677 * Incoming multicast message from CADET.
1680 cadet_recv_message (void *cls,
1681 struct GNUNET_CADET_Channel *channel,
1683 const struct GNUNET_MessageHeader *m)
1685 const struct GNUNET_MULTICAST_MessageHeader *
1686 msg = (const struct GNUNET_MULTICAST_MessageHeader *) m;
1687 uint16_t size = ntohs (m->size);
1688 if (size < sizeof (*msg))
1690 GNUNET_break_op (0);
1691 return GNUNET_SYSERR;
1693 struct Channel *chn = *ctx;
1696 GNUNET_break_op (0);
1697 return GNUNET_SYSERR;
1699 if (ntohl (msg->purpose.size) != (size
1700 - sizeof (msg->header)
1701 - sizeof (msg->hop_counter)
1702 - sizeof (msg->signature)))
1704 GNUNET_break_op (0);
1705 return GNUNET_SYSERR;
1708 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE,
1709 &msg->purpose, &msg->signature,
1710 &chn->group_pub_key))
1712 GNUNET_break_op (0);
1713 return GNUNET_SYSERR;
1716 client_send_all (&chn->group_pub_hash, m);
1722 * Incoming multicast request message from CADET.
1725 cadet_recv_request (void *cls,
1726 struct GNUNET_CADET_Channel *channel,
1728 const struct GNUNET_MessageHeader *m)
1730 const struct GNUNET_MULTICAST_RequestHeader *
1731 req = (const struct GNUNET_MULTICAST_RequestHeader *) m;
1732 uint16_t size = ntohs (m->size);
1733 if (size < sizeof (*req))
1735 GNUNET_break_op (0);
1736 return GNUNET_SYSERR;
1738 struct Channel *chn = *ctx;
1741 GNUNET_break_op (0);
1742 return GNUNET_SYSERR;
1744 if (ntohl (req->purpose.size) != (size
1745 - sizeof (req->header)
1746 - sizeof (req->member_pub_key)
1747 - sizeof (req->signature)))
1749 GNUNET_break_op (0);
1750 return GNUNET_SYSERR;
1753 GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST,
1754 &req->purpose, &req->signature,
1755 &req->member_pub_key))
1757 GNUNET_break_op (0);
1758 return GNUNET_SYSERR;
1761 client_send_origin (&chn->group_pub_hash, m);
1767 * Incoming multicast replay request from CADET.
1770 cadet_recv_replay_request (void *cls,
1771 struct GNUNET_CADET_Channel *channel,
1773 const struct GNUNET_MessageHeader *m)
1775 struct MulticastReplayRequestMessage rep;
1776 uint16_t size = ntohs (m->size);
1777 if (size < sizeof (rep))
1779 GNUNET_break_op (0);
1780 return GNUNET_SYSERR;
1782 struct Channel *chn = *ctx;
1784 GNUNET_memcpy (&rep, m, sizeof (rep));
1785 GNUNET_memcpy (&rep.member_pub_key, &chn->member_pub_key, sizeof (chn->member_pub_key));
1787 struct GNUNET_CONTAINER_MultiHashMap *
1788 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
1789 &chn->grp->pub_key_hash);
1790 if (NULL == grp_replay_req)
1792 grp_replay_req = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1793 GNUNET_CONTAINER_multihashmap_put (replay_req_cadet,
1794 &chn->grp->pub_key_hash, grp_replay_req,
1795 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1797 struct GNUNET_HashCode key_hash;
1798 replay_key_hash (rep.fragment_id, rep.message_id, rep.fragment_offset,
1799 rep.flags, &key_hash);
1800 GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, chn,
1801 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1803 client_send_random (&chn->group_pub_hash, &rep.header);
1809 * Incoming multicast replay response from CADET.
1812 cadet_recv_replay_response (void *cls,
1813 struct GNUNET_CADET_Channel *channel,
1815 const struct GNUNET_MessageHeader *m)
1817 //struct Channel *chn = *ctx;
1819 /* @todo FIXME: got replay error response, send request to other members */
1826 * Message handlers for CADET.
1828 static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
1829 { cadet_recv_join_request,
1830 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST, 0 },
1832 { cadet_recv_message,
1833 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, 0 },
1835 { cadet_recv_request,
1836 GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST, 0 },
1838 { cadet_recv_replay_request,
1839 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST, 0 },
1841 { cadet_recv_replay_response,
1842 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE, 0 },
1849 * Connected to core service.
1852 core_connected_cb (void *cls, const struct GNUNET_PeerIdentity *my_identity)
1854 this_peer = *my_identity;
1856 stats = GNUNET_STATISTICS_create ("multicast", cfg);
1857 origins = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1858 members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1859 group_members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1860 channels_in = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1861 channels_out = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1862 replay_req_cadet = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1863 replay_req_client = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1865 cadet = GNUNET_CADET_connect (cfg, NULL,
1866 &cadet_notify_channel_end,
1868 GNUNET_assert (NULL != cadet);
1870 nc = GNUNET_SERVER_notification_context_create (server, 1);
1871 GNUNET_SERVER_add_handlers (server, server_handlers);
1872 GNUNET_SERVER_disconnect_notify (server,
1873 &client_notify_disconnect, NULL);
1874 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
1882 * @param cls closure
1883 * @param server the initialized server
1884 * @param cfg configuration to use
1888 struct GNUNET_SERVER_Handle *srv,
1889 const struct GNUNET_CONFIGURATION_Handle *c)
1893 GNUNET_SERVER_connect_notify (server, &client_notify_connect, NULL);
1894 core = GNUNET_CORE_connecT (cfg, NULL, &core_connected_cb, NULL, NULL, NULL);
1899 * The main function for the multicast service.
1901 * @param argc number of arguments from the command line
1902 * @param argv command line arguments
1903 * @return 0 ok, 1 on error
1906 main (int argc, char *const *argv)
1908 return (GNUNET_OK ==
1909 GNUNET_SERVICE_run (argc, argv, "multicast",
1910 GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
1913 /* end of gnunet-service-multicast.c */