summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c4
-rw-r--r--testing/DHT_test.c8
-rw-r--r--toxcore/DHT.c387
-rw-r--r--toxcore/DHT.h27
-rw-r--r--toxcore/LAN_discovery.c124
-rw-r--r--toxcore/Lossless_UDP.c30
-rw-r--r--toxcore/Lossless_UDP.h6
-rw-r--r--toxcore/Messenger.c48
-rw-r--r--toxcore/network.c231
-rw-r--r--toxcore/network.h32
-rw-r--r--toxcore/tox.h31
-rw-r--r--toxcore/util.c3
12 files changed, 277 insertions, 654 deletions
diff --git a/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c b/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c
index 890085cc..dc519448 100644
--- a/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c
+++ b/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c
@@ -305,12 +305,8 @@ struct server_conf_s configure_server(char *cfg_file)
305 printf("bootstrap_server %d: Invalid port.\n", i); 305 printf("bootstrap_server %d: Invalid port.\n", i);
306 } 306 }
307 307
308#ifdef TOX_ENABLE_IPV6
309 server_conf.info[i].conn.ip.family = AF_INET; 308 server_conf.info[i].conn.ip.family = AF_INET;
310 server_conf.info[i].conn.ip.ip4.uint32 = resolve_addr(strcpy(tmp_ip, bs_ip)); 309 server_conf.info[i].conn.ip.ip4.uint32 = resolve_addr(strcpy(tmp_ip, bs_ip));
311#else
312 server_conf.info[i].conn.ip.uint32 = resolve_addr(strcpy(tmp_ip, bs_ip));
313#endif
314 server_conf.info[i].conn.port = htons(bs_port); 310 server_conf.info[i].conn.port = htons(bs_port);
315 b16_to_key(strcpy(tmp_pk, bs_pk), bs_pk_p); 311 b16_to_key(strcpy(tmp_pk, bs_pk), bs_pk_p);
316 } 312 }
diff --git a/testing/DHT_test.c b/testing/DHT_test.c
index 492586fc..11027af5 100644
--- a/testing/DHT_test.c
+++ b/testing/DHT_test.c
@@ -80,12 +80,8 @@ void print_clientlist(DHT *dht)
80 printf("%02hhX", client->client_id[j]); 80 printf("%02hhX", client->client_id[j]);
81 } 81 }
82 82
83#ifdef CLIENT_ONETOONE_IP
84 print_assoc(&client->assoc, 1);
85#else
86 print_assoc(&client->assoc4, 1); 83 print_assoc(&client->assoc4, 1);
87 print_assoc(&client->assoc6, 1); 84 print_assoc(&client->assoc6, 1);
88#endif
89 } 85 }
90} 86}
91 87
@@ -119,12 +115,8 @@ void print_friendlist(DHT *dht)
119 printf("%hhX", client->client_id[j]); 115 printf("%hhX", client->client_id[j]);
120 } 116 }
121 117
122#ifdef CLIENT_ONETOONE_IP
123 print_assoc(&client->assoc, 0);
124#else
125 print_assoc(&client->assoc4, 0); 118 print_assoc(&client->assoc4, 0);
126 print_assoc(&client->assoc6, 0); 119 print_assoc(&client->assoc6, 0);
127#endif
128 } 120 }
129 } 121 }
130} 122}
diff --git a/toxcore/DHT.c b/toxcore/DHT.c
index 470826f0..ee51f16c 100644
--- a/toxcore/DHT.c
+++ b/toxcore/DHT.c
@@ -131,12 +131,9 @@ static int client_in_list(Client_data *list, uint32_t length, uint8_t *client_id
131 uint64_t temp_time = unix_time(); 131 uint64_t temp_time = unix_time();
132 132
133 for (i = 0; i < length; i++) 133 for (i = 0; i < length; i++)
134#ifdef CLIENT_ONETOONE_IP /* Dead nodes are considered dead (not in the list)*/ 134 /* Dead nodes are considered dead (not in the list)*/
135 if (!is_timeout(temp_time, list[i].assoc.timestamp, KILL_NODE_TIMEOUT))
136#else
137 if (!is_timeout(temp_time, list[i].assoc4.timestamp, KILL_NODE_TIMEOUT) || 135 if (!is_timeout(temp_time, list[i].assoc4.timestamp, KILL_NODE_TIMEOUT) ||
138 !is_timeout(temp_time, list[i].assoc6.timestamp, KILL_NODE_TIMEOUT)) 136 !is_timeout(temp_time, list[i].assoc6.timestamp, KILL_NODE_TIMEOUT))
139#endif
140 if (id_equal(list[i].client_id, client_id)) 137 if (id_equal(list[i].client_id, client_id))
141 return 1; 138 return 1;
142 139
@@ -155,41 +152,12 @@ static int client_or_ip_port_in_list(Client_data *list, uint32_t length, uint8_t
155 uint32_t i; 152 uint32_t i;
156 uint64_t temp_time = unix_time(); 153 uint64_t temp_time = unix_time();
157 154
158#ifdef CLIENT_ONETOONE_IP
159 uint8_t candropipv4 = 1;
160
161 if (ip_port.ip.family == AF_INET6) {
162 uint8_t ipv6cnt = 0;
163
164 /* ipv6: count how many spots are used */
165 for (i = 0; i < length; i++)
166 if (list[i].assoc.ip_port.ip.family == AF_INET6)
167 ipv6cnt++;
168
169 /* more than half the list filled with ipv6: block ipv4->ipv6 overwrite */
170 if (ipv6cnt > length / 2)
171 candropipv4 = 0;
172 }
173
174#endif
175
176 /* if client_id is in list, find it and maybe overwrite ip_port */ 155 /* if client_id is in list, find it and maybe overwrite ip_port */
177 for (i = 0; i < length; ++i) 156 for (i = 0; i < length; ++i)
178 if (id_equal(list[i].client_id, client_id)) { 157 if (id_equal(list[i].client_id, client_id)) {
179 /* Refresh the client timestamp. */ 158 /* Refresh the client timestamp. */
180#ifdef CLIENT_ONETOONE_IP
181 /* if we got "too many" ipv6 addresses already, keep the ipv4 address */
182 if (!candropipv4 && (list[i].assoc.ip_port.ip.family == AF_INET))
183 return 1;
184
185 if (LAN_ip(list[i].assoc.ip_port.ip) != 0 && LAN_ip(ip_port.ip) == 0)
186 return 1;
187
188 list[i].assoc.ip_port = ip_port;
189 list[i].assoc.timestamp = temp_time;
190#else
191
192 if (ip_port.ip.family == AF_INET) { 159 if (ip_port.ip.family == AF_INET) {
160
193#ifdef LOGGING 161#ifdef LOGGING
194 162
195 if (!ipport_equal(&list[i].assoc4.ip_port, &ip_port)) { 163 if (!ipport_equal(&list[i].assoc4.ip_port, &ip_port)) {
@@ -209,6 +177,7 @@ static int client_or_ip_port_in_list(Client_data *list, uint32_t length, uint8_t
209 list[i].assoc4.ip_port = ip_port; 177 list[i].assoc4.ip_port = ip_port;
210 list[i].assoc4.timestamp = temp_time; 178 list[i].assoc4.timestamp = temp_time;
211 } else if (ip_port.ip.family == AF_INET6) { 179 } else if (ip_port.ip.family == AF_INET6) {
180
212#ifdef LOGGING 181#ifdef LOGGING
213 182
214 if (!ipport_equal(&list[i].assoc6.ip_port, &ip_port)) { 183 if (!ipport_equal(&list[i].assoc6.ip_port, &ip_port)) {
@@ -229,7 +198,6 @@ static int client_or_ip_port_in_list(Client_data *list, uint32_t length, uint8_t
229 list[i].assoc6.timestamp = temp_time; 198 list[i].assoc6.timestamp = temp_time;
230 } 199 }
231 200
232#endif
233 return 1; 201 return 1;
234 } 202 }
235 203
@@ -238,21 +206,6 @@ static int client_or_ip_port_in_list(Client_data *list, uint32_t length, uint8_t
238 * TODO: maybe we SHOULDN'T do that if that client_id is in a friend_list 206 * TODO: maybe we SHOULDN'T do that if that client_id is in a friend_list
239 * and the one who is the actual friend's client_id/address set? */ 207 * and the one who is the actual friend's client_id/address set? */
240 for (i = 0; i < length; ++i) { 208 for (i = 0; i < length; ++i) {
241#ifdef CLIENT_ONETOONE_IP
242
243 if (ipport_equal(&list[i].assoc.ip_port, &ip_port)) {
244 /* Initialize client timestamp. */
245 list[i].assoc.timestamp = temp_time;
246 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
247#ifdef LOGGING
248 sprintf(logbuffer, "coipil[%u]: switching client_id\n", i);
249 loglog(logbuffer);
250#endif
251 return 1;
252 }
253
254#else
255
256 /* MAYBE: check the other address, if valid, don't nuke? */ 209 /* MAYBE: check the other address, if valid, don't nuke? */
257 if ((ip_port.ip.family == AF_INET) && ipport_equal(&list[i].assoc4.ip_port, &ip_port)) { 210 if ((ip_port.ip.family == AF_INET) && ipport_equal(&list[i].assoc4.ip_port, &ip_port)) {
258 /* Initialize client timestamp. */ 211 /* Initialize client timestamp. */
@@ -277,8 +230,6 @@ static int client_or_ip_port_in_list(Client_data *list, uint32_t length, uint8_t
277 memset(&list[i].assoc4, 0, sizeof(list[i].assoc4)); 230 memset(&list[i].assoc4, 0, sizeof(list[i].assoc4));
278 return 1; 231 return 1;
279 } 232 }
280
281#endif
282 } 233 }
283 234
284 return 0; 235 return 0;
@@ -338,22 +289,15 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod
338 continue; 289 continue;
339 290
340 IPPTsPng *ipptp = NULL; 291 IPPTsPng *ipptp = NULL;
341#ifdef CLIENT_ONETOONE_IP
342 ipptp = &client->assoc;
343#else
344
345 if (sa_family == AF_INET) 292 if (sa_family == AF_INET)
346 ipptp = &client->assoc4; 293 ipptp = &client->assoc4;
347 else 294 else
348 ipptp = &client->assoc6; 295 ipptp = &client->assoc6;
349 296
350#endif
351
352 /* node not in a good condition? */ 297 /* node not in a good condition? */
353 if (is_timeout(timestamp, ipptp->timestamp, BAD_NODE_TIMEOUT)) 298 if (is_timeout(timestamp, ipptp->timestamp, BAD_NODE_TIMEOUT))
354 continue; 299 continue;
355 300
356#ifdef TOX_ENABLE_IPV6
357 IP *client_ip = &ipptp->ip_port.ip; 301 IP *client_ip = &ipptp->ip_port.ip;
358 302
359 /* 303 /*
@@ -373,9 +317,6 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod
373 } 317 }
374 318
375 ipv46x = !(sa_family == ip_treat_as_family); 319 ipv46x = !(sa_family == ip_treat_as_family);
376#else
377 ipv46x = !(sa_family == AF_INET);
378#endif
379 320
380 /* node address of the wrong family? */ 321 /* node address of the wrong family? */
381 if (ipv46x) 322 if (ipv46x)
@@ -454,43 +395,17 @@ static int replace_bad( Client_data *list,
454 uint32_t i; 395 uint32_t i;
455 uint64_t temp_time = unix_time(); 396 uint64_t temp_time = unix_time();
456 397
457#ifdef CLIENT_ONETOONE_IP
458 uint8_t candropipv4 = 1;
459
460 if (ip_port.ip.family == AF_INET6) {
461 uint32_t ipv6cnt = 0;
462
463 /* ipv6: count how many spots are used */
464 for (i = 0; i < length; i++)
465 if (list[i].assoc.ip_port.ip.family == AF_INET6)
466 ipv6cnt++;
467
468 /* more than half the list filled with ipv6: block ipv4->ipv6 overwrite */
469 if (ipv6cnt > length / 2)
470 candropipv4 = 0;
471 }
472
473#endif
474
475 for (i = 0; i < length; ++i) { 398 for (i = 0; i < length; ++i) {
476 /* If node is bad */ 399 /* If node is bad */
477 Client_data *client = &list[i]; 400 Client_data *client = &list[i];
478 IPPTsPng *ipptp = NULL; 401 IPPTsPng *ipptp = NULL;
479 402
480#ifdef CLIENT_ONETOONE_IP
481 ipptp = &client->assoc;
482
483 if ((candropipv4 || (ipptp->ip_port.ip.family == AF_INET6)) &&
484 is_timeout(temp_time, ipptp->timestamp, BAD_NODE_TIMEOUT)) {
485#else
486
487 if (ip_port.ip.family == AF_INET) 403 if (ip_port.ip.family == AF_INET)
488 ipptp = &client->assoc4; 404 ipptp = &client->assoc4;
489 else 405 else
490 ipptp = &client->assoc6; 406 ipptp = &client->assoc6;
491 407
492 if (is_timeout(temp_time, ipptp->timestamp, BAD_NODE_TIMEOUT)) { 408 if (is_timeout(temp_time, ipptp->timestamp, BAD_NODE_TIMEOUT)) {
493#endif
494 memcpy(client->client_id, client_id, CLIENT_ID_SIZE); 409 memcpy(client->client_id, client_id, CLIENT_ID_SIZE);
495 ipptp->ip_port = ip_port; 410 ipptp->ip_port = ip_port;
496 ipptp->timestamp = temp_time; 411 ipptp->timestamp = temp_time;
@@ -542,60 +457,17 @@ static int replace_good( Client_data *list,
542 457
543 int8_t replace = -1; 458 int8_t replace = -1;
544 459
545#ifdef CLIENT_ONETOONE_IP 460 /* Because the list is sorted, we can simply check the client_id at the
546 uint8_t candropipv4 = 1; 461 * border, either it is closer, then every other one is as well, or it is
547 462 * further, then it gets pushed out in favor of the new address, which
548 if (ip_port.ip.family == AF_INET6) { 463 * will with the next sort() move to its "rightful" position
549 uint32_t i, ipv6cnt = 0; 464 *
550 465 * CAVEAT: weirdly enough, the list is sorted DESCENDING in distance
551 /* ipv6: count how many spots are used */ 466 * so the furthest element is the first, NOT the last (at least that's
552 for (i = 0; i < length; i++) 467 * what the comment above sort_list() claims)
553 if (list[i].assoc.ip_port.ip.family == AF_INET6) 468 */
554 ipv6cnt++; 469 if (id_closest(comp_client_id, list[0].client_id, client_id) == 2)
555 470 replace = 0;
556 /* more than half the list filled with ipv6: block ipv4->ipv6 overwrite */
557 if (ipv6cnt > length / 2)
558 candropipv4 = 0;
559 }
560
561 uint32_t i;
562
563 if (candropipv4) {
564 /* either we got an ipv4 address, or we're "allowed" to push out an ipv4
565 * address in favor of an ipv6 one
566 *
567 * because the list is sorted, we can simply check the client_id at the
568 * border, either it is closer, then every other one is as well, or it is
569 * further, then it gets pushed out in favor of the new address, which
570 * will with the next sort() move to its "rightful" position
571 *
572 * CAVEAT: weirdly enough, the list is sorted DESCENDING in distance
573 * so the furthest element is the first, NOT the last (at least that's
574 * what the comment above sort_list() claims)
575 */
576#endif
577 if (id_closest(comp_client_id, list[0].client_id, client_id) == 2)
578 replace = 0;
579
580#ifdef CLIENT_ONETOONE_IP
581 } else {
582 /* ipv6 case without a right to push out an ipv4: only look for ipv6
583 * addresses, the first one we find is either closer (then we can skip
584 * out like above) or further (then we can replace it, like above)
585 */
586 for (i = 0; i < length; i++) {
587 Client_data *client = &list[i];
588
589 if (client->assoc.ip_port.ip.family == AF_INET6) {
590 if (id_closest(comp_client_id, list[i].client_id, client_id) == 2)
591 replace = i;
592
593 break;
594 }
595 }
596 }
597
598#endif
599 471
600 if (replace != -1) { 472 if (replace != -1) {
601#ifdef DEBUG 473#ifdef DEBUG
@@ -603,16 +475,12 @@ static int replace_good( Client_data *list,
603#endif 475#endif
604 Client_data *client = &list[replace]; 476 Client_data *client = &list[replace];
605 IPPTsPng *ipptp = NULL; 477 IPPTsPng *ipptp = NULL;
606#ifdef CLIENT_ONETOONE_IP
607 ipptp = &client->assoc;
608#else
609 478
610 if (ip_port.ip.family == AF_INET) 479 if (ip_port.ip.family == AF_INET)
611 ipptp = &client->assoc4; 480 ipptp = &client->assoc4;
612 else 481 else
613 ipptp = &client->assoc6; 482 ipptp = &client->assoc6;
614 483
615#endif
616 memcpy(client->client_id, client_id, CLIENT_ID_SIZE); 484 memcpy(client->client_id, client_id, CLIENT_ID_SIZE);
617 ipptp->ip_port = ip_port; 485 ipptp->ip_port = ip_port;
618 ipptp->timestamp = unix_time(); 486 ipptp->timestamp = unix_time();
@@ -681,11 +549,6 @@ static void returnedip_ports(DHT *dht, IP_Port ip_port, uint8_t *client_id, uint
681 if (id_equal(client_id, dht->c->self_public_key)) { 549 if (id_equal(client_id, dht->c->self_public_key)) {
682 for (i = 0; i < LCLIENT_LIST; ++i) { 550 for (i = 0; i < LCLIENT_LIST; ++i) {
683 if (id_equal(nodeclient_id, dht->close_clientlist[i].client_id)) { 551 if (id_equal(nodeclient_id, dht->close_clientlist[i].client_id)) {
684#ifdef CLIENT_ONETOONE_IP
685 dht->close_clientlist[i].assoc.ret_ip_port = ip_port;
686 dht->close_clientlist[i].assoc.ret_timestamp = temp_time;
687#else
688
689 if (ip_port.ip.family == AF_INET) { 552 if (ip_port.ip.family == AF_INET) {
690 dht->close_clientlist[i].assoc4.ret_ip_port = ip_port; 553 dht->close_clientlist[i].assoc4.ret_ip_port = ip_port;
691 dht->close_clientlist[i].assoc4.ret_timestamp = temp_time; 554 dht->close_clientlist[i].assoc4.ret_timestamp = temp_time;
@@ -694,7 +557,6 @@ static void returnedip_ports(DHT *dht, IP_Port ip_port, uint8_t *client_id, uint
694 dht->close_clientlist[i].assoc6.ret_timestamp = temp_time; 557 dht->close_clientlist[i].assoc6.ret_timestamp = temp_time;
695 } 558 }
696 559
697#endif
698 return; 560 return;
699 } 561 }
700 } 562 }
@@ -704,11 +566,6 @@ static void returnedip_ports(DHT *dht, IP_Port ip_port, uint8_t *client_id, uint
704 if (id_equal(client_id, dht->friends_list[i].client_id)) { 566 if (id_equal(client_id, dht->friends_list[i].client_id)) {
705 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 567 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
706 if (id_equal(nodeclient_id, dht->friends_list[i].client_list[j].client_id)) { 568 if (id_equal(nodeclient_id, dht->friends_list[i].client_list[j].client_id)) {
707#ifdef CLIENT_ONETOONE_IP
708 dht->friends_list[i].client_list[j].assoc.ret_ip_port = ip_port;
709 dht->friends_list[i].client_list[j].assoc.ret_timestamp = temp_time;
710#else
711
712 if (ip_port.ip.family == AF_INET) { 569 if (ip_port.ip.family == AF_INET) {
713 dht->friends_list[i].client_list[j].assoc4.ret_ip_port = ip_port; 570 dht->friends_list[i].client_list[j].assoc4.ret_ip_port = ip_port;
714 dht->friends_list[i].client_list[j].assoc4.ret_timestamp = temp_time; 571 dht->friends_list[i].client_list[j].assoc4.ret_timestamp = temp_time;
@@ -717,7 +574,6 @@ static void returnedip_ports(DHT *dht, IP_Port ip_port, uint8_t *client_id, uint
717 dht->friends_list[i].client_list[j].assoc6.ret_timestamp = temp_time; 574 dht->friends_list[i].client_list[j].assoc6.ret_timestamp = temp_time;
718 } 575 }
719 576
720#endif
721 return; 577 return;
722 } 578 }
723 } 579 }
@@ -836,7 +692,7 @@ static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cl
836 new_nonce(nonce); 692 new_nonce(nonce);
837 693
838 memcpy(plain, &ping_id, sizeof(ping_id)); 694 memcpy(plain, &ping_id, sizeof(ping_id));
839#ifdef TOX_ENABLE_IPV6 695
840 Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id)); 696 Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id));
841 int i, num_nodes_ok = 0; 697 int i, num_nodes_ok = 0;
842 698
@@ -862,10 +718,6 @@ static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cl
862 num_nodes = num_nodes_ok; 718 num_nodes = num_nodes_ok;
863 } 719 }
864 720
865#else
866 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * Node4_format_size);
867#endif
868
869 int len = encrypt_data( public_key, 721 int len = encrypt_data( public_key,
870 dht->c->self_secret_key, 722 dht->c->self_secret_key,
871 nonce, 723 nonce,
@@ -887,7 +739,6 @@ static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cl
887 return sendpacket(dht->c->lossless_udp->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); 739 return sendpacket(dht->c->lossless_udp->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len);
888} 740}
889 741
890#ifdef TOX_ENABLE_IPV6
891/* Send a send nodes response: message for IPv6 nodes */ 742/* Send a send nodes response: message for IPv6 nodes */
892static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id) 743static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id)
893{ 744{
@@ -933,7 +784,6 @@ static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_
933 784
934 return sendpacket(dht->c->lossless_udp->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); 785 return sendpacket(dht->c->lossless_udp->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len);
935} 786}
936#endif
937 787
938static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) 788static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length)
939{ 789{
@@ -962,10 +812,8 @@ static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32
962 812
963 memcpy(&ping_id, plain, sizeof(ping_id)); 813 memcpy(&ping_id, plain, sizeof(ping_id));
964 sendnodes(dht, source, packet + 1, plain + sizeof(ping_id), ping_id); 814 sendnodes(dht, source, packet + 1, plain + sizeof(ping_id), ping_id);
965#ifdef TOX_ENABLE_IPV6
966 sendnodes_ipv6(dht, source, packet + 1, plain + sizeof(ping_id), 815 sendnodes_ipv6(dht, source, packet + 1, plain + sizeof(ping_id),
967 ping_id); /* TODO: prevent possible amplification attacks */ 816 ping_id); /* TODO: prevent possible amplification attacks */
968#endif
969 817
970 add_toping(dht->ping, packet + 1, source); 818 add_toping(dht->ping, packet + 1, source);
971 //send_ping_request(dht, source, packet + 1); /* TODO: make this smarter? */ 819 //send_ping_request(dht, source, packet + 1); /* TODO: make this smarter? */
@@ -1005,14 +853,11 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3
1005 if (!is_gettingnodes(dht, source, ping_id)) 853 if (!is_gettingnodes(dht, source, ping_id))
1006 return 1; 854 return 1;
1007 855
1008 uint32_t i;
1009 Node_format nodes_list[MAX_SENT_NODES];
1010
1011#ifdef TOX_ENABLE_IPV6
1012 Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id)); 856 Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id));
857 Node_format nodes_list[MAX_SENT_NODES];
858 uint32_t i, num_nodes_ok = 0;
1013 859
1014 uint32_t num_nodes_ok = 0; 860 /* blow up from Node4 (IPv4) wire format to Node (IPv4/IPv6) structure */
1015
1016 for (i = 0; i < num_nodes; i++) 861 for (i = 0; i < num_nodes; i++)
1017 if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != (uint32_t)~0)) { 862 if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != (uint32_t)~0)) {
1018 memcpy(nodes_list[num_nodes_ok].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE); 863 memcpy(nodes_list[num_nodes_ok].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE);
@@ -1028,10 +873,6 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3
1028 num_nodes = num_nodes_ok; 873 num_nodes = num_nodes_ok;
1029 } 874 }
1030 875
1031#else
1032 memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format));
1033#endif
1034
1035 addto_lists(dht, source, packet + 1); 876 addto_lists(dht, source, packet + 1);
1036 877
1037 for (i = 0; i < num_nodes; ++i) { 878 for (i = 0; i < num_nodes; ++i) {
@@ -1042,7 +883,6 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3
1042 return 0; 883 return 0;
1043} 884}
1044 885
1045#ifdef TOX_ENABLE_IPV6
1046static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, uint32_t length) 886static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, uint32_t length)
1047{ 887{
1048 DHT *dht = object; 888 DHT *dht = object;
@@ -1088,7 +928,6 @@ static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet,
1088 928
1089 return 0; 929 return 0;
1090} 930}
1091#endif
1092 931
1093/*----------------------------------------------------------------------------------*/ 932/*----------------------------------------------------------------------------------*/
1094/*------------------------END of packet handling functions--------------------------*/ 933/*------------------------END of packet handling functions--------------------------*/
@@ -1103,21 +942,17 @@ static void get_bunchnodes(DHT *dht, Client_data *list, uint16_t length, uint16_
1103 942
1104 for (i = 0; i < length; ++i) { 943 for (i = 0; i < length; ++i) {
1105 IPPTsPng *assoc; 944 IPPTsPng *assoc;
1106#ifdef CLIENT_ONETOONE_IP
1107 assoc = &list[i].assoc;
1108#else
1109 uint32_t a; 945 uint32_t a;
1110 946
1111 for (a = 0, assoc = &list[i].assoc6; a < 2; a++, assoc = &list[i].assoc4) 947 for (a = 0, assoc = &list[i].assoc6; a < 2; a++, assoc = &list[i].assoc4)
1112#endif 948 if (ipport_isset(&(assoc->ip_port)) &&
1113 if (ipport_isset(&(assoc->ip_port)) && 949 !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) {
1114 !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { 950 getnodes(dht, assoc->ip_port, list[i].client_id, client_id);
1115 getnodes(dht, assoc->ip_port, list[i].client_id, client_id); 951 ++num;
1116 ++num;
1117 952
1118 if (num >= max_num) 953 if (num >= max_num)
1119 return; 954 return;
1120 } 955 }
1121 } 956 }
1122} 957}
1123 958
@@ -1194,17 +1029,13 @@ int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port)
1194 1029
1195 if (id_equal(client->client_id, client_id)) { 1030 if (id_equal(client->client_id, client_id)) {
1196 IPPTsPng *assoc = NULL; 1031 IPPTsPng *assoc = NULL;
1197#ifdef CLIENT_ONETOONE_IP
1198 assoc = &client->assoc;
1199#else
1200 uint32_t a; 1032 uint32_t a;
1201 1033
1202 for (a = 0, assoc = &client->assoc6; a < 2; a++, assoc = &client->assoc4) 1034 for (a = 0, assoc = &client->assoc6; a < 2; a++, assoc = &client->assoc4)
1203#endif 1035 if (!is_timeout(temp_time, assoc->timestamp, BAD_NODE_TIMEOUT)) {
1204 if (!is_timeout(temp_time, assoc->timestamp, BAD_NODE_TIMEOUT)) { 1036 *ip_port = assoc->ip_port;
1205 *ip_port = assoc->ip_port; 1037 return 1;
1206 return 1; 1038 }
1207 }
1208 } 1039 }
1209 } 1040 }
1210 1041
@@ -1229,27 +1060,22 @@ static void do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, uint8
1229 /* If node is not dead. */ 1060 /* If node is not dead. */
1230 Client_data *client = &list[i]; 1061 Client_data *client = &list[i];
1231 IPPTsPng *assoc; 1062 IPPTsPng *assoc;
1232#ifdef CLIENT_ONETOONE_IP
1233 assoc = &client->assoc;
1234#else
1235 uint32_t a; 1063 uint32_t a;
1236 1064
1237 for (a = 0, assoc = &client->assoc6; a < 2; a++, assoc = &client->assoc4) 1065 for (a = 0, assoc = &client->assoc6; a < 2; a++, assoc = &client->assoc4)
1238#endif 1066 if (!is_timeout(temp_time, assoc->timestamp, KILL_NODE_TIMEOUT)) {
1239 1067 if (is_timeout(temp_time, assoc->last_pinged, PING_INTERVAL)) {
1240 if (!is_timeout(temp_time, assoc->timestamp, KILL_NODE_TIMEOUT)) { 1068 send_ping_request(dht->ping, assoc->ip_port, client->client_id );
1241 if (is_timeout(temp_time, assoc->last_pinged, PING_INTERVAL)) { 1069 assoc->last_pinged = temp_time;
1242 send_ping_request(dht->ping, assoc->ip_port, client->client_id ); 1070 }
1243 assoc->last_pinged = temp_time;
1244 }
1245 1071
1246 /* If node is good. */ 1072 /* If node is good. */
1247 if (!is_timeout(temp_time, assoc->timestamp, BAD_NODE_TIMEOUT)) { 1073 if (!is_timeout(temp_time, assoc->timestamp, BAD_NODE_TIMEOUT)) {
1248 client_list[num_nodes] = client; 1074 client_list[num_nodes] = client;
1249 assoc_list[num_nodes] = assoc; 1075 assoc_list[num_nodes] = assoc;
1250 ++num_nodes; 1076 ++num_nodes;
1077 }
1251 } 1078 }
1252 }
1253 } 1079 }
1254 1080
1255 if ((num_nodes != 0) && 1081 if ((num_nodes != 0) &&
@@ -1291,31 +1117,25 @@ int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enable
1291{ 1117{
1292 IP_Port ip_port_v64; 1118 IP_Port ip_port_v64;
1293 IP *ip_extra = NULL; 1119 IP *ip_extra = NULL;
1294#ifdef TOX_ENABLE_IPV6
1295 IP_Port ip_port_v4; 1120 IP_Port ip_port_v4;
1296 ip_init(&ip_port_v64.ip, ipv6enabled); 1121 ip_init(&ip_port_v64.ip, ipv6enabled);
1297 1122
1298 if (ipv6enabled) { 1123 if (ipv6enabled) {
1124 /* setup for getting BOTH: an IPv6 AND an IPv4 address */
1299 ip_port_v64.ip.family = AF_UNSPEC; 1125 ip_port_v64.ip.family = AF_UNSPEC;
1300 ip_reset(&ip_port_v4.ip); 1126 ip_reset(&ip_port_v4.ip);
1301 ip_extra = &ip_port_v4.ip; 1127 ip_extra = &ip_port_v4.ip;
1302 } 1128 }
1303 1129
1304#else
1305 ip_init(&ip_port_v64.ip, 0);
1306#endif
1307
1308 if (addr_resolve_or_parse_ip(address, &ip_port_v64.ip, ip_extra)) { 1130 if (addr_resolve_or_parse_ip(address, &ip_port_v64.ip, ip_extra)) {
1309 ip_port_v64.port = port; 1131 ip_port_v64.port = port;
1310 DHT_bootstrap(dht, ip_port_v64, public_key); 1132 DHT_bootstrap(dht, ip_port_v64, public_key);
1311#ifdef TOX_ENABLE_IPV6
1312 1133
1313 if ((ip_extra != NULL) && ip_isset(ip_extra)) { 1134 if ((ip_extra != NULL) && ip_isset(ip_extra)) {
1314 ip_port_v4.port = port; 1135 ip_port_v4.port = port;
1315 DHT_bootstrap(dht, ip_port_v4, public_key); 1136 DHT_bootstrap(dht, ip_port_v4, public_key);
1316 } 1137 }
1317 1138
1318#endif
1319 return 1; 1139 return 1;
1320 } else 1140 } else
1321 return 0; 1141 return 0;
@@ -1332,12 +1152,6 @@ int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length)
1332 for (i = 0; i < LCLIENT_LIST; ++i) { 1152 for (i = 0; i < LCLIENT_LIST; ++i) {
1333 if (id_equal(client_id, dht->close_clientlist[i].client_id)) { 1153 if (id_equal(client_id, dht->close_clientlist[i].client_id)) {
1334 Client_data *client = &dht->close_clientlist[i]; 1154 Client_data *client = &dht->close_clientlist[i];
1335#ifdef CLIENT_ONETOONE_IP
1336
1337 if (ip_isset(&client->assoc.ip_port.ip))
1338 return sendpacket(dht->c->lossless_udp->net, dht->close_clientlist[i].assoc.ip_port, packet, length);
1339
1340#else
1341 1155
1342 if (ip_isset(&client->assoc6.ip_port.ip)) 1156 if (ip_isset(&client->assoc6.ip_port.ip))
1343 return sendpacket(dht->c->lossless_udp->net, client->assoc6.ip_port, packet, length); 1157 return sendpacket(dht->c->lossless_udp->net, client->assoc6.ip_port, packet, length);
@@ -1345,8 +1159,6 @@ int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length)
1345 return sendpacket(dht->c->lossless_udp->net, client->assoc4.ip_port, packet, length); 1159 return sendpacket(dht->c->lossless_udp->net, client->assoc4.ip_port, packet, length);
1346 else 1160 else
1347 break; 1161 break;
1348
1349#endif
1350 } 1162 }
1351 } 1163 }
1352 1164
@@ -1355,7 +1167,6 @@ int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length)
1355 1167
1356/* Puts all the different ips returned by the nodes for a friend_num into array ip_portlist. 1168/* Puts all the different ips returned by the nodes for a friend_num into array ip_portlist.
1357 * ip_portlist must be at least MAX_FRIEND_CLIENTS big. 1169 * ip_portlist must be at least MAX_FRIEND_CLIENTS big.
1358 * unless CLIENT_ONETOONE_IP is defined, returns an array with ips of the same family.
1359 * 1170 *
1360 * return the number of ips returned. 1171 * return the number of ips returned.
1361 * return 0 if we are connected to friend or if no ips were found. 1172 * return 0 if we are connected to friend or if no ips were found.
@@ -1375,55 +1186,56 @@ static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num)
1375 int num_ipv4s = 0; 1186 int num_ipv4s = 0;
1376 IP_Port ipv6s[MAX_FRIEND_CLIENTS]; 1187 IP_Port ipv6s[MAX_FRIEND_CLIENTS];
1377 int num_ipv6s = 0; 1188 int num_ipv6s = 0;
1189 uint8_t connected;
1378 1190
1379 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { 1191 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
1380 client = &(friend->client_list[i]); 1192 client = &(friend->client_list[i]);
1381 1193 connected = 0;
1382 IPPTsPng *assoc = NULL;
1383#ifdef CLIENT_ONETOONE_IP
1384 assoc = &client->assoc;
1385#else
1386 assoc = &client->assoc4;
1387#endif
1388
1389 if (id_equal(client->client_id, friend->client_id) &&
1390 !is_timeout(temp_time, assoc->timestamp, BAD_NODE_TIMEOUT))
1391 return 0;
1392 1194
1393 /* If ip is not zero and node is good. */ 1195 /* If ip is not zero and node is good. */
1394 if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { 1196 if (ip_isset(&client->assoc4.ret_ip_port.ip) && !is_timeout(temp_time, client->assoc4.ret_timestamp, BAD_NODE_TIMEOUT)) {
1395 ipv4s[num_ipv4s] = assoc->ret_ip_port; 1197 ipv4s[num_ipv4s] = client->assoc4.ret_ip_port;
1396 ++num_ipv4s; 1198 ++num_ipv4s;
1199
1200 connected = 1;
1397 } 1201 }
1398 }
1399 1202
1400#ifndef CLIENT_ONETOONE_IP 1203 if (ip_isset(&client->assoc6.ret_ip_port.ip) && !is_timeout(temp_time, client->assoc6.ret_timestamp, BAD_NODE_TIMEOUT)) {
1204 ipv6s[num_ipv6s] = client->assoc6.ret_ip_port;
1205 ++num_ipv6s;
1401 1206
1402 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { 1207 connected = 1;
1403 client = &(friend->client_list[i]); 1208 }
1404 1209
1405 IPPTsPng *assoc = NULL; 1210 if (connected && id_equal(client->client_id, friend->client_id))
1406 assoc = &client->assoc6; 1211 return 0; /* direct connectivity */
1212 }
1407 1213
1408 if (id_equal(client->client_id, friend->client_id) && 1214#ifdef FRIEND_IPLIST_PAD
1409 !is_timeout(temp_time, assoc->timestamp, BAD_NODE_TIMEOUT)) 1215 memcpy(ip_portlist, ipv6s, num_ipv6s * sizeof(IP_Port));
1410 return 0; 1216 if (num_ipv6s == MAX_FRIEND_CLIENTS)
1217 return MAX_FRIEND_CLIENTS;
1411 1218
1412 /* If ip is not zero and node is good. */ 1219 int num_ipv4s_used = MAX_FRIEND_CLIENTS - num_ipv6s;
1413 if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { 1220 if (num_ipv4s_used > num_ipv4s)
1414 ipv6s[num_ipv6s] = assoc->ret_ip_port; 1221 num_ipv4s_used = num_ipv4s;
1415 ++num_ipv6s; 1222 memcpy(&ip_portlist[num_ipv6s], ipv4s, num_ipv4s_used * sizeof(IP_Port));
1416 } 1223 return num_ipv6s + num_ipv4s_used;
1417 } 1224
1225#else /* !FRIEND_IPLIST_PAD */
1418 1226
1227 /* there must be some secret reason why we can't pad the longer list
1228 * with the shorter one...
1229 */
1419 if (num_ipv6s >= num_ipv4s) { 1230 if (num_ipv6s >= num_ipv4s) {
1420 memcpy(ip_portlist, ipv6s, num_ipv6s * sizeof(IP_Port)); 1231 memcpy(ip_portlist, ipv6s, num_ipv6s * sizeof(IP_Port));
1421 return num_ipv6s; 1232 return num_ipv6s;
1422 } 1233 }
1423 1234
1424#endif
1425 memcpy(ip_portlist, ipv4s, num_ipv4s * sizeof(IP_Port)); 1235 memcpy(ip_portlist, ipv4s, num_ipv4s * sizeof(IP_Port));
1426 return num_ipv4s; 1236 return num_ipv4s;
1237
1238#endif /* !FRIEND_IPLIST_PAD */
1427} 1239}
1428 1240
1429 1241
@@ -1452,30 +1264,23 @@ int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t lengt
1452 DHT_Friend *friend = &dht->friends_list[num]; 1264 DHT_Friend *friend = &dht->friends_list[num];
1453 Client_data *client; 1265 Client_data *client;
1454 1266
1455#ifndef CLIENT_ONETOONE_IP
1456 /* extra legwork, because having the outside allocating the space for us 1267 /* extra legwork, because having the outside allocating the space for us
1457 * is *usually* good(tm) (bites us in the behind in this case though) */ 1268 * is *usually* good(tm) (bites us in the behind in this case though) */
1458 uint32_t a; 1269 uint32_t a;
1459 1270
1460 for (a = 0; a < 2; a++) 1271 for (a = 0; a < 2; a++)
1461#endif
1462 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { 1272 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
1463 if (friend_sent[i])/* Send one packet per client.*/ 1273 if (friend_sent[i])/* Send one packet per client.*/
1464 continue; 1274 continue;
1465 1275
1466 client = &friend->client_list[i]; 1276 client = &friend->client_list[i];
1467 IPPTsPng *assoc = NULL; 1277 IPPTsPng *assoc = NULL;
1468#ifdef CLIENT_ONETOONE_IP
1469 assoc = &client->assoc;
1470#else
1471 1278
1472 if (!a) 1279 if (!a)
1473 assoc = &client->assoc4; 1280 assoc = &client->assoc4;
1474 else 1281 else
1475 assoc = &client->assoc6; 1282 assoc = &client->assoc6;
1476 1283
1477#endif
1478
1479 /* If ip is not zero and node is good. */ 1284 /* If ip is not zero and node is good. */
1480 if (ip_isset(&assoc->ret_ip_port.ip) && 1285 if (ip_isset(&assoc->ret_ip_port.ip) &&
1481 !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { 1286 !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) {
@@ -1510,27 +1315,20 @@ static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint
1510 uint32_t i; 1315 uint32_t i;
1511 uint64_t temp_time = unix_time(); 1316 uint64_t temp_time = unix_time();
1512 1317
1513#ifndef CLIENT_ONETOONE_IP
1514 /* extra legwork, because having the outside allocating the space for us 1318 /* extra legwork, because having the outside allocating the space for us
1515 * is *usually* good(tm) (bites us in the behind in this case though) */ 1319 * is *usually* good(tm) (bites us in the behind in this case though) */
1516 uint32_t a; 1320 uint32_t a;
1517 1321
1518 for (a = 0; a < 2; a++) 1322 for (a = 0; a < 2; a++)
1519#endif
1520 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { 1323 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
1521 client = &friend->client_list[i]; 1324 client = &friend->client_list[i];
1522 IPPTsPng *assoc = NULL; 1325 IPPTsPng *assoc = NULL;
1523#ifdef CLIENT_ONETOONE_IP
1524 assoc = &client->assoc;
1525#else
1526 1326
1527 if (!a) 1327 if (!a)
1528 assoc = &client->assoc4; 1328 assoc = &client->assoc4;
1529 else 1329 else
1530 assoc = &client->assoc6; 1330 assoc = &client->assoc6;
1531 1331
1532#endif
1533
1534 /* If ip is not zero and node is good. */ 1332 /* If ip is not zero and node is good. */
1535 if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { 1333 if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) {
1536 ip_list[n] = assoc->ip_port; 1334 ip_list[n] = assoc->ip_port;
@@ -1776,9 +1574,7 @@ DHT *new_DHT(Net_Crypto *c)
1776 dht->c = c; 1574 dht->c = c;
1777 networking_registerhandler(c->lossless_udp->net, NET_PACKET_GET_NODES, &handle_getnodes, dht); 1575 networking_registerhandler(c->lossless_udp->net, NET_PACKET_GET_NODES, &handle_getnodes, dht);
1778 networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES, &handle_sendnodes, dht); 1576 networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES, &handle_sendnodes, dht);
1779#ifdef TOX_ENABLE_IPV6
1780 networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, dht); 1577 networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, dht);
1781#endif
1782 1578
1783 init_cryptopackets(dht); 1579 init_cryptopackets(dht);
1784 cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, dht); 1580 cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, dht);
@@ -1885,12 +1681,8 @@ uint32_t DHT_size(DHT *dht)
1885 uint32_t num = 0, i; 1681 uint32_t num = 0, i;
1886 1682
1887 for (i = 0; i < LCLIENT_LIST; ++i) 1683 for (i = 0; i < LCLIENT_LIST; ++i)
1888#ifdef CLIENT_ONETOONE_IP
1889 if (dht->close_clientlist[i].assoc.timestamp != 0)
1890#else
1891 if ((dht->close_clientlist[i].assoc4.timestamp != 0) || 1684 if ((dht->close_clientlist[i].assoc4.timestamp != 0) ||
1892 (dht->close_clientlist[i].assoc6.timestamp != 0)) 1685 (dht->close_clientlist[i].assoc6.timestamp != 0))
1893#endif
1894 num++; 1686 num++;
1895 1687
1896 uint32_t size32 = sizeof(uint32_t), sizesubhead = size32 * 2; 1688 uint32_t size32 = sizeof(uint32_t), sizesubhead = size32 * 2;
@@ -1917,11 +1709,7 @@ void DHT_save(DHT *dht, uint8_t *data)
1917 data += sizeof(uint32_t); 1709 data += sizeof(uint32_t);
1918 1710
1919 len = sizeof(DHT_Friend) * dht->num_friends; 1711 len = sizeof(DHT_Friend) * dht->num_friends;
1920#ifdef CLIENT_ONETOONE_IP
1921 type = DHT_STATE_TYPE_FRIENDS;
1922#else
1923 type = DHT_STATE_TYPE_FRIENDS_ASSOC46; 1712 type = DHT_STATE_TYPE_FRIENDS_ASSOC46;
1924#endif
1925 data = z_state_save_subheader(data, len, type); 1713 data = z_state_save_subheader(data, len, type);
1926 memcpy(data, dht->friends_list, len); 1714 memcpy(data, dht->friends_list, len);
1927 data += len; 1715 data += len;
@@ -1929,32 +1717,20 @@ void DHT_save(DHT *dht, uint8_t *data)
1929 uint32_t num = 0, i; 1717 uint32_t num = 0, i;
1930 1718
1931 for (i = 0; i < LCLIENT_LIST; ++i) 1719 for (i = 0; i < LCLIENT_LIST; ++i)
1932#ifdef CLIENT_ONETOONE_IP
1933 if (dht->close_clientlist[i].assoc.timestamp != 0)
1934#else
1935 if ((dht->close_clientlist[i].assoc4.timestamp != 0) || 1720 if ((dht->close_clientlist[i].assoc4.timestamp != 0) ||
1936 (dht->close_clientlist[i].assoc6.timestamp != 0)) 1721 (dht->close_clientlist[i].assoc6.timestamp != 0))
1937#endif
1938 num++; 1722 num++;
1939 1723
1940 len = num * sizeof(Client_data); 1724 len = num * sizeof(Client_data);
1941#ifdef CLIENT_ONETOONE_IP
1942 type = DHT_STATE_TYPE_CLIENTS;
1943#else
1944 type = DHT_STATE_TYPE_CLIENTS_ASSOC46; 1725 type = DHT_STATE_TYPE_CLIENTS_ASSOC46;
1945#endif
1946 data = z_state_save_subheader(data, len, type); 1726 data = z_state_save_subheader(data, len, type);
1947 1727
1948 if (num) { 1728 if (num) {
1949 Client_data *clients = (Client_data *)data; 1729 Client_data *clients = (Client_data *)data;
1950 1730
1951 for (num = 0, i = 0; i < LCLIENT_LIST; ++i) 1731 for (num = 0, i = 0; i < LCLIENT_LIST; ++i)
1952#ifdef CLIENT_ONETOONE_IP
1953 if (dht->close_clientlist[i].assoc.timestamp != 0)
1954#else
1955 if ((dht->close_clientlist[i].assoc4.timestamp != 0) || 1732 if ((dht->close_clientlist[i].assoc4.timestamp != 0) ||
1956 (dht->close_clientlist[i].assoc6.timestamp != 0)) 1733 (dht->close_clientlist[i].assoc6.timestamp != 0))
1957#endif
1958 memcpy(&clients[num++], &dht->close_clientlist[i], sizeof(Client_data)); 1734 memcpy(&clients[num++], &dht->close_clientlist[i], sizeof(Client_data));
1959 } 1735 }
1960 1736
@@ -2005,18 +1781,18 @@ static int dht_load_state_callback(void *outer, uint8_t *data, uint32_t length,
2005 break; 1781 break;
2006 1782
2007 case DHT_STATE_TYPE_FRIENDS_ASSOC46: 1783 case DHT_STATE_TYPE_FRIENDS_ASSOC46:
2008 if (length % sizeof(DHT_Friend_new) != 0) 1784 if (length % sizeof(DHT_Friend) != 0)
2009 break; 1785 break;
2010 1786
2011 { /* localize declarations */ 1787 { /* localize declarations */
2012 DHT_Friend_new *friend_list = (DHT_Friend_new *)data; 1788 DHT_Friend *friend_list = (DHT_Friend *)data;
2013 num = length / sizeof(DHT_Friend_new); 1789 num = length / sizeof(DHT_Friend);
2014 1790
2015 for (i = 0; i < num; ++i) { 1791 for (i = 0; i < num; ++i) {
2016 DHT_addfriend(dht, friend_list[i].client_id); 1792 DHT_addfriend(dht, friend_list[i].client_id);
2017 1793
2018 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 1794 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
2019 Client_data_new *client = &friend_list[i].client_list[j]; 1795 Client_data *client = &friend_list[i].client_list[j];
2020 1796
2021 if (client->assoc4.timestamp != 0) 1797 if (client->assoc4.timestamp != 0)
2022 getnodes(dht, client->assoc4.ip_port, client->client_id, friend_list[i].client_id); 1798 getnodes(dht, client->assoc4.ip_port, client->client_id, friend_list[i].client_id);
@@ -2030,12 +1806,12 @@ static int dht_load_state_callback(void *outer, uint8_t *data, uint32_t length,
2030 break; 1806 break;
2031 1807
2032 case DHT_STATE_TYPE_CLIENTS_ASSOC46: 1808 case DHT_STATE_TYPE_CLIENTS_ASSOC46:
2033 if ((length % sizeof(Client_data_new)) != 0) 1809 if ((length % sizeof(Client_data)) != 0)
2034 break; 1810 break;
2035 1811
2036 { /* localize declarations */ 1812 { /* localize declarations */
2037 num = length / sizeof(Client_data_new); 1813 num = length / sizeof(Client_data);
2038 Client_data_new *client_list = (Client_data_new *)data; 1814 Client_data *client_list = (Client_data *)data;
2039 1815
2040 for (i = 0; i < num; ++i) { 1816 for (i = 0; i < num; ++i) {
2041 if (client_list[i].assoc4.timestamp != 0) 1817 if (client_list[i].assoc4.timestamp != 0)
@@ -2048,9 +1824,12 @@ static int dht_load_state_callback(void *outer, uint8_t *data, uint32_t length,
2048 1824
2049 break; 1825 break;
2050 1826
1827#ifdef DEBUG
2051 default: 1828 default:
2052 fprintf(stderr, "Load state (DHT): contains unrecognized part (len %u, type %u)\n", 1829 fprintf(stderr, "Load state (DHT): contains unrecognized part (len %u, type %u)\n",
2053 length, type); 1830 length, type);
1831 break;
1832#endif
2054 } 1833 }
2055 1834
2056 return 0; 1835 return 0;
@@ -2085,13 +1864,9 @@ int DHT_isconnected(DHT *dht)
2085 1864
2086 for (i = 0; i < LCLIENT_LIST; ++i) { 1865 for (i = 0; i < LCLIENT_LIST; ++i) {
2087 Client_data *client = &dht->close_clientlist[i]; 1866 Client_data *client = &dht->close_clientlist[i];
2088#ifdef CLIENT_ONETOONE_IP
2089 1867
2090 if (!is_timeout(temp_time, client->assoc.timestamp, BAD_NODE_TIMEOUT))
2091#else
2092 if (!is_timeout(temp_time, client->assoc4.timestamp, BAD_NODE_TIMEOUT) || 1868 if (!is_timeout(temp_time, client->assoc4.timestamp, BAD_NODE_TIMEOUT) ||
2093 !is_timeout(temp_time, client->assoc6.timestamp, BAD_NODE_TIMEOUT)) 1869 !is_timeout(temp_time, client->assoc6.timestamp, BAD_NODE_TIMEOUT))
2094#endif
2095 return 1; 1870 return 1;
2096 } 1871 }
2097 1872
diff --git a/toxcore/DHT.h b/toxcore/DHT.h
index 46193b56..360773ff 100644
--- a/toxcore/DHT.h
+++ b/toxcore/DHT.h
@@ -56,13 +56,13 @@ typedef struct {
56typedef struct { 56typedef struct {
57 uint8_t client_id[CLIENT_ID_SIZE]; 57 uint8_t client_id[CLIENT_ID_SIZE];
58 IPPTsPng assoc; 58 IPPTsPng assoc;
59} Client_data_old; 59} Client_data_old; /* required to load old state files */
60 60
61typedef struct { 61typedef struct {
62 uint8_t client_id[CLIENT_ID_SIZE]; 62 uint8_t client_id[CLIENT_ID_SIZE];
63 IPPTsPng assoc4; 63 IPPTsPng assoc4;
64 IPPTsPng assoc6; 64 IPPTsPng assoc6;
65} Client_data_new; 65} Client_data;
66 66
67/*----------------------------------------------------------------------------------*/ 67/*----------------------------------------------------------------------------------*/
68 68
@@ -85,27 +85,18 @@ typedef struct {
85 85
86 /* Symetric NAT hole punching stuff. */ 86 /* Symetric NAT hole punching stuff. */
87 NAT nat; 87 NAT nat;
88} DHT_Friend_old; 88} DHT_Friend_old; /* required to load old state files */
89 89
90typedef struct { 90typedef struct {
91 uint8_t client_id[CLIENT_ID_SIZE]; 91 uint8_t client_id[CLIENT_ID_SIZE];
92 Client_data_new client_list[MAX_FRIEND_CLIENTS]; 92 Client_data client_list[MAX_FRIEND_CLIENTS];
93 93
94 /* Time at which the last get_nodes request was sent. */ 94 /* Time at which the last get_nodes request was sent. */
95 uint64_t lastgetnode; 95 uint64_t lastgetnode;
96 96
97 /* Symetric NAT hole punching stuff. */ 97 /* Symetric NAT hole punching stuff. */
98 NAT nat; 98 NAT nat;
99} DHT_Friend_new; 99} DHT_Friend;
100
101/* #define CLIENT_ONETOONE_IP */
102#ifdef CLIENT_ONETOONE_IP
103typedef Client_data_old Client_data;
104typedef DHT_Friend_old DHT_Friend;
105#else
106typedef Client_data_new Client_data;
107typedef DHT_Friend_new DHT_Friend;
108#endif
109 100
110/* this must be kept even if IP_Port is expanded: wire compatibility */ 101/* this must be kept even if IP_Port is expanded: wire compatibility */
111typedef struct { 102typedef struct {
@@ -116,13 +107,7 @@ typedef struct {
116typedef struct { 107typedef struct {
117 uint8_t client_id[CLIENT_ID_SIZE]; 108 uint8_t client_id[CLIENT_ID_SIZE];
118 IP_Port ip_port; 109 IP_Port ip_port;
119} Node46_format; 110} Node_format;
120
121#ifdef TOX_ENABLE_IPV6
122typedef Node46_format Node_format;
123#else
124typedef Node4_format Node_format;
125#endif
126 111
127/*----------------------------------------------------------------------------------*/ 112/*----------------------------------------------------------------------------------*/
128 113
diff --git a/toxcore/LAN_discovery.c b/toxcore/LAN_discovery.c
index 1e4fa125..a4f1ccc2 100644
--- a/toxcore/LAN_discovery.c
+++ b/toxcore/LAN_discovery.c
@@ -30,60 +30,89 @@
30#define MAX_INTERFACES 16 30#define MAX_INTERFACES 16
31 31
32#ifdef __linux 32#ifdef __linux
33#ifndef TOX_ENABLE_IPV6 33
34/* Send packet to all broadcast addresses 34static int broadcast_count = -1;
35 * 35static IP_Port broadcast_ip_port[MAX_INTERFACES];
36 * return higher than 0 on success. 36
37 * return 0 on error. 37static void fetch_broadcast_info(uint16_t port)
38 *
39 * TODO: Make this work with IPv6 and remove the #ifndef TOX_ENABLE_IPV6.
40 */
41static uint32_t send_broadcasts(Networking_Core *net, uint16_t port, uint8_t *data, uint16_t length)
42{ 38{
43 /* Not sure how many platforms this will run on, 39 /* Not sure how many platforms this will run on,
44 * so it's wrapped in __linux for now. 40 * so it's wrapped in __linux for now.
41 * Definitely won't work like this on Windows...
45 */ 42 */
46 struct sockaddr_in *sock_holder = NULL; 43 broadcast_count = 0;
47 struct ifreq i_faces[MAX_INTERFACES]; 44 sock_t sock = 0;
48 struct ifconf ifconf;
49 int count = 0;
50 int sock = 0;
51 int i = 0;
52 45
53 /* Configure ifconf for the ioctl call. */ 46 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
54 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 47 return;
55 return 1;
56 }
57 48
49 /* Configure ifconf for the ioctl call. */
50 struct ifreq i_faces[MAX_INTERFACES];
58 memset(i_faces, 0, sizeof(struct ifreq) * MAX_INTERFACES); 51 memset(i_faces, 0, sizeof(struct ifreq) * MAX_INTERFACES);
59 52
53 struct ifconf ifconf;
60 ifconf.ifc_buf = (char *)i_faces; 54 ifconf.ifc_buf = (char *)i_faces;
61 ifconf.ifc_len = sizeof(i_faces); 55 ifconf.ifc_len = sizeof(i_faces);
62 count = ifconf.ifc_len / sizeof(struct ifreq);
63 56
64 if (ioctl(sock, SIOCGIFCONF, &ifconf) < 0) { 57 if (ioctl(sock, SIOCGIFCONF, &ifconf) < 0) {
65 return 1; 58 close(sock);
59 return;
66 } 60 }
67 61
62 /* ifconf.ifc_len is set by the ioctl() to the actual length used;
63 * on usage of the complete array the call should be repeated with
64 * a larger array, not done (640kB and 16 interfaces shall be
65 * enough, for everybody!)
66 */
67 int i, count = ifconf.ifc_len / sizeof(struct ifreq);
68
68 for (i = 0; i < count; i++) { 69 for (i = 0; i < count; i++) {
69 if (ioctl(sock, SIOCGIFBRDADDR, &i_faces[i]) < 0) { 70 /* there are interfaces with are incapable of broadcast */
70 return 1; 71 if (ioctl(sock, SIOCGIFBRDADDR, &i_faces[i]) < 0)
71 } 72 continue;
72 73
73 /* Just to clarify where we're getting the values from. */ 74 /* moot check: only AF_INET returned (backwards compat.) */
74 sock_holder = (struct sockaddr_in *)&i_faces[i].ifr_broadaddr; 75 if (i_faces[i].ifr_broadaddr.sa_family != AF_INET)
76 continue;
75 77
76 if (sock_holder != NULL) { 78 struct sockaddr_in *sock4 = (struct sockaddr_in *)&i_faces[i].ifr_broadaddr;
77 IP_Port ip_port = {{{{sock_holder->sin_addr.s_addr}}, port, 0}}; 79
78 sendpacket(net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES); 80 if (broadcast_count >= MAX_INTERFACES)
79 } 81 return;
82
83 IP_Port *ip_port = &broadcast_ip_port[broadcast_count];
84 ip_port->ip.family = AF_INET;
85 ip_port->ip.ip4.in_addr = sock4->sin_addr;
86 ip_port->port = port;
87 broadcast_count++;
80 } 88 }
81 89
82 close(sock); 90 close(sock);
83 return 0;
84} 91}
85#endif 92
86#endif 93/* Send packet to all IPv4 broadcast addresses
94 *
95 * return 1 if sent to at least one broadcast target.
96 * return 0 on failure to find any valid broadcast target.
97 */
98static uint32_t send_broadcasts(Networking_Core *net, uint16_t port, uint8_t *data, uint16_t length)
99{
100 /* fetch only once? on every packet? every X seconds?
101 * old: every packet, new: once */
102 if (broadcast_count < 0)
103 fetch_broadcast_info(port);
104
105 if (!broadcast_count)
106 return 0;
107
108 int i;
109
110 for (i = 0; i < broadcast_count; i++)
111 sendpacket(net, broadcast_ip_port[i], data, 1 + crypto_box_PUBLICKEYBYTES);
112
113 return 1;
114}
115#endif /* __linux */
87 116
88/* Return the broadcast ip. */ 117/* Return the broadcast ip. */
89static IP broadcast_ip(sa_family_t family_socket, sa_family_t family_broadcast) 118static IP broadcast_ip(sa_family_t family_socket, sa_family_t family_broadcast)
@@ -91,8 +120,6 @@ static IP broadcast_ip(sa_family_t family_socket, sa_family_t family_broadcast)
91 IP ip; 120 IP ip;
92 ip_reset(&ip); 121 ip_reset(&ip);
93 122
94#ifdef TOX_ENABLE_IPV6
95
96 if (family_socket == AF_INET6) { 123 if (family_socket == AF_INET6) {
97 if (family_broadcast == AF_INET6) { 124 if (family_broadcast == AF_INET6) {
98 ip.family = AF_INET6; 125 ip.family = AF_INET6;
@@ -116,14 +143,6 @@ static IP broadcast_ip(sa_family_t family_socket, sa_family_t family_broadcast)
116 } 143 }
117 } 144 }
118 145
119#else
120
121 if (family_socket == AF_INET)
122 if (family_broadcast == AF_INET)
123 ip.uint32 = INADDR_BROADCAST;
124
125#endif
126
127 return ip; 146 return ip;
128} 147}
129 148
@@ -132,13 +151,8 @@ static IP broadcast_ip(sa_family_t family_socket, sa_family_t family_broadcast)
132 */ 151 */
133int LAN_ip(IP ip) 152int LAN_ip(IP ip)
134{ 153{
135#ifdef TOX_ENABLE_IPV6
136
137 if (ip.family == AF_INET) { 154 if (ip.family == AF_INET) {
138 IP4 ip4 = ip.ip4; 155 IP4 ip4 = ip.ip4;
139#else
140 IP4 ip4 = ip;
141#endif
142 156
143 /* Loopback. */ 157 /* Loopback. */
144 if (ip4.uint8[0] == 127) 158 if (ip4.uint8[0] == 127)
@@ -161,9 +175,8 @@ int LAN_ip(IP ip)
161 && ip4.uint8[2] != 255) 175 && ip4.uint8[2] != 255)
162 return 0; 176 return 0;
163 177
164#ifdef TOX_ENABLE_IPV6 178 } else if (ip.family == AF_INET6) {
165 } else if (ip.family == AF_INET6) 179
166 {
167 /* autogenerated for each interface: FE80::* (up to FEBF::*) 180 /* autogenerated for each interface: FE80::* (up to FEBF::*)
168 FF02::1 is - according to RFC 4291 - multicast all-nodes link-local */ 181 FF02::1 is - according to RFC 4291 - multicast all-nodes link-local */
169 if (((ip.ip6.uint8[0] == 0xFF) && (ip.ip6.uint8[1] < 3) && (ip.ip6.uint8[15] == 1)) || 182 if (((ip.ip6.uint8[0] == 0xFF) && (ip.ip6.uint8[1] < 3) && (ip.ip6.uint8[15] == 1)) ||
@@ -179,8 +192,6 @@ int LAN_ip(IP ip)
179 } 192 }
180 } 193 }
181 194
182#endif
183
184 return -1; 195 return -1;
185} 196}
186 197
@@ -206,16 +217,12 @@ int send_LANdiscovery(uint16_t port, Net_Crypto *c)
206 memcpy(data + 1, c->self_public_key, crypto_box_PUBLICKEYBYTES); 217 memcpy(data + 1, c->self_public_key, crypto_box_PUBLICKEYBYTES);
207 218
208#ifdef __linux 219#ifdef __linux
209#ifndef TOX_ENABLE_IPV6
210 send_broadcasts(c->lossless_udp->net, port, data, 1 + crypto_box_PUBLICKEYBYTES); 220 send_broadcasts(c->lossless_udp->net, port, data, 1 + crypto_box_PUBLICKEYBYTES);
211#endif 221#endif
212#endif
213 int res = -1; 222 int res = -1;
214 IP_Port ip_port; 223 IP_Port ip_port;
215 ip_port.port = port; 224 ip_port.port = port;
216 225
217#ifdef TOX_ENABLE_IPV6
218
219 /* IPv6 multicast */ 226 /* IPv6 multicast */
220 if (c->lossless_udp->net->family == AF_INET6) { 227 if (c->lossless_udp->net->family == AF_INET6) {
221 ip_port.ip = broadcast_ip(AF_INET6, AF_INET6); 228 ip_port.ip = broadcast_ip(AF_INET6, AF_INET6);
@@ -227,9 +234,6 @@ int send_LANdiscovery(uint16_t port, Net_Crypto *c)
227 234
228 /* IPv4 broadcast (has to be IPv4-in-IPv6 mapping if socket is AF_INET6 */ 235 /* IPv4 broadcast (has to be IPv4-in-IPv6 mapping if socket is AF_INET6 */
229 ip_port.ip = broadcast_ip(c->lossless_udp->net->family, AF_INET); 236 ip_port.ip = broadcast_ip(c->lossless_udp->net->family, AF_INET);
230#else
231 ip_port.ip = broadcast_ip(AF_INET, AF_INET);
232#endif
233 237
234 if (ip_isset(&ip_port.ip)) 238 if (ip_isset(&ip_port.ip))
235 if (sendpacket(c->lossless_udp->net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES)) 239 if (sendpacket(c->lossless_udp->net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES))
diff --git a/toxcore/Lossless_UDP.c b/toxcore/Lossless_UDP.c
index 02fc7251..6d82b768 100644
--- a/toxcore/Lossless_UDP.c
+++ b/toxcore/Lossless_UDP.c
@@ -119,24 +119,15 @@ static uint32_t handshake_id(Lossless_UDP *ludp, IP_Port source)
119 id ^= randtable_initget(ludp, i, *uint8); 119 id ^= randtable_initget(ludp, i, *uint8);
120 i++; 120 i++;
121 121
122#ifdef TOX_ENABLE_IPV6
123
124 if (source.ip.family == AF_INET) { 122 if (source.ip.family == AF_INET) {
125 IP4 ip4 = source.ip.ip4;
126#else
127 IP4 ip4 = source.ip;
128#endif
129 int k; 123 int k;
130 124
131 for (k = 0; k < 4; k++) { 125 for (k = 0; k < 4; k++) {
132 id ^= randtable_initget(ludp, i++, ip4.uint8[k]); 126 id ^= randtable_initget(ludp, i++, source.ip.ip4.uint8[k]);
133 } 127 }
134
135#ifdef TOX_ENABLE_IPV6
136 } 128 }
137 129
138 if (source.ip.family == AF_INET6) 130 if (source.ip.family == AF_INET6) {
139 {
140 int k; 131 int k;
141 132
142 for (k = 0; k < 16; k++) { 133 for (k = 0; k < 16; k++) {
@@ -144,8 +135,6 @@ static uint32_t handshake_id(Lossless_UDP *ludp, IP_Port source)
144 } 135 }
145 } 136 }
146 137
147#endif
148
149 /* id can't be zero. */ 138 /* id can't be zero. */
150 if (id == 0) 139 if (id == 0)
151 id = 1; 140 id = 1;
@@ -160,21 +149,18 @@ static uint32_t handshake_id(Lossless_UDP *ludp, IP_Port source)
160 */ 149 */
161static void change_handshake(Lossless_UDP *ludp, IP_Port source) 150static void change_handshake(Lossless_UDP *ludp, IP_Port source)
162{ 151{
163#ifdef TOX_ENABLE_IPV6
164 uint8_t rand; 152 uint8_t rand;
165 153
166 if (source.ip.family == AF_INET) { 154 if (source.ip.family == AF_INET) {
167 rand = 2 + random_int() % 4; 155 rand = random_int() % 4;
168 } else if (source.ip.family == AF_INET6) { 156 } else if (source.ip.family == AF_INET6) {
169 rand = 2 + random_int() % 16; 157 rand = random_int() % 16;
170 } else { 158 } else {
171 return; 159 return;
172 } 160 }
173 161
174#else 162 /* Forced to be more robust against strange definitions of sa_family_t */
175 uint8_t rand = 2 + random_int() % 4; 163 ludp->randtable[2 + rand][((uint8_t *)&source.ip.ip6)[rand]] = random_int();
176#endif
177 ludp->randtable[rand][((uint8_t *)&source.ip)[rand]] = random_int();
178} 164}
179 165
180/* 166/*
@@ -467,8 +453,8 @@ uint32_t sendqueue(Lossless_UDP *ludp, int connection_id)
467/* return number of packets in all queues waiting to be successfully sent. */ 453/* return number of packets in all queues waiting to be successfully sent. */
468uint32_t sendqueue_total(Lossless_UDP *ludp) 454uint32_t sendqueue_total(Lossless_UDP *ludp)
469{ 455{
470 uint32_t total = 0; 456 uint32_t i, total = 0;
471 int i; 457
472 for(i = 0; i < ludp->connections.len; i++) { 458 for(i = 0; i < ludp->connections.len; i++) {
473 Connection *connection = &tox_array_get(&ludp->connections, i, Connection); 459 Connection *connection = &tox_array_get(&ludp->connections, i, Connection);
474 if (connection->status != 0) 460 if (connection->status != 0)
diff --git a/toxcore/Lossless_UDP.h b/toxcore/Lossless_UDP.h
index 794381de..d2f1986f 100644
--- a/toxcore/Lossless_UDP.h
+++ b/toxcore/Lossless_UDP.h
@@ -134,14 +134,8 @@ typedef struct {
134 tox_array connections; 134 tox_array connections;
135 135
136 /* Table of random numbers used in handshake_id. */ 136 /* Table of random numbers used in handshake_id. */
137#ifdef TOX_ENABLE_IPV6
138 /* IPv6 (16) + port (2)*/ 137 /* IPv6 (16) + port (2)*/
139 uint32_t randtable[18][256]; 138 uint32_t randtable[18][256];
140#else
141 /* IPv4 (4) + port (2) */
142 uint32_t randtable[6][256];
143#endif
144
145} Lossless_UDP; 139} Lossless_UDP;
146 140
147/* 141/*
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index 76f2a5fd..2e8efeac 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -1759,7 +1759,7 @@ static char *ID2String(uint8_t *client_id)
1759 uint32_t i; 1759 uint32_t i;
1760 1760
1761 for (i = 0; i < CLIENT_ID_SIZE; i++) 1761 for (i = 0; i < CLIENT_ID_SIZE; i++)
1762 sprintf(&IDString[i], "%02X", client_id[i]); 1762 sprintf(&IDString[i * 2], "%02X", client_id[i]);
1763 1763
1764 IDString[CLIENT_ID_SIZE * 2] = 0; 1764 IDString[CLIENT_ID_SIZE * 2] = 0;
1765 return IDString; 1765 return IDString;
@@ -1789,24 +1789,20 @@ void doMessenger(Messenger *m)
1789 for (client = 0; client < LCLIENT_LIST; client++) { 1789 for (client = 0; client < LCLIENT_LIST; client++) {
1790 Client_data *cptr = &m->dht->close_clientlist[client]; 1790 Client_data *cptr = &m->dht->close_clientlist[client];
1791 IPPTsPng *assoc = NULL; 1791 IPPTsPng *assoc = NULL;
1792#ifdef CLIENT_ONETOONE_IP
1793 assoc = &cptr->assoc;
1794#else
1795 uint32_t a; 1792 uint32_t a;
1796 1793
1797 for (a = 0, assoc = &cptr->assoc4; a < 2; a++, assoc = &cptr->assoc6) 1794 for (a = 0, assoc = &cptr->assoc4; a < 2; a++, assoc = &cptr->assoc6)
1798#endif 1795 if (ip_isset(&assoc->ip_port.ip)) {
1799 if (ip_isset(&assoc->ip_port.ip)) { 1796 last_pinged = lastdump - assoc->last_pinged;
1800 last_pinged = lastdump - assoc->last_pinged;
1801 1797
1802 if (last_pinged > 999) 1798 if (last_pinged > 999)
1803 last_pinged = 999; 1799 last_pinged = 999;
1804 1800
1805 snprintf(logbuffer, sizeof(logbuffer), "C[%2u] %s:%u [%3u] %s\n", 1801 snprintf(logbuffer, sizeof(logbuffer), "C[%2u] %s:%u [%3u] %s\n",
1806 client, ip_ntoa(&assoc->ip_port.ip), ntohs(assoc->ip_port.port), 1802 client, ip_ntoa(&assoc->ip_port.ip), ntohs(assoc->ip_port.port),
1807 last_pinged, ID2String(cptr->client_id)); 1803 last_pinged, ID2String(cptr->client_id));
1808 loglog(logbuffer); 1804 loglog(logbuffer);
1809 } 1805 }
1810 } 1806 }
1811 1807
1812 loglog(" = = = = = = = = \n"); 1808 loglog(" = = = = = = = = \n");
@@ -1850,25 +1846,21 @@ void doMessenger(Messenger *m)
1850 for (client = 0; client < MAX_FRIEND_CLIENTS; client++) { 1846 for (client = 0; client < MAX_FRIEND_CLIENTS; client++) {
1851 Client_data *cptr = &dhtfptr->client_list[client]; 1847 Client_data *cptr = &dhtfptr->client_list[client];
1852 IPPTsPng *assoc = NULL; 1848 IPPTsPng *assoc = NULL;
1853#ifdef CLIENT_ONETOONE_IP
1854 assoc = &cptr->assoc;
1855#else
1856 uint32_t a; 1849 uint32_t a;
1857 1850
1858 for (a = 0, assoc = &cptr->assoc4; a < 2; a++, assoc = &cptr->assoc6) 1851 for (a = 0, assoc = &cptr->assoc4; a < 2; a++, assoc = &cptr->assoc6)
1859#endif 1852 if (ip_isset(&assoc->ip_port.ip)) {
1860 if (ip_isset(&assoc->ip_port.ip)) { 1853 last_pinged = lastdump - assoc->last_pinged;
1861 last_pinged = lastdump - assoc->last_pinged;
1862 1854
1863 if (last_pinged > 999) 1855 if (last_pinged > 999)
1864 last_pinged = 999; 1856 last_pinged = 999;
1865 1857
1866 snprintf(logbuffer, sizeof(logbuffer), "F[%2u] => C[%2u] %s:%u [%3u] %s\n", 1858 snprintf(logbuffer, sizeof(logbuffer), "F[%2u] => C[%2u] %s:%u [%3u] %s\n",
1867 friend, client, ip_ntoa(&assoc->ip_port.ip), 1859 friend, client, ip_ntoa(&assoc->ip_port.ip),
1868 ntohs(assoc->ip_port.port), last_pinged, 1860 ntohs(assoc->ip_port.port), last_pinged,
1869 ID2String(cptr->client_id)); 1861 ID2String(cptr->client_id));
1870 loglog(logbuffer); 1862 loglog(logbuffer);
1871 } 1863 }
1872 } 1864 }
1873 } 1865 }
1874 1866
diff --git a/toxcore/network.c b/toxcore/network.c
index ff0cdf29..53511df6 100644
--- a/toxcore/network.c
+++ b/toxcore/network.c
@@ -45,7 +45,9 @@
45static const char *inet_ntop(sa_family_t family, void *addr, char *buf, size_t bufsize) 45static const char *inet_ntop(sa_family_t family, void *addr, char *buf, size_t bufsize)
46{ 46{
47 if (family == AF_INET) { 47 if (family == AF_INET) {
48 struct sockaddr_in saddr = { 0 }; 48 struct sockaddr_in saddr;
49 memset(&saddr, 0, sizeof(saddr));
50
49 saddr.sin_family = AF_INET; 51 saddr.sin_family = AF_INET;
50 saddr.sin_addr = *(struct in_addr *)addr; 52 saddr.sin_addr = *(struct in_addr *)addr;
51 53
@@ -56,7 +58,9 @@ static const char *inet_ntop(sa_family_t family, void *addr, char *buf, size_t b
56 58
57 return buf; 59 return buf;
58 } else if (family == AF_INET6) { 60 } else if (family == AF_INET6) {
59 struct sockaddr_in6 saddr = { 0 }; 61 struct sockaddr_in6 saddr;
62 memset(&saddr, 0, sizeof(saddr));
63
60 saddr.sin6_family = AF_INET6; 64 saddr.sin6_family = AF_INET6;
61 saddr.sin6_addr = *(struct in6_addr *)addr; 65 saddr.sin6_addr = *(struct in6_addr *)addr;
62 66
@@ -74,7 +78,8 @@ static const char *inet_ntop(sa_family_t family, void *addr, char *buf, size_t b
74static int inet_pton(sa_family_t family, const char *addrString, void *addrbuf) 78static int inet_pton(sa_family_t family, const char *addrString, void *addrbuf)
75{ 79{
76 if (family == AF_INET) { 80 if (family == AF_INET) {
77 struct sockaddr_in saddr = { 0 }; 81 struct sockaddr_in saddr;
82 memset(&saddr, 0, sizeof(saddr));
78 83
79 INT len = sizeof(saddr); 84 INT len = sizeof(saddr);
80 85
@@ -85,7 +90,8 @@ static int inet_pton(sa_family_t family, const char *addrString, void *addrbuf)
85 90
86 return 1; 91 return 1;
87 } else if (family == AF_INET6) { 92 } else if (family == AF_INET6) {
88 struct sockaddr_in6 saddr = { 0 }; 93 struct sockaddr_in6 saddr;
94 memset(&saddr, 0, sizeof(saddr));
89 95
90 INT len = sizeof(saddr); 96 INT len = sizeof(saddr);
91 97
@@ -146,24 +152,19 @@ static void loglogdata(char *message, uint8_t *buffer, size_t buflen, IP_Port *i
146 */ 152 */
147int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t length) 153int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t length)
148{ 154{
149#ifdef TOX_ENABLE_IPV6
150
151 /* socket AF_INET, but target IP NOT: can't send */ 155 /* socket AF_INET, but target IP NOT: can't send */
152 if ((net->family == AF_INET) && (ip_port.ip.family != AF_INET)) 156 if ((net->family == AF_INET) && (ip_port.ip.family != AF_INET))
153 return -1; 157 return -1;
154 158
155#endif
156
157 struct sockaddr_storage addr; 159 struct sockaddr_storage addr;
158 size_t addrsize = 0; 160 size_t addrsize = 0;
159 161
160#ifdef TOX_ENABLE_IPV6
161
162 if (ip_port.ip.family == AF_INET) { 162 if (ip_port.ip.family == AF_INET) {
163 if (net->family == AF_INET6) { 163 if (net->family == AF_INET6) {
164 /* must convert to IPV4-in-IPV6 address */ 164 /* must convert to IPV4-in-IPV6 address */
165 addrsize = sizeof(struct sockaddr_in6);
166 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr; 165 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
166
167 addrsize = sizeof(struct sockaddr_in6);
167 addr6->sin6_family = AF_INET6; 168 addr6->sin6_family = AF_INET6;
168 addr6->sin6_port = ip_port.port; 169 addr6->sin6_port = ip_port.port;
169 170
@@ -180,48 +181,36 @@ int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t le
180 addr6->sin6_flowinfo = 0; 181 addr6->sin6_flowinfo = 0;
181 addr6->sin6_scope_id = 0; 182 addr6->sin6_scope_id = 0;
182 } else { 183 } else {
183 IP4 ip4 = ip_port.ip.ip4;
184#else
185 IP4 ip4 = ip_port.ip;
186#endif
187 addrsize = sizeof(struct sockaddr_in);
188 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr; 184 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
185
186 addrsize = sizeof(struct sockaddr_in);
189 addr4->sin_family = AF_INET; 187 addr4->sin_family = AF_INET;
190 addr4->sin_addr = ip4.in_addr; 188 addr4->sin_addr = ip_port.ip.ip4.in_addr;
191 addr4->sin_port = ip_port.port; 189 addr4->sin_port = ip_port.port;
192#ifdef TOX_ENABLE_IPV6
193 } 190 }
194 } else if (ip_port.ip.family == AF_INET6) 191 } else if (ip_port.ip.family == AF_INET6) {
195 {
196 addrsize = sizeof(struct sockaddr_in6);
197 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr; 192 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
193
194 addrsize = sizeof(struct sockaddr_in6);
198 addr6->sin6_family = AF_INET6; 195 addr6->sin6_family = AF_INET6;
199 addr6->sin6_port = ip_port.port; 196 addr6->sin6_port = ip_port.port;
200 addr6->sin6_addr = ip_port.ip.ip6.in6_addr; 197 addr6->sin6_addr = ip_port.ip.ip6.in6_addr;
201 198
202 addr6->sin6_flowinfo = 0; 199 addr6->sin6_flowinfo = 0;
203 addr6->sin6_scope_id = 0; 200 addr6->sin6_scope_id = 0;
204 } else 201 } else {
205 {
206 /* unknown address type*/ 202 /* unknown address type*/
207 return -1; 203 return -1;
208 } 204 }
209 205
210#endif
211
212 int res = sendto(net->sock, (char *) data, length, 0, (struct sockaddr *)&addr, addrsize); 206 int res = sendto(net->sock, (char *) data, length, 0, (struct sockaddr *)&addr, addrsize);
213#ifdef LOGGING 207#ifdef LOGGING
214 loglogdata("O=>", data, length, &ip_port, res); 208 loglogdata("O=>", data, length, &ip_port, res);
215#endif 209#endif
216 210
217 if (res == length) 211 if ((res >= 0) && ((uint32_t)res == length))
218 net->send_fail_eagain = 0; 212 net->send_fail_eagain = 0;
219 213 else if ((res < 0) && (errno == EWOULDBLOCK))
220#ifdef WIN32
221 else if ((res < 0) && (errno == WSAEWOULDBLOCK))
222#else
223 else if ((res < 0) && (errno == EAGAIN))
224#endif
225 net->send_fail_eagain = current_time(); 214 net->send_fail_eagain = current_time();
226 215
227 return res; 216 return res;
@@ -258,32 +247,21 @@ static int receivepacket(sock_t sock, IP_Port *ip_port, uint8_t *data, uint32_t
258 247
259 *length = (uint32_t)fail_or_len; 248 *length = (uint32_t)fail_or_len;
260 249
261#ifdef TOX_ENABLE_IPV6
262
263 if (addr.ss_family == AF_INET) { 250 if (addr.ss_family == AF_INET) {
264 struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr; 251 struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr;
252
265 ip_port->ip.family = addr_in->sin_family; 253 ip_port->ip.family = addr_in->sin_family;
266 ip_port->ip.ip4.in_addr = addr_in->sin_addr; 254 ip_port->ip.ip4.in_addr = addr_in->sin_addr;
267 ip_port->port = addr_in->sin_port; 255 ip_port->port = addr_in->sin_port;
268 } else if (addr.ss_family == AF_INET6) { 256 } else if (addr.ss_family == AF_INET6) {
269 struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)&addr; 257 struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)&addr;
258
270 ip_port->ip.family = addr_in6->sin6_family; 259 ip_port->ip.family = addr_in6->sin6_family;
271 ip_port->ip.ip6.in6_addr = addr_in6->sin6_addr; 260 ip_port->ip.ip6.in6_addr = addr_in6->sin6_addr;
272 ip_port->port = addr_in6->sin6_port; 261 ip_port->port = addr_in6->sin6_port;
273 } else 262 } else
274 return -1; 263 return -1;
275 264
276#else
277
278 if (addr.ss_family == AF_INET) {
279 struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr;
280 ip_port->ip.in_addr = addr_in->sin_addr;
281 ip_port->port = addr_in->sin_port;
282 } else
283 return -1;
284
285#endif
286
287#ifdef LOGGING 265#ifdef LOGGING
288 loglogdata("=>O", data, MAX_UDP_PACKET_SIZE, ip_port, *length); 266 loglogdata("=>O", data, MAX_UDP_PACKET_SIZE, ip_port, *length);
289#endif 267#endif
@@ -393,10 +371,13 @@ int networking_wait_execute(uint8_t *data, uint16_t len, uint16_t milliseconds)
393 /* returns -1 on error, 0 on timeout, the socket on activity */ 371 /* returns -1 on error, 0 on timeout, the socket on activity */
394 int res = select(nfds, &readfds, &writefds, &exceptfds, &timeout); 372 int res = select(nfds, &readfds, &writefds, &exceptfds, &timeout);
395#ifdef LOGGING 373#ifdef LOGGING
396 sprintf(logbuffer, "select(%d): %d (%d, %s) - %d %d %d\n", milliseconds, res, errno, 374 /* only dump if not timeout */
397 strerror(errno), FD_ISSET(s->sock, &readfds), FD_ISSET(s->sock, &writefds), 375 if (res) {
398 FD_ISSET(s->sock, &exceptfds)); 376 sprintf(logbuffer, "select(%d): %d (%d, %s) - %d %d %d\n", milliseconds, res, errno,
399 loglog(logbuffer); 377 strerror(errno), FD_ISSET(s->sock, &readfds), FD_ISSET(s->sock, &writefds),
378 FD_ISSET(s->sock, &exceptfds));
379 loglog(logbuffer);
380 }
400#endif 381#endif
401 382
402 if (FD_ISSET(s->sock, &writefds)) 383 if (FD_ISSET(s->sock, &writefds))
@@ -452,8 +433,6 @@ static void at_shutdown(void)
452 */ 433 */
453Networking_Core *new_networking(IP ip, uint16_t port) 434Networking_Core *new_networking(IP ip, uint16_t port)
454{ 435{
455#ifdef TOX_ENABLE_IPV6
456
457 /* maybe check for invalid IPs like 224+.x.y.z? if there is any IP set ever */ 436 /* maybe check for invalid IPs like 224+.x.y.z? if there is any IP set ever */
458 if (ip.family != AF_INET && ip.family != AF_INET6) { 437 if (ip.family != AF_INET && ip.family != AF_INET6) {
459#ifdef DEBUG 438#ifdef DEBUG
@@ -462,8 +441,6 @@ Networking_Core *new_networking(IP ip, uint16_t port)
462 return NULL; 441 return NULL;
463 } 442 }
464 443
465#endif
466
467 if (at_startup() != 0) 444 if (at_startup() != 0)
468 return NULL; 445 return NULL;
469 446
@@ -472,11 +449,7 @@ Networking_Core *new_networking(IP ip, uint16_t port)
472 if (temp == NULL) 449 if (temp == NULL)
473 return NULL; 450 return NULL;
474 451
475#ifdef TOX_ENABLE_IPV6
476 temp->family = ip.family; 452 temp->family = ip.family;
477#else
478 temp->family = AF_INET;
479#endif
480 temp->port = 0; 453 temp->port = 0;
481 454
482 /* Initialize our socket. */ 455 /* Initialize our socket. */
@@ -491,7 +464,7 @@ Networking_Core *new_networking(IP ip, uint16_t port)
491 return NULL; 464 return NULL;
492 } 465 }
493 466
494#else 467#else /* !WIN32 */
495 468
496 if (temp->sock < 0) { 469 if (temp->sock < 0) {
497#ifdef DEBUG 470#ifdef DEBUG
@@ -501,7 +474,7 @@ Networking_Core *new_networking(IP ip, uint16_t port)
501 return NULL; 474 return NULL;
502 } 475 }
503 476
504#endif 477#endif /* !WIN32 */
505 478
506 /* Functions to increase the size of the send and receive UDP buffers. 479 /* Functions to increase the size of the send and receive UDP buffers.
507 */ 480 */
@@ -519,33 +492,28 @@ Networking_Core *new_networking(IP ip, uint16_t port)
519 u_long mode = 1; 492 u_long mode = 1;
520 /* ioctl(sock, FIONBIO, &mode); */ 493 /* ioctl(sock, FIONBIO, &mode); */
521 ioctlsocket(temp->sock, FIONBIO, &mode); 494 ioctlsocket(temp->sock, FIONBIO, &mode);
522#else 495#else /* !WIN32 */
523 fcntl(temp->sock, F_SETFL, O_NONBLOCK, 1); 496 fcntl(temp->sock, F_SETFL, O_NONBLOCK, 1);
524#endif 497#endif /* !WIN32 */
525 498
526 /* Bind our socket to port PORT and the given IP address (usually 0.0.0.0 or ::) */ 499 /* Bind our socket to port PORT and the given IP address (usually 0.0.0.0 or ::) */
527 uint16_t *portptr = NULL; 500 uint16_t *portptr = NULL;
528 struct sockaddr_storage addr; 501 struct sockaddr_storage addr;
529 size_t addrsize; 502 size_t addrsize;
530#ifdef TOX_ENABLE_IPV6
531 503
532 if (temp->family == AF_INET) { 504 if (temp->family == AF_INET) {
533 IP4 ip4 = ip.ip4;
534#else
535 IP4 ip4 = ip;
536#endif
537 addrsize = sizeof(struct sockaddr_in);
538 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr; 505 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
506
507 addrsize = sizeof(struct sockaddr_in);
539 addr4->sin_family = AF_INET; 508 addr4->sin_family = AF_INET;
540 addr4->sin_port = 0; 509 addr4->sin_port = 0;
541 addr4->sin_addr = ip4.in_addr; 510 addr4->sin_addr = ip.ip4.in_addr;
542 511
543 portptr = &addr4->sin_port; 512 portptr = &addr4->sin_port;
544#ifdef TOX_ENABLE_IPV6 513 } else if (temp->family == AF_INET6) {
545 } else if (temp->family == AF_INET6)
546 {
547 addrsize = sizeof(struct sockaddr_in6);
548 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr; 514 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
515
516 addrsize = sizeof(struct sockaddr_in6);
549 addr6->sin6_family = AF_INET6; 517 addr6->sin6_family = AF_INET6;
550 addr6->sin6_port = 0; 518 addr6->sin6_port = 0;
551 addr6->sin6_addr = ip.ip6.in6_addr; 519 addr6->sin6_addr = ip.ip6.in6_addr;
@@ -560,22 +528,38 @@ Networking_Core *new_networking(IP ip, uint16_t port)
560 if (ip.family == AF_INET6) 528 if (ip.family == AF_INET6)
561 { 529 {
562 char ipv6only = 0; 530 char ipv6only = 0;
531 socklen_t optsize = sizeof(ipv6only);
563#ifdef LOGGING 532#ifdef LOGGING
564 errno = 0; 533 errno = 0;
565 int res =
566#endif 534#endif
567 setsockopt(temp->sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, sizeof(ipv6only)); 535 int res = getsockopt(temp->sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, &optsize);
536 if ((res == 0) && (ipv6only == 0)) {
568#ifdef LOGGING 537#ifdef LOGGING
538 loglog("Dual-stack socket: enabled per default.\n");
539#endif
540 } else {
541 ipv6only = 0;
542#ifdef LOGGING
543 if (res < 0) {
544 sprintf(logbuffer, "Dual-stack socket: Failed to query default. (%d, %s)\n",
545 errno, strerror(errno));
546 loglog(logbuffer);
547 }
569 548
570 if (res < 0) { 549 errno = 0;
571 sprintf(logbuffer, 550 res =
572 "Failed to enable dual-stack on IPv6 socket, won't be able to receive from/send to IPv4 addresses. (%u, %s)\n", 551#endif
573 errno, strerror(errno)); 552 setsockopt(temp->sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, sizeof(ipv6only));
574 loglog(logbuffer); 553#ifdef LOGGING
575 } else 554 if (res < 0) {
576 loglog("Embedded IPv4 addresses enabled successfully.\n"); 555 sprintf(logbuffer,
577 556 "Dual-stack socket: Failed to enable, won't be able to receive from/send to IPv4 addresses. (%u, %s)\n",
557 errno, strerror(errno));
558 loglog(logbuffer);
559 } else
560 loglog("Dual-stack socket: Enabled successfully.\n");
578#endif 561#endif
562 }
579 563
580 /* multicast local nodes */ 564 /* multicast local nodes */
581 struct ipv6_mreq mreq; 565 struct ipv6_mreq mreq;
@@ -601,8 +585,6 @@ Networking_Core *new_networking(IP ip, uint16_t port)
601#endif 585#endif
602 } 586 }
603 587
604#endif
605
606 /* a hanging program or a different user might block the standard port; 588 /* a hanging program or a different user might block the standard port;
607 * as long as it isn't a parameter coming from the commandline, 589 * as long as it isn't a parameter coming from the commandline,
608 * try a few ports after it, to see if we can find a "free" one 590 * try a few ports after it, to see if we can find a "free" one
@@ -685,14 +667,16 @@ int ip_equal(IP *a, IP *b)
685 if (!a || !b) 667 if (!a || !b)
686 return 0; 668 return 0;
687 669
688#ifdef TOX_ENABLE_IPV6
689
690 /* same family */ 670 /* same family */
691 if (a->family == b->family) { 671 if (a->family == b->family) {
692 if (a->family == AF_INET) 672 if (a->family == AF_INET)
693 return (a->ip4.in_addr.s_addr == b->ip4.in_addr.s_addr); 673 return (a->ip4.in_addr.s_addr == b->ip4.in_addr.s_addr);
694 else if (a->family == AF_INET6) 674 else if (a->family == AF_INET6)
675#ifdef WIN32
676 return IN6_ADDR_EQUAL(&a->ip6.in6_addr, &b->ip6.in6_addr);
677#else
695 return IN6_ARE_ADDR_EQUAL(&a->ip6.in6_addr, &b->ip6.in6_addr); 678 return IN6_ARE_ADDR_EQUAL(&a->ip6.in6_addr, &b->ip6.in6_addr);
679#endif
696 else 680 else
697 return 0; 681 return 0;
698 } 682 }
@@ -707,9 +691,6 @@ int ip_equal(IP *a, IP *b)
707 } 691 }
708 692
709 return 0; 693 return 0;
710#else
711 return (a->uint32 == b->uint32);
712#endif
713}; 694};
714 695
715/* ipport_equal 696/* ipport_equal
@@ -735,11 +716,7 @@ void ip_reset(IP *ip)
735 if (!ip) 716 if (!ip)
736 return; 717 return;
737 718
738#ifdef TOX_ENABLE_IPV6
739 memset(ip, 0, sizeof(IP)); 719 memset(ip, 0, sizeof(IP));
740#else
741 ip->uint32 = 0;
742#endif
743}; 720};
744 721
745/* nulls out ip, sets family according to flag */ 722/* nulls out ip, sets family according to flag */
@@ -748,12 +725,8 @@ void ip_init(IP *ip, uint8_t ipv6enabled)
748 if (!ip) 725 if (!ip)
749 return; 726 return;
750 727
751#ifdef TOX_ENABLE_IPV6
752 memset(ip, 0, sizeof(IP)); 728 memset(ip, 0, sizeof(IP));
753 ip->family = ipv6enabled ? AF_INET6 : AF_INET; 729 ip->family = ipv6enabled ? AF_INET6 : AF_INET;
754#else
755 ip->uint32 = 0;
756#endif
757}; 730};
758 731
759/* checks if ip is valid */ 732/* checks if ip is valid */
@@ -762,11 +735,7 @@ int ip_isset(IP *ip)
762 if (!ip) 735 if (!ip)
763 return 0; 736 return 0;
764 737
765#ifdef TOX_ENABLE_IPV6
766 return (ip->family != 0); 738 return (ip->family != 0);
767#else
768 return (ip->uint32 != 0);
769#endif
770}; 739};
771 740
772/* checks if ip is valid */ 741/* checks if ip is valid */
@@ -808,27 +777,23 @@ static char addresstext[96];
808const char *ip_ntoa(IP *ip) 777const char *ip_ntoa(IP *ip)
809{ 778{
810 if (ip) { 779 if (ip) {
811#ifdef TOX_ENABLE_IPV6
812
813 if (ip->family == AF_INET) { 780 if (ip->family == AF_INET) {
814 addresstext[0] = 0; 781 /* returns standard quad-dotted notation */
815 struct in_addr *addr = (struct in_addr *)&ip->ip4; 782 struct in_addr *addr = (struct in_addr *)&ip->ip4;
783
784 addresstext[0] = 0;
816 inet_ntop(ip->family, addr, addresstext, sizeof(addresstext)); 785 inet_ntop(ip->family, addr, addresstext, sizeof(addresstext));
817 } else if (ip->family == AF_INET6) { 786 } else if (ip->family == AF_INET6) {
818 addresstext[0] = '['; 787 /* returns hex-groups enclosed into square brackets */
819 struct in6_addr *addr = (struct in6_addr *)&ip->ip6; 788 struct in6_addr *addr = (struct in6_addr *)&ip->ip6;
789
790 addresstext[0] = '[';
820 inet_ntop(ip->family, addr, &addresstext[1], sizeof(addresstext) - 3); 791 inet_ntop(ip->family, addr, &addresstext[1], sizeof(addresstext) - 3);
821 size_t len = strlen(addresstext); 792 size_t len = strlen(addresstext);
822 addresstext[len] = ']'; 793 addresstext[len] = ']';
823 addresstext[len + 1] = 0; 794 addresstext[len + 1] = 0;
824 } else 795 } else
825 snprintf(addresstext, sizeof(addresstext), "(IP invalid, family %u)", ip->family); 796 snprintf(addresstext, sizeof(addresstext), "(IP invalid, family %u)", ip->family);
826
827#else
828 addresstext[0] = 0;
829 struct in_addr *addr = (struct in_addr *)&ip;
830 inet_ntop(AF_INET, addr, addresstext, sizeof(addresstext));
831#endif
832 } else 797 } else
833 snprintf(addresstext, sizeof(addresstext), "(IP invalid: NULL)"); 798 snprintf(addresstext, sizeof(addresstext), "(IP invalid: NULL)");
834 799
@@ -856,7 +821,6 @@ int addr_parse_ip(const char *address, IP *to)
856 if (!address || !to) 821 if (!address || !to)
857 return 0; 822 return 0;
858 823
859#ifdef TOX_ENABLE_IPV6
860 struct in_addr addr4; 824 struct in_addr addr4;
861 825
862 if (1 == inet_pton(AF_INET, address, &addr4)) { 826 if (1 == inet_pton(AF_INET, address, &addr4)) {
@@ -873,16 +837,6 @@ int addr_parse_ip(const char *address, IP *to)
873 return 1; 837 return 1;
874 }; 838 };
875 839
876#else
877 struct in_addr addr4;
878
879 if (1 == inet_pton(AF_INET, address, &addr4)) {
880 to->in_addr = addr4;
881 return 1;
882 };
883
884#endif
885
886 return 0; 840 return 0;
887}; 841};
888 842
@@ -909,12 +863,7 @@ int addr_resolve(const char *address, IP *to, IP *extra)
909 if (!address || !to) 863 if (!address || !to)
910 return 0; 864 return 0;
911 865
912 sa_family_t family; 866 sa_family_t family = to->family;
913#ifdef TOX_ENABLE_IPV6
914 family = to->family;
915#else
916 family = AF_INET;
917#endif
918 867
919 struct addrinfo *server = NULL; 868 struct addrinfo *server = NULL;
920 struct addrinfo *walker = NULL; 869 struct addrinfo *walker = NULL;
@@ -935,36 +884,25 @@ int addr_resolve(const char *address, IP *to, IP *extra)
935 return 0; 884 return 0;
936 } 885 }
937 886
938#ifdef TOX_ENABLE_IPV6
939 IP4 ip4; 887 IP4 ip4;
940 memset(&ip4, 0, sizeof(ip4)); 888 memset(&ip4, 0, sizeof(ip4));
941 IP6 ip6; 889 IP6 ip6;
942 memset(&ip6, 0, sizeof(ip6)); 890 memset(&ip6, 0, sizeof(ip6));
943#endif
944 891
945 for (walker = server; (walker != NULL) && (rc != 3); walker = walker->ai_next) { 892 for (walker = server; (walker != NULL) && (rc != 3); walker = walker->ai_next) {
946 switch (walker->ai_family) { 893 switch (walker->ai_family) {
947 case AF_INET: 894 case AF_INET:
948 if (walker->ai_family == family) { /* AF_INET requested, done */ 895 if (walker->ai_family == family) { /* AF_INET requested, done */
949 struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr; 896 struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr;
950#ifdef TOX_ENABLE_IPV6
951 to->ip4.in_addr = addr->sin_addr; 897 to->ip4.in_addr = addr->sin_addr;
952#else
953 to->in_addr = addr->sin_addr;
954#endif
955 rc = 3; 898 rc = 3;
956 } 899 } else if (!(rc & 1)) { /* AF_UNSPEC requested, store away */
957
958#ifdef TOX_ENABLE_IPV6
959 else if (!(rc & 1)) { /* AF_UNSPEC requested, store away */
960 struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr; 900 struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr;
961 ip4.in_addr = addr->sin_addr; 901 ip4.in_addr = addr->sin_addr;
962 rc |= 1; 902 rc |= 1;
963 } 903 }
964 904
965#endif
966 break; /* switch */ 905 break; /* switch */
967#ifdef TOX_ENABLE_IPV6
968 906
969 case AF_INET6: 907 case AF_INET6:
970 if (walker->ai_family == family) { /* AF_INET6 requested, done */ 908 if (walker->ai_family == family) { /* AF_INET6 requested, done */
@@ -982,12 +920,9 @@ int addr_resolve(const char *address, IP *to, IP *extra)
982 } 920 }
983 921
984 break; /* switch */ 922 break; /* switch */
985#endif
986 } 923 }
987 } 924 }
988 925
989#ifdef TOX_ENABLE_IPV6
990
991 if (to->family == AF_UNSPEC) { 926 if (to->family == AF_UNSPEC) {
992 if (rc & 2) { 927 if (rc & 2) {
993 to->family = AF_INET6; 928 to->family = AF_INET6;
@@ -1004,9 +939,6 @@ int addr_resolve(const char *address, IP *to, IP *extra)
1004 rc = 0; 939 rc = 0;
1005 } 940 }
1006 941
1007#endif
1008
1009
1010 freeaddrinfo(server); 942 freeaddrinfo(server);
1011 return rc; 943 return rc;
1012} 944}
@@ -1044,10 +976,11 @@ static void loglogdata(char *message, uint8_t *buffer, size_t buflen, IP_Port *i
1044 data[0] = buflen > 4 ? ntohl(*(uint32_t *)&buffer[1]) : 0; 976 data[0] = buflen > 4 ? ntohl(*(uint32_t *)&buffer[1]) : 0;
1045 data[1] = buflen > 7 ? ntohl(*(uint32_t *)&buffer[5]) : 0; 977 data[1] = buflen > 7 ? ntohl(*(uint32_t *)&buffer[5]) : 0;
1046 978
979 /* Windows doesn't necessarily know %zu */
1047 if (res < 0) { 980 if (res < 0) {
1048 int written = snprintf(logbuffer, sizeof(logbuffer), "[%2u] %s %3hu%c %s:%hu (%u: %s) | %04x%04x\n", 981 snprintf(logbuffer, sizeof(logbuffer), "[%2u] %s %3hu%c %s:%hu (%u: %s) | %04x%04x\n",
1049 buffer[0], message, (buflen < 999 ? (uint16_t)buflen : 999), 'E', 982 buffer[0], message, (buflen < 999 ? (uint16_t)buflen : 999), 'E',
1050 ip_ntoa(&ip_port->ip), port, errno, strerror(errno), data[0], data[1]); 983 ip_ntoa(&ip_port->ip), port, errno, strerror(errno), data[0], data[1]);
1051 } else if ((res > 0) && ((size_t)res <= buflen)) 984 } else if ((res > 0) && ((size_t)res <= buflen))
1052 snprintf(logbuffer, sizeof(logbuffer), "[%2u] %s %3zu%c %s:%hu (%u: %s) | %04x%04x\n", 985 snprintf(logbuffer, sizeof(logbuffer), "[%2u] %s %3zu%c %s:%hu (%u: %s) | %04x%04x\n",
1053 buffer[0], message, (res < 999 ? (size_t)res : 999), ((size_t)res < buflen ? '<' : '='), 986 buffer[0], message, (res < 999 ? (size_t)res : 999), ((size_t)res < buflen ? '<' : '='),
diff --git a/toxcore/network.h b/toxcore/network.h
index 8a0e20dc..1253c07e 100644
--- a/toxcore/network.h
+++ b/toxcore/network.h
@@ -40,14 +40,11 @@
40#include <ws2tcpip.h> 40#include <ws2tcpip.h>
41 41
42typedef unsigned int sock_t; 42typedef unsigned int sock_t;
43typedef INT sa_family_t; 43/* sa_family_t is the sockaddr_in / sockaddr_in6 family field */
44 44typedef short sa_family_t;
45#ifndef IN6_ARE_ADDR_EQUAL 45
46#define IN6_ARE_ADDR_EQUAL(a,b) \ 46#ifndef EWOULDBLOCK
47 ((((__const uint32_t *) (a))[0] == ((__const uint32_t *) (b))[0]) \ 47#define EWOULDBLOCK WSAEWOULDBLOCK
48 && (((__const uint32_t *) (a))[1] == ((__const uint32_t *) (b))[1]) \
49 && (((__const uint32_t *) (a))[2] == ((__const uint32_t *) (b))[2]) \
50 && (((__const uint32_t *) (a))[3] == ((__const uint32_t *) (b))[3]))
51#endif 48#endif
52 49
53#else // Linux includes 50#else // Linux includes
@@ -103,7 +100,6 @@ typedef int sock_t;
103/* Current time, unix format */ 100/* Current time, unix format */
104#define unix_time() ((uint64_t)time(NULL)) 101#define unix_time() ((uint64_t)time(NULL))
105 102
106
107typedef union { 103typedef union {
108 uint8_t uint8[4]; 104 uint8_t uint8[4];
109 uint16_t uint16[2]; 105 uint16_t uint16[2];
@@ -124,7 +120,7 @@ typedef struct {
124 IP4 ip4; 120 IP4 ip4;
125 IP6 ip6; 121 IP6 ip6;
126 }; 122 };
127} IPAny; 123} IP;
128 124
129typedef union { 125typedef union {
130 struct { 126 struct {
@@ -136,24 +132,12 @@ typedef union {
136 uint8_t uint8[8]; 132 uint8_t uint8[8];
137} IP4_Port; 133} IP4_Port;
138 134
139/* will replace IP_Port as soon as the complete infrastructure is in place
140 * removed the unused union and padding also */
141typedef struct { 135typedef struct {
142 IPAny ip; 136 IP ip;
143 uint16_t port; 137 uint16_t port;
144} IPAny_Port; 138} IP_Port;
145 139
146/* #undef TOX_ENABLE_IPV6 */
147#define TOX_ENABLE_IPV6
148#ifdef TOX_ENABLE_IPV6
149#define TOX_ENABLE_IPV6_DEFAULT 1 140#define TOX_ENABLE_IPV6_DEFAULT 1
150typedef IPAny IP;
151typedef IPAny_Port IP_Port;
152#else
153#define TOX_ENABLE_IPV6_DEFAULT 0
154typedef IP4 IP;
155typedef IP4_Port IP_Port;
156#endif
157 141
158/* ip_ntoa 142/* ip_ntoa
159 * converts ip into a string 143 * converts ip into a string
diff --git a/toxcore/tox.h b/toxcore/tox.h
index 1f14fe46..2a26e7a6 100644
--- a/toxcore/tox.h
+++ b/toxcore/tox.h
@@ -36,7 +36,9 @@
36#include <windows.h> 36#include <windows.h>
37#include <ws2tcpip.h> 37#include <ws2tcpip.h>
38 38
39typedef INT sa_family_t; 39/* sa_family_t is the sockaddr_in / sockaddr_in6 family field */
40typedef short sa_family_t;
41
40#ifndef true 42#ifndef true
41#define true 1 43#define true 1
42#endif 44#endif
@@ -69,7 +71,6 @@ typedef union {
69 uint32_t i; 71 uint32_t i;
70} tox_IP4; 72} tox_IP4;
71 73
72
73typedef union { 74typedef union {
74 uint8_t uint8[16]; 75 uint8_t uint8[16];
75 uint16_t uint16[8]; 76 uint16_t uint16[8];
@@ -83,36 +84,16 @@ typedef struct {
83 tox_IP4 ip4; 84 tox_IP4 ip4;
84 tox_IP6 ip6; 85 tox_IP6 ip6;
85 }; 86 };
86} tox_IPAny; 87} tox_IP;
87
88typedef union {
89 struct {
90 tox_IP4 ip;
91 uint16_t port;
92 /* Not used for anything right now. */
93 uint16_t padding;
94 };
95 uint8_t uint8[8];
96} tox_IP4_Port;
97 88
98/* will replace IP_Port as soon as the complete infrastructure is in place 89/* will replace IP_Port as soon as the complete infrastructure is in place
99 * removed the unused union and padding also */ 90 * removed the unused union and padding also */
100typedef struct { 91typedef struct {
101 tox_IPAny ip; 92 tox_IP ip;
102 uint16_t port; 93 uint16_t port;
103} tox_IPAny_Port; 94} tox_IP_Port;
104 95
105/* #undef TOX_ENABLE_IPV6 */
106#define TOX_ENABLE_IPV6
107#ifdef TOX_ENABLE_IPV6
108#define TOX_ENABLE_IPV6_DEFAULT 1 96#define TOX_ENABLE_IPV6_DEFAULT 1
109typedef tox_IPAny tox_IP;
110typedef tox_IPAny_Port tox_IP_Port;
111#else
112#define TOX_ENABLE_IPV6_DEFAULT 0
113typedef tox_IP4 tox_IP;
114typedef tox_IP4_Port tox_IP_Port;
115#endif
116 97
117 98
118/* Errors for m_addfriend 99/* Errors for m_addfriend
diff --git a/toxcore/util.c b/toxcore/util.c
index 8fc6806e..a1de6392 100644
--- a/toxcore/util.c
+++ b/toxcore/util.c
@@ -109,6 +109,7 @@ void loginit(uint16_t port)
109 109
110 struct tm *tm = localtime(&starttime); 110 struct tm *tm = localtime(&starttime);
111 111
112 /* "%F %T" might not be Windows compatible */
112 if (strftime(logbuffer + 32, sizeof(logbuffer) - 32, "%F %T", tm)) 113 if (strftime(logbuffer + 32, sizeof(logbuffer) - 32, "%F %T", tm))
113 sprintf(logbuffer, "%u-%s.log", ntohs(port), logbuffer + 32); 114 sprintf(logbuffer, "%u-%s.log", ntohs(port), logbuffer + 32);
114 else 115 else
@@ -149,7 +150,7 @@ void loglog(char *text)
149 if (!logbufferpredata) 150 if (!logbufferpredata)
150 return; 151 return;
151 152
152 if (len + logbufferprehead - logbufferpredata + 16U < logbufferprelen) { 153 if (len + (logbufferprehead - logbufferpredata) + 16U < logbufferprelen) {
153 size_t logpos = logbufferprehead - logbufferpredata; 154 size_t logpos = logbufferprehead - logbufferpredata;
154 size_t lennew = logbufferprelen * 1.4; 155 size_t lennew = logbufferprelen * 1.4;
155 logbufferpredata = realloc(logbufferpredata, lennew); 156 logbufferpredata = realloc(logbufferpredata, lennew);