summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--toxcore/DHT.c121
-rw-r--r--toxcore/DHT.h24
-rw-r--r--toxcore/network.h12
-rw-r--r--toxcore/tox.c5
-rw-r--r--toxcore/tox.h2
5 files changed, 137 insertions, 27 deletions
diff --git a/toxcore/DHT.c b/toxcore/DHT.c
index 151f59d3..4c15c1eb 100644
--- a/toxcore/DHT.c
+++ b/toxcore/DHT.c
@@ -197,18 +197,37 @@ static int friend_number(DHT *dht, uint8_t *client_id)
197 * 197 *
198 * TODO: For the love of based Allah make this function cleaner and much more efficient. 198 * TODO: For the love of based Allah make this function cleaner and much more efficient.
199 */ 199 */
200static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list) 200static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family)
201{ 201{
202 uint32_t i, j, k; 202 uint32_t i, j, k;
203 uint64_t temp_time = unix_time(); 203 uint64_t temp_time = unix_time();
204 int num_nodes = 0, closest, tout, inlist; 204 int num_nodes = 0, closest, tout, inlist, ipv46x;
205 205
206 for (i = 0; i < LCLIENT_LIST; ++i) { 206 for (i = 0; i < LCLIENT_LIST; ++i) {
207 tout = is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT); 207 tout = is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT);
208 inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, dht->close_clientlist[i].client_id); 208 inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, dht->close_clientlist[i].client_id);
209 209
210 /*
211 * NET_PACKET_SEND_NODES sends ONLY AF_INET
212 * NET_PACKET_SEND_NODES_EX sends ALL BUT AF_INET (i.e. AF_INET6),
213 * it could send both, but then a) packet size is an issue and
214 * b) duplicates the traffic (NET_PACKET_SEND_NODES has to be
215 * sent anyways for backwards compatibility)
216 * we COULD send ALL as NET_PACKET_SEND_NODES_EX if we KNEW that the
217 * partner node understands - that's true if *they* are on IPv6
218 */
219#ifdef NETWORK_IP_PORT_IS_IPV6
220 ipv46x = 0;
221 if (sa_family == AF_INET)
222 ipv46x = dht->close_clientlist[i].ip_port.ip.family != AF_INET;
223 else
224 ipv46x = dht->close_clientlist[i].ip_port.ip.family == AF_INET;
225#else
226 ipv46x = sa_family != AF_INET;
227#endif
228
210 /* If node isn't good or is already in list. */ 229 /* If node isn't good or is already in list. */
211 if (tout || inlist) 230 if (tout || inlist || ipv46x)
212 continue; 231 continue;
213 232
214 if (num_nodes < MAX_SENT_NODES) { 233 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
247 MAX_SENT_NODES, 266 MAX_SENT_NODES,
248 dht->friends_list[i].client_list[j].client_id); 267 dht->friends_list[i].client_list[j].client_id);
249 268
269#ifdef NETWORK_IP_PORT_IS_IPV6
270 ipv46x = 0;
271 if (sa_family == AF_INET)
272 ipv46x = dht->friends_list[i].client_list[j].ip_port.ip.family != AF_INET;
273 else
274 ipv46x = dht->friends_list[i].client_list[j].ip_port.ip.family == AF_INET;
275#else
276 ipv46x = sa_family != AF_INET;
277#endif
278
250 /* If node isn't good or is already in list. */ 279 /* If node isn't good or is already in list. */
251 if (tout || inlist) 280 if (tout || inlist || ipv46x)
252 continue; 281 continue;
253 282
254 if (num_nodes < MAX_SENT_NODES) { 283 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
522} 551}
523 552
524/* Send a send nodes response. */ 553/* Send a send nodes response. */
554/* because of BINARY compatibility, the Node_format MUST BE Node4_format,
555 * IPv6 nodes are sent in a different message */
525static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id) 556static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id)
526{ 557{
527 /* Check if packet is going to be sent to ourself. */ 558 /* Check if packet is going to be sent to ourself. */
528 if (id_equal(public_key, dht->c->self_public_key)) 559 if (id_equal(public_key, dht->c->self_public_key))
529 return -1; 560 return -1;
530 561
562 size_t Node4_format_size = sizeof(Node4_format);
531 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) 563 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id)
532 + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING]; 564 + Node4_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING];
533 565
534 Node_format nodes_list[MAX_SENT_NODES]; 566 Node_format nodes_list[MAX_SENT_NODES];
535 int num_nodes = get_close_nodes(dht, client_id, nodes_list); 567 int num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET);
536 568
537 if (num_nodes == 0) 569 if (num_nodes == 0)
538 return 0; 570 return 0;
539 571
540 uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES]; 572 uint8_t plain[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES];
541 uint8_t encrypt[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING]; 573 uint8_t encrypt[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING];
542 uint8_t nonce[crypto_box_NONCEBYTES]; 574 uint8_t nonce[crypto_box_NONCEBYTES];
543 random_nonce(nonce); 575 random_nonce(nonce);
544 576
545 memcpy(plain, &ping_id, sizeof(ping_id)); 577 memcpy(plain, &ping_id, sizeof(ping_id));
546 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * sizeof(Node_format)); 578#if DHT_NODEFORMAT == 46
579 Node4_format *nodes4_list = &(plain + sizeof(ping_id));
580 int i, num_nodes_ok = 0;
581 for(i = 0; i < num_nodes, i++)
582 if (nodes_list[i].ip.family == AF_INET) {
583 memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE);
584 nodes4_list[num_nodes_ok].ip_port.ip.uint32 = nodes_list[i].ip_port.ip.ip4.uint32;
585 nodes4_list[num_nodes_ok].ip_port.port = nodes_list[i].ip_port.port;
586
587 num_nodes_ok++;
588 }
589
590 if (num_nodes_ok < num_nodes) {
591 /* shouldn't happen */
592 num_nodes = num_nodes_ok;
593 }
594#else
595 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * Node4_format_size);
596#endif
547 597
548 int len = encrypt_data( public_key, 598 int len = encrypt_data( public_key,
549 dht->c->self_secret_key, 599 dht->c->self_secret_key,
550 nonce, 600 nonce,
551 plain, 601 plain,
552 sizeof(ping_id) + num_nodes * sizeof(Node_format), 602 sizeof(ping_id) + num_nodes * Node4_format_size,
553 encrypt ); 603 encrypt );
554 604
555 if (len == -1) 605 if (len == -1)
556 return -1; 606 return -1;
557 607
558 if ((unsigned int)len != sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING) 608 if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node4_format_size + ENCRYPTION_PADDING)
559 return -1; 609 return -1;
560 610
561 data[0] = NET_PACKET_SEND_NODES; 611 data[0] = NET_PACKET_SEND_NODES;
@@ -606,22 +656,23 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3
606 uint32_t cid_size = 1 + CLIENT_ID_SIZE; 656 uint32_t cid_size = 1 + CLIENT_ID_SIZE;
607 cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; 657 cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING;
608 658
609 if (length > (cid_size + sizeof(Node_format) * MAX_SENT_NODES) || 659 size_t Node4_format_size = sizeof(Node4_format);
610 ((length - cid_size) % sizeof(Node_format)) != 0 || 660 if (length > (cid_size + Node4_format_size * MAX_SENT_NODES) ||
611 (length < cid_size + sizeof(Node_format))) 661 ((length - cid_size) % Node4_format_size) != 0 ||
662 (length < cid_size + Node4_format_size))
612 return 1; 663 return 1;
613 664
614 uint32_t num_nodes = (length - cid_size) / sizeof(Node_format); 665 uint32_t num_nodes = (length - cid_size) / Node4_format_size;
615 uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES]; 666 uint8_t plain[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES];
616 667
617 int len = decrypt_data( 668 int len = decrypt_data(
618 packet + 1, 669 packet + 1,
619 dht->c->self_secret_key, 670 dht->c->self_secret_key,
620 packet + 1 + CLIENT_ID_SIZE, 671 packet + 1 + CLIENT_ID_SIZE,
621 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, 672 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
622 sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING, plain ); 673 sizeof(ping_id) + num_nodes * Node4_format_size + ENCRYPTION_PADDING, plain );
623 674
624 if ((unsigned int)len != sizeof(ping_id) + num_nodes * sizeof(Node_format)) 675 if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node4_format_size)
625 return 1; 676 return 1;
626 677
627 memcpy(&ping_id, plain, sizeof(ping_id)); 678 memcpy(&ping_id, plain, sizeof(ping_id));
@@ -630,7 +681,28 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3
630 return 1; 681 return 1;
631 682
632 Node_format nodes_list[MAX_SENT_NODES]; 683 Node_format nodes_list[MAX_SENT_NODES];
684
685#if DHT_NODEFORMAT == 46
686 Node4_format *nodes4_list = &(plain + sizeof(ping_id));
687
688 int i, num_nodes_ok = 0;
689 for(i = 0; i < num_nodes, i++)
690 if ((nodes_list[i].ip != 0) && (nodes_list[i].ip != ~0)) {
691 memcpy(nodes_list[num_nodes_ok].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE);
692 nodes_list[num_nodes_ok].ip_port.ip.family = AF_INET;
693 nodes_list[num_nodes_ok].ip_port.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32;
694 nodes_list[num_nodes_ok].ip_port.port = nodes4_list[i].ip_port.port;
695
696 num_nodes_ok++;
697 }
698
699 if (num_nodes_ok < num_nodes) {
700 /* shouldn't happen */
701 num_nodes = num_nodes_ok;
702 }
703#else
633 memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format)); 704 memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format));
705#endif
634 706
635 addto_lists(dht, source, packet + 1); 707 addto_lists(dht, source, packet + 1);
636 708
@@ -808,6 +880,19 @@ void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key)
808 getnodes(dht, ip_port, public_key, dht->c->self_public_key); 880 getnodes(dht, ip_port, public_key, dht->c->self_public_key);
809 send_ping_request(dht->ping, dht->c, ip_port, public_key); 881 send_ping_request(dht->ping, dht->c, ip_port, public_key);
810} 882}
883void DHT_bootstrap_ex(DHT *dht, const char *address, uint16_t port, uint8_t *public_key)
884{
885 IPAny_Port ipany_port;
886 ipany_port.ip.family = AF_INET;
887 if (addr_resolve_or_parse_ip(address, &ipany_port.ip)) {
888 /* IPAny temporary: copy down */
889 IP_Port ip_port;
890 ip_port.ip.uint32 = ipany_port.ip.ip4.uint32;
891 ip_port.port = port;
892
893 DHT_bootstrap(dht, ip_port, public_key);
894 }
895}
811 896
812/* Send the given packet to node with client_id 897/* Send the given packet to node with client_id
813 * 898 *
diff --git a/toxcore/DHT.h b/toxcore/DHT.h
index e5122b5e..5963d297 100644
--- a/toxcore/DHT.h
+++ b/toxcore/DHT.h
@@ -75,10 +75,21 @@ typedef struct {
75 uint64_t NATping_timestamp; 75 uint64_t NATping_timestamp;
76} DHT_Friend; 76} DHT_Friend;
77 77
78/* this must be kept even if IP_Port is expanded: wire compatibility */
78typedef struct { 79typedef struct {
79 uint8_t client_id[CLIENT_ID_SIZE]; 80 uint8_t client_id[CLIENT_ID_SIZE];
80 IP_Port ip_port; 81 IP4_Port ip_port;
81} Node_format; 82} Node4_format;
83
84typedef struct {
85 uint8_t client_id[CLIENT_ID_SIZE];
86 IPAny_Port ip_port;
87} Node46_format;
88/* IPAny temporary: change to 46 */
89#define DHT_NODEFORMAT 4
90typedef Node4_format Node_format;
91/* #define DHT_NODEFORMAT 46 */
92/* typedef Node46_format Node_format; */
82 93
83typedef struct { 94typedef struct {
84 IP_Port ip_port; 95 IP_Port ip_port;
@@ -88,15 +99,15 @@ typedef struct {
88 99
89/*----------------------------------------------------------------------------------*/ 100/*----------------------------------------------------------------------------------*/
90typedef struct { 101typedef struct {
91 Net_Crypto *c; 102 Net_Crypto *c;
92 Client_data close_clientlist[LCLIENT_LIST]; 103 Client_data close_clientlist[LCLIENT_LIST];
93 DHT_Friend *friends_list; 104 DHT_Friend *friends_list;
94 uint16_t num_friends; 105 uint16_t num_friends;
95 Pinged send_nodes[LSEND_NODES_ARRAY]; 106 Pinged send_nodes[LSEND_NODES_ARRAY];
96 Node_format toping[MAX_TOPING]; 107 Node_format toping[MAX_TOPING];
97 uint64_t last_toping; 108 uint64_t last_toping;
98 uint64_t close_lastgetnodes; 109 uint64_t close_lastgetnodes;
99 void *ping; 110 void *ping;
100} DHT; 111} DHT;
101/*----------------------------------------------------------------------------------*/ 112/*----------------------------------------------------------------------------------*/
102 113
@@ -137,6 +148,7 @@ void do_DHT(DHT *dht);
137 * Sends a get nodes request to the given node with ip port and public_key. 148 * Sends a get nodes request to the given node with ip port and public_key.
138 */ 149 */
139void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key); 150void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key);
151void DHT_bootstrap_ex(DHT *dht, const char *address, uint16_t port, uint8_t *public_key);
140 152
141/* Add nodes to the toping list. 153/* Add nodes to the toping list.
142 * All nodes in this list are pinged every TIME_TOPING seconds 154 * All nodes in this list are pinged every TIME_TOPING seconds
diff --git a/toxcore/network.h b/toxcore/network.h
index 1d2d1a4f..913763ee 100644
--- a/toxcore/network.h
+++ b/toxcore/network.h
@@ -71,7 +71,8 @@ typedef int sock_t;
71#define NET_PACKET_PING_REQUEST 0 /* Ping request packet ID. */ 71#define NET_PACKET_PING_REQUEST 0 /* Ping request packet ID. */
72#define NET_PACKET_PING_RESPONSE 1 /* Ping response packet ID. */ 72#define NET_PACKET_PING_RESPONSE 1 /* Ping response packet ID. */
73#define NET_PACKET_GET_NODES 2 /* Get nodes request packet ID. */ 73#define NET_PACKET_GET_NODES 2 /* Get nodes request packet ID. */
74#define NET_PACKET_SEND_NODES 3 /* Send nodes response packet ID. */ 74#define NET_PACKET_SEND_NODES 3 /* Send nodes response packet ID for IPv4 addresses. */
75#define NET_PACKET_SEND_NODES_EX 4 /* Send nodes response packet ID for other addresses. */
75#define NET_PACKET_HANDSHAKE 16 /* Handshake packet ID. */ 76#define NET_PACKET_HANDSHAKE 16 /* Handshake packet ID. */
76#define NET_PACKET_SYNC 17 /* SYNC packet ID. */ 77#define NET_PACKET_SYNC 17 /* SYNC packet ID. */
77#define NET_PACKET_DATA 18 /* Data packet ID. */ 78#define NET_PACKET_DATA 18 /* Data packet ID. */
@@ -114,8 +115,7 @@ typedef union {
114 uint16_t padding; 115 uint16_t padding;
115 }; 116 };
116 uint8_t uint8[8]; 117 uint8_t uint8[8];
117} IP_Port; 118} IP4_Port;
118
119 119
120/* will replace IP_Port as soon as the complete infrastructure is in place 120/* will replace IP_Port as soon as the complete infrastructure is in place
121 * removed the unused union and padding also */ 121 * removed the unused union and padding also */
@@ -124,6 +124,12 @@ typedef struct {
124 uint16_t port; 124 uint16_t port;
125} IPAny_Port; 125} IPAny_Port;
126 126
127#ifdef NETWORK_IP_PORT_IS_IPV6
128typedef IPAny_Port IP_Port;
129#else
130typedef IP4_Port IP_Port;
131#endif
132
127/* ipport_equal 133/* ipport_equal
128 * compares two IPAny_Port structures 134 * compares two IPAny_Port structures
129 * unset means unequal 135 * unset means unequal
diff --git a/toxcore/tox.c b/toxcore/tox.c
index 83b19e9b..1507b2c5 100644
--- a/toxcore/tox.c
+++ b/toxcore/tox.c
@@ -374,6 +374,11 @@ void tox_bootstrap(void *tox, IP_Port ip_port, uint8_t *public_key)
374 Messenger *m = tox; 374 Messenger *m = tox;
375 DHT_bootstrap(m->dht, ip_port, public_key); 375 DHT_bootstrap(m->dht, ip_port, public_key);
376} 376}
377void tox_bootstrap_ex(void *tox, const char *address, uint16_t port, uint8_t *public_key)
378{
379 Messenger *m = tox;
380 DHT_bootstrap_ex(m->dht, address, port, public_key);
381};
377 382
378/* return 0 if we are not connected to the DHT. 383/* return 0 if we are not connected to the DHT.
379 * return 1 if we are. 384 * return 1 if we are.
diff --git a/toxcore/tox.h b/toxcore/tox.h
index 811e798b..77f0be7f 100644
--- a/toxcore/tox.h
+++ b/toxcore/tox.h
@@ -291,8 +291,10 @@ void tox_callback_connectionstatus(Tox *tox, void (*function)(Tox *tox, int, uin
291 291
292/* Use this function to bootstrap the client. 292/* Use this function to bootstrap the client.
293 * Sends a get nodes request to the given node with ip port and public_key. 293 * Sends a get nodes request to the given node with ip port and public_key.
294 * tox_bootstrap_ex converts the address into an IP_Port structure internally
294 */ 295 */
295void tox_bootstrap(Tox *tox, tox_IP_Port ip_port, uint8_t *public_key); 296void tox_bootstrap(Tox *tox, tox_IP_Port ip_port, uint8_t *public_key);
297void tox_bootstrap_ex(Tox *tox, const char *address, uint16_t port, uint8_t *public_key);
296 298
297/* return 0 if we are not connected to the DHT. 299/* return 0 if we are not connected to the DHT.
298 * return 1 if we are. 300 * return 1 if we are.