*/
uint64_t unique_id;
+ /**
+ * Free the saved message once sent, set
+ * to GNUNET_YES for messages that don't
+ * receive responses!
+ */
+ int free_on_send;
+
};
struct PendingMessageList
GNUNET_SCHEDULER_REASON_PREREQ_DONE);
}
- if (pos->unique_id == 0)
+ GNUNET_assert(handle->th == NULL);
+ if (pos->free_on_send == GNUNET_YES)
GNUNET_free(pos->msg);
GNUNET_free (pos);
handle->current = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"`%s': In transmit_pending\n", "DHT API");
#endif
+ handle->th = NULL;
+
if (buf == NULL)
{
#if DEBUG_DHT_API
return 0;
}
- handle->th = NULL;
-
if (handle->current != NULL)
{
tsize = ntohs (handle->current->msg->size);
return; /* action already pending */
if (GNUNET_YES != try_connect (handle))
{
+ handle->th = NULL;
finish (handle, GNUNET_SYSERR);
return;
}
handle->cfg);
if (handle->current != NULL)
{
+ handle->th = NULL;
finish(handle, GNUNET_SYSERR); /* If there was a current message, kill it! */
}
#if RETRANSMIT
"`%s': Called GNUNET_DHT_disconnect\n", "DHT API");
#endif
GNUNET_assert (handle != NULL);
- if (handle->th != NULL) /* We have a live transmit request in the Aether */
+ if (handle->th != NULL) /* We have a live transmit request */
{
GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th);
handle->th = NULL;
}
/**
- * Perform an asynchronous FIND_PEER operation on the DHT.
+ * Send a message to the DHT telling it to start issuing random GET
+ * requests every 'frequency' milliseconds.
+ *
+ * @param handle handle to the DHT service
+ * @param frequency delay (in milliseconds) between sending malicious messages
+ * @param cont continuation to call once the message is sent
+ * @param cont_cls closure for continuation
+ *
+ * @return GNUNET_YES if the control message was sent, GNUNET_NO if not
+ */
+int GNUNET_DHT_set_malicious_getter (struct GNUNET_DHT_Handle *handle, int frequency, GNUNET_SCHEDULER_Task cont, void *cont_cls)
+{
+ struct GNUNET_DHT_ControlMessage *msg;
+ struct PendingMessage *pending;
+
+ if ((handle->current != NULL) && (handle->retransmit_stage != DHT_RETRANSMITTING))
+ return GNUNET_NO;
+
+ msg = GNUNET_malloc(sizeof(struct GNUNET_DHT_ControlMessage));
+ msg->header.size = htons(sizeof(struct GNUNET_DHT_ControlMessage));
+ msg->header.type = htons(GNUNET_MESSAGE_TYPE_DHT_CONTROL);
+ msg->command = htons(GNUNET_MESSAGE_TYPE_DHT_MALICIOUS_GET);
+ msg->variable = htons(frequency);
+
+ pending = GNUNET_malloc (sizeof (struct PendingMessage));
+ pending->msg = &msg->header;
+ pending->timeout = GNUNET_TIME_relative_get_forever();
+ pending->free_on_send = GNUNET_YES;
+ pending->cont = cont;
+ pending->cont_cls = cont_cls;
+ pending->unique_id = 0;
+
+ if (handle->current == NULL)
+ {
+ handle->current = pending;
+ process_pending_message (handle);
+ }
+ else
+ {
+ handle->retransmit_stage = DHT_RETRANSMITTING_MESSAGE_QUEUED;
+ handle->retransmission_buffer = pending;
+ }
+
+ return GNUNET_YES;
+}
+
+/**
+ * Send a message to the DHT telling it to issue a single find
+ * peer request using the peers unique identifier as key. This
+ * is used to fill the routing table, and is normally controlled
+ * by the DHT itself. However, for testing and perhaps more
+ * close control over the DHT, this can be explicitly managed.
+ *
+ * @param handle handle to the DHT service
+ * @param cont continuation to call once the message is sent
+ * @param cont_cls closure for continuation
+ *
+ * @return GNUNET_YES if the control message was sent, GNUNET_NO if not
+ */
+int GNUNET_DHT_find_peers (struct GNUNET_DHT_Handle *handle,
+ GNUNET_SCHEDULER_Task cont, void *cont_cls)
+{
+ struct GNUNET_DHT_ControlMessage *msg;
+ struct PendingMessage *pending;
+
+ if ((handle->current != NULL) && (handle->retransmit_stage != DHT_RETRANSMITTING))
+ return GNUNET_NO;
+
+ msg = GNUNET_malloc(sizeof(struct GNUNET_DHT_ControlMessage));
+ msg->header.size = htons(sizeof(struct GNUNET_DHT_ControlMessage));
+ msg->header.type = htons(GNUNET_MESSAGE_TYPE_DHT_CONTROL);
+ msg->command = htons(GNUNET_MESSAGE_TYPE_DHT_FIND_PEER);
+
+ pending = GNUNET_malloc (sizeof (struct PendingMessage));
+ pending->msg = &msg->header;
+ pending->timeout = GNUNET_TIME_relative_get_forever();
+ pending->free_on_send = GNUNET_YES;
+ pending->cont = cont;
+ pending->cont_cls = cont_cls;
+ pending->unique_id = 0;
+
+ if (handle->current == NULL)
+ {
+ handle->current = pending;
+ process_pending_message (handle);
+ }
+ else
+ {
+ handle->retransmit_stage = DHT_RETRANSMITTING_MESSAGE_QUEUED;
+ handle->retransmission_buffer = pending;
+ }
+
+ return GNUNET_YES;
+}
+
+/**
+ * Send a message to the DHT telling it to start issuing random PUT
+ * requests every 'frequency' milliseconds.
+ *
+ * @param handle handle to the DHT service
+ * @param frequency delay (in milliseconds) between sending malicious messages
+ * @param cont continuation to call once the message is sent
+ * @param cont_cls closure for continuation
+ *
+ * @return GNUNET_YES if the control message was sent, GNUNET_NO if not
+ */
+int GNUNET_DHT_set_malicious_putter (struct GNUNET_DHT_Handle *handle, int frequency, GNUNET_SCHEDULER_Task cont, void *cont_cls)
+{
+ struct GNUNET_DHT_ControlMessage *msg;
+ struct PendingMessage *pending;
+
+ if ((handle->current != NULL) && (handle->retransmit_stage != DHT_RETRANSMITTING))
+ return GNUNET_NO;
+
+ msg = GNUNET_malloc(sizeof(struct GNUNET_DHT_ControlMessage));
+ msg->header.size = htons(sizeof(struct GNUNET_DHT_ControlMessage));
+ msg->header.type = htons(GNUNET_MESSAGE_TYPE_DHT_CONTROL);
+ msg->command = htons(GNUNET_MESSAGE_TYPE_DHT_MALICIOUS_PUT);
+ msg->variable = htons(frequency);
+
+ pending = GNUNET_malloc (sizeof (struct PendingMessage));
+ pending->msg = &msg->header;
+ pending->timeout = GNUNET_TIME_relative_get_forever();
+ pending->free_on_send = GNUNET_YES;
+ pending->cont = cont;
+ pending->cont_cls = cont_cls;
+ pending->unique_id = 0;
+
+ if (handle->current == NULL)
+ {
+ handle->current = pending;
+ process_pending_message (handle);
+ }
+ else
+ {
+ handle->retransmit_stage = DHT_RETRANSMITTING_MESSAGE_QUEUED;
+ handle->retransmission_buffer = pending;
+ }
+
+ return GNUNET_YES;
+}
+
+/**
+ * Send a message to the DHT telling it to start dropping
+ * all requests received.
+ *
+ * @param handle handle to the DHT service
+ * @param cont continuation to call once the message is sent
+ * @param cont_cls closure for continuation
+ *
+ * @return GNUNET_YES if the control message was sent, GNUNET_NO if not
+ */
+int GNUNET_DHT_set_malicious_dropper (struct GNUNET_DHT_Handle *handle, GNUNET_SCHEDULER_Task cont, void *cont_cls)
+{
+ struct GNUNET_DHT_ControlMessage *msg;
+ struct PendingMessage *pending;
+
+ if ((handle->current != NULL) && (handle->retransmit_stage != DHT_RETRANSMITTING))
+ return GNUNET_NO;
+
+ msg = GNUNET_malloc(sizeof(struct GNUNET_DHT_ControlMessage));
+ msg->header.size = htons(sizeof(struct GNUNET_DHT_ControlMessage));
+ msg->header.type = htons(GNUNET_MESSAGE_TYPE_DHT_CONTROL);
+ msg->command = htons(GNUNET_MESSAGE_TYPE_DHT_MALICIOUS_DROP);
+ msg->variable = htons(0);
+
+ pending = GNUNET_malloc (sizeof (struct PendingMessage));
+ pending->msg = &msg->header;
+ pending->timeout = GNUNET_TIME_relative_get_forever();
+ pending->free_on_send = GNUNET_YES;
+ pending->cont = cont;
+ pending->cont_cls = cont_cls;
+ pending->unique_id = 0;
+
+ if (handle->current == NULL)
+ {
+ handle->current = pending;
+ process_pending_message (handle);
+ }
+ else
+ {
+ handle->retransmit_stage = DHT_RETRANSMITTING_MESSAGE_QUEUED;
+ handle->retransmission_buffer = pending;
+ }
+
+ return GNUNET_YES;
+}
+
+
+/**
+ * Initiate a generic DHT route operation.
*
* @param handle handle to the DHT service
* @param key the key to look up
message->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_LOCAL_ROUTE);
memcpy (&message->key, key, sizeof (GNUNET_HashCode));
message->options = htonl (options);
- message->desired_replication_level = htonl (options);
+ message->desired_replication_level = htonl (desired_replication_level);
message->unique_id = GNUNET_htonll (route_handle->uid);
memcpy (&message[1], enc, ntohs (enc->size));
pending = GNUNET_malloc (sizeof (struct PendingMessage));
pending->msg = &message->header;
pending->timeout = timeout;
+ if (iter == NULL)
+ pending->free_on_send = GNUNET_YES;
pending->cont = cont;
pending->cont_cls = cont_cls;
pending->unique_id = route_handle->uid;
struct GNUNET_DHT_GetHandle *
GNUNET_DHT_get_start (struct GNUNET_DHT_Handle *handle,
struct GNUNET_TIME_Relative timeout,
- uint32_t type,
+ enum GNUNET_BLOCK_Type type,
const GNUNET_HashCode * key,
GNUNET_DHT_GetIterator iter,
void *iter_cls,
get_msg.type = htons (type);
get_handle->route_handle =
- GNUNET_DHT_route_start (handle, key, 0, 0, &get_msg.header, timeout,
+ GNUNET_DHT_route_start (handle, key, DEFAULT_GET_REPLICATION, 0, &get_msg.header, timeout,
&get_reply_iterator, get_handle, cont, cont_cls);
return get_handle;
pending->timeout = GNUNET_TIME_relative_get_forever();
pending->cont = cont;
pending->cont_cls = cont_cls;
+ pending->free_on_send = GNUNET_YES;
pending->unique_id = 0; /* When finished is called, free pending->msg */
if (route_handle->dht_handle->current == NULL)
void *cont_cls)
{
struct GNUNET_DHT_FindPeerHandle *find_peer_handle;
- struct GNUNET_MessageHeader find_peer_msg;
+ struct GNUNET_DHT_FindPeerMessage find_peer_msg;
if ((handle->current != NULL) && (handle->retransmit_stage != DHT_RETRANSMITTING)) /* Can't send right now, we have a pending message... */
return NULL;
"FIND PEER", GNUNET_h2s (key));
#endif
- find_peer_msg.size = htons(sizeof(struct GNUNET_MessageHeader));
- find_peer_msg.type = htons(GNUNET_MESSAGE_TYPE_DHT_FIND_PEER);
+ find_peer_msg.header.size = htons(sizeof(struct GNUNET_DHT_FindPeerMessage));
+ find_peer_msg.header.type = htons(GNUNET_MESSAGE_TYPE_DHT_FIND_PEER);
find_peer_handle->route_handle =
- GNUNET_DHT_route_start (handle, key, 0, options, &find_peer_msg,
+ GNUNET_DHT_route_start (handle, key, 0, options, &find_peer_msg.header,
timeout, &find_peer_reply_iterator,
find_peer_handle, cont, cont_cls);
return find_peer_handle;
void
GNUNET_DHT_put (struct GNUNET_DHT_Handle *handle,
const GNUNET_HashCode * key,
- uint32_t type,
+ enum GNUNET_BLOCK_Type type,
uint32_t size,
const char *data,
struct GNUNET_TIME_Absolute exp,
if ((handle->current != NULL) && (handle->retransmit_stage != DHT_RETRANSMITTING))
{
+ GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "handle->current is not null!\n");
if (cont != NULL)
{
GNUNET_SCHEDULER_add_continuation (handle->sched, cont, cont_cls,
put_msg->expiration = GNUNET_TIME_absolute_hton(exp);
memcpy (&put_msg[1], data, size);
- put_route = GNUNET_DHT_route_start (handle, key, 0, 0, &put_msg->header, timeout, NULL,
+ put_route = GNUNET_DHT_route_start (handle, key, DEFAULT_PUT_REPLICATION, 0, &put_msg->header, timeout, NULL,
NULL, cont, cont_cls);
if (put_route == NULL) /* Route start failed! */
{
+ GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "route start for PUT failed!\n");
if (cont != NULL)
{
GNUNET_SCHEDULER_add_continuation (handle->sched, cont, cont_cls,
}
}
else
- GNUNET_free(put_route);
+ {
+ GNUNET_free(put_route);
+ }
GNUNET_free (put_msg);
}
+
+/* end of dht_api.c */