#include "gnunet_util_lib.h"
#include "gnunet_signatures.h"
#include "gnunet_statistics_service.h"
+#include "gnunet_core_service.h"
#include "gnunet_multicast_service.h"
#include "multicast.h"
*/
static const struct GNUNET_CONFIGURATION_Handle *cfg;
+/**
+ * Server handle.
+ */
+static struct GNUNET_SERVER_Handle *server;
+
+/**
+ * Core handle.
+ * Only used during initialization.
+ */
+static struct GNUNET_CORE_Handle *core;
+
+/**
+ * Identity of this peer.
+ */
+static struct GNUNET_PeerIdentity this_peer;
+
/**
* Handle to the statistics service.
*/
*/
static struct GNUNET_CONTAINER_MultiHashMap *group_members;
-
/**
* List of connected clients.
*/
/**
* Private key of the member.
*/
- struct GNUNET_CRYPTO_EddsaPrivateKey priv_key;
+ struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key;
/**
* Public key of the member.
*/
- struct GNUNET_CRYPTO_EddsaPublicKey pub_key;
+ struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
/**
* Hash of @a pub_key.
/**
* Join request sent to the origin / members.
*/
- struct MulticastJoinRequestMessage *join_request;
+ struct MulticastJoinRequestMessage *join_req;
/**
* Join decision sent in reply to our request.
* Only a positive decision is stored here, in case of a negative decision the
* client is disconnected.
*/
- struct MulticastJoinDecisionMessage *join_decision;
+ struct MulticastJoinDecisionMessageHeader *join_dcsn;
/**
* Last request fragment ID sent to the origin.
* @param tc unused
*/
static void
-cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
- /* FIXME: do clean up here */
+ if (NULL != core)
+ {
+ GNUNET_CORE_disconnect (core);
+ core = NULL;
+ }
+ if (NULL != stats)
+ {
+ GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
+ stats = NULL;
+ }
+ /* FIXME: do more clean up here */
}
/**
grp_mem);
GNUNET_CONTAINER_multihashmap_destroy (grp_mem);
}
- if (NULL != mem->join_decision)
- GNUNET_free (mem->join_decision);
+ if (NULL != mem->join_dcsn)
+ {
+ GNUNET_free (mem->join_dcsn);
+ mem->join_dcsn = NULL;
+ }
GNUNET_CONTAINER_multihashmap_remove (members, &grp->pub_key_hash, mem);
}
const struct GNUNET_MessageHeader *msg = cls;
struct Member *mem = member;
- if (NULL != mem->join_decision)
+ if (NULL != mem->join_dcsn)
{ /* Only send message to admitted members */
message_to_clients (&mem->grp, msg);
}
* Handle a connecting client starting an origin.
*/
static void
-handle_origin_start (void *cls, struct GNUNET_SERVER_Client *client,
+client_origin_start (void *cls, struct GNUNET_SERVER_Client *client,
const struct GNUNET_MessageHeader *m)
{
const struct MulticastOriginStartMessage *
{
orig = GNUNET_new (struct Origin);
orig->priv_key = msg->group_key;
+ orig->max_fragment_id = GNUNET_ntohll (msg->max_fragment_id);
grp = &orig->grp;
grp->is_origin = GNUNET_YES;
grp->pub_key = pub_key;
* Handle a connecting client joining a group.
*/
static void
-handle_member_join (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *m)
+client_member_join (void *cls, struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *m)
{
const struct MulticastMemberJoinMessage *
msg = (const struct MulticastMemberJoinMessage *) m;
+ uint16_t msg_size = ntohs (msg->header.size);
- struct GNUNET_CRYPTO_EddsaPublicKey mem_pub_key;
+ struct GNUNET_CRYPTO_EcdsaPublicKey mem_pub_key;
struct GNUNET_HashCode pub_key_hash, mem_pub_key_hash;
- GNUNET_CRYPTO_eddsa_key_get_public (&msg->member_key, &mem_pub_key);
+ GNUNET_CRYPTO_ecdsa_key_get_public (&msg->member_key, &mem_pub_key);
GNUNET_CRYPTO_hash (&mem_pub_key, sizeof (mem_pub_key), &mem_pub_key_hash);
GNUNET_CRYPTO_hash (&msg->group_key, sizeof (msg->group_key), &pub_key_hash);
mem->priv_key = msg->member_key;
mem->pub_key = mem_pub_key;
mem->pub_key_hash = mem_pub_key_hash;
+ mem->max_fragment_id = 0; // FIXME
grp = &mem->grp;
grp->is_origin = GNUNET_NO;
GNUNET_SERVER_client_set_user_context (client, grp);
- if (NULL != mem->join_decision)
+ if (NULL != mem->join_dcsn)
{ /* Already got a join decision, send it to client. */
GNUNET_SERVER_notification_context_add (nc, client);
GNUNET_SERVER_notification_context_unicast (nc, client,
(struct GNUNET_MessageHeader *)
- mem->join_decision,
+ mem->join_dcsn,
GNUNET_NO);
}
else if (grp->clients_head == grp->clients_tail)
- { /* First client, send join request. */
+ { /* First client of the group, send join request. */
struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1];
uint32_t relay_count = ntohs (msg->relay_count);
- struct GNUNET_MessageHeader *
- join_msg = ((struct GNUNET_MessageHeader *)
- ((char *) &msg[1]) + relay_count * sizeof (*relays));
- uint16_t join_msg_size = ntohs (join_msg->size);
+ uint16_t relay_size = relay_count * sizeof (*relays);
+ struct GNUNET_MessageHeader *join_msg = NULL;
+ uint16_t join_msg_size = 0;
+ if (sizeof (*msg) + relay_size + sizeof (struct GNUNET_MessageHeader)
+ <= msg_size)
+ {
+ join_msg = (struct GNUNET_MessageHeader *)
+ (((char *) &msg[1]) + relay_size);
+ join_msg_size = ntohs (join_msg->size);
+ }
+ if (sizeof (*msg) + relay_size + join_msg_size != msg_size)
+ {
+ GNUNET_break (0);
+ GNUNET_SERVER_client_disconnect (client);
+ return;
+ }
struct MulticastJoinRequestMessage *
req = GNUNET_malloc (sizeof (*req) + join_msg_size);
req->header.size = htons (sizeof (*req) + join_msg_size);
req->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST);
req->group_key = grp->pub_key;
- GNUNET_CRYPTO_eddsa_key_get_public (&mem->priv_key, &req->member_key);
- memcpy (&req[1], join_msg, join_msg_size);
+ req->member_peer = this_peer;
+ GNUNET_CRYPTO_ecdsa_key_get_public (&mem->priv_key, &req->member_key);
+ if (0 < join_msg_size)
+ memcpy (&req[1], join_msg, join_msg_size);
req->purpose.size = htonl (sizeof (*req) + join_msg_size
- sizeof (req->header)
- sizeof (req->signature));
req->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
- if (GNUNET_OK != GNUNET_CRYPTO_eddsa_sign (&mem->priv_key, &req->purpose,
+ if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (&mem->priv_key, &req->purpose,
&req->signature))
{
/* FIXME: handle error */
GNUNET_assert (0);
}
- if (NULL != mem->join_request)
- GNUNET_free (mem->join_request);
- mem->join_request = req;
+ if (NULL != mem->join_req)
+ GNUNET_free (mem->join_req);
+ mem->join_req = req;
if (GNUNET_YES
== GNUNET_CONTAINER_multihashmap_contains (origins, &grp->pub_key_hash))
{ /* Local origin */
- message_to_origin (grp, (struct GNUNET_MessageHeader *) mem->join_request);
+ message_to_origin (grp, (struct GNUNET_MessageHeader *) mem->join_req);
}
else
{
* Join decision from client.
*/
static void
-handle_join_decision (void *cls, struct GNUNET_SERVER_Client *client,
+client_join_decision (void *cls, struct GNUNET_SERVER_Client *client,
const struct GNUNET_MessageHeader *m)
{
struct Group *
grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
- const struct MulticastClientJoinDecisionMessage *
- cl_dcsn = (const struct MulticastClientJoinDecisionMessage *) m;
-
- struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &cl_dcsn[1];
- uint32_t relay_count = ntohs (cl_dcsn->relay_count);
-
- struct GNUNET_MessageHeader *join_msg = NULL;
- uint16_t join_msg_size = 0;
- if (sizeof (*cl_dcsn) + relay_count * sizeof (*relays) + sizeof (*m)
- <= ntohs (m->size))
- {
- join_msg = ((struct GNUNET_MessageHeader *)
- ((char *) &cl_dcsn[1]) + relay_count * sizeof (*relays));
- join_msg_size = ntohs (join_msg->size);
- }
-
- struct MulticastJoinDecisionMessage *
- dcsn = GNUNET_malloc (sizeof (*dcsn) + join_msg_size);
- dcsn->header.size = htons (sizeof (*dcsn) + join_msg_size);
- dcsn->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION);
- dcsn->is_admitted = cl_dcsn->is_admitted;
- memcpy (&dcsn[1], join_msg, join_msg_size);
+ const struct MulticastJoinDecisionMessageHeader *
+ hdcsn = (const struct MulticastJoinDecisionMessageHeader *) m;
+ const struct MulticastJoinDecisionMessage *
+ dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1];
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"%p Got join decision from client for group %s..\n",
if (NULL != grp_mem)
{
struct GNUNET_HashCode member_key_hash;
- GNUNET_CRYPTO_hash (&cl_dcsn->member_key, sizeof (cl_dcsn->member_key),
+ GNUNET_CRYPTO_hash (&hdcsn->member_key, sizeof (hdcsn->member_key),
&member_key_hash);
struct Member *
mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &member_key_hash);
grp, GNUNET_h2s (&member_key_hash), mem);
if (NULL != mem)
{
- message_to_clients (grp, (struct GNUNET_MessageHeader *) dcsn);
- if (GNUNET_YES == dcsn->is_admitted)
+ message_to_clients (&mem->grp, (struct GNUNET_MessageHeader *) hdcsn);
+ if (GNUNET_YES == ntohl (dcsn->is_admitted))
{ /* Member admitted, store join_decision. */
- mem->join_decision = dcsn;
+ uint16_t dcsn_size = ntohs (dcsn->header.size);
+ mem->join_dcsn = GNUNET_malloc (dcsn_size);
+ memcpy (mem->join_dcsn, dcsn, dcsn_size);
}
else
{ /* Refused entry, disconnect clients. */
- GNUNET_free (dcsn);
struct ClientList *cl = mem->grp.clients_head;
while (NULL != cl)
{
- GNUNET_SERVER_client_disconnect (cl->client);
+ struct GNUNET_SERVER_Client *client = cl->client;
cl = cl->next;
+ GNUNET_SERVER_client_disconnect (client);
}
}
}
}
else
{
- /* FIXME: send join decision to remote peers */
+ /* FIXME: send join decision to hdcsn->peer */
}
GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
* Incoming message from a client.
*/
static void
-handle_multicast_message (void *cls, struct GNUNET_SERVER_Client *client,
+client_multicast_message (void *cls, struct GNUNET_SERVER_Client *client,
const struct GNUNET_MessageHeader *m)
{
struct Group *
struct GNUNET_MULTICAST_MessageHeader *
msg = (struct GNUNET_MULTICAST_MessageHeader *) m;
- msg->fragment_id = GNUNET_htonll (orig->max_fragment_id++);
+ msg->fragment_id = GNUNET_htonll (++orig->max_fragment_id);
msg->purpose.size = htonl (sizeof (*msg) + ntohs (m->size)
- sizeof (msg->header)
- sizeof (msg->hop_counter)
* Incoming request from a client.
*/
static void
-handle_multicast_request (void *cls, struct GNUNET_SERVER_Client *client,
+client_multicast_request (void *cls, struct GNUNET_SERVER_Client *client,
const struct GNUNET_MessageHeader *m)
{
struct Group *
struct GNUNET_MULTICAST_RequestHeader *
req = (struct GNUNET_MULTICAST_RequestHeader *) m;
- req->fragment_id = GNUNET_ntohll (mem->max_fragment_id++);
-
+ req->fragment_id = GNUNET_ntohll (++mem->max_fragment_id);
req->purpose.size = htonl (sizeof (*req) + ntohs (m->size)
- sizeof (req->header)
- sizeof (req->member_key)
- sizeof (req->signature));
req->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
- if (GNUNET_OK != GNUNET_CRYPTO_eddsa_sign (&mem->priv_key, &req->purpose,
+ if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (&mem->priv_key, &req->purpose,
&req->signature))
{
/* FIXME: handle error */
GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
+
/**
- * Process multicast requests.
- *
- * @param cls closure
- * @param server the initialized server
- * @param cfg configuration to use
+ * Connected to core service.
*/
static void
-run (void *cls, struct GNUNET_SERVER_Handle *server,
- const struct GNUNET_CONFIGURATION_Handle *c)
+core_connected_cb (void *cls, const struct GNUNET_PeerIdentity *my_identity)
{
+ this_peer = *my_identity;
+
static const struct GNUNET_SERVER_MessageHandler handlers[] = {
- { &handle_origin_start, NULL,
+ { &client_origin_start, NULL,
GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START, 0 },
- { &handle_member_join, NULL,
+ { &client_member_join, NULL,
GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_JOIN, 0 },
- { &handle_join_decision, NULL,
+ { &client_join_decision, NULL,
GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION, 0 },
- { &handle_multicast_message, NULL,
+ { &client_multicast_message, NULL,
GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, 0 },
- { &handle_multicast_request, NULL,
+ { &client_multicast_request, NULL,
GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST, 0 },
{NULL, NULL, 0, 0}
};
- cfg = c;
stats = GNUNET_STATISTICS_create ("multicast", cfg);
origins = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
GNUNET_SERVER_add_handlers (server, handlers);
GNUNET_SERVER_disconnect_notify (server, &client_disconnect, NULL);
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
+ GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
NULL);
}
+/**
+ * Service started.
+ *
+ * @param cls closure
+ * @param server the initialized server
+ * @param cfg configuration to use
+ */
+static void
+run (void *cls, struct GNUNET_SERVER_Handle *srv,
+ const struct GNUNET_CONFIGURATION_Handle *c)
+{
+ cfg = c;
+ server = srv;
+ core = GNUNET_CORE_connect (cfg, NULL, core_connected_cb, NULL, NULL,
+ NULL, GNUNET_NO, NULL, GNUNET_NO, NULL);
+}
+
+
/**
* The main function for the multicast service.
*