2 This file is part of GNUnet.
3 Copyright (C) 2009 Christian Grothoff (and other contributing authors)
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_key;
163 * Hash of @a group_key.
165 struct GNUNET_HashCode group_key_hash;
168 * Public key of the joining member.
170 struct GNUNET_CRYPTO_EcdsaPublicKey member_key;
173 * Remote peer identity.
175 struct GNUNET_PeerIdentity peer;
178 * Is the remote peer admitted to the group?
179 * @see enum JoinStatus
185 * @see enum ChannelDirection
192 * List of connected clients.
196 struct ClientList *prev;
197 struct ClientList *next;
198 struct GNUNET_SERVER_Client *client;
202 * Common part of the client context for both an origin and 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;
220 * Is this an origin (#GNUNET_YES), or member (#GNUNET_NO)?
225 * Is the client disconnected? #GNUNET_YES or #GNUNET_NO
227 uint8_t disconnected;
232 * Client context for a group's origin.
239 * Private key of the group.
241 struct GNUNET_CRYPTO_EddsaPrivateKey priv_key;
244 * Last message fragment ID sent to the group.
246 uint64_t max_fragment_id;
251 * Client context for a group member.
258 * Private key of the member.
260 struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key;
263 * Public key of the member.
265 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
268 * Hash of @a pub_key.
270 struct GNUNET_HashCode pub_key_hash;
273 * Join request sent to the origin / members.
275 struct MulticastJoinRequestMessage *join_req;
278 * Join decision sent in reply to our request.
280 * Only a positive decision is stored here, in case of a negative decision the
281 * client is disconnected.
283 struct MulticastJoinDecisionMessageHeader *join_dcsn;
286 * CADET channel to the origin.
288 struct Channel *origin_channel;
291 * Peer identity of origin.
293 struct GNUNET_PeerIdentity origin;
296 * Peer identity of relays (other members to connect).
298 struct GNUNET_PeerIdentity *relays;
301 * Last request fragment ID sent to the origin.
303 uint64_t max_fragment_id;
306 * Number of @a relays.
308 uint32_t relay_count;
312 struct ReplayRequestKey
314 uint64_t fragment_id;
316 uint64_t fragment_offset;
322 * Task run during shutdown.
328 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
332 GNUNET_CORE_disconnect (core);
337 GNUNET_CADET_disconnect (cadet);
342 GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
345 /* FIXME: do more clean up here */
350 * Clean up origin data structures after a client disconnected.
353 cleanup_origin (struct Origin *orig)
355 struct Group *grp = &orig->grp;
356 GNUNET_CONTAINER_multihashmap_remove (origins, &grp->pub_key_hash, orig);
361 * Clean up member data structures after a client disconnected.
364 cleanup_member (struct Member *mem)
366 struct Group *grp = &mem->grp;
367 struct GNUNET_CONTAINER_MultiHashMap *
368 grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members,
370 GNUNET_assert (NULL != grp_mem);
371 GNUNET_CONTAINER_multihashmap_remove (grp_mem, &mem->pub_key_hash, mem);
373 if (0 == GNUNET_CONTAINER_multihashmap_size (grp_mem))
375 GNUNET_CONTAINER_multihashmap_remove (group_members, &grp->pub_key_hash,
377 GNUNET_CONTAINER_multihashmap_destroy (grp_mem);
379 if (NULL != mem->join_dcsn)
381 GNUNET_free (mem->join_dcsn);
382 mem->join_dcsn = NULL;
384 GNUNET_CONTAINER_multihashmap_remove (members, &grp->pub_key_hash, mem);
389 * Clean up group data structures after a client disconnected.
392 cleanup_group (struct Group *grp)
394 (GNUNET_YES == grp->is_origin)
395 ? cleanup_origin ((struct Origin *) grp)
396 : cleanup_member ((struct Member *) grp);
403 replay_key_hash (uint64_t fragment_id, uint64_t message_id,
404 uint64_t fragment_offset, uint64_t flags,
405 struct GNUNET_HashCode *key_hash)
407 struct ReplayRequestKey key = {
408 .fragment_id = fragment_id,
409 .message_id = message_id,
410 .fragment_offset = fragment_offset,
413 GNUNET_CRYPTO_hash (&key, sizeof (key), key_hash);
418 * Remove channel from replay request hashmap.
423 * @return #GNUNET_YES if there are more entries to process,
424 * #GNUNET_NO when reached end of hashmap.
427 replay_req_remove_cadet (struct Channel *chn)
429 struct GNUNET_CONTAINER_MultiHashMap *
430 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
431 &chn->grp->pub_key_hash);
432 if (NULL == grp_replay_req)
435 struct GNUNET_CONTAINER_MultiHashMapIterator *
436 it = GNUNET_CONTAINER_multihashmap_iterator_create (grp_replay_req);
437 struct GNUNET_HashCode key;
438 const struct Channel *c;
440 == GNUNET_CONTAINER_multihashmap_iterator_next (it, &key,
445 GNUNET_CONTAINER_multihashmap_remove (grp_replay_req, &key, chn);
449 GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
455 * Remove client from replay request hashmap.
460 * @return #GNUNET_YES if there are more entries to process,
461 * #GNUNET_NO when reached end of hashmap.
464 replay_req_remove_client (struct Group *grp, struct GNUNET_SERVER_Client *client)
466 struct GNUNET_CONTAINER_MultiHashMap *
467 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
469 if (NULL == grp_replay_req)
472 struct GNUNET_CONTAINER_MultiHashMapIterator *
473 it = GNUNET_CONTAINER_multihashmap_iterator_create (grp_replay_req);
474 struct GNUNET_HashCode key;
475 const struct GNUNET_SERVER_Client *c;
477 == GNUNET_CONTAINER_multihashmap_iterator_next (it, &key,
482 GNUNET_CONTAINER_multihashmap_remove (replay_req_client, &key, client);
486 GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
492 * Called whenever a client is disconnected.
494 * Frees our resources associated with that client.
496 * @param cls Closure.
497 * @param client Client handle.
500 client_notify_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
506 = GNUNET_SERVER_client_get_user_context (client, struct Group);
510 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
511 "%p User context is NULL in client_disconnect()\n", grp);
516 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
517 "%p Client (%s) disconnected from group %s\n",
518 grp, (GNUNET_YES == grp->is_origin) ? "origin" : "member",
519 GNUNET_h2s (&grp->pub_key_hash));
521 struct ClientList *cl = grp->clients_head;
524 if (cl->client == client)
526 GNUNET_CONTAINER_DLL_remove (grp->clients_head, grp->clients_tail, cl);
533 while (GNUNET_YES == replay_req_remove_client (grp, client));
535 if (NULL == grp->clients_head)
536 { /* Last client disconnected. */
538 if (NULL != grp->tmit_head)
539 { /* Send pending messages via CADET before cleanup. */
540 transmit_message (grp);
552 * Send message to a client.
555 client_send (struct GNUNET_SERVER_Client *client,
556 const struct GNUNET_MessageHeader *msg)
558 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
559 "%p Sending message to client.\n", client);
561 GNUNET_SERVER_notification_context_add (nc, client);
562 GNUNET_SERVER_notification_context_unicast (nc, client, msg, GNUNET_NO);
567 * Send message to all clients connected to the group.
570 client_send_group (const struct Group *grp,
571 const struct GNUNET_MessageHeader *msg)
573 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
574 "%p Sending message to all clients of the group.\n", grp);
576 struct ClientList *cl = grp->clients_head;
579 GNUNET_SERVER_notification_context_add (nc, cl->client);
580 GNUNET_SERVER_notification_context_unicast (nc, cl->client, msg, GNUNET_NO);
587 * Iterator callback for sending a message to origin clients.
590 client_send_origin_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
593 const struct GNUNET_MessageHeader *msg = cls;
594 struct Member *orig = origin;
596 client_send_group (&orig->grp, msg);
602 * Iterator callback for sending a message to member clients.
605 client_send_member_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
608 const struct GNUNET_MessageHeader *msg = cls;
609 struct Member *mem = member;
611 if (NULL != mem->join_dcsn)
612 { /* Only send message to admitted members */
613 client_send_group (&mem->grp, msg);
620 * Send message to all origin and member clients connected to the group.
622 * @param grp The group to send @a msg to.
623 * @param msg Message to send.
626 client_send_all (struct GNUNET_HashCode *pub_key_hash,
627 const struct GNUNET_MessageHeader *msg)
630 n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash,
631 client_send_origin_cb,
633 n += GNUNET_CONTAINER_multihashmap_get_multiple (members, pub_key_hash,
634 client_send_member_cb,
641 * Send message to a random origin client or a random member client.
643 * @param grp The group to send @a msg to.
644 * @param msg Message to send.
647 client_send_random (struct GNUNET_HashCode *pub_key_hash,
648 const struct GNUNET_MessageHeader *msg)
651 n = GNUNET_CONTAINER_multihashmap_get_random (origins, client_send_origin_cb,
654 n = GNUNET_CONTAINER_multihashmap_get_random (members, client_send_member_cb,
661 * Send message to all origin clients connected to the group.
663 * @param grp The group to send @a msg to.
664 * @param msg Message to send.
667 client_send_origin (struct GNUNET_HashCode *pub_key_hash,
668 const struct GNUNET_MessageHeader *msg)
671 n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash,
672 client_send_origin_cb,
679 * CADET is ready to transmit a message.
682 cadet_notify_transmit_ready (void *cls, size_t buf_size, void *buf)
686 /* FIXME: connection closed */
689 const struct GNUNET_MessageHeader *msg = cls;
690 uint16_t msg_size = ntohs (msg->size);
691 GNUNET_assert (msg_size <= buf_size);
692 memcpy (buf, msg, msg_size);
698 * Send a message to a CADET channel.
700 * @param chn Channel.
701 * @param msg Message.
704 cadet_send_channel (struct Channel *chn, const struct GNUNET_MessageHeader *msg)
707 = GNUNET_CADET_notify_transmit_ready (chn->channel, GNUNET_NO,
708 GNUNET_TIME_UNIT_FOREVER_REL,
710 &cadet_notify_transmit_ready,
712 GNUNET_assert (NULL != chn->tmit_handle);
717 * Create new outgoing CADET channel.
720 * Peer to connect to.
722 * Public key of group the channel belongs to.
723 * @param group_key_hash
724 * Hash of @a group_key.
728 static struct Channel *
729 cadet_channel_create (struct Group *grp, struct GNUNET_PeerIdentity *peer)
731 struct Channel *chn = GNUNET_malloc (sizeof (*chn));
733 chn->group_key = grp->pub_key;
734 chn->group_key_hash = grp->pub_key_hash;
736 chn->direction = DIR_OUTGOING;
737 chn->join_status = JOIN_WAITING;
738 chn->channel = GNUNET_CADET_channel_create (cadet, chn, &chn->peer,
739 GNUNET_APPLICATION_TYPE_MULTICAST,
740 GNUNET_CADET_OPTION_RELIABLE);
741 GNUNET_CONTAINER_multihashmap_put (channels_out, &chn->group_key_hash, chn,
742 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
748 * Create CADET channel and send a join request.
751 cadet_send_join_request (struct Member *mem)
753 mem->origin_channel = cadet_channel_create (&mem->grp, &mem->origin);
754 cadet_send_channel (mem->origin_channel, &mem->join_req->header);
757 for (i = 0; i < mem->relay_count; i++)
760 chn = cadet_channel_create (&mem->grp, &mem->relays[i]);
761 cadet_send_channel (chn, &mem->join_req->header);
767 cadet_send_join_decision_cb (void *cls,
768 const struct GNUNET_HashCode *group_key_hash,
771 const struct MulticastJoinDecisionMessageHeader *hdcsn = cls;
772 struct Channel *chn = channel;
774 if (0 == memcmp (&hdcsn->member_key, &chn->member_key, sizeof (chn->member_key))
775 && 0 == memcmp (&hdcsn->peer, &chn->peer, sizeof (chn->peer)))
777 cadet_send_channel (chn, &hdcsn->header);
785 * Send join decision to a remote peer.
788 cadet_send_join_decision (struct Group *grp,
789 const struct MulticastJoinDecisionMessageHeader *hdcsn)
791 GNUNET_CONTAINER_multihashmap_get_multiple (channels_in, &grp->pub_key_hash,
792 &cadet_send_join_decision_cb,
798 * Iterator callback for sending a message to origin clients.
801 cadet_send_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
804 const struct GNUNET_MessageHeader *msg = cls;
805 struct Channel *chn = channel;
806 if (JOIN_ADMITTED == chn->join_status)
807 cadet_send_channel (chn, msg);
813 * Send message to all connected children.
816 cadet_send_children (struct GNUNET_HashCode *pub_key_hash,
817 const struct GNUNET_MessageHeader *msg)
820 if (channels_in != NULL)
821 n += GNUNET_CONTAINER_multihashmap_get_multiple (channels_in, pub_key_hash,
822 cadet_send_cb, (void *) msg);
828 * Send message to all connected parents.
831 cadet_send_parents (struct GNUNET_HashCode *pub_key_hash,
832 const struct GNUNET_MessageHeader *msg)
835 if (channels_in != NULL)
836 n += GNUNET_CONTAINER_multihashmap_get_multiple (channels_out, pub_key_hash,
837 cadet_send_cb, (void *) msg);
843 * Handle a connecting client starting an origin.
846 client_recv_origin_start (void *cls, struct GNUNET_SERVER_Client *client,
847 const struct GNUNET_MessageHeader *m)
849 const struct MulticastOriginStartMessage *
850 msg = (const struct MulticastOriginStartMessage *) m;
852 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
853 struct GNUNET_HashCode pub_key_hash;
855 GNUNET_CRYPTO_eddsa_key_get_public (&msg->group_key, &pub_key);
856 GNUNET_CRYPTO_hash (&pub_key, sizeof (pub_key), &pub_key_hash);
859 orig = GNUNET_CONTAINER_multihashmap_get (origins, &pub_key_hash);
864 orig = GNUNET_new (struct Origin);
865 orig->priv_key = msg->group_key;
866 orig->max_fragment_id = GNUNET_ntohll (msg->max_fragment_id);
868 grp->is_origin = GNUNET_YES;
869 grp->pub_key = pub_key;
870 grp->pub_key_hash = pub_key_hash;
872 GNUNET_CONTAINER_multihashmap_put (origins, &grp->pub_key_hash, orig,
873 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
880 struct ClientList *cl = GNUNET_new (struct ClientList);
882 GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl);
884 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
885 "%p Client connected as origin to group %s.\n",
886 orig, GNUNET_h2s (&grp->pub_key_hash));
888 GNUNET_SERVER_client_set_user_context (client, grp);
889 GNUNET_SERVER_receive_done (client, GNUNET_OK);
894 * Handle a connecting client joining a group.
897 client_recv_member_join (void *cls, struct GNUNET_SERVER_Client *client,
898 const struct GNUNET_MessageHeader *m)
900 const struct MulticastMemberJoinMessage *
901 msg = (const struct MulticastMemberJoinMessage *) m;
902 uint16_t msg_size = ntohs (msg->header.size);
904 struct GNUNET_CRYPTO_EcdsaPublicKey mem_pub_key;
905 struct GNUNET_HashCode pub_key_hash, mem_pub_key_hash;
907 GNUNET_CRYPTO_ecdsa_key_get_public (&msg->member_key, &mem_pub_key);
908 GNUNET_CRYPTO_hash (&mem_pub_key, sizeof (mem_pub_key), &mem_pub_key_hash);
909 GNUNET_CRYPTO_hash (&msg->group_key, sizeof (msg->group_key), &pub_key_hash);
911 struct GNUNET_CONTAINER_MultiHashMap *
912 grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members, &pub_key_hash);
913 struct Member *mem = NULL;
918 mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &mem_pub_key_hash);
922 mem = GNUNET_new (struct Member);
923 mem->priv_key = msg->member_key;
924 mem->pub_key = mem_pub_key;
925 mem->pub_key_hash = mem_pub_key_hash;
926 mem->max_fragment_id = 0; // FIXME
929 grp->is_origin = GNUNET_NO;
930 grp->pub_key = msg->group_key;
931 grp->pub_key_hash = pub_key_hash;
935 grp_mem = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
936 GNUNET_CONTAINER_multihashmap_put (group_members, &grp->pub_key_hash, grp_mem,
937 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
939 GNUNET_CONTAINER_multihashmap_put (grp_mem, &mem->pub_key_hash, mem,
940 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
941 GNUNET_CONTAINER_multihashmap_put (members, &grp->pub_key_hash, mem,
942 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
949 struct ClientList *cl = GNUNET_new (struct ClientList);
951 GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl);
953 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
954 "%p Client connected to group %s..\n",
955 mem, GNUNET_h2s (&grp->pub_key_hash));
956 char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&mem->pub_key);
957 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
958 "%p ..as member %s (%s).\n",
959 mem, GNUNET_h2s (&mem->pub_key_hash), str);
962 GNUNET_SERVER_client_set_user_context (client, grp);
964 if (NULL != mem->join_dcsn)
965 { /* Already got a join decision, send it to client. */
966 GNUNET_SERVER_notification_context_add (nc, client);
967 GNUNET_SERVER_notification_context_unicast (nc, client,
968 (struct GNUNET_MessageHeader *)
972 else if (grp->clients_head == grp->clients_tail)
973 { /* First client of the group, send join request. */
974 struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1];
975 uint32_t relay_count = ntohl (msg->relay_count);
976 uint16_t relay_size = relay_count * sizeof (*relays);
977 struct GNUNET_MessageHeader *join_msg = NULL;
978 uint16_t join_msg_size = 0;
979 if (sizeof (*msg) + relay_size + sizeof (struct GNUNET_MessageHeader)
982 join_msg = (struct GNUNET_MessageHeader *)
983 (((char *) &msg[1]) + relay_size);
984 join_msg_size = ntohs (join_msg->size);
986 if (sizeof (*msg) + relay_size + join_msg_size != msg_size)
989 GNUNET_SERVER_client_disconnect (client);
993 struct MulticastJoinRequestMessage *
994 req = GNUNET_malloc (sizeof (*req) + join_msg_size);
995 req->header.size = htons (sizeof (*req) + join_msg_size);
996 req->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST);
997 req->group_key = grp->pub_key;
998 req->peer = this_peer;
999 GNUNET_CRYPTO_ecdsa_key_get_public (&mem->priv_key, &req->member_key);
1000 if (0 < join_msg_size)
1001 memcpy (&req[1], join_msg, join_msg_size);
1003 req->member_key = mem->pub_key;
1004 req->purpose.size = htonl (msg_size
1005 - sizeof (req->header)
1006 - sizeof (req->reserved)
1007 - sizeof (req->signature));
1008 req->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
1010 if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (&mem->priv_key, &req->purpose,
1013 /* FIXME: handle error */
1017 if (NULL != mem->join_req)
1018 GNUNET_free (mem->join_req);
1019 mem->join_req = req;
1021 if (0 == client_send_origin (&grp->pub_key_hash, &mem->join_req->header))
1022 { /* No local origins, send to remote origin */
1023 cadet_send_join_request (mem);
1026 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1031 client_send_join_decision (struct Member *mem,
1032 const struct MulticastJoinDecisionMessageHeader *hdcsn)
1034 client_send_group (&mem->grp, &hdcsn->header);
1036 const struct MulticastJoinDecisionMessage *
1037 dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1];
1038 if (GNUNET_YES == ntohl (dcsn->is_admitted))
1039 { /* Member admitted, store join_decision. */
1040 uint16_t dcsn_size = ntohs (dcsn->header.size);
1041 mem->join_dcsn = GNUNET_malloc (dcsn_size);
1042 memcpy (mem->join_dcsn, dcsn, dcsn_size);
1045 { /* Refused entry, disconnect clients. */
1047 struct ClientList *cl = mem->grp.clients_head;
1050 struct GNUNET_SERVER_Client *client = cl->client;
1052 GNUNET_SERVER_client_disconnect (client);
1060 * Join decision from client.
1063 client_recv_join_decision (void *cls, struct GNUNET_SERVER_Client *client,
1064 const struct GNUNET_MessageHeader *m)
1067 grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
1068 const struct MulticastJoinDecisionMessageHeader *
1069 hdcsn = (const struct MulticastJoinDecisionMessageHeader *) m;
1074 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1077 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1078 "%p Got join decision from client for group %s..\n",
1079 grp, GNUNET_h2s (&grp->pub_key_hash));
1081 struct GNUNET_CONTAINER_MultiHashMap *
1082 grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members,
1083 &grp->pub_key_hash);
1084 struct Member *mem = NULL;
1085 if (NULL != grp_mem)
1087 struct GNUNET_HashCode member_key_hash;
1088 GNUNET_CRYPTO_hash (&hdcsn->member_key, sizeof (hdcsn->member_key),
1090 mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &member_key_hash);
1091 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1092 "%p ..and member %s: %p\n",
1093 grp, GNUNET_h2s (&member_key_hash), mem);
1096 { /* Found local member */
1097 client_send_join_decision (mem, hdcsn);
1100 { /* Look for remote member */
1101 cadet_send_join_decision (grp, hdcsn);
1103 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1108 * Incoming message from a client.
1111 client_recv_multicast_message (void *cls, struct GNUNET_SERVER_Client *client,
1112 const struct GNUNET_MessageHeader *m)
1115 grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
1116 struct GNUNET_MULTICAST_MessageHeader *out;
1117 struct Origin *orig;
1122 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1125 GNUNET_assert (GNUNET_YES == grp->is_origin);
1126 orig = (struct Origin *) grp;
1128 /* FIXME: yucky, should use separate message structs for P2P and CS! */
1129 out = (struct GNUNET_MULTICAST_MessageHeader *) GNUNET_copy_message (m);
1130 out->fragment_id = GNUNET_htonll (++orig->max_fragment_id);
1131 out->purpose.size = htonl (ntohs (out->header.size)
1132 - sizeof (out->header)
1133 - sizeof (out->hop_counter)
1134 - sizeof (out->signature));
1135 out->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE);
1137 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_sign (&orig->priv_key, &out->purpose,
1143 client_send_all (&grp->pub_key_hash, &out->header);
1144 cadet_send_children (&grp->pub_key_hash, &out->header);
1147 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1152 * Incoming request from a client.
1155 client_recv_multicast_request (void *cls, struct GNUNET_SERVER_Client *client,
1156 const struct GNUNET_MessageHeader *m)
1158 struct Group *grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
1160 struct GNUNET_MULTICAST_RequestHeader *out;
1164 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1167 GNUNET_assert (GNUNET_NO == grp->is_origin);
1168 mem = (struct Member *) grp;
1170 /* FIXME: yucky, should use separate message structs for P2P and CS! */
1171 out = (struct GNUNET_MULTICAST_RequestHeader *) GNUNET_copy_message (m);
1172 out->member_key = mem->pub_key;
1173 out->fragment_id = GNUNET_ntohll (++mem->max_fragment_id);
1174 out->purpose.size = htonl (ntohs (out->header.size)
1175 - sizeof (out->header)
1176 - sizeof (out->member_key)
1177 - sizeof (out->signature));
1178 out->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
1180 if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (&mem->priv_key, &out->purpose,
1186 if (0 == client_send_origin (&grp->pub_key_hash, &out->header))
1187 { /* No local origins, send to remote origin */
1188 if (NULL != mem->origin_channel)
1190 cadet_send_channel (mem->origin_channel, &out->header);
1194 /* FIXME: not yet connected to origin */
1195 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1201 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1206 * Incoming replay request from a client.
1209 client_recv_replay_request (void *cls, struct GNUNET_SERVER_Client *client,
1210 const struct GNUNET_MessageHeader *m)
1212 struct Group *grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
1217 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1220 GNUNET_assert (GNUNET_NO == grp->is_origin);
1221 mem = (struct Member *) grp;
1223 struct GNUNET_CONTAINER_MultiHashMap *
1224 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
1225 &grp->pub_key_hash);
1226 if (NULL == grp_replay_req)
1228 grp_replay_req = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1229 GNUNET_CONTAINER_multihashmap_put (replay_req_client,
1230 &grp->pub_key_hash, grp_replay_req,
1231 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1233 struct MulticastReplayRequestMessage *
1234 rep = (struct MulticastReplayRequestMessage *) m;
1235 struct GNUNET_HashCode key_hash;
1236 replay_key_hash (rep->fragment_id, rep->message_id, rep->fragment_offset,
1237 rep->flags, &key_hash);
1238 GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, client,
1239 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1241 if (0 == client_send_origin (&grp->pub_key_hash, m))
1242 { /* No local origin, replay from remote members / origin. */
1243 if (NULL != mem->origin_channel)
1245 cadet_send_channel (mem->origin_channel, m);
1249 /* FIXME: not yet connected to origin */
1250 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1254 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1259 cadet_send_replay_response_cb (void *cls,
1260 const struct GNUNET_HashCode *key_hash,
1263 struct Channel *chn = value;
1264 struct GNUNET_MessageHeader *msg = cls;
1266 cadet_send_channel (chn, msg);
1272 client_send_replay_response_cb (void *cls,
1273 const struct GNUNET_HashCode *key_hash,
1276 struct GNUNET_SERVER_Client *client = value;
1277 struct GNUNET_MessageHeader *msg = cls;
1279 client_send (client, msg);
1285 * End of replay response from a client.
1288 client_recv_replay_response_end (void *cls, struct GNUNET_SERVER_Client *client,
1289 const struct GNUNET_MessageHeader *m)
1291 struct Group *grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
1295 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1299 struct MulticastReplayResponseMessage *
1300 res = (struct MulticastReplayResponseMessage *) m;
1302 struct GNUNET_HashCode key_hash;
1303 replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset,
1304 res->flags, &key_hash);
1306 struct GNUNET_CONTAINER_MultiHashMap *
1307 grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
1308 &grp->pub_key_hash);
1309 if (NULL != grp_replay_req_cadet)
1311 GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_cadet, &key_hash);
1313 struct GNUNET_CONTAINER_MultiHashMap *
1314 grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
1315 &grp->pub_key_hash);
1316 if (NULL != grp_replay_req_client)
1318 GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_client, &key_hash);
1320 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1325 * Incoming replay response from a client.
1327 * Respond with a multicast message on success, or otherwise with an error code.
1330 client_recv_replay_response (void *cls, struct GNUNET_SERVER_Client *client,
1331 const struct GNUNET_MessageHeader *m)
1333 struct Group *grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
1337 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1341 struct MulticastReplayResponseMessage *
1342 res = (struct MulticastReplayResponseMessage *) m;
1344 const struct GNUNET_MessageHeader *msg = m;
1345 if (GNUNET_MULTICAST_REC_OK == res->error_code)
1347 msg = (struct GNUNET_MessageHeader *) &res[1];
1350 struct GNUNET_HashCode key_hash;
1351 replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset,
1352 res->flags, &key_hash);
1354 struct GNUNET_CONTAINER_MultiHashMap *
1355 grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
1356 &grp->pub_key_hash);
1357 if (NULL != grp_replay_req_cadet)
1359 GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_cadet, &key_hash,
1360 cadet_send_replay_response_cb,
1363 if (GNUNET_MULTICAST_REC_OK == res->error_code)
1365 struct GNUNET_CONTAINER_MultiHashMap *
1366 grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
1367 &grp->pub_key_hash);
1368 if (NULL != grp_replay_req_client)
1370 GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_client, &key_hash,
1371 client_send_replay_response_cb,
1377 client_recv_replay_response_end (cls, client, m);
1380 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1385 * Incoming replay request from a client.
1388 client_recv_replay_request_cancel (void *cls, struct GNUNET_SERVER_Client *client,
1389 const struct GNUNET_MessageHeader *m)
1391 struct Group *grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
1396 * Incoming replay request from a client.
1399 client_recv_membership_test_result (void *cls, struct GNUNET_SERVER_Client *client,
1400 const struct GNUNET_MessageHeader *m)
1402 struct Group *grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
1407 * A new client connected.
1410 client_notify_connect (void *cls, struct GNUNET_SERVER_Client *client)
1412 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client connected: %p\n", client);
1413 /* FIXME: send connect ACK */
1418 * Message handlers for the server.
1420 static const struct GNUNET_SERVER_MessageHandler server_handlers[] = {
1421 { client_recv_origin_start, NULL,
1422 GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START, 0 },
1424 { client_recv_member_join, NULL,
1425 GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_JOIN, 0 },
1427 { client_recv_join_decision, NULL,
1428 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION, 0 },
1430 { client_recv_multicast_message, NULL,
1431 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, 0 },
1433 { client_recv_multicast_request, NULL,
1434 GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST, 0 },
1436 { client_recv_replay_request, NULL,
1437 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST, 0 },
1439 { client_recv_replay_request_cancel, NULL,
1440 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST_CANCEL, 0 },
1442 { client_recv_replay_response, NULL,
1443 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE, 0 },
1445 { client_recv_replay_response_end, NULL,
1446 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE_END, 0 },
1448 { client_recv_membership_test_result, NULL,
1449 GNUNET_MESSAGE_TYPE_MULTICAST_MEMBERSHIP_TEST_RESULT, 0 },
1451 { NULL, NULL, 0, 0 }
1456 * New incoming CADET channel.
1459 cadet_notify_channel_new (void *cls,
1460 struct GNUNET_CADET_Channel *channel,
1461 const struct GNUNET_PeerIdentity *initiator,
1463 enum GNUNET_CADET_ChannelOption options)
1470 * CADET channel is being destroyed.
1473 cadet_notify_channel_end (void *cls,
1474 const struct GNUNET_CADET_Channel *channel,
1480 struct Channel *chn = ctx;
1481 if (NULL != chn->grp)
1483 if (GNUNET_NO == chn->grp->is_origin)
1485 struct Member *mem = (struct Member *) chn->grp;
1486 if (chn == mem->origin_channel)
1487 mem->origin_channel = NULL;
1491 while (GNUNET_YES == replay_req_remove_cadet (chn));
1498 * Incoming join request message from CADET.
1501 cadet_recv_join_request (void *cls,
1502 struct GNUNET_CADET_Channel *channel,
1504 const struct GNUNET_MessageHeader *m)
1506 const struct MulticastJoinRequestMessage *
1507 req = (const struct MulticastJoinRequestMessage *) m;
1508 uint16_t size = ntohs (m->size);
1509 if (size < sizeof (*req))
1511 GNUNET_break_op (0);
1512 return GNUNET_SYSERR;
1516 GNUNET_break_op (0);
1517 return GNUNET_SYSERR;
1519 if (ntohl (req->purpose.size) != (size
1520 - sizeof (req->header)
1521 - sizeof (req->reserved)
1522 - sizeof (req->signature)))
1524 GNUNET_break_op (0);
1525 return GNUNET_SYSERR;
1528 GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST,
1529 &req->purpose, &req->signature,
1532 GNUNET_break_op (0);
1533 return GNUNET_SYSERR;
1536 struct GNUNET_HashCode group_key_hash;
1537 GNUNET_CRYPTO_hash (&req->group_key, sizeof (req->group_key), &group_key_hash);
1539 struct Channel *chn = GNUNET_malloc (sizeof *chn);
1540 chn->channel = channel;
1541 chn->group_key = req->group_key;
1542 chn->group_key_hash = group_key_hash;
1543 chn->member_key = req->member_key;
1544 chn->peer = req->peer;
1545 chn->join_status = JOIN_WAITING;
1546 GNUNET_CONTAINER_multihashmap_put (channels_in, &chn->group_key_hash, chn,
1547 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1549 client_send_all (&group_key_hash, m);
1555 * Incoming join decision message from CADET.
1558 cadet_recv_join_decision (void *cls,
1559 struct GNUNET_CADET_Channel *channel,
1561 const struct GNUNET_MessageHeader *m)
1563 const struct MulticastJoinDecisionMessage *
1564 dcsn = (const struct MulticastJoinDecisionMessage *) m;
1565 uint16_t size = ntohs (m->size);
1566 if (size < sizeof (*dcsn))
1568 GNUNET_break_op (0);
1569 return GNUNET_SYSERR;
1571 struct Channel *chn = *ctx;
1574 GNUNET_break_op (0);
1575 return GNUNET_SYSERR;
1577 if (NULL == chn->grp || GNUNET_NO != chn->grp->is_origin)
1579 GNUNET_break_op (0);
1580 return GNUNET_SYSERR;
1582 switch (chn->join_status)
1585 return GNUNET_SYSERR;
1590 case JOIN_NOT_ASKED:
1595 struct MulticastJoinDecisionMessageHeader *
1596 hdcsn = GNUNET_malloc (sizeof (*hdcsn) + size);
1597 hdcsn->peer = chn->peer;
1598 memcpy (&hdcsn[1], dcsn, sizeof (*hdcsn) + size);
1600 struct Member *mem = (struct Member *) chn->grp;
1601 client_send_join_decision (mem, hdcsn);
1602 GNUNET_free (hdcsn);
1603 if (GNUNET_YES == ntohs (dcsn->is_admitted))
1605 chn->join_status = JOIN_ADMITTED;
1610 chn->join_status = JOIN_REFUSED;
1611 return GNUNET_SYSERR;
1616 * Incoming multicast message from CADET.
1619 cadet_recv_message (void *cls,
1620 struct GNUNET_CADET_Channel *channel,
1622 const struct GNUNET_MessageHeader *m)
1624 const struct GNUNET_MULTICAST_MessageHeader *
1625 msg = (const struct GNUNET_MULTICAST_MessageHeader *) m;
1626 uint16_t size = ntohs (m->size);
1627 if (size < sizeof (*msg))
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 (ntohl (msg->purpose.size) != (size
1639 - sizeof (msg->header)
1640 - sizeof (msg->hop_counter)
1641 - sizeof (msg->signature)))
1643 GNUNET_break_op (0);
1644 return GNUNET_SYSERR;
1647 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE,
1648 &msg->purpose, &msg->signature,
1651 GNUNET_break_op (0);
1652 return GNUNET_SYSERR;
1655 client_send_all (&chn->group_key_hash, m);
1661 * Incoming multicast request message from CADET.
1664 cadet_recv_request (void *cls,
1665 struct GNUNET_CADET_Channel *channel,
1667 const struct GNUNET_MessageHeader *m)
1669 const struct GNUNET_MULTICAST_RequestHeader *
1670 req = (const struct GNUNET_MULTICAST_RequestHeader *) m;
1671 uint16_t size = ntohs (m->size);
1672 if (size < sizeof (*req))
1674 GNUNET_break_op (0);
1675 return GNUNET_SYSERR;
1677 struct Channel *chn = *ctx;
1680 GNUNET_break_op (0);
1681 return GNUNET_SYSERR;
1683 if (ntohl (req->purpose.size) != (size
1684 - sizeof (req->header)
1685 - sizeof (req->member_key)
1686 - sizeof (req->signature)))
1688 GNUNET_break_op (0);
1689 return GNUNET_SYSERR;
1692 GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST,
1693 &req->purpose, &req->signature,
1696 GNUNET_break_op (0);
1697 return GNUNET_SYSERR;
1700 client_send_origin (&chn->group_key_hash, m);
1706 * Incoming multicast replay request from CADET.
1709 cadet_recv_replay_request (void *cls,
1710 struct GNUNET_CADET_Channel *channel,
1712 const struct GNUNET_MessageHeader *m)
1714 struct MulticastReplayRequestMessage rep;
1715 uint16_t size = ntohs (m->size);
1716 if (size < sizeof (rep))
1718 GNUNET_break_op (0);
1719 return GNUNET_SYSERR;
1721 struct Channel *chn = *ctx;
1723 memcpy (&rep, m, sizeof (rep));
1724 memcpy (&rep.member_key, &chn->member_key, sizeof (chn->member_key));
1726 struct GNUNET_CONTAINER_MultiHashMap *
1727 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
1728 &chn->grp->pub_key_hash);
1729 if (NULL == grp_replay_req)
1731 grp_replay_req = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1732 GNUNET_CONTAINER_multihashmap_put (replay_req_cadet,
1733 &chn->grp->pub_key_hash, grp_replay_req,
1734 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1736 struct GNUNET_HashCode key_hash;
1737 replay_key_hash (rep.fragment_id, rep.message_id, rep.fragment_offset,
1738 rep.flags, &key_hash);
1739 GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, chn,
1740 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1742 client_send_random (&chn->group_key_hash, &rep.header);
1748 * Incoming multicast replay request cancellation from CADET.
1751 cadet_recv_replay_request_cancel (void *cls,
1752 struct GNUNET_CADET_Channel *channel,
1754 const struct GNUNET_MessageHeader *m)
1761 * Incoming multicast replay response from CADET.
1764 cadet_recv_replay_response (void *cls,
1765 struct GNUNET_CADET_Channel *channel,
1767 const struct GNUNET_MessageHeader *m)
1769 struct Channel *chn = *ctx;
1771 /* @todo FIXME: got replay error response, send request to other members */
1778 * Message handlers for CADET.
1780 static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
1781 { cadet_recv_join_request,
1782 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST, 0 },
1784 { cadet_recv_message,
1785 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, 0 },
1787 { cadet_recv_request,
1788 GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST, 0 },
1790 { cadet_recv_replay_request,
1791 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST, 0 },
1793 { cadet_recv_replay_request_cancel,
1794 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST_CANCEL, 0 },
1796 { cadet_recv_replay_response,
1797 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE, 0 },
1804 * Listening ports for CADET.
1806 static const uint32_t cadet_ports[] = { GNUNET_APPLICATION_TYPE_MULTICAST, 0 };
1810 * Connected to core service.
1813 core_connected_cb (void *cls, const struct GNUNET_PeerIdentity *my_identity)
1815 this_peer = *my_identity;
1817 stats = GNUNET_STATISTICS_create ("multicast", cfg);
1818 origins = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1819 members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1820 group_members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1821 channels_in = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1822 channels_out = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1823 replay_req_cadet = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1824 replay_req_client = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1826 cadet = GNUNET_CADET_connect (cfg, NULL,
1827 &cadet_notify_channel_new,
1828 &cadet_notify_channel_end,
1829 cadet_handlers, cadet_ports);
1831 nc = GNUNET_SERVER_notification_context_create (server, 1);
1832 GNUNET_SERVER_add_handlers (server, server_handlers);
1833 GNUNET_SERVER_disconnect_notify (server, &client_notify_disconnect, NULL);
1835 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
1843 * @param cls closure
1844 * @param server the initialized server
1845 * @param cfg configuration to use
1848 run (void *cls, struct GNUNET_SERVER_Handle *srv,
1849 const struct GNUNET_CONFIGURATION_Handle *c)
1853 GNUNET_SERVER_connect_notify (server, &client_notify_connect, NULL);
1854 core = GNUNET_CORE_connect (cfg, NULL, &core_connected_cb, NULL, NULL,
1855 NULL, GNUNET_NO, NULL, GNUNET_NO, NULL);
1860 * The main function for the multicast service.
1862 * @param argc number of arguments from the command line
1863 * @param argv command line arguments
1864 * @return 0 ok, 1 on error
1867 main (int argc, char *const *argv)
1869 return (GNUNET_OK ==
1870 GNUNET_SERVICE_run (argc, argv, "multicast",
1871 GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
1874 /* end of gnunet-service-multicast.c */