GNUnet 0.21.2
gnunet-service-dht_neighbours.c File Reference

GNUnet DHT service's bucket and neighbour management code. More...

#include "gnunet_common.h"
#include "platform.h"
#include "gnunet_constants.h"
#include "gnunet_protocols.h"
#include "gnunet_hello_uri_lib.h"
#include "gnunet-service-dht.h"
#include "gnunet-service-dht_neighbours.h"
#include "gnunet-service-dht_routing.h"
#include "dht.h"
#include "dht_helper.h"
Include dependency graph for gnunet-service-dht_neighbours.c:

Go to the source code of this file.

Data Structures

struct  PeerResultMessage
 P2P Result message. More...
 
struct  PeerGetMessage
 P2P GET message. More...
 
struct  Target
 List of targets that we can use to reach this peer. More...
 
struct  PeerInfo
 Entry for a peer in a bucket. More...
 
struct  PeerBucket
 Peers are grouped into buckets. More...
 

Macros

#define LOG_TRAFFIC(kind, ...)
 
#define SANITY_CHECKS   2
 Enable slow sanity checks to debug issues. More...
 
#define MAX_BUCKETS   sizeof(struct GNUNET_HashCode) * 8
 How many buckets will we allow in total. More...
 
#define DEFAULT_BUCKET_SIZE   8
 What is the maximum number of peers in a given bucket. More...
 
#define FIND_PEER_REPLICATION_LEVEL   4
 Desired replication level for FIND PEER requests. More...
 
#define MAXIMUM_PENDING_PER_PEER   64
 Maximum allowed number of pending messages per peer. More...
 
#define DHT_MINIMUM_FIND_PEER_INTERVAL
 How long at least to wait before sending another find peer request. More...
 
#define DHT_AVG_FIND_PEER_INTERVAL
 How long to additionally wait on average per bucket_size to send out the FIND PEER requests if we did successfully connect (!) to a a new peer and added it to a bucket (as counted in newly_found_peers). More...
 
#define GET_TIMEOUT   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
 How long at most to wait for transmission of a GET request to another peer? More...
 

Functions

static void send_done_cb (void *cls)
 Function called whenever we finished sending to a target. More...
 
static void do_send (struct PeerInfo *pi, const struct GNUNET_MessageHeader *msg)
 Send msg to pi. More...
 
static int find_bucket (const struct GNUNET_HashCode *hc)
 Find the optimal bucket for this key. More...
 
static enum GNUNET_GenericReturnValue add_known_to_bloom (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
 Add each of the peers we already know to the Bloom filter of the request so that we don't get duplicate HELLOs. More...
 
static void send_find_peer_message (void *cls)
 Task to send a find peer message for our own peer identifier so that we can find the closest peers in the network to ourselves and attempt to connect to them. More...
 
static void update_hold (struct PeerBucket *bucket)
 The list of the first bucket_size peers of bucket changed. More...
 
void GDS_u_connect (void *cls, struct GNUNET_DHTU_Target *target, const struct GNUNET_PeerIdentity *pid, void **ctx)
 Function to call when we connect to a peer and can henceforth transmit to that peer. More...
 
void GDS_u_disconnect (void *ctx)
 Function to call when we disconnected from a peer and can henceforth cannot transmit to that peer anymore. More...
 
static unsigned int get_forward_count (uint16_t hop_count, uint16_t target_replication)
 To how many peers should we (on average) forward the request to obtain the desired target_replication count (on average). More...
 
enum GNUNET_GenericReturnValue GDS_am_closest_peer (const struct GNUNET_HashCode *key, const struct GNUNET_CONTAINER_BloomFilter *bloom)
 Check whether my identity is closer than any known peers. More...
 
static struct PeerInfoselect_peer (const struct GNUNET_HashCode *key, const struct GNUNET_CONTAINER_BloomFilter *bloom, uint32_t hops)
 Select a peer from the routing table that would be a good routing destination for sending a message for key. More...
 
static unsigned int get_target_peers (const struct GNUNET_HashCode *key, struct GNUNET_CONTAINER_BloomFilter *bloom, uint16_t hop_count, uint16_t target_replication, struct PeerInfo ***targets)
 Compute the set of peers that the given request should be forwarded to. More...
 
static void hello_check (const struct GNUNET_DATACACHE_Block *bd)
 If we got a HELLO, consider it for our own routing table. More...
 
enum GNUNET_GenericReturnValue GDS_NEIGHBOURS_handle_put (const struct GNUNET_DATACACHE_Block *bd, uint16_t desired_replication_level, uint16_t hop_count, struct GNUNET_CONTAINER_BloomFilter *bf)
 Perform a PUT operation. More...
 
enum GNUNET_GenericReturnValue GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type, enum GNUNET_DHT_RouteOption options, uint16_t desired_replication_level, uint16_t hop_count, const struct GNUNET_HashCode *key, const void *xquery, size_t xquery_size, struct GNUNET_BLOCK_Group *bg, struct GNUNET_CONTAINER_BloomFilter *peer_bf)
 Perform a GET operation. More...
 
struct PeerInfoGDS_NEIGHBOURS_lookup_peer (const struct GNUNET_PeerIdentity *target)
 Lookup peer by peer's identity. More...
 
bool GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi, const struct GNUNET_DATACACHE_Block *bd, const struct GNUNET_HashCode *query_hash, unsigned int get_path_length, const struct GNUNET_DHT_PathElement *get_path)
 Handle a reply (route to origin). More...
 
static enum GNUNET_GenericReturnValue check_dht_p2p_put (void *cls, const struct PeerPutMessage *put)
 Check validity of a p2p put request. More...
 
static void handle_dht_p2p_put (void *cls, const struct PeerPutMessage *put)
 Core handler for p2p put requests. More...
 
static void handle_find_my_hello (struct PeerInfo *pi, const struct GNUNET_HashCode *query_hash, struct GNUNET_BLOCK_Group *bg)
 We have received a request for a HELLO. More...
 
static void handle_find_local_hello (struct PeerInfo *pi, const struct GNUNET_HashCode *query_hash, struct GNUNET_BLOCK_Group *bg)
 We have received a request for nearby HELLOs. More...
 
static void handle_local_result (void *cls, const struct GNUNET_DATACACHE_Block *bd)
 Handle an exact result from local datacache for a GET operation. More...
 
static enum GNUNET_GenericReturnValue check_dht_p2p_get (void *cls, const struct PeerGetMessage *get)
 Check validity of p2p get request. More...
 
static void handle_dht_p2p_get (void *cls, const struct PeerGetMessage *get)
 Core handler for p2p get requests. More...
 
static bool process_reply_with_path (const struct GNUNET_DATACACHE_Block *bd, const struct GNUNET_HashCode *query_hash, unsigned int get_path_length, const struct GNUNET_DHT_PathElement *get_path)
 Process a reply, after the get_path has been updated. More...
 
static enum GNUNET_GenericReturnValue check_dht_p2p_result (void *cls, const struct PeerResultMessage *prm)
 Check validity of p2p result message. More...
 
static void handle_dht_p2p_result (void *cls, const struct PeerResultMessage *prm)
 Core handler for p2p result messages. More...
 
static enum GNUNET_GenericReturnValue check_dht_p2p_hello (void *cls, const struct GNUNET_MessageHeader *hello)
 Check validity of a p2p hello message. More...
 
static void handle_dht_p2p_hello (void *cls, const struct GNUNET_MessageHeader *hello)
 Core handler for p2p HELLO messages. More...
 
void GDS_u_receive (void *cls, void **tctx, void **sctx, const void *message, size_t message_size)
 Function to call when we receive a message. More...
 
void GDS_try_connect (void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
 Callback function used to extract URIs from a builder. More...
 
void GDS_NEIGHBOURS_broadcast (const struct GNUNET_MessageHeader *msg)
 Send msg to all peers in our buckets. More...
 
enum GNUNET_GenericReturnValue GDS_NEIGHBOURS_init ()
 Initialize neighbours subsystem. More...
 
void GDS_NEIGHBOURS_done ()
 Shutdown neighbours subsystem. More...
 
struct GNUNET_PeerIdentityGDS_NEIGHBOURS_get_id ()
 Get the ID of the local node. More...
 

Variables

static int cache_results
 Do we cache all results that we are routing in the local datacache? More...
 
static unsigned int closest_bucket
 The lowest currently used bucket, initially 0 (for 0-bits matching bucket). More...
 
static unsigned int newly_found_peers
 How many peers have we added since we sent out our last find peer request? More...
 
static int disable_try_connect
 Option for testing that disables the 'connect' function of the DHT. More...
 
static struct PeerBucket k_buckets [sizeof(struct GNUNET_HashCode) *8]
 The buckets. More...
 
static struct GNUNET_CONTAINER_MultiPeerMapall_connected_peers
 Hash map of all CORE-connected peers, for easy removal from k_buckets on disconnect. More...
 
static unsigned int bucket_size = 8
 Maximum size for each bucket. More...
 
static struct GNUNET_SCHEDULER_Taskfind_peer_task
 Task that sends FIND PEER requests. More...
 

Detailed Description

GNUnet DHT service's bucket and neighbour management code.

Author
Christian Grothoff
Nathan Evans

Definition in file gnunet-service-dht_neighbours.c.

Macro Definition Documentation

◆ LOG_TRAFFIC

#define LOG_TRAFFIC (   kind,
  ... 
)
Value:
GNUNET_log_from (kind, "dht-traffic", \
__VA_ARGS__)
#define GNUNET_log_from(kind, comp,...)

Definition at line 38 of file gnunet-service-dht_neighbours.c.

◆ SANITY_CHECKS

#define SANITY_CHECKS   2

Enable slow sanity checks to debug issues.

TODO: might want to eventually implement probabilistic load-based path verification, but for now it is all or nothing based on this define.

0: do not check – if signatures become performance critical 1: check all external inputs – normal production for now 2: check internal computations as well – for debugging

Definition at line 52 of file gnunet-service-dht_neighbours.c.

◆ MAX_BUCKETS

#define MAX_BUCKETS   sizeof(struct GNUNET_HashCode) * 8

How many buckets will we allow in total.

Definition at line 57 of file gnunet-service-dht_neighbours.c.

◆ DEFAULT_BUCKET_SIZE

#define DEFAULT_BUCKET_SIZE   8

What is the maximum number of peers in a given bucket.

Definition at line 62 of file gnunet-service-dht_neighbours.c.

◆ FIND_PEER_REPLICATION_LEVEL

#define FIND_PEER_REPLICATION_LEVEL   4

Desired replication level for FIND PEER requests.

Definition at line 67 of file gnunet-service-dht_neighbours.c.

◆ MAXIMUM_PENDING_PER_PEER

#define MAXIMUM_PENDING_PER_PEER   64

Maximum allowed number of pending messages per peer.

Definition at line 72 of file gnunet-service-dht_neighbours.c.

◆ DHT_MINIMUM_FIND_PEER_INTERVAL

#define DHT_MINIMUM_FIND_PEER_INTERVAL
Value:
#define GNUNET_TIME_UNIT_MINUTES
One minute.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:484

How long at least to wait before sending another find peer request.

This is basically the frequency at which we will usually send out requests when we are 'perfectly' connected.

Definition at line 79 of file gnunet-service-dht_neighbours.c.

◆ DHT_AVG_FIND_PEER_INTERVAL

#define DHT_AVG_FIND_PEER_INTERVAL
Value:
#define GNUNET_TIME_UNIT_SECONDS
One second.

How long to additionally wait on average per bucket_size to send out the FIND PEER requests if we did successfully connect (!) to a a new peer and added it to a bucket (as counted in newly_found_peers).

This time is Multiplied by 100 * newly_found_peers / bucket_size to get the new delay for finding peers (the DHT_MINIMUM_FIND_PEER_INTERVAL is still added on top). Also the range in which we randomize, so the effective value is half of the number given here.

Definition at line 92 of file gnunet-service-dht_neighbours.c.

◆ GET_TIMEOUT

How long at most to wait for transmission of a GET request to another peer?

Definition at line 98 of file gnunet-service-dht_neighbours.c.

Function Documentation

◆ send_done_cb()

static void send_done_cb ( void *  cls)
static

Function called whenever we finished sending to a target.

Marks the transmission as finished (and the target as ready for the next message).

Parameters
clsa struct Target *

Definition at line 399 of file gnunet-service-dht_neighbours.c.

400{
401 struct Target *t = cls;
402 struct PeerInfo *pi = t->pi; /* NULL if t->dropped! */
403
404 GNUNET_assert (t->load > 0);
405 t->load--;
406 if (0 < t->load)
407 return;
408 if (t->dropped)
409 {
410 GNUNET_free (t);
411 return;
412 }
413 /* move target back to the front */
415 pi->t_tail,
416 t);
418 pi->t_tail,
419 t);
420}
static struct GNUNET_SCHEDULER_Task * t
Main task.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_free(ptr)
Wrapper around free.
Entry for a peer in a bucket.
struct Target * t_tail
Tail of DLL of targets for this peer.
struct Target * t_head
Head of DLL of targets for this peer.
List of targets that we can use to reach this peer.

References GNUNET_assert, GNUNET_CONTAINER_DLL_insert, GNUNET_CONTAINER_DLL_remove, GNUNET_free, t, PeerInfo::t_head, and PeerInfo::t_tail.

Referenced by do_send().

Here is the caller graph for this function:

◆ do_send()

static void do_send ( struct PeerInfo pi,
const struct GNUNET_MessageHeader msg 
)
static

Send msg to pi.

Parameters
piwhere to send the message
msgmessage to send

Definition at line 430 of file gnunet-service-dht_neighbours.c.

432{
433 struct Target *t;
434
435 for (t = pi->t_head;
436 NULL != t;
437 t = t->next)
438 if (t->load < MAXIMUM_PENDING_PER_PEER)
439 break;
440 if (NULL == t)
441 {
442 /* all targets busy, drop message */
444 "# messages dropped (underlays busy)",
445 1,
446 GNUNET_NO);
447 return;
448 }
449 t->load++;
450 /* rotate busy targets to the end */
451 if (MAXIMUM_PENDING_PER_PEER == t->load)
452 {
454 pi->t_tail,
455 t);
457 pi->t_tail,
458 t);
459 }
460 GDS_u_send (t->u,
461 t->utarget,
462 msg,
463 ntohs (msg->size),
465 t);
466}
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
void GDS_u_send(struct GDS_Underlay *u, struct GNUNET_DHTU_Target *target, const void *msg, size_t msg_size, GNUNET_SCHEDULER_TaskCallback finished_cb, void *finished_cb_cls)
Send message to some other participant over the network.
struct GNUNET_STATISTICS_Handle * GDS_stats
Handle for the statistics service.
#define MAXIMUM_PENDING_PER_PEER
Maximum allowed number of pending messages per peer.
static void send_done_cb(void *cls)
Function called whenever we finished sending to a target.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
@ GNUNET_NO
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
struct GNUNET_SCHEDULER_Task * next
This is a linked list.
Definition: scheduler.c:140
struct PeerInfo * pi
Peer this is a target for.

References GDS_stats, GDS_u_send(), GNUNET_CONTAINER_DLL_insert_tail, GNUNET_CONTAINER_DLL_remove, GNUNET_NO, GNUNET_STATISTICS_update(), MAXIMUM_PENDING_PER_PEER, msg, GNUNET_SCHEDULER_Task::next, Target::pi, send_done_cb(), GNUNET_MessageHeader::size, t, PeerInfo::t_head, and PeerInfo::t_tail.

Referenced by GDS_NEIGHBOURS_broadcast(), GDS_NEIGHBOURS_handle_get(), GDS_NEIGHBOURS_handle_put(), and GDS_NEIGHBOURS_handle_reply().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_bucket()

static int find_bucket ( const struct GNUNET_HashCode hc)
static

Find the optimal bucket for this key.

Parameters
hcthe hashcode to compare our identity to
Returns
the proper bucket index, or -1 on error (same hashcode)

Definition at line 477 of file gnunet-service-dht_neighbours.c.

