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
|
||||
* 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;
|
||||
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;
|
||||
}
|
||||
|
||||
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.
|
||||
*
|
||||
* return 0 if successful.
|
||||
|
@ -884,26 +931,24 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3
|
|||
return 1;
|
||||
|
||||
Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id));
|
||||
uint32_t i;
|
||||
|
||||
IP_Port ipp;
|
||||
ipp.ip.family = AF_INET;
|
||||
uint64_t time_now = unix_time();
|
||||
IPPTs ippts;
|
||||
ippts.ip_port.ip.family = AF_INET;
|
||||
ippts.timestamp = time_now;
|
||||
|
||||
uint32_t 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)) {
|
||||
ipp.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32;
|
||||
ipp.port = nodes4_list[i].ip_port.port;
|
||||
ippts.ip_port.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32;
|
||||
ippts.ip_port.port = nodes4_list[i].ip_port.port;
|
||||
|
||||
send_ping_request(dht->ping, ipp, nodes4_list[i].client_id);
|
||||
int used = returnedip_ports(dht, ipp, nodes4_list[i].client_id, packet + 1);
|
||||
|
||||
if (dht->assoc) {
|
||||
IPPTs ippts;
|
||||
ippts.ip_port = ipp;
|
||||
ippts.timestamp = 0;
|
||||
send_ping_request(dht->ping, ippts.ip_port, nodes4_list[i].client_id);
|
||||
int used = returnedip_ports(dht, ippts.ip_port, nodes4_list[i].client_id, packet + 1);
|
||||
|
||||
if (dht->assoc)
|
||||
Assoc_add_entry(dht->assoc, nodes4_list[i].client_id, &ippts, NULL, used ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -921,6 +966,7 @@ static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet,
|
|||
return 1;
|
||||
|
||||
Node_format *nodes_list = (Node_format *)(plain + sizeof(ping_id));
|
||||
uint64_t time_now = unix_time();
|
||||
uint32_t 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) {
|
||||
IPPTs ippts;
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -479,7 +479,7 @@ static uint8_t candidates_create_new(Assoc *assoc, hash_t hash, uint8_t *id, uin
|
|||
ipp_recv = NULL;
|
||||
|
||||
if (ipp_recv) {
|
||||
entry->seen_at = unix_time();
|
||||
entry->seen_at = ippts_send->timestamp;
|
||||
entry->seen_family = ippts_send->ip_port.ip.family;
|
||||
|
||||
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];
|
||||
|
||||
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);
|
||||
uint32_t index = b * assoc->candidates_bucket_size + i;
|
||||
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) {
|
||||
state->result[pos++] = &entry->client;
|
||||
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;
|
||||
client_quota_good++;
|
||||
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)
|
||||
{
|
||||
/* primes besides 2 are odd */
|
||||
if (!(limit % 2))
|
||||
limit--;
|
||||
/* even => odd */
|
||||
limit = limit - (1 - (limit % 2));
|
||||
|
||||
while (!odd_min9_is_prime(limit))
|
||||
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_count = 1U << bits;
|
||||
|
||||
if (entries <= 8) {
|
||||
if (entries <= 4)
|
||||
entries = 3;
|
||||
else if (!(entries % 2)) /* 6, 8 => 5, 7 */
|
||||
entries--;
|
||||
if (entries < 25) {
|
||||
if (entries <= 6)
|
||||
entries = 5;
|
||||
else {
|
||||
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+ */
|
||||
entries = (1 << 17) - 1;
|
||||
else {
|
||||
|
@ -860,6 +891,8 @@ void Assoc_status(Assoc *assoc)
|
|||
return;
|
||||
}
|
||||
|
||||
loglog("[b:p] hash => [id...] used, seen, heard\n");
|
||||
|
||||
size_t bid, cid, total = 0;
|
||||
|
||||
for (bid = 0; bid < assoc->candidates_bucket_count; bid++) {
|
||||
|
@ -869,11 +902,13 @@ void Assoc_status(Assoc *assoc)
|
|||
Client_entry *entry = &bucket->list[cid];
|
||||
|
||||
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),
|
||||
entry->used_at ? (int)(unix_time() - entry->used_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);
|
||||
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 {
|
||||
uint8_t *wanted_id; /* the target client_id */
|
||||
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_absolute_callback distance_absolute_func;
|
||||
|
|
Loading…
Reference in New Issue
Block a user