Skip to content

Commit 760f20c

Browse files
committed
DHT improvements part 1.
1 parent dedf863 commit 760f20c

File tree

3 files changed

+125
-113
lines changed

3 files changed

+125
-113
lines changed

toxcore/DHT.c

Lines changed: 105 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@
6565
/* Number of get node requests to send to quickly find close nodes. */
6666
#define MAX_BOOTSTRAP_TIMES 5
6767

68+
static uint8_t calc_dist(uint8_t a, uint8_t b)
69+
{
70+
return a ^ b;
71+
}
72+
6873
/* Compares pk1 and pk2 with pk.
6974
*
7075
* return 0 if both are same distance.
@@ -79,43 +84,38 @@ int id_closest(const uint8_t *pk, const uint8_t *pk1, const uint8_t *pk2)
7984

8085
for (i = 0; i < crypto_box_PUBLICKEYBYTES; ++i) {
8186

82-
distance1 = pk[i] ^ pk1[i];
83-
distance2 = pk[i] ^ pk2[i];
87+
distance1 = calc_dist(pk[i], pk1[i]);
88+
distance2 = calc_dist(pk[i], pk2[i]);
8489

85-
if (!i) {
86-
if (distance1 & (1 << 7)) {
87-
d1_abs = 1;
88-
}
90+
if (distance1 < distance2)
91+
return 1;
8992

90-
if (distance2 & (1 << 7)) {
91-
d2_abs = 1;
92-
}
93-
}
93+
if (distance1 > distance2)
94+
return 2;
95+
}
9496

95-
if (d1_abs)
96-
distance1 = ~distance1;
97+
return 0;
98+
}
9799

98-
if (d2_abs)
99-
distance2 = ~distance2;
100+
/* Return index of first unequal bit number.
101+
*/
102+
static unsigned int bit_by_bit_cmp(const uint8_t *pk1, const uint8_t *pk2)
103+
{
104+
unsigned int i, j = 0;
100105

101-
if (i == (crypto_box_PUBLICKEYBYTES - 1)) {
102-
if (d1_abs)
103-
if (distance1 != UINT8_MAX)
104-
++distance1;
106+
for (i = 0; i < crypto_box_PUBLICKEYBYTES; ++i) {
107+
if (pk1[i] == pk2[i])
108+
continue;
105109

106-
if (d2_abs)
107-
if (distance2 != UINT8_MAX)
108-
++distance2;
110+
for (j = 0; j < 8; ++j) {
111+
if ((pk1[i] & (1 << (7 - j))) != (pk2[i] & (1 << (7 - j))))
112+
break;
109113
}
110114

111-
if (distance1 < distance2)
112-
return 1;
113-
114-
if (distance1 > distance2)
115-
return 2;
115+
break;
116116
}
117117

118-
return 0;
118+
return i * 8 + j;
119119
}
120120

121121
/* Shared key generations are costly, it is therefor smart to store commonly used
@@ -586,7 +586,7 @@ static int get_somewhat_close_nodes(const DHT *dht, const uint8_t *public_key, N
586586
{
587587
uint32_t num_nodes = 0, i;
588588
get_close_nodes_inner(public_key, nodes_list, sa_family,
589-
dht->close_clientlist, LCLIENT_LIST, &num_nodes, is_LAN, want_good);
589+
dht->close_clientlist, LCLIENT_LIST, &num_nodes, is_LAN, 0);
590590

591591
/*TODO uncomment this when hardening is added to close friend clients
592592
for (i = 0; i < dht->num_friends; ++i)
@@ -780,6 +780,68 @@ static int replace_all( Client_data *list,
780780
return 0;
781781
}
782782

783+
/* Add node to close list.
784+
*
785+
* simulate is set to 1 if we want to check if a node can be added to the list without adding it.
786+
*
787+
* return -1 on failure.
788+
* return 0 on success.
789+
*/
790+
static int add_to_close(DHT *dht, const uint8_t *public_key, IP_Port ip_port, _Bool simulate)
791+
{
792+
unsigned int i;
793+
794+
unsigned int index = bit_by_bit_cmp(public_key, dht->self_public_key);
795+
796+
if (index > LCLIENT_LENGTH)
797+
index = LCLIENT_LENGTH - 1;
798+
799+
for (i = 0; i < LCLIENT_NODES; ++i) {
800+
Client_data *client = &dht->close_clientlist[(index * LCLIENT_NODES) + i];
801+
802+
if (is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) && is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)) {
803+
if (!simulate) {
804+
IPPTsPng *ipptp_write = NULL;
805+
IPPTsPng *ipptp_clear = NULL;
806+
807+
if (ip_port.ip.family == AF_INET) {
808+
ipptp_write = &client->assoc4;
809+
ipptp_clear = &client->assoc6;
810+
} else {
811+
ipptp_write = &client->assoc6;
812+
ipptp_clear = &client->assoc4;
813+
}
814+
815+
id_copy(client->public_key, public_key);
816+
ipptp_write->ip_port = ip_port;
817+
ipptp_write->timestamp = unix_time();
818+
819+
ip_reset(&ipptp_write->ret_ip_port.ip);
820+
ipptp_write->ret_ip_port.port = 0;
821+
ipptp_write->ret_timestamp = 0;
822+
823+
/* zero out other address */
824+
memset(ipptp_clear, 0, sizeof(*ipptp_clear));
825+
}
826+
827+
return 0;
828+
}
829+
}
830+
831+
return -1;
832+
}
833+
834+
/* Return 1 if node can be added to close list, 0 if it can't.
835+
*/
836+
_Bool node_addable_to_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_port)
837+
{
838+
if (add_to_close(dht, public_key, ip_port, 1) == 0) {
839+
return 1;
840+
}
841+
842+
return 0;
843+
}
844+
783845
static _Bool is_pk_in_client_list(Client_data *list, unsigned int client_list_length, const uint8_t *public_key,
784846
IP_Port ip_port)
785847
{
@@ -807,23 +869,18 @@ static unsigned int ping_node_from_getnodes_ok(DHT *dht, const uint8_t *public_k
807869
{
808870
_Bool ret = 0;
809871

810-
if (store_node_ok(&dht->close_clientlist[1], public_key, dht->self_public_key)) {
811-
ret = 1;
812-
}
813-
814-
if (store_node_ok(&dht->close_clientlist[0], public_key, dht->self_public_key)) {
872+
if (add_to_close(dht, public_key, ip_port, 1) == 0) {
815873
ret = 1;
816874
}
817875

818-
if (ret && !client_in_nodelist(dht->to_bootstrap, dht->num_to_bootstrap, public_key)
819-
&& !is_pk_in_client_list(dht->close_clientlist, LCLIENT_LIST, public_key, ip_port)) {
820-
if (dht->num_to_bootstrap < MAX_SENT_NODES) {
876+
if (ret && !client_in_nodelist(dht->to_bootstrap, dht->num_to_bootstrap, public_key)) {
877+
if (dht->num_to_bootstrap < MAX_CLOSE_TO_BOOTSTRAP_NODES) {
821878
memcpy(dht->to_bootstrap[dht->num_to_bootstrap].public_key, public_key, crypto_box_PUBLICKEYBYTES);
822879
dht->to_bootstrap[dht->num_to_bootstrap].ip_port = ip_port;
823880
++dht->num_to_bootstrap;
824881
} else {
825882
//TODO: ipv6 vs v4
826-
add_to_list(dht->to_bootstrap, MAX_SENT_NODES, public_key, ip_port, dht->self_public_key);
883+
add_to_list(dht->to_bootstrap, MAX_CLOSE_TO_BOOTSTRAP_NODES, public_key, ip_port, dht->self_public_key);
827884
}
828885
}
829886

@@ -878,7 +935,7 @@ int addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *public_key)
878935
* to replace the first ip by the second.
879936
*/
880937
if (!client_or_ip_port_in_list(dht->close_clientlist, LCLIENT_LIST, public_key, ip_port)) {
881-
if (replace_all(dht->close_clientlist, LCLIENT_LIST, public_key, ip_port, dht->self_public_key))
938+
if (add_to_close(dht, public_key, ip_port, 0))
882939
used++;
883940
} else
884941
used++;
@@ -1391,54 +1448,9 @@ int DHT_getfriendip(const DHT *dht, const uint8_t *public_key, IP_Port *ip_port)
13911448
return -1;
13921449
}
13931450

1394-
static void abs_divide_by_2(uint8_t *public_key_dist)
1395-
{
1396-
unsigned int i;
1397-
_Bool one = 0, abs = 0;
1398-
1399-
if (public_key_dist[0] & (1 << 7)) {
1400-
for (i = 0; i < crypto_box_PUBLICKEYBYTES; ++i) {
1401-
public_key_dist[i] = ~public_key_dist[i];
1402-
}
1403-
1404-
if (public_key_dist[crypto_box_PUBLICKEYBYTES - 1] != UINT8_MAX)
1405-
++public_key_dist[crypto_box_PUBLICKEYBYTES - 1];
1406-
}
1407-
1408-
for (i = 0; i < crypto_box_PUBLICKEYBYTES; ++i) {
1409-
_Bool temp = 0;
1410-
1411-
if (public_key_dist[i] & (1)) {
1412-
temp = 1;
1413-
}
1414-
1415-
public_key_dist[i] >>= 1;
1416-
1417-
if (one)
1418-
public_key_dist[i] += (1 << 7);
1419-
1420-
one = temp;
1421-
}
1422-
}
1423-
1424-
static void find_midpoint(uint8_t *out, const uint8_t *top, const uint8_t *bot)
1425-
{
1426-
unsigned int i;
1427-
1428-
for (i = 0; i < crypto_box_PUBLICKEYBYTES; ++i) {
1429-
out[i] = top[i] ^ bot[i];
1430-
}
1431-
1432-
abs_divide_by_2(out);
1433-
1434-
for (i = 0; i < crypto_box_PUBLICKEYBYTES; ++i) {
1435-
out[i] ^= bot[i];
1436-
}
1437-
}
1438-
14391451
/* returns number of nodes not in kill-timeout */
14401452
static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, const uint8_t *public_key,
1441-
Client_data *list, uint32_t list_count, uint32_t *bootstrap_times)
1453+
Client_data *list, uint32_t list_count, uint32_t *bootstrap_times, _Bool sortable)
14421454
{
14431455
uint32_t i;
14441456
uint8_t not_kill = 0;
@@ -1482,33 +1494,19 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co
14821494
}
14831495
}
14841496

1485-
if (sort_ok) {
1497+
if (sortable && sort_ok) {
14861498
sort_client_list(list, list_count, public_key);
14871499
}
14881500

14891501
if ((num_nodes != 0) && (is_timeout(*lastgetnode, GET_NODE_INTERVAL) || *bootstrap_times < MAX_BOOTSTRAP_TIMES)) {
1490-
uint32_t rand_node = rand() % (num_nodes * 2);
1491-
1492-
if (rand_node >= num_nodes) {
1493-
rand_node = rand_node % num_nodes;
1494-
1495-
if ((num_nodes - 1) != rand_node) {
1496-
rand_node += rand() % (num_nodes - (rand_node + 1));
1497-
}
1498-
1499-
if (memcmp(client_list[rand_node]->public_key, public_key, crypto_box_PUBLICKEYBYTES) != 0) {
1500-
uint8_t get_pk[crypto_box_PUBLICKEYBYTES];
1501-
find_midpoint(get_pk, client_list[rand_node]->public_key, public_key);
1502-
getnodes(dht, assoc_list[rand_node]->ip_port, client_list[rand_node]->public_key, get_pk, NULL);
1503-
}
1504-
} else {
1505-
if ((num_nodes - 1) != rand_node) {
1506-
rand_node += rand() % (num_nodes - (rand_node + 1));
1507-
}
1502+
uint32_t rand_node = rand() % (num_nodes);
15081503

1509-
getnodes(dht, assoc_list[rand_node]->ip_port, client_list[rand_node]->public_key, public_key, NULL);
1504+
if ((num_nodes - 1) != rand_node) {
1505+
rand_node += rand() % (num_nodes - (rand_node + 1));
15101506
}
15111507

1508+
getnodes(dht, assoc_list[rand_node]->ip_port, client_list[rand_node]->public_key, public_key, NULL);
1509+
15121510
*lastgetnode = temp_time;
15131511
++*bootstrap_times;
15141512
}
@@ -1533,7 +1531,7 @@ static void do_DHT_friends(DHT *dht)
15331531
friend->num_to_bootstrap = 0;
15341532

15351533
do_ping_and_sendnode_requests(dht, &friend->lastgetnode, friend->public_key, friend->client_list, MAX_FRIEND_CLIENTS,
1536-
&friend->bootstrap_times);
1534+
&friend->bootstrap_times, 1);
15371535
}
15381536
}
15391537