478{
479 struct GNUNET_HashCode xor;
480 unsigned int bits;
481
484 &xor);
486 if (bits == MAX_BUCKETS)
487 {
488 /* How can all bits match? Got my own ID? */
489 GNUNET_break (0);
490 return -1;
491 }
492 return MAX_BUCKETS - bits - 1;
493}
struct GNUNET_HashCode GDS_my_identity_hash
Hash of the identity of this peer.
#define MAX_BUCKETS
How many buckets will we allow in total.
void GNUNET_CRYPTO_hash_xor(const struct GNUNET_HashCode *a, const struct GNUNET_HashCode *b, struct GNUNET_HashCode *result)
compute result = a ^ b
Definition: crypto_hash.c:135
unsigned int GNUNET_CRYPTO_hash_count_leading_zeros(const struct GNUNET_HashCode *h)
Count the number of leading 0 bits in h.
Definition: crypto_hash.c:177
uint32_t bits[512/8/sizeof(uint32_t)]
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
A 512-bit hashcode.

References GNUNET_HashCode::bits, GDS_my_identity_hash, GNUNET_break, GNUNET_CRYPTO_hash_count_leading_zeros(), GNUNET_CRYPTO_hash_xor(), and MAX_BUCKETS.

Referenced by GDS_am_closest_peer(), GDS_try_connect(), and GDS_u_connect().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_known_to_bloom()

static enum GNUNET_GenericReturnValue add_known_to_bloom ( void *  cls,
const struct GNUNET_PeerIdentity key,
void *  value 
)
static

Add each of the peers we already know to the Bloom filter of the request so that we don't get duplicate HELLOs.

Parameters
clsthe struct GNUNET_BLOCK_Group
keypeer identity to add to the bloom filter
valuethe peer information
Returns
GNUNET_YES (we should continue to iterate)

Definition at line 506 of file gnunet-service-dht_neighbours.c.

509{
510 struct GNUNET_BLOCK_Group *bg = cls;
511 struct PeerInfo *pi = value;
512
514 &pi->phash,
515 1);
517 "Adding known peer (%s) to Bloom filter for FIND PEER\n",
518 GNUNET_i2s (key));
519 return GNUNET_YES;
520}
struct GNUNET_HashCode key
The key used in the DHT.
static char * value
Value of the record to add/remove.
enum GNUNET_GenericReturnValue GNUNET_BLOCK_group_set_seen(struct GNUNET_BLOCK_Group *bg, const struct GNUNET_HashCode *seen_results, unsigned int seen_results_count)
Update block group to filter out the given results.
Definition: block.c:363
#define GNUNET_log(kind,...)
@ GNUNET_YES
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_DEBUG
Block group data.
struct GNUNET_HashCode phash
Hash of id.

References GNUNET_BLOCK_group_set_seen(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_YES, key, PeerInfo::phash, and value.

Referenced by send_find_peer_message().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ send_find_peer_message()

static void send_find_peer_message ( void *  cls)
static

Task to send a find peer message for our own peer identifier so that we can find the closest peers in the network to ourselves and attempt to connect to them.

Parameters
clsclosure for this task, NULL

Definition at line 531 of file gnunet-service-dht_neighbours.c.

532{
533 (void) cls;
534
535 /* Compute when to do this again (and if we should
536 even send a message right now) */
537 {
538 struct GNUNET_TIME_Relative next_send_time;
539 bool done_early;
540
541 find_peer_task = NULL;
542 done_early = (newly_found_peers > bucket_size);
543 /* schedule next round, taking longer if we found more peers
544 in the last round. */
545 next_send_time.rel_value_us =
551 1 + 100 * (1 + newly_found_peers) / bucket_size).rel_value_us);
555 GNUNET_SCHEDULER_add_delayed (next_send_time,
557 NULL);
558 if (done_early)
559 return;
560 }
561
562 /* actually send 'find peer' request */
563 {
564 struct GNUNET_BLOCK_Group *bg;
565 struct GNUNET_CONTAINER_BloomFilter *peer_bf;
566
569 NULL,
570 0,
571 "seen-set-size",
574 NULL);
577 bg);
578 peer_bf
582 if (GNUNET_OK !=
587 0, /* hop count */
589 NULL, 0, /* xquery */
590 bg,
591 peer_bf))
592 {
594 "# Failed to initiate FIND PEER lookup",
595 1,
596 GNUNET_NO);
597 }
598 else
599 {
601 "# FIND PEER messages initiated",
602 1,
603 GNUNET_NO);
604 }
607 }
608}
#define DHT_BLOOM_SIZE
Size of the bloom filter the DHT uses to filter peers.
Definition: dht.h:34
struct GNUNET_BLOCK_Context * GDS_block_context
Our handle to the BLOCK library.
static void send_find_peer_message(void *cls)
Task to send a find peer message for our own peer identifier so that we can find the closest peers in...
static unsigned int newly_found_peers
How many peers have we added since we sent out our last find peer request?
#define FIND_PEER_REPLICATION_LEVEL
Desired replication level for FIND PEER requests.
static struct GNUNET_CONTAINER_MultiPeerMap * all_connected_peers
Hash map of all CORE-connected peers, for easy removal from k_buckets on disconnect.
#define DHT_MINIMUM_FIND_PEER_INTERVAL
How long at least to wait before sending another find peer request.
static struct GNUNET_SCHEDULER_Task * find_peer_task
Task that sends FIND PEER requests.
static enum GNUNET_GenericReturnValue add_known_to_bloom(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Add each of the peers we already know to the Bloom filter of the request so that we don't get duplica...
static unsigned int bucket_size
Maximum size for each bucket.
enum GNUNET_GenericReturnValue GDS_NEIGHBOURS_handle_get(enum GNUNET_BLOCK_Type type, enum GNUNET_DHT_RouteOption options, uint16_t desired_replication_level, uint16_t hop_count, const struct GNUNET_HashCode *key, const void *xquery, size_t xquery_size, struct GNUNET_BLOCK_Group *bg, struct GNUNET_CONTAINER_BloomFilter *peer_bf)
Perform a GET operation.
#define DHT_AVG_FIND_PEER_INTERVAL
How long to additionally wait on average per bucket_size to send out the FIND PEER requests if we did...
void GNUNET_BLOCK_group_destroy(struct GNUNET_BLOCK_Group *bg)
Destroy resources used by a block group.
Definition: block.c:192
struct GNUNET_BLOCK_Group * GNUNET_BLOCK_group_create(struct GNUNET_BLOCK_Context *ctx, enum GNUNET_BLOCK_Type type, const void *raw_data, size_t raw_data_size,...)
Create a new block group.
Definition: block.c:247
struct GNUNET_CONTAINER_BloomFilter * GNUNET_CONTAINER_bloomfilter_init(const char *data, size_t size, unsigned int k)
Create a Bloom filter from raw bits.
void GNUNET_CONTAINER_bloomfilter_free(struct GNUNET_CONTAINER_BloomFilter *bf)
Free the space associated with a filter in memory, flush to drive if needed (do not free the space on...
#define GNUNET_CONSTANTS_BLOOMFILTER_K
K-value that must be used for the bloom filters in 'GET' queries.
uint64_t GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Generate a random unsigned 64-bit value.
@ GNUNET_CRYPTO_QUALITY_WEAK
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
@ GNUNET_DHT_RO_RECORD_ROUTE
We should keep track of the route that the message took in the P2P network.
@ GNUNET_DHT_RO_FIND_APPROXIMATE
Approximate results are fine.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
unsigned int GNUNET_CONTAINER_multipeermap_size(const struct GNUNET_CONTAINER_MultiPeerMap *map)
Get the number of key-value pairs in the map.
@ GNUNET_OK
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1278
@ GNUNET_BLOCK_TYPE_DHT_HELLO
Type of a block that contains a DHT-NG HELLO for a peer.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.

References add_known_to_bloom(), all_connected_peers, bucket_size, DHT_AVG_FIND_PEER_INTERVAL, DHT_BLOOM_SIZE, DHT_MINIMUM_FIND_PEER_INTERVAL, FIND_PEER_REPLICATION_LEVEL, find_peer_task, GDS_block_context, GDS_my_identity_hash, GDS_NEIGHBOURS_handle_get(), GDS_stats, GNUNET_assert, GNUNET_BLOCK_group_create(), GNUNET_BLOCK_group_destroy(), GNUNET_BLOCK_TYPE_DHT_HELLO, GNUNET_CONSTANTS_BLOOMFILTER_K, GNUNET_CONTAINER_bloomfilter_free(), GNUNET_CONTAINER_bloomfilter_init(), GNUNET_CONTAINER_multipeermap_iterate(), GNUNET_CONTAINER_multipeermap_size(), GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_u64(), GNUNET_DHT_RO_FIND_APPROXIMATE, GNUNET_DHT_RO_RECORD_ROUTE, GNUNET_NO, GNUNET_OK, GNUNET_SCHEDULER_add_delayed(), GNUNET_STATISTICS_update(), GNUNET_TIME_relative_multiply(), newly_found_peers, GNUNET_TIME_Relative::rel_value_us, and send_find_peer_message().

Referenced by GDS_u_connect(), and send_find_peer_message().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_hold()

static void update_hold ( struct PeerBucket bucket)
static

The list of the first bucket_size peers of bucket changed.

We should thus make sure we have called 'hold' all of the first bucket_size peers!

Parameters
[in,out]bucketthe bucket where the peer set changed

Definition at line 619 of file gnunet-service-dht_neighbours.c.

620{
621 unsigned int off = 0;
622
623 /* find the peer -- we just go over all of them, should
624 be hardly any more expensive than just finding the 'right'
625 one. */
626 for (struct PeerInfo *pos = bucket->head;
627 NULL != pos;
628 pos = pos->next)
629 {
630 if (off > bucket_size)
631 break; /* We only hold up to #bucket_size peers per bucket */
632 off++;
633 for (struct Target *tp = pos->t_head;
634 NULL != tp;
635 tp = tp->next)
636 if (NULL == tp->ph)
637 tp->ph = GDS_u_hold (tp->u,
638 tp->utarget);
639 }
640}
struct GNUNET_DHTU_PreferenceHandle * GDS_u_hold(struct GDS_Underlay *u, struct GNUNET_DHTU_Target *target)
Create a hold on target at underlay u.
struct PeerInfo * head
Head of DLL.
struct PeerInfo * next
Next peer entry (DLL)
struct Target * next
Kept in a DLL.

References bucket_size, GDS_u_hold(), PeerBucket::head, Target::next, and PeerInfo::next.

Referenced by GDS_u_connect(), and GDS_u_disconnect().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GDS_u_connect()

void GDS_u_connect ( void *  cls,
struct GNUNET_DHTU_Target target,
const struct GNUNET_PeerIdentity pid,
void **  ctx 
)

Function to call when we connect to a peer and can henceforth transmit to that peer.

Parameters
clsthe closure, must be a struct GDS_Underlay
targethandle to the target, pointer will remain valid until disconnect_cb is called
pidpeer identity, pointer will remain valid until disconnect_cb is called
[out]ctxstorage space for DHT to use in association with this target

Definition at line 644 of file gnunet-service-dht_neighbours.c.

648{
649 struct GDS_Underlay *u = cls;
650 struct PeerInfo *pi;
651 struct PeerBucket *bucket;
652 bool do_hold = false;
653
654 /* Check for connect to self message */
656 pid))
657 return;
659 "Connected to peer %s\n",
660 GNUNET_i2s (pid));
662 pid);
663 if (NULL == pi)
664 {
666 "# peers connected",
667 1,
668 GNUNET_NO);
669 pi = GNUNET_new (struct PeerInfo);
670 pi->id = *pid;
672 sizeof(*pid),
673 &pi->phash);
674 pi->peer_bucket = find_bucket (&pi->phash);
675 GNUNET_assert ( (pi->peer_bucket >= 0) &&
676 ((unsigned int) pi->peer_bucket < MAX_BUCKETS));
677 bucket = &k_buckets[pi->peer_bucket];
679 bucket->tail,
680 pi);
681 bucket->peers_size++;
683 (unsigned int) pi->peer_bucket + 1);
686 &pi->id,
687 pi,
689 if (bucket->peers_size <= bucket_size)
690 {
692 do_hold = true;
693 }
696 {
697 /* got a first connection, good time to start with FIND PEER requests... */
700 NULL);
701 }
702 }
703 {
704 struct Target *t;
705
706 t = GNUNET_new (struct Target);
707 t->u = u;
708 t->utarget = target;
709 t->pi = pi;
711 pi->t_tail,
712 t);
713 *ctx = t;
714
715 }
716 if (do_hold)
717 update_hold (bucket);
718}
static mp_limb_t u[(((256)+GMP_NUMB_BITS - 1)/GMP_NUMB_BITS)]
static struct GNUNET_FS_Handle * ctx
struct GNUNET_PeerIdentity GDS_my_identity
Identity of this peer.
static int disable_try_connect
Option for testing that disables the 'connect' function of the DHT.
static int find_bucket(const struct GNUNET_HashCode *hc)
Find the optimal bucket for this key.
static unsigned int closest_bucket
The lowest currently used bucket, initially 0 (for 0-bits matching bucket).
static struct PeerBucket k_buckets[sizeof(struct GNUNET_HashCode) *8]
The buckets.
static void update_hold(struct PeerBucket *bucket)
The list of the first bucket_size peers of bucket changed.
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
void * GNUNET_CONTAINER_multipeermap_get(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Given a key find a value in the map matching the key.
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
#define GNUNET_MAX(a, b)
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1305
Information we keep per underlay.
Peers are grouped into buckets.
struct PeerInfo * tail
Tail of DLL.
unsigned int peers_size
Number of peers in the bucket.
struct GNUNET_PeerIdentity id
What is the identity of the peer?
int peer_bucket
Which bucket is this peer in?

References all_connected_peers, bucket_size, closest_bucket, ctx, disable_try_connect, find_bucket(), find_peer_task, GDS_my_identity, GDS_stats, GNUNET_assert, GNUNET_CONTAINER_DLL_insert, GNUNET_CONTAINER_DLL_insert_tail, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CONTAINER_multipeermap_get(), GNUNET_CONTAINER_multipeermap_put(), GNUNET_CONTAINER_multipeermap_size(), GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_MAX, GNUNET_memcmp, GNUNET_new, GNUNET_NO, GNUNET_OK, GNUNET_SCHEDULER_add_now(), GNUNET_STATISTICS_update(), GNUNET_YES, PeerBucket::head, PeerInfo::id, k_buckets, MAX_BUCKETS, newly_found_peers, PeerInfo::peer_bucket, PeerBucket::peers_size, PeerInfo::phash, Target::pi, pid, send_find_peer_message(), t, PeerInfo::t_head, PeerInfo::t_tail, PeerBucket::tail, u, and update_hold().

Referenced by load_underlay().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GDS_u_disconnect()

void GDS_u_disconnect ( void *  ctx)

Function to call when we disconnected from a peer and can henceforth cannot transmit to that peer anymore.

Parameters
[in]ctxstorage space used by the DHT in association with this target

Definition at line 722 of file gnunet-service-dht_neighbours.c.

723{
724 struct Target *t = ctx;
725 struct PeerInfo *pi;
726 struct PeerBucket *bucket;
727 bool was_held = false;
728
729 /* Check for disconnect from self message (on shutdown) */
730 if (NULL == t)
731 return;
732 pi = t->pi;
734 pi->t_tail,
735 t);
736 if (NULL != t->ph)
737 {
738 GDS_u_drop (t->u,
739 t->ph);
740 t->ph = NULL;
741 was_held = true;
742 }
743 if (t->load > 0)
744 {
745 t->dropped = true;
746 t->pi = NULL;
747 }
748 else
749 {
750 GNUNET_free (t);
751 }
752 if (NULL != pi->t_head)
753 return; /* got other connections still */
755 "Disconnected from peer %s\n",
756 GNUNET_i2s (&pi->id));
758 "# peers connected",
759 -1,
760 GNUNET_NO);
763 &pi->id,
764 pi));
767 {
769 find_peer_task = NULL;
770 }
771 GNUNET_assert (pi->peer_bucket >= 0);
772 bucket = &k_buckets[pi->peer_bucket];
774 bucket->tail,
775 pi);
776 GNUNET_assert (bucket->peers_size > 0);
777 bucket->peers_size--;
778 if ( (was_held) &&
779 (bucket->peers_size >= bucket_size - 1) )
780 update_hold (bucket);
781 while ( (closest_bucket > 0) &&
784 GNUNET_free (pi->hello);
785 GNUNET_free (pi);
786}
void GDS_u_drop(struct GDS_Underlay *u, struct GNUNET_DHTU_PreferenceHandle *ph)
Drop a hold ph from underlay u.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:981
void * hello
Block with a HELLO of this peer.

