From 88678e584aaf3956a0c88c80fa65efc505773f7d Mon Sep 17 00:00:00 2001 From: "Coren[m]" Date: Sat, 21 Sep 2013 15:39:15 +0200 Subject: [PATCH] moved stuff that belongs into ping.[ch] there DHT.*, ping.*: - moved stuff from struct DHT into struct PING: toping, last_toping - moved functions add_toping(), do_toping() - made id_closest() publicly accessible - send_ping_request(): killed (Net_Crypto *c) parameter in favor of copying it into (PING *) on new_ping() group_chats.c: - killed local 1:1 copy in favor of DHT.c::id_closest() --- toxcore/DHT.c | 112 +++++----------------- toxcore/DHT.h | 39 ++++---- toxcore/group_chats.c | 25 ----- toxcore/ping.c | 210 +++++++++++++++++++++++++++++------------- toxcore/ping.h | 33 +++++-- 5 files changed, 213 insertions(+), 206 deletions(-) diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 84c00c70..1761f50b 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -56,9 +56,6 @@ /* Interval in seconds between punching attempts*/ #define PUNCH_INTERVAL 10 -/* Ping newly announced nodes to ping per TIME_TOPING seconds*/ -#define TIME_TOPING 5 - #define NAT_PING_REQUEST 0 #define NAT_PING_RESPONSE 1 @@ -84,7 +81,7 @@ Client_data *DHT_get_close_list(DHT *dht) * return 1 if client_id1 is closer. * return 2 if client_id2 is closer. */ -static int id_closest(uint8_t *id, uint8_t *id1, uint8_t *id2) +int id_closest(uint8_t *id, uint8_t *id1, uint8_t *id2) { size_t i; uint8_t distance1, distance2; @@ -443,7 +440,6 @@ static void returnedip_ports(DHT *dht, IP_Port ip_port, uint8_t *client_id, uint } } -/* Same as last function but for get_node requests. */ static int is_gettingnodes(DHT *dht, IP_Port ip_port, uint64_t ping_id) { uint32_t i; @@ -454,7 +450,7 @@ static int is_gettingnodes(DHT *dht, IP_Port ip_port, uint64_t ping_id) if (!is_timeout(temp_time, dht->send_nodes[i].timestamp, PING_TIMEOUT)) { pinging = 0; - if (ping_id != 0 && dht->send_nodes[i].ping_id == ping_id) + if (ping_id != 0 && dht->send_nodes[i].id == ping_id) ++pinging; if (ip_isset(&ip_port.ip) && ipport_equal(&dht->send_nodes[i].ip_port, &ip_port)) @@ -480,7 +476,7 @@ static uint64_t add_gettingnodes(DHT *dht, IP_Port ip_port) if (is_timeout(temp_time, dht->send_nodes[j].timestamp, PING_TIMEOUT - i)) { dht->send_nodes[j].timestamp = temp_time; dht->send_nodes[j].ip_port = ip_port; - dht->send_nodes[j].ping_id = ping_id; + dht->send_nodes[j].id = ping_id; return ping_id; } } @@ -751,7 +747,7 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3 addto_lists(dht, source, packet + 1); for (i = 0; i < num_nodes; ++i) { - send_ping_request(dht->ping, dht->c, nodes_list[i].ip_port, nodes_list[i].client_id); + send_ping_request(dht->ping, nodes_list[i].ip_port, nodes_list[i].client_id); returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1); } @@ -798,7 +794,7 @@ static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, addto_lists(dht, source, packet + 1); for (i = 0; i < num_nodes; ++i) { - send_ping_request(dht->ping, dht->c, nodes_list[i].ip_port, nodes_list[i].client_id); + send_ping_request(dht->ping, nodes_list[i].ip_port, nodes_list[i].client_id); returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1); } @@ -927,7 +923,7 @@ static void do_DHT_friends(DHT *dht) /* If node is not dead. */ if (!is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, Kill_NODE_TIMEOUT)) { if ((dht->friends_list[i].client_list[j].last_pinged + PING_INTERVAL) <= temp_time) { - send_ping_request(dht->ping, dht->c, dht->friends_list[i].client_list[j].ip_port, + send_ping_request(dht->ping, dht->friends_list[i].client_list[j].ip_port, dht->friends_list[i].client_list[j].client_id ); dht->friends_list[i].client_list[j].last_pinged = temp_time; } @@ -965,7 +961,7 @@ static void do_Close(DHT *dht) /* If node is not dead. */ if (!is_timeout(temp_time, dht->close_clientlist[i].timestamp, Kill_NODE_TIMEOUT)) { if ((dht->close_clientlist[i].last_pinged + PING_INTERVAL) <= temp_time) { - send_ping_request(dht->ping, dht->c, dht->close_clientlist[i].ip_port, + send_ping_request(dht->ping, dht->close_clientlist[i].ip_port, dht->close_clientlist[i].client_id ); dht->close_clientlist[i].last_pinged = temp_time; } @@ -990,7 +986,7 @@ static void do_Close(DHT *dht) void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key) { getnodes(dht, ip_port, public_key, dht->c->self_public_key); - send_ping_request(dht->ping, dht->c, ip_port, public_key); + send_ping_request(dht->ping, ip_port, public_key); } int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled, uint16_t port, uint8_t *public_key) @@ -1307,7 +1303,7 @@ static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports, IP_Port pinging; ip_copy(&pinging.ip, &ip); pinging.port = htons(port); - send_ping_request(dht->ping, dht->c, pinging, dht->friends_list[friend_num].client_id); + send_ping_request(dht->ping, pinging, dht->friends_list[friend_num].client_id); } dht->friends_list[friend_num].punching_index = i; @@ -1353,94 +1349,34 @@ static void do_NAT(DHT *dht) /*----------------------------------------------------------------------------------*/ /*-----------------------END OF NAT PUNCHING FUNCTIONS------------------------------*/ - -/* Add nodes to the toping list. - * All nodes in this list are pinged every TIME_TOPING seconds - * and are then removed from the list. - * If the list is full the nodes farthest from our client_id are replaced. - * The purpose of this list is to enable quick integration of new nodes into the - * network while preventing amplification attacks. - * - * return 0 if node was added. - * return -1 if node was not added. - */ -int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port) -{ - if (!ip_isset(&ip_port.ip)) - return -1; - - uint32_t i; - - for (i = 0; i < MAX_TOPING; ++i) { - if (!ip_isset(&dht->toping[i].ip_port.ip)) { - memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); - ipport_copy(&dht->toping[i].ip_port, &ip_port); - return 0; - } - } - - for (i = 0; i < MAX_TOPING; ++i) { - if (id_closest(dht->c->self_public_key, dht->toping[i].client_id, client_id) == 2) { - memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); - ipport_copy(&dht->toping[i].ip_port, &ip_port); - return 0; - } - } - - return -1; -} - -/* Ping all the valid nodes in the toping list every TIME_TOPING seconds. - * This function must be run at least once every TIME_TOPING seconds. - */ -static void do_toping(DHT *dht) -{ - uint64_t temp_time = unix_time(); - - if (!is_timeout(temp_time, dht->last_toping, TIME_TOPING)) - return; - - dht->last_toping = temp_time; - uint32_t i; - - for (i = 0; i < MAX_TOPING; ++i) { - if (!ip_isset(&dht->toping[i].ip_port.ip)) - return; - - send_ping_request(dht->ping, dht->c, dht->toping[i].ip_port, dht->toping[i].client_id); - ip_reset(&dht->toping[i].ip_port.ip); - } -} - - DHT *new_DHT(Net_Crypto *c) { if (c == NULL) return NULL; - DHT *temp = calloc(1, sizeof(DHT)); + DHT *dht = calloc(1, sizeof(DHT)); - if (temp == NULL) + if (dht == NULL) return NULL; - temp->ping = new_ping(); + dht->ping = new_ping(dht, c); - if (temp->ping == NULL) { - kill_DHT(temp); + if (dht->ping == NULL) { + kill_DHT(dht); return NULL; } - temp->c = c; - networking_registerhandler(c->lossless_udp->net, NET_PACKET_PING_REQUEST, &handle_ping_request, temp); - networking_registerhandler(c->lossless_udp->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, temp); - networking_registerhandler(c->lossless_udp->net, NET_PACKET_GET_NODES, &handle_getnodes, temp); - networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES, &handle_sendnodes, temp); + dht->c = c; + networking_registerhandler(c->lossless_udp->net, NET_PACKET_GET_NODES, &handle_getnodes, dht); + networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES, &handle_sendnodes, dht); #ifdef TOX_ENABLE_IPV6 - networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, temp); + networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, dht); #endif - init_cryptopackets(temp); - cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, temp); - return temp; + + init_cryptopackets(dht); + cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, dht); + + return dht; } void do_DHT(DHT *dht) @@ -1448,7 +1384,7 @@ void do_DHT(DHT *dht) do_Close(dht); do_DHT_friends(dht); do_NAT(dht); - do_toping(dht); + do_toping(dht->ping); } void kill_DHT(DHT *dht) { 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 @@ #include "net_crypto.h" - /* Size of the client_id in bytes. */ #define CLIENT_ID_SIZE crypto_box_PUBLICKEYBYTES @@ -92,22 +91,23 @@ typedef Node46_format Node_format; typedef Node4_format Node_format; #endif -typedef struct { - IP_Port ip_port; - uint64_t ping_id; - uint64_t timestamp; -} Pinged; - /*----------------------------------------------------------------------------------*/ + +typedef struct { + IP_Port ip_port; + uint64_t id; + uint64_t timestamp; +} pinged_t; + typedef struct { Net_Crypto *c; + Client_data close_clientlist[LCLIENT_LIST]; DHT_Friend *friends_list; uint16_t num_friends; - Pinged send_nodes[LSEND_NODES_ARRAY]; - Node_format toping[MAX_TOPING]; - uint64_t last_toping; uint64_t close_lastgetnodes; + + pinged_t send_nodes[LSEND_NODES_ARRAY]; void *ping; } DHT; /*----------------------------------------------------------------------------------*/ @@ -152,6 +152,14 @@ int DHT_delfriend(DHT *dht, uint8_t *client_id); */ int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port); +/* Compares client_id1 and client_id2 with client_id. + * + * return 0 if both are same distance. + * return 1 if client_id1 is closer. + * return 2 if client_id2 is closer. + */ +int id_closest(uint8_t *id, uint8_t *id1, uint8_t *id2); + /* Run this function at least a couple times per second (It's the main loop). */ void do_DHT(DHT *dht); @@ -176,17 +184,6 @@ void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key); int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled, uint16_t port, uint8_t *public_key); -/* Add nodes to the toping list. - * All nodes in this list are pinged every TIME_TOPING seconds - * and are then removed from the list. - * If the list is full the nodes farthest from our client_id are replaced. - * The purpose of this list is to enable quick integration of new nodes into the - * network while preventing amplification attacks. - * - * return 0 if node was added. - * return -1 if node was not added. - */ -int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port); /* ROUTING FUNCTIONS */ 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 { } sendnodes_data; -/* Compares client_id1 and client_id2 with client_id - * return 0 if both are same distance - * return 1 if client_id1 is closer - * return 2 if client_id2 is closer - */ -static int id_closest(uint8_t *id, uint8_t *id1, uint8_t *id2) -{ - size_t i; - uint8_t distance1, distance2; - - for (i = 0; i < CLIENT_ID_SIZE; ++i) { - - distance1 = abs(((int8_t *)id)[i] ^ ((int8_t *)id1)[i]); - distance2 = abs(((int8_t *)id)[i] ^ ((int8_t *)id2)[i]); - - if (distance1 < distance2) - return 1; - - if (distance1 > distance2) - return 2; - } - - return 0; -} - /* * 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 @@ #include #include -#include "DHT.h" #include "net_crypto.h" -#include "network.h" -#include "util.h" +#include "DHT.h" #define PING_NUM_MAX 256 #define PING_TIMEOUT 5 // 5s -typedef struct { - IP_Port ipp; - uint64_t id; - uint64_t timestamp; -} pinged_t; +/* Ping newly announced nodes to ping per TIME_TOPING seconds*/ +#define TIME_TOPING 5 typedef struct { + Net_Crypto *c; + pinged_t pings[PING_NUM_MAX]; size_t num_pings; size_t pos_pings; + + Node_format toping[MAX_TOPING]; + uint64_t last_toping; } PING; -void *new_ping(void) -{ - return calloc(1, sizeof(PING)); -} +#define __PING_C__ -void kill_ping(void *ping) -{ - free(ping); -} +#include "network.h" +#include "util.h" +#include "ping.h" -static bool is_timeout(uint64_t time) +static bool is_ping_timeout(uint64_t time) { return (time + PING_TIMEOUT) < now(); } -static void remove_timeouts(void *ping) // O(n) +static void remove_timeouts(PING *ping) // O(n) { - PING *png = ping; size_t i, id; - size_t new_pos = png->pos_pings; - size_t new_num = png->num_pings; + size_t new_pos = ping->pos_pings; + size_t new_num = ping->num_pings; // Loop through buffer, oldest first. - for (i = 0; i < png->num_pings; i++) { - id = (png->pos_pings + i) % PING_NUM_MAX; + for (i = 0; i < ping->num_pings; i++) { + id = (ping->pos_pings + i) % PING_NUM_MAX; - if (is_timeout(png->pings[id].timestamp)) { + if (is_ping_timeout(ping->pings[id].timestamp)) { new_pos++; new_num--; } @@ -68,37 +63,35 @@ static void remove_timeouts(void *ping) // O(n) } } - png->num_pings = new_num; - png->pos_pings = new_pos % PING_NUM_MAX; + ping->num_pings = new_num; + ping->pos_pings = new_pos % PING_NUM_MAX; } -uint64_t add_ping(void *ping, IP_Port ipp) // O(n) +static uint64_t add_ping(PING *ping, IP_Port ipp) // O(n) { - PING *png = ping; size_t p; remove_timeouts(ping); /* Remove oldest ping if full buffer. */ - if (png->num_pings == PING_NUM_MAX) { - png->num_pings--; - png->pos_pings = (png->pos_pings + 1) % PING_NUM_MAX; + if (ping->num_pings == PING_NUM_MAX) { + ping->num_pings--; + ping->pos_pings = (ping->pos_pings + 1) % PING_NUM_MAX; } /* Insert new ping at end of list. */ - p = (png->pos_pings + png->num_pings) % PING_NUM_MAX; + p = (ping->pos_pings + ping->num_pings) % PING_NUM_MAX; - png->pings[p].ipp = ipp; - png->pings[p].timestamp = now(); - png->pings[p].id = random_64b(); + ping->pings[p].ip_port = ipp; + ping->pings[p].timestamp = now(); + ping->pings[p].id = random_64b(); - png->num_pings++; - return png->pings[p].id; + ping->num_pings++; + return ping->pings[p].id; } -bool is_pinging(void *ping, IP_Port ipp, uint64_t ping_id) // O(n) TODO: Replace this with something else. +static bool is_pinging(PING *ping, IP_Port ipp, uint64_t ping_id) // O(n) TODO: Replace this with something else. { - PING *png = ping; /* shouldn't that be an OR ? */ 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 remove_timeouts(ping); - for (i = 0; i < png->num_pings; i++) { - id = (png->pos_pings + i) % PING_NUM_MAX; + for (i = 0; i < ping->num_pings; i++) { + id = (ping->pos_pings + i) % PING_NUM_MAX; /* ping_id = 0 means match any id. */ - if ((!ip_isset(&ipp.ip) || ipport_equal(&png->pings[id].ipp, &ipp)) && - (png->pings[id].id == ping_id || ping_id == 0)) { + if ((!ip_isset(&ipp.ip) || ipport_equal(&ping->pings[id].ip_port, &ipp)) && + (ping->pings[id].id == ping_id || ping_id == 0)) { return true; } } @@ -123,25 +116,25 @@ bool is_pinging(void *ping, IP_Port ipp, uint64_t ping_id) // O(n) TODO: Repl #define DHT_PING_SIZE (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(uint64_t) + ENCRYPTION_PADDING) -int send_ping_request(void *ping, Net_Crypto *c, IP_Port ipp, uint8_t *client_id) +int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id) { uint8_t pk[DHT_PING_SIZE]; int rc; uint64_t ping_id; - if (is_pinging(ping, ipp, 0) || id_eq(client_id, c->self_public_key)) + if (is_pinging(ping, ipp, 0) || id_eq(client_id, ping->c->self_public_key)) return 1; // Generate random ping_id. ping_id = add_ping(ping, ipp); pk[0] = NET_PACKET_PING_REQUEST; - id_cpy(pk + 1, c->self_public_key); // Our pubkey + id_cpy(pk + 1, ping->c->self_public_key); // Our pubkey new_nonce(pk + 1 + CLIENT_ID_SIZE); // Generate new nonce // Encrypt ping_id using recipient privkey rc = encrypt_data(client_id, - c->self_secret_key, + ping->c->self_secret_key, pk + 1 + CLIENT_ID_SIZE, (uint8_t *) &ping_id, sizeof(ping_id), 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 if (rc != sizeof(ping_id) + ENCRYPTION_PADDING) return 1; - return sendpacket(c->lossless_udp->net, ipp, pk, sizeof(pk)); + return sendpacket(ping->c->lossless_udp->net, ipp, pk, sizeof(pk)); } -int send_ping_response(Net_Crypto *c, IP_Port ipp, uint8_t *client_id, uint64_t ping_id) +static int send_ping_response(PING *ping, IP_Port ipp, uint8_t *client_id, uint64_t ping_id) { uint8_t pk[DHT_PING_SIZE]; int rc; - if (id_eq(client_id, c->self_public_key)) + if (id_eq(client_id, ping->c->self_public_key)) return 1; pk[0] = NET_PACKET_PING_RESPONSE; - id_cpy(pk + 1, c->self_public_key); // Our pubkey + id_cpy(pk + 1, ping->c->self_public_key); // Our pubkey new_nonce(pk + 1 + CLIENT_ID_SIZE); // Generate new nonce // Encrypt ping_id using recipient privkey rc = encrypt_data(client_id, - c->self_secret_key, + ping->c->self_secret_key, pk + 1 + CLIENT_ID_SIZE, (uint8_t *) &ping_id, sizeof(ping_id), 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 if (rc != sizeof(ping_id) + ENCRYPTION_PADDING) return 1; - return sendpacket(c->lossless_udp->net, ipp, pk, sizeof(pk)); + return sendpacket(ping->c->lossless_udp->net, ipp, pk, sizeof(pk)); } -int handle_ping_request(void *object, IP_Port source, uint8_t *packet, uint32_t length) +static int handle_ping_request(void *_dht, IP_Port source, uint8_t *packet, uint32_t length) { - DHT *dht = object; + DHT *dht = _dht; int rc; uint64_t ping_id; if (length != DHT_PING_SIZE) return 1; - if (id_eq(packet + 1, dht->c->self_public_key)) + PING *ping = dht->ping; + if (id_eq(packet + 1, ping->c->self_public_key)) return 1; // Decrypt ping_id rc = decrypt_data(packet + 1, - dht->c->self_secret_key, + ping->c->self_secret_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, sizeof(ping_id) + ENCRYPTION_PADDING, @@ -201,27 +195,28 @@ int handle_ping_request(void *object, IP_Port source, uint8_t *packet, uint32_t return 1; // Send response - send_ping_response(dht->c, source, packet + 1, ping_id); - add_toping(dht, packet + 1, source); + send_ping_response(ping, source, packet + 1, ping_id); + add_toping(ping, packet + 1, source); return 0; } -int handle_ping_response(void *object, IP_Port source, uint8_t *packet, uint32_t length) +static int handle_ping_response(void *_dht, IP_Port source, uint8_t *packet, uint32_t length) { - DHT *dht = object; + DHT *dht = _dht; int rc; uint64_t ping_id; if (length != DHT_PING_SIZE) return 1; - if (id_eq(packet + 1, dht->c->self_public_key)) + PING *ping = dht->ping; + if (id_eq(packet + 1, ping->c->self_public_key)) return 1; // Decrypt ping_id rc = decrypt_data(packet + 1, - dht->c->self_secret_key, + ping->c->self_secret_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, sizeof(ping_id) + ENCRYPTION_PADDING, @@ -231,10 +226,97 @@ int handle_ping_response(void *object, IP_Port source, uint8_t *packet, uint32_t return 1; /* Make sure ping_id is correct. */ - if (!is_pinging(dht->ping, source, ping_id)) + if (!is_pinging(ping, source, ping_id)) return 1; // Associate source ip with client_id addto_lists(dht, source, packet + 1); return 0; } + + +/* Add nodes to the toping list. + * All nodes in this list are pinged every TIME_TOPING seconds + * and are then removed from the list. + * If the list is full the nodes farthest from our client_id are replaced. + * The purpose of this list is to enable quick integration of new nodes into the + * network while preventing amplification attacks. + * + * return 0 if node was added. + * return -1 if node was not added. + */ +int add_toping(PING *ping, uint8_t *client_id, IP_Port ip_port) +{ + if (!ip_isset(&ip_port.ip)) + return -1; + + uint32_t i; + + for (i = 0; i < MAX_TOPING; ++i) { + if (!ip_isset(&ping->toping[i].ip_port.ip)) { + memcpy(ping->toping[i].client_id, client_id, CLIENT_ID_SIZE); + ipport_copy(&ping->toping[i].ip_port, &ip_port); + return 0; + } + } + + for (i = 0; i < MAX_TOPING; ++i) { + if (id_closest(ping->c->self_public_key, ping->toping[i].client_id, client_id) == 2) { + memcpy(ping->toping[i].client_id, client_id, CLIENT_ID_SIZE); + ipport_copy(&ping->toping[i].ip_port, &ip_port); + return 0; + } + } + + return -1; +} + + +/* Ping all the valid nodes in the toping list every TIME_TOPING seconds. + * This function must be run at least once every TIME_TOPING seconds. + */ +static int is_timeout(uint64_t time_now, uint64_t timestamp, uint64_t timeout) +{ + return timestamp + timeout <= time_now; +} + +void do_toping(PING *ping) +{ + uint64_t temp_time = unix_time(); + + if (!is_timeout(temp_time, ping->last_toping, TIME_TOPING)) + return; + + ping->last_toping = temp_time; + uint32_t i; + + for (i = 0; i < MAX_TOPING; ++i) { + if (!ip_isset(&ping->toping[i].ip_port.ip)) + return; + + send_ping_request(ping, ping->toping[i].ip_port, ping->toping[i].client_id); + ip_reset(&ping->toping[i].ip_port.ip); + } +} + + +PING *new_ping(DHT *dht, Net_Crypto *c) +{ + PING *ping = calloc(1, sizeof(PING)); + if (ping == NULL) + return NULL; + + ping->c = c; + networking_registerhandler(ping->c->lossless_udp->net, NET_PACKET_PING_REQUEST, &handle_ping_request, dht); + networking_registerhandler(ping->c->lossless_udp->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, dht); + + return ping; +} + +void kill_ping(PING *ping) +{ + networking_registerhandler(ping->c->lossless_udp->net, NET_PACKET_PING_REQUEST, NULL, NULL); + networking_registerhandler(ping->c->lossless_udp->net, NET_PACKET_PING_RESPONSE, NULL, NULL); + + free(ping); +} 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 @@ * This file is donated to the Tox Project. * Copyright 2013 plutooo */ +#ifndef __PING_H__ +#define __PING_H__ #include -void *new_ping(void); -void kill_ping(void *ping); -uint64_t add_ping(void *ping, IP_Port ipp); -bool is_pinging(void *ping, IP_Port ipp, uint64_t ping_id); -int send_ping_request(void *ping, Net_Crypto *c, IP_Port ipp, uint8_t *client_id); -int send_ping_response(Net_Crypto *c, IP_Port ipp, uint8_t *client_id, uint64_t ping_id); -int handle_ping_request(void *object, IP_Port source, uint8_t *packet, uint32_t length); -int handle_ping_response(void *object, IP_Port source, uint8_t *packet, uint32_t length); +#ifndef __PING_C__ +typedef struct PING PING; +#endif + +/* Add nodes to the toping list. + * All nodes in this list are pinged every TIME_TOPING seconds + * and are then removed from the list. + * If the list is full the nodes farthest from our client_id are replaced. + * The purpose of this list is to enable quick integration of new nodes into the + * network while preventing amplification attacks. + * + * return 0 if node was added. + * return -1 if node was not added. + */ +int add_toping(PING *ping, uint8_t *client_id, IP_Port ip_port); +void do_toping(PING *ping); + +PING *new_ping(DHT *dht, Net_Crypto *c); +void kill_ping(PING *ping); + +int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id); + +#endif /* __PING_H__ */