diff options
-rw-r--r-- | toxcore/DHT.c | 127 |
1 files changed, 48 insertions, 79 deletions
diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 1e6cc623..d83e409e 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c | |||
@@ -1357,6 +1357,7 @@ int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length) | |||
1357 | 1357 | ||
1358 | /* Puts all the different ips returned by the nodes for a friend_num into array ip_portlist. | 1358 | /* Puts all the different ips returned by the nodes for a friend_num into array ip_portlist. |
1359 | * ip_portlist must be at least MAX_FRIEND_CLIENTS big. | 1359 | * ip_portlist must be at least MAX_FRIEND_CLIENTS big. |
1360 | * unless CLIENT_ONETOONE_IP is defined, returns an array with ips of the same family. | ||
1360 | * | 1361 | * |
1361 | * return the number of ips returned. | 1362 | * return the number of ips returned. |
1362 | * return 0 if we are connected to friend or if no ips were found. | 1363 | * return 0 if we are connected to friend or if no ips were found. |
@@ -1364,7 +1365,7 @@ int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length) | |||
1364 | */ | 1365 | */ |
1365 | static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num) | 1366 | static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num) |
1366 | { | 1367 | { |
1367 | int i, num_ips = 0; | 1368 | int i; |
1368 | uint64_t temp_time = unix_time(); | 1369 | uint64_t temp_time = unix_time(); |
1369 | 1370 | ||
1370 | if (friend_num >= dht->num_friends) | 1371 | if (friend_num >= dht->num_friends) |
@@ -1372,97 +1373,59 @@ static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num) | |||
1372 | 1373 | ||
1373 | DHT_Friend *friend = &dht->friends_list[friend_num]; | 1374 | DHT_Friend *friend = &dht->friends_list[friend_num]; |
1374 | Client_data *client; | 1375 | Client_data *client; |
1376 | IP_Port ipv4s[MAX_FRIEND_CLIENTS]; | ||
1377 | int num_ipv4s = 0; | ||
1378 | IP_Port ipv6s[MAX_FRIEND_CLIENTS]; | ||
1379 | int num_ipv6s = 0; | ||
1375 | 1380 | ||
1376 | #ifndef CLIENT_ONETOONE_IP | 1381 | for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { |
1377 | /* extra legwork, because having the outside allocating the space for us | 1382 | client = &(friend->client_list[i]); |
1378 | * is *usually* good(tm) (bites us in the behind in this case though) */ | ||
1379 | int client_friend = -1; | ||
1380 | uint8_t client_friend_flags = 0; | ||
1381 | uint32_t a; | ||
1382 | |||
1383 | for (a = 0; a < 2; a++) | ||
1384 | #endif | ||
1385 | for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { | ||
1386 | client = &(friend->client_list[i]); | ||
1387 | 1383 | ||
1388 | IPPTsPng *assoc = NULL; | 1384 | IPPTsPng *assoc = NULL; |
1389 | #ifdef CLIENT_ONETOONE_IP | 1385 | #ifdef CLIENT_ONETOONE_IP |
1390 | assoc = &client->assoc; | 1386 | assoc = &client->assoc; |
1391 | #else | 1387 | #else |
1392 | 1388 | assoc = &client->assoc4; | |
1393 | /* this is the one place where ipv4 is favored over ipv6, because | ||
1394 | * we can't be sure there's enough space to return both, and we do | ||
1395 | * need to return IPv4 (because of the majority of the people still | ||
1396 | * lacking IPv6 connectivity) */ | ||
1397 | if (!a) | ||
1398 | assoc = &client->assoc4; | ||
1399 | else | ||
1400 | assoc = &client->assoc6; | ||
1401 | |||
1402 | #endif | 1389 | #endif |
1403 | 1390 | ||
1404 | if (id_equal(client->client_id, friend->client_id) && | 1391 | if (id_equal(client->client_id, friend->client_id) && |
1405 | !is_timeout(temp_time, assoc->timestamp, BAD_NODE_TIMEOUT)) | 1392 | !is_timeout(temp_time, assoc->timestamp, BAD_NODE_TIMEOUT)) |
1406 | return 0; | 1393 | return 0; |
1407 | 1394 | ||
1408 | /* If ip is not zero and node is good. */ | 1395 | /* If ip is not zero and node is good. */ |
1409 | if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { | 1396 | if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { |
1410 | ip_portlist[num_ips] = assoc->ret_ip_port; | 1397 | ipv4s[num_ipv4s] = assoc->ret_ip_port; |
1411 | ++num_ips; | 1398 | ++num_ipv4s; |
1399 | } | ||
1400 | } | ||
1412 | 1401 | ||
1413 | #ifndef CLIENT_ONETOONE_IP | 1402 | #ifndef CLIENT_ONETOONE_IP |
1414 | 1403 | ||
1415 | if ((client_friend == -1) && id_equal(client->client_id, friend->client_id)) | 1404 | for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { |
1416 | client_friend = i; | 1405 | client = &(friend->client_list[i]); |
1417 | |||
1418 | if (client_friend == i) | ||
1419 | client_friend_flags |= 1 << a; | ||
1420 | |||
1421 | if (num_ips == MAX_FRIEND_CLIENTS) { | ||
1422 | /* if we got "real" IP addresses for the friend and we added | ||
1423 | * the ipv4 one, but (maybe) couldn't add the ipv6 one | ||
1424 | * due to space constraints... */ | ||
1425 | if ((client_friend != -1) && (client_friend_flags == 1)) { | ||
1426 | assoc = &friend->client_list[client_friend].assoc6; | ||
1427 | |||
1428 | /* but the IPv6 address WOULD be valid... (which also | ||
1429 | * means there is DEFINITELY a functioning IPv6 stack | ||
1430 | * and connectivity!) */ | ||
1431 | if (ip_isset(&assoc->ret_ip_port.ip) && | ||
1432 | !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { | ||
1433 | uint32_t r; | ||
1434 | |||
1435 | /* then kick another entry out: | ||
1436 | * first, try to find an IPv6 entry to kick | ||
1437 | * (don't need to look for friend's, because he | ||
1438 | * definitely hasn't been added yet) */ | ||
1439 | for (r = 0; r < MAX_FRIEND_CLIENTS; r++) | ||
1440 | if (ip_portlist[r].ip.family == AF_INET6) { | ||
1441 | ip_portlist[r] = assoc->ip_port; | ||
1442 | return num_ips; | ||
1443 | } | ||
1444 | |||
1445 | /* no IPv6 found to kick: | ||
1446 | * kick the first IPv4 that is NOT the friend's one */ | ||
1447 | for (r = 0; r < MAX_FRIEND_CLIENTS; r++) | ||
1448 | if ((ip_portlist[r].ip.family == AF_INET) && | ||
1449 | !ipport_equal(&ip_portlist[r], &assoc->ip_port)) { | ||
1450 | ip_portlist[r] = assoc->ip_port; | ||
1451 | return num_ips; | ||
1452 | } | ||
1453 | |||
1454 | /* shouldn't be reached... */ | ||
1455 | } | ||
1456 | } | ||
1457 | 1406 | ||
1458 | return num_ips; | 1407 | IPPTsPng *assoc = NULL; |
1459 | } | 1408 | assoc = &client->assoc6; |
1460 | 1409 | ||
1461 | #endif | 1410 | if (id_equal(client->client_id, friend->client_id) && |
1462 | } | 1411 | !is_timeout(temp_time, assoc->timestamp, BAD_NODE_TIMEOUT)) |
1412 | return 0; | ||
1413 | |||
1414 | /* If ip is not zero and node is good. */ | ||
1415 | if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { | ||
1416 | ipv6s[num_ipv6s] = assoc->ret_ip_port; | ||
1417 | ++num_ipv6s; | ||
1463 | } | 1418 | } |
1419 | } | ||
1420 | |||
1421 | if (num_ipv6s >= num_ipv4s) { | ||
1422 | memcpy(ip_portlist, ipv6s, num_ipv6s * sizeof(IP_Port)); | ||
1423 | return num_ipv6s; | ||
1424 | } | ||
1464 | 1425 | ||
1465 | return num_ips; | 1426 | #endif |
1427 | memcpy(ip_portlist, ipv4s, num_ipv4s * sizeof(IP_Port)); | ||
1428 | return num_ipv4s; | ||
1466 | } | 1429 | } |
1467 | 1430 | ||
1468 | 1431 | ||
@@ -1479,6 +1442,7 @@ int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t lengt | |||
1479 | return 0; | 1442 | return 0; |
1480 | 1443 | ||
1481 | uint32_t i, sent = 0; | 1444 | uint32_t i, sent = 0; |
1445 | uint8_t friend_sent[MAX_FRIEND_CLIENTS] = {0}; | ||
1482 | 1446 | ||
1483 | IP_Port ip_list[MAX_FRIEND_CLIENTS]; | 1447 | IP_Port ip_list[MAX_FRIEND_CLIENTS]; |
1484 | int ip_num = friend_iplist(dht, ip_list, num); | 1448 | int ip_num = friend_iplist(dht, ip_list, num); |
@@ -1498,6 +1462,9 @@ int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t lengt | |||
1498 | for (a = 0; a < 2; a++) | 1462 | for (a = 0; a < 2; a++) |
1499 | #endif | 1463 | #endif |
1500 | for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { | 1464 | for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { |
1465 | if (friend_sent[i])/* Send one packet per client.*/ | ||
1466 | continue; | ||
1467 | |||
1501 | client = &friend->client_list[i]; | 1468 | client = &friend->client_list[i]; |
1502 | IPPTsPng *assoc = NULL; | 1469 | IPPTsPng *assoc = NULL; |
1503 | #ifdef CLIENT_ONETOONE_IP | 1470 | #ifdef CLIENT_ONETOONE_IP |
@@ -1516,8 +1483,10 @@ int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t lengt | |||
1516 | !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { | 1483 | !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { |
1517 | int retval = sendpacket(dht->c->lossless_udp->net, assoc->ip_port, packet, length); | 1484 | int retval = sendpacket(dht->c->lossless_udp->net, assoc->ip_port, packet, length); |
1518 | 1485 | ||
1519 | if ((unsigned int)retval == length) | 1486 | if ((unsigned int)retval == length) { |
1520 | ++sent; | 1487 | ++sent; |
1488 | friend_sent[i] = 1; | ||
1489 | } | ||
1521 | } | 1490 | } |
1522 | } | 1491 | } |
1523 | 1492 | ||