summaryrefslogtreecommitdiff
path: root/toxcore
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore')
-rw-r--r--toxcore/DHT.c201
-rw-r--r--toxcore/DHT.h35
-rw-r--r--toxcore/LAN_discovery.c85
-rw-r--r--toxcore/Lossless_UDP.c58
-rw-r--r--toxcore/Lossless_UDP.h6
-rw-r--r--toxcore/Messenger.c74
-rw-r--r--toxcore/Messenger.h2
-rw-r--r--toxcore/friend_requests.c12
-rw-r--r--toxcore/group_chats.c4
-rw-r--r--toxcore/net_crypto.c2
-rw-r--r--toxcore/network.c604
-rw-r--r--toxcore/network.h100
-rw-r--r--toxcore/ping.c10
-rw-r--r--toxcore/tox.c12
-rw-r--r--toxcore/tox.h65
-rw-r--r--toxcore/util.c37
-rw-r--r--toxcore/util.h18
17 files changed, 1119 insertions, 206 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
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;
@@ -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 */
200static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list) 194static 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 */
525static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id) 550static 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
569static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) 613static 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. */
706IP_Port DHT_getfriendip(DHT *dht, uint8_t *client_id) 771int 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}
879void 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 */
1033static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num) 1110static 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 */
1146int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port) 1225int 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
diff --git a/toxcore/DHT.h b/toxcore/DHT.h
index e5122b5e..d980f269 100644
--- a/toxcore/DHT.h
+++ b/toxcore/DHT.h
@@ -75,10 +75,22 @@ 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 */
79typedef struct {
80 uint8_t client_id[CLIENT_ID_SIZE];
81 IP4_Port ip_port;
82} Node4_format;
83
78typedef struct { 84typedef struct {
79 uint8_t client_id[CLIENT_ID_SIZE]; 85 uint8_t client_id[CLIENT_ID_SIZE];
80 IP_Port ip_port; 86 IP_Port ip_port;
81} Node_format; 87} Node46_format;
88
89#ifdef TOX_ENABLE_IPV6
90typedef Node46_format Node_format;
91#else
92typedef Node4_format Node_format;
93#endif
82 94
83typedef struct { 95typedef struct {
84 IP_Port ip_port; 96 IP_Port ip_port;
@@ -88,15 +100,15 @@ typedef struct {
88 100
89/*----------------------------------------------------------------------------------*/ 101/*----------------------------------------------------------------------------------*/
90typedef struct { 102typedef struct {
91 Net_Crypto *c; 103 Net_Crypto *c;
92 Client_data close_clientlist[LCLIENT_LIST]; 104 Client_data close_clientlist[LCLIENT_LIST];
93 DHT_Friend *friends_list; 105 DHT_Friend *friends_list;
94 uint16_t num_friends; 106 uint16_t num_friends;
95 Pinged send_nodes[LSEND_NODES_ARRAY]; 107 Pinged send_nodes[LSEND_NODES_ARRAY];
96 Node_format toping[MAX_TOPING]; 108 Node_format toping[MAX_TOPING];
97 uint64_t last_toping; 109 uint64_t last_toping;
98 uint64_t close_lastgetnodes; 110 uint64_t close_lastgetnodes;
99 void *ping; 111 void *ping;
100} DHT; 112} DHT;
101/*----------------------------------------------------------------------------------*/ 113/*----------------------------------------------------------------------------------*/
102 114
@@ -124,11 +136,21 @@ int DHT_delfriend(DHT *dht, uint8_t *client_id);
124 * ip must be 4 bytes long. 136 * ip must be 4 bytes long.
125 * port must be 2 bytes long. 137 * port must be 2 bytes long.
126 * 138 *
139 * !!! Signature changed!!!
140 *
141 * OLD: IP_Port DHT_getfriendip(DHT *dht, uint8_t *client_id);
142 *
127 * return ip if success. 143 * return ip if success.
128 * return ip of 0 if failure (This means the friend is either offline or we have not found him yet). 144 * return ip of 0 if failure (This means the friend is either offline or we have not found him yet).
129 * return ip of 1 if friend is not in list. 145 * return ip of 1 if friend is not in list.
146 *
147 * NEW: int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port);
148 *
149 * return -1, -- if client_id does NOT refer to a friend
150 * return 0, -- if client_id refers to a friend and we failed to find the friend (yet)
151 * return 1, ip if client_id refers to a friend and we found him
130 */ 152 */
131IP_Port DHT_getfriendip(DHT *dht, uint8_t *client_id); 153int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port);
132 154
133/* Run this function at least a couple times per second (It's the main loop). */ 155/* Run this function at least a couple times per second (It's the main loop). */
134void do_DHT(DHT *dht); 156void do_DHT(DHT *dht);
@@ -137,6 +159,7 @@ void do_DHT(DHT *dht);
137 * Sends a get nodes request to the given node with ip port and public_key. 159 * Sends a get nodes request to the given node with ip port and public_key.
138 */ 160 */
139void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key); 161void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key);
162void DHT_bootstrap_ex(DHT *dht, const char *address, uint8_t ipv6enabled, uint16_t port, uint8_t *public_key);
140 163
141/* Add nodes to the toping list. 164/* Add nodes to the toping list.
142 * All nodes in this list are pinged every TIME_TOPING seconds 165 * All nodes in this list are pinged every TIME_TOPING seconds
diff --git a/toxcore/LAN_discovery.c b/toxcore/LAN_discovery.c
index 1980cd93..4cbe3177 100644
--- a/toxcore/LAN_discovery.c
+++ b/toxcore/LAN_discovery.c
@@ -71,7 +71,7 @@ static uint32_t send_broadcasts(Networking_Core *net, uint16_t port, uint8_t * d
71 sock_holder = (struct sockaddr_in *)&i_faces[i].ifr_broadaddr; 71 sock_holder = (struct sockaddr_in *)&i_faces[i].ifr_broadaddr;
72 if (sock_holder != NULL) { 72 if (sock_holder != NULL) {
73 IP_Port ip_port = {{{{sock_holder->sin_addr.s_addr}}, port, 0}}; 73 IP_Port ip_port = {{{{sock_holder->sin_addr.s_addr}}, port, 0}};
74 sendpacket(net->sock, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES); 74 sendpacket(net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES);
75 } 75 }
76 } 76 }
77 77
@@ -81,10 +81,32 @@ static uint32_t send_broadcasts(Networking_Core *net, uint16_t port, uint8_t * d
81#endif 81#endif
82 82
83/* Return the broadcast ip. */ 83/* Return the broadcast ip. */
84static IP broadcast_ip(void) 84static IP broadcast_ip(sa_family_t sa_family)
85{ 85{
86 IP ip; 86 IP ip;
87 ip.uint32 = ~0; 87 ip_reset(&ip);
88
89#ifdef TOX_ENABLE_IPV6
90 if (sa_family == AF_INET)
91 {
92 ip.family = AF_INET;
93 ip.ip4.uint32 = INADDR_BROADCAST;
94 }
95
96 if (sa_family == AF_INET6)
97 {
98 ip.family = AF_INET6;
99 /* FF02::1 is - according to RFC 4291 - multicast all-nodes link-local */
100 /* FE80::*: MUST be exact, for that we would need to look over all
101 * interfaces and check in which status they are */
102 ip.ip6.s6_addr[ 0] = 0xFF;
103 ip.ip6.s6_addr[ 1] = 0x02;
104 ip.ip6.s6_addr[15] = 0x01;
105 }
106#else
107 ip.uint32 = INADDR_BROADCAST;
108#endif
109
88 return ip; 110 return ip;
89} 111}
90 112
@@ -93,21 +115,42 @@ static IP broadcast_ip(void)
93 */ 115 */
94static int LAN_ip(IP ip) 116static int LAN_ip(IP ip)
95{ 117{
96 if (ip.uint8[0] == 127) /* Loopback. */ 118#ifdef TOX_ENABLE_IPV6
97 return 0; 119 if (ip.family == AF_INET) {
98 120 IP4 ip4 = ip.ip4;
99 if (ip.uint8[0] == 10) /* 10.0.0.0 to 10.255.255.255 range. */ 121#else
100 return 0; 122 IP4 ip4 = ip;
101 123#endif
102 if (ip.uint8[0] == 172 && ip.uint8[1] >= 16 && ip.uint8[1] <= 31) /* 172.16.0.0 to 172.31.255.255 range. */ 124 /* Loopback. */
103 return 0; 125 if (ip4.uint8[0] == 127)
104 126 return 0;
105 if (ip.uint8[0] == 192 && ip.uint8[1] == 168) /* 192.168.0.0 to 192.168.255.255 range. */ 127
106 return 0; 128 /* 10.0.0.0 to 10.255.255.255 range. */
107 129 if (ip4.uint8[0] == 10)
108 if (ip.uint8[0] == 169 && ip.uint8[1] == 254 && ip.uint8[2] != 0 130 return 0;
109 && ip.uint8[2] != 255)/* 169.254.1.0 to 169.254.254.255 range. */ 131
110 return 0; 132 /* 172.16.0.0 to 172.31.255.255 range. */
133 if (ip4.uint8[0] == 172 && ip4.uint8[1] >= 16 && ip4.uint8[1] <= 31)
134 return 0;
135
136 /* 192.168.0.0 to 192.168.255.255 range. */
137 if (ip4.uint8[0] == 192 && ip4.uint8[1] == 168)
138 return 0;
139
140 /* 169.254.1.0 to 169.254.254.255 range. */
141 if (ip4.uint8[0] == 169 && ip4.uint8[1] == 254 && ip4.uint8[2] != 0
142 && ip4.uint8[2] != 255)
143 return 0;
144#ifdef TOX_ENABLE_IPV6
145 }
146 else if (ip.family == AF_INET6) {
147 /* autogenerated for each interface: FE80::* (up to FEBF::*)
148 /* FF02::1 is - according to RFC 4291 - multicast all-nodes link-local */
149 if (((ip.ip6.s6_addr[0] == 0xFF) && (ip.ip6.s6_addr[1] < 3) && (ip.ip6.s6_addr[15] == 1)) ||
150 ((ip.ip6.s6_addr[0] == 0xFE) && ((ip.ip6.s6_addr[1] & 0xC0) == 0x80)))
151 return 0;
152 }
153#endif
111 154
112 return -1; 155 return -1;
113} 156}
@@ -135,8 +178,10 @@ int send_LANdiscovery(uint16_t port, Net_Crypto *c)
135#ifdef __linux 178#ifdef __linux
136 send_broadcasts(c->lossless_udp->net, port, data, 1 + crypto_box_PUBLICKEYBYTES); 179 send_broadcasts(c->lossless_udp->net, port, data, 1 + crypto_box_PUBLICKEYBYTES);
137#endif 180#endif
138 IP_Port ip_port = {{broadcast_ip(), port, 0}}; 181 IP_Port ip_port;
139 return sendpacket(c->lossless_udp->net->sock, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES); 182 ip_port.ip = broadcast_ip(c->lossless_udp->net->family);
183 ip_port.port = port;
184 return sendpacket(c->lossless_udp->net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES);
140} 185}
141 186
142 187
diff --git a/toxcore/Lossless_UDP.c b/toxcore/Lossless_UDP.c
index fbb473e7..ca874562 100644
--- a/toxcore/Lossless_UDP.c
+++ b/toxcore/Lossless_UDP.c
@@ -44,9 +44,7 @@
44int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port) 44int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port)
45{ 45{
46 tox_array_for_each(&ludp->connections, Connection, tmp) { 46 tox_array_for_each(&ludp->connections, Connection, tmp) {
47 if (tmp->ip_port.ip.uint32 == ip_port.ip.uint32 && 47 if (tmp-> status > 0 && ipport_equal(&tmp->ip_port, &ip_port)) {
48 tmp->ip_port.port == ip_port.port &&
49 tmp->status > 0) {
50 return tmp_i; 48 return tmp_i;
51 } 49 }
52 } 50 }
@@ -61,17 +59,49 @@ int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port)
61 * 59 *
62 * TODO: make this better 60 * TODO: make this better
63 */ 61 */
64static uint32_t handshake_id(Lossless_UDP *ludp, IP_Port source) 62
63static uint8_t randtable_initget(Lossless_UDP *ludp, uint32_t index, uint8_t value)
65{ 64{
66 uint32_t id = 0, i; 65 if (ludp->randtable[index][value] == 0)
66 ludp->randtable[index][value] = random_int();
67 67
68 for (i = 0; i < 6; ++i) { 68 return ludp->randtable[index][value];
69 if (ludp->randtable[i][source.uint8[i]] == 0) 69}
70 ludp->randtable[i][source.uint8[i]] = random_int();
71 70
72 id ^= ludp->randtable[i][source.uint8[i]]; 71static uint32_t handshake_id(Lossless_UDP *ludp, IP_Port source)
72{
73 uint32_t id = 0, i = 0;
74
75 uint8_t *uint8;
76 uint8 = (uint8_t *)&source.port;
77 id ^= randtable_initget(ludp, i, *uint8);
78 i++, uint8++;
79 id ^= randtable_initget(ludp, i, *uint8);
80 i++;
81
82#ifdef TOX_ENABLE_IPV6
83 if (source.ip.family == AF_INET)
84 {
85 IP4 ip4 = source.ip.ip4;
86#else
87 IP4 ip4 = source.ip;
88#endif
89 int k;
90 for (k = 0; k < 4; k++) {
91 id ^= randtable_initget(ludp, i++, ip4.uint8[k]);
92 }
93#ifdef TOX_ENABLE_IPV6
73 } 94 }
74 95
96 if (source.ip.family == AF_INET6)
97 {
98 int k;
99 for (k = 0; k < 16; k++) {
100 id ^= randtable_initget(ludp, i++, source.ip.ip6.s6_addr[k]);
101 }
102 }
103#endif
104
75 /* id can't be zero. */ 105 /* id can't be zero. */
76 if (id == 0) 106 if (id == 0)
77 id = 1; 107 id = 1;
@@ -290,7 +320,9 @@ IP_Port connection_ip(Lossless_UDP *ludp, int connection_id)
290 if ((unsigned int)connection_id < ludp->connections.len) 320 if ((unsigned int)connection_id < ludp->connections.len)
291 return tox_array_get(&ludp->connections, connection_id, Connection).ip_port; 321 return tox_array_get(&ludp->connections, connection_id, Connection).ip_port;
292 322
293 IP_Port zero = {{{{0}}, 0, 0}}; 323 IP_Port zero;
324 ip_reset(&zero.ip);
325 zero.port = 0;
294 return zero; 326 return zero;
295} 327}
296 328
@@ -429,7 +461,7 @@ static int send_handshake(Lossless_UDP *ludp, IP_Port ip_port, uint32_t handshak
429 temp = htonl(handshake_id2); 461 temp = htonl(handshake_id2);
430 memcpy(packet + 5, &temp, 4); 462 memcpy(packet + 5, &temp, 4);
431 463
432 return sendpacket(ludp->net->sock, ip_port, packet, sizeof(packet)); 464 return sendpacket(ludp->net, ip_port, packet, sizeof(packet));
433} 465}
434 466
435static int send_SYNC(Lossless_UDP *ludp, int connection_id) 467static int send_SYNC(Lossless_UDP *ludp, int connection_id)
@@ -456,7 +488,7 @@ static int send_SYNC(Lossless_UDP *ludp, int connection_id)
456 index += 4; 488 index += 4;
457 memcpy(packet + index, requested, 4 * number); 489 memcpy(packet + index, requested, 4 * number);
458 490
459 return sendpacket(ludp->net->sock, ip_port, packet, (number * 4 + 4 + 4 + 2)); 491 return sendpacket(ludp->net, ip_port, packet, (number * 4 + 4 + 4 + 2));
460 492
461} 493}
462 494
@@ -471,7 +503,7 @@ static int send_data_packet(Lossless_UDP *ludp, int connection_id, uint32_t pack
471 temp = htonl(packet_num); 503 temp = htonl(packet_num);
472 memcpy(packet + 1, &temp, 4); 504 memcpy(packet + 1, &temp, 4);
473 memcpy(packet + 5, connection->sendbuffer[index].data, connection->sendbuffer[index].size); 505 memcpy(packet + 5, connection->sendbuffer[index].data, connection->sendbuffer[index].size);
474 return sendpacket(ludp->net->sock, connection->ip_port, packet, 1 + 4 + connection->sendbuffer[index].size); 506 return sendpacket(ludp->net, connection->ip_port, packet, 1 + 4 + connection->sendbuffer[index].size);
475} 507}
476 508
477/* Sends 1 data packet. */ 509/* Sends 1 data packet. */
diff --git a/toxcore/Lossless_UDP.h b/toxcore/Lossless_UDP.h
index 20471b0a..f0ce0e87 100644
--- a/toxcore/Lossless_UDP.h
+++ b/toxcore/Lossless_UDP.h
@@ -123,7 +123,13 @@ typedef struct {
123 tox_array connections; 123 tox_array connections;
124 124
125 /* Table of random numbers used in handshake_id. */ 125 /* Table of random numbers used in handshake_id. */
126#ifdef TOX_ENABLE_IPV6
127 /* IPv6 (16) + port (2)*/
128 uint32_t randtable[18][256];
129#else
130 /* IPv4 (4) + port (2) */
126 uint32_t randtable[6][256]; 131 uint32_t randtable[6][256];
132#endif
127 133
128} Lossless_UDP; 134} Lossless_UDP;
129 135
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index b712d142..b955ad5a 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -651,7 +651,7 @@ static void LANdiscovery(Messenger *m)
651} 651}
652 652
653/* Run this at startup. */ 653/* Run this at startup. */
654Messenger *initMessenger(void) 654Messenger *initMessenger(uint8_t ipv6enabled)
655{ 655{
656 Messenger *m = calloc(1, sizeof(Messenger)); 656 Messenger *m = calloc(1, sizeof(Messenger));
657 657
@@ -659,7 +659,7 @@ Messenger *initMessenger(void)
659 return NULL; 659 return NULL;
660 660
661 IP ip; 661 IP ip;
662 ip.uint32 = 0; 662 ip_init(&ip, ipv6enabled);
663 m->net = new_networking(ip, PORT); 663 m->net = new_networking(ip, PORT);
664 664
665 if (m->net == NULL) { 665 if (m->net == NULL) {
@@ -743,11 +743,12 @@ void doFriends(Messenger *m)
743 } 743 }
744 } 744 }
745 745
746 IP_Port friendip = DHT_getfriendip(m->dht, m->friendlist[i].client_id); 746 IP_Port friendip;
747 int friendok = DHT_getfriendip(m->dht, m->friendlist[i].client_id, &friendip);
747 748
748 switch (is_cryptoconnected(m->net_crypto, m->friendlist[i].crypt_connection_id)) { 749 switch (is_cryptoconnected(m->net_crypto, m->friendlist[i].crypt_connection_id)) {
749 case 0: 750 case 0:
750 if (friendip.ip.uint32 > 1) 751 if (friendok == 1)
751 m->friendlist[i].crypt_connection_id = crypto_connect(m->net_crypto, m->friendlist[i].client_id, friendip); 752 m->friendlist[i].crypt_connection_id = crypto_connect(m->net_crypto, m->friendlist[i].client_id, friendip);
752 753
753 break; 754 break;
@@ -964,19 +965,23 @@ void Messenger_save(Messenger *m, uint8_t *data)
964{ 965{
965 save_keys(m->net_crypto, data); 966 save_keys(m->net_crypto, data);
966 data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; 967 data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
968
967 uint32_t nospam = get_nospam(&(m->fr)); 969 uint32_t nospam = get_nospam(&(m->fr));
968 memcpy(data, &nospam, sizeof(nospam)); 970 memcpy(data, &nospam, sizeof(nospam));
969 data += sizeof(nospam); 971 data += sizeof(nospam);
972
970 uint32_t size = DHT_size(m->dht); 973 uint32_t size = DHT_size(m->dht);
971 memcpy(data, &size, sizeof(size)); 974 memcpy(data, &size, sizeof(size));
972 data += sizeof(size); 975 data += sizeof(size);
973 DHT_save(m->dht, data); 976 DHT_save(m->dht, data);
974 data += size; 977 data += size;
978
975 size = sizeof(Friend) * m->numfriends; 979 size = sizeof(Friend) * m->numfriends;
976 memcpy(data, &size, sizeof(size)); 980 memcpy(data, &size, sizeof(size));
977 data += sizeof(size); 981 data += sizeof(size);
978 memcpy(data, m->friendlist, sizeof(Friend) * m->numfriends); 982 memcpy(data, m->friendlist, sizeof(Friend) * m->numfriends);
979 data += size; 983 data += size;
984
980 uint16_t small_size = m->name_length; 985 uint16_t small_size = m->name_length;
981 memcpy(data, &small_size, sizeof(small_size)); 986 memcpy(data, &small_size, sizeof(small_size));
982 data += sizeof(small_size); 987 data += sizeof(small_size);
@@ -989,59 +994,64 @@ int Messenger_load(Messenger *m, uint8_t *data, uint32_t length)
989 if (length == ~((uint32_t)0)) 994 if (length == ~((uint32_t)0))
990 return -1; 995 return -1;
991 996
992 if (length < crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t) * 3) 997 /* BLOCK1: PUBKEY, SECKEY, NOSPAM, SIZE */
998 if (length < crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t) * 2)
993 return -1; 999 return -1;
994 1000
995 length -= crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t) * 3;
996 load_keys(m->net_crypto, data); 1001 load_keys(m->net_crypto, data);
997 data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; 1002 data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
1003 length -= crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
1004
998 uint32_t nospam; 1005 uint32_t nospam;
999 memcpy(&nospam, data, sizeof(nospam)); 1006 memcpy(&nospam, data, sizeof(nospam));
1000 set_nospam(&(m->fr), nospam); 1007 set_nospam(&(m->fr), nospam);
1001 data += sizeof(nospam); 1008 data += sizeof(nospam);
1009 length -= sizeof(nospam);
1010
1002 uint32_t size; 1011 uint32_t size;
1003 memcpy(&size, data, sizeof(size)); 1012 memcpy(&size, data, sizeof(size));
1004 data += sizeof(size); 1013 data += sizeof(size);
1014 length -= sizeof(size);
1005 1015
1006 if (length < size) 1016 if (length < size)
1007 return -1; 1017 return -1;
1008 1018
1009 length -= size;
1010
1011 if (DHT_load(m->dht, data, size) == -1) 1019 if (DHT_load(m->dht, data, size) == -1)
1012 return -1; 1020 fprintf(stderr, "Data file: Something wicked happened to the stored connections.\n");
1021
1022 /* go on, friends still might be intact */
1013 1023
1014 data += size; 1024 data += size;
1025 length -= size;
1026
1015 memcpy(&size, data, sizeof(size)); 1027 memcpy(&size, data, sizeof(size));
1016 data += sizeof(size); 1028 data += sizeof(size);
1017 1029 if (length < size)
1018 if (length < size || size % sizeof(Friend) != 0)
1019 return -1; 1030 return -1;
1020 1031
1021 Friend *temp = malloc(size); 1032 if (!(size % sizeof(Friend))) {
1022 memcpy(temp, data, size); 1033 uint16_t num = size / sizeof(Friend);
1023 1034 Friend temp[num];
1024 uint16_t num = size / sizeof(Friend); 1035 memcpy(temp, data, size);
1025 1036
1026 uint32_t i; 1037 uint32_t i;
1027 1038 for (i = 0; i < num; ++i) {
1028 for (i = 0; i < num; ++i) { 1039 if (temp[i].status >= 3) {
1029 if (temp[i].status >= 3) { 1040 int fnum = m_addfriend_norequest(m, temp[i].client_id);
1030 int fnum = m_addfriend_norequest(m, temp[i].client_id); 1041 setfriendname(m, fnum, temp[i].name, temp[i].name_length);
1031 setfriendname(m, fnum, temp[i].name, temp[i].name_length); 1042 /* set_friend_statusmessage(fnum, temp[i].statusmessage, temp[i].statusmessage_length); */
1032 /* set_friend_statusmessage(fnum, temp[i].statusmessage, temp[i].statusmessage_length); */ 1043 } else if (temp[i].status != 0) {
1033 } else if (temp[i].status != 0) { 1044 /* TODO: This is not a good way to do this. */
1034 /* TODO: This is not a good way to do this. */ 1045 uint8_t address[FRIEND_ADDRESS_SIZE];
1035 uint8_t address[FRIEND_ADDRESS_SIZE]; 1046 memcpy(address, temp[i].client_id, crypto_box_PUBLICKEYBYTES);
1036 memcpy(address, temp[i].client_id, crypto_box_PUBLICKEYBYTES); 1047 memcpy(address + crypto_box_PUBLICKEYBYTES, &(temp[i].friendrequest_nospam), sizeof(uint32_t));
1037 memcpy(address + crypto_box_PUBLICKEYBYTES, &(temp[i].friendrequest_nospam), sizeof(uint32_t)); 1048 uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum));
1038 uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum)); 1049 memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(uint32_t), &checksum, sizeof(checksum));
1039 memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(uint32_t), &checksum, sizeof(checksum)); 1050 m_addfriend(m, address, temp[i].info, temp[i].info_size);
1040 m_addfriend(m, address, temp[i].info, temp[i].info_size); 1051 }
1041 } 1052 }
1042 } 1053 }
1043 1054
1044 free(temp);
1045 data += size; 1055 data += size;
1046 length -= size; 1056 length -= size;
1047 1057
diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h
index 40617d08..dfb3f7c6 100644
--- a/toxcore/Messenger.h
+++ b/toxcore/Messenger.h
@@ -371,7 +371,7 @@ void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, in
371 * return allocated instance of Messenger on success. 371 * return allocated instance of Messenger on success.
372 * return 0 if there are problems. 372 * return 0 if there are problems.
373 */ 373 */
374Messenger *initMessenger(void); 374Messenger *initMessenger(uint8_t ipv6enabled);
375 375
376/* Run this before closing shop 376/* Run this before closing shop
377 * Free all datastructures. 377 * Free all datastructures.
diff --git a/toxcore/friend_requests.c b/toxcore/friend_requests.c
index b01015c4..c821d998 100644
--- a/toxcore/friend_requests.c
+++ b/toxcore/friend_requests.c
@@ -50,18 +50,22 @@ int send_friendrequest(DHT *dht, uint8_t *public_key, uint32_t nospam_num, uint8
50 if (len == -1) 50 if (len == -1)
51 return -1; 51 return -1;
52 52
53 IP_Port ip_port = DHT_getfriendip(dht, public_key); 53 IP_Port ip_port;
54 int friendok = DHT_getfriendip(dht, public_key, &ip_port);
54 55
55 if (ip_port.ip.uint32 == 1) 56 // not a friend
57 if (friendok == -1)
56 return -1; 58 return -1;
57 59
58 if (ip_port.ip.uint32 != 0) { 60 // is a friend and we know how to reach him
59 if (sendpacket(dht->c->lossless_udp->net->sock, ip_port, packet, len) != -1) 61 if (friendok == 1) {
62 if (sendpacket(dht->c->lossless_udp->net, ip_port, packet, len) != -1)
60 return 0; 63 return 0;
61 64
62 return -1; 65 return -1;
63 } 66 }
64 67
68 // is a friend, we DON'T know how to reach him
65 int num = route_tofriend(dht, public_key, packet, len); 69 int num = route_tofriend(dht, public_key, packet, len);
66 70
67 if (num == 0) 71 if (num == 0)
diff --git a/toxcore/group_chats.c b/toxcore/group_chats.c
index 3c134348..59266b7a 100644
--- a/toxcore/group_chats.c
+++ b/toxcore/group_chats.c
@@ -185,7 +185,7 @@ static int send_groupchatpacket(Group_Chat *chat, IP_Port ip_port, uint8_t *publ
185 if (len == -1) 185 if (len == -1)
186 return -1; 186 return -1;
187 187
188 if (sendpacket(chat->net->sock, ip_port, packet, len) == len) 188 if (sendpacket(chat->net, ip_port, packet, len) == len)
189 return 0; 189 return 0;
190 190
191 return -1; 191 return -1;
@@ -204,7 +204,7 @@ static uint8_t sendto_allpeers(Group_Chat *chat, uint8_t *data, uint16_t length,
204 uint64_t temp_time = unix_time(); 204 uint64_t temp_time = unix_time();
205 205
206 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { 206 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) {
207 if (chat->close[i].ip_port.ip.uint32 != 0 && chat->close[i].last_recv + BAD_NODE_TIMEOUT > temp_time) { 207 if (ip_isset(&chat->close[i].ip_port.ip) && chat->close[i].last_recv + BAD_NODE_TIMEOUT > temp_time) {
208 if (send_groupchatpacket(chat, chat->close[i].ip_port, chat->close[i].client_id, data, length, request_id) == 0) 208 if (send_groupchatpacket(chat, chat->close[i].ip_port, chat->close[i].client_id, data, length, request_id) == 0)
209 ++sent; 209 ++sent;
210 } 210 }
diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c
index a182bb53..b6f08fe4 100644
--- a/toxcore/net_crypto.c
+++ b/toxcore/net_crypto.c
@@ -439,7 +439,7 @@ int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port)
439 if (id != -1) { 439 if (id != -1) {
440 IP_Port c_ip = connection_ip(c->lossless_udp, c->crypto_connections[id].number); 440 IP_Port c_ip = connection_ip(c->lossless_udp, c->crypto_connections[id].number);
441 441
442 if (c_ip.ip.uint32 == ip_port.ip.uint32 && c_ip.port == ip_port.port) 442 if (ipport_equal(&c_ip, &ip_port))
443 return -1; 443 return -1;
444 } 444 }
445 445
diff --git a/toxcore/network.c b/toxcore/network.c
index ed3dff8a..0b5eba61 100644
--- a/toxcore/network.c
+++ b/toxcore/network.c
@@ -26,6 +26,7 @@
26#endif 26#endif
27 27
28#include "network.h" 28#include "network.h"
29#include "util.h"
29 30
30/* return current UNIX time in microseconds (us). */ 31/* return current UNIX time in microseconds (us). */
31uint64_t current_time(void) 32uint64_t current_time(void)
@@ -61,17 +62,76 @@ uint32_t random_int(void)
61#endif 62#endif
62} 63}
63 64
65#ifdef LOGGING
66static void loglogdata(char *message, uint8_t *buffer, size_t buflen, IP_Port *ip_port, ssize_t res);
67#endif
68
64/* Basic network functions: 69/* Basic network functions:
65 * Function to send packet(data) of length length to ip_port. 70 * Function to send packet(data) of length length to ip_port.
66 */ 71 */
67#ifdef WIN32 72int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t length)
68int sendpacket(unsigned int sock, IP_Port ip_port, uint8_t *data, uint32_t length) 73{
74#ifdef TOX_ENABLE_IPV6
75 /* socket AF_INET, but target IP NOT: can't send */
76 if ((net->family == AF_INET) && (ip_port.ip.family != AF_INET))
77 return 0;
78#endif
79
80 struct sockaddr_storage addr;
81 size_t addrsize = 0;
82
83#ifdef TOX_ENABLE_IPV6
84 if (ip_port.ip.family == AF_INET) {
85 if (net->family == AF_INET6) {
86 /* must convert to IPV4-in-IPV6 address */
87 addrsize = sizeof(struct sockaddr_in6);
88 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
89 addr6->sin6_family = AF_INET6;
90 addr6->sin6_port = ip_port.port;
91
92 /* there should be a macro for this in a standards compliant
93 * environment, not found */
94 addr6->sin6_addr.s6_addr32[0] = 0;
95 addr6->sin6_addr.s6_addr32[1] = 0;
96 addr6->sin6_addr.s6_addr32[2] = htonl(0xFFFF);
97 addr6->sin6_addr.s6_addr32[3] = ip_port.ip.ip4.uint32;
98
99 addr6->sin6_flowinfo = 0;
100 addr6->sin6_scope_id = 0;
101 }
102 else {
103 IP4 ip4 = ip_port.ip.ip4;
69#else 104#else
70int sendpacket(int sock, IP_Port ip_port, uint8_t *data, uint32_t length) 105 IP4 ip4 = ip_port.ip;
71#endif 106#endif
72{ 107 addrsize = sizeof(struct sockaddr_in);
73 ADDR addr = {AF_INET, ip_port.port, ip_port.ip, {0}}; 108 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
74 return sendto(sock, (char *) data, length, 0, (struct sockaddr *)&addr, sizeof(addr)); 109 addr4->sin_family = AF_INET;
110 addr4->sin_addr = ip4.in_addr;
111 addr4->sin_port = ip_port.port;
112#ifdef TOX_ENABLE_IPV6
113 }
114 }
115 else if (ip_port.ip.family == AF_INET6) {
116 addrsize = sizeof(struct sockaddr_in6);
117 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
118 addr6->sin6_family = AF_INET6;
119 addr6->sin6_port = ip_port.port;
120 addr6->sin6_addr = ip_port.ip.ip6;
121
122 addr6->sin6_flowinfo = 0;
123 addr6->sin6_scope_id = 0;
124 } else {
125 /* unknown address type*/
126 return 0;
127 }
128#endif
129
130 int res = sendto(net->sock, (char *) data, length, 0, (struct sockaddr *)&addr, addrsize);
131#ifdef LOGGING
132 loglogdata("O=>", data, length, &ip_port, res);
133#endif
134 return res;
75} 135}
76 136
77/* Function to receive data 137/* Function to receive data
@@ -80,13 +140,9 @@ int sendpacket(int sock, IP_Port ip_port, uint8_t *data, uint32_t length)
80 * Packet length is put into length. 140 * Packet length is put into length.
81 * Dump all empty packets. 141 * Dump all empty packets.
82 */ 142 */
83#ifdef WIN32 143static int receivepacket(sock_t sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
84static int receivepacket(unsigned int sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
85#else
86static int receivepacket(int sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
87#endif
88{ 144{
89 ADDR addr; 145 struct sockaddr_storage addr;
90#ifdef WIN32 146#ifdef WIN32
91 int addrlen = sizeof(addr); 147 int addrlen = sizeof(addr);
92#else 148#else
@@ -94,11 +150,43 @@ static int receivepacket(int sock, IP_Port *ip_port, uint8_t *data, uint32_t *le
94#endif 150#endif
95 (*(int32_t *)length) = recvfrom(sock, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen); 151 (*(int32_t *)length) = recvfrom(sock, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen);
96 152
97 if (*(int32_t *)length <= 0) 153 if (*(int32_t *)length <= 0) {
154#ifdef LOGGING
155 if ((length < 0) && (errno != EWOULDBLOCK))
156 sprintf(logbuffer, "Unexpected error reading from socket: %u, %s\n", errno, strerror(errno));
157#endif
98 return -1; /* Nothing received or empty packet. */ 158 return -1; /* Nothing received or empty packet. */
159 }
160
161#ifdef TOX_ENABLE_IPV6
162 if (addr.ss_family == AF_INET) {
163 struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr;
164 ip_port->ip.family = addr_in->sin_family;
165 ip_port->ip.ip4.in_addr = addr_in->sin_addr;
166 ip_port->port = addr_in->sin_port;
167 }
168 else if (addr.ss_family == AF_INET6) {
169 struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)&addr;
170 ip_port->ip.family = addr_in6->sin6_family;
171 ip_port->ip.ip6 = addr_in6->sin6_addr;
172 ip_port->port = addr_in6->sin6_port;
173 }
174 else
175 return -1;
176#else
177 if (addr.ss_family == AF_INET) {
178 struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr;
179 ip_port->ip.in_addr = addr_in->sin_addr;
180 ip_port->port = addr_in->sin_port;
181 }
182 else
183 return -1;
184#endif
185
186#ifdef LOGGING
187 loglogdata("=>O", data, *length, ip_port, 0);
188#endif
99 189
100 ip_port->ip = addr.ip;
101 ip_port->port = addr.port;
102 return 0; 190 return 0;
103} 191}
104 192
@@ -162,16 +250,31 @@ static void at_shutdown(void)
162 */ 250 */
163Networking_Core *new_networking(IP ip, uint16_t port) 251Networking_Core *new_networking(IP ip, uint16_t port)
164{ 252{
253#ifdef TOX_ENABLE_IPV6
254 /* maybe check for invalid IPs like 224+.x.y.z? if there is any IP set ever */
255 if (ip.family != AF_INET && ip.family != AF_INET6)
256 return NULL;
257#endif
258
165 if (at_startup() != 0) 259 if (at_startup() != 0)
166 return NULL; 260 return NULL;
167 261
168 /* Initialize our socket. */
169 Networking_Core *temp = calloc(1, sizeof(Networking_Core)); 262 Networking_Core *temp = calloc(1, sizeof(Networking_Core));
170
171 if (temp == NULL) 263 if (temp == NULL)
172 return NULL; 264 return NULL;
173 265
174 temp->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 266 sa_family_t family = 0;
267#ifdef TOX_ENABLE_IPV6
268 family = ip.family;
269#else
270 family = AF_INET;
271#endif
272 temp->family = family;
273 temp->port = 0;
274
275 /* Initialize our socket. */
276 /* add log message what we're creating */
277 temp->sock = socket(temp->family, SOCK_DGRAM, IPPROTO_UDP);
175 278
176 /* Check for socket error. */ 279 /* Check for socket error. */
177#ifdef WIN32 280#ifdef WIN32
@@ -204,7 +307,7 @@ Networking_Core *new_networking(IP ip, uint16_t port)
204 return -1; 307 return -1;
205 */ 308 */
206 309
207 /* Enable broadcast on socket. */ 310 /* Enable broadcast on socket? */
208 int broadcast = 1; 311 int broadcast = 1;
209 setsockopt(temp->sock, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast)); 312 setsockopt(temp->sock, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast));
210 313
@@ -218,10 +321,106 @@ Networking_Core *new_networking(IP ip, uint16_t port)
218 fcntl(temp->sock, F_SETFL, O_NONBLOCK, 1); 321 fcntl(temp->sock, F_SETFL, O_NONBLOCK, 1);
219#endif 322#endif
220 323
221 /* Bind our socket to port PORT and address 0.0.0.0 */ 324#ifdef LOGGING
222 ADDR addr = {AF_INET, htons(port), ip, {0}}; 325 loginit(ntohs(port));
223 bind(temp->sock, (struct sockaddr *)&addr, sizeof(addr)); 326#endif
224 return temp; 327
328 /* Bind our socket to port PORT and the given IP address (usually 0.0.0.0 or ::) */
329 uint16_t *portptr = NULL;
330 struct sockaddr_storage addr;
331 size_t addrsize;
332#ifdef TOX_ENABLE_IPV6
333 if (temp->family == AF_INET)
334 {
335 IP4 ip4 = ip.ip4;
336#else
337 IP4 ip4 = ip;
338#endif
339 addrsize = sizeof(struct sockaddr_in);
340 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
341 addr4->sin_family = AF_INET;
342 addr4->sin_port = htons(port);
343 addr4->sin_addr = ip4.in_addr;
344
345 portptr = &addr4->sin_port;
346#ifdef TOX_ENABLE_IPV6
347 }
348 else if (temp->family == AF_INET6)
349 {
350 addrsize = sizeof(struct sockaddr_in6);
351 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
352 addr6->sin6_family = AF_INET6;
353 addr6->sin6_port = htons(port);
354 addr6->sin6_addr = ip.ip6;
355
356 addr6->sin6_flowinfo = 0;
357 addr6->sin6_scope_id = 0;
358
359 portptr = &addr6->sin6_port;
360 }
361 else
362 return NULL;
363
364 if (ip.family == AF_INET6) {
365 char ipv6only = 0;
366 int res = setsockopt(temp->sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, sizeof(ipv6only));
367#ifdef LOGGING
368 if (res < 0) {
369 sprintf(logbuffer, "Failed to enable dual-stack on IPv6 socket, won't be able to receive from/send to IPv4 addresses. (%u, %s)\n",
370 errno, strerror(errno));
371 loglog(logbuffer);
372 }
373 else
374 loglog("Embedded IPv4 addresses enabled successfully.\n");
375#endif
376
377 /* multicast local nodes */
378 struct ipv6_mreq mreq;
379 memset(&mreq, 0, sizeof(mreq));
380 mreq.ipv6mr_multiaddr.s6_addr[ 0] = 0xFF;
381 mreq.ipv6mr_multiaddr.s6_addr[ 1] = 0x02;
382 mreq.ipv6mr_multiaddr.s6_addr[15] = 0x01;
383 mreq.ipv6mr_interface = 0;
384 res = setsockopt(temp->sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
385#ifdef LOGGING
386 if (res < 0) {
387 sprintf(logbuffer, "Failed to activate local multicast membership. (%u, %s)\n",
388 errno, strerror(errno));
389 loglog(logbuffer);
390 }
391 else
392 loglog("Local multicast group FF02::1 joined successfully.\n");
393#endif
394 }
395#endif
396
397 /* a hanging program or a different user might block the standard port;
398 * as long as it isn't a parameter coming from the commandline,
399 * try a few ports after it, to see if we can find a "free" one
400 */
401 int tries, res;
402 for(tries = 0; tries < 9; tries++)
403 {
404 res = bind(temp->sock, (struct sockaddr *)&addr, addrsize);
405 if (!res)
406 {
407 temp->port = *portptr;
408#ifdef LOGGING
409 sprintf(logbuffer, "Bound successfully to %s:%u.\n", ip_ntoa(&ip), ntohs(temp->port));
410 loglog(logbuffer);
411#endif
412 return temp;
413 }
414
415 uint16_t port = ntohs(*portptr);
416 port++;
417 *portptr = htons(port);
418 }
419
420 fprintf(stderr, "Failed to bind socket: %u, %s (IP/Port: %s:%u\n", errno,
421 strerror(errno), ip_ntoa(&ip), port);
422 free(temp);
423 return NULL;
225} 424}
226 425
227/* Function to cleanup networking stuff. */ 426/* Function to cleanup networking stuff. */
@@ -235,3 +434,362 @@ void kill_networking(Networking_Core *net)
235 free(net); 434 free(net);
236 return; 435 return;
237} 436}
437
438/* ip_equal
439 * compares two IPAny structures
440 * unset means unequal
441 *
442 * returns 0 when not equal or when uninitialized
443 */
444int ip_equal(IP *a, IP *b)
445{
446 if (!a || !b)
447 return 0;
448
449#ifdef TOX_ENABLE_IPV6
450 if (a->family == AF_INET)
451 return (a->ip4.in_addr.s_addr == b->ip4.in_addr.s_addr);
452
453 if (a->family == AF_INET6)
454 return IN6_ARE_ADDR_EQUAL(&a->ip6, &b->ip6);
455
456 return 0;
457#else
458 return (a->uint32 == b->uint32);
459#endif
460};
461
462/* ipport_equal
463 * compares two IPAny_Port structures
464 * unset means unequal
465 *
466 * returns 0 when not equal or when uninitialized
467 */
468int ipport_equal(IP_Port *a, IP_Port *b)
469{
470 if (!a || !b)
471 return 0;
472
473 if (!a->port || (a->port != b->port))
474 return 0;
475
476 return ip_equal(&a->ip, &b->ip);
477};
478
479/* nulls out ip */
480void ip_reset(IP *ip)
481{
482 if (!ip)
483 return;
484
485#ifdef TOX_ENABLE_IPV6
486 memset(ip, 0, sizeof(IP));
487#else
488 ip->uint32 = 0;
489#endif
490};
491
492/* nulls out ip, sets family according to flag */
493void ip_init(IP *ip, uint8_t ipv6enabled)
494{
495 if (!ip)
496 return;
497
498#ifdef TOX_ENABLE_IPV6
499 memset(ip, 0, sizeof(IP));
500 ip->family = ipv6enabled ? AF_INET6 : AF_INET;
501#else
502 ip->uint32 = 0;
503#endif
504};
505
506/* checks if ip is valid */
507int ip_isset(IP *ip)
508{
509 if (!ip)
510 return 0;
511
512#ifdef TOX_ENABLE_IPV6
513 return (ip->family != 0);
514#else
515 return (ip->uint32 != 0);
516#endif
517};
518
519/* checks if ip is valid */
520int ipport_isset(IP_Port *ipport)
521{
522 if (!ipport)
523 return 0;
524
525 if (!ipport->port)
526 return 0;
527
528 return ip_isset(&ipport->ip);
529};
530
531/* copies an ip structure (careful about direction!) */
532void ip_copy(IP *target, IP *source)
533{
534 if (!source || !target)
535 return;
536
537 memcpy(target, source, sizeof(IP));
538};
539
540/* copies an ip_port structure (careful about direction!) */
541void ipport_copy(IP_Port *target, IP_Port *source)
542{
543 if (!source || !target)
544 return;
545
546 memcpy(target, source, sizeof(IP_Port));
547};
548
549/* ip_ntoa
550 * converts ip into a string
551 * uses a static buffer, so mustn't used multiple times in the same output
552 */
553/* there would be INET6_ADDRSTRLEN, but it might be too short for the error message */
554static char addresstext[96];
555const char *ip_ntoa(IP *ip)
556{
557 if (ip) {
558#ifdef TOX_ENABLE_IPV6
559 if (ip->family == AF_INET) {
560 addresstext[0] = 0;
561 struct in_addr *addr = (struct in_addr *)&ip->ip4;
562 inet_ntop(ip->family, addr, addresstext, sizeof(addresstext));
563 }
564 else if (ip->family == AF_INET6) {
565 addresstext[0] = '[';
566 struct in6_addr *addr = (struct in6_addr *)&ip->ip6;
567 inet_ntop(ip->family, addr, &addresstext[1], sizeof(addresstext) - 3);
568 size_t len = strlen(addresstext);
569 addresstext[len] = ']';
570 addresstext[len + 1] = 0;
571 }
572 else
573 snprintf(addresstext, sizeof(addresstext), "(IP invalid, family %u)", ip->family);
574#else
575 addresstext[0] = 0;
576 struct in_addr *addr = (struct in_addr *)&ip;
577 inet_ntop(AF_INET, addr, addresstext, sizeof(addresstext));
578#endif
579 }
580 else
581 snprintf(addresstext, sizeof(addresstext), "(IP invalid: NULL)");
582
583 addresstext[INET6_ADDRSTRLEN + 2] = 0;
584 return addresstext;
585};
586
587/*
588 * addr_parse_ip
589 * directly parses the input into an IP structure
590 * tries IPv4 first, then IPv6
591 *
592 * input
593 * address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6)
594 *
595 * output
596 * IP: family and the value is set on success
597 *
598 * returns 1 on success, 0 on failure
599 */
600
601int addr_parse_ip(const char *address, IP *to)
602{
603 if (!address || !to)
604 return 0;
605
606#ifdef TOX_ENABLE_IPV6
607 struct in_addr addr4;
608 if (1 == inet_pton(AF_INET, address, &addr4)) {
609 to->family = AF_INET;
610 to->ip4.in_addr = addr4;
611 return 1;
612 };
613
614 struct in6_addr addr6;
615 if (1 == inet_pton(AF_INET6, address, &addr6)) {
616 to->family = AF_INET6;
617 to->ip6 = addr6;
618 return 1;
619 };
620#else
621 struct in_addr addr4;
622 if (1 == inet_pton(AF_INET, address, &addr4)) {
623 to->in_addr = addr4;
624 return 1;
625 };
626#endif
627
628 return 0;
629};
630
631/*
632 * addr_resolve():
633 * uses getaddrinfo to resolve an address into an IP address
634 * uses the first IPv4/IPv6 addresses returned by getaddrinfo
635 *
636 * input
637 * address: a hostname (or something parseable to an IP address)
638 * ip: ip.family MUST be initialized, either set to a specific IP version
639 * (AF_INET/AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both
640 * IP versions are acceptable
641 *
642 * returns in ip a valid IPAny (v4/v6),
643 * prefers v6 if ip.family was AF_UNSPEC and both available
644 * returns 0 on failure
645 */
646
647int addr_resolve(const char *address, IP *to)
648{
649 if (!address || !to)
650 return 0;
651
652 sa_family_t family;
653#ifdef TOX_ENABLE_IPV6
654 family = to->family;
655#else
656 family = AF_INET;
657#endif
658
659 struct addrinfo *server = NULL;
660 struct addrinfo *walker = NULL;
661 struct addrinfo hints;
662 int rc;
663
664 memset(&hints, 0, sizeof(hints));
665 hints.ai_family = family;
666 hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses.
667
668#ifdef __WIN32__
669 WSADATA wsa_data;
670
671 /* CLEANUP: really not the best place to put this */
672 rc = WSAStartup(MAKEWORD(2, 2), &wsa_data);
673
674 if (rc != 0) {
675 return 0;
676 }
677
678#endif
679
680 rc = getaddrinfo(address, NULL, &hints, &server);
681 // Lookup failed.
682 if (rc != 0) {
683#ifdef __WIN32__
684 WSACleanup();
685#endif
686 return 0;
687 }
688
689#ifdef TOX_ENABLE_IPV6
690 IP4 ip4;
691 memset(&ip4, 0, sizeof(ip4));
692 IP6 ip6;
693 memset(&ip6, 0, sizeof(ip6));
694#endif
695
696 walker = server;
697 while (walker && (rc != 3)) {
698 if (family != AF_UNSPEC) {
699 if (walker->ai_family == family) {
700 if (family == AF_INET) {
701 if (walker->ai_addrlen == sizeof(struct sockaddr_in)) {
702 struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr;
703#ifdef TOX_ENABLE_IPV6
704 to->ip4.in_addr = addr->sin_addr;
705#else
706 to->in_addr = addr->sin_addr;
707#endif
708 rc = 3;
709 }
710 }
711#ifdef TOX_ENABLE_IPV6
712 else if (family == AF_INET6) {
713 if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
714 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr;
715 to->ip6 = addr->sin6_addr;
716 rc = 3;
717 }
718 }
719#endif
720 }
721 }
722#ifdef TOX_ENABLE_IPV6
723 else {
724 if (walker->ai_family == AF_INET) {
725 if (walker->ai_addrlen == sizeof(struct sockaddr_in)) {
726 struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr;
727 ip4.in_addr = addr->sin_addr;
728 rc |= 1;
729 }
730 }
731 else if (walker->ai_family == AF_INET6) {
732 if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
733 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr;
734 ip6 = addr->sin6_addr;
735 rc |= 2;
736 }
737 }
738 }
739#endif
740
741 walker = walker->ai_next;
742 }
743
744#ifdef TOX_ENABLE_IPV6
745 if (to->family == AF_UNSPEC) {
746 if (rc & 2) {
747 to->family = AF_INET6;
748 to->ip6 = ip6;
749 }
750 else if (rc & 1) {
751 to->family = AF_INET;
752 to->ip4 = ip4;
753 }
754 else
755 rc = 0;
756 }
757#endif
758
759
760 freeaddrinfo(server);
761#ifdef __WIN32__
762 WSACleanup();
763#endif
764 return rc;
765}
766
767/*
768 * addr_resolve_or_parse_ip
769 * resolves string into an IP address
770 *
771 * to->family MUST be set (AF_UNSPEC, AF_INET, AF_INET6)
772 * returns 1 on success, 0 on failure
773 */
774int addr_resolve_or_parse_ip(const char *address, IP *to)
775{
776 if (!addr_resolve(address, to))
777 if (!addr_parse_ip(address, to))
778 return 0;
779
780 return 1;
781};
782
783#ifdef LOGGING
784static void loglogdata(char *message, uint8_t *buffer, size_t buflen, IP_Port *ip_port, ssize_t res)
785{
786 snprintf(logbuffer, sizeof(logbuffer), "[%2u] %3u%c %s %s:%u (%u: %s) | %04x%04x\n",
787 buffer[0], res < 0 ? (buflen & 0xFF) : res,
788 res < 0 ? '-' : (res == buflen ? '=' : '+'),
789 message, ip_ntoa(&ip_port->ip), ntohs(ip_port->port), res < 0 ? errno : 0,
790 res < 0 ? strerror(errno) : "OK", buflen > 4 ? ntohl(*(uint32_t *)&buffer[1]) : 0,
791 buflen > 7 ? ntohl(*(uint32_t *)(&buffer[5])) : 0);
792 logbuffer[sizeof(logbuffer) - 1] = 0;
793 loglog(logbuffer);
794}
795#endif
diff --git a/toxcore/network.h b/toxcore/network.h
index 2d08e88d..e804379d 100644
--- a/toxcore/network.h
+++ b/toxcore/network.h
@@ -39,17 +39,22 @@
39#include <windows.h> 39#include <windows.h>
40#include <ws2tcpip.h> 40#include <ws2tcpip.h>
41 41
42typedef unsigned int sock_t;
43
42#else // Linux includes 44#else // Linux includes
43 45
44#include <fcntl.h> 46#include <fcntl.h>
45#include <sys/socket.h> 47#include <sys/socket.h>
46#include <netinet/in.h> 48#include <netinet/in.h>
49#include <arpa/inet.h>
47#include <errno.h> 50#include <errno.h>
48#include <sys/time.h> 51#include <sys/time.h>
49#include <sys/types.h> 52#include <sys/types.h>
50#include <netdb.h> 53#include <netdb.h>
51#include <unistd.h> 54#include <unistd.h>
52 55
56typedef int sock_t;
57
53#endif 58#endif
54 59
55#ifndef VANILLA_NACL 60#ifndef VANILLA_NACL
@@ -66,7 +71,8 @@
66#define NET_PACKET_PING_REQUEST 0 /* Ping request packet ID. */ 71#define NET_PACKET_PING_REQUEST 0 /* Ping request packet ID. */
67#define NET_PACKET_PING_RESPONSE 1 /* Ping response packet ID. */ 72#define NET_PACKET_PING_RESPONSE 1 /* Ping response packet ID. */
68#define NET_PACKET_GET_NODES 2 /* Get nodes request packet ID. */ 73#define NET_PACKET_GET_NODES 2 /* Get nodes request packet ID. */
69#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. */
70#define NET_PACKET_HANDSHAKE 16 /* Handshake packet ID. */ 76#define NET_PACKET_HANDSHAKE 16 /* Handshake packet ID. */
71#define NET_PACKET_SYNC 17 /* SYNC packet ID. */ 77#define NET_PACKET_SYNC 17 /* SYNC packet ID. */
72#define NET_PACKET_DATA 18 /* Data packet ID. */ 78#define NET_PACKET_DATA 18 /* Data packet ID. */
@@ -82,27 +88,83 @@ typedef union {
82 uint8_t uint8[4]; 88 uint8_t uint8[4];
83 uint16_t uint16[2]; 89 uint16_t uint16[2];
84 uint32_t uint32; 90 uint32_t uint32;
85} IP; 91 struct in_addr in_addr;
92} IP4;
93
94typedef struct in6_addr IP6;
95
96typedef struct {
97 sa_family_t family;
98 union {
99 IP4 ip4;
100 IP6 ip6;
101 };
102} IPAny;
86 103
87typedef union { 104typedef union {
88 struct { 105 struct {
89 IP ip; 106 IP4 ip;
90 uint16_t port; 107 uint16_t port;
91 /* Not used for anything right now. */ 108 /* Not used for anything right now. */
92 uint16_t padding; 109 uint16_t padding;
93 }; 110 };
94 uint8_t uint8[8]; 111 uint8_t uint8[8];
95} IP_Port; 112} IP4_Port;
96 113
114/* will replace IP_Port as soon as the complete infrastructure is in place
115 * removed the unused union and padding also */
97typedef struct { 116typedef struct {
98 int16_t family; 117 IPAny ip;
99 uint16_t port; 118 uint16_t port;
100 IP ip; 119} IPAny_Port;
101 uint8_t zeroes[8]; 120
102#ifdef ENABLE_IPV6 121#undef TOX_ENABLE_IPV6
103 uint8_t zeroes2[12]; 122/* #define TOX_ENABLE_IPV6 */
123#ifdef TOX_ENABLE_IPV6
124#define TOX_ENABLE_IPV6_DEFAULT 1
125typedef IPAny IP;
126typedef IPAny_Port IP_Port;
127#else
128#define TOX_ENABLE_IPV6_DEFAULT 0
129typedef IP4 IP;
130typedef IP4_Port IP_Port;
104#endif 131#endif
105} ADDR; 132
133/* ip_ntoa
134 * converts ip into a string
135 * uses a static buffer, so mustn't used multiple times in the same output
136 */
137const char *ip_ntoa(IP *ip);
138
139/* ipport_equal
140 * compares two IPAny_Port structures
141 * unset means unequal
142 *
143 * returns 0 when not equal or when uninitialized
144 */
145int ipport_equal(IP_Port *a, IP_Port *b);
146
147/* nulls out ip */
148void ip_reset(IP *ip);
149/* nulls out ip, sets family according to flag */
150void ip_init(IP *ip, uint8_t ipv6enabled);
151/* checks if ip is valid */
152int ip_isset(IP *ip);
153/* checks if ip is valid */
154int ipport_isset(IP_Port *ipport);
155/* copies an ip structure */
156void ip_copy(IP *target, IP *source);
157/* copies an ip_port structure */
158void ipport_copy(IP_Port *target, IP_Port *source);
159
160/*
161 * addr_resolve_or_parse_ip
162 * resolves string into an IP address
163 *
164 * to->family MUST be set (AF_UNSPEC, AF_INET, AF_INET6)
165 * returns 1 on success, 0 on failure
166 */
167int addr_resolve_or_parse_ip(const char *address, IP *to);
106 168
107/* Function to receive data, ip and port of sender is put into ip_port. 169/* Function to receive data, ip and port of sender is put into ip_port.
108 * Packet data is put into data. 170 * Packet data is put into data.
@@ -117,13 +179,11 @@ typedef struct {
117 179
118typedef struct { 180typedef struct {
119 Packet_Handles packethandlers[256]; 181 Packet_Handles packethandlers[256];
120 /* Our UDP socket. */
121#ifdef WIN32
122 unsigned int sock;
123#else
124 int sock;
125#endif
126 182
183 /* Our UDP socket. */
184 sa_family_t family;
185 uint16_t port;
186 sock_t sock;
127} Networking_Core; 187} Networking_Core;
128 188
129/* return current time in milleseconds since the epoch. */ 189/* return current time in milleseconds since the epoch. */
@@ -137,12 +197,7 @@ uint32_t random_int(void);
137/* Basic network functions: */ 197/* Basic network functions: */
138 198
139/* Function to send packet(data) of length length to ip_port. */ 199/* Function to send packet(data) of length length to ip_port. */
140#ifdef WIN32 200int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t length);
141int sendpacket(unsigned int sock, IP_Port ip_port, uint8_t *data, uint32_t length);
142#else
143int sendpacket(int sock, IP_Port ip_port, uint8_t *data, uint32_t length);
144#endif
145
146 201
147/* Function to call when packet beginning with byte is received. */ 202/* Function to call when packet beginning with byte is received. */
148void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handler_callback cb, void *object); 203void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handler_callback cb, void *object);
@@ -163,5 +218,4 @@ Networking_Core *new_networking(IP ip, uint16_t port);
163/* Function to cleanup networking stuff (doesn't do much right now). */ 218/* Function to cleanup networking stuff (doesn't do much right now). */
164void kill_networking(Networking_Core *net); 219void kill_networking(Networking_Core *net);
165 220
166
167#endif 221#endif
diff --git a/toxcore/ping.c b/toxcore/ping.c
index 3b39d911..49e0dba9 100644
--- a/toxcore/ping.c
+++ b/toxcore/ping.c
@@ -100,7 +100,8 @@ bool is_pinging(void *ping, IP_Port ipp, uint64_t ping_id) // O(n) TODO: Repl
100{ 100{
101 PING *png = ping; 101 PING *png = ping;
102 102
103 if (ipp.ip.uint32 == 0 && ping_id == 0) 103 /* shouldn't that be an OR ? */
104 if (!ip_isset(&ipp.ip) && ping_id == 0)
104 return false; 105 return false;
105 106
106 size_t i, id; 107 size_t i, id;
@@ -111,7 +112,8 @@ bool is_pinging(void *ping, IP_Port ipp, uint64_t ping_id) // O(n) TODO: Repl
111 id = (png->pos_pings + i) % PING_NUM_MAX; 112 id = (png->pos_pings + i) % PING_NUM_MAX;
112 113
113 /* ping_id = 0 means match any id. */ 114 /* ping_id = 0 means match any id. */
114 if ((ipp_eq(png->pings[id].ipp, ipp) || ipp.ip.uint32 == 0) && (png->pings[id].id == ping_id || ping_id == 0)) { 115 if ((!ip_isset(&ipp.ip) || ipport_equal(&png->pings[id].ipp, &ipp)) &&
116 (png->pings[id].id == ping_id || ping_id == 0)) {
115 return true; 117 return true;
116 } 118 }
117 } 119 }
@@ -147,7 +149,7 @@ int send_ping_request(void *ping, Net_Crypto *c, IP_Port ipp, uint8_t *client_id
147 if (rc != sizeof(ping_id) + ENCRYPTION_PADDING) 149 if (rc != sizeof(ping_id) + ENCRYPTION_PADDING)
148 return 1; 150 return 1;
149 151
150 return sendpacket(c->lossless_udp->net->sock, ipp, pk, sizeof(pk)); 152 return sendpacket(c->lossless_udp->net, ipp, pk, sizeof(pk));
151} 153}
152 154
153int send_ping_response(Net_Crypto *c, IP_Port ipp, uint8_t *client_id, uint64_t ping_id) 155int send_ping_response(Net_Crypto *c, IP_Port ipp, uint8_t *client_id, uint64_t ping_id)
@@ -172,7 +174,7 @@ int send_ping_response(Net_Crypto *c, IP_Port ipp, uint8_t *client_id, uint64_t
172 if (rc != sizeof(ping_id) + ENCRYPTION_PADDING) 174 if (rc != sizeof(ping_id) + ENCRYPTION_PADDING)
173 return 1; 175 return 1;
174 176
175 return sendpacket(c->lossless_udp->net->sock, ipp, pk, sizeof(pk)); 177 return sendpacket(c->lossless_udp->net, ipp, pk, sizeof(pk));
176} 178}
177 179
178int handle_ping_request(void *object, IP_Port source, uint8_t *packet, uint32_t length) 180int handle_ping_request(void *object, IP_Port source, uint8_t *packet, uint32_t length)
diff --git a/toxcore/tox.c b/toxcore/tox.c
index 54bbd9f0..6417b16a 100644
--- a/toxcore/tox.c
+++ b/toxcore/tox.c
@@ -374,6 +374,12 @@ 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, uint8_t ipv6enabled,
378 uint16_t port, uint8_t *public_key)
379{
380 Messenger *m = tox;
381 DHT_bootstrap_ex(m->dht, address, ipv6enabled, port, public_key);
382};
377 383
378/* return 0 if we are not connected to the DHT. 384/* return 0 if we are not connected to the DHT.
379 * return 1 if we are. 385 * return 1 if we are.
@@ -389,9 +395,13 @@ int tox_isconnected(void *tox)
389 * return allocated instance of tox on success. 395 * return allocated instance of tox on success.
390 * return 0 if there are problems. 396 * return 0 if there are problems.
391 */ 397 */
398void *tox_new_ex(uint8_t ipv6enabled)
399{
400 return initMessenger(ipv6enabled);
401}
392void *tox_new(void) 402void *tox_new(void)
393{ 403{
394 return initMessenger(); 404 return tox_new_ex(0);
395} 405}
396 406
397/* Run this before closing shop. 407/* Run this before closing shop.
diff --git a/toxcore/tox.h b/toxcore/tox.h
index 811e798b..15bef94c 100644
--- a/toxcore/tox.h
+++ b/toxcore/tox.h
@@ -26,6 +26,22 @@
26 26
27#include <stdint.h> 27#include <stdint.h>
28 28
29#ifdef WIN32
30#ifndef WINVER
31//Windows XP
32#define WINVER 0x0501
33#endif
34
35#include <winsock2.h>
36#include <windows.h>
37#include <ws2tcpip.h>
38
39#else
40
41#include <netinet/ip.h>
42
43#endif
44
29#ifdef __cplusplus 45#ifdef __cplusplus
30extern "C" { 46extern "C" {
31#endif 47#endif
@@ -36,19 +52,52 @@ extern "C" {
36 52
37#define TOX_FRIEND_ADDRESS_SIZE (TOX_CLIENT_ID_SIZE + sizeof(uint32_t) + sizeof(uint16_t)) 53#define TOX_FRIEND_ADDRESS_SIZE (TOX_CLIENT_ID_SIZE + sizeof(uint32_t) + sizeof(uint16_t))
38 54
39
40typedef union { 55typedef union {
41 uint8_t c[4]; 56 uint8_t c[4];
42 uint16_t s[2]; 57 uint16_t s[2];
43 uint32_t i; 58 uint32_t i;
44} tox_IP; 59} tox_IP4;
60
61
62typedef struct in6_addr tox_IP6;
45 63
46typedef struct { 64typedef struct {
47 tox_IP ip; 65 sa_family_t family;
66 union {
67 tox_IP4 ip4;
68 tox_IP6 ip6;
69 };
70} tox_IPAny;
71
72typedef union {
73 struct {
74 tox_IP4 ip;
75 uint16_t port;
76 /* Not used for anything right now. */
77 uint16_t padding;
78 };
79 uint8_t uint8[8];
80} tox_IP4_Port;
81
82/* will replace IP_Port as soon as the complete infrastructure is in place
83 * removed the unused union and padding also */
84typedef struct {
85 tox_IPAny ip;
48 uint16_t port; 86 uint16_t port;
49 /* Not used for anything right now. */ 87} tox_IPAny_Port;
50 uint16_t padding; 88
51} tox_IP_Port; 89#undef TOX_ENABLE_IPV6
90/* #define TOX_ENABLE_IPV6 */
91#ifdef TOX_ENABLE_IPV6
92#define TOX_ENABLE_IPV6_DEFAULT 1
93typedef tox_IPAny tox_IP;
94typedef tox_IPAny_Port tox_IP_Port;
95#else
96#define TOX_ENABLE_IPV6_DEFAULT 0
97typedef tox_IP4 tox_IP;
98typedef tox_IP4_Port tox_IP_Port;
99#endif
100
52 101
53/* Errors for m_addfriend 102/* Errors for m_addfriend
54 * FAERR - Friend Add Error 103 * FAERR - Friend Add Error
@@ -291,8 +340,11 @@ void tox_callback_connectionstatus(Tox *tox, void (*function)(Tox *tox, int, uin
291 340
292/* Use this function to bootstrap the client. 341/* Use this function to bootstrap the client.
293 * Sends a get nodes request to the given node with ip port and public_key. 342 * Sends a get nodes request to the given node with ip port and public_key.
343 * tox_bootstrap_ex converts the address into an IP_Port structure internally
294 */ 344 */
295void tox_bootstrap(Tox *tox, tox_IP_Port ip_port, uint8_t *public_key); 345void tox_bootstrap(Tox *tox, tox_IP_Port ip_port, uint8_t *public_key);
346void tox_bootstrap_ex(Tox *tox, const char *address, uint8_t ipv6enabled,
347 uint16_t port, uint8_t *public_key);
296 348
297/* return 0 if we are not connected to the DHT. 349/* return 0 if we are not connected to the DHT.
298 * return 1 if we are. 350 * return 1 if we are.
@@ -305,6 +357,7 @@ int tox_isconnected(Tox *tox);
305 * return 0 if there are problems. 357 * return 0 if there are problems.
306 */ 358 */
307Tox *tox_new(void); 359Tox *tox_new(void);
360Tox *tox_new_ex(uint8_t ipv6enabled);
308 361
309/* Run this before closing shop. 362/* Run this before closing shop.
310 * Free all datastructures. */ 363 * Free all datastructures. */
diff --git a/toxcore/util.c b/toxcore/util.c
index 1728ea21..19d464d4 100644
--- a/toxcore/util.c
+++ b/toxcore/util.c
@@ -10,11 +10,12 @@
10#endif 10#endif
11 11
12#include <time.h> 12#include <time.h>
13#include <stdint.h>
14#include <stdbool.h>
15 13
14/* for CLIENT_ID_SIZE */
16#include "DHT.h" 15#include "DHT.h"
17 16
17#include "util.h"
18
18uint64_t now() 19uint64_t now()
19{ 20{
20 return time(NULL); 21 return time(NULL);
@@ -32,11 +33,6 @@ uint64_t random_64b()
32 return r; 33 return r;
33} 34}
34 35
35bool ipp_eq(IP_Port a, IP_Port b)
36{
37 return (a.ip.uint32 == b.ip.uint32) && (a.port == b.port);
38}
39
40bool id_eq(uint8_t *dest, uint8_t *src) 36bool id_eq(uint8_t *dest, uint8_t *src)
41{ 37{
42 return memcmp(dest, src, CLIENT_ID_SIZE) == 0; 38 return memcmp(dest, src, CLIENT_ID_SIZE) == 0;
@@ -46,3 +42,30 @@ void id_cpy(uint8_t *dest, uint8_t *src)
46{ 42{
47 memcpy(dest, src, CLIENT_ID_SIZE); 43 memcpy(dest, src, CLIENT_ID_SIZE);
48} 44}
45
46#ifdef LOGGING
47char logbuffer[512];
48static FILE *logfile = NULL;
49void loginit(uint16_t port)
50{
51 if (logfile)
52 fclose(logfile);
53
54 sprintf(logbuffer, "%u-%u.log", ntohs(port), now);
55 logfile = fopen(logbuffer, "w");
56};
57void loglog(char *text)
58{
59 if (logfile) {
60 fprintf(logfile, text);
61 fflush(logfile);
62 }
63};
64void logexit()
65{
66 if (logfile) {
67 fclose(logfile);
68 logfile = NULL;
69 }
70};
71#endif
diff --git a/toxcore/util.h b/toxcore/util.h
index 90a3c8e4..20731a05 100644
--- a/toxcore/util.h
+++ b/toxcore/util.h
@@ -5,8 +5,24 @@
5 * Copyright 2013 plutooo 5 * Copyright 2013 plutooo
6 */ 6 */
7 7
8#ifndef __UTIL_H__
9#define __UTIL_H__
10
11#include <stdbool.h>
12#include <stdint.h>
13
8uint64_t now(); 14uint64_t now();
9uint64_t random_64b(); 15uint64_t random_64b();
10bool ipp_eq(IP_Port a, IP_Port b);
11bool id_eq(uint8_t *dest, uint8_t *src); 16bool id_eq(uint8_t *dest, uint8_t *src);
12void id_cpy(uint8_t *dest, uint8_t *src); 17void id_cpy(uint8_t *dest, uint8_t *src);
18
19#undef LOGGING
20// #define LOGGING
21#ifdef LOGGING
22extern char logbuffer[512];
23void loginit(uint16_t port);
24void loglog(char *text);
25void logexit();
26#endif
27
28#endif /* __UTIL_H__ */