DHT improvements.

Feed better nodes to onion, bootstrap off close clients when DHT friend is added.
This commit is contained in:
irungentoo 2015-12-11 16:48:10 -05:00
parent ae801b3257
commit 22b1ebb46e
No known key found for this signature in database
GPG Key ID: 10349DC9BED89E98
3 changed files with 74 additions and 55 deletions

View File

@ -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;

View File

@ -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.

View File

@ -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);
}