static GNUNET_SCHEDULER_TaskIdentifier retry_task;
+/**
+ * Task run to check for messages that need to be sent to a client.
+ *
+ * @param client a ClientList, containing the client and any messages to be sent to it
+ */
+static void
+process_pending_messages (struct ClientList *client);
+
+
+/**
+ * Add a PendingMessage to the clients list of messages to be sent
+ *
+ * @param client the active client to send the message to
+ * @param pending_message the actual message to send
+ */
+static void
+add_pending_message (struct ClientList *client,
+ struct PendingMessage *pending_message)
+{
+ GNUNET_CONTAINER_DLL_insert_tail (client->pending_head, client->pending_tail,
+ pending_message);
+ process_pending_messages (client);
+}
+
+
/**
* Find a client if it exists, add it otherwise.
*
if (record->client != client)
return GNUNET_YES;
-#if DEBUG_DHT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Removing client %p's record for key %s\n", client,
GNUNET_h2s (key));
-#endif
GNUNET_assert (GNUNET_YES ==
GNUNET_CONTAINER_multihashmap_remove (forward_map, key,
record));
struct PendingMessage *reply;
struct ClientMonitorRecord *monitor;
-#if DEBUG_DHT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Local client %p disconnects\n", client);
-#endif
pos = find_active_client (client);
GNUNET_CONTAINER_DLL_remove (client_head, client_tail, pos);
if (pos->transmit_handle != NULL)
const struct GNUNET_DHT_ClientPutMessage *dht_msg;
struct GNUNET_CONTAINER_BloomFilter *peer_bf;
uint16_t size;
+ struct PendingMessage *pm;
+ struct GNUNET_DHT_ClientPutConfirmationMessage *conf;
size = ntohs (message->size);
if (size < sizeof (struct GNUNET_DHT_ClientPutMessage))
GNUNET_NO);
dht_msg = (const struct GNUNET_DHT_ClientPutMessage *) message;
/* give to local clients */
-#if DEBUG_DHT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Handling local PUT of %u-bytes for query %s\n",
size - sizeof (struct GNUNET_DHT_ClientPutMessage),
GNUNET_h2s (&dht_msg->key));
-#endif
GDS_CLIENTS_handle_reply (GNUNET_TIME_absolute_ntoh (dht_msg->expiration),
&dht_msg->key, 0, NULL, 0, NULL,
ntohl (dht_msg->type),
&dht_msg[1],
size - sizeof (struct GNUNET_DHT_ClientPutMessage));
GNUNET_CONTAINER_bloomfilter_free (peer_bf);
+ pm = GNUNET_malloc (sizeof (struct PendingMessage) +
+ sizeof (struct GNUNET_DHT_ClientPutConfirmationMessage));
+ conf = (struct GNUNET_DHT_ClientPutConfirmationMessage *) &pm[1];
+ conf->header.size = htons (sizeof (struct GNUNET_DHT_ClientPutConfirmationMessage));
+ conf->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_CLIENT_PUT_OK);
+ conf->reserved = htonl (0);
+ conf->unique_id = dht_msg->unique_id;
+ pm->msg = &conf->header;
+ add_pending_message (find_active_client (client), pm);
GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
gettext_noop
("# GET requests received from clients"), 1,
GNUNET_NO);
-#if DEBUG_DHT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Received request for %s from local client %p\n",
GNUNET_h2s (&get->key), client);
-#endif
cqr = GNUNET_malloc (sizeof (struct ClientQueryRecord) + xquery_size);
cqr->key = get->key;
cqr->client = find_active_client (client);
if (record->unique_id != ctx->unique_id)
return GNUNET_YES;
-#if DEBUG_DHT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Removing client %p's record for key %s (by unique id)\n",
ctx->client->client_handle, GNUNET_h2s (key));
-#endif
return remove_client_records (ctx->client, key, record);
}
gettext_noop
("# GET STOP requests received from clients"), 1,
GNUNET_NO);
-#if DEBUG_DHT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p stopped request for key %s\n",
client, GNUNET_h2s (&dht_stop_msg->key));
-#endif
ctx.client = find_active_client (client);
ctx.unique_id = dht_stop_msg->unique_id;
GNUNET_CONTAINER_multihashmap_get_multiple (forward_map, &dht_stop_msg->key,
/**
- * Handler for monitor messages
+ * Handler for monitor start messages
*
* @param cls closure for the service
* @param client the client we received this message from
const struct GNUNET_MessageHeader *message)
{
struct ClientMonitorRecord *r;
- const struct GNUNET_DHT_MonitorStartMessage *msg;
- unsigned int i;
- char *c;
+ const struct GNUNET_DHT_MonitorStartStopMessage *msg;
- msg = (struct GNUNET_DHT_MonitorStartMessage *) message;
+ msg = (struct GNUNET_DHT_MonitorStartStopMessage *) message;
r = GNUNET_malloc (sizeof(struct ClientMonitorRecord));
r->client = find_active_client(client);
r->type = ntohl(msg->type);
- r->get = msg->get;
- r->get_resp = msg->get_resp;
- r->put = msg->put;
- c = (char *) &msg->key;
- for (i = 0; i < sizeof (GNUNET_HashCode) && c[i] == 0; i++);
- if (sizeof (GNUNET_HashCode) == i)
- r->key = NULL;
+ r->get = ntohs(msg->get);
+ r->get_resp = ntohs(msg->get_resp);
+ r->put = ntohs(msg->put);
+ if (0 == ntohs(msg->filter_key))
+ r->key = NULL;
else
{
r->key = GNUNET_malloc (sizeof (GNUNET_HashCode));
memcpy (r->key, &msg->key, sizeof (GNUNET_HashCode));
}
GNUNET_CONTAINER_DLL_insert (monitor_head, monitor_tail, r);
- // FIXME add remove somewhere
GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
-
/**
- * Task run to check for messages that need to be sent to a client.
+ * Handler for monitor stop messages
+ *
+ * @param cls closure for the service
+ * @param client the client we received this message from
+ * @param message the actual message received
*
- * @param client a ClientList, containing the client and any messages to be sent to it
*/
static void
-process_pending_messages (struct ClientList *client);
+handle_dht_local_monitor_stop (void *cls, struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *message)
+{
+ struct ClientMonitorRecord *r;
+ const struct GNUNET_DHT_MonitorStartStopMessage *msg;
+ int keys_match;
+
+ msg = (struct GNUNET_DHT_MonitorStartStopMessage *) message;
+ r = monitor_head;
+
+ while (NULL != r)
+ {
+ if (NULL == r->key)
+ keys_match = (0 == ntohs(msg->filter_key));
+ else
+ {
+ keys_match = (0 != ntohs(msg->filter_key)
+ && !memcmp(r->key, &msg->key, sizeof(GNUNET_HashCode)));
+ }
+ if (find_active_client(client) == r->client
+ && ntohl(msg->type) == r->type
+ && r->get == msg->get
+ && r->get_resp == msg->get_resp
+ && r->put == msg->put
+ && keys_match
+ )
+ {
+ GNUNET_CONTAINER_DLL_remove (monitor_head, monitor_tail, r);
+ GNUNET_free_non_null (r->key);
+ GNUNET_free (r);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+ return; /* Delete only ONE entry */
+ }
+ r = r->next;
+ }
+
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
/**
if (buf == NULL)
{
/* client disconnected */
-#if DEBUG_DHT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Client %p disconnected, pending messages will be discarded\n",
client->client_handle);
-#endif
return 0;
}
off = 0;
reply);
memcpy (&cbuf[off], reply->msg, msize);
GNUNET_free (reply);
-#if DEBUG_DHT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting %u bytes to client %p\n",
msize, client->client_handle);
-#endif
off += msize;
}
process_pending_messages (client);
-#if DEBUG_DHT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitted %u/%u bytes to client %p\n",
(unsigned int) off, (unsigned int) size, client->client_handle);
-#endif
return off;
}
{
if ((client->pending_head == NULL) || (client->transmit_handle != NULL))
{
-#if DEBUG_DHT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Not asking for transmission to %p now: %s\n",
client->client_handle,
client->pending_head ==
NULL ? "no more messages" : "request already pending");
-#endif
return;
}
-#if DEBUG_DHT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Asking for transmission of %u bytes to client %p\n",
ntohs (client->pending_head->msg->size), client->client_handle);
-#endif
client->transmit_handle =
GNUNET_SERVER_notify_transmit_ready (client->client_handle,
ntohs (client->pending_head->
}
-/**
- * Add a PendingMessage to the clients list of messages to be sent
- *
- * @param client the active client to send the message to
- * @param pending_message the actual message to send
- */
-static void
-add_pending_message (struct ClientList *client,
- struct PendingMessage *pending_message)
-{
- GNUNET_CONTAINER_DLL_insert_tail (client->pending_head, client->pending_tail,
- pending_message);
- process_pending_messages (client);
-}
-
-
/**
* Closure for 'forward_reply'
*/
if ((record->type != GNUNET_BLOCK_TYPE_ANY) && (record->type != frc->type))
{
-#if DEBUG_DHT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Record type missmatch, not passing request for key %s to local client\n",
GNUNET_h2s (key));
-#endif
GNUNET_STATISTICS_update (GDS_stats,
gettext_noop
("# Key match, type mismatches in REPLY to CLIENT"),
for (i = 0; i < record->seen_replies_count; i++)
if (0 == memcmp (&record->seen_replies[i], &ch, sizeof (GNUNET_HashCode)))
{
-#if DEBUG_DHT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Duplicate reply, not passing request for key %s to local client\n",
GNUNET_h2s (key));
-#endif
GNUNET_STATISTICS_update (GDS_stats,
gettext_noop
("# Duplicate REPLIES to CLIENT request dropped"),
GNUNET_BLOCK_evaluate (GDS_block_context, record->type, key, NULL, 0,
record->xquery, record->xquery_size, frc->data,
frc->data_size);
-#if DEBUG_DHT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Evaluation result is %d for key %s for local client's query\n",
(int) eval, GNUNET_h2s (key));
-#endif
switch (eval)
{
case GNUNET_BLOCK_EVALUATION_OK_LAST:
GNUNET_NO);
reply = (struct GNUNET_DHT_ClientResultMessage *) &pm[1];
reply->unique_id = record->unique_id;
-#if DEBUG_DHT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Queueing reply to query %s for client %p\n", GNUNET_h2s (key),
record->client->client_handle);
-#endif
add_pending_message (record->client, pm);
if (GNUNET_YES == do_free)
remove_client_records (record->client, key, record);
msize += sizeof (struct PendingMessage);
pm = (struct PendingMessage *) GNUNET_malloc (msize);
mmsg = (struct GNUNET_DHT_MonitorGetMessage *) &pm[1];
- pm->msg = (struct GNUNET_MessageHeader *) mmsg;
+ pm->msg = &mmsg->header;
mmsg->header.size = htons (msize - sizeof (struct PendingMessage));
mmsg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET);
mmsg->options = htonl(options);
sizeof (struct GNUNET_DHT_ClientGetStopMessage)},
{&handle_dht_local_monitor, NULL,
GNUNET_MESSAGE_TYPE_DHT_MONITOR_START,
- sizeof (struct GNUNET_DHT_MonitorStartMessage)},
+ sizeof (struct GNUNET_DHT_MonitorStartStopMessage)},
+ {&handle_dht_local_monitor_stop, NULL,
+ GNUNET_MESSAGE_TYPE_DHT_MONITOR_STOP,
+ sizeof (struct GNUNET_DHT_MonitorStartStopMessage)},
{NULL, NULL, 0, 0}
};
forward_map = GNUNET_CONTAINER_multihashmap_create (1024);