*/
#define DHT_BLOOM_SIZE 128
+/**
+ * Desired replication level for FIND PEER requests
+ */
+#define FIND_PEER_REPLICATION_LEVEL 4
+
/**
* How often to update our preference levels for peers in our routing tables.
*/
GNUNET_TIME_absolute_get_remaining (pending->timeout),
&peer->id, msize,
&core_transmit_notify, peer);
-
return off;
}
* the two hash codes increases
*/
static unsigned int
-distance (const GNUNET_HashCode * target, const GNUNET_HashCode * have)
+get_distance (const GNUNET_HashCode * target, const GNUNET_HashCode * have)
{
unsigned int bucket;
unsigned int msb;
}
-/**
- * Return a number that is larger the closer the
- * "have" GNUNET_hash code is to the "target".
- *
- * @return inverse distance metric, non-zero.
- * Must fudge the value if NO bits match.
- */
-static unsigned int
-inverse_distance (const GNUNET_HashCode * target, const GNUNET_HashCode * have)
-{
- if (GNUNET_CRYPTO_hash_matching_bits (target, have) == 0)
- return 1; /* Never return 0! */
- return ((unsigned int) -1) - distance (target, have);
-}
-
-
/**
* Check whether my identity is closer than any known peers. If a
* non-null bloomfilter is given, check if this is the closest peer
* that hasn't already been routed to.
- * FIXME: needed?
*
* @param key hash code to check closeness to
* @param bloom bloomfilter, exclude these entries from the decision
* @return GNUNET_YES if node location is closest,
* GNUNET_NO otherwise.
*/
-/* static */
-int
+static int
am_closest_peer (const GNUNET_HashCode *key,
const struct GNUNET_CONTAINER_BloomFilter *bloom)
{
return GNUNET_YES;
bucket_num = find_bucket (key);
bits = GNUNET_CRYPTO_hash_matching_bits (&my_identity.hashPubKey, key);
- my_distance = distance (&my_identity.hashPubKey, key);
+ my_distance = get_distance (&my_identity.hashPubKey, key);
pos = k_buckets[bucket_num].head;
count = 0;
while ((pos != NULL) && (count < bucket_size))
unsigned int count;
unsigned int selected;
struct PeerInfo *pos;
- unsigned int distance;
- unsigned int largest_distance;
+ unsigned int dist;
+ unsigned int smallest_distance;
struct PeerInfo *chosen;
if (hops >= GDS_NSE_get ())
{
/* greedy selection (closest peer that is not in bloomfilter) */
- largest_distance = 0;
+ smallest_distance = UINT_MAX;
chosen = NULL;
for (bc = closest_bucket; bc < MAX_BUCKETS; bc++)
{
count = 0;
while ((pos != NULL) && (count < bucket_size))
{
- /* If we are doing strict Kademlia routing, then checking the bloomfilter is basically cheating! */
if (GNUNET_NO ==
GNUNET_CONTAINER_bloomfilter_test (bloom, &pos->id.hashPubKey))
{
- distance = inverse_distance (key, &pos->id.hashPubKey);
- if (distance > largest_distance)
+ dist = get_distance (key, &pos->id.hashPubKey);
+ if (dist < smallest_distance)
{
chosen = pos;
- largest_distance = distance;
+ smallest_distance = dist;
}
}
count++;
// FIXME: pass priority!?
GDS_NEIGHBOURS_handle_get (GNUNET_BLOCK_TYPE_DHT_HELLO,
GNUNET_DHT_RO_FIND_PEER,
- 16 /* FIXME: replication level? */,
+ FIND_PEER_REPLICATION_LEVEL,
0,
&my_identity.hashPubKey,
NULL, 0,
uint32_t putlen;
uint16_t msize;
size_t payload_size;
+ enum GNUNET_DHT_RouteOption options;
struct GNUNET_CONTAINER_BloomFilter *bf;
GNUNET_HashCode test_key;
}
put_path = (const struct GNUNET_PeerIdentity*) &put[1];
payload = &put_path[putlen];
+ options = ntohl (put->options);
payload_size = msize - (sizeof (struct PeerPutMessage) +
putlen * sizeof (struct GNUNET_PeerIdentity));
switch (GNUNET_BLOCK_get_key (GDS_block_context,
struct GNUNET_PeerIdentity pp[putlen+1];
/* extend 'put path' by sender */
- memcpy (pp, put_path, putlen * sizeof (struct GNUNET_PeerIdentity));
- pp[putlen] = *peer;
-
+ if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE))
+ {
+ memcpy (pp, put_path, putlen * sizeof (struct GNUNET_PeerIdentity));
+ pp[putlen] = *peer;
+ putlen++;
+ }
+ else
+ putlen = 0;
+
/* give to local clients */
GDS_CLIENT_handle_reply (GNUNET_TIME_absolute_ntoh (put->expiration_time),
&put->key,
0, NULL,
- putlen + 1,
+ putlen,
pp,
ntohl (put->type),
payload_size,
payload);
/* store locally */
- GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (put->expiration_time),
- &put->key,
- putlen + 1, pp,
- ntohl (put->type),
- payload_size,
- payload);
+ if ( (0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
+ (am_closest_peer (&put->key,
+ bf) ) )
+ GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (put->expiration_time),
+ &put->key,
+ putlen, pp,
+ ntohl (put->type),
+ payload_size,
+ payload);
/* route to other peers */
GDS_NEIGHBOURS_handle_put (ntohl (put->type),
- ntohl (put->options),
+ options,
ntohl (put->desired_replication_level),
GNUNET_TIME_absolute_ntoh (put->expiration_time),
ntohl (put->hop_count) + 1 /* who adds +1? */,
bf,
&put->key,
- putlen + 1, pp,
+ putlen, pp,
payload,
payload_size);
}
/* remember request for routing replies */
GDS_ROUTING_add (peer,
type,
+ options,
&get->key,
xquery, xquery_size,
reply_bf, get->bf_mutator);
/* FIXME: check options (find peer, local-processing-only-if-nearest, etc.!) */
/* local lookup (this may update the reply_bf) */
- GDS_DATACACHE_handle_get (&get->key,
- type,
- xquery, xquery_size,
- &reply_bf,
- get->bf_mutator);
+ if ( (0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
+ (am_closest_peer (&get->key,
+ peer_bf) ) )
+ GDS_DATACACHE_handle_get (&get->key,
+ type,
+ xquery, xquery_size,
+ &reply_bf,
+ get->bf_mutator);
/* FIXME: should track if the local lookup resulted in a
definitive result and then NOT do P2P forwarding */
-
- /* P2P forwarding */
+
+ /* P2P forwarding */
GDS_NEIGHBOURS_handle_get (type,
options,
ntohl (get->desired_replication_level),
/* append 'peer' to 'get_path' */
{
struct GNUNET_PeerIdentity xget_path[get_path_length+1];
-
+
memcpy (xget_path, get_path, get_path_length * sizeof (struct GNUNET_PeerIdentity));
xget_path[get_path_length] = *peer;
+ get_path_length++;
/* forward to local clients */
GDS_CLIENT_handle_reply (GNUNET_TIME_absolute_ntoh (prm->expiration_time),
&prm->key,
- get_path_length + 1,
+ get_path_length,
xget_path,
put_path_length,
put_path,
&prm->key,
put_path_length,
put_path,
- get_path_length + 1,
+ get_path_length,
xget_path,
data,
data_size);
*/
uint32_t reply_bf_mutator;
+ /**
+ * Request options.
+ */
+ enum GNUNET_DHT_RouteOption options;
+
};
struct ProcessContext *pc = cls;
struct RecentRequest *rr = value;
enum GNUNET_BLOCK_EvaluationResult eval;
+ unsigned int gpl;
+ unsigned int ppl;
if ( (rr->type != GNUNET_BLOCK_TYPE_ANY) &&
(rr->type != pc->type) )
return GNUNET_OK; /* type missmatch */
+
+ if (0 != (rr->options & GNUNET_DHT_RO_RECORD_ROUTE))
+ {
+ gpl = pc->get_path_length;
+ ppl = pc->put_path_length;
+ }
+ else
+ {
+ gpl = 0;
+ ppl = 0;
+ }
eval = GNUNET_BLOCK_evaluate (GDS_block_context,
pc->type,
key,
pc->type,
pc->expiration_time,
key,
- pc->put_path_length,
+ ppl,
pc->put_path,
- pc->get_path_length,
+ gpl,
pc->get_path,
pc->data,
pc->data_size);
*
* @param sender peer that originated the request
* @param type type of the block
+ * @param options options for processing
* @param key key for the content
* @param xquery extended query
* @param xquery_size number of bytes in xquery
void
GDS_ROUTING_add (const struct GNUNET_PeerIdentity *sender,
enum GNUNET_BLOCK_Type type,
+ enum GNUNET_DHT_RouteOption options,
const GNUNET_HashCode *key,
const void *xquery,
size_t xquery_size,
recent_req->reply_bf =
GNUNET_CONTAINER_bloomfilter_copy (reply_bf);
recent_req->type = type;
+ recent_req->options = options;
recent_req->xquery = &recent_req[1];
recent_req->xquery_size = xquery_size;
recent_req->reply_bf_mutator = reply_bf_mutator;