summaryrefslogtreecommitdiff
path: root/toxcore/DHT.c
diff options
context:
space:
mode:
authorCoren[m] <Break@Ocean>2013-09-09 19:17:21 +0200
committerCoren[m] <Break@Ocean>2013-09-09 19:17:21 +0200
commita77253c79b9c2acaa73164dcbd0694cb7b19db91 (patch)
treec8ccaa21afb3776748d2dae050d162b766d73740 /toxcore/DHT.c
parent9a8dc575b7a2004fbe6e8237a8565df390d76529 (diff)
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
Diffstat (limited to 'toxcore/DHT.c')
-rw-r--r--toxcore/DHT.c121
1 files changed, 103 insertions, 18 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 *