mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
get_close_nodes(): make use of assoc to find some really close nodes
DHT.c: - get_close_nodes(): use assoc to find nodes for the requested reference id - handle_sendnodes*(): set a proper timestamp for "heard" nodes assoc.*: - expand Assoc_close_entries by flags for additional restrictions for search - Assoc_get_close_entries(): honor the new flags - new_Assoc() prime handling: min. prime is now 5 instead of 3, and up to 25 is handled directly - Assoc_status(): added address family for seen/heard, print of hash is now fixed width
This commit is contained in:
parent
2967b67b7f
commit
110a8e889c
|
@ -333,7 +333,7 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod
|
||||||
* TODO: For the love of based <your favorite deity, in doubt use "love"> make
|
* TODO: For the love of based <your favorite deity, in doubt use "love"> make
|
||||||
* this function cleaner and much more efficient.
|
* this function cleaner and much more efficient.
|
||||||
*/
|
*/
|
||||||
static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family, uint8_t is_LAN)
|
static int get_somewhat_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family, uint8_t is_LAN)
|
||||||
{
|
{
|
||||||
int num_nodes = 0, i;
|
int num_nodes = 0, i;
|
||||||
get_close_nodes_inner(dht, client_id, nodes_list, sa_family,
|
get_close_nodes_inner(dht, client_id, nodes_list, sa_family,
|
||||||
|
@ -347,6 +347,53 @@ static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list
|
||||||
return num_nodes;
|
return num_nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family, uint8_t is_LAN)
|
||||||
|
{
|
||||||
|
if (!dht->assoc)
|
||||||
|
return get_somewhat_close_nodes(dht, client_id, nodes_list, sa_family, is_LAN);
|
||||||
|
|
||||||
|
Client_data *result[MAX_SENT_NODES];
|
||||||
|
|
||||||
|
Assoc_close_entries request;
|
||||||
|
memset(&request, 0, sizeof(request));
|
||||||
|
request.count = MAX_SENT_NODES;
|
||||||
|
request.count_good = MAX_SENT_NODES / 2;
|
||||||
|
request.result = result;
|
||||||
|
request.wanted_id = client_id;
|
||||||
|
request.flags = (is_LAN ? LANOk : 0) + (sa_family == AF_INET ? ProtoIPv4 : ProtoIPv6);
|
||||||
|
|
||||||
|
uint8_t num_found = Assoc_get_close_entries(dht->assoc, &request);
|
||||||
|
|
||||||
|
if (!num_found)
|
||||||
|
return get_somewhat_close_nodes(dht, client_id, nodes_list, sa_family, is_LAN);
|
||||||
|
|
||||||
|
uint8_t i, num_returned = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < num_found; i++) {
|
||||||
|
Client_data *client = result[i];
|
||||||
|
|
||||||
|
if (client) {
|
||||||
|
id_copy(nodes_list[i].client_id, client->client_id);
|
||||||
|
|
||||||
|
if (sa_family == AF_INET)
|
||||||
|
if (ipport_isset(&client->assoc4.ip_port)) {
|
||||||
|
nodes_list[i].ip_port = client->assoc4.ip_port;
|
||||||
|
num_returned++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sa_family == AF_INET6)
|
||||||
|
if (ipport_isset(&client->assoc6.ip_port)) {
|
||||||
|
nodes_list[i].ip_port = client->assoc6.ip_port;
|
||||||
|
num_returned++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return num_returned;
|
||||||
|
}
|
||||||
|
|
||||||
/* Replace first bad (or empty) node with this one.
|
/* Replace first bad (or empty) node with this one.
|
||||||
*
|
*
|
||||||
* return 0 if successful.
|
* return 0 if successful.
|
||||||
|
@ -884,26 +931,24 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id));
|
Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id));
|
||||||
uint32_t i;
|
|
||||||
|
|
||||||
IP_Port ipp;
|
uint64_t time_now = unix_time();
|
||||||
ipp.ip.family = AF_INET;
|
IPPTs ippts;
|
||||||
|
ippts.ip_port.ip.family = AF_INET;
|
||||||
|
ippts.timestamp = time_now;
|
||||||
|
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
for (i = 0; i < num_nodes; i++)
|
for (i = 0; i < num_nodes; i++)
|
||||||
if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != (uint32_t)~0)) {
|
if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != (uint32_t)~0)) {
|
||||||
ipp.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32;
|
ippts.ip_port.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32;
|
||||||
ipp.port = nodes4_list[i].ip_port.port;
|
ippts.ip_port.port = nodes4_list[i].ip_port.port;
|
||||||
|
|
||||||
send_ping_request(dht->ping, ipp, nodes4_list[i].client_id);
|
send_ping_request(dht->ping, ippts.ip_port, nodes4_list[i].client_id);
|
||||||
int used = returnedip_ports(dht, ipp, nodes4_list[i].client_id, packet + 1);
|
int used = returnedip_ports(dht, ippts.ip_port, nodes4_list[i].client_id, packet + 1);
|
||||||
|
|
||||||
if (dht->assoc) {
|
|
||||||
IPPTs ippts;
|
|
||||||
ippts.ip_port = ipp;
|
|
||||||
ippts.timestamp = 0;
|
|
||||||
|
|
||||||
|
if (dht->assoc)
|
||||||
Assoc_add_entry(dht->assoc, nodes4_list[i].client_id, &ippts, NULL, used ? 1 : 0);
|
Assoc_add_entry(dht->assoc, nodes4_list[i].client_id, &ippts, NULL, used ? 1 : 0);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -921,6 +966,7 @@ static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet,
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
Node_format *nodes_list = (Node_format *)(plain + sizeof(ping_id));
|
Node_format *nodes_list = (Node_format *)(plain + sizeof(ping_id));
|
||||||
|
uint64_t time_now = unix_time();
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
for (i = 0; i < num_nodes; i++)
|
for (i = 0; i < num_nodes; i++)
|
||||||
|
@ -931,7 +977,7 @@ static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet,
|
||||||
if (dht->assoc) {
|
if (dht->assoc) {
|
||||||
IPPTs ippts;
|
IPPTs ippts;
|
||||||
ippts.ip_port = nodes_list[i].ip_port;
|
ippts.ip_port = nodes_list[i].ip_port;
|
||||||
ippts.timestamp = 0;
|
ippts.timestamp = time_now;
|
||||||
|
|
||||||
Assoc_add_entry(dht->assoc, nodes_list[i].client_id, &ippts, NULL, used ? 1 : 0);
|
Assoc_add_entry(dht->assoc, nodes_list[i].client_id, &ippts, NULL, used ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -479,7 +479,7 @@ static uint8_t candidates_create_new(Assoc *assoc, hash_t hash, uint8_t *id, uin
|
||||||
ipp_recv = NULL;
|
ipp_recv = NULL;
|
||||||
|
|
||||||
if (ipp_recv) {
|
if (ipp_recv) {
|
||||||
entry->seen_at = unix_time();
|
entry->seen_at = ippts_send->timestamp;
|
||||||
entry->seen_family = ippts_send->ip_port.ip.family;
|
entry->seen_family = ippts_send->ip_port.ip.family;
|
||||||
|
|
||||||
ipptsp->ip_port = ippts_send->ip_port;
|
ipptsp->ip_port = ippts_send->ip_port;
|
||||||
|
@ -628,6 +628,24 @@ uint8_t Assoc_get_close_entries(Assoc *assoc, Assoc_close_entries *state)
|
||||||
Client_entry *entry = &cnd_bckt->list[i];
|
Client_entry *entry = &cnd_bckt->list[i];
|
||||||
|
|
||||||
if (entry->hash) {
|
if (entry->hash) {
|
||||||
|
if (state->flags & ProtoIPv4) {
|
||||||
|
if (!ipport_isset(&entry->client.assoc4.ip_port))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!(state->flags & LANOk))
|
||||||
|
if (!LAN_ip(entry->client.assoc4.ip_port.ip))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->flags & ProtoIPv6) {
|
||||||
|
if (!ipport_isset(&entry->client.assoc6.ip_port))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!(state->flags & LANOk))
|
||||||
|
if (!LAN_ip(entry->client.assoc6.ip_port.ip))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t dist = state->distance_absolute_func(assoc, state->custom_data, state->wanted_id, entry->client.client_id);
|
uint64_t dist = state->distance_absolute_func(assoc, state->custom_data, state->wanted_id, entry->client.client_id);
|
||||||
uint32_t index = b * assoc->candidates_bucket_size + i;
|
uint32_t index = b * assoc->candidates_bucket_size + i;
|
||||||
dist_list[index] = (dist << DISTANCE_INDEX_INDEX_BITS) | index;
|
dist_list[index] = (dist << DISTANCE_INDEX_INDEX_BITS) | index;
|
||||||
|
@ -685,7 +703,16 @@ uint8_t Assoc_get_close_entries(Assoc *assoc, Assoc_close_entries *state)
|
||||||
if (client_quota_good >= client_quota_max) {
|
if (client_quota_good >= client_quota_max) {
|
||||||
state->result[pos++] = &entry->client;
|
state->result[pos++] = &entry->client;
|
||||||
taken_last = i;
|
taken_last = i;
|
||||||
} else if (!is_timeout(entry->seen_at, BAD_NODE_TIMEOUT)) {
|
} else {
|
||||||
|
if (state->flags & (ProtoIPv4 | ProtoIPv6)) {
|
||||||
|
if ((state->flags & ProtoIPv4) && is_timeout(entry->client.assoc4.timestamp, BAD_NODE_TIMEOUT))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((state->flags & ProtoIPv6) && is_timeout(entry->client.assoc6.timestamp, BAD_NODE_TIMEOUT))
|
||||||
|
continue;
|
||||||
|
} else if (is_timeout(entry->seen_at, BAD_NODE_TIMEOUT))
|
||||||
|
continue;
|
||||||
|
|
||||||
state->result[pos++] = &entry->client;
|
state->result[pos++] = &entry->client;
|
||||||
client_quota_good++;
|
client_quota_good++;
|
||||||
taken_last = i;
|
taken_last = i;
|
||||||
|
@ -729,9 +756,8 @@ static uint8_t odd_min9_is_prime(size_t value)
|
||||||
|
|
||||||
static size_t prime_upto_min9(size_t limit)
|
static size_t prime_upto_min9(size_t limit)
|
||||||
{
|
{
|
||||||
/* primes besides 2 are odd */
|
/* even => odd */
|
||||||
if (!(limit % 2))
|
limit = limit - (1 - (limit % 2));
|
||||||
limit--;
|
|
||||||
|
|
||||||
while (!odd_min9_is_prime(limit))
|
while (!odd_min9_is_prime(limit))
|
||||||
limit -= 2;
|
limit -= 2;
|
||||||
|
@ -762,11 +788,16 @@ Assoc *new_Assoc(size_t bits, size_t entries, uint8_t *public_id)
|
||||||
assoc->candidates_bucket_bits = bits;
|
assoc->candidates_bucket_bits = bits;
|
||||||
assoc->candidates_bucket_count = 1U << bits;
|
assoc->candidates_bucket_count = 1U << bits;
|
||||||
|
|
||||||
if (entries <= 8) {
|
if (entries < 25) {
|
||||||
if (entries <= 4)
|
if (entries <= 6)
|
||||||
entries = 3;
|
entries = 5;
|
||||||
else if (!(entries % 2)) /* 6, 8 => 5, 7 */
|
else {
|
||||||
entries--;
|
entries = entries - (1 - (entries % 2)); /* even => odd */
|
||||||
|
|
||||||
|
/* 7..23: all odds but 9&15 are prime */
|
||||||
|
if (!(entries % 3)) /* 9, 15 */
|
||||||
|
entries -= 2; /* 7, 13 */
|
||||||
|
}
|
||||||
} else if (entries > ((1 << 17) - 1)) /* 130k+ */
|
} else if (entries > ((1 << 17) - 1)) /* 130k+ */
|
||||||
entries = (1 << 17) - 1;
|
entries = (1 << 17) - 1;
|
||||||
else {
|
else {
|
||||||
|
@ -860,6 +891,8 @@ void Assoc_status(Assoc *assoc)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loglog("[b:p] hash => [id...] used, seen, heard\n");
|
||||||
|
|
||||||
size_t bid, cid, total = 0;
|
size_t bid, cid, total = 0;
|
||||||
|
|
||||||
for (bid = 0; bid < assoc->candidates_bucket_count; bid++) {
|
for (bid = 0; bid < assoc->candidates_bucket_count; bid++) {
|
||||||
|
@ -869,11 +902,13 @@ void Assoc_status(Assoc *assoc)
|
||||||
Client_entry *entry = &bucket->list[cid];
|
Client_entry *entry = &bucket->list[cid];
|
||||||
|
|
||||||
if (entry->hash) {
|
if (entry->hash) {
|
||||||
sprintf(logbuffer, "[%3i:%3i] %x => [%s...] %i, %i, %i\n",
|
sprintf(logbuffer, "[%3i:%3i] %08x => [%s...] %i, %i(%c), %i(%c)\n",
|
||||||
(int)bid, (int)cid, entry->hash, idpart2str(entry->client.client_id, 8),
|
(int)bid, (int)cid, entry->hash, idpart2str(entry->client.client_id, 8),
|
||||||
entry->used_at ? (int)(unix_time() - entry->used_at) : 0,
|
entry->used_at ? (int)(unix_time() - entry->used_at) : 0,
|
||||||
entry->seen_at ? (int)(unix_time() - entry->seen_at) : 0,
|
entry->seen_at ? (int)(unix_time() - entry->seen_at) : 0,
|
||||||
entry->heard_at ? (int)(unix_time() - entry->heard_at) : 0);
|
entry->seen_at ? (entry->seen_family == AF_INET ? '4' : (entry->seen_family == AF_INET6 ? '6' : '?')) : '?',
|
||||||
|
entry->heard_at ? (int)(unix_time() - entry->heard_at) : 0,
|
||||||
|
entry->heard_at ? (entry->heard_family == AF_INET ? '4' : (entry->heard_family == AF_INET6 ? '6' : '?')) : '?');
|
||||||
loglog(logbuffer);
|
loglog(logbuffer);
|
||||||
total++;
|
total++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,9 +37,16 @@ uint8_t Assoc_add_entry(Assoc *assoc, uint8_t *id, IPPTs *ippts_send, IP_Port *i
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
typedef enum AssocCloseEntriesFlags {
|
||||||
|
ProtoIPv4 = 1,
|
||||||
|
ProtoIPv6 = 2,
|
||||||
|
LANOk = 4,
|
||||||
|
} AssocCloseEntriesFlags;
|
||||||
|
|
||||||
typedef struct Assoc_close_entries {
|
typedef struct Assoc_close_entries {
|
||||||
uint8_t *wanted_id; /* the target client_id */
|
|
||||||
void *custom_data; /* given to distance functions */
|
void *custom_data; /* given to distance functions */
|
||||||
|
uint8_t *wanted_id; /* the target client_id */
|
||||||
|
uint8_t flags; /* additional flags */
|
||||||
|
|
||||||
Assoc_distance_relative_callback distance_relative_func;
|
Assoc_distance_relative_callback distance_relative_func;
|
||||||
Assoc_distance_absolute_callback distance_absolute_func;
|
Assoc_distance_absolute_callback distance_absolute_func;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user