References all_connected_peers, bucket_size, closest_bucket, ctx, disable_try_connect, find_peer_task, GDS_stats, GDS_u_drop(), GNUNET_assert, GNUNET_CONTAINER_DLL_remove, GNUNET_CONTAINER_multipeermap_remove(), GNUNET_CONTAINER_multipeermap_size(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_SCHEDULER_cancel(), GNUNET_STATISTICS_update(), GNUNET_YES, PeerBucket::head, PeerInfo::hello, PeerInfo::id, k_buckets, PeerInfo::peer_bucket, PeerBucket::peers_size, t, PeerInfo::t_head, PeerInfo::t_tail, PeerBucket::tail, and update_hold().

Referenced by load_underlay().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_forward_count()

static unsigned int get_forward_count ( uint16_t  hop_count,
uint16_t  target_replication 
)
static

To how many peers should we (on average) forward the request to obtain the desired target_replication count (on average).

Parameters
hop_countnumber of hops the message has traversed
target_replicationthe number of total paths desired
Returns
Some number of peers to forward the message to

Definition at line 798 of file gnunet-service-dht_neighbours.c.

800{
801 uint32_t random_value;
802 uint32_t forward_count;
803 float target_value;
804 float rm1;
805
806 if (hop_count > GDS_NSE_get () * 4.0)
807 {
808 /* forcefully terminate */
810 "# requests TTL-dropped",
811 1,
812 GNUNET_NO);
813 return 0;
814 }
815 if (hop_count > GDS_NSE_get () * 2.0)
816 {
817 /* Once we have reached our ideal number of hops, only forward to 1 peer */
818 return 1;
819 }
820 /* bound by system-wide maximum and minimum */
821 if (0 == target_replication)
822 target_replication = 1; /* 0 is verboten */
823 target_replication =
825 target_replication);
826 rm1 = target_replication - 1.0;
827 target_value =
828 1 + (rm1) / (GDS_NSE_get () + (rm1 * hop_count));
829
830 /* Set forward count to floor of target_value */
831 forward_count = (uint32_t) target_value;
832 /* Subtract forward_count (floor) from target_value (yields value between 0 and 1) */
833 target_value = target_value - forward_count;
835 UINT32_MAX);
836 if (random_value < (target_value * UINT32_MAX))
837 forward_count++;
838 return GNUNET_MIN (forward_count,
840}
double GDS_NSE_get(void)
Return the current NSE.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
#define GNUNET_DHT_MAXIMUM_REPLICATION_LEVEL
Maximum allowed replication level for all requests.
#define GNUNET_MIN(a, b)

References GDS_NSE_get(), GDS_stats, GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_u32(), GNUNET_DHT_MAXIMUM_REPLICATION_LEVEL, GNUNET_MIN, GNUNET_NO, and GNUNET_STATISTICS_update().

Referenced by get_target_peers().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GDS_am_closest_peer()

enum GNUNET_GenericReturnValue GDS_am_closest_peer ( const struct GNUNET_HashCode key,
const struct GNUNET_CONTAINER_BloomFilter bloom 
)

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.

Parameters
keyhash code to check closeness to
bloombloomfilter, exclude these entries from the decision
Returns
GNUNET_YES if node location is closest, GNUNET_NO otherwise.

Definition at line 854 of file gnunet-service-dht_neighbours.c.

856{
858 key))
859 return GNUNET_YES;
860 for (int bucket_num = find_bucket (key);
861 bucket_num < closest_bucket;
862 bucket_num++)
863 {
864 unsigned int count = 0;
865
866 GNUNET_assert (bucket_num >= 0);
867 for (struct PeerInfo *pos = k_buckets[bucket_num].head;
868 NULL != pos;
869 pos = pos->next)
870 {
871 if (count >= bucket_size)
872 break; /* we only consider first #bucket_size entries per bucket */
873 count++;
874 if ( (NULL != bloom) &&
875 (GNUNET_YES ==
877 &pos->phash)) )
878 continue; /* Ignore filtered peers */
879 /* All peers in this bucket must be closer than us, as
880 they mismatch with our PID on the pivotal bit. So
881 because an unfiltered peer exists, we are not the
882 closest. */
883 int delta = GNUNET_CRYPTO_hash_xorcmp (&pos->phash,
885 key);
886 switch (delta)
887 {
888 case -1: /* pos closer */
889 return GNUNET_NO;
890 case 0: /* identical, impossible! */
891 GNUNET_assert (0);
892 break;
893 case 1: /* I am closer */
894 break;
895 }
896 }
897 }
898 /* No closer (unfiltered) peers found; we must be the closest! */
899 return GNUNET_YES;
900}
bool GNUNET_CONTAINER_bloomfilter_test(const struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
Test if an element is in the filter.
int GNUNET_CRYPTO_hash_xorcmp(const struct GNUNET_HashCode *h1, const struct GNUNET_HashCode *h2, const struct GNUNET_HashCode *target)
Find out which of the two GNUNET_CRYPTO_hash codes is closer to target in the XOR metric (Kademlia).
Definition: crypto_hash.c:243
static struct GNUNET_TIME_Relative delta
Definition: speedup.c:36

References bucket_size, closest_bucket, delta, find_bucket(), GDS_my_identity_hash, GNUNET_assert, GNUNET_CONTAINER_bloomfilter_test(), GNUNET_CRYPTO_hash_xorcmp(), GNUNET_memcmp, GNUNET_NO, GNUNET_YES, PeerBucket::head, k_buckets, key, and PeerInfo::next.

Referenced by handle_dht_local_put(), handle_dht_p2p_get(), and handle_dht_p2p_put().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ select_peer()

static struct PeerInfo * select_peer ( const struct GNUNET_HashCode key,
const struct GNUNET_CONTAINER_BloomFilter bloom,
uint32_t  hops 
)
static

Select a peer from the routing table that would be a good routing destination for sending a message for key.

The resulting peer must not be in the set of bloom blocked peers.

Note that we should not ALWAYS select the closest peer to the target, we do a "random" peer selection if the number of hops is below the logarithm of the network size estimate.

In all cases, we only consider at most the first bucket_size peers of any k_buckets. The other peers in the bucket are there because GNUnet doesn't really allow the DHT to "reject" connections, but we only use the first bucket_size, even if more exist. (The idea is to ensure that those connections are frequently used, and for others to be not used by the DHT, and thus possibly dropped by transport due to disuse).

Parameters
keythe key we are selecting a peer to route to
blooma Bloom filter containing entries this request has seen already
hopshow many hops has this message traversed thus far
Returns
Peer to route to, or NULL on error

Definition at line 925 of file gnunet-service-dht_neighbours.c.

928{
929 if (0 == closest_bucket)
930 {
932 "# Peer selection failed",
933 1,
934 GNUNET_NO);
935 return NULL; /* we have zero connections */
936 }
937 if (hops >= GDS_NSE_get ())
938 {
939 /* greedy selection (closest peer that is not in Bloom filter) */
940 struct PeerInfo *chosen = NULL;
941 int best_bucket;
942 int bucket_offset;
943
944 {
945 struct GNUNET_HashCode xor;
946
949 &xor);
950 best_bucket = GNUNET_CRYPTO_hash_count_leading_zeros (&xor);
951 }
952 if (best_bucket >= closest_bucket)
953 bucket_offset = closest_bucket - 1;
954 else
955 bucket_offset = best_bucket;
956 while (-1 != bucket_offset)
957 {
958 struct PeerBucket *bucket = &k_buckets[bucket_offset];
959 unsigned int count = 0;
960
961 for (struct PeerInfo *pos = bucket->head;
962 NULL != pos;
963 pos = pos->next)
964 {
965 if (count >= bucket_size)
966 break; /* we only consider first #bucket_size entries per bucket */
967 count++;
968 if ( (NULL != bloom) &&
969 (GNUNET_YES ==
971 &pos->phash)) )
972 {
974 "Excluded peer `%s' due to BF match in greedy routing for %s\n",
975 GNUNET_i2s (&pos->id),
976 GNUNET_h2s (key));
977 continue;
978 }
979 if (NULL == chosen)
980 {
981 /* First candidate */
982 chosen = pos;
983 }
984 else
985 {
986 int delta = GNUNET_CRYPTO_hash_xorcmp (&pos->phash,
987 &chosen->phash,
988 key);
989 switch (delta)
990 {
991 case -1: /* pos closer */
992 chosen = pos;
993 break;
994 case 0: /* identical, impossible! */
995 GNUNET_assert (0);
996 break;
997 case 1: /* chosen closer */
998 break;
999 }
1000 }
1001 count++;
1002 } /* for all (#bucket_size) peers in bucket */
1003 if (NULL != chosen)
1004 break;
1005
1006 /* If we chose nothing in first iteration, first go through deeper
1007 buckets (best chance to find a good match), and if we still found
1008 nothing, then to shallower buckets. Terminate on any match in the
1009 current bucket, as this search order guarantees that it can only get
1010 worse as we keep going. */
1011 if (bucket_offset > best_bucket)
1012 {
1013 /* Go through more deeper buckets */
1014 bucket_offset++;
1015 if (bucket_offset == closest_bucket)
1016 {
1017 /* Can't go any deeper, if nothing selected,
1018 go for shallower buckets */
1019 bucket_offset = best_bucket - 1;
1020 }
1021 }
1022 else
1023 {
1024 /* We're either at the 'best_bucket' or already moving
1025 on to shallower buckets. */
1026 if (bucket_offset == best_bucket)
1027 bucket_offset++; /* go for deeper buckets */
1028 else
1029 bucket_offset--; /* go for shallower buckets */
1030 }
1031 } /* for applicable buckets (starting at best match) */
1032 if (NULL == chosen)
1033 {
1035 "# Peer selection failed",
1036 1,
1037 GNUNET_NO);
1038 return NULL;
1039 }
1041 "Selected peer `%s' in greedy routing for %s\n",
1042 GNUNET_i2s (&chosen->id),
1043 GNUNET_h2s (key));
1044 return chosen;
1045 } /* end of 'greedy' peer selection */
1046
1047 /* select "random" peer */
1048 /* count number of peers that are available and not filtered,
1049 but limit to at most #bucket_size peers, starting with
1050 those 'furthest' from us. */
1051 {
1052 unsigned int total = 0;
1053 unsigned int selected;
1054
1055 for (unsigned int bc = 0; bc < closest_bucket; bc++)
1056 {
1057 struct PeerBucket *bucket = &k_buckets[bc];
1058 unsigned int count = 0;
1059
1060 for (struct PeerInfo *pos = bucket->head;
1061 NULL != pos;
1062 pos = pos->next)
1063 {
1064 count++;
1065 if (count > bucket_size)
1066 break; /* limits search to #bucket_size peers per bucket */
1067 if ( (NULL != bloom) &&
1068 (GNUNET_YES ==
1070 &pos->phash)) )
1071 {
1073 "Excluded peer `%s' due to BF match in random routing for %s\n",
1074 GNUNET_i2s (&pos->id),
1075 GNUNET_h2s (key));
1076 continue; /* Ignore filtered peers */
1077 }
1078 total++;
1079 } /* for all peers in bucket */
1080 } /* for all buckets */
1081 if (0 == total) /* No peers to select from! */
1082 {
1084 "# Peer selection failed",
1085 1,
1086 GNUNET_NO);
1087 return NULL;
1088 }
1089
1090 /* Now actually choose a peer */
1092 total);
1093 for (unsigned int bc = 0; bc < closest_bucket; bc++)
1094 {
1095 unsigned int count = 0;
1096
1097 for (struct PeerInfo *pos = k_buckets[bc].head;
1098 pos != NULL;
1099 pos = pos->next)
1100 {
1101 count++;
1102 if (count > bucket_size)
1103 break; /* limits search to #bucket_size peers per bucket */
1104
1105 if ( (NULL != bloom) &&
1106 (GNUNET_YES ==
1108 &pos->phash)) )
1109 continue; /* Ignore bloomfiltered peers */
1110 if (0 == selected--)
1111 {
1113 "Selected peer `%s' in random routing for %s\n",
1114 GNUNET_i2s (&pos->id),
1115 GNUNET_h2s (key));
1116 return pos;
1117 }
1118 } /* for peers in bucket */
1119 } /* for all buckets */
1120 } /* random peer selection scope */
1121 GNUNET_break (0);
1122 return NULL;
1123}
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).

References bucket_size, closest_bucket, delta, GDS_my_identity_hash, GDS_NSE_get(), GDS_stats, GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_bloomfilter_test(), GNUNET_CRYPTO_hash_count_leading_zeros(), GNUNET_CRYPTO_hash_xor(), GNUNET_CRYPTO_hash_xorcmp(), GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_u32(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_YES, PeerBucket::head, PeerInfo::id, k_buckets, key, PeerInfo::next, and PeerInfo::phash.

Referenced by get_target_peers(), and handle_find_local_hello().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_target_peers()

static unsigned int get_target_peers ( const struct GNUNET_HashCode key,
struct GNUNET_CONTAINER_BloomFilter bloom,
uint16_t  hop_count,
uint16_t  target_replication,
struct PeerInfo ***  targets 
)
static

Compute the set of peers that the given request should be forwarded to.

Parameters
keyrouting key
[in,out]bloomBloom filter excluding peers as targets, all selected peers will be added to the Bloom filter
hop_countnumber of hops the request has traversed so far
target_replicationdesired number of replicas
[out]targetswhere to store an array of target peers (to be free()ed by the caller)
Returns
number of peers returned in targets.

Definition at line 1140 of file gnunet-service-dht_neighbours.c.

1145{
1146 unsigned int target;
1147 unsigned int off;
1148 struct PeerInfo **rtargets;
1149
1150 GNUNET_assert (NULL != bloom);
1151 target = get_forward_count (hop_count,
1152 target_replication);
1153 if (0 == target)
1154 {
1155 *targets = NULL;
1156 return 0;
1157 }
1158 rtargets = GNUNET_new_array (target,
1159 struct PeerInfo *);
1160 for (off = 0; off < target; off++)
1161 {
1162 struct PeerInfo *nxt;
1163
1164 nxt = select_peer (key,
1165 bloom,
1166 hop_count);
1167 if (NULL == nxt)
1168 break;
1169 rtargets[off] = nxt;
1170 }
1172 "Selected %u/%u peers at hop %u for %s (target was %u)\n",
1173 off,
1175 (unsigned int) hop_count,
1176 GNUNET_h2s (key),
1177 target);
1178 if (0 == off)
1179 {
1180 GNUNET_free (rtargets);
1181 *targets = NULL;
1182 return 0;
1183 }
1184 *targets = rtargets;
1186 "Forwarding query `%s' to %u peers (goal was %u peers)\n",
1187 GNUNET_h2s (key),
1188 off,
1189 target);
1190 return off;
1191}
static struct PeerInfo * select_peer(const struct GNUNET_HashCode *key, const struct GNUNET_CONTAINER_BloomFilter *bloom, uint32_t hops)
Select a peer from the routing table that would be a good routing destination for sending a message f...
static unsigned int get_forward_count(uint16_t hop_count, uint16_t target_replication)
To how many peers should we (on average) forward the request to obtain the desired target_replication...
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.