@@ -1551,7 +1549,7 @@ static void do_Close(DHT *dht)
15511549
dht->num_to_bootstrap = 0;
15521550

15531551
uint8_t not_killed = do_ping_and_sendnode_requests(dht, &dht->close_lastgetnodes, dht->self_public_key,
1554-
dht->close_clientlist, LCLIENT_LIST, &dht->close_bootstrap_times);
1552+
dht->close_clientlist, LCLIENT_LIST, &dht->close_bootstrap_times, 0);
15551553

15561554
if (!not_killed) {
15571555
/* all existing nodes are at least KILL_NODE_TIMEOUT,
@@ -2453,7 +2451,7 @@ void do_DHT(DHT *dht)
24532451
do_DHT_friends(dht);
24542452
do_NAT(dht);
24552453
do_to_ping(dht->ping);
2456-
do_hardening(dht);
2454+
//do_hardening(dht);
24572455
#ifdef ENABLE_ASSOC_DHT
24582456

24592457
if (dht->assoc)

toxcore/DHT.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,13 @@
3131
/* Maximum number of clients stored per friend. */
3232
#define MAX_FRIEND_CLIENTS 8
3333

34+
#define LCLIENT_NODES (MAX_FRIEND_CLIENTS)
35+
#define LCLIENT_LENGTH 128
36+
3437
/* A list of the clients mathematically closest to ours. */
35-
#define LCLIENT_LIST 32
38+
#define LCLIENT_LIST (LCLIENT_LENGTH * LCLIENT_NODES)
39+
40+
#define MAX_CLOSE_TO_BOOTSTRAP_NODES 8
3641

3742
/* The max number of nodes to send with send nodes. */
3843
#define MAX_SENT_NODES 4
@@ -58,7 +63,7 @@
5863
#define TOX_TCP_INET6 138
5964

6065
/* The number of "fake" friends to add (for optimization purposes and so our paths for the onion part are more random) */
61-
#define DHT_FAKE_FRIEND_NUMBER 4
66+
#define DHT_FAKE_FRIEND_NUMBER 2
6267

6368
/* Functions to transfer ips safely across wire. */
6469
void to_net_family(IP *ip);
@@ -232,7 +237,7 @@ typedef struct {
232237

233238
Cryptopacket_Handles cryptopackethandlers[256];
234239

235-
Node_format to_bootstrap[MAX_SENT_NODES];
240+
Node_format to_bootstrap[MAX_CLOSE_TO_BOOTSTRAP_NODES];
236241
unsigned int num_to_bootstrap;
237242
} DHT;
238243
/*----------------------------------------------------------------------------------*/
@@ -307,6 +312,10 @@ int id_closest(const uint8_t *pk, const uint8_t *pk1, const uint8_t *pk2);
307312
_Bool add_to_list(Node_format *nodes_list, unsigned int length, const uint8_t *pk, IP_Port ip_port,
308313
const uint8_t *cmp_pk);
309314

315+
/* Return 1 if node can be added to close list, 0 if it can't.
316+
*/
317+
_Bool node_addable_to_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_port);
318+
310319
/* Get the (maximum MAX_SENT_NODES) closest nodes to public_key we know
311320
* and put them in nodes_list (must be MAX_SENT_NODES big).
312321
*

toxcore/ping.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@
3939
#define PING_NUM_MAX 512
4040

4141
/* Maximum newly announced nodes to ping per TIME_TO_PING seconds. */
42-
#define MAX_TO_PING 16
42+
#define MAX_TO_PING 32
4343

