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;
225 * Is this an origin (#GNUNET_YES), or member (#GNUNET_NO)?
230 * Is the client disconnected? #GNUNET_YES or #GNUNET_NO
232 uint8_t disconnected;
237 * Client context for a group's origin.
244 * Private key of the group.
246 struct GNUNET_CRYPTO_EddsaPrivateKey priv_key;
249 * Last message fragment ID sent to the group.
251 uint64_t max_fragment_id;
256 * Client context for a group member.
263 * Private key of the member.
265 struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key;
268 * Public key of the member.
270 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
273 * Hash of @a pub_key.
275 struct GNUNET_HashCode pub_key_hash;
278 * Join request sent to the origin / members.
280 struct MulticastJoinRequestMessage *join_req;
283 * Join decision sent in reply to our request.
285 * Only a positive decision is stored here, in case of a negative decision the
286 * client is disconnected.
288 struct MulticastJoinDecisionMessageHeader *join_dcsn;
291 * CADET channel to the origin.
293 struct Channel *origin_channel;
296 * Peer identity of origin.
298 struct GNUNET_PeerIdentity origin;
301 * Peer identity of relays (other members to connect).
303 struct GNUNET_PeerIdentity *relays;
306 * Last request fragment ID sent to the origin.
308 uint64_t max_fragment_id;
311 * Number of @a relays.
313 uint32_t relay_count;
317 struct ReplayRequestKey
319 uint64_t fragment_id;
321 uint64_t fragment_offset;
327 * Task run during shutdown.
332 shutdown_task (void *cls)
336 GNUNET_CORE_disconnect (core);
341 GNUNET_CADET_disconnect (cadet);
346 GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
349 /* FIXME: do more clean up here */
354 * Clean up origin data structures after a client disconnected.
357 cleanup_origin (struct Origin *orig)
359 struct Group *grp = &orig->grp;
360 GNUNET_CONTAINER_multihashmap_remove (origins, &grp->pub_key_hash, orig);
365 * Clean up member data structures after a client disconnected.
368 cleanup_member (struct Member *mem)
370 struct Group *grp = &mem->grp;
371 struct GNUNET_CONTAINER_MultiHashMap *
372 grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members,
374 GNUNET_assert (NULL != grp_mem);
375 GNUNET_CONTAINER_multihashmap_remove (grp_mem, &mem->pub_key_hash, mem);
377 if (0 == GNUNET_CONTAINER_multihashmap_size (grp_mem))
379 GNUNET_CONTAINER_multihashmap_remove (group_members, &grp->pub_key_hash,
381 GNUNET_CONTAINER_multihashmap_destroy (grp_mem);
383 if (NULL != mem->join_dcsn)
385 GNUNET_free (mem->join_dcsn);
386 mem->join_dcsn = NULL;
388 GNUNET_CONTAINER_multihashmap_remove (members, &grp->pub_key_hash, mem);
393 * Clean up group data structures after a client disconnected.
396 cleanup_group (struct Group *grp)
398 (GNUNET_YES == grp->is_origin)
399 ? cleanup_origin ((struct Origin *) grp)
400 : cleanup_member ((struct Member *) grp);
407 replay_key_hash (uint64_t fragment_id, uint64_t message_id,
408 uint64_t fragment_offset, uint64_t flags,
409 struct GNUNET_HashCode *key_hash)
411 struct ReplayRequestKey key = {
412 .fragment_id = fragment_id,
413 .message_id = message_id,
414 .fragment_offset = fragment_offset,
417 GNUNET_CRYPTO_hash (&key, sizeof (key), key_hash);
422 * Remove channel from replay request hashmap.
427 * @return #GNUNET_YES if there are more entries to process,
428 * #GNUNET_NO when reached end of hashmap.
431 replay_req_remove_cadet (struct Channel *chn)
433 struct GNUNET_CONTAINER_MultiHashMap *
434 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
435 &chn->grp->pub_key_hash);
436 if (NULL == grp_replay_req)
439 struct GNUNET_CONTAINER_MultiHashMapIterator *
440 it = GNUNET_CONTAINER_multihashmap_iterator_create (grp_replay_req);
441 struct GNUNET_HashCode key;
442 const struct Channel *c;
444 == GNUNET_CONTAINER_multihashmap_iterator_next (it, &key,
449 GNUNET_CONTAINER_multihashmap_remove (grp_replay_req, &key, chn);
450 GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
454 GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
460 * Remove client from replay request hashmap.
465 * @return #GNUNET_YES if there are more entries to process,
466 * #GNUNET_NO when reached end of hashmap.
469 replay_req_remove_client (struct Group *grp, struct GNUNET_SERVER_Client *client)
471 struct GNUNET_CONTAINER_MultiHashMap *
472 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
474 if (NULL == grp_replay_req)
477 struct GNUNET_CONTAINER_MultiHashMapIterator *
478 it = GNUNET_CONTAINER_multihashmap_iterator_create (grp_replay_req);
479 struct GNUNET_HashCode key;
480 const struct GNUNET_SERVER_Client *c;
482 == GNUNET_CONTAINER_multihashmap_iterator_next (it, &key,
487 GNUNET_CONTAINER_multihashmap_remove (replay_req_client, &key, client);
488 GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
492 GNUNET_CONTAINER_multihashmap_iterator_destroy (it);
498 * Called whenever a client is disconnected.
500 * Frees our resources associated with that client.
502 * @param cls Closure.
503 * @param client Client handle.
506 client_notify_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
512 = GNUNET_SERVER_client_get_user_context (client, struct Group);
516 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
517 "%p User context is NULL in client_disconnect()\n", grp);
522 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
523 "%p Client (%s) disconnected from group %s\n",
524 grp, (GNUNET_YES == grp->is_origin) ? "origin" : "member",
525 GNUNET_h2s (&grp->pub_key_hash));
527 struct ClientList *cl = grp->clients_head;
530 if (cl->client == client)
532 GNUNET_CONTAINER_DLL_remove (grp->clients_head, grp->clients_tail, cl);
539 while (GNUNET_YES == replay_req_remove_client (grp, client));
541 if (NULL == grp->clients_head)
542 { /* Last client disconnected. */
544 if (NULL != grp->tmit_head)
545 { /* Send pending messages via CADET before cleanup. */
546 transmit_message (grp);
558 * Send message to a client.
561 client_send (struct GNUNET_SERVER_Client *client,
562 const struct GNUNET_MessageHeader *msg)
564 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
565 "%p Sending message to client.\n", client);
567 GNUNET_SERVER_notification_context_add (nc, client);
568 GNUNET_SERVER_notification_context_unicast (nc, client, msg, GNUNET_NO);
573 * Send message to all clients connected to the group.
576 client_send_group (const struct Group *grp,
577 const struct GNUNET_MessageHeader *msg)
579 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
580 "%p Sending message to all clients of the group.\n", grp);
582 struct ClientList *cl = grp->clients_head;
585 GNUNET_SERVER_notification_context_add (nc, cl->client);
586 GNUNET_SERVER_notification_context_unicast (nc, cl->client, msg, GNUNET_NO);
593 * Iterator callback for sending a message to origin clients.
596 client_send_origin_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
599 const struct GNUNET_MessageHeader *msg = cls;
600 struct Member *orig = origin;
602 client_send_group (&orig->grp, msg);
608 * Iterator callback for sending a message to member clients.
611 client_send_member_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
614 const struct GNUNET_MessageHeader *msg = cls;
615 struct Member *mem = member;
617 if (NULL != mem->join_dcsn)
618 { /* Only send message to admitted members */
619 client_send_group (&mem->grp, msg);
626 * Send message to all origin and member clients connected to the group.
628 * @param pub_key_hash
629 * H(key_pub) of the group.
634 client_send_all (struct GNUNET_HashCode *pub_key_hash,
635 const struct GNUNET_MessageHeader *msg)
638 n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash,
639 client_send_origin_cb,
641 n += GNUNET_CONTAINER_multihashmap_get_multiple (members, pub_key_hash,
642 client_send_member_cb,
649 * Send message to a random origin client or a random member client.
651 * @param grp The group to send @a msg to.
652 * @param msg Message to send.
655 client_send_random (struct GNUNET_HashCode *pub_key_hash,
656 const struct GNUNET_MessageHeader *msg)
659 n = GNUNET_CONTAINER_multihashmap_get_random (origins, client_send_origin_cb,
662 n = GNUNET_CONTAINER_multihashmap_get_random (members, client_send_member_cb,
669 * Send message to all origin clients connected to the group.
671 * @param pub_key_hash
672 * H(key_pub) of the group.
677 client_send_origin (struct GNUNET_HashCode *pub_key_hash,
678 const struct GNUNET_MessageHeader *msg)
681 n += GNUNET_CONTAINER_multihashmap_get_multiple (origins, pub_key_hash,
682 client_send_origin_cb,
689 * Send fragment acknowledgement to all clients of the channel.
691 * @param pub_key_hash
692 * H(key_pub) of the group.
695 client_send_ack (struct GNUNET_HashCode *pub_key_hash)
697 static struct GNUNET_MessageHeader *msg = NULL;
700 msg = GNUNET_malloc (sizeof (*msg));
701 msg->type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_FRAGMENT_ACK);
702 msg->size = htons (sizeof (*msg));
704 client_send_all (pub_key_hash, msg);
708 struct CadetTransmitClosure
711 const struct GNUNET_MessageHeader *msg;
716 * CADET is ready to transmit a message.
719 cadet_notify_transmit_ready (void *cls, size_t buf_size, void *buf)
723 /* FIXME: connection closed */
726 struct CadetTransmitClosure *tcls = cls;
727 struct Channel *chn = tcls->chn;
728 uint16_t msg_size = ntohs (tcls->msg->size);
729 GNUNET_assert (msg_size <= buf_size);
730 GNUNET_memcpy (buf, tcls->msg, msg_size);
733 if (0 == chn->msgs_pending)
737 else if (0 == --chn->msgs_pending)
739 client_send_ack (&chn->group_pub_hash);
746 * Send a message to a CADET channel.
748 * @param chn Channel.
749 * @param msg Message.
752 cadet_send_channel (struct Channel *chn, const struct GNUNET_MessageHeader *msg)
754 struct CadetTransmitClosure *tcls = GNUNET_malloc (sizeof (*tcls));
760 = GNUNET_CADET_notify_transmit_ready (chn->channel, GNUNET_NO,
761 GNUNET_TIME_UNIT_FOREVER_REL,
763 &cadet_notify_transmit_ready,
765 GNUNET_assert (NULL != chn->tmit_handle);
770 * Create new outgoing CADET channel.
773 * Peer to connect to.
774 * @param group_pub_key
775 * Public key of group the channel belongs to.
776 * @param group_pub_hash
777 * Hash of @a group_pub_key.
781 static struct Channel *
782 cadet_channel_create (struct Group *grp, struct GNUNET_PeerIdentity *peer)
784 struct Channel *chn = GNUNET_malloc (sizeof (*chn));
786 chn->group_pub_key = grp->pub_key;
787 chn->group_pub_hash = grp->pub_key_hash;
789 chn->direction = DIR_OUTGOING;
790 chn->join_status = JOIN_WAITING;
791 chn->channel = GNUNET_CADET_channel_create (cadet, chn, &chn->peer,
792 GC_u2h (GNUNET_APPLICATION_TYPE_MULTICAST),
793 GNUNET_CADET_OPTION_RELIABLE);
794 GNUNET_CONTAINER_multihashmap_put (channels_out, &chn->group_pub_hash, chn,
795 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
801 * Create CADET channel and send a join request.
804 cadet_send_join_request (struct Member *mem)
806 mem->origin_channel = cadet_channel_create (&mem->grp, &mem->origin);
807 cadet_send_channel (mem->origin_channel, &mem->join_req->header);
810 for (i = 0; i < mem->relay_count; i++)
813 chn = cadet_channel_create (&mem->grp, &mem->relays[i]);
814 cadet_send_channel (chn, &mem->join_req->header);
820 cadet_send_join_decision_cb (void *cls,
821 const struct GNUNET_HashCode *group_pub_hash,
824 const struct MulticastJoinDecisionMessageHeader *hdcsn = cls;
825 struct Channel *chn = channel;
827 if (0 == memcmp (&hdcsn->member_pub_key, &chn->member_pub_key, sizeof (chn->member_pub_key))
828 && 0 == memcmp (&hdcsn->peer, &chn->peer, sizeof (chn->peer)))
830 cadet_send_channel (chn, &hdcsn->header);
838 * Send join decision to a remote peer.
841 cadet_send_join_decision (struct Group *grp,
842 const struct MulticastJoinDecisionMessageHeader *hdcsn)
844 GNUNET_CONTAINER_multihashmap_get_multiple (channels_in, &grp->pub_key_hash,
845 &cadet_send_join_decision_cb,
851 * Iterator callback for sending a message to origin clients.
854 cadet_send_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
857 const struct GNUNET_MessageHeader *msg = cls;
858 struct Channel *chn = channel;
859 if (JOIN_ADMITTED == chn->join_status)
860 cadet_send_channel (chn, msg);
866 * Send message to all connected children.
869 cadet_send_children (struct GNUNET_HashCode *pub_key_hash,
870 const struct GNUNET_MessageHeader *msg)
873 if (channels_in != NULL)
874 n += GNUNET_CONTAINER_multihashmap_get_multiple (channels_in, pub_key_hash,
875 cadet_send_cb, (void *) msg);
880 #if 0 // unused as yet
882 * Send message to all connected parents.
885 cadet_send_parents (struct GNUNET_HashCode *pub_key_hash,
886 const struct GNUNET_MessageHeader *msg)
889 if (channels_in != NULL)
890 n += GNUNET_CONTAINER_multihashmap_get_multiple (channels_out, pub_key_hash,
891 cadet_send_cb, (void *) msg);
898 * Handle a connecting client starting an origin.
901 client_recv_origin_start (void *cls, struct GNUNET_SERVER_Client *client,
902 const struct GNUNET_MessageHeader *m)
904 const struct MulticastOriginStartMessage *
905 msg = (const struct MulticastOriginStartMessage *) m;
907 struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
908 struct GNUNET_HashCode pub_key_hash;
910 GNUNET_CRYPTO_eddsa_key_get_public (&msg->group_key, &pub_key);
911 GNUNET_CRYPTO_hash (&pub_key, sizeof (pub_key), &pub_key_hash);
914 orig = GNUNET_CONTAINER_multihashmap_get (origins, &pub_key_hash);
919 orig = GNUNET_new (struct Origin);
920 orig->priv_key = msg->group_key;
921 orig->max_fragment_id = GNUNET_ntohll (msg->max_fragment_id);
923 grp->is_origin = GNUNET_YES;
924 grp->pub_key = pub_key;
925 grp->pub_key_hash = pub_key_hash;
927 GNUNET_CONTAINER_multihashmap_put (origins, &grp->pub_key_hash, orig,
928 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
935 struct ClientList *cl = GNUNET_new (struct ClientList);
937 GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl);
939 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
940 "%p Client connected as origin to group %s.\n",
941 orig, GNUNET_h2s (&grp->pub_key_hash));
943 GNUNET_SERVER_client_set_user_context (client, grp);
944 GNUNET_SERVER_receive_done (client, GNUNET_OK);
949 * Handle a connecting client joining a group.
952 client_recv_member_join (void *cls, struct GNUNET_SERVER_Client *client,
953 const struct GNUNET_MessageHeader *m)
955 const struct MulticastMemberJoinMessage *
956 msg = (const struct MulticastMemberJoinMessage *) m;
957 uint16_t msg_size = ntohs (msg->header.size);
959 struct GNUNET_CRYPTO_EcdsaPublicKey mem_pub_key;
960 struct GNUNET_HashCode pub_key_hash, mem_pub_key_hash;
962 GNUNET_CRYPTO_ecdsa_key_get_public (&msg->member_key, &mem_pub_key);
963 GNUNET_CRYPTO_hash (&mem_pub_key, sizeof (mem_pub_key), &mem_pub_key_hash);
964 GNUNET_CRYPTO_hash (&msg->group_pub_key, sizeof (msg->group_pub_key), &pub_key_hash);
966 struct GNUNET_CONTAINER_MultiHashMap *
967 grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members, &pub_key_hash);
968 struct Member *mem = NULL;
973 mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &mem_pub_key_hash);
977 mem = GNUNET_new (struct Member);
978 mem->priv_key = msg->member_key;
979 mem->pub_key = mem_pub_key;
980 mem->pub_key_hash = mem_pub_key_hash;
981 mem->max_fragment_id = 0; // FIXME
984 grp->is_origin = GNUNET_NO;
985 grp->pub_key = msg->group_pub_key;
986 grp->pub_key_hash = pub_key_hash;
990 grp_mem = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
991 GNUNET_CONTAINER_multihashmap_put (group_members, &grp->pub_key_hash, grp_mem,
992 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
994 GNUNET_CONTAINER_multihashmap_put (grp_mem, &mem->pub_key_hash, mem,
995 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
996 GNUNET_CONTAINER_multihashmap_put (members, &grp->pub_key_hash, mem,
997 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1004 struct ClientList *cl = GNUNET_new (struct ClientList);
1005 cl->client = client;
1006 GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl);
1008 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1009 "%p Client connected to group %s..\n",
1010 mem, GNUNET_h2s (&grp->pub_key_hash));
1011 char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&mem->pub_key);
1012 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1013 "%p ..as member %s (%s).\n",
1014 mem, GNUNET_h2s (&mem->pub_key_hash), str);
1017 GNUNET_SERVER_client_set_user_context (client, grp);
1019 if (NULL != mem->join_dcsn)
1020 { /* Already got a join decision, send it to client. */
1021 GNUNET_SERVER_notification_context_add (nc, client);
1022 GNUNET_SERVER_notification_context_unicast (nc, client,
1023 (struct GNUNET_MessageHeader *)
1028 { /* First client of the group, send join request. */
1029 struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1];
1030 uint32_t relay_count = ntohl (msg->relay_count);
1031 uint16_t relay_size = relay_count * sizeof (*relays);
1032 struct GNUNET_MessageHeader *join_msg = NULL;
1033 uint16_t join_msg_size = 0;
1034 if (sizeof (*msg) + relay_size + sizeof (struct GNUNET_MessageHeader)
1037 join_msg = (struct GNUNET_MessageHeader *)
1038 (((char *) &msg[1]) + relay_size);
1039 join_msg_size = ntohs (join_msg->size);
1041 if (sizeof (*msg) + relay_size + join_msg_size != msg_size)
1044 GNUNET_SERVER_client_disconnect (client);
1048 struct MulticastJoinRequestMessage *
1049 req = GNUNET_malloc (sizeof (*req) + join_msg_size);
1050 req->header.size = htons (sizeof (*req) + join_msg_size);
1051 req->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST);
1052 req->group_pub_key = grp->pub_key;
1053 req->peer = this_peer;
1054 GNUNET_CRYPTO_ecdsa_key_get_public (&mem->priv_key, &req->member_pub_key);
1055 if (0 < join_msg_size)
1056 GNUNET_memcpy (&req[1], join_msg, join_msg_size);
1058 req->member_pub_key = mem->pub_key;
1059 req->purpose.size = htonl (msg_size
1060 - sizeof (req->header)
1061 - sizeof (req->reserved)
1062 - sizeof (req->signature));
1063 req->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
1065 if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (&mem->priv_key, &req->purpose,
1068 /* FIXME: handle error */
1072 if (NULL != mem->join_req)
1073 GNUNET_free (mem->join_req);
1074 mem->join_req = req;
1076 if (0 == client_send_origin (&grp->pub_key_hash, &mem->join_req->header))
1077 { /* No local origins, send to remote origin */
1078 cadet_send_join_request (mem);
1081 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1086 client_send_join_decision (struct Member *mem,
1087 const struct MulticastJoinDecisionMessageHeader *hdcsn)
1089 client_send_group (&mem->grp, &hdcsn->header);
1091 const struct MulticastJoinDecisionMessage *
1092 dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1];
1093 if (GNUNET_YES == ntohl (dcsn->is_admitted))
1094 { /* Member admitted, store join_decision. */
1095 uint16_t dcsn_size = ntohs (dcsn->header.size);
1096 mem->join_dcsn = GNUNET_malloc (dcsn_size);
1097 GNUNET_memcpy (mem->join_dcsn, dcsn, dcsn_size);
1100 { /* Refused entry, but replay would be still possible for past members. */
1106 * Join decision from client.
1109 client_recv_join_decision (void *cls, struct GNUNET_SERVER_Client *client,
1110 const struct GNUNET_MessageHeader *m)
1113 grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
1114 const struct MulticastJoinDecisionMessageHeader *
1115 hdcsn = (const struct MulticastJoinDecisionMessageHeader *) m;
1120 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1123 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1124 "%p Got join decision from client for group %s..\n",
1125 grp, GNUNET_h2s (&grp->pub_key_hash));
1127 struct GNUNET_CONTAINER_MultiHashMap *
1128 grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members,
1129 &grp->pub_key_hash);
1130 struct Member *mem = NULL;
1131 if (NULL != grp_mem)
1133 struct GNUNET_HashCode member_key_hash;
1134 GNUNET_CRYPTO_hash (&hdcsn->member_pub_key, sizeof (hdcsn->member_pub_key),
1136 mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &member_key_hash);
1137 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1138 "%p ..and member %s: %p\n",
1139 grp, GNUNET_h2s (&member_key_hash), mem);
1142 { /* Found local member */
1143 client_send_join_decision (mem, hdcsn);
1146 { /* Look for remote member */
1147 cadet_send_join_decision (grp, hdcsn);
1149 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1154 * Incoming message from a client.
1157 client_recv_multicast_message (void *cls, struct GNUNET_SERVER_Client *client,
1158 const struct GNUNET_MessageHeader *m)
1161 grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
1162 struct GNUNET_MULTICAST_MessageHeader *out;
1163 struct Origin *orig;
1168 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1171 GNUNET_assert (GNUNET_YES == grp->is_origin);
1172 orig = (struct Origin *) grp;
1174 /* FIXME: yucky, should use separate message structs for P2P and CS! */
1175 out = (struct GNUNET_MULTICAST_MessageHeader *) GNUNET_copy_message (m);
1176 out->fragment_id = GNUNET_htonll (++orig->max_fragment_id);
1177 out->purpose.size = htonl (ntohs (out->header.size)
1178 - sizeof (out->header)
1179 - sizeof (out->hop_counter)
1180 - sizeof (out->signature));
1181 out->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE);
1183 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_sign (&orig->priv_key, &out->purpose,
1189 client_send_all (&grp->pub_key_hash, &out->header);
1190 if (0 == cadet_send_children (&grp->pub_key_hash, &out->header))
1192 client_send_ack (&grp->pub_key_hash);
1196 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1201 * Incoming request from a client.
1204 client_recv_multicast_request (void *cls, struct GNUNET_SERVER_Client *client,
1205 const struct GNUNET_MessageHeader *m)
1207 struct Group *grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
1209 struct GNUNET_MULTICAST_RequestHeader *out;
1213 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1216 GNUNET_assert (GNUNET_NO == grp->is_origin);
1217 mem = (struct Member *) grp;
1219 /* FIXME: yucky, should use separate message structs for P2P and CS! */
1220 out = (struct GNUNET_MULTICAST_RequestHeader *) GNUNET_copy_message (m);
1221 out->member_pub_key = mem->pub_key;
1222 out->fragment_id = GNUNET_ntohll (++mem->max_fragment_id);
1223 out->purpose.size = htonl (ntohs (out->header.size)
1224 - sizeof (out->header)
1225 - sizeof (out->member_pub_key)
1226 - sizeof (out->signature));
1227 out->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
1229 if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (&mem->priv_key, &out->purpose,
1235 uint8_t send_ack = GNUNET_YES;
1236 if (0 == client_send_origin (&grp->pub_key_hash, &out->header))
1237 { /* No local origins, send to remote origin */
1238 if (NULL != mem->origin_channel)
1240 cadet_send_channel (mem->origin_channel, &out->header);
1241 send_ack = GNUNET_NO;
1245 /* FIXME: not yet connected to origin */
1246 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1251 if (GNUNET_YES == send_ack)
1253 client_send_ack (&grp->pub_key_hash);
1256 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1261 * Incoming replay request from a client.
1264 client_recv_replay_request (void *cls, struct GNUNET_SERVER_Client *client,
1265 const struct GNUNET_MessageHeader *m)
1267 struct Group *grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
1272 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1275 GNUNET_assert (GNUNET_NO == grp->is_origin);
1276 mem = (struct Member *) grp;
1278 struct GNUNET_CONTAINER_MultiHashMap *
1279 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
1280 &grp->pub_key_hash);
1281 if (NULL == grp_replay_req)
1283 grp_replay_req = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1284 GNUNET_CONTAINER_multihashmap_put (replay_req_client,
1285 &grp->pub_key_hash, grp_replay_req,
1286 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1288 struct MulticastReplayRequestMessage *
1289 rep = (struct MulticastReplayRequestMessage *) m;
1290 struct GNUNET_HashCode key_hash;
1291 replay_key_hash (rep->fragment_id, rep->message_id, rep->fragment_offset,
1292 rep->flags, &key_hash);
1293 GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, client,
1294 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1296 if (0 == client_send_origin (&grp->pub_key_hash, m))
1297 { /* No local origin, replay from remote members / origin. */
1298 if (NULL != mem->origin_channel)
1300 cadet_send_channel (mem->origin_channel, m);
1304 /* FIXME: not yet connected to origin */
1305 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1309 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1314 cadet_send_replay_response_cb (void *cls,
1315 const struct GNUNET_HashCode *key_hash,
1318 struct Channel *chn = value;
1319 struct GNUNET_MessageHeader *msg = cls;
1321 cadet_send_channel (chn, msg);
1327 client_send_replay_response_cb (void *cls,
1328 const struct GNUNET_HashCode *key_hash,
1331 struct GNUNET_SERVER_Client *client = value;
1332 struct GNUNET_MessageHeader *msg = cls;
1334 client_send (client, msg);
1340 * End of replay response from a client.
1343 client_recv_replay_response_end (void *cls, struct GNUNET_SERVER_Client *client,
1344 const struct GNUNET_MessageHeader *m)
1346 struct Group *grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
1350 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1354 struct MulticastReplayResponseMessage *
1355 res = (struct MulticastReplayResponseMessage *) m;
1357 struct GNUNET_HashCode key_hash;
1358 replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset,
1359 res->flags, &key_hash);
1361 struct GNUNET_CONTAINER_MultiHashMap *
1362 grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
1363 &grp->pub_key_hash);
1364 if (NULL != grp_replay_req_cadet)
1366 GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_cadet, &key_hash);
1368 struct GNUNET_CONTAINER_MultiHashMap *
1369 grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
1370 &grp->pub_key_hash);
1371 if (NULL != grp_replay_req_client)
1373 GNUNET_CONTAINER_multihashmap_remove_all (grp_replay_req_client, &key_hash);
1375 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1380 * Incoming replay response from a client.
1382 * Respond with a multicast message on success, or otherwise with an error code.
1385 client_recv_replay_response (void *cls, struct GNUNET_SERVER_Client *client,
1386 const struct GNUNET_MessageHeader *m)
1388 struct Group *grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
1392 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1396 struct MulticastReplayResponseMessage *
1397 res = (struct MulticastReplayResponseMessage *) m;
1399 const struct GNUNET_MessageHeader *msg = m;
1400 if (GNUNET_MULTICAST_REC_OK == res->error_code)
1402 msg = (struct GNUNET_MessageHeader *) &res[1];
1405 struct GNUNET_HashCode key_hash;
1406 replay_key_hash (res->fragment_id, res->message_id, res->fragment_offset,
1407 res->flags, &key_hash);
1409 struct GNUNET_CONTAINER_MultiHashMap *
1410 grp_replay_req_cadet = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
1411 &grp->pub_key_hash);
1412 if (NULL != grp_replay_req_cadet)
1414 GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_cadet, &key_hash,
1415 cadet_send_replay_response_cb,
1418 if (GNUNET_MULTICAST_REC_OK == res->error_code)
1420 struct GNUNET_CONTAINER_MultiHashMap *
1421 grp_replay_req_client = GNUNET_CONTAINER_multihashmap_get (replay_req_client,
1422 &grp->pub_key_hash);
1423 if (NULL != grp_replay_req_client)
1425 GNUNET_CONTAINER_multihashmap_get_multiple (grp_replay_req_client, &key_hash,
1426 client_send_replay_response_cb,
1432 client_recv_replay_response_end (cls, client, m);
1435 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1440 * A new client connected.
1443 client_notify_connect (void *cls, struct GNUNET_SERVER_Client *client)
1445 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client connected: %p\n", client);
1446 /* FIXME: send connect ACK */
1451 * Message handlers for the server.
1453 static const struct GNUNET_SERVER_MessageHandler server_handlers[] = {
1454 { client_recv_origin_start, NULL,
1455 GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START, 0 },
1457 { client_recv_member_join, NULL,
1458 GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_JOIN, 0 },
1460 { client_recv_join_decision, NULL,
1461 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION, 0 },
1463 { client_recv_multicast_message, NULL,
1464 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, 0 },
1466 { client_recv_multicast_request, NULL,
1467 GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST, 0 },
1469 { client_recv_replay_request, NULL,
1470 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST, 0 },
1472 { client_recv_replay_response, NULL,
1473 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE, 0 },
1475 { client_recv_replay_response_end, NULL,
1476 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE_END, 0 },
1478 { NULL, NULL, 0, 0 }
1483 * New incoming CADET channel.
1486 cadet_notify_channel_new (void *cls,
1487 struct GNUNET_CADET_Channel *channel,
1488 const struct GNUNET_PeerIdentity *initiator,
1489 const struct GNUNET_HashCode *port,
1490 enum GNUNET_CADET_ChannelOption options)
1497 * CADET channel is being destroyed.
1500 cadet_notify_channel_end (void *cls,
1501 const struct GNUNET_CADET_Channel *channel,
1507 struct Channel *chn = ctx;
1508 if (NULL != chn->grp)
1510 if (GNUNET_NO == chn->grp->is_origin)
1512 struct Member *mem = (struct Member *) chn->grp;
1513 if (chn == mem->origin_channel)
1514 mem->origin_channel = NULL;
1518 while (GNUNET_YES == replay_req_remove_cadet (chn));
1525 * Incoming join request message from CADET.
1528 cadet_recv_join_request (void *cls,
1529 struct GNUNET_CADET_Channel *channel,
1531 const struct GNUNET_MessageHeader *m)
1533 const struct MulticastJoinRequestMessage *
1534 req = (const struct MulticastJoinRequestMessage *) m;
1535 uint16_t size = ntohs (m->size);
1536 if (size < sizeof (*req))
1538 GNUNET_break_op (0);
1539 return GNUNET_SYSERR;
1543 GNUNET_break_op (0);
1544 return GNUNET_SYSERR;
1546 if (ntohl (req->purpose.size) != (size
1547 - sizeof (req->header)
1548 - sizeof (req->reserved)
1549 - sizeof (req->signature)))
1551 GNUNET_break_op (0);
1552 return GNUNET_SYSERR;
1555 GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST,
1556 &req->purpose, &req->signature,
1557 &req->member_pub_key))
1559 GNUNET_break_op (0);
1560 return GNUNET_SYSERR;
1563 struct GNUNET_HashCode group_pub_hash;
1564 GNUNET_CRYPTO_hash (&req->group_pub_key, sizeof (req->group_pub_key), &group_pub_hash);
1566 struct Channel *chn = GNUNET_malloc (sizeof *chn);
1567 chn->channel = channel;
1568 chn->group_pub_key = req->group_pub_key;
1569 chn->group_pub_hash = group_pub_hash;
1570 chn->member_pub_key = req->member_pub_key;
1571 chn->peer = req->peer;
1572 chn->join_status = JOIN_WAITING;
1573 GNUNET_CONTAINER_multihashmap_put (channels_in, &chn->group_pub_hash, chn,
1574 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1576 client_send_all (&group_pub_hash, m);
1582 * Incoming join decision message from CADET.
1585 cadet_recv_join_decision (void *cls,
1586 struct GNUNET_CADET_Channel *channel,
1588 const struct GNUNET_MessageHeader *m)
1590 const struct MulticastJoinDecisionMessage *
1591 dcsn = (const struct MulticastJoinDecisionMessage *) m;
1592 uint16_t size = ntohs (m->size);
1593 if (size < sizeof (*dcsn))
1595 GNUNET_break_op (0);
1596 return GNUNET_SYSERR;
1598 struct Channel *chn = *ctx;
1601 GNUNET_break_op (0);
1602 return GNUNET_SYSERR;
1604 if (NULL == chn->grp || GNUNET_NO != chn->grp->is_origin)
1606 GNUNET_break_op (0);
1607 return GNUNET_SYSERR;
1609 switch (chn->join_status)
1612 return GNUNET_SYSERR;
1617 case JOIN_NOT_ASKED:
1622 struct MulticastJoinDecisionMessageHeader *
1623 hdcsn = GNUNET_malloc (sizeof (*hdcsn) + size);
1624 hdcsn->peer = chn->peer;
1625 GNUNET_memcpy (&hdcsn[1], dcsn, sizeof (*hdcsn) + size);
1627 struct Member *mem = (struct Member *) chn->grp;
1628 client_send_join_decision (mem, hdcsn);
1629 GNUNET_free (hdcsn);
1630 if (GNUNET_YES == ntohs (dcsn->is_admitted))
1632 chn->join_status = JOIN_ADMITTED;
1637 chn->join_status = JOIN_REFUSED;
1638 return GNUNET_SYSERR;
1643 * Incoming multicast message from CADET.
1646 cadet_recv_message (void *cls,
1647 struct GNUNET_CADET_Channel *channel,
1649 const struct GNUNET_MessageHeader *m)
1651 const struct GNUNET_MULTICAST_MessageHeader *
1652 msg = (const struct GNUNET_MULTICAST_MessageHeader *) m;
1653 uint16_t size = ntohs (m->size);
1654 if (size < sizeof (*msg))
1656 GNUNET_break_op (0);
1657 return GNUNET_SYSERR;
1659 struct Channel *chn = *ctx;
1662 GNUNET_break_op (0);
1663 return GNUNET_SYSERR;
1665 if (ntohl (msg->purpose.size) != (size
1666 - sizeof (msg->header)
1667 - sizeof (msg->hop_counter)
1668 - sizeof (msg->signature)))
1670 GNUNET_break_op (0);
1671 return GNUNET_SYSERR;
1674 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE,
1675 &msg->purpose, &msg->signature,
1676 &chn->group_pub_key))
1678 GNUNET_break_op (0);
1679 return GNUNET_SYSERR;
1682 client_send_all (&chn->group_pub_hash, m);
1688 * Incoming multicast request message from CADET.
1691 cadet_recv_request (void *cls,
1692 struct GNUNET_CADET_Channel *channel,
1694 const struct GNUNET_MessageHeader *m)
1696 const struct GNUNET_MULTICAST_RequestHeader *
1697 req = (const struct GNUNET_MULTICAST_RequestHeader *) m;
1698 uint16_t size = ntohs (m->size);
1699 if (size < sizeof (*req))
1701 GNUNET_break_op (0);
1702 return GNUNET_SYSERR;
1704 struct Channel *chn = *ctx;
1707 GNUNET_break_op (0);
1708 return GNUNET_SYSERR;
1710 if (ntohl (req->purpose.size) != (size
1711 - sizeof (req->header)
1712 - sizeof (req->member_pub_key)
1713 - sizeof (req->signature)))
1715 GNUNET_break_op (0);
1716 return GNUNET_SYSERR;
1719 GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST,
1720 &req->purpose, &req->signature,
1721 &req->member_pub_key))
1723 GNUNET_break_op (0);
1724 return GNUNET_SYSERR;
1727 client_send_origin (&chn->group_pub_hash, m);
1733 * Incoming multicast replay request from CADET.
1736 cadet_recv_replay_request (void *cls,
1737 struct GNUNET_CADET_Channel *channel,
1739 const struct GNUNET_MessageHeader *m)
1741 struct MulticastReplayRequestMessage rep;
1742 uint16_t size = ntohs (m->size);
1743 if (size < sizeof (rep))
1745 GNUNET_break_op (0);
1746 return GNUNET_SYSERR;
1748 struct Channel *chn = *ctx;
1750 GNUNET_memcpy (&rep, m, sizeof (rep));
1751 GNUNET_memcpy (&rep.member_pub_key, &chn->member_pub_key, sizeof (chn->member_pub_key));
1753 struct GNUNET_CONTAINER_MultiHashMap *
1754 grp_replay_req = GNUNET_CONTAINER_multihashmap_get (replay_req_cadet,
1755 &chn->grp->pub_key_hash);
1756 if (NULL == grp_replay_req)
1758 grp_replay_req = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1759 GNUNET_CONTAINER_multihashmap_put (replay_req_cadet,
1760 &chn->grp->pub_key_hash, grp_replay_req,
1761 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1763 struct GNUNET_HashCode key_hash;
1764 replay_key_hash (rep.fragment_id, rep.message_id, rep.fragment_offset,
1765 rep.flags, &key_hash);
1766 GNUNET_CONTAINER_multihashmap_put (grp_replay_req, &key_hash, chn,
1767 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1769 client_send_random (&chn->group_pub_hash, &rep.header);
1775 * Incoming multicast replay response from CADET.
1778 cadet_recv_replay_response (void *cls,
1779 struct GNUNET_CADET_Channel *channel,
1781 const struct GNUNET_MessageHeader *m)
1783 //struct Channel *chn = *ctx;
1785 /* @todo FIXME: got replay error response, send request to other members */
1792 * Message handlers for CADET.
1794 static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
1795 { cadet_recv_join_request,
1796 GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST, 0 },
1798 { cadet_recv_message,
1799 GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, 0 },
1801 { cadet_recv_request,
1802 GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST, 0 },
1804 { cadet_recv_replay_request,
1805 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST, 0 },
1807 { cadet_recv_replay_response,
1808 GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_RESPONSE, 0 },
1815 * Connected to core service.
1818 core_connected_cb (void *cls, const struct GNUNET_PeerIdentity *my_identity)
1820 this_peer = *my_identity;
1822 stats = GNUNET_STATISTICS_create ("multicast", cfg);
1823 origins = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1824 members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1825 group_members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1826 channels_in = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1827 channels_out = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
1828 replay_req_cadet = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1829 replay_req_client = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
1831 cadet = GNUNET_CADET_connect (cfg, NULL,
1832 &cadet_notify_channel_end,
1834 GNUNET_assert (NULL != cadet);
1835 GNUNET_CADET_open_port (cadet, GC_u2h (GNUNET_APPLICATION_TYPE_MULTICAST),
1836 &cadet_notify_channel_new, NULL);
1838 nc = GNUNET_SERVER_notification_context_create (server, 1);
1839 GNUNET_SERVER_add_handlers (server, server_handlers);
1840 GNUNET_SERVER_disconnect_notify (server,
1841 &client_notify_disconnect, NULL);
1842 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
1850 * @param cls closure
1851 * @param server the initialized server
1852 * @param cfg configuration to use
1856 struct GNUNET_SERVER_Handle *srv,
1857 const struct GNUNET_CONFIGURATION_Handle *c)
1861 GNUNET_SERVER_connect_notify (server, &client_notify_connect, NULL);
1862 core = GNUNET_CORE_connect (cfg, NULL, &core_connected_cb, NULL, NULL,
1863 NULL, GNUNET_NO, NULL, GNUNET_NO, NULL);
1868 * The main function for the multicast service.
1870 * @param argc number of arguments from the command line
1871 * @param argv command line arguments
1872 * @return 0 ok, 1 on error
1875 main (int argc, char *const *argv)
1877 return (GNUNET_OK ==
1878 GNUNET_SERVICE_run (argc, argv, "multicast",
1879 GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
1882 /* end of gnunet-service-multicast.c */