References all_connected_peers, get_forward_count(), GNUNET_assert, GNUNET_CONTAINER_multipeermap_size(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_h2s(), GNUNET_log, GNUNET_new_array, key, and select_peer().

Referenced by GDS_NEIGHBOURS_handle_get(), and GDS_NEIGHBOURS_handle_put().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ hello_check()

static void hello_check ( const struct GNUNET_DATACACHE_Block bd)
static

If we got a HELLO, consider it for our own routing table.

Parameters
bdblock data we got

Definition at line 1200 of file gnunet-service-dht_neighbours.c.

1201{
1202 struct GNUNET_HELLO_Builder *b;
1203
1205 return;
1206
1208 bd->data_size);
1210 {
1213 NULL);
1214 }
1216}
void GDS_try_connect(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
Callback function used to extract URIs from a builder.
void GNUNET_HELLO_builder_free(struct GNUNET_HELLO_Builder *builder)
Release resources of a builder.
Definition: hello-uri.c:373
const struct GNUNET_PeerIdentity * GNUNET_HELLO_builder_iterate(const struct GNUNET_HELLO_Builder *builder, GNUNET_HELLO_UriCallback uc, void *uc_cls)
Iterate over URIs in a builder.
Definition: hello-uri.c:909
struct GNUNET_HELLO_Builder * GNUNET_HELLO_builder_from_block(const void *block, size_t block_size)
Parse block into builder.
Definition: hello-uri.c:414
enum GNUNET_BLOCK_Type type
Type of the block.
const void * data
Actual block data.
size_t data_size
Number of bytes in data.
Context for building (or parsing) HELLO URIs.
Definition: hello-uri.c:205

References GNUNET_DATACACHE_Block::data, GNUNET_DATACACHE_Block::data_size, disable_try_connect, GDS_try_connect(), GNUNET_BLOCK_TYPE_DHT_HELLO, GNUNET_HELLO_builder_free(), GNUNET_HELLO_builder_from_block(), GNUNET_HELLO_builder_iterate(), GNUNET_YES, and GNUNET_DATACACHE_Block::type.

Referenced by GDS_NEIGHBOURS_handle_put(), and handle_dht_p2p_result().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GDS_NEIGHBOURS_handle_put()

enum GNUNET_GenericReturnValue GDS_NEIGHBOURS_handle_put ( const struct GNUNET_DATACACHE_Block bd,
uint16_t  desired_replication_level,
uint16_t  hop_count,
struct GNUNET_CONTAINER_BloomFilter bf 
)

Perform a PUT operation.

Forwards the given request to other peers. Does not store the data locally. Does not give the data to local clients. May do nothing if this is the only peer in the network (or if we are the closest peer in the network).

Parameters
bddata about the block
desired_replication_leveldesired replication level
hop_counthow many hops has this message traversed so far
bfBloom filter of peers this PUT has already traversed
Returns
GNUNET_OK if the request was forwarded, GNUNET_NO if not

Definition at line 1220 of file gnunet-service-dht_neighbours.c.

1224{
1225 unsigned int target_count;
1226 struct PeerInfo **targets;
1227 size_t msize;
1228 enum GNUNET_DHT_RouteOption ro;
1229 unsigned int put_path_length = bd->put_path_length;
1230 const struct GNUNET_DHT_PathElement *put_path = bd->put_path;
1231 bool truncated = (0 != (bd->ro & GNUNET_DHT_RO_TRUNCATED));
1232 const struct GNUNET_PeerIdentity *trunc_peer
1233 = truncated
1234 ? &bd->trunc_peer
1235 : NULL;
1237
1240 bd->ro, &ro,
1241 bd->expiration_time,
1242 bd->data, bd->data_size,
1243 put_path, put_path_length,
1244 &put_path_length,
1245 trunc_peer);
1246 /* Path may have been truncated by the call above */
1247 truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
1249 "Adding myself (%s) to PUT bloomfilter for %s with RO(%s/%s)\n",
1251 GNUNET_h2s (&bd->key),
1252 (bd->ro & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE) ? "x" : "-",
1253 (bd->ro & GNUNET_DHT_RO_RECORD_ROUTE) ? "R" : "-");
1254
1255 /* if we got a HELLO, consider it for our own routing table */
1256 hello_check (bd);
1257 GNUNET_assert (NULL != bf);
1261 "# PUT requests routed",
1262 1,
1263 GNUNET_NO);
1264 if (GNUNET_OK != ret)
1265 return ret;
1266 target_count
1267 = get_target_peers (&bd->key,
1268 bf,
1269 hop_count,
1270 desired_replication_level,
1271 &targets);
1272 if (0 == target_count)
1273 {
1275 "Routing PUT for %s terminates after %u hops at %s\n",
1276 GNUNET_h2s (&bd->key),
1277 (unsigned int) hop_count,
1279 return GNUNET_NO;
1280 }
1281 for (unsigned int i = 0; i < target_count; i++)
1282 {
1283 struct PeerInfo *target = targets[i];
1284 struct PeerPutMessage *ppm;
1285 char buf[msize] GNUNET_ALIGN;
1286
1287 ppm = (struct PeerPutMessage *) buf;
1290 &target->phash));
1292 &target->phash);
1294 &target->id, &target->phash, bf,
1295 &bd->key, ro, bd->type, bd->expiration_time,
1296 bd->data, bd->data_size,
1297 put_path, put_path_length,
1299 trunc_peer);
1301 "Routing PUT for %s after %u hops to %s\n",
1302 GNUNET_h2s (&bd->key),
1303 (unsigned int) hop_count,
1304 GNUNET_i2s (&target->id));
1305 do_send (target,
1306 &ppm->header);
1307 }
1308 GNUNET_free (targets);
1310 "# PUT messages queued for transmission",
1311 target_count,
1312 GNUNET_NO);
1313 return (0 < target_count) ? GNUNET_OK : GNUNET_NO;
1314}
void GDS_helper_make_put_message(struct PeerPutMessage *ppm, size_t msize, const struct GNUNET_CRYPTO_EddsaPrivateKey *sk, const struct GNUNET_PeerIdentity *target, const struct GNUNET_HashCode *target_hash, const struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *block_key, enum GNUNET_DHT_RouteOption ro, enum GNUNET_BLOCK_Type block_type, struct GNUNET_TIME_Absolute block_expiration_time, const uint8_t *block_data, size_t block_data_len, const struct GNUNET_DHT_PathElement *put_path, unsigned int put_path_len, size_t hop_count, uint32_t desired_replication_level, const struct GNUNET_PeerIdentity *trunc_peer)
Definition: dht_helper.c:172
enum GNUNET_GenericReturnValue GDS_helper_put_message_get_size(size_t *msize_out, const struct GNUNET_PeerIdentity *my_identity, enum GNUNET_DHT_RouteOption ro_in, enum GNUNET_DHT_RouteOption *ro_out, struct GNUNET_TIME_Absolute block_expiration_time, const uint8_t *block_data, size_t block_data_len, const struct GNUNET_DHT_PathElement *put_path_in, unsigned int put_path_len_in, unsigned int *put_path_len_out, const struct GNUNET_PeerIdentity *trunc_peer)
Definition: dht_helper.c:36
static int ret
Final status code.
Definition: gnunet-arm.c:94
struct GNUNET_CRYPTO_EddsaPrivateKey GDS_my_private_key
Our private key.
static void do_send(struct PeerInfo *pi, const struct GNUNET_MessageHeader *msg)
Send msg to pi.
static unsigned int get_target_peers(const struct GNUNET_HashCode *key, struct GNUNET_CONTAINER_BloomFilter *bloom, uint16_t hop_count, uint16_t target_replication, struct PeerInfo ***targets)
Compute the set of peers that the given request should be forwarded to.
static void hello_check(const struct GNUNET_DATACACHE_Block *bd)
If we got a HELLO, consider it for our own routing table.
void GNUNET_CONTAINER_bloomfilter_add(struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
Add an element to the filter.
GNUNET_DHT_RouteOption
Options for routing.
@ GNUNET_DHT_RO_TRUNCATED
Flag set if the path was truncated.
@ GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE
Each peer along the way should process the request (otherwise only peers locally closest to the key w...
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to 'struct's.
GNUNET_GenericReturnValue
Named constants for return values.
const struct GNUNET_DHT_PathElement * put_path
PUT path taken by the block, array of peer identities.
enum GNUNET_DHT_RouteOption ro
Options for routing for the block.
struct GNUNET_PeerIdentity trunc_peer
If the path was truncated, this is the peer ID at which the path was truncated.
struct GNUNET_HashCode key
Key of the block.
unsigned int put_path_length
Length of the put_path array.
struct GNUNET_TIME_Absolute expiration_time
When does the block expire?
A (signed) path tracking a block's flow through the DHT is represented by an array of path elements,...
The identity of the host (wraps the signing key of the peer).
P2P PUT message.
Definition: dht.h:429
uint16_t desired_replication_level
Replication level for this message.
Definition: dht.h:453
uint16_t hop_count
Hop count.
Definition: dht.h:448
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_DHT_P2P_PUT.
Definition: dht.h:433
uint16_t put_path_length
Length of the PUT path that follows (if tracked).
Definition: dht.h:458

References GNUNET_DATACACHE_Block::data, GNUNET_DATACACHE_Block::data_size, PeerPutMessage::desired_replication_level, do_send(), GNUNET_DATACACHE_Block::expiration_time, GDS_helper_make_put_message(), GDS_helper_put_message_get_size(), GDS_my_identity, GDS_my_identity_hash, GDS_my_private_key, GDS_stats, get_target_peers(), GNUNET_ALIGN, GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_bloomfilter_add(), GNUNET_CONTAINER_bloomfilter_test(), GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, GNUNET_DHT_RO_RECORD_ROUTE, GNUNET_DHT_RO_TRUNCATED, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_h2s(), GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_STATISTICS_update(), PeerPutMessage::header, hello_check(), PeerPutMessage::hop_count, PeerInfo::id, GNUNET_DATACACHE_Block::key, PeerInfo::phash, GNUNET_DATACACHE_Block::put_path, GNUNET_DATACACHE_Block::put_path_length, PeerPutMessage::put_path_length, ret, GNUNET_DATACACHE_Block::ro, GNUNET_DATACACHE_Block::trunc_peer, and GNUNET_DATACACHE_Block::type.

Referenced by handle_dht_local_put(), and handle_dht_p2p_put().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GDS_NEIGHBOURS_handle_get()

enum GNUNET_GenericReturnValue GDS_NEIGHBOURS_handle_get ( enum GNUNET_BLOCK_Type  type,
enum GNUNET_DHT_RouteOption  options,
uint16_t  desired_replication_level,
uint16_t  hop_count,
const struct GNUNET_HashCode key,
const void *  xquery,
size_t  xquery_size,
struct GNUNET_BLOCK_Group bg,
struct GNUNET_CONTAINER_BloomFilter peer_bf 
)

Perform a GET operation.

Forwards the given request to other peers. Does not lookup the key locally. May do nothing if this is the only peer in the network (or if we are the closest peer in the network).

Parameters
typetype of the block
optionsrouting options
desired_replication_leveldesired replication count
hop_counthow many hops did this request traverse so far?
keykey for the content
xqueryextended query
xquery_sizenumber of bytes in xquery
bgblock group to filter replies
peer_bffilter for peers not to select (again, updated)
Returns
GNUNET_OK if the request was forwarded, GNUNET_NO if not

Definition at line 1318 of file gnunet-service-dht_neighbours.c.

1327{
1328 unsigned int target_count;
1329 struct PeerInfo **targets;
1330 size_t msize;
1331 size_t result_filter_size;
1332 void *result_filter;
1333
1334 GNUNET_assert (NULL != peer_bf);
1336 "# GET requests routed",
1337 1,
1338 GNUNET_NO);
1339 target_count = get_target_peers (key,
1340 peer_bf,
1341 hop_count,
1342 desired_replication_level,
1343 &targets);
1345 "Adding myself (%s) to GET bloomfilter for %s with RO(%s/%s)\n",
1347 GNUNET_h2s (key),
1349 (options & GNUNET_DHT_RO_RECORD_ROUTE) ? "R" : "-");
1350
1353 if (0 == target_count)
1354 {
1356 "Routing GET for %s terminates after %u hops at %s\n",
1357 GNUNET_h2s (key),
1358 (unsigned int) hop_count,
1360 return GNUNET_NO;
1361 }
1362 if (GNUNET_OK !=
1364 &result_filter,
1365 &result_filter_size))
1366 {
1367 result_filter = NULL;
1368 result_filter_size = 0;
1369 }
1370 msize = xquery_size + result_filter_size;
1371 if (msize + sizeof(struct PeerGetMessage) >= GNUNET_MAX_MESSAGE_SIZE)
1372 {
1373 GNUNET_break (0);
1374 GNUNET_free (result_filter);
1375 GNUNET_free (targets);
1376 return GNUNET_NO;
1377 }
1378 /* forward request */
1379 for (unsigned int i = 0; i < target_count; i++)
1380 {
1381 struct PeerInfo *target = targets[i];
1382 struct PeerGetMessage *pgm;
1383 char buf[sizeof (*pgm) + msize] GNUNET_ALIGN;
1384 char *rf;
1385
1387 "Routing GET for %s after %u hops to %s\n",
1388 GNUNET_h2s (key),
1389 (unsigned int) hop_count,
1390 GNUNET_i2s (&target->id));
1393 &target->phash));
1395 &target->phash);
1396 pgm = (struct PeerGetMessage *) buf;
1398 pgm->header.size = htons (sizeof (buf));
1399 pgm->type = htonl (type);
1400 pgm->options = htons (options);
1401 pgm->hop_count = htons (hop_count + 1);
1403 pgm->result_filter_size = htons ((uint16_t) result_filter_size);
1406 &target->phash));
1409 pgm->bloomfilter,
1411 pgm->key = *key;
1412 rf = (char *) &pgm[1];
1413 GNUNET_memcpy (rf,
1414 result_filter,
1417 xquery,
1418 xquery_size);
1419 do_send (target,
1420 &pgm->header);
1421 }
1423 "# GET messages queued for transmission",
1424 target_count,
1425 GNUNET_NO);
1426 GNUNET_free (targets);
1427 GNUNET_free (result_filter);
1428 return (0 < target_count) ? GNUNET_OK : GNUNET_NO;
1429}
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
static uint32_t type
Type string converted to DNS type value.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message,...
enum GNUNET_GenericReturnValue GNUNET_BLOCK_group_serialize(struct GNUNET_BLOCK_Group *bg, void **raw_data, size_t *raw_data_size)
Serialize state of a block group.
Definition: block.c:175
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_bloomfilter_get_raw_data(const struct GNUNET_CONTAINER_BloomFilter *bf, char *data, size_t size)
Copy the raw data of this Bloom filter into the given data array.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_MESSAGE_TYPE_DHT_P2P_GET
Peer tries to find data in DHT.
uint16_t result_filter_size
Size of the result filter.
char bloomfilter[128]
Bloomfilter (for peer identities) to stop circular routes.
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_DHT_P2P_GET.
uint16_t hop_count
Hop count.
uint16_t desired_replication_level
Desired replication level for this request.
uint16_t options
Processing options.
struct GNUNET_HashCode key
The key we are looking for.
uint32_t type
Desired content type.

References PeerGetMessage::bloomfilter, PeerGetMessage::desired_replication_level, DHT_BLOOM_SIZE, do_send(), GDS_my_identity, GDS_my_identity_hash, GDS_stats, get_target_peers(), GNUNET_ALIGN, GNUNET_assert, GNUNET_BLOCK_group_serialize(), GNUNET_break, GNUNET_CONTAINER_bloomfilter_add(), GNUNET_CONTAINER_bloomfilter_get_raw_data(), GNUNET_CONTAINER_bloomfilter_test(), GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, GNUNET_DHT_RO_RECORD_ROUTE, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_h2s(), GNUNET_i2s(), GNUNET_log, GNUNET_MAX_MESSAGE_SIZE, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_DHT_P2P_GET, GNUNET_NO, GNUNET_OK, GNUNET_STATISTICS_update(), GNUNET_YES, PeerGetMessage::header, PeerGetMessage::hop_count, PeerInfo::id, key, PeerGetMessage::key, options, PeerGetMessage::options, PeerInfo::phash, PeerGetMessage::result_filter_size, GNUNET_MessageHeader::size, type, GNUNET_MessageHeader::type, and PeerGetMessage::type.

Referenced by handle_dht_p2p_get(), send_find_peer_message(), and transmit_request().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GDS_NEIGHBOURS_lookup_peer()

struct PeerInfo * GDS_NEIGHBOURS_lookup_peer ( const struct GNUNET_PeerIdentity target)

Lookup peer by peer's identity.

Parameters
targetpeer to look up
Returns
NULL if we are not connected to target

Definition at line 1433 of file gnunet-service-dht_neighbours.c.

1434{
1436 target);
1437}

References all_connected_peers, and GNUNET_CONTAINER_multipeermap_get().

Referenced by process().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GDS_NEIGHBOURS_handle_reply()

bool GDS_NEIGHBOURS_handle_reply ( struct PeerInfo pi,
const struct GNUNET_DATACACHE_Block bd,
const struct GNUNET_HashCode query_hash,
unsigned int  get_path_length,
const struct GNUNET_DHT_PathElement get_path 
)

