#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
* Map of peer identities to active transmission requests of this
* client to the peer (of type 'struct GSC_ClientActiveRequest').
*/
- struct GNUNET_CONTAINER_MultiHashMap *requests;
+ 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,
};
+/**
+ * Big "or" of all client options.
+ */
+static uint32_t all_client_options;
+
/**
* Head of linked list of our clients.
*/
* client's queue is getting too large?
*/
static void
-send_to_client (struct GSC_Client *client,
- const struct GNUNET_MessageHeader *msg,
- int can_drop)
+send_to_client (struct GSC_Client *client,
+ const struct GNUNET_MessageHeader *msg, int can_drop)
{
-#if DEBUG_CORE_CLIENT
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));
-#endif
GNUNET_SERVER_notification_context_unicast (notifier, client->client_handle,
msg, can_drop);
}
*/
void
GSC_CLIENTS_send_to_client (struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *msg,
- int can_drop)
+ const struct GNUNET_MessageHeader *msg,
+ int can_drop)
{
struct GSC_Client *c;
* @return GNUNET_YES if 'c' is interested, GNUNET_NO if not.
*/
static int
-type_match (uint16_t type,
- struct GSC_Client *c)
+type_match (uint16_t type, struct GSC_Client *c)
{
unsigned int i;
- for (i=0;i<c->tcnt;i++)
+ if (c->tcnt == 0)
+ return GNUNET_YES; /* peer without handlers 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_MessageHeader *msg,
- int can_drop,
- int options,
- uint16_t type)
+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; c != NULL; c = c->next)
{
- if (! ( (0 != (c->options & options)) ||
- ( (0 != (options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) &&
- (GNUNET_YES == type_match (type, c)) ) ) )
- continue; /* skip */
-#if DEBUG_CORE_CLIENT > 1
+ 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 message of type %u to client.\n",
- (unsigned int) ntohs (msg->type));
-#endif
+ "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);
}
}
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);
-#if DEBUG_CORE_CLIENT
+ 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",
+ "Client connecting to core service is interested in %u message types\n",
(unsigned int) c->tcnt);
-#endif
/* 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);
- if (0 != (c->options & GNUNET_CORE_OPTION_SEND_CONNECT))
- GSC_SESSIONS_notify_client_about_sessions (c);
+ GSC_SESSIONS_notify_client_about_sessions (c);
GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
*
* @param cls unused
* @param client new client that sent CORE_SEND_REQUEST
- * @param message the 'struct InitMessage' (presumably)
+ * @param message the 'struct SendMessageRequest' (presumably)
*/
static void
handle_client_send_request (void *cls, struct GNUNET_SERVER_Client *client,
const struct SendMessageRequest *req;
struct GSC_Client *c;
struct GSC_ClientActiveRequest *car;
+ int is_loopback;
req = (const struct SendMessageRequest *) message;
c = find_client (client);
return;
}
if (c->requests == NULL)
- c->requests = GNUNET_CONTAINER_multihashmap_create (16);
- car = GNUNET_CONTAINER_multihashmap_get (c->requests, &req->peer.hashPubKey);
+ 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 (car == NULL)
{
/* create new entry */
car = GNUNET_malloc (sizeof (struct GSC_ClientActiveRequest));
GNUNET_assert (GNUNET_OK ==
- GNUNET_CONTAINER_multihashmap_put (c->requests,
- &req->peer.hashPubKey,
+ GNUNET_CONTAINER_multipeermap_put (c->requests,
+ &req->peer,
car,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
car->client_handle = c;
}
+ else
+ {
+ GSC_SESSIONS_dequeue_request (car);
+ }
car->target = req->peer;
car->deadline = GNUNET_TIME_absolute_ntoh (req->deadline);
car->priority = ntohl (req->priority);
car->msize = ntohs (req->size);
car->smr_id = req->smr_id;
car->was_solicited = GNUNET_NO;
- if (0 ==
- memcmp (&req->peer, &GSC_my_identity, sizeof (struct GNUNET_PeerIdentity)))
+ if (is_loopback)
+ {
+ /* loopback, satisfy immediately */
GSC_CLIENTS_solicit_request (car);
- else
- GSC_SESSIONS_queue_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;
+
+ /**
+ * Is corking allowed (set only once we have the real message).
+ */
+ int cork;
+
+};
+
+
/**
* Handle CORE_SEND request.
*
{
const struct SendMessage *sm;
struct GSC_Client *c;
- struct GSC_ClientActiveRequest *car;
+ struct TokenizerContext tc;
uint16_t msize;
msize = ntohs (message->size);
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return;
}
- car = GNUNET_CONTAINER_multihashmap_get (c->requests, &sm->peer.hashPubKey);
- if (NULL == car)
+ tc.car =
+ GNUNET_CONTAINER_multipeermap_get (c->requests, &sm->peer);
+ if (NULL == tc.car)
{
- /* client did not request transmission first! */
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ /* 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;
}
GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap_remove (c->requests,
- &sm->peer.hashPubKey,
- car));
- car->cork = ntohs (sm->cork);
- GNUNET_SERVER_mst_receive (client_mst,
- car,
- (const char*) &sm[1], msize,
- GNUNET_YES,
- GNUNET_NO);
+ GNUNET_CONTAINER_multipeermap_remove (c->requests,
+ &sm->peer,
+ tc.car));
+ tc.cork = ntohl (sm->cork);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Client asked for transmission of %u bytes to `%s' %s\n", msize,
+ GNUNET_i2s (&sm->peer), tc.cork ? "now" : "");
+ GNUNET_SERVER_mst_receive (client_mst, &tc, (const char *) &sm[1], msize,
+ GNUNET_YES, GNUNET_NO);
if (0 !=
- memcmp (&car->target, &GSC_my_identity, sizeof (struct GNUNET_PeerIdentity)))
- GSC_SESSIONS_dequeue_request (car);
- GNUNET_free (car);
+ memcmp (&tc.car->target, &GSC_my_identity,
+ sizeof (struct GNUNET_PeerIdentity)))
+ GSC_SESSIONS_dequeue_request (tc.car);
+ GNUNET_free (tc.car);
GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
* @param client reservation request ('struct GSC_ClientActiveRequest')
* @param message the actual message
*/
-static void
+static int
client_tokenizer_callback (void *cls, void *client,
- const struct GNUNET_MessageHeader *message)
+ const struct GNUNET_MessageHeader *message)
{
- struct GSC_ClientActiveRequest *car = client;
-
+ 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)))
+ memcmp (&car->target, &GSC_my_identity,
+ sizeof (struct GNUNET_PeerIdentity)))
{
- GSC_CLIENTS_deliver_message (&GSC_my_identity,
- NULL, 0,
- message,
+ 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 | GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND);
- GSC_CLIENTS_deliver_message (&GSC_my_identity,
- NULL, 0,
- message,
+ GNUNET_CORE_OPTION_SEND_FULL_INBOUND);
+ GSC_CLIENTS_deliver_message (&GSC_my_identity, message,
sizeof (struct GNUNET_MessageHeader),
- GNUNET_CORE_OPTION_SEND_HDR_INBOUND | GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND);
+ GNUNET_CORE_OPTION_SEND_HDR_INBOUND);
}
else
- GSC_SESSIONS_transmit (car, message, car->cork);
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Delivering message of type %u to %s\n", ntohs (message->type),
+ 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);
+ }
+ return GNUNET_OK;
}
* @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)
+ * @return #GNUNET_YES (continue iteration)
*/
static int
-destroy_active_client_request (void *cls, const GNUNET_HashCode * key,
+destroy_active_client_request (void *cls,
+ const struct GNUNET_PeerIdentity *key,
void *value)
{
struct GSC_ClientActiveRequest *car = value;
GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap_remove (car->client_handle->requests,
- &car->target.hashPubKey,
- car));
+ GNUNET_CONTAINER_multipeermap_remove (car->
+ client_handle->requests,
+ &car->target,
+ car));
GSC_SESSIONS_dequeue_request (car);
GNUNET_free (car);
return GNUNET_YES;
* @param client identification of the client
*/
static void
-handle_client_disconnect (void *cls,
- struct GNUNET_SERVER_Client *client)
+handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
{
struct GSC_Client *c;
if (client == NULL)
return;
-#if DEBUG_CORE_CLIENT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Client %p has disconnected from core service.\n", client);
-#endif
c = find_client (client);
if (c == NULL)
- return; /* client never sent INIT */
- GNUNET_CONTAINER_DLL_remove (client_head,
- client_tail,
- c);
+ return; /* client never sent INIT */
+ GNUNET_CONTAINER_DLL_remove (client_head, client_tail, c);
if (c->requests != NULL)
{
- GNUNET_CONTAINER_multihashmap_iterate (c->requests,
+ GNUNET_CONTAINER_multipeermap_iterate (c->requests,
&destroy_active_client_request,
NULL);
- GNUNET_CONTAINER_multihashmap_destroy (c->requests);
+ 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;
}
struct SendMessageReady smr;
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);
+ return;
+ }
smr.header.size = htons (sizeof (struct SendMessageReady));
smr.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SEND_READY);
smr.size = htons (car->msize);
GSC_CLIENTS_reject_request (struct GSC_ClientActiveRequest *car)
{
GNUNET_assert (GNUNET_YES ==
- destroy_active_client_request (NULL, &car->target.hashPubKey, car));
+ GNUNET_CONTAINER_multipeermap_remove (car->
+ client_handle->requests,
+ &car->target,
+ car));
+ GNUNET_free (car);
}
*
* @param client client to notify
* @param neighbour identity of the neighbour that changed status
- * @param atsi performance information about neighbour
- * @param atsi_count number of entries in 'ats' array
- * @param tmap_old previous type map for the neighbour, NULL for disconnect
+ * @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
-GDS_CLIENTS_notify_client_about_neighbour (struct GSC_Client *client,
- const struct GNUNET_PeerIdentity *neighbour,
- const struct GNUNET_TRANSPORT_ATS_Information *atsi,
- unsigned int atsi_count,
- const struct GSC_TypeMap *tmap_old,
- const struct GSC_TypeMap *tmap_new)
+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];
- struct GNUNET_TRANSPORT_ATS_Information *a;
+ 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)
- return; /* no change */
+ {
+ GNUNET_assert (old_match ==
+ GNUNET_CONTAINER_multipeermap_contains (client->connectmap,
+ neighbour));
+ return; /* no change */
+ }
if (old_match == GNUNET_NO)
{
- /* send connect */
- size =
- sizeof (struct ConnectNotifyMessage) +
- (atsi_count) * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
- if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
- {
- GNUNET_break (0);
- /* recovery strategy: throw away performance data */
- atsi_count = 0;
- size = sizeof (struct ConnectNotifyMessage);
- }
+ /* 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->ats_count = htonl (atsi_count);
- a = &cnm->ats;
- memcpy (a, atsi,
- sizeof (struct GNUNET_TRANSPORT_ATS_Information) * atsi_count);
- a[atsi_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
- a[atsi_count].value = htonl (0);
-#if DEBUG_CORE_CLIENT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Sending `%s' message to client.\n",
+ cnm->reserved = htonl (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message to client.\n",
"NOTIFY_CONNECT");
-#endif
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);
* or types processed by the respective peer.
*
* @param neighbour identity of the neighbour that changed status
- * @param atsi performance information about neighbour
- * @param atsi_count number of entries in 'ats' array
- * @param tmap_old previous type map for the neighbour, NULL for disconnect
+ * @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
-GDS_CLIENTS_notify_clients_about_neighbour (const struct GNUNET_PeerIdentity *neighbour,
- const struct GNUNET_TRANSPORT_ATS_Information *atsi,
- unsigned int atsi_count,
- const struct GSC_TypeMap *tmap_old,
- const struct GSC_TypeMap *tmap_new)
+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; c != NULL; c = c->next)
- GDS_CLIENTS_notify_client_about_neighbour (c, neighbour, atsi,
- atsi_count,
- tmap_old, tmap_new);
+ 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
+ * that the sending peer actually lists the given message type as one
* of its types.
*
- * @param sender peer who sent us the message
- * @param atsi performance information about neighbour
- * @param atsi_count number of entries in 'ats' array
+ * @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
*/
void
GSC_CLIENTS_deliver_message (const struct GNUNET_PeerIdentity *sender,
- const struct GNUNET_TRANSPORT_ATS_Information *atsi,
- unsigned int atsi_count,
- const struct GNUNET_MessageHeader *msg,
- uint16_t msize,
- int options)
+ const struct GNUNET_MessageHeader *msg,
+ uint16_t msize,
+ uint32_t options)
{
- size_t size = msize + sizeof (struct NotifyTrafficMessage) +
- atsi_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
- char buf[size];
+ size_t size = msize + sizeof (struct NotifyTrafficMessage);
+ char buf[size] GNUNET_ALIGN;
struct NotifyTrafficMessage *ntm;
- struct GNUNET_TRANSPORT_ATS_Information *a;
- if (0 == options)
- {
- GNUNET_snprintf (buf, sizeof (buf),
- gettext_noop ("# bytes of messages of type %u received"),
- (unsigned int) ntohs (msg->type));
- GNUNET_STATISTICS_update (GSC_stats, buf, msize, GNUNET_NO);
- }
if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
{
GNUNET_break (0);
/* recovery strategy: throw performance data away... */
- atsi_count = 0;
size = msize + sizeof (struct NotifyTrafficMessage);
}
-#if DEBUG_CORE
+ 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 `%4s' of type %u to client.\n",
- GNUNET_i2s (sender),
- (unsigned int) ntohs (msg->type));
-#endif
+ 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);
- ntm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND);
- ntm->ats_count = htonl (atsi_count);
+ 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;
- a = &ntm->ats;
- memcpy (a, atsi,
- sizeof (struct GNUNET_TRANSPORT_ATS_Information) * atsi_count);
- a[atsi_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
- a[atsi_count].value = htonl (0);
- memcpy (&a[atsi_count + 1], msg, msize);
- send_to_all_clients (&ntm->header, GNUNET_YES,
- options, ntohs (msg->type));
+ memcpy (&ntm[1], msg, msize);
+ send_to_all_clients (sender, &ntm->header, GNUNET_YES, options,
+ ntohs (msg->type));
}
{&GSC_SESSIONS_handle_client_iterate_peers, NULL,
GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS,
sizeof (struct GNUNET_MessageHeader)},
- {&GSC_SESSIONS_handle_client_have_peer, NULL,
- GNUNET_MESSAGE_TYPE_CORE_PEER_CONNECTED,
- sizeof (struct GNUNET_MessageHeader) +
- sizeof (struct GNUNET_PeerIdentity)},
{&handle_client_send_request, NULL,
GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST,
sizeof (struct SendMessageRequest)},
{
struct GSC_Client *c;
- while (NULL != (c = client_head))
+ while (NULL != (c = client_head))
handle_client_disconnect (NULL, c->client_handle);
- GNUNET_SERVER_notification_context_destroy (notifier);
- notifier = NULL;
- GNUNET_SERVER_mst_destroy (client_mst);
- client_mst = NULL;
+ 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 */