diff --git a/CMakeLists.txt b/CMakeLists.txt index cda3bb06..9f164dad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -228,6 +228,7 @@ endif() # LAYER 3: Distributed Hash Table # ------------------------------- +apidsl(toxcore/ping_array.api.h) add_submodule(toxcore toxdht toxcore/DHT.c toxcore/DHT.h diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 1086ebc1..141ae533 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -1179,9 +1179,9 @@ static int getnodes(DHT *dht, IP_Port ip_port, const uint8_t *public_key, const if (sendback_node != NULL) { memcpy(plain_message + sizeof(receiver), sendback_node, sizeof(Node_format)); - ping_id = ping_array_add(&dht->dht_harden_ping_array, plain_message, sizeof(plain_message)); + ping_id = ping_array_add(dht->dht_harden_ping_array, plain_message, sizeof(plain_message)); } else { - ping_id = ping_array_add(&dht->dht_ping_array, plain_message, sizeof(receiver)); + ping_id = ping_array_add(dht->dht_ping_array, plain_message, sizeof(receiver)); } if (ping_id == 0) { @@ -1296,9 +1296,9 @@ static uint8_t sent_getnode_to_node(DHT *dht, const uint8_t *public_key, IP_Port { uint8_t data[sizeof(Node_format) * 2]; - if (ping_array_check(data, sizeof(data), &dht->dht_ping_array, ping_id) == sizeof(Node_format)) { + if (ping_array_check(dht->dht_ping_array, data, sizeof(data), ping_id) == sizeof(Node_format)) { memset(sendback_node, 0, sizeof(Node_format)); - } else if (ping_array_check(data, sizeof(data), &dht->dht_harden_ping_array, ping_id) == sizeof(data)) { + } else if (ping_array_check(dht->dht_harden_ping_array, data, sizeof(data), ping_id) == sizeof(data)) { memcpy(sendback_node, data + sizeof(Node_format), sizeof(Node_format)); } else { return 0; @@ -2578,8 +2578,8 @@ DHT *new_DHT(Logger *log, Networking_Core *net, bool holepunching_enabled) new_symmetric_key(dht->secret_symmetric_key); crypto_new_keypair(dht->self_public_key, dht->self_secret_key); - ping_array_init(&dht->dht_ping_array, DHT_PING_ARRAY_SIZE, PING_TIMEOUT); - ping_array_init(&dht->dht_harden_ping_array, DHT_PING_ARRAY_SIZE, PING_TIMEOUT); + dht->dht_ping_array = ping_array_new(DHT_PING_ARRAY_SIZE, PING_TIMEOUT); + dht->dht_harden_ping_array = ping_array_new(DHT_PING_ARRAY_SIZE, PING_TIMEOUT); for (uint32_t i = 0; i < DHT_FAKE_FRIEND_NUMBER; ++i) { uint8_t random_key_bytes[CRYPTO_PUBLIC_KEY_SIZE]; @@ -2622,8 +2622,8 @@ void kill_DHT(DHT *dht) networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, NULL, NULL); cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, NULL, NULL); cryptopacket_registerhandler(dht, CRYPTO_PACKET_HARDENING, NULL, NULL); - ping_array_free_all(&dht->dht_ping_array); - ping_array_free_all(&dht->dht_harden_ping_array); + ping_array_kill(dht->dht_ping_array); + ping_array_kill(dht->dht_harden_ping_array); kill_ping(dht->ping); free(dht->friends_list); free(dht->loaded_nodes_list); diff --git a/toxcore/DHT.h b/toxcore/DHT.h index 510b3c5c..dae6ea31 100644 --- a/toxcore/DHT.h +++ b/toxcore/DHT.h @@ -252,8 +252,8 @@ typedef struct { Shared_Keys shared_keys_sent; struct PING *ping; - Ping_Array dht_ping_array; - Ping_Array dht_harden_ping_array; + Ping_Array *dht_ping_array; + Ping_Array *dht_harden_ping_array; uint64_t last_run; Cryptopacket_Handles cryptopackethandlers[256]; diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 0d1191a6..1490d78d 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -397,7 +397,7 @@ static int new_sendback(Onion_Client *onion_c, uint32_t num, const uint8_t *publ memcpy(data + sizeof(uint32_t), public_key, CRYPTO_PUBLIC_KEY_SIZE); memcpy(data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, &ip_port, sizeof(IP_Port)); memcpy(data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port), &path_num, sizeof(uint32_t)); - *sendback = ping_array_add(&onion_c->announce_ping_array, data, sizeof(data)); + *sendback = ping_array_add(onion_c->announce_ping_array, data, sizeof(data)); if (*sendback == 0) { return -1; @@ -423,7 +423,7 @@ static uint32_t check_sendback(Onion_Client *onion_c, const uint8_t *sendback, u memcpy(&sback, sendback, sizeof(uint64_t)); uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port) + sizeof(uint32_t)]; - if (ping_array_check(data, sizeof(data), &onion_c->announce_ping_array, sback) != sizeof(data)) { + if (ping_array_check(onion_c->announce_ping_array, data, sizeof(data), sback) != sizeof(data)) { return ~0; } @@ -1733,7 +1733,9 @@ Onion_Client *new_onion_client(Net_Crypto *c) return NULL; } - if (ping_array_init(&onion_c->announce_ping_array, ANNOUNCE_ARRAY_SIZE, ANNOUNCE_TIMEOUT) != 0) { + onion_c->announce_ping_array = ping_array_new(ANNOUNCE_ARRAY_SIZE, ANNOUNCE_TIMEOUT); + + if (onion_c->announce_ping_array == NULL) { free(onion_c); return NULL; } @@ -1758,7 +1760,7 @@ void kill_onion_client(Onion_Client *onion_c) return; } - ping_array_free_all(&onion_c->announce_ping_array); + ping_array_kill(onion_c->announce_ping_array); realloc_onion_friends(onion_c, 0); networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, NULL, NULL); networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, NULL, NULL); diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h index 216dbec0..9acb9bac 100644 --- a/toxcore/onion_client.h +++ b/toxcore/onion_client.h @@ -162,7 +162,7 @@ typedef struct { Node_format path_nodes_bs[MAX_PATH_NODES]; uint16_t path_nodes_index_bs; - Ping_Array announce_ping_array; + Ping_Array *announce_ping_array; uint8_t last_pinged_index; struct { oniondata_handler_callback function; diff --git a/toxcore/ping.c b/toxcore/ping.c index 72b3fe62..b99c2a8c 100644 --- a/toxcore/ping.c +++ b/toxcore/ping.c @@ -48,7 +48,7 @@ struct PING { DHT *dht; - Ping_Array ping_array; + Ping_Array *ping_array; Node_format to_ping[MAX_TO_PING]; uint64_t last_to_ping; }; @@ -76,7 +76,7 @@ int send_ping_request(PING *ping, IP_Port ipp, const uint8_t *public_key) uint8_t data[PING_DATA_SIZE]; id_copy(data, public_key); memcpy(data + CRYPTO_PUBLIC_KEY_SIZE, &ipp, sizeof(IP_Port)); - ping_id = ping_array_add(&ping->ping_array, data, sizeof(data)); + ping_id = ping_array_add(ping->ping_array, data, sizeof(data)); if (ping_id == 0) { return 1; @@ -217,7 +217,7 @@ static int handle_ping_response(void *object, IP_Port source, const uint8_t *pac memcpy(&ping_id, ping_plain + 1, sizeof(ping_id)); uint8_t data[PING_DATA_SIZE]; - if (ping_array_check(data, sizeof(data), &ping->ping_array, ping_id) != sizeof(data)) { + if (ping_array_check(ping->ping_array, data, sizeof(data), ping_id) != sizeof(data)) { return 1; } @@ -359,7 +359,9 @@ PING *new_ping(DHT *dht) return NULL; } - if (ping_array_init(&ping->ping_array, PING_NUM_MAX, PING_TIMEOUT) != 0) { + ping->ping_array = ping_array_new(PING_NUM_MAX, PING_TIMEOUT); + + if (ping->ping_array == NULL) { free(ping); return NULL; } @@ -375,7 +377,7 @@ void kill_ping(PING *ping) { networking_registerhandler(ping->dht->net, NET_PACKET_PING_REQUEST, NULL, NULL); networking_registerhandler(ping->dht->net, NET_PACKET_PING_RESPONSE, NULL, NULL); - ping_array_free_all(&ping->ping_array); + ping_array_kill(ping->ping_array); free(ping); } diff --git a/toxcore/ping_array.api.h b/toxcore/ping_array.api.h new file mode 100644 index 00000000..55b80570 --- /dev/null +++ b/toxcore/ping_array.api.h @@ -0,0 +1,72 @@ +%{ +/* + * Implementation of an efficient array to store that we pinged something. + */ + +/* + * Copyright © 2016-2017 The TokTok team. + * Copyright © 2013 Tox project. + * + * This file is part of Tox, the free peer to peer instant messenger. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + */ +#ifndef PING_ARRAY_H +#define PING_ARRAY_H + +#include "network.h" +%} + +class ping_Array { + +struct this; + +/** + * Initialize a Ping_Array. + * size represents the total size of the array and should be a power of 2. + * timeout represents the maximum timeout in seconds for the entry. + * + * return 0 on success. + * return -1 on failure. + */ +static this new(uint32_t size, uint32_t timeout); + +/** + * Free all the allocated memory in a Ping_Array. + */ +void kill(); + +/** + * Add a data with length to the Ping_Array list and return a ping_id. + * + * return ping_id on success. + * return 0 on failure. + */ +uint64_t add(const uint8_t *data, uint32_t length); + +/** + * Check if ping_id is valid and not timed out. + * + * On success, copies the data into data of length, + * + * return length of data copied on success. + * return -1 on failure. + */ +int32_t check(uint8_t[length] data, uint64_t ping_id); + +} + +%{ +#endif +%} diff --git a/toxcore/ping_array.c b/toxcore/ping_array.c index ea3e5101..eafedc77 100644 --- a/toxcore/ping_array.c +++ b/toxcore/ping_array.c @@ -30,6 +30,55 @@ #include "crypto_core.h" #include "util.h" + +typedef struct { + void *data; + uint32_t length; + uint64_t time; + uint64_t ping_id; +} Ping_Array_Entry; + +struct Ping_Array { + Ping_Array_Entry *entries; + + uint32_t last_deleted; /* number representing the next entry to be deleted. */ + uint32_t last_added; /* number representing the last entry to be added. */ + uint32_t total_size; /* The length of entries */ + uint32_t timeout; /* The timeout after which entries are cleared. */ +}; + +/* Initialize a Ping_Array. + * size represents the total size of the array and should be a power of 2. + * timeout represents the maximum timeout in seconds for the entry. + * + * return 0 on success. + * return -1 on failure. + */ +Ping_Array *ping_array_new(uint32_t size, uint32_t timeout) +{ + if (size == 0 || timeout == 0) { + return NULL; + } + + Ping_Array *empty_array = (Ping_Array *)calloc(1, sizeof(Ping_Array)); + + if (empty_array == NULL) { + return NULL; + } + + empty_array->entries = (Ping_Array_Entry *)calloc(size, sizeof(Ping_Array_Entry)); + + if (empty_array->entries == NULL) { + free(empty_array); + return NULL; + } + + empty_array->last_deleted = empty_array->last_added = 0; + empty_array->total_size = size; + empty_array->timeout = timeout; + return empty_array; +} + static void clear_entry(Ping_Array *array, uint32_t index) { free(array->entries[index].data); @@ -39,6 +88,20 @@ static void clear_entry(Ping_Array *array, uint32_t index) array->entries[index].ping_id = 0; } +/* Free all the allocated memory in a Ping_Array. + */ +void ping_array_kill(Ping_Array *array) +{ + while (array->last_deleted != array->last_added) { + uint32_t index = array->last_deleted % array->total_size; + clear_entry(array, index); + ++array->last_deleted; + } + + free(array->entries); + free(array); +} + /* Clear timed out entries. */ static void ping_array_clear_timedout(Ping_Array *array) @@ -101,7 +164,7 @@ uint64_t ping_array_add(Ping_Array *array, const uint8_t *data, uint32_t length) * return length of data copied on success. * return -1 on failure. */ -int ping_array_check(uint8_t *data, uint32_t length, Ping_Array *array, uint64_t ping_id) +int32_t ping_array_check(Ping_Array *array, uint8_t *data, size_t length, uint64_t ping_id) { if (ping_id == 0) { return -1; @@ -130,43 +193,3 @@ int ping_array_check(uint8_t *data, uint32_t length, Ping_Array *array, uint64_t clear_entry(array, index); return len; } - -/* Initialize a Ping_Array. - * size represents the total size of the array and should be a power of 2. - * timeout represents the maximum timeout in seconds for the entry. - * - * return 0 on success. - * return -1 on failure. - */ -int ping_array_init(Ping_Array *empty_array, uint32_t size, uint32_t timeout) -{ - if (size == 0 || timeout == 0 || empty_array == NULL) { - return -1; - } - - empty_array->entries = (Ping_Array_Entry *)calloc(size, sizeof(Ping_Array_Entry)); - - if (empty_array->entries == NULL) { - return -1; - } - - empty_array->last_deleted = empty_array->last_added = 0; - empty_array->total_size = size; - empty_array->timeout = timeout; - return 0; -} - -/* Free all the allocated memory in a Ping_Array. - */ -void ping_array_free_all(Ping_Array *array) -{ - while (array->last_deleted != array->last_added) { - uint32_t index = array->last_deleted % array->total_size; - clear_entry(array, index); - ++array->last_deleted; - } - - free(array->entries); - array->entries = NULL; -} - diff --git a/toxcore/ping_array.h b/toxcore/ping_array.h index bdf3c6db..b927bbd4 100644 --- a/toxcore/ping_array.h +++ b/toxcore/ping_array.h @@ -26,51 +26,42 @@ #include "network.h" -typedef struct { - void *data; - uint32_t length; - uint64_t time; - uint64_t ping_id; -} Ping_Array_Entry; +#ifndef PING_ARRAY_DEFINED +#define PING_ARRAY_DEFINED +typedef struct Ping_Array Ping_Array; +#endif /* PING_ARRAY_DEFINED */ - -typedef struct { - Ping_Array_Entry *entries; - - uint32_t last_deleted; /* number representing the next entry to be deleted. */ - uint32_t last_added; /* number representing the last entry to be added. */ - uint32_t total_size; /* The length of entries */ - uint32_t timeout; /* The timeout after which entries are cleared. */ -} Ping_Array; - - -/* Add a data with length to the Ping_Array list and return a ping_id. - * - * return ping_id on success. - * return 0 on failure. - */ -uint64_t ping_array_add(Ping_Array *array, const uint8_t *data, uint32_t length); - -/* Check if ping_id is valid and not timed out. - * - * On success, copies the data into data of length, - * - * return length of data copied on success. - * return -1 on failure. - */ -int ping_array_check(uint8_t *data, uint32_t length, Ping_Array *array, uint64_t ping_id); - -/* Initialize a Ping_Array. +/** + * Initialize a Ping_Array. * size represents the total size of the array and should be a power of 2. * timeout represents the maximum timeout in seconds for the entry. * * return 0 on success. * return -1 on failure. */ -int ping_array_init(Ping_Array *empty_array, uint32_t size, uint32_t timeout); +struct Ping_Array *ping_array_new(uint32_t size, uint32_t timeout); -/* Free all the allocated memory in a Ping_Array. +/** + * Free all the allocated memory in a Ping_Array. */ -void ping_array_free_all(Ping_Array *array); +void ping_array_kill(struct Ping_Array *_array); + +/** + * Add a data with length to the Ping_Array list and return a ping_id. + * + * return ping_id on success. + * return 0 on failure. + */ +uint64_t ping_array_add(struct Ping_Array *_array, const uint8_t *data, uint32_t length); + +/** + * Check if ping_id is valid and not timed out. + * + * On success, copies the data into data of length, + * + * return length of data copied on success. + * return -1 on failure. + */ +int32_t ping_array_check(struct Ping_Array *_array, uint8_t *data, size_t length, uint64_t ping_id); #endif