Handle a reply (route to origin).

Only forwards the reply back to other peers waiting for it. Does not do local caching or forwarding to local clients.

Parameters
pineighbour that should receive the block
bddetails about the reply
query_hashquery that was used for the request
get_path_lengthnumber of entries in put_path
get_pathpeers this reply has traversed so far (if tracked)
Returns
true on success

Definition at line 1441 of file gnunet-service-dht_neighbours.c.

1446{
1447 struct GNUNET_DHT_PathElement *paths;
1448 size_t msize;
1449 unsigned int ppl = bd->put_path_length;
1450 const struct GNUNET_DHT_PathElement *put_path = bd->put_path;
1451 enum GNUNET_DHT_RouteOption ro = bd->ro;
1452 bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
1453 const struct GNUNET_PeerIdentity *trunc_peer
1454 = truncated
1455 ? &bd->trunc_peer
1456 : NULL;
1457 bool tracking = (0 != (ro & GNUNET_DHT_RO_RECORD_ROUTE));
1458#if SANITY_CHECKS > 1
1459 unsigned int failure_offset;
1460
1461 failure_offset
1463 bd->data_size,
1464 bd->expiration_time,
1465 trunc_peer,
1466 put_path,
1467 ppl,
1468 get_path,
1469 get_path_length,
1471 if (0 != failure_offset)
1472 {
1473 GNUNET_assert (failure_offset <= ppl + get_path_length);
1474 GNUNET_break_op (0);
1475 if (failure_offset < ppl)
1476 {
1477 trunc_peer = &put_path[failure_offset - 1].pred;
1478 put_path += failure_offset;
1479 ppl -= failure_offset;
1480 truncated = true;
1482 }
1483 else
1484 {
1485 failure_offset -= ppl;
1486 if (0 == failure_offset)
1487 trunc_peer = &put_path[ppl - 1].pred;
1488 else
1489 trunc_peer = &get_path[failure_offset - 1].pred;
1490 ppl = 0;
1491 put_path = NULL;
1492 truncated = true;
1494 get_path += failure_offset;
1495 get_path_length -= failure_offset;
1496 }
1497 }
1498#endif
1499 msize = bd->data_size + sizeof (struct PeerResultMessage);
1500 if (msize > GNUNET_MAX_MESSAGE_SIZE)
1501 {
1502 GNUNET_break_op (0);
1503 return false;
1504 }
1505 if (truncated)
1506 msize += sizeof (struct GNUNET_PeerIdentity);
1507 if (tracking)
1508 msize += sizeof (struct GNUNET_CRYPTO_EddsaSignature);
1509 if (msize < bd->data_size)
1510 {
1511 GNUNET_break_op (0);
1512 return false;
1513 }
1514 if ( (GNUNET_MAX_MESSAGE_SIZE - msize)
1515 / sizeof(struct GNUNET_DHT_PathElement)
1516 < (get_path_length + ppl) )
1517 {
1518 get_path_length = 0;
1519 ppl = 0;
1520 }
1521 if ( (get_path_length > UINT16_MAX) ||
1522 (ppl > UINT16_MAX) )
1523 {
1524 GNUNET_break (0);
1525 get_path_length = 0;
1526 ppl = 0;
1527 }
1528 msize += (get_path_length + ppl)
1529 * sizeof(struct GNUNET_DHT_PathElement);
1531 "Forwarding reply for key %s to peer %s\n",
1532 GNUNET_h2s (query_hash),
1533 GNUNET_i2s (&pi->id));
1535 "# RESULT messages queued for transmission",
1536 1,
1537 GNUNET_NO);
1538 {
1539 struct PeerResultMessage *prm;
1540 char buf[msize] GNUNET_ALIGN;
1541 void *data;
1542
1543 prm = (struct PeerResultMessage *) buf;
1545 prm->header.size = htons (sizeof (buf));
1546 prm->type = htonl ((uint32_t) bd->type);
1547 prm->reserved = htons (0);
1548 prm->options = htons ((uint16_t) ro);
1549 prm->put_path_length = htons ((uint16_t) ppl);
1550 prm->get_path_length = htons ((uint16_t) get_path_length);
1552 prm->key = *query_hash;
1553 if (truncated)
1554 {
1555 void *tgt = &prm[1];
1556
1557 GNUNET_memcpy (tgt,
1558 trunc_peer,
1559 sizeof (struct GNUNET_PeerIdentity));
1560 paths = (struct GNUNET_DHT_PathElement *)
1561 (tgt + sizeof (struct GNUNET_PeerIdentity));
1562 }
1563 else
1564 {
1565 paths = (struct GNUNET_DHT_PathElement *) &prm[1];
1566 }
1567 if (NULL != put_path)
1568 {
1569 GNUNET_memcpy (paths,
1570 put_path,
1571 ppl * sizeof(struct GNUNET_DHT_PathElement));
1572 }
1573 else
1574 {
1575 GNUNET_assert (0 == ppl);
1576 }
1577 if (NULL != get_path)
1578 {
1579 GNUNET_memcpy (&paths[ppl],
1580 get_path,
1581 get_path_length * sizeof(struct GNUNET_DHT_PathElement));
1582 }
1583 else
1584 {
1585 GNUNET_assert (0 == get_path_length);
1586 }
1587 if (tracking)
1588 {
1590 void *tgt = &paths[get_path_length + ppl];
1591 const struct GNUNET_PeerIdentity *pred;
1592
1593 if (ppl + get_path_length > 0)
1594 pred = &paths[ppl + get_path_length - 1].pred;
1595 else if (truncated)
1596 pred = trunc_peer;
1597 else
1598 pred = NULL; /* we are first! */
1599 /* Note that the last signature in 'paths' was not initialized before,
1600 so this is crucial to avoid sending garbage. */
1602 bd->data_size,
1604 bd->expiration_time,
1605 pred,
1606 &pi->id,
1607 &sig);
1608 memcpy (tgt,
1609 &sig,
1610 sizeof (sig));
1611 data = tgt + sizeof (sig);
1613 "Signing GET PATH %u/%u of %s => %s\n",
1614 ppl,
1615 get_path_length,
1616 GNUNET_h2s (query_hash),
1617 GNUNET_B2S (&sig));
1618#if SANITY_CHECKS > 1
1619 {
1620 struct GNUNET_DHT_PathElement xpaths[get_path_length + 1];
1621
1622 memcpy (xpaths,
1623 &paths[ppl],
1624 get_path_length * sizeof (struct GNUNET_DHT_PathElement));
1625 xpaths[get_path_length].sig = sig;
1626 xpaths[get_path_length].pred = GDS_my_identity;
1627 if (0 !=
1629 bd->data_size,
1630 bd->expiration_time,
1631 trunc_peer,
1632 paths,
1633 ppl,
1634 xpaths,
1635 get_path_length + 1,
1636 &pi->id))
1637 {
1638 GNUNET_break (0);
1639 return false;
1640 }
1641 }
1642#endif
1643 }
1644 else
1645 {
1646 data = &prm[1];
1647 }
1649 bd->data,
1650 bd->data_size);
1651 do_send (pi,
1652 &prm->header);
1653 }
1654 return true;
1655}
void GDS_helper_sign_path(const void *data, size_t data_size, const struct GNUNET_CRYPTO_EddsaPrivateKey *sk, struct GNUNET_TIME_Absolute exp_time, const struct GNUNET_PeerIdentity *pred, const struct GNUNET_PeerIdentity *succ, struct GNUNET_CRYPTO_EddsaSignature *sig)
Sign that we are routing a message from pred to succ.
Definition: dht_helper.c:145
static char * data
The data to insert into the dht.
static size_t data_size
Number of bytes in data.
unsigned int GNUNET_DHT_verify_path(const void *data, size_t data_size, struct GNUNET_TIME_Absolute exp_time, const struct GNUNET_PeerIdentity *trunc_peer, const struct GNUNET_DHT_PathElement *put_path, unsigned int put_path_len, const struct GNUNET_DHT_PathElement *get_path, unsigned int get_path_len, const struct GNUNET_PeerIdentity *me)
Verify signatures on a path consisting of put_path and get_path in reverse order (starting at the las...
Definition: dht_api.c:1351
#define GNUNET_B2S(obj)
Convert a fixed-sized object to a string using GNUNET_b2s().
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
#define GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT
Data is returned to peer from DHT.
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:638
an ECC signature using EdDSA.
struct GNUNET_PeerIdentity pred
Previous peer on the path (matches "pred" in the signed field).
struct GNUNET_CRYPTO_EddsaSignature sig
Signature affirming the hop of type GNUNET_SIGNATURE_PURPOSE_DHT_HOP.
uint16_t get_path_length
Length of the GET path that follows (if tracked).
uint16_t options
Message options, actually an 'enum GNUNET_DHT_RouteOption' value in NBO.
struct GNUNET_HashCode key
The key of the corresponding GET request.
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT.
uint16_t put_path_length
Length of the PUT path that follows (if tracked).
struct GNUNET_TIME_AbsoluteNBO expiration_time
When does the content expire?

References data, GNUNET_DATACACHE_Block::data, data_size, GNUNET_DATACACHE_Block::data_size, do_send(), GNUNET_DATACACHE_Block::expiration_time, PeerResultMessage::expiration_time, GDS_helper_sign_path(), GDS_my_identity, GDS_my_private_key, GDS_stats, PeerResultMessage::get_path_length, GNUNET_ALIGN, GNUNET_assert, GNUNET_B2S, GNUNET_break, GNUNET_break_op, GNUNET_DHT_RO_RECORD_ROUTE, GNUNET_DHT_RO_TRUNCATED, GNUNET_DHT_verify_path(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_i2s(), GNUNET_log, GNUNET_MAX_MESSAGE_SIZE, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT, GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_TIME_absolute_hton(), PeerResultMessage::header, PeerInfo::id, PeerResultMessage::key, PeerResultMessage::options, GNUNET_DHT_PathElement::pred, GNUNET_DATACACHE_Block::put_path, GNUNET_DATACACHE_Block::put_path_length, PeerResultMessage::put_path_length, PeerResultMessage::reserved, GNUNET_DATACACHE_Block::ro, GNUNET_DHT_PathElement::sig, GNUNET_MessageHeader::size, GNUNET_DATACACHE_Block::trunc_peer, GNUNET_MessageHeader::type, GNUNET_DATACACHE_Block::type, and PeerResultMessage::type.

Referenced by handle_find_local_hello(), handle_find_my_hello(), handle_local_result(), and process().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_dht_p2p_put()

static enum GNUNET_GenericReturnValue check_dht_p2p_put ( void *  cls,
const struct PeerPutMessage put 
)
static

Check validity of a p2p put request.

Parameters
clsclosure with the struct PeerInfo of the sender
putmessage
Returns
GNUNET_OK if the message is valid

Definition at line 1666 of file gnunet-service-dht_neighbours.c.

1668{
1670 = (enum GNUNET_DHT_RouteOption) ntohs (put->options);
1671 bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
1672 bool has_path = (0 != (ro & GNUNET_DHT_RO_RECORD_ROUTE));
1673 uint16_t msize = ntohs (put->header.size);
1674 uint16_t putlen = ntohs (put->put_path_length);
1675 size_t xsize = (has_path
1676 ? sizeof (struct GNUNET_CRYPTO_EddsaSignature)
1677 : 0)
1678 + (truncated
1679 ? sizeof (struct GNUNET_PeerIdentity)
1680 : 0);
1681 size_t var_meta_size
1682 = putlen * sizeof(struct GNUNET_DHT_PathElement)
1683 + xsize;
1684
1685 (void) cls;
1686 if ( (msize <
1687 sizeof (struct PeerPutMessage) + var_meta_size) ||
1688 (putlen >
1689 (GNUNET_MAX_MESSAGE_SIZE
1690 - sizeof (struct PeerPutMessage)
1691 - xsize)
1692 / sizeof(struct GNUNET_DHT_PathElement)) )
1693 {
1694 GNUNET_break_op (0);
1695 return GNUNET_SYSERR;
1696 }
1697 if (GNUNET_BLOCK_TYPE_ANY == htonl (put->type))
1698 {
1699 GNUNET_break_op (0);
1700 return GNUNET_SYSERR;
1701 }
1702 return GNUNET_OK;
1703}
@ GNUNET_SYSERR
@ GNUNET_BLOCK_TYPE_ANY
Identifier for any block.
uint32_t type
Content type, must not be zero.
Definition: dht.h:438
uint16_t options
Processing options.
Definition: dht.h:443

References GNUNET_BLOCK_TYPE_ANY, GNUNET_break_op, GNUNET_DHT_RO_RECORD_ROUTE, GNUNET_DHT_RO_TRUNCATED, GNUNET_OK, GNUNET_SYSERR, PeerPutMessage::header, PeerPutMessage::options, PeerPutMessage::put_path_length, GNUNET_MessageHeader::size, and PeerPutMessage::type.

◆ handle_dht_p2p_put()

static void handle_dht_p2p_put ( void *  cls,
const struct PeerPutMessage put 
)
static

Core handler for p2p put requests.

Parameters
clsclosure with the struct Target of the sender
putmessage

Definition at line 1713 of file gnunet-service-dht_neighbours.c.

1715{
1716 struct Target *t = cls;
1717 struct PeerInfo *peer = t->pi;
1719 = (enum GNUNET_DHT_RouteOption) ntohs (put->options);
1720 bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
1721 bool has_path = (0 != (ro & GNUNET_DHT_RO_RECORD_ROUTE));
1722 uint16_t msize = ntohs (put->header.size);
1723 uint16_t putlen = ntohs (put->put_path_length);
1724 const struct GNUNET_PeerIdentity *trunc_peer
1725 = truncated
1726 ? (const struct GNUNET_PeerIdentity *) &put[1]
1727 : NULL;
1728 const struct GNUNET_DHT_PathElement *put_path
1729 = truncated
1730 ? (const struct GNUNET_DHT_PathElement *) &trunc_peer[1]
1731 : (const struct GNUNET_DHT_PathElement *) &put[1];
1732 const struct GNUNET_CRYPTO_EddsaSignature *last_sig
1733 = has_path
1734 ? (const struct GNUNET_CRYPTO_EddsaSignature *) &put_path[putlen]
1735 : NULL;
1736 const char *data
1737 = has_path
1738 ? (const char *) &last_sig[1]
1739 : (const char *) &put_path[putlen];
1740 size_t var_meta_size
1741 = putlen * sizeof(struct GNUNET_DHT_PathElement)
1742 + (has_path ? sizeof (*last_sig) : 0)
1743 + (truncated ? sizeof (*trunc_peer) : 0);
1744 struct GNUNET_DATACACHE_Block bd = {
1745 .key = put->key,
1746 .expiration_time = GNUNET_TIME_absolute_ntoh (put->expiration_time),
1747 .type = ntohl (put->type),
1748 .ro = ro,
1749 .data_size = msize - sizeof(*put) - var_meta_size,
1750 .data = data
1751 };
1752
1753 if (NULL != trunc_peer)
1754 bd.trunc_peer = *trunc_peer;
1756 "PUT for `%s' from %s with RO (%s/%s)\n",
1757 GNUNET_h2s (&put->key),
1758 GNUNET_i2s (&peer->id),
1759 (bd.ro & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE) ? "x" : "-",
1760 has_path ? "R" : "-");
1762 {
1764 "# Expired PUTs discarded",
1765 1,
1766 GNUNET_NO);
1767 return;
1768 }
1769 {
1770 /* Only call 'check_block' if that keeps our CPU load (from
1771 the cryptography) below 50% on average */
1772 static struct GNUNET_TIME_Relative avg_latency;
1773 static struct GNUNET_TIME_Absolute next_time;
1774
1775 if (GNUNET_TIME_absolute_is_past (next_time))
1776 {
1777 struct GNUNET_TIME_Absolute now
1779 struct GNUNET_TIME_Relative latency;
1781
1782 if (GNUNET_NO ==
1784 bd.type,
1785 bd.data,
1786 bd.data_size))
1787 {
1788 GNUNET_break_op (0);
1789 return;
1790 }
1791 latency = GNUNET_TIME_absolute_get_duration (now);
1792 /* Use *moving average* to estimate check_block latency */
1793 avg_latency
1796 GNUNET_TIME_relative_multiply (avg_latency,
1797 7),
1798 latency),
1799 8);
1800 /* average delay = 50% of avg_latency => 50% CPU load from crypto (at most) */
1803 avg_latency.rel_value_us > 0
1804 ? avg_latency.rel_value_us
1805 : 1LLU);
1807 }
1808 }
1809 if (! has_path)
1810 putlen = 0;
1812 "# P2P PUT requests received",
1813 1,
1814 GNUNET_NO);
1816 "# P2P PUT bytes received",
1817 msize,
1818 GNUNET_NO);
1819 {
1820 struct GNUNET_HashCode test_key;
1822
1824 bd.type,
1825 bd.data,
1826 bd.data_size,
1827 &test_key);
1828 switch (ret)
1829 {
1830 case GNUNET_YES:
1831 if (0 != GNUNET_memcmp (&test_key,
1832 &bd.key))
1833 {
1834 GNUNET_break_op (0);
1835 return;
1836 }
1837 break;
1838 case GNUNET_NO:
1839 /* cannot verify, good luck */
1840 break;
1841 case GNUNET_SYSERR:
1842 /* block type not supported, good luck */
1843 break;
1844 }
1845 }
1846
1847 {
1849 struct GNUNET_DHT_PathElement pp[putlen + 1];
1850
1856 &peer->phash));
1857 /* extend 'put path' by sender */
1858 bd.put_path = pp;
1859 bd.put_path_length = putlen + 1;
1860 if (has_path)
1861 {
1862 unsigned int failure_offset;
1863
1864 GNUNET_memcpy (pp,
1865 put_path,
1866 putlen * sizeof(struct GNUNET_DHT_PathElement));
1867 pp[putlen].pred = peer->id;
1868 pp[putlen].sig = *last_sig;
1869#if SANITY_CHECKS
1870 /* TODO: might want to eventually implement probabilistic
1871 load-based path verification, but for now it is all or nothing */
1872 failure_offset
1874 bd.data_size,
1875 bd.expiration_time,
1876 trunc_peer,
1877 pp,
1878 putlen + 1,
1879 NULL, 0, /* get_path */
1881#else
1882 failure_offset = 0;
1883#endif
1884 if (0 != failure_offset)
1885 {
1886 GNUNET_break_op (0);
1888 "Recorded put path invalid at offset %u, truncating\n",
1889 failure_offset);
1890 GNUNET_assert (failure_offset <= putlen + 1);
1891 bd.put_path = &pp[failure_offset];
1892 bd.put_path_length = (putlen + 1) - failure_offset;
1894 bd.trunc_peer = pp[failure_offset - 1].pred;
1895 }
1896 }
1897 else
1898 {
1899 bd.put_path_length = 0;
1900 }
1901
1902 /* give to local clients */
1904 &bd.key,
1905 0, NULL /* get path */));
1906
1907 /* store locally */
1908 if ( (0 != (bd.ro & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
1909 (GDS_am_closest_peer (&put->key,
1910 bf)) )
1912 {
1913 enum GNUNET_GenericReturnValue forwarded;
1914
1915 /* route to other peers */
1916 forwarded
1918 ntohs (put->desired_replication_level),
1919 ntohs (put->hop_count),
1920 bf);
1921 /* notify monitoring clients */
1922 bd.ro |= ((GNUNET_OK == forwarded)
1924 : 0);
1926 ntohs (put->hop_count),
1927 ntohs (put->desired_replication_level));
1928 }
1930 }
1931}
void GDS_CLIENTS_process_put(const struct GNUNET_DATACACHE_Block *bd, uint32_t hop_count, uint32_t desired_replication_level)
Check if some client is monitoring PUT messages and notify them in that case.
bool GDS_CLIENTS_handle_reply(const struct GNUNET_DATACACHE_Block *bd, const struct GNUNET_HashCode *query_hash, unsigned int get_path_length, const struct GNUNET_DHT_PathElement *get_path)
Handle a reply we've received from another peer.
void GDS_DATACACHE_handle_put(const struct GNUNET_DATACACHE_Block *bd)
Handle a datum we've received from another peer.
enum GNUNET_GenericReturnValue GDS_NEIGHBOURS_handle_put(const struct GNUNET_DATACACHE_Block *bd, uint16_t desired_replication_level, uint16_t hop_count, struct GNUNET_CONTAINER_BloomFilter *bf)
Perform a PUT operation.
enum GNUNET_GenericReturnValue GDS_am_closest_peer(const struct GNUNET_HashCode *key, const struct GNUNET_CONTAINER_BloomFilter *bloom)
Check whether my identity is closer than any known peers.
enum GNUNET_GenericReturnValue GNUNET_BLOCK_check_block(struct GNUNET_BLOCK_Context *ctx, enum GNUNET_BLOCK_Type type, const void *block, size_t block_size)
Function called to validate a block.
Definition: block.c:319
enum GNUNET_GenericReturnValue GNUNET_BLOCK_get_key(struct GNUNET_BLOCK_Context *ctx, enum GNUNET_BLOCK_Type type, const void *block, size_t block_size, struct GNUNET_HashCode *key)
Function called to obtain the key for a block.
Definition: block.c:276
@ GNUNET_DHT_RO_LAST_HOP
Flag given to monitors if this was the last hop for a GET/PUT.
@ GNUNET_ERROR_TYPE_WARNING
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition: time.c:436
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:737
struct GNUNET_TIME_Relative GNUNET_TIME_relative_add(struct GNUNET_TIME_Relative a1, struct GNUNET_TIME_Relative a2)
Add relative times together.
Definition: time.c:585
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:316
struct GNUNET_TIME_Relative GNUNET_TIME_relative_divide(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Divide relative time by a given factor.
Definition: time.c:550
bool GNUNET_TIME_absolute_is_past(struct GNUNET_TIME_Absolute abs)
Test if abs is truly in the past (excluding now).
Definition: time.c:669
Information about a block stored in the datacache.
Time for absolute times used by GNUnet, in microseconds.
char bloomfilter[128]
Bloomfilter (for peer identities) to stop circular routes.
Definition: dht.h:468
struct GNUNET_HashCode key
The key we are storing under.
Definition: dht.h:473
struct GNUNET_TIME_AbsoluteNBO expiration_time
When does the content expire?
Definition: dht.h:463

References PeerPutMessage::bloomfilter, data, GNUNET_DATACACHE_Block::data, GNUNET_DATACACHE_Block::data_size, delta, PeerPutMessage::desired_replication_level, DHT_BLOOM_SIZE, GNUNET_DATACACHE_Block::expiration_time, PeerPutMessage::expiration_time, GDS_am_closest_peer(), GDS_block_context, GDS_CLIENTS_handle_reply(), GDS_CLIENTS_process_put(), GDS_DATACACHE_handle_put(), GDS_my_identity, GDS_NEIGHBOURS_handle_put(), GDS_stats, GNUNET_assert, GNUNET_BLOCK_check_block(), GNUNET_BLOCK_get_key(), GNUNET_break, GNUNET_break_op, GNUNET_CONSTANTS_BLOOMFILTER_K, GNUNET_CONTAINER_bloomfilter_free(), GNUNET_CONTAINER_bloomfilter_init(), GNUNET_CONTAINER_bloomfilter_test(), GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_u64(), GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, GNUNET_DHT_RO_LAST_HOP, GNUNET_DHT_RO_RECORD_ROUTE, GNUNET_DHT_RO_TRUNCATED, GNUNET_DHT_verify_path(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_h2s(), GNUNET_i2s(), GNUNET_log, GNUNET_memcmp, GNUNET_memcpy, GNUNET_NO, GNUNET_OK, GNUNET_STATISTICS_update(), GNUNET_SYSERR, GNUNET_TIME_absolute_get(), GNUNET_TIME_absolute_get_duration(), GNUNET_TIME_absolute_is_past(), GNUNET_TIME_absolute_ntoh(), GNUNET_TIME_relative_add(), GNUNET_TIME_relative_divide(), GNUNET_TIME_relative_multiply(), GNUNET_TIME_relative_to_absolute(), GNUNET_YES, PeerPutMessage::header, PeerPutMessage::hop_count, PeerInfo::id, GNUNET_DATACACHE_Block::key, PeerPutMessage::key, PeerPutMessage::options, PeerInfo::phash, GNUNET_DHT_PathElement::pred, GNUNET_DATACACHE_Block::put_path, GNUNET_DATACACHE_Block::put_path_length, PeerPutMessage::put_path_length, GNUNET_TIME_Relative::rel_value_us, ret, GNUNET_DATACACHE_Block::ro, GNUNET_DHT_PathElement::sig, GNUNET_MessageHeader::size, t, GNUNET_DATACACHE_Block::trunc_peer, GNUNET_DATACACHE_Block::type, and PeerPutMessage::type.

Here is the call graph for this function:

◆ handle_find_my_hello()

static void handle_find_my_hello ( struct PeerInfo pi,
const struct GNUNET_HashCode query_hash,
struct GNUNET_BLOCK_Group bg 
)
static

We have received a request for a HELLO.

Sends our HELLO back.

Parameters
pisender of the request
keypeers close to this key are desired
bggroup for filtering peers

Definition at line 1943 of file gnunet-service-dht_neighbours.c.

1946{
1947 size_t block_size = 0;
1948
1949 /* TODO: consider caching our HELLO block for a bit, to
1950 avoid signing too often here... */
1954 NULL,
1955 &block_size,
1957 {
1958 char block[block_size];
1959
1960 if (GNUNET_OK !=
1963 block,
1964 &block_size,
1966 {
1968 "# FIND PEER requests ignored due to lack of HELLO",
1969 1,
1970 GNUNET_NO);
1971 }
1972 else if (GNUNET_BLOCK_REPLY_OK_MORE ==
1975 bg,
1977 NULL, 0,
1978 block,
1979 block_size))
1980 {
1981 struct GNUNET_DATACACHE_Block bd = {
1983 .expiration_time
1986 .key = GDS_my_identity_hash,
1987 .data = block,
1988 .data_size = block_size
1989 };
1990
1992 &bd,
1993 query_hash,
1994 0, NULL /* get path */));
1995 }
1996 else
1997 {
1999 "# FIND PEER requests ignored due to Bloomfilter",
2000 1,
2001 GNUNET_NO);
2002 }
2003 }
2004}
struct GNUNET_HELLO_Builder * GDS_my_hello
Our HELLO.
bool GDS_NEIGHBOURS_handle_reply(struct PeerInfo *pi, const struct GNUNET_DATACACHE_Block *bd, const struct GNUNET_HashCode *query_hash, unsigned int get_path_length, const struct GNUNET_DHT_PathElement *get_path)
Handle a reply (route to origin).
enum GNUNET_BLOCK_ReplyEvaluationResult GNUNET_BLOCK_check_reply(struct GNUNET_BLOCK_Context *ctx, enum GNUNET_BLOCK_Type type, struct GNUNET_BLOCK_Group *group, const struct GNUNET_HashCode *query, const void *xquery, size_t xquery_size, const void *reply_block, size_t reply_block_size)
Function called to validate if a reply is good for a particular query.
Definition: block.c:337
@ GNUNET_BLOCK_REPLY_OK_MORE
Valid result, and there may be more.
enum GNUNET_GenericReturnValue GNUNET_HELLO_builder_to_block(const struct GNUNET_HELLO_Builder *builder, const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, void *block, size_t *block_size, struct GNUNET_TIME_Relative expiration_time)
Generate DHT block from a builder.
Definition: hello-uri.c:782
#define GNUNET_HELLO_ADDRESS_EXPIRATION
For how long are HELLO signatures valid?
#define GNUNET_TIME_UNIT_ZERO
Relative time zero.

