summaryrefslogtreecommitdiff
path: root/toxcore/DHT.c
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2013-09-28 09:21:08 -0400
committerirungentoo <irungentoo@gmail.com>2013-09-28 09:21:08 -0400
commited07194eb638d2b6baa4ae033f05cddd585aaef0 (patch)
tree8081be78b7cc7c2361862b0b0f2856e870acb811 /toxcore/DHT.c
parentd14ba73bc316211ec3e3e9a1600bda37b2bf2ae4 (diff)
friend_iplist and route_tofriend behaviour fixes.
Diffstat (limited to 'toxcore/DHT.c')
-rw-r--r--toxcore/DHT.c127
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 */
1365static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num) 1366static 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