From: Christian Grothoff Date: Tue, 20 Sep 2016 15:14:05 +0000 (+0000) Subject: converting core service to new service API X-Git-Tag: initial-import-from-subversion-38251~242 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=5663ca18885242fca4dd209898ffda9cbe675c58;p=oweals%2Fgnunet.git converting core service to new service API --- diff --git a/src/core/Makefile.am b/src/core/Makefile.am index a99f74af6..aea64fa34 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -41,7 +41,6 @@ bin_PROGRAMS = \ gnunet_service_core_SOURCES = \ gnunet-service-core.c gnunet-service-core.h \ - gnunet-service-core_clients.c gnunet-service-core_clients.h \ gnunet-service-core_kx.c gnunet-service-core_kx.h \ gnunet-service-core_sessions.c gnunet-service-core_sessions.h \ gnunet-service-core_typemap.c gnunet-service-core_typemap.h diff --git a/src/core/core_api.c b/src/core/core_api.c index 6055b99c1..67f17352d 100644 --- a/src/core/core_api.c +++ b/src/core/core_api.c @@ -541,11 +541,12 @@ handle_notify_inbound (void *cls, uint16_t et; GNUNET_break (GNUNET_NO == h->currently_down); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Received inbound message from `%s'.\n", - GNUNET_i2s (&ntm->peer)); em = (const struct GNUNET_MessageHeader *) &ntm[1]; et = ntohs (em->type); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Received inbound message of type %d from `%s'.\n", + (int) et, + GNUNET_i2s (&ntm->peer)); for (unsigned int hpos = 0; NULL != h->handlers[hpos].callback; hpos++) { const struct GNUNET_CORE_MessageHandler *mh; diff --git a/src/core/gnunet-service-core.c b/src/core/gnunet-service-core.c index f9391e616..acaa10092 100644 --- a/src/core/gnunet-service-core.c +++ b/src/core/gnunet-service-core.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - Copyright (C) 2009, 2010, 2011 GNUnet e.V. + Copyright (C) 2009, 2010, 2011, 2016 GNUnet e.V. GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -27,11 +27,75 @@ #include #include "gnunet_util_lib.h" #include "gnunet-service-core.h" -#include "gnunet-service-core_clients.h" #include "gnunet-service-core_kx.h" #include "gnunet-service-core_sessions.h" #include "gnunet-service-core_typemap.h" +/** + * How many messages do we queue up at most for optional + * notifications to a client? (this can cause notifications + * about outgoing messages to be dropped). + */ +#define MAX_NOTIFY_QUEUE 1024 + + +/** + * Data structure for each client connected to the CORE service. + */ +struct GSC_Client +{ + /** + * Clients are kept in a linked list. + */ + struct GSC_Client *next; + + /** + * Clients are kept in a linked list. + */ + struct GSC_Client *prev; + + /** + * Handle for the client with the server API. + */ + struct GNUNET_SERVICE_Client *client; + + /** + * Message queue to talk to @e client. + */ + struct GNUNET_MQ_Handle *mq; + + /** + * Array of the types of messages this peer cares + * about (with @e tcnt entries). Allocated as part + * of this client struct, do not free! + */ + uint16_t *types; + + /** + * Map of peer identities to active transmission requests of this + * client to the peer (of type `struct GSC_ClientActiveRequest`). + */ + struct GNUNET_CONTAINER_MultiPeerMap *requests; + + /** + * Map containing all peers that this client knows we're connected to. + */ + struct GNUNET_CONTAINER_MultiPeerMap *connectmap; + + /** + * Options for messages this client cares about, + * see GNUNET_CORE_OPTION_ values. + */ + uint32_t options; + + /** + * Number of types of incoming messages this client + * specifically cares about. Size of the @e types array. + */ + unsigned int tcnt; + +}; + /** * Our identity. @@ -49,9 +113,739 @@ const struct GNUNET_CONFIGURATION_Handle *GSC_cfg; struct GNUNET_STATISTICS_Handle *GSC_stats; /** - * Handle to the server of the core service. + * Big "or" of all client options. + */ +static uint32_t all_client_options; + +/** + * Head of linked list of our clients. + */ +static struct GSC_Client *client_head; + +/** + * Tail of linked list of our clients. + */ +static struct GSC_Client *client_tail; + + +/** + * Test if the client is interested in messages of the given type. + * + * @param type message type + * @param c client to test + * @return #GNUNET_YES if @a c is interested, #GNUNET_NO if not. + */ +static int +type_match (uint16_t type, + struct GSC_Client *c) +{ + if ( (0 == c->tcnt) && + (0 != c->options) ) + return GNUNET_YES; /* peer without handlers and inbound/outbond + callbacks matches ALL */ + if (NULL == c->types) + return GNUNET_NO; + for (unsigned int i = 0; i < c->tcnt; i++) + if (type == c->types[i]) + return GNUNET_YES; + return GNUNET_NO; +} + + +/** + * Check #GNUNET_MESSAGE_TYPE_CORE_INIT request. + * + * @param cls client that sent #GNUNET_MESSAGE_TYPE_CORE_INIT + * @param im the `struct InitMessage` + * @return #GNUNET_OK if @a im is well-formed */ -static struct GNUNET_SERVER_Handle *GSC_server; +static int +check_client_init (void *cls, + const struct InitMessage *im) +{ + return GNUNET_OK; +} + + +/** + * Handle #GNUNET_MESSAGE_TYPE_CORE_INIT request. + * + * @param cls client that sent #GNUNET_MESSAGE_TYPE_CORE_INIT + * @param im the `struct InitMessage` + */ +static void +handle_client_init (void *cls, + const struct InitMessage *im) +{ + struct GSC_Client *c = cls; + struct GNUNET_MQ_Envelope *env; + struct InitReplyMessage *irm; + uint16_t msize; + const uint16_t *types; + + /* check that we don't have an entry already */ + msize = ntohs (im->header.size) - sizeof (struct InitMessage); + types = (const uint16_t *) &im[1]; + c->tcnt = msize / sizeof (uint16_t); + c->options = ntohl (im->options); + all_client_options |= c->options; + c->types = GNUNET_malloc (msize); + c->connectmap = GNUNET_CONTAINER_multipeermap_create (16, + GNUNET_NO); + GNUNET_assert (GNUNET_YES == + GNUNET_CONTAINER_multipeermap_put (c->connectmap, + &GSC_my_identity, + NULL, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); + for (unsigned int i = 0; i < c->tcnt; i++) + c->types[i] = ntohs (types[i]); + GSC_TYPEMAP_add (c->types, + c->tcnt); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Client connecting to core service is interested in %u message types\n", + (unsigned int) c->tcnt); + /* send init reply message */ + env = GNUNET_MQ_msg (irm, + GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY); + irm->reserved = htonl (0); + irm->my_identity = GSC_my_identity; + GNUNET_MQ_send (c->mq, + env); + GSC_SESSIONS_notify_client_about_sessions (c); + GNUNET_SERVICE_client_continue (c->client); +} + + +/** + * We will never be ready to transmit the given message in (disconnect + * or invalid request). Frees resources associated with @a car. We + * don't explicitly tell the client, he'll learn with the disconnect + * (or violated the protocol). + * + * @param car request that now permanently failed; the + * responsibility for the handle is now returned + * to CLIENTS (SESSIONS is done with it). + * @param drop_client #GNUNET_YES if the client violated the protocol + * and we should thus drop the connection + */ +void +GSC_CLIENTS_reject_request (struct GSC_ClientActiveRequest *car, + int drop_client) +{ + GNUNET_assert (GNUNET_YES == + GNUNET_CONTAINER_multipeermap_remove (car-> + client_handle->requests, + &car->target, + car)); + if (GNUNET_YES == drop_client) + GNUNET_SERVICE_client_drop (car->client_handle->client); + GNUNET_free (car); +} + + +/** + * Tell a client that we are ready to receive the message. + * + * @param car request that is now ready; the responsibility + * for the handle remains shared between CLIENTS + * and SESSIONS after this call. + */ +void +GSC_CLIENTS_solicit_request (struct GSC_ClientActiveRequest *car) +{ + struct GSC_Client *c; + struct GNUNET_MQ_Envelope *env; + struct SendMessageReady *smr; + struct GNUNET_TIME_Relative delay; + struct GNUNET_TIME_Relative left; + + c = car->client_handle; + if (GNUNET_YES != + GNUNET_CONTAINER_multipeermap_contains (c->connectmap, + &car->target)) + { + /* connection has gone down since, drop request */ + GNUNET_assert (0 != + memcmp (&car->target, + &GSC_my_identity, + sizeof (struct GNUNET_PeerIdentity))); + GSC_SESSIONS_dequeue_request (car); + GSC_CLIENTS_reject_request (car, + GNUNET_NO); + return; + } + delay = GNUNET_TIME_absolute_get_duration (car->received_time); + left = GNUNET_TIME_absolute_get_duration (car->deadline); + if (delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us) + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Client waited %s for permission to transmit to `%s'%s (priority %u)\n", + GNUNET_STRINGS_relative_time_to_string (delay, + GNUNET_YES), + GNUNET_i2s (&car->target), + (0 == left.rel_value_us) + ? " (past deadline)" + : "", + car->priority); + env = GNUNET_MQ_msg (smr, + GNUNET_MESSAGE_TYPE_CORE_SEND_READY); + smr->size = htons (car->msize); + smr->smr_id = car->smr_id; + smr->peer = car->target; + GNUNET_MQ_send (c->mq, + env); +} + + +/** + * Handle #GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST message. + * + * @param cls client that sent a #GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST + * @param req the `struct SendMessageRequest` + */ +static void +handle_client_send_request (void *cls, + const struct SendMessageRequest *req) +{ + struct GSC_Client *c = cls; + struct GSC_ClientActiveRequest *car; + int is_loopback; + + if (NULL == c->requests) + c->requests = GNUNET_CONTAINER_multipeermap_create (16, + GNUNET_NO); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Client asked for transmission to `%s'\n", + GNUNET_i2s (&req->peer)); + is_loopback = + (0 == + memcmp (&req->peer, + &GSC_my_identity, + sizeof (struct GNUNET_PeerIdentity))); + if ((! is_loopback) && + (GNUNET_YES != + GNUNET_CONTAINER_multipeermap_contains (c->connectmap, + &req->peer))) + { + /* neighbour must have disconnected since request was issued, + * ignore (client will realize it once it processes the + * disconnect notification) */ + GNUNET_STATISTICS_update (GSC_stats, + gettext_noop + ("# send requests dropped (disconnected)"), 1, + GNUNET_NO); + GNUNET_SERVICE_client_continue (c->client); + return; + } + + car = GNUNET_CONTAINER_multipeermap_get (c->requests, + &req->peer); + if (NULL == car) + { + /* create new entry */ + car = GNUNET_new (struct GSC_ClientActiveRequest); + GNUNET_assert (GNUNET_OK == + GNUNET_CONTAINER_multipeermap_put (c->requests, + &req->peer, + car, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); + car->client_handle = c; + } + else + { + /* dequeue and recycle memory from pending request, there can only + be at most one per client and peer */ + GNUNET_STATISTICS_update (GSC_stats, + gettext_noop ("# dequeuing CAR (duplicate request)"), + 1, + GNUNET_NO); + GSC_SESSIONS_dequeue_request (car); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Transmission request to `%s' was a duplicate!\n", + GNUNET_i2s (&req->peer)); + } + car->target = req->peer; + car->received_time = GNUNET_TIME_absolute_get (); + car->deadline = GNUNET_TIME_absolute_ntoh (req->deadline); + car->priority = (enum GNUNET_CORE_Priority) ntohl (req->priority); + car->msize = ntohs (req->size); + car->smr_id = req->smr_id; + car->was_solicited = GNUNET_NO; + GNUNET_SERVICE_client_continue (c->client); + if (is_loopback) + { + /* loopback, satisfy immediately */ + GSC_CLIENTS_solicit_request (car); + return; + } + GSC_SESSIONS_queue_request (car); +} + + +/** + * Closure for the #client_tokenizer_callback(). + */ +struct TokenizerContext +{ + + /** + * Active request handle for the message. + */ + struct GSC_ClientActiveRequest *car; + + /** + * How important is this message. + */ + enum GNUNET_CORE_Priority priority; + + /** + * Is corking allowed (set only once we have the real message). + */ + int cork; + +}; + + +/** + * Functions with this signature are called whenever a complete + * message is received by the tokenizer. Used by + * #handle_client_send() for dispatching messages from clients to + * either the SESSION subsystem or other CLIENT (for loopback). + * + * @param cls reservation request (`struct TokenizerContext`) + * @param message the actual message + */ +static int +tokenized_cb (void *cls, + const struct GNUNET_MessageHeader *message) +{ + struct TokenizerContext *tc = cls; + struct GSC_ClientActiveRequest *car = tc->car; + char buf[92]; + + GNUNET_snprintf (buf, + sizeof (buf), + gettext_noop ("# bytes of messages of type %u received"), + (unsigned int) ntohs (message->type)); + GNUNET_STATISTICS_update (GSC_stats, + buf, + ntohs (message->size), + GNUNET_NO); + if (0 == + memcmp (&car->target, + &GSC_my_identity, + sizeof (struct GNUNET_PeerIdentity))) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Delivering message of type %u to myself\n", + ntohs (message->type)); + GSC_CLIENTS_deliver_message (&GSC_my_identity, + message, + ntohs (message->size), + GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND); + GSC_CLIENTS_deliver_message (&GSC_my_identity, + message, + sizeof (struct GNUNET_MessageHeader), + GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND); + GSC_CLIENTS_deliver_message (&GSC_my_identity, + message, + ntohs (message->size), + GNUNET_CORE_OPTION_SEND_FULL_INBOUND); + GSC_CLIENTS_deliver_message (&GSC_my_identity, + message, + sizeof (struct GNUNET_MessageHeader), + GNUNET_CORE_OPTION_SEND_HDR_INBOUND); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Delivering message of type %u and size %u to %s\n", + ntohs (message->type), + ntohs (message->size), + GNUNET_i2s (&car->target)); + GSC_CLIENTS_deliver_message (&car->target, + message, + ntohs (message->size), + GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND); + GSC_CLIENTS_deliver_message (&car->target, + message, + sizeof (struct GNUNET_MessageHeader), + GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND); + GSC_SESSIONS_transmit (car, + message, + tc->cork, + tc->priority); + } + return GNUNET_OK; +} + + +/** + * Check #GNUNET_MESSAGE_TYPE_CORE_SEND request. + * + * @param cls the `struct GSC_Client` + * @param sm the `struct SendMessage` + * @return #GNUNET_OK if @a sm is well-formed + */ +static int +check_client_send (void *cls, + const struct SendMessage *sm) +{ + return GNUNET_OK; +} + + +/** + * Handle #GNUNET_MESSAGE_TYPE_CORE_SEND request. + * + * @param cls the `struct GSC_Client` + * @param sm the `struct SendMessage` + */ +static void +handle_client_send (void *cls, + const struct SendMessage *sm) +{ + struct GSC_Client *c = cls; + struct TokenizerContext tc; + uint16_t msize; + struct GNUNET_TIME_Relative delay; + struct GNUNET_MessageStreamTokenizer *mst; + + msize = ntohs (sm->header.size) - sizeof (struct SendMessage); + GNUNET_break (0 == ntohl (sm->reserved)); + tc.car = GNUNET_CONTAINER_multipeermap_get (c->requests, + &sm->peer); + if (NULL == tc.car) + { + /* Must have been that we first approved the request, then got disconnected + * (which triggered removal of the 'car') and now the client gives us a message + * just *before* the client learns about the disconnect. Theoretically, we + * might also now be *again* connected. So this can happen (but should be + * rare). If it does happen, the message is discarded. */ + GNUNET_STATISTICS_update (GSC_stats, + gettext_noop ("# messages discarded (session disconnected)"), + 1, + GNUNET_NO); + GNUNET_SERVICE_client_continue (c->client); + return; + } + delay = GNUNET_TIME_absolute_get_duration (tc.car->received_time); + tc.cork = ntohl (sm->cork); + tc.priority = (enum GNUNET_CORE_Priority) ntohl (sm->priority); + if (delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us) + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Client waited %s for transmission of %u bytes to `%s'%s\n", + GNUNET_STRINGS_relative_time_to_string (delay, + GNUNET_YES), + msize, + GNUNET_i2s (&sm->peer), + tc.cork ? " (cork)" : " (uncorked)"); + else + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Client waited %s for transmission of %u bytes to `%s'%s\n", + GNUNET_STRINGS_relative_time_to_string (delay, + GNUNET_YES), + msize, + GNUNET_i2s (&sm->peer), + tc.cork ? " (cork)" : " (uncorked)"); + + GNUNET_assert (GNUNET_YES == + GNUNET_CONTAINER_multipeermap_remove (c->requests, + &sm->peer, + tc.car)); + mst = GNUNET_MST_create (&tokenized_cb, + &tc); + GNUNET_MST_from_buffer (mst, + (const char *) &sm[1], + msize, + GNUNET_YES, + GNUNET_NO); + GNUNET_MST_destroy (mst); + GSC_SESSIONS_dequeue_request (tc.car); + GNUNET_free (tc.car); + GNUNET_SERVICE_client_continue (c->client); +} + + +/** + * Free client request records. + * + * @param cls NULL + * @param key identity of peer for which this is an active request + * @param value the `struct GSC_ClientActiveRequest` to free + * @return #GNUNET_YES (continue iteration) + */ +static int +destroy_active_client_request (void *cls, + const struct GNUNET_PeerIdentity *key, + void *value) +{ + struct GSC_ClientActiveRequest *car = value; + + GNUNET_assert (GNUNET_YES == + GNUNET_CONTAINER_multipeermap_remove (car-> + client_handle->requests, + &car->target, + car)); + GSC_SESSIONS_dequeue_request (car); + GNUNET_free (car); + return GNUNET_YES; +} + + +/** + * A client connected, set up. + * + * @param cls closure + * @param client identification of the client + * @param mq message queue to talk to @a client + * @return our client handle + */ +static void * +client_connect_cb (void *cls, + struct GNUNET_SERVICE_Client *client, + struct GNUNET_MQ_Handle *mq) +{ + struct GSC_Client *c; + + c = GNUNET_new (struct GSC_Client); + c->client = client; + c->mq = mq; + GNUNET_CONTAINER_DLL_insert (client_head, + client_tail, + c); + return c; +} + + +/** + * A client disconnected, clean up. + * + * @param cls closure + * @param client identification of the client + * @param app_ctx our `struct GST_Client` for @a client + */ +static void +client_disconnect_cb (void *cls, + struct GNUNET_SERVICE_Client *client, + void *app_ctx) +{ + struct GSC_Client *c = app_ctx; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Client %p has disconnected from core service.\n", + client); + GNUNET_CONTAINER_DLL_remove (client_head, + client_tail, + c); + if (NULL != c->requests) + { + GNUNET_CONTAINER_multipeermap_iterate (c->requests, + &destroy_active_client_request, + NULL); + GNUNET_CONTAINER_multipeermap_destroy (c->requests); + } + if (NULL != c->connectmap) + { + GNUNET_CONTAINER_multipeermap_destroy (c->connectmap); + c->connectmap = NULL; + } + if (NULL != c->types) + { + GSC_TYPEMAP_remove (c->types, + c->tcnt); + GNUNET_free (c->types); + } + GNUNET_free (c); + + /* recalculate 'all_client_options' */ + all_client_options = 0; + for (c = client_head; NULL != c ; c = c->next) + all_client_options |= c->options; +} + + +/** + * Notify a particular client about a change to existing connection to + * one of our neighbours (check if the client is interested). Called + * from #GSC_SESSIONS_notify_client_about_sessions(). + * + * @param client client to notify + * @param neighbour identity of the neighbour that changed status + * @param tmap_old previous type map for the neighbour, NULL for connect + * @param tmap_new updated type map for the neighbour, NULL for disconnect + */ +void +GSC_CLIENTS_notify_client_about_neighbour (struct GSC_Client *client, + const struct GNUNET_PeerIdentity *neighbour, + const struct GSC_TypeMap *tmap_old, + const struct GSC_TypeMap *tmap_new) +{ + struct GNUNET_MQ_Envelope *env; + int old_match; + int new_match; + + old_match = GSC_TYPEMAP_test_match (tmap_old, + client->types, + client->tcnt); + new_match = GSC_TYPEMAP_test_match (tmap_new, + client->types, + client->tcnt); + if (old_match == new_match) + { + GNUNET_assert (old_match == + GNUNET_CONTAINER_multipeermap_contains (client->connectmap, + neighbour)); + return; /* no change */ + } + if (GNUNET_NO == old_match) + { + struct ConnectNotifyMessage *cnm; + + /* send connect */ + GNUNET_assert (GNUNET_NO == + GNUNET_CONTAINER_multipeermap_contains (client->connectmap, + neighbour)); + GNUNET_assert (GNUNET_YES == + GNUNET_CONTAINER_multipeermap_put (client->connectmap, + neighbour, + NULL, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); + env = GNUNET_MQ_msg (cnm, + GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT); + cnm->reserved = htonl (0); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Sending NOTIFY_CONNECT message to client.\n"); + cnm->peer = *neighbour; + GNUNET_MQ_send (client->mq, + env); + } + else + { + struct DisconnectNotifyMessage *dcm; + + /* send disconnect */ + GNUNET_assert (GNUNET_YES == + GNUNET_CONTAINER_multipeermap_contains (client->connectmap, + neighbour)); + GNUNET_assert (GNUNET_YES == + GNUNET_CONTAINER_multipeermap_remove (client->connectmap, + neighbour, + NULL)); + env = GNUNET_MQ_msg (dcm, + GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT); + dcm->reserved = htonl (0); + dcm->peer = *neighbour; + GNUNET_MQ_send (client->mq, + env); + } +} + + +/** + * Notify all clients about a change to existing session. + * Called from SESSIONS whenever there is a change in sessions + * or types processed by the respective peer. + * + * @param neighbour identity of the neighbour that changed status + * @param tmap_old previous type map for the neighbour, NULL for connect + * @param tmap_new updated type map for the neighbour, NULL for disconnect + */ +void +GSC_CLIENTS_notify_clients_about_neighbour (const struct GNUNET_PeerIdentity *neighbour, + const struct GSC_TypeMap *tmap_old, + const struct GSC_TypeMap *tmap_new) +{ + struct GSC_Client *c; + + for (c = client_head; NULL != c; c = c->next) + GSC_CLIENTS_notify_client_about_neighbour (c, + neighbour, + tmap_old, + tmap_new); +} + + +/** + * Deliver P2P message to interested clients. Caller must have checked + * that the sending peer actually lists the given message type as one + * of its types. + * + * @param sender peer who sent us the message + * @param msg the message + * @param msize number of bytes to transmit + * @param options options for checking which clients should + * receive the message + */ +void +GSC_CLIENTS_deliver_message (const struct GNUNET_PeerIdentity *sender, + const struct GNUNET_MessageHeader *msg, + uint16_t msize, + uint32_t options) +{ + size_t size = msize + sizeof (struct NotifyTrafficMessage); + + if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE) + { + GNUNET_break (0); + return; + } + if (! ( (0 != (all_client_options & options)) || + (0 != (options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) )) + return; /* no client cares about this message notification */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Core service passes message from `%s' of type %u to client.\n", + GNUNET_i2s (sender), + (unsigned int) ntohs (msg->type)); + GSC_SESSIONS_add_to_typemap (sender, + ntohs (msg->type)); + + for (struct GSC_Client *c = client_head; NULL != c; c = c->next) + { + struct GNUNET_MQ_Envelope *env; + struct NotifyTrafficMessage *ntm; + uint16_t mtype; + int tm; + + tm = type_match (ntohs (msg->type), + c); + if (! ( (0 != (c->options & options)) || + ( (0 != (options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) && + (GNUNET_YES == tm) ) ) ) + continue; /* neither options nor type match permit the message */ + if ( (0 != (options & GNUNET_CORE_OPTION_SEND_HDR_INBOUND)) && + ( (0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) || + (GNUNET_YES == tm) ) ) + continue; + if ( (0 != (options & GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND)) && + (0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND)) ) + continue; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Sending %u message with %u bytes to client interested in messages of type %u.\n", + options, + ntohs (msg->size), + (unsigned int) ntohs (msg->type)); + + if (0 != (options & (GNUNET_CORE_OPTION_SEND_FULL_INBOUND | GNUNET_CORE_OPTION_SEND_HDR_INBOUND))) + mtype = GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND; + else + mtype = GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND; + env = GNUNET_MQ_msg_extra (ntm, + msize, + mtype); + ntm->peer = *sender; + GNUNET_memcpy (&ntm[1], + msg, + msize); + + GNUNET_assert ( (0 == (c->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) || + (GNUNET_YES != tm) || + (GNUNET_YES == + GNUNET_CONTAINER_multipeermap_contains (c->connectmap, + sender)) ); + GNUNET_MQ_send (c->mq, + env); + } +} /** @@ -63,9 +857,12 @@ static struct GNUNET_SERVER_Handle *GSC_server; static void shutdown_task (void *cls) { + struct GSC_Client *c; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core service shutting down.\n"); - GSC_CLIENTS_done (); + while (NULL != (c = client_head)) + GNUNET_SERVICE_client_drop (c->client); GSC_SESSIONS_done (); GSC_KX_done (); GSC_TYPEMAP_done (); @@ -79,23 +876,42 @@ shutdown_task (void *cls) } +/** + * Handle #GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request. For this + * request type, the client does not have to have transmitted an INIT + * request. All current peers are returned, regardless of which + * message types they accept. + * + * @param cls client sending the iteration request + * @param message iteration request message + */ +static void +handle_client_monitor_peers (void *cls, + const struct GNUNET_MessageHeader *message) +{ + struct GSC_Client *c = cls; + + GNUNET_SERVICE_client_continue (c->client); + GSC_KX_handle_client_monitor_peers (c->mq); +} + + /** * Initiate core service. * * @param cls closure - * @param server the initialized server * @param c configuration to use + * @param service the initialized service */ static void run (void *cls, - struct GNUNET_SERVER_Handle *server, - const struct GNUNET_CONFIGURATION_Handle *c) + const struct GNUNET_CONFIGURATION_Handle *c, + struct GNUNET_SERVICE_Handle *service) { struct GNUNET_CRYPTO_EddsaPrivateKey *pk; char *keyfile; GSC_cfg = c; - GSC_server = server; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (GSC_cfg, "PEER", @@ -111,20 +927,18 @@ run (void *cls, GSC_cfg); GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); - GNUNET_SERVER_suspend (server); + GNUNET_SERVICE_suspend (service); GSC_TYPEMAP_init (); pk = GNUNET_CRYPTO_eddsa_key_create_from_file (keyfile); GNUNET_free (keyfile); GNUNET_assert (NULL != pk); - if (GNUNET_OK != GSC_KX_init (pk, - server)) + if (GNUNET_OK != GSC_KX_init (pk)) { GNUNET_SCHEDULER_shutdown (); return; } GSC_SESSIONS_init (); - GSC_CLIENTS_init (GSC_server); - GNUNET_SERVER_resume (GSC_server); + GNUNET_SERVICE_resume (service); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Core service of `%s' ready.\n"), GNUNET_i2s (&GSC_my_identity)); @@ -132,19 +946,32 @@ run (void *cls, /** - * The main function for the transport service. - * - * @param argc number of arguments from the command line - * @param argv command line arguments - * @return 0 ok, 1 on error + * Define "main" method using service macro. */ -int -main (int argc, char *const *argv) -{ - return (GNUNET_OK == - GNUNET_SERVICE_run (argc, argv, "core", - GNUNET_SERVICE_OPTION_NONE, - &run, NULL)) ? 0 : 1; -} +GNUNET_SERVICE_MAIN +("core", + GNUNET_SERVICE_OPTION_NONE, + &run, + &client_connect_cb, + &client_disconnect_cb, + NULL, + GNUNET_MQ_hd_var_size (client_init, + GNUNET_MESSAGE_TYPE_CORE_INIT, + struct InitMessage, + NULL), + GNUNET_MQ_hd_fixed_size (client_monitor_peers, + GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS, + struct GNUNET_MessageHeader, + NULL), + GNUNET_MQ_hd_fixed_size (client_send_request, + GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST, + struct SendMessageRequest, + NULL), + GNUNET_MQ_hd_var_size (client_send, + GNUNET_MESSAGE_TYPE_CORE_SEND, + struct SendMessage, + NULL), + GNUNET_MQ_handler_end ()); + /* end of gnunet-service-core.c */ diff --git a/src/core/gnunet-service-core.h b/src/core/gnunet-service-core.h index 068a2f84f..86ac333b5 100644 --- a/src/core/gnunet-service-core.h +++ b/src/core/gnunet-service-core.h @@ -29,6 +29,8 @@ #include "gnunet_statistics_service.h" #include "gnunet_core_service.h" #include "core.h" +#include "gnunet-service-core_typemap.h" + /** * Opaque handle to a client. @@ -99,6 +101,84 @@ struct GSC_ClientActiveRequest }; +/** + * Tell a client that we are ready to receive the message. + * + * @param car request that is now ready; the responsibility + * for the handle remains shared between CLIENTS + * and SESSIONS after this call. + */ +void +GSC_CLIENTS_solicit_request (struct GSC_ClientActiveRequest *car); + + +/** + * We will never be ready to transmit the given message in (disconnect + * or invalid request). Frees resources associated with @a car. We + * don't explicitly tell the client, he'll learn with the disconnect + * (or violated the protocol). + * + * @param car request that now permanently failed; the + * responsibility for the handle is now returned + * to CLIENTS (SESSIONS is done with it). + * @param drop_client #GNUNET_YES if the client violated the protocol + * and we should thus drop the connection + */ +void +GSC_CLIENTS_reject_request (struct GSC_ClientActiveRequest *car, + int drop_client); + + +/** + * Notify a particular client about a change to existing connection to + * one of our neighbours (check if the client is interested). Called + * from #GSC_SESSIONS_notify_client_about_sessions(). + * + * @param client client to notify + * @param neighbour identity of the neighbour that changed status + * @param tmap_old previous type map for the neighbour, NULL for connect + * @param tmap_new updated type map for the neighbour, NULL for disconnect + */ +void +GSC_CLIENTS_notify_client_about_neighbour (struct GSC_Client *client, + const struct GNUNET_PeerIdentity *neighbour, + const struct GSC_TypeMap *tmap_old, + const struct GSC_TypeMap *tmap_new); + + +/** + * Deliver P2P message to interested clients. Caller must have checked + * that the sending peer actually lists the given message type as one + * of its types. + * + * @param sender peer who sent us the message + * @param msg the message + * @param msize number of bytes to transmit + * @param options options for checking which clients should + * receive the message + */ +void +GSC_CLIENTS_deliver_message (const struct GNUNET_PeerIdentity *sender, + const struct GNUNET_MessageHeader *msg, + uint16_t msize, + uint32_t options); + + +/** + * Notify all clients about a change to existing session. + * Called from SESSIONS whenever there is a change in sessions + * or types processed by the respective peer. + * + * @param neighbour identity of the neighbour that changed status + * @param tmap_old previous type map for the neighbour, NULL for connect + * @param tmap_new updated type map for the neighbour, NULL for disconnect + */ +void +GSC_CLIENTS_notify_clients_about_neighbour (const struct GNUNET_PeerIdentity *neighbour, + const struct GSC_TypeMap *tmap_old, + const struct GSC_TypeMap *tmap_new); + + /** * Our configuration. */ diff --git a/src/core/gnunet-service-core_clients.c b/src/core/gnunet-service-core_clients.c deleted file mode 100644 index 5db33f04b..000000000 --- a/src/core/gnunet-service-core_clients.c +++ /dev/null @@ -1,960 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2009, 2010, 2011 GNUnet e.V. - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -/** - * @file core/gnunet-service-core_clients.c - * @brief code for managing interactions with clients of core service - * @author Christian Grothoff - */ -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_statistics_service.h" -#include "gnunet_transport_service.h" -#include "gnunet-service-core.h" -#include "gnunet-service-core_clients.h" -#include "gnunet-service-core_sessions.h" -#include "gnunet-service-core_typemap.h" -#include "core.h" - - -/** - * How many messages do we queue up at most for optional - * notifications to a client? (this can cause notifications - * about outgoing messages to be dropped). - */ -#define MAX_NOTIFY_QUEUE 1024 - - -/** - * Data structure for each client connected to the CORE service. - */ -struct GSC_Client -{ - /** - * Clients are kept in a linked list. - */ - struct GSC_Client *next; - - /** - * Clients are kept in a linked list. - */ - struct GSC_Client *prev; - - /** - * Handle for the client with the server API. - */ - struct GNUNET_SERVER_Client *client_handle; - - /** - * Array of the types of messages this peer cares - * about (with @e tcnt entries). Allocated as part - * of this client struct, do not free! - */ - const uint16_t *types; - - /** - * Map of peer identities to active transmission requests of this - * client to the peer (of type `struct GSC_ClientActiveRequest`). - */ - struct GNUNET_CONTAINER_MultiPeerMap *requests; - - /** - * Map containing all peers that this client knows we're connected to. - */ - struct GNUNET_CONTAINER_MultiPeerMap *connectmap; - - /** - * Options for messages this client cares about, - * see GNUNET_CORE_OPTION_ values. - */ - uint32_t options; - - /** - * Number of types of incoming messages this client - * specifically cares about. Size of the @e types array. - */ - unsigned int tcnt; - -}; - - -/** - * Big "or" of all client options. - */ -static uint32_t all_client_options; - -/** - * Head of linked list of our clients. - */ -static struct GSC_Client *client_head; - -/** - * Tail of linked list of our clients. - */ -static struct GSC_Client *client_tail; - -/** - * Context for notifications we need to send to our clients. - */ -static struct GNUNET_SERVER_NotificationContext *notifier; - -/** - * Tokenizer for messages received from clients. - */ -static struct GNUNET_SERVER_MessageStreamTokenizer *client_mst; - - -/** - * Lookup our client struct given the server's client handle. - * - * @param client server client handle to look up - * @return our client handle for the client - */ -static struct GSC_Client * -find_client (struct GNUNET_SERVER_Client *client) -{ - struct GSC_Client *c; - - c = client_head; - while ((c != NULL) && (c->client_handle != client)) - c = c->next; - return c; -} - - -/** - * Send a message to one of our clients. - * - * @param client target for the message - * @param msg message to transmit - * @param can_drop could this message be dropped if the - * client's queue is getting too large? - */ -static void -send_to_client (struct GSC_Client *client, - const struct GNUNET_MessageHeader *msg, - int can_drop) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Preparing to send %u bytes of message of type %u to client.\n", - (unsigned int) ntohs (msg->size), - (unsigned int) ntohs (msg->type)); - GNUNET_SERVER_notification_context_unicast (notifier, client->client_handle, - msg, can_drop); -} - - -/** - * Send a message to one of our clients. - * - * @param client target for the message - * @param msg message to transmit - * @param can_drop could this message be dropped if the - * client's queue is getting too large? - */ -void -GSC_CLIENTS_send_to_client (struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *msg, - int can_drop) -{ - struct GSC_Client *c; - - c = find_client (client); - if (NULL == c) - { - GNUNET_break (0); - return; - } - send_to_client (c, msg, can_drop); -} - - -/** - * Test if the client is interested in messages of the given type. - * - * @param type message type - * @param c client to test - * @return #GNUNET_YES if @a c is interested, #GNUNET_NO if not. - */ -static int -type_match (uint16_t type, struct GSC_Client *c) -{ - unsigned int i; - - if (c->tcnt == 0 && c->options != 0) - return GNUNET_YES; /* peer without handlers and inbound/outbond - callbacks matches ALL */ - for (i = 0; i < c->tcnt; i++) - if (type == c->types[i]) - return GNUNET_YES; - return GNUNET_NO; -} - - -/** - * Send a message to all of our current clients that have the right - * options set. - * - * @param partner origin (or destination) of the message (used to check that this peer is - * known to be connected to the respective client) - * @param msg message to multicast - * @param can_drop can this message be discarded if the queue is too long - * @param options mask to use - * @param type type of the embedded message, 0 for none - */ -static void -send_to_all_clients (const struct GNUNET_PeerIdentity *partner, - const struct GNUNET_MessageHeader *msg, - int can_drop, - uint32_t options, - uint16_t type) -{ - struct GSC_Client *c; - int tm; - - for (c = client_head; NULL != c; c = c->next) - { - tm = type_match (type, c); - if (! ( (0 != (c->options & options)) || - ( (0 != (options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) && - (GNUNET_YES == tm) ) ) ) - continue; /* neither options nor type match permit the message */ - if ( (0 != (options & GNUNET_CORE_OPTION_SEND_HDR_INBOUND)) && - ( (0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) || - (GNUNET_YES == tm) ) ) - continue; - if ( (0 != (options & GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND)) && - (0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND)) ) - continue; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Sending %u message with %u bytes to client interested in messages of type %u.\n", - options, - ntohs (msg->size), - (unsigned int) type); - GNUNET_assert ( (0 == (c->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) || - (GNUNET_YES != tm) || - (GNUNET_YES == - GNUNET_CONTAINER_multipeermap_contains (c->connectmap, - partner)) ); - send_to_client (c, msg, can_drop); - } -} - - -/** - * Handle #GNUNET_MESSAGE_TYPE_CORE_INIT request. - * - * @param cls unused - * @param client new client that sent #GNUNET_MESSAGE_TYPE_CORE_INIT - * @param message the `struct InitMessage` (presumably) - */ -static void -handle_client_init (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) -{ - const struct InitMessage *im; - struct InitReplyMessage irm; - struct GSC_Client *c; - uint16_t msize; - const uint16_t *types; - uint16_t *wtypes; - unsigned int i; - - /* check that we don't have an entry already */ - c = find_client (client); - if (NULL != c) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - msize = ntohs (message->size); - if (msize < sizeof (struct InitMessage)) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - GNUNET_SERVER_notification_context_add (notifier, client); - im = (const struct InitMessage *) message; - types = (const uint16_t *) &im[1]; - msize -= sizeof (struct InitMessage); - c = GNUNET_malloc (sizeof (struct GSC_Client) + msize); - c->client_handle = client; - c->tcnt = msize / sizeof (uint16_t); - c->options = ntohl (im->options); - all_client_options |= c->options; - c->types = (const uint16_t *) &c[1]; - c->connectmap = GNUNET_CONTAINER_multipeermap_create (16, GNUNET_NO); - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multipeermap_put (c->connectmap, - &GSC_my_identity, - NULL, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); - wtypes = (uint16_t *) & c[1]; - for (i = 0; i < c->tcnt; i++) - wtypes[i] = ntohs (types[i]); - GSC_TYPEMAP_add (wtypes, c->tcnt); - GNUNET_CONTAINER_DLL_insert (client_head, client_tail, c); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Client connecting to core service is interested in %u message types\n", - (unsigned int) c->tcnt); - /* send init reply message */ - irm.header.size = htons (sizeof (struct InitReplyMessage)); - irm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY); - irm.reserved = htonl (0); - irm.my_identity = GSC_my_identity; - send_to_client (c, &irm.header, GNUNET_NO); - GSC_SESSIONS_notify_client_about_sessions (c); - GNUNET_SERVER_receive_done (client, GNUNET_OK); -} - - -/** - * Handle #GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST message. - * - * @param cls unused - * @param client new client that sent a #GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST - * @param message the `struct SendMessageRequest` (presumably) - */ -static void -handle_client_send_request (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) -{ - const struct SendMessageRequest *req; - struct GSC_Client *c; - struct GSC_ClientActiveRequest *car; - int is_loopback; - - req = (const struct SendMessageRequest *) message; - c = find_client (client); - if (NULL == c) - { - /* client did not send INIT first! */ - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, - GNUNET_SYSERR); - return; - } - if (NULL == c->requests) - c->requests = GNUNET_CONTAINER_multipeermap_create (16, - GNUNET_NO); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Client asked for transmission to `%s'\n", - GNUNET_i2s (&req->peer)); - is_loopback = - (0 == - memcmp (&req->peer, - &GSC_my_identity, - sizeof (struct GNUNET_PeerIdentity))); - if ((! is_loopback) && - (GNUNET_YES != - GNUNET_CONTAINER_multipeermap_contains (c->connectmap, - &req->peer))) - { - /* neighbour must have disconnected since request was issued, - * ignore (client will realize it once it processes the - * disconnect notification) */ - GNUNET_STATISTICS_update (GSC_stats, - gettext_noop - ("# send requests dropped (disconnected)"), 1, - GNUNET_NO); - GNUNET_SERVER_receive_done (client, - GNUNET_OK); - return; - } - - car = GNUNET_CONTAINER_multipeermap_get (c->requests, - &req->peer); - if (NULL == car) - { - /* create new entry */ - car = GNUNET_new (struct GSC_ClientActiveRequest); - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multipeermap_put (c->requests, - &req->peer, - car, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); - car->client_handle = c; - } - else - { - /* dequeue and recycle memory from pending request, there can only - be at most one per client and peer */ - GNUNET_STATISTICS_update (GSC_stats, - gettext_noop ("# dequeuing CAR (duplicate request)"), - 1, - GNUNET_NO); - GSC_SESSIONS_dequeue_request (car); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Transmission request to `%s' was a duplicate!\n", - GNUNET_i2s (&req->peer)); - } - car->target = req->peer; - car->received_time = GNUNET_TIME_absolute_get (); - car->deadline = GNUNET_TIME_absolute_ntoh (req->deadline); - car->priority = (enum GNUNET_CORE_Priority) ntohl (req->priority); - car->msize = ntohs (req->size); - car->smr_id = req->smr_id; - car->was_solicited = GNUNET_NO; - if (is_loopback) - { - /* loopback, satisfy immediately */ - GSC_CLIENTS_solicit_request (car); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } - GSC_SESSIONS_queue_request (car); - GNUNET_SERVER_receive_done (client, GNUNET_OK); -} - - -/** - * Closure for the #client_tokenizer_callback(). - */ -struct TokenizerContext -{ - - /** - * Active request handle for the message. - */ - struct GSC_ClientActiveRequest *car; - - /** - * How important is this message. - */ - enum GNUNET_CORE_Priority priority; - - /** - * Is corking allowed (set only once we have the real message). - */ - int cork; - -}; - - -/** - * Handle #GNUNET_MESSAGE_TYPE_CORE_SEND request. - * - * @param cls unused - * @param client the client issuing the request - * @param message the `struct SendMessage` - */ -static void -handle_client_send (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) -{ - const struct SendMessage *sm; - struct GSC_Client *c; - struct TokenizerContext tc; - uint16_t msize; - struct GNUNET_TIME_Relative delay; - - msize = ntohs (message->size); - if (msize < sizeof (struct SendMessage)) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, - GNUNET_SYSERR); - return; - } - sm = (const struct SendMessage *) message; - msize -= sizeof (struct SendMessage); - GNUNET_break (0 == ntohl (sm->reserved)); - c = find_client (client); - if (NULL == c) - { - /* client did not send INIT first! */ - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, - GNUNET_SYSERR); - return; - } - tc.car = GNUNET_CONTAINER_multipeermap_get (c->requests, - &sm->peer); - if (NULL == tc.car) - { - /* Must have been that we first approved the request, then got disconnected - * (which triggered removal of the 'car') and now the client gives us a message - * just *before* the client learns about the disconnect. Theoretically, we - * might also now be *again* connected. So this can happen (but should be - * rare). If it does happen, the message is discarded. */ - GNUNET_STATISTICS_update (GSC_stats, - gettext_noop ("# messages discarded (session disconnected)"), - 1, - GNUNET_NO); - GNUNET_SERVER_receive_done (client, - GNUNET_OK); - return; - } - delay = GNUNET_TIME_absolute_get_duration (tc.car->received_time); - tc.cork = ntohl (sm->cork); - tc.priority = (enum GNUNET_CORE_Priority) ntohl (sm->priority); - if (delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us) - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Client waited %s for transmission of %u bytes to `%s'%s\n", - GNUNET_STRINGS_relative_time_to_string (delay, - GNUNET_YES), - msize, - GNUNET_i2s (&sm->peer), - tc.cork ? " (cork)" : " (uncorked)"); - else - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Client waited %s for transmission of %u bytes to `%s'%s\n", - GNUNET_STRINGS_relative_time_to_string (delay, - GNUNET_YES), - msize, - GNUNET_i2s (&sm->peer), - tc.cork ? " (cork)" : " (uncorked)"); - - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multipeermap_remove (c->requests, - &sm->peer, - tc.car)); - GNUNET_SERVER_mst_receive (client_mst, &tc, - (const char *) &sm[1], - msize, - GNUNET_YES, - GNUNET_NO); - GSC_SESSIONS_dequeue_request (tc.car); - GNUNET_free (tc.car); - GNUNET_SERVER_receive_done (client, - GNUNET_OK); -} - - -/** - * Functions with this signature are called whenever a complete - * message is received by the tokenizer. Used by the 'client_mst' for - * dispatching messages from clients to either the SESSION subsystem - * or other CLIENT (for loopback). - * - * @param cls closure - * @param client reservation request (`struct GSC_ClientActiveRequest`) - * @param message the actual message - */ -static int -client_tokenizer_callback (void *cls, - void *client, - const struct GNUNET_MessageHeader *message) -{ - struct TokenizerContext *tc = client; - struct GSC_ClientActiveRequest *car = tc->car; - char buf[92]; - - GNUNET_snprintf (buf, sizeof (buf), - gettext_noop ("# bytes of messages of type %u received"), - (unsigned int) ntohs (message->type)); - GNUNET_STATISTICS_update (GSC_stats, - buf, - ntohs (message->size), - GNUNET_NO); - if (0 == - memcmp (&car->target, - &GSC_my_identity, - sizeof (struct GNUNET_PeerIdentity))) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Delivering message of type %u to myself\n", - ntohs (message->type)); - GSC_CLIENTS_deliver_message (&GSC_my_identity, message, - ntohs (message->size), - GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND); - GSC_CLIENTS_deliver_message (&GSC_my_identity, message, - sizeof (struct GNUNET_MessageHeader), - GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND); - GSC_CLIENTS_deliver_message (&GSC_my_identity, message, - ntohs (message->size), - GNUNET_CORE_OPTION_SEND_FULL_INBOUND); - GSC_CLIENTS_deliver_message (&GSC_my_identity, message, - sizeof (struct GNUNET_MessageHeader), - GNUNET_CORE_OPTION_SEND_HDR_INBOUND); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Delivering message of type %u and size %u to %s\n", - ntohs (message->type), ntohs (message->size), - GNUNET_i2s (&car->target)); - GSC_CLIENTS_deliver_message (&car->target, message, - ntohs (message->size), - GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND); - GSC_CLIENTS_deliver_message (&car->target, message, - sizeof (struct GNUNET_MessageHeader), - GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND); - GSC_SESSIONS_transmit (car, - message, - tc->cork, - tc->priority); - } - return GNUNET_OK; -} - - -/** - * Free client request records. - * - * @param cls NULL - * @param key identity of peer for which this is an active request - * @param value the `struct GSC_ClientActiveRequest` to free - * @return #GNUNET_YES (continue iteration) - */ -static int -destroy_active_client_request (void *cls, - const struct GNUNET_PeerIdentity *key, - void *value) -{ - struct GSC_ClientActiveRequest *car = value; - - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multipeermap_remove (car-> - client_handle->requests, - &car->target, - car)); - GSC_SESSIONS_dequeue_request (car); - GNUNET_free (car); - return GNUNET_YES; -} - - -/** - * A client disconnected, clean up. - * - * @param cls closure - * @param client identification of the client - */ -static void -handle_client_disconnect (void *cls, - struct GNUNET_SERVER_Client *client) -{ - struct GSC_Client *c; - - if (NULL == client) - return; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Client %p has disconnected from core service.\n", - client); - c = find_client (client); - if (c == NULL) - return; /* client never sent INIT */ - GNUNET_CONTAINER_DLL_remove (client_head, client_tail, c); - if (c->requests != NULL) - { - GNUNET_CONTAINER_multipeermap_iterate (c->requests, - &destroy_active_client_request, - NULL); - GNUNET_CONTAINER_multipeermap_destroy (c->requests); - } - GNUNET_CONTAINER_multipeermap_destroy (c->connectmap); - c->connectmap = NULL; - GSC_TYPEMAP_remove (c->types, c->tcnt); - GNUNET_free (c); - - /* recalculate 'all_client_options' */ - all_client_options = 0; - for (c = client_head; NULL != c ; c = c->next) - all_client_options |= c->options; -} - - -/** - * Tell a client that we are ready to receive the message. - * - * @param car request that is now ready; the responsibility - * for the handle remains shared between CLIENTS - * and SESSIONS after this call. - */ -void -GSC_CLIENTS_solicit_request (struct GSC_ClientActiveRequest *car) -{ - struct GSC_Client *c; - struct SendMessageReady smr; - struct GNUNET_TIME_Relative delay; - struct GNUNET_TIME_Relative left; - - c = car->client_handle; - if (GNUNET_YES != - GNUNET_CONTAINER_multipeermap_contains (c->connectmap, - &car->target)) - { - /* connection has gone down since, drop request */ - GNUNET_assert (0 != - memcmp (&car->target, - &GSC_my_identity, - sizeof (struct GNUNET_PeerIdentity))); - GSC_SESSIONS_dequeue_request (car); - GSC_CLIENTS_reject_request (car, - GNUNET_NO); - return; - } - delay = GNUNET_TIME_absolute_get_duration (car->received_time); - left = GNUNET_TIME_absolute_get_duration (car->deadline); - if (delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us) - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Client waited %s for permission to transmit to `%s'%s (priority %u)\n", - GNUNET_STRINGS_relative_time_to_string (delay, - GNUNET_YES), - GNUNET_i2s (&car->target), - (0 == left.rel_value_us) - ? " (past deadline)" - : "", - car->priority); - smr.header.size = htons (sizeof (struct SendMessageReady)); - smr.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SEND_READY); - smr.size = htons (car->msize); - smr.smr_id = car->smr_id; - smr.peer = car->target; - send_to_client (c, &smr.header, GNUNET_NO); -} - - -/** - * We will never be ready to transmit the given message in (disconnect - * or invalid request). Frees resources associated with @a car. We - * don't explicitly tell the client, he'll learn with the disconnect - * (or violated the protocol). - * - * @param car request that now permanently failed; the - * responsibility for the handle is now returned - * to CLIENTS (SESSIONS is done with it). - * @param drop_client #GNUNET_YES if the client violated the protocol - * and we should thus drop the connection - */ -void -GSC_CLIENTS_reject_request (struct GSC_ClientActiveRequest *car, - int drop_client) -{ - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multipeermap_remove (car-> - client_handle->requests, - &car->target, - car)); - if (GNUNET_YES == drop_client) - GNUNET_SERVER_client_disconnect (car->client_handle->client_handle); - GNUNET_free (car); -} - - -/** - * Notify a particular client about a change to existing connection to - * one of our neighbours (check if the client is interested). Called - * from 'GSC_SESSIONS_notify_client_about_sessions'. - * - * @param client client to notify - * @param neighbour identity of the neighbour that changed status - * @param tmap_old previous type map for the neighbour, NULL for connect - * @param tmap_new updated type map for the neighbour, NULL for disconnect - */ -void -GSC_CLIENTS_notify_client_about_neighbour (struct GSC_Client *client, - const struct GNUNET_PeerIdentity *neighbour, - const struct GSC_TypeMap *tmap_old, - const struct GSC_TypeMap *tmap_new) -{ - struct ConnectNotifyMessage *cnm; - size_t size; - char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1] GNUNET_ALIGN; - struct DisconnectNotifyMessage dcm; - int old_match; - int new_match; - - old_match = GSC_TYPEMAP_test_match (tmap_old, client->types, client->tcnt); - new_match = GSC_TYPEMAP_test_match (tmap_new, client->types, client->tcnt); - if (old_match == new_match) - { - GNUNET_assert (old_match == - GNUNET_CONTAINER_multipeermap_contains (client->connectmap, - neighbour)); - return; /* no change */ - } - if (old_match == GNUNET_NO) - { - /* send connect */ - GNUNET_assert (GNUNET_NO == - GNUNET_CONTAINER_multipeermap_contains (client->connectmap, - neighbour)); - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multipeermap_put (client->connectmap, - neighbour, - NULL, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); - size = sizeof (struct ConnectNotifyMessage); - cnm = (struct ConnectNotifyMessage *) buf; - cnm->header.size = htons (size); - cnm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT); - cnm->reserved = htonl (0); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Sending `%s' message to client.\n", - "NOTIFY_CONNECT"); - cnm->peer = *neighbour; - send_to_client (client, &cnm->header, GNUNET_NO); - } - else - { - /* send disconnect */ - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multipeermap_contains (client->connectmap, - neighbour)); - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multipeermap_remove (client->connectmap, - neighbour, - NULL)); - dcm.header.size = htons (sizeof (struct DisconnectNotifyMessage)); - dcm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT); - dcm.reserved = htonl (0); - dcm.peer = *neighbour; - send_to_client (client, &dcm.header, GNUNET_NO); - } -} - - -/** - * Notify all clients about a change to existing session. - * Called from SESSIONS whenever there is a change in sessions - * or types processed by the respective peer. - * - * @param neighbour identity of the neighbour that changed status - * @param tmap_old previous type map for the neighbour, NULL for connect - * @param tmap_new updated type map for the neighbour, NULL for disconnect - */ -void -GSC_CLIENTS_notify_clients_about_neighbour (const struct GNUNET_PeerIdentity *neighbour, - const struct GSC_TypeMap *tmap_old, - const struct GSC_TypeMap *tmap_new) -{ - struct GSC_Client *c; - - for (c = client_head; NULL != c; c = c->next) - GSC_CLIENTS_notify_client_about_neighbour (c, neighbour, - tmap_old, tmap_new); -} - - -/** - * Deliver P2P message to interested clients. Caller must have checked - * that the sending peer actually lists the given message type as one - * of its types. - * - * @param sender peer who sent us the message - * @param msg the message - * @param msize number of bytes to transmit - * @param options options for checking which clients should - * receive the message - */ -void -GSC_CLIENTS_deliver_message (const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *msg, - uint16_t msize, - uint32_t options) -{ - size_t size = msize + sizeof (struct NotifyTrafficMessage); - char buf[size] GNUNET_ALIGN; - struct NotifyTrafficMessage *ntm; - - if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE) - { - GNUNET_break (0); - /* recovery strategy: throw performance data away... */ - size = msize + sizeof (struct NotifyTrafficMessage); - } - if (! ( (0 != (all_client_options & options)) || - (0 != (options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) )) - return; /* no client cares about this message notification */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Core service passes message from `%s' of type %u to client.\n", - GNUNET_i2s (sender), - (unsigned int) ntohs (msg->type)); - GSC_SESSIONS_add_to_typemap (sender, ntohs (msg->type)); - ntm = (struct NotifyTrafficMessage *) buf; - ntm->header.size = htons (size); - if (0 != (options & (GNUNET_CORE_OPTION_SEND_FULL_INBOUND | GNUNET_CORE_OPTION_SEND_HDR_INBOUND))) - ntm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND); - else - ntm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND); - ntm->peer = *sender; - GNUNET_memcpy (&ntm[1], - msg, - msize); - send_to_all_clients (sender, - &ntm->header, - GNUNET_YES, - options, - ntohs (msg->type)); -} - - -/** - * Initialize clients subsystem. - * - * @param server handle to server clients connect to - */ -void -GSC_CLIENTS_init (struct GNUNET_SERVER_Handle *server) -{ - static const struct GNUNET_SERVER_MessageHandler handlers[] = { - {&handle_client_init, NULL, - GNUNET_MESSAGE_TYPE_CORE_INIT, 0}, - {&GSC_KX_handle_client_monitor_peers, NULL, - GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS, - sizeof (struct GNUNET_MessageHeader)}, - {&handle_client_send_request, NULL, - GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST, - sizeof (struct SendMessageRequest)}, - {&handle_client_send, NULL, - GNUNET_MESSAGE_TYPE_CORE_SEND, 0}, - {NULL, NULL, 0, 0} - }; - - /* setup notification */ - client_mst = GNUNET_SERVER_mst_create (&client_tokenizer_callback, NULL); - notifier = - GNUNET_SERVER_notification_context_create (server, MAX_NOTIFY_QUEUE); - GNUNET_SERVER_disconnect_notify (server, - &handle_client_disconnect, NULL); - GNUNET_SERVER_add_handlers (server, handlers); -} - - -/** - * Shutdown clients subsystem. - */ -void -GSC_CLIENTS_done () -{ - struct GSC_Client *c; - - while (NULL != (c = client_head)) - handle_client_disconnect (NULL, c->client_handle); - if (NULL != notifier) - { - GNUNET_SERVER_notification_context_destroy (notifier); - notifier = NULL; - } - if (NULL != client_mst) - { - GNUNET_SERVER_mst_destroy (client_mst); - client_mst = NULL; - } -} - -/* end of gnunet-service-core_clients.c */ diff --git a/src/core/gnunet-service-core_clients.h b/src/core/gnunet-service-core_clients.h deleted file mode 100644 index 4947f337c..000000000 --- a/src/core/gnunet-service-core_clients.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2009, 2010, 2011 GNUnet e.V. - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -/** - * @file core/gnunet-service-core_clients.h - * @brief code for managing interactions with clients of core service - * @author Christian Grothoff - */ -#ifndef GNUNET_SERVICE_CORE_CLIENTS_H -#define GNUNET_SERVICE_CORE_CLIENTS_H - -#include "gnunet_util_lib.h" -#include "gnunet-service-core.h" -#include "gnunet-service-core_typemap.h" - - -/** - * Send a message to one of our clients. - * - * @param client target for the message - * @param msg message to transmit - * @param can_drop could this message be dropped if the - * client's queue is getting too large? - */ -void -GSC_CLIENTS_send_to_client (struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *msg, - int can_drop); - - -/** - * Notify a particular client about a change to existing connection to - * one of our neighbours (check if the client is interested). Called - * from 'GSC_SESSIONS_notify_client_about_sessions'. - * - * @param client client to notify - * @param neighbour identity of the neighbour that changed status - * @param tmap_old previous type map for the neighbour, NULL for disconnect - * @param tmap_new updated type map for the neighbour, NULL for disconnect - */ -void -GSC_CLIENTS_notify_client_about_neighbour (struct GSC_Client *client, - const struct GNUNET_PeerIdentity *neighbour, - const struct GSC_TypeMap *tmap_old, - const struct GSC_TypeMap *tmap_new); - - -/** - * Notify all clients about a change to existing session. - * Called from SESSIONS whenever there is a change in sessions - * or types processed by the respective peer. - * - * @param neighbour identity of the neighbour that changed status - * @param tmap_old previous type map for the neighbour, NULL for disconnect - * @param tmap_new updated type map for the neighbour, NULL for disconnect - */ -void -GSC_CLIENTS_notify_clients_about_neighbour (const struct GNUNET_PeerIdentity *neighbour, - const struct GSC_TypeMap *tmap_old, - const struct GSC_TypeMap *tmap_new); - - -/** - * Deliver P2P message to interested clients. Caller must have checked - * that the sending peer actually lists the given message type as one - * of its types. - * - * @param sender peer who sent us the message - * @param msg the message - * @param msize number of bytes to transmit - * @param options options for checking which clients should - * receive the message - */ -void -GSC_CLIENTS_deliver_message (const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *msg, - uint16_t msize, - uint32_t options); - - -/** - * Tell a client that we are ready to receive the message. - * - * @param car request that is now ready; the responsibility - * for the handle remains shared between CLIENTS - * and SESSIONS after this call. - */ -void -GSC_CLIENTS_solicit_request (struct GSC_ClientActiveRequest *car); - - -/** - * We will never be ready to transmit the given message in (disconnect - * or invalid request). Frees resources associated with @a car. We - * don't explicitly tell the client, he'll learn with the disconnect - * (or violated the protocol). - * - * @param car request that now permanently failed; the - * responsibility for the handle is now returned - * to CLIENTS (SESSIONS is done with it). - * @param drop_client #GNUNET_YES if the client violated the protocol - * and we should thus drop the connection - */ -void -GSC_CLIENTS_reject_request (struct GSC_ClientActiveRequest *car, - int drop_client); - - -/** - * Initialize clients subsystem. - * - * @param server handle to server clients connect to - */ -void -GSC_CLIENTS_init (struct GNUNET_SERVER_Handle *server); - - -/** - * Shutdown clients subsystem. - */ -void -GSC_CLIENTS_done (void); - -#endif -/* end of gnunet-service-core_clients.h */ diff --git a/src/core/gnunet-service-core_kx.c b/src/core/gnunet-service-core_kx.c index 6f6786d89..6743ce215 100644 --- a/src/core/gnunet-service-core_kx.c +++ b/src/core/gnunet-service-core_kx.c @@ -26,7 +26,6 @@ #include "platform.h" #include "gnunet-service-core_kx.h" #include "gnunet-service-core.h" -#include "gnunet-service-core_clients.h" #include "gnunet-service-core_sessions.h" #include "gnunet_statistics_service.h" #include "gnunet_transport_core_service.h" @@ -392,34 +391,9 @@ static struct GSC_KeyExchangeInfo *kx_tail; static struct GNUNET_SCHEDULER_Task *rekey_task; /** - * Notification context for all monitors. + * Notification context for broadcasting to monitors. */ -static struct GNUNET_SERVER_NotificationContext *nc; - - -/** - * Inform the given monitor about the KX state of - * the given peer. - * - * @param client client to inform - * @param kx key exchange state to inform about - */ -static void -monitor_notify (struct GNUNET_SERVER_Client *client, - struct GSC_KeyExchangeInfo *kx) -{ - struct MonitorNotifyMessage msg; - - msg.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY); - msg.header.size = htons (sizeof (msg)); - msg.state = htonl ((uint32_t) kx->status); - msg.peer = *kx->peer; - msg.timeout = GNUNET_TIME_absolute_hton (kx->timeout); - GNUNET_SERVER_notification_context_unicast (nc, - client, - &msg.header, - GNUNET_NO); -} +static struct GNUNET_NotificationContext *nc; /** @@ -453,9 +427,9 @@ monitor_notify_all (struct GSC_KeyExchangeInfo *kx) msg.state = htonl ((uint32_t) kx->status); msg.peer = *kx->peer; msg.timeout = GNUNET_TIME_absolute_hton (kx->timeout); - GNUNET_SERVER_notification_context_broadcast (nc, - &msg.header, - GNUNET_NO); + GNUNET_notification_context_broadcast (nc, + &msg.header, + GNUNET_NO); kx->last_notify_timeout = kx->timeout; } @@ -1807,12 +1781,10 @@ do_rekey (void *cls) * Initialize KX subsystem. * * @param pk private key to use for the peer - * @param server the server of the CORE service * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ int -GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk, - struct GNUNET_SERVER_Handle *server) +GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk) { struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_fixed_size (ephemeral_key, @@ -1834,8 +1806,6 @@ GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk, GNUNET_MQ_handler_end() }; - nc = GNUNET_SERVER_notification_context_create (server, - 1); my_private_key = pk; GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, &GSC_my_identity.public_key); @@ -1848,10 +1818,12 @@ GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk, return GNUNET_SYSERR; } sign_ephemeral_key (); + nc = GNUNET_notification_context_create (1); rekey_task = GNUNET_SCHEDULER_add_delayed (REKEY_FREQUENCY, &do_rekey, NULL); - mst = GNUNET_SERVER_mst_create (&deliver_message, NULL); + mst = GNUNET_SERVER_mst_create (&deliver_message, + NULL); transport = GNUNET_TRANSPORT_core_connect (GSC_cfg, &GSC_my_identity, @@ -1902,7 +1874,7 @@ GSC_KX_done () } if (NULL != nc) { - GNUNET_SERVER_notification_context_destroy (nc); + GNUNET_notification_context_destroy (nc); nc = NULL; } } @@ -1940,34 +1912,36 @@ GSC_NEIGHBOURS_check_excess_bandwidth (const struct GSC_KeyExchangeInfo *kxinfo) * request. All current peers are returned, regardless of which * message types they accept. * - * @param cls unused - * @param client client sending the iteration request - * @param message iteration request message + * @param mq message queue to add for monitoring */ void -GSC_KX_handle_client_monitor_peers (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +GSC_KX_handle_client_monitor_peers (struct GNUNET_MQ_Handle *mq) { - struct MonitorNotifyMessage done_msg; + struct GNUNET_MQ_Envelope *env; + struct MonitorNotifyMessage *done_msg; struct GSC_KeyExchangeInfo *kx; - GNUNET_SERVER_receive_done (client, GNUNET_OK); - GNUNET_SERVER_notification_context_add (nc, - client); + GNUNET_notification_context_add (nc, + mq); for (kx = kx_head; NULL != kx; kx = kx->next) - monitor_notify (client, kx); - done_msg.header.size = htons (sizeof (struct MonitorNotifyMessage)); - done_msg.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY); - done_msg.state = htonl ((uint32_t) GNUNET_CORE_KX_ITERATION_FINISHED); - memset (&done_msg.peer, - 0, - sizeof (struct GNUNET_PeerIdentity)); - done_msg.timeout = GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_FOREVER_ABS); - GNUNET_SERVER_notification_context_unicast (nc, - client, - &done_msg.header, - GNUNET_NO); + { + struct GNUNET_MQ_Envelope *env; + struct MonitorNotifyMessage *msg; + + env = GNUNET_MQ_msg (msg, + GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY); + msg->state = htonl ((uint32_t) kx->status); + msg->peer = *kx->peer; + msg->timeout = GNUNET_TIME_absolute_hton (kx->timeout); + GNUNET_MQ_send (mq, + env); + } + env = GNUNET_MQ_msg (done_msg, + GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY); + done_msg->state = htonl ((uint32_t) GNUNET_CORE_KX_ITERATION_FINISHED); + done_msg->timeout = GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_FOREVER_ABS); + GNUNET_MQ_send (mq, + env); } diff --git a/src/core/gnunet-service-core_kx.h b/src/core/gnunet-service-core_kx.h index 8614f090f..28293e607 100644 --- a/src/core/gnunet-service-core_kx.h +++ b/src/core/gnunet-service-core_kx.h @@ -53,12 +53,10 @@ GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx, * Initialize KX subsystem. * * @param pk private key to use for the peer - * @param server the server of the CORE service * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ int -GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk, - struct GNUNET_SERVER_Handle *server); +GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk); /** @@ -94,14 +92,10 @@ GSC_NEIGHBOURS_get_queue_length (const struct GSC_KeyExchangeInfo *target); * request. All current peers are returned, regardless of which * message types they accept. * - * @param cls unused - * @param client client sending the iteration request - * @param message iteration request message + * @param mq message queue to add for monitoring */ void -GSC_KX_handle_client_monitor_peers (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message); +GSC_KX_handle_client_monitor_peers (struct GNUNET_MQ_Handle *mq); #endif diff --git a/src/core/gnunet-service-core_sessions.c b/src/core/gnunet-service-core_sessions.c index ef5285b45..036fd1425 100644 --- a/src/core/gnunet-service-core_sessions.c +++ b/src/core/gnunet-service-core_sessions.c @@ -28,7 +28,6 @@ #include "gnunet-service-core_kx.h" #include "gnunet-service-core_typemap.h" #include "gnunet-service-core_sessions.h" -#include "gnunet-service-core_clients.h" #include "gnunet_constants.h" #include "core.h"