References GDS_block_context, GDS_my_hello, GDS_my_identity_hash, GDS_my_private_key, GDS_NEIGHBOURS_handle_reply(), GDS_stats, GNUNET_BLOCK_check_reply(), GNUNET_BLOCK_REPLY_OK_MORE, GNUNET_BLOCK_TYPE_DHT_HELLO, GNUNET_break, GNUNET_HELLO_ADDRESS_EXPIRATION, GNUNET_HELLO_builder_to_block(), GNUNET_NO, GNUNET_OK, GNUNET_STATISTICS_update(), GNUNET_TIME_relative_to_absolute(), GNUNET_TIME_UNIT_ZERO, and GNUNET_DATACACHE_Block::type.

Referenced by handle_dht_p2p_get().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_find_local_hello()

static void handle_find_local_hello ( struct PeerInfo pi,
const struct GNUNET_HashCode query_hash,
struct GNUNET_BLOCK_Group bg 
)
static

We have received a request for nearby HELLOs.

Sends matching HELLOs back.

Parameters
pisender of the request
keypeers close to this key are desired
bggroup for filtering peers

Definition at line 2016 of file gnunet-service-dht_neighbours.c.

2019{
2020 /* Force non-random selection by hop count */
2021 struct PeerInfo *peer;
2022
2023 peer = select_peer (query_hash,
2024 NULL,
2025 GDS_NSE_get () + 1);
2026 if ( (NULL != peer->hello) &&
2032 bg,
2033 &peer->phash,
2034 NULL, 0, /* xquery */
2035 peer->hello,
2036 peer->hello_size)) )
2037 {
2038 struct GNUNET_DATACACHE_Block bd = {
2040 .expiration_time = peer->hello_expiration,
2041 .key = peer->phash,
2042 .data = peer->hello,
2043 .data_size = peer->hello_size
2044 };
2045
2047 &bd,
2048 query_hash,
2049 0, NULL /* get path */));
2050 }
2051}
struct GNUNET_TIME_Absolute hello_expiration
When does our HELLO from this peer expire?
size_t hello_size
Number of bytes in hello.

References GDS_block_context, GDS_NEIGHBOURS_handle_reply(), GDS_NSE_get(), GNUNET_BLOCK_check_reply(), GNUNET_BLOCK_REPLY_OK_MORE, GNUNET_BLOCK_TYPE_DHT_HELLO, GNUNET_break, GNUNET_TIME_absolute_is_past(), PeerInfo::hello, PeerInfo::hello_expiration, PeerInfo::hello_size, PeerInfo::phash, select_peer(), and GNUNET_DATACACHE_Block::type.

Referenced by handle_dht_p2p_get().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_local_result()

static void handle_local_result ( void *  cls,
const struct GNUNET_DATACACHE_Block bd 
)
static

Handle an exact result from local datacache for a GET operation.

Parameters
clsthe struct PeerInfo for which this is a reply
bddetails about the block we found locally

Definition at line 2061 of file gnunet-service-dht_neighbours.c.

2063{
2064 struct PeerInfo *peer = cls;
2065
2067 bd,
2068 &bd->key,
2069 0, NULL /* get path */));
2070}

References GDS_NEIGHBOURS_handle_reply(), GNUNET_break, and GNUNET_DATACACHE_Block::key.

Referenced by handle_dht_p2p_get().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_dht_p2p_get()

static enum GNUNET_GenericReturnValue check_dht_p2p_get ( void *  cls,
const struct PeerGetMessage get 
)
static

Check validity of p2p get request.

Parameters
clsclosure with the struct Target of the sender
getthe message
Returns
GNUNET_OK if the message is well-formed

Definition at line 2081 of file gnunet-service-dht_neighbours.c.

2083{
2084 uint16_t msize = ntohs (get->header.size);
2085 uint16_t result_filter_size = ntohs (get->result_filter_size);
2086
2087 (void) cls;
2088 if (msize < sizeof(*get) + result_filter_size)
2089 {
2090 GNUNET_break_op (0);
2091 return GNUNET_SYSERR;
2092 }
2093 return GNUNET_OK;
2094}
static int get
Get DID Documement for DID Flag.
Definition: gnunet-did.c:63

References get, GNUNET_break_op, GNUNET_OK, and GNUNET_SYSERR.

◆ handle_dht_p2p_get()

static void handle_dht_p2p_get ( void *  cls,
const struct PeerGetMessage get 
)
static

Core handler for p2p get requests.

Parameters
clsclosure with the struct Target of the sender
getthe message

Definition at line 2104 of file gnunet-service-dht_neighbours.c.

