summaryrefslogtreecommitdiff
path: root/toxcore/DHT.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore/DHT.c')
-rw-r--r--toxcore/DHT.c315
1 files changed, 250 insertions, 65 deletions
diff --git a/toxcore/DHT.c b/toxcore/DHT.c
index e2d91256..1798ea1a 100644
--- a/toxcore/DHT.c
+++ b/toxcore/DHT.c
@@ -115,11 +115,6 @@ static int client_id_cmp(ClientPair p1, ClientPair p2)
115 return c; 115 return c;
116} 116}
117 117
118static int ipport_equal(IP_Port a, IP_Port b)
119{
120 return (a.ip.uint32 == b.ip.uint32) && (a.port == b.port);
121}
122
123static int id_equal(uint8_t *a, uint8_t *b) 118static int id_equal(uint8_t *a, uint8_t *b)
124{ 119{
125 return memcmp(a, b, CLIENT_ID_SIZE) == 0; 120 return memcmp(a, b, CLIENT_ID_SIZE) == 0;
@@ -142,20 +137,23 @@ static int client_in_list(Client_data *list, uint32_t length, uint8_t *client_id
142 uint32_t i; 137 uint32_t i;
143 uint64_t temp_time = unix_time(); 138 uint64_t temp_time = unix_time();
144 139
145 for (i = 0; i < length; ++i) { 140 /* if client_id is in list, find it and maybe overwrite ip_port */
146 /* If ip_port is assigned to a different client_id replace it */ 141 for (i = 0; i < length; ++i)
147 if (ipport_equal(list[i].ip_port, ip_port)) { 142 if (id_equal(list[i].client_id, client_id)) {
148 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); 143 /* Refresh the client timestamp. */
144 list[i].timestamp = temp_time;
145 list[i].ip_port = ip_port;
146 return 1;
149 } 147 }
150 148
151 if (id_equal(list[i].client_id, client_id)) { 149 /* client_id not in list yet: find ip_port to overwrite */
150 for (i = 0; i < length; ++i)
151 if (ipport_equal(&list[i].ip_port, &ip_port)) {
152 /* Refresh the client timestamp. */ 152 /* Refresh the client timestamp. */
153 list[i].timestamp = temp_time; 153 list[i].timestamp = temp_time;
154 list[i].ip_port.ip.uint32 = ip_port.ip.uint32; 154 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
155 list[i].ip_port.port = ip_port.port;
156 return 1; 155 return 1;
157 } 156 }
158 }
159 157
160 return 0; 158 return 0;
161} 159}
@@ -197,18 +195,37 @@ static int friend_number(DHT *dht, uint8_t *client_id)
197 * 195 *
198 * TODO: For the love of based Allah make this function cleaner and much more efficient. 196 * TODO: For the love of based Allah make this function cleaner and much more efficient.
199 */ 197 */
200static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list) 198static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family)
201{ 199{
202 uint32_t i, j, k; 200 uint32_t i, j, k;
203 uint64_t temp_time = unix_time(); 201 uint64_t temp_time = unix_time();
204 int num_nodes = 0, closest, tout, inlist; 202 int num_nodes = 0, closest, tout, inlist, ipv46x;
205 203
206 for (i = 0; i < LCLIENT_LIST; ++i) { 204 for (i = 0; i < LCLIENT_LIST; ++i) {
207 tout = is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT); 205 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); 206 inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, dht->close_clientlist[i].client_id);
209 207
208 /*
209 * NET_PACKET_SEND_NODES sends ONLY AF_INET
210 * NET_PACKET_SEND_NODES_EX sends ALL BUT AF_INET (i.e. AF_INET6),
211 * it could send both, but then a) packet size is an issue and
212 * b) duplicates the traffic (NET_PACKET_SEND_NODES has to be
213 * sent anyways for backwards compatibility)
214 * we COULD send ALL as NET_PACKET_SEND_NODES_EX if we KNEW that the
215 * partner node understands - that's true if *they* are on IPv6
216 */
217#ifdef TOX_ENABLE_IPV6
218 ipv46x = 0;
219 if (sa_family == AF_INET)
220 ipv46x = dht->close_clientlist[i].ip_port.ip.family != AF_INET;
221 else
222 ipv46x = dht->close_clientlist[i].ip_port.ip.family == AF_INET;
223#else
224 ipv46x = sa_family != AF_INET;
225#endif
226
210 /* If node isn't good or is already in list. */ 227 /* If node isn't good or is already in list. */
211 if (tout || inlist) 228 if (tout || inlist || ipv46x)
212 continue; 229 continue;
213 230
214 if (num_nodes < MAX_SENT_NODES) { 231 if (num_nodes < MAX_SENT_NODES) {
@@ -247,8 +264,18 @@ static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list
247 MAX_SENT_NODES, 264 MAX_SENT_NODES,
248 dht->friends_list[i].client_list[j].client_id); 265 dht->friends_list[i].client_list[j].client_id);
249 266
267#ifdef TOX_ENABLE_IPV6
268 ipv46x = 0;
269 if (sa_family == AF_INET)
270 ipv46x = dht->friends_list[i].client_list[j].ip_port.ip.family != AF_INET;
271 else
272 ipv46x = dht->friends_list[i].client_list[j].ip_port.ip.family == AF_INET;
273#else
274 ipv46x = sa_family != AF_INET;
275#endif
276
250 /* If node isn't good or is already in list. */ 277 /* If node isn't good or is already in list. */
251 if (tout || inlist) 278 if (tout || inlist || ipv46x)
252 continue; 279 continue;
253 280
254 if (num_nodes < MAX_SENT_NODES) { 281 if (num_nodes < MAX_SENT_NODES) {
@@ -301,7 +328,7 @@ static int replace_bad( Client_data *list,
301 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); 328 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
302 list[i].ip_port = ip_port; 329 list[i].ip_port = ip_port;
303 list[i].timestamp = temp_time; 330 list[i].timestamp = temp_time;
304 list[i].ret_ip_port.ip.uint32 = 0; 331 ip_reset(&list[i].ret_ip_port.ip);
305 list[i].ret_ip_port.port = 0; 332 list[i].ret_ip_port.port = 0;
306 list[i].ret_timestamp = 0; 333 list[i].ret_timestamp = 0;
307 return 0; 334 return 0;
@@ -349,7 +376,7 @@ static int replace_good( Client_data *list,
349 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); 376 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
350 list[i].ip_port = ip_port; 377 list[i].ip_port = ip_port;
351 list[i].timestamp = temp_time; 378 list[i].timestamp = temp_time;
352 list[i].ret_ip_port.ip.uint32 = 0; 379 ip_reset(&list[i].ret_ip_port.ip);
353 list[i].ret_ip_port.port = 0; 380 list[i].ret_ip_port.port = 0;
354 list[i].ret_timestamp = 0; 381 list[i].ret_timestamp = 0;
355 return 0; 382 return 0;
@@ -447,13 +474,13 @@ static int is_gettingnodes(DHT *dht, IP_Port ip_port, uint64_t ping_id)
447 if (!is_timeout(temp_time, dht->send_nodes[i].timestamp, PING_TIMEOUT)) { 474 if (!is_timeout(temp_time, dht->send_nodes[i].timestamp, PING_TIMEOUT)) {
448 pinging = 0; 475 pinging = 0;
449 476
450 if (ip_port.ip.uint32 != 0 && ipport_equal(dht->send_nodes[i].ip_port, ip_port)) 477 if (ping_id != 0 && dht->send_nodes[i].ping_id == ping_id)
451 ++pinging; 478 ++pinging;
452 479
453 if (ping_id != 0 && dht->send_nodes[i].ping_id == ping_id) 480 if (ip_isset(&ip_port.ip) && ipport_equal(&dht->send_nodes[i].ip_port, &ip_port))
454 ++pinging; 481 ++pinging;
455 482
456 if (pinging == (ping_id != 0) + (ip_port.ip.uint32 != 0)) 483 if (pinging == (ping_id != 0) + (ip_isset(&ip_port.ip) != 0))
457 return 1; 484 return 1;
458 } 485 }
459 } 486 }
@@ -518,44 +545,65 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli
518 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); 545 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
519 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); 546 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len);
520 547
521 return sendpacket(dht->c->lossless_udp->net->sock, ip_port, data, sizeof(data)); 548 return sendpacket(dht->c->lossless_udp->net, ip_port, data, sizeof(data));
522} 549}
523 550
524/* Send a send nodes response. */ 551/* Send a send nodes response. */
552/* because of BINARY compatibility, the Node_format MUST BE Node4_format,
553 * 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) 554static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id)
526{ 555{
527 /* Check if packet is going to be sent to ourself. */ 556 /* Check if packet is going to be sent to ourself. */
528 if (id_equal(public_key, dht->c->self_public_key)) 557 if (id_equal(public_key, dht->c->self_public_key))
529 return -1; 558 return -1;
530 559
560 size_t Node4_format_size = sizeof(Node4_format);
531 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) 561 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id)
532 + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING]; 562 + Node4_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING];
533 563
534 Node_format nodes_list[MAX_SENT_NODES]; 564 Node_format nodes_list[MAX_SENT_NODES];
535 int num_nodes = get_close_nodes(dht, client_id, nodes_list); 565 int num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET);
536 566
537 if (num_nodes == 0) 567 if (num_nodes == 0)
538 return 0; 568 return 0;
539 569
540 uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES]; 570 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]; 571 uint8_t encrypt[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING];
542 uint8_t nonce[crypto_box_NONCEBYTES]; 572 uint8_t nonce[crypto_box_NONCEBYTES];
543 random_nonce(nonce); 573 random_nonce(nonce);
544 574
545 memcpy(plain, &ping_id, sizeof(ping_id)); 575 memcpy(plain, &ping_id, sizeof(ping_id));
546 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * sizeof(Node_format)); 576#ifdef TOX_ENABLE_IPV6
577 Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id));
578 int i, num_nodes_ok = 0;
579 for(i = 0; i < num_nodes; i++)
580 if (nodes_list[i].ip_port.ip.family == AF_INET) {
581 memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE);
582 nodes4_list[num_nodes_ok].ip_port.ip.uint32 = nodes_list[i].ip_port.ip.ip4.uint32;
583 nodes4_list[num_nodes_ok].ip_port.port = nodes_list[i].ip_port.port;
584
585 num_nodes_ok++;
586 }
587
588 if (num_nodes_ok < num_nodes) {
589 /* shouldn't happen */
590 num_nodes = num_nodes_ok;
591 }
592#else
593 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * Node4_format_size);
594#endif
547 595
548 int len = encrypt_data( public_key, 596 int len = encrypt_data( public_key,
549 dht->c->self_secret_key, 597 dht->c->self_secret_key,
550 nonce, 598 nonce,
551 plain, 599 plain,
552 sizeof(ping_id) + num_nodes * sizeof(Node_format), 600 sizeof(ping_id) + num_nodes * Node4_format_size,
553 encrypt ); 601 encrypt );
554 602
555 if (len == -1) 603 if (len == -1)
556 return -1; 604 return -1;
557 605
558 if ((unsigned int)len != sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING) 606 if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node4_format_size + ENCRYPTION_PADDING)
559 return -1; 607 return -1;
560 608
561 data[0] = NET_PACKET_SEND_NODES; 609 data[0] = NET_PACKET_SEND_NODES;
@@ -563,9 +611,57 @@ static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cl
563 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); 611 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
564 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); 612 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len);
565 613
566 return sendpacket(dht->c->lossless_udp->net->sock, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); 614 return sendpacket(dht->c->lossless_udp->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len);
567} 615}
568 616
617#ifdef TOX_ENABLE_IPV6
618/* Send a send nodes response: message for IPv6 nodes */
619static int sendnodes_ex(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id)
620{
621 /* Check if packet is going to be sent to ourself. */
622 if (id_equal(public_key, dht->c->self_public_key))
623 return -1;
624
625 size_t Node_format_size = sizeof(Node_format);
626 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id)
627 + Node_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING];
628
629 Node_format nodes_list[MAX_SENT_NODES];
630 int num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET6);
631
632 if (num_nodes == 0)
633 return 0;
634
635 uint8_t plain[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES];
636 uint8_t encrypt[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING];
637 uint8_t nonce[crypto_box_NONCEBYTES];
638 random_nonce(nonce);
639
640 memcpy(plain, &ping_id, sizeof(ping_id));
641 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * Node_format_size);
642
643 int len = encrypt_data( public_key,
644 dht->c->self_secret_key,
645 nonce,
646 plain,
647 sizeof(ping_id) + num_nodes * Node_format_size,
648 encrypt );
649
650 if (len == -1)
651 return -1;
652
653 if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node_format_size + ENCRYPTION_PADDING)
654 return -1;
655
656 data[0] = NET_PACKET_SEND_NODES_EX;
657 memcpy(data + 1, dht->c->self_public_key, CLIENT_ID_SIZE);
658 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
659 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len);
660
661 return sendpacket(dht->c->lossless_udp->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len);
662}
663#endif
664
569static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) 665static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length)
570{ 666{
571 DHT *dht = object; 667 DHT *dht = object;
@@ -593,6 +689,9 @@ static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32
593 689
594 memcpy(&ping_id, plain, sizeof(ping_id)); 690 memcpy(&ping_id, plain, sizeof(ping_id));
595 sendnodes(dht, source, packet + 1, plain + sizeof(ping_id), ping_id); 691 sendnodes(dht, source, packet + 1, plain + sizeof(ping_id), ping_id);
692#ifdef TOX_ENABLE_IPV6
693 sendnodes_ex(dht, source, packet + 1, plain + sizeof(ping_id), ping_id);
694#endif
596 695
597 //send_ping_request(dht, source, packet + 1); /* TODO: make this smarter? */ 696 //send_ping_request(dht, source, packet + 1); /* TODO: make this smarter? */
598 697
@@ -606,22 +705,23 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3
606 uint32_t cid_size = 1 + CLIENT_ID_SIZE; 705 uint32_t cid_size = 1 + CLIENT_ID_SIZE;
607 cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; 706 cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING;
608 707
609 if (length > (cid_size + sizeof(Node_format) * MAX_SENT_NODES) || 708 size_t Node4_format_size = sizeof(Node4_format);
610 ((length - cid_size) % sizeof(Node_format)) != 0 || 709 if (length > (cid_size + Node4_format_size * MAX_SENT_NODES) ||
611 (length < cid_size + sizeof(Node_format))) 710 ((length - cid_size) % Node4_format_size) != 0 ||
711 (length < cid_size + Node4_format_size))
612 return 1; 712 return 1;
613 713
614 uint32_t num_nodes = (length - cid_size) / sizeof(Node_format); 714 uint32_t num_nodes = (length - cid_size) / Node4_format_size;
615 uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES]; 715 uint8_t plain[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES];
616 716
617 int len = decrypt_data( 717 int len = decrypt_data(
618 packet + 1, 718 packet + 1,
619 dht->c->self_secret_key, 719 dht->c->self_secret_key,
620 packet + 1 + CLIENT_ID_SIZE, 720 packet + 1 + CLIENT_ID_SIZE,
621 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, 721 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
622 sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING, plain ); 722 sizeof(ping_id) + num_nodes * Node4_format_size + ENCRYPTION_PADDING, plain );
623 723
624 if ((unsigned int)len != sizeof(ping_id) + num_nodes * sizeof(Node_format)) 724 if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node4_format_size)
625 return 1; 725 return 1;
626 726
627 memcpy(&ping_id, plain, sizeof(ping_id)); 727 memcpy(&ping_id, plain, sizeof(ping_id));
@@ -629,12 +729,78 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3
629 if (!is_gettingnodes(dht, source, ping_id)) 729 if (!is_gettingnodes(dht, source, ping_id))
630 return 1; 730 return 1;
631 731
732 uint32_t i;
632 Node_format nodes_list[MAX_SENT_NODES]; 733 Node_format nodes_list[MAX_SENT_NODES];
734
735#ifdef TOX_ENABLE_IPV6
736 Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id));
737
738 int num_nodes_ok = 0;
739 for(i = 0; i < num_nodes; i++)
740 if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != ~0)) {
741 memcpy(nodes_list[num_nodes_ok].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE);
742 nodes_list[num_nodes_ok].ip_port.ip.family = AF_INET;
743 nodes_list[num_nodes_ok].ip_port.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32;
744 nodes_list[num_nodes_ok].ip_port.port = nodes4_list[i].ip_port.port;
745
746 num_nodes_ok++;
747 }
748
749 if (num_nodes_ok < num_nodes) {
750 /* shouldn't happen */
751 num_nodes = num_nodes_ok;
752 }
753#else
633 memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format)); 754 memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format));
755#endif
634 756
635 addto_lists(dht, source, packet + 1); 757 addto_lists(dht, source, packet + 1);
636 758
759 for (i = 0; i < num_nodes; ++i) {
760 send_ping_request(dht->ping, dht->c, nodes_list[i].ip_port, nodes_list[i].client_id);
761 returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1);
762 }
763
764 return 0;
765}
766
767#ifdef TOX_ENABLE_IPV6
768static int handle_sendnodes_ex(void *object, IP_Port source, uint8_t *packet, uint32_t length)
769{
770 DHT *dht = object;
771 uint64_t ping_id;
772 uint32_t cid_size = 1 + CLIENT_ID_SIZE;
773 cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING;
774
775 size_t Node_format_size = sizeof(Node4_format);
776 if (length > (cid_size + Node_format_size * MAX_SENT_NODES) ||
777 ((length - cid_size) % Node_format_size) != 0 ||
778 (length < cid_size + Node_format_size))
779 return 1;
780
781 uint32_t num_nodes = (length - cid_size) / Node_format_size;
782 uint8_t plain[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES];
783
784 int len = decrypt_data(
785 packet + 1,
786 dht->c->self_secret_key,
787 packet + 1 + CLIENT_ID_SIZE,
788 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
789 sizeof(ping_id) + num_nodes * Node_format_size + ENCRYPTION_PADDING, plain );
790
791 if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node_format_size)
792 return 1;
793
794 memcpy(&ping_id, plain, sizeof(ping_id));
795
796 if (!is_gettingnodes(dht, source, ping_id))
797 return 1;
798
637 uint32_t i; 799 uint32_t i;
800 Node_format nodes_list[MAX_SENT_NODES];
801 memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format));
802
803 addto_lists(dht, source, packet + 1);
638 804
639 for (i = 0; i < num_nodes; ++i) { 805 for (i = 0; i < num_nodes; ++i) {
640 send_ping_request(dht->ping, dht->c, nodes_list[i].ip_port, nodes_list[i].client_id); 806 send_ping_request(dht->ping, dht->c, nodes_list[i].ip_port, nodes_list[i].client_id);
@@ -643,6 +809,7 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3
643 809
644 return 0; 810 return 0;
645} 811}
812#endif
646 813
647/*----------------------------------------------------------------------------------*/ 814/*----------------------------------------------------------------------------------*/
648/*------------------------END of packet handling functions--------------------------*/ 815/*------------------------END of packet handling functions--------------------------*/
@@ -703,27 +870,30 @@ int DHT_delfriend(DHT *dht, uint8_t *client_id)
703} 870}
704 871
705/* TODO: Optimize this. */ 872/* TODO: Optimize this. */
706IP_Port DHT_getfriendip(DHT *dht, uint8_t *client_id) 873int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port)
707{ 874{
708 uint32_t i, j; 875 uint32_t i, j;
709 uint64_t temp_time = unix_time(); 876 uint64_t temp_time = unix_time();
710 IP_Port empty = {{{{0}}, 0, 0}}; 877
878 ip_reset(&ip_port->ip);
879 ip_port->port = 0;
711 880
712 for (i = 0; i < dht->num_friends; ++i) { 881 for (i = 0; i < dht->num_friends; ++i) {
713 /* Equal */ 882 /* Equal */
714 if (id_equal(dht->friends_list[i].client_id, client_id)) { 883 if (id_equal(dht->friends_list[i].client_id, client_id)) {
715 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 884 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
716 if (id_equal(dht->friends_list[i].client_list[j].client_id, client_id) 885 if (id_equal(dht->friends_list[i].client_list[j].client_id, client_id)
717 && !is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) 886 && !is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) {
718 return dht->friends_list[i].client_list[j].ip_port; 887 *ip_port = dht->friends_list[i].client_list[j].ip_port;
888 return 1;
889 }
719 } 890 }
720 891
721 return empty; 892 return 0;
722 } 893 }
723 } 894 }
724 895
725 empty.ip.uint32 = 1; 896 return -1;
726 return empty;
727} 897}
728 898
729/* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request 899/* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request
@@ -808,6 +978,18 @@ 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); 978 getnodes(dht, ip_port, public_key, dht->c->self_public_key);
809 send_ping_request(dht->ping, dht->c, ip_port, public_key); 979 send_ping_request(dht->ping, dht->c, ip_port, public_key);
810} 980}
981int DHT_bootstrap_ex(DHT *dht, const char *address, uint8_t ipv6enabled, uint16_t port, uint8_t *public_key)
982{
983 IP_Port ip_port;
984 ip_init(&ip_port.ip, ipv6enabled);
985 if (addr_resolve_or_parse_ip(address, &ip_port.ip)) {
986 ip_port.port = port;
987 DHT_bootstrap(dht, ip_port, public_key);
988 return 1;
989 }
990 else
991 return 0;
992}
811 993
812/* Send the given packet to node with client_id 994/* Send the given packet to node with client_id
813 * 995 *
@@ -819,7 +1001,7 @@ int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length)
819 1001
820 for (i = 0; i < LCLIENT_LIST; ++i) { 1002 for (i = 0; i < LCLIENT_LIST; ++i) {
821 if (id_equal(client_id, dht->close_clientlist[i].client_id)) 1003 if (id_equal(client_id, dht->close_clientlist[i].client_id))
822 return sendpacket(dht->c->lossless_udp->net->sock, dht->close_clientlist[i].ip_port, packet, length); 1004 return sendpacket(dht->c->lossless_udp->net, dht->close_clientlist[i].ip_port, packet, length);
823 } 1005 }
824 1006
825 return -1; 1007 return -1;
@@ -848,7 +1030,7 @@ static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num)
848 client = &friend->client_list[i]; 1030 client = &friend->client_list[i];
849 1031
850 /* If ip is not zero and node is good. */ 1032 /* If ip is not zero and node is good. */
851 if (client->ret_ip_port.ip.uint32 != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { 1033 if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) {
852 1034
853 if (id_equal(client->client_id, friend->client_id)) 1035 if (id_equal(client->client_id, friend->client_id))
854 return 0; 1036 return 0;
@@ -890,8 +1072,8 @@ int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t lengt
890 client = &friend->client_list[i]; 1072 client = &friend->client_list[i];
891 1073
892 /* If ip is not zero and node is good. */ 1074 /* If ip is not zero and node is good. */
893 if (client->ret_ip_port.ip.uint32 != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { 1075 if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) {
894 int retval = sendpacket(dht->c->lossless_udp->net->sock, client->ip_port, packet, length); 1076 int retval = sendpacket(dht->c->lossless_udp->net, client->ip_port, packet, length);
895 1077
896 if ((unsigned int)retval == length) 1078 if ((unsigned int)retval == length)
897 ++sent; 1079 ++sent;
@@ -924,7 +1106,7 @@ static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint
924 client = &friend->client_list[i]; 1106 client = &friend->client_list[i];
925 1107
926 /* If ip is not zero and node is good. */ 1108 /* If ip is not zero and node is good. */
927 if (client->ret_ip_port.ip.uint32 != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { 1109 if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) {
928 ip_list[n] = client->ip_port; 1110 ip_list[n] = client->ip_port;
929 ++n; 1111 ++n;
930 } 1112 }
@@ -933,7 +1115,7 @@ static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint
933 if (n < 1) 1115 if (n < 1)
934 return 0; 1116 return 0;
935 1117
936 int retval = sendpacket(dht->c->lossless_udp->net->sock, ip_list[rand() % n], packet, length); 1118 int retval = sendpacket(dht->c->lossless_udp->net, ip_list[rand() % n], packet, length);
937 1119
938 if ((unsigned int)retval == length) 1120 if ((unsigned int)retval == length)
939 return 1; 1121 return 1;
@@ -1032,7 +1214,8 @@ static int handle_NATping(void *object, IP_Port source, uint8_t *source_pubkey,
1032 */ 1214 */
1033static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num) 1215static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num)
1034{ 1216{
1035 IP zero = {{0}}; 1217 IP zero;
1218 ip_reset(&zero);
1036 1219
1037 if (len > MAX_FRIEND_CLIENTS) 1220 if (len > MAX_FRIEND_CLIENTS)
1038 return zero; 1221 return zero;
@@ -1042,7 +1225,7 @@ static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num)
1042 1225
1043 for (i = 0; i < len; ++i) { 1226 for (i = 0; i < len; ++i) {
1044 for (j = 0; j < len; ++j) { 1227 for (j = 0; j < len; ++j) {
1045 if (ip_portlist[i].ip.uint32 == ip_portlist[j].ip.uint32) 1228 if (ip_equal(&ip_portlist[i].ip, &ip_portlist[j].ip))
1046 ++numbers[i]; 1229 ++numbers[i];
1047 } 1230 }
1048 1231
@@ -1065,7 +1248,7 @@ static uint16_t NAT_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t
1065 uint16_t num = 0; 1248 uint16_t num = 0;
1066 1249
1067 for (i = 0; i < len; ++i) { 1250 for (i = 0; i < len; ++i) {
1068 if (ip_portlist[i].ip.uint32 == ip.uint32) { 1251 if (ip_equal(&ip_portlist[i].ip, &ip)) {
1069 portlist[num] = ntohs(ip_portlist[i].port); 1252 portlist[num] = ntohs(ip_portlist[i].port);
1070 ++num; 1253 ++num;
1071 } 1254 }
@@ -1085,7 +1268,9 @@ static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports,
1085 for (i = dht->friends_list[friend_num].punching_index; i != top; i++) { 1268 for (i = dht->friends_list[friend_num].punching_index; i != top; i++) {
1086 /* TODO: Improve port guessing algorithm. */ 1269 /* TODO: Improve port guessing algorithm. */
1087 uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1); 1270 uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1);
1088 IP_Port pinging = {{ip, htons(port), 0}}; 1271 IP_Port pinging;
1272 ip_copy(&pinging.ip, &ip);
1273 pinging.port = htons(port);
1089 send_ping_request(dht->ping, dht->c, pinging, dht->friends_list[friend_num].client_id); 1274 send_ping_request(dht->ping, dht->c, pinging, dht->friends_list[friend_num].client_id);
1090 } 1275 }
1091 1276
@@ -1115,8 +1300,7 @@ static void do_NAT(DHT *dht)
1115 dht->friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) { 1300 dht->friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) {
1116 1301
1117 IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2); 1302 IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2);
1118 1303 if (!ip_isset(&ip))
1119 if (ip.uint32 == 0)
1120 continue; 1304 continue;
1121 1305
1122 uint16_t port_list[MAX_FRIEND_CLIENTS]; 1306 uint16_t port_list[MAX_FRIEND_CLIENTS];
@@ -1145,16 +1329,15 @@ static void do_NAT(DHT *dht)
1145 */ 1329 */
1146int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port) 1330int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port)
1147{ 1331{
1148 if (ip_port.ip.uint32 == 0) 1332 if (!ip_isset(&ip_port.ip))
1149 return -1; 1333 return -1;
1150 1334
1151 uint32_t i; 1335 uint32_t i;
1152 1336
1153 for (i = 0; i < MAX_TOPING; ++i) { 1337 for (i = 0; i < MAX_TOPING; ++i) {
1154 if (dht->toping[i].ip_port.ip.uint32 == 0) { 1338 if (!ip_isset(&dht->toping[i].ip_port.ip)) {
1155 memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); 1339 memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE);
1156 dht->toping[i].ip_port.ip.uint32 = ip_port.ip.uint32; 1340 ipport_copy(&dht->toping[i].ip_port, &ip_port);
1157 dht->toping[i].ip_port.port = ip_port.port;
1158 return 0; 1341 return 0;
1159 } 1342 }
1160 } 1343 }
@@ -1162,8 +1345,7 @@ int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port)
1162 for (i = 0; i < MAX_TOPING; ++i) { 1345 for (i = 0; i < MAX_TOPING; ++i) {
1163 if (id_closest(dht->c->self_public_key, dht->toping[i].client_id, client_id) == 2) { 1346 if (id_closest(dht->c->self_public_key, dht->toping[i].client_id, client_id) == 2) {
1164 memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); 1347 memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE);
1165 dht->toping[i].ip_port.ip.uint32 = ip_port.ip.uint32; 1348 ipport_copy(&dht->toping[i].ip_port, &ip_port);
1166 dht->toping[i].ip_port.port = ip_port.port;
1167 return 0; 1349 return 0;
1168 } 1350 }
1169 } 1351 }
@@ -1185,11 +1367,11 @@ static void do_toping(DHT *dht)
1185 uint32_t i; 1367 uint32_t i;
1186 1368
1187 for (i = 0; i < MAX_TOPING; ++i) { 1369 for (i = 0; i < MAX_TOPING; ++i) {
1188 if (dht->toping[i].ip_port.ip.uint32 == 0) 1370 if (!ip_isset(&dht->toping[i].ip_port.ip))
1189 return; 1371 return;
1190 1372
1191 send_ping_request(dht->ping, dht->c, dht->toping[i].ip_port, dht->toping[i].client_id); 1373 send_ping_request(dht->ping, dht->c, dht->toping[i].ip_port, dht->toping[i].client_id);
1192 dht->toping[i].ip_port.ip.uint32 = 0; 1374 ip_reset(&dht->toping[i].ip_port.ip);
1193 } 1375 }
1194} 1376}
1195 1377
@@ -1216,6 +1398,9 @@ DHT *new_DHT(Net_Crypto *c)
1216 networking_registerhandler(c->lossless_udp->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, temp); 1398 networking_registerhandler(c->lossless_udp->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, temp);
1217 networking_registerhandler(c->lossless_udp->net, NET_PACKET_GET_NODES, &handle_getnodes, temp); 1399 networking_registerhandler(c->lossless_udp->net, NET_PACKET_GET_NODES, &handle_getnodes, temp);
1218 networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES, &handle_sendnodes, temp); 1400 networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES, &handle_sendnodes, temp);
1401#ifdef TOX_ENABLE_IPV6
1402 networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES_EX, &handle_sendnodes_ex, temp);
1403#endif
1219 init_cryptopackets(temp); 1404 init_cryptopackets(temp);
1220 cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, temp); 1405 cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, temp);
1221 return temp; 1406 return temp;