diff --git a/toxcore/DHT.c b/toxcore/DHT.c index ae1ef8b1..3b7d2da5 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -1253,37 +1253,7 @@ int DHT_addfriend(DHT *dht, const uint8_t *public_key, void (*ip_callback)(void if (lock_count) *lock_count = lock_num + 1; -#ifdef ENABLE_ASSOC_DHT - - if (dht->assoc) { - /* get up to MAX_FRIEND_CLIENTS connectable nodes */ - DHT_Friend *friend = &dht->friends_list[dht->num_friends - 1]; - - Assoc_close_entries close_entries; - memset(&close_entries, 0, sizeof(close_entries)); - close_entries.wanted_id = public_key; - close_entries.count_good = MAX_FRIEND_CLIENTS / 2; - close_entries.count = MAX_FRIEND_CLIENTS; - close_entries.result = calloc(MAX_FRIEND_CLIENTS, sizeof(*close_entries.result)); - - uint8_t i, found = Assoc_get_close_entries(dht->assoc, &close_entries); - - for (i = 0; i < found; i++) - memcpy(&friend->client_list[i], close_entries.result[i], sizeof(*close_entries.result[i])); - - if (found) { - /* send getnodes to the "best" entry */ - Client_data *client = &friend->client_list[0]; - - if (ipport_isset(&client->assoc4.ip_port)) - getnodes(dht, client->assoc4.ip_port, client->public_key, friend->public_key, NULL); - - if (ipport_isset(&client->assoc6.ip_port)) - getnodes(dht, client->assoc6.ip_port, client->public_key, friend->public_key, NULL); - } - } - -#endif + friend->num_to_bootstrap = get_close_nodes(dht, friend->public_key, friend->to_bootstrap, 0, 1, 0); return 0; } @@ -1464,11 +1434,20 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co */ static void do_DHT_friends(DHT *dht) { - uint32_t i; + unsigned int i, j; - for (i = 0; i < dht->num_friends; ++i) - do_ping_and_sendnode_requests(dht, &dht->friends_list[i].lastgetnode, dht->friends_list[i].public_key, - dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, &dht->friends_list[i].bootstrap_times); + for (i = 0; i < dht->num_friends; ++i) { + DHT_Friend *friend = &dht->friends_list[i]; + + for (j = 0; j < friend->num_to_bootstrap; ++j) { + getnodes(dht, friend->to_bootstrap[j].ip_port, friend->to_bootstrap[j].public_key, friend->public_key, NULL); + } + + friend->num_to_bootstrap = 0; + + do_ping_and_sendnode_requests(dht, &friend->lastgetnode, friend->public_key, friend->client_list, MAX_FRIEND_CLIENTS, + &friend->bootstrap_times); + } } /* Ping each client in the close nodes list every PING_INTERVAL seconds. @@ -2151,17 +2130,16 @@ Node_format random_node(DHT *dht, sa_family_t sa_family) * * return the number of nodes. */ -uint16_t closelist_nodes(DHT *dht, Node_format *nodes, uint16_t max_num) +uint16_t list_nodes(Client_data *list, unsigned int length, Node_format *nodes, uint16_t max_num) { if (max_num == 0) return 0; uint16_t count = 0; - Client_data *list = dht->close_clientlist; - uint32_t i; + unsigned int i; - for (i = LCLIENT_LIST; i != 0; --i) { + for (i = length; i != 0; --i) { IPPTsPng *assoc = NULL; if (!is_timeout(list[i - 1].assoc4.timestamp, BAD_NODE_TIMEOUT)) @@ -2187,6 +2165,38 @@ uint16_t closelist_nodes(DHT *dht, Node_format *nodes, uint16_t max_num) return count; } +/* Put up to max_num nodes in nodes from the random friends. + * + * return the number of nodes. + */ +uint16_t randfriends_nodes(DHT *dht, Node_format *nodes, uint16_t max_num) +{ + if (max_num == 0) + return 0; + + uint16_t count = 0; + unsigned int i, r = rand(); + + for (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, nodes + count, + max_num - count); + + if (count >= max_num) + break; + } + + return count; +} + +/* Put up to max_num nodes in nodes from the closelist. + * + * return the number of nodes. + */ +uint16_t closelist_nodes(DHT *dht, Node_format *nodes, uint16_t max_num) +{ + return list_nodes(dht->close_clientlist, LCLIENT_LIST, nodes, max_num); +} + void do_hardening(DHT *dht) { uint32_t i; @@ -2321,7 +2331,11 @@ DHT *new_DHT(Networking_Core *net) for (i = 0; i < DHT_FAKE_FRIEND_NUMBER; ++i) { uint8_t random_key_bytes[crypto_box_PUBLICKEYBYTES]; randombytes(random_key_bytes, sizeof(random_key_bytes)); - DHT_addfriend(dht, random_key_bytes, 0, 0, 0, 0); + + if (DHT_addfriend(dht, random_key_bytes, 0, 0, 0, 0) != 0) { + kill_DHT(dht); + return NULL; + } } return dht; diff --git a/toxcore/DHT.h b/toxcore/DHT.h index 50ab92dc..c83ca073 100644 --- a/toxcore/DHT.h +++ b/toxcore/DHT.h @@ -123,6 +123,12 @@ typedef struct { #define DHT_FRIEND_MAX_LOCKS 32 +typedef struct { + uint8_t public_key[crypto_box_PUBLICKEYBYTES]; + IP_Port ip_port; +} +Node_format; + typedef struct { uint8_t public_key[crypto_box_PUBLICKEYBYTES]; Client_data client_list[MAX_FRIEND_CLIENTS]; @@ -142,14 +148,10 @@ typedef struct { int32_t number; } callbacks[DHT_FRIEND_MAX_LOCKS]; + Node_format to_bootstrap[MAX_SENT_NODES]; + unsigned int num_to_bootstrap; } DHT_Friend; -typedef struct { - uint8_t public_key[crypto_box_PUBLICKEYBYTES]; - IP_Port ip_port; -} -Node_format; - /* Return packet size of packed node with ip_family on success. * Return -1 on failure. */ @@ -311,6 +313,12 @@ int get_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *node uint8_t is_LAN, uint8_t want_good); +/* Put up to max_num nodes in nodes from the random friends. + * + * return the number of nodes. + */ +uint16_t randfriends_nodes(DHT *dht, Node_format *nodes, uint16_t max_num); + /* Put up to max_num nodes in nodes from the closelist. * * return the number of nodes. diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 61378fd0..11a7b629 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -1209,16 +1209,14 @@ int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_on static void populate_path_nodes(Onion_Client *onion_c) { - Node_format nodes_list[MAX_SENT_NODES]; - uint8_t public_key[crypto_box_PUBLICKEYBYTES]; - uint32_t random_num = rand(); - memcpy(public_key, &random_num, sizeof(random_num)); + Node_format nodes_list[MAX_FRIEND_CLIENTS]; + + unsigned int num_nodes = randfriends_nodes(onion_c->dht, nodes_list, MAX_FRIEND_CLIENTS); - unsigned int num_nodes = get_close_nodes(onion_c->dht, public_key, nodes_list, (rand() % 2) ? AF_INET : AF_INET6, 1, 0); unsigned int i; for (i = 0; i < num_nodes; ++i) { - onion_add_path_node(onion_c, nodes_list[i].ip_port, nodes_list[i].public_key); + int r = onion_add_path_node(onion_c, nodes_list[i].ip_port, nodes_list[i].public_key); } } @@ -1415,7 +1413,7 @@ static int onion_isconnected(const Onion_Client *onion_c) return 0; } -#define ONION_CONNECTION_SECONDS 2 +#define ONION_CONNECTION_SECONDS 3 /* return 0 if we are not connected to the network. * return 1 if we are connected with TCP only. @@ -1441,8 +1439,6 @@ void do_onion_client(Onion_Client *onion_c) if (onion_c->last_run == unix_time()) return; - populate_path_nodes(onion_c); - do_announce(onion_c); if (onion_isconnected(onion_c)) { @@ -1461,6 +1457,7 @@ void do_onion_client(Onion_Client *onion_c) _Bool UDP_connected = DHT_non_lan_connected(onion_c->dht); if (is_timeout(onion_c->first_run, ONION_CONNECTION_SECONDS)) { + populate_path_nodes(onion_c); set_tcp_onion_status(onion_c->c->tcp_c, !UDP_connected); }