summaryrefslogtreecommitdiff
path: root/protocols/Tox/libtox/src
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Tox/libtox/src')
-rw-r--r--protocols/Tox/libtox/src/third_party/cmp/cmp.c4
-rw-r--r--protocols/Tox/libtox/src/toxcore/DHT.c294
-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.inc179
-rw-r--r--protocols/Tox/libtox/src/toxcore/Messenger.c165
-rw-r--r--protocols/Tox/libtox/src/toxcore/Messenger.h57
-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.c21
-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.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/conference_invite.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/conference_message.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/conference_peer_list_changed.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/conference_peer_name.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/conference_title.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/dht_get_nodes_response.c223
-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.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/file_recv.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/file_recv_chunk.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/file_recv_control.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_connection_status.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_lossless_packet.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_lossy_packet.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_message.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_name.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_read_receipt.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_request.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_status.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_status_message.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/friend_typing.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_custom_packet.c12
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_custom_private_packet.c12
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_invite.c12
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_join_fail.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_message.c30
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_moderation.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_password.c12
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_peer_exit.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_peer_join.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_peer_limit.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_peer_name.c12
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_peer_status.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_privacy_state.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_private_message.c55
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_self_join.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_topic.c12
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_topic_lock.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/group_voice_state.c8
-rw-r--r--protocols/Tox/libtox/src/toxcore/events/self_connection_status.c8
-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.c27
-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.c124
-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.c515
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_chats.h21
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_common.h9
-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.c47
-rw-r--r--protocols/Tox/libtox/src/toxcore/group_pack.h4
-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.c237
-rw-r--r--protocols/Tox/libtox/src/toxcore/net_crypto.h31
-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.c166
-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.c318
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox.h1644
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_api.c592
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_dispatch.c18
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_dispatch.h17
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_event.c110
-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.h39
-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.h385
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_struct.h9
-rw-r--r--protocols/Tox/libtox/src/toxcore/tox_unpack.c112
-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.c97
-rw-r--r--protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.h40
147 files changed, 5842 insertions, 3502 deletions
diff --git a/protocols/Tox/libtox/src/third_party/cmp/cmp.c b/protocols/Tox/libtox/src/third_party/cmp/cmp.c
index c312efd6c7..c11d23a8a3 100644
--- a/protocols/Tox/libtox/src/third_party/cmp/cmp.c
+++ b/protocols/Tox/libtox/src/third_party/cmp/cmp.c
@@ -865,7 +865,7 @@ bool cmp_write_pfix(cmp_ctx_t *ctx, uint8_t c) {
}
bool cmp_write_nfix(cmp_ctx_t *ctx, int8_t c) {
- if (c >= -32 && c <= -1)
+ if (c >= -0x20 && c <= -1)
return write_fixed_value(ctx, (uint8_t)c);
ctx->error = CMP_ERROR_INPUT_VALUE_TOO_LARGE;
@@ -875,7 +875,7 @@ bool cmp_write_nfix(cmp_ctx_t *ctx, int8_t c) {
bool cmp_write_sfix(cmp_ctx_t *ctx, int8_t c) {
if (c >= 0)
return cmp_write_pfix(ctx, (uint8_t)c);
- if (c >= -32 && c <= -1)
+ if (c >= -0x20 && c <= -1)
return cmp_write_nfix(ctx, c);
ctx->error = CMP_ERROR_INPUT_VALUE_TOO_LARGE;
diff --git a/protocols/Tox/libtox/src/toxcore/DHT.c b/protocols/Tox/libtox/src/toxcore/DHT.c
index 2567d1b5a8..0dc49008e4 100644
--- a/protocols/Tox/libtox/src/toxcore/DHT.c
+++ b/protocols/Tox/libtox/src/toxcore/DHT.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -9,7 +9,6 @@
#include "DHT.h"
#include <assert.h>
-#include <stdlib.h>
#include <string.h>
#include "LAN_discovery.h"
@@ -24,13 +23,15 @@
#include "ping.h"
#include "ping_array.h"
#include "shared_key_cache.h"
+#include "sort.h"
#include "state.h"
+#include "util.h"
/** The timeout after which a node is discarded completely. */
#define KILL_NODE_TIMEOUT (BAD_NODE_TIMEOUT + PING_INTERVAL)
-/** Ping interval in seconds for each random sending of a get nodes request. */
-#define GET_NODE_INTERVAL 20
+/** Ping interval in seconds for each random sending of a nodes request. */
+#define NODES_REQUEST_INTERVAL 20
#define MAX_PUNCHING_PORTS 48
@@ -45,7 +46,7 @@
#define NAT_PING_REQUEST 0
#define NAT_PING_RESPONSE 1
-/** Number of get node requests to send to quickly find close nodes. */
+/** Number of node requests to send to quickly find close nodes. */
#define MAX_BOOTSTRAP_TIMES 5
// TODO(sudden6): find out why we need multiple callbacks and if we really need 32
@@ -65,9 +66,9 @@ struct DHT_Friend {
uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
Client_data client_list[MAX_FRIEND_CLIENTS];
- /* Time at which the last get_nodes request was sent. */
- uint64_t lastgetnode;
- /* number of times get_node packets were sent. */
+ /* Time at which the last nodes request was sent. */
+ uint64_t last_nodes_request;
+ /* number of times nodes request packets were sent. */
uint32_t bootstrap_times;
/* Symmetric NAT hole punching stuff. */
@@ -103,7 +104,7 @@ struct DHT {
bool lan_discovery_enabled;
Client_data close_clientlist[LCLIENT_LIST];
- uint64_t close_lastgetnodes;
+ uint64_t close_last_nodes_request;
uint32_t close_bootstrap_times;
/* DHT keypair */
@@ -129,7 +130,7 @@ struct DHT {
Node_format to_bootstrap[MAX_CLOSE_TO_BOOTSTRAP_NODES];
unsigned int num_to_bootstrap;
- dht_get_nodes_response_cb *get_nodes_response;
+ dht_nodes_response_cb *nodes_response_callback;
};
const uint8_t *dht_friend_public_key(const DHT_Friend *dht_friend)
@@ -279,7 +280,7 @@ const uint8_t *dht_get_shared_key_sent(DHT *dht, const uint8_t *public_key)
#define CRYPTO_SIZE (1 + CRYPTO_PUBLIC_KEY_SIZE * 2 + CRYPTO_NONCE_SIZE)
-int create_request(const Random *rng, const uint8_t *send_public_key, const uint8_t *send_secret_key,
+int create_request(const Memory *mem, const Random *rng, const uint8_t *send_public_key, const uint8_t *send_secret_key,
uint8_t *packet, const uint8_t *recv_public_key,
const uint8_t *data, uint32_t data_length, uint8_t request_id)
{
@@ -296,7 +297,7 @@ int create_request(const Random *rng, const uint8_t *send_public_key, const uint
uint8_t temp[MAX_CRYPTO_REQUEST_SIZE] = {0};
temp[0] = request_id;
memcpy(temp + 1, data, data_length);
- const int len = encrypt_data(recv_public_key, send_secret_key, nonce, temp, data_length + 1,
+ const int len = encrypt_data(mem, recv_public_key, send_secret_key, nonce, temp, data_length + 1,
packet + CRYPTO_SIZE);
if (len == -1) {
@@ -312,7 +313,7 @@ int create_request(const Random *rng, const uint8_t *send_public_key, const uint
return len + CRYPTO_SIZE;
}
-int handle_request(const uint8_t *self_public_key, const uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data,
+int handle_request(const Memory *mem, const uint8_t *self_public_key, const uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data,
uint8_t *request_id, const uint8_t *packet, uint16_t packet_length)
{
if (self_public_key == nullptr || public_key == nullptr || data == nullptr || request_id == nullptr
@@ -331,7 +332,7 @@ int handle_request(const uint8_t *self_public_key, const uint8_t *self_secret_ke
memcpy(public_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_PUBLIC_KEY_SIZE);
const uint8_t *const nonce = packet + 1 + CRYPTO_PUBLIC_KEY_SIZE * 2;
uint8_t temp[MAX_CRYPTO_REQUEST_SIZE];
- int32_t len1 = decrypt_data(public_key, self_secret_key, nonce,
+ int32_t len1 = decrypt_data(mem, public_key, self_secret_key, nonce,
packet + CRYPTO_SIZE, packet_length - CRYPTO_SIZE, temp);
if (len1 == -1 || len1 == 0) {
@@ -378,14 +379,14 @@ int dht_create_packet(const Memory *mem, const Random *rng,
random_nonce(rng, nonce);
- const int encrypted_length = encrypt_data_symmetric(shared_key, nonce, plain, plain_length, encrypted);
+ const int encrypted_length = encrypt_data_symmetric(mem, shared_key, nonce, plain, plain_length, encrypted);
- if (encrypted_length == -1) {
+ if (encrypted_length < 0) {
mem_delete(mem, encrypted);
return -1;
}
- if (length < 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + encrypted_length) {
+ if (length < 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + (size_t)encrypted_length) {
mem_delete(mem, encrypted);
return -1;
}
@@ -430,7 +431,7 @@ int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed
const int ipp_size = unpack_ip_port(&nodes[num].ip_port, data + len_processed, length - len_processed, tcp_enabled);
if (ipp_size == -1) {
- return -1;
+ break;
}
len_processed += ipp_size;
@@ -449,6 +450,10 @@ int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed
#endif /* NDEBUG */
}
+ if (num == 0 && max_num_nodes > 0 && length > 0) {
+ return -1;
+ }
+
if (processed_data_len != nullptr) {
*processed_data_len = len_processed;
}
@@ -707,7 +712,7 @@ static void get_close_nodes_inner(
}
/**
- * Find MAX_SENT_NODES nodes closest to the public_key for the send nodes request:
+ * Find MAX_SENT_NODES nodes closest to the public_key for the nodes request:
* put them in the nodes_list and return how many were found.
*
* want_announce: return only nodes which implement the dht announcements protocol.
@@ -755,49 +760,6 @@ int get_close_nodes(
is_lan, want_announce);
}
-typedef struct DHT_Cmp_Data {
- uint64_t cur_time;
- const uint8_t *base_public_key;
- Client_data entry;
-} DHT_Cmp_Data;
-
-non_null()
-static int dht_cmp_entry(const void *a, const void *b)
-{
- const DHT_Cmp_Data *cmp1 = (const DHT_Cmp_Data *)a;
- const DHT_Cmp_Data *cmp2 = (const DHT_Cmp_Data *)b;
- const Client_data entry1 = cmp1->entry;
- const Client_data entry2 = cmp2->entry;
- const uint8_t *cmp_public_key = cmp1->base_public_key;
-
- const bool t1 = assoc_timeout(cmp1->cur_time, &entry1.assoc4) && assoc_timeout(cmp1->cur_time, &entry1.assoc6);
- const bool t2 = assoc_timeout(cmp2->cur_time, &entry2.assoc4) && assoc_timeout(cmp2->cur_time, &entry2.assoc6);
-
- if (t1 && t2) {
- return 0;
- }
-
- if (t1) {
- return -1;
- }
-
- if (t2) {
- return 1;
- }
-
- const int closest = id_closest(cmp_public_key, entry1.public_key, entry2.public_key);
-
- if (closest == 1) {
- return 1;
- }
-
- if (closest == 2) {
- return -1;
- }
-
- return 0;
-}
-
#ifdef CHECK_ANNOUNCE_NODE
non_null()
static void set_announce_node_in_list(Client_data *list, uint32_t list_len, const uint8_t *public_key)
@@ -870,7 +832,7 @@ static int handle_data_search_response(void *object, const IP_Port *source,
const uint8_t *public_key = packet + 1;
const uint8_t *shared_key = dht_get_shared_key_recv(dht, public_key);
- if (decrypt_data_symmetric(shared_key,
+ if (decrypt_data_symmetric(dht->mem, shared_key,
packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
plain_len + CRYPTO_MAC_SIZE,
@@ -914,31 +876,117 @@ static bool store_node_ok(const Client_data *client, uint64_t cur_time, const ui
|| id_closest(comp_public_key, client->public_key, public_key) == 2;
}
+typedef struct Client_data_Cmp {
+ const Memory *mem;
+ uint64_t cur_time;
+ const uint8_t *comp_public_key;
+} Client_data_Cmp;
+
non_null()
-static void sort_client_list(const Memory *mem, Client_data *list, uint64_t cur_time, unsigned int length,
- const uint8_t *comp_public_key)
+static int client_data_cmp(const Client_data_Cmp *cmp, const Client_data *entry1, const Client_data *entry2)
{
- // Pass comp_public_key to qsort with each Client_data entry, so the
- // comparison function can use it as the base of comparison.
- DHT_Cmp_Data *cmp_list = (DHT_Cmp_Data *)mem_valloc(mem, length, sizeof(DHT_Cmp_Data));
+ const bool t1 = assoc_timeout(cmp->cur_time, &entry1->assoc4) && assoc_timeout(cmp->cur_time, &entry1->assoc6);
+ const bool t2 = assoc_timeout(cmp->cur_time, &entry2->assoc4) && assoc_timeout(cmp->cur_time, &entry2->assoc6);
- if (cmp_list == nullptr) {
- return;
+ if (t1 && t2) {
+ return 0;
}
- for (uint32_t i = 0; i < length; ++i) {
- cmp_list[i].cur_time = cur_time;
- cmp_list[i].base_public_key = comp_public_key;
- cmp_list[i].entry = list[i];
+ if (t1) {
+ return -1;
+ }
+
+ if (t2) {
+ return 1;
}
- qsort(cmp_list, length, sizeof(DHT_Cmp_Data), dht_cmp_entry);
+ const int closest = id_closest(cmp->comp_public_key, entry1->public_key, entry2->public_key);
- for (uint32_t i = 0; i < length; ++i) {
- list[i] = cmp_list[i].entry;
+ if (closest == 1) {
+ return 1;
}
- mem_delete(mem, cmp_list);
+ if (closest == 2) {
+ return -1;
+ }
+
+ return 0;
+}
+
+non_null()
+static bool client_data_less_handler(const void *object, const void *a, const void *b)
+{
+ const Client_data_Cmp *cmp = (const Client_data_Cmp *)object;
+ const Client_data *entry1 = (const Client_data *)a;
+ const Client_data *entry2 = (const Client_data *)b;
+
+ return client_data_cmp(cmp, entry1, entry2) < 0;
+}
+
+non_null()
+static const void *client_data_get_handler(const void *arr, uint32_t index)
+{
+ const Client_data *entries = (const Client_data *)arr;
+ return &entries[index];
+}
+
+non_null()
+static void client_data_set_handler(void *arr, uint32_t index, const void *val)
+{
+ Client_data *entries = (Client_data *)arr;
+ const Client_data *entry = (const Client_data *)val;
+ entries[index] = *entry;
+}
+
+non_null()
+static void *client_data_subarr_handler(void *arr, uint32_t index, uint32_t size)
+{
+ Client_data *entries = (Client_data *)arr;
+ return &entries[index];
+}
+
+non_null()
+static void *client_data_alloc_handler(const void *object, uint32_t size)
+{
+ const Client_data_Cmp *cmp = (const Client_data_Cmp *)object;
+ Client_data *tmp = (Client_data *)mem_valloc(cmp->mem, size, sizeof(Client_data));
+
+ if (tmp == nullptr) {
+ return nullptr;
+ }
+
+ return tmp;
+}
+
+non_null()
+static void client_data_delete_handler(const void *object, void *arr, uint32_t size)
+{
+ const Client_data_Cmp *cmp = (const Client_data_Cmp *)object;
+ mem_delete(cmp->mem, arr);
+}
+
+static const Sort_Funcs client_data_cmp_funcs = {
+ client_data_less_handler,
+ client_data_get_handler,
+ client_data_set_handler,
+ client_data_subarr_handler,
+ client_data_alloc_handler,
+ client_data_delete_handler,
+};
+
+non_null()
+static void sort_client_list(const Memory *mem, Client_data *list, uint64_t cur_time, unsigned int length,
+ const uint8_t *comp_public_key)
+{
+ // Pass comp_public_key to merge_sort with each Client_data entry, so the
+ // comparison function can use it as the base of comparison.
+ const Client_data_Cmp cmp = {
+ mem,
+ cur_time,
+ comp_public_key,
+ };
+
+ merge_sort(list, length, &cmp, &client_data_cmp_funcs);
}
non_null()
@@ -1087,7 +1135,7 @@ static bool is_pk_in_close_list(const DHT *dht, const uint8_t *public_key, const
ip_port);
}
-/** @brief Check if the node obtained with a get_nodes with public_key should be pinged.
+/** @brief Check if the node obtained from a nodes response with public_key should be pinged.
*
* NOTE: for best results call it after addto_lists.
*
@@ -1095,7 +1143,7 @@ static bool is_pk_in_close_list(const DHT *dht, const uint8_t *public_key, const
* return true if it should.
*/
non_null()
-static bool ping_node_from_getnodes_ok(DHT *dht, const uint8_t *public_key, const IP_Port *ip_port)
+static bool ping_node_from_nodes_response_ok(DHT *dht, const uint8_t *public_key, const IP_Port *ip_port)
{
bool ret = false;
@@ -1266,7 +1314,7 @@ static void returnedip_ports(DHT *dht, const IP_Port *ip_port, const uint8_t *pu
}
}
-bool dht_getnodes(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *client_id)
+bool dht_send_nodes_request(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *client_id)
{
/* Check if packet is going to be sent to ourself. */
if (pk_equal(public_key, dht->self_public_key)) {
@@ -1301,21 +1349,21 @@ bool dht_getnodes(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key, c
const uint8_t *shared_key = dht_get_shared_key_sent(dht, public_key);
const int len = dht_create_packet(dht->mem, dht->rng,
- dht->self_public_key, shared_key, NET_PACKET_GET_NODES,
+ dht->self_public_key, shared_key, NET_PACKET_NODES_REQUEST,
plain, sizeof(plain), data, sizeof(data));
if (len != sizeof(data)) {
- LOGGER_ERROR(dht->log, "getnodes packet encryption failed");
+ LOGGER_ERROR(dht->log, "nodes request packet encryption failed");
return false;
}
return sendpacket(dht->net, ip_port, data, len) > 0;
}
-/** Send a send nodes response: message for IPv6 nodes */
+/** Send a nodes response */
non_null()
-static int sendnodes_ipv6(const DHT *dht, const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *client_id,
- const uint8_t *sendback_data, uint16_t length, const uint8_t *shared_encryption_key)
+static int send_nodes_response(const DHT *dht, const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *client_id,
+ const uint8_t *sendback_data, uint16_t length, const uint8_t *shared_encryption_key)
{
/* Check if packet is going to be sent to ourself. */
if (pk_equal(public_key, dht->self_public_key)) {
@@ -1347,15 +1395,15 @@ static int sendnodes_ipv6(const DHT *dht, const IP_Port *ip_port, const uint8_t
plain[0] = num_nodes;
memcpy(plain + 1 + nodes_length, sendback_data, length);
- const uint32_t crypto_size = 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_MAC_SIZE;
- const uint32_t data_size = 1 + nodes_length + length + crypto_size;
+ const uint16_t crypto_size = 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_MAC_SIZE;
+ const uint16_t data_size = 1 + nodes_length + length + crypto_size;
VLA(uint8_t, data, data_size);
const int len = dht_create_packet(dht->mem, dht->rng,
- dht->self_public_key, shared_encryption_key, NET_PACKET_SEND_NODES_IPV6,
+ dht->self_public_key, shared_encryption_key, NET_PACKET_NODES_RESPONSE,
plain, 1 + nodes_length + length, data, data_size);
- if (len != data_size) {
+ if (len < 0 || (uint32_t)len != data_size) {
return -1;
}
@@ -1365,7 +1413,7 @@ static int sendnodes_ipv6(const DHT *dht, const IP_Port *ip_port, const uint8_t
#define CRYPTO_NODE_SIZE (CRYPTO_PUBLIC_KEY_SIZE + sizeof(uint64_t))
non_null()
-static int handle_getnodes(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)
+static int handle_nodes_request(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)
{
DHT *const dht = (DHT *)object;
@@ -1381,6 +1429,7 @@ static int handle_getnodes(void *object, const IP_Port *source, const uint8_t *p
uint8_t plain[CRYPTO_NODE_SIZE];
const uint8_t *shared_key = dht_get_shared_key_recv(dht, packet + 1);
const int len = decrypt_data_symmetric(
+ dht->mem,
shared_key,
packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
@@ -1391,16 +1440,16 @@ static int handle_getnodes(void *object, const IP_Port *source, const uint8_t *p
return 1;
}
- sendnodes_ipv6(dht, source, packet + 1, plain, plain + CRYPTO_PUBLIC_KEY_SIZE, sizeof(uint64_t), shared_key);
+ send_nodes_response(dht, source, packet + 1, plain, plain + CRYPTO_PUBLIC_KEY_SIZE, sizeof(uint64_t), shared_key);
ping_add(dht->ping, packet + 1, source);
return 0;
}
-/** Return true if we sent a getnode packet to the peer associated with the supplied info. */
+/** Return true if we sent a nodes request packet to the peer associated with the supplied info. */
non_null()
-static bool sent_getnode_to_node(DHT *dht, const uint8_t *public_key, const IP_Port *node_ip_port, uint64_t ping_id)
+static bool sent_nodes_request_to_node(DHT *dht, const uint8_t *public_key, const IP_Port *node_ip_port, uint64_t ping_id)
{
uint8_t data[sizeof(Node_format) * 2];
@@ -1418,8 +1467,8 @@ static bool sent_getnode_to_node(DHT *dht, const uint8_t *public_key, const IP_P
}
non_null()
-static bool handle_sendnodes_core(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length,
- Node_format *plain_nodes, uint16_t size_plain_nodes, uint32_t *num_nodes_out)
+static bool handle_nodes_response_core(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length,
+ Node_format *plain_nodes, uint16_t size_plain_nodes, uint32_t *num_nodes_out)
{
DHT *const dht = (DHT *)object;
const uint32_t cid_size = 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + 1 + sizeof(uint64_t) + CRYPTO_MAC_SIZE;
@@ -1442,6 +1491,7 @@ static bool handle_sendnodes_core(void *object, const IP_Port *source, const uin
VLA(uint8_t, plain, plain_size);
const uint8_t *shared_key = dht_get_shared_key_sent(dht, packet + 1);
const int len = decrypt_data_symmetric(
+ dht->mem,
shared_key,
packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
@@ -1459,7 +1509,7 @@ static bool handle_sendnodes_core(void *object, const IP_Port *source, const uin
uint64_t ping_id;
memcpy(&ping_id, plain + 1 + data_size, sizeof(ping_id));
- if (!sent_getnode_to_node(dht, packet + 1, source, ping_id)) {
+ if (!sent_nodes_request_to_node(dht, packet + 1, source, ping_id)) {
return false;
}
@@ -1487,14 +1537,14 @@ static bool handle_sendnodes_core(void *object, const IP_Port *source, const uin
}
non_null()
-static int handle_sendnodes_ipv6(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length,
+static int handle_nodes_response(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length,
void *userdata)
{
DHT *const dht = (DHT *)object;
Node_format plain_nodes[MAX_SENT_NODES];
uint32_t num_nodes;
- if (!handle_sendnodes_core(object, source, packet, length, plain_nodes, MAX_SENT_NODES, &num_nodes)) {
+ if (!handle_nodes_response_core(object, source, packet, length, plain_nodes, MAX_SENT_NODES, &num_nodes)) {
return 1;
}
@@ -1504,11 +1554,11 @@ static int handle_sendnodes_ipv6(void *object, const IP_Port *source, const uint
for (uint32_t i = 0; i < num_nodes; ++i) {
if (ipport_isset(&plain_nodes[i].ip_port)) {
- ping_node_from_getnodes_ok(dht, plain_nodes[i].public_key, &plain_nodes[i].ip_port);
+ ping_node_from_nodes_response_ok(dht, plain_nodes[i].public_key, &plain_nodes[i].ip_port);
returnedip_ports(dht, &plain_nodes[i].ip_port, plain_nodes[i].public_key, packet + 1);
- if (dht->get_nodes_response != nullptr) {
- dht->get_nodes_response(dht, &plain_nodes[i], userdata);
+ if (dht->nodes_response_callback != nullptr) {
+ dht->nodes_response_callback(dht, &plain_nodes[i], userdata);
}
}
}
@@ -1721,7 +1771,7 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co
if (mono_time_is_timeout(dht->mono_time, assoc->last_pinged, PING_INTERVAL)) {
const IP_Port *target = &assoc->ip_port;
const uint8_t *target_key = client->public_key;
- dht_getnodes(dht, target, target_key, public_key);
+ dht_send_nodes_request(dht, target, target_key, public_key);
assoc->last_pinged = temp_time;
}
@@ -1746,7 +1796,7 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co
sort_client_list(dht->mem, list, dht->cur_time, list_count, public_key);
}
- if (num_nodes > 0 && (mono_time_is_timeout(dht->mono_time, *lastgetnode, GET_NODE_INTERVAL)
+ if (num_nodes > 0 && (mono_time_is_timeout(dht->mono_time, *lastgetnode, NODES_REQUEST_INTERVAL)
|| *bootstrap_times < MAX_BOOTSTRAP_TIMES)) {
uint32_t rand_node = random_range_u32(dht->rng, num_nodes);
@@ -1756,7 +1806,7 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co
const IP_Port *target = &assoc_list[rand_node]->ip_port;
const uint8_t *target_key = client_list[rand_node]->public_key;
- dht_getnodes(dht, target, target_key, public_key);
+ dht_send_nodes_request(dht, target, target_key, public_key);
*lastgetnode = temp_time;
++*bootstrap_times;
@@ -1769,7 +1819,7 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co
/** @brief Ping each client in the "friends" list every PING_INTERVAL seconds.
*
- * Send a get nodes request every GET_NODE_INTERVAL seconds to a random good
+ * Send a nodes request every NODES_REQUEST_INTERVAL seconds to a random good
* node for each "friend" in our "friends" list.
*/
non_null()
@@ -1779,31 +1829,31 @@ static void do_dht_friends(DHT *dht)
DHT_Friend *const dht_friend = &dht->friends_list[i];
for (size_t j = 0; j < dht_friend->num_to_bootstrap; ++j) {
- dht_getnodes(dht, &dht_friend->to_bootstrap[j].ip_port, dht_friend->to_bootstrap[j].public_key, dht_friend->public_key);
+ dht_send_nodes_request(dht, &dht_friend->to_bootstrap[j].ip_port, dht_friend->to_bootstrap[j].public_key, dht_friend->public_key);
}
dht_friend->num_to_bootstrap = 0;
- do_ping_and_sendnode_requests(dht, &dht_friend->lastgetnode, dht_friend->public_key, dht_friend->client_list,
+ do_ping_and_sendnode_requests(dht, &dht_friend->last_nodes_request, dht_friend->public_key, dht_friend->client_list,
MAX_FRIEND_CLIENTS, &dht_friend->bootstrap_times, true);
}
}
/** @brief Ping each client in the close nodes list every PING_INTERVAL seconds.
*
- * Send a get nodes request every GET_NODE_INTERVAL seconds to a random good node in the list.
+ * Send a nodes request every NODES_REQUEST_INTERVAL seconds to a random good node in the list.
*/
non_null()
static void do_close(DHT *dht)
{
for (size_t i = 0; i < dht->num_to_bootstrap; ++i) {
- dht_getnodes(dht, &dht->to_bootstrap[i].ip_port, dht->to_bootstrap[i].public_key, dht->self_public_key);
+ dht_send_nodes_request(dht, &dht->to_bootstrap[i].ip_port, dht->to_bootstrap[i].public_key, dht->self_public_key);
}
dht->num_to_bootstrap = 0;
const uint8_t not_killed = do_ping_and_sendnode_requests(
- dht, &dht->close_lastgetnodes, dht->self_public_key, dht->close_clientlist, LCLIENT_LIST, &dht->close_bootstrap_times,
+ dht, &dht->close_last_nodes_request, dht->self_public_key, dht->close_clientlist, LCLIENT_LIST, &dht->close_bootstrap_times,
false);
if (not_killed != 0) {
@@ -1837,10 +1887,10 @@ bool dht_bootstrap(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key)
return true;
}
- return dht_getnodes(dht, ip_port, public_key, dht->self_public_key);
+ return dht_send_nodes_request(dht, ip_port, public_key, dht->self_public_key);
}
-bool dht_bootstrap_from_address(DHT *dht, const char *address, bool ipv6enabled,
+bool dht_bootstrap_from_address(DHT *dht, const char *address, bool ipv6enabled, bool dns_enabled,
uint16_t port, const uint8_t *public_key)
{
IP_Port ip_port_v64;
@@ -1855,7 +1905,7 @@ bool dht_bootstrap_from_address(DHT *dht, const char *address, bool ipv6enabled,
ip_extra = &ip_port_v4.ip;
}
- if (addr_resolve_or_parse_ip(dht->ns, address, &ip_port_v64.ip, ip_extra)) {
+ if (addr_resolve_or_parse_ip(dht->ns, dht->mem, address, &ip_port_v64.ip, ip_extra, dns_enabled)) {
ip_port_v64.port = port;
dht_bootstrap(dht, &ip_port_v64, public_key);
@@ -2123,7 +2173,7 @@ static int send_nat_ping(const DHT *dht, const uint8_t *public_key, uint64_t pin
memcpy(data + 1, &ping_id, sizeof(uint64_t));
/* 254 is NAT ping request packet id */
const int len = create_request(
- dht->rng, dht->self_public_key, dht->self_secret_key, packet_data, public_key,
+ dht->mem, dht->rng, dht->self_public_key, dht->self_secret_key, packet_data, public_key,
data, sizeof(uint64_t) + 1, CRYPTO_PACKET_NAT_PING);
if (len == -1) {
@@ -2458,7 +2508,7 @@ static int cryptopacket_handle(void *object, const IP_Port *source, const uint8_
uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
uint8_t data[MAX_CRYPTO_REQUEST_SIZE];
uint8_t number;
- const int len = handle_request(dht->self_public_key, dht->self_secret_key, public_key,
+ const int len = handle_request(dht->mem, dht->self_public_key, dht->self_secret_key, public_key,
data, &number, packet, length);
if (len == -1 || len == 0) {
@@ -2484,9 +2534,9 @@ static int cryptopacket_handle(void *object, const IP_Port *source, const uint8_
return 1;
}
-void dht_callback_get_nodes_response(DHT *dht, dht_get_nodes_response_cb *function)
+void dht_callback_nodes_response(DHT *dht, dht_nodes_response_cb *function)
{
- dht->get_nodes_response = function;
+ dht->nodes_response_callback = function;
}
non_null(1, 2, 3) nullable(5)
@@ -2547,8 +2597,8 @@ DHT *new_dht(const Logger *log, const Memory *mem, const Random *rng, const Netw
return nullptr;
}
- networking_registerhandler(dht->net, NET_PACKET_GET_NODES, &handle_getnodes, dht);
- networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, dht);
+ networking_registerhandler(dht->net, NET_PACKET_NODES_REQUEST, &handle_nodes_request, dht);
+ networking_registerhandler(dht->net, NET_PACKET_NODES_RESPONSE, &handle_nodes_response, dht);
networking_registerhandler(dht->net, NET_PACKET_CRYPTO, &cryptopacket_handle, dht);
networking_registerhandler(dht->net, NET_PACKET_LAN_DISCOVERY, &handle_lan_discovery, dht);
cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, &handle_nat_ping, dht);
@@ -2626,8 +2676,8 @@ void kill_dht(DHT *dht)
return;
}
- networking_registerhandler(dht->net, NET_PACKET_GET_NODES, nullptr, nullptr);
- networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, nullptr, nullptr);
+ networking_registerhandler(dht->net, NET_PACKET_NODES_REQUEST, nullptr, nullptr);
+ networking_registerhandler(dht->net, NET_PACKET_NODES_RESPONSE, nullptr, nullptr);
networking_registerhandler(dht->net, NET_PACKET_CRYPTO, nullptr, nullptr);
networking_registerhandler(dht->net, NET_PACKET_LAN_DISCOVERY, nullptr, nullptr);
cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, nullptr, nullptr);
diff --git a/protocols/Tox/libtox/src/toxcore/DHT.h b/protocols/Tox/libtox/src/toxcore/DHT.h
index 19a9e1d937..16b293331c 100644
--- a/protocols/Tox/libtox/src/toxcore/DHT.h
+++ b/protocols/Tox/libtox/src/toxcore/DHT.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -36,7 +36,7 @@ extern "C" {
#define MAX_CLOSE_TO_BOOTSTRAP_NODES 8
-/** The max number of nodes to send with send nodes. */
+/** The max number of nodes to send with nodes response. */
#define MAX_SENT_NODES 4
/** Ping timeout in seconds */
@@ -99,7 +99,7 @@ extern "C" {
* @return the length of the created packet on success.
*/
non_null()
-int create_request(const Random *rng, const uint8_t *send_public_key, const uint8_t *send_secret_key,
+int create_request(const Memory *mem, const Random *rng, const uint8_t *send_public_key, const uint8_t *send_secret_key,
uint8_t *packet, const uint8_t *recv_public_key,
const uint8_t *data, uint32_t data_length, uint8_t request_id);
@@ -127,7 +127,7 @@ int create_request(const Random *rng, const uint8_t *send_public_key, const uint
*/
non_null()
int handle_request(
- const uint8_t *self_public_key, const uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data,
+ const Memory *mem, const uint8_t *self_public_key, const uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data,
uint8_t *request_id, const uint8_t *packet, uint16_t packet_length);
typedef struct IPPTs {
@@ -259,21 +259,21 @@ non_null()
const uint8_t *dht_get_shared_key_sent(DHT *dht, const uint8_t *public_key);
/**
- * Sends a getnodes request to `ip_port` with the public key `public_key` for nodes
+ * Sends a nodes request to `ip_port` with the public key `public_key` for nodes
* that are close to `client_id`.
*
* @retval true on success.
*/
non_null()
-bool dht_getnodes(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *client_id);
+bool dht_send_nodes_request(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *client_id);
typedef void dht_ip_cb(void *object, int32_t number, const IP_Port *ip_port);
-typedef void dht_get_nodes_response_cb(const DHT *dht, const Node_format *node, void *user_data);
+typedef void dht_nodes_response_cb(const DHT *dht, const Node_format *node, void *user_data);
-/** Sets the callback to be triggered on a getnodes response. */
+/** Sets the callback to be triggered on a nodes response. */
non_null(1) nullable(2)
-void dht_callback_get_nodes_response(DHT *dht, dht_get_nodes_response_cb *function);
+void dht_callback_nodes_response(DHT *dht, dht_nodes_response_cb *function);
/** @brief Add a new friend to the friends list.
* @param public_key must be CRYPTO_PUBLIC_KEY_SIZE bytes long.
@@ -390,7 +390,7 @@ void do_dht(DHT *dht);
* Use these two functions to bootstrap the client.
*/
/**
- * @brief Sends a "get nodes" request to the given node with ip, port and public_key
+ * @brief Sends a "nodes request" to the given node with ip, port and public_key
* to setup connections
*/
non_null()
@@ -398,18 +398,19 @@ bool dht_bootstrap(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key);
/** @brief Resolves address into an IP address.
*
- * If successful, sends a "get nodes" request to the given node with ip, port
+ * If successful, sends a "nodes request" to the given node with ip, port
* and public_key to setup connections
*
* @param address can be a hostname or an IP address (IPv4 or IPv6).
* @param ipv6enabled if false, the resolving sticks STRICTLY to IPv4 addresses.
* Otherwise, the resolving looks for IPv6 addresses first, then IPv4 addresses.
+ * @param dns_enabled if false, the resolving does not use DNS, only IP addresses are supported.
*
* @retval true if the address could be converted into an IP address
* @retval false otherwise
*/
non_null()
-bool dht_bootstrap_from_address(DHT *dht, const char *address, bool ipv6enabled,
+bool dht_bootstrap_from_address(DHT *dht, const char *address, bool ipv6enabled, bool dns_enabled,
uint16_t port, const uint8_t *public_key);
/** @brief Start sending packets after DHT loaded_friends_list and loaded_clients_list are set.
diff --git a/protocols/Tox/libtox/src/toxcore/LAN_discovery.c b/protocols/Tox/libtox/src/toxcore/LAN_discovery.c
index aead975911..fcc3d4793f 100644
--- a/protocols/Tox/libtox/src/toxcore/LAN_discovery.c
+++ b/protocols/Tox/libtox/src/toxcore/LAN_discovery.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -8,8 +8,6 @@
*/
#include "LAN_discovery.h"
-#include <stdlib.h>
-
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
// The mingw32/64 Windows library warns about including winsock2.h after
// windows.h even though with the above it's a valid thing to do. So, to make
@@ -41,11 +39,14 @@
#include "attributes.h"
#include "ccompat.h"
#include "crypto_core.h"
+#include "mem.h"
#include "network.h"
#define MAX_INTERFACES 16
struct Broadcast_Info {
+ const Memory *mem;
+
uint32_t count;
IP ips[MAX_INTERFACES];
};
@@ -53,29 +54,31 @@ struct Broadcast_Info {
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
non_null()
-static Broadcast_Info *fetch_broadcast_info(const Network *ns)
+static Broadcast_Info *fetch_broadcast_info(const Memory *mem, const Network *ns)
{
- Broadcast_Info *broadcast = (Broadcast_Info *)calloc(1, sizeof(Broadcast_Info));
+ Broadcast_Info *broadcast = (Broadcast_Info *)mem_alloc(mem, sizeof(Broadcast_Info));
if (broadcast == nullptr) {
return nullptr;
}
- IP_ADAPTER_INFO *adapter_info = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO));
+ broadcast->mem = mem;
+
+ IP_ADAPTER_INFO *adapter_info = (IP_ADAPTER_INFO *)mem_balloc(mem, sizeof(IP_ADAPTER_INFO));
if (adapter_info == nullptr) {
- free(broadcast);
+ mem_delete(mem, broadcast);
return nullptr;
}
unsigned long out_buf_len = sizeof(IP_ADAPTER_INFO);
if (GetAdaptersInfo(adapter_info, &out_buf_len) == ERROR_BUFFER_OVERFLOW) {
- free(adapter_info);
- IP_ADAPTER_INFO *new_adapter_info = (IP_ADAPTER_INFO *)malloc(out_buf_len);
+ mem_delete(mem, adapter_info);
+ IP_ADAPTER_INFO *new_adapter_info = (IP_ADAPTER_INFO *)mem_balloc(mem, out_buf_len);
if (new_adapter_info == nullptr) {
- free(broadcast);
+ mem_delete(mem, broadcast);
return nullptr;
}
@@ -113,7 +116,7 @@ static Broadcast_Info *fetch_broadcast_info(const Network *ns)
}
if (adapter_info != nullptr) {
- free(adapter_info);
+ mem_delete(mem, adapter_info);
}
return broadcast;
@@ -122,14 +125,19 @@ static Broadcast_Info *fetch_broadcast_info(const Network *ns)
#elif !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && (defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__))
non_null()
-static Broadcast_Info *fetch_broadcast_info(const Network *ns)
+static bool ip4_is_local(const IP4 *ip4);
+
+non_null()
+static Broadcast_Info *fetch_broadcast_info(const Memory *mem, const Network *ns)
{
- Broadcast_Info *broadcast = (Broadcast_Info *)calloc(1, sizeof(Broadcast_Info));
+ Broadcast_Info *broadcast = (Broadcast_Info *)mem_alloc(mem, sizeof(Broadcast_Info));
if (broadcast == nullptr) {
return nullptr;
}
+ broadcast->mem = mem;
+
/* Not sure how many platforms this will run on,
* so it's wrapped in `__linux__` for now.
* Definitely won't work like this on Windows...
@@ -137,7 +145,7 @@ static Broadcast_Info *fetch_broadcast_info(const Network *ns)
const Socket sock = net_socket(ns, net_family_ipv4(), TOX_SOCK_STREAM, 0);
if (!sock_valid(sock)) {
- free(broadcast);
+ mem_delete(mem, broadcast);
return nullptr;
}
@@ -150,7 +158,7 @@ static Broadcast_Info *fetch_broadcast_info(const Network *ns)
if (ioctl(net_socket_to_native(sock), SIOCGIFCONF, &ifc) < 0) {
kill_sock(ns, sock);
- free(broadcast);
+ mem_delete(mem, broadcast);
return nullptr;
}
@@ -162,7 +170,8 @@ static Broadcast_Info *fetch_broadcast_info(const Network *ns)
const int n = ifc.ifc_len / sizeof(struct ifreq);
for (int i = 0; i < n; ++i) {
- /* there are interfaces with are incapable of broadcast */
+ /* there are interfaces with are incapable of broadcast
+ * on Linux, `lo` has no broadcast address, but this function returns `>=0` */
if (ioctl(net_socket_to_native(sock), SIOCGIFBRDADDR, &i_faces[i]) < 0) {
continue;
}
@@ -172,7 +181,7 @@ static Broadcast_Info *fetch_broadcast_info(const Network *ns)
continue;
}
- const struct sockaddr_in *sock4 = (const struct sockaddr_in *)(void *)&i_faces[i].ifr_broadaddr;
+ const struct sockaddr_in *broadaddr4 = (const struct sockaddr_in *)(void *)&i_faces[i].ifr_broadaddr;
if (broadcast->count >= MAX_INTERFACES) {
break;
@@ -180,10 +189,27 @@ static Broadcast_Info *fetch_broadcast_info(const Network *ns)
IP *ip = &broadcast->ips[broadcast->count];
ip->family = net_family_ipv4();
- ip->ip.v4.uint32 = sock4->sin_addr.s_addr;
+ ip->ip.v4.uint32 = broadaddr4->sin_addr.s_addr;
+ // if no broadcast address
if (ip->ip.v4.uint32 == 0) {
- continue;
+ if (ioctl(net_socket_to_native(sock), SIOCGIFADDR, &i_faces[i]) < 0) {
+ continue;
+ }
+
+ const struct sockaddr_in *addr4 = (const struct sockaddr_in *)(void *)&i_faces[i].ifr_addr;
+
+
+ IP4 ip4_staging;
+ ip4_staging.uint32 = addr4->sin_addr.s_addr;
+
+ if (ip4_is_local(&ip4_staging)) {
+ // this is 127.x.x.x
+ ip->ip.v4.uint32 = ip4_staging.uint32;
+ } else {
+ // give up.
+ continue;
+ }
}
++broadcast->count;
@@ -197,9 +223,17 @@ static Broadcast_Info *fetch_broadcast_info(const Network *ns)
#else // TODO(irungentoo): Other platforms?
non_null()
-static Broadcast_Info *fetch_broadcast_info(const Network *ns)
+static Broadcast_Info *fetch_broadcast_info(const Memory *mem, const Network *ns)
{
- return (Broadcast_Info *)calloc(1, sizeof(Broadcast_Info));
+ Broadcast_Info *broadcast = (Broadcast_Info *)mem_alloc(mem, sizeof(Broadcast_Info));
+
+ if (broadcast == nullptr) {
+ return nullptr;
+ }
+
+ broadcast->mem = mem;
+
+ return broadcast;
}
#endif /* platforms */
@@ -375,12 +409,16 @@ bool lan_discovery_send(const Networking_Core *net, const Broadcast_Info *broadc
return res;
}
-Broadcast_Info *lan_discovery_init(const Network *ns)
+Broadcast_Info *lan_discovery_init(const Memory *mem, const Network *ns)
{
- return fetch_broadcast_info(ns);
+ return fetch_broadcast_info(mem, ns);
}
void lan_discovery_kill(Broadcast_Info *broadcast)
{
- free(broadcast);
+ if (broadcast == nullptr) {
+ return;
+ }
+
+ mem_delete(broadcast->mem, broadcast);
}
diff --git a/protocols/Tox/libtox/src/toxcore/LAN_discovery.h b/protocols/Tox/libtox/src/toxcore/LAN_discovery.h
index 94e5d3581c..c18ce9e562 100644
--- a/protocols/Tox/libtox/src/toxcore/LAN_discovery.h
+++ b/protocols/Tox/libtox/src/toxcore/LAN_discovery.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -10,6 +10,7 @@
#define C_TOXCORE_TOXCORE_LAN_DISCOVERY_H
#include "attributes.h"
+#include "mem.h"
#include "network.h"
/**
@@ -32,7 +33,7 @@ bool lan_discovery_send(const Networking_Core *net, const Broadcast_Info *broadc
* Discovers broadcast devices and IP addresses.
*/
non_null()
-Broadcast_Info *lan_discovery_init(const Network *ns);
+Broadcast_Info *lan_discovery_init(const Memory *mem, const Network *ns);
/**
* Free all resources associated with the broadcast info.
diff --git a/protocols/Tox/libtox/src/toxcore/Makefile.inc b/protocols/Tox/libtox/src/toxcore/Makefile.inc
new file mode 100644
index 0000000000..de9227b6d0
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/Makefile.inc
@@ -0,0 +1,179 @@
+lib_LTLIBRARIES += libtoxcore.la
+
+libtoxcore_la_include_HEADERS = \
+ ../toxcore/tox.h \
+ ../toxcore/tox_options.h
+
+libtoxcore_la_includedir = $(includedir)/tox
+
+libtoxcore_la_SOURCES = ../third_party/cmp/cmp.c \
+ ../third_party/cmp/cmp.h \
+ ../toxcore/events/conference_connected.c \
+ ../toxcore/events/conference_invite.c \
+ ../toxcore/events/conference_message.c \
+ ../toxcore/events/conference_peer_list_changed.c \
+ ../toxcore/events/conference_peer_name.c \
+ ../toxcore/events/conference_title.c \
+ ../toxcore/events/dht_nodes_response.c \
+ ../toxcore/events/events_alloc.c \
+ ../toxcore/events/events_alloc.h \
+ ../toxcore/events/file_chunk_request.c \
+ ../toxcore/events/file_recv.c \
+ ../toxcore/events/file_recv_chunk.c \
+ ../toxcore/events/file_recv_control.c \
+ ../toxcore/events/friend_connection_status.c \
+ ../toxcore/events/friend_lossless_packet.c \
+ ../toxcore/events/friend_lossy_packet.c \
+ ../toxcore/events/friend_message.c \
+ ../toxcore/events/friend_name.c \
+ ../toxcore/events/friend_read_receipt.c \
+ ../toxcore/events/friend_request.c \
+ ../toxcore/events/friend_status.c \
+ ../toxcore/events/friend_status_message.c \
+ ../toxcore/events/friend_typing.c \
+ ../toxcore/events/self_connection_status.c \
+ ../toxcore/events/group_custom_packet.c \
+ ../toxcore/events/group_custom_private_packet.c \
+ ../toxcore/events/group_invite.c \
+ ../toxcore/events/group_join_fail.c \
+ ../toxcore/events/group_message.c \
+ ../toxcore/events/group_moderation.c \
+ ../toxcore/events/group_password.c \
+ ../toxcore/events/group_peer_exit.c \
+ ../toxcore/events/group_peer_join.c \
+ ../toxcore/events/group_peer_limit.c \
+ ../toxcore/events/group_peer_name.c \
+ ../toxcore/events/group_peer_status.c \
+ ../toxcore/events/group_privacy_state.c \
+ ../toxcore/events/group_private_message.c \
+ ../toxcore/events/group_self_join.c \
+ ../toxcore/events/group_topic.c \
+ ../toxcore/events/group_topic_lock.c \
+ ../toxcore/events/group_voice_state.c \
+ ../toxcore/announce.c \
+ ../toxcore/announce.h \
+ ../toxcore/attributes.h \
+ ../toxcore/bin_pack.c \
+ ../toxcore/bin_pack.h \
+ ../toxcore/bin_unpack.c \
+ ../toxcore/bin_unpack.h \
+ ../toxcore/ccompat.c \
+ ../toxcore/ccompat.h \
+ ../toxcore/crypto_core_pack.c \
+ ../toxcore/crypto_core_pack.h \
+ ../toxcore/crypto_core.c \
+ ../toxcore/crypto_core.h \
+ ../toxcore/DHT.c \
+ ../toxcore/DHT.h \
+ ../toxcore/forwarding.c \
+ ../toxcore/forwarding.h \
+ ../toxcore/friend_connection.c \
+ ../toxcore/friend_connection.h \
+ ../toxcore/friend_requests.c \
+ ../toxcore/friend_requests.h \
+ ../toxcore/group_announce.c \
+ ../toxcore/group_announce.h \
+ ../toxcore/group_chats.c \
+ ../toxcore/group_chats.h \
+ ../toxcore/group_common.h \
+ ../toxcore/group_connection.c \
+ ../toxcore/group_connection.h \
+ ../toxcore/group_moderation.c \
+ ../toxcore/group_moderation.h \
+ ../toxcore/group_onion_announce.c \
+ ../toxcore/group_onion_announce.h \
+ ../toxcore/group_pack.c \
+ ../toxcore/group_pack.h \
+ ../toxcore/group.c \
+ ../toxcore/group.h \
+ ../toxcore/LAN_discovery.c \
+ ../toxcore/LAN_discovery.h \
+ ../toxcore/list.c \
+ ../toxcore/list.h \
+ ../toxcore/logger.c \
+ ../toxcore/logger.h \
+ ../toxcore/mem.c \
+ ../toxcore/mem.h \
+ ../toxcore/Messenger.c \
+ ../toxcore/Messenger.h \
+ ../toxcore/mono_time.c \
+ ../toxcore/mono_time.h \
+ ../toxcore/net_crypto.c \
+ ../toxcore/net_crypto.h \
+ ../toxcore/net_profile.c \
+ ../toxcore/net_profile.h \
+ ../toxcore/network.c \
+ ../toxcore/network.h \
+ ../toxcore/onion_announce.c \
+ ../toxcore/onion_announce.h \
+ ../toxcore/onion_client.c \
+ ../toxcore/onion_client.h \
+ ../toxcore/onion.c \
+ ../toxcore/onion.h \
+ ../toxcore/ping_array.c \
+ ../toxcore/ping_array.h \
+ ../toxcore/ping.c \
+ ../toxcore/ping.h \
+ ../toxcore/shared_key_cache.c \
+ ../toxcore/shared_key_cache.h \
+ ../toxcore/sort.c \
+ ../toxcore/sort.h \
+ ../toxcore/state.c \
+ ../toxcore/state.h \
+ ../toxcore/TCP_client.c \
+ ../toxcore/TCP_client.h \
+ ../toxcore/TCP_common.c \
+ ../toxcore/TCP_common.h \
+ ../toxcore/TCP_connection.c \
+ ../toxcore/TCP_connection.h \
+ ../toxcore/TCP_server.c \
+ ../toxcore/TCP_server.h \
+ ../toxcore/timed_auth.c \
+ ../toxcore/timed_auth.h \
+ ../toxcore/tox_api.c \
+ ../toxcore/tox_dispatch.c \
+ ../toxcore/tox_dispatch.h \
+ ../toxcore/tox_event.c \
+ ../toxcore/tox_event.h \
+ ../toxcore/tox_events.c \
+ ../toxcore/tox_events.h \
+ ../toxcore/tox_log_level.c \
+ ../toxcore/tox_log_level.h \
+ ../toxcore/tox_options.c \
+ ../toxcore/tox_options.h \
+ ../toxcore/tox_pack.c \
+ ../toxcore/tox_pack.h \
+ ../toxcore/tox_private.c \
+ ../toxcore/tox_private.h \
+ ../toxcore/tox_struct.h \
+ ../toxcore/tox_unpack.c \
+ ../toxcore/tox_unpack.h \
+ ../toxcore/tox.c \
+ ../toxcore/tox.h \
+ ../toxcore/util.c \
+ ../toxcore/util.h
+
+libtoxcore_la_CFLAGS = -I$(top_srcdir) \
+ -I$(top_srcdir)/toxcore \
+ $(LIBSODIUM_CFLAGS) \
+ $(MSGPACK_CFLAGS) \
+ $(PTHREAD_CFLAGS) \
+ -DCMP_NO_FLOAT=1
+
+libtoxcore_la_LDFLAGS = $(LT_LDFLAGS) \
+ $(EXTRA_LT_LDFLAGS) \
+ $(LIBSODIUM_LDFLAGS) \
+ $(MSGPACK_LDFLAGS) \
+ $(MATH_LDFLAGS) \
+ $(RT_LIBS) \
+ $(WINSOCK2_LIBS)
+
+libtoxcore_la_LIBADD = $(LIBSODIUM_LIBS) \
+ $(MSGPACK_LIBS) \
+ $(PTHREAD_LIBS)
+
+if SET_SO_VERSION
+
+EXTRA_libtoxcore_la_DEPENDENCIES = ../so.version
+
+endif
diff --git a/protocols/Tox/libtox/src/toxcore/Messenger.c b/protocols/Tox/libtox/src/toxcore/Messenger.c
index 947edef7e1..2d25abda56 100644
--- a/protocols/Tox/libtox/src/toxcore/Messenger.c
+++ b/protocols/Tox/libtox/src/toxcore/Messenger.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -34,6 +34,7 @@
#include "mem.h"
#include "mono_time.h"
#include "net_crypto.h"
+#include "net_profile.h"
#include "network.h"
#include "onion.h"
#include "onion_announce.h"
@@ -137,7 +138,7 @@ void getaddress(const Messenger *m, uint8_t *address)
}
non_null()
-static bool send_online_packet(Messenger *m, int friendcon_id)
+static bool send_online_packet(const Messenger *m, int friendcon_id)
{
const uint8_t packet[1] = {PACKET_ID_ONLINE};
return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, friendcon_id), packet,
@@ -145,7 +146,7 @@ static bool send_online_packet(Messenger *m, int friendcon_id)
}
non_null()
-static bool send_offline_packet(Messenger *m, int friendcon_id)
+static bool send_offline_packet(const Messenger *m, int friendcon_id)
{
const uint8_t packet[1] = {PACKET_ID_OFFLINE};
return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, friendcon_id), packet,
@@ -472,10 +473,6 @@ int m_delfriend(Messenger *m, int32_t friendnumber)
return -1;
}
- if (m->friend_connectionstatuschange_internal != nullptr) {
- m->friend_connectionstatuschange_internal(m, friendnumber, false, m->friend_connectionstatuschange_internal_userdata);
- }
-
clear_receipts(m, friendnumber);
remove_request_received(m->fr, m->friendlist[friendnumber].real_pk);
friend_connection_callbacks(m->fr_c, m->friendlist[friendnumber].friendcon_id, MESSENGER_CALLBACK_INDEX, nullptr,
@@ -775,31 +772,31 @@ int m_set_statusmessage(Messenger *m, const uint8_t *status, uint16_t length)
}
non_null()
-static bool userstatus_from_int(uint8_t status, Userstatus *out)
+static bool userstatus_from_int(uint8_t status, Userstatus *out_enum)
{
switch (status) {
case USERSTATUS_NONE: {
- *out = USERSTATUS_NONE;
+ *out_enum = USERSTATUS_NONE;
return true;
}
case USERSTATUS_AWAY: {
- *out = USERSTATUS_AWAY;
+ *out_enum = USERSTATUS_AWAY;
return true;
}
case USERSTATUS_BUSY: {
- *out = USERSTATUS_BUSY;
+ *out_enum = USERSTATUS_BUSY;
return true;
}
case USERSTATUS_INVALID: {
- *out = USERSTATUS_INVALID;
+ *out_enum = USERSTATUS_INVALID;
return true;
}
default: {
- *out = USERSTATUS_INVALID;
+ *out_enum = USERSTATUS_INVALID;
return false;
}
}
@@ -1027,13 +1024,6 @@ void m_callback_core_connection(Messenger *m, m_self_connection_status_cb *funct
m->core_connection_change = function;
}
-void m_callback_connectionstatus_internal_av(Messenger *m, m_friend_connectionstatuschange_internal_cb *function,
- void *userdata)
-{
- m->friend_connectionstatuschange_internal = function;
- m->friend_connectionstatuschange_internal_userdata = userdata;
-}
-
non_null(1) nullable(3)
static void check_friend_tcp_udp(Messenger *m, int32_t friendnumber, void *userdata)
{
@@ -1081,11 +1071,6 @@ static void check_friend_connectionstatus(Messenger *m, int32_t friendnumber, ui
m->friendlist[friendnumber].status = status;
check_friend_tcp_udp(m, friendnumber, userdata);
-
- if (m->friend_connectionstatuschange_internal != nullptr) {
- m->friend_connectionstatuschange_internal(m, friendnumber, is_online,
- m->friend_connectionstatuschange_internal_userdata);
- }
}
}
@@ -1855,23 +1840,6 @@ static int handle_filecontrol(Messenger *m, int32_t friendnumber, bool outbound,
}
}
-/** @brief Set the callback for msi packets. */
-void m_callback_msi_packet(Messenger *m, m_msi_packet_cb *function, void *userdata)
-{
- m->msi_packet = function;
- m->msi_packet_userdata = userdata;
-}
-
-/** @brief Send an msi packet.
- *
- * @retval true on success
- * @retval false on failure
- */
-bool m_msi_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length)
-{
- return write_cryptpacket_id(m, friendnumber, PACKET_ID_MSI, data, length, false);
-}
-
static int m_handle_lossy_packet(void *object, int friendcon_id, const uint8_t *data, uint16_t length,
void *userdata)
{
@@ -1881,17 +1849,6 @@ static int m_handle_lossy_packet(void *object, int friendcon_id, const uint8_t *
return 1;
}
- if (data[0] <= PACKET_ID_RANGE_LOSSY_AV_END) {
- const RTP_Packet_Handler *const ph =
- &m->friendlist[friendcon_id].lossy_rtp_packethandlers[data[0] % PACKET_ID_RANGE_LOSSY_AV_SIZE];
-
- if (ph->function != nullptr) {
- return ph->function(m, friendcon_id, data, length, ph->object);
- }
-
- return 1;
- }
-
if (m->lossy_packethandler != nullptr) {
m->lossy_packethandler(m, friendcon_id, data[0], data, length, userdata);
}
@@ -1904,38 +1861,6 @@ void custom_lossy_packet_registerhandler(Messenger *m, m_friend_lossy_packet_cb
m->lossy_packethandler = lossy_packethandler;
}
-int m_callback_rtp_packet(Messenger *m, int32_t friendnumber, uint8_t byte, m_lossy_rtp_packet_cb *function,
- void *object)
-{
- if (!m_friend_exists(m, friendnumber)) {
- return -1;
- }
-
- if (byte < PACKET_ID_RANGE_LOSSY_AV_START || byte > PACKET_ID_RANGE_LOSSY_AV_END) {
- return -1;
- }
-
- m->friendlist[friendnumber].lossy_rtp_packethandlers[byte % PACKET_ID_RANGE_LOSSY_AV_SIZE].function = function;
- m->friendlist[friendnumber].lossy_rtp_packethandlers[byte % PACKET_ID_RANGE_LOSSY_AV_SIZE].object = object;
- return 0;
-}
-
-/** @brief High level function to send custom lossy packets.
- *
- * TODO(oxij): this name is confusing, because this function sends both av and custom lossy packets.
- * Meanwhile, m_handle_lossy_packet routes custom packets to custom_lossy_packet_registerhandler
- * as you would expect from its name.
- *
- * I.e. custom_lossy_packet_registerhandler's "custom lossy packet" and this "custom lossy packet"
- * are not the same set of packets.
- *
- * @retval -1 if friend invalid.
- * @retval -2 if length wrong.
- * @retval -3 if first byte invalid.
- * @retval -4 if friend offline.
- * @retval -5 if packet failed to send because of other error.
- * @retval 0 on success.
- */
int m_send_custom_lossy_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length)
{
if (!m_friend_exists(m, friendnumber)) {
@@ -1946,7 +1871,6 @@ int m_send_custom_lossy_packet(const Messenger *m, int32_t friendnumber, const u
return -2;
}
- // TODO(oxij): send_lossy_cryptpacket makes this check already, similarly for other similar places
if (data[0] < PACKET_ID_RANGE_LOSSY_START || data[0] > PACKET_ID_RANGE_LOSSY_END) {
return -3;
}
@@ -1974,7 +1898,10 @@ static int handle_custom_lossless_packet(void *object, int friend_num, const uin
}
if (packet[0] < PACKET_ID_RANGE_LOSSLESS_CUSTOM_START || packet[0] > PACKET_ID_RANGE_LOSSLESS_CUSTOM_END) {
- return -1;
+ // allow PACKET_ID_MSI packets to be handled by custom packet handler
+ if (packet[0] != PACKET_ID_MSI) {
+ return -1;
+ }
}
if (m->lossless_packethandler != nullptr) {
@@ -2357,20 +2284,6 @@ static int m_handle_packet_file_data(Messenger *m, const int friendcon_id, const
}
non_null(1, 3) nullable(5)
-static int m_handle_packet_msi(Messenger *m, const int friendcon_id, const uint8_t *data, const uint16_t data_length, void *userdata)
-{
- if (data_length == 0) {
- return 0;
- }
-
- if (m->msi_packet != nullptr) {
- m->msi_packet(m, friendcon_id, data, data_length, m->msi_packet_userdata);
- }
-
- return 0;
-}
-
-non_null(1, 3) nullable(5)
static int m_handle_packet_invite_groupchat(Messenger *m, const int friendcon_id, const uint8_t *data, const uint16_t data_length, void *userdata)
{
// first two bytes are messenger packet type and group invite type
@@ -2443,7 +2356,7 @@ static int m_handle_packet(void *object, int friendcon_id, const uint8_t *data,
case PACKET_ID_FILE_DATA:
return m_handle_packet_file_data(m, friendcon_id, payload, payload_length, userdata);
case PACKET_ID_MSI:
- return m_handle_packet_msi(m, friendcon_id, payload, payload_length, userdata);
+ return handle_custom_lossless_packet(object, friendcon_id, data, length, userdata);
case PACKET_ID_INVITE_GROUPCHAT:
return m_handle_packet_invite_groupchat(m, friendcon_id, payload, payload_length, userdata);
}
@@ -2468,14 +2381,12 @@ static void do_friends(Messenger *m, void *userdata)
}
}
- if (m->friendlist[i].status == FRIEND_REQUESTED
- || m->friendlist[i].status == FRIEND_CONFIRMED) { /* friend is not online. */
- if (m->friendlist[i].status == FRIEND_REQUESTED) {
- /* If we didn't connect to friend after successfully sending him a friend request the request is deemed
- * unsuccessful so we set the status back to FRIEND_ADDED and try again.
- */
- check_friend_request_timed_out(m, i, temp_time, userdata);
- }
+ if (m->friendlist[i].status == FRIEND_REQUESTED) {
+ /* If we didn't connect to friend after successfully sending him a friend
+ * request the request is deemed unsuccessful so we set the status back to
+ * FRIEND_ADDED and try again.
+ */
+ check_friend_request_timed_out(m, i, temp_time, userdata);
}
if (m->friendlist[i].status == FRIEND_ONLINE) { /* friend is online. */
@@ -2605,7 +2516,7 @@ static bool self_announce_group(const Messenger *m, GC_Chat *chat, Onion_Friend
return false;
}
- if (gca_add_announce(m->mono_time, m->group_announce, &announce) == nullptr) {
+ if (gca_add_announce(m->mem, m->mono_time, m->group_announce, &announce) == nullptr) {
onion_friend_set_gc_data(onion_friend, nullptr, 0);
return false;
}
@@ -3261,7 +3172,7 @@ static bool handle_groups_load(void *obj, Bin_Unpack *bu)
non_null()
static State_Load_Status groups_load(Messenger *m, const uint8_t *data, uint32_t length)
{
- if (!bin_unpack_obj(handle_groups_load, m, data, length)) {
+ if (!bin_unpack_obj(m->mem, handle_groups_load, m, data, length)) {
LOGGER_ERROR(m->log, "msgpack failed to unpack groupchats array");
return STATE_LOAD_STATUS_ERROR;
}
@@ -3565,14 +3476,14 @@ Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random *
m->rng = rng;
m->ns = ns;
- m->fr = friendreq_new();
+ m->fr = friendreq_new(mem);
if (m->fr == nullptr) {
mem_delete(mem, m);
return nullptr;
}
- m->log = logger_new();
+ m->log = logger_new(mem);
if (m->log == nullptr) {
friendreq_kill(m->fr);
@@ -3621,11 +3532,24 @@ Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random *
return nullptr;
}
- m->net_crypto = new_net_crypto(m->log, m->mem, m->rng, m->ns, m->mono_time, m->dht, &options->proxy_info);
+ m->tcp_np = netprof_new(m->log, mem);
+
+ if (m->tcp_np == nullptr) {
+ LOGGER_WARNING(m->log, "TCP netprof initialisation failed");
+ kill_dht(m->dht);
+ kill_networking(m->net);
+ friendreq_kill(m->fr);
+ logger_kill(m->log);
+ mem_delete(mem, m);
+ return nullptr;
+ }
+
+ m->net_crypto = new_net_crypto(m->log, m->mem, m->rng, m->ns, m->mono_time, m->dht, &options->proxy_info, m->tcp_np);
if (m->net_crypto == nullptr) {
LOGGER_WARNING(m->log, "net_crypto initialisation failed");
+ netprof_kill(mem, m->tcp_np);
kill_dht(m->dht);
kill_networking(m->net);
friendreq_kill(m->fr);
@@ -3634,12 +3558,13 @@ Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random *
return nullptr;
}
- m->group_announce = new_gca_list();
+ m->group_announce = new_gca_list(m->mem);
if (m->group_announce == nullptr) {
LOGGER_WARNING(m->log, "DHT group chats initialisation failed");
kill_net_crypto(m->net_crypto);
+ netprof_kill(mem, m->tcp_np);
kill_dht(m->dht);
kill_networking(m->net);
friendreq_kill(m->fr);
@@ -3649,7 +3574,7 @@ Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random *
}
if (options->dht_announcements_enabled) {
- m->forwarding = new_forwarding(m->log, m->rng, m->mono_time, m->dht);
+ m->forwarding = new_forwarding(m->log, m->mem, m->rng, m->mono_time, m->dht);
if (m->forwarding != nullptr) {
m->announce = new_announcements(m->log, m->mem, m->rng, m->mono_time, m->forwarding);
} else {
@@ -3664,7 +3589,7 @@ Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random *
m->onion_a = new_onion_announce(m->log, m->mem, m->rng, m->mono_time, m->dht);
m->onion_c = new_onion_client(m->log, m->mem, m->rng, m->mono_time, m->net_crypto);
if (m->onion_c != nullptr) {
- m->fr_c = new_friend_connections(m->log, m->mono_time, m->ns, m->onion_c, options->local_discovery_enabled);
+ m->fr_c = new_friend_connections(m->log, m->mem, m->mono_time, m->ns, m->onion_c, options->local_discovery_enabled);
}
if ((options->dht_announcements_enabled && (m->forwarding == nullptr || m->announce == nullptr)) ||
@@ -3679,6 +3604,7 @@ Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random *
kill_announcements(m->announce);
kill_forwarding(m->forwarding);
kill_net_crypto(m->net_crypto);
+ netprof_kill(mem, m->tcp_np);
kill_dht(m->dht);
kill_networking(m->net);
friendreq_kill(m->fr);
@@ -3702,6 +3628,7 @@ Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random *
kill_announcements(m->announce);
kill_forwarding(m->forwarding);
kill_net_crypto(m->net_crypto);
+ netprof_kill(mem, m->tcp_np);
kill_dht(m->dht);
kill_networking(m->net);
friendreq_kill(m->fr);
@@ -3727,6 +3654,7 @@ Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random *
kill_announcements(m->announce);
kill_forwarding(m->forwarding);
kill_net_crypto(m->net_crypto);
+ netprof_kill(mem, m->tcp_np);
kill_dht(m->dht);
kill_networking(m->net);
friendreq_kill(m->fr);
@@ -3782,6 +3710,7 @@ void kill_messenger(Messenger *m)
kill_announcements(m->announce);
kill_forwarding(m->forwarding);
kill_net_crypto(m->net_crypto);
+ netprof_kill(m->mem, m->tcp_np);
kill_dht(m->dht);
kill_networking(m->net);
diff --git a/protocols/Tox/libtox/src/toxcore/Messenger.h b/protocols/Tox/libtox/src/toxcore/Messenger.h
index cace3340b2..1286ddf138 100644
--- a/protocols/Tox/libtox/src/toxcore/Messenger.h
+++ b/protocols/Tox/libtox/src/toxcore/Messenger.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -25,6 +25,7 @@
#include "mem.h"
#include "mono_time.h"
#include "net_crypto.h"
+#include "net_profile.h"
#include "network.h"
#include "onion.h"
#include "onion_announce.h"
@@ -86,6 +87,8 @@ typedef struct Messenger_Options {
Messenger_State_Plugin *state_plugins;
uint8_t state_plugins_length;
+
+ bool dns_enabled;
} Messenger_Options;
struct Receipts {
@@ -200,20 +203,10 @@ typedef void m_friend_lossy_packet_cb(Messenger *m, uint32_t friend_number, uint
size_t length, void *user_data);
typedef void m_friend_lossless_packet_cb(Messenger *m, uint32_t friend_number, uint8_t packet_id, const uint8_t *data,
size_t length, void *user_data);
-typedef void m_friend_connectionstatuschange_internal_cb(Messenger *m, uint32_t friend_number,
- bool is_online, void *user_data);
typedef void m_conference_invite_cb(Messenger *m, uint32_t friend_number, const uint8_t *cookie, uint16_t length,
void *user_data);
typedef void m_group_invite_cb(const Messenger *m, uint32_t friend_number, const uint8_t *invite_data, size_t length,
const uint8_t *group_name, size_t group_name_length, void *user_data);
-typedef void m_msi_packet_cb(Messenger *m, uint32_t friend_number, const uint8_t *data, uint16_t length,
- void *user_data);
-typedef int m_lossy_rtp_packet_cb(Messenger *m, uint32_t friend_number, const uint8_t *data, uint16_t length, void *object);
-
-typedef struct RTP_Packet_Handler {
- m_lossy_rtp_packet_cb *function;
- void *object;
-} RTP_Packet_Handler;
typedef struct Friend {
uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
@@ -243,8 +236,6 @@ typedef struct Friend {
uint32_t num_sending_files;
struct File_Transfers file_receiving[MAX_CONCURRENT_FILE_PIPES];
- RTP_Packet_Handler lossy_rtp_packethandlers[PACKET_ID_RANGE_LOSSY_AV_SIZE];
-
struct Receipts *receipts_start;
struct Receipts *receipts_end;
} Friend;
@@ -258,6 +249,7 @@ struct Messenger {
Networking_Core *net;
Net_Crypto *net_crypto;
+ Net_Profile *tcp_np;
DHT *dht;
Forwarding *forwarding;
@@ -301,8 +293,6 @@ struct Messenger {
m_friend_typing_cb *friend_typingchange;
m_friend_read_receipt_cb *read_receipt;
m_friend_connection_status_cb *friend_connectionstatuschange;
- m_friend_connectionstatuschange_internal_cb *friend_connectionstatuschange_internal;
- void *friend_connectionstatuschange_internal_userdata;
struct Group_Chats *conferences_object;
m_conference_invite_cb *conference_invite;
@@ -314,9 +304,6 @@ struct Messenger {
m_file_recv_chunk_cb *file_filedata;
m_file_chunk_request_cb *file_reqchunk;
- m_msi_packet_cb *msi_packet;
- void *msi_packet_userdata;
-
m_friend_lossy_packet_cb *lossy_packethandler;
m_friend_lossless_packet_cb *lossless_packethandler;
@@ -614,10 +601,6 @@ non_null() void m_callback_read_receipt(Messenger *m, m_friend_read_receipt_cb *
*/
non_null() void m_callback_connectionstatus(Messenger *m, m_friend_connection_status_cb *function);
-/** Same as previous but for internal A/V core usage only */
-non_null() void m_callback_connectionstatus_internal_av(
- Messenger *m, m_friend_connectionstatuschange_internal_cb *function, void *userdata);
-
/** @brief Set the callback for typing changes. */
non_null() void m_callback_core_connection(Messenger *m, m_self_connection_status_cb *function);
@@ -731,29 +714,6 @@ non_null(1) nullable(5)
int send_file_data(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint64_t position,
const uint8_t *data, uint16_t length);
-/*** A/V related */
-
-/** @brief Set the callback for msi packets. */
-non_null(1) nullable(2, 3)
-void m_callback_msi_packet(Messenger *m, m_msi_packet_cb *function, void *userdata);
-
-/** @brief Send an msi packet.
- *
- * @retval true on success
- * @retval false on failure
- */
-non_null()
-bool m_msi_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length);
-
-/** @brief Set handlers for lossy rtp packets.
- *
- * @retval -1 on failure.
- * @retval 0 on success.
- */
-non_null(1) nullable(4, 5)
-int m_callback_rtp_packet(Messenger *m, int32_t friendnumber, uint8_t byte,
- m_lossy_rtp_packet_cb *function, void *object);
-
/*** CUSTOM PACKETS */
/** @brief Set handlers for custom lossy packets. */
@@ -761,13 +721,6 @@ non_null() void custom_lossy_packet_registerhandler(Messenger *m, m_friend_lossy
/** @brief High level function to send custom lossy packets.
*
- * TODO(oxij): this name is confusing, because this function sends both av and custom lossy packets.
- * Meanwhile, m_handle_lossy_packet routes custom packets to custom_lossy_packet_registerhandler
- * as you would expect from its name.
- *
- * I.e. custom_lossy_packet_registerhandler's "custom lossy packet" and this "custom lossy packet"
- * are not the same set of packets.
- *
* @retval -1 if friend invalid.
* @retval -2 if length wrong.
* @retval -3 if first byte invalid.
diff --git a/protocols/Tox/libtox/src/toxcore/TCP_client.c b/protocols/Tox/libtox/src/toxcore/TCP_client.c
index 2b8c6e448f..1982412cda 100644
--- a/protocols/Tox/libtox/src/toxcore/TCP_client.c
+++ b/protocols/Tox/libtox/src/toxcore/TCP_client.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2014 Tox project.
*/
@@ -20,6 +20,7 @@
#include "logger.h"
#include "mem.h"
#include "mono_time.h"
+#include "net_profile.h"
#include "network.h"
#include "util.h"
@@ -107,13 +108,25 @@ void tcp_con_set_custom_uint(TCP_Client_Connection *con, uint32_t value)
* @retval false on failure
*/
non_null()
-static bool connect_sock_to(const Logger *logger, const Memory *mem, Socket sock, const IP_Port *ip_port, const TCP_Proxy_Info *proxy_info)
+static bool connect_sock_to(const Network *ns, const Logger *logger, const Memory *mem, Socket sock, const IP_Port *ip_port, const TCP_Proxy_Info *proxy_info)
{
+ Net_Err_Connect err;
if (proxy_info->proxy_type != TCP_PROXY_NONE) {
- return net_connect(mem, logger, sock, &proxy_info->ip_port);
+ net_connect(ns, mem, logger, sock, &proxy_info->ip_port, &err);
} else {
- return net_connect(mem, logger, sock, ip_port);
+ net_connect(ns, mem, logger, sock, ip_port, &err);
}
+ switch (err) {
+ case NET_ERR_CONNECT_OK:
+ case NET_ERR_CONNECT_FAILED: {
+ /* nonblocking socket, connect will never return success */
+ return true;
+ }
+ case NET_ERR_CONNECT_INVALID_FAMILY:
+ return false;
+ }
+ LOGGER_ERROR(logger, "unexpected error code %s from net_connect", net_err_connect_to_string(err));
+ return false;
}
/**
@@ -312,7 +325,7 @@ static int generate_handshake(TCP_Client_Connection *tcp_conn)
memcpy(plain + CRYPTO_PUBLIC_KEY_SIZE, tcp_conn->con.sent_nonce, CRYPTO_NONCE_SIZE);
memcpy(tcp_conn->con.last_packet, tcp_conn->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
random_nonce(tcp_conn->con.rng, tcp_conn->con.last_packet + CRYPTO_PUBLIC_KEY_SIZE);
- const int len = encrypt_data_symmetric(tcp_conn->con.shared_key, tcp_conn->con.last_packet + CRYPTO_PUBLIC_KEY_SIZE, plain,
+ const int len = encrypt_data_symmetric(tcp_conn->con.mem, tcp_conn->con.shared_key, tcp_conn->con.last_packet + CRYPTO_PUBLIC_KEY_SIZE, plain,
sizeof(plain), tcp_conn->con.last_packet + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
if (len != sizeof(plain) + CRYPTO_MAC_SIZE) {
@@ -334,7 +347,7 @@ non_null()
static int handle_handshake(TCP_Client_Connection *tcp_conn, const uint8_t *data)
{
uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE];
- const int len = decrypt_data_symmetric(tcp_conn->con.shared_key, data, data + CRYPTO_NONCE_SIZE,
+ const int len = decrypt_data_symmetric(tcp_conn->con.mem, tcp_conn->con.shared_key, data, data + CRYPTO_NONCE_SIZE,
TCP_SERVER_HANDSHAKE_SIZE - CRYPTO_NONCE_SIZE, plain);
if (len != sizeof(plain)) {
@@ -582,7 +595,7 @@ void forwarding_handler(TCP_Client_Connection *con, forwarded_response_cb *forwa
TCP_Client_Connection *new_tcp_connection(
const Logger *logger, const Memory *mem, const Mono_Time *mono_time, const Random *rng, const Network *ns,
const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *self_public_key, const uint8_t *self_secret_key,
- const TCP_Proxy_Info *proxy_info)
+ const TCP_Proxy_Info *proxy_info, Net_Profile *net_profile)
{
assert(logger != nullptr);
assert(mem != nullptr);
@@ -591,6 +604,7 @@ TCP_Client_Connection *new_tcp_connection(
assert(ns != nullptr);
if (!net_family_is_ipv4(ip_port->ip.family) && !net_family_is_ipv6(ip_port->ip.family)) {
+ LOGGER_ERROR(logger, "Invalid IP family: %d", ip_port->ip.family.value);
return nullptr;
}
@@ -609,15 +623,26 @@ TCP_Client_Connection *new_tcp_connection(
const Socket sock = net_socket(ns, family, TOX_SOCK_STREAM, TOX_PROTO_TCP);
if (!sock_valid(sock)) {
+ LOGGER_ERROR(logger, "Failed to create TCP socket with family %d", family.value);
return nullptr;
}
if (!set_socket_nosigpipe(ns, sock)) {
+ LOGGER_ERROR(logger, "Failed to set TCP socket to ignore SIGPIPE");
kill_sock(ns, sock);
return nullptr;
}
- if (!(set_socket_nonblock(ns, sock) && connect_sock_to(logger, mem, sock, ip_port, proxy_info))) {
+ if (!set_socket_nonblock(ns, sock)) {
+ LOGGER_ERROR(logger, "Failed to set TCP socket to non-blocking");
+ kill_sock(ns, sock);
+ return nullptr;
+ }
+
+ if (!connect_sock_to(ns, logger, mem, sock, ip_port, proxy_info)) {
+ Ip_Ntoa ip_ntoa;
+ LOGGER_WARNING(logger, "Failed to connect TCP socket to %s:%u",
+ net_ip_ntoa(&ip_port->ip, &ip_ntoa), net_ntohs(ip_port->port));
kill_sock(ns, sock);
return nullptr;
}
@@ -625,6 +650,7 @@ TCP_Client_Connection *new_tcp_connection(
TCP_Client_Connection *temp = (TCP_Client_Connection *)mem_alloc(mem, sizeof(TCP_Client_Connection));
if (temp == nullptr) {
+ LOGGER_ERROR(logger, "Failed to allocate memory for TCP_Client_Connection");
kill_sock(ns, sock);
return nullptr;
}
@@ -634,6 +660,7 @@ TCP_Client_Connection *new_tcp_connection(
temp->con.rng = rng;
temp->con.sock = sock;
temp->con.ip_port = *ip_port;
+ temp->con.net_profile = net_profile;
memcpy(temp->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
memcpy(temp->self_public_key, self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
encrypt_precompute(temp->public_key, self_secret_key, temp->con.shared_key);
@@ -657,6 +684,7 @@ TCP_Client_Connection *new_tcp_connection(
temp->status = TCP_CLIENT_CONNECTING;
if (generate_handshake(temp) == -1) {
+ LOGGER_ERROR(logger, "Failed to generate handshake");
kill_sock(ns, sock);
mem_delete(mem, temp);
return nullptr;
@@ -819,6 +847,8 @@ static int handle_tcp_client_packet(const Logger *logger, TCP_Client_Connection
return -1;
}
+ netprof_record_packet(conn->con.net_profile, data[0], length, PACKET_DIRECTION_RECV);
+
switch (data[0]) {
case TCP_PACKET_ROUTING_RESPONSE:
return handle_tcp_client_routing_response(conn, data, length);
diff --git a/protocols/Tox/libtox/src/toxcore/TCP_client.h b/protocols/Tox/libtox/src/toxcore/TCP_client.h
index ea2654b953..3ed6e8c683 100644
--- a/protocols/Tox/libtox/src/toxcore/TCP_client.h
+++ b/protocols/Tox/libtox/src/toxcore/TCP_client.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2014 Tox project.
*/
@@ -15,6 +15,7 @@
#include "logger.h"
#include "mem.h"
#include "mono_time.h"
+#include "net_profile.h"
#include "network.h"
#define TCP_CONNECTION_TIMEOUT 10
@@ -60,11 +61,11 @@ non_null()
void tcp_con_set_custom_uint(TCP_Client_Connection *con, uint32_t value);
/** Create new TCP connection to ip_port/public_key */
-non_null(1, 2, 3, 4, 5, 6, 7, 8, 9) nullable(10)
+non_null(1, 2, 3, 4, 5, 6, 7, 8, 9) nullable(10, 11)
TCP_Client_Connection *new_tcp_connection(
const Logger *logger, const Memory *mem, const Mono_Time *mono_time, const Random *rng, const Network *ns,
const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *self_public_key, const uint8_t *self_secret_key,
- const TCP_Proxy_Info *proxy_info);
+ const TCP_Proxy_Info *proxy_info, Net_Profile *net_profile);
/** Run the TCP connection */
non_null(1, 2, 3) nullable(4)
diff --git a/protocols/Tox/libtox/src/toxcore/TCP_common.c b/protocols/Tox/libtox/src/toxcore/TCP_common.c
index bd3b7ca4c7..1a8a5d9731 100644
--- a/protocols/Tox/libtox/src/toxcore/TCP_common.c
+++ b/protocols/Tox/libtox/src/toxcore/TCP_common.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2014 Tox project.
*/
@@ -35,7 +35,8 @@ int send_pending_data_nonpriority(const Logger *logger, TCP_Connection *con)
}
const uint16_t left = con->last_packet_length - con->last_packet_sent;
- const int len = net_send(con->ns, logger, con->sock, con->last_packet + con->last_packet_sent, left, &con->ip_port);
+ const int len = net_send(con->ns, logger, con->sock, con->last_packet + con->last_packet_sent, left, &con->ip_port,
+ con->net_profile);
if (len <= 0) {
return -1;
@@ -66,7 +67,7 @@ int send_pending_data(const Logger *logger, TCP_Connection *con)
while (p != nullptr) {
const uint16_t left = p->size - p->sent;
- const int len = net_send(con->ns, logger, con->sock, p->data + p->sent, left, &con->ip_port);
+ const int len = net_send(con->ns, logger, con->sock, p->data + p->sent, left, &con->ip_port, con->net_profile);
if (len != left) {
if (len > 0) {
@@ -157,14 +158,15 @@ int write_packet_tcp_secure_connection(const Logger *logger, TCP_Connection *con
uint16_t c_length = net_htons(length + CRYPTO_MAC_SIZE);
memcpy(packet, &c_length, sizeof(uint16_t));
- int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t));
+ int len = encrypt_data_symmetric(con->mem, con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t));
if ((unsigned int)len != (packet_size - sizeof(uint16_t))) {
return -1;
}
if (priority) {
- len = sendpriority ? net_send(con->ns, logger, con->sock, packet, packet_size, &con->ip_port) : 0;
+ len = sendpriority ? net_send(con->ns, logger, con->sock, packet, packet_size, &con->ip_port,
+ con->net_profile) : 0;
if (len <= 0) {
len = 0;
@@ -179,7 +181,7 @@ int write_packet_tcp_secure_connection(const Logger *logger, TCP_Connection *con
return add_priority(con, packet, packet_size, len) ? 1 : 0;
}
- len = net_send(con->ns, logger, con->sock, packet, packet_size, &con->ip_port);
+ len = net_send(con->ns, logger, con->sock, packet, packet_size, &con->ip_port, con->net_profile);
if (len <= 0) {
return 0;
@@ -234,7 +236,7 @@ int read_tcp_packet(
* return -1 on failure.
*/
non_null()
-static uint16_t read_tcp_length(const Logger *logger, const Memory *mem, const Network *ns, Socket sock, const IP_Port *ip_port)
+static uint16_t read_tcp_length(const Logger *logger, const Network *ns, Socket sock, const IP_Port *ip_port)
{
const uint16_t count = net_socket_data_recv_buffer(ns, sock);
@@ -273,7 +275,7 @@ int read_packet_tcp_secure_connection(
uint16_t max_len, const IP_Port *ip_port)
{
if (*next_packet_length == 0) {
- const uint16_t len = read_tcp_length(logger, mem, ns, sock, ip_port);
+ const uint16_t len = read_tcp_length(logger, ns, sock, ip_port);
if (len == (uint16_t) -1) {
return -1;
@@ -305,7 +307,7 @@ int read_packet_tcp_secure_connection(
*next_packet_length = 0;
- const int len = decrypt_data_symmetric(shared_key, recv_nonce, data_encrypted, len_packet, data);
+ const int len = decrypt_data_symmetric(mem, shared_key, recv_nonce, data_encrypted, len_packet, data);
if (len + CRYPTO_MAC_SIZE != len_packet) {
LOGGER_ERROR(logger, "decrypted length %d does not match expected length %d", len + CRYPTO_MAC_SIZE, len_packet);
diff --git a/protocols/Tox/libtox/src/toxcore/TCP_common.h b/protocols/Tox/libtox/src/toxcore/TCP_common.h
index 9fa136609c..dd07fd1ec5 100644
--- a/protocols/Tox/libtox/src/toxcore/TCP_common.h
+++ b/protocols/Tox/libtox/src/toxcore/TCP_common.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2014 Tox project.
*/
@@ -10,6 +10,7 @@
#include "crypto_core.h"
#include "logger.h"
#include "mem.h"
+#include "net_profile.h"
#include "network.h"
typedef struct TCP_Priority_List TCP_Priority_List;
@@ -66,6 +67,10 @@ typedef struct TCP_Connection {
TCP_Priority_List *priority_queue_start;
TCP_Priority_List *priority_queue_end;
+
+ // This is a shared pointer to the parent's respective Net_Profile object
+ // (either TCP_Server for TCP server packets or TCP_Connections for TCP client packets).
+ Net_Profile *net_profile;
} TCP_Connection;
/**
diff --git a/protocols/Tox/libtox/src/toxcore/TCP_connection.c b/protocols/Tox/libtox/src/toxcore/TCP_connection.c
index c7161a9289..42269ad553 100644
--- a/protocols/Tox/libtox/src/toxcore/TCP_connection.c
+++ b/protocols/Tox/libtox/src/toxcore/TCP_connection.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2015 Tox project.
*/
@@ -20,6 +20,7 @@
#include "logger.h"
#include "mem.h"
#include "mono_time.h"
+#include "net_profile.h"
#include "network.h"
#include "util.h"
@@ -56,6 +57,9 @@ struct TCP_Connections {
bool onion_status;
uint16_t onion_num_conns;
+
+ /* Network profile for all TCP client packets. */
+ Net_Profile *net_profile;
};
static const TCP_Connection_to empty_tcp_connection_to = {0};
@@ -928,7 +932,8 @@ static int reconnect_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connec
uint8_t relay_pk[CRYPTO_PUBLIC_KEY_SIZE];
memcpy(relay_pk, tcp_con_public_key(tcp_con->connection), CRYPTO_PUBLIC_KEY_SIZE);
kill_tcp_connection(tcp_con->connection);
- tcp_con->connection = new_tcp_connection(tcp_c->logger, tcp_c->mem, tcp_c->mono_time, tcp_c->rng, tcp_c->ns, &ip_port, relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info);
+ tcp_con->connection = new_tcp_connection(tcp_c->logger, tcp_c->mem, tcp_c->mono_time, tcp_c->rng, tcp_c->ns, &ip_port, relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info,
+ tcp_c->net_profile);
if (tcp_con->connection == nullptr) {
kill_tcp_relay_connection(tcp_c, tcp_connections_number);
@@ -1017,7 +1022,7 @@ static int unsleep_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connecti
tcp_con->connection = new_tcp_connection(
tcp_c->logger, tcp_c->mem, tcp_c->mono_time, tcp_c->rng, tcp_c->ns, &tcp_con->ip_port,
- tcp_con->relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info);
+ tcp_con->relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info, tcp_c->net_profile);
if (tcp_con->connection == nullptr) {
kill_tcp_relay_connection(tcp_c, tcp_connections_number);
@@ -1315,7 +1320,7 @@ static int add_tcp_relay_instance(TCP_Connections *tcp_c, const IP_Port *ip_port
tcp_con->connection = new_tcp_connection(
tcp_c->logger, tcp_c->mem, tcp_c->mono_time, tcp_c->rng, tcp_c->ns, &ipp_copy,
- relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info);
+ relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info, tcp_c->net_profile);
if (tcp_con->connection == nullptr) {
return -1;
@@ -1591,7 +1596,7 @@ int set_tcp_onion_status(TCP_Connections *tcp_c, bool status)
* Returns NULL on failure.
*/
TCP_Connections *new_tcp_connections(const Logger *logger, const Memory *mem, const Random *rng, const Network *ns,
- Mono_Time *mono_time, const uint8_t *secret_key, const TCP_Proxy_Info *proxy_info)
+ Mono_Time *mono_time, const uint8_t *secret_key, const TCP_Proxy_Info *proxy_info, Net_Profile *tcp_np)
{
assert(logger != nullptr);
assert(mem != nullptr);
@@ -1609,6 +1614,7 @@ TCP_Connections *new_tcp_connections(const Logger *logger, const Memory *mem, co
return nullptr;
}
+ temp->net_profile = tcp_np;
temp->logger = logger;
temp->mem = mem;
temp->rng = rng;
@@ -1727,3 +1733,4 @@ void kill_tcp_connections(TCP_Connections *tcp_c)
mem_delete(tcp_c->mem, tcp_c->connections);
mem_delete(tcp_c->mem, tcp_c);
}
+
diff --git a/protocols/Tox/libtox/src/toxcore/TCP_connection.h b/protocols/Tox/libtox/src/toxcore/TCP_connection.h
index 2d35919f10..3ff2173503 100644
--- a/protocols/Tox/libtox/src/toxcore/TCP_connection.h
+++ b/protocols/Tox/libtox/src/toxcore/TCP_connection.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2015 Tox project.
*/
@@ -21,6 +21,7 @@
#include "logger.h"
#include "mem.h"
#include "mono_time.h"
+#include "net_profile.h"
#include "network.h"
#define TCP_CONN_NONE 0
@@ -306,7 +307,7 @@ uint32_t tcp_copy_connected_relays_index(const TCP_Connections *tcp_c, Node_form
*/
non_null()
TCP_Connections *new_tcp_connections(const Logger *logger, const Memory *mem, const Random *rng, const Network *ns,
- Mono_Time *mono_time, const uint8_t *secret_key, const TCP_Proxy_Info *proxy_info);
+ Mono_Time *mono_time, const uint8_t *secret_key, const TCP_Proxy_Info *proxy_info, Net_Profile *tcp_np);
non_null()
int kill_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number);
diff --git a/protocols/Tox/libtox/src/toxcore/TCP_server.c b/protocols/Tox/libtox/src/toxcore/TCP_server.c
index 1363d90220..288cd94c48 100644
--- a/protocols/Tox/libtox/src/toxcore/TCP_server.c
+++ b/protocols/Tox/libtox/src/toxcore/TCP_server.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2014 Tox project.
*/
@@ -27,6 +27,7 @@
#include "logger.h"
#include "mem.h"
#include "mono_time.h"
+#include "net_profile.h"
#include "network.h"
#include "onion.h"
@@ -91,6 +92,9 @@ struct TCP_Server {
uint64_t counter;
BS_List accepted_key_list;
+
+ /* Network profile for all TCP server packets. */
+ Net_Profile *net_profile;
};
static_assert(sizeof(TCP_Server) < 7 * 1024 * 1024,
@@ -236,6 +240,7 @@ static int add_accepted(TCP_Server *tcp_server, const Mono_Time *mono_time, TCP_
tcp_server->accepted_connection_array[index].identifier = ++tcp_server->counter;
tcp_server->accepted_connection_array[index].last_pinged = mono_time_get(mono_time);
tcp_server->accepted_connection_array[index].ping_id = 0;
+ tcp_server->accepted_connection_array[index].con.net_profile = tcp_server->net_profile;
return index;
}
@@ -327,7 +332,7 @@ static int handle_tcp_handshake(const Logger *logger, TCP_Secure_Connection *con
uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
encrypt_precompute(data, self_secret_key, shared_key);
uint8_t plain[TCP_HANDSHAKE_PLAIN_SIZE];
- int len = decrypt_data_symmetric(shared_key, data + CRYPTO_PUBLIC_KEY_SIZE,
+ int len = decrypt_data_symmetric(con->con.mem, shared_key, data + CRYPTO_PUBLIC_KEY_SIZE,
data + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, TCP_HANDSHAKE_PLAIN_SIZE + CRYPTO_MAC_SIZE, plain);
if (len != TCP_HANDSHAKE_PLAIN_SIZE) {
@@ -347,7 +352,7 @@ static int handle_tcp_handshake(const Logger *logger, TCP_Secure_Connection *con
uint8_t response[TCP_SERVER_HANDSHAKE_SIZE];
random_nonce(con->con.rng, response);
- len = encrypt_data_symmetric(shared_key, response, resp_plain, TCP_HANDSHAKE_PLAIN_SIZE,
+ len = encrypt_data_symmetric(con->con.mem, shared_key, response, resp_plain, TCP_HANDSHAKE_PLAIN_SIZE,
response + CRYPTO_NONCE_SIZE);
if (len != TCP_HANDSHAKE_PLAIN_SIZE + CRYPTO_MAC_SIZE) {
@@ -357,7 +362,7 @@ static int handle_tcp_handshake(const Logger *logger, TCP_Secure_Connection *con
const IP_Port ipp = {{{0}}};
- if (TCP_SERVER_HANDSHAKE_SIZE != net_send(con->con.ns, logger, con->con.sock, response, TCP_SERVER_HANDSHAKE_SIZE, &ipp)) {
+ if (TCP_SERVER_HANDSHAKE_SIZE != net_send(con->con.ns, logger, con->con.sock, response, TCP_SERVER_HANDSHAKE_SIZE, &ipp, con->con.net_profile)) {
crypto_memzero(shared_key, sizeof(shared_key));
return -1;
}
@@ -680,6 +685,7 @@ static int handle_tcp_packet(TCP_Server *tcp_server, uint32_t con_id, const uint
}
TCP_Secure_Connection *const con = &tcp_server->accepted_connection_array[con_id];
+ netprof_record_packet(con->con.net_profile, data[0], length, PACKET_DIRECTION_RECV);
switch (data[0]) {
case TCP_PACKET_ROUTING_REQUEST: {
@@ -914,7 +920,7 @@ static int accept_connection(TCP_Server *tcp_server, Socket sock)
}
non_null()
-static Socket new_listening_tcp_socket(const Logger *logger, const Network *ns, Family family, uint16_t port)
+static Socket new_listening_tcp_socket(const Logger *logger, const Memory *mem, const Network *ns, Family family, uint16_t port)
{
const Socket sock = net_socket(ns, family, TOX_SOCK_STREAM, TOX_PROTO_TCP);
@@ -936,10 +942,9 @@ static Socket new_listening_tcp_socket(const Logger *logger, const Network *ns,
ok = ok && bind_to_port(ns, sock, family, port) && (net_listen(ns, sock, TCP_MAX_BACKLOG) == 0);
if (!ok) {
- char *const error = net_new_strerror(net_error());
+ Net_Strerror error_str;
LOGGER_WARNING(logger, "could not bind to TCP port %d (family = %d): %s",
- port, family.value, error != nullptr ? error : "(null)");
- net_kill_strerror(error);
+ port, family.value, net_strerror(net_error(), &error_str));
kill_sock(ns, sock);
return net_invalid_socket();
}
@@ -969,6 +974,14 @@ TCP_Server *new_tcp_server(const Logger *logger, const Memory *mem, const Random
return nullptr;
}
+ Net_Profile *np = netprof_new(logger, mem);
+
+ if (np == nullptr) {
+ mem_delete(mem, temp);
+ return nullptr;
+ }
+
+ temp->net_profile = np;
temp->logger = logger;
temp->mem = mem;
temp->ns = ns;
@@ -978,6 +991,7 @@ TCP_Server *new_tcp_server(const Logger *logger, const Memory *mem, const Random
if (socks_listening == nullptr) {
LOGGER_ERROR(logger, "socket allocation failed");
+ netprof_kill(mem, temp->net_profile);
mem_delete(mem, temp);
return nullptr;
}
@@ -989,6 +1003,7 @@ TCP_Server *new_tcp_server(const Logger *logger, const Memory *mem, const Random
if (temp->efd == -1) {
LOGGER_ERROR(logger, "epoll initialisation failed");
+ netprof_kill(mem, temp->net_profile);
mem_delete(mem, socks_listening);
mem_delete(mem, temp);
return nullptr;
@@ -999,7 +1014,7 @@ TCP_Server *new_tcp_server(const Logger *logger, const Memory *mem, const Random
const Family family = ipv6_enabled ? net_family_ipv6() : net_family_ipv4();
for (uint32_t i = 0; i < num_sockets; ++i) {
- const Socket sock = new_listening_tcp_socket(logger, ns, family, ports[i]);
+ const Socket sock = new_listening_tcp_socket(logger, mem, ns, family, ports[i]);
if (!sock_valid(sock)) {
continue;
@@ -1022,6 +1037,7 @@ TCP_Server *new_tcp_server(const Logger *logger, const Memory *mem, const Random
}
if (temp->num_listening_socks == 0) {
+ netprof_kill(mem, temp->net_profile);
mem_delete(mem, temp->socks_listening);
mem_delete(mem, temp);
return nullptr;
@@ -1040,7 +1056,7 @@ TCP_Server *new_tcp_server(const Logger *logger, const Memory *mem, const Random
memcpy(temp->secret_key, secret_key, CRYPTO_SECRET_KEY_SIZE);
crypto_derive_public_key(temp->public_key, temp->secret_key);
- bs_list_init(&temp->accepted_key_list, CRYPTO_PUBLIC_KEY_SIZE, 8, memcmp);
+ bs_list_init(&temp->accepted_key_list, mem, CRYPTO_PUBLIC_KEY_SIZE, 8, memcmp);
return temp;
}
@@ -1422,6 +1438,16 @@ void kill_tcp_server(TCP_Server *tcp_server)
crypto_memzero(tcp_server->secret_key, sizeof(tcp_server->secret_key));
+ netprof_kill(tcp_server->mem, tcp_server->net_profile);
mem_delete(tcp_server->mem, tcp_server->socks_listening);
mem_delete(tcp_server->mem, tcp_server);
}
+
+const Net_Profile *tcp_server_get_net_profile(const TCP_Server *tcp_server)
+{
+ if (tcp_server == nullptr) {
+ return nullptr;
+ }
+
+ return tcp_server->net_profile;
+}
diff --git a/protocols/Tox/libtox/src/toxcore/TCP_server.h b/protocols/Tox/libtox/src/toxcore/TCP_server.h
index 1d3933a415..bd4c98b0cd 100644
--- a/protocols/Tox/libtox/src/toxcore/TCP_server.h
+++ b/protocols/Tox/libtox/src/toxcore/TCP_server.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2014 Tox project.
*/
@@ -15,6 +15,7 @@
#include "logger.h"
#include "mem.h"
#include "mono_time.h"
+#include "net_profile.h"
#include "network.h"
#include "onion.h"
@@ -52,4 +53,11 @@ void do_tcp_server(TCP_Server *tcp_server, const Mono_Time *mono_time);
nullable(1)
void kill_tcp_server(TCP_Server *tcp_server);
+/** @brief Returns a pointer to the net profile associated with `tcp_server`.
+ *
+ * Returns null if `tcp_server` is null.
+ */
+nullable(1)
+const Net_Profile *tcp_server_get_net_profile(const TCP_Server *tcp_server);
+
#endif /* C_TOXCORE_TOXCORE_TCP_SERVER_H */
diff --git a/protocols/Tox/libtox/src/toxcore/announce.c b/protocols/Tox/libtox/src/toxcore/announce.c
index b983cb0574..dc34ca05e3 100644
--- a/protocols/Tox/libtox/src/toxcore/announce.c
+++ b/protocols/Tox/libtox/src/toxcore/announce.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2020-2021 The TokTok team.
+ * Copyright © 2020-2025 The TokTok team.
*/
/**
@@ -9,7 +9,6 @@
#include "announce.h"
#include <assert.h>
-#include <stdlib.h>
#include <string.h>
#include "DHT.h"
@@ -239,9 +238,9 @@ bool announce_store_data(Announcements *announce, const uint8_t *data_public_key
if (length > 0) {
assert(data != nullptr);
- free(entry->data);
+ mem_delete(announce->mem, entry->data);
- uint8_t *entry_data = (uint8_t *)malloc(length);
+ uint8_t *entry_data = (uint8_t *)mem_balloc(announce->mem, length);
if (entry_data == nullptr) {
entry->data = nullptr; // TODO(iphydf): Is this necessary?
@@ -451,7 +450,7 @@ static int create_reply_plain_store_announce_request(Announcements *announce,
return -1;
}
- if (decrypt_data_symmetric(shared_key,
+ if (decrypt_data_symmetric(announce->mem, shared_key,
data + CRYPTO_PUBLIC_KEY_SIZE,
data + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
plain_len + CRYPTO_MAC_SIZE,
@@ -568,7 +567,7 @@ static int create_reply(Announcements *announce, const IP_Port *source,
VLA(uint8_t, plain, plain_len);
const uint8_t *shared_key = dht_get_shared_key_recv(announce->dht, data + 1);
- if (decrypt_data_symmetric(shared_key,
+ if (decrypt_data_symmetric(announce->mem, shared_key,
data + 1 + CRYPTO_PUBLIC_KEY_SIZE,
data + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
plain_len + CRYPTO_MAC_SIZE,
@@ -579,7 +578,7 @@ static int create_reply(Announcements *announce, const IP_Port *source,
const int plain_reply_max_len = (int)reply_max_length -
(1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_MAC_SIZE);
- if (plain_reply_max_len < sizeof(uint64_t)) {
+ if (plain_reply_max_len < (int)sizeof(uint64_t)) {
return -1;
}
@@ -651,7 +650,7 @@ Announcements *new_announcements(const Logger *log, const Memory *mem, const Ran
return nullptr;
}
- Announcements *announce = (Announcements *)calloc(1, sizeof(Announcements));
+ Announcements *announce = (Announcements *)mem_alloc(mem, sizeof(Announcements));
if (announce == nullptr) {
return nullptr;
@@ -669,7 +668,7 @@ Announcements *new_announcements(const Logger *log, const Memory *mem, const Ran
new_hmac_key(announce->rng, announce->hmac_key);
announce->shared_keys = shared_key_cache_new(log, mono_time, mem, announce->secret_key, KEYS_TIMEOUT, MAX_KEYS_PER_SLOT);
if (announce->shared_keys == nullptr) {
- free(announce);
+ mem_delete(announce->mem, announce);
return nullptr;
}
@@ -700,8 +699,8 @@ void kill_announcements(Announcements *announce)
shared_key_cache_free(announce->shared_keys);
for (uint32_t i = 0; i < ANNOUNCE_BUCKETS * ANNOUNCE_BUCKET_SIZE; ++i) {
- free(announce->entries[i].data);
+ mem_delete(announce->mem, announce->entries[i].data);
}
- free(announce);
+ mem_delete(announce->mem, announce);
}
diff --git a/protocols/Tox/libtox/src/toxcore/announce.h b/protocols/Tox/libtox/src/toxcore/announce.h
index bd05088d06..c1397454ac 100644
--- a/protocols/Tox/libtox/src/toxcore/announce.h
+++ b/protocols/Tox/libtox/src/toxcore/announce.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2020-2021 The TokTok team.
+ * Copyright © 2020-2025 The TokTok team.
*/
#ifndef C_TOXCORE_TOXCORE_ANNOUNCE_H
diff --git a/protocols/Tox/libtox/src/toxcore/attributes.h b/protocols/Tox/libtox/src/toxcore/attributes.h
index 087efe20dc..009dfa359e 100644
--- a/protocols/Tox/libtox/src/toxcore/attributes.h
+++ b/protocols/Tox/libtox/src/toxcore/attributes.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2022-2025 The TokTok team.
*/
/**
diff --git a/protocols/Tox/libtox/src/toxcore/bin_pack.c b/protocols/Tox/libtox/src/toxcore/bin_pack.c
index 56bdc9ec75..82e9d20dd4 100644
--- a/protocols/Tox/libtox/src/toxcore/bin_pack.c
+++ b/protocols/Tox/libtox/src/toxcore/bin_pack.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2022-2025 The TokTok team.
*/
#include "bin_pack.h"
diff --git a/protocols/Tox/libtox/src/toxcore/bin_pack.h b/protocols/Tox/libtox/src/toxcore/bin_pack.h
index ce6926a448..4b2927f972 100644
--- a/protocols/Tox/libtox/src/toxcore/bin_pack.h
+++ b/protocols/Tox/libtox/src/toxcore/bin_pack.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2022-2025 The TokTok team.
*/
#ifndef C_TOXCORE_TOXCORE_BIN_PACK_H
#define C_TOXCORE_TOXCORE_BIN_PACK_H
diff --git a/protocols/Tox/libtox/src/toxcore/bin_unpack.c b/protocols/Tox/libtox/src/toxcore/bin_unpack.c
index d6b1c52ea5..e3110946bf 100644
--- a/protocols/Tox/libtox/src/toxcore/bin_unpack.c
+++ b/protocols/Tox/libtox/src/toxcore/bin_unpack.c
@@ -1,18 +1,20 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2022-2025 The TokTok team.
*/
#include "bin_unpack.h"
#include <assert.h>
-#include <stdlib.h>
#include <string.h>
#include "../third_party/cmp/cmp.h"
#include "attributes.h"
#include "ccompat.h"
+#include "mem.h"
struct Bin_Unpack {
+ const Memory *mem;
+
const uint8_t *bytes;
uint32_t bytes_size;
cmp_ctx_t ctx;
@@ -54,17 +56,18 @@ static size_t null_writer(cmp_ctx_t *ctx, const void *data, size_t count)
}
non_null()
-static void bin_unpack_init(Bin_Unpack *bu, const uint8_t *buf, uint32_t buf_size)
+static void bin_unpack_init(Bin_Unpack *bu, const Memory *mem, const uint8_t *buf, uint32_t buf_size)
{
+ bu->mem = mem;
bu->bytes = buf;
bu->bytes_size = buf_size;
cmp_init(&bu->ctx, bu, buf_reader, buf_skipper, null_writer);
}
-bool bin_unpack_obj(bin_unpack_cb *callback, void *obj, const uint8_t *buf, uint32_t buf_size)
+bool bin_unpack_obj(const Memory *mem, bin_unpack_cb *callback, void *obj, const uint8_t *buf, uint32_t buf_size)
{
Bin_Unpack bu;
- bin_unpack_init(&bu, buf, buf_size);
+ bin_unpack_init(&bu, mem, buf, buf_size);
return callback(obj, &bu);
}
@@ -120,10 +123,14 @@ bool bin_unpack_bin(Bin_Unpack *bu, uint8_t **data_ptr, uint32_t *data_length_pt
// There aren't as many bytes as this bin claims to want to allocate.
return false;
}
- uint8_t *const data = (uint8_t *)malloc(bin_size);
+ uint8_t *const data = (uint8_t *)mem_balloc(bu->mem, bin_size);
+
+ if (data == nullptr) {
+ return false;
+ }
if (!bin_unpack_bin_b(bu, data, bin_size)) {
- free(data);
+ mem_delete(bu->mem, data);
return false;
}
diff --git a/protocols/Tox/libtox/src/toxcore/bin_unpack.h b/protocols/Tox/libtox/src/toxcore/bin_unpack.h
index 0554bd1a7a..029c3a0d0a 100644
--- a/protocols/Tox/libtox/src/toxcore/bin_unpack.h
+++ b/protocols/Tox/libtox/src/toxcore/bin_unpack.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2022-2025 The TokTok team.
*/
#ifndef C_TOXCORE_TOXCORE_BIN_UNPACK_H
@@ -9,6 +9,7 @@
#include <stdint.h>
#include "attributes.h"
+#include "mem.h"
#ifdef __cplusplus
extern "C" {
@@ -46,7 +47,7 @@ typedef bool bin_unpack_cb(void *obj, Bin_Unpack *bu);
* @retval false if an error occurred (e.g. buffer overrun).
*/
non_null()
-bool bin_unpack_obj(bin_unpack_cb *callback, void *obj, const uint8_t *buf, uint32_t buf_size);
+bool bin_unpack_obj(const Memory *mem, bin_unpack_cb *callback, void *obj, const uint8_t *buf, uint32_t buf_size);
/** @brief Start unpacking a MessagePack array.
*
diff --git a/protocols/Tox/libtox/src/toxcore/ccompat.c b/protocols/Tox/libtox/src/toxcore/ccompat.c
index 6e4689736a..3ac18a270e 100644
--- a/protocols/Tox/libtox/src/toxcore/ccompat.c
+++ b/protocols/Tox/libtox/src/toxcore/ccompat.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2022-2025 The TokTok team.
*/
#include "ccompat.h"
diff --git a/protocols/Tox/libtox/src/toxcore/ccompat.h b/protocols/Tox/libtox/src/toxcore/ccompat.h
index 47ab9ed2bf..df68413741 100644
--- a/protocols/Tox/libtox/src/toxcore/ccompat.h
+++ b/protocols/Tox/libtox/src/toxcore/ccompat.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2021 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
*/
/**
diff --git a/protocols/Tox/libtox/src/toxcore/crypto_core.c b/protocols/Tox/libtox/src/toxcore/crypto_core.c
index 7bb5bb929f..8a6aa38fba 100644
--- a/protocols/Tox/libtox/src/toxcore/crypto_core.c
+++ b/protocols/Tox/libtox/src/toxcore/crypto_core.c
@@ -1,18 +1,18 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2024 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
#include "crypto_core.h"
#include <assert.h>
-#include <stdlib.h>
#include <string.h>
#include <sodium.h>
#include "attributes.h"
#include "ccompat.h"
+#include "mem.h"
#include "util.h"
static_assert(CRYPTO_PUBLIC_KEY_SIZE == crypto_box_PUBLICKEYBYTES,
@@ -88,9 +88,10 @@ const uint8_t *get_chat_id(const Extended_Public_Key *key)
}
#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
-static uint8_t *crypto_malloc(size_t bytes)
+non_null()
+static uint8_t *crypto_malloc(const Memory *mem, size_t bytes)
{
- uint8_t *ptr = (uint8_t *)malloc(bytes);
+ uint8_t *ptr = (uint8_t *)mem_balloc(mem, bytes);
if (ptr != nullptr) {
crypto_memlock(ptr, bytes);
@@ -99,15 +100,15 @@ static uint8_t *crypto_malloc(size_t bytes)
return ptr;
}
-nullable(1)
-static void crypto_free(uint8_t *ptr, size_t bytes)
+non_null(1) nullable(2)
+static void crypto_free(const Memory *mem, uint8_t *ptr, size_t bytes)
{
if (ptr != nullptr) {
crypto_memzero(ptr, bytes);
crypto_memunlock(ptr, bytes);
}
- free(ptr);
+ mem_delete(mem, ptr);
}
#endif /* !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) */
@@ -240,7 +241,8 @@ int32_t encrypt_precompute(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
}
-int32_t encrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE],
+int32_t encrypt_data_symmetric(const Memory *mem,
+ const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE],
const uint8_t nonce[CRYPTO_NONCE_SIZE],
const uint8_t *plain, size_t length, uint8_t *encrypted)
{
@@ -258,12 +260,12 @@ int32_t encrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE],
const size_t size_temp_plain = length + crypto_box_ZEROBYTES;
const size_t size_temp_encrypted = length + crypto_box_MACBYTES + crypto_box_BOXZEROBYTES;
- uint8_t *temp_plain = crypto_malloc(size_temp_plain);
- uint8_t *temp_encrypted = crypto_malloc(size_temp_encrypted);
+ uint8_t *temp_plain = crypto_malloc(mem, size_temp_plain);
+ uint8_t *temp_encrypted = crypto_malloc(mem, size_temp_encrypted);
if (temp_plain == nullptr || temp_encrypted == nullptr) {
- crypto_free(temp_plain, size_temp_plain);
- crypto_free(temp_encrypted, size_temp_encrypted);
+ crypto_free(mem, temp_plain, size_temp_plain);
+ crypto_free(mem, temp_encrypted, size_temp_encrypted);
return -1;
}
@@ -278,22 +280,23 @@ int32_t encrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE],
if (crypto_box_afternm(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce,
shared_key) != 0) {
- crypto_free(temp_plain, size_temp_plain);
- crypto_free(temp_encrypted, size_temp_encrypted);
+ crypto_free(mem, temp_plain, size_temp_plain);
+ crypto_free(mem, temp_encrypted, size_temp_encrypted);
return -1;
}
// Unpad the encrypted message.
memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length + crypto_box_MACBYTES);
- crypto_free(temp_plain, size_temp_plain);
- crypto_free(temp_encrypted, size_temp_encrypted);
+ crypto_free(mem, temp_plain, size_temp_plain);
+ crypto_free(mem, temp_encrypted, size_temp_encrypted);
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
assert(length < INT32_MAX - crypto_box_MACBYTES);
return (int32_t)(length + crypto_box_MACBYTES);
}
-int32_t decrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE],
+int32_t decrypt_data_symmetric(const Memory *mem,
+ const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE],
const uint8_t nonce[CRYPTO_NONCE_SIZE],
const uint8_t *encrypted, size_t length, uint8_t *plain)
{
@@ -310,12 +313,12 @@ int32_t decrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE],
const size_t size_temp_plain = length + crypto_box_ZEROBYTES;
const size_t size_temp_encrypted = length + crypto_box_BOXZEROBYTES;
- uint8_t *temp_plain = crypto_malloc(size_temp_plain);
- uint8_t *temp_encrypted = crypto_malloc(size_temp_encrypted);
+ uint8_t *temp_plain = crypto_malloc(mem, size_temp_plain);
+ uint8_t *temp_encrypted = crypto_malloc(mem, size_temp_encrypted);
if (temp_plain == nullptr || temp_encrypted == nullptr) {
- crypto_free(temp_plain, size_temp_plain);
- crypto_free(temp_encrypted, size_temp_encrypted);
+ crypto_free(mem, temp_plain, size_temp_plain);
+ crypto_free(mem, temp_encrypted, size_temp_encrypted);
return -1;
}
@@ -330,22 +333,23 @@ int32_t decrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE],
if (crypto_box_open_afternm(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, nonce,
shared_key) != 0) {
- crypto_free(temp_plain, size_temp_plain);
- crypto_free(temp_encrypted, size_temp_encrypted);
+ crypto_free(mem, temp_plain, size_temp_plain);
+ crypto_free(mem, temp_encrypted, size_temp_encrypted);
return -1;
}
memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_MACBYTES);
- crypto_free(temp_plain, size_temp_plain);
- crypto_free(temp_encrypted, size_temp_encrypted);
+ crypto_free(mem, temp_plain, size_temp_plain);
+ crypto_free(mem, temp_encrypted, size_temp_encrypted);
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
assert(length > crypto_box_MACBYTES);
assert(length < INT32_MAX);
return (int32_t)(length - crypto_box_MACBYTES);
}
-int32_t encrypt_data(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
+int32_t encrypt_data(const Memory *mem,
+ const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE],
const uint8_t nonce[CRYPTO_NONCE_SIZE],
const uint8_t *plain, size_t length, uint8_t *encrypted)
@@ -356,12 +360,13 @@ int32_t encrypt_data(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
uint8_t k[crypto_box_BEFORENMBYTES];
encrypt_precompute(public_key, secret_key, k);
- const int ret = encrypt_data_symmetric(k, nonce, plain, length, encrypted);
+ const int ret = encrypt_data_symmetric(mem, k, nonce, plain, length, encrypted);
crypto_memzero(k, sizeof(k));
return ret;
}
-int32_t decrypt_data(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
+int32_t decrypt_data(const Memory *mem,
+ const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE],
const uint8_t nonce[CRYPTO_NONCE_SIZE],
const uint8_t *encrypted, size_t length, uint8_t *plain)
@@ -372,7 +377,7 @@ int32_t decrypt_data(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
uint8_t k[crypto_box_BEFORENMBYTES];
encrypt_precompute(public_key, secret_key, k);
- const int ret = decrypt_data_symmetric(k, nonce, encrypted, length, plain);
+ const int ret = decrypt_data_symmetric(mem, k, nonce, encrypted, length, plain);
crypto_memzero(k, sizeof(k));
return ret;
}
diff --git a/protocols/Tox/libtox/src/toxcore/crypto_core.h b/protocols/Tox/libtox/src/toxcore/crypto_core.h
index 979791bd97..558118e397 100644
--- a/protocols/Tox/libtox/src/toxcore/crypto_core.h
+++ b/protocols/Tox/libtox/src/toxcore/crypto_core.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2024 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -16,6 +16,7 @@
#include <stdint.h>
#include "attributes.h"
+#include "mem.h"
#ifdef __cplusplus
extern "C" {
@@ -386,7 +387,8 @@ void crypto_derive_public_key(uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
* @return length of encrypted data if everything was fine.
*/
non_null()
-int32_t encrypt_data(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
+int32_t encrypt_data(const Memory *mem,
+ const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE],
const uint8_t nonce[CRYPTO_NONCE_SIZE],
const uint8_t *plain, size_t length, uint8_t *encrypted);
@@ -403,7 +405,8 @@ int32_t encrypt_data(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
* @return length of plain text data if everything was fine.
*/
non_null()
-int32_t decrypt_data(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
+int32_t decrypt_data(const Memory *mem,
+ const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE],
const uint8_t nonce[CRYPTO_NONCE_SIZE],
const uint8_t *encrypted, size_t length, uint8_t *plain);
@@ -431,7 +434,8 @@ int32_t encrypt_precompute(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
* @return length of encrypted data if everything was fine.
*/
non_null()
-int32_t encrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE],
+int32_t encrypt_data_symmetric(const Memory *mem,
+ const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE],
const uint8_t nonce[CRYPTO_NONCE_SIZE],
const uint8_t *plain, size_t length, uint8_t *encrypted);
@@ -446,7 +450,8 @@ int32_t encrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE],
* @return length of plain data if everything was fine.
*/
non_null()
-int32_t decrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE],
+int32_t decrypt_data_symmetric(const Memory *mem,
+ const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE],
const uint8_t nonce[CRYPTO_NONCE_SIZE],
const uint8_t *encrypted, size_t length, uint8_t *plain);
diff --git a/protocols/Tox/libtox/src/toxcore/crypto_core_pack.c b/protocols/Tox/libtox/src/toxcore/crypto_core_pack.c
index a173d39d8d..4c08fc7d2a 100644
--- a/protocols/Tox/libtox/src/toxcore/crypto_core_pack.c
+++ b/protocols/Tox/libtox/src/toxcore/crypto_core_pack.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2024 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
diff --git a/protocols/Tox/libtox/src/toxcore/crypto_core_pack.h b/protocols/Tox/libtox/src/toxcore/crypto_core_pack.h
index 1efefff840..85b47ff4e4 100644
--- a/protocols/Tox/libtox/src/toxcore/crypto_core_pack.h
+++ b/protocols/Tox/libtox/src/toxcore/crypto_core_pack.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2024 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
diff --git a/protocols/Tox/libtox/src/toxcore/events/conference_connected.c b/protocols/Tox/libtox/src/toxcore/events/conference_connected.c
index dbd9e4b51a..d19f0191a2 100644
--- a/protocols/Tox/libtox/src/toxcore/events/conference_connected.c
+++ b/protocols/Tox/libtox/src/toxcore/events/conference_connected.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -12,6 +12,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
/*****************************************************
@@ -109,7 +110,10 @@ static Tox_Event_Conference_Connected *tox_events_add_conference_connected(Tox_E
event.type = TOX_EVENT_CONFERENCE_CONNECTED;
event.data.conference_connected = conference_connected;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_conference_connected_free(conference_connected, mem);
+ return nullptr;
+ }
return conference_connected;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/conference_invite.c b/protocols/Tox/libtox/src/toxcore/events/conference_invite.c
index fb1f794bf3..04206e768f 100644
--- a/protocols/Tox/libtox/src/toxcore/events/conference_invite.c
+++ b/protocols/Tox/libtox/src/toxcore/events/conference_invite.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -14,6 +14,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
#include "../tox_pack.h"
#include "../tox_unpack.h"
@@ -177,7 +178,10 @@ static Tox_Event_Conference_Invite *tox_events_add_conference_invite(Tox_Events
event.type = TOX_EVENT_CONFERENCE_INVITE;
event.data.conference_invite = conference_invite;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_conference_invite_free(conference_invite, mem);
+ return nullptr;
+ }
return conference_invite;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/conference_message.c b/protocols/Tox/libtox/src/toxcore/events/conference_message.c
index 74e1123e01..7cef201a35 100644
--- a/protocols/Tox/libtox/src/toxcore/events/conference_message.c
+++ b/protocols/Tox/libtox/src/toxcore/events/conference_message.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -14,6 +14,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
#include "../tox_pack.h"
#include "../tox_unpack.h"
@@ -193,7 +194,10 @@ static Tox_Event_Conference_Message *tox_events_add_conference_message(Tox_Event
event.type = TOX_EVENT_CONFERENCE_MESSAGE;
event.data.conference_message = conference_message;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_conference_message_free(conference_message, mem);
+ return nullptr;
+ }
return conference_message;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/conference_peer_list_changed.c b/protocols/Tox/libtox/src/toxcore/events/conference_peer_list_changed.c
index 050bfb08f8..68744208d6 100644
--- a/protocols/Tox/libtox/src/toxcore/events/conference_peer_list_changed.c
+++ b/protocols/Tox/libtox/src/toxcore/events/conference_peer_list_changed.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -12,6 +12,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
/*****************************************************
@@ -109,7 +110,10 @@ static Tox_Event_Conference_Peer_List_Changed *tox_events_add_conference_peer_li
event.type = TOX_EVENT_CONFERENCE_PEER_LIST_CHANGED;
event.data.conference_peer_list_changed = conference_peer_list_changed;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_conference_peer_list_changed_free(conference_peer_list_changed, mem);
+ return nullptr;
+ }
return conference_peer_list_changed;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/conference_peer_name.c b/protocols/Tox/libtox/src/toxcore/events/conference_peer_name.c
index fc6c255791..36de6ba9c2 100644
--- a/protocols/Tox/libtox/src/toxcore/events/conference_peer_name.c
+++ b/protocols/Tox/libtox/src/toxcore/events/conference_peer_name.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -14,6 +14,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
/*****************************************************
@@ -175,7 +176,10 @@ static Tox_Event_Conference_Peer_Name *tox_events_add_conference_peer_name(Tox_E
event.type = TOX_EVENT_CONFERENCE_PEER_NAME;
event.data.conference_peer_name = conference_peer_name;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_conference_peer_name_free(conference_peer_name, mem);
+ return nullptr;
+ }
return conference_peer_name;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/conference_title.c b/protocols/Tox/libtox/src/toxcore/events/conference_title.c
index d761f51285..cd92ba1651 100644
--- a/protocols/Tox/libtox/src/toxcore/events/conference_title.c
+++ b/protocols/Tox/libtox/src/toxcore/events/conference_title.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -14,6 +14,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
/*****************************************************
@@ -175,7 +176,10 @@ static Tox_Event_Conference_Title *tox_events_add_conference_title(Tox_Events *e
event.type = TOX_EVENT_CONFERENCE_TITLE;
event.data.conference_title = conference_title;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_conference_title_free(conference_title, mem);
+ return nullptr;
+ }
return conference_title;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/dht_get_nodes_response.c b/protocols/Tox/libtox/src/toxcore/events/dht_get_nodes_response.c
deleted file mode 100644
index 6e03b73ea4..0000000000
--- a/protocols/Tox/libtox/src/toxcore/events/dht_get_nodes_response.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
- */
-
-#include "events_alloc.h"
-
-#include <assert.h>
-#include <string.h>
-
-#include "../attributes.h"
-#include "../bin_pack.h"
-#include "../bin_unpack.h"
-#include "../ccompat.h"
-#include "../mem.h"
-#include "../tox.h"
-#include "../tox_events.h"
-#include "../tox_private.h"
-
-/*****************************************************
- *
- * :: struct and accessors
- *
- *****************************************************/
-
-struct Tox_Event_Dht_Get_Nodes_Response {
- uint8_t public_key[TOX_PUBLIC_KEY_SIZE];
- uint8_t *ip;
- uint32_t ip_length;
- uint16_t port;
-};
-
-non_null()
-static bool tox_event_dht_get_nodes_response_set_public_key(Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response, const uint8_t public_key[TOX_PUBLIC_KEY_SIZE])
-{
- memcpy(dht_get_nodes_response->public_key, public_key, TOX_PUBLIC_KEY_SIZE);
- return true;
-}
-const uint8_t *tox_event_dht_get_nodes_response_get_public_key(const Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response)
-{
- return dht_get_nodes_response->public_key;
-}
-
-non_null()
-static bool tox_event_dht_get_nodes_response_set_ip(Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response,
- const char *ip, uint32_t ip_length, const Memory *mem)
-{
- if (dht_get_nodes_response->ip != nullptr) {
- mem_delete(mem, dht_get_nodes_response->ip);
- dht_get_nodes_response->ip = nullptr;
- dht_get_nodes_response->ip_length = 0;
- }
-
- uint8_t *ip_tmp = (uint8_t *)mem_balloc(mem, ip_length);
-
- if (ip_tmp == nullptr) {
- return false;
- }
-
- memcpy(ip_tmp, ip, ip_length);
- dht_get_nodes_response->ip = ip_tmp;
- dht_get_nodes_response->ip_length = ip_length;
- return true;
-}
-uint32_t tox_event_dht_get_nodes_response_get_ip_length(const Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response)
-{
- return dht_get_nodes_response->ip_length;
-}
-const uint8_t *tox_event_dht_get_nodes_response_get_ip(const Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response)
-{
- return dht_get_nodes_response->ip;
-}
-
-non_null()
-static bool tox_event_dht_get_nodes_response_set_port(Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response, uint16_t port)
-{
- dht_get_nodes_response->port = port;
- return true;
-}
-uint16_t tox_event_dht_get_nodes_response_get_port(const Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response)
-{
- return dht_get_nodes_response->port;
-}
-
-non_null()
-static void tox_event_dht_get_nodes_response_construct(Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response)
-{
- *dht_get_nodes_response = (Tox_Event_Dht_Get_Nodes_Response) {
- {
- 0
- }
- };
-}
-non_null()
-static void tox_event_dht_get_nodes_response_destruct(Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response, const Memory *mem)
-{
- mem_delete(mem, dht_get_nodes_response->ip);
-}
-
-bool tox_event_dht_get_nodes_response_pack(
- const Tox_Event_Dht_Get_Nodes_Response *event, Bin_Pack *bp)
-{
- return bin_pack_array(bp, 3)
- && bin_pack_bin(bp, event->public_key, TOX_PUBLIC_KEY_SIZE)
- && bin_pack_bin(bp, event->ip, event->ip_length)
- && bin_pack_u16(bp, event->port);
-}
-
-non_null()
-static bool tox_event_dht_get_nodes_response_unpack_into(
- Tox_Event_Dht_Get_Nodes_Response *event, Bin_Unpack *bu)
-{
- if (!bin_unpack_array_fixed(bu, 3, nullptr)) {
- return false;
- }
-
- return bin_unpack_bin_fixed(bu, event->public_key, TOX_PUBLIC_KEY_SIZE)
- && bin_unpack_bin(bu, &event->ip, &event->ip_length)
- && bin_unpack_u16(bu, &event->port);
-}
-
-const Tox_Event_Dht_Get_Nodes_Response *tox_event_get_dht_get_nodes_response(
- const Tox_Event *event)
-{
- return event->type == TOX_EVENT_DHT_GET_NODES_RESPONSE ? event->data.dht_get_nodes_response : nullptr;
-}
-
-Tox_Event_Dht_Get_Nodes_Response *tox_event_dht_get_nodes_response_new(const Memory *mem)
-{
- Tox_Event_Dht_Get_Nodes_Response *const dht_get_nodes_response =
- (Tox_Event_Dht_Get_Nodes_Response *)mem_alloc(mem, sizeof(Tox_Event_Dht_Get_Nodes_Response));
-
- if (dht_get_nodes_response == nullptr) {
- return nullptr;
- }
-
- tox_event_dht_get_nodes_response_construct(dht_get_nodes_response);
- return dht_get_nodes_response;
-}
-
-void tox_event_dht_get_nodes_response_free(Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response, const Memory *mem)
-{
- if (dht_get_nodes_response != nullptr) {
- tox_event_dht_get_nodes_response_destruct(dht_get_nodes_response, mem);
- }
- mem_delete(mem, dht_get_nodes_response);
-}
-
-non_null()
-static Tox_Event_Dht_Get_Nodes_Response *tox_events_add_dht_get_nodes_response(Tox_Events *events, const Memory *mem)
-{
- Tox_Event_Dht_Get_Nodes_Response *const dht_get_nodes_response = tox_event_dht_get_nodes_response_new(mem);
-
- if (dht_get_nodes_response == nullptr) {
- return nullptr;
- }
-
- Tox_Event event;
- event.type = TOX_EVENT_DHT_GET_NODES_RESPONSE;
- event.data.dht_get_nodes_response = dht_get_nodes_response;
-
- tox_events_add(events, &event);
- return dht_get_nodes_response;
-}
-
-bool tox_event_dht_get_nodes_response_unpack(
- Tox_Event_Dht_Get_Nodes_Response **event, Bin_Unpack *bu, const Memory *mem)
-{
- *event = tox_event_dht_get_nodes_response_new(mem);
-
- if (*event == nullptr) {
- return false;
- }
-
- return tox_event_dht_get_nodes_response_unpack_into(*event, bu);
-}
-
-non_null()
-static Tox_Event_Dht_Get_Nodes_Response *tox_event_dht_get_nodes_response_alloc(void *user_data)
-{
- Tox_Events_State *state = tox_events_alloc(user_data);
- assert(state != nullptr);
-
- if (state->events == nullptr) {
- return nullptr;
- }
-
- Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response = tox_events_add_dht_get_nodes_response(state->events, state->mem);
-
- if (dht_get_nodes_response == nullptr) {
- state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
- return nullptr;
- }
-
- return dht_get_nodes_response;
-}
-
-/*****************************************************
- *
- * :: event handler
- *
- *****************************************************/
-
-void tox_events_handle_dht_get_nodes_response(
- Tox *tox, const uint8_t public_key[TOX_PUBLIC_KEY_SIZE],
- const char *ip, uint16_t port, void *user_data)
-{
- Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response = tox_event_dht_get_nodes_response_alloc(user_data);
-
- if (dht_get_nodes_response == nullptr) {
- return;
- }
-
- const size_t ip_length = strlen(ip);
- if (ip_length >= UINT32_MAX) {
- return;
- }
-
- const Tox_System *sys = tox_get_system(tox);
-
- tox_event_dht_get_nodes_response_set_public_key(dht_get_nodes_response, public_key);
- tox_event_dht_get_nodes_response_set_ip(dht_get_nodes_response, ip, ip_length + 1, sys->mem);
- tox_event_dht_get_nodes_response_set_port(dht_get_nodes_response, port);
-}
diff --git a/protocols/Tox/libtox/src/toxcore/events/dht_nodes_response.c b/protocols/Tox/libtox/src/toxcore/events/dht_nodes_response.c
new file mode 100644
index 0000000000..7a3f5f2730
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/events/dht_nodes_response.c
@@ -0,0 +1,222 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022-2025 The TokTok team.
+ */
+
+#include "events_alloc.h"
+
+#include <assert.h>
+#include <string.h>
+
+#include "../attributes.h"
+#include "../bin_pack.h"
+#include "../bin_unpack.h"
+#include "../ccompat.h"
+#include "../mem.h"
+#include "../tox.h"
+#include "../tox_event.h"
+#include "../tox_events.h"
+#include "../tox_private.h"
+
+/*****************************************************
+ *
+ * :: struct and accessors
+ *
+ *****************************************************/
+
+struct Tox_Event_Dht_Nodes_Response {
+ uint8_t public_key[TOX_PUBLIC_KEY_SIZE];
+ uint8_t *ip;
+ uint32_t ip_length;
+ uint16_t port;
+};
+
+non_null()
+static bool tox_event_dht_nodes_response_set_public_key(Tox_Event_Dht_Nodes_Response *dht_nodes_response, const uint8_t public_key[TOX_PUBLIC_KEY_SIZE])
+{
+ memcpy(dht_nodes_response->public_key, public_key, TOX_PUBLIC_KEY_SIZE);
+ return true;
+}
+const uint8_t *tox_event_dht_nodes_response_get_public_key(const Tox_Event_Dht_Nodes_Response *dht_nodes_response)
+{
+ return dht_nodes_response->public_key;
+}
+
+non_null()
+static bool tox_event_dht_nodes_response_set_ip(Tox_Event_Dht_Nodes_Response *dht_nodes_response,
+ const char *ip, uint32_t ip_length, const Memory *mem)
+{
+ if (dht_nodes_response->ip != nullptr) {
+ mem_delete(mem, dht_nodes_response->ip);
+ dht_nodes_response->ip = nullptr;
+ dht_nodes_response->ip_length = 0;
+ }
+
+ uint8_t *ip_tmp = (uint8_t *)mem_balloc(mem, ip_length + 1);
+
+ if (ip_tmp == nullptr) {
+ return false;
+ }
+
+ memcpy(ip_tmp, ip, ip_length + 1);
+ dht_nodes_response->ip = ip_tmp;
+ dht_nodes_response->ip_length = ip_length;
+ return true;
+}
+uint32_t tox_event_dht_nodes_response_get_ip_length(const Tox_Event_Dht_Nodes_Response *dht_nodes_response)
+{
+ return dht_nodes_response->ip_length;
+}
+const uint8_t *tox_event_dht_nodes_response_get_ip(const Tox_Event_Dht_Nodes_Response *dht_nodes_response)
+{
+ return dht_nodes_response->ip;
+}
+
+non_null()
+static bool tox_event_dht_nodes_response_set_port(Tox_Event_Dht_Nodes_Response *dht_nodes_response, uint16_t port)
+{
+ dht_nodes_response->port = port;
+ return true;
+}
+uint16_t tox_event_dht_nodes_response_get_port(const Tox_Event_Dht_Nodes_Response *dht_nodes_response)
+{
+ return dht_nodes_response->port;
+}
+
+non_null()
+static void tox_event_dht_nodes_response_construct(Tox_Event_Dht_Nodes_Response *dht_nodes_response)
+{
+ *dht_nodes_response = (Tox_Event_Dht_Nodes_Response) {
+ {
+ 0
+ }
+ };
+}
+non_null()
+static void tox_event_dht_nodes_response_destruct(Tox_Event_Dht_Nodes_Response *dht_nodes_response, const Memory *mem)
+{
+ mem_delete(mem, dht_nodes_response->ip);
+}
+
+bool tox_event_dht_nodes_response_pack(
+ const Tox_Event_Dht_Nodes_Response *event, Bin_Pack *bp)
+{
+ return bin_pack_array(bp, 3)
+ && bin_pack_bin(bp, event->public_key, TOX_PUBLIC_KEY_SIZE)
+ && bin_pack_bin(bp, event->ip, event->ip_length)
+ && bin_pack_u16(bp, event->port);
+}
+
+non_null()
+static bool tox_event_dht_nodes_response_unpack_into(
+ Tox_Event_Dht_Nodes_Response *event, Bin_Unpack *bu)
+{
+ if (!bin_unpack_array_fixed(bu, 3, nullptr)) {
+ return false;
+ }
+
+ return bin_unpack_bin_fixed(bu, event->public_key, TOX_PUBLIC_KEY_SIZE)
+ && bin_unpack_bin(bu, &event->ip, &event->ip_length)
+ && bin_unpack_u16(bu, &event->port);
+}
+
+const Tox_Event_Dht_Nodes_Response *tox_event_get_dht_nodes_response(
+ const Tox_Event *event)
+{
+ return event->type == TOX_EVENT_DHT_NODES_RESPONSE ? event->data.dht_nodes_response : nullptr;
+}
+
+Tox_Event_Dht_Nodes_Response *tox_event_dht_nodes_response_new(const Memory *mem)
+{
+ Tox_Event_Dht_Nodes_Response *const dht_nodes_response =
+ (Tox_Event_Dht_Nodes_Response *)mem_alloc(mem, sizeof(Tox_Event_Dht_Nodes_Response));
+
+ if (dht_nodes_response == nullptr) {
+ return nullptr;
+ }
+
+ tox_event_dht_nodes_response_construct(dht_nodes_response);
+ return dht_nodes_response;
+}
+
+void tox_event_dht_nodes_response_free(Tox_Event_Dht_Nodes_Response *dht_nodes_response, const Memory *mem)
+{
+ if (dht_nodes_response != nullptr) {
+ tox_event_dht_nodes_response_destruct(dht_nodes_response, mem);
+ }
+ mem_delete(mem, dht_nodes_response);
+}
+
+non_null()
+static Tox_Event_Dht_Nodes_Response *tox_events_add_dht_nodes_response(Tox_Events *events, const Memory *mem)
+{
+ Tox_Event_Dht_Nodes_Response *const dht_nodes_response = tox_event_dht_nodes_response_new(mem);
+
+ if (dht_nodes_response == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event event;
+ event.type = TOX_EVENT_DHT_NODES_RESPONSE;
+ event.data.dht_nodes_response = dht_nodes_response;
+
+ if (!tox_events_add(events, &event)) {
+ tox_event_dht_nodes_response_free(dht_nodes_response, mem);
+ return nullptr;
+ }
+ return dht_nodes_response;
+}
+
+bool tox_event_dht_nodes_response_unpack(
+ Tox_Event_Dht_Nodes_Response **event, Bin_Unpack *bu, const Memory *mem)
+{
+ *event = tox_event_dht_nodes_response_new(mem);
+
+ if (*event == nullptr) {
+ return false;
+ }
+
+ return tox_event_dht_nodes_response_unpack_into(*event, bu);
+}
+
+non_null()
+static Tox_Event_Dht_Nodes_Response *tox_event_dht_nodes_response_alloc(void *user_data)
+{
+ Tox_Events_State *state = tox_events_alloc(user_data);
+ assert(state != nullptr);
+
+ if (state->events == nullptr) {
+ return nullptr;
+ }
+
+ Tox_Event_Dht_Nodes_Response *dht_nodes_response = tox_events_add_dht_nodes_response(state->events, state->mem);
+
+ if (dht_nodes_response == nullptr) {
+ state->error = TOX_ERR_EVENTS_ITERATE_MALLOC;
+ return nullptr;
+ }
+
+ return dht_nodes_response;
+}
+
+/*****************************************************
+ *
+ * :: event handler
+ *
+ *****************************************************/
+
+void tox_events_handle_dht_nodes_response(
+ Tox *tox, const uint8_t public_key[TOX_PUBLIC_KEY_SIZE],
+ const char *ip, uint32_t ip_length, uint16_t port, void *user_data)
+{
+ Tox_Event_Dht_Nodes_Response *dht_nodes_response = tox_event_dht_nodes_response_alloc(user_data);
+
+ if (dht_nodes_response == nullptr) {
+ return;
+ }
+
+ const Tox_System *sys = tox_get_system(tox);
+
+ tox_event_dht_nodes_response_set_public_key(dht_nodes_response, public_key);
+ tox_event_dht_nodes_response_set_ip(dht_nodes_response, ip, ip_length, sys->mem);
+ tox_event_dht_nodes_response_set_port(dht_nodes_response, port);
+}
diff --git a/protocols/Tox/libtox/src/toxcore/events/events_alloc.c b/protocols/Tox/libtox/src/toxcore/events/events_alloc.c
index 24eebb3124..18405ea90d 100644
--- a/protocols/Tox/libtox/src/toxcore/events/events_alloc.c
+++ b/protocols/Tox/libtox/src/toxcore/events/events_alloc.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2022-2025 The TokTok team.
*/
#include "events_alloc.h"
diff --git a/protocols/Tox/libtox/src/toxcore/events/events_alloc.h b/protocols/Tox/libtox/src/toxcore/events/events_alloc.h
index a40db97052..d0343d9ccb 100644
--- a/protocols/Tox/libtox/src/toxcore/events/events_alloc.h
+++ b/protocols/Tox/libtox/src/toxcore/events/events_alloc.h
@@ -1,16 +1,13 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2022-2025 The TokTok team.
*/
#ifndef C_TOXCORE_TOXCORE_EVENTS_EVENTS_ALLOC_H
#define C_TOXCORE_TOXCORE_EVENTS_EVENTS_ALLOC_H
#include "../attributes.h"
-#include "../bin_pack.h"
-#include "../bin_unpack.h"
#include "../mem.h"
#include "../tox.h"
-#include "../tox_event.h"
#include "../tox_events.h"
#include "../tox_private.h"
@@ -38,7 +35,7 @@ tox_conference_message_cb tox_events_handle_conference_message;
tox_conference_peer_list_changed_cb tox_events_handle_conference_peer_list_changed;
tox_conference_peer_name_cb tox_events_handle_conference_peer_name;
tox_conference_title_cb tox_events_handle_conference_title;
-tox_dht_get_nodes_response_cb tox_events_handle_dht_get_nodes_response;
+tox_dht_nodes_response_cb tox_events_handle_dht_nodes_response;
tox_file_chunk_request_cb tox_events_handle_file_chunk_request;
tox_file_recv_cb tox_events_handle_file_recv;
tox_file_recv_chunk_cb tox_events_handle_file_recv_chunk;
diff --git a/protocols/Tox/libtox/src/toxcore/events/file_chunk_request.c b/protocols/Tox/libtox/src/toxcore/events/file_chunk_request.c
index 4117ef3c4b..d59b7a5ba7 100644
--- a/protocols/Tox/libtox/src/toxcore/events/file_chunk_request.c
+++ b/protocols/Tox/libtox/src/toxcore/events/file_chunk_request.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -12,6 +12,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
/*****************************************************
@@ -162,7 +163,10 @@ static Tox_Event_File_Chunk_Request *tox_events_add_file_chunk_request(Tox_Event
event.type = TOX_EVENT_FILE_CHUNK_REQUEST;
event.data.file_chunk_request = file_chunk_request;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_file_chunk_request_free(file_chunk_request, mem);
+ return nullptr;
+ }
return file_chunk_request;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/file_recv.c b/protocols/Tox/libtox/src/toxcore/events/file_recv.c
index 45cec44b0d..6ba2fdecfd 100644
--- a/protocols/Tox/libtox/src/toxcore/events/file_recv.c
+++ b/protocols/Tox/libtox/src/toxcore/events/file_recv.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -14,6 +14,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
/*****************************************************
@@ -207,7 +208,10 @@ static Tox_Event_File_Recv *tox_events_add_file_recv(Tox_Events *events, const M
event.type = TOX_EVENT_FILE_RECV;
event.data.file_recv = file_recv;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_file_recv_free(file_recv, mem);
+ return nullptr;
+ }
return file_recv;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/file_recv_chunk.c b/protocols/Tox/libtox/src/toxcore/events/file_recv_chunk.c
index 2edf7c5a7b..cb4487e23c 100644
--- a/protocols/Tox/libtox/src/toxcore/events/file_recv_chunk.c
+++ b/protocols/Tox/libtox/src/toxcore/events/file_recv_chunk.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -14,6 +14,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
/*****************************************************
@@ -191,7 +192,10 @@ static Tox_Event_File_Recv_Chunk *tox_events_add_file_recv_chunk(Tox_Events *eve
event.type = TOX_EVENT_FILE_RECV_CHUNK;
event.data.file_recv_chunk = file_recv_chunk;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_file_recv_chunk_free(file_recv_chunk, mem);
+ return nullptr;
+ }
return file_recv_chunk;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/file_recv_control.c b/protocols/Tox/libtox/src/toxcore/events/file_recv_control.c
index 14a34aaf3b..72de182e72 100644
--- a/protocols/Tox/libtox/src/toxcore/events/file_recv_control.c
+++ b/protocols/Tox/libtox/src/toxcore/events/file_recv_control.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -12,6 +12,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
#include "../tox_pack.h"
#include "../tox_unpack.h"
@@ -148,7 +149,10 @@ static Tox_Event_File_Recv_Control *tox_events_add_file_recv_control(Tox_Events
event.type = TOX_EVENT_FILE_RECV_CONTROL;
event.data.file_recv_control = file_recv_control;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_file_recv_control_free(file_recv_control, mem);
+ return nullptr;
+ }
return file_recv_control;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_connection_status.c b/protocols/Tox/libtox/src/toxcore/events/friend_connection_status.c
index 330554b05e..d57980ddff 100644
--- a/protocols/Tox/libtox/src/toxcore/events/friend_connection_status.c
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_connection_status.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -12,6 +12,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
#include "../tox_pack.h"
#include "../tox_unpack.h"
@@ -132,7 +133,10 @@ static Tox_Event_Friend_Connection_Status *tox_events_add_friend_connection_stat
event.type = TOX_EVENT_FRIEND_CONNECTION_STATUS;
event.data.friend_connection_status = friend_connection_status;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_friend_connection_status_free(friend_connection_status, mem);
+ return nullptr;
+ }
return friend_connection_status;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_lossless_packet.c b/protocols/Tox/libtox/src/toxcore/events/friend_lossless_packet.c
index 17e8fad926..098c5ab006 100644
--- a/protocols/Tox/libtox/src/toxcore/events/friend_lossless_packet.c
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_lossless_packet.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -14,6 +14,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
/*****************************************************
@@ -159,7 +160,10 @@ static Tox_Event_Friend_Lossless_Packet *tox_events_add_friend_lossless_packet(T
event.type = TOX_EVENT_FRIEND_LOSSLESS_PACKET;
event.data.friend_lossless_packet = friend_lossless_packet;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_friend_lossless_packet_free(friend_lossless_packet, mem);
+ return nullptr;
+ }
return friend_lossless_packet;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_lossy_packet.c b/protocols/Tox/libtox/src/toxcore/events/friend_lossy_packet.c
index 6b2e9ed2b0..016fa5d25c 100644
--- a/protocols/Tox/libtox/src/toxcore/events/friend_lossy_packet.c
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_lossy_packet.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -14,6 +14,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
/*****************************************************
@@ -159,7 +160,10 @@ static Tox_Event_Friend_Lossy_Packet *tox_events_add_friend_lossy_packet(Tox_Eve
event.type = TOX_EVENT_FRIEND_LOSSY_PACKET;
event.data.friend_lossy_packet = friend_lossy_packet;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_friend_lossy_packet_free(friend_lossy_packet, mem);
+ return nullptr;
+ }
return friend_lossy_packet;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_message.c b/protocols/Tox/libtox/src/toxcore/events/friend_message.c
index befcc74a24..cedc3b588c 100644
--- a/protocols/Tox/libtox/src/toxcore/events/friend_message.c
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_message.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -14,6 +14,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
#include "../tox_pack.h"
#include "../tox_unpack.h"
@@ -177,7 +178,10 @@ static Tox_Event_Friend_Message *tox_events_add_friend_message(Tox_Events *event
event.type = TOX_EVENT_FRIEND_MESSAGE;
event.data.friend_message = friend_message;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_friend_message_free(friend_message, mem);
+ return nullptr;
+ }
return friend_message;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_name.c b/protocols/Tox/libtox/src/toxcore/events/friend_name.c
index dfa9b39608..9f8de0ce31 100644
--- a/protocols/Tox/libtox/src/toxcore/events/friend_name.c
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_name.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -14,6 +14,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
/*****************************************************
@@ -159,7 +160,10 @@ static Tox_Event_Friend_Name *tox_events_add_friend_name(Tox_Events *events, con
event.type = TOX_EVENT_FRIEND_NAME;
event.data.friend_name = friend_name;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_friend_name_free(friend_name, mem);
+ return nullptr;
+ }
return friend_name;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_read_receipt.c b/protocols/Tox/libtox/src/toxcore/events/friend_read_receipt.c
index e5f2f9db52..4ba426716e 100644
--- a/protocols/Tox/libtox/src/toxcore/events/friend_read_receipt.c
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_read_receipt.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -12,6 +12,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
/*****************************************************
@@ -130,7 +131,10 @@ static Tox_Event_Friend_Read_Receipt *tox_events_add_friend_read_receipt(Tox_Eve
event.type = TOX_EVENT_FRIEND_READ_RECEIPT;
event.data.friend_read_receipt = friend_read_receipt;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_friend_read_receipt_free(friend_read_receipt, mem);
+ return nullptr;
+ }
return friend_read_receipt;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_request.c b/protocols/Tox/libtox/src/toxcore/events/friend_request.c
index b492c15147..631c236bac 100644
--- a/protocols/Tox/libtox/src/toxcore/events/friend_request.c
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_request.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2022-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -13,6 +13,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
#include "../tox_private.h"
@@ -152,7 +153,10 @@ static Tox_Event_Friend_Request *tox_events_add_friend_request(Tox_Events *event
event.type = TOX_EVENT_FRIEND_REQUEST;
event.data.friend_request = friend_request;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_friend_request_free(friend_request, mem);
+ return nullptr;
+ }
return friend_request;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_status.c b/protocols/Tox/libtox/src/toxcore/events/friend_status.c
index 3d7499722b..209eed8bc5 100644
--- a/protocols/Tox/libtox/src/toxcore/events/friend_status.c
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_status.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -12,6 +12,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
#include "../tox_pack.h"
#include "../tox_unpack.h"
@@ -132,7 +133,10 @@ static Tox_Event_Friend_Status *tox_events_add_friend_status(Tox_Events *events,
event.type = TOX_EVENT_FRIEND_STATUS;
event.data.friend_status = friend_status;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_friend_status_free(friend_status, mem);
+ return nullptr;
+ }
return friend_status;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_status_message.c b/protocols/Tox/libtox/src/toxcore/events/friend_status_message.c
index ad0519911e..2c6d0fb02f 100644
--- a/protocols/Tox/libtox/src/toxcore/events/friend_status_message.c
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_status_message.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -14,6 +14,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
/*****************************************************
@@ -159,7 +160,10 @@ static Tox_Event_Friend_Status_Message *tox_events_add_friend_status_message(Tox
event.type = TOX_EVENT_FRIEND_STATUS_MESSAGE;
event.data.friend_status_message = friend_status_message;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_friend_status_message_free(friend_status_message, mem);
+ return nullptr;
+ }
return friend_status_message;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/friend_typing.c b/protocols/Tox/libtox/src/toxcore/events/friend_typing.c
index 692b07fb88..cb2cfac94d 100644
--- a/protocols/Tox/libtox/src/toxcore/events/friend_typing.c
+++ b/protocols/Tox/libtox/src/toxcore/events/friend_typing.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -12,6 +12,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
/*****************************************************
@@ -130,7 +131,10 @@ static Tox_Event_Friend_Typing *tox_events_add_friend_typing(Tox_Events *events,
event.type = TOX_EVENT_FRIEND_TYPING;
event.data.friend_typing = friend_typing;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_friend_typing_free(friend_typing, mem);
+ return nullptr;
+ }
return friend_typing;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_custom_packet.c b/protocols/Tox/libtox/src/toxcore/events/group_custom_packet.c
index a82e2c3a6c..337d601f04 100644
--- a/protocols/Tox/libtox/src/toxcore/events/group_custom_packet.c
+++ b/protocols/Tox/libtox/src/toxcore/events/group_custom_packet.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -14,6 +14,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
/*****************************************************
@@ -175,7 +176,10 @@ static Tox_Event_Group_Custom_Packet *tox_events_add_group_custom_packet(Tox_Eve
event.type = TOX_EVENT_GROUP_CUSTOM_PACKET;
event.data.group_custom_packet = group_custom_packet;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_group_custom_packet_free(group_custom_packet, mem);
+ return nullptr;
+ }
return group_custom_packet;
}
@@ -220,7 +224,7 @@ static Tox_Event_Group_Custom_Packet *tox_event_group_custom_packet_alloc(void *
*****************************************************/
void tox_events_handle_group_custom_packet(
- Tox *tox, uint32_t group_number, uint32_t peer_id, const uint8_t *data, size_t length,
+ Tox *tox, uint32_t group_number, uint32_t peer_id, const uint8_t *data, size_t data_length,
void *user_data)
{
Tox_Event_Group_Custom_Packet *group_custom_packet = tox_event_group_custom_packet_alloc(user_data);
@@ -231,5 +235,5 @@ void tox_events_handle_group_custom_packet(
tox_event_group_custom_packet_set_group_number(group_custom_packet, group_number);
tox_event_group_custom_packet_set_peer_id(group_custom_packet, peer_id);
- tox_event_group_custom_packet_set_data(group_custom_packet, data, length);
+ tox_event_group_custom_packet_set_data(group_custom_packet, data, data_length);
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_custom_private_packet.c b/protocols/Tox/libtox/src/toxcore/events/group_custom_private_packet.c
index 56282f0fb8..9408a8dc68 100644
--- a/protocols/Tox/libtox/src/toxcore/events/group_custom_private_packet.c
+++ b/protocols/Tox/libtox/src/toxcore/events/group_custom_private_packet.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -14,6 +14,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
/*****************************************************
@@ -175,7 +176,10 @@ static Tox_Event_Group_Custom_Private_Packet *tox_events_add_group_custom_privat
event.type = TOX_EVENT_GROUP_CUSTOM_PRIVATE_PACKET;
event.data.group_custom_private_packet = group_custom_private_packet;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_group_custom_private_packet_free(group_custom_private_packet, mem);
+ return nullptr;
+ }
return group_custom_private_packet;
}
@@ -220,7 +224,7 @@ static Tox_Event_Group_Custom_Private_Packet *tox_event_group_custom_private_pac
*****************************************************/
void tox_events_handle_group_custom_private_packet(
- Tox *tox, uint32_t group_number, uint32_t peer_id, const uint8_t *data, size_t length,
+ Tox *tox, uint32_t group_number, uint32_t peer_id, const uint8_t *data, size_t data_length,
void *user_data)
{
Tox_Event_Group_Custom_Private_Packet *group_custom_private_packet = tox_event_group_custom_private_packet_alloc(user_data);
@@ -231,5 +235,5 @@ void tox_events_handle_group_custom_private_packet(
tox_event_group_custom_private_packet_set_group_number(group_custom_private_packet, group_number);
tox_event_group_custom_private_packet_set_peer_id(group_custom_private_packet, peer_id);
- tox_event_group_custom_private_packet_set_data(group_custom_private_packet, data, length);
+ tox_event_group_custom_private_packet_set_data(group_custom_private_packet, data, data_length);
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_invite.c b/protocols/Tox/libtox/src/toxcore/events/group_invite.c
index 0691dcd1fe..3385b89ad5 100644
--- a/protocols/Tox/libtox/src/toxcore/events/group_invite.c
+++ b/protocols/Tox/libtox/src/toxcore/events/group_invite.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -14,6 +14,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
/*****************************************************
@@ -203,7 +204,10 @@ static Tox_Event_Group_Invite *tox_events_add_group_invite(Tox_Events *events, c
event.type = TOX_EVENT_GROUP_INVITE;
event.data.group_invite = group_invite;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_group_invite_free(group_invite, mem);
+ return nullptr;
+ }
return group_invite;
}
@@ -248,7 +252,7 @@ static Tox_Event_Group_Invite *tox_event_group_invite_alloc(void *user_data)
*****************************************************/
void tox_events_handle_group_invite(
- Tox *tox, uint32_t friend_number, const uint8_t *invite_data, size_t length, const uint8_t *group_name, size_t group_name_length,
+ Tox *tox, uint32_t friend_number, const uint8_t *invite_data, size_t invite_data_length, const uint8_t *group_name, size_t group_name_length,
void *user_data)
{
Tox_Event_Group_Invite *group_invite = tox_event_group_invite_alloc(user_data);
@@ -258,6 +262,6 @@ void tox_events_handle_group_invite(
}
tox_event_group_invite_set_friend_number(group_invite, friend_number);
- tox_event_group_invite_set_invite_data(group_invite, invite_data, length);
+ tox_event_group_invite_set_invite_data(group_invite, invite_data, invite_data_length);
tox_event_group_invite_set_group_name(group_invite, group_name, group_name_length);
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_join_fail.c b/protocols/Tox/libtox/src/toxcore/events/group_join_fail.c
index b85896858b..8fdefb77e4 100644
--- a/protocols/Tox/libtox/src/toxcore/events/group_join_fail.c
+++ b/protocols/Tox/libtox/src/toxcore/events/group_join_fail.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -12,6 +12,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
#include "../tox_pack.h"
#include "../tox_unpack.h"
@@ -132,7 +133,10 @@ static Tox_Event_Group_Join_Fail *tox_events_add_group_join_fail(Tox_Events *eve
event.type = TOX_EVENT_GROUP_JOIN_FAIL;
event.data.group_join_fail = group_join_fail;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_group_join_fail_free(group_join_fail, mem);
+ return nullptr;
+ }
return group_join_fail;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_message.c b/protocols/Tox/libtox/src/toxcore/events/group_message.c
index a200f84566..dfb2bc961a 100644
--- a/protocols/Tox/libtox/src/toxcore/events/group_message.c
+++ b/protocols/Tox/libtox/src/toxcore/events/group_message.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -14,6 +14,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
#include "../tox_pack.h"
#include "../tox_unpack.h"
@@ -27,7 +28,7 @@
struct Tox_Event_Group_Message {
uint32_t group_number;
uint32_t peer_id;
- Tox_Message_Type type;
+ Tox_Message_Type message_type;
uint8_t *message;
uint32_t message_length;
uint32_t message_id;
@@ -60,16 +61,16 @@ uint32_t tox_event_group_message_get_peer_id(const Tox_Event_Group_Message *grou
}
non_null()
-static void tox_event_group_message_set_type(Tox_Event_Group_Message *group_message,
- Tox_Message_Type type)
+static void tox_event_group_message_set_message_type(Tox_Event_Group_Message *group_message,
+ Tox_Message_Type message_type)
{
assert(group_message != nullptr);
- group_message->type = type;
+ group_message->message_type = message_type;
}
-Tox_Message_Type tox_event_group_message_get_type(const Tox_Event_Group_Message *group_message)
+Tox_Message_Type tox_event_group_message_get_message_type(const Tox_Event_Group_Message *group_message)
{
assert(group_message != nullptr);
- return group_message->type;
+ return group_message->message_type;
}
non_null(1) nullable(2)
@@ -143,7 +144,7 @@ bool tox_event_group_message_pack(
return bin_pack_array(bp, 5)
&& bin_pack_u32(bp, event->group_number)
&& bin_pack_u32(bp, event->peer_id)
- && tox_message_type_pack(event->type, bp)
+ && tox_message_type_pack(event->message_type, bp)
&& bin_pack_bin(bp, event->message, event->message_length)
&& bin_pack_u32(bp, event->message_id);
}
@@ -159,7 +160,7 @@ static bool tox_event_group_message_unpack_into(
return bin_unpack_u32(bu, &event->group_number)
&& bin_unpack_u32(bu, &event->peer_id)
- && tox_message_type_unpack(&event->type, bu)
+ && tox_message_type_unpack(&event->message_type, bu)
&& bin_unpack_bin(bu, &event->message, &event->message_length)
&& bin_unpack_u32(bu, &event->message_id);
}
@@ -209,7 +210,10 @@ static Tox_Event_Group_Message *tox_events_add_group_message(Tox_Events *events,
event.type = TOX_EVENT_GROUP_MESSAGE;
event.data.group_message = group_message;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_group_message_free(group_message, mem);
+ return nullptr;
+ }
return group_message;
}
@@ -254,7 +258,7 @@ static Tox_Event_Group_Message *tox_event_group_message_alloc(void *user_data)
*****************************************************/
void tox_events_handle_group_message(
- Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Message_Type type, const uint8_t *message, size_t length, uint32_t message_id,
+ Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Message_Type message_type, const uint8_t *message, size_t message_length, uint32_t message_id,
void *user_data)
{
Tox_Event_Group_Message *group_message = tox_event_group_message_alloc(user_data);
@@ -265,7 +269,7 @@ void tox_events_handle_group_message(
tox_event_group_message_set_group_number(group_message, group_number);
tox_event_group_message_set_peer_id(group_message, peer_id);
- tox_event_group_message_set_type(group_message, type);
- tox_event_group_message_set_message(group_message, message, length);
+ tox_event_group_message_set_message_type(group_message, message_type);
+ tox_event_group_message_set_message(group_message, message, message_length);
tox_event_group_message_set_message_id(group_message, message_id);
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_moderation.c b/protocols/Tox/libtox/src/toxcore/events/group_moderation.c
index ba510d5b2a..9e2b87e6c2 100644
--- a/protocols/Tox/libtox/src/toxcore/events/group_moderation.c
+++ b/protocols/Tox/libtox/src/toxcore/events/group_moderation.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -12,6 +12,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
#include "../tox_pack.h"
#include "../tox_unpack.h"
@@ -164,7 +165,10 @@ static Tox_Event_Group_Moderation *tox_events_add_group_moderation(Tox_Events *e
event.type = TOX_EVENT_GROUP_MODERATION;
event.data.group_moderation = group_moderation;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_group_moderation_free(group_moderation, mem);
+ return nullptr;
+ }
return group_moderation;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_password.c b/protocols/Tox/libtox/src/toxcore/events/group_password.c
index ad6e86b9d3..33b64a0a8b 100644
--- a/protocols/Tox/libtox/src/toxcore/events/group_password.c
+++ b/protocols/Tox/libtox/src/toxcore/events/group_password.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -14,6 +14,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
/*****************************************************
@@ -159,7 +160,10 @@ static Tox_Event_Group_Password *tox_events_add_group_password(Tox_Events *event
event.type = TOX_EVENT_GROUP_PASSWORD;
event.data.group_password = group_password;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_group_password_free(group_password, mem);
+ return nullptr;
+ }
return group_password;
}
@@ -204,7 +208,7 @@ static Tox_Event_Group_Password *tox_event_group_password_alloc(void *user_data)
*****************************************************/
void tox_events_handle_group_password(
- Tox *tox, uint32_t group_number, const uint8_t *password, size_t length,
+ Tox *tox, uint32_t group_number, const uint8_t *password, size_t password_length,
void *user_data)
{
Tox_Event_Group_Password *group_password = tox_event_group_password_alloc(user_data);
@@ -214,5 +218,5 @@ void tox_events_handle_group_password(
}
tox_event_group_password_set_group_number(group_password, group_number);
- tox_event_group_password_set_password(group_password, password, length);
+ tox_event_group_password_set_password(group_password, password, password_length);
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_peer_exit.c b/protocols/Tox/libtox/src/toxcore/events/group_peer_exit.c
index 16d1eba7a6..a09f96b7d0 100644
--- a/protocols/Tox/libtox/src/toxcore/events/group_peer_exit.c
+++ b/protocols/Tox/libtox/src/toxcore/events/group_peer_exit.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -14,6 +14,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
#include "../tox_pack.h"
#include "../tox_unpack.h"
@@ -237,7 +238,10 @@ static Tox_Event_Group_Peer_Exit *tox_events_add_group_peer_exit(Tox_Events *eve
event.type = TOX_EVENT_GROUP_PEER_EXIT;
event.data.group_peer_exit = group_peer_exit;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_group_peer_exit_free(group_peer_exit, mem);
+ return nullptr;
+ }
return group_peer_exit;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_peer_join.c b/protocols/Tox/libtox/src/toxcore/events/group_peer_join.c
index af0d006e87..d450564429 100644
--- a/protocols/Tox/libtox/src/toxcore/events/group_peer_join.c
+++ b/protocols/Tox/libtox/src/toxcore/events/group_peer_join.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -12,6 +12,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
/*****************************************************
@@ -130,7 +131,10 @@ static Tox_Event_Group_Peer_Join *tox_events_add_group_peer_join(Tox_Events *eve
event.type = TOX_EVENT_GROUP_PEER_JOIN;
event.data.group_peer_join = group_peer_join;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_group_peer_join_free(group_peer_join, mem);
+ return nullptr;
+ }
return group_peer_join;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_peer_limit.c b/protocols/Tox/libtox/src/toxcore/events/group_peer_limit.c
index 5e2e23558c..65c44e7a19 100644
--- a/protocols/Tox/libtox/src/toxcore/events/group_peer_limit.c
+++ b/protocols/Tox/libtox/src/toxcore/events/group_peer_limit.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -12,6 +12,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
/*****************************************************
@@ -130,7 +131,10 @@ static Tox_Event_Group_Peer_Limit *tox_events_add_group_peer_limit(Tox_Events *e
event.type = TOX_EVENT_GROUP_PEER_LIMIT;
event.data.group_peer_limit = group_peer_limit;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_group_peer_limit_free(group_peer_limit, mem);
+ return nullptr;
+ }
return group_peer_limit;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_peer_name.c b/protocols/Tox/libtox/src/toxcore/events/group_peer_name.c
index f8273e94b4..d653ff5531 100644
--- a/protocols/Tox/libtox/src/toxcore/events/group_peer_name.c
+++ b/protocols/Tox/libtox/src/toxcore/events/group_peer_name.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -14,6 +14,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
/*****************************************************
@@ -175,7 +176,10 @@ static Tox_Event_Group_Peer_Name *tox_events_add_group_peer_name(Tox_Events *eve
event.type = TOX_EVENT_GROUP_PEER_NAME;
event.data.group_peer_name = group_peer_name;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_group_peer_name_free(group_peer_name, mem);
+ return nullptr;
+ }
return group_peer_name;
}
@@ -220,7 +224,7 @@ static Tox_Event_Group_Peer_Name *tox_event_group_peer_name_alloc(void *user_dat
*****************************************************/
void tox_events_handle_group_peer_name(
- Tox *tox, uint32_t group_number, uint32_t peer_id, const uint8_t *name, size_t length,
+ Tox *tox, uint32_t group_number, uint32_t peer_id, const uint8_t *name, size_t name_length,
void *user_data)
{
Tox_Event_Group_Peer_Name *group_peer_name = tox_event_group_peer_name_alloc(user_data);
@@ -231,5 +235,5 @@ void tox_events_handle_group_peer_name(
tox_event_group_peer_name_set_group_number(group_peer_name, group_number);
tox_event_group_peer_name_set_peer_id(group_peer_name, peer_id);
- tox_event_group_peer_name_set_name(group_peer_name, name, length);
+ tox_event_group_peer_name_set_name(group_peer_name, name, name_length);
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_peer_status.c b/protocols/Tox/libtox/src/toxcore/events/group_peer_status.c
index 4165d90ec2..3dc56df5ff 100644
--- a/protocols/Tox/libtox/src/toxcore/events/group_peer_status.c
+++ b/protocols/Tox/libtox/src/toxcore/events/group_peer_status.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -12,6 +12,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
#include "../tox_pack.h"
#include "../tox_unpack.h"
@@ -148,7 +149,10 @@ static Tox_Event_Group_Peer_Status *tox_events_add_group_peer_status(Tox_Events
event.type = TOX_EVENT_GROUP_PEER_STATUS;
event.data.group_peer_status = group_peer_status;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_group_peer_status_free(group_peer_status, mem);
+ return nullptr;
+ }
return group_peer_status;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_privacy_state.c b/protocols/Tox/libtox/src/toxcore/events/group_privacy_state.c
index 1c683c255c..fde9e1d79c 100644
--- a/protocols/Tox/libtox/src/toxcore/events/group_privacy_state.c
+++ b/protocols/Tox/libtox/src/toxcore/events/group_privacy_state.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -12,6 +12,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
#include "../tox_pack.h"
#include "../tox_unpack.h"
@@ -132,7 +133,10 @@ static Tox_Event_Group_Privacy_State *tox_events_add_group_privacy_state(Tox_Eve
event.type = TOX_EVENT_GROUP_PRIVACY_STATE;
event.data.group_privacy_state = group_privacy_state;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_group_privacy_state_free(group_privacy_state, mem);
+ return nullptr;
+ }
return group_privacy_state;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_private_message.c b/protocols/Tox/libtox/src/toxcore/events/group_private_message.c
index 648f707880..24dd1db670 100644
--- a/protocols/Tox/libtox/src/toxcore/events/group_private_message.c
+++ b/protocols/Tox/libtox/src/toxcore/events/group_private_message.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -14,6 +14,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
#include "../tox_pack.h"
#include "../tox_unpack.h"
@@ -27,9 +28,10 @@
struct Tox_Event_Group_Private_Message {
uint32_t group_number;
uint32_t peer_id;
- Tox_Message_Type type;
+ Tox_Message_Type message_type;
uint8_t *message;
uint32_t message_length;
+ uint32_t message_id;
};
non_null()
@@ -59,16 +61,16 @@ uint32_t tox_event_group_private_message_get_peer_id(const Tox_Event_Group_Priva
}
non_null()
-static void tox_event_group_private_message_set_type(Tox_Event_Group_Private_Message *group_private_message,
- Tox_Message_Type type)
+static void tox_event_group_private_message_set_message_type(Tox_Event_Group_Private_Message *group_private_message,
+ Tox_Message_Type message_type)
{
assert(group_private_message != nullptr);
- group_private_message->type = type;
+ group_private_message->message_type = message_type;
}
-Tox_Message_Type tox_event_group_private_message_get_type(const Tox_Event_Group_Private_Message *group_private_message)
+Tox_Message_Type tox_event_group_private_message_get_message_type(const Tox_Event_Group_Private_Message *group_private_message)
{
assert(group_private_message != nullptr);
- return group_private_message->type;
+ return group_private_message->message_type;
}
non_null(1) nullable(2)
@@ -111,6 +113,19 @@ const uint8_t *tox_event_group_private_message_get_message(const Tox_Event_Group
}
non_null()
+static void tox_event_group_private_message_set_message_id(Tox_Event_Group_Private_Message *group_private_message,
+ uint32_t message_id)
+{
+ assert(group_private_message != nullptr);
+ group_private_message->message_id = message_id;
+}
+uint32_t tox_event_group_private_message_get_message_id(const Tox_Event_Group_Private_Message *group_private_message)
+{
+ assert(group_private_message != nullptr);
+ return group_private_message->message_id;
+}
+
+non_null()
static void tox_event_group_private_message_construct(Tox_Event_Group_Private_Message *group_private_message)
{
*group_private_message = (Tox_Event_Group_Private_Message) {
@@ -126,11 +141,12 @@ static void tox_event_group_private_message_destruct(Tox_Event_Group_Private_Mes
bool tox_event_group_private_message_pack(
const Tox_Event_Group_Private_Message *event, Bin_Pack *bp)
{
- return bin_pack_array(bp, 4)
+ return bin_pack_array(bp, 5)
&& bin_pack_u32(bp, event->group_number)
&& bin_pack_u32(bp, event->peer_id)
- && tox_message_type_pack(event->type, bp)
- && bin_pack_bin(bp, event->message, event->message_length);
+ && tox_message_type_pack(event->message_type, bp)
+ && bin_pack_bin(bp, event->message, event->message_length)
+ && bin_pack_u32(bp, event->message_id);
}
non_null()
@@ -138,14 +154,15 @@ static bool tox_event_group_private_message_unpack_into(
Tox_Event_Group_Private_Message *event, Bin_Unpack *bu)
{
assert(event != nullptr);
- if (!bin_unpack_array_fixed(bu, 4, nullptr)) {
+ if (!bin_unpack_array_fixed(bu, 5, nullptr)) {
return false;
}
return bin_unpack_u32(bu, &event->group_number)
&& bin_unpack_u32(bu, &event->peer_id)
- && tox_message_type_unpack(&event->type, bu)
- && bin_unpack_bin(bu, &event->message, &event->message_length);
+ && tox_message_type_unpack(&event->message_type, bu)
+ && bin_unpack_bin(bu, &event->message, &event->message_length)
+ && bin_unpack_u32(bu, &event->message_id);
}
/*****************************************************
@@ -193,7 +210,10 @@ static Tox_Event_Group_Private_Message *tox_events_add_group_private_message(Tox
event.type = TOX_EVENT_GROUP_PRIVATE_MESSAGE;
event.data.group_private_message = group_private_message;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_group_private_message_free(group_private_message, mem);
+ return nullptr;
+ }
return group_private_message;
}
@@ -238,7 +258,7 @@ static Tox_Event_Group_Private_Message *tox_event_group_private_message_alloc(vo
*****************************************************/
void tox_events_handle_group_private_message(
- Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Message_Type type, const uint8_t *message, size_t length,
+ Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Message_Type message_type, const uint8_t *message, size_t message_length, uint32_t message_id,
void *user_data)
{
Tox_Event_Group_Private_Message *group_private_message = tox_event_group_private_message_alloc(user_data);
@@ -249,6 +269,7 @@ void tox_events_handle_group_private_message(
tox_event_group_private_message_set_group_number(group_private_message, group_number);
tox_event_group_private_message_set_peer_id(group_private_message, peer_id);
- tox_event_group_private_message_set_type(group_private_message, type);
- tox_event_group_private_message_set_message(group_private_message, message, length);
+ tox_event_group_private_message_set_message_type(group_private_message, message_type);
+ tox_event_group_private_message_set_message(group_private_message, message, message_length);
+ tox_event_group_private_message_set_message_id(group_private_message, message_id);
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_self_join.c b/protocols/Tox/libtox/src/toxcore/events/group_self_join.c
index 0745e975f8..07038632aa 100644
--- a/protocols/Tox/libtox/src/toxcore/events/group_self_join.c
+++ b/protocols/Tox/libtox/src/toxcore/events/group_self_join.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -12,6 +12,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
/*****************************************************
@@ -109,7 +110,10 @@ static Tox_Event_Group_Self_Join *tox_events_add_group_self_join(Tox_Events *eve
event.type = TOX_EVENT_GROUP_SELF_JOIN;
event.data.group_self_join = group_self_join;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_group_self_join_free(group_self_join, mem);
+ return nullptr;
+ }
return group_self_join;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_topic.c b/protocols/Tox/libtox/src/toxcore/events/group_topic.c
index 23cdd5d354..f9d1a7b953 100644
--- a/protocols/Tox/libtox/src/toxcore/events/group_topic.c
+++ b/protocols/Tox/libtox/src/toxcore/events/group_topic.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -14,6 +14,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
/*****************************************************
@@ -175,7 +176,10 @@ static Tox_Event_Group_Topic *tox_events_add_group_topic(Tox_Events *events, con
event.type = TOX_EVENT_GROUP_TOPIC;
event.data.group_topic = group_topic;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_group_topic_free(group_topic, mem);
+ return nullptr;
+ }
return group_topic;
}
@@ -220,7 +224,7 @@ static Tox_Event_Group_Topic *tox_event_group_topic_alloc(void *user_data)
*****************************************************/
void tox_events_handle_group_topic(
- Tox *tox, uint32_t group_number, uint32_t peer_id, const uint8_t *topic, size_t length,
+ Tox *tox, uint32_t group_number, uint32_t peer_id, const uint8_t *topic, size_t topic_length,
void *user_data)
{
Tox_Event_Group_Topic *group_topic = tox_event_group_topic_alloc(user_data);
@@ -231,5 +235,5 @@ void tox_events_handle_group_topic(
tox_event_group_topic_set_group_number(group_topic, group_number);
tox_event_group_topic_set_peer_id(group_topic, peer_id);
- tox_event_group_topic_set_topic(group_topic, topic, length);
+ tox_event_group_topic_set_topic(group_topic, topic, topic_length);
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_topic_lock.c b/protocols/Tox/libtox/src/toxcore/events/group_topic_lock.c
index 36fb49393a..a21acea293 100644
--- a/protocols/Tox/libtox/src/toxcore/events/group_topic_lock.c
+++ b/protocols/Tox/libtox/src/toxcore/events/group_topic_lock.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -12,6 +12,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
#include "../tox_pack.h"
#include "../tox_unpack.h"
@@ -132,7 +133,10 @@ static Tox_Event_Group_Topic_Lock *tox_events_add_group_topic_lock(Tox_Events *e
event.type = TOX_EVENT_GROUP_TOPIC_LOCK;
event.data.group_topic_lock = group_topic_lock;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_group_topic_lock_free(group_topic_lock, mem);
+ return nullptr;
+ }
return group_topic_lock;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/group_voice_state.c b/protocols/Tox/libtox/src/toxcore/events/group_voice_state.c
index fba0300389..ebc78dca21 100644
--- a/protocols/Tox/libtox/src/toxcore/events/group_voice_state.c
+++ b/protocols/Tox/libtox/src/toxcore/events/group_voice_state.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -12,6 +12,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
#include "../tox_pack.h"
#include "../tox_unpack.h"
@@ -132,7 +133,10 @@ static Tox_Event_Group_Voice_State *tox_events_add_group_voice_state(Tox_Events
event.type = TOX_EVENT_GROUP_VOICE_STATE;
event.data.group_voice_state = group_voice_state;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_group_voice_state_free(group_voice_state, mem);
+ return nullptr;
+ }
return group_voice_state;
}
diff --git a/protocols/Tox/libtox/src/toxcore/events/self_connection_status.c b/protocols/Tox/libtox/src/toxcore/events/self_connection_status.c
index 8d8bc803ea..f66daff544 100644
--- a/protocols/Tox/libtox/src/toxcore/events/self_connection_status.c
+++ b/protocols/Tox/libtox/src/toxcore/events/self_connection_status.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2023-2024 The TokTok team.
+ * Copyright © 2023-2025 The TokTok team.
*/
#include "events_alloc.h"
@@ -12,6 +12,7 @@
#include "../ccompat.h"
#include "../mem.h"
#include "../tox.h"
+#include "../tox_event.h"
#include "../tox_events.h"
#include "../tox_pack.h"
#include "../tox_unpack.h"
@@ -111,7 +112,10 @@ static Tox_Event_Self_Connection_Status *tox_events_add_self_connection_status(T
event.type = TOX_EVENT_SELF_CONNECTION_STATUS;
event.data.self_connection_status = self_connection_status;
- tox_events_add(events, &event);
+ if (!tox_events_add(events, &event)) {
+ tox_event_self_connection_status_free(self_connection_status, mem);
+ return nullptr;
+ }
return self_connection_status;
}
diff --git a/protocols/Tox/libtox/src/toxcore/forwarding.c b/protocols/Tox/libtox/src/toxcore/forwarding.c
index 18ff3203fc..6d608b5e7b 100644
--- a/protocols/Tox/libtox/src/toxcore/forwarding.c
+++ b/protocols/Tox/libtox/src/toxcore/forwarding.c
@@ -1,11 +1,10 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2019-2022 The TokTok team.
+ * Copyright © 2019-2025 The TokTok team.
*/
#include "forwarding.h"
#include <assert.h>
-#include <stdlib.h>
#include <string.h>
#include "DHT.h"
@@ -13,12 +12,14 @@
#include "ccompat.h"
#include "crypto_core.h"
#include "logger.h"
+#include "mem.h"
#include "mono_time.h"
#include "network.h"
#include "timed_auth.h"
struct Forwarding {
const Logger *log;
+ const Memory *mem;
const Random *rng;
DHT *dht;
const Mono_Time *mono_time;
@@ -357,19 +358,20 @@ void set_callback_forward_reply(Forwarding *forwarding, forward_reply_cb *functi
forwarding->forward_reply_callback_object = object;
}
-Forwarding *new_forwarding(const Logger *log, const Random *rng, const Mono_Time *mono_time, DHT *dht)
+Forwarding *new_forwarding(const Logger *log, const Memory *mem, const Random *rng, const Mono_Time *mono_time, DHT *dht)
{
if (log == nullptr || mono_time == nullptr || dht == nullptr) {
return nullptr;
}
- Forwarding *forwarding = (Forwarding *)calloc(1, sizeof(Forwarding));
+ Forwarding *forwarding = (Forwarding *)mem_alloc(mem, sizeof(Forwarding));
if (forwarding == nullptr) {
return nullptr;
}
forwarding->log = log;
+ forwarding->mem = mem;
forwarding->rng = rng;
forwarding->mono_time = mono_time;
forwarding->dht = dht;
@@ -396,5 +398,5 @@ void kill_forwarding(Forwarding *forwarding)
crypto_memzero(forwarding->hmac_key, CRYPTO_HMAC_KEY_SIZE);
- free(forwarding);
+ mem_delete(forwarding->mem, forwarding);
}
diff --git a/protocols/Tox/libtox/src/toxcore/forwarding.h b/protocols/Tox/libtox/src/toxcore/forwarding.h
index bd0ef09e1c..b4431f57af 100644
--- a/protocols/Tox/libtox/src/toxcore/forwarding.h
+++ b/protocols/Tox/libtox/src/toxcore/forwarding.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2019-2022 The TokTok team.
+ * Copyright © 2019-2025 The TokTok team.
*/
#ifndef C_TOXCORE_TOXCORE_FORWARDING_H
@@ -9,6 +9,7 @@
#include "attributes.h"
#include "crypto_core.h"
#include "logger.h"
+#include "mem.h"
#include "mono_time.h"
#include "network.h"
@@ -116,7 +117,7 @@ non_null(1) nullable(2, 3)
void set_callback_forward_reply(Forwarding *forwarding, forward_reply_cb *function, void *object);
non_null()
-Forwarding *new_forwarding(const Logger *log, const Random *rng, const Mono_Time *mono_time, DHT *dht);
+Forwarding *new_forwarding(const Logger *log, const Memory *mem, const Random *rng, const Mono_Time *mono_time, DHT *dht);
nullable(1)
void kill_forwarding(Forwarding *forwarding);
diff --git a/protocols/Tox/libtox/src/toxcore/friend_connection.c b/protocols/Tox/libtox/src/toxcore/friend_connection.c
index 33bfa40d34..78c6d4acdc 100644
--- a/protocols/Tox/libtox/src/toxcore/friend_connection.c
+++ b/protocols/Tox/libtox/src/toxcore/friend_connection.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2014 Tox project.
*/
@@ -8,7 +8,6 @@
*/
#include "friend_connection.h"
-#include <stdlib.h>
#include <string.h>
#include "DHT.h"
@@ -18,6 +17,7 @@
#include "ccompat.h"
#include "crypto_core.h"
#include "logger.h"
+#include "mem.h"
#include "mono_time.h"
#include "net_crypto.h"
#include "network.h"
@@ -69,6 +69,7 @@ static const Friend_Conn empty_friend_conn = {0};
struct Friend_Connections {
const Mono_Time *mono_time;
+ const Memory *mem;
const Logger *logger;
Net_Crypto *net_crypto;
DHT *dht;
@@ -126,12 +127,12 @@ non_null()
static bool realloc_friendconns(Friend_Connections *fr_c, uint32_t num)
{
if (num == 0) {
- free(fr_c->conns);
+ mem_delete(fr_c->mem, fr_c->conns);
fr_c->conns = nullptr;
return true;
}
- Friend_Conn *newgroup_cons = (Friend_Conn *)realloc(fr_c->conns, num * sizeof(Friend_Conn));
+ Friend_Conn *newgroup_cons = (Friend_Conn *)mem_vrealloc(fr_c->mem, fr_c->conns, num, sizeof(Friend_Conn));
if (newgroup_cons == nullptr) {
return false;
@@ -875,6 +876,10 @@ void set_friend_request_callback(Friend_Connections *fr_c, fr_request_cb *fr_req
int send_friend_request_packet(Friend_Connections *fr_c, int friendcon_id, uint32_t nospam_num, const uint8_t *data,
uint16_t length)
{
+ // TODO(Jfreegman): This max packet size is too large to be handled by receiving clients
+ // when sent via the onion. We currently limit the length at a higher level, but
+ // this bounds check should be fixed to represent the max size of a packet that
+ // the onion client can handle.
if (1 + sizeof(nospam_num) + length > ONION_CLIENT_MAX_DATA_SIZE || length == 0) {
return -1;
}
@@ -908,14 +913,14 @@ int send_friend_request_packet(Friend_Connections *fr_c, int friendcon_id, uint3
/** Create new friend_connections instance. */
Friend_Connections *new_friend_connections(
- const Logger *logger, const Mono_Time *mono_time, const Network *ns,
+ const Logger *logger, const Memory *mem, const Mono_Time *mono_time, const Network *ns,
Onion_Client *onion_c, bool local_discovery_enabled)
{
if (onion_c == nullptr) {
return nullptr;
}
- Friend_Connections *const temp = (Friend_Connections *)calloc(1, sizeof(Friend_Connections));
+ Friend_Connections *const temp = (Friend_Connections *)mem_alloc(mem, sizeof(Friend_Connections));
if (temp == nullptr) {
return nullptr;
@@ -924,7 +929,7 @@ Friend_Connections *new_friend_connections(
temp->local_discovery_enabled = local_discovery_enabled;
if (temp->local_discovery_enabled) {
- temp->broadcast = lan_discovery_init(ns);
+ temp->broadcast = lan_discovery_init(mem, ns);
if (temp->broadcast == nullptr) {
LOGGER_ERROR(logger, "could not initialise LAN discovery");
@@ -933,6 +938,7 @@ Friend_Connections *new_friend_connections(
}
temp->mono_time = mono_time;
+ temp->mem = mem;
temp->logger = logger;
temp->dht = onion_get_dht(onion_c);
temp->net_crypto = onion_get_net_crypto(onion_c);
@@ -1032,6 +1038,11 @@ void kill_friend_connections(Friend_Connections *fr_c)
kill_friend_connection(fr_c, i);
}
+ // there might be allocated NONE connections
+ if (fr_c->conns != nullptr) {
+ mem_delete(fr_c->mem, fr_c->conns);
+ }
+
lan_discovery_kill(fr_c->broadcast);
- free(fr_c);
+ mem_delete(fr_c->mem, fr_c);
}
diff --git a/protocols/Tox/libtox/src/toxcore/friend_connection.h b/protocols/Tox/libtox/src/toxcore/friend_connection.h
index bbd4454729..8c3c84f1c5 100644
--- a/protocols/Tox/libtox/src/toxcore/friend_connection.h
+++ b/protocols/Tox/libtox/src/toxcore/friend_connection.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2014 Tox project.
*/
@@ -12,9 +12,9 @@
#include <stdint.h>
#include "DHT.h"
-#include "LAN_discovery.h"
#include "attributes.h"
#include "logger.h"
+#include "mem.h"
#include "mono_time.h"
#include "net_crypto.h"
#include "network.h"
@@ -161,7 +161,7 @@ void set_friend_request_callback(Friend_Connections *fr_c, fr_request_cb *fr_req
/** Create new friend_connections instance. */
non_null()
Friend_Connections *new_friend_connections(
- const Logger *logger, const Mono_Time *mono_time, const Network *ns,
+ const Logger *logger, const Memory *mem, const Mono_Time *mono_time, const Network *ns,
Onion_Client *onion_c, bool local_discovery_enabled);
/** main friend_connections loop. */
diff --git a/protocols/Tox/libtox/src/toxcore/friend_requests.c b/protocols/Tox/libtox/src/toxcore/friend_requests.c
index 8b915449cd..e28ce7df85 100644
--- a/protocols/Tox/libtox/src/toxcore/friend_requests.c
+++ b/protocols/Tox/libtox/src/toxcore/friend_requests.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -8,18 +8,22 @@
*/
#include "friend_requests.h"
-#include <stdlib.h>
#include <string.h>
#include "attributes.h"
#include "ccompat.h"
#include "crypto_core.h"
#include "friend_connection.h"
+#include "mem.h"
#include "network.h"
#include "onion.h"
#include "onion_announce.h"
#include "onion_client.h"
+static_assert(ONION_CLIENT_MAX_DATA_SIZE <= MAX_DATA_REQUEST_SIZE, "ONION_CLIENT_MAX_DATA_SIZE is too big");
+static_assert(MAX_DATA_REQUEST_SIZE <= ONION_MAX_DATA_SIZE, "MAX_DATA_REQUEST_SIZE is too big");
+static_assert(SIZE_IPPORT <= ONION_SEND_BASE, "IP_Port does not fit in the onion packet");
+
/**
* NOTE: The following is just a temporary fix for the multiple friend requests received at the same time problem.
* TODO(irungentoo): Make this better (This will most likely tie in with the way we will handle spam).
@@ -32,6 +36,8 @@ struct Received_Requests {
};
struct Friend_Requests {
+ const Memory *mem;
+
uint32_t nospam;
fr_friend_request_cb *handle_friendrequest;
uint8_t handle_friendrequest_isset;
@@ -164,12 +170,24 @@ void friendreq_init(Friend_Requests *fr, Friend_Connections *fr_c)
set_friend_request_callback(fr_c, &friendreq_handlepacket, fr);
}
-Friend_Requests *friendreq_new(void)
+Friend_Requests *friendreq_new(const Memory *mem)
{
- return (Friend_Requests *)calloc(1, sizeof(Friend_Requests));
+ Friend_Requests *fr = (Friend_Requests *)mem_alloc(mem, sizeof(Friend_Requests));
+
+ if (fr == nullptr) {
+ return nullptr;
+ }
+
+ fr->mem = mem;
+
+ return fr;
}
void friendreq_kill(Friend_Requests *fr)
{
- free(fr);
+ if (fr == nullptr) {
+ return;
+ }
+
+ mem_delete(fr->mem, fr);
}
diff --git a/protocols/Tox/libtox/src/toxcore/friend_requests.h b/protocols/Tox/libtox/src/toxcore/friend_requests.h
index a78a570dfa..c7bae81fb8 100644
--- a/protocols/Tox/libtox/src/toxcore/friend_requests.h
+++ b/protocols/Tox/libtox/src/toxcore/friend_requests.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2014 Tox project.
*/
@@ -13,8 +13,10 @@
#include "attributes.h"
#include "friend_connection.h"
+#include "mem.h"
-#define MAX_FRIEND_REQUEST_DATA_SIZE (ONION_CLIENT_MAX_DATA_SIZE - (1 + sizeof(uint32_t)))
+// TODO(Jfreegman): This should be the maximum size that an onion client can handle.
+#define MAX_FRIEND_REQUEST_DATA_SIZE (ONION_CLIENT_MAX_DATA_SIZE - 100)
typedef struct Friend_Requests Friend_Requests;
@@ -49,7 +51,8 @@ void set_filter_function(Friend_Requests *fr, filter_function_cb *function, void
non_null()
void friendreq_init(Friend_Requests *fr, Friend_Connections *fr_c);
-Friend_Requests *friendreq_new(void);
+non_null()
+Friend_Requests *friendreq_new(const Memory *mem);
nullable(1)
void friendreq_kill(Friend_Requests *fr);
diff --git a/protocols/Tox/libtox/src/toxcore/group.c b/protocols/Tox/libtox/src/toxcore/group.c
index 14e61e6ffc..dbc3876403 100644
--- a/protocols/Tox/libtox/src/toxcore/group.c
+++ b/protocols/Tox/libtox/src/toxcore/group.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2014 Tox project.
*/
@@ -9,7 +9,6 @@
#include "group.h"
#include <assert.h>
-#include <stdlib.h>
#include <string.h>
#include "DHT.h"
@@ -20,9 +19,11 @@
#include "friend_connection.h"
#include "group_common.h"
#include "logger.h"
+#include "mem.h"
#include "mono_time.h"
#include "net_crypto.h"
#include "network.h"
+#include "sort.h"
#include "state.h"
#include "util.h"
@@ -147,6 +148,7 @@ typedef struct Group_c {
} Group_c;
struct Group_Chats {
+ const Memory *mem;
const Mono_Time *mono_time;
Messenger *m;
@@ -246,19 +248,19 @@ static bool is_groupnumber_valid(const Group_Chats *g_c, uint32_t groupnumber)
/** @brief Set the size of the groupchat list to num.
*
- * @retval false if realloc fails.
+ * @retval false if mem_vrealloc fails.
* @retval true if it succeeds.
*/
non_null()
static bool realloc_conferences(Group_Chats *g_c, uint16_t num)
{
if (num == 0) {
- free(g_c->chats);
+ mem_delete(g_c->mem, g_c->chats);
g_c->chats = nullptr;
return true;
}
- Group_c *newgroup_chats = (Group_c *)realloc(g_c->chats, num * sizeof(Group_c));
+ Group_c *newgroup_chats = (Group_c *)mem_vrealloc(g_c->mem, g_c->chats, num, sizeof(Group_c));
if (newgroup_chats == nullptr) {
return false;
@@ -300,10 +302,10 @@ static int32_t create_group_chat(Group_Chats *g_c)
}
non_null()
-static void wipe_group_c(Group_c *g)
+static void wipe_group_c(const Memory *mem, Group_c *g)
{
- free(g->frozen);
- free(g->group);
+ mem_delete(mem, g->frozen);
+ mem_delete(mem, g->group);
crypto_memzero(g, sizeof(Group_c));
}
@@ -318,7 +320,7 @@ static bool wipe_group_chat(Group_Chats *g_c, uint32_t groupnumber)
return false;
}
- wipe_group_c(&g_c->chats[groupnumber]);
+ wipe_group_c(g_c->mem, &g_c->chats[groupnumber]);
uint16_t i;
@@ -667,7 +669,7 @@ static int get_frozen_index(const Group_c *g, uint16_t peer_number)
}
non_null()
-static bool delete_frozen(Group_c *g, uint32_t frozen_index)
+static bool delete_frozen(const Memory *mem, Group_c *g, uint32_t frozen_index)
{
if (frozen_index >= g->numfrozen) {
return false;
@@ -676,14 +678,14 @@ static bool delete_frozen(Group_c *g, uint32_t frozen_index)
--g->numfrozen;
if (g->numfrozen == 0) {
- free(g->frozen);
+ mem_delete(mem, g->frozen);
g->frozen = nullptr;
} else {
if (g->numfrozen != frozen_index) {
g->frozen[frozen_index] = g->frozen[g->numfrozen];
}
- Group_Peer *const frozen_temp = (Group_Peer *)realloc(g->frozen, g->numfrozen * sizeof(Group_Peer));
+ Group_Peer *const frozen_temp = (Group_Peer *)mem_vrealloc(mem, g->frozen, g->numfrozen, sizeof(Group_Peer));
if (frozen_temp == nullptr) {
return false;
@@ -724,7 +726,7 @@ static int note_peer_active(Group_Chats *g_c, uint32_t groupnumber, uint16_t pee
/* Now thaw the peer */
- Group_Peer *temp = (Group_Peer *)realloc(g->group, (g->numpeers + 1) * sizeof(Group_Peer));
+ Group_Peer *temp = (Group_Peer *)mem_vrealloc(g_c->mem, g->group, g->numpeers + 1, sizeof(Group_Peer));
if (temp == nullptr) {
return -1;
@@ -741,7 +743,7 @@ static int note_peer_active(Group_Chats *g_c, uint32_t groupnumber, uint16_t pee
++g->numpeers;
- delete_frozen(g, frozen_index);
+ delete_frozen(g_c->mem, g, frozen_index);
if (g_c->peer_list_changed_callback != nullptr) {
g_c->peer_list_changed_callback(g_c->m, groupnumber, userdata);
@@ -777,7 +779,7 @@ static void delete_any_peer_with_pk(Group_Chats *g_c, uint32_t groupnumber, cons
const int frozen_index = frozen_in_group(g, real_pk);
if (frozen_index >= 0) {
- delete_frozen(g, frozen_index);
+ delete_frozen(g_c->mem, g, frozen_index);
}
}
@@ -837,7 +839,7 @@ static int addpeer(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *real_p
delete_any_peer_with_pk(g_c, groupnumber, real_pk, userdata);
- Group_Peer *temp = (Group_Peer *)realloc(g->group, (g->numpeers + 1) * sizeof(Group_Peer));
+ Group_Peer *temp = (Group_Peer *)mem_vrealloc(g_c->mem, g->group, g->numpeers + 1, sizeof(Group_Peer));
if (temp == nullptr) {
return -1;
@@ -928,14 +930,14 @@ static bool delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void
void *peer_object = g->group[peer_index].object;
if (g->numpeers == 0) {
- free(g->group);
+ mem_delete(g_c->mem, g->group);
g->group = nullptr;
} else {
if (g->numpeers != (uint32_t)peer_index) {
g->group[peer_index] = g->group[g->numpeers];
}
- Group_Peer *temp = (Group_Peer *)realloc(g->group, g->numpeers * sizeof(Group_Peer));
+ Group_Peer *temp = (Group_Peer *)mem_vrealloc(g_c->mem, g->group, g->numpeers, sizeof(Group_Peer));
if (temp == nullptr) {
return false;
@@ -957,39 +959,90 @@ static bool delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void
/** Order peers with friends first and with more recently active earlier */
non_null()
-static int cmp_frozen(const void *a, const void *b)
+static bool group_peer_less_handler(const void *object, const void *a, const void *b)
{
const Group_Peer *pa = (const Group_Peer *)a;
const Group_Peer *pb = (const Group_Peer *)b;
- if (pa->is_friend ^ pb->is_friend) {
- return pa->is_friend ? -1 : 1;
+ if (((pa->is_friend ? 1 : 0) ^ (pb->is_friend ? 1 : 0)) != 0) {
+ return pa->is_friend;
}
- return cmp_uint(pb->last_active, pa->last_active);
+ return cmp_uint(pb->last_active, pa->last_active) < 0;
}
+non_null()
+static const void *group_peer_get_handler(const void *arr, uint32_t index)
+{
+ const Group_Peer *entries = (const Group_Peer *)arr;
+ return &entries[index];
+}
+
+non_null()
+static void group_peer_set_handler(void *arr, uint32_t index, const void *val)
+{
+ Group_Peer *entries = (Group_Peer *)arr;
+ const Group_Peer *entry = (const Group_Peer *)val;
+ entries[index] = *entry;
+}
+
+non_null()
+static void *group_peer_subarr_handler(void *arr, uint32_t index, uint32_t size)
+{
+ Group_Peer *entries = (Group_Peer *)arr;
+ return &entries[index];
+}
+
+non_null()
+static void *group_peer_alloc_handler(const void *object, uint32_t size)
+{
+ const Memory *mem = (const Memory *)object;
+ Group_Peer *tmp = (Group_Peer *)mem_valloc(mem, size, sizeof(Group_Peer));
+
+ if (tmp == nullptr) {
+ return nullptr;
+ }
+
+ return tmp;
+}
+
+non_null()
+static void group_peer_delete_handler(const void *object, void *arr, uint32_t size)
+{
+ const Memory *mem = (const Memory *)object;
+ mem_delete(mem, arr);
+}
+
+static const Sort_Funcs group_peer_cmp_funcs = {
+ group_peer_less_handler,
+ group_peer_get_handler,
+ group_peer_set_handler,
+ group_peer_subarr_handler,
+ group_peer_alloc_handler,
+ group_peer_delete_handler,
+};
+
/** @brief Delete frozen peers as necessary to ensure at most `g->maxfrozen` remain.
*
* @retval true if any frozen peers are removed.
*/
non_null()
-static bool delete_old_frozen(Group_c *g)
+static bool delete_old_frozen(Group_c *g, const Memory *mem)
{
if (g->numfrozen <= g->maxfrozen) {
return false;
}
if (g->maxfrozen == 0) {
- free(g->frozen);
+ mem_delete(mem, g->frozen);
g->frozen = nullptr;
g->numfrozen = 0;
return true;
}
- qsort(g->frozen, g->numfrozen, sizeof(Group_Peer), cmp_frozen);
+ merge_sort(g->frozen, g->numfrozen, mem, &group_peer_cmp_funcs);
- Group_Peer *temp = (Group_Peer *)realloc(g->frozen, g->maxfrozen * sizeof(Group_Peer));
+ Group_Peer *temp = (Group_Peer *)mem_vrealloc(mem, g->frozen, g->maxfrozen, sizeof(Group_Peer));
if (temp == nullptr) {
return false;
@@ -1014,7 +1067,7 @@ static bool freeze_peer(Group_Chats *g_c, uint32_t groupnumber, int peer_index,
return false;
}
- Group_Peer *temp = (Group_Peer *)realloc(g->frozen, (g->numfrozen + 1) * sizeof(Group_Peer));
+ Group_Peer *temp = (Group_Peer *)mem_vrealloc(g_c->mem, g->frozen, g->numfrozen + 1, sizeof(Group_Peer));
if (temp == nullptr) {
return false;
@@ -1032,7 +1085,7 @@ static bool freeze_peer(Group_Chats *g_c, uint32_t groupnumber, int peer_index,
++g->numfrozen;
- delete_old_frozen(g);
+ delete_old_frozen(g, g_c->mem);
return true;
}
@@ -1519,7 +1572,7 @@ int group_set_max_frozen(const Group_Chats *g_c, uint32_t groupnumber, uint32_t
}
g->maxfrozen = maxfrozen;
- delete_old_frozen(g);
+ delete_old_frozen(g, g_c->mem);
return 0;
}
@@ -2520,7 +2573,7 @@ static int handle_send_peers(Group_Chats *g_c, uint32_t groupnumber, const uint8
non_null(1, 3) nullable(6)
static void handle_direct_packet(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *data, uint16_t length,
- int connection_index, void *userdata)
+ uint32_t connection_index, void *userdata)
{
if (length == 0) {
return;
@@ -2832,7 +2885,7 @@ static bool check_message_info(uint32_t message_number, uint8_t message_id, Grou
non_null(1, 3) nullable(6)
static void handle_message_packet_group(Group_Chats *g_c, uint32_t groupnumber, const uint8_t *data, uint16_t length,
- int connection_index, void *userdata)
+ uint32_t connection_index, void *userdata)
{
if (length < sizeof(uint16_t) + sizeof(uint32_t) + 1) {
return;
@@ -3612,7 +3665,7 @@ static uint32_t load_group(Group_c *g, const Group_Chats *g_c, const uint8_t *da
}
// This is inefficient, but allows us to check data consistency before allocating memory
- Group_Peer *tmp_frozen = (Group_Peer *)realloc(g->frozen, (j + 1) * sizeof(Group_Peer));
+ Group_Peer *tmp_frozen = (Group_Peer *)mem_vrealloc(g_c->mem, g->frozen, j + 1, sizeof(Group_Peer));
if (tmp_frozen == nullptr) {
// Memory allocation failure
@@ -3752,18 +3805,19 @@ bool conferences_load_state_section(Group_Chats *g_c, const uint8_t *data, uint3
}
/** Create new groupchat instance. */
-Group_Chats *new_groupchats(const Mono_Time *mono_time, Messenger *m)
+Group_Chats *new_groupchats(const Mono_Time *mono_time, const Memory *mem, Messenger *m)
{
if (m == nullptr) {
return nullptr;
}
- Group_Chats *temp = (Group_Chats *)calloc(1, sizeof(Group_Chats));
+ Group_Chats *temp = (Group_Chats *)mem_alloc(mem, sizeof(Group_Chats));
if (temp == nullptr) {
return nullptr;
}
+ temp->mem = mem;
temp->mono_time = mono_time;
temp->m = m;
temp->fr_c = m->fr_c;
@@ -3814,7 +3868,7 @@ void kill_groupchats(Group_Chats *g_c)
m_callback_conference_invite(g_c->m, nullptr);
set_global_status_callback(g_c->m->fr_c, nullptr, nullptr);
g_c->m->conferences_object = nullptr;
- free(g_c);
+ mem_delete(g_c->mem, g_c);
}
/**
diff --git a/protocols/Tox/libtox/src/toxcore/group.h b/protocols/Tox/libtox/src/toxcore/group.h
index 5ce03275ec..706428fdda 100644
--- a/protocols/Tox/libtox/src/toxcore/group.h
+++ b/protocols/Tox/libtox/src/toxcore/group.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2014 Tox project.
*/
@@ -15,6 +15,7 @@
#include "Messenger.h"
#include "attributes.h"
#include "crypto_core.h"
+#include "mem.h"
#include "mono_time.h"
#include "state.h"
@@ -390,7 +391,7 @@ bool conferences_load_state_section(
/** Create new groupchat instance. */
non_null()
-Group_Chats *new_groupchats(const Mono_Time *mono_time, Messenger *m);
+Group_Chats *new_groupchats(const Mono_Time *mono_time, const Memory *mem, Messenger *m);
/** main groupchats loop. */
non_null(1) nullable(2)
diff --git a/protocols/Tox/libtox/src/toxcore/group_announce.c b/protocols/Tox/libtox/src/toxcore/group_announce.c
index ee083198c1..caa70193aa 100644
--- a/protocols/Tox/libtox/src/toxcore/group_announce.c
+++ b/protocols/Tox/libtox/src/toxcore/group_announce.c
@@ -5,7 +5,6 @@
#include "group_announce.h"
-#include <stdlib.h>
#include <string.h>
#include "DHT.h"
@@ -13,6 +12,7 @@
#include "ccompat.h"
#include "crypto_core.h"
#include "logger.h"
+#include "mem.h"
#include "mono_time.h"
#include "network.h"
@@ -36,7 +36,7 @@ static void remove_announces(GC_Announces_List *gc_announces_list, GC_Announces
announces->next_announce->prev_announce = announces->prev_announce;
}
- free(announces);
+ mem_delete(gc_announces_list->mem, announces);
}
/**
@@ -343,10 +343,11 @@ int gca_unpack_announces_list(const Logger *log, const uint8_t *data, uint16_t l
non_null()
static GC_Announces *gca_new_announces(
+ const Memory *mem,
GC_Announces_List *gc_announces_list,
const GC_Public_Announce *public_announce)
{
- GC_Announces *announces = (GC_Announces *)calloc(1, sizeof(GC_Announces));
+ GC_Announces *announces = (GC_Announces *)mem_alloc(mem, sizeof(GC_Announces));
if (announces == nullptr) {
return nullptr;
@@ -366,7 +367,7 @@ static GC_Announces *gca_new_announces(
return announces;
}
-GC_Peer_Announce *gca_add_announce(const Mono_Time *mono_time, GC_Announces_List *gc_announces_list,
+GC_Peer_Announce *gca_add_announce(const Memory *mem, const Mono_Time *mono_time, GC_Announces_List *gc_announces_list,
const GC_Public_Announce *public_announce)
{
if (gc_announces_list == nullptr || public_announce == nullptr) {
@@ -377,7 +378,7 @@ GC_Peer_Announce *gca_add_announce(const Mono_Time *mono_time, GC_Announces_List
// No entry for this chat_id exists so we create one
if (announces == nullptr) {
- announces = gca_new_announces(gc_announces_list, public_announce);
+ announces = gca_new_announces(mem, gc_announces_list, public_announce);
if (announces == nullptr) {
return nullptr;
@@ -410,9 +411,17 @@ bool gca_is_valid_announce(const GC_Announce *announce)
return announce->tcp_relays_count > 0 || announce->ip_port_is_set;
}
-GC_Announces_List *new_gca_list(void)
+GC_Announces_List *new_gca_list(const Memory *mem)
{
- return (GC_Announces_List *)calloc(1, sizeof(GC_Announces_List));
+ GC_Announces_List *announces_list = (GC_Announces_List *)mem_alloc(mem, sizeof(GC_Announces_List));
+
+ if (announces_list == nullptr) {
+ return nullptr;
+ }
+
+ announces_list->mem = mem;
+
+ return announces_list;
}
void kill_gca(GC_Announces_List *announces_list)
@@ -425,11 +434,11 @@ void kill_gca(GC_Announces_List *announces_list)
while (root != nullptr) {
GC_Announces *next = root->next_announce;
- free(root);
+ mem_delete(announces_list->mem, root);
root = next;
}
- free(announces_list);
+ mem_delete(announces_list->mem, announces_list);
}
/* How long we save a peer's announce before we consider it stale and remove it. */
diff --git a/protocols/Tox/libtox/src/toxcore/group_announce.h b/protocols/Tox/libtox/src/toxcore/group_announce.h
index 72f2cfc1b8..2e043a069a 100644
--- a/protocols/Tox/libtox/src/toxcore/group_announce.h
+++ b/protocols/Tox/libtox/src/toxcore/group_announce.h
@@ -16,6 +16,7 @@
#include "attributes.h"
#include "crypto_core.h"
#include "logger.h"
+#include "mem.h"
#include "mono_time.h"
#include "network.h"
@@ -79,6 +80,8 @@ struct GC_Announces {
/* A list of all announces. */
struct GC_Announces_List {
+ const Memory *mem;
+
GC_Announces *root_announces;
uint64_t last_timeout_check;
};
@@ -87,7 +90,8 @@ struct GC_Announces_List {
*
* The caller is responsible for freeing the memory with `kill_gca`.
*/
-GC_Announces_List *new_gca_list(void);
+non_null()
+GC_Announces_List *new_gca_list(const Memory *mem);
/** @brief Frees all dynamically allocated memory associated with `announces_list`. */
nullable(1)
@@ -135,7 +139,7 @@ int gca_get_announces(const GC_Announces_List *gc_announces_list, GC_Announce *g
* @retval null on failure.
*/
non_null()
-GC_Peer_Announce *gca_add_announce(const Mono_Time *mono_time, GC_Announces_List *gc_announces_list,
+GC_Peer_Announce *gca_add_announce(const Memory *mem, const Mono_Time *mono_time, GC_Announces_List *gc_announces_list,
const GC_Public_Announce *public_announce);
/** @brief Packs an announce into a data buffer.
diff --git a/protocols/Tox/libtox/src/toxcore/group_chats.c b/protocols/Tox/libtox/src/toxcore/group_chats.c
index 96f647cc2e..43ed7e8272 100644
--- a/protocols/Tox/libtox/src/toxcore/group_chats.c
+++ b/protocols/Tox/libtox/src/toxcore/group_chats.c
@@ -12,7 +12,6 @@
#include <sodium.h>
#include <assert.h>
-#include <stdlib.h>
#include <string.h>
#include "DHT.h"
@@ -30,6 +29,7 @@
#include "group_moderation.h"
#include "group_pack.h"
#include "logger.h"
+#include "mem.h"
#include "mono_time.h"
#include "net_crypto.h"
#include "network.h"
@@ -168,8 +168,6 @@ non_null() static void group_delete(GC_Session *c, GC_Chat *chat);
non_null() static void group_cleanup(const GC_Session *c, GC_Chat *chat);
non_null() static bool group_exists(const GC_Session *c, const uint8_t *chat_id);
non_null() static void add_tcp_relays_to_chat(const GC_Session *c, GC_Chat *chat);
-non_null(1, 2) nullable(4)
-static bool peer_delete(const GC_Session *c, GC_Chat *chat, uint32_t peer_number, void *userdata);
non_null() static void create_gc_session_keypair(const Logger *log, const Random *rng, uint8_t *public_key,
uint8_t *secret_key);
non_null() static size_t load_gc_peers(GC_Chat *chat, const GC_SavedPeerInfo *addrs, uint16_t num_addrs);
@@ -837,6 +835,21 @@ static int saved_peer_index(const GC_Chat *chat, const uint8_t *public_key)
return -1;
}
+/** @brief Removes entry containing `public_key` from the saved peers list. */
+non_null()
+static void saved_peers_remove_entry(GC_Chat *chat, const uint8_t *public_key)
+{
+ const int idx = saved_peer_index(chat, public_key);
+
+ if (idx < 0) {
+ return;
+ }
+
+ chat->saved_peers[idx] = (GC_SavedPeerInfo) {
+ 0
+ };
+}
+
/** @brief Returns the index of the first vacant entry in saved peers list.
*
* If `public_key` is non-null and already exists in the list, its index will be returned.
@@ -961,7 +974,7 @@ non_null() static bool broadcast_gc_mod_list(const GC_Chat *chat);
non_null() static bool broadcast_gc_shared_state(const GC_Chat *chat);
non_null() static bool update_gc_sanctions_list(GC_Chat *chat, const uint8_t *public_sig_key);
non_null() static bool update_gc_topic(GC_Chat *chat, const uint8_t *public_sig_key);
-non_null() static bool send_gc_set_observer(const GC_Chat *chat, const uint8_t *target_ext_pk,
+non_null() static bool send_gc_set_observer(const GC_Chat *chat, const Extended_Public_Key *target_ext_pk,
const uint8_t *sanction_data, uint16_t length, bool add_obs);
/** Returns true if peer designated by `peer_number` is in the sanctions list as an observer. */
@@ -1119,7 +1132,7 @@ static bool prune_gc_mod_list(GC_Chat *chat)
non_null()
static bool prune_gc_sanctions_list_inner(
GC_Chat *chat, const Mod_Sanction *sanction,
- const uint8_t target_ext_pk[ENC_PUBLIC_KEY_SIZE + SIG_PUBLIC_KEY_SIZE])
+ const Extended_Public_Key *target_ext_pk)
{
if (!sanctions_list_remove_observer(&chat->moderation, sanction->target_public_enc_key, nullptr)) {
LOGGER_WARNING(chat->log, "Failed to remove entry from observer list");
@@ -1159,10 +1172,10 @@ static bool prune_gc_sanctions_list(GC_Chat *chat)
if (peer_number == -1) {
const Mod_Sanction *sanction = &chat->moderation.sanctions[i];
- uint8_t target_ext_pk[ENC_PUBLIC_KEY_SIZE + SIG_PUBLIC_KEY_SIZE];
- memcpy(target_ext_pk, sanction->target_public_enc_key, ENC_PUBLIC_KEY_SIZE);
- memcpy(target_ext_pk + ENC_PUBLIC_KEY_SIZE, sanction->setter_public_sig_key, SIG_PUBLIC_KEY_SIZE);
- return prune_gc_sanctions_list_inner(chat, sanction, target_ext_pk);
+ Extended_Public_Key target_ext_pk;
+ memcpy(target_ext_pk.enc, sanction->target_public_enc_key, ENC_PUBLIC_KEY_SIZE);
+ memcpy(target_ext_pk.sig, sanction->setter_public_sig_key, SIG_PUBLIC_KEY_SIZE);
+ return prune_gc_sanctions_list_inner(chat, sanction, &target_ext_pk);
}
}
@@ -1473,8 +1486,8 @@ static bool sign_gc_shared_state(GC_Chat *chat)
* Return -2 on decryption failure.
* Return -3 if plaintext payload length is invalid.
*/
-non_null(1, 2, 3, 5, 6) nullable(4)
-static int group_packet_unwrap(const Logger *log, const GC_Connection *gconn, uint8_t *data, uint64_t *message_id,
+non_null(1, 2, 3, 4, 6, 7) nullable(5)
+static int group_packet_unwrap(const Logger *log, const Memory *mem, const GC_Connection *gconn, uint8_t *data, uint64_t *message_id,
uint8_t *packet_type, const uint8_t *packet, uint16_t length)
{
assert(data != nullptr);
@@ -1485,18 +1498,18 @@ static int group_packet_unwrap(const Logger *log, const GC_Connection *gconn, ui
return -1;
}
- uint8_t *plain = (uint8_t *)malloc(length);
+ uint8_t *plain = (uint8_t *)mem_balloc(mem, length);
if (plain == nullptr) {
LOGGER_ERROR(log, "Failed to allocate memory for plain data buffer");
return -1;
}
- int plain_len = decrypt_data_symmetric(gconn->session_shared_key, packet, packet + CRYPTO_NONCE_SIZE,
+ int plain_len = decrypt_data_symmetric(mem, gconn->session_shared_key, packet, packet + CRYPTO_NONCE_SIZE,
length - CRYPTO_NONCE_SIZE, plain);
if (plain_len <= 0) {
- free(plain);
+ mem_delete(mem, plain);
return plain_len == 0 ? -3 : -2;
}
@@ -1510,7 +1523,7 @@ static int group_packet_unwrap(const Logger *log, const GC_Connection *gconn, ui
--plain_len;
if (plain_len < min_plain_len) {
- free(plain);
+ mem_delete(mem, plain);
return -3;
}
}
@@ -1527,13 +1540,13 @@ static int group_packet_unwrap(const Logger *log, const GC_Connection *gconn, ui
memcpy(data, real_plain + header_len, plain_len);
- free(plain);
+ mem_delete(mem, plain);
return plain_len;
}
int group_packet_wrap(
- const Logger *log, const Random *rng, const uint8_t *self_pk, const uint8_t *shared_key, uint8_t *packet,
+ const Logger *log, const Memory *mem, const Random *rng, const uint8_t *self_pk, const uint8_t *shared_key, uint8_t *packet,
uint16_t packet_size, const uint8_t *data, uint16_t length, uint64_t message_id,
uint8_t gp_packet_type, Net_Packet_Type net_packet_type)
{
@@ -1553,7 +1566,7 @@ int group_packet_wrap(
return -1;
}
- uint8_t *plain = (uint8_t *)malloc(packet_size);
+ uint8_t *plain = (uint8_t *)mem_balloc(mem, packet_size);
if (plain == nullptr) {
return -1;
@@ -1581,20 +1594,20 @@ int group_packet_wrap(
const uint16_t plain_len = padding_len + enc_header_len + length;
const uint16_t encrypt_buf_size = plain_len + CRYPTO_MAC_SIZE;
- uint8_t *encrypt = (uint8_t *)malloc(encrypt_buf_size);
+ uint8_t *encrypt = (uint8_t *)mem_balloc(mem, encrypt_buf_size);
if (encrypt == nullptr) {
- free(plain);
+ mem_delete(mem, plain);
return -2;
}
- const int enc_len = encrypt_data_symmetric(shared_key, nonce, plain, plain_len, encrypt);
+ const int enc_len = encrypt_data_symmetric(mem, shared_key, nonce, plain, plain_len, encrypt);
- free(plain);
+ mem_delete(mem, plain);
if (enc_len != encrypt_buf_size) {
LOGGER_ERROR(log, "encryption failed. packet type: 0x%02x, enc_len: %d", gp_packet_type, enc_len);
- free(encrypt);
+ mem_delete(mem, encrypt);
return -3;
}
@@ -1603,7 +1616,7 @@ int group_packet_wrap(
memcpy(packet + 1 + ENC_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE);
memcpy(packet + 1 + ENC_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, encrypt, enc_len);
- free(encrypt);
+ mem_delete(mem, encrypt);
return 1 + ENC_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + enc_len;
}
@@ -1613,7 +1626,7 @@ int group_packet_wrap(
* Returns true on success.
*/
non_null()
-static bool send_lossy_group_packet(const GC_Chat *chat, const GC_Connection *gconn, const uint8_t *data,
+static bool send_lossy_group_packet(const GC_Chat *chat, GC_Connection *gconn, const uint8_t *data,
uint16_t length, uint8_t packet_type)
{
assert(length <= MAX_GC_CUSTOM_LOSSY_PACKET_SIZE);
@@ -1627,25 +1640,25 @@ static bool send_lossy_group_packet(const GC_Chat *chat, const GC_Connection *gc
}
const uint16_t packet_size = gc_get_wrapped_packet_size(length, NET_PACKET_GC_LOSSY);
- uint8_t *packet = (uint8_t *)malloc(packet_size);
+ uint8_t *packet = (uint8_t *)mem_balloc(chat->mem, packet_size);
if (packet == nullptr) {
return false;
}
const int len = group_packet_wrap(
- chat->log, chat->rng, chat->self_public_key.enc, gconn->session_shared_key, packet,
+ chat->log, chat->mem, chat->rng, chat->self_public_key.enc, gconn->session_shared_key, packet,
packet_size, data, length, 0, packet_type, NET_PACKET_GC_LOSSY);
if (len < 0) {
LOGGER_ERROR(chat->log, "Failed to encrypt packet (type: 0x%02x, error: %d)", packet_type, len);
- free(packet);
+ mem_delete(chat->mem, packet);
return false;
}
const bool ret = gcc_send_packet(chat, gconn, packet, (uint16_t)len);
- free(packet);
+ mem_delete(chat->mem, packet);
return ret;
}
@@ -1883,7 +1896,7 @@ static bool sync_response_send_peers(GC_Chat *chat, GC_Connection *gconn, uint32
return true;
}
- uint8_t *response = (uint8_t *)malloc(MAX_GC_PACKET_CHUNK_SIZE);
+ uint8_t *response = (uint8_t *)mem_balloc(chat->mem, MAX_GC_PACKET_CHUNK_SIZE);
if (response == nullptr) {
return false;
@@ -1923,7 +1936,7 @@ static bool sync_response_send_peers(GC_Chat *chat, GC_Connection *gconn, uint32
++num_announces;
}
- free(response);
+ mem_delete(chat->mem, response);
if (num_announces == 0) {
// we send an empty sync response even if we didn't send any peers as an acknowledgement
@@ -2223,7 +2236,7 @@ static int handle_gc_invite_response_reject(const GC_Session *c, GC_Chat *chat,
* Return true on success.
*/
non_null()
-static bool send_gc_invite_response_reject(const GC_Chat *chat, const GC_Connection *gconn, uint8_t type)
+static bool send_gc_invite_response_reject(const GC_Chat *chat, GC_Connection *gconn, uint8_t type)
{
if (type >= GJ_INVALID) {
type = GJ_INVITE_FAILED;
@@ -2340,7 +2353,7 @@ static bool send_gc_lossy_packet_all_peers(const GC_Chat *chat, const uint8_t *d
uint32_t confirmed_peers = 0;
for (uint32_t i = 1; i < chat->numpeers; ++i) {
- const GC_Connection *gconn = get_gc_connection(chat, i);
+ GC_Connection *gconn = get_gc_connection(chat, i);
assert(gconn != nullptr);
@@ -2387,7 +2400,7 @@ static bool send_gc_broadcast_message(const GC_Chat *chat, const uint8_t *data,
return false;
}
- uint8_t *packet = (uint8_t *)malloc(length + GC_BROADCAST_ENC_HEADER_SIZE);
+ uint8_t *packet = (uint8_t *)mem_balloc(chat->mem, length + GC_BROADCAST_ENC_HEADER_SIZE);
if (packet == nullptr) {
return false;
@@ -2397,7 +2410,7 @@ static bool send_gc_broadcast_message(const GC_Chat *chat, const uint8_t *data,
const bool ret = send_gc_lossless_packet_all_peers(chat, packet, packet_len, GP_BROADCAST);
- free(packet);
+ mem_delete(chat->mem, packet);
return ret;
}
@@ -2631,7 +2644,7 @@ void gc_get_chat_id(const GC_Chat *chat, uint8_t *dest)
non_null()
static bool send_self_to_peer(const GC_Chat *chat, GC_Connection *gconn)
{
- GC_Peer *self = (GC_Peer *)calloc(1, sizeof(GC_Peer));
+ GC_Peer *self = (GC_Peer *)mem_alloc(chat->mem, sizeof(GC_Peer));
if (self == nullptr) {
return false;
@@ -2640,10 +2653,10 @@ static bool send_self_to_peer(const GC_Chat *chat, GC_Connection *gconn)
copy_self(chat, self);
const uint16_t data_size = PACKED_GC_PEER_SIZE + sizeof(uint16_t) + MAX_GC_PASSWORD_SIZE;
- uint8_t *data = (uint8_t *)malloc(data_size);
+ uint8_t *data = (uint8_t *)mem_balloc(chat->mem, data_size);
if (data == nullptr) {
- free(self);
+ mem_delete(chat->mem, self);
return false;
}
@@ -2660,17 +2673,17 @@ static bool send_self_to_peer(const GC_Chat *chat, GC_Connection *gconn)
const int packed_len = pack_gc_peer(data + length, data_size - length, self);
length += packed_len;
- free(self);
+ mem_delete(chat->mem, self);
if (packed_len <= 0) {
LOGGER_DEBUG(chat->log, "pack_gc_peer failed in handle_gc_peer_info_request_request %d", packed_len);
- free(data);
+ mem_delete(chat->mem, data);
return false;
}
const bool ret = send_lossless_group_packet(chat, gconn, data, length, GP_PEER_INFO_RESPONSE);
- free(data);
+ mem_delete(chat->mem, data);
return ret;
}
@@ -2736,7 +2749,7 @@ static bool send_gc_peer_exchange(const GC_Chat *chat, GC_Connection *gconn)
* Return -5 if supplied group password is invalid.
* Return -6 if we fail to add the peer to the peer list.
* Return -7 if peer's role cannot be validated.
- * Return -8 if malloc fails.
+ * Return -8 if memory allocation fails.
*/
non_null(1, 2, 4) nullable(6)
static int handle_gc_peer_info_response(const GC_Session *c, GC_Chat *chat, uint32_t peer_number,
@@ -2781,7 +2794,7 @@ static int handle_gc_peer_info_response(const GC_Session *c, GC_Chat *chat, uint
return -1;
}
- GC_Peer *peer_info = (GC_Peer *)calloc(1, sizeof(GC_Peer));
+ GC_Peer *peer_info = (GC_Peer *)mem_alloc(chat->mem, sizeof(GC_Peer));
if (peer_info == nullptr) {
return -8;
@@ -2789,17 +2802,17 @@ static int handle_gc_peer_info_response(const GC_Session *c, GC_Chat *chat, uint
if (unpack_gc_peer(peer_info, data + unpacked_len, length - unpacked_len) == -1) {
LOGGER_ERROR(chat->log, "unpack_gc_peer() failed");
- free(peer_info);
+ mem_delete(chat->mem, peer_info);
return -6;
}
if (peer_update(chat, peer_info, peer_number) == -1) {
LOGGER_WARNING(chat->log, "peer_update() failed");
- free(peer_info);
+ mem_delete(chat->mem, peer_info);
return -6;
}
- free(peer_info);
+ mem_delete(chat->mem, peer_info);
const bool was_confirmed = gconn->confirmed;
gconn->confirmed = true;
@@ -3181,7 +3194,7 @@ static int handle_gc_sanctions_list(const GC_Session *c, GC_Chat *chat, const ui
Mod_Sanction_Creds creds;
- Mod_Sanction *sanctions = (Mod_Sanction *)calloc(num_sanctions, sizeof(Mod_Sanction));
+ Mod_Sanction *sanctions = (Mod_Sanction *)mem_valloc(chat->mem, num_sanctions, sizeof(Mod_Sanction));
if (sanctions == nullptr) {
return -1;
@@ -3192,25 +3205,25 @@ static int handle_gc_sanctions_list(const GC_Session *c, GC_Chat *chat, const ui
if (unpacked_num != num_sanctions) {
LOGGER_WARNING(chat->log, "Failed to unpack sanctions list: %d", unpacked_num);
- free(sanctions);
+ mem_delete(chat->mem, sanctions);
return handle_gc_sanctions_list_error(chat);
}
if (!sanctions_list_check_integrity(&chat->moderation, &creds, sanctions, num_sanctions)) {
LOGGER_WARNING(chat->log, "Sanctions list failed integrity check");
- free(sanctions);
+ mem_delete(chat->mem, sanctions);
return handle_gc_sanctions_list_error(chat);
}
if (creds.version < chat->moderation.sanctions_creds.version) {
- free(sanctions);
+ mem_delete(chat->mem, sanctions);
return 0;
}
// this may occur if two mods change the sanctions list at the exact same time
if (creds.version == chat->moderation.sanctions_creds.version
&& creds.checksum <= chat->moderation.sanctions_creds.checksum) {
- free(sanctions);
+ mem_delete(chat->mem, sanctions);
return 0;
}
@@ -3247,7 +3260,7 @@ static int make_gc_mod_list_packet(const GC_Chat *chat, uint8_t *data, uint32_t
const uint16_t length = sizeof(uint16_t) + mod_list_size;
if (mod_list_size > 0) {
- uint8_t *packed_mod_list = (uint8_t *)malloc(mod_list_size);
+ uint8_t *packed_mod_list = (uint8_t *)mem_balloc(chat->mem, mod_list_size);
if (packed_mod_list == nullptr) {
return -1;
@@ -3256,7 +3269,7 @@ static int make_gc_mod_list_packet(const GC_Chat *chat, uint8_t *data, uint32_t
mod_list_pack(&chat->moderation, packed_mod_list);
memcpy(data + sizeof(uint16_t), packed_mod_list, mod_list_size);
- free(packed_mod_list);
+ mem_delete(chat->mem, packed_mod_list);
}
return length;
@@ -3271,7 +3284,7 @@ static bool send_peer_mod_list(const GC_Chat *chat, GC_Connection *gconn)
{
const uint16_t mod_list_size = chat->moderation.num_mods * MOD_LIST_ENTRY_SIZE;
const uint16_t length = sizeof(uint16_t) + mod_list_size;
- uint8_t *packet = (uint8_t *)malloc(length);
+ uint8_t *packet = (uint8_t *)mem_balloc(chat->mem, length);
if (packet == nullptr) {
return false;
@@ -3280,13 +3293,13 @@ static bool send_peer_mod_list(const GC_Chat *chat, GC_Connection *gconn)
const int packet_len = make_gc_mod_list_packet(chat, packet, length, mod_list_size);
if (packet_len != length) {
- free(packet);
+ mem_delete(chat->mem, packet);
return false;
}
const bool ret = send_lossless_group_packet(chat, gconn, packet, length, GP_MOD_LIST);
- free(packet);
+ mem_delete(chat->mem, packet);
return ret;
}
@@ -3330,7 +3343,7 @@ static bool send_peer_sanctions_list(const GC_Chat *chat, GC_Connection *gconn)
const uint16_t packet_size = MOD_SANCTION_PACKED_SIZE * chat->moderation.num_sanctions +
sizeof(uint16_t) + MOD_SANCTIONS_CREDS_SIZE;
- uint8_t *packet = (uint8_t *)malloc(packet_size);
+ uint8_t *packet = (uint8_t *)mem_balloc(chat->mem, packet_size);
if (packet == nullptr) {
return false;
@@ -3339,13 +3352,13 @@ static bool send_peer_sanctions_list(const GC_Chat *chat, GC_Connection *gconn)
const int packet_len = make_gc_sanctions_list_packet(chat, packet, packet_size);
if (packet_len == -1) {
- free(packet);
+ mem_delete(chat->mem, packet);
return false;
}
const bool ret = send_lossless_group_packet(chat, gconn, packet, (uint16_t)packet_len, GP_SANCTIONS_LIST);
- free(packet);
+ mem_delete(chat->mem, packet);
return ret;
}
@@ -3360,7 +3373,7 @@ static bool broadcast_gc_sanctions_list(const GC_Chat *chat)
const uint16_t packet_size = MOD_SANCTION_PACKED_SIZE * chat->moderation.num_sanctions +
sizeof(uint16_t) + MOD_SANCTIONS_CREDS_SIZE;
- uint8_t *packet = (uint8_t *)malloc(packet_size);
+ uint8_t *packet = (uint8_t *)mem_balloc(chat->mem, packet_size);
if (packet == nullptr) {
return false;
@@ -3369,13 +3382,13 @@ static bool broadcast_gc_sanctions_list(const GC_Chat *chat)
const int packet_len = make_gc_sanctions_list_packet(chat, packet, packet_size);
if (packet_len == -1) {
- free(packet);
+ mem_delete(chat->mem, packet);
return false;
}
const bool ret = send_gc_lossless_packet_all_peers(chat, packet, (uint16_t)packet_len, GP_SANCTIONS_LIST);
- free(packet);
+ mem_delete(chat->mem, packet);
return ret;
}
@@ -3406,7 +3419,7 @@ static bool broadcast_gc_mod_list(const GC_Chat *chat)
{
const uint16_t mod_list_size = chat->moderation.num_mods * MOD_LIST_ENTRY_SIZE;
const uint16_t length = sizeof(uint16_t) + mod_list_size;
- uint8_t *packet = (uint8_t *)malloc(length);
+ uint8_t *packet = (uint8_t *)mem_balloc(chat->mem, length);
if (packet == nullptr) {
return false;
@@ -3415,13 +3428,13 @@ static bool broadcast_gc_mod_list(const GC_Chat *chat)
const int packet_len = make_gc_mod_list_packet(chat, packet, length, mod_list_size);
if (packet_len != length) {
- free(packet);
+ mem_delete(chat->mem, packet);
return false;
}
const bool ret = send_gc_lossless_packet_all_peers(chat, packet, length, GP_MOD_LIST);
- free(packet);
+ mem_delete(chat->mem, packet);
return ret;
}
@@ -3699,7 +3712,7 @@ non_null()
static bool send_peer_topic(const GC_Chat *chat, GC_Connection *gconn)
{
const uint16_t packet_buf_size = SIGNATURE_SIZE + chat->topic_info.length + GC_MIN_PACKED_TOPIC_INFO_SIZE;
- uint8_t *packet = (uint8_t *)malloc(packet_buf_size);
+ uint8_t *packet = (uint8_t *)mem_balloc(chat->mem, packet_buf_size);
if (packet == nullptr) {
return false;
@@ -3708,16 +3721,16 @@ static bool send_peer_topic(const GC_Chat *chat, GC_Connection *gconn)
const int packet_len = make_gc_topic_packet(chat, packet, packet_buf_size);
if (packet_len != packet_buf_size) {
- free(packet);
+ mem_delete(chat->mem, packet);
return false;
}
if (!send_lossless_group_packet(chat, gconn, packet, packet_buf_size, GP_TOPIC)) {
- free(packet);
+ mem_delete(chat->mem, packet);
return false;
}
- free(packet);
+ mem_delete(chat->mem, packet);
return true;
}
@@ -3767,7 +3780,7 @@ non_null()
static bool broadcast_gc_topic(const GC_Chat *chat)
{
const uint16_t packet_buf_size = SIGNATURE_SIZE + chat->topic_info.length + GC_MIN_PACKED_TOPIC_INFO_SIZE;
- uint8_t *packet = (uint8_t *)malloc(packet_buf_size);
+ uint8_t *packet = (uint8_t *)mem_balloc(chat->mem, packet_buf_size);
if (packet == nullptr) {
return false;
@@ -3776,13 +3789,13 @@ static bool broadcast_gc_topic(const GC_Chat *chat)
const int packet_len = make_gc_topic_packet(chat, packet, packet_buf_size);
if (packet_len != packet_buf_size) {
- free(packet);
+ mem_delete(chat->mem, packet);
return false;
}
const bool ret = send_gc_lossless_packet_all_peers(chat, packet, packet_buf_size, GP_TOPIC);
- free(packet);
+ mem_delete(chat->mem, packet);
return ret;
}
@@ -3832,7 +3845,7 @@ int gc_set_topic(GC_Chat *chat, const uint8_t *topic, uint16_t length)
chat->topic_info.checksum = get_gc_topic_checksum(&chat->topic_info);
const uint16_t packet_buf_size = length + GC_MIN_PACKED_TOPIC_INFO_SIZE;
- uint8_t *packed_topic = (uint8_t *)malloc(packet_buf_size);
+ uint8_t *packed_topic = (uint8_t *)mem_balloc(chat->mem, packet_buf_size);
if (packed_topic == nullptr) {
return -3;
@@ -3859,13 +3872,13 @@ int gc_set_topic(GC_Chat *chat, const uint8_t *topic, uint16_t length)
chat->topic_prev_checksum = old_topic_info.checksum;
chat->topic_time_set = mono_time_get(chat->mono_time);
- free(packed_topic);
+ mem_delete(chat->mem, packed_topic);
return 0;
ON_ERROR:
chat->topic_info = old_topic_info;
memcpy(chat->topic_sig, old_topic_sig, SIGNATURE_SIZE);
- free(packed_topic);
+ mem_delete(chat->mem, packed_topic);
return err;
}
@@ -4116,24 +4129,24 @@ int gc_founder_set_password(GC_Chat *chat, const uint8_t *password, uint16_t pas
}
const uint16_t oldlen = chat->shared_state.password_length;
- uint8_t *oldpasswd = memdup(chat->shared_state.password, oldlen);
+ uint8_t *oldpasswd = memdup(chat->mem, chat->shared_state.password, oldlen);
if (oldpasswd == nullptr && oldlen > 0) {
return -4;
}
if (!set_gc_password_local(chat, password, password_length)) {
- free(oldpasswd);
+ mem_delete(chat->mem, oldpasswd);
return -2;
}
if (!sign_gc_shared_state(chat)) {
set_gc_password_local(chat, oldpasswd, oldlen);
- free(oldpasswd);
+ mem_delete(chat->mem, oldpasswd);
return -2;
}
- free(oldpasswd);
+ mem_delete(chat->mem, oldpasswd);
if (!broadcast_gc_shared_state(chat)) {
return -3;
@@ -4258,7 +4271,7 @@ non_null()
static bool send_gc_set_mod(const GC_Chat *chat, const GC_Connection *gconn, bool add_mod)
{
const uint16_t length = 1 + SIG_PUBLIC_KEY_SIZE;
- uint8_t *data = (uint8_t *)malloc(length);
+ uint8_t *data = (uint8_t *)mem_balloc(chat->mem, length);
if (data == nullptr) {
return false;
@@ -4269,11 +4282,11 @@ static bool send_gc_set_mod(const GC_Chat *chat, const GC_Connection *gconn, boo
memcpy(data + 1, get_sig_pk(&gconn->addr.public_key), SIG_PUBLIC_KEY_SIZE);
if (!send_gc_broadcast_message(chat, data, length, GM_SET_MOD)) {
- free(data);
+ mem_delete(chat->mem, data);
return false;
}
- free(data);
+ mem_delete(chat->mem, data);
return true;
}
@@ -4457,11 +4470,11 @@ static int handle_gc_set_observer(const GC_Session *c, GC_Chat *chat, uint32_t p
* Returns true on success.
*/
non_null()
-static bool send_gc_set_observer(const GC_Chat *chat, const uint8_t *target_ext_pk, const uint8_t *sanction_data,
- uint16_t length, bool add_obs)
+static bool send_gc_set_observer(const GC_Chat *chat, const Extended_Public_Key *target_ext_pk,
+ const uint8_t *sanction_data, uint16_t length, bool add_obs)
{
- const uint16_t packet_len = 1 + EXT_PUBLIC_KEY_SIZE + length;
- uint8_t *packet = (uint8_t *)malloc(packet_len);
+ const uint16_t packet_len = 1 + ENC_PUBLIC_KEY_SIZE + SIG_PUBLIC_KEY_SIZE + length;
+ uint8_t *packet = (uint8_t *)mem_balloc(chat->mem, packet_len);
if (packet == nullptr) {
return false;
@@ -4469,15 +4482,16 @@ static bool send_gc_set_observer(const GC_Chat *chat, const uint8_t *target_ext_
net_pack_bool(&packet[0], add_obs);
- memcpy(packet + 1, target_ext_pk, EXT_PUBLIC_KEY_SIZE);
- memcpy(packet + 1 + EXT_PUBLIC_KEY_SIZE, sanction_data, length);
+ memcpy(packet + 1, target_ext_pk->enc, ENC_PUBLIC_KEY_SIZE);
+ memcpy(packet + 1 + ENC_PUBLIC_KEY_SIZE, target_ext_pk->sig, SIG_PUBLIC_KEY_SIZE);
+ memcpy(packet + 1 + ENC_PUBLIC_KEY_SIZE + SIG_PUBLIC_KEY_SIZE, sanction_data, length);
if (!send_gc_broadcast_message(chat, packet, packet_len, GM_SET_OBSERVER)) {
- free(packet);
+ mem_delete(chat->mem, packet);
return false;
}
- free(packet);
+ mem_delete(chat->mem, packet);
return true;
}
@@ -4557,7 +4571,7 @@ static bool mod_gc_set_observer(GC_Chat *chat, uint32_t peer_number, bool add_ob
update_gc_peer_roles(chat);
- return send_gc_set_observer(chat, gconn->addr.public_key.enc, sanction_data, length, add_obs);
+ return send_gc_set_observer(chat, &gconn->addr.public_key, sanction_data, length, add_obs);
}
/** @brief Sets the role of `peer_number` to `new_role`. If necessary this function will first
@@ -4894,7 +4908,7 @@ int gc_send_message(const GC_Chat *chat, const uint8_t *message, uint16_t length
const uint8_t packet_type = type == GC_MESSAGE_TYPE_NORMAL ? GM_PLAIN_MESSAGE : GM_ACTION_MESSAGE;
const uint16_t length_raw = length + GC_MESSAGE_PSEUDO_ID_SIZE;
- uint8_t *message_raw = (uint8_t *)malloc(length_raw);
+ uint8_t *message_raw = (uint8_t *)mem_balloc(chat->mem, length_raw);
if (message_raw == nullptr) {
return -5;
@@ -4906,15 +4920,16 @@ int gc_send_message(const GC_Chat *chat, const uint8_t *message, uint16_t length
memcpy(message_raw + GC_MESSAGE_PSEUDO_ID_SIZE, message, length);
if (!send_gc_broadcast_message(chat, message_raw, length_raw, packet_type)) {
- free(message_raw);
+ mem_delete(chat->mem, message_raw);
return -5;
}
+ mem_delete(chat->mem, message_raw);
+
if (message_id != nullptr) {
*message_id = pseudo_msg_id;
}
- free(message_raw);
return 0;
}
@@ -4954,7 +4969,7 @@ static int handle_gc_message(const GC_Session *c, const GC_Chat *chat, const GC_
}
int gc_send_private_message(const GC_Chat *chat, GC_Peer_Id peer_id, uint8_t type, const uint8_t *message,
- uint16_t length)
+ uint16_t length, uint32_t *message_id)
{
if (length > MAX_GC_MESSAGE_SIZE) {
return -1;
@@ -4980,32 +4995,41 @@ int gc_send_private_message(const GC_Chat *chat, GC_Peer_Id peer_id, uint8_t typ
return -5;
}
- uint8_t *message_with_type = (uint8_t *)malloc(length + 1);
+ const uint16_t raw_length = 1 + length + GC_MESSAGE_PSEUDO_ID_SIZE;
+ uint8_t *message_with_type = (uint8_t *)mem_balloc(chat->mem, raw_length);
if (message_with_type == nullptr) {
return -6;
}
message_with_type[0] = type;
- memcpy(message_with_type + 1, message, length);
- uint8_t *packet = (uint8_t *)malloc(length + 1 + GC_BROADCAST_ENC_HEADER_SIZE);
+ const uint32_t pseudo_msg_id = random_u32(chat->rng);
+ net_pack_u32(message_with_type + 1, pseudo_msg_id);
+
+ memcpy(message_with_type + 1 + GC_MESSAGE_PSEUDO_ID_SIZE, message, length);
+
+ uint8_t *packet = (uint8_t *)mem_balloc(chat->mem, raw_length + GC_BROADCAST_ENC_HEADER_SIZE);
if (packet == nullptr) {
- free(message_with_type);
+ mem_delete(chat->mem, message_with_type);
return -6;
}
- const uint16_t packet_len = make_gc_broadcast_header(message_with_type, length + 1, packet, GM_PRIVATE_MESSAGE);
+ const uint16_t packet_len = make_gc_broadcast_header(message_with_type, raw_length, packet, GM_PRIVATE_MESSAGE);
- free(message_with_type);
+ mem_delete(chat->mem, message_with_type);
if (!send_lossless_group_packet(chat, gconn, packet, packet_len, GP_BROADCAST)) {
- free(packet);
+ mem_delete(chat->mem, packet);
return -6;
}
- free(packet);
+ mem_delete(chat->mem, packet);
+
+ if (message_id != nullptr) {
+ *message_id = pseudo_msg_id;
+ }
return 0;
}
@@ -5019,7 +5043,7 @@ non_null(1, 2, 3, 4) nullable(6)
static int handle_gc_private_message(const GC_Session *c, const GC_Chat *chat, const GC_Peer *peer, const uint8_t *data,
uint16_t length, void *userdata)
{
- if (data == nullptr || length > MAX_GC_MESSAGE_SIZE || length <= 1) {
+ if (data == nullptr || length > MAX_GC_MESSAGE_SIZE || length <= 1 + GC_MESSAGE_PSEUDO_ID_SIZE) {
return -1;
}
@@ -5034,8 +5058,13 @@ static int handle_gc_private_message(const GC_Session *c, const GC_Chat *chat, c
return 0;
}
+ uint32_t message_id;
+ net_unpack_u32(data + 1, &message_id);
+
if (c->private_message != nullptr) {
- c->private_message(c->messenger, chat->group_number, peer->peer_id, message_type, data + 1, length - 1, userdata);
+ c->private_message(c->messenger, chat->group_number, peer->peer_id, message_type,
+ data + 1 + GC_MESSAGE_PSEUDO_ID_SIZE, length - 1 - GC_MESSAGE_PSEUDO_ID_SIZE,
+ message_id, userdata);
}
return 0;
@@ -5066,10 +5095,6 @@ int gc_send_custom_private_packet(const GC_Chat *chat, bool lossless, GC_Peer_Id
return -3;
}
- if (gc_get_self_role(chat) >= GR_OBSERVER) {
- return -4;
- }
-
bool ret;
if (lossless) {
@@ -5078,7 +5103,7 @@ int gc_send_custom_private_packet(const GC_Chat *chat, bool lossless, GC_Peer_Id
ret = send_lossy_group_packet(chat, gconn, message, length, GP_CUSTOM_PRIVATE_PACKET);
}
- return ret ? 0 : -5;
+ return ret ? 0 : -4;
}
/** @brief Handles a custom private packet.
@@ -5098,10 +5123,6 @@ static int handle_gc_custom_private_packet(const GC_Session *c, const GC_Chat *c
return -1;
}
- if (peer->ignore || peer->role >= GR_OBSERVER) {
- return 0;
- }
-
if (c->custom_private_packet != nullptr) {
c->custom_private_packet(c->messenger, chat->group_number, peer->peer_id, data, length, userdata);
}
@@ -5119,10 +5140,6 @@ int gc_send_custom_packet(const GC_Chat *chat, bool lossless, const uint8_t *dat
return -2;
}
- if (gc_get_self_role(chat) >= GR_OBSERVER) {
- return -3;
- }
-
bool success;
if (lossless) {
@@ -5131,7 +5148,7 @@ int gc_send_custom_packet(const GC_Chat *chat, bool lossless, const uint8_t *dat
success = send_gc_lossy_packet_all_peers(chat, data, length, GP_CUSTOM_PACKET);
}
- return success ? 0 : -4;
+ return success ? 0 : -3;
}
/** @brief Handles a custom packet.
@@ -5151,10 +5168,6 @@ static int handle_gc_custom_packet(const GC_Session *c, const GC_Chat *chat, con
return -1;
}
- if (peer->ignore || peer->role >= GR_OBSERVER) {
- return 0;
- }
-
if (c->custom_packet != nullptr) {
c->custom_packet(c->messenger, chat->group_number, peer->peer_id, data, length, userdata);
}
@@ -5330,7 +5343,7 @@ static int handle_gc_message_ack(const GC_Chat *chat, GC_Connection *gconn, cons
const Group_Message_Ack_Type type = (Group_Message_Ack_Type) data[0];
if (type == GR_ACK_RECV) {
- if (!gcc_handle_ack(chat->log, gconn, message_id)) {
+ if (!gcc_handle_ack(chat->log, chat->mem, gconn, message_id)) {
return -2;
}
@@ -5508,7 +5521,7 @@ static int handle_gc_broadcast(const GC_Session *c, GC_Chat *chat, uint32_t peer
* Return -2 if decryption fails.
*/
non_null()
-static int unwrap_group_handshake_packet(const Logger *log, const uint8_t *self_sk, const uint8_t *sender_pk,
+static int unwrap_group_handshake_packet(const Logger *log, const Memory *mem, const uint8_t *self_sk, const uint8_t *sender_pk,
uint8_t *plain, size_t plain_size, const uint8_t *packet, uint16_t length)
{
if (length <= CRYPTO_NONCE_SIZE) {
@@ -5516,7 +5529,7 @@ static int unwrap_group_handshake_packet(const Logger *log, const uint8_t *self_
return -1;
}
- const int plain_len = decrypt_data(sender_pk, self_sk, packet, packet + CRYPTO_NONCE_SIZE,
+ const int plain_len = decrypt_data(mem, sender_pk, self_sk, packet, packet + CRYPTO_NONCE_SIZE,
length - CRYPTO_NONCE_SIZE, plain);
if (plain_len < 0 || (uint32_t)plain_len != plain_size) {
@@ -5534,12 +5547,12 @@ static int unwrap_group_handshake_packet(const Logger *log, const uint8_t *self_
*
* Return length of encrypted packet on success.
* Return -1 if packet size is invalid.
- * Return -2 on malloc failure.
+ * Return -2 on memory allocation failure.
* Return -3 if encryption fails.
*/
non_null()
static int wrap_group_handshake_packet(
- const Logger *log, const Random *rng, const uint8_t *self_pk, const uint8_t *self_sk,
+ const Logger *log, const Memory *mem, const Random *rng, const uint8_t *self_pk, const uint8_t *self_sk,
const uint8_t *target_pk, uint8_t *packet, uint32_t packet_size,
const uint8_t *data, uint16_t length)
{
@@ -5552,17 +5565,17 @@ static int wrap_group_handshake_packet(
random_nonce(rng, nonce);
const size_t encrypt_buf_size = length + CRYPTO_MAC_SIZE;
- uint8_t *encrypt = (uint8_t *)malloc(encrypt_buf_size);
+ uint8_t *encrypt = (uint8_t *)mem_balloc(mem, encrypt_buf_size);
if (encrypt == nullptr) {
return -2;
}
- const int enc_len = encrypt_data(target_pk, self_sk, nonce, data, length, encrypt);
+ const int enc_len = encrypt_data(mem, target_pk, self_sk, nonce, data, length, encrypt);
if (enc_len < 0 || (size_t)enc_len != encrypt_buf_size) {
LOGGER_ERROR(log, "Failed to encrypt group handshake packet (len: %d)", enc_len);
- free(encrypt);
+ mem_delete(mem, encrypt);
return -3;
}
@@ -5572,7 +5585,7 @@ static int wrap_group_handshake_packet(
memcpy(packet + 1 + ENC_PUBLIC_KEY_SIZE + ENC_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE);
memcpy(packet + 1 + ENC_PUBLIC_KEY_SIZE + ENC_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, encrypt, enc_len);
- free(encrypt);
+ mem_delete(mem, encrypt);
return 1 + ENC_PUBLIC_KEY_SIZE + ENC_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + enc_len;
}
@@ -5622,7 +5635,7 @@ static int make_gc_handshake_packet(const GC_Chat *chat, const GC_Connection *gc
}
const int enc_len = wrap_group_handshake_packet(
- chat->log, chat->rng, chat->self_public_key.enc, chat->self_secret_key.enc,
+ chat->log, chat->mem, chat->rng, chat->self_public_key.enc, chat->self_secret_key.enc,
gconn->addr.public_key.enc, packet, (uint16_t)packet_size, data, length);
if (enc_len != GC_MIN_ENCRYPTED_HS_PAYLOAD_SIZE + nodes_size) {
@@ -5945,18 +5958,18 @@ static int handle_gc_handshake_packet(GC_Chat *chat, const uint8_t *sender_pk, c
}
const size_t data_buf_size = length - CRYPTO_NONCE_SIZE - CRYPTO_MAC_SIZE;
- uint8_t *data = (uint8_t *)malloc(data_buf_size);
+ uint8_t *data = (uint8_t *)mem_balloc(chat->mem, data_buf_size);
if (data == nullptr) {
return -1;
}
- const int plain_len = unwrap_group_handshake_packet(chat->log, chat->self_secret_key.enc, sender_pk, data,
+ const int plain_len = unwrap_group_handshake_packet(chat->log, chat->mem, chat->self_secret_key.enc, sender_pk, data,
data_buf_size, packet, length);
if (plain_len < GC_MIN_HS_PACKET_PAYLOAD_SIZE) {
LOGGER_DEBUG(chat->log, "Failed to unwrap handshake packet (probably a stale request using an old key)");
- free(data);
+ mem_delete(chat->mem, data);
return -1;
}
@@ -5972,11 +5985,11 @@ static int handle_gc_handshake_packet(GC_Chat *chat, const uint8_t *sender_pk, c
} else if (handshake_type == GH_RESPONSE) {
peer_number = handle_gc_handshake_response(chat, sender_pk, real_data, real_len);
} else {
- free(data);
+ mem_delete(chat->mem, data);
return -1;
}
- free(data);
+ mem_delete(chat->mem, data);
GC_Connection *gconn = get_gc_connection(chat, peer_number);
@@ -6171,7 +6184,7 @@ static bool handle_gc_lossless_packet(const GC_Session *c, GC_Chat *chat, const
return true;
}
- uint8_t *data = (uint8_t *)malloc(length);
+ uint8_t *data = (uint8_t *)mem_balloc(chat->mem, length);
if (data == nullptr) {
LOGGER_DEBUG(chat->log, "Failed to allocate memory for packet data buffer");
@@ -6181,19 +6194,19 @@ static bool handle_gc_lossless_packet(const GC_Session *c, GC_Chat *chat, const
uint8_t packet_type;
uint64_t message_id;
- const int len = group_packet_unwrap(chat->log, gconn, data, &message_id, &packet_type, packet, length);
+ const int len = group_packet_unwrap(chat->log, chat->mem, gconn, data, &message_id, &packet_type, packet, length);
if (len < 0) {
Ip_Ntoa ip_str;
LOGGER_DEBUG(chat->log, "Failed to unwrap lossless packet from %s:%d: %d",
net_ip_ntoa(&gconn->addr.ip_port.ip, &ip_str), net_ntohs(gconn->addr.ip_port.port), len);
- free(data);
+ mem_delete(chat->mem, data);
return false;
}
if (!gconn->handshaked && (packet_type != GP_HS_RESPONSE_ACK && packet_type != GP_INVITE_REQUEST)) {
LOGGER_DEBUG(chat->log, "Got lossless packet type 0x%02x from unconfirmed peer", packet_type);
- free(data);
+ mem_delete(chat->mem, data);
return false;
}
@@ -6203,28 +6216,27 @@ static bool handle_gc_lossless_packet(const GC_Session *c, GC_Chat *chat, const
if (message_id == 3 && is_invite_packet && gconn->received_message_id <= 1) {
// we missed initial handshake request. Drop this packet and wait for another handshake request.
LOGGER_DEBUG(chat->log, "Missed handshake packet, type: 0x%02x", packet_type);
- free(data);
+ mem_delete(chat->mem, data);
return false;
}
- const int lossless_ret = gcc_handle_received_message(chat->log, chat->mono_time, gconn, data, (uint16_t) len,
- packet_type, message_id, direct_conn);
+ const int lossless_ret = gcc_handle_received_message(chat->log, chat->mem, chat->mono_time, gconn, data, (uint16_t) len, packet_type, message_id, direct_conn);
if (packet_type == GP_INVITE_REQUEST && !gconn->handshaked) { // Both peers sent request at same time
- free(data);
+ mem_delete(chat->mem, data);
return true;
}
if (lossless_ret < 0) {
LOGGER_DEBUG(chat->log, "failed to handle packet %llu (type: 0x%02x, id: %llu)",
(unsigned long long)message_id, packet_type, (unsigned long long)message_id);
- free(data);
+ mem_delete(chat->mem, data);
return false;
}
/* Duplicate packet */
if (lossless_ret == 0) {
- free(data);
+ mem_delete(chat->mem, data);
return gc_send_message_ack(chat, gconn, message_id, GR_ACK_RECV);
}
@@ -6232,7 +6244,7 @@ static bool handle_gc_lossless_packet(const GC_Session *c, GC_Chat *chat, const
if (lossless_ret == 1) {
LOGGER_TRACE(chat->log, "received out of order packet from peer %u. expected %llu, got %llu", peer_number,
(unsigned long long)gconn->received_message_id + 1, (unsigned long long)message_id);
- free(data);
+ mem_delete(chat->mem, data);
return gc_send_message_ack(chat, gconn, gconn->received_message_id + 1, GR_ACK_REQ);
}
@@ -6240,13 +6252,13 @@ static bool handle_gc_lossless_packet(const GC_Session *c, GC_Chat *chat, const
if (lossless_ret == 3) {
const bool frag_ret = handle_gc_packet_fragment(c, chat, peer_number, gconn, data, (uint16_t)len, packet_type,
message_id, userdata);
- free(data);
+ mem_delete(chat->mem, data);
return frag_ret;
}
const bool ret = handle_gc_lossless_helper(c, chat, peer_number, data, (uint16_t)len, packet_type, userdata);
- free(data);
+ mem_delete(chat->mem, data);
if (!ret) {
return false;
@@ -6325,7 +6337,7 @@ static bool handle_gc_lossy_packet(const GC_Session *c, GC_Chat *chat, const uin
return false;
}
- uint8_t *data = (uint8_t *)malloc(length);
+ uint8_t *data = (uint8_t *)mem_balloc(chat->mem, length);
if (data == nullptr) {
LOGGER_ERROR(chat->log, "Failed to allocate memory for packet buffer");
@@ -6334,19 +6346,19 @@ static bool handle_gc_lossy_packet(const GC_Session *c, GC_Chat *chat, const uin
uint8_t packet_type;
- const int len = group_packet_unwrap(chat->log, gconn, data, nullptr, &packet_type, packet, length);
+ const int len = group_packet_unwrap(chat->log, chat->mem, gconn, data, nullptr, &packet_type, packet, length);
if (len <= 0) {
Ip_Ntoa ip_str;
LOGGER_DEBUG(chat->log, "Failed to unwrap lossy packet from %s:%d: %d",
net_ip_ntoa(&gconn->addr.ip_port.ip, &ip_str), net_ntohs(gconn->addr.ip_port.port), len);
- free(data);
+ mem_delete(chat->mem, data);
return false;
}
const int ret = handle_gc_lossy_packet_decoded(c, chat, gconn, peer, packet_type, data, (uint16_t)len, userdata);
- free(data);
+ mem_delete(chat->mem, data);
if (ret < 0) {
LOGGER_DEBUG(chat->log, "Lossy packet handle error %d: type: 0x%02x, peernumber %d", ret, packet_type,
@@ -6702,6 +6714,7 @@ void gc_callback_rejected(const Messenger *m, gc_rejected_cb *function)
*
* Return true on success.
*/
+non_null(1, 2) nullable(4)
static bool peer_delete(const GC_Session *c, GC_Chat *chat, uint32_t peer_number, void *userdata)
{
GC_Peer *peer = get_gc_peer(chat, peer_number);
@@ -6710,17 +6723,23 @@ static bool peer_delete(const GC_Session *c, GC_Chat *chat, uint32_t peer_number
return false;
}
+ GC_Connection *gconn = &peer->gconn;
+
// We need to save some peer info for the callback before deleting it
- const bool peer_confirmed = peer->gconn.confirmed;
+ const bool peer_confirmed = gconn->confirmed;
const GC_Peer_Id peer_id = peer->peer_id;
uint8_t nick[MAX_GC_NICK_SIZE];
const uint16_t nick_length = peer->nick_length;
- const GC_Exit_Info exit_info = peer->gconn.exit_info;
+ const GC_Exit_Info exit_info = gconn->exit_info;
assert(nick_length <= MAX_GC_NICK_SIZE);
memcpy(nick, peer->nick, nick_length);
- gcc_peer_cleanup(&peer->gconn);
+ if (exit_info.exit_type == GC_EXIT_TYPE_KICKED) {
+ saved_peers_remove_entry(chat, gconn->addr.public_key.enc);
+ }
+
+ gcc_peer_cleanup(chat->mem, gconn);
--chat->numpeers;
@@ -6732,7 +6751,7 @@ static bool peer_delete(const GC_Session *c, GC_Chat *chat, uint32_t peer_number
0
};
- GC_Peer *tmp_group = (GC_Peer *)realloc(chat->group, chat->numpeers * sizeof(GC_Peer));
+ GC_Peer *tmp_group = (GC_Peer *)mem_vrealloc(chat->mem, chat->group, chat->numpeers, sizeof(GC_Peer));
if (tmp_group == nullptr) {
return false;
@@ -6808,8 +6827,8 @@ int peer_add(GC_Chat *chat, const IP_Port *ipp, const uint8_t *public_key)
}
}
- GC_Message_Array_Entry *send = (GC_Message_Array_Entry *)calloc(GCC_BUFFER_SIZE, sizeof(GC_Message_Array_Entry));
- GC_Message_Array_Entry *recv = (GC_Message_Array_Entry *)calloc(GCC_BUFFER_SIZE, sizeof(GC_Message_Array_Entry));
+ GC_Message_Array_Entry *send = (GC_Message_Array_Entry *)mem_valloc(chat->mem, GCC_BUFFER_SIZE, sizeof(GC_Message_Array_Entry));
+ GC_Message_Array_Entry *recv = (GC_Message_Array_Entry *)mem_valloc(chat->mem, GCC_BUFFER_SIZE, sizeof(GC_Message_Array_Entry));
if (send == nullptr || recv == nullptr) {
LOGGER_ERROR(chat->log, "Failed to allocate memory for gconn buffers");
@@ -6818,22 +6837,22 @@ int peer_add(GC_Chat *chat, const IP_Port *ipp, const uint8_t *public_key)
kill_tcp_connection_to(chat->tcp_conn, tcp_connection_num);
}
- free(send);
- free(recv);
+ mem_delete(chat->mem, send);
+ mem_delete(chat->mem, recv);
return -1;
}
- GC_Peer *tmp_group = (GC_Peer *)realloc(chat->group, (chat->numpeers + 1) * sizeof(GC_Peer));
+ GC_Peer *tmp_group = (GC_Peer *)mem_vrealloc(chat->mem, chat->group, chat->numpeers + 1, sizeof(GC_Peer));
if (tmp_group == nullptr) {
- LOGGER_ERROR(chat->log, "Failed to allocate memory for group realloc");
+ LOGGER_ERROR(chat->log, "Failed to allocate memory for group mem_vrealloc");
if (tcp_connection_num != -1) {
kill_tcp_connection_to(chat->tcp_conn, tcp_connection_num);
}
- free(send);
- free(recv);
+ mem_delete(chat->mem, send);
+ mem_delete(chat->mem, recv);
return -1;
}
@@ -7053,10 +7072,10 @@ static void do_peer_delete(const GC_Session *c, GC_Chat *chat, void *userdata)
* Return true on success.
*/
non_null()
-static bool ping_peer(const GC_Chat *chat, const GC_Connection *gconn)
+static bool ping_peer(const GC_Chat *chat, GC_Connection *gconn)
{
const uint16_t buf_size = GC_PING_PACKET_MIN_DATA_SIZE + sizeof(IP_Port);
- uint8_t *data = (uint8_t *)malloc(buf_size);
+ uint8_t *data = (uint8_t *)mem_balloc(chat->mem, buf_size);
if (data == nullptr) {
return false;
@@ -7102,11 +7121,11 @@ static bool ping_peer(const GC_Chat *chat, const GC_Connection *gconn)
}
if (!send_lossy_group_packet(chat, gconn, data, packed_len, GP_PING)) {
- free(data);
+ mem_delete(chat->mem, data);
return false;
}
- free(data);
+ mem_delete(chat->mem, data);
return true;
}
@@ -7319,15 +7338,15 @@ void do_gc(GC_Session *c, void *userdata)
* Return true on success.
*/
non_null()
-static bool realloc_groupchats(GC_Session *c, uint32_t n)
+static bool realloc_groupchats(const Memory *mem, GC_Session *c, uint32_t n)
{
if (n == 0) {
- free(c->chats);
+ mem_delete(mem, c->chats);
c->chats = nullptr;
return true;
}
- GC_Chat *temp = (GC_Chat *)realloc(c->chats, n * sizeof(GC_Chat));
+ GC_Chat *temp = (GC_Chat *)mem_vrealloc(mem, c->chats, n, sizeof(GC_Chat));
if (temp == nullptr) {
return false;
@@ -7338,7 +7357,7 @@ static bool realloc_groupchats(GC_Session *c, uint32_t n)
}
non_null()
-static int get_new_group_index(GC_Session *c)
+static int get_new_group_index(const Memory *mem, GC_Session *c)
{
if (c == nullptr) {
return -1;
@@ -7350,7 +7369,7 @@ static int get_new_group_index(GC_Session *c)
}
}
- if (!realloc_groupchats(c, c->chats_index + 1)) {
+ if (!realloc_groupchats(mem, c, c->chats_index + 1)) {
return -1;
}
@@ -7378,7 +7397,7 @@ static void add_tcp_relays_to_chat(const GC_Session *c, GC_Chat *chat)
return;
}
- Node_format *tcp_relays = (Node_format *)calloc(num_relays, sizeof(Node_format));
+ Node_format *tcp_relays = (Node_format *)mem_valloc(chat->mem, num_relays, sizeof(Node_format));
if (tcp_relays == nullptr) {
return;
@@ -7390,7 +7409,7 @@ static void add_tcp_relays_to_chat(const GC_Session *c, GC_Chat *chat)
add_tcp_relay_global(chat->tcp_conn, &tcp_relays[i].ip_port, tcp_relays[i].public_key);
}
- free(tcp_relays);
+ mem_delete(chat->mem, tcp_relays);
}
non_null()
@@ -7399,7 +7418,7 @@ static bool init_gc_tcp_connection(const GC_Session *c, GC_Chat *chat)
const Messenger *m = c->messenger;
chat->tcp_conn = new_tcp_connections(chat->log, chat->mem, chat->rng, m->ns, chat->mono_time, chat->self_secret_key.enc,
- &m->options.proxy_info);
+ &m->options.proxy_info, c->tcp_np);
if (chat->tcp_conn == nullptr) {
return false;
@@ -7460,7 +7479,7 @@ non_null()
static bool create_new_chat_ext_keypair(GC_Chat *chat);
non_null()
-static int create_new_group(GC_Session *c, const uint8_t *nick, size_t nick_length, bool founder,
+static int create_new_group(const Memory *mem, GC_Session *c, const uint8_t *nick, size_t nick_length, bool founder,
const Group_Privacy_State privacy_state)
{
if (nick == nullptr || nick_length == 0) {
@@ -7471,7 +7490,7 @@ static int create_new_group(GC_Session *c, const uint8_t *nick, size_t nick_leng
return -1;
}
- const int group_number = get_new_group_index(c);
+ const int group_number = get_new_group_index(mem, c);
if (group_number == -1) {
return -1;
@@ -7610,7 +7629,7 @@ void gc_group_save(const GC_Chat *chat, Bin_Pack *bp)
int gc_group_load(GC_Session *c, Bin_Unpack *bu)
{
- const int group_number = get_new_group_index(c);
+ const int group_number = get_new_group_index(c->messenger->mem, c);
if (group_number < 0) {
return -1;
@@ -7680,7 +7699,7 @@ int gc_group_add(GC_Session *c, Group_Privacy_State privacy_state,
return -2;
}
- const int group_number = create_new_group(c, nick, nick_length, true, privacy_state);
+ const int group_number = create_new_group(c->messenger->mem, c, nick, nick_length, true, privacy_state);
if (group_number == -1) {
return -3;
@@ -7732,10 +7751,52 @@ int gc_group_add(GC_Session *c, Group_Privacy_State privacy_state,
return group_number;
}
+int gc_rejoin_group(GC_Session *c, GC_Chat *chat, const uint8_t *passwd, uint16_t passwd_len)
+{
+ if (c == nullptr) {
+ LOGGER_ERROR(chat->log, "NULL group session pointer.");
+ return -1;
+ }
+
+ if (passwd != nullptr && passwd_len > 0) {
+ if (!set_gc_password_local(chat, passwd, passwd_len)) {
+ LOGGER_WARNING(chat->log, "Failed to set new password during reconnect.");
+ }
+ }
+
+ chat->time_connected = 0;
+
+ if (group_can_handle_packets(chat)) {
+ send_gc_self_exit(chat, nullptr, 0);
+ }
+
+ for (uint32_t i = 1; i < chat->numpeers; ++i) {
+ GC_Connection *gconn = get_gc_connection(chat, i);
+ assert(gconn != nullptr);
+
+ gcc_mark_for_deletion(gconn, chat->tcp_conn, GC_EXIT_TYPE_SELF_DISCONNECTED, nullptr, 0);
+ }
+
+ if (is_public_chat(chat)) {
+ kill_group_friend_connection(c, chat);
+
+ if (!m_create_group_connection(c->messenger, chat)) {
+ LOGGER_WARNING(chat->log, "Failed to create new messenger connection for group");
+ return -1;
+ }
+
+ chat->update_self_announces = true;
+ }
+
+ chat->connection_state = CS_CONNECTING;
+
+ return 0;
+}
+
int gc_group_join(GC_Session *c, const uint8_t *chat_id, const uint8_t *nick, size_t nick_length, const uint8_t *passwd,
uint16_t passwd_len)
{
- if (chat_id == nullptr || group_exists(c, chat_id) || getfriend_id(c->messenger, chat_id) != -1) {
+ if (chat_id == nullptr) {
return -2;
}
@@ -7747,7 +7808,15 @@ int gc_group_join(GC_Session *c, const uint8_t *chat_id, const uint8_t *nick, si
return -4;
}
- const int group_number = create_new_group(c, nick, nick_length, false, GI_PUBLIC);
+ GC_Chat *existing_group = gc_get_group_by_public_key(c, chat_id);
+
+ // If we're already in the group we try to reconnect to it
+ if (existing_group != nullptr) {
+ const int ret = gc_rejoin_group(c, existing_group, passwd, passwd_len);
+ return ret != 0 ? -6 : ret;
+ }
+
+ const int group_number = create_new_group(c->messenger->mem, c, nick, nick_length, false, GI_PUBLIC);
if (group_number == -1) {
return -1;
@@ -7805,41 +7874,6 @@ bool gc_disconnect_from_group(const GC_Session *c, GC_Chat *chat)
return true;
}
-int gc_rejoin_group(GC_Session *c, GC_Chat *chat)
-{
- if (c == nullptr || chat == nullptr) {
- return -1;
- }
-
- chat->time_connected = 0;
-
- if (group_can_handle_packets(chat)) {
- send_gc_self_exit(chat, nullptr, 0);
- }
-
- for (uint32_t i = 1; i < chat->numpeers; ++i) {
- GC_Connection *gconn = get_gc_connection(chat, i);
- assert(gconn != nullptr);
-
- gcc_mark_for_deletion(gconn, chat->tcp_conn, GC_EXIT_TYPE_SELF_DISCONNECTED, nullptr, 0);
- }
-
- if (is_public_chat(chat)) {
- kill_group_friend_connection(c, chat);
-
- if (!m_create_group_connection(c->messenger, chat)) {
- LOGGER_WARNING(chat->log, "Failed to create new messenger connection for group");
- return -2;
- }
-
- chat->update_self_announces = true;
- }
-
- chat->connection_state = CS_CONNECTING;
-
- return 0;
-}
-
bool group_not_added(const GC_Session *c, const uint8_t *chat_id, uint32_t length)
{
if (length < CHAT_ID_SIZE) {
@@ -7860,7 +7894,7 @@ int gc_invite_friend(const GC_Session *c, GC_Chat *chat, int32_t friend_number,
assert(group_name_length <= MAX_GC_GROUP_NAME_SIZE);
- uint8_t *packet = (uint8_t *)malloc(2 + CHAT_ID_SIZE + ENC_PUBLIC_KEY_SIZE + group_name_length);
+ uint8_t *packet = (uint8_t *)mem_balloc(chat->mem, 2 + CHAT_ID_SIZE + ENC_PUBLIC_KEY_SIZE + group_name_length);
if (packet == nullptr) {
return -1;
@@ -7881,11 +7915,11 @@ int gc_invite_friend(const GC_Session *c, GC_Chat *chat, int32_t friend_number,
assert(length <= MAX_GC_PACKET_SIZE);
if (!callback(c->messenger, friend_number, packet, length)) {
- free(packet);
+ mem_delete(chat->mem, packet);
return -2;
}
- free(packet);
+ mem_delete(chat->mem, packet);
chat->saved_invites[chat->saved_invites_index] = friend_number;
chat->saved_invites_index = (chat->saved_invites_index + 1) % MAX_GC_SAVED_INVITES;
@@ -7954,7 +7988,7 @@ static bool send_gc_invite_confirmed_packet(const Messenger *m, const GC_Chat *c
}
const uint16_t packet_length = 2 + length;
- uint8_t *packet = (uint8_t *)malloc(packet_length);
+ uint8_t *packet = (uint8_t *)mem_balloc(chat->mem, packet_length);
if (packet == nullptr) {
return false;
@@ -7966,11 +8000,11 @@ static bool send_gc_invite_confirmed_packet(const Messenger *m, const GC_Chat *c
memcpy(packet + 2, data, length);
if (!send_group_invite_packet(m, friend_number, packet, packet_length)) {
- free(packet);
+ mem_delete(chat->mem, packet);
return false;
}
- free(packet);
+ mem_delete(chat->mem, packet);
return true;
}
@@ -8183,7 +8217,7 @@ int gc_accept_invite(GC_Session *c, int32_t friend_number, const uint8_t *data,
const uint8_t *chat_id = data;
const uint8_t *invite_chat_pk = data + CHAT_ID_SIZE;
- const int group_number = create_new_group(c, nick, nick_length, false, GI_PUBLIC);
+ const int group_number = create_new_group(c->messenger->mem, c, nick, nick_length, false, GI_PUBLIC);
if (group_number == -1) {
return -2;
@@ -8232,7 +8266,7 @@ GC_Session *new_dht_groupchats(Messenger *m)
return nullptr;
}
- GC_Session *c = (GC_Session *)calloc(1, sizeof(GC_Session));
+ GC_Session *c = (GC_Session *)mem_alloc(m->mem, sizeof(GC_Session));
if (c == nullptr) {
return nullptr;
@@ -8240,6 +8274,7 @@ GC_Session *new_dht_groupchats(Messenger *m)
c->messenger = m;
c->announces_list = m->group_announce;
+ c->tcp_np = m->tcp_np;
networking_registerhandler(m->net, NET_PACKET_GC_LOSSLESS, &handle_gc_udp_packet, m);
networking_registerhandler(m->net, NET_PACKET_GC_LOSSY, &handle_gc_udp_packet, m);
@@ -8263,7 +8298,7 @@ static void group_cleanup(const GC_Session *c, GC_Chat *chat)
gcc_cleanup(chat);
if (chat->group != nullptr) {
- free(chat->group);
+ mem_delete(chat->mem, chat->group);
chat->group = nullptr;
}
@@ -8298,7 +8333,7 @@ static void group_delete(GC_Session *c, GC_Chat *chat)
if (c->chats_index != i) {
c->chats_index = i;
- if (!realloc_groupchats(c, c->chats_index)) {
+ if (!realloc_groupchats(c->messenger->mem, c, c->chats_index)) {
LOGGER_ERROR(c->messenger->log, "Failed to reallocate groupchats array");
}
}
@@ -8341,8 +8376,8 @@ void kill_dht_groupchats(GC_Session *c)
networking_registerhandler(c->messenger->net, NET_PACKET_GC_HANDSHAKE, nullptr, nullptr);
onion_group_announce_register(c->messenger->onion_c, nullptr, nullptr);
- free(c->chats);
- free(c);
+ mem_delete(c->messenger->mem, c->chats);
+ mem_delete(c->messenger->mem, c);
}
bool gc_group_is_valid(const GC_Chat *chat)
@@ -8353,7 +8388,7 @@ bool gc_group_is_valid(const GC_Chat *chat)
/** Return true if `group_number` designates an active group in session `c`. */
static bool group_number_valid(const GC_Session *c, int group_number)
{
- if (group_number < 0 || group_number >= c->chats_index) {
+ if (group_number < 0 || (uint32_t)group_number >= c->chats_index) {
return false;
}
@@ -8408,19 +8443,7 @@ GC_Chat *gc_get_group_by_public_key(const GC_Session *c, const uint8_t *public_k
/** Return True if chat_id exists in the session chat array */
static bool group_exists(const GC_Session *c, const uint8_t *chat_id)
{
- for (uint32_t i = 0; i < c->chats_index; ++i) {
- const GC_Chat *chat = &c->chats[i];
-
- if (chat->connection_state == CS_NONE) {
- continue;
- }
-
- if (memcmp(get_chat_id(&chat->chat_public_key), chat_id, CHAT_ID_SIZE) == 0) {
- return true;
- }
- }
-
- return false;
+ return gc_get_group_by_public_key(c, chat_id) != nullptr;
}
/** Creates a new 32-byte session encryption keypair and puts the results in `public_key` and `secret_key`. */
diff --git a/protocols/Tox/libtox/src/toxcore/group_chats.h b/protocols/Tox/libtox/src/toxcore/group_chats.h
index 32a7323dc4..481dee19eb 100644
--- a/protocols/Tox/libtox/src/toxcore/group_chats.h
+++ b/protocols/Tox/libtox/src/toxcore/group_chats.h
@@ -22,6 +22,7 @@
#include "group_common.h"
#include "group_connection.h"
#include "logger.h"
+#include "mem.h"
#include "network.h"
#define GC_PING_TIMEOUT 12
@@ -141,9 +142,9 @@ int get_peer_number_of_enc_pk(const GC_Chat *chat, const uint8_t *public_enc_key
* Return -2 if malloc fails.
* Return -3 if encryption fails.
*/
-non_null(1, 2, 3, 4, 5) nullable(7)
+non_null(1, 2, 3, 4, 5, 6) nullable(8)
int group_packet_wrap(
- const Logger *log, const Random *rng, const uint8_t *self_pk, const uint8_t *shared_key, uint8_t *packet,
+ const Logger *log, const Memory *mem, const Random *rng, const uint8_t *self_pk, const uint8_t *shared_key, uint8_t *packet,
uint16_t packet_size, const uint8_t *data, uint16_t length, uint64_t message_id,
uint8_t gp_packet_type, Net_Packet_Type net_packet_type);
@@ -181,9 +182,9 @@ int gc_send_message(const GC_Chat *chat, const uint8_t *message, uint16_t length
* Returns -5 if the sender has the observer role.
* Returns -6 if the packet fails to send.
*/
-non_null()
+non_null(1, 4) nullable(6)
int gc_send_private_message(const GC_Chat *chat, GC_Peer_Id peer_id, uint8_t type, const uint8_t *message,
- uint16_t length);
+ uint16_t length, uint32_t *message_id);
/** @brief Sends a custom packet to the group. If lossless is true, the packet will be lossless.
*
@@ -192,8 +193,7 @@ int gc_send_private_message(const GC_Chat *chat, GC_Peer_Id peer_id, uint8_t typ
* Returns 0 on success.
* Returns -1 if the message is too long.
* Returns -2 if the message pointer is NULL or length is zero.
- * Returns -3 if the sender has the observer role.
- * Returns -4 if the packet did not successfully send to any peer.
+ * Returns -3 if the packet did not successfully send to any peer.
*/
non_null()
int gc_send_custom_packet(const GC_Chat *chat, bool lossless, const uint8_t *data, uint16_t length);
@@ -206,8 +206,7 @@ int gc_send_custom_packet(const GC_Chat *chat, bool lossless, const uint8_t *dat
* @retval -1 if the message is too long.
* @retval -2 if the message pointer is NULL or length is zero.
* @retval -3 if the supplied peer_id does not designate a valid peer.
- * @retval -4 if the sender has the observer role.
- * @retval -5 if the packet fails to send.
+ * @retval -4 if the packet fails to send.
*/
non_null()
int gc_send_custom_private_packet(const GC_Chat *chat, bool lossless, GC_Peer_Id peer_id, const uint8_t *message,
@@ -651,7 +650,7 @@ int gc_group_add(GC_Session *c, Group_Privacy_State privacy_state, const uint8_t
*
* Return group_number on success.
* Return -1 if the group object fails to initialize.
- * Return -2 if chat_id is NULL or a group with chat_id already exists in the chats array.
+ * Return -2 if chat_id is NULL.
* Return -3 if nick is too long.
* Return -4 if nick is empty or nick length is zero.
* Return -5 if there is an error setting the group password.
@@ -677,8 +676,8 @@ bool gc_disconnect_from_group(const GC_Session *c, GC_Chat *chat);
* Returns -1 if the group handler object or chat object is null.
* Returns -2 if the Messenger friend connection fails to initialize.
*/
-non_null()
-int gc_rejoin_group(GC_Session *c, GC_Chat *chat);
+non_null(1, 2) nullable(3)
+int gc_rejoin_group(GC_Session *c, GC_Chat *chat, const uint8_t *passwd, uint16_t passwd_len);
/** @brief Joins a group using the invite data received in a friend's group invite.
*
diff --git a/protocols/Tox/libtox/src/toxcore/group_common.h b/protocols/Tox/libtox/src/toxcore/group_common.h
index bb1e6f9a64..19217706a7 100644
--- a/protocols/Tox/libtox/src/toxcore/group_common.h
+++ b/protocols/Tox/libtox/src/toxcore/group_common.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2022 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
*/
/**
@@ -20,6 +20,7 @@
#include "logger.h"
#include "mem.h"
#include "mono_time.h"
+#include "net_profile.h"
#include "network.h"
#define MAX_GC_PART_MESSAGE_SIZE 128
@@ -52,7 +53,7 @@
#define MAX_GC_PACKET_SIZE (MAX_GC_PACKET_CHUNK_SIZE * 100)
/* Max number of messages to store in the send/recv arrays */
-#define GCC_BUFFER_SIZE 8192
+#define GCC_BUFFER_SIZE 2048
/** Self UDP status. Must correspond to return values from `ipport_self_copy()`. */
typedef enum Self_UDP_Status {
@@ -114,6 +115,7 @@ typedef struct GC_Connection {
uint64_t last_sent_tcp_relays_time; /* the last time we attempted to send this peer our tcp relays */
uint16_t tcp_relay_share_index;
uint64_t last_received_direct_time; /* the last time we received a direct UDP packet from this connection */
+ uint64_t last_sent_direct_try_time; /* the last time we tried sending a direct UDP packet */
uint64_t last_sent_ip_time; /* the last time we sent our ip info to this peer in a ping packet */
Node_format connected_tcp_relays[MAX_FRIEND_TCP_CONNECTIONS];
@@ -348,7 +350,7 @@ typedef struct Messenger Messenger;
typedef void gc_message_cb(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id, unsigned int type,
const uint8_t *message, size_t length, uint32_t message_id, void *user_data);
typedef void gc_private_message_cb(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id, unsigned int type,
- const uint8_t *message, size_t length, void *user_data);
+ const uint8_t *message, size_t length, uint32_t message_id, void *user_data);
typedef void gc_custom_packet_cb(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id, const uint8_t *data,
size_t length, void *user_data);
typedef void gc_custom_private_packet_cb(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id,
@@ -377,6 +379,7 @@ typedef void gc_rejected_cb(const Messenger *m, uint32_t group_number, unsigned
typedef struct GC_Session {
Messenger *messenger;
GC_Chat *chats;
+ Net_Profile *tcp_np;
struct GC_Announces_List *announces_list;
uint32_t chats_index;
diff --git a/protocols/Tox/libtox/src/toxcore/group_connection.c b/protocols/Tox/libtox/src/toxcore/group_connection.c
index 1c2d1ec3da..dd6d21fd7c 100644
--- a/protocols/Tox/libtox/src/toxcore/group_connection.c
+++ b/protocols/Tox/libtox/src/toxcore/group_connection.c
@@ -11,7 +11,6 @@
#include <assert.h>
#include <stdint.h>
-#include <stdlib.h>
#include <string.h>
#include "DHT.h"
@@ -22,6 +21,7 @@
#include "group_chats.h"
#include "group_common.h"
#include "logger.h"
+#include "mem.h"
#include "mono_time.h"
#include "network.h"
#include "util.h"
@@ -29,6 +29,9 @@
/** Seconds since last direct UDP packet was received before the connection is considered dead */
#define GCC_UDP_DIRECT_TIMEOUT (GC_PING_TIMEOUT + 4)
+/** Seconds since last direct UDP packet was sent before we can try again. Cheap NAT hole punch */
+#define GCC_UDP_DIRECT_RETRY 1
+
/** Returns true if array entry does not contain an active packet. */
non_null()
static bool array_entry_is_empty(const GC_Message_Array_Entry *array_entry)
@@ -39,9 +42,9 @@ static bool array_entry_is_empty(const GC_Message_Array_Entry *array_entry)
/** @brief Clears an array entry. */
non_null()
-static void clear_array_entry(GC_Message_Array_Entry *const array_entry)
+static void clear_array_entry(const Memory *mem, GC_Message_Array_Entry *const array_entry)
{
- free(array_entry->data);
+ mem_delete(mem, array_entry->data);
*array_entry = (GC_Message_Array_Entry) {
nullptr
@@ -54,14 +57,14 @@ static void clear_array_entry(GC_Message_Array_Entry *const array_entry)
* to `start_id`.
*/
non_null()
-static void clear_send_queue_id_range(GC_Connection *gconn, uint64_t start_id, uint64_t end_id)
+static void clear_send_queue_id_range(const Memory *mem, GC_Connection *gconn, uint64_t start_id, uint64_t end_id)
{
const uint16_t start_idx = gcc_get_array_index(start_id);
const uint16_t end_idx = gcc_get_array_index(end_id);
for (uint16_t i = start_idx; i != end_idx; i = (i + 1) % GCC_BUFFER_SIZE) {
GC_Message_Array_Entry *entry = &gconn->send_array[i];
- clear_array_entry(entry);
+ clear_array_entry(mem, entry);
}
gconn->send_message_id = start_id;
@@ -90,8 +93,8 @@ void gcc_set_recv_message_id(GC_Connection *gconn, uint64_t id)
*
* Return true on success.
*/
-non_null(1, 2, 3) nullable(4)
-static bool create_array_entry(const Logger *log, const Mono_Time *mono_time, GC_Message_Array_Entry *array_entry,
+non_null(1, 2, 3, 4) nullable(5)
+static bool create_array_entry(const Logger *log, const Memory *mem, const Mono_Time *mono_time, GC_Message_Array_Entry *array_entry,
const uint8_t *data, uint16_t length, uint8_t packet_type, uint64_t message_id)
{
if (!array_entry_is_empty(array_entry)) {
@@ -109,7 +112,7 @@ static bool create_array_entry(const Logger *log, const Mono_Time *mono_time, GC
return false;
}
- uint8_t *entry_data = (uint8_t *)malloc(length);
+ uint8_t *entry_data = (uint8_t *)mem_balloc(mem, length);
if (entry_data == nullptr) {
return false;
@@ -134,9 +137,9 @@ static bool create_array_entry(const Logger *log, const Mono_Time *mono_time, GC
*
* Returns true and increments gconn's send_message_id on success.
*/
-non_null(1, 2, 3) nullable(4)
-static bool add_to_send_array(const Logger *log, const Mono_Time *mono_time, GC_Connection *gconn, const uint8_t *data,
- uint16_t length, uint8_t packet_type)
+non_null(1, 2, 3, 4) nullable(5)
+static bool add_to_send_array(const Logger *log, const Memory *mem, const Mono_Time *mono_time, GC_Connection *gconn,
+ const uint8_t *data, uint16_t length, uint8_t packet_type)
{
/* check if send_array is full */
if ((gconn->send_message_id % GCC_BUFFER_SIZE) == (uint16_t)(gconn->send_array_start - 1)) {
@@ -147,7 +150,7 @@ static bool add_to_send_array(const Logger *log, const Mono_Time *mono_time, GC_
const uint16_t idx = gcc_get_array_index(gconn->send_message_id);
GC_Message_Array_Entry *array_entry = &gconn->send_array[idx];
- if (!create_array_entry(log, mono_time, array_entry, data, length, packet_type, gconn->send_message_id)) {
+ if (!create_array_entry(log, mem, mono_time, array_entry, data, length, packet_type, gconn->send_message_id)) {
return false;
}
@@ -161,7 +164,7 @@ int gcc_send_lossless_packet(const GC_Chat *chat, GC_Connection *gconn, const ui
{
const uint64_t message_id = gconn->send_message_id;
- if (!add_to_send_array(chat->log, chat->mono_time, gconn, data, length, packet_type)) {
+ if (!add_to_send_array(chat->log, chat->mem, chat->mono_time, gconn, data, length, packet_type)) {
LOGGER_WARNING(chat->log, "Failed to add payload to send array: (type: 0x%02x, length: %d)", packet_type, length);
return -1;
}
@@ -172,7 +175,7 @@ int gcc_send_lossless_packet(const GC_Chat *chat, GC_Connection *gconn, const ui
if (gcc_encrypt_and_send_lossless_packet(chat, gconn, data, length, message_id, packet_type) == -1) {
const uint16_t idx = gcc_get_array_index(message_id);
GC_Message_Array_Entry *array_entry = &gconn->send_array[idx];
- clear_array_entry(array_entry);
+ clear_array_entry(chat->mem, array_entry);
gconn->send_message_id = message_id;
LOGGER_ERROR(chat->log, "Failed to encrypt payload: (type: 0x%02x, length: %d)", packet_type, length);
return -2;
@@ -196,7 +199,7 @@ bool gcc_send_lossless_packet_fragments(const GC_Chat *chat, GC_Connection *gcon
chunk[0] = packet_type;
memcpy(chunk + 1, data, MAX_GC_PACKET_CHUNK_SIZE - 1);
- if (!add_to_send_array(chat->log, chat->mono_time, gconn, chunk, MAX_GC_PACKET_CHUNK_SIZE, GP_FRAGMENT)) {
+ if (!add_to_send_array(chat->log, chat->mem, chat->mono_time, gconn, chunk, MAX_GC_PACKET_CHUNK_SIZE, GP_FRAGMENT)) {
return false;
}
@@ -209,15 +212,15 @@ bool gcc_send_lossless_packet_fragments(const GC_Chat *chat, GC_Connection *gcon
memcpy(chunk, data + processed, chunk_len);
processed += chunk_len;
- if (!add_to_send_array(chat->log, chat->mono_time, gconn, chunk, chunk_len, GP_FRAGMENT)) {
- clear_send_queue_id_range(gconn, start_id, gconn->send_message_id);
+ if (!add_to_send_array(chat->log, chat->mem, chat->mono_time, gconn, chunk, chunk_len, GP_FRAGMENT)) {
+ clear_send_queue_id_range(chat->mem, gconn, start_id, gconn->send_message_id);
return false;
}
}
// empty packet signals the end of the sequence
- if (!add_to_send_array(chat->log, chat->mono_time, gconn, nullptr, 0, GP_FRAGMENT)) {
- clear_send_queue_id_range(gconn, start_id, gconn->send_message_id);
+ if (!add_to_send_array(chat->log, chat->mem, chat->mono_time, gconn, nullptr, 0, GP_FRAGMENT)) {
+ clear_send_queue_id_range(chat->mem, gconn, start_id, gconn->send_message_id);
return false;
}
@@ -241,7 +244,7 @@ bool gcc_send_lossless_packet_fragments(const GC_Chat *chat, GC_Connection *gcon
return true;
}
-bool gcc_handle_ack(const Logger *log, GC_Connection *gconn, uint64_t message_id)
+bool gcc_handle_ack(const Logger *log, const Memory *mem, GC_Connection *gconn, uint64_t message_id)
{
uint16_t idx = gcc_get_array_index(message_id);
GC_Message_Array_Entry *array_entry = &gconn->send_array[idx];
@@ -255,7 +258,7 @@ bool gcc_handle_ack(const Logger *log, GC_Connection *gconn, uint64_t message_id
return false;
}
- clear_array_entry(array_entry);
+ clear_array_entry(mem, array_entry);
/* Put send_array_start in proper position */
if (idx == gconn->send_array_start) {
@@ -336,15 +339,15 @@ int gcc_save_tcp_relay(const Random *rng, GC_Connection *gconn, const Node_forma
*
* Return true on success.
*/
-non_null(1, 2, 3) nullable(4)
-static bool store_in_recv_array(const Logger *log, const Mono_Time *mono_time, GC_Connection *gconn,
- const uint8_t *data,
+non_null(1, 2, 3, 4) nullable(5)
+static bool store_in_recv_array(const Logger *log, const Memory *mem, const Mono_Time *mono_time,
+ GC_Connection *gconn, const uint8_t *data,
uint16_t length, uint8_t packet_type, uint64_t message_id)
{
const uint16_t idx = gcc_get_array_index(message_id);
GC_Message_Array_Entry *ary_entry = &gconn->recv_array[idx];
- return create_array_entry(log, mono_time, ary_entry, data, length, packet_type, message_id);
+ return create_array_entry(log, mem, mono_time, ary_entry, data, length, packet_type, message_id);
}
/**
@@ -358,8 +361,8 @@ static bool store_in_recv_array(const Logger *log, const Mono_Time *mono_time, G
* Return the length of the fully reassembled packet on success.
* Return 0 on failure.
*/
-non_null(1, 3) nullable(2)
-static uint16_t reassemble_packet(const Logger *log, GC_Connection *gconn, uint8_t **payload, uint64_t message_id)
+non_null(1, 2, 4) nullable(3)
+static uint16_t reassemble_packet(const Logger *log, const Memory *mem, GC_Connection *gconn, uint8_t **payload, uint64_t message_id)
{
uint16_t end_idx = gcc_get_array_index(message_id - 1);
uint16_t start_idx = end_idx;
@@ -395,7 +398,7 @@ static uint16_t reassemble_packet(const Logger *log, GC_Connection *gconn, uint8
return 0;
}
- uint8_t *tmp_payload = (uint8_t *)malloc(packet_length);
+ uint8_t *tmp_payload = (uint8_t *)mem_balloc(mem, packet_length);
if (tmp_payload == nullptr) {
LOGGER_ERROR(log, "Failed to allocate %u bytes for payload buffer", packet_length);
@@ -414,7 +417,7 @@ static uint16_t reassemble_packet(const Logger *log, GC_Connection *gconn, uint8
memcpy(tmp_payload + processed, entry->data, entry->data_length);
processed += entry->data_length;
- clear_array_entry(entry);
+ clear_array_entry(mem, entry);
}
assert(*payload == nullptr);
@@ -428,7 +431,7 @@ int gcc_handle_packet_fragment(const GC_Session *c, GC_Chat *chat, uint32_t peer
uint64_t message_id, void *userdata)
{
if (length > 0) {
- if (!store_in_recv_array(chat->log, chat->mono_time, gconn, chunk, length, packet_type, message_id)) {
+ if (!store_in_recv_array(chat->log, chat->mem, chat->mono_time, gconn, chunk, length, packet_type, message_id)) {
return -1;
}
@@ -442,15 +445,15 @@ int gcc_handle_packet_fragment(const GC_Session *c, GC_Chat *chat, uint32_t peer
memcpy(sender_pk, get_enc_key(&gconn->addr.public_key), ENC_PUBLIC_KEY_SIZE);
uint8_t *payload = nullptr;
- const uint16_t processed_len = reassemble_packet(chat->log, gconn, &payload, message_id);
+ const uint16_t processed_len = reassemble_packet(chat->log, chat->mem, gconn, &payload, message_id);
if (processed_len == 0) {
- free(payload);
+ mem_delete(chat->mem, payload);
return -1;
}
if (!handle_gc_lossless_helper(c, chat, peer_number, payload + 1, processed_len - 1, payload[0], userdata)) {
- free(payload);
+ mem_delete(chat->mem, payload);
return -1;
}
@@ -459,19 +462,19 @@ int gcc_handle_packet_fragment(const GC_Session *c, GC_Chat *chat, uint32_t peer
gconn = get_gc_connection(chat, peer_number);
if (gconn == nullptr) {
- free(payload);
+ mem_delete(chat->mem, payload);
return 0;
}
gcc_set_recv_message_id(gconn, gconn->received_message_id + 1);
gconn->last_chunk_id = 0;
- free(payload);
+ mem_delete(chat->mem, payload);
return 0;
}
-int gcc_handle_received_message(const Logger *log, const Mono_Time *mono_time, GC_Connection *gconn,
+int gcc_handle_received_message(const Logger *log, const Memory *mem, const Mono_Time *mono_time, GC_Connection *gconn,
const uint8_t *data, uint16_t length, uint8_t packet_type, uint64_t message_id,
bool direct_conn)
{
@@ -490,7 +493,7 @@ int gcc_handle_received_message(const Logger *log, const Mono_Time *mono_time, G
/* we're missing an older message from this peer so we store it in recv_array */
if (message_id > gconn->received_message_id + 1) {
- if (!store_in_recv_array(log, mono_time, gconn, data, length, packet_type, message_id)) {
+ if (!store_in_recv_array(log, mem, mono_time, gconn, data, length, packet_type, message_id)) {
return -1;
}
@@ -522,7 +525,7 @@ static bool process_recv_array_entry(const GC_Session *c, GC_Chat *chat, GC_Conn
peer_number = get_peer_number_of_enc_pk(chat, sender_pk, false);
gconn = get_gc_connection(chat, peer_number);
- clear_array_entry(array_entry);
+ clear_array_entry(chat->mem, array_entry);
if (gconn == nullptr) {
return true;
@@ -595,7 +598,7 @@ void gcc_resend_packets(const GC_Chat *chat, GC_Connection *gconn)
}
}
-bool gcc_send_packet(const GC_Chat *chat, const GC_Connection *gconn, const uint8_t *packet, uint16_t length)
+bool gcc_send_packet(const GC_Chat *chat, GC_Connection *gconn, const uint8_t *packet, uint16_t length)
{
if (packet == nullptr || length == 0) {
return false;
@@ -608,8 +611,12 @@ bool gcc_send_packet(const GC_Chat *chat, const GC_Connection *gconn, const uint
return (uint16_t) sendpacket(chat->net, &gconn->addr.ip_port, packet, length) == length;
}
- if ((uint16_t) sendpacket(chat->net, &gconn->addr.ip_port, packet, length) == length) {
- direct_send_attempt = true;
+ if (gcc_conn_should_try_direct(chat->mono_time, gconn)) {
+ gconn->last_sent_direct_try_time = mono_time_get(chat->mono_time);
+
+ if ((uint16_t) sendpacket(chat->net, &gconn->addr.ip_port, packet, length) == length) {
+ direct_send_attempt = true;
+ }
}
}
@@ -617,11 +624,11 @@ bool gcc_send_packet(const GC_Chat *chat, const GC_Connection *gconn, const uint
return ret == 0 || direct_send_attempt;
}
-int gcc_encrypt_and_send_lossless_packet(const GC_Chat *chat, const GC_Connection *gconn, const uint8_t *data,
+int gcc_encrypt_and_send_lossless_packet(const GC_Chat *chat, GC_Connection *gconn, const uint8_t *data,
uint16_t length, uint64_t message_id, uint8_t packet_type)
{
const uint16_t packet_size = gc_get_wrapped_packet_size(length, NET_PACKET_GC_LOSSLESS);
- uint8_t *packet = (uint8_t *)malloc(packet_size);
+ uint8_t *packet = (uint8_t *)mem_balloc(chat->mem, packet_size);
if (packet == nullptr) {
LOGGER_ERROR(chat->log, "Failed to allocate memory for packet buffer");
@@ -629,22 +636,22 @@ int gcc_encrypt_and_send_lossless_packet(const GC_Chat *chat, const GC_Connectio
}
const int enc_len = group_packet_wrap(
- chat->log, chat->rng, chat->self_public_key.enc, gconn->session_shared_key, packet,
+ chat->log, chat->mem, chat->rng, chat->self_public_key.enc, gconn->session_shared_key, packet,
packet_size, data, length, message_id, packet_type, NET_PACKET_GC_LOSSLESS);
if (enc_len < 0) {
LOGGER_ERROR(chat->log, "Failed to wrap packet (type: 0x%02x, error: %d)", packet_type, enc_len);
- free(packet);
+ mem_delete(chat->mem, packet);
return -1;
}
if (!gcc_send_packet(chat, gconn, packet, (uint16_t)enc_len)) {
LOGGER_DEBUG(chat->log, "Failed to send packet (type: 0x%02x, enc_len: %d)", packet_type, enc_len);
- free(packet);
+ mem_delete(chat->mem, packet);
return -2;
}
- free(packet);
+ mem_delete(chat->mem, packet);
return 0;
}
@@ -659,6 +666,11 @@ bool gcc_conn_is_direct(const Mono_Time *mono_time, const GC_Connection *gconn)
return GCC_UDP_DIRECT_TIMEOUT + gconn->last_received_direct_time > mono_time_get(mono_time);
}
+bool gcc_conn_should_try_direct(const Mono_Time *mono_time, const GC_Connection *gconn)
+{
+ return mono_time_is_timeout(mono_time, gconn->last_sent_direct_try_time, GCC_UDP_DIRECT_RETRY);
+}
+
bool gcc_direct_conn_is_possible(const GC_Chat *chat, const GC_Connection *gconn)
{
return !net_family_is_unspec(gconn->addr.ip_port.ip.family) && !net_family_is_unspec(net_family(chat->net));
@@ -686,15 +698,15 @@ void gcc_mark_for_deletion(GC_Connection *gconn, TCP_Connections *tcp_conn, Grou
}
}
-void gcc_peer_cleanup(GC_Connection *gconn)
+void gcc_peer_cleanup(const Memory *mem, GC_Connection *gconn)
{
for (size_t i = 0; i < GCC_BUFFER_SIZE; ++i) {
- free(gconn->send_array[i].data);
- free(gconn->recv_array[i].data);
+ mem_delete(mem, gconn->send_array[i].data);
+ mem_delete(mem, gconn->recv_array[i].data);
}
- free(gconn->recv_array);
- free(gconn->send_array);
+ mem_delete(mem, gconn->recv_array);
+ mem_delete(mem, gconn->send_array);
crypto_memunlock(gconn->session_secret_key, sizeof(gconn->session_secret_key));
crypto_memunlock(gconn->session_shared_key, sizeof(gconn->session_shared_key));
@@ -707,6 +719,6 @@ void gcc_cleanup(const GC_Chat *chat)
GC_Connection *gconn = get_gc_connection(chat, i);
assert(gconn != nullptr);
- gcc_peer_cleanup(gconn);
+ gcc_peer_cleanup(chat->mem, gconn);
}
}
diff --git a/protocols/Tox/libtox/src/toxcore/group_connection.h b/protocols/Tox/libtox/src/toxcore/group_connection.h
index 4a9ccad0b3..7122f7a12d 100644
--- a/protocols/Tox/libtox/src/toxcore/group_connection.h
+++ b/protocols/Tox/libtox/src/toxcore/group_connection.h
@@ -16,6 +16,7 @@
#include "crypto_core.h"
#include "group_common.h"
#include "logger.h"
+#include "mem.h"
#include "mono_time.h"
#include "network.h"
@@ -35,8 +36,8 @@ void gcc_mark_for_deletion(GC_Connection *gconn, TCP_Connections *tcp_conn, Grou
* Return 0 if message is a duplicate.
* Return -1 on failure
*/
-non_null(1, 2, 3) nullable(4)
-int gcc_handle_received_message(const Logger *log, const Mono_Time *mono_time, GC_Connection *gconn,
+non_null(1, 2, 3, 4) nullable(5)
+int gcc_handle_received_message(const Logger *log, const Memory *mem, const Mono_Time *mono_time, GC_Connection *gconn,
const uint8_t *data, uint16_t length, uint8_t packet_type, uint64_t message_id,
bool direct_conn);
@@ -63,7 +64,7 @@ uint16_t gcc_get_array_index(uint64_t message_id);
* Return true on success.
*/
non_null()
-bool gcc_handle_ack(const Logger *log, GC_Connection *gconn, uint64_t message_id);
+bool gcc_handle_ack(const Logger *log, const Memory *mem, GC_Connection *gconn, uint64_t message_id);
/** @brief Sets the send_message_id and send_array_start for `gconn` to `id`.
*
@@ -134,6 +135,10 @@ void gcc_make_session_shared_key(GC_Connection *gconn, const uint8_t *sender_pk)
non_null()
bool gcc_conn_is_direct(const Mono_Time *mono_time, const GC_Connection *gconn);
+/** @brief Return true if we can try a direct connection with `gconn` again. */
+non_null()
+bool gcc_conn_should_try_direct(const Mono_Time *mono_time, const GC_Connection *gconn);
+
/** @brief Return true if a direct UDP connection is possible with `gconn`. */
non_null()
bool gcc_direct_conn_is_possible(const GC_Chat *chat, const GC_Connection *gconn);
@@ -145,7 +150,7 @@ bool gcc_direct_conn_is_possible(const GC_Chat *chat, const GC_Connection *gconn
* Return true on success.
*/
non_null()
-bool gcc_send_packet(const GC_Chat *chat, const GC_Connection *gconn, const uint8_t *packet, uint16_t length);
+bool gcc_send_packet(const GC_Chat *chat, GC_Connection *gconn, const uint8_t *packet, uint16_t length);
/** @brief Sends a lossless packet to `gconn` comprised of `data` of size `length`.
*
@@ -183,12 +188,12 @@ bool gcc_send_lossless_packet_fragments(const GC_Chat *chat, GC_Connection *gcon
* Return -2 if the packet fails to send.
*/
non_null(1, 2) nullable(3)
-int gcc_encrypt_and_send_lossless_packet(const GC_Chat *chat, const GC_Connection *gconn, const uint8_t *data,
+int gcc_encrypt_and_send_lossless_packet(const GC_Chat *chat, GC_Connection *gconn, const uint8_t *data,
uint16_t length, uint64_t message_id, uint8_t packet_type);
/** @brief Called when a peer leaves the group. */
non_null()
-void gcc_peer_cleanup(GC_Connection *gconn);
+void gcc_peer_cleanup(const Memory *mem, GC_Connection *gconn);
/** @brief Called on group exit. */
non_null()
diff --git a/protocols/Tox/libtox/src/toxcore/group_moderation.c b/protocols/Tox/libtox/src/toxcore/group_moderation.c
index 3cb69e9403..acc17bd570 100644
--- a/protocols/Tox/libtox/src/toxcore/group_moderation.c
+++ b/protocols/Tox/libtox/src/toxcore/group_moderation.c
@@ -11,7 +11,6 @@
#include <assert.h>
-#include <stdlib.h>
#include <string.h>
#include <time.h>
@@ -20,6 +19,7 @@
#include "ccompat.h"
#include "crypto_core.h"
#include "logger.h"
+#include "mem.h"
#include "network.h"
#include "util.h"
@@ -51,7 +51,7 @@ int mod_list_unpack(Moderation *moderation, const uint8_t *data, uint16_t length
return 0;
}
- uint8_t **tmp_list = (uint8_t **)calloc(num_mods, sizeof(uint8_t *));
+ uint8_t **tmp_list = (uint8_t **)mem_valloc(moderation->mem, num_mods, sizeof(uint8_t *));
if (tmp_list == nullptr) {
return -1;
@@ -60,7 +60,7 @@ int mod_list_unpack(Moderation *moderation, const uint8_t *data, uint16_t length
uint16_t unpacked_len = 0;
for (uint16_t i = 0; i < num_mods; ++i) {
- uint8_t *entry = (uint8_t *)malloc(MOD_LIST_ENTRY_SIZE);
+ uint8_t *entry = (uint8_t *)mem_balloc(moderation->mem, MOD_LIST_ENTRY_SIZE);
if (entry == nullptr) {
free_uint8_t_pointer_array(moderation->mem, tmp_list, i);
@@ -102,7 +102,7 @@ bool mod_list_make_hash(const Moderation *moderation, uint8_t *hash)
assert(data_buf_size > 0);
- uint8_t *data = (uint8_t *)malloc(data_buf_size);
+ uint8_t *data = (uint8_t *)mem_balloc(moderation->mem, data_buf_size);
if (data == nullptr) {
return false;
@@ -112,7 +112,7 @@ bool mod_list_make_hash(const Moderation *moderation, uint8_t *hash)
mod_list_get_data_hash(hash, data, data_buf_size);
- free(data);
+ mem_delete(moderation->mem, data);
return true;
}
@@ -166,10 +166,10 @@ bool mod_list_remove_index(Moderation *moderation, uint16_t index)
MOD_LIST_ENTRY_SIZE);
}
- free(moderation->mod_list[moderation->num_mods]);
+ mem_delete(moderation->mem, moderation->mod_list[moderation->num_mods]);
moderation->mod_list[moderation->num_mods] = nullptr;
- uint8_t **tmp_list = (uint8_t **)realloc(moderation->mod_list, moderation->num_mods * sizeof(uint8_t *));
+ uint8_t **tmp_list = (uint8_t **)mem_vrealloc(moderation->mem, moderation->mod_list, moderation->num_mods, sizeof(uint8_t *));
if (tmp_list == nullptr) {
return false;
@@ -203,7 +203,7 @@ bool mod_list_add_entry(Moderation *moderation, const uint8_t *mod_data)
return false;
}
- uint8_t **tmp_list = (uint8_t **)realloc(moderation->mod_list, (moderation->num_mods + 1) * sizeof(uint8_t *));
+ uint8_t **tmp_list = (uint8_t **)mem_vrealloc(moderation->mem, moderation->mod_list, moderation->num_mods + 1, sizeof(uint8_t *));
if (tmp_list == nullptr) {
return false;
@@ -211,7 +211,7 @@ bool mod_list_add_entry(Moderation *moderation, const uint8_t *mod_data)
moderation->mod_list = tmp_list;
- uint8_t *entry = (uint8_t *)malloc(MOD_LIST_ENTRY_SIZE);
+ uint8_t *entry = (uint8_t *)mem_balloc(moderation->mem, MOD_LIST_ENTRY_SIZE);
if (entry == nullptr) {
return false;
@@ -405,8 +405,8 @@ int sanctions_list_unpack(Mod_Sanction *sanctions, Mod_Sanction_Creds *creds, ui
*
* Return true on success.
*/
-non_null(4) nullable(1)
-static bool sanctions_list_make_hash(const Mod_Sanction *sanctions, uint32_t new_version, uint16_t num_sanctions,
+non_null(1, 5) nullable(2)
+static bool sanctions_list_make_hash(const Memory *mem, const Mod_Sanction *sanctions, uint32_t new_version, uint16_t num_sanctions,
uint8_t *hash)
{
if (num_sanctions == 0 || sanctions == nullptr) {
@@ -422,7 +422,7 @@ static bool sanctions_list_make_hash(const Mod_Sanction *sanctions, uint32_t new
return false;
}
- uint8_t *data = (uint8_t *)malloc(data_buf_size);
+ uint8_t *data = (uint8_t *)mem_balloc(mem, data_buf_size);
if (data == nullptr) {
return false;
@@ -435,7 +435,7 @@ static bool sanctions_list_make_hash(const Mod_Sanction *sanctions, uint32_t new
memcpy(&data[sig_data_size], &new_version, sizeof(uint32_t));
crypto_sha256(hash, data, data_buf_size);
- free(data);
+ mem_delete(mem, data);
return true;
}
@@ -492,7 +492,7 @@ bool sanctions_list_make_creds(Moderation *moderation)
uint8_t hash[MOD_SANCTION_HASH_SIZE];
- if (!sanctions_list_make_hash(moderation->sanctions, moderation->sanctions_creds.version,
+ if (!sanctions_list_make_hash(moderation->mem, moderation->sanctions, moderation->sanctions_creds.version,
moderation->num_sanctions, hash)) {
moderation->sanctions_creds = old_creds;
return false;
@@ -533,7 +533,7 @@ static bool sanctions_creds_validate(const Moderation *moderation, const Mod_San
uint8_t hash[MOD_SANCTION_HASH_SIZE];
- if (!sanctions_list_make_hash(sanctions, creds->version, num_sanctions, hash)) {
+ if (!sanctions_list_make_hash(moderation->mem, sanctions, creds->version, num_sanctions, hash)) {
return false;
}
@@ -612,9 +612,9 @@ static bool sanctions_apply_new(Moderation *moderation, Mod_Sanction *new_sancti
* memory returned by this function.
*/
non_null()
-static Mod_Sanction *sanctions_list_copy(const Mod_Sanction *sanctions, uint16_t num_sanctions)
+static Mod_Sanction *sanctions_list_copy(const Memory *mem, const Mod_Sanction *sanctions, uint16_t num_sanctions)
{
- Mod_Sanction *copy = (Mod_Sanction *)calloc(num_sanctions, sizeof(Mod_Sanction));
+ Mod_Sanction *copy = (Mod_Sanction *)mem_valloc(mem, num_sanctions, sizeof(Mod_Sanction));
if (copy == nullptr) {
return nullptr;
@@ -655,7 +655,7 @@ static bool sanctions_list_remove_index(Moderation *moderation, uint16_t index,
}
/* Operate on a copy of the list in case something goes wrong. */
- Mod_Sanction *sanctions_copy = sanctions_list_copy(moderation->sanctions, moderation->num_sanctions);
+ Mod_Sanction *sanctions_copy = sanctions_list_copy(moderation->mem, moderation->sanctions, moderation->num_sanctions);
if (sanctions_copy == nullptr) {
return false;
@@ -665,15 +665,15 @@ static bool sanctions_list_remove_index(Moderation *moderation, uint16_t index,
sanctions_copy[index] = sanctions_copy[new_num];
}
- Mod_Sanction *new_list = (Mod_Sanction *)realloc(sanctions_copy, new_num * sizeof(Mod_Sanction));
+ Mod_Sanction *new_list = (Mod_Sanction *)mem_vrealloc(moderation->mem, sanctions_copy, new_num, sizeof(Mod_Sanction));
if (new_list == nullptr) {
- free(sanctions_copy);
+ mem_delete(moderation->mem, sanctions_copy);
return false;
}
if (!sanctions_apply_new(moderation, new_list, creds, new_num)) {
- free(new_list);
+ mem_delete(moderation->mem, new_list);
return false;
}
@@ -753,7 +753,7 @@ bool sanctions_list_add_entry(Moderation *moderation, const Mod_Sanction *sancti
Mod_Sanction *sanctions_copy = nullptr;
if (moderation->num_sanctions > 0) {
- sanctions_copy = sanctions_list_copy(moderation->sanctions, moderation->num_sanctions);
+ sanctions_copy = sanctions_list_copy(moderation->mem, moderation->sanctions, moderation->num_sanctions);
if (sanctions_copy == nullptr) {
return false;
@@ -761,17 +761,17 @@ bool sanctions_list_add_entry(Moderation *moderation, const Mod_Sanction *sancti
}
const uint16_t index = moderation->num_sanctions;
- Mod_Sanction *new_list = (Mod_Sanction *)realloc(sanctions_copy, (index + 1) * sizeof(Mod_Sanction));
+ Mod_Sanction *new_list = (Mod_Sanction *)mem_vrealloc(moderation->mem, sanctions_copy, index + 1, sizeof(Mod_Sanction));
if (new_list == nullptr) {
- free(sanctions_copy);
+ mem_delete(moderation->mem, sanctions_copy);
return false;
}
new_list[index] = *sanction;
if (!sanctions_apply_new(moderation, new_list, creds, index + 1)) {
- free(new_list);
+ mem_delete(moderation->mem, new_list);
return false;
}
@@ -864,7 +864,7 @@ uint16_t sanctions_list_replace_sig(Moderation *moderation, const uint8_t *publi
void sanctions_list_cleanup(Moderation *moderation)
{
- free(moderation->sanctions);
+ mem_delete(moderation->mem, moderation->sanctions);
moderation->sanctions = nullptr;
moderation->num_sanctions = 0;
diff --git a/protocols/Tox/libtox/src/toxcore/group_onion_announce.c b/protocols/Tox/libtox/src/toxcore/group_onion_announce.c
index d05db09a07..5a19935c50 100644
--- a/protocols/Tox/libtox/src/toxcore/group_onion_announce.c
+++ b/protocols/Tox/libtox/src/toxcore/group_onion_announce.c
@@ -14,17 +14,22 @@
#include "crypto_core.h"
#include "group_announce.h"
#include "logger.h"
+#include "mem.h"
#include "mono_time.h"
#include "network.h"
#include "onion_announce.h"
#include "timed_auth.h"
+static_assert(TIMED_AUTH_SIZE <= ONION_ANNOUNCE_REQUEST_MAX_SIZE,
+ "Timed auth does not fit into the onion packet");
+static_assert(PACKED_NODE_SIZE_IP6 <= GCA_ANNOUNCE_MAX_SIZE,
+ "IP6 does not fit into the GC_Announce");
static_assert(GCA_ANNOUNCE_MAX_SIZE <= ONION_MAX_EXTRA_DATA_SIZE,
"GC_Announce does not fit into the onion packet extra data");
static pack_extra_data_cb pack_group_announces;
non_null()
-static int pack_group_announces(void *object, const Logger *logger, const Mono_Time *mono_time,
+static int pack_group_announces(void *object, const Logger *logger, const Memory *mem, const Mono_Time *mono_time,
uint8_t num_nodes, uint8_t *plain, uint16_t plain_size,
uint8_t *response, uint16_t response_size, uint16_t offset)
{
@@ -37,7 +42,7 @@ static int pack_group_announces(void *object, const Logger *logger, const Mono_T
return -1;
}
- const GC_Peer_Announce *new_announce = gca_add_announce(mono_time, gc_announces_list, &public_announce);
+ const GC_Peer_Announce *new_announce = gca_add_announce(mem, mono_time, gc_announces_list, &public_announce);
if (new_announce == nullptr) {
LOGGER_ERROR(logger, "Failed to add group announce");
@@ -76,7 +81,7 @@ void gca_onion_init(GC_Announces_List *group_announce, Onion_Announce *onion_a)
}
int create_gca_announce_request(
- const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id,
+ const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id,
const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id,
const uint8_t *client_id, const uint8_t *data_public_key, uint64_t sendback_data,
const uint8_t *gc_data, uint16_t gc_data_length)
@@ -108,7 +113,7 @@ int create_gca_announce_request(
random_nonce(rng, packet + 1);
memcpy(packet + 1 + CRYPTO_NONCE_SIZE, public_key, CRYPTO_PUBLIC_KEY_SIZE);
- const int len = encrypt_data(dest_client_id, secret_key, packet + 1, plain,
+ const int len = encrypt_data(mem, dest_client_id, secret_key, packet + 1, plain,
encrypted_size, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE);
const uint32_t full_length = (uint32_t)len + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE;
diff --git a/protocols/Tox/libtox/src/toxcore/group_onion_announce.h b/protocols/Tox/libtox/src/toxcore/group_onion_announce.h
index 5fbac02e0a..8abff63795 100644
--- a/protocols/Tox/libtox/src/toxcore/group_onion_announce.h
+++ b/protocols/Tox/libtox/src/toxcore/group_onion_announce.h
@@ -9,6 +9,7 @@
#include "attributes.h"
#include "crypto_core.h"
#include "group_announce.h"
+#include "mem.h"
#include "onion_announce.h"
non_null()
@@ -16,9 +17,9 @@ void gca_onion_init(GC_Announces_List *group_announce, Onion_Announce *onion_a);
non_null()
int create_gca_announce_request(
- const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id,
- const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id,
- const uint8_t *client_id, const uint8_t *data_public_key, uint64_t sendback_data,
- const uint8_t *gc_data, uint16_t gc_data_length);
+ const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length,
+ const uint8_t *dest_client_id, const uint8_t *public_key, const uint8_t *secret_key,
+ const uint8_t *ping_id, const uint8_t *client_id, const uint8_t *data_public_key,
+ uint64_t sendback_data, const uint8_t *gc_data, uint16_t gc_data_length);
#endif /* C_TOXCORE_TOXCORE_GROUP_ONION_ANNOUNCE_H */
diff --git a/protocols/Tox/libtox/src/toxcore/group_pack.c b/protocols/Tox/libtox/src/toxcore/group_pack.c
index e3af82c67a..877df7409e 100644
--- a/protocols/Tox/libtox/src/toxcore/group_pack.c
+++ b/protocols/Tox/libtox/src/toxcore/group_pack.c
@@ -10,7 +10,6 @@
#include "group_pack.h"
#include <stdint.h>
-#include <stdlib.h>
#include <string.h>
#include "DHT.h"
@@ -23,49 +22,53 @@
#include "group_common.h"
#include "group_moderation.h"
#include "logger.h"
+#include "mem.h"
#include "network.h"
#include "util.h"
-bool group_privacy_state_from_int(uint8_t value, Group_Privacy_State *out)
+static_assert(GC_SAVED_PEER_SIZE >= sizeof(IP_Port),
+ "GC_SAVED_PEER_SIZE cannot contain IP_Port");
+
+bool group_privacy_state_from_int(uint8_t value, Group_Privacy_State *out_enum)
{
switch (value) {
case GI_PUBLIC: {
- *out = GI_PUBLIC;
+ *out_enum = GI_PUBLIC;
return true;
}
case GI_PRIVATE: {
- *out = GI_PRIVATE;
+ *out_enum = GI_PRIVATE;
return true;
}
default: {
- *out = GI_PUBLIC;
+ *out_enum = GI_PUBLIC;
return false;
}
}
}
-bool group_voice_state_from_int(uint8_t value, Group_Voice_State *out)
+bool group_voice_state_from_int(uint8_t value, Group_Voice_State *out_enum)
{
switch (value) {
case GV_ALL: {
- *out = GV_ALL;
+ *out_enum = GV_ALL;
return true;
}
case GV_MODS: {
- *out = GV_MODS;
+ *out_enum = GV_MODS;
return true;
}
case GV_FOUNDER: {
- *out = GV_FOUNDER;
+ *out_enum = GV_FOUNDER;
return true;
}
default: {
- *out = GV_ALL;
+ *out_enum = GV_ALL;
return false;
}
}
@@ -180,7 +183,7 @@ static bool load_unpack_mod_list(GC_Chat *chat, Bin_Unpack *bu)
chat->moderation.num_mods = MOD_MAX_NUM_MODERATORS;
}
- uint8_t *packed_mod_list = (uint8_t *)malloc(chat->moderation.num_mods * MOD_LIST_ENTRY_SIZE);
+ uint8_t *packed_mod_list = (uint8_t *)mem_balloc(chat->mem, chat->moderation.num_mods * MOD_LIST_ENTRY_SIZE);
if (packed_mod_list == nullptr) {
LOGGER_ERROR(chat->log, "Failed to allocate memory for packed mod list");
@@ -191,17 +194,17 @@ static bool load_unpack_mod_list(GC_Chat *chat, Bin_Unpack *bu)
if (!bin_unpack_bin_fixed(bu, packed_mod_list, packed_size)) {
LOGGER_ERROR(chat->log, "Failed to unpack mod list binary data");
- free(packed_mod_list);
+ mem_delete(chat->mem, packed_mod_list);
return false;
}
if (mod_list_unpack(&chat->moderation, packed_mod_list, packed_size, chat->moderation.num_mods) == -1) {
LOGGER_ERROR(chat->log, "Failed to unpack mod list info");
- free(packed_mod_list);
+ mem_delete(chat->mem, packed_mod_list);
return false;
}
- free(packed_mod_list);
+ mem_delete(chat->mem, packed_mod_list);
return true;
}
@@ -299,7 +302,7 @@ static bool load_unpack_saved_peers(GC_Chat *chat, Bin_Unpack *bu)
return true;
}
- uint8_t *saved_peers = (uint8_t *)malloc(saved_peers_size * GC_SAVED_PEER_SIZE);
+ uint8_t *saved_peers = (uint8_t *)mem_balloc(chat->mem, saved_peers_size * GC_SAVED_PEER_SIZE);
if (saved_peers == nullptr) {
LOGGER_ERROR(chat->log, "Failed to allocate memory for saved peer list");
@@ -308,7 +311,7 @@ static bool load_unpack_saved_peers(GC_Chat *chat, Bin_Unpack *bu)
if (!bin_unpack_bin_fixed(bu, saved_peers, saved_peers_size)) {
LOGGER_ERROR(chat->log, "Failed to unpack saved peers binary data");
- free(saved_peers);
+ mem_delete(chat->mem, saved_peers);
return false;
}
@@ -316,7 +319,7 @@ static bool load_unpack_saved_peers(GC_Chat *chat, Bin_Unpack *bu)
LOGGER_ERROR(chat->log, "Failed to unpack saved peers"); // recoverable error
}
- free(saved_peers);
+ mem_delete(chat->mem, saved_peers);
return true;
}
@@ -390,7 +393,7 @@ static void save_pack_mod_list(const GC_Chat *chat, Bin_Pack *bp)
return;
}
- uint8_t *packed_mod_list = (uint8_t *)malloc(num_mods * MOD_LIST_ENTRY_SIZE);
+ uint8_t *packed_mod_list = (uint8_t *)mem_balloc(chat->mem, num_mods * MOD_LIST_ENTRY_SIZE);
// we can still recover without the mod list
if (packed_mod_list == nullptr) {
@@ -408,7 +411,7 @@ static void save_pack_mod_list(const GC_Chat *chat, Bin_Pack *bp)
bin_pack_bin(bp, packed_mod_list, packed_size); // 2
- free(packed_mod_list);
+ mem_delete(chat->mem, packed_mod_list);
}
non_null()
@@ -445,7 +448,7 @@ static void save_pack_saved_peers(const GC_Chat *chat, Bin_Pack *bp)
{
bin_pack_array(bp, 2);
- uint8_t *saved_peers = (uint8_t *)malloc(GC_MAX_SAVED_PEERS * GC_SAVED_PEER_SIZE);
+ uint8_t *saved_peers = (uint8_t *)mem_balloc(chat->mem, GC_MAX_SAVED_PEERS * GC_SAVED_PEER_SIZE);
// we can still recover without the saved peers list
if (saved_peers == nullptr) {
@@ -466,13 +469,13 @@ static void save_pack_saved_peers(const GC_Chat *chat, Bin_Pack *bp)
if (packed_size == 0) {
bin_pack_nil(bp); // 2
- free(saved_peers);
+ mem_delete(chat->mem, saved_peers);
return;
}
bin_pack_bin(bp, saved_peers, packed_size); // 2
- free(saved_peers);
+ mem_delete(chat->mem, saved_peers);
}
void gc_save_pack_group(const GC_Chat *chat, Bin_Pack *bp)
diff --git a/protocols/Tox/libtox/src/toxcore/group_pack.h b/protocols/Tox/libtox/src/toxcore/group_pack.h
index 03252fb86d..4c999132db 100644
--- a/protocols/Tox/libtox/src/toxcore/group_pack.h
+++ b/protocols/Tox/libtox/src/toxcore/group_pack.h
@@ -34,8 +34,8 @@ non_null()
bool gc_load_unpack_group(GC_Chat *chat, Bin_Unpack *bu);
non_null()
-bool group_privacy_state_from_int(uint8_t value, Group_Privacy_State *out);
+bool group_privacy_state_from_int(uint8_t value, Group_Privacy_State *out_enum);
non_null()
-bool group_voice_state_from_int(uint8_t value, Group_Voice_State *out);
+bool group_voice_state_from_int(uint8_t value, Group_Voice_State *out_enum);
#endif /* C_TOXCORE_TOXCORE_GROUP_PACK_H */
diff --git a/protocols/Tox/libtox/src/toxcore/list.c b/protocols/Tox/libtox/src/toxcore/list.c
index bf3db247f1..689ad0a614 100644
--- a/protocols/Tox/libtox/src/toxcore/list.c
+++ b/protocols/Tox/libtox/src/toxcore/list.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2014 Tox project.
*/
@@ -12,11 +12,11 @@
#include <assert.h>
#include <stdbool.h>
-#include <stdlib.h>
#include <string.h>
#include "attributes.h"
#include "ccompat.h"
+#include "mem.h"
/**
* Basically, the elements in the list are placed in order so that they can be searched for easily
@@ -115,7 +115,7 @@ static bool resize(BS_List *list, uint32_t new_size)
return true;
}
- uint8_t *data = (uint8_t *)realloc(list->data, list->element_size * new_size);
+ uint8_t *data = (uint8_t *)mem_brealloc(list->mem, list->data, new_size * list->element_size);
if (data == nullptr) {
return false;
@@ -123,7 +123,7 @@ static bool resize(BS_List *list, uint32_t new_size)
list->data = data;
- int *ids = (int *)realloc(list->ids, new_size * sizeof(int));
+ int *ids = (int *)mem_vrealloc(list->mem, list->ids, new_size, sizeof(int));
if (ids == nullptr) {
return false;
@@ -134,8 +134,10 @@ static bool resize(BS_List *list, uint32_t new_size)
return true;
}
-int bs_list_init(BS_List *list, uint32_t element_size, uint32_t initial_capacity, bs_list_cmp_cb *cmp_callback)
+int bs_list_init(BS_List *list, const Memory *mem, uint32_t element_size, uint32_t initial_capacity, bs_list_cmp_cb *cmp_callback)
{
+ list->mem = mem;
+
// set initial values
list->n = 0;
list->element_size = element_size;
@@ -162,10 +164,10 @@ void bs_list_free(BS_List *list)
}
// free both arrays
- free(list->data);
+ mem_delete(list->mem, list->data);
list->data = nullptr;
- free(list->ids);
+ mem_delete(list->mem, list->ids);
list->ids = nullptr;
}
diff --git a/protocols/Tox/libtox/src/toxcore/list.h b/protocols/Tox/libtox/src/toxcore/list.h
index 1dc66d01a4..ae0ea32746 100644
--- a/protocols/Tox/libtox/src/toxcore/list.h
+++ b/protocols/Tox/libtox/src/toxcore/list.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2014 Tox project.
*/
@@ -16,6 +16,7 @@
#include <stdint.h>
#include "attributes.h"
+#include "mem.h"
#ifdef __cplusplus
extern "C" {
@@ -24,6 +25,8 @@ extern "C" {
typedef int bs_list_cmp_cb(const void *a, const void *b, size_t size);
typedef struct BS_List {
+ const Memory *mem;
+
uint32_t n; // number of elements
uint32_t capacity; // number of elements memory is allocated for
uint32_t element_size; // size of the elements
@@ -41,7 +44,7 @@ typedef struct BS_List {
* @retval 0 failure
*/
non_null()
-int bs_list_init(BS_List *list, uint32_t element_size, uint32_t initial_capacity, bs_list_cmp_cb *cmp_callback);
+int bs_list_init(BS_List *list, const Memory *mem, uint32_t element_size, uint32_t initial_capacity, bs_list_cmp_cb *cmp_callback);
/** Free a list initiated with list_init */
nullable(1)
diff --git a/protocols/Tox/libtox/src/toxcore/logger.c b/protocols/Tox/libtox/src/toxcore/logger.c
index 67fa52330b..b97ef8e184 100644
--- a/protocols/Tox/libtox/src/toxcore/logger.c
+++ b/protocols/Tox/libtox/src/toxcore/logger.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013-2015 Tox project.
*/
@@ -8,88 +8,62 @@
*/
#include "logger.h"
+#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "attributes.h"
#include "ccompat.h"
+#include "mem.h"
struct Logger {
+ const Memory *mem;
+
logger_cb *callback;
void *context;
void *userdata;
};
-#ifndef NDEBUG
-static const char *logger_level_name(Logger_Level level)
-{
- switch (level) {
- case LOGGER_LEVEL_TRACE:
- return "TRACE";
-
- case LOGGER_LEVEL_DEBUG:
- return "DEBUG";
-
- case LOGGER_LEVEL_INFO:
- return "INFO";
-
- case LOGGER_LEVEL_WARNING:
- return "WARNING";
-
- case LOGGER_LEVEL_ERROR:
- return "ERROR";
- }
-
- return "<unknown>";
-}
-#endif /* NDEBUG */
-
-non_null(1, 3, 5, 6) nullable(7)
-static void logger_stderr_handler(void *context, Logger_Level level, const char *file, int line, const char *func,
- const char *message, void *userdata)
-{
-#ifndef NDEBUG
- // GL stands for "global logger".
- fprintf(stderr, "[GL] %s %s:%d(%s): %s\n", logger_level_name(level), file, line, func, message);
- fprintf(stderr, "Default stderr logger triggered; aborting program\n");
- abort();
-#endif /* NDEBUG */
-}
-
-static const Logger logger_stderr = {
- logger_stderr_handler,
- nullptr,
- nullptr,
-};
-
/*
* Public Functions
*/
-Logger *logger_new(void)
+Logger *logger_new(const Memory *mem)
{
- return (Logger *)calloc(1, sizeof(Logger));
+ Logger *log = (Logger *)mem_alloc(mem, sizeof(Logger));
+
+ if (log == nullptr) {
+ return nullptr;
+ }
+
+ log->mem = mem;
+
+ return log;
}
void logger_kill(Logger *log)
{
- free(log);
+ if (log == nullptr) {
+ return;
+ }
+
+ mem_delete(log->mem, log);
}
void logger_callback_log(Logger *log, logger_cb *function, void *context, void *userdata)
{
+ assert(log != nullptr);
log->callback = function;
log->context = context;
log->userdata = userdata;
}
-void logger_write(const Logger *log, Logger_Level level, const char *file, int line, const char *func,
+void logger_write(const Logger *log, Logger_Level level, const char *file, uint32_t line, const char *func,
const char *format, ...)
{
if (log == nullptr) {
- log = &logger_stderr;
+ return;
}
if (log->callback == nullptr) {
diff --git a/protocols/Tox/libtox/src/toxcore/logger.h b/protocols/Tox/libtox/src/toxcore/logger.h
index 830db883aa..893c21fd10 100644
--- a/protocols/Tox/libtox/src/toxcore/logger.h
+++ b/protocols/Tox/libtox/src/toxcore/logger.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -12,6 +12,7 @@
#include <stdint.h>
#include "attributes.h"
+#include "mem.h"
#ifdef __cplusplus
extern "C" {
@@ -32,13 +33,14 @@ typedef enum Logger_Level {
typedef struct Logger Logger;
-typedef void logger_cb(void *context, Logger_Level level, const char *file, int line,
+typedef void logger_cb(void *context, Logger_Level level, const char *file, uint32_t line,
const char *func, const char *message, void *userdata);
/**
* Creates a new logger with logging disabled (callback is NULL) by default.
*/
-Logger *logger_new(void);
+non_null()
+Logger *logger_new(const Memory *mem);
/**
* Frees all resources associated with the logger.
@@ -64,7 +66,7 @@ void logger_callback_log(Logger *log, logger_cb *function, void *context, void *
*/
non_null(3, 5, 6) nullable(1) GNU_PRINTF(6, 7)
void logger_write(
- const Logger *log, Logger_Level level, const char *file, int line, const char *func,
+ const Logger *log, Logger_Level level, const char *file, uint32_t line, const char *func,
const char *format, ...);
/* @brief Terminate the program with a signal. */
diff --git a/protocols/Tox/libtox/src/toxcore/mem.c b/protocols/Tox/libtox/src/toxcore/mem.c
index bddc335b82..32e7eec07c 100644
--- a/protocols/Tox/libtox/src/toxcore/mem.c
+++ b/protocols/Tox/libtox/src/toxcore/mem.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -53,6 +53,12 @@ void *mem_balloc(const Memory *mem, uint32_t size)
return ptr;
}
+void *mem_brealloc(const Memory *mem, void *ptr, uint32_t size)
+{
+ void *const new_ptr = mem->funcs->realloc(mem->obj, ptr, size);
+ return new_ptr;
+}
+
void *mem_alloc(const Memory *mem, uint32_t size)
{
void *const ptr = mem->funcs->calloc(mem->obj, 1, size);
diff --git a/protocols/Tox/libtox/src/toxcore/mem.h b/protocols/Tox/libtox/src/toxcore/mem.h
index 7a96b6d358..6c36027ce7 100644
--- a/protocols/Tox/libtox/src/toxcore/mem.h
+++ b/protocols/Tox/libtox/src/toxcore/mem.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -46,6 +46,14 @@ const Memory *os_memory(void);
non_null() void *mem_balloc(const Memory *mem, uint32_t size);
/**
+ * @brief Resize an array of a given size for built-in types.
+ *
+ * If used for a type other than byte-sized types, `size` needs to be manually
+ * multiplied by the element size.
+ */
+non_null(1) nullable(2) void *mem_brealloc(const Memory *mem, void *ptr, uint32_t size);
+
+/**
* @brief Allocate a single object.
*
* Always use as `(T *)mem_alloc(mem, sizeof(T))`.
diff --git a/protocols/Tox/libtox/src/toxcore/mono_time.c b/protocols/Tox/libtox/src/toxcore/mono_time.c
index 124f94fc23..8a3044c6f0 100644
--- a/protocols/Tox/libtox/src/toxcore/mono_time.c
+++ b/protocols/Tox/libtox/src/toxcore/mono_time.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2023 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2014 Tox project.
*/
#ifndef _XOPEN_SOURCE
@@ -218,7 +218,7 @@ void mono_time_set_current_time_callback(Mono_Time *mono_time,
* The starting point is unspecified and in particular is likely not comparable
* to the return value of `mono_time_get_ms()`.
*/
-uint64_t current_time_monotonic(Mono_Time *mono_time)
+uint64_t current_time_monotonic(const Mono_Time *mono_time)
{
return mono_time->current_time_callback(mono_time->user_data);
}
diff --git a/protocols/Tox/libtox/src/toxcore/mono_time.h b/protocols/Tox/libtox/src/toxcore/mono_time.h
index d0f2b7a6d3..e23c1ba0df 100644
--- a/protocols/Tox/libtox/src/toxcore/mono_time.h
+++ b/protocols/Tox/libtox/src/toxcore/mono_time.h
@@ -87,7 +87,7 @@ bool mono_time_is_timeout(const Mono_Time *mono_time, uint64_t timestamp, uint64
* to the return value of `mono_time_get_ms()`.
*/
non_null()
-uint64_t current_time_monotonic(Mono_Time *mono_time);
+uint64_t current_time_monotonic(const Mono_Time *mono_time);
/**
* Override implementation of `current_time_monotonic()` (for tests).
diff --git a/protocols/Tox/libtox/src/toxcore/net_crypto.c b/protocols/Tox/libtox/src/toxcore/net_crypto.c
index 1680b078b7..bf9f1d595a 100644
--- a/protocols/Tox/libtox/src/toxcore/net_crypto.c
+++ b/protocols/Tox/libtox/src/toxcore/net_crypto.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -10,6 +10,7 @@
*/
#include "net_crypto.h"
+#include <pthread.h>
#include <string.h>
#include "DHT.h"
@@ -23,6 +24,7 @@
#include "logger.h"
#include "mem.h"
#include "mono_time.h"
+#include "net_profile.h"
#include "network.h"
#include "util.h"
@@ -122,9 +124,6 @@ typedef struct Crypto_Connection {
bool maximum_speed_reached;
- /* Must be a pointer, because the struct is moved in memory */
- pthread_mutex_t *mutex;
-
dht_pk_cb *dht_pk_callback;
void *dht_pk_callback_object;
uint32_t dht_pk_callback_number;
@@ -143,10 +142,6 @@ struct Net_Crypto {
TCP_Connections *tcp_c;
Crypto_Connection *crypto_connections;
- pthread_mutex_t tcp_mutex;
-
- pthread_mutex_t connections_mutex;
- unsigned int connection_use_counter;
uint32_t crypto_connections_length; /* Length of connections array. */
@@ -237,7 +232,7 @@ static int create_cookie_request(const Net_Crypto *c, uint8_t *packet, const uin
packet[0] = NET_PACKET_COOKIE_REQUEST;
memcpy(packet + 1, dht_get_self_public_key(c->dht), CRYPTO_PUBLIC_KEY_SIZE);
memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE);
- const int len = encrypt_data_symmetric(shared_key, nonce, plain, sizeof(plain),
+ const int len = encrypt_data_symmetric(c->mem, shared_key, nonce, plain, sizeof(plain),
packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
if (len != COOKIE_REQUEST_PLAIN_LENGTH + CRYPTO_MAC_SIZE) {
@@ -253,7 +248,7 @@ static int create_cookie_request(const Net_Crypto *c, uint8_t *packet, const uin
* @retval 0 on success.
*/
non_null()
-static int create_cookie(const Random *rng, const Mono_Time *mono_time, uint8_t *cookie, const uint8_t *bytes,
+static int create_cookie(const Memory *mem, const Random *rng, const Mono_Time *mono_time, uint8_t *cookie, const uint8_t *bytes,
const uint8_t *encryption_key)
{
uint8_t contents[COOKIE_CONTENTS_LENGTH];
@@ -261,7 +256,7 @@ static int create_cookie(const Random *rng, const Mono_Time *mono_time, uint8_t
memcpy(contents, &temp_time, sizeof(temp_time));
memcpy(contents + sizeof(temp_time), bytes, COOKIE_DATA_LENGTH);
random_nonce(rng, cookie);
- const int len = encrypt_data_symmetric(encryption_key, cookie, contents, sizeof(contents), cookie + CRYPTO_NONCE_SIZE);
+ const int len = encrypt_data_symmetric(mem, encryption_key, cookie, contents, sizeof(contents), cookie + CRYPTO_NONCE_SIZE);
if (len != COOKIE_LENGTH - CRYPTO_NONCE_SIZE) {
return -1;
@@ -276,11 +271,11 @@ static int create_cookie(const Random *rng, const Mono_Time *mono_time, uint8_t
* @retval 0 on success.
*/
non_null()
-static int open_cookie(const Mono_Time *mono_time, uint8_t *bytes, const uint8_t *cookie,
+static int open_cookie(const Memory *mem, const Mono_Time *mono_time, uint8_t *bytes, const uint8_t *cookie,
const uint8_t *encryption_key)
{
uint8_t contents[COOKIE_CONTENTS_LENGTH];
- const int len = decrypt_data_symmetric(encryption_key, cookie, cookie + CRYPTO_NONCE_SIZE,
+ const int len = decrypt_data_symmetric(mem, encryption_key, cookie, cookie + CRYPTO_NONCE_SIZE,
COOKIE_LENGTH - CRYPTO_NONCE_SIZE, contents);
if (len != sizeof(contents)) {
@@ -315,14 +310,14 @@ static int create_cookie_response(const Net_Crypto *c, uint8_t *packet, const ui
memcpy(cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, dht_public_key, CRYPTO_PUBLIC_KEY_SIZE);
uint8_t plain[COOKIE_LENGTH + sizeof(uint64_t)];
- if (create_cookie(c->rng, c->mono_time, plain, cookie_plain, c->secret_symmetric_key) != 0) {
+ if (create_cookie(c->mem, c->rng, c->mono_time, plain, cookie_plain, c->secret_symmetric_key) != 0) {
return -1;
}
memcpy(plain + COOKIE_LENGTH, request_plain + COOKIE_DATA_LENGTH, sizeof(uint64_t));
packet[0] = NET_PACKET_COOKIE_RESPONSE;
random_nonce(c->rng, packet + 1);
- const int len = encrypt_data_symmetric(shared_key, packet + 1, plain, sizeof(plain), packet + 1 + CRYPTO_NONCE_SIZE);
+ const int len = encrypt_data_symmetric(c->mem, shared_key, packet + 1, plain, sizeof(plain), packet + 1 + CRYPTO_NONCE_SIZE);
if (len != COOKIE_RESPONSE_LENGTH - (1 + CRYPTO_NONCE_SIZE)) {
return -1;
@@ -349,7 +344,7 @@ static int handle_cookie_request(const Net_Crypto *c, uint8_t *request_plain, ui
memcpy(dht_public_key, packet + 1, CRYPTO_PUBLIC_KEY_SIZE);
const uint8_t *tmp_shared_key = dht_get_shared_key_sent(c->dht, dht_public_key);
memcpy(shared_key, tmp_shared_key, CRYPTO_SHARED_KEY_SIZE);
- const int len = decrypt_data_symmetric(shared_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
+ const int len = decrypt_data_symmetric(c->mem, shared_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, COOKIE_REQUEST_PLAIN_LENGTH + CRYPTO_MAC_SIZE,
request_plain);
@@ -446,7 +441,7 @@ static int tcp_oob_handle_cookie_request(const Net_Crypto *c, unsigned int tcp_c
* @retval COOKIE_LENGTH on success.
*/
non_null()
-static int handle_cookie_response(uint8_t *cookie, uint64_t *number,
+static int handle_cookie_response(const Memory *mem, uint8_t *cookie, uint64_t *number,
const uint8_t *packet, uint16_t length,
const uint8_t *shared_key)
{
@@ -455,7 +450,7 @@ static int handle_cookie_response(uint8_t *cookie, uint64_t *number,
}
uint8_t plain[COOKIE_LENGTH + sizeof(uint64_t)];
- const int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
+ const int len = decrypt_data_symmetric(mem, shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
length - (1 + CRYPTO_NONCE_SIZE), plain);
if (len != sizeof(plain)) {
@@ -488,13 +483,13 @@ static int create_crypto_handshake(const Net_Crypto *c, uint8_t *packet, const u
memcpy(cookie_plain, peer_real_pk, CRYPTO_PUBLIC_KEY_SIZE);
memcpy(cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, peer_dht_pubkey, CRYPTO_PUBLIC_KEY_SIZE);
- if (create_cookie(c->rng, c->mono_time, plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE,
+ if (create_cookie(c->mem, c->rng, c->mono_time, plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE,
cookie_plain, c->secret_symmetric_key) != 0) {
return -1;
}
random_nonce(c->rng, packet + 1 + COOKIE_LENGTH);
- const int len = encrypt_data(peer_real_pk, c->self_secret_key, packet + 1 + COOKIE_LENGTH, plain, sizeof(plain),
+ const int len = encrypt_data(c->mem, peer_real_pk, c->self_secret_key, packet + 1 + COOKIE_LENGTH, plain, sizeof(plain),
packet + 1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE);
if (len != HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE)) {
@@ -535,7 +530,7 @@ static bool handle_crypto_handshake(const Net_Crypto *c, uint8_t *nonce, uint8_t
uint8_t cookie_plain[COOKIE_DATA_LENGTH];
- if (open_cookie(c->mono_time, cookie_plain, packet + 1, c->secret_symmetric_key) != 0) {
+ if (open_cookie(c->mem, c->mono_time, cookie_plain, packet + 1, c->secret_symmetric_key) != 0) {
return false;
}
@@ -547,7 +542,7 @@ static bool handle_crypto_handshake(const Net_Crypto *c, uint8_t *nonce, uint8_t
crypto_sha512(cookie_hash, packet + 1, COOKIE_LENGTH);
uint8_t plain[CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH];
- const int len = decrypt_data(cookie_plain, c->self_secret_key, packet + 1 + COOKIE_LENGTH,
+ const int len = decrypt_data(c->mem, cookie_plain, c->self_secret_key, packet + 1 + COOKIE_LENGTH,
packet + 1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE,
HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE), plain);
@@ -680,7 +675,7 @@ static IP_Port return_ip_port_connection(const Net_Crypto *c, int crypt_connecti
* @retval 0 on success.
*/
non_null()
-static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length)
+static int send_packet_to(const Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length)
{
// TODO(irungentoo): TCP, etc...
Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
@@ -691,7 +686,6 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t
bool direct_send_attempt = false;
- pthread_mutex_lock(conn->mutex);
const IP_Port ip_port = return_ip_port_connection(c, crypt_connection_id);
// TODO(irungentoo): on bad networks, direct connections might not last indefinitely.
@@ -703,11 +697,9 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t
if (direct_connected) {
if ((uint32_t)sendpacket(dht_get_net(c->dht), &ip_port, data, length) == length) {
- pthread_mutex_unlock(conn->mutex);
return 0;
}
- pthread_mutex_unlock(conn->mutex);
LOGGER_WARNING(c->log, "sending packet of length %d failed", length);
return -1;
}
@@ -724,19 +716,12 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t
}
}
- pthread_mutex_unlock(conn->mutex);
- pthread_mutex_lock(&c->tcp_mutex);
const int ret = send_packet_tcp_connection(c->tcp_c, conn->connection_number_tcp, data, length);
- pthread_mutex_unlock(&c->tcp_mutex);
-
- pthread_mutex_lock(conn->mutex);
if (ret == 0) {
conn->last_tcp_sent = current_time_monotonic(c->mono_time);
}
- pthread_mutex_unlock(conn->mutex);
-
if (direct_send_attempt) {
return 0;
}
@@ -998,7 +983,7 @@ static int generate_request_packet(uint8_t *data, uint16_t length, const Packets
* @return number of requested packets on success.
*/
non_null()
-static int handle_request_packet(const Memory *mem, Mono_Time *mono_time, Packets_Array *send_array,
+static int handle_request_packet(const Memory *mem, const Mono_Time *mono_time, Packets_Array *send_array,
const uint8_t *data, uint16_t length,
uint64_t *latest_send_time, uint64_t rtt_time)
{
@@ -1081,7 +1066,7 @@ static int handle_request_packet(const Memory *mem, Mono_Time *mono_time, Packet
* @retval 0 on success.
*/
non_null()
-static int send_data_packet(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length)
+static int send_data_packet(const Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length)
{
const uint16_t max_length = MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + CRYPTO_MAC_SIZE);
@@ -1097,21 +1082,18 @@ static int send_data_packet(Net_Crypto *c, int crypt_connection_id, const uint8_
return -1;
}
- pthread_mutex_lock(conn->mutex);
const uint16_t packet_size = 1 + sizeof(uint16_t) + length + CRYPTO_MAC_SIZE;
VLA(uint8_t, packet, packet_size);
packet[0] = NET_PACKET_CRYPTO_DATA;
memcpy(packet + 1, conn->sent_nonce + (CRYPTO_NONCE_SIZE - sizeof(uint16_t)), sizeof(uint16_t));
- const int len = encrypt_data_symmetric(conn->shared_key, conn->sent_nonce, data, length, packet + 1 + sizeof(uint16_t));
+ const int len = encrypt_data_symmetric(c->mem, conn->shared_key, conn->sent_nonce, data, length, packet + 1 + sizeof(uint16_t));
if (len + 1 + sizeof(uint16_t) != packet_size) {
LOGGER_ERROR(c->log, "encryption failed: %d", len);
- pthread_mutex_unlock(conn->mutex);
return -1;
}
increment_nonce(conn->sent_nonce);
- pthread_mutex_unlock(conn->mutex);
return send_packet_to(c, crypt_connection_id, packet, packet_size);
}
@@ -1122,7 +1104,7 @@ static int send_data_packet(Net_Crypto *c, int crypt_connection_id, const uint8_
* @retval 0 on success.
*/
non_null()
-static int send_data_packet_helper(Net_Crypto *c, int crypt_connection_id, uint32_t buffer_start, uint32_t num,
+static int send_data_packet_helper(const Net_Crypto *c, int crypt_connection_id, uint32_t buffer_start, uint32_t num,
const uint8_t *data, uint16_t length)
{
if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) {
@@ -1144,7 +1126,7 @@ static int send_data_packet_helper(Net_Crypto *c, int crypt_connection_id, uint3
}
non_null()
-static int reset_max_speed_reached(Net_Crypto *c, int crypt_connection_id)
+static int reset_max_speed_reached(const Net_Crypto *c, int crypt_connection_id)
{
Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
@@ -1179,7 +1161,7 @@ static int reset_max_speed_reached(Net_Crypto *c, int crypt_connection_id)
* @return positive packet number if data was put into the queue.
*/
non_null()
-static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length,
+static int64_t send_lossless_packet(const Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length,
bool congestion_control)
{
if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) {
@@ -1207,9 +1189,7 @@ static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, cons
dt.sent_time = 0;
dt.length = length;
memcpy(dt.data, data, length);
- pthread_mutex_lock(conn->mutex);
const int64_t packet_num = add_data_end_of_buffer(c->log, c->mem, &conn->send_array, &dt);
- pthread_mutex_unlock(conn->mutex);
if (packet_num == -1) {
return -1;
@@ -1277,7 +1257,7 @@ static int handle_data_packet(const Net_Crypto *c, int crypt_connection_id, uint
net_unpack_u16(packet + 1, &num);
const uint16_t diff = num - num_cur_nonce;
increment_nonce_number(nonce, diff);
- const int len = decrypt_data_symmetric(conn->shared_key, nonce, packet + 1 + sizeof(uint16_t),
+ const int len = decrypt_data_symmetric(c->mem, conn->shared_key, nonce, packet + 1 + sizeof(uint16_t),
length - (1 + sizeof(uint16_t)), data);
if ((unsigned int)len != length - crypto_packet_overhead) {
@@ -1297,7 +1277,7 @@ static int handle_data_packet(const Net_Crypto *c, int crypt_connection_id, uint
* @retval 0 on success.
*/
non_null()
-static int send_request_packet(Net_Crypto *c, int crypt_connection_id)
+static int send_request_packet(const Net_Crypto *c, int crypt_connection_id)
{
const Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
@@ -1322,7 +1302,7 @@ static int send_request_packet(Net_Crypto *c, int crypt_connection_id)
* @return number of packets sent on success.
*/
non_null()
-static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint32_t max_num)
+static int send_requested_packets(const Net_Crypto *c, int crypt_connection_id, uint32_t max_num)
{
if (max_num == 0) {
return -1;
@@ -1436,7 +1416,7 @@ static int clear_temp_packet(const Net_Crypto *c, int crypt_connection_id)
* @retval 0 on success.
*/
non_null()
-static int send_temp_packet(Net_Crypto *c, int crypt_connection_id)
+static int send_temp_packet(const Net_Crypto *c, int crypt_connection_id)
{
Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
@@ -1464,7 +1444,7 @@ static int send_temp_packet(Net_Crypto *c, int crypt_connection_id)
* @retval 0 on success.
*/
non_null()
-static int create_send_handshake(Net_Crypto *c, int crypt_connection_id, const uint8_t *cookie,
+static int create_send_handshake(const Net_Crypto *c, int crypt_connection_id, const uint8_t *cookie,
const uint8_t *dht_public_key)
{
const Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
@@ -1494,7 +1474,7 @@ static int create_send_handshake(Net_Crypto *c, int crypt_connection_id, const u
* @retval 0 on success.
*/
non_null()
-static int send_kill_packet(Net_Crypto *c, int crypt_connection_id)
+static int send_kill_packet(const Net_Crypto *c, int crypt_connection_id)
{
const Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
@@ -1521,18 +1501,7 @@ static void connection_kill(Net_Crypto *c, int crypt_connection_id, void *userda
false, userdata);
}
- while (true) { /* TODO(irungentoo): is this really the best way to do this? */
- pthread_mutex_lock(&c->connections_mutex);
-
- if (c->connection_use_counter == 0) {
- break;
- }
-
- pthread_mutex_unlock(&c->connections_mutex);
- }
-
crypto_kill(c, crypt_connection_id);
- pthread_mutex_unlock(&c->connections_mutex);
}
/** @brief Handle a received data packet.
@@ -1635,9 +1604,7 @@ static int handle_data_packet_core(Net_Crypto *c, int crypt_connection_id, const
}
while (true) {
- pthread_mutex_lock(conn->mutex);
const int ret = read_data_beg_buffer(c->mem, &conn->recv_array, &dt);
- pthread_mutex_unlock(conn->mutex);
if (ret == -1) {
break;
@@ -1682,7 +1649,7 @@ static int handle_data_packet_core(Net_Crypto *c, int crypt_connection_id, const
}
non_null()
-static int handle_packet_cookie_response(Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length)
+static int handle_packet_cookie_response(const Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length)
{
Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
@@ -1697,7 +1664,7 @@ static int handle_packet_cookie_response(Net_Crypto *c, int crypt_connection_id,
uint8_t cookie[COOKIE_LENGTH];
uint64_t number;
- if (handle_cookie_response(cookie, &number, packet, length, conn->shared_key) != sizeof(cookie)) {
+ if (handle_cookie_response(c->mem, cookie, &number, packet, length, conn->shared_key) != sizeof(cookie)) {
return -1;
}
@@ -1714,7 +1681,7 @@ static int handle_packet_cookie_response(Net_Crypto *c, int crypt_connection_id,
}
non_null(1, 3) nullable(5)
-static int handle_packet_crypto_hs(Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length,
+static int handle_packet_crypto_hs(const Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length,
void *userdata)
{
Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
@@ -1835,16 +1802,6 @@ static int realloc_cryptoconnection(Net_Crypto *c, uint32_t num)
non_null()
static int create_crypto_connection(Net_Crypto *c)
{
- while (true) { /* TODO(irungentoo): is this really the best way to do this? */
- pthread_mutex_lock(&c->connections_mutex);
-
- if (c->connection_use_counter == 0) {
- break;
- }
-
- pthread_mutex_unlock(&c->connections_mutex);
- }
-
int id = -1;
for (uint32_t i = 0; i < c->crypto_connections_length; ++i) {
@@ -1863,30 +1820,17 @@ static int create_crypto_connection(Net_Crypto *c)
}
if (id != -1) {
- pthread_mutex_t *mutex = (pthread_mutex_t *)mem_alloc(c->mem, sizeof(pthread_mutex_t));
-
- if (mutex == nullptr) {
- pthread_mutex_unlock(&c->connections_mutex);
- return -1;
- }
-
- if (pthread_mutex_init(mutex, nullptr) != 0) {
- mem_delete(c->mem, mutex);
- pthread_mutex_unlock(&c->connections_mutex);
- return -1;
- }
-
// Memsetting float/double to 0 is non-portable, so we explicitly set them to 0
c->crypto_connections[id].packet_recv_rate = 0.0;
c->crypto_connections[id].packet_send_rate = 0.0;
c->crypto_connections[id].last_packets_left_rem = 0.0;
c->crypto_connections[id].packet_send_rate_requested = 0.0;
c->crypto_connections[id].last_packets_left_requested_rem = 0.0;
- c->crypto_connections[id].mutex = mutex;
+
+ // TODO(Green-Sky): This enum is likely unneeded and the same as FREE.
c->crypto_connections[id].status = CRYPTO_CONN_NO_CONNECTION;
}
- pthread_mutex_unlock(&c->connections_mutex);
return id;
}
@@ -1914,8 +1858,6 @@ static int wipe_crypto_connection(Net_Crypto *c, int crypt_connection_id)
uint32_t i;
- pthread_mutex_destroy(c->crypto_connections[crypt_connection_id].mutex);
- mem_delete(c->mem, c->crypto_connections[crypt_connection_id].mutex);
crypto_memzero(&c->crypto_connections[crypt_connection_id], sizeof(Crypto_Connection));
/* check if we can resize the connections array */
@@ -2098,9 +2040,7 @@ int accept_crypto_connection(Net_Crypto *c, const New_Connection *n_c)
return -1;
}
- pthread_mutex_lock(&c->tcp_mutex);
const int connection_number_tcp = new_tcp_connection_to(c->tcp_c, n_c->dht_public_key, crypt_connection_id);
- pthread_mutex_unlock(&c->tcp_mutex);
if (connection_number_tcp == -1) {
wipe_crypto_connection(c, crypt_connection_id);
@@ -2117,9 +2057,7 @@ int accept_crypto_connection(Net_Crypto *c, const New_Connection *n_c)
conn->status = CRYPTO_CONN_NOT_CONFIRMED;
if (create_send_handshake(c, crypt_connection_id, n_c->cookie, n_c->dht_public_key) != 0) {
- pthread_mutex_lock(&c->tcp_mutex);
kill_tcp_connection_to(c->tcp_c, conn->connection_number_tcp);
- pthread_mutex_unlock(&c->tcp_mutex);
wipe_crypto_connection(c, crypt_connection_id);
return -1;
}
@@ -2155,9 +2093,7 @@ int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key, const u
Crypto_Connection *conn = &c->crypto_connections[crypt_connection_id];
- pthread_mutex_lock(&c->tcp_mutex);
const int connection_number_tcp = new_tcp_connection_to(c->tcp_c, dht_public_key, crypt_connection_id);
- pthread_mutex_unlock(&c->tcp_mutex);
if (connection_number_tcp == -1) {
wipe_crypto_connection(c, crypt_connection_id);
@@ -2181,9 +2117,7 @@ int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key, const u
if (create_cookie_request(c, cookie_request, conn->dht_public_key, conn->cookie_request_number,
conn->shared_key) != sizeof(cookie_request)
|| new_temp_packet(c, crypt_connection_id, cookie_request, sizeof(cookie_request)) != 0) {
- pthread_mutex_lock(&c->tcp_mutex);
kill_tcp_connection_to(c->tcp_c, conn->connection_number_tcp);
- pthread_mutex_unlock(&c->tcp_mutex);
wipe_crypto_connection(c, crypt_connection_id);
return -1;
}
@@ -2241,11 +2175,7 @@ static int tcp_data_callback(void *object, int crypt_connection_id, const uint8_
return tcp_handle_cookie_request(c, conn->connection_number_tcp, packet, length);
}
- // This unlocks the mutex that at this point is locked by do_tcp before
- // calling do_tcp_connections.
- pthread_mutex_unlock(&c->tcp_mutex);
const int ret = handle_packet_connection(c, crypt_connection_id, packet, length, false, userdata);
- pthread_mutex_lock(&c->tcp_mutex);
if (ret != 0) {
return -1;
@@ -2295,10 +2225,7 @@ int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, const IP_Port *ip
return -1;
}
- pthread_mutex_lock(&c->tcp_mutex);
- const int ret = add_tcp_relay_connection(c->tcp_c, conn->connection_number_tcp, ip_port, public_key);
- pthread_mutex_unlock(&c->tcp_mutex);
- return ret;
+ return add_tcp_relay_connection(c->tcp_c, conn->connection_number_tcp, ip_port, public_key);
}
/** @brief Add a tcp relay to the array.
@@ -2308,10 +2235,7 @@ int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, const IP_Port *ip
*/
int add_tcp_relay(Net_Crypto *c, const IP_Port *ip_port, const uint8_t *public_key)
{
- pthread_mutex_lock(&c->tcp_mutex);
- const int ret = add_tcp_relay_global(c->tcp_c, ip_port, public_key);
- pthread_mutex_unlock(&c->tcp_mutex);
- return ret;
+ return add_tcp_relay_global(c->tcp_c, ip_port, public_key);
}
/** @brief Return a random TCP connection number for use in send_tcp_onion_request.
@@ -2322,13 +2246,9 @@ int add_tcp_relay(Net_Crypto *c, const IP_Port *ip_port, const uint8_t *public_k
* return TCP connection number on success.
* return -1 on failure.
*/
-int get_random_tcp_con_number(Net_Crypto *c)
+int get_random_tcp_con_number(const Net_Crypto *c)
{
- pthread_mutex_lock(&c->tcp_mutex);
- const int ret = get_random_tcp_onion_conn_number(c->tcp_c);
- pthread_mutex_unlock(&c->tcp_mutex);
-
- return ret;
+ return get_random_tcp_onion_conn_number(c->tcp_c);
}
/** @brief Put IP_Port of a random onion TCP connection in ip_port.
@@ -2336,13 +2256,9 @@ int get_random_tcp_con_number(Net_Crypto *c)
* return true on success.
* return false on failure.
*/
-bool get_random_tcp_conn_ip_port(Net_Crypto *c, IP_Port *ip_port)
+bool get_random_tcp_conn_ip_port(const Net_Crypto *c, IP_Port *ip_port)
{
- pthread_mutex_lock(&c->tcp_mutex);
- const bool ret = tcp_get_random_conn_ip_port(c->tcp_c, ip_port);
- pthread_mutex_unlock(&c->tcp_mutex);
-
- return ret;
+ return tcp_get_random_conn_ip_port(c->tcp_c, ip_port);
}
/** @brief Send an onion packet via the TCP relay corresponding to tcp_connections_number.
@@ -2352,11 +2268,7 @@ bool get_random_tcp_conn_ip_port(Net_Crypto *c, IP_Port *ip_port)
*/
int send_tcp_onion_request(Net_Crypto *c, unsigned int tcp_connections_number, const uint8_t *data, uint16_t length)
{
- pthread_mutex_lock(&c->tcp_mutex);
- const int ret = tcp_send_onion_request(c->tcp_c, tcp_connections_number, data, length);
- pthread_mutex_unlock(&c->tcp_mutex);
-
- return ret;
+ return tcp_send_onion_request(c->tcp_c, tcp_connections_number, data, length);
}
/**
@@ -2371,12 +2283,8 @@ int send_tcp_forward_request(const Logger *logger, Net_Crypto *c, const IP_Port
const uint8_t *chain_keys, uint16_t chain_length,
const uint8_t *data, uint16_t data_length)
{
- pthread_mutex_lock(&c->tcp_mutex);
- const int ret = tcp_send_forward_request(logger, c->tcp_c, tcp_forwarder, dht_node,
- chain_keys, chain_length, data, data_length);
- pthread_mutex_unlock(&c->tcp_mutex);
-
- return ret;
+ return tcp_send_forward_request(logger, c->tcp_c, tcp_forwarder, dht_node,
+ chain_keys, chain_length, data, data_length);
}
/** @brief Copy a maximum of num random TCP relays we are connected to to tcp_relays.
@@ -2386,38 +2294,28 @@ int send_tcp_forward_request(const Logger *logger, Net_Crypto *c, const IP_Port
* return number of relays copied to tcp_relays on success.
* return 0 on failure.
*/
-unsigned int copy_connected_tcp_relays(Net_Crypto *c, Node_format *tcp_relays, uint16_t num)
+unsigned int copy_connected_tcp_relays(const Net_Crypto *c, Node_format *tcp_relays, uint16_t num)
{
if (num == 0) {
return 0;
}
- pthread_mutex_lock(&c->tcp_mutex);
- const unsigned int ret = tcp_copy_connected_relays(c->tcp_c, tcp_relays, num);
- pthread_mutex_unlock(&c->tcp_mutex);
-
- return ret;
+ return tcp_copy_connected_relays(c->tcp_c, tcp_relays, num);
}
-uint32_t copy_connected_tcp_relays_index(Net_Crypto *c, Node_format *tcp_relays, uint16_t num, uint32_t idx)
+uint32_t copy_connected_tcp_relays_index(const Net_Crypto *c, Node_format *tcp_relays, uint16_t num, uint32_t idx)
{
if (num == 0) {
return 0;
}
- pthread_mutex_lock(&c->tcp_mutex);
- const uint32_t ret = tcp_copy_connected_relays_index(c->tcp_c, tcp_relays, num, idx);
- pthread_mutex_unlock(&c->tcp_mutex);
-
- return ret;
+ return tcp_copy_connected_relays_index(c->tcp_c, tcp_relays, num, idx);
}
non_null()
static void do_tcp(Net_Crypto *c, void *userdata)
{
- pthread_mutex_lock(&c->tcp_mutex);
do_tcp_connections(c->log, c->tcp_c, userdata);
- pthread_mutex_unlock(&c->tcp_mutex);
for (uint32_t i = 0; i < c->crypto_connections_length; ++i) {
const Crypto_Connection *conn = get_crypto_connection(c, i);
@@ -2436,9 +2334,7 @@ static void do_tcp(Net_Crypto *c, void *userdata)
continue;
}
- pthread_mutex_lock(&c->tcp_mutex);
set_tcp_connection_to_status(c->tcp_c, conn->connection_number_tcp, !direct_connected);
- pthread_mutex_unlock(&c->tcp_mutex);
}
}
@@ -2593,15 +2489,12 @@ static int udp_handle_packet(void *object, const IP_Port *source, const uint8_t
return -1;
}
- pthread_mutex_lock(conn->mutex);
-
if (net_family_is_ipv4(source->ip.family)) {
conn->direct_lastrecv_timev4 = mono_time_get(c->mono_time);
} else {
conn->direct_lastrecv_timev6 = mono_time_get(c->mono_time);
}
- pthread_mutex_unlock(conn->mutex);
return 0;
}
@@ -2866,7 +2759,7 @@ static void send_crypto_packets(Net_Crypto *c)
* @retval 1 if max speed was reached for this connection (no more data can be physically through the pipe).
* @retval 0 if it wasn't reached.
*/
-bool max_speed_reached(Net_Crypto *c, int crypt_connection_id)
+bool max_speed_reached(const Net_Crypto *c, int crypt_connection_id)
{
return reset_max_speed_reached(c, crypt_connection_id) != 0;
}
@@ -2901,7 +2794,7 @@ uint32_t crypto_num_free_sendqueue_slots(const Net_Crypto *c, int crypt_connecti
*
* congestion_control: should congestion control apply to this packet?
*/
-int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length,
+int64_t write_cryptpacket(const Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length,
bool congestion_control)
{
if (length == 0) {
@@ -2987,7 +2880,7 @@ int cryptpacket_received(const Net_Crypto *c, int crypt_connection_id, uint32_t
*
* The first byte of data must be in the PACKET_ID_RANGE_LOSSY.
*/
-int send_lossy_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length)
+int send_lossy_cryptpacket(const Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length)
{
if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) {
return -1;
@@ -2997,26 +2890,16 @@ int send_lossy_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t
return -1;
}
- pthread_mutex_lock(&c->connections_mutex);
- ++c->connection_use_counter;
- pthread_mutex_unlock(&c->connections_mutex);
-
Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
int ret = -1;
if (conn != nullptr) {
- pthread_mutex_lock(conn->mutex);
const uint32_t buffer_start = conn->recv_array.buffer_start;
const uint32_t buffer_end = conn->send_array.buffer_end;
- pthread_mutex_unlock(conn->mutex);
ret = send_data_packet_helper(c, crypt_connection_id, buffer_start, buffer_end, data, length);
}
- pthread_mutex_lock(&c->connections_mutex);
- --c->connection_use_counter;
- pthread_mutex_unlock(&c->connections_mutex);
-
return ret;
}
@@ -3036,9 +2919,7 @@ int crypto_kill(Net_Crypto *c, int crypt_connection_id)
send_kill_packet(c, crypt_connection_id);
}
- pthread_mutex_lock(&c->tcp_mutex);
kill_tcp_connection_to(c->tcp_c, conn->connection_number_tcp);
- pthread_mutex_unlock(&c->tcp_mutex);
bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_portv4, crypt_connection_id);
bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_portv6, crypt_connection_id);
@@ -3107,7 +2988,7 @@ void load_secret_key(Net_Crypto *c, const uint8_t *sk)
* Sets all the global connection variables to their default values.
*/
Net_Crypto *new_net_crypto(const Logger *log, const Memory *mem, const Random *rng, const Network *ns,
- Mono_Time *mono_time, DHT *dht, const TCP_Proxy_Info *proxy_info)
+ Mono_Time *mono_time, DHT *dht, const TCP_Proxy_Info *proxy_info, Net_Profile *tcp_np)
{
if (dht == nullptr) {
return nullptr;
@@ -3125,7 +3006,7 @@ Net_Crypto *new_net_crypto(const Logger *log, const Memory *mem, const Random *r
temp->mono_time = mono_time;
temp->ns = ns;
- temp->tcp_c = new_tcp_connections(log, mem, rng, ns, mono_time, dht_get_self_secret_key(dht), proxy_info);
+ temp->tcp_c = new_tcp_connections(log, mem, rng, ns, mono_time, dht_get_self_secret_key(dht), proxy_info, tcp_np);
if (temp->tcp_c == nullptr) {
mem_delete(mem, temp);
@@ -3135,13 +3016,6 @@ Net_Crypto *new_net_crypto(const Logger *log, const Memory *mem, const Random *r
set_packet_tcp_connection_callback(temp->tcp_c, &tcp_data_callback, temp);
set_oob_packet_tcp_connection_callback(temp->tcp_c, &tcp_oob_callback, temp);
- if (create_recursive_mutex(&temp->tcp_mutex) != 0 ||
- pthread_mutex_init(&temp->connections_mutex, nullptr) != 0) {
- kill_tcp_connections(temp->tcp_c);
- mem_delete(mem, temp);
- return nullptr;
- }
-
temp->dht = dht;
new_keys(temp);
@@ -3154,7 +3028,7 @@ Net_Crypto *new_net_crypto(const Logger *log, const Memory *mem, const Random *r
networking_registerhandler(dht_get_net(dht), NET_PACKET_CRYPTO_HS, &udp_handle_packet, temp);
networking_registerhandler(dht_get_net(dht), NET_PACKET_CRYPTO_DATA, &udp_handle_packet, temp);
- bs_list_init(&temp->ip_port_list, sizeof(IP_Port), 8, ipport_cmp_handler);
+ bs_list_init(&temp->ip_port_list, mem, sizeof(IP_Port), 8, ipport_cmp_handler);
return temp;
}
@@ -3215,9 +3089,6 @@ void kill_net_crypto(Net_Crypto *c)
crypto_kill(c, i);
}
- pthread_mutex_destroy(&c->tcp_mutex);
- pthread_mutex_destroy(&c->connections_mutex);
-
kill_tcp_connections(c->tcp_c);
bs_list_free(&c->ip_port_list);
networking_registerhandler(dht_get_net(c->dht), NET_PACKET_COOKIE_REQUEST, nullptr, nullptr);
diff --git a/protocols/Tox/libtox/src/toxcore/net_crypto.h b/protocols/Tox/libtox/src/toxcore/net_crypto.h
index 0d817e4315..894707005b 100644
--- a/protocols/Tox/libtox/src/toxcore/net_crypto.h
+++ b/protocols/Tox/libtox/src/toxcore/net_crypto.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -9,10 +9,7 @@
#ifndef C_TOXCORE_TOXCORE_NET_CRYPTO_H
#define C_TOXCORE_TOXCORE_NET_CRYPTO_H
-#include <pthread.h>
-
#include "DHT.h"
-#include "LAN_discovery.h"
#include "TCP_client.h"
#include "TCP_connection.h"
#include "attributes.h"
@@ -20,8 +17,13 @@
#include "logger.h"
#include "mem.h"
#include "mono_time.h"
+#include "net_profile.h"
#include "network.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*** Crypto payloads. */
/*** Ranges. */
@@ -40,7 +42,6 @@
/** Packets in this range are reserved for AV use. */
#define PACKET_ID_RANGE_LOSSY_START 192
#define PACKET_ID_RANGE_LOSSY_AV_START 192
-#define PACKET_ID_RANGE_LOSSY_AV_SIZE 8
#define PACKET_ID_RANGE_LOSSY_AV_END 199
/** Packets in this range can be used for anything. */
#define PACKET_ID_RANGE_LOSSY_CUSTOM_START 200
@@ -243,7 +244,7 @@ uint32_t crypto_num_free_sendqueue_slots(const Net_Crypto *c, int crypt_connecti
* @retval 0 if it wasn't reached.
*/
non_null()
-bool max_speed_reached(Net_Crypto *c, int crypt_connection_id);
+bool max_speed_reached(const Net_Crypto *c, int crypt_connection_id);
/** @brief Sends a lossless cryptopacket.
*
@@ -255,7 +256,7 @@ bool max_speed_reached(Net_Crypto *c, int crypt_connection_id);
* congestion_control: should congestion control apply to this packet?
*/
non_null()
-int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id,
+int64_t write_cryptpacket(const Net_Crypto *c, int crypt_connection_id,
const uint8_t *data, uint16_t length, bool congestion_control);
/** @brief Check if packet_number was received by the other side.
@@ -283,7 +284,7 @@ int cryptpacket_received(const Net_Crypto *c, int crypt_connection_id, uint32_t
* The first byte of data must be in the PACKET_ID_RANGE_LOSSY.
*/
non_null()
-int send_lossy_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length);
+int send_lossy_cryptpacket(const Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length);
/** @brief Add a tcp relay, associating it to a crypt_connection_id.
*
@@ -311,7 +312,7 @@ int add_tcp_relay(Net_Crypto *c, const IP_Port *ip_port, const uint8_t *public_k
* return -1 on failure.
*/
non_null()
-int get_random_tcp_con_number(Net_Crypto *c);
+int get_random_tcp_con_number(const Net_Crypto *c);
/** @brief Put IP_Port of a random onion TCP connection in ip_port.
*
@@ -319,7 +320,7 @@ int get_random_tcp_con_number(Net_Crypto *c);
* return false on failure.
*/
non_null()
-bool get_random_tcp_conn_ip_port(Net_Crypto *c, IP_Port *ip_port);
+bool get_random_tcp_conn_ip_port(const Net_Crypto *c, IP_Port *ip_port);
/** @brief Send an onion packet via the TCP relay corresponding to tcp_connections_number.
*
@@ -351,7 +352,7 @@ int send_tcp_forward_request(const Logger *logger, Net_Crypto *c, const IP_Port
* return 0 on failure.
*/
non_null()
-unsigned int copy_connected_tcp_relays(Net_Crypto *c, Node_format *tcp_relays, uint16_t num);
+unsigned int copy_connected_tcp_relays(const Net_Crypto *c, Node_format *tcp_relays, uint16_t num);
/**
* Copy a maximum of `max_num` TCP relays we are connected to starting at the index in the TCP relay array
@@ -360,7 +361,7 @@ unsigned int copy_connected_tcp_relays(Net_Crypto *c, Node_format *tcp_relays, u
* Returns the number of relays successfully copied.
*/
non_null()
-uint32_t copy_connected_tcp_relays_index(Net_Crypto *c, Node_format *tcp_relays, uint16_t num, uint32_t idx);
+uint32_t copy_connected_tcp_relays_index(const Net_Crypto *c, Node_format *tcp_relays, uint16_t num, uint32_t idx);
/** @brief Kill a crypto connection.
*
@@ -405,7 +406,7 @@ void load_secret_key(Net_Crypto *c, const uint8_t *sk);
*/
non_null()
Net_Crypto *new_net_crypto(const Logger *log, const Memory *mem, const Random *rng, const Network *ns,
- Mono_Time *mono_time, DHT *dht, const TCP_Proxy_Info *proxy_info);
+ Mono_Time *mono_time, DHT *dht, const TCP_Proxy_Info *proxy_info, Net_Profile *tcp_np);
/** return the optimal interval in ms for running do_net_crypto. */
non_null()
@@ -418,4 +419,8 @@ void do_net_crypto(Net_Crypto *c, void *userdata);
nullable(1)
void kill_net_crypto(Net_Crypto *c);
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
#endif /* C_TOXCORE_TOXCORE_NET_CRYPTO_H */
diff --git a/protocols/Tox/libtox/src/toxcore/net_profile.c b/protocols/Tox/libtox/src/toxcore/net_profile.c
new file mode 100644
index 0000000000..1d700bdb85
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/net_profile.c
@@ -0,0 +1,157 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2023-2025 The TokTok team.
+ */
+
+/**
+ * Functions for the network profile.
+ */
+
+#include "net_profile.h"
+
+#include <stdint.h>
+
+#include "attributes.h"
+#include "logger.h"
+#include "mem.h"
+
+#include "ccompat.h"
+
+#define NETPROF_TCP_DATA_PACKET_ID 0x10
+
+typedef struct Net_Profile {
+ uint64_t packets_recv[NET_PROF_MAX_PACKET_IDS];
+ uint64_t packets_sent[NET_PROF_MAX_PACKET_IDS];
+
+ uint64_t total_packets_recv;
+ uint64_t total_packets_sent;
+
+ uint64_t bytes_recv[NET_PROF_MAX_PACKET_IDS];
+ uint64_t bytes_sent[NET_PROF_MAX_PACKET_IDS];
+
+ uint64_t total_bytes_recv;
+ uint64_t total_bytes_sent;
+} Net_Profile;
+
+/** Returns the number of sent or received packets for all ID's between `start_id` and `end_id`. */
+nullable(1)
+static uint64_t netprof_get_packet_count_id_range(const Net_Profile *profile, uint8_t start_id, uint8_t end_id,
+ Packet_Direction dir)
+{
+ if (profile == nullptr) {
+ return 0;
+ }
+
+ const uint64_t *arr = dir == PACKET_DIRECTION_SEND ? profile->packets_sent : profile->packets_recv;
+ uint64_t count = 0;
+
+ for (size_t i = start_id; i <= end_id; ++i) {
+ count += arr[i];
+ }
+
+ return count;
+}
+
+/** Returns the number of sent or received bytes for all ID's between `start_id` and `end_id`. */
+nullable(1)
+static uint64_t netprof_get_bytes_id_range(const Net_Profile *profile, uint8_t start_id, uint8_t end_id,
+ Packet_Direction dir)
+{
+ if (profile == nullptr) {
+ return 0;
+ }
+
+ const uint64_t *arr = dir == PACKET_DIRECTION_SEND ? profile->bytes_sent : profile->bytes_recv;
+ uint64_t bytes = 0;
+
+ for (size_t i = start_id; i <= end_id; ++i) {
+ bytes += arr[i];
+ }
+
+ return bytes;
+}
+
+void netprof_record_packet(Net_Profile *profile, uint8_t id, size_t length, Packet_Direction dir)
+{
+ if (profile == nullptr) {
+ return;
+ }
+
+ if (dir == PACKET_DIRECTION_SEND) {
+ ++profile->total_packets_sent;
+ ++profile->packets_sent[id];
+
+ profile->total_bytes_sent += length;
+ profile->bytes_sent[id] += length;
+ } else {
+ ++profile->total_packets_recv;
+ ++profile->packets_recv[id];
+
+ profile->total_bytes_recv += length;
+ profile->bytes_recv[id] += length;
+ }
+}
+
+uint64_t netprof_get_packet_count_id(const Net_Profile *profile, uint8_t id, Packet_Direction dir)
+{
+ if (profile == nullptr) {
+ return 0;
+ }
+
+ // Special case - TCP data packets can have any ID between 0x10 and 0xff
+ if (id == NETPROF_TCP_DATA_PACKET_ID) {
+ return netprof_get_packet_count_id_range(profile, id, UINT8_MAX, dir);
+ }
+
+ return dir == PACKET_DIRECTION_SEND ? profile->packets_sent[id] : profile->packets_recv[id];
+}
+
+uint64_t netprof_get_packet_count_total(const Net_Profile *profile, Packet_Direction dir)
+{
+ if (profile == nullptr) {
+ return 0;
+ }
+
+ return dir == PACKET_DIRECTION_SEND ? profile->total_packets_sent : profile->total_packets_recv;
+}
+
+uint64_t netprof_get_bytes_id(const Net_Profile *profile, uint8_t id, Packet_Direction dir)
+{
+ if (profile == nullptr) {
+ return 0;
+ }
+
+ // Special case - TCP data packets can have any ID between 0x10 and 0xff
+ if (id == NETPROF_TCP_DATA_PACKET_ID) {
+ return netprof_get_bytes_id_range(profile, id, 0xff, dir);
+ }
+
+ return dir == PACKET_DIRECTION_SEND ? profile->bytes_sent[id] : profile->bytes_recv[id];
+}
+
+uint64_t netprof_get_bytes_total(const Net_Profile *profile, Packet_Direction dir)
+{
+ if (profile == nullptr) {
+ return 0;
+ }
+
+ return dir == PACKET_DIRECTION_SEND ? profile->total_bytes_sent : profile->total_bytes_recv;
+}
+
+Net_Profile *netprof_new(const Logger *log, const Memory *mem)
+{
+ Net_Profile *np = (Net_Profile *)mem_alloc(mem, sizeof(Net_Profile));
+
+ if (np == nullptr) {
+ LOGGER_ERROR(log, "failed to allocate memory for net profiler");
+ return nullptr;
+ }
+
+ return np;
+}
+
+void netprof_kill(const Memory *mem, Net_Profile *net_profile)
+{
+ if (net_profile != nullptr) {
+ mem_delete(mem, net_profile);
+ }
+}
diff --git a/protocols/Tox/libtox/src/toxcore/net_profile.h b/protocols/Tox/libtox/src/toxcore/net_profile.h
new file mode 100644
index 0000000000..be16f671de
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/net_profile.h
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2023-2025 The TokTok team.
+ */
+
+/**
+ * Functions for the network profile.
+ */
+#ifndef C_TOXCORE_TOXCORE_NET_PROFILE_H
+#define C_TOXCORE_TOXCORE_NET_PROFILE_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "attributes.h"
+#include "logger.h"
+#include "mem.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The max number of packet ID's (must fit inside one byte) */
+#define NET_PROF_MAX_PACKET_IDS 256
+
+/* If passed to a netprof function as a nullptr the function will have no effect. */
+typedef struct Net_Profile Net_Profile;
+
+/** Specifies whether the query is for sent or received packets. */
+typedef enum Packet_Direction {
+ PACKET_DIRECTION_SEND,
+ PACKET_DIRECTION_RECV,
+} Packet_Direction;
+
+/**
+ * Records a sent or received packet of type `id` and size `length` to the given profile.
+ */
+nullable(1)
+void netprof_record_packet(Net_Profile *profile, uint8_t id, size_t length, Packet_Direction dir);
+
+/**
+ * Returns the number of sent or received packets of type `id` for the given profile.
+ */
+nullable(1)
+uint64_t netprof_get_packet_count_id(const Net_Profile *profile, uint8_t id, Packet_Direction dir);
+
+/**
+ * Returns the total number of sent or received packets for the given profile.
+ */
+nullable(1)
+uint64_t netprof_get_packet_count_total(const Net_Profile *profile, Packet_Direction dir);
+
+/**
+ * Returns the number of bytes sent or received of packet type `id` for the given profile.
+ */
+nullable(1)
+uint64_t netprof_get_bytes_id(const Net_Profile *profile, uint8_t id, Packet_Direction dir);
+
+/**
+ * Returns the total number of bytes sent or received for the given profile.
+ */
+nullable(1)
+uint64_t netprof_get_bytes_total(const Net_Profile *profile, Packet_Direction dir);
+
+/**
+ * Returns a new net_profile object. The caller is responsible for freeing the
+ * returned memory via `netprof_kill`.
+ */
+non_null()
+Net_Profile *netprof_new(const Logger *log, const Memory *mem);
+
+/**
+ * Kills a net_profile object and frees all associated memory.
+ */
+non_null(1) nullable(2)
+void netprof_kill(const Memory *mem, Net_Profile *net_profile);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* C_TOXCORE_TOXCORE_NET_PROFILE_H */
diff --git a/protocols/Tox/libtox/src/toxcore/network.c b/protocols/Tox/libtox/src/toxcore/network.c
index 55aa4e2818..bd6babf26e 100644
--- a/protocols/Tox/libtox/src/toxcore/network.c
+++ b/protocols/Tox/libtox/src/toxcore/network.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2023 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -86,6 +86,7 @@
#include "ccompat.h"
#include "logger.h"
#include "mem.h"
+#include "net_profile.h"
#include "util.h"
// Disable MSG_NOSIGNAL on systems not supporting it, e.g. Windows, FreeBSD
@@ -263,9 +264,11 @@ static int make_family(Family tox_family)
{
switch (tox_family.value) {
case TOX_AF_INET:
+ case TCP_INET:
return AF_INET;
case TOX_AF_INET6:
+ case TCP_INET6:
return AF_INET6;
case TOX_AF_UNSPEC:
@@ -514,6 +517,12 @@ static int sys_listen(void *obj, Socket sock, int backlog)
}
non_null()
+static int sys_connect(void *obj, Socket sock, const Network_Addr *addr)
+{
+ return connect(net_socket_to_native(sock), (const struct sockaddr *)&addr->addr, addr->size);
+}
+
+non_null()
static int sys_recvbuf(void *obj, Socket sock)
{
#ifdef OS_WIN32
@@ -583,7 +592,97 @@ static int sys_getsockopt(void *obj, Socket sock, int level, int optname, void *
non_null()
static int sys_setsockopt(void *obj, Socket sock, int level, int optname, const void *optval, size_t optlen)
{
+#ifdef EMSCRIPTEN
+ return 0;
+#else
return setsockopt(net_socket_to_native(sock), level, optname, (const char *)optval, optlen);
+#endif /* EMSCRIPTEN */
+}
+
+// sets and fills an array of addrs for address
+// returns the number of entries in addrs
+non_null()
+static int sys_getaddrinfo(void *obj, const Memory *mem, const char *address, int family, int sock_type, Network_Addr **addrs)
+{
+ assert(addrs != nullptr);
+
+ struct addrinfo hints = {0};
+ hints.ai_family = family;
+
+
+ // different platforms favour a different field
+ // hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses.
+ hints.ai_socktype = sock_type;
+ // hints.ai_protocol = protocol;
+
+ struct addrinfo *infos = nullptr;
+
+ const int rc = getaddrinfo(address, nullptr, &hints, &infos);
+
+ // Lookup failed.
+ if (rc != 0) {
+ // TODO(Green-Sky): log error
+ return 0;
+ }
+
+ const int32_t max_count = INT32_MAX / sizeof(Network_Addr);
+
+ // we count number of "valid" results
+ int result = 0;
+ for (struct addrinfo *walker = infos; walker != nullptr && result < max_count; walker = walker->ai_next) {
+ if (walker->ai_family == family || family == AF_UNSPEC) {
+ ++result;
+ }
+
+ // do we need to check socktype/protocol?
+ }
+
+ assert(max_count >= result);
+
+ Network_Addr *tmp_addrs = (Network_Addr *)mem_valloc(mem, result, sizeof(Network_Addr));
+ if (tmp_addrs == nullptr) {
+ freeaddrinfo(infos);
+ return 0;
+ }
+
+ // now we fill in
+ int i = 0;
+ for (struct addrinfo *walker = infos; walker != nullptr; walker = walker->ai_next) {
+ if (walker->ai_family == family || family == AF_UNSPEC) {
+ tmp_addrs[i].size = sizeof(struct sockaddr_storage);
+ tmp_addrs[i].addr.ss_family = walker->ai_family;
+
+ // according to spec, storage is supposed to be large enough (and source shows they are)
+ // storage is 128 bytes
+ assert(walker->ai_addrlen <= tmp_addrs[i].size);
+
+ memcpy(&tmp_addrs[i].addr, walker->ai_addr, walker->ai_addrlen);
+ tmp_addrs[i].size = walker->ai_addrlen;
+
+ ++i;
+ }
+ }
+
+ assert(i == result);
+
+ freeaddrinfo(infos);
+
+ *addrs = tmp_addrs;
+
+ // number of entries in addrs
+ return result;
+}
+
+non_null()
+static int sys_freeaddrinfo(void *obj, const Memory *mem, Network_Addr *addrs)
+{
+ if (addrs == nullptr) {
+ return 0;
+ }
+
+ mem_delete(mem, addrs);
+
+ return 0;
}
static const Network_Funcs os_network_funcs = {
@@ -591,6 +690,7 @@ static const Network_Funcs os_network_funcs = {
sys_accept,
sys_bind,
sys_listen,
+ sys_connect,
sys_recvbuf,
sys_recv,
sys_recvfrom,
@@ -600,8 +700,10 @@ static const Network_Funcs os_network_funcs = {
sys_socket_nonblock,
sys_getsockopt,
sys_setsockopt,
+ sys_getaddrinfo,
+ sys_freeaddrinfo,
};
-static const Network os_network_obj = {&os_network_funcs};
+static const Network os_network_obj = {&os_network_funcs, nullptr};
const Network *os_network(void)
{
@@ -674,11 +776,11 @@ static const char *net_packet_type_name(Net_Packet_Type type)
case NET_PACKET_PING_RESPONSE:
return "PING_RESPONSE";
- case NET_PACKET_GET_NODES:
- return "GET_NODES";
+ case NET_PACKET_NODES_REQUEST:
+ return "NODES_REQUEST";
- case NET_PACKET_SEND_NODES_IPV6:
- return "SEND_NODES_IPV6";
+ case NET_PACKET_NODES_RESPONSE:
+ return "NODES_RESPONSE";
case NET_PACKET_COOKIE_REQUEST:
return "COOKIE_REQUEST";
@@ -787,13 +889,12 @@ static void loglogdata(const Logger *log, const char *message, const uint8_t *bu
if (res < 0) { /* Windows doesn't necessarily know `%zu` */
Ip_Ntoa ip_str;
const int error = net_error();
- char *strerror = net_new_strerror(error);
+ Net_Strerror error_str;
LOGGER_TRACE(log, "[%02x = %-21s] %s %3u%c %s:%u (%u: %s) | %08x%08x...%02x",
buffer[0], net_packet_type_name((Net_Packet_Type)buffer[0]), message,
min_u16(buflen, 999), 'E',
net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port), error,
- strerror, data_0(buflen, buffer), data_1(buflen, buffer), buffer[buflen - 1]);
- net_kill_strerror(strerror);
+ net_strerror(error, &error_str), data_0(buflen, buffer), data_1(buflen, buffer), buffer[buflen - 1]);
} else if ((res > 0) && ((size_t)res <= buflen)) {
Ip_Ntoa ip_str;
LOGGER_TRACE(log, "[%02x = %-21s] %s %3u%c %s:%u (%u: %s) | %08x%08x...%02x",
@@ -812,9 +913,14 @@ static void loglogdata(const Logger *log, const char *message, const uint8_t *bu
}
int net_send(const Network *ns, const Logger *log,
- Socket sock, const uint8_t *buf, size_t len, const IP_Port *ip_port)
+ Socket sock, const uint8_t *buf, size_t len, const IP_Port *ip_port, Net_Profile *net_profile)
{
const int res = ns->funcs->send(ns->obj, sock, buf, len);
+
+ if (res > 0) {
+ netprof_record_packet(net_profile, buf[0], res, PACKET_DIRECTION_SEND);
+ }
+
loglogdata(log, "T=>", buf, len, ip_port, res);
return res;
}
@@ -882,7 +988,11 @@ bool set_socket_nosigpipe(const Network *ns, Socket sock)
bool set_socket_reuseaddr(const Network *ns, Socket sock)
{
int set = 1;
+#if defined(OS_WIN32)
+ return net_setsockopt(ns, sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, &set, sizeof(set)) == 0;
+#else
return net_setsockopt(ns, sock, SOL_SOCKET, SO_REUSEADDR, &set, sizeof(set)) == 0;
+#endif /* OS_WIN32 */
}
bool set_socket_dualstack(const Network *ns, Socket sock)
@@ -914,6 +1024,8 @@ struct Networking_Core {
uint16_t port;
/* Our UDP socket. */
Socket sock;
+
+ Net_Profile *udp_net_profile;
};
Family net_family(const Networking_Core *net)
@@ -941,7 +1053,7 @@ int send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet packe
if (net_family_is_unspec(net->family)) { /* Socket not initialized */
// TODO(iphydf): Make this an error. Currently, the onion client calls
- // this via DHT getnodes.
+ // this via DHT nodes requests.
LOGGER_WARNING(net->log, "attempted to send message of length %u on uninitialised socket", packet.length);
return -1;
}
@@ -999,6 +1111,11 @@ int send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet packe
loglogdata(net->log, "O=>", packet.data, packet.length, ip_port, res);
assert(res <= INT_MAX);
+
+ if (res == packet.length && packet.data != nullptr) {
+ netprof_record_packet(net->udp_net_profile, packet.data[0], packet.length, PACKET_DIRECTION_SEND);
+ }
+
return (int)res;
}
@@ -1019,7 +1136,7 @@ int sendpacket(const Networking_Core *net, const IP_Port *ip_port, const uint8_t
* Packet length is put into length.
*/
non_null()
-static int receivepacket(const Network *ns, const Memory *mem, const Logger *log, Socket sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
+static int receivepacket(const Network *ns, const Logger *log, Socket sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
{
memset(ip_port, 0, sizeof(IP_Port));
Network_Addr addr = {{0}};
@@ -1032,9 +1149,8 @@ static int receivepacket(const Network *ns, const Memory *mem, const Logger *log
const int error = net_error();
if (!should_ignore_recv_error(error)) {
- char *strerror = net_new_strerror(error);
- LOGGER_ERROR(log, "unexpected error reading from socket: %u, %s", error, strerror);
- net_kill_strerror(strerror);
+ Net_Strerror error_str;
+ LOGGER_ERROR(log, "unexpected error reading from socket: %u, %s", error, net_strerror(error, &error_str));
}
return -1; /* Nothing received. */
@@ -1098,11 +1214,13 @@ void networking_poll(const Networking_Core *net, void *userdata)
uint8_t data[MAX_UDP_PACKET_SIZE] = {0};
uint32_t length;
- while (receivepacket(net->ns, net->mem, net->log, net->sock, &ip_port, data, &length) != -1) {
+ while (receivepacket(net->ns, net->log, net->sock, &ip_port, data, &length) != -1) {
if (length < 1) {
continue;
}
+ netprof_record_packet(net->udp_net_profile, data[0], length, PACKET_DIRECTION_RECV);
+
const Packet_Handler *const handler = &net->packethandlers[data[0]];
if (handler->function == nullptr) {
@@ -1163,6 +1281,14 @@ Networking_Core *new_networking_ex(
return nullptr;
}
+ Net_Profile *np = netprof_new(log, mem);
+
+ if (np == nullptr) {
+ free(temp);
+ return nullptr;
+ }
+
+ temp->udp_net_profile = np;
temp->ns = ns;
temp->log = log;
temp->mem = mem;
@@ -1176,9 +1302,9 @@ Networking_Core *new_networking_ex(
/* Check for socket error. */
if (!sock_valid(temp->sock)) {
const int neterror = net_error();
- char *strerror = net_new_strerror(neterror);
- LOGGER_ERROR(log, "failed to get a socket?! %d, %s", neterror, strerror);
- net_kill_strerror(strerror);
+ Net_Strerror error_str;
+ LOGGER_ERROR(log, "failed to get a socket?! %d, %s", neterror, net_strerror(neterror, &error_str));
+ netprof_kill(mem, temp->udp_net_profile);
mem_delete(mem, temp);
if (error != nullptr) {
@@ -1279,15 +1405,13 @@ Networking_Core *new_networking_ex(
const int res = net_setsockopt(ns, temp->sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
const int neterror = net_error();
- char *strerror = net_new_strerror(neterror);
+ Net_Strerror error_str;
if (res < 0) {
- LOGGER_INFO(log, "Failed to activate local multicast membership in FF02::1. (%d, %s)", neterror, strerror);
+ LOGGER_INFO(log, "Failed to activate local multicast membership in FF02::1. (%d, %s)", neterror, net_strerror(neterror, &error_str));
} else {
- LOGGER_TRACE(log, "Local multicast group joined successfully. (%d, %s)", neterror, strerror);
+ LOGGER_TRACE(log, "Local multicast group joined successfully. (%d, %s)", neterror, net_strerror(neterror, &error_str));
}
-
- net_kill_strerror(strerror);
#endif /* ESP_PLATFORM */
}
@@ -1345,10 +1469,9 @@ Networking_Core *new_networking_ex(
Ip_Ntoa ip_str;
const int neterror = net_error();
- char *strerror = net_new_strerror(neterror);
+ Net_Strerror error_str;
LOGGER_ERROR(log, "failed to bind socket: %d, %s IP: %s port_from: %u port_to: %u",
- neterror, strerror, net_ip_ntoa(ip, &ip_str), port_from, port_to);
- net_kill_strerror(strerror);
+ neterror, net_strerror(neterror, &error_str), net_ip_ntoa(ip, &ip_str), port_from, port_to);
kill_networking(temp);
if (error != nullptr) {
@@ -1386,6 +1509,7 @@ void kill_networking(Networking_Core *net)
kill_sock(net->ns, net->sock);
}
+ netprof_kill(net->mem, net->udp_net_profile);
mem_delete(net->mem, net);
}
@@ -1754,14 +1878,14 @@ bool ip_parse_addr(const IP *ip, char *address, size_t length)
return false;
}
- if (net_family_is_ipv4(ip->family)) {
+ if (net_family_is_ipv4(ip->family) || net_family_is_tcp_ipv4(ip->family)) {
struct in_addr addr;
assert(make_family(ip->family) == AF_INET);
fill_addr4(&ip->ip.v4, &addr);
return inet_ntop4(&addr, address, length) != nullptr;
}
- if (net_family_is_ipv6(ip->family)) {
+ if (net_family_is_ipv6(ip->family) || net_family_is_tcp_ipv6(ip->family)) {
struct in6_addr addr;
assert(make_family(ip->family) == AF_INET6);
fill_addr6(&ip->ip.v6, &addr);
@@ -1815,37 +1939,34 @@ bool addr_parse_ip(const char *address, IP *to)
* prefers v6 if `ip.family` was TOX_AF_UNSPEC and both available
* Returns in `*extra` an IPv4 address, if family was TOX_AF_UNSPEC and `*to` is TOX_AF_INET6
*
- * @return 0 on failure, `TOX_ADDR_RESOLVE_*` on success.
+ * @return false on failure, true on success.
*/
-non_null(1, 2, 3) nullable(4)
-static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extra)
+non_null(1, 2, 3, 4) nullable(5)
+static bool addr_resolve(const Network *ns, const Memory *mem, const char *address, IP *to, IP *extra)
{
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
if ((true)) {
- return 0;
+ return false;
}
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
if (address == nullptr || to == nullptr) {
- return 0;
+ return false;
}
const Family tox_family = to->family;
const int family = make_family(tox_family);
- struct addrinfo hints = {0};
- hints.ai_family = family;
- hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses.
-
- struct addrinfo *server = nullptr;
+ Network_Addr *addrs = nullptr;
+ const int rc = ns->funcs->getaddrinfo(ns->obj, mem, address, family, 0, &addrs);
- const int rc = getaddrinfo(address, nullptr, &hints, &server);
-
- // Lookup failed.
- if (rc != 0) {
- return 0;
+ // Lookup failed / empty.
+ if (rc <= 0) {
+ return false;
}
+ assert(addrs != nullptr);
+
IP ip4;
ip_init(&ip4, false); // ipv6enabled = false
IP ip6;
@@ -1854,16 +1975,16 @@ static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extr
int result = 0;
bool done = false;
- for (struct addrinfo *walker = server; walker != nullptr && !done; walker = walker->ai_next) {
- switch (walker->ai_family) {
+ for (int i = 0; i < rc && !done; ++i) {
+ switch (addrs[i].addr.ss_family) {
case AF_INET: {
- if (walker->ai_family == family) { /* AF_INET requested, done */
- const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)walker->ai_addr;
+ if (addrs[i].addr.ss_family == family) { /* AF_INET requested, done */
+ const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)&addrs[i].addr;
get_ip4(&to->ip.v4, &addr->sin_addr);
result = TOX_ADDR_RESOLVE_INET;
done = true;
} else if ((result & TOX_ADDR_RESOLVE_INET) == 0) { /* AF_UNSPEC requested, store away */
- const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)walker->ai_addr;
+ const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)&addrs[i].addr;
get_ip4(&ip4.ip.v4, &addr->sin_addr);
result |= TOX_ADDR_RESOLVE_INET;
}
@@ -1872,16 +1993,16 @@ static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extr
}
case AF_INET6: {
- if (walker->ai_family == family) { /* AF_INET6 requested, done */
- if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
- const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)walker->ai_addr;
+ if (addrs[i].addr.ss_family == family) { /* AF_INET6 requested, done */
+ if (addrs[i].size == sizeof(struct sockaddr_in6)) {
+ const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)&addrs[i].addr;
get_ip6(&to->ip.v6, &addr->sin6_addr);
result = TOX_ADDR_RESOLVE_INET6;
done = true;
}
} else if ((result & TOX_ADDR_RESOLVE_INET6) == 0) { /* AF_UNSPEC requested, store away */
- if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
- const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)walker->ai_addr;
+ if (addrs[i].size == sizeof(struct sockaddr_in6)) {
+ const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)&addrs[i].addr;
get_ip6(&ip6.ip.v6, &addr->sin6_addr);
result |= TOX_ADDR_RESOLVE_INET6;
}
@@ -1906,37 +2027,48 @@ static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extr
}
}
- freeaddrinfo(server);
- return result;
+ ns->funcs->freeaddrinfo(ns->obj, mem, addrs);
+ return result != 0;
}
-bool addr_resolve_or_parse_ip(const Network *ns, const char *address, IP *to, IP *extra)
+bool addr_resolve_or_parse_ip(const Network *ns, const Memory *mem, const char *address, IP *to, IP *extra, bool dns_enabled)
{
- if (addr_resolve(ns, address, to, extra) == 0) {
- if (!addr_parse_ip(address, to)) {
- return false;
- }
+ if (dns_enabled && addr_resolve(ns, mem, address, to, extra)) {
+ return true;
}
- return true;
+ return addr_parse_ip(address, to);
+}
+
+const char *net_err_connect_to_string(Net_Err_Connect err)
+{
+ switch (err) {
+ case NET_ERR_CONNECT_OK:
+ return "NET_ERR_CONNECT_OK";
+ case NET_ERR_CONNECT_INVALID_FAMILY:
+ return "NET_ERR_CONNECT_INVALID_FAMILY";
+ case NET_ERR_CONNECT_FAILED:
+ return "NET_ERR_CONNECT_FAILED";
+ }
+
+ return "<invalid Net_Err_Connect>";
}
-bool net_connect(const Memory *mem, const Logger *log, Socket sock, const IP_Port *ip_port)
+bool net_connect(const Network *ns, const Memory *mem, const Logger *log, Socket sock, const IP_Port *ip_port, Net_Err_Connect *err)
{
- struct sockaddr_storage addr = {0};
- size_t addrsize;
+ Network_Addr addr = {{0}};
if (net_family_is_ipv4(ip_port->ip.family)) {
- struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
+ struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr.addr;
- addrsize = sizeof(struct sockaddr_in);
+ addr.size = sizeof(struct sockaddr_in);
addr4->sin_family = AF_INET;
fill_addr4(&ip_port->ip.ip.v4, &addr4->sin_addr);
addr4->sin_port = ip_port->port;
} else if (net_family_is_ipv6(ip_port->ip.family)) {
- struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr.addr;
- addrsize = sizeof(struct sockaddr_in6);
+ addr.size = sizeof(struct sockaddr_in6);
addr6->sin6_family = AF_INET6;
fill_addr6(&ip_port->ip.ip.v6, &addr6->sin6_addr);
addr6->sin6_port = ip_port->port;
@@ -1944,11 +2076,13 @@ bool net_connect(const Memory *mem, const Logger *log, Socket sock, const IP_Por
Ip_Ntoa ip_str;
LOGGER_ERROR(log, "cannot connect to %s:%d which is neither IPv4 nor IPv6",
net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port));
+ *err = NET_ERR_CONNECT_INVALID_FAMILY;
return false;
}
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
if ((true)) {
+ *err = NET_ERR_CONNECT_OK;
return true;
}
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
@@ -1958,23 +2092,24 @@ bool net_connect(const Memory *mem, const Logger *log, Socket sock, const IP_Por
net_socket_to_native(sock), net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port));
errno = 0;
- if (connect(net_socket_to_native(sock), (struct sockaddr *)&addr, addrsize) == -1) {
+ if (ns->funcs->connect(ns->obj, sock, &addr) == -1) {
const int error = net_error();
// Non-blocking socket: "Operation in progress" means it's connecting.
if (!should_ignore_connect_error(error)) {
- char *net_strerror = net_new_strerror(error);
+ Net_Strerror error_str;
LOGGER_WARNING(log, "failed to connect to %s:%d: %d (%s)",
- net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port), error, net_strerror);
- net_kill_strerror(net_strerror);
+ net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port), error, net_strerror(error, &error_str));
+ *err = NET_ERR_CONNECT_FAILED;
return false;
}
}
+ *err = NET_ERR_CONNECT_OK;
return true;
}
-int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int tox_type)
+int32_t net_getipport(const Network *ns, const Memory *mem, const char *node, IP_Port **res, int tox_type, bool dns_enabled)
{
assert(node != nullptr);
@@ -1996,6 +2131,10 @@ int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int to
return 1;
}
+ if (!dns_enabled) {
+ return -1;
+ }
+
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
if ((true)) {
IP_Port *ip_port = (IP_Port *)mem_alloc(mem, sizeof(IP_Port));
@@ -2010,25 +2149,29 @@ int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int to
}
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
+ int type = make_socktype(tox_type);
+ // ugly
+ if (tox_type == -1) {
+ type = 0;
+ }
+
// It's not an IP address, so now we try doing a DNS lookup.
- struct addrinfo *infos;
- const int ret = getaddrinfo(node, nullptr, nullptr, &infos);
+ Network_Addr *addrs = nullptr;
+ const int rc = ns->funcs->getaddrinfo(ns->obj, mem, node, AF_UNSPEC, type, &addrs);
- if (ret != 0) {
+ // Lookup failed / empty.
+ if (rc <= 0) {
return -1;
}
+ assert(addrs != nullptr);
+
// Used to avoid calloc parameter overflow
const size_t max_count = min_u64(SIZE_MAX, INT32_MAX) / sizeof(IP_Port);
- const int type = make_socktype(tox_type);
size_t count = 0;
- for (struct addrinfo *cur = infos; count < max_count && cur != nullptr; cur = cur->ai_next) {
- if (cur->ai_socktype != 0 && type > 0 && cur->ai_socktype != type) {
- continue;
- }
-
- if (cur->ai_family != AF_INET && cur->ai_family != AF_INET6) {
+ for (int i = 0; i < rc && count < max_count; ++i) {
+ if (addrs[i].addr.ss_family != AF_INET && addrs[i].addr.ss_family != AF_INET6) {
continue;
}
@@ -2038,40 +2181,36 @@ int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int to
assert(count <= max_count);
if (count == 0) {
- freeaddrinfo(infos);
+ ns->funcs->freeaddrinfo(ns->obj, mem, addrs);
return 0;
}
IP_Port *ip_port = (IP_Port *)mem_valloc(mem, count, sizeof(IP_Port));
if (ip_port == nullptr) {
- freeaddrinfo(infos);
+ ns->funcs->freeaddrinfo(ns->obj, mem, addrs);
*res = nullptr;
return -1;
}
*res = ip_port;
- for (struct addrinfo *cur = infos; cur != nullptr; cur = cur->ai_next) {
- if (cur->ai_socktype != 0 && type > 0 && cur->ai_socktype != type) {
- continue;
- }
-
- if (cur->ai_family == AF_INET) {
- const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)cur->ai_addr;
+ for (int i = 0; i < rc && count < max_count; ++i) {
+ if (addrs[i].addr.ss_family == AF_INET) {
+ const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)&addrs[i].addr;
ip_port->ip.ip.v4.uint32 = addr->sin_addr.s_addr;
- } else if (cur->ai_family == AF_INET6) {
- const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(const void *)cur->ai_addr;
+ } else if (addrs[i].addr.ss_family == AF_INET6) {
+ const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(const void *)&addrs[i].addr;
memcpy(ip_port->ip.ip.v6.uint8, addr->sin6_addr.s6_addr, sizeof(IP6));
} else {
continue;
}
- const Family *const family = make_tox_family(cur->ai_family);
+ const Family *const family = make_tox_family(addrs[i].addr.ss_family);
assert(family != nullptr);
if (family == nullptr) {
- freeaddrinfo(infos);
+ ns->funcs->freeaddrinfo(ns->obj, mem, addrs);
return -1;
}
@@ -2080,7 +2219,7 @@ int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int to
++ip_port;
}
- freeaddrinfo(infos);
+ ns->funcs->freeaddrinfo(ns->obj, mem, addrs);
return count;
}
@@ -2227,19 +2366,11 @@ int net_error(void)
}
#ifdef OS_WIN32
-char *net_new_strerror(int error)
-{
- char *str = nullptr;
- // Windows API is weird. The 5th function arg is of char* type, but we
- // have to pass char** so that it could assign new memory block to our
- // pointer, so we have to cast our char** to char* for the compilation
- // not to fail (otherwise it would fail to find a variant of this function
- // accepting char** as the 5th arg) and Windows inside casts it back
- // to char** to do the assignment. So no, this cast you see here, although
- // it looks weird, is not a mistake.
- FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr,
- error, 0, (char *)&str, 0, nullptr);
- return str;
+char *net_strerror(int error, Net_Strerror *buf)
+{
+ FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr,
+ error, 0, buf->data, NET_STRERROR_SIZE, nullptr);
+ return buf->data;
}
#else
#if defined(_GNU_SOURCE) && defined(__GLIBC__)
@@ -2267,32 +2398,24 @@ static const char *net_strerror_r(int error, char *tmp, size_t tmp_size)
return tmp;
}
#endif /* GNU */
-char *net_new_strerror(int error)
+char *net_strerror(int error, Net_Strerror *buf)
{
- char tmp[256];
-
errno = 0;
- const char *retstr = net_strerror_r(error, tmp, sizeof(tmp));
+ const char *retstr = net_strerror_r(error, buf->data, NET_STRERROR_SIZE);
const size_t retstr_len = strlen(retstr);
+ assert(retstr_len < NET_STRERROR_SIZE);
+ buf->size = (uint16_t)retstr_len;
- char *str = (char *)malloc(retstr_len + 1);
-
- if (str == nullptr) {
- return nullptr;
- }
-
- memcpy(str, retstr, retstr_len + 1);
-
- return str;
+ return buf->data;
}
#endif /* OS_WIN32 */
-void net_kill_strerror(char *strerror)
+const Net_Profile *net_get_net_profile(const Networking_Core *net)
{
-#ifdef OS_WIN32
- LocalFree((char *)strerror);
-#else
- free(strerror);
-#endif /* OS_WIN32 */
+ if (net == nullptr) {
+ return nullptr;
+ }
+
+ return net->udp_net_profile;
}
diff --git a/protocols/Tox/libtox/src/toxcore/network.h b/protocols/Tox/libtox/src/toxcore/network.h
index 06857b8917..a13c98bf6f 100644
--- a/protocols/Tox/libtox/src/toxcore/network.h
+++ b/protocols/Tox/libtox/src/toxcore/network.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -17,6 +17,7 @@
#include "bin_pack.h"
#include "logger.h"
#include "mem.h"
+#include "net_profile.h"
#ifdef __cplusplus
extern "C" {
@@ -39,6 +40,7 @@ typedef int net_close_cb(void *obj, Socket sock);
typedef Socket net_accept_cb(void *obj, Socket sock);
typedef int net_bind_cb(void *obj, Socket sock, const Network_Addr *addr);
typedef int net_listen_cb(void *obj, Socket sock, int backlog);
+typedef int net_connect_cb(void *obj, Socket sock, const Network_Addr *addr);
typedef int net_recvbuf_cb(void *obj, Socket sock);
typedef int net_recv_cb(void *obj, Socket sock, uint8_t *buf, size_t len);
typedef int net_recvfrom_cb(void *obj, Socket sock, uint8_t *buf, size_t len, Network_Addr *addr);
@@ -48,8 +50,8 @@ typedef Socket net_socket_cb(void *obj, int domain, int type, int proto);
typedef int net_socket_nonblock_cb(void *obj, Socket sock, bool nonblock);
typedef int net_getsockopt_cb(void *obj, Socket sock, int level, int optname, void *optval, size_t *optlen);
typedef int net_setsockopt_cb(void *obj, Socket sock, int level, int optname, const void *optval, size_t optlen);
-typedef int net_getaddrinfo_cb(void *obj, int family, Network_Addr **addrs);
-typedef int net_freeaddrinfo_cb(void *obj, Network_Addr *addrs);
+typedef int net_getaddrinfo_cb(void *obj, const Memory *mem, const char *address, int family, int protocol, Network_Addr **addrs);
+typedef int net_freeaddrinfo_cb(void *obj, const Memory *mem, Network_Addr *addrs);
/** @brief Functions wrapping POSIX network functions.
*
@@ -61,6 +63,7 @@ typedef struct Network_Funcs {
net_accept_cb *accept;
net_bind_cb *bind;
net_listen_cb *listen;
+ net_connect_cb *connect;
net_recvbuf_cb *recvbuf;
net_recv_cb *recv;
net_recvfrom_cb *recvfrom;
@@ -110,8 +113,8 @@ Family net_family_tox_tcp_ipv6(void);
typedef enum Net_Packet_Type {
NET_PACKET_PING_REQUEST = 0x00, /* Ping request packet ID. */
NET_PACKET_PING_RESPONSE = 0x01, /* Ping response packet ID. */
- NET_PACKET_GET_NODES = 0x02, /* Get nodes request packet ID. */
- NET_PACKET_SEND_NODES_IPV6 = 0x04, /* Send nodes response packet ID for other addresses. */
+ NET_PACKET_NODES_REQUEST = 0x02, /* Nodes request packet ID. */
+ NET_PACKET_NODES_RESPONSE = 0x04, /* Nodes response packet ID. */
NET_PACKET_COOKIE_REQUEST = 0x18, /* Cookie request packet */
NET_PACKET_COOKIE_RESPONSE = 0x19, /* Cookie response packet */
NET_PACKET_CRYPTO_HS = 0x1a, /* Crypto handshake packet */
@@ -233,11 +236,27 @@ Socket net_invalid_socket(void);
/**
* Calls send(sockfd, buf, len, MSG_NOSIGNAL).
- */
-non_null()
-int net_send(const Network *ns, const Logger *log, Socket sock, const uint8_t *buf, size_t len, const IP_Port *ip_port);
+ *
+ * @param ns System network object.
+ * @param log Logger object.
+ * @param sock Socket to send data with.
+ * @param buf Data to send.
+ * @param len Length of data.
+ * @param ip_port IP and port to send data to.
+ * @param net_profile Network profile to record the packet.
+ */
+non_null(1, 2, 4, 6) nullable(7)
+int net_send(const Network *ns, const Logger *log, Socket sock, const uint8_t *buf, size_t len, const IP_Port *ip_port,
+ Net_Profile *net_profile);
/**
* Calls recv(sockfd, buf, len, MSG_NOSIGNAL).
+ *
+ * @param ns System network object.
+ * @param log Logger object.
+ * @param sock Socket to receive data with.
+ * @param buf Buffer to store received data.
+ * @param len Length of buffer.
+ * @param ip_port IP and port of the sender.
*/
non_null()
int net_recv(const Network *ns, const Logger *log, Socket sock, uint8_t *buf, size_t len, const IP_Port *ip_port);
@@ -396,21 +415,23 @@ non_null()
void ipport_copy(IP_Port *target, const IP_Port *source);
/**
- * Resolves string into an IP address
+ * @brief Resolves string into an IP address.
*
- * @param address a hostname (or something parseable to an IP address)
- * @param to to.family MUST be initialized, either set to a specific IP version
+ * @param[in,out] ns Network object.
+ * @param[in] address a hostname (or something parseable to an IP address).
+ * @param[in,out] to to.family MUST be initialized, either set to a specific IP version
* (TOX_AF_INET/TOX_AF_INET6) or to the unspecified TOX_AF_UNSPEC (0), if both
- * IP versions are acceptable
- * @param extra can be NULL and is only set in special circumstances, see returns
+ * IP versions are acceptable.
+ * @param[out] extra can be NULL and is only set in special circumstances, see returns.
+ * @param[in] dns_enabled if false, DNS resolution is skipped.
*
- * Returns in `*to` a matching address (IPv6 or IPv4)
- * Returns in `*extra`, if not NULL, an IPv4 address, if `to->family` was TOX_AF_UNSPEC
+ * Returns in `*to` a matching address (IPv6 or IPv4).
+ * Returns in `*extra`, if not NULL, an IPv4 address, if `to->family` was `TOX_AF_UNSPEC`.
*
* @return true on success, false on failure
*/
-non_null(1, 2, 3) nullable(4)
-bool addr_resolve_or_parse_ip(const Network *ns, const char *address, IP *to, IP *extra);
+non_null(1, 2, 3, 4) nullable(5)
+bool addr_resolve_or_parse_ip(const Network *ns, const Memory *mem, const char *address, IP *to, IP *extra, bool dns_enabled);
/** @brief Function to receive data, ip and port of sender is put into ip_port.
* Packet data is put into data.
@@ -495,13 +516,22 @@ void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handl
non_null(1) nullable(2)
void networking_poll(const Networking_Core *net, void *userdata);
+typedef enum Net_Err_Connect {
+ NET_ERR_CONNECT_OK,
+ NET_ERR_CONNECT_INVALID_FAMILY,
+ NET_ERR_CONNECT_FAILED,
+} Net_Err_Connect;
+
+const char *net_err_connect_to_string(Net_Err_Connect err);
+
/** @brief Connect a socket to the address specified by the ip_port.
*
- * Return true on success.
- * Return false on failure.
+ * @param[out] err Set to NET_ERR_CONNECT_OK on success, otherwise an error code.
+ *
+ * @retval true on success, false on failure.
*/
non_null()
-bool net_connect(const Memory *mem, const Logger *log, Socket sock, const IP_Port *ip_port);
+bool net_connect(const Network *ns, const Memory *mem, const Logger *log, Socket sock, const IP_Port *ip_port, Net_Err_Connect *err);
/** @brief High-level getaddrinfo implementation.
*
@@ -510,14 +540,21 @@ bool net_connect(const Memory *mem, const Logger *log, Socket sock, const IP_Por
* address that can be specified by calling `net_connect()`, the port is ignored.
*
* Skip all addresses with socktype != type (use type = -1 to get all addresses)
- * To correctly deallocate array memory use `net_freeipport()`
+ * To correctly deallocate array memory use `net_freeipport()`.
+ *
+ * @param ns Network object.
+ * @param mem Memory allocator.
+ * @param node The node parameter identifies the host or service on which to connect.
+ * @param[out] res An array of IP_Port structures will be allocated into this pointer.
+ * @param tox_type The type of socket to use (stream or datagram), only relevant for DNS lookups.
+ * @param dns_enabled If false, DNS resolution is skipped, when passed a hostname, this function will return an error.
*
* @return number of elements in res array.
* @retval 0 if res array empty.
* @retval -1 on error.
*/
non_null()
-int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int tox_type);
+int32_t net_getipport(const Network *ns, const Memory *mem, const char *node, IP_Port **res, int tox_type, bool dns_enabled);
/** Deallocates memory allocated by net_getipport */
non_null(1) nullable(2)
@@ -560,26 +597,32 @@ bool bind_to_port(const Network *ns, Socket sock, Family family, uint16_t port);
* Note that different platforms may return different codes for the same error,
* so you likely shouldn't be checking the value returned by this function
* unless you know what you are doing, you likely just want to use it in
- * combination with `net_new_strerror()` to print the error.
+ * combination with `net_strerror()` to print the error.
*
* return platform-dependent network error code, if any.
*/
int net_error(void);
-/** @brief Get a text explanation for the error code from `net_error()`.
+#define NET_STRERROR_SIZE 256
+
+/** @brief Contains a null terminated formatted error message.
*
- * return NULL on failure.
- * return pointer to a NULL-terminated string describing the error code on
- * success. The returned string must be freed using `net_kill_strerror()`.
+ * This struct should not contain more than at most the 2 fields.
*/
-char *net_new_strerror(int error);
+typedef struct Net_Strerror {
+ char data[NET_STRERROR_SIZE];
+ uint16_t size;
+} Net_Strerror;
-/** @brief Frees the string returned by `net_new_strerror()`.
- * It's valid to pass NULL as the argument, the function does nothing in this
- * case.
+/** @brief Get a text explanation for the error code from `net_error()`.
+ *
+ * @param error The error code to get a string for.
+ * @param buf The struct to store the error message in (usually on stack).
+ *
+ * @return pointer to a NULL-terminated string describing the error code.
*/
-nullable(1)
-void net_kill_strerror(char *strerror);
+non_null()
+char *net_strerror(int error, Net_Strerror *buf);
/** @brief Initialize networking.
* Bind to ip and port.
@@ -603,6 +646,13 @@ Networking_Core *new_networking_no_udp(const Logger *log, const Memory *mem, con
nullable(1)
void kill_networking(Networking_Core *net);
+/** @brief Returns a pointer to the network net_profile object associated with `net`.
+ *
+ * Returns null if `net` is null.
+ */
+non_null()
+const Net_Profile *net_get_net_profile(const Networking_Core *net);
+
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/protocols/Tox/libtox/src/toxcore/onion.c b/protocols/Tox/libtox/src/toxcore/onion.c
index 9fab57af90..f948be52cb 100644
--- a/protocols/Tox/libtox/src/toxcore/onion.c
+++ b/protocols/Tox/libtox/src/toxcore/onion.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -180,7 +180,7 @@ int onion_path_to_nodes(Node_format *nodes, unsigned int num_nodes, const Onion_
* return -1 on failure.
* return length of created packet on success.
*/
-int create_onion_packet(const Random *rng, uint8_t *packet, uint16_t max_packet_length,
+int create_onion_packet(const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length,
const Onion_Path *path, const IP_Port *dest,
const uint8_t *data, uint16_t length)
{
@@ -202,7 +202,7 @@ int create_onion_packet(const Random *rng, uint8_t *packet, uint16_t max_packet_
ipport_pack(step2, &path->ip_port3);
memcpy(step2 + SIZE_IPPORT, path->public_key3, CRYPTO_PUBLIC_KEY_SIZE);
- int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, step1_size,
+ int len = encrypt_data_symmetric(mem, path->shared_key3, nonce, step1, step1_size,
step2 + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
if (len != SIZE_IPPORT + length + CRYPTO_MAC_SIZE) {
@@ -213,7 +213,7 @@ int create_onion_packet(const Random *rng, uint8_t *packet, uint16_t max_packet_
VLA(uint8_t, step3, step3_size);
ipport_pack(step3, &path->ip_port2);
memcpy(step3 + SIZE_IPPORT, path->public_key2, CRYPTO_PUBLIC_KEY_SIZE);
- len = encrypt_data_symmetric(path->shared_key2, nonce, step2, step2_size,
+ len = encrypt_data_symmetric(mem, path->shared_key2, nonce, step2, step2_size,
step3 + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
if (len != SIZE_IPPORT + SEND_BASE + length + CRYPTO_MAC_SIZE) {
@@ -224,7 +224,7 @@ int create_onion_packet(const Random *rng, uint8_t *packet, uint16_t max_packet_
memcpy(packet + 1, nonce, CRYPTO_NONCE_SIZE);
memcpy(packet + 1 + CRYPTO_NONCE_SIZE, path->public_key1, CRYPTO_PUBLIC_KEY_SIZE);
- len = encrypt_data_symmetric(path->shared_key1, nonce, step3, step3_size,
+ len = encrypt_data_symmetric(mem, path->shared_key1, nonce, step3, step3_size,
packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE);
if (len != SIZE_IPPORT + SEND_BASE * 2 + length + CRYPTO_MAC_SIZE) {
@@ -243,7 +243,7 @@ int create_onion_packet(const Random *rng, uint8_t *packet, uint16_t max_packet_
* return -1 on failure.
* return length of created packet on success.
*/
-int create_onion_packet_tcp(const Random *rng, uint8_t *packet, uint16_t max_packet_length,
+int create_onion_packet_tcp(const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length,
const Onion_Path *path, const IP_Port *dest,
const uint8_t *data, uint16_t length)
{
@@ -265,7 +265,7 @@ int create_onion_packet_tcp(const Random *rng, uint8_t *packet, uint16_t max_pac
ipport_pack(step2, &path->ip_port3);
memcpy(step2 + SIZE_IPPORT, path->public_key3, CRYPTO_PUBLIC_KEY_SIZE);
- int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, step1_size,
+ int len = encrypt_data_symmetric(mem, path->shared_key3, nonce, step1, step1_size,
step2 + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
if (len != SIZE_IPPORT + length + CRYPTO_MAC_SIZE) {
@@ -274,7 +274,7 @@ int create_onion_packet_tcp(const Random *rng, uint8_t *packet, uint16_t max_pac
ipport_pack(packet + CRYPTO_NONCE_SIZE, &path->ip_port2);
memcpy(packet + CRYPTO_NONCE_SIZE + SIZE_IPPORT, path->public_key2, CRYPTO_PUBLIC_KEY_SIZE);
- len = encrypt_data_symmetric(path->shared_key2, nonce, step2, step2_size,
+ len = encrypt_data_symmetric(mem, path->shared_key2, nonce, step2, step2_size,
packet + CRYPTO_NONCE_SIZE + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
if (len != SIZE_IPPORT + SEND_BASE + length + CRYPTO_MAC_SIZE) {
@@ -355,7 +355,7 @@ static int handle_send_initial(void *object, const IP_Port *source, const uint8_
}
const int len = decrypt_data_symmetric(
- shared_key, &packet[nonce_start], &packet[ciphertext_start], ciphertext_length, plain);
+ onion->mem, shared_key, &packet[nonce_start], &packet[ciphertext_start], ciphertext_length, plain);
if (len != plaintext_length) {
LOGGER_TRACE(onion->log, "decrypt failed: %d != %d", len, plaintext_length);
@@ -393,7 +393,7 @@ int onion_send_1(const Onion *onion, const uint8_t *plain, uint16_t len, const I
uint16_t data_len = 1 + CRYPTO_NONCE_SIZE + (len - SIZE_IPPORT);
uint8_t *ret_part = data + data_len;
random_nonce(onion->rng, ret_part);
- len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ip_port, SIZE_IPPORT,
+ len = encrypt_data_symmetric(onion->mem, onion->secret_symmetric_key, ret_part, ip_port, SIZE_IPPORT,
ret_part + CRYPTO_NONCE_SIZE);
if (len != SIZE_IPPORT + CRYPTO_MAC_SIZE) {
@@ -436,7 +436,7 @@ static int handle_send_1(void *object, const IP_Port *source, const uint8_t *pac
return 1;
}
- int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
+ int len = decrypt_data_symmetric(onion->mem, shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_1), plain);
if (len != length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_1 + CRYPTO_MAC_SIZE)) {
@@ -459,7 +459,7 @@ static int handle_send_1(void *object, const IP_Port *source, const uint8_t *pac
uint8_t ret_data[RETURN_1 + SIZE_IPPORT];
ipport_pack(ret_data, source);
memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_1), RETURN_1);
- len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data),
+ len = encrypt_data_symmetric(onion->mem, onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data),
ret_part + CRYPTO_NONCE_SIZE);
if (len != RETURN_2 - CRYPTO_NONCE_SIZE) {
@@ -502,7 +502,7 @@ static int handle_send_2(void *object, const IP_Port *source, const uint8_t *pac
return 1;
}
- int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
+ int len = decrypt_data_symmetric(onion->mem, shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_2), plain);
if (len != length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_2 + CRYPTO_MAC_SIZE)) {
@@ -532,7 +532,7 @@ static int handle_send_2(void *object, const IP_Port *source, const uint8_t *pac
uint8_t ret_data[RETURN_2 + SIZE_IPPORT];
ipport_pack(ret_data, source);
memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_2), RETURN_2);
- len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data),
+ len = encrypt_data_symmetric(onion->mem, onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data),
ret_part + CRYPTO_NONCE_SIZE);
if (len != RETURN_3 - CRYPTO_NONCE_SIZE) {
@@ -574,7 +574,7 @@ static int handle_recv_3(void *object, const IP_Port *source, const uint8_t *pac
change_symmetric_key(onion);
uint8_t plain[SIZE_IPPORT + RETURN_2];
- const int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
+ const int len = decrypt_data_symmetric(onion->mem, onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
SIZE_IPPORT + RETURN_2 + CRYPTO_MAC_SIZE, plain);
if ((uint32_t)len != sizeof(plain)) {
@@ -627,7 +627,7 @@ static int handle_recv_2(void *object, const IP_Port *source, const uint8_t *pac
change_symmetric_key(onion);
uint8_t plain[SIZE_IPPORT + RETURN_1];
- const int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
+ const int len = decrypt_data_symmetric(onion->mem, onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
SIZE_IPPORT + RETURN_1 + CRYPTO_MAC_SIZE, plain);
if ((uint32_t)len != sizeof(plain)) {
@@ -679,7 +679,7 @@ static int handle_recv_1(void *object, const IP_Port *source, const uint8_t *pac
change_symmetric_key(onion);
uint8_t plain[SIZE_IPPORT];
- const int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
+ const int len = decrypt_data_symmetric(onion->mem, onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
SIZE_IPPORT + CRYPTO_MAC_SIZE, plain);
if ((uint32_t)len != SIZE_IPPORT) {
diff --git a/protocols/Tox/libtox/src/toxcore/onion.h b/protocols/Tox/libtox/src/toxcore/onion.h
index a5d3554e7b..bbc3f22435 100644
--- a/protocols/Tox/libtox/src/toxcore/onion.h
+++ b/protocols/Tox/libtox/src/toxcore/onion.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -105,7 +105,7 @@ int onion_path_to_nodes(Node_format *nodes, unsigned int num_nodes, const Onion_
* return length of created packet on success.
*/
non_null()
-int create_onion_packet(const Random *rng, uint8_t *packet, uint16_t max_packet_length,
+int create_onion_packet(const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length,
const Onion_Path *path, const IP_Port *dest,
const uint8_t *data, uint16_t length);
@@ -119,7 +119,7 @@ int create_onion_packet(const Random *rng, uint8_t *packet, uint16_t max_packet_
* return length of created packet on success.
*/
non_null()
-int create_onion_packet_tcp(const Random *rng, uint8_t *packet, uint16_t max_packet_length,
+int create_onion_packet_tcp(const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length,
const Onion_Path *path, const IP_Port *dest,
const uint8_t *data, uint16_t length);
diff --git a/protocols/Tox/libtox/src/toxcore/onion_announce.c b/protocols/Tox/libtox/src/toxcore/onion_announce.c
index 593d81aa2c..50e2e00aef 100644
--- a/protocols/Tox/libtox/src/toxcore/onion_announce.c
+++ b/protocols/Tox/libtox/src/toxcore/onion_announce.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -9,7 +9,6 @@
#include "onion_announce.h"
#include <assert.h>
-#include <stdlib.h>
#include <string.h>
#include "DHT.h"
@@ -23,7 +22,9 @@
#include "network.h"
#include "onion.h"
#include "shared_key_cache.h"
+#include "sort.h"
#include "timed_auth.h"
+#include "util.h"
#define PING_ID_TIMEOUT ONION_ANNOUNCE_TIMEOUT
@@ -103,7 +104,7 @@ void onion_announce_entry_set_time(Onion_Announce *onion_a, uint32_t entry, uint
* return -1 on failure.
* return packet length on success.
*/
-int create_announce_request(const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id,
+int create_announce_request(const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id,
const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id,
const uint8_t *data_public_key, uint64_t sendback_data)
{
@@ -122,7 +123,7 @@ int create_announce_request(const Random *rng, uint8_t *packet, uint16_t max_pac
packet[0] = NET_PACKET_ANNOUNCE_REQUEST_OLD;
random_nonce(rng, packet + 1);
- const int len = encrypt_data(dest_client_id, secret_key, packet + 1, plain, sizeof(plain),
+ const int len = encrypt_data(mem, dest_client_id, secret_key, packet + 1, plain, sizeof(plain),
packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE);
if ((uint32_t)len + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE != ONION_ANNOUNCE_REQUEST_MIN_SIZE) {
@@ -146,7 +147,7 @@ int create_announce_request(const Random *rng, uint8_t *packet, uint16_t max_pac
* return -1 on failure.
* return 0 on success.
*/
-int create_data_request(const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *public_key,
+int create_data_request(const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *public_key,
const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length)
{
if (DATA_REQUEST_MIN_SIZE + length > max_packet_length) {
@@ -167,7 +168,7 @@ int create_data_request(const Random *rng, uint8_t *packet, uint16_t max_packet_
memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, random_public_key, CRYPTO_PUBLIC_KEY_SIZE);
- const int len = encrypt_data(encrypt_public_key, random_secret_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, data, length,
+ const int len = encrypt_data(mem, encrypt_public_key, random_secret_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, data, length,
packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE);
if (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + len != DATA_REQUEST_MIN_SIZE +
@@ -193,14 +194,14 @@ int create_data_request(const Random *rng, uint8_t *packet, uint16_t max_packet_
* return 0 on success.
*/
int send_announce_request(
- const Logger *log, const Networking_Core *net, const Random *rng,
+ const Logger *log, const Memory *mem, const Networking_Core *net, const Random *rng,
const Onion_Path *path, const Node_format *dest,
const uint8_t *public_key, const uint8_t *secret_key,
const uint8_t *ping_id, const uint8_t *client_id,
const uint8_t *data_public_key, uint64_t sendback_data)
{
uint8_t request[ONION_ANNOUNCE_REQUEST_MIN_SIZE];
- int len = create_announce_request(rng, request, sizeof(request), dest->public_key, public_key, secret_key, ping_id,
+ int len = create_announce_request(mem, rng, request, sizeof(request), dest->public_key, public_key, secret_key, ping_id,
client_id, data_public_key, sendback_data);
if (len != sizeof(request)) {
@@ -208,7 +209,7 @@ int send_announce_request(
}
uint8_t packet[ONION_MAX_PACKET_SIZE];
- len = create_onion_packet(rng, packet, sizeof(packet), path, &dest->ip_port, request, sizeof(request));
+ len = create_onion_packet(mem, rng, packet, sizeof(packet), path, &dest->ip_port, request, sizeof(request));
if (len == -1) {
return -1;
@@ -238,19 +239,19 @@ int send_announce_request(
* return 0 on success.
*/
int send_data_request(
- const Logger *log, const Networking_Core *net, const Random *rng, const Onion_Path *path, const IP_Port *dest,
+ const Logger *log, const Memory *mem, const Networking_Core *net, const Random *rng, const Onion_Path *path, const IP_Port *dest,
const uint8_t *public_key, const uint8_t *encrypt_public_key, const uint8_t *nonce,
const uint8_t *data, uint16_t length)
{
uint8_t request[ONION_MAX_DATA_SIZE];
- int len = create_data_request(rng, request, sizeof(request), public_key, encrypt_public_key, nonce, data, length);
+ int len = create_data_request(mem, rng, request, sizeof(request), public_key, encrypt_public_key, nonce, data, length);
if (len == -1) {
return -1;
}
uint8_t packet[ONION_MAX_PACKET_SIZE];
- len = create_onion_packet(rng, packet, sizeof(packet), path, dest, request, len);
+ len = create_onion_packet(mem, rng, packet, sizeof(packet), path, dest, request, len);
if (len == -1) {
return -1;
@@ -281,23 +282,17 @@ static int in_entries(const Onion_Announce *onion_a, const uint8_t *public_key)
return -1;
}
-typedef struct Cmp_Data {
+typedef struct Onion_Announce_Entry_Cmp {
+ const Memory *mem;
const Mono_Time *mono_time;
- const uint8_t *base_public_key;
- Onion_Announce_Entry entry;
-} Cmp_Data;
+ const uint8_t *comp_public_key;
+} Onion_Announce_Entry_Cmp;
non_null()
-static int cmp_entry(const void *a, const void *b)
+static int onion_announce_entry_cmp(const Onion_Announce_Entry_Cmp *cmp, const Onion_Announce_Entry *entry1, const Onion_Announce_Entry *entry2)
{
- const Cmp_Data *cmp1 = (const Cmp_Data *)a;
- const Cmp_Data *cmp2 = (const Cmp_Data *)b;
- const Onion_Announce_Entry entry1 = cmp1->entry;
- const Onion_Announce_Entry entry2 = cmp2->entry;
- const uint8_t *cmp_public_key = cmp1->base_public_key;
-
- const bool t1 = mono_time_is_timeout(cmp1->mono_time, entry1.announce_time, ONION_ANNOUNCE_TIMEOUT);
- const bool t2 = mono_time_is_timeout(cmp1->mono_time, entry2.announce_time, ONION_ANNOUNCE_TIMEOUT);
+ const bool t1 = mono_time_is_timeout(cmp->mono_time, entry1->announce_time, ONION_ANNOUNCE_TIMEOUT);
+ const bool t2 = mono_time_is_timeout(cmp->mono_time, entry2->announce_time, ONION_ANNOUNCE_TIMEOUT);
if (t1 && t2) {
return 0;
@@ -311,7 +306,7 @@ static int cmp_entry(const void *a, const void *b)
return 1;
}
- const int closest = id_closest(cmp_public_key, entry1.public_key, entry2.public_key);
+ const int closest = id_closest(cmp->comp_public_key, entry1->public_key, entry2->public_key);
if (closest == 1) {
return 1;
@@ -325,31 +320,80 @@ static int cmp_entry(const void *a, const void *b)
}
non_null()
-static void sort_onion_announce_list(const Memory *mem, const Mono_Time *mono_time,
- Onion_Announce_Entry *list, unsigned int length,
- const uint8_t *comp_public_key)
+static bool onion_announce_entry_less_handler(const void *object, const void *a, const void *b)
{
- // Pass comp_public_key to qsort with each Client_data entry, so the
- // comparison function can use it as the base of comparison.
- Cmp_Data *cmp_list = (Cmp_Data *)mem_valloc(mem, length, sizeof(Cmp_Data));
+ const Onion_Announce_Entry_Cmp *cmp = (const Onion_Announce_Entry_Cmp *)object;
+ const Onion_Announce_Entry *entry1 = (const Onion_Announce_Entry *)a;
+ const Onion_Announce_Entry *entry2 = (const Onion_Announce_Entry *)b;
- if (cmp_list == nullptr) {
- return;
- }
+ return onion_announce_entry_cmp(cmp, entry1, entry2) < 0;
+}
- for (uint32_t i = 0; i < length; ++i) {
- cmp_list[i].mono_time = mono_time;
- cmp_list[i].base_public_key = comp_public_key;
- cmp_list[i].entry = list[i];
- }
+non_null()
+static const void *onion_announce_entry_get_handler(const void *arr, uint32_t index)
+{
+ const Onion_Announce_Entry *entries = (const Onion_Announce_Entry *)arr;
+ return &entries[index];
+}
- qsort(cmp_list, length, sizeof(Cmp_Data), cmp_entry);
+non_null()
+static void onion_announce_entry_set_handler(void *arr, uint32_t index, const void *val)
+{
+ Onion_Announce_Entry *entries = (Onion_Announce_Entry *)arr;
+ const Onion_Announce_Entry *entry = (const Onion_Announce_Entry *)val;
+ entries[index] = *entry;
+}
- for (uint32_t i = 0; i < length; ++i) {
- list[i] = cmp_list[i].entry;
+non_null()
+static void *onion_announce_entry_subarr_handler(void *arr, uint32_t index, uint32_t size)
+{
+ Onion_Announce_Entry *entries = (Onion_Announce_Entry *)arr;
+ return &entries[index];
+}
+
+non_null()
+static void *onion_announce_entry_alloc_handler(const void *object, uint32_t size)
+{
+ const Onion_Announce_Entry_Cmp *cmp = (const Onion_Announce_Entry_Cmp *)object;
+ Onion_Announce_Entry *tmp = (Onion_Announce_Entry *)mem_valloc(cmp->mem, size, sizeof(Onion_Announce_Entry));
+
+ if (tmp == nullptr) {
+ return nullptr;
}
- mem_delete(mem, cmp_list);
+ return tmp;
+}
+
+non_null()
+static void onion_announce_entry_delete_handler(const void *object, void *arr, uint32_t size)
+{
+ const Onion_Announce_Entry_Cmp *cmp = (const Onion_Announce_Entry_Cmp *)object;
+ mem_delete(cmp->mem, arr);
+}
+
+static const Sort_Funcs onion_announce_entry_cmp_funcs = {
+ onion_announce_entry_less_handler,
+ onion_announce_entry_get_handler,
+ onion_announce_entry_set_handler,
+ onion_announce_entry_subarr_handler,
+ onion_announce_entry_alloc_handler,
+ onion_announce_entry_delete_handler,
+};
+
+non_null()
+static void sort_onion_announce_list(const Memory *mem, const Mono_Time *mono_time,
+ Onion_Announce_Entry *list, unsigned int length,
+ const uint8_t *comp_public_key)
+{
+ // Pass comp_public_key to sort with each Onion_Announce_Entry entry, so the
+ // comparison function can use it as the base of comparison.
+ const Onion_Announce_Entry_Cmp cmp = {
+ mem,
+ mono_time,
+ comp_public_key,
+ };
+
+ merge_sort(list, length, &cmp, &onion_announce_entry_cmp_funcs);
}
/** @brief add entry to entries list
@@ -455,7 +499,7 @@ static int handle_announce_request_common(
return 1;
}
- const int decrypted_len = decrypt_data_symmetric(shared_key, packet + 1,
+ const int decrypted_len = decrypt_data_symmetric(onion_a->mem, shared_key, packet + 1,
packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, plain_size + CRYPTO_MAC_SIZE, plain);
if ((uint32_t)decrypted_len != plain_size) {
@@ -463,11 +507,17 @@ static int handle_announce_request_common(
return 1;
}
- const uint16_t ping_id_data_len = CRYPTO_PUBLIC_KEY_SIZE + sizeof(*source);
- uint8_t ping_id_data[CRYPTO_PUBLIC_KEY_SIZE + sizeof(*source)];
+ const uint16_t ping_id_data_len = CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT;
+ uint8_t ping_id_data[CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT];
memcpy(ping_id_data, packet_public_key, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(ping_id_data + CRYPTO_PUBLIC_KEY_SIZE, source, sizeof(*source));
-
+ const int packed_len = pack_ip_port(onion_a->log, &ping_id_data[CRYPTO_PUBLIC_KEY_SIZE], SIZE_IPPORT, source);
+ if (packed_len < 0) {
+ LOGGER_ERROR(onion_a->log, "failed to pack IP/Port");
+ mem_delete(onion_a->mem, plain);
+ return 1;
+ }
+ assert(packed_len <= SIZE_IPPORT);
+ memzero(&ping_id_data[CRYPTO_PUBLIC_KEY_SIZE + packed_len], SIZE_IPPORT - packed_len);
const uint8_t *data_public_key = plain + ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE;
int index;
@@ -510,7 +560,7 @@ static int handle_announce_request_common(
int nodes_length = 0;
if (num_nodes != 0) {
- nodes_length = pack_nodes(onion_a->log, response + nodes_offset, sizeof(nodes_list), nodes_list,
+ nodes_length = pack_nodes(onion_a->log, &response[nodes_offset], num_nodes * PACKED_NODE_SIZE_IP6, nodes_list,
(uint16_t)num_nodes);
if (nodes_length <= 0) {
@@ -529,7 +579,7 @@ static int handle_announce_request_common(
const int extra_size = pack_extra_data_callback == nullptr ? 0
: pack_extra_data_callback(onion_a->extra_data_object,
- onion_a->log, onion_a->mono_time, num_nodes,
+ onion_a->log, onion_a->mem, onion_a->mono_time, num_nodes,
plain + ONION_MINIMAL_SIZE, length - ANNOUNCE_REQUEST_MIN_SIZE_RECV,
response, response_size, offset);
@@ -542,7 +592,7 @@ static int handle_announce_request_common(
offset += extra_size;
uint8_t data[ONION_ANNOUNCE_RESPONSE_MAX_SIZE];
- const int len = encrypt_data_symmetric(shared_key, nonce, response, offset,
+ const int len = encrypt_data_symmetric(onion_a->mem, shared_key, nonce, response, offset,
data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE);
if (len != offset + CRYPTO_MAC_SIZE) {
diff --git a/protocols/Tox/libtox/src/toxcore/onion_announce.h b/protocols/Tox/libtox/src/toxcore/onion_announce.h
index 1158093170..d8834395c0 100644
--- a/protocols/Tox/libtox/src/toxcore/onion_announce.h
+++ b/protocols/Tox/libtox/src/toxcore/onion_announce.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -65,7 +65,7 @@ void onion_announce_entry_set_time(Onion_Announce *onion_a, uint32_t entry, uint
* return packet length on success.
*/
non_null()
-int create_announce_request(const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id,
+int create_announce_request(const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id,
const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id,
const uint8_t *data_public_key, uint64_t sendback_data);
@@ -82,7 +82,7 @@ int create_announce_request(const Random *rng, uint8_t *packet, uint16_t max_pac
* return 0 on success.
*/
non_null()
-int create_data_request(const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *public_key,
+int create_data_request(const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *public_key,
const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length);
/** @brief Create and send an onion announce request packet.
@@ -101,7 +101,7 @@ int create_data_request(const Random *rng, uint8_t *packet, uint16_t max_packet_
*/
non_null()
int send_announce_request(
- const Logger *log, const Networking_Core *net, const Random *rng,
+ const Logger *log, const Memory *mem, const Networking_Core *net, const Random *rng,
const Onion_Path *path, const Node_format *dest,
const uint8_t *public_key, const uint8_t *secret_key,
const uint8_t *ping_id, const uint8_t *client_id,
@@ -125,11 +125,11 @@ int send_announce_request(
*/
non_null()
int send_data_request(
- const Logger *log, const Networking_Core *net, const Random *rng, const Onion_Path *path, const IP_Port *dest,
+ const Logger *log, const Memory *mem, const Networking_Core *net, const Random *rng, const Onion_Path *path, const IP_Port *dest,
const uint8_t *public_key, const uint8_t *encrypt_public_key, const uint8_t *nonce,
const uint8_t *data, uint16_t length);
-typedef int pack_extra_data_cb(void *object, const Logger *logger, const Mono_Time *mono_time,
+typedef int pack_extra_data_cb(void *object, const Logger *logger, const Memory *mem, const Mono_Time *mono_time,
uint8_t num_nodes, uint8_t *plain, uint16_t plain_size,
uint8_t *response, uint16_t response_size, uint16_t offset);
diff --git a/protocols/Tox/libtox/src/toxcore/onion_client.c b/protocols/Tox/libtox/src/toxcore/onion_client.c
index 9b0ac96102..e802d70298 100644
--- a/protocols/Tox/libtox/src/toxcore/onion_client.c
+++ b/protocols/Tox/libtox/src/toxcore/onion_client.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -10,7 +10,6 @@
#include "onion_client.h"
#include <assert.h>
-#include <stdlib.h>
#include <string.h>
#include "DHT.h"
@@ -29,6 +28,7 @@
#include "onion.h"
#include "onion_announce.h"
#include "ping_array.h"
+#include "sort.h"
#include "timed_auth.h"
#include "util.h"
@@ -470,6 +470,7 @@ static int random_path(const Onion_Client *onion_c, Onion_Client_Paths *onion_pa
onion_paths->paths[pathnum].path_num = path_num;
} else {
+ assert(0 <= n && n < NUMBER_ONION_PATHS);
pathnum = n;
}
}
@@ -528,7 +529,7 @@ static int send_onion_packet_tcp_udp(const Onion_Client *onion_c, const Onion_Pa
{
if (net_family_is_ipv4(path->ip_port1.ip.family) || net_family_is_ipv6(path->ip_port1.ip.family)) {
uint8_t packet[ONION_MAX_PACKET_SIZE];
- const int len = create_onion_packet(onion_c->rng, packet, sizeof(packet), path, dest, data, length);
+ const int len = create_onion_packet(onion_c->mem, onion_c->rng, packet, sizeof(packet), path, dest, data, length);
if (len == -1) {
return -1;
@@ -545,7 +546,7 @@ static int send_onion_packet_tcp_udp(const Onion_Client *onion_c, const Onion_Pa
if (ip_port_to_tcp_connections_number(&path->ip_port1, &tcp_connections_number)) {
uint8_t packet[ONION_MAX_PACKET_SIZE];
- const int len = create_onion_packet_tcp(onion_c->rng, packet, sizeof(packet), path, dest, data, length);
+ const int len = create_onion_packet_tcp(onion_c->mem, onion_c->rng, packet, sizeof(packet), path, dest, data, length);
if (len == -1) {
return -1;
@@ -576,11 +577,17 @@ non_null()
static int new_sendback(Onion_Client *onion_c, uint32_t num, const uint8_t *public_key, const IP_Port *ip_port,
uint32_t path_num, uint64_t *sendback)
{
- uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port) + sizeof(uint32_t)];
+ uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT + sizeof(uint32_t)];
memcpy(data, &num, sizeof(uint32_t));
- memcpy(data + sizeof(uint32_t), public_key, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, ip_port, sizeof(IP_Port));
- memcpy(data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port), &path_num, sizeof(uint32_t));
+ memcpy(&data[sizeof(uint32_t)], public_key, CRYPTO_PUBLIC_KEY_SIZE);
+ const int packed_len = pack_ip_port(onion_c->logger, &data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE], SIZE_IPPORT, ip_port);
+ if (packed_len < 0) {
+ LOGGER_ERROR(onion_c->logger, "failed to pack IP/port");
+ return -1;
+ }
+ assert(packed_len <= SIZE_IPPORT);
+ memzero(&data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + packed_len], SIZE_IPPORT - packed_len);
+ memcpy(&data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT], &path_num, sizeof(uint32_t));
*sendback = ping_array_add(onion_c->announce_ping_array, onion_c->mono_time, onion_c->rng, data, sizeof(data));
if (*sendback == 0) {
@@ -607,15 +614,15 @@ static uint32_t check_sendback(Onion_Client *onion_c, const uint8_t *sendback, u
{
uint64_t sback;
memcpy(&sback, sendback, sizeof(uint64_t));
- uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port) + sizeof(uint32_t)];
+ uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT + sizeof(uint32_t)];
if (ping_array_check(onion_c->announce_ping_array, onion_c->mono_time, data, sizeof(data), sback) != sizeof(data)) {
return -1;
}
memcpy(ret_pubkey, data + sizeof(uint32_t), CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(ret_ip_port, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, sizeof(IP_Port));
- memcpy(path_num, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port), sizeof(uint32_t));
+ unpack_ip_port(ret_ip_port, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, SIZE_IPPORT, false);
+ memcpy(path_num, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT, sizeof(uint32_t));
uint32_t num;
memcpy(&num, data, sizeof(uint32_t));
@@ -661,7 +668,7 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, con
if (num == 0) {
len = create_announce_request(
- onion_c->rng, request, sizeof(request), dest_pubkey, nc_get_self_public_key(onion_c->c),
+ onion_c->mem, onion_c->rng, request, sizeof(request), dest_pubkey, nc_get_self_public_key(onion_c->c),
nc_get_self_secret_key(onion_c->c), ping_id, nc_get_self_public_key(onion_c->c),
onion_c->temp_public_key, sendback);
} else {
@@ -669,14 +676,14 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, con
if (onion_friend->gc_data_length == 0) { // contact is a friend
len = create_announce_request(
- onion_c->rng, request, sizeof(request), dest_pubkey, onion_friend->temp_public_key,
+ onion_c->mem, onion_c->rng, request, sizeof(request), dest_pubkey, onion_friend->temp_public_key,
onion_friend->temp_secret_key, ping_id, onion_friend->real_public_key,
zero_ping_id, sendback);
} else { // contact is a gc
onion_friend->is_groupchat = true;
len = create_gca_announce_request(
- onion_c->rng, request, sizeof(request), dest_pubkey, onion_friend->temp_public_key,
+ onion_c->mem, onion_c->rng, request, sizeof(request), dest_pubkey, onion_friend->temp_public_key,
onion_friend->temp_secret_key, ping_id, onion_friend->real_public_key,
zero_ping_id, sendback, onion_friend->gc_data,
onion_friend->gc_data_length);
@@ -694,23 +701,17 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, con
return send_onion_packet_tcp_udp(onion_c, &path, dest, request, len);
}
-typedef struct Onion_Client_Cmp_Data {
+typedef struct Onion_Node_Cmp {
+ const Memory *mem;
const Mono_Time *mono_time;
- const uint8_t *base_public_key;
- Onion_Node entry;
-} Onion_Client_Cmp_Data;
+ const uint8_t *comp_public_key;
+} Onion_Node_Cmp;
non_null()
-static int onion_client_cmp_entry(const void *a, const void *b)
+static int onion_node_cmp(const Onion_Node_Cmp *cmp, const Onion_Node *entry1, const Onion_Node *entry2)
{
- const Onion_Client_Cmp_Data *cmp1 = (const Onion_Client_Cmp_Data *)a;
- const Onion_Client_Cmp_Data *cmp2 = (const Onion_Client_Cmp_Data *)b;
- const Onion_Node entry1 = cmp1->entry;
- const Onion_Node entry2 = cmp2->entry;
- const uint8_t *cmp_public_key = cmp1->base_public_key;
-
- const bool t1 = onion_node_timed_out(&entry1, cmp1->mono_time);
- const bool t2 = onion_node_timed_out(&entry2, cmp2->mono_time);
+ const bool t1 = onion_node_timed_out(entry1, cmp->mono_time);
+ const bool t2 = onion_node_timed_out(entry2, cmp->mono_time);
if (t1 && t2) {
return 0;
@@ -724,7 +725,7 @@ static int onion_client_cmp_entry(const void *a, const void *b)
return 1;
}
- const int closest = id_closest(cmp_public_key, entry1.public_key, entry2.public_key);
+ const int closest = id_closest(cmp->comp_public_key, entry1->public_key, entry2->public_key);
if (closest == 1) {
return 1;
@@ -738,30 +739,79 @@ static int onion_client_cmp_entry(const void *a, const void *b)
}
non_null()
-static void sort_onion_node_list(const Memory *mem, const Mono_Time *mono_time,
- Onion_Node *list, unsigned int length, const uint8_t *comp_public_key)
+static bool onion_node_less_handler(const void *object, const void *a, const void *b)
{
- // Pass comp_public_key to qsort with each Client_data entry, so the
- // comparison function can use it as the base of comparison.
- Onion_Client_Cmp_Data *cmp_list = (Onion_Client_Cmp_Data *)mem_valloc(mem, length, sizeof(Onion_Client_Cmp_Data));
+ const Onion_Node_Cmp *cmp = (const Onion_Node_Cmp *)object;
+ const Onion_Node *entry1 = (const Onion_Node *)a;
+ const Onion_Node *entry2 = (const Onion_Node *)b;
- if (cmp_list == nullptr) {
- return;
- }
+ return onion_node_cmp(cmp, entry1, entry2) < 0;
+}
- for (uint32_t i = 0; i < length; ++i) {
- cmp_list[i].mono_time = mono_time;
- cmp_list[i].base_public_key = comp_public_key;
- cmp_list[i].entry = list[i];
- }
+non_null()
+static const void *onion_node_get_handler(const void *arr, uint32_t index)
+{
+ const Onion_Node *entries = (const Onion_Node *)arr;
+ return &entries[index];
+}
- qsort(cmp_list, length, sizeof(Onion_Client_Cmp_Data), onion_client_cmp_entry);
+non_null()
+static void onion_node_set_handler(void *arr, uint32_t index, const void *val)
+{
+ Onion_Node *entries = (Onion_Node *)arr;
+ const Onion_Node *entry = (const Onion_Node *)val;
+ entries[index] = *entry;
+}
- for (uint32_t i = 0; i < length; ++i) {
- list[i] = cmp_list[i].entry;
+non_null()
+static void *onion_node_subarr_handler(void *arr, uint32_t index, uint32_t size)
+{
+ Onion_Node *entries = (Onion_Node *)arr;
+ return &entries[index];
+}
+
+non_null()
+static void *onion_node_alloc_handler(const void *object, uint32_t size)
+{
+ const Onion_Node_Cmp *cmp = (const Onion_Node_Cmp *)object;
+ Onion_Node *tmp = (Onion_Node *)mem_valloc(cmp->mem, size, sizeof(Onion_Node));
+
+ if (tmp == nullptr) {
+ return nullptr;
}
- mem_delete(mem, cmp_list);
+ return tmp;
+}
+
+non_null()
+static void onion_node_delete_handler(const void *object, void *arr, uint32_t size)
+{
+ const Onion_Node_Cmp *cmp = (const Onion_Node_Cmp *)object;
+ mem_delete(cmp->mem, arr);
+}
+
+static const Sort_Funcs onion_node_cmp_funcs = {
+ onion_node_less_handler,
+ onion_node_get_handler,
+ onion_node_set_handler,
+ onion_node_subarr_handler,
+ onion_node_alloc_handler,
+ onion_node_delete_handler,
+};
+
+non_null()
+static void sort_onion_node_list(const Memory *mem, const Mono_Time *mono_time,
+ Onion_Node *list, unsigned int length, const uint8_t *comp_public_key)
+{
+ // Pass comp_public_key to sort with each Onion_Node entry, so the
+ // comparison function can use it as the base of comparison.
+ const Onion_Node_Cmp cmp = {
+ mem,
+ mono_time,
+ comp_public_key,
+ };
+
+ merge_sort(list, length, &cmp, &onion_node_cmp_funcs);
}
non_null()
@@ -955,14 +1005,14 @@ static int handle_announce_response(void *object, const IP_Port *source, const u
}
uint8_t plain[1 + ONION_PING_ID_SIZE + ONION_ANNOUNCE_RESPONSE_MAX_SIZE - ONION_ANNOUNCE_RESPONSE_MIN_SIZE];
- const int plain_size = 1 + ONION_PING_ID_SIZE + length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE;
+ const uint32_t plain_size = 1 + ONION_PING_ID_SIZE + length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE;
int len;
const uint16_t nonce_start = 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH;
const uint16_t ciphertext_start = nonce_start + CRYPTO_NONCE_SIZE;
const uint16_t ciphertext_size = length - ciphertext_start;
if (num == 0) {
- len = decrypt_data(public_key, nc_get_self_secret_key(onion_c->c),
+ len = decrypt_data(onion_c->mem, public_key, nc_get_self_secret_key(onion_c->c),
&packet[nonce_start], &packet[ciphertext_start], ciphertext_size, plain);
} else {
if (!onion_c->friends_list[num - 1].is_valid) {
@@ -970,7 +1020,7 @@ static int handle_announce_response(void *object, const IP_Port *source, const u
return 1;
}
- len = decrypt_data(public_key, onion_c->friends_list[num - 1].temp_secret_key,
+ len = decrypt_data(onion_c->mem, public_key, onion_c->friends_list[num - 1].temp_secret_key,
&packet[nonce_start], &packet[ciphertext_start], ciphertext_size, plain);
}
@@ -1066,7 +1116,7 @@ static int handle_announce_response_old(void *object, const IP_Port *source, con
const uint16_t ciphertext_size = length - ciphertext_start;
if (num == 0) {
- len = decrypt_data(public_key, nc_get_self_secret_key(onion_c->c),
+ len = decrypt_data(onion_c->mem, public_key, nc_get_self_secret_key(onion_c->c),
&packet[nonce_start], &packet[ciphertext_start], ciphertext_size, plain);
} else {
if (!onion_c->friends_list[num - 1].is_valid) {
@@ -1074,7 +1124,7 @@ static int handle_announce_response_old(void *object, const IP_Port *source, con
return 1;
}
- len = decrypt_data(public_key, onion_c->friends_list[num - 1].temp_secret_key,
+ len = decrypt_data(onion_c->mem, public_key, onion_c->friends_list[num - 1].temp_secret_key,
&packet[nonce_start], &packet[ciphertext_start], ciphertext_size, plain);
}
@@ -1136,7 +1186,7 @@ static int handle_data_response(void *object, const IP_Port *source, const uint8
const uint16_t temp_plain_size = length - ONION_DATA_RESPONSE_MIN_SIZE;
VLA(uint8_t, temp_plain, temp_plain_size);
- int len = decrypt_data(packet + 1 + CRYPTO_NONCE_SIZE, onion_c->temp_secret_key, packet + 1,
+ int len = decrypt_data(onion_c->mem, packet + 1 + CRYPTO_NONCE_SIZE, onion_c->temp_secret_key, packet + 1,
packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE), temp_plain);
@@ -1146,7 +1196,7 @@ static int handle_data_response(void *object, const IP_Port *source, const uint8
const uint16_t plain_size = temp_plain_size - DATA_IN_RESPONSE_MIN_SIZE;
VLA(uint8_t, plain, plain_size);
- len = decrypt_data(temp_plain, nc_get_self_secret_key(onion_c->c),
+ len = decrypt_data(onion_c->mem, temp_plain, nc_get_self_secret_key(onion_c->c),
packet + 1, temp_plain + CRYPTO_PUBLIC_KEY_SIZE,
temp_plain_size - CRYPTO_PUBLIC_KEY_SIZE, plain);
@@ -1215,7 +1265,7 @@ static int handle_dhtpk_announce(void *object, const uint8_t *source_pubkey, con
const Family family = nodes[i].ip_port.ip.family;
if (net_family_is_ipv4(family) || net_family_is_ipv6(family)) {
- dht_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].public_key, onion_c->friends_list[friend_num].dht_public_key);
+ dht_send_nodes_request(onion_c->dht, &nodes[i].ip_port, nodes[i].public_key, onion_c->friends_list[friend_num].dht_public_key);
} else if (net_family_is_tcp_ipv4(family) || net_family_is_tcp_ipv6(family)) {
if (onion_c->friends_list[friend_num].tcp_relay_node_callback != nullptr) {
void *obj = onion_c->friends_list[friend_num].tcp_relay_node_callback_object;
@@ -1305,7 +1355,7 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data,
const uint16_t packet_size = DATA_IN_RESPONSE_MIN_SIZE + length;
VLA(uint8_t, packet, packet_size);
memcpy(packet, nc_get_self_public_key(onion_c->c), CRYPTO_PUBLIC_KEY_SIZE);
- int len = encrypt_data(onion_c->friends_list[friend_num].real_public_key,
+ int len = encrypt_data(onion_c->mem, onion_c->friends_list[friend_num].real_public_key,
nc_get_self_secret_key(onion_c->c), nonce, data,
length, packet + CRYPTO_PUBLIC_KEY_SIZE);
@@ -1324,7 +1374,7 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data,
uint8_t o_packet[ONION_MAX_PACKET_SIZE];
len = create_data_request(
- onion_c->rng, o_packet, sizeof(o_packet), onion_c->friends_list[friend_num].real_public_key,
+ onion_c->mem, onion_c->rng, o_packet, sizeof(o_packet), onion_c->friends_list[friend_num].real_public_key,
node_list[good_nodes[i]].data_public_key, nonce, packet, packet_size);
if (len == -1) {
@@ -1364,7 +1414,7 @@ static int send_dht_dhtpk(const Onion_Client *onion_c, int friend_num, const uin
VLA(uint8_t, temp, temp_size);
memcpy(temp, nc_get_self_public_key(onion_c->c), CRYPTO_PUBLIC_KEY_SIZE);
memcpy(temp + CRYPTO_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE);
- int len = encrypt_data(onion_c->friends_list[friend_num].real_public_key,
+ int len = encrypt_data(onion_c->mem, onion_c->friends_list[friend_num].real_public_key,
nc_get_self_secret_key(onion_c->c), nonce, data,
length, temp + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
@@ -1374,7 +1424,7 @@ static int send_dht_dhtpk(const Onion_Client *onion_c, int friend_num, const uin
uint8_t packet_data[MAX_CRYPTO_REQUEST_SIZE];
len = create_request(
- onion_c->rng, dht_get_self_public_key(onion_c->dht), dht_get_self_secret_key(onion_c->dht), packet_data,
+ onion_c->mem, onion_c->rng, dht_get_self_public_key(onion_c->dht), dht_get_self_secret_key(onion_c->dht), packet_data,
onion_c->friends_list[friend_num].dht_public_key, temp, temp_size, CRYPTO_PACKET_DHTPK);
assert(len <= UINT16_MAX);
const Packet packet = {packet_data, (uint16_t)len};
@@ -1401,7 +1451,7 @@ static int handle_dht_dhtpk(void *object, const IP_Port *source, const uint8_t *
}
uint8_t plain[DHTPK_DATA_MAX_LENGTH];
- const int len = decrypt_data(packet, nc_get_self_secret_key(onion_c->c),
+ const int len = decrypt_data(onion_c->mem, packet, nc_get_self_secret_key(onion_c->c),
packet + CRYPTO_PUBLIC_KEY_SIZE,
packet + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
length - (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE), plain);
diff --git a/protocols/Tox/libtox/src/toxcore/onion_client.h b/protocols/Tox/libtox/src/toxcore/onion_client.h
index 61e4e6fd1c..5999f15c65 100644
--- a/protocols/Tox/libtox/src/toxcore/onion_client.h
+++ b/protocols/Tox/libtox/src/toxcore/onion_client.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -183,6 +183,8 @@ non_null()
unsigned int onion_getfriend_dht_pubkey(const Onion_Client *onion_c, int friend_num, uint8_t *dht_key);
#define ONION_DATA_IN_RESPONSE_MIN_SIZE (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE)
+
+// TODO(Jfreegman): This is not the correct value; data this large will be dropped by the onion client.
#define ONION_CLIENT_MAX_DATA_SIZE (MAX_DATA_REQUEST_SIZE - ONION_DATA_IN_RESPONSE_MIN_SIZE)
/** @brief Send data of length length to friendnum.
diff --git a/protocols/Tox/libtox/src/toxcore/ping.c b/protocols/Tox/libtox/src/toxcore/ping.c
index 303c418cea..bfb3c92cd3 100644
--- a/protocols/Tox/libtox/src/toxcore/ping.c
+++ b/protocols/Tox/libtox/src/toxcore/ping.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
* Copyright © 2013 plutooo
*/
@@ -31,6 +31,7 @@
struct Ping {
const Mono_Time *mono_time;
const Random *rng;
+ const Memory *mem;
DHT *dht;
Ping_Array *ping_array;
@@ -72,7 +73,7 @@ void ping_send_request(Ping *ping, const IP_Port *ipp, const uint8_t *public_key
pk_copy(pk + 1, dht_get_self_public_key(ping->dht)); // Our pubkey
random_nonce(ping->rng, pk + 1 + CRYPTO_PUBLIC_KEY_SIZE); // Generate new nonce
- rc = encrypt_data_symmetric(shared_key,
+ rc = encrypt_data_symmetric(ping->mem, shared_key,
pk + 1 + CRYPTO_PUBLIC_KEY_SIZE,
ping_plain, sizeof(ping_plain),
pk + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
@@ -104,7 +105,7 @@ static int ping_send_response(const Ping *ping, const IP_Port *ipp, const uint8_
random_nonce(ping->rng, pk + 1 + CRYPTO_PUBLIC_KEY_SIZE); // Generate new nonce
// Encrypt ping_id using recipient privkey
- const int rc = encrypt_data_symmetric(shared_encryption_key,
+ const int rc = encrypt_data_symmetric(ping->mem, shared_encryption_key,
pk + 1 + CRYPTO_PUBLIC_KEY_SIZE,
ping_plain, sizeof(ping_plain),
pk + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
@@ -137,7 +138,7 @@ static int handle_ping_request(void *object, const IP_Port *source, const uint8_
uint8_t ping_plain[PING_PLAIN_SIZE];
// Decrypt ping_id
- const int rc = decrypt_data_symmetric(shared_key,
+ const int rc = decrypt_data_symmetric(ping->mem, shared_key,
packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
PING_PLAIN_SIZE + CRYPTO_MAC_SIZE,
@@ -182,7 +183,7 @@ static int handle_ping_response(void *object, const IP_Port *source, const uint8
uint8_t ping_plain[PING_PLAIN_SIZE];
// Decrypt ping_id
- rc = decrypt_data_symmetric(shared_key,
+ rc = decrypt_data_symmetric(ping->mem, shared_key,
packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
PING_PLAIN_SIZE + CRYPTO_MAC_SIZE,
@@ -348,6 +349,7 @@ Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Random *rng,
ping->mono_time = mono_time;
ping->rng = rng;
+ ping->mem = mem;
ping->dht = dht;
networking_registerhandler(dht_get_net(ping->dht), NET_PACKET_PING_REQUEST, &handle_ping_request, dht);
networking_registerhandler(dht_get_net(ping->dht), NET_PACKET_PING_RESPONSE, &handle_ping_response, dht);
diff --git a/protocols/Tox/libtox/src/toxcore/ping.h b/protocols/Tox/libtox/src/toxcore/ping.h
index b0339ec75d..98ae7bd754 100644
--- a/protocols/Tox/libtox/src/toxcore/ping.h
+++ b/protocols/Tox/libtox/src/toxcore/ping.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
* Copyright © 2013 plutooo
*/
diff --git a/protocols/Tox/libtox/src/toxcore/ping_array.c b/protocols/Tox/libtox/src/toxcore/ping_array.c
index c40215ea47..91b9064ecc 100644
--- a/protocols/Tox/libtox/src/toxcore/ping_array.c
+++ b/protocols/Tox/libtox/src/toxcore/ping_array.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2014 Tox project.
*/
diff --git a/protocols/Tox/libtox/src/toxcore/ping_array.h b/protocols/Tox/libtox/src/toxcore/ping_array.h
index 3e50e66876..2d1f9f5cc2 100644
--- a/protocols/Tox/libtox/src/toxcore/ping_array.h
+++ b/protocols/Tox/libtox/src/toxcore/ping_array.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
diff --git a/protocols/Tox/libtox/src/toxcore/shared_key_cache.c b/protocols/Tox/libtox/src/toxcore/shared_key_cache.c
index 80d74aecb4..64906b569c 100644
--- a/protocols/Tox/libtox/src/toxcore/shared_key_cache.c
+++ b/protocols/Tox/libtox/src/toxcore/shared_key_cache.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2022-2025 The TokTok team.
*/
#include "shared_key_cache.h"
diff --git a/protocols/Tox/libtox/src/toxcore/shared_key_cache.h b/protocols/Tox/libtox/src/toxcore/shared_key_cache.h
index f6e84c3130..69295325d6 100644
--- a/protocols/Tox/libtox/src/toxcore/shared_key_cache.h
+++ b/protocols/Tox/libtox/src/toxcore/shared_key_cache.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2022-2025 The TokTok team.
*/
#ifndef C_TOXCORE_TOXCORE_SHARED_KEY_CACHE_H
diff --git a/protocols/Tox/libtox/src/toxcore/sort.c b/protocols/Tox/libtox/src/toxcore/sort.c
new file mode 100644
index 0000000000..9bd83d6171
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/sort.c
@@ -0,0 +1,182 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2023-2025 The TokTok team.
+ */
+
+#include "sort.h"
+
+#include <assert.h>
+
+#include "attributes.h"
+#include "ccompat.h"
+#include "util.h"
+
+/**
+ * @brief Threshold for when to switch to insertion sort.
+ *
+ * This is a trade-off between the complexity of insertion sort and the
+ * overhead of merge sort. The threshold is chosen to be the smallest value
+ * that gives a measurable speedup for insertion sort over merge sort. This is
+ * based on measurements done in sort_bench.cc. Starting from 32 elements,
+ * merge sort is faster than insertion sort in all our tests (both unsorted
+ * and mostly-sorted).
+ *
+ * Toxcore has a lot of small arrays it wants to sort, so this optimisation
+ * makes sense.
+ */
+#define SMALL_ARRAY_THRESHOLD 16
+
+non_null()
+static void merge_sort_merge_back(
+ void *arr,
+ const void *l_arr, uint32_t l_arr_size,
+ const void *r_arr, uint32_t r_arr_size,
+ uint32_t left_start,
+ const void *object, const Sort_Funcs *funcs)
+{
+ uint32_t li = 0;
+ uint32_t ri = 0;
+ uint32_t k = left_start;
+
+ while (li < l_arr_size && ri < r_arr_size) {
+ const void *l = funcs->get_callback(l_arr, li);
+ const void *r = funcs->get_callback(r_arr, ri);
+ // !(r < l) <=> (r >= l) <=> (l <= r)
+ if (!funcs->less_callback(object, r, l)) {
+ funcs->set_callback(arr, k, l);
+ ++li;
+ } else {
+ funcs->set_callback(arr, k, r);
+ ++ri;
+ }
+ ++k;
+ }
+
+ /* Copy the remaining elements of `l_arr[]`, if there are any. */
+ while (li < l_arr_size) {
+ funcs->set_callback(arr, k, funcs->get_callback(l_arr, li));
+ ++li;
+ ++k;
+ }
+
+ /* Copy the remaining elements of `r_arr[]`, if there are any. */
+ while (ri < r_arr_size) {
+ funcs->set_callback(arr, k, funcs->get_callback(r_arr, ri));
+ ++ri;
+ ++k;
+ }
+}
+
+/** Function to merge the two haves `arr[left_start..mid]` and `arr[mid+1..right_end]` of array `arr[]`. */
+non_null()
+static void merge_sort_merge(
+ void *arr, uint32_t left_start, uint32_t mid, uint32_t right_end, void *tmp,
+ const void *object, const Sort_Funcs *funcs)
+{
+ const uint32_t l_arr_size = mid - left_start + 1;
+ const uint32_t r_arr_size = right_end - mid;
+
+ /* Temporary arrays, using the tmp buffer created in `merge_sort` below. */
+ void *l_arr = funcs->subarr_callback(tmp, 0, l_arr_size);
+ void *r_arr = funcs->subarr_callback(tmp, l_arr_size, r_arr_size);
+
+ /* Copy data to temp arrays `l_arr[]` and `r_arr[]`.
+ *
+ * This is iterating and repeatedly calling `get` and `set`, which sounds
+ * slow, but is only marginally slower than having a `copy` callback. With
+ * a `copy` callback, we'd save 3-4% in time.
+ */
+ for (uint32_t i = 0; i < l_arr_size; ++i) {
+ funcs->set_callback(l_arr, i, funcs->get_callback(arr, left_start + i));
+ }
+ for (uint32_t i = 0; i < r_arr_size; ++i) {
+ funcs->set_callback(r_arr, i, funcs->get_callback(arr, mid + 1 + i));
+ }
+
+ /* Merge the temp arrays back into `arr[left_start..right_end]`. */
+ merge_sort_merge_back(arr, l_arr, l_arr_size, r_arr, r_arr_size, left_start, object, funcs);
+}
+
+non_null()
+static void insertion_sort_step(void *arr, void *tmp, uint32_t i, const void *object, const Sort_Funcs *funcs)
+{
+ funcs->set_callback(tmp, 0, funcs->get_callback(arr, i));
+ uint32_t j = i;
+
+ while (j > 0) {
+ if (!funcs->less_callback(object, tmp, funcs->get_callback(arr, j - 1))) {
+ break;
+ }
+ funcs->set_callback(arr, j, funcs->get_callback(arr, j - 1));
+ --j;
+ }
+
+ funcs->set_callback(arr, j, tmp);
+}
+
+non_null()
+static void insertion_sort_with_buf(void *arr, uint32_t arr_size, void *tmp, uint32_t tmp_size, const void *object, const Sort_Funcs *funcs)
+{
+ for (uint32_t i = 1; i < arr_size; ++i) {
+ insertion_sort_step(arr, tmp, i, object, funcs);
+ }
+}
+
+non_null()
+static bool insertion_sort(void *arr, uint32_t arr_size, const void *object, const Sort_Funcs *funcs)
+{
+ void *tmp = funcs->alloc_callback(object, 1);
+
+ if (tmp == nullptr) {
+ return false;
+ }
+
+ insertion_sort_with_buf(arr, arr_size, tmp, 1, object, funcs);
+
+ funcs->delete_callback(object, tmp, 1);
+ return true;
+}
+
+void merge_sort_with_buf(void *arr, uint32_t arr_size, void *tmp, uint32_t tmp_size, const void *object, const Sort_Funcs *funcs)
+{
+ assert(tmp_size >= arr_size);
+
+ if (arr_size <= SMALL_ARRAY_THRESHOLD) {
+ assert(tmp_size >= 1);
+ insertion_sort_with_buf(arr, arr_size, tmp, tmp_size, object, funcs);
+ return;
+ }
+
+ // Merge subarrays in bottom up manner. First merge subarrays of
+ // size 1 to create sorted subarrays of size 2, then merge subarrays
+ // of size 2 to create sorted subarrays of size 4, and so on.
+ for (uint32_t curr_size = 1; curr_size <= arr_size - 1; curr_size = 2 * curr_size) {
+ // Pick starting point of different subarrays of current size
+ for (uint32_t left_start = 0; left_start < arr_size - 1; left_start += 2 * curr_size) {
+ // Find ending point of left subarray. mid+1 is starting
+ // point of right
+ const uint32_t mid = min_u32(left_start + curr_size - 1, arr_size - 1);
+ const uint32_t right_end = min_u32(left_start + 2 * curr_size - 1, arr_size - 1);
+
+ // Merge Subarrays arr[left_start...mid] & arr[mid+1...right_end]
+ merge_sort_merge(arr, left_start, mid, right_end, tmp, object, funcs);
+ }
+ }
+}
+
+bool merge_sort(void *arr, uint32_t arr_size, const void *object, const Sort_Funcs *funcs)
+{
+ if (arr_size <= SMALL_ARRAY_THRESHOLD) {
+ return insertion_sort(arr, arr_size, object, funcs);
+ }
+
+ void *tmp = funcs->alloc_callback(object, arr_size);
+
+ if (tmp == nullptr) {
+ return false;
+ }
+
+ merge_sort_with_buf(arr, arr_size, tmp, arr_size, object, funcs);
+
+ funcs->delete_callback(object, tmp, arr_size);
+ return true;
+}
diff --git a/protocols/Tox/libtox/src/toxcore/sort.h b/protocols/Tox/libtox/src/toxcore/sort.h
new file mode 100644
index 0000000000..b95ca8be3c
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/sort.h
@@ -0,0 +1,116 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2023-2025 The TokTok team.
+ */
+
+#ifndef C_TOXCORE_TOXCORE_SORT_H
+#define C_TOXCORE_TOXCORE_SORT_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "attributes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @brief Compare elements with a less-than ordering: `a < b`. */
+typedef bool sort_less_cb(const void *object, const void *a, const void *b);
+/** @brief Get element from array at index. */
+typedef const void *sort_get_cb(const void *arr, uint32_t index);
+/** @brief Set element in array at index to new value (perform copy). */
+typedef void sort_set_cb(void *arr, uint32_t index, const void *val);
+/** @brief Get a sub-array at an index of a given size (mutable pointer).
+ *
+ * Used to index in the temporary array allocated by `sort_alloc_cb` and get
+ * a sub-array for working memory.
+ */
+typedef void *sort_subarr_cb(void *arr, uint32_t index, uint32_t size);
+/** @brief Allocate a new array of the element type.
+ *
+ * @param size The array size in elements of type T (not byte size). This value
+ * is always exactly the input array size as passed to `merge_sort`.
+ */
+typedef void *sort_alloc_cb(const void *object, uint32_t size);
+/** @brief Free the element type array. */
+typedef void sort_delete_cb(const void *object, void *arr, uint32_t size);
+
+/** @brief Virtual function table for getting/setting elements in an array and
+ * comparing them.
+ *
+ * Only the `less`, `alloc`, and `delete` functions get a `this`-pointer. We
+ * assume that indexing in an array doesn't need any other information than the
+ * array itself.
+ *
+ * For now, the `this`-pointer is const, because we assume sorting doesn't need
+ * to mutate any state, but if necessary that can be changed in the future.
+ */
+typedef struct Sort_Funcs {
+ sort_less_cb *less_callback;
+ sort_get_cb *get_callback;
+ sort_set_cb *set_callback;
+ sort_subarr_cb *subarr_callback;
+ sort_alloc_cb *alloc_callback;
+ sort_delete_cb *delete_callback;
+} Sort_Funcs;
+
+/** @brief Non-recursive merge sort function to sort `arr[0...arr_size-1]`.
+ *
+ * Avoids `memcpy` and avoids treating elements as byte arrays. Instead, uses
+ * callbacks to index in arrays and copy elements. This makes it quite a bit
+ * slower than `qsort`, but works with elements that require special care when
+ * being copied (e.g. if they are part of a graph or other data structure that
+ * with pointers or other invariants).
+ *
+ * This function actually uses insertion sort for small arrays (up to 16
+ * elements), which is faster than merge sort for small arrays, especially
+ * when mostly sorted (a common use case in toxcore).
+ *
+ * Allocates a single temporary array with the provided alloc callback, and
+ * frees it at the end. This is significantly faster than an in-place
+ * implementation.
+ *
+ * Complexity:
+ * - Space: `O(n) where n = array_size`.
+ * - Time: `O(n * log n) where n = array_size`.
+ *
+ * Compared to `qsort`, this is about 60-70% slower for large arrays. For small
+ * arrays (up to 16 elements), it's about 50% faster than `qsort`.
+ *
+ * @param[in,out] arr An array of type T.
+ * @param arr_size Number of elements in @p arr (count, not byte size).
+ * @param[in] object Comparator object.
+ * @param[in] funcs Callback struct for elements of type T.
+ */
+non_null()
+bool merge_sort(void *arr, uint32_t arr_size, const void *object, const Sort_Funcs *funcs);
+
+/**
+ * @brief Merge sort like above but with a pre-allocated buffer.
+ *
+ * This function is the same as `merge_sort` but uses a pre-allocated buffer
+ * for temporary storage. This can be useful if the caller wants to avoid
+ * dynamic memory allocation.
+ *
+ * This function is 1-2% faster than `merge_sort` for small arrays up to 1000
+ * elements, and about 5-10% faster for large arrays (2000+ elements).
+ *
+ * The main upside is that `alloc` and `delete` callbacks don't need to be
+ * implemented, and the caller can use a stack-allocated buffer.
+ *
+ * @param[in,out] arr An array of type T.
+ * @param arr_size Number of elements in @p arr (count, not byte size).
+ * @param[in,out] tmp A buffer of size `tmp_size` for temporary storage.
+ * @param tmp_size Number of elements in @p tmp (count, not byte size). Must be
+ * at least as large as `arr_size`.
+ * @param[in] object Comparator object.
+ * @param[in] funcs Callback struct for elements of type T.
+ */
+non_null()
+void merge_sort_with_buf(void *arr, uint32_t arr_size, void *tmp, uint32_t tmp_size, const void *object, const Sort_Funcs *funcs);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* C_TOXCORE_TOXCORE_SORT_H */
diff --git a/protocols/Tox/libtox/src/toxcore/timed_auth.c b/protocols/Tox/libtox/src/toxcore/timed_auth.c
index 875003257b..45afe0704a 100644
--- a/protocols/Tox/libtox/src/toxcore/timed_auth.c
+++ b/protocols/Tox/libtox/src/toxcore/timed_auth.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2019-2021 The TokTok team.
+ * Copyright © 2019-2025 The TokTok team.
*/
#include "timed_auth.h"
diff --git a/protocols/Tox/libtox/src/toxcore/timed_auth.h b/protocols/Tox/libtox/src/toxcore/timed_auth.h
index bb19570872..ccef4b305e 100644
--- a/protocols/Tox/libtox/src/toxcore/timed_auth.h
+++ b/protocols/Tox/libtox/src/toxcore/timed_auth.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2019-2021 The TokTok team.
+ * Copyright © 2019-2025 The TokTok team.
*/
#ifndef C_TOXCORE_TOXCORE_TIMED_AUTH_H
#define C_TOXCORE_TOXCORE_TIMED_AUTH_H
diff --git a/protocols/Tox/libtox/src/toxcore/tox.c b/protocols/Tox/libtox/src/toxcore/tox.c
index 085fab2ec1..8e1b43903d 100644
--- a/protocols/Tox/libtox/src/toxcore/tox.c
+++ b/protocols/Tox/libtox/src/toxcore/tox.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -32,8 +32,10 @@
#include "network.h"
#include "onion_client.h"
#include "state.h"
+#include "tox_log_level.h"
+#include "tox_options.h"
#include "tox_private.h"
-#include "tox_struct.h"
+#include "tox_struct.h" // IWYU pragma: keep
#include "util.h"
#include "../toxencryptsave/defines.h"
@@ -79,7 +81,7 @@ struct Tox_Userdata {
static logger_cb tox_log_handler;
non_null(1, 3, 5, 6) nullable(7)
-static void tox_log_handler(void *context, Logger_Level level, const char *file, int line, const char *func,
+static void tox_log_handler(void *context, Logger_Level level, const char *file, uint32_t line, const char *func,
const char *message, void *userdata)
{
Tox *tox = (Tox *)context;
@@ -360,20 +362,22 @@ static void tox_conference_peer_list_changed_handler(Messenger *m, uint32_t conf
}
}
-static dht_get_nodes_response_cb tox_dht_get_nodes_response_handler;
+static dht_nodes_response_cb tox_dht_nodes_response_handler;
non_null(1, 2) nullable(3)
-static void tox_dht_get_nodes_response_handler(const DHT *dht, const Node_format *node, void *user_data)
+static void tox_dht_nodes_response_handler(const DHT *dht, const Node_format *node, void *user_data)
{
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
- if (tox_data->tox->dht_get_nodes_response_callback == nullptr) {
+ if (tox_data->tox->dht_nodes_response_callback == nullptr) {
return;
}
Ip_Ntoa ip_str;
+ net_ip_ntoa(&node->ip_port.ip, &ip_str);
+
tox_unlock(tox_data->tox);
- tox_data->tox->dht_get_nodes_response_callback(
- tox_data->tox, node->public_key, net_ip_ntoa(&node->ip_port.ip, &ip_str), net_ntohs(node->ip_port.port),
+ tox_data->tox->dht_nodes_response_callback(
+ tox_data->tox, node->public_key, ip_str.buf, ip_str.length, net_ntohs(node->ip_port.port),
tox_data->user_data);
tox_lock(tox_data->tox);
}
@@ -524,7 +528,7 @@ static void tox_group_password_handler(const Messenger *m, uint32_t group_number
non_null(1, 5) nullable(8)
static void tox_group_message_handler(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id, unsigned int type,
- const uint8_t *message, size_t length, uint32_t message_id, void *user_data)
+ const uint8_t *message, size_t length, Tox_Group_Message_Id message_id, void *user_data)
{
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
@@ -536,16 +540,16 @@ static void tox_group_message_handler(const Messenger *m, uint32_t group_number,
}
}
-non_null(1, 5) nullable(7)
+non_null(1, 5) nullable(8)
static void tox_group_private_message_handler(const Messenger *m, uint32_t group_number, GC_Peer_Id peer_id,
- unsigned int type, const uint8_t *message, size_t length, void *user_data)
+ unsigned int type, const uint8_t *message, size_t length, Tox_Group_Message_Id message_id, void *user_data)
{
struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data;
if (tox_data->tox->group_private_message_callback != nullptr) {
tox_unlock(tox_data->tox);
tox_data->tox->group_private_message_callback(tox_data->tox, group_number, gc_peer_id_to_int(peer_id), (Tox_Message_Type)type, message,
- length, tox_data->user_data);
+ length, message_id, tox_data->user_data);
tox_lock(tox_data->tox);
}
}
@@ -712,7 +716,8 @@ static int tox_load(Tox *tox, const uint8_t *data, uint32_t length)
length - cookie_len, STATE_COOKIE_TYPE);
}
-Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
+nullable(1, 2, 3)
+static Tox *tox_new_system(const struct Tox_Options *options, Tox_Err_New *error, const Tox_System *sys)
{
struct Tox_Options *default_options = nullptr;
@@ -736,7 +741,6 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
const struct Tox_Options *const opts = options != nullptr ? options : default_options;
assert(opts != nullptr);
- const Tox_System *sys = tox_options_get_operating_system(opts);
const Tox_System default_system = tox_default_system();
if (sys == nullptr) {
@@ -752,6 +756,8 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
Messenger_Options m_options = {false};
+ m_options.dns_enabled = !tox_options_get_experimental_disable_dns(opts);
+
bool load_savedata_sk = false;
bool load_savedata_tox = false;
@@ -855,9 +861,10 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
}
const char *const proxy_host = tox_options_get_proxy_host(opts);
+ const bool dns_enabled = !tox_options_get_experimental_disable_dns(opts);
if (proxy_host == nullptr
- || !addr_resolve_or_parse_ip(tox->sys.ns, proxy_host, &m_options.proxy_info.ip_port.ip, nullptr)) {
+ || !addr_resolve_or_parse_ip(tox->sys.ns, tox->sys.mem, proxy_host, &m_options.proxy_info.ip_port.ip, nullptr, dns_enabled)) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_HOST);
// TODO(irungentoo): TOX_ERR_NEW_PROXY_NOT_FOUND if domain.
mem_delete(sys->mem, tox);
@@ -926,7 +933,7 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
return nullptr;
}
- tox->m->conferences_object = new_groupchats(tox->mono_time, tox->m);
+ tox->m->conferences_object = new_groupchats(tox->mono_time, sys->mem, tox->m);
if (tox->m->conferences_object == nullptr) {
kill_messenger(tox->m);
@@ -983,7 +990,7 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
callback_file_reqchunk(tox->m, tox_file_chunk_request_handler);
callback_file_sendrequest(tox->m, tox_file_recv_handler);
callback_file_data(tox->m, tox_file_recv_chunk_handler);
- dht_callback_get_nodes_response(tox->m->dht, tox_dht_get_nodes_response_handler);
+ dht_callback_nodes_response(tox->m->dht, tox_dht_nodes_response_handler);
g_callback_group_invite(tox->m->conferences_object, tox_conference_invite_handler);
g_callback_group_connected(tox->m->conferences_object, tox_conference_connected_handler);
g_callback_group_message(tox->m->conferences_object, tox_conference_message_handler);
@@ -1020,6 +1027,37 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
return tox;
}
+Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
+{
+ return tox_new_system(options, error, nullptr);
+}
+
+Tox *tox_new_testing(const Tox_Options *options, Tox_Err_New *error, const Tox_Options_Testing *testing, Tox_Err_New_Testing *testing_error)
+{
+ if (testing == nullptr) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_NEW_NULL);
+ SET_ERROR_PARAMETER(testing_error, TOX_ERR_NEW_TESTING_NULL);
+ return nullptr;
+ }
+
+ if (testing->operating_system == nullptr) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_NEW_NULL);
+ SET_ERROR_PARAMETER(testing_error, TOX_ERR_NEW_TESTING_NULL);
+ return nullptr;
+ }
+
+ const Tox_System *sys = testing->operating_system;
+
+ if (sys->rng == nullptr || sys->ns == nullptr || sys->mem == nullptr) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_NEW_NULL);
+ SET_ERROR_PARAMETER(testing_error, TOX_ERR_NEW_TESTING_NULL);
+ return nullptr;
+ }
+
+ SET_ERROR_PARAMETER(testing_error, TOX_ERR_NEW_TESTING_OK);
+ return tox_new_system(options, error, sys);
+}
+
void tox_kill(Tox *tox)
{
if (tox == nullptr) {
@@ -1027,7 +1065,7 @@ void tox_kill(Tox *tox)
}
tox_lock(tox);
- LOGGER_ASSERT(tox->m->log, tox->m->msi_packet == nullptr, "Attempted to kill tox while toxav is still alive");
+ LOGGER_ASSERT(tox->m->log, tox->toxav_object == nullptr, "Attempted to kill tox while toxav is still alive");
kill_groupchats(tox->m->conferences_object);
kill_messenger(tox->m);
mono_time_free(tox->sys.mem, tox->mono_time);
@@ -1108,7 +1146,7 @@ static int32_t resolve_bootstrap_node(Tox *tox, const char *host, uint16_t port,
return -1;
}
- const int32_t count = net_getipport(tox->sys.mem, host, root, TOX_SOCK_DGRAM);
+ const int32_t count = net_getipport(tox->sys.ns, tox->sys.mem, host, root, TOX_SOCK_DGRAM, tox->m->options.dns_enabled);
if (count < 1) {
LOGGER_DEBUG(tox->m->log, "could not resolve bootstrap node '%s'", host);
@@ -2520,6 +2558,12 @@ uint32_t tox_conference_join(Tox *tox, uint32_t friend_number, const uint8_t *co
Tox_Err_Conference_Join *error)
{
assert(tox != nullptr);
+
+ if (cookie == nullptr) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_NULL);
+ return UINT32_MAX;
+ }
+
tox_lock(tox);
const int ret = join_groupchat(tox->m->conferences_object, friend_number, GROUPCHAT_TYPE_TEXT, cookie, length);
tox_unlock(tox);
@@ -3209,7 +3253,7 @@ bool tox_group_reconnect(Tox *tox, uint32_t group_number, Tox_Err_Group_Reconnec
return false;
}
- const int ret = gc_rejoin_group(tox->m->group_handler, chat);
+ const int ret = gc_rejoin_group(tox->m->group_handler, chat, nullptr, 0);
tox_unlock(tox);
switch (ret) {
@@ -3688,7 +3732,7 @@ bool tox_group_set_topic(Tox *tox, uint32_t group_number, const uint8_t *topic,
return false;
}
-size_t tox_group_get_topic_size(const Tox *tox, uint32_t group_number, Tox_Err_Group_State_Queries *error)
+size_t tox_group_get_topic_size(const Tox *tox, uint32_t group_number, Tox_Err_Group_State_Query *error)
{
assert(tox != nullptr);
@@ -3696,12 +3740,12 @@ size_t tox_group_get_topic_size(const Tox *tox, uint32_t group_number, Tox_Err_G
const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number);
if (chat == nullptr) {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND);
tox_unlock(tox);
return -1;
}
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_OK);
const size_t ret = gc_get_topic_size(chat);
tox_unlock(tox);
@@ -3709,7 +3753,7 @@ size_t tox_group_get_topic_size(const Tox *tox, uint32_t group_number, Tox_Err_G
return ret;
}
-bool tox_group_get_topic(const Tox *tox, uint32_t group_number, uint8_t *topic, Tox_Err_Group_State_Queries *error)
+bool tox_group_get_topic(const Tox *tox, uint32_t group_number, uint8_t *topic, Tox_Err_Group_State_Query *error)
{
assert(tox != nullptr);
@@ -3717,7 +3761,7 @@ bool tox_group_get_topic(const Tox *tox, uint32_t group_number, uint8_t *topic,
const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number);
if (chat == nullptr) {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND);
tox_unlock(tox);
return false;
}
@@ -3725,11 +3769,11 @@ bool tox_group_get_topic(const Tox *tox, uint32_t group_number, uint8_t *topic,
gc_get_topic(chat, topic);
tox_unlock(tox);
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_OK);
return true;
}
-size_t tox_group_get_name_size(const Tox *tox, uint32_t group_number, Tox_Err_Group_State_Queries *error)
+size_t tox_group_get_name_size(const Tox *tox, uint32_t group_number, Tox_Err_Group_State_Query *error)
{
assert(tox != nullptr);
@@ -3737,12 +3781,12 @@ size_t tox_group_get_name_size(const Tox *tox, uint32_t group_number, Tox_Err_Gr
const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number);
if (chat == nullptr) {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND);
tox_unlock(tox);
return -1;
}
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_OK);
const size_t ret = gc_get_group_name_size(chat);
tox_unlock(tox);
@@ -3750,7 +3794,7 @@ size_t tox_group_get_name_size(const Tox *tox, uint32_t group_number, Tox_Err_Gr
return ret;
}
-bool tox_group_get_name(const Tox *tox, uint32_t group_number, uint8_t *name, Tox_Err_Group_State_Queries *error)
+bool tox_group_get_name(const Tox *tox, uint32_t group_number, uint8_t *name, Tox_Err_Group_State_Query *error)
{
assert(tox != nullptr);
@@ -3758,7 +3802,7 @@ bool tox_group_get_name(const Tox *tox, uint32_t group_number, uint8_t *name, To
const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number);
if (chat == nullptr) {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND);
tox_unlock(tox);
return false;
}
@@ -3766,12 +3810,12 @@ bool tox_group_get_name(const Tox *tox, uint32_t group_number, uint8_t *name, To
gc_get_group_name(chat, name);
tox_unlock(tox);
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_OK);
return true;
}
-bool tox_group_get_chat_id(const Tox *tox, uint32_t group_number, uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE], Tox_Err_Group_State_Queries *error)
+bool tox_group_get_chat_id(const Tox *tox, uint32_t group_number, uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE], Tox_Err_Group_State_Query *error)
{
assert(tox != nullptr);
@@ -3779,12 +3823,12 @@ bool tox_group_get_chat_id(const Tox *tox, uint32_t group_number, uint8_t chat_i
const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number);
if (chat == nullptr) {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND);
tox_unlock(tox);
return false;
}
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_OK);
gc_get_chat_id(chat, chat_id);
tox_unlock(tox);
@@ -3803,7 +3847,7 @@ uint32_t tox_group_get_number_groups(const Tox *tox)
}
Tox_Group_Privacy_State tox_group_get_privacy_state(const Tox *tox, uint32_t group_number,
- Tox_Err_Group_State_Queries *error)
+ Tox_Err_Group_State_Query *error)
{
assert(tox != nullptr);
@@ -3811,12 +3855,12 @@ Tox_Group_Privacy_State tox_group_get_privacy_state(const Tox *tox, uint32_t gro
const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number);
if (chat == nullptr) {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND);
tox_unlock(tox);
return (Tox_Group_Privacy_State) - 1;
}
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_OK);
const uint8_t state = gc_get_privacy_state(chat);
tox_unlock(tox);
@@ -3824,7 +3868,7 @@ Tox_Group_Privacy_State tox_group_get_privacy_state(const Tox *tox, uint32_t gro
return (Tox_Group_Privacy_State)state;
}
-Tox_Group_Topic_Lock tox_group_get_topic_lock(const Tox *tox, uint32_t group_number, Tox_Err_Group_State_Queries *error)
+Tox_Group_Topic_Lock tox_group_get_topic_lock(const Tox *tox, uint32_t group_number, Tox_Err_Group_State_Query *error)
{
assert(tox != nullptr);
@@ -3832,12 +3876,12 @@ Tox_Group_Topic_Lock tox_group_get_topic_lock(const Tox *tox, uint32_t group_num
const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number);
if (chat == nullptr) {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND);
tox_unlock(tox);
return (Tox_Group_Topic_Lock) - 1;
}
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_OK);
const Group_Topic_Lock topic_lock = gc_get_topic_lock_state(chat);
tox_unlock(tox);
@@ -3846,7 +3890,7 @@ Tox_Group_Topic_Lock tox_group_get_topic_lock(const Tox *tox, uint32_t group_num
}
Tox_Group_Voice_State tox_group_get_voice_state(const Tox *tox, uint32_t group_number,
- Tox_Err_Group_State_Queries *error)
+ Tox_Err_Group_State_Query *error)
{
assert(tox != nullptr);
@@ -3854,12 +3898,12 @@ Tox_Group_Voice_State tox_group_get_voice_state(const Tox *tox, uint32_t group_n
const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number);
if (chat == nullptr) {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND);
tox_unlock(tox);
return (Tox_Group_Voice_State) - 1;
}
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_OK);
const Group_Voice_State voice_state = gc_get_voice_state(chat);
tox_unlock(tox);
@@ -3867,7 +3911,7 @@ Tox_Group_Voice_State tox_group_get_voice_state(const Tox *tox, uint32_t group_n
return (Tox_Group_Voice_State)voice_state;
}
-uint16_t tox_group_get_peer_limit(const Tox *tox, uint32_t group_number, Tox_Err_Group_State_Queries *error)
+uint16_t tox_group_get_peer_limit(const Tox *tox, uint32_t group_number, Tox_Err_Group_State_Query *error)
{
assert(tox != nullptr);
@@ -3875,12 +3919,12 @@ uint16_t tox_group_get_peer_limit(const Tox *tox, uint32_t group_number, Tox_Err
const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number);
if (chat == nullptr) {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND);
tox_unlock(tox);
return -1;
}
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_OK);
const uint16_t ret = gc_get_max_peers(chat);
tox_unlock(tox);
@@ -3888,7 +3932,7 @@ uint16_t tox_group_get_peer_limit(const Tox *tox, uint32_t group_number, Tox_Err
return ret;
}
-size_t tox_group_get_password_size(const Tox *tox, uint32_t group_number, Tox_Err_Group_State_Queries *error)
+size_t tox_group_get_password_size(const Tox *tox, uint32_t group_number, Tox_Err_Group_State_Query *error)
{
assert(tox != nullptr);
@@ -3896,12 +3940,12 @@ size_t tox_group_get_password_size(const Tox *tox, uint32_t group_number, Tox_Er
const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number);
if (chat == nullptr) {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND);
tox_unlock(tox);
return -1;
}
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_OK);
const size_t ret = gc_get_password_size(chat);
tox_unlock(tox);
@@ -3910,7 +3954,7 @@ size_t tox_group_get_password_size(const Tox *tox, uint32_t group_number, Tox_Er
}
bool tox_group_get_password(const Tox *tox, uint32_t group_number, uint8_t *password,
- Tox_Err_Group_State_Queries *error)
+ Tox_Err_Group_State_Query *error)
{
assert(tox != nullptr);
@@ -3918,12 +3962,12 @@ bool tox_group_get_password(const Tox *tox, uint32_t group_number, uint8_t *pass
const GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number);
if (chat == nullptr) {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND);
tox_unlock(tox);
return false;
}
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERIES_OK);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_STATE_QUERY_OK);
gc_get_password(chat, password);
tox_unlock(tox);
@@ -3932,7 +3976,7 @@ bool tox_group_get_password(const Tox *tox, uint32_t group_number, uint8_t *pass
}
Tox_Group_Message_Id tox_group_send_message(
- const Tox *tox, uint32_t group_number, Tox_Message_Type type, const uint8_t *message,
+ const Tox *tox, uint32_t group_number, Tox_Message_Type message_type, const uint8_t *message,
size_t length, Tox_Err_Group_Send_Message *error)
{
assert(tox != nullptr);
@@ -3953,7 +3997,7 @@ Tox_Group_Message_Id tox_group_send_message(
}
uint32_t message_id = 0;
- const int ret = gc_send_message(chat, message, length, type, &message_id);
+ const int ret = gc_send_message(chat, message, length, message_type, &message_id);
tox_unlock(tox);
switch (ret) {
@@ -3994,8 +4038,8 @@ Tox_Group_Message_Id tox_group_send_message(
return -1;
}
-bool tox_group_send_private_message(const Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Message_Type type,
- const uint8_t *message, size_t length, Tox_Err_Group_Send_Private_Message *error)
+Tox_Group_Message_Id tox_group_send_private_message(const Tox *tox, uint32_t group_number, uint32_t peer_id,
+ Tox_Message_Type message_type, const uint8_t *message, size_t length, Tox_Err_Group_Send_Private_Message *error)
{
assert(tox != nullptr);
@@ -4005,59 +4049,60 @@ bool tox_group_send_private_message(const Tox *tox, uint32_t group_number, uint3
if (chat == nullptr) {
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_GROUP_NOT_FOUND);
tox_unlock(tox);
- return false;
+ return -1;
}
if (chat->connection_state == CS_DISCONNECTED) {
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_DISCONNECTED);
tox_unlock(tox);
- return false;
+ return -1;
}
- const int ret = gc_send_private_message(chat, gc_peer_id_from_int(peer_id), type, message, length);
+ uint32_t message_id = 0;
+ const int ret = gc_send_private_message(chat, gc_peer_id_from_int(peer_id), message_type, message, length, &message_id);
tox_unlock(tox);
switch (ret) {
case 0: {
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_OK);
- return true;
+ return message_id;
}
case -1: {
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_TOO_LONG);
- return false;
+ return -1;
}
case -2: {
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_EMPTY);
- return false;
+ return -1;
}
case -3: {
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PEER_NOT_FOUND);
- return false;
+ return -1;
}
case -4: {
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_BAD_TYPE);
- return false;
+ return -1;
}
case -5: {
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PERMISSIONS);
- return false;
+ return -1;
}
case -6: {
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_FAIL_SEND);
- return false;
+ return -1;
}
}
/* can't happen */
LOGGER_FATAL(tox->m->log, "impossible return value: %d", ret);
- return false;
+ return -1;
}
bool tox_group_send_custom_packet(const Tox *tox, uint32_t group_number, bool lossless, const uint8_t *data,
@@ -4100,11 +4145,6 @@ bool tox_group_send_custom_packet(const Tox *tox, uint32_t group_number, bool lo
}
case -3: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_CUSTOM_PACKET_PERMISSIONS);
- return false;
- }
-
- case -4: {
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_CUSTOM_PACKET_FAIL_SEND);
return false;
}
@@ -4162,11 +4202,6 @@ bool tox_group_send_custom_private_packet(const Tox *tox, uint32_t group_number,
}
case -4: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_PERMISSIONS);
- return false;
- }
-
- case -5: {
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_FAIL_SEND);
return false;
}
@@ -4241,6 +4276,11 @@ uint32_t tox_group_invite_accept(Tox *tox, uint32_t friend_number, const uint8_t
{
assert(tox != nullptr);
+ if (invite_data == nullptr || name == nullptr) {
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_INVITE_ACCEPT_NULL);
+ return UINT32_MAX;
+ }
+
tox_lock(tox);
const int ret = gc_accept_invite(tox->m->group_handler, friend_number, invite_data, length, name, name_length, password,
password_length);
@@ -4278,7 +4318,7 @@ uint32_t tox_group_invite_accept(Tox *tox, uint32_t friend_number, const uint8_t
}
case -6: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_INVITE_ACCEPT_CORE);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_INVITE_ACCEPT_FRIEND_NOT_FOUND);
return UINT32_MAX;
}
@@ -4294,8 +4334,8 @@ uint32_t tox_group_invite_accept(Tox *tox, uint32_t friend_number, const uint8_t
return UINT32_MAX;
}
-bool tox_group_founder_set_password(Tox *tox, uint32_t group_number, const uint8_t *password, size_t length,
- Tox_Err_Group_Founder_Set_Password *error)
+bool tox_group_set_password(Tox *tox, uint32_t group_number, const uint8_t *password, size_t length,
+ Tox_Err_Group_Set_Password *error)
{
assert(tox != nullptr);
@@ -4303,13 +4343,13 @@ bool tox_group_founder_set_password(Tox *tox, uint32_t group_number, const uint8
GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number);
if (chat == nullptr) {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_GROUP_NOT_FOUND);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PASSWORD_GROUP_NOT_FOUND);
tox_unlock(tox);
return false;
}
if (chat->connection_state == CS_DISCONNECTED) {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_DISCONNECTED);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PASSWORD_DISCONNECTED);
tox_unlock(tox);
return false;
}
@@ -4319,27 +4359,27 @@ bool tox_group_founder_set_password(Tox *tox, uint32_t group_number, const uint8
switch (ret) {
case 0: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PASSWORD_OK);
return true;
}
case -1: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_PERMISSIONS);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PASSWORD_PERMISSIONS);
return false;
}
case -2: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_TOO_LONG);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PASSWORD_TOO_LONG);
return false;
}
case -3: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_FAIL_SEND);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PASSWORD_FAIL_SEND);
return false;
}
case -4: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_MALLOC);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PASSWORD_MALLOC);
return false;
}
}
@@ -4350,8 +4390,8 @@ bool tox_group_founder_set_password(Tox *tox, uint32_t group_number, const uint8
return false;
}
-bool tox_group_founder_set_privacy_state(Tox *tox, uint32_t group_number, Tox_Group_Privacy_State privacy_state,
- Tox_Err_Group_Founder_Set_Privacy_State *error)
+bool tox_group_set_privacy_state(Tox *tox, uint32_t group_number, Tox_Group_Privacy_State privacy_state,
+ Tox_Err_Group_Set_Privacy_State *error)
{
assert(tox != nullptr);
@@ -4361,32 +4401,32 @@ bool tox_group_founder_set_privacy_state(Tox *tox, uint32_t group_number, Tox_Gr
switch (ret) {
case 0: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PRIVACY_STATE_OK);
return true;
}
case -1: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_GROUP_NOT_FOUND);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PRIVACY_STATE_GROUP_NOT_FOUND);
return false;
}
case -2: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_PERMISSIONS);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PRIVACY_STATE_PERMISSIONS);
return false;
}
case -3: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_DISCONNECTED);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PRIVACY_STATE_DISCONNECTED);
return false;
}
case -4: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SET);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PRIVACY_STATE_FAIL_SET);
return false;
}
case -5: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SEND);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PRIVACY_STATE_FAIL_SEND);
return false;
}
}
@@ -4397,8 +4437,8 @@ bool tox_group_founder_set_privacy_state(Tox *tox, uint32_t group_number, Tox_Gr
return false;
}
-bool tox_group_founder_set_topic_lock(Tox *tox, uint32_t group_number, Tox_Group_Topic_Lock topic_lock,
- Tox_Err_Group_Founder_Set_Topic_Lock *error)
+bool tox_group_set_topic_lock(Tox *tox, uint32_t group_number, Tox_Group_Topic_Lock topic_lock,
+ Tox_Err_Group_Set_Topic_Lock *error)
{
assert(tox != nullptr);
@@ -4408,37 +4448,37 @@ bool tox_group_founder_set_topic_lock(Tox *tox, uint32_t group_number, Tox_Group
switch (ret) {
case 0: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_TOPIC_LOCK_OK);
return true;
}
case -1: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_GROUP_NOT_FOUND);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_TOPIC_LOCK_GROUP_NOT_FOUND);
return false;
}
case -2: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_INVALID);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_TOPIC_LOCK_INVALID);
return false;
}
case -3: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_PERMISSIONS);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_TOPIC_LOCK_PERMISSIONS);
return false;
}
case -4: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_DISCONNECTED);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_TOPIC_LOCK_DISCONNECTED);
return false;
}
case -5: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_FAIL_SET);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_TOPIC_LOCK_FAIL_SET);
return false;
}
case -6: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_FAIL_SEND);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_TOPIC_LOCK_FAIL_SEND);
return false;
}
}
@@ -4449,8 +4489,8 @@ bool tox_group_founder_set_topic_lock(Tox *tox, uint32_t group_number, Tox_Group
return false;
}
-bool tox_group_founder_set_voice_state(Tox *tox, uint32_t group_number, Tox_Group_Voice_State voice_state,
- Tox_Err_Group_Founder_Set_Voice_State *error)
+bool tox_group_set_voice_state(Tox *tox, uint32_t group_number, Tox_Group_Voice_State voice_state,
+ Tox_Err_Group_Set_Voice_State *error)
{
assert(tox != nullptr);
@@ -4460,32 +4500,32 @@ bool tox_group_founder_set_voice_state(Tox *tox, uint32_t group_number, Tox_Grou
switch (ret) {
case 0: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_OK);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_VOICE_STATE_OK);
return true;
}
case -1: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_GROUP_NOT_FOUND);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_VOICE_STATE_GROUP_NOT_FOUND);
return false;
}
case -2: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_PERMISSIONS);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_VOICE_STATE_PERMISSIONS);
return false;
}
case -3: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_DISCONNECTED);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_VOICE_STATE_DISCONNECTED);
return false;
}
case -4: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_FAIL_SET);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_VOICE_STATE_FAIL_SET);
return false;
}
case -5: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_FAIL_SEND);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_VOICE_STATE_FAIL_SEND);
return false;
}
}
@@ -4496,8 +4536,8 @@ bool tox_group_founder_set_voice_state(Tox *tox, uint32_t group_number, Tox_Grou
return false;
}
-bool tox_group_founder_set_peer_limit(Tox *tox, uint32_t group_number, uint16_t peer_limit,
- Tox_Err_Group_Founder_Set_Peer_Limit *error)
+bool tox_group_set_peer_limit(Tox *tox, uint32_t group_number, uint16_t peer_limit,
+ Tox_Err_Group_Set_Peer_Limit *error)
{
assert(tox != nullptr);
@@ -4505,13 +4545,13 @@ bool tox_group_founder_set_peer_limit(Tox *tox, uint32_t group_number, uint16_t
GC_Chat *chat = gc_get_group(tox->m->group_handler, group_number);
if (chat == nullptr) {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_GROUP_NOT_FOUND);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PEER_LIMIT_GROUP_NOT_FOUND);
tox_unlock(tox);
return false;
}
if (chat->connection_state == CS_DISCONNECTED) {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_DISCONNECTED);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PEER_LIMIT_DISCONNECTED);
tox_unlock(tox);
return false;
}
@@ -4521,22 +4561,22 @@ bool tox_group_founder_set_peer_limit(Tox *tox, uint32_t group_number, uint16_t
switch (ret) {
case 0: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PEER_LIMIT_OK);
return true;
}
case -1: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_PERMISSIONS);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PEER_LIMIT_PERMISSIONS);
return false;
}
case -2: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SET);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PEER_LIMIT_FAIL_SET);
return false;
}
case -3: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SEND);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_PEER_LIMIT_FAIL_SEND);
return false;
}
}
@@ -4587,8 +4627,8 @@ bool tox_group_set_ignore(Tox *tox, uint32_t group_number, uint32_t peer_id, boo
return false;
}
-bool tox_group_mod_set_role(Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Group_Role role,
- Tox_Err_Group_Mod_Set_Role *error)
+bool tox_group_set_role(Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_Group_Role role,
+ Tox_Err_Group_Set_Role *error)
{
assert(tox != nullptr);
@@ -4598,37 +4638,37 @@ bool tox_group_mod_set_role(Tox *tox, uint32_t group_number, uint32_t peer_id, T
switch (ret) {
case 0: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_SET_ROLE_OK);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_ROLE_OK);
return true;
}
case -1: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_SET_ROLE_GROUP_NOT_FOUND);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_ROLE_GROUP_NOT_FOUND);
return false;
}
case -2: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_SET_ROLE_PEER_NOT_FOUND);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_ROLE_PEER_NOT_FOUND);
return false;
}
case -3: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_ROLE_PERMISSIONS);
return false;
}
case -4: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_SET_ROLE_ASSIGNMENT);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_ROLE_ASSIGNMENT);
return false;
}
case -5: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_SET_ROLE_FAIL_ACTION);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_ROLE_FAIL_ACTION);
return false;
}
case -6: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_SET_ROLE_SELF);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_SET_ROLE_SELF);
return false;
}
}
@@ -4639,8 +4679,8 @@ bool tox_group_mod_set_role(Tox *tox, uint32_t group_number, uint32_t peer_id, T
return false;
}
-bool tox_group_mod_kick_peer(const Tox *tox, uint32_t group_number, uint32_t peer_id,
- Tox_Err_Group_Mod_Kick_Peer *error)
+bool tox_group_kick_peer(const Tox *tox, uint32_t group_number, uint32_t peer_id,
+ Tox_Err_Group_Kick_Peer *error)
{
assert(tox != nullptr);
@@ -4650,37 +4690,37 @@ bool tox_group_mod_kick_peer(const Tox *tox, uint32_t group_number, uint32_t pee
switch (ret) {
case 0: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_KICK_PEER_OK);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_KICK_PEER_OK);
return true;
}
case -1: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_KICK_PEER_GROUP_NOT_FOUND);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_KICK_PEER_GROUP_NOT_FOUND);
return false;
}
case -2: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_KICK_PEER_PEER_NOT_FOUND);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_KICK_PEER_PEER_NOT_FOUND);
return false;
}
case -3: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_KICK_PEER_PERMISSIONS);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_KICK_PEER_PERMISSIONS);
return false;
}
case -4: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_KICK_PEER_FAIL_ACTION);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_KICK_PEER_FAIL_ACTION);
return false;
}
case -5: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_KICK_PEER_FAIL_SEND);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_KICK_PEER_FAIL_SEND);
return false;
}
case -6: {
- SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_MOD_KICK_PEER_SELF);
+ SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_KICK_PEER_SELF);
return false;
}
}
diff --git a/protocols/Tox/libtox/src/toxcore/tox.h b/protocols/Tox/libtox/src/toxcore/tox.h
index fa887fc779..f44b8201ac 100644
--- a/protocols/Tox/libtox/src/toxcore/tox.h
+++ b/protocols/Tox/libtox/src/toxcore/tox.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -25,9 +25,8 @@
* could not perform any operation, because one of the required parameters was
* NULL. Some functions operate correctly or are defined as effectless on NULL.
*
- * Some functions additionally return a value outside their
- * return type domain, or a bool containing true on success and false on
- * failure.
+ * Some functions additionally return a value outside their return type domain,
+ * or a bool containing true on success and false on failure.
*
* All functions that take a Tox instance pointer will cause undefined behaviour
* when passed a NULL Tox pointer.
@@ -52,17 +51,9 @@
* event listeners, it needs to implement the dispatch functionality itself.
*
* The last argument to a callback is the user data pointer. It is passed from
- * tox_iterate to each callback in sequence.
- *
- * The user data pointer is never stored or dereferenced by any library code, so
- * can be any pointer, including NULL. Callbacks must all operate on the same
- * object type. In the apidsl code (tox.in.h), this is denoted with `any`. The
- * `any` in tox_iterate must be the same `any` as in all callbacks. In C,
- * lacking parametric polymorphism, this is a pointer to void.
- *
- * Old style callbacks that are registered together with a user data pointer
- * receive that pointer as argument when they are called. They can each have
- * their own user data pointer of their own type.
+ * tox_iterate to each callback in sequence. The user data pointer is never
+ * stored or dereferenced by any library code, so can be any pointer, including
+ * NULL.
*
* @section threading Threading implications
*
@@ -96,6 +87,13 @@
* If any other thread calls tox_self_set_name while this thread is allocating
* memory, the length may have become invalid, and the call to
* tox_self_get_name may cause undefined behaviour.
+ *
+ * @section deprecations
+ *
+ * Some functions and types are deprecated. We recommend compiling with
+ * `-DTOX_HIDE_DEPRECATED` to hide them. They will be removed in the next major
+ * version of Tox (and since we're in major version 0, that means the next
+ * minor version).
*/
#ifndef C_TOXCORE_TOXCORE_TOX_H
#define C_TOXCORE_TOXCORE_TOX_H
@@ -104,14 +102,14 @@
#include <stddef.h>
#include <stdint.h>
+#include "tox_options.h" // IWYU pragma: export
+
#ifdef __cplusplus
extern "C" {
#endif
/** @{ @namespace tox */
-#ifndef TOX_DEFINED
-#define TOX_DEFINED
/**
* @brief The Tox instance type.
*
@@ -122,7 +120,6 @@ extern "C" {
* limiting factor is the number of usable ports on a device.
*/
typedef struct Tox Tox;
-#endif /* TOX_DEFINED */
/** @{
* @name API version
@@ -157,7 +154,7 @@ uint32_t tox_version_minor(void);
* Incremented when bugfixes are applied without changing any functionality or
* API or ABI.
*/
-#define TOX_VERSION_PATCH 18
+#define TOX_VERSION_PATCH 21
uint32_t tox_version_patch(void);
@@ -206,7 +203,7 @@ bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch);
*
* The values of these are not part of the ABI. Prefer to use the function
* versions of them for code that should remain compatible with future versions
- * of toxcore.
+ * of the Tox library.
*/
/**
@@ -283,7 +280,7 @@ uint32_t tox_max_status_message_length(void);
*
* @deprecated The macro will be removed in 0.3.0. Use the function instead.
*/
-#define TOX_MAX_FRIEND_REQUEST_LENGTH 1016
+#define TOX_MAX_FRIEND_REQUEST_LENGTH 921
uint32_t tox_max_friend_request_length(void);
@@ -396,431 +393,6 @@ const char *tox_message_type_to_string(Tox_Message_Type value);
/** @} */
/** @{
- * @name Startup options
- */
-
-/**
- * @brief Type of proxy used to connect to TCP relays.
- */
-typedef enum Tox_Proxy_Type {
-
- /**
- * Don't use a proxy.
- */
- TOX_PROXY_TYPE_NONE,
-
- /**
- * HTTP proxy using CONNECT.
- */
- TOX_PROXY_TYPE_HTTP,
-
- /**
- * SOCKS proxy for simple socket pipes.
- */
- TOX_PROXY_TYPE_SOCKS5,
-
-} Tox_Proxy_Type;
-
-const char *tox_proxy_type_to_string(Tox_Proxy_Type value);
-
-/**
- * @brief Type of savedata to create the Tox instance from.
- */
-typedef enum Tox_Savedata_Type {
-
- /**
- * No savedata.
- */
- TOX_SAVEDATA_TYPE_NONE,
-
- /**
- * Savedata is one that was obtained from tox_get_savedata.
- */
- TOX_SAVEDATA_TYPE_TOX_SAVE,
-
- /**
- * Savedata is a secret key of length TOX_SECRET_KEY_SIZE.
- */
- TOX_SAVEDATA_TYPE_SECRET_KEY,
-
-} Tox_Savedata_Type;
-
-const char *tox_savedata_type_to_string(Tox_Savedata_Type value);
-
-/**
- * @brief Severity level of log messages.
- */
-typedef enum Tox_Log_Level {
-
- /**
- * Very detailed traces including all network activity.
- */
- TOX_LOG_LEVEL_TRACE,
-
- /**
- * Debug messages such as which port we bind to.
- */
- TOX_LOG_LEVEL_DEBUG,
-
- /**
- * Informational log messages such as video call status changes.
- */
- TOX_LOG_LEVEL_INFO,
-
- /**
- * Warnings about events_alloc inconsistency or logic errors.
- */
- TOX_LOG_LEVEL_WARNING,
-
- /**
- * Severe unexpected errors caused by external or events_alloc inconsistency.
- */
- TOX_LOG_LEVEL_ERROR,
-
-} Tox_Log_Level;
-
-const char *tox_log_level_to_string(Tox_Log_Level value);
-
-/**
- * @brief This event is triggered when the toxcore library logs an events_alloc message.
- *
- * This is mostly useful for debugging. This callback can be called from any
- * function, not just tox_iterate. This means the user data lifetime must at
- * least extend between registering and unregistering it or tox_kill.
- *
- * Other toxcore modules such as toxav may concurrently call this callback at
- * any time. Thus, user code must make sure it is equipped to handle concurrent
- * execution, e.g. by employing appropriate mutex locking.
- *
- * When using the experimental_thread_safety option, no Tox API functions can
- * be called from within the log callback.
- *
- * @param level The severity of the log message.
- * @param file The source file from which the message originated.
- * @param line The source line from which the message originated.
- * @param func The function from which the message originated.
- * @param message The log message.
- * @param user_data The user data pointer passed to tox_new in options.
- */
-typedef void tox_log_cb(Tox *tox, Tox_Log_Level level, const char *file, uint32_t line, const char *func,
- const char *message, void *user_data);
-
-/**
- * @brief Operating system functions used by Tox.
- *
- * This struct is opaque and generally shouldn't be used in clients, but in
- * combination with tox_private.h, it allows tests to inject non-IO (hermetic)
- * versions of low level network, RNG, and time keeping functions.
- */
-typedef struct Tox_System Tox_System;
-
-/**
- * @brief This struct contains all the startup options for Tox.
- *
- * You must tox_options_new to allocate an object of this type.
- *
- * WARNING: Although this struct happens to be visible in the API, it is
- * effectively private. Do not allocate this yourself or access members
- * directly, as it *will* break binary compatibility frequently.
- *
- * @deprecated The memory layout of this struct (size, alignment, and field
- * order) is not part of the ABI. To remain compatible, prefer to use
- * tox_options_new to allocate the object and accessor functions to set the
- * members. The struct will become opaque (i.e. the definition will become
- * private) in v0.3.0.
- */
-typedef struct Tox_Options Tox_Options;
-struct Tox_Options {
-
- /**
- * The type of socket to create.
- *
- * If this is set to false, an IPv4 socket is created, which subsequently
- * only allows IPv4 communication.
- * If it is set to true, an IPv6 socket is created, allowing both IPv4 and
- * IPv6 communication.
- */
- bool ipv6_enabled;
-
- /**
- * Enable the use of UDP communication when available.
- *
- * Setting this to false will force Tox to use TCP only. Communications will
- * need to be relayed through a TCP relay node, potentially slowing them down.
- *
- * If a proxy is enabled, UDP will be disabled if either toxcore or the
- * proxy don't support proxying UDP messages.
- */
- bool udp_enabled;
-
- /**
- * Enable local network peer discovery.
- *
- * Disabling this will cause Tox to not look for peers on the local network.
- */
- bool local_discovery_enabled;
-
- /**
- * Enable storing DHT announcements and forwarding corresponding requests.
- *
- * Disabling this will cause Tox to ignore the relevant packets.
- */
- bool dht_announcements_enabled;
-
- /**
- * Pass communications through a proxy.
- */
- Tox_Proxy_Type proxy_type;
-
- /**
- * The IP address or DNS name of the proxy to be used.
- *
- * If used, this must be non-NULL and be a valid DNS name. The name must not
- * exceed TOX_MAX_HOSTNAME_LENGTH characters, and be in a NUL-terminated C string
- * format (TOX_MAX_HOSTNAME_LENGTH includes the NUL byte).
- *
- * This member is ignored (it can be NULL) if proxy_type is TOX_PROXY_TYPE_NONE.
- *
- * The data pointed at by this member is owned by the user, so must
- * outlive the options object.
- */
- const char *proxy_host;
-
- /**
- * The port to use to connect to the proxy server.
- *
- * Ports must be in the range (1, 65535). The value is ignored if
- * proxy_type is TOX_PROXY_TYPE_NONE.
- */
- uint16_t proxy_port;
-
- /**
- * The start port of the inclusive port range to attempt to use.
- *
- * If both start_port and end_port are 0, the default port range will be
- * used: `[33445, 33545]`.
- *
- * If either start_port or end_port is 0 while the other is non-zero, the
- * non-zero port will be the only port in the range.
- *
- * Having start_port > end_port will yield the same behavior as if start_port
- * and end_port were swapped.
- */
- uint16_t start_port;
-
- /**
- * The end port of the inclusive port range to attempt to use.
- */
- uint16_t end_port;
-
- /**
- * The port to use for the TCP server (relay). If 0, the TCP server is
- * disabled.
- *
- * Enabling it is not required for Tox to function properly.
- *
- * When enabled, your Tox instance can act as a TCP relay for other Tox
- * instance. This leads to increased traffic, thus when writing a client
- * it is recommended to enable TCP server only if the user has an option
- * to disable it.
- */
- uint16_t tcp_port;
-
- /**
- * Enables or disables UDP hole-punching in toxcore. (Default: enabled).
- */
- bool hole_punching_enabled;
-
- /**
- * The type of savedata to load from.
- */
- Tox_Savedata_Type savedata_type;
-
- /**
- * The savedata.
- *
- * The data pointed at by this member is owned by the user, so must
- * outlive the options object.
- */
- const uint8_t *savedata_data;
-
- /**
- * The length of the savedata.
- */
- size_t savedata_length;
-
- /**
- * Logging callback for the new tox instance.
- */
- tox_log_cb *log_callback;
-
- /**
- * User data pointer passed to the logging callback.
- */
- void *log_user_data;
-
- /**
- * These options are experimental, so avoid writing code that depends on
- * them. Options marked "experimental" may change their behaviour or go away
- * entirely in the future, or may be renamed to something non-experimental
- * if they become part of the supported API.
- */
- /**
- * Make public API functions thread-safe using a per-instance lock.
- *
- * Default: false.
- */
- bool experimental_thread_safety;
-
- /**
- * Low level operating system functionality such as send/recv, random
- * number generation, and memory allocation.
- */
- const Tox_System *operating_system;
-
- /**
- * Enable saving DHT-based group chats to Tox save data (via `tox_get_savedata`).
- * This format will change in the future, so don't rely on it.
- *
- * As an alternative, clients can save the group chat ID in client-owned
- * savedata. Then, when the client starts, it can use `tox_group_join`
- * with the saved chat ID to recreate the group chat.
- *
- * Default: false.
- */
- bool experimental_groups_persistence;
-};
-
-bool tox_options_get_ipv6_enabled(const Tox_Options *options);
-
-void tox_options_set_ipv6_enabled(Tox_Options *options, bool ipv6_enabled);
-
-bool tox_options_get_udp_enabled(const Tox_Options *options);
-
-void tox_options_set_udp_enabled(Tox_Options *options, bool udp_enabled);
-
-bool tox_options_get_local_discovery_enabled(const Tox_Options *options);
-
-void tox_options_set_local_discovery_enabled(Tox_Options *options, bool local_discovery_enabled);
-
-bool tox_options_get_dht_announcements_enabled(const Tox_Options *options);
-
-void tox_options_set_dht_announcements_enabled(Tox_Options *options, bool dht_announcements_enabled);
-
-Tox_Proxy_Type tox_options_get_proxy_type(const Tox_Options *options);
-
-void tox_options_set_proxy_type(Tox_Options *options, Tox_Proxy_Type proxy_type);
-
-const char *tox_options_get_proxy_host(const Tox_Options *options);
-
-void tox_options_set_proxy_host(Tox_Options *options, const char *proxy_host);
-
-uint16_t tox_options_get_proxy_port(const Tox_Options *options);
-
-void tox_options_set_proxy_port(Tox_Options *options, uint16_t proxy_port);
-
-uint16_t tox_options_get_start_port(const Tox_Options *options);
-
-void tox_options_set_start_port(Tox_Options *options, uint16_t start_port);
-
-uint16_t tox_options_get_end_port(const Tox_Options *options);
-
-void tox_options_set_end_port(Tox_Options *options, uint16_t end_port);
-
-uint16_t tox_options_get_tcp_port(const Tox_Options *options);
-
-void tox_options_set_tcp_port(Tox_Options *options, uint16_t tcp_port);
-
-bool tox_options_get_hole_punching_enabled(const Tox_Options *options);
-
-void tox_options_set_hole_punching_enabled(Tox_Options *options, bool hole_punching_enabled);
-
-Tox_Savedata_Type tox_options_get_savedata_type(const Tox_Options *options);
-
-void tox_options_set_savedata_type(Tox_Options *options, Tox_Savedata_Type savedata_type);
-
-const uint8_t *tox_options_get_savedata_data(const Tox_Options *options);
-
-void tox_options_set_savedata_data(Tox_Options *options, const uint8_t savedata_data[], size_t length);
-
-size_t tox_options_get_savedata_length(const Tox_Options *options);
-
-void tox_options_set_savedata_length(Tox_Options *options, size_t savedata_length);
-
-tox_log_cb *tox_options_get_log_callback(const Tox_Options *options);
-
-void tox_options_set_log_callback(Tox_Options *options, tox_log_cb *log_callback);
-
-void *tox_options_get_log_user_data(const Tox_Options *options);
-
-void tox_options_set_log_user_data(Tox_Options *options, void *log_user_data);
-
-bool tox_options_get_experimental_thread_safety(const Tox_Options *options);
-
-void tox_options_set_experimental_thread_safety(Tox_Options *options, bool experimental_thread_safety);
-
-const Tox_System *tox_options_get_operating_system(const Tox_Options *options);
-
-void tox_options_set_operating_system(Tox_Options *options, const Tox_System *operating_system);
-
-bool tox_options_get_experimental_groups_persistence(const Tox_Options *options);
-
-void tox_options_set_experimental_groups_persistence(Tox_Options *options, bool experimental_groups_persistence);
-
-/**
- * @brief Initialises a Tox_Options object with the default options.
- *
- * The result of this function is independent of the original options. All
- * values will be overwritten, no values will be read (so it is permissible
- * to pass an uninitialised object).
- *
- * If options is NULL, this function has no effect.
- *
- * @param options An options object to be filled with default options.
- */
-void tox_options_default(Tox_Options *options);
-
-typedef enum Tox_Err_Options_New {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_OPTIONS_NEW_OK,
-
- /**
- * The function failed to allocate enough memory for the options struct.
- */
- TOX_ERR_OPTIONS_NEW_MALLOC,
-
-} Tox_Err_Options_New;
-
-const char *tox_err_options_new_to_string(Tox_Err_Options_New value);
-
-/**
- * @brief Allocates a new Tox_Options object and initialises it with the default
- * options.
- *
- * This function can be used to preserve long term ABI compatibility by
- * giving the responsibility of allocation and deallocation to the Tox library.
- *
- * Objects returned from this function must be freed using the tox_options_free
- * function.
- *
- * @return A new Tox_Options object with default options or NULL on failure.
- */
-Tox_Options *tox_options_new(Tox_Err_Options_New *error);
-
-/**
- * @brief Releases all resources associated with an options objects.
- *
- * Passing a pointer that was not returned by tox_options_new results in
- * undefined behaviour.
- */
-void tox_options_free(Tox_Options *options);
-
-/** @} */
-
-/** @{
* @name Creation and destruction
*/
@@ -837,15 +409,16 @@ typedef enum Tox_Err_New {
TOX_ERR_NEW_NULL,
/**
- * The function was unable to allocate enough memory to store the events_alloc
- * structures for the Tox object.
+ * The function was unable to allocate enough memory to store the
+ * internal structures for the Tox object.
*/
TOX_ERR_NEW_MALLOC,
/**
* The function was unable to bind to a port. This may mean that all ports
* have already been bound, e.g. by other Tox instances, or it may mean
- * a permission error. You may be able to gather more information from errno.
+ * a permission error. You may be able to gather more information from
+ * errno.
*/
TOX_ERR_NEW_PORT_ALLOC,
@@ -913,7 +486,7 @@ Tox *tox_new(const Tox_Options *options, Tox_Err_New *error);
void tox_kill(Tox *tox);
/**
- * @brief Calculates the number of bytes required to store the tox instance with
+ * @brief Calculates the number of bytes required to store the Tox instance with
* tox_get_savedata.
*
* This function cannot fail. The result is always greater than 0.
@@ -923,11 +496,12 @@ void tox_kill(Tox *tox);
size_t tox_get_savedata_size(const Tox *tox);
/**
- * @brief Store all information associated with the tox instance to a byte array.
+ * @brief Store all information associated with the Tox instance to a byte
+ * array.
*
- * @param savedata A memory region large enough to store the tox instance
- * data. Call tox_get_savedata_size to find the number of bytes required. If this parameter
- * is NULL, this function has no effect.
+ * @param savedata A memory region large enough to store the Tox instance
+ * data. Call tox_get_savedata_size to find the number of bytes required. If
+ * this parameter is NULL, this function has no effect.
*/
void tox_get_savedata(const Tox *tox, uint8_t savedata[]);
@@ -966,7 +540,7 @@ typedef enum Tox_Err_Bootstrap {
const char *tox_err_bootstrap_to_string(Tox_Err_Bootstrap value);
/**
- * @brief Sends a "get nodes" request to the given bootstrap node with IP, port,
+ * @brief Sends a "nodes request" to the given bootstrap node with IP, port,
* and public key to setup connections.
*
* This function will attempt to connect to the node using UDP. You must use
@@ -1065,14 +639,16 @@ typedef void tox_self_connection_status_cb(Tox *tox, Tox_Connection connection_s
void tox_callback_self_connection_status(Tox *tox, tox_self_connection_status_cb *callback);
/**
- * @brief Return the time in milliseconds before `tox_iterate()` should be called again
- * for optimal performance.
+ * @brief Return the time in milliseconds before `tox_iterate()` should be
+ * called again for optimal performance.
*/
uint32_t tox_iteration_interval(const Tox *tox);
/**
- * @brief The main loop that needs to be run in intervals of `tox_iteration_interval()`
- * milliseconds.
+ * @brief The main loop that needs to be run in intervals of
+ * `tox_iteration_interval()` milliseconds.
+ * @param user_data Any pointer a client wishes the Tox instance to pass into
+ * the event callbacks, including NULL.
*/
void tox_iterate(Tox *tox, void *user_data);
@@ -1172,7 +748,8 @@ const char *tox_err_set_info_to_string(Tox_Err_Set_Info value);
bool tox_self_set_name(Tox *tox, const uint8_t name[], size_t length, Tox_Err_Set_Info *error);
/**
- * @brief Return the length of the current nickname as passed to tox_self_set_name.
+ * @brief Return the length of the current nickname as passed to
+ * tox_self_set_name.
*
* If no nickname was set before calling this function, the name is empty,
* and this function returns 0.
@@ -1206,7 +783,8 @@ bool tox_self_set_status_message(
Tox *tox, const uint8_t status_message[], size_t length, Tox_Err_Set_Info *error);
/**
- * @brief Return the length of the current status message as passed to tox_self_set_status_message.
+ * @brief Return the length of the current status message as passed to
+ * tox_self_set_status_message.
*
* If no status message was set before calling this function, the status
* is empty, and this function returns 0.
@@ -1216,13 +794,14 @@ bool tox_self_set_status_message(
size_t tox_self_get_status_message_size(const Tox *tox);
/**
- * @brief Write the status message set by tox_self_set_status_message to a byte array.
+ * @brief Write the status message set by tox_self_set_status_message to a byte
+ * array.
*
* If no status message was set before calling this function, the status is
* empty, and this function has no effect.
*
- * Call tox_self_get_status_message_size to find out how much memory to allocate for
- * the result.
+ * Call tox_self_get_status_message_size to find out how much memory to allocate
+ * for the result.
*
* @param status_message A valid memory location large enough to hold the
* status message. If this parameter is NULL, the function has no effect.
@@ -1279,8 +858,8 @@ typedef enum Tox_Err_Friend_Add {
TOX_ERR_FRIEND_ADD_OWN_KEY,
/**
- * A friend request has already been sent, or the address belongs to a friend
- * that is already on the friend list.
+ * A friend request has already been sent, or the address belongs to a
+ * friend that is already on the friend list.
*/
TOX_ERR_FRIEND_ADD_ALREADY_SENT,
@@ -1360,7 +939,8 @@ typedef enum Tox_Err_Friend_Delete {
TOX_ERR_FRIEND_DELETE_OK,
/**
- * There was no friend with the given friend number. No friends were deleted.
+ * There was no friend with the given friend number. No friends were
+ * deleted.
*/
TOX_ERR_FRIEND_DELETE_FRIEND_NOT_FOUND,
@@ -1411,14 +991,15 @@ const char *tox_err_friend_by_public_key_to_string(Tox_Err_Friend_By_Public_Key
/**
* @brief Return the friend number associated with that Public Key.
*
- * @return the friend number on success, an unspecified value on failure.
* @param public_key A byte array containing the Public Key.
+ *
+ * @return the friend number on success, an unspecified value on failure.
*/
Tox_Friend_Number tox_friend_by_public_key(const Tox *tox, const uint8_t public_key[TOX_PUBLIC_KEY_SIZE], Tox_Err_Friend_By_Public_Key *error);
/**
- * @brief Checks if a friend with the given friend number exists and returns true if
- * it does.
+ * @brief Checks if a friend with the given friend number exists and returns
+ * true if it does.
*/
bool tox_friend_exists(const Tox *tox, Tox_Friend_Number friend_number);
@@ -1433,7 +1014,8 @@ size_t tox_self_get_friend_list_size(const Tox *tox);
/**
* @brief Copy a list of valid friend numbers into an array.
*
- * Call tox_self_get_friend_list_size to determine the number of elements to allocate.
+ * Call tox_self_get_friend_list_size to determine the number of elements to
+ * allocate.
*
* @param friend_list A memory region with enough space to hold the friend
* list. If this parameter is NULL, this function has no effect.
@@ -1457,7 +1039,8 @@ typedef enum Tox_Err_Friend_Get_Public_Key {
const char *tox_err_friend_get_public_key_to_string(Tox_Err_Friend_Get_Public_Key value);
/**
- * @brief Copies the Public Key associated with a given friend number to a byte array.
+ * @brief Copies the Public Key associated with a given friend number to a byte
+ * array.
*
* @param friend_number The friend number you want the Public Key of.
* @param public_key A memory region of at least TOX_PUBLIC_KEY_SIZE bytes. If
@@ -1486,8 +1069,8 @@ typedef enum Tox_Err_Friend_Get_Last_Online {
const char *tox_err_friend_get_last_online_to_string(Tox_Err_Friend_Get_Last_Online value);
/**
- * @brief Return a unix-time timestamp of the last time the friend associated with a given
- * friend number was seen online.
+ * @brief Return a unix-time timestamp of the last time the friend associated
+ * with a given friend number was seen online.
*
* This function will return UINT64_MAX on error.
*
@@ -1514,8 +1097,9 @@ typedef enum Tox_Err_Friend_Query {
/**
* The pointer parameter for storing the query result (name, message) was
- * NULL. Unlike the `_self_` variants of these functions, which have no effect
- * when a parameter is NULL, these functions return an error in that case.
+ * NULL. Unlike the `_self_` variants of these functions, which have no
+ * effect when a parameter is NULL, these functions return an error in that
+ * case.
*/
TOX_ERR_FRIEND_QUERY_NULL,
@@ -1540,8 +1124,8 @@ size_t tox_friend_get_name_size(
const Tox *tox, Tox_Friend_Number friend_number, Tox_Err_Friend_Query *error);
/**
- * @brief Write the name of the friend designated by the given friend number to a byte
- * array.
+ * @brief Write the name of the friend designated by the given friend number to
+ * a byte array.
*
* Call tox_friend_get_name_size to determine the allocation size for the `name`
* parameter.
@@ -1579,22 +1163,23 @@ void tox_callback_friend_name(Tox *tox, tox_friend_name_cb *callback);
/**
* @brief Return the length of the friend's status message.
*
- * If the friend number isinvalid, the return value is SIZE_MAX.
+ * If the friend number is invalid, the return value is SIZE_MAX.
*/
size_t tox_friend_get_status_message_size(
const Tox *tox, Tox_Friend_Number friend_number, Tox_Err_Friend_Query *error);
/**
- * @brief Write the status message of the friend designated by the given friend number to a byte
- * array.
+ * @brief Write the status message of the friend designated by the given friend
+ * number to a byte array.
*
- * Call tox_friend_get_status_message_size to determine the allocation size for the `status_message`
- * parameter.
+ * Call tox_friend_get_status_message_size to determine the allocation size for
+ * the `status_message` parameter.
*
- * The data written to `status_message` is equal to the data received by the last
- * `friend_status_message` callback.
+ * The data written to `status_message` is equal to the data received by the
+ * last `friend_status_message` callback.
*
- * @param status_message A valid memory region large enough to store the friend's status message.
+ * @param status_message A valid memory region large enough to store the
+ * friend's status message.
*/
bool tox_friend_get_status_message(
const Tox *tox, Tox_Friend_Number friend_number, uint8_t status_message[],
@@ -1604,7 +1189,8 @@ bool tox_friend_get_status_message(
* @param friend_number The friend number of the friend whose status message
* changed.
* @param message A byte array containing the same data as
- * tox_friend_get_status_message would write to its `status_message` parameter.
+ * tox_friend_get_status_message would write to its `status_message`
+ * parameter.
* @param length A value equal to the return value of
* tox_friend_get_status_message_size.
*/
@@ -1814,7 +1400,8 @@ typedef uint32_t Tox_Friend_Message_Id;
* then reassemble the fragments. Messages may not be empty.
*
* The return value of this function is the message ID. If a read receipt is
- * received, the triggered `friend_read_receipt` event will be passed this message ID.
+ * received, the triggered `friend_read_receipt` event will be passed this
+ * message ID.
*
* Message IDs are unique per friend. The first message ID is 0. Message IDs are
* incremented by 1 each time a message is sent. If UINT32_MAX messages were
@@ -1831,7 +1418,8 @@ Tox_Friend_Message_Id tox_friend_send_message(
const uint8_t message[], size_t length, Tox_Err_Friend_Send_Message *error);
/**
- * @param friend_number The friend number of the friend who received the message.
+ * @param friend_number The friend number of the friend who received the
+ * message.
* @param message_id The message ID as returned from tox_friend_send_message
* corresponding to the message sent.
*/
@@ -1875,6 +1463,7 @@ void tox_callback_friend_request(Tox *tox, tox_friend_request_cb *callback);
/**
* @param friend_number The friend number of the friend who sent the message.
+ * @param type The type of the message (normal, action, ...).
* @param message The message data they sent.
* @param length The size of the message byte array.
*/
@@ -1906,10 +1495,10 @@ typedef uint32_t Tox_File_Number;
* primarily for validating cached avatars. This use is highly recommended to
* avoid unnecessary avatar updates.
*
- * If hash is NULL or data is NULL while length is not 0 the function returns false,
- * otherwise it returns true.
+ * If hash is NULL or data is NULL while length is not 0 the function returns
+ * false, otherwise it returns true.
*
- * This function is a wrapper to events_alloc message-digest functions.
+ * This function is a wrapper to internal message-digest functions.
*
* @param hash A valid memory location the hash data. It must be at least
* TOX_HASH_LENGTH bytes in size.
@@ -1923,17 +1512,17 @@ bool tox_hash(uint8_t hash[TOX_HASH_LENGTH], const uint8_t data[], size_t length
/**
* @brief A list of pre-defined file kinds.
*
- * Toxcore itself does not behave differently for different file kinds. These
- * are a hint to the client telling it what use the sender intended for the
- * file. The `kind` parameter in the send function and recv callback are
+ * The Tox library itself does not behave differently for different file kinds.
+ * These are a hint to the client telling it what use the sender intended for
+ * the file. The `kind` parameter in the send function and recv callback are
* `uint32_t`, not Tox_File_Kind, because clients can invent their own file
* kind. Unknown file kinds should be treated as TOX_FILE_KIND_DATA.
*/
enum Tox_File_Kind {
/**
- * Arbitrary file data. Clients can choose to handle it based on the file name
- * or magic or any other way they choose.
+ * Arbitrary file data. Clients can choose to handle it based on the file
+ * name or magic or any other way they choose.
*/
TOX_FILE_KIND_DATA,
@@ -1941,21 +1530,21 @@ enum Tox_File_Kind {
* Avatar file_id. This consists of tox_hash(image).
* Avatar data. This consists of the image data.
*
- * Avatars can be sent at any time the client wishes. Generally, a client will
- * send the avatar to a friend when that friend comes online, and to all
- * friends when the avatar changed. A client can save some traffic by
- * remembering which friend received the updated avatar already and only send
- * it if the friend has an out of date avatar.
+ * Avatars can be sent at any time the client wishes. Generally, a client
+ * will send the avatar to a friend when that friend comes online, and to
+ * all friends when the avatar changed. A client can save some traffic by
+ * remembering which friend received the updated avatar already and only
+ * send it if the friend has an out of date avatar.
*
* Clients who receive avatar send requests can reject it (by sending
* TOX_FILE_CONTROL_CANCEL before any other controls), or accept it (by
- * sending TOX_FILE_CONTROL_RESUME). The file_id of length TOX_HASH_LENGTH bytes
- * (same length as TOX_FILE_ID_LENGTH) will contain the hash. A client can compare
- * this hash with a saved hash and send TOX_FILE_CONTROL_CANCEL to terminate the avatar
- * transfer if it matches.
+ * sending TOX_FILE_CONTROL_RESUME). The file_id of length TOX_HASH_LENGTH
+ * bytes (same length as TOX_FILE_ID_LENGTH) will contain the hash. A client
+ * can compare this hash with a saved hash and send TOX_FILE_CONTROL_CANCEL
+ * to terminate the avatar transfer if it matches.
*
- * When file_size is set to 0 in the transfer request it means that the client
- * has no avatar.
+ * When file_size is set to 0 in the transfer request it means that the
+ * client has no avatar.
*/
TOX_FILE_KIND_AVATAR,
@@ -1964,16 +1553,17 @@ enum Tox_File_Kind {
typedef enum Tox_File_Control {
/**
- * Sent by the receiving side to accept a file send request. Also sent after a
- * TOX_FILE_CONTROL_PAUSE command to continue sending or receiving.
+ * Sent by the receiving side to accept a file send request. Also sent after
+ * a TOX_FILE_CONTROL_PAUSE command to continue sending or receiving.
*/
TOX_FILE_CONTROL_RESUME,
/**
* Sent by clients to pause the file transfer. The initial state of a file
- * transfer is always paused on the receiving side and running on the sending
- * side. If both the sending and receiving side pause the transfer, then both
- * need to send TOX_FILE_CONTROL_RESUME for the transfer to resume.
+ * transfer is always paused on the receiving side and running on the
+ * sending side. If both the sending and receiving side pause the transfer,
+ * then both need to send TOX_FILE_CONTROL_RESUME for the transfer to
+ * resume.
*/
TOX_FILE_CONTROL_PAUSE,
@@ -2005,7 +1595,8 @@ typedef enum Tox_Err_File_Control {
TOX_ERR_FILE_CONTROL_FRIEND_NOT_CONNECTED,
/**
- * No file transfer with the given file number was found for the given friend.
+ * No file transfer with the given file number was found for the given
+ * friend.
*/
TOX_ERR_FILE_CONTROL_NOT_FOUND,
@@ -2089,7 +1680,8 @@ typedef enum Tox_Err_File_Seek {
TOX_ERR_FILE_SEEK_FRIEND_NOT_CONNECTED,
/**
- * No file transfer with the given file number was found for the given friend.
+ * No file transfer with the given file number was found for the given
+ * friend.
*/
TOX_ERR_FILE_SEEK_NOT_FOUND,
@@ -2113,7 +1705,8 @@ typedef enum Tox_Err_File_Seek {
const char *tox_err_file_seek_to_string(Tox_Err_File_Seek value);
/**
- * @brief Sends a file seek control command to a friend for a given file transfer.
+ * @brief Sends a file seek control command to a friend for a given file
+ * transfer.
*
* This function can only be called to resume a file transfer right before
* TOX_FILE_CONTROL_RESUME is sent.
@@ -2144,7 +1737,8 @@ typedef enum Tox_Err_File_Get {
TOX_ERR_FILE_GET_FRIEND_NOT_FOUND,
/**
- * No file transfer with the given file number was found for the given friend.
+ * No file transfer with the given file number was found for the given
+ * friend.
*/
TOX_ERR_FILE_GET_NOT_FOUND,
@@ -2158,8 +1752,8 @@ const char *tox_err_file_get_to_string(Tox_Err_File_Get value);
* @param friend_number The friend number of the friend the file is being
* transferred to or received from.
* @param file_number The friend-specific identifier for the file transfer.
- * @param file_id A memory region of at least TOX_FILE_ID_LENGTH bytes. If
- * this parameter is NULL, this function has no effect.
+ * @param file_id A memory region of at least TOX_FILE_ID_LENGTH bytes. If this
+ * parameter is NULL, this function has no effect.
*
* @return true on success.
*/
@@ -2202,8 +1796,8 @@ typedef enum Tox_Err_File_Send {
TOX_ERR_FILE_SEND_NAME_TOO_LONG,
/**
- * Too many ongoing transfers. The maximum number of concurrent file transfers
- * is 256 per friend per direction (sending and receiving).
+ * Too many ongoing transfers. The maximum number of concurrent file
+ * transfers is 256 per friend per direction (sending and receiving).
*/
TOX_ERR_FILE_SEND_TOO_MANY,
@@ -2214,8 +1808,8 @@ const char *tox_err_file_send_to_string(Tox_Err_File_Send value);
/**
* @brief Send a file transmission request.
*
- * Maximum filename length is TOX_MAX_FILENAME_LENGTH bytes. The filename
- * should generally just be a file name, not a path with directory names.
+ * Maximum filename length is TOX_MAX_FILENAME_LENGTH bytes. The filename should
+ * generally just be a file name, not a path with directory names.
*
* If a non-UINT64_MAX file size is provided, it can be used by both sides to
* determine the sending progress. File size can be set to UINT64_MAX for
@@ -2224,8 +1818,8 @@ const char *tox_err_file_send_to_string(Tox_Err_File_Send value);
* File transmission occurs in chunks, which are requested through the
* `file_chunk_request` event.
*
- * When a friend goes offline, all file transfers associated with the friend are
- * purged from core.
+ * When a friend goes offline, all file transfers associated with the friend get
+ * purged.
*
* If the file contents change during a transfer, the behaviour is unspecified
* in general. What will actually happen depends on the mode in which the file
@@ -2234,15 +1828,16 @@ const char *tox_err_file_send_to_string(Tox_Err_File_Send value);
* - If the file size was increased
* - and sending mode was streaming (file_size = UINT64_MAX), the behaviour
* will be as expected.
- * - and sending mode was file (file_size != UINT64_MAX), the file_chunk_request
- * callback will receive length = 0 when Core thinks the file transfer has
- * finished. If the client remembers the file size as it was when sending the
- * request, it will terminate the transfer normally. If the client re-reads the
- * size, it will think the friend cancelled the transfer.
+ * - and sending mode was file (file_size != UINT64_MAX), the
+ * file_chunk_request callback will receive length = 0 when Tox thinks the
+ * file transfer has finished. If the client remembers the file size as it
+ * was when sending the request, it will terminate the transfer normally. If
+ * the client re-reads the size, it will think the friend cancelled the
+ * transfer.
* - If the file size was decreased
* - and sending mode was streaming, the behaviour is as expected.
* - and sending mode was file, the callback will return 0 at the new
- * (earlier) end-of-file, signalling to the friend that the transfer was
+ * (earlier) end-of-file, signaling to the friend that the transfer was
* cancelled.
* - If the file contents were modified
* - at a position before the current read, the two files (local and remote)
@@ -2255,19 +1850,20 @@ const char *tox_err_file_send_to_string(Tox_Err_File_Send value);
* @param friend_number The friend number of the friend the file send request
* should be sent to.
* @param kind The meaning of the file to be sent.
- * @param file_size Size in bytes of the file the client wants to send, UINT64_MAX if
- * unknown or streaming.
- * @param file_id A file identifier of length TOX_FILE_ID_LENGTH that can be used to
- * uniquely identify file transfers across core restarts. If NULL, a random one will
- * be generated by core. It can then be obtained by using `tox_file_get_file_id()`.
+ * @param file_size Size in bytes of the file the client wants to send,
+ * UINT64_MAX if unknown or streaming.
+ * @param file_id A file identifier of length TOX_FILE_ID_LENGTH that can be
+ * used to uniquely identify file transfers across Tox restarts. If NULL, a
+ * random one will be generated by the library. It can then be obtained by
+ * using `tox_file_get_file_id()`.
* @param filename Name of the file. Does not need to be the actual name. This
* name will be sent along with the file send request.
* @param filename_length Size in bytes of the filename.
*
* @return A file number used as an identifier in subsequent callbacks. This
* number is per friend. File numbers are reused after a transfer terminates.
- * On failure, this function returns an unspecified value. Any pattern in file numbers
- * should not be relied on.
+ * On failure, this function returns an unspecified value. Any pattern in file
+ * numbers should not be relied on.
*/
Tox_File_Number tox_file_send(
Tox *tox, Tox_Friend_Number friend_number, uint32_t kind, uint64_t file_size,
@@ -2297,20 +1893,23 @@ typedef enum Tox_Err_File_Send_Chunk {
TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_CONNECTED,
/**
- * No file transfer with the given file number was found for the given friend.
+ * No file transfer with the given file number was found for the given
+ * friend.
*/
TOX_ERR_FILE_SEND_CHUNK_NOT_FOUND,
/**
* File transfer was found but isn't in a transferring state: (paused, done,
- * broken, etc...) (happens only when not called from the request chunk callback).
+ * broken, etc...) (happens only when not called from the request chunk
+ * callback).
*/
TOX_ERR_FILE_SEND_CHUNK_NOT_TRANSFERRING,
/**
- * Attempted to send more or less data than requested. The requested data size is
- * adjusted according to maximum transmission unit and the expected end of
- * the file. Trying to send less or more than requested will return this error.
+ * Attempted to send more or less data than requested. The requested data
+ * size is adjusted according to maximum transmission unit and the expected
+ * end of the file. Trying to send less or more than requested will return
+ * this error.
*/
TOX_ERR_FILE_SEND_CHUNK_INVALID_LENGTH,
@@ -2334,10 +1933,11 @@ const char *tox_err_file_send_chunk_to_string(Tox_Err_File_Send_Chunk value);
* This function is called in response to the `file_chunk_request` callback. The
* length parameter should be equal to the one received though the callback.
* If it is zero, the transfer is assumed complete. For files with known size,
- * Core will know that the transfer is complete after the last byte has been
+ * Tox will know that the transfer is complete after the last byte has been
* received, so it is not necessary (though not harmful) to send a zero-length
- * chunk to terminate. For streams, core will know that the transfer is finished
- * if a chunk with length less than the length requested in the callback is sent.
+ * chunk to terminate. For streams, Tox will know that the transfer is finished
+ * if a chunk with length less than the length requested in the callback is
+ * sent.
*
* @param friend_number The friend number of the receiving friend for this file.
* @param file_number The file transfer identifier returned by tox_file_send.
@@ -2379,7 +1979,7 @@ typedef void tox_file_chunk_request_cb(
*
* Pass NULL to unset.
*
- * This event is triggered when Core is ready to send more file data.
+ * This event is triggered when Tox is ready to send more file data.
*/
void tox_callback_file_chunk_request(Tox *tox, tox_file_chunk_request_cb *callback);
@@ -2458,6 +2058,7 @@ void tox_callback_file_recv_chunk(Tox *tox, tox_file_recv_chunk_cb *callback);
typedef uint32_t Tox_Conference_Number;
typedef uint32_t Tox_Conference_Peer_Number;
+typedef uint32_t Tox_Conference_Offline_Peer_Number;
/**
* @brief Conference types for the conference_invite event.
@@ -2465,7 +2066,8 @@ typedef uint32_t Tox_Conference_Peer_Number;
typedef enum Tox_Conference_Type {
/**
- * Text-only conferences that must be accepted with the tox_conference_join function.
+ * Text-only conferences that must be accepted with the tox_conference_join
+ * function.
*/
TOX_CONFERENCE_TYPE_TEXT,
@@ -2502,7 +2104,8 @@ typedef void tox_conference_invite_cb(
void tox_callback_conference_invite(Tox *tox, tox_conference_invite_cb *callback);
/**
- * @param conference_number The conference number of the conference to which we have connected.
+ * @param conference_number The conference number of the conference to which we
+ * have connected.
*/
typedef void tox_conference_connected_cb(Tox *tox, Tox_Conference_Number conference_number, void *user_data);
@@ -2555,7 +2158,8 @@ typedef void tox_conference_title_cb(
*
* This event is triggered when a peer changes the conference title.
*
- * If peer_number == UINT32_MAX, then author is unknown (e.g. initial joining the conference).
+ * If peer_number == UINT32_MAX, then author is unknown (e.g. initial joining
+ * the conference).
*/
void tox_callback_conference_title(Tox *tox, tox_conference_title_cb *callback);
@@ -2640,7 +2244,8 @@ const char *tox_err_conference_delete_to_string(Tox_Err_Conference_Delete value)
/**
* @brief This function deletes a conference.
*
- * @param conference_number The conference number of the conference to be deleted.
+ * @param conference_number The conference number of the conference to be
+ * deleted.
*
* @return true on success.
*/
@@ -2682,7 +2287,7 @@ const char *tox_err_conference_peer_query_to_string(Tox_Err_Conference_Peer_Quer
* peer_number for the functions querying these peers. Return value is
* unspecified on failure.
*/
-Tox_Conference_Peer_Number tox_conference_peer_count(
+uint32_t tox_conference_peer_count(
const Tox *tox, Tox_Conference_Number conference_number, Tox_Err_Conference_Peer_Query *error);
/**
@@ -2697,7 +2302,8 @@ size_t tox_conference_peer_get_name_size(
/**
* @brief Copy the name of peer_number who is in conference_number to name.
*
- * Call tox_conference_peer_get_name_size to determine the allocation size for the `name` parameter.
+ * Call tox_conference_peer_get_name_size to determine the allocation size for
+ * the `name` parameter.
*
* @param name A valid memory region large enough to store the peer's name.
*
@@ -2708,7 +2314,8 @@ bool tox_conference_peer_get_name(
uint8_t name[], Tox_Err_Conference_Peer_Query *error);
/**
- * @brief Copy the public key of peer_number who is in conference_number to public_key.
+ * @brief Copy the public key of peer_number who is in conference_number to
+ * public_key.
*
* public_key must be TOX_PUBLIC_KEY_SIZE long.
*
@@ -2744,10 +2351,11 @@ uint32_t tox_conference_offline_peer_count(
*/
size_t tox_conference_offline_peer_get_name_size(
const Tox *tox, Tox_Conference_Number conference_number,
- Tox_Conference_Peer_Number offline_peer_number, Tox_Err_Conference_Peer_Query *error);
+ Tox_Conference_Offline_Peer_Number offline_peer_number, Tox_Err_Conference_Peer_Query *error);
/**
- * @brief Copy the name of offline_peer_number who is in conference_number to name.
+ * @brief Copy the name of offline_peer_number who is in conference_number to
+ * name.
*
* Call tox_conference_offline_peer_get_name_size to determine the allocation
* size for the `name` parameter.
@@ -2757,11 +2365,12 @@ size_t tox_conference_offline_peer_get_name_size(
* @return true on success.
*/
bool tox_conference_offline_peer_get_name(
- const Tox *tox, Tox_Conference_Number conference_number, Tox_Conference_Peer_Number offline_peer_number,
+ const Tox *tox, Tox_Conference_Number conference_number, Tox_Conference_Offline_Peer_Number offline_peer_number,
uint8_t name[], Tox_Err_Conference_Peer_Query *error);
/**
- * @brief Copy the public key of offline_peer_number who is in conference_number to public_key.
+ * @brief Copy the public key of offline_peer_number who is in conference_number
+ * to public_key.
*
* public_key must be TOX_PUBLIC_KEY_SIZE long.
*
@@ -2769,14 +2378,15 @@ bool tox_conference_offline_peer_get_name(
*/
bool tox_conference_offline_peer_get_public_key(
const Tox *tox, Tox_Conference_Number conference_number,
- Tox_Conference_Peer_Number offline_peer_number, uint8_t public_key[TOX_PUBLIC_KEY_SIZE], Tox_Err_Conference_Peer_Query *error);
+ Tox_Conference_Offline_Peer_Number offline_peer_number, uint8_t public_key[TOX_PUBLIC_KEY_SIZE], Tox_Err_Conference_Peer_Query *error);
/**
- * @brief Return a unix-time timestamp of the last time offline_peer_number was seen to be active.
+ * @brief Return a unix-time timestamp of the last time offline_peer_number was
+ * seen to be active.
*/
uint64_t tox_conference_offline_peer_get_last_active(
const Tox *tox, Tox_Conference_Number conference_number,
- Tox_Conference_Peer_Number offline_peer_number, Tox_Err_Conference_Peer_Query *error);
+ Tox_Conference_Offline_Peer_Number offline_peer_number, Tox_Err_Conference_Peer_Query *error);
typedef enum Tox_Err_Conference_Set_Max_Offline {
@@ -2831,7 +2441,8 @@ const char *tox_err_conference_invite_to_string(Tox_Err_Conference_Invite value)
* @brief Invites a friend to a conference.
*
* @param friend_number The friend number of the friend we want to invite.
- * @param conference_number The conference number of the conference we want to invite the friend to.
+ * @param conference_number The conference number of the conference we want to
+ * invite the friend to.
*
* @return true on success.
*/
@@ -2852,7 +2463,8 @@ typedef enum Tox_Err_Conference_Join {
TOX_ERR_CONFERENCE_JOIN_INVALID_LENGTH,
/**
- * The conference is not the expected type. This indicates an invalid cookie.
+ * The conference is not the expected type. This indicates an invalid
+ * cookie.
*/
TOX_ERR_CONFERENCE_JOIN_WRONG_TYPE,
@@ -2876,6 +2488,11 @@ typedef enum Tox_Err_Conference_Join {
*/
TOX_ERR_CONFERENCE_JOIN_FAIL_SEND,
+ /**
+ * The cookie passed was NULL.
+ */
+ TOX_ERR_CONFERENCE_JOIN_NULL,
+
} Tox_Err_Conference_Join;
const char *tox_err_conference_join_to_string(Tox_Err_Conference_Join value);
@@ -2887,7 +2504,7 @@ const char *tox_err_conference_join_to_string(Tox_Err_Conference_Join value);
* to it until a handshaking procedure has been completed. A
* `conference_connected` event will then occur for the conference. The client
* will then remain connected to the conference until the conference is deleted,
- * even across core restarts. Many operations on a conference will fail with a
+ * even across Tox restarts. Many operations on a conference will fail with a
* corresponding error if attempted on a conference to which the client is not
* yet connected.
*
@@ -2995,9 +2612,11 @@ size_t tox_conference_get_title_size(
const Tox *tox, Tox_Conference_Number conference_number, Tox_Err_Conference_Title *error);
/**
- * @brief Write the title designated by the given conference number to a byte array.
+ * @brief Write the title designated by the given conference number to a byte
+ * array.
*
- * Call tox_conference_get_title_size to determine the allocation size for the `title` parameter.
+ * Call tox_conference_get_title_size to determine the allocation size for the
+ * `title` parameter.
*
* The data written to `title` is equal to the data received by the last
* `conference_title` callback.
@@ -3013,7 +2632,8 @@ bool tox_conference_get_title(
Tox_Err_Conference_Title *error);
/**
- * @brief Set the conference title and broadcast it to the rest of the conference.
+ * @brief Set the conference title and broadcast it to the rest of the
+ * conference.
*
* Title length cannot be longer than TOX_MAX_NAME_LENGTH.
*
@@ -3027,7 +2647,8 @@ bool tox_conference_set_title(
/**
* @brief Return the number of conferences in the Tox instance.
*
- * This should be used to determine how much memory to allocate for `tox_conference_get_chatlist`.
+ * This should be used to determine how much memory to allocate for
+ * `tox_conference_get_chatlist`.
*/
size_t tox_conference_get_chatlist_size(const Tox *tox);
@@ -3037,8 +2658,8 @@ size_t tox_conference_get_chatlist_size(const Tox *tox);
* Determine how much space to allocate for the array with the
* `tox_conference_get_chatlist_size` function.
*
- * Note that `tox_get_savedata` saves all connected conferences;
- * when toxcore is created from savedata in which conferences were saved, those
+ * Note that `tox_get_savedata` saves all connected conferences; when a Tox
+ * instance is created from savedata in which conferences were saved, those
* conferences will be connected at startup, and will be listed by
* `tox_conference_get_chatlist`.
*
@@ -3048,7 +2669,8 @@ size_t tox_conference_get_chatlist_size(const Tox *tox);
void tox_conference_get_chatlist(const Tox *tox, Tox_Conference_Number chatlist[]);
/**
- * @brief Returns the type of conference (Tox_Conference_Type) that conference_number is.
+ * @brief Returns the type of conference (Tox_Conference_Type) that
+ * conference_number is.
*
* Return value is unspecified on failure.
*/
@@ -3118,18 +2740,22 @@ const char *tox_err_conference_by_id_to_string(Tox_Err_Conference_By_Id value);
Tox_Conference_Number tox_conference_by_id(
const Tox *tox, const uint8_t id[TOX_CONFERENCE_ID_SIZE], Tox_Err_Conference_By_Id *error);
+#ifndef TOX_HIDE_DEPRECATED
/**
* @brief Get the conference unique ID.
*
* If uid is NULL, this function has no effect.
*
- * @param uid A memory region large enough to store TOX_CONFERENCE_UID_SIZE bytes.
+ * @param uid A memory region large enough to store TOX_CONFERENCE_UID_SIZE
+ * bytes.
*
* @return true on success.
- * @deprecated use tox_conference_get_id instead (exactly the same function, just renamed).
+ * @deprecated use tox_conference_get_id instead (exactly the same function,
+ * just renamed).
*/
bool tox_conference_get_uid(
const Tox *tox, Tox_Conference_Number conference_number, uint8_t uid[TOX_CONFERENCE_UID_SIZE]);
+#endif /* TOX_HIDE_DEPRECATED */
typedef enum Tox_Err_Conference_By_Uid {
@@ -3152,16 +2778,20 @@ typedef enum Tox_Err_Conference_By_Uid {
const char *tox_err_conference_by_uid_to_string(Tox_Err_Conference_By_Uid value);
+#ifndef TOX_HIDE_DEPRECATED
/**
* @brief Return the conference number associated with the specified uid.
*
- * @param uid A byte array containing the conference id (TOX_CONFERENCE_UID_SIZE).
+ * @param uid A byte array containing the conference id
+ * (TOX_CONFERENCE_UID_SIZE).
*
* @return the conference number on success, an unspecified value on failure.
- * @deprecated use tox_conference_by_id instead (exactly the same function, just renamed).
+ * @deprecated use tox_conference_by_id instead (exactly the same function,
+ * just renamed).
*/
Tox_Conference_Number tox_conference_by_uid(
const Tox *tox, const uint8_t uid[TOX_CONFERENCE_UID_SIZE], Tox_Err_Conference_By_Uid *error);
+#endif /* TOX_HIDE_DEPRECATED */
/** @} */
@@ -3192,8 +2822,9 @@ typedef enum Tox_Err_Friend_Custom_Packet {
TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_CONNECTED,
/**
- * The first byte of data was not in the specified range for the packet type.
- * This range is 192-254 for lossy, and 69, 160-191 for lossless packets.
+ * The first byte of data was not one of the permitted values;
+ * for lossy packets the first byte must be in the range 192-254,
+ * and for lossless packets it must be either 69 or in the range 160-191.
*/
TOX_ERR_FRIEND_CUSTOM_PACKET_INVALID,
@@ -3244,7 +2875,7 @@ bool tox_friend_send_lossy_packet(
/**
* @brief Send a custom lossless packet to a friend.
*
- * The first byte of data must be in the range 69, 160-191. Maximum length of a
+ * The first byte of data must be either 69 or in the range 160-191. Maximum length of a
* custom packet is TOX_MAX_CUSTOM_PACKET_SIZE.
*
* Lossless packet behaviour is comparable to TCP (reliability, arrive in order)
@@ -3263,6 +2894,9 @@ bool tox_friend_send_lossless_packet(
Tox_Err_Friend_Custom_Packet *error);
/**
+ * tox_callback_friend_lossy_packet is the compatibility function to
+ * set the callback for all packet IDs except those reserved for ToxAV.
+ *
* @param friend_number The friend number of the friend who sent a lossy packet.
* @param data A byte array containing the received packet data.
* @param length The length of the packet data byte array.
@@ -3322,7 +2956,8 @@ const char *tox_err_get_port_to_string(Tox_Err_Get_Port value);
* @brief Writes the temporary DHT public key of this instance to a byte array.
*
* This can be used in combination with an externally accessible IP address and
- * the bound port (from tox_self_get_udp_port) to run a temporary bootstrap node.
+ * the bound port (from tox_self_get_udp_port) to run a temporary bootstrap
+ * node.
*
* Be aware that every time a new instance is created, the DHT public key
* changes, meaning this cannot be used to run a permanent bootstrap node.
@@ -3435,22 +3070,24 @@ uint32_t tox_group_peer_public_key_size(void);
typedef enum Tox_Group_Privacy_State {
/**
- * The group is considered to be public. Anyone may join the group using the Chat ID.
+ * The group is considered to be public. Anyone may join the group using
+ * the Chat ID.
*
- * If the group is in this state, even if the Chat ID is never explicitly shared
- * with someone outside of the group, information including the Chat ID, IP addresses,
- * and peer ID's (but not Tox ID's) is visible to anyone with access to a node
- * storing a DHT entry for the given group.
+ * If the group is in this state, even if the Chat ID is never explicitly
+ * shared with someone outside of the group, information including the Chat
+ * ID, IP addresses, and peer ID's (but not Tox ID's) is visible to anyone
+ * with access to a node storing a DHT entry for the given group.
*/
TOX_GROUP_PRIVACY_STATE_PUBLIC,
/**
- * The group is considered to be private. The only way to join the group is by having
- * someone in your contact list send you an invite.
+ * The group is considered to be private. The only way to join the group is
+ * by having someone in your contact list send you an invite.
*
- * If the group is in this state, no group information (mentioned above) is present in the DHT;
- * the DHT is not used for any purpose at all. If a public group is set to private,
- * all DHT information related to the group will expire shortly.
+ * If the group is in this state, no group information (mentioned above) is
+ * present in the DHT; the DHT is not used for any purpose at all. If a
+ * public group is set to private, all DHT information related to the group
+ * will expire shortly.
*/
TOX_GROUP_PRIVACY_STATE_PRIVATE,
@@ -3460,16 +3097,20 @@ const char *tox_group_privacy_state_to_string(Tox_Group_Privacy_State value);
/**
* Represents the state of the group topic lock.
+ *
+ * The default is enabled.
*/
typedef enum Tox_Group_Topic_Lock {
/**
- * The topic lock is enabled. Only peers with the founder and moderator roles may set the topic.
+ * The topic lock is enabled. Only peers with the founder and moderator
+ * roles may set the topic.
*/
TOX_GROUP_TOPIC_LOCK_ENABLED,
/**
- * The topic lock is disabled. All peers except those with the observer role may set the topic.
+ * The topic lock is disabled. All peers except those with the observer role
+ * may set the topic.
*/
TOX_GROUP_TOPIC_LOCK_DISABLED,
@@ -3478,8 +3119,9 @@ typedef enum Tox_Group_Topic_Lock {
const char *tox_group_topic_lock_to_string(Tox_Group_Topic_Lock value);
/**
- * Represents the group voice state, which determines which Group Roles have permission to speak
- * in the group chat. The voice state does not have any effect private messages or topic setting.
+ * Represents the group voice state, which determines which Group Roles have
+ * permission to speak in the group chat. The voice state does not have any
+ * effect private messages or topic setting.
*/
typedef enum Tox_Group_Voice_State {
/**
@@ -3503,14 +3145,15 @@ const char *tox_group_voice_state_to_string(Tox_Group_Voice_State value);
/**
* Represents group roles.
*
- * Roles are hierarchical in that each role has a set of privileges plus all the privileges
- * of the roles below it.
+ * Roles are hierarchical in that each role has a set of privileges plus all the
+ * privileges of the roles below it.
*/
typedef enum Tox_Group_Role {
/**
- * May kick all other peers as well as set their role to anything (except founder).
- * Founders may also set the group password, toggle the privacy state, and set the peer limit.
+ * May kick all other peers as well as set their role to anything (except
+ * founder). Founders may also set the group password, toggle the privacy
+ * state, and set the peer limit.
*/
TOX_GROUP_ROLE_FOUNDER,
@@ -3526,7 +3169,8 @@ typedef enum Tox_Group_Role {
TOX_GROUP_ROLE_USER,
/**
- * May observe the group and ignore peers; may not communicate with other peers or with the group.
+ * May observe the group and ignore peers; may not communicate with other
+ * peers or with the group.
*/
TOX_GROUP_ROLE_OBSERVER,
@@ -3548,7 +3192,8 @@ typedef enum Tox_Err_Group_New {
TOX_ERR_GROUP_NEW_OK,
/**
- * name exceeds TOX_MAX_NAME_LENGTH or group_name exceeded TOX_GROUP_MAX_GROUP_NAME_LENGTH.
+ * name exceeds TOX_MAX_NAME_LENGTH or group_name exceeded
+ * TOX_GROUP_MAX_GROUP_NAME_LENGTH.
*/
TOX_ERR_GROUP_NEW_TOO_LONG,
@@ -3563,13 +3208,14 @@ typedef enum Tox_Err_Group_New {
TOX_ERR_GROUP_NEW_INIT,
/**
- * The group state failed to initialize. This usually indicates that something went wrong
- * related to cryptographic signing.
+ * The group state failed to initialize. This usually indicates that
+ * something went wrong related to cryptographic signing.
*/
TOX_ERR_GROUP_NEW_STATE,
/**
- * The group failed to announce to the DHT. This indicates a network related error.
+ * The group failed to announce to the DHT. This indicates a network related
+ * error.
*/
TOX_ERR_GROUP_NEW_ANNOUNCE,
@@ -3584,18 +3230,19 @@ const char *tox_err_group_new_to_string(Tox_Err_Group_New value);
*
* The caller of this function has Founder role privileges.
*
- * The client should initiate its peer list with self info after calling this function, as
- * the peer_join callback will not be triggered.
+ * The client should initiate its peer list with self info after calling this
+ * function, as the peer_join callback will not be triggered.
*
- * @param privacy_state The privacy state of the group. If this is set to TOX_GROUP_PRIVACY_STATE_PUBLIC,
- * the group will attempt to announce itself to the DHT and anyone with the Chat ID may join.
- * Otherwise a friend invite will be required to join the group.
+ * @param privacy_state The privacy state of the group. If this is set to
+ * TOX_GROUP_PRIVACY_STATE_PUBLIC, the group will attempt to announce itself
+ * to the DHT and anyone with the Chat ID may join. Otherwise a friend invite
+ * will be required to join the group.
* @param group_name The name of the group. The name must be non-NULL.
- * @param group_name_length The length of the group name. This must be greater than zero and no larger than
- * TOX_GROUP_MAX_GROUP_NAME_LENGTH.
+ * @param group_name_length The length of the group name. This must be greater
+ * than zero and no larger than TOX_GROUP_MAX_GROUP_NAME_LENGTH.
* @param name The name of the peer creating the group.
- * @param name_length The length of the peer's name. This must be greater than zero and no larger
- * than TOX_MAX_NAME_LENGTH.
+ * @param name_length The length of the peer's name. This must be greater than
+ * zero and no larger than TOX_MAX_NAME_LENGTH.
*
* @return group_number on success, UINT32_MAX on failure.
*/
@@ -3617,8 +3264,7 @@ typedef enum Tox_Err_Group_Join {
TOX_ERR_GROUP_JOIN_INIT,
/**
- * The chat_id pointer is set to NULL or a group with chat_id already exists. This usually
- * happens if the client attempts to create multiple sessions for the same group.
+ * The chat_id pointer is set to NULL.
*/
TOX_ERR_GROUP_JOIN_BAD_CHAT_ID,
@@ -3633,7 +3279,8 @@ typedef enum Tox_Err_Group_Join {
TOX_ERR_GROUP_JOIN_TOO_LONG,
/**
- * Failed to set password. This usually occurs if the password exceeds TOX_GROUP_MAX_PASSWORD_SIZE.
+ * Failed to set password. This usually occurs if the password exceeds
+ * TOX_GROUP_MAX_PASSWORD_SIZE.
*/
TOX_ERR_GROUP_JOIN_PASSWORD,
@@ -3647,19 +3294,25 @@ typedef enum Tox_Err_Group_Join {
const char *tox_err_group_join_to_string(Tox_Err_Group_Join value);
/**
- * Joins a group chat with specified Chat ID.
+ * Joins a group chat with specified Chat ID or reconnects to an existing group.
*
- * This function creates a new group chat object, adds it to the chats array, and sends
- * a DHT announcement to find peers in the group associated with chat_id. Once a peer has been
- * found a join attempt will be initiated.
+ * This function creates a new group chat object, adds it to the chats array,
+ * and sends a DHT announcement to find peers in the group associated with
+ * chat_id. Once a peer has been found a join attempt will be initiated.
*
- * @param chat_id The Chat ID of the group you wish to join. This must be TOX_GROUP_CHAT_ID_SIZE bytes.
- * @param password The password required to join the group. Set to NULL if no password is required.
- * @param password_length The length of the password. If length is equal to zero,
- * the password parameter is ignored. length must be no larger than TOX_GROUP_MAX_PASSWORD_SIZE.
+ * If a group with the specified Chat ID already exists, this function will attempt
+ * to reconnect to the group.
+ *
+ * @param chat_id The Chat ID of the group you wish to join. This must be
+ * TOX_GROUP_CHAT_ID_SIZE bytes.
+ * @param password The password required to join the group. Set to NULL if no
+ * password is required.
+ * @param password_length The length of the password. If length is equal to
+ * zero, the password parameter is ignored. length must be no larger than
+ * TOX_GROUP_MAX_PASSWORD_SIZE.
* @param name The name of the peer joining the group.
- * @param name_length The length of the peer's name. This must be greater than zero and no larger
- * than TOX_MAX_NAME_LENGTH.
+ * @param name_length The length of the peer's name. This must be greater than
+ * zero and no larger than TOX_MAX_NAME_LENGTH.
*
* @return group_number on success, UINT32_MAX on failure.
*/
@@ -3686,8 +3339,8 @@ typedef enum Tox_Err_Group_Is_Connected {
const char *tox_err_group_is_connected_to_string(Tox_Err_Group_Is_Connected value);
/**
- * Returns true if the group chat is currently connected or attempting to connect to other peers
- * in the group.
+ * Returns true if the group chat is currently connected or attempting to
+ * connect to other peers in the group.
*
* @param group_number The group number of the designated group.
*/
@@ -3714,7 +3367,8 @@ typedef enum Tox_Err_Group_Disconnect {
const char *tox_err_group_disconnect_to_string(Tox_Err_Group_Disconnect value);
/**
- * Disconnects from a group chat while retaining the group state and credentials.
+ * Disconnects from a group chat while retaining the group state and
+ * credentials.
*
* Returns true if we successfully disconnect from the group.
*
@@ -3743,17 +3397,22 @@ typedef enum Tox_Err_Group_Reconnect {
const char *tox_err_group_reconnect_to_string(Tox_Err_Group_Reconnect value);
+#ifndef TOX_HIDE_DEPRECATED
/**
* Reconnects to a group.
*
- * This function disconnects from all peers in the group, then attempts to reconnect with the group.
- * The caller's state is not changed (i.e. name, status, role, chat public key etc.).
+ * This function disconnects from all peers in the group, then attempts to
+ * reconnect with the group. The caller's state is not changed (i.e. name,
+ * status, role, chat public key etc.).
*
* @param group_number The group number of the group we wish to reconnect to.
*
* @return true on success.
+ *
+ * @deprecated Use `tox_group_join` instead.
*/
bool tox_group_reconnect(Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_Reconnect *error);
+#endif /* TOX_HIDE_DEPRECATED */
typedef enum Tox_Err_Group_Leave {
@@ -3783,14 +3442,16 @@ const char *tox_err_group_leave_to_string(Tox_Err_Group_Leave value);
/**
* Leaves a group.
*
- * This function sends a parting packet containing a custom (non-obligatory) message to all
- * peers in a group, and deletes the group from the chat array. All group state information is permanently
- * lost, including keys and role credentials.
+ * This function sends a parting packet containing a custom (non-obligatory)
+ * message to all peers in a group, and deletes the group from the chat array.
+ * All group state information is permanently lost, including keys and role
+ * credentials.
*
* @param group_number The group number of the group we wish to leave.
- * @param part_message The parting message to be sent to all the peers. Set to NULL if we do not wish to
- * send a parting message.
- * @param length The length of the parting message. Set to 0 if we do not wish to send a parting message.
+ * @param part_message The parting message to be sent to all the peers. Set to
+ * NULL if we do not wish to send a parting message.
+ * @param length The length of the parting message. Set to 0 if we do not wish
+ * to send a parting message.
*
* @return true if the group chat instance is successfully deleted.
*/
@@ -3859,10 +3520,11 @@ typedef enum Tox_Err_Group_Self_Name_Set {
const char *tox_err_group_self_name_set_to_string(Tox_Err_Group_Self_Name_Set value);
/**
- * Set the client's nickname for the group instance designated by the given group number.
+ * Set the client's nickname for the group instance designated by the given
+ * group number.
*
- * Nickname length cannot exceed TOX_MAX_NAME_LENGTH. If length is equal to zero or name is a NULL
- * pointer, the function call will fail.
+ * Nickname length cannot exceed TOX_MAX_NAME_LENGTH. If length is equal to
+ * zero or name is a NULL pointer, the function call will fail.
*
* @param name A byte array containing the new nickname.
* @param length The size of the name byte array.
@@ -3875,8 +3537,8 @@ bool tox_group_self_set_name(
Tox_Err_Group_Self_Name_Set *error);
/**
- * Return the length of the client's current nickname for the group instance designated
- * by group_number as passed to tox_group_self_set_name.
+ * Return the length of the client's current nickname for the group instance
+ * designated by group_number as passed to tox_group_self_set_name.
*
* If no nickname was set before calling this function, the name is empty,
* and this function returns 0.
@@ -3891,7 +3553,8 @@ size_t tox_group_self_get_name_size(const Tox *tox, Tox_Group_Number group_numbe
* If no nickname was set before calling this function, the name is empty,
* and this function has no effect.
*
- * Call tox_group_self_get_name_size to find out how much memory to allocate for the result.
+ * Call tox_group_self_get_name_size to find out how much memory to allocate for
+ * the result.
*
* @param name A valid memory location large enough to hold the nickname.
* If this parameter is NULL, the function has no effect.
@@ -3927,7 +3590,8 @@ typedef enum Tox_Err_Group_Self_Status_Set {
const char *tox_err_group_self_status_set_to_string(Tox_Err_Group_Self_Status_Set value);
/**
- * Set the client's status for the group instance. Status must be a Tox_User_Status.
+ * Set the client's status for the group instance. Status must be a
+ * Tox_User_Status.
*
* @return true on success.
*/
@@ -3953,13 +3617,16 @@ Tox_Group_Role tox_group_self_get_role(const Tox *tox, Tox_Group_Number group_nu
Tox_Group_Peer_Number tox_group_self_get_peer_id(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_Self_Query *error);
/**
- * Write the client's group public key designated by the given group number to a byte array.
+ * Write the client's group public key designated by the given group number to
+ * a byte array.
*
- * This key will be permanently tied to the client's identity for this particular group until
- * the client explicitly leaves the group. This key is the only way for other peers to reliably
- * identify the client across client restarts.
+ * This key will be permanently tied to the client's identity for this
+ * particular group until the client explicitly leaves the group. This key is
+ * the only way for other peers to reliably identify the client across client
+ * restarts.
*
- * `public_key` should have room for at least TOX_GROUP_PEER_PUBLIC_KEY_SIZE bytes.
+ * `public_key` should have room for at least TOX_GROUP_PEER_PUBLIC_KEY_SIZE
+ * bytes.
*
* @param public_key A valid memory region large enough to store the public key.
* If this parameter is NULL, this function call has no effect.
@@ -4000,8 +3667,8 @@ typedef enum Tox_Err_Group_Peer_Query {
const char *tox_err_group_peer_query_to_string(Tox_Err_Group_Peer_Query value);
/**
- * Return the length of the peer's name. If the group number or ID is invalid, the
- * return value is unspecified.
+ * Return the length of the peer's name. If the group number or ID is invalid,
+ * the return value is unspecified.
*
* @param group_number The group number of the group we wish to query.
* @param peer_id The ID of the peer whose name length we want to retrieve.
@@ -4016,7 +3683,8 @@ size_t tox_group_peer_get_name_size(const Tox *tox, Tox_Group_Number group_numbe
* Write the name of the peer designated by the given ID to a byte
* array.
*
- * Call tox_group_peer_get_name_size to determine the allocation size for the `name` parameter.
+ * Call tox_group_peer_get_name_size to determine the allocation size for the
+ * `name` parameter.
*
* The data written to `name` is equal to the data received by the last
* `group_peer_name` callback.
@@ -4045,8 +3713,8 @@ Tox_User_Status tox_group_peer_get_status(const Tox *tox, Tox_Group_Number group
Tox_Err_Group_Peer_Query *error);
/**
- * Return the peer's role (user/moderator/founder...). If the ID or group number is
- * invalid, the return value is unspecified.
+ * Return the peer's role (user/moderator/founder...). If the ID or group number
+ * is invalid, the return value is unspecified.
*
* @param group_number The group number of the group we wish to query.
* @param peer_id The ID of the peer whose role we wish to query.
@@ -4060,8 +3728,9 @@ Tox_Group_Role tox_group_peer_get_role(const Tox *tox, Tox_Group_Number group_nu
/**
* Return the type of connection we have established with a peer.
*
- * If `peer_id` designates ourself, the return value indicates whether we're capable
- * of making UDP connections with other peers, or are limited to TCP connections.
+ * If `peer_id` designates ourself, the return value indicates whether we're
+ * capable of making UDP connections with other peers, or are limited to TCP
+ * connections.
*
* @param group_number The group number of the group we wish to query.
* @param peer_id The ID of the peer whose connection status we wish to query.
@@ -4070,13 +3739,15 @@ Tox_Connection tox_group_peer_get_connection_status(const Tox *tox, Tox_Group_Nu
Tox_Err_Group_Peer_Query *error);
/**
- * Write the group public key with the designated peer_id for the designated group number to public_key.
+ * Write the group public key with the designated peer_id for the designated
+ * group number to public_key.
*
- * This key will be permanently tied to a particular peer until they explicitly leave the group and is
- * the only way to reliably identify the same peer across client restarts.
+ * This key will be permanently tied to a particular peer until they explicitly
+ * leave the group and is the only way to reliably identify the same peer across
+ * client restarts.
*
- * `public_key` should have room for at least TOX_GROUP_PEER_PUBLIC_KEY_SIZE bytes. If `public_key` is null
- * this function has no effect.
+ * `public_key` should have room for at least TOX_GROUP_PEER_PUBLIC_KEY_SIZE
+ * bytes. If `public_key` is NULL this function has no effect.
*
* @param group_number The group number of the group we wish to query.
* @param peer_id The ID of the peer whose public key we wish to retrieve.
@@ -4090,14 +3761,15 @@ bool tox_group_peer_get_public_key(
uint8_t public_key[TOX_PUBLIC_KEY_SIZE], Tox_Err_Group_Peer_Query *error);
/**
- * @param group_number The group number of the group the name change is intended for.
+ * @param group_number The group number of the group the name change is intended
+ * for.
* @param peer_id The ID of the peer who has changed their name.
* @param name The name data.
- * @param length The length of the name.
+ * @param name_length The length of the name.
*/
typedef void tox_group_peer_name_cb(
Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id,
- const uint8_t name[], size_t length, void *user_data);
+ const uint8_t name[], size_t name_length, void *user_data);
/**
* Set the callback for the `group_peer_name` event. Pass NULL to unset.
@@ -4107,7 +3779,8 @@ typedef void tox_group_peer_name_cb(
void tox_callback_group_peer_name(Tox *tox, tox_group_peer_name_cb *callback);
/**
- * @param group_number The group number of the group the status change is intended for.
+ * @param group_number The group number of the group the status change is
+ * intended for.
* @param peer_id The ID of the peer who has changed their status.
* @param status The new status of the peer.
*/
@@ -4130,21 +3803,21 @@ void tox_callback_group_peer_status(Tox *tox, tox_group_peer_status_cb *callback
/**
* General error codes for group state get and size functions.
*/
-typedef enum Tox_Err_Group_State_Queries {
+typedef enum Tox_Err_Group_State_Query {
/**
* The function returned successfully.
*/
- TOX_ERR_GROUP_STATE_QUERIES_OK,
+ TOX_ERR_GROUP_STATE_QUERY_OK,
/**
* The group number passed did not designate a valid group.
*/
- TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND,
+ TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND,
-} Tox_Err_Group_State_Queries;
+} Tox_Err_Group_State_Query;
-const char *tox_err_group_state_queries_to_string(Tox_Err_Group_State_Queries value);
+const char *tox_err_group_state_query_to_string(Tox_Err_Group_State_Query value);
/**
* Error codes for group topic setting.
@@ -4172,7 +3845,8 @@ typedef enum Tox_Err_Group_Topic_Set {
TOX_ERR_GROUP_TOPIC_SET_PERMISSIONS,
/**
- * The packet could not be created. This error is usually related to cryptographic signing.
+ * The packet could not be created. This error is usually related to
+ * cryptographic signing.
*/
TOX_ERR_GROUP_TOPIC_SET_FAIL_CREATE,
@@ -4193,8 +3867,8 @@ const char *tox_err_group_topic_set_to_string(Tox_Err_Group_Topic_Set value);
/**
* Set the group topic and broadcast it to the rest of the group.
*
- * topic length cannot be longer than TOX_GROUP_MAX_TOPIC_LENGTH. If length is equal to zero or
- * topic is set to NULL, the topic will be unset.
+ * Topic length cannot be longer than TOX_GROUP_MAX_TOPIC_LENGTH. If the length
+ * is equal to zero or topic is set to NULL, the topic will be unset.
*
* @return true on success.
*/
@@ -4210,12 +3884,13 @@ bool tox_group_set_topic(
* The return value is equal to the `length` argument received by the last
* `group_topic` callback.
*/
-size_t tox_group_get_topic_size(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_State_Queries *error);
+size_t tox_group_get_topic_size(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_State_Query *error);
/**
* Write the topic designated by the given group number to a byte array.
*
- * Call tox_group_get_topic_size to determine the allocation size for the `topic` parameter.
+ * Call tox_group_get_topic_size to determine the allocation size for the
+ * `topic` parameter.
*
* The data written to `topic` is equal to the data received by the last
* `group_topic` callback.
@@ -4227,18 +3902,19 @@ size_t tox_group_get_topic_size(const Tox *tox, Tox_Group_Number group_number, T
*/
bool tox_group_get_topic(
const Tox *tox, Tox_Group_Number group_number,
- uint8_t topic[], Tox_Err_Group_State_Queries *error);
+ uint8_t topic[], Tox_Err_Group_State_Query *error);
/**
- * @param group_number The group number of the group the topic change is intended for.
- * @param peer_id The ID of the peer who changed the topic. If the peer who set the topic
- * is not present in our peer list this value will be set to 0.
+ * @param group_number The group number of the group the topic change is
+ * intended for.
+ * @param peer_id The ID of the peer who changed the topic. If the peer who set
+ * the topic is not present in our peer list this value will be set to 0.
* @param topic The topic data.
- * @param length The topic length.
+ * @param topic_length The topic length.
*/
typedef void tox_group_topic_cb(
Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id,
- const uint8_t topic[], size_t length,
+ const uint8_t topic[], size_t topic_length,
void *user_data);
/**
@@ -4252,12 +3928,14 @@ void tox_callback_group_topic(Tox *tox, tox_group_topic_cb *callback);
* Return the length of the group name. If the group number is invalid, the
* return value is unspecified.
*/
-size_t tox_group_get_name_size(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_State_Queries *error);
+size_t tox_group_get_name_size(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_State_Query *error);
/**
- * Write the name of the group designated by the given group number to a byte array.
+ * Write the name of the group designated by the given group number to a byte
+ * array.
*
- * Call tox_group_get_name_size to determine the allocation size for the `name` parameter.
+ * Call tox_group_get_name_size to determine the allocation size for the `name`
+ * parameter.
*
* @param name A valid memory region large enough to store the group name.
* If this parameter is NULL, this function call has no effect.
@@ -4266,7 +3944,7 @@ size_t tox_group_get_name_size(const Tox *tox, Tox_Group_Number group_number, To
*/
bool tox_group_get_name(
const Tox *tox, Tox_Group_Number group_number,
- uint8_t name[], Tox_Err_Group_State_Queries *error);
+ uint8_t name[], Tox_Err_Group_State_Query *error);
/**
* Write the Chat ID designated by the given group number to a byte array.
@@ -4280,7 +3958,7 @@ bool tox_group_get_name(
*/
bool tox_group_get_chat_id(
const Tox *tox, Tox_Group_Number group_number, uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE],
- Tox_Err_Group_State_Queries *error);
+ Tox_Err_Group_State_Query *error);
/**
* Return the number of groups in the Tox chats array.
@@ -4288,19 +3966,21 @@ bool tox_group_get_chat_id(
uint32_t tox_group_get_number_groups(const Tox *tox);
/**
- * Return the privacy state of the group designated by the given group number. If group number
- * is invalid, the return value is unspecified.
+ * Return the privacy state of the group designated by the given group number.
+ * If group number is invalid, the return value is unspecified.
*
* The value returned is equal to the data received by the last
* `group_privacy_state` callback.
*
- * @see the `Group chat founder controls` section for the respective set function.
+ * @see the `Group chat Founder controls` section for the respective set
+ * function.
*/
Tox_Group_Privacy_State tox_group_get_privacy_state(const Tox *tox, Tox_Group_Number group_number,
- Tox_Err_Group_State_Queries *error);
+ Tox_Err_Group_State_Query *error);
/**
- * @param group_number The group number of the group the privacy state is intended for.
+ * @param group_number The group number of the group the privacy state is
+ * intended for.
* @param privacy_state The new privacy state.
*/
typedef void tox_group_privacy_state_cb(Tox *tox, Tox_Group_Number group_number, Tox_Group_Privacy_State privacy_state,
@@ -4314,18 +3994,21 @@ typedef void tox_group_privacy_state_cb(Tox *tox, Tox_Group_Number group_number,
void tox_callback_group_privacy_state(Tox *tox, tox_group_privacy_state_cb *callback);
/**
- * Return the voice state of the group designated by the given group number. If group number
- * is invalid, the return value is unspecified.
+ * Return the voice state of the group designated by the given group number. If
+ * group number is invalid, the return value is unspecified.
*
- * The value returned is equal to the data received by the last `group_voice_state` callback.
+ * The value returned is equal to the data received by the last
+ * `group_voice_state` callback.
*
- * @see the `Group chat founder controls` section for the respective set function.
+ * @see the `Group chat Founder controls` section for the respective set
+ * function.
*/
Tox_Group_Voice_State tox_group_get_voice_state(const Tox *tox, Tox_Group_Number group_number,
- Tox_Err_Group_State_Queries *error);
+ Tox_Err_Group_State_Query *error);
/**
- * @param group_number The group number of the group the voice state change is intended for.
+ * @param group_number The group number of the group the voice state change is
+ * intended for.
* @param voice_state The new voice state.
*/
typedef void tox_group_voice_state_cb(Tox *tox, Tox_Group_Number group_number, Tox_Group_Voice_State voice_state,
@@ -4339,19 +4022,22 @@ typedef void tox_group_voice_state_cb(Tox *tox, Tox_Group_Number group_number, T
void tox_callback_group_voice_state(Tox *tox, tox_group_voice_state_cb *callback);
/**
- * Return the topic lock status of the group designated by the given group number. If group number
+ * Return the topic lock status of the group designated by the given group
+ * number. If group number
* is invalid, the return value is unspecified.
*
* The value returned is equal to the data received by the last
* `group_topic_lock` callback.
*
- * @see the `Group chat founder contols` section for the respective set function.
+ * @see the `Group chat Founder controls` section for the respective set
+ * function.
*/
Tox_Group_Topic_Lock tox_group_get_topic_lock(const Tox *tox, Tox_Group_Number group_number,
- Tox_Err_Group_State_Queries *error);
+ Tox_Err_Group_State_Query *error);
/**
- * @param group_number The group number of the group for which the topic lock has changed.
+ * @param group_number The group number of the group for which the topic lock
+ * has changed.
* @param topic_lock The new topic lock state.
*/
typedef void tox_group_topic_lock_cb(Tox *tox, Tox_Group_Number group_number, Tox_Group_Topic_Lock topic_lock, void *user_data);
@@ -4364,18 +4050,21 @@ typedef void tox_group_topic_lock_cb(Tox *tox, Tox_Group_Number group_number, To
void tox_callback_group_topic_lock(Tox *tox, tox_group_topic_lock_cb *callback);
/**
- * Return the maximum number of peers allowed for the group designated by the given group number.
- * If the group number is invalid, the return value is unspecified.
+ * Return the maximum number of peers allowed for the group designated by the
+ * given group number. If the group number is invalid, the return value is
+ * unspecified.
*
* The value returned is equal to the data received by the last
* `group_peer_limit` callback.
*
- * @see the `Group chat founder controls` section for the respective set function.
+ * @see the `Group chat Founder controls` section for the respective set
+ * function.
*/
-uint16_t tox_group_get_peer_limit(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_State_Queries *error);
+uint16_t tox_group_get_peer_limit(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_State_Query *error);
/**
- * @param group_number The group number of the group for which the peer limit has changed.
+ * @param group_number The group number of the group for which the peer limit
+ * has changed.
* @param peer_limit The new peer limit for the group.
*/
typedef void tox_group_peer_limit_cb(Tox *tox, Tox_Group_Number group_number, uint32_t peer_limit, void *user_data);
@@ -4383,7 +4072,8 @@ typedef void tox_group_peer_limit_cb(Tox *tox, Tox_Group_Number group_number, ui
/**
* Set the callback for the `group_peer_limit` event. Pass NULL to unset.
*
- * This event is triggered when the group founder changes the maximum peer limit.
+ * This event is triggered when the group founder changes the maximum peer
+ * limit.
*/
void tox_callback_group_peer_limit(Tox *tox, tox_group_peer_limit_cb *callback);
@@ -4391,35 +4081,39 @@ void tox_callback_group_peer_limit(Tox *tox, tox_group_peer_limit_cb *callback);
* Return the length of the group password. If the group number is invalid, the
* return value is unspecified.
*/
-size_t tox_group_get_password_size(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_State_Queries *error);
+size_t tox_group_get_password_size(const Tox *tox, Tox_Group_Number group_number, Tox_Err_Group_State_Query *error);
/**
- * Write the password for the group designated by the given group number to a byte array.
+ * Write the password for the group designated by the given group number to a
+ * byte array.
*
- * Call tox_group_get_password_size to determine the allocation size for the `password` parameter.
+ * Call tox_group_get_password_size to determine the allocation size for the
+ * `password` parameter.
*
- * The data received is equal to the data received by the last
- * `group_password` callback.
+ * The data received is equal to the data received by the last `group_password`
+ * callback.
*
- * @see the `Group chat founder controls` section for the respective set function.
+ * @see the `Group chat Founder controls` section for the respective set
+ * function.
*
- * @param password A valid memory region large enough to store the group password.
- * If this parameter is NULL, this function call has no effect.
+ * @param password A valid memory region large enough to store the group
+ * password. If this parameter is NULL, this function call has no effect.
*
* @return true on success.
*/
bool tox_group_get_password(
const Tox *tox, Tox_Group_Number group_number, uint8_t password[],
- Tox_Err_Group_State_Queries *error);
+ Tox_Err_Group_State_Query *error);
/**
- * @param group_number The group number of the group for which the password has changed.
+ * @param group_number The group number of the group for which the password has
+ * changed.
* @param password The new group password.
- * @param length The length of the password.
+ * @param password_length The length of the password.
*/
typedef void tox_group_password_cb(
Tox *tox, Tox_Group_Number group_number,
- const uint8_t password[], size_t length,
+ const uint8_t password[], size_t password_length,
void *user_data);
/**
@@ -4453,7 +4147,7 @@ typedef enum Tox_Err_Group_Send_Message {
TOX_ERR_GROUP_SEND_MESSAGE_TOO_LONG,
/**
- * The message pointer is null or length is zero.
+ * The message pointer is NULL or length is zero.
*/
TOX_ERR_GROUP_SEND_MESSAGE_EMPTY,
@@ -4487,12 +4181,13 @@ const char *tox_err_group_send_message_to_string(Tox_Err_Group_Send_Message valu
* This function creates a group message packet and pushes it into the send
* queue.
*
- * The message length may not exceed TOX_GROUP_MAX_MESSAGE_LENGTH. Larger messages
- * must be split by the client and sent as separate messages. Other clients can
- * then reassemble the fragments. Messages may not be empty.
+ * The message length may not exceed TOX_GROUP_MAX_MESSAGE_LENGTH. Larger
+ * messages must be split by the client and sent as separate messages. Other
+ * clients can then reassemble the fragments. Messages may not be empty.
*
- * @param group_number The group number of the group the message is intended for.
- * @param type Message type (normal, action, ...).
+ * @param group_number The group number of the group the message is intended
+ * for.
+ * @param message_type Message type (normal, action, ...).
* @param message A non-NULL pointer to the first element of a byte array
* containing the message text.
* @param length Length of the message to be sent.
@@ -4501,7 +4196,7 @@ const char *tox_err_group_send_message_to_string(Tox_Err_Group_Send_Message valu
* returned message ID value will be undefined.
*/
Tox_Group_Message_Id tox_group_send_message(
- const Tox *tox, Tox_Group_Number group_number, Tox_Message_Type type,
+ const Tox *tox, Tox_Group_Number group_number, Tox_Message_Type message_type,
const uint8_t message[], size_t length,
Tox_Err_Group_Send_Message *error);
@@ -4528,11 +4223,16 @@ typedef enum Tox_Err_Group_Send_Private_Message {
TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_TOO_LONG,
/**
- * The message pointer is null or length is zero.
+ * The message pointer is NULL or length is zero.
*/
TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_EMPTY,
/**
+ * The message type is invalid.
+ */
+ TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_BAD_TYPE,
+
+ /**
* The caller does not have the required permissions to send group messages.
*/
TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PERMISSIONS,
@@ -4547,11 +4247,6 @@ typedef enum Tox_Err_Group_Send_Private_Message {
*/
TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_DISCONNECTED,
- /**
- * The message type is invalid.
- */
- TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_BAD_TYPE,
-
} Tox_Err_Group_Send_Private_Message;
const char *tox_err_group_send_private_message_to_string(Tox_Err_Group_Send_Private_Message value);
@@ -4559,23 +4254,25 @@ const char *tox_err_group_send_private_message_to_string(Tox_Err_Group_Send_Priv
/**
* Send a text chat message to the specified peer in the specified group.
*
- * This function creates a group private message packet and pushes it into the send
- * queue.
+ * This function creates a group private message packet and pushes it into the
+ * send queue.
*
- * The message length may not exceed TOX_GROUP_MAX_MESSAGE_LENGTH. Larger messages
- * must be split by the client and sent as separate messages. Other clients can
- * then reassemble the fragments. Messages may not be empty.
+ * The message length may not exceed TOX_GROUP_MAX_MESSAGE_LENGTH. Larger
+ * messages must be split by the client and sent as separate messages. Other
+ * clients can then reassemble the fragments. Messages may not be empty.
*
- * @param group_number The group number of the group the message is intended for.
+ * @param group_number The group number of the group the message is intended
+ * for.
* @param peer_id The ID of the peer the message is intended for.
+ * @param message_type The type of message (normal, action, ...).
* @param message A non-NULL pointer to the first element of a byte array
* containing the message text.
* @param length Length of the message to be sent.
*
* @return true on success.
*/
-bool tox_group_send_private_message(
- const Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, Tox_Message_Type type,
+Tox_Group_Message_Id tox_group_send_private_message(
+ const Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, Tox_Message_Type message_type,
const uint8_t message[], size_t length,
Tox_Err_Group_Send_Private_Message *error);
@@ -4599,16 +4296,11 @@ typedef enum Tox_Err_Group_Send_Custom_Packet {
TOX_ERR_GROUP_SEND_CUSTOM_PACKET_TOO_LONG,
/**
- * The message pointer is null or length is zero.
+ * The message pointer is NULL or length is zero.
*/
TOX_ERR_GROUP_SEND_CUSTOM_PACKET_EMPTY,
/**
- * The caller does not have the required permissions to send group messages.
- */
- TOX_ERR_GROUP_SEND_CUSTOM_PACKET_PERMISSIONS,
-
- /**
* The group is disconnected.
*/
TOX_ERR_GROUP_SEND_CUSTOM_PACKET_DISCONNECTED,
@@ -4626,15 +4318,17 @@ const char *tox_err_group_send_custom_packet_to_string(Tox_Err_Group_Send_Custom
/**
* Send a custom packet to the group.
*
- * If lossless is true the packet will be lossless. Lossless packet behaviour is comparable
- * to TCP (reliability, arrive in order) but with packets instead of a stream.
+ * If lossless is true the packet will be lossless. Lossless packet behaviour is
+ * comparable to TCP (reliability, arrive in order) but with packets instead of
+ * a stream.
*
- * If lossless is false, the packet will be lossy. Lossy packets behave like UDP packets,
- * meaning they might never reach the other side or might arrive more than once (if someone
- * is messing with the connection) or might arrive in the wrong order.
+ * If lossless is false, the packet will be lossy. Lossy packets behave like UDP
+ * packets, meaning they might never reach the other side or might arrive more
+ * than once (if someone is messing with the connection) or might arrive in the
+ * wrong order.
*
- * Unless latency is an issue or message reliability is not important, it is recommended that you use
- * lossless packets.
+ * Unless latency is an issue or message reliability is not important, it is
+ * recommended that you use lossless packets.
*
* The message length may not exceed TOX_MAX_CUSTOM_PACKET_SIZE. Larger packets
* must be split by the client and sent as separate packets. Other clients can
@@ -4672,7 +4366,7 @@ typedef enum Tox_Err_Group_Send_Custom_Private_Packet {
TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_TOO_LONG,
/**
- * The message pointer is null or length is zero.
+ * The message pointer is NULL or length is zero.
*/
TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_EMPTY,
@@ -4682,11 +4376,6 @@ typedef enum Tox_Err_Group_Send_Custom_Private_Packet {
TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_PEER_NOT_FOUND,
/**
- * The caller does not have the required permissions to send group messages.
- */
- TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_PERMISSIONS,
-
- /**
* The packet failed to send.
*/
TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_FAIL_SEND,
@@ -4703,15 +4392,17 @@ const char *tox_err_group_send_custom_private_packet_to_string(Tox_Err_Group_Sen
/**
* Send a custom private packet to a designated peer in the group.
*
- * If lossless is true the packet will be lossless. Lossless packet behaviour is comparable
- * to TCP (reliability, arrive in order) but with packets instead of a stream.
+ * If lossless is true the packet will be lossless. Lossless packet behaviour is
+ * comparable to TCP (reliability, arrive in order) but with packets instead of
+ * a stream.
*
- * If lossless is false, the packet will be lossy. Lossy packets behave like UDP packets,
- * meaning they might never reach the other side or might arrive more than once (if someone
- * is messing with the connection) or might arrive in the wrong order.
+ * If lossless is false, the packet will be lossy. Lossy packets behave like UDP
+ * packets, meaning they might never reach the other side or might arrive more
+ * than once (if someone is messing with the connection) or might arrive in the
+ * wrong order.
*
- * Unless latency is an issue or message reliability is not important, it is recommended that you use
- * lossless packets.
+ * Unless latency is an issue or message reliability is not important, it is
+ * recommended that you use lossless packets.
*
* The packet length may not exceed TOX_MAX_CUSTOM_PACKET_SIZE. Larger packets
* must be split by the client and sent as separate packets. Other clients can
@@ -4736,16 +4427,18 @@ bool tox_group_send_custom_private_packet(const Tox *tox, Tox_Group_Number group
******************************************************************************/
/**
- * @param group_number The group number of the group the message is intended for.
+ * @param group_number The group number of the group the message is intended
+ * for.
* @param peer_id The ID of the peer who sent the message.
- * @param type The type of message (normal, action, ...).
+ * @param message_type The type of message (normal, action, ...).
* @param message The message data.
- * @param message_id A pseudo message id that clients can use to uniquely identify this group message.
- * @param length The length of the message.
+ * @param message_length The length of the message.
+ * @param message_id A pseudo message id that clients can use to uniquely
+ * identify this group message.
*/
typedef void tox_group_message_cb(
- Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, Tox_Message_Type type,
- const uint8_t message[], size_t length, Tox_Group_Message_Id message_id, void *user_data);
+ Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, Tox_Message_Type message_type,
+ const uint8_t message[], size_t message_length, Tox_Group_Message_Id message_id, void *user_data);
/**
* Set the callback for the `group_message` event. Pass NULL to unset.
@@ -4755,14 +4448,18 @@ typedef void tox_group_message_cb(
void tox_callback_group_message(Tox *tox, tox_group_message_cb *callback);
/**
- * @param group_number The group number of the group the private message is intended for.
+ * @param group_number The group number of the group the private message is
+ * intended for.
* @param peer_id The ID of the peer who sent the private message.
+ * @param message_type The type of message (normal, action, ...).
* @param message The message data.
- * @param length The length of the message.
+ * @param message_length The length of the message.
+ * @param message_id A pseudo message id that clients can use to uniquely
+ * identify this group message.
*/
typedef void tox_group_private_message_cb(
- Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, Tox_Message_Type type,
- const uint8_t message[], size_t length, void *user_data);
+ Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, Tox_Message_Type message_type,
+ const uint8_t message[], size_t message_length, Tox_Group_Message_Id message_id, void *user_data);
/**
* Set the callback for the `group_private_message` event. Pass NULL to unset.
@@ -4775,11 +4472,11 @@ void tox_callback_group_private_message(Tox *tox, tox_group_private_message_cb *
* @param group_number The group number of the group the packet is intended for.
* @param peer_id The ID of the peer who sent the packet.
* @param data The packet data.
- * @param length The length of the data.
+ * @param data_length The length of the data.
*/
typedef void tox_group_custom_packet_cb(
Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id,
- const uint8_t data[], size_t length, void *user_data);
+ const uint8_t data[], size_t data_length, void *user_data);
/**
* Set the callback for the `group_custom_packet` event. Pass NULL to unset.
@@ -4792,14 +4489,15 @@ void tox_callback_group_custom_packet(Tox *tox, tox_group_custom_packet_cb *call
* @param group_number The group number of the group the packet is intended for.
* @param peer_id The ID of the peer who sent the packet.
* @param data The packet data.
- * @param length The length of the data.
+ * @param data_length The length of the data.
*/
typedef void tox_group_custom_private_packet_cb(
Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id,
- const uint8_t data[], size_t length, void *user_data);
+ const uint8_t data[], size_t data_length, void *user_data);
/**
- * Set the callback for the `group_custom_private_packet` event. Pass NULL to unset.
+ * Set the callback for the `group_custom_private_packet` event. Pass NULL to
+ * unset.
*
* This event is triggered when the client receives a custom private packet.
*/
@@ -4829,7 +4527,8 @@ typedef enum Tox_Err_Group_Invite_Friend {
TOX_ERR_GROUP_INVITE_FRIEND_FRIEND_NOT_FOUND,
/**
- * Creation of the invite packet failed. This indicates a network related error.
+ * Creation of the invite packet failed. This indicates a network related
+ * error.
*/
TOX_ERR_GROUP_INVITE_FRIEND_INVITE_FAIL,
@@ -4850,10 +4549,13 @@ const char *tox_err_group_invite_friend_to_string(Tox_Err_Group_Invite_Friend va
/**
* Invite a friend to a group.
*
- * This function creates an invite request packet and pushes it to the send queue.
+ * This function creates an invite request packet and pushes it to the send
+ * queue.
*
- * @param group_number The group number of the group the message is intended for.
- * @param friend_number The friend number of the friend the invite is intended for.
+ * @param group_number The group number of the group the message is intended
+ * for.
+ * @param friend_number The friend number of the friend the invite is intended
+ * for.
*
* @return true on success.
*/
@@ -4889,36 +4591,44 @@ typedef enum Tox_Err_Group_Invite_Accept {
TOX_ERR_GROUP_INVITE_ACCEPT_EMPTY,
/**
- * Failed to set password. This usually occurs if the password exceeds TOX_GROUP_MAX_PASSWORD_SIZE.
+ * Failed to set password. This usually occurs if the password exceeds
+ * TOX_GROUP_MAX_PASSWORD_SIZE.
*/
TOX_ERR_GROUP_INVITE_ACCEPT_PASSWORD,
/**
- * There was a core error when initiating the group.
+ * The friend number passed did not designate a valid friend.
*/
- TOX_ERR_GROUP_INVITE_ACCEPT_CORE,
+ TOX_ERR_GROUP_INVITE_ACCEPT_FRIEND_NOT_FOUND,
/**
* Packet failed to send.
*/
TOX_ERR_GROUP_INVITE_ACCEPT_FAIL_SEND,
+ /**
+ * Invite data or name is NULL.
+ */
+ TOX_ERR_GROUP_INVITE_ACCEPT_NULL,
+
} Tox_Err_Group_Invite_Accept;
const char *tox_err_group_invite_accept_to_string(Tox_Err_Group_Invite_Accept value);
/**
- * Accept an invite to a group chat that the client previously received from a friend. The invite
- * is only valid while the inviter is present in the group.
+ * Accept an invite to a group chat that the client previously received from a
+ * friend. The invite is only valid while the inviter is present in the group.
*
* @param invite_data The invite data received from the `group_invite` event.
* @param length The length of the invite data.
* @param name The name of the peer joining the group.
- * @param name_length The length of the peer's name. This must be greater than zero and no larger
- * than TOX_MAX_NAME_LENGTH.
- * @param password The password required to join the group. Set to NULL if no password is required.
- * @param password_length The length of the password. If password_length is equal to zero, the password
- * parameter will be ignored. password_length must be no larger than TOX_GROUP_MAX_PASSWORD_SIZE.
+ * @param name_length The length of the peer's name. This must be greater than
+ * zero and no larger than TOX_MAX_NAME_LENGTH.
+ * @param password The password required to join the group. Set to NULL if no
+ * password is required.
+ * @param password_length The length of the password. If password_length is
+ * equal to zero, the password parameter will be ignored. password_length
+ * must be no larger than TOX_GROUP_MAX_PASSWORD_SIZE.
*
* @return the group_number on success, UINT32_MAX on failure.
*/
@@ -4932,26 +4642,30 @@ Tox_Group_Number tox_group_invite_accept(
/**
* @param friend_number The friend number of the contact who sent the invite.
* @param invite_data The invite data.
- * @param length The length of invite_data.
+ * @param invite_data_length The length of invite_data.
+ * @param group_name The name of the group. In conferences, this is "title".
+ * @param group_name_length The length of the group name.
*/
typedef void tox_group_invite_cb(
Tox *tox, Tox_Friend_Number friend_number,
- const uint8_t invite_data[], size_t length,
+ const uint8_t invite_data[], size_t invite_data_length,
const uint8_t group_name[], size_t group_name_length,
void *user_data);
/**
* Set the callback for the `group_invite` event. Pass NULL to unset.
*
- * This event is triggered when the client receives a group invite from a friend. The client must store
- * invite_data which is used to join the group via tox_group_invite_accept.
+ * This event is triggered when the client receives a group invite from a
+ * friend. The client must store invite_data which is used to join the group
+ * via tox_group_invite_accept.
*/
void tox_callback_group_invite(Tox *tox, tox_group_invite_cb *callback);
/**
- * @param group_number The group number of the group in which a new peer has joined.
- * @param peer_id The permanent ID of the new peer. This id should not be relied on for
- * client behaviour and should be treated as a random value.
+ * @param group_number The group number of the group in which a new peer has
+ * joined.
+ * @param peer_id The permanent ID of the new peer. This id should not be relied
+ * on for client behaviour and should be treated as a random value.
*/
typedef void tox_group_peer_join_cb(Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, void *user_data);
@@ -4963,7 +4677,8 @@ typedef void tox_group_peer_join_cb(Tox *tox, Tox_Group_Number group_number, Tox
void tox_callback_group_peer_join(Tox *tox, tox_group_peer_join_cb *callback);
/**
- * Represents peer exit events. These should be used with the `group_peer_exit` event.
+ * Represents peer exit events. These should be used with the `group_peer_exit`
+ * event.
*/
typedef enum Tox_Group_Exit_Type {
@@ -4983,8 +4698,9 @@ typedef enum Tox_Group_Exit_Type {
TOX_GROUP_EXIT_TYPE_DISCONNECTED,
/**
- * Your connection with all peers has been severed. This will occur when you are kicked from
- * a group, rejoin a group, or manually disconnect from a group.
+ * Your connection with all peers has been severed. This will occur when you
+ * are kicked from a group, rejoin a group, or manually disconnect from a
+ * group.
*/
TOX_GROUP_EXIT_TYPE_SELF_DISCONNECTED,
@@ -5004,8 +4720,8 @@ const char *tox_group_exit_type_to_string(Tox_Group_Exit_Type value);
/**
* @param group_number The group number of the group in which a peer has left.
- * @param peer_id The ID of the peer who left the group. This ID no longer designates a valid peer
- * and cannot be used for API calls.
+ * @param peer_id The ID of the peer who left the group. This ID no longer
+ * designates a valid peer and cannot be used for API calls.
* @param exit_type The type of exit event. One of Tox_Group_Exit_Type.
* @param name The nickname of the peer who left the group.
* @param name_length The length of the peer name.
@@ -5032,14 +4748,14 @@ typedef void tox_group_self_join_cb(Tox *tox, Tox_Group_Number group_number, voi
/**
* Set the callback for the `group_self_join` event. Pass NULL to unset.
*
- * This event is triggered when the client has successfully joined a group. Use this to initialize
- * any group information the client may need.
+ * This event is triggered when the client has successfully joined a group. Use
+ * this to initialize any group information the client may need.
*/
void tox_callback_group_self_join(Tox *tox, tox_group_self_join_cb *callback);
/**
- * Represents types of failed group join attempts. These are used in the tox_callback_group_rejected
- * callback when a peer fails to join a group.
+ * Represents types of failed group join attempts. These are used in the
+ * tox_callback_group_rejected callback when a peer fails to join a group.
*/
typedef enum Tox_Group_Join_Fail {
@@ -5054,8 +4770,8 @@ typedef enum Tox_Group_Join_Fail {
TOX_GROUP_JOIN_FAIL_INVALID_PASSWORD,
/**
- * The join attempt failed due to an unspecified error. This often occurs when the group is
- * not found in the DHT.
+ * The join attempt failed due to an unspecified error. This often occurs
+ * when the group is not found in the DHT.
*/
TOX_GROUP_JOIN_FAIL_UNKNOWN,
@@ -5064,7 +4780,8 @@ typedef enum Tox_Group_Join_Fail {
const char *tox_group_join_fail_to_string(Tox_Group_Join_Fail value);
/**
- * @param group_number The group number of the group for which the join has failed.
+ * @param group_number The group number of the group for which the join has
+ * failed.
* @param fail_type The type of group rejection.
*/
typedef void tox_group_join_fail_cb(Tox *tox, Tox_Group_Number group_number, Tox_Group_Join_Fail fail_type, void *user_data);
@@ -5078,289 +4795,306 @@ void tox_callback_group_join_fail(Tox *tox, tox_group_join_fail_cb *callback);
/*******************************************************************************
*
- * :: Group chat founder controls (these only work for the group founder)
+ * :: Group chat Founder controls
*
******************************************************************************/
-typedef enum Tox_Err_Group_Founder_Set_Password {
+typedef enum Tox_Err_Group_Set_Password {
/**
* The function returned successfully.
*/
- TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK,
+ TOX_ERR_GROUP_SET_PASSWORD_OK,
/**
* The group number passed did not designate a valid group.
*/
- TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_GROUP_NOT_FOUND,
+ TOX_ERR_GROUP_SET_PASSWORD_GROUP_NOT_FOUND,
/**
* The caller does not have the required permissions to set the password.
*/
- TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_PERMISSIONS,
+ TOX_ERR_GROUP_SET_PASSWORD_PERMISSIONS,
/**
* Password length exceeded TOX_GROUP_MAX_PASSWORD_SIZE.
*/
- TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_TOO_LONG,
+ TOX_ERR_GROUP_SET_PASSWORD_TOO_LONG,
/**
* The packet failed to send.
*/
- TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_FAIL_SEND,
+ TOX_ERR_GROUP_SET_PASSWORD_FAIL_SEND,
/**
* The function failed to allocate enough memory for the operation.
*/
- TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_MALLOC,
+ TOX_ERR_GROUP_SET_PASSWORD_MALLOC,
/**
* The group is disconnected.
*/
- TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_DISCONNECTED,
+ TOX_ERR_GROUP_SET_PASSWORD_DISCONNECTED,
-} Tox_Err_Group_Founder_Set_Password;
+} Tox_Err_Group_Set_Password;
-const char *tox_err_group_founder_set_password_to_string(Tox_Err_Group_Founder_Set_Password value);
+const char *tox_err_group_set_password_to_string(Tox_Err_Group_Set_Password value);
/**
* Set or unset the group password.
*
- * This function sets the groups password, creates a new group shared state including the change,
- * and distributes it to the rest of the group.
+ * This function allows Founders to set or unset a group password. It will
+ * create a new group shared state including the change and distribute it to the
+ * rest of the group.
*
- * @param group_number The group number of the group for which we wish to set the password.
- * @param password The password we want to set. Set password to NULL to unset the password.
- * @param length The length of the password. length must be no longer than TOX_GROUP_MAX_PASSWORD_SIZE.
+ * @param group_number The group number of the group for which we wish to set
+ * the password.
+ * @param password The password we want to set. Set password to NULL to unset
+ * the password.
+ * @param length The length of the password. length must be no longer than
+ * TOX_GROUP_MAX_PASSWORD_SIZE.
*
* @return true on success.
*/
-bool tox_group_founder_set_password(
+bool tox_group_set_password(
Tox *tox, Tox_Group_Number group_number,
const uint8_t password[], size_t length,
- Tox_Err_Group_Founder_Set_Password *error);
+ Tox_Err_Group_Set_Password *error);
-typedef enum Tox_Err_Group_Founder_Set_Topic_Lock {
+typedef enum Tox_Err_Group_Set_Topic_Lock {
/**
* The function returned successfully.
*/
- TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK,
+ TOX_ERR_GROUP_SET_TOPIC_LOCK_OK,
/**
* The group number passed did not designate a valid group.
*/
- TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_GROUP_NOT_FOUND,
+ TOX_ERR_GROUP_SET_TOPIC_LOCK_GROUP_NOT_FOUND,
/**
* Tox_Group_Topic_Lock is an invalid type.
*/
- TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_INVALID,
+ TOX_ERR_GROUP_SET_TOPIC_LOCK_INVALID,
/**
* The caller does not have the required permissions to set the topic lock.
*/
- TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_PERMISSIONS,
+ TOX_ERR_GROUP_SET_TOPIC_LOCK_PERMISSIONS,
/**
- * The topic lock could not be set. This may occur due to an error related to
- * cryptographic signing of the new shared state.
+ * The topic lock could not be set. This may occur due to an error related
+ * to cryptographic signing of the new shared state.
*/
- TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_FAIL_SET,
+ TOX_ERR_GROUP_SET_TOPIC_LOCK_FAIL_SET,
/**
* The packet failed to send.
*/
- TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_FAIL_SEND,
+ TOX_ERR_GROUP_SET_TOPIC_LOCK_FAIL_SEND,
/**
* The group is disconnected.
*/
- TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_DISCONNECTED,
+ TOX_ERR_GROUP_SET_TOPIC_LOCK_DISCONNECTED,
-} Tox_Err_Group_Founder_Set_Topic_Lock;
+} Tox_Err_Group_Set_Topic_Lock;
-const char *tox_err_group_founder_set_topic_lock_to_string(Tox_Err_Group_Founder_Set_Topic_Lock value);
+const char *tox_err_group_set_topic_lock_to_string(Tox_Err_Group_Set_Topic_Lock value);
/**
* Set the group topic lock state.
*
- * This function sets the group's topic lock state to enabled or disabled, creates a new shared
- * state including the change, and distributes it to the rest of the group.
+ * This function allows Founders to enable or disable the group's topic lock. It
+ * will create a new shared state including the change and distribute it to the
+ * rest of the group.
*
- * When the topic lock is enabled, only the group founder and moderators may set the topic.
- * When disabled, all peers except those with the observer role may set the topic.
+ * When the topic lock is enabled, only the group founder and moderators may set
+ * the topic. When disabled, all peers except those with the observer role may
+ * set the topic.
*
- * @param group_number The group number of the group for which we wish to change the topic lock state.
+ * @param group_number The group number of the group for which we wish to change
+ * the topic lock state.
* @param topic_lock The state we wish to set the topic lock to.
*
* @return true on success.
*/
-bool tox_group_founder_set_topic_lock(Tox *tox, Tox_Group_Number group_number, Tox_Group_Topic_Lock topic_lock,
- Tox_Err_Group_Founder_Set_Topic_Lock *error);
+bool tox_group_set_topic_lock(Tox *tox, Tox_Group_Number group_number, Tox_Group_Topic_Lock topic_lock,
+ Tox_Err_Group_Set_Topic_Lock *error);
-typedef enum Tox_Err_Group_Founder_Set_Voice_State {
+typedef enum Tox_Err_Group_Set_Voice_State {
/**
* The function returned successfully.
*/
- TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_OK,
+ TOX_ERR_GROUP_SET_VOICE_STATE_OK,
/**
* The group number passed did not designate a valid group.
*/
- TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_GROUP_NOT_FOUND,
+ TOX_ERR_GROUP_SET_VOICE_STATE_GROUP_NOT_FOUND,
/**
- * The caller does not have the required permissions to set the privacy state.
+ * The caller does not have the required permissions to set the privacy
+ * state.
*/
- TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_PERMISSIONS,
+ TOX_ERR_GROUP_SET_VOICE_STATE_PERMISSIONS,
/**
- * The voice state could not be set. This may occur due to an error related to
- * cryptographic signing of the new shared state.
+ * The voice state could not be set. This may occur due to an error related
+ * to cryptographic signing of the new shared state.
*/
- TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_FAIL_SET,
+ TOX_ERR_GROUP_SET_VOICE_STATE_FAIL_SET,
/**
* The packet failed to send.
*/
- TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_FAIL_SEND,
+ TOX_ERR_GROUP_SET_VOICE_STATE_FAIL_SEND,
/**
* The group is disconnected.
*/
- TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_DISCONNECTED,
+ TOX_ERR_GROUP_SET_VOICE_STATE_DISCONNECTED,
-} Tox_Err_Group_Founder_Set_Voice_State;
+} Tox_Err_Group_Set_Voice_State;
-const char *tox_err_group_founder_set_voice_state_to_string(Tox_Err_Group_Founder_Set_Voice_State value);
+const char *tox_err_group_set_voice_state_to_string(Tox_Err_Group_Set_Voice_State value);
/**
* Set the group voice state.
*
- * This function sets the group's voice state, creates a new group shared state
- * including the change, and distributes it to the rest of the group.
+ * This function allows Founders to set the group's voice state. It will create
+ * a new group shared state including the change and distribute it to the rest
+ * of the group.
*
- * If an attempt is made to set the voice state to the same state that the group is already
- * in, the function call will be successful and no action will be taken.
+ * If an attempt is made to set the voice state to the same state that the group
+ * is already in, the function call will be successful and no action will be
+ * taken.
*
- * @param group_number The group number of the group for which we wish to change the voice state.
+ * @param group_number The group number of the group for which we wish to change
+ * the voice state.
* @param voice_state The voice state we wish to set the group to.
*
* @return true on success.
*/
-bool tox_group_founder_set_voice_state(Tox *tox, Tox_Group_Number group_number, Tox_Group_Voice_State voice_state,
- Tox_Err_Group_Founder_Set_Voice_State *error);
+bool tox_group_set_voice_state(Tox *tox, Tox_Group_Number group_number, Tox_Group_Voice_State voice_state,
+ Tox_Err_Group_Set_Voice_State *error);
-typedef enum Tox_Err_Group_Founder_Set_Privacy_State {
+typedef enum Tox_Err_Group_Set_Privacy_State {
/**
* The function returned successfully.
*/
- TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK,
+ TOX_ERR_GROUP_SET_PRIVACY_STATE_OK,
/**
* The group number passed did not designate a valid group.
*/
- TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_GROUP_NOT_FOUND,
+ TOX_ERR_GROUP_SET_PRIVACY_STATE_GROUP_NOT_FOUND,
/**
- * The caller does not have the required permissions to set the privacy state.
+ * The caller does not have the required permissions to set the privacy
+ * state.
*/
- TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_PERMISSIONS,
+ TOX_ERR_GROUP_SET_PRIVACY_STATE_PERMISSIONS,
/**
- * The privacy state could not be set. This may occur due to an error related to
- * cryptographic signing of the new shared state.
+ * The privacy state could not be set. This may occur due to an error
+ * related to cryptographic signing of the new shared state.
*/
- TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SET,
+ TOX_ERR_GROUP_SET_PRIVACY_STATE_FAIL_SET,
/**
* The packet failed to send.
*/
- TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SEND,
+ TOX_ERR_GROUP_SET_PRIVACY_STATE_FAIL_SEND,
/**
* The group is disconnected.
*/
- TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_DISCONNECTED,
+ TOX_ERR_GROUP_SET_PRIVACY_STATE_DISCONNECTED,
-} Tox_Err_Group_Founder_Set_Privacy_State;
+} Tox_Err_Group_Set_Privacy_State;
-const char *tox_err_group_founder_set_privacy_state_to_string(Tox_Err_Group_Founder_Set_Privacy_State value);
+const char *tox_err_group_set_privacy_state_to_string(Tox_Err_Group_Set_Privacy_State value);
/**
* Set the group privacy state.
*
- * This function sets the group's privacy state, creates a new group shared state
- * including the change, and distributes it to the rest of the group.
+ * This function allows Founders to set the group's privacy state. It will
+ * create a new group shared state including the change and distribute it to the
+ * rest of the group.
*
- * If an attempt is made to set the privacy state to the same state that the group is already
- * in, the function call will be successful and no action will be taken.
+ * If an attempt is made to set the privacy state to the same state that the
+ * group is already in, the function call will be successful and no action will
+ * be taken.
*
- * @param group_number The group number of the group for which we wish to change the privacy state.
+ * @param group_number The group number of the group for which we wish to change
+ * the privacy state.
* @param privacy_state The privacy state we wish to set the group to.
*
* @return true on success.
*/
-bool tox_group_founder_set_privacy_state(Tox *tox, Tox_Group_Number group_number, Tox_Group_Privacy_State privacy_state,
- Tox_Err_Group_Founder_Set_Privacy_State *error);
+bool tox_group_set_privacy_state(Tox *tox, Tox_Group_Number group_number, Tox_Group_Privacy_State privacy_state,
+ Tox_Err_Group_Set_Privacy_State *error);
-typedef enum Tox_Err_Group_Founder_Set_Peer_Limit {
+typedef enum Tox_Err_Group_Set_Peer_Limit {
/**
* The function returned successfully.
*/
- TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK,
+ TOX_ERR_GROUP_SET_PEER_LIMIT_OK,
/**
* The group number passed did not designate a valid group.
*/
- TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_GROUP_NOT_FOUND,
+ TOX_ERR_GROUP_SET_PEER_LIMIT_GROUP_NOT_FOUND,
/**
* The caller does not have the required permissions to set the peer limit.
*/
- TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_PERMISSIONS,
+ TOX_ERR_GROUP_SET_PEER_LIMIT_PERMISSIONS,
/**
- * The peer limit could not be set. This may occur due to an error related to
- * cryptographic signing of the new shared state.
+ * The peer limit could not be set. This may occur due to an error related
+ * to cryptographic signing of the new shared state.
*/
- TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SET,
+ TOX_ERR_GROUP_SET_PEER_LIMIT_FAIL_SET,
/**
* The packet failed to send.
*/
- TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SEND,
+ TOX_ERR_GROUP_SET_PEER_LIMIT_FAIL_SEND,
/**
* The group is disconnected.
*/
- TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_DISCONNECTED,
+ TOX_ERR_GROUP_SET_PEER_LIMIT_DISCONNECTED,
-} Tox_Err_Group_Founder_Set_Peer_Limit;
+} Tox_Err_Group_Set_Peer_Limit;
-const char *tox_err_group_founder_set_peer_limit_to_string(Tox_Err_Group_Founder_Set_Peer_Limit value);
+const char *tox_err_group_set_peer_limit_to_string(Tox_Err_Group_Set_Peer_Limit value);
/**
* Set the group peer limit.
*
- * This function sets a limit for the number of peers who may be in the group, creates a new
- * group shared state including the change, and distributes it to the rest of the group.
+ * This function allows Founders to set a limit for the number of peers who may
+ * be in the group. It will create a new group shared state including the change
+ * and distribute it to the rest of the group.
*
- * @param group_number The group number of the group for which we wish to set the peer limit.
+ * @param group_number The group number of the group for which we wish to set
+ * the peer limit.
* @param peer_limit The maximum number of peers to allow in the group.
*
* @return true on success.
*/
-bool tox_group_founder_set_peer_limit(Tox *tox, Tox_Group_Number group_number, uint16_t peer_limit,
- Tox_Err_Group_Founder_Set_Peer_Limit *error);
+bool tox_group_set_peer_limit(Tox *tox, Tox_Group_Number group_number, uint16_t peer_limit,
+ Tox_Err_Group_Set_Peer_Limit *error);
/*******************************************************************************
*
- * :: Group chat moderation
+ * :: Group chat moderation controls
*
******************************************************************************/
@@ -5393,7 +5127,8 @@ const char *tox_err_group_set_ignore_to_string(Tox_Err_Group_Set_Ignore value);
/**
* Ignore or unignore a peer.
*
- * @param group_number The group number of the group in which you wish to ignore a peer.
+ * @param group_number The group number of the group in which you wish to ignore
+ * a peer.
* @param peer_id The ID of the peer who shall be ignored or unignored.
* @param ignore True to ignore the peer, false to unignore the peer.
*
@@ -5402,123 +5137,134 @@ const char *tox_err_group_set_ignore_to_string(Tox_Err_Group_Set_Ignore value);
bool tox_group_set_ignore(Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, bool ignore,
Tox_Err_Group_Set_Ignore *error);
-typedef enum Tox_Err_Group_Mod_Set_Role {
+typedef enum Tox_Err_Group_Set_Role {
/**
* The function returned successfully.
*/
- TOX_ERR_GROUP_MOD_SET_ROLE_OK,
+ TOX_ERR_GROUP_SET_ROLE_OK,
/**
* The group number passed did not designate a valid group.
*/
- TOX_ERR_GROUP_MOD_SET_ROLE_GROUP_NOT_FOUND,
+ TOX_ERR_GROUP_SET_ROLE_GROUP_NOT_FOUND,
/**
- * The ID passed did not designate a valid peer. Note: you cannot set your own role.
+ * The ID passed did not designate a valid peer. Note: you cannot set your
+ * own role.
*/
- TOX_ERR_GROUP_MOD_SET_ROLE_PEER_NOT_FOUND,
+ TOX_ERR_GROUP_SET_ROLE_PEER_NOT_FOUND,
/**
* The caller does not have the required permissions for this action.
*/
- TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS,
+ TOX_ERR_GROUP_SET_ROLE_PERMISSIONS,
/**
- * The role assignment is invalid. This will occur if you try to set a peer's role to
- * the role they already have.
+ * The role assignment is invalid. This will occur if you try to set a
+ * peer's role to the role they already have.
*/
- TOX_ERR_GROUP_MOD_SET_ROLE_ASSIGNMENT,
+ TOX_ERR_GROUP_SET_ROLE_ASSIGNMENT,
/**
- * The role was not successfully set. This may occur if the packet failed to send, or
- * if the role limit has been reached.
+ * The role was not successfully set. This may occur if the packet failed to
+ * send, or if the role limit has been reached.
*/
- TOX_ERR_GROUP_MOD_SET_ROLE_FAIL_ACTION,
+ TOX_ERR_GROUP_SET_ROLE_FAIL_ACTION,
/**
* The caller attempted to set their own role.
*/
- TOX_ERR_GROUP_MOD_SET_ROLE_SELF,
+ TOX_ERR_GROUP_SET_ROLE_SELF,
-} Tox_Err_Group_Mod_Set_Role;
+} Tox_Err_Group_Set_Role;
-const char *tox_err_group_mod_set_role_to_string(Tox_Err_Group_Mod_Set_Role value);
+const char *tox_err_group_set_role_to_string(Tox_Err_Group_Set_Role value);
/**
* Set a peer's role.
*
- * This function will first remove the peer's previous role and then assign them a new role.
- * It will also send a packet to the rest of the group, requesting that they perform
- * the role reassignment. Note: peers cannot be set to the founder role.
+ * This function will first remove the peer's previous role and then assign them
+ * a new role. It will also send a packet to the rest of the group, requesting
+ * that they perform the role reassignment.
*
- * @param group_number The group number of the group the in which you wish set the peer's role.
+ * Only Founders may promote peers to the Moderator role, and only Founders and
+ * Moderators may set peers to the Observer or User role. Moderators may not set
+ * the role of other Moderators or the Founder. Peers may not be promoted to the
+ * Founder role.
+ *
+ * @param group_number The group number of the group the in which you wish set
+ * the peer's role.
* @param peer_id The ID of the peer whose role you wish to set.
* @param role The role you wish to set the peer to.
*
* @return true on success.
*/
-bool tox_group_mod_set_role(Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, Tox_Group_Role role,
- Tox_Err_Group_Mod_Set_Role *error);
+bool tox_group_set_role(Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id, Tox_Group_Role role,
+ Tox_Err_Group_Set_Role *error);
-typedef enum Tox_Err_Group_Mod_Kick_Peer {
+typedef enum Tox_Err_Group_Kick_Peer {
/**
* The function returned successfully.
*/
- TOX_ERR_GROUP_MOD_KICK_PEER_OK,
+ TOX_ERR_GROUP_KICK_PEER_OK,
/**
* The group number passed did not designate a valid group.
*/
- TOX_ERR_GROUP_MOD_KICK_PEER_GROUP_NOT_FOUND,
+ TOX_ERR_GROUP_KICK_PEER_GROUP_NOT_FOUND,
/**
* The ID passed did not designate a valid peer.
*/
- TOX_ERR_GROUP_MOD_KICK_PEER_PEER_NOT_FOUND,
+ TOX_ERR_GROUP_KICK_PEER_PEER_NOT_FOUND,
/**
* The caller does not have the required permissions for this action.
*/
- TOX_ERR_GROUP_MOD_KICK_PEER_PERMISSIONS,
+ TOX_ERR_GROUP_KICK_PEER_PERMISSIONS,
/**
* The peer could not be kicked from the group.
*/
- TOX_ERR_GROUP_MOD_KICK_PEER_FAIL_ACTION,
+ TOX_ERR_GROUP_KICK_PEER_FAIL_ACTION,
/**
* The packet failed to send.
*/
- TOX_ERR_GROUP_MOD_KICK_PEER_FAIL_SEND,
+ TOX_ERR_GROUP_KICK_PEER_FAIL_SEND,
/**
* The caller attempted to set their own role.
*/
- TOX_ERR_GROUP_MOD_KICK_PEER_SELF,
+ TOX_ERR_GROUP_KICK_PEER_SELF,
-} Tox_Err_Group_Mod_Kick_Peer;
+} Tox_Err_Group_Kick_Peer;
-const char *tox_err_group_mod_kick_peer_to_string(Tox_Err_Group_Mod_Kick_Peer value);
+const char *tox_err_group_kick_peer_to_string(Tox_Err_Group_Kick_Peer value);
/**
* Kick a peer.
*
- * This function will remove a peer from the caller's peer list and send a packet to all
- * group members requesting them to do the same. Note: This function will not trigger
- * the `group_peer_exit` event for the caller.
+ * This function allows peers with the Founder or Moderator role to silently
+ * instruct all other peers in the group to remove a particular peer from their
+ * peer list.
+ *
+ * Note: This function will not trigger the `group_peer_exit` event for the
+ * caller.
*
* @param group_number The group number of the group the action is intended for.
* @param peer_id The ID of the peer who will be kicked.
*
* @return true on success.
*/
-bool tox_group_mod_kick_peer(const Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id,
- Tox_Err_Group_Mod_Kick_Peer *error);
+bool tox_group_kick_peer(const Tox *tox, Tox_Group_Number group_number, Tox_Group_Peer_Number peer_id,
+ Tox_Err_Group_Kick_Peer *error);
/**
- * Represents moderation events. These should be used with the `group_moderation` event.
+ * Represents moderation events. These should be used with the
+ * `group_moderation` event.
*/
typedef enum Tox_Group_Mod_Event {
@@ -5559,12 +5305,13 @@ typedef void tox_group_moderation_cb(
/**
* Set the callback for the `group_moderation` event. Pass NULL to unset.
*
- * This event is triggered when a moderator or founder executes a moderation event, with
- * the exception of the peer who initiates the event. It is also triggered when the
- * observer and moderator lists are silently modified (this may occur during group syncing).
+ * This event is triggered when a moderator or founder executes a moderation
+ * event, with the exception of the peer who initiates the event. It is also
+ * triggered when the observer and moderator lists are silently modified (this
+ * may occur during group syncing).
*
- * If either peer id does not designate a valid peer in the group chat, the client should
- * manually update all peer roles.
+ * If either peer id does not designate a valid peer in the group chat, the
+ * client should manually update all peer roles.
*/
void tox_callback_group_moderation(Tox *tox, tox_group_moderation_cb *callback);
@@ -5579,6 +5326,7 @@ void tox_callback_group_moderation(Tox *tox, tox_group_moderation_cb *callback);
//!TOKSTYLE-
#ifndef DOXYGEN_IGNORE
+#ifndef TOX_HIDE_DEPRECATED
typedef Tox_Err_Options_New TOX_ERR_OPTIONS_NEW;
typedef Tox_Err_New TOX_ERR_NEW;
typedef Tox_Err_Bootstrap TOX_ERR_BOOTSTRAP;
@@ -5613,11 +5361,11 @@ typedef Tox_User_Status TOX_USER_STATUS;
typedef Tox_Message_Type TOX_MESSAGE_TYPE;
typedef Tox_Proxy_Type TOX_PROXY_TYPE;
typedef Tox_Savedata_Type TOX_SAVEDATA_TYPE;
-typedef Tox_Log_Level TOX_LOG_LEVEL;
typedef Tox_Connection TOX_CONNECTION;
typedef Tox_File_Control TOX_FILE_CONTROL;
typedef Tox_Conference_Type TOX_CONFERENCE_TYPE;
typedef enum Tox_File_Kind TOX_FILE_KIND;
+#endif /* TOX_HIDE_DEPRECATED */
#endif
//!TOKSTYLE+
diff --git a/protocols/Tox/libtox/src/toxcore/tox_api.c b/protocols/Tox/libtox/src/toxcore/tox_api.c
index 02791674b5..808cd473f5 100644
--- a/protocols/Tox/libtox/src/toxcore/tox_api.c
+++ b/protocols/Tox/libtox/src/toxcore/tox_api.c
@@ -1,20 +1,11 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2021 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
*/
-#include "tox.h"
+#include "tox.h" // IWYU pragma: associated
-#include <stdlib.h>
-
-#include "ccompat.h"
+#include "tox_options.h"
#include "tox_private.h"
-#define SET_ERROR_PARAMETER(param, x) \
- do { \
- if (param != nullptr) { \
- *param = x; \
- } \
- } while (0)
-
uint32_t tox_version_major(void)
{
return TOX_VERSION_MAJOR;
@@ -136,199 +127,6 @@ uint32_t tox_dht_node_public_key_size(void)
return TOX_DHT_NODE_PUBLIC_KEY_SIZE;
}
-bool tox_options_get_ipv6_enabled(const Tox_Options *options)
-{
- return options->ipv6_enabled;
-}
-void tox_options_set_ipv6_enabled(Tox_Options *options, bool ipv6_enabled)
-{
- options->ipv6_enabled = ipv6_enabled;
-}
-bool tox_options_get_udp_enabled(const Tox_Options *options)
-{
- return options->udp_enabled;
-}
-void tox_options_set_udp_enabled(Tox_Options *options, bool udp_enabled)
-{
- options->udp_enabled = udp_enabled;
-}
-Tox_Proxy_Type tox_options_get_proxy_type(const Tox_Options *options)
-{
- return options->proxy_type;
-}
-void tox_options_set_proxy_type(Tox_Options *options, Tox_Proxy_Type proxy_type)
-{
- options->proxy_type = proxy_type;
-}
-const char *tox_options_get_proxy_host(const Tox_Options *options)
-{
- return options->proxy_host;
-}
-void tox_options_set_proxy_host(Tox_Options *options, const char *proxy_host)
-{
- options->proxy_host = proxy_host;
-}
-uint16_t tox_options_get_proxy_port(const Tox_Options *options)
-{
- return options->proxy_port;
-}
-void tox_options_set_proxy_port(Tox_Options *options, uint16_t proxy_port)
-{
- options->proxy_port = proxy_port;
-}
-uint16_t tox_options_get_start_port(const Tox_Options *options)
-{
- return options->start_port;
-}
-void tox_options_set_start_port(Tox_Options *options, uint16_t start_port)
-{
- options->start_port = start_port;
-}
-uint16_t tox_options_get_end_port(const Tox_Options *options)
-{
- return options->end_port;
-}
-void tox_options_set_end_port(Tox_Options *options, uint16_t end_port)
-{
- options->end_port = end_port;
-}
-uint16_t tox_options_get_tcp_port(const Tox_Options *options)
-{
- return options->tcp_port;
-}
-void tox_options_set_tcp_port(Tox_Options *options, uint16_t tcp_port)
-{
- options->tcp_port = tcp_port;
-}
-bool tox_options_get_hole_punching_enabled(const Tox_Options *options)
-{
- return options->hole_punching_enabled;
-}
-void tox_options_set_hole_punching_enabled(Tox_Options *options, bool hole_punching_enabled)
-{
- options->hole_punching_enabled = hole_punching_enabled;
-}
-Tox_Savedata_Type tox_options_get_savedata_type(const Tox_Options *options)
-{
- return options->savedata_type;
-}
-void tox_options_set_savedata_type(Tox_Options *options, Tox_Savedata_Type savedata_type)
-{
- options->savedata_type = savedata_type;
-}
-size_t tox_options_get_savedata_length(const Tox_Options *options)
-{
- return options->savedata_length;
-}
-void tox_options_set_savedata_length(Tox_Options *options, size_t savedata_length)
-{
- options->savedata_length = savedata_length;
-}
-tox_log_cb *tox_options_get_log_callback(const Tox_Options *options)
-{
- return options->log_callback;
-}
-void tox_options_set_log_callback(Tox_Options *options, tox_log_cb *log_callback)
-{
- options->log_callback = log_callback;
-}
-void *tox_options_get_log_user_data(const Tox_Options *options)
-{
- return options->log_user_data;
-}
-void tox_options_set_log_user_data(Tox_Options *options, void *log_user_data)
-{
- options->log_user_data = log_user_data;
-}
-bool tox_options_get_local_discovery_enabled(const Tox_Options *options)
-{
- return options->local_discovery_enabled;
-}
-void tox_options_set_local_discovery_enabled(Tox_Options *options, bool local_discovery_enabled)
-{
- options->local_discovery_enabled = local_discovery_enabled;
-}
-bool tox_options_get_dht_announcements_enabled(const Tox_Options *options)
-{
- return options->dht_announcements_enabled;
-}
-void tox_options_set_dht_announcements_enabled(Tox_Options *options, bool dht_announcements_enabled)
-{
- options->dht_announcements_enabled = dht_announcements_enabled;
-}
-bool tox_options_get_experimental_thread_safety(const Tox_Options *options)
-{
- return options->experimental_thread_safety;
-}
-void tox_options_set_experimental_thread_safety(
- Tox_Options *options, bool experimental_thread_safety)
-{
- options->experimental_thread_safety = experimental_thread_safety;
-}
-const Tox_System *tox_options_get_operating_system(const Tox_Options *options)
-{
- return options->operating_system;
-}
-void tox_options_set_operating_system(Tox_Options *options, const Tox_System *operating_system)
-{
- options->operating_system = operating_system;
-}
-bool tox_options_get_experimental_groups_persistence(const Tox_Options *options)
-{
- return options->experimental_groups_persistence;
-}
-void tox_options_set_experimental_groups_persistence(
- Tox_Options *options, bool experimental_groups_persistence)
-{
- options->experimental_groups_persistence = experimental_groups_persistence;
-}
-
-const uint8_t *tox_options_get_savedata_data(const Tox_Options *options)
-{
- return options->savedata_data;
-}
-
-void tox_options_set_savedata_data(Tox_Options *options, const uint8_t *savedata_data, size_t length)
-{
- options->savedata_data = savedata_data;
- options->savedata_length = length;
-}
-
-void tox_options_default(Tox_Options *options)
-{
- if (options != nullptr) {
- const Tox_Options default_options = {false};
- *options = default_options;
- tox_options_set_ipv6_enabled(options, true);
- tox_options_set_udp_enabled(options, true);
- tox_options_set_proxy_type(options, TOX_PROXY_TYPE_NONE);
- tox_options_set_hole_punching_enabled(options, true);
- tox_options_set_local_discovery_enabled(options, true);
- tox_options_set_dht_announcements_enabled(options, true);
- tox_options_set_experimental_thread_safety(options, false);
- tox_options_set_experimental_groups_persistence(options, false);
- }
-}
-
-Tox_Options *tox_options_new(Tox_Err_Options_New *error)
-{
- Tox_Options *options = (Tox_Options *)calloc(1, sizeof(Tox_Options));
-
- if (options != nullptr) {
- tox_options_default(options);
- SET_ERROR_PARAMETER(error, TOX_ERR_OPTIONS_NEW_OK);
- return options;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_OPTIONS_NEW_MALLOC);
- return nullptr;
-}
-
-void tox_options_free(Tox_Options *options)
-{
- free(options);
-}
-
const char *tox_user_status_to_string(Tox_User_Status value)
{
switch (value) {
@@ -386,27 +184,6 @@ const char *tox_savedata_type_to_string(Tox_Savedata_Type value)
return "<invalid Tox_Savedata_Type>";
}
-const char *tox_log_level_to_string(Tox_Log_Level value)
-{
- switch (value) {
- case TOX_LOG_LEVEL_TRACE:
- return "TOX_LOG_LEVEL_TRACE";
-
- case TOX_LOG_LEVEL_DEBUG:
- return "TOX_LOG_LEVEL_DEBUG";
-
- case TOX_LOG_LEVEL_INFO:
- return "TOX_LOG_LEVEL_INFO";
-
- case TOX_LOG_LEVEL_WARNING:
- return "TOX_LOG_LEVEL_WARNING";
-
- case TOX_LOG_LEVEL_ERROR:
- return "TOX_LOG_LEVEL_ERROR";
- }
-
- return "<invalid Tox_Log_Level>";
-}
const char *tox_err_options_new_to_string(Tox_Err_Options_New value)
{
switch (value) {
@@ -895,6 +672,9 @@ const char *tox_err_conference_join_to_string(Tox_Err_Conference_Join value)
case TOX_ERR_CONFERENCE_JOIN_FAIL_SEND:
return "TOX_ERR_CONFERENCE_JOIN_FAIL_SEND";
+
+ case TOX_ERR_CONFERENCE_JOIN_NULL:
+ return "TOX_ERR_CONFERENCE_JOIN_NULL";
}
return "<invalid Tox_Err_Conference_Join>";
@@ -1253,17 +1033,17 @@ const char *tox_err_group_peer_query_to_string(Tox_Err_Group_Peer_Query value)
return "<invalid Tox_Err_Group_Peer_Query>";
}
-const char *tox_err_group_state_queries_to_string(Tox_Err_Group_State_Queries value)
+const char *tox_err_group_state_query_to_string(Tox_Err_Group_State_Query value)
{
switch (value) {
- case TOX_ERR_GROUP_STATE_QUERIES_OK:
- return "TOX_ERR_GROUP_STATE_QUERIES_OK";
+ case TOX_ERR_GROUP_STATE_QUERY_OK:
+ return "TOX_ERR_GROUP_STATE_QUERY_OK";
- case TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND:
- return "TOX_ERR_GROUP_STATE_QUERIES_GROUP_NOT_FOUND";
+ case TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_STATE_QUERY_GROUP_NOT_FOUND";
}
- return "<invalid Tox_Err_Group_State_Queries>";
+ return "<invalid Tox_Err_Group_State_Query>";
}
const char *tox_err_group_topic_set_to_string(Tox_Err_Group_Topic_Set value)
{
@@ -1340,6 +1120,9 @@ const char *tox_err_group_send_private_message_to_string(Tox_Err_Group_Send_Priv
case TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_EMPTY:
return "TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_EMPTY";
+ case TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_BAD_TYPE:
+ return "TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_BAD_TYPE";
+
case TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PERMISSIONS:
return "TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PERMISSIONS";
@@ -1348,9 +1131,6 @@ const char *tox_err_group_send_private_message_to_string(Tox_Err_Group_Send_Priv
case TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_DISCONNECTED:
return "TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_DISCONNECTED";
-
- case TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_BAD_TYPE:
- return "TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_BAD_TYPE";
}
return "<invalid Tox_Err_Group_Send_Private_Message>";
@@ -1370,9 +1150,6 @@ const char *tox_err_group_send_custom_packet_to_string(Tox_Err_Group_Send_Custom
case TOX_ERR_GROUP_SEND_CUSTOM_PACKET_EMPTY:
return "TOX_ERR_GROUP_SEND_CUSTOM_PACKET_EMPTY";
- case TOX_ERR_GROUP_SEND_CUSTOM_PACKET_PERMISSIONS:
- return "TOX_ERR_GROUP_SEND_CUSTOM_PACKET_PERMISSIONS";
-
case TOX_ERR_GROUP_SEND_CUSTOM_PACKET_DISCONNECTED:
return "TOX_ERR_GROUP_SEND_CUSTOM_PACKET_DISCONNECTED";
@@ -1400,9 +1177,6 @@ const char *tox_err_group_send_custom_private_packet_to_string(Tox_Err_Group_Sen
case TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_PEER_NOT_FOUND:
return "TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_PEER_NOT_FOUND";
- case TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_PERMISSIONS:
- return "TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_PERMISSIONS";
-
case TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_FAIL_SEND:
return "TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_FAIL_SEND";
@@ -1457,11 +1231,14 @@ const char *tox_err_group_invite_accept_to_string(Tox_Err_Group_Invite_Accept va
case TOX_ERR_GROUP_INVITE_ACCEPT_PASSWORD:
return "TOX_ERR_GROUP_INVITE_ACCEPT_PASSWORD";
- case TOX_ERR_GROUP_INVITE_ACCEPT_CORE:
- return "TOX_ERR_GROUP_INVITE_ACCEPT_CORE";
+ case TOX_ERR_GROUP_INVITE_ACCEPT_FRIEND_NOT_FOUND:
+ return "TOX_ERR_GROUP_INVITE_ACCEPT_FRIEND_NOT_FOUND";
case TOX_ERR_GROUP_INVITE_ACCEPT_FAIL_SEND:
return "TOX_ERR_GROUP_INVITE_ACCEPT_FAIL_SEND";
+
+ case TOX_ERR_GROUP_INVITE_ACCEPT_NULL:
+ return "TOX_ERR_GROUP_INVITE_ACCEPT_NULL";
}
return "<invalid Tox_Err_Group_Invite_Accept>";
@@ -1505,131 +1282,131 @@ const char *tox_group_join_fail_to_string(Tox_Group_Join_Fail value)
return "<invalid Tox_Group_Join_Fail>";
}
-const char *tox_err_group_founder_set_password_to_string(Tox_Err_Group_Founder_Set_Password value)
+const char *tox_err_group_set_password_to_string(Tox_Err_Group_Set_Password value)
{
switch (value) {
- case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK:
- return "TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK";
+ case TOX_ERR_GROUP_SET_PASSWORD_OK:
+ return "TOX_ERR_GROUP_SET_PASSWORD_OK";
- case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_GROUP_NOT_FOUND:
- return "TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_GROUP_NOT_FOUND";
+ case TOX_ERR_GROUP_SET_PASSWORD_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_SET_PASSWORD_GROUP_NOT_FOUND";
- case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_PERMISSIONS:
- return "TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_PERMISSIONS";
+ case TOX_ERR_GROUP_SET_PASSWORD_PERMISSIONS:
+ return "TOX_ERR_GROUP_SET_PASSWORD_PERMISSIONS";
- case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_TOO_LONG:
- return "TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_TOO_LONG";
+ case TOX_ERR_GROUP_SET_PASSWORD_TOO_LONG:
+ return "TOX_ERR_GROUP_SET_PASSWORD_TOO_LONG";
- case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_FAIL_SEND:
- return "TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_FAIL_SEND";
+ case TOX_ERR_GROUP_SET_PASSWORD_FAIL_SEND:
+ return "TOX_ERR_GROUP_SET_PASSWORD_FAIL_SEND";
- case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_MALLOC:
- return "TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_MALLOC";
+ case TOX_ERR_GROUP_SET_PASSWORD_MALLOC:
+ return "TOX_ERR_GROUP_SET_PASSWORD_MALLOC";
- case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_DISCONNECTED:
- return "TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_DISCONNECTED";
+ case TOX_ERR_GROUP_SET_PASSWORD_DISCONNECTED:
+ return "TOX_ERR_GROUP_SET_PASSWORD_DISCONNECTED";
}
- return "<invalid Tox_Err_Group_Founder_Set_Password>";
+ return "<invalid Tox_Err_Group_Set_Password>";
}
-const char *tox_err_group_founder_set_topic_lock_to_string(Tox_Err_Group_Founder_Set_Topic_Lock value)
+const char *tox_err_group_set_topic_lock_to_string(Tox_Err_Group_Set_Topic_Lock value)
{
switch (value) {
- case TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK:
- return "TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK";
+ case TOX_ERR_GROUP_SET_TOPIC_LOCK_OK:
+ return "TOX_ERR_GROUP_SET_TOPIC_LOCK_OK";
- case TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_GROUP_NOT_FOUND:
- return "TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_GROUP_NOT_FOUND";
+ case TOX_ERR_GROUP_SET_TOPIC_LOCK_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_SET_TOPIC_LOCK_GROUP_NOT_FOUND";
- case TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_INVALID:
- return "TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_INVALID";
+ case TOX_ERR_GROUP_SET_TOPIC_LOCK_INVALID:
+ return "TOX_ERR_GROUP_SET_TOPIC_LOCK_INVALID";
- case TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_PERMISSIONS:
- return "TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_PERMISSIONS";
+ case TOX_ERR_GROUP_SET_TOPIC_LOCK_PERMISSIONS:
+ return "TOX_ERR_GROUP_SET_TOPIC_LOCK_PERMISSIONS";
- case TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_FAIL_SET:
- return "TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_FAIL_SET";
+ case TOX_ERR_GROUP_SET_TOPIC_LOCK_FAIL_SET:
+ return "TOX_ERR_GROUP_SET_TOPIC_LOCK_FAIL_SET";
- case TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_FAIL_SEND:
- return "TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_FAIL_SEND";
+ case TOX_ERR_GROUP_SET_TOPIC_LOCK_FAIL_SEND:
+ return "TOX_ERR_GROUP_SET_TOPIC_LOCK_FAIL_SEND";
- case TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_DISCONNECTED:
- return "TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_DISCONNECTED";
+ case TOX_ERR_GROUP_SET_TOPIC_LOCK_DISCONNECTED:
+ return "TOX_ERR_GROUP_SET_TOPIC_LOCK_DISCONNECTED";
}
- return "<invalid Tox_Err_Group_Founder_Set_Topic_Lock>";
+ return "<invalid Tox_Err_Group_Set_Topic_Lock>";
}
-const char *tox_err_group_founder_set_voice_state_to_string(Tox_Err_Group_Founder_Set_Voice_State value)
+const char *tox_err_group_set_voice_state_to_string(Tox_Err_Group_Set_Voice_State value)
{
switch (value) {
- case TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_OK:
- return "TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_OK";
+ case TOX_ERR_GROUP_SET_VOICE_STATE_OK:
+ return "TOX_ERR_GROUP_SET_VOICE_STATE_OK";
- case TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_GROUP_NOT_FOUND:
- return "TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_GROUP_NOT_FOUND";
+ case TOX_ERR_GROUP_SET_VOICE_STATE_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_SET_VOICE_STATE_GROUP_NOT_FOUND";
- case TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_PERMISSIONS:
- return "TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_PERMISSIONS";
+ case TOX_ERR_GROUP_SET_VOICE_STATE_PERMISSIONS:
+ return "TOX_ERR_GROUP_SET_VOICE_STATE_PERMISSIONS";
- case TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_FAIL_SET:
- return "TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_FAIL_SET";
+ case TOX_ERR_GROUP_SET_VOICE_STATE_FAIL_SET:
+ return "TOX_ERR_GROUP_SET_VOICE_STATE_FAIL_SET";
- case TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_FAIL_SEND:
- return "TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_FAIL_SEND";
+ case TOX_ERR_GROUP_SET_VOICE_STATE_FAIL_SEND:
+ return "TOX_ERR_GROUP_SET_VOICE_STATE_FAIL_SEND";
- case TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_DISCONNECTED:
- return "TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_DISCONNECTED";
+ case TOX_ERR_GROUP_SET_VOICE_STATE_DISCONNECTED:
+ return "TOX_ERR_GROUP_SET_VOICE_STATE_DISCONNECTED";
}
- return "<invalid Tox_Err_Group_Founder_Set_Voice_State>";
+ return "<invalid Tox_Err_Group_Set_Voice_State>";
}
-const char *tox_err_group_founder_set_privacy_state_to_string(Tox_Err_Group_Founder_Set_Privacy_State value)
+const char *tox_err_group_set_privacy_state_to_string(Tox_Err_Group_Set_Privacy_State value)
{
switch (value) {
- case TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK:
- return "TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK";
+ case TOX_ERR_GROUP_SET_PRIVACY_STATE_OK:
+ return "TOX_ERR_GROUP_SET_PRIVACY_STATE_OK";
- case TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_GROUP_NOT_FOUND:
- return "TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_GROUP_NOT_FOUND";
+ case TOX_ERR_GROUP_SET_PRIVACY_STATE_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_SET_PRIVACY_STATE_GROUP_NOT_FOUND";
- case TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_PERMISSIONS:
- return "TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_PERMISSIONS";
+ case TOX_ERR_GROUP_SET_PRIVACY_STATE_PERMISSIONS:
+ return "TOX_ERR_GROUP_SET_PRIVACY_STATE_PERMISSIONS";
- case TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SET:
- return "TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SET";
+ case TOX_ERR_GROUP_SET_PRIVACY_STATE_FAIL_SET:
+ return "TOX_ERR_GROUP_SET_PRIVACY_STATE_FAIL_SET";
- case TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SEND:
- return "TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_FAIL_SEND";
+ case TOX_ERR_GROUP_SET_PRIVACY_STATE_FAIL_SEND:
+ return "TOX_ERR_GROUP_SET_PRIVACY_STATE_FAIL_SEND";
- case TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_DISCONNECTED:
- return "TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_DISCONNECTED";
+ case TOX_ERR_GROUP_SET_PRIVACY_STATE_DISCONNECTED:
+ return "TOX_ERR_GROUP_SET_PRIVACY_STATE_DISCONNECTED";
}
- return "<invalid Tox_Err_Group_Founder_Set_Privacy_State>";
+ return "<invalid Tox_Err_Group_Set_Privacy_State>";
}
-const char *tox_err_group_founder_set_peer_limit_to_string(Tox_Err_Group_Founder_Set_Peer_Limit value)
+const char *tox_err_group_set_peer_limit_to_string(Tox_Err_Group_Set_Peer_Limit value)
{
switch (value) {
- case TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK:
- return "TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK";
+ case TOX_ERR_GROUP_SET_PEER_LIMIT_OK:
+ return "TOX_ERR_GROUP_SET_PEER_LIMIT_OK";
- case TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_GROUP_NOT_FOUND:
- return "TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_GROUP_NOT_FOUND";
+ case TOX_ERR_GROUP_SET_PEER_LIMIT_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_SET_PEER_LIMIT_GROUP_NOT_FOUND";
- case TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_PERMISSIONS:
- return "TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_PERMISSIONS";
+ case TOX_ERR_GROUP_SET_PEER_LIMIT_PERMISSIONS:
+ return "TOX_ERR_GROUP_SET_PEER_LIMIT_PERMISSIONS";
- case TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SET:
- return "TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SET";
+ case TOX_ERR_GROUP_SET_PEER_LIMIT_FAIL_SET:
+ return "TOX_ERR_GROUP_SET_PEER_LIMIT_FAIL_SET";
- case TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SEND:
- return "TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_FAIL_SEND";
+ case TOX_ERR_GROUP_SET_PEER_LIMIT_FAIL_SEND:
+ return "TOX_ERR_GROUP_SET_PEER_LIMIT_FAIL_SEND";
- case TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_DISCONNECTED:
- return "TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_DISCONNECTED";
+ case TOX_ERR_GROUP_SET_PEER_LIMIT_DISCONNECTED:
+ return "TOX_ERR_GROUP_SET_PEER_LIMIT_DISCONNECTED";
}
- return "<invalid Tox_Err_Group_Founder_Set_Peer_Limit>";
+ return "<invalid Tox_Err_Group_Set_Peer_Limit>";
}
const char *tox_err_group_set_ignore_to_string(Tox_Err_Group_Set_Ignore value)
{
@@ -1649,59 +1426,59 @@ const char *tox_err_group_set_ignore_to_string(Tox_Err_Group_Set_Ignore value)
return "<invalid Tox_Err_Group_Set_Ignore>";
}
-const char *tox_err_group_mod_set_role_to_string(Tox_Err_Group_Mod_Set_Role value)
+const char *tox_err_group_set_role_to_string(Tox_Err_Group_Set_Role value)
{
switch (value) {
- case TOX_ERR_GROUP_MOD_SET_ROLE_OK:
- return "TOX_ERR_GROUP_MOD_SET_ROLE_OK";
+ case TOX_ERR_GROUP_SET_ROLE_OK:
+ return "TOX_ERR_GROUP_SET_ROLE_OK";
- case TOX_ERR_GROUP_MOD_SET_ROLE_GROUP_NOT_FOUND:
- return "TOX_ERR_GROUP_MOD_SET_ROLE_GROUP_NOT_FOUND";
+ case TOX_ERR_GROUP_SET_ROLE_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_SET_ROLE_GROUP_NOT_FOUND";
- case TOX_ERR_GROUP_MOD_SET_ROLE_PEER_NOT_FOUND:
- return "TOX_ERR_GROUP_MOD_SET_ROLE_PEER_NOT_FOUND";
+ case TOX_ERR_GROUP_SET_ROLE_PEER_NOT_FOUND:
+ return "TOX_ERR_GROUP_SET_ROLE_PEER_NOT_FOUND";
- case TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS:
- return "TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS";
+ case TOX_ERR_GROUP_SET_ROLE_PERMISSIONS:
+ return "TOX_ERR_GROUP_SET_ROLE_PERMISSIONS";
- case TOX_ERR_GROUP_MOD_SET_ROLE_ASSIGNMENT:
- return "TOX_ERR_GROUP_MOD_SET_ROLE_ASSIGNMENT";
+ case TOX_ERR_GROUP_SET_ROLE_ASSIGNMENT:
+ return "TOX_ERR_GROUP_SET_ROLE_ASSIGNMENT";
- case TOX_ERR_GROUP_MOD_SET_ROLE_FAIL_ACTION:
- return "TOX_ERR_GROUP_MOD_SET_ROLE_FAIL_ACTION";
+ case TOX_ERR_GROUP_SET_ROLE_FAIL_ACTION:
+ return "TOX_ERR_GROUP_SET_ROLE_FAIL_ACTION";
- case TOX_ERR_GROUP_MOD_SET_ROLE_SELF:
- return "TOX_ERR_GROUP_MOD_SET_ROLE_SELF";
+ case TOX_ERR_GROUP_SET_ROLE_SELF:
+ return "TOX_ERR_GROUP_SET_ROLE_SELF";
}
- return "<invalid Tox_Err_Group_Mod_Set_Role>";
+ return "<invalid Tox_Err_Group_Set_Role>";
}
-const char *tox_err_group_mod_kick_peer_to_string(Tox_Err_Group_Mod_Kick_Peer value)
+const char *tox_err_group_kick_peer_to_string(Tox_Err_Group_Kick_Peer value)
{
switch (value) {
- case TOX_ERR_GROUP_MOD_KICK_PEER_OK:
- return "TOX_ERR_GROUP_MOD_KICK_PEER_OK";
+ case TOX_ERR_GROUP_KICK_PEER_OK:
+ return "TOX_ERR_GROUP_KICK_PEER_OK";
- case TOX_ERR_GROUP_MOD_KICK_PEER_GROUP_NOT_FOUND:
- return "TOX_ERR_GROUP_MOD_KICK_PEER_GROUP_NOT_FOUND";
+ case TOX_ERR_GROUP_KICK_PEER_GROUP_NOT_FOUND:
+ return "TOX_ERR_GROUP_KICK_PEER_GROUP_NOT_FOUND";
- case TOX_ERR_GROUP_MOD_KICK_PEER_PEER_NOT_FOUND:
- return "TOX_ERR_GROUP_MOD_KICK_PEER_PEER_NOT_FOUND";
+ case TOX_ERR_GROUP_KICK_PEER_PEER_NOT_FOUND:
+ return "TOX_ERR_GROUP_KICK_PEER_PEER_NOT_FOUND";
- case TOX_ERR_GROUP_MOD_KICK_PEER_PERMISSIONS:
- return "TOX_ERR_GROUP_MOD_KICK_PEER_PERMISSIONS";
+ case TOX_ERR_GROUP_KICK_PEER_PERMISSIONS:
+ return "TOX_ERR_GROUP_KICK_PEER_PERMISSIONS";
- case TOX_ERR_GROUP_MOD_KICK_PEER_FAIL_ACTION:
- return "TOX_ERR_GROUP_MOD_KICK_PEER_FAIL_ACTION";
+ case TOX_ERR_GROUP_KICK_PEER_FAIL_ACTION:
+ return "TOX_ERR_GROUP_KICK_PEER_FAIL_ACTION";
- case TOX_ERR_GROUP_MOD_KICK_PEER_FAIL_SEND:
- return "TOX_ERR_GROUP_MOD_KICK_PEER_FAIL_SEND";
+ case TOX_ERR_GROUP_KICK_PEER_FAIL_SEND:
+ return "TOX_ERR_GROUP_KICK_PEER_FAIL_SEND";
- case TOX_ERR_GROUP_MOD_KICK_PEER_SELF:
- return "TOX_ERR_GROUP_MOD_KICK_PEER_SELF";
+ case TOX_ERR_GROUP_KICK_PEER_SELF:
+ return "TOX_ERR_GROUP_KICK_PEER_SELF";
}
- return "<invalid Tox_Err_Group_Mod_Kick_Peer>";
+ return "<invalid Tox_Err_Group_Kick_Peer>";
}
const char *tox_group_mod_event_to_string(Tox_Group_Mod_Event value)
{
@@ -1721,3 +1498,120 @@ const char *tox_group_mod_event_to_string(Tox_Group_Mod_Event value)
return "<invalid Tox_Group_Mod_Event>";
}
+const char *tox_netprof_packet_id_to_string(Tox_Netprof_Packet_Id value)
+{
+ switch (value) {
+ case TOX_NETPROF_PACKET_ID_ZERO:
+ return "TOX_NETPROF_PACKET_ID_ZERO";
+ case TOX_NETPROF_PACKET_ID_ONE:
+ return "TOX_NETPROF_PACKET_ID_ONE";
+ case TOX_NETPROF_PACKET_ID_TWO:
+ return "TOX_NETPROF_PACKET_ID_TWO";
+ case TOX_NETPROF_PACKET_ID_TCP_DISCONNECT:
+ return "TOX_NETPROF_PACKET_ID_TCP_DISCONNECT";
+ case TOX_NETPROF_PACKET_ID_FOUR:
+ return "TOX_NETPROF_PACKET_ID_FOUR";
+ case TOX_NETPROF_PACKET_ID_TCP_PONG:
+ return "TOX_NETPROF_PACKET_ID_TCP_PONG";
+ case TOX_NETPROF_PACKET_ID_TCP_OOB_SEND:
+ return "TOX_NETPROF_PACKET_ID_TCP_OOB_SEND";
+ case TOX_NETPROF_PACKET_ID_TCP_OOB_RECV:
+ return "TOX_NETPROF_PACKET_ID_TCP_OOB_RECV";
+ case TOX_NETPROF_PACKET_ID_TCP_ONION_REQUEST:
+ return "TOX_NETPROF_PACKET_ID_TCP_ONION_REQUEST";
+ case TOX_NETPROF_PACKET_ID_TCP_ONION_RESPONSE:
+ return "TOX_NETPROF_PACKET_ID_TCP_ONION_RESPONSE";
+ case TOX_NETPROF_PACKET_ID_TCP_DATA:
+ return "TOX_NETPROF_PACKET_ID_TCP_DATA";
+ case TOX_NETPROF_PACKET_ID_COOKIE_REQUEST:
+ return "TOX_NETPROF_PACKET_ID_COOKIE_REQUEST";
+ case TOX_NETPROF_PACKET_ID_COOKIE_RESPONSE:
+ return "TOX_NETPROF_PACKET_ID_COOKIE_RESPONSE";
+ case TOX_NETPROF_PACKET_ID_CRYPTO_HS:
+ return "TOX_NETPROF_PACKET_ID_CRYPTO_HS";
+ case TOX_NETPROF_PACKET_ID_CRYPTO_DATA:
+ return "TOX_NETPROF_PACKET_ID_CRYPTO_DATA";
+ case TOX_NETPROF_PACKET_ID_CRYPTO:
+ return "TOX_NETPROF_PACKET_ID_CRYPTO";
+ case TOX_NETPROF_PACKET_ID_LAN_DISCOVERY:
+ return "TOX_NETPROF_PACKET_ID_LAN_DISCOVERY";
+ case TOX_NETPROF_PACKET_ID_GC_HANDSHAKE:
+ return "TOX_NETPROF_PACKET_ID_GC_HANDSHAKE";
+ case TOX_NETPROF_PACKET_ID_GC_LOSSLESS:
+ return "TOX_NETPROF_PACKET_ID_GC_LOSSLESS";
+ case TOX_NETPROF_PACKET_ID_GC_LOSSY:
+ return "TOX_NETPROF_PACKET_ID_GC_LOSSY";
+ case TOX_NETPROF_PACKET_ID_ONION_SEND_INITIAL:
+ return "TOX_NETPROF_PACKET_ID_ONION_SEND_INITIAL";
+ case TOX_NETPROF_PACKET_ID_ONION_SEND_1:
+ return "TOX_NETPROF_PACKET_ID_ONION_SEND_1";
+ case TOX_NETPROF_PACKET_ID_ONION_SEND_2:
+ return "TOX_NETPROF_PACKET_ID_ONION_SEND_2";
+ case TOX_NETPROF_PACKET_ID_ANNOUNCE_REQUEST_OLD:
+ return "TOX_NETPROF_PACKET_ID_ANNOUNCE_REQUEST_OLD";
+ case TOX_NETPROF_PACKET_ID_ANNOUNCE_RESPONSE_OLD:
+ return "TOX_NETPROF_PACKET_ID_ANNOUNCE_RESPONSE_OLD";
+ case TOX_NETPROF_PACKET_ID_ONION_DATA_REQUEST:
+ return "TOX_NETPROF_PACKET_ID_ONION_DATA_REQUEST";
+ case TOX_NETPROF_PACKET_ID_ONION_DATA_RESPONSE:
+ return "TOX_NETPROF_PACKET_ID_ONION_DATA_RESPONSE";
+ case TOX_NETPROF_PACKET_ID_ANNOUNCE_REQUEST:
+ return "TOX_NETPROF_PACKET_ID_ANNOUNCE_REQUEST";
+ case TOX_NETPROF_PACKET_ID_ANNOUNCE_RESPONSE:
+ return "TOX_NETPROF_PACKET_ID_ANNOUNCE_RESPONSE";
+ case TOX_NETPROF_PACKET_ID_ONION_RECV_3:
+ return "TOX_NETPROF_PACKET_ID_ONION_RECV_3";
+ case TOX_NETPROF_PACKET_ID_ONION_RECV_2:
+ return "TOX_NETPROF_PACKET_ID_ONION_RECV_2";
+ case TOX_NETPROF_PACKET_ID_ONION_RECV_1:
+ return "TOX_NETPROF_PACKET_ID_ONION_RECV_1";
+ case TOX_NETPROF_PACKET_ID_FORWARD_REQUEST:
+ return "TOX_NETPROF_PACKET_ID_FORWARD_REQUEST";
+ case TOX_NETPROF_PACKET_ID_FORWARDING:
+ return "TOX_NETPROF_PACKET_ID_FORWARDING";
+ case TOX_NETPROF_PACKET_ID_FORWARD_REPLY:
+ return "TOX_NETPROF_PACKET_ID_FORWARD_REPLY";
+ case TOX_NETPROF_PACKET_ID_DATA_SEARCH_REQUEST:
+ return "TOX_NETPROF_PACKET_ID_DATA_SEARCH_REQUEST";
+ case TOX_NETPROF_PACKET_ID_DATA_SEARCH_RESPONSE:
+ return "TOX_NETPROF_PACKET_ID_DATA_SEARCH_RESPONSE";
+ case TOX_NETPROF_PACKET_ID_DATA_RETRIEVE_REQUEST:
+ return "TOX_NETPROF_PACKET_ID_DATA_RETRIEVE_REQUEST";
+ case TOX_NETPROF_PACKET_ID_DATA_RETRIEVE_RESPONSE:
+ return "TOX_NETPROF_PACKET_ID_DATA_RETRIEVE_RESPONSE";
+ case TOX_NETPROF_PACKET_ID_STORE_ANNOUNCE_REQUEST:
+ return "TOX_NETPROF_PACKET_ID_STORE_ANNOUNCE_REQUEST";
+ case TOX_NETPROF_PACKET_ID_STORE_ANNOUNCE_RESPONSE:
+ return "TOX_NETPROF_PACKET_ID_STORE_ANNOUNCE_RESPONSE";
+ case TOX_NETPROF_PACKET_ID_BOOTSTRAP_INFO:
+ return "TOX_NETPROF_PACKET_ID_BOOTSTRAP_INFO";
+ }
+
+ return "<invalid Tox_Netprof_Packet_Id>";
+}
+const char *tox_netprof_packet_type_to_string(Tox_Netprof_Packet_Type value)
+{
+ switch (value) {
+ case TOX_NETPROF_PACKET_TYPE_TCP_CLIENT:
+ return "TOX_NETPROF_PACKET_TYPE_TCP_CLIENT";
+ case TOX_NETPROF_PACKET_TYPE_TCP_SERVER:
+ return "TOX_NETPROF_PACKET_TYPE_TCP_SERVER";
+ case TOX_NETPROF_PACKET_TYPE_TCP:
+ return "TOX_NETPROF_PACKET_TYPE_TCP";
+ case TOX_NETPROF_PACKET_TYPE_UDP:
+ return "TOX_NETPROF_PACKET_TYPE_UDP";
+ }
+
+ return "<invalid Tox_Netprof_Packet_Type>";
+}
+const char *tox_netprof_direction_to_string(Tox_Netprof_Direction value)
+{
+ switch (value) {
+ case TOX_NETPROF_DIRECTION_SENT:
+ return "TOX_NETPROF_DIRECTION_SENT";
+ case TOX_NETPROF_DIRECTION_RECV:
+ return "TOX_NETPROF_DIRECTION_RECV";
+ }
+
+ return "<invalid Tox_Netprof_Direction>";
+}
diff --git a/protocols/Tox/libtox/src/toxcore/tox_dispatch.c b/protocols/Tox/libtox/src/toxcore/tox_dispatch.c
index 5383925bfa..c793f6b582 100644
--- a/protocols/Tox/libtox/src/toxcore/tox_dispatch.c
+++ b/protocols/Tox/libtox/src/toxcore/tox_dispatch.c
@@ -1,15 +1,15 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2022-2025 The TokTok team.
*/
#include "tox_dispatch.h"
+#include <stdint.h>
#include <stdlib.h>
#include "attributes.h"
#include "ccompat.h"
#include "events/events_alloc.h" // IWYU pragma: keep
-#include "tox.h"
#include "tox_event.h"
#include "tox_events.h"
@@ -53,7 +53,7 @@ struct Tox_Dispatch {
tox_events_group_self_join_cb *group_self_join_callback;
tox_events_group_join_fail_cb *group_join_fail_callback;
tox_events_group_moderation_cb *group_moderation_callback;
- tox_events_dht_get_nodes_response_cb *dht_get_nodes_response_callback;
+ tox_events_dht_nodes_response_cb *dht_nodes_response_callback;
};
Tox_Dispatch *tox_dispatch_new(Tox_Err_Dispatch_New *error)
@@ -279,10 +279,10 @@ void tox_events_callback_group_moderation(
{
dispatch->group_moderation_callback = callback;
}
-void tox_events_callback_dht_get_nodes_response(
- Tox_Dispatch *dispatch, tox_events_dht_get_nodes_response_cb *callback)
+void tox_events_callback_dht_nodes_response(
+ Tox_Dispatch *dispatch, tox_events_dht_nodes_response_cb *callback)
{
- dispatch->dht_get_nodes_response_callback = callback;
+ dispatch->dht_nodes_response_callback = callback;
}
non_null(1, 2) nullable(3)
@@ -601,9 +601,9 @@ static void tox_dispatch_invoke_event(const Tox_Dispatch *dispatch, const Tox_Ev
break;
}
- case TOX_EVENT_DHT_GET_NODES_RESPONSE: {
- if (dispatch->dht_get_nodes_response_callback != nullptr) {
- dispatch->dht_get_nodes_response_callback(event->data.dht_get_nodes_response, user_data);
+ case TOX_EVENT_DHT_NODES_RESPONSE: {
+ if (dispatch->dht_nodes_response_callback != nullptr) {
+ dispatch->dht_nodes_response_callback(event->data.dht_nodes_response, user_data);
}
break;
diff --git a/protocols/Tox/libtox/src/toxcore/tox_dispatch.h b/protocols/Tox/libtox/src/toxcore/tox_dispatch.h
index 2588065a4d..6ad3fc8b66 100644
--- a/protocols/Tox/libtox/src/toxcore/tox_dispatch.h
+++ b/protocols/Tox/libtox/src/toxcore/tox_dispatch.h
@@ -1,5 +1,12 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2022-2025 The TokTok team.
+ */
+
+/**
+ * WARNING: This is an experimental API and is subject to change.
+ *
+ * At this point, it probably won't change very much anymore, but we may have
+ * small breaking changes before a stable release.
*/
#ifndef C_TOXCORE_TOXCORE_TOX_DISPATCH_H
@@ -129,8 +136,8 @@ typedef void tox_events_group_join_fail_cb(
const Tox_Event_Group_Join_Fail *event, void *user_data);
typedef void tox_events_group_moderation_cb(
const Tox_Event_Group_Moderation *event, void *user_data);
-typedef void tox_events_dht_get_nodes_response_cb(
- const Tox_Event_Dht_Get_Nodes_Response *event, void *user_data);
+typedef void tox_events_dht_nodes_response_cb(
+ const Tox_Event_Dht_Nodes_Response *event, void *user_data);
void tox_events_callback_conference_connected(
Tox_Dispatch *dispatch, tox_events_conference_connected_cb *callback);
@@ -210,8 +217,8 @@ void tox_events_callback_group_join_fail(
Tox_Dispatch *dispatch, tox_events_group_join_fail_cb *callback);
void tox_events_callback_group_moderation(
Tox_Dispatch *dispatch, tox_events_group_moderation_cb *callback);
-void tox_events_callback_dht_get_nodes_response(
- Tox_Dispatch *dispatch, tox_events_dht_get_nodes_response_cb *callback);
+void tox_events_callback_dht_nodes_response(
+ Tox_Dispatch *dispatch, tox_events_dht_nodes_response_cb *callback);
#ifdef __cplusplus
} /* extern "C" */
diff --git a/protocols/Tox/libtox/src/toxcore/tox_event.c b/protocols/Tox/libtox/src/toxcore/tox_event.c
index b0a65503cd..0a08b622e9 100644
--- a/protocols/Tox/libtox/src/toxcore/tox_event.c
+++ b/protocols/Tox/libtox/src/toxcore/tox_event.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2022-2025 The TokTok team.
*/
#include "tox_event.h"
@@ -133,8 +133,8 @@ const char *tox_event_type_to_string(Tox_Event_Type type)
case TOX_EVENT_GROUP_MODERATION:
return "TOX_EVENT_GROUP_MODERATION";
- case TOX_EVENT_DHT_GET_NODES_RESPONSE:
- return "TOX_EVENT_DHT_GET_NODES_RESPONSE";
+ case TOX_EVENT_DHT_NODES_RESPONSE:
+ return "TOX_EVENT_DHT_NODES_RESPONSE";
case TOX_EVENT_INVALID:
return "TOX_EVENT_INVALID";
@@ -350,8 +350,8 @@ bool tox_event_construct(Tox_Event *event, Tox_Event_Type type, const Memory *me
break;
}
- case TOX_EVENT_DHT_GET_NODES_RESPONSE: {
- event->data.dht_get_nodes_response = tox_event_dht_get_nodes_response_new(mem);
+ case TOX_EVENT_DHT_NODES_RESPONSE: {
+ event->data.dht_nodes_response = tox_event_dht_nodes_response_new(mem);
break;
}
@@ -565,8 +565,8 @@ void tox_event_destruct(Tox_Event *event, const Memory *mem)
break;
}
- case TOX_EVENT_DHT_GET_NODES_RESPONSE: {
- tox_event_dht_get_nodes_response_free(event->data.dht_get_nodes_response, mem);
+ case TOX_EVENT_DHT_NODES_RESPONSE: {
+ tox_event_dht_nodes_response_free(event->data.dht_nodes_response, mem);
break;
}
@@ -705,8 +705,8 @@ static bool tox_event_data_pack(Tox_Event_Type type, const Tox_Event_Data *data,
case TOX_EVENT_GROUP_MODERATION:
return tox_event_group_moderation_pack(data->group_moderation, bp);
- case TOX_EVENT_DHT_GET_NODES_RESPONSE:
- return tox_event_dht_get_nodes_response_pack(data->dht_get_nodes_response, bp);
+ case TOX_EVENT_DHT_NODES_RESPONSE:
+ return tox_event_dht_nodes_response_pack(data->dht_nodes_response, bp);
case TOX_EVENT_INVALID:
return false;
@@ -725,216 +725,216 @@ bool tox_event_pack(const Tox_Event *event, Bin_Pack *bp)
}
non_null()
-static bool tox_event_type_from_int(uint32_t value, Tox_Event_Type *out)
+static bool tox_event_type_from_int(uint32_t value, Tox_Event_Type *out_enum)
{
switch (value) {
case TOX_EVENT_SELF_CONNECTION_STATUS: {
- *out = TOX_EVENT_SELF_CONNECTION_STATUS;
+ *out_enum = TOX_EVENT_SELF_CONNECTION_STATUS;
return true;
}
case TOX_EVENT_FRIEND_REQUEST: {
- *out = TOX_EVENT_FRIEND_REQUEST;
+ *out_enum = TOX_EVENT_FRIEND_REQUEST;
return true;
}
case TOX_EVENT_FRIEND_CONNECTION_STATUS: {
- *out = TOX_EVENT_FRIEND_CONNECTION_STATUS;
+ *out_enum = TOX_EVENT_FRIEND_CONNECTION_STATUS;
return true;
}
case TOX_EVENT_FRIEND_LOSSY_PACKET: {
- *out = TOX_EVENT_FRIEND_LOSSY_PACKET;
+ *out_enum = TOX_EVENT_FRIEND_LOSSY_PACKET;
return true;
}
case TOX_EVENT_FRIEND_LOSSLESS_PACKET: {
- *out = TOX_EVENT_FRIEND_LOSSLESS_PACKET;
+ *out_enum = TOX_EVENT_FRIEND_LOSSLESS_PACKET;
return true;
}
case TOX_EVENT_FRIEND_NAME: {
- *out = TOX_EVENT_FRIEND_NAME;
+ *out_enum = TOX_EVENT_FRIEND_NAME;
return true;
}
case TOX_EVENT_FRIEND_STATUS: {
- *out = TOX_EVENT_FRIEND_STATUS;
+ *out_enum = TOX_EVENT_FRIEND_STATUS;
return true;
}
case TOX_EVENT_FRIEND_STATUS_MESSAGE: {
- *out = TOX_EVENT_FRIEND_STATUS_MESSAGE;
+ *out_enum = TOX_EVENT_FRIEND_STATUS_MESSAGE;
return true;
}
case TOX_EVENT_FRIEND_MESSAGE: {
- *out = TOX_EVENT_FRIEND_MESSAGE;
+ *out_enum = TOX_EVENT_FRIEND_MESSAGE;
return true;
}
case TOX_EVENT_FRIEND_READ_RECEIPT: {
- *out = TOX_EVENT_FRIEND_READ_RECEIPT;
+ *out_enum = TOX_EVENT_FRIEND_READ_RECEIPT;
return true;
}
case TOX_EVENT_FRIEND_TYPING: {
- *out = TOX_EVENT_FRIEND_TYPING;
+ *out_enum = TOX_EVENT_FRIEND_TYPING;
return true;
}
case TOX_EVENT_FILE_CHUNK_REQUEST: {
- *out = TOX_EVENT_FILE_CHUNK_REQUEST;
+ *out_enum = TOX_EVENT_FILE_CHUNK_REQUEST;
return true;
}
case TOX_EVENT_FILE_RECV: {
- *out = TOX_EVENT_FILE_RECV;
+ *out_enum = TOX_EVENT_FILE_RECV;
return true;
}
case TOX_EVENT_FILE_RECV_CHUNK: {
- *out = TOX_EVENT_FILE_RECV_CHUNK;
+ *out_enum = TOX_EVENT_FILE_RECV_CHUNK;
return true;
}
case TOX_EVENT_FILE_RECV_CONTROL: {
- *out = TOX_EVENT_FILE_RECV_CONTROL;
+ *out_enum = TOX_EVENT_FILE_RECV_CONTROL;
return true;
}
case TOX_EVENT_CONFERENCE_INVITE: {
- *out = TOX_EVENT_CONFERENCE_INVITE;
+ *out_enum = TOX_EVENT_CONFERENCE_INVITE;
return true;
}
case TOX_EVENT_CONFERENCE_CONNECTED: {
- *out = TOX_EVENT_CONFERENCE_CONNECTED;
+ *out_enum = TOX_EVENT_CONFERENCE_CONNECTED;
return true;
}
case TOX_EVENT_CONFERENCE_PEER_LIST_CHANGED: {
- *out = TOX_EVENT_CONFERENCE_PEER_LIST_CHANGED;
+ *out_enum = TOX_EVENT_CONFERENCE_PEER_LIST_CHANGED;
return true;
}
case TOX_EVENT_CONFERENCE_PEER_NAME: {
- *out = TOX_EVENT_CONFERENCE_PEER_NAME;
+ *out_enum = TOX_EVENT_CONFERENCE_PEER_NAME;
return true;
}
case TOX_EVENT_CONFERENCE_TITLE: {
- *out = TOX_EVENT_CONFERENCE_TITLE;
+ *out_enum = TOX_EVENT_CONFERENCE_TITLE;
return true;
}
case TOX_EVENT_CONFERENCE_MESSAGE: {
- *out = TOX_EVENT_CONFERENCE_MESSAGE;
+ *out_enum = TOX_EVENT_CONFERENCE_MESSAGE;
return true;
}
case TOX_EVENT_GROUP_PEER_NAME: {
- *out = TOX_EVENT_GROUP_PEER_NAME;
+ *out_enum = TOX_EVENT_GROUP_PEER_NAME;
return true;
}
case TOX_EVENT_GROUP_PEER_STATUS: {
- *out = TOX_EVENT_GROUP_PEER_STATUS;
+ *out_enum = TOX_EVENT_GROUP_PEER_STATUS;
return true;
}
case TOX_EVENT_GROUP_TOPIC: {
- *out = TOX_EVENT_GROUP_TOPIC;
+ *out_enum = TOX_EVENT_GROUP_TOPIC;
return true;
}
case TOX_EVENT_GROUP_PRIVACY_STATE: {
- *out = TOX_EVENT_GROUP_PRIVACY_STATE;
+ *out_enum = TOX_EVENT_GROUP_PRIVACY_STATE;
return true;
}
case TOX_EVENT_GROUP_VOICE_STATE: {
- *out = TOX_EVENT_GROUP_VOICE_STATE;
+ *out_enum = TOX_EVENT_GROUP_VOICE_STATE;
return true;
}
case TOX_EVENT_GROUP_TOPIC_LOCK: {
- *out = TOX_EVENT_GROUP_TOPIC_LOCK;
+ *out_enum = TOX_EVENT_GROUP_TOPIC_LOCK;
return true;
}
case TOX_EVENT_GROUP_PEER_LIMIT: {
- *out = TOX_EVENT_GROUP_PEER_LIMIT;
+ *out_enum = TOX_EVENT_GROUP_PEER_LIMIT;
return true;
}
case TOX_EVENT_GROUP_PASSWORD: {
- *out = TOX_EVENT_GROUP_PASSWORD;
+ *out_enum = TOX_EVENT_GROUP_PASSWORD;
return true;
}
case TOX_EVENT_GROUP_MESSAGE: {
- *out = TOX_EVENT_GROUP_MESSAGE;
+ *out_enum = TOX_EVENT_GROUP_MESSAGE;
return true;
}
case TOX_EVENT_GROUP_PRIVATE_MESSAGE: {
- *out = TOX_EVENT_GROUP_PRIVATE_MESSAGE;
+ *out_enum = TOX_EVENT_GROUP_PRIVATE_MESSAGE;
return true;
}
case TOX_EVENT_GROUP_CUSTOM_PACKET: {
- *out = TOX_EVENT_GROUP_CUSTOM_PACKET;
+ *out_enum = TOX_EVENT_GROUP_CUSTOM_PACKET;
return true;
}
case TOX_EVENT_GROUP_CUSTOM_PRIVATE_PACKET: {
- *out = TOX_EVENT_GROUP_CUSTOM_PRIVATE_PACKET;
+ *out_enum = TOX_EVENT_GROUP_CUSTOM_PRIVATE_PACKET;
return true;
}
case TOX_EVENT_GROUP_INVITE: {
- *out = TOX_EVENT_GROUP_INVITE;
+ *out_enum = TOX_EVENT_GROUP_INVITE;
return true;
}
case TOX_EVENT_GROUP_PEER_JOIN: {
- *out = TOX_EVENT_GROUP_PEER_JOIN;
+ *out_enum = TOX_EVENT_GROUP_PEER_JOIN;
return true;
}
case TOX_EVENT_GROUP_PEER_EXIT: {
- *out = TOX_EVENT_GROUP_PEER_EXIT;
+ *out_enum = TOX_EVENT_GROUP_PEER_EXIT;
return true;
}
case TOX_EVENT_GROUP_SELF_JOIN: {
- *out = TOX_EVENT_GROUP_SELF_JOIN;
+ *out_enum = TOX_EVENT_GROUP_SELF_JOIN;
return true;
}
case TOX_EVENT_GROUP_JOIN_FAIL: {
- *out = TOX_EVENT_GROUP_JOIN_FAIL;
+ *out_enum = TOX_EVENT_GROUP_JOIN_FAIL;
return true;
}
case TOX_EVENT_GROUP_MODERATION: {
- *out = TOX_EVENT_GROUP_MODERATION;
+ *out_enum = TOX_EVENT_GROUP_MODERATION;
return true;
}
- case TOX_EVENT_DHT_GET_NODES_RESPONSE: {
- *out = TOX_EVENT_DHT_GET_NODES_RESPONSE;
+ case TOX_EVENT_DHT_NODES_RESPONSE: {
+ *out_enum = TOX_EVENT_DHT_NODES_RESPONSE;
return true;
}
case TOX_EVENT_INVALID: {
- *out = TOX_EVENT_INVALID;
+ *out_enum = TOX_EVENT_INVALID;
return true;
}
default: {
- *out = TOX_EVENT_INVALID;
+ *out_enum = TOX_EVENT_INVALID;
return false;
}
}
@@ -1069,8 +1069,8 @@ static bool tox_event_data_unpack(Tox_Event_Type type, Tox_Event_Data *data, Bin
case TOX_EVENT_GROUP_MODERATION:
return tox_event_group_moderation_unpack(&data->group_moderation, bu, mem);
- case TOX_EVENT_DHT_GET_NODES_RESPONSE:
- return tox_event_dht_get_nodes_response_unpack(&data->dht_get_nodes_response, bu, mem);
+ case TOX_EVENT_DHT_NODES_RESPONSE:
+ return tox_event_dht_nodes_response_unpack(&data->dht_nodes_response, bu, mem);
case TOX_EVENT_INVALID:
return false;
diff --git a/protocols/Tox/libtox/src/toxcore/tox_event.h b/protocols/Tox/libtox/src/toxcore/tox_event.h
index fa98aae229..eebc233608 100644
--- a/protocols/Tox/libtox/src/toxcore/tox_event.h
+++ b/protocols/Tox/libtox/src/toxcore/tox_event.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2022-2025 The TokTok team.
*/
#ifndef C_TOXCORE_TOXCORE_TOX_EVENT_H
@@ -61,7 +61,7 @@ typedef union Tox_Event_Data {
Tox_Event_Group_Self_Join *group_self_join;
Tox_Event_Group_Join_Fail *group_join_fail;
Tox_Event_Group_Moderation *group_moderation;
- Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response;
+ Tox_Event_Dht_Nodes_Response *dht_nodes_response;
} Tox_Event_Data;
struct Tox_Event {
@@ -113,7 +113,7 @@ non_null() Tox_Event_Group_Peer_Exit *tox_event_group_peer_exit_new(const Memory
non_null() Tox_Event_Group_Self_Join *tox_event_group_self_join_new(const Memory *mem);
non_null() Tox_Event_Group_Join_Fail *tox_event_group_join_fail_new(const Memory *mem);
non_null() Tox_Event_Group_Moderation *tox_event_group_moderation_new(const Memory *mem);
-non_null() Tox_Event_Dht_Get_Nodes_Response *tox_event_dht_get_nodes_response_new(const Memory *mem);
+non_null() Tox_Event_Dht_Nodes_Response *tox_event_dht_nodes_response_new(const Memory *mem);
/**
* Destructor.
@@ -159,7 +159,7 @@ non_null(2) nullable(1) void tox_event_group_peer_exit_free(Tox_Event_Group_Peer
non_null(2) nullable(1) void tox_event_group_self_join_free(Tox_Event_Group_Self_Join *group_self_join, const Memory *mem);
non_null(2) nullable(1) void tox_event_group_join_fail_free(Tox_Event_Group_Join_Fail *group_join_fail, const Memory *mem);
non_null(2) nullable(1) void tox_event_group_moderation_free(Tox_Event_Group_Moderation *group_moderation, const Memory *mem);
-non_null(2) nullable(1) void tox_event_dht_get_nodes_response_free(Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response, const Memory *mem);
+non_null(2) nullable(1) void tox_event_dht_nodes_response_free(Tox_Event_Dht_Nodes_Response *dht_nodes_response, const Memory *mem);
/**
* Pack into msgpack.
@@ -205,7 +205,7 @@ non_null() bool tox_event_group_peer_exit_pack(const Tox_Event_Group_Peer_Exit *
non_null() bool tox_event_group_self_join_pack(const Tox_Event_Group_Self_Join *event, Bin_Pack *bp);
non_null() bool tox_event_group_join_fail_pack(const Tox_Event_Group_Join_Fail *event, Bin_Pack *bp);
non_null() bool tox_event_group_moderation_pack(const Tox_Event_Group_Moderation *event, Bin_Pack *bp);
-non_null() bool tox_event_dht_get_nodes_response_pack(const Tox_Event_Dht_Get_Nodes_Response *event, Bin_Pack *bp);
+non_null() bool tox_event_dht_nodes_response_pack(const Tox_Event_Dht_Nodes_Response *event, Bin_Pack *bp);
/**
* Unpack from msgpack.
@@ -251,7 +251,7 @@ non_null() bool tox_event_group_peer_exit_unpack(Tox_Event_Group_Peer_Exit **eve
non_null() bool tox_event_group_self_join_unpack(Tox_Event_Group_Self_Join **event, Bin_Unpack *bu, const Memory *mem);
non_null() bool tox_event_group_join_fail_unpack(Tox_Event_Group_Join_Fail **event, Bin_Unpack *bu, const Memory *mem);
non_null() bool tox_event_group_moderation_unpack(Tox_Event_Group_Moderation **event, Bin_Unpack *bu, const Memory *mem);
-non_null() bool tox_event_dht_get_nodes_response_unpack(Tox_Event_Dht_Get_Nodes_Response **event, Bin_Unpack *bu, const Memory *mem);
+non_null() bool tox_event_dht_nodes_response_unpack(Tox_Event_Dht_Nodes_Response **event, Bin_Unpack *bu, const Memory *mem);
#ifdef __cplusplus
} /* extern "C" */
diff --git a/protocols/Tox/libtox/src/toxcore/tox_events.c b/protocols/Tox/libtox/src/toxcore/tox_events.c
index a5d995cf50..81bb76ff8c 100644
--- a/protocols/Tox/libtox/src/toxcore/tox_events.c
+++ b/protocols/Tox/libtox/src/toxcore/tox_events.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022-2024 The TokTok team.
+ * Copyright © 2022-2025 The TokTok team.
*/
#include "tox_events.h"
@@ -17,7 +17,7 @@
#include "tox.h"
#include "tox_event.h"
#include "tox_private.h"
-#include "tox_struct.h"
+#include "tox_struct.h" // IWYU pragma: keep
/*****************************************************
*
@@ -66,7 +66,7 @@ void tox_events_init(Tox *tox)
tox_callback_group_self_join(tox, tox_events_handle_group_self_join);
tox_callback_group_join_fail(tox, tox_events_handle_group_join_fail);
tox_callback_group_moderation(tox, tox_events_handle_group_moderation);
- tox_callback_dht_get_nodes_response(tox, tox_events_handle_dht_get_nodes_response);
+ tox_callback_dht_nodes_response(tox, tox_events_handle_dht_nodes_response);
}
uint32_t tox_events_get_size(const Tox_Events *events)
@@ -173,7 +173,7 @@ Tox_Events *tox_events_load(const Tox_System *sys, const uint8_t *bytes, uint32_
};
events->mem = sys->mem;
- if (!bin_unpack_obj(tox_events_unpack_handler, events, bytes, bytes_size)) {
+ if (!bin_unpack_obj(sys->mem, tox_events_unpack_handler, events, bytes, bytes_size)) {
tox_events_free(events);
return nullptr;
}
diff --git a/protocols/Tox/libtox/src/toxcore/tox_events.h b/protocols/Tox/libtox/src/toxcore/tox_events.h
index 3edaa7d06b..d82930e450 100644
--- a/protocols/Tox/libtox/src/toxcore/tox_events.h
+++ b/protocols/Tox/libtox/src/toxcore/tox_events.h
@@ -1,5 +1,12 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022-2024 The TokTok team.
+ * Copyright © 2022-2025 The TokTok team.
+ */
+
+/**
+ * WARNING: This is an experimental API and is subject to change.
+ *
+ * At this point, it probably won't change very much anymore, but we may have
+ * small breaking changes before a stable release.
*/
#ifndef C_TOXCORE_TOXCORE_TOX_EVENTS_H
@@ -248,7 +255,7 @@ uint32_t tox_event_group_message_get_group_number(
const Tox_Event_Group_Message *group_message);
uint32_t tox_event_group_message_get_peer_id(
const Tox_Event_Group_Message *group_message);
-Tox_Message_Type tox_event_group_message_get_type(
+Tox_Message_Type tox_event_group_message_get_message_type(
const Tox_Event_Group_Message *group_message);
const uint8_t *tox_event_group_message_get_message(
const Tox_Event_Group_Message *group_message);
@@ -262,12 +269,14 @@ uint32_t tox_event_group_private_message_get_group_number(
const Tox_Event_Group_Private_Message *group_private_message);
uint32_t tox_event_group_private_message_get_peer_id(
const Tox_Event_Group_Private_Message *group_private_message);
-Tox_Message_Type tox_event_group_private_message_get_type(
+Tox_Message_Type tox_event_group_private_message_get_message_type(
const Tox_Event_Group_Private_Message *group_private_message);
const uint8_t *tox_event_group_private_message_get_message(
const Tox_Event_Group_Private_Message *group_private_message);
uint32_t tox_event_group_private_message_get_message_length(
const Tox_Event_Group_Private_Message *group_private_message);
+uint32_t tox_event_group_private_message_get_message_id(
+ const Tox_Event_Group_Private_Message *group_private_message);
typedef struct Tox_Event_Group_Custom_Packet Tox_Event_Group_Custom_Packet;
uint32_t tox_event_group_custom_packet_get_group_number(
@@ -343,15 +352,15 @@ uint32_t tox_event_group_moderation_get_target_peer_id(
Tox_Group_Mod_Event tox_event_group_moderation_get_mod_type(
const Tox_Event_Group_Moderation *group_moderation);
-typedef struct Tox_Event_Dht_Get_Nodes_Response Tox_Event_Dht_Get_Nodes_Response;
-const uint8_t *tox_event_dht_get_nodes_response_get_public_key(
- const Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response);
-const uint8_t *tox_event_dht_get_nodes_response_get_ip(
- const Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response);
-uint32_t tox_event_dht_get_nodes_response_get_ip_length(
- const Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response);
-uint16_t tox_event_dht_get_nodes_response_get_port(
- const Tox_Event_Dht_Get_Nodes_Response *dht_get_nodes_response);
+typedef struct Tox_Event_Dht_Nodes_Response Tox_Event_Dht_Nodes_Response;
+const uint8_t *tox_event_dht_nodes_response_get_public_key(
+ const Tox_Event_Dht_Nodes_Response *dht_nodes_response);
+const uint8_t *tox_event_dht_nodes_response_get_ip(
+ const Tox_Event_Dht_Nodes_Response *dht_nodes_response);
+uint32_t tox_event_dht_nodes_response_get_ip_length(
+ const Tox_Event_Dht_Nodes_Response *dht_nodes_response);
+uint16_t tox_event_dht_nodes_response_get_port(
+ const Tox_Event_Dht_Nodes_Response *dht_nodes_response);
typedef enum Tox_Event_Type {
TOX_EVENT_SELF_CONNECTION_STATUS = 0,
@@ -401,7 +410,7 @@ typedef enum Tox_Event_Type {
TOX_EVENT_GROUP_JOIN_FAIL = 37,
TOX_EVENT_GROUP_MODERATION = 38,
- TOX_EVENT_DHT_GET_NODES_RESPONSE = 39,
+ TOX_EVENT_DHT_NODES_RESPONSE = 39,
TOX_EVENT_INVALID = 255,
} Tox_Event_Type;
@@ -498,7 +507,7 @@ const Tox_Event_Group_Join_Fail *tox_event_get_group_join_fail(
const Tox_Event *event);
const Tox_Event_Group_Moderation *tox_event_get_group_moderation(
const Tox_Event *event);
-const Tox_Event_Dht_Get_Nodes_Response *tox_event_get_dht_get_nodes_response(
+const Tox_Event_Dht_Nodes_Response *tox_event_get_dht_nodes_response(
const Tox_Event *event);
/**
@@ -568,6 +577,8 @@ void tox_events_free(Tox_Events *events);
uint32_t tox_events_bytes_size(const Tox_Events *events);
bool tox_events_get_bytes(const Tox_Events *events, uint8_t *bytes);
+typedef struct Tox_System Tox_System;
+
Tox_Events *tox_events_load(const Tox_System *sys, const uint8_t *bytes, uint32_t bytes_size);
bool tox_events_equal(const Tox_System *sys, const Tox_Events *a, const Tox_Events *b);
diff --git a/protocols/Tox/libtox/src/toxcore/tox_log_level.c b/protocols/Tox/libtox/src/toxcore/tox_log_level.c
new file mode 100644
index 0000000000..04f83b0f9a
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/tox_log_level.c
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2016-2025 The TokTok team.
+ * Copyright © 2013 Tox project.
+ */
+#include "tox_log_level.h"
+
+const char *tox_log_level_to_string(Tox_Log_Level value)
+{
+ switch (value) {
+ case TOX_LOG_LEVEL_TRACE:
+ return "TOX_LOG_LEVEL_TRACE";
+
+ case TOX_LOG_LEVEL_DEBUG:
+ return "TOX_LOG_LEVEL_DEBUG";
+
+ case TOX_LOG_LEVEL_INFO:
+ return "TOX_LOG_LEVEL_INFO";
+
+ case TOX_LOG_LEVEL_WARNING:
+ return "TOX_LOG_LEVEL_WARNING";
+
+ case TOX_LOG_LEVEL_ERROR:
+ return "TOX_LOG_LEVEL_ERROR";
+ }
+
+ return "<invalid Tox_Log_Level>";
+}
diff --git a/protocols/Tox/libtox/src/toxcore/tox_log_level.h b/protocols/Tox/libtox/src/toxcore/tox_log_level.h
new file mode 100644
index 0000000000..0009ecd54b
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/tox_log_level.h
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2022-2025 The TokTok team.
+ */
+
+#ifndef C_TOXCORE_TOXCORE_TOX_LOG_LEVEL_H
+#define C_TOXCORE_TOXCORE_TOX_LOG_LEVEL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Severity level of log messages.
+ */
+typedef enum Tox_Log_Level {
+ /**
+ * Very detailed traces including all network activity.
+ */
+ TOX_LOG_LEVEL_TRACE,
+
+ /**
+ * Debug messages such as which port we bind to.
+ */
+ TOX_LOG_LEVEL_DEBUG,
+
+ /**
+ * Informational log messages such as video call status changes.
+ */
+ TOX_LOG_LEVEL_INFO,
+
+ /**
+ * Warnings about internal inconsistency or logic errors.
+ */
+ TOX_LOG_LEVEL_WARNING,
+
+ /**
+ * Severe unexpected errors caused by external or internal inconsistency.
+ */
+ TOX_LOG_LEVEL_ERROR,
+} Tox_Log_Level;
+
+const char *tox_log_level_to_string(Tox_Log_Level value);
+
+//!TOKSTYLE-
+#ifndef DOXYGEN_IGNORE
+
+#ifndef TOX_HIDE_DEPRECATED
+typedef Tox_Log_Level TOX_LOG_LEVEL;
+#endif /* TOX_HIDE_DEPRECATED */
+
+#endif
+//!TOKSTYLE+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* C_TOXCORE_TOXCORE_TOX_LOG_LEVEL_H */
diff --git a/protocols/Tox/libtox/src/toxcore/tox_options.c b/protocols/Tox/libtox/src/toxcore/tox_options.c
new file mode 100644
index 0000000000..d67a8aebd0
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/tox_options.c
@@ -0,0 +1,285 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2016-2025 The TokTok team.
+ * Copyright © 2013 Tox project.
+ */
+
+#include "tox_options.h"
+
+#include <stdlib.h> // free, malloc, calloc
+#include <string.h> // memcpy, strlen
+
+#include "ccompat.h" // nullptr
+
+#define SET_ERROR_PARAMETER(param, x) \
+ do { \
+ if (param != nullptr) { \
+ *param = x; \
+ } \
+ } while (0)
+
+
+bool tox_options_get_ipv6_enabled(const Tox_Options *options)
+{
+ return options->ipv6_enabled;
+}
+void tox_options_set_ipv6_enabled(Tox_Options *options, bool ipv6_enabled)
+{
+ options->ipv6_enabled = ipv6_enabled;
+}
+bool tox_options_get_udp_enabled(const Tox_Options *options)
+{
+ return options->udp_enabled;
+}
+void tox_options_set_udp_enabled(Tox_Options *options, bool udp_enabled)
+{
+ options->udp_enabled = udp_enabled;
+}
+Tox_Proxy_Type tox_options_get_proxy_type(const Tox_Options *options)
+{
+ return options->proxy_type;
+}
+void tox_options_set_proxy_type(Tox_Options *options, Tox_Proxy_Type proxy_type)
+{
+ options->proxy_type = proxy_type;
+}
+const char *tox_options_get_proxy_host(const Tox_Options *options)
+{
+ return options->proxy_host;
+}
+bool tox_options_set_proxy_host(Tox_Options *options, const char *proxy_host)
+{
+ if (!options->experimental_owned_data) {
+ options->proxy_host = proxy_host;
+ return true;
+ }
+
+ if (options->owned_proxy_host != nullptr) {
+ free(options->owned_proxy_host);
+ options->owned_proxy_host = nullptr;
+ }
+ if (proxy_host == nullptr) {
+ options->proxy_host = nullptr;
+ return true;
+ }
+
+ const size_t proxy_host_length = strlen(proxy_host) + 1;
+ char *owned_ptr = (char *)malloc(proxy_host_length);
+ if (owned_ptr == nullptr) {
+ options->proxy_host = proxy_host;
+ options->owned_proxy_host = nullptr;
+ return false;
+ }
+
+ memcpy(owned_ptr, proxy_host, proxy_host_length);
+ options->proxy_host = owned_ptr;
+ options->owned_proxy_host = owned_ptr;
+ return true;
+}
+uint16_t tox_options_get_proxy_port(const Tox_Options *options)
+{
+ return options->proxy_port;
+}
+void tox_options_set_proxy_port(Tox_Options *options, uint16_t proxy_port)
+{
+ options->proxy_port = proxy_port;
+}
+uint16_t tox_options_get_start_port(const Tox_Options *options)
+{
+ return options->start_port;
+}
+void tox_options_set_start_port(Tox_Options *options, uint16_t start_port)
+{
+ options->start_port = start_port;
+}
+uint16_t tox_options_get_end_port(const Tox_Options *options)
+{
+ return options->end_port;
+}
+void tox_options_set_end_port(Tox_Options *options, uint16_t end_port)
+{
+ options->end_port = end_port;
+}
+uint16_t tox_options_get_tcp_port(const Tox_Options *options)
+{
+ return options->tcp_port;
+}
+void tox_options_set_tcp_port(Tox_Options *options, uint16_t tcp_port)
+{
+ options->tcp_port = tcp_port;
+}
+bool tox_options_get_hole_punching_enabled(const Tox_Options *options)
+{
+ return options->hole_punching_enabled;
+}
+void tox_options_set_hole_punching_enabled(Tox_Options *options, bool hole_punching_enabled)
+{
+ options->hole_punching_enabled = hole_punching_enabled;
+}
+Tox_Savedata_Type tox_options_get_savedata_type(const Tox_Options *options)
+{
+ return options->savedata_type;
+}
+void tox_options_set_savedata_type(Tox_Options *options, Tox_Savedata_Type savedata_type)
+{
+ options->savedata_type = savedata_type;
+}
+size_t tox_options_get_savedata_length(const Tox_Options *options)
+{
+ return options->savedata_length;
+}
+void tox_options_set_savedata_length(Tox_Options *options, size_t savedata_length)
+{
+ options->savedata_length = savedata_length;
+}
+tox_log_cb *tox_options_get_log_callback(const Tox_Options *options)
+{
+ return options->log_callback;
+}
+void tox_options_set_log_callback(Tox_Options *options, tox_log_cb *log_callback)
+{
+ options->log_callback = log_callback;
+}
+void *tox_options_get_log_user_data(const Tox_Options *options)
+{
+ return options->log_user_data;
+}
+void tox_options_set_log_user_data(Tox_Options *options, void *log_user_data)
+{
+ options->log_user_data = log_user_data;
+}
+bool tox_options_get_local_discovery_enabled(const Tox_Options *options)
+{
+ return options->local_discovery_enabled;
+}
+void tox_options_set_local_discovery_enabled(Tox_Options *options, bool local_discovery_enabled)
+{
+ options->local_discovery_enabled = local_discovery_enabled;
+}
+bool tox_options_get_dht_announcements_enabled(const Tox_Options *options)
+{
+ return options->dht_announcements_enabled;
+}
+void tox_options_set_dht_announcements_enabled(Tox_Options *options, bool dht_announcements_enabled)
+{
+ options->dht_announcements_enabled = dht_announcements_enabled;
+}
+bool tox_options_get_experimental_thread_safety(const Tox_Options *options)
+{
+ return options->experimental_thread_safety;
+}
+void tox_options_set_experimental_thread_safety(
+ Tox_Options *options, bool experimental_thread_safety)
+{
+ options->experimental_thread_safety = experimental_thread_safety;
+}
+bool tox_options_get_experimental_groups_persistence(const Tox_Options *options)
+{
+ return options->experimental_groups_persistence;
+}
+void tox_options_set_experimental_groups_persistence(
+ Tox_Options *options, bool experimental_groups_persistence)
+{
+ options->experimental_groups_persistence = experimental_groups_persistence;
+}
+bool tox_options_get_experimental_disable_dns(const Tox_Options *options)
+{
+ return options->experimental_disable_dns;
+}
+void tox_options_set_experimental_disable_dns(Tox_Options *options, bool experimental_disable_dns)
+{
+ options->experimental_disable_dns = experimental_disable_dns;
+}
+bool tox_options_get_experimental_owned_data(const Tox_Options *options)
+{
+ return options->experimental_owned_data;
+}
+void tox_options_set_experimental_owned_data(
+ Tox_Options *options, bool experimental_owned_data)
+{
+ options->experimental_owned_data = experimental_owned_data;
+}
+
+const uint8_t *tox_options_get_savedata_data(const Tox_Options *options)
+{
+ return options->savedata_data;
+}
+
+bool tox_options_set_savedata_data(Tox_Options *options, const uint8_t *savedata_data, size_t length)
+{
+ if (!options->experimental_owned_data) {
+ options->savedata_data = savedata_data;
+ options->savedata_length = length;
+ return true;
+ }
+
+ if (options->owned_savedata_data != nullptr) {
+ free(options->owned_savedata_data);
+ options->owned_savedata_data = nullptr;
+ }
+ if (savedata_data == nullptr) {
+ options->savedata_data = nullptr;
+ options->savedata_length = 0;
+ return true;
+ }
+
+ uint8_t *owned_ptr = (uint8_t *)malloc(length);
+ if (owned_ptr == nullptr) {
+ options->savedata_data = savedata_data;
+ options->savedata_length = length;
+ options->owned_savedata_data = nullptr;
+ return false;
+ }
+
+ memcpy(owned_ptr, savedata_data, length);
+ options->savedata_data = owned_ptr;
+ options->savedata_length = length;
+ options->owned_savedata_data = owned_ptr;
+ return true;
+}
+
+void tox_options_default(Tox_Options *options)
+{
+ if (options != nullptr) {
+ // Free any owned data.
+ tox_options_set_proxy_host(options, nullptr);
+ tox_options_set_savedata_data(options, nullptr, 0);
+
+ // Set the rest to default values.
+ const Tox_Options default_options = {false};
+ *options = default_options;
+ tox_options_set_ipv6_enabled(options, true);
+ tox_options_set_udp_enabled(options, true);
+ tox_options_set_proxy_type(options, TOX_PROXY_TYPE_NONE);
+ tox_options_set_hole_punching_enabled(options, true);
+ tox_options_set_local_discovery_enabled(options, true);
+ tox_options_set_dht_announcements_enabled(options, true);
+ tox_options_set_experimental_thread_safety(options, false);
+ tox_options_set_experimental_groups_persistence(options, false);
+ tox_options_set_experimental_disable_dns(options, false);
+ tox_options_set_experimental_owned_data(options, false);
+ }
+}
+
+Tox_Options *tox_options_new(Tox_Err_Options_New *error)
+{
+ Tox_Options *options = (Tox_Options *)calloc(1, sizeof(Tox_Options));
+
+ if (options != nullptr) {
+ tox_options_default(options);
+ SET_ERROR_PARAMETER(error, TOX_ERR_OPTIONS_NEW_OK);
+ return options;
+ }
+
+ SET_ERROR_PARAMETER(error, TOX_ERR_OPTIONS_NEW_MALLOC);
+ return nullptr;
+}
+
+void tox_options_free(Tox_Options *options)
+{
+ if (options != nullptr) {
+ // Free any owned data.
+ tox_options_set_proxy_host(options, nullptr);
+ tox_options_set_savedata_data(options, nullptr, 0);
+ free(options);
+ }
+}
diff --git a/protocols/Tox/libtox/src/toxcore/tox_options.h b/protocols/Tox/libtox/src/toxcore/tox_options.h
new file mode 100644
index 0000000000..7d8b7aafaa
--- /dev/null
+++ b/protocols/Tox/libtox/src/toxcore/tox_options.h
@@ -0,0 +1,455 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * Copyright © 2016-2025 The TokTok team.
+ * Copyright © 2013 Tox project.
+ */
+
+#ifndef C_TOXCORE_TOXCORE_TOX_OPTIONS_H
+#define C_TOXCORE_TOXCORE_TOX_OPTIONS_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "tox_log_level.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Tox;
+
+/** @{
+ * @name Startup options
+ */
+
+/**
+ * @brief Type of proxy used to connect to TCP relays.
+ */
+typedef enum Tox_Proxy_Type {
+ /**
+ * Don't use a proxy.
+ */
+ TOX_PROXY_TYPE_NONE,
+
+ /**
+ * HTTP proxy using CONNECT.
+ */
+ TOX_PROXY_TYPE_HTTP,
+
+ /**
+ * SOCKS proxy for simple socket pipes.
+ */
+ TOX_PROXY_TYPE_SOCKS5,
+} Tox_Proxy_Type;
+
+const char *tox_proxy_type_to_string(Tox_Proxy_Type value);
+
+/**
+ * @brief Type of savedata to create the Tox instance from.
+ */
+typedef enum Tox_Savedata_Type {
+ /**
+ * No savedata.
+ */
+ TOX_SAVEDATA_TYPE_NONE,
+
+ /**
+ * Savedata is one that was obtained from tox_get_savedata.
+ */
+ TOX_SAVEDATA_TYPE_TOX_SAVE,
+
+ /**
+ * Savedata is a secret key of length TOX_SECRET_KEY_SIZE.
+ */
+ TOX_SAVEDATA_TYPE_SECRET_KEY,
+} Tox_Savedata_Type;
+
+const char *tox_savedata_type_to_string(Tox_Savedata_Type value);
+
+/**
+ * @brief This event is triggered when Tox logs an internal message.
+ *
+ * This is mostly useful for debugging. This callback can be called from any
+ * function, not just tox_iterate. This means the user data lifetime must at
+ * least extend between registering and unregistering it or tox_kill.
+ *
+ * Other toxcore modules such as toxav may concurrently call this callback at
+ * any time. Thus, user code must make sure it is equipped to handle concurrent
+ * execution, e.g. by employing appropriate mutex locking.
+ *
+ * When using the experimental_thread_safety option, no Tox API functions can
+ * be called from within the log callback.
+ *
+ * @param level The severity of the log message.
+ * @param file The source file from which the message originated.
+ * @param line The source line from which the message originated.
+ * @param func The function from which the message originated.
+ * @param message The log message.
+ * @param user_data The user data pointer passed to tox_new in options.
+ */
+typedef void tox_log_cb(struct Tox *tox, Tox_Log_Level level, const char *file,
+ uint32_t line, const char *func, const char *message,
+ void *user_data);
+
+/**
+ * @brief This struct contains all the startup options for Tox.
+ *
+ * You must tox_options_new to allocate an object of this type.
+ *
+ * WARNING: Although this struct happens to be visible in the API, it is
+ * effectively private. Do not allocate this yourself or access members
+ * directly, as it *will* break binary compatibility frequently.
+ *
+ * @deprecated The memory layout of this struct (size, alignment, and field
+ * order) is not part of the ABI. To remain compatible, prefer to use
+ * tox_options_new to allocate the object and accessor functions to set the
+ * members. The struct will become opaque (i.e. the definition will become
+ * private) in v0.3.0.
+ */
+typedef struct Tox_Options Tox_Options;
+
+#ifndef TOX_HIDE_DEPRECATED
+struct Tox_Options {
+ /**
+ * The type of socket to create.
+ *
+ * If this is set to false, an IPv4 socket is created, which subsequently
+ * only allows IPv4 communication.
+ * If it is set to true, an IPv6 socket is created, allowing both IPv4 and
+ * IPv6 communication.
+ */
+ bool ipv6_enabled;
+
+ /**
+ * Enable the use of UDP communication when available.
+ *
+ * Setting this to false will force Tox to use TCP only. Communications will
+ * need to be relayed through a TCP relay node, potentially slowing them
+ * down.
+ *
+ * If a proxy is enabled, UDP will be disabled if either the Tox library or
+ * the proxy don't support proxying UDP messages.
+ */
+ bool udp_enabled;
+
+ /**
+ * Enable local network peer discovery.
+ *
+ * Disabling this will cause Tox to not look for peers on the local network.
+ */
+ bool local_discovery_enabled;
+
+ /**
+ * Enable storing DHT announcements and forwarding corresponding requests.
+ *
+ * Disabling this will cause Tox to ignore the relevant packets.
+ */
+ bool dht_announcements_enabled;
+
+ /**
+ * Pass communications through a proxy.
+ */
+ Tox_Proxy_Type proxy_type;
+
+ /**
+ * The IP address or DNS name of the proxy to be used.
+ *
+ * If used, this must be non-NULL and be a valid DNS name. The name must not
+ * exceed TOX_MAX_HOSTNAME_LENGTH characters, and be in a NUL-terminated C
+ * string format (TOX_MAX_HOSTNAME_LENGTH includes the NUL byte).
+ *
+ * This member is ignored (it can be NULL) if proxy_type is
+ * TOX_PROXY_TYPE_NONE.
+ *
+ * The data pointed at by this member is owned by the user, so must
+ * outlive the options object (unless experimental_owned_data is set).
+ */
+ const char *proxy_host;
+
+ /**
+ * The port to use to connect to the proxy server.
+ *
+ * Ports must be in the range (1, 65535). The value is ignored if
+ * proxy_type is TOX_PROXY_TYPE_NONE.
+ */
+ uint16_t proxy_port;
+
+ /**
+ * The start port of the inclusive port range to attempt to use.
+ *
+ * If both start_port and end_port are 0, the default port range will be
+ * used: `[33445, 33545]`.
+ *
+ * If either start_port or end_port is 0 while the other is non-zero, the
+ * non-zero port will be the only port in the range.
+ *
+ * Having start_port > end_port will yield the same behavior as if
+ * start_port and end_port were swapped.
+ */
+ uint16_t start_port;
+
+ /**
+ * The end port of the inclusive port range to attempt to use.
+ */
+ uint16_t end_port;
+
+ /**
+ * The port to use for the TCP server (relay). If 0, the TCP server is
+ * disabled.
+ *
+ * Enabling it is not required for Tox to function properly.
+ *
+ * When enabled, your Tox instance can act as a TCP relay for other Tox
+ * instance. This leads to increased traffic, thus when writing a client
+ * it is recommended to enable TCP server only if the user has an option
+ * to disable it.
+ */
+ uint16_t tcp_port;
+
+ /**
+ * Enables or disables UDP hole-punching. (Default: enabled).
+ */
+ bool hole_punching_enabled;
+
+ /**
+ * The type of savedata to load from.
+ */
+ Tox_Savedata_Type savedata_type;
+
+ /**
+ * The savedata (either a Tox save or a secret key) to load from.
+ *
+ * The data pointed at by this member is owned by the user, so must
+ * outlive the options object (unless experimental_owned_data is set).
+ */
+ const uint8_t *savedata_data;
+
+ /**
+ * The length of the savedata.
+ */
+ size_t savedata_length;
+
+ /**
+ * Logging callback for the new Tox instance.
+ */
+ tox_log_cb *log_callback;
+
+ /**
+ * User data pointer passed to the logging callback.
+ */
+ void *log_user_data;
+
+ /**
+ * These options are experimental, so avoid writing code that depends on
+ * them. Options marked "experimental" may change their behaviour or go away
+ * entirely in the future, or may be renamed to something non-experimental
+ * if they become part of the supported API.
+ */
+ /**
+ * Make public API functions thread-safe using a per-instance lock.
+ *
+ * Default: false.
+ */
+ bool experimental_thread_safety;
+
+ /**
+ * Enable saving DHT-based group chats to Tox save data (via
+ * `tox_get_savedata`). This format will change in the future, so don't rely
+ * on it.
+ *
+ * As an alternative, clients can save the group chat ID in client-owned
+ * savedata. Then, when the client starts, it can use `tox_group_join`
+ * with the saved chat ID to recreate the group chat.
+ *
+ * Default: false.
+ */
+ bool experimental_groups_persistence;
+
+ /**
+ * @brief Disable DNS hostname resolution.
+ *
+ * Hostnames or IP addresses are passed to the bootstrap/add_tcp_relay
+ * function and proxy host options. If disabled (this flag is true), only
+ * IP addresses are allowed.
+ *
+ * If this is set to true, the library will not attempt to resolve
+ * hostnames. This is useful for clients that want to resolve hostnames
+ * themselves and pass the resolved IP addresses to the library (e.g. in
+ * case it wants to use Tor).
+ * Passing hostnames will result in a TOX_ERR_BOOTSTRAP_BAD_HOST error if
+ * this is set to true.
+ *
+ * Default: false. May become true in the future (0.3.0).
+ */
+ bool experimental_disable_dns;
+
+ /**
+ * @brief Whether the savedata data is owned by the Tox_Options object.
+ *
+ * If true, the setters for savedata and proxy_host try to copy the string.
+ * If that fails, the value is not copied and the member is set to the
+ * user-provided pointer. In that case, the user must not free the string
+ * until the Tox_Options object is freed. Client code can check whether
+ * allocation succeeded by checking the returned bool. If
+ * experimental_owned_data is false, it will always return true. If set to
+ * true, the return value will be false on allocation failure.
+ *
+ * If set to true, this must be set before any other member that allocates
+ * memory is set.
+ */
+ bool experimental_owned_data;
+
+ /**
+ * @brief Owned pointer to the savedata data.
+ * @private
+ */
+ uint8_t *owned_savedata_data;
+
+ /**
+ * @brief Owned pointer to the proxy host.
+ * @private
+ */
+ char *owned_proxy_host;
+};
+#endif /* TOX_HIDE_DEPRECATED */
+
+bool tox_options_get_ipv6_enabled(const Tox_Options *options);
+
+void tox_options_set_ipv6_enabled(Tox_Options *options, bool ipv6_enabled);
+
+bool tox_options_get_udp_enabled(const Tox_Options *options);
+
+void tox_options_set_udp_enabled(Tox_Options *options, bool udp_enabled);
+
+bool tox_options_get_local_discovery_enabled(const Tox_Options *options);
+
+void tox_options_set_local_discovery_enabled(Tox_Options *options, bool local_discovery_enabled);
+
+bool tox_options_get_dht_announcements_enabled(const Tox_Options *options);
+
+void tox_options_set_dht_announcements_enabled(
+ Tox_Options *options, bool dht_announcements_enabled);
+
+Tox_Proxy_Type tox_options_get_proxy_type(const Tox_Options *options);
+
+void tox_options_set_proxy_type(Tox_Options *options, Tox_Proxy_Type proxy_type);
+
+const char *tox_options_get_proxy_host(const Tox_Options *options);
+
+bool tox_options_set_proxy_host(Tox_Options *options, const char *proxy_host);
+
+uint16_t tox_options_get_proxy_port(const Tox_Options *options);
+
+void tox_options_set_proxy_port(Tox_Options *options, uint16_t proxy_port);
+
+uint16_t tox_options_get_start_port(const Tox_Options *options);
+
+void tox_options_set_start_port(Tox_Options *options, uint16_t start_port);
+
+uint16_t tox_options_get_end_port(const Tox_Options *options);
+
+void tox_options_set_end_port(Tox_Options *options, uint16_t end_port);
+
+uint16_t tox_options_get_tcp_port(const Tox_Options *options);
+
+void tox_options_set_tcp_port(Tox_Options *options, uint16_t tcp_port);
+
+bool tox_options_get_hole_punching_enabled(const Tox_Options *options);
+
+void tox_options_set_hole_punching_enabled(Tox_Options *options, bool hole_punching_enabled);
+
+Tox_Savedata_Type tox_options_get_savedata_type(const Tox_Options *options);
+
+void tox_options_set_savedata_type(Tox_Options *options, Tox_Savedata_Type savedata_type);
+
+const uint8_t *tox_options_get_savedata_data(const Tox_Options *options);
+
+bool tox_options_set_savedata_data(
+ Tox_Options *options, const uint8_t savedata_data[], size_t length);
+
+size_t tox_options_get_savedata_length(const Tox_Options *options);
+
+void tox_options_set_savedata_length(Tox_Options *options, size_t savedata_length);
+
+tox_log_cb *tox_options_get_log_callback(const Tox_Options *options);
+
+void tox_options_set_log_callback(Tox_Options *options, tox_log_cb *log_callback);
+
+void *tox_options_get_log_user_data(const Tox_Options *options);
+
+void tox_options_set_log_user_data(Tox_Options *options, void *log_user_data);
+
+bool tox_options_get_experimental_owned_data(const Tox_Options *options);
+
+void tox_options_set_experimental_owned_data(Tox_Options *options, bool experimental_owned_data);
+
+bool tox_options_get_experimental_thread_safety(const Tox_Options *options);
+
+void tox_options_set_experimental_thread_safety(
+ Tox_Options *options, bool experimental_thread_safety);
+
+bool tox_options_get_experimental_groups_persistence(const Tox_Options *options);
+
+void tox_options_set_experimental_groups_persistence(
+ Tox_Options *options, bool experimental_groups_persistence);
+
+bool tox_options_get_experimental_disable_dns(const Tox_Options *options);
+
+void tox_options_set_experimental_disable_dns(Tox_Options *options, bool experimental_disable_dns);
+
+/**
+ * @brief Initialises a Tox_Options object with the default options.
+ *
+ * The result of this function is independent of the original options. All
+ * values will be overwritten, no values will be read (so it is permissible
+ * to pass an uninitialised object).
+ *
+ * If options is NULL, this function has no effect.
+ *
+ * @param options An options object to be filled with default options.
+ */
+void tox_options_default(Tox_Options *options);
+
+typedef enum Tox_Err_Options_New {
+ /**
+ * The function returned successfully.
+ */
+ TOX_ERR_OPTIONS_NEW_OK,
+
+ /**
+ * The function failed to allocate enough memory for the options struct.
+ */
+ TOX_ERR_OPTIONS_NEW_MALLOC,
+} Tox_Err_Options_New;
+
+const char *tox_err_options_new_to_string(Tox_Err_Options_New value);
+
+/**
+ * @brief Allocates a new Tox_Options object and initialises it with the default
+ * options.
+ *
+ * This function can be used to preserve long term ABI compatibility by
+ * giving the responsibility of allocation and deallocation to the Tox library.
+ *
+ * Objects returned from this function must be freed using the tox_options_free
+ * function.
+ *
+ * @return A new Tox_Options object with default options or NULL on failure.
+ */
+Tox_Options *tox_options_new(Tox_Err_Options_New *error);
+
+/**
+ * @brief Releases all resources associated with an options objects.
+ *
+ * Passing a pointer that was not returned by tox_options_new results in
+ * undefined behaviour.
+ */
+void tox_options_free(Tox_Options *options);
+
+/** @} */
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* C_TOXCORE_TOXCORE_TOX_OPTIONS_H */
diff --git a/protocols/Tox/libtox/src/toxcore/tox_pack.c b/protocols/Tox/libtox/src/toxcore/tox_pack.c
index 3d584ac708..63995c8464 100644
--- a/protocols/Tox/libtox/src/toxcore/tox_pack.c
+++ b/protocols/Tox/libtox/src/toxcore/tox_pack.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2022-2025 The TokTok team.
*/
#include "tox_pack.h"
diff --git a/protocols/Tox/libtox/src/toxcore/tox_pack.h b/protocols/Tox/libtox/src/toxcore/tox_pack.h
index ea8605dcc3..895cd232bb 100644
--- a/protocols/Tox/libtox/src/toxcore/tox_pack.h
+++ b/protocols/Tox/libtox/src/toxcore/tox_pack.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2022-2025 The TokTok team.
*/
#ifndef C_TOXCORE_TOXCORE_TOX_PACK_H
diff --git a/protocols/Tox/libtox/src/toxcore/tox_private.c b/protocols/Tox/libtox/src/toxcore/tox_private.c
index 7b6050a9f8..dd9c63cd36 100644
--- a/protocols/Tox/libtox/src/toxcore/tox_private.c
+++ b/protocols/Tox/libtox/src/toxcore/tox_private.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2022 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -11,16 +11,19 @@
#include <assert.h>
#include "DHT.h"
-#include "attributes.h"
+#include "Messenger.h"
+#include "TCP_server.h"
#include "ccompat.h"
#include "crypto_core.h"
#include "group_chats.h"
#include "group_common.h"
+#include "logger.h"
#include "mem.h"
#include "net_crypto.h"
+#include "net_profile.h"
#include "network.h"
#include "tox.h"
-#include "tox_struct.h"
+#include "tox_struct.h" // IWYU pragma: keep
#define SET_ERROR_PARAMETER(param, x) \
do { \
@@ -91,43 +94,43 @@ void *tox_get_av_object(const Tox *tox)
return object;
}
-void tox_callback_dht_get_nodes_response(Tox *tox, tox_dht_get_nodes_response_cb *callback)
+void tox_callback_dht_nodes_response(Tox *tox, tox_dht_nodes_response_cb *callback)
{
assert(tox != nullptr);
- tox->dht_get_nodes_response_callback = callback;
+ tox->dht_nodes_response_callback = callback;
}
-bool tox_dht_get_nodes(const Tox *tox, const uint8_t *public_key, const char *ip, uint16_t port,
- const uint8_t *target_public_key, Tox_Err_Dht_Get_Nodes *error)
+bool tox_dht_send_nodes_request(const Tox *tox, const uint8_t *public_key, const char *ip, uint16_t port,
+ const uint8_t *target_public_key, Tox_Err_Dht_Send_Nodes_Request *error)
{
assert(tox != nullptr);
tox_lock(tox);
if (tox->m->options.udp_disabled) {
- SET_ERROR_PARAMETER(error, TOX_ERR_DHT_GET_NODES_UDP_DISABLED);
+ SET_ERROR_PARAMETER(error, TOX_ERR_DHT_SEND_NODES_REQUEST_UDP_DISABLED);
tox_unlock(tox);
return false;
}
if (public_key == nullptr || ip == nullptr || target_public_key == nullptr) {
- SET_ERROR_PARAMETER(error, TOX_ERR_DHT_GET_NODES_NULL);
+ SET_ERROR_PARAMETER(error, TOX_ERR_DHT_SEND_NODES_REQUEST_NULL);
tox_unlock(tox);
return false;
}
if (port == 0) {
- SET_ERROR_PARAMETER(error, TOX_ERR_DHT_GET_NODES_BAD_PORT);
+ SET_ERROR_PARAMETER(error, TOX_ERR_DHT_SEND_NODES_REQUEST_BAD_PORT);
tox_unlock(tox);
return false;
}
IP_Port *root;
- const int32_t count = net_getipport(tox->sys.mem, ip, &root, TOX_SOCK_DGRAM);
+ const int32_t count = net_getipport(tox->sys.ns, tox->sys.mem, ip, &root, TOX_SOCK_DGRAM, tox->m->options.dns_enabled);
if (count < 1) {
- SET_ERROR_PARAMETER(error, TOX_ERR_DHT_GET_NODES_BAD_IP);
+ SET_ERROR_PARAMETER(error, TOX_ERR_DHT_SEND_NODES_REQUEST_BAD_IP);
net_freeipport(tox->sys.mem, root);
tox_unlock(tox);
return false;
@@ -138,7 +141,7 @@ bool tox_dht_get_nodes(const Tox *tox, const uint8_t *public_key, const char *ip
for (int32_t i = 0; i < count; ++i) {
root[i].port = net_htons(port);
- if (dht_getnodes(tox->m->dht, &root[i], public_key, target_public_key)) {
+ if (dht_send_nodes_request(tox->m->dht, &root[i], public_key, target_public_key)) {
success = true;
}
}
@@ -148,11 +151,11 @@ bool tox_dht_get_nodes(const Tox *tox, const uint8_t *public_key, const char *ip
net_freeipport(tox->sys.mem, root);
if (!success) {
- SET_ERROR_PARAMETER(error, TOX_ERR_DHT_GET_NODES_FAIL);
+ SET_ERROR_PARAMETER(error, TOX_ERR_DHT_SEND_NODES_REQUEST_FAIL);
return false;
}
- SET_ERROR_PARAMETER(error, TOX_ERR_DHT_GET_NODES_OK);
+ SET_ERROR_PARAMETER(error, TOX_ERR_DHT_SEND_NODES_REQUEST_OK);
return true;
}
@@ -226,3 +229,199 @@ bool tox_group_peer_get_ip_address(const Tox *tox, uint32_t group_number, uint32
SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_OK);
return true;
}
+
+uint64_t tox_netprof_get_packet_id_count(const Tox *tox, Tox_Netprof_Packet_Type type, uint8_t id,
+ Tox_Netprof_Direction direction)
+{
+ assert(tox != nullptr);
+
+ tox_lock(tox);
+
+ const Net_Profile *tcp_c_profile = tox->m->tcp_np;
+ const Net_Profile *tcp_s_profile = tcp_server_get_net_profile(tox->m->tcp_server);
+
+ const Packet_Direction dir = (Packet_Direction) direction;
+
+ uint64_t count = 0;
+
+ switch (type) {
+ case TOX_NETPROF_PACKET_TYPE_TCP_CLIENT: {
+ count = netprof_get_packet_count_id(tcp_c_profile, id, dir);
+ break;
+ }
+
+ case TOX_NETPROF_PACKET_TYPE_TCP_SERVER: {
+ count = netprof_get_packet_count_id(tcp_s_profile, id, dir);
+ break;
+ }
+
+ case TOX_NETPROF_PACKET_TYPE_TCP: {
+ const uint64_t tcp_c_count = netprof_get_packet_count_id(tcp_c_profile, id, dir);
+ const uint64_t tcp_s_count = netprof_get_packet_count_id(tcp_s_profile, id, dir);
+ count = tcp_c_count + tcp_s_count;
+ break;
+ }
+
+ case TOX_NETPROF_PACKET_TYPE_UDP: {
+ const Net_Profile *udp_profile = net_get_net_profile(tox->m->net);
+ count = netprof_get_packet_count_id(udp_profile, id, dir);
+ break;
+ }
+
+ default: {
+ LOGGER_ERROR(tox->m->log, "invalid packet type: %d", type);
+ break;
+ }
+ }
+
+ tox_unlock(tox);
+
+ return count;
+}
+
+uint64_t tox_netprof_get_packet_total_count(const Tox *tox, Tox_Netprof_Packet_Type type,
+ Tox_Netprof_Direction direction)
+{
+ assert(tox != nullptr);
+
+ tox_lock(tox);
+
+ const Net_Profile *tcp_c_profile = tox->m->tcp_np;
+ const Net_Profile *tcp_s_profile = tcp_server_get_net_profile(tox->m->tcp_server);
+
+ const Packet_Direction dir = (Packet_Direction) direction;
+
+ uint64_t count = 0;
+
+ switch (type) {
+ case TOX_NETPROF_PACKET_TYPE_TCP_CLIENT: {
+ count = netprof_get_packet_count_total(tcp_c_profile, dir);
+ break;
+ }
+
+ case TOX_NETPROF_PACKET_TYPE_TCP_SERVER: {
+ count = netprof_get_packet_count_total(tcp_s_profile, dir);
+ break;
+ }
+
+ case TOX_NETPROF_PACKET_TYPE_TCP: {
+ const uint64_t tcp_c_count = netprof_get_packet_count_total(tcp_c_profile, dir);
+ const uint64_t tcp_s_count = netprof_get_packet_count_total(tcp_s_profile, dir);
+ count = tcp_c_count + tcp_s_count;
+ break;
+ }
+
+ case TOX_NETPROF_PACKET_TYPE_UDP: {
+ const Net_Profile *udp_profile = net_get_net_profile(tox->m->net);
+ count = netprof_get_packet_count_total(udp_profile, dir);
+ break;
+ }
+
+ default: {
+ LOGGER_ERROR(tox->m->log, "invalid packet type: %d", type);
+ break;
+ }
+ }
+
+ tox_unlock(tox);
+
+ return count;
+}
+
+uint64_t tox_netprof_get_packet_id_bytes(const Tox *tox, Tox_Netprof_Packet_Type type, uint8_t id,
+ Tox_Netprof_Direction direction)
+{
+ assert(tox != nullptr);
+
+ tox_lock(tox);
+
+ const Net_Profile *tcp_c_profile = tox->m->tcp_np;
+ const Net_Profile *tcp_s_profile = tcp_server_get_net_profile(tox->m->tcp_server);
+
+ const Packet_Direction dir = (Packet_Direction) direction;
+
+ uint64_t bytes = 0;
+
+ switch (type) {
+ case TOX_NETPROF_PACKET_TYPE_TCP_CLIENT: {
+ bytes = netprof_get_bytes_id(tcp_c_profile, id, dir);
+ break;
+ }
+
+ case TOX_NETPROF_PACKET_TYPE_TCP_SERVER: {
+ bytes = netprof_get_bytes_id(tcp_s_profile, id, dir);
+ break;
+ }
+
+ case TOX_NETPROF_PACKET_TYPE_TCP: {
+ const uint64_t tcp_c_bytes = netprof_get_bytes_id(tcp_c_profile, id, dir);
+ const uint64_t tcp_s_bytes = netprof_get_bytes_id(tcp_s_profile, id, dir);
+ bytes = tcp_c_bytes + tcp_s_bytes;
+ break;
+ }
+
+ case TOX_NETPROF_PACKET_TYPE_UDP: {
+ const Net_Profile *udp_profile = net_get_net_profile(tox->m->net);
+ bytes = netprof_get_bytes_id(udp_profile, id, dir);
+ break;
+ }
+
+ default: {
+ LOGGER_ERROR(tox->m->log, "invalid packet type: %d", type);
+ break;
+ }
+ }
+
+ tox_unlock(tox);
+
+ return bytes;
+}
+
+uint64_t tox_netprof_get_packet_total_bytes(const Tox *tox, Tox_Netprof_Packet_Type type,
+ Tox_Netprof_Direction direction)
+{
+ assert(tox != nullptr);
+
+ tox_lock(tox);
+
+ const Net_Profile *tcp_c_profile = tox->m->tcp_np;
+ const Net_Profile *tcp_s_profile = tcp_server_get_net_profile(tox->m->tcp_server);
+
+ const Packet_Direction dir = (Packet_Direction) direction;
+
+ uint64_t bytes = 0;
+
+ switch (type) {
+ case TOX_NETPROF_PACKET_TYPE_TCP_CLIENT: {
+ bytes = netprof_get_bytes_total(tcp_c_profile, dir);
+ break;
+ }
+
+ case TOX_NETPROF_PACKET_TYPE_TCP_SERVER: {
+ bytes = netprof_get_bytes_total(tcp_s_profile, dir);
+ break;
+ }
+
+ case TOX_NETPROF_PACKET_TYPE_TCP: {
+ const uint64_t tcp_c_bytes = netprof_get_bytes_total(tcp_c_profile, dir);
+ const uint64_t tcp_s_bytes = netprof_get_bytes_total(tcp_s_profile, dir);
+ bytes = tcp_c_bytes + tcp_s_bytes;
+ break;
+ }
+
+ case TOX_NETPROF_PACKET_TYPE_UDP: {
+ const Net_Profile *udp_profile = net_get_net_profile(tox->m->net);
+ bytes = netprof_get_bytes_total(udp_profile, dir);
+ break;
+ }
+
+ default: {
+ LOGGER_ERROR(tox->m->log, "invalid packet type: %d", type);
+ break;
+ }
+ }
+
+ tox_unlock(tox);
+
+ return bytes;
+}
diff --git a/protocols/Tox/libtox/src/toxcore/tox_private.h b/protocols/Tox/libtox/src/toxcore/tox_private.h
index d36ab026c3..4cc3edd00c 100644
--- a/protocols/Tox/libtox/src/toxcore/tox_private.h
+++ b/protocols/Tox/libtox/src/toxcore/tox_private.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2020 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -11,6 +11,7 @@
#include <stdint.h>
#include "tox.h"
+#include "tox_options.h"
#ifdef __cplusplus
extern "C" {
@@ -18,38 +19,49 @@ extern "C" {
typedef uint64_t tox_mono_time_cb(void *user_data);
-struct Tox_System {
+typedef struct Tox_System {
tox_mono_time_cb *mono_time_callback;
void *mono_time_user_data;
const struct Random *rng;
const struct Network *ns;
const struct Memory *mem;
-};
+} Tox_System;
Tox_System tox_default_system(void);
+const Tox_System *tox_get_system(Tox *tox);
+
+typedef struct Tox_Options_Testing {
+ const struct Tox_System *operating_system;
+} Tox_Options_Testing;
+
+typedef enum Tox_Err_New_Testing {
+ TOX_ERR_NEW_TESTING_OK,
+ TOX_ERR_NEW_TESTING_NULL,
+} Tox_Err_New_Testing;
+
+Tox *tox_new_testing(const Tox_Options *options, Tox_Err_New *error, const Tox_Options_Testing *testing, Tox_Err_New_Testing *testing_error);
+
void tox_lock(const Tox *tox);
void tox_unlock(const Tox *tox);
-const Tox_System *tox_get_system(Tox *tox);
-
/**
- * Set the callback for the `friend_lossy_packet` event for a specific packet ID.
- * Pass NULL to unset.
+ * Set the callback for the `friend_lossy_packet` event for a specific packet
+ * ID. Pass NULL to unset.
*
* allowed packet ID range:
- * from `PACKET_ID_RANGE_LOSSY_START` to `PACKET_ID_RANGE_LOSSY_END` (both inclusive)
+ * from `PACKET_ID_RANGE_LOSSY_START` to `PACKET_ID_RANGE_LOSSY_END` (both
+ * inclusive)
*/
void tox_callback_friend_lossy_packet_per_pktid(Tox *tox, tox_friend_lossy_packet_cb *callback, uint8_t pktid);
/**
- * Set the callback for the `friend_lossless_packet` event for a specific packet ID.
- * Pass NULL to unset.
+ * Set the callback for the `friend_lossless_packet` event for a specific packet
+ * ID. Pass NULL to unset.
*
* allowed packet ID range:
- * from `PACKET_ID_RANGE_LOSSLESS_CUSTOM_START` to `PACKET_ID_RANGE_LOSSLESS_CUSTOM_END` (both inclusive)
- * and
- * `PACKET_ID_MSI`
+ * from `PACKET_ID_RANGE_LOSSLESS_CUSTOM_START` to
+ * `PACKET_ID_RANGE_LOSSLESS_CUSTOM_END` (both inclusive) and `PACKET_ID_MSI`
*/
void tox_callback_friend_lossless_packet_per_pktid(Tox *tox, tox_friend_lossless_packet_cb *callback, uint8_t pktid);
@@ -78,69 +90,73 @@ uint32_t tox_dht_node_public_key_size(void);
/**
* @param public_key The node's public key.
- * @param ip The node's IP address, represented as a null terminated string.
+ * @param ip The node's IP address, represented as a NUL-terminated C string.
* @param port The node's port.
*/
-typedef void tox_dht_get_nodes_response_cb(Tox *tox, const uint8_t *public_key, const char *ip, uint16_t port,
- void *user_data);
+typedef void tox_dht_nodes_response_cb(
+ Tox *tox, const uint8_t *public_key, const char *ip, uint32_t ip_length,
+ uint16_t port, void *user_data);
/**
- * Set the callback for the `dht_get_nodes_response` event. Pass NULL to unset.
+ * Set the callback for the `dht_nodes_response` event. Pass NULL to unset.
*
- * This event is triggered when a getnodes response is received from a DHT peer.
+ * This event is triggered when a nodes response is received from a DHT peer.
*/
-void tox_callback_dht_get_nodes_response(Tox *tox, tox_dht_get_nodes_response_cb *callback);
+void tox_callback_dht_nodes_response(Tox *tox, tox_dht_nodes_response_cb *callback);
-typedef enum Tox_Err_Dht_Get_Nodes {
+typedef enum Tox_Err_Dht_Send_Nodes_Request {
/**
* The function returned successfully.
*/
- TOX_ERR_DHT_GET_NODES_OK,
+ TOX_ERR_DHT_SEND_NODES_REQUEST_OK,
/**
- * UDP is disabled in tox options; the DHT can only be queried when UDP is enabled.
+ * UDP is disabled in Tox options; the DHT can only be queried when UDP is
+ * enabled.
*/
- TOX_ERR_DHT_GET_NODES_UDP_DISABLED,
+ TOX_ERR_DHT_SEND_NODES_REQUEST_UDP_DISABLED,
/**
* One of the arguments to the function was NULL when it was not expected.
*/
- TOX_ERR_DHT_GET_NODES_NULL,
+ TOX_ERR_DHT_SEND_NODES_REQUEST_NULL,
/**
* The supplied port is invalid.
*/
- TOX_ERR_DHT_GET_NODES_BAD_PORT,
+ TOX_ERR_DHT_SEND_NODES_REQUEST_BAD_PORT,
/**
* The supplied IP address is invalid.
*/
- TOX_ERR_DHT_GET_NODES_BAD_IP,
+ TOX_ERR_DHT_SEND_NODES_REQUEST_BAD_IP,
/**
- * The getnodes request failed. This usually means the packet failed to send.
+ * The nodes request failed. This usually means the packet failed to
+ * send.
*/
- TOX_ERR_DHT_GET_NODES_FAIL,
-} Tox_Err_Dht_Get_Nodes;
+ TOX_ERR_DHT_SEND_NODES_REQUEST_FAIL,
+} Tox_Err_Dht_Send_Nodes_Request;
/**
- * This function sends a getnodes request to a DHT node for its peers that
- * are "close" to the passed target public key according to the distance metric used
- * by the DHT implementation.
+ * This function sends a nodes request to a DHT node for its peers that
+ * are "close" to the passed target public key according to the distance metric
+ * used by the DHT implementation.
*
- * @param public_key The public key of the node that we wish to query. This key must be
- * at least `TOX_DHT_NODE_PUBLIC_KEY_SIZE` bytes in length.
- * @param ip A NULL terminated string representing the IP address of the node we wish to query.
+ * @param public_key The public key of the node that we wish to query. This key
+ * must be at least `TOX_DHT_NODE_PUBLIC_KEY_SIZE` bytes in length.
+ * @param ip A NUL-terminated C string representing the IP address of the node
+ * we wish to query.
* @param port The port of the node we wish to query.
- * @param target_public_key The public key for which we want to find close nodes.
+ * @param target_public_key The public key for which we want to find close
+ * nodes.
*
* @return true on success.
*/
-bool tox_dht_get_nodes(const Tox *tox, const uint8_t *public_key, const char *ip, uint16_t port,
- const uint8_t *target_public_key, Tox_Err_Dht_Get_Nodes *error);
+bool tox_dht_send_nodes_request(const Tox *tox, const uint8_t *public_key, const char *ip, uint16_t port,
+ const uint8_t *target_public_key, Tox_Err_Dht_Send_Nodes_Request *error);
/**
- * This function returns the ratio of close dht nodes that are known to support announce/store.
* This function returns the number of DHT nodes in the closelist.
*
* @return number
@@ -148,8 +164,8 @@ bool tox_dht_get_nodes(const Tox *tox, const uint8_t *public_key, const char *ip
uint16_t tox_dht_get_num_closelist(const Tox *tox);
/**
- * This function returns the number of DHT nodes in the closelist,
- * that are capable to store annouce data (introduced in version 0.2.18).
+ * This function returns the number of DHT nodes in the closelist
+ * that are capable of storing announce data (introduced in version 0.2.18).
*
* @return number
*/
@@ -157,6 +173,267 @@ uint16_t tox_dht_get_num_closelist_announce_capable(const Tox *tox);
/*******************************************************************************
*
+ * :: Network profiler
+ *
+ ******************************************************************************/
+
+
+/**
+ * Represents all of the network packet identifiers that Toxcore uses.
+ *
+ * Notes:
+ * - Some packet ID's have different purposes depending on the
+ * packet type. These ID's are given numeral names.
+ *
+ * - Queries for invalid packet ID's return undefined results. For example,
+ * querying a TCP-exclusive packet ID for UDP, or querying an ID that
+ * doesn't exist in this enum.
+ */
+typedef enum Tox_Netprof_Packet_Id {
+ /**
+ * Ping request packet (UDP).
+ * Routing request (TCP).
+ */
+ TOX_NETPROF_PACKET_ID_ZERO = 0x00,
+
+ /**
+ * Ping response packet (UDP).
+ * Routing response (TCP).
+ */
+ TOX_NETPROF_PACKET_ID_ONE = 0x01,
+
+ /**
+ * Nodes request packet (UDP).
+ * Connection notification (TCP).
+ */
+ TOX_NETPROF_PACKET_ID_TWO = 0x02,
+
+ /**
+ * TCP disconnect notification.
+ */
+ TOX_NETPROF_PACKET_ID_TCP_DISCONNECT = 0x03,
+
+ /**
+ * Nodes response packet (UDP).
+ * Ping packet (TCP).
+ */
+ TOX_NETPROF_PACKET_ID_FOUR = 0x04,
+
+ /**
+ * TCP pong packet.
+ */
+ TOX_NETPROF_PACKET_ID_TCP_PONG = 0x05,
+
+ /**
+ * TCP out-of-band send packet.
+ */
+ TOX_NETPROF_PACKET_ID_TCP_OOB_SEND = 0x06,
+
+ /**
+ * TCP out-of-band receive packet.
+ */
+ TOX_NETPROF_PACKET_ID_TCP_OOB_RECV = 0x07,
+
+ /**
+ * TCP onion request packet.
+ */
+ TOX_NETPROF_PACKET_ID_TCP_ONION_REQUEST = 0x08,
+
+ /**
+ * TCP onion response packet.
+ */
+ TOX_NETPROF_PACKET_ID_TCP_ONION_RESPONSE = 0x09,
+
+ /**
+ * TCP data packet.
+ */
+ TOX_NETPROF_PACKET_ID_TCP_DATA = 0x10,
+
+ /**
+ * Cookie request packet.
+ */
+ TOX_NETPROF_PACKET_ID_COOKIE_REQUEST = 0x18,
+
+ /**
+ * Cookie response packet.
+ */
+ TOX_NETPROF_PACKET_ID_COOKIE_RESPONSE = 0x19,
+
+ /**
+ * Crypto handshake packet.
+ */
+ TOX_NETPROF_PACKET_ID_CRYPTO_HS = 0x1a,
+
+ /**
+ * Crypto data packet.
+ */
+ TOX_NETPROF_PACKET_ID_CRYPTO_DATA = 0x1b,
+
+ /**
+ * Encrypted data packet.
+ */
+ TOX_NETPROF_PACKET_ID_CRYPTO = 0x20,
+
+ /**
+ * LAN discovery packet.
+ */
+ TOX_NETPROF_PACKET_ID_LAN_DISCOVERY = 0x21,
+
+ /**
+ * DHT groupchat packets.
+ */
+ TOX_NETPROF_PACKET_ID_GC_HANDSHAKE = 0x5a,
+ TOX_NETPROF_PACKET_ID_GC_LOSSLESS = 0x5b,
+ TOX_NETPROF_PACKET_ID_GC_LOSSY = 0x5c,
+
+ /**
+ * Onion send packets.
+ */
+ TOX_NETPROF_PACKET_ID_ONION_SEND_INITIAL = 0x80,
+ TOX_NETPROF_PACKET_ID_ONION_SEND_1 = 0x81,
+ TOX_NETPROF_PACKET_ID_ONION_SEND_2 = 0x82,
+
+ /**
+ * DHT announce request packet (deprecated).
+ */
+ TOX_NETPROF_PACKET_ID_ANNOUNCE_REQUEST_OLD = 0x83,
+
+ /**
+ * DHT announce response packet (deprecated).
+ */
+ TOX_NETPROF_PACKET_ID_ANNOUNCE_RESPONSE_OLD = 0x84,
+
+ /**
+ * Onion data request packet.
+ */
+ TOX_NETPROF_PACKET_ID_ONION_DATA_REQUEST = 0x85,
+
+ /**
+ * Onion data response packet.
+ */
+ TOX_NETPROF_PACKET_ID_ONION_DATA_RESPONSE = 0x86,
+
+ /**
+ * DHT announce request packet.
+ */
+ TOX_NETPROF_PACKET_ID_ANNOUNCE_REQUEST = 0x87,
+
+ /**
+ * DHT announce response packet.
+ */
+ TOX_NETPROF_PACKET_ID_ANNOUNCE_RESPONSE = 0x88,
+
+ /**
+ * Onion receive packets.
+ */
+ TOX_NETPROF_PACKET_ID_ONION_RECV_3 = 0x8c,
+ TOX_NETPROF_PACKET_ID_ONION_RECV_2 = 0x8d,
+ TOX_NETPROF_PACKET_ID_ONION_RECV_1 = 0x8e,
+
+ TOX_NETPROF_PACKET_ID_FORWARD_REQUEST = 0x90,
+ TOX_NETPROF_PACKET_ID_FORWARDING = 0x91,
+ TOX_NETPROF_PACKET_ID_FORWARD_REPLY = 0x92,
+
+ TOX_NETPROF_PACKET_ID_DATA_SEARCH_REQUEST = 0x93,
+ TOX_NETPROF_PACKET_ID_DATA_SEARCH_RESPONSE = 0x94,
+ TOX_NETPROF_PACKET_ID_DATA_RETRIEVE_REQUEST = 0x95,
+ TOX_NETPROF_PACKET_ID_DATA_RETRIEVE_RESPONSE = 0x96,
+ TOX_NETPROF_PACKET_ID_STORE_ANNOUNCE_REQUEST = 0x97,
+ TOX_NETPROF_PACKET_ID_STORE_ANNOUNCE_RESPONSE = 0x98,
+
+ /**
+ * Bootstrap info packet.
+ */
+ TOX_NETPROF_PACKET_ID_BOOTSTRAP_INFO = 0xf0,
+} Tox_Netprof_Packet_Id;
+
+const char *tox_netprof_packet_id_to_string(Tox_Netprof_Packet_Id value);
+
+/**
+ * Specifies the packet type for a given query.
+ */
+typedef enum Tox_Netprof_Packet_Type {
+ /**
+ * TCP client packets.
+ */
+ TOX_NETPROF_PACKET_TYPE_TCP_CLIENT,
+
+ /**
+ * TCP server packets.
+ */
+ TOX_NETPROF_PACKET_TYPE_TCP_SERVER,
+
+ /**
+ * Combined TCP server and TCP client packets.
+ */
+ TOX_NETPROF_PACKET_TYPE_TCP,
+
+ /**
+ * UDP packets.
+ */
+ TOX_NETPROF_PACKET_TYPE_UDP,
+} Tox_Netprof_Packet_Type;
+
+const char *tox_netprof_packet_type_to_string(Tox_Netprof_Packet_Type value);
+
+/**
+ * Specifies the packet direction for a given query.
+ */
+typedef enum Tox_Netprof_Direction {
+ /**
+ * Outbound packets.
+ */
+ TOX_NETPROF_DIRECTION_SENT,
+
+ /**
+ * Inbound packets.
+ */
+ TOX_NETPROF_DIRECTION_RECV,
+} Tox_Netprof_Direction;
+
+const char *tox_netprof_direction_to_string(Tox_Netprof_Direction value);
+
+/**
+ * Return the number of packets sent or received for a specific packet ID.
+ *
+ * @param type The types of packets being queried.
+ * @param id The packet ID being queried.
+ * @param direction The packet direction.
+ */
+uint64_t tox_netprof_get_packet_id_count(const Tox *tox, Tox_Netprof_Packet_Type type, uint8_t id,
+ Tox_Netprof_Direction direction);
+
+/**
+ * Return the total number of packets sent or received.
+ *
+ * @param type The types of packets being queried.
+ * @param direction The packet direction.
+ */
+uint64_t tox_netprof_get_packet_total_count(const Tox *tox, Tox_Netprof_Packet_Type type,
+ Tox_Netprof_Direction direction);
+
+/**
+ * Return the number of bytes sent or received for a specific packet ID.
+ *
+ * @param type The types of packets being queried.
+ * @param id The packet ID being queried.
+ * @param direction The packet direction.
+ */
+uint64_t tox_netprof_get_packet_id_bytes(const Tox *tox, Tox_Netprof_Packet_Type type, uint8_t id,
+ Tox_Netprof_Direction direction);
+
+/**
+ * Return the total number of bytes sent or received.
+ *
+ * @param type The types of packets being queried.
+ * @param direction The packet direction.
+ */
+uint64_t tox_netprof_get_packet_total_bytes(const Tox *tox, Tox_Netprof_Packet_Type type,
+ Tox_Netprof_Direction direction);
+
+
+/*******************************************************************************
+ *
* :: DHT groupchat queries.
*
******************************************************************************/
@@ -169,30 +446,32 @@ uint16_t tox_dht_get_num_closelist_announce_capable(const Tox *tox);
uint32_t tox_group_peer_ip_string_max_length(void);
/**
- * Return the length of the peer's IP address in string form. If the group number or ID
- * is invalid, the return value is unspecified.
+ * Return the length of the peer's IP address in string form. If the group
+ * number or ID is invalid, the return value is unspecified.
*
* @param group_number The group number of the group we wish to query.
- * @param peer_id The ID of the peer whose IP address length we want to retrieve.
+ * @param peer_id The ID of the peer whose IP address length we want to
+ * retrieve.
*/
size_t tox_group_peer_get_ip_address_size(const Tox *tox, uint32_t group_number, uint32_t peer_id,
Tox_Err_Group_Peer_Query *error);
/**
- * Write the IP address associated with the designated peer_id for the designated group number
- * to ip_addr.
+ * Write the IP address associated with the designated peer_id for the
+ * designated group number to ip_addr.
*
- * If the peer is forcing TCP connections a placeholder value will be written instead,
- * indicating that their real IP address is unknown to us.
+ * If the peer is forcing TCP connections a placeholder value will be written
+ * instead, indicating that their real IP address is unknown to us.
*
- * If `peer_id` designates ourself, it will write either our own IP address or a placeholder value,
- * depending on whether or not we're forcing TCP connections.
+ * If `peer_id` designates ourself, it will write either our own IP address or a
+ * placeholder value, depending on whether or not we're forcing TCP connections.
*
- * Call tox_group_peer_get_ip_address_size to determine the allocation size for the `ip_addr` parameter.
+ * Call tox_group_peer_get_ip_address_size to determine the allocation size for
+ * the `ip_addr` parameter.
*
* @param group_number The group number of the group we wish to query.
* @param peer_id The ID of the peer whose public key we wish to retrieve.
- * @param ip_addr A valid memory region large enough to store the IP address string.
- * If this parameter is NULL, this function call has no effect.
+ * @param ip_addr A valid memory region large enough to store the IP address
+ * string. If this parameter is NULL, this function call has no effect.
*
* @return true on success.
*/
diff --git a/protocols/Tox/libtox/src/toxcore/tox_struct.h b/protocols/Tox/libtox/src/toxcore/tox_struct.h
index bd42fcce8d..9383c2a509 100644
--- a/protocols/Tox/libtox/src/toxcore/tox_struct.h
+++ b/protocols/Tox/libtox/src/toxcore/tox_struct.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2022 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -8,10 +8,9 @@
#include <pthread.h>
-#include "Messenger.h"
-#include "mem.h"
#include "mono_time.h"
#include "tox.h"
+#include "tox_options.h" // tox_log_cb
#include "tox_private.h"
#ifdef __cplusplus
@@ -19,7 +18,7 @@ extern "C" {
#endif
struct Tox {
- Messenger *m;
+ struct Messenger *m;
Mono_Time *mono_time;
Tox_System sys;
pthread_mutex_t *mutex;
@@ -44,7 +43,7 @@ struct Tox {
tox_conference_title_cb *conference_title_callback;
tox_conference_peer_name_cb *conference_peer_name_callback;
tox_conference_peer_list_changed_cb *conference_peer_list_changed_callback;
- tox_dht_get_nodes_response_cb *dht_get_nodes_response_callback;
+ tox_dht_nodes_response_cb *dht_nodes_response_callback;
tox_friend_lossy_packet_cb *friend_lossy_packet_callback_per_pktid[UINT8_MAX + 1];
tox_friend_lossless_packet_cb *friend_lossless_packet_callback_per_pktid[UINT8_MAX + 1];
tox_group_peer_name_cb *group_peer_name_callback;
diff --git a/protocols/Tox/libtox/src/toxcore/tox_unpack.c b/protocols/Tox/libtox/src/toxcore/tox_unpack.c
index b5e05da872..6b31029624 100644
--- a/protocols/Tox/libtox/src/toxcore/tox_unpack.c
+++ b/protocols/Tox/libtox/src/toxcore/tox_unpack.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2022-2025 The TokTok team.
*/
#include "tox_unpack.h"
@@ -11,21 +11,21 @@
#include "tox.h"
non_null()
-static bool tox_conference_type_from_int(uint32_t value, Tox_Conference_Type *out)
+static bool tox_conference_type_from_int(uint32_t value, Tox_Conference_Type *out_enum)
{
switch (value) {
case TOX_CONFERENCE_TYPE_TEXT: {
- *out = TOX_CONFERENCE_TYPE_TEXT;
+ *out_enum = TOX_CONFERENCE_TYPE_TEXT;
return true;
}
case TOX_CONFERENCE_TYPE_AV: {
- *out = TOX_CONFERENCE_TYPE_AV;
+ *out_enum = TOX_CONFERENCE_TYPE_AV;
return true;
}
default: {
- *out = TOX_CONFERENCE_TYPE_TEXT;
+ *out_enum = TOX_CONFERENCE_TYPE_TEXT;
return false;
}
}
@@ -38,26 +38,26 @@ bool tox_conference_type_unpack(Tox_Conference_Type *val, Bin_Unpack *bu)
}
non_null()
-static bool tox_connection_from_int(uint32_t value, Tox_Connection *out)
+static bool tox_connection_from_int(uint32_t value, Tox_Connection *out_enum)
{
switch (value) {
case TOX_CONNECTION_NONE: {
- *out = TOX_CONNECTION_NONE;
+ *out_enum = TOX_CONNECTION_NONE;
return true;
}
case TOX_CONNECTION_TCP: {
- *out = TOX_CONNECTION_TCP;
+ *out_enum = TOX_CONNECTION_TCP;
return true;
}
case TOX_CONNECTION_UDP: {
- *out = TOX_CONNECTION_UDP;
+ *out_enum = TOX_CONNECTION_UDP;
return true;
}
default: {
- *out = TOX_CONNECTION_NONE;
+ *out_enum = TOX_CONNECTION_NONE;
return false;
}
}
@@ -71,26 +71,26 @@ bool tox_connection_unpack(Tox_Connection *val, Bin_Unpack *bu)
}
non_null()
-static bool tox_file_control_from_int(uint32_t value, Tox_File_Control *out)
+static bool tox_file_control_from_int(uint32_t value, Tox_File_Control *out_enum)
{
switch (value) {
case TOX_FILE_CONTROL_RESUME: {
- *out = TOX_FILE_CONTROL_RESUME;
+ *out_enum = TOX_FILE_CONTROL_RESUME;
return true;
}
case TOX_FILE_CONTROL_PAUSE: {
- *out = TOX_FILE_CONTROL_PAUSE;
+ *out_enum = TOX_FILE_CONTROL_PAUSE;
return true;
}
case TOX_FILE_CONTROL_CANCEL: {
- *out = TOX_FILE_CONTROL_CANCEL;
+ *out_enum = TOX_FILE_CONTROL_CANCEL;
return true;
}
default: {
- *out = TOX_FILE_CONTROL_RESUME;
+ *out_enum = TOX_FILE_CONTROL_RESUME;
return false;
}
}
@@ -104,21 +104,21 @@ bool tox_file_control_unpack(Tox_File_Control *val, Bin_Unpack *bu)
}
non_null()
-static bool tox_message_type_from_int(uint32_t value, Tox_Message_Type *out)
+static bool tox_message_type_from_int(uint32_t value, Tox_Message_Type *out_enum)
{
switch (value) {
case TOX_MESSAGE_TYPE_NORMAL: {
- *out = TOX_MESSAGE_TYPE_NORMAL;
+ *out_enum = TOX_MESSAGE_TYPE_NORMAL;
return true;
}
case TOX_MESSAGE_TYPE_ACTION: {
- *out = TOX_MESSAGE_TYPE_ACTION;
+ *out_enum = TOX_MESSAGE_TYPE_ACTION;
return true;
}
default: {
- *out = TOX_MESSAGE_TYPE_NORMAL;
+ *out_enum = TOX_MESSAGE_TYPE_NORMAL;
return false;
}
}
@@ -132,26 +132,26 @@ bool tox_message_type_unpack(Tox_Message_Type *val, Bin_Unpack *bu)
}
non_null()
-static bool tox_user_status_from_int(uint32_t value, Tox_User_Status *out)
+static bool tox_user_status_from_int(uint32_t value, Tox_User_Status *out_enum)
{
switch (value) {
case TOX_USER_STATUS_NONE: {
- *out = TOX_USER_STATUS_NONE;
+ *out_enum = TOX_USER_STATUS_NONE;
return true;
}
case TOX_USER_STATUS_AWAY: {
- *out = TOX_USER_STATUS_AWAY;
+ *out_enum = TOX_USER_STATUS_AWAY;
return true;
}
case TOX_USER_STATUS_BUSY: {
- *out = TOX_USER_STATUS_BUSY;
+ *out_enum = TOX_USER_STATUS_BUSY;
return true;
}
default: {
- *out = TOX_USER_STATUS_NONE;
+ *out_enum = TOX_USER_STATUS_NONE;
return false;
}
}
@@ -165,19 +165,19 @@ bool tox_user_status_unpack(Tox_User_Status *val, Bin_Unpack *bu)
}
non_null()
-static bool tox_group_privacy_state_from_int(uint32_t value, Tox_Group_Privacy_State *out)
+static bool tox_group_privacy_state_from_int(uint32_t value, Tox_Group_Privacy_State *out_enum)
{
switch (value) {
case TOX_GROUP_PRIVACY_STATE_PUBLIC: {
- *out = TOX_GROUP_PRIVACY_STATE_PUBLIC;
+ *out_enum = TOX_GROUP_PRIVACY_STATE_PUBLIC;
return true;
}
case TOX_GROUP_PRIVACY_STATE_PRIVATE: {
- *out = TOX_GROUP_PRIVACY_STATE_PRIVATE;
+ *out_enum = TOX_GROUP_PRIVACY_STATE_PRIVATE;
return true;
}
default: {
- *out = TOX_GROUP_PRIVACY_STATE_PUBLIC;
+ *out_enum = TOX_GROUP_PRIVACY_STATE_PUBLIC;
return false;
}
}
@@ -189,23 +189,23 @@ bool tox_group_privacy_state_unpack(Tox_Group_Privacy_State *val, Bin_Unpack *bu
&& tox_group_privacy_state_from_int(u32, val);
}
non_null()
-static bool tox_group_voice_state_from_int(uint32_t value, Tox_Group_Voice_State *out)
+static bool tox_group_voice_state_from_int(uint32_t value, Tox_Group_Voice_State *out_enum)
{
switch (value) {
case TOX_GROUP_VOICE_STATE_ALL: {
- *out = TOX_GROUP_VOICE_STATE_ALL;
+ *out_enum = TOX_GROUP_VOICE_STATE_ALL;
return true;
}
case TOX_GROUP_VOICE_STATE_MODERATOR: {
- *out = TOX_GROUP_VOICE_STATE_MODERATOR;
+ *out_enum = TOX_GROUP_VOICE_STATE_MODERATOR;
return true;
}
case TOX_GROUP_VOICE_STATE_FOUNDER: {
- *out = TOX_GROUP_VOICE_STATE_FOUNDER;
+ *out_enum = TOX_GROUP_VOICE_STATE_FOUNDER;
return true;
}
default: {
- *out = TOX_GROUP_VOICE_STATE_ALL;
+ *out_enum = TOX_GROUP_VOICE_STATE_ALL;
return false;
}
}
@@ -218,19 +218,19 @@ bool tox_group_voice_state_unpack(Tox_Group_Voice_State *val, Bin_Unpack *bu)
}
non_null()
-static bool tox_group_topic_lock_from_int(uint32_t value, Tox_Group_Topic_Lock *out)
+static bool tox_group_topic_lock_from_int(uint32_t value, Tox_Group_Topic_Lock *out_enum)
{
switch (value) {
case TOX_GROUP_TOPIC_LOCK_ENABLED: {
- *out = TOX_GROUP_TOPIC_LOCK_ENABLED;
+ *out_enum = TOX_GROUP_TOPIC_LOCK_ENABLED;
return true;
}
case TOX_GROUP_TOPIC_LOCK_DISABLED: {
- *out = TOX_GROUP_TOPIC_LOCK_DISABLED;
+ *out_enum = TOX_GROUP_TOPIC_LOCK_DISABLED;
return true;
}
default: {
- *out = TOX_GROUP_TOPIC_LOCK_ENABLED;
+ *out_enum = TOX_GROUP_TOPIC_LOCK_ENABLED;
return false;
}
}
@@ -243,23 +243,23 @@ bool tox_group_topic_lock_unpack(Tox_Group_Topic_Lock *val, Bin_Unpack *bu)
}
non_null()
-static bool tox_group_join_fail_from_int(uint32_t value, Tox_Group_Join_Fail *out)
+static bool tox_group_join_fail_from_int(uint32_t value, Tox_Group_Join_Fail *out_enum)
{
switch (value) {
case TOX_GROUP_JOIN_FAIL_PEER_LIMIT: {
- *out = TOX_GROUP_JOIN_FAIL_PEER_LIMIT;
+ *out_enum = TOX_GROUP_JOIN_FAIL_PEER_LIMIT;
return true;
}
case TOX_GROUP_JOIN_FAIL_INVALID_PASSWORD: {
- *out = TOX_GROUP_JOIN_FAIL_INVALID_PASSWORD;
+ *out_enum = TOX_GROUP_JOIN_FAIL_INVALID_PASSWORD;
return true;
}
case TOX_GROUP_JOIN_FAIL_UNKNOWN: {
- *out = TOX_GROUP_JOIN_FAIL_UNKNOWN;
+ *out_enum = TOX_GROUP_JOIN_FAIL_UNKNOWN;
return true;
}
default: {
- *out = TOX_GROUP_JOIN_FAIL_PEER_LIMIT;
+ *out_enum = TOX_GROUP_JOIN_FAIL_PEER_LIMIT;
return false;
}
}
@@ -272,27 +272,27 @@ bool tox_group_join_fail_unpack(Tox_Group_Join_Fail *val, Bin_Unpack *bu)
}
non_null()
-static bool tox_group_mod_event_from_int(uint32_t value, Tox_Group_Mod_Event *out)
+static bool tox_group_mod_event_from_int(uint32_t value, Tox_Group_Mod_Event *out_enum)
{
switch (value) {
case TOX_GROUP_MOD_EVENT_KICK: {
- *out = TOX_GROUP_MOD_EVENT_KICK;
+ *out_enum = TOX_GROUP_MOD_EVENT_KICK;
return true;
}
case TOX_GROUP_MOD_EVENT_OBSERVER: {
- *out = TOX_GROUP_MOD_EVENT_OBSERVER;
+ *out_enum = TOX_GROUP_MOD_EVENT_OBSERVER;
return true;
}
case TOX_GROUP_MOD_EVENT_USER: {
- *out = TOX_GROUP_MOD_EVENT_USER;
+ *out_enum = TOX_GROUP_MOD_EVENT_USER;
return true;
}
case TOX_GROUP_MOD_EVENT_MODERATOR: {
- *out = TOX_GROUP_MOD_EVENT_MODERATOR;
+ *out_enum = TOX_GROUP_MOD_EVENT_MODERATOR;
return true;
}
default: {
- *out = TOX_GROUP_MOD_EVENT_KICK;
+ *out_enum = TOX_GROUP_MOD_EVENT_KICK;
return false;
}
}
@@ -305,35 +305,35 @@ bool tox_group_mod_event_unpack(Tox_Group_Mod_Event *val, Bin_Unpack *bu)
}
non_null()
-static bool tox_group_exit_type_from_int(uint32_t value, Tox_Group_Exit_Type *out)
+static bool tox_group_exit_type_from_int(uint32_t value, Tox_Group_Exit_Type *out_enum)
{
switch (value) {
case TOX_GROUP_EXIT_TYPE_QUIT: {
- *out = TOX_GROUP_EXIT_TYPE_QUIT;
+ *out_enum = TOX_GROUP_EXIT_TYPE_QUIT;
return true;
}
case TOX_GROUP_EXIT_TYPE_TIMEOUT: {
- *out = TOX_GROUP_EXIT_TYPE_TIMEOUT;
+ *out_enum = TOX_GROUP_EXIT_TYPE_TIMEOUT;
return true;
}
case TOX_GROUP_EXIT_TYPE_DISCONNECTED: {
- *out = TOX_GROUP_EXIT_TYPE_DISCONNECTED;
+ *out_enum = TOX_GROUP_EXIT_TYPE_DISCONNECTED;
return true;
}
case TOX_GROUP_EXIT_TYPE_SELF_DISCONNECTED: {
- *out = TOX_GROUP_EXIT_TYPE_SELF_DISCONNECTED;
+ *out_enum = TOX_GROUP_EXIT_TYPE_SELF_DISCONNECTED;
return true;
}
case TOX_GROUP_EXIT_TYPE_KICK: {
- *out = TOX_GROUP_EXIT_TYPE_KICK;
+ *out_enum = TOX_GROUP_EXIT_TYPE_KICK;
return true;
}
case TOX_GROUP_EXIT_TYPE_SYNC_ERROR: {
- *out = TOX_GROUP_EXIT_TYPE_SYNC_ERROR;
+ *out_enum = TOX_GROUP_EXIT_TYPE_SYNC_ERROR;
return true;
}
default: {
- *out = TOX_GROUP_EXIT_TYPE_QUIT;
+ *out_enum = TOX_GROUP_EXIT_TYPE_QUIT;
return false;
}
}
diff --git a/protocols/Tox/libtox/src/toxcore/tox_unpack.h b/protocols/Tox/libtox/src/toxcore/tox_unpack.h
index 828d2947a6..09092379da 100644
--- a/protocols/Tox/libtox/src/toxcore/tox_unpack.h
+++ b/protocols/Tox/libtox/src/toxcore/tox_unpack.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2022 The TokTok team.
+ * Copyright © 2022-2025 The TokTok team.
*/
#ifndef C_TOXCORE_TOXCORE_TOX_UNPACK_H
diff --git a/protocols/Tox/libtox/src/toxcore/util.c b/protocols/Tox/libtox/src/toxcore/util.c
index 1851e58a08..455e513cef 100644
--- a/protocols/Tox/libtox/src/toxcore/util.c
+++ b/protocols/Tox/libtox/src/toxcore/util.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
* Copyright © 2013 plutooo
*/
@@ -13,7 +13,6 @@
#include "util.h"
-#include <stdlib.h>
#include <string.h>
#include "ccompat.h"
@@ -81,13 +80,13 @@ bool memeq(const uint8_t *a, size_t a_size, const uint8_t *b, size_t b_size)
return a_size == b_size && memcmp(a, b, a_size) == 0;
}
-uint8_t *memdup(const uint8_t *data, size_t data_size)
+uint8_t *memdup(const Memory *mem, const uint8_t *data, size_t data_size)
{
if (data == nullptr || data_size == 0) {
return nullptr;
}
- uint8_t *copy = (uint8_t *)malloc(data_size);
+ uint8_t *copy = (uint8_t *)mem_balloc(mem, data_size);
if (copy != nullptr) {
memcpy(copy, data, data_size);
diff --git a/protocols/Tox/libtox/src/toxcore/util.h b/protocols/Tox/libtox/src/toxcore/util.h
index 5be74a8d86..9be721318b 100644
--- a/protocols/Tox/libtox/src/toxcore/util.h
+++ b/protocols/Tox/libtox/src/toxcore/util.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
* Copyright © 2013 plutooo
*/
@@ -46,7 +46,7 @@ non_null() bool memeq(const uint8_t *a, size_t a_size, const uint8_t *b, size_t
*
* @return nullptr on allocation failure or if the input data was nullptr or data_size was 0.
*/
-nullable(1) uint8_t *memdup(const uint8_t *data, size_t data_size);
+non_null(1) nullable(2) uint8_t *memdup(const Memory *mem, const uint8_t *data, size_t data_size);
/**
* @brief Set all bytes in `data` to 0.
@@ -79,7 +79,12 @@ uint16_t min_u16(uint16_t a, uint16_t b);
uint32_t min_u32(uint32_t a, uint32_t b);
uint64_t min_u64(uint64_t a, uint64_t b);
-// Comparison function: return -1 if a<b, 0 if a==b, 1 if a>b.
+/**
+ * Comparison function:
+ * @retval -1 if `a < b`
+ * @retval 0 if `a == b`
+ * @retval 1 if `a > b`
+ */
int cmp_uint(uint64_t a, uint64_t b);
/** @brief Returns a 32-bit hash of key of size len */
diff --git a/protocols/Tox/libtox/src/toxencryptsave/defines.h b/protocols/Tox/libtox/src/toxencryptsave/defines.h
index ac80cc7893..ca66f4d38d 100644
--- a/protocols/Tox/libtox/src/toxencryptsave/defines.h
+++ b/protocols/Tox/libtox/src/toxencryptsave/defines.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2021 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
diff --git a/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.c b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.c
index c43e357528..63bda86058 100644
--- a/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.c
+++ b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.c
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
@@ -67,7 +67,8 @@ void tox_pass_key_free(Tox_Pass_Key *key)
* produce the same key as was previously used. Any data encrypted with this
* module can be used as input.
*
- * The cipher text must be at least TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes in length.
+ * The cipher text must be at least TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes in
+ * length.
* The salt must be TOX_PASS_SALT_LENGTH bytes in length.
* If the passed byte arrays are smaller than required, the behaviour is
* undefined.
@@ -182,10 +183,11 @@ Tox_Pass_Key *tox_pass_key_derive_with_salt(
}
/**
- * Encrypt a plain text with a key produced by tox_pass_key_derive or tox_pass_key_derive_with_salt.
+ * Encrypt a plain text with a key produced by tox_pass_key_derive or
+ * tox_pass_key_derive_with_salt.
*
- * The output array must be at least `plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH`
- * bytes long.
+ * The output array must be at least
+ * `plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH` bytes long.
*
* @param plaintext A byte array of length `plaintext_len`.
* @param plaintext_len The length of the plain text array. Bigger than 0.
@@ -229,8 +231,8 @@ bool tox_pass_key_encrypt(const Tox_Pass_Key *key, const uint8_t plaintext[], si
ciphertext += crypto_box_NONCEBYTES;
/* now encrypt */
- if (encrypt_data_symmetric(key->key, nonce, plaintext, plaintext_len, ciphertext)
- != plaintext_len + crypto_box_MACBYTES) {
+ const int32_t encrypted_len = encrypt_data_symmetric(os_memory(), key->key, nonce, plaintext, plaintext_len, ciphertext);
+ if (encrypted_len < 0 || (size_t)encrypted_len != plaintext_len + crypto_box_MACBYTES) {
SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_FAILED);
return false;
}
@@ -242,9 +244,9 @@ bool tox_pass_key_encrypt(const Tox_Pass_Key *key, const uint8_t plaintext[], si
/**
* Encrypts the given data with the given passphrase.
*
- * The output array must be at least `plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH`
- * bytes long. This delegates to tox_pass_key_derive and
- * tox_pass_key_encrypt.
+ * The output array must be at least
+ * `plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH` bytes long. This delegates
+ * to tox_pass_key_derive and tox_pass_key_encrypt.
*
* @param plaintext A byte array of length `plaintext_len`.
* @param plaintext_len The length of the plain text array. Bigger than 0.
@@ -280,7 +282,8 @@ bool tox_pass_encrypt(const uint8_t plaintext[], size_t plaintext_len, const uin
* tox_pass_key_derive or tox_pass_key_derive_with_salt.
*
* @param ciphertext A byte array of length `ciphertext_len`.
- * @param ciphertext_len The length of the cipher text array. At least TOX_PASS_ENCRYPTION_EXTRA_LENGTH.
+ * @param ciphertext_len The length of the cipher text array. At least
+ * TOX_PASS_ENCRYPTION_EXTRA_LENGTH.
* @param plaintext The plain text array to write the decrypted data to.
*
* @return true on success.
@@ -313,8 +316,8 @@ bool tox_pass_key_decrypt(const Tox_Pass_Key *key, const uint8_t ciphertext[], s
ciphertext += crypto_box_NONCEBYTES;
/* decrypt the ciphertext */
- if (decrypt_data_symmetric(key->key, nonce, ciphertext, decrypt_length + crypto_box_MACBYTES, plaintext)
- != decrypt_length) {
+ const int32_t decrypted_len = decrypt_data_symmetric(os_memory(), key->key, nonce, ciphertext, decrypt_length + crypto_box_MACBYTES, plaintext);
+ if (decrypted_len < 0 || (size_t)decrypted_len != decrypt_length) {
SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_FAILED);
return false;
}
@@ -326,11 +329,13 @@ bool tox_pass_key_decrypt(const Tox_Pass_Key *key, const uint8_t ciphertext[], s
/**
* Decrypts the given data with the given passphrase.
*
- * The output array must be at least `ciphertext_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH`
- * bytes long. This delegates to tox_pass_key_decrypt.
+ * The output array must be at least
+ * `ciphertext_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH` bytes long. This
+ * delegates to tox_pass_key_decrypt.
*
* @param ciphertext A byte array of length `ciphertext_len`.
- * @param ciphertext_len The length of the cipher text array. At least TOX_PASS_ENCRYPTION_EXTRA_LENGTH.
+ * @param ciphertext_len The length of the cipher text array. At least
+ * TOX_PASS_ENCRYPTION_EXTRA_LENGTH.
* @param passphrase The user-provided password. Can be empty.
* @param passphrase_len The length of the password.
* @param plaintext The plain text array to write the decrypted data to.
@@ -390,3 +395,63 @@ bool tox_is_data_encrypted(const uint8_t data[TOX_PASS_ENCRYPTION_EXTRA_LENGTH])
{
return memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0;
}
+
+const char *tox_err_key_derivation_to_string(Tox_Err_Key_Derivation error)
+{
+ switch (error) {
+ case TOX_ERR_KEY_DERIVATION_OK:
+ return "TOX_ERR_KEY_DERIVATION_OK";
+ case TOX_ERR_KEY_DERIVATION_NULL:
+ return "TOX_ERR_KEY_DERIVATION_NULL";
+ case TOX_ERR_KEY_DERIVATION_FAILED:
+ return "TOX_ERR_KEY_DERIVATION_FAILED";
+ }
+ return "<invalid Tox_Err_Key_Derivation>";
+}
+
+const char *tox_err_encryption_to_string(Tox_Err_Encryption error)
+{
+ switch (error) {
+ case TOX_ERR_ENCRYPTION_OK:
+ return "TOX_ERR_ENCRYPTION_OK";
+ case TOX_ERR_ENCRYPTION_NULL:
+ return "TOX_ERR_ENCRYPTION_NULL";
+ case TOX_ERR_ENCRYPTION_KEY_DERIVATION_FAILED:
+ return "TOX_ERR_ENCRYPTION_KEY_DERIVATION_FAILED";
+ case TOX_ERR_ENCRYPTION_FAILED:
+ return "TOX_ERR_ENCRYPTION_FAILED";
+ }
+ return "<invalid Tox_Err_Encryption>";
+}
+
+const char *tox_err_decryption_to_string(Tox_Err_Decryption error)
+{
+ switch (error) {
+ case TOX_ERR_DECRYPTION_OK:
+ return "TOX_ERR_DECRYPTION_OK";
+ case TOX_ERR_DECRYPTION_NULL:
+ return "TOX_ERR_DECRYPTION_NULL";
+ case TOX_ERR_DECRYPTION_INVALID_LENGTH:
+ return "TOX_ERR_DECRYPTION_INVALID_LENGTH";
+ case TOX_ERR_DECRYPTION_BAD_FORMAT:
+ return "TOX_ERR_DECRYPTION_BAD_FORMAT";
+ case TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED:
+ return "TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED";
+ case TOX_ERR_DECRYPTION_FAILED:
+ return "TOX_ERR_DECRYPTION_FAILED";
+ }
+ return "<invalid Tox_Err_Decryption>";
+}
+
+const char *tox_err_get_salt_to_string(Tox_Err_Get_Salt error)
+{
+ switch (error) {
+ case TOX_ERR_GET_SALT_OK:
+ return "TOX_ERR_GET_SALT_OK";
+ case TOX_ERR_GET_SALT_NULL:
+ return "TOX_ERR_GET_SALT_NULL";
+ case TOX_ERR_GET_SALT_BAD_FORMAT:
+ return "TOX_ERR_GET_SALT_BAD_FORMAT";
+ }
+ return "<invalid Tox_Err_Get_Salt>";
+}
diff --git a/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.h b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.h
index b9691551c7..f70ff8b4d1 100644
--- a/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.h
+++ b/protocols/Tox/libtox/src/toxencryptsave/toxencryptsave.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
- * Copyright © 2016-2018 The TokTok team.
+ * Copyright © 2016-2025 The TokTok team.
* Copyright © 2013-2016 Tox Developers.
*/
@@ -88,6 +88,8 @@ typedef enum Tox_Err_Key_Derivation {
} Tox_Err_Key_Derivation;
+const char *tox_err_key_derivation_to_string(Tox_Err_Key_Derivation error);
+
typedef enum Tox_Err_Encryption {
/**
@@ -114,6 +116,8 @@ typedef enum Tox_Err_Encryption {
} Tox_Err_Encryption;
+const char *tox_err_encryption_to_string(Tox_Err_Encryption error);
+
typedef enum Tox_Err_Decryption {
/**
@@ -152,6 +156,8 @@ typedef enum Tox_Err_Decryption {
} Tox_Err_Decryption;
+const char *tox_err_decryption_to_string(Tox_Err_Decryption error);
+
/*******************************************************************************
*
* BEGIN PART 1
@@ -165,9 +171,9 @@ typedef enum Tox_Err_Decryption {
/**
* Encrypts the given data with the given passphrase.
*
- * The output array must be at least `plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH`
- * bytes long. This delegates to tox_pass_key_derive and
- * tox_pass_key_encrypt.
+ * The output array must be at least
+ * `plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH` bytes long. This delegates
+ * to tox_pass_key_derive and tox_pass_key_encrypt.
*
* @param plaintext A byte array of length `plaintext_len`.
* @param plaintext_len The length of the plain text array. Bigger than 0.
@@ -183,11 +189,13 @@ bool tox_pass_encrypt(const uint8_t plaintext[], size_t plaintext_len, const uin
/**
* Decrypts the given data with the given passphrase.
*
- * The output array must be at least `ciphertext_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH`
- * bytes long. This delegates to tox_pass_key_decrypt.
+ * The output array must be at least
+ * `ciphertext_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH` bytes long. This
+ * delegates to tox_pass_key_decrypt.
*
* @param ciphertext A byte array of length `ciphertext_len`.
- * @param ciphertext_len The length of the cipher text array. At least TOX_PASS_ENCRYPTION_EXTRA_LENGTH.
+ * @param ciphertext_len The length of the cipher text array. At least
+ * TOX_PASS_ENCRYPTION_EXTRA_LENGTH.
* @param passphrase The user-provided password. Can be empty.
* @param passphrase_len The length of the password.
* @param plaintext The plain text array to write the decrypted data to.
@@ -215,7 +223,8 @@ bool tox_pass_decrypt(const uint8_t ciphertext[], size_t ciphertext_len, const u
* user-provided password.
*
* The Tox_Pass_Key structure is hidden in the implementation. It can be created
- * using tox_pass_key_derive or tox_pass_key_derive_with_salt and must be deallocated using tox_pass_key_free.
+ * using tox_pass_key_derive or tox_pass_key_derive_with_salt and must be
+ * deallocated using tox_pass_key_free.
*/
#ifndef TOX_PASS_KEY_DEFINED
#define TOX_PASS_KEY_DEFINED
@@ -261,10 +270,11 @@ Tox_Pass_Key *tox_pass_key_derive_with_salt(
const uint8_t salt[TOX_PASS_SALT_LENGTH], Tox_Err_Key_Derivation *error);
/**
- * Encrypt a plain text with a key produced by tox_pass_key_derive or tox_pass_key_derive_with_salt.
+ * Encrypt a plain text with a key produced by tox_pass_key_derive or
+ * tox_pass_key_derive_with_salt.
*
- * The output array must be at least `plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH`
- * bytes long.
+ * The output array must be at least
+ * `plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH` bytes long.
*
* @param plaintext A byte array of length `plaintext_len`.
* @param plaintext_len The length of the plain text array. Bigger than 0.
@@ -280,7 +290,8 @@ bool tox_pass_key_encrypt(const Tox_Pass_Key *key, const uint8_t plaintext[], si
* tox_pass_key_derive or tox_pass_key_derive_with_salt.
*
* @param ciphertext A byte array of length `ciphertext_len`.
- * @param ciphertext_len The length of the cipher text array. At least TOX_PASS_ENCRYPTION_EXTRA_LENGTH.
+ * @param ciphertext_len The length of the cipher text array. At least
+ * TOX_PASS_ENCRYPTION_EXTRA_LENGTH.
* @param plaintext The plain text array to write the decrypted data to.
*
* @return true on success.
@@ -308,6 +319,8 @@ typedef enum Tox_Err_Get_Salt {
} Tox_Err_Get_Salt;
+const char *tox_err_get_salt_to_string(Tox_Err_Get_Salt error);
+
/**
* Retrieves the salt used to encrypt the given data.
*
@@ -315,7 +328,8 @@ typedef enum Tox_Err_Get_Salt {
* produce the same key as was previously used. Any data encrypted with this
* module can be used as input.
*
- * The cipher text must be at least TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes in length.
+ * The cipher text must be at least TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes in
+ * length.
* The salt must be TOX_PASS_SALT_LENGTH bytes in length.
* If the passed byte arrays are smaller than required, the behaviour is
* undefined.