#include "gnunet_protocols.h"
#include "gnunet_signatures.h"
#include "gnunet_statistics_service.h"
+#include "gnunet_transport_service.h"
#include "gnunet_util_lib.h"
#include "gnunet-service-fs_indexing.h"
#include "fs.h"
*/
#define TRUST_FLUSH_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
+/**
+ * How quickly do we age cover traffic? At the given
+ * time interval, remaining cover traffic counters are
+ * decremented by 1/16th.
+ */
+#define COVER_AGE_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
+
/**
* How often do we at most PUT content into the DHT?
*/
};
-
-
-
/**
* Doubly-linked list of messages we are performing
* due to a pending request.
*/
static struct GNUNET_LOAD_Value *rt_entry_lifetime;
+/**
+ * How many query messages have we received 'recently' that
+ * have not yet been claimed as cover traffic?
+ */
+static unsigned int cover_query_count;
+
+/**
+ * How many content messages have we received 'recently' that
+ * have not yet been claimed as cover traffic?
+ */
+static unsigned int cover_content_count;
+
+/**
+ * ID of our task that we use to age the cover counters.
+ */
+static GNUNET_SCHEDULER_TaskIdentifier cover_age_task;
+
+static void
+age_cover_counters (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ cover_content_count = (cover_content_count * 15) / 16;
+ cover_query_count = (cover_query_count * 15) / 16;
+ cover_age_task = GNUNET_SCHEDULER_add_delayed (COVER_AGE_FREQUENCY,
+ &age_cover_counters,
+ NULL);
+}
+
/**
* We've just now completed a datastore request. Update our
* datastore load calculations.
static struct GNUNET_TIME_Relative
get_latency (const struct GNUNET_TRANSPORT_ATS_Information *atsi)
{
- /* FIXME: extract latency data from 'atsi' */
- return GNUNET_TIME_UNIT_SECONDS;
+ while ( (ntohl (atsi->type) != GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR) &&
+ (ntohl (atsi->type) != GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY) )
+ atsi++;
+ if (ntohl (atsi->type) == GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR)
+ {
+ GNUNET_break (0);
+ /* how can we not have latency data? */
+ return GNUNET_TIME_UNIT_SECONDS;
+ }
+ return GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
+ ntohl (atsi->value));
}
cfg = NULL;
GNUNET_free_non_null (trustDirectory);
trustDirectory = NULL;
+ GNUNET_SCHEDULER_cancel (cover_age_task);
+ cover_age_task = GNUNET_SCHEDULER_NO_TASK;
}
&process_dht_reply,
pr);
}
+
+ if ( (pr->anonymity_level > 1) &&
+ (cover_query_count < pr->anonymity_level - 1) )
+ {
+ delay = get_processing_delay ();
+#if DEBUG_FS
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Not enough cover traffic to forward query `%s', will try again in %llu ms!\n",
+ GNUNET_h2s (&pr->query),
+ delay.rel_value);
+#endif
+ pr->task = GNUNET_SCHEDULER_add_delayed (delay,
+ &forward_request_task,
+ pr);
+ return;
+ }
+ /* consume cover traffic */
+ if (pr->anonymity_level > 1)
+ cover_query_count -= pr->anonymity_level - 1;
+
/* (1) select target */
psc.pr = pr;
psc.target_score = -DBL_MAX;
*/
uint32_t priority;
+ /**
+ * Anonymity requirements for this reply.
+ */
+ uint32_t anonymity_level;
+
/**
* Evaluation result (returned).
*/
size_t msize;
unsigned int i;
+ if (NULL == pr->client_request_list)
+ {
+ /* reply will go over the network, check for cover traffic */
+ if ( (prq->anonymity_level > 1) &&
+ (cover_content_count < prq->anonymity_level - 1) )
+ {
+ /* insufficient cover traffic, skip */
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# replies suppressed due to lack of cover traffic"),
+ 1,
+ GNUNET_NO);
+ return GNUNET_YES;
+ }
+ if (prq->anonymity_level > 1)
+ cover_content_count -= prq->anonymity_level - 1;
+ }
#if DEBUG_FS
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Matched result (type %u) for query `%s' with pending request\n",
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
+ cover_content_count++;
#if DEBUG_FS
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Received result for query `%s' from peer `%4s'\n",
prq.type = type;
prq.expiration = expiration;
prq.priority = 0;
+ prq.anonymity_level = 1;
prq.finished = GNUNET_NO;
prq.request_found = GNUNET_NO;
GNUNET_CONTAINER_multihashmap_get_multiple (query_request_map,
prq.priority = priority;
prq.finished = GNUNET_NO;
prq.request_found = GNUNET_NO;
+ prq.anonymity_level = anonymity;
if ( (old_rf == 0) &&
(pr->results_found == 0) )
update_datastore_delays (pr->start_time);
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
+ cover_query_count++;
bm = ntohl (gm->hash_bitmap);
bits = 0;
cps = GNUNET_CONTAINER_multihashmap_get (connected_peers,
GNUNET_SERVER_add_handlers (server, handlers);
+ cover_age_task = GNUNET_SCHEDULER_add_delayed (COVER_AGE_FREQUENCY,
+ &age_cover_counters,
+ NULL);
GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
&shutdown_task,
NULL);