diff options
Diffstat (limited to 'toxcore/DHT.c')
-rw-r--r-- | toxcore/DHT.c | 201 |
1 files changed, 139 insertions, 62 deletions
diff --git a/toxcore/DHT.c b/toxcore/DHT.c index e2d91256..a4734747 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 | ||
118 | static int ipport_equal(IP_Port a, IP_Port b) | ||
119 | { | ||
120 | return (a.ip.uint32 == b.ip.uint32) && (a.port == b.port); | ||
121 | } | ||
122 | |||
123 | static int id_equal(uint8_t *a, uint8_t *b) | 118 | static 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; |
@@ -144,15 +139,14 @@ static int client_in_list(Client_data *list, uint32_t length, uint8_t *client_id | |||
144 | 139 | ||
145 | for (i = 0; i < length; ++i) { | 140 | for (i = 0; i < length; ++i) { |
146 | /* If ip_port is assigned to a different client_id replace it */ | 141 | /* If ip_port is assigned to a different client_id replace it */ |
147 | if (ipport_equal(list[i].ip_port, ip_port)) { | 142 | if (ipport_equal(&list[i].ip_port, &ip_port)) { |
148 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); | 143 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); |
149 | } | 144 | } |
150 | 145 | ||
151 | if (id_equal(list[i].client_id, client_id)) { | 146 | if (id_equal(list[i].client_id, client_id)) { |
152 | /* Refresh the client timestamp. */ | 147 | /* Refresh the client timestamp. */ |
153 | list[i].timestamp = temp_time; | 148 | list[i].timestamp = temp_time; |
154 | list[i].ip_port.ip.uint32 = ip_port.ip.uint32; | 149 | ipport_copy(&list[i].ip_port, &ip_port); |
155 | list[i].ip_port.port = ip_port.port; | ||
156 | return 1; | 150 | return 1; |
157 | } | 151 | } |
158 | } | 152 | } |
@@ -197,18 +191,37 @@ static int friend_number(DHT *dht, uint8_t *client_id) | |||
197 | * | 191 | * |
198 | * TODO: For the love of based Allah make this function cleaner and much more efficient. | 192 | * TODO: For the love of based Allah make this function cleaner and much more efficient. |
199 | */ | 193 | */ |
200 | static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list) | 194 | static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family) |
201 | { | 195 | { |
202 | uint32_t i, j, k; | 196 | uint32_t i, j, k; |
203 | uint64_t temp_time = unix_time(); | 197 | uint64_t temp_time = unix_time(); |
204 | int num_nodes = 0, closest, tout, inlist; | 198 | int num_nodes = 0, closest, tout, inlist, ipv46x; |
205 | 199 | ||
206 | for (i = 0; i < LCLIENT_LIST; ++i) { | 200 | for (i = 0; i < LCLIENT_LIST; ++i) { |
207 | tout = is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT); | 201 | 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); | 202 | inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, dht->close_clientlist[i].client_id); |
209 | 203 | ||
204 | /* | ||
205 | * NET_PACKET_SEND_NODES sends ONLY AF_INET | ||
206 | * NET_PACKET_SEND_NODES_EX sends ALL BUT AF_INET (i.e. AF_INET6), | ||
207 | * it could send both, but then a) packet size is an issue and | ||
208 | * b) duplicates the traffic (NET_PACKET_SEND_NODES has to be | ||
209 | * sent anyways for backwards compatibility) | ||
210 | * we COULD send ALL as NET_PACKET_SEND_NODES_EX if we KNEW that the | ||
211 | * partner node understands - that's true if *they* are on IPv6 | ||
212 | */ | ||
213 | #ifdef TOX_ENABLE_IPV6 | ||
214 | ipv46x = 0; | ||
215 | if (sa_family == AF_INET) | ||
216 | ipv46x = dht->close_clientlist[i].ip_port.ip.family != AF_INET; | ||
217 | else | ||
218 | ipv46x = dht->close_clientlist[i].ip_port.ip.family == AF_INET; | ||
219 | #else | ||
220 | ipv46x = sa_family != AF_INET; | ||
221 | #endif | ||
222 | |||
210 | /* If node isn't good or is already in list. */ | 223 | /* If node isn't good or is already in list. */ |
211 | if (tout || inlist) | 224 | if (tout || inlist || ipv46x) |
212 | continue; | 225 | continue; |
213 | 226 | ||
214 | if (num_nodes < MAX_SENT_NODES) { | 227 | if (num_nodes < MAX_SENT_NODES) { |
@@ -247,8 +260,18 @@ static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list | |||
247 | MAX_SENT_NODES, | 260 | MAX_SENT_NODES, |
248 | dht->friends_list[i].client_list[j].client_id); | 261 | dht->friends_list[i].client_list[j].client_id); |
249 | 262 | ||
263 | #ifdef TOX_ENABLE_IPV6 | ||
264 | ipv46x = 0; | ||
265 | if (sa_family == AF_INET) | ||
266 | ipv46x = dht->friends_list[i].client_list[j].ip_port.ip.family != AF_INET; | ||
267 | else | ||
268 | ipv46x = dht->friends_list[i].client_list[j].ip_port.ip.family == AF_INET; | ||
269 | #else | ||
270 | ipv46x = sa_family != AF_INET; | ||
271 | #endif | ||
272 | |||
250 | /* If node isn't good or is already in list. */ | 273 | /* If node isn't good or is already in list. */ |
251 | if (tout || inlist) | 274 | if (tout || inlist || ipv46x) |
252 | continue; | 275 | continue; |
253 | 276 | ||
254 | if (num_nodes < MAX_SENT_NODES) { | 277 | if (num_nodes < MAX_SENT_NODES) { |
@@ -301,7 +324,7 @@ static int replace_bad( Client_data *list, | |||
301 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); | 324 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); |
302 | list[i].ip_port = ip_port; | 325 | list[i].ip_port = ip_port; |
303 | list[i].timestamp = temp_time; | 326 | list[i].timestamp = temp_time; |
304 | list[i].ret_ip_port.ip.uint32 = 0; | 327 | ip_reset(&list[i].ret_ip_port.ip); |
305 | list[i].ret_ip_port.port = 0; | 328 | list[i].ret_ip_port.port = 0; |
306 | list[i].ret_timestamp = 0; | 329 | list[i].ret_timestamp = 0; |
307 | return 0; | 330 | return 0; |
@@ -349,7 +372,7 @@ static int replace_good( Client_data *list, | |||
349 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); | 372 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); |
350 | list[i].ip_port = ip_port; | 373 | list[i].ip_port = ip_port; |
351 | list[i].timestamp = temp_time; | 374 | list[i].timestamp = temp_time; |
352 | list[i].ret_ip_port.ip.uint32 = 0; | 375 | ip_reset(&list[i].ret_ip_port.ip); |
353 | list[i].ret_ip_port.port = 0; | 376 | list[i].ret_ip_port.port = 0; |
354 | list[i].ret_timestamp = 0; | 377 | list[i].ret_timestamp = 0; |
355 | return 0; | 378 | return 0; |
@@ -447,13 +470,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)) { | 470 | if (!is_timeout(temp_time, dht->send_nodes[i].timestamp, PING_TIMEOUT)) { |
448 | pinging = 0; | 471 | pinging = 0; |
449 | 472 | ||
450 | if (ip_port.ip.uint32 != 0 && ipport_equal(dht->send_nodes[i].ip_port, ip_port)) | 473 | if (ping_id != 0 && dht->send_nodes[i].ping_id == ping_id) |
451 | ++pinging; | 474 | ++pinging; |
452 | 475 | ||
453 | if (ping_id != 0 && dht->send_nodes[i].ping_id == ping_id) | 476 | if (ip_isset(&ip_port.ip) && ipport_equal(&dht->send_nodes[i].ip_port, &ip_port)) |
454 | ++pinging; | 477 | ++pinging; |
455 | 478 | ||
456 | if (pinging == (ping_id != 0) + (ip_port.ip.uint32 != 0)) | 479 | if (pinging == (ping_id != 0) + (ip_isset(&ip_port.ip) != 0)) |
457 | return 1; | 480 | return 1; |
458 | } | 481 | } |
459 | } | 482 | } |
@@ -518,44 +541,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); | 541 | memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); |
519 | memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); | 542 | memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); |
520 | 543 | ||
521 | return sendpacket(dht->c->lossless_udp->net->sock, ip_port, data, sizeof(data)); | 544 | return sendpacket(dht->c->lossless_udp->net, ip_port, data, sizeof(data)); |
522 | } | 545 | } |
523 | 546 | ||
524 | /* Send a send nodes response. */ | 547 | /* Send a send nodes response. */ |
548 | /* because of BINARY compatibility, the Node_format MUST BE Node4_format, | ||
549 | * IPv6 nodes are sent in a different message */ | ||
525 | static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id) | 550 | static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id) |
526 | { | 551 | { |
527 | /* Check if packet is going to be sent to ourself. */ | 552 | /* Check if packet is going to be sent to ourself. */ |
528 | if (id_equal(public_key, dht->c->self_public_key)) | 553 | if (id_equal(public_key, dht->c->self_public_key)) |
529 | return -1; | 554 | return -1; |
530 | 555 | ||
556 | size_t Node4_format_size = sizeof(Node4_format); | ||
531 | uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) | 557 | uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) |
532 | + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING]; | 558 | + Node4_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING]; |
533 | 559 | ||
534 | Node_format nodes_list[MAX_SENT_NODES]; | 560 | Node_format nodes_list[MAX_SENT_NODES]; |
535 | int num_nodes = get_close_nodes(dht, client_id, nodes_list); | 561 | int num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET); |
536 | 562 | ||
537 | if (num_nodes == 0) | 563 | if (num_nodes == 0) |
538 | return 0; | 564 | return 0; |
539 | 565 | ||
540 | uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES]; | 566 | 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]; | 567 | uint8_t encrypt[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING]; |
542 | uint8_t nonce[crypto_box_NONCEBYTES]; | 568 | uint8_t nonce[crypto_box_NONCEBYTES]; |
543 | random_nonce(nonce); | 569 | random_nonce(nonce); |
544 | 570 | ||
545 | memcpy(plain, &ping_id, sizeof(ping_id)); | 571 | memcpy(plain, &ping_id, sizeof(ping_id)); |
546 | memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * sizeof(Node_format)); | 572 | #ifdef TOX_ENABLE_IPV6 |
573 | Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id)); | ||
574 | int i, num_nodes_ok = 0; | ||
575 | for(i = 0; i < num_nodes; i++) | ||
576 | if (nodes_list[i].ip_port.ip.family == AF_INET) { | ||
577 | memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE); | ||
578 | nodes4_list[num_nodes_ok].ip_port.ip.uint32 = nodes_list[i].ip_port.ip.ip4.uint32; | ||
579 | nodes4_list[num_nodes_ok].ip_port.port = nodes_list[i].ip_port.port; | ||
580 | |||
581 | num_nodes_ok++; | ||
582 | } | ||
583 | |||
584 | if (num_nodes_ok < num_nodes) { | ||
585 | /* shouldn't happen */ | ||
586 | num_nodes = num_nodes_ok; | ||
587 | } | ||
588 | #else | ||
589 | memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * Node4_format_size); | ||
590 | #endif | ||
547 | 591 | ||
548 | int len = encrypt_data( public_key, | 592 | int len = encrypt_data( public_key, |
549 | dht->c->self_secret_key, | 593 | dht->c->self_secret_key, |
550 | nonce, | 594 | nonce, |
551 | plain, | 595 | plain, |
552 | sizeof(ping_id) + num_nodes * sizeof(Node_format), | 596 | sizeof(ping_id) + num_nodes * Node4_format_size, |
553 | encrypt ); | 597 | encrypt ); |
554 | 598 | ||
555 | if (len == -1) | 599 | if (len == -1) |
556 | return -1; | 600 | return -1; |
557 | 601 | ||
558 | if ((unsigned int)len != sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING) | 602 | if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node4_format_size + ENCRYPTION_PADDING) |
559 | return -1; | 603 | return -1; |
560 | 604 | ||
561 | data[0] = NET_PACKET_SEND_NODES; | 605 | data[0] = NET_PACKET_SEND_NODES; |
@@ -563,7 +607,7 @@ 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); | 607 | memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); |
564 | memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); | 608 | memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); |
565 | 609 | ||
566 | return sendpacket(dht->c->lossless_udp->net->sock, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); | 610 | return sendpacket(dht->c->lossless_udp->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); |
567 | } | 611 | } |
568 | 612 | ||
569 | static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) | 613 | static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) |
@@ -606,22 +650,23 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3 | |||
606 | uint32_t cid_size = 1 + CLIENT_ID_SIZE; | 650 | uint32_t cid_size = 1 + CLIENT_ID_SIZE; |
607 | cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; | 651 | cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; |
608 | 652 | ||
609 | if (length > (cid_size + sizeof(Node_format) * MAX_SENT_NODES) || | 653 | size_t Node4_format_size = sizeof(Node4_format); |
610 | ((length - cid_size) % sizeof(Node_format)) != 0 || | 654 | if (length > (cid_size + Node4_format_size * MAX_SENT_NODES) || |
611 | (length < cid_size + sizeof(Node_format))) | 655 | ((length - cid_size) % Node4_format_size) != 0 || |
656 | (length < cid_size + Node4_format_size)) | ||
612 | return 1; | 657 | return 1; |
613 | 658 | ||
614 | uint32_t num_nodes = (length - cid_size) / sizeof(Node_format); | 659 | uint32_t num_nodes = (length - cid_size) / Node4_format_size; |
615 | uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES]; | 660 | uint8_t plain[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES]; |
616 | 661 | ||
617 | int len = decrypt_data( | 662 | int len = decrypt_data( |
618 | packet + 1, | 663 | packet + 1, |
619 | dht->c->self_secret_key, | 664 | dht->c->self_secret_key, |
620 | packet + 1 + CLIENT_ID_SIZE, | 665 | packet + 1 + CLIENT_ID_SIZE, |
621 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, | 666 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, |
622 | sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING, plain ); | 667 | sizeof(ping_id) + num_nodes * Node4_format_size + ENCRYPTION_PADDING, plain ); |
623 | 668 | ||
624 | if ((unsigned int)len != sizeof(ping_id) + num_nodes * sizeof(Node_format)) | 669 | if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node4_format_size) |
625 | return 1; | 670 | return 1; |
626 | 671 | ||
627 | memcpy(&ping_id, plain, sizeof(ping_id)); | 672 | memcpy(&ping_id, plain, sizeof(ping_id)); |
@@ -629,13 +674,33 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3 | |||
629 | if (!is_gettingnodes(dht, source, ping_id)) | 674 | if (!is_gettingnodes(dht, source, ping_id)) |
630 | return 1; | 675 | return 1; |
631 | 676 | ||
677 | uint32_t i; | ||
632 | Node_format nodes_list[MAX_SENT_NODES]; | 678 | Node_format nodes_list[MAX_SENT_NODES]; |
679 | |||
680 | #ifdef TOX_ENABLE_IPV6 | ||
681 | Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id)); | ||
682 | |||
683 | int num_nodes_ok = 0; | ||
684 | for(i = 0; i < num_nodes; i++) | ||
685 | if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != ~0)) { | ||
686 | memcpy(nodes_list[num_nodes_ok].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE); | ||
687 | nodes_list[num_nodes_ok].ip_port.ip.family = AF_INET; | ||
688 | nodes_list[num_nodes_ok].ip_port.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32; | ||
689 | nodes_list[num_nodes_ok].ip_port.port = nodes4_list[i].ip_port.port; | ||
690 | |||
691 | num_nodes_ok++; | ||
692 | } | ||
693 | |||
694 | if (num_nodes_ok < num_nodes) { | ||
695 | /* shouldn't happen */ | ||
696 | num_nodes = num_nodes_ok; | ||
697 | } | ||
698 | #else | ||
633 | memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format)); | 699 | memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format)); |
700 | #endif | ||
634 | 701 | ||
635 | addto_lists(dht, source, packet + 1); | 702 | addto_lists(dht, source, packet + 1); |
636 | 703 | ||
637 | uint32_t i; | ||
638 | |||
639 | for (i = 0; i < num_nodes; ++i) { | 704 | 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); | 705 | send_ping_request(dht->ping, dht->c, nodes_list[i].ip_port, nodes_list[i].client_id); |
641 | returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1); | 706 | returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1); |
@@ -703,27 +768,30 @@ int DHT_delfriend(DHT *dht, uint8_t *client_id) | |||
703 | } | 768 | } |
704 | 769 | ||
705 | /* TODO: Optimize this. */ | 770 | /* TODO: Optimize this. */ |
706 | IP_Port DHT_getfriendip(DHT *dht, uint8_t *client_id) | 771 | int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port) |
707 | { | 772 | { |
708 | uint32_t i, j; | 773 | uint32_t i, j; |
709 | uint64_t temp_time = unix_time(); | 774 | uint64_t temp_time = unix_time(); |
710 | IP_Port empty = {{{{0}}, 0, 0}}; | 775 | |
776 | ip_reset(&ip_port->ip); | ||
777 | ip_port->port = 0; | ||
711 | 778 | ||
712 | for (i = 0; i < dht->num_friends; ++i) { | 779 | for (i = 0; i < dht->num_friends; ++i) { |
713 | /* Equal */ | 780 | /* Equal */ |
714 | if (id_equal(dht->friends_list[i].client_id, client_id)) { | 781 | if (id_equal(dht->friends_list[i].client_id, client_id)) { |
715 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { | 782 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { |
716 | if (id_equal(dht->friends_list[i].client_list[j].client_id, client_id) | 783 | 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)) | 784 | && !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; | 785 | *ip_port = dht->friends_list[i].client_list[j].ip_port; |
786 | return 1; | ||
787 | } | ||
719 | } | 788 | } |
720 | 789 | ||
721 | return empty; | 790 | return 0; |
722 | } | 791 | } |
723 | } | 792 | } |
724 | 793 | ||
725 | empty.ip.uint32 = 1; | 794 | return -1; |
726 | return empty; | ||
727 | } | 795 | } |
728 | 796 | ||
729 | /* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request | 797 | /* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request |
@@ -808,6 +876,15 @@ 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); | 876 | getnodes(dht, ip_port, public_key, dht->c->self_public_key); |
809 | send_ping_request(dht->ping, dht->c, ip_port, public_key); | 877 | send_ping_request(dht->ping, dht->c, ip_port, public_key); |
810 | } | 878 | } |
879 | void DHT_bootstrap_ex(DHT *dht, const char *address, uint8_t ipv6enabled, uint16_t port, uint8_t *public_key) | ||
880 | { | ||
881 | IP_Port ip_port; | ||
882 | ip_init(&ip_port.ip, ipv6enabled); | ||
883 | if (addr_resolve_or_parse_ip(address, &ip_port.ip)) { | ||
884 | ip_port.port = port; | ||
885 | DHT_bootstrap(dht, ip_port, public_key); | ||
886 | } | ||
887 | } | ||
811 | 888 | ||
812 | /* Send the given packet to node with client_id | 889 | /* Send the given packet to node with client_id |
813 | * | 890 | * |
@@ -819,7 +896,7 @@ int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length) | |||
819 | 896 | ||
820 | for (i = 0; i < LCLIENT_LIST; ++i) { | 897 | for (i = 0; i < LCLIENT_LIST; ++i) { |
821 | if (id_equal(client_id, dht->close_clientlist[i].client_id)) | 898 | 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); | 899 | return sendpacket(dht->c->lossless_udp->net, dht->close_clientlist[i].ip_port, packet, length); |
823 | } | 900 | } |
824 | 901 | ||
825 | return -1; | 902 | return -1; |
@@ -848,7 +925,7 @@ static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num) | |||
848 | client = &friend->client_list[i]; | 925 | client = &friend->client_list[i]; |
849 | 926 | ||
850 | /* If ip is not zero and node is good. */ | 927 | /* 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)) { | 928 | if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { |
852 | 929 | ||
853 | if (id_equal(client->client_id, friend->client_id)) | 930 | if (id_equal(client->client_id, friend->client_id)) |
854 | return 0; | 931 | return 0; |
@@ -890,8 +967,8 @@ int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t lengt | |||
890 | client = &friend->client_list[i]; | 967 | client = &friend->client_list[i]; |
891 | 968 | ||
892 | /* If ip is not zero and node is good. */ | 969 | /* 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)) { | 970 | 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); | 971 | int retval = sendpacket(dht->c->lossless_udp->net, client->ip_port, packet, length); |
895 | 972 | ||
896 | if ((unsigned int)retval == length) | 973 | if ((unsigned int)retval == length) |
897 | ++sent; | 974 | ++sent; |
@@ -924,7 +1001,7 @@ static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint | |||
924 | client = &friend->client_list[i]; | 1001 | client = &friend->client_list[i]; |
925 | 1002 | ||
926 | /* If ip is not zero and node is good. */ | 1003 | /* 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)) { | 1004 | 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; | 1005 | ip_list[n] = client->ip_port; |
929 | ++n; | 1006 | ++n; |
930 | } | 1007 | } |
@@ -933,7 +1010,7 @@ static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint | |||
933 | if (n < 1) | 1010 | if (n < 1) |
934 | return 0; | 1011 | return 0; |
935 | 1012 | ||
936 | int retval = sendpacket(dht->c->lossless_udp->net->sock, ip_list[rand() % n], packet, length); | 1013 | int retval = sendpacket(dht->c->lossless_udp->net, ip_list[rand() % n], packet, length); |
937 | 1014 | ||
938 | if ((unsigned int)retval == length) | 1015 | if ((unsigned int)retval == length) |
939 | return 1; | 1016 | return 1; |
@@ -1032,7 +1109,8 @@ static int handle_NATping(void *object, IP_Port source, uint8_t *source_pubkey, | |||
1032 | */ | 1109 | */ |
1033 | static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num) | 1110 | static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num) |
1034 | { | 1111 | { |
1035 | IP zero = {{0}}; | 1112 | IP zero; |
1113 | ip_reset(&zero); | ||
1036 | 1114 | ||
1037 | if (len > MAX_FRIEND_CLIENTS) | 1115 | if (len > MAX_FRIEND_CLIENTS) |
1038 | return zero; | 1116 | return zero; |
@@ -1042,7 +1120,7 @@ static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num) | |||
1042 | 1120 | ||
1043 | for (i = 0; i < len; ++i) { | 1121 | for (i = 0; i < len; ++i) { |
1044 | for (j = 0; j < len; ++j) { | 1122 | for (j = 0; j < len; ++j) { |
1045 | if (ip_portlist[i].ip.uint32 == ip_portlist[j].ip.uint32) | 1123 | if (ip_equal(&ip_portlist[i].ip, &ip_portlist[j].ip)) |
1046 | ++numbers[i]; | 1124 | ++numbers[i]; |
1047 | } | 1125 | } |
1048 | 1126 | ||
@@ -1065,7 +1143,7 @@ static uint16_t NAT_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t | |||
1065 | uint16_t num = 0; | 1143 | uint16_t num = 0; |
1066 | 1144 | ||
1067 | for (i = 0; i < len; ++i) { | 1145 | for (i = 0; i < len; ++i) { |
1068 | if (ip_portlist[i].ip.uint32 == ip.uint32) { | 1146 | if (ip_equal(&ip_portlist[i].ip, &ip)) { |
1069 | portlist[num] = ntohs(ip_portlist[i].port); | 1147 | portlist[num] = ntohs(ip_portlist[i].port); |
1070 | ++num; | 1148 | ++num; |
1071 | } | 1149 | } |
@@ -1085,7 +1163,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++) { | 1163 | for (i = dht->friends_list[friend_num].punching_index; i != top; i++) { |
1086 | /* TODO: Improve port guessing algorithm. */ | 1164 | /* TODO: Improve port guessing algorithm. */ |
1087 | uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1); | 1165 | uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1); |
1088 | IP_Port pinging = {{ip, htons(port), 0}}; | 1166 | IP_Port pinging; |
1167 | ip_copy(&pinging.ip, &ip); | ||
1168 | pinging.port = htons(port); | ||
1089 | send_ping_request(dht->ping, dht->c, pinging, dht->friends_list[friend_num].client_id); | 1169 | send_ping_request(dht->ping, dht->c, pinging, dht->friends_list[friend_num].client_id); |
1090 | } | 1170 | } |
1091 | 1171 | ||
@@ -1115,8 +1195,7 @@ static void do_NAT(DHT *dht) | |||
1115 | dht->friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) { | 1195 | dht->friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) { |
1116 | 1196 | ||
1117 | IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2); | 1197 | IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2); |
1118 | 1198 | if (!ip_isset(&ip)) | |
1119 | if (ip.uint32 == 0) | ||
1120 | continue; | 1199 | continue; |
1121 | 1200 | ||
1122 | uint16_t port_list[MAX_FRIEND_CLIENTS]; | 1201 | uint16_t port_list[MAX_FRIEND_CLIENTS]; |
@@ -1145,16 +1224,15 @@ static void do_NAT(DHT *dht) | |||
1145 | */ | 1224 | */ |
1146 | int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port) | 1225 | int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port) |
1147 | { | 1226 | { |
1148 | if (ip_port.ip.uint32 == 0) | 1227 | if (!ip_isset(&ip_port.ip)) |
1149 | return -1; | 1228 | return -1; |
1150 | 1229 | ||
1151 | uint32_t i; | 1230 | uint32_t i; |
1152 | 1231 | ||
1153 | for (i = 0; i < MAX_TOPING; ++i) { | 1232 | for (i = 0; i < MAX_TOPING; ++i) { |
1154 | if (dht->toping[i].ip_port.ip.uint32 == 0) { | 1233 | if (!ip_isset(&dht->toping[i].ip_port.ip)) { |
1155 | memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); | 1234 | memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); |
1156 | dht->toping[i].ip_port.ip.uint32 = ip_port.ip.uint32; | 1235 | ipport_copy(&dht->toping[i].ip_port, &ip_port); |
1157 | dht->toping[i].ip_port.port = ip_port.port; | ||
1158 | return 0; | 1236 | return 0; |
1159 | } | 1237 | } |
1160 | } | 1238 | } |
@@ -1162,8 +1240,7 @@ int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port) | |||
1162 | for (i = 0; i < MAX_TOPING; ++i) { | 1240 | for (i = 0; i < MAX_TOPING; ++i) { |
1163 | if (id_closest(dht->c->self_public_key, dht->toping[i].client_id, client_id) == 2) { | 1241 | 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); | 1242 | memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); |
1165 | dht->toping[i].ip_port.ip.uint32 = ip_port.ip.uint32; | 1243 | ipport_copy(&dht->toping[i].ip_port, &ip_port); |
1166 | dht->toping[i].ip_port.port = ip_port.port; | ||
1167 | return 0; | 1244 | return 0; |
1168 | } | 1245 | } |
1169 | } | 1246 | } |
@@ -1185,11 +1262,11 @@ static void do_toping(DHT *dht) | |||
1185 | uint32_t i; | 1262 | uint32_t i; |
1186 | 1263 | ||
1187 | for (i = 0; i < MAX_TOPING; ++i) { | 1264 | for (i = 0; i < MAX_TOPING; ++i) { |
1188 | if (dht->toping[i].ip_port.ip.uint32 == 0) | 1265 | if (!ip_isset(&dht->toping[i].ip_port.ip)) |
1189 | return; | 1266 | return; |
1190 | 1267 | ||
1191 | send_ping_request(dht->ping, dht->c, dht->toping[i].ip_port, dht->toping[i].client_id); | 1268 | 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; | 1269 | ip_reset(&dht->toping[i].ip_port.ip); |
1193 | } | 1270 | } |
1194 | } | 1271 | } |
1195 | 1272 | ||