summaryrefslogtreecommitdiff
path: root/protocols/Tox/libtox/src
diff options
context:
space:
mode:
authorGeorge Hazan <george.hazan@gmail.com>2025-05-25 19:12:13 +0300
committerGeorge Hazan <george.hazan@gmail.com>2025-05-25 19:12:13 +0300
commita15f120c4ff2824b71301d5c270288b74bb2aa37 (patch)
treefd3ea82de8d92d7cd2795e931b584d9c4857cb89 /protocols/Tox/libtox/src
parent5e0856749a27b186dd23273b238dd176922f6f1a (diff)
libtox: update to 2.2.1
Diffstat (limited to 'protocols/Tox/libtox/src')
-rw-r--r--protocols/Tox/libtox/src/toxcore/DHT.c284
-rw-r--r--protocols/Tox/libtox/src/toxcore/DHT.h25
-rw-r--r--protocols/Tox/libtox/src/toxcore/LAN_discovery.c86
-rw-r--r--protocols/Tox/libtox/src/toxcore/LAN_discovery.h5
-rw-r--r--protocols/Tox/libtox/src/toxcore/Makefile.inc169
-rw-r--r--protocols/Tox/libtox/src/toxcore/Messenger.c41
-rw-r--r--protocols/Tox/libtox/src/toxcore/Messenger.h6
-rw-r--r--protocols/Tox/libtox/src/toxcore/TCP_client.c46
-rw-r--r--protocols/Tox/libtox/src/toxcore/TCP_client.h7
-rw-r--r--protocols/Tox/libtox/src/toxcore/TCP_common.c20
-rw-r--r--protocols/Tox/libtox/src/toxcore/TCP_common.h7
-rw-r--r--protocols/Tox/libtox/src/toxcore/TCP_connection.c17
-rw-r--r--protocols/Tox/libtox/src/toxcore/TCP_connection.h5
-rw-r--r--protocols/Tox/libtox/src/toxcore/TCP_server.c46
-rw-r--r--protocols/Tox/libtox/src/toxcore/TCP_server.h10
-rw-r--r--protocols/Tox/libtox/src/toxcore/announce.c19
-rw-r--r--protocols/Tox/libtox/src/toxcore/announce.h2
-rw-r--r--protocols/Tox/libtox/src/toxcore/attributes.h2
-rw-r--r--protocols/Tox/libtox/src/toxcore/bin_pack.c2
-rw-r--r--protocols/Tox/libtox/src/toxcore/bin_pack.h2
-rw-r--r--protocols/Tox/libtox/src/toxcore/bin_unpack.c21
-rw-r--r--protocols/Tox/libtox/src/toxcore/bin_unpack.h5
-rw-r--r--protocols/Tox/libtox/src/toxcore/ccompat.c2
-rw-r--r--protocols/Tox/libtox/src/toxcore/ccompat.h2
-rw-r--r--protocols/Tox/libtox/src/toxcore/crypto_core.c63
-rw-r--r--protocols/Tox/libtox/src/toxcore/crypto_core.h15
-rw-r--r--protocols/Tox/libtox/src/toxcore/crypto_core_pack.c2
-rw-r--r--protocols/Tox/libtox/src/toxcore/crypto_core_pack.h2
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/conference_connected.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/conference_invite.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/conference_message.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/conference_peer_list_changed.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/conference_peer_name.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/conference_title.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/dht_get_nodes_response.c226
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/dht_nodes_response.c222
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/events_alloc.c2
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/events_alloc.h7
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/file_chunk_request.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/file_recv.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/file_recv_chunk.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/file_recv_control.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_connection_status.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_lossless_packet.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_lossy_packet.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_message.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_name.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_read_receipt.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_request.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_status.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_status_message.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_typing.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_custom_packet.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_custom_private_packet.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_invite.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_join_fail.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_message.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_moderation.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_password.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_peer_exit.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_peer_join.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_peer_limit.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_peer_name.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_peer_status.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_privacy_state.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_private_message.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_self_join.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_topic.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_topic_lock.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_voice_state.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/self_connection_status.c3
-rw-r--r--protocols/Tox/libtox/src/toxcore/forwarding.c12
-rw-r--r--protocols/Tox/libtox/src/toxcore/forwarding.h5
-rw-r--r--protocols/Tox/libtox/src/toxcore/friend_connection.c24
-rw-r--r--protocols/Tox/libtox/src/toxcore/friend_connection.h6
-rw-r--r--protocols/Tox/libtox/src/toxcore/friend_requests.c28
-rw-r--r--protocols/Tox/libtox/src/toxcore/friend_requests.h9
-rw-r--r--protocols/Tox/libtox/src/toxcore/group.c120
-rw-r--r--protocols/Tox/libtox/src/toxcore/group.h5
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_announce.c27
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_announce.h8
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_chats.c443
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_chats.h11
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_common.h7
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_connection.c118
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_connection.h17
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_moderation.c52
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_onion_announce.c13
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_onion_announce.h9
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_pack.c29
-rw-r--r--protocols/Tox/libtox/src/toxcore/list.c16
-rw-r--r--protocols/Tox/libtox/src/toxcore/list.h7
-rw-r--r--protocols/Tox/libtox/src/toxcore/logger.c72
-rw-r--r--protocols/Tox/libtox/src/toxcore/logger.h10
-rw-r--r--protocols/Tox/libtox/src/toxcore/mem.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/mem.h10
-rw-r--r--protocols/Tox/libtox/src/toxcore/mono_time.c4
-rw-r--r--protocols/Tox/libtox/src/toxcore/mono_time.h2
-rw-r--r--protocols/Tox/libtox/src/toxcore/net_crypto.c76
-rw-r--r--protocols/Tox/libtox/src/toxcore/net_crypto.h22
-rw-r--r--protocols/Tox/libtox/src/toxcore/net_profile.c157
-rw-r--r--protocols/Tox/libtox/src/toxcore/net_profile.h81
-rw-r--r--protocols/Tox/libtox/src/toxcore/network.c383
-rw-r--r--protocols/Tox/libtox/src/toxcore/network.h116
-rw-r--r--protocols/Tox/libtox/src/toxcore/onion.c34
-rw-r--r--protocols/Tox/libtox/src/toxcore/onion.h6
-rw-r--r--protocols/Tox/libtox/src/toxcore/onion_announce.c154
-rw-r--r--protocols/Tox/libtox/src/toxcore/onion_announce.h12
-rw-r--r--protocols/Tox/libtox/src/toxcore/onion_client.c164
-rw-r--r--protocols/Tox/libtox/src/toxcore/onion_client.h4
-rw-r--r--protocols/Tox/libtox/src/toxcore/ping.c12
-rw-r--r--protocols/Tox/libtox/src/toxcore/ping.h2
-rw-r--r--protocols/Tox/libtox/src/toxcore/ping_array.c2
-rw-r--r--protocols/Tox/libtox/src/toxcore/ping_array.h2
-rw-r--r--protocols/Tox/libtox/src/toxcore/shared_key_cache.c2
-rw-r--r--protocols/Tox/libtox/src/toxcore/shared_key_cache.h2
-rw-r--r--protocols/Tox/libtox/src/toxcore/sort.c182
-rw-r--r--protocols/Tox/libtox/src/toxcore/sort.h116
-rw-r--r--protocols/Tox/libtox/src/toxcore/timed_auth.c2
-rw-r--r--protocols/Tox/libtox/src/toxcore/timed_auth.h2
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox.c33
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox.h449
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_api.c338
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_dispatch.c18
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_dispatch.h10
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_event.c26
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_event.h12
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_events.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_events.h24
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_log_level.c27
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_log_level.h58
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_options.c285
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_options.h455
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_pack.c2
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_pack.h2
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_private.c229
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_private.h299
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_struct.h9
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_unpack.c2
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_unpack.h2
-rw-r--r--protocols/Tox/libtox/src/toxcore/util.c7
-rw-r--r--protocols/Tox/libtox/src/toxcore/util.h11
-rw-r--r--protocols/Tox/libtox/src/toxencryptsave/defines.h2
-rw-r--r--protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.c66
-rw-r--r--protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.h10
145 files changed, 4284 insertions, 2192 deletions
diff --git a/protocols/Tox/libtox/src/toxcore/DHT.c b/protocols/Tox/libtox/src/toxcore/DHT.c
index 89c85c3463..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,7 +379,7 @@ 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 < 0) {
mem_delete(mem, encrypted);
@@ -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)) {
@@ -1352,7 +1400,7 @@ static int sendnodes_ipv6(const DHT *dht, const IP_Port *ip_port, const uint8_t
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 < 0 || (uint32_t)len != data_size) {
@@ -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
index db3e193243..de9227b6d0 100644
--- a/protocols/Tox/libtox/src/toxcore/Makefile.inc
+++ b/protocols/Tox/libtox/src/toxcore/Makefile.inc
@@ -1,26 +1,20 @@
lib_LTLIBRARIES += libtoxcore.la
libtoxcore_la_include_HEADERS = \
- ../toxcore/tox.h
+ ../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/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/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_get_nodes_response.c \
+ ../toxcore/events/dht_nodes_response.c \
../toxcore/events/events_alloc.c \
../toxcore/events/events_alloc.h \
../toxcore/events/file_chunk_request.c \
@@ -56,93 +50,108 @@ libtoxcore_la_SOURCES = ../third_party/cmp/cmp.c \
../toxcore/events/group_topic.c \
../toxcore/events/group_topic_lock.c \
../toxcore/events/group_voice_state.c \
- ../toxcore/DHT.h \
+ ../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/mem.h \
+ ../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/mono_time.h \
+ ../toxcore/mem.h \
+ ../toxcore/Messenger.c \
+ ../toxcore/Messenger.h \
../toxcore/mono_time.c \
- ../toxcore/network.h \
+ ../toxcore/mono_time.h \
+ ../toxcore/net_crypto.c \
+ ../toxcore/net_crypto.h \
+ ../toxcore/net_profile.c \
+ ../toxcore/net_profile.h \
../toxcore/network.c \
- ../toxcore/crypto_core.h \
- ../toxcore/crypto_core.c \
- ../toxcore/crypto_core_pack.h \
- ../toxcore/crypto_core_pack.c \
- ../toxcore/timed_auth.h \
- ../toxcore/timed_auth.c \
- ../toxcore/ping_array.h \
+ ../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/net_crypto.h \
- ../toxcore/net_crypto.c \
- ../toxcore/friend_requests.h \
- ../toxcore/friend_requests.c \
- ../toxcore/LAN_discovery.h \
- ../toxcore/LAN_discovery.c \
- ../toxcore/friend_connection.h \
- ../toxcore/friend_connection.c \
- ../toxcore/Messenger.h \
- ../toxcore/Messenger.c \
- ../toxcore/ping.h \
+ ../toxcore/ping_array.h \
../toxcore/ping.c \
- ../toxcore/shared_key_cache.h \
+ ../toxcore/ping.h \
../toxcore/shared_key_cache.c \
- ../toxcore/state.h \
+ ../toxcore/shared_key_cache.h \
+ ../toxcore/sort.c \
+ ../toxcore/sort.h \
../toxcore/state.c \
- ../toxcore/tox.h \
- ../toxcore/tox.c \
- ../toxcore/tox_dispatch.h \
+ ../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_event.h \
+ ../toxcore/tox_dispatch.h \
../toxcore/tox_event.c \
- ../toxcore/tox_events.h \
+ ../toxcore/tox_event.h \
../toxcore/tox_events.c \
- ../toxcore/tox_pack.h \
+ ../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_unpack.h \
- ../toxcore/tox_unpack.c \
+ ../toxcore/tox_pack.h \
../toxcore/tox_private.c \
../toxcore/tox_private.h \
../toxcore/tox_struct.h \
- ../toxcore/tox_api.c \
- ../toxcore/util.h \
+ ../toxcore/tox_unpack.c \
+ ../toxcore/tox_unpack.h \
+ ../toxcore/tox.c \
+ ../toxcore/tox.h \
../toxcore/util.c \
- ../toxcore/group.h \
- ../toxcore/group.c \
- ../toxcore/group_announce.h \
- ../toxcore/group_announce.c \
- ../toxcore/group_onion_announce.c \
- ../toxcore/group_onion_announce.h \
- ../toxcore/group_chats.h \
- ../toxcore/group_chats.c \
- ../toxcore/group_common.h \
- ../toxcore/group_connection.c \
- ../toxcore/group_connection.h \
- ../toxcore/group_pack.c \
- ../toxcore/group_pack.h \
- ../toxcore/group_moderation.c \
- ../toxcore/group_moderation.h \
- ../toxcore/onion.h \
- ../toxcore/onion.c \
- ../toxcore/logger.h \
- ../toxcore/logger.c \
- ../toxcore/onion_announce.h \
- ../toxcore/onion_announce.c \
- ../toxcore/onion_client.h \
- ../toxcore/onion_client.c \
- ../toxcore/announce.h \
- ../toxcore/announce.c \
- ../toxcore/forwarding.h \
- ../toxcore/forwarding.c \
- ../toxcore/TCP_client.h \
- ../toxcore/TCP_client.c \
- ../toxcore/TCP_common.h \
- ../toxcore/TCP_common.c \
- ../toxcore/TCP_server.h \
- ../toxcore/TCP_server.c \
- ../toxcore/TCP_connection.h \
- ../toxcore/TCP_connection.c \
- ../toxcore/list.c \
- ../toxcore/list.h
+ ../toxcore/util.h
libtoxcore_la_CFLAGS = -I$(top_srcdir) \
-I$(top_srcdir)/toxcore \
diff --git a/protocols/Tox/libtox/src/toxcore/Messenger.c b/protocols/Tox/libtox/src/toxcore/Messenger.c
index 7c9730bb63..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,
@@ -2515,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;
}
@@ -3171,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;
}
@@ -3475,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);
@@ -3531,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);
@@ -3544,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);
@@ -3559,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 {
@@ -3574,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)) ||
@@ -3589,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);
@@ -3612,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);
@@ -3637,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);
@@ -3692,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 998a009f15..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 {
@@ -246,6 +249,7 @@ struct Messenger {
Networking_Core *net;
Net_Crypto *net_crypto;
+ Net_Profile *tcp_np;
DHT *dht;
Forwarding *forwarding;
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 7bda993232..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,
@@ -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 8aeb17204b..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"
/*****************************************************
diff --git a/protocols/Tox/libtox/src/toxcore/events/conference_invite.c b/protocols/Tox/libtox/src/toxcore/events/conference_invite.c
index c9b8d14bc1..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"
diff --git a/protocols/Tox/libtox/src/toxcore/events/conference_message.c b/protocols/Tox/libtox/src/toxcore/events/conference_message.c
index e509827e45..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"
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 f7efd3f806..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"
/*****************************************************
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 930065631f..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"
/*****************************************************
diff --git a/protocols/Tox/libtox/src/toxcore/events/conference_title.c b/protocols/Tox/libtox/src/toxcore/events/conference_title.c
index d8e269032e..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"
/*****************************************************
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 f637b9c93a..0000000000
--- a/protocols/Tox/libtox/src/toxcore/events/dht_get_nodes_response.c
+++ /dev/null
@@ -1,226 +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;
-
- if (!tox_events_add(events, &event)) {
- tox_event_dht_get_nodes_response_free(dht_get_nodes_response, mem);
- return nullptr;
- }
- 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 23e5f5bf18..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"
/*****************************************************
diff --git a/protocols/Tox/libtox/src/toxcore/events/file_recv.c b/protocols/Tox/libtox/src/toxcore/events/file_recv.c
index 389ce59830..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"
/*****************************************************
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 619011a4af..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"
/*****************************************************
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 3c575c09a6..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"
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 68c48695ad..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"
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 b783e332f0..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"
/*****************************************************
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 e3a6ad5f59..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"
/*****************************************************
diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_message.c b/protocols/Tox/libtox/src/toxcore/events/friend_message.c
index dfd1daea39..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"
diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_name.c b/protocols/Tox/libtox/src/toxcore/events/friend_name.c
index b5a5129724..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"
/*****************************************************
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 88808b5825..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"
/*****************************************************
diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_request.c b/protocols/Tox/libtox/src/toxcore/events/friend_request.c
index 6cd8ac66c7..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"
diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_status.c b/protocols/Tox/libtox/src/toxcore/events/friend_status.c
index 5af2d451d7..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"
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 178342f292..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"
/*****************************************************
diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_typing.c b/protocols/Tox/libtox/src/toxcore/events/friend_typing.c
index 96c719570f..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"
/*****************************************************
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 eb4d49d594..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"
/*****************************************************
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 f7c1634120..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"
/*****************************************************
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_invite.c b/protocols/Tox/libtox/src/toxcore/events/group_invite.c
index 6372eb598c..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"
/*****************************************************
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 7b95454b84..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"
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_message.c b/protocols/Tox/libtox/src/toxcore/events/group_message.c
index 9ed07e43a6..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"
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_moderation.c b/protocols/Tox/libtox/src/toxcore/events/group_moderation.c
index eb8d3ba41e..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"
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_password.c b/protocols/Tox/libtox/src/toxcore/events/group_password.c
index 14bda0f766..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"
/*****************************************************
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 405b4b6c16..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"
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 8dc34befee..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"
/*****************************************************
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 157827c560..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"
/*****************************************************
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 063a6ab9a3..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"
/*****************************************************
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 d646caec8c..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"
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 3fa081c20a..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"
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 9b7f95aa3d..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"
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 6cc3080aa6..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"
/*****************************************************
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_topic.c b/protocols/Tox/libtox/src/toxcore/events/group_topic.c
index 7588d43f7f..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"
/*****************************************************
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 431ff38159..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"
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 d9c592b882..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"
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 b79d70b408..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"
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 f017b08888..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);
@@ -1034,9 +1040,9 @@ void kill_friend_connections(Friend_Connections *fr_c)
// there might be allocated NONE connections
if (fr_c->conns != nullptr) {
- free(fr_c->conns);
+ 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 3d96b962de..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;
}
@@ -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 2d64ae60ec..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.
@@ -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;
}
@@ -4461,7 +4474,7 @@ static bool send_gc_set_observer(const GC_Chat *chat, const Extended_Public_Key
const uint8_t *sanction_data, uint16_t length, bool add_obs)
{
const uint16_t packet_len = 1 + ENC_PUBLIC_KEY_SIZE + SIG_PUBLIC_KEY_SIZE + length;
- uint8_t *packet = (uint8_t *)malloc(packet_len);
+ uint8_t *packet = (uint8_t *)mem_balloc(chat->mem, packet_len);
if (packet == nullptr) {
return false;
@@ -4474,11 +4487,11 @@ static bool send_gc_set_observer(const GC_Chat *chat, const Extended_Public_Key
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;
}
@@ -4895,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;
@@ -4907,11 +4920,11 @@ 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;
}
- free(message_raw);
+ mem_delete(chat->mem, message_raw);
if (message_id != nullptr) {
*message_id = pseudo_msg_id;
@@ -4983,7 +4996,7 @@ int gc_send_private_message(const GC_Chat *chat, GC_Peer_Id peer_id, uint8_t typ
}
const uint16_t raw_length = 1 + length + GC_MESSAGE_PSEUDO_ID_SIZE;
- uint8_t *message_with_type = (uint8_t *)malloc(raw_length);
+ uint8_t *message_with_type = (uint8_t *)mem_balloc(chat->mem, raw_length);
if (message_with_type == nullptr) {
return -6;
@@ -4996,23 +5009,23 @@ int gc_send_private_message(const GC_Chat *chat, GC_Peer_Id peer_id, uint8_t typ
memcpy(message_with_type + 1 + GC_MESSAGE_PSEUDO_ID_SIZE, message, length);
- uint8_t *packet = (uint8_t *)malloc(raw_length + GC_BROADCAST_ENC_HEADER_SIZE);
+ 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, 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;
@@ -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)
@@ -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 d22ce400e6..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);
@@ -649,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.
@@ -675,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 daa8fe17c8..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];
@@ -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 c20d6a1213..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,9 +22,13 @@
#include "group_common.h"
#include "group_moderation.h"
#include "logger.h"
+#include "mem.h"
#include "network.h"
#include "util.h"
+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) {
@@ -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/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 5aafe8a8a9..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"
@@ -230,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) {
@@ -246,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];
@@ -254,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;
@@ -269,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)) {
@@ -308,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;
@@ -342,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);
@@ -439,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)
{
@@ -448,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)) {
@@ -481,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)) {
@@ -528,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;
}
@@ -540,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);
@@ -673,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);
@@ -981,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)
{
@@ -1064,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);
@@ -1084,7 +1086,7 @@ static int send_data_packet(Net_Crypto *c, int crypt_connection_id, const uint8_
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);
@@ -1102,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) {
@@ -1124,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);
@@ -1159,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) {
@@ -1255,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) {
@@ -1275,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);
@@ -1300,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;
@@ -1414,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);
@@ -1442,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);
@@ -1472,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);
@@ -1647,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);
@@ -1662,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;
}
@@ -1679,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);
@@ -2757,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;
}
@@ -2792,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) {
@@ -2878,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;
@@ -2986,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;
@@ -3004,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);
@@ -3026,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;
}
diff --git a/protocols/Tox/libtox/src/toxcore/net_crypto.h b/protocols/Tox/libtox/src/toxcore/net_crypto.h
index 8368d46e39..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. */
@@ -242,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.
*
@@ -254,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.
@@ -282,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.
*
@@ -404,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()
@@ -417,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 326575963b..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()
@@ -962,7 +1012,7 @@ static int handle_announce_response(void *object, const IP_Port *source, const u
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 b02eb4e98b..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);
}
@@ -752,6 +756,8 @@ static Tox *tox_new_system(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 @@ static Tox *tox_new_system(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 @@ static Tox *tox_new_system(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 @@ static Tox *tox_new_system(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);
@@ -1139,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);
@@ -3246,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) {
diff --git a/protocols/Tox/libtox/src/toxcore/tox.h b/protocols/Tox/libtox/src/toxcore/tox.h
index ebeed3b1f5..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-2024 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -87,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
@@ -95,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.
*
@@ -113,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
@@ -148,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 20
+#define TOX_VERSION_PATCH 21
uint32_t tox_version_patch(void);
@@ -274,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);
@@ -387,415 +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 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);
-
-/**
- * @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(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;
-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.
- */
- 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.
- *
- * 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;
-
- /**
- * 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);
-
-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
*/
@@ -943,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
@@ -3143,6 +2740,7 @@ 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.
*
@@ -3157,6 +2755,7 @@ Tox_Conference_Number tox_conference_by_id(
*/
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 {
@@ -3179,6 +2778,7 @@ 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.
*
@@ -3191,6 +2791,7 @@ const char *tox_err_conference_by_uid_to_string(Tox_Err_Conference_By_Uid value)
*/
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 */
/** @} */
@@ -3663,9 +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,
@@ -3695,12 +3294,15 @@ 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.
*
+ * 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
@@ -3795,6 +3397,7 @@ 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.
*
@@ -3805,8 +3408,11 @@ const char *tox_err_group_reconnect_to_string(Tox_Err_Group_Reconnect value);
* @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 {
@@ -5720,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;
@@ -5754,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 18d861c18e..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,191 +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;
-}
-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) {
@@ -378,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) {
@@ -1713,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 29ac66a412..6ad3fc8b66 100644
--- a/protocols/Tox/libtox/src/toxcore/tox_dispatch.h
+++ b/protocols/Tox/libtox/src/toxcore/tox_dispatch.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2022-2025 The TokTok team.
*/
/**
@@ -136,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);
@@ -217,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 f702d629fc..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;
@@ -923,8 +923,8 @@ static bool tox_event_type_from_int(uint32_t value, Tox_Event_Type *out_enum)
return true;
}
- case TOX_EVENT_DHT_GET_NODES_RESPONSE: {
- *out_enum = TOX_EVENT_DHT_GET_NODES_RESPONSE;
+ case TOX_EVENT_DHT_NODES_RESPONSE: {
+ *out_enum = TOX_EVENT_DHT_NODES_RESPONSE;
return true;
}
@@ -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 6bbf13e8ef..d82930e450 100644
--- a/protocols/Tox/libtox/src/toxcore/tox_events.h
+++ b/protocols/Tox/libtox/src/toxcore/tox_events.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022-2024 The TokTok team.
+ * Copyright © 2022-2025 The TokTok team.
*/
/**
@@ -352,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,
@@ -410,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;
@@ -507,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);
/**
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 c872bfea47..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-2024 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" {
@@ -92,52 +93,53 @@ uint32_t tox_dht_node_public_key_size(void);
* @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.
*/
- 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
+ * 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
+ * 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.
*
@@ -151,8 +153,8 @@ typedef enum Tox_Err_Dht_Get_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 number of DHT nodes in the closelist.
@@ -171,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.
*
******************************************************************************/
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 5caef02c07..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"
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 b785c26732..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.
*/
@@ -231,7 +231,7 @@ bool tox_pass_key_encrypt(const Tox_Pass_Key *key, const uint8_t plaintext[], si
ciphertext += crypto_box_NONCEBYTES;
/* now encrypt */
- const int32_t encrypted_len = encrypt_data_symmetric(key->key, nonce, plaintext, plaintext_len, ciphertext);
+ 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;
@@ -316,7 +316,7 @@ bool tox_pass_key_decrypt(const Tox_Pass_Key *key, const uint8_t ciphertext[], s
ciphertext += crypto_box_NONCEBYTES;
/* decrypt the ciphertext */
- const int32_t decrypted_len = decrypt_data_symmetric(key->key, nonce, ciphertext, decrypt_length + crypto_box_MACBYTES, plaintext);
+ 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;
@@ -395,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 e4cf116c97..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-2024 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
@@ -313,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.
*