2106{
2107 struct Target *t = cls;
2108 struct PeerInfo *peer = t->pi;
2109 uint16_t msize = ntohs (get->header.size);
2110 uint16_t result_filter_size = ntohs (get->result_filter_size);
2111 uint16_t hop_count = ntohs (get->hop_count);
2112 enum GNUNET_BLOCK_Type type = (enum GNUNET_BLOCK_Type) ntohl (get->type);
2114 get->options);
2116 const void *result_filter = (const void *) &get[1];
2117 const void *xquery = result_filter + result_filter_size;
2118 size_t xquery_size = msize - sizeof (*get) - result_filter_size;
2119
2120 /* parse and validate message */
2122 "# P2P GET requests received",
2123 1,
2124 GNUNET_NO);
2126 "# P2P GET bytes received",
2127 msize,
2128 GNUNET_NO);
2129 if (GNUNET_NO ==
2131 type,
2132 &get->key,
2133 xquery,
2134 xquery_size))
2135 {
2136 /* request invalid */
2137 GNUNET_break_op (0);
2138 return;
2139 }
2140
2141 {
2142 struct GNUNET_BLOCK_Group *bg;
2143 struct GNUNET_CONTAINER_BloomFilter *peer_bf;
2144
2145 peer_bf = GNUNET_CONTAINER_bloomfilter_init (get->bloomfilter,
2148 ;
2151 &peer->phash));
2153 type,
2154 result_filter,
2155 result_filter_size,
2156 "filter-size",
2157 result_filter_size,
2158 NULL);
2160 "GET for %s at %s after %u hops\n",
2161 GNUNET_h2s (&get->key),
2163 (unsigned int) hop_count);
2164 /* local lookup (this may update the bg) */
2166 (GDS_am_closest_peer (&get->key,
2167 peer_bf)) )
2168 {
2171 {
2173 "# P2P HELLO lookup requests processed",
2174 1,
2175 GNUNET_NO);
2177 &get->key,
2178 bg);
2181 &get->key,
2182 bg);
2183 }
2185 {
2187 eval = GDS_DATACACHE_get_closest (&get->key,
2188 type,
2189 xquery,
2190 xquery_size,
2191 bg,
2193 peer);
2194 else
2195 eval = GDS_DATACACHE_handle_get (&get->key,
2196 type,
2197 xquery,
2198 xquery_size,
2199 bg,
2201 peer);
2202 }
2203 }
2204 else
2205 {
2207 "# P2P GET requests ONLY routed",
2208 1,
2209 GNUNET_NO);
2210 }
2211
2212 /* remember request for routing replies
2213 TODO: why should we do this if GNUNET_BLOCK_REPLY_OK_LAST == eval?
2214 */
2215 GDS_ROUTING_add (&peer->id,
2216 type,
2217 bg, /* bg now owned by routing, but valid at least until end of this function! */
2218 options,
2219 &get->key,
2220 xquery,
2221 xquery_size);
2222
2223 /* P2P forwarding */
2224 {
2225 bool forwarded = false;
2226 uint16_t desired_replication_level = ntohs (
2227 get->desired_replication_level);
2228
2229 if (eval != GNUNET_BLOCK_REPLY_OK_LAST)
2230 forwarded = (GNUNET_OK ==
2232 options,
2233 desired_replication_level,
2234 hop_count,
2235 &get->key,
2236 xquery,
2237 xquery_size,
2238 bg,
2239 peer_bf));
2241 options
2242 | (forwarded
2243 ? 0
2245 type,
2246 hop_count,
2247 desired_replication_level,
2248 &get->key);
2249 }
2250 /* clean up; note that 'bg' is owned by routing now! */
2252 }
2253}
void GDS_CLIENTS_process_get(enum GNUNET_DHT_RouteOption options, enum GNUNET_BLOCK_Type type, uint32_t hop_count, uint32_t desired_replication_level, const struct GNUNET_HashCode *key)
Check if some client is monitoring GET messages and notify them in that case.
enum GNUNET_BLOCK_ReplyEvaluationResult GDS_DATACACHE_get_closest(const struct GNUNET_HashCode *key, enum GNUNET_BLOCK_Type type, const void *xquery, size_t xquery_size, struct GNUNET_BLOCK_Group *bg, GDS_DATACACHE_GetCallback cb, void *cb_cls)
Handle a request for data close to a key that we have received from another peer.
enum GNUNET_BLOCK_ReplyEvaluationResult GDS_DATACACHE_handle_get(const struct GNUNET_HashCode *key, enum GNUNET_BLOCK_Type type, const void *xquery, size_t xquery_size, struct GNUNET_BLOCK_Group *bg, GDS_DATACACHE_GetCallback gc, void *gc_cls)
Handle a GET request we've received from another peer.
static void handle_find_local_hello(struct PeerInfo *pi, const struct GNUNET_HashCode *query_hash, struct GNUNET_BLOCK_Group *bg)
We have received a request for nearby HELLOs.
static void handle_local_result(void *cls, const struct GNUNET_DATACACHE_Block *bd)
Handle an exact result from local datacache for a GET operation.
static void handle_find_my_hello(struct PeerInfo *pi, const struct GNUNET_HashCode *query_hash, struct GNUNET_BLOCK_Group *bg)
We have received a request for a HELLO.
void GDS_ROUTING_add(const struct GNUNET_PeerIdentity *sender, enum GNUNET_BLOCK_Type type, struct GNUNET_BLOCK_Group *bg, enum GNUNET_DHT_RouteOption options, const struct GNUNET_HashCode *key, const void *xquery, size_t xquery_size)
Add a new entry to our routing table.
enum GNUNET_GenericReturnValue GNUNET_BLOCK_check_query(struct GNUNET_BLOCK_Context *ctx, enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode *query, const void *xquery, size_t xquery_size)
Function called to validate a request.
Definition: block.c:296
GNUNET_BLOCK_ReplyEvaluationResult
Possible ways for how a block may relate to a query.
@ GNUNET_BLOCK_REPLY_OK_LAST
Last possible valid result.
GNUNET_BLOCK_Type
WARNING: This header is generated! In order to add DHT block types, you must register them in GANA,...

References DHT_BLOOM_SIZE, GDS_am_closest_peer(), GDS_block_context, GDS_CLIENTS_process_get(), GDS_DATACACHE_get_closest(), GDS_DATACACHE_handle_get(), GDS_my_identity, GDS_NEIGHBOURS_handle_get(), GDS_ROUTING_add(), GDS_stats, get, GNUNET_BLOCK_check_query(), GNUNET_BLOCK_group_create(), GNUNET_BLOCK_REPLY_OK_LAST, GNUNET_BLOCK_REPLY_OK_MORE, GNUNET_BLOCK_TYPE_ANY, GNUNET_BLOCK_TYPE_DHT_HELLO, GNUNET_break_op, GNUNET_CONSTANTS_BLOOMFILTER_K, GNUNET_CONTAINER_bloomfilter_free(), GNUNET_CONTAINER_bloomfilter_init(), GNUNET_CONTAINER_bloomfilter_test(), GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, GNUNET_DHT_RO_FIND_APPROXIMATE, GNUNET_DHT_RO_LAST_HOP, GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_STATISTICS_update(), GNUNET_YES, handle_find_local_hello(), handle_find_my_hello(), handle_local_result(), PeerInfo::id, options, PeerInfo::phash, t, and type.

Here is the call graph for this function:

◆ process_reply_with_path()

static bool process_reply_with_path ( const struct GNUNET_DATACACHE_Block bd,
const struct GNUNET_HashCode query_hash,
unsigned int  get_path_length,
const struct GNUNET_DHT_PathElement get_path 
)
static

Process a reply, after the get_path has been updated.

Parameters
bdblock details
query_hashhash of the original query, might not match key in bd
get_path_lengthnumber of entries in get_path
get_pathpath the reply has taken
Returns
true on success

Definition at line 2266 of file gnunet-service-dht_neighbours.c.

2270{
2271 /* forward to local clients */
2273 "Forwarding reply to local clients\n");
2274 if (! GDS_CLIENTS_handle_reply (bd,
2275 query_hash,
2276 get_path_length,
2277 get_path))
2278 {
2279 GNUNET_break (0);
2280 return false;
2281 }
2283 get_path,
2284 get_path_length);
2286 {
2287 struct GNUNET_DHT_PathElement xput_path[GNUNET_NZL (get_path_length
2288 + bd->put_path_length)];
2289 struct GNUNET_DATACACHE_Block bdx = *bd;
2290
2291 if (NULL != bd->put_path)
2292 GNUNET_memcpy (xput_path,
2293 bd->put_path,
2294 bd->put_path_length * sizeof(struct
2296 GNUNET_memcpy (&xput_path[bd->put_path_length],
2297 get_path,
2298 get_path_length * sizeof(struct GNUNET_DHT_PathElement));
2299 bdx.put_path = xput_path;
2300 bdx.put_path_length += get_path_length;
2302 }
2303 /* forward to other peers */
2305 query_hash,
2306 get_path_length,
2307 get_path);
2308 return true;
2309}
void GDS_CLIENTS_process_get_resp(const struct GNUNET_DATACACHE_Block *bd, const struct GNUNET_DHT_PathElement *get_path, unsigned int get_path_length)
Check if some client is monitoring GET RESP messages and notify them in that case.
static int cache_results
Do we cache all results that we are routing in the local datacache?
void GDS_ROUTING_process(const struct GNUNET_DATACACHE_Block *bd, const struct GNUNET_HashCode *query_hash, unsigned int get_path_length, const struct GNUNET_DHT_PathElement *get_path)
Handle a reply (route to origin).
#define GNUNET_NZL(l)
Macro used to avoid using 0 for the length of a variable-size array (Non-Zero-Length).

References cache_results, GDS_CLIENTS_handle_reply(), GDS_CLIENTS_process_get_resp(), GDS_DATACACHE_handle_put(), GDS_ROUTING_process(), GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_memcpy, GNUNET_NZL, GNUNET_YES, GNUNET_DATACACHE_Block::put_path, and GNUNET_DATACACHE_Block::put_path_length.

Referenced by handle_dht_p2p_result().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_dht_p2p_result()

static enum GNUNET_GenericReturnValue check_dht_p2p_result ( void *  cls,
const struct PeerResultMessage prm 
)
static

Check validity of p2p result message.

Parameters
clsclosure
prmmessage
Returns
GNUNET_YES if the message is well-formed

Definition at line 2320 of file gnunet-service-dht_neighbours.c.

2322{
2323 uint16_t msize = ntohs (prm->header.size) - sizeof (*prm);
2325 = (enum GNUNET_DHT_RouteOption) ntohs (prm->options);
2326 bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
2327 bool tracked = (0 != (ro & GNUNET_DHT_RO_RECORD_ROUTE));
2328
2329 uint16_t get_path_length = ntohs (prm->get_path_length);
2330 uint16_t put_path_length = ntohs (prm->put_path_length);
2331 size_t vsize = (truncated ? sizeof (struct GNUNET_PeerIdentity) : 0)
2332 + (tracked ? sizeof (struct GNUNET_CRYPTO_EddsaSignature) : 0);
2333
2334 (void) cls;
2335 if ( (msize < vsize) ||
2336 (msize - vsize <
2337 (get_path_length + put_path_length)
2338 * sizeof(struct GNUNET_DHT_PathElement)) ||
2339 (get_path_length >
2340 GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_DHT_PathElement)) ||
2341 (put_path_length >
2342 GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_DHT_PathElement)) )
2343 {
2344 GNUNET_break_op (0);
2345 return GNUNET_SYSERR;
2346 }
2347 return GNUNET_OK;
2348}

References PeerResultMessage::get_path_length, GNUNET_break_op, GNUNET_DHT_RO_RECORD_ROUTE, GNUNET_DHT_RO_TRUNCATED, GNUNET_OK, GNUNET_SYSERR, PeerResultMessage::header, PeerResultMessage::options, GNUNET_DATACACHE_Block::put_path_length, PeerResultMessage::put_path_length, GNUNET_DATACACHE_Block::ro, and GNUNET_MessageHeader::size.

◆ handle_dht_p2p_result()

static void handle_dht_p2p_result ( void *  cls,
const struct PeerResultMessage prm 
)
static

Core handler for p2p result messages.

Parameters
clsclosure
prmmessage

Definition at line 2358 of file gnunet-service-dht_neighbours.c.

2360{
2361 struct Target *t = cls;
2362 struct PeerInfo *peer = t->pi;
2363 uint16_t msize = ntohs (prm->header.size) - sizeof (*prm);
2365 = (enum GNUNET_DHT_RouteOption) ntohs (prm->options);
2366 bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
2367 bool tracked = (0 != (ro & GNUNET_DHT_RO_RECORD_ROUTE));
2368 uint16_t get_path_length = ntohs (prm->get_path_length);
2369 uint16_t put_path_length = ntohs (prm->put_path_length);
2370 const struct GNUNET_PeerIdentity *trunc_peer
2371 = truncated
2372 ? (const struct GNUNET_PeerIdentity *) &prm[1]
2373 : NULL;
2374 const struct GNUNET_DHT_PathElement *put_path
2375 = truncated
2376 ? (const struct GNUNET_DHT_PathElement *) &trunc_peer[1]
2377 : (const struct GNUNET_DHT_PathElement *) &prm[1];
2378 const struct GNUNET_DHT_PathElement *get_path
2379 = &put_path[put_path_length];
2380 const struct GNUNET_CRYPTO_EddsaSignature *last_sig
2381 = tracked
2382 ? (const struct GNUNET_CRYPTO_EddsaSignature *) &get_path[get_path_length]
2383 : NULL;
2384 const void *data
2385 = tracked
2386 ? (const void *) &last_sig[1]
2387 : (const void *) &get_path[get_path_length];
2388 size_t vsize = (truncated ? sizeof (struct GNUNET_PeerIdentity) : 0)
2389 + (tracked ? sizeof (struct GNUNET_CRYPTO_EddsaSignature) : 0);
2390 struct GNUNET_DATACACHE_Block bd = {
2392 .put_path = put_path,
2393 .put_path_length = put_path_length,
2394 .key = prm->key,
2395 .type = ntohl (prm->type),
2396 .ro = ro,
2397 .data = data,
2398 .data_size = msize - vsize - (get_path_length + put_path_length)
2399 * sizeof(struct GNUNET_DHT_PathElement)
2400 };
2401
2402 /* parse and validate message */
2403 if (GNUNET_TIME_absolute_is_past (bd.expiration_time))
2404 {
2406 "# Expired results discarded",
2407 1,
2408 GNUNET_NO);
2409 return;
2410 }
2411 if (GNUNET_OK !=
2413 bd.type,
2414 bd.data,
2415 bd.data_size))
2416 {
2417 GNUNET_break_op (0);
2418 return;
2419 }
2421 "# P2P RESULTS received",
2422 1,
2423 GNUNET_NO);
2425 "# P2P RESULT bytes received",
2426 msize,
2427 GNUNET_NO);
2428 {
2430
2432 bd.type,
2433 bd.data,
2434 bd.data_size,
2435 &bd.key);
2436 if (GNUNET_NO == ret)
2437 bd.key = prm->key;
2438 }
2439
2440 /* if we got a HELLO, consider it for our own routing table */
2441 hello_check (&bd);
2442
2443 /* Need to append 'peer' to 'get_path' */
2444 if (tracked)
2445 {
2446 struct GNUNET_DHT_PathElement xget_path[get_path_length + 1];
2447 struct GNUNET_DHT_PathElement *gp = xget_path;
2448 unsigned int failure_offset;
2449
2450 GNUNET_memcpy (xget_path,
2451 get_path,
2452 get_path_length * sizeof(struct GNUNET_DHT_PathElement));
2453 xget_path[get_path_length].pred = peer->id;
2454 /* use memcpy(), as last_sig may not be aligned */
2455 memcpy (&xget_path[get_path_length].sig,
2456 last_sig,
2457 sizeof (*last_sig));
2458#if SANITY_CHECKS
2459 /* TODO: might want to eventually implement probabilistic
2460 load-based path verification, but for now it is all or nothing */
2461 failure_offset
2462 = GNUNET_DHT_verify_path (bd.data,
2463 bd.data_size,
2464 bd.expiration_time,
2465 trunc_peer,
2466 put_path,
2467 put_path_length,
2468 gp,
2469 get_path_length + 1,
2471#else
2472 failure_offset = 0;
2473#endif
2474 if (0 != failure_offset)
2475 {
2477 "Recorded path invalid at offset %u, truncating\n",
2478 failure_offset);
2479 GNUNET_assert (failure_offset <= bd.put_path_length + get_path_length
2480 + 1);
2481 if (failure_offset < bd.put_path_length)
2482 {
2483 /* failure on put path */
2484 trunc_peer = &bd.put_path[failure_offset - 1].pred;
2485 bd.ro |= GNUNET_DHT_RO_TRUNCATED;
2486 bd.put_path = &bd.put_path[failure_offset];
2487 bd.put_path_length -= failure_offset;
2488 truncated = true;
2489 }
2490 else
2491 {
2492 /* failure on get path */
2493 failure_offset -= bd.put_path_length;
2494 if (0 == failure_offset)
2495 trunc_peer = &bd.put_path[bd.put_path_length - 1].pred;
2496 else
2497 trunc_peer = &gp[failure_offset - 1].pred;
2498 get_path_length -= failure_offset;
2499 gp = &gp[failure_offset];
2500 bd.put_path_length = 0;
2501 bd.put_path = NULL;
2502 bd.ro |= GNUNET_DHT_RO_TRUNCATED;
2503 truncated = true;
2504 }
2505 }
2507 "Extending GET path of length %u with %s\n",
2508 get_path_length,
2509 GNUNET_i2s (&peer->id));
2510 if (truncated)
2511 {
2512 GNUNET_assert (NULL != trunc_peer);
2513 bd.trunc_peer = *trunc_peer;
2514 }
2516 &prm->key,
2517 get_path_length + 1,
2518 gp));
2519 }
2520 else
2521 {
2522 if (truncated)
2523 {
2524 GNUNET_assert (NULL != trunc_peer);
2525 bd.trunc_peer = *trunc_peer;
2526 }
2528 &prm->key,
2529 0,
2530 NULL));
2531 }
2532}
static bool process_reply_with_path(const struct GNUNET_DATACACHE_Block *bd, const struct GNUNET_HashCode *query_hash, unsigned int get_path_length, const struct GNUNET_DHT_PathElement *get_path)
Process a reply, after the get_path has been updated.

