mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
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()
This commit is contained in:
parent
20b6900fb1
commit
88678e584a
112
toxcore/DHT.c
112
toxcore/DHT.c
|
@ -56,9 +56,6 @@
|
||||||
/* Interval in seconds between punching attempts*/
|
/* Interval in seconds between punching attempts*/
|
||||||
#define PUNCH_INTERVAL 10
|
#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_REQUEST 0
|
||||||
#define NAT_PING_RESPONSE 1
|
#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 1 if client_id1 is closer.
|
||||||
* return 2 if client_id2 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;
|
size_t i;
|
||||||
uint8_t distance1, distance2;
|
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)
|
static int is_gettingnodes(DHT *dht, IP_Port ip_port, uint64_t ping_id)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
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)) {
|
if (!is_timeout(temp_time, dht->send_nodes[i].timestamp, PING_TIMEOUT)) {
|
||||||
pinging = 0;
|
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;
|
++pinging;
|
||||||
|
|
||||||
if (ip_isset(&ip_port.ip) && ipport_equal(&dht->send_nodes[i].ip_port, &ip_port))
|
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)) {
|
if (is_timeout(temp_time, dht->send_nodes[j].timestamp, PING_TIMEOUT - i)) {
|
||||||
dht->send_nodes[j].timestamp = temp_time;
|
dht->send_nodes[j].timestamp = temp_time;
|
||||||
dht->send_nodes[j].ip_port = ip_port;
|
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;
|
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);
|
addto_lists(dht, source, packet + 1);
|
||||||
|
|
||||||
for (i = 0; i < num_nodes; ++i) {
|
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);
|
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);
|
addto_lists(dht, source, packet + 1);
|
||||||
|
|
||||||
for (i = 0; i < num_nodes; ++i) {
|
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);
|
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 node is not dead. */
|
||||||
if (!is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, Kill_NODE_TIMEOUT)) {
|
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) {
|
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].client_id );
|
||||||
dht->friends_list[i].client_list[j].last_pinged = temp_time;
|
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 node is not dead. */
|
||||||
if (!is_timeout(temp_time, dht->close_clientlist[i].timestamp, Kill_NODE_TIMEOUT)) {
|
if (!is_timeout(temp_time, dht->close_clientlist[i].timestamp, Kill_NODE_TIMEOUT)) {
|
||||||
if ((dht->close_clientlist[i].last_pinged + PING_INTERVAL) <= temp_time) {
|
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].client_id );
|
||||||
dht->close_clientlist[i].last_pinged = temp_time;
|
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)
|
void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key)
|
||||||
{
|
{
|
||||||
getnodes(dht, ip_port, public_key, dht->c->self_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,
|
int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled,
|
||||||
uint16_t port, uint8_t *public_key)
|
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_Port pinging;
|
||||||
ip_copy(&pinging.ip, &ip);
|
ip_copy(&pinging.ip, &ip);
|
||||||
pinging.port = htons(port);
|
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;
|
dht->friends_list[friend_num].punching_index = i;
|
||||||
|
@ -1353,94 +1349,34 @@ static void do_NAT(DHT *dht)
|
||||||
/*----------------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------------*/
|
||||||
/*-----------------------END OF NAT PUNCHING FUNCTIONS------------------------------*/
|
/*-----------------------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)
|
DHT *new_DHT(Net_Crypto *c)
|
||||||
{
|
{
|
||||||
if (c == NULL)
|
if (c == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
DHT *temp = calloc(1, sizeof(DHT));
|
DHT *dht = calloc(1, sizeof(DHT));
|
||||||
|
|
||||||
if (temp == NULL)
|
if (dht == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
temp->ping = new_ping();
|
dht->ping = new_ping(dht, c);
|
||||||
|
|
||||||
if (temp->ping == NULL) {
|
if (dht->ping == NULL) {
|
||||||
kill_DHT(temp);
|
kill_DHT(dht);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
temp->c = c;
|
dht->c = c;
|
||||||
networking_registerhandler(c->lossless_udp->net, NET_PACKET_PING_REQUEST, &handle_ping_request, temp);
|
networking_registerhandler(c->lossless_udp->net, NET_PACKET_GET_NODES, &handle_getnodes, dht);
|
||||||
networking_registerhandler(c->lossless_udp->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, temp);
|
networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES, &handle_sendnodes, dht);
|
||||||
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);
|
|
||||||
#ifdef TOX_ENABLE_IPV6
|
#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
|
#endif
|
||||||
init_cryptopackets(temp);
|
|
||||||
cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, temp);
|
init_cryptopackets(dht);
|
||||||
return temp;
|
cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, dht);
|
||||||
|
|
||||||
|
return dht;
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_DHT(DHT *dht)
|
void do_DHT(DHT *dht)
|
||||||
|
@ -1448,7 +1384,7 @@ void do_DHT(DHT *dht)
|
||||||
do_Close(dht);
|
do_Close(dht);
|
||||||
do_DHT_friends(dht);
|
do_DHT_friends(dht);
|
||||||
do_NAT(dht);
|
do_NAT(dht);
|
||||||
do_toping(dht);
|
do_toping(dht->ping);
|
||||||
}
|
}
|
||||||
void kill_DHT(DHT *dht)
|
void kill_DHT(DHT *dht)
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
|
|
||||||
#include "net_crypto.h"
|
#include "net_crypto.h"
|
||||||
|
|
||||||
|
|
||||||
/* Size of the client_id in bytes. */
|
/* Size of the client_id in bytes. */
|
||||||
#define CLIENT_ID_SIZE crypto_box_PUBLICKEYBYTES
|
#define CLIENT_ID_SIZE crypto_box_PUBLICKEYBYTES
|
||||||
|
|
||||||
|
@ -92,22 +91,23 @@ typedef Node46_format Node_format;
|
||||||
typedef Node4_format Node_format;
|
typedef Node4_format Node_format;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
IP_Port ip_port;
|
IP_Port ip_port;
|
||||||
uint64_t ping_id;
|
uint64_t id;
|
||||||
uint64_t timestamp;
|
uint64_t timestamp;
|
||||||
} Pinged;
|
} pinged_t;
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------------*/
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Net_Crypto *c;
|
Net_Crypto *c;
|
||||||
|
|
||||||
Client_data close_clientlist[LCLIENT_LIST];
|
Client_data close_clientlist[LCLIENT_LIST];
|
||||||
DHT_Friend *friends_list;
|
DHT_Friend *friends_list;
|
||||||
uint16_t num_friends;
|
uint16_t num_friends;
|
||||||
Pinged send_nodes[LSEND_NODES_ARRAY];
|
|
||||||
Node_format toping[MAX_TOPING];
|
|
||||||
uint64_t last_toping;
|
|
||||||
uint64_t close_lastgetnodes;
|
uint64_t close_lastgetnodes;
|
||||||
|
|
||||||
|
pinged_t send_nodes[LSEND_NODES_ARRAY];
|
||||||
void *ping;
|
void *ping;
|
||||||
} DHT;
|
} 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);
|
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). */
|
/* Run this function at least a couple times per second (It's the main loop). */
|
||||||
void do_DHT(DHT *dht);
|
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,
|
int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled,
|
||||||
uint16_t port, uint8_t *public_key);
|
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 */
|
/* ROUTING FUNCTIONS */
|
||||||
|
|
||||||
|
|
|
@ -53,31 +53,6 @@ typedef struct {
|
||||||
|
|
||||||
} sendnodes_data;
|
} 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.
|
* check if peer with client_id is in peer array.
|
||||||
|
|
210
toxcore/ping.c
210
toxcore/ping.c
|
@ -12,53 +12,48 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "DHT.h"
|
|
||||||
#include "net_crypto.h"
|
#include "net_crypto.h"
|
||||||
#include "network.h"
|
#include "DHT.h"
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
#define PING_NUM_MAX 256
|
#define PING_NUM_MAX 256
|
||||||
#define PING_TIMEOUT 5 // 5s
|
#define PING_TIMEOUT 5 // 5s
|
||||||
|
|
||||||
typedef struct {
|
/* Ping newly announced nodes to ping per TIME_TOPING seconds*/
|
||||||
IP_Port ipp;
|
#define TIME_TOPING 5
|
||||||
uint64_t id;
|
|
||||||
uint64_t timestamp;
|
|
||||||
} pinged_t;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
Net_Crypto *c;
|
||||||
|
|
||||||
pinged_t pings[PING_NUM_MAX];
|
pinged_t pings[PING_NUM_MAX];
|
||||||
size_t num_pings;
|
size_t num_pings;
|
||||||
size_t pos_pings;
|
size_t pos_pings;
|
||||||
|
|
||||||
|
Node_format toping[MAX_TOPING];
|
||||||
|
uint64_t last_toping;
|
||||||
} PING;
|
} PING;
|
||||||
|
|
||||||
void *new_ping(void)
|
#define __PING_C__
|
||||||
{
|
|
||||||
return calloc(1, sizeof(PING));
|
|
||||||
}
|
|
||||||
|
|
||||||
void kill_ping(void *ping)
|
#include "network.h"
|
||||||
{
|
#include "util.h"
|
||||||
free(ping);
|
#include "ping.h"
|
||||||
}
|
|
||||||
|
|
||||||
static bool is_timeout(uint64_t time)
|
static bool is_ping_timeout(uint64_t time)
|
||||||
{
|
{
|
||||||
return (time + PING_TIMEOUT) < now();
|
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 i, id;
|
||||||
size_t new_pos = png->pos_pings;
|
size_t new_pos = ping->pos_pings;
|
||||||
size_t new_num = png->num_pings;
|
size_t new_num = ping->num_pings;
|
||||||
|
|
||||||
// Loop through buffer, oldest first.
|
// Loop through buffer, oldest first.
|
||||||
for (i = 0; i < png->num_pings; i++) {
|
for (i = 0; i < ping->num_pings; i++) {
|
||||||
id = (png->pos_pings + i) % PING_NUM_MAX;
|
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_pos++;
|
||||||
new_num--;
|
new_num--;
|
||||||
}
|
}
|
||||||
|
@ -68,37 +63,35 @@ static void remove_timeouts(void *ping) // O(n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
png->num_pings = new_num;
|
ping->num_pings = new_num;
|
||||||
png->pos_pings = new_pos % PING_NUM_MAX;
|
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;
|
size_t p;
|
||||||
|
|
||||||
remove_timeouts(ping);
|
remove_timeouts(ping);
|
||||||
|
|
||||||
/* Remove oldest ping if full buffer. */
|
/* Remove oldest ping if full buffer. */
|
||||||
if (png->num_pings == PING_NUM_MAX) {
|
if (ping->num_pings == PING_NUM_MAX) {
|
||||||
png->num_pings--;
|
ping->num_pings--;
|
||||||
png->pos_pings = (png->pos_pings + 1) % PING_NUM_MAX;
|
ping->pos_pings = (ping->pos_pings + 1) % PING_NUM_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Insert new ping at end of list. */
|
/* 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;
|
ping->pings[p].ip_port = ipp;
|
||||||
png->pings[p].timestamp = now();
|
ping->pings[p].timestamp = now();
|
||||||
png->pings[p].id = random_64b();
|
ping->pings[p].id = random_64b();
|
||||||
|
|
||||||
png->num_pings++;
|
ping->num_pings++;
|
||||||
return png->pings[p].id;
|
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 ? */
|
/* shouldn't that be an OR ? */
|
||||||
if (!ip_isset(&ipp.ip) && ping_id == 0)
|
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);
|
remove_timeouts(ping);
|
||||||
|
|
||||||
for (i = 0; i < png->num_pings; i++) {
|
for (i = 0; i < ping->num_pings; i++) {
|
||||||
id = (png->pos_pings + i) % PING_NUM_MAX;
|
id = (ping->pos_pings + i) % PING_NUM_MAX;
|
||||||
|
|
||||||
/* ping_id = 0 means match any id. */
|
/* ping_id = 0 means match any id. */
|
||||||
if ((!ip_isset(&ipp.ip) || ipport_equal(&png->pings[id].ipp, &ipp)) &&
|
if ((!ip_isset(&ipp.ip) || ipport_equal(&ping->pings[id].ip_port, &ipp)) &&
|
||||||
(png->pings[id].id == ping_id || ping_id == 0)) {
|
(ping->pings[id].id == ping_id || ping_id == 0)) {
|
||||||
return true;
|
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)
|
#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];
|
uint8_t pk[DHT_PING_SIZE];
|
||||||
int rc;
|
int rc;
|
||||||
uint64_t ping_id;
|
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;
|
return 1;
|
||||||
|
|
||||||
// Generate random ping_id.
|
// Generate random ping_id.
|
||||||
ping_id = add_ping(ping, ipp);
|
ping_id = add_ping(ping, ipp);
|
||||||
|
|
||||||
pk[0] = NET_PACKET_PING_REQUEST;
|
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
|
new_nonce(pk + 1 + CLIENT_ID_SIZE); // Generate new nonce
|
||||||
|
|
||||||
// Encrypt ping_id using recipient privkey
|
// Encrypt ping_id using recipient privkey
|
||||||
rc = encrypt_data(client_id,
|
rc = encrypt_data(client_id,
|
||||||
c->self_secret_key,
|
ping->c->self_secret_key,
|
||||||
pk + 1 + CLIENT_ID_SIZE,
|
pk + 1 + CLIENT_ID_SIZE,
|
||||||
(uint8_t *) &ping_id, sizeof(ping_id),
|
(uint8_t *) &ping_id, sizeof(ping_id),
|
||||||
pk + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES);
|
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)
|
if (rc != sizeof(ping_id) + ENCRYPTION_PADDING)
|
||||||
return 1;
|
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];
|
uint8_t pk[DHT_PING_SIZE];
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (id_eq(client_id, c->self_public_key))
|
if (id_eq(client_id, ping->c->self_public_key))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
pk[0] = NET_PACKET_PING_RESPONSE;
|
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
|
new_nonce(pk + 1 + CLIENT_ID_SIZE); // Generate new nonce
|
||||||
|
|
||||||
// Encrypt ping_id using recipient privkey
|
// Encrypt ping_id using recipient privkey
|
||||||
rc = encrypt_data(client_id,
|
rc = encrypt_data(client_id,
|
||||||
c->self_secret_key,
|
ping->c->self_secret_key,
|
||||||
pk + 1 + CLIENT_ID_SIZE,
|
pk + 1 + CLIENT_ID_SIZE,
|
||||||
(uint8_t *) &ping_id, sizeof(ping_id),
|
(uint8_t *) &ping_id, sizeof(ping_id),
|
||||||
pk + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES);
|
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)
|
if (rc != sizeof(ping_id) + ENCRYPTION_PADDING)
|
||||||
return 1;
|
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;
|
int rc;
|
||||||
uint64_t ping_id;
|
uint64_t ping_id;
|
||||||
|
|
||||||
if (length != DHT_PING_SIZE)
|
if (length != DHT_PING_SIZE)
|
||||||
return 1;
|
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;
|
return 1;
|
||||||
|
|
||||||
// Decrypt ping_id
|
// Decrypt ping_id
|
||||||
rc = decrypt_data(packet + 1,
|
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,
|
||||||
packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
|
packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
|
||||||
sizeof(ping_id) + ENCRYPTION_PADDING,
|
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;
|
return 1;
|
||||||
|
|
||||||
// Send response
|
// Send response
|
||||||
send_ping_response(dht->c, source, packet + 1, ping_id);
|
send_ping_response(ping, source, packet + 1, ping_id);
|
||||||
add_toping(dht, packet + 1, source);
|
add_toping(ping, packet + 1, source);
|
||||||
|
|
||||||
return 0;
|
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;
|
int rc;
|
||||||
uint64_t ping_id;
|
uint64_t ping_id;
|
||||||
|
|
||||||
if (length != DHT_PING_SIZE)
|
if (length != DHT_PING_SIZE)
|
||||||
return 1;
|
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;
|
return 1;
|
||||||
|
|
||||||
// Decrypt ping_id
|
// Decrypt ping_id
|
||||||
rc = decrypt_data(packet + 1,
|
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,
|
||||||
packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
|
packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
|
||||||
sizeof(ping_id) + ENCRYPTION_PADDING,
|
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;
|
return 1;
|
||||||
|
|
||||||
/* Make sure ping_id is correct. */
|
/* Make sure ping_id is correct. */
|
||||||
if (!is_pinging(dht->ping, source, ping_id))
|
if (!is_pinging(ping, source, ping_id))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
// Associate source ip with client_id
|
// Associate source ip with client_id
|
||||||
addto_lists(dht, source, packet + 1);
|
addto_lists(dht, source, packet + 1);
|
||||||
return 0;
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -4,14 +4,31 @@
|
||||||
* This file is donated to the Tox Project.
|
* This file is donated to the Tox Project.
|
||||||
* Copyright 2013 plutooo
|
* Copyright 2013 plutooo
|
||||||
*/
|
*/
|
||||||
|
#ifndef __PING_H__
|
||||||
|
#define __PING_H__
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
void *new_ping(void);
|
#ifndef __PING_C__
|
||||||
void kill_ping(void *ping);
|
typedef struct PING PING;
|
||||||
uint64_t add_ping(void *ping, IP_Port ipp);
|
#endif
|
||||||
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);
|
/* Add nodes to the toping list.
|
||||||
int send_ping_response(Net_Crypto *c, IP_Port ipp, uint8_t *client_id, uint64_t ping_id);
|
* All nodes in this list are pinged every TIME_TOPING seconds
|
||||||
int handle_ping_request(void *object, IP_Port source, uint8_t *packet, uint32_t length);
|
* and are then removed from the list.
|
||||||
int handle_ping_response(void *object, IP_Port source, uint8_t *packet, uint32_t length);
|
* 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__ */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user