mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
tox.*, DHT.*;
- second set of *_bootstrap_ex() functions to allow addresses instead of IPs network.h: - new message ID for sending/receiving IPv6 nodes DHT.*: - get_close_nodes(): - additional parameter to select which kind of nodes: IPv4 or IPv6 - sendnodes()/handle_sendnodes(): - the IPv4 message must remain intact even when the Node_format structure (which embeds IP_Port) is expanded - added Node4_format to keep the structure "alive" - copying in/out of wider to smaller format required in sendnodes()/handle_sendnodes() - switch of Node_format from Node4_format to Node46_format by define
This commit is contained in:
parent
9a8dc575b7
commit
a77253c79b
121
toxcore/DHT.c
121
toxcore/DHT.c
|
@ -197,18 +197,37 @@ static int friend_number(DHT *dht, uint8_t *client_id)
|
||||||
*
|
*
|
||||||
* TODO: For the love of based Allah make this function cleaner and much more efficient.
|
* TODO: For the love of based Allah make this function cleaner and much more efficient.
|
||||||
*/
|
*/
|
||||||
static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list)
|
static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family)
|
||||||
{
|
{
|
||||||
uint32_t i, j, k;
|
uint32_t i, j, k;
|
||||||
uint64_t temp_time = unix_time();
|
uint64_t temp_time = unix_time();
|
||||||
int num_nodes = 0, closest, tout, inlist;
|
int num_nodes = 0, closest, tout, inlist, ipv46x;
|
||||||
|
|
||||||
for (i = 0; i < LCLIENT_LIST; ++i) {
|
for (i = 0; i < LCLIENT_LIST; ++i) {
|
||||||
tout = is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT);
|
tout = is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT);
|
||||||
inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, dht->close_clientlist[i].client_id);
|
inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, dht->close_clientlist[i].client_id);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NET_PACKET_SEND_NODES sends ONLY AF_INET
|
||||||
|
* NET_PACKET_SEND_NODES_EX sends ALL BUT AF_INET (i.e. AF_INET6),
|
||||||
|
* it could send both, but then a) packet size is an issue and
|
||||||
|
* b) duplicates the traffic (NET_PACKET_SEND_NODES has to be
|
||||||
|
* sent anyways for backwards compatibility)
|
||||||
|
* we COULD send ALL as NET_PACKET_SEND_NODES_EX if we KNEW that the
|
||||||
|
* partner node understands - that's true if *they* are on IPv6
|
||||||
|
*/
|
||||||
|
#ifdef NETWORK_IP_PORT_IS_IPV6
|
||||||
|
ipv46x = 0;
|
||||||
|
if (sa_family == AF_INET)
|
||||||
|
ipv46x = dht->close_clientlist[i].ip_port.ip.family != AF_INET;
|
||||||
|
else
|
||||||
|
ipv46x = dht->close_clientlist[i].ip_port.ip.family == AF_INET;
|
||||||
|
#else
|
||||||
|
ipv46x = sa_family != AF_INET;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* If node isn't good or is already in list. */
|
/* If node isn't good or is already in list. */
|
||||||
if (tout || inlist)
|
if (tout || inlist || ipv46x)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (num_nodes < MAX_SENT_NODES) {
|
if (num_nodes < MAX_SENT_NODES) {
|
||||||
|
@ -247,8 +266,18 @@ static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list
|
||||||
MAX_SENT_NODES,
|
MAX_SENT_NODES,
|
||||||
dht->friends_list[i].client_list[j].client_id);
|
dht->friends_list[i].client_list[j].client_id);
|
||||||
|
|
||||||
|
#ifdef NETWORK_IP_PORT_IS_IPV6
|
||||||
|
ipv46x = 0;
|
||||||
|
if (sa_family == AF_INET)
|
||||||
|
ipv46x = dht->friends_list[i].client_list[j].ip_port.ip.family != AF_INET;
|
||||||
|
else
|
||||||
|
ipv46x = dht->friends_list[i].client_list[j].ip_port.ip.family == AF_INET;
|
||||||
|
#else
|
||||||
|
ipv46x = sa_family != AF_INET;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* If node isn't good or is already in list. */
|
/* If node isn't good or is already in list. */
|
||||||
if (tout || inlist)
|
if (tout || inlist || ipv46x)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (num_nodes < MAX_SENT_NODES) {
|
if (num_nodes < MAX_SENT_NODES) {
|
||||||
|
@ -522,40 +551,61 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send a send nodes response. */
|
/* Send a send nodes response. */
|
||||||
|
/* because of BINARY compatibility, the Node_format MUST BE Node4_format,
|
||||||
|
* IPv6 nodes are sent in a different message */
|
||||||
static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id)
|
static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id)
|
||||||
{
|
{
|
||||||
/* Check if packet is going to be sent to ourself. */
|
/* Check if packet is going to be sent to ourself. */
|
||||||
if (id_equal(public_key, dht->c->self_public_key))
|
if (id_equal(public_key, dht->c->self_public_key))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
size_t Node4_format_size = sizeof(Node4_format);
|
||||||
uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id)
|
uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id)
|
||||||
+ sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING];
|
+ Node4_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING];
|
||||||
|
|
||||||
Node_format nodes_list[MAX_SENT_NODES];
|
Node_format nodes_list[MAX_SENT_NODES];
|
||||||
int num_nodes = get_close_nodes(dht, client_id, nodes_list);
|
int num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET);
|
||||||
|
|
||||||
if (num_nodes == 0)
|
if (num_nodes == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES];
|
uint8_t plain[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES];
|
||||||
uint8_t encrypt[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING];
|
uint8_t encrypt[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING];
|
||||||
uint8_t nonce[crypto_box_NONCEBYTES];
|
uint8_t nonce[crypto_box_NONCEBYTES];
|
||||||
random_nonce(nonce);
|
random_nonce(nonce);
|
||||||
|
|
||||||
memcpy(plain, &ping_id, sizeof(ping_id));
|
memcpy(plain, &ping_id, sizeof(ping_id));
|
||||||
memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * sizeof(Node_format));
|
#if DHT_NODEFORMAT == 46
|
||||||
|
Node4_format *nodes4_list = &(plain + sizeof(ping_id));
|
||||||
|
int i, num_nodes_ok = 0;
|
||||||
|
for(i = 0; i < num_nodes, i++)
|
||||||
|
if (nodes_list[i].ip.family == AF_INET) {
|
||||||
|
memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE);
|
||||||
|
nodes4_list[num_nodes_ok].ip_port.ip.uint32 = nodes_list[i].ip_port.ip.ip4.uint32;
|
||||||
|
nodes4_list[num_nodes_ok].ip_port.port = nodes_list[i].ip_port.port;
|
||||||
|
|
||||||
|
num_nodes_ok++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_nodes_ok < num_nodes) {
|
||||||
|
/* shouldn't happen */
|
||||||
|
num_nodes = num_nodes_ok;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * Node4_format_size);
|
||||||
|
#endif
|
||||||
|
|
||||||
int len = encrypt_data( public_key,
|
int len = encrypt_data( public_key,
|
||||||
dht->c->self_secret_key,
|
dht->c->self_secret_key,
|
||||||
nonce,
|
nonce,
|
||||||
plain,
|
plain,
|
||||||
sizeof(ping_id) + num_nodes * sizeof(Node_format),
|
sizeof(ping_id) + num_nodes * Node4_format_size,
|
||||||
encrypt );
|
encrypt );
|
||||||
|
|
||||||
if (len == -1)
|
if (len == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if ((unsigned int)len != sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING)
|
if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node4_format_size + ENCRYPTION_PADDING)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
data[0] = NET_PACKET_SEND_NODES;
|
data[0] = NET_PACKET_SEND_NODES;
|
||||||
|
@ -606,22 +656,23 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3
|
||||||
uint32_t cid_size = 1 + CLIENT_ID_SIZE;
|
uint32_t cid_size = 1 + CLIENT_ID_SIZE;
|
||||||
cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING;
|
cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING;
|
||||||
|
|
||||||
if (length > (cid_size + sizeof(Node_format) * MAX_SENT_NODES) ||
|
size_t Node4_format_size = sizeof(Node4_format);
|
||||||
((length - cid_size) % sizeof(Node_format)) != 0 ||
|
if (length > (cid_size + Node4_format_size * MAX_SENT_NODES) ||
|
||||||
(length < cid_size + sizeof(Node_format)))
|
((length - cid_size) % Node4_format_size) != 0 ||
|
||||||
|
(length < cid_size + Node4_format_size))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
uint32_t num_nodes = (length - cid_size) / sizeof(Node_format);
|
uint32_t num_nodes = (length - cid_size) / Node4_format_size;
|
||||||
uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES];
|
uint8_t plain[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES];
|
||||||
|
|
||||||
int len = decrypt_data(
|
int len = decrypt_data(
|
||||||
packet + 1,
|
packet + 1,
|
||||||
dht->c->self_secret_key,
|
dht->c->self_secret_key,
|
||||||
packet + 1 + CLIENT_ID_SIZE,
|
packet + 1 + CLIENT_ID_SIZE,
|
||||||
packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
|
packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
|
||||||
sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING, plain );
|
sizeof(ping_id) + num_nodes * Node4_format_size + ENCRYPTION_PADDING, plain );
|
||||||
|
|
||||||
if ((unsigned int)len != sizeof(ping_id) + num_nodes * sizeof(Node_format))
|
if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node4_format_size)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
memcpy(&ping_id, plain, sizeof(ping_id));
|
memcpy(&ping_id, plain, sizeof(ping_id));
|
||||||
|
@ -630,7 +681,28 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
Node_format nodes_list[MAX_SENT_NODES];
|
Node_format nodes_list[MAX_SENT_NODES];
|
||||||
|
|
||||||
|
#if DHT_NODEFORMAT == 46
|
||||||
|
Node4_format *nodes4_list = &(plain + sizeof(ping_id));
|
||||||
|
|
||||||
|
int i, num_nodes_ok = 0;
|
||||||
|
for(i = 0; i < num_nodes, i++)
|
||||||
|
if ((nodes_list[i].ip != 0) && (nodes_list[i].ip != ~0)) {
|
||||||
|
memcpy(nodes_list[num_nodes_ok].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE);
|
||||||
|
nodes_list[num_nodes_ok].ip_port.ip.family = AF_INET;
|
||||||
|
nodes_list[num_nodes_ok].ip_port.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32;
|
||||||
|
nodes_list[num_nodes_ok].ip_port.port = nodes4_list[i].ip_port.port;
|
||||||
|
|
||||||
|
num_nodes_ok++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_nodes_ok < num_nodes) {
|
||||||
|
/* shouldn't happen */
|
||||||
|
num_nodes = num_nodes_ok;
|
||||||
|
}
|
||||||
|
#else
|
||||||
memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format));
|
memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format));
|
||||||
|
#endif
|
||||||
|
|
||||||
addto_lists(dht, source, packet + 1);
|
addto_lists(dht, source, packet + 1);
|
||||||
|
|
||||||
|
@ -808,6 +880,19 @@ void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key)
|
||||||
getnodes(dht, ip_port, public_key, dht->c->self_public_key);
|
getnodes(dht, ip_port, public_key, dht->c->self_public_key);
|
||||||
send_ping_request(dht->ping, dht->c, ip_port, public_key);
|
send_ping_request(dht->ping, dht->c, ip_port, public_key);
|
||||||
}
|
}
|
||||||
|
void DHT_bootstrap_ex(DHT *dht, const char *address, uint16_t port, uint8_t *public_key)
|
||||||
|
{
|
||||||
|
IPAny_Port ipany_port;
|
||||||
|
ipany_port.ip.family = AF_INET;
|
||||||
|
if (addr_resolve_or_parse_ip(address, &ipany_port.ip)) {
|
||||||
|
/* IPAny temporary: copy down */
|
||||||
|
IP_Port ip_port;
|
||||||
|
ip_port.ip.uint32 = ipany_port.ip.ip4.uint32;
|
||||||
|
ip_port.port = port;
|
||||||
|
|
||||||
|
DHT_bootstrap(dht, ip_port, public_key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Send the given packet to node with client_id
|
/* Send the given packet to node with client_id
|
||||||
*
|
*
|
||||||
|
|
|
@ -75,10 +75,21 @@ typedef struct {
|
||||||
uint64_t NATping_timestamp;
|
uint64_t NATping_timestamp;
|
||||||
} DHT_Friend;
|
} DHT_Friend;
|
||||||
|
|
||||||
|
/* this must be kept even if IP_Port is expanded: wire compatibility */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t client_id[CLIENT_ID_SIZE];
|
uint8_t client_id[CLIENT_ID_SIZE];
|
||||||
IP_Port ip_port;
|
IP4_Port ip_port;
|
||||||
} Node_format;
|
} Node4_format;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t client_id[CLIENT_ID_SIZE];
|
||||||
|
IPAny_Port ip_port;
|
||||||
|
} Node46_format;
|
||||||
|
/* IPAny temporary: change to 46 */
|
||||||
|
#define DHT_NODEFORMAT 4
|
||||||
|
typedef Node4_format Node_format;
|
||||||
|
/* #define DHT_NODEFORMAT 46 */
|
||||||
|
/* typedef Node46_format Node_format; */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
IP_Port ip_port;
|
IP_Port ip_port;
|
||||||
|
@ -137,6 +148,7 @@ void do_DHT(DHT *dht);
|
||||||
* Sends a get nodes request to the given node with ip port and public_key.
|
* Sends a get nodes request to the given node with ip port and public_key.
|
||||||
*/
|
*/
|
||||||
void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key);
|
void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key);
|
||||||
|
void DHT_bootstrap_ex(DHT *dht, const char *address, uint16_t port, uint8_t *public_key);
|
||||||
|
|
||||||
/* Add nodes to the toping list.
|
/* Add nodes to the toping list.
|
||||||
* All nodes in this list are pinged every TIME_TOPING seconds
|
* All nodes in this list are pinged every TIME_TOPING seconds
|
||||||
|
|
|
@ -71,7 +71,8 @@ typedef int sock_t;
|
||||||
#define NET_PACKET_PING_REQUEST 0 /* Ping request packet ID. */
|
#define NET_PACKET_PING_REQUEST 0 /* Ping request packet ID. */
|
||||||
#define NET_PACKET_PING_RESPONSE 1 /* Ping response packet ID. */
|
#define NET_PACKET_PING_RESPONSE 1 /* Ping response packet ID. */
|
||||||
#define NET_PACKET_GET_NODES 2 /* Get nodes request packet ID. */
|
#define NET_PACKET_GET_NODES 2 /* Get nodes request packet ID. */
|
||||||
#define NET_PACKET_SEND_NODES 3 /* Send nodes response packet ID. */
|
#define NET_PACKET_SEND_NODES 3 /* Send nodes response packet ID for IPv4 addresses. */
|
||||||
|
#define NET_PACKET_SEND_NODES_EX 4 /* Send nodes response packet ID for other addresses. */
|
||||||
#define NET_PACKET_HANDSHAKE 16 /* Handshake packet ID. */
|
#define NET_PACKET_HANDSHAKE 16 /* Handshake packet ID. */
|
||||||
#define NET_PACKET_SYNC 17 /* SYNC packet ID. */
|
#define NET_PACKET_SYNC 17 /* SYNC packet ID. */
|
||||||
#define NET_PACKET_DATA 18 /* Data packet ID. */
|
#define NET_PACKET_DATA 18 /* Data packet ID. */
|
||||||
|
@ -114,8 +115,7 @@ typedef union {
|
||||||
uint16_t padding;
|
uint16_t padding;
|
||||||
};
|
};
|
||||||
uint8_t uint8[8];
|
uint8_t uint8[8];
|
||||||
} IP_Port;
|
} IP4_Port;
|
||||||
|
|
||||||
|
|
||||||
/* will replace IP_Port as soon as the complete infrastructure is in place
|
/* will replace IP_Port as soon as the complete infrastructure is in place
|
||||||
* removed the unused union and padding also */
|
* removed the unused union and padding also */
|
||||||
|
@ -124,6 +124,12 @@ typedef struct {
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
} IPAny_Port;
|
} IPAny_Port;
|
||||||
|
|
||||||
|
#ifdef NETWORK_IP_PORT_IS_IPV6
|
||||||
|
typedef IPAny_Port IP_Port;
|
||||||
|
#else
|
||||||
|
typedef IP4_Port IP_Port;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ipport_equal
|
/* ipport_equal
|
||||||
* compares two IPAny_Port structures
|
* compares two IPAny_Port structures
|
||||||
* unset means unequal
|
* unset means unequal
|
||||||
|
|
|
@ -374,6 +374,11 @@ void tox_bootstrap(void *tox, IP_Port ip_port, uint8_t *public_key)
|
||||||
Messenger *m = tox;
|
Messenger *m = tox;
|
||||||
DHT_bootstrap(m->dht, ip_port, public_key);
|
DHT_bootstrap(m->dht, ip_port, public_key);
|
||||||
}
|
}
|
||||||
|
void tox_bootstrap_ex(void *tox, const char *address, uint16_t port, uint8_t *public_key)
|
||||||
|
{
|
||||||
|
Messenger *m = tox;
|
||||||
|
DHT_bootstrap_ex(m->dht, address, port, public_key);
|
||||||
|
};
|
||||||
|
|
||||||
/* return 0 if we are not connected to the DHT.
|
/* return 0 if we are not connected to the DHT.
|
||||||
* return 1 if we are.
|
* return 1 if we are.
|
||||||
|
|
|
@ -291,8 +291,10 @@ void tox_callback_connectionstatus(Tox *tox, void (*function)(Tox *tox, int, uin
|
||||||
|
|
||||||
/* Use this function to bootstrap the client.
|
/* Use this function to bootstrap the client.
|
||||||
* Sends a get nodes request to the given node with ip port and public_key.
|
* Sends a get nodes request to the given node with ip port and public_key.
|
||||||
|
* tox_bootstrap_ex converts the address into an IP_Port structure internally
|
||||||
*/
|
*/
|
||||||
void tox_bootstrap(Tox *tox, tox_IP_Port ip_port, uint8_t *public_key);
|
void tox_bootstrap(Tox *tox, tox_IP_Port ip_port, uint8_t *public_key);
|
||||||
|
void tox_bootstrap_ex(Tox *tox, const char *address, uint16_t port, uint8_t *public_key);
|
||||||
|
|
||||||
/* return 0 if we are not connected to the DHT.
|
/* return 0 if we are not connected to the DHT.
|
||||||
* return 1 if we are.
|
* return 1 if we are.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user