References data, GNUNET_DATACACHE_Block::expiration_time, PeerResultMessage::expiration_time, GDS_block_context, GDS_my_identity, GDS_stats, PeerResultMessage::get_path_length, GNUNET_assert, GNUNET_BLOCK_check_block(), GNUNET_BLOCK_get_key(), GNUNET_break, GNUNET_break_op, GNUNET_DHT_RO_RECORD_ROUTE, GNUNET_DHT_RO_TRUNCATED, GNUNET_DHT_verify_path(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_i2s(), GNUNET_log, GNUNET_memcpy, GNUNET_NO, GNUNET_OK, GNUNET_STATISTICS_update(), GNUNET_TIME_absolute_is_past(), GNUNET_TIME_absolute_ntoh(), PeerResultMessage::header, hello_check(), PeerInfo::id, PeerResultMessage::key, PeerResultMessage::options, GNUNET_DHT_PathElement::pred, process_reply_with_path(), PeerResultMessage::put_path_length, ret, GNUNET_DHT_PathElement::sig, GNUNET_MessageHeader::size, t, and PeerResultMessage::type.

Here is the call graph for this function:

◆ check_dht_p2p_hello()

static enum GNUNET_GenericReturnValue check_dht_p2p_hello ( void *  cls,
const struct GNUNET_MessageHeader hello 
)
static

Check validity of a p2p hello message.

Parameters
clsclosure
hellomessage
Returns
GNUNET_YES if the message is well-formed

Definition at line 2543 of file gnunet-service-dht_neighbours.c.

2545{
2546 struct Target *t = cls;
2547 struct PeerInfo *peer = t->pi;
2549 size_t hellob_size;
2550 void *hellob;
2552
2554 &peer->id,
2555 &hellob,
2556 &hellob_size,
2557 &expiration);
2558 GNUNET_free (hellob);
2559 return ret;
2560}
static struct GNUNET_TIME_Relative expiration
User supplied expiration value.
enum GNUNET_GenericReturnValue GNUNET_HELLO_dht_msg_to_block(const struct GNUNET_MessageHeader *hello, const struct GNUNET_PeerIdentity *pid, void **block, size_t *block_size, struct GNUNET_TIME_Absolute *block_expiration)
Convert a DHT hello message to a HELLO block.
Definition: hello-uri.c:931

References expiration, GNUNET_free, GNUNET_HELLO_dht_msg_to_block(), PeerInfo::id, ret, and t.

Here is the call graph for this function:

◆ handle_dht_p2p_hello()

static void handle_dht_p2p_hello ( void *  cls,
const struct GNUNET_MessageHeader hello 
)
static

Core handler for p2p HELLO messages.

Parameters
clsclosure
hellomessage

Definition at line 2570 of file gnunet-service-dht_neighbours.c.

2572{
2573 struct Target *t = cls;
2574 struct PeerInfo *peer = t->pi;
2575
2576 GNUNET_free (peer->hello);
2577 peer->hello_size = 0;
2580 &peer->id,
2581 &peer->hello,
2582 &peer->hello_size,
2583 &peer->hello_expiration));
2584}

References GNUNET_break, GNUNET_free, GNUNET_HELLO_dht_msg_to_block(), GNUNET_OK, PeerInfo::hello, PeerInfo::hello_expiration, PeerInfo::hello_size, PeerInfo::id, and t.

Here is the call graph for this function:

◆ GDS_u_receive()

void GDS_u_receive ( void *  cls,
void **  tctx,
void **  sctx,
const void *  message,
size_t  message_size 
)

Function to call when we receive a message.

Parameters
clsthe closure
[in,out]tctxctx of target address where we received the message from
[in,out]sctxctx of our own source address at which we received the message
messagethe message we received
message_sizenumber of bytes in message

Definition at line 2588 of file gnunet-service-dht_neighbours.c.

2593{
2594 struct Target *t = *tctx;
2595 struct GNUNET_MQ_MessageHandler core_handlers[] = {
2596 GNUNET_MQ_hd_var_size (dht_p2p_get,
2598 struct PeerGetMessage,
2599 t),
2600 GNUNET_MQ_hd_var_size (dht_p2p_put,
2602 struct PeerPutMessage,
2603 t),
2604 GNUNET_MQ_hd_var_size (dht_p2p_result,
2606 struct PeerResultMessage,
2607 t),
2608 GNUNET_MQ_hd_var_size (dht_p2p_hello,
2610 struct GNUNET_MessageHeader,
2611 t),
2613 };
2614 const struct GNUNET_MessageHeader *mh = message;
2615
2616 (void) cls; /* the 'struct GDS_Underlay' */
2617 (void) sctx; /* our receiver address */
2618 if (NULL == t)
2619 {
2620 /* Received message claiming to originate from myself?
2621 Ignore! */
2622 GNUNET_break_op (0);
2623 return;
2624 }
2625 if (message_size < sizeof (*mh))
2626 {
2627 GNUNET_break_op (0);
2628 return;
2629 }
2630 if (message_size != ntohs (mh->size))
2631 {
2632 GNUNET_break_op (0);
2633 return;
2634 }
2636 "Handling message of type %u from peer %s\n",
2637 ntohs (mh->type),
2638 GNUNET_i2s (&t->pi->id));
2639 if (GNUNET_OK !=
2640 GNUNET_MQ_handle_message (core_handlers,
2641 mh))
2642 {
2643 GNUNET_break_op (0);
2644 return;
2645 }
2646}
static struct GNUNET_CADET_Handle * mh
Cadet handle.
Definition: gnunet-cadet.c:92
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
enum GNUNET_GenericReturnValue GNUNET_MQ_handle_message(const struct GNUNET_MQ_MessageHandler *handlers, const struct GNUNET_MessageHeader *mh)
Call the message message handler that was registered for the type of the given message in the given h...
Definition: mq.c:205
#define GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO
HELLO advertising a neighbours addresses.
#define GNUNET_MESSAGE_TYPE_DHT_P2P_PUT
Peer is storing data in DHT.
Message handler for a specific message type.
Header for all communications.

References GNUNET_break_op, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_MESSAGE_TYPE_DHT_P2P_GET, GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO, GNUNET_MESSAGE_TYPE_DHT_P2P_PUT, GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT, GNUNET_MQ_handle_message(), GNUNET_MQ_handler_end, GNUNET_MQ_hd_var_size, GNUNET_OK, mh, and t.

Referenced by load_underlay().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GDS_try_connect()

void GDS_try_connect ( void *  cls,
const struct GNUNET_PeerIdentity pid,
const char *  uri 
)

Callback function used to extract URIs from a builder.

Called when we should consider connecting to a peer.

Parameters
clsclosure pointing to a struct GNUNET_PeerIdentity *
urione of the URIs

Definition at line 2657 of file gnunet-service-dht_neighbours.c.

2660{
2661 (void) cls;
2662 struct GNUNET_HashCode phash;
2663 int peer_bucket;
2664 struct PeerBucket *bucket;
2665
2666 if (0 == GNUNET_memcmp (&GDS_my_identity,
2667 pid))
2668 {
2670 "Got a HELLO for my own PID, ignoring it\n");
2671 return; /* that's us! */
2672 }
2674 sizeof(*pid),
2675 &phash);
2676 peer_bucket = find_bucket (&phash);
2677 GNUNET_assert ( (peer_bucket >= 0) &&
2678 ((unsigned int) peer_bucket < MAX_BUCKETS));
2679 bucket = &k_buckets[peer_bucket];
2680 for (struct PeerInfo *pi = bucket->head;
2681 NULL != pi;
2682 pi = pi->next)
2683 if (0 ==
2684 GNUNET_memcmp (&pi->id,
2685 pid))
2686 {
2687 /* already connected */
2689 uri);
2690 return;
2691 }
2692 if (bucket->peers_size >= bucket_size)
2693 return; /* do not care */
2695 "Discovered peer %s at %s suitable for bucket %d (%u/%u), trying to connect\n",
2696 GNUNET_i2s (pid),
2697 uri,
2698 peer_bucket,
2699 bucket->peers_size,
2700 bucket_size);
2701 /* new peer that we like! */
2703 uri);
2704}
static struct GNUNET_FS_Uri * uri
Value of URI provided on command-line (when not publishing a file but just creating UBlocks to refer ...
void GDS_u_try_connect(const struct GNUNET_PeerIdentity *pid, const char *address)
Ask all underlays to connect to peer pid at address.
@ GNUNET_ERROR_TYPE_INFO

References bucket_size, find_bucket(), GDS_my_identity, GDS_u_try_connect(), GNUNET_assert, GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_i2s(), GNUNET_log, GNUNET_memcmp, PeerBucket::head, k_buckets, MAX_BUCKETS, PeerInfo::next, PeerBucket::peers_size, pid, and uri.

Referenced by handle_dht_local_hello_offer(), and hello_check().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GDS_NEIGHBOURS_broadcast()

void GDS_NEIGHBOURS_broadcast ( const struct GNUNET_MessageHeader msg)

Send msg to all peers in our buckets.

Parameters
msgmessage to broadcast

Definition at line 2713 of file gnunet-service-dht_neighbours.c.

2714{
2715 for (unsigned int bc = 0; bc<closest_bucket; bc++)
2716 {
2717 struct PeerBucket *bucket = &k_buckets[bc];
2718 unsigned int count = 0;
2719
2720 for (struct PeerInfo *pos = bucket->head;
2721 NULL != pos;
2722 pos = pos->next)
2723 {
2724 if (count >= bucket_size)
2725 break; /* we only consider first #bucket_size entries per bucket */
2726 count++;
2727 do_send (pos,
2728 msg);
2729 }
2730 }
2731}

References bucket_size, closest_bucket, do_send(), PeerBucket::head, k_buckets, msg, and PeerInfo::next.

Referenced by broadcast_hello().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GDS_NEIGHBOURS_init()

enum GNUNET_GenericReturnValue GDS_NEIGHBOURS_init ( void  )

Initialize neighbours subsystem.

Returns
GNUNET_OK on success, GNUNET_SYSERR on error

Definition at line 2735 of file gnunet-service-dht_neighbours.c.

2736{
2737
2738 unsigned long long temp_config_num;
2739
2742 "DHT",
2743 "DISABLE_TRY_CONNECT");
2744 if (GNUNET_OK ==
2746 "DHT",
2747 "bucket_size",
2748 &temp_config_num))
2749 bucket_size = (unsigned int) temp_config_num;
2752 "DHT",
2753 "CACHE_RESULTS");
2755 GNUNET_YES);
2756 return GNUNET_OK;
2757}
const struct GNUNET_CONFIGURATION_Handle * GDS_cfg
Configuration we use.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).

References all_connected_peers, bucket_size, cache_results, disable_try_connect, GDS_cfg, GNUNET_CONFIGURATION_get_value_number(), GNUNET_CONFIGURATION_get_value_yesno(), GNUNET_CONTAINER_multipeermap_create(), GNUNET_OK, GNUNET_YES, and consensus-simulation::int.

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GDS_NEIGHBOURS_done()

void GDS_NEIGHBOURS_done ( void  )

Shutdown neighbours subsystem.

Definition at line 2761 of file gnunet-service-dht_neighbours.c.

2762{
2763 if (NULL == all_connected_peers)
2764 return;
2765 GNUNET_assert (0 ==
2768 all_connected_peers = NULL;
2769 GNUNET_assert (NULL == find_peer_task);
2770}
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.

References all_connected_peers, find_peer_task, GNUNET_assert, GNUNET_CONTAINER_multipeermap_destroy(), and GNUNET_CONTAINER_multipeermap_size().

Referenced by shutdown_task().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GDS_NEIGHBOURS_get_id()

struct GNUNET_PeerIdentity * GDS_NEIGHBOURS_get_id ( void  )

Get the ID of the local node.

Returns
identity of the local node

Definition at line 2774 of file gnunet-service-dht_neighbours.c.

2775{
2776 return &GDS_my_identity;
2777}

References GDS_my_identity.

Variable Documentation

◆ cache_results

int cache_results
static

Do we cache all results that we are routing in the local datacache?

Definition at line 351 of file gnunet-service-dht_neighbours.c.

Referenced by GDS_NEIGHBOURS_init(), and process_reply_with_path().

◆ closest_bucket

unsigned int closest_bucket
static

The lowest currently used bucket, initially 0 (for 0-bits matching bucket).

Definition at line 356 of file gnunet-service-dht_neighbours.c.

Referenced by GDS_am_closest_peer(), GDS_NEIGHBOURS_broadcast(), GDS_u_connect(), GDS_u_disconnect(), and select_peer().

◆ newly_found_peers

unsigned int newly_found_peers
static

How many peers have we added since we sent out our last find peer request?

Definition at line 362 of file gnunet-service-dht_neighbours.c.

Referenced by GDS_u_connect(), and send_find_peer_message().

◆ disable_try_connect

int disable_try_connect
static

Option for testing that disables the 'connect' function of the DHT.

Definition at line 367 of file gnunet-service-dht_neighbours.c.

Referenced by GDS_NEIGHBOURS_init(), GDS_u_connect(), GDS_u_disconnect(), and hello_check().

◆ k_buckets

struct PeerBucket k_buckets[sizeof(struct GNUNET_HashCode) *8]
static

The buckets.

Array of size MAX_BUCKETS. Offset 0 means 0 bits matching.

Definition at line 372 of file gnunet-service-dht_neighbours.c.

Referenced by GDS_am_closest_peer(), GDS_NEIGHBOURS_broadcast(), GDS_try_connect(), GDS_u_connect(), GDS_u_disconnect(), and select_peer().

◆ all_connected_peers

struct GNUNET_CONTAINER_MultiPeerMap* all_connected_peers
static

Hash map of all CORE-connected peers, for easy removal from k_buckets on disconnect.

Values are of type struct PeerInfo.

Definition at line 378 of file gnunet-service-dht_neighbours.c.

Referenced by GDS_NEIGHBOURS_done(), GDS_NEIGHBOURS_init(), GDS_NEIGHBOURS_lookup_peer(), GDS_u_connect(), GDS_u_disconnect(), get_target_peers(), and send_find_peer_message().

◆ bucket_size

◆ find_peer_task

struct GNUNET_SCHEDULER_Task* find_peer_task
static

Task that sends FIND PEER requests.

Definition at line 388 of file gnunet-service-dht_neighbours.c.

Referenced by GDS_NEIGHBOURS_done(), GDS_u_connect(), GDS_u_disconnect(), and send_find_peer_message().