diff options
Diffstat (limited to 'protocols/Tox/libtox/src')
147 files changed, 5842 insertions, 3502 deletions
diff --git a/protocols/Tox/libtox/src/third_party/cmp/cmp.c b/protocols/Tox/libtox/src/third_party/cmp/cmp.c index c312efd6c7..c11d23a8a3 100644 --- a/protocols/Tox/libtox/src/third_party/cmp/cmp.c +++ b/protocols/Tox/libtox/src/third_party/cmp/cmp.c @@ -865,7 +865,7 @@ bool cmp_write_pfix(cmp_ctx_t *ctx, uint8_t c) { } bool cmp_write_nfix(cmp_ctx_t *ctx, int8_t c) { - if (c >= -32 && c <= -1) + if (c >= -0x20 && c <= -1) return write_fixed_value(ctx, (uint8_t)c); ctx->error = CMP_ERROR_INPUT_VALUE_TOO_LARGE; @@ -875,7 +875,7 @@ bool cmp_write_nfix(cmp_ctx_t *ctx, int8_t c) { bool cmp_write_sfix(cmp_ctx_t *ctx, int8_t c) { if (c >= 0) return cmp_write_pfix(ctx, (uint8_t)c); - if (c >= -32 && c <= -1) + if (c >= -0x20 && c <= -1) return cmp_write_nfix(ctx, c); ctx->error = CMP_ERROR_INPUT_VALUE_TOO_LARGE; diff --git a/protocols/Tox/libtox/src/toxcore/DHT.c b/protocols/Tox/libtox/src/toxcore/DHT.c index 2567d1b5a8..0dc49008e4 100644 --- a/protocols/Tox/libtox/src/toxcore/DHT.c +++ b/protocols/Tox/libtox/src/toxcore/DHT.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ @@ -9,7 +9,6 @@ #include "DHT.h" #include <assert.h> -#include <stdlib.h> #include <string.h> #include "LAN_discovery.h" @@ -24,13 +23,15 @@ #include "ping.h" #include "ping_array.h" #include "shared_key_cache.h" +#include "sort.h" #include "state.h" +#include "util.h" /** The timeout after which a node is discarded completely. */ #define KILL_NODE_TIMEOUT (BAD_NODE_TIMEOUT + PING_INTERVAL) -/** Ping interval in seconds for each random sending of a get nodes request. */ -#define GET_NODE_INTERVAL 20 +/** Ping interval in seconds for each random sending of a nodes request. */ +#define NODES_REQUEST_INTERVAL 20 #define MAX_PUNCHING_PORTS 48 @@ -45,7 +46,7 @@ #define NAT_PING_REQUEST 0 #define NAT_PING_RESPONSE 1 -/** Number of get node requests to send to quickly find close nodes. */ +/** Number of node requests to send to quickly find close nodes. */ #define MAX_BOOTSTRAP_TIMES 5 // TODO(sudden6): find out why we need multiple callbacks and if we really need 32 @@ -65,9 +66,9 @@ struct DHT_Friend { uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; Client_data client_list[MAX_FRIEND_CLIENTS]; - /* Time at which the last get_nodes request was sent. */ - uint64_t lastgetnode; - /* number of times get_node packets were sent. */ + /* Time at which the last nodes request was sent. */ + uint64_t last_nodes_request; + /* number of times nodes request packets were sent. */ uint32_t bootstrap_times; /* Symmetric NAT hole punching stuff. */ @@ -103,7 +104,7 @@ struct DHT { bool lan_discovery_enabled; Client_data close_clientlist[LCLIENT_LIST]; - uint64_t close_lastgetnodes; + uint64_t close_last_nodes_request; uint32_t close_bootstrap_times; /* DHT keypair */ @@ -129,7 +130,7 @@ struct DHT { Node_format to_bootstrap[MAX_CLOSE_TO_BOOTSTRAP_NODES]; unsigned int num_to_bootstrap; - dht_get_nodes_response_cb *get_nodes_response; + dht_nodes_response_cb *nodes_response_callback; }; const uint8_t *dht_friend_public_key(const DHT_Friend *dht_friend) @@ -279,7 +280,7 @@ const uint8_t *dht_get_shared_key_sent(DHT *dht, const uint8_t *public_key) #define CRYPTO_SIZE (1 + CRYPTO_PUBLIC_KEY_SIZE * 2 + CRYPTO_NONCE_SIZE) -int create_request(const Random *rng, const uint8_t *send_public_key, const uint8_t *send_secret_key, +int create_request(const Memory *mem, const Random *rng, const uint8_t *send_public_key, const uint8_t *send_secret_key, uint8_t *packet, const uint8_t *recv_public_key, const uint8_t *data, uint32_t data_length, uint8_t request_id) { @@ -296,7 +297,7 @@ int create_request(const Random *rng, const uint8_t *send_public_key, const uint uint8_t temp[MAX_CRYPTO_REQUEST_SIZE] = {0}; temp[0] = request_id; memcpy(temp + 1, data, data_length); - const int len = encrypt_data(recv_public_key, send_secret_key, nonce, temp, data_length + 1, + const int len = encrypt_data(mem, recv_public_key, send_secret_key, nonce, temp, data_length + 1, packet + CRYPTO_SIZE); if (len == -1) { @@ -312,7 +313,7 @@ int create_request(const Random *rng, const uint8_t *send_public_key, const uint return len + CRYPTO_SIZE; } -int handle_request(const uint8_t *self_public_key, const uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data, +int handle_request(const Memory *mem, const uint8_t *self_public_key, const uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data, uint8_t *request_id, const uint8_t *packet, uint16_t packet_length) { if (self_public_key == nullptr || public_key == nullptr || data == nullptr || request_id == nullptr @@ -331,7 +332,7 @@ int handle_request(const uint8_t *self_public_key, const uint8_t *self_secret_ke memcpy(public_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_PUBLIC_KEY_SIZE); const uint8_t *const nonce = packet + 1 + CRYPTO_PUBLIC_KEY_SIZE * 2; uint8_t temp[MAX_CRYPTO_REQUEST_SIZE]; - int32_t len1 = decrypt_data(public_key, self_secret_key, nonce, + int32_t len1 = decrypt_data(mem, public_key, self_secret_key, nonce, packet + CRYPTO_SIZE, packet_length - CRYPTO_SIZE, temp); if (len1 == -1 || len1 == 0) { @@ -378,14 +379,14 @@ int dht_create_packet(const Memory *mem, const Random *rng, random_nonce(rng, nonce); - const int encrypted_length = encrypt_data_symmetric(shared_key, nonce, plain, plain_length, encrypted); + const int encrypted_length = encrypt_data_symmetric(mem, shared_key, nonce, plain, plain_length, encrypted); - if (encrypted_length == -1) { + if (encrypted_length < 0) { mem_delete(mem, encrypted); return -1; } - if (length < 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + encrypted_length) { + if (length < 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + (size_t)encrypted_length) { mem_delete(mem, encrypted); return -1; } @@ -430,7 +431,7 @@ int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed const int ipp_size = unpack_ip_port(&nodes[num].ip_port, data + len_processed, length - len_processed, tcp_enabled); if (ipp_size == -1) { - return -1; + break; } len_processed += ipp_size; @@ -449,6 +450,10 @@ int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed #endif /* NDEBUG */ } + if (num == 0 && max_num_nodes > 0 && length > 0) { + return -1; + } + if (processed_data_len != nullptr) { *processed_data_len = len_processed; } @@ -707,7 +712,7 @@ static void get_close_nodes_inner( } /** - * Find MAX_SENT_NODES nodes closest to the public_key for the send nodes request: + * Find MAX_SENT_NODES nodes closest to the public_key for the nodes request: * put them in the nodes_list and return how many were found. * * want_announce: return only nodes which implement the dht announcements protocol. @@ -755,49 +760,6 @@ int get_close_nodes( is_lan, want_announce); } -typedef struct DHT_Cmp_Data { - uint64_t cur_time; - const uint8_t *base_public_key; - Client_data entry; -} DHT_Cmp_Data; - -non_null() -static int dht_cmp_entry(const void *a, const void *b) -{ - const DHT_Cmp_Data *cmp1 = (const DHT_Cmp_Data *)a; - const DHT_Cmp_Data *cmp2 = (const DHT_Cmp_Data *)b; - const Client_data entry1 = cmp1->entry; - const Client_data entry2 = cmp2->entry; - const uint8_t *cmp_public_key = cmp1->base_public_key; - - const bool t1 = assoc_timeout(cmp1->cur_time, &entry1.assoc4) && assoc_timeout(cmp1->cur_time, &entry1.assoc6); - const bool t2 = assoc_timeout(cmp2->cur_time, &entry2.assoc4) && assoc_timeout(cmp2->cur_time, &entry2.assoc6); - - if (t1 && t2) { - return 0; - } - - if (t1) { - return -1; - } - - if (t2) { - return 1; - } - - const int closest = id_closest(cmp_public_key, entry1.public_key, entry2.public_key); - - if (closest == 1) { - return 1; - } - - if (closest == 2) { - return -1; - } - - return 0; -} - #ifdef CHECK_ANNOUNCE_NODE non_null() static void set_announce_node_in_list(Client_data *list, uint32_t list_len, const uint8_t *public_key) @@ -870,7 +832,7 @@ static int handle_data_search_response(void *object, const IP_Port *source, const uint8_t *public_key = packet + 1; const uint8_t *shared_key = dht_get_shared_key_recv(dht, public_key); - if (decrypt_data_symmetric(shared_key, + if (decrypt_data_symmetric(dht->mem, shared_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, plain_len + CRYPTO_MAC_SIZE, @@ -914,31 +876,117 @@ static bool store_node_ok(const Client_data *client, uint64_t cur_time, const ui || id_closest(comp_public_key, client->public_key, public_key) == 2; } +typedef struct Client_data_Cmp { + const Memory *mem; + uint64_t cur_time; + const uint8_t *comp_public_key; +} Client_data_Cmp; + non_null() -static void sort_client_list(const Memory *mem, Client_data *list, uint64_t cur_time, unsigned int length, - const uint8_t *comp_public_key) +static int client_data_cmp(const Client_data_Cmp *cmp, const Client_data *entry1, const Client_data *entry2) { - // Pass comp_public_key to qsort with each Client_data entry, so the - // comparison function can use it as the base of comparison. - DHT_Cmp_Data *cmp_list = (DHT_Cmp_Data *)mem_valloc(mem, length, sizeof(DHT_Cmp_Data)); + const bool t1 = assoc_timeout(cmp->cur_time, &entry1->assoc4) && assoc_timeout(cmp->cur_time, &entry1->assoc6); + const bool t2 = assoc_timeout(cmp->cur_time, &entry2->assoc4) && assoc_timeout(cmp->cur_time, &entry2->assoc6); - if (cmp_list == nullptr) { - return; + if (t1 && t2) { + return 0; } - for (uint32_t i = 0; i < length; ++i) { - cmp_list[i].cur_time = cur_time; - cmp_list[i].base_public_key = comp_public_key; - cmp_list[i].entry = list[i]; + if (t1) { + return -1; + } + + if (t2) { + return 1; } - qsort(cmp_list, length, sizeof(DHT_Cmp_Data), dht_cmp_entry); + const int closest = id_closest(cmp->comp_public_key, entry1->public_key, entry2->public_key); - for (uint32_t i = 0; i < length; ++i) { - list[i] = cmp_list[i].entry; + if (closest == 1) { + return 1; } - mem_delete(mem, cmp_list); + if (closest == 2) { + return -1; + } + + return 0; +} + +non_null() +static bool client_data_less_handler(const void *object, const void *a, const void *b) +{ + const Client_data_Cmp *cmp = (const Client_data_Cmp *)object; + const Client_data *entry1 = (const Client_data *)a; + const Client_data *entry2 = (const Client_data *)b; + + return client_data_cmp(cmp, entry1, entry2) < 0; +} + +non_null() +static const void *client_data_get_handler(const void *arr, uint32_t index) +{ + const Client_data *entries = (const Client_data *)arr; + return &entries[index]; +} + +non_null() +static void client_data_set_handler(void *arr, uint32_t index, const void *val) +{ + Client_data *entries = (Client_data *)arr; + const Client_data *entry = (const Client_data *)val; + entries[index] = *entry; +} + +non_null() +static void *client_data_subarr_handler(void *arr, uint32_t index, uint32_t size) +{ + Client_data *entries = (Client_data *)arr; + return &entries[index]; +} + +non_null() +static void *client_data_alloc_handler(const void *object, uint32_t size) +{ + const Client_data_Cmp *cmp = (const Client_data_Cmp *)object; + Client_data *tmp = (Client_data *)mem_valloc(cmp->mem, size, sizeof(Client_data)); + + if (tmp == nullptr) { + return nullptr; + } + + return tmp; +} + +non_null() +static void client_data_delete_handler(const void *object, void *arr, uint32_t size) +{ + const Client_data_Cmp *cmp = (const Client_data_Cmp *)object; + mem_delete(cmp->mem, arr); +} + +static const Sort_Funcs client_data_cmp_funcs = { + client_data_less_handler, + client_data_get_handler, + client_data_set_handler, + client_data_subarr_handler, + client_data_alloc_handler, + client_data_delete_handler, +}; + +non_null() +static void sort_client_list(const Memory *mem, Client_data *list, uint64_t cur_time, unsigned int length, + const uint8_t *comp_public_key) +{ + // Pass comp_public_key to merge_sort with each Client_data entry, so the + // comparison function can use it as the base of comparison. + const Client_data_Cmp cmp = { + mem, + cur_time, + comp_public_key, + }; + + merge_sort(list, length, &cmp, &client_data_cmp_funcs); } non_null() @@ -1087,7 +1135,7 @@ static bool is_pk_in_close_list(const DHT *dht, const uint8_t *public_key, const ip_port); } -/** @brief Check if the node obtained with a get_nodes with public_key should be pinged. +/** @brief Check if the node obtained from a nodes response with public_key should be pinged. * * NOTE: for best results call it after addto_lists. * @@ -1095,7 +1143,7 @@ static bool is_pk_in_close_list(const DHT *dht, const uint8_t *public_key, const * return true if it should. */ non_null() -static bool ping_node_from_getnodes_ok(DHT *dht, const uint8_t *public_key, const IP_Port *ip_port) +static bool ping_node_from_nodes_response_ok(DHT *dht, const uint8_t *public_key, const IP_Port *ip_port) { bool ret = false; @@ -1266,7 +1314,7 @@ static void returnedip_ports(DHT *dht, const IP_Port *ip_port, const uint8_t *pu } } -bool dht_getnodes(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *client_id) +bool dht_send_nodes_request(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *client_id) { /* Check if packet is going to be sent to ourself. */ if (pk_equal(public_key, dht->self_public_key)) { @@ -1301,21 +1349,21 @@ bool dht_getnodes(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key, c const uint8_t *shared_key = dht_get_shared_key_sent(dht, public_key); const int len = dht_create_packet(dht->mem, dht->rng, - dht->self_public_key, shared_key, NET_PACKET_GET_NODES, + dht->self_public_key, shared_key, NET_PACKET_NODES_REQUEST, plain, sizeof(plain), data, sizeof(data)); if (len != sizeof(data)) { - LOGGER_ERROR(dht->log, "getnodes packet encryption failed"); + LOGGER_ERROR(dht->log, "nodes request packet encryption failed"); return false; } return sendpacket(dht->net, ip_port, data, len) > 0; } -/** Send a send nodes response: message for IPv6 nodes */ +/** Send a nodes response */ non_null() -static int sendnodes_ipv6(const DHT *dht, const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *client_id, - const uint8_t *sendback_data, uint16_t length, const uint8_t *shared_encryption_key) +static int send_nodes_response(const DHT *dht, const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *client_id, + const uint8_t *sendback_data, uint16_t length, const uint8_t *shared_encryption_key) { /* Check if packet is going to be sent to ourself. */ if (pk_equal(public_key, dht->self_public_key)) { @@ -1347,15 +1395,15 @@ static int sendnodes_ipv6(const DHT *dht, const IP_Port *ip_port, const uint8_t plain[0] = num_nodes; memcpy(plain + 1 + nodes_length, sendback_data, length); - const uint32_t crypto_size = 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_MAC_SIZE; - const uint32_t data_size = 1 + nodes_length + length + crypto_size; + const uint16_t crypto_size = 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_MAC_SIZE; + const uint16_t data_size = 1 + nodes_length + length + crypto_size; VLA(uint8_t, data, data_size); const int len = dht_create_packet(dht->mem, dht->rng, - dht->self_public_key, shared_encryption_key, NET_PACKET_SEND_NODES_IPV6, + dht->self_public_key, shared_encryption_key, NET_PACKET_NODES_RESPONSE, plain, 1 + nodes_length + length, data, data_size); - if (len != data_size) { + if (len < 0 || (uint32_t)len != data_size) { return -1; } @@ -1365,7 +1413,7 @@ static int sendnodes_ipv6(const DHT *dht, const IP_Port *ip_port, const uint8_t #define CRYPTO_NODE_SIZE (CRYPTO_PUBLIC_KEY_SIZE + sizeof(uint64_t)) non_null() -static int handle_getnodes(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata) +static int handle_nodes_request(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata) { DHT *const dht = (DHT *)object; @@ -1381,6 +1429,7 @@ static int handle_getnodes(void *object, const IP_Port *source, const uint8_t *p uint8_t plain[CRYPTO_NODE_SIZE]; const uint8_t *shared_key = dht_get_shared_key_recv(dht, packet + 1); const int len = decrypt_data_symmetric( + dht->mem, shared_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, @@ -1391,16 +1440,16 @@ static int handle_getnodes(void *object, const IP_Port *source, const uint8_t *p return 1; } - sendnodes_ipv6(dht, source, packet + 1, plain, plain + CRYPTO_PUBLIC_KEY_SIZE, sizeof(uint64_t), shared_key); + send_nodes_response(dht, source, packet + 1, plain, plain + CRYPTO_PUBLIC_KEY_SIZE, sizeof(uint64_t), shared_key); ping_add(dht->ping, packet + 1, source); return 0; } -/** Return true if we sent a getnode packet to the peer associated with the supplied info. */ +/** Return true if we sent a nodes request packet to the peer associated with the supplied info. */ non_null() -static bool sent_getnode_to_node(DHT *dht, const uint8_t *public_key, const IP_Port *node_ip_port, uint64_t ping_id) +static bool sent_nodes_request_to_node(DHT *dht, const uint8_t *public_key, const IP_Port *node_ip_port, uint64_t ping_id) { uint8_t data[sizeof(Node_format) * 2]; @@ -1418,8 +1467,8 @@ static bool sent_getnode_to_node(DHT *dht, const uint8_t *public_key, const IP_P } non_null() -static bool handle_sendnodes_core(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, - Node_format *plain_nodes, uint16_t size_plain_nodes, uint32_t *num_nodes_out) +static bool handle_nodes_response_core(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, + Node_format *plain_nodes, uint16_t size_plain_nodes, uint32_t *num_nodes_out) { DHT *const dht = (DHT *)object; const uint32_t cid_size = 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + 1 + sizeof(uint64_t) + CRYPTO_MAC_SIZE; @@ -1442,6 +1491,7 @@ static bool handle_sendnodes_core(void *object, const IP_Port *source, const uin VLA(uint8_t, plain, plain_size); const uint8_t *shared_key = dht_get_shared_key_sent(dht, packet + 1); const int len = decrypt_data_symmetric( + dht->mem, shared_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, @@ -1459,7 +1509,7 @@ static bool handle_sendnodes_core(void *object, const IP_Port *source, const uin uint64_t ping_id; memcpy(&ping_id, plain + 1 + data_size, sizeof(ping_id)); - if (!sent_getnode_to_node(dht, packet + 1, source, ping_id)) { + if (!sent_nodes_request_to_node(dht, packet + 1, source, ping_id)) { return false; } @@ -1487,14 +1537,14 @@ static bool handle_sendnodes_core(void *object, const IP_Port *source, const uin } non_null() -static int handle_sendnodes_ipv6(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, +static int handle_nodes_response(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata) { DHT *const dht = (DHT *)object; Node_format plain_nodes[MAX_SENT_NODES]; uint32_t num_nodes; - if (!handle_sendnodes_core(object, source, packet, length, plain_nodes, MAX_SENT_NODES, &num_nodes)) { + if (!handle_nodes_response_core(object, source, packet, length, plain_nodes, MAX_SENT_NODES, &num_nodes)) { return 1; } @@ -1504,11 +1554,11 @@ static int handle_sendnodes_ipv6(void *object, const IP_Port *source, const uint for (uint32_t i = 0; i < num_nodes; ++i) { if (ipport_isset(&plain_nodes[i].ip_port)) { - ping_node_from_getnodes_ok(dht, plain_nodes[i].public_key, &plain_nodes[i].ip_port); + ping_node_from_nodes_response_ok(dht, plain_nodes[i].public_key, &plain_nodes[i].ip_port); returnedip_ports(dht, &plain_nodes[i].ip_port, plain_nodes[i].public_key, packet + 1); - if (dht->get_nodes_response != nullptr) { - dht->get_nodes_response(dht, &plain_nodes[i], userdata); + if (dht->nodes_response_callback != nullptr) { + dht->nodes_response_callback(dht, &plain_nodes[i], userdata); } } } @@ -1721,7 +1771,7 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co if (mono_time_is_timeout(dht->mono_time, assoc->last_pinged, PING_INTERVAL)) { const IP_Port *target = &assoc->ip_port; const uint8_t *target_key = client->public_key; - dht_getnodes(dht, target, target_key, public_key); + dht_send_nodes_request(dht, target, target_key, public_key); assoc->last_pinged = temp_time; } @@ -1746,7 +1796,7 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co sort_client_list(dht->mem, list, dht->cur_time, list_count, public_key); } - if (num_nodes > 0 && (mono_time_is_timeout(dht->mono_time, *lastgetnode, GET_NODE_INTERVAL) + if (num_nodes > 0 && (mono_time_is_timeout(dht->mono_time, *lastgetnode, NODES_REQUEST_INTERVAL) || *bootstrap_times < MAX_BOOTSTRAP_TIMES)) { uint32_t rand_node = random_range_u32(dht->rng, num_nodes); @@ -1756,7 +1806,7 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co const IP_Port *target = &assoc_list[rand_node]->ip_port; const uint8_t *target_key = client_list[rand_node]->public_key; - dht_getnodes(dht, target, target_key, public_key); + dht_send_nodes_request(dht, target, target_key, public_key); *lastgetnode = temp_time; ++*bootstrap_times; @@ -1769,7 +1819,7 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co /** @brief Ping each client in the "friends" list every PING_INTERVAL seconds. * - * Send a get nodes request every GET_NODE_INTERVAL seconds to a random good + * Send a nodes request every NODES_REQUEST_INTERVAL seconds to a random good * node for each "friend" in our "friends" list. */ non_null() @@ -1779,31 +1829,31 @@ static void do_dht_friends(DHT *dht) DHT_Friend *const dht_friend = &dht->friends_list[i]; for (size_t j = 0; j < dht_friend->num_to_bootstrap; ++j) { - dht_getnodes(dht, &dht_friend->to_bootstrap[j].ip_port, dht_friend->to_bootstrap[j].public_key, dht_friend->public_key); + dht_send_nodes_request(dht, &dht_friend->to_bootstrap[j].ip_port, dht_friend->to_bootstrap[j].public_key, dht_friend->public_key); } dht_friend->num_to_bootstrap = 0; - do_ping_and_sendnode_requests(dht, &dht_friend->lastgetnode, dht_friend->public_key, dht_friend->client_list, + do_ping_and_sendnode_requests(dht, &dht_friend->last_nodes_request, dht_friend->public_key, dht_friend->client_list, MAX_FRIEND_CLIENTS, &dht_friend->bootstrap_times, true); } } /** @brief Ping each client in the close nodes list every PING_INTERVAL seconds. * - * Send a get nodes request every GET_NODE_INTERVAL seconds to a random good node in the list. + * Send a nodes request every NODES_REQUEST_INTERVAL seconds to a random good node in the list. */ non_null() static void do_close(DHT *dht) { for (size_t i = 0; i < dht->num_to_bootstrap; ++i) { - dht_getnodes(dht, &dht->to_bootstrap[i].ip_port, dht->to_bootstrap[i].public_key, dht->self_public_key); + dht_send_nodes_request(dht, &dht->to_bootstrap[i].ip_port, dht->to_bootstrap[i].public_key, dht->self_public_key); } dht->num_to_bootstrap = 0; const uint8_t not_killed = do_ping_and_sendnode_requests( - dht, &dht->close_lastgetnodes, dht->self_public_key, dht->close_clientlist, LCLIENT_LIST, &dht->close_bootstrap_times, + dht, &dht->close_last_nodes_request, dht->self_public_key, dht->close_clientlist, LCLIENT_LIST, &dht->close_bootstrap_times, false); if (not_killed != 0) { @@ -1837,10 +1887,10 @@ bool dht_bootstrap(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key) return true; } - return dht_getnodes(dht, ip_port, public_key, dht->self_public_key); + return dht_send_nodes_request(dht, ip_port, public_key, dht->self_public_key); } -bool dht_bootstrap_from_address(DHT *dht, const char *address, bool ipv6enabled, +bool dht_bootstrap_from_address(DHT *dht, const char *address, bool ipv6enabled, bool dns_enabled, uint16_t port, const uint8_t *public_key) { IP_Port ip_port_v64; @@ -1855,7 +1905,7 @@ bool dht_bootstrap_from_address(DHT *dht, const char *address, bool ipv6enabled, ip_extra = &ip_port_v4.ip; } - if (addr_resolve_or_parse_ip(dht->ns, address, &ip_port_v64.ip, ip_extra)) { + if (addr_resolve_or_parse_ip(dht->ns, dht->mem, address, &ip_port_v64.ip, ip_extra, dns_enabled)) { ip_port_v64.port = port; dht_bootstrap(dht, &ip_port_v64, public_key); @@ -2123,7 +2173,7 @@ static int send_nat_ping(const DHT *dht, const uint8_t *public_key, uint64_t pin memcpy(data + 1, &ping_id, sizeof(uint64_t)); /* 254 is NAT ping request packet id */ const int len = create_request( - dht->rng, dht->self_public_key, dht->self_secret_key, packet_data, public_key, + dht->mem, dht->rng, dht->self_public_key, dht->self_secret_key, packet_data, public_key, data, sizeof(uint64_t) + 1, CRYPTO_PACKET_NAT_PING); if (len == -1) { @@ -2458,7 +2508,7 @@ static int cryptopacket_handle(void *object, const IP_Port *source, const uint8_ uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; uint8_t data[MAX_CRYPTO_REQUEST_SIZE]; uint8_t number; - const int len = handle_request(dht->self_public_key, dht->self_secret_key, public_key, + const int len = handle_request(dht->mem, dht->self_public_key, dht->self_secret_key, public_key, data, &number, packet, length); if (len == -1 || len == 0) { @@ -2484,9 +2534,9 @@ static int cryptopacket_handle(void *object, const IP_Port *source, const uint8_ return 1; } -void dht_callback_get_nodes_response(DHT *dht, dht_get_nodes_response_cb *function) +void dht_callback_nodes_response(DHT *dht, dht_nodes_response_cb *function) { - dht->get_nodes_response = function; + dht->nodes_response_callback = function; } non_null(1, 2, 3) nullable(5) @@ -2547,8 +2597,8 @@ DHT *new_dht(const Logger *log, const Memory *mem, const Random *rng, const Netw return nullptr; } - networking_registerhandler(dht->net, NET_PACKET_GET_NODES, &handle_getnodes, dht); - networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, dht); + networking_registerhandler(dht->net, NET_PACKET_NODES_REQUEST, &handle_nodes_request, dht); + networking_registerhandler(dht->net, NET_PACKET_NODES_RESPONSE, &handle_nodes_response, dht); networking_registerhandler(dht->net, NET_PACKET_CRYPTO, &cryptopacket_handle, dht); networking_registerhandler(dht->net, NET_PACKET_LAN_DISCOVERY, &handle_lan_discovery, dht); cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, &handle_nat_ping, dht); @@ -2626,8 +2676,8 @@ void kill_dht(DHT *dht) return; } - networking_registerhandler(dht->net, NET_PACKET_GET_NODES, nullptr, nullptr); - networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, nullptr, nullptr); + networking_registerhandler(dht->net, NET_PACKET_NODES_REQUEST, nullptr, nullptr); + networking_registerhandler(dht->net, NET_PACKET_NODES_RESPONSE, nullptr, nullptr); networking_registerhandler(dht->net, NET_PACKET_CRYPTO, nullptr, nullptr); networking_registerhandler(dht->net, NET_PACKET_LAN_DISCOVERY, nullptr, nullptr); cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, nullptr, nullptr); diff --git a/protocols/Tox/libtox/src/toxcore/DHT.h b/protocols/Tox/libtox/src/toxcore/DHT.h index 19a9e1d937..16b293331c 100644 --- a/protocols/Tox/libtox/src/toxcore/DHT.h +++ b/protocols/Tox/libtox/src/toxcore/DHT.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ @@ -36,7 +36,7 @@ extern "C" { #define MAX_CLOSE_TO_BOOTSTRAP_NODES 8 -/** The max number of nodes to send with send nodes. */ +/** The max number of nodes to send with nodes response. */ #define MAX_SENT_NODES 4 /** Ping timeout in seconds */ @@ -99,7 +99,7 @@ extern "C" { * @return the length of the created packet on success. */ non_null() -int create_request(const Random *rng, const uint8_t *send_public_key, const uint8_t *send_secret_key, +int create_request(const Memory *mem, const Random *rng, const uint8_t *send_public_key, const uint8_t *send_secret_key, uint8_t *packet, const uint8_t *recv_public_key, const uint8_t *data, uint32_t data_length, uint8_t request_id); @@ -127,7 +127,7 @@ int create_request(const Random *rng, const uint8_t *send_public_key, const uint */ non_null() int handle_request( - const uint8_t *self_public_key, const uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data, + const Memory *mem, const uint8_t *self_public_key, const uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data, uint8_t *request_id, const uint8_t *packet, uint16_t packet_length); typedef struct IPPTs { @@ -259,21 +259,21 @@ non_null() const uint8_t *dht_get_shared_key_sent(DHT *dht, const uint8_t *public_key); /** - * Sends a getnodes request to `ip_port` with the public key `public_key` for nodes + * Sends a nodes request to `ip_port` with the public key `public_key` for nodes * that are close to `client_id`. * * @retval true on success. */ non_null() -bool dht_getnodes(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *client_id); +bool dht_send_nodes_request(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *client_id); typedef void dht_ip_cb(void *object, int32_t number, const IP_Port *ip_port); -typedef void dht_get_nodes_response_cb(const DHT *dht, const Node_format *node, void *user_data); +typedef void dht_nodes_response_cb(const DHT *dht, const Node_format *node, void *user_data); -/** Sets the callback to be triggered on a getnodes response. */ +/** Sets the callback to be triggered on a nodes response. */ non_null(1) nullable(2) -void dht_callback_get_nodes_response(DHT *dht, dht_get_nodes_response_cb *function); +void dht_callback_nodes_response(DHT *dht, dht_nodes_response_cb *function); /** @brief Add a new friend to the friends list. * @param public_key must be CRYPTO_PUBLIC_KEY_SIZE bytes long. @@ -390,7 +390,7 @@ void do_dht(DHT *dht); * Use these two functions to bootstrap the client. */ /** - * @brief Sends a "get nodes" request to the given node with ip, port and public_key + * @brief Sends a "nodes request" to the given node with ip, port and public_key * to setup connections */ non_null() @@ -398,18 +398,19 @@ bool dht_bootstrap(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key); /** @brief Resolves address into an IP address. * - * If successful, sends a "get nodes" request to the given node with ip, port + * If successful, sends a "nodes request" to the given node with ip, port * and public_key to setup connections * * @param address can be a hostname or an IP address (IPv4 or IPv6). * @param ipv6enabled if false, the resolving sticks STRICTLY to IPv4 addresses. * Otherwise, the resolving looks for IPv6 addresses first, then IPv4 addresses. + * @param dns_enabled if false, the resolving does not use DNS, only IP addresses are supported. * * @retval true if the address could be converted into an IP address * @retval false otherwise */ non_null() -bool dht_bootstrap_from_address(DHT *dht, const char *address, bool ipv6enabled, +bool dht_bootstrap_from_address(DHT *dht, const char *address, bool ipv6enabled, bool dns_enabled, uint16_t port, const uint8_t *public_key); /** @brief Start sending packets after DHT loaded_friends_list and loaded_clients_list are set. diff --git a/protocols/Tox/libtox/src/toxcore/LAN_discovery.c b/protocols/Tox/libtox/src/toxcore/LAN_discovery.c index aead975911..fcc3d4793f 100644 --- a/protocols/Tox/libtox/src/toxcore/LAN_discovery.c +++ b/protocols/Tox/libtox/src/toxcore/LAN_discovery.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ @@ -8,8 +8,6 @@ */ #include "LAN_discovery.h" -#include <stdlib.h> - #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) // The mingw32/64 Windows library warns about including winsock2.h after // windows.h even though with the above it's a valid thing to do. So, to make @@ -41,11 +39,14 @@ #include "attributes.h" #include "ccompat.h" #include "crypto_core.h" +#include "mem.h" #include "network.h" #define MAX_INTERFACES 16 struct Broadcast_Info { + const Memory *mem; + uint32_t count; IP ips[MAX_INTERFACES]; }; @@ -53,29 +54,31 @@ struct Broadcast_Info { #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) non_null() -static Broadcast_Info *fetch_broadcast_info(const Network *ns) +static Broadcast_Info *fetch_broadcast_info(const Memory *mem, const Network *ns) { - Broadcast_Info *broadcast = (Broadcast_Info *)calloc(1, sizeof(Broadcast_Info)); + Broadcast_Info *broadcast = (Broadcast_Info *)mem_alloc(mem, sizeof(Broadcast_Info)); if (broadcast == nullptr) { return nullptr; } - IP_ADAPTER_INFO *adapter_info = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO)); + broadcast->mem = mem; + + IP_ADAPTER_INFO *adapter_info = (IP_ADAPTER_INFO *)mem_balloc(mem, sizeof(IP_ADAPTER_INFO)); if (adapter_info == nullptr) { - free(broadcast); + mem_delete(mem, broadcast); return nullptr; } unsigned long out_buf_len = sizeof(IP_ADAPTER_INFO); if (GetAdaptersInfo(adapter_info, &out_buf_len) == ERROR_BUFFER_OVERFLOW) { - free(adapter_info); - IP_ADAPTER_INFO *new_adapter_info = (IP_ADAPTER_INFO *)malloc(out_buf_len); + mem_delete(mem, adapter_info); + IP_ADAPTER_INFO *new_adapter_info = (IP_ADAPTER_INFO *)mem_balloc(mem, out_buf_len); if (new_adapter_info == nullptr) { - free(broadcast); + mem_delete(mem, broadcast); return nullptr; } @@ -113,7 +116,7 @@ static Broadcast_Info *fetch_broadcast_info(const Network *ns) } if (adapter_info != nullptr) { - free(adapter_info); + mem_delete(mem, adapter_info); } return broadcast; @@ -122,14 +125,19 @@ static Broadcast_Info *fetch_broadcast_info(const Network *ns) #elif !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && (defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__)) non_null() -static Broadcast_Info *fetch_broadcast_info(const Network *ns) +static bool ip4_is_local(const IP4 *ip4); + +non_null() +static Broadcast_Info *fetch_broadcast_info(const Memory *mem, const Network *ns) { - Broadcast_Info *broadcast = (Broadcast_Info *)calloc(1, sizeof(Broadcast_Info)); + Broadcast_Info *broadcast = (Broadcast_Info *)mem_alloc(mem, sizeof(Broadcast_Info)); if (broadcast == nullptr) { return nullptr; } + broadcast->mem = mem; + /* Not sure how many platforms this will run on, * so it's wrapped in `__linux__` for now. * Definitely won't work like this on Windows... @@ -137,7 +145,7 @@ static Broadcast_Info *fetch_broadcast_info(const Network *ns) const Socket sock = net_socket(ns, net_family_ipv4(), TOX_SOCK_STREAM, 0); if (!sock_valid(sock)) { - free(broadcast); + mem_delete(mem, broadcast); return nullptr; } @@ -150,7 +158,7 @@ static Broadcast_Info *fetch_broadcast_info(const Network *ns) if (ioctl(net_socket_to_native(sock), SIOCGIFCONF, &ifc) < 0) { kill_sock(ns, sock); - free(broadcast); + mem_delete(mem, broadcast); return nullptr; } @@ -162,7 +170,8 @@ static Broadcast_Info *fetch_broadcast_info(const Network *ns) const int n = ifc.ifc_len / sizeof(struct ifreq); for (int i = 0; i < n; ++i) { - /* there are interfaces with are incapable of broadcast */ + /* there are interfaces with are incapable of broadcast + * on Linux, `lo` has no broadcast address, but this function returns `>=0` */ if (ioctl(net_socket_to_native(sock), SIOCGIFBRDADDR, &i_faces[i]) < 0) { continue; } @@ -172,7 +181,7 @@ static Broadcast_Info *fetch_broadcast_info(const Network *ns) continue; } - const struct sockaddr_in *sock4 = (const struct sockaddr_in *)(void *)&i_faces[i].ifr_broadaddr; + const struct sockaddr_in *broadaddr4 = (const struct sockaddr_in *)(void *)&i_faces[i].ifr_broadaddr; if (broadcast->count >= MAX_INTERFACES) { break; @@ -180,10 +189,27 @@ static Broadcast_Info *fetch_broadcast_info(const Network *ns) IP *ip = &broadcast->ips[broadcast->count]; ip->family = net_family_ipv4(); - ip->ip.v4.uint32 = sock4->sin_addr.s_addr; + ip->ip.v4.uint32 = broadaddr4->sin_addr.s_addr; + // if no broadcast address if (ip->ip.v4.uint32 == 0) { - continue; + if (ioctl(net_socket_to_native(sock), SIOCGIFADDR, &i_faces[i]) < 0) { + continue; + } + + const struct sockaddr_in *addr4 = (const struct sockaddr_in *)(void *)&i_faces[i].ifr_addr; + + + IP4 ip4_staging; + ip4_staging.uint32 = addr4->sin_addr.s_addr; + + if (ip4_is_local(&ip4_staging)) { + // this is 127.x.x.x + ip->ip.v4.uint32 = ip4_staging.uint32; + } else { + // give up. + continue; + } } ++broadcast->count; @@ -197,9 +223,17 @@ static Broadcast_Info *fetch_broadcast_info(const Network *ns) #else // TODO(irungentoo): Other platforms? non_null() -static Broadcast_Info *fetch_broadcast_info(const Network *ns) +static Broadcast_Info *fetch_broadcast_info(const Memory *mem, const Network *ns) { - return (Broadcast_Info *)calloc(1, sizeof(Broadcast_Info)); + Broadcast_Info *broadcast = (Broadcast_Info *)mem_alloc(mem, sizeof(Broadcast_Info)); + + if (broadcast == nullptr) { + return nullptr; + } + + broadcast->mem = mem; + + return broadcast; } #endif /* platforms */ @@ -375,12 +409,16 @@ bool lan_discovery_send(const Networking_Core *net, const Broadcast_Info *broadc return res; } -Broadcast_Info *lan_discovery_init(const Network *ns) +Broadcast_Info *lan_discovery_init(const Memory *mem, const Network *ns) { - return fetch_broadcast_info(ns); + return fetch_broadcast_info(mem, ns); } void lan_discovery_kill(Broadcast_Info *broadcast) { - free(broadcast); + if (broadcast == nullptr) { + return; + } + + mem_delete(broadcast->mem, broadcast); } diff --git a/protocols/Tox/libtox/src/toxcore/LAN_discovery.h b/protocols/Tox/libtox/src/toxcore/LAN_discovery.h index 94e5d3581c..c18ce9e562 100644 --- a/protocols/Tox/libtox/src/toxcore/LAN_discovery.h +++ b/protocols/Tox/libtox/src/toxcore/LAN_discovery.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ @@ -10,6 +10,7 @@ #define C_TOXCORE_TOXCORE_LAN_DISCOVERY_H #include "attributes.h" +#include "mem.h" #include "network.h" /** @@ -32,7 +33,7 @@ bool lan_discovery_send(const Networking_Core *net, const Broadcast_Info *broadc * Discovers broadcast devices and IP addresses. */ non_null() -Broadcast_Info *lan_discovery_init(const Network *ns); +Broadcast_Info *lan_discovery_init(const Memory *mem, const Network *ns); /** * Free all resources associated with the broadcast info. diff --git a/protocols/Tox/libtox/src/toxcore/Makefile.inc b/protocols/Tox/libtox/src/toxcore/Makefile.inc new file mode 100644 index 0000000000..de9227b6d0 --- /dev/null +++ b/protocols/Tox/libtox/src/toxcore/Makefile.inc @@ -0,0 +1,179 @@ +lib_LTLIBRARIES += libtoxcore.la + +libtoxcore_la_include_HEADERS = \ + ../toxcore/tox.h \ + ../toxcore/tox_options.h + +libtoxcore_la_includedir = $(includedir)/tox + +libtoxcore_la_SOURCES = ../third_party/cmp/cmp.c \ + ../third_party/cmp/cmp.h \ + ../toxcore/events/conference_connected.c \ + ../toxcore/events/conference_invite.c \ + ../toxcore/events/conference_message.c \ + ../toxcore/events/conference_peer_list_changed.c \ + ../toxcore/events/conference_peer_name.c \ + ../toxcore/events/conference_title.c \ + ../toxcore/events/dht_nodes_response.c \ + ../toxcore/events/events_alloc.c \ + ../toxcore/events/events_alloc.h \ + ../toxcore/events/file_chunk_request.c \ + ../toxcore/events/file_recv.c \ + ../toxcore/events/file_recv_chunk.c \ + ../toxcore/events/file_recv_control.c \ + ../toxcore/events/friend_connection_status.c \ + ../toxcore/events/friend_lossless_packet.c \ + ../toxcore/events/friend_lossy_packet.c \ + ../toxcore/events/friend_message.c \ + ../toxcore/events/friend_name.c \ + ../toxcore/events/friend_read_receipt.c \ + ../toxcore/events/friend_request.c \ + ../toxcore/events/friend_status.c \ + ../toxcore/events/friend_status_message.c \ + ../toxcore/events/friend_typing.c \ + ../toxcore/events/self_connection_status.c \ + ../toxcore/events/group_custom_packet.c \ + ../toxcore/events/group_custom_private_packet.c \ + ../toxcore/events/group_invite.c \ + ../toxcore/events/group_join_fail.c \ + ../toxcore/events/group_message.c \ + ../toxcore/events/group_moderation.c \ + ../toxcore/events/group_password.c \ + ../toxcore/events/group_peer_exit.c \ + ../toxcore/events/group_peer_join.c \ + ../toxcore/events/group_peer_limit.c \ + ../toxcore/events/group_peer_name.c \ + ../toxcore/events/group_peer_status.c \ + ../toxcore/events/group_privacy_state.c \ + ../toxcore/events/group_private_message.c \ + ../toxcore/events/group_self_join.c \ + ../toxcore/events/group_topic.c \ + ../toxcore/events/group_topic_lock.c \ + ../toxcore/events/group_voice_state.c \ + ../toxcore/announce.c \ + ../toxcore/announce.h \ + ../toxcore/attributes.h \ + ../toxcore/bin_pack.c \ + ../toxcore/bin_pack.h \ + ../toxcore/bin_unpack.c \ + ../toxcore/bin_unpack.h \ + ../toxcore/ccompat.c \ + ../toxcore/ccompat.h \ + ../toxcore/crypto_core_pack.c \ + ../toxcore/crypto_core_pack.h \ + ../toxcore/crypto_core.c \ + ../toxcore/crypto_core.h \ + ../toxcore/DHT.c \ + ../toxcore/DHT.h \ + ../toxcore/forwarding.c \ + ../toxcore/forwarding.h \ + ../toxcore/friend_connection.c \ + ../toxcore/friend_connection.h \ + ../toxcore/friend_requests.c \ + ../toxcore/friend_requests.h \ + ../toxcore/group_announce.c \ + ../toxcore/group_announce.h \ + ../toxcore/group_chats.c \ + ../toxcore/group_chats.h \ + ../toxcore/group_common.h \ + ../toxcore/group_connection.c \ + ../toxcore/group_connection.h \ + ../toxcore/group_moderation.c \ + ../toxcore/group_moderation.h \ + ../toxcore/group_onion_announce.c \ + ../toxcore/group_onion_announce.h \ + ../toxcore/group_pack.c \ + ../toxcore/group_pack.h \ + ../toxcore/group.c \ + ../toxcore/group.h \ + ../toxcore/LAN_discovery.c \ + ../toxcore/LAN_discovery.h \ + ../toxcore/list.c \ + ../toxcore/list.h \ + ../toxcore/logger.c \ + ../toxcore/logger.h \ + ../toxcore/mem.c \ + ../toxcore/mem.h \ + ../toxcore/Messenger.c \ + ../toxcore/Messenger.h \ + ../toxcore/mono_time.c \ + ../toxcore/mono_time.h \ + ../toxcore/net_crypto.c \ + ../toxcore/net_crypto.h \ + ../toxcore/net_profile.c \ + ../toxcore/net_profile.h \ + ../toxcore/network.c \ + ../toxcore/network.h \ + ../toxcore/onion_announce.c \ + ../toxcore/onion_announce.h \ + ../toxcore/onion_client.c \ + ../toxcore/onion_client.h \ + ../toxcore/onion.c \ + ../toxcore/onion.h \ + ../toxcore/ping_array.c \ + ../toxcore/ping_array.h \ + ../toxcore/ping.c \ + ../toxcore/ping.h \ + ../toxcore/shared_key_cache.c \ + ../toxcore/shared_key_cache.h \ + ../toxcore/sort.c \ + ../toxcore/sort.h \ + ../toxcore/state.c \ + ../toxcore/state.h \ + ../toxcore/TCP_client.c \ + ../toxcore/TCP_client.h \ + ../toxcore/TCP_common.c \ + ../toxcore/TCP_common.h \ + ../toxcore/TCP_connection.c \ + ../toxcore/TCP_connection.h \ + ../toxcore/TCP_server.c \ + ../toxcore/TCP_server.h \ + ../toxcore/timed_auth.c \ + ../toxcore/timed_auth.h \ + ../toxcore/tox_api.c \ + ../toxcore/tox_dispatch.c \ + ../toxcore/tox_dispatch.h \ + ../toxcore/tox_event.c \ + ../toxcore/tox_event.h \ + ../toxcore/tox_events.c \ + ../toxcore/tox_events.h \ + ../toxcore/tox_log_level.c \ + ../toxcore/tox_log_level.h \ + ../toxcore/tox_options.c \ + ../toxcore/tox_options.h \ + ../toxcore/tox_pack.c \ + ../toxcore/tox_pack.h \ + ../toxcore/tox_private.c \ + ../toxcore/tox_private.h \ + ../toxcore/tox_struct.h \ + ../toxcore/tox_unpack.c \ + ../toxcore/tox_unpack.h \ + ../toxcore/tox.c \ + ../toxcore/tox.h \ + ../toxcore/util.c \ + ../toxcore/util.h + +libtoxcore_la_CFLAGS = -I$(top_srcdir) \ + -I$(top_srcdir)/toxcore \ + $(LIBSODIUM_CFLAGS) \ + $(MSGPACK_CFLAGS) \ + $(PTHREAD_CFLAGS) \ + -DCMP_NO_FLOAT=1 + +libtoxcore_la_LDFLAGS = $(LT_LDFLAGS) \ + $(EXTRA_LT_LDFLAGS) \ + $(LIBSODIUM_LDFLAGS) \ + $(MSGPACK_LDFLAGS) \ + $(MATH_LDFLAGS) \ + $(RT_LIBS) \ + $(WINSOCK2_LIBS) + +libtoxcore_la_LIBADD = $(LIBSODIUM_LIBS) \ + $(MSGPACK_LIBS) \ + $(PTHREAD_LIBS) + +if SET_SO_VERSION + +EXTRA_libtoxcore_la_DEPENDENCIES = ../so.version + +endif diff --git a/protocols/Tox/libtox/src/toxcore/Messenger.c b/protocols/Tox/libtox/src/toxcore/Messenger.c index 947edef7e1..2d25abda56 100644 --- a/protocols/Tox/libtox/src/toxcore/Messenger.c +++ b/protocols/Tox/libtox/src/toxcore/Messenger.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ @@ -34,6 +34,7 @@ #include "mem.h" #include "mono_time.h" #include "net_crypto.h" +#include "net_profile.h" #include "network.h" #include "onion.h" #include "onion_announce.h" @@ -137,7 +138,7 @@ void getaddress(const Messenger *m, uint8_t *address) } non_null() -static bool send_online_packet(Messenger *m, int friendcon_id) +static bool send_online_packet(const Messenger *m, int friendcon_id) { const uint8_t packet[1] = {PACKET_ID_ONLINE}; return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, friendcon_id), packet, @@ -145,7 +146,7 @@ static bool send_online_packet(Messenger *m, int friendcon_id) } non_null() -static bool send_offline_packet(Messenger *m, int friendcon_id) +static bool send_offline_packet(const Messenger *m, int friendcon_id) { const uint8_t packet[1] = {PACKET_ID_OFFLINE}; return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, friendcon_id), packet, @@ -472,10 +473,6 @@ int m_delfriend(Messenger *m, int32_t friendnumber) return -1; } - if (m->friend_connectionstatuschange_internal != nullptr) { - m->friend_connectionstatuschange_internal(m, friendnumber, false, m->friend_connectionstatuschange_internal_userdata); - } - clear_receipts(m, friendnumber); remove_request_received(m->fr, m->friendlist[friendnumber].real_pk); friend_connection_callbacks(m->fr_c, m->friendlist[friendnumber].friendcon_id, MESSENGER_CALLBACK_INDEX, nullptr, @@ -775,31 +772,31 @@ int m_set_statusmessage(Messenger *m, const uint8_t *status, uint16_t length) } non_null() -static bool userstatus_from_int(uint8_t status, Userstatus *out) +static bool userstatus_from_int(uint8_t status, Userstatus *out_enum) { switch (status) { case USERSTATUS_NONE: { - *out = USERSTATUS_NONE; + *out_enum = USERSTATUS_NONE; return true; } case USERSTATUS_AWAY: { - *out = USERSTATUS_AWAY; + *out_enum = USERSTATUS_AWAY; return true; } case USERSTATUS_BUSY: { - *out = USERSTATUS_BUSY; + *out_enum = USERSTATUS_BUSY; return true; } case USERSTATUS_INVALID: { - *out = USERSTATUS_INVALID; + *out_enum = USERSTATUS_INVALID; return true; } default: { - *out = USERSTATUS_INVALID; + *out_enum = USERSTATUS_INVALID; return false; } } @@ -1027,13 +1024,6 @@ void m_callback_core_connection(Messenger *m, m_self_connection_status_cb *funct m->core_connection_change = function; } -void m_callback_connectionstatus_internal_av(Messenger *m, m_friend_connectionstatuschange_internal_cb *function, - void *userdata) -{ - m->friend_connectionstatuschange_internal = function; - m->friend_connectionstatuschange_internal_userdata = userdata; -} - non_null(1) nullable(3) static void check_friend_tcp_udp(Messenger *m, int32_t friendnumber, void *userdata) { @@ -1081,11 +1071,6 @@ static void check_friend_connectionstatus(Messenger *m, int32_t friendnumber, ui m->friendlist[friendnumber].status = status; check_friend_tcp_udp(m, friendnumber, userdata); - - if (m->friend_connectionstatuschange_internal != nullptr) { - m->friend_connectionstatuschange_internal(m, friendnumber, is_online, - m->friend_connectionstatuschange_internal_userdata); - } } } @@ -1855,23 +1840,6 @@ static int handle_filecontrol(Messenger *m, int32_t friendnumber, bool outbound, } } -/** @brief Set the callback for msi packets. */ -void m_callback_msi_packet(Messenger *m, m_msi_packet_cb *function, void *userdata) -{ - m->msi_packet = function; - m->msi_packet_userdata = userdata; -} - -/** @brief Send an msi packet. - * - * @retval true on success - * @retval false on failure - */ -bool m_msi_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length) -{ - return write_cryptpacket_id(m, friendnumber, PACKET_ID_MSI, data, length, false); -} - static int m_handle_lossy_packet(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata) { @@ -1881,17 +1849,6 @@ static int m_handle_lossy_packet(void *object, int friendcon_id, const uint8_t * return 1; } - if (data[0] <= PACKET_ID_RANGE_LOSSY_AV_END) { - const RTP_Packet_Handler *const ph = - &m->friendlist[friendcon_id].lossy_rtp_packethandlers[data[0] % PACKET_ID_RANGE_LOSSY_AV_SIZE]; - - if (ph->function != nullptr) { - return ph->function(m, friendcon_id, data, length, ph->object); - } - - return 1; - } - if (m->lossy_packethandler != nullptr) { m->lossy_packethandler(m, friendcon_id, data[0], data, length, userdata); } @@ -1904,38 +1861,6 @@ void custom_lossy_packet_registerhandler(Messenger *m, m_friend_lossy_packet_cb m->lossy_packethandler = lossy_packethandler; } -int m_callback_rtp_packet(Messenger *m, int32_t friendnumber, uint8_t byte, m_lossy_rtp_packet_cb *function, - void *object) -{ - if (!m_friend_exists(m, friendnumber)) { - return -1; - } - - if (byte < PACKET_ID_RANGE_LOSSY_AV_START || byte > PACKET_ID_RANGE_LOSSY_AV_END) { - return -1; - } - - m->friendlist[friendnumber].lossy_rtp_packethandlers[byte % PACKET_ID_RANGE_LOSSY_AV_SIZE].function = function; - m->friendlist[friendnumber].lossy_rtp_packethandlers[byte % PACKET_ID_RANGE_LOSSY_AV_SIZE].object = object; - return 0; -} - -/** @brief High level function to send custom lossy packets. - * - * TODO(oxij): this name is confusing, because this function sends both av and custom lossy packets. - * Meanwhile, m_handle_lossy_packet routes custom packets to custom_lossy_packet_registerhandler - * as you would expect from its name. - * - * I.e. custom_lossy_packet_registerhandler's "custom lossy packet" and this "custom lossy packet" - * are not the same set of packets. - * - * @retval -1 if friend invalid. - * @retval -2 if length wrong. - * @retval -3 if first byte invalid. - * @retval -4 if friend offline. - * @retval -5 if packet failed to send because of other error. - * @retval 0 on success. - */ int m_send_custom_lossy_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length) { if (!m_friend_exists(m, friendnumber)) { @@ -1946,7 +1871,6 @@ int m_send_custom_lossy_packet(const Messenger *m, int32_t friendnumber, const u return -2; } - // TODO(oxij): send_lossy_cryptpacket makes this check already, similarly for other similar places if (data[0] < PACKET_ID_RANGE_LOSSY_START || data[0] > PACKET_ID_RANGE_LOSSY_END) { return -3; } @@ -1974,7 +1898,10 @@ static int handle_custom_lossless_packet(void *object, int friend_num, const uin } if (packet[0] < PACKET_ID_RANGE_LOSSLESS_CUSTOM_START || packet[0] > PACKET_ID_RANGE_LOSSLESS_CUSTOM_END) { - return -1; + // allow PACKET_ID_MSI packets to be handled by custom packet handler + if (packet[0] != PACKET_ID_MSI) { + return -1; + } } if (m->lossless_packethandler != nullptr) { @@ -2357,20 +2284,6 @@ static int m_handle_packet_file_data(Messenger *m, const int friendcon_id, const } non_null(1, 3) nullable(5) -static int m_handle_packet_msi(Messenger *m, const int friendcon_id, const uint8_t *data, const uint16_t data_length, void *userdata) -{ - if (data_length == 0) { - return 0; - } - - if (m->msi_packet != nullptr) { - m->msi_packet(m, friendcon_id, data, data_length, m->msi_packet_userdata); - } - - return 0; -} - -non_null(1, 3) nullable(5) static int m_handle_packet_invite_groupchat(Messenger *m, const int friendcon_id, const uint8_t *data, const uint16_t data_length, void *userdata) { // first two bytes are messenger packet type and group invite type @@ -2443,7 +2356,7 @@ static int m_handle_packet(void *object, int friendcon_id, const uint8_t *data, case PACKET_ID_FILE_DATA: return m_handle_packet_file_data(m, friendcon_id, payload, payload_length, userdata); case PACKET_ID_MSI: - return m_handle_packet_msi(m, friendcon_id, payload, payload_length, userdata); + return handle_custom_lossless_packet(object, friendcon_id, data, length, userdata); case PACKET_ID_INVITE_GROUPCHAT: return m_handle_packet_invite_groupchat(m, friendcon_id, payload, payload_length, userdata); } @@ -2468,14 +2381,12 @@ static void do_friends(Messenger *m, void *userdata) } } - if (m->friendlist[i].status == FRIEND_REQUESTED - || m->friendlist[i].status == FRIEND_CONFIRMED) { /* friend is not online. */ - if (m->friendlist[i].status == FRIEND_REQUESTED) { - /* If we didn't connect to friend after successfully sending him a friend request the request is deemed - * unsuccessful so we set the status back to FRIEND_ADDED and try again. - */ - check_friend_request_timed_out(m, i, temp_time, userdata); - } + if (m->friendlist[i].status == FRIEND_REQUESTED) { + /* If we didn't connect to friend after successfully sending him a friend + * request the request is deemed unsuccessful so we set the status back to + * FRIEND_ADDED and try again. + */ + check_friend_request_timed_out(m, i, temp_time, userdata); } if (m->friendlist[i].status == FRIEND_ONLINE) { /* friend is online. */ @@ -2605,7 +2516,7 @@ static bool self_announce_group(const Messenger *m, GC_Chat *chat, Onion_Friend return false; } - if (gca_add_announce(m->mono_time, m->group_announce, &announce) == nullptr) { + if (gca_add_announce(m->mem, m->mono_time, m->group_announce, &announce) == nullptr) { onion_friend_set_gc_data(onion_friend, nullptr, 0); return false; } @@ -3261,7 +3172,7 @@ static bool handle_groups_load(void *obj, Bin_Unpack *bu) non_null() static State_Load_Status groups_load(Messenger *m, const uint8_t *data, uint32_t length) { - if (!bin_unpack_obj(handle_groups_load, m, data, length)) { + if (!bin_unpack_obj(m->mem, handle_groups_load, m, data, length)) { LOGGER_ERROR(m->log, "msgpack failed to unpack groupchats array"); return STATE_LOAD_STATUS_ERROR; } @@ -3565,14 +3476,14 @@ Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random * m->rng = rng; m->ns = ns; - m->fr = friendreq_new(); + m->fr = friendreq_new(mem); if (m->fr == nullptr) { mem_delete(mem, m); return nullptr; } - m->log = logger_new(); + m->log = logger_new(mem); if (m->log == nullptr) { friendreq_kill(m->fr); @@ -3621,11 +3532,24 @@ Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random * return nullptr; } - m->net_crypto = new_net_crypto(m->log, m->mem, m->rng, m->ns, m->mono_time, m->dht, &options->proxy_info); + m->tcp_np = netprof_new(m->log, mem); + + if (m->tcp_np == nullptr) { + LOGGER_WARNING(m->log, "TCP netprof initialisation failed"); + kill_dht(m->dht); + kill_networking(m->net); + friendreq_kill(m->fr); + logger_kill(m->log); + mem_delete(mem, m); + return nullptr; + } + + m->net_crypto = new_net_crypto(m->log, m->mem, m->rng, m->ns, m->mono_time, m->dht, &options->proxy_info, m->tcp_np); if (m->net_crypto == nullptr) { LOGGER_WARNING(m->log, "net_crypto initialisation failed"); + netprof_kill(mem, m->tcp_np); kill_dht(m->dht); kill_networking(m->net); friendreq_kill(m->fr); @@ -3634,12 +3558,13 @@ Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random * return nullptr; } - m->group_announce = new_gca_list(); + m->group_announce = new_gca_list(m->mem); if (m->group_announce == nullptr) { LOGGER_WARNING(m->log, "DHT group chats initialisation failed"); kill_net_crypto(m->net_crypto); + netprof_kill(mem, m->tcp_np); kill_dht(m->dht); kill_networking(m->net); friendreq_kill(m->fr); @@ -3649,7 +3574,7 @@ Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random * } if (options->dht_announcements_enabled) { - m->forwarding = new_forwarding(m->log, m->rng, m->mono_time, m->dht); + m->forwarding = new_forwarding(m->log, m->mem, m->rng, m->mono_time, m->dht); if (m->forwarding != nullptr) { m->announce = new_announcements(m->log, m->mem, m->rng, m->mono_time, m->forwarding); } else { @@ -3664,7 +3589,7 @@ Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random * m->onion_a = new_onion_announce(m->log, m->mem, m->rng, m->mono_time, m->dht); m->onion_c = new_onion_client(m->log, m->mem, m->rng, m->mono_time, m->net_crypto); if (m->onion_c != nullptr) { - m->fr_c = new_friend_connections(m->log, m->mono_time, m->ns, m->onion_c, options->local_discovery_enabled); + m->fr_c = new_friend_connections(m->log, m->mem, m->mono_time, m->ns, m->onion_c, options->local_discovery_enabled); } if ((options->dht_announcements_enabled && (m->forwarding == nullptr || m->announce == nullptr)) || @@ -3679,6 +3604,7 @@ Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random * kill_announcements(m->announce); kill_forwarding(m->forwarding); kill_net_crypto(m->net_crypto); + netprof_kill(mem, m->tcp_np); kill_dht(m->dht); kill_networking(m->net); friendreq_kill(m->fr); @@ -3702,6 +3628,7 @@ Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random * kill_announcements(m->announce); kill_forwarding(m->forwarding); kill_net_crypto(m->net_crypto); + netprof_kill(mem, m->tcp_np); kill_dht(m->dht); kill_networking(m->net); friendreq_kill(m->fr); @@ -3727,6 +3654,7 @@ Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random * kill_announcements(m->announce); kill_forwarding(m->forwarding); kill_net_crypto(m->net_crypto); + netprof_kill(mem, m->tcp_np); kill_dht(m->dht); kill_networking(m->net); friendreq_kill(m->fr); @@ -3782,6 +3710,7 @@ void kill_messenger(Messenger *m) kill_announcements(m->announce); kill_forwarding(m->forwarding); kill_net_crypto(m->net_crypto); + netprof_kill(m->mem, m->tcp_np); kill_dht(m->dht); kill_networking(m->net); diff --git a/protocols/Tox/libtox/src/toxcore/Messenger.h b/protocols/Tox/libtox/src/toxcore/Messenger.h index cace3340b2..1286ddf138 100644 --- a/protocols/Tox/libtox/src/toxcore/Messenger.h +++ b/protocols/Tox/libtox/src/toxcore/Messenger.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ @@ -25,6 +25,7 @@ #include "mem.h" #include "mono_time.h" #include "net_crypto.h" +#include "net_profile.h" #include "network.h" #include "onion.h" #include "onion_announce.h" @@ -86,6 +87,8 @@ typedef struct Messenger_Options { Messenger_State_Plugin *state_plugins; uint8_t state_plugins_length; + + bool dns_enabled; } Messenger_Options; struct Receipts { @@ -200,20 +203,10 @@ typedef void m_friend_lossy_packet_cb(Messenger *m, uint32_t friend_number, uint size_t length, void *user_data); typedef void m_friend_lossless_packet_cb(Messenger *m, uint32_t friend_number, uint8_t packet_id, const uint8_t *data, size_t length, void *user_data); -typedef void m_friend_connectionstatuschange_internal_cb(Messenger *m, uint32_t friend_number, - bool is_online, void *user_data); typedef void m_conference_invite_cb(Messenger *m, uint32_t friend_number, const uint8_t *cookie, uint16_t length, void *user_data); typedef void m_group_invite_cb(const Messenger *m, uint32_t friend_number, const uint8_t *invite_data, size_t length, const uint8_t *group_name, size_t group_name_length, void *user_data); -typedef void m_msi_packet_cb(Messenger *m, uint32_t friend_number, const uint8_t *data, uint16_t length, - void *user_data); -typedef int m_lossy_rtp_packet_cb(Messenger *m, uint32_t friend_number, const uint8_t *data, uint16_t length, void *object); - -typedef struct RTP_Packet_Handler { - m_lossy_rtp_packet_cb *function; - void *object; -} RTP_Packet_Handler; typedef struct Friend { uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE]; @@ -243,8 +236,6 @@ typedef struct Friend { uint32_t num_sending_files; struct File_Transfers file_receiving[MAX_CONCURRENT_FILE_PIPES]; - RTP_Packet_Handler lossy_rtp_packethandlers[PACKET_ID_RANGE_LOSSY_AV_SIZE]; - struct Receipts *receipts_start; struct Receipts *receipts_end; } Friend; @@ -258,6 +249,7 @@ struct Messenger { Networking_Core *net; Net_Crypto *net_crypto; + Net_Profile *tcp_np; DHT *dht; Forwarding *forwarding; @@ -301,8 +293,6 @@ struct Messenger { m_friend_typing_cb *friend_typingchange; m_friend_read_receipt_cb *read_receipt; m_friend_connection_status_cb *friend_connectionstatuschange; - m_friend_connectionstatuschange_internal_cb *friend_connectionstatuschange_internal; - void *friend_connectionstatuschange_internal_userdata; struct Group_Chats *conferences_object; m_conference_invite_cb *conference_invite; @@ -314,9 +304,6 @@ struct Messenger { m_file_recv_chunk_cb *file_filedata; m_file_chunk_request_cb *file_reqchunk; - m_msi_packet_cb *msi_packet; - void *msi_packet_userdata; - m_friend_lossy_packet_cb *lossy_packethandler; m_friend_lossless_packet_cb *lossless_packethandler; @@ -614,10 +601,6 @@ non_null() void m_callback_read_receipt(Messenger *m, m_friend_read_receipt_cb * */ non_null() void m_callback_connectionstatus(Messenger *m, m_friend_connection_status_cb *function); -/** Same as previous but for internal A/V core usage only */ -non_null() void m_callback_connectionstatus_internal_av( - Messenger *m, m_friend_connectionstatuschange_internal_cb *function, void *userdata); - /** @brief Set the callback for typing changes. */ non_null() void m_callback_core_connection(Messenger *m, m_self_connection_status_cb *function); @@ -731,29 +714,6 @@ non_null(1) nullable(5) int send_file_data(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data, uint16_t length); -/*** A/V related */ - -/** @brief Set the callback for msi packets. */ -non_null(1) nullable(2, 3) -void m_callback_msi_packet(Messenger *m, m_msi_packet_cb *function, void *userdata); - -/** @brief Send an msi packet. - * - * @retval true on success - * @retval false on failure - */ -non_null() -bool m_msi_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length); - -/** @brief Set handlers for lossy rtp packets. - * - * @retval -1 on failure. - * @retval 0 on success. - */ -non_null(1) nullable(4, 5) -int m_callback_rtp_packet(Messenger *m, int32_t friendnumber, uint8_t byte, - m_lossy_rtp_packet_cb *function, void *object); - /*** CUSTOM PACKETS */ /** @brief Set handlers for custom lossy packets. */ @@ -761,13 +721,6 @@ non_null() void custom_lossy_packet_registerhandler(Messenger *m, m_friend_lossy /** @brief High level function to send custom lossy packets. * - * TODO(oxij): this name is confusing, because this function sends both av and custom lossy packets. - * Meanwhile, m_handle_lossy_packet routes custom packets to custom_lossy_packet_registerhandler - * as you would expect from its name. - * - * I.e. custom_lossy_packet_registerhandler's "custom lossy packet" and this "custom lossy packet" - * are not the same set of packets. - * * @retval -1 if friend invalid. * @retval -2 if length wrong. * @retval -3 if first byte invalid. diff --git a/protocols/Tox/libtox/src/toxcore/TCP_client.c b/protocols/Tox/libtox/src/toxcore/TCP_client.c index 2b8c6e448f..1982412cda 100644 --- a/protocols/Tox/libtox/src/toxcore/TCP_client.c +++ b/protocols/Tox/libtox/src/toxcore/TCP_client.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2014 Tox project. */ @@ -20,6 +20,7 @@ #include "logger.h" #include "mem.h" #include "mono_time.h" +#include "net_profile.h" #include "network.h" #include "util.h" @@ -107,13 +108,25 @@ void tcp_con_set_custom_uint(TCP_Client_Connection *con, uint32_t value) * @retval false on failure */ non_null() -static bool connect_sock_to(const Logger *logger, const Memory *mem, Socket sock, const IP_Port *ip_port, const TCP_Proxy_Info *proxy_info) +static bool connect_sock_to(const Network *ns, const Logger *logger, const Memory *mem, Socket sock, const IP_Port *ip_port, const TCP_Proxy_Info *proxy_info) { + Net_Err_Connect err; if (proxy_info->proxy_type != TCP_PROXY_NONE) { - return net_connect(mem, logger, sock, &proxy_info->ip_port); + net_connect(ns, mem, logger, sock, &proxy_info->ip_port, &err); } else { - return net_connect(mem, logger, sock, ip_port); + net_connect(ns, mem, logger, sock, ip_port, &err); } + switch (err) { + case NET_ERR_CONNECT_OK: + case NET_ERR_CONNECT_FAILED: { + /* nonblocking socket, connect will never return success */ + return true; + } + case NET_ERR_CONNECT_INVALID_FAMILY: + return false; + } + LOGGER_ERROR(logger, "unexpected error code %s from net_connect", net_err_connect_to_string(err)); + return false; } /** @@ -312,7 +325,7 @@ static int generate_handshake(TCP_Client_Connection *tcp_conn) memcpy(plain + CRYPTO_PUBLIC_KEY_SIZE, tcp_conn->con.sent_nonce, CRYPTO_NONCE_SIZE); memcpy(tcp_conn->con.last_packet, tcp_conn->self_public_key, CRYPTO_PUBLIC_KEY_SIZE); random_nonce(tcp_conn->con.rng, tcp_conn->con.last_packet + CRYPTO_PUBLIC_KEY_SIZE); - const int len = encrypt_data_symmetric(tcp_conn->con.shared_key, tcp_conn->con.last_packet + CRYPTO_PUBLIC_KEY_SIZE, plain, + const int len = encrypt_data_symmetric(tcp_conn->con.mem, tcp_conn->con.shared_key, tcp_conn->con.last_packet + CRYPTO_PUBLIC_KEY_SIZE, plain, sizeof(plain), tcp_conn->con.last_packet + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE); if (len != sizeof(plain) + CRYPTO_MAC_SIZE) { @@ -334,7 +347,7 @@ non_null() static int handle_handshake(TCP_Client_Connection *tcp_conn, const uint8_t *data) { uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE]; - const int len = decrypt_data_symmetric(tcp_conn->con.shared_key, data, data + CRYPTO_NONCE_SIZE, + const int len = decrypt_data_symmetric(tcp_conn->con.mem, tcp_conn->con.shared_key, data, data + CRYPTO_NONCE_SIZE, TCP_SERVER_HANDSHAKE_SIZE - CRYPTO_NONCE_SIZE, plain); if (len != sizeof(plain)) { @@ -582,7 +595,7 @@ void forwarding_handler(TCP_Client_Connection *con, forwarded_response_cb *forwa TCP_Client_Connection *new_tcp_connection( const Logger *logger, const Memory *mem, const Mono_Time *mono_time, const Random *rng, const Network *ns, const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *self_public_key, const uint8_t *self_secret_key, - const TCP_Proxy_Info *proxy_info) + const TCP_Proxy_Info *proxy_info, Net_Profile *net_profile) { assert(logger != nullptr); assert(mem != nullptr); @@ -591,6 +604,7 @@ TCP_Client_Connection *new_tcp_connection( assert(ns != nullptr); if (!net_family_is_ipv4(ip_port->ip.family) && !net_family_is_ipv6(ip_port->ip.family)) { + LOGGER_ERROR(logger, "Invalid IP family: %d", ip_port->ip.family.value); return nullptr; } @@ -609,15 +623,26 @@ TCP_Client_Connection *new_tcp_connection( const Socket sock = net_socket(ns, family, TOX_SOCK_STREAM, TOX_PROTO_TCP); if (!sock_valid(sock)) { + LOGGER_ERROR(logger, "Failed to create TCP socket with family %d", family.value); return nullptr; } if (!set_socket_nosigpipe(ns, sock)) { + LOGGER_ERROR(logger, "Failed to set TCP socket to ignore SIGPIPE"); kill_sock(ns, sock); return nullptr; } - if (!(set_socket_nonblock(ns, sock) && connect_sock_to(logger, mem, sock, ip_port, proxy_info))) { + if (!set_socket_nonblock(ns, sock)) { + LOGGER_ERROR(logger, "Failed to set TCP socket to non-blocking"); + kill_sock(ns, sock); + return nullptr; + } + + if (!connect_sock_to(ns, logger, mem, sock, ip_port, proxy_info)) { + Ip_Ntoa ip_ntoa; + LOGGER_WARNING(logger, "Failed to connect TCP socket to %s:%u", + net_ip_ntoa(&ip_port->ip, &ip_ntoa), net_ntohs(ip_port->port)); kill_sock(ns, sock); return nullptr; } @@ -625,6 +650,7 @@ TCP_Client_Connection *new_tcp_connection( TCP_Client_Connection *temp = (TCP_Client_Connection *)mem_alloc(mem, sizeof(TCP_Client_Connection)); if (temp == nullptr) { + LOGGER_ERROR(logger, "Failed to allocate memory for TCP_Client_Connection"); kill_sock(ns, sock); return nullptr; } @@ -634,6 +660,7 @@ TCP_Client_Connection *new_tcp_connection( temp->con.rng = rng; temp->con.sock = sock; temp->con.ip_port = *ip_port; + temp->con.net_profile = net_profile; memcpy(temp->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE); memcpy(temp->self_public_key, self_public_key, CRYPTO_PUBLIC_KEY_SIZE); encrypt_precompute(temp->public_key, self_secret_key, temp->con.shared_key); @@ -657,6 +684,7 @@ TCP_Client_Connection *new_tcp_connection( temp->status = TCP_CLIENT_CONNECTING; if (generate_handshake(temp) == -1) { + LOGGER_ERROR(logger, "Failed to generate handshake"); kill_sock(ns, sock); mem_delete(mem, temp); return nullptr; @@ -819,6 +847,8 @@ static int handle_tcp_client_packet(const Logger *logger, TCP_Client_Connection return -1; } + netprof_record_packet(conn->con.net_profile, data[0], length, PACKET_DIRECTION_RECV); + switch (data[0]) { case TCP_PACKET_ROUTING_RESPONSE: return handle_tcp_client_routing_response(conn, data, length); diff --git a/protocols/Tox/libtox/src/toxcore/TCP_client.h b/protocols/Tox/libtox/src/toxcore/TCP_client.h index ea2654b953..3ed6e8c683 100644 --- a/protocols/Tox/libtox/src/toxcore/TCP_client.h +++ b/protocols/Tox/libtox/src/toxcore/TCP_client.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2014 Tox project. */ @@ -15,6 +15,7 @@ #include "logger.h" #include "mem.h" #include "mono_time.h" +#include "net_profile.h" #include "network.h" #define TCP_CONNECTION_TIMEOUT 10 @@ -60,11 +61,11 @@ non_null() void tcp_con_set_custom_uint(TCP_Client_Connection *con, uint32_t value); /** Create new TCP connection to ip_port/public_key */ -non_null(1, 2, 3, 4, 5, 6, 7, 8, 9) nullable(10) +non_null(1, 2, 3, 4, 5, 6, 7, 8, 9) nullable(10, 11) TCP_Client_Connection *new_tcp_connection( const Logger *logger, const Memory *mem, const Mono_Time *mono_time, const Random *rng, const Network *ns, const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *self_public_key, const uint8_t *self_secret_key, - const TCP_Proxy_Info *proxy_info); + const TCP_Proxy_Info *proxy_info, Net_Profile *net_profile); /** Run the TCP connection */ non_null(1, 2, 3) nullable(4) diff --git a/protocols/Tox/libtox/src/toxcore/TCP_common.c b/protocols/Tox/libtox/src/toxcore/TCP_common.c index bd3b7ca4c7..1a8a5d9731 100644 --- a/protocols/Tox/libtox/src/toxcore/TCP_common.c +++ b/protocols/Tox/libtox/src/toxcore/TCP_common.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2014 Tox project. */ @@ -35,7 +35,8 @@ int send_pending_data_nonpriority(const Logger *logger, TCP_Connection *con) } const uint16_t left = con->last_packet_length - con->last_packet_sent; - const int len = net_send(con->ns, logger, con->sock, con->last_packet + con->last_packet_sent, left, &con->ip_port); + const int len = net_send(con->ns, logger, con->sock, con->last_packet + con->last_packet_sent, left, &con->ip_port, + con->net_profile); if (len <= 0) { return -1; @@ -66,7 +67,7 @@ int send_pending_data(const Logger *logger, TCP_Connection *con) while (p != nullptr) { const uint16_t left = p->size - p->sent; - const int len = net_send(con->ns, logger, con->sock, p->data + p->sent, left, &con->ip_port); + const int len = net_send(con->ns, logger, con->sock, p->data + p->sent, left, &con->ip_port, con->net_profile); if (len != left) { if (len > 0) { @@ -157,14 +158,15 @@ int write_packet_tcp_secure_connection(const Logger *logger, TCP_Connection *con uint16_t c_length = net_htons(length + CRYPTO_MAC_SIZE); memcpy(packet, &c_length, sizeof(uint16_t)); - int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); + int len = encrypt_data_symmetric(con->mem, con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); if ((unsigned int)len != (packet_size - sizeof(uint16_t))) { return -1; } if (priority) { - len = sendpriority ? net_send(con->ns, logger, con->sock, packet, packet_size, &con->ip_port) : 0; + len = sendpriority ? net_send(con->ns, logger, con->sock, packet, packet_size, &con->ip_port, + con->net_profile) : 0; if (len <= 0) { len = 0; @@ -179,7 +181,7 @@ int write_packet_tcp_secure_connection(const Logger *logger, TCP_Connection *con return add_priority(con, packet, packet_size, len) ? 1 : 0; } - len = net_send(con->ns, logger, con->sock, packet, packet_size, &con->ip_port); + len = net_send(con->ns, logger, con->sock, packet, packet_size, &con->ip_port, con->net_profile); if (len <= 0) { return 0; @@ -234,7 +236,7 @@ int read_tcp_packet( * return -1 on failure. */ non_null() -static uint16_t read_tcp_length(const Logger *logger, const Memory *mem, const Network *ns, Socket sock, const IP_Port *ip_port) +static uint16_t read_tcp_length(const Logger *logger, const Network *ns, Socket sock, const IP_Port *ip_port) { const uint16_t count = net_socket_data_recv_buffer(ns, sock); @@ -273,7 +275,7 @@ int read_packet_tcp_secure_connection( uint16_t max_len, const IP_Port *ip_port) { if (*next_packet_length == 0) { - const uint16_t len = read_tcp_length(logger, mem, ns, sock, ip_port); + const uint16_t len = read_tcp_length(logger, ns, sock, ip_port); if (len == (uint16_t) -1) { return -1; @@ -305,7 +307,7 @@ int read_packet_tcp_secure_connection( *next_packet_length = 0; - const int len = decrypt_data_symmetric(shared_key, recv_nonce, data_encrypted, len_packet, data); + const int len = decrypt_data_symmetric(mem, shared_key, recv_nonce, data_encrypted, len_packet, data); if (len + CRYPTO_MAC_SIZE != len_packet) { LOGGER_ERROR(logger, "decrypted length %d does not match expected length %d", len + CRYPTO_MAC_SIZE, len_packet); diff --git a/protocols/Tox/libtox/src/toxcore/TCP_common.h b/protocols/Tox/libtox/src/toxcore/TCP_common.h index 9fa136609c..dd07fd1ec5 100644 --- a/protocols/Tox/libtox/src/toxcore/TCP_common.h +++ b/protocols/Tox/libtox/src/toxcore/TCP_common.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2014 Tox project. */ @@ -10,6 +10,7 @@ #include "crypto_core.h" #include "logger.h" #include "mem.h" +#include "net_profile.h" #include "network.h" typedef struct TCP_Priority_List TCP_Priority_List; @@ -66,6 +67,10 @@ typedef struct TCP_Connection { TCP_Priority_List *priority_queue_start; TCP_Priority_List *priority_queue_end; + + // This is a shared pointer to the parent's respective Net_Profile object + // (either TCP_Server for TCP server packets or TCP_Connections for TCP client packets). + Net_Profile *net_profile; } TCP_Connection; /** diff --git a/protocols/Tox/libtox/src/toxcore/TCP_connection.c b/protocols/Tox/libtox/src/toxcore/TCP_connection.c index c7161a9289..42269ad553 100644 --- a/protocols/Tox/libtox/src/toxcore/TCP_connection.c +++ b/protocols/Tox/libtox/src/toxcore/TCP_connection.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2015 Tox project. */ @@ -20,6 +20,7 @@ #include "logger.h" #include "mem.h" #include "mono_time.h" +#include "net_profile.h" #include "network.h" #include "util.h" @@ -56,6 +57,9 @@ struct TCP_Connections { bool onion_status; uint16_t onion_num_conns; + + /* Network profile for all TCP client packets. */ + Net_Profile *net_profile; }; static const TCP_Connection_to empty_tcp_connection_to = {0}; @@ -928,7 +932,8 @@ static int reconnect_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connec uint8_t relay_pk[CRYPTO_PUBLIC_KEY_SIZE]; memcpy(relay_pk, tcp_con_public_key(tcp_con->connection), CRYPTO_PUBLIC_KEY_SIZE); kill_tcp_connection(tcp_con->connection); - tcp_con->connection = new_tcp_connection(tcp_c->logger, tcp_c->mem, tcp_c->mono_time, tcp_c->rng, tcp_c->ns, &ip_port, relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info); + tcp_con->connection = new_tcp_connection(tcp_c->logger, tcp_c->mem, tcp_c->mono_time, tcp_c->rng, tcp_c->ns, &ip_port, relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info, + tcp_c->net_profile); if (tcp_con->connection == nullptr) { kill_tcp_relay_connection(tcp_c, tcp_connections_number); @@ -1017,7 +1022,7 @@ static int unsleep_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connecti tcp_con->connection = new_tcp_connection( tcp_c->logger, tcp_c->mem, tcp_c->mono_time, tcp_c->rng, tcp_c->ns, &tcp_con->ip_port, - tcp_con->relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info); + tcp_con->relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info, tcp_c->net_profile); if (tcp_con->connection == nullptr) { kill_tcp_relay_connection(tcp_c, tcp_connections_number); @@ -1315,7 +1320,7 @@ static int add_tcp_relay_instance(TCP_Connections *tcp_c, const IP_Port *ip_port tcp_con->connection = new_tcp_connection( tcp_c->logger, tcp_c->mem, tcp_c->mono_time, tcp_c->rng, tcp_c->ns, &ipp_copy, - relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info); + relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info, tcp_c->net_profile); if (tcp_con->connection == nullptr) { return -1; @@ -1591,7 +1596,7 @@ int set_tcp_onion_status(TCP_Connections *tcp_c, bool status) * Returns NULL on failure. */ TCP_Connections *new_tcp_connections(const Logger *logger, const Memory *mem, const Random *rng, const Network *ns, - Mono_Time *mono_time, const uint8_t *secret_key, const TCP_Proxy_Info *proxy_info) + Mono_Time *mono_time, const uint8_t *secret_key, const TCP_Proxy_Info *proxy_info, Net_Profile *tcp_np) { assert(logger != nullptr); assert(mem != nullptr); @@ -1609,6 +1614,7 @@ TCP_Connections *new_tcp_connections(const Logger *logger, const Memory *mem, co return nullptr; } + temp->net_profile = tcp_np; temp->logger = logger; temp->mem = mem; temp->rng = rng; @@ -1727,3 +1733,4 @@ void kill_tcp_connections(TCP_Connections *tcp_c) mem_delete(tcp_c->mem, tcp_c->connections); mem_delete(tcp_c->mem, tcp_c); } + diff --git a/protocols/Tox/libtox/src/toxcore/TCP_connection.h b/protocols/Tox/libtox/src/toxcore/TCP_connection.h index 2d35919f10..3ff2173503 100644 --- a/protocols/Tox/libtox/src/toxcore/TCP_connection.h +++ b/protocols/Tox/libtox/src/toxcore/TCP_connection.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2015 Tox project. */ @@ -21,6 +21,7 @@ #include "logger.h" #include "mem.h" #include "mono_time.h" +#include "net_profile.h" #include "network.h" #define TCP_CONN_NONE 0 @@ -306,7 +307,7 @@ uint32_t tcp_copy_connected_relays_index(const TCP_Connections *tcp_c, Node_form */ non_null() TCP_Connections *new_tcp_connections(const Logger *logger, const Memory *mem, const Random *rng, const Network *ns, - Mono_Time *mono_time, const uint8_t *secret_key, const TCP_Proxy_Info *proxy_info); + Mono_Time *mono_time, const uint8_t *secret_key, const TCP_Proxy_Info *proxy_info, Net_Profile *tcp_np); non_null() int kill_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number); diff --git a/protocols/Tox/libtox/src/toxcore/TCP_server.c b/protocols/Tox/libtox/src/toxcore/TCP_server.c index 1363d90220..288cd94c48 100644 --- a/protocols/Tox/libtox/src/toxcore/TCP_server.c +++ b/protocols/Tox/libtox/src/toxcore/TCP_server.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2014 Tox project. */ @@ -27,6 +27,7 @@ #include "logger.h" #include "mem.h" #include "mono_time.h" +#include "net_profile.h" #include "network.h" #include "onion.h" @@ -91,6 +92,9 @@ struct TCP_Server { uint64_t counter; BS_List accepted_key_list; + + /* Network profile for all TCP server packets. */ + Net_Profile *net_profile; }; static_assert(sizeof(TCP_Server) < 7 * 1024 * 1024, @@ -236,6 +240,7 @@ static int add_accepted(TCP_Server *tcp_server, const Mono_Time *mono_time, TCP_ tcp_server->accepted_connection_array[index].identifier = ++tcp_server->counter; tcp_server->accepted_connection_array[index].last_pinged = mono_time_get(mono_time); tcp_server->accepted_connection_array[index].ping_id = 0; + tcp_server->accepted_connection_array[index].con.net_profile = tcp_server->net_profile; return index; } @@ -327,7 +332,7 @@ static int handle_tcp_handshake(const Logger *logger, TCP_Secure_Connection *con uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; encrypt_precompute(data, self_secret_key, shared_key); uint8_t plain[TCP_HANDSHAKE_PLAIN_SIZE]; - int len = decrypt_data_symmetric(shared_key, data + CRYPTO_PUBLIC_KEY_SIZE, + int len = decrypt_data_symmetric(con->con.mem, shared_key, data + CRYPTO_PUBLIC_KEY_SIZE, data + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, TCP_HANDSHAKE_PLAIN_SIZE + CRYPTO_MAC_SIZE, plain); if (len != TCP_HANDSHAKE_PLAIN_SIZE) { @@ -347,7 +352,7 @@ static int handle_tcp_handshake(const Logger *logger, TCP_Secure_Connection *con uint8_t response[TCP_SERVER_HANDSHAKE_SIZE]; random_nonce(con->con.rng, response); - len = encrypt_data_symmetric(shared_key, response, resp_plain, TCP_HANDSHAKE_PLAIN_SIZE, + len = encrypt_data_symmetric(con->con.mem, shared_key, response, resp_plain, TCP_HANDSHAKE_PLAIN_SIZE, response + CRYPTO_NONCE_SIZE); if (len != TCP_HANDSHAKE_PLAIN_SIZE + CRYPTO_MAC_SIZE) { @@ -357,7 +362,7 @@ static int handle_tcp_handshake(const Logger *logger, TCP_Secure_Connection *con const IP_Port ipp = {{{0}}}; - if (TCP_SERVER_HANDSHAKE_SIZE != net_send(con->con.ns, logger, con->con.sock, response, TCP_SERVER_HANDSHAKE_SIZE, &ipp)) { + if (TCP_SERVER_HANDSHAKE_SIZE != net_send(con->con.ns, logger, con->con.sock, response, TCP_SERVER_HANDSHAKE_SIZE, &ipp, con->con.net_profile)) { crypto_memzero(shared_key, sizeof(shared_key)); return -1; } @@ -680,6 +685,7 @@ static int handle_tcp_packet(TCP_Server *tcp_server, uint32_t con_id, const uint } TCP_Secure_Connection *const con = &tcp_server->accepted_connection_array[con_id]; + netprof_record_packet(con->con.net_profile, data[0], length, PACKET_DIRECTION_RECV); switch (data[0]) { case TCP_PACKET_ROUTING_REQUEST: { @@ -914,7 +920,7 @@ static int accept_connection(TCP_Server *tcp_server, Socket sock) } non_null() -static Socket new_listening_tcp_socket(const Logger *logger, const Network *ns, Family family, uint16_t port) +static Socket new_listening_tcp_socket(const Logger *logger, const Memory *mem, const Network *ns, Family family, uint16_t port) { const Socket sock = net_socket(ns, family, TOX_SOCK_STREAM, TOX_PROTO_TCP); @@ -936,10 +942,9 @@ static Socket new_listening_tcp_socket(const Logger *logger, const Network *ns, ok = ok && bind_to_port(ns, sock, family, port) && (net_listen(ns, sock, TCP_MAX_BACKLOG) == 0); if (!ok) { - char *const error = net_new_strerror(net_error()); + Net_Strerror error_str; LOGGER_WARNING(logger, "could not bind to TCP port %d (family = %d): %s", - port, family.value, error != nullptr ? error : "(null)"); - net_kill_strerror(error); + port, family.value, net_strerror(net_error(), &error_str)); kill_sock(ns, sock); return net_invalid_socket(); } @@ -969,6 +974,14 @@ TCP_Server *new_tcp_server(const Logger *logger, const Memory *mem, const Random return nullptr; } + Net_Profile *np = netprof_new(logger, mem); + + if (np == nullptr) { + mem_delete(mem, temp); + return nullptr; + } + + temp->net_profile = np; temp->logger = logger; temp->mem = mem; temp->ns = ns; @@ -978,6 +991,7 @@ TCP_Server *new_tcp_server(const Logger *logger, const Memory *mem, const Random if (socks_listening == nullptr) { LOGGER_ERROR(logger, "socket allocation failed"); + netprof_kill(mem, temp->net_profile); mem_delete(mem, temp); return nullptr; } @@ -989,6 +1003,7 @@ TCP_Server *new_tcp_server(const Logger *logger, const Memory *mem, const Random if (temp->efd == -1) { LOGGER_ERROR(logger, "epoll initialisation failed"); + netprof_kill(mem, temp->net_profile); mem_delete(mem, socks_listening); mem_delete(mem, temp); return nullptr; @@ -999,7 +1014,7 @@ TCP_Server *new_tcp_server(const Logger *logger, const Memory *mem, const Random const Family family = ipv6_enabled ? net_family_ipv6() : net_family_ipv4(); for (uint32_t i = 0; i < num_sockets; ++i) { - const Socket sock = new_listening_tcp_socket(logger, ns, family, ports[i]); + const Socket sock = new_listening_tcp_socket(logger, mem, ns, family, ports[i]); if (!sock_valid(sock)) { continue; @@ -1022,6 +1037,7 @@ TCP_Server *new_tcp_server(const Logger *logger, const Memory *mem, const Random } if (temp->num_listening_socks == 0) { + netprof_kill(mem, temp->net_profile); mem_delete(mem, temp->socks_listening); mem_delete(mem, temp); return nullptr; @@ -1040,7 +1056,7 @@ TCP_Server *new_tcp_server(const Logger *logger, const Memory *mem, const Random memcpy(temp->secret_key, secret_key, CRYPTO_SECRET_KEY_SIZE); crypto_derive_public_key(temp->public_key, temp->secret_key); - bs_list_init(&temp->accepted_key_list, CRYPTO_PUBLIC_KEY_SIZE, 8, memcmp); + bs_list_init(&temp->accepted_key_list, mem, CRYPTO_PUBLIC_KEY_SIZE, 8, memcmp); return temp; } @@ -1422,6 +1438,16 @@ void kill_tcp_server(TCP_Server *tcp_server) crypto_memzero(tcp_server->secret_key, sizeof(tcp_server->secret_key)); + netprof_kill(tcp_server->mem, tcp_server->net_profile); mem_delete(tcp_server->mem, tcp_server->socks_listening); mem_delete(tcp_server->mem, tcp_server); } + +const Net_Profile *tcp_server_get_net_profile(const TCP_Server *tcp_server) +{ + if (tcp_server == nullptr) { + return nullptr; + } + + return tcp_server->net_profile; +} diff --git a/protocols/Tox/libtox/src/toxcore/TCP_server.h b/protocols/Tox/libtox/src/toxcore/TCP_server.h index 1d3933a415..bd4c98b0cd 100644 --- a/protocols/Tox/libtox/src/toxcore/TCP_server.h +++ b/protocols/Tox/libtox/src/toxcore/TCP_server.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2014 Tox project. */ @@ -15,6 +15,7 @@ #include "logger.h" #include "mem.h" #include "mono_time.h" +#include "net_profile.h" #include "network.h" #include "onion.h" @@ -52,4 +53,11 @@ void do_tcp_server(TCP_Server *tcp_server, const Mono_Time *mono_time); nullable(1) void kill_tcp_server(TCP_Server *tcp_server); +/** @brief Returns a pointer to the net profile associated with `tcp_server`. + * + * Returns null if `tcp_server` is null. + */ +nullable(1) +const Net_Profile *tcp_server_get_net_profile(const TCP_Server *tcp_server); + #endif /* C_TOXCORE_TOXCORE_TCP_SERVER_H */ diff --git a/protocols/Tox/libtox/src/toxcore/announce.c b/protocols/Tox/libtox/src/toxcore/announce.c index b983cb0574..dc34ca05e3 100644 --- a/protocols/Tox/libtox/src/toxcore/announce.c +++ b/protocols/Tox/libtox/src/toxcore/announce.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2020-2021 The TokTok team. + * Copyright © 2020-2025 The TokTok team. */ /** @@ -9,7 +9,6 @@ #include "announce.h" #include <assert.h> -#include <stdlib.h> #include <string.h> #include "DHT.h" @@ -239,9 +238,9 @@ bool announce_store_data(Announcements *announce, const uint8_t *data_public_key if (length > 0) { assert(data != nullptr); - free(entry->data); + mem_delete(announce->mem, entry->data); - uint8_t *entry_data = (uint8_t *)malloc(length); + uint8_t *entry_data = (uint8_t *)mem_balloc(announce->mem, length); if (entry_data == nullptr) { entry->data = nullptr; // TODO(iphydf): Is this necessary? @@ -451,7 +450,7 @@ static int create_reply_plain_store_announce_request(Announcements *announce, return -1; } - if (decrypt_data_symmetric(shared_key, + if (decrypt_data_symmetric(announce->mem, shared_key, data + CRYPTO_PUBLIC_KEY_SIZE, data + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, plain_len + CRYPTO_MAC_SIZE, @@ -568,7 +567,7 @@ static int create_reply(Announcements *announce, const IP_Port *source, VLA(uint8_t, plain, plain_len); const uint8_t *shared_key = dht_get_shared_key_recv(announce->dht, data + 1); - if (decrypt_data_symmetric(shared_key, + if (decrypt_data_symmetric(announce->mem, shared_key, data + 1 + CRYPTO_PUBLIC_KEY_SIZE, data + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, plain_len + CRYPTO_MAC_SIZE, @@ -579,7 +578,7 @@ static int create_reply(Announcements *announce, const IP_Port *source, const int plain_reply_max_len = (int)reply_max_length - (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_MAC_SIZE); - if (plain_reply_max_len < sizeof(uint64_t)) { + if (plain_reply_max_len < (int)sizeof(uint64_t)) { return -1; } @@ -651,7 +650,7 @@ Announcements *new_announcements(const Logger *log, const Memory *mem, const Ran return nullptr; } - Announcements *announce = (Announcements *)calloc(1, sizeof(Announcements)); + Announcements *announce = (Announcements *)mem_alloc(mem, sizeof(Announcements)); if (announce == nullptr) { return nullptr; @@ -669,7 +668,7 @@ Announcements *new_announcements(const Logger *log, const Memory *mem, const Ran new_hmac_key(announce->rng, announce->hmac_key); announce->shared_keys = shared_key_cache_new(log, mono_time, mem, announce->secret_key, KEYS_TIMEOUT, MAX_KEYS_PER_SLOT); if (announce->shared_keys == nullptr) { - free(announce); + mem_delete(announce->mem, announce); return nullptr; } @@ -700,8 +699,8 @@ void kill_announcements(Announcements *announce) shared_key_cache_free(announce->shared_keys); for (uint32_t i = 0; i < ANNOUNCE_BUCKETS * ANNOUNCE_BUCKET_SIZE; ++i) { - free(announce->entries[i].data); + mem_delete(announce->mem, announce->entries[i].data); } - free(announce); + mem_delete(announce->mem, announce); } diff --git a/protocols/Tox/libtox/src/toxcore/announce.h b/protocols/Tox/libtox/src/toxcore/announce.h index bd05088d06..c1397454ac 100644 --- a/protocols/Tox/libtox/src/toxcore/announce.h +++ b/protocols/Tox/libtox/src/toxcore/announce.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2020-2021 The TokTok team. + * Copyright © 2020-2025 The TokTok team. */ #ifndef C_TOXCORE_TOXCORE_ANNOUNCE_H diff --git a/protocols/Tox/libtox/src/toxcore/attributes.h b/protocols/Tox/libtox/src/toxcore/attributes.h index 087efe20dc..009dfa359e 100644 --- a/protocols/Tox/libtox/src/toxcore/attributes.h +++ b/protocols/Tox/libtox/src/toxcore/attributes.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2022 The TokTok team. + * Copyright © 2022-2025 The TokTok team. */ /** diff --git a/protocols/Tox/libtox/src/toxcore/bin_pack.c b/protocols/Tox/libtox/src/toxcore/bin_pack.c index 56bdc9ec75..82e9d20dd4 100644 --- a/protocols/Tox/libtox/src/toxcore/bin_pack.c +++ b/protocols/Tox/libtox/src/toxcore/bin_pack.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2022 The TokTok team. + * Copyright © 2022-2025 The TokTok team. */ #include "bin_pack.h" diff --git a/protocols/Tox/libtox/src/toxcore/bin_pack.h b/protocols/Tox/libtox/src/toxcore/bin_pack.h index ce6926a448..4b2927f972 100644 --- a/protocols/Tox/libtox/src/toxcore/bin_pack.h +++ b/protocols/Tox/libtox/src/toxcore/bin_pack.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2022 The TokTok team. + * Copyright © 2022-2025 The TokTok team. */ #ifndef C_TOXCORE_TOXCORE_BIN_PACK_H #define C_TOXCORE_TOXCORE_BIN_PACK_H diff --git a/protocols/Tox/libtox/src/toxcore/bin_unpack.c b/protocols/Tox/libtox/src/toxcore/bin_unpack.c index d6b1c52ea5..e3110946bf 100644 --- a/protocols/Tox/libtox/src/toxcore/bin_unpack.c +++ b/protocols/Tox/libtox/src/toxcore/bin_unpack.c @@ -1,18 +1,20 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2022 The TokTok team. + * Copyright © 2022-2025 The TokTok team. */ #include "bin_unpack.h" #include <assert.h> -#include <stdlib.h> #include <string.h> #include "../third_party/cmp/cmp.h" #include "attributes.h" #include "ccompat.h" +#include "mem.h" struct Bin_Unpack { + const Memory *mem; + const uint8_t *bytes; uint32_t bytes_size; cmp_ctx_t ctx; @@ -54,17 +56,18 @@ static size_t null_writer(cmp_ctx_t *ctx, const void *data, size_t count) } non_null() -static void bin_unpack_init(Bin_Unpack *bu, const uint8_t *buf, uint32_t buf_size) +static void bin_unpack_init(Bin_Unpack *bu, const Memory *mem, const uint8_t *buf, uint32_t buf_size) { + bu->mem = mem; bu->bytes = buf; bu->bytes_size = buf_size; cmp_init(&bu->ctx, bu, buf_reader, buf_skipper, null_writer); } -bool bin_unpack_obj(bin_unpack_cb *callback, void *obj, const uint8_t *buf, uint32_t buf_size) +bool bin_unpack_obj(const Memory *mem, bin_unpack_cb *callback, void *obj, const uint8_t *buf, uint32_t buf_size) { Bin_Unpack bu; - bin_unpack_init(&bu, buf, buf_size); + bin_unpack_init(&bu, mem, buf, buf_size); return callback(obj, &bu); } @@ -120,10 +123,14 @@ bool bin_unpack_bin(Bin_Unpack *bu, uint8_t **data_ptr, uint32_t *data_length_pt // There aren't as many bytes as this bin claims to want to allocate. return false; } - uint8_t *const data = (uint8_t *)malloc(bin_size); + uint8_t *const data = (uint8_t *)mem_balloc(bu->mem, bin_size); + + if (data == nullptr) { + return false; + } if (!bin_unpack_bin_b(bu, data, bin_size)) { - free(data); + mem_delete(bu->mem, data); return false; } diff --git a/protocols/Tox/libtox/src/toxcore/bin_unpack.h b/protocols/Tox/libtox/src/toxcore/bin_unpack.h index 0554bd1a7a..029c3a0d0a 100644 --- a/protocols/Tox/libtox/src/toxcore/bin_unpack.h +++ b/protocols/Tox/libtox/src/toxcore/bin_unpack.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2022 The TokTok team. + * Copyright © 2022-2025 The TokTok team. */ #ifndef C_TOXCORE_TOXCORE_BIN_UNPACK_H @@ -9,6 +9,7 @@ #include <stdint.h> #include "attributes.h" +#include "mem.h" #ifdef __cplusplus extern "C" { @@ -46,7 +47,7 @@ typedef bool bin_unpack_cb(void *obj, Bin_Unpack *bu); * @retval false if an error occurred (e.g. buffer overrun). */ non_null() -bool bin_unpack_obj(bin_unpack_cb *callback, void *obj, const uint8_t *buf, uint32_t buf_size); +bool bin_unpack_obj(const Memory *mem, bin_unpack_cb *callback, void *obj, const uint8_t *buf, uint32_t buf_size); /** @brief Start unpacking a MessagePack array. * diff --git a/protocols/Tox/libtox/src/toxcore/ccompat.c b/protocols/Tox/libtox/src/toxcore/ccompat.c index 6e4689736a..3ac18a270e 100644 --- a/protocols/Tox/libtox/src/toxcore/ccompat.c +++ b/protocols/Tox/libtox/src/toxcore/ccompat.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2022 The TokTok team. + * Copyright © 2022-2025 The TokTok team. */ #include "ccompat.h" diff --git a/protocols/Tox/libtox/src/toxcore/ccompat.h b/protocols/Tox/libtox/src/toxcore/ccompat.h index 47ab9ed2bf..df68413741 100644 --- a/protocols/Tox/libtox/src/toxcore/ccompat.h +++ b/protocols/Tox/libtox/src/toxcore/ccompat.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2021 The TokTok team. + * Copyright © 2016-2025 The TokTok team. */ /** diff --git a/protocols/Tox/libtox/src/toxcore/crypto_core.c b/protocols/Tox/libtox/src/toxcore/crypto_core.c index 7bb5bb929f..8a6aa38fba 100644 --- a/protocols/Tox/libtox/src/toxcore/crypto_core.c +++ b/protocols/Tox/libtox/src/toxcore/crypto_core.c @@ -1,18 +1,18 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2024 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ #include "crypto_core.h" #include <assert.h> -#include <stdlib.h> #include <string.h> #include <sodium.h> #include "attributes.h" #include "ccompat.h" +#include "mem.h" #include "util.h" static_assert(CRYPTO_PUBLIC_KEY_SIZE == crypto_box_PUBLICKEYBYTES, @@ -88,9 +88,10 @@ const uint8_t *get_chat_id(const Extended_Public_Key *key) } #if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) -static uint8_t *crypto_malloc(size_t bytes) +non_null() +static uint8_t *crypto_malloc(const Memory *mem, size_t bytes) { - uint8_t *ptr = (uint8_t *)malloc(bytes); + uint8_t *ptr = (uint8_t *)mem_balloc(mem, bytes); if (ptr != nullptr) { crypto_memlock(ptr, bytes); @@ -99,15 +100,15 @@ static uint8_t *crypto_malloc(size_t bytes) return ptr; } -nullable(1) -static void crypto_free(uint8_t *ptr, size_t bytes) +non_null(1) nullable(2) +static void crypto_free(const Memory *mem, uint8_t *ptr, size_t bytes) { if (ptr != nullptr) { crypto_memzero(ptr, bytes); crypto_memunlock(ptr, bytes); } - free(ptr); + mem_delete(mem, ptr); } #endif /* !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) */ @@ -240,7 +241,8 @@ int32_t encrypt_precompute(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE], #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ } -int32_t encrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE], +int32_t encrypt_data_symmetric(const Memory *mem, + const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE], const uint8_t nonce[CRYPTO_NONCE_SIZE], const uint8_t *plain, size_t length, uint8_t *encrypted) { @@ -258,12 +260,12 @@ int32_t encrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE], const size_t size_temp_plain = length + crypto_box_ZEROBYTES; const size_t size_temp_encrypted = length + crypto_box_MACBYTES + crypto_box_BOXZEROBYTES; - uint8_t *temp_plain = crypto_malloc(size_temp_plain); - uint8_t *temp_encrypted = crypto_malloc(size_temp_encrypted); + uint8_t *temp_plain = crypto_malloc(mem, size_temp_plain); + uint8_t *temp_encrypted = crypto_malloc(mem, size_temp_encrypted); if (temp_plain == nullptr || temp_encrypted == nullptr) { - crypto_free(temp_plain, size_temp_plain); - crypto_free(temp_encrypted, size_temp_encrypted); + crypto_free(mem, temp_plain, size_temp_plain); + crypto_free(mem, temp_encrypted, size_temp_encrypted); return -1; } @@ -278,22 +280,23 @@ int32_t encrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE], if (crypto_box_afternm(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, shared_key) != 0) { - crypto_free(temp_plain, size_temp_plain); - crypto_free(temp_encrypted, size_temp_encrypted); + crypto_free(mem, temp_plain, size_temp_plain); + crypto_free(mem, temp_encrypted, size_temp_encrypted); return -1; } // Unpad the encrypted message. memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length + crypto_box_MACBYTES); - crypto_free(temp_plain, size_temp_plain); - crypto_free(temp_encrypted, size_temp_encrypted); + crypto_free(mem, temp_plain, size_temp_plain); + crypto_free(mem, temp_encrypted, size_temp_encrypted); #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ assert(length < INT32_MAX - crypto_box_MACBYTES); return (int32_t)(length + crypto_box_MACBYTES); } -int32_t decrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE], +int32_t decrypt_data_symmetric(const Memory *mem, + const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE], const uint8_t nonce[CRYPTO_NONCE_SIZE], const uint8_t *encrypted, size_t length, uint8_t *plain) { @@ -310,12 +313,12 @@ int32_t decrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE], const size_t size_temp_plain = length + crypto_box_ZEROBYTES; const size_t size_temp_encrypted = length + crypto_box_BOXZEROBYTES; - uint8_t *temp_plain = crypto_malloc(size_temp_plain); - uint8_t *temp_encrypted = crypto_malloc(size_temp_encrypted); + uint8_t *temp_plain = crypto_malloc(mem, size_temp_plain); + uint8_t *temp_encrypted = crypto_malloc(mem, size_temp_encrypted); if (temp_plain == nullptr || temp_encrypted == nullptr) { - crypto_free(temp_plain, size_temp_plain); - crypto_free(temp_encrypted, size_temp_encrypted); + crypto_free(mem, temp_plain, size_temp_plain); + crypto_free(mem, temp_encrypted, size_temp_encrypted); return -1; } @@ -330,22 +333,23 @@ int32_t decrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE], if (crypto_box_open_afternm(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, nonce, shared_key) != 0) { - crypto_free(temp_plain, size_temp_plain); - crypto_free(temp_encrypted, size_temp_encrypted); + crypto_free(mem, temp_plain, size_temp_plain); + crypto_free(mem, temp_encrypted, size_temp_encrypted); return -1; } memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_MACBYTES); - crypto_free(temp_plain, size_temp_plain); - crypto_free(temp_encrypted, size_temp_encrypted); + crypto_free(mem, temp_plain, size_temp_plain); + crypto_free(mem, temp_encrypted, size_temp_encrypted); #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ assert(length > crypto_box_MACBYTES); assert(length < INT32_MAX); return (int32_t)(length - crypto_box_MACBYTES); } -int32_t encrypt_data(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE], +int32_t encrypt_data(const Memory *mem, + const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE], const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE], const uint8_t nonce[CRYPTO_NONCE_SIZE], const uint8_t *plain, size_t length, uint8_t *encrypted) @@ -356,12 +360,13 @@ int32_t encrypt_data(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE], uint8_t k[crypto_box_BEFORENMBYTES]; encrypt_precompute(public_key, secret_key, k); - const int ret = encrypt_data_symmetric(k, nonce, plain, length, encrypted); + const int ret = encrypt_data_symmetric(mem, k, nonce, plain, length, encrypted); crypto_memzero(k, sizeof(k)); return ret; } -int32_t decrypt_data(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE], +int32_t decrypt_data(const Memory *mem, + const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE], const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE], const uint8_t nonce[CRYPTO_NONCE_SIZE], const uint8_t *encrypted, size_t length, uint8_t *plain) @@ -372,7 +377,7 @@ int32_t decrypt_data(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE], uint8_t k[crypto_box_BEFORENMBYTES]; encrypt_precompute(public_key, secret_key, k); - const int ret = decrypt_data_symmetric(k, nonce, encrypted, length, plain); + const int ret = decrypt_data_symmetric(mem, k, nonce, encrypted, length, plain); crypto_memzero(k, sizeof(k)); return ret; } diff --git a/protocols/Tox/libtox/src/toxcore/crypto_core.h b/protocols/Tox/libtox/src/toxcore/crypto_core.h index 979791bd97..558118e397 100644 --- a/protocols/Tox/libtox/src/toxcore/crypto_core.h +++ b/protocols/Tox/libtox/src/toxcore/crypto_core.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2024 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ @@ -16,6 +16,7 @@ #include <stdint.h> #include "attributes.h" +#include "mem.h" #ifdef __cplusplus extern "C" { @@ -386,7 +387,8 @@ void crypto_derive_public_key(uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE], * @return length of encrypted data if everything was fine. */ non_null() -int32_t encrypt_data(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE], +int32_t encrypt_data(const Memory *mem, + const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE], const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE], const uint8_t nonce[CRYPTO_NONCE_SIZE], const uint8_t *plain, size_t length, uint8_t *encrypted); @@ -403,7 +405,8 @@ int32_t encrypt_data(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE], * @return length of plain text data if everything was fine. */ non_null() -int32_t decrypt_data(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE], +int32_t decrypt_data(const Memory *mem, + const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE], const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE], const uint8_t nonce[CRYPTO_NONCE_SIZE], const uint8_t *encrypted, size_t length, uint8_t *plain); @@ -431,7 +434,8 @@ int32_t encrypt_precompute(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE], * @return length of encrypted data if everything was fine. */ non_null() -int32_t encrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE], +int32_t encrypt_data_symmetric(const Memory *mem, + const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE], const uint8_t nonce[CRYPTO_NONCE_SIZE], const uint8_t *plain, size_t length, uint8_t *encrypted); @@ -446,7 +450,8 @@ int32_t encrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE], * @return length of plain data if everything was fine. */ non_null() -int32_t decrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE], +int32_t decrypt_data_symmetric(const Memory *mem, + const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE], const uint8_t nonce[CRYPTO_NONCE_SIZE], const uint8_t *encrypted, size_t length, uint8_t *plain); diff --git a/protocols/Tox/libtox/src/toxcore/crypto_core_pack.c b/protocols/Tox/libtox/src/toxcore/crypto_core_pack.c index a173d39d8d..4c08fc7d2a 100644 --- a/protocols/Tox/libtox/src/toxcore/crypto_core_pack.c +++ b/protocols/Tox/libtox/src/toxcore/crypto_core_pack.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2024 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ diff --git a/protocols/Tox/libtox/src/toxcore/crypto_core_pack.h b/protocols/Tox/libtox/src/toxcore/crypto_core_pack.h index 1efefff840..85b47ff4e4 100644 --- a/protocols/Tox/libtox/src/toxcore/crypto_core_pack.h +++ b/protocols/Tox/libtox/src/toxcore/crypto_core_pack.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2024 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ diff --git a/protocols/Tox/libtox/src/toxcore/events/conference_connected.c b/protocols/Tox/libtox/src/toxcore/events/conference_connected.c index dbd9e4b51a..d19f0191a2 100644 --- a/protocols/Tox/libtox/src/toxcore/events/conference_connected.c +++ b/protocols/Tox/libtox/src/toxcore/events/conference_connected.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -12,6 +12,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" /***************************************************** @@ -109,7 +110,10 @@ static Tox_Event_Conference_Connected *tox_events_add_conference_connected(Tox_E event.type = TOX_EVENT_CONFERENCE_CONNECTED; event.data.conference_connected = conference_connected; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_conference_connected_free(conference_connected, mem); + return nullptr; + } return conference_connected; } diff --git a/protocols/Tox/libtox/src/toxcore/events/conference_invite.c b/protocols/Tox/libtox/src/toxcore/events/conference_invite.c index fb1f794bf3..04206e768f 100644 --- a/protocols/Tox/libtox/src/toxcore/events/conference_invite.c +++ b/protocols/Tox/libtox/src/toxcore/events/conference_invite.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -14,6 +14,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" #include "../tox_pack.h" #include "../tox_unpack.h" @@ -177,7 +178,10 @@ static Tox_Event_Conference_Invite *tox_events_add_conference_invite(Tox_Events event.type = TOX_EVENT_CONFERENCE_INVITE; event.data.conference_invite = conference_invite; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_conference_invite_free(conference_invite, mem); + return nullptr; + } return conference_invite; } diff --git a/protocols/Tox/libtox/src/toxcore/events/conference_message.c b/protocols/Tox/libtox/src/toxcore/events/conference_message.c index 74e1123e01..7cef201a35 100644 --- a/protocols/Tox/libtox/src/toxcore/events/conference_message.c +++ b/protocols/Tox/libtox/src/toxcore/events/conference_message.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -14,6 +14,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" #include "../tox_pack.h" #include "../tox_unpack.h" @@ -193,7 +194,10 @@ static Tox_Event_Conference_Message *tox_events_add_conference_message(Tox_Event event.type = TOX_EVENT_CONFERENCE_MESSAGE; event.data.conference_message = conference_message; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_conference_message_free(conference_message, mem); + return nullptr; + } return conference_message; } diff --git a/protocols/Tox/libtox/src/toxcore/events/conference_peer_list_changed.c b/protocols/Tox/libtox/src/toxcore/events/conference_peer_list_changed.c index 050bfb08f8..68744208d6 100644 --- a/protocols/Tox/libtox/src/toxcore/events/conference_peer_list_changed.c +++ b/protocols/Tox/libtox/src/toxcore/events/conference_peer_list_changed.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -12,6 +12,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" /***************************************************** @@ -109,7 +110,10 @@ static Tox_Event_Conference_Peer_List_Changed *tox_events_add_conference_peer_li event.type = TOX_EVENT_CONFERENCE_PEER_LIST_CHANGED; event.data.conference_peer_list_changed = conference_peer_list_changed; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_conference_peer_list_changed_free(conference_peer_list_changed, mem); + return nullptr; + } return conference_peer_list_changed; } diff --git a/protocols/Tox/libtox/src/toxcore/events/conference_peer_name.c b/protocols/Tox/libtox/src/toxcore/events/conference_peer_name.c index fc6c255791..36de6ba9c2 100644 --- a/protocols/Tox/libtox/src/toxcore/events/conference_peer_name.c +++ b/protocols/Tox/libtox/src/toxcore/events/conference_peer_name.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -14,6 +14,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" /***************************************************** @@ -175,7 +176,10 @@ static Tox_Event_Conference_Peer_Name *tox_events_add_conference_peer_name(Tox_E event.type = TOX_EVENT_CONFERENCE_PEER_NAME; event.data.conference_peer_name = conference_peer_name; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_conference_peer_name_free(conference_peer_name, mem); + return nullptr; + } return conference_peer_name; } diff --git a/protocols/Tox/libtox/src/toxcore/events/conference_title.c b/protocols/Tox/libtox/src/toxcore/events/conference_title.c index d761f51285..cd92ba1651 100644 --- a/protocols/Tox/libtox/src/toxcore/events/conference_title.c +++ b/protocols/Tox/libtox/src/toxcore/events/conference_title.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -14,6 +14,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" /***************************************************** @@ -175,7 +176,10 @@ static Tox_Event_Conference_Title *tox_events_add_conference_title(Tox_Events *e event.type = TOX_EVENT_CONFERENCE_TITLE; event.data.conference_title = conference_title; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_conference_title_free(conference_title, mem); + return nullptr; + } return conference_title; } diff --git a/protocols/Tox/libtox/src/toxcore/events/dht_get_nodes_response.c b/protocols/Tox/libtox/src/toxcore/events/dht_get_nodes_response.c deleted file mode 100644 index 6e03b73ea4..0000000000 --- a/protocols/Tox/libtox/src/toxcore/events/dht_get_nodes_response.c +++ /dev/null @@ -1,223 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2022 The TokTok team. - */ - -#include "events_alloc.h" - -#include <assert.h> -#include <string.h> - -#include "../attributes.h" -#include "../bin_pack.h" -#include "../bin_unpack.h" -#include "../ccompat.h" -#include "../mem.h" -#include "../tox.h" -#include "../tox_events.h" -#include "../tox_private.h" - -/***************************************************** - * - * :: struct and accessors - * - *****************************************************/ - -struct Tox_Event_Dht_Get_Nodes_Response { - uint8_t public_key[TOX_PUBLIC_KEY_SIZE]; - uint8_t *ip; - uint32_t ip_length; - uint16_t port; -}; - -non_null() -static bool tox_event_dht_get_nodes_response_set_public_key(Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response, const uint8_t public_key[TOX_PUBLIC_KEY_SIZE]) -{ - memcpy(dht_get_nodes_response->public_key, public_key, TOX_PUBLIC_KEY_SIZE); - return true; -} -const uint8_t *tox_event_dht_get_nodes_response_get_public_key(const Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response) -{ - return dht_get_nodes_response->public_key; -} - -non_null() -static bool tox_event_dht_get_nodes_response_set_ip(Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response, - const char *ip, uint32_t ip_length, const Memory *mem) -{ - if (dht_get_nodes_response->ip != nullptr) { - mem_delete(mem, dht_get_nodes_response->ip); - dht_get_nodes_response->ip = nullptr; - dht_get_nodes_response->ip_length = 0; - } - - uint8_t *ip_tmp = (uint8_t *)mem_balloc(mem, ip_length); - - if (ip_tmp == nullptr) { - return false; - } - - memcpy(ip_tmp, ip, ip_length); - dht_get_nodes_response->ip = ip_tmp; - dht_get_nodes_response->ip_length = ip_length; - return true; -} -uint32_t tox_event_dht_get_nodes_response_get_ip_length(const Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response) -{ - return dht_get_nodes_response->ip_length; -} -const uint8_t *tox_event_dht_get_nodes_response_get_ip(const Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response) -{ - return dht_get_nodes_response->ip; -} - -non_null() -static bool tox_event_dht_get_nodes_response_set_port(Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response, uint16_t port) -{ - dht_get_nodes_response->port = port; - return true; -} -uint16_t tox_event_dht_get_nodes_response_get_port(const Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response) -{ - return dht_get_nodes_response->port; -} - -non_null() -static void tox_event_dht_get_nodes_response_construct(Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response) -{ - *dht_get_nodes_response = (Tox_Event_Dht_Get_Nodes_Response) { - { - 0 - } - }; -} -non_null() -static void tox_event_dht_get_nodes_response_destruct(Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response, const Memory *mem) -{ - mem_delete(mem, dht_get_nodes_response->ip); -} - -bool tox_event_dht_get_nodes_response_pack( - const Tox_Event_Dht_Get_Nodes_Response *event, Bin_Pack *bp) -{ - return bin_pack_array(bp, 3) - && bin_pack_bin(bp, event->public_key, TOX_PUBLIC_KEY_SIZE) - && bin_pack_bin(bp, event->ip, event->ip_length) - && bin_pack_u16(bp, event->port); -} - -non_null() -static bool tox_event_dht_get_nodes_response_unpack_into( - Tox_Event_Dht_Get_Nodes_Response *event, Bin_Unpack *bu) -{ - if (!bin_unpack_array_fixed(bu, 3, nullptr)) { - return false; - } - - return bin_unpack_bin_fixed(bu, event->public_key, TOX_PUBLIC_KEY_SIZE) - && bin_unpack_bin(bu, &event->ip, &event->ip_length) - && bin_unpack_u16(bu, &event->port); -} - -const Tox_Event_Dht_Get_Nodes_Response *tox_event_get_dht_get_nodes_response( - const Tox_Event *event) -{ - return event->type == TOX_EVENT_DHT_GET_NODES_RESPONSE ? event->data.dht_get_nodes_response : nullptr; -} - -Tox_Event_Dht_Get_Nodes_Response *tox_event_dht_get_nodes_response_new(const Memory *mem) -{ - Tox_Event_Dht_Get_Nodes_Response *const dht_get_nodes_response = - (Tox_Event_Dht_Get_Nodes_Response *)mem_alloc(mem, sizeof(Tox_Event_Dht_Get_Nodes_Response)); - - if (dht_get_nodes_response == nullptr) { - return nullptr; - } - - tox_event_dht_get_nodes_response_construct(dht_get_nodes_response); - return dht_get_nodes_response; -} - -void tox_event_dht_get_nodes_response_free(Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response, const Memory *mem) -{ - if (dht_get_nodes_response != nullptr) { - tox_event_dht_get_nodes_response_destruct(dht_get_nodes_response, mem); - } - mem_delete(mem, dht_get_nodes_response); -} - -non_null() -static Tox_Event_Dht_Get_Nodes_Response *tox_events_add_dht_get_nodes_response(Tox_Events *events, const Memory *mem) -{ - Tox_Event_Dht_Get_Nodes_Response *const dht_get_nodes_response = tox_event_dht_get_nodes_response_new(mem); - - if (dht_get_nodes_response == nullptr) { - return nullptr; - } - - Tox_Event event; - event.type = TOX_EVENT_DHT_GET_NODES_RESPONSE; - event.data.dht_get_nodes_response = dht_get_nodes_response; - - tox_events_add(events, &event); - return dht_get_nodes_response; -} - -bool tox_event_dht_get_nodes_response_unpack( - Tox_Event_Dht_Get_Nodes_Response **event, Bin_Unpack *bu, const Memory *mem) -{ - *event = tox_event_dht_get_nodes_response_new(mem); - - if (*event == nullptr) { - return false; - } - - return tox_event_dht_get_nodes_response_unpack_into(*event, bu); -} - -non_null() -static Tox_Event_Dht_Get_Nodes_Response *tox_event_dht_get_nodes_response_alloc(void *user_data) -{ - Tox_Events_State *state = tox_events_alloc(user_data); - assert(state != nullptr); - - if (state->events == nullptr) { - return nullptr; - } - - Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response = tox_events_add_dht_get_nodes_response(state->events, state->mem); - - if (dht_get_nodes_response == nullptr) { - state->error = TOX_ERR_EVENTS_ITERATE_MALLOC; - return nullptr; - } - - return dht_get_nodes_response; -} - -/***************************************************** - * - * :: event handler - * - *****************************************************/ - -void tox_events_handle_dht_get_nodes_response( - Tox *tox, const uint8_t public_key[TOX_PUBLIC_KEY_SIZE], - const char *ip, uint16_t port, void *user_data) -{ - Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response = tox_event_dht_get_nodes_response_alloc(user_data); - - if (dht_get_nodes_response == nullptr) { - return; - } - - const size_t ip_length = strlen(ip); - if (ip_length >= UINT32_MAX) { - return; - } - - const Tox_System *sys = tox_get_system(tox); - - tox_event_dht_get_nodes_response_set_public_key(dht_get_nodes_response, public_key); - tox_event_dht_get_nodes_response_set_ip(dht_get_nodes_response, ip, ip_length + 1, sys->mem); - tox_event_dht_get_nodes_response_set_port(dht_get_nodes_response, port); -} diff --git a/protocols/Tox/libtox/src/toxcore/events/dht_nodes_response.c b/protocols/Tox/libtox/src/toxcore/events/dht_nodes_response.c new file mode 100644 index 0000000000..7a3f5f2730 --- /dev/null +++ b/protocols/Tox/libtox/src/toxcore/events/dht_nodes_response.c @@ -0,0 +1,222 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022-2025 The TokTok team. + */ + +#include "events_alloc.h" + +#include <assert.h> +#include <string.h> + +#include "../attributes.h" +#include "../bin_pack.h" +#include "../bin_unpack.h" +#include "../ccompat.h" +#include "../mem.h" +#include "../tox.h" +#include "../tox_event.h" +#include "../tox_events.h" +#include "../tox_private.h" + +/***************************************************** + * + * :: struct and accessors + * + *****************************************************/ + +struct Tox_Event_Dht_Nodes_Response { + uint8_t public_key[TOX_PUBLIC_KEY_SIZE]; + uint8_t *ip; + uint32_t ip_length; + uint16_t port; +}; + +non_null() +static bool tox_event_dht_nodes_response_set_public_key(Tox_Event_Dht_Nodes_Response *dht_nodes_response, const uint8_t public_key[TOX_PUBLIC_KEY_SIZE]) +{ + memcpy(dht_nodes_response->public_key, public_key, TOX_PUBLIC_KEY_SIZE); + return true; +} +const uint8_t *tox_event_dht_nodes_response_get_public_key(const Tox_Event_Dht_Nodes_Response *dht_nodes_response) +{ + return dht_nodes_response->public_key; +} + +non_null() +static bool tox_event_dht_nodes_response_set_ip(Tox_Event_Dht_Nodes_Response *dht_nodes_response, + const char *ip, uint32_t ip_length, const Memory *mem) +{ + if (dht_nodes_response->ip != nullptr) { + mem_delete(mem, dht_nodes_response->ip); + dht_nodes_response->ip = nullptr; + dht_nodes_response->ip_length = 0; + } + + uint8_t *ip_tmp = (uint8_t *)mem_balloc(mem, ip_length + 1); + + if (ip_tmp == nullptr) { + return false; + } + + memcpy(ip_tmp, ip, ip_length + 1); + dht_nodes_response->ip = ip_tmp; + dht_nodes_response->ip_length = ip_length; + return true; +} +uint32_t tox_event_dht_nodes_response_get_ip_length(const Tox_Event_Dht_Nodes_Response *dht_nodes_response) +{ + return dht_nodes_response->ip_length; +} +const uint8_t *tox_event_dht_nodes_response_get_ip(const Tox_Event_Dht_Nodes_Response *dht_nodes_response) +{ + return dht_nodes_response->ip; +} + +non_null() +static bool tox_event_dht_nodes_response_set_port(Tox_Event_Dht_Nodes_Response *dht_nodes_response, uint16_t port) +{ + dht_nodes_response->port = port; + return true; +} +uint16_t tox_event_dht_nodes_response_get_port(const Tox_Event_Dht_Nodes_Response *dht_nodes_response) +{ + return dht_nodes_response->port; +} + +non_null() +static void tox_event_dht_nodes_response_construct(Tox_Event_Dht_Nodes_Response *dht_nodes_response) +{ + *dht_nodes_response = (Tox_Event_Dht_Nodes_Response) { + { + 0 + } + }; +} +non_null() +static void tox_event_dht_nodes_response_destruct(Tox_Event_Dht_Nodes_Response *dht_nodes_response, const Memory *mem) +{ + mem_delete(mem, dht_nodes_response->ip); +} + +bool tox_event_dht_nodes_response_pack( + const Tox_Event_Dht_Nodes_Response *event, Bin_Pack *bp) +{ + return bin_pack_array(bp, 3) + && bin_pack_bin(bp, event->public_key, TOX_PUBLIC_KEY_SIZE) + && bin_pack_bin(bp, event->ip, event->ip_length) + && bin_pack_u16(bp, event->port); +} + +non_null() +static bool tox_event_dht_nodes_response_unpack_into( + Tox_Event_Dht_Nodes_Response *event, Bin_Unpack *bu) +{ + if (!bin_unpack_array_fixed(bu, 3, nullptr)) { + return false; + } + + return bin_unpack_bin_fixed(bu, event->public_key, TOX_PUBLIC_KEY_SIZE) + && bin_unpack_bin(bu, &event->ip, &event->ip_length) + && bin_unpack_u16(bu, &event->port); +} + +const Tox_Event_Dht_Nodes_Response *tox_event_get_dht_nodes_response( + const Tox_Event *event) +{ + return event->type == TOX_EVENT_DHT_NODES_RESPONSE ? event->data.dht_nodes_response : nullptr; +} + +Tox_Event_Dht_Nodes_Response *tox_event_dht_nodes_response_new(const Memory *mem) +{ + Tox_Event_Dht_Nodes_Response *const dht_nodes_response = + (Tox_Event_Dht_Nodes_Response *)mem_alloc(mem, sizeof(Tox_Event_Dht_Nodes_Response)); + + if (dht_nodes_response == nullptr) { + return nullptr; + } + + tox_event_dht_nodes_response_construct(dht_nodes_response); + return dht_nodes_response; +} + +void tox_event_dht_nodes_response_free(Tox_Event_Dht_Nodes_Response *dht_nodes_response, const Memory *mem) +{ + if (dht_nodes_response != nullptr) { + tox_event_dht_nodes_response_destruct(dht_nodes_response, mem); + } + mem_delete(mem, dht_nodes_response); +} + +non_null() +static Tox_Event_Dht_Nodes_Response *tox_events_add_dht_nodes_response(Tox_Events *events, const Memory *mem) +{ + Tox_Event_Dht_Nodes_Response *const dht_nodes_response = tox_event_dht_nodes_response_new(mem); + + if (dht_nodes_response == nullptr) { + return nullptr; + } + + Tox_Event event; + event.type = TOX_EVENT_DHT_NODES_RESPONSE; + event.data.dht_nodes_response = dht_nodes_response; + + if (!tox_events_add(events, &event)) { + tox_event_dht_nodes_response_free(dht_nodes_response, mem); + return nullptr; + } + return dht_nodes_response; +} + +bool tox_event_dht_nodes_response_unpack( + Tox_Event_Dht_Nodes_Response **event, Bin_Unpack *bu, const Memory *mem) +{ + *event = tox_event_dht_nodes_response_new(mem); + + if (*event == nullptr) { + return false; + } + + return tox_event_dht_nodes_response_unpack_into(*event, bu); +} + +non_null() +static Tox_Event_Dht_Nodes_Response *tox_event_dht_nodes_response_alloc(void *user_data) +{ + Tox_Events_State *state = tox_events_alloc(user_data); + assert(state != nullptr); + + if (state->events == nullptr) { + return nullptr; + } + + Tox_Event_Dht_Nodes_Response *dht_nodes_response = tox_events_add_dht_nodes_response(state->events, state->mem); + + if (dht_nodes_response == nullptr) { + state->error = TOX_ERR_EVENTS_ITERATE_MALLOC; + return nullptr; + } + + return dht_nodes_response; +} + +/***************************************************** + * + * :: event handler + * + *****************************************************/ + +void tox_events_handle_dht_nodes_response( + Tox *tox, const uint8_t public_key[TOX_PUBLIC_KEY_SIZE], + const char *ip, uint32_t ip_length, uint16_t port, void *user_data) +{ + Tox_Event_Dht_Nodes_Response *dht_nodes_response = tox_event_dht_nodes_response_alloc(user_data); + + if (dht_nodes_response == nullptr) { + return; + } + + const Tox_System *sys = tox_get_system(tox); + + tox_event_dht_nodes_response_set_public_key(dht_nodes_response, public_key); + tox_event_dht_nodes_response_set_ip(dht_nodes_response, ip, ip_length, sys->mem); + tox_event_dht_nodes_response_set_port(dht_nodes_response, port); +} diff --git a/protocols/Tox/libtox/src/toxcore/events/events_alloc.c b/protocols/Tox/libtox/src/toxcore/events/events_alloc.c index 24eebb3124..18405ea90d 100644 --- a/protocols/Tox/libtox/src/toxcore/events/events_alloc.c +++ b/protocols/Tox/libtox/src/toxcore/events/events_alloc.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2022 The TokTok team. + * Copyright © 2022-2025 The TokTok team. */ #include "events_alloc.h" diff --git a/protocols/Tox/libtox/src/toxcore/events/events_alloc.h b/protocols/Tox/libtox/src/toxcore/events/events_alloc.h index a40db97052..d0343d9ccb 100644 --- a/protocols/Tox/libtox/src/toxcore/events/events_alloc.h +++ b/protocols/Tox/libtox/src/toxcore/events/events_alloc.h @@ -1,16 +1,13 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2022 The TokTok team. + * Copyright © 2022-2025 The TokTok team. */ #ifndef C_TOXCORE_TOXCORE_EVENTS_EVENTS_ALLOC_H #define C_TOXCORE_TOXCORE_EVENTS_EVENTS_ALLOC_H #include "../attributes.h" -#include "../bin_pack.h" -#include "../bin_unpack.h" #include "../mem.h" #include "../tox.h" -#include "../tox_event.h" #include "../tox_events.h" #include "../tox_private.h" @@ -38,7 +35,7 @@ tox_conference_message_cb tox_events_handle_conference_message; tox_conference_peer_list_changed_cb tox_events_handle_conference_peer_list_changed; tox_conference_peer_name_cb tox_events_handle_conference_peer_name; tox_conference_title_cb tox_events_handle_conference_title; -tox_dht_get_nodes_response_cb tox_events_handle_dht_get_nodes_response; +tox_dht_nodes_response_cb tox_events_handle_dht_nodes_response; tox_file_chunk_request_cb tox_events_handle_file_chunk_request; tox_file_recv_cb tox_events_handle_file_recv; tox_file_recv_chunk_cb tox_events_handle_file_recv_chunk; diff --git a/protocols/Tox/libtox/src/toxcore/events/file_chunk_request.c b/protocols/Tox/libtox/src/toxcore/events/file_chunk_request.c index 4117ef3c4b..d59b7a5ba7 100644 --- a/protocols/Tox/libtox/src/toxcore/events/file_chunk_request.c +++ b/protocols/Tox/libtox/src/toxcore/events/file_chunk_request.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -12,6 +12,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" /***************************************************** @@ -162,7 +163,10 @@ static Tox_Event_File_Chunk_Request *tox_events_add_file_chunk_request(Tox_Event event.type = TOX_EVENT_FILE_CHUNK_REQUEST; event.data.file_chunk_request = file_chunk_request; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_file_chunk_request_free(file_chunk_request, mem); + return nullptr; + } return file_chunk_request; } diff --git a/protocols/Tox/libtox/src/toxcore/events/file_recv.c b/protocols/Tox/libtox/src/toxcore/events/file_recv.c index 45cec44b0d..6ba2fdecfd 100644 --- a/protocols/Tox/libtox/src/toxcore/events/file_recv.c +++ b/protocols/Tox/libtox/src/toxcore/events/file_recv.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -14,6 +14,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" /***************************************************** @@ -207,7 +208,10 @@ static Tox_Event_File_Recv *tox_events_add_file_recv(Tox_Events *events, const M event.type = TOX_EVENT_FILE_RECV; event.data.file_recv = file_recv; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_file_recv_free(file_recv, mem); + return nullptr; + } return file_recv; } diff --git a/protocols/Tox/libtox/src/toxcore/events/file_recv_chunk.c b/protocols/Tox/libtox/src/toxcore/events/file_recv_chunk.c index 2edf7c5a7b..cb4487e23c 100644 --- a/protocols/Tox/libtox/src/toxcore/events/file_recv_chunk.c +++ b/protocols/Tox/libtox/src/toxcore/events/file_recv_chunk.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -14,6 +14,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" /***************************************************** @@ -191,7 +192,10 @@ static Tox_Event_File_Recv_Chunk *tox_events_add_file_recv_chunk(Tox_Events *eve event.type = TOX_EVENT_FILE_RECV_CHUNK; event.data.file_recv_chunk = file_recv_chunk; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_file_recv_chunk_free(file_recv_chunk, mem); + return nullptr; + } return file_recv_chunk; } diff --git a/protocols/Tox/libtox/src/toxcore/events/file_recv_control.c b/protocols/Tox/libtox/src/toxcore/events/file_recv_control.c index 14a34aaf3b..72de182e72 100644 --- a/protocols/Tox/libtox/src/toxcore/events/file_recv_control.c +++ b/protocols/Tox/libtox/src/toxcore/events/file_recv_control.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -12,6 +12,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" #include "../tox_pack.h" #include "../tox_unpack.h" @@ -148,7 +149,10 @@ static Tox_Event_File_Recv_Control *tox_events_add_file_recv_control(Tox_Events event.type = TOX_EVENT_FILE_RECV_CONTROL; event.data.file_recv_control = file_recv_control; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_file_recv_control_free(file_recv_control, mem); + return nullptr; + } return file_recv_control; } diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_connection_status.c b/protocols/Tox/libtox/src/toxcore/events/friend_connection_status.c index 330554b05e..d57980ddff 100644 --- a/protocols/Tox/libtox/src/toxcore/events/friend_connection_status.c +++ b/protocols/Tox/libtox/src/toxcore/events/friend_connection_status.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -12,6 +12,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" #include "../tox_pack.h" #include "../tox_unpack.h" @@ -132,7 +133,10 @@ static Tox_Event_Friend_Connection_Status *tox_events_add_friend_connection_stat event.type = TOX_EVENT_FRIEND_CONNECTION_STATUS; event.data.friend_connection_status = friend_connection_status; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_friend_connection_status_free(friend_connection_status, mem); + return nullptr; + } return friend_connection_status; } diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_lossless_packet.c b/protocols/Tox/libtox/src/toxcore/events/friend_lossless_packet.c index 17e8fad926..098c5ab006 100644 --- a/protocols/Tox/libtox/src/toxcore/events/friend_lossless_packet.c +++ b/protocols/Tox/libtox/src/toxcore/events/friend_lossless_packet.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -14,6 +14,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" /***************************************************** @@ -159,7 +160,10 @@ static Tox_Event_Friend_Lossless_Packet *tox_events_add_friend_lossless_packet(T event.type = TOX_EVENT_FRIEND_LOSSLESS_PACKET; event.data.friend_lossless_packet = friend_lossless_packet; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_friend_lossless_packet_free(friend_lossless_packet, mem); + return nullptr; + } return friend_lossless_packet; } diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_lossy_packet.c b/protocols/Tox/libtox/src/toxcore/events/friend_lossy_packet.c index 6b2e9ed2b0..016fa5d25c 100644 --- a/protocols/Tox/libtox/src/toxcore/events/friend_lossy_packet.c +++ b/protocols/Tox/libtox/src/toxcore/events/friend_lossy_packet.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -14,6 +14,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" /***************************************************** @@ -159,7 +160,10 @@ static Tox_Event_Friend_Lossy_Packet *tox_events_add_friend_lossy_packet(Tox_Eve event.type = TOX_EVENT_FRIEND_LOSSY_PACKET; event.data.friend_lossy_packet = friend_lossy_packet; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_friend_lossy_packet_free(friend_lossy_packet, mem); + return nullptr; + } return friend_lossy_packet; } diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_message.c b/protocols/Tox/libtox/src/toxcore/events/friend_message.c index befcc74a24..cedc3b588c 100644 --- a/protocols/Tox/libtox/src/toxcore/events/friend_message.c +++ b/protocols/Tox/libtox/src/toxcore/events/friend_message.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -14,6 +14,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" #include "../tox_pack.h" #include "../tox_unpack.h" @@ -177,7 +178,10 @@ static Tox_Event_Friend_Message *tox_events_add_friend_message(Tox_Events *event event.type = TOX_EVENT_FRIEND_MESSAGE; event.data.friend_message = friend_message; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_friend_message_free(friend_message, mem); + return nullptr; + } return friend_message; } diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_name.c b/protocols/Tox/libtox/src/toxcore/events/friend_name.c index dfa9b39608..9f8de0ce31 100644 --- a/protocols/Tox/libtox/src/toxcore/events/friend_name.c +++ b/protocols/Tox/libtox/src/toxcore/events/friend_name.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -14,6 +14,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" /***************************************************** @@ -159,7 +160,10 @@ static Tox_Event_Friend_Name *tox_events_add_friend_name(Tox_Events *events, con event.type = TOX_EVENT_FRIEND_NAME; event.data.friend_name = friend_name; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_friend_name_free(friend_name, mem); + return nullptr; + } return friend_name; } diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_read_receipt.c b/protocols/Tox/libtox/src/toxcore/events/friend_read_receipt.c index e5f2f9db52..4ba426716e 100644 --- a/protocols/Tox/libtox/src/toxcore/events/friend_read_receipt.c +++ b/protocols/Tox/libtox/src/toxcore/events/friend_read_receipt.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -12,6 +12,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" /***************************************************** @@ -130,7 +131,10 @@ static Tox_Event_Friend_Read_Receipt *tox_events_add_friend_read_receipt(Tox_Eve event.type = TOX_EVENT_FRIEND_READ_RECEIPT; event.data.friend_read_receipt = friend_read_receipt; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_friend_read_receipt_free(friend_read_receipt, mem); + return nullptr; + } return friend_read_receipt; } diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_request.c b/protocols/Tox/libtox/src/toxcore/events/friend_request.c index b492c15147..631c236bac 100644 --- a/protocols/Tox/libtox/src/toxcore/events/friend_request.c +++ b/protocols/Tox/libtox/src/toxcore/events/friend_request.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2022 The TokTok team. + * Copyright © 2022-2025 The TokTok team. */ #include "events_alloc.h" @@ -13,6 +13,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" #include "../tox_private.h" @@ -152,7 +153,10 @@ static Tox_Event_Friend_Request *tox_events_add_friend_request(Tox_Events *event event.type = TOX_EVENT_FRIEND_REQUEST; event.data.friend_request = friend_request; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_friend_request_free(friend_request, mem); + return nullptr; + } return friend_request; } diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_status.c b/protocols/Tox/libtox/src/toxcore/events/friend_status.c index 3d7499722b..209eed8bc5 100644 --- a/protocols/Tox/libtox/src/toxcore/events/friend_status.c +++ b/protocols/Tox/libtox/src/toxcore/events/friend_status.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -12,6 +12,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" #include "../tox_pack.h" #include "../tox_unpack.h" @@ -132,7 +133,10 @@ static Tox_Event_Friend_Status *tox_events_add_friend_status(Tox_Events *events, event.type = TOX_EVENT_FRIEND_STATUS; event.data.friend_status = friend_status; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_friend_status_free(friend_status, mem); + return nullptr; + } return friend_status; } diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_status_message.c b/protocols/Tox/libtox/src/toxcore/events/friend_status_message.c index ad0519911e..2c6d0fb02f 100644 --- a/protocols/Tox/libtox/src/toxcore/events/friend_status_message.c +++ b/protocols/Tox/libtox/src/toxcore/events/friend_status_message.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -14,6 +14,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" /***************************************************** @@ -159,7 +160,10 @@ static Tox_Event_Friend_Status_Message *tox_events_add_friend_status_message(Tox event.type = TOX_EVENT_FRIEND_STATUS_MESSAGE; event.data.friend_status_message = friend_status_message; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_friend_status_message_free(friend_status_message, mem); + return nullptr; + } return friend_status_message; } diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_typing.c b/protocols/Tox/libtox/src/toxcore/events/friend_typing.c index 692b07fb88..cb2cfac94d 100644 --- a/protocols/Tox/libtox/src/toxcore/events/friend_typing.c +++ b/protocols/Tox/libtox/src/toxcore/events/friend_typing.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -12,6 +12,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" /***************************************************** @@ -130,7 +131,10 @@ static Tox_Event_Friend_Typing *tox_events_add_friend_typing(Tox_Events *events, event.type = TOX_EVENT_FRIEND_TYPING; event.data.friend_typing = friend_typing; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_friend_typing_free(friend_typing, mem); + return nullptr; + } return friend_typing; } diff --git a/protocols/Tox/libtox/src/toxcore/events/group_custom_packet.c b/protocols/Tox/libtox/src/toxcore/events/group_custom_packet.c index a82e2c3a6c..337d601f04 100644 --- a/protocols/Tox/libtox/src/toxcore/events/group_custom_packet.c +++ b/protocols/Tox/libtox/src/toxcore/events/group_custom_packet.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -14,6 +14,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" /***************************************************** @@ -175,7 +176,10 @@ static Tox_Event_Group_Custom_Packet *tox_events_add_group_custom_packet(Tox_Eve event.type = TOX_EVENT_GROUP_CUSTOM_PACKET; event.data.group_custom_packet = group_custom_packet; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_group_custom_packet_free(group_custom_packet, mem); + return nullptr; + } return group_custom_packet; } @@ -220,7 +224,7 @@ static Tox_Event_Group_Custom_Packet *tox_event_group_custom_packet_alloc(void * *****************************************************/ void tox_events_handle_group_custom_packet( - Tox *tox, uint32_t group_number, uint32_t peer_id, const uint8_t *data, size_t length, + Tox *tox, uint32_t group_number, uint32_t peer_id, const uint8_t *data, size_t data_length, void *user_data) { Tox_Event_Group_Custom_Packet *group_custom_packet = tox_event_group_custom_packet_alloc(user_data); @@ -231,5 +235,5 @@ void tox_events_handle_group_custom_packet( tox_event_group_custom_packet_set_group_number(group_custom_packet, group_number); tox_event_group_custom_packet_set_peer_id(group_custom_packet, peer_id); - tox_event_group_custom_packet_set_data(group_custom_packet, data, length); + tox_event_group_custom_packet_set_data(group_custom_packet, data, data_length); } diff --git a/protocols/Tox/libtox/src/toxcore/events/group_custom_private_packet.c b/protocols/Tox/libtox/src/toxcore/events/group_custom_private_packet.c index 56282f0fb8..9408a8dc68 100644 --- a/protocols/Tox/libtox/src/toxcore/events/group_custom_private_packet.c +++ b/protocols/Tox/libtox/src/toxcore/events/group_custom_private_packet.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -14,6 +14,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" /***************************************************** @@ -175,7 +176,10 @@ static Tox_Event_Group_Custom_Private_Packet *tox_events_add_group_custom_privat event.type = TOX_EVENT_GROUP_CUSTOM_PRIVATE_PACKET; event.data.group_custom_private_packet = group_custom_private_packet; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_group_custom_private_packet_free(group_custom_private_packet, mem); + return nullptr; + } return group_custom_private_packet; } @@ -220,7 +224,7 @@ static Tox_Event_Group_Custom_Private_Packet *tox_event_group_custom_private_pac *****************************************************/ void tox_events_handle_group_custom_private_packet( - Tox *tox, uint32_t group_number, uint32_t peer_id, const uint8_t *data, size_t length, + Tox *tox, uint32_t group_number, uint32_t peer_id, const uint8_t *data, size_t data_length, void *user_data) { Tox_Event_Group_Custom_Private_Packet *group_custom_private_packet = tox_event_group_custom_private_packet_alloc(user_data); @@ -231,5 +235,5 @@ void tox_events_handle_group_custom_private_packet( tox_event_group_custom_private_packet_set_group_number(group_custom_private_packet, group_number); tox_event_group_custom_private_packet_set_peer_id(group_custom_private_packet, peer_id); - tox_event_group_custom_private_packet_set_data(group_custom_private_packet, data, length); + tox_event_group_custom_private_packet_set_data(group_custom_private_packet, data, data_length); } diff --git a/protocols/Tox/libtox/src/toxcore/events/group_invite.c b/protocols/Tox/libtox/src/toxcore/events/group_invite.c index 0691dcd1fe..3385b89ad5 100644 --- a/protocols/Tox/libtox/src/toxcore/events/group_invite.c +++ b/protocols/Tox/libtox/src/toxcore/events/group_invite.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -14,6 +14,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" /***************************************************** @@ -203,7 +204,10 @@ static Tox_Event_Group_Invite *tox_events_add_group_invite(Tox_Events *events, c event.type = TOX_EVENT_GROUP_INVITE; event.data.group_invite = group_invite; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_group_invite_free(group_invite, mem); + return nullptr; + } return group_invite; } @@ -248,7 +252,7 @@ static Tox_Event_Group_Invite *tox_event_group_invite_alloc(void *user_data) *****************************************************/ void tox_events_handle_group_invite( - Tox *tox, uint32_t friend_number, const uint8_t *invite_data, size_t length, const uint8_t *group_name, size_t group_name_length, + Tox *tox, uint32_t friend_number, const uint8_t *invite_data, size_t invite_data_length, const uint8_t *group_name, size_t group_name_length, void *user_data) { Tox_Event_Group_Invite *group_invite = tox_event_group_invite_alloc(user_data); @@ -258,6 +262,6 @@ void tox_events_handle_group_invite( } tox_event_group_invite_set_friend_number(group_invite, friend_number); - tox_event_group_invite_set_invite_data(group_invite, invite_data, length); + tox_event_group_invite_set_invite_data(group_invite, invite_data, invite_data_length); tox_event_group_invite_set_group_name(group_invite, group_name, group_name_length); } diff --git a/protocols/Tox/libtox/src/toxcore/events/group_join_fail.c b/protocols/Tox/libtox/src/toxcore/events/group_join_fail.c index b85896858b..8fdefb77e4 100644 --- a/protocols/Tox/libtox/src/toxcore/events/group_join_fail.c +++ b/protocols/Tox/libtox/src/toxcore/events/group_join_fail.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -12,6 +12,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" #include "../tox_pack.h" #include "../tox_unpack.h" @@ -132,7 +133,10 @@ static Tox_Event_Group_Join_Fail *tox_events_add_group_join_fail(Tox_Events *eve event.type = TOX_EVENT_GROUP_JOIN_FAIL; event.data.group_join_fail = group_join_fail; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_group_join_fail_free(group_join_fail, mem); + return nullptr; + } return group_join_fail; } diff --git a/protocols/Tox/libtox/src/toxcore/events/group_message.c b/protocols/Tox/libtox/src/toxcore/events/group_message.c index a200f84566..dfb2bc961a 100644 --- a/protocols/Tox/libtox/src/toxcore/events/group_message.c +++ b/protocols/Tox/libtox/src/toxcore/events/group_message.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -14,6 +14,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" #include "../tox_pack.h" #include "../tox_unpack.h" @@ -27,7 +28,7 @@ struct Tox_Event_Group_Message { uint32_t group_number; uint32_t peer_id; - Tox_Message_Type type; + Tox_Message_Type message_type; uint8_t *message; uint32_t message_length; uint32_t message_id; @@ -60,16 +61,16 @@ uint32_t tox_event_group_message_get_peer_id(const Tox_Event_Group_Message *grou } non_null() -static void tox_event_group_message_set_type(Tox_Event_Group_Message *group_message, - Tox_Message_Type type) +static void tox_event_group_message_set_message_type(Tox_Event_Group_Message *group_message, + Tox_Message_Type message_type) { assert(group_message != nullptr); - group_message->type = type; + group_message->message_type = message_type; } -Tox_Message_Type tox_event_group_message_get_type(const Tox_Event_Group_Message *group_message) +Tox_Message_Type tox_event_group_message_get_message_type(const Tox_Event_Group_Message *group_message) { assert(group_message != nullptr); - return group_message->type; + return group_message->message_type; } non_null(1) nullable(2) @@ -143,7 +144,7 @@ bool tox_event_group_message_pack( return bin_pack_array(bp, 5) && bin_pack_u32(bp, event->group_number) && bin_pack_u32(bp, event->peer_id) - && tox_message_type_pack(event->type, bp) + && tox_message_type_pack(event->message_type, bp) && bin_pack_bin(bp, event->message, event->message_length) && bin_pack_u32(bp, event->message_id); } @@ -159,7 +160,7 @@ static bool tox_event_group_message_unpack_into( return bin_unpack_u32(bu, &event->group_number) && bin_unpack_u32(bu, &event->peer_id) - && tox_message_type_unpack(&event->type, bu) + && tox_message_type_unpack(&event->message_type, bu) && bin_unpack_bin(bu, &event->message, &event->message_length) && bin_unpack_u32(bu, &event->message_id); } @@ -209,7 +210,10 @@ static Tox_Event_Group_Message *tox_events_add_group_message(Tox_Events *events, event.type = TOX_EVENT_GROUP_MESSAGE; event.data.group_message = group_message; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_group_message_free(group_message, mem); + return nullptr; + } return group_message; } @@ -254,7 +258,7 @@ static Tox_Event_Group_Message *tox_event_group_message_alloc(void *user_data) *****************************************************/ void tox_events_handle_group_message( - Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Message_Type type, const uint8_t *message, size_t length, uint32_t message_id, + Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Message_Type message_type, const uint8_t *message, size_t message_length, uint32_t message_id, void *user_data) { Tox_Event_Group_Message *group_message = tox_event_group_message_alloc(user_data); @@ -265,7 +269,7 @@ void tox_events_handle_group_message( tox_event_group_message_set_group_number(group_message, group_number); tox_event_group_message_set_peer_id(group_message, peer_id); - tox_event_group_message_set_type(group_message, type); - tox_event_group_message_set_message(group_message, message, length); + tox_event_group_message_set_message_type(group_message, message_type); + tox_event_group_message_set_message(group_message, message, message_length); tox_event_group_message_set_message_id(group_message, message_id); } diff --git a/protocols/Tox/libtox/src/toxcore/events/group_moderation.c b/protocols/Tox/libtox/src/toxcore/events/group_moderation.c index ba510d5b2a..9e2b87e6c2 100644 --- a/protocols/Tox/libtox/src/toxcore/events/group_moderation.c +++ b/protocols/Tox/libtox/src/toxcore/events/group_moderation.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -12,6 +12,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" #include "../tox_pack.h" #include "../tox_unpack.h" @@ -164,7 +165,10 @@ static Tox_Event_Group_Moderation *tox_events_add_group_moderation(Tox_Events *e event.type = TOX_EVENT_GROUP_MODERATION; event.data.group_moderation = group_moderation; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_group_moderation_free(group_moderation, mem); + return nullptr; + } return group_moderation; } diff --git a/protocols/Tox/libtox/src/toxcore/events/group_password.c b/protocols/Tox/libtox/src/toxcore/events/group_password.c index ad6e86b9d3..33b64a0a8b 100644 --- a/protocols/Tox/libtox/src/toxcore/events/group_password.c +++ b/protocols/Tox/libtox/src/toxcore/events/group_password.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -14,6 +14,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" /***************************************************** @@ -159,7 +160,10 @@ static Tox_Event_Group_Password *tox_events_add_group_password(Tox_Events *event event.type = TOX_EVENT_GROUP_PASSWORD; event.data.group_password = group_password; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_group_password_free(group_password, mem); + return nullptr; + } return group_password; } @@ -204,7 +208,7 @@ static Tox_Event_Group_Password *tox_event_group_password_alloc(void *user_data) *****************************************************/ void tox_events_handle_group_password( - Tox *tox, uint32_t group_number, const uint8_t *password, size_t length, + Tox *tox, uint32_t group_number, const uint8_t *password, size_t password_length, void *user_data) { Tox_Event_Group_Password *group_password = tox_event_group_password_alloc(user_data); @@ -214,5 +218,5 @@ void tox_events_handle_group_password( } tox_event_group_password_set_group_number(group_password, group_number); - tox_event_group_password_set_password(group_password, password, length); + tox_event_group_password_set_password(group_password, password, password_length); } diff --git a/protocols/Tox/libtox/src/toxcore/events/group_peer_exit.c b/protocols/Tox/libtox/src/toxcore/events/group_peer_exit.c index 16d1eba7a6..a09f96b7d0 100644 --- a/protocols/Tox/libtox/src/toxcore/events/group_peer_exit.c +++ b/protocols/Tox/libtox/src/toxcore/events/group_peer_exit.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -14,6 +14,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" #include "../tox_pack.h" #include "../tox_unpack.h" @@ -237,7 +238,10 @@ static Tox_Event_Group_Peer_Exit *tox_events_add_group_peer_exit(Tox_Events *eve event.type = TOX_EVENT_GROUP_PEER_EXIT; event.data.group_peer_exit = group_peer_exit; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_group_peer_exit_free(group_peer_exit, mem); + return nullptr; + } return group_peer_exit; } diff --git a/protocols/Tox/libtox/src/toxcore/events/group_peer_join.c b/protocols/Tox/libtox/src/toxcore/events/group_peer_join.c index af0d006e87..d450564429 100644 --- a/protocols/Tox/libtox/src/toxcore/events/group_peer_join.c +++ b/protocols/Tox/libtox/src/toxcore/events/group_peer_join.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -12,6 +12,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" /***************************************************** @@ -130,7 +131,10 @@ static Tox_Event_Group_Peer_Join *tox_events_add_group_peer_join(Tox_Events *eve event.type = TOX_EVENT_GROUP_PEER_JOIN; event.data.group_peer_join = group_peer_join; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_group_peer_join_free(group_peer_join, mem); + return nullptr; + } return group_peer_join; } diff --git a/protocols/Tox/libtox/src/toxcore/events/group_peer_limit.c b/protocols/Tox/libtox/src/toxcore/events/group_peer_limit.c index 5e2e23558c..65c44e7a19 100644 --- a/protocols/Tox/libtox/src/toxcore/events/group_peer_limit.c +++ b/protocols/Tox/libtox/src/toxcore/events/group_peer_limit.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -12,6 +12,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" /***************************************************** @@ -130,7 +131,10 @@ static Tox_Event_Group_Peer_Limit *tox_events_add_group_peer_limit(Tox_Events *e event.type = TOX_EVENT_GROUP_PEER_LIMIT; event.data.group_peer_limit = group_peer_limit; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_group_peer_limit_free(group_peer_limit, mem); + return nullptr; + } return group_peer_limit; } diff --git a/protocols/Tox/libtox/src/toxcore/events/group_peer_name.c b/protocols/Tox/libtox/src/toxcore/events/group_peer_name.c index f8273e94b4..d653ff5531 100644 --- a/protocols/Tox/libtox/src/toxcore/events/group_peer_name.c +++ b/protocols/Tox/libtox/src/toxcore/events/group_peer_name.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -14,6 +14,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" /***************************************************** @@ -175,7 +176,10 @@ static Tox_Event_Group_Peer_Name *tox_events_add_group_peer_name(Tox_Events *eve event.type = TOX_EVENT_GROUP_PEER_NAME; event.data.group_peer_name = group_peer_name; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_group_peer_name_free(group_peer_name, mem); + return nullptr; + } return group_peer_name; } @@ -220,7 +224,7 @@ static Tox_Event_Group_Peer_Name *tox_event_group_peer_name_alloc(void *user_dat *****************************************************/ void tox_events_handle_group_peer_name( - Tox *tox, uint32_t group_number, uint32_t peer_id, const uint8_t *name, size_t length, + Tox *tox, uint32_t group_number, uint32_t peer_id, const uint8_t *name, size_t name_length, void *user_data) { Tox_Event_Group_Peer_Name *group_peer_name = tox_event_group_peer_name_alloc(user_data); @@ -231,5 +235,5 @@ void tox_events_handle_group_peer_name( tox_event_group_peer_name_set_group_number(group_peer_name, group_number); tox_event_group_peer_name_set_peer_id(group_peer_name, peer_id); - tox_event_group_peer_name_set_name(group_peer_name, name, length); + tox_event_group_peer_name_set_name(group_peer_name, name, name_length); } diff --git a/protocols/Tox/libtox/src/toxcore/events/group_peer_status.c b/protocols/Tox/libtox/src/toxcore/events/group_peer_status.c index 4165d90ec2..3dc56df5ff 100644 --- a/protocols/Tox/libtox/src/toxcore/events/group_peer_status.c +++ b/protocols/Tox/libtox/src/toxcore/events/group_peer_status.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -12,6 +12,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" #include "../tox_pack.h" #include "../tox_unpack.h" @@ -148,7 +149,10 @@ static Tox_Event_Group_Peer_Status *tox_events_add_group_peer_status(Tox_Events event.type = TOX_EVENT_GROUP_PEER_STATUS; event.data.group_peer_status = group_peer_status; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_group_peer_status_free(group_peer_status, mem); + return nullptr; + } return group_peer_status; } diff --git a/protocols/Tox/libtox/src/toxcore/events/group_privacy_state.c b/protocols/Tox/libtox/src/toxcore/events/group_privacy_state.c index 1c683c255c..fde9e1d79c 100644 --- a/protocols/Tox/libtox/src/toxcore/events/group_privacy_state.c +++ b/protocols/Tox/libtox/src/toxcore/events/group_privacy_state.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -12,6 +12,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" #include "../tox_pack.h" #include "../tox_unpack.h" @@ -132,7 +133,10 @@ static Tox_Event_Group_Privacy_State *tox_events_add_group_privacy_state(Tox_Eve event.type = TOX_EVENT_GROUP_PRIVACY_STATE; event.data.group_privacy_state = group_privacy_state; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_group_privacy_state_free(group_privacy_state, mem); + return nullptr; + } return group_privacy_state; } diff --git a/protocols/Tox/libtox/src/toxcore/events/group_private_message.c b/protocols/Tox/libtox/src/toxcore/events/group_private_message.c index 648f707880..24dd1db670 100644 --- a/protocols/Tox/libtox/src/toxcore/events/group_private_message.c +++ b/protocols/Tox/libtox/src/toxcore/events/group_private_message.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -14,6 +14,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" #include "../tox_pack.h" #include "../tox_unpack.h" @@ -27,9 +28,10 @@ struct Tox_Event_Group_Private_Message { uint32_t group_number; uint32_t peer_id; - Tox_Message_Type type; + Tox_Message_Type message_type; uint8_t *message; uint32_t message_length; + uint32_t message_id; }; non_null() @@ -59,16 +61,16 @@ uint32_t tox_event_group_private_message_get_peer_id(const Tox_Event_Group_Priva } non_null() -static void tox_event_group_private_message_set_type(Tox_Event_Group_Private_Message *group_private_message, - Tox_Message_Type type) +static void tox_event_group_private_message_set_message_type(Tox_Event_Group_Private_Message *group_private_message, + Tox_Message_Type message_type) { assert(group_private_message != nullptr); - group_private_message->type = type; + group_private_message->message_type = message_type; } -Tox_Message_Type tox_event_group_private_message_get_type(const Tox_Event_Group_Private_Message *group_private_message) +Tox_Message_Type tox_event_group_private_message_get_message_type(const Tox_Event_Group_Private_Message *group_private_message) { assert(group_private_message != nullptr); - return group_private_message->type; + return group_private_message->message_type; } non_null(1) nullable(2) @@ -111,6 +113,19 @@ const uint8_t *tox_event_group_private_message_get_message(const Tox_Event_Group } non_null() +static void tox_event_group_private_message_set_message_id(Tox_Event_Group_Private_Message *group_private_message, + uint32_t message_id) +{ + assert(group_private_message != nullptr); + group_private_message->message_id = message_id; +} +uint32_t tox_event_group_private_message_get_message_id(const Tox_Event_Group_Private_Message *group_private_message) +{ + assert(group_private_message != nullptr); + return group_private_message->message_id; +} + +non_null() static void tox_event_group_private_message_construct(Tox_Event_Group_Private_Message *group_private_message) { *group_private_message = (Tox_Event_Group_Private_Message) { @@ -126,11 +141,12 @@ static void tox_event_group_private_message_destruct(Tox_Event_Group_Private_Mes bool tox_event_group_private_message_pack( const Tox_Event_Group_Private_Message *event, Bin_Pack *bp) { - return bin_pack_array(bp, 4) + return bin_pack_array(bp, 5) && bin_pack_u32(bp, event->group_number) && bin_pack_u32(bp, event->peer_id) - && tox_message_type_pack(event->type, bp) - && bin_pack_bin(bp, event->message, event->message_length); + && tox_message_type_pack(event->message_type, bp) + && bin_pack_bin(bp, event->message, event->message_length) + && bin_pack_u32(bp, event->message_id); } non_null() @@ -138,14 +154,15 @@ static bool tox_event_group_private_message_unpack_into( Tox_Event_Group_Private_Message *event, Bin_Unpack *bu) { assert(event != nullptr); - if (!bin_unpack_array_fixed(bu, 4, nullptr)) { + if (!bin_unpack_array_fixed(bu, 5, nullptr)) { return false; } return bin_unpack_u32(bu, &event->group_number) && bin_unpack_u32(bu, &event->peer_id) - && tox_message_type_unpack(&event->type, bu) - && bin_unpack_bin(bu, &event->message, &event->message_length); + && tox_message_type_unpack(&event->message_type, bu) + && bin_unpack_bin(bu, &event->message, &event->message_length) + && bin_unpack_u32(bu, &event->message_id); } /***************************************************** @@ -193,7 +210,10 @@ static Tox_Event_Group_Private_Message *tox_events_add_group_private_message(Tox event.type = TOX_EVENT_GROUP_PRIVATE_MESSAGE; event.data.group_private_message = group_private_message; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_group_private_message_free(group_private_message, mem); + return nullptr; + } return group_private_message; } @@ -238,7 +258,7 @@ static Tox_Event_Group_Private_Message *tox_event_group_private_message_alloc(vo *****************************************************/ void tox_events_handle_group_private_message( - Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Message_Type type, const uint8_t *message, size_t length, + Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Message_Type message_type, const uint8_t *message, size_t message_length, uint32_t message_id, void *user_data) { Tox_Event_Group_Private_Message *group_private_message = tox_event_group_private_message_alloc(user_data); @@ -249,6 +269,7 @@ void tox_events_handle_group_private_message( tox_event_group_private_message_set_group_number(group_private_message, group_number); tox_event_group_private_message_set_peer_id(group_private_message, peer_id); - tox_event_group_private_message_set_type(group_private_message, type); - tox_event_group_private_message_set_message(group_private_message, message, length); + tox_event_group_private_message_set_message_type(group_private_message, message_type); + tox_event_group_private_message_set_message(group_private_message, message, message_length); + tox_event_group_private_message_set_message_id(group_private_message, message_id); } diff --git a/protocols/Tox/libtox/src/toxcore/events/group_self_join.c b/protocols/Tox/libtox/src/toxcore/events/group_self_join.c index 0745e975f8..07038632aa 100644 --- a/protocols/Tox/libtox/src/toxcore/events/group_self_join.c +++ b/protocols/Tox/libtox/src/toxcore/events/group_self_join.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -12,6 +12,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" /***************************************************** @@ -109,7 +110,10 @@ static Tox_Event_Group_Self_Join *tox_events_add_group_self_join(Tox_Events *eve event.type = TOX_EVENT_GROUP_SELF_JOIN; event.data.group_self_join = group_self_join; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_group_self_join_free(group_self_join, mem); + return nullptr; + } return group_self_join; } diff --git a/protocols/Tox/libtox/src/toxcore/events/group_topic.c b/protocols/Tox/libtox/src/toxcore/events/group_topic.c index 23cdd5d354..f9d1a7b953 100644 --- a/protocols/Tox/libtox/src/toxcore/events/group_topic.c +++ b/protocols/Tox/libtox/src/toxcore/events/group_topic.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -14,6 +14,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" /***************************************************** @@ -175,7 +176,10 @@ static Tox_Event_Group_Topic *tox_events_add_group_topic(Tox_Events *events, con event.type = TOX_EVENT_GROUP_TOPIC; event.data.group_topic = group_topic; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_group_topic_free(group_topic, mem); + return nullptr; + } return group_topic; } @@ -220,7 +224,7 @@ static Tox_Event_Group_Topic *tox_event_group_topic_alloc(void *user_data) *****************************************************/ void tox_events_handle_group_topic( - Tox *tox, uint32_t group_number, uint32_t peer_id, const uint8_t *topic, size_t length, + Tox *tox, uint32_t group_number, uint32_t peer_id, const uint8_t *topic, size_t topic_length, void *user_data) { Tox_Event_Group_Topic *group_topic = tox_event_group_topic_alloc(user_data); @@ -231,5 +235,5 @@ void tox_events_handle_group_topic( tox_event_group_topic_set_group_number(group_topic, group_number); tox_event_group_topic_set_peer_id(group_topic, peer_id); - tox_event_group_topic_set_topic(group_topic, topic, length); + tox_event_group_topic_set_topic(group_topic, topic, topic_length); } diff --git a/protocols/Tox/libtox/src/toxcore/events/group_topic_lock.c b/protocols/Tox/libtox/src/toxcore/events/group_topic_lock.c index 36fb49393a..a21acea293 100644 --- a/protocols/Tox/libtox/src/toxcore/events/group_topic_lock.c +++ b/protocols/Tox/libtox/src/toxcore/events/group_topic_lock.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -12,6 +12,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" #include "../tox_pack.h" #include "../tox_unpack.h" @@ -132,7 +133,10 @@ static Tox_Event_Group_Topic_Lock *tox_events_add_group_topic_lock(Tox_Events *e event.type = TOX_EVENT_GROUP_TOPIC_LOCK; event.data.group_topic_lock = group_topic_lock; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_group_topic_lock_free(group_topic_lock, mem); + return nullptr; + } return group_topic_lock; } diff --git a/protocols/Tox/libtox/src/toxcore/events/group_voice_state.c b/protocols/Tox/libtox/src/toxcore/events/group_voice_state.c index fba0300389..ebc78dca21 100644 --- a/protocols/Tox/libtox/src/toxcore/events/group_voice_state.c +++ b/protocols/Tox/libtox/src/toxcore/events/group_voice_state.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -12,6 +12,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" #include "../tox_pack.h" #include "../tox_unpack.h" @@ -132,7 +133,10 @@ static Tox_Event_Group_Voice_State *tox_events_add_group_voice_state(Tox_Events event.type = TOX_EVENT_GROUP_VOICE_STATE; event.data.group_voice_state = group_voice_state; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_group_voice_state_free(group_voice_state, mem); + return nullptr; + } return group_voice_state; } diff --git a/protocols/Tox/libtox/src/toxcore/events/self_connection_status.c b/protocols/Tox/libtox/src/toxcore/events/self_connection_status.c index 8d8bc803ea..f66daff544 100644 --- a/protocols/Tox/libtox/src/toxcore/events/self_connection_status.c +++ b/protocols/Tox/libtox/src/toxcore/events/self_connection_status.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2023-2024 The TokTok team. + * Copyright © 2023-2025 The TokTok team. */ #include "events_alloc.h" @@ -12,6 +12,7 @@ #include "../ccompat.h" #include "../mem.h" #include "../tox.h" +#include "../tox_event.h" #include "../tox_events.h" #include "../tox_pack.h" #include "../tox_unpack.h" @@ -111,7 +112,10 @@ static Tox_Event_Self_Connection_Status *tox_events_add_self_connection_status(T event.type = TOX_EVENT_SELF_CONNECTION_STATUS; event.data.self_connection_status = self_connection_status; - tox_events_add(events, &event); + if (!tox_events_add(events, &event)) { + tox_event_self_connection_status_free(self_connection_status, mem); + return nullptr; + } return self_connection_status; } diff --git a/protocols/Tox/libtox/src/toxcore/forwarding.c b/protocols/Tox/libtox/src/toxcore/forwarding.c index 18ff3203fc..6d608b5e7b 100644 --- a/protocols/Tox/libtox/src/toxcore/forwarding.c +++ b/protocols/Tox/libtox/src/toxcore/forwarding.c @@ -1,11 +1,10 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2019-2022 The TokTok team. + * Copyright © 2019-2025 The TokTok team. */ #include "forwarding.h" #include <assert.h> -#include <stdlib.h> #include <string.h> #include "DHT.h" @@ -13,12 +12,14 @@ #include "ccompat.h" #include "crypto_core.h" #include "logger.h" +#include "mem.h" #include "mono_time.h" #include "network.h" #include "timed_auth.h" struct Forwarding { const Logger *log; + const Memory *mem; const Random *rng; DHT *dht; const Mono_Time *mono_time; @@ -357,19 +358,20 @@ void set_callback_forward_reply(Forwarding *forwarding, forward_reply_cb *functi forwarding->forward_reply_callback_object = object; } -Forwarding *new_forwarding(const Logger *log, const Random *rng, const Mono_Time *mono_time, DHT *dht) +Forwarding *new_forwarding(const Logger *log, const Memory *mem, const Random *rng, const Mono_Time *mono_time, DHT *dht) { if (log == nullptr || mono_time == nullptr || dht == nullptr) { return nullptr; } - Forwarding *forwarding = (Forwarding *)calloc(1, sizeof(Forwarding)); + Forwarding *forwarding = (Forwarding *)mem_alloc(mem, sizeof(Forwarding)); if (forwarding == nullptr) { return nullptr; } forwarding->log = log; + forwarding->mem = mem; forwarding->rng = rng; forwarding->mono_time = mono_time; forwarding->dht = dht; @@ -396,5 +398,5 @@ void kill_forwarding(Forwarding *forwarding) crypto_memzero(forwarding->hmac_key, CRYPTO_HMAC_KEY_SIZE); - free(forwarding); + mem_delete(forwarding->mem, forwarding); } diff --git a/protocols/Tox/libtox/src/toxcore/forwarding.h b/protocols/Tox/libtox/src/toxcore/forwarding.h index bd0ef09e1c..b4431f57af 100644 --- a/protocols/Tox/libtox/src/toxcore/forwarding.h +++ b/protocols/Tox/libtox/src/toxcore/forwarding.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2019-2022 The TokTok team. + * Copyright © 2019-2025 The TokTok team. */ #ifndef C_TOXCORE_TOXCORE_FORWARDING_H @@ -9,6 +9,7 @@ #include "attributes.h" #include "crypto_core.h" #include "logger.h" +#include "mem.h" #include "mono_time.h" #include "network.h" @@ -116,7 +117,7 @@ non_null(1) nullable(2, 3) void set_callback_forward_reply(Forwarding *forwarding, forward_reply_cb *function, void *object); non_null() -Forwarding *new_forwarding(const Logger *log, const Random *rng, const Mono_Time *mono_time, DHT *dht); +Forwarding *new_forwarding(const Logger *log, const Memory *mem, const Random *rng, const Mono_Time *mono_time, DHT *dht); nullable(1) void kill_forwarding(Forwarding *forwarding); diff --git a/protocols/Tox/libtox/src/toxcore/friend_connection.c b/protocols/Tox/libtox/src/toxcore/friend_connection.c index 33bfa40d34..78c6d4acdc 100644 --- a/protocols/Tox/libtox/src/toxcore/friend_connection.c +++ b/protocols/Tox/libtox/src/toxcore/friend_connection.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2014 Tox project. */ @@ -8,7 +8,6 @@ */ #include "friend_connection.h" -#include <stdlib.h> #include <string.h> #include "DHT.h" @@ -18,6 +17,7 @@ #include "ccompat.h" #include "crypto_core.h" #include "logger.h" +#include "mem.h" #include "mono_time.h" #include "net_crypto.h" #include "network.h" @@ -69,6 +69,7 @@ static const Friend_Conn empty_friend_conn = {0}; struct Friend_Connections { const Mono_Time *mono_time; + const Memory *mem; const Logger *logger; Net_Crypto *net_crypto; DHT *dht; @@ -126,12 +127,12 @@ non_null() static bool realloc_friendconns(Friend_Connections *fr_c, uint32_t num) { if (num == 0) { - free(fr_c->conns); + mem_delete(fr_c->mem, fr_c->conns); fr_c->conns = nullptr; return true; } - Friend_Conn *newgroup_cons = (Friend_Conn *)realloc(fr_c->conns, num * sizeof(Friend_Conn)); + Friend_Conn *newgroup_cons = (Friend_Conn *)mem_vrealloc(fr_c->mem, fr_c->conns, num, sizeof(Friend_Conn)); if (newgroup_cons == nullptr) { return false; @@ -875,6 +876,10 @@ void set_friend_request_callback(Friend_Connections *fr_c, fr_request_cb *fr_req int send_friend_request_packet(Friend_Connections *fr_c, int friendcon_id, uint32_t nospam_num, const uint8_t *data, uint16_t length) { + // TODO(Jfreegman): This max packet size is too large to be handled by receiving clients + // when sent via the onion. We currently limit the length at a higher level, but + // this bounds check should be fixed to represent the max size of a packet that + // the onion client can handle. if (1 + sizeof(nospam_num) + length > ONION_CLIENT_MAX_DATA_SIZE || length == 0) { return -1; } @@ -908,14 +913,14 @@ int send_friend_request_packet(Friend_Connections *fr_c, int friendcon_id, uint3 /** Create new friend_connections instance. */ Friend_Connections *new_friend_connections( - const Logger *logger, const Mono_Time *mono_time, const Network *ns, + const Logger *logger, const Memory *mem, const Mono_Time *mono_time, const Network *ns, Onion_Client *onion_c, bool local_discovery_enabled) { if (onion_c == nullptr) { return nullptr; } - Friend_Connections *const temp = (Friend_Connections *)calloc(1, sizeof(Friend_Connections)); + Friend_Connections *const temp = (Friend_Connections *)mem_alloc(mem, sizeof(Friend_Connections)); if (temp == nullptr) { return nullptr; @@ -924,7 +929,7 @@ Friend_Connections *new_friend_connections( temp->local_discovery_enabled = local_discovery_enabled; if (temp->local_discovery_enabled) { - temp->broadcast = lan_discovery_init(ns); + temp->broadcast = lan_discovery_init(mem, ns); if (temp->broadcast == nullptr) { LOGGER_ERROR(logger, "could not initialise LAN discovery"); @@ -933,6 +938,7 @@ Friend_Connections *new_friend_connections( } temp->mono_time = mono_time; + temp->mem = mem; temp->logger = logger; temp->dht = onion_get_dht(onion_c); temp->net_crypto = onion_get_net_crypto(onion_c); @@ -1032,6 +1038,11 @@ void kill_friend_connections(Friend_Connections *fr_c) kill_friend_connection(fr_c, i); } + // there might be allocated NONE connections + if (fr_c->conns != nullptr) { + mem_delete(fr_c->mem, fr_c->conns); + } + lan_discovery_kill(fr_c->broadcast); - free(fr_c); + mem_delete(fr_c->mem, fr_c); } diff --git a/protocols/Tox/libtox/src/toxcore/friend_connection.h b/protocols/Tox/libtox/src/toxcore/friend_connection.h index bbd4454729..8c3c84f1c5 100644 --- a/protocols/Tox/libtox/src/toxcore/friend_connection.h +++ b/protocols/Tox/libtox/src/toxcore/friend_connection.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2014 Tox project. */ @@ -12,9 +12,9 @@ #include <stdint.h> #include "DHT.h" -#include "LAN_discovery.h" #include "attributes.h" #include "logger.h" +#include "mem.h" #include "mono_time.h" #include "net_crypto.h" #include "network.h" @@ -161,7 +161,7 @@ void set_friend_request_callback(Friend_Connections *fr_c, fr_request_cb *fr_req /** Create new friend_connections instance. */ non_null() Friend_Connections *new_friend_connections( - const Logger *logger, const Mono_Time *mono_time, const Network *ns, + const Logger *logger, const Memory *mem, const Mono_Time *mono_time, const Network *ns, Onion_Client *onion_c, bool local_discovery_enabled); /** main friend_connections loop. */ diff --git a/protocols/Tox/libtox/src/toxcore/friend_requests.c b/protocols/Tox/libtox/src/toxcore/friend_requests.c index 8b915449cd..e28ce7df85 100644 --- a/protocols/Tox/libtox/src/toxcore/friend_requests.c +++ b/protocols/Tox/libtox/src/toxcore/friend_requests.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ @@ -8,18 +8,22 @@ */ #include "friend_requests.h" -#include <stdlib.h> #include <string.h> #include "attributes.h" #include "ccompat.h" #include "crypto_core.h" #include "friend_connection.h" +#include "mem.h" #include "network.h" #include "onion.h" #include "onion_announce.h" #include "onion_client.h" +static_assert(ONION_CLIENT_MAX_DATA_SIZE <= MAX_DATA_REQUEST_SIZE, "ONION_CLIENT_MAX_DATA_SIZE is too big"); +static_assert(MAX_DATA_REQUEST_SIZE <= ONION_MAX_DATA_SIZE, "MAX_DATA_REQUEST_SIZE is too big"); +static_assert(SIZE_IPPORT <= ONION_SEND_BASE, "IP_Port does not fit in the onion packet"); + /** * NOTE: The following is just a temporary fix for the multiple friend requests received at the same time problem. * TODO(irungentoo): Make this better (This will most likely tie in with the way we will handle spam). @@ -32,6 +36,8 @@ struct Received_Requests { }; struct Friend_Requests { + const Memory *mem; + uint32_t nospam; fr_friend_request_cb *handle_friendrequest; uint8_t handle_friendrequest_isset; @@ -164,12 +170,24 @@ void friendreq_init(Friend_Requests *fr, Friend_Connections *fr_c) set_friend_request_callback(fr_c, &friendreq_handlepacket, fr); } -Friend_Requests *friendreq_new(void) +Friend_Requests *friendreq_new(const Memory *mem) { - return (Friend_Requests *)calloc(1, sizeof(Friend_Requests)); + Friend_Requests *fr = (Friend_Requests *)mem_alloc(mem, sizeof(Friend_Requests)); + + if (fr == nullptr) { + return nullptr; + } + + fr->mem = mem; + + return fr; } void friendreq_kill(Friend_Requests *fr) { - free(fr); + if (fr == nullptr) { + return; + } + + mem_delete(fr->mem, fr); } diff --git a/protocols/Tox/libtox/src/toxcore/friend_requests.h b/protocols/Tox/libtox/src/toxcore/friend_requests.h index a78a570dfa..c7bae81fb8 100644 --- a/protocols/Tox/libtox/src/toxcore/friend_requests.h +++ b/protocols/Tox/libtox/src/toxcore/friend_requests.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2014 Tox project. */ @@ -13,8 +13,10 @@ #include "attributes.h" #include "friend_connection.h" +#include "mem.h" -#define MAX_FRIEND_REQUEST_DATA_SIZE (ONION_CLIENT_MAX_DATA_SIZE - (1 + sizeof(uint32_t))) +// TODO(Jfreegman): This should be the maximum size that an onion client can handle. +#define MAX_FRIEND_REQUEST_DATA_SIZE (ONION_CLIENT_MAX_DATA_SIZE - 100) typedef struct Friend_Requests Friend_Requests; @@ -49,7 +51,8 @@ void set_filter_function(Friend_Requests *fr, filter_function_cb *function, void non_null() void friendreq_init(Friend_Requests *fr, Friend_Connections *fr_c); -Friend_Requests *friendreq_new(void); +non_null() +Friend_Requests *friendreq_new(const Memory *mem); nullable(1) void friendreq_kill(Friend_Requests *fr); diff --git a/protocols/Tox/libtox/src/toxcore/group.c b/protocols/Tox/libtox/src/toxcore/group.c index 14e61e6ffc..dbc3876403 100644 --- a/protocols/Tox/libtox/src/toxcore/group.c +++ b/protocols/Tox/libtox/src/toxcore/group.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2014 Tox project. */ @@ -9,7 +9,6 @@ #include "group.h" #include <assert.h> -#include <stdlib.h> #include <string.h> #include "DHT.h" @@ -20,9 +19,11 @@ #include "friend_connection.h" #include "group_common.h" #include "logger.h" +#include "mem.h" #include "mono_time.h" #include "net_crypto.h" #include "network.h" +#include "sort.h" #include "state.h" #include "util.h" @@ -147,6 +148,7 @@ typedef struct Group_c { } Group_c; struct Group_Chats { + const Memory *mem; const Mono_Time *mono_time; Messenger *m; @@ -246,19 +248,19 @@ static bool is_groupnumber_valid(const Group_Chats *g_c, uint32_t groupnumber) /** @brief Set the size of the groupchat list to num. * - * @retval false if realloc fails. + * @retval false if mem_vrealloc fails. * @retval true if it succeeds. */ non_null() static bool realloc_conferences(Group_Chats *g_c, uint16_t num) { if (num == 0) { - free(g_c->chats); + mem_delete(g_c->mem, g_c->chats); g_c->chats = nullptr; return true; } - Group_c *newgroup_chats = (Group_c *)realloc(g_c->chats, num * sizeof(Group_c)); + Group_c *newgroup_chats = (Group_c *)mem_vrealloc(g_c->mem, g_c->chats, num, sizeof(Group_c)); if (newgroup_chats == nullptr) { return false; @@ -300,10 +302,10 @@ static int32_t create_group_chat(Group_Chats *g_c) } non_null() -static void wipe_group_c(Group_c *g) +static void wipe_group_c(const Memory *mem, Group_c *g) { - free(g->frozen); - free(g->group); + mem_delete(mem, g->frozen); + mem_delete(mem, g->group); crypto_memzero(g, sizeof(Group_c)); } @@ -318,7 +320,7 @@ static bool wipe_group_chat(Group_Chats *g_c, uint32_t groupnumber) return false; } - wipe_group_c(&g_c->chats[groupnumber]); + wipe_group_c(g_c->mem, &g_c->chats[groupnumber]); uint16_t i; @@ -667,7 +669,7 @@ static int get_frozen_index(const Group_c *g, uint16_t peer_number) } non_null() -static bool delete_frozen(Group_c *g, uint32_t frozen_index) +static bool delete_frozen(const Memory *mem, Group_c *g, uint32_t frozen_index) { if (frozen_index >= g->numfrozen) { return false; @@ -676,14 +678,14 @@ static bool delete_frozen(Group_c *g, uint32_t frozen_index) --g->numfrozen; if (g->numfrozen == 0) { - free(g->frozen); + mem_delete(mem, g->frozen); g->frozen = nullptr; } else { if (g->numfrozen != frozen_index) { g->frozen[frozen_index] = g->frozen[g->numfrozen]; } - Group_Peer *const frozen_temp = (Group_Peer *)realloc(g->frozen, g->numfrozen * sizeof(Group_Peer)); + Group_Peer *const frozen_temp = (Group_Peer *)mem_vrealloc(mem, g->frozen, g->numfrozen, sizeof(Group_Peer)); if (frozen_temp == nullptr) { return false; @@ -724,7 +726,7 @@ static int note_peer_active(Group_Chats *g_c, uint32_t groupnumber, uint16_t pee /* Now thaw the peer */ - Group_Peer *temp = (Group_Peer *)realloc(g->group, (g->numpeers + 1) * sizeof(Group_Peer)); + Group_Peer *temp = (Group_Peer *)mem_vrealloc(g_c->mem, g->group, g->numpeers + 1, sizeof(Group_Peer)); if (temp == nullptr) { return -1; @@ -741,7 +743,7 @@ static int note_peer_active(Group_Chats *g_c, uint32_t groupnumber, uint16_t pee ++g->numpeers; - delete_frozen(g, frozen_index); + delete_frozen(g_c->mem, g, frozen_index); if (g_c->peer_list_changed_callback != nullptr) { g_c->peer_list_changed_callback(g_c->m, groupnumber, userdata); @@ -777,7 +779,7 @@ static void delete_any_peer_with_pk(Group_Chats *g_c, uint32_t groupnumber, cons const int frozen_index = frozen_in_group(g, real_pk); if (frozen_index >= 0) { - delete_frozen(g, frozen_index); + delete_frozen(g_c->mem, g, frozen_index); } } @@ -837,7 +839,7 @@ static int addpeer(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_p delete_any_peer_with_pk(g_c, groupnumber, real_pk, userdata); - Group_Peer *temp = (Group_Peer *)realloc(g->group, (g->numpeers + 1) * sizeof(Group_Peer)); + Group_Peer *temp = (Group_Peer *)mem_vrealloc(g_c->mem, g->group, g->numpeers + 1, sizeof(Group_Peer)); if (temp == nullptr) { return -1; @@ -928,14 +930,14 @@ static bool delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void void *peer_object = g->group[peer_index].object; if (g->numpeers == 0) { - free(g->group); + mem_delete(g_c->mem, g->group); g->group = nullptr; } else { if (g->numpeers != (uint32_t)peer_index) { g->group[peer_index] = g->group[g->numpeers]; } - Group_Peer *temp = (Group_Peer *)realloc(g->group, g->numpeers * sizeof(Group_Peer)); + Group_Peer *temp = (Group_Peer *)mem_vrealloc(g_c->mem, g->group, g->numpeers, sizeof(Group_Peer)); if (temp == nullptr) { return false; @@ -957,39 +959,90 @@ static bool delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void /** Order peers with friends first and with more recently active earlier */ non_null() -static int cmp_frozen(const void *a, const void *b) +static bool group_peer_less_handler(const void *object, const void *a, const void *b) { const Group_Peer *pa = (const Group_Peer *)a; const Group_Peer *pb = (const Group_Peer *)b; - if (pa->is_friend ^ pb->is_friend) { - return pa->is_friend ? -1 : 1; + if (((pa->is_friend ? 1 : 0) ^ (pb->is_friend ? 1 : 0)) != 0) { + return pa->is_friend; } - return cmp_uint(pb->last_active, pa->last_active); + return cmp_uint(pb->last_active, pa->last_active) < 0; } +non_null() +static const void *group_peer_get_handler(const void *arr, uint32_t index) +{ + const Group_Peer *entries = (const Group_Peer *)arr; + return &entries[index]; +} + +non_null() +static void group_peer_set_handler(void *arr, uint32_t index, const void *val) +{ + Group_Peer *entries = (Group_Peer *)arr; + const Group_Peer *entry = (const Group_Peer *)val; + entries[index] = *entry; +} + +non_null() +static void *group_peer_subarr_handler(void *arr, uint32_t index, uint32_t size) +{ + Group_Peer *entries = (Group_Peer *)arr; + return &entries[index]; +} + +non_null() +static void *group_peer_alloc_handler(const void *object, uint32_t size) +{ + const Memory *mem = (const Memory *)object; + Group_Peer *tmp = (Group_Peer *)mem_valloc(mem, size, sizeof(Group_Peer)); + + if (tmp == nullptr) { + return nullptr; + } + + return tmp; +} + +non_null() +static void group_peer_delete_handler(const void *object, void *arr, uint32_t size) +{ + const Memory *mem = (const Memory *)object; + mem_delete(mem, arr); +} + +static const Sort_Funcs group_peer_cmp_funcs = { + group_peer_less_handler, + group_peer_get_handler, + group_peer_set_handler, + group_peer_subarr_handler, + group_peer_alloc_handler, + group_peer_delete_handler, +}; + /** @brief Delete frozen peers as necessary to ensure at most `g->maxfrozen` remain. * * @retval true if any frozen peers are removed. */ non_null() -static bool delete_old_frozen(Group_c *g) +static bool delete_old_frozen(Group_c *g, const Memory *mem) { if (g->numfrozen <= g->maxfrozen) { return false; } if (g->maxfrozen == 0) { - free(g->frozen); + mem_delete(mem, g->frozen); g->frozen = nullptr; g->numfrozen = 0; return true; } - qsort(g->frozen, g->numfrozen, sizeof(Group_Peer), cmp_frozen); + merge_sort(g->frozen, g->numfrozen, mem, &group_peer_cmp_funcs); - Group_Peer *temp = (Group_Peer *)realloc(g->frozen, g->maxfrozen * sizeof(Group_Peer)); + Group_Peer *temp = (Group_Peer *)mem_vrealloc(mem, g->frozen, g->maxfrozen, sizeof(Group_Peer)); if (temp == nullptr) { return false; @@ -1014,7 +1067,7 @@ static bool freeze_peer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, return false; } - Group_Peer *temp = (Group_Peer *)realloc(g->frozen, (g->numfrozen + 1) * sizeof(Group_Peer)); + Group_Peer *temp = (Group_Peer *)mem_vrealloc(g_c->mem, g->frozen, g->numfrozen + 1, sizeof(Group_Peer)); if (temp == nullptr) { return false; @@ -1032,7 +1085,7 @@ static bool freeze_peer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, ++g->numfrozen; - delete_old_frozen(g); + delete_old_frozen(g, g_c->mem); return true; } @@ -1519,7 +1572,7 @@ int group_set_max_frozen(const Group_Chats *g_c, uint32_t groupnumber, uint32_t } g->maxfrozen = maxfrozen; - delete_old_frozen(g); + delete_old_frozen(g, g_c->mem); return 0; } @@ -2520,7 +2573,7 @@ static int handle_send_peers(Group_Chats *g_c, uint32_t groupnumber, const uint8 non_null(1, 3) nullable(6) static void handle_direct_packet(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *data, uint16_t length, - int connection_index, void *userdata) + uint32_t connection_index, void *userdata) { if (length == 0) { return; @@ -2832,7 +2885,7 @@ static bool check_message_info(uint32_t message_number, uint8_t message_id, Grou non_null(1, 3) nullable(6) static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *data, uint16_t length, - int connection_index, void *userdata) + uint32_t connection_index, void *userdata) { if (length < sizeof(uint16_t) + sizeof(uint32_t) + 1) { return; @@ -3612,7 +3665,7 @@ static uint32_t load_group(Group_c *g, const Group_Chats *g_c, const uint8_t *da } // This is inefficient, but allows us to check data consistency before allocating memory - Group_Peer *tmp_frozen = (Group_Peer *)realloc(g->frozen, (j + 1) * sizeof(Group_Peer)); + Group_Peer *tmp_frozen = (Group_Peer *)mem_vrealloc(g_c->mem, g->frozen, j + 1, sizeof(Group_Peer)); if (tmp_frozen == nullptr) { // Memory allocation failure @@ -3752,18 +3805,19 @@ bool conferences_load_state_section(Group_Chats *g_c, const uint8_t *data, uint3 } /** Create new groupchat instance. */ -Group_Chats *new_groupchats(const Mono_Time *mono_time, Messenger *m) +Group_Chats *new_groupchats(const Mono_Time *mono_time, const Memory *mem, Messenger *m) { if (m == nullptr) { return nullptr; } - Group_Chats *temp = (Group_Chats *)calloc(1, sizeof(Group_Chats)); + Group_Chats *temp = (Group_Chats *)mem_alloc(mem, sizeof(Group_Chats)); if (temp == nullptr) { return nullptr; } + temp->mem = mem; temp->mono_time = mono_time; temp->m = m; temp->fr_c = m->fr_c; @@ -3814,7 +3868,7 @@ void kill_groupchats(Group_Chats *g_c) m_callback_conference_invite(g_c->m, nullptr); set_global_status_callback(g_c->m->fr_c, nullptr, nullptr); g_c->m->conferences_object = nullptr; - free(g_c); + mem_delete(g_c->mem, g_c); } /** diff --git a/protocols/Tox/libtox/src/toxcore/group.h b/protocols/Tox/libtox/src/toxcore/group.h index 5ce03275ec..706428fdda 100644 --- a/protocols/Tox/libtox/src/toxcore/group.h +++ b/protocols/Tox/libtox/src/toxcore/group.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2014 Tox project. */ @@ -15,6 +15,7 @@ #include "Messenger.h" #include "attributes.h" #include "crypto_core.h" +#include "mem.h" #include "mono_time.h" #include "state.h" @@ -390,7 +391,7 @@ bool conferences_load_state_section( /** Create new groupchat instance. */ non_null() -Group_Chats *new_groupchats(const Mono_Time *mono_time, Messenger *m); +Group_Chats *new_groupchats(const Mono_Time *mono_time, const Memory *mem, Messenger *m); /** main groupchats loop. */ non_null(1) nullable(2) diff --git a/protocols/Tox/libtox/src/toxcore/group_announce.c b/protocols/Tox/libtox/src/toxcore/group_announce.c index ee083198c1..caa70193aa 100644 --- a/protocols/Tox/libtox/src/toxcore/group_announce.c +++ b/protocols/Tox/libtox/src/toxcore/group_announce.c @@ -5,7 +5,6 @@ #include "group_announce.h" -#include <stdlib.h> #include <string.h> #include "DHT.h" @@ -13,6 +12,7 @@ #include "ccompat.h" #include "crypto_core.h" #include "logger.h" +#include "mem.h" #include "mono_time.h" #include "network.h" @@ -36,7 +36,7 @@ static void remove_announces(GC_Announces_List *gc_announces_list, GC_Announces announces->next_announce->prev_announce = announces->prev_announce; } - free(announces); + mem_delete(gc_announces_list->mem, announces); } /** @@ -343,10 +343,11 @@ int gca_unpack_announces_list(const Logger *log, const uint8_t *data, uint16_t l non_null() static GC_Announces *gca_new_announces( + const Memory *mem, GC_Announces_List *gc_announces_list, const GC_Public_Announce *public_announce) { - GC_Announces *announces = (GC_Announces *)calloc(1, sizeof(GC_Announces)); + GC_Announces *announces = (GC_Announces *)mem_alloc(mem, sizeof(GC_Announces)); if (announces == nullptr) { return nullptr; @@ -366,7 +367,7 @@ static GC_Announces *gca_new_announces( return announces; } -GC_Peer_Announce *gca_add_announce(const Mono_Time *mono_time, GC_Announces_List *gc_announces_list, +GC_Peer_Announce *gca_add_announce(const Memory *mem, const Mono_Time *mono_time, GC_Announces_List *gc_announces_list, const GC_Public_Announce *public_announce) { if (gc_announces_list == nullptr || public_announce == nullptr) { @@ -377,7 +378,7 @@ GC_Peer_Announce *gca_add_announce(const Mono_Time *mono_time, GC_Announces_List // No entry for this chat_id exists so we create one if (announces == nullptr) { - announces = gca_new_announces(gc_announces_list, public_announce); + announces = gca_new_announces(mem, gc_announces_list, public_announce); if (announces == nullptr) { return nullptr; @@ -410,9 +411,17 @@ bool gca_is_valid_announce(const GC_Announce *announce) return announce->tcp_relays_count > 0 || announce->ip_port_is_set; } -GC_Announces_List *new_gca_list(void) +GC_Announces_List *new_gca_list(const Memory *mem) { - return (GC_Announces_List *)calloc(1, sizeof(GC_Announces_List)); + GC_Announces_List *announces_list = (GC_Announces_List *)mem_alloc(mem, sizeof(GC_Announces_List)); + + if (announces_list == nullptr) { + return nullptr; + } + + announces_list->mem = mem; + + return announces_list; } void kill_gca(GC_Announces_List *announces_list) @@ -425,11 +434,11 @@ void kill_gca(GC_Announces_List *announces_list) while (root != nullptr) { GC_Announces *next = root->next_announce; - free(root); + mem_delete(announces_list->mem, root); root = next; } - free(announces_list); + mem_delete(announces_list->mem, announces_list); } /* How long we save a peer's announce before we consider it stale and remove it. */ diff --git a/protocols/Tox/libtox/src/toxcore/group_announce.h b/protocols/Tox/libtox/src/toxcore/group_announce.h index 72f2cfc1b8..2e043a069a 100644 --- a/protocols/Tox/libtox/src/toxcore/group_announce.h +++ b/protocols/Tox/libtox/src/toxcore/group_announce.h @@ -16,6 +16,7 @@ #include "attributes.h" #include "crypto_core.h" #include "logger.h" +#include "mem.h" #include "mono_time.h" #include "network.h" @@ -79,6 +80,8 @@ struct GC_Announces { /* A list of all announces. */ struct GC_Announces_List { + const Memory *mem; + GC_Announces *root_announces; uint64_t last_timeout_check; }; @@ -87,7 +90,8 @@ struct GC_Announces_List { * * The caller is responsible for freeing the memory with `kill_gca`. */ -GC_Announces_List *new_gca_list(void); +non_null() +GC_Announces_List *new_gca_list(const Memory *mem); /** @brief Frees all dynamically allocated memory associated with `announces_list`. */ nullable(1) @@ -135,7 +139,7 @@ int gca_get_announces(const GC_Announces_List *gc_announces_list, GC_Announce *g * @retval null on failure. */ non_null() -GC_Peer_Announce *gca_add_announce(const Mono_Time *mono_time, GC_Announces_List *gc_announces_list, +GC_Peer_Announce *gca_add_announce(const Memory *mem, const Mono_Time *mono_time, GC_Announces_List *gc_announces_list, const GC_Public_Announce *public_announce); /** @brief Packs an announce into a data buffer. diff --git a/protocols/Tox/libtox/src/toxcore/group_chats.c b/protocols/Tox/libtox/src/toxcore/group_chats.c index 96f647cc2e..43ed7e8272 100644 --- a/protocols/Tox/libtox/src/toxcore/group_chats.c +++ b/protocols/Tox/libtox/src/toxcore/group_chats.c @@ -12,7 +12,6 @@ #include <sodium.h> #include <assert.h> -#include <stdlib.h> #include <string.h> #include "DHT.h" @@ -30,6 +29,7 @@ #include "group_moderation.h" #include "group_pack.h" #include "logger.h" +#include "mem.h" #include "mono_time.h" #include "net_crypto.h" #include "network.h" @@ -168,8 +168,6 @@ non_null() static void group_delete(GC_Session *c, GC_Chat *chat); non_null() static void group_cleanup(const GC_Session *c, GC_Chat *chat); non_null() static bool group_exists(const GC_Session *c, const uint8_t *chat_id); non_null() static void add_tcp_relays_to_chat(const GC_Session *c, GC_Chat *chat); -non_null(1, 2) nullable(4) -static bool peer_delete(const GC_Session *c, GC_Chat *chat, uint32_t peer_number, void *userdata); non_null() static void create_gc_session_keypair(const Logger *log, const Random *rng, uint8_t *public_key, uint8_t *secret_key); non_null() static size_t load_gc_peers(GC_Chat *chat, const GC_SavedPeerInfo *addrs, uint16_t num_addrs); @@ -837,6 +835,21 @@ static int saved_peer_index(const GC_Chat *chat, const uint8_t *public_key) return -1; } +/** @brief Removes entry containing `public_key` from the saved peers list. */ +non_null() +static void saved_peers_remove_entry(GC_Chat *chat, const uint8_t *public_key) +{ + const int idx = saved_peer_index(chat, public_key); + + if (idx < 0) { + return; + } + + chat->saved_peers[idx] = (GC_SavedPeerInfo) { + 0 + }; +} + /** @brief Returns the index of the first vacant entry in saved peers list. * * If `public_key` is non-null and already exists in the list, its index will be returned. @@ -961,7 +974,7 @@ non_null() static bool broadcast_gc_mod_list(const GC_Chat *chat); non_null() static bool broadcast_gc_shared_state(const GC_Chat *chat); non_null() static bool update_gc_sanctions_list(GC_Chat *chat, const uint8_t *public_sig_key); non_null() static bool update_gc_topic(GC_Chat *chat, const uint8_t *public_sig_key); -non_null() static bool send_gc_set_observer(const GC_Chat *chat, const uint8_t *target_ext_pk, +non_null() static bool send_gc_set_observer(const GC_Chat *chat, const Extended_Public_Key *target_ext_pk, const uint8_t *sanction_data, uint16_t length, bool add_obs); /** Returns true if peer designated by `peer_number` is in the sanctions list as an observer. */ @@ -1119,7 +1132,7 @@ static bool prune_gc_mod_list(GC_Chat *chat) non_null() static bool prune_gc_sanctions_list_inner( GC_Chat *chat, const Mod_Sanction *sanction, - const uint8_t target_ext_pk[ENC_PUBLIC_KEY_SIZE + SIG_PUBLIC_KEY_SIZE]) + const Extended_Public_Key *target_ext_pk) { if (!sanctions_list_remove_observer(&chat->moderation, sanction->target_public_enc_key, nullptr)) { LOGGER_WARNING(chat->log, "Failed to remove entry from observer list"); @@ -1159,10 +1172,10 @@ static bool prune_gc_sanctions_list(GC_Chat *chat) if (peer_number == -1) { const Mod_Sanction *sanction = &chat->moderation.sanctions[i]; - uint8_t target_ext_pk[ENC_PUBLIC_KEY_SIZE + SIG_PUBLIC_KEY_SIZE]; - memcpy(target_ext_pk, sanction->target_public_enc_key, ENC_PUBLIC_KEY_SIZE); - memcpy(target_ext_pk + ENC_PUBLIC_KEY_SIZE, sanction->setter_public_sig_key, SIG_PUBLIC_KEY_SIZE); - return prune_gc_sanctions_list_inner(chat, sanction, target_ext_pk); + Extended_Public_Key target_ext_pk; + memcpy(target_ext_pk.enc, sanction->target_public_enc_key, ENC_PUBLIC_KEY_SIZE); + memcpy(target_ext_pk.sig, sanction->setter_public_sig_key, SIG_PUBLIC_KEY_SIZE); + return prune_gc_sanctions_list_inner(chat, sanction, &target_ext_pk); } } @@ -1473,8 +1486,8 @@ static bool sign_gc_shared_state(GC_Chat *chat) * Return -2 on decryption failure. * Return -3 if plaintext payload length is invalid. */ -non_null(1, 2, 3, 5, 6) nullable(4) -static int group_packet_unwrap(const Logger *log, const GC_Connection *gconn, uint8_t *data, uint64_t *message_id, +non_null(1, 2, 3, 4, 6, 7) nullable(5) +static int group_packet_unwrap(const Logger *log, const Memory *mem, const GC_Connection *gconn, uint8_t *data, uint64_t *message_id, uint8_t *packet_type, const uint8_t *packet, uint16_t length) { assert(data != nullptr); @@ -1485,18 +1498,18 @@ static int group_packet_unwrap(const Logger *log, const GC_Connection *gconn, ui return -1; } - uint8_t *plain = (uint8_t *)malloc(length); + uint8_t *plain = (uint8_t *)mem_balloc(mem, length); if (plain == nullptr) { LOGGER_ERROR(log, "Failed to allocate memory for plain data buffer"); return -1; } - int plain_len = decrypt_data_symmetric(gconn->session_shared_key, packet, packet + CRYPTO_NONCE_SIZE, + int plain_len = decrypt_data_symmetric(mem, gconn->session_shared_key, packet, packet + CRYPTO_NONCE_SIZE, length - CRYPTO_NONCE_SIZE, plain); if (plain_len <= 0) { - free(plain); + mem_delete(mem, plain); return plain_len == 0 ? -3 : -2; } @@ -1510,7 +1523,7 @@ static int group_packet_unwrap(const Logger *log, const GC_Connection *gconn, ui --plain_len; if (plain_len < min_plain_len) { - free(plain); + mem_delete(mem, plain); return -3; } } @@ -1527,13 +1540,13 @@ static int group_packet_unwrap(const Logger *log, const GC_Connection *gconn, ui memcpy(data, real_plain + header_len, plain_len); - free(plain); + mem_delete(mem, plain); return plain_len; } int group_packet_wrap( - const Logger *log, const Random *rng, const uint8_t *self_pk, const uint8_t *shared_key, uint8_t *packet, + const Logger *log, const Memory *mem, const Random *rng, const uint8_t *self_pk, const uint8_t *shared_key, uint8_t *packet, uint16_t packet_size, const uint8_t *data, uint16_t length, uint64_t message_id, uint8_t gp_packet_type, Net_Packet_Type net_packet_type) { @@ -1553,7 +1566,7 @@ int group_packet_wrap( return -1; } - uint8_t *plain = (uint8_t *)malloc(packet_size); + uint8_t *plain = (uint8_t *)mem_balloc(mem, packet_size); if (plain == nullptr) { return -1; @@ -1581,20 +1594,20 @@ int group_packet_wrap( const uint16_t plain_len = padding_len + enc_header_len + length; const uint16_t encrypt_buf_size = plain_len + CRYPTO_MAC_SIZE; - uint8_t *encrypt = (uint8_t *)malloc(encrypt_buf_size); + uint8_t *encrypt = (uint8_t *)mem_balloc(mem, encrypt_buf_size); if (encrypt == nullptr) { - free(plain); + mem_delete(mem, plain); return -2; } - const int enc_len = encrypt_data_symmetric(shared_key, nonce, plain, plain_len, encrypt); + const int enc_len = encrypt_data_symmetric(mem, shared_key, nonce, plain, plain_len, encrypt); - free(plain); + mem_delete(mem, plain); if (enc_len != encrypt_buf_size) { LOGGER_ERROR(log, "encryption failed. packet type: 0x%02x, enc_len: %d", gp_packet_type, enc_len); - free(encrypt); + mem_delete(mem, encrypt); return -3; } @@ -1603,7 +1616,7 @@ int group_packet_wrap( memcpy(packet + 1 + ENC_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE); memcpy(packet + 1 + ENC_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, encrypt, enc_len); - free(encrypt); + mem_delete(mem, encrypt); return 1 + ENC_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + enc_len; } @@ -1613,7 +1626,7 @@ int group_packet_wrap( * Returns true on success. */ non_null() -static bool send_lossy_group_packet(const GC_Chat *chat, const GC_Connection *gconn, const uint8_t *data, +static bool send_lossy_group_packet(const GC_Chat *chat, GC_Connection *gconn, const uint8_t *data, uint16_t length, uint8_t packet_type) { assert(length <= MAX_GC_CUSTOM_LOSSY_PACKET_SIZE); @@ -1627,25 +1640,25 @@ static bool send_lossy_group_packet(const GC_Chat *chat, const GC_Connection *gc } const uint16_t packet_size = gc_get_wrapped_packet_size(length, NET_PACKET_GC_LOSSY); - uint8_t *packet = (uint8_t *)malloc(packet_size); + uint8_t *packet = (uint8_t *)mem_balloc(chat->mem, packet_size); if (packet == nullptr) { return false; } const int len = group_packet_wrap( - chat->log, chat->rng, chat->self_public_key.enc, gconn->session_shared_key, packet, + chat->log, chat->mem, chat->rng, chat->self_public_key.enc, gconn->session_shared_key, packet, packet_size, data, length, 0, packet_type, NET_PACKET_GC_LOSSY); if (len < 0) { LOGGER_ERROR(chat->log, "Failed to encrypt packet (type: 0x%02x, error: %d)", packet_type, len); - free(packet); + mem_delete(chat->mem, packet); return false; } const bool ret = gcc_send_packet(chat, gconn, packet, (uint16_t)len); - free(packet); + mem_delete(chat->mem, packet); return ret; } @@ -1883,7 +1896,7 @@ static bool sync_response_send_peers(GC_Chat *chat, GC_Connection *gconn, uint32 return true; } - uint8_t *response = (uint8_t *)malloc(MAX_GC_PACKET_CHUNK_SIZE); + uint8_t *response = (uint8_t *)mem_balloc(chat->mem, MAX_GC_PACKET_CHUNK_SIZE); if (response == nullptr) { return false; @@ -1923,7 +1936,7 @@ static bool sync_response_send_peers(GC_Chat *chat, GC_Connection *gconn, uint32 ++num_announces; } - free(response); + mem_delete(chat->mem, response); if (num_announces == 0) { // we send an empty sync response even if we didn't send any peers as an acknowledgement @@ -2223,7 +2236,7 @@ static int handle_gc_invite_response_reject(const GC_Session *c, GC_Chat *chat, * Return true on success. */ non_null() -static bool send_gc_invite_response_reject(const GC_Chat *chat, const GC_Connection *gconn, uint8_t type) +static bool send_gc_invite_response_reject(const GC_Chat *chat, GC_Connection *gconn, uint8_t type) { if (type >= GJ_INVALID) { type = GJ_INVITE_FAILED; @@ -2340,7 +2353,7 @@ static bool send_gc_lossy_packet_all_peers(const GC_Chat *chat, const uint8_t *d uint32_t confirmed_peers = 0; for (uint32_t i = 1; i < chat->numpeers; ++i) { - const GC_Connection *gconn = get_gc_connection(chat, i); + GC_Connection *gconn = get_gc_connection(chat, i); assert(gconn != nullptr); @@ -2387,7 +2400,7 @@ static bool send_gc_broadcast_message(const GC_Chat *chat, const uint8_t *data, return false; } - uint8_t *packet = (uint8_t *)malloc(length + GC_BROADCAST_ENC_HEADER_SIZE); + uint8_t *packet = (uint8_t *)mem_balloc(chat->mem, length + GC_BROADCAST_ENC_HEADER_SIZE); if (packet == nullptr) { return false; @@ -2397,7 +2410,7 @@ static bool send_gc_broadcast_message(const GC_Chat *chat, const uint8_t *data, const bool ret = send_gc_lossless_packet_all_peers(chat, packet, packet_len, GP_BROADCAST); - free(packet); + mem_delete(chat->mem, packet); return ret; } @@ -2631,7 +2644,7 @@ void gc_get_chat_id(const GC_Chat *chat, uint8_t *dest) non_null() static bool send_self_to_peer(const GC_Chat *chat, GC_Connection *gconn) { - GC_Peer *self = (GC_Peer *)calloc(1, sizeof(GC_Peer)); + GC_Peer *self = (GC_Peer *)mem_alloc(chat->mem, sizeof(GC_Peer)); if (self == nullptr) { return false; @@ -2640,10 +2653,10 @@ static bool send_self_to_peer(const GC_Chat *chat, GC_Connection *gconn) copy_self(chat, self); const uint16_t data_size = PACKED_GC_PEER_SIZE + sizeof(uint16_t) + MAX_GC_PASSWORD_SIZE; - uint8_t *data = (uint8_t *)malloc(data_size); + uint8_t *data = (uint8_t *)mem_balloc(chat->mem, data_size); if (data == nullptr) { - free(self); + mem_delete(chat->mem, self); return false; } @@ -2660,17 +2673,17 @@ static bool send_self_to_peer(const GC_Chat *chat, GC_Connection *gconn) const int packed_len = pack_gc_peer(data + length, data_size - length, self); length += packed_len; - free(self); + mem_delete(chat->mem, self); if (packed_len <= 0) { LOGGER_DEBUG(chat->log, "pack_gc_peer failed in handle_gc_peer_info_request_request %d", packed_len); - free(data); + mem_delete(chat->mem, data); return false; } const bool ret = send_lossless_group_packet(chat, gconn, data, length, GP_PEER_INFO_RESPONSE); - free(data); + mem_delete(chat->mem, data); return ret; } @@ -2736,7 +2749,7 @@ static bool send_gc_peer_exchange(const GC_Chat *chat, GC_Connection *gconn) * Return -5 if supplied group password is invalid. * Return -6 if we fail to add the peer to the peer list. * Return -7 if peer's role cannot be validated. - * Return -8 if malloc fails. + * Return -8 if memory allocation fails. */ non_null(1, 2, 4) nullable(6) static int handle_gc_peer_info_response(const GC_Session *c, GC_Chat *chat, uint32_t peer_number, @@ -2781,7 +2794,7 @@ static int handle_gc_peer_info_response(const GC_Session *c, GC_Chat *chat, uint return -1; } - GC_Peer *peer_info = (GC_Peer *)calloc(1, sizeof(GC_Peer)); + GC_Peer *peer_info = (GC_Peer *)mem_alloc(chat->mem, sizeof(GC_Peer)); if (peer_info == nullptr) { return -8; @@ -2789,17 +2802,17 @@ static int handle_gc_peer_info_response(const GC_Session *c, GC_Chat *chat, uint if (unpack_gc_peer(peer_info, data + unpacked_len, length - unpacked_len) == -1) { LOGGER_ERROR(chat->log, "unpack_gc_peer() failed"); - free(peer_info); + mem_delete(chat->mem, peer_info); return -6; } if (peer_update(chat, peer_info, peer_number) == -1) { LOGGER_WARNING(chat->log, "peer_update() failed"); - free(peer_info); + mem_delete(chat->mem, peer_info); return -6; } - free(peer_info); + mem_delete(chat->mem, peer_info); const bool was_confirmed = gconn->confirmed; gconn->confirmed = true; @@ -3181,7 +3194,7 @@ static int handle_gc_sanctions_list(const GC_Session *c, GC_Chat *chat, const ui Mod_Sanction_Creds creds; - Mod_Sanction *sanctions = (Mod_Sanction *)calloc(num_sanctions, sizeof(Mod_Sanction)); + Mod_Sanction *sanctions = (Mod_Sanction *)mem_valloc(chat->mem, num_sanctions, sizeof(Mod_Sanction)); if (sanctions == nullptr) { return -1; @@ -3192,25 +3205,25 @@ static int handle_gc_sanctions_list(const GC_Session *c, GC_Chat *chat, const ui if (unpacked_num != num_sanctions) { LOGGER_WARNING(chat->log, "Failed to unpack sanctions list: %d", unpacked_num); - free(sanctions); + mem_delete(chat->mem, sanctions); return handle_gc_sanctions_list_error(chat); } if (!sanctions_list_check_integrity(&chat->moderation, &creds, sanctions, num_sanctions)) { LOGGER_WARNING(chat->log, "Sanctions list failed integrity check"); - free(sanctions); + mem_delete(chat->mem, sanctions); return handle_gc_sanctions_list_error(chat); } if (creds.version < chat->moderation.sanctions_creds.version) { - free(sanctions); + mem_delete(chat->mem, sanctions); return 0; } // this may occur if two mods change the sanctions list at the exact same time if (creds.version == chat->moderation.sanctions_creds.version && creds.checksum <= chat->moderation.sanctions_creds.checksum) { - free(sanctions); + mem_delete(chat->mem, sanctions); return 0; } @@ -3247,7 +3260,7 @@ static int make_gc_mod_list_packet(const GC_Chat *chat, uint8_t *data, uint32_t const uint16_t length = sizeof(uint16_t) + mod_list_size; if (mod_list_size > 0) { - uint8_t *packed_mod_list = (uint8_t *)malloc(mod_list_size); + uint8_t *packed_mod_list = (uint8_t *)mem_balloc(chat->mem, mod_list_size); if (packed_mod_list == nullptr) { return -1; @@ -3256,7 +3269,7 @@ static int make_gc_mod_list_packet(const GC_Chat *chat, uint8_t *data, uint32_t mod_list_pack(&chat->moderation, packed_mod_list); memcpy(data + sizeof(uint16_t), packed_mod_list, mod_list_size); - free(packed_mod_list); + mem_delete(chat->mem, packed_mod_list); } return length; @@ -3271,7 +3284,7 @@ static bool send_peer_mod_list(const GC_Chat *chat, GC_Connection *gconn) { const uint16_t mod_list_size = chat->moderation.num_mods * MOD_LIST_ENTRY_SIZE; const uint16_t length = sizeof(uint16_t) + mod_list_size; - uint8_t *packet = (uint8_t *)malloc(length); + uint8_t *packet = (uint8_t *)mem_balloc(chat->mem, length); if (packet == nullptr) { return false; @@ -3280,13 +3293,13 @@ static bool send_peer_mod_list(const GC_Chat *chat, GC_Connection *gconn) const int packet_len = make_gc_mod_list_packet(chat, packet, length, mod_list_size); if (packet_len != length) { - free(packet); + mem_delete(chat->mem, packet); return false; } const bool ret = send_lossless_group_packet(chat, gconn, packet, length, GP_MOD_LIST); - free(packet); + mem_delete(chat->mem, packet); return ret; } @@ -3330,7 +3343,7 @@ static bool send_peer_sanctions_list(const GC_Chat *chat, GC_Connection *gconn) const uint16_t packet_size = MOD_SANCTION_PACKED_SIZE * chat->moderation.num_sanctions + sizeof(uint16_t) + MOD_SANCTIONS_CREDS_SIZE; - uint8_t *packet = (uint8_t *)malloc(packet_size); + uint8_t *packet = (uint8_t *)mem_balloc(chat->mem, packet_size); if (packet == nullptr) { return false; @@ -3339,13 +3352,13 @@ static bool send_peer_sanctions_list(const GC_Chat *chat, GC_Connection *gconn) const int packet_len = make_gc_sanctions_list_packet(chat, packet, packet_size); if (packet_len == -1) { - free(packet); + mem_delete(chat->mem, packet); return false; } const bool ret = send_lossless_group_packet(chat, gconn, packet, (uint16_t)packet_len, GP_SANCTIONS_LIST); - free(packet); + mem_delete(chat->mem, packet); return ret; } @@ -3360,7 +3373,7 @@ static bool broadcast_gc_sanctions_list(const GC_Chat *chat) const uint16_t packet_size = MOD_SANCTION_PACKED_SIZE * chat->moderation.num_sanctions + sizeof(uint16_t) + MOD_SANCTIONS_CREDS_SIZE; - uint8_t *packet = (uint8_t *)malloc(packet_size); + uint8_t *packet = (uint8_t *)mem_balloc(chat->mem, packet_size); if (packet == nullptr) { return false; @@ -3369,13 +3382,13 @@ static bool broadcast_gc_sanctions_list(const GC_Chat *chat) const int packet_len = make_gc_sanctions_list_packet(chat, packet, packet_size); if (packet_len == -1) { - free(packet); + mem_delete(chat->mem, packet); return false; } const bool ret = send_gc_lossless_packet_all_peers(chat, packet, (uint16_t)packet_len, GP_SANCTIONS_LIST); - free(packet); + mem_delete(chat->mem, packet); return ret; } @@ -3406,7 +3419,7 @@ static bool broadcast_gc_mod_list(const GC_Chat *chat) { const uint16_t mod_list_size = chat->moderation.num_mods * MOD_LIST_ENTRY_SIZE; const uint16_t length = sizeof(uint16_t) + mod_list_size; - uint8_t *packet = (uint8_t *)malloc(length); + uint8_t *packet = (uint8_t *)mem_balloc(chat->mem, length); if (packet == nullptr) { return false; @@ -3415,13 +3428,13 @@ static bool broadcast_gc_mod_list(const GC_Chat *chat) const int packet_len = make_gc_mod_list_packet(chat, packet, length, mod_list_size); if (packet_len != length) { - free(packet); + mem_delete(chat->mem, packet); return false; } const bool ret = send_gc_lossless_packet_all_peers(chat, packet, length, GP_MOD_LIST); - free(packet); + mem_delete(chat->mem, packet); return ret; } @@ -3699,7 +3712,7 @@ non_null() static bool send_peer_topic(const GC_Chat *chat, GC_Connection *gconn) { const uint16_t packet_buf_size = SIGNATURE_SIZE + chat->topic_info.length + GC_MIN_PACKED_TOPIC_INFO_SIZE; - uint8_t *packet = (uint8_t *)malloc(packet_buf_size); + uint8_t *packet = (uint8_t *)mem_balloc(chat->mem, packet_buf_size); if (packet == nullptr) { return false; @@ -3708,16 +3721,16 @@ static bool send_peer_topic(const GC_Chat *chat, GC_Connection *gconn) const int packet_len = make_gc_topic_packet(chat, packet, packet_buf_size); if (packet_len != packet_buf_size) { - free(packet); + mem_delete(chat->mem, packet); return false; } if (!send_lossless_group_packet(chat, gconn, packet, packet_buf_size, GP_TOPIC)) { - free(packet); + mem_delete(chat->mem, packet); return false; } - free(packet); + mem_delete(chat->mem, packet); return true; } @@ -3767,7 +3780,7 @@ non_null() static bool broadcast_gc_topic(const GC_Chat *chat) { const uint16_t packet_buf_size = SIGNATURE_SIZE + chat->topic_info.length + GC_MIN_PACKED_TOPIC_INFO_SIZE; - uint8_t *packet = (uint8_t *)malloc(packet_buf_size); + uint8_t *packet = (uint8_t *)mem_balloc(chat->mem, packet_buf_size); if (packet == nullptr) { return false; @@ -3776,13 +3789,13 @@ static bool broadcast_gc_topic(const GC_Chat *chat) const int packet_len = make_gc_topic_packet(chat, packet, packet_buf_size); if (packet_len != packet_buf_size) { - free(packet); + mem_delete(chat->mem, packet); return false; } const bool ret = send_gc_lossless_packet_all_peers(chat, packet, packet_buf_size, GP_TOPIC); - free(packet); + mem_delete(chat->mem, packet); return ret; } @@ -3832,7 +3845,7 @@ int gc_set_topic(GC_Chat *chat, const uint8_t *topic, uint16_t length) chat->topic_info.checksum = get_gc_topic_checksum(&chat->topic_info); const uint16_t packet_buf_size = length + GC_MIN_PACKED_TOPIC_INFO_SIZE; - uint8_t *packed_topic = (uint8_t *)malloc(packet_buf_size); + uint8_t *packed_topic = (uint8_t *)mem_balloc(chat->mem, packet_buf_size); if (packed_topic == nullptr) { return -3; @@ -3859,13 +3872,13 @@ int gc_set_topic(GC_Chat *chat, const uint8_t *topic, uint16_t length) chat->topic_prev_checksum = old_topic_info.checksum; chat->topic_time_set = mono_time_get(chat->mono_time); - free(packed_topic); + mem_delete(chat->mem, packed_topic); return 0; ON_ERROR: chat->topic_info = old_topic_info; memcpy(chat->topic_sig, old_topic_sig, SIGNATURE_SIZE); - free(packed_topic); + mem_delete(chat->mem, packed_topic); return err; } @@ -4116,24 +4129,24 @@ int gc_founder_set_password(GC_Chat *chat, const uint8_t *password, uint16_t pas } const uint16_t oldlen = chat->shared_state.password_length; - uint8_t *oldpasswd = memdup(chat->shared_state.password, oldlen); + uint8_t *oldpasswd = memdup(chat->mem, chat->shared_state.password, oldlen); if (oldpasswd == nullptr && oldlen > 0) { return -4; } if (!set_gc_password_local(chat, password, password_length)) { - free(oldpasswd); + mem_delete(chat->mem, oldpasswd); return -2; } if (!sign_gc_shared_state(chat)) { set_gc_password_local(chat, oldpasswd, oldlen); - free(oldpasswd); + mem_delete(chat->mem, oldpasswd); return -2; } - free(oldpasswd); + mem_delete(chat->mem, oldpasswd); if (!broadcast_gc_shared_state(chat)) { return -3; @@ -4258,7 +4271,7 @@ non_null() static bool send_gc_set_mod(const GC_Chat *chat, const GC_Connection *gconn, bool add_mod) { const uint16_t length = 1 + SIG_PUBLIC_KEY_SIZE; - uint8_t *data = (uint8_t *)malloc(length); + uint8_t *data = (uint8_t *)mem_balloc(chat->mem, length); if (data == nullptr) { return false; @@ -4269,11 +4282,11 @@ static bool send_gc_set_mod(const GC_Chat *chat, const GC_Connection *gconn, boo memcpy(data + 1, get_sig_pk(&gconn->addr.public_key), SIG_PUBLIC_KEY_SIZE); if (!send_gc_broadcast_message(chat, data, length, GM_SET_MOD)) { - free(data); + mem_delete(chat->mem, data); return false; } - free(data); + mem_delete(chat->mem, data); return true; } @@ -4457,11 +4470,11 @@ static int handle_gc_set_observer(const GC_Session *c, GC_Chat *chat, uint32_t p * Returns true on success. */ non_null() -static bool send_gc_set_observer(const GC_Chat *chat, const uint8_t *target_ext_pk, const uint8_t *sanction_data, - uint16_t length, bool add_obs) +static bool send_gc_set_observer(const GC_Chat *chat, const Extended_Public_Key *target_ext_pk, + const uint8_t *sanction_data, uint16_t length, bool add_obs) { - const uint16_t packet_len = 1 + EXT_PUBLIC_KEY_SIZE + length; - uint8_t *packet = (uint8_t *)malloc(packet_len); + const uint16_t packet_len = 1 + ENC_PUBLIC_KEY_SIZE + SIG_PUBLIC_KEY_SIZE + length; + uint8_t *packet = (uint8_t *)mem_balloc(chat->mem, packet_len); if (packet == nullptr) { return false; @@ -4469,15 +4482,16 @@ static bool send_gc_set_observer(const GC_Chat *chat, const uint8_t *target_ext_ net_pack_bool(&packet[0], add_obs); - memcpy(packet + 1, target_ext_pk, EXT_PUBLIC_KEY_SIZE); - memcpy(packet + 1 + EXT_PUBLIC_KEY_SIZE, sanction_data, length); + memcpy(packet + 1, target_ext_pk->enc, ENC_PUBLIC_KEY_SIZE); + memcpy(packet + 1 + ENC_PUBLIC_KEY_SIZE, target_ext_pk->sig, SIG_PUBLIC_KEY_SIZE); + memcpy(packet + 1 + ENC_PUBLIC_KEY_SIZE + SIG_PUBLIC_KEY_SIZE, sanction_data, length); if (!send_gc_broadcast_message(chat, packet, packet_len, GM_SET_OBSERVER)) { - free(packet); + mem_delete(chat->mem, packet); return false; } - free(packet); + mem_delete(chat->mem, packet); return true; } @@ -4557,7 +4571,7 @@ static bool mod_gc_set_observer(GC_Chat *chat, uint32_t peer_number, bool add_ob update_gc_peer_roles(chat); - return send_gc_set_observer(chat, gconn->addr.public_key.enc, sanction_data, length, add_obs); + return send_gc_set_observer(chat, &gconn->addr.public_key, sanction_data, length, add_obs); } /** @brief Sets the role of `peer_number` to `new_role`. If necessary this function will first @@ -4894,7 +4908,7 @@ int gc_send_message(const GC_Chat *chat, const uint8_t *message, uint16_t length const uint8_t packet_type = type == GC_MESSAGE_TYPE_NORMAL ? GM_PLAIN_MESSAGE : GM_ACTION_MESSAGE; const uint16_t length_raw = length + GC_MESSAGE_PSEUDO_ID_SIZE; - uint8_t *message_raw = (uint8_t *)malloc(length_raw); + uint8_t *message_raw = (uint8_t *)mem_balloc(chat->mem, length_raw); if (message_raw == nullptr) { return -5; @@ -4906,15 +4920,16 @@ int gc_send_message(const GC_Chat *chat, const uint8_t *message, uint16_t length memcpy(message_raw + GC_MESSAGE_PSEUDO_ID_SIZE, message, length); if (!send_gc_broadcast_message(chat, message_raw, length_raw, packet_type)) { - free(message_raw); + mem_delete(chat->mem, message_raw); return -5; } + mem_delete(chat->mem, message_raw); + if (message_id != nullptr) { *message_id = pseudo_msg_id; } - free(message_raw); return 0; } @@ -4954,7 +4969,7 @@ static int handle_gc_message(const GC_Session *c, const GC_Chat *chat, const GC_ } int gc_send_private_message(const GC_Chat *chat, GC_Peer_Id peer_id, uint8_t type, const uint8_t *message, - uint16_t length) + uint16_t length, uint32_t *message_id) { if (length > MAX_GC_MESSAGE_SIZE) { return -1; @@ -4980,32 +4995,41 @@ int gc_send_private_message(const GC_Chat *chat, GC_Peer_Id peer_id, uint8_t typ return -5; } - uint8_t *message_with_type = (uint8_t *)malloc(length + 1); + const uint16_t raw_length = 1 + length + GC_MESSAGE_PSEUDO_ID_SIZE; + uint8_t *message_with_type = (uint8_t *)mem_balloc(chat->mem, raw_length); if (message_with_type == nullptr) { return -6; } message_with_type[0] = type; - memcpy(message_with_type + 1, message, length); - uint8_t *packet = (uint8_t *)malloc(length + 1 + GC_BROADCAST_ENC_HEADER_SIZE); + const uint32_t pseudo_msg_id = random_u32(chat->rng); + net_pack_u32(message_with_type + 1, pseudo_msg_id); + + memcpy(message_with_type + 1 + GC_MESSAGE_PSEUDO_ID_SIZE, message, length); + + uint8_t *packet = (uint8_t *)mem_balloc(chat->mem, raw_length + GC_BROADCAST_ENC_HEADER_SIZE); if (packet == nullptr) { - free(message_with_type); + mem_delete(chat->mem, message_with_type); return -6; } - const uint16_t packet_len = make_gc_broadcast_header(message_with_type, length + 1, packet, GM_PRIVATE_MESSAGE); + const uint16_t packet_len = make_gc_broadcast_header(message_with_type, raw_length, packet, GM_PRIVATE_MESSAGE); - free(message_with_type); + mem_delete(chat->mem, message_with_type); if (!send_lossless_group_packet(chat, gconn, packet, packet_len, GP_BROADCAST)) { - free(packet); + mem_delete(chat->mem, packet); return -6; } - free(packet); + mem_delete(chat->mem, packet); + + if (message_id != nullptr) { + *message_id = pseudo_msg_id; + } return 0; } @@ -5019,7 +5043,7 @@ non_null(1, 2, 3, 4) nullable(6) static int handle_gc_private_message(const GC_Session *c, const GC_Chat *chat, const GC_Peer *peer, const uint8_t *data, uint16_t length, void *userdata) { - if (data == nullptr || length > MAX_GC_MESSAGE_SIZE || length <= 1) { + if (data == nullptr || length > MAX_GC_MESSAGE_SIZE || length <= 1 + GC_MESSAGE_PSEUDO_ID_SIZE) { return -1; } @@ -5034,8 +5058,13 @@ static int handle_gc_private_message(const GC_Session *c, const GC_Chat *chat, c return 0; } + uint32_t message_id; + net_unpack_u32(data + 1, &message_id); + if (c->private_message != nullptr) { - c->private_message(c->messenger, chat->group_number, peer->peer_id, message_type, data + 1, length - 1, userdata); + c->private_message(c->messenger, chat->group_number, peer->peer_id, message_type, + data + 1 + GC_MESSAGE_PSEUDO_ID_SIZE, length - 1 - GC_MESSAGE_PSEUDO_ID_SIZE, + message_id, userdata); } return 0; @@ -5066,10 +5095,6 @@ int gc_send_custom_private_packet(const GC_Chat *chat, bool lossless, GC_Peer_Id return -3; } - if (gc_get_self_role(chat) >= GR_OBSERVER) { - return -4; - } - bool ret; if (lossless) { @@ -5078,7 +5103,7 @@ int gc_send_custom_private_packet(const GC_Chat *chat, bool lossless, GC_Peer_Id ret = send_lossy_group_packet(chat, gconn, message, length, GP_CUSTOM_PRIVATE_PACKET); } - return ret ? 0 : -5; + return ret ? 0 : -4; } /** @brief Handles a custom private packet. @@ -5098,10 +5123,6 @@ static int handle_gc_custom_private_packet(const GC_Session *c, const GC_Chat *c return -1; } - if (peer->ignore || peer->role >= GR_OBSERVER) { - return 0; - } - if (c->custom_private_packet != nullptr) { c->custom_private_packet(c->messenger, chat->group_number, peer->peer_id, data, length, userdata); } @@ -5119,10 +5140,6 @@ int gc_send_custom_packet(const GC_Chat *chat, bool lossless, const uint8_t *dat return -2; } - if (gc_get_self_role(chat) >= GR_OBSERVER) { - return -3; - } - bool success; if (lossless) { @@ -5131,7 +5148,7 @@ int gc_send_custom_packet(const GC_Chat *chat, bool lossless, const uint8_t *dat success = send_gc_lossy_packet_all_peers(chat, data, length, GP_CUSTOM_PACKET); } - return success ? 0 : -4; + return success ? 0 : -3; } /** @brief Handles a custom packet. @@ -5151,10 +5168,6 @@ static int handle_gc_custom_packet(const GC_Session *c, const GC_Chat *chat, con return -1; } - if (peer->ignore || peer->role >= GR_OBSERVER) { - return 0; - } - if (c->custom_packet != nullptr) { c->custom_packet(c->messenger, chat->group_number, peer->peer_id, data, length, userdata); } @@ -5330,7 +5343,7 @@ static int handle_gc_message_ack(const GC_Chat *chat, GC_Connection *gconn, cons const Group_Message_Ack_Type type = (Group_Message_Ack_Type) data[0]; if (type == GR_ACK_RECV) { - if (!gcc_handle_ack(chat->log, gconn, message_id)) { + if (!gcc_handle_ack(chat->log, chat->mem, gconn, message_id)) { return -2; } @@ -5508,7 +5521,7 @@ static int handle_gc_broadcast(const GC_Session *c, GC_Chat *chat, uint32_t peer * Return -2 if decryption fails. */ non_null() -static int unwrap_group_handshake_packet(const Logger *log, const uint8_t *self_sk, const uint8_t *sender_pk, +static int unwrap_group_handshake_packet(const Logger *log, const Memory *mem, const uint8_t *self_sk, const uint8_t *sender_pk, uint8_t *plain, size_t plain_size, const uint8_t *packet, uint16_t length) { if (length <= CRYPTO_NONCE_SIZE) { @@ -5516,7 +5529,7 @@ static int unwrap_group_handshake_packet(const Logger *log, const uint8_t *self_ return -1; } - const int plain_len = decrypt_data(sender_pk, self_sk, packet, packet + CRYPTO_NONCE_SIZE, + const int plain_len = decrypt_data(mem, sender_pk, self_sk, packet, packet + CRYPTO_NONCE_SIZE, length - CRYPTO_NONCE_SIZE, plain); if (plain_len < 0 || (uint32_t)plain_len != plain_size) { @@ -5534,12 +5547,12 @@ static int unwrap_group_handshake_packet(const Logger *log, const uint8_t *self_ * * Return length of encrypted packet on success. * Return -1 if packet size is invalid. - * Return -2 on malloc failure. + * Return -2 on memory allocation failure. * Return -3 if encryption fails. */ non_null() static int wrap_group_handshake_packet( - const Logger *log, const Random *rng, const uint8_t *self_pk, const uint8_t *self_sk, + const Logger *log, const Memory *mem, const Random *rng, const uint8_t *self_pk, const uint8_t *self_sk, const uint8_t *target_pk, uint8_t *packet, uint32_t packet_size, const uint8_t *data, uint16_t length) { @@ -5552,17 +5565,17 @@ static int wrap_group_handshake_packet( random_nonce(rng, nonce); const size_t encrypt_buf_size = length + CRYPTO_MAC_SIZE; - uint8_t *encrypt = (uint8_t *)malloc(encrypt_buf_size); + uint8_t *encrypt = (uint8_t *)mem_balloc(mem, encrypt_buf_size); if (encrypt == nullptr) { return -2; } - const int enc_len = encrypt_data(target_pk, self_sk, nonce, data, length, encrypt); + const int enc_len = encrypt_data(mem, target_pk, self_sk, nonce, data, length, encrypt); if (enc_len < 0 || (size_t)enc_len != encrypt_buf_size) { LOGGER_ERROR(log, "Failed to encrypt group handshake packet (len: %d)", enc_len); - free(encrypt); + mem_delete(mem, encrypt); return -3; } @@ -5572,7 +5585,7 @@ static int wrap_group_handshake_packet( memcpy(packet + 1 + ENC_PUBLIC_KEY_SIZE + ENC_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE); memcpy(packet + 1 + ENC_PUBLIC_KEY_SIZE + ENC_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, encrypt, enc_len); - free(encrypt); + mem_delete(mem, encrypt); return 1 + ENC_PUBLIC_KEY_SIZE + ENC_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + enc_len; } @@ -5622,7 +5635,7 @@ static int make_gc_handshake_packet(const GC_Chat *chat, const GC_Connection *gc } const int enc_len = wrap_group_handshake_packet( - chat->log, chat->rng, chat->self_public_key.enc, chat->self_secret_key.enc, + chat->log, chat->mem, chat->rng, chat->self_public_key.enc, chat->self_secret_key.enc, gconn->addr.public_key.enc, packet, (uint16_t)packet_size, data, length); if (enc_len != GC_MIN_ENCRYPTED_HS_PAYLOAD_SIZE + nodes_size) { @@ -5945,18 +5958,18 @@ static int handle_gc_handshake_packet(GC_Chat *chat, const uint8_t *sender_pk, c } const size_t data_buf_size = length - CRYPTO_NONCE_SIZE - CRYPTO_MAC_SIZE; - uint8_t *data = (uint8_t *)malloc(data_buf_size); + uint8_t *data = (uint8_t *)mem_balloc(chat->mem, data_buf_size); if (data == nullptr) { return -1; } - const int plain_len = unwrap_group_handshake_packet(chat->log, chat->self_secret_key.enc, sender_pk, data, + const int plain_len = unwrap_group_handshake_packet(chat->log, chat->mem, chat->self_secret_key.enc, sender_pk, data, data_buf_size, packet, length); if (plain_len < GC_MIN_HS_PACKET_PAYLOAD_SIZE) { LOGGER_DEBUG(chat->log, "Failed to unwrap handshake packet (probably a stale request using an old key)"); - free(data); + mem_delete(chat->mem, data); return -1; } @@ -5972,11 +5985,11 @@ static int handle_gc_handshake_packet(GC_Chat *chat, const uint8_t *sender_pk, c } else if (handshake_type == GH_RESPONSE) { peer_number = handle_gc_handshake_response(chat, sender_pk, real_data, real_len); } else { - free(data); + mem_delete(chat->mem, data); return -1; } - free(data); + mem_delete(chat->mem, data); GC_Connection *gconn = get_gc_connection(chat, peer_number); @@ -6171,7 +6184,7 @@ static bool handle_gc_lossless_packet(const GC_Session *c, GC_Chat *chat, const return true; } - uint8_t *data = (uint8_t *)malloc(length); + uint8_t *data = (uint8_t *)mem_balloc(chat->mem, length); if (data == nullptr) { LOGGER_DEBUG(chat->log, "Failed to allocate memory for packet data buffer"); @@ -6181,19 +6194,19 @@ static bool handle_gc_lossless_packet(const GC_Session *c, GC_Chat *chat, const uint8_t packet_type; uint64_t message_id; - const int len = group_packet_unwrap(chat->log, gconn, data, &message_id, &packet_type, packet, length); + const int len = group_packet_unwrap(chat->log, chat->mem, gconn, data, &message_id, &packet_type, packet, length); if (len < 0) { Ip_Ntoa ip_str; LOGGER_DEBUG(chat->log, "Failed to unwrap lossless packet from %s:%d: %d", net_ip_ntoa(&gconn->addr.ip_port.ip, &ip_str), net_ntohs(gconn->addr.ip_port.port), len); - free(data); + mem_delete(chat->mem, data); return false; } if (!gconn->handshaked && (packet_type != GP_HS_RESPONSE_ACK && packet_type != GP_INVITE_REQUEST)) { LOGGER_DEBUG(chat->log, "Got lossless packet type 0x%02x from unconfirmed peer", packet_type); - free(data); + mem_delete(chat->mem, data); return false; } @@ -6203,28 +6216,27 @@ static bool handle_gc_lossless_packet(const GC_Session *c, GC_Chat *chat, const if (message_id == 3 && is_invite_packet && gconn->received_message_id <= 1) { // we missed initial handshake request. Drop this packet and wait for another handshake request. LOGGER_DEBUG(chat->log, "Missed handshake packet, type: 0x%02x", packet_type); - free(data); + mem_delete(chat->mem, data); return false; } - const int lossless_ret = gcc_handle_received_message(chat->log, chat->mono_time, gconn, data, (uint16_t) len, - packet_type, message_id, direct_conn); + const int lossless_ret = gcc_handle_received_message(chat->log, chat->mem, chat->mono_time, gconn, data, (uint16_t) len, packet_type, message_id, direct_conn); if (packet_type == GP_INVITE_REQUEST && !gconn->handshaked) { // Both peers sent request at same time - free(data); + mem_delete(chat->mem, data); return true; } if (lossless_ret < 0) { LOGGER_DEBUG(chat->log, "failed to handle packet %llu (type: 0x%02x, id: %llu)", (unsigned long long)message_id, packet_type, (unsigned long long)message_id); - free(data); + mem_delete(chat->mem, data); return false; } /* Duplicate packet */ if (lossless_ret == 0) { - free(data); + mem_delete(chat->mem, data); return gc_send_message_ack(chat, gconn, message_id, GR_ACK_RECV); } @@ -6232,7 +6244,7 @@ static bool handle_gc_lossless_packet(const GC_Session *c, GC_Chat *chat, const if (lossless_ret == 1) { LOGGER_TRACE(chat->log, "received out of order packet from peer %u. expected %llu, got %llu", peer_number, (unsigned long long)gconn->received_message_id + 1, (unsigned long long)message_id); - free(data); + mem_delete(chat->mem, data); return gc_send_message_ack(chat, gconn, gconn->received_message_id + 1, GR_ACK_REQ); } @@ -6240,13 +6252,13 @@ static bool handle_gc_lossless_packet(const GC_Session *c, GC_Chat *chat, const if (lossless_ret == 3) { const bool frag_ret = handle_gc_packet_fragment(c, chat, peer_number, gconn, data, (uint16_t)len, packet_type, message_id, userdata); - free(data); + mem_delete(chat->mem, data); return frag_ret; } const bool ret = handle_gc_lossless_helper(c, chat, peer_number, data, (uint16_t)len, packet_type, userdata); - free(data); + mem_delete(chat->mem, data); if (!ret) { return false; @@ -6325,7 +6337,7 @@ static bool handle_gc_lossy_packet(const GC_Session *c, GC_Chat *chat, const uin return false; } - uint8_t *data = (uint8_t *)malloc(length); + uint8_t *data = (uint8_t *)mem_balloc(chat->mem, length); if (data == nullptr) { LOGGER_ERROR(chat->log, "Failed to allocate memory for packet buffer"); @@ -6334,19 +6346,19 @@ static bool handle_gc_lossy_packet(const GC_Session *c, GC_Chat *chat, const uin uint8_t packet_type; - const int len = group_packet_unwrap(chat->log, gconn, data, nullptr, &packet_type, packet, length); + const int len = group_packet_unwrap(chat->log, chat->mem, gconn, data, nullptr, &packet_type, packet, length); if (len <= 0) { Ip_Ntoa ip_str; LOGGER_DEBUG(chat->log, "Failed to unwrap lossy packet from %s:%d: %d", net_ip_ntoa(&gconn->addr.ip_port.ip, &ip_str), net_ntohs(gconn->addr.ip_port.port), len); - free(data); + mem_delete(chat->mem, data); return false; } const int ret = handle_gc_lossy_packet_decoded(c, chat, gconn, peer, packet_type, data, (uint16_t)len, userdata); - free(data); + mem_delete(chat->mem, data); if (ret < 0) { LOGGER_DEBUG(chat->log, "Lossy packet handle error %d: type: 0x%02x, peernumber %d", ret, packet_type, @@ -6702,6 +6714,7 @@ void gc_callback_rejected(const Messenger *m, gc_rejected_cb *function) * * Return true on success. */ +non_null(1, 2) nullable(4) static bool peer_delete(const GC_Session *c, GC_Chat *chat, uint32_t peer_number, void *userdata) { GC_Peer *peer = get_gc_peer(chat, peer_number); @@ -6710,17 +6723,23 @@ static bool peer_delete(const GC_Session *c, GC_Chat *chat, uint32_t peer_number return false; } + GC_Connection *gconn = &peer->gconn; + // We need to save some peer info for the callback before deleting it - const bool peer_confirmed = peer->gconn.confirmed; + const bool peer_confirmed = gconn->confirmed; const GC_Peer_Id peer_id = peer->peer_id; uint8_t nick[MAX_GC_NICK_SIZE]; const uint16_t nick_length = peer->nick_length; - const GC_Exit_Info exit_info = peer->gconn.exit_info; + const GC_Exit_Info exit_info = gconn->exit_info; assert(nick_length <= MAX_GC_NICK_SIZE); memcpy(nick, peer->nick, nick_length); - gcc_peer_cleanup(&peer->gconn); + if (exit_info.exit_type == GC_EXIT_TYPE_KICKED) { + saved_peers_remove_entry(chat, gconn->addr.public_key.enc); + } + + gcc_peer_cleanup(chat->mem, gconn); --chat->numpeers; @@ -6732,7 +6751,7 @@ static bool peer_delete(const GC_Session *c, GC_Chat *chat, uint32_t peer_number 0 }; - GC_Peer *tmp_group = (GC_Peer *)realloc(chat->group, chat->numpeers * sizeof(GC_Peer)); + GC_Peer *tmp_group = (GC_Peer *)mem_vrealloc(chat->mem, chat->group, chat->numpeers, sizeof(GC_Peer)); if (tmp_group == nullptr) { return false; @@ -6808,8 +6827,8 @@ int peer_add(GC_Chat *chat, const IP_Port *ipp, const uint8_t *public_key) } } - GC_Message_Array_Entry *send = (GC_Message_Array_Entry *)calloc(GCC_BUFFER_SIZE, sizeof(GC_Message_Array_Entry)); - GC_Message_Array_Entry *recv = (GC_Message_Array_Entry *)calloc(GCC_BUFFER_SIZE, sizeof(GC_Message_Array_Entry)); + GC_Message_Array_Entry *send = (GC_Message_Array_Entry *)mem_valloc(chat->mem, GCC_BUFFER_SIZE, sizeof(GC_Message_Array_Entry)); + GC_Message_Array_Entry *recv = (GC_Message_Array_Entry *)mem_valloc(chat->mem, GCC_BUFFER_SIZE, sizeof(GC_Message_Array_Entry)); if (send == nullptr || recv == nullptr) { LOGGER_ERROR(chat->log, "Failed to allocate memory for gconn buffers"); @@ -6818,22 +6837,22 @@ int peer_add(GC_Chat *chat, const IP_Port *ipp, const uint8_t *public_key) kill_tcp_connection_to(chat->tcp_conn, tcp_connection_num); } - free(send); - free(recv); + mem_delete(chat->mem, send); + mem_delete(chat->mem, recv); return -1; } - GC_Peer *tmp_group = (GC_Peer *)realloc(chat->group, (chat->numpeers + 1) * sizeof(GC_Peer)); + GC_Peer *tmp_group = (GC_Peer *)mem_vrealloc(chat->mem, chat->group, chat->numpeers + 1, sizeof(GC_Peer)); if (tmp_group == nullptr) { - LOGGER_ERROR(chat->log, "Failed to allocate memory for group realloc"); + LOGGER_ERROR(chat->log, "Failed to allocate memory for group mem_vrealloc"); if (tcp_connection_num != -1) { kill_tcp_connection_to(chat->tcp_conn, tcp_connection_num); } - free(send); - free(recv); + mem_delete(chat->mem, send); + mem_delete(chat->mem, recv); return -1; } @@ -7053,10 +7072,10 @@ static void do_peer_delete(const GC_Session *c, GC_Chat *chat, void *userdata) * Return true on success. */ non_null() -static bool ping_peer(const GC_Chat *chat, const GC_Connection *gconn) +static bool ping_peer(const GC_Chat *chat, GC_Connection *gconn) { const uint16_t buf_size = GC_PING_PACKET_MIN_DATA_SIZE + sizeof(IP_Port); - uint8_t *data = (uint8_t *)malloc(buf_size); + uint8_t *data = (uint8_t *)mem_balloc(chat->mem, buf_size); if (data == nullptr) { return false; @@ -7102,11 +7121,11 @@ static bool ping_peer(const GC_Chat *chat, const GC_Connection *gconn) } if (!send_lossy_group_packet(chat, gconn, data, packed_len, GP_PING)) { - free(data); + mem_delete(chat->mem, data); return false; } - free(data); + mem_delete(chat->mem, data); return true; } @@ -7319,15 +7338,15 @@ void do_gc(GC_Session *c, void *userdata) * Return true on success. */ non_null() -static bool realloc_groupchats(GC_Session *c, uint32_t n) +static bool realloc_groupchats(const Memory *mem, GC_Session *c, uint32_t n) { if (n == 0) { - free(c->chats); + mem_delete(mem, c->chats); c->chats = nullptr; return true; } - GC_Chat *temp = (GC_Chat *)realloc(c->chats, n * sizeof(GC_Chat)); + GC_Chat *temp = (GC_Chat *)mem_vrealloc(mem, c->chats, n, sizeof(GC_Chat)); if (temp == nullptr) { return false; @@ -7338,7 +7357,7 @@ static bool realloc_groupchats(GC_Session *c, uint32_t n) } non_null() -static int get_new_group_index(GC_Session *c) +static int get_new_group_index(const Memory *mem, GC_Session *c) { if (c == nullptr) { return -1; @@ -7350,7 +7369,7 @@ static int get_new_group_index(GC_Session *c) } } - if (!realloc_groupchats(c, c->chats_index + 1)) { + if (!realloc_groupchats(mem, c, c->chats_index + 1)) { return -1; } @@ -7378,7 +7397,7 @@ static void add_tcp_relays_to_chat(const GC_Session *c, GC_Chat *chat) return; } - Node_format *tcp_relays = (Node_format *)calloc(num_relays, sizeof(Node_format)); + Node_format *tcp_relays = (Node_format *)mem_valloc(chat->mem, num_relays, sizeof(Node_format)); if (tcp_relays == nullptr) { return; @@ -7390,7 +7409,7 @@ static void add_tcp_relays_to_chat(const GC_Session *c, GC_Chat *chat) add_tcp_relay_global(chat->tcp_conn, &tcp_relays[i].ip_port, tcp_relays[i].public_key); } - free(tcp_relays); + mem_delete(chat->mem, tcp_relays); } non_null() @@ -7399,7 +7418,7 @@ static bool init_gc_tcp_connection(const GC_Session *c, GC_Chat *chat) const Messenger *m = c->messenger; chat->tcp_conn = new_tcp_connections(chat->log, chat->mem, chat->rng, m->ns, chat->mono_time, chat->self_secret_key.enc, - &m->options.proxy_info); + &m->options.proxy_info, c->tcp_np); if (chat->tcp_conn == nullptr) { return false; @@ -7460,7 +7479,7 @@ non_null() static bool create_new_chat_ext_keypair(GC_Chat *chat); non_null() -static int create_new_group(GC_Session *c, const uint8_t *nick, size_t nick_length, bool founder, +static int create_new_group(const Memory *mem, GC_Session *c, const uint8_t *nick, size_t nick_length, bool founder, const Group_Privacy_State privacy_state) { if (nick == nullptr || nick_length == 0) { @@ -7471,7 +7490,7 @@ static int create_new_group(GC_Session *c, const uint8_t *nick, size_t nick_leng return -1; } - const int group_number = get_new_group_index(c); + const int group_number = get_new_group_index(mem, c); if (group_number == -1) { return -1; @@ -7610,7 +7629,7 @@ void gc_group_save(const GC_Chat *chat, Bin_Pack *bp) int gc_group_load(GC_Session *c, Bin_Unpack *bu) { - const int group_number = get_new_group_index(c); + const int group_number = get_new_group_index(c->messenger->mem, c); if (group_number < 0) { return -1; @@ -7680,7 +7699,7 @@ int gc_group_add(GC_Session *c, Group_Privacy_State privacy_state, return -2; } - const int group_number = create_new_group(c, nick, nick_length, true, privacy_state); + const int group_number = create_new_group(c->messenger->mem, c, nick, nick_length, true, privacy_state); if (group_number == -1) { return -3; @@ -7732,10 +7751,52 @@ int gc_group_add(GC_Session *c, Group_Privacy_State privacy_state, return group_number; } +int gc_rejoin_group(GC_Session *c, GC_Chat *chat, const uint8_t *passwd, uint16_t passwd_len) +{ + if (c == nullptr) { + LOGGER_ERROR(chat->log, "NULL group session pointer."); + return -1; + } + + if (passwd != nullptr && passwd_len > 0) { + if (!set_gc_password_local(chat, passwd, passwd_len)) { + LOGGER_WARNING(chat->log, "Failed to set new password during reconnect."); + } + } + + chat->time_connected = 0; + + if (group_can_handle_packets(chat)) { + send_gc_self_exit(chat, nullptr, 0); + } + + for (uint32_t i = 1; i < chat->numpeers; ++i) { + GC_Connection *gconn = get_gc_connection(chat, i); + assert(gconn != nullptr); + + gcc_mark_for_deletion(gconn, chat->tcp_conn, GC_EXIT_TYPE_SELF_DISCONNECTED, nullptr, 0); + } + + if (is_public_chat(chat)) { + kill_group_friend_connection(c, chat); + + if (!m_create_group_connection(c->messenger, chat)) { + LOGGER_WARNING(chat->log, "Failed to create new messenger connection for group"); + return -1; + } + + chat->update_self_announces = true; + } + + chat->connection_state = CS_CONNECTING; + + return 0; +} + int gc_group_join(GC_Session *c, const uint8_t *chat_id, const uint8_t *nick, size_t nick_length, const uint8_t *passwd, uint16_t passwd_len) { - if (chat_id == nullptr || group_exists(c, chat_id) || getfriend_id(c->messenger, chat_id) != -1) { + if (chat_id == nullptr) { return -2; } @@ -7747,7 +7808,15 @@ int gc_group_join(GC_Session *c, const uint8_t *chat_id, const uint8_t *nick, si return -4; } - const int group_number = create_new_group(c, nick, nick_length, false, GI_PUBLIC); + GC_Chat *existing_group = gc_get_group_by_public_key(c, chat_id); + + // If we're already in the group we try to reconnect to it + if (existing_group != nullptr) { + const int ret = gc_rejoin_group(c, existing_group, passwd, passwd_len); + return ret != 0 ? -6 : ret; + } + + const int group_number = create_new_group(c->messenger->mem, c, nick, nick_length, false, GI_PUBLIC); if (group_number == -1) { return -1; @@ -7805,41 +7874,6 @@ bool gc_disconnect_from_group(const GC_Session *c, GC_Chat *chat) return true; } -int gc_rejoin_group(GC_Session *c, GC_Chat *chat) -{ - if (c == nullptr || chat == nullptr) { - return -1; - } - - chat->time_connected = 0; - - if (group_can_handle_packets(chat)) { - send_gc_self_exit(chat, nullptr, 0); - } - - for (uint32_t i = 1; i < chat->numpeers; ++i) { - GC_Connection *gconn = get_gc_connection(chat, i); - assert(gconn != nullptr); - - gcc_mark_for_deletion(gconn, chat->tcp_conn, GC_EXIT_TYPE_SELF_DISCONNECTED, nullptr, 0); - } - - if (is_public_chat(chat)) { - kill_group_friend_connection(c, chat); - - if (!m_create_group_connection(c->messenger, chat)) { - LOGGER_WARNING(chat->log, "Failed to create new messenger connection for group"); - return -2; - } - - chat->update_self_announces = true; - } - - chat->connection_state = CS_CONNECTING; - - return 0; -} - bool group_not_added(const GC_Session *c, const uint8_t *chat_id, uint32_t length) { if (length < CHAT_ID_SIZE) { @@ -7860,7 +7894,7 @@ int gc_invite_friend(const GC_Session *c, GC_Chat *chat, int32_t friend_number, assert(group_name_length <= MAX_GC_GROUP_NAME_SIZE); - uint8_t *packet = (uint8_t *)malloc(2 + CHAT_ID_SIZE + ENC_PUBLIC_KEY_SIZE + group_name_length); + uint8_t *packet = (uint8_t *)mem_balloc(chat->mem, 2 + CHAT_ID_SIZE + ENC_PUBLIC_KEY_SIZE + group_name_length); if (packet == nullptr) { return -1; @@ -7881,11 +7915,11 @@ int gc_invite_friend(const GC_Session *c, GC_Chat *chat, int32_t friend_number, assert(length <= MAX_GC_PACKET_SIZE); if (!callback(c->messenger, friend_number, packet, length)) { - free(packet); + mem_delete(chat->mem, packet); return -2; } - free(packet); + mem_delete(chat->mem, packet); chat->saved_invites[chat->saved_invites_index] = friend_number; chat->saved_invites_index = (chat->saved_invites_index + 1) % MAX_GC_SAVED_INVITES; @@ -7954,7 +7988,7 @@ static bool send_gc_invite_confirmed_packet(const Messenger *m, const GC_Chat *c } const uint16_t packet_length = 2 + length; - uint8_t *packet = (uint8_t *)malloc(packet_length); + uint8_t *packet = (uint8_t *)mem_balloc(chat->mem, packet_length); if (packet == nullptr) { return false; @@ -7966,11 +8000,11 @@ static bool send_gc_invite_confirmed_packet(const Messenger *m, const GC_Chat *c memcpy(packet + 2, data, length); if (!send_group_invite_packet(m, friend_number, packet, packet_length)) { - free(packet); + mem_delete(chat->mem, packet); return false; } - free(packet); + mem_delete(chat->mem, packet); return true; } @@ -8183,7 +8217,7 @@ int gc_accept_invite(GC_Session *c, int32_t friend_number, const uint8_t *data, const uint8_t *chat_id = data; const uint8_t *invite_chat_pk = data + CHAT_ID_SIZE; - const int group_number = create_new_group(c, nick, nick_length, false, GI_PUBLIC); + const int group_number = create_new_group(c->messenger->mem, c, nick, nick_length, false, GI_PUBLIC); if (group_number == -1) { return -2; @@ -8232,7 +8266,7 @@ GC_Session *new_dht_groupchats(Messenger *m) return nullptr; } - GC_Session *c = (GC_Session *)calloc(1, sizeof(GC_Session)); + GC_Session *c = (GC_Session *)mem_alloc(m->mem, sizeof(GC_Session)); if (c == nullptr) { return nullptr; @@ -8240,6 +8274,7 @@ GC_Session *new_dht_groupchats(Messenger *m) c->messenger = m; c->announces_list = m->group_announce; + c->tcp_np = m->tcp_np; networking_registerhandler(m->net, NET_PACKET_GC_LOSSLESS, &handle_gc_udp_packet, m); networking_registerhandler(m->net, NET_PACKET_GC_LOSSY, &handle_gc_udp_packet, m); @@ -8263,7 +8298,7 @@ static void group_cleanup(const GC_Session *c, GC_Chat *chat) gcc_cleanup(chat); if (chat->group != nullptr) { - free(chat->group); + mem_delete(chat->mem, chat->group); chat->group = nullptr; } @@ -8298,7 +8333,7 @@ static void group_delete(GC_Session *c, GC_Chat *chat) if (c->chats_index != i) { c->chats_index = i; - if (!realloc_groupchats(c, c->chats_index)) { + if (!realloc_groupchats(c->messenger->mem, c, c->chats_index)) { LOGGER_ERROR(c->messenger->log, "Failed to reallocate groupchats array"); } } @@ -8341,8 +8376,8 @@ void kill_dht_groupchats(GC_Session *c) networking_registerhandler(c->messenger->net, NET_PACKET_GC_HANDSHAKE, nullptr, nullptr); onion_group_announce_register(c->messenger->onion_c, nullptr, nullptr); - free(c->chats); - free(c); + mem_delete(c->messenger->mem, c->chats); + mem_delete(c->messenger->mem, c); } bool gc_group_is_valid(const GC_Chat *chat) @@ -8353,7 +8388,7 @@ bool gc_group_is_valid(const GC_Chat *chat) /** Return true if `group_number` designates an active group in session `c`. */ static bool group_number_valid(const GC_Session *c, int group_number) { - if (group_number < 0 || group_number >= c->chats_index) { + if (group_number < 0 || (uint32_t)group_number >= c->chats_index) { return false; } @@ -8408,19 +8443,7 @@ GC_Chat *gc_get_group_by_public_key(const GC_Session *c, const uint8_t *public_k /** Return True if chat_id exists in the session chat array */ static bool group_exists(const GC_Session *c, const uint8_t *chat_id) { - for (uint32_t i = 0; i < c->chats_index; ++i) { - const GC_Chat *chat = &c->chats[i]; - - if (chat->connection_state == CS_NONE) { - continue; - } - - if (memcmp(get_chat_id(&chat->chat_public_key), chat_id, CHAT_ID_SIZE) == 0) { - return true; - } - } - - return false; + return gc_get_group_by_public_key(c, chat_id) != nullptr; } /** Creates a new 32-byte session encryption keypair and puts the results in `public_key` and `secret_key`. */ diff --git a/protocols/Tox/libtox/src/toxcore/group_chats.h b/protocols/Tox/libtox/src/toxcore/group_chats.h index 32a7323dc4..481dee19eb 100644 --- a/protocols/Tox/libtox/src/toxcore/group_chats.h +++ b/protocols/Tox/libtox/src/toxcore/group_chats.h @@ -22,6 +22,7 @@ #include "group_common.h" #include "group_connection.h" #include "logger.h" +#include "mem.h" #include "network.h" #define GC_PING_TIMEOUT 12 @@ -141,9 +142,9 @@ int get_peer_number_of_enc_pk(const GC_Chat *chat, const uint8_t *public_enc_key * Return -2 if malloc fails. * Return -3 if encryption fails. */ -non_null(1, 2, 3, 4, 5) nullable(7) +non_null(1, 2, 3, 4, 5, 6) nullable(8) int group_packet_wrap( - const Logger *log, const Random *rng, const uint8_t *self_pk, const uint8_t *shared_key, uint8_t *packet, + const Logger *log, const Memory *mem, const Random *rng, const uint8_t *self_pk, const uint8_t *shared_key, uint8_t *packet, uint16_t packet_size, const uint8_t *data, uint16_t length, uint64_t message_id, uint8_t gp_packet_type, Net_Packet_Type net_packet_type); @@ -181,9 +182,9 @@ int gc_send_message(const GC_Chat *chat, const uint8_t *message, uint16_t length * Returns -5 if the sender has the observer role. * Returns -6 if the packet fails to send. */ -non_null() +non_null(1, 4) nullable(6) int gc_send_private_message(const GC_Chat *chat, GC_Peer_Id peer_id, uint8_t type, const uint8_t *message, - uint16_t length); + uint16_t length, uint32_t *message_id); /** @brief Sends a custom packet to the group. If lossless is true, the packet will be lossless. * @@ -192,8 +193,7 @@ int gc_send_private_message(const GC_Chat *chat, GC_Peer_Id peer_id, uint8_t typ * Returns 0 on success. * Returns -1 if the message is too long. * Returns -2 if the message pointer is NULL or length is zero. - * Returns -3 if the sender has the observer role. - * Returns -4 if the packet did not successfully send to any peer. + * Returns -3 if the packet did not successfully send to any peer. */ non_null() int gc_send_custom_packet(const GC_Chat *chat, bool lossless, const uint8_t *data, uint16_t length); @@ -206,8 +206,7 @@ int gc_send_custom_packet(const GC_Chat *chat, bool lossless, const uint8_t *dat * @retval -1 if the message is too long. * @retval -2 if the message pointer is NULL or length is zero. * @retval -3 if the supplied peer_id does not designate a valid peer. - * @retval -4 if the sender has the observer role. - * @retval -5 if the packet fails to send. + * @retval -4 if the packet fails to send. */ non_null() int gc_send_custom_private_packet(const GC_Chat *chat, bool lossless, GC_Peer_Id peer_id, const uint8_t *message, @@ -651,7 +650,7 @@ int gc_group_add(GC_Session *c, Group_Privacy_State privacy_state, const uint8_t * * Return group_number on success. * Return -1 if the group object fails to initialize. - * Return -2 if chat_id is NULL or a group with chat_id already exists in the chats array. + * Return -2 if chat_id is NULL. * Return -3 if nick is too long. * Return -4 if nick is empty or nick length is zero. * Return -5 if there is an error setting the group password. @@ -677,8 +676,8 @@ bool gc_disconnect_from_group(const GC_Session *c, GC_Chat *chat); * Returns -1 if the group handler object or chat object is null. * Returns -2 if the Messenger friend connection fails to initialize. */ -non_null() -int gc_rejoin_group(GC_Session *c, GC_Chat *chat); +non_null(1, 2) nullable(3) +int gc_rejoin_group(GC_Session *c, GC_Chat *chat, const uint8_t *passwd, uint16_t passwd_len); /** @brief Joins a group using the invite data received in a friend's group invite. * diff --git a/protocols/Tox/libtox/src/toxcore/group_common.h b/protocols/Tox/libtox/src/toxcore/group_common.h index bb1e6f9a64..19217706a7 100644 --- a/protocols/Tox/libtox/src/toxcore/group_common.h +++ b/protocols/Tox/libtox/src/toxcore/group_common.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2022 The TokTok team. + * Copyright © 2016-2025 The TokTok team. */ /** @@ -20,6 +20,7 @@ #include "logger.h" #include "mem.h" #include "mono_time.h" +#include "net_profile.h" #include "network.h" #define MAX_GC_PART_MESSAGE_SIZE 128 @@ -52,7 +53,7 @@ #define MAX_GC_PACKET_SIZE (MAX_GC_PACKET_CHUNK_SIZE * 100) /* Max number of messages to store in the send/recv arrays */ -#define GCC_BUFFER_SIZE 8192 +#define GCC_BUFFER_SIZE 2048 /** Self UDP status. Must correspond to return values from `ipport_self_copy()`. */ typedef enum Self_UDP_Status { @@ -114,6 +115,7 @@ typedef struct GC_Connection { uint64_t last_sent_tcp_relays_time; /* the last time we attempted to send this peer our tcp relays */ uint16_t tcp_relay_share_index; uint64_t last_received_direct_time; /* the last time we received a direct UDP packet from this connection */ + uint64_t last_sent_direct_try_time; /* the last time we tried sending a direct UDP packet */ uint64_t last_sent_ip_time; /* the last time we sent our ip info to this peer in a ping packet */ Node_format connected_tcp_relays[MAX_FRIEND_TCP_CONNECTIONS]; @@ -348,7 +350,7 @@ typedef struct Messenger Messenger; typedef void gc_message_cb(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id, unsigned int type, const uint8_t *message, size_t length, uint32_t message_id, void *user_data); typedef void gc_private_message_cb(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id, unsigned int type, - const uint8_t *message, size_t length, void *user_data); + const uint8_t *message, size_t length, uint32_t message_id, void *user_data); typedef void gc_custom_packet_cb(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id, const uint8_t *data, size_t length, void *user_data); typedef void gc_custom_private_packet_cb(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id, @@ -377,6 +379,7 @@ typedef void gc_rejected_cb(const Messenger *m, uint32_t group_number, unsigned typedef struct GC_Session { Messenger *messenger; GC_Chat *chats; + Net_Profile *tcp_np; struct GC_Announces_List *announces_list; uint32_t chats_index; diff --git a/protocols/Tox/libtox/src/toxcore/group_connection.c b/protocols/Tox/libtox/src/toxcore/group_connection.c index 1c2d1ec3da..dd6d21fd7c 100644 --- a/protocols/Tox/libtox/src/toxcore/group_connection.c +++ b/protocols/Tox/libtox/src/toxcore/group_connection.c @@ -11,7 +11,6 @@ #include <assert.h> #include <stdint.h> -#include <stdlib.h> #include <string.h> #include "DHT.h" @@ -22,6 +21,7 @@ #include "group_chats.h" #include "group_common.h" #include "logger.h" +#include "mem.h" #include "mono_time.h" #include "network.h" #include "util.h" @@ -29,6 +29,9 @@ /** Seconds since last direct UDP packet was received before the connection is considered dead */ #define GCC_UDP_DIRECT_TIMEOUT (GC_PING_TIMEOUT + 4) +/** Seconds since last direct UDP packet was sent before we can try again. Cheap NAT hole punch */ +#define GCC_UDP_DIRECT_RETRY 1 + /** Returns true if array entry does not contain an active packet. */ non_null() static bool array_entry_is_empty(const GC_Message_Array_Entry *array_entry) @@ -39,9 +42,9 @@ static bool array_entry_is_empty(const GC_Message_Array_Entry *array_entry) /** @brief Clears an array entry. */ non_null() -static void clear_array_entry(GC_Message_Array_Entry *const array_entry) +static void clear_array_entry(const Memory *mem, GC_Message_Array_Entry *const array_entry) { - free(array_entry->data); + mem_delete(mem, array_entry->data); *array_entry = (GC_Message_Array_Entry) { nullptr @@ -54,14 +57,14 @@ static void clear_array_entry(GC_Message_Array_Entry *const array_entry) * to `start_id`. */ non_null() -static void clear_send_queue_id_range(GC_Connection *gconn, uint64_t start_id, uint64_t end_id) +static void clear_send_queue_id_range(const Memory *mem, GC_Connection *gconn, uint64_t start_id, uint64_t end_id) { const uint16_t start_idx = gcc_get_array_index(start_id); const uint16_t end_idx = gcc_get_array_index(end_id); for (uint16_t i = start_idx; i != end_idx; i = (i + 1) % GCC_BUFFER_SIZE) { GC_Message_Array_Entry *entry = &gconn->send_array[i]; - clear_array_entry(entry); + clear_array_entry(mem, entry); } gconn->send_message_id = start_id; @@ -90,8 +93,8 @@ void gcc_set_recv_message_id(GC_Connection *gconn, uint64_t id) * * Return true on success. */ -non_null(1, 2, 3) nullable(4) -static bool create_array_entry(const Logger *log, const Mono_Time *mono_time, GC_Message_Array_Entry *array_entry, +non_null(1, 2, 3, 4) nullable(5) +static bool create_array_entry(const Logger *log, const Memory *mem, const Mono_Time *mono_time, GC_Message_Array_Entry *array_entry, const uint8_t *data, uint16_t length, uint8_t packet_type, uint64_t message_id) { if (!array_entry_is_empty(array_entry)) { @@ -109,7 +112,7 @@ static bool create_array_entry(const Logger *log, const Mono_Time *mono_time, GC return false; } - uint8_t *entry_data = (uint8_t *)malloc(length); + uint8_t *entry_data = (uint8_t *)mem_balloc(mem, length); if (entry_data == nullptr) { return false; @@ -134,9 +137,9 @@ static bool create_array_entry(const Logger *log, const Mono_Time *mono_time, GC * * Returns true and increments gconn's send_message_id on success. */ -non_null(1, 2, 3) nullable(4) -static bool add_to_send_array(const Logger *log, const Mono_Time *mono_time, GC_Connection *gconn, const uint8_t *data, - uint16_t length, uint8_t packet_type) +non_null(1, 2, 3, 4) nullable(5) +static bool add_to_send_array(const Logger *log, const Memory *mem, const Mono_Time *mono_time, GC_Connection *gconn, + const uint8_t *data, uint16_t length, uint8_t packet_type) { /* check if send_array is full */ if ((gconn->send_message_id % GCC_BUFFER_SIZE) == (uint16_t)(gconn->send_array_start - 1)) { @@ -147,7 +150,7 @@ static bool add_to_send_array(const Logger *log, const Mono_Time *mono_time, GC_ const uint16_t idx = gcc_get_array_index(gconn->send_message_id); GC_Message_Array_Entry *array_entry = &gconn->send_array[idx]; - if (!create_array_entry(log, mono_time, array_entry, data, length, packet_type, gconn->send_message_id)) { + if (!create_array_entry(log, mem, mono_time, array_entry, data, length, packet_type, gconn->send_message_id)) { return false; } @@ -161,7 +164,7 @@ int gcc_send_lossless_packet(const GC_Chat *chat, GC_Connection *gconn, const ui { const uint64_t message_id = gconn->send_message_id; - if (!add_to_send_array(chat->log, chat->mono_time, gconn, data, length, packet_type)) { + if (!add_to_send_array(chat->log, chat->mem, chat->mono_time, gconn, data, length, packet_type)) { LOGGER_WARNING(chat->log, "Failed to add payload to send array: (type: 0x%02x, length: %d)", packet_type, length); return -1; } @@ -172,7 +175,7 @@ int gcc_send_lossless_packet(const GC_Chat *chat, GC_Connection *gconn, const ui if (gcc_encrypt_and_send_lossless_packet(chat, gconn, data, length, message_id, packet_type) == -1) { const uint16_t idx = gcc_get_array_index(message_id); GC_Message_Array_Entry *array_entry = &gconn->send_array[idx]; - clear_array_entry(array_entry); + clear_array_entry(chat->mem, array_entry); gconn->send_message_id = message_id; LOGGER_ERROR(chat->log, "Failed to encrypt payload: (type: 0x%02x, length: %d)", packet_type, length); return -2; @@ -196,7 +199,7 @@ bool gcc_send_lossless_packet_fragments(const GC_Chat *chat, GC_Connection *gcon chunk[0] = packet_type; memcpy(chunk + 1, data, MAX_GC_PACKET_CHUNK_SIZE - 1); - if (!add_to_send_array(chat->log, chat->mono_time, gconn, chunk, MAX_GC_PACKET_CHUNK_SIZE, GP_FRAGMENT)) { + if (!add_to_send_array(chat->log, chat->mem, chat->mono_time, gconn, chunk, MAX_GC_PACKET_CHUNK_SIZE, GP_FRAGMENT)) { return false; } @@ -209,15 +212,15 @@ bool gcc_send_lossless_packet_fragments(const GC_Chat *chat, GC_Connection *gcon memcpy(chunk, data + processed, chunk_len); processed += chunk_len; - if (!add_to_send_array(chat->log, chat->mono_time, gconn, chunk, chunk_len, GP_FRAGMENT)) { - clear_send_queue_id_range(gconn, start_id, gconn->send_message_id); + if (!add_to_send_array(chat->log, chat->mem, chat->mono_time, gconn, chunk, chunk_len, GP_FRAGMENT)) { + clear_send_queue_id_range(chat->mem, gconn, start_id, gconn->send_message_id); return false; } } // empty packet signals the end of the sequence - if (!add_to_send_array(chat->log, chat->mono_time, gconn, nullptr, 0, GP_FRAGMENT)) { - clear_send_queue_id_range(gconn, start_id, gconn->send_message_id); + if (!add_to_send_array(chat->log, chat->mem, chat->mono_time, gconn, nullptr, 0, GP_FRAGMENT)) { + clear_send_queue_id_range(chat->mem, gconn, start_id, gconn->send_message_id); return false; } @@ -241,7 +244,7 @@ bool gcc_send_lossless_packet_fragments(const GC_Chat *chat, GC_Connection *gcon return true; } -bool gcc_handle_ack(const Logger *log, GC_Connection *gconn, uint64_t message_id) +bool gcc_handle_ack(const Logger *log, const Memory *mem, GC_Connection *gconn, uint64_t message_id) { uint16_t idx = gcc_get_array_index(message_id); GC_Message_Array_Entry *array_entry = &gconn->send_array[idx]; @@ -255,7 +258,7 @@ bool gcc_handle_ack(const Logger *log, GC_Connection *gconn, uint64_t message_id return false; } - clear_array_entry(array_entry); + clear_array_entry(mem, array_entry); /* Put send_array_start in proper position */ if (idx == gconn->send_array_start) { @@ -336,15 +339,15 @@ int gcc_save_tcp_relay(const Random *rng, GC_Connection *gconn, const Node_forma * * Return true on success. */ -non_null(1, 2, 3) nullable(4) -static bool store_in_recv_array(const Logger *log, const Mono_Time *mono_time, GC_Connection *gconn, - const uint8_t *data, +non_null(1, 2, 3, 4) nullable(5) +static bool store_in_recv_array(const Logger *log, const Memory *mem, const Mono_Time *mono_time, + GC_Connection *gconn, const uint8_t *data, uint16_t length, uint8_t packet_type, uint64_t message_id) { const uint16_t idx = gcc_get_array_index(message_id); GC_Message_Array_Entry *ary_entry = &gconn->recv_array[idx]; - return create_array_entry(log, mono_time, ary_entry, data, length, packet_type, message_id); + return create_array_entry(log, mem, mono_time, ary_entry, data, length, packet_type, message_id); } /** @@ -358,8 +361,8 @@ static bool store_in_recv_array(const Logger *log, const Mono_Time *mono_time, G * Return the length of the fully reassembled packet on success. * Return 0 on failure. */ -non_null(1, 3) nullable(2) -static uint16_t reassemble_packet(const Logger *log, GC_Connection *gconn, uint8_t **payload, uint64_t message_id) +non_null(1, 2, 4) nullable(3) +static uint16_t reassemble_packet(const Logger *log, const Memory *mem, GC_Connection *gconn, uint8_t **payload, uint64_t message_id) { uint16_t end_idx = gcc_get_array_index(message_id - 1); uint16_t start_idx = end_idx; @@ -395,7 +398,7 @@ static uint16_t reassemble_packet(const Logger *log, GC_Connection *gconn, uint8 return 0; } - uint8_t *tmp_payload = (uint8_t *)malloc(packet_length); + uint8_t *tmp_payload = (uint8_t *)mem_balloc(mem, packet_length); if (tmp_payload == nullptr) { LOGGER_ERROR(log, "Failed to allocate %u bytes for payload buffer", packet_length); @@ -414,7 +417,7 @@ static uint16_t reassemble_packet(const Logger *log, GC_Connection *gconn, uint8 memcpy(tmp_payload + processed, entry->data, entry->data_length); processed += entry->data_length; - clear_array_entry(entry); + clear_array_entry(mem, entry); } assert(*payload == nullptr); @@ -428,7 +431,7 @@ int gcc_handle_packet_fragment(const GC_Session *c, GC_Chat *chat, uint32_t peer uint64_t message_id, void *userdata) { if (length > 0) { - if (!store_in_recv_array(chat->log, chat->mono_time, gconn, chunk, length, packet_type, message_id)) { + if (!store_in_recv_array(chat->log, chat->mem, chat->mono_time, gconn, chunk, length, packet_type, message_id)) { return -1; } @@ -442,15 +445,15 @@ int gcc_handle_packet_fragment(const GC_Session *c, GC_Chat *chat, uint32_t peer memcpy(sender_pk, get_enc_key(&gconn->addr.public_key), ENC_PUBLIC_KEY_SIZE); uint8_t *payload = nullptr; - const uint16_t processed_len = reassemble_packet(chat->log, gconn, &payload, message_id); + const uint16_t processed_len = reassemble_packet(chat->log, chat->mem, gconn, &payload, message_id); if (processed_len == 0) { - free(payload); + mem_delete(chat->mem, payload); return -1; } if (!handle_gc_lossless_helper(c, chat, peer_number, payload + 1, processed_len - 1, payload[0], userdata)) { - free(payload); + mem_delete(chat->mem, payload); return -1; } @@ -459,19 +462,19 @@ int gcc_handle_packet_fragment(const GC_Session *c, GC_Chat *chat, uint32_t peer gconn = get_gc_connection(chat, peer_number); if (gconn == nullptr) { - free(payload); + mem_delete(chat->mem, payload); return 0; } gcc_set_recv_message_id(gconn, gconn->received_message_id + 1); gconn->last_chunk_id = 0; - free(payload); + mem_delete(chat->mem, payload); return 0; } -int gcc_handle_received_message(const Logger *log, const Mono_Time *mono_time, GC_Connection *gconn, +int gcc_handle_received_message(const Logger *log, const Memory *mem, const Mono_Time *mono_time, GC_Connection *gconn, const uint8_t *data, uint16_t length, uint8_t packet_type, uint64_t message_id, bool direct_conn) { @@ -490,7 +493,7 @@ int gcc_handle_received_message(const Logger *log, const Mono_Time *mono_time, G /* we're missing an older message from this peer so we store it in recv_array */ if (message_id > gconn->received_message_id + 1) { - if (!store_in_recv_array(log, mono_time, gconn, data, length, packet_type, message_id)) { + if (!store_in_recv_array(log, mem, mono_time, gconn, data, length, packet_type, message_id)) { return -1; } @@ -522,7 +525,7 @@ static bool process_recv_array_entry(const GC_Session *c, GC_Chat *chat, GC_Conn peer_number = get_peer_number_of_enc_pk(chat, sender_pk, false); gconn = get_gc_connection(chat, peer_number); - clear_array_entry(array_entry); + clear_array_entry(chat->mem, array_entry); if (gconn == nullptr) { return true; @@ -595,7 +598,7 @@ void gcc_resend_packets(const GC_Chat *chat, GC_Connection *gconn) } } -bool gcc_send_packet(const GC_Chat *chat, const GC_Connection *gconn, const uint8_t *packet, uint16_t length) +bool gcc_send_packet(const GC_Chat *chat, GC_Connection *gconn, const uint8_t *packet, uint16_t length) { if (packet == nullptr || length == 0) { return false; @@ -608,8 +611,12 @@ bool gcc_send_packet(const GC_Chat *chat, const GC_Connection *gconn, const uint return (uint16_t) sendpacket(chat->net, &gconn->addr.ip_port, packet, length) == length; } - if ((uint16_t) sendpacket(chat->net, &gconn->addr.ip_port, packet, length) == length) { - direct_send_attempt = true; + if (gcc_conn_should_try_direct(chat->mono_time, gconn)) { + gconn->last_sent_direct_try_time = mono_time_get(chat->mono_time); + + if ((uint16_t) sendpacket(chat->net, &gconn->addr.ip_port, packet, length) == length) { + direct_send_attempt = true; + } } } @@ -617,11 +624,11 @@ bool gcc_send_packet(const GC_Chat *chat, const GC_Connection *gconn, const uint return ret == 0 || direct_send_attempt; } -int gcc_encrypt_and_send_lossless_packet(const GC_Chat *chat, const GC_Connection *gconn, const uint8_t *data, +int gcc_encrypt_and_send_lossless_packet(const GC_Chat *chat, GC_Connection *gconn, const uint8_t *data, uint16_t length, uint64_t message_id, uint8_t packet_type) { const uint16_t packet_size = gc_get_wrapped_packet_size(length, NET_PACKET_GC_LOSSLESS); - uint8_t *packet = (uint8_t *)malloc(packet_size); + uint8_t *packet = (uint8_t *)mem_balloc(chat->mem, packet_size); if (packet == nullptr) { LOGGER_ERROR(chat->log, "Failed to allocate memory for packet buffer"); @@ -629,22 +636,22 @@ int gcc_encrypt_and_send_lossless_packet(const GC_Chat *chat, const GC_Connectio } const int enc_len = group_packet_wrap( - chat->log, chat->rng, chat->self_public_key.enc, gconn->session_shared_key, packet, + chat->log, chat->mem, chat->rng, chat->self_public_key.enc, gconn->session_shared_key, packet, packet_size, data, length, message_id, packet_type, NET_PACKET_GC_LOSSLESS); if (enc_len < 0) { LOGGER_ERROR(chat->log, "Failed to wrap packet (type: 0x%02x, error: %d)", packet_type, enc_len); - free(packet); + mem_delete(chat->mem, packet); return -1; } if (!gcc_send_packet(chat, gconn, packet, (uint16_t)enc_len)) { LOGGER_DEBUG(chat->log, "Failed to send packet (type: 0x%02x, enc_len: %d)", packet_type, enc_len); - free(packet); + mem_delete(chat->mem, packet); return -2; } - free(packet); + mem_delete(chat->mem, packet); return 0; } @@ -659,6 +666,11 @@ bool gcc_conn_is_direct(const Mono_Time *mono_time, const GC_Connection *gconn) return GCC_UDP_DIRECT_TIMEOUT + gconn->last_received_direct_time > mono_time_get(mono_time); } +bool gcc_conn_should_try_direct(const Mono_Time *mono_time, const GC_Connection *gconn) +{ + return mono_time_is_timeout(mono_time, gconn->last_sent_direct_try_time, GCC_UDP_DIRECT_RETRY); +} + bool gcc_direct_conn_is_possible(const GC_Chat *chat, const GC_Connection *gconn) { return !net_family_is_unspec(gconn->addr.ip_port.ip.family) && !net_family_is_unspec(net_family(chat->net)); @@ -686,15 +698,15 @@ void gcc_mark_for_deletion(GC_Connection *gconn, TCP_Connections *tcp_conn, Grou } } -void gcc_peer_cleanup(GC_Connection *gconn) +void gcc_peer_cleanup(const Memory *mem, GC_Connection *gconn) { for (size_t i = 0; i < GCC_BUFFER_SIZE; ++i) { - free(gconn->send_array[i].data); - free(gconn->recv_array[i].data); + mem_delete(mem, gconn->send_array[i].data); + mem_delete(mem, gconn->recv_array[i].data); } - free(gconn->recv_array); - free(gconn->send_array); + mem_delete(mem, gconn->recv_array); + mem_delete(mem, gconn->send_array); crypto_memunlock(gconn->session_secret_key, sizeof(gconn->session_secret_key)); crypto_memunlock(gconn->session_shared_key, sizeof(gconn->session_shared_key)); @@ -707,6 +719,6 @@ void gcc_cleanup(const GC_Chat *chat) GC_Connection *gconn = get_gc_connection(chat, i); assert(gconn != nullptr); - gcc_peer_cleanup(gconn); + gcc_peer_cleanup(chat->mem, gconn); } } diff --git a/protocols/Tox/libtox/src/toxcore/group_connection.h b/protocols/Tox/libtox/src/toxcore/group_connection.h index 4a9ccad0b3..7122f7a12d 100644 --- a/protocols/Tox/libtox/src/toxcore/group_connection.h +++ b/protocols/Tox/libtox/src/toxcore/group_connection.h @@ -16,6 +16,7 @@ #include "crypto_core.h" #include "group_common.h" #include "logger.h" +#include "mem.h" #include "mono_time.h" #include "network.h" @@ -35,8 +36,8 @@ void gcc_mark_for_deletion(GC_Connection *gconn, TCP_Connections *tcp_conn, Grou * Return 0 if message is a duplicate. * Return -1 on failure */ -non_null(1, 2, 3) nullable(4) -int gcc_handle_received_message(const Logger *log, const Mono_Time *mono_time, GC_Connection *gconn, +non_null(1, 2, 3, 4) nullable(5) +int gcc_handle_received_message(const Logger *log, const Memory *mem, const Mono_Time *mono_time, GC_Connection *gconn, const uint8_t *data, uint16_t length, uint8_t packet_type, uint64_t message_id, bool direct_conn); @@ -63,7 +64,7 @@ uint16_t gcc_get_array_index(uint64_t message_id); * Return true on success. */ non_null() -bool gcc_handle_ack(const Logger *log, GC_Connection *gconn, uint64_t message_id); +bool gcc_handle_ack(const Logger *log, const Memory *mem, GC_Connection *gconn, uint64_t message_id); /** @brief Sets the send_message_id and send_array_start for `gconn` to `id`. * @@ -134,6 +135,10 @@ void gcc_make_session_shared_key(GC_Connection *gconn, const uint8_t *sender_pk) non_null() bool gcc_conn_is_direct(const Mono_Time *mono_time, const GC_Connection *gconn); +/** @brief Return true if we can try a direct connection with `gconn` again. */ +non_null() +bool gcc_conn_should_try_direct(const Mono_Time *mono_time, const GC_Connection *gconn); + /** @brief Return true if a direct UDP connection is possible with `gconn`. */ non_null() bool gcc_direct_conn_is_possible(const GC_Chat *chat, const GC_Connection *gconn); @@ -145,7 +150,7 @@ bool gcc_direct_conn_is_possible(const GC_Chat *chat, const GC_Connection *gconn * Return true on success. */ non_null() -bool gcc_send_packet(const GC_Chat *chat, const GC_Connection *gconn, const uint8_t *packet, uint16_t length); +bool gcc_send_packet(const GC_Chat *chat, GC_Connection *gconn, const uint8_t *packet, uint16_t length); /** @brief Sends a lossless packet to `gconn` comprised of `data` of size `length`. * @@ -183,12 +188,12 @@ bool gcc_send_lossless_packet_fragments(const GC_Chat *chat, GC_Connection *gcon * Return -2 if the packet fails to send. */ non_null(1, 2) nullable(3) -int gcc_encrypt_and_send_lossless_packet(const GC_Chat *chat, const GC_Connection *gconn, const uint8_t *data, +int gcc_encrypt_and_send_lossless_packet(const GC_Chat *chat, GC_Connection *gconn, const uint8_t *data, uint16_t length, uint64_t message_id, uint8_t packet_type); /** @brief Called when a peer leaves the group. */ non_null() -void gcc_peer_cleanup(GC_Connection *gconn); +void gcc_peer_cleanup(const Memory *mem, GC_Connection *gconn); /** @brief Called on group exit. */ non_null() diff --git a/protocols/Tox/libtox/src/toxcore/group_moderation.c b/protocols/Tox/libtox/src/toxcore/group_moderation.c index 3cb69e9403..acc17bd570 100644 --- a/protocols/Tox/libtox/src/toxcore/group_moderation.c +++ b/protocols/Tox/libtox/src/toxcore/group_moderation.c @@ -11,7 +11,6 @@ #include <assert.h> -#include <stdlib.h> #include <string.h> #include <time.h> @@ -20,6 +19,7 @@ #include "ccompat.h" #include "crypto_core.h" #include "logger.h" +#include "mem.h" #include "network.h" #include "util.h" @@ -51,7 +51,7 @@ int mod_list_unpack(Moderation *moderation, const uint8_t *data, uint16_t length return 0; } - uint8_t **tmp_list = (uint8_t **)calloc(num_mods, sizeof(uint8_t *)); + uint8_t **tmp_list = (uint8_t **)mem_valloc(moderation->mem, num_mods, sizeof(uint8_t *)); if (tmp_list == nullptr) { return -1; @@ -60,7 +60,7 @@ int mod_list_unpack(Moderation *moderation, const uint8_t *data, uint16_t length uint16_t unpacked_len = 0; for (uint16_t i = 0; i < num_mods; ++i) { - uint8_t *entry = (uint8_t *)malloc(MOD_LIST_ENTRY_SIZE); + uint8_t *entry = (uint8_t *)mem_balloc(moderation->mem, MOD_LIST_ENTRY_SIZE); if (entry == nullptr) { free_uint8_t_pointer_array(moderation->mem, tmp_list, i); @@ -102,7 +102,7 @@ bool mod_list_make_hash(const Moderation *moderation, uint8_t *hash) assert(data_buf_size > 0); - uint8_t *data = (uint8_t *)malloc(data_buf_size); + uint8_t *data = (uint8_t *)mem_balloc(moderation->mem, data_buf_size); if (data == nullptr) { return false; @@ -112,7 +112,7 @@ bool mod_list_make_hash(const Moderation *moderation, uint8_t *hash) mod_list_get_data_hash(hash, data, data_buf_size); - free(data); + mem_delete(moderation->mem, data); return true; } @@ -166,10 +166,10 @@ bool mod_list_remove_index(Moderation *moderation, uint16_t index) MOD_LIST_ENTRY_SIZE); } - free(moderation->mod_list[moderation->num_mods]); + mem_delete(moderation->mem, moderation->mod_list[moderation->num_mods]); moderation->mod_list[moderation->num_mods] = nullptr; - uint8_t **tmp_list = (uint8_t **)realloc(moderation->mod_list, moderation->num_mods * sizeof(uint8_t *)); + uint8_t **tmp_list = (uint8_t **)mem_vrealloc(moderation->mem, moderation->mod_list, moderation->num_mods, sizeof(uint8_t *)); if (tmp_list == nullptr) { return false; @@ -203,7 +203,7 @@ bool mod_list_add_entry(Moderation *moderation, const uint8_t *mod_data) return false; } - uint8_t **tmp_list = (uint8_t **)realloc(moderation->mod_list, (moderation->num_mods + 1) * sizeof(uint8_t *)); + uint8_t **tmp_list = (uint8_t **)mem_vrealloc(moderation->mem, moderation->mod_list, moderation->num_mods + 1, sizeof(uint8_t *)); if (tmp_list == nullptr) { return false; @@ -211,7 +211,7 @@ bool mod_list_add_entry(Moderation *moderation, const uint8_t *mod_data) moderation->mod_list = tmp_list; - uint8_t *entry = (uint8_t *)malloc(MOD_LIST_ENTRY_SIZE); + uint8_t *entry = (uint8_t *)mem_balloc(moderation->mem, MOD_LIST_ENTRY_SIZE); if (entry == nullptr) { return false; @@ -405,8 +405,8 @@ int sanctions_list_unpack(Mod_Sanction *sanctions, Mod_Sanction_Creds *creds, ui * * Return true on success. */ -non_null(4) nullable(1) -static bool sanctions_list_make_hash(const Mod_Sanction *sanctions, uint32_t new_version, uint16_t num_sanctions, +non_null(1, 5) nullable(2) +static bool sanctions_list_make_hash(const Memory *mem, const Mod_Sanction *sanctions, uint32_t new_version, uint16_t num_sanctions, uint8_t *hash) { if (num_sanctions == 0 || sanctions == nullptr) { @@ -422,7 +422,7 @@ static bool sanctions_list_make_hash(const Mod_Sanction *sanctions, uint32_t new return false; } - uint8_t *data = (uint8_t *)malloc(data_buf_size); + uint8_t *data = (uint8_t *)mem_balloc(mem, data_buf_size); if (data == nullptr) { return false; @@ -435,7 +435,7 @@ static bool sanctions_list_make_hash(const Mod_Sanction *sanctions, uint32_t new memcpy(&data[sig_data_size], &new_version, sizeof(uint32_t)); crypto_sha256(hash, data, data_buf_size); - free(data); + mem_delete(mem, data); return true; } @@ -492,7 +492,7 @@ bool sanctions_list_make_creds(Moderation *moderation) uint8_t hash[MOD_SANCTION_HASH_SIZE]; - if (!sanctions_list_make_hash(moderation->sanctions, moderation->sanctions_creds.version, + if (!sanctions_list_make_hash(moderation->mem, moderation->sanctions, moderation->sanctions_creds.version, moderation->num_sanctions, hash)) { moderation->sanctions_creds = old_creds; return false; @@ -533,7 +533,7 @@ static bool sanctions_creds_validate(const Moderation *moderation, const Mod_San uint8_t hash[MOD_SANCTION_HASH_SIZE]; - if (!sanctions_list_make_hash(sanctions, creds->version, num_sanctions, hash)) { + if (!sanctions_list_make_hash(moderation->mem, sanctions, creds->version, num_sanctions, hash)) { return false; } @@ -612,9 +612,9 @@ static bool sanctions_apply_new(Moderation *moderation, Mod_Sanction *new_sancti * memory returned by this function. */ non_null() -static Mod_Sanction *sanctions_list_copy(const Mod_Sanction *sanctions, uint16_t num_sanctions) +static Mod_Sanction *sanctions_list_copy(const Memory *mem, const Mod_Sanction *sanctions, uint16_t num_sanctions) { - Mod_Sanction *copy = (Mod_Sanction *)calloc(num_sanctions, sizeof(Mod_Sanction)); + Mod_Sanction *copy = (Mod_Sanction *)mem_valloc(mem, num_sanctions, sizeof(Mod_Sanction)); if (copy == nullptr) { return nullptr; @@ -655,7 +655,7 @@ static bool sanctions_list_remove_index(Moderation *moderation, uint16_t index, } /* Operate on a copy of the list in case something goes wrong. */ - Mod_Sanction *sanctions_copy = sanctions_list_copy(moderation->sanctions, moderation->num_sanctions); + Mod_Sanction *sanctions_copy = sanctions_list_copy(moderation->mem, moderation->sanctions, moderation->num_sanctions); if (sanctions_copy == nullptr) { return false; @@ -665,15 +665,15 @@ static bool sanctions_list_remove_index(Moderation *moderation, uint16_t index, sanctions_copy[index] = sanctions_copy[new_num]; } - Mod_Sanction *new_list = (Mod_Sanction *)realloc(sanctions_copy, new_num * sizeof(Mod_Sanction)); + Mod_Sanction *new_list = (Mod_Sanction *)mem_vrealloc(moderation->mem, sanctions_copy, new_num, sizeof(Mod_Sanction)); if (new_list == nullptr) { - free(sanctions_copy); + mem_delete(moderation->mem, sanctions_copy); return false; } if (!sanctions_apply_new(moderation, new_list, creds, new_num)) { - free(new_list); + mem_delete(moderation->mem, new_list); return false; } @@ -753,7 +753,7 @@ bool sanctions_list_add_entry(Moderation *moderation, const Mod_Sanction *sancti Mod_Sanction *sanctions_copy = nullptr; if (moderation->num_sanctions > 0) { - sanctions_copy = sanctions_list_copy(moderation->sanctions, moderation->num_sanctions); + sanctions_copy = sanctions_list_copy(moderation->mem, moderation->sanctions, moderation->num_sanctions); if (sanctions_copy == nullptr) { return false; @@ -761,17 +761,17 @@ bool sanctions_list_add_entry(Moderation *moderation, const Mod_Sanction *sancti } const uint16_t index = moderation->num_sanctions; - Mod_Sanction *new_list = (Mod_Sanction *)realloc(sanctions_copy, (index + 1) * sizeof(Mod_Sanction)); + Mod_Sanction *new_list = (Mod_Sanction *)mem_vrealloc(moderation->mem, sanctions_copy, index + 1, sizeof(Mod_Sanction)); if (new_list == nullptr) { - free(sanctions_copy); + mem_delete(moderation->mem, sanctions_copy); return false; } new_list[index] = *sanction; if (!sanctions_apply_new(moderation, new_list, creds, index + 1)) { - free(new_list); + mem_delete(moderation->mem, new_list); return false; } @@ -864,7 +864,7 @@ uint16_t sanctions_list_replace_sig(Moderation *moderation, const uint8_t *publi void sanctions_list_cleanup(Moderation *moderation) { - free(moderation->sanctions); + mem_delete(moderation->mem, moderation->sanctions); moderation->sanctions = nullptr; moderation->num_sanctions = 0; diff --git a/protocols/Tox/libtox/src/toxcore/group_onion_announce.c b/protocols/Tox/libtox/src/toxcore/group_onion_announce.c index d05db09a07..5a19935c50 100644 --- a/protocols/Tox/libtox/src/toxcore/group_onion_announce.c +++ b/protocols/Tox/libtox/src/toxcore/group_onion_announce.c @@ -14,17 +14,22 @@ #include "crypto_core.h" #include "group_announce.h" #include "logger.h" +#include "mem.h" #include "mono_time.h" #include "network.h" #include "onion_announce.h" #include "timed_auth.h" +static_assert(TIMED_AUTH_SIZE <= ONION_ANNOUNCE_REQUEST_MAX_SIZE, + "Timed auth does not fit into the onion packet"); +static_assert(PACKED_NODE_SIZE_IP6 <= GCA_ANNOUNCE_MAX_SIZE, + "IP6 does not fit into the GC_Announce"); static_assert(GCA_ANNOUNCE_MAX_SIZE <= ONION_MAX_EXTRA_DATA_SIZE, "GC_Announce does not fit into the onion packet extra data"); static pack_extra_data_cb pack_group_announces; non_null() -static int pack_group_announces(void *object, const Logger *logger, const Mono_Time *mono_time, +static int pack_group_announces(void *object, const Logger *logger, const Memory *mem, const Mono_Time *mono_time, uint8_t num_nodes, uint8_t *plain, uint16_t plain_size, uint8_t *response, uint16_t response_size, uint16_t offset) { @@ -37,7 +42,7 @@ static int pack_group_announces(void *object, const Logger *logger, const Mono_T return -1; } - const GC_Peer_Announce *new_announce = gca_add_announce(mono_time, gc_announces_list, &public_announce); + const GC_Peer_Announce *new_announce = gca_add_announce(mem, mono_time, gc_announces_list, &public_announce); if (new_announce == nullptr) { LOGGER_ERROR(logger, "Failed to add group announce"); @@ -76,7 +81,7 @@ void gca_onion_init(GC_Announces_List *group_announce, Onion_Announce *onion_a) } int create_gca_announce_request( - const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id, + const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id, const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id, const uint8_t *data_public_key, uint64_t sendback_data, const uint8_t *gc_data, uint16_t gc_data_length) @@ -108,7 +113,7 @@ int create_gca_announce_request( random_nonce(rng, packet + 1); memcpy(packet + 1 + CRYPTO_NONCE_SIZE, public_key, CRYPTO_PUBLIC_KEY_SIZE); - const int len = encrypt_data(dest_client_id, secret_key, packet + 1, plain, + const int len = encrypt_data(mem, dest_client_id, secret_key, packet + 1, plain, encrypted_size, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE); const uint32_t full_length = (uint32_t)len + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE; diff --git a/protocols/Tox/libtox/src/toxcore/group_onion_announce.h b/protocols/Tox/libtox/src/toxcore/group_onion_announce.h index 5fbac02e0a..8abff63795 100644 --- a/protocols/Tox/libtox/src/toxcore/group_onion_announce.h +++ b/protocols/Tox/libtox/src/toxcore/group_onion_announce.h @@ -9,6 +9,7 @@ #include "attributes.h" #include "crypto_core.h" #include "group_announce.h" +#include "mem.h" #include "onion_announce.h" non_null() @@ -16,9 +17,9 @@ void gca_onion_init(GC_Announces_List *group_announce, Onion_Announce *onion_a); non_null() int create_gca_announce_request( - const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id, - const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id, - const uint8_t *client_id, const uint8_t *data_public_key, uint64_t sendback_data, - const uint8_t *gc_data, uint16_t gc_data_length); + const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length, + const uint8_t *dest_client_id, const uint8_t *public_key, const uint8_t *secret_key, + const uint8_t *ping_id, const uint8_t *client_id, const uint8_t *data_public_key, + uint64_t sendback_data, const uint8_t *gc_data, uint16_t gc_data_length); #endif /* C_TOXCORE_TOXCORE_GROUP_ONION_ANNOUNCE_H */ diff --git a/protocols/Tox/libtox/src/toxcore/group_pack.c b/protocols/Tox/libtox/src/toxcore/group_pack.c index e3af82c67a..877df7409e 100644 --- a/protocols/Tox/libtox/src/toxcore/group_pack.c +++ b/protocols/Tox/libtox/src/toxcore/group_pack.c @@ -10,7 +10,6 @@ #include "group_pack.h" #include <stdint.h> -#include <stdlib.h> #include <string.h> #include "DHT.h" @@ -23,49 +22,53 @@ #include "group_common.h" #include "group_moderation.h" #include "logger.h" +#include "mem.h" #include "network.h" #include "util.h" -bool group_privacy_state_from_int(uint8_t value, Group_Privacy_State *out) +static_assert(GC_SAVED_PEER_SIZE >= sizeof(IP_Port), + "GC_SAVED_PEER_SIZE cannot contain IP_Port"); + +bool group_privacy_state_from_int(uint8_t value, Group_Privacy_State *out_enum) { switch (value) { case GI_PUBLIC: { - *out = GI_PUBLIC; + *out_enum = GI_PUBLIC; return true; } case GI_PRIVATE: { - *out = GI_PRIVATE; + *out_enum = GI_PRIVATE; return true; } default: { - *out = GI_PUBLIC; + *out_enum = GI_PUBLIC; return false; } } } -bool group_voice_state_from_int(uint8_t value, Group_Voice_State *out) +bool group_voice_state_from_int(uint8_t value, Group_Voice_State *out_enum) { switch (value) { case GV_ALL: { - *out = GV_ALL; + *out_enum = GV_ALL; return true; } case GV_MODS: { - *out = GV_MODS; + *out_enum = GV_MODS; return true; } case GV_FOUNDER: { - *out = GV_FOUNDER; + *out_enum = GV_FOUNDER; return true; } default: { - *out = GV_ALL; + *out_enum = GV_ALL; return false; } } @@ -180,7 +183,7 @@ static bool load_unpack_mod_list(GC_Chat *chat, Bin_Unpack *bu) chat->moderation.num_mods = MOD_MAX_NUM_MODERATORS; } - uint8_t *packed_mod_list = (uint8_t *)malloc(chat->moderation.num_mods * MOD_LIST_ENTRY_SIZE); + uint8_t *packed_mod_list = (uint8_t *)mem_balloc(chat->mem, chat->moderation.num_mods * MOD_LIST_ENTRY_SIZE); if (packed_mod_list == nullptr) { LOGGER_ERROR(chat->log, "Failed to allocate memory for packed mod list"); @@ -191,17 +194,17 @@ static bool load_unpack_mod_list(GC_Chat *chat, Bin_Unpack *bu) if (!bin_unpack_bin_fixed(bu, packed_mod_list, packed_size)) { LOGGER_ERROR(chat->log, "Failed to unpack mod list binary data"); - free(packed_mod_list); + mem_delete(chat->mem, packed_mod_list); return false; } if (mod_list_unpack(&chat->moderation, packed_mod_list, packed_size, chat->moderation.num_mods) == -1) { LOGGER_ERROR(chat->log, "Failed to unpack mod list info"); - free(packed_mod_list); + mem_delete(chat->mem, packed_mod_list); return false; } - free(packed_mod_list); + mem_delete(chat->mem, packed_mod_list); return true; } @@ -299,7 +302,7 @@ static bool load_unpack_saved_peers(GC_Chat *chat, Bin_Unpack *bu) return true; } - uint8_t *saved_peers = (uint8_t *)malloc(saved_peers_size * GC_SAVED_PEER_SIZE); + uint8_t *saved_peers = (uint8_t *)mem_balloc(chat->mem, saved_peers_size * GC_SAVED_PEER_SIZE); if (saved_peers == nullptr) { LOGGER_ERROR(chat->log, "Failed to allocate memory for saved peer list"); @@ -308,7 +311,7 @@ static bool load_unpack_saved_peers(GC_Chat *chat, Bin_Unpack *bu) if (!bin_unpack_bin_fixed(bu, saved_peers, saved_peers_size)) { LOGGER_ERROR(chat->log, "Failed to unpack saved peers binary data"); - free(saved_peers); + mem_delete(chat->mem, saved_peers); return false; } @@ -316,7 +319,7 @@ static bool load_unpack_saved_peers(GC_Chat *chat, Bin_Unpack *bu) LOGGER_ERROR(chat->log, "Failed to unpack saved peers"); // recoverable error } - free(saved_peers); + mem_delete(chat->mem, saved_peers); return true; } @@ -390,7 +393,7 @@ static void save_pack_mod_list(const GC_Chat *chat, Bin_Pack *bp) return; } - uint8_t *packed_mod_list = (uint8_t *)malloc(num_mods * MOD_LIST_ENTRY_SIZE); + uint8_t *packed_mod_list = (uint8_t *)mem_balloc(chat->mem, num_mods * MOD_LIST_ENTRY_SIZE); // we can still recover without the mod list if (packed_mod_list == nullptr) { @@ -408,7 +411,7 @@ static void save_pack_mod_list(const GC_Chat *chat, Bin_Pack *bp) bin_pack_bin(bp, packed_mod_list, packed_size); // 2 - free(packed_mod_list); + mem_delete(chat->mem, packed_mod_list); } non_null() @@ -445,7 +448,7 @@ static void save_pack_saved_peers(const GC_Chat *chat, Bin_Pack *bp) { bin_pack_array(bp, 2); - uint8_t *saved_peers = (uint8_t *)malloc(GC_MAX_SAVED_PEERS * GC_SAVED_PEER_SIZE); + uint8_t *saved_peers = (uint8_t *)mem_balloc(chat->mem, GC_MAX_SAVED_PEERS * GC_SAVED_PEER_SIZE); // we can still recover without the saved peers list if (saved_peers == nullptr) { @@ -466,13 +469,13 @@ static void save_pack_saved_peers(const GC_Chat *chat, Bin_Pack *bp) if (packed_size == 0) { bin_pack_nil(bp); // 2 - free(saved_peers); + mem_delete(chat->mem, saved_peers); return; } bin_pack_bin(bp, saved_peers, packed_size); // 2 - free(saved_peers); + mem_delete(chat->mem, saved_peers); } void gc_save_pack_group(const GC_Chat *chat, Bin_Pack *bp) diff --git a/protocols/Tox/libtox/src/toxcore/group_pack.h b/protocols/Tox/libtox/src/toxcore/group_pack.h index 03252fb86d..4c999132db 100644 --- a/protocols/Tox/libtox/src/toxcore/group_pack.h +++ b/protocols/Tox/libtox/src/toxcore/group_pack.h @@ -34,8 +34,8 @@ non_null() bool gc_load_unpack_group(GC_Chat *chat, Bin_Unpack *bu); non_null() -bool group_privacy_state_from_int(uint8_t value, Group_Privacy_State *out); +bool group_privacy_state_from_int(uint8_t value, Group_Privacy_State *out_enum); non_null() -bool group_voice_state_from_int(uint8_t value, Group_Voice_State *out); +bool group_voice_state_from_int(uint8_t value, Group_Voice_State *out_enum); #endif /* C_TOXCORE_TOXCORE_GROUP_PACK_H */ diff --git a/protocols/Tox/libtox/src/toxcore/list.c b/protocols/Tox/libtox/src/toxcore/list.c index bf3db247f1..689ad0a614 100644 --- a/protocols/Tox/libtox/src/toxcore/list.c +++ b/protocols/Tox/libtox/src/toxcore/list.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2014 Tox project. */ @@ -12,11 +12,11 @@ #include <assert.h> #include <stdbool.h> -#include <stdlib.h> #include <string.h> #include "attributes.h" #include "ccompat.h" +#include "mem.h" /** * Basically, the elements in the list are placed in order so that they can be searched for easily @@ -115,7 +115,7 @@ static bool resize(BS_List *list, uint32_t new_size) return true; } - uint8_t *data = (uint8_t *)realloc(list->data, list->element_size * new_size); + uint8_t *data = (uint8_t *)mem_brealloc(list->mem, list->data, new_size * list->element_size); if (data == nullptr) { return false; @@ -123,7 +123,7 @@ static bool resize(BS_List *list, uint32_t new_size) list->data = data; - int *ids = (int *)realloc(list->ids, new_size * sizeof(int)); + int *ids = (int *)mem_vrealloc(list->mem, list->ids, new_size, sizeof(int)); if (ids == nullptr) { return false; @@ -134,8 +134,10 @@ static bool resize(BS_List *list, uint32_t new_size) return true; } -int bs_list_init(BS_List *list, uint32_t element_size, uint32_t initial_capacity, bs_list_cmp_cb *cmp_callback) +int bs_list_init(BS_List *list, const Memory *mem, uint32_t element_size, uint32_t initial_capacity, bs_list_cmp_cb *cmp_callback) { + list->mem = mem; + // set initial values list->n = 0; list->element_size = element_size; @@ -162,10 +164,10 @@ void bs_list_free(BS_List *list) } // free both arrays - free(list->data); + mem_delete(list->mem, list->data); list->data = nullptr; - free(list->ids); + mem_delete(list->mem, list->ids); list->ids = nullptr; } diff --git a/protocols/Tox/libtox/src/toxcore/list.h b/protocols/Tox/libtox/src/toxcore/list.h index 1dc66d01a4..ae0ea32746 100644 --- a/protocols/Tox/libtox/src/toxcore/list.h +++ b/protocols/Tox/libtox/src/toxcore/list.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2014 Tox project. */ @@ -16,6 +16,7 @@ #include <stdint.h> #include "attributes.h" +#include "mem.h" #ifdef __cplusplus extern "C" { @@ -24,6 +25,8 @@ extern "C" { typedef int bs_list_cmp_cb(const void *a, const void *b, size_t size); typedef struct BS_List { + const Memory *mem; + uint32_t n; // number of elements uint32_t capacity; // number of elements memory is allocated for uint32_t element_size; // size of the elements @@ -41,7 +44,7 @@ typedef struct BS_List { * @retval 0 failure */ non_null() -int bs_list_init(BS_List *list, uint32_t element_size, uint32_t initial_capacity, bs_list_cmp_cb *cmp_callback); +int bs_list_init(BS_List *list, const Memory *mem, uint32_t element_size, uint32_t initial_capacity, bs_list_cmp_cb *cmp_callback); /** Free a list initiated with list_init */ nullable(1) diff --git a/protocols/Tox/libtox/src/toxcore/logger.c b/protocols/Tox/libtox/src/toxcore/logger.c index 67fa52330b..b97ef8e184 100644 --- a/protocols/Tox/libtox/src/toxcore/logger.c +++ b/protocols/Tox/libtox/src/toxcore/logger.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013-2015 Tox project. */ @@ -8,88 +8,62 @@ */ #include "logger.h" +#include <assert.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "attributes.h" #include "ccompat.h" +#include "mem.h" struct Logger { + const Memory *mem; + logger_cb *callback; void *context; void *userdata; }; -#ifndef NDEBUG -static const char *logger_level_name(Logger_Level level) -{ - switch (level) { - case LOGGER_LEVEL_TRACE: - return "TRACE"; - - case LOGGER_LEVEL_DEBUG: - return "DEBUG"; - - case LOGGER_LEVEL_INFO: - return "INFO"; - - case LOGGER_LEVEL_WARNING: - return "WARNING"; - - case LOGGER_LEVEL_ERROR: - return "ERROR"; - } - - return "<unknown>"; -} -#endif /* NDEBUG */ - -non_null(1, 3, 5, 6) nullable(7) -static void logger_stderr_handler(void *context, Logger_Level level, const char *file, int line, const char *func, - const char *message, void *userdata) -{ -#ifndef NDEBUG - // GL stands for "global logger". - fprintf(stderr, "[GL] %s %s:%d(%s): %s\n", logger_level_name(level), file, line, func, message); - fprintf(stderr, "Default stderr logger triggered; aborting program\n"); - abort(); -#endif /* NDEBUG */ -} - -static const Logger logger_stderr = { - logger_stderr_handler, - nullptr, - nullptr, -}; - /* * Public Functions */ -Logger *logger_new(void) +Logger *logger_new(const Memory *mem) { - return (Logger *)calloc(1, sizeof(Logger)); + Logger *log = (Logger *)mem_alloc(mem, sizeof(Logger)); + + if (log == nullptr) { + return nullptr; + } + + log->mem = mem; + + return log; } void logger_kill(Logger *log) { - free(log); + if (log == nullptr) { + return; + } + + mem_delete(log->mem, log); } void logger_callback_log(Logger *log, logger_cb *function, void *context, void *userdata) { + assert(log != nullptr); log->callback = function; log->context = context; log->userdata = userdata; } -void logger_write(const Logger *log, Logger_Level level, const char *file, int line, const char *func, +void logger_write(const Logger *log, Logger_Level level, const char *file, uint32_t line, const char *func, const char *format, ...) { if (log == nullptr) { - log = &logger_stderr; + return; } if (log->callback == nullptr) { diff --git a/protocols/Tox/libtox/src/toxcore/logger.h b/protocols/Tox/libtox/src/toxcore/logger.h index 830db883aa..893c21fd10 100644 --- a/protocols/Tox/libtox/src/toxcore/logger.h +++ b/protocols/Tox/libtox/src/toxcore/logger.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ @@ -12,6 +12,7 @@ #include <stdint.h> #include "attributes.h" +#include "mem.h" #ifdef __cplusplus extern "C" { @@ -32,13 +33,14 @@ typedef enum Logger_Level { typedef struct Logger Logger; -typedef void logger_cb(void *context, Logger_Level level, const char *file, int line, +typedef void logger_cb(void *context, Logger_Level level, const char *file, uint32_t line, const char *func, const char *message, void *userdata); /** * Creates a new logger with logging disabled (callback is NULL) by default. */ -Logger *logger_new(void); +non_null() +Logger *logger_new(const Memory *mem); /** * Frees all resources associated with the logger. @@ -64,7 +66,7 @@ void logger_callback_log(Logger *log, logger_cb *function, void *context, void * */ non_null(3, 5, 6) nullable(1) GNU_PRINTF(6, 7) void logger_write( - const Logger *log, Logger_Level level, const char *file, int line, const char *func, + const Logger *log, Logger_Level level, const char *file, uint32_t line, const char *func, const char *format, ...); /* @brief Terminate the program with a signal. */ diff --git a/protocols/Tox/libtox/src/toxcore/mem.c b/protocols/Tox/libtox/src/toxcore/mem.c index bddc335b82..32e7eec07c 100644 --- a/protocols/Tox/libtox/src/toxcore/mem.c +++ b/protocols/Tox/libtox/src/toxcore/mem.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ @@ -53,6 +53,12 @@ void *mem_balloc(const Memory *mem, uint32_t size) return ptr; } +void *mem_brealloc(const Memory *mem, void *ptr, uint32_t size) +{ + void *const new_ptr = mem->funcs->realloc(mem->obj, ptr, size); + return new_ptr; +} + void *mem_alloc(const Memory *mem, uint32_t size) { void *const ptr = mem->funcs->calloc(mem->obj, 1, size); diff --git a/protocols/Tox/libtox/src/toxcore/mem.h b/protocols/Tox/libtox/src/toxcore/mem.h index 7a96b6d358..6c36027ce7 100644 --- a/protocols/Tox/libtox/src/toxcore/mem.h +++ b/protocols/Tox/libtox/src/toxcore/mem.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ @@ -46,6 +46,14 @@ const Memory *os_memory(void); non_null() void *mem_balloc(const Memory *mem, uint32_t size); /** + * @brief Resize an array of a given size for built-in types. + * + * If used for a type other than byte-sized types, `size` needs to be manually + * multiplied by the element size. + */ +non_null(1) nullable(2) void *mem_brealloc(const Memory *mem, void *ptr, uint32_t size); + +/** * @brief Allocate a single object. * * Always use as `(T *)mem_alloc(mem, sizeof(T))`. diff --git a/protocols/Tox/libtox/src/toxcore/mono_time.c b/protocols/Tox/libtox/src/toxcore/mono_time.c index 124f94fc23..8a3044c6f0 100644 --- a/protocols/Tox/libtox/src/toxcore/mono_time.c +++ b/protocols/Tox/libtox/src/toxcore/mono_time.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2023 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2014 Tox project. */ #ifndef _XOPEN_SOURCE @@ -218,7 +218,7 @@ void mono_time_set_current_time_callback(Mono_Time *mono_time, * The starting point is unspecified and in particular is likely not comparable * to the return value of `mono_time_get_ms()`. */ -uint64_t current_time_monotonic(Mono_Time *mono_time) +uint64_t current_time_monotonic(const Mono_Time *mono_time) { return mono_time->current_time_callback(mono_time->user_data); } diff --git a/protocols/Tox/libtox/src/toxcore/mono_time.h b/protocols/Tox/libtox/src/toxcore/mono_time.h index d0f2b7a6d3..e23c1ba0df 100644 --- a/protocols/Tox/libtox/src/toxcore/mono_time.h +++ b/protocols/Tox/libtox/src/toxcore/mono_time.h @@ -87,7 +87,7 @@ bool mono_time_is_timeout(const Mono_Time *mono_time, uint64_t timestamp, uint64 * to the return value of `mono_time_get_ms()`. */ non_null() -uint64_t current_time_monotonic(Mono_Time *mono_time); +uint64_t current_time_monotonic(const Mono_Time *mono_time); /** * Override implementation of `current_time_monotonic()` (for tests). diff --git a/protocols/Tox/libtox/src/toxcore/net_crypto.c b/protocols/Tox/libtox/src/toxcore/net_crypto.c index 1680b078b7..bf9f1d595a 100644 --- a/protocols/Tox/libtox/src/toxcore/net_crypto.c +++ b/protocols/Tox/libtox/src/toxcore/net_crypto.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ @@ -10,6 +10,7 @@ */ #include "net_crypto.h" +#include <pthread.h> #include <string.h> #include "DHT.h" @@ -23,6 +24,7 @@ #include "logger.h" #include "mem.h" #include "mono_time.h" +#include "net_profile.h" #include "network.h" #include "util.h" @@ -122,9 +124,6 @@ typedef struct Crypto_Connection { bool maximum_speed_reached; - /* Must be a pointer, because the struct is moved in memory */ - pthread_mutex_t *mutex; - dht_pk_cb *dht_pk_callback; void *dht_pk_callback_object; uint32_t dht_pk_callback_number; @@ -143,10 +142,6 @@ struct Net_Crypto { TCP_Connections *tcp_c; Crypto_Connection *crypto_connections; - pthread_mutex_t tcp_mutex; - - pthread_mutex_t connections_mutex; - unsigned int connection_use_counter; uint32_t crypto_connections_length; /* Length of connections array. */ @@ -237,7 +232,7 @@ static int create_cookie_request(const Net_Crypto *c, uint8_t *packet, const uin packet[0] = NET_PACKET_COOKIE_REQUEST; memcpy(packet + 1, dht_get_self_public_key(c->dht), CRYPTO_PUBLIC_KEY_SIZE); memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE); - const int len = encrypt_data_symmetric(shared_key, nonce, plain, sizeof(plain), + const int len = encrypt_data_symmetric(c->mem, shared_key, nonce, plain, sizeof(plain), packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE); if (len != COOKIE_REQUEST_PLAIN_LENGTH + CRYPTO_MAC_SIZE) { @@ -253,7 +248,7 @@ static int create_cookie_request(const Net_Crypto *c, uint8_t *packet, const uin * @retval 0 on success. */ non_null() -static int create_cookie(const Random *rng, const Mono_Time *mono_time, uint8_t *cookie, const uint8_t *bytes, +static int create_cookie(const Memory *mem, const Random *rng, const Mono_Time *mono_time, uint8_t *cookie, const uint8_t *bytes, const uint8_t *encryption_key) { uint8_t contents[COOKIE_CONTENTS_LENGTH]; @@ -261,7 +256,7 @@ static int create_cookie(const Random *rng, const Mono_Time *mono_time, uint8_t memcpy(contents, &temp_time, sizeof(temp_time)); memcpy(contents + sizeof(temp_time), bytes, COOKIE_DATA_LENGTH); random_nonce(rng, cookie); - const int len = encrypt_data_symmetric(encryption_key, cookie, contents, sizeof(contents), cookie + CRYPTO_NONCE_SIZE); + const int len = encrypt_data_symmetric(mem, encryption_key, cookie, contents, sizeof(contents), cookie + CRYPTO_NONCE_SIZE); if (len != COOKIE_LENGTH - CRYPTO_NONCE_SIZE) { return -1; @@ -276,11 +271,11 @@ static int create_cookie(const Random *rng, const Mono_Time *mono_time, uint8_t * @retval 0 on success. */ non_null() -static int open_cookie(const Mono_Time *mono_time, uint8_t *bytes, const uint8_t *cookie, +static int open_cookie(const Memory *mem, const Mono_Time *mono_time, uint8_t *bytes, const uint8_t *cookie, const uint8_t *encryption_key) { uint8_t contents[COOKIE_CONTENTS_LENGTH]; - const int len = decrypt_data_symmetric(encryption_key, cookie, cookie + CRYPTO_NONCE_SIZE, + const int len = decrypt_data_symmetric(mem, encryption_key, cookie, cookie + CRYPTO_NONCE_SIZE, COOKIE_LENGTH - CRYPTO_NONCE_SIZE, contents); if (len != sizeof(contents)) { @@ -315,14 +310,14 @@ static int create_cookie_response(const Net_Crypto *c, uint8_t *packet, const ui memcpy(cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, dht_public_key, CRYPTO_PUBLIC_KEY_SIZE); uint8_t plain[COOKIE_LENGTH + sizeof(uint64_t)]; - if (create_cookie(c->rng, c->mono_time, plain, cookie_plain, c->secret_symmetric_key) != 0) { + if (create_cookie(c->mem, c->rng, c->mono_time, plain, cookie_plain, c->secret_symmetric_key) != 0) { return -1; } memcpy(plain + COOKIE_LENGTH, request_plain + COOKIE_DATA_LENGTH, sizeof(uint64_t)); packet[0] = NET_PACKET_COOKIE_RESPONSE; random_nonce(c->rng, packet + 1); - const int len = encrypt_data_symmetric(shared_key, packet + 1, plain, sizeof(plain), packet + 1 + CRYPTO_NONCE_SIZE); + const int len = encrypt_data_symmetric(c->mem, shared_key, packet + 1, plain, sizeof(plain), packet + 1 + CRYPTO_NONCE_SIZE); if (len != COOKIE_RESPONSE_LENGTH - (1 + CRYPTO_NONCE_SIZE)) { return -1; @@ -349,7 +344,7 @@ static int handle_cookie_request(const Net_Crypto *c, uint8_t *request_plain, ui memcpy(dht_public_key, packet + 1, CRYPTO_PUBLIC_KEY_SIZE); const uint8_t *tmp_shared_key = dht_get_shared_key_sent(c->dht, dht_public_key); memcpy(shared_key, tmp_shared_key, CRYPTO_SHARED_KEY_SIZE); - const int len = decrypt_data_symmetric(shared_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, + const int len = decrypt_data_symmetric(c->mem, shared_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, COOKIE_REQUEST_PLAIN_LENGTH + CRYPTO_MAC_SIZE, request_plain); @@ -446,7 +441,7 @@ static int tcp_oob_handle_cookie_request(const Net_Crypto *c, unsigned int tcp_c * @retval COOKIE_LENGTH on success. */ non_null() -static int handle_cookie_response(uint8_t *cookie, uint64_t *number, +static int handle_cookie_response(const Memory *mem, uint8_t *cookie, uint64_t *number, const uint8_t *packet, uint16_t length, const uint8_t *shared_key) { @@ -455,7 +450,7 @@ static int handle_cookie_response(uint8_t *cookie, uint64_t *number, } uint8_t plain[COOKIE_LENGTH + sizeof(uint64_t)]; - const int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE, + const int len = decrypt_data_symmetric(mem, shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE, length - (1 + CRYPTO_NONCE_SIZE), plain); if (len != sizeof(plain)) { @@ -488,13 +483,13 @@ static int create_crypto_handshake(const Net_Crypto *c, uint8_t *packet, const u memcpy(cookie_plain, peer_real_pk, CRYPTO_PUBLIC_KEY_SIZE); memcpy(cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, peer_dht_pubkey, CRYPTO_PUBLIC_KEY_SIZE); - if (create_cookie(c->rng, c->mono_time, plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE, + if (create_cookie(c->mem, c->rng, c->mono_time, plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE, cookie_plain, c->secret_symmetric_key) != 0) { return -1; } random_nonce(c->rng, packet + 1 + COOKIE_LENGTH); - const int len = encrypt_data(peer_real_pk, c->self_secret_key, packet + 1 + COOKIE_LENGTH, plain, sizeof(plain), + const int len = encrypt_data(c->mem, peer_real_pk, c->self_secret_key, packet + 1 + COOKIE_LENGTH, plain, sizeof(plain), packet + 1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE); if (len != HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE)) { @@ -535,7 +530,7 @@ static bool handle_crypto_handshake(const Net_Crypto *c, uint8_t *nonce, uint8_t uint8_t cookie_plain[COOKIE_DATA_LENGTH]; - if (open_cookie(c->mono_time, cookie_plain, packet + 1, c->secret_symmetric_key) != 0) { + if (open_cookie(c->mem, c->mono_time, cookie_plain, packet + 1, c->secret_symmetric_key) != 0) { return false; } @@ -547,7 +542,7 @@ static bool handle_crypto_handshake(const Net_Crypto *c, uint8_t *nonce, uint8_t crypto_sha512(cookie_hash, packet + 1, COOKIE_LENGTH); uint8_t plain[CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH]; - const int len = decrypt_data(cookie_plain, c->self_secret_key, packet + 1 + COOKIE_LENGTH, + const int len = decrypt_data(c->mem, cookie_plain, c->self_secret_key, packet + 1 + COOKIE_LENGTH, packet + 1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE, HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE), plain); @@ -680,7 +675,7 @@ static IP_Port return_ip_port_connection(const Net_Crypto *c, int crypt_connecti * @retval 0 on success. */ non_null() -static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length) +static int send_packet_to(const Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length) { // TODO(irungentoo): TCP, etc... Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); @@ -691,7 +686,6 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t bool direct_send_attempt = false; - pthread_mutex_lock(conn->mutex); const IP_Port ip_port = return_ip_port_connection(c, crypt_connection_id); // TODO(irungentoo): on bad networks, direct connections might not last indefinitely. @@ -703,11 +697,9 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t if (direct_connected) { if ((uint32_t)sendpacket(dht_get_net(c->dht), &ip_port, data, length) == length) { - pthread_mutex_unlock(conn->mutex); return 0; } - pthread_mutex_unlock(conn->mutex); LOGGER_WARNING(c->log, "sending packet of length %d failed", length); return -1; } @@ -724,19 +716,12 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t } } - pthread_mutex_unlock(conn->mutex); - pthread_mutex_lock(&c->tcp_mutex); const int ret = send_packet_tcp_connection(c->tcp_c, conn->connection_number_tcp, data, length); - pthread_mutex_unlock(&c->tcp_mutex); - - pthread_mutex_lock(conn->mutex); if (ret == 0) { conn->last_tcp_sent = current_time_monotonic(c->mono_time); } - pthread_mutex_unlock(conn->mutex); - if (direct_send_attempt) { return 0; } @@ -998,7 +983,7 @@ static int generate_request_packet(uint8_t *data, uint16_t length, const Packets * @return number of requested packets on success. */ non_null() -static int handle_request_packet(const Memory *mem, Mono_Time *mono_time, Packets_Array *send_array, +static int handle_request_packet(const Memory *mem, const Mono_Time *mono_time, Packets_Array *send_array, const uint8_t *data, uint16_t length, uint64_t *latest_send_time, uint64_t rtt_time) { @@ -1081,7 +1066,7 @@ static int handle_request_packet(const Memory *mem, Mono_Time *mono_time, Packet * @retval 0 on success. */ non_null() -static int send_data_packet(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length) +static int send_data_packet(const Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length) { const uint16_t max_length = MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + CRYPTO_MAC_SIZE); @@ -1097,21 +1082,18 @@ static int send_data_packet(Net_Crypto *c, int crypt_connection_id, const uint8_ return -1; } - pthread_mutex_lock(conn->mutex); const uint16_t packet_size = 1 + sizeof(uint16_t) + length + CRYPTO_MAC_SIZE; VLA(uint8_t, packet, packet_size); packet[0] = NET_PACKET_CRYPTO_DATA; memcpy(packet + 1, conn->sent_nonce + (CRYPTO_NONCE_SIZE - sizeof(uint16_t)), sizeof(uint16_t)); - const int len = encrypt_data_symmetric(conn->shared_key, conn->sent_nonce, data, length, packet + 1 + sizeof(uint16_t)); + const int len = encrypt_data_symmetric(c->mem, conn->shared_key, conn->sent_nonce, data, length, packet + 1 + sizeof(uint16_t)); if (len + 1 + sizeof(uint16_t) != packet_size) { LOGGER_ERROR(c->log, "encryption failed: %d", len); - pthread_mutex_unlock(conn->mutex); return -1; } increment_nonce(conn->sent_nonce); - pthread_mutex_unlock(conn->mutex); return send_packet_to(c, crypt_connection_id, packet, packet_size); } @@ -1122,7 +1104,7 @@ static int send_data_packet(Net_Crypto *c, int crypt_connection_id, const uint8_ * @retval 0 on success. */ non_null() -static int send_data_packet_helper(Net_Crypto *c, int crypt_connection_id, uint32_t buffer_start, uint32_t num, +static int send_data_packet_helper(const Net_Crypto *c, int crypt_connection_id, uint32_t buffer_start, uint32_t num, const uint8_t *data, uint16_t length) { if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) { @@ -1144,7 +1126,7 @@ static int send_data_packet_helper(Net_Crypto *c, int crypt_connection_id, uint3 } non_null() -static int reset_max_speed_reached(Net_Crypto *c, int crypt_connection_id) +static int reset_max_speed_reached(const Net_Crypto *c, int crypt_connection_id) { Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); @@ -1179,7 +1161,7 @@ static int reset_max_speed_reached(Net_Crypto *c, int crypt_connection_id) * @return positive packet number if data was put into the queue. */ non_null() -static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length, +static int64_t send_lossless_packet(const Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length, bool congestion_control) { if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) { @@ -1207,9 +1189,7 @@ static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, cons dt.sent_time = 0; dt.length = length; memcpy(dt.data, data, length); - pthread_mutex_lock(conn->mutex); const int64_t packet_num = add_data_end_of_buffer(c->log, c->mem, &conn->send_array, &dt); - pthread_mutex_unlock(conn->mutex); if (packet_num == -1) { return -1; @@ -1277,7 +1257,7 @@ static int handle_data_packet(const Net_Crypto *c, int crypt_connection_id, uint net_unpack_u16(packet + 1, &num); const uint16_t diff = num - num_cur_nonce; increment_nonce_number(nonce, diff); - const int len = decrypt_data_symmetric(conn->shared_key, nonce, packet + 1 + sizeof(uint16_t), + const int len = decrypt_data_symmetric(c->mem, conn->shared_key, nonce, packet + 1 + sizeof(uint16_t), length - (1 + sizeof(uint16_t)), data); if ((unsigned int)len != length - crypto_packet_overhead) { @@ -1297,7 +1277,7 @@ static int handle_data_packet(const Net_Crypto *c, int crypt_connection_id, uint * @retval 0 on success. */ non_null() -static int send_request_packet(Net_Crypto *c, int crypt_connection_id) +static int send_request_packet(const Net_Crypto *c, int crypt_connection_id) { const Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); @@ -1322,7 +1302,7 @@ static int send_request_packet(Net_Crypto *c, int crypt_connection_id) * @return number of packets sent on success. */ non_null() -static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint32_t max_num) +static int send_requested_packets(const Net_Crypto *c, int crypt_connection_id, uint32_t max_num) { if (max_num == 0) { return -1; @@ -1436,7 +1416,7 @@ static int clear_temp_packet(const Net_Crypto *c, int crypt_connection_id) * @retval 0 on success. */ non_null() -static int send_temp_packet(Net_Crypto *c, int crypt_connection_id) +static int send_temp_packet(const Net_Crypto *c, int crypt_connection_id) { Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); @@ -1464,7 +1444,7 @@ static int send_temp_packet(Net_Crypto *c, int crypt_connection_id) * @retval 0 on success. */ non_null() -static int create_send_handshake(Net_Crypto *c, int crypt_connection_id, const uint8_t *cookie, +static int create_send_handshake(const Net_Crypto *c, int crypt_connection_id, const uint8_t *cookie, const uint8_t *dht_public_key) { const Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); @@ -1494,7 +1474,7 @@ static int create_send_handshake(Net_Crypto *c, int crypt_connection_id, const u * @retval 0 on success. */ non_null() -static int send_kill_packet(Net_Crypto *c, int crypt_connection_id) +static int send_kill_packet(const Net_Crypto *c, int crypt_connection_id) { const Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); @@ -1521,18 +1501,7 @@ static void connection_kill(Net_Crypto *c, int crypt_connection_id, void *userda false, userdata); } - while (true) { /* TODO(irungentoo): is this really the best way to do this? */ - pthread_mutex_lock(&c->connections_mutex); - - if (c->connection_use_counter == 0) { - break; - } - - pthread_mutex_unlock(&c->connections_mutex); - } - crypto_kill(c, crypt_connection_id); - pthread_mutex_unlock(&c->connections_mutex); } /** @brief Handle a received data packet. @@ -1635,9 +1604,7 @@ static int handle_data_packet_core(Net_Crypto *c, int crypt_connection_id, const } while (true) { - pthread_mutex_lock(conn->mutex); const int ret = read_data_beg_buffer(c->mem, &conn->recv_array, &dt); - pthread_mutex_unlock(conn->mutex); if (ret == -1) { break; @@ -1682,7 +1649,7 @@ static int handle_data_packet_core(Net_Crypto *c, int crypt_connection_id, const } non_null() -static int handle_packet_cookie_response(Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length) +static int handle_packet_cookie_response(const Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length) { Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); @@ -1697,7 +1664,7 @@ static int handle_packet_cookie_response(Net_Crypto *c, int crypt_connection_id, uint8_t cookie[COOKIE_LENGTH]; uint64_t number; - if (handle_cookie_response(cookie, &number, packet, length, conn->shared_key) != sizeof(cookie)) { + if (handle_cookie_response(c->mem, cookie, &number, packet, length, conn->shared_key) != sizeof(cookie)) { return -1; } @@ -1714,7 +1681,7 @@ static int handle_packet_cookie_response(Net_Crypto *c, int crypt_connection_id, } non_null(1, 3) nullable(5) -static int handle_packet_crypto_hs(Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length, +static int handle_packet_crypto_hs(const Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length, void *userdata) { Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); @@ -1835,16 +1802,6 @@ static int realloc_cryptoconnection(Net_Crypto *c, uint32_t num) non_null() static int create_crypto_connection(Net_Crypto *c) { - while (true) { /* TODO(irungentoo): is this really the best way to do this? */ - pthread_mutex_lock(&c->connections_mutex); - - if (c->connection_use_counter == 0) { - break; - } - - pthread_mutex_unlock(&c->connections_mutex); - } - int id = -1; for (uint32_t i = 0; i < c->crypto_connections_length; ++i) { @@ -1863,30 +1820,17 @@ static int create_crypto_connection(Net_Crypto *c) } if (id != -1) { - pthread_mutex_t *mutex = (pthread_mutex_t *)mem_alloc(c->mem, sizeof(pthread_mutex_t)); - - if (mutex == nullptr) { - pthread_mutex_unlock(&c->connections_mutex); - return -1; - } - - if (pthread_mutex_init(mutex, nullptr) != 0) { - mem_delete(c->mem, mutex); - pthread_mutex_unlock(&c->connections_mutex); - return -1; - } - // Memsetting float/double to 0 is non-portable, so we explicitly set them to 0 c->crypto_connections[id].packet_recv_rate = 0.0; c->crypto_connections[id].packet_send_rate = 0.0; c->crypto_connections[id].last_packets_left_rem = 0.0; c->crypto_connections[id].packet_send_rate_requested = 0.0; c->crypto_connections[id].last_packets_left_requested_rem = 0.0; - c->crypto_connections[id].mutex = mutex; + + // TODO(Green-Sky): This enum is likely unneeded and the same as FREE. c->crypto_connections[id].status = CRYPTO_CONN_NO_CONNECTION; } - pthread_mutex_unlock(&c->connections_mutex); return id; } @@ -1914,8 +1858,6 @@ static int wipe_crypto_connection(Net_Crypto *c, int crypt_connection_id) uint32_t i; - pthread_mutex_destroy(c->crypto_connections[crypt_connection_id].mutex); - mem_delete(c->mem, c->crypto_connections[crypt_connection_id].mutex); crypto_memzero(&c->crypto_connections[crypt_connection_id], sizeof(Crypto_Connection)); /* check if we can resize the connections array */ @@ -2098,9 +2040,7 @@ int accept_crypto_connection(Net_Crypto *c, const New_Connection *n_c) return -1; } - pthread_mutex_lock(&c->tcp_mutex); const int connection_number_tcp = new_tcp_connection_to(c->tcp_c, n_c->dht_public_key, crypt_connection_id); - pthread_mutex_unlock(&c->tcp_mutex); if (connection_number_tcp == -1) { wipe_crypto_connection(c, crypt_connection_id); @@ -2117,9 +2057,7 @@ int accept_crypto_connection(Net_Crypto *c, const New_Connection *n_c) conn->status = CRYPTO_CONN_NOT_CONFIRMED; if (create_send_handshake(c, crypt_connection_id, n_c->cookie, n_c->dht_public_key) != 0) { - pthread_mutex_lock(&c->tcp_mutex); kill_tcp_connection_to(c->tcp_c, conn->connection_number_tcp); - pthread_mutex_unlock(&c->tcp_mutex); wipe_crypto_connection(c, crypt_connection_id); return -1; } @@ -2155,9 +2093,7 @@ int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key, const u Crypto_Connection *conn = &c->crypto_connections[crypt_connection_id]; - pthread_mutex_lock(&c->tcp_mutex); const int connection_number_tcp = new_tcp_connection_to(c->tcp_c, dht_public_key, crypt_connection_id); - pthread_mutex_unlock(&c->tcp_mutex); if (connection_number_tcp == -1) { wipe_crypto_connection(c, crypt_connection_id); @@ -2181,9 +2117,7 @@ int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key, const u if (create_cookie_request(c, cookie_request, conn->dht_public_key, conn->cookie_request_number, conn->shared_key) != sizeof(cookie_request) || new_temp_packet(c, crypt_connection_id, cookie_request, sizeof(cookie_request)) != 0) { - pthread_mutex_lock(&c->tcp_mutex); kill_tcp_connection_to(c->tcp_c, conn->connection_number_tcp); - pthread_mutex_unlock(&c->tcp_mutex); wipe_crypto_connection(c, crypt_connection_id); return -1; } @@ -2241,11 +2175,7 @@ static int tcp_data_callback(void *object, int crypt_connection_id, const uint8_ return tcp_handle_cookie_request(c, conn->connection_number_tcp, packet, length); } - // This unlocks the mutex that at this point is locked by do_tcp before - // calling do_tcp_connections. - pthread_mutex_unlock(&c->tcp_mutex); const int ret = handle_packet_connection(c, crypt_connection_id, packet, length, false, userdata); - pthread_mutex_lock(&c->tcp_mutex); if (ret != 0) { return -1; @@ -2295,10 +2225,7 @@ int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, const IP_Port *ip return -1; } - pthread_mutex_lock(&c->tcp_mutex); - const int ret = add_tcp_relay_connection(c->tcp_c, conn->connection_number_tcp, ip_port, public_key); - pthread_mutex_unlock(&c->tcp_mutex); - return ret; + return add_tcp_relay_connection(c->tcp_c, conn->connection_number_tcp, ip_port, public_key); } /** @brief Add a tcp relay to the array. @@ -2308,10 +2235,7 @@ int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, const IP_Port *ip */ int add_tcp_relay(Net_Crypto *c, const IP_Port *ip_port, const uint8_t *public_key) { - pthread_mutex_lock(&c->tcp_mutex); - const int ret = add_tcp_relay_global(c->tcp_c, ip_port, public_key); - pthread_mutex_unlock(&c->tcp_mutex); - return ret; + return add_tcp_relay_global(c->tcp_c, ip_port, public_key); } /** @brief Return a random TCP connection number for use in send_tcp_onion_request. @@ -2322,13 +2246,9 @@ int add_tcp_relay(Net_Crypto *c, const IP_Port *ip_port, const uint8_t *public_k * return TCP connection number on success. * return -1 on failure. */ -int get_random_tcp_con_number(Net_Crypto *c) +int get_random_tcp_con_number(const Net_Crypto *c) { - pthread_mutex_lock(&c->tcp_mutex); - const int ret = get_random_tcp_onion_conn_number(c->tcp_c); - pthread_mutex_unlock(&c->tcp_mutex); - - return ret; + return get_random_tcp_onion_conn_number(c->tcp_c); } /** @brief Put IP_Port of a random onion TCP connection in ip_port. @@ -2336,13 +2256,9 @@ int get_random_tcp_con_number(Net_Crypto *c) * return true on success. * return false on failure. */ -bool get_random_tcp_conn_ip_port(Net_Crypto *c, IP_Port *ip_port) +bool get_random_tcp_conn_ip_port(const Net_Crypto *c, IP_Port *ip_port) { - pthread_mutex_lock(&c->tcp_mutex); - const bool ret = tcp_get_random_conn_ip_port(c->tcp_c, ip_port); - pthread_mutex_unlock(&c->tcp_mutex); - - return ret; + return tcp_get_random_conn_ip_port(c->tcp_c, ip_port); } /** @brief Send an onion packet via the TCP relay corresponding to tcp_connections_number. @@ -2352,11 +2268,7 @@ bool get_random_tcp_conn_ip_port(Net_Crypto *c, IP_Port *ip_port) */ int send_tcp_onion_request(Net_Crypto *c, unsigned int tcp_connections_number, const uint8_t *data, uint16_t length) { - pthread_mutex_lock(&c->tcp_mutex); - const int ret = tcp_send_onion_request(c->tcp_c, tcp_connections_number, data, length); - pthread_mutex_unlock(&c->tcp_mutex); - - return ret; + return tcp_send_onion_request(c->tcp_c, tcp_connections_number, data, length); } /** @@ -2371,12 +2283,8 @@ int send_tcp_forward_request(const Logger *logger, Net_Crypto *c, const IP_Port const uint8_t *chain_keys, uint16_t chain_length, const uint8_t *data, uint16_t data_length) { - pthread_mutex_lock(&c->tcp_mutex); - const int ret = tcp_send_forward_request(logger, c->tcp_c, tcp_forwarder, dht_node, - chain_keys, chain_length, data, data_length); - pthread_mutex_unlock(&c->tcp_mutex); - - return ret; + return tcp_send_forward_request(logger, c->tcp_c, tcp_forwarder, dht_node, + chain_keys, chain_length, data, data_length); } /** @brief Copy a maximum of num random TCP relays we are connected to to tcp_relays. @@ -2386,38 +2294,28 @@ int send_tcp_forward_request(const Logger *logger, Net_Crypto *c, const IP_Port * return number of relays copied to tcp_relays on success. * return 0 on failure. */ -unsigned int copy_connected_tcp_relays(Net_Crypto *c, Node_format *tcp_relays, uint16_t num) +unsigned int copy_connected_tcp_relays(const Net_Crypto *c, Node_format *tcp_relays, uint16_t num) { if (num == 0) { return 0; } - pthread_mutex_lock(&c->tcp_mutex); - const unsigned int ret = tcp_copy_connected_relays(c->tcp_c, tcp_relays, num); - pthread_mutex_unlock(&c->tcp_mutex); - - return ret; + return tcp_copy_connected_relays(c->tcp_c, tcp_relays, num); } -uint32_t copy_connected_tcp_relays_index(Net_Crypto *c, Node_format *tcp_relays, uint16_t num, uint32_t idx) +uint32_t copy_connected_tcp_relays_index(const Net_Crypto *c, Node_format *tcp_relays, uint16_t num, uint32_t idx) { if (num == 0) { return 0; } - pthread_mutex_lock(&c->tcp_mutex); - const uint32_t ret = tcp_copy_connected_relays_index(c->tcp_c, tcp_relays, num, idx); - pthread_mutex_unlock(&c->tcp_mutex); - - return ret; + return tcp_copy_connected_relays_index(c->tcp_c, tcp_relays, num, idx); } non_null() static void do_tcp(Net_Crypto *c, void *userdata) { - pthread_mutex_lock(&c->tcp_mutex); do_tcp_connections(c->log, c->tcp_c, userdata); - pthread_mutex_unlock(&c->tcp_mutex); for (uint32_t i = 0; i < c->crypto_connections_length; ++i) { const Crypto_Connection *conn = get_crypto_connection(c, i); @@ -2436,9 +2334,7 @@ static void do_tcp(Net_Crypto *c, void *userdata) continue; } - pthread_mutex_lock(&c->tcp_mutex); set_tcp_connection_to_status(c->tcp_c, conn->connection_number_tcp, !direct_connected); - pthread_mutex_unlock(&c->tcp_mutex); } } @@ -2593,15 +2489,12 @@ static int udp_handle_packet(void *object, const IP_Port *source, const uint8_t return -1; } - pthread_mutex_lock(conn->mutex); - if (net_family_is_ipv4(source->ip.family)) { conn->direct_lastrecv_timev4 = mono_time_get(c->mono_time); } else { conn->direct_lastrecv_timev6 = mono_time_get(c->mono_time); } - pthread_mutex_unlock(conn->mutex); return 0; } @@ -2866,7 +2759,7 @@ static void send_crypto_packets(Net_Crypto *c) * @retval 1 if max speed was reached for this connection (no more data can be physically through the pipe). * @retval 0 if it wasn't reached. */ -bool max_speed_reached(Net_Crypto *c, int crypt_connection_id) +bool max_speed_reached(const Net_Crypto *c, int crypt_connection_id) { return reset_max_speed_reached(c, crypt_connection_id) != 0; } @@ -2901,7 +2794,7 @@ uint32_t crypto_num_free_sendqueue_slots(const Net_Crypto *c, int crypt_connecti * * congestion_control: should congestion control apply to this packet? */ -int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length, +int64_t write_cryptpacket(const Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length, bool congestion_control) { if (length == 0) { @@ -2987,7 +2880,7 @@ int cryptpacket_received(const Net_Crypto *c, int crypt_connection_id, uint32_t * * The first byte of data must be in the PACKET_ID_RANGE_LOSSY. */ -int send_lossy_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length) +int send_lossy_cryptpacket(const Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length) { if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) { return -1; @@ -2997,26 +2890,16 @@ int send_lossy_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t return -1; } - pthread_mutex_lock(&c->connections_mutex); - ++c->connection_use_counter; - pthread_mutex_unlock(&c->connections_mutex); - Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); int ret = -1; if (conn != nullptr) { - pthread_mutex_lock(conn->mutex); const uint32_t buffer_start = conn->recv_array.buffer_start; const uint32_t buffer_end = conn->send_array.buffer_end; - pthread_mutex_unlock(conn->mutex); ret = send_data_packet_helper(c, crypt_connection_id, buffer_start, buffer_end, data, length); } - pthread_mutex_lock(&c->connections_mutex); - --c->connection_use_counter; - pthread_mutex_unlock(&c->connections_mutex); - return ret; } @@ -3036,9 +2919,7 @@ int crypto_kill(Net_Crypto *c, int crypt_connection_id) send_kill_packet(c, crypt_connection_id); } - pthread_mutex_lock(&c->tcp_mutex); kill_tcp_connection_to(c->tcp_c, conn->connection_number_tcp); - pthread_mutex_unlock(&c->tcp_mutex); bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_portv4, crypt_connection_id); bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_portv6, crypt_connection_id); @@ -3107,7 +2988,7 @@ void load_secret_key(Net_Crypto *c, const uint8_t *sk) * Sets all the global connection variables to their default values. */ Net_Crypto *new_net_crypto(const Logger *log, const Memory *mem, const Random *rng, const Network *ns, - Mono_Time *mono_time, DHT *dht, const TCP_Proxy_Info *proxy_info) + Mono_Time *mono_time, DHT *dht, const TCP_Proxy_Info *proxy_info, Net_Profile *tcp_np) { if (dht == nullptr) { return nullptr; @@ -3125,7 +3006,7 @@ Net_Crypto *new_net_crypto(const Logger *log, const Memory *mem, const Random *r temp->mono_time = mono_time; temp->ns = ns; - temp->tcp_c = new_tcp_connections(log, mem, rng, ns, mono_time, dht_get_self_secret_key(dht), proxy_info); + temp->tcp_c = new_tcp_connections(log, mem, rng, ns, mono_time, dht_get_self_secret_key(dht), proxy_info, tcp_np); if (temp->tcp_c == nullptr) { mem_delete(mem, temp); @@ -3135,13 +3016,6 @@ Net_Crypto *new_net_crypto(const Logger *log, const Memory *mem, const Random *r set_packet_tcp_connection_callback(temp->tcp_c, &tcp_data_callback, temp); set_oob_packet_tcp_connection_callback(temp->tcp_c, &tcp_oob_callback, temp); - if (create_recursive_mutex(&temp->tcp_mutex) != 0 || - pthread_mutex_init(&temp->connections_mutex, nullptr) != 0) { - kill_tcp_connections(temp->tcp_c); - mem_delete(mem, temp); - return nullptr; - } - temp->dht = dht; new_keys(temp); @@ -3154,7 +3028,7 @@ Net_Crypto *new_net_crypto(const Logger *log, const Memory *mem, const Random *r networking_registerhandler(dht_get_net(dht), NET_PACKET_CRYPTO_HS, &udp_handle_packet, temp); networking_registerhandler(dht_get_net(dht), NET_PACKET_CRYPTO_DATA, &udp_handle_packet, temp); - bs_list_init(&temp->ip_port_list, sizeof(IP_Port), 8, ipport_cmp_handler); + bs_list_init(&temp->ip_port_list, mem, sizeof(IP_Port), 8, ipport_cmp_handler); return temp; } @@ -3215,9 +3089,6 @@ void kill_net_crypto(Net_Crypto *c) crypto_kill(c, i); } - pthread_mutex_destroy(&c->tcp_mutex); - pthread_mutex_destroy(&c->connections_mutex); - kill_tcp_connections(c->tcp_c); bs_list_free(&c->ip_port_list); networking_registerhandler(dht_get_net(c->dht), NET_PACKET_COOKIE_REQUEST, nullptr, nullptr); diff --git a/protocols/Tox/libtox/src/toxcore/net_crypto.h b/protocols/Tox/libtox/src/toxcore/net_crypto.h index 0d817e4315..894707005b 100644 --- a/protocols/Tox/libtox/src/toxcore/net_crypto.h +++ b/protocols/Tox/libtox/src/toxcore/net_crypto.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ @@ -9,10 +9,7 @@ #ifndef C_TOXCORE_TOXCORE_NET_CRYPTO_H #define C_TOXCORE_TOXCORE_NET_CRYPTO_H -#include <pthread.h> - #include "DHT.h" -#include "LAN_discovery.h" #include "TCP_client.h" #include "TCP_connection.h" #include "attributes.h" @@ -20,8 +17,13 @@ #include "logger.h" #include "mem.h" #include "mono_time.h" +#include "net_profile.h" #include "network.h" +#ifdef __cplusplus +extern "C" { +#endif + /*** Crypto payloads. */ /*** Ranges. */ @@ -40,7 +42,6 @@ /** Packets in this range are reserved for AV use. */ #define PACKET_ID_RANGE_LOSSY_START 192 #define PACKET_ID_RANGE_LOSSY_AV_START 192 -#define PACKET_ID_RANGE_LOSSY_AV_SIZE 8 #define PACKET_ID_RANGE_LOSSY_AV_END 199 /** Packets in this range can be used for anything. */ #define PACKET_ID_RANGE_LOSSY_CUSTOM_START 200 @@ -243,7 +244,7 @@ uint32_t crypto_num_free_sendqueue_slots(const Net_Crypto *c, int crypt_connecti * @retval 0 if it wasn't reached. */ non_null() -bool max_speed_reached(Net_Crypto *c, int crypt_connection_id); +bool max_speed_reached(const Net_Crypto *c, int crypt_connection_id); /** @brief Sends a lossless cryptopacket. * @@ -255,7 +256,7 @@ bool max_speed_reached(Net_Crypto *c, int crypt_connection_id); * congestion_control: should congestion control apply to this packet? */ non_null() -int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, +int64_t write_cryptpacket(const Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length, bool congestion_control); /** @brief Check if packet_number was received by the other side. @@ -283,7 +284,7 @@ int cryptpacket_received(const Net_Crypto *c, int crypt_connection_id, uint32_t * The first byte of data must be in the PACKET_ID_RANGE_LOSSY. */ non_null() -int send_lossy_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length); +int send_lossy_cryptpacket(const Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length); /** @brief Add a tcp relay, associating it to a crypt_connection_id. * @@ -311,7 +312,7 @@ int add_tcp_relay(Net_Crypto *c, const IP_Port *ip_port, const uint8_t *public_k * return -1 on failure. */ non_null() -int get_random_tcp_con_number(Net_Crypto *c); +int get_random_tcp_con_number(const Net_Crypto *c); /** @brief Put IP_Port of a random onion TCP connection in ip_port. * @@ -319,7 +320,7 @@ int get_random_tcp_con_number(Net_Crypto *c); * return false on failure. */ non_null() -bool get_random_tcp_conn_ip_port(Net_Crypto *c, IP_Port *ip_port); +bool get_random_tcp_conn_ip_port(const Net_Crypto *c, IP_Port *ip_port); /** @brief Send an onion packet via the TCP relay corresponding to tcp_connections_number. * @@ -351,7 +352,7 @@ int send_tcp_forward_request(const Logger *logger, Net_Crypto *c, const IP_Port * return 0 on failure. */ non_null() -unsigned int copy_connected_tcp_relays(Net_Crypto *c, Node_format *tcp_relays, uint16_t num); +unsigned int copy_connected_tcp_relays(const Net_Crypto *c, Node_format *tcp_relays, uint16_t num); /** * Copy a maximum of `max_num` TCP relays we are connected to starting at the index in the TCP relay array @@ -360,7 +361,7 @@ unsigned int copy_connected_tcp_relays(Net_Crypto *c, Node_format *tcp_relays, u * Returns the number of relays successfully copied. */ non_null() -uint32_t copy_connected_tcp_relays_index(Net_Crypto *c, Node_format *tcp_relays, uint16_t num, uint32_t idx); +uint32_t copy_connected_tcp_relays_index(const Net_Crypto *c, Node_format *tcp_relays, uint16_t num, uint32_t idx); /** @brief Kill a crypto connection. * @@ -405,7 +406,7 @@ void load_secret_key(Net_Crypto *c, const uint8_t *sk); */ non_null() Net_Crypto *new_net_crypto(const Logger *log, const Memory *mem, const Random *rng, const Network *ns, - Mono_Time *mono_time, DHT *dht, const TCP_Proxy_Info *proxy_info); + Mono_Time *mono_time, DHT *dht, const TCP_Proxy_Info *proxy_info, Net_Profile *tcp_np); /** return the optimal interval in ms for running do_net_crypto. */ non_null() @@ -418,4 +419,8 @@ void do_net_crypto(Net_Crypto *c, void *userdata); nullable(1) void kill_net_crypto(Net_Crypto *c); +#ifdef __cplusplus +} /* extern "C" */ +#endif + #endif /* C_TOXCORE_TOXCORE_NET_CRYPTO_H */ diff --git a/protocols/Tox/libtox/src/toxcore/net_profile.c b/protocols/Tox/libtox/src/toxcore/net_profile.c new file mode 100644 index 0000000000..1d700bdb85 --- /dev/null +++ b/protocols/Tox/libtox/src/toxcore/net_profile.c @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2023-2025 The TokTok team. + */ + +/** + * Functions for the network profile. + */ + +#include "net_profile.h" + +#include <stdint.h> + +#include "attributes.h" +#include "logger.h" +#include "mem.h" + +#include "ccompat.h" + +#define NETPROF_TCP_DATA_PACKET_ID 0x10 + +typedef struct Net_Profile { + uint64_t packets_recv[NET_PROF_MAX_PACKET_IDS]; + uint64_t packets_sent[NET_PROF_MAX_PACKET_IDS]; + + uint64_t total_packets_recv; + uint64_t total_packets_sent; + + uint64_t bytes_recv[NET_PROF_MAX_PACKET_IDS]; + uint64_t bytes_sent[NET_PROF_MAX_PACKET_IDS]; + + uint64_t total_bytes_recv; + uint64_t total_bytes_sent; +} Net_Profile; + +/** Returns the number of sent or received packets for all ID's between `start_id` and `end_id`. */ +nullable(1) +static uint64_t netprof_get_packet_count_id_range(const Net_Profile *profile, uint8_t start_id, uint8_t end_id, + Packet_Direction dir) +{ + if (profile == nullptr) { + return 0; + } + + const uint64_t *arr = dir == PACKET_DIRECTION_SEND ? profile->packets_sent : profile->packets_recv; + uint64_t count = 0; + + for (size_t i = start_id; i <= end_id; ++i) { + count += arr[i]; + } + + return count; +} + +/** Returns the number of sent or received bytes for all ID's between `start_id` and `end_id`. */ +nullable(1) +static uint64_t netprof_get_bytes_id_range(const Net_Profile *profile, uint8_t start_id, uint8_t end_id, + Packet_Direction dir) +{ + if (profile == nullptr) { + return 0; + } + + const uint64_t *arr = dir == PACKET_DIRECTION_SEND ? profile->bytes_sent : profile->bytes_recv; + uint64_t bytes = 0; + + for (size_t i = start_id; i <= end_id; ++i) { + bytes += arr[i]; + } + + return bytes; +} + +void netprof_record_packet(Net_Profile *profile, uint8_t id, size_t length, Packet_Direction dir) +{ + if (profile == nullptr) { + return; + } + + if (dir == PACKET_DIRECTION_SEND) { + ++profile->total_packets_sent; + ++profile->packets_sent[id]; + + profile->total_bytes_sent += length; + profile->bytes_sent[id] += length; + } else { + ++profile->total_packets_recv; + ++profile->packets_recv[id]; + + profile->total_bytes_recv += length; + profile->bytes_recv[id] += length; + } +} + +uint64_t netprof_get_packet_count_id(const Net_Profile *profile, uint8_t id, Packet_Direction dir) +{ + if (profile == nullptr) { + return 0; + } + + // Special case - TCP data packets can have any ID between 0x10 and 0xff + if (id == NETPROF_TCP_DATA_PACKET_ID) { + return netprof_get_packet_count_id_range(profile, id, UINT8_MAX, dir); + } + + return dir == PACKET_DIRECTION_SEND ? profile->packets_sent[id] : profile->packets_recv[id]; +} + +uint64_t netprof_get_packet_count_total(const Net_Profile *profile, Packet_Direction dir) +{ + if (profile == nullptr) { + return 0; + } + + return dir == PACKET_DIRECTION_SEND ? profile->total_packets_sent : profile->total_packets_recv; +} + +uint64_t netprof_get_bytes_id(const Net_Profile *profile, uint8_t id, Packet_Direction dir) +{ + if (profile == nullptr) { + return 0; + } + + // Special case - TCP data packets can have any ID between 0x10 and 0xff + if (id == NETPROF_TCP_DATA_PACKET_ID) { + return netprof_get_bytes_id_range(profile, id, 0xff, dir); + } + + return dir == PACKET_DIRECTION_SEND ? profile->bytes_sent[id] : profile->bytes_recv[id]; +} + +uint64_t netprof_get_bytes_total(const Net_Profile *profile, Packet_Direction dir) +{ + if (profile == nullptr) { + return 0; + } + + return dir == PACKET_DIRECTION_SEND ? profile->total_bytes_sent : profile->total_bytes_recv; +} + +Net_Profile *netprof_new(const Logger *log, const Memory *mem) +{ + Net_Profile *np = (Net_Profile *)mem_alloc(mem, sizeof(Net_Profile)); + + if (np == nullptr) { + LOGGER_ERROR(log, "failed to allocate memory for net profiler"); + return nullptr; + } + + return np; +} + +void netprof_kill(const Memory *mem, Net_Profile *net_profile) +{ + if (net_profile != nullptr) { + mem_delete(mem, net_profile); + } +} diff --git a/protocols/Tox/libtox/src/toxcore/net_profile.h b/protocols/Tox/libtox/src/toxcore/net_profile.h new file mode 100644 index 0000000000..be16f671de --- /dev/null +++ b/protocols/Tox/libtox/src/toxcore/net_profile.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2023-2025 The TokTok team. + */ + +/** + * Functions for the network profile. + */ +#ifndef C_TOXCORE_TOXCORE_NET_PROFILE_H +#define C_TOXCORE_TOXCORE_NET_PROFILE_H + +#include <stddef.h> +#include <stdint.h> + +#include "attributes.h" +#include "logger.h" +#include "mem.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* The max number of packet ID's (must fit inside one byte) */ +#define NET_PROF_MAX_PACKET_IDS 256 + +/* If passed to a netprof function as a nullptr the function will have no effect. */ +typedef struct Net_Profile Net_Profile; + +/** Specifies whether the query is for sent or received packets. */ +typedef enum Packet_Direction { + PACKET_DIRECTION_SEND, + PACKET_DIRECTION_RECV, +} Packet_Direction; + +/** + * Records a sent or received packet of type `id` and size `length` to the given profile. + */ +nullable(1) +void netprof_record_packet(Net_Profile *profile, uint8_t id, size_t length, Packet_Direction dir); + +/** + * Returns the number of sent or received packets of type `id` for the given profile. + */ +nullable(1) +uint64_t netprof_get_packet_count_id(const Net_Profile *profile, uint8_t id, Packet_Direction dir); + +/** + * Returns the total number of sent or received packets for the given profile. + */ +nullable(1) +uint64_t netprof_get_packet_count_total(const Net_Profile *profile, Packet_Direction dir); + +/** + * Returns the number of bytes sent or received of packet type `id` for the given profile. + */ +nullable(1) +uint64_t netprof_get_bytes_id(const Net_Profile *profile, uint8_t id, Packet_Direction dir); + +/** + * Returns the total number of bytes sent or received for the given profile. + */ +nullable(1) +uint64_t netprof_get_bytes_total(const Net_Profile *profile, Packet_Direction dir); + +/** + * Returns a new net_profile object. The caller is responsible for freeing the + * returned memory via `netprof_kill`. + */ +non_null() +Net_Profile *netprof_new(const Logger *log, const Memory *mem); + +/** + * Kills a net_profile object and frees all associated memory. + */ +non_null(1) nullable(2) +void netprof_kill(const Memory *mem, Net_Profile *net_profile); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* C_TOXCORE_TOXCORE_NET_PROFILE_H */ diff --git a/protocols/Tox/libtox/src/toxcore/network.c b/protocols/Tox/libtox/src/toxcore/network.c index 55aa4e2818..bd6babf26e 100644 --- a/protocols/Tox/libtox/src/toxcore/network.c +++ b/protocols/Tox/libtox/src/toxcore/network.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2023 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ @@ -86,6 +86,7 @@ #include "ccompat.h" #include "logger.h" #include "mem.h" +#include "net_profile.h" #include "util.h" // Disable MSG_NOSIGNAL on systems not supporting it, e.g. Windows, FreeBSD @@ -263,9 +264,11 @@ static int make_family(Family tox_family) { switch (tox_family.value) { case TOX_AF_INET: + case TCP_INET: return AF_INET; case TOX_AF_INET6: + case TCP_INET6: return AF_INET6; case TOX_AF_UNSPEC: @@ -514,6 +517,12 @@ static int sys_listen(void *obj, Socket sock, int backlog) } non_null() +static int sys_connect(void *obj, Socket sock, const Network_Addr *addr) +{ + return connect(net_socket_to_native(sock), (const struct sockaddr *)&addr->addr, addr->size); +} + +non_null() static int sys_recvbuf(void *obj, Socket sock) { #ifdef OS_WIN32 @@ -583,7 +592,97 @@ static int sys_getsockopt(void *obj, Socket sock, int level, int optname, void * non_null() static int sys_setsockopt(void *obj, Socket sock, int level, int optname, const void *optval, size_t optlen) { +#ifdef EMSCRIPTEN + return 0; +#else return setsockopt(net_socket_to_native(sock), level, optname, (const char *)optval, optlen); +#endif /* EMSCRIPTEN */ +} + +// sets and fills an array of addrs for address +// returns the number of entries in addrs +non_null() +static int sys_getaddrinfo(void *obj, const Memory *mem, const char *address, int family, int sock_type, Network_Addr **addrs) +{ + assert(addrs != nullptr); + + struct addrinfo hints = {0}; + hints.ai_family = family; + + + // different platforms favour a different field + // hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses. + hints.ai_socktype = sock_type; + // hints.ai_protocol = protocol; + + struct addrinfo *infos = nullptr; + + const int rc = getaddrinfo(address, nullptr, &hints, &infos); + + // Lookup failed. + if (rc != 0) { + // TODO(Green-Sky): log error + return 0; + } + + const int32_t max_count = INT32_MAX / sizeof(Network_Addr); + + // we count number of "valid" results + int result = 0; + for (struct addrinfo *walker = infos; walker != nullptr && result < max_count; walker = walker->ai_next) { + if (walker->ai_family == family || family == AF_UNSPEC) { + ++result; + } + + // do we need to check socktype/protocol? + } + + assert(max_count >= result); + + Network_Addr *tmp_addrs = (Network_Addr *)mem_valloc(mem, result, sizeof(Network_Addr)); + if (tmp_addrs == nullptr) { + freeaddrinfo(infos); + return 0; + } + + // now we fill in + int i = 0; + for (struct addrinfo *walker = infos; walker != nullptr; walker = walker->ai_next) { + if (walker->ai_family == family || family == AF_UNSPEC) { + tmp_addrs[i].size = sizeof(struct sockaddr_storage); + tmp_addrs[i].addr.ss_family = walker->ai_family; + + // according to spec, storage is supposed to be large enough (and source shows they are) + // storage is 128 bytes + assert(walker->ai_addrlen <= tmp_addrs[i].size); + + memcpy(&tmp_addrs[i].addr, walker->ai_addr, walker->ai_addrlen); + tmp_addrs[i].size = walker->ai_addrlen; + + ++i; + } + } + + assert(i == result); + + freeaddrinfo(infos); + + *addrs = tmp_addrs; + + // number of entries in addrs + return result; +} + +non_null() +static int sys_freeaddrinfo(void *obj, const Memory *mem, Network_Addr *addrs) +{ + if (addrs == nullptr) { + return 0; + } + + mem_delete(mem, addrs); + + return 0; } static const Network_Funcs os_network_funcs = { @@ -591,6 +690,7 @@ static const Network_Funcs os_network_funcs = { sys_accept, sys_bind, sys_listen, + sys_connect, sys_recvbuf, sys_recv, sys_recvfrom, @@ -600,8 +700,10 @@ static const Network_Funcs os_network_funcs = { sys_socket_nonblock, sys_getsockopt, sys_setsockopt, + sys_getaddrinfo, + sys_freeaddrinfo, }; -static const Network os_network_obj = {&os_network_funcs}; +static const Network os_network_obj = {&os_network_funcs, nullptr}; const Network *os_network(void) { @@ -674,11 +776,11 @@ static const char *net_packet_type_name(Net_Packet_Type type) case NET_PACKET_PING_RESPONSE: return "PING_RESPONSE"; - case NET_PACKET_GET_NODES: - return "GET_NODES"; + case NET_PACKET_NODES_REQUEST: + return "NODES_REQUEST"; - case NET_PACKET_SEND_NODES_IPV6: - return "SEND_NODES_IPV6"; + case NET_PACKET_NODES_RESPONSE: + return "NODES_RESPONSE"; case NET_PACKET_COOKIE_REQUEST: return "COOKIE_REQUEST"; @@ -787,13 +889,12 @@ static void loglogdata(const Logger *log, const char *message, const uint8_t *bu if (res < 0) { /* Windows doesn't necessarily know `%zu` */ Ip_Ntoa ip_str; const int error = net_error(); - char *strerror = net_new_strerror(error); + Net_Strerror error_str; LOGGER_TRACE(log, "[%02x = %-21s] %s %3u%c %s:%u (%u: %s) | %08x%08x...%02x", buffer[0], net_packet_type_name((Net_Packet_Type)buffer[0]), message, min_u16(buflen, 999), 'E', net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port), error, - strerror, data_0(buflen, buffer), data_1(buflen, buffer), buffer[buflen - 1]); - net_kill_strerror(strerror); + net_strerror(error, &error_str), data_0(buflen, buffer), data_1(buflen, buffer), buffer[buflen - 1]); } else if ((res > 0) && ((size_t)res <= buflen)) { Ip_Ntoa ip_str; LOGGER_TRACE(log, "[%02x = %-21s] %s %3u%c %s:%u (%u: %s) | %08x%08x...%02x", @@ -812,9 +913,14 @@ static void loglogdata(const Logger *log, const char *message, const uint8_t *bu } int net_send(const Network *ns, const Logger *log, - Socket sock, const uint8_t *buf, size_t len, const IP_Port *ip_port) + Socket sock, const uint8_t *buf, size_t len, const IP_Port *ip_port, Net_Profile *net_profile) { const int res = ns->funcs->send(ns->obj, sock, buf, len); + + if (res > 0) { + netprof_record_packet(net_profile, buf[0], res, PACKET_DIRECTION_SEND); + } + loglogdata(log, "T=>", buf, len, ip_port, res); return res; } @@ -882,7 +988,11 @@ bool set_socket_nosigpipe(const Network *ns, Socket sock) bool set_socket_reuseaddr(const Network *ns, Socket sock) { int set = 1; +#if defined(OS_WIN32) + return net_setsockopt(ns, sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, &set, sizeof(set)) == 0; +#else return net_setsockopt(ns, sock, SOL_SOCKET, SO_REUSEADDR, &set, sizeof(set)) == 0; +#endif /* OS_WIN32 */ } bool set_socket_dualstack(const Network *ns, Socket sock) @@ -914,6 +1024,8 @@ struct Networking_Core { uint16_t port; /* Our UDP socket. */ Socket sock; + + Net_Profile *udp_net_profile; }; Family net_family(const Networking_Core *net) @@ -941,7 +1053,7 @@ int send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet packe if (net_family_is_unspec(net->family)) { /* Socket not initialized */ // TODO(iphydf): Make this an error. Currently, the onion client calls - // this via DHT getnodes. + // this via DHT nodes requests. LOGGER_WARNING(net->log, "attempted to send message of length %u on uninitialised socket", packet.length); return -1; } @@ -999,6 +1111,11 @@ int send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet packe loglogdata(net->log, "O=>", packet.data, packet.length, ip_port, res); assert(res <= INT_MAX); + + if (res == packet.length && packet.data != nullptr) { + netprof_record_packet(net->udp_net_profile, packet.data[0], packet.length, PACKET_DIRECTION_SEND); + } + return (int)res; } @@ -1019,7 +1136,7 @@ int sendpacket(const Networking_Core *net, const IP_Port *ip_port, const uint8_t * Packet length is put into length. */ non_null() -static int receivepacket(const Network *ns, const Memory *mem, const Logger *log, Socket sock, IP_Port *ip_port, uint8_t *data, uint32_t *length) +static int receivepacket(const Network *ns, const Logger *log, Socket sock, IP_Port *ip_port, uint8_t *data, uint32_t *length) { memset(ip_port, 0, sizeof(IP_Port)); Network_Addr addr = {{0}}; @@ -1032,9 +1149,8 @@ static int receivepacket(const Network *ns, const Memory *mem, const Logger *log const int error = net_error(); if (!should_ignore_recv_error(error)) { - char *strerror = net_new_strerror(error); - LOGGER_ERROR(log, "unexpected error reading from socket: %u, %s", error, strerror); - net_kill_strerror(strerror); + Net_Strerror error_str; + LOGGER_ERROR(log, "unexpected error reading from socket: %u, %s", error, net_strerror(error, &error_str)); } return -1; /* Nothing received. */ @@ -1098,11 +1214,13 @@ void networking_poll(const Networking_Core *net, void *userdata) uint8_t data[MAX_UDP_PACKET_SIZE] = {0}; uint32_t length; - while (receivepacket(net->ns, net->mem, net->log, net->sock, &ip_port, data, &length) != -1) { + while (receivepacket(net->ns, net->log, net->sock, &ip_port, data, &length) != -1) { if (length < 1) { continue; } + netprof_record_packet(net->udp_net_profile, data[0], length, PACKET_DIRECTION_RECV); + const Packet_Handler *const handler = &net->packethandlers[data[0]]; if (handler->function == nullptr) { @@ -1163,6 +1281,14 @@ Networking_Core *new_networking_ex( return nullptr; } + Net_Profile *np = netprof_new(log, mem); + + if (np == nullptr) { + free(temp); + return nullptr; + } + + temp->udp_net_profile = np; temp->ns = ns; temp->log = log; temp->mem = mem; @@ -1176,9 +1302,9 @@ Networking_Core *new_networking_ex( /* Check for socket error. */ if (!sock_valid(temp->sock)) { const int neterror = net_error(); - char *strerror = net_new_strerror(neterror); - LOGGER_ERROR(log, "failed to get a socket?! %d, %s", neterror, strerror); - net_kill_strerror(strerror); + Net_Strerror error_str; + LOGGER_ERROR(log, "failed to get a socket?! %d, %s", neterror, net_strerror(neterror, &error_str)); + netprof_kill(mem, temp->udp_net_profile); mem_delete(mem, temp); if (error != nullptr) { @@ -1279,15 +1405,13 @@ Networking_Core *new_networking_ex( const int res = net_setsockopt(ns, temp->sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); const int neterror = net_error(); - char *strerror = net_new_strerror(neterror); + Net_Strerror error_str; if (res < 0) { - LOGGER_INFO(log, "Failed to activate local multicast membership in FF02::1. (%d, %s)", neterror, strerror); + LOGGER_INFO(log, "Failed to activate local multicast membership in FF02::1. (%d, %s)", neterror, net_strerror(neterror, &error_str)); } else { - LOGGER_TRACE(log, "Local multicast group joined successfully. (%d, %s)", neterror, strerror); + LOGGER_TRACE(log, "Local multicast group joined successfully. (%d, %s)", neterror, net_strerror(neterror, &error_str)); } - - net_kill_strerror(strerror); #endif /* ESP_PLATFORM */ } @@ -1345,10 +1469,9 @@ Networking_Core *new_networking_ex( Ip_Ntoa ip_str; const int neterror = net_error(); - char *strerror = net_new_strerror(neterror); + Net_Strerror error_str; LOGGER_ERROR(log, "failed to bind socket: %d, %s IP: %s port_from: %u port_to: %u", - neterror, strerror, net_ip_ntoa(ip, &ip_str), port_from, port_to); - net_kill_strerror(strerror); + neterror, net_strerror(neterror, &error_str), net_ip_ntoa(ip, &ip_str), port_from, port_to); kill_networking(temp); if (error != nullptr) { @@ -1386,6 +1509,7 @@ void kill_networking(Networking_Core *net) kill_sock(net->ns, net->sock); } + netprof_kill(net->mem, net->udp_net_profile); mem_delete(net->mem, net); } @@ -1754,14 +1878,14 @@ bool ip_parse_addr(const IP *ip, char *address, size_t length) return false; } - if (net_family_is_ipv4(ip->family)) { + if (net_family_is_ipv4(ip->family) || net_family_is_tcp_ipv4(ip->family)) { struct in_addr addr; assert(make_family(ip->family) == AF_INET); fill_addr4(&ip->ip.v4, &addr); return inet_ntop4(&addr, address, length) != nullptr; } - if (net_family_is_ipv6(ip->family)) { + if (net_family_is_ipv6(ip->family) || net_family_is_tcp_ipv6(ip->family)) { struct in6_addr addr; assert(make_family(ip->family) == AF_INET6); fill_addr6(&ip->ip.v6, &addr); @@ -1815,37 +1939,34 @@ bool addr_parse_ip(const char *address, IP *to) * prefers v6 if `ip.family` was TOX_AF_UNSPEC and both available * Returns in `*extra` an IPv4 address, if family was TOX_AF_UNSPEC and `*to` is TOX_AF_INET6 * - * @return 0 on failure, `TOX_ADDR_RESOLVE_*` on success. + * @return false on failure, true on success. */ -non_null(1, 2, 3) nullable(4) -static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extra) +non_null(1, 2, 3, 4) nullable(5) +static bool addr_resolve(const Network *ns, const Memory *mem, const char *address, IP *to, IP *extra) { #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION if ((true)) { - return 0; + return false; } #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ if (address == nullptr || to == nullptr) { - return 0; + return false; } const Family tox_family = to->family; const int family = make_family(tox_family); - struct addrinfo hints = {0}; - hints.ai_family = family; - hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses. - - struct addrinfo *server = nullptr; + Network_Addr *addrs = nullptr; + const int rc = ns->funcs->getaddrinfo(ns->obj, mem, address, family, 0, &addrs); - const int rc = getaddrinfo(address, nullptr, &hints, &server); - - // Lookup failed. - if (rc != 0) { - return 0; + // Lookup failed / empty. + if (rc <= 0) { + return false; } + assert(addrs != nullptr); + IP ip4; ip_init(&ip4, false); // ipv6enabled = false IP ip6; @@ -1854,16 +1975,16 @@ static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extr int result = 0; bool done = false; - for (struct addrinfo *walker = server; walker != nullptr && !done; walker = walker->ai_next) { - switch (walker->ai_family) { + for (int i = 0; i < rc && !done; ++i) { + switch (addrs[i].addr.ss_family) { case AF_INET: { - if (walker->ai_family == family) { /* AF_INET requested, done */ - const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)walker->ai_addr; + if (addrs[i].addr.ss_family == family) { /* AF_INET requested, done */ + const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)&addrs[i].addr; get_ip4(&to->ip.v4, &addr->sin_addr); result = TOX_ADDR_RESOLVE_INET; done = true; } else if ((result & TOX_ADDR_RESOLVE_INET) == 0) { /* AF_UNSPEC requested, store away */ - const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)walker->ai_addr; + const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)&addrs[i].addr; get_ip4(&ip4.ip.v4, &addr->sin_addr); result |= TOX_ADDR_RESOLVE_INET; } @@ -1872,16 +1993,16 @@ static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extr } case AF_INET6: { - if (walker->ai_family == family) { /* AF_INET6 requested, done */ - if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) { - const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)walker->ai_addr; + if (addrs[i].addr.ss_family == family) { /* AF_INET6 requested, done */ + if (addrs[i].size == sizeof(struct sockaddr_in6)) { + const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)&addrs[i].addr; get_ip6(&to->ip.v6, &addr->sin6_addr); result = TOX_ADDR_RESOLVE_INET6; done = true; } } else if ((result & TOX_ADDR_RESOLVE_INET6) == 0) { /* AF_UNSPEC requested, store away */ - if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) { - const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)walker->ai_addr; + if (addrs[i].size == sizeof(struct sockaddr_in6)) { + const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)&addrs[i].addr; get_ip6(&ip6.ip.v6, &addr->sin6_addr); result |= TOX_ADDR_RESOLVE_INET6; } @@ -1906,37 +2027,48 @@ static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extr } } - freeaddrinfo(server); - return result; + ns->funcs->freeaddrinfo(ns->obj, mem, addrs); + return result != 0; } -bool addr_resolve_or_parse_ip(const Network *ns, const char *address, IP *to, IP *extra) +bool addr_resolve_or_parse_ip(const Network *ns, const Memory *mem, const char *address, IP *to, IP *extra, bool dns_enabled) { - if (addr_resolve(ns, address, to, extra) == 0) { - if (!addr_parse_ip(address, to)) { - return false; - } + if (dns_enabled && addr_resolve(ns, mem, address, to, extra)) { + return true; } - return true; + return addr_parse_ip(address, to); +} + +const char *net_err_connect_to_string(Net_Err_Connect err) +{ + switch (err) { + case NET_ERR_CONNECT_OK: + return "NET_ERR_CONNECT_OK"; + case NET_ERR_CONNECT_INVALID_FAMILY: + return "NET_ERR_CONNECT_INVALID_FAMILY"; + case NET_ERR_CONNECT_FAILED: + return "NET_ERR_CONNECT_FAILED"; + } + + return "<invalid Net_Err_Connect>"; } -bool net_connect(const Memory *mem, const Logger *log, Socket sock, const IP_Port *ip_port) +bool net_connect(const Network *ns, const Memory *mem, const Logger *log, Socket sock, const IP_Port *ip_port, Net_Err_Connect *err) { - struct sockaddr_storage addr = {0}; - size_t addrsize; + Network_Addr addr = {{0}}; if (net_family_is_ipv4(ip_port->ip.family)) { - struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr; + struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr.addr; - addrsize = sizeof(struct sockaddr_in); + addr.size = sizeof(struct sockaddr_in); addr4->sin_family = AF_INET; fill_addr4(&ip_port->ip.ip.v4, &addr4->sin_addr); addr4->sin_port = ip_port->port; } else if (net_family_is_ipv6(ip_port->ip.family)) { - struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr; + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr.addr; - addrsize = sizeof(struct sockaddr_in6); + addr.size = sizeof(struct sockaddr_in6); addr6->sin6_family = AF_INET6; fill_addr6(&ip_port->ip.ip.v6, &addr6->sin6_addr); addr6->sin6_port = ip_port->port; @@ -1944,11 +2076,13 @@ bool net_connect(const Memory *mem, const Logger *log, Socket sock, const IP_Por Ip_Ntoa ip_str; LOGGER_ERROR(log, "cannot connect to %s:%d which is neither IPv4 nor IPv6", net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port)); + *err = NET_ERR_CONNECT_INVALID_FAMILY; return false; } #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION if ((true)) { + *err = NET_ERR_CONNECT_OK; return true; } #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ @@ -1958,23 +2092,24 @@ bool net_connect(const Memory *mem, const Logger *log, Socket sock, const IP_Por net_socket_to_native(sock), net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port)); errno = 0; - if (connect(net_socket_to_native(sock), (struct sockaddr *)&addr, addrsize) == -1) { + if (ns->funcs->connect(ns->obj, sock, &addr) == -1) { const int error = net_error(); // Non-blocking socket: "Operation in progress" means it's connecting. if (!should_ignore_connect_error(error)) { - char *net_strerror = net_new_strerror(error); + Net_Strerror error_str; LOGGER_WARNING(log, "failed to connect to %s:%d: %d (%s)", - net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port), error, net_strerror); - net_kill_strerror(net_strerror); + net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port), error, net_strerror(error, &error_str)); + *err = NET_ERR_CONNECT_FAILED; return false; } } + *err = NET_ERR_CONNECT_OK; return true; } -int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int tox_type) +int32_t net_getipport(const Network *ns, const Memory *mem, const char *node, IP_Port **res, int tox_type, bool dns_enabled) { assert(node != nullptr); @@ -1996,6 +2131,10 @@ int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int to return 1; } + if (!dns_enabled) { + return -1; + } + #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION if ((true)) { IP_Port *ip_port = (IP_Port *)mem_alloc(mem, sizeof(IP_Port)); @@ -2010,25 +2149,29 @@ int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int to } #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ + int type = make_socktype(tox_type); + // ugly + if (tox_type == -1) { + type = 0; + } + // It's not an IP address, so now we try doing a DNS lookup. - struct addrinfo *infos; - const int ret = getaddrinfo(node, nullptr, nullptr, &infos); + Network_Addr *addrs = nullptr; + const int rc = ns->funcs->getaddrinfo(ns->obj, mem, node, AF_UNSPEC, type, &addrs); - if (ret != 0) { + // Lookup failed / empty. + if (rc <= 0) { return -1; } + assert(addrs != nullptr); + // Used to avoid calloc parameter overflow const size_t max_count = min_u64(SIZE_MAX, INT32_MAX) / sizeof(IP_Port); - const int type = make_socktype(tox_type); size_t count = 0; - for (struct addrinfo *cur = infos; count < max_count && cur != nullptr; cur = cur->ai_next) { - if (cur->ai_socktype != 0 && type > 0 && cur->ai_socktype != type) { - continue; - } - - if (cur->ai_family != AF_INET && cur->ai_family != AF_INET6) { + for (int i = 0; i < rc && count < max_count; ++i) { + if (addrs[i].addr.ss_family != AF_INET && addrs[i].addr.ss_family != AF_INET6) { continue; } @@ -2038,40 +2181,36 @@ int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int to assert(count <= max_count); if (count == 0) { - freeaddrinfo(infos); + ns->funcs->freeaddrinfo(ns->obj, mem, addrs); return 0; } IP_Port *ip_port = (IP_Port *)mem_valloc(mem, count, sizeof(IP_Port)); if (ip_port == nullptr) { - freeaddrinfo(infos); + ns->funcs->freeaddrinfo(ns->obj, mem, addrs); *res = nullptr; return -1; } *res = ip_port; - for (struct addrinfo *cur = infos; cur != nullptr; cur = cur->ai_next) { - if (cur->ai_socktype != 0 && type > 0 && cur->ai_socktype != type) { - continue; - } - - if (cur->ai_family == AF_INET) { - const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)cur->ai_addr; + for (int i = 0; i < rc && count < max_count; ++i) { + if (addrs[i].addr.ss_family == AF_INET) { + const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)&addrs[i].addr; ip_port->ip.ip.v4.uint32 = addr->sin_addr.s_addr; - } else if (cur->ai_family == AF_INET6) { - const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(const void *)cur->ai_addr; + } else if (addrs[i].addr.ss_family == AF_INET6) { + const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(const void *)&addrs[i].addr; memcpy(ip_port->ip.ip.v6.uint8, addr->sin6_addr.s6_addr, sizeof(IP6)); } else { continue; } - const Family *const family = make_tox_family(cur->ai_family); + const Family *const family = make_tox_family(addrs[i].addr.ss_family); assert(family != nullptr); if (family == nullptr) { - freeaddrinfo(infos); + ns->funcs->freeaddrinfo(ns->obj, mem, addrs); return -1; } @@ -2080,7 +2219,7 @@ int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int to ++ip_port; } - freeaddrinfo(infos); + ns->funcs->freeaddrinfo(ns->obj, mem, addrs); return count; } @@ -2227,19 +2366,11 @@ int net_error(void) } #ifdef OS_WIN32 -char *net_new_strerror(int error) -{ - char *str = nullptr; - // Windows API is weird. The 5th function arg is of char* type, but we - // have to pass char** so that it could assign new memory block to our - // pointer, so we have to cast our char** to char* for the compilation - // not to fail (otherwise it would fail to find a variant of this function - // accepting char** as the 5th arg) and Windows inside casts it back - // to char** to do the assignment. So no, this cast you see here, although - // it looks weird, is not a mistake. - FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, - error, 0, (char *)&str, 0, nullptr); - return str; +char *net_strerror(int error, Net_Strerror *buf) +{ + FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, + error, 0, buf->data, NET_STRERROR_SIZE, nullptr); + return buf->data; } #else #if defined(_GNU_SOURCE) && defined(__GLIBC__) @@ -2267,32 +2398,24 @@ static const char *net_strerror_r(int error, char *tmp, size_t tmp_size) return tmp; } #endif /* GNU */ -char *net_new_strerror(int error) +char *net_strerror(int error, Net_Strerror *buf) { - char tmp[256]; - errno = 0; - const char *retstr = net_strerror_r(error, tmp, sizeof(tmp)); + const char *retstr = net_strerror_r(error, buf->data, NET_STRERROR_SIZE); const size_t retstr_len = strlen(retstr); + assert(retstr_len < NET_STRERROR_SIZE); + buf->size = (uint16_t)retstr_len; - char *str = (char *)malloc(retstr_len + 1); - - if (str == nullptr) { - return nullptr; - } - - memcpy(str, retstr, retstr_len + 1); - - return str; + return buf->data; } #endif /* OS_WIN32 */ -void net_kill_strerror(char *strerror) +const Net_Profile *net_get_net_profile(const Networking_Core *net) { -#ifdef OS_WIN32 - LocalFree((char *)strerror); -#else - free(strerror); -#endif /* OS_WIN32 */ + if (net == nullptr) { + return nullptr; + } + + return net->udp_net_profile; } diff --git a/protocols/Tox/libtox/src/toxcore/network.h b/protocols/Tox/libtox/src/toxcore/network.h index 06857b8917..a13c98bf6f 100644 --- a/protocols/Tox/libtox/src/toxcore/network.h +++ b/protocols/Tox/libtox/src/toxcore/network.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ @@ -17,6 +17,7 @@ #include "bin_pack.h" #include "logger.h" #include "mem.h" +#include "net_profile.h" #ifdef __cplusplus extern "C" { @@ -39,6 +40,7 @@ typedef int net_close_cb(void *obj, Socket sock); typedef Socket net_accept_cb(void *obj, Socket sock); typedef int net_bind_cb(void *obj, Socket sock, const Network_Addr *addr); typedef int net_listen_cb(void *obj, Socket sock, int backlog); +typedef int net_connect_cb(void *obj, Socket sock, const Network_Addr *addr); typedef int net_recvbuf_cb(void *obj, Socket sock); typedef int net_recv_cb(void *obj, Socket sock, uint8_t *buf, size_t len); typedef int net_recvfrom_cb(void *obj, Socket sock, uint8_t *buf, size_t len, Network_Addr *addr); @@ -48,8 +50,8 @@ typedef Socket net_socket_cb(void *obj, int domain, int type, int proto); typedef int net_socket_nonblock_cb(void *obj, Socket sock, bool nonblock); typedef int net_getsockopt_cb(void *obj, Socket sock, int level, int optname, void *optval, size_t *optlen); typedef int net_setsockopt_cb(void *obj, Socket sock, int level, int optname, const void *optval, size_t optlen); -typedef int net_getaddrinfo_cb(void *obj, int family, Network_Addr **addrs); -typedef int net_freeaddrinfo_cb(void *obj, Network_Addr *addrs); +typedef int net_getaddrinfo_cb(void *obj, const Memory *mem, const char *address, int family, int protocol, Network_Addr **addrs); +typedef int net_freeaddrinfo_cb(void *obj, const Memory *mem, Network_Addr *addrs); /** @brief Functions wrapping POSIX network functions. * @@ -61,6 +63,7 @@ typedef struct Network_Funcs { net_accept_cb *accept; net_bind_cb *bind; net_listen_cb *listen; + net_connect_cb *connect; net_recvbuf_cb *recvbuf; net_recv_cb *recv; net_recvfrom_cb *recvfrom; @@ -110,8 +113,8 @@ Family net_family_tox_tcp_ipv6(void); typedef enum Net_Packet_Type { NET_PACKET_PING_REQUEST = 0x00, /* Ping request packet ID. */ NET_PACKET_PING_RESPONSE = 0x01, /* Ping response packet ID. */ - NET_PACKET_GET_NODES = 0x02, /* Get nodes request packet ID. */ - NET_PACKET_SEND_NODES_IPV6 = 0x04, /* Send nodes response packet ID for other addresses. */ + NET_PACKET_NODES_REQUEST = 0x02, /* Nodes request packet ID. */ + NET_PACKET_NODES_RESPONSE = 0x04, /* Nodes response packet ID. */ NET_PACKET_COOKIE_REQUEST = 0x18, /* Cookie request packet */ NET_PACKET_COOKIE_RESPONSE = 0x19, /* Cookie response packet */ NET_PACKET_CRYPTO_HS = 0x1a, /* Crypto handshake packet */ @@ -233,11 +236,27 @@ Socket net_invalid_socket(void); /** * Calls send(sockfd, buf, len, MSG_NOSIGNAL). - */ -non_null() -int net_send(const Network *ns, const Logger *log, Socket sock, const uint8_t *buf, size_t len, const IP_Port *ip_port); + * + * @param ns System network object. + * @param log Logger object. + * @param sock Socket to send data with. + * @param buf Data to send. + * @param len Length of data. + * @param ip_port IP and port to send data to. + * @param net_profile Network profile to record the packet. + */ +non_null(1, 2, 4, 6) nullable(7) +int net_send(const Network *ns, const Logger *log, Socket sock, const uint8_t *buf, size_t len, const IP_Port *ip_port, + Net_Profile *net_profile); /** * Calls recv(sockfd, buf, len, MSG_NOSIGNAL). + * + * @param ns System network object. + * @param log Logger object. + * @param sock Socket to receive data with. + * @param buf Buffer to store received data. + * @param len Length of buffer. + * @param ip_port IP and port of the sender. */ non_null() int net_recv(const Network *ns, const Logger *log, Socket sock, uint8_t *buf, size_t len, const IP_Port *ip_port); @@ -396,21 +415,23 @@ non_null() void ipport_copy(IP_Port *target, const IP_Port *source); /** - * Resolves string into an IP address + * @brief Resolves string into an IP address. * - * @param address a hostname (or something parseable to an IP address) - * @param to to.family MUST be initialized, either set to a specific IP version + * @param[in,out] ns Network object. + * @param[in] address a hostname (or something parseable to an IP address). + * @param[in,out] to to.family MUST be initialized, either set to a specific IP version * (TOX_AF_INET/TOX_AF_INET6) or to the unspecified TOX_AF_UNSPEC (0), if both - * IP versions are acceptable - * @param extra can be NULL and is only set in special circumstances, see returns + * IP versions are acceptable. + * @param[out] extra can be NULL and is only set in special circumstances, see returns. + * @param[in] dns_enabled if false, DNS resolution is skipped. * - * Returns in `*to` a matching address (IPv6 or IPv4) - * Returns in `*extra`, if not NULL, an IPv4 address, if `to->family` was TOX_AF_UNSPEC + * Returns in `*to` a matching address (IPv6 or IPv4). + * Returns in `*extra`, if not NULL, an IPv4 address, if `to->family` was `TOX_AF_UNSPEC`. * * @return true on success, false on failure */ -non_null(1, 2, 3) nullable(4) -bool addr_resolve_or_parse_ip(const Network *ns, const char *address, IP *to, IP *extra); +non_null(1, 2, 3, 4) nullable(5) +bool addr_resolve_or_parse_ip(const Network *ns, const Memory *mem, const char *address, IP *to, IP *extra, bool dns_enabled); /** @brief Function to receive data, ip and port of sender is put into ip_port. * Packet data is put into data. @@ -495,13 +516,22 @@ void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handl non_null(1) nullable(2) void networking_poll(const Networking_Core *net, void *userdata); +typedef enum Net_Err_Connect { + NET_ERR_CONNECT_OK, + NET_ERR_CONNECT_INVALID_FAMILY, + NET_ERR_CONNECT_FAILED, +} Net_Err_Connect; + +const char *net_err_connect_to_string(Net_Err_Connect err); + /** @brief Connect a socket to the address specified by the ip_port. * - * Return true on success. - * Return false on failure. + * @param[out] err Set to NET_ERR_CONNECT_OK on success, otherwise an error code. + * + * @retval true on success, false on failure. */ non_null() -bool net_connect(const Memory *mem, const Logger *log, Socket sock, const IP_Port *ip_port); +bool net_connect(const Network *ns, const Memory *mem, const Logger *log, Socket sock, const IP_Port *ip_port, Net_Err_Connect *err); /** @brief High-level getaddrinfo implementation. * @@ -510,14 +540,21 @@ bool net_connect(const Memory *mem, const Logger *log, Socket sock, const IP_Por * address that can be specified by calling `net_connect()`, the port is ignored. * * Skip all addresses with socktype != type (use type = -1 to get all addresses) - * To correctly deallocate array memory use `net_freeipport()` + * To correctly deallocate array memory use `net_freeipport()`. + * + * @param ns Network object. + * @param mem Memory allocator. + * @param node The node parameter identifies the host or service on which to connect. + * @param[out] res An array of IP_Port structures will be allocated into this pointer. + * @param tox_type The type of socket to use (stream or datagram), only relevant for DNS lookups. + * @param dns_enabled If false, DNS resolution is skipped, when passed a hostname, this function will return an error. * * @return number of elements in res array. * @retval 0 if res array empty. * @retval -1 on error. */ non_null() -int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int tox_type); +int32_t net_getipport(const Network *ns, const Memory *mem, const char *node, IP_Port **res, int tox_type, bool dns_enabled); /** Deallocates memory allocated by net_getipport */ non_null(1) nullable(2) @@ -560,26 +597,32 @@ bool bind_to_port(const Network *ns, Socket sock, Family family, uint16_t port); * Note that different platforms may return different codes for the same error, * so you likely shouldn't be checking the value returned by this function * unless you know what you are doing, you likely just want to use it in - * combination with `net_new_strerror()` to print the error. + * combination with `net_strerror()` to print the error. * * return platform-dependent network error code, if any. */ int net_error(void); -/** @brief Get a text explanation for the error code from `net_error()`. +#define NET_STRERROR_SIZE 256 + +/** @brief Contains a null terminated formatted error message. * - * return NULL on failure. - * return pointer to a NULL-terminated string describing the error code on - * success. The returned string must be freed using `net_kill_strerror()`. + * This struct should not contain more than at most the 2 fields. */ -char *net_new_strerror(int error); +typedef struct Net_Strerror { + char data[NET_STRERROR_SIZE]; + uint16_t size; +} Net_Strerror; -/** @brief Frees the string returned by `net_new_strerror()`. - * It's valid to pass NULL as the argument, the function does nothing in this - * case. +/** @brief Get a text explanation for the error code from `net_error()`. + * + * @param error The error code to get a string for. + * @param buf The struct to store the error message in (usually on stack). + * + * @return pointer to a NULL-terminated string describing the error code. */ -nullable(1) -void net_kill_strerror(char *strerror); +non_null() +char *net_strerror(int error, Net_Strerror *buf); /** @brief Initialize networking. * Bind to ip and port. @@ -603,6 +646,13 @@ Networking_Core *new_networking_no_udp(const Logger *log, const Memory *mem, con nullable(1) void kill_networking(Networking_Core *net); +/** @brief Returns a pointer to the network net_profile object associated with `net`. + * + * Returns null if `net` is null. + */ +non_null() +const Net_Profile *net_get_net_profile(const Networking_Core *net); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/protocols/Tox/libtox/src/toxcore/onion.c b/protocols/Tox/libtox/src/toxcore/onion.c index 9fab57af90..f948be52cb 100644 --- a/protocols/Tox/libtox/src/toxcore/onion.c +++ b/protocols/Tox/libtox/src/toxcore/onion.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ @@ -180,7 +180,7 @@ int onion_path_to_nodes(Node_format *nodes, unsigned int num_nodes, const Onion_ * return -1 on failure. * return length of created packet on success. */ -int create_onion_packet(const Random *rng, uint8_t *packet, uint16_t max_packet_length, +int create_onion_packet(const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length, const Onion_Path *path, const IP_Port *dest, const uint8_t *data, uint16_t length) { @@ -202,7 +202,7 @@ int create_onion_packet(const Random *rng, uint8_t *packet, uint16_t max_packet_ ipport_pack(step2, &path->ip_port3); memcpy(step2 + SIZE_IPPORT, path->public_key3, CRYPTO_PUBLIC_KEY_SIZE); - int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, step1_size, + int len = encrypt_data_symmetric(mem, path->shared_key3, nonce, step1, step1_size, step2 + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE); if (len != SIZE_IPPORT + length + CRYPTO_MAC_SIZE) { @@ -213,7 +213,7 @@ int create_onion_packet(const Random *rng, uint8_t *packet, uint16_t max_packet_ VLA(uint8_t, step3, step3_size); ipport_pack(step3, &path->ip_port2); memcpy(step3 + SIZE_IPPORT, path->public_key2, CRYPTO_PUBLIC_KEY_SIZE); - len = encrypt_data_symmetric(path->shared_key2, nonce, step2, step2_size, + len = encrypt_data_symmetric(mem, path->shared_key2, nonce, step2, step2_size, step3 + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE); if (len != SIZE_IPPORT + SEND_BASE + length + CRYPTO_MAC_SIZE) { @@ -224,7 +224,7 @@ int create_onion_packet(const Random *rng, uint8_t *packet, uint16_t max_packet_ memcpy(packet + 1, nonce, CRYPTO_NONCE_SIZE); memcpy(packet + 1 + CRYPTO_NONCE_SIZE, path->public_key1, CRYPTO_PUBLIC_KEY_SIZE); - len = encrypt_data_symmetric(path->shared_key1, nonce, step3, step3_size, + len = encrypt_data_symmetric(mem, path->shared_key1, nonce, step3, step3_size, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE); if (len != SIZE_IPPORT + SEND_BASE * 2 + length + CRYPTO_MAC_SIZE) { @@ -243,7 +243,7 @@ int create_onion_packet(const Random *rng, uint8_t *packet, uint16_t max_packet_ * return -1 on failure. * return length of created packet on success. */ -int create_onion_packet_tcp(const Random *rng, uint8_t *packet, uint16_t max_packet_length, +int create_onion_packet_tcp(const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length, const Onion_Path *path, const IP_Port *dest, const uint8_t *data, uint16_t length) { @@ -265,7 +265,7 @@ int create_onion_packet_tcp(const Random *rng, uint8_t *packet, uint16_t max_pac ipport_pack(step2, &path->ip_port3); memcpy(step2 + SIZE_IPPORT, path->public_key3, CRYPTO_PUBLIC_KEY_SIZE); - int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, step1_size, + int len = encrypt_data_symmetric(mem, path->shared_key3, nonce, step1, step1_size, step2 + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE); if (len != SIZE_IPPORT + length + CRYPTO_MAC_SIZE) { @@ -274,7 +274,7 @@ int create_onion_packet_tcp(const Random *rng, uint8_t *packet, uint16_t max_pac ipport_pack(packet + CRYPTO_NONCE_SIZE, &path->ip_port2); memcpy(packet + CRYPTO_NONCE_SIZE + SIZE_IPPORT, path->public_key2, CRYPTO_PUBLIC_KEY_SIZE); - len = encrypt_data_symmetric(path->shared_key2, nonce, step2, step2_size, + len = encrypt_data_symmetric(mem, path->shared_key2, nonce, step2, step2_size, packet + CRYPTO_NONCE_SIZE + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE); if (len != SIZE_IPPORT + SEND_BASE + length + CRYPTO_MAC_SIZE) { @@ -355,7 +355,7 @@ static int handle_send_initial(void *object, const IP_Port *source, const uint8_ } const int len = decrypt_data_symmetric( - shared_key, &packet[nonce_start], &packet[ciphertext_start], ciphertext_length, plain); + onion->mem, shared_key, &packet[nonce_start], &packet[ciphertext_start], ciphertext_length, plain); if (len != plaintext_length) { LOGGER_TRACE(onion->log, "decrypt failed: %d != %d", len, plaintext_length); @@ -393,7 +393,7 @@ int onion_send_1(const Onion *onion, const uint8_t *plain, uint16_t len, const I uint16_t data_len = 1 + CRYPTO_NONCE_SIZE + (len - SIZE_IPPORT); uint8_t *ret_part = data + data_len; random_nonce(onion->rng, ret_part); - len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ip_port, SIZE_IPPORT, + len = encrypt_data_symmetric(onion->mem, onion->secret_symmetric_key, ret_part, ip_port, SIZE_IPPORT, ret_part + CRYPTO_NONCE_SIZE); if (len != SIZE_IPPORT + CRYPTO_MAC_SIZE) { @@ -436,7 +436,7 @@ static int handle_send_1(void *object, const IP_Port *source, const uint8_t *pac return 1; } - int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, + int len = decrypt_data_symmetric(onion->mem, shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_1), plain); if (len != length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_1 + CRYPTO_MAC_SIZE)) { @@ -459,7 +459,7 @@ static int handle_send_1(void *object, const IP_Port *source, const uint8_t *pac uint8_t ret_data[RETURN_1 + SIZE_IPPORT]; ipport_pack(ret_data, source); memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_1), RETURN_1); - len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data), + len = encrypt_data_symmetric(onion->mem, onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data), ret_part + CRYPTO_NONCE_SIZE); if (len != RETURN_2 - CRYPTO_NONCE_SIZE) { @@ -502,7 +502,7 @@ static int handle_send_2(void *object, const IP_Port *source, const uint8_t *pac return 1; } - int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, + int len = decrypt_data_symmetric(onion->mem, shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_2), plain); if (len != length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_2 + CRYPTO_MAC_SIZE)) { @@ -532,7 +532,7 @@ static int handle_send_2(void *object, const IP_Port *source, const uint8_t *pac uint8_t ret_data[RETURN_2 + SIZE_IPPORT]; ipport_pack(ret_data, source); memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_2), RETURN_2); - len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data), + len = encrypt_data_symmetric(onion->mem, onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data), ret_part + CRYPTO_NONCE_SIZE); if (len != RETURN_3 - CRYPTO_NONCE_SIZE) { @@ -574,7 +574,7 @@ static int handle_recv_3(void *object, const IP_Port *source, const uint8_t *pac change_symmetric_key(onion); uint8_t plain[SIZE_IPPORT + RETURN_2]; - const int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE, + const int len = decrypt_data_symmetric(onion->mem, onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE, SIZE_IPPORT + RETURN_2 + CRYPTO_MAC_SIZE, plain); if ((uint32_t)len != sizeof(plain)) { @@ -627,7 +627,7 @@ static int handle_recv_2(void *object, const IP_Port *source, const uint8_t *pac change_symmetric_key(onion); uint8_t plain[SIZE_IPPORT + RETURN_1]; - const int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE, + const int len = decrypt_data_symmetric(onion->mem, onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE, SIZE_IPPORT + RETURN_1 + CRYPTO_MAC_SIZE, plain); if ((uint32_t)len != sizeof(plain)) { @@ -679,7 +679,7 @@ static int handle_recv_1(void *object, const IP_Port *source, const uint8_t *pac change_symmetric_key(onion); uint8_t plain[SIZE_IPPORT]; - const int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE, + const int len = decrypt_data_symmetric(onion->mem, onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE, SIZE_IPPORT + CRYPTO_MAC_SIZE, plain); if ((uint32_t)len != SIZE_IPPORT) { diff --git a/protocols/Tox/libtox/src/toxcore/onion.h b/protocols/Tox/libtox/src/toxcore/onion.h index a5d3554e7b..bbc3f22435 100644 --- a/protocols/Tox/libtox/src/toxcore/onion.h +++ b/protocols/Tox/libtox/src/toxcore/onion.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ @@ -105,7 +105,7 @@ int onion_path_to_nodes(Node_format *nodes, unsigned int num_nodes, const Onion_ * return length of created packet on success. */ non_null() -int create_onion_packet(const Random *rng, uint8_t *packet, uint16_t max_packet_length, +int create_onion_packet(const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length, const Onion_Path *path, const IP_Port *dest, const uint8_t *data, uint16_t length); @@ -119,7 +119,7 @@ int create_onion_packet(const Random *rng, uint8_t *packet, uint16_t max_packet_ * return length of created packet on success. */ non_null() -int create_onion_packet_tcp(const Random *rng, uint8_t *packet, uint16_t max_packet_length, +int create_onion_packet_tcp(const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length, const Onion_Path *path, const IP_Port *dest, const uint8_t *data, uint16_t length); diff --git a/protocols/Tox/libtox/src/toxcore/onion_announce.c b/protocols/Tox/libtox/src/toxcore/onion_announce.c index 593d81aa2c..50e2e00aef 100644 --- a/protocols/Tox/libtox/src/toxcore/onion_announce.c +++ b/protocols/Tox/libtox/src/toxcore/onion_announce.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ @@ -9,7 +9,6 @@ #include "onion_announce.h" #include <assert.h> -#include <stdlib.h> #include <string.h> #include "DHT.h" @@ -23,7 +22,9 @@ #include "network.h" #include "onion.h" #include "shared_key_cache.h" +#include "sort.h" #include "timed_auth.h" +#include "util.h" #define PING_ID_TIMEOUT ONION_ANNOUNCE_TIMEOUT @@ -103,7 +104,7 @@ void onion_announce_entry_set_time(Onion_Announce *onion_a, uint32_t entry, uint * return -1 on failure. * return packet length on success. */ -int create_announce_request(const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id, +int create_announce_request(const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id, const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id, const uint8_t *data_public_key, uint64_t sendback_data) { @@ -122,7 +123,7 @@ int create_announce_request(const Random *rng, uint8_t *packet, uint16_t max_pac packet[0] = NET_PACKET_ANNOUNCE_REQUEST_OLD; random_nonce(rng, packet + 1); - const int len = encrypt_data(dest_client_id, secret_key, packet + 1, plain, sizeof(plain), + const int len = encrypt_data(mem, dest_client_id, secret_key, packet + 1, plain, sizeof(plain), packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE); if ((uint32_t)len + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE != ONION_ANNOUNCE_REQUEST_MIN_SIZE) { @@ -146,7 +147,7 @@ int create_announce_request(const Random *rng, uint8_t *packet, uint16_t max_pac * return -1 on failure. * return 0 on success. */ -int create_data_request(const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *public_key, +int create_data_request(const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *public_key, const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length) { if (DATA_REQUEST_MIN_SIZE + length > max_packet_length) { @@ -167,7 +168,7 @@ int create_data_request(const Random *rng, uint8_t *packet, uint16_t max_packet_ memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, random_public_key, CRYPTO_PUBLIC_KEY_SIZE); - const int len = encrypt_data(encrypt_public_key, random_secret_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, data, length, + const int len = encrypt_data(mem, encrypt_public_key, random_secret_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, data, length, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE); if (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + len != DATA_REQUEST_MIN_SIZE + @@ -193,14 +194,14 @@ int create_data_request(const Random *rng, uint8_t *packet, uint16_t max_packet_ * return 0 on success. */ int send_announce_request( - const Logger *log, const Networking_Core *net, const Random *rng, + const Logger *log, const Memory *mem, const Networking_Core *net, const Random *rng, const Onion_Path *path, const Node_format *dest, const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id, const uint8_t *data_public_key, uint64_t sendback_data) { uint8_t request[ONION_ANNOUNCE_REQUEST_MIN_SIZE]; - int len = create_announce_request(rng, request, sizeof(request), dest->public_key, public_key, secret_key, ping_id, + int len = create_announce_request(mem, rng, request, sizeof(request), dest->public_key, public_key, secret_key, ping_id, client_id, data_public_key, sendback_data); if (len != sizeof(request)) { @@ -208,7 +209,7 @@ int send_announce_request( } uint8_t packet[ONION_MAX_PACKET_SIZE]; - len = create_onion_packet(rng, packet, sizeof(packet), path, &dest->ip_port, request, sizeof(request)); + len = create_onion_packet(mem, rng, packet, sizeof(packet), path, &dest->ip_port, request, sizeof(request)); if (len == -1) { return -1; @@ -238,19 +239,19 @@ int send_announce_request( * return 0 on success. */ int send_data_request( - const Logger *log, const Networking_Core *net, const Random *rng, const Onion_Path *path, const IP_Port *dest, + const Logger *log, const Memory *mem, const Networking_Core *net, const Random *rng, const Onion_Path *path, const IP_Port *dest, const uint8_t *public_key, const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length) { uint8_t request[ONION_MAX_DATA_SIZE]; - int len = create_data_request(rng, request, sizeof(request), public_key, encrypt_public_key, nonce, data, length); + int len = create_data_request(mem, rng, request, sizeof(request), public_key, encrypt_public_key, nonce, data, length); if (len == -1) { return -1; } uint8_t packet[ONION_MAX_PACKET_SIZE]; - len = create_onion_packet(rng, packet, sizeof(packet), path, dest, request, len); + len = create_onion_packet(mem, rng, packet, sizeof(packet), path, dest, request, len); if (len == -1) { return -1; @@ -281,23 +282,17 @@ static int in_entries(const Onion_Announce *onion_a, const uint8_t *public_key) return -1; } -typedef struct Cmp_Data { +typedef struct Onion_Announce_Entry_Cmp { + const Memory *mem; const Mono_Time *mono_time; - const uint8_t *base_public_key; - Onion_Announce_Entry entry; -} Cmp_Data; + const uint8_t *comp_public_key; +} Onion_Announce_Entry_Cmp; non_null() -static int cmp_entry(const void *a, const void *b) +static int onion_announce_entry_cmp(const Onion_Announce_Entry_Cmp *cmp, const Onion_Announce_Entry *entry1, const Onion_Announce_Entry *entry2) { - const Cmp_Data *cmp1 = (const Cmp_Data *)a; - const Cmp_Data *cmp2 = (const Cmp_Data *)b; - const Onion_Announce_Entry entry1 = cmp1->entry; - const Onion_Announce_Entry entry2 = cmp2->entry; - const uint8_t *cmp_public_key = cmp1->base_public_key; - - const bool t1 = mono_time_is_timeout(cmp1->mono_time, entry1.announce_time, ONION_ANNOUNCE_TIMEOUT); - const bool t2 = mono_time_is_timeout(cmp1->mono_time, entry2.announce_time, ONION_ANNOUNCE_TIMEOUT); + const bool t1 = mono_time_is_timeout(cmp->mono_time, entry1->announce_time, ONION_ANNOUNCE_TIMEOUT); + const bool t2 = mono_time_is_timeout(cmp->mono_time, entry2->announce_time, ONION_ANNOUNCE_TIMEOUT); if (t1 && t2) { return 0; @@ -311,7 +306,7 @@ static int cmp_entry(const void *a, const void *b) return 1; } - const int closest = id_closest(cmp_public_key, entry1.public_key, entry2.public_key); + const int closest = id_closest(cmp->comp_public_key, entry1->public_key, entry2->public_key); if (closest == 1) { return 1; @@ -325,31 +320,80 @@ static int cmp_entry(const void *a, const void *b) } non_null() -static void sort_onion_announce_list(const Memory *mem, const Mono_Time *mono_time, - Onion_Announce_Entry *list, unsigned int length, - const uint8_t *comp_public_key) +static bool onion_announce_entry_less_handler(const void *object, const void *a, const void *b) { - // Pass comp_public_key to qsort with each Client_data entry, so the - // comparison function can use it as the base of comparison. - Cmp_Data *cmp_list = (Cmp_Data *)mem_valloc(mem, length, sizeof(Cmp_Data)); + const Onion_Announce_Entry_Cmp *cmp = (const Onion_Announce_Entry_Cmp *)object; + const Onion_Announce_Entry *entry1 = (const Onion_Announce_Entry *)a; + const Onion_Announce_Entry *entry2 = (const Onion_Announce_Entry *)b; - if (cmp_list == nullptr) { - return; - } + return onion_announce_entry_cmp(cmp, entry1, entry2) < 0; +} - for (uint32_t i = 0; i < length; ++i) { - cmp_list[i].mono_time = mono_time; - cmp_list[i].base_public_key = comp_public_key; - cmp_list[i].entry = list[i]; - } +non_null() +static const void *onion_announce_entry_get_handler(const void *arr, uint32_t index) +{ + const Onion_Announce_Entry *entries = (const Onion_Announce_Entry *)arr; + return &entries[index]; +} - qsort(cmp_list, length, sizeof(Cmp_Data), cmp_entry); +non_null() +static void onion_announce_entry_set_handler(void *arr, uint32_t index, const void *val) +{ + Onion_Announce_Entry *entries = (Onion_Announce_Entry *)arr; + const Onion_Announce_Entry *entry = (const Onion_Announce_Entry *)val; + entries[index] = *entry; +} - for (uint32_t i = 0; i < length; ++i) { - list[i] = cmp_list[i].entry; +non_null() +static void *onion_announce_entry_subarr_handler(void *arr, uint32_t index, uint32_t size) +{ + Onion_Announce_Entry *entries = (Onion_Announce_Entry *)arr; + return &entries[index]; +} + +non_null() +static void *onion_announce_entry_alloc_handler(const void *object, uint32_t size) +{ + const Onion_Announce_Entry_Cmp *cmp = (const Onion_Announce_Entry_Cmp *)object; + Onion_Announce_Entry *tmp = (Onion_Announce_Entry *)mem_valloc(cmp->mem, size, sizeof(Onion_Announce_Entry)); + + if (tmp == nullptr) { + return nullptr; } - mem_delete(mem, cmp_list); + return tmp; +} + +non_null() +static void onion_announce_entry_delete_handler(const void *object, void *arr, uint32_t size) +{ + const Onion_Announce_Entry_Cmp *cmp = (const Onion_Announce_Entry_Cmp *)object; + mem_delete(cmp->mem, arr); +} + +static const Sort_Funcs onion_announce_entry_cmp_funcs = { + onion_announce_entry_less_handler, + onion_announce_entry_get_handler, + onion_announce_entry_set_handler, + onion_announce_entry_subarr_handler, + onion_announce_entry_alloc_handler, + onion_announce_entry_delete_handler, +}; + +non_null() +static void sort_onion_announce_list(const Memory *mem, const Mono_Time *mono_time, + Onion_Announce_Entry *list, unsigned int length, + const uint8_t *comp_public_key) +{ + // Pass comp_public_key to sort with each Onion_Announce_Entry entry, so the + // comparison function can use it as the base of comparison. + const Onion_Announce_Entry_Cmp cmp = { + mem, + mono_time, + comp_public_key, + }; + + merge_sort(list, length, &cmp, &onion_announce_entry_cmp_funcs); } /** @brief add entry to entries list @@ -455,7 +499,7 @@ static int handle_announce_request_common( return 1; } - const int decrypted_len = decrypt_data_symmetric(shared_key, packet + 1, + const int decrypted_len = decrypt_data_symmetric(onion_a->mem, shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, plain_size + CRYPTO_MAC_SIZE, plain); if ((uint32_t)decrypted_len != plain_size) { @@ -463,11 +507,17 @@ static int handle_announce_request_common( return 1; } - const uint16_t ping_id_data_len = CRYPTO_PUBLIC_KEY_SIZE + sizeof(*source); - uint8_t ping_id_data[CRYPTO_PUBLIC_KEY_SIZE + sizeof(*source)]; + const uint16_t ping_id_data_len = CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT; + uint8_t ping_id_data[CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT]; memcpy(ping_id_data, packet_public_key, CRYPTO_PUBLIC_KEY_SIZE); - memcpy(ping_id_data + CRYPTO_PUBLIC_KEY_SIZE, source, sizeof(*source)); - + const int packed_len = pack_ip_port(onion_a->log, &ping_id_data[CRYPTO_PUBLIC_KEY_SIZE], SIZE_IPPORT, source); + if (packed_len < 0) { + LOGGER_ERROR(onion_a->log, "failed to pack IP/Port"); + mem_delete(onion_a->mem, plain); + return 1; + } + assert(packed_len <= SIZE_IPPORT); + memzero(&ping_id_data[CRYPTO_PUBLIC_KEY_SIZE + packed_len], SIZE_IPPORT - packed_len); const uint8_t *data_public_key = plain + ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE; int index; @@ -510,7 +560,7 @@ static int handle_announce_request_common( int nodes_length = 0; if (num_nodes != 0) { - nodes_length = pack_nodes(onion_a->log, response + nodes_offset, sizeof(nodes_list), nodes_list, + nodes_length = pack_nodes(onion_a->log, &response[nodes_offset], num_nodes * PACKED_NODE_SIZE_IP6, nodes_list, (uint16_t)num_nodes); if (nodes_length <= 0) { @@ -529,7 +579,7 @@ static int handle_announce_request_common( const int extra_size = pack_extra_data_callback == nullptr ? 0 : pack_extra_data_callback(onion_a->extra_data_object, - onion_a->log, onion_a->mono_time, num_nodes, + onion_a->log, onion_a->mem, onion_a->mono_time, num_nodes, plain + ONION_MINIMAL_SIZE, length - ANNOUNCE_REQUEST_MIN_SIZE_RECV, response, response_size, offset); @@ -542,7 +592,7 @@ static int handle_announce_request_common( offset += extra_size; uint8_t data[ONION_ANNOUNCE_RESPONSE_MAX_SIZE]; - const int len = encrypt_data_symmetric(shared_key, nonce, response, offset, + const int len = encrypt_data_symmetric(onion_a->mem, shared_key, nonce, response, offset, data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE); if (len != offset + CRYPTO_MAC_SIZE) { diff --git a/protocols/Tox/libtox/src/toxcore/onion_announce.h b/protocols/Tox/libtox/src/toxcore/onion_announce.h index 1158093170..d8834395c0 100644 --- a/protocols/Tox/libtox/src/toxcore/onion_announce.h +++ b/protocols/Tox/libtox/src/toxcore/onion_announce.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ @@ -65,7 +65,7 @@ void onion_announce_entry_set_time(Onion_Announce *onion_a, uint32_t entry, uint * return packet length on success. */ non_null() -int create_announce_request(const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id, +int create_announce_request(const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id, const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id, const uint8_t *data_public_key, uint64_t sendback_data); @@ -82,7 +82,7 @@ int create_announce_request(const Random *rng, uint8_t *packet, uint16_t max_pac * return 0 on success. */ non_null() -int create_data_request(const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *public_key, +int create_data_request(const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *public_key, const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length); /** @brief Create and send an onion announce request packet. @@ -101,7 +101,7 @@ int create_data_request(const Random *rng, uint8_t *packet, uint16_t max_packet_ */ non_null() int send_announce_request( - const Logger *log, const Networking_Core *net, const Random *rng, + const Logger *log, const Memory *mem, const Networking_Core *net, const Random *rng, const Onion_Path *path, const Node_format *dest, const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id, @@ -125,11 +125,11 @@ int send_announce_request( */ non_null() int send_data_request( - const Logger *log, const Networking_Core *net, const Random *rng, const Onion_Path *path, const IP_Port *dest, + const Logger *log, const Memory *mem, const Networking_Core *net, const Random *rng, const Onion_Path *path, const IP_Port *dest, const uint8_t *public_key, const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length); -typedef int pack_extra_data_cb(void *object, const Logger *logger, const Mono_Time *mono_time, +typedef int pack_extra_data_cb(void *object, const Logger *logger, const Memory *mem, const Mono_Time *mono_time, uint8_t num_nodes, uint8_t *plain, uint16_t plain_size, uint8_t *response, uint16_t response_size, uint16_t offset); diff --git a/protocols/Tox/libtox/src/toxcore/onion_client.c b/protocols/Tox/libtox/src/toxcore/onion_client.c index 9b0ac96102..e802d70298 100644 --- a/protocols/Tox/libtox/src/toxcore/onion_client.c +++ b/protocols/Tox/libtox/src/toxcore/onion_client.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ @@ -10,7 +10,6 @@ #include "onion_client.h" #include <assert.h> -#include <stdlib.h> #include <string.h> #include "DHT.h" @@ -29,6 +28,7 @@ #include "onion.h" #include "onion_announce.h" #include "ping_array.h" +#include "sort.h" #include "timed_auth.h" #include "util.h" @@ -470,6 +470,7 @@ static int random_path(const Onion_Client *onion_c, Onion_Client_Paths *onion_pa onion_paths->paths[pathnum].path_num = path_num; } else { + assert(0 <= n && n < NUMBER_ONION_PATHS); pathnum = n; } } @@ -528,7 +529,7 @@ static int send_onion_packet_tcp_udp(const Onion_Client *onion_c, const Onion_Pa { if (net_family_is_ipv4(path->ip_port1.ip.family) || net_family_is_ipv6(path->ip_port1.ip.family)) { uint8_t packet[ONION_MAX_PACKET_SIZE]; - const int len = create_onion_packet(onion_c->rng, packet, sizeof(packet), path, dest, data, length); + const int len = create_onion_packet(onion_c->mem, onion_c->rng, packet, sizeof(packet), path, dest, data, length); if (len == -1) { return -1; @@ -545,7 +546,7 @@ static int send_onion_packet_tcp_udp(const Onion_Client *onion_c, const Onion_Pa if (ip_port_to_tcp_connections_number(&path->ip_port1, &tcp_connections_number)) { uint8_t packet[ONION_MAX_PACKET_SIZE]; - const int len = create_onion_packet_tcp(onion_c->rng, packet, sizeof(packet), path, dest, data, length); + const int len = create_onion_packet_tcp(onion_c->mem, onion_c->rng, packet, sizeof(packet), path, dest, data, length); if (len == -1) { return -1; @@ -576,11 +577,17 @@ non_null() static int new_sendback(Onion_Client *onion_c, uint32_t num, const uint8_t *public_key, const IP_Port *ip_port, uint32_t path_num, uint64_t *sendback) { - uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port) + sizeof(uint32_t)]; + uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT + sizeof(uint32_t)]; memcpy(data, &num, sizeof(uint32_t)); - 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)); + memcpy(&data[sizeof(uint32_t)], public_key, CRYPTO_PUBLIC_KEY_SIZE); + const int packed_len = pack_ip_port(onion_c->logger, &data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE], SIZE_IPPORT, ip_port); + if (packed_len < 0) { + LOGGER_ERROR(onion_c->logger, "failed to pack IP/port"); + return -1; + } + assert(packed_len <= SIZE_IPPORT); + memzero(&data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + packed_len], SIZE_IPPORT - packed_len); + memcpy(&data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT], &path_num, sizeof(uint32_t)); *sendback = ping_array_add(onion_c->announce_ping_array, onion_c->mono_time, onion_c->rng, data, sizeof(data)); if (*sendback == 0) { @@ -607,15 +614,15 @@ static uint32_t check_sendback(Onion_Client *onion_c, const uint8_t *sendback, u { uint64_t sback; memcpy(&sback, sendback, sizeof(uint64_t)); - uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port) + sizeof(uint32_t)]; + uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT + sizeof(uint32_t)]; if (ping_array_check(onion_c->announce_ping_array, onion_c->mono_time, data, sizeof(data), sback) != sizeof(data)) { return -1; } memcpy(ret_pubkey, data + sizeof(uint32_t), CRYPTO_PUBLIC_KEY_SIZE); - memcpy(ret_ip_port, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, sizeof(IP_Port)); - memcpy(path_num, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port), sizeof(uint32_t)); + unpack_ip_port(ret_ip_port, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, SIZE_IPPORT, false); + memcpy(path_num, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT, sizeof(uint32_t)); uint32_t num; memcpy(&num, data, sizeof(uint32_t)); @@ -661,7 +668,7 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, con if (num == 0) { len = create_announce_request( - onion_c->rng, request, sizeof(request), dest_pubkey, nc_get_self_public_key(onion_c->c), + onion_c->mem, onion_c->rng, request, sizeof(request), dest_pubkey, nc_get_self_public_key(onion_c->c), nc_get_self_secret_key(onion_c->c), ping_id, nc_get_self_public_key(onion_c->c), onion_c->temp_public_key, sendback); } else { @@ -669,14 +676,14 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, con if (onion_friend->gc_data_length == 0) { // contact is a friend len = create_announce_request( - onion_c->rng, request, sizeof(request), dest_pubkey, onion_friend->temp_public_key, + onion_c->mem, onion_c->rng, request, sizeof(request), dest_pubkey, onion_friend->temp_public_key, onion_friend->temp_secret_key, ping_id, onion_friend->real_public_key, zero_ping_id, sendback); } else { // contact is a gc onion_friend->is_groupchat = true; len = create_gca_announce_request( - onion_c->rng, request, sizeof(request), dest_pubkey, onion_friend->temp_public_key, + onion_c->mem, onion_c->rng, request, sizeof(request), dest_pubkey, onion_friend->temp_public_key, onion_friend->temp_secret_key, ping_id, onion_friend->real_public_key, zero_ping_id, sendback, onion_friend->gc_data, onion_friend->gc_data_length); @@ -694,23 +701,17 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, con return send_onion_packet_tcp_udp(onion_c, &path, dest, request, len); } -typedef struct Onion_Client_Cmp_Data { +typedef struct Onion_Node_Cmp { + const Memory *mem; const Mono_Time *mono_time; - const uint8_t *base_public_key; - Onion_Node entry; -} Onion_Client_Cmp_Data; + const uint8_t *comp_public_key; +} Onion_Node_Cmp; non_null() -static int onion_client_cmp_entry(const void *a, const void *b) +static int onion_node_cmp(const Onion_Node_Cmp *cmp, const Onion_Node *entry1, const Onion_Node *entry2) { - const Onion_Client_Cmp_Data *cmp1 = (const Onion_Client_Cmp_Data *)a; - const Onion_Client_Cmp_Data *cmp2 = (const Onion_Client_Cmp_Data *)b; - const Onion_Node entry1 = cmp1->entry; - const Onion_Node entry2 = cmp2->entry; - const uint8_t *cmp_public_key = cmp1->base_public_key; - - const bool t1 = onion_node_timed_out(&entry1, cmp1->mono_time); - const bool t2 = onion_node_timed_out(&entry2, cmp2->mono_time); + const bool t1 = onion_node_timed_out(entry1, cmp->mono_time); + const bool t2 = onion_node_timed_out(entry2, cmp->mono_time); if (t1 && t2) { return 0; @@ -724,7 +725,7 @@ static int onion_client_cmp_entry(const void *a, const void *b) return 1; } - const int closest = id_closest(cmp_public_key, entry1.public_key, entry2.public_key); + const int closest = id_closest(cmp->comp_public_key, entry1->public_key, entry2->public_key); if (closest == 1) { return 1; @@ -738,30 +739,79 @@ static int onion_client_cmp_entry(const void *a, const void *b) } non_null() -static void sort_onion_node_list(const Memory *mem, const Mono_Time *mono_time, - Onion_Node *list, unsigned int length, const uint8_t *comp_public_key) +static bool onion_node_less_handler(const void *object, const void *a, const void *b) { - // Pass comp_public_key to qsort with each Client_data entry, so the - // comparison function can use it as the base of comparison. - Onion_Client_Cmp_Data *cmp_list = (Onion_Client_Cmp_Data *)mem_valloc(mem, length, sizeof(Onion_Client_Cmp_Data)); + const Onion_Node_Cmp *cmp = (const Onion_Node_Cmp *)object; + const Onion_Node *entry1 = (const Onion_Node *)a; + const Onion_Node *entry2 = (const Onion_Node *)b; - if (cmp_list == nullptr) { - return; - } + return onion_node_cmp(cmp, entry1, entry2) < 0; +} - for (uint32_t i = 0; i < length; ++i) { - cmp_list[i].mono_time = mono_time; - cmp_list[i].base_public_key = comp_public_key; - cmp_list[i].entry = list[i]; - } +non_null() +static const void *onion_node_get_handler(const void *arr, uint32_t index) +{ + const Onion_Node *entries = (const Onion_Node *)arr; + return &entries[index]; +} - qsort(cmp_list, length, sizeof(Onion_Client_Cmp_Data), onion_client_cmp_entry); +non_null() +static void onion_node_set_handler(void *arr, uint32_t index, const void *val) +{ + Onion_Node *entries = (Onion_Node *)arr; + const Onion_Node *entry = (const Onion_Node *)val; + entries[index] = *entry; +} - for (uint32_t i = 0; i < length; ++i) { - list[i] = cmp_list[i].entry; +non_null() +static void *onion_node_subarr_handler(void *arr, uint32_t index, uint32_t size) +{ + Onion_Node *entries = (Onion_Node *)arr; + return &entries[index]; +} + +non_null() +static void *onion_node_alloc_handler(const void *object, uint32_t size) +{ + const Onion_Node_Cmp *cmp = (const Onion_Node_Cmp *)object; + Onion_Node *tmp = (Onion_Node *)mem_valloc(cmp->mem, size, sizeof(Onion_Node)); + + if (tmp == nullptr) { + return nullptr; } - mem_delete(mem, cmp_list); + return tmp; +} + +non_null() +static void onion_node_delete_handler(const void *object, void *arr, uint32_t size) +{ + const Onion_Node_Cmp *cmp = (const Onion_Node_Cmp *)object; + mem_delete(cmp->mem, arr); +} + +static const Sort_Funcs onion_node_cmp_funcs = { + onion_node_less_handler, + onion_node_get_handler, + onion_node_set_handler, + onion_node_subarr_handler, + onion_node_alloc_handler, + onion_node_delete_handler, +}; + +non_null() +static void sort_onion_node_list(const Memory *mem, const Mono_Time *mono_time, + Onion_Node *list, unsigned int length, const uint8_t *comp_public_key) +{ + // Pass comp_public_key to sort with each Onion_Node entry, so the + // comparison function can use it as the base of comparison. + const Onion_Node_Cmp cmp = { + mem, + mono_time, + comp_public_key, + }; + + merge_sort(list, length, &cmp, &onion_node_cmp_funcs); } non_null() @@ -955,14 +1005,14 @@ static int handle_announce_response(void *object, const IP_Port *source, const u } uint8_t plain[1 + ONION_PING_ID_SIZE + ONION_ANNOUNCE_RESPONSE_MAX_SIZE - ONION_ANNOUNCE_RESPONSE_MIN_SIZE]; - const int plain_size = 1 + ONION_PING_ID_SIZE + length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE; + const uint32_t plain_size = 1 + ONION_PING_ID_SIZE + length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE; int len; const uint16_t nonce_start = 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH; const uint16_t ciphertext_start = nonce_start + CRYPTO_NONCE_SIZE; const uint16_t ciphertext_size = length - ciphertext_start; if (num == 0) { - len = decrypt_data(public_key, nc_get_self_secret_key(onion_c->c), + len = decrypt_data(onion_c->mem, public_key, nc_get_self_secret_key(onion_c->c), &packet[nonce_start], &packet[ciphertext_start], ciphertext_size, plain); } else { if (!onion_c->friends_list[num - 1].is_valid) { @@ -970,7 +1020,7 @@ static int handle_announce_response(void *object, const IP_Port *source, const u return 1; } - len = decrypt_data(public_key, onion_c->friends_list[num - 1].temp_secret_key, + len = decrypt_data(onion_c->mem, public_key, onion_c->friends_list[num - 1].temp_secret_key, &packet[nonce_start], &packet[ciphertext_start], ciphertext_size, plain); } @@ -1066,7 +1116,7 @@ static int handle_announce_response_old(void *object, const IP_Port *source, con const uint16_t ciphertext_size = length - ciphertext_start; if (num == 0) { - len = decrypt_data(public_key, nc_get_self_secret_key(onion_c->c), + len = decrypt_data(onion_c->mem, public_key, nc_get_self_secret_key(onion_c->c), &packet[nonce_start], &packet[ciphertext_start], ciphertext_size, plain); } else { if (!onion_c->friends_list[num - 1].is_valid) { @@ -1074,7 +1124,7 @@ static int handle_announce_response_old(void *object, const IP_Port *source, con return 1; } - len = decrypt_data(public_key, onion_c->friends_list[num - 1].temp_secret_key, + len = decrypt_data(onion_c->mem, public_key, onion_c->friends_list[num - 1].temp_secret_key, &packet[nonce_start], &packet[ciphertext_start], ciphertext_size, plain); } @@ -1136,7 +1186,7 @@ static int handle_data_response(void *object, const IP_Port *source, const uint8 const uint16_t temp_plain_size = length - ONION_DATA_RESPONSE_MIN_SIZE; VLA(uint8_t, temp_plain, temp_plain_size); - int len = decrypt_data(packet + 1 + CRYPTO_NONCE_SIZE, onion_c->temp_secret_key, packet + 1, + int len = decrypt_data(onion_c->mem, packet + 1 + CRYPTO_NONCE_SIZE, onion_c->temp_secret_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE), temp_plain); @@ -1146,7 +1196,7 @@ static int handle_data_response(void *object, const IP_Port *source, const uint8 const uint16_t plain_size = temp_plain_size - DATA_IN_RESPONSE_MIN_SIZE; VLA(uint8_t, plain, plain_size); - len = decrypt_data(temp_plain, nc_get_self_secret_key(onion_c->c), + len = decrypt_data(onion_c->mem, temp_plain, nc_get_self_secret_key(onion_c->c), packet + 1, temp_plain + CRYPTO_PUBLIC_KEY_SIZE, temp_plain_size - CRYPTO_PUBLIC_KEY_SIZE, plain); @@ -1215,7 +1265,7 @@ static int handle_dhtpk_announce(void *object, const uint8_t *source_pubkey, con const Family family = nodes[i].ip_port.ip.family; if (net_family_is_ipv4(family) || net_family_is_ipv6(family)) { - dht_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].public_key, onion_c->friends_list[friend_num].dht_public_key); + dht_send_nodes_request(onion_c->dht, &nodes[i].ip_port, nodes[i].public_key, onion_c->friends_list[friend_num].dht_public_key); } else if (net_family_is_tcp_ipv4(family) || net_family_is_tcp_ipv6(family)) { if (onion_c->friends_list[friend_num].tcp_relay_node_callback != nullptr) { void *obj = onion_c->friends_list[friend_num].tcp_relay_node_callback_object; @@ -1305,7 +1355,7 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data, const uint16_t packet_size = DATA_IN_RESPONSE_MIN_SIZE + length; VLA(uint8_t, packet, packet_size); memcpy(packet, nc_get_self_public_key(onion_c->c), CRYPTO_PUBLIC_KEY_SIZE); - int len = encrypt_data(onion_c->friends_list[friend_num].real_public_key, + int len = encrypt_data(onion_c->mem, onion_c->friends_list[friend_num].real_public_key, nc_get_self_secret_key(onion_c->c), nonce, data, length, packet + CRYPTO_PUBLIC_KEY_SIZE); @@ -1324,7 +1374,7 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data, uint8_t o_packet[ONION_MAX_PACKET_SIZE]; len = create_data_request( - onion_c->rng, o_packet, sizeof(o_packet), onion_c->friends_list[friend_num].real_public_key, + onion_c->mem, onion_c->rng, o_packet, sizeof(o_packet), onion_c->friends_list[friend_num].real_public_key, node_list[good_nodes[i]].data_public_key, nonce, packet, packet_size); if (len == -1) { @@ -1364,7 +1414,7 @@ static int send_dht_dhtpk(const Onion_Client *onion_c, int friend_num, const uin VLA(uint8_t, temp, temp_size); memcpy(temp, nc_get_self_public_key(onion_c->c), CRYPTO_PUBLIC_KEY_SIZE); memcpy(temp + CRYPTO_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE); - int len = encrypt_data(onion_c->friends_list[friend_num].real_public_key, + int len = encrypt_data(onion_c->mem, onion_c->friends_list[friend_num].real_public_key, nc_get_self_secret_key(onion_c->c), nonce, data, length, temp + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE); @@ -1374,7 +1424,7 @@ static int send_dht_dhtpk(const Onion_Client *onion_c, int friend_num, const uin uint8_t packet_data[MAX_CRYPTO_REQUEST_SIZE]; len = create_request( - onion_c->rng, dht_get_self_public_key(onion_c->dht), dht_get_self_secret_key(onion_c->dht), packet_data, + onion_c->mem, onion_c->rng, dht_get_self_public_key(onion_c->dht), dht_get_self_secret_key(onion_c->dht), packet_data, onion_c->friends_list[friend_num].dht_public_key, temp, temp_size, CRYPTO_PACKET_DHTPK); assert(len <= UINT16_MAX); const Packet packet = {packet_data, (uint16_t)len}; @@ -1401,7 +1451,7 @@ static int handle_dht_dhtpk(void *object, const IP_Port *source, const uint8_t * } uint8_t plain[DHTPK_DATA_MAX_LENGTH]; - const int len = decrypt_data(packet, nc_get_self_secret_key(onion_c->c), + const int len = decrypt_data(onion_c->mem, packet, nc_get_self_secret_key(onion_c->c), packet + CRYPTO_PUBLIC_KEY_SIZE, packet + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, length - (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE), plain); diff --git a/protocols/Tox/libtox/src/toxcore/onion_client.h b/protocols/Tox/libtox/src/toxcore/onion_client.h index 61e4e6fd1c..5999f15c65 100644 --- a/protocols/Tox/libtox/src/toxcore/onion_client.h +++ b/protocols/Tox/libtox/src/toxcore/onion_client.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ @@ -183,6 +183,8 @@ non_null() unsigned int onion_getfriend_dht_pubkey(const Onion_Client *onion_c, int friend_num, uint8_t *dht_key); #define ONION_DATA_IN_RESPONSE_MIN_SIZE (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE) + +// TODO(Jfreegman): This is not the correct value; data this large will be dropped by the onion client. #define ONION_CLIENT_MAX_DATA_SIZE (MAX_DATA_REQUEST_SIZE - ONION_DATA_IN_RESPONSE_MIN_SIZE) /** @brief Send data of length length to friendnum. diff --git a/protocols/Tox/libtox/src/toxcore/ping.c b/protocols/Tox/libtox/src/toxcore/ping.c index 303c418cea..bfb3c92cd3 100644 --- a/protocols/Tox/libtox/src/toxcore/ping.c +++ b/protocols/Tox/libtox/src/toxcore/ping.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. * Copyright © 2013 plutooo */ @@ -31,6 +31,7 @@ struct Ping { const Mono_Time *mono_time; const Random *rng; + const Memory *mem; DHT *dht; Ping_Array *ping_array; @@ -72,7 +73,7 @@ void ping_send_request(Ping *ping, const IP_Port *ipp, const uint8_t *public_key pk_copy(pk + 1, dht_get_self_public_key(ping->dht)); // Our pubkey random_nonce(ping->rng, pk + 1 + CRYPTO_PUBLIC_KEY_SIZE); // Generate new nonce - rc = encrypt_data_symmetric(shared_key, + rc = encrypt_data_symmetric(ping->mem, shared_key, pk + 1 + CRYPTO_PUBLIC_KEY_SIZE, ping_plain, sizeof(ping_plain), pk + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE); @@ -104,7 +105,7 @@ static int ping_send_response(const Ping *ping, const IP_Port *ipp, const uint8_ random_nonce(ping->rng, pk + 1 + CRYPTO_PUBLIC_KEY_SIZE); // Generate new nonce // Encrypt ping_id using recipient privkey - const int rc = encrypt_data_symmetric(shared_encryption_key, + const int rc = encrypt_data_symmetric(ping->mem, shared_encryption_key, pk + 1 + CRYPTO_PUBLIC_KEY_SIZE, ping_plain, sizeof(ping_plain), pk + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE); @@ -137,7 +138,7 @@ static int handle_ping_request(void *object, const IP_Port *source, const uint8_ uint8_t ping_plain[PING_PLAIN_SIZE]; // Decrypt ping_id - const int rc = decrypt_data_symmetric(shared_key, + const int rc = decrypt_data_symmetric(ping->mem, shared_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, PING_PLAIN_SIZE + CRYPTO_MAC_SIZE, @@ -182,7 +183,7 @@ static int handle_ping_response(void *object, const IP_Port *source, const uint8 uint8_t ping_plain[PING_PLAIN_SIZE]; // Decrypt ping_id - rc = decrypt_data_symmetric(shared_key, + rc = decrypt_data_symmetric(ping->mem, shared_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, PING_PLAIN_SIZE + CRYPTO_MAC_SIZE, @@ -348,6 +349,7 @@ Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Random *rng, ping->mono_time = mono_time; ping->rng = rng; + ping->mem = mem; ping->dht = dht; networking_registerhandler(dht_get_net(ping->dht), NET_PACKET_PING_REQUEST, &handle_ping_request, dht); networking_registerhandler(dht_get_net(ping->dht), NET_PACKET_PING_RESPONSE, &handle_ping_response, dht); diff --git a/protocols/Tox/libtox/src/toxcore/ping.h b/protocols/Tox/libtox/src/toxcore/ping.h index b0339ec75d..98ae7bd754 100644 --- a/protocols/Tox/libtox/src/toxcore/ping.h +++ b/protocols/Tox/libtox/src/toxcore/ping.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. * Copyright © 2013 plutooo */ diff --git a/protocols/Tox/libtox/src/toxcore/ping_array.c b/protocols/Tox/libtox/src/toxcore/ping_array.c index c40215ea47..91b9064ecc 100644 --- a/protocols/Tox/libtox/src/toxcore/ping_array.c +++ b/protocols/Tox/libtox/src/toxcore/ping_array.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2014 Tox project. */ diff --git a/protocols/Tox/libtox/src/toxcore/ping_array.h b/protocols/Tox/libtox/src/toxcore/ping_array.h index 3e50e66876..2d1f9f5cc2 100644 --- a/protocols/Tox/libtox/src/toxcore/ping_array.h +++ b/protocols/Tox/libtox/src/toxcore/ping_array.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ diff --git a/protocols/Tox/libtox/src/toxcore/shared_key_cache.c b/protocols/Tox/libtox/src/toxcore/shared_key_cache.c index 80d74aecb4..64906b569c 100644 --- a/protocols/Tox/libtox/src/toxcore/shared_key_cache.c +++ b/protocols/Tox/libtox/src/toxcore/shared_key_cache.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2022 The TokTok team. + * Copyright © 2022-2025 The TokTok team. */ #include "shared_key_cache.h" diff --git a/protocols/Tox/libtox/src/toxcore/shared_key_cache.h b/protocols/Tox/libtox/src/toxcore/shared_key_cache.h index f6e84c3130..69295325d6 100644 --- a/protocols/Tox/libtox/src/toxcore/shared_key_cache.h +++ b/protocols/Tox/libtox/src/toxcore/shared_key_cache.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2022 The TokTok team. + * Copyright © 2022-2025 The TokTok team. */ #ifndef C_TOXCORE_TOXCORE_SHARED_KEY_CACHE_H diff --git a/protocols/Tox/libtox/src/toxcore/sort.c b/protocols/Tox/libtox/src/toxcore/sort.c new file mode 100644 index 0000000000..9bd83d6171 --- /dev/null +++ b/protocols/Tox/libtox/src/toxcore/sort.c @@ -0,0 +1,182 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2023-2025 The TokTok team. + */ + +#include "sort.h" + +#include <assert.h> + +#include "attributes.h" +#include "ccompat.h" +#include "util.h" + +/** + * @brief Threshold for when to switch to insertion sort. + * + * This is a trade-off between the complexity of insertion sort and the + * overhead of merge sort. The threshold is chosen to be the smallest value + * that gives a measurable speedup for insertion sort over merge sort. This is + * based on measurements done in sort_bench.cc. Starting from 32 elements, + * merge sort is faster than insertion sort in all our tests (both unsorted + * and mostly-sorted). + * + * Toxcore has a lot of small arrays it wants to sort, so this optimisation + * makes sense. + */ +#define SMALL_ARRAY_THRESHOLD 16 + +non_null() +static void merge_sort_merge_back( + void *arr, + const void *l_arr, uint32_t l_arr_size, + const void *r_arr, uint32_t r_arr_size, + uint32_t left_start, + const void *object, const Sort_Funcs *funcs) +{ + uint32_t li = 0; + uint32_t ri = 0; + uint32_t k = left_start; + + while (li < l_arr_size && ri < r_arr_size) { + const void *l = funcs->get_callback(l_arr, li); + const void *r = funcs->get_callback(r_arr, ri); + // !(r < l) <=> (r >= l) <=> (l <= r) + if (!funcs->less_callback(object, r, l)) { + funcs->set_callback(arr, k, l); + ++li; + } else { + funcs->set_callback(arr, k, r); + ++ri; + } + ++k; + } + + /* Copy the remaining elements of `l_arr[]`, if there are any. */ + while (li < l_arr_size) { + funcs->set_callback(arr, k, funcs->get_callback(l_arr, li)); + ++li; + ++k; + } + + /* Copy the remaining elements of `r_arr[]`, if there are any. */ + while (ri < r_arr_size) { + funcs->set_callback(arr, k, funcs->get_callback(r_arr, ri)); + ++ri; + ++k; + } +} + +/** Function to merge the two haves `arr[left_start..mid]` and `arr[mid+1..right_end]` of array `arr[]`. */ +non_null() +static void merge_sort_merge( + void *arr, uint32_t left_start, uint32_t mid, uint32_t right_end, void *tmp, + const void *object, const Sort_Funcs *funcs) +{ + const uint32_t l_arr_size = mid - left_start + 1; + const uint32_t r_arr_size = right_end - mid; + + /* Temporary arrays, using the tmp buffer created in `merge_sort` below. */ + void *l_arr = funcs->subarr_callback(tmp, 0, l_arr_size); + void *r_arr = funcs->subarr_callback(tmp, l_arr_size, r_arr_size); + + /* Copy data to temp arrays `l_arr[]` and `r_arr[]`. + * + * This is iterating and repeatedly calling `get` and `set`, which sounds + * slow, but is only marginally slower than having a `copy` callback. With + * a `copy` callback, we'd save 3-4% in time. + */ + for (uint32_t i = 0; i < l_arr_size; ++i) { + funcs->set_callback(l_arr, i, funcs->get_callback(arr, left_start + i)); + } + for (uint32_t i = 0; i < r_arr_size; ++i) { + funcs->set_callback(r_arr, i, funcs->get_callback(arr, mid + 1 + i)); + } + + /* Merge the temp arrays back into `arr[left_start..right_end]`. */ + merge_sort_merge_back(arr, l_arr, l_arr_size, r_arr, r_arr_size, left_start, object, funcs); +} + +non_null() +static void insertion_sort_step(void *arr, void *tmp, uint32_t i, const void *object, const Sort_Funcs *funcs) +{ + funcs->set_callback(tmp, 0, funcs->get_callback(arr, i)); + uint32_t j = i; + + while (j > 0) { + if (!funcs->less_callback(object, tmp, funcs->get_callback(arr, j - 1))) { + break; + } + funcs->set_callback(arr, j, funcs->get_callback(arr, j - 1)); + --j; + } + + funcs->set_callback(arr, j, tmp); +} + +non_null() +static void insertion_sort_with_buf(void *arr, uint32_t arr_size, void *tmp, uint32_t tmp_size, const void *object, const Sort_Funcs *funcs) +{ + for (uint32_t i = 1; i < arr_size; ++i) { + insertion_sort_step(arr, tmp, i, object, funcs); + } +} + +non_null() +static bool insertion_sort(void *arr, uint32_t arr_size, const void *object, const Sort_Funcs *funcs) +{ + void *tmp = funcs->alloc_callback(object, 1); + + if (tmp == nullptr) { + return false; + } + + insertion_sort_with_buf(arr, arr_size, tmp, 1, object, funcs); + + funcs->delete_callback(object, tmp, 1); + return true; +} + +void merge_sort_with_buf(void *arr, uint32_t arr_size, void *tmp, uint32_t tmp_size, const void *object, const Sort_Funcs *funcs) +{ + assert(tmp_size >= arr_size); + + if (arr_size <= SMALL_ARRAY_THRESHOLD) { + assert(tmp_size >= 1); + insertion_sort_with_buf(arr, arr_size, tmp, tmp_size, object, funcs); + return; + } + + // Merge subarrays in bottom up manner. First merge subarrays of + // size 1 to create sorted subarrays of size 2, then merge subarrays + // of size 2 to create sorted subarrays of size 4, and so on. + for (uint32_t curr_size = 1; curr_size <= arr_size - 1; curr_size = 2 * curr_size) { + // Pick starting point of different subarrays of current size + for (uint32_t left_start = 0; left_start < arr_size - 1; left_start += 2 * curr_size) { + // Find ending point of left subarray. mid+1 is starting + // point of right + const uint32_t mid = min_u32(left_start + curr_size - 1, arr_size - 1); + const uint32_t right_end = min_u32(left_start + 2 * curr_size - 1, arr_size - 1); + + // Merge Subarrays arr[left_start...mid] & arr[mid+1...right_end] + merge_sort_merge(arr, left_start, mid, right_end, tmp, object, funcs); + } + } +} + +bool merge_sort(void *arr, uint32_t arr_size, const void *object, const Sort_Funcs *funcs) +{ + if (arr_size <= SMALL_ARRAY_THRESHOLD) { + return insertion_sort(arr, arr_size, object, funcs); + } + + void *tmp = funcs->alloc_callback(object, arr_size); + + if (tmp == nullptr) { + return false; + } + + merge_sort_with_buf(arr, arr_size, tmp, arr_size, object, funcs); + + funcs->delete_callback(object, tmp, arr_size); + return true; +} diff --git a/protocols/Tox/libtox/src/toxcore/sort.h b/protocols/Tox/libtox/src/toxcore/sort.h new file mode 100644 index 0000000000..b95ca8be3c --- /dev/null +++ b/protocols/Tox/libtox/src/toxcore/sort.h @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2023-2025 The TokTok team. + */ + +#ifndef C_TOXCORE_TOXCORE_SORT_H +#define C_TOXCORE_TOXCORE_SORT_H + +#include <stdbool.h> +#include <stdint.h> + +#include "attributes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Compare elements with a less-than ordering: `a < b`. */ +typedef bool sort_less_cb(const void *object, const void *a, const void *b); +/** @brief Get element from array at index. */ +typedef const void *sort_get_cb(const void *arr, uint32_t index); +/** @brief Set element in array at index to new value (perform copy). */ +typedef void sort_set_cb(void *arr, uint32_t index, const void *val); +/** @brief Get a sub-array at an index of a given size (mutable pointer). + * + * Used to index in the temporary array allocated by `sort_alloc_cb` and get + * a sub-array for working memory. + */ +typedef void *sort_subarr_cb(void *arr, uint32_t index, uint32_t size); +/** @brief Allocate a new array of the element type. + * + * @param size The array size in elements of type T (not byte size). This value + * is always exactly the input array size as passed to `merge_sort`. + */ +typedef void *sort_alloc_cb(const void *object, uint32_t size); +/** @brief Free the element type array. */ +typedef void sort_delete_cb(const void *object, void *arr, uint32_t size); + +/** @brief Virtual function table for getting/setting elements in an array and + * comparing them. + * + * Only the `less`, `alloc`, and `delete` functions get a `this`-pointer. We + * assume that indexing in an array doesn't need any other information than the + * array itself. + * + * For now, the `this`-pointer is const, because we assume sorting doesn't need + * to mutate any state, but if necessary that can be changed in the future. + */ +typedef struct Sort_Funcs { + sort_less_cb *less_callback; + sort_get_cb *get_callback; + sort_set_cb *set_callback; + sort_subarr_cb *subarr_callback; + sort_alloc_cb *alloc_callback; + sort_delete_cb *delete_callback; +} Sort_Funcs; + +/** @brief Non-recursive merge sort function to sort `arr[0...arr_size-1]`. + * + * Avoids `memcpy` and avoids treating elements as byte arrays. Instead, uses + * callbacks to index in arrays and copy elements. This makes it quite a bit + * slower than `qsort`, but works with elements that require special care when + * being copied (e.g. if they are part of a graph or other data structure that + * with pointers or other invariants). + * + * This function actually uses insertion sort for small arrays (up to 16 + * elements), which is faster than merge sort for small arrays, especially + * when mostly sorted (a common use case in toxcore). + * + * Allocates a single temporary array with the provided alloc callback, and + * frees it at the end. This is significantly faster than an in-place + * implementation. + * + * Complexity: + * - Space: `O(n) where n = array_size`. + * - Time: `O(n * log n) where n = array_size`. + * + * Compared to `qsort`, this is about 60-70% slower for large arrays. For small + * arrays (up to 16 elements), it's about 50% faster than `qsort`. + * + * @param[in,out] arr An array of type T. + * @param arr_size Number of elements in @p arr (count, not byte size). + * @param[in] object Comparator object. + * @param[in] funcs Callback struct for elements of type T. + */ +non_null() +bool merge_sort(void *arr, uint32_t arr_size, const void *object, const Sort_Funcs *funcs); + +/** + * @brief Merge sort like above but with a pre-allocated buffer. + * + * This function is the same as `merge_sort` but uses a pre-allocated buffer + * for temporary storage. This can be useful if the caller wants to avoid + * dynamic memory allocation. + * + * This function is 1-2% faster than `merge_sort` for small arrays up to 1000 + * elements, and about 5-10% faster for large arrays (2000+ elements). + * + * The main upside is that `alloc` and `delete` callbacks don't need to be + * implemented, and the caller can use a stack-allocated buffer. + * + * @param[in,out] arr An array of type T. + * @param arr_size Number of elements in @p arr (count, not byte size). + * @param[in,out] tmp A buffer of size `tmp_size` for temporary storage. + * @param tmp_size Number of elements in @p tmp (count, not byte size). Must be + * at least as large as `arr_size`. + * @param[in] object Comparator object. + * @param[in] funcs Callback struct for elements of type T. + */ +non_null() +void merge_sort_with_buf(void *arr, uint32_t arr_size, void *tmp, uint32_t tmp_size, const void *object, const Sort_Funcs *funcs); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* C_TOXCORE_TOXCORE_SORT_H */ diff --git a/protocols/Tox/libtox/src/toxcore/timed_auth.c b/protocols/Tox/libtox/src/toxcore/timed_auth.c index 875003257b..45afe0704a 100644 --- a/protocols/Tox/libtox/src/toxcore/timed_auth.c +++ b/protocols/Tox/libtox/src/toxcore/timed_auth.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2019-2021 The TokTok team. + * Copyright © 2019-2025 The TokTok team. */ #include "timed_auth.h" diff --git a/protocols/Tox/libtox/src/toxcore/timed_auth.h b/protocols/Tox/libtox/src/toxcore/timed_auth.h index bb19570872..ccef4b305e 100644 --- a/protocols/Tox/libtox/src/toxcore/timed_auth.h +++ b/protocols/Tox/libtox/src/toxcore/timed_auth.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2019-2021 The TokTok team. + * Copyright © 2019-2025 The TokTok team. */ #ifndef C_TOXCORE_TOXCORE_TIMED_AUTH_H #define C_TOXCORE_TOXCORE_TIMED_AUTH_H diff --git a/protocols/Tox/libtox/src/toxcore/tox.c b/protocols/Tox/libtox/src/toxcore/tox.c index 085fab2ec1..8e1b43903d 100644 --- a/protocols/Tox/libtox/src/toxcore/tox.c +++ b/protocols/Tox/libtox/src/toxcore/tox.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ @@ -32,8 +32,10 @@ #include "network.h" #include "onion_client.h" #include "state.h" +#include "tox_log_level.h" +#include "tox_options.h" #include "tox_private.h" -#include "tox_struct.h" +#include "tox_struct.h" // IWYU pragma: keep #include "util.h" #include "../toxencryptsave/defines.h" @@ -79,7 +81,7 @@ struct Tox_Userdata { static logger_cb tox_log_handler; non_null(1, 3, 5, 6) nullable(7) -static void tox_log_handler(void *context, Logger_Level level, const char *file, int line, const char *func, +static void tox_log_handler(void *context, Logger_Level level, const char *file, uint32_t line, const char *func, const char *message, void *userdata) { Tox *tox = (Tox *)context; @@ -360,20 +362,22 @@ static void tox_conference_peer_list_changed_handler(Messenger *m, uint32_t conf } } -static dht_get_nodes_response_cb tox_dht_get_nodes_response_handler; +static dht_nodes_response_cb tox_dht_nodes_response_handler; non_null(1, 2) nullable(3) -static void tox_dht_get_nodes_response_handler(const DHT *dht, const Node_format *node, void *user_data) +static void tox_dht_nodes_response_handler(const DHT *dht, const Node_format *node, void *user_data) { struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data; - if (tox_data->tox->dht_get_nodes_response_callback == nullptr) { + if (tox_data->tox->dht_nodes_response_callback == nullptr) { return; } Ip_Ntoa ip_str; + net_ip_ntoa(&node->ip_port.ip, &ip_str); + tox_unlock(tox_data->tox); - tox_data->tox->dht_get_nodes_response_callback( - tox_data->tox, node->public_key, net_ip_ntoa(&node->ip_port.ip, &ip_str), net_ntohs(node->ip_port.port), + tox_data->tox->dht_nodes_response_callback( + tox_data->tox, node->public_key, ip_str.buf, ip_str.length, net_ntohs(node->ip_port.port), tox_data->user_data); tox_lock(tox_data->tox); } @@ -524,7 +528,7 @@ static void tox_group_password_handler(const Messenger *m, uint32_t group_number non_null(1, 5) nullable(8) static void tox_group_message_handler(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id, unsigned int type, - const uint8_t *message, size_t length, uint32_t message_id, void *user_data) + const uint8_t *message, size_t length, Tox_Group_Message_Id message_id, void *user_data) { struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data; @@ -536,16 +540,16 @@ static void tox_group_message_handler(const Messenger *m, uint32_t group_number, } } -non_null(1, 5) nullable(7) +non_null(1, 5) nullable(8) static void tox_group_private_message_handler(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id, - unsigned int type, const uint8_t *message, size_t length, void *user_data) + unsigned int type, const uint8_t *message, size_t length, Tox_Group_Message_Id message_id, void *user_data) { struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data; if (tox_data->tox->group_private_message_callback != nullptr) { tox_unlock(tox_data->tox); tox_data->tox->group_private_message_callback(tox_data->tox, group_number, gc_peer_id_to_int(peer_id), (Tox_Message_Type)type, message, - length, tox_data->user_data); + length, message_id, tox_data->user_data); tox_lock(tox_data->tox); } } @@ -712,7 +716,8 @@ static int tox_load(Tox *tox, const uint8_t *data, uint32_t length) length - cookie_len, STATE_COOKIE_TYPE); } -Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error) +nullable(1, 2, 3) +static Tox *tox_new_system(const struct Tox_Options *options, Tox_Err_New *error, const Tox_System *sys) { struct Tox_Options *default_options = nullptr; @@ -736,7 +741,6 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error) const struct Tox_Options *const opts = options != nullptr ? options : default_options; assert(opts != nullptr); - const Tox_System *sys = tox_options_get_operating_system(opts); const Tox_System default_system = tox_default_system(); if (sys == nullptr) { @@ -752,6 +756,8 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error) Messenger_Options m_options = {false}; + m_options.dns_enabled = !tox_options_get_experimental_disable_dns(opts); + bool load_savedata_sk = false; bool load_savedata_tox = false; @@ -855,9 +861,10 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error) } const char *const proxy_host = tox_options_get_proxy_host(opts); + const bool dns_enabled = !tox_options_get_experimental_disable_dns(opts); if (proxy_host == nullptr - || !addr_resolve_or_parse_ip(tox->sys.ns, proxy_host, &m_options.proxy_info.ip_port.ip, nullptr)) { + || !addr_resolve_or_parse_ip(tox->sys.ns, tox->sys.mem, proxy_host, &m_options.proxy_info.ip_port.ip, nullptr, dns_enabled)) { SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_HOST); // TODO(irungentoo): TOX_ERR_NEW_PROXY_NOT_FOUND if domain. mem_delete(sys->mem, tox); @@ -926,7 +933,7 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error) return nullptr; } - tox->m->conferences_object = new_groupchats(tox->mono_time, tox->m); + tox->m->conferences_object = new_groupchats(tox->mono_time, sys->mem, tox->m); if (tox->m->conferences_object == nullptr) { kill_messenger(tox->m); @@ -983,7 +990,7 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error) callback_file_reqchunk(tox->m, tox_file_chunk_request_handler); callback_file_sendrequest(tox->m, tox_file_recv_handler); callback_file_data(tox->m, tox_file_recv_chunk_handler); - dht_callback_get_nodes_response(tox->m->dht, tox_dht_get_nodes_response_handler); + dht_callback_nodes_response(tox->m->dht, tox_dht_nodes_response_handler); g_callback_group_invite(tox->m->conferences_object, tox_conference_invite_handler); g_callback_group_connected(tox->m->conferences_object, tox_conference_connected_handler); g_callback_group_message(tox->m->conferences_object, tox_conference_message_handler); @@ -1020,6 +1027,37 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error) return tox; } +Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error) +{ + return tox_new_system(options, error, nullptr); +} + +Tox *tox_new_testing(const Tox_Options *options, Tox_Err_New *error, const Tox_Options_Testing *testing, Tox_Err_New_Testing *testing_error) +{ + if (testing == nullptr) { + SET_ERROR_PARAMETER(error, TOX_ERR_NEW_NULL); + SET_ERROR_PARAMETER(testing_error, TOX_ERR_NEW_TESTING_NULL); + return nullptr; + } + + if (testing->operating_system == nullptr) { + SET_ERROR_PARAMETER(error, TOX_ERR_NEW_NULL); + SET_ERROR_PARAMETER(testing_error, TOX_ERR_NEW_TESTING_NULL); + return nullptr; + } + + const Tox_System *sys = testing->operating_system; + + if (sys->rng == nullptr || sys->ns == nullptr || sys->mem == nullptr) { + SET_ERROR_PARAMETER(error, TOX_ERR_NEW_NULL); + SET_ERROR_PARAMETER(testing_error, TOX_ERR_NEW_TESTING_NULL); + return nullptr; + } + + SET_ERROR_PARAMETER(testing_error, TOX_ERR_NEW_TESTING_OK); + return tox_new_system(options, error, sys); +} + void tox_kill(Tox *tox) { if (tox == nullptr) { @@ -1027,7 +1065,7 @@ void tox_kill(Tox *tox) } tox_lock(tox); - LOGGER_ASSERT(tox->m->log, tox->m->msi_packet == nullptr, "Attempted to kill tox while toxav is still alive"); + LOGGER_ASSERT(tox->m->log, tox->toxav_object == nullptr, "Attempted to kill tox while toxav is still alive"); kill_groupchats(tox->m->conferences_object); kill_messenger(tox->m); mono_time_free(tox->sys.mem, tox->mono_time); @@ -1108,7 +1146,7 @@ static int32_t resolve_bootstrap_node(Tox *tox, const char *host, uint16_t port, return -1; } - const int32_t count = net_getipport(tox->sys.mem, host, root, TOX_SOCK_DGRAM); + const int32_t count = net_getipport(tox->sys.ns, tox->sys.mem, host, root, TOX_SOCK_DGRAM, tox->m->options.dns_enabled); if (count < 1) { LOGGER_DEBUG(tox->m->log, "could not resolve bootstrap node '%s'", host); @@ -2520,6 +2558,12 @@ uint32_t tox_conference_join(Tox *tox, uint32_t friend_number, const uint8_t *co Tox_Err_Conference_Join *error) { assert(tox != nullptr); + + if (cookie == nullptr) { + SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_NULL); + return UINT32_MAX; + } + tox_lock(tox); const int ret = join_groupchat(tox->m->conferences_object, friend_number, GROUPCHAT_TYPE_TEXT, cookie, length); tox_unlock(tox); @@ -3209,7 +3253,7 @@ bool tox_group_reconnect(Tox *tox, uint32_t group_number, Tox_Err_Group_Reconnec return false; } - const int ret = gc_rejoin_group(tox->m->group_handler, chat); + const int ret = gc_rejoin_group(tox->m->group_handler, chat, nullptr, 0); tox_unlock(tox); switch (ret) { @@ -3688,7 +3732,7 @@ bool tox_group_set_topic(Tox *tox, uint32_t group_number, const uint8_t *topic, return false; } -size_t tox_group_get_topic_size(const Tox *tox, uint32_t group_number, Tox_Err_Group_State_Queries *error) +size_t tox_group_get_topic_size(const Tox *tox, uint32_t group_number, Tox_Err_Group_State_Query *error) { assert(tox != nullptr); @@ -3696,12 +3740,12 @@ size_t tox_group_get_topic_size(const Tox *tox, uint32_t group_number, Tox_Err_G const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number); if (chat == nullptr) { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND); tox_unlock(tox); return -1; } - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_OK); const size_t ret = gc_get_topic_size(chat); tox_unlock(tox); @@ -3709,7 +3753,7 @@ size_t tox_group_get_topic_size(const Tox *tox, uint32_t group_number, Tox_Err_G return ret; } -bool tox_group_get_topic(const Tox *tox, uint32_t group_number, uint8_t *topic, Tox_Err_Group_State_Queries *error) +bool tox_group_get_topic(const Tox *tox, uint32_t group_number, uint8_t *topic, Tox_Err_Group_State_Query *error) { assert(tox != nullptr); @@ -3717,7 +3761,7 @@ bool tox_group_get_topic(const Tox *tox, uint32_t group_number, uint8_t *topic, const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number); if (chat == nullptr) { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND); tox_unlock(tox); return false; } @@ -3725,11 +3769,11 @@ bool tox_group_get_topic(const Tox *tox, uint32_t group_number, uint8_t *topic, gc_get_topic(chat, topic); tox_unlock(tox); - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_OK); return true; } -size_t tox_group_get_name_size(const Tox *tox, uint32_t group_number, Tox_Err_Group_State_Queries *error) +size_t tox_group_get_name_size(const Tox *tox, uint32_t group_number, Tox_Err_Group_State_Query *error) { assert(tox != nullptr); @@ -3737,12 +3781,12 @@ size_t tox_group_get_name_size(const Tox *tox, uint32_t group_number, Tox_Err_Gr const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number); if (chat == nullptr) { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND); tox_unlock(tox); return -1; } - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_OK); const size_t ret = gc_get_group_name_size(chat); tox_unlock(tox); @@ -3750,7 +3794,7 @@ size_t tox_group_get_name_size(const Tox *tox, uint32_t group_number, Tox_Err_Gr return ret; } -bool tox_group_get_name(const Tox *tox, uint32_t group_number, uint8_t *name, Tox_Err_Group_State_Queries *error) +bool tox_group_get_name(const Tox *tox, uint32_t group_number, uint8_t *name, Tox_Err_Group_State_Query *error) { assert(tox != nullptr); @@ -3758,7 +3802,7 @@ bool tox_group_get_name(const Tox *tox, uint32_t group_number, uint8_t *name, To const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number); if (chat == nullptr) { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND); tox_unlock(tox); return false; } @@ -3766,12 +3810,12 @@ bool tox_group_get_name(const Tox *tox, uint32_t group_number, uint8_t *name, To gc_get_group_name(chat, name); tox_unlock(tox); - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_OK); return true; } -bool tox_group_get_chat_id(const Tox *tox, uint32_t group_number, uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE], Tox_Err_Group_State_Queries *error) +bool tox_group_get_chat_id(const Tox *tox, uint32_t group_number, uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE], Tox_Err_Group_State_Query *error) { assert(tox != nullptr); @@ -3779,12 +3823,12 @@ bool tox_group_get_chat_id(const Tox *tox, uint32_t group_number, uint8_t chat_i const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number); if (chat == nullptr) { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND); tox_unlock(tox); return false; } - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_OK); gc_get_chat_id(chat, chat_id); tox_unlock(tox); @@ -3803,7 +3847,7 @@ uint32_t tox_group_get_number_groups(const Tox *tox) } Tox_Group_Privacy_State tox_group_get_privacy_state(const Tox *tox, uint32_t group_number, - Tox_Err_Group_State_Queries *error) + Tox_Err_Group_State_Query *error) { assert(tox != nullptr); @@ -3811,12 +3855,12 @@ Tox_Group_Privacy_State tox_group_get_privacy_state(const Tox *tox, uint32_t gro const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number); if (chat == nullptr) { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND); tox_unlock(tox); return (Tox_Group_Privacy_State) - 1; } - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_OK); const uint8_t state = gc_get_privacy_state(chat); tox_unlock(tox); @@ -3824,7 +3868,7 @@ Tox_Group_Privacy_State tox_group_get_privacy_state(const Tox *tox, uint32_t gro return (Tox_Group_Privacy_State)state; } -Tox_Group_Topic_Lock tox_group_get_topic_lock(const Tox *tox, uint32_t group_number, Tox_Err_Group_State_Queries *error) +Tox_Group_Topic_Lock tox_group_get_topic_lock(const Tox *tox, uint32_t group_number, Tox_Err_Group_State_Query *error) { assert(tox != nullptr); @@ -3832,12 +3876,12 @@ Tox_Group_Topic_Lock tox_group_get_topic_lock(const Tox *tox, uint32_t group_num const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number); if (chat == nullptr) { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND); tox_unlock(tox); return (Tox_Group_Topic_Lock) - 1; } - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_OK); const Group_Topic_Lock topic_lock = gc_get_topic_lock_state(chat); tox_unlock(tox); @@ -3846,7 +3890,7 @@ Tox_Group_Topic_Lock tox_group_get_topic_lock(const Tox *tox, uint32_t group_num } Tox_Group_Voice_State tox_group_get_voice_state(const Tox *tox, uint32_t group_number, - Tox_Err_Group_State_Queries *error) + Tox_Err_Group_State_Query *error) { assert(tox != nullptr); @@ -3854,12 +3898,12 @@ Tox_Group_Voice_State tox_group_get_voice_state(const Tox *tox, uint32_t group_n const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number); if (chat == nullptr) { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND); tox_unlock(tox); return (Tox_Group_Voice_State) - 1; } - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_OK); const Group_Voice_State voice_state = gc_get_voice_state(chat); tox_unlock(tox); @@ -3867,7 +3911,7 @@ Tox_Group_Voice_State tox_group_get_voice_state(const Tox *tox, uint32_t group_n return (Tox_Group_Voice_State)voice_state; } -uint16_t tox_group_get_peer_limit(const Tox *tox, uint32_t group_number, Tox_Err_Group_State_Queries *error) +uint16_t tox_group_get_peer_limit(const Tox *tox, uint32_t group_number, Tox_Err_Group_State_Query *error) { assert(tox != nullptr); @@ -3875,12 +3919,12 @@ uint16_t tox_group_get_peer_limit(const Tox *tox, uint32_t group_number, Tox_Err const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number); if (chat == nullptr) { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND); tox_unlock(tox); return -1; } - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_OK); const uint16_t ret = gc_get_max_peers(chat); tox_unlock(tox); @@ -3888,7 +3932,7 @@ uint16_t tox_group_get_peer_limit(const Tox *tox, uint32_t group_number, Tox_Err return ret; } -size_t tox_group_get_password_size(const Tox *tox, uint32_t group_number, Tox_Err_Group_State_Queries *error) +size_t tox_group_get_password_size(const Tox *tox, uint32_t group_number, Tox_Err_Group_State_Query *error) { assert(tox != nullptr); @@ -3896,12 +3940,12 @@ size_t tox_group_get_password_size(const Tox *tox, uint32_t group_number, Tox_Er const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number); if (chat == nullptr) { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND); tox_unlock(tox); return -1; } - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_OK); const size_t ret = gc_get_password_size(chat); tox_unlock(tox); @@ -3910,7 +3954,7 @@ size_t tox_group_get_password_size(const Tox *tox, uint32_t group_number, Tox_Er } bool tox_group_get_password(const Tox *tox, uint32_t group_number, uint8_t *password, - Tox_Err_Group_State_Queries *error) + Tox_Err_Group_State_Query *error) { assert(tox != nullptr); @@ -3918,12 +3962,12 @@ bool tox_group_get_password(const Tox *tox, uint32_t group_number, uint8_t *pass const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number); if (chat == nullptr) { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND); tox_unlock(tox); return false; } - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_OK); gc_get_password(chat, password); tox_unlock(tox); @@ -3932,7 +3976,7 @@ bool tox_group_get_password(const Tox *tox, uint32_t group_number, uint8_t *pass } Tox_Group_Message_Id tox_group_send_message( - const Tox *tox, uint32_t group_number, Tox_Message_Type type, const uint8_t *message, + const Tox *tox, uint32_t group_number, Tox_Message_Type message_type, const uint8_t *message, size_t length, Tox_Err_Group_Send_Message *error) { assert(tox != nullptr); @@ -3953,7 +3997,7 @@ Tox_Group_Message_Id tox_group_send_message( } uint32_t message_id = 0; - const int ret = gc_send_message(chat, message, length, type, &message_id); + const int ret = gc_send_message(chat, message, length, message_type, &message_id); tox_unlock(tox); switch (ret) { @@ -3994,8 +4038,8 @@ Tox_Group_Message_Id tox_group_send_message( return -1; } -bool tox_group_send_private_message(const Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Message_Type type, - const uint8_t *message, size_t length, Tox_Err_Group_Send_Private_Message *error) +Tox_Group_Message_Id tox_group_send_private_message(const Tox *tox, uint32_t group_number, uint32_t peer_id, + Tox_Message_Type message_type, const uint8_t *message, size_t length, Tox_Err_Group_Send_Private_Message *error) { assert(tox != nullptr); @@ -4005,59 +4049,60 @@ bool tox_group_send_private_message(const Tox *tox, uint32_t group_number, uint3 if (chat == nullptr) { SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_GROUP_NOT_FOUND); tox_unlock(tox); - return false; + return -1; } if (chat->connection_state == CS_DISCONNECTED) { SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_DISCONNECTED); tox_unlock(tox); - return false; + return -1; } - const int ret = gc_send_private_message(chat, gc_peer_id_from_int(peer_id), type, message, length); + uint32_t message_id = 0; + const int ret = gc_send_private_message(chat, gc_peer_id_from_int(peer_id), message_type, message, length, &message_id); tox_unlock(tox); switch (ret) { case 0: { SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_OK); - return true; + return message_id; } case -1: { SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_TOO_LONG); - return false; + return -1; } case -2: { SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_EMPTY); - return false; + return -1; } case -3: { SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PEER_NOT_FOUND); - return false; + return -1; } case -4: { SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_BAD_TYPE); - return false; + return -1; } case -5: { SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PERMISSIONS); - return false; + return -1; } case -6: { SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_FAIL_SEND); - return false; + return -1; } } /* can't happen */ LOGGER_FATAL(tox->m->log, "impossible return value: %d", ret); - return false; + return -1; } bool tox_group_send_custom_packet(const Tox *tox, uint32_t group_number, bool lossless, const uint8_t *data, @@ -4100,11 +4145,6 @@ bool tox_group_send_custom_packet(const Tox *tox, uint32_t group_number, bool lo } case -3: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_CUSTOM_PACKET_PERMISSIONS); - return false; - } - - case -4: { SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_CUSTOM_PACKET_FAIL_SEND); return false; } @@ -4162,11 +4202,6 @@ bool tox_group_send_custom_private_packet(const Tox *tox, uint32_t group_number, } case -4: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_PERMISSIONS); - return false; - } - - case -5: { SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_FAIL_SEND); return false; } @@ -4241,6 +4276,11 @@ uint32_t tox_group_invite_accept(Tox *tox, uint32_t friend_number, const uint8_t { assert(tox != nullptr); + if (invite_data == nullptr || name == nullptr) { + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_INVITE_ACCEPT_NULL); + return UINT32_MAX; + } + tox_lock(tox); const int ret = gc_accept_invite(tox->m->group_handler, friend_number, invite_data, length, name, name_length, password, password_length); @@ -4278,7 +4318,7 @@ uint32_t tox_group_invite_accept(Tox *tox, uint32_t friend_number, const uint8_t } case -6: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_INVITE_ACCEPT_CORE); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_INVITE_ACCEPT_FRIEND_NOT_FOUND); return UINT32_MAX; } @@ -4294,8 +4334,8 @@ uint32_t tox_group_invite_accept(Tox *tox, uint32_t friend_number, const uint8_t return UINT32_MAX; } -bool tox_group_founder_set_password(Tox *tox, uint32_t group_number, const uint8_t *password, size_t length, - Tox_Err_Group_Founder_Set_Password *error) +bool tox_group_set_password(Tox *tox, uint32_t group_number, const uint8_t *password, size_t length, + Tox_Err_Group_Set_Password *error) { assert(tox != nullptr); @@ -4303,13 +4343,13 @@ bool tox_group_founder_set_password(Tox *tox, uint32_t group_number, const uint8 GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number); if (chat == nullptr) { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_GROUP_NOT_FOUND); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PASSWORD_GROUP_NOT_FOUND); tox_unlock(tox); return false; } if (chat->connection_state == CS_DISCONNECTED) { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_DISCONNECTED); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PASSWORD_DISCONNECTED); tox_unlock(tox); return false; } @@ -4319,27 +4359,27 @@ bool tox_group_founder_set_password(Tox *tox, uint32_t group_number, const uint8 switch (ret) { case 0: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PASSWORD_OK); return true; } case -1: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_PERMISSIONS); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PASSWORD_PERMISSIONS); return false; } case -2: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_TOO_LONG); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PASSWORD_TOO_LONG); return false; } case -3: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_FAIL_SEND); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PASSWORD_FAIL_SEND); return false; } case -4: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_MALLOC); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PASSWORD_MALLOC); return false; } } @@ -4350,8 +4390,8 @@ bool tox_group_founder_set_password(Tox *tox, uint32_t group_number, const uint8 return false; } -bool tox_group_founder_set_privacy_state(Tox *tox, uint32_t group_number, Tox_Group_Privacy_State privacy_state, - Tox_Err_Group_Founder_Set_Privacy_State *error) +bool tox_group_set_privacy_state(Tox *tox, uint32_t group_number, Tox_Group_Privacy_State privacy_state, + Tox_Err_Group_Set_Privacy_State *error) { assert(tox != nullptr); @@ -4361,32 +4401,32 @@ bool tox_group_founder_set_privacy_state(Tox *tox, uint32_t group_number, Tox_Gr switch (ret) { case 0: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PRIVACY_STATE_OK); return true; } case -1: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_GROUP_NOT_FOUND); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PRIVACY_STATE_GROUP_NOT_FOUND); return false; } case -2: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_PERMISSIONS); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PRIVACY_STATE_PERMISSIONS); return false; } case -3: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_DISCONNECTED); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PRIVACY_STATE_DISCONNECTED); return false; } case -4: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SET); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PRIVACY_STATE_FAIL_SET); return false; } case -5: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SEND); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PRIVACY_STATE_FAIL_SEND); return false; } } @@ -4397,8 +4437,8 @@ bool tox_group_founder_set_privacy_state(Tox *tox, uint32_t group_number, Tox_Gr return false; } -bool tox_group_founder_set_topic_lock(Tox *tox, uint32_t group_number, Tox_Group_Topic_Lock topic_lock, - Tox_Err_Group_Founder_Set_Topic_Lock *error) +bool tox_group_set_topic_lock(Tox *tox, uint32_t group_number, Tox_Group_Topic_Lock topic_lock, + Tox_Err_Group_Set_Topic_Lock *error) { assert(tox != nullptr); @@ -4408,37 +4448,37 @@ bool tox_group_founder_set_topic_lock(Tox *tox, uint32_t group_number, Tox_Group switch (ret) { case 0: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_TOPIC_LOCK_OK); return true; } case -1: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_GROUP_NOT_FOUND); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_TOPIC_LOCK_GROUP_NOT_FOUND); return false; } case -2: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_INVALID); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_TOPIC_LOCK_INVALID); return false; } case -3: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_PERMISSIONS); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_TOPIC_LOCK_PERMISSIONS); return false; } case -4: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_DISCONNECTED); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_TOPIC_LOCK_DISCONNECTED); return false; } case -5: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_FAIL_SET); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_TOPIC_LOCK_FAIL_SET); return false; } case -6: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_FAIL_SEND); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_TOPIC_LOCK_FAIL_SEND); return false; } } @@ -4449,8 +4489,8 @@ bool tox_group_founder_set_topic_lock(Tox *tox, uint32_t group_number, Tox_Group return false; } -bool tox_group_founder_set_voice_state(Tox *tox, uint32_t group_number, Tox_Group_Voice_State voice_state, - Tox_Err_Group_Founder_Set_Voice_State *error) +bool tox_group_set_voice_state(Tox *tox, uint32_t group_number, Tox_Group_Voice_State voice_state, + Tox_Err_Group_Set_Voice_State *error) { assert(tox != nullptr); @@ -4460,32 +4500,32 @@ bool tox_group_founder_set_voice_state(Tox *tox, uint32_t group_number, Tox_Grou switch (ret) { case 0: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_OK); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_VOICE_STATE_OK); return true; } case -1: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_GROUP_NOT_FOUND); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_VOICE_STATE_GROUP_NOT_FOUND); return false; } case -2: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_PERMISSIONS); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_VOICE_STATE_PERMISSIONS); return false; } case -3: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_DISCONNECTED); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_VOICE_STATE_DISCONNECTED); return false; } case -4: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_FAIL_SET); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_VOICE_STATE_FAIL_SET); return false; } case -5: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_FAIL_SEND); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_VOICE_STATE_FAIL_SEND); return false; } } @@ -4496,8 +4536,8 @@ bool tox_group_founder_set_voice_state(Tox *tox, uint32_t group_number, Tox_Grou return false; } -bool tox_group_founder_set_peer_limit(Tox *tox, uint32_t group_number, uint16_t peer_limit, - Tox_Err_Group_Founder_Set_Peer_Limit *error) +bool tox_group_set_peer_limit(Tox *tox, uint32_t group_number, uint16_t peer_limit, + Tox_Err_Group_Set_Peer_Limit *error) { assert(tox != nullptr); @@ -4505,13 +4545,13 @@ bool tox_group_founder_set_peer_limit(Tox *tox, uint32_t group_number, uint16_t GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number); if (chat == nullptr) { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_GROUP_NOT_FOUND); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PEER_LIMIT_GROUP_NOT_FOUND); tox_unlock(tox); return false; } if (chat->connection_state == CS_DISCONNECTED) { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_DISCONNECTED); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PEER_LIMIT_DISCONNECTED); tox_unlock(tox); return false; } @@ -4521,22 +4561,22 @@ bool tox_group_founder_set_peer_limit(Tox *tox, uint32_t group_number, uint16_t switch (ret) { case 0: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PEER_LIMIT_OK); return true; } case -1: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_PERMISSIONS); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PEER_LIMIT_PERMISSIONS); return false; } case -2: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SET); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PEER_LIMIT_FAIL_SET); return false; } case -3: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SEND); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PEER_LIMIT_FAIL_SEND); return false; } } @@ -4587,8 +4627,8 @@ bool tox_group_set_ignore(Tox *tox, uint32_t group_number, uint32_t peer_id, boo return false; } -bool tox_group_mod_set_role(Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Group_Role role, - Tox_Err_Group_Mod_Set_Role *error) +bool tox_group_set_role(Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Group_Role role, + Tox_Err_Group_Set_Role *error) { assert(tox != nullptr); @@ -4598,37 +4638,37 @@ bool tox_group_mod_set_role(Tox *tox, uint32_t group_number, uint32_t peer_id, T switch (ret) { case 0: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_SET_ROLE_OK); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_ROLE_OK); return true; } case -1: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_SET_ROLE_GROUP_NOT_FOUND); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_ROLE_GROUP_NOT_FOUND); return false; } case -2: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_SET_ROLE_PEER_NOT_FOUND); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_ROLE_PEER_NOT_FOUND); return false; } case -3: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_ROLE_PERMISSIONS); return false; } case -4: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_SET_ROLE_ASSIGNMENT); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_ROLE_ASSIGNMENT); return false; } case -5: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_SET_ROLE_FAIL_ACTION); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_ROLE_FAIL_ACTION); return false; } case -6: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_SET_ROLE_SELF); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_ROLE_SELF); return false; } } @@ -4639,8 +4679,8 @@ bool tox_group_mod_set_role(Tox *tox, uint32_t group_number, uint32_t peer_id, T return false; } -bool tox_group_mod_kick_peer(const Tox *tox, uint32_t group_number, uint32_t peer_id, - Tox_Err_Group_Mod_Kick_Peer *error) +bool tox_group_kick_peer(const Tox *tox, uint32_t group_number, uint32_t peer_id, + Tox_Err_Group_Kick_Peer *error) { assert(tox != nullptr); @@ -4650,37 +4690,37 @@ bool tox_group_mod_kick_peer(const Tox *tox, uint32_t group_number, uint32_t pee switch (ret) { case 0: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_KICK_PEER_OK); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_KICK_PEER_OK); return true; } case -1: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_KICK_PEER_GROUP_NOT_FOUND); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_KICK_PEER_GROUP_NOT_FOUND); return false; } case -2: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_KICK_PEER_PEER_NOT_FOUND); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_KICK_PEER_PEER_NOT_FOUND); return false; } case -3: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_KICK_PEER_PERMISSIONS); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_KICK_PEER_PERMISSIONS); return false; } case -4: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_KICK_PEER_FAIL_ACTION); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_KICK_PEER_FAIL_ACTION); return false; } case -5: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_KICK_PEER_FAIL_SEND); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_KICK_PEER_FAIL_SEND); return false; } case -6: { - SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_KICK_PEER_SELF); + SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_KICK_PEER_SELF); return false; } } diff --git a/protocols/Tox/libtox/src/toxcore/tox.h b/protocols/Tox/libtox/src/toxcore/tox.h index fa887fc779..f44b8201ac 100644 --- a/protocols/Tox/libtox/src/toxcore/tox.h +++ b/protocols/Tox/libtox/src/toxcore/tox.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ @@ -25,9 +25,8 @@ * could not perform any operation, because one of the required parameters was * NULL. Some functions operate correctly or are defined as effectless on NULL. * - * Some functions additionally return a value outside their - * return type domain, or a bool containing true on success and false on - * failure. + * Some functions additionally return a value outside their return type domain, + * or a bool containing true on success and false on failure. * * All functions that take a Tox instance pointer will cause undefined behaviour * when passed a NULL Tox pointer. @@ -52,17 +51,9 @@ * event listeners, it needs to implement the dispatch functionality itself. * * The last argument to a callback is the user data pointer. It is passed from - * tox_iterate to each callback in sequence. - * - * The user data pointer is never stored or dereferenced by any library code, so - * can be any pointer, including NULL. Callbacks must all operate on the same - * object type. In the apidsl code (tox.in.h), this is denoted with `any`. The - * `any` in tox_iterate must be the same `any` as in all callbacks. In C, - * lacking parametric polymorphism, this is a pointer to void. - * - * Old style callbacks that are registered together with a user data pointer - * receive that pointer as argument when they are called. They can each have - * their own user data pointer of their own type. + * tox_iterate to each callback in sequence. The user data pointer is never + * stored or dereferenced by any library code, so can be any pointer, including + * NULL. * * @section threading Threading implications * @@ -96,6 +87,13 @@ * If any other thread calls tox_self_set_name while this thread is allocating * memory, the length may have become invalid, and the call to * tox_self_get_name may cause undefined behaviour. + * + * @section deprecations + * + * Some functions and types are deprecated. We recommend compiling with + * `-DTOX_HIDE_DEPRECATED` to hide them. They will be removed in the next major + * version of Tox (and since we're in major version 0, that means the next + * minor version). */ #ifndef C_TOXCORE_TOXCORE_TOX_H #define C_TOXCORE_TOXCORE_TOX_H @@ -104,14 +102,14 @@ #include <stddef.h> #include <stdint.h> +#include "tox_options.h" // IWYU pragma: export + #ifdef __cplusplus extern "C" { #endif /** @{ @namespace tox */ -#ifndef TOX_DEFINED -#define TOX_DEFINED /** * @brief The Tox instance type. * @@ -122,7 +120,6 @@ extern "C" { * limiting factor is the number of usable ports on a device. */ typedef struct Tox Tox; -#endif /* TOX_DEFINED */ /** @{ * @name API version @@ -157,7 +154,7 @@ uint32_t tox_version_minor(void); * Incremented when bugfixes are applied without changing any functionality or * API or ABI. */ -#define TOX_VERSION_PATCH 18 +#define TOX_VERSION_PATCH 21 uint32_t tox_version_patch(void); @@ -206,7 +203,7 @@ bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch); * * The values of these are not part of the ABI. Prefer to use the function * versions of them for code that should remain compatible with future versions - * of toxcore. + * of the Tox library. */ /** @@ -283,7 +280,7 @@ uint32_t tox_max_status_message_length(void); * * @deprecated The macro will be removed in 0.3.0. Use the function instead. */ -#define TOX_MAX_FRIEND_REQUEST_LENGTH 1016 +#define TOX_MAX_FRIEND_REQUEST_LENGTH 921 uint32_t tox_max_friend_request_length(void); @@ -396,431 +393,6 @@ const char *tox_message_type_to_string(Tox_Message_Type value); /** @} */ /** @{ - * @name Startup options - */ - -/** - * @brief Type of proxy used to connect to TCP relays. - */ -typedef enum Tox_Proxy_Type { - - /** - * Don't use a proxy. - */ - TOX_PROXY_TYPE_NONE, - - /** - * HTTP proxy using CONNECT. - */ - TOX_PROXY_TYPE_HTTP, - - /** - * SOCKS proxy for simple socket pipes. - */ - TOX_PROXY_TYPE_SOCKS5, - -} Tox_Proxy_Type; - -const char *tox_proxy_type_to_string(Tox_Proxy_Type value); - -/** - * @brief Type of savedata to create the Tox instance from. - */ -typedef enum Tox_Savedata_Type { - - /** - * No savedata. - */ - TOX_SAVEDATA_TYPE_NONE, - - /** - * Savedata is one that was obtained from tox_get_savedata. - */ - TOX_SAVEDATA_TYPE_TOX_SAVE, - - /** - * Savedata is a secret key of length TOX_SECRET_KEY_SIZE. - */ - TOX_SAVEDATA_TYPE_SECRET_KEY, - -} Tox_Savedata_Type; - -const char *tox_savedata_type_to_string(Tox_Savedata_Type value); - -/** - * @brief Severity level of log messages. - */ -typedef enum Tox_Log_Level { - - /** - * Very detailed traces including all network activity. - */ - TOX_LOG_LEVEL_TRACE, - - /** - * Debug messages such as which port we bind to. - */ - TOX_LOG_LEVEL_DEBUG, - - /** - * Informational log messages such as video call status changes. - */ - TOX_LOG_LEVEL_INFO, - - /** - * Warnings about events_alloc inconsistency or logic errors. - */ - TOX_LOG_LEVEL_WARNING, - - /** - * Severe unexpected errors caused by external or events_alloc inconsistency. - */ - TOX_LOG_LEVEL_ERROR, - -} Tox_Log_Level; - -const char *tox_log_level_to_string(Tox_Log_Level value); - -/** - * @brief This event is triggered when the toxcore library logs an events_alloc message. - * - * This is mostly useful for debugging. This callback can be called from any - * function, not just tox_iterate. This means the user data lifetime must at - * least extend between registering and unregistering it or tox_kill. - * - * Other toxcore modules such as toxav may concurrently call this callback at - * any time. Thus, user code must make sure it is equipped to handle concurrent - * execution, e.g. by employing appropriate mutex locking. - * - * When using the experimental_thread_safety option, no Tox API functions can - * be called from within the log callback. - * - * @param level The severity of the log message. - * @param file The source file from which the message originated. - * @param line The source line from which the message originated. - * @param func The function from which the message originated. - * @param message The log message. - * @param user_data The user data pointer passed to tox_new in options. - */ -typedef void tox_log_cb(Tox *tox, Tox_Log_Level level, const char *file, uint32_t line, const char *func, - const char *message, void *user_data); - -/** - * @brief Operating system functions used by Tox. - * - * This struct is opaque and generally shouldn't be used in clients, but in - * combination with tox_private.h, it allows tests to inject non-IO (hermetic) - * versions of low level network, RNG, and time keeping functions. - */ -typedef struct Tox_System Tox_System; - -/** - * @brief This struct contains all the startup options for Tox. - * - * You must tox_options_new to allocate an object of this type. - * - * WARNING: Although this struct happens to be visible in the API, it is - * effectively private. Do not allocate this yourself or access members - * directly, as it *will* break binary compatibility frequently. - * - * @deprecated The memory layout of this struct (size, alignment, and field - * order) is not part of the ABI. To remain compatible, prefer to use - * tox_options_new to allocate the object and accessor functions to set the - * members. The struct will become opaque (i.e. the definition will become - * private) in v0.3.0. - */ -typedef struct Tox_Options Tox_Options; -struct Tox_Options { - - /** - * The type of socket to create. - * - * If this is set to false, an IPv4 socket is created, which subsequently - * only allows IPv4 communication. - * If it is set to true, an IPv6 socket is created, allowing both IPv4 and - * IPv6 communication. - */ - bool ipv6_enabled; - - /** - * Enable the use of UDP communication when available. - * - * Setting this to false will force Tox to use TCP only. Communications will - * need to be relayed through a TCP relay node, potentially slowing them down. - * - * If a proxy is enabled, UDP will be disabled if either toxcore or the - * proxy don't support proxying UDP messages. - */ - bool udp_enabled; - - /** - * Enable local network peer discovery. - * - * Disabling this will cause Tox to not look for peers on the local network. - */ - bool local_discovery_enabled; - - /** - * Enable storing DHT announcements and forwarding corresponding requests. - * - * Disabling this will cause Tox to ignore the relevant packets. - */ - bool dht_announcements_enabled; - - /** - * Pass communications through a proxy. - */ - Tox_Proxy_Type proxy_type; - - /** - * The IP address or DNS name of the proxy to be used. - * - * If used, this must be non-NULL and be a valid DNS name. The name must not - * exceed TOX_MAX_HOSTNAME_LENGTH characters, and be in a NUL-terminated C string - * format (TOX_MAX_HOSTNAME_LENGTH includes the NUL byte). - * - * This member is ignored (it can be NULL) if proxy_type is TOX_PROXY_TYPE_NONE. - * - * The data pointed at by this member is owned by the user, so must - * outlive the options object. - */ - const char *proxy_host; - - /** - * The port to use to connect to the proxy server. - * - * Ports must be in the range (1, 65535). The value is ignored if - * proxy_type is TOX_PROXY_TYPE_NONE. - */ - uint16_t proxy_port; - - /** - * The start port of the inclusive port range to attempt to use. - * - * If both start_port and end_port are 0, the default port range will be - * used: `[33445, 33545]`. - * - * If either start_port or end_port is 0 while the other is non-zero, the - * non-zero port will be the only port in the range. - * - * Having start_port > end_port will yield the same behavior as if start_port - * and end_port were swapped. - */ - uint16_t start_port; - - /** - * The end port of the inclusive port range to attempt to use. - */ - uint16_t end_port; - - /** - * The port to use for the TCP server (relay). If 0, the TCP server is - * disabled. - * - * Enabling it is not required for Tox to function properly. - * - * When enabled, your Tox instance can act as a TCP relay for other Tox - * instance. This leads to increased traffic, thus when writing a client - * it is recommended to enable TCP server only if the user has an option - * to disable it. - */ - uint16_t tcp_port; - - /** - * Enables or disables UDP hole-punching in toxcore. (Default: enabled). - */ - bool hole_punching_enabled; - - /** - * The type of savedata to load from. - */ - Tox_Savedata_Type savedata_type; - - /** - * The savedata. - * - * The data pointed at by this member is owned by the user, so must - * outlive the options object. - */ - const uint8_t *savedata_data; - - /** - * The length of the savedata. - */ - size_t savedata_length; - - /** - * Logging callback for the new tox instance. - */ - tox_log_cb *log_callback; - - /** - * User data pointer passed to the logging callback. - */ - void *log_user_data; - - /** - * These options are experimental, so avoid writing code that depends on - * them. Options marked "experimental" may change their behaviour or go away - * entirely in the future, or may be renamed to something non-experimental - * if they become part of the supported API. - */ - /** - * Make public API functions thread-safe using a per-instance lock. - * - * Default: false. - */ - bool experimental_thread_safety; - - /** - * Low level operating system functionality such as send/recv, random - * number generation, and memory allocation. - */ - const Tox_System *operating_system; - - /** - * Enable saving DHT-based group chats to Tox save data (via `tox_get_savedata`). - * This format will change in the future, so don't rely on it. - * - * As an alternative, clients can save the group chat ID in client-owned - * savedata. Then, when the client starts, it can use `tox_group_join` - * with the saved chat ID to recreate the group chat. - * - * Default: false. - */ - bool experimental_groups_persistence; -}; - -bool tox_options_get_ipv6_enabled(const Tox_Options *options); - -void tox_options_set_ipv6_enabled(Tox_Options *options, bool ipv6_enabled); - -bool tox_options_get_udp_enabled(const Tox_Options *options); - -void tox_options_set_udp_enabled(Tox_Options *options, bool udp_enabled); - -bool tox_options_get_local_discovery_enabled(const Tox_Options *options); - -void tox_options_set_local_discovery_enabled(Tox_Options *options, bool local_discovery_enabled); - -bool tox_options_get_dht_announcements_enabled(const Tox_Options *options); - -void tox_options_set_dht_announcements_enabled(Tox_Options *options, bool dht_announcements_enabled); - -Tox_Proxy_Type tox_options_get_proxy_type(const Tox_Options *options); - -void tox_options_set_proxy_type(Tox_Options *options, Tox_Proxy_Type proxy_type); - -const char *tox_options_get_proxy_host(const Tox_Options *options); - -void tox_options_set_proxy_host(Tox_Options *options, const char *proxy_host); - -uint16_t tox_options_get_proxy_port(const Tox_Options *options); - -void tox_options_set_proxy_port(Tox_Options *options, uint16_t proxy_port); - -uint16_t tox_options_get_start_port(const Tox_Options *options); - -void tox_options_set_start_port(Tox_Options *options, uint16_t start_port); - -uint16_t tox_options_get_end_port(const Tox_Options *options); - -void tox_options_set_end_port(Tox_Options *options, uint16_t end_port); - -uint16_t tox_options_get_tcp_port(const Tox_Options *options); - -void tox_options_set_tcp_port(Tox_Options *options, uint16_t tcp_port); - -bool tox_options_get_hole_punching_enabled(const Tox_Options *options); - -void tox_options_set_hole_punching_enabled(Tox_Options *options, bool hole_punching_enabled); - -Tox_Savedata_Type tox_options_get_savedata_type(const Tox_Options *options); - -void tox_options_set_savedata_type(Tox_Options *options, Tox_Savedata_Type savedata_type); - -const uint8_t *tox_options_get_savedata_data(const Tox_Options *options); - -void tox_options_set_savedata_data(Tox_Options *options, const uint8_t savedata_data[], size_t length); - -size_t tox_options_get_savedata_length(const Tox_Options *options); - -void tox_options_set_savedata_length(Tox_Options *options, size_t savedata_length); - -tox_log_cb *tox_options_get_log_callback(const Tox_Options *options); - -void tox_options_set_log_callback(Tox_Options *options, tox_log_cb *log_callback); - -void *tox_options_get_log_user_data(const Tox_Options *options); - -void tox_options_set_log_user_data(Tox_Options *options, void *log_user_data); - -bool tox_options_get_experimental_thread_safety(const Tox_Options *options); - -void tox_options_set_experimental_thread_safety(Tox_Options *options, bool experimental_thread_safety); - -const Tox_System *tox_options_get_operating_system(const Tox_Options *options); - -void tox_options_set_operating_system(Tox_Options *options, const Tox_System *operating_system); - -bool tox_options_get_experimental_groups_persistence(const Tox_Options *options); - -void tox_options_set_experimental_groups_persistence(Tox_Options *options, bool experimental_groups_persistence); - -/** - * @brief Initialises a Tox_Options object with the default options. - * - * The result of this function is independent of the original options. All - * values will be overwritten, no values will be read (so it is permissible - * to pass an uninitialised object). - * - * If options is NULL, this function has no effect. - * - * @param options An options object to be filled with default options. - */ -void tox_options_default(Tox_Options *options); - -typedef enum Tox_Err_Options_New { - - /** - * The function returned successfully. - */ - TOX_ERR_OPTIONS_NEW_OK, - - /** - * The function failed to allocate enough memory for the options struct. - */ - TOX_ERR_OPTIONS_NEW_MALLOC, - -} Tox_Err_Options_New; - -const char *tox_err_options_new_to_string(Tox_Err_Options_New value); - -/** - * @brief Allocates a new Tox_Options object and initialises it with the default - * options. - * - * This function can be used to preserve long term ABI compatibility by - * giving the responsibility of allocation and deallocation to the Tox library. - * - * Objects returned from this function must be freed using the tox_options_free - * function. - * - * @return A new Tox_Options object with default options or NULL on failure. - */ -Tox_Options *tox_options_new(Tox_Err_Options_New *error); - -/** - * @brief Releases all resources associated with an options objects. - * - * Passing a pointer that was not returned by tox_options_new results in - * undefined behaviour. - */ -void tox_options_free(Tox_Options *options); - -/** @} */ - -/** @{ * @name Creation and destruction */ @@ -837,15 +409,16 @@ typedef enum Tox_Err_New { TOX_ERR_NEW_NULL, /** - * The function was unable to allocate enough memory to store the events_alloc - * structures for the Tox object. + * The function was unable to allocate enough memory to store the + * internal structures for the Tox object. */ TOX_ERR_NEW_MALLOC, /** * The function was unable to bind to a port. This may mean that all ports * have already been bound, e.g. by other Tox instances, or it may mean - * a permission error. You may be able to gather more information from errno. + * a permission error. You may be able to gather more information from + * errno. */ TOX_ERR_NEW_PORT_ALLOC, @@ -913,7 +486,7 @@ Tox *tox_new(const Tox_Options *options, Tox_Err_New *error); void tox_kill(Tox *tox); /** - * @brief Calculates the number of bytes required to store the tox instance with + * @brief Calculates the number of bytes required to store the Tox instance with * tox_get_savedata. * * This function cannot fail. The result is always greater than 0. @@ -923,11 +496,12 @@ void tox_kill(Tox *tox); size_t tox_get_savedata_size(const Tox *tox); /** - * @brief Store all information associated with the tox instance to a byte array. + * @brief Store all information associated with the Tox instance to a byte + * array. * - * @param savedata A memory region large enough to store the tox instance - * data. Call tox_get_savedata_size to find the number of bytes required. If this parameter - * is NULL, this function has no effect. + * @param savedata A memory region large enough to store the Tox instance + * data. Call tox_get_savedata_size to find the number of bytes required. If + * this parameter is NULL, this function has no effect. */ void tox_get_savedata(const Tox *tox, uint8_t savedata[]); @@ -966,7 +540,7 @@ typedef enum Tox_Err_Bootstrap { const char *tox_err_bootstrap_to_string(Tox_Err_Bootstrap value); /** - * @brief Sends a "get nodes" request to the given bootstrap node with IP, port, + * @brief Sends a "nodes request" to the given bootstrap node with IP, port, * and public key to setup connections. * * This function will attempt to connect to the node using UDP. You must use @@ -1065,14 +639,16 @@ typedef void tox_self_connection_status_cb(Tox *tox, Tox_Connection connection_s void tox_callback_self_connection_status(Tox *tox, tox_self_connection_status_cb *callback); /** - * @brief Return the time in milliseconds before `tox_iterate()` should be called again - * for optimal performance. + * @brief Return the time in milliseconds before `tox_iterate()` should be + * called again for optimal performance. */ uint32_t tox_iteration_interval(const Tox *tox); /** - * @brief The main loop that needs to be run in intervals of `tox_iteration_interval()` - * milliseconds. + * @brief The main loop that needs to be run in intervals of + * `tox_iteration_interval()` milliseconds. + * @param user_data Any pointer a client wishes the Tox instance to pass into + * the event callbacks, including NULL. */ void tox_iterate(Tox *tox, void *user_data); @@ -1172,7 +748,8 @@ const char *tox_err_set_info_to_string(Tox_Err_Set_Info value); bool tox_self_set_name(Tox *tox, const uint8_t name[], size_t length, Tox_Err_Set_Info *error); /** - * @brief Return the length of the current nickname as passed to tox_self_set_name. + * @brief Return the length of the current nickname as passed to + * tox_self_set_name. * * If no nickname was set before calling this function, the name is empty, * and this function returns 0. @@ -1206,7 +783,8 @@ bool tox_self_set_status_message( Tox *tox, const uint8_t status_message[], size_t length, Tox_Err_Set_Info *error); /** - * @brief Return the length of the current status message as passed to tox_self_set_status_message. + * @brief Return the length of the current status message as passed to + * tox_self_set_status_message. * * If no status message was set before calling this function, the status * is empty, and this function returns 0. @@ -1216,13 +794,14 @@ bool tox_self_set_status_message( size_t tox_self_get_status_message_size(const Tox *tox); /** - * @brief Write the status message set by tox_self_set_status_message to a byte array. + * @brief Write the status message set by tox_self_set_status_message to a byte + * array. * * If no status message was set before calling this function, the status is * empty, and this function has no effect. * - * Call tox_self_get_status_message_size to find out how much memory to allocate for - * the result. + * Call tox_self_get_status_message_size to find out how much memory to allocate + * for the result. * * @param status_message A valid memory location large enough to hold the * status message. If this parameter is NULL, the function has no effect. @@ -1279,8 +858,8 @@ typedef enum Tox_Err_Friend_Add { TOX_ERR_FRIEND_ADD_OWN_KEY, /** - * A friend request has already been sent, or the address belongs to a friend - * that is already on the friend list. + * A friend request has already been sent, or the address belongs to a + * friend that is already on the friend list. */ TOX_ERR_FRIEND_ADD_ALREADY_SENT, @@ -1360,7 +939,8 @@ typedef enum Tox_Err_Friend_Delete { TOX_ERR_FRIEND_DELETE_OK, /** - * There was no friend with the given friend number. No friends were deleted. + * There was no friend with the given friend number. No friends were + * deleted. */ TOX_ERR_FRIEND_DELETE_FRIEND_NOT_FOUND, @@ -1411,14 +991,15 @@ const char *tox_err_friend_by_public_key_to_string(Tox_Err_Friend_By_Public_Key /** * @brief Return the friend number associated with that Public Key. * - * @return the friend number on success, an unspecified value on failure. * @param public_key A byte array containing the Public Key. + * + * @return the friend number on success, an unspecified value on failure. */ Tox_Friend_Number tox_friend_by_public_key(const Tox *tox, const uint8_t public_key[TOX_PUBLIC_KEY_SIZE], Tox_Err_Friend_By_Public_Key *error); /** - * @brief Checks if a friend with the given friend number exists and returns true if - * it does. + * @brief Checks if a friend with the given friend number exists and returns + * true if it does. */ bool tox_friend_exists(const Tox *tox, Tox_Friend_Number friend_number); @@ -1433,7 +1014,8 @@ size_t tox_self_get_friend_list_size(const Tox *tox); /** * @brief Copy a list of valid friend numbers into an array. * - * Call tox_self_get_friend_list_size to determine the number of elements to allocate. + * Call tox_self_get_friend_list_size to determine the number of elements to + * allocate. * * @param friend_list A memory region with enough space to hold the friend * list. If this parameter is NULL, this function has no effect. @@ -1457,7 +1039,8 @@ typedef enum Tox_Err_Friend_Get_Public_Key { const char *tox_err_friend_get_public_key_to_string(Tox_Err_Friend_Get_Public_Key value); /** - * @brief Copies the Public Key associated with a given friend number to a byte array. + * @brief Copies the Public Key associated with a given friend number to a byte + * array. * * @param friend_number The friend number you want the Public Key of. * @param public_key A memory region of at least TOX_PUBLIC_KEY_SIZE bytes. If @@ -1486,8 +1069,8 @@ typedef enum Tox_Err_Friend_Get_Last_Online { const char *tox_err_friend_get_last_online_to_string(Tox_Err_Friend_Get_Last_Online value); /** - * @brief Return a unix-time timestamp of the last time the friend associated with a given - * friend number was seen online. + * @brief Return a unix-time timestamp of the last time the friend associated + * with a given friend number was seen online. * * This function will return UINT64_MAX on error. * @@ -1514,8 +1097,9 @@ typedef enum Tox_Err_Friend_Query { /** * The pointer parameter for storing the query result (name, message) was - * NULL. Unlike the `_self_` variants of these functions, which have no effect - * when a parameter is NULL, these functions return an error in that case. + * NULL. Unlike the `_self_` variants of these functions, which have no + * effect when a parameter is NULL, these functions return an error in that + * case. */ TOX_ERR_FRIEND_QUERY_NULL, @@ -1540,8 +1124,8 @@ size_t tox_friend_get_name_size( const Tox *tox, Tox_Friend_Number friend_number, Tox_Err_Friend_Query *error); /** - * @brief Write the name of the friend designated by the given friend number to a byte - * array. + * @brief Write the name of the friend designated by the given friend number to + * a byte array. * * Call tox_friend_get_name_size to determine the allocation size for the `name` * parameter. @@ -1579,22 +1163,23 @@ void tox_callback_friend_name(Tox *tox, tox_friend_name_cb *callback); /** * @brief Return the length of the friend's status message. * - * If the friend number isinvalid, the return value is SIZE_MAX. + * If the friend number is invalid, the return value is SIZE_MAX. */ size_t tox_friend_get_status_message_size( const Tox *tox, Tox_Friend_Number friend_number, Tox_Err_Friend_Query *error); /** - * @brief Write the status message of the friend designated by the given friend number to a byte - * array. + * @brief Write the status message of the friend designated by the given friend + * number to a byte array. * - * Call tox_friend_get_status_message_size to determine the allocation size for the `status_message` - * parameter. + * Call tox_friend_get_status_message_size to determine the allocation size for + * the `status_message` parameter. * - * The data written to `status_message` is equal to the data received by the last - * `friend_status_message` callback. + * The data written to `status_message` is equal to the data received by the + * last `friend_status_message` callback. * - * @param status_message A valid memory region large enough to store the friend's status message. + * @param status_message A valid memory region large enough to store the + * friend's status message. */ bool tox_friend_get_status_message( const Tox *tox, Tox_Friend_Number friend_number, uint8_t status_message[], @@ -1604,7 +1189,8 @@ bool tox_friend_get_status_message( * @param friend_number The friend number of the friend whose status message * changed. * @param message A byte array containing the same data as - * tox_friend_get_status_message would write to its `status_message` parameter. + * tox_friend_get_status_message would write to its `status_message` + * parameter. * @param length A value equal to the return value of * tox_friend_get_status_message_size. */ @@ -1814,7 +1400,8 @@ typedef uint32_t Tox_Friend_Message_Id; * then reassemble the fragments. Messages may not be empty. * * The return value of this function is the message ID. If a read receipt is - * received, the triggered `friend_read_receipt` event will be passed this message ID. + * received, the triggered `friend_read_receipt` event will be passed this + * message ID. * * Message IDs are unique per friend. The first message ID is 0. Message IDs are * incremented by 1 each time a message is sent. If UINT32_MAX messages were @@ -1831,7 +1418,8 @@ Tox_Friend_Message_Id tox_friend_send_message( const uint8_t message[], size_t length, Tox_Err_Friend_Send_Message *error); /** - * @param friend_number The friend number of the friend who received the message. + * @param friend_number The friend number of the friend who received the + * message. * @param message_id The message ID as returned from tox_friend_send_message * corresponding to the message sent. */ @@ -1875,6 +1463,7 @@ void tox_callback_friend_request(Tox *tox, tox_friend_request_cb *callback); /** * @param friend_number The friend number of the friend who sent the message. + * @param type The type of the message (normal, action, ...). * @param message The message data they sent. * @param length The size of the message byte array. */ @@ -1906,10 +1495,10 @@ typedef uint32_t Tox_File_Number; * primarily for validating cached avatars. This use is highly recommended to * avoid unnecessary avatar updates. * - * If hash is NULL or data is NULL while length is not 0 the function returns false, - * otherwise it returns true. + * If hash is NULL or data is NULL while length is not 0 the function returns + * false, otherwise it returns true. * - * This function is a wrapper to events_alloc message-digest functions. + * This function is a wrapper to internal message-digest functions. * * @param hash A valid memory location the hash data. It must be at least * TOX_HASH_LENGTH bytes in size. @@ -1923,17 +1512,17 @@ bool tox_hash(uint8_t hash[TOX_HASH_LENGTH], const uint8_t data[], size_t length /** * @brief A list of pre-defined file kinds. * - * Toxcore itself does not behave differently for different file kinds. These - * are a hint to the client telling it what use the sender intended for the - * file. The `kind` parameter in the send function and recv callback are + * The Tox library itself does not behave differently for different file kinds. + * These are a hint to the client telling it what use the sender intended for + * the file. The `kind` parameter in the send function and recv callback are * `uint32_t`, not Tox_File_Kind, because clients can invent their own file * kind. Unknown file kinds should be treated as TOX_FILE_KIND_DATA. */ enum Tox_File_Kind { /** - * Arbitrary file data. Clients can choose to handle it based on the file name - * or magic or any other way they choose. + * Arbitrary file data. Clients can choose to handle it based on the file + * name or magic or any other way they choose. */ TOX_FILE_KIND_DATA, @@ -1941,21 +1530,21 @@ enum Tox_File_Kind { * Avatar file_id. This consists of tox_hash(image). * Avatar data. This consists of the image data. * - * Avatars can be sent at any time the client wishes. Generally, a client will - * send the avatar to a friend when that friend comes online, and to all - * friends when the avatar changed. A client can save some traffic by - * remembering which friend received the updated avatar already and only send - * it if the friend has an out of date avatar. + * Avatars can be sent at any time the client wishes. Generally, a client + * will send the avatar to a friend when that friend comes online, and to + * all friends when the avatar changed. A client can save some traffic by + * remembering which friend received the updated avatar already and only + * send it if the friend has an out of date avatar. * * Clients who receive avatar send requests can reject it (by sending * TOX_FILE_CONTROL_CANCEL before any other controls), or accept it (by - * sending TOX_FILE_CONTROL_RESUME). The file_id of length TOX_HASH_LENGTH bytes - * (same length as TOX_FILE_ID_LENGTH) will contain the hash. A client can compare - * this hash with a saved hash and send TOX_FILE_CONTROL_CANCEL to terminate the avatar - * transfer if it matches. + * sending TOX_FILE_CONTROL_RESUME). The file_id of length TOX_HASH_LENGTH + * bytes (same length as TOX_FILE_ID_LENGTH) will contain the hash. A client + * can compare this hash with a saved hash and send TOX_FILE_CONTROL_CANCEL + * to terminate the avatar transfer if it matches. * - * When file_size is set to 0 in the transfer request it means that the client - * has no avatar. + * When file_size is set to 0 in the transfer request it means that the + * client has no avatar. */ TOX_FILE_KIND_AVATAR, @@ -1964,16 +1553,17 @@ enum Tox_File_Kind { typedef enum Tox_File_Control { /** - * Sent by the receiving side to accept a file send request. Also sent after a - * TOX_FILE_CONTROL_PAUSE command to continue sending or receiving. + * Sent by the receiving side to accept a file send request. Also sent after + * a TOX_FILE_CONTROL_PAUSE command to continue sending or receiving. */ TOX_FILE_CONTROL_RESUME, /** * Sent by clients to pause the file transfer. The initial state of a file - * transfer is always paused on the receiving side and running on the sending - * side. If both the sending and receiving side pause the transfer, then both - * need to send TOX_FILE_CONTROL_RESUME for the transfer to resume. + * transfer is always paused on the receiving side and running on the + * sending side. If both the sending and receiving side pause the transfer, + * then both need to send TOX_FILE_CONTROL_RESUME for the transfer to + * resume. */ TOX_FILE_CONTROL_PAUSE, @@ -2005,7 +1595,8 @@ typedef enum Tox_Err_File_Control { TOX_ERR_FILE_CONTROL_FRIEND_NOT_CONNECTED, /** - * No file transfer with the given file number was found for the given friend. + * No file transfer with the given file number was found for the given + * friend. */ TOX_ERR_FILE_CONTROL_NOT_FOUND, @@ -2089,7 +1680,8 @@ typedef enum Tox_Err_File_Seek { TOX_ERR_FILE_SEEK_FRIEND_NOT_CONNECTED, /** - * No file transfer with the given file number was found for the given friend. + * No file transfer with the given file number was found for the given + * friend. */ TOX_ERR_FILE_SEEK_NOT_FOUND, @@ -2113,7 +1705,8 @@ typedef enum Tox_Err_File_Seek { const char *tox_err_file_seek_to_string(Tox_Err_File_Seek value); /** - * @brief Sends a file seek control command to a friend for a given file transfer. + * @brief Sends a file seek control command to a friend for a given file + * transfer. * * This function can only be called to resume a file transfer right before * TOX_FILE_CONTROL_RESUME is sent. @@ -2144,7 +1737,8 @@ typedef enum Tox_Err_File_Get { TOX_ERR_FILE_GET_FRIEND_NOT_FOUND, /** - * No file transfer with the given file number was found for the given friend. + * No file transfer with the given file number was found for the given + * friend. */ TOX_ERR_FILE_GET_NOT_FOUND, @@ -2158,8 +1752,8 @@ const char *tox_err_file_get_to_string(Tox_Err_File_Get value); * @param friend_number The friend number of the friend the file is being * transferred to or received from. * @param file_number The friend-specific identifier for the file transfer. - * @param file_id A memory region of at least TOX_FILE_ID_LENGTH bytes. If - * this parameter is NULL, this function has no effect. + * @param file_id A memory region of at least TOX_FILE_ID_LENGTH bytes. If this + * parameter is NULL, this function has no effect. * * @return true on success. */ @@ -2202,8 +1796,8 @@ typedef enum Tox_Err_File_Send { TOX_ERR_FILE_SEND_NAME_TOO_LONG, /** - * Too many ongoing transfers. The maximum number of concurrent file transfers - * is 256 per friend per direction (sending and receiving). + * Too many ongoing transfers. The maximum number of concurrent file + * transfers is 256 per friend per direction (sending and receiving). */ TOX_ERR_FILE_SEND_TOO_MANY, @@ -2214,8 +1808,8 @@ const char *tox_err_file_send_to_string(Tox_Err_File_Send value); /** * @brief Send a file transmission request. * - * Maximum filename length is TOX_MAX_FILENAME_LENGTH bytes. The filename - * should generally just be a file name, not a path with directory names. + * Maximum filename length is TOX_MAX_FILENAME_LENGTH bytes. The filename should + * generally just be a file name, not a path with directory names. * * If a non-UINT64_MAX file size is provided, it can be used by both sides to * determine the sending progress. File size can be set to UINT64_MAX for @@ -2224,8 +1818,8 @@ const char *tox_err_file_send_to_string(Tox_Err_File_Send value); * File transmission occurs in chunks, which are requested through the * `file_chunk_request` event. * - * When a friend goes offline, all file transfers associated with the friend are - * purged from core. + * When a friend goes offline, all file transfers associated with the friend get + * purged. * * If the file contents change during a transfer, the behaviour is unspecified * in general. What will actually happen depends on the mode in which the file @@ -2234,15 +1828,16 @@ const char *tox_err_file_send_to_string(Tox_Err_File_Send value); * - If the file size was increased * - and sending mode was streaming (file_size = UINT64_MAX), the behaviour * will be as expected. - * - and sending mode was file (file_size != UINT64_MAX), the file_chunk_request - * callback will receive length = 0 when Core thinks the file transfer has - * finished. If the client remembers the file size as it was when sending the - * request, it will terminate the transfer normally. If the client re-reads the - * size, it will think the friend cancelled the transfer. + * - and sending mode was file (file_size != UINT64_MAX), the + * file_chunk_request callback will receive length = 0 when Tox thinks the + * file transfer has finished. If the client remembers the file size as it + * was when sending the request, it will terminate the transfer normally. If + * the client re-reads the size, it will think the friend cancelled the + * transfer. * - If the file size was decreased * - and sending mode was streaming, the behaviour is as expected. * - and sending mode was file, the callback will return 0 at the new - * (earlier) end-of-file, signalling to the friend that the transfer was + * (earlier) end-of-file, signaling to the friend that the transfer was * cancelled. * - If the file contents were modified * - at a position before the current read, the two files (local and remote) @@ -2255,19 +1850,20 @@ const char *tox_err_file_send_to_string(Tox_Err_File_Send value); * @param friend_number The friend number of the friend the file send request * should be sent to. * @param kind The meaning of the file to be sent. - * @param file_size Size in bytes of the file the client wants to send, UINT64_MAX if - * unknown or streaming. - * @param file_id A file identifier of length TOX_FILE_ID_LENGTH that can be used to - * uniquely identify file transfers across core restarts. If NULL, a random one will - * be generated by core. It can then be obtained by using `tox_file_get_file_id()`. + * @param file_size Size in bytes of the file the client wants to send, + * UINT64_MAX if unknown or streaming. + * @param file_id A file identifier of length TOX_FILE_ID_LENGTH that can be + * used to uniquely identify file transfers across Tox restarts. If NULL, a + * random one will be generated by the library. It can then be obtained by + * using `tox_file_get_file_id()`. * @param filename Name of the file. Does not need to be the actual name. This * name will be sent along with the file send request. * @param filename_length Size in bytes of the filename. * * @return A file number used as an identifier in subsequent callbacks. This * number is per friend. File numbers are reused after a transfer terminates. - * On failure, this function returns an unspecified value. Any pattern in file numbers - * should not be relied on. + * On failure, this function returns an unspecified value. Any pattern in file + * numbers should not be relied on. */ Tox_File_Number tox_file_send( Tox *tox, Tox_Friend_Number friend_number, uint32_t kind, uint64_t file_size, @@ -2297,20 +1893,23 @@ typedef enum Tox_Err_File_Send_Chunk { TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_CONNECTED, /** - * No file transfer with the given file number was found for the given friend. + * No file transfer with the given file number was found for the given + * friend. */ TOX_ERR_FILE_SEND_CHUNK_NOT_FOUND, /** * File transfer was found but isn't in a transferring state: (paused, done, - * broken, etc...) (happens only when not called from the request chunk callback). + * broken, etc...) (happens only when not called from the request chunk + * callback). */ TOX_ERR_FILE_SEND_CHUNK_NOT_TRANSFERRING, /** - * Attempted to send more or less data than requested. The requested data size is - * adjusted according to maximum transmission unit and the expected end of - * the file. Trying to send less or more than requested will return this error. + * Attempted to send more or less data than requested. The requested data + * size is adjusted according to maximum transmission unit and the expected + * end of the file. Trying to send less or more than requested will return + * this error. */ TOX_ERR_FILE_SEND_CHUNK_INVALID_LENGTH, @@ -2334,10 +1933,11 @@ const char *tox_err_file_send_chunk_to_string(Tox_Err_File_Send_Chunk value); * This function is called in response to the `file_chunk_request` callback. The * length parameter should be equal to the one received though the callback. * If it is zero, the transfer is assumed complete. For files with known size, - * Core will know that the transfer is complete after the last byte has been + * Tox will know that the transfer is complete after the last byte has been * received, so it is not necessary (though not harmful) to send a zero-length - * chunk to terminate. For streams, core will know that the transfer is finished - * if a chunk with length less than the length requested in the callback is sent. + * chunk to terminate. For streams, Tox will know that the transfer is finished + * if a chunk with length less than the length requested in the callback is + * sent. * * @param friend_number The friend number of the receiving friend for this file. * @param file_number The file transfer identifier returned by tox_file_send. @@ -2379,7 +1979,7 @@ typedef void tox_file_chunk_request_cb( * * Pass NULL to unset. * - * This event is triggered when Core is ready to send more file data. + * This event is triggered when Tox is ready to send more file data. */ void tox_callback_file_chunk_request(Tox *tox, tox_file_chunk_request_cb *callback); @@ -2458,6 +2058,7 @@ void tox_callback_file_recv_chunk(Tox *tox, tox_file_recv_chunk_cb *callback); typedef uint32_t Tox_Conference_Number; typedef uint32_t Tox_Conference_Peer_Number; +typedef uint32_t Tox_Conference_Offline_Peer_Number; /** * @brief Conference types for the conference_invite event. @@ -2465,7 +2066,8 @@ typedef uint32_t Tox_Conference_Peer_Number; typedef enum Tox_Conference_Type { /** - * Text-only conferences that must be accepted with the tox_conference_join function. + * Text-only conferences that must be accepted with the tox_conference_join + * function. */ TOX_CONFERENCE_TYPE_TEXT, @@ -2502,7 +2104,8 @@ typedef void tox_conference_invite_cb( void tox_callback_conference_invite(Tox *tox, tox_conference_invite_cb *callback); /** - * @param conference_number The conference number of the conference to which we have connected. + * @param conference_number The conference number of the conference to which we + * have connected. */ typedef void tox_conference_connected_cb(Tox *tox, Tox_Conference_Number conference_number, void *user_data); @@ -2555,7 +2158,8 @@ typedef void tox_conference_title_cb( * * This event is triggered when a peer changes the conference title. * - * If peer_number == UINT32_MAX, then author is unknown (e.g. initial joining the conference). + * If peer_number == UINT32_MAX, then author is unknown (e.g. initial joining + * the conference). */ void tox_callback_conference_title(Tox *tox, tox_conference_title_cb *callback); @@ -2640,7 +2244,8 @@ const char *tox_err_conference_delete_to_string(Tox_Err_Conference_Delete value) /** * @brief This function deletes a conference. * - * @param conference_number The conference number of the conference to be deleted. + * @param conference_number The conference number of the conference to be + * deleted. * * @return true on success. */ @@ -2682,7 +2287,7 @@ const char *tox_err_conference_peer_query_to_string(Tox_Err_Conference_Peer_Quer * peer_number for the functions querying these peers. Return value is * unspecified on failure. */ -Tox_Conference_Peer_Number tox_conference_peer_count( +uint32_t tox_conference_peer_count( const Tox *tox, Tox_Conference_Number conference_number, Tox_Err_Conference_Peer_Query *error); /** @@ -2697,7 +2302,8 @@ size_t tox_conference_peer_get_name_size( /** * @brief Copy the name of peer_number who is in conference_number to name. * - * Call tox_conference_peer_get_name_size to determine the allocation size for the `name` parameter. + * Call tox_conference_peer_get_name_size to determine the allocation size for + * the `name` parameter. * * @param name A valid memory region large enough to store the peer's name. * @@ -2708,7 +2314,8 @@ bool tox_conference_peer_get_name( uint8_t name[], Tox_Err_Conference_Peer_Query *error); /** - * @brief Copy the public key of peer_number who is in conference_number to public_key. + * @brief Copy the public key of peer_number who is in conference_number to + * public_key. * * public_key must be TOX_PUBLIC_KEY_SIZE long. * @@ -2744,10 +2351,11 @@ uint32_t tox_conference_offline_peer_count( */ size_t tox_conference_offline_peer_get_name_size( const Tox *tox, Tox_Conference_Number conference_number, - Tox_Conference_Peer_Number offline_peer_number, Tox_Err_Conference_Peer_Query *error); + Tox_Conference_Offline_Peer_Number offline_peer_number, Tox_Err_Conference_Peer_Query *error); /** - * @brief Copy the name of offline_peer_number who is in conference_number to name. + * @brief Copy the name of offline_peer_number who is in conference_number to + * name. * * Call tox_conference_offline_peer_get_name_size to determine the allocation * size for the `name` parameter. @@ -2757,11 +2365,12 @@ size_t tox_conference_offline_peer_get_name_size( * @return true on success. */ bool tox_conference_offline_peer_get_name( - const Tox *tox, Tox_Conference_Number conference_number, Tox_Conference_Peer_Number offline_peer_number, + const Tox *tox, Tox_Conference_Number conference_number, Tox_Conference_Offline_Peer_Number offline_peer_number, uint8_t name[], Tox_Err_Conference_Peer_Query *error); /** - * @brief Copy the public key of offline_peer_number who is in conference_number to public_key. + * @brief Copy the public key of offline_peer_number who is in conference_number + * to public_key. * * public_key must be TOX_PUBLIC_KEY_SIZE long. * @@ -2769,14 +2378,15 @@ bool tox_conference_offline_peer_get_name( */ bool tox_conference_offline_peer_get_public_key( const Tox *tox, Tox_Conference_Number conference_number, - Tox_Conference_Peer_Number offline_peer_number, uint8_t public_key[TOX_PUBLIC_KEY_SIZE], Tox_Err_Conference_Peer_Query *error); + Tox_Conference_Offline_Peer_Number offline_peer_number, uint8_t public_key[TOX_PUBLIC_KEY_SIZE], Tox_Err_Conference_Peer_Query *error); /** - * @brief Return a unix-time timestamp of the last time offline_peer_number was seen to be active. + * @brief Return a unix-time timestamp of the last time offline_peer_number was + * seen to be active. */ uint64_t tox_conference_offline_peer_get_last_active( const Tox *tox, Tox_Conference_Number conference_number, - Tox_Conference_Peer_Number offline_peer_number, Tox_Err_Conference_Peer_Query *error); + Tox_Conference_Offline_Peer_Number offline_peer_number, Tox_Err_Conference_Peer_Query *error); typedef enum Tox_Err_Conference_Set_Max_Offline { @@ -2831,7 +2441,8 @@ const char *tox_err_conference_invite_to_string(Tox_Err_Conference_Invite value) * @brief Invites a friend to a conference. * * @param friend_number The friend number of the friend we want to invite. - * @param conference_number The conference number of the conference we want to invite the friend to. + * @param conference_number The conference number of the conference we want to + * invite the friend to. * * @return true on success. */ @@ -2852,7 +2463,8 @@ typedef enum Tox_Err_Conference_Join { TOX_ERR_CONFERENCE_JOIN_INVALID_LENGTH, /** - * The conference is not the expected type. This indicates an invalid cookie. + * The conference is not the expected type. This indicates an invalid + * cookie. */ TOX_ERR_CONFERENCE_JOIN_WRONG_TYPE, @@ -2876,6 +2488,11 @@ typedef enum Tox_Err_Conference_Join { */ TOX_ERR_CONFERENCE_JOIN_FAIL_SEND, + /** + * The cookie passed was NULL. + */ + TOX_ERR_CONFERENCE_JOIN_NULL, + } Tox_Err_Conference_Join; const char *tox_err_conference_join_to_string(Tox_Err_Conference_Join value); @@ -2887,7 +2504,7 @@ const char *tox_err_conference_join_to_string(Tox_Err_Conference_Join value); * to it until a handshaking procedure has been completed. A * `conference_connected` event will then occur for the conference. The client * will then remain connected to the conference until the conference is deleted, - * even across core restarts. Many operations on a conference will fail with a + * even across Tox restarts. Many operations on a conference will fail with a * corresponding error if attempted on a conference to which the client is not * yet connected. * @@ -2995,9 +2612,11 @@ size_t tox_conference_get_title_size( const Tox *tox, Tox_Conference_Number conference_number, Tox_Err_Conference_Title *error); /** - * @brief Write the title designated by the given conference number to a byte array. + * @brief Write the title designated by the given conference number to a byte + * array. * - * Call tox_conference_get_title_size to determine the allocation size for the `title` parameter. + * Call tox_conference_get_title_size to determine the allocation size for the + * `title` parameter. * * The data written to `title` is equal to the data received by the last * `conference_title` callback. @@ -3013,7 +2632,8 @@ bool tox_conference_get_title( Tox_Err_Conference_Title *error); /** - * @brief Set the conference title and broadcast it to the rest of the conference. + * @brief Set the conference title and broadcast it to the rest of the + * conference. * * Title length cannot be longer than TOX_MAX_NAME_LENGTH. * @@ -3027,7 +2647,8 @@ bool tox_conference_set_title( /** * @brief Return the number of conferences in the Tox instance. * - * This should be used to determine how much memory to allocate for `tox_conference_get_chatlist`. + * This should be used to determine how much memory to allocate for + * `tox_conference_get_chatlist`. */ size_t tox_conference_get_chatlist_size(const Tox *tox); @@ -3037,8 +2658,8 @@ size_t tox_conference_get_chatlist_size(const Tox *tox); * Determine how much space to allocate for the array with the * `tox_conference_get_chatlist_size` function. * - * Note that `tox_get_savedata` saves all connected conferences; - * when toxcore is created from savedata in which conferences were saved, those + * Note that `tox_get_savedata` saves all connected conferences; when a Tox + * instance is created from savedata in which conferences were saved, those * conferences will be connected at startup, and will be listed by * `tox_conference_get_chatlist`. * @@ -3048,7 +2669,8 @@ size_t tox_conference_get_chatlist_size(const Tox *tox); void tox_conference_get_chatlist(const Tox *tox, Tox_Conference_Number chatlist[]); /** - * @brief Returns the type of conference (Tox_Conference_Type) that conference_number is. + * @brief Returns the type of conference (Tox_Conference_Type) that + * conference_number is. * * Return value is unspecified on failure. */ @@ -3118,18 +2740,22 @@ const char *tox_err_conference_by_id_to_string(Tox_Err_Conference_By_Id value); Tox_Conference_Number tox_conference_by_id( const Tox *tox, const uint8_t id[TOX_CONFERENCE_ID_SIZE], Tox_Err_Conference_By_Id *error); +#ifndef TOX_HIDE_DEPRECATED /** * @brief Get the conference unique ID. * * If uid is NULL, this function has no effect. * - * @param uid A memory region large enough to store TOX_CONFERENCE_UID_SIZE bytes. + * @param uid A memory region large enough to store TOX_CONFERENCE_UID_SIZE + * bytes. * * @return true on success. - * @deprecated use tox_conference_get_id instead (exactly the same function, just renamed). + * @deprecated use tox_conference_get_id instead (exactly the same function, + * just renamed). */ bool tox_conference_get_uid( const Tox *tox, Tox_Conference_Number conference_number, uint8_t uid[TOX_CONFERENCE_UID_SIZE]); +#endif /* TOX_HIDE_DEPRECATED */ typedef enum Tox_Err_Conference_By_Uid { @@ -3152,16 +2778,20 @@ typedef enum Tox_Err_Conference_By_Uid { const char *tox_err_conference_by_uid_to_string(Tox_Err_Conference_By_Uid value); +#ifndef TOX_HIDE_DEPRECATED /** * @brief Return the conference number associated with the specified uid. * - * @param uid A byte array containing the conference id (TOX_CONFERENCE_UID_SIZE). + * @param uid A byte array containing the conference id + * (TOX_CONFERENCE_UID_SIZE). * * @return the conference number on success, an unspecified value on failure. - * @deprecated use tox_conference_by_id instead (exactly the same function, just renamed). + * @deprecated use tox_conference_by_id instead (exactly the same function, + * just renamed). */ Tox_Conference_Number tox_conference_by_uid( const Tox *tox, const uint8_t uid[TOX_CONFERENCE_UID_SIZE], Tox_Err_Conference_By_Uid *error); +#endif /* TOX_HIDE_DEPRECATED */ /** @} */ @@ -3192,8 +2822,9 @@ typedef enum Tox_Err_Friend_Custom_Packet { TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_CONNECTED, /** - * The first byte of data was not in the specified range for the packet type. - * This range is 192-254 for lossy, and 69, 160-191 for lossless packets. + * The first byte of data was not one of the permitted values; + * for lossy packets the first byte must be in the range 192-254, + * and for lossless packets it must be either 69 or in the range 160-191. */ TOX_ERR_FRIEND_CUSTOM_PACKET_INVALID, @@ -3244,7 +2875,7 @@ bool tox_friend_send_lossy_packet( /** * @brief Send a custom lossless packet to a friend. * - * The first byte of data must be in the range 69, 160-191. Maximum length of a + * The first byte of data must be either 69 or in the range 160-191. Maximum length of a * custom packet is TOX_MAX_CUSTOM_PACKET_SIZE. * * Lossless packet behaviour is comparable to TCP (reliability, arrive in order) @@ -3263,6 +2894,9 @@ bool tox_friend_send_lossless_packet( Tox_Err_Friend_Custom_Packet *error); /** + * tox_callback_friend_lossy_packet is the compatibility function to + * set the callback for all packet IDs except those reserved for ToxAV. + * * @param friend_number The friend number of the friend who sent a lossy packet. * @param data A byte array containing the received packet data. * @param length The length of the packet data byte array. @@ -3322,7 +2956,8 @@ const char *tox_err_get_port_to_string(Tox_Err_Get_Port value); * @brief Writes the temporary DHT public key of this instance to a byte array. * * This can be used in combination with an externally accessible IP address and - * the bound port (from tox_self_get_udp_port) to run a temporary bootstrap node. + * the bound port (from tox_self_get_udp_port) to run a temporary bootstrap + * node. * * Be aware that every time a new instance is created, the DHT public key * changes, meaning this cannot be used to run a permanent bootstrap node. @@ -3435,22 +3070,24 @@ uint32_t tox_group_peer_public_key_size(void); typedef enum Tox_Group_Privacy_State { /** - * The group is considered to be public. Anyone may join the group using the Chat ID. + * The group is considered to be public. Anyone may join the group using + * the Chat ID. * - * If the group is in this state, even if the Chat ID is never explicitly shared - * with someone outside of the group, information including the Chat ID, IP addresses, - * and peer ID's (but not Tox ID's) is visible to anyone with access to a node - * storing a DHT entry for the given group. + * If the group is in this state, even if the Chat ID is never explicitly + * shared with someone outside of the group, information including the Chat + * ID, IP addresses, and peer ID's (but not Tox ID's) is visible to anyone + * with access to a node storing a DHT entry for the given group. */ TOX_GROUP_PRIVACY_STATE_PUBLIC, /** - * The group is considered to be private. The only way to join the group is by having - * someone in your contact list send you an invite. + * The group is considered to be private. The only way to join the group is + * by having someone in your contact list send you an invite. * - * If the group is in this state, no group information (mentioned above) is present in the DHT; - * the DHT is not used for any purpose at all. If a public group is set to private, - * all DHT information related to the group will expire shortly. + * If the group is in this state, no group information (mentioned above) is + * present in the DHT; the DHT is not used for any purpose at all. If a + * public group is set to private, all DHT information related to the group + * will expire shortly. */ TOX_GROUP_PRIVACY_STATE_PRIVATE, @@ -3460,16 +3097,20 @@ const char *tox_group_privacy_state_to_string(Tox_Group_Privacy_State value); /** * Represents the state of the group topic lock. + * + * The default is enabled. */ typedef enum Tox_Group_Topic_Lock { /** - * The topic lock is enabled. Only peers with the founder and moderator roles may set the topic. + * The topic lock is enabled. Only peers with the founder and moderator + * roles may set the topic. */ TOX_GROUP_TOPIC_LOCK_ENABLED, /** - * The topic lock is disabled. All peers except those with the observer role may set the topic. + * The topic lock is disabled. All peers except those with the observer role + * may set the topic. */ TOX_GROUP_TOPIC_LOCK_DISABLED, @@ -3478,8 +3119,9 @@ typedef enum Tox_Group_Topic_Lock { const char *tox_group_topic_lock_to_string(Tox_Group_Topic_Lock value); /** - * Represents the group voice state, which determines which Group Roles have permission to speak - * in the group chat. The voice state does not have any effect private messages or topic setting. + * Represents the group voice state, which determines which Group Roles have + * permission to speak in the group chat. The voice state does not have any + * effect private messages or topic setting. */ typedef enum Tox_Group_Voice_State { /** @@ -3503,14 +3145,15 @@ const char *tox_group_voice_state_to_string(Tox_Group_Voice_State value); /** * Represents group roles. * - * Roles are hierarchical in that each role has a set of privileges plus all the privileges - * of the roles below it. + * Roles are hierarchical in that each role has a set of privileges plus all the + * privileges of the roles below it. */ typedef enum Tox_Group_Role { /** - * May kick all other peers as well as set their role to anything (except founder). - * Founders may also set the group password, toggle the privacy state, and set the peer limit. + * May kick all other peers as well as set their role to anything (except + * founder). Founders may also set the group password, toggle the privacy + * state, and set the peer limit. */ TOX_GROUP_ROLE_FOUNDER, @@ -3526,7 +3169,8 @@ typedef enum Tox_Group_Role { TOX_GROUP_ROLE_USER, /** - * May observe the group and ignore peers; may not communicate with other peers or with the group. + * May observe the group and ignore peers; may not communicate with other + * peers or with the group. */ TOX_GROUP_ROLE_OBSERVER, @@ -3548,7 +3192,8 @@ typedef enum Tox_Err_Group_New { TOX_ERR_GROUP_NEW_OK, /** - * name exceeds TOX_MAX_NAME_LENGTH or group_name exceeded TOX_GROUP_MAX_GROUP_NAME_LENGTH. + * name exceeds TOX_MAX_NAME_LENGTH or group_name exceeded + * TOX_GROUP_MAX_GROUP_NAME_LENGTH. */ TOX_ERR_GROUP_NEW_TOO_LONG, @@ -3563,13 +3208,14 @@ typedef enum Tox_Err_Group_New { TOX_ERR_GROUP_NEW_INIT, /** - * The group state failed to initialize. This usually indicates that something went wrong - * related to cryptographic signing. + * The group state failed to initialize. This usually indicates that + * something went wrong related to cryptographic signing. */ TOX_ERR_GROUP_NEW_STATE, /** - * The group failed to announce to the DHT. This indicates a network related error. + * The group failed to announce to the DHT. This indicates a network related + * error. */ TOX_ERR_GROUP_NEW_ANNOUNCE, @@ -3584,18 +3230,19 @@ const char *tox_err_group_new_to_string(Tox_Err_Group_New value); * * The caller of this function has Founder role privileges. * - * The client should initiate its peer list with self info after calling this function, as - * the peer_join callback will not be triggered. + * The client should initiate its peer list with self info after calling this + * function, as the peer_join callback will not be triggered. * - * @param privacy_state The privacy state of the group. If this is set to TOX_GROUP_PRIVACY_STATE_PUBLIC, - * the group will attempt to announce itself to the DHT and anyone with the Chat ID may join. - * Otherwise a friend invite will be required to join the group. + * @param privacy_state The privacy state of the group. If this is set to + * TOX_GROUP_PRIVACY_STATE_PUBLIC, the group will attempt to announce itself + * to the DHT and anyone with the Chat ID may join. Otherwise a friend invite + * will be required to join the group. * @param group_name The name of the group. The name must be non-NULL. - * @param group_name_length The length of the group name. This must be greater than zero and no larger than - * TOX_GROUP_MAX_GROUP_NAME_LENGTH. + * @param group_name_length The length of the group name. This must be greater + * than zero and no larger than TOX_GROUP_MAX_GROUP_NAME_LENGTH. * @param name The name of the peer creating the group. - * @param name_length The length of the peer's name. This must be greater than zero and no larger - * than TOX_MAX_NAME_LENGTH. + * @param name_length The length of the peer's name. This must be greater than + * zero and no larger than TOX_MAX_NAME_LENGTH. * * @return group_number on success, UINT32_MAX on failure. */ @@ -3617,8 +3264,7 @@ typedef enum Tox_Err_Group_Join { TOX_ERR_GROUP_JOIN_INIT, /** - * The chat_id pointer is set to NULL or a group with chat_id already exists. This usually - * happens if the client attempts to create multiple sessions for the same group. + * The chat_id pointer is set to NULL. */ TOX_ERR_GROUP_JOIN_BAD_CHAT_ID, @@ -3633,7 +3279,8 @@ typedef enum Tox_Err_Group_Join { TOX_ERR_GROUP_JOIN_TOO_LONG, /** - * Failed to set password. This usually occurs if the password exceeds TOX_GROUP_MAX_PASSWORD_SIZE. + * Failed to set password. This usually occurs if the password exceeds + * TOX_GROUP_MAX_PASSWORD_SIZE. */ TOX_ERR_GROUP_JOIN_PASSWORD, @@ -3647,19 +3294,25 @@ typedef enum Tox_Err_Group_Join { const char *tox_err_group_join_to_string(Tox_Err_Group_Join value); /** - * Joins a group chat with specified Chat ID. + * Joins a group chat with specified Chat ID or reconnects to an existing group. * - * This function creates a new group chat object, adds it to the chats array, and sends - * a DHT announcement to find peers in the group associated with chat_id. Once a peer has been - * found a join attempt will be initiated. + * This function creates a new group chat object, adds it to the chats array, + * and sends a DHT announcement to find peers in the group associated with + * chat_id. Once a peer has been found a join attempt will be initiated. * - * @param chat_id The Chat ID of the group you wish to join. This must be TOX_GROUP_CHAT_ID_SIZE bytes. - * @param password The password required to join the group. Set to NULL if no password is required. - * @param password_length The length of the password. If length is equal to zero, - * the password parameter is ignored. length must be no larger than TOX_GROUP_MAX_PASSWORD_SIZE. + * If a group with the specified Chat ID already exists, this function will attempt + * to reconnect to the group. + * + * @param chat_id The Chat ID of the group you wish to join. This must be + * TOX_GROUP_CHAT_ID_SIZE bytes. + * @param password The password required to join the group. Set to NULL if no + * password is required. + * @param password_length The length of the password. If length is equal to + * zero, the password parameter is ignored. length must be no larger than + * TOX_GROUP_MAX_PASSWORD_SIZE. * @param name The name of the peer joining the group. - * @param name_length The length of the peer's name. This must be greater than zero and no larger - * than TOX_MAX_NAME_LENGTH. + * @param name_length The length of the peer's name. This must be greater than + * zero and no larger than TOX_MAX_NAME_LENGTH. * * @return group_number on success, UINT32_MAX on failure. */ @@ -3686,8 +3339,8 @@ typedef enum Tox_Err_Group_Is_Connected { const char *tox_err_group_is_connected_to_string(Tox_Err_Group_Is_Connected value); /** - * Returns true if the group chat is currently connected or attempting to connect to other peers - * in the group. + * Returns true if the group chat is currently connected or attempting to + * connect to other peers in the group. * * @param group_number The group number of the designated group. */ @@ -3714,7 +3367,8 @@ typedef enum Tox_Err_Group_Disconnect { const char *tox_err_group_disconnect_to_string(Tox_Err_Group_Disconnect value); /** - * Disconnects from a group chat while retaining the group state and credentials. + * Disconnects from a group chat while retaining the group state and + * credentials. * * Returns true if we successfully disconnect from the group. * @@ -3743,17 +3397,22 @@ typedef enum Tox_Err_Group_Reconnect { const char *tox_err_group_reconnect_to_string(Tox_Err_Group_Reconnect value); +#ifndef TOX_HIDE_DEPRECATED /** * Reconnects to a group. * - * This function disconnects from all peers in the group, then attempts to reconnect with the group. - * The caller's state is not changed (i.e. name, status, role, chat public key etc.). + * This function disconnects from all peers in the group, then attempts to + * reconnect with the group. The caller's state is not changed (i.e. name, + * status, role, chat public key etc.). * * @param group_number The group number of the group we wish to reconnect to. * * @return true on success. + * + * @deprecated Use `tox_group_join` instead. */ bool tox_group_reconnect(Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_Reconnect *error); +#endif /* TOX_HIDE_DEPRECATED */ typedef enum Tox_Err_Group_Leave { @@ -3783,14 +3442,16 @@ const char *tox_err_group_leave_to_string(Tox_Err_Group_Leave value); /** * Leaves a group. * - * This function sends a parting packet containing a custom (non-obligatory) message to all - * peers in a group, and deletes the group from the chat array. All group state information is permanently - * lost, including keys and role credentials. + * This function sends a parting packet containing a custom (non-obligatory) + * message to all peers in a group, and deletes the group from the chat array. + * All group state information is permanently lost, including keys and role + * credentials. * * @param group_number The group number of the group we wish to leave. - * @param part_message The parting message to be sent to all the peers. Set to NULL if we do not wish to - * send a parting message. - * @param length The length of the parting message. Set to 0 if we do not wish to send a parting message. + * @param part_message The parting message to be sent to all the peers. Set to + * NULL if we do not wish to send a parting message. + * @param length The length of the parting message. Set to 0 if we do not wish + * to send a parting message. * * @return true if the group chat instance is successfully deleted. */ @@ -3859,10 +3520,11 @@ typedef enum Tox_Err_Group_Self_Name_Set { const char *tox_err_group_self_name_set_to_string(Tox_Err_Group_Self_Name_Set value); /** - * Set the client's nickname for the group instance designated by the given group number. + * Set the client's nickname for the group instance designated by the given + * group number. * - * Nickname length cannot exceed TOX_MAX_NAME_LENGTH. If length is equal to zero or name is a NULL - * pointer, the function call will fail. + * Nickname length cannot exceed TOX_MAX_NAME_LENGTH. If length is equal to + * zero or name is a NULL pointer, the function call will fail. * * @param name A byte array containing the new nickname. * @param length The size of the name byte array. @@ -3875,8 +3537,8 @@ bool tox_group_self_set_name( Tox_Err_Group_Self_Name_Set *error); /** - * Return the length of the client's current nickname for the group instance designated - * by group_number as passed to tox_group_self_set_name. + * Return the length of the client's current nickname for the group instance + * designated by group_number as passed to tox_group_self_set_name. * * If no nickname was set before calling this function, the name is empty, * and this function returns 0. @@ -3891,7 +3553,8 @@ size_t tox_group_self_get_name_size(const Tox *tox, Tox_Group_Number group_numbe * If no nickname was set before calling this function, the name is empty, * and this function has no effect. * - * Call tox_group_self_get_name_size to find out how much memory to allocate for the result. + * Call tox_group_self_get_name_size to find out how much memory to allocate for + * the result. * * @param name A valid memory location large enough to hold the nickname. * If this parameter is NULL, the function has no effect. @@ -3927,7 +3590,8 @@ typedef enum Tox_Err_Group_Self_Status_Set { const char *tox_err_group_self_status_set_to_string(Tox_Err_Group_Self_Status_Set value); /** - * Set the client's status for the group instance. Status must be a Tox_User_Status. + * Set the client's status for the group instance. Status must be a + * Tox_User_Status. * * @return true on success. */ @@ -3953,13 +3617,16 @@ Tox_Group_Role tox_group_self_get_role(const Tox *tox, Tox_Group_Number group_nu Tox_Group_Peer_Number tox_group_self_get_peer_id(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_Self_Query *error); /** - * Write the client's group public key designated by the given group number to a byte array. + * Write the client's group public key designated by the given group number to + * a byte array. * - * This key will be permanently tied to the client's identity for this particular group until - * the client explicitly leaves the group. This key is the only way for other peers to reliably - * identify the client across client restarts. + * This key will be permanently tied to the client's identity for this + * particular group until the client explicitly leaves the group. This key is + * the only way for other peers to reliably identify the client across client + * restarts. * - * `public_key` should have room for at least TOX_GROUP_PEER_PUBLIC_KEY_SIZE bytes. + * `public_key` should have room for at least TOX_GROUP_PEER_PUBLIC_KEY_SIZE + * bytes. * * @param public_key A valid memory region large enough to store the public key. * If this parameter is NULL, this function call has no effect. @@ -4000,8 +3667,8 @@ typedef enum Tox_Err_Group_Peer_Query { const char *tox_err_group_peer_query_to_string(Tox_Err_Group_Peer_Query value); /** - * Return the length of the peer's name. If the group number or ID is invalid, the - * return value is unspecified. + * Return the length of the peer's name. If the group number or ID is invalid, + * the return value is unspecified. * * @param group_number The group number of the group we wish to query. * @param peer_id The ID of the peer whose name length we want to retrieve. @@ -4016,7 +3683,8 @@ size_t tox_group_peer_get_name_size(const Tox *tox, Tox_Group_Number group_numbe * Write the name of the peer designated by the given ID to a byte * array. * - * Call tox_group_peer_get_name_size to determine the allocation size for the `name` parameter. + * Call tox_group_peer_get_name_size to determine the allocation size for the + * `name` parameter. * * The data written to `name` is equal to the data received by the last * `group_peer_name` callback. @@ -4045,8 +3713,8 @@ Tox_User_Status tox_group_peer_get_status(const Tox *tox, Tox_Group_Number group Tox_Err_Group_Peer_Query *error); /** - * Return the peer's role (user/moderator/founder...). If the ID or group number is - * invalid, the return value is unspecified. + * Return the peer's role (user/moderator/founder...). If the ID or group number + * is invalid, the return value is unspecified. * * @param group_number The group number of the group we wish to query. * @param peer_id The ID of the peer whose role we wish to query. @@ -4060,8 +3728,9 @@ Tox_Group_Role tox_group_peer_get_role(const Tox *tox, Tox_Group_Number group_nu /** * Return the type of connection we have established with a peer. * - * If `peer_id` designates ourself, the return value indicates whether we're capable - * of making UDP connections with other peers, or are limited to TCP connections. + * If `peer_id` designates ourself, the return value indicates whether we're + * capable of making UDP connections with other peers, or are limited to TCP + * connections. * * @param group_number The group number of the group we wish to query. * @param peer_id The ID of the peer whose connection status we wish to query. @@ -4070,13 +3739,15 @@ Tox_Connection tox_group_peer_get_connection_status(const Tox *tox, Tox_Group_Nu Tox_Err_Group_Peer_Query *error); /** - * Write the group public key with the designated peer_id for the designated group number to public_key. + * Write the group public key with the designated peer_id for the designated + * group number to public_key. * - * This key will be permanently tied to a particular peer until they explicitly leave the group and is - * the only way to reliably identify the same peer across client restarts. + * This key will be permanently tied to a particular peer until they explicitly + * leave the group and is the only way to reliably identify the same peer across + * client restarts. * - * `public_key` should have room for at least TOX_GROUP_PEER_PUBLIC_KEY_SIZE bytes. If `public_key` is null - * this function has no effect. + * `public_key` should have room for at least TOX_GROUP_PEER_PUBLIC_KEY_SIZE + * bytes. If `public_key` is NULL this function has no effect. * * @param group_number The group number of the group we wish to query. * @param peer_id The ID of the peer whose public key we wish to retrieve. @@ -4090,14 +3761,15 @@ bool tox_group_peer_get_public_key( uint8_t public_key[TOX_PUBLIC_KEY_SIZE], Tox_Err_Group_Peer_Query *error); /** - * @param group_number The group number of the group the name change is intended for. + * @param group_number The group number of the group the name change is intended + * for. * @param peer_id The ID of the peer who has changed their name. * @param name The name data. - * @param length The length of the name. + * @param name_length The length of the name. */ typedef void tox_group_peer_name_cb( Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, - const uint8_t name[], size_t length, void *user_data); + const uint8_t name[], size_t name_length, void *user_data); /** * Set the callback for the `group_peer_name` event. Pass NULL to unset. @@ -4107,7 +3779,8 @@ typedef void tox_group_peer_name_cb( void tox_callback_group_peer_name(Tox *tox, tox_group_peer_name_cb *callback); /** - * @param group_number The group number of the group the status change is intended for. + * @param group_number The group number of the group the status change is + * intended for. * @param peer_id The ID of the peer who has changed their status. * @param status The new status of the peer. */ @@ -4130,21 +3803,21 @@ void tox_callback_group_peer_status(Tox *tox, tox_group_peer_status_cb *callback /** * General error codes for group state get and size functions. */ -typedef enum Tox_Err_Group_State_Queries { +typedef enum Tox_Err_Group_State_Query { /** * The function returned successfully. */ - TOX_ERR_GROUP_STATE_QUERIES_OK, + TOX_ERR_GROUP_STATE_QUERY_OK, /** * The group number passed did not designate a valid group. */ - TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND, + TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND, -} Tox_Err_Group_State_Queries; +} Tox_Err_Group_State_Query; -const char *tox_err_group_state_queries_to_string(Tox_Err_Group_State_Queries value); +const char *tox_err_group_state_query_to_string(Tox_Err_Group_State_Query value); /** * Error codes for group topic setting. @@ -4172,7 +3845,8 @@ typedef enum Tox_Err_Group_Topic_Set { TOX_ERR_GROUP_TOPIC_SET_PERMISSIONS, /** - * The packet could not be created. This error is usually related to cryptographic signing. + * The packet could not be created. This error is usually related to + * cryptographic signing. */ TOX_ERR_GROUP_TOPIC_SET_FAIL_CREATE, @@ -4193,8 +3867,8 @@ const char *tox_err_group_topic_set_to_string(Tox_Err_Group_Topic_Set value); /** * Set the group topic and broadcast it to the rest of the group. * - * topic length cannot be longer than TOX_GROUP_MAX_TOPIC_LENGTH. If length is equal to zero or - * topic is set to NULL, the topic will be unset. + * Topic length cannot be longer than TOX_GROUP_MAX_TOPIC_LENGTH. If the length + * is equal to zero or topic is set to NULL, the topic will be unset. * * @return true on success. */ @@ -4210,12 +3884,13 @@ bool tox_group_set_topic( * The return value is equal to the `length` argument received by the last * `group_topic` callback. */ -size_t tox_group_get_topic_size(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_State_Queries *error); +size_t tox_group_get_topic_size(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_State_Query *error); /** * Write the topic designated by the given group number to a byte array. * - * Call tox_group_get_topic_size to determine the allocation size for the `topic` parameter. + * Call tox_group_get_topic_size to determine the allocation size for the + * `topic` parameter. * * The data written to `topic` is equal to the data received by the last * `group_topic` callback. @@ -4227,18 +3902,19 @@ size_t tox_group_get_topic_size(const Tox *tox, Tox_Group_Number group_number, T */ bool tox_group_get_topic( const Tox *tox, Tox_Group_Number group_number, - uint8_t topic[], Tox_Err_Group_State_Queries *error); + uint8_t topic[], Tox_Err_Group_State_Query *error); /** - * @param group_number The group number of the group the topic change is intended for. - * @param peer_id The ID of the peer who changed the topic. If the peer who set the topic - * is not present in our peer list this value will be set to 0. + * @param group_number The group number of the group the topic change is + * intended for. + * @param peer_id The ID of the peer who changed the topic. If the peer who set + * the topic is not present in our peer list this value will be set to 0. * @param topic The topic data. - * @param length The topic length. + * @param topic_length The topic length. */ typedef void tox_group_topic_cb( Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, - const uint8_t topic[], size_t length, + const uint8_t topic[], size_t topic_length, void *user_data); /** @@ -4252,12 +3928,14 @@ void tox_callback_group_topic(Tox *tox, tox_group_topic_cb *callback); * Return the length of the group name. If the group number is invalid, the * return value is unspecified. */ -size_t tox_group_get_name_size(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_State_Queries *error); +size_t tox_group_get_name_size(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_State_Query *error); /** - * Write the name of the group designated by the given group number to a byte array. + * Write the name of the group designated by the given group number to a byte + * array. * - * Call tox_group_get_name_size to determine the allocation size for the `name` parameter. + * Call tox_group_get_name_size to determine the allocation size for the `name` + * parameter. * * @param name A valid memory region large enough to store the group name. * If this parameter is NULL, this function call has no effect. @@ -4266,7 +3944,7 @@ size_t tox_group_get_name_size(const Tox *tox, Tox_Group_Number group_number, To */ bool tox_group_get_name( const Tox *tox, Tox_Group_Number group_number, - uint8_t name[], Tox_Err_Group_State_Queries *error); + uint8_t name[], Tox_Err_Group_State_Query *error); /** * Write the Chat ID designated by the given group number to a byte array. @@ -4280,7 +3958,7 @@ bool tox_group_get_name( */ bool tox_group_get_chat_id( const Tox *tox, Tox_Group_Number group_number, uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE], - Tox_Err_Group_State_Queries *error); + Tox_Err_Group_State_Query *error); /** * Return the number of groups in the Tox chats array. @@ -4288,19 +3966,21 @@ bool tox_group_get_chat_id( uint32_t tox_group_get_number_groups(const Tox *tox); /** - * Return the privacy state of the group designated by the given group number. If group number - * is invalid, the return value is unspecified. + * Return the privacy state of the group designated by the given group number. + * If group number is invalid, the return value is unspecified. * * The value returned is equal to the data received by the last * `group_privacy_state` callback. * - * @see the `Group chat founder controls` section for the respective set function. + * @see the `Group chat Founder controls` section for the respective set + * function. */ Tox_Group_Privacy_State tox_group_get_privacy_state(const Tox *tox, Tox_Group_Number group_number, - Tox_Err_Group_State_Queries *error); + Tox_Err_Group_State_Query *error); /** - * @param group_number The group number of the group the privacy state is intended for. + * @param group_number The group number of the group the privacy state is + * intended for. * @param privacy_state The new privacy state. */ typedef void tox_group_privacy_state_cb(Tox *tox, Tox_Group_Number group_number, Tox_Group_Privacy_State privacy_state, @@ -4314,18 +3994,21 @@ typedef void tox_group_privacy_state_cb(Tox *tox, Tox_Group_Number group_number, void tox_callback_group_privacy_state(Tox *tox, tox_group_privacy_state_cb *callback); /** - * Return the voice state of the group designated by the given group number. If group number - * is invalid, the return value is unspecified. + * Return the voice state of the group designated by the given group number. If + * group number is invalid, the return value is unspecified. * - * The value returned is equal to the data received by the last `group_voice_state` callback. + * The value returned is equal to the data received by the last + * `group_voice_state` callback. * - * @see the `Group chat founder controls` section for the respective set function. + * @see the `Group chat Founder controls` section for the respective set + * function. */ Tox_Group_Voice_State tox_group_get_voice_state(const Tox *tox, Tox_Group_Number group_number, - Tox_Err_Group_State_Queries *error); + Tox_Err_Group_State_Query *error); /** - * @param group_number The group number of the group the voice state change is intended for. + * @param group_number The group number of the group the voice state change is + * intended for. * @param voice_state The new voice state. */ typedef void tox_group_voice_state_cb(Tox *tox, Tox_Group_Number group_number, Tox_Group_Voice_State voice_state, @@ -4339,19 +4022,22 @@ typedef void tox_group_voice_state_cb(Tox *tox, Tox_Group_Number group_number, T void tox_callback_group_voice_state(Tox *tox, tox_group_voice_state_cb *callback); /** - * Return the topic lock status of the group designated by the given group number. If group number + * Return the topic lock status of the group designated by the given group + * number. If group number * is invalid, the return value is unspecified. * * The value returned is equal to the data received by the last * `group_topic_lock` callback. * - * @see the `Group chat founder contols` section for the respective set function. + * @see the `Group chat Founder controls` section for the respective set + * function. */ Tox_Group_Topic_Lock tox_group_get_topic_lock(const Tox *tox, Tox_Group_Number group_number, - Tox_Err_Group_State_Queries *error); + Tox_Err_Group_State_Query *error); /** - * @param group_number The group number of the group for which the topic lock has changed. + * @param group_number The group number of the group for which the topic lock + * has changed. * @param topic_lock The new topic lock state. */ typedef void tox_group_topic_lock_cb(Tox *tox, Tox_Group_Number group_number, Tox_Group_Topic_Lock topic_lock, void *user_data); @@ -4364,18 +4050,21 @@ typedef void tox_group_topic_lock_cb(Tox *tox, Tox_Group_Number group_number, To void tox_callback_group_topic_lock(Tox *tox, tox_group_topic_lock_cb *callback); /** - * Return the maximum number of peers allowed for the group designated by the given group number. - * If the group number is invalid, the return value is unspecified. + * Return the maximum number of peers allowed for the group designated by the + * given group number. If the group number is invalid, the return value is + * unspecified. * * The value returned is equal to the data received by the last * `group_peer_limit` callback. * - * @see the `Group chat founder controls` section for the respective set function. + * @see the `Group chat Founder controls` section for the respective set + * function. */ -uint16_t tox_group_get_peer_limit(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_State_Queries *error); +uint16_t tox_group_get_peer_limit(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_State_Query *error); /** - * @param group_number The group number of the group for which the peer limit has changed. + * @param group_number The group number of the group for which the peer limit + * has changed. * @param peer_limit The new peer limit for the group. */ typedef void tox_group_peer_limit_cb(Tox *tox, Tox_Group_Number group_number, uint32_t peer_limit, void *user_data); @@ -4383,7 +4072,8 @@ typedef void tox_group_peer_limit_cb(Tox *tox, Tox_Group_Number group_number, ui /** * Set the callback for the `group_peer_limit` event. Pass NULL to unset. * - * This event is triggered when the group founder changes the maximum peer limit. + * This event is triggered when the group founder changes the maximum peer + * limit. */ void tox_callback_group_peer_limit(Tox *tox, tox_group_peer_limit_cb *callback); @@ -4391,35 +4081,39 @@ void tox_callback_group_peer_limit(Tox *tox, tox_group_peer_limit_cb *callback); * Return the length of the group password. If the group number is invalid, the * return value is unspecified. */ -size_t tox_group_get_password_size(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_State_Queries *error); +size_t tox_group_get_password_size(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_State_Query *error); /** - * Write the password for the group designated by the given group number to a byte array. + * Write the password for the group designated by the given group number to a + * byte array. * - * Call tox_group_get_password_size to determine the allocation size for the `password` parameter. + * Call tox_group_get_password_size to determine the allocation size for the + * `password` parameter. * - * The data received is equal to the data received by the last - * `group_password` callback. + * The data received is equal to the data received by the last `group_password` + * callback. * - * @see the `Group chat founder controls` section for the respective set function. + * @see the `Group chat Founder controls` section for the respective set + * function. * - * @param password A valid memory region large enough to store the group password. - * If this parameter is NULL, this function call has no effect. + * @param password A valid memory region large enough to store the group + * password. If this parameter is NULL, this function call has no effect. * * @return true on success. */ bool tox_group_get_password( const Tox *tox, Tox_Group_Number group_number, uint8_t password[], - Tox_Err_Group_State_Queries *error); + Tox_Err_Group_State_Query *error); /** - * @param group_number The group number of the group for which the password has changed. + * @param group_number The group number of the group for which the password has + * changed. * @param password The new group password. - * @param length The length of the password. + * @param password_length The length of the password. */ typedef void tox_group_password_cb( Tox *tox, Tox_Group_Number group_number, - const uint8_t password[], size_t length, + const uint8_t password[], size_t password_length, void *user_data); /** @@ -4453,7 +4147,7 @@ typedef enum Tox_Err_Group_Send_Message { TOX_ERR_GROUP_SEND_MESSAGE_TOO_LONG, /** - * The message pointer is null or length is zero. + * The message pointer is NULL or length is zero. */ TOX_ERR_GROUP_SEND_MESSAGE_EMPTY, @@ -4487,12 +4181,13 @@ const char *tox_err_group_send_message_to_string(Tox_Err_Group_Send_Message valu * This function creates a group message packet and pushes it into the send * queue. * - * The message length may not exceed TOX_GROUP_MAX_MESSAGE_LENGTH. Larger messages - * must be split by the client and sent as separate messages. Other clients can - * then reassemble the fragments. Messages may not be empty. + * The message length may not exceed TOX_GROUP_MAX_MESSAGE_LENGTH. Larger + * messages must be split by the client and sent as separate messages. Other + * clients can then reassemble the fragments. Messages may not be empty. * - * @param group_number The group number of the group the message is intended for. - * @param type Message type (normal, action, ...). + * @param group_number The group number of the group the message is intended + * for. + * @param message_type Message type (normal, action, ...). * @param message A non-NULL pointer to the first element of a byte array * containing the message text. * @param length Length of the message to be sent. @@ -4501,7 +4196,7 @@ const char *tox_err_group_send_message_to_string(Tox_Err_Group_Send_Message valu * returned message ID value will be undefined. */ Tox_Group_Message_Id tox_group_send_message( - const Tox *tox, Tox_Group_Number group_number, Tox_Message_Type type, + const Tox *tox, Tox_Group_Number group_number, Tox_Message_Type message_type, const uint8_t message[], size_t length, Tox_Err_Group_Send_Message *error); @@ -4528,11 +4223,16 @@ typedef enum Tox_Err_Group_Send_Private_Message { TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_TOO_LONG, /** - * The message pointer is null or length is zero. + * The message pointer is NULL or length is zero. */ TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_EMPTY, /** + * The message type is invalid. + */ + TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_BAD_TYPE, + + /** * The caller does not have the required permissions to send group messages. */ TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PERMISSIONS, @@ -4547,11 +4247,6 @@ typedef enum Tox_Err_Group_Send_Private_Message { */ TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_DISCONNECTED, - /** - * The message type is invalid. - */ - TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_BAD_TYPE, - } Tox_Err_Group_Send_Private_Message; const char *tox_err_group_send_private_message_to_string(Tox_Err_Group_Send_Private_Message value); @@ -4559,23 +4254,25 @@ const char *tox_err_group_send_private_message_to_string(Tox_Err_Group_Send_Priv /** * Send a text chat message to the specified peer in the specified group. * - * This function creates a group private message packet and pushes it into the send - * queue. + * This function creates a group private message packet and pushes it into the + * send queue. * - * The message length may not exceed TOX_GROUP_MAX_MESSAGE_LENGTH. Larger messages - * must be split by the client and sent as separate messages. Other clients can - * then reassemble the fragments. Messages may not be empty. + * The message length may not exceed TOX_GROUP_MAX_MESSAGE_LENGTH. Larger + * messages must be split by the client and sent as separate messages. Other + * clients can then reassemble the fragments. Messages may not be empty. * - * @param group_number The group number of the group the message is intended for. + * @param group_number The group number of the group the message is intended + * for. * @param peer_id The ID of the peer the message is intended for. + * @param message_type The type of message (normal, action, ...). * @param message A non-NULL pointer to the first element of a byte array * containing the message text. * @param length Length of the message to be sent. * * @return true on success. */ -bool tox_group_send_private_message( - const Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, Tox_Message_Type type, +Tox_Group_Message_Id tox_group_send_private_message( + const Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, Tox_Message_Type message_type, const uint8_t message[], size_t length, Tox_Err_Group_Send_Private_Message *error); @@ -4599,16 +4296,11 @@ typedef enum Tox_Err_Group_Send_Custom_Packet { TOX_ERR_GROUP_SEND_CUSTOM_PACKET_TOO_LONG, /** - * The message pointer is null or length is zero. + * The message pointer is NULL or length is zero. */ TOX_ERR_GROUP_SEND_CUSTOM_PACKET_EMPTY, /** - * The caller does not have the required permissions to send group messages. - */ - TOX_ERR_GROUP_SEND_CUSTOM_PACKET_PERMISSIONS, - - /** * The group is disconnected. */ TOX_ERR_GROUP_SEND_CUSTOM_PACKET_DISCONNECTED, @@ -4626,15 +4318,17 @@ const char *tox_err_group_send_custom_packet_to_string(Tox_Err_Group_Send_Custom /** * Send a custom packet to the group. * - * If lossless is true the packet will be lossless. Lossless packet behaviour is comparable - * to TCP (reliability, arrive in order) but with packets instead of a stream. + * If lossless is true the packet will be lossless. Lossless packet behaviour is + * comparable to TCP (reliability, arrive in order) but with packets instead of + * a stream. * - * If lossless is false, the packet will be lossy. Lossy packets behave like UDP packets, - * meaning they might never reach the other side or might arrive more than once (if someone - * is messing with the connection) or might arrive in the wrong order. + * If lossless is false, the packet will be lossy. Lossy packets behave like UDP + * packets, meaning they might never reach the other side or might arrive more + * than once (if someone is messing with the connection) or might arrive in the + * wrong order. * - * Unless latency is an issue or message reliability is not important, it is recommended that you use - * lossless packets. + * Unless latency is an issue or message reliability is not important, it is + * recommended that you use lossless packets. * * The message length may not exceed TOX_MAX_CUSTOM_PACKET_SIZE. Larger packets * must be split by the client and sent as separate packets. Other clients can @@ -4672,7 +4366,7 @@ typedef enum Tox_Err_Group_Send_Custom_Private_Packet { TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_TOO_LONG, /** - * The message pointer is null or length is zero. + * The message pointer is NULL or length is zero. */ TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_EMPTY, @@ -4682,11 +4376,6 @@ typedef enum Tox_Err_Group_Send_Custom_Private_Packet { TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_PEER_NOT_FOUND, /** - * The caller does not have the required permissions to send group messages. - */ - TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_PERMISSIONS, - - /** * The packet failed to send. */ TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_FAIL_SEND, @@ -4703,15 +4392,17 @@ const char *tox_err_group_send_custom_private_packet_to_string(Tox_Err_Group_Sen /** * Send a custom private packet to a designated peer in the group. * - * If lossless is true the packet will be lossless. Lossless packet behaviour is comparable - * to TCP (reliability, arrive in order) but with packets instead of a stream. + * If lossless is true the packet will be lossless. Lossless packet behaviour is + * comparable to TCP (reliability, arrive in order) but with packets instead of + * a stream. * - * If lossless is false, the packet will be lossy. Lossy packets behave like UDP packets, - * meaning they might never reach the other side or might arrive more than once (if someone - * is messing with the connection) or might arrive in the wrong order. + * If lossless is false, the packet will be lossy. Lossy packets behave like UDP + * packets, meaning they might never reach the other side or might arrive more + * than once (if someone is messing with the connection) or might arrive in the + * wrong order. * - * Unless latency is an issue or message reliability is not important, it is recommended that you use - * lossless packets. + * Unless latency is an issue or message reliability is not important, it is + * recommended that you use lossless packets. * * The packet length may not exceed TOX_MAX_CUSTOM_PACKET_SIZE. Larger packets * must be split by the client and sent as separate packets. Other clients can @@ -4736,16 +4427,18 @@ bool tox_group_send_custom_private_packet(const Tox *tox, Tox_Group_Number group ******************************************************************************/ /** - * @param group_number The group number of the group the message is intended for. + * @param group_number The group number of the group the message is intended + * for. * @param peer_id The ID of the peer who sent the message. - * @param type The type of message (normal, action, ...). + * @param message_type The type of message (normal, action, ...). * @param message The message data. - * @param message_id A pseudo message id that clients can use to uniquely identify this group message. - * @param length The length of the message. + * @param message_length The length of the message. + * @param message_id A pseudo message id that clients can use to uniquely + * identify this group message. */ typedef void tox_group_message_cb( - Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, Tox_Message_Type type, - const uint8_t message[], size_t length, Tox_Group_Message_Id message_id, void *user_data); + Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, Tox_Message_Type message_type, + const uint8_t message[], size_t message_length, Tox_Group_Message_Id message_id, void *user_data); /** * Set the callback for the `group_message` event. Pass NULL to unset. @@ -4755,14 +4448,18 @@ typedef void tox_group_message_cb( void tox_callback_group_message(Tox *tox, tox_group_message_cb *callback); /** - * @param group_number The group number of the group the private message is intended for. + * @param group_number The group number of the group the private message is + * intended for. * @param peer_id The ID of the peer who sent the private message. + * @param message_type The type of message (normal, action, ...). * @param message The message data. - * @param length The length of the message. + * @param message_length The length of the message. + * @param message_id A pseudo message id that clients can use to uniquely + * identify this group message. */ typedef void tox_group_private_message_cb( - Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, Tox_Message_Type type, - const uint8_t message[], size_t length, void *user_data); + Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, Tox_Message_Type message_type, + const uint8_t message[], size_t message_length, Tox_Group_Message_Id message_id, void *user_data); /** * Set the callback for the `group_private_message` event. Pass NULL to unset. @@ -4775,11 +4472,11 @@ void tox_callback_group_private_message(Tox *tox, tox_group_private_message_cb * * @param group_number The group number of the group the packet is intended for. * @param peer_id The ID of the peer who sent the packet. * @param data The packet data. - * @param length The length of the data. + * @param data_length The length of the data. */ typedef void tox_group_custom_packet_cb( Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, - const uint8_t data[], size_t length, void *user_data); + const uint8_t data[], size_t data_length, void *user_data); /** * Set the callback for the `group_custom_packet` event. Pass NULL to unset. @@ -4792,14 +4489,15 @@ void tox_callback_group_custom_packet(Tox *tox, tox_group_custom_packet_cb *call * @param group_number The group number of the group the packet is intended for. * @param peer_id The ID of the peer who sent the packet. * @param data The packet data. - * @param length The length of the data. + * @param data_length The length of the data. */ typedef void tox_group_custom_private_packet_cb( Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, - const uint8_t data[], size_t length, void *user_data); + const uint8_t data[], size_t data_length, void *user_data); /** - * Set the callback for the `group_custom_private_packet` event. Pass NULL to unset. + * Set the callback for the `group_custom_private_packet` event. Pass NULL to + * unset. * * This event is triggered when the client receives a custom private packet. */ @@ -4829,7 +4527,8 @@ typedef enum Tox_Err_Group_Invite_Friend { TOX_ERR_GROUP_INVITE_FRIEND_FRIEND_NOT_FOUND, /** - * Creation of the invite packet failed. This indicates a network related error. + * Creation of the invite packet failed. This indicates a network related + * error. */ TOX_ERR_GROUP_INVITE_FRIEND_INVITE_FAIL, @@ -4850,10 +4549,13 @@ const char *tox_err_group_invite_friend_to_string(Tox_Err_Group_Invite_Friend va /** * Invite a friend to a group. * - * This function creates an invite request packet and pushes it to the send queue. + * This function creates an invite request packet and pushes it to the send + * queue. * - * @param group_number The group number of the group the message is intended for. - * @param friend_number The friend number of the friend the invite is intended for. + * @param group_number The group number of the group the message is intended + * for. + * @param friend_number The friend number of the friend the invite is intended + * for. * * @return true on success. */ @@ -4889,36 +4591,44 @@ typedef enum Tox_Err_Group_Invite_Accept { TOX_ERR_GROUP_INVITE_ACCEPT_EMPTY, /** - * Failed to set password. This usually occurs if the password exceeds TOX_GROUP_MAX_PASSWORD_SIZE. + * Failed to set password. This usually occurs if the password exceeds + * TOX_GROUP_MAX_PASSWORD_SIZE. */ TOX_ERR_GROUP_INVITE_ACCEPT_PASSWORD, /** - * There was a core error when initiating the group. + * The friend number passed did not designate a valid friend. */ - TOX_ERR_GROUP_INVITE_ACCEPT_CORE, + TOX_ERR_GROUP_INVITE_ACCEPT_FRIEND_NOT_FOUND, /** * Packet failed to send. */ TOX_ERR_GROUP_INVITE_ACCEPT_FAIL_SEND, + /** + * Invite data or name is NULL. + */ + TOX_ERR_GROUP_INVITE_ACCEPT_NULL, + } Tox_Err_Group_Invite_Accept; const char *tox_err_group_invite_accept_to_string(Tox_Err_Group_Invite_Accept value); /** - * Accept an invite to a group chat that the client previously received from a friend. The invite - * is only valid while the inviter is present in the group. + * Accept an invite to a group chat that the client previously received from a + * friend. The invite is only valid while the inviter is present in the group. * * @param invite_data The invite data received from the `group_invite` event. * @param length The length of the invite data. * @param name The name of the peer joining the group. - * @param name_length The length of the peer's name. This must be greater than zero and no larger - * than TOX_MAX_NAME_LENGTH. - * @param password The password required to join the group. Set to NULL if no password is required. - * @param password_length The length of the password. If password_length is equal to zero, the password - * parameter will be ignored. password_length must be no larger than TOX_GROUP_MAX_PASSWORD_SIZE. + * @param name_length The length of the peer's name. This must be greater than + * zero and no larger than TOX_MAX_NAME_LENGTH. + * @param password The password required to join the group. Set to NULL if no + * password is required. + * @param password_length The length of the password. If password_length is + * equal to zero, the password parameter will be ignored. password_length + * must be no larger than TOX_GROUP_MAX_PASSWORD_SIZE. * * @return the group_number on success, UINT32_MAX on failure. */ @@ -4932,26 +4642,30 @@ Tox_Group_Number tox_group_invite_accept( /** * @param friend_number The friend number of the contact who sent the invite. * @param invite_data The invite data. - * @param length The length of invite_data. + * @param invite_data_length The length of invite_data. + * @param group_name The name of the group. In conferences, this is "title". + * @param group_name_length The length of the group name. */ typedef void tox_group_invite_cb( Tox *tox, Tox_Friend_Number friend_number, - const uint8_t invite_data[], size_t length, + const uint8_t invite_data[], size_t invite_data_length, const uint8_t group_name[], size_t group_name_length, void *user_data); /** * Set the callback for the `group_invite` event. Pass NULL to unset. * - * This event is triggered when the client receives a group invite from a friend. The client must store - * invite_data which is used to join the group via tox_group_invite_accept. + * This event is triggered when the client receives a group invite from a + * friend. The client must store invite_data which is used to join the group + * via tox_group_invite_accept. */ void tox_callback_group_invite(Tox *tox, tox_group_invite_cb *callback); /** - * @param group_number The group number of the group in which a new peer has joined. - * @param peer_id The permanent ID of the new peer. This id should not be relied on for - * client behaviour and should be treated as a random value. + * @param group_number The group number of the group in which a new peer has + * joined. + * @param peer_id The permanent ID of the new peer. This id should not be relied + * on for client behaviour and should be treated as a random value. */ typedef void tox_group_peer_join_cb(Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, void *user_data); @@ -4963,7 +4677,8 @@ typedef void tox_group_peer_join_cb(Tox *tox, Tox_Group_Number group_number, Tox void tox_callback_group_peer_join(Tox *tox, tox_group_peer_join_cb *callback); /** - * Represents peer exit events. These should be used with the `group_peer_exit` event. + * Represents peer exit events. These should be used with the `group_peer_exit` + * event. */ typedef enum Tox_Group_Exit_Type { @@ -4983,8 +4698,9 @@ typedef enum Tox_Group_Exit_Type { TOX_GROUP_EXIT_TYPE_DISCONNECTED, /** - * Your connection with all peers has been severed. This will occur when you are kicked from - * a group, rejoin a group, or manually disconnect from a group. + * Your connection with all peers has been severed. This will occur when you + * are kicked from a group, rejoin a group, or manually disconnect from a + * group. */ TOX_GROUP_EXIT_TYPE_SELF_DISCONNECTED, @@ -5004,8 +4720,8 @@ const char *tox_group_exit_type_to_string(Tox_Group_Exit_Type value); /** * @param group_number The group number of the group in which a peer has left. - * @param peer_id The ID of the peer who left the group. This ID no longer designates a valid peer - * and cannot be used for API calls. + * @param peer_id The ID of the peer who left the group. This ID no longer + * designates a valid peer and cannot be used for API calls. * @param exit_type The type of exit event. One of Tox_Group_Exit_Type. * @param name The nickname of the peer who left the group. * @param name_length The length of the peer name. @@ -5032,14 +4748,14 @@ typedef void tox_group_self_join_cb(Tox *tox, Tox_Group_Number group_number, voi /** * Set the callback for the `group_self_join` event. Pass NULL to unset. * - * This event is triggered when the client has successfully joined a group. Use this to initialize - * any group information the client may need. + * This event is triggered when the client has successfully joined a group. Use + * this to initialize any group information the client may need. */ void tox_callback_group_self_join(Tox *tox, tox_group_self_join_cb *callback); /** - * Represents types of failed group join attempts. These are used in the tox_callback_group_rejected - * callback when a peer fails to join a group. + * Represents types of failed group join attempts. These are used in the + * tox_callback_group_rejected callback when a peer fails to join a group. */ typedef enum Tox_Group_Join_Fail { @@ -5054,8 +4770,8 @@ typedef enum Tox_Group_Join_Fail { TOX_GROUP_JOIN_FAIL_INVALID_PASSWORD, /** - * The join attempt failed due to an unspecified error. This often occurs when the group is - * not found in the DHT. + * The join attempt failed due to an unspecified error. This often occurs + * when the group is not found in the DHT. */ TOX_GROUP_JOIN_FAIL_UNKNOWN, @@ -5064,7 +4780,8 @@ typedef enum Tox_Group_Join_Fail { const char *tox_group_join_fail_to_string(Tox_Group_Join_Fail value); /** - * @param group_number The group number of the group for which the join has failed. + * @param group_number The group number of the group for which the join has + * failed. * @param fail_type The type of group rejection. */ typedef void tox_group_join_fail_cb(Tox *tox, Tox_Group_Number group_number, Tox_Group_Join_Fail fail_type, void *user_data); @@ -5078,289 +4795,306 @@ void tox_callback_group_join_fail(Tox *tox, tox_group_join_fail_cb *callback); /******************************************************************************* * - * :: Group chat founder controls (these only work for the group founder) + * :: Group chat Founder controls * ******************************************************************************/ -typedef enum Tox_Err_Group_Founder_Set_Password { +typedef enum Tox_Err_Group_Set_Password { /** * The function returned successfully. */ - TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK, + TOX_ERR_GROUP_SET_PASSWORD_OK, /** * The group number passed did not designate a valid group. */ - TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_GROUP_NOT_FOUND, + TOX_ERR_GROUP_SET_PASSWORD_GROUP_NOT_FOUND, /** * The caller does not have the required permissions to set the password. */ - TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_PERMISSIONS, + TOX_ERR_GROUP_SET_PASSWORD_PERMISSIONS, /** * Password length exceeded TOX_GROUP_MAX_PASSWORD_SIZE. */ - TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_TOO_LONG, + TOX_ERR_GROUP_SET_PASSWORD_TOO_LONG, /** * The packet failed to send. */ - TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_FAIL_SEND, + TOX_ERR_GROUP_SET_PASSWORD_FAIL_SEND, /** * The function failed to allocate enough memory for the operation. */ - TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_MALLOC, + TOX_ERR_GROUP_SET_PASSWORD_MALLOC, /** * The group is disconnected. */ - TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_DISCONNECTED, + TOX_ERR_GROUP_SET_PASSWORD_DISCONNECTED, -} Tox_Err_Group_Founder_Set_Password; +} Tox_Err_Group_Set_Password; -const char *tox_err_group_founder_set_password_to_string(Tox_Err_Group_Founder_Set_Password value); +const char *tox_err_group_set_password_to_string(Tox_Err_Group_Set_Password value); /** * Set or unset the group password. * - * This function sets the groups password, creates a new group shared state including the change, - * and distributes it to the rest of the group. + * This function allows Founders to set or unset a group password. It will + * create a new group shared state including the change and distribute it to the + * rest of the group. * - * @param group_number The group number of the group for which we wish to set the password. - * @param password The password we want to set. Set password to NULL to unset the password. - * @param length The length of the password. length must be no longer than TOX_GROUP_MAX_PASSWORD_SIZE. + * @param group_number The group number of the group for which we wish to set + * the password. + * @param password The password we want to set. Set password to NULL to unset + * the password. + * @param length The length of the password. length must be no longer than + * TOX_GROUP_MAX_PASSWORD_SIZE. * * @return true on success. */ -bool tox_group_founder_set_password( +bool tox_group_set_password( Tox *tox, Tox_Group_Number group_number, const uint8_t password[], size_t length, - Tox_Err_Group_Founder_Set_Password *error); + Tox_Err_Group_Set_Password *error); -typedef enum Tox_Err_Group_Founder_Set_Topic_Lock { +typedef enum Tox_Err_Group_Set_Topic_Lock { /** * The function returned successfully. */ - TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK, + TOX_ERR_GROUP_SET_TOPIC_LOCK_OK, /** * The group number passed did not designate a valid group. */ - TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_GROUP_NOT_FOUND, + TOX_ERR_GROUP_SET_TOPIC_LOCK_GROUP_NOT_FOUND, /** * Tox_Group_Topic_Lock is an invalid type. */ - TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_INVALID, + TOX_ERR_GROUP_SET_TOPIC_LOCK_INVALID, /** * The caller does not have the required permissions to set the topic lock. */ - TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_PERMISSIONS, + TOX_ERR_GROUP_SET_TOPIC_LOCK_PERMISSIONS, /** - * The topic lock could not be set. This may occur due to an error related to - * cryptographic signing of the new shared state. + * The topic lock could not be set. This may occur due to an error related + * to cryptographic signing of the new shared state. */ - TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_FAIL_SET, + TOX_ERR_GROUP_SET_TOPIC_LOCK_FAIL_SET, /** * The packet failed to send. */ - TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_FAIL_SEND, + TOX_ERR_GROUP_SET_TOPIC_LOCK_FAIL_SEND, /** * The group is disconnected. */ - TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_DISCONNECTED, + TOX_ERR_GROUP_SET_TOPIC_LOCK_DISCONNECTED, -} Tox_Err_Group_Founder_Set_Topic_Lock; +} Tox_Err_Group_Set_Topic_Lock; -const char *tox_err_group_founder_set_topic_lock_to_string(Tox_Err_Group_Founder_Set_Topic_Lock value); +const char *tox_err_group_set_topic_lock_to_string(Tox_Err_Group_Set_Topic_Lock value); /** * Set the group topic lock state. * - * This function sets the group's topic lock state to enabled or disabled, creates a new shared - * state including the change, and distributes it to the rest of the group. + * This function allows Founders to enable or disable the group's topic lock. It + * will create a new shared state including the change and distribute it to the + * rest of the group. * - * When the topic lock is enabled, only the group founder and moderators may set the topic. - * When disabled, all peers except those with the observer role may set the topic. + * When the topic lock is enabled, only the group founder and moderators may set + * the topic. When disabled, all peers except those with the observer role may + * set the topic. * - * @param group_number The group number of the group for which we wish to change the topic lock state. + * @param group_number The group number of the group for which we wish to change + * the topic lock state. * @param topic_lock The state we wish to set the topic lock to. * * @return true on success. */ -bool tox_group_founder_set_topic_lock(Tox *tox, Tox_Group_Number group_number, Tox_Group_Topic_Lock topic_lock, - Tox_Err_Group_Founder_Set_Topic_Lock *error); +bool tox_group_set_topic_lock(Tox *tox, Tox_Group_Number group_number, Tox_Group_Topic_Lock topic_lock, + Tox_Err_Group_Set_Topic_Lock *error); -typedef enum Tox_Err_Group_Founder_Set_Voice_State { +typedef enum Tox_Err_Group_Set_Voice_State { /** * The function returned successfully. */ - TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_OK, + TOX_ERR_GROUP_SET_VOICE_STATE_OK, /** * The group number passed did not designate a valid group. */ - TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_GROUP_NOT_FOUND, + TOX_ERR_GROUP_SET_VOICE_STATE_GROUP_NOT_FOUND, /** - * The caller does not have the required permissions to set the privacy state. + * The caller does not have the required permissions to set the privacy + * state. */ - TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_PERMISSIONS, + TOX_ERR_GROUP_SET_VOICE_STATE_PERMISSIONS, /** - * The voice state could not be set. This may occur due to an error related to - * cryptographic signing of the new shared state. + * The voice state could not be set. This may occur due to an error related + * to cryptographic signing of the new shared state. */ - TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_FAIL_SET, + TOX_ERR_GROUP_SET_VOICE_STATE_FAIL_SET, /** * The packet failed to send. */ - TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_FAIL_SEND, + TOX_ERR_GROUP_SET_VOICE_STATE_FAIL_SEND, /** * The group is disconnected. */ - TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_DISCONNECTED, + TOX_ERR_GROUP_SET_VOICE_STATE_DISCONNECTED, -} Tox_Err_Group_Founder_Set_Voice_State; +} Tox_Err_Group_Set_Voice_State; -const char *tox_err_group_founder_set_voice_state_to_string(Tox_Err_Group_Founder_Set_Voice_State value); +const char *tox_err_group_set_voice_state_to_string(Tox_Err_Group_Set_Voice_State value); /** * Set the group voice state. * - * This function sets the group's voice state, creates a new group shared state - * including the change, and distributes it to the rest of the group. + * This function allows Founders to set the group's voice state. It will create + * a new group shared state including the change and distribute it to the rest + * of the group. * - * If an attempt is made to set the voice state to the same state that the group is already - * in, the function call will be successful and no action will be taken. + * If an attempt is made to set the voice state to the same state that the group + * is already in, the function call will be successful and no action will be + * taken. * - * @param group_number The group number of the group for which we wish to change the voice state. + * @param group_number The group number of the group for which we wish to change + * the voice state. * @param voice_state The voice state we wish to set the group to. * * @return true on success. */ -bool tox_group_founder_set_voice_state(Tox *tox, Tox_Group_Number group_number, Tox_Group_Voice_State voice_state, - Tox_Err_Group_Founder_Set_Voice_State *error); +bool tox_group_set_voice_state(Tox *tox, Tox_Group_Number group_number, Tox_Group_Voice_State voice_state, + Tox_Err_Group_Set_Voice_State *error); -typedef enum Tox_Err_Group_Founder_Set_Privacy_State { +typedef enum Tox_Err_Group_Set_Privacy_State { /** * The function returned successfully. */ - TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK, + TOX_ERR_GROUP_SET_PRIVACY_STATE_OK, /** * The group number passed did not designate a valid group. */ - TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_GROUP_NOT_FOUND, + TOX_ERR_GROUP_SET_PRIVACY_STATE_GROUP_NOT_FOUND, /** - * The caller does not have the required permissions to set the privacy state. + * The caller does not have the required permissions to set the privacy + * state. */ - TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_PERMISSIONS, + TOX_ERR_GROUP_SET_PRIVACY_STATE_PERMISSIONS, /** - * The privacy state could not be set. This may occur due to an error related to - * cryptographic signing of the new shared state. + * The privacy state could not be set. This may occur due to an error + * related to cryptographic signing of the new shared state. */ - TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SET, + TOX_ERR_GROUP_SET_PRIVACY_STATE_FAIL_SET, /** * The packet failed to send. */ - TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SEND, + TOX_ERR_GROUP_SET_PRIVACY_STATE_FAIL_SEND, /** * The group is disconnected. */ - TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_DISCONNECTED, + TOX_ERR_GROUP_SET_PRIVACY_STATE_DISCONNECTED, -} Tox_Err_Group_Founder_Set_Privacy_State; +} Tox_Err_Group_Set_Privacy_State; -const char *tox_err_group_founder_set_privacy_state_to_string(Tox_Err_Group_Founder_Set_Privacy_State value); +const char *tox_err_group_set_privacy_state_to_string(Tox_Err_Group_Set_Privacy_State value); /** * Set the group privacy state. * - * This function sets the group's privacy state, creates a new group shared state - * including the change, and distributes it to the rest of the group. + * This function allows Founders to set the group's privacy state. It will + * create a new group shared state including the change and distribute it to the + * rest of the group. * - * If an attempt is made to set the privacy state to the same state that the group is already - * in, the function call will be successful and no action will be taken. + * If an attempt is made to set the privacy state to the same state that the + * group is already in, the function call will be successful and no action will + * be taken. * - * @param group_number The group number of the group for which we wish to change the privacy state. + * @param group_number The group number of the group for which we wish to change + * the privacy state. * @param privacy_state The privacy state we wish to set the group to. * * @return true on success. */ -bool tox_group_founder_set_privacy_state(Tox *tox, Tox_Group_Number group_number, Tox_Group_Privacy_State privacy_state, - Tox_Err_Group_Founder_Set_Privacy_State *error); +bool tox_group_set_privacy_state(Tox *tox, Tox_Group_Number group_number, Tox_Group_Privacy_State privacy_state, + Tox_Err_Group_Set_Privacy_State *error); -typedef enum Tox_Err_Group_Founder_Set_Peer_Limit { +typedef enum Tox_Err_Group_Set_Peer_Limit { /** * The function returned successfully. */ - TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK, + TOX_ERR_GROUP_SET_PEER_LIMIT_OK, /** * The group number passed did not designate a valid group. */ - TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_GROUP_NOT_FOUND, + TOX_ERR_GROUP_SET_PEER_LIMIT_GROUP_NOT_FOUND, /** * The caller does not have the required permissions to set the peer limit. */ - TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_PERMISSIONS, + TOX_ERR_GROUP_SET_PEER_LIMIT_PERMISSIONS, /** - * The peer limit could not be set. This may occur due to an error related to - * cryptographic signing of the new shared state. + * The peer limit could not be set. This may occur due to an error related + * to cryptographic signing of the new shared state. */ - TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SET, + TOX_ERR_GROUP_SET_PEER_LIMIT_FAIL_SET, /** * The packet failed to send. */ - TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SEND, + TOX_ERR_GROUP_SET_PEER_LIMIT_FAIL_SEND, /** * The group is disconnected. */ - TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_DISCONNECTED, + TOX_ERR_GROUP_SET_PEER_LIMIT_DISCONNECTED, -} Tox_Err_Group_Founder_Set_Peer_Limit; +} Tox_Err_Group_Set_Peer_Limit; -const char *tox_err_group_founder_set_peer_limit_to_string(Tox_Err_Group_Founder_Set_Peer_Limit value); +const char *tox_err_group_set_peer_limit_to_string(Tox_Err_Group_Set_Peer_Limit value); /** * Set the group peer limit. * - * This function sets a limit for the number of peers who may be in the group, creates a new - * group shared state including the change, and distributes it to the rest of the group. + * This function allows Founders to set a limit for the number of peers who may + * be in the group. It will create a new group shared state including the change + * and distribute it to the rest of the group. * - * @param group_number The group number of the group for which we wish to set the peer limit. + * @param group_number The group number of the group for which we wish to set + * the peer limit. * @param peer_limit The maximum number of peers to allow in the group. * * @return true on success. */ -bool tox_group_founder_set_peer_limit(Tox *tox, Tox_Group_Number group_number, uint16_t peer_limit, - Tox_Err_Group_Founder_Set_Peer_Limit *error); +bool tox_group_set_peer_limit(Tox *tox, Tox_Group_Number group_number, uint16_t peer_limit, + Tox_Err_Group_Set_Peer_Limit *error); /******************************************************************************* * - * :: Group chat moderation + * :: Group chat moderation controls * ******************************************************************************/ @@ -5393,7 +5127,8 @@ const char *tox_err_group_set_ignore_to_string(Tox_Err_Group_Set_Ignore value); /** * Ignore or unignore a peer. * - * @param group_number The group number of the group in which you wish to ignore a peer. + * @param group_number The group number of the group in which you wish to ignore + * a peer. * @param peer_id The ID of the peer who shall be ignored or unignored. * @param ignore True to ignore the peer, false to unignore the peer. * @@ -5402,123 +5137,134 @@ const char *tox_err_group_set_ignore_to_string(Tox_Err_Group_Set_Ignore value); bool tox_group_set_ignore(Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, bool ignore, Tox_Err_Group_Set_Ignore *error); -typedef enum Tox_Err_Group_Mod_Set_Role { +typedef enum Tox_Err_Group_Set_Role { /** * The function returned successfully. */ - TOX_ERR_GROUP_MOD_SET_ROLE_OK, + TOX_ERR_GROUP_SET_ROLE_OK, /** * The group number passed did not designate a valid group. */ - TOX_ERR_GROUP_MOD_SET_ROLE_GROUP_NOT_FOUND, + TOX_ERR_GROUP_SET_ROLE_GROUP_NOT_FOUND, /** - * The ID passed did not designate a valid peer. Note: you cannot set your own role. + * The ID passed did not designate a valid peer. Note: you cannot set your + * own role. */ - TOX_ERR_GROUP_MOD_SET_ROLE_PEER_NOT_FOUND, + TOX_ERR_GROUP_SET_ROLE_PEER_NOT_FOUND, /** * The caller does not have the required permissions for this action. */ - TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS, + TOX_ERR_GROUP_SET_ROLE_PERMISSIONS, /** - * The role assignment is invalid. This will occur if you try to set a peer's role to - * the role they already have. + * The role assignment is invalid. This will occur if you try to set a + * peer's role to the role they already have. */ - TOX_ERR_GROUP_MOD_SET_ROLE_ASSIGNMENT, + TOX_ERR_GROUP_SET_ROLE_ASSIGNMENT, /** - * The role was not successfully set. This may occur if the packet failed to send, or - * if the role limit has been reached. + * The role was not successfully set. This may occur if the packet failed to + * send, or if the role limit has been reached. */ - TOX_ERR_GROUP_MOD_SET_ROLE_FAIL_ACTION, + TOX_ERR_GROUP_SET_ROLE_FAIL_ACTION, /** * The caller attempted to set their own role. */ - TOX_ERR_GROUP_MOD_SET_ROLE_SELF, + TOX_ERR_GROUP_SET_ROLE_SELF, -} Tox_Err_Group_Mod_Set_Role; +} Tox_Err_Group_Set_Role; -const char *tox_err_group_mod_set_role_to_string(Tox_Err_Group_Mod_Set_Role value); +const char *tox_err_group_set_role_to_string(Tox_Err_Group_Set_Role value); /** * Set a peer's role. * - * This function will first remove the peer's previous role and then assign them a new role. - * It will also send a packet to the rest of the group, requesting that they perform - * the role reassignment. Note: peers cannot be set to the founder role. + * This function will first remove the peer's previous role and then assign them + * a new role. It will also send a packet to the rest of the group, requesting + * that they perform the role reassignment. * - * @param group_number The group number of the group the in which you wish set the peer's role. + * Only Founders may promote peers to the Moderator role, and only Founders and + * Moderators may set peers to the Observer or User role. Moderators may not set + * the role of other Moderators or the Founder. Peers may not be promoted to the + * Founder role. + * + * @param group_number The group number of the group the in which you wish set + * the peer's role. * @param peer_id The ID of the peer whose role you wish to set. * @param role The role you wish to set the peer to. * * @return true on success. */ -bool tox_group_mod_set_role(Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, Tox_Group_Role role, - Tox_Err_Group_Mod_Set_Role *error); +bool tox_group_set_role(Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, Tox_Group_Role role, + Tox_Err_Group_Set_Role *error); -typedef enum Tox_Err_Group_Mod_Kick_Peer { +typedef enum Tox_Err_Group_Kick_Peer { /** * The function returned successfully. */ - TOX_ERR_GROUP_MOD_KICK_PEER_OK, + TOX_ERR_GROUP_KICK_PEER_OK, /** * The group number passed did not designate a valid group. */ - TOX_ERR_GROUP_MOD_KICK_PEER_GROUP_NOT_FOUND, + TOX_ERR_GROUP_KICK_PEER_GROUP_NOT_FOUND, /** * The ID passed did not designate a valid peer. */ - TOX_ERR_GROUP_MOD_KICK_PEER_PEER_NOT_FOUND, + TOX_ERR_GROUP_KICK_PEER_PEER_NOT_FOUND, /** * The caller does not have the required permissions for this action. */ - TOX_ERR_GROUP_MOD_KICK_PEER_PERMISSIONS, + TOX_ERR_GROUP_KICK_PEER_PERMISSIONS, /** * The peer could not be kicked from the group. */ - TOX_ERR_GROUP_MOD_KICK_PEER_FAIL_ACTION, + TOX_ERR_GROUP_KICK_PEER_FAIL_ACTION, /** * The packet failed to send. */ - TOX_ERR_GROUP_MOD_KICK_PEER_FAIL_SEND, + TOX_ERR_GROUP_KICK_PEER_FAIL_SEND, /** * The caller attempted to set their own role. */ - TOX_ERR_GROUP_MOD_KICK_PEER_SELF, + TOX_ERR_GROUP_KICK_PEER_SELF, -} Tox_Err_Group_Mod_Kick_Peer; +} Tox_Err_Group_Kick_Peer; -const char *tox_err_group_mod_kick_peer_to_string(Tox_Err_Group_Mod_Kick_Peer value); +const char *tox_err_group_kick_peer_to_string(Tox_Err_Group_Kick_Peer value); /** * Kick a peer. * - * This function will remove a peer from the caller's peer list and send a packet to all - * group members requesting them to do the same. Note: This function will not trigger - * the `group_peer_exit` event for the caller. + * This function allows peers with the Founder or Moderator role to silently + * instruct all other peers in the group to remove a particular peer from their + * peer list. + * + * Note: This function will not trigger the `group_peer_exit` event for the + * caller. * * @param group_number The group number of the group the action is intended for. * @param peer_id The ID of the peer who will be kicked. * * @return true on success. */ -bool tox_group_mod_kick_peer(const Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, - Tox_Err_Group_Mod_Kick_Peer *error); +bool tox_group_kick_peer(const Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, + Tox_Err_Group_Kick_Peer *error); /** - * Represents moderation events. These should be used with the `group_moderation` event. + * Represents moderation events. These should be used with the + * `group_moderation` event. */ typedef enum Tox_Group_Mod_Event { @@ -5559,12 +5305,13 @@ typedef void tox_group_moderation_cb( /** * Set the callback for the `group_moderation` event. Pass NULL to unset. * - * This event is triggered when a moderator or founder executes a moderation event, with - * the exception of the peer who initiates the event. It is also triggered when the - * observer and moderator lists are silently modified (this may occur during group syncing). + * This event is triggered when a moderator or founder executes a moderation + * event, with the exception of the peer who initiates the event. It is also + * triggered when the observer and moderator lists are silently modified (this + * may occur during group syncing). * - * If either peer id does not designate a valid peer in the group chat, the client should - * manually update all peer roles. + * If either peer id does not designate a valid peer in the group chat, the + * client should manually update all peer roles. */ void tox_callback_group_moderation(Tox *tox, tox_group_moderation_cb *callback); @@ -5579,6 +5326,7 @@ void tox_callback_group_moderation(Tox *tox, tox_group_moderation_cb *callback); //!TOKSTYLE- #ifndef DOXYGEN_IGNORE +#ifndef TOX_HIDE_DEPRECATED typedef Tox_Err_Options_New TOX_ERR_OPTIONS_NEW; typedef Tox_Err_New TOX_ERR_NEW; typedef Tox_Err_Bootstrap TOX_ERR_BOOTSTRAP; @@ -5613,11 +5361,11 @@ typedef Tox_User_Status TOX_USER_STATUS; typedef Tox_Message_Type TOX_MESSAGE_TYPE; typedef Tox_Proxy_Type TOX_PROXY_TYPE; typedef Tox_Savedata_Type TOX_SAVEDATA_TYPE; -typedef Tox_Log_Level TOX_LOG_LEVEL; typedef Tox_Connection TOX_CONNECTION; typedef Tox_File_Control TOX_FILE_CONTROL; typedef Tox_Conference_Type TOX_CONFERENCE_TYPE; typedef enum Tox_File_Kind TOX_FILE_KIND; +#endif /* TOX_HIDE_DEPRECATED */ #endif //!TOKSTYLE+ diff --git a/protocols/Tox/libtox/src/toxcore/tox_api.c b/protocols/Tox/libtox/src/toxcore/tox_api.c index 02791674b5..808cd473f5 100644 --- a/protocols/Tox/libtox/src/toxcore/tox_api.c +++ b/protocols/Tox/libtox/src/toxcore/tox_api.c @@ -1,20 +1,11 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2021 The TokTok team. + * Copyright © 2016-2025 The TokTok team. */ -#include "tox.h" +#include "tox.h" // IWYU pragma: associated -#include <stdlib.h> - -#include "ccompat.h" +#include "tox_options.h" #include "tox_private.h" -#define SET_ERROR_PARAMETER(param, x) \ - do { \ - if (param != nullptr) { \ - *param = x; \ - } \ - } while (0) - uint32_t tox_version_major(void) { return TOX_VERSION_MAJOR; @@ -136,199 +127,6 @@ uint32_t tox_dht_node_public_key_size(void) return TOX_DHT_NODE_PUBLIC_KEY_SIZE; } -bool tox_options_get_ipv6_enabled(const Tox_Options *options) -{ - return options->ipv6_enabled; -} -void tox_options_set_ipv6_enabled(Tox_Options *options, bool ipv6_enabled) -{ - options->ipv6_enabled = ipv6_enabled; -} -bool tox_options_get_udp_enabled(const Tox_Options *options) -{ - return options->udp_enabled; -} -void tox_options_set_udp_enabled(Tox_Options *options, bool udp_enabled) -{ - options->udp_enabled = udp_enabled; -} -Tox_Proxy_Type tox_options_get_proxy_type(const Tox_Options *options) -{ - return options->proxy_type; -} -void tox_options_set_proxy_type(Tox_Options *options, Tox_Proxy_Type proxy_type) -{ - options->proxy_type = proxy_type; -} -const char *tox_options_get_proxy_host(const Tox_Options *options) -{ - return options->proxy_host; -} -void tox_options_set_proxy_host(Tox_Options *options, const char *proxy_host) -{ - options->proxy_host = proxy_host; -} -uint16_t tox_options_get_proxy_port(const Tox_Options *options) -{ - return options->proxy_port; -} -void tox_options_set_proxy_port(Tox_Options *options, uint16_t proxy_port) -{ - options->proxy_port = proxy_port; -} -uint16_t tox_options_get_start_port(const Tox_Options *options) -{ - return options->start_port; -} -void tox_options_set_start_port(Tox_Options *options, uint16_t start_port) -{ - options->start_port = start_port; -} -uint16_t tox_options_get_end_port(const Tox_Options *options) -{ - return options->end_port; -} -void tox_options_set_end_port(Tox_Options *options, uint16_t end_port) -{ - options->end_port = end_port; -} -uint16_t tox_options_get_tcp_port(const Tox_Options *options) -{ - return options->tcp_port; -} -void tox_options_set_tcp_port(Tox_Options *options, uint16_t tcp_port) -{ - options->tcp_port = tcp_port; -} -bool tox_options_get_hole_punching_enabled(const Tox_Options *options) -{ - return options->hole_punching_enabled; -} -void tox_options_set_hole_punching_enabled(Tox_Options *options, bool hole_punching_enabled) -{ - options->hole_punching_enabled = hole_punching_enabled; -} -Tox_Savedata_Type tox_options_get_savedata_type(const Tox_Options *options) -{ - return options->savedata_type; -} -void tox_options_set_savedata_type(Tox_Options *options, Tox_Savedata_Type savedata_type) -{ - options->savedata_type = savedata_type; -} -size_t tox_options_get_savedata_length(const Tox_Options *options) -{ - return options->savedata_length; -} -void tox_options_set_savedata_length(Tox_Options *options, size_t savedata_length) -{ - options->savedata_length = savedata_length; -} -tox_log_cb *tox_options_get_log_callback(const Tox_Options *options) -{ - return options->log_callback; -} -void tox_options_set_log_callback(Tox_Options *options, tox_log_cb *log_callback) -{ - options->log_callback = log_callback; -} -void *tox_options_get_log_user_data(const Tox_Options *options) -{ - return options->log_user_data; -} -void tox_options_set_log_user_data(Tox_Options *options, void *log_user_data) -{ - options->log_user_data = log_user_data; -} -bool tox_options_get_local_discovery_enabled(const Tox_Options *options) -{ - return options->local_discovery_enabled; -} -void tox_options_set_local_discovery_enabled(Tox_Options *options, bool local_discovery_enabled) -{ - options->local_discovery_enabled = local_discovery_enabled; -} -bool tox_options_get_dht_announcements_enabled(const Tox_Options *options) -{ - return options->dht_announcements_enabled; -} -void tox_options_set_dht_announcements_enabled(Tox_Options *options, bool dht_announcements_enabled) -{ - options->dht_announcements_enabled = dht_announcements_enabled; -} -bool tox_options_get_experimental_thread_safety(const Tox_Options *options) -{ - return options->experimental_thread_safety; -} -void tox_options_set_experimental_thread_safety( - Tox_Options *options, bool experimental_thread_safety) -{ - options->experimental_thread_safety = experimental_thread_safety; -} -const Tox_System *tox_options_get_operating_system(const Tox_Options *options) -{ - return options->operating_system; -} -void tox_options_set_operating_system(Tox_Options *options, const Tox_System *operating_system) -{ - options->operating_system = operating_system; -} -bool tox_options_get_experimental_groups_persistence(const Tox_Options *options) -{ - return options->experimental_groups_persistence; -} -void tox_options_set_experimental_groups_persistence( - Tox_Options *options, bool experimental_groups_persistence) -{ - options->experimental_groups_persistence = experimental_groups_persistence; -} - -const uint8_t *tox_options_get_savedata_data(const Tox_Options *options) -{ - return options->savedata_data; -} - -void tox_options_set_savedata_data(Tox_Options *options, const uint8_t *savedata_data, size_t length) -{ - options->savedata_data = savedata_data; - options->savedata_length = length; -} - -void tox_options_default(Tox_Options *options) -{ - if (options != nullptr) { - const Tox_Options default_options = {false}; - *options = default_options; - tox_options_set_ipv6_enabled(options, true); - tox_options_set_udp_enabled(options, true); - tox_options_set_proxy_type(options, TOX_PROXY_TYPE_NONE); - tox_options_set_hole_punching_enabled(options, true); - tox_options_set_local_discovery_enabled(options, true); - tox_options_set_dht_announcements_enabled(options, true); - tox_options_set_experimental_thread_safety(options, false); - tox_options_set_experimental_groups_persistence(options, false); - } -} - -Tox_Options *tox_options_new(Tox_Err_Options_New *error) -{ - Tox_Options *options = (Tox_Options *)calloc(1, sizeof(Tox_Options)); - - if (options != nullptr) { - tox_options_default(options); - SET_ERROR_PARAMETER(error, TOX_ERR_OPTIONS_NEW_OK); - return options; - } - - SET_ERROR_PARAMETER(error, TOX_ERR_OPTIONS_NEW_MALLOC); - return nullptr; -} - -void tox_options_free(Tox_Options *options) -{ - free(options); -} - const char *tox_user_status_to_string(Tox_User_Status value) { switch (value) { @@ -386,27 +184,6 @@ const char *tox_savedata_type_to_string(Tox_Savedata_Type value) return "<invalid Tox_Savedata_Type>"; } -const char *tox_log_level_to_string(Tox_Log_Level value) -{ - switch (value) { - case TOX_LOG_LEVEL_TRACE: - return "TOX_LOG_LEVEL_TRACE"; - - case TOX_LOG_LEVEL_DEBUG: - return "TOX_LOG_LEVEL_DEBUG"; - - case TOX_LOG_LEVEL_INFO: - return "TOX_LOG_LEVEL_INFO"; - - case TOX_LOG_LEVEL_WARNING: - return "TOX_LOG_LEVEL_WARNING"; - - case TOX_LOG_LEVEL_ERROR: - return "TOX_LOG_LEVEL_ERROR"; - } - - return "<invalid Tox_Log_Level>"; -} const char *tox_err_options_new_to_string(Tox_Err_Options_New value) { switch (value) { @@ -895,6 +672,9 @@ const char *tox_err_conference_join_to_string(Tox_Err_Conference_Join value) case TOX_ERR_CONFERENCE_JOIN_FAIL_SEND: return "TOX_ERR_CONFERENCE_JOIN_FAIL_SEND"; + + case TOX_ERR_CONFERENCE_JOIN_NULL: + return "TOX_ERR_CONFERENCE_JOIN_NULL"; } return "<invalid Tox_Err_Conference_Join>"; @@ -1253,17 +1033,17 @@ const char *tox_err_group_peer_query_to_string(Tox_Err_Group_Peer_Query value) return "<invalid Tox_Err_Group_Peer_Query>"; } -const char *tox_err_group_state_queries_to_string(Tox_Err_Group_State_Queries value) +const char *tox_err_group_state_query_to_string(Tox_Err_Group_State_Query value) { switch (value) { - case TOX_ERR_GROUP_STATE_QUERIES_OK: - return "TOX_ERR_GROUP_STATE_QUERIES_OK"; + case TOX_ERR_GROUP_STATE_QUERY_OK: + return "TOX_ERR_GROUP_STATE_QUERY_OK"; - case TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND: - return "TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND"; + case TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND: + return "TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND"; } - return "<invalid Tox_Err_Group_State_Queries>"; + return "<invalid Tox_Err_Group_State_Query>"; } const char *tox_err_group_topic_set_to_string(Tox_Err_Group_Topic_Set value) { @@ -1340,6 +1120,9 @@ const char *tox_err_group_send_private_message_to_string(Tox_Err_Group_Send_Priv case TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_EMPTY: return "TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_EMPTY"; + case TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_BAD_TYPE: + return "TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_BAD_TYPE"; + case TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PERMISSIONS: return "TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PERMISSIONS"; @@ -1348,9 +1131,6 @@ const char *tox_err_group_send_private_message_to_string(Tox_Err_Group_Send_Priv case TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_DISCONNECTED: return "TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_DISCONNECTED"; - - case TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_BAD_TYPE: - return "TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_BAD_TYPE"; } return "<invalid Tox_Err_Group_Send_Private_Message>"; @@ -1370,9 +1150,6 @@ const char *tox_err_group_send_custom_packet_to_string(Tox_Err_Group_Send_Custom case TOX_ERR_GROUP_SEND_CUSTOM_PACKET_EMPTY: return "TOX_ERR_GROUP_SEND_CUSTOM_PACKET_EMPTY"; - case TOX_ERR_GROUP_SEND_CUSTOM_PACKET_PERMISSIONS: - return "TOX_ERR_GROUP_SEND_CUSTOM_PACKET_PERMISSIONS"; - case TOX_ERR_GROUP_SEND_CUSTOM_PACKET_DISCONNECTED: return "TOX_ERR_GROUP_SEND_CUSTOM_PACKET_DISCONNECTED"; @@ -1400,9 +1177,6 @@ const char *tox_err_group_send_custom_private_packet_to_string(Tox_Err_Group_Sen case TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_PEER_NOT_FOUND: return "TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_PEER_NOT_FOUND"; - case TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_PERMISSIONS: - return "TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_PERMISSIONS"; - case TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_FAIL_SEND: return "TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_FAIL_SEND"; @@ -1457,11 +1231,14 @@ const char *tox_err_group_invite_accept_to_string(Tox_Err_Group_Invite_Accept va case TOX_ERR_GROUP_INVITE_ACCEPT_PASSWORD: return "TOX_ERR_GROUP_INVITE_ACCEPT_PASSWORD"; - case TOX_ERR_GROUP_INVITE_ACCEPT_CORE: - return "TOX_ERR_GROUP_INVITE_ACCEPT_CORE"; + case TOX_ERR_GROUP_INVITE_ACCEPT_FRIEND_NOT_FOUND: + return "TOX_ERR_GROUP_INVITE_ACCEPT_FRIEND_NOT_FOUND"; case TOX_ERR_GROUP_INVITE_ACCEPT_FAIL_SEND: return "TOX_ERR_GROUP_INVITE_ACCEPT_FAIL_SEND"; + + case TOX_ERR_GROUP_INVITE_ACCEPT_NULL: + return "TOX_ERR_GROUP_INVITE_ACCEPT_NULL"; } return "<invalid Tox_Err_Group_Invite_Accept>"; @@ -1505,131 +1282,131 @@ const char *tox_group_join_fail_to_string(Tox_Group_Join_Fail value) return "<invalid Tox_Group_Join_Fail>"; } -const char *tox_err_group_founder_set_password_to_string(Tox_Err_Group_Founder_Set_Password value) +const char *tox_err_group_set_password_to_string(Tox_Err_Group_Set_Password value) { switch (value) { - case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK: - return "TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK"; + case TOX_ERR_GROUP_SET_PASSWORD_OK: + return "TOX_ERR_GROUP_SET_PASSWORD_OK"; - case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_GROUP_NOT_FOUND: - return "TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_GROUP_NOT_FOUND"; + case TOX_ERR_GROUP_SET_PASSWORD_GROUP_NOT_FOUND: + return "TOX_ERR_GROUP_SET_PASSWORD_GROUP_NOT_FOUND"; - case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_PERMISSIONS: - return "TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_PERMISSIONS"; + case TOX_ERR_GROUP_SET_PASSWORD_PERMISSIONS: + return "TOX_ERR_GROUP_SET_PASSWORD_PERMISSIONS"; - case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_TOO_LONG: - return "TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_TOO_LONG"; + case TOX_ERR_GROUP_SET_PASSWORD_TOO_LONG: + return "TOX_ERR_GROUP_SET_PASSWORD_TOO_LONG"; - case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_FAIL_SEND: - return "TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_FAIL_SEND"; + case TOX_ERR_GROUP_SET_PASSWORD_FAIL_SEND: + return "TOX_ERR_GROUP_SET_PASSWORD_FAIL_SEND"; - case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_MALLOC: - return "TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_MALLOC"; + case TOX_ERR_GROUP_SET_PASSWORD_MALLOC: + return "TOX_ERR_GROUP_SET_PASSWORD_MALLOC"; - case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_DISCONNECTED: - return "TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_DISCONNECTED"; + case TOX_ERR_GROUP_SET_PASSWORD_DISCONNECTED: + return "TOX_ERR_GROUP_SET_PASSWORD_DISCONNECTED"; } - return "<invalid Tox_Err_Group_Founder_Set_Password>"; + return "<invalid Tox_Err_Group_Set_Password>"; } -const char *tox_err_group_founder_set_topic_lock_to_string(Tox_Err_Group_Founder_Set_Topic_Lock value) +const char *tox_err_group_set_topic_lock_to_string(Tox_Err_Group_Set_Topic_Lock value) { switch (value) { - case TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK: - return "TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK"; + case TOX_ERR_GROUP_SET_TOPIC_LOCK_OK: + return "TOX_ERR_GROUP_SET_TOPIC_LOCK_OK"; - case TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_GROUP_NOT_FOUND: - return "TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_GROUP_NOT_FOUND"; + case TOX_ERR_GROUP_SET_TOPIC_LOCK_GROUP_NOT_FOUND: + return "TOX_ERR_GROUP_SET_TOPIC_LOCK_GROUP_NOT_FOUND"; - case TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_INVALID: - return "TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_INVALID"; + case TOX_ERR_GROUP_SET_TOPIC_LOCK_INVALID: + return "TOX_ERR_GROUP_SET_TOPIC_LOCK_INVALID"; - case TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_PERMISSIONS: - return "TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_PERMISSIONS"; + case TOX_ERR_GROUP_SET_TOPIC_LOCK_PERMISSIONS: + return "TOX_ERR_GROUP_SET_TOPIC_LOCK_PERMISSIONS"; - case TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_FAIL_SET: - return "TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_FAIL_SET"; + case TOX_ERR_GROUP_SET_TOPIC_LOCK_FAIL_SET: + return "TOX_ERR_GROUP_SET_TOPIC_LOCK_FAIL_SET"; - case TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_FAIL_SEND: - return "TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_FAIL_SEND"; + case TOX_ERR_GROUP_SET_TOPIC_LOCK_FAIL_SEND: + return "TOX_ERR_GROUP_SET_TOPIC_LOCK_FAIL_SEND"; - case TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_DISCONNECTED: - return "TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_DISCONNECTED"; + case TOX_ERR_GROUP_SET_TOPIC_LOCK_DISCONNECTED: + return "TOX_ERR_GROUP_SET_TOPIC_LOCK_DISCONNECTED"; } - return "<invalid Tox_Err_Group_Founder_Set_Topic_Lock>"; + return "<invalid Tox_Err_Group_Set_Topic_Lock>"; } -const char *tox_err_group_founder_set_voice_state_to_string(Tox_Err_Group_Founder_Set_Voice_State value) +const char *tox_err_group_set_voice_state_to_string(Tox_Err_Group_Set_Voice_State value) { switch (value) { - case TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_OK: - return "TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_OK"; + case TOX_ERR_GROUP_SET_VOICE_STATE_OK: + return "TOX_ERR_GROUP_SET_VOICE_STATE_OK"; - case TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_GROUP_NOT_FOUND: - return "TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_GROUP_NOT_FOUND"; + case TOX_ERR_GROUP_SET_VOICE_STATE_GROUP_NOT_FOUND: + return "TOX_ERR_GROUP_SET_VOICE_STATE_GROUP_NOT_FOUND"; - case TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_PERMISSIONS: - return "TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_PERMISSIONS"; + case TOX_ERR_GROUP_SET_VOICE_STATE_PERMISSIONS: + return "TOX_ERR_GROUP_SET_VOICE_STATE_PERMISSIONS"; - case TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_FAIL_SET: - return "TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_FAIL_SET"; + case TOX_ERR_GROUP_SET_VOICE_STATE_FAIL_SET: + return "TOX_ERR_GROUP_SET_VOICE_STATE_FAIL_SET"; - case TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_FAIL_SEND: - return "TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_FAIL_SEND"; + case TOX_ERR_GROUP_SET_VOICE_STATE_FAIL_SEND: + return "TOX_ERR_GROUP_SET_VOICE_STATE_FAIL_SEND"; - case TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_DISCONNECTED: - return "TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_DISCONNECTED"; + case TOX_ERR_GROUP_SET_VOICE_STATE_DISCONNECTED: + return "TOX_ERR_GROUP_SET_VOICE_STATE_DISCONNECTED"; } - return "<invalid Tox_Err_Group_Founder_Set_Voice_State>"; + return "<invalid Tox_Err_Group_Set_Voice_State>"; } -const char *tox_err_group_founder_set_privacy_state_to_string(Tox_Err_Group_Founder_Set_Privacy_State value) +const char *tox_err_group_set_privacy_state_to_string(Tox_Err_Group_Set_Privacy_State value) { switch (value) { - case TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK: - return "TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK"; + case TOX_ERR_GROUP_SET_PRIVACY_STATE_OK: + return "TOX_ERR_GROUP_SET_PRIVACY_STATE_OK"; - case TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_GROUP_NOT_FOUND: - return "TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_GROUP_NOT_FOUND"; + case TOX_ERR_GROUP_SET_PRIVACY_STATE_GROUP_NOT_FOUND: + return "TOX_ERR_GROUP_SET_PRIVACY_STATE_GROUP_NOT_FOUND"; - case TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_PERMISSIONS: - return "TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_PERMISSIONS"; + case TOX_ERR_GROUP_SET_PRIVACY_STATE_PERMISSIONS: + return "TOX_ERR_GROUP_SET_PRIVACY_STATE_PERMISSIONS"; - case TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SET: - return "TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SET"; + case TOX_ERR_GROUP_SET_PRIVACY_STATE_FAIL_SET: + return "TOX_ERR_GROUP_SET_PRIVACY_STATE_FAIL_SET"; - case TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SEND: - return "TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SEND"; + case TOX_ERR_GROUP_SET_PRIVACY_STATE_FAIL_SEND: + return "TOX_ERR_GROUP_SET_PRIVACY_STATE_FAIL_SEND"; - case TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_DISCONNECTED: - return "TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_DISCONNECTED"; + case TOX_ERR_GROUP_SET_PRIVACY_STATE_DISCONNECTED: + return "TOX_ERR_GROUP_SET_PRIVACY_STATE_DISCONNECTED"; } - return "<invalid Tox_Err_Group_Founder_Set_Privacy_State>"; + return "<invalid Tox_Err_Group_Set_Privacy_State>"; } -const char *tox_err_group_founder_set_peer_limit_to_string(Tox_Err_Group_Founder_Set_Peer_Limit value) +const char *tox_err_group_set_peer_limit_to_string(Tox_Err_Group_Set_Peer_Limit value) { switch (value) { - case TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK: - return "TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK"; + case TOX_ERR_GROUP_SET_PEER_LIMIT_OK: + return "TOX_ERR_GROUP_SET_PEER_LIMIT_OK"; - case TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_GROUP_NOT_FOUND: - return "TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_GROUP_NOT_FOUND"; + case TOX_ERR_GROUP_SET_PEER_LIMIT_GROUP_NOT_FOUND: + return "TOX_ERR_GROUP_SET_PEER_LIMIT_GROUP_NOT_FOUND"; - case TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_PERMISSIONS: - return "TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_PERMISSIONS"; + case TOX_ERR_GROUP_SET_PEER_LIMIT_PERMISSIONS: + return "TOX_ERR_GROUP_SET_PEER_LIMIT_PERMISSIONS"; - case TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SET: - return "TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SET"; + case TOX_ERR_GROUP_SET_PEER_LIMIT_FAIL_SET: + return "TOX_ERR_GROUP_SET_PEER_LIMIT_FAIL_SET"; - case TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SEND: - return "TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SEND"; + case TOX_ERR_GROUP_SET_PEER_LIMIT_FAIL_SEND: + return "TOX_ERR_GROUP_SET_PEER_LIMIT_FAIL_SEND"; - case TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_DISCONNECTED: - return "TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_DISCONNECTED"; + case TOX_ERR_GROUP_SET_PEER_LIMIT_DISCONNECTED: + return "TOX_ERR_GROUP_SET_PEER_LIMIT_DISCONNECTED"; } - return "<invalid Tox_Err_Group_Founder_Set_Peer_Limit>"; + return "<invalid Tox_Err_Group_Set_Peer_Limit>"; } const char *tox_err_group_set_ignore_to_string(Tox_Err_Group_Set_Ignore value) { @@ -1649,59 +1426,59 @@ const char *tox_err_group_set_ignore_to_string(Tox_Err_Group_Set_Ignore value) return "<invalid Tox_Err_Group_Set_Ignore>"; } -const char *tox_err_group_mod_set_role_to_string(Tox_Err_Group_Mod_Set_Role value) +const char *tox_err_group_set_role_to_string(Tox_Err_Group_Set_Role value) { switch (value) { - case TOX_ERR_GROUP_MOD_SET_ROLE_OK: - return "TOX_ERR_GROUP_MOD_SET_ROLE_OK"; + case TOX_ERR_GROUP_SET_ROLE_OK: + return "TOX_ERR_GROUP_SET_ROLE_OK"; - case TOX_ERR_GROUP_MOD_SET_ROLE_GROUP_NOT_FOUND: - return "TOX_ERR_GROUP_MOD_SET_ROLE_GROUP_NOT_FOUND"; + case TOX_ERR_GROUP_SET_ROLE_GROUP_NOT_FOUND: + return "TOX_ERR_GROUP_SET_ROLE_GROUP_NOT_FOUND"; - case TOX_ERR_GROUP_MOD_SET_ROLE_PEER_NOT_FOUND: - return "TOX_ERR_GROUP_MOD_SET_ROLE_PEER_NOT_FOUND"; + case TOX_ERR_GROUP_SET_ROLE_PEER_NOT_FOUND: + return "TOX_ERR_GROUP_SET_ROLE_PEER_NOT_FOUND"; - case TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS: - return "TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS"; + case TOX_ERR_GROUP_SET_ROLE_PERMISSIONS: + return "TOX_ERR_GROUP_SET_ROLE_PERMISSIONS"; - case TOX_ERR_GROUP_MOD_SET_ROLE_ASSIGNMENT: - return "TOX_ERR_GROUP_MOD_SET_ROLE_ASSIGNMENT"; + case TOX_ERR_GROUP_SET_ROLE_ASSIGNMENT: + return "TOX_ERR_GROUP_SET_ROLE_ASSIGNMENT"; - case TOX_ERR_GROUP_MOD_SET_ROLE_FAIL_ACTION: - return "TOX_ERR_GROUP_MOD_SET_ROLE_FAIL_ACTION"; + case TOX_ERR_GROUP_SET_ROLE_FAIL_ACTION: + return "TOX_ERR_GROUP_SET_ROLE_FAIL_ACTION"; - case TOX_ERR_GROUP_MOD_SET_ROLE_SELF: - return "TOX_ERR_GROUP_MOD_SET_ROLE_SELF"; + case TOX_ERR_GROUP_SET_ROLE_SELF: + return "TOX_ERR_GROUP_SET_ROLE_SELF"; } - return "<invalid Tox_Err_Group_Mod_Set_Role>"; + return "<invalid Tox_Err_Group_Set_Role>"; } -const char *tox_err_group_mod_kick_peer_to_string(Tox_Err_Group_Mod_Kick_Peer value) +const char *tox_err_group_kick_peer_to_string(Tox_Err_Group_Kick_Peer value) { switch (value) { - case TOX_ERR_GROUP_MOD_KICK_PEER_OK: - return "TOX_ERR_GROUP_MOD_KICK_PEER_OK"; + case TOX_ERR_GROUP_KICK_PEER_OK: + return "TOX_ERR_GROUP_KICK_PEER_OK"; - case TOX_ERR_GROUP_MOD_KICK_PEER_GROUP_NOT_FOUND: - return "TOX_ERR_GROUP_MOD_KICK_PEER_GROUP_NOT_FOUND"; + case TOX_ERR_GROUP_KICK_PEER_GROUP_NOT_FOUND: + return "TOX_ERR_GROUP_KICK_PEER_GROUP_NOT_FOUND"; - case TOX_ERR_GROUP_MOD_KICK_PEER_PEER_NOT_FOUND: - return "TOX_ERR_GROUP_MOD_KICK_PEER_PEER_NOT_FOUND"; + case TOX_ERR_GROUP_KICK_PEER_PEER_NOT_FOUND: + return "TOX_ERR_GROUP_KICK_PEER_PEER_NOT_FOUND"; - case TOX_ERR_GROUP_MOD_KICK_PEER_PERMISSIONS: - return "TOX_ERR_GROUP_MOD_KICK_PEER_PERMISSIONS"; + case TOX_ERR_GROUP_KICK_PEER_PERMISSIONS: + return "TOX_ERR_GROUP_KICK_PEER_PERMISSIONS"; - case TOX_ERR_GROUP_MOD_KICK_PEER_FAIL_ACTION: - return "TOX_ERR_GROUP_MOD_KICK_PEER_FAIL_ACTION"; + case TOX_ERR_GROUP_KICK_PEER_FAIL_ACTION: + return "TOX_ERR_GROUP_KICK_PEER_FAIL_ACTION"; - case TOX_ERR_GROUP_MOD_KICK_PEER_FAIL_SEND: - return "TOX_ERR_GROUP_MOD_KICK_PEER_FAIL_SEND"; + case TOX_ERR_GROUP_KICK_PEER_FAIL_SEND: + return "TOX_ERR_GROUP_KICK_PEER_FAIL_SEND"; - case TOX_ERR_GROUP_MOD_KICK_PEER_SELF: - return "TOX_ERR_GROUP_MOD_KICK_PEER_SELF"; + case TOX_ERR_GROUP_KICK_PEER_SELF: + return "TOX_ERR_GROUP_KICK_PEER_SELF"; } - return "<invalid Tox_Err_Group_Mod_Kick_Peer>"; + return "<invalid Tox_Err_Group_Kick_Peer>"; } const char *tox_group_mod_event_to_string(Tox_Group_Mod_Event value) { @@ -1721,3 +1498,120 @@ const char *tox_group_mod_event_to_string(Tox_Group_Mod_Event value) return "<invalid Tox_Group_Mod_Event>"; } +const char *tox_netprof_packet_id_to_string(Tox_Netprof_Packet_Id value) +{ + switch (value) { + case TOX_NETPROF_PACKET_ID_ZERO: + return "TOX_NETPROF_PACKET_ID_ZERO"; + case TOX_NETPROF_PACKET_ID_ONE: + return "TOX_NETPROF_PACKET_ID_ONE"; + case TOX_NETPROF_PACKET_ID_TWO: + return "TOX_NETPROF_PACKET_ID_TWO"; + case TOX_NETPROF_PACKET_ID_TCP_DISCONNECT: + return "TOX_NETPROF_PACKET_ID_TCP_DISCONNECT"; + case TOX_NETPROF_PACKET_ID_FOUR: + return "TOX_NETPROF_PACKET_ID_FOUR"; + case TOX_NETPROF_PACKET_ID_TCP_PONG: + return "TOX_NETPROF_PACKET_ID_TCP_PONG"; + case TOX_NETPROF_PACKET_ID_TCP_OOB_SEND: + return "TOX_NETPROF_PACKET_ID_TCP_OOB_SEND"; + case TOX_NETPROF_PACKET_ID_TCP_OOB_RECV: + return "TOX_NETPROF_PACKET_ID_TCP_OOB_RECV"; + case TOX_NETPROF_PACKET_ID_TCP_ONION_REQUEST: + return "TOX_NETPROF_PACKET_ID_TCP_ONION_REQUEST"; + case TOX_NETPROF_PACKET_ID_TCP_ONION_RESPONSE: + return "TOX_NETPROF_PACKET_ID_TCP_ONION_RESPONSE"; + case TOX_NETPROF_PACKET_ID_TCP_DATA: + return "TOX_NETPROF_PACKET_ID_TCP_DATA"; + case TOX_NETPROF_PACKET_ID_COOKIE_REQUEST: + return "TOX_NETPROF_PACKET_ID_COOKIE_REQUEST"; + case TOX_NETPROF_PACKET_ID_COOKIE_RESPONSE: + return "TOX_NETPROF_PACKET_ID_COOKIE_RESPONSE"; + case TOX_NETPROF_PACKET_ID_CRYPTO_HS: + return "TOX_NETPROF_PACKET_ID_CRYPTO_HS"; + case TOX_NETPROF_PACKET_ID_CRYPTO_DATA: + return "TOX_NETPROF_PACKET_ID_CRYPTO_DATA"; + case TOX_NETPROF_PACKET_ID_CRYPTO: + return "TOX_NETPROF_PACKET_ID_CRYPTO"; + case TOX_NETPROF_PACKET_ID_LAN_DISCOVERY: + return "TOX_NETPROF_PACKET_ID_LAN_DISCOVERY"; + case TOX_NETPROF_PACKET_ID_GC_HANDSHAKE: + return "TOX_NETPROF_PACKET_ID_GC_HANDSHAKE"; + case TOX_NETPROF_PACKET_ID_GC_LOSSLESS: + return "TOX_NETPROF_PACKET_ID_GC_LOSSLESS"; + case TOX_NETPROF_PACKET_ID_GC_LOSSY: + return "TOX_NETPROF_PACKET_ID_GC_LOSSY"; + case TOX_NETPROF_PACKET_ID_ONION_SEND_INITIAL: + return "TOX_NETPROF_PACKET_ID_ONION_SEND_INITIAL"; + case TOX_NETPROF_PACKET_ID_ONION_SEND_1: + return "TOX_NETPROF_PACKET_ID_ONION_SEND_1"; + case TOX_NETPROF_PACKET_ID_ONION_SEND_2: + return "TOX_NETPROF_PACKET_ID_ONION_SEND_2"; + case TOX_NETPROF_PACKET_ID_ANNOUNCE_REQUEST_OLD: + return "TOX_NETPROF_PACKET_ID_ANNOUNCE_REQUEST_OLD"; + case TOX_NETPROF_PACKET_ID_ANNOUNCE_RESPONSE_OLD: + return "TOX_NETPROF_PACKET_ID_ANNOUNCE_RESPONSE_OLD"; + case TOX_NETPROF_PACKET_ID_ONION_DATA_REQUEST: + return "TOX_NETPROF_PACKET_ID_ONION_DATA_REQUEST"; + case TOX_NETPROF_PACKET_ID_ONION_DATA_RESPONSE: + return "TOX_NETPROF_PACKET_ID_ONION_DATA_RESPONSE"; + case TOX_NETPROF_PACKET_ID_ANNOUNCE_REQUEST: + return "TOX_NETPROF_PACKET_ID_ANNOUNCE_REQUEST"; + case TOX_NETPROF_PACKET_ID_ANNOUNCE_RESPONSE: + return "TOX_NETPROF_PACKET_ID_ANNOUNCE_RESPONSE"; + case TOX_NETPROF_PACKET_ID_ONION_RECV_3: + return "TOX_NETPROF_PACKET_ID_ONION_RECV_3"; + case TOX_NETPROF_PACKET_ID_ONION_RECV_2: + return "TOX_NETPROF_PACKET_ID_ONION_RECV_2"; + case TOX_NETPROF_PACKET_ID_ONION_RECV_1: + return "TOX_NETPROF_PACKET_ID_ONION_RECV_1"; + case TOX_NETPROF_PACKET_ID_FORWARD_REQUEST: + return "TOX_NETPROF_PACKET_ID_FORWARD_REQUEST"; + case TOX_NETPROF_PACKET_ID_FORWARDING: + return "TOX_NETPROF_PACKET_ID_FORWARDING"; + case TOX_NETPROF_PACKET_ID_FORWARD_REPLY: + return "TOX_NETPROF_PACKET_ID_FORWARD_REPLY"; + case TOX_NETPROF_PACKET_ID_DATA_SEARCH_REQUEST: + return "TOX_NETPROF_PACKET_ID_DATA_SEARCH_REQUEST"; + case TOX_NETPROF_PACKET_ID_DATA_SEARCH_RESPONSE: + return "TOX_NETPROF_PACKET_ID_DATA_SEARCH_RESPONSE"; + case TOX_NETPROF_PACKET_ID_DATA_RETRIEVE_REQUEST: + return "TOX_NETPROF_PACKET_ID_DATA_RETRIEVE_REQUEST"; + case TOX_NETPROF_PACKET_ID_DATA_RETRIEVE_RESPONSE: + return "TOX_NETPROF_PACKET_ID_DATA_RETRIEVE_RESPONSE"; + case TOX_NETPROF_PACKET_ID_STORE_ANNOUNCE_REQUEST: + return "TOX_NETPROF_PACKET_ID_STORE_ANNOUNCE_REQUEST"; + case TOX_NETPROF_PACKET_ID_STORE_ANNOUNCE_RESPONSE: + return "TOX_NETPROF_PACKET_ID_STORE_ANNOUNCE_RESPONSE"; + case TOX_NETPROF_PACKET_ID_BOOTSTRAP_INFO: + return "TOX_NETPROF_PACKET_ID_BOOTSTRAP_INFO"; + } + + return "<invalid Tox_Netprof_Packet_Id>"; +} +const char *tox_netprof_packet_type_to_string(Tox_Netprof_Packet_Type value) +{ + switch (value) { + case TOX_NETPROF_PACKET_TYPE_TCP_CLIENT: + return "TOX_NETPROF_PACKET_TYPE_TCP_CLIENT"; + case TOX_NETPROF_PACKET_TYPE_TCP_SERVER: + return "TOX_NETPROF_PACKET_TYPE_TCP_SERVER"; + case TOX_NETPROF_PACKET_TYPE_TCP: + return "TOX_NETPROF_PACKET_TYPE_TCP"; + case TOX_NETPROF_PACKET_TYPE_UDP: + return "TOX_NETPROF_PACKET_TYPE_UDP"; + } + + return "<invalid Tox_Netprof_Packet_Type>"; +} +const char *tox_netprof_direction_to_string(Tox_Netprof_Direction value) +{ + switch (value) { + case TOX_NETPROF_DIRECTION_SENT: + return "TOX_NETPROF_DIRECTION_SENT"; + case TOX_NETPROF_DIRECTION_RECV: + return "TOX_NETPROF_DIRECTION_RECV"; + } + + return "<invalid Tox_Netprof_Direction>"; +} diff --git a/protocols/Tox/libtox/src/toxcore/tox_dispatch.c b/protocols/Tox/libtox/src/toxcore/tox_dispatch.c index 5383925bfa..c793f6b582 100644 --- a/protocols/Tox/libtox/src/toxcore/tox_dispatch.c +++ b/protocols/Tox/libtox/src/toxcore/tox_dispatch.c @@ -1,15 +1,15 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2022 The TokTok team. + * Copyright © 2022-2025 The TokTok team. */ #include "tox_dispatch.h" +#include <stdint.h> #include <stdlib.h> #include "attributes.h" #include "ccompat.h" #include "events/events_alloc.h" // IWYU pragma: keep -#include "tox.h" #include "tox_event.h" #include "tox_events.h" @@ -53,7 +53,7 @@ struct Tox_Dispatch { tox_events_group_self_join_cb *group_self_join_callback; tox_events_group_join_fail_cb *group_join_fail_callback; tox_events_group_moderation_cb *group_moderation_callback; - tox_events_dht_get_nodes_response_cb *dht_get_nodes_response_callback; + tox_events_dht_nodes_response_cb *dht_nodes_response_callback; }; Tox_Dispatch *tox_dispatch_new(Tox_Err_Dispatch_New *error) @@ -279,10 +279,10 @@ void tox_events_callback_group_moderation( { dispatch->group_moderation_callback = callback; } -void tox_events_callback_dht_get_nodes_response( - Tox_Dispatch *dispatch, tox_events_dht_get_nodes_response_cb *callback) +void tox_events_callback_dht_nodes_response( + Tox_Dispatch *dispatch, tox_events_dht_nodes_response_cb *callback) { - dispatch->dht_get_nodes_response_callback = callback; + dispatch->dht_nodes_response_callback = callback; } non_null(1, 2) nullable(3) @@ -601,9 +601,9 @@ static void tox_dispatch_invoke_event(const Tox_Dispatch *dispatch, const Tox_Ev break; } - case TOX_EVENT_DHT_GET_NODES_RESPONSE: { - if (dispatch->dht_get_nodes_response_callback != nullptr) { - dispatch->dht_get_nodes_response_callback(event->data.dht_get_nodes_response, user_data); + case TOX_EVENT_DHT_NODES_RESPONSE: { + if (dispatch->dht_nodes_response_callback != nullptr) { + dispatch->dht_nodes_response_callback(event->data.dht_nodes_response, user_data); } break; diff --git a/protocols/Tox/libtox/src/toxcore/tox_dispatch.h b/protocols/Tox/libtox/src/toxcore/tox_dispatch.h index 2588065a4d..6ad3fc8b66 100644 --- a/protocols/Tox/libtox/src/toxcore/tox_dispatch.h +++ b/protocols/Tox/libtox/src/toxcore/tox_dispatch.h @@ -1,5 +1,12 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2022 The TokTok team. + * Copyright © 2022-2025 The TokTok team. + */ + +/** + * WARNING: This is an experimental API and is subject to change. + * + * At this point, it probably won't change very much anymore, but we may have + * small breaking changes before a stable release. */ #ifndef C_TOXCORE_TOXCORE_TOX_DISPATCH_H @@ -129,8 +136,8 @@ typedef void tox_events_group_join_fail_cb( const Tox_Event_Group_Join_Fail *event, void *user_data); typedef void tox_events_group_moderation_cb( const Tox_Event_Group_Moderation *event, void *user_data); -typedef void tox_events_dht_get_nodes_response_cb( - const Tox_Event_Dht_Get_Nodes_Response *event, void *user_data); +typedef void tox_events_dht_nodes_response_cb( + const Tox_Event_Dht_Nodes_Response *event, void *user_data); void tox_events_callback_conference_connected( Tox_Dispatch *dispatch, tox_events_conference_connected_cb *callback); @@ -210,8 +217,8 @@ void tox_events_callback_group_join_fail( Tox_Dispatch *dispatch, tox_events_group_join_fail_cb *callback); void tox_events_callback_group_moderation( Tox_Dispatch *dispatch, tox_events_group_moderation_cb *callback); -void tox_events_callback_dht_get_nodes_response( - Tox_Dispatch *dispatch, tox_events_dht_get_nodes_response_cb *callback); +void tox_events_callback_dht_nodes_response( + Tox_Dispatch *dispatch, tox_events_dht_nodes_response_cb *callback); #ifdef __cplusplus } /* extern "C" */ diff --git a/protocols/Tox/libtox/src/toxcore/tox_event.c b/protocols/Tox/libtox/src/toxcore/tox_event.c index b0a65503cd..0a08b622e9 100644 --- a/protocols/Tox/libtox/src/toxcore/tox_event.c +++ b/protocols/Tox/libtox/src/toxcore/tox_event.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2022 The TokTok team. + * Copyright © 2022-2025 The TokTok team. */ #include "tox_event.h" @@ -133,8 +133,8 @@ const char *tox_event_type_to_string(Tox_Event_Type type) case TOX_EVENT_GROUP_MODERATION: return "TOX_EVENT_GROUP_MODERATION"; - case TOX_EVENT_DHT_GET_NODES_RESPONSE: - return "TOX_EVENT_DHT_GET_NODES_RESPONSE"; + case TOX_EVENT_DHT_NODES_RESPONSE: + return "TOX_EVENT_DHT_NODES_RESPONSE"; case TOX_EVENT_INVALID: return "TOX_EVENT_INVALID"; @@ -350,8 +350,8 @@ bool tox_event_construct(Tox_Event *event, Tox_Event_Type type, const Memory *me break; } - case TOX_EVENT_DHT_GET_NODES_RESPONSE: { - event->data.dht_get_nodes_response = tox_event_dht_get_nodes_response_new(mem); + case TOX_EVENT_DHT_NODES_RESPONSE: { + event->data.dht_nodes_response = tox_event_dht_nodes_response_new(mem); break; } @@ -565,8 +565,8 @@ void tox_event_destruct(Tox_Event *event, const Memory *mem) break; } - case TOX_EVENT_DHT_GET_NODES_RESPONSE: { - tox_event_dht_get_nodes_response_free(event->data.dht_get_nodes_response, mem); + case TOX_EVENT_DHT_NODES_RESPONSE: { + tox_event_dht_nodes_response_free(event->data.dht_nodes_response, mem); break; } @@ -705,8 +705,8 @@ static bool tox_event_data_pack(Tox_Event_Type type, const Tox_Event_Data *data, case TOX_EVENT_GROUP_MODERATION: return tox_event_group_moderation_pack(data->group_moderation, bp); - case TOX_EVENT_DHT_GET_NODES_RESPONSE: - return tox_event_dht_get_nodes_response_pack(data->dht_get_nodes_response, bp); + case TOX_EVENT_DHT_NODES_RESPONSE: + return tox_event_dht_nodes_response_pack(data->dht_nodes_response, bp); case TOX_EVENT_INVALID: return false; @@ -725,216 +725,216 @@ bool tox_event_pack(const Tox_Event *event, Bin_Pack *bp) } non_null() -static bool tox_event_type_from_int(uint32_t value, Tox_Event_Type *out) +static bool tox_event_type_from_int(uint32_t value, Tox_Event_Type *out_enum) { switch (value) { case TOX_EVENT_SELF_CONNECTION_STATUS: { - *out = TOX_EVENT_SELF_CONNECTION_STATUS; + *out_enum = TOX_EVENT_SELF_CONNECTION_STATUS; return true; } case TOX_EVENT_FRIEND_REQUEST: { - *out = TOX_EVENT_FRIEND_REQUEST; + *out_enum = TOX_EVENT_FRIEND_REQUEST; return true; } case TOX_EVENT_FRIEND_CONNECTION_STATUS: { - *out = TOX_EVENT_FRIEND_CONNECTION_STATUS; + *out_enum = TOX_EVENT_FRIEND_CONNECTION_STATUS; return true; } case TOX_EVENT_FRIEND_LOSSY_PACKET: { - *out = TOX_EVENT_FRIEND_LOSSY_PACKET; + *out_enum = TOX_EVENT_FRIEND_LOSSY_PACKET; return true; } case TOX_EVENT_FRIEND_LOSSLESS_PACKET: { - *out = TOX_EVENT_FRIEND_LOSSLESS_PACKET; + *out_enum = TOX_EVENT_FRIEND_LOSSLESS_PACKET; return true; } case TOX_EVENT_FRIEND_NAME: { - *out = TOX_EVENT_FRIEND_NAME; + *out_enum = TOX_EVENT_FRIEND_NAME; return true; } case TOX_EVENT_FRIEND_STATUS: { - *out = TOX_EVENT_FRIEND_STATUS; + *out_enum = TOX_EVENT_FRIEND_STATUS; return true; } case TOX_EVENT_FRIEND_STATUS_MESSAGE: { - *out = TOX_EVENT_FRIEND_STATUS_MESSAGE; + *out_enum = TOX_EVENT_FRIEND_STATUS_MESSAGE; return true; } case TOX_EVENT_FRIEND_MESSAGE: { - *out = TOX_EVENT_FRIEND_MESSAGE; + *out_enum = TOX_EVENT_FRIEND_MESSAGE; return true; } case TOX_EVENT_FRIEND_READ_RECEIPT: { - *out = TOX_EVENT_FRIEND_READ_RECEIPT; + *out_enum = TOX_EVENT_FRIEND_READ_RECEIPT; return true; } case TOX_EVENT_FRIEND_TYPING: { - *out = TOX_EVENT_FRIEND_TYPING; + *out_enum = TOX_EVENT_FRIEND_TYPING; return true; } case TOX_EVENT_FILE_CHUNK_REQUEST: { - *out = TOX_EVENT_FILE_CHUNK_REQUEST; + *out_enum = TOX_EVENT_FILE_CHUNK_REQUEST; return true; } case TOX_EVENT_FILE_RECV: { - *out = TOX_EVENT_FILE_RECV; + *out_enum = TOX_EVENT_FILE_RECV; return true; } case TOX_EVENT_FILE_RECV_CHUNK: { - *out = TOX_EVENT_FILE_RECV_CHUNK; + *out_enum = TOX_EVENT_FILE_RECV_CHUNK; return true; } case TOX_EVENT_FILE_RECV_CONTROL: { - *out = TOX_EVENT_FILE_RECV_CONTROL; + *out_enum = TOX_EVENT_FILE_RECV_CONTROL; return true; } case TOX_EVENT_CONFERENCE_INVITE: { - *out = TOX_EVENT_CONFERENCE_INVITE; + *out_enum = TOX_EVENT_CONFERENCE_INVITE; return true; } case TOX_EVENT_CONFERENCE_CONNECTED: { - *out = TOX_EVENT_CONFERENCE_CONNECTED; + *out_enum = TOX_EVENT_CONFERENCE_CONNECTED; return true; } case TOX_EVENT_CONFERENCE_PEER_LIST_CHANGED: { - *out = TOX_EVENT_CONFERENCE_PEER_LIST_CHANGED; + *out_enum = TOX_EVENT_CONFERENCE_PEER_LIST_CHANGED; return true; } case TOX_EVENT_CONFERENCE_PEER_NAME: { - *out = TOX_EVENT_CONFERENCE_PEER_NAME; + *out_enum = TOX_EVENT_CONFERENCE_PEER_NAME; return true; } case TOX_EVENT_CONFERENCE_TITLE: { - *out = TOX_EVENT_CONFERENCE_TITLE; + *out_enum = TOX_EVENT_CONFERENCE_TITLE; return true; } case TOX_EVENT_CONFERENCE_MESSAGE: { - *out = TOX_EVENT_CONFERENCE_MESSAGE; + *out_enum = TOX_EVENT_CONFERENCE_MESSAGE; return true; } case TOX_EVENT_GROUP_PEER_NAME: { - *out = TOX_EVENT_GROUP_PEER_NAME; + *out_enum = TOX_EVENT_GROUP_PEER_NAME; return true; } case TOX_EVENT_GROUP_PEER_STATUS: { - *out = TOX_EVENT_GROUP_PEER_STATUS; + *out_enum = TOX_EVENT_GROUP_PEER_STATUS; return true; } case TOX_EVENT_GROUP_TOPIC: { - *out = TOX_EVENT_GROUP_TOPIC; + *out_enum = TOX_EVENT_GROUP_TOPIC; return true; } case TOX_EVENT_GROUP_PRIVACY_STATE: { - *out = TOX_EVENT_GROUP_PRIVACY_STATE; + *out_enum = TOX_EVENT_GROUP_PRIVACY_STATE; return true; } case TOX_EVENT_GROUP_VOICE_STATE: { - *out = TOX_EVENT_GROUP_VOICE_STATE; + *out_enum = TOX_EVENT_GROUP_VOICE_STATE; return true; } case TOX_EVENT_GROUP_TOPIC_LOCK: { - *out = TOX_EVENT_GROUP_TOPIC_LOCK; + *out_enum = TOX_EVENT_GROUP_TOPIC_LOCK; return true; } case TOX_EVENT_GROUP_PEER_LIMIT: { - *out = TOX_EVENT_GROUP_PEER_LIMIT; + *out_enum = TOX_EVENT_GROUP_PEER_LIMIT; return true; } case TOX_EVENT_GROUP_PASSWORD: { - *out = TOX_EVENT_GROUP_PASSWORD; + *out_enum = TOX_EVENT_GROUP_PASSWORD; return true; } case TOX_EVENT_GROUP_MESSAGE: { - *out = TOX_EVENT_GROUP_MESSAGE; + *out_enum = TOX_EVENT_GROUP_MESSAGE; return true; } case TOX_EVENT_GROUP_PRIVATE_MESSAGE: { - *out = TOX_EVENT_GROUP_PRIVATE_MESSAGE; + *out_enum = TOX_EVENT_GROUP_PRIVATE_MESSAGE; return true; } case TOX_EVENT_GROUP_CUSTOM_PACKET: { - *out = TOX_EVENT_GROUP_CUSTOM_PACKET; + *out_enum = TOX_EVENT_GROUP_CUSTOM_PACKET; return true; } case TOX_EVENT_GROUP_CUSTOM_PRIVATE_PACKET: { - *out = TOX_EVENT_GROUP_CUSTOM_PRIVATE_PACKET; + *out_enum = TOX_EVENT_GROUP_CUSTOM_PRIVATE_PACKET; return true; } case TOX_EVENT_GROUP_INVITE: { - *out = TOX_EVENT_GROUP_INVITE; + *out_enum = TOX_EVENT_GROUP_INVITE; return true; } case TOX_EVENT_GROUP_PEER_JOIN: { - *out = TOX_EVENT_GROUP_PEER_JOIN; + *out_enum = TOX_EVENT_GROUP_PEER_JOIN; return true; } case TOX_EVENT_GROUP_PEER_EXIT: { - *out = TOX_EVENT_GROUP_PEER_EXIT; + *out_enum = TOX_EVENT_GROUP_PEER_EXIT; return true; } case TOX_EVENT_GROUP_SELF_JOIN: { - *out = TOX_EVENT_GROUP_SELF_JOIN; + *out_enum = TOX_EVENT_GROUP_SELF_JOIN; return true; } case TOX_EVENT_GROUP_JOIN_FAIL: { - *out = TOX_EVENT_GROUP_JOIN_FAIL; + *out_enum = TOX_EVENT_GROUP_JOIN_FAIL; return true; } case TOX_EVENT_GROUP_MODERATION: { - *out = TOX_EVENT_GROUP_MODERATION; + *out_enum = TOX_EVENT_GROUP_MODERATION; return true; } - case TOX_EVENT_DHT_GET_NODES_RESPONSE: { - *out = TOX_EVENT_DHT_GET_NODES_RESPONSE; + case TOX_EVENT_DHT_NODES_RESPONSE: { + *out_enum = TOX_EVENT_DHT_NODES_RESPONSE; return true; } case TOX_EVENT_INVALID: { - *out = TOX_EVENT_INVALID; + *out_enum = TOX_EVENT_INVALID; return true; } default: { - *out = TOX_EVENT_INVALID; + *out_enum = TOX_EVENT_INVALID; return false; } } @@ -1069,8 +1069,8 @@ static bool tox_event_data_unpack(Tox_Event_Type type, Tox_Event_Data *data, Bin case TOX_EVENT_GROUP_MODERATION: return tox_event_group_moderation_unpack(&data->group_moderation, bu, mem); - case TOX_EVENT_DHT_GET_NODES_RESPONSE: - return tox_event_dht_get_nodes_response_unpack(&data->dht_get_nodes_response, bu, mem); + case TOX_EVENT_DHT_NODES_RESPONSE: + return tox_event_dht_nodes_response_unpack(&data->dht_nodes_response, bu, mem); case TOX_EVENT_INVALID: return false; diff --git a/protocols/Tox/libtox/src/toxcore/tox_event.h b/protocols/Tox/libtox/src/toxcore/tox_event.h index fa98aae229..eebc233608 100644 --- a/protocols/Tox/libtox/src/toxcore/tox_event.h +++ b/protocols/Tox/libtox/src/toxcore/tox_event.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2022 The TokTok team. + * Copyright © 2022-2025 The TokTok team. */ #ifndef C_TOXCORE_TOXCORE_TOX_EVENT_H @@ -61,7 +61,7 @@ typedef union Tox_Event_Data { Tox_Event_Group_Self_Join *group_self_join; Tox_Event_Group_Join_Fail *group_join_fail; Tox_Event_Group_Moderation *group_moderation; - Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response; + Tox_Event_Dht_Nodes_Response *dht_nodes_response; } Tox_Event_Data; struct Tox_Event { @@ -113,7 +113,7 @@ non_null() Tox_Event_Group_Peer_Exit *tox_event_group_peer_exit_new(const Memory non_null() Tox_Event_Group_Self_Join *tox_event_group_self_join_new(const Memory *mem); non_null() Tox_Event_Group_Join_Fail *tox_event_group_join_fail_new(const Memory *mem); non_null() Tox_Event_Group_Moderation *tox_event_group_moderation_new(const Memory *mem); -non_null() Tox_Event_Dht_Get_Nodes_Response *tox_event_dht_get_nodes_response_new(const Memory *mem); +non_null() Tox_Event_Dht_Nodes_Response *tox_event_dht_nodes_response_new(const Memory *mem); /** * Destructor. @@ -159,7 +159,7 @@ non_null(2) nullable(1) void tox_event_group_peer_exit_free(Tox_Event_Group_Peer non_null(2) nullable(1) void tox_event_group_self_join_free(Tox_Event_Group_Self_Join *group_self_join, const Memory *mem); non_null(2) nullable(1) void tox_event_group_join_fail_free(Tox_Event_Group_Join_Fail *group_join_fail, const Memory *mem); non_null(2) nullable(1) void tox_event_group_moderation_free(Tox_Event_Group_Moderation *group_moderation, const Memory *mem); -non_null(2) nullable(1) void tox_event_dht_get_nodes_response_free(Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response, const Memory *mem); +non_null(2) nullable(1) void tox_event_dht_nodes_response_free(Tox_Event_Dht_Nodes_Response *dht_nodes_response, const Memory *mem); /** * Pack into msgpack. @@ -205,7 +205,7 @@ non_null() bool tox_event_group_peer_exit_pack(const Tox_Event_Group_Peer_Exit * non_null() bool tox_event_group_self_join_pack(const Tox_Event_Group_Self_Join *event, Bin_Pack *bp); non_null() bool tox_event_group_join_fail_pack(const Tox_Event_Group_Join_Fail *event, Bin_Pack *bp); non_null() bool tox_event_group_moderation_pack(const Tox_Event_Group_Moderation *event, Bin_Pack *bp); -non_null() bool tox_event_dht_get_nodes_response_pack(const Tox_Event_Dht_Get_Nodes_Response *event, Bin_Pack *bp); +non_null() bool tox_event_dht_nodes_response_pack(const Tox_Event_Dht_Nodes_Response *event, Bin_Pack *bp); /** * Unpack from msgpack. @@ -251,7 +251,7 @@ non_null() bool tox_event_group_peer_exit_unpack(Tox_Event_Group_Peer_Exit **eve non_null() bool tox_event_group_self_join_unpack(Tox_Event_Group_Self_Join **event, Bin_Unpack *bu, const Memory *mem); non_null() bool tox_event_group_join_fail_unpack(Tox_Event_Group_Join_Fail **event, Bin_Unpack *bu, const Memory *mem); non_null() bool tox_event_group_moderation_unpack(Tox_Event_Group_Moderation **event, Bin_Unpack *bu, const Memory *mem); -non_null() bool tox_event_dht_get_nodes_response_unpack(Tox_Event_Dht_Get_Nodes_Response **event, Bin_Unpack *bu, const Memory *mem); +non_null() bool tox_event_dht_nodes_response_unpack(Tox_Event_Dht_Nodes_Response **event, Bin_Unpack *bu, const Memory *mem); #ifdef __cplusplus } /* extern "C" */ diff --git a/protocols/Tox/libtox/src/toxcore/tox_events.c b/protocols/Tox/libtox/src/toxcore/tox_events.c index a5d995cf50..81bb76ff8c 100644 --- a/protocols/Tox/libtox/src/toxcore/tox_events.c +++ b/protocols/Tox/libtox/src/toxcore/tox_events.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2022-2024 The TokTok team. + * Copyright © 2022-2025 The TokTok team. */ #include "tox_events.h" @@ -17,7 +17,7 @@ #include "tox.h" #include "tox_event.h" #include "tox_private.h" -#include "tox_struct.h" +#include "tox_struct.h" // IWYU pragma: keep /***************************************************** * @@ -66,7 +66,7 @@ void tox_events_init(Tox *tox) tox_callback_group_self_join(tox, tox_events_handle_group_self_join); tox_callback_group_join_fail(tox, tox_events_handle_group_join_fail); tox_callback_group_moderation(tox, tox_events_handle_group_moderation); - tox_callback_dht_get_nodes_response(tox, tox_events_handle_dht_get_nodes_response); + tox_callback_dht_nodes_response(tox, tox_events_handle_dht_nodes_response); } uint32_t tox_events_get_size(const Tox_Events *events) @@ -173,7 +173,7 @@ Tox_Events *tox_events_load(const Tox_System *sys, const uint8_t *bytes, uint32_ }; events->mem = sys->mem; - if (!bin_unpack_obj(tox_events_unpack_handler, events, bytes, bytes_size)) { + if (!bin_unpack_obj(sys->mem, tox_events_unpack_handler, events, bytes, bytes_size)) { tox_events_free(events); return nullptr; } diff --git a/protocols/Tox/libtox/src/toxcore/tox_events.h b/protocols/Tox/libtox/src/toxcore/tox_events.h index 3edaa7d06b..d82930e450 100644 --- a/protocols/Tox/libtox/src/toxcore/tox_events.h +++ b/protocols/Tox/libtox/src/toxcore/tox_events.h @@ -1,5 +1,12 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2022-2024 The TokTok team. + * Copyright © 2022-2025 The TokTok team. + */ + +/** + * WARNING: This is an experimental API and is subject to change. + * + * At this point, it probably won't change very much anymore, but we may have + * small breaking changes before a stable release. */ #ifndef C_TOXCORE_TOXCORE_TOX_EVENTS_H @@ -248,7 +255,7 @@ uint32_t tox_event_group_message_get_group_number( const Tox_Event_Group_Message *group_message); uint32_t tox_event_group_message_get_peer_id( const Tox_Event_Group_Message *group_message); -Tox_Message_Type tox_event_group_message_get_type( +Tox_Message_Type tox_event_group_message_get_message_type( const Tox_Event_Group_Message *group_message); const uint8_t *tox_event_group_message_get_message( const Tox_Event_Group_Message *group_message); @@ -262,12 +269,14 @@ uint32_t tox_event_group_private_message_get_group_number( const Tox_Event_Group_Private_Message *group_private_message); uint32_t tox_event_group_private_message_get_peer_id( const Tox_Event_Group_Private_Message *group_private_message); -Tox_Message_Type tox_event_group_private_message_get_type( +Tox_Message_Type tox_event_group_private_message_get_message_type( const Tox_Event_Group_Private_Message *group_private_message); const uint8_t *tox_event_group_private_message_get_message( const Tox_Event_Group_Private_Message *group_private_message); uint32_t tox_event_group_private_message_get_message_length( const Tox_Event_Group_Private_Message *group_private_message); +uint32_t tox_event_group_private_message_get_message_id( + const Tox_Event_Group_Private_Message *group_private_message); typedef struct Tox_Event_Group_Custom_Packet Tox_Event_Group_Custom_Packet; uint32_t tox_event_group_custom_packet_get_group_number( @@ -343,15 +352,15 @@ uint32_t tox_event_group_moderation_get_target_peer_id( Tox_Group_Mod_Event tox_event_group_moderation_get_mod_type( const Tox_Event_Group_Moderation *group_moderation); -typedef struct Tox_Event_Dht_Get_Nodes_Response Tox_Event_Dht_Get_Nodes_Response; -const uint8_t *tox_event_dht_get_nodes_response_get_public_key( - const Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response); -const uint8_t *tox_event_dht_get_nodes_response_get_ip( - const Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response); -uint32_t tox_event_dht_get_nodes_response_get_ip_length( - const Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response); -uint16_t tox_event_dht_get_nodes_response_get_port( - const Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response); +typedef struct Tox_Event_Dht_Nodes_Response Tox_Event_Dht_Nodes_Response; +const uint8_t *tox_event_dht_nodes_response_get_public_key( + const Tox_Event_Dht_Nodes_Response *dht_nodes_response); +const uint8_t *tox_event_dht_nodes_response_get_ip( + const Tox_Event_Dht_Nodes_Response *dht_nodes_response); +uint32_t tox_event_dht_nodes_response_get_ip_length( + const Tox_Event_Dht_Nodes_Response *dht_nodes_response); +uint16_t tox_event_dht_nodes_response_get_port( + const Tox_Event_Dht_Nodes_Response *dht_nodes_response); typedef enum Tox_Event_Type { TOX_EVENT_SELF_CONNECTION_STATUS = 0, @@ -401,7 +410,7 @@ typedef enum Tox_Event_Type { TOX_EVENT_GROUP_JOIN_FAIL = 37, TOX_EVENT_GROUP_MODERATION = 38, - TOX_EVENT_DHT_GET_NODES_RESPONSE = 39, + TOX_EVENT_DHT_NODES_RESPONSE = 39, TOX_EVENT_INVALID = 255, } Tox_Event_Type; @@ -498,7 +507,7 @@ const Tox_Event_Group_Join_Fail *tox_event_get_group_join_fail( const Tox_Event *event); const Tox_Event_Group_Moderation *tox_event_get_group_moderation( const Tox_Event *event); -const Tox_Event_Dht_Get_Nodes_Response *tox_event_get_dht_get_nodes_response( +const Tox_Event_Dht_Nodes_Response *tox_event_get_dht_nodes_response( const Tox_Event *event); /** @@ -568,6 +577,8 @@ void tox_events_free(Tox_Events *events); uint32_t tox_events_bytes_size(const Tox_Events *events); bool tox_events_get_bytes(const Tox_Events *events, uint8_t *bytes); +typedef struct Tox_System Tox_System; + Tox_Events *tox_events_load(const Tox_System *sys, const uint8_t *bytes, uint32_t bytes_size); bool tox_events_equal(const Tox_System *sys, const Tox_Events *a, const Tox_Events *b); diff --git a/protocols/Tox/libtox/src/toxcore/tox_log_level.c b/protocols/Tox/libtox/src/toxcore/tox_log_level.c new file mode 100644 index 0000000000..04f83b0f9a --- /dev/null +++ b/protocols/Tox/libtox/src/toxcore/tox_log_level.c @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2016-2025 The TokTok team. + * Copyright © 2013 Tox project. + */ +#include "tox_log_level.h" + +const char *tox_log_level_to_string(Tox_Log_Level value) +{ + switch (value) { + case TOX_LOG_LEVEL_TRACE: + return "TOX_LOG_LEVEL_TRACE"; + + case TOX_LOG_LEVEL_DEBUG: + return "TOX_LOG_LEVEL_DEBUG"; + + case TOX_LOG_LEVEL_INFO: + return "TOX_LOG_LEVEL_INFO"; + + case TOX_LOG_LEVEL_WARNING: + return "TOX_LOG_LEVEL_WARNING"; + + case TOX_LOG_LEVEL_ERROR: + return "TOX_LOG_LEVEL_ERROR"; + } + + return "<invalid Tox_Log_Level>"; +} diff --git a/protocols/Tox/libtox/src/toxcore/tox_log_level.h b/protocols/Tox/libtox/src/toxcore/tox_log_level.h new file mode 100644 index 0000000000..0009ecd54b --- /dev/null +++ b/protocols/Tox/libtox/src/toxcore/tox_log_level.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2022-2025 The TokTok team. + */ + +#ifndef C_TOXCORE_TOXCORE_TOX_LOG_LEVEL_H +#define C_TOXCORE_TOXCORE_TOX_LOG_LEVEL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Severity level of log messages. + */ +typedef enum Tox_Log_Level { + /** + * Very detailed traces including all network activity. + */ + TOX_LOG_LEVEL_TRACE, + + /** + * Debug messages such as which port we bind to. + */ + TOX_LOG_LEVEL_DEBUG, + + /** + * Informational log messages such as video call status changes. + */ + TOX_LOG_LEVEL_INFO, + + /** + * Warnings about internal inconsistency or logic errors. + */ + TOX_LOG_LEVEL_WARNING, + + /** + * Severe unexpected errors caused by external or internal inconsistency. + */ + TOX_LOG_LEVEL_ERROR, +} Tox_Log_Level; + +const char *tox_log_level_to_string(Tox_Log_Level value); + +//!TOKSTYLE- +#ifndef DOXYGEN_IGNORE + +#ifndef TOX_HIDE_DEPRECATED +typedef Tox_Log_Level TOX_LOG_LEVEL; +#endif /* TOX_HIDE_DEPRECATED */ + +#endif +//!TOKSTYLE+ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* C_TOXCORE_TOXCORE_TOX_LOG_LEVEL_H */ diff --git a/protocols/Tox/libtox/src/toxcore/tox_options.c b/protocols/Tox/libtox/src/toxcore/tox_options.c new file mode 100644 index 0000000000..d67a8aebd0 --- /dev/null +++ b/protocols/Tox/libtox/src/toxcore/tox_options.c @@ -0,0 +1,285 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2016-2025 The TokTok team. + * Copyright © 2013 Tox project. + */ + +#include "tox_options.h" + +#include <stdlib.h> // free, malloc, calloc +#include <string.h> // memcpy, strlen + +#include "ccompat.h" // nullptr + +#define SET_ERROR_PARAMETER(param, x) \ + do { \ + if (param != nullptr) { \ + *param = x; \ + } \ + } while (0) + + +bool tox_options_get_ipv6_enabled(const Tox_Options *options) +{ + return options->ipv6_enabled; +} +void tox_options_set_ipv6_enabled(Tox_Options *options, bool ipv6_enabled) +{ + options->ipv6_enabled = ipv6_enabled; +} +bool tox_options_get_udp_enabled(const Tox_Options *options) +{ + return options->udp_enabled; +} +void tox_options_set_udp_enabled(Tox_Options *options, bool udp_enabled) +{ + options->udp_enabled = udp_enabled; +} +Tox_Proxy_Type tox_options_get_proxy_type(const Tox_Options *options) +{ + return options->proxy_type; +} +void tox_options_set_proxy_type(Tox_Options *options, Tox_Proxy_Type proxy_type) +{ + options->proxy_type = proxy_type; +} +const char *tox_options_get_proxy_host(const Tox_Options *options) +{ + return options->proxy_host; +} +bool tox_options_set_proxy_host(Tox_Options *options, const char *proxy_host) +{ + if (!options->experimental_owned_data) { + options->proxy_host = proxy_host; + return true; + } + + if (options->owned_proxy_host != nullptr) { + free(options->owned_proxy_host); + options->owned_proxy_host = nullptr; + } + if (proxy_host == nullptr) { + options->proxy_host = nullptr; + return true; + } + + const size_t proxy_host_length = strlen(proxy_host) + 1; + char *owned_ptr = (char *)malloc(proxy_host_length); + if (owned_ptr == nullptr) { + options->proxy_host = proxy_host; + options->owned_proxy_host = nullptr; + return false; + } + + memcpy(owned_ptr, proxy_host, proxy_host_length); + options->proxy_host = owned_ptr; + options->owned_proxy_host = owned_ptr; + return true; +} +uint16_t tox_options_get_proxy_port(const Tox_Options *options) +{ + return options->proxy_port; +} +void tox_options_set_proxy_port(Tox_Options *options, uint16_t proxy_port) +{ + options->proxy_port = proxy_port; +} +uint16_t tox_options_get_start_port(const Tox_Options *options) +{ + return options->start_port; +} +void tox_options_set_start_port(Tox_Options *options, uint16_t start_port) +{ + options->start_port = start_port; +} +uint16_t tox_options_get_end_port(const Tox_Options *options) +{ + return options->end_port; +} +void tox_options_set_end_port(Tox_Options *options, uint16_t end_port) +{ + options->end_port = end_port; +} +uint16_t tox_options_get_tcp_port(const Tox_Options *options) +{ + return options->tcp_port; +} +void tox_options_set_tcp_port(Tox_Options *options, uint16_t tcp_port) +{ + options->tcp_port = tcp_port; +} +bool tox_options_get_hole_punching_enabled(const Tox_Options *options) +{ + return options->hole_punching_enabled; +} +void tox_options_set_hole_punching_enabled(Tox_Options *options, bool hole_punching_enabled) +{ + options->hole_punching_enabled = hole_punching_enabled; +} +Tox_Savedata_Type tox_options_get_savedata_type(const Tox_Options *options) +{ + return options->savedata_type; +} +void tox_options_set_savedata_type(Tox_Options *options, Tox_Savedata_Type savedata_type) +{ + options->savedata_type = savedata_type; +} +size_t tox_options_get_savedata_length(const Tox_Options *options) +{ + return options->savedata_length; +} +void tox_options_set_savedata_length(Tox_Options *options, size_t savedata_length) +{ + options->savedata_length = savedata_length; +} +tox_log_cb *tox_options_get_log_callback(const Tox_Options *options) +{ + return options->log_callback; +} +void tox_options_set_log_callback(Tox_Options *options, tox_log_cb *log_callback) +{ + options->log_callback = log_callback; +} +void *tox_options_get_log_user_data(const Tox_Options *options) +{ + return options->log_user_data; +} +void tox_options_set_log_user_data(Tox_Options *options, void *log_user_data) +{ + options->log_user_data = log_user_data; +} +bool tox_options_get_local_discovery_enabled(const Tox_Options *options) +{ + return options->local_discovery_enabled; +} +void tox_options_set_local_discovery_enabled(Tox_Options *options, bool local_discovery_enabled) +{ + options->local_discovery_enabled = local_discovery_enabled; +} +bool tox_options_get_dht_announcements_enabled(const Tox_Options *options) +{ + return options->dht_announcements_enabled; +} +void tox_options_set_dht_announcements_enabled(Tox_Options *options, bool dht_announcements_enabled) +{ + options->dht_announcements_enabled = dht_announcements_enabled; +} +bool tox_options_get_experimental_thread_safety(const Tox_Options *options) +{ + return options->experimental_thread_safety; +} +void tox_options_set_experimental_thread_safety( + Tox_Options *options, bool experimental_thread_safety) +{ + options->experimental_thread_safety = experimental_thread_safety; +} +bool tox_options_get_experimental_groups_persistence(const Tox_Options *options) +{ + return options->experimental_groups_persistence; +} +void tox_options_set_experimental_groups_persistence( + Tox_Options *options, bool experimental_groups_persistence) +{ + options->experimental_groups_persistence = experimental_groups_persistence; +} +bool tox_options_get_experimental_disable_dns(const Tox_Options *options) +{ + return options->experimental_disable_dns; +} +void tox_options_set_experimental_disable_dns(Tox_Options *options, bool experimental_disable_dns) +{ + options->experimental_disable_dns = experimental_disable_dns; +} +bool tox_options_get_experimental_owned_data(const Tox_Options *options) +{ + return options->experimental_owned_data; +} +void tox_options_set_experimental_owned_data( + Tox_Options *options, bool experimental_owned_data) +{ + options->experimental_owned_data = experimental_owned_data; +} + +const uint8_t *tox_options_get_savedata_data(const Tox_Options *options) +{ + return options->savedata_data; +} + +bool tox_options_set_savedata_data(Tox_Options *options, const uint8_t *savedata_data, size_t length) +{ + if (!options->experimental_owned_data) { + options->savedata_data = savedata_data; + options->savedata_length = length; + return true; + } + + if (options->owned_savedata_data != nullptr) { + free(options->owned_savedata_data); + options->owned_savedata_data = nullptr; + } + if (savedata_data == nullptr) { + options->savedata_data = nullptr; + options->savedata_length = 0; + return true; + } + + uint8_t *owned_ptr = (uint8_t *)malloc(length); + if (owned_ptr == nullptr) { + options->savedata_data = savedata_data; + options->savedata_length = length; + options->owned_savedata_data = nullptr; + return false; + } + + memcpy(owned_ptr, savedata_data, length); + options->savedata_data = owned_ptr; + options->savedata_length = length; + options->owned_savedata_data = owned_ptr; + return true; +} + +void tox_options_default(Tox_Options *options) +{ + if (options != nullptr) { + // Free any owned data. + tox_options_set_proxy_host(options, nullptr); + tox_options_set_savedata_data(options, nullptr, 0); + + // Set the rest to default values. + const Tox_Options default_options = {false}; + *options = default_options; + tox_options_set_ipv6_enabled(options, true); + tox_options_set_udp_enabled(options, true); + tox_options_set_proxy_type(options, TOX_PROXY_TYPE_NONE); + tox_options_set_hole_punching_enabled(options, true); + tox_options_set_local_discovery_enabled(options, true); + tox_options_set_dht_announcements_enabled(options, true); + tox_options_set_experimental_thread_safety(options, false); + tox_options_set_experimental_groups_persistence(options, false); + tox_options_set_experimental_disable_dns(options, false); + tox_options_set_experimental_owned_data(options, false); + } +} + +Tox_Options *tox_options_new(Tox_Err_Options_New *error) +{ + Tox_Options *options = (Tox_Options *)calloc(1, sizeof(Tox_Options)); + + if (options != nullptr) { + tox_options_default(options); + SET_ERROR_PARAMETER(error, TOX_ERR_OPTIONS_NEW_OK); + return options; + } + + SET_ERROR_PARAMETER(error, TOX_ERR_OPTIONS_NEW_MALLOC); + return nullptr; +} + +void tox_options_free(Tox_Options *options) +{ + if (options != nullptr) { + // Free any owned data. + tox_options_set_proxy_host(options, nullptr); + tox_options_set_savedata_data(options, nullptr, 0); + free(options); + } +} diff --git a/protocols/Tox/libtox/src/toxcore/tox_options.h b/protocols/Tox/libtox/src/toxcore/tox_options.h new file mode 100644 index 0000000000..7d8b7aafaa --- /dev/null +++ b/protocols/Tox/libtox/src/toxcore/tox_options.h @@ -0,0 +1,455 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2016-2025 The TokTok team. + * Copyright © 2013 Tox project. + */ + +#ifndef C_TOXCORE_TOXCORE_TOX_OPTIONS_H +#define C_TOXCORE_TOXCORE_TOX_OPTIONS_H + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#include "tox_log_level.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct Tox; + +/** @{ + * @name Startup options + */ + +/** + * @brief Type of proxy used to connect to TCP relays. + */ +typedef enum Tox_Proxy_Type { + /** + * Don't use a proxy. + */ + TOX_PROXY_TYPE_NONE, + + /** + * HTTP proxy using CONNECT. + */ + TOX_PROXY_TYPE_HTTP, + + /** + * SOCKS proxy for simple socket pipes. + */ + TOX_PROXY_TYPE_SOCKS5, +} Tox_Proxy_Type; + +const char *tox_proxy_type_to_string(Tox_Proxy_Type value); + +/** + * @brief Type of savedata to create the Tox instance from. + */ +typedef enum Tox_Savedata_Type { + /** + * No savedata. + */ + TOX_SAVEDATA_TYPE_NONE, + + /** + * Savedata is one that was obtained from tox_get_savedata. + */ + TOX_SAVEDATA_TYPE_TOX_SAVE, + + /** + * Savedata is a secret key of length TOX_SECRET_KEY_SIZE. + */ + TOX_SAVEDATA_TYPE_SECRET_KEY, +} Tox_Savedata_Type; + +const char *tox_savedata_type_to_string(Tox_Savedata_Type value); + +/** + * @brief This event is triggered when Tox logs an internal message. + * + * This is mostly useful for debugging. This callback can be called from any + * function, not just tox_iterate. This means the user data lifetime must at + * least extend between registering and unregistering it or tox_kill. + * + * Other toxcore modules such as toxav may concurrently call this callback at + * any time. Thus, user code must make sure it is equipped to handle concurrent + * execution, e.g. by employing appropriate mutex locking. + * + * When using the experimental_thread_safety option, no Tox API functions can + * be called from within the log callback. + * + * @param level The severity of the log message. + * @param file The source file from which the message originated. + * @param line The source line from which the message originated. + * @param func The function from which the message originated. + * @param message The log message. + * @param user_data The user data pointer passed to tox_new in options. + */ +typedef void tox_log_cb(struct Tox *tox, Tox_Log_Level level, const char *file, + uint32_t line, const char *func, const char *message, + void *user_data); + +/** + * @brief This struct contains all the startup options for Tox. + * + * You must tox_options_new to allocate an object of this type. + * + * WARNING: Although this struct happens to be visible in the API, it is + * effectively private. Do not allocate this yourself or access members + * directly, as it *will* break binary compatibility frequently. + * + * @deprecated The memory layout of this struct (size, alignment, and field + * order) is not part of the ABI. To remain compatible, prefer to use + * tox_options_new to allocate the object and accessor functions to set the + * members. The struct will become opaque (i.e. the definition will become + * private) in v0.3.0. + */ +typedef struct Tox_Options Tox_Options; + +#ifndef TOX_HIDE_DEPRECATED +struct Tox_Options { + /** + * The type of socket to create. + * + * If this is set to false, an IPv4 socket is created, which subsequently + * only allows IPv4 communication. + * If it is set to true, an IPv6 socket is created, allowing both IPv4 and + * IPv6 communication. + */ + bool ipv6_enabled; + + /** + * Enable the use of UDP communication when available. + * + * Setting this to false will force Tox to use TCP only. Communications will + * need to be relayed through a TCP relay node, potentially slowing them + * down. + * + * If a proxy is enabled, UDP will be disabled if either the Tox library or + * the proxy don't support proxying UDP messages. + */ + bool udp_enabled; + + /** + * Enable local network peer discovery. + * + * Disabling this will cause Tox to not look for peers on the local network. + */ + bool local_discovery_enabled; + + /** + * Enable storing DHT announcements and forwarding corresponding requests. + * + * Disabling this will cause Tox to ignore the relevant packets. + */ + bool dht_announcements_enabled; + + /** + * Pass communications through a proxy. + */ + Tox_Proxy_Type proxy_type; + + /** + * The IP address or DNS name of the proxy to be used. + * + * If used, this must be non-NULL and be a valid DNS name. The name must not + * exceed TOX_MAX_HOSTNAME_LENGTH characters, and be in a NUL-terminated C + * string format (TOX_MAX_HOSTNAME_LENGTH includes the NUL byte). + * + * This member is ignored (it can be NULL) if proxy_type is + * TOX_PROXY_TYPE_NONE. + * + * The data pointed at by this member is owned by the user, so must + * outlive the options object (unless experimental_owned_data is set). + */ + const char *proxy_host; + + /** + * The port to use to connect to the proxy server. + * + * Ports must be in the range (1, 65535). The value is ignored if + * proxy_type is TOX_PROXY_TYPE_NONE. + */ + uint16_t proxy_port; + + /** + * The start port of the inclusive port range to attempt to use. + * + * If both start_port and end_port are 0, the default port range will be + * used: `[33445, 33545]`. + * + * If either start_port or end_port is 0 while the other is non-zero, the + * non-zero port will be the only port in the range. + * + * Having start_port > end_port will yield the same behavior as if + * start_port and end_port were swapped. + */ + uint16_t start_port; + + /** + * The end port of the inclusive port range to attempt to use. + */ + uint16_t end_port; + + /** + * The port to use for the TCP server (relay). If 0, the TCP server is + * disabled. + * + * Enabling it is not required for Tox to function properly. + * + * When enabled, your Tox instance can act as a TCP relay for other Tox + * instance. This leads to increased traffic, thus when writing a client + * it is recommended to enable TCP server only if the user has an option + * to disable it. + */ + uint16_t tcp_port; + + /** + * Enables or disables UDP hole-punching. (Default: enabled). + */ + bool hole_punching_enabled; + + /** + * The type of savedata to load from. + */ + Tox_Savedata_Type savedata_type; + + /** + * The savedata (either a Tox save or a secret key) to load from. + * + * The data pointed at by this member is owned by the user, so must + * outlive the options object (unless experimental_owned_data is set). + */ + const uint8_t *savedata_data; + + /** + * The length of the savedata. + */ + size_t savedata_length; + + /** + * Logging callback for the new Tox instance. + */ + tox_log_cb *log_callback; + + /** + * User data pointer passed to the logging callback. + */ + void *log_user_data; + + /** + * These options are experimental, so avoid writing code that depends on + * them. Options marked "experimental" may change their behaviour or go away + * entirely in the future, or may be renamed to something non-experimental + * if they become part of the supported API. + */ + /** + * Make public API functions thread-safe using a per-instance lock. + * + * Default: false. + */ + bool experimental_thread_safety; + + /** + * Enable saving DHT-based group chats to Tox save data (via + * `tox_get_savedata`). This format will change in the future, so don't rely + * on it. + * + * As an alternative, clients can save the group chat ID in client-owned + * savedata. Then, when the client starts, it can use `tox_group_join` + * with the saved chat ID to recreate the group chat. + * + * Default: false. + */ + bool experimental_groups_persistence; + + /** + * @brief Disable DNS hostname resolution. + * + * Hostnames or IP addresses are passed to the bootstrap/add_tcp_relay + * function and proxy host options. If disabled (this flag is true), only + * IP addresses are allowed. + * + * If this is set to true, the library will not attempt to resolve + * hostnames. This is useful for clients that want to resolve hostnames + * themselves and pass the resolved IP addresses to the library (e.g. in + * case it wants to use Tor). + * Passing hostnames will result in a TOX_ERR_BOOTSTRAP_BAD_HOST error if + * this is set to true. + * + * Default: false. May become true in the future (0.3.0). + */ + bool experimental_disable_dns; + + /** + * @brief Whether the savedata data is owned by the Tox_Options object. + * + * If true, the setters for savedata and proxy_host try to copy the string. + * If that fails, the value is not copied and the member is set to the + * user-provided pointer. In that case, the user must not free the string + * until the Tox_Options object is freed. Client code can check whether + * allocation succeeded by checking the returned bool. If + * experimental_owned_data is false, it will always return true. If set to + * true, the return value will be false on allocation failure. + * + * If set to true, this must be set before any other member that allocates + * memory is set. + */ + bool experimental_owned_data; + + /** + * @brief Owned pointer to the savedata data. + * @private + */ + uint8_t *owned_savedata_data; + + /** + * @brief Owned pointer to the proxy host. + * @private + */ + char *owned_proxy_host; +}; +#endif /* TOX_HIDE_DEPRECATED */ + +bool tox_options_get_ipv6_enabled(const Tox_Options *options); + +void tox_options_set_ipv6_enabled(Tox_Options *options, bool ipv6_enabled); + +bool tox_options_get_udp_enabled(const Tox_Options *options); + +void tox_options_set_udp_enabled(Tox_Options *options, bool udp_enabled); + +bool tox_options_get_local_discovery_enabled(const Tox_Options *options); + +void tox_options_set_local_discovery_enabled(Tox_Options *options, bool local_discovery_enabled); + +bool tox_options_get_dht_announcements_enabled(const Tox_Options *options); + +void tox_options_set_dht_announcements_enabled( + Tox_Options *options, bool dht_announcements_enabled); + +Tox_Proxy_Type tox_options_get_proxy_type(const Tox_Options *options); + +void tox_options_set_proxy_type(Tox_Options *options, Tox_Proxy_Type proxy_type); + +const char *tox_options_get_proxy_host(const Tox_Options *options); + +bool tox_options_set_proxy_host(Tox_Options *options, const char *proxy_host); + +uint16_t tox_options_get_proxy_port(const Tox_Options *options); + +void tox_options_set_proxy_port(Tox_Options *options, uint16_t proxy_port); + +uint16_t tox_options_get_start_port(const Tox_Options *options); + +void tox_options_set_start_port(Tox_Options *options, uint16_t start_port); + +uint16_t tox_options_get_end_port(const Tox_Options *options); + +void tox_options_set_end_port(Tox_Options *options, uint16_t end_port); + +uint16_t tox_options_get_tcp_port(const Tox_Options *options); + +void tox_options_set_tcp_port(Tox_Options *options, uint16_t tcp_port); + +bool tox_options_get_hole_punching_enabled(const Tox_Options *options); + +void tox_options_set_hole_punching_enabled(Tox_Options *options, bool hole_punching_enabled); + +Tox_Savedata_Type tox_options_get_savedata_type(const Tox_Options *options); + +void tox_options_set_savedata_type(Tox_Options *options, Tox_Savedata_Type savedata_type); + +const uint8_t *tox_options_get_savedata_data(const Tox_Options *options); + +bool tox_options_set_savedata_data( + Tox_Options *options, const uint8_t savedata_data[], size_t length); + +size_t tox_options_get_savedata_length(const Tox_Options *options); + +void tox_options_set_savedata_length(Tox_Options *options, size_t savedata_length); + +tox_log_cb *tox_options_get_log_callback(const Tox_Options *options); + +void tox_options_set_log_callback(Tox_Options *options, tox_log_cb *log_callback); + +void *tox_options_get_log_user_data(const Tox_Options *options); + +void tox_options_set_log_user_data(Tox_Options *options, void *log_user_data); + +bool tox_options_get_experimental_owned_data(const Tox_Options *options); + +void tox_options_set_experimental_owned_data(Tox_Options *options, bool experimental_owned_data); + +bool tox_options_get_experimental_thread_safety(const Tox_Options *options); + +void tox_options_set_experimental_thread_safety( + Tox_Options *options, bool experimental_thread_safety); + +bool tox_options_get_experimental_groups_persistence(const Tox_Options *options); + +void tox_options_set_experimental_groups_persistence( + Tox_Options *options, bool experimental_groups_persistence); + +bool tox_options_get_experimental_disable_dns(const Tox_Options *options); + +void tox_options_set_experimental_disable_dns(Tox_Options *options, bool experimental_disable_dns); + +/** + * @brief Initialises a Tox_Options object with the default options. + * + * The result of this function is independent of the original options. All + * values will be overwritten, no values will be read (so it is permissible + * to pass an uninitialised object). + * + * If options is NULL, this function has no effect. + * + * @param options An options object to be filled with default options. + */ +void tox_options_default(Tox_Options *options); + +typedef enum Tox_Err_Options_New { + /** + * The function returned successfully. + */ + TOX_ERR_OPTIONS_NEW_OK, + + /** + * The function failed to allocate enough memory for the options struct. + */ + TOX_ERR_OPTIONS_NEW_MALLOC, +} Tox_Err_Options_New; + +const char *tox_err_options_new_to_string(Tox_Err_Options_New value); + +/** + * @brief Allocates a new Tox_Options object and initialises it with the default + * options. + * + * This function can be used to preserve long term ABI compatibility by + * giving the responsibility of allocation and deallocation to the Tox library. + * + * Objects returned from this function must be freed using the tox_options_free + * function. + * + * @return A new Tox_Options object with default options or NULL on failure. + */ +Tox_Options *tox_options_new(Tox_Err_Options_New *error); + +/** + * @brief Releases all resources associated with an options objects. + * + * Passing a pointer that was not returned by tox_options_new results in + * undefined behaviour. + */ +void tox_options_free(Tox_Options *options); + +/** @} */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* C_TOXCORE_TOXCORE_TOX_OPTIONS_H */ diff --git a/protocols/Tox/libtox/src/toxcore/tox_pack.c b/protocols/Tox/libtox/src/toxcore/tox_pack.c index 3d584ac708..63995c8464 100644 --- a/protocols/Tox/libtox/src/toxcore/tox_pack.c +++ b/protocols/Tox/libtox/src/toxcore/tox_pack.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2022 The TokTok team. + * Copyright © 2022-2025 The TokTok team. */ #include "tox_pack.h" diff --git a/protocols/Tox/libtox/src/toxcore/tox_pack.h b/protocols/Tox/libtox/src/toxcore/tox_pack.h index ea8605dcc3..895cd232bb 100644 --- a/protocols/Tox/libtox/src/toxcore/tox_pack.h +++ b/protocols/Tox/libtox/src/toxcore/tox_pack.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2022 The TokTok team. + * Copyright © 2022-2025 The TokTok team. */ #ifndef C_TOXCORE_TOXCORE_TOX_PACK_H diff --git a/protocols/Tox/libtox/src/toxcore/tox_private.c b/protocols/Tox/libtox/src/toxcore/tox_private.c index 7b6050a9f8..dd9c63cd36 100644 --- a/protocols/Tox/libtox/src/toxcore/tox_private.c +++ b/protocols/Tox/libtox/src/toxcore/tox_private.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2022 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ @@ -11,16 +11,19 @@ #include <assert.h> #include "DHT.h" -#include "attributes.h" +#include "Messenger.h" +#include "TCP_server.h" #include "ccompat.h" #include "crypto_core.h" #include "group_chats.h" #include "group_common.h" +#include "logger.h" #include "mem.h" #include "net_crypto.h" +#include "net_profile.h" #include "network.h" #include "tox.h" -#include "tox_struct.h" +#include "tox_struct.h" // IWYU pragma: keep #define SET_ERROR_PARAMETER(param, x) \ do { \ @@ -91,43 +94,43 @@ void *tox_get_av_object(const Tox *tox) return object; } -void tox_callback_dht_get_nodes_response(Tox *tox, tox_dht_get_nodes_response_cb *callback) +void tox_callback_dht_nodes_response(Tox *tox, tox_dht_nodes_response_cb *callback) { assert(tox != nullptr); - tox->dht_get_nodes_response_callback = callback; + tox->dht_nodes_response_callback = callback; } -bool tox_dht_get_nodes(const Tox *tox, const uint8_t *public_key, const char *ip, uint16_t port, - const uint8_t *target_public_key, Tox_Err_Dht_Get_Nodes *error) +bool tox_dht_send_nodes_request(const Tox *tox, const uint8_t *public_key, const char *ip, uint16_t port, + const uint8_t *target_public_key, Tox_Err_Dht_Send_Nodes_Request *error) { assert(tox != nullptr); tox_lock(tox); if (tox->m->options.udp_disabled) { - SET_ERROR_PARAMETER(error, TOX_ERR_DHT_GET_NODES_UDP_DISABLED); + SET_ERROR_PARAMETER(error, TOX_ERR_DHT_SEND_NODES_REQUEST_UDP_DISABLED); tox_unlock(tox); return false; } if (public_key == nullptr || ip == nullptr || target_public_key == nullptr) { - SET_ERROR_PARAMETER(error, TOX_ERR_DHT_GET_NODES_NULL); + SET_ERROR_PARAMETER(error, TOX_ERR_DHT_SEND_NODES_REQUEST_NULL); tox_unlock(tox); return false; } if (port == 0) { - SET_ERROR_PARAMETER(error, TOX_ERR_DHT_GET_NODES_BAD_PORT); + SET_ERROR_PARAMETER(error, TOX_ERR_DHT_SEND_NODES_REQUEST_BAD_PORT); tox_unlock(tox); return false; } IP_Port *root; - const int32_t count = net_getipport(tox->sys.mem, ip, &root, TOX_SOCK_DGRAM); + const int32_t count = net_getipport(tox->sys.ns, tox->sys.mem, ip, &root, TOX_SOCK_DGRAM, tox->m->options.dns_enabled); if (count < 1) { - SET_ERROR_PARAMETER(error, TOX_ERR_DHT_GET_NODES_BAD_IP); + SET_ERROR_PARAMETER(error, TOX_ERR_DHT_SEND_NODES_REQUEST_BAD_IP); net_freeipport(tox->sys.mem, root); tox_unlock(tox); return false; @@ -138,7 +141,7 @@ bool tox_dht_get_nodes(const Tox *tox, const uint8_t *public_key, const char *ip for (int32_t i = 0; i < count; ++i) { root[i].port = net_htons(port); - if (dht_getnodes(tox->m->dht, &root[i], public_key, target_public_key)) { + if (dht_send_nodes_request(tox->m->dht, &root[i], public_key, target_public_key)) { success = true; } } @@ -148,11 +151,11 @@ bool tox_dht_get_nodes(const Tox *tox, const uint8_t *public_key, const char *ip net_freeipport(tox->sys.mem, root); if (!success) { - SET_ERROR_PARAMETER(error, TOX_ERR_DHT_GET_NODES_FAIL); + SET_ERROR_PARAMETER(error, TOX_ERR_DHT_SEND_NODES_REQUEST_FAIL); return false; } - SET_ERROR_PARAMETER(error, TOX_ERR_DHT_GET_NODES_OK); + SET_ERROR_PARAMETER(error, TOX_ERR_DHT_SEND_NODES_REQUEST_OK); return true; } @@ -226,3 +229,199 @@ bool tox_group_peer_get_ip_address(const Tox *tox, uint32_t group_number, uint32 SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_OK); return true; } + +uint64_t tox_netprof_get_packet_id_count(const Tox *tox, Tox_Netprof_Packet_Type type, uint8_t id, + Tox_Netprof_Direction direction) +{ + assert(tox != nullptr); + + tox_lock(tox); + + const Net_Profile *tcp_c_profile = tox->m->tcp_np; + const Net_Profile *tcp_s_profile = tcp_server_get_net_profile(tox->m->tcp_server); + + const Packet_Direction dir = (Packet_Direction) direction; + + uint64_t count = 0; + + switch (type) { + case TOX_NETPROF_PACKET_TYPE_TCP_CLIENT: { + count = netprof_get_packet_count_id(tcp_c_profile, id, dir); + break; + } + + case TOX_NETPROF_PACKET_TYPE_TCP_SERVER: { + count = netprof_get_packet_count_id(tcp_s_profile, id, dir); + break; + } + + case TOX_NETPROF_PACKET_TYPE_TCP: { + const uint64_t tcp_c_count = netprof_get_packet_count_id(tcp_c_profile, id, dir); + const uint64_t tcp_s_count = netprof_get_packet_count_id(tcp_s_profile, id, dir); + count = tcp_c_count + tcp_s_count; + break; + } + + case TOX_NETPROF_PACKET_TYPE_UDP: { + const Net_Profile *udp_profile = net_get_net_profile(tox->m->net); + count = netprof_get_packet_count_id(udp_profile, id, dir); + break; + } + + default: { + LOGGER_ERROR(tox->m->log, "invalid packet type: %d", type); + break; + } + } + + tox_unlock(tox); + + return count; +} + +uint64_t tox_netprof_get_packet_total_count(const Tox *tox, Tox_Netprof_Packet_Type type, + Tox_Netprof_Direction direction) +{ + assert(tox != nullptr); + + tox_lock(tox); + + const Net_Profile *tcp_c_profile = tox->m->tcp_np; + const Net_Profile *tcp_s_profile = tcp_server_get_net_profile(tox->m->tcp_server); + + const Packet_Direction dir = (Packet_Direction) direction; + + uint64_t count = 0; + + switch (type) { + case TOX_NETPROF_PACKET_TYPE_TCP_CLIENT: { + count = netprof_get_packet_count_total(tcp_c_profile, dir); + break; + } + + case TOX_NETPROF_PACKET_TYPE_TCP_SERVER: { + count = netprof_get_packet_count_total(tcp_s_profile, dir); + break; + } + + case TOX_NETPROF_PACKET_TYPE_TCP: { + const uint64_t tcp_c_count = netprof_get_packet_count_total(tcp_c_profile, dir); + const uint64_t tcp_s_count = netprof_get_packet_count_total(tcp_s_profile, dir); + count = tcp_c_count + tcp_s_count; + break; + } + + case TOX_NETPROF_PACKET_TYPE_UDP: { + const Net_Profile *udp_profile = net_get_net_profile(tox->m->net); + count = netprof_get_packet_count_total(udp_profile, dir); + break; + } + + default: { + LOGGER_ERROR(tox->m->log, "invalid packet type: %d", type); + break; + } + } + + tox_unlock(tox); + + return count; +} + +uint64_t tox_netprof_get_packet_id_bytes(const Tox *tox, Tox_Netprof_Packet_Type type, uint8_t id, + Tox_Netprof_Direction direction) +{ + assert(tox != nullptr); + + tox_lock(tox); + + const Net_Profile *tcp_c_profile = tox->m->tcp_np; + const Net_Profile *tcp_s_profile = tcp_server_get_net_profile(tox->m->tcp_server); + + const Packet_Direction dir = (Packet_Direction) direction; + + uint64_t bytes = 0; + + switch (type) { + case TOX_NETPROF_PACKET_TYPE_TCP_CLIENT: { + bytes = netprof_get_bytes_id(tcp_c_profile, id, dir); + break; + } + + case TOX_NETPROF_PACKET_TYPE_TCP_SERVER: { + bytes = netprof_get_bytes_id(tcp_s_profile, id, dir); + break; + } + + case TOX_NETPROF_PACKET_TYPE_TCP: { + const uint64_t tcp_c_bytes = netprof_get_bytes_id(tcp_c_profile, id, dir); + const uint64_t tcp_s_bytes = netprof_get_bytes_id(tcp_s_profile, id, dir); + bytes = tcp_c_bytes + tcp_s_bytes; + break; + } + + case TOX_NETPROF_PACKET_TYPE_UDP: { + const Net_Profile *udp_profile = net_get_net_profile(tox->m->net); + bytes = netprof_get_bytes_id(udp_profile, id, dir); + break; + } + + default: { + LOGGER_ERROR(tox->m->log, "invalid packet type: %d", type); + break; + } + } + + tox_unlock(tox); + + return bytes; +} + +uint64_t tox_netprof_get_packet_total_bytes(const Tox *tox, Tox_Netprof_Packet_Type type, + Tox_Netprof_Direction direction) +{ + assert(tox != nullptr); + + tox_lock(tox); + + const Net_Profile *tcp_c_profile = tox->m->tcp_np; + const Net_Profile *tcp_s_profile = tcp_server_get_net_profile(tox->m->tcp_server); + + const Packet_Direction dir = (Packet_Direction) direction; + + uint64_t bytes = 0; + + switch (type) { + case TOX_NETPROF_PACKET_TYPE_TCP_CLIENT: { + bytes = netprof_get_bytes_total(tcp_c_profile, dir); + break; + } + + case TOX_NETPROF_PACKET_TYPE_TCP_SERVER: { + bytes = netprof_get_bytes_total(tcp_s_profile, dir); + break; + } + + case TOX_NETPROF_PACKET_TYPE_TCP: { + const uint64_t tcp_c_bytes = netprof_get_bytes_total(tcp_c_profile, dir); + const uint64_t tcp_s_bytes = netprof_get_bytes_total(tcp_s_profile, dir); + bytes = tcp_c_bytes + tcp_s_bytes; + break; + } + + case TOX_NETPROF_PACKET_TYPE_UDP: { + const Net_Profile *udp_profile = net_get_net_profile(tox->m->net); + bytes = netprof_get_bytes_total(udp_profile, dir); + break; + } + + default: { + LOGGER_ERROR(tox->m->log, "invalid packet type: %d", type); + break; + } + } + + tox_unlock(tox); + + return bytes; +} diff --git a/protocols/Tox/libtox/src/toxcore/tox_private.h b/protocols/Tox/libtox/src/toxcore/tox_private.h index d36ab026c3..4cc3edd00c 100644 --- a/protocols/Tox/libtox/src/toxcore/tox_private.h +++ b/protocols/Tox/libtox/src/toxcore/tox_private.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2020 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ @@ -11,6 +11,7 @@ #include <stdint.h> #include "tox.h" +#include "tox_options.h" #ifdef __cplusplus extern "C" { @@ -18,38 +19,49 @@ extern "C" { typedef uint64_t tox_mono_time_cb(void *user_data); -struct Tox_System { +typedef struct Tox_System { tox_mono_time_cb *mono_time_callback; void *mono_time_user_data; const struct Random *rng; const struct Network *ns; const struct Memory *mem; -}; +} Tox_System; Tox_System tox_default_system(void); +const Tox_System *tox_get_system(Tox *tox); + +typedef struct Tox_Options_Testing { + const struct Tox_System *operating_system; +} Tox_Options_Testing; + +typedef enum Tox_Err_New_Testing { + TOX_ERR_NEW_TESTING_OK, + TOX_ERR_NEW_TESTING_NULL, +} Tox_Err_New_Testing; + +Tox *tox_new_testing(const Tox_Options *options, Tox_Err_New *error, const Tox_Options_Testing *testing, Tox_Err_New_Testing *testing_error); + void tox_lock(const Tox *tox); void tox_unlock(const Tox *tox); -const Tox_System *tox_get_system(Tox *tox); - /** - * Set the callback for the `friend_lossy_packet` event for a specific packet ID. - * Pass NULL to unset. + * Set the callback for the `friend_lossy_packet` event for a specific packet + * ID. Pass NULL to unset. * * allowed packet ID range: - * from `PACKET_ID_RANGE_LOSSY_START` to `PACKET_ID_RANGE_LOSSY_END` (both inclusive) + * from `PACKET_ID_RANGE_LOSSY_START` to `PACKET_ID_RANGE_LOSSY_END` (both + * inclusive) */ void tox_callback_friend_lossy_packet_per_pktid(Tox *tox, tox_friend_lossy_packet_cb *callback, uint8_t pktid); /** - * Set the callback for the `friend_lossless_packet` event for a specific packet ID. - * Pass NULL to unset. + * Set the callback for the `friend_lossless_packet` event for a specific packet + * ID. Pass NULL to unset. * * allowed packet ID range: - * from `PACKET_ID_RANGE_LOSSLESS_CUSTOM_START` to `PACKET_ID_RANGE_LOSSLESS_CUSTOM_END` (both inclusive) - * and - * `PACKET_ID_MSI` + * from `PACKET_ID_RANGE_LOSSLESS_CUSTOM_START` to + * `PACKET_ID_RANGE_LOSSLESS_CUSTOM_END` (both inclusive) and `PACKET_ID_MSI` */ void tox_callback_friend_lossless_packet_per_pktid(Tox *tox, tox_friend_lossless_packet_cb *callback, uint8_t pktid); @@ -78,69 +90,73 @@ uint32_t tox_dht_node_public_key_size(void); /** * @param public_key The node's public key. - * @param ip The node's IP address, represented as a null terminated string. + * @param ip The node's IP address, represented as a NUL-terminated C string. * @param port The node's port. */ -typedef void tox_dht_get_nodes_response_cb(Tox *tox, const uint8_t *public_key, const char *ip, uint16_t port, - void *user_data); +typedef void tox_dht_nodes_response_cb( + Tox *tox, const uint8_t *public_key, const char *ip, uint32_t ip_length, + uint16_t port, void *user_data); /** - * Set the callback for the `dht_get_nodes_response` event. Pass NULL to unset. + * Set the callback for the `dht_nodes_response` event. Pass NULL to unset. * - * This event is triggered when a getnodes response is received from a DHT peer. + * This event is triggered when a nodes response is received from a DHT peer. */ -void tox_callback_dht_get_nodes_response(Tox *tox, tox_dht_get_nodes_response_cb *callback); +void tox_callback_dht_nodes_response(Tox *tox, tox_dht_nodes_response_cb *callback); -typedef enum Tox_Err_Dht_Get_Nodes { +typedef enum Tox_Err_Dht_Send_Nodes_Request { /** * The function returned successfully. */ - TOX_ERR_DHT_GET_NODES_OK, + TOX_ERR_DHT_SEND_NODES_REQUEST_OK, /** - * UDP is disabled in tox options; the DHT can only be queried when UDP is enabled. + * UDP is disabled in Tox options; the DHT can only be queried when UDP is + * enabled. */ - TOX_ERR_DHT_GET_NODES_UDP_DISABLED, + TOX_ERR_DHT_SEND_NODES_REQUEST_UDP_DISABLED, /** * One of the arguments to the function was NULL when it was not expected. */ - TOX_ERR_DHT_GET_NODES_NULL, + TOX_ERR_DHT_SEND_NODES_REQUEST_NULL, /** * The supplied port is invalid. */ - TOX_ERR_DHT_GET_NODES_BAD_PORT, + TOX_ERR_DHT_SEND_NODES_REQUEST_BAD_PORT, /** * The supplied IP address is invalid. */ - TOX_ERR_DHT_GET_NODES_BAD_IP, + TOX_ERR_DHT_SEND_NODES_REQUEST_BAD_IP, /** - * The getnodes request failed. This usually means the packet failed to send. + * The nodes request failed. This usually means the packet failed to + * send. */ - TOX_ERR_DHT_GET_NODES_FAIL, -} Tox_Err_Dht_Get_Nodes; + TOX_ERR_DHT_SEND_NODES_REQUEST_FAIL, +} Tox_Err_Dht_Send_Nodes_Request; /** - * This function sends a getnodes request to a DHT node for its peers that - * are "close" to the passed target public key according to the distance metric used - * by the DHT implementation. + * This function sends a nodes request to a DHT node for its peers that + * are "close" to the passed target public key according to the distance metric + * used by the DHT implementation. * - * @param public_key The public key of the node that we wish to query. This key must be - * at least `TOX_DHT_NODE_PUBLIC_KEY_SIZE` bytes in length. - * @param ip A NULL terminated string representing the IP address of the node we wish to query. + * @param public_key The public key of the node that we wish to query. This key + * must be at least `TOX_DHT_NODE_PUBLIC_KEY_SIZE` bytes in length. + * @param ip A NUL-terminated C string representing the IP address of the node + * we wish to query. * @param port The port of the node we wish to query. - * @param target_public_key The public key for which we want to find close nodes. + * @param target_public_key The public key for which we want to find close + * nodes. * * @return true on success. */ -bool tox_dht_get_nodes(const Tox *tox, const uint8_t *public_key, const char *ip, uint16_t port, - const uint8_t *target_public_key, Tox_Err_Dht_Get_Nodes *error); +bool tox_dht_send_nodes_request(const Tox *tox, const uint8_t *public_key, const char *ip, uint16_t port, + const uint8_t *target_public_key, Tox_Err_Dht_Send_Nodes_Request *error); /** - * This function returns the ratio of close dht nodes that are known to support announce/store. * This function returns the number of DHT nodes in the closelist. * * @return number @@ -148,8 +164,8 @@ bool tox_dht_get_nodes(const Tox *tox, const uint8_t *public_key, const char *ip uint16_t tox_dht_get_num_closelist(const Tox *tox); /** - * This function returns the number of DHT nodes in the closelist, - * that are capable to store annouce data (introduced in version 0.2.18). + * This function returns the number of DHT nodes in the closelist + * that are capable of storing announce data (introduced in version 0.2.18). * * @return number */ @@ -157,6 +173,267 @@ uint16_t tox_dht_get_num_closelist_announce_capable(const Tox *tox); /******************************************************************************* * + * :: Network profiler + * + ******************************************************************************/ + + +/** + * Represents all of the network packet identifiers that Toxcore uses. + * + * Notes: + * - Some packet ID's have different purposes depending on the + * packet type. These ID's are given numeral names. + * + * - Queries for invalid packet ID's return undefined results. For example, + * querying a TCP-exclusive packet ID for UDP, or querying an ID that + * doesn't exist in this enum. + */ +typedef enum Tox_Netprof_Packet_Id { + /** + * Ping request packet (UDP). + * Routing request (TCP). + */ + TOX_NETPROF_PACKET_ID_ZERO = 0x00, + + /** + * Ping response packet (UDP). + * Routing response (TCP). + */ + TOX_NETPROF_PACKET_ID_ONE = 0x01, + + /** + * Nodes request packet (UDP). + * Connection notification (TCP). + */ + TOX_NETPROF_PACKET_ID_TWO = 0x02, + + /** + * TCP disconnect notification. + */ + TOX_NETPROF_PACKET_ID_TCP_DISCONNECT = 0x03, + + /** + * Nodes response packet (UDP). + * Ping packet (TCP). + */ + TOX_NETPROF_PACKET_ID_FOUR = 0x04, + + /** + * TCP pong packet. + */ + TOX_NETPROF_PACKET_ID_TCP_PONG = 0x05, + + /** + * TCP out-of-band send packet. + */ + TOX_NETPROF_PACKET_ID_TCP_OOB_SEND = 0x06, + + /** + * TCP out-of-band receive packet. + */ + TOX_NETPROF_PACKET_ID_TCP_OOB_RECV = 0x07, + + /** + * TCP onion request packet. + */ + TOX_NETPROF_PACKET_ID_TCP_ONION_REQUEST = 0x08, + + /** + * TCP onion response packet. + */ + TOX_NETPROF_PACKET_ID_TCP_ONION_RESPONSE = 0x09, + + /** + * TCP data packet. + */ + TOX_NETPROF_PACKET_ID_TCP_DATA = 0x10, + + /** + * Cookie request packet. + */ + TOX_NETPROF_PACKET_ID_COOKIE_REQUEST = 0x18, + + /** + * Cookie response packet. + */ + TOX_NETPROF_PACKET_ID_COOKIE_RESPONSE = 0x19, + + /** + * Crypto handshake packet. + */ + TOX_NETPROF_PACKET_ID_CRYPTO_HS = 0x1a, + + /** + * Crypto data packet. + */ + TOX_NETPROF_PACKET_ID_CRYPTO_DATA = 0x1b, + + /** + * Encrypted data packet. + */ + TOX_NETPROF_PACKET_ID_CRYPTO = 0x20, + + /** + * LAN discovery packet. + */ + TOX_NETPROF_PACKET_ID_LAN_DISCOVERY = 0x21, + + /** + * DHT groupchat packets. + */ + TOX_NETPROF_PACKET_ID_GC_HANDSHAKE = 0x5a, + TOX_NETPROF_PACKET_ID_GC_LOSSLESS = 0x5b, + TOX_NETPROF_PACKET_ID_GC_LOSSY = 0x5c, + + /** + * Onion send packets. + */ + TOX_NETPROF_PACKET_ID_ONION_SEND_INITIAL = 0x80, + TOX_NETPROF_PACKET_ID_ONION_SEND_1 = 0x81, + TOX_NETPROF_PACKET_ID_ONION_SEND_2 = 0x82, + + /** + * DHT announce request packet (deprecated). + */ + TOX_NETPROF_PACKET_ID_ANNOUNCE_REQUEST_OLD = 0x83, + + /** + * DHT announce response packet (deprecated). + */ + TOX_NETPROF_PACKET_ID_ANNOUNCE_RESPONSE_OLD = 0x84, + + /** + * Onion data request packet. + */ + TOX_NETPROF_PACKET_ID_ONION_DATA_REQUEST = 0x85, + + /** + * Onion data response packet. + */ + TOX_NETPROF_PACKET_ID_ONION_DATA_RESPONSE = 0x86, + + /** + * DHT announce request packet. + */ + TOX_NETPROF_PACKET_ID_ANNOUNCE_REQUEST = 0x87, + + /** + * DHT announce response packet. + */ + TOX_NETPROF_PACKET_ID_ANNOUNCE_RESPONSE = 0x88, + + /** + * Onion receive packets. + */ + TOX_NETPROF_PACKET_ID_ONION_RECV_3 = 0x8c, + TOX_NETPROF_PACKET_ID_ONION_RECV_2 = 0x8d, + TOX_NETPROF_PACKET_ID_ONION_RECV_1 = 0x8e, + + TOX_NETPROF_PACKET_ID_FORWARD_REQUEST = 0x90, + TOX_NETPROF_PACKET_ID_FORWARDING = 0x91, + TOX_NETPROF_PACKET_ID_FORWARD_REPLY = 0x92, + + TOX_NETPROF_PACKET_ID_DATA_SEARCH_REQUEST = 0x93, + TOX_NETPROF_PACKET_ID_DATA_SEARCH_RESPONSE = 0x94, + TOX_NETPROF_PACKET_ID_DATA_RETRIEVE_REQUEST = 0x95, + TOX_NETPROF_PACKET_ID_DATA_RETRIEVE_RESPONSE = 0x96, + TOX_NETPROF_PACKET_ID_STORE_ANNOUNCE_REQUEST = 0x97, + TOX_NETPROF_PACKET_ID_STORE_ANNOUNCE_RESPONSE = 0x98, + + /** + * Bootstrap info packet. + */ + TOX_NETPROF_PACKET_ID_BOOTSTRAP_INFO = 0xf0, +} Tox_Netprof_Packet_Id; + +const char *tox_netprof_packet_id_to_string(Tox_Netprof_Packet_Id value); + +/** + * Specifies the packet type for a given query. + */ +typedef enum Tox_Netprof_Packet_Type { + /** + * TCP client packets. + */ + TOX_NETPROF_PACKET_TYPE_TCP_CLIENT, + + /** + * TCP server packets. + */ + TOX_NETPROF_PACKET_TYPE_TCP_SERVER, + + /** + * Combined TCP server and TCP client packets. + */ + TOX_NETPROF_PACKET_TYPE_TCP, + + /** + * UDP packets. + */ + TOX_NETPROF_PACKET_TYPE_UDP, +} Tox_Netprof_Packet_Type; + +const char *tox_netprof_packet_type_to_string(Tox_Netprof_Packet_Type value); + +/** + * Specifies the packet direction for a given query. + */ +typedef enum Tox_Netprof_Direction { + /** + * Outbound packets. + */ + TOX_NETPROF_DIRECTION_SENT, + + /** + * Inbound packets. + */ + TOX_NETPROF_DIRECTION_RECV, +} Tox_Netprof_Direction; + +const char *tox_netprof_direction_to_string(Tox_Netprof_Direction value); + +/** + * Return the number of packets sent or received for a specific packet ID. + * + * @param type The types of packets being queried. + * @param id The packet ID being queried. + * @param direction The packet direction. + */ +uint64_t tox_netprof_get_packet_id_count(const Tox *tox, Tox_Netprof_Packet_Type type, uint8_t id, + Tox_Netprof_Direction direction); + +/** + * Return the total number of packets sent or received. + * + * @param type The types of packets being queried. + * @param direction The packet direction. + */ +uint64_t tox_netprof_get_packet_total_count(const Tox *tox, Tox_Netprof_Packet_Type type, + Tox_Netprof_Direction direction); + +/** + * Return the number of bytes sent or received for a specific packet ID. + * + * @param type The types of packets being queried. + * @param id The packet ID being queried. + * @param direction The packet direction. + */ +uint64_t tox_netprof_get_packet_id_bytes(const Tox *tox, Tox_Netprof_Packet_Type type, uint8_t id, + Tox_Netprof_Direction direction); + +/** + * Return the total number of bytes sent or received. + * + * @param type The types of packets being queried. + * @param direction The packet direction. + */ +uint64_t tox_netprof_get_packet_total_bytes(const Tox *tox, Tox_Netprof_Packet_Type type, + Tox_Netprof_Direction direction); + + +/******************************************************************************* + * * :: DHT groupchat queries. * ******************************************************************************/ @@ -169,30 +446,32 @@ uint16_t tox_dht_get_num_closelist_announce_capable(const Tox *tox); uint32_t tox_group_peer_ip_string_max_length(void); /** - * Return the length of the peer's IP address in string form. If the group number or ID - * is invalid, the return value is unspecified. + * Return the length of the peer's IP address in string form. If the group + * number or ID is invalid, the return value is unspecified. * * @param group_number The group number of the group we wish to query. - * @param peer_id The ID of the peer whose IP address length we want to retrieve. + * @param peer_id The ID of the peer whose IP address length we want to + * retrieve. */ size_t tox_group_peer_get_ip_address_size(const Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Err_Group_Peer_Query *error); /** - * Write the IP address associated with the designated peer_id for the designated group number - * to ip_addr. + * Write the IP address associated with the designated peer_id for the + * designated group number to ip_addr. * - * If the peer is forcing TCP connections a placeholder value will be written instead, - * indicating that their real IP address is unknown to us. + * If the peer is forcing TCP connections a placeholder value will be written + * instead, indicating that their real IP address is unknown to us. * - * If `peer_id` designates ourself, it will write either our own IP address or a placeholder value, - * depending on whether or not we're forcing TCP connections. + * If `peer_id` designates ourself, it will write either our own IP address or a + * placeholder value, depending on whether or not we're forcing TCP connections. * - * Call tox_group_peer_get_ip_address_size to determine the allocation size for the `ip_addr` parameter. + * Call tox_group_peer_get_ip_address_size to determine the allocation size for + * the `ip_addr` parameter. * * @param group_number The group number of the group we wish to query. * @param peer_id The ID of the peer whose public key we wish to retrieve. - * @param ip_addr A valid memory region large enough to store the IP address string. - * If this parameter is NULL, this function call has no effect. + * @param ip_addr A valid memory region large enough to store the IP address + * string. If this parameter is NULL, this function call has no effect. * * @return true on success. */ diff --git a/protocols/Tox/libtox/src/toxcore/tox_struct.h b/protocols/Tox/libtox/src/toxcore/tox_struct.h index bd42fcce8d..9383c2a509 100644 --- a/protocols/Tox/libtox/src/toxcore/tox_struct.h +++ b/protocols/Tox/libtox/src/toxcore/tox_struct.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2022 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ @@ -8,10 +8,9 @@ #include <pthread.h> -#include "Messenger.h" -#include "mem.h" #include "mono_time.h" #include "tox.h" +#include "tox_options.h" // tox_log_cb #include "tox_private.h" #ifdef __cplusplus @@ -19,7 +18,7 @@ extern "C" { #endif struct Tox { - Messenger *m; + struct Messenger *m; Mono_Time *mono_time; Tox_System sys; pthread_mutex_t *mutex; @@ -44,7 +43,7 @@ struct Tox { tox_conference_title_cb *conference_title_callback; tox_conference_peer_name_cb *conference_peer_name_callback; tox_conference_peer_list_changed_cb *conference_peer_list_changed_callback; - tox_dht_get_nodes_response_cb *dht_get_nodes_response_callback; + tox_dht_nodes_response_cb *dht_nodes_response_callback; tox_friend_lossy_packet_cb *friend_lossy_packet_callback_per_pktid[UINT8_MAX + 1]; tox_friend_lossless_packet_cb *friend_lossless_packet_callback_per_pktid[UINT8_MAX + 1]; tox_group_peer_name_cb *group_peer_name_callback; diff --git a/protocols/Tox/libtox/src/toxcore/tox_unpack.c b/protocols/Tox/libtox/src/toxcore/tox_unpack.c index b5e05da872..6b31029624 100644 --- a/protocols/Tox/libtox/src/toxcore/tox_unpack.c +++ b/protocols/Tox/libtox/src/toxcore/tox_unpack.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2022 The TokTok team. + * Copyright © 2022-2025 The TokTok team. */ #include "tox_unpack.h" @@ -11,21 +11,21 @@ #include "tox.h" non_null() -static bool tox_conference_type_from_int(uint32_t value, Tox_Conference_Type *out) +static bool tox_conference_type_from_int(uint32_t value, Tox_Conference_Type *out_enum) { switch (value) { case TOX_CONFERENCE_TYPE_TEXT: { - *out = TOX_CONFERENCE_TYPE_TEXT; + *out_enum = TOX_CONFERENCE_TYPE_TEXT; return true; } case TOX_CONFERENCE_TYPE_AV: { - *out = TOX_CONFERENCE_TYPE_AV; + *out_enum = TOX_CONFERENCE_TYPE_AV; return true; } default: { - *out = TOX_CONFERENCE_TYPE_TEXT; + *out_enum = TOX_CONFERENCE_TYPE_TEXT; return false; } } @@ -38,26 +38,26 @@ bool tox_conference_type_unpack(Tox_Conference_Type *val, Bin_Unpack *bu) } non_null() -static bool tox_connection_from_int(uint32_t value, Tox_Connection *out) +static bool tox_connection_from_int(uint32_t value, Tox_Connection *out_enum) { switch (value) { case TOX_CONNECTION_NONE: { - *out = TOX_CONNECTION_NONE; + *out_enum = TOX_CONNECTION_NONE; return true; } case TOX_CONNECTION_TCP: { - *out = TOX_CONNECTION_TCP; + *out_enum = TOX_CONNECTION_TCP; return true; } case TOX_CONNECTION_UDP: { - *out = TOX_CONNECTION_UDP; + *out_enum = TOX_CONNECTION_UDP; return true; } default: { - *out = TOX_CONNECTION_NONE; + *out_enum = TOX_CONNECTION_NONE; return false; } } @@ -71,26 +71,26 @@ bool tox_connection_unpack(Tox_Connection *val, Bin_Unpack *bu) } non_null() -static bool tox_file_control_from_int(uint32_t value, Tox_File_Control *out) +static bool tox_file_control_from_int(uint32_t value, Tox_File_Control *out_enum) { switch (value) { case TOX_FILE_CONTROL_RESUME: { - *out = TOX_FILE_CONTROL_RESUME; + *out_enum = TOX_FILE_CONTROL_RESUME; return true; } case TOX_FILE_CONTROL_PAUSE: { - *out = TOX_FILE_CONTROL_PAUSE; + *out_enum = TOX_FILE_CONTROL_PAUSE; return true; } case TOX_FILE_CONTROL_CANCEL: { - *out = TOX_FILE_CONTROL_CANCEL; + *out_enum = TOX_FILE_CONTROL_CANCEL; return true; } default: { - *out = TOX_FILE_CONTROL_RESUME; + *out_enum = TOX_FILE_CONTROL_RESUME; return false; } } @@ -104,21 +104,21 @@ bool tox_file_control_unpack(Tox_File_Control *val, Bin_Unpack *bu) } non_null() -static bool tox_message_type_from_int(uint32_t value, Tox_Message_Type *out) +static bool tox_message_type_from_int(uint32_t value, Tox_Message_Type *out_enum) { switch (value) { case TOX_MESSAGE_TYPE_NORMAL: { - *out = TOX_MESSAGE_TYPE_NORMAL; + *out_enum = TOX_MESSAGE_TYPE_NORMAL; return true; } case TOX_MESSAGE_TYPE_ACTION: { - *out = TOX_MESSAGE_TYPE_ACTION; + *out_enum = TOX_MESSAGE_TYPE_ACTION; return true; } default: { - *out = TOX_MESSAGE_TYPE_NORMAL; + *out_enum = TOX_MESSAGE_TYPE_NORMAL; return false; } } @@ -132,26 +132,26 @@ bool tox_message_type_unpack(Tox_Message_Type *val, Bin_Unpack *bu) } non_null() -static bool tox_user_status_from_int(uint32_t value, Tox_User_Status *out) +static bool tox_user_status_from_int(uint32_t value, Tox_User_Status *out_enum) { switch (value) { case TOX_USER_STATUS_NONE: { - *out = TOX_USER_STATUS_NONE; + *out_enum = TOX_USER_STATUS_NONE; return true; } case TOX_USER_STATUS_AWAY: { - *out = TOX_USER_STATUS_AWAY; + *out_enum = TOX_USER_STATUS_AWAY; return true; } case TOX_USER_STATUS_BUSY: { - *out = TOX_USER_STATUS_BUSY; + *out_enum = TOX_USER_STATUS_BUSY; return true; } default: { - *out = TOX_USER_STATUS_NONE; + *out_enum = TOX_USER_STATUS_NONE; return false; } } @@ -165,19 +165,19 @@ bool tox_user_status_unpack(Tox_User_Status *val, Bin_Unpack *bu) } non_null() -static bool tox_group_privacy_state_from_int(uint32_t value, Tox_Group_Privacy_State *out) +static bool tox_group_privacy_state_from_int(uint32_t value, Tox_Group_Privacy_State *out_enum) { switch (value) { case TOX_GROUP_PRIVACY_STATE_PUBLIC: { - *out = TOX_GROUP_PRIVACY_STATE_PUBLIC; + *out_enum = TOX_GROUP_PRIVACY_STATE_PUBLIC; return true; } case TOX_GROUP_PRIVACY_STATE_PRIVATE: { - *out = TOX_GROUP_PRIVACY_STATE_PRIVATE; + *out_enum = TOX_GROUP_PRIVACY_STATE_PRIVATE; return true; } default: { - *out = TOX_GROUP_PRIVACY_STATE_PUBLIC; + *out_enum = TOX_GROUP_PRIVACY_STATE_PUBLIC; return false; } } @@ -189,23 +189,23 @@ bool tox_group_privacy_state_unpack(Tox_Group_Privacy_State *val, Bin_Unpack *bu && tox_group_privacy_state_from_int(u32, val); } non_null() -static bool tox_group_voice_state_from_int(uint32_t value, Tox_Group_Voice_State *out) +static bool tox_group_voice_state_from_int(uint32_t value, Tox_Group_Voice_State *out_enum) { switch (value) { case TOX_GROUP_VOICE_STATE_ALL: { - *out = TOX_GROUP_VOICE_STATE_ALL; + *out_enum = TOX_GROUP_VOICE_STATE_ALL; return true; } case TOX_GROUP_VOICE_STATE_MODERATOR: { - *out = TOX_GROUP_VOICE_STATE_MODERATOR; + *out_enum = TOX_GROUP_VOICE_STATE_MODERATOR; return true; } case TOX_GROUP_VOICE_STATE_FOUNDER: { - *out = TOX_GROUP_VOICE_STATE_FOUNDER; + *out_enum = TOX_GROUP_VOICE_STATE_FOUNDER; return true; } default: { - *out = TOX_GROUP_VOICE_STATE_ALL; + *out_enum = TOX_GROUP_VOICE_STATE_ALL; return false; } } @@ -218,19 +218,19 @@ bool tox_group_voice_state_unpack(Tox_Group_Voice_State *val, Bin_Unpack *bu) } non_null() -static bool tox_group_topic_lock_from_int(uint32_t value, Tox_Group_Topic_Lock *out) +static bool tox_group_topic_lock_from_int(uint32_t value, Tox_Group_Topic_Lock *out_enum) { switch (value) { case TOX_GROUP_TOPIC_LOCK_ENABLED: { - *out = TOX_GROUP_TOPIC_LOCK_ENABLED; + *out_enum = TOX_GROUP_TOPIC_LOCK_ENABLED; return true; } case TOX_GROUP_TOPIC_LOCK_DISABLED: { - *out = TOX_GROUP_TOPIC_LOCK_DISABLED; + *out_enum = TOX_GROUP_TOPIC_LOCK_DISABLED; return true; } default: { - *out = TOX_GROUP_TOPIC_LOCK_ENABLED; + *out_enum = TOX_GROUP_TOPIC_LOCK_ENABLED; return false; } } @@ -243,23 +243,23 @@ bool tox_group_topic_lock_unpack(Tox_Group_Topic_Lock *val, Bin_Unpack *bu) } non_null() -static bool tox_group_join_fail_from_int(uint32_t value, Tox_Group_Join_Fail *out) +static bool tox_group_join_fail_from_int(uint32_t value, Tox_Group_Join_Fail *out_enum) { switch (value) { case TOX_GROUP_JOIN_FAIL_PEER_LIMIT: { - *out = TOX_GROUP_JOIN_FAIL_PEER_LIMIT; + *out_enum = TOX_GROUP_JOIN_FAIL_PEER_LIMIT; return true; } case TOX_GROUP_JOIN_FAIL_INVALID_PASSWORD: { - *out = TOX_GROUP_JOIN_FAIL_INVALID_PASSWORD; + *out_enum = TOX_GROUP_JOIN_FAIL_INVALID_PASSWORD; return true; } case TOX_GROUP_JOIN_FAIL_UNKNOWN: { - *out = TOX_GROUP_JOIN_FAIL_UNKNOWN; + *out_enum = TOX_GROUP_JOIN_FAIL_UNKNOWN; return true; } default: { - *out = TOX_GROUP_JOIN_FAIL_PEER_LIMIT; + *out_enum = TOX_GROUP_JOIN_FAIL_PEER_LIMIT; return false; } } @@ -272,27 +272,27 @@ bool tox_group_join_fail_unpack(Tox_Group_Join_Fail *val, Bin_Unpack *bu) } non_null() -static bool tox_group_mod_event_from_int(uint32_t value, Tox_Group_Mod_Event *out) +static bool tox_group_mod_event_from_int(uint32_t value, Tox_Group_Mod_Event *out_enum) { switch (value) { case TOX_GROUP_MOD_EVENT_KICK: { - *out = TOX_GROUP_MOD_EVENT_KICK; + *out_enum = TOX_GROUP_MOD_EVENT_KICK; return true; } case TOX_GROUP_MOD_EVENT_OBSERVER: { - *out = TOX_GROUP_MOD_EVENT_OBSERVER; + *out_enum = TOX_GROUP_MOD_EVENT_OBSERVER; return true; } case TOX_GROUP_MOD_EVENT_USER: { - *out = TOX_GROUP_MOD_EVENT_USER; + *out_enum = TOX_GROUP_MOD_EVENT_USER; return true; } case TOX_GROUP_MOD_EVENT_MODERATOR: { - *out = TOX_GROUP_MOD_EVENT_MODERATOR; + *out_enum = TOX_GROUP_MOD_EVENT_MODERATOR; return true; } default: { - *out = TOX_GROUP_MOD_EVENT_KICK; + *out_enum = TOX_GROUP_MOD_EVENT_KICK; return false; } } @@ -305,35 +305,35 @@ bool tox_group_mod_event_unpack(Tox_Group_Mod_Event *val, Bin_Unpack *bu) } non_null() -static bool tox_group_exit_type_from_int(uint32_t value, Tox_Group_Exit_Type *out) +static bool tox_group_exit_type_from_int(uint32_t value, Tox_Group_Exit_Type *out_enum) { switch (value) { case TOX_GROUP_EXIT_TYPE_QUIT: { - *out = TOX_GROUP_EXIT_TYPE_QUIT; + *out_enum = TOX_GROUP_EXIT_TYPE_QUIT; return true; } case TOX_GROUP_EXIT_TYPE_TIMEOUT: { - *out = TOX_GROUP_EXIT_TYPE_TIMEOUT; + *out_enum = TOX_GROUP_EXIT_TYPE_TIMEOUT; return true; } case TOX_GROUP_EXIT_TYPE_DISCONNECTED: { - *out = TOX_GROUP_EXIT_TYPE_DISCONNECTED; + *out_enum = TOX_GROUP_EXIT_TYPE_DISCONNECTED; return true; } case TOX_GROUP_EXIT_TYPE_SELF_DISCONNECTED: { - *out = TOX_GROUP_EXIT_TYPE_SELF_DISCONNECTED; + *out_enum = TOX_GROUP_EXIT_TYPE_SELF_DISCONNECTED; return true; } case TOX_GROUP_EXIT_TYPE_KICK: { - *out = TOX_GROUP_EXIT_TYPE_KICK; + *out_enum = TOX_GROUP_EXIT_TYPE_KICK; return true; } case TOX_GROUP_EXIT_TYPE_SYNC_ERROR: { - *out = TOX_GROUP_EXIT_TYPE_SYNC_ERROR; + *out_enum = TOX_GROUP_EXIT_TYPE_SYNC_ERROR; return true; } default: { - *out = TOX_GROUP_EXIT_TYPE_QUIT; + *out_enum = TOX_GROUP_EXIT_TYPE_QUIT; return false; } } diff --git a/protocols/Tox/libtox/src/toxcore/tox_unpack.h b/protocols/Tox/libtox/src/toxcore/tox_unpack.h index 828d2947a6..09092379da 100644 --- a/protocols/Tox/libtox/src/toxcore/tox_unpack.h +++ b/protocols/Tox/libtox/src/toxcore/tox_unpack.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2022 The TokTok team. + * Copyright © 2022-2025 The TokTok team. */ #ifndef C_TOXCORE_TOXCORE_TOX_UNPACK_H diff --git a/protocols/Tox/libtox/src/toxcore/util.c b/protocols/Tox/libtox/src/toxcore/util.c index 1851e58a08..455e513cef 100644 --- a/protocols/Tox/libtox/src/toxcore/util.c +++ b/protocols/Tox/libtox/src/toxcore/util.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. * Copyright © 2013 plutooo */ @@ -13,7 +13,6 @@ #include "util.h" -#include <stdlib.h> #include <string.h> #include "ccompat.h" @@ -81,13 +80,13 @@ bool memeq(const uint8_t *a, size_t a_size, const uint8_t *b, size_t b_size) return a_size == b_size && memcmp(a, b, a_size) == 0; } -uint8_t *memdup(const uint8_t *data, size_t data_size) +uint8_t *memdup(const Memory *mem, const uint8_t *data, size_t data_size) { if (data == nullptr || data_size == 0) { return nullptr; } - uint8_t *copy = (uint8_t *)malloc(data_size); + uint8_t *copy = (uint8_t *)mem_balloc(mem, data_size); if (copy != nullptr) { memcpy(copy, data, data_size); diff --git a/protocols/Tox/libtox/src/toxcore/util.h b/protocols/Tox/libtox/src/toxcore/util.h index 5be74a8d86..9be721318b 100644 --- a/protocols/Tox/libtox/src/toxcore/util.h +++ b/protocols/Tox/libtox/src/toxcore/util.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. * Copyright © 2013 plutooo */ @@ -46,7 +46,7 @@ non_null() bool memeq(const uint8_t *a, size_t a_size, const uint8_t *b, size_t * * @return nullptr on allocation failure or if the input data was nullptr or data_size was 0. */ -nullable(1) uint8_t *memdup(const uint8_t *data, size_t data_size); +non_null(1) nullable(2) uint8_t *memdup(const Memory *mem, const uint8_t *data, size_t data_size); /** * @brief Set all bytes in `data` to 0. @@ -79,7 +79,12 @@ uint16_t min_u16(uint16_t a, uint16_t b); uint32_t min_u32(uint32_t a, uint32_t b); uint64_t min_u64(uint64_t a, uint64_t b); -// Comparison function: return -1 if a<b, 0 if a==b, 1 if a>b. +/** + * Comparison function: + * @retval -1 if `a < b` + * @retval 0 if `a == b` + * @retval 1 if `a > b` + */ int cmp_uint(uint64_t a, uint64_t b); /** @brief Returns a 32-bit hash of key of size len */ diff --git a/protocols/Tox/libtox/src/toxencryptsave/defines.h b/protocols/Tox/libtox/src/toxencryptsave/defines.h index ac80cc7893..ca66f4d38d 100644 --- a/protocols/Tox/libtox/src/toxencryptsave/defines.h +++ b/protocols/Tox/libtox/src/toxencryptsave/defines.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2021 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ diff --git a/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.c b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.c index c43e357528..63bda86058 100644 --- a/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.c +++ b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013 Tox project. */ @@ -67,7 +67,8 @@ void tox_pass_key_free(Tox_Pass_Key *key) * produce the same key as was previously used. Any data encrypted with this * module can be used as input. * - * The cipher text must be at least TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes in length. + * The cipher text must be at least TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes in + * length. * The salt must be TOX_PASS_SALT_LENGTH bytes in length. * If the passed byte arrays are smaller than required, the behaviour is * undefined. @@ -182,10 +183,11 @@ Tox_Pass_Key *tox_pass_key_derive_with_salt( } /** - * Encrypt a plain text with a key produced by tox_pass_key_derive or tox_pass_key_derive_with_salt. + * Encrypt a plain text with a key produced by tox_pass_key_derive or + * tox_pass_key_derive_with_salt. * - * The output array must be at least `plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH` - * bytes long. + * The output array must be at least + * `plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH` bytes long. * * @param plaintext A byte array of length `plaintext_len`. * @param plaintext_len The length of the plain text array. Bigger than 0. @@ -229,8 +231,8 @@ bool tox_pass_key_encrypt(const Tox_Pass_Key *key, const uint8_t plaintext[], si ciphertext += crypto_box_NONCEBYTES; /* now encrypt */ - if (encrypt_data_symmetric(key->key, nonce, plaintext, plaintext_len, ciphertext) - != plaintext_len + crypto_box_MACBYTES) { + const int32_t encrypted_len = encrypt_data_symmetric(os_memory(), key->key, nonce, plaintext, plaintext_len, ciphertext); + if (encrypted_len < 0 || (size_t)encrypted_len != plaintext_len + crypto_box_MACBYTES) { SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_FAILED); return false; } @@ -242,9 +244,9 @@ bool tox_pass_key_encrypt(const Tox_Pass_Key *key, const uint8_t plaintext[], si /** * Encrypts the given data with the given passphrase. * - * The output array must be at least `plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH` - * bytes long. This delegates to tox_pass_key_derive and - * tox_pass_key_encrypt. + * The output array must be at least + * `plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH` bytes long. This delegates + * to tox_pass_key_derive and tox_pass_key_encrypt. * * @param plaintext A byte array of length `plaintext_len`. * @param plaintext_len The length of the plain text array. Bigger than 0. @@ -280,7 +282,8 @@ bool tox_pass_encrypt(const uint8_t plaintext[], size_t plaintext_len, const uin * tox_pass_key_derive or tox_pass_key_derive_with_salt. * * @param ciphertext A byte array of length `ciphertext_len`. - * @param ciphertext_len The length of the cipher text array. At least TOX_PASS_ENCRYPTION_EXTRA_LENGTH. + * @param ciphertext_len The length of the cipher text array. At least + * TOX_PASS_ENCRYPTION_EXTRA_LENGTH. * @param plaintext The plain text array to write the decrypted data to. * * @return true on success. @@ -313,8 +316,8 @@ bool tox_pass_key_decrypt(const Tox_Pass_Key *key, const uint8_t ciphertext[], s ciphertext += crypto_box_NONCEBYTES; /* decrypt the ciphertext */ - if (decrypt_data_symmetric(key->key, nonce, ciphertext, decrypt_length + crypto_box_MACBYTES, plaintext) - != decrypt_length) { + const int32_t decrypted_len = decrypt_data_symmetric(os_memory(), key->key, nonce, ciphertext, decrypt_length + crypto_box_MACBYTES, plaintext); + if (decrypted_len < 0 || (size_t)decrypted_len != decrypt_length) { SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_FAILED); return false; } @@ -326,11 +329,13 @@ bool tox_pass_key_decrypt(const Tox_Pass_Key *key, const uint8_t ciphertext[], s /** * Decrypts the given data with the given passphrase. * - * The output array must be at least `ciphertext_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH` - * bytes long. This delegates to tox_pass_key_decrypt. + * The output array must be at least + * `ciphertext_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH` bytes long. This + * delegates to tox_pass_key_decrypt. * * @param ciphertext A byte array of length `ciphertext_len`. - * @param ciphertext_len The length of the cipher text array. At least TOX_PASS_ENCRYPTION_EXTRA_LENGTH. + * @param ciphertext_len The length of the cipher text array. At least + * TOX_PASS_ENCRYPTION_EXTRA_LENGTH. * @param passphrase The user-provided password. Can be empty. * @param passphrase_len The length of the password. * @param plaintext The plain text array to write the decrypted data to. @@ -390,3 +395,63 @@ bool tox_is_data_encrypted(const uint8_t data[TOX_PASS_ENCRYPTION_EXTRA_LENGTH]) { return memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0; } + +const char *tox_err_key_derivation_to_string(Tox_Err_Key_Derivation error) +{ + switch (error) { + case TOX_ERR_KEY_DERIVATION_OK: + return "TOX_ERR_KEY_DERIVATION_OK"; + case TOX_ERR_KEY_DERIVATION_NULL: + return "TOX_ERR_KEY_DERIVATION_NULL"; + case TOX_ERR_KEY_DERIVATION_FAILED: + return "TOX_ERR_KEY_DERIVATION_FAILED"; + } + return "<invalid Tox_Err_Key_Derivation>"; +} + +const char *tox_err_encryption_to_string(Tox_Err_Encryption error) +{ + switch (error) { + case TOX_ERR_ENCRYPTION_OK: + return "TOX_ERR_ENCRYPTION_OK"; + case TOX_ERR_ENCRYPTION_NULL: + return "TOX_ERR_ENCRYPTION_NULL"; + case TOX_ERR_ENCRYPTION_KEY_DERIVATION_FAILED: + return "TOX_ERR_ENCRYPTION_KEY_DERIVATION_FAILED"; + case TOX_ERR_ENCRYPTION_FAILED: + return "TOX_ERR_ENCRYPTION_FAILED"; + } + return "<invalid Tox_Err_Encryption>"; +} + +const char *tox_err_decryption_to_string(Tox_Err_Decryption error) +{ + switch (error) { + case TOX_ERR_DECRYPTION_OK: + return "TOX_ERR_DECRYPTION_OK"; + case TOX_ERR_DECRYPTION_NULL: + return "TOX_ERR_DECRYPTION_NULL"; + case TOX_ERR_DECRYPTION_INVALID_LENGTH: + return "TOX_ERR_DECRYPTION_INVALID_LENGTH"; + case TOX_ERR_DECRYPTION_BAD_FORMAT: + return "TOX_ERR_DECRYPTION_BAD_FORMAT"; + case TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED: + return "TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED"; + case TOX_ERR_DECRYPTION_FAILED: + return "TOX_ERR_DECRYPTION_FAILED"; + } + return "<invalid Tox_Err_Decryption>"; +} + +const char *tox_err_get_salt_to_string(Tox_Err_Get_Salt error) +{ + switch (error) { + case TOX_ERR_GET_SALT_OK: + return "TOX_ERR_GET_SALT_OK"; + case TOX_ERR_GET_SALT_NULL: + return "TOX_ERR_GET_SALT_NULL"; + case TOX_ERR_GET_SALT_BAD_FORMAT: + return "TOX_ERR_GET_SALT_BAD_FORMAT"; + } + return "<invalid Tox_Err_Get_Salt>"; +} diff --git a/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.h b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.h index b9691551c7..f70ff8b4d1 100644 --- a/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.h +++ b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2025 The TokTok team. * Copyright © 2013-2016 Tox Developers. */ @@ -88,6 +88,8 @@ typedef enum Tox_Err_Key_Derivation { } Tox_Err_Key_Derivation; +const char *tox_err_key_derivation_to_string(Tox_Err_Key_Derivation error); + typedef enum Tox_Err_Encryption { /** @@ -114,6 +116,8 @@ typedef enum Tox_Err_Encryption { } Tox_Err_Encryption; +const char *tox_err_encryption_to_string(Tox_Err_Encryption error); + typedef enum Tox_Err_Decryption { /** @@ -152,6 +156,8 @@ typedef enum Tox_Err_Decryption { } Tox_Err_Decryption; +const char *tox_err_decryption_to_string(Tox_Err_Decryption error); + /******************************************************************************* * * BEGIN PART 1 @@ -165,9 +171,9 @@ typedef enum Tox_Err_Decryption { /** * Encrypts the given data with the given passphrase. * - * The output array must be at least `plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH` - * bytes long. This delegates to tox_pass_key_derive and - * tox_pass_key_encrypt. + * The output array must be at least + * `plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH` bytes long. This delegates + * to tox_pass_key_derive and tox_pass_key_encrypt. * * @param plaintext A byte array of length `plaintext_len`. * @param plaintext_len The length of the plain text array. Bigger than 0. @@ -183,11 +189,13 @@ bool tox_pass_encrypt(const uint8_t plaintext[], size_t plaintext_len, const uin /** * Decrypts the given data with the given passphrase. * - * The output array must be at least `ciphertext_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH` - * bytes long. This delegates to tox_pass_key_decrypt. + * The output array must be at least + * `ciphertext_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH` bytes long. This + * delegates to tox_pass_key_decrypt. * * @param ciphertext A byte array of length `ciphertext_len`. - * @param ciphertext_len The length of the cipher text array. At least TOX_PASS_ENCRYPTION_EXTRA_LENGTH. + * @param ciphertext_len The length of the cipher text array. At least + * TOX_PASS_ENCRYPTION_EXTRA_LENGTH. * @param passphrase The user-provided password. Can be empty. * @param passphrase_len The length of the password. * @param plaintext The plain text array to write the decrypted data to. @@ -215,7 +223,8 @@ bool tox_pass_decrypt(const uint8_t ciphertext[], size_t ciphertext_len, const u * user-provided password. * * The Tox_Pass_Key structure is hidden in the implementation. It can be created - * using tox_pass_key_derive or tox_pass_key_derive_with_salt and must be deallocated using tox_pass_key_free. + * using tox_pass_key_derive or tox_pass_key_derive_with_salt and must be + * deallocated using tox_pass_key_free. */ #ifndef TOX_PASS_KEY_DEFINED #define TOX_PASS_KEY_DEFINED @@ -261,10 +270,11 @@ Tox_Pass_Key *tox_pass_key_derive_with_salt( const uint8_t salt[TOX_PASS_SALT_LENGTH], Tox_Err_Key_Derivation *error); /** - * Encrypt a plain text with a key produced by tox_pass_key_derive or tox_pass_key_derive_with_salt. + * Encrypt a plain text with a key produced by tox_pass_key_derive or + * tox_pass_key_derive_with_salt. * - * The output array must be at least `plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH` - * bytes long. + * The output array must be at least + * `plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH` bytes long. * * @param plaintext A byte array of length `plaintext_len`. * @param plaintext_len The length of the plain text array. Bigger than 0. @@ -280,7 +290,8 @@ bool tox_pass_key_encrypt(const Tox_Pass_Key *key, const uint8_t plaintext[], si * tox_pass_key_derive or tox_pass_key_derive_with_salt. * * @param ciphertext A byte array of length `ciphertext_len`. - * @param ciphertext_len The length of the cipher text array. At least TOX_PASS_ENCRYPTION_EXTRA_LENGTH. + * @param ciphertext_len The length of the cipher text array. At least + * TOX_PASS_ENCRYPTION_EXTRA_LENGTH. * @param plaintext The plain text array to write the decrypted data to. * * @return true on success. @@ -308,6 +319,8 @@ typedef enum Tox_Err_Get_Salt { } Tox_Err_Get_Salt; +const char *tox_err_get_salt_to_string(Tox_Err_Get_Salt error); + /** * Retrieves the salt used to encrypt the given data. * @@ -315,7 +328,8 @@ typedef enum Tox_Err_Get_Salt { * produce the same key as was previously used. Any data encrypted with this * module can be used as input. * - * The cipher text must be at least TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes in length. + * The cipher text must be at least TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes in + * length. * The salt must be TOX_PASS_SALT_LENGTH bytes in length. * If the passed byte arrays are smaller than required, the behaviour is * undefined. |