summaryrefslogtreecommitdiff
path: root/toxcore
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2013-09-27 21:10:34 -0400
committerirungentoo <irungentoo@gmail.com>2013-09-27 21:10:34 -0400
commit0e318af9e22bf585252ed4c2dd708b82ed27f9c9 (patch)
treeb929afc4d0dee7ef3435c9359a4ad97180c9f12b /toxcore
parentc7c72b0756e3bf4fcc3e346c34849d801be5c5fd (diff)
parentf7f670bf7c5a282d56257876394115e462a052d2 (diff)
Merge branch 'ClientData46' of https://github.com/FullName/ProjectTox-Core into FullName-ClientData46
Diffstat (limited to 'toxcore')
-rw-r--r--toxcore/DHT.c753
-rw-r--r--toxcore/DHT.h51
-rw-r--r--toxcore/LAN_discovery.c2
-rw-r--r--toxcore/LAN_discovery.h7
-rw-r--r--toxcore/Messenger.c51
-rw-r--r--toxcore/util.h2
6 files changed, 645 insertions, 221 deletions
diff --git a/toxcore/DHT.c b/toxcore/DHT.c
index db3c5883..c830b021 100644
--- a/toxcore/DHT.c
+++ b/toxcore/DHT.c
@@ -32,6 +32,7 @@
32#include "ping.h" 32#include "ping.h"
33#include "misc_tools.h" 33#include "misc_tools.h"
34#include "util.h" 34#include "util.h"
35#include "LAN_discovery.h"
35 36
36/* The number of seconds for a non responsive node to become bad. */ 37/* The number of seconds for a non responsive node to become bad. */
37#define BAD_NODE_TIMEOUT 70 38#define BAD_NODE_TIMEOUT 70
@@ -43,7 +44,7 @@
43#define PING_TIMEOUT 5 44#define PING_TIMEOUT 5
44 45
45/* The timeout after which a node is discarded completely. */ 46/* The timeout after which a node is discarded completely. */
46#define Kill_NODE_TIMEOUT 300 47#define KILL_NODE_TIMEOUT 300
47 48
48/* Ping interval in seconds for each node in our lists. */ 49/* Ping interval in seconds for each node in our lists. */
49#define PING_INTERVAL 60 50#define PING_INTERVAL 60
@@ -124,6 +125,17 @@ static int is_timeout(uint64_t time_now, uint64_t timestamp, uint64_t timeout)
124 return timestamp + timeout <= time_now; 125 return timestamp + timeout <= time_now;
125} 126}
126 127
128static int client_in_list(Client_data *list, uint32_t length, uint8_t *client_id)
129{
130 uint32_t i;
131
132 for(i = 0; i < length; i++)
133 if (id_equal(list[i].client_id, client_id))
134 return 1;
135
136 return 0;
137}
138
127/* Check if client with client_id is already in list of length length. 139/* Check if client with client_id is already in list of length length.
128 * If it is then set its corresponding timestamp to current time. 140 * If it is then set its corresponding timestamp to current time.
129 * If the id is already in the list with a different ip_port, update it. 141 * If the id is already in the list with a different ip_port, update it.
@@ -136,6 +148,7 @@ static int client_or_ip_port_in_list(Client_data *list, uint32_t length, uint8_t
136 uint32_t i; 148 uint32_t i;
137 uint64_t temp_time = unix_time(); 149 uint64_t temp_time = unix_time();
138 150
151#ifdef CLIENT_ONETOONE_IP
139 uint8_t candropipv4 = 1; 152 uint8_t candropipv4 = 1;
140 153
141 if (ip_port.ip.family == AF_INET6) { 154 if (ip_port.ip.family == AF_INET6) {
@@ -143,35 +156,101 @@ static int client_or_ip_port_in_list(Client_data *list, uint32_t length, uint8_t
143 156
144 /* ipv6: count how many spots are used */ 157 /* ipv6: count how many spots are used */
145 for (i = 0; i < length; i++) 158 for (i = 0; i < length; i++)
146 if (list[i].ip_port.ip.family == AF_INET6) 159 if (list[i].assoc.ip_port.ip.family == AF_INET6)
147 ipv6cnt++; 160 ipv6cnt++;
148 161
149 /* more than half the list filled with ipv6: block ipv4->ipv6 overwrite */ 162 /* more than half the list filled with ipv6: block ipv4->ipv6 overwrite */
150 if (ipv6cnt > length / 2) 163 if (ipv6cnt > length / 2)
151 candropipv4 = 0; 164 candropipv4 = 0;
152 } 165 }
166#endif
153 167
154 /* if client_id is in list, find it and maybe overwrite ip_port */ 168 /* if client_id is in list, find it and maybe overwrite ip_port */
155 for (i = 0; i < length; ++i) 169 for (i = 0; i < length; ++i)
156 if (id_equal(list[i].client_id, client_id)) { 170 if (id_equal(list[i].client_id, client_id)) {
171 /* Refresh the client timestamp. */
172#ifdef CLIENT_ONETOONE_IP
157 /* if we got "too many" ipv6 addresses already, keep the ipv4 address */ 173 /* if we got "too many" ipv6 addresses already, keep the ipv4 address */
158 if (!candropipv4 && (list[i].ip_port.ip.family == AF_INET)) 174 if (!candropipv4 && (list[i].assoc.ip_port.ip.family == AF_INET))
159 return 1; 175 return 1;
160 176
161 /* Refresh the client timestamp. */ 177 list[i].assoc.ip_port = ip_port;
162 list[i].timestamp = temp_time; 178 list[i].assoc.timestamp = temp_time;
163 list[i].ip_port = ip_port; 179#else
180 if (ip_port.ip.family == AF_INET) {
181#ifdef LOGGING
182 if (!ipport_equal(&list[i].assoc4.ip_port, &ip_port)) {
183 size_t x;
184 x = sprintf(logbuffer, "coipil[%u]: switching ipv4 from %s:%u ", i,
185 ip_ntoa(&list[i].assoc4.ip_port.ip), ntohs(list[i].assoc4.ip_port.port));
186 sprintf(logbuffer + x, "to %s:%u\n",
187 ip_ntoa(&ip_port.ip), ntohs(ip_port.port));
188 loglog(logbuffer);
189 }
190#endif
191 list[i].assoc4.ip_port = ip_port;
192 list[i].assoc4.timestamp = temp_time;
193 } else if (ip_port.ip.family == AF_INET6) {
194#ifdef LOGGING
195 if (!ipport_equal(&list[i].assoc6.ip_port, &ip_port)) {
196 size_t x;
197 x = sprintf(logbuffer, "coipil[%u]: switching ipv6 from %s:%u ", i,
198 ip_ntoa(&list[i].assoc6.ip_port.ip), ntohs(list[i].assoc6.ip_port.port));
199 sprintf(logbuffer + x, "to %s:%u\n",
200 ip_ntoa(&ip_port.ip), ntohs(ip_port.port));
201 loglog(logbuffer);
202 }
203#endif
204 list[i].assoc6.ip_port = ip_port;
205 list[i].assoc6.timestamp = temp_time;
206 }
207#endif
164 return 1; 208 return 1;
165 } 209 }
166 210
167 /* client_id not in list yet: find ip_port to overwrite */ 211 /* client_id not in list yet: see if we can find an identical ip_port, in
168 for (i = 0; i < length; ++i) 212 * that case we kill the old client_id by overwriting it with the new one
169 if (ipport_equal(&list[i].ip_port, &ip_port)) { 213 * TODO: maybe we SHOULDN'T do that if that client_id is in a friend_list
170 /* Refresh the client timestamp. */ 214 * and the one who is the actual friend's client_id/address set? */
171 list[i].timestamp = temp_time; 215 for (i = 0; i < length; ++i) {
216#ifdef CLIENT_ONETOONE_IP
217 if (ipport_equal(&list[i].assoc.ip_port, &ip_port)) {
218 /* Initialize client timestamp. */
219 list[i].assoc.timestamp = temp_time;
172 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); 220 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
221#ifdef LOGGING
222 sprintf(logbuffer, "coipil[%u]: switching client_id\n", i);
223 loglog(logbuffer);
224#endif
173 return 1; 225 return 1;
174 } 226 }
227#else
228 /* MAYBE: check the other address, if valid, don't nuke? */
229 if ((ip_port.ip.family == AF_INET) && ipport_equal(&list[i].assoc4.ip_port, &ip_port)) {
230 /* Initialize client timestamp. */
231 list[i].assoc4.timestamp = temp_time;
232 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
233#ifdef LOGGING
234 sprintf(logbuffer, "coipil[%u]: switching client_id (ipv4) \n", i);
235 loglog(logbuffer);
236#endif
237 /* kill the other address, if it was set */
238 memset(&list[i].assoc6, 0, sizeof(list[i].assoc6));
239 return 1;
240 } else if ((ip_port.ip.family == AF_INET6) && ipport_equal(&list[i].assoc6.ip_port, &ip_port)) {
241 /* Initialize client timestamp. */
242 list[i].assoc6.timestamp = temp_time;
243 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
244#ifdef LOGGING
245 sprintf(logbuffer, "coipil[%u]: switching client_id (ipv6) \n", i);
246 loglog(logbuffer);
247#endif
248 /* kill the other address, if it was set */
249 memset(&list[i].assoc4, 0, sizeof(list[i].assoc4));
250 return 1;
251 }
252#endif
253 }
175 254
176 return 0; 255 return 0;
177} 256}
@@ -215,17 +294,36 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod
215 sa_family_t sa_family, Client_data *client_list, uint32_t client_list_length, 294 sa_family_t sa_family, Client_data *client_list, uint32_t client_list_length,
216 time_t timestamp, int *num_nodes_ptr) 295 time_t timestamp, int *num_nodes_ptr)
217{ 296{
297 if ((sa_family != AF_INET) && (sa_family != AF_INET6))
298 return;
299
218 int num_nodes = *num_nodes_ptr; 300 int num_nodes = *num_nodes_ptr;
219 int tout, inlist, ipv46x, j, closest; 301 int ipv46x, j, closest;
220 uint32_t i; 302 uint32_t i;
221 303
222 for (i = 0; i < client_list_length; i++) { 304 for (i = 0; i < client_list_length; i++) {
223 Client_data *client = &client_list[i]; 305 Client_data *client = &client_list[i];
224 tout = is_timeout(timestamp, client->timestamp, BAD_NODE_TIMEOUT); 306
225 inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, client->client_id); 307 /* node already in list? */
308 if (client_in_nodelist(nodes_list, MAX_SENT_NODES, client->client_id))
309 continue;
310
311 IPPTsPng *ipptp = NULL;
312#ifdef CLIENT_ONETOONE_IP
313 ipptp = &client->assoc;
314#else
315 if (sa_family == AF_INET)
316 ipptp = &client->assoc4;
317 else
318 ipptp = &client->assoc6;
319#endif
320
321 /* node not in a good condition? */
322 if (is_timeout(timestamp, ipptp->timestamp, BAD_NODE_TIMEOUT))
323 continue;
226 324
227#ifdef TOX_ENABLE_IPV6 325#ifdef TOX_ENABLE_IPV6
228 IP *client_ip = &client->ip_port.ip; 326 IP *client_ip = &ipptp->ip_port.ip;
229 327
230 /* 328 /*
231 * Careful: AF_INET isn't seen as AF_INET on dual-stack sockets for 329 * Careful: AF_INET isn't seen as AF_INET on dual-stack sockets for
@@ -237,7 +335,8 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod
237 if ((dht->c->lossless_udp->net->family == AF_INET6) && 335 if ((dht->c->lossless_udp->net->family == AF_INET6) &&
238 (client_ip->family == AF_INET6)) { 336 (client_ip->family == AF_INET6)) {
239 /* socket is AF_INET6, address claims AF_INET6: 337 /* socket is AF_INET6, address claims AF_INET6:
240 * check for embedded IPv4-in-IPv6 */ 338 * check for embedded IPv4-in-IPv6 (shouldn't happen anymore,
339 * all storing functions should already convert down to IPv4) */
241 if (IN6_IS_ADDR_V4MAPPED(&client_ip->ip6.in6_addr)) 340 if (IN6_IS_ADDR_V4MAPPED(&client_ip->ip6.in6_addr))
242 ip_treat_as_family = AF_INET; 341 ip_treat_as_family = AF_INET;
243 } 342 }
@@ -247,8 +346,11 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod
247 ipv46x = !(sa_family == AF_INET); 346 ipv46x = !(sa_family == AF_INET);
248#endif 347#endif
249 348
250 /* If node isn't good or is already in list. */ 349 /* node address of the wrong family? */
251 if (tout || inlist || ipv46x) 350 if (ipv46x)
351 continue;
352
353 if (!LAN_ip(ipptp->ip_port.ip))
252 continue; 354 continue;
253 355
254 if (num_nodes < MAX_SENT_NODES) { 356 if (num_nodes < MAX_SENT_NODES) {
@@ -256,7 +358,7 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod
256 client->client_id, 358 client->client_id,
257 CLIENT_ID_SIZE ); 359 CLIENT_ID_SIZE );
258 360
259 nodes_list[num_nodes].ip_port = client->ip_port; 361 nodes_list[num_nodes].ip_port = ipptp->ip_port;
260 num_nodes++; 362 num_nodes++;
261 } else { 363 } else {
262 /* see if node_list contains a client_id that's "further away" 364 /* see if node_list contains a client_id that's "further away"
@@ -274,7 +376,7 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod
274 client->client_id, 376 client->client_id,
275 CLIENT_ID_SIZE); 377 CLIENT_ID_SIZE);
276 378
277 nodes_list[j].ip_port = client->ip_port; 379 nodes_list[j].ip_port = ipptp->ip_port;
278 break; 380 break;
279 } 381 }
280 } 382 }
@@ -315,9 +417,13 @@ static int replace_bad( Client_data *list,
315 uint8_t *client_id, 417 uint8_t *client_id,
316 IP_Port ip_port ) 418 IP_Port ip_port )
317{ 419{
420 if ((ip_port.ip.family != AF_INET) && (ip_port.ip.family != AF_INET6))
421 return 1;
422
318 uint32_t i; 423 uint32_t i;
319 uint64_t temp_time = unix_time(); 424 uint64_t temp_time = unix_time();
320 425
426#ifdef CLIENT_ONETOONE_IP
321 uint8_t candropipv4 = 1; 427 uint8_t candropipv4 = 1;
322 428
323 if (ip_port.ip.family == AF_INET6) { 429 if (ip_port.ip.family == AF_INET6) {
@@ -325,26 +431,39 @@ static int replace_bad( Client_data *list,
325 431
326 /* ipv6: count how many spots are used */ 432 /* ipv6: count how many spots are used */
327 for (i = 0; i < length; i++) 433 for (i = 0; i < length; i++)
328 if (list[i].ip_port.ip.family == AF_INET6) 434 if (list[i].assoc.ip_port.ip.family == AF_INET6)
329 ipv6cnt++; 435 ipv6cnt++;
330 436
331 /* more than half the list filled with ipv6: block ipv4->ipv6 overwrite */ 437 /* more than half the list filled with ipv6: block ipv4->ipv6 overwrite */
332 if (ipv6cnt > length / 2) 438 if (ipv6cnt > length / 2)
333 candropipv4 = 0; 439 candropipv4 = 0;
334 } 440 }
335 441#endif
336 for (i = 0; i < length; ++i) { 442 for (i = 0; i < length; ++i) {
337 /* If node is bad */ 443 /* If node is bad */
338 Client_data *client = &list[i]; 444 Client_data *client = &list[i];
445 IPPTsPng *ipptp = NULL;
446
447#ifdef CLIENT_ONETOONE_IP
448 ipptp = &client->assoc;
449 if ((candropipv4 || (ipptp->ip_port.ip.family == AF_INET6)) &&
450 is_timeout(temp_time, ipptp->timestamp, BAD_NODE_TIMEOUT)) {
451#else
452 if (ip_port.ip.family == AF_INET)
453 ipptp = &client->assoc4;
454 else
455 ipptp = &client->assoc6;
339 456
340 if ((candropipv4 || (client->ip_port.ip.family == AF_INET6)) && 457 if (is_timeout(temp_time, ipptp->timestamp, BAD_NODE_TIMEOUT)) {
341 is_timeout(temp_time, client->timestamp, BAD_NODE_TIMEOUT)) { 458#endif
342 memcpy(client->client_id, client_id, CLIENT_ID_SIZE); 459 memcpy(client->client_id, client_id, CLIENT_ID_SIZE);
343 client->ip_port = ip_port; 460 ipptp->ip_port = ip_port;
344 client->timestamp = temp_time; 461 ipptp->timestamp = temp_time;
345 ip_reset(&client->ret_ip_port.ip); 462
346 client->ret_ip_port.port = 0; 463 ip_reset(&ipptp->ret_ip_port.ip);
347 client->ret_timestamp = 0; 464 ipptp->ret_ip_port.port = 0;
465 ipptp->ret_timestamp = 0;
466
348 return 0; 467 return 0;
349 } 468 }
350 } 469 }
@@ -381,8 +500,14 @@ static int replace_good( Client_data *list,
381 IP_Port ip_port, 500 IP_Port ip_port,
382 uint8_t *comp_client_id ) 501 uint8_t *comp_client_id )
383{ 502{
503 if ((ip_port.ip.family != AF_INET) && (ip_port.ip.family != AF_INET6))
504 return 1;
505
384 sort_list(list, length, comp_client_id); 506 sort_list(list, length, comp_client_id);
385 507
508 int8_t replace = -1;
509
510#ifdef CLIENT_ONETOONE_IP
386 uint8_t candropipv4 = 1; 511 uint8_t candropipv4 = 1;
387 512
388 if (ip_port.ip.family == AF_INET6) { 513 if (ip_port.ip.family == AF_INET6) {
@@ -390,7 +515,7 @@ static int replace_good( Client_data *list,
390 515
391 /* ipv6: count how many spots are used */ 516 /* ipv6: count how many spots are used */
392 for (i = 0; i < length; i++) 517 for (i = 0; i < length; i++)
393 if (list[i].ip_port.ip.family == AF_INET6) 518 if (list[i].assoc.ip_port.ip.family == AF_INET6)
394 ipv6cnt++; 519 ipv6cnt++;
395 520
396 /* more than half the list filled with ipv6: block ipv4->ipv6 overwrite */ 521 /* more than half the list filled with ipv6: block ipv4->ipv6 overwrite */
@@ -398,7 +523,6 @@ static int replace_good( Client_data *list,
398 candropipv4 = 0; 523 candropipv4 = 0;
399 } 524 }
400 525
401 int8_t replace = -1;
402 uint32_t i; 526 uint32_t i;
403 527
404 if (candropipv4) { 528 if (candropipv4) {
@@ -414,8 +538,10 @@ static int replace_good( Client_data *list,
414 * so the furthest element is the first, NOT the last (at least that's 538 * so the furthest element is the first, NOT the last (at least that's
415 * what the comment above sort_list() claims) 539 * what the comment above sort_list() claims)
416 */ 540 */
541#endif
417 if (id_closest(comp_client_id, list[0].client_id, client_id) == 2) 542 if (id_closest(comp_client_id, list[0].client_id, client_id) == 2)
418 replace = 0; 543 replace = 0;
544#ifdef CLIENT_ONETOONE_IP
419 } else { 545 } else {
420 /* ipv6 case without a right to push out an ipv4: only look for ipv6 546 /* ipv6 case without a right to push out an ipv4: only look for ipv6
421 * addresses, the first one we find is either closer (then we can skip 547 * addresses, the first one we find is either closer (then we can skip
@@ -424,7 +550,7 @@ static int replace_good( Client_data *list,
424 for (i = 0; i < length; i++) { 550 for (i = 0; i < length; i++) {
425 Client_data *client = &list[i]; 551 Client_data *client = &list[i];
426 552
427 if (client->ip_port.ip.family == AF_INET6) { 553 if (client->assoc.ip_port.ip.family == AF_INET6) {
428 if (id_closest(comp_client_id, list[i].client_id, client_id) == 2) 554 if (id_closest(comp_client_id, list[i].client_id, client_id) == 2)
429 replace = i; 555 replace = i;
430 556
@@ -432,18 +558,29 @@ static int replace_good( Client_data *list,
432 } 558 }
433 } 559 }
434 } 560 }
561#endif
435 562
436 if (replace != -1) { 563 if (replace != -1) {
437#ifdef DEBUG 564#ifdef DEBUG
438 assert(replace >= 0 && replace < length); 565 assert(replace >= 0 && replace < length);
439#endif 566#endif
440 Client_data *client = &list[replace]; 567 Client_data *client = &list[replace];
568 IPPTsPng *ipptp = NULL;
569#ifdef CLIENT_ONETOONE_IP
570 ipptp = &client->assoc;
571#else
572 if (ip_port.ip.family == AF_INET)
573 ipptp = &client->assoc4;
574 else
575 ipptp = &client->assoc6;
576#endif
441 memcpy(client->client_id, client_id, CLIENT_ID_SIZE); 577 memcpy(client->client_id, client_id, CLIENT_ID_SIZE);
442 client->ip_port = ip_port; 578 ipptp->ip_port = ip_port;
443 client->timestamp = unix_time(); 579 ipptp->timestamp = unix_time();
444 ip_reset(&client->ret_ip_port.ip); 580
445 client->ret_ip_port.port = 0; 581 ip_reset(&ipptp->ret_ip_port.ip);
446 client->ret_timestamp = 0; 582 ipptp->ret_ip_port.port = 0;
583 ipptp->ret_timestamp = 0;
447 return 0; 584 return 0;
448 } 585 }
449 586
@@ -463,6 +600,17 @@ void addto_lists(DHT *dht, IP_Port ip_port, uint8_t *client_id)
463 ip_port.ip.ip4.uint32 = ip_port.ip.ip6.uint32[3]; 600 ip_port.ip.ip4.uint32 = ip_port.ip.ip6.uint32[3];
464 } 601 }
465 602
603 int address_local = LAN_ip(ip_port.ip) == 0;
604 if (address_local) {
605#ifdef LOGGING
606 sprintf(logbuffer, "addto_lists: address is local! address %s:%u\n", ip_ntoa(&ip_port.ip), ntohs(ip_port.port));
607 loglog(logbuffer);
608#endif
609 /* if client is already in list, don't kill its potentially good address */
610 if (client_in_list(dht->close_clientlist, LCLIENT_LIST, client_id))
611 return;
612 }
613
466 /* NOTE: Current behavior if there are two clients with the same id is 614 /* NOTE: Current behavior if there are two clients with the same id is
467 * to replace the first ip by the second. 615 * to replace the first ip by the second.
468 */ 616 */
@@ -496,25 +644,48 @@ static void returnedip_ports(DHT *dht, IP_Port ip_port, uint8_t *client_id, uint
496 uint32_t i, j; 644 uint32_t i, j;
497 uint64_t temp_time = unix_time(); 645 uint64_t temp_time = unix_time();
498 646
499 if (id_equal(client_id, dht->c->self_public_key)) { 647 /* convert IPv4-in-IPv6 to IPv4 */
648 if ((ip_port.ip.family == AF_INET6) && IN6_IS_ADDR_V4MAPPED(&ip_port.ip.ip6.in6_addr)) {
649 ip_port.ip.family = AF_INET;
650 ip_port.ip.ip4.uint32 = ip_port.ip.ip6.uint32[3];
651 }
500 652
653 if (id_equal(client_id, dht->c->self_public_key)) {
501 for (i = 0; i < LCLIENT_LIST; ++i) { 654 for (i = 0; i < LCLIENT_LIST; ++i) {
502 if (id_equal(nodeclient_id, dht->close_clientlist[i].client_id)) { 655 if (id_equal(nodeclient_id, dht->close_clientlist[i].client_id)) {
503 dht->close_clientlist[i].ret_ip_port = ip_port; 656#ifdef CLIENT_ONETOONE_IP
504 dht->close_clientlist[i].ret_timestamp = temp_time; 657 dht->close_clientlist[i].assoc.ret_ip_port = ip_port;
658 dht->close_clientlist[i].assoc.ret_timestamp = temp_time;
659#else
660 if (ip_port.ip.family == AF_INET) {
661 dht->close_clientlist[i].assoc4.ret_ip_port = ip_port;
662 dht->close_clientlist[i].assoc4.ret_timestamp = temp_time;
663 } else if (ip_port.ip.family == AF_INET6) {
664 dht->close_clientlist[i].assoc6.ret_ip_port = ip_port;
665 dht->close_clientlist[i].assoc6.ret_timestamp = temp_time;
666 }
667#endif
505 return; 668 return;
506 } 669 }
507 } 670 }
508 671
509 } else { 672 } else {
510
511 for (i = 0; i < dht->num_friends; ++i) { 673 for (i = 0; i < dht->num_friends; ++i) {
512 if (id_equal(client_id, dht->friends_list[i].client_id)) { 674 if (id_equal(client_id, dht->friends_list[i].client_id)) {
513
514 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 675 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
515 if (id_equal(nodeclient_id, dht->friends_list[i].client_list[j].client_id)) { 676 if (id_equal(nodeclient_id, dht->friends_list[i].client_list[j].client_id)) {
516 dht->friends_list[i].client_list[j].ret_ip_port = ip_port; 677#ifdef CLIENT_ONETOONE_IP
517 dht->friends_list[i].client_list[j].ret_timestamp = temp_time; 678 dht->friends_list[i].client_list[j].assoc.ret_ip_port = ip_port;
679 dht->friends_list[i].client_list[j].assoc.ret_timestamp = temp_time;
680#else
681 if (ip_port.ip.family == AF_INET) {
682 dht->friends_list[i].client_list[j].assoc4.ret_ip_port = ip_port;
683 dht->friends_list[i].client_list[j].assoc4.ret_timestamp = temp_time;
684 } else if (ip_port.ip.family == AF_INET6) {
685 dht->friends_list[i].client_list[j].assoc6.ret_ip_port = ip_port;
686 dht->friends_list[i].client_list[j].assoc6.ret_timestamp = temp_time;
687 }
688#endif
518 return; 689 return;
519 } 690 }
520 } 691 }
@@ -897,14 +1068,24 @@ static void get_bunchnodes(DHT *dht, Client_data *list, uint16_t length, uint16_
897 uint64_t temp_time = unix_time(); 1068 uint64_t temp_time = unix_time();
898 uint32_t i, num = 0; 1069 uint32_t i, num = 0;
899 1070
900 for (i = 0; i < length; ++i) 1071 for (i = 0; i < length; ++i) {
901 if (ipport_isset(&(list[i].ip_port)) && !is_timeout(temp_time, list[i].ret_timestamp, BAD_NODE_TIMEOUT)) { 1072 IPPTsPng *assoc;
902 getnodes(dht, list[i].ip_port, list[i].client_id, client_id); 1073#ifdef CLIENT_ONETOONE_IP
903 ++num; 1074 assoc = &list[i].assoc;
1075#else
1076 uint32_t a;
904 1077
905 if (num >= max_num) 1078 for (a = 0, assoc = &list[i].assoc6; a < 2; a++, assoc = &list[i].assoc4)
906 return; 1079#endif
907 } 1080 if (ipport_isset(&(assoc->ip_port)) &&
1081 !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) {
1082 getnodes(dht, assoc->ip_port, list[i].client_id, client_id);
1083 ++num;
1084
1085 if (num >= max_num)
1086 return;
1087 }
1088 }
908} 1089}
909 1090
910int DHT_addfriend(DHT *dht, uint8_t *client_id) 1091int DHT_addfriend(DHT *dht, uint8_t *client_id)
@@ -922,7 +1103,7 @@ int DHT_addfriend(DHT *dht, uint8_t *client_id)
922 memset(&dht->friends_list[dht->num_friends], 0, sizeof(DHT_Friend)); 1103 memset(&dht->friends_list[dht->num_friends], 0, sizeof(DHT_Friend));
923 memcpy(dht->friends_list[dht->num_friends].client_id, client_id, CLIENT_ID_SIZE); 1104 memcpy(dht->friends_list[dht->num_friends].client_id, client_id, CLIENT_ID_SIZE);
924 1105
925 dht->friends_list[dht->num_friends].NATping_id = ((uint64_t)random_int() << 32) + random_int(); 1106 dht->friends_list[dht->num_friends].nat.NATping_id = ((uint64_t)random_int() << 32) + random_int();
926 ++dht->num_friends; 1107 ++dht->num_friends;
927 get_bunchnodes(dht, dht->close_clientlist, LCLIENT_LIST, MAX_FRIEND_CLIENTS, client_id);/*TODO: make this better?*/ 1108 get_bunchnodes(dht, dht->close_clientlist, LCLIENT_LIST, MAX_FRIEND_CLIENTS, client_id);/*TODO: make this better?*/
928 return 0; 1109 return 0;
@@ -976,10 +1157,20 @@ int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port)
976 /* Equal */ 1157 /* Equal */
977 if (id_equal(dht->friends_list[i].client_id, client_id)) { 1158 if (id_equal(dht->friends_list[i].client_id, client_id)) {
978 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 1159 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
979 if (id_equal(dht->friends_list[i].client_list[j].client_id, client_id) 1160 Client_data *client = &dht->friends_list[i].client_list[j];
980 && !is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) { 1161 if (id_equal(client->client_id, client_id)) {
981 *ip_port = dht->friends_list[i].client_list[j].ip_port; 1162 IPPTsPng *assoc = NULL;
982 return 1; 1163#ifdef CLIENT_ONETOONE_IP
1164 assoc = &client->assoc;
1165#else
1166 uint32_t a;
1167
1168 for (a = 0, assoc = &client->assoc6; a < 2; a++, assoc = &client->assoc4)
1169#endif
1170 if (!is_timeout(temp_time, assoc->timestamp, BAD_NODE_TIMEOUT)) {
1171 *ip_port = assoc->ip_port;
1172 return 1;
1173 }
983 } 1174 }
984 } 1175 }
985 1176
@@ -990,81 +1181,70 @@ int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port)
990 return -1; 1181 return -1;
991} 1182}
992 1183
993/* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request 1184static void do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, uint8_t *client_id,
994 * every GET_NODE_INTERVAL seconds to a random good node for each "friend" in our "friends" list. 1185 Client_data *list, uint32_t list_count)
995 */
996static void do_DHT_friends(DHT *dht)
997{ 1186{
998 uint32_t i, j; 1187 uint32_t i;
999 uint64_t temp_time = unix_time(); 1188 uint64_t temp_time = unix_time();
1000 uint32_t rand_node;
1001 uint32_t index[MAX_FRIEND_CLIENTS];
1002 1189
1003 for (i = 0; i < dht->num_friends; ++i) { 1190 uint32_t num_nodes = 0;
1004 uint32_t num_nodes = 0; 1191 Client_data *client_list[list_count];
1005 1192 IPPTsPng *assoc_list[list_count];
1006 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 1193
1007 /* If node is not dead. */ 1194 for (i = 0; i < list_count; i++) {
1008 if (!is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, Kill_NODE_TIMEOUT)) { 1195 /* If node is not dead. */
1009 if ((dht->friends_list[i].client_list[j].last_pinged + PING_INTERVAL) <= temp_time) { 1196 Client_data *client = &list[i];
1010 send_ping_request(dht->ping, dht->friends_list[i].client_list[j].ip_port, 1197 IPPTsPng *assoc;
1011 dht->friends_list[i].client_list[j].client_id ); 1198#ifdef CLIENT_ONETOONE_IP
1012 dht->friends_list[i].client_list[j].last_pinged = temp_time; 1199 assoc = &client->assoc;
1200#else
1201 uint32_t a;
1202
1203 for (a = 0, assoc = &client->assoc6; a < 2; a++, assoc = &client->assoc4)
1204#endif
1205
1206 if (!is_timeout(temp_time, assoc->timestamp, KILL_NODE_TIMEOUT)) {
1207 if (is_timeout(temp_time, assoc->last_pinged, PING_INTERVAL)) {
1208 send_ping_request(dht->ping, assoc->ip_port, client->client_id );
1209 assoc->last_pinged = temp_time;
1013 } 1210 }
1014 1211
1015 /* If node is good. */ 1212 /* If node is good. */
1016 if (!is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) { 1213 if (!is_timeout(temp_time, assoc->timestamp, BAD_NODE_TIMEOUT)) {
1017 index[num_nodes] = j; 1214 client_list[num_nodes] = client;
1215 assoc_list[num_nodes] = assoc;
1018 ++num_nodes; 1216 ++num_nodes;
1019 } 1217 }
1020 } 1218 }
1021 } 1219 }
1022 1220
1023 if (dht->friends_list[i].lastgetnode + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) { 1221 if ((num_nodes != 0) &&
1024 rand_node = rand() % num_nodes; 1222 is_timeout(temp_time, *lastgetnode, GET_NODE_INTERVAL)) {
1025 getnodes(dht, dht->friends_list[i].client_list[index[rand_node]].ip_port, 1223 uint32_t rand_node = rand() % num_nodes;
1026 dht->friends_list[i].client_list[index[rand_node]].client_id, 1224 getnodes(dht, assoc_list[rand_node]->ip_port, client_list[rand_node]->client_id,
1027 dht->friends_list[i].client_id ); 1225 client_id);
1028 dht->friends_list[i].lastgetnode = temp_time; 1226 *lastgetnode = temp_time;
1029 }
1030 } 1227 }
1031} 1228}
1032 1229
1230/* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request
1231 * every GET_NODE_INTERVAL seconds to a random good node for each "friend" in our "friends" list.
1232 */
1233static void do_DHT_friends(DHT *dht)
1234{
1235 uint32_t i;
1236 for (i = 0; i < dht->num_friends; ++i)
1237 do_ping_and_sendnode_requests(dht, &dht->friends_list[i].lastgetnode, dht->friends_list[i].client_id,
1238 dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS);
1239}
1240
1033/* Ping each client in the close nodes list every PING_INTERVAL seconds. 1241/* Ping each client in the close nodes list every PING_INTERVAL seconds.
1034 * Send a get nodes request every GET_NODE_INTERVAL seconds to a random good node in the list. 1242 * Send a get nodes request every GET_NODE_INTERVAL seconds to a random good node in the list.
1035 */ 1243 */
1036static void do_Close(DHT *dht) 1244static void do_Close(DHT *dht)
1037{ 1245{
1038 uint32_t i; 1246 do_ping_and_sendnode_requests(dht, &dht->close_lastgetnodes, dht->c->self_public_key,
1039 uint64_t temp_time = unix_time(); 1247 dht->close_clientlist, LCLIENT_LIST);
1040 uint32_t num_nodes = 0;
1041 uint32_t rand_node;
1042 uint32_t index[LCLIENT_LIST];
1043
1044 for (i = 0; i < LCLIENT_LIST; ++i) {
1045 /* If node is not dead. */
1046 if (!is_timeout(temp_time, dht->close_clientlist[i].timestamp, Kill_NODE_TIMEOUT)) {
1047 if ((dht->close_clientlist[i].last_pinged + PING_INTERVAL) <= temp_time) {
1048 send_ping_request(dht->ping, dht->close_clientlist[i].ip_port,
1049 dht->close_clientlist[i].client_id );
1050 dht->close_clientlist[i].last_pinged = temp_time;
1051 }
1052
1053 /* If node is good. */
1054 if (!is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT)) {
1055 index[num_nodes] = i;
1056 ++num_nodes;
1057 }
1058 }
1059 }
1060
1061 if (dht->close_lastgetnodes + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) {
1062 rand_node = rand() % num_nodes;
1063 getnodes(dht, dht->close_clientlist[index[rand_node]].ip_port,
1064 dht->close_clientlist[index[rand_node]].client_id,
1065 dht->c->self_public_key );
1066 dht->close_lastgetnodes = temp_time;
1067 }
1068} 1248}
1069 1249
1070void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key) 1250void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key)
@@ -1116,8 +1296,20 @@ int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length)
1116 uint32_t i; 1296 uint32_t i;
1117 1297
1118 for (i = 0; i < LCLIENT_LIST; ++i) { 1298 for (i = 0; i < LCLIENT_LIST; ++i) {
1119 if (id_equal(client_id, dht->close_clientlist[i].client_id)) 1299 if (id_equal(client_id, dht->close_clientlist[i].client_id)) {
1120 return sendpacket(dht->c->lossless_udp->net, dht->close_clientlist[i].ip_port, packet, length); 1300 Client_data *client = &dht->close_clientlist[i];
1301#ifdef CLIENT_ONETOONE_IP
1302 if (ip_isset(&client->assoc.ip_port.ip))
1303 return sendpacket(dht->c->lossless_udp->net, dht->close_clientlist[i].assoc.ip_port, packet, length);
1304#else
1305 if (ip_isset(&client->assoc6.ip_port.ip))
1306 return sendpacket(dht->c->lossless_udp->net, client->assoc6.ip_port, packet, length);
1307 else if (ip_isset(&client->assoc4.ip_port.ip))
1308 return sendpacket(dht->c->lossless_udp->net, client->assoc4.ip_port, packet, length);
1309 else
1310 break;
1311#endif
1312 }
1121 } 1313 }
1122 1314
1123 return -1; 1315 return -1;
@@ -1132,8 +1324,7 @@ int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length)
1132 */ 1324 */
1133static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num) 1325static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num)
1134{ 1326{
1135 int num_ips = 0; 1327 int i, num_ips = 0;
1136 uint32_t i;
1137 uint64_t temp_time = unix_time(); 1328 uint64_t temp_time = unix_time();
1138 1329
1139 if (friend_num >= dht->num_friends) 1330 if (friend_num >= dht->num_friends)
@@ -1142,18 +1333,89 @@ static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num)
1142 DHT_Friend *friend = &dht->friends_list[friend_num]; 1333 DHT_Friend *friend = &dht->friends_list[friend_num];
1143 Client_data *client; 1334 Client_data *client;
1144 1335
1145 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { 1336#ifndef CLIENT_ONETOONE_IP
1146 client = &(friend->client_list[i]); 1337 /* extra legwork, because having the outside allocating the space for us
1338 * is *usually* good(tm) (bites us in the behind in this case though) */
1339 int client_friend = -1;
1340 uint8_t client_friend_flags = 0;
1341 uint32_t a;
1147 1342
1148 if (id_equal(client->client_id, friend->client_id) && !is_timeout(temp_time, client->timestamp, BAD_NODE_TIMEOUT)) 1343 for(a = 0; a < 2; a++)
1149 return 0; 1344#endif
1345 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
1346 client = &(friend->client_list[i]);
1347
1348 IPPTsPng *assoc = NULL;
1349#ifdef CLIENT_ONETOONE_IP
1350 assoc = &client->assoc;
1351#else
1352 /* this is the one place where ipv4 is favored over ipv6, because
1353 * we can't be sure there's enough space to return both, and we do
1354 * need to return IPv4 (because of the majority of the people still
1355 * lacking IPv6 connectivity) */
1356 if (!a)
1357 assoc = &client->assoc4;
1358 else
1359 assoc = &client->assoc6;
1360#endif
1361 if (id_equal(client->client_id, friend->client_id) &&
1362 !is_timeout(temp_time, assoc->timestamp, BAD_NODE_TIMEOUT))
1363 return 0;
1150 1364
1151 /* If ip is not zero and node is good. */ 1365 /* If ip is not zero and node is good. */
1152 if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { 1366 if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) {
1153 ip_portlist[num_ips] = client->ret_ip_port; 1367 ip_portlist[num_ips] = assoc->ret_ip_port;
1154 ++num_ips; 1368 ++num_ips;
1369
1370#ifndef CLIENT_ONETOONE_IP
1371 if ((client_friend == -1) && id_equal(client->client_id, friend->client_id))
1372 client_friend = i;
1373
1374 if (client_friend == i)
1375 client_friend_flags |= 1 << a;
1376
1377 if (num_ips == MAX_FRIEND_CLIENTS) {
1378 /* if we got "real" IP addresses for the friend and we added
1379 * the ipv4 one, but (maybe) couldn't add the ipv6 one
1380 * due to space constraints... */
1381 if ((client_friend != -1) && (client_friend_flags == 1)) {
1382 assoc = &friend->client_list[client_friend].assoc6;
1383
1384 /* but the IPv6 address WOULD be valid... (which also
1385 * means there is DEFINITELY a functioning IPv6 stack
1386 * and connectivity!) */
1387 if (ip_isset(&assoc->ret_ip_port.ip) &&
1388 !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) {
1389 uint32_t r;
1390
1391 /* then kick another entry out:
1392 * first, try to find an IPv6 entry to kick
1393 * (don't need to look for friend's, because he
1394 * definitely hasn't been added yet) */
1395 for (r = 0; r < MAX_FRIEND_CLIENTS; r++)
1396 if (ip_portlist[r].ip.family == AF_INET6) {
1397 ip_portlist[r] = assoc->ip_port;
1398 return num_ips;
1399 }
1400
1401 /* no IPv6 found to kick:
1402 * kick the first IPv4 that is NOT the friend's one */
1403 for (r = 0; r < MAX_FRIEND_CLIENTS; r++)
1404 if ((ip_portlist[r].ip.family == AF_INET) &&
1405 !ipport_equal(&ip_portlist[r], &assoc->ip_port)) {
1406 ip_portlist[r] = assoc->ip_port;
1407 return num_ips;
1408 }
1409
1410 /* shouldn't be reached... */
1411 }
1412 }
1413
1414 return num_ips;
1415 }
1416#endif
1417 }
1155 } 1418 }
1156 }
1157 1419
1158 return num_ips; 1420 return num_ips;
1159} 1421}
@@ -1177,23 +1439,39 @@ int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t lengt
1177 int ip_num = friend_iplist(dht, ip_list, num); 1439 int ip_num = friend_iplist(dht, ip_list, num);
1178 1440
1179 if (ip_num < (MAX_FRIEND_CLIENTS / 2)) 1441 if (ip_num < (MAX_FRIEND_CLIENTS / 2))
1180 return 0; 1442 return 0; /* Reason for that? */
1181 1443
1182 uint64_t temp_time = unix_time(); 1444 uint64_t temp_time = unix_time();
1183 DHT_Friend *friend = &dht->friends_list[num]; 1445 DHT_Friend *friend = &dht->friends_list[num];
1184 Client_data *client; 1446 Client_data *client;
1185 1447
1186 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { 1448#ifndef CLIENT_ONETOONE_IP
1187 client = &friend->client_list[i]; 1449 /* extra legwork, because having the outside allocating the space for us
1450 * is *usually* good(tm) (bites us in the behind in this case though) */
1451 uint32_t a;
1188 1452
1189 /* If ip is not zero and node is good. */ 1453 for(a = 0; a < 2; a++)
1190 if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { 1454#endif
1191 int retval = sendpacket(dht->c->lossless_udp->net, client->ip_port, packet, length); 1455 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
1456 client = &friend->client_list[i];
1457 IPPTsPng *assoc = NULL;
1458#ifdef CLIENT_ONETOONE_IP
1459 assoc = &client->assoc;
1460#else
1461 if (!a)
1462 assoc = &client->assoc4;
1463 else
1464 assoc = &client->assoc6;
1465#endif
1466 /* If ip is not zero and node is good. */
1467 if (ip_isset(&assoc->ret_ip_port.ip) &&
1468 !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) {
1469 int retval = sendpacket(dht->c->lossless_udp->net, assoc->ip_port, packet, length);
1192 1470
1193 if ((unsigned int)retval == length) 1471 if ((unsigned int)retval == length)
1194 ++sent; 1472 ++sent;
1473 }
1195 } 1474 }
1196 }
1197 1475
1198 return sent; 1476 return sent;
1199} 1477}
@@ -1212,20 +1490,35 @@ static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint
1212 DHT_Friend *friend = &dht->friends_list[num]; 1490 DHT_Friend *friend = &dht->friends_list[num];
1213 Client_data *client; 1491 Client_data *client;
1214 1492
1215 IP_Port ip_list[MAX_FRIEND_CLIENTS]; 1493 IP_Port ip_list[MAX_FRIEND_CLIENTS * 2];
1216 int n = 0; 1494 int n = 0;
1217 uint32_t i; 1495 uint32_t i;
1218 uint64_t temp_time = unix_time(); 1496 uint64_t temp_time = unix_time();
1219 1497
1220 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { 1498#ifndef CLIENT_ONETOONE_IP
1221 client = &friend->client_list[i]; 1499 /* extra legwork, because having the outside allocating the space for us
1500 * is *usually* good(tm) (bites us in the behind in this case though) */
1501 uint32_t a;
1222 1502
1223 /* If ip is not zero and node is good. */ 1503 for(a = 0; a < 2; a++)
1224 if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { 1504#endif
1225 ip_list[n] = client->ip_port; 1505 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
1226 ++n; 1506 client = &friend->client_list[i];
1507 IPPTsPng *assoc = NULL;
1508#ifdef CLIENT_ONETOONE_IP
1509 assoc = &client->assoc;
1510#else
1511 if (!a)
1512 assoc = &client->assoc4;
1513 else
1514 assoc = &client->assoc6;
1515#endif
1516 /* If ip is not zero and node is good. */
1517 if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) {
1518 ip_list[n] = assoc->ip_port;
1519 ++n;
1520 }
1227 } 1521 }
1228 }
1229 1522
1230 if (n < 1) 1523 if (n < 1)
1231 return 0; 1524 return 0;
@@ -1308,12 +1601,12 @@ static int handle_NATping(void *object, IP_Port source, uint8_t *source_pubkey,
1308 if (packet[0] == NAT_PING_REQUEST) { 1601 if (packet[0] == NAT_PING_REQUEST) {
1309 /* 1 is reply */ 1602 /* 1 is reply */
1310 send_NATping(dht, source_pubkey, ping_id, NAT_PING_RESPONSE); 1603 send_NATping(dht, source_pubkey, ping_id, NAT_PING_RESPONSE);
1311 friend->recvNATping_timestamp = unix_time(); 1604 friend->nat.recvNATping_timestamp = unix_time();
1312 return 0; 1605 return 0;
1313 } else if (packet[0] == NAT_PING_RESPONSE) { 1606 } else if (packet[0] == NAT_PING_RESPONSE) {
1314 if (friend->NATping_id == ping_id) { 1607 if (friend->nat.NATping_id == ping_id) {
1315 friend->NATping_id = ((uint64_t)random_int() << 32) + random_int(); 1608 friend->nat.NATping_id = ((uint64_t)random_int() << 32) + random_int();
1316 friend->hole_punching = 1; 1609 friend->nat.hole_punching = 1;
1317 return 0; 1610 return 0;
1318 } 1611 }
1319 } 1612 }
@@ -1378,9 +1671,9 @@ static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports,
1378 return; 1671 return;
1379 1672
1380 uint32_t i; 1673 uint32_t i;
1381 uint32_t top = dht->friends_list[friend_num].punching_index + MAX_PUNCHING_PORTS; 1674 uint32_t top = dht->friends_list[friend_num].nat.punching_index + MAX_PUNCHING_PORTS;
1382 1675
1383 for (i = dht->friends_list[friend_num].punching_index; i != top; i++) { 1676 for (i = dht->friends_list[friend_num].nat.punching_index; i != top; i++) {
1384 /* TODO: Improve port guessing algorithm. */ 1677 /* TODO: Improve port guessing algorithm. */
1385 uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1); 1678 uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1);
1386 IP_Port pinging; 1679 IP_Port pinging;
@@ -1389,7 +1682,7 @@ static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports,
1389 send_ping_request(dht->ping, pinging, dht->friends_list[friend_num].client_id); 1682 send_ping_request(dht->ping, pinging, dht->friends_list[friend_num].client_id);
1390 } 1683 }
1391 1684
1392 dht->friends_list[friend_num].punching_index = i; 1685 dht->friends_list[friend_num].nat.punching_index = i;
1393} 1686}
1394 1687
1395static void do_NAT(DHT *dht) 1688static void do_NAT(DHT *dht)
@@ -1405,14 +1698,14 @@ static void do_NAT(DHT *dht)
1405 if (num < MAX_FRIEND_CLIENTS / 2) 1698 if (num < MAX_FRIEND_CLIENTS / 2)
1406 continue; 1699 continue;
1407 1700
1408 if (dht->friends_list[i].NATping_timestamp + PUNCH_INTERVAL < temp_time) { 1701 if (dht->friends_list[i].nat.NATping_timestamp + PUNCH_INTERVAL < temp_time) {
1409 send_NATping(dht, dht->friends_list[i].client_id, dht->friends_list[i].NATping_id, NAT_PING_REQUEST); 1702 send_NATping(dht, dht->friends_list[i].client_id, dht->friends_list[i].nat.NATping_id, NAT_PING_REQUEST);
1410 dht->friends_list[i].NATping_timestamp = temp_time; 1703 dht->friends_list[i].nat.NATping_timestamp = temp_time;
1411 } 1704 }
1412 1705
1413 if (dht->friends_list[i].hole_punching == 1 && 1706 if (dht->friends_list[i].nat.hole_punching == 1 &&
1414 dht->friends_list[i].punching_timestamp + PUNCH_INTERVAL < temp_time && 1707 dht->friends_list[i].nat.punching_timestamp + PUNCH_INTERVAL < temp_time &&
1415 dht->friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) { 1708 dht->friends_list[i].nat.recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) {
1416 1709
1417 IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2); 1710 IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2);
1418 1711
@@ -1423,8 +1716,8 @@ static void do_NAT(DHT *dht)
1423 uint16_t numports = NAT_getports(port_list, ip_list, num, ip); 1716 uint16_t numports = NAT_getports(port_list, ip_list, num, ip);
1424 punch_holes(dht, ip, port_list, numports, i); 1717 punch_holes(dht, ip, port_list, numports, i);
1425 1718
1426 dht->friends_list[i].punching_timestamp = temp_time; 1719 dht->friends_list[i].nat.punching_timestamp = temp_time;
1427 dht->friends_list[i].hole_punching = 0; 1720 dht->friends_list[i].nat.hole_punching = 0;
1428 } 1721 }
1429 } 1722 }
1430} 1723}
@@ -1496,16 +1789,17 @@ void DHT_save_old(DHT *dht, uint8_t *data)
1496 */ 1789 */
1497int DHT_load_old(DHT *dht, uint8_t *data, uint32_t size) 1790int DHT_load_old(DHT *dht, uint8_t *data, uint32_t size)
1498{ 1791{
1499 if (size < sizeof(dht->close_clientlist)) { 1792 size_t clientlist_oldsize = sizeof(Client_data_old) * LCLIENT_LIST;
1793 if (size < clientlist_oldsize) {
1500#ifdef DEBUG 1794#ifdef DEBUG
1501 fprintf(stderr, "DHT_load: Expected at least %u bytes, got %u.\n", sizeof(dht->close_clientlist), size); 1795 fprintf(stderr, "DHT_load: Expected at least %u bytes, got %u.\n", sizeof(dht->close_clientlist), size);
1502#endif 1796#endif
1503 return -1; 1797 return -1;
1504 } 1798 }
1505 1799
1506 uint32_t friendlistsize = size - sizeof(dht->close_clientlist); 1800 uint32_t friendlistsize = size - clientlist_oldsize;
1507 1801
1508 if (friendlistsize % sizeof(DHT_Friend) != 0) { 1802 if (friendlistsize % sizeof(DHT_Friend_old) != 0) {
1509#ifdef DEBUG 1803#ifdef DEBUG
1510 fprintf(stderr, "DHT_load: Expected a multiple of %u, got %u.\n", sizeof(DHT_Friend), friendlistsize); 1804 fprintf(stderr, "DHT_load: Expected a multiple of %u, got %u.\n", sizeof(DHT_Friend), friendlistsize);
1511#endif 1805#endif
@@ -1513,11 +1807,11 @@ int DHT_load_old(DHT *dht, uint8_t *data, uint32_t size)
1513 } 1807 }
1514 1808
1515 uint32_t i, j; 1809 uint32_t i, j;
1516 Client_data *client; 1810 Client_data_old *client;
1517 uint16_t friends_num = friendlistsize / sizeof(DHT_Friend); 1811 uint16_t friends_num = friendlistsize / sizeof(DHT_Friend_old);
1518 1812
1519 if (friends_num != 0) { 1813 if (friends_num != 0) {
1520 DHT_Friend *tempfriends_list = (DHT_Friend *)(data + sizeof(dht->close_clientlist)); 1814 DHT_Friend_old *tempfriends_list = (DHT_Friend_old *)(data + sizeof(dht->close_clientlist));
1521 1815
1522 for (i = 0; i < friends_num; ++i) { 1816 for (i = 0; i < friends_num; ++i) {
1523 DHT_addfriend(dht, tempfriends_list[i].client_id); 1817 DHT_addfriend(dht, tempfriends_list[i].client_id);
@@ -1525,17 +1819,17 @@ int DHT_load_old(DHT *dht, uint8_t *data, uint32_t size)
1525 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 1819 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
1526 client = &tempfriends_list[i].client_list[j]; 1820 client = &tempfriends_list[i].client_list[j];
1527 1821
1528 if (client->timestamp != 0) 1822 if (client->assoc.timestamp != 0)
1529 getnodes(dht, client->ip_port, client->client_id, tempfriends_list[i].client_id); 1823 getnodes(dht, client->assoc.ip_port, client->client_id, tempfriends_list[i].client_id);
1530 } 1824 }
1531 } 1825 }
1532 } 1826 }
1533 1827
1534 Client_data *tempclose_clientlist = (Client_data *)data; 1828 Client_data_old *tempclose_clientlist = (Client_data_old *)data;
1535 1829
1536 for (i = 0; i < LCLIENT_LIST; ++i) { 1830 for (i = 0; i < LCLIENT_LIST; ++i) {
1537 if (tempclose_clientlist[i].timestamp != 0) 1831 if (tempclose_clientlist[i].assoc.timestamp != 0)
1538 DHT_bootstrap(dht, tempclose_clientlist[i].ip_port, 1832 DHT_bootstrap(dht, tempclose_clientlist[i].assoc.ip_port,
1539 tempclose_clientlist[i].client_id ); 1833 tempclose_clientlist[i].client_id );
1540 } 1834 }
1541 1835
@@ -1548,8 +1842,10 @@ int DHT_load_old(DHT *dht, uint8_t *data, uint32_t size)
1548#define DHT_STATE_COOKIE_GLOBAL 0x159000d 1842#define DHT_STATE_COOKIE_GLOBAL 0x159000d
1549 1843
1550#define DHT_STATE_COOKIE_TYPE 0x11ce 1844#define DHT_STATE_COOKIE_TYPE 0x11ce
1551#define DHT_STATE_TYPE_FRIENDS 1 1845#define DHT_STATE_TYPE_FRIENDS 1
1552#define DHT_STATE_TYPE_CLIENTS 2 1846#define DHT_STATE_TYPE_CLIENTS 2
1847#define DHT_STATE_TYPE_FRIENDS_ASSOC46 3
1848#define DHT_STATE_TYPE_CLIENTS_ASSOC46 4
1553 1849
1554/* Get the size of the DHT (for saving). */ 1850/* Get the size of the DHT (for saving). */
1555uint32_t DHT_size(DHT *dht) 1851uint32_t DHT_size(DHT *dht)
@@ -1557,7 +1853,12 @@ uint32_t DHT_size(DHT *dht)
1557 uint32_t num = 0, i; 1853 uint32_t num = 0, i;
1558 1854
1559 for (i = 0; i < LCLIENT_LIST; ++i) 1855 for (i = 0; i < LCLIENT_LIST; ++i)
1560 if (dht->close_clientlist[i].timestamp != 0) 1856#ifdef CLIENT_ONETOONE_IP
1857 if (dht->close_clientlist[i].assoc.timestamp != 0)
1858#else
1859 if ((dht->close_clientlist[i].assoc4.timestamp != 0) ||
1860 (dht->close_clientlist[i].assoc6.timestamp != 0))
1861#endif
1561 num++; 1862 num++;
1562 1863
1563 uint32_t size32 = sizeof(uint32_t), sizesubhead = size32 * 2; 1864 uint32_t size32 = sizeof(uint32_t), sizesubhead = size32 * 2;
@@ -1584,7 +1885,11 @@ void DHT_save(DHT *dht, uint8_t *data)
1584 data += sizeof(uint32_t); 1885 data += sizeof(uint32_t);
1585 1886
1586 len = sizeof(DHT_Friend) * dht->num_friends; 1887 len = sizeof(DHT_Friend) * dht->num_friends;
1888#ifdef CLIENT_ONETOONE_IP
1587 type = DHT_STATE_TYPE_FRIENDS; 1889 type = DHT_STATE_TYPE_FRIENDS;
1890#else
1891 type = DHT_STATE_TYPE_FRIENDS_ASSOC46;
1892#endif
1588 data = z_state_save_subheader(data, len, type); 1893 data = z_state_save_subheader(data, len, type);
1589 memcpy(data, dht->friends_list, len); 1894 memcpy(data, dht->friends_list, len);
1590 data += len; 1895 data += len;
@@ -1592,18 +1897,32 @@ void DHT_save(DHT *dht, uint8_t *data)
1592 uint32_t num = 0, i; 1897 uint32_t num = 0, i;
1593 1898
1594 for (i = 0; i < LCLIENT_LIST; ++i) 1899 for (i = 0; i < LCLIENT_LIST; ++i)
1595 if (dht->close_clientlist[i].timestamp != 0) 1900#ifdef CLIENT_ONETOONE_IP
1901 if (dht->close_clientlist[i].assoc.timestamp != 0)
1902#else
1903 if ((dht->close_clientlist[i].assoc4.timestamp != 0) ||
1904 (dht->close_clientlist[i].assoc6.timestamp != 0))
1905#endif
1596 num++; 1906 num++;
1597 1907
1598 len = num * sizeof(Client_data); 1908 len = num * sizeof(Client_data);
1909#ifdef CLIENT_ONETOONE_IP
1599 type = DHT_STATE_TYPE_CLIENTS; 1910 type = DHT_STATE_TYPE_CLIENTS;
1911#else
1912 type = DHT_STATE_TYPE_CLIENTS_ASSOC46;
1913#endif
1600 data = z_state_save_subheader(data, len, type); 1914 data = z_state_save_subheader(data, len, type);
1601 1915
1602 if (num) { 1916 if (num) {
1603 Client_data *clients = (Client_data *)data; 1917 Client_data *clients = (Client_data *)data;
1604 1918
1605 for (num = 0, i = 0; i < LCLIENT_LIST; ++i) 1919 for (num = 0, i = 0; i < LCLIENT_LIST; ++i)
1606 if (dht->close_clientlist[i].timestamp != 0) 1920#ifdef CLIENT_ONETOONE_IP
1921 if (dht->close_clientlist[i].assoc.timestamp != 0)
1922#else
1923 if ((dht->close_clientlist[i].assoc4.timestamp != 0) ||
1924 (dht->close_clientlist[i].assoc6.timestamp != 0))
1925#endif
1607 memcpy(&clients[num++], &dht->close_clientlist[i], sizeof(Client_data)); 1926 memcpy(&clients[num++], &dht->close_clientlist[i], sizeof(Client_data));
1608 } 1927 }
1609 1928
@@ -1617,35 +1936,81 @@ static int dht_load_state_callback(void *outer, uint8_t *data, uint32_t length,
1617 1936
1618 switch (type) { 1937 switch (type) {
1619 case DHT_STATE_TYPE_FRIENDS: 1938 case DHT_STATE_TYPE_FRIENDS:
1620 if (length % sizeof(DHT_Friend) != 0) 1939 if (length % sizeof(DHT_Friend_old) != 0)
1621 break; 1940 break;
1622 1941
1623 DHT_Friend *friend_list = (DHT_Friend *)data; 1942 { /* localize declarations */
1624 num = length / sizeof(DHT_Friend); 1943 DHT_Friend_old *friend_list = (DHT_Friend_old *)data;
1944 num = length / sizeof(DHT_Friend_old);
1625 1945
1626 for (i = 0; i < num; ++i) { 1946 for (i = 0; i < num; ++i) {
1627 DHT_addfriend(dht, friend_list[i].client_id); 1947 DHT_addfriend(dht, friend_list[i].client_id);
1628 1948
1629 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 1949 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
1630 Client_data *client = &friend_list[i].client_list[j]; 1950 Client_data_old *client = &friend_list[i].client_list[j];
1631 1951
1632 if (client->timestamp != 0) 1952 if (client->assoc.timestamp != 0)
1633 getnodes(dht, client->ip_port, client->client_id, friend_list[i].client_id); 1953 getnodes(dht, client->assoc.ip_port, client->client_id, friend_list[i].client_id);
1954 }
1634 } 1955 }
1635 } 1956 } /* localize declarations */
1636 1957
1637 break; 1958 break;
1638 1959
1639 case DHT_STATE_TYPE_CLIENTS: 1960 case DHT_STATE_TYPE_CLIENTS:
1640 if ((length % sizeof(Client_data)) != 0) 1961 if ((length % sizeof(Client_data_old)) != 0)
1962 break;
1963
1964 { /* localize declarations */
1965 num = length / sizeof(Client_data_old);
1966 Client_data_old *client_list = (Client_data_old *)data;
1967
1968 for (i = 0; i < num; ++i)
1969 if (client_list[i].assoc.timestamp != 0)
1970 DHT_bootstrap(dht, client_list[i].assoc.ip_port, client_list[i].client_id);
1971 } /* localize declarations */
1972
1973 break;
1974
1975 case DHT_STATE_TYPE_FRIENDS_ASSOC46:
1976 if (length % sizeof(DHT_Friend_new) != 0)
1977 break;
1978
1979 { /* localize declarations */
1980 DHT_Friend_new *friend_list = (DHT_Friend_new *)data;
1981 num = length / sizeof(DHT_Friend_new);
1982
1983 for (i = 0; i < num; ++i) {
1984 DHT_addfriend(dht, friend_list[i].client_id);
1985
1986 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
1987 Client_data_new *client = &friend_list[i].client_list[j];
1988
1989 if (client->assoc4.timestamp != 0)
1990 getnodes(dht, client->assoc4.ip_port, client->client_id, friend_list[i].client_id);
1991 if (client->assoc6.timestamp != 0)
1992 getnodes(dht, client->assoc6.ip_port, client->client_id, friend_list[i].client_id);
1993 }
1994 }
1995 } /* localize declarations */
1996
1997 break;
1998
1999 case DHT_STATE_TYPE_CLIENTS_ASSOC46:
2000 if ((length % sizeof(Client_data_new)) != 0)
1641 break; 2001 break;
1642 2002
1643 num = length / sizeof(Client_data); 2003 { /* localize declarations */
1644 Client_data *client_list = (Client_data *)data; 2004 num = length / sizeof(Client_data_new);
2005 Client_data_new *client_list = (Client_data_new *)data;
1645 2006
1646 for (i = 0; i < num; ++i) 2007 for (i = 0; i < num; ++i) {
1647 if (client_list[i].timestamp != 0) 2008 if (client_list[i].assoc4.timestamp != 0)
1648 DHT_bootstrap(dht, client_list[i].ip_port, client_list[i].client_id); 2009 DHT_bootstrap(dht, client_list[i].assoc4.ip_port, client_list[i].client_id);
2010 if (client_list[i].assoc6.timestamp != 0)
2011 DHT_bootstrap(dht, client_list[i].assoc6.ip_port, client_list[i].client_id);
2012 }
2013 } /* localize declarations */
1649 2014
1650 break; 2015 break;
1651 2016
@@ -1685,7 +2050,13 @@ int DHT_isconnected(DHT *dht)
1685 uint64_t temp_time = unix_time(); 2050 uint64_t temp_time = unix_time();
1686 2051
1687 for (i = 0; i < LCLIENT_LIST; ++i) { 2052 for (i = 0; i < LCLIENT_LIST; ++i) {
1688 if (!is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT)) 2053 Client_data *client = &dht->close_clientlist[i];
2054#ifdef CLIENT_ONETOONE_IP
2055 if (!is_timeout(temp_time, client->assoc.timestamp, BAD_NODE_TIMEOUT))
2056#else
2057 if (!is_timeout(temp_time, client->assoc4.timestamp, BAD_NODE_TIMEOUT) ||
2058 !is_timeout(temp_time, client->assoc6.timestamp, BAD_NODE_TIMEOUT))
2059#endif
1689 return 1; 2060 return 1;
1690 } 2061 }
1691 2062
diff --git a/toxcore/DHT.h b/toxcore/DHT.h
index 7cb3198d..46193b56 100644
--- a/toxcore/DHT.h
+++ b/toxcore/DHT.h
@@ -44,7 +44,6 @@
44#define MAX_TOPING 16 44#define MAX_TOPING 16
45 45
46typedef struct { 46typedef struct {
47 uint8_t client_id[CLIENT_ID_SIZE];
48 IP_Port ip_port; 47 IP_Port ip_port;
49 uint64_t timestamp; 48 uint64_t timestamp;
50 uint64_t last_pinged; 49 uint64_t last_pinged;
@@ -52,19 +51,22 @@ typedef struct {
52 /* Returned by this node. Either our friend or us. */ 51 /* Returned by this node. Either our friend or us. */
53 IP_Port ret_ip_port; 52 IP_Port ret_ip_port;
54 uint64_t ret_timestamp; 53 uint64_t ret_timestamp;
55} Client_data; 54} IPPTsPng;
56
57/*----------------------------------------------------------------------------------*/
58 55
59typedef struct { 56typedef struct {
60 uint8_t client_id[CLIENT_ID_SIZE]; 57 uint8_t client_id[CLIENT_ID_SIZE];
61 Client_data client_list[MAX_FRIEND_CLIENTS]; 58 IPPTsPng assoc;
59} Client_data_old;
62 60
63 /* Time at which the last get_nodes request was sent. */ 61typedef struct {
64 uint64_t lastgetnode; 62 uint8_t client_id[CLIENT_ID_SIZE];
63 IPPTsPng assoc4;
64 IPPTsPng assoc6;
65} Client_data_new;
65 66
66 /* Symetric NAT hole punching stuff. */ 67/*----------------------------------------------------------------------------------*/
67 68
69typedef struct {
68 /* 1 if currently hole punching, otherwise 0 */ 70 /* 1 if currently hole punching, otherwise 0 */
69 uint8_t hole_punching; 71 uint8_t hole_punching;
70 uint32_t punching_index; 72 uint32_t punching_index;
@@ -72,7 +74,38 @@ typedef struct {
72 uint64_t recvNATping_timestamp; 74 uint64_t recvNATping_timestamp;
73 uint64_t NATping_id; 75 uint64_t NATping_id;
74 uint64_t NATping_timestamp; 76 uint64_t NATping_timestamp;
75} DHT_Friend; 77} NAT;
78
79typedef struct {
80 uint8_t client_id[CLIENT_ID_SIZE];
81 Client_data_old client_list[MAX_FRIEND_CLIENTS];
82
83 /* Time at which the last get_nodes request was sent. */
84 uint64_t lastgetnode;
85
86 /* Symetric NAT hole punching stuff. */
87 NAT nat;
88} DHT_Friend_old;
89
90typedef struct {
91 uint8_t client_id[CLIENT_ID_SIZE];
92 Client_data_new client_list[MAX_FRIEND_CLIENTS];
93
94 /* Time at which the last get_nodes request was sent. */
95 uint64_t lastgetnode;
96
97 /* Symetric NAT hole punching stuff. */
98 NAT nat;
99} DHT_Friend_new;
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
76 109
77/* this must be kept even if IP_Port is expanded: wire compatibility */ 110/* this must be kept even if IP_Port is expanded: wire compatibility */
78typedef struct { 111typedef struct {
diff --git a/toxcore/LAN_discovery.c b/toxcore/LAN_discovery.c
index cf4196d2..1e4fa125 100644
--- a/toxcore/LAN_discovery.c
+++ b/toxcore/LAN_discovery.c
@@ -130,7 +130,7 @@ static IP broadcast_ip(sa_family_t family_socket, sa_family_t family_broadcast)
130/* return 0 if ip is a LAN ip. 130/* return 0 if ip is a LAN ip.
131 * return -1 if it is not. 131 * return -1 if it is not.
132 */ 132 */
133static int LAN_ip(IP ip) 133int LAN_ip(IP ip)
134{ 134{
135#ifdef TOX_ENABLE_IPV6 135#ifdef TOX_ENABLE_IPV6
136 136
diff --git a/toxcore/LAN_discovery.h b/toxcore/LAN_discovery.h
index 3e9d9de5..9d19114d 100644
--- a/toxcore/LAN_discovery.h
+++ b/toxcore/LAN_discovery.h
@@ -41,10 +41,15 @@
41/* Send a LAN discovery pcaket to the broadcast address with port port. */ 41/* Send a LAN discovery pcaket to the broadcast address with port port. */
42int send_LANdiscovery(uint16_t port, Net_Crypto *c); 42int send_LANdiscovery(uint16_t port, Net_Crypto *c);
43 43
44
45/* Sets up packet handlers. */ 44/* Sets up packet handlers. */
46void LANdiscovery_init(DHT *dht); 45void LANdiscovery_init(DHT *dht);
47 46
47/* checks if a given IP isn't routable
48 *
49 * return 0 if ip is a LAN ip.
50 * return -1 if it is not.
51 */
52int LAN_ip(IP ip);
48 53
49 54
50#endif 55#endif
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index 07c8096f..b2c860c6 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -1296,18 +1296,25 @@ void doMessenger(Messenger *m)
1296 1296
1297 for (client = 0; client < LCLIENT_LIST; client++) { 1297 for (client = 0; client < LCLIENT_LIST; client++) {
1298 Client_data *cptr = &m->dht->close_clientlist[client]; 1298 Client_data *cptr = &m->dht->close_clientlist[client];
1299 IPPTsPng *assoc = NULL;
1300#ifdef CLIENT_ONETOONE_IP
1301 assoc = &cptr->assoc;
1302#else
1303 uint32_t a;
1299 1304
1300 if (ip_isset(&cptr->ip_port.ip)) { 1305 for (a = 0, assoc = &cptr->assoc4; a < 2; a++, assoc = &cptr->assoc6)
1301 last_pinged = lastdump - cptr->last_pinged; 1306#endif
1307 if (ip_isset(&assoc->ip_port.ip)) {
1308 last_pinged = lastdump - assoc->last_pinged;
1302 1309
1303 if (last_pinged > 999) 1310 if (last_pinged > 999)
1304 last_pinged = 999; 1311 last_pinged = 999;
1305 1312
1306 snprintf(logbuffer, sizeof(logbuffer), "C[%2u] %s:%u [%3u] %s\n", 1313 snprintf(logbuffer, sizeof(logbuffer), "C[%2u] %s:%u [%3u] %s\n",
1307 client, ip_ntoa(&cptr->ip_port.ip), ntohs(cptr->ip_port.port), 1314 client, ip_ntoa(&assoc->ip_port.ip), ntohs(assoc->ip_port.port),
1308 last_pinged, ID2String(cptr->client_id)); 1315 last_pinged, ID2String(cptr->client_id));
1309 loglog(logbuffer); 1316 loglog(logbuffer);
1310 } 1317 }
1311 } 1318 }
1312 1319
1313 loglog(" = = = = = = = = \n"); 1320 loglog(" = = = = = = = = \n");
@@ -1350,16 +1357,26 @@ void doMessenger(Messenger *m)
1350 1357
1351 for (client = 0; client < MAX_FRIEND_CLIENTS; client++) { 1358 for (client = 0; client < MAX_FRIEND_CLIENTS; client++) {
1352 Client_data *cptr = &dhtfptr->client_list[client]; 1359 Client_data *cptr = &dhtfptr->client_list[client];
1353 last_pinged = lastdump - cptr->last_pinged; 1360 IPPTsPng *assoc = NULL;
1361#ifdef CLIENT_ONETOONE_IP
1362 assoc = &cptr->assoc;
1363#else
1364 uint32_t a;
1354 1365
1355 if (last_pinged > 999) 1366 for (a = 0, assoc = &cptr->assoc4; a < 2; a++, assoc = &cptr->assoc6)
1356 last_pinged = 999; 1367#endif
1368 if (ip_isset(&assoc->ip_port.ip)) {
1369 last_pinged = lastdump - assoc->last_pinged;
1357 1370
1358 snprintf(logbuffer, sizeof(logbuffer), "F[%2u] => C[%2u] %s:%u [%3u] %s\n", 1371 if (last_pinged > 999)
1359 friend, client, ip_ntoa(&cptr->ip_port.ip), 1372 last_pinged = 999;
1360 ntohs(cptr->ip_port.port), last_pinged, 1373
1361 ID2String(cptr->client_id)); 1374 snprintf(logbuffer, sizeof(logbuffer), "F[%2u] => C[%2u] %s:%u [%3u] %s\n",
1362 loglog(logbuffer); 1375 friend, client, ip_ntoa(&assoc->ip_port.ip),
1376 ntohs(assoc->ip_port.port), last_pinged,
1377 ID2String(cptr->client_id));
1378 loglog(logbuffer);
1379 }
1363 } 1380 }
1364 } 1381 }
1365 1382
diff --git a/toxcore/util.h b/toxcore/util.h
index 9e4ac79a..13ab4792 100644
--- a/toxcore/util.h
+++ b/toxcore/util.h
@@ -20,8 +20,6 @@ typedef int (*load_state_callback_func)(void *outer, uint8_t *data, uint32_t len
20int load_state(load_state_callback_func load_state_callback, void *outer, 20int load_state(load_state_callback_func load_state_callback, void *outer,
21 uint8_t *data, uint32_t length, uint16_t cookie_inner); 21 uint8_t *data, uint32_t length, uint16_t cookie_inner);
22 22
23#undef LOGGING
24/* #define LOGGING */
25#ifdef LOGGING 23#ifdef LOGGING
26extern char logbuffer[512]; 24extern char logbuffer[512];
27void loginit(uint16_t port); 25void loginit(uint16_t port);