4444
/* Ping newly announced nodes to ping per TIME_TO_PING seconds*/
45-
#define TIME_TO_PING 4
45+
#define TIME_TO_PING 2
4646

4747

4848
struct PING {
@@ -262,9 +262,11 @@ int add_to_ping(PING *ping, const uint8_t *public_key, IP_Port ip_port)
262262
if (!ip_isset(&ip_port.ip))
263263
return -1;
264264

265-
if (in_list(ping->dht->close_clientlist, LCLIENT_LIST, public_key, ip_port))
265+
if (!node_addable_to_close_list(ping->dht, public_key, ip_port))
266266
return -1;
267267

268+
if (in_list(ping->dht->close_clientlist, LCLIENT_LIST, public_key, ip_port))
269+
return -1;
268270

269271
IP_Port temp;
270272

@@ -311,6 +313,9 @@ void do_to_ping(PING *ping)
311313
if (!ip_isset(&ping->to_ping[i].ip_port.ip))
312314
break;
313315

316+
if (!node_addable_to_close_list(ping->dht, ping->to_ping[i].public_key, ping->to_ping[i].ip_port))
317+
continue;
318+
314319
send_ping_request(ping, ping->to_ping[i].ip_port, ping->to_ping[i].public_key);
315320
ip_reset(&ping->to_ping[i].ip_port.ip);
316321
}

0 commit comments

Comments
 (0)