diff options
Diffstat (limited to 'toxcore')
-rw-r--r-- | toxcore/DHT.c | 112 | ||||
-rw-r--r-- | toxcore/DHT.h | 37 | ||||
-rw-r--r-- | toxcore/group_chats.c | 25 | ||||
-rw-r--r-- | toxcore/ping.c | 210 | ||||
-rw-r--r-- | toxcore/ping.h | 33 |
5 files changed, 212 insertions, 205 deletions
diff --git a/toxcore/DHT.c b/toxcore/DHT.c index bdfe120f..ad4c8a1d 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c | |||
@@ -56,9 +56,6 @@ | |||
56 | /* Interval in seconds between punching attempts*/ | 56 | /* Interval in seconds between punching attempts*/ |
57 | #define PUNCH_INTERVAL 10 | 57 | #define PUNCH_INTERVAL 10 |
58 | 58 | ||
59 | /* Ping newly announced nodes to ping per TIME_TOPING seconds*/ | ||
60 | #define TIME_TOPING 5 | ||
61 | |||
62 | #define NAT_PING_REQUEST 0 | 59 | #define NAT_PING_REQUEST 0 |
63 | #define NAT_PING_RESPONSE 1 | 60 | #define NAT_PING_RESPONSE 1 |
64 | 61 | ||
@@ -84,7 +81,7 @@ Client_data *DHT_get_close_list(DHT *dht) | |||
84 | * return 1 if client_id1 is closer. | 81 | * return 1 if client_id1 is closer. |
85 | * return 2 if client_id2 is closer. | 82 | * return 2 if client_id2 is closer. |
86 | */ | 83 | */ |
87 | static int id_closest(uint8_t *id, uint8_t *id1, uint8_t *id2) | 84 | int id_closest(uint8_t *id, uint8_t *id1, uint8_t *id2) |
88 | { | 85 | { |
89 | size_t i; | 86 | size_t i; |
90 | uint8_t distance1, distance2; | 87 | uint8_t distance1, distance2; |
@@ -522,7 +519,6 @@ static void returnedip_ports(DHT *dht, IP_Port ip_port, uint8_t *client_id, uint | |||
522 | } | 519 | } |
523 | } | 520 | } |
524 | 521 | ||
525 | /* Same as last function but for get_node requests. */ | ||
526 | static int is_gettingnodes(DHT *dht, IP_Port ip_port, uint64_t ping_id) | 522 | static int is_gettingnodes(DHT *dht, IP_Port ip_port, uint64_t ping_id) |
527 | { | 523 | { |
528 | uint32_t i; | 524 | uint32_t i; |
@@ -533,7 +529,7 @@ static int is_gettingnodes(DHT *dht, IP_Port ip_port, uint64_t ping_id) | |||
533 | if (!is_timeout(temp_time, dht->send_nodes[i].timestamp, PING_TIMEOUT)) { | 529 | if (!is_timeout(temp_time, dht->send_nodes[i].timestamp, PING_TIMEOUT)) { |
534 | pinging = 0; | 530 | pinging = 0; |
535 | 531 | ||
536 | if (ping_id != 0 && dht->send_nodes[i].ping_id == ping_id) | 532 | if (ping_id != 0 && dht->send_nodes[i].id == ping_id) |
537 | ++pinging; | 533 | ++pinging; |
538 | 534 | ||
539 | if (ip_isset(&ip_port.ip) && ipport_equal(&dht->send_nodes[i].ip_port, &ip_port)) | 535 | if (ip_isset(&ip_port.ip) && ipport_equal(&dht->send_nodes[i].ip_port, &ip_port)) |
@@ -559,7 +555,7 @@ static uint64_t add_gettingnodes(DHT *dht, IP_Port ip_port) | |||
559 | if (is_timeout(temp_time, dht->send_nodes[j].timestamp, PING_TIMEOUT - i)) { | 555 | if (is_timeout(temp_time, dht->send_nodes[j].timestamp, PING_TIMEOUT - i)) { |
560 | dht->send_nodes[j].timestamp = temp_time; | 556 | dht->send_nodes[j].timestamp = temp_time; |
561 | dht->send_nodes[j].ip_port = ip_port; | 557 | dht->send_nodes[j].ip_port = ip_port; |
562 | dht->send_nodes[j].ping_id = ping_id; | 558 | dht->send_nodes[j].id = ping_id; |
563 | return ping_id; | 559 | return ping_id; |
564 | } | 560 | } |
565 | } | 561 | } |
@@ -830,7 +826,7 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3 | |||
830 | addto_lists(dht, source, packet + 1); | 826 | addto_lists(dht, source, packet + 1); |
831 | 827 | ||
832 | for (i = 0; i < num_nodes; ++i) { | 828 | for (i = 0; i < num_nodes; ++i) { |
833 | send_ping_request(dht->ping, dht->c, nodes_list[i].ip_port, nodes_list[i].client_id); | 829 | send_ping_request(dht->ping, nodes_list[i].ip_port, nodes_list[i].client_id); |
834 | returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1); | 830 | returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1); |
835 | } | 831 | } |
836 | 832 | ||
@@ -877,7 +873,7 @@ static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, | |||
877 | addto_lists(dht, source, packet + 1); | 873 | addto_lists(dht, source, packet + 1); |
878 | 874 | ||
879 | for (i = 0; i < num_nodes; ++i) { | 875 | for (i = 0; i < num_nodes; ++i) { |
880 | send_ping_request(dht->ping, dht->c, nodes_list[i].ip_port, nodes_list[i].client_id); | 876 | send_ping_request(dht->ping, nodes_list[i].ip_port, nodes_list[i].client_id); |
881 | returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1); | 877 | returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1); |
882 | } | 878 | } |
883 | 879 | ||
@@ -1006,7 +1002,7 @@ static void do_DHT_friends(DHT *dht) | |||
1006 | /* If node is not dead. */ | 1002 | /* If node is not dead. */ |
1007 | if (!is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, Kill_NODE_TIMEOUT)) { | 1003 | if (!is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, Kill_NODE_TIMEOUT)) { |
1008 | if ((dht->friends_list[i].client_list[j].last_pinged + PING_INTERVAL) <= temp_time) { | 1004 | if ((dht->friends_list[i].client_list[j].last_pinged + PING_INTERVAL) <= temp_time) { |
1009 | send_ping_request(dht->ping, dht->c, dht->friends_list[i].client_list[j].ip_port, | 1005 | send_ping_request(dht->ping, dht->friends_list[i].client_list[j].ip_port, |
1010 | dht->friends_list[i].client_list[j].client_id ); | 1006 | dht->friends_list[i].client_list[j].client_id ); |
1011 | dht->friends_list[i].client_list[j].last_pinged = temp_time; | 1007 | dht->friends_list[i].client_list[j].last_pinged = temp_time; |
1012 | } | 1008 | } |
@@ -1044,7 +1040,7 @@ static void do_Close(DHT *dht) | |||
1044 | /* If node is not dead. */ | 1040 | /* If node is not dead. */ |
1045 | if (!is_timeout(temp_time, dht->close_clientlist[i].timestamp, Kill_NODE_TIMEOUT)) { | 1041 | if (!is_timeout(temp_time, dht->close_clientlist[i].timestamp, Kill_NODE_TIMEOUT)) { |
1046 | if ((dht->close_clientlist[i].last_pinged + PING_INTERVAL) <= temp_time) { | 1042 | if ((dht->close_clientlist[i].last_pinged + PING_INTERVAL) <= temp_time) { |
1047 | send_ping_request(dht->ping, dht->c, dht->close_clientlist[i].ip_port, | 1043 | send_ping_request(dht->ping, dht->close_clientlist[i].ip_port, |
1048 | dht->close_clientlist[i].client_id ); | 1044 | dht->close_clientlist[i].client_id ); |
1049 | dht->close_clientlist[i].last_pinged = temp_time; | 1045 | dht->close_clientlist[i].last_pinged = temp_time; |
1050 | } | 1046 | } |
@@ -1069,7 +1065,7 @@ static void do_Close(DHT *dht) | |||
1069 | void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key) | 1065 | void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key) |
1070 | { | 1066 | { |
1071 | getnodes(dht, ip_port, public_key, dht->c->self_public_key); | 1067 | getnodes(dht, ip_port, public_key, dht->c->self_public_key); |
1072 | send_ping_request(dht->ping, dht->c, ip_port, public_key); | 1068 | send_ping_request(dht->ping, ip_port, public_key); |
1073 | } | 1069 | } |
1074 | int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled, | 1070 | int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled, |
1075 | uint16_t port, uint8_t *public_key) | 1071 | uint16_t port, uint8_t *public_key) |
@@ -1386,7 +1382,7 @@ static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports, | |||
1386 | IP_Port pinging; | 1382 | IP_Port pinging; |
1387 | ip_copy(&pinging.ip, &ip); | 1383 | ip_copy(&pinging.ip, &ip); |
1388 | pinging.port = htons(port); | 1384 | pinging.port = htons(port); |
1389 | send_ping_request(dht->ping, dht->c, pinging, dht->friends_list[friend_num].client_id); | 1385 | send_ping_request(dht->ping, pinging, dht->friends_list[friend_num].client_id); |
1390 | } | 1386 | } |
1391 | 1387 | ||
1392 | dht->friends_list[friend_num].punching_index = i; | 1388 | dht->friends_list[friend_num].punching_index = i; |
@@ -1432,94 +1428,34 @@ static void do_NAT(DHT *dht) | |||
1432 | /*----------------------------------------------------------------------------------*/ | 1428 | /*----------------------------------------------------------------------------------*/ |
1433 | /*-----------------------END OF NAT PUNCHING FUNCTIONS------------------------------*/ | 1429 | /*-----------------------END OF NAT PUNCHING FUNCTIONS------------------------------*/ |
1434 | 1430 | ||
1435 | |||
1436 | /* Add nodes to the toping list. | ||
1437 | * All nodes in this list are pinged every TIME_TOPING seconds | ||
1438 | * and are then removed from the list. | ||
1439 | * If the list is full the nodes farthest from our client_id are replaced. | ||
1440 | * The purpose of this list is to enable quick integration of new nodes into the | ||
1441 | * network while preventing amplification attacks. | ||
1442 | * | ||
1443 | * return 0 if node was added. | ||
1444 | * return -1 if node was not added. | ||
1445 | */ | ||
1446 | int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port) | ||
1447 | { | ||
1448 | if (!ip_isset(&ip_port.ip)) | ||
1449 | return -1; | ||
1450 | |||
1451 | uint32_t i; | ||
1452 | |||
1453 | for (i = 0; i < MAX_TOPING; ++i) { | ||
1454 | if (!ip_isset(&dht->toping[i].ip_port.ip)) { | ||
1455 | memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); | ||
1456 | ipport_copy(&dht->toping[i].ip_port, &ip_port); | ||
1457 | return 0; | ||
1458 | } | ||
1459 | } | ||
1460 | |||
1461 | for (i = 0; i < MAX_TOPING; ++i) { | ||
1462 | if (id_closest(dht->c->self_public_key, dht->toping[i].client_id, client_id) == 2) { | ||
1463 | memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); | ||
1464 | ipport_copy(&dht->toping[i].ip_port, &ip_port); | ||
1465 | return 0; | ||
1466 | } | ||
1467 | } | ||
1468 | |||
1469 | return -1; | ||
1470 | } | ||
1471 | |||
1472 | /* Ping all the valid nodes in the toping list every TIME_TOPING seconds. | ||
1473 | * This function must be run at least once every TIME_TOPING seconds. | ||
1474 | */ | ||
1475 | static void do_toping(DHT *dht) | ||
1476 | { | ||
1477 | uint64_t temp_time = unix_time(); | ||
1478 | |||
1479 | if (!is_timeout(temp_time, dht->last_toping, TIME_TOPING)) | ||
1480 | return; | ||
1481 | |||
1482 | dht->last_toping = temp_time; | ||
1483 | uint32_t i; | ||
1484 | |||
1485 | for (i = 0; i < MAX_TOPING; ++i) { | ||
1486 | if (!ip_isset(&dht->toping[i].ip_port.ip)) | ||
1487 | return; | ||
1488 | |||
1489 | send_ping_request(dht->ping, dht->c, dht->toping[i].ip_port, dht->toping[i].client_id); | ||
1490 | ip_reset(&dht->toping[i].ip_port.ip); | ||
1491 | } | ||
1492 | } | ||
1493 | |||
1494 | |||
1495 | DHT *new_DHT(Net_Crypto *c) | 1431 | DHT *new_DHT(Net_Crypto *c) |
1496 | { | 1432 | { |
1497 | if (c == NULL) | 1433 | if (c == NULL) |
1498 | return NULL; | 1434 | return NULL; |
1499 | 1435 | ||
1500 | DHT *temp = calloc(1, sizeof(DHT)); | 1436 | DHT *dht = calloc(1, sizeof(DHT)); |
1501 | 1437 | ||
1502 | if (temp == NULL) | 1438 | if (dht == NULL) |
1503 | return NULL; | 1439 | return NULL; |
1504 | 1440 | ||
1505 | temp->ping = new_ping(); | 1441 | dht->ping = new_ping(dht, c); |
1506 | 1442 | ||
1507 | if (temp->ping == NULL) { | 1443 | if (dht->ping == NULL) { |
1508 | kill_DHT(temp); | 1444 | kill_DHT(dht); |
1509 | return NULL; | 1445 | return NULL; |
1510 | } | 1446 | } |
1511 | 1447 | ||
1512 | temp->c = c; | 1448 | dht->c = c; |
1513 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_PING_REQUEST, &handle_ping_request, temp); | 1449 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_GET_NODES, &handle_getnodes, dht); |
1514 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, temp); | 1450 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES, &handle_sendnodes, dht); |
1515 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_GET_NODES, &handle_getnodes, temp); | ||
1516 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES, &handle_sendnodes, temp); | ||
1517 | #ifdef TOX_ENABLE_IPV6 | 1451 | #ifdef TOX_ENABLE_IPV6 |
1518 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, temp); | 1452 | networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, dht); |
1519 | #endif | 1453 | #endif |
1520 | init_cryptopackets(temp); | 1454 | |
1521 | cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, temp); | 1455 | init_cryptopackets(dht); |
1522 | return temp; | 1456 | cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, dht); |
1457 | |||
1458 | return dht; | ||
1523 | } | 1459 | } |
1524 | 1460 | ||
1525 | void do_DHT(DHT *dht) | 1461 | void do_DHT(DHT *dht) |
@@ -1527,7 +1463,7 @@ void do_DHT(DHT *dht) | |||
1527 | do_Close(dht); | 1463 | do_Close(dht); |
1528 | do_DHT_friends(dht); | 1464 | do_DHT_friends(dht); |
1529 | do_NAT(dht); | 1465 | do_NAT(dht); |
1530 | do_toping(dht); | 1466 | do_toping(dht->ping); |
1531 | } | 1467 | } |
1532 | void kill_DHT(DHT *dht) | 1468 | void kill_DHT(DHT *dht) |
1533 | { | 1469 | { |
diff --git a/toxcore/DHT.h b/toxcore/DHT.h index e6f227f7..7cb3198d 100644 --- a/toxcore/DHT.h +++ b/toxcore/DHT.h | |||
@@ -26,7 +26,6 @@ | |||
26 | 26 | ||
27 | #include "net_crypto.h" | 27 | #include "net_crypto.h" |
28 | 28 | ||
29 | |||
30 | /* Size of the client_id in bytes. */ | 29 | /* Size of the client_id in bytes. */ |
31 | #define CLIENT_ID_SIZE crypto_box_PUBLICKEYBYTES | 30 | #define CLIENT_ID_SIZE crypto_box_PUBLICKEYBYTES |
32 | 31 | ||
@@ -92,22 +91,23 @@ typedef Node46_format Node_format; | |||
92 | typedef Node4_format Node_format; | 91 | typedef Node4_format Node_format; |
93 | #endif | 92 | #endif |
94 | 93 | ||
94 | /*----------------------------------------------------------------------------------*/ | ||
95 | |||
95 | typedef struct { | 96 | typedef struct { |
96 | IP_Port ip_port; | 97 | IP_Port ip_port; |
97 | uint64_t ping_id; | 98 | uint64_t id; |
98 | uint64_t timestamp; | 99 | uint64_t timestamp; |
99 | } Pinged; | 100 | } pinged_t; |
100 | 101 | ||
101 | /*----------------------------------------------------------------------------------*/ | ||
102 | typedef struct { | 102 | typedef struct { |
103 | Net_Crypto *c; | 103 | Net_Crypto *c; |
104 | |||
104 | Client_data close_clientlist[LCLIENT_LIST]; | 105 | Client_data close_clientlist[LCLIENT_LIST]; |
105 | DHT_Friend *friends_list; | 106 | DHT_Friend *friends_list; |
106 | uint16_t num_friends; | 107 | uint16_t num_friends; |
107 | Pinged send_nodes[LSEND_NODES_ARRAY]; | ||
108 | Node_format toping[MAX_TOPING]; | ||
109 | uint64_t last_toping; | ||
110 | uint64_t close_lastgetnodes; | 108 | uint64_t close_lastgetnodes; |
109 | |||
110 | pinged_t send_nodes[LSEND_NODES_ARRAY]; | ||
111 | void *ping; | 111 | void *ping; |
112 | } DHT; | 112 | } DHT; |
113 | /*----------------------------------------------------------------------------------*/ | 113 | /*----------------------------------------------------------------------------------*/ |
@@ -152,6 +152,14 @@ int DHT_delfriend(DHT *dht, uint8_t *client_id); | |||
152 | */ | 152 | */ |
153 | int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port); | 153 | int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port); |
154 | 154 | ||
155 | /* Compares client_id1 and client_id2 with client_id. | ||
156 | * | ||
157 | * return 0 if both are same distance. | ||
158 | * return 1 if client_id1 is closer. | ||
159 | * return 2 if client_id2 is closer. | ||
160 | */ | ||
161 | int id_closest(uint8_t *id, uint8_t *id1, uint8_t *id2); | ||
162 | |||
155 | /* Run this function at least a couple times per second (It's the main loop). */ | 163 | /* Run this function at least a couple times per second (It's the main loop). */ |
156 | void do_DHT(DHT *dht); | 164 | void do_DHT(DHT *dht); |
157 | 165 | ||
@@ -176,17 +184,6 @@ void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key); | |||
176 | int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled, | 184 | int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled, |
177 | uint16_t port, uint8_t *public_key); | 185 | uint16_t port, uint8_t *public_key); |
178 | 186 | ||
179 | /* Add nodes to the toping list. | ||
180 | * All nodes in this list are pinged every TIME_TOPING seconds | ||
181 | * and are then removed from the list. | ||
182 | * If the list is full the nodes farthest from our client_id are replaced. | ||
183 | * The purpose of this list is to enable quick integration of new nodes into the | ||
184 | * network while preventing amplification attacks. | ||
185 | * | ||
186 | * return 0 if node was added. | ||
187 | * return -1 if node was not added. | ||
188 | */ | ||
189 | int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port); | ||
190 | 187 | ||
191 | /* ROUTING FUNCTIONS */ | 188 | /* ROUTING FUNCTIONS */ |
192 | 189 | ||
diff --git a/toxcore/group_chats.c b/toxcore/group_chats.c index dc8e158b..c32b26ba 100644 --- a/toxcore/group_chats.c +++ b/toxcore/group_chats.c | |||
@@ -53,31 +53,6 @@ typedef struct { | |||
53 | 53 | ||
54 | } sendnodes_data; | 54 | } sendnodes_data; |
55 | 55 | ||
56 | /* Compares client_id1 and client_id2 with client_id | ||
57 | * return 0 if both are same distance | ||
58 | * return 1 if client_id1 is closer | ||
59 | * return 2 if client_id2 is closer | ||
60 | */ | ||
61 | static int id_closest(uint8_t *id, uint8_t *id1, uint8_t *id2) | ||
62 | { | ||
63 | size_t i; | ||
64 | uint8_t distance1, distance2; | ||
65 | |||
66 | for (i = 0; i < CLIENT_ID_SIZE; ++i) { | ||
67 | |||
68 | distance1 = abs(((int8_t *)id)[i] ^ ((int8_t *)id1)[i]); | ||
69 | distance2 = abs(((int8_t *)id)[i] ^ ((int8_t *)id2)[i]); | ||
70 | |||
71 | if (distance1 < distance2) | ||
72 | return 1; | ||
73 | |||
74 | if (distance1 > distance2) | ||
75 | return 2; | ||
76 | } | ||
77 | |||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | 56 | ||
82 | /* | 57 | /* |
83 | * check if peer with client_id is in peer array. | 58 | * check if peer with client_id is in peer array. |
diff --git a/toxcore/ping.c b/toxcore/ping.c index 56ce2f59..09b80f0d 100644 --- a/toxcore/ping.c +++ b/toxcore/ping.c | |||
@@ -12,53 +12,48 @@ | |||
12 | #include <stdbool.h> | 12 | #include <stdbool.h> |
13 | #include <stdint.h> | 13 | #include <stdint.h> |
14 | 14 | ||
15 | #include "DHT.h" | ||
16 | #include "net_crypto.h" | 15 | #include "net_crypto.h" |
17 | #include "network.h" | 16 | #include "DHT.h" |
18 | #include "util.h" | ||
19 | 17 | ||
20 | #define PING_NUM_MAX 256 | 18 | #define PING_NUM_MAX 256 |
21 | #define PING_TIMEOUT 5 // 5s | 19 | #define PING_TIMEOUT 5 // 5s |
22 | 20 | ||
23 | typedef struct { | 21 | /* Ping newly announced nodes to ping per TIME_TOPING seconds*/ |
24 | IP_Port ipp; | 22 | #define TIME_TOPING 5 |
25 | uint64_t id; | ||
26 | uint64_t timestamp; | ||
27 | } pinged_t; | ||
28 | 23 | ||
29 | typedef struct { | 24 | typedef struct { |
25 | Net_Crypto *c; | ||
26 | |||
30 | pinged_t pings[PING_NUM_MAX]; | 27 | pinged_t pings[PING_NUM_MAX]; |
31 | size_t num_pings; | 28 | size_t num_pings; |
32 | size_t pos_pings; | 29 | size_t pos_pings; |
30 | |||
31 | Node_format toping[MAX_TOPING]; | ||
32 | uint64_t last_toping; | ||
33 | } PING; | 33 | } PING; |
34 | 34 | ||
35 | void *new_ping(void) | 35 | #define __PING_C__ |
36 | { | ||
37 | return calloc(1, sizeof(PING)); | ||
38 | } | ||
39 | 36 | ||
40 | void kill_ping(void *ping) | 37 | #include "network.h" |
41 | { | 38 | #include "util.h" |
42 | free(ping); | 39 | #include "ping.h" |
43 | } | ||
44 | 40 | ||
45 | static bool is_timeout(uint64_t time) | 41 | static bool is_ping_timeout(uint64_t time) |
46 | { | 42 | { |
47 | return (time + PING_TIMEOUT) < now(); | 43 | return (time + PING_TIMEOUT) < now(); |
48 | } | 44 | } |
49 | 45 | ||
50 | static void remove_timeouts(void *ping) // O(n) | 46 | static void remove_timeouts(PING *ping) // O(n) |
51 | { | 47 | { |
52 | PING *png = ping; | ||
53 | size_t i, id; | 48 | size_t i, id; |
54 | size_t new_pos = png->pos_pings; | 49 | size_t new_pos = ping->pos_pings; |
55 | size_t new_num = png->num_pings; | 50 | size_t new_num = ping->num_pings; |
56 | 51 | ||
57 | // Loop through buffer, oldest first. | 52 | // Loop through buffer, oldest first. |
58 | for (i = 0; i < png->num_pings; i++) { | 53 | for (i = 0; i < ping->num_pings; i++) { |
59 | id = (png->pos_pings + i) % PING_NUM_MAX; | 54 | id = (ping->pos_pings + i) % PING_NUM_MAX; |
60 | 55 | ||
61 | if (is_timeout(png->pings[id].timestamp)) { | 56 | if (is_ping_timeout(ping->pings[id].timestamp)) { |
62 | new_pos++; | 57 | new_pos++; |
63 | new_num--; | 58 | new_num--; |
64 | } | 59 | } |
@@ -68,37 +63,35 @@ static void remove_timeouts(void *ping) // O(n) | |||
68 | } | 63 | } |
69 | } | 64 | } |
70 | 65 | ||
71 | png->num_pings = new_num; | 66 | ping->num_pings = new_num; |
72 | png->pos_pings = new_pos % PING_NUM_MAX; | 67 | ping->pos_pings = new_pos % PING_NUM_MAX; |
73 | } | 68 | } |
74 | 69 | ||
75 | uint64_t add_ping(void *ping, IP_Port ipp) // O(n) | 70 | static uint64_t add_ping(PING *ping, IP_Port ipp) // O(n) |
76 | { | 71 | { |
77 | PING *png = ping; | ||
78 | size_t p; | 72 | size_t p; |
79 | 73 | ||
80 | remove_timeouts(ping); | 74 | remove_timeouts(ping); |
81 | 75 | ||
82 | /* Remove oldest ping if full buffer. */ | 76 | /* Remove oldest ping if full buffer. */ |
83 | if (png->num_pings == PING_NUM_MAX) { | 77 | if (ping->num_pings == PING_NUM_MAX) { |
84 | png->num_pings--; | 78 | ping->num_pings--; |
85 | png->pos_pings = (png->pos_pings + 1) % PING_NUM_MAX; | 79 | ping->pos_pings = (ping->pos_pings + 1) % PING_NUM_MAX; |
86 | } | 80 | } |
87 | 81 | ||
88 | /* Insert new ping at end of list. */ | 82 | /* Insert new ping at end of list. */ |
89 | p = (png->pos_pings + png->num_pings) % PING_NUM_MAX; | 83 | p = (ping->pos_pings + ping->num_pings) % PING_NUM_MAX; |
90 | 84 | ||
91 | png->pings[p].ipp = ipp; | 85 | ping->pings[p].ip_port = ipp; |
92 | png->pings[p].timestamp = now(); | 86 | ping->pings[p].timestamp = now(); |
93 | png->pings[p].id = random_64b(); | 87 | ping->pings[p].id = random_64b(); |
94 | 88 | ||
95 | png->num_pings++; | 89 | ping->num_pings++; |
96 | return png->pings[p].id; | 90 | return ping->pings[p].id; |
97 | } | 91 | } |
98 | 92 | ||
99 | bool is_pinging(void *ping, IP_Port ipp, uint64_t ping_id) // O(n) TODO: Replace this with something else. | 93 | static bool is_pinging(PING *ping, IP_Port ipp, uint64_t ping_id) // O(n) TODO: Replace this with something else. |
100 | { | 94 | { |
101 | PING *png = ping; | ||
102 | 95 | ||
103 | /* shouldn't that be an OR ? */ | 96 | /* shouldn't that be an OR ? */ |
104 | if (!ip_isset(&ipp.ip) && ping_id == 0) | 97 | if (!ip_isset(&ipp.ip) && ping_id == 0) |
@@ -108,12 +101,12 @@ bool is_pinging(void *ping, IP_Port ipp, uint64_t ping_id) // O(n) TODO: Repl | |||
108 | 101 | ||
109 | remove_timeouts(ping); | 102 | remove_timeouts(ping); |
110 | 103 | ||
111 | for (i = 0; i < png->num_pings; i++) { | 104 | for (i = 0; i < ping->num_pings; i++) { |
112 | id = (png->pos_pings + i) % PING_NUM_MAX; | 105 | id = (ping->pos_pings + i) % PING_NUM_MAX; |
113 | 106 | ||
114 | /* ping_id = 0 means match any id. */ | 107 | /* ping_id = 0 means match any id. */ |
115 | if ((!ip_isset(&ipp.ip) || ipport_equal(&png->pings[id].ipp, &ipp)) && | 108 | if ((!ip_isset(&ipp.ip) || ipport_equal(&ping->pings[id].ip_port, &ipp)) && |
116 | (png->pings[id].id == ping_id || ping_id == 0)) { | 109 | (ping->pings[id].id == ping_id || ping_id == 0)) { |
117 | return true; | 110 | return true; |
118 | } | 111 | } |
119 | } | 112 | } |
@@ -123,25 +116,25 @@ bool is_pinging(void *ping, IP_Port ipp, uint64_t ping_id) // O(n) TODO: Repl | |||
123 | 116 | ||
124 | #define DHT_PING_SIZE (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(uint64_t) + ENCRYPTION_PADDING) | 117 | #define DHT_PING_SIZE (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(uint64_t) + ENCRYPTION_PADDING) |
125 | 118 | ||
126 | int send_ping_request(void *ping, Net_Crypto *c, IP_Port ipp, uint8_t *client_id) | 119 | int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id) |
127 | { | 120 | { |
128 | uint8_t pk[DHT_PING_SIZE]; | 121 | uint8_t pk[DHT_PING_SIZE]; |
129 | int rc; | 122 | int rc; |
130 | uint64_t ping_id; | 123 | uint64_t ping_id; |
131 | 124 | ||
132 | if (is_pinging(ping, ipp, 0) || id_eq(client_id, c->self_public_key)) | 125 | if (is_pinging(ping, ipp, 0) || id_eq(client_id, ping->c->self_public_key)) |
133 | return 1; | 126 | return 1; |
134 | 127 | ||
135 | // Generate random ping_id. | 128 | // Generate random ping_id. |
136 | ping_id = add_ping(ping, ipp); | 129 | ping_id = add_ping(ping, ipp); |
137 | 130 | ||
138 | pk[0] = NET_PACKET_PING_REQUEST; | 131 | pk[0] = NET_PACKET_PING_REQUEST; |
139 | id_cpy(pk + 1, c->self_public_key); // Our pubkey | 132 | id_cpy(pk + 1, ping->c->self_public_key); // Our pubkey |
140 | new_nonce(pk + 1 + CLIENT_ID_SIZE); // Generate new nonce | 133 | new_nonce(pk + 1 + CLIENT_ID_SIZE); // Generate new nonce |
141 | 134 | ||
142 | // Encrypt ping_id using recipient privkey | 135 | // Encrypt ping_id using recipient privkey |
143 | rc = encrypt_data(client_id, | 136 | rc = encrypt_data(client_id, |
144 | c->self_secret_key, | 137 | ping->c->self_secret_key, |
145 | pk + 1 + CLIENT_ID_SIZE, | 138 | pk + 1 + CLIENT_ID_SIZE, |
146 | (uint8_t *) &ping_id, sizeof(ping_id), | 139 | (uint8_t *) &ping_id, sizeof(ping_id), |
147 | pk + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES); | 140 | pk + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES); |
@@ -149,24 +142,24 @@ int send_ping_request(void *ping, Net_Crypto *c, IP_Port ipp, uint8_t *client_id | |||
149 | if (rc != sizeof(ping_id) + ENCRYPTION_PADDING) | 142 | if (rc != sizeof(ping_id) + ENCRYPTION_PADDING) |
150 | return 1; | 143 | return 1; |
151 | 144 | ||
152 | return sendpacket(c->lossless_udp->net, ipp, pk, sizeof(pk)); | 145 | return sendpacket(ping->c->lossless_udp->net, ipp, pk, sizeof(pk)); |
153 | } | 146 | } |
154 | 147 | ||
155 | int send_ping_response(Net_Crypto *c, IP_Port ipp, uint8_t *client_id, uint64_t ping_id) | 148 | static int send_ping_response(PING *ping, IP_Port ipp, uint8_t *client_id, uint64_t ping_id) |
156 | { | 149 | { |
157 | uint8_t pk[DHT_PING_SIZE]; | 150 | uint8_t pk[DHT_PING_SIZE]; |
158 | int rc; | 151 | int rc; |
159 | 152 | ||
160 | if (id_eq(client_id, c->self_public_key)) | 153 | if (id_eq(client_id, ping->c->self_public_key)) |
161 | return 1; | 154 | return 1; |
162 | 155 | ||
163 | pk[0] = NET_PACKET_PING_RESPONSE; | 156 | pk[0] = NET_PACKET_PING_RESPONSE; |
164 | id_cpy(pk + 1, c->self_public_key); // Our pubkey | 157 | id_cpy(pk + 1, ping->c->self_public_key); // Our pubkey |
165 | new_nonce(pk + 1 + CLIENT_ID_SIZE); // Generate new nonce | 158 | new_nonce(pk + 1 + CLIENT_ID_SIZE); // Generate new nonce |
166 | 159 | ||
167 | // Encrypt ping_id using recipient privkey | 160 | // Encrypt ping_id using recipient privkey |
168 | rc = encrypt_data(client_id, | 161 | rc = encrypt_data(client_id, |
169 | c->self_secret_key, | 162 | ping->c->self_secret_key, |
170 | pk + 1 + CLIENT_ID_SIZE, | 163 | pk + 1 + CLIENT_ID_SIZE, |
171 | (uint8_t *) &ping_id, sizeof(ping_id), | 164 | (uint8_t *) &ping_id, sizeof(ping_id), |
172 | pk + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES); | 165 | pk + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES); |
@@ -174,24 +167,25 @@ int send_ping_response(Net_Crypto *c, IP_Port ipp, uint8_t *client_id, uint64_t | |||
174 | if (rc != sizeof(ping_id) + ENCRYPTION_PADDING) | 167 | if (rc != sizeof(ping_id) + ENCRYPTION_PADDING) |
175 | return 1; | 168 | return 1; |
176 | 169 | ||
177 | return sendpacket(c->lossless_udp->net, ipp, pk, sizeof(pk)); | 170 | return sendpacket(ping->c->lossless_udp->net, ipp, pk, sizeof(pk)); |
178 | } | 171 | } |
179 | 172 | ||
180 | int handle_ping_request(void *object, IP_Port source, uint8_t *packet, uint32_t length) | 173 | static int handle_ping_request(void *_dht, IP_Port source, uint8_t *packet, uint32_t length) |
181 | { | 174 | { |
182 | DHT *dht = object; | 175 | DHT *dht = _dht; |
183 | int rc; | 176 | int rc; |
184 | uint64_t ping_id; | 177 | uint64_t ping_id; |
185 | 178 | ||
186 | if (length != DHT_PING_SIZE) | 179 | if (length != DHT_PING_SIZE) |
187 | return 1; | 180 | return 1; |
188 | 181 | ||
189 | if (id_eq(packet + 1, dht->c->self_public_key)) | 182 | PING *ping = dht->ping; |
183 | if (id_eq(packet + 1, ping->c->self_public_key)) | ||
190 | return 1; | 184 | return 1; |
191 | 185 | ||
192 | // Decrypt ping_id | 186 | // Decrypt ping_id |
193 | rc = decrypt_data(packet + 1, | 187 | rc = decrypt_data(packet + 1, |
194 | dht->c->self_secret_key, | 188 | ping->c->self_secret_key, |
195 | packet + 1 + CLIENT_ID_SIZE, | 189 | packet + 1 + CLIENT_ID_SIZE, |
196 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, | 190 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, |
197 | sizeof(ping_id) + ENCRYPTION_PADDING, | 191 | sizeof(ping_id) + ENCRYPTION_PADDING, |
@@ -201,27 +195,28 @@ int handle_ping_request(void *object, IP_Port source, uint8_t *packet, uint32_t | |||
201 | return 1; | 195 | return 1; |
202 | 196 | ||
203 | // Send response | 197 | // Send response |
204 | send_ping_response(dht->c, source, packet + 1, ping_id); | 198 | send_ping_response(ping, source, packet + 1, ping_id); |
205 | add_toping(dht, packet + 1, source); | 199 | add_toping(ping, packet + 1, source); |
206 | 200 | ||
207 | return 0; | 201 | return 0; |
208 | } | 202 | } |
209 | 203 | ||
210 | int handle_ping_response(void *object, IP_Port source, uint8_t *packet, uint32_t length) | 204 | static int handle_ping_response(void *_dht, IP_Port source, uint8_t *packet, uint32_t length) |
211 | { | 205 | { |
212 | DHT *dht = object; | 206 | DHT *dht = _dht; |
213 | int rc; | 207 | int rc; |
214 | uint64_t ping_id; | 208 | uint64_t ping_id; |
215 | 209 | ||
216 | if (length != DHT_PING_SIZE) | 210 | if (length != DHT_PING_SIZE) |
217 | return 1; | 211 | return 1; |
218 | 212 | ||
219 | if (id_eq(packet + 1, dht->c->self_public_key)) | 213 | PING *ping = dht->ping; |
214 | if (id_eq(packet + 1, ping->c->self_public_key)) | ||
220 | return 1; | 215 | return 1; |
221 | 216 | ||
222 | // Decrypt ping_id | 217 | // Decrypt ping_id |
223 | rc = decrypt_data(packet + 1, | 218 | rc = decrypt_data(packet + 1, |
224 | dht->c->self_secret_key, | 219 | ping->c->self_secret_key, |
225 | packet + 1 + CLIENT_ID_SIZE, | 220 | packet + 1 + CLIENT_ID_SIZE, |
226 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, | 221 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, |
227 | sizeof(ping_id) + ENCRYPTION_PADDING, | 222 | sizeof(ping_id) + ENCRYPTION_PADDING, |
@@ -231,10 +226,97 @@ int handle_ping_response(void *object, IP_Port source, uint8_t *packet, uint32_t | |||
231 | return 1; | 226 | return 1; |
232 | 227 | ||
233 | /* Make sure ping_id is correct. */ | 228 | /* Make sure ping_id is correct. */ |
234 | if (!is_pinging(dht->ping, source, ping_id)) | 229 | if (!is_pinging(ping, source, ping_id)) |
235 | return 1; | 230 | return 1; |
236 | 231 | ||
237 | // Associate source ip with client_id | 232 | // Associate source ip with client_id |
238 | addto_lists(dht, source, packet + 1); | 233 | addto_lists(dht, source, packet + 1); |
239 | return 0; | 234 | return 0; |
240 | } | 235 | } |
236 | |||
237 | |||
238 | /* Add nodes to the toping list. | ||
239 | * All nodes in this list are pinged every TIME_TOPING seconds | ||
240 | * and are then removed from the list. | ||
241 | * If the list is full the nodes farthest from our client_id are replaced. | ||
242 | * The purpose of this list is to enable quick integration of new nodes into the | ||
243 | * network while preventing amplification attacks. | ||
244 | * | ||
245 | * return 0 if node was added. | ||
246 | * return -1 if node was not added. | ||
247 | */ | ||
248 | int add_toping(PING *ping, uint8_t *client_id, IP_Port ip_port) | ||
249 | { | ||
250 | if (!ip_isset(&ip_port.ip)) | ||
251 | return -1; | ||
252 | |||
253 | uint32_t i; | ||
254 | |||
255 | for (i = 0; i < MAX_TOPING; ++i) { | ||
256 | if (!ip_isset(&ping->toping[i].ip_port.ip)) { | ||
257 | memcpy(ping->toping[i].client_id, client_id, CLIENT_ID_SIZE); | ||
258 | ipport_copy(&ping->toping[i].ip_port, &ip_port); | ||
259 | return 0; | ||
260 | } | ||
261 | } | ||
262 | |||
263 | for (i = 0; i < MAX_TOPING; ++i) { | ||
264 | if (id_closest(ping->c->self_public_key, ping->toping[i].client_id, client_id) == 2) { | ||
265 | memcpy(ping->toping[i].client_id, client_id, CLIENT_ID_SIZE); | ||
266 | ipport_copy(&ping->toping[i].ip_port, &ip_port); | ||
267 | return 0; | ||
268 | } | ||
269 | } | ||
270 | |||
271 | return -1; | ||
272 | } | ||
273 | |||
274 | |||
275 | /* Ping all the valid nodes in the toping list every TIME_TOPING seconds. | ||
276 | * This function must be run at least once every TIME_TOPING seconds. | ||
277 | */ | ||
278 | static int is_timeout(uint64_t time_now, uint64_t timestamp, uint64_t timeout) | ||
279 | { | ||
280 | return timestamp + timeout <= time_now; | ||
281 | } | ||
282 | |||
283 | void do_toping(PING *ping) | ||
284 | { | ||
285 | uint64_t temp_time = unix_time(); | ||
286 | |||
287 | if (!is_timeout(temp_time, ping->last_toping, TIME_TOPING)) | ||
288 | return; | ||
289 | |||
290 | ping->last_toping = temp_time; | ||
291 | uint32_t i; | ||
292 | |||
293 | for (i = 0; i < MAX_TOPING; ++i) { | ||
294 | if (!ip_isset(&ping->toping[i].ip_port.ip)) | ||
295 | return; | ||
296 | |||
297 | send_ping_request(ping, ping->toping[i].ip_port, ping->toping[i].client_id); | ||
298 | ip_reset(&ping->toping[i].ip_port.ip); | ||
299 | } | ||
300 | } | ||
301 | |||
302 | |||
303 | PING *new_ping(DHT *dht, Net_Crypto *c) | ||
304 | { | ||
305 | PING *ping = calloc(1, sizeof(PING)); | ||
306 | if (ping == NULL) | ||
307 | return NULL; | ||
308 | |||
309 | ping->c = c; | ||
310 | networking_registerhandler(ping->c->lossless_udp->net, NET_PACKET_PING_REQUEST, &handle_ping_request, dht); | ||
311 | networking_registerhandler(ping->c->lossless_udp->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, dht); | ||
312 | |||
313 | return ping; | ||
314 | } | ||
315 | |||
316 | void kill_ping(PING *ping) | ||
317 | { | ||
318 | networking_registerhandler(ping->c->lossless_udp->net, NET_PACKET_PING_REQUEST, NULL, NULL); | ||
319 | networking_registerhandler(ping->c->lossless_udp->net, NET_PACKET_PING_RESPONSE, NULL, NULL); | ||
320 | |||
321 | free(ping); | ||
322 | } | ||
diff --git a/toxcore/ping.h b/toxcore/ping.h index 5d080e34..fabb1afd 100644 --- a/toxcore/ping.h +++ b/toxcore/ping.h | |||
@@ -4,14 +4,31 @@ | |||
4 | * This file is donated to the Tox Project. | 4 | * This file is donated to the Tox Project. |
5 | * Copyright 2013 plutooo | 5 | * Copyright 2013 plutooo |
6 | */ | 6 | */ |
7 | #ifndef __PING_H__ | ||
8 | #define __PING_H__ | ||
7 | 9 | ||
8 | #include <stdbool.h> | 10 | #include <stdbool.h> |
9 | 11 | ||
10 | void *new_ping(void); | 12 | #ifndef __PING_C__ |
11 | void kill_ping(void *ping); | 13 | typedef struct PING PING; |
12 | uint64_t add_ping(void *ping, IP_Port ipp); | 14 | #endif |
13 | bool is_pinging(void *ping, IP_Port ipp, uint64_t ping_id); | 15 | |
14 | int send_ping_request(void *ping, Net_Crypto *c, IP_Port ipp, uint8_t *client_id); | 16 | /* Add nodes to the toping list. |
15 | int send_ping_response(Net_Crypto *c, IP_Port ipp, uint8_t *client_id, uint64_t ping_id); | 17 | * All nodes in this list are pinged every TIME_TOPING seconds |
16 | int handle_ping_request(void *object, IP_Port source, uint8_t *packet, uint32_t length); | 18 | * and are then removed from the list. |
17 | int handle_ping_response(void *object, IP_Port source, uint8_t *packet, uint32_t length); | 19 | * If the list is full the nodes farthest from our client_id are replaced. |
20 | * The purpose of this list is to enable quick integration of new nodes into the | ||
21 | * network while preventing amplification attacks. | ||
22 | * | ||
23 | * return 0 if node was added. | ||
24 | * return -1 if node was not added. | ||
25 | */ | ||
26 | int add_toping(PING *ping, uint8_t *client_id, IP_Port ip_port); | ||
27 | void do_toping(PING *ping); | ||
28 | |||
29 | PING *new_ping(DHT *dht, Net_Crypto *c); | ||
30 | void kill_ping(PING *ping); | ||
31 | |||
32 | int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id); | ||
33 | |||
34 | #endif /* __PING_H__ */ | ||