summaryrefslogtreecommitdiff
path: root/protocols/Tox/libtox/src/toxcore/DHT.c
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Tox/libtox/src/toxcore/DHT.c')
-rw-r--r--protocols/Tox/libtox/src/toxcore/DHT.c126
1 files changed, 73 insertions, 53 deletions
diff --git a/protocols/Tox/libtox/src/toxcore/DHT.c b/protocols/Tox/libtox/src/toxcore/DHT.c
index b3017259b2..267d46881e 100644
--- a/protocols/Tox/libtox/src/toxcore/DHT.c
+++ b/protocols/Tox/libtox/src/toxcore/DHT.c
@@ -173,9 +173,9 @@ const uint8_t *dht_get_friend_public_key(const DHT *dht, uint32_t friend_num)
return dht->friends_list[friend_num].public_key;
}
-static bool assoc_timeout(const Mono_Time *mono_time, const IPPTsPng *assoc)
+static bool assoc_timeout(uint64_t cur_time, const IPPTsPng *assoc)
{
- return mono_time_is_timeout(mono_time, assoc->timestamp, BAD_NODE_TIMEOUT);
+ return (assoc->timestamp + BAD_NODE_TIMEOUT) <= cur_time;
}
/* Compares pk1 and pk2 with pk.
@@ -295,7 +295,7 @@ void dht_get_shared_key_sent(DHT *dht, uint8_t *shared_key, const uint8_t *publi
get_shared_key(dht->mono_time, &dht->shared_keys_sent, shared_key, dht->self_secret_key, public_key);
}
-#define CRYPTO_SIZE 1 + CRYPTO_PUBLIC_KEY_SIZE * 2 + CRYPTO_NONCE_SIZE
+#define CRYPTO_SIZE (1 + CRYPTO_PUBLIC_KEY_SIZE * 2 + CRYPTO_NONCE_SIZE)
/* Create a request to peer.
* send_public_key and send_secret_key are the pub/secret keys of the sender.
@@ -583,7 +583,8 @@ int pack_nodes(uint8_t *data, uint16_t length, const Node_format *nodes, uint16_
int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed_data_len, const uint8_t *data,
uint16_t length, bool tcp_enabled)
{
- uint32_t num = 0, len_processed = 0;
+ uint32_t num = 0;
+ uint32_t len_processed = 0;
while (num < max_num_nodes && len_processed < length) {
const int ipp_size = unpack_ip_port(&nodes[num].ip_port, data + len_processed, length - len_processed, tcp_enabled);
@@ -787,7 +788,7 @@ static uint8_t hardening_correct(const Hardening *h)
/*
* helper for get_close_nodes(). argument list is a monster :D
*/
-static void get_close_nodes_inner(const Mono_Time *mono_time, const uint8_t *public_key, Node_format *nodes_list,
+static void get_close_nodes_inner(uint64_t cur_time, const uint8_t *public_key, Node_format *nodes_list,
Family sa_family, const Client_data *client_list, uint32_t client_list_length,
uint32_t *num_nodes_ptr, bool is_LAN, uint8_t want_good)
{
@@ -818,7 +819,7 @@ static void get_close_nodes_inner(const Mono_Time *mono_time, const uint8_t *pub
}
/* node not in a good condition? */
- if (assoc_timeout(mono_time, ipptp)) {
+ if (assoc_timeout(cur_time, ipptp)) {
continue;
}
@@ -856,7 +857,7 @@ static int get_somewhat_close_nodes(const DHT *dht, const uint8_t *public_key, N
Family sa_family, bool is_LAN, uint8_t want_good)
{
uint32_t num_nodes = 0;
- get_close_nodes_inner(dht->mono_time, public_key, nodes_list, sa_family,
+ get_close_nodes_inner(dht->last_run, public_key, nodes_list, sa_family,
dht->close_clientlist, LCLIENT_LIST, &num_nodes, is_LAN, 0);
/* TODO(irungentoo): uncomment this when hardening is added to close friend clients */
@@ -871,7 +872,7 @@ static int get_somewhat_close_nodes(const DHT *dht, const uint8_t *public_key, N
#endif
for (uint32_t i = 0; i < dht->num_friends; ++i) {
- get_close_nodes_inner(dht->mono_time, public_key, nodes_list, sa_family,
+ get_close_nodes_inner(dht->last_run, public_key, nodes_list, sa_family,
dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
&num_nodes, is_LAN, 0);
}
@@ -887,7 +888,7 @@ int get_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *node
}
typedef struct DHT_Cmp_data {
- const Mono_Time *mono_time;
+ uint64_t cur_time;
const uint8_t *base_public_key;
Client_data entry;
} DHT_Cmp_data;
@@ -899,15 +900,16 @@ static bool incorrect_hardening(const IPPTsPng *assoc)
static int cmp_dht_entry(const void *a, const void *b)
{
- DHT_Cmp_data cmp1, cmp2;
+ DHT_Cmp_data cmp1;
+ DHT_Cmp_data cmp2;
memcpy(&cmp1, a, sizeof(DHT_Cmp_data));
memcpy(&cmp2, b, sizeof(DHT_Cmp_data));
const Client_data entry1 = cmp1.entry;
const Client_data entry2 = cmp2.entry;
const uint8_t *cmp_public_key = cmp1.base_public_key;
- bool t1 = assoc_timeout(cmp1.mono_time, &entry1.assoc4) && assoc_timeout(cmp1.mono_time, &entry1.assoc6);
- bool t2 = assoc_timeout(cmp2.mono_time, &entry2.assoc4) && assoc_timeout(cmp2.mono_time, &entry2.assoc6);
+ bool t1 = assoc_timeout(cmp1.cur_time, &entry1.assoc4) && assoc_timeout(cmp1.cur_time, &entry1.assoc6);
+ bool t2 = assoc_timeout(cmp2.cur_time, &entry2.assoc4) && assoc_timeout(cmp2.cur_time, &entry2.assoc6);
if (t1 && t2) {
return 0;
@@ -950,15 +952,15 @@ static int cmp_dht_entry(const void *a, const void *b)
* return 0 if node can't be stored.
* return 1 if it can.
*/
-static unsigned int store_node_ok(const Client_data *client, const Mono_Time *mono_time, const uint8_t *public_key,
+static unsigned int store_node_ok(const Client_data *client, uint64_t cur_time, const uint8_t *public_key,
const uint8_t *comp_public_key)
{
- return (assoc_timeout(mono_time, &client->assoc4)
- && assoc_timeout(mono_time, &client->assoc6))
+ return (assoc_timeout(cur_time, &client->assoc4)
+ && assoc_timeout(cur_time, &client->assoc6))
|| id_closest(comp_public_key, client->public_key, public_key) == 2;
}
-static void sort_client_list(Client_data *list, const Mono_Time *mono_time, unsigned int length,
+static void sort_client_list(Client_data *list, uint64_t cur_time, unsigned int length,
const uint8_t *comp_public_key)
{
// Pass comp_public_key to qsort with each Client_data entry, so the
@@ -966,7 +968,7 @@ static void sort_client_list(Client_data *list, const Mono_Time *mono_time, unsi
VLA(DHT_Cmp_data, cmp_list, length);
for (uint32_t i = 0; i < length; ++i) {
- cmp_list[i].mono_time = mono_time;
+ cmp_list[i].cur_time = cur_time;
cmp_list[i].base_public_key = comp_public_key;
cmp_list[i].entry = list[i];
}
@@ -1015,7 +1017,7 @@ static void update_client_with_reset(const Mono_Time *mono_time, Client_data *cl
* than public_key.
*
* returns true when the item was stored, false otherwise */
-static bool replace_all(const Mono_Time *mono_time,
+static bool replace_all(const DHT *dht,
Client_data *list,
uint16_t length,
const uint8_t *public_key,
@@ -1026,17 +1028,17 @@ static bool replace_all(const Mono_Time *mono_time,
return false;
}
- if (!store_node_ok(&list[1], mono_time, public_key, comp_public_key) &&
- !store_node_ok(&list[0], mono_time, public_key, comp_public_key)) {
+ if (!store_node_ok(&list[1], dht->last_run, public_key, comp_public_key) &&
+ !store_node_ok(&list[0], dht->last_run, public_key, comp_public_key)) {
return false;
}
- sort_client_list(list, mono_time, length, comp_public_key);
+ sort_client_list(list, dht->last_run, length, comp_public_key);
Client_data *const client = &list[0];
id_copy(client->public_key, public_key);
- update_client_with_reset(mono_time, client, &ip_port);
+ update_client_with_reset(dht->mono_time, client, &ip_port);
return true;
}
@@ -1060,8 +1062,8 @@ static int add_to_close(DHT *dht, const uint8_t *public_key, IP_Port ip_port, bo
* index is left as >= LCLIENT_LENGTH */
Client_data *const client = &dht->close_clientlist[(index * LCLIENT_NODES) + i];
- if (!assoc_timeout(dht->mono_time, &client->assoc4) ||
- !assoc_timeout(dht->mono_time, &client->assoc6)) {
+ if (!assoc_timeout(dht->last_run, &client->assoc4) ||
+ !assoc_timeout(dht->last_run, &client->assoc6)) {
continue;
}
@@ -1084,7 +1086,7 @@ bool node_addable_to_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_
return add_to_close(dht, public_key, ip_port, 1) == 0;
}
-static bool is_pk_in_client_list(const Client_data *list, unsigned int client_list_length, const Mono_Time *mono_time,
+static bool is_pk_in_client_list(const Client_data *list, unsigned int client_list_length, uint64_t cur_time,
const uint8_t *public_key, IP_Port ip_port)
{
const uint32_t index = index_of_client_pk(list, client_list_length, public_key);
@@ -1097,7 +1099,7 @@ static bool is_pk_in_client_list(const Client_data *list, unsigned int client_li
? &list[index].assoc4
: &list[index].assoc6;
- return !assoc_timeout(mono_time, assoc);
+ return !assoc_timeout(cur_time, assoc);
}
static bool is_pk_in_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_port)
@@ -1108,7 +1110,7 @@ static bool is_pk_in_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_
index = LCLIENT_LENGTH - 1;
}
- return is_pk_in_client_list(dht->close_clientlist + index * LCLIENT_NODES, LCLIENT_NODES, dht->mono_time, public_key,
+ return is_pk_in_client_list(dht->close_clientlist + index * LCLIENT_NODES, LCLIENT_NODES, dht->last_run, public_key,
ip_port);
}
@@ -1148,17 +1150,17 @@ static bool ping_node_from_getnodes_ok(DHT *dht, const uint8_t *public_key, IP_P
bool store_ok = false;
- if (store_node_ok(&dht_friend->client_list[1], dht->mono_time, public_key, dht_friend->public_key)) {
+ if (store_node_ok(&dht_friend->client_list[1], dht->last_run, public_key, dht_friend->public_key)) {
store_ok = true;
}
- if (store_node_ok(&dht_friend->client_list[0], dht->mono_time, public_key, dht_friend->public_key)) {
+ if (store_node_ok(&dht_friend->client_list[0], dht->last_run, public_key, dht_friend->public_key)) {
store_ok = true;
}
unsigned int *const friend_num = &dht_friend->num_to_bootstrap;
const uint32_t index = index_of_node_pk(dht_friend->to_bootstrap, *friend_num, public_key);
- const bool pk_in_list = is_pk_in_client_list(dht_friend->client_list, MAX_FRIEND_CLIENTS, dht->mono_time, public_key,
+ const bool pk_in_list = is_pk_in_client_list(dht_friend->client_list, MAX_FRIEND_CLIENTS, dht->last_run, public_key,
ip_port);
if (store_ok && index == UINT32_MAX && !pk_in_list) {
@@ -1212,7 +1214,7 @@ uint32_t addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *public_key)
/* replace_all should be called only if !in_list (don't extract to variable) */
if (in_list
- || replace_all(dht->mono_time, dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, public_key, ip_port,
+ || replace_all(dht, dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, public_key, ip_port,
dht->friends_list[i].public_key)) {
DHT_Friend *dht_friend = &dht->friends_list[i];
@@ -1292,7 +1294,7 @@ static void returnedip_ports(DHT *dht, IP_Port ip_port, const uint8_t *public_ke
}
/* Send a getnodes request.
- sendback_node is the node that it will send back the response to (set to NULL to disable this) */
+ * sendback_node is the node that it will send back the response to (set to NULL to disable this) */
static int getnodes(DHT *dht, IP_Port ip_port, const uint8_t *public_key, const uint8_t *client_id,
const Node_format *sendback_node)
{
@@ -1425,7 +1427,7 @@ static int handle_getnodes(void *object, IP_Port source, const uint8_t *packet,
}
/* return false if no
- return true if yes */
+ * return true if yes */
static bool sent_getnode_to_node(DHT *dht, const uint8_t *public_key, IP_Port node_ip_port, uint64_t ping_id,
Node_format *sendback_node)
{
@@ -1676,7 +1678,7 @@ int dht_getfriendip(const DHT *dht, const uint8_t *public_key, IP_Port *ip_port)
for (const IPPTsPng * const *it = assocs; *it; ++it) {
const IPPTsPng *const assoc = *it;
- if (!assoc_timeout(dht->mono_time, assoc)) {
+ if (!assoc_timeout(dht->last_run, assoc)) {
*ip_port = assoc->ip_port;
return 1;
}
@@ -1717,7 +1719,7 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co
}
/* If node is good. */
- if (!assoc_timeout(dht->mono_time, assoc)) {
+ if (!assoc_timeout(dht->last_run, assoc)) {
client_list[num_nodes] = client;
assoc_list[num_nodes] = assoc;
++num_nodes;
@@ -1734,7 +1736,7 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co
}
if (sortable && sort_ok) {
- sort_client_list(list, dht->mono_time, list_count, public_key);
+ sort_client_list(list, dht->last_run, list_count, public_key);
}
if ((num_nodes != 0) && (mono_time_is_timeout(dht->mono_time, *lastgetnode, GET_NODE_INTERVAL)
@@ -1918,8 +1920,8 @@ static int friend_iplist(const DHT *dht, IP_Port *ip_portlist, uint16_t friend_n
}
if (id_equal(client->public_key, dht_friend->public_key)) {
- if (!assoc_timeout(dht->mono_time, &client->assoc6)
- || !assoc_timeout(dht->mono_time, &client->assoc4)) {
+ if (!assoc_timeout(dht->last_run, &client->assoc6)
+ || !assoc_timeout(dht->last_run, &client->assoc4)) {
return 0; /* direct connectivity */
}
}
@@ -2389,7 +2391,7 @@ static uint32_t have_nodes_closelist(DHT *dht, Node_format *nodes, uint16_t num)
const IPPTsPng *const temp = get_closelist_IPPTsPng(dht, nodes[i].public_key, nodes[i].ip_port.ip.family);
if (temp) {
- if (!assoc_timeout(dht->mono_time, temp)) {
+ if (!assoc_timeout(dht->last_run, temp)) {
++counter;
}
}
@@ -2417,7 +2419,8 @@ static int handle_hardening(void *object, IP_Port source, const uint8_t *source_
return 1;
}
- Node_format node, tocheck_node;
+ Node_format node;
+ Node_format tocheck_node;
node.ip_port = source;
memcpy(node.public_key, source_pubkey, CRYPTO_PUBLIC_KEY_SIZE);
memcpy(&tocheck_node, packet + 1, sizeof(Node_format));
@@ -2444,7 +2447,7 @@ static int handle_hardening(void *object, IP_Port source, const uint8_t *source_
length_nodes, 0);
/* TODO(irungentoo): MAX_SENT_NODES nodes should be returned at all times
- (right now we have a small network size so it could cause problems for testing and etc..) */
+ * (right now we have a small network size so it could cause problems for testing and etc..) */
if (num_nodes <= 0) {
return 1;
}
@@ -2508,7 +2511,7 @@ static Node_format random_node(DHT *dht, Family sa_family)
*
* return the number of nodes.
*/
-static uint16_t list_nodes(Client_data *list, size_t length, const Mono_Time *mono_time, Node_format *nodes,
+static uint16_t list_nodes(Client_data *list, size_t length, uint64_t cur_time, Node_format *nodes,
uint16_t max_num)
{
if (max_num == 0) {
@@ -2520,11 +2523,11 @@ static uint16_t list_nodes(Client_data *list, size_t length, const Mono_Time *mo
for (size_t i = length; i != 0; --i) {
const IPPTsPng *assoc = nullptr;
- if (!assoc_timeout(mono_time, &list[i - 1].assoc4)) {
+ if (!assoc_timeout(cur_time, &list[i - 1].assoc4)) {
assoc = &list[i - 1].assoc4;
}
- if (!assoc_timeout(mono_time, &list[i - 1].assoc6)) {
+ if (!assoc_timeout(cur_time, &list[i - 1].assoc6)) {
if (assoc == nullptr) {
assoc = &list[i - 1].assoc6;
} else if (random_u08() % 2) {
@@ -2560,7 +2563,7 @@ uint16_t randfriends_nodes(DHT *dht, Node_format *nodes, uint16_t max_num)
const uint32_t r = random_u32();
for (size_t i = 0; i < DHT_FAKE_FRIEND_NUMBER; ++i) {
- count += list_nodes(dht->friends_list[(i + r) % DHT_FAKE_FRIEND_NUMBER].client_list, MAX_FRIEND_CLIENTS, dht->mono_time,
+ count += list_nodes(dht->friends_list[(i + r) % DHT_FAKE_FRIEND_NUMBER].client_list, MAX_FRIEND_CLIENTS, dht->last_run,
nodes + count, max_num - count);
if (count >= max_num) {
@@ -2577,7 +2580,7 @@ uint16_t randfriends_nodes(DHT *dht, Node_format *nodes, uint16_t max_num)
*/
uint16_t closelist_nodes(DHT *dht, Node_format *nodes, uint16_t max_num)
{
- return list_nodes(dht->close_clientlist, LCLIENT_LIST, dht->mono_time, nodes, max_num);
+ return list_nodes(dht->close_clientlist, LCLIENT_LIST, dht->last_run, nodes, max_num);
}
#if DHT_HARDENING
@@ -2698,6 +2701,7 @@ DHT *new_dht(const Logger *log, Mono_Time *mono_time, Networking_Core *net, bool
}
dht->mono_time = mono_time;
+ dht->last_run = mono_time_get(mono_time);
dht->log = log;
dht->net = net;
@@ -2743,10 +2747,14 @@ DHT *new_dht(const Logger *log, Mono_Time *mono_time, Networking_Core *net, bool
void do_dht(DHT *dht)
{
- if (dht->last_run == mono_time_get(dht->mono_time)) {
+ const uint64_t cur_time = mono_time_get(dht->mono_time);
+
+ if (dht->last_run == cur_time) {
return;
}
+ dht->last_run = cur_time;
+
// Load friends/clients if first call to do_dht
if (dht->loaded_num_nodes) {
dht_connect_after_load(dht);
@@ -2759,7 +2767,6 @@ void do_dht(DHT *dht)
#if DHT_HARDENING
do_hardening(dht);
#endif
- dht->last_run = mono_time_get(dht->mono_time);
}
void kill_dht(DHT *dht)
@@ -2827,7 +2834,12 @@ void dht_save(const DHT *dht, uint8_t *data)
/* get right offset. we write the actual header later. */
data = state_write_section_header(data, DHT_STATE_COOKIE_TYPE, 0, 0);
- Node_format clients[MAX_SAVED_DHT_NODES];
+ Node_format *clients = (Node_format *)malloc(MAX_SAVED_DHT_NODES * sizeof(Node_format));
+
+ if (clients == nullptr) {
+ LOGGER_ERROR(dht->log, "could not allocate %u nodes", MAX_SAVED_DHT_NODES);
+ return;
+ }
uint32_t num = 0;
@@ -2870,6 +2882,8 @@ void dht_save(const DHT *dht, uint8_t *data)
state_write_section_header(old_data, DHT_STATE_COOKIE_TYPE, pack_nodes(data, sizeof(Node_format) * num, clients, num),
DHT_STATE_TYPE_NODES);
+
+ free(clients);
}
/* Bootstrap from this number of nodes every time dht_connect_after_load() is called */
@@ -2917,6 +2931,12 @@ static State_Load_Status dht_load_state_callback(void *outer, const uint8_t *dat
// Copy to loaded_clients_list
dht->loaded_nodes_list = (Node_format *)calloc(MAX_SAVED_DHT_NODES, sizeof(Node_format));
+ if (dht->loaded_nodes_list == nullptr) {
+ LOGGER_ERROR(dht->log, "could not allocate %u nodes", MAX_SAVED_DHT_NODES);
+ dht->loaded_num_nodes = 0;
+ break;
+ }
+
const int num = unpack_nodes(dht->loaded_nodes_list, MAX_SAVED_DHT_NODES, nullptr, data, length, 0);
if (num > 0) {
@@ -2967,8 +2987,8 @@ bool dht_isconnected(const DHT *dht)
for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
const Client_data *const client = &dht->close_clientlist[i];
- if (!assoc_timeout(dht->mono_time, &client->assoc4) ||
- !assoc_timeout(dht->mono_time, &client->assoc6)) {
+ if (!assoc_timeout(dht->last_run, &client->assoc4) ||
+ !assoc_timeout(dht->last_run, &client->assoc6)) {
return true;
}
}
@@ -2984,12 +3004,12 @@ bool dht_non_lan_connected(const DHT *dht)
for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
const Client_data *const client = &dht->close_clientlist[i];
- if (!assoc_timeout(dht->mono_time, &client->assoc4)
+ if (!assoc_timeout(dht->last_run, &client->assoc4)
&& !ip_is_lan(client->assoc4.ip_port.ip)) {
return true;
}
- if (!assoc_timeout(dht->mono_time, &client->assoc6)
+ if (!assoc_timeout(dht->last_run, &client->assoc6)
&& !ip_is_lan(client->assoc6.ip_port.ip)) {
return true;
}