Squashed 'external/toxcore/c-toxcore/' changes from 640e6cace..e58eb27a8

e58eb27a8 fix(toxav): remove extra copy of video frame on encode Tested and works, but there might be alignment issues and other stuff.
206ea3530 refactor: Explicitly pass dependencies to constructors.
7cefa93cf fix(toxencryptsave): Wipe salt and passkey after usage.
7c3be2342 refactor: Add file/line to tox-bootstrapd logging.
f84e8cdce refactor: Move loglogdata out of network.c.
390f7db06 refactor: Move random and memory OS-specifics to `os_*` files.
REVERT: 640e6cace fix(toxav): remove extra copy of video frame on encode Tested and works, but there might be alignment issues and other stuff.

git-subtree-dir: external/toxcore/c-toxcore
git-subtree-split: e58eb27a84f9fa0cd996868e079f39e90a5c04b6
This commit is contained in:
Green Sky
2025-11-04 21:18:05 +01:00
parent 54c0a3c874
commit 596ea37298
117 changed files with 1409 additions and 697 deletions

View File

@@ -39,6 +39,12 @@ cc_library(
visibility = ["//c-toxcore:__subpackages__"],
)
cc_library(
name = "tox_attributes",
hdrs = ["tox_attributes.h"],
visibility = ["//c-toxcore:__subpackages__"],
)
cc_library(
name = "ccompat",
srcs = ["ccompat.c"],
@@ -47,6 +53,59 @@ cc_library(
deps = [":attributes"],
)
cc_library(
name = "tox_memory",
srcs = ["tox_memory.c"],
hdrs = [
"tox_memory.h",
"tox_memory_impl.h",
],
visibility = ["//c-toxcore:__subpackages__"],
deps = [
":ccompat",
":tox_attributes",
],
)
cc_library(
name = "os_memory",
srcs = ["os_memory.c"],
hdrs = ["os_memory.h"],
visibility = ["//c-toxcore:__subpackages__"],
deps = [
":attributes",
":tox_memory",
],
)
cc_library(
name = "tox_random",
srcs = ["tox_random.c"],
hdrs = [
"tox_random.h",
"tox_random_impl.h",
],
visibility = ["//c-toxcore:__subpackages__"],
deps = [
":ccompat",
":tox_attributes",
":tox_memory",
],
)
cc_library(
name = "os_random",
srcs = ["os_random.c"],
hdrs = ["os_random.h"],
visibility = ["//c-toxcore:__subpackages__"],
deps = [
":attributes",
":ccompat",
":tox_random",
"@libsodium",
],
)
cc_library(
name = "mem",
srcs = ["mem.c"],
@@ -55,6 +114,7 @@ cc_library(
deps = [
":attributes",
":ccompat",
":tox_memory",
],
)
@@ -65,7 +125,9 @@ cc_library(
hdrs = ["mem_test_util.hh"],
deps = [
":mem",
":os_memory",
":test_util",
":tox_memory",
],
)
@@ -75,6 +137,7 @@ cc_test(
srcs = ["mem_test.cc"],
deps = [
":mem",
":os_memory",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
],
@@ -208,6 +271,7 @@ cc_test(
":bin_unpack",
":logger",
":mem",
":os_memory",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
],
@@ -222,6 +286,7 @@ cc_library(
":attributes",
":ccompat",
":mem",
":tox_random",
":util",
"@libsodium",
],
@@ -249,6 +314,7 @@ cc_library(
deps = [
":crypto_core",
":test_util",
":tox_random",
],
)
@@ -285,6 +351,7 @@ cc_test(
deps = [
":list",
":mem",
":os_memory",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
],
@@ -372,8 +439,14 @@ cc_library(
cc_library(
name = "network",
srcs = ["network.c"],
hdrs = ["network.h"],
srcs = [
"net_log.c",
"network.c",
],
hdrs = [
"net_log.h",
"network.h",
],
visibility = [
"//c-toxcore/auto_tests:__pkg__",
"//c-toxcore/other:__pkg__",
@@ -1148,6 +1221,8 @@ cc_library(
":net_profile",
":network",
":onion_client",
":os_memory",
":os_random",
":state",
":tox_log_level",
":tox_options",
@@ -1163,6 +1238,7 @@ cc_test(
srcs = ["tox_test.cc"],
deps = [
":crypto_core",
":os_random",
":tox",
":tox_log_level",
":tox_options",

View File

@@ -25,7 +25,6 @@
#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)
@@ -161,10 +160,6 @@ void dht_set_self_secret_key(DHT *dht, const uint8_t *key)
memcpy(dht->self_secret_key, key, CRYPTO_SECRET_KEY_SIZE);
}
Networking_Core *dht_get_net(const DHT *dht)
{
return dht->net;
}
struct Ping *dht_get_ping(const DHT *dht)
{
return dht->ping;
@@ -2509,7 +2504,7 @@ DHT *new_dht(const Logger *log, const Memory *mem, const Random *rng, const Netw
dht->hole_punching_enabled = hole_punching_enabled;
dht->lan_discovery_enabled = lan_discovery_enabled;
dht->ping = ping_new(mem, mono_time, rng, dht);
dht->ping = ping_new(mem, mono_time, rng, dht, net);
if (dht->ping == nullptr) {
LOGGER_ERROR(log, "failed to initialise ping");

View File

@@ -222,7 +222,6 @@ const uint8_t *_Nonnull dht_get_self_secret_key(const DHT *_Nonnull dht);
void dht_set_self_public_key(DHT *_Nonnull dht, const uint8_t *_Nonnull key);
void dht_set_self_secret_key(DHT *_Nonnull dht, const uint8_t *_Nonnull key);
Networking_Core *_Nonnull dht_get_net(const DHT *_Nonnull dht);
struct Ping *_Nonnull dht_get_ping(const DHT *_Nonnull dht);
const Client_data *_Nonnull dht_get_close_clientlist(const DHT *_Nonnull dht);
const Client_data *_Nonnull dht_get_close_client(const DHT *_Nonnull dht, uint32_t client_num);

View File

@@ -100,6 +100,8 @@ libtoxcore_la_SOURCES = ../third_party/cmp/cmp.c \
../toxcore/mono_time.h \
../toxcore/net_crypto.c \
../toxcore/net_crypto.h \
../toxcore/net_log.c \
../toxcore/net_log.h \
../toxcore/net_profile.c \
../toxcore/net_profile.h \
../toxcore/network.c \
@@ -110,6 +112,10 @@ libtoxcore_la_SOURCES = ../third_party/cmp/cmp.c \
../toxcore/onion_client.h \
../toxcore/onion.c \
../toxcore/onion.h \
../toxcore/os_memory.c \
../toxcore/os_memory.h \
../toxcore/os_random.c \
../toxcore/os_random.h \
../toxcore/ping_array.c \
../toxcore/ping_array.h \
../toxcore/ping.c \
@@ -131,6 +137,7 @@ libtoxcore_la_SOURCES = ../third_party/cmp/cmp.c \
../toxcore/timed_auth.c \
../toxcore/timed_auth.h \
../toxcore/tox_api.c \
../toxcore/tox_attributes.h \
../toxcore/tox_dispatch.c \
../toxcore/tox_dispatch.h \
../toxcore/tox_event.c \
@@ -139,12 +146,18 @@ libtoxcore_la_SOURCES = ../third_party/cmp/cmp.c \
../toxcore/tox_events.h \
../toxcore/tox_log_level.c \
../toxcore/tox_log_level.h \
../toxcore/tox_memory.c \
../toxcore/tox_memory.h \
../toxcore/tox_memory_impl.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_random.c \
../toxcore/tox_random.h \
../toxcore/tox_random_impl.h \
../toxcore/tox_struct.h \
../toxcore/tox_unpack.c \
../toxcore/tox_unpack.h \

View File

@@ -3443,7 +3443,7 @@ 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);
m->net_crypto = new_net_crypto(m->log, m->mem, m->rng, m->ns, m->mono_time, m->net, m->dht, &options->proxy_info, m->tcp_np);
if (m->net_crypto == nullptr) {
LOGGER_WARNING(m->log, "net_crypto initialisation failed");
@@ -3473,9 +3473,9 @@ Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random *
}
if (options->dht_announcements_enabled) {
m->forwarding = new_forwarding(m->log, m->mem, m->rng, m->mono_time, m->dht);
m->forwarding = new_forwarding(m->log, m->mem, m->rng, m->mono_time, m->dht, m->net);
if (m->forwarding != nullptr) {
m->announce = new_announcements(m->log, m->mem, m->rng, m->mono_time, m->forwarding);
m->announce = new_announcements(m->log, m->mem, m->rng, m->mono_time, m->forwarding, m->dht, m->net);
} else {
m->announce = nullptr;
}
@@ -3484,11 +3484,11 @@ Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random *
m->announce = nullptr;
}
m->onion = new_onion(m->log, m->mem, m->mono_time, m->rng, m->dht);
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);
m->onion = new_onion(m->log, m->mem, m->mono_time, m->rng, m->dht, m->net);
m->onion_a = new_onion_announce(m->log, m->mem, m->rng, m->mono_time, m->dht, m->net);
m->onion_c = new_onion_client(m->log, m->mem, m->rng, m->mono_time, m->net_crypto, m->dht, m->net);
if (m->onion_c != nullptr) {
m->fr_c = new_friend_connections(m->log, m->mem, 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, m->dht, m->net_crypto, m->net, options->local_discovery_enabled);
}
if ((options->dht_announcements_enabled && (m->forwarding == nullptr || m->announce == nullptr)) ||

View File

@@ -613,7 +613,7 @@ static int handle_dht_announce_request(
}
Announcements *new_announcements(const Logger *log, const Memory *mem, const Random *rng, const Mono_Time *mono_time,
Forwarding *forwarding)
Forwarding *forwarding, DHT *dht, Networking_Core *net)
{
if (log == nullptr || mono_time == nullptr || forwarding == nullptr) {
return nullptr;
@@ -630,8 +630,8 @@ Announcements *new_announcements(const Logger *log, const Memory *mem, const Ran
announce->rng = rng;
announce->forwarding = forwarding;
announce->mono_time = mono_time;
announce->dht = forwarding_get_dht(forwarding);
announce->net = dht_get_net(announce->dht);
announce->dht = dht;
announce->net = net;
announce->public_key = dht_get_self_public_key(announce->dht);
announce->secret_key = dht_get_self_secret_key(announce->dht);
new_hmac_key(announce->rng, announce->hmac_key);

View File

@@ -7,12 +7,14 @@
#include <stdint.h>
#include "DHT.h"
#include "attributes.h"
#include "crypto_core.h"
#include "forwarding.h"
#include "logger.h"
#include "mem.h"
#include "mono_time.h"
#include "network.h"
#define MAX_ANNOUNCEMENT_SIZE 512
@@ -22,7 +24,8 @@ uint8_t announce_response_of_request_type(uint8_t request_type);
typedef struct Announcements Announcements;
Announcements *_Nullable new_announcements(const Logger *_Nonnull log, const Memory *_Nonnull mem, const Random *_Nonnull rng, const Mono_Time *_Nonnull mono_time, Forwarding *_Nonnull forwarding);
Announcements *_Nullable new_announcements(const Logger *_Nonnull log, const Memory *_Nonnull mem, const Random *_Nonnull rng, const Mono_Time *_Nonnull mono_time, Forwarding *_Nonnull forwarding,
DHT *_Nonnull dht, Networking_Core *_Nonnull net);
/**
* @brief If data is stored, run `on_retrieve_callback` on it.

View File

@@ -7,6 +7,7 @@
#include "bin_unpack.h"
#include "logger.h"
#include "mem.h"
#include "os_memory.h"
namespace {

View File

@@ -13,6 +13,7 @@
#include "attributes.h"
#include "ccompat.h"
#include "mem.h"
#include "tox_random.h"
#include "util.h"
static_assert(CRYPTO_PUBLIC_KEY_SIZE == crypto_box_PUBLICKEYBYTES,
@@ -204,7 +205,7 @@ uint64_t random_u64(const Random *rng)
uint32_t random_range_u32(const Random *rng, uint32_t upper_bound)
{
return rng->funcs->random_uniform(rng->obj, upper_bound);
return tox_random_uniform(rng, upper_bound);
}
bool crypto_signature_create(uint8_t signature[CRYPTO_SIGNATURE_SIZE],
@@ -493,39 +494,7 @@ void crypto_sha512(uint8_t hash[CRYPTO_SHA512_SIZE], const uint8_t *data, size_t
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
}
static void sys_random_bytes(void *_Nonnull obj, uint8_t *_Nonnull bytes, size_t length)
{
randombytes(bytes, length);
}
static uint32_t sys_random_uniform(void *_Nonnull obj, uint32_t upper_bound)
{
return randombytes_uniform(upper_bound);
}
static const Random_Funcs os_random_funcs = {
sys_random_bytes,
sys_random_uniform,
};
static const Random os_random_obj = {&os_random_funcs};
const Random *os_random(void)
{
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
if ((true)) {
return nullptr;
}
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
// It is safe to call this function more than once and from different
// threads -- subsequent calls won't have any effects.
if (sodium_init() == -1) {
return nullptr;
}
return &os_random_obj;
}
void random_bytes(const Random *rng, uint8_t *bytes, size_t length)
{
rng->funcs->random_bytes(rng->obj, bytes, length);
tox_random_bytes(rng, bytes, length);
}

View File

@@ -17,6 +17,7 @@
#include "attributes.h"
#include "mem.h"
#include "tox_random.h"
#ifdef __cplusplus
extern "C" {
@@ -78,44 +79,6 @@ extern "C" {
*/
#define CRYPTO_SHA512_SIZE 64
/** @brief Fill a byte array with random bytes.
*
* This is the key generator callback and as such must be a cryptographically
* secure pseudo-random number generator (CSPRNG). The security of Tox heavily
* depends on the security of this RNG.
*/
typedef void crypto_random_bytes_cb(void *_Nullable obj, uint8_t *_Nonnull bytes, size_t length);
/** @brief Generate a random integer between 0 and @p upper_bound.
*
* Should produce a uniform random distribution, but Tox security does not
* depend on this being correct. In principle, it could even be a non-CSPRNG.
*/
typedef uint32_t crypto_random_uniform_cb(void *_Nullable obj, uint32_t upper_bound);
/** @brief Virtual function table for Random. */
typedef struct Random_Funcs {
crypto_random_bytes_cb *_Nullable random_bytes;
crypto_random_uniform_cb *_Nullable random_uniform;
} Random_Funcs;
/** @brief Random number generator object.
*
* Can be used by test code and fuzzers to make toxcore behave in specific
* well-defined (non-random) ways. Production code ought to use libsodium's
* CSPRNG and use `os_random` below.
*/
typedef struct Random {
const Random_Funcs *_Nullable funcs;
void *_Nullable obj;
} Random;
/** @brief System random number generator.
*
* Uses libsodium's CSPRNG (on Linux, `/dev/urandom`).
*/
const Random *_Nullable os_random(void);
/**
* @brief The number of bytes in an encryption public key used by DHT group chats.
*/
@@ -227,6 +190,11 @@ bool crypto_sha512_eq(const uint8_t cksum1[_Nonnull CRYPTO_SHA512_SIZE], const u
*/
bool crypto_sha256_eq(const uint8_t cksum1[_Nonnull CRYPTO_SHA256_SIZE], const uint8_t cksum2[_Nonnull CRYPTO_SHA256_SIZE]);
/**
* @brief Shorter internal name for the RNG type.
*/
typedef Tox_Random Random;
/**
* @brief Return a random 8 bit integer.
*/

View File

@@ -5,15 +5,16 @@
#include "crypto_core.h"
#include "test_util.hh"
#include "tox_random_impl.h"
Random_Funcs const Random_Class::vtable = {
Method<crypto_random_bytes_cb, Random_Class>::invoke<&Random_Class::random_bytes>,
Method<crypto_random_uniform_cb, Random_Class>::invoke<&Random_Class::random_uniform>,
Tox_Random_Funcs const Random_Class::vtable = {
Method<tox_random_bytes_cb, Random_Class>::invoke<&Random_Class::random_bytes>,
Method<tox_random_uniform_cb, Random_Class>::invoke<&Random_Class::random_uniform>,
};
Random_Class::~Random_Class() = default;
void Test_Random::random_bytes(void *obj, uint8_t *bytes, size_t length)
void Test_Random::random_bytes(void *obj, uint8_t *bytes, uint32_t length)
{
std::generate(bytes, &bytes[length], std::ref(lcg));
}

View File

@@ -8,12 +8,13 @@
#include "crypto_core.h"
#include "test_util.hh"
#include "tox_random_impl.h"
struct Random_Class {
static Random_Funcs const vtable;
Random const self;
static Tox_Random_Funcs const vtable;
Tox_Random const self;
operator Random const *() const { return &self; }
operator Tox_Random const *() const { return &self; }
Random_Class(Random_Class const &) = default;
Random_Class()
@@ -22,8 +23,8 @@ struct Random_Class {
}
virtual ~Random_Class();
virtual crypto_random_bytes_cb random_bytes = 0;
virtual crypto_random_uniform_cb random_uniform = 0;
virtual tox_random_bytes_cb random_bytes = 0;
virtual tox_random_uniform_cb random_uniform = 0;
};
/**
@@ -35,7 +36,7 @@ struct Random_Class {
class Test_Random : public Random_Class {
std::minstd_rand lcg;
void random_bytes(void *obj, uint8_t *bytes, size_t length) override;
void random_bytes(void *obj, uint8_t *bytes, uint32_t length) override;
uint32_t random_uniform(void *obj, uint32_t upper_bound) override;
};
@@ -83,6 +84,6 @@ inline bool operator==(PublicKey::Base const &pk1, PublicKey const &pk2)
std::ostream &operator<<(std::ostream &out, PublicKey const &pk);
PublicKey random_pk(const Random *rng);
PublicKey random_pk(const Tox_Random *rng);
#endif // C_TOXCORE_TOXCORE_CRYPTO_CORE_TEST_UTIL_H

View File

@@ -6,7 +6,6 @@
#define C_TOXCORE_TOXCORE_EVENTS_EVENTS_ALLOC_H
#include "../attributes.h"
#include "../mem.h"
#include "../tox.h"
#include "../tox_events.h"
#include "../tox_private.h"
@@ -15,17 +14,19 @@
extern "C" {
#endif
struct Tox_Memory;
struct Tox_Events {
Tox_Event *_Nonnull events;
uint32_t events_size;
uint32_t events_capacity;
const Memory *_Nonnull mem;
const struct Tox_Memory *_Nonnull mem;
};
typedef struct Tox_Events_State {
Tox_Err_Events_Iterate error;
const Memory *_Nonnull mem;
const struct Tox_Memory *_Nonnull mem;
Tox_Events *_Nonnull events;
} Tox_Events_State;

View File

@@ -37,11 +37,6 @@ struct Forwarding {
void *forwarded_response_callback_object;
};
DHT *forwarding_get_dht(const Forwarding *forwarding)
{
return forwarding->dht;
}
#define SENDBACK_TIMEOUT 3600
bool send_forward_request(const Networking_Core *net, const IP_Port *forwarder,
@@ -348,7 +343,8 @@ void set_callback_forward_reply(Forwarding *forwarding, forward_reply_cb *functi
forwarding->forward_reply_callback_object = object;
}
Forwarding *_Nullable new_forwarding(const Logger *log, const Memory *mem, const Random *rng, const Mono_Time *mono_time, DHT *dht)
Forwarding *_Nullable new_forwarding(const Logger *log, const Memory *mem, const Random *rng, const Mono_Time *mono_time, DHT *dht,
Networking_Core *net)
{
if (log == nullptr || mono_time == nullptr || dht == nullptr) {
return nullptr;
@@ -365,7 +361,7 @@ Forwarding *_Nullable new_forwarding(const Logger *log, const Memory *mem, const
forwarding->rng = rng;
forwarding->mono_time = mono_time;
forwarding->dht = dht;
forwarding->net = dht_get_net(dht);
forwarding->net = net;
networking_registerhandler(forwarding->net, NET_PACKET_FORWARD_REQUEST, &handle_forward_request, forwarding);
networking_registerhandler(forwarding->net, NET_PACKET_FORWARD_REPLY, &handle_forward_reply, forwarding);

View File

@@ -30,8 +30,6 @@ extern "C" {
typedef struct Forwarding Forwarding;
DHT *_Nonnull forwarding_get_dht(const Forwarding *_Nonnull forwarding);
/**
* @brief Send data to forwarder for forwarding via chain of dht nodes.
* Destination is last key in the chain.
@@ -100,7 +98,8 @@ typedef bool forward_reply_cb(void *_Nullable object, const uint8_t *_Nullable s
* sendback.
*/
void set_callback_forward_reply(Forwarding *_Nonnull forwarding, forward_reply_cb *_Nullable function, void *_Nullable object);
Forwarding *_Nullable new_forwarding(const Logger *_Nonnull log, const Memory *_Nonnull mem, const Random *_Nonnull rng, const Mono_Time *_Nonnull mono_time, DHT *_Nonnull dht);
Forwarding *_Nullable new_forwarding(const Logger *_Nonnull log, const Memory *_Nonnull mem, const Random *_Nonnull rng, const Mono_Time *_Nonnull mono_time, DHT *_Nonnull dht,
Networking_Core *_Nonnull net);
void kill_forwarding(Forwarding *_Nullable forwarding);
#ifdef __cplusplus

View File

@@ -71,6 +71,7 @@ struct Friend_Connections {
const Mono_Time *mono_time;
const Memory *mem;
const Logger *logger;
Networking_Core *net;
Net_Crypto *net_crypto;
DHT *dht;
Broadcast_Info *broadcast;
@@ -896,7 +897,8 @@ 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 Memory *mem, const Mono_Time *mono_time, const Network *ns,
Onion_Client *onion_c, bool local_discovery_enabled)
Onion_Client *onion_c, DHT *dht, Net_Crypto *net_crypto, Networking_Core *net,
bool local_discovery_enabled)
{
if (onion_c == nullptr) {
return nullptr;
@@ -922,8 +924,9 @@ 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);
temp->dht = dht;
temp->net = net;
temp->net_crypto = net_crypto;
temp->onion_c = onion_c;
// Don't include default port in port range
temp->next_lan_port = TOX_PORTRANGE_FROM + 1;
@@ -942,12 +945,12 @@ static void lan_discovery(Friend_Connections *_Nonnull fr_c)
last = last > TOX_PORTRANGE_TO ? TOX_PORTRANGE_TO : last;
// Always send to default port
lan_discovery_send(dht_get_net(fr_c->dht), fr_c->broadcast, dht_get_self_public_key(fr_c->dht),
lan_discovery_send(fr_c->net, fr_c->broadcast, dht_get_self_public_key(fr_c->dht),
net_htons(TOX_PORT_DEFAULT));
// And check some extra ports
for (uint16_t port = first; port < last; ++port) {
lan_discovery_send(dht_get_net(fr_c->dht), fr_c->broadcast, dht_get_self_public_key(fr_c->dht), net_htons(port));
lan_discovery_send(fr_c->net, fr_c->broadcast, dht_get_self_public_key(fr_c->dht), net_htons(port));
}
// Don't include default port in port range

View File

@@ -145,7 +145,8 @@ void set_friend_request_callback(Friend_Connections *_Nonnull fr_c, fr_request_c
/** Create new friend_connections instance. */
Friend_Connections *_Nullable new_friend_connections(const Logger *_Nonnull logger, const Memory *_Nonnull mem, const Mono_Time *_Nonnull mono_time, const Network *_Nonnull ns,
Onion_Client *_Nonnull onion_c, bool local_discovery_enabled);
Onion_Client *_Nonnull onion_c, DHT *_Nonnull dht, Net_Crypto *_Nonnull net_crypto, Networking_Core *_Nonnull net,
bool local_discovery_enabled);
/** main friend_connections loop. */
void do_friend_connections(Friend_Connections *_Nonnull fr_c, void *_Nonnull userdata);

View File

@@ -3,6 +3,7 @@
#include <gtest/gtest.h>
#include "mem.h"
#include "os_memory.h"
namespace {

View File

@@ -5,59 +5,29 @@
#include "mem.h"
#include <stdlib.h>
#include <string.h>
#include "attributes.h"
#include "ccompat.h"
static void *sys_malloc(void *_Nullable obj, uint32_t size)
{
return malloc(size);
}
static void *sys_calloc(void *_Nullable obj, uint32_t nmemb, uint32_t size)
{
return calloc(nmemb, size);
}
static void *sys_realloc(void *_Nullable obj, void *_Nullable ptr, uint32_t size)
{
return realloc(ptr, size);
}
static void sys_free(void *_Nullable obj, void *_Nullable ptr)
{
free(ptr);
}
static const Memory_Funcs os_memory_funcs = {
sys_malloc,
sys_calloc,
sys_realloc,
sys_free,
};
static const Memory os_memory_obj = {&os_memory_funcs};
const Memory *os_memory(void)
{
return &os_memory_obj;
}
#include "tox_memory.h"
void *mem_balloc(const Memory *mem, uint32_t size)
{
void *const ptr = mem->funcs->malloc(mem->obj, size);
void *const ptr = tox_memory_malloc(mem, 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);
void *const new_ptr = tox_memory_realloc(mem, ptr, size);
return new_ptr;
}
void *mem_alloc(const Memory *mem, uint32_t size)
{
void *const ptr = mem->funcs->calloc(mem->obj, 1, size);
void *const ptr = tox_memory_malloc(mem, size);
if (ptr != nullptr) {
memset(ptr, 0, size);
}
return ptr;
}
@@ -69,7 +39,10 @@ void *mem_valloc(const Memory *mem, uint32_t nmemb, uint32_t size)
return nullptr;
}
void *const ptr = mem->funcs->calloc(mem->obj, nmemb, size);
void *const ptr = tox_memory_malloc(mem, bytes);
if (ptr != nullptr) {
memset(ptr, 0, bytes);
}
return ptr;
}
@@ -81,11 +54,11 @@ void *mem_vrealloc(const Memory *mem, void *ptr, uint32_t nmemb, uint32_t size)
return nullptr;
}
void *const new_ptr = mem->funcs->realloc(mem->obj, ptr, bytes);
void *const new_ptr = tox_memory_realloc(mem, ptr, bytes);
return new_ptr;
}
void mem_delete(const Memory *mem, void *ptr)
{
mem->funcs->free(mem->obj, ptr);
tox_memory_dealloc(mem, ptr);
}

View File

@@ -12,30 +12,13 @@
#include <stdint.h> // uint*_t
#include "attributes.h"
#include "tox_memory.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void *mem_malloc_cb(void *_Nullable obj, uint32_t size);
typedef void *mem_calloc_cb(void *_Nullable obj, uint32_t nmemb, uint32_t size);
typedef void *mem_realloc_cb(void *_Nullable obj, void *_Nullable ptr, uint32_t size);
typedef void mem_free_cb(void *_Nullable obj, void *_Nullable ptr);
/** @brief Functions wrapping standard C memory allocation functions. */
typedef struct Memory_Funcs {
mem_malloc_cb *_Nullable malloc;
mem_calloc_cb *_Nullable calloc;
mem_realloc_cb *_Nullable realloc;
mem_free_cb *_Nullable free;
} Memory_Funcs;
typedef struct Memory {
const Memory_Funcs *_Nullable funcs;
void *_Nullable obj;
} Memory;
const Memory *_Nullable os_memory(void);
typedef Tox_Memory Memory;
/**
* @brief Allocate an array of a given size for built-in types.

View File

@@ -2,6 +2,8 @@
#include <gtest/gtest.h>
#include "os_memory.h"
namespace {
TEST(Mem, AllocLarge)

View File

@@ -2,28 +2,28 @@
#include <cstdlib>
#include "mem.h"
#include "test_util.hh"
#include "tox_memory_impl.h"
Memory_Funcs const Memory_Class::vtable = {
Method<mem_malloc_cb, Memory_Class>::invoke<&Memory_Class::malloc>,
Method<mem_calloc_cb, Memory_Class>::invoke<&Memory_Class::calloc>,
Method<mem_realloc_cb, Memory_Class>::invoke<&Memory_Class::realloc>,
Method<mem_free_cb, Memory_Class>::invoke<&Memory_Class::free>,
Tox_Memory_Funcs const Memory_Class::vtable = {
Method<tox_memory_malloc_cb, Memory_Class>::invoke<&Memory_Class::malloc>,
Method<tox_memory_realloc_cb, Memory_Class>::invoke<&Memory_Class::realloc>,
Method<tox_memory_dealloc_cb, Memory_Class>::invoke<&Memory_Class::dealloc>,
};
Memory_Class::~Memory_Class() = default;
void *Test_Memory::malloc(void *obj, uint32_t size) { return mem->funcs->malloc(mem->obj, size); }
void *Test_Memory::calloc(void *obj, uint32_t nmemb, uint32_t size)
void *Test_Memory::malloc(void *obj, uint32_t size)
{
return mem->funcs->calloc(mem->obj, nmemb, size);
return mem->funcs->malloc_callback(mem->user_data, size);
}
void *Test_Memory::realloc(void *obj, void *ptr, uint32_t size)
{
return mem->funcs->realloc(mem->obj, ptr, size);
return mem->funcs->realloc_callback(mem->user_data, ptr, size);
}
void Test_Memory::free(void *obj, void *ptr) { return mem->funcs->free(mem->obj, ptr); }
void Test_Memory::dealloc(void *obj, void *ptr)
{
return mem->funcs->dealloc_callback(mem->user_data, ptr);
}

View File

@@ -2,13 +2,15 @@
#define C_TOXCORE_TOXCORE_MEM_TEST_UTIL_H
#include "mem.h"
#include "os_memory.h"
#include "test_util.hh"
#include "tox_memory_impl.h"
struct Memory_Class {
static Memory_Funcs const vtable;
Memory const self;
static Tox_Memory_Funcs const vtable;
Tox_Memory const self;
operator Memory const *() const { return &self; }
operator Tox_Memory const *() const { return &self; }
Memory_Class(Memory_Class const &) = default;
Memory_Class()
@@ -17,10 +19,9 @@ struct Memory_Class {
}
virtual ~Memory_Class();
virtual mem_malloc_cb malloc = 0;
virtual mem_calloc_cb calloc = 0;
virtual mem_realloc_cb realloc = 0;
virtual mem_free_cb free = 0;
virtual tox_memory_malloc_cb malloc = 0;
virtual tox_memory_realloc_cb realloc = 0;
virtual tox_memory_dealloc_cb dealloc = 0;
};
/**
@@ -28,12 +29,11 @@ struct Memory_Class {
* subclassed to override individual (or all) functions.
*/
class Test_Memory : public Memory_Class {
const Memory *mem = REQUIRE_NOT_NULL(os_memory());
const Tox_Memory *mem = REQUIRE_NOT_NULL(os_memory());
void *malloc(void *obj, uint32_t size) override;
void *calloc(void *obj, uint32_t nmemb, uint32_t size) override;
void *realloc(void *obj, void *ptr, uint32_t size) override;
void free(void *obj, void *ptr) override;
void dealloc(void *obj, void *ptr) override;
};
#endif // C_TOXCORE_TOXCORE_MEM_TEST_UTIL_H

View File

@@ -137,6 +137,7 @@ struct Net_Crypto {
const Random *rng;
Mono_Time *mono_time;
const Network *ns;
Networking_Core *net;
DHT *dht;
TCP_Connections *tcp_c;
@@ -176,11 +177,6 @@ TCP_Connections *nc_get_tcp_c(const Net_Crypto *c)
return c->tcp_c;
}
DHT *nc_get_dht(const Net_Crypto *c)
{
return c->dht;
}
static bool crypt_connection_id_is_valid(const Net_Crypto *_Nonnull c, int crypt_connection_id)
{
if ((uint32_t)crypt_connection_id >= c->crypto_connections_length) {
@@ -366,7 +362,7 @@ static int udp_handle_cookie_request(void *_Nonnull object, const IP_Port *_Nonn
return 1;
}
if ((uint32_t)sendpacket(dht_get_net(c->dht), source, data, sizeof(data)) != sizeof(data)) {
if ((uint32_t)sendpacket(c->net, source, data, sizeof(data)) != sizeof(data)) {
return 1;
}
@@ -676,7 +672,7 @@ static int send_packet_to(const Net_Crypto *_Nonnull c, int crypt_connection_id,
crypto_connection_status(c, crypt_connection_id, &direct_connected, nullptr);
if (direct_connected) {
if ((uint32_t)sendpacket(dht_get_net(c->dht), &ip_port, data, length) == length) {
if ((uint32_t)sendpacket(c->net, &ip_port, data, length) == length) {
return 0;
}
@@ -689,7 +685,7 @@ static int send_packet_to(const Net_Crypto *_Nonnull c, int crypt_connection_id,
if ((((UDP_DIRECT_TIMEOUT / 2) + conn->direct_send_attempt_time) < current_time && length < 96)
|| data[0] == NET_PACKET_COOKIE_REQUEST || data[0] == NET_PACKET_CRYPTO_HS) {
if ((uint32_t)sendpacket(dht_get_net(c->dht), &ip_port, data, length) == length) {
if ((uint32_t)sendpacket(c->net, &ip_port, data, length) == length) {
direct_send_attempt = true;
conn->direct_send_attempt_time = mono_time_get(c->mono_time);
}
@@ -2915,7 +2911,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, Net_Profile *tcp_np)
Mono_Time *mono_time, Networking_Core *net, DHT *dht, const TCP_Proxy_Info *proxy_info, Net_Profile *tcp_np)
{
if (dht == nullptr) {
return nullptr;
@@ -2932,6 +2928,7 @@ Net_Crypto *new_net_crypto(const Logger *log, const Memory *mem, const Random *r
temp->rng = rng;
temp->mono_time = mono_time;
temp->ns = ns;
temp->net = net;
temp->tcp_c = new_tcp_connections(log, mem, rng, ns, mono_time, dht_get_self_secret_key(dht), proxy_info, tcp_np);
@@ -2950,10 +2947,10 @@ Net_Crypto *new_net_crypto(const Logger *log, const Memory *mem, const Random *r
temp->current_sleep_time = CRYPTO_SEND_PACKET_INTERVAL;
networking_registerhandler(dht_get_net(dht), NET_PACKET_COOKIE_REQUEST, &udp_handle_cookie_request, temp);
networking_registerhandler(dht_get_net(dht), NET_PACKET_COOKIE_RESPONSE, &udp_handle_packet, temp);
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);
networking_registerhandler(net, NET_PACKET_COOKIE_REQUEST, &udp_handle_cookie_request, temp);
networking_registerhandler(net, NET_PACKET_COOKIE_RESPONSE, &udp_handle_packet, temp);
networking_registerhandler(net, NET_PACKET_CRYPTO_HS, &udp_handle_packet, temp);
networking_registerhandler(net, NET_PACKET_CRYPTO_DATA, &udp_handle_packet, temp);
bs_list_init(&temp->ip_port_list, mem, sizeof(IP_Port), 8, ipport_cmp_handler);
@@ -3016,10 +3013,10 @@ void kill_net_crypto(Net_Crypto *c)
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);
networking_registerhandler(dht_get_net(c->dht), NET_PACKET_COOKIE_RESPONSE, nullptr, nullptr);
networking_registerhandler(dht_get_net(c->dht), NET_PACKET_CRYPTO_HS, nullptr, nullptr);
networking_registerhandler(dht_get_net(c->dht), NET_PACKET_CRYPTO_DATA, nullptr, nullptr);
networking_registerhandler(c->net, NET_PACKET_COOKIE_REQUEST, nullptr, nullptr);
networking_registerhandler(c->net, NET_PACKET_COOKIE_RESPONSE, nullptr, nullptr);
networking_registerhandler(c->net, NET_PACKET_CRYPTO_HS, nullptr, nullptr);
networking_registerhandler(c->net, NET_PACKET_CRYPTO_DATA, nullptr, nullptr);
crypto_memzero(c, sizeof(Net_Crypto));
mem_delete(mem, c);
}

View File

@@ -126,7 +126,6 @@ typedef struct Net_Crypto Net_Crypto;
const uint8_t *_Nonnull nc_get_self_public_key(const Net_Crypto *_Nonnull c);
const uint8_t *_Nonnull nc_get_self_secret_key(const Net_Crypto *_Nonnull c);
TCP_Connections *_Nonnull nc_get_tcp_c(const Net_Crypto *_Nonnull c);
DHT *_Nonnull nc_get_dht(const Net_Crypto *_Nonnull c);
typedef struct New_Connection {
IP_Port source;
@@ -369,7 +368,8 @@ void load_secret_key(Net_Crypto *_Nonnull c, const uint8_t *_Nonnull sk);
/** @brief Create new instance of Net_Crypto.
* Sets all the global connection variables to their default values.
*/
Net_Crypto *_Nullable new_net_crypto(const Logger *_Nonnull log, const Memory *_Nonnull mem, const Random *_Nonnull rng, const Network *_Nonnull ns, Mono_Time *_Nonnull mono_time, DHT *_Nonnull dht,
Net_Crypto *_Nullable new_net_crypto(const Logger *_Nonnull log, const Memory *_Nonnull mem, const Random *_Nonnull rng, const Network *_Nonnull ns, Mono_Time *_Nonnull mono_time,
Networking_Core *_Nonnull net, DHT *_Nonnull dht,
const TCP_Proxy_Info *_Nonnull proxy_info, Net_Profile *_Nonnull tcp_np);
/** return the optimal interval in ms for running do_net_crypto. */

View File

@@ -76,7 +76,7 @@ void TestNetCrypto(Fuzz_Data &input)
const Ptr<Net_Crypto> net_crypto(
new_net_crypto(logger.get(), sys.mem.get(), sys.rng.get(), sys.ns.get(), mono_time.get(),
dht.get(), &proxy_info, tcp_np),
net.get(), dht.get(), &proxy_info, tcp_np),
kill_net_crypto);
if (net_crypto == nullptr) {
netprof_kill(sys.mem.get(), tcp_np);

180
toxcore/net_log.c Normal file
View File

@@ -0,0 +1,180 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
/**
* Network traffic logging function.
*/
#include "net_log.h"
#include "attributes.h"
#include "logger.h"
#include "network.h"
#include "util.h"
static uint32_t data_0(uint16_t buflen, const uint8_t *_Nonnull buffer)
{
uint32_t data = 0;
if (buflen > 4) {
net_unpack_u32(buffer + 1, &data);
}
return data;
}
static uint32_t data_1(uint16_t buflen, const uint8_t *_Nonnull buffer)
{
uint32_t data = 0;
if (buflen > 8) {
net_unpack_u32(buffer + 5, &data);
}
return data;
}
static const char *net_packet_type_name(Net_Packet_Type type)
{
switch (type) {
case NET_PACKET_PING_REQUEST:
return "PING_REQUEST";
case NET_PACKET_PING_RESPONSE:
return "PING_RESPONSE";
case NET_PACKET_NODES_REQUEST:
return "NODES_REQUEST";
case NET_PACKET_NODES_RESPONSE:
return "NODES_RESPONSE";
case NET_PACKET_COOKIE_REQUEST:
return "COOKIE_REQUEST";
case NET_PACKET_COOKIE_RESPONSE:
return "COOKIE_RESPONSE";
case NET_PACKET_CRYPTO_HS:
return "CRYPTO_HS";
case NET_PACKET_CRYPTO_DATA:
return "CRYPTO_DATA";
case NET_PACKET_CRYPTO:
return "CRYPTO";
case NET_PACKET_GC_HANDSHAKE:
return "GC_HANDSHAKE";
case NET_PACKET_GC_LOSSLESS:
return "GC_LOSSLESS";
case NET_PACKET_GC_LOSSY:
return "GC_LOSSY";
case NET_PACKET_LAN_DISCOVERY:
return "LAN_DISCOVERY";
case NET_PACKET_ONION_SEND_INITIAL:
return "ONION_SEND_INITIAL";
case NET_PACKET_ONION_SEND_1:
return "ONION_SEND_1";
case NET_PACKET_ONION_SEND_2:
return "ONION_SEND_2";
case NET_PACKET_ANNOUNCE_REQUEST_OLD:
return "ANNOUNCE_REQUEST_OLD";
case NET_PACKET_ANNOUNCE_RESPONSE_OLD:
return "ANNOUNCE_RESPONSE_OLD";
case NET_PACKET_ONION_DATA_REQUEST:
return "ONION_DATA_REQUEST";
case NET_PACKET_ONION_DATA_RESPONSE:
return "ONION_DATA_RESPONSE";
case NET_PACKET_ANNOUNCE_REQUEST:
return "ANNOUNCE_REQUEST";
case NET_PACKET_ANNOUNCE_RESPONSE:
return "ANNOUNCE_RESPONSE";
case NET_PACKET_ONION_RECV_3:
return "ONION_RECV_3";
case NET_PACKET_ONION_RECV_2:
return "ONION_RECV_2";
case NET_PACKET_ONION_RECV_1:
return "ONION_RECV_1";
case NET_PACKET_FORWARD_REQUEST:
return "FORWARD_REQUEST";
case NET_PACKET_FORWARDING:
return "FORWARDING";
case NET_PACKET_FORWARD_REPLY:
return "FORWARD_REPLY";
case NET_PACKET_DATA_SEARCH_REQUEST:
return "DATA_SEARCH_REQUEST";
case NET_PACKET_DATA_SEARCH_RESPONSE:
return "DATA_SEARCH_RESPONSE";
case NET_PACKET_DATA_RETRIEVE_REQUEST:
return "DATA_RETRIEVE_REQUEST";
case NET_PACKET_DATA_RETRIEVE_RESPONSE:
return "DATA_RETRIEVE_RESPONSE";
case NET_PACKET_STORE_ANNOUNCE_REQUEST:
return "STORE_ANNOUNCE_REQUEST";
case NET_PACKET_STORE_ANNOUNCE_RESPONSE:
return "STORE_ANNOUNCE_RESPONSE";
case BOOTSTRAP_INFO_PACKET_ID:
return "BOOTSTRAP_INFO";
case NET_PACKET_MAX:
return "MAX";
}
return "<unknown>";
}
void net_log_data(const Logger *log, const char *message, const uint8_t *buffer,
uint16_t buflen, const IP_Port *ip_port, long res)
{
if (res < 0) { /* Windows doesn't necessarily know `%zu` */
Ip_Ntoa ip_str;
const int error = net_error();
Net_Strerror error_str;
LOGGER_TRACE(log, "[%02x = %-21s] %s %3u%c %s:%u (%d: %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,
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 (%d: %s) | %08x%08x...%02x",
buffer[0], net_packet_type_name((Net_Packet_Type)buffer[0]), message,
min_u16(res, 999), (size_t)res < buflen ? '<' : '=',
net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port), 0, "OK",
data_0(buflen, buffer), data_1(buflen, buffer), buffer[buflen - 1]);
} else { /* empty or overwrite */
Ip_Ntoa ip_str;
LOGGER_TRACE(log, "[%02x = %-21s] %s %ld%c%u %s:%u (%d: %s) | %08x%08x...%02x",
buffer[0], net_packet_type_name((Net_Packet_Type)buffer[0]), message,
res, res == 0 ? '!' : '>', buflen,
net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port), 0, "OK",
data_0(buflen, buffer), data_1(buflen, buffer), buffer[buflen - 1]);
}
}

27
toxcore/net_log.h Normal file
View File

@@ -0,0 +1,27 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
#ifndef C_TOXCORE_TOXCORE_NET_LOG_H
#define C_TOXCORE_TOXCORE_NET_LOG_H
#include <stdbool.h> // bool
#include <stdint.h> // uint*_t
#include "attributes.h"
#include "logger.h"
#include "network.h"
#ifdef __cplusplus
extern "C" {
#endif
void net_log_data(const Logger *_Nonnull log, const char *_Nonnull message, const uint8_t *_Nonnull buffer,
uint16_t buflen, const IP_Port *_Nonnull ip_port, long res);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* C_TOXCORE_TOXCORE_NET_LOG_H */

View File

@@ -86,6 +86,7 @@
#include "ccompat.h"
#include "logger.h"
#include "mem.h"
#include "net_log.h"
#include "net_profile.h"
#include "util.h"
@@ -714,170 +715,6 @@ static int net_getsockopt(const Network *_Nonnull ns, Socket sock, int level, in
return ns->funcs->getsockopt(ns->obj, sock, level, optname, optval, optlen);
}
static uint32_t data_0(uint16_t buflen, const uint8_t *_Nonnull buffer)
{
uint32_t data = 0;
if (buflen > 4) {
net_unpack_u32(buffer + 1, &data);
}
return data;
}
static uint32_t data_1(uint16_t buflen, const uint8_t *_Nonnull buffer)
{
uint32_t data = 0;
if (buflen > 8) {
net_unpack_u32(buffer + 5, &data);
}
return data;
}
static const char *net_packet_type_name(Net_Packet_Type type)
{
switch (type) {
case NET_PACKET_PING_REQUEST:
return "PING_REQUEST";
case NET_PACKET_PING_RESPONSE:
return "PING_RESPONSE";
case NET_PACKET_NODES_REQUEST:
return "NODES_REQUEST";
case NET_PACKET_NODES_RESPONSE:
return "NODES_RESPONSE";
case NET_PACKET_COOKIE_REQUEST:
return "COOKIE_REQUEST";
case NET_PACKET_COOKIE_RESPONSE:
return "COOKIE_RESPONSE";
case NET_PACKET_CRYPTO_HS:
return "CRYPTO_HS";
case NET_PACKET_CRYPTO_DATA:
return "CRYPTO_DATA";
case NET_PACKET_CRYPTO:
return "CRYPTO";
case NET_PACKET_GC_HANDSHAKE:
return "GC_HANDSHAKE";
case NET_PACKET_GC_LOSSLESS:
return "GC_LOSSLESS";
case NET_PACKET_GC_LOSSY:
return "GC_LOSSY";
case NET_PACKET_LAN_DISCOVERY:
return "LAN_DISCOVERY";
case NET_PACKET_ONION_SEND_INITIAL:
return "ONION_SEND_INITIAL";
case NET_PACKET_ONION_SEND_1:
return "ONION_SEND_1";
case NET_PACKET_ONION_SEND_2:
return "ONION_SEND_2";
case NET_PACKET_ANNOUNCE_REQUEST_OLD:
return "ANNOUNCE_REQUEST_OLD";
case NET_PACKET_ANNOUNCE_RESPONSE_OLD:
return "ANNOUNCE_RESPONSE_OLD";
case NET_PACKET_ONION_DATA_REQUEST:
return "ONION_DATA_REQUEST";
case NET_PACKET_ONION_DATA_RESPONSE:
return "ONION_DATA_RESPONSE";
case NET_PACKET_ANNOUNCE_REQUEST:
return "ANNOUNCE_REQUEST";
case NET_PACKET_ANNOUNCE_RESPONSE:
return "ANNOUNCE_RESPONSE";
case NET_PACKET_ONION_RECV_3:
return "ONION_RECV_3";
case NET_PACKET_ONION_RECV_2:
return "ONION_RECV_2";
case NET_PACKET_ONION_RECV_1:
return "ONION_RECV_1";
case NET_PACKET_FORWARD_REQUEST:
return "FORWARD_REQUEST";
case NET_PACKET_FORWARDING:
return "FORWARDING";
case NET_PACKET_FORWARD_REPLY:
return "FORWARD_REPLY";
case NET_PACKET_DATA_SEARCH_REQUEST:
return "DATA_SEARCH_REQUEST";
case NET_PACKET_DATA_SEARCH_RESPONSE:
return "DATA_SEARCH_RESPONSE";
case NET_PACKET_DATA_RETRIEVE_REQUEST:
return "DATA_RETRIEVE_REQUEST";
case NET_PACKET_DATA_RETRIEVE_RESPONSE:
return "DATA_RETRIEVE_RESPONSE";
case NET_PACKET_STORE_ANNOUNCE_REQUEST:
return "STORE_ANNOUNCE_REQUEST";
case NET_PACKET_STORE_ANNOUNCE_RESPONSE:
return "STORE_ANNOUNCE_RESPONSE";
case BOOTSTRAP_INFO_PACKET_ID:
return "BOOTSTRAP_INFO";
case NET_PACKET_MAX:
return "MAX";
}
return "<unknown>";
}
static void loglogdata(const Logger *_Nonnull log, const char *_Nonnull message, const uint8_t *_Nonnull buffer, uint16_t buflen, const IP_Port *_Nonnull ip_port, long res)
{
if (res < 0) { /* Windows doesn't necessarily know `%zu` */
Ip_Ntoa ip_str;
const int error = net_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), (unsigned int)error,
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",
buffer[0], net_packet_type_name((Net_Packet_Type)buffer[0]), message,
min_u16(res, 999), (size_t)res < buflen ? '<' : '=',
net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port), (unsigned int)0, "OK",
data_0(buflen, buffer), data_1(buflen, buffer), buffer[buflen - 1]);
} else { /* empty or overwrite */
Ip_Ntoa ip_str;
LOGGER_TRACE(log, "[%02x = %-21s] %s %lu%c%u %s:%u (%u: %s) | %08x%08x...%02x",
buffer[0], net_packet_type_name((Net_Packet_Type)buffer[0]), message,
(unsigned long)res, res == 0 ? '!' : '>', buflen,
net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port), (unsigned int)0, "OK",
data_0(buflen, buffer), data_1(buflen, buffer), buffer[buflen - 1]);
}
}
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)
{
@@ -887,7 +724,7 @@ int net_send(const Network *ns, const Logger *log,
netprof_record_packet(net_profile, buf[0], res, PACKET_DIRECTION_SEND);
}
loglogdata(log, "T=>", buf, len, ip_port, res);
net_log_data(log, "T=>", buf, len, ip_port, res);
return res;
}
@@ -900,7 +737,7 @@ int net_recv(const Network *ns, const Logger *log,
Socket sock, uint8_t *buf, size_t len, const IP_Port *ip_port)
{
const int res = ns->funcs->recv(ns->obj, sock, buf, len);
loglogdata(log, "=>T", buf, len, ip_port, res);
net_log_data(log, "=>T", buf, len, ip_port, res);
return res;
}
@@ -1068,7 +905,7 @@ int send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet packe
}
const long res = net_sendto(net->ns, net->sock, packet.data, packet.length, &addr, &ipp_copy);
loglogdata(net->log, "O=>", packet.data, packet.length, ip_port, res);
net_log_data(net->log, "O=>", packet.data, packet.length, ip_port, res);
assert(res <= INT_MAX);
@@ -1151,7 +988,7 @@ static int receivepacket(const Network *_Nonnull ns, const Logger *_Nonnull log,
return -1;
}
loglogdata(log, "=>O", data, MAX_UDP_PACKET_SIZE, ip_port, *length);
net_log_data(log, "=>O", data, MAX_UDP_PACKET_SIZE, ip_port, *length);
return 0;
}

View File

@@ -702,7 +702,7 @@ void set_callback_handle_recv_1(Onion *onion, onion_recv_1_cb *function, void *o
onion->callback_object = object;
}
Onion *new_onion(const Logger *log, const Memory *mem, const Mono_Time *mono_time, const Random *rng, DHT *dht)
Onion *new_onion(const Logger *log, const Memory *mem, const Mono_Time *mono_time, const Random *rng, DHT *dht, Networking_Core *net)
{
if (dht == nullptr) {
return nullptr;
@@ -716,7 +716,7 @@ Onion *new_onion(const Logger *log, const Memory *mem, const Mono_Time *mono_tim
onion->log = log;
onion->dht = dht;
onion->net = dht_get_net(dht);
onion->net = net;
onion->mono_time = mono_time;
onion->rng = rng;
onion->mem = mem;

View File

@@ -140,7 +140,7 @@ int onion_send_1(const Onion *_Nonnull onion, const uint8_t *_Nonnull plain, uin
/** Set the callback to be called when the dest ip_port doesn't have TOX_AF_INET6 or TOX_AF_INET as the family. */
void set_callback_handle_recv_1(Onion *_Nonnull onion, onion_recv_1_cb *_Nullable function, void *_Nullable object);
Onion *_Nullable new_onion(const Logger *_Nonnull log, const Memory *_Nonnull mem, const Mono_Time *_Nonnull mono_time, const Random *_Nonnull rng, DHT *_Nonnull dht);
Onion *_Nullable new_onion(const Logger *_Nonnull log, const Memory *_Nonnull mem, const Mono_Time *_Nonnull mono_time, const Random *_Nonnull rng, DHT *_Nonnull dht, Networking_Core *_Nonnull net);
void kill_onion(Onion *_Nullable onion);
#endif /* C_TOXCORE_TOXCORE_ONION_H */

View File

@@ -680,7 +680,8 @@ static int handle_data_request(void *_Nonnull object, const IP_Port *_Nonnull so
return 0;
}
Onion_Announce *new_onion_announce(const Logger *log, const Memory *mem, const Random *rng, const Mono_Time *mono_time, DHT *dht)
Onion_Announce *new_onion_announce(const Logger *log, const Memory *mem, const Random *rng, const Mono_Time *mono_time, DHT *dht,
Networking_Core *net)
{
if (dht == nullptr) {
return nullptr;
@@ -697,7 +698,7 @@ Onion_Announce *new_onion_announce(const Logger *log, const Memory *mem, const R
onion_a->mem = mem;
onion_a->mono_time = mono_time;
onion_a->dht = dht;
onion_a->net = dht_get_net(dht);
onion_a->net = net;
onion_a->extra_data_max_size = 0;
onion_a->extra_data_callback = nullptr;
onion_a->extra_data_object = nullptr;

View File

@@ -124,7 +124,8 @@ typedef int pack_extra_data_cb(void *_Nonnull object, const Logger *_Nonnull log
void onion_announce_extra_data_callback(Onion_Announce *_Nonnull onion_a, uint16_t extra_data_max_size, pack_extra_data_cb *_Nonnull extra_data_callback, void *_Nonnull extra_data_object);
Onion_Announce *_Nullable new_onion_announce(const Logger *_Nonnull log, const Memory *_Nonnull mem, const Random *_Nonnull rng, const Mono_Time *_Nonnull mono_time, DHT *_Nonnull dht);
Onion_Announce *_Nullable new_onion_announce(const Logger *_Nonnull log, const Memory *_Nonnull mem, const Random *_Nonnull rng, const Mono_Time *_Nonnull mono_time, DHT *_Nonnull dht,
Networking_Core *_Nonnull net);
void kill_onion_announce(Onion_Announce *_Nullable onion_a);
#endif /* C_TOXCORE_TOXCORE_ONION_ANNOUNCE_H */

View File

@@ -203,16 +203,6 @@ bool onion_friend_is_groupchat(const Onion_Friend *const onion_friend)
return onion_friend->is_groupchat;
}
DHT *onion_get_dht(const Onion_Client *onion_c)
{
return onion_c->dht;
}
Net_Crypto *onion_get_net_crypto(const Onion_Client *onion_c)
{
return onion_c->c;
}
/** @brief Add a node to the path_nodes bootstrap array.
*
* If a node with the given public key was already in the bootstrap array, this function has no
@@ -2169,7 +2159,8 @@ void do_onion_client(Onion_Client *onion_c)
onion_c->last_run = mono_time_get(onion_c->mono_time);
}
Onion_Client *new_onion_client(const Logger *logger, const Memory *mem, const Random *rng, const Mono_Time *mono_time, Net_Crypto *c)
Onion_Client *new_onion_client(const Logger *logger, const Memory *mem, const Random *rng, const Mono_Time *mono_time, Net_Crypto *c,
DHT *dht, Networking_Core *net)
{
if (c == nullptr) {
return nullptr;
@@ -2192,8 +2183,8 @@ Onion_Client *new_onion_client(const Logger *logger, const Memory *mem, const Ra
onion_c->logger = logger;
onion_c->rng = rng;
onion_c->mem = mem;
onion_c->dht = nc_get_dht(c);
onion_c->net = dht_get_net(onion_c->dht);
onion_c->dht = dht;
onion_c->net = net;
onion_c->c = c;
new_symmetric_key(rng, onion_c->secret_symmetric_key);
crypto_new_keypair(rng, onion_c->temp_public_key, onion_c->temp_secret_key);

View File

@@ -21,7 +21,6 @@
#include "net_crypto.h"
#include "network.h"
#include "onion_announce.h"
#include "ping_array.h"
#define MAX_ONION_CLIENTS 8
#define MAX_ONION_CLIENTS_ANNOUNCE 12 // Number of nodes to announce ourselves to.
@@ -66,9 +65,6 @@
typedef struct Onion_Client Onion_Client;
DHT *_Nonnull onion_get_dht(const Onion_Client *_Nonnull onion_c);
Net_Crypto *_Nonnull onion_get_net_crypto(const Onion_Client *_Nonnull onion_c);
/** @brief Add a node to the path_nodes bootstrap array.
*
* If a node with the given public key was already in the bootstrap array, this function has no
@@ -195,7 +191,8 @@ typedef bool onion_group_announce_cb(Onion_Client *_Nonnull onion_c, uint32_t se
void onion_group_announce_register(Onion_Client *_Nonnull onion_c, onion_group_announce_cb *_Nullable func, void *_Nullable user_data);
void do_onion_client(Onion_Client *_Nonnull onion_c);
Onion_Client *_Nullable new_onion_client(const Logger *_Nonnull logger, const Memory *_Nonnull mem, const Random *_Nonnull rng, const Mono_Time *_Nonnull mono_time, Net_Crypto *_Nonnull c);
Onion_Client *_Nullable new_onion_client(const Logger *_Nonnull logger, const Memory *_Nonnull mem, const Random *_Nonnull rng, const Mono_Time *_Nonnull mono_time, Net_Crypto *_Nonnull c,
DHT *_Nonnull dht, Networking_Core *_Nonnull net);
void kill_onion_client(Onion_Client *_Nullable onion_c);
typedef enum Onion_Connection_Status {

40
toxcore/os_memory.c Normal file
View File

@@ -0,0 +1,40 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2022-2025 The TokTok team.
*/
#include "os_memory.h"
#include <stdlib.h>
#include "attributes.h"
#include "tox_memory.h"
#include "tox_memory_impl.h" // IWYU pragma: keep
static void *os_malloc(void *_Nonnull self, uint32_t size)
{
// cppcheck-suppress misra-c2012-21.3
return malloc(size);
}
static void *os_realloc(void *_Nonnull self, void *_Nullable ptr, uint32_t size)
{
// cppcheck-suppress misra-c2012-21.3
return realloc(ptr, size);
}
static void os_dealloc(void *_Nonnull self, void *_Nullable ptr)
{
// cppcheck-suppress misra-c2012-21.3
free(ptr);
}
static const Tox_Memory_Funcs os_memory_funcs = {
os_malloc,
os_realloc,
os_dealloc,
};
const Tox_Memory os_memory_obj = {&os_memory_funcs};
const Tox_Memory *os_memory(void)
{
return &os_memory_obj;
}

22
toxcore/os_memory.h Normal file
View File

@@ -0,0 +1,22 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2022-2025 The TokTok team.
*/
#ifndef C_TOXCORE_TOXCORE_OS_MEMORY_H
#define C_TOXCORE_TOXCORE_OS_MEMORY_H
#include "tox_memory.h"
#ifdef __cplusplus
extern "C" {
#endif
extern const Tox_Memory os_memory_obj;
const Tox_Memory *os_memory(void);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* C_TOXCORE_TOXCORE_OS_MEMORY_H */

43
toxcore/os_random.c Normal file
View File

@@ -0,0 +1,43 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2022-2025 The TokTok team.
*/
#include "os_random.h"
#include <sodium.h>
#include "attributes.h"
#include "ccompat.h"
#include "tox_random.h"
#include "tox_random_impl.h"
static void os_random_bytes(void *_Nonnull self, uint8_t *_Nonnull bytes, uint32_t length)
{
randombytes(bytes, length);
}
static uint32_t os_random_uniform(void *_Nonnull self, uint32_t upper_bound)
{
return randombytes_uniform(upper_bound);
}
static const Tox_Random_Funcs os_random_funcs = {
os_random_bytes,
os_random_uniform,
};
const Tox_Random os_random_obj = {&os_random_funcs};
const Tox_Random *os_random(void)
{
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
if ((true)) {
return nullptr;
}
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
// It is safe to call this function more than once and from different
// threads -- subsequent calls won't have any effects.
if (sodium_init() == -1) {
return nullptr;
}
return &os_random_obj;
}

26
toxcore/os_random.h Normal file
View File

@@ -0,0 +1,26 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2022-2025 The TokTok team.
*/
#ifndef C_TOXCORE_TOXCORE_OS_RANDOM_H
#define C_TOXCORE_TOXCORE_OS_RANDOM_H
#include "tox_random.h"
#ifdef __cplusplus
extern "C" {
#endif
extern const Tox_Random os_random_obj;
/** @brief System random number generator.
*
* Uses libsodium's CSPRNG (on Linux, `/dev/urandom`).
*/
const Tox_Random *os_random(void);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* C_TOXCORE_TOXCORE_OS_RANDOM_H */

View File

@@ -33,6 +33,7 @@ struct Ping {
const Random *rng;
const Memory *mem;
DHT *dht;
Networking_Core *net;
Ping_Array *ping_array;
Node_format to_ping[MAX_TO_PING];
@@ -83,7 +84,7 @@ void ping_send_request(Ping *ping, const IP_Port *ipp, const uint8_t *public_key
}
// We never check this return value and failures in sendpacket are already logged
sendpacket(dht_get_net(ping->dht), ipp, pk, sizeof(pk));
sendpacket(ping->net, ipp, pk, sizeof(pk));
}
static int ping_send_response(const Ping *_Nonnull ping, const IP_Port *_Nonnull ipp, const uint8_t *_Nonnull public_key, uint64_t ping_id, const uint8_t *_Nonnull shared_encryption_key)
@@ -112,7 +113,7 @@ static int ping_send_response(const Ping *_Nonnull ping, const IP_Port *_Nonnull
return 1;
}
return sendpacket(dht_get_net(ping->dht), ipp, pk, sizeof(pk));
return sendpacket(ping->net, ipp, pk, sizeof(pk));
}
static int handle_ping_request(void *_Nonnull object, const IP_Port *_Nonnull source, const uint8_t *_Nonnull packet, uint16_t length, void *_Nonnull userdata)
@@ -324,7 +325,7 @@ void ping_iterate(Ping *ping)
}
}
Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Random *rng, DHT *dht)
Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Random *rng, DHT *dht, Networking_Core *net)
{
Ping *ping = (Ping *)mem_alloc(mem, sizeof(Ping));
@@ -343,8 +344,9 @@ Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Random *rng,
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);
ping->net = net;
networking_registerhandler(ping->net, NET_PACKET_PING_REQUEST, &handle_ping_request, dht);
networking_registerhandler(ping->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, dht);
return ping;
}
@@ -355,8 +357,8 @@ void ping_kill(const Memory *mem, Ping *ping)
return;
}
networking_registerhandler(dht_get_net(ping->dht), NET_PACKET_PING_REQUEST, nullptr, nullptr);
networking_registerhandler(dht_get_net(ping->dht), NET_PACKET_PING_RESPONSE, nullptr, nullptr);
networking_registerhandler(ping->net, NET_PACKET_PING_REQUEST, nullptr, nullptr);
networking_registerhandler(ping->net, NET_PACKET_PING_RESPONSE, nullptr, nullptr);
ping_array_kill(ping->ping_array);
mem_delete(mem, ping);

View File

@@ -21,7 +21,7 @@
typedef struct Ping Ping;
Ping *_Nullable ping_new(const Memory *_Nonnull mem, const Mono_Time *_Nonnull mono_time, const Random *_Nonnull rng, DHT *_Nonnull dht);
Ping *_Nullable ping_new(const Memory *_Nonnull mem, const Mono_Time *_Nonnull mono_time, const Random *_Nonnull rng, DHT *_Nonnull dht, Networking_Core *_Nonnull net);
void ping_kill(const Memory *_Nonnull mem, Ping *_Nullable ping);
/** @brief Add nodes to the to_ping list.

View File

@@ -9,7 +9,7 @@
#include "sort.h"
struct Memory;
struct Tox_Memory;
template <typename T>
constexpr Sort_Funcs sort_funcs()
@@ -41,7 +41,7 @@ constexpr Sort_Funcs sort_funcs()
// A realistic test case where we have a struct with some stuff and an expensive value we compare.
struct Some_Type {
const Memory *mem;
const Tox_Memory *mem;
std::array<uint32_t, 8> compare_value;
const char *name;

31
toxcore/tox_attributes.h Normal file
View File

@@ -0,0 +1,31 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2022-2025 The TokTok team.
*/
/**
* nonnull attributes for GCC/Clang and Cimple.
*
* This file is a modified version of c-toxcore/toxcore/attributes.h with a
* `tox_` prefix added to the macros to avoid conflicts with client code.
*/
#ifndef C_TOXCORE_TOXCORE_TOX_ATTRIBUTES_H
#define C_TOXCORE_TOXCORE_TOX_ATTRIBUTES_H
/* No declarations here. */
//!TOKSTYLE-
#ifndef __clang__
#define _Nonnull
#define _Nullable
#endif
#ifdef SPARSE
#define tox_bitwise __attribute__((bitwise))
#else
#define tox_bitwise
#endif
//!TOKSTYLE+
#endif /* C_TOXCORE_TOXCORE_TOX_ATTRIBUTES_H */

60
toxcore/tox_memory.c Normal file
View File

@@ -0,0 +1,60 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
#include "tox_memory.h"
#include <string.h>
#include "ccompat.h"
#include "tox_memory_impl.h" // IWYU pragma: keep
Tox_Memory *tox_memory_new(const Tox_Memory_Funcs *funcs, void *user_data)
{
const Tox_Memory bootstrap = {funcs, user_data};
Tox_Memory *mem = (Tox_Memory *)tox_memory_alloc(&bootstrap, sizeof(Tox_Memory));
if (mem == nullptr) {
return nullptr;
}
*mem = bootstrap;
return mem;
}
void tox_memory_free(Tox_Memory *mem)
{
if (mem == nullptr) {
return;
}
tox_memory_dealloc(mem, mem);
}
void *tox_memory_malloc(const Tox_Memory *mem, uint32_t size)
{
void *const ptr = mem->funcs->malloc_callback(mem->user_data, size);
return ptr;
}
void *tox_memory_alloc(const Tox_Memory *mem, uint32_t size)
{
void *const ptr = tox_memory_malloc(mem, size);
if (ptr != nullptr) {
memset(ptr, 0, size);
}
return ptr;
}
void *tox_memory_realloc(const Tox_Memory *mem, void *ptr, uint32_t size)
{
void *const new_ptr = mem->funcs->realloc_callback(mem->user_data, ptr, size);
return new_ptr;
}
void tox_memory_dealloc(const Tox_Memory *mem, void *ptr)
{
mem->funcs->dealloc_callback(mem->user_data, ptr);
}

75
toxcore/tox_memory.h Normal file
View File

@@ -0,0 +1,75 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
/**
* Memory allocation and deallocation functions.
*/
#ifndef C_TOXCORE_TOXCORE_TOX_MEMORY_H
#define C_TOXCORE_TOXCORE_TOX_MEMORY_H
#include <stdint.h> // uint*_t
#include "tox_attributes.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Functions wrapping standard C memory allocation functions. */
typedef struct Tox_Memory_Funcs Tox_Memory_Funcs;
/**
* @brief A dynamic memory allocator.
*/
typedef struct Tox_Memory Tox_Memory;
/**
* @brief Allocates a new allocator using itself to allocate its own memory.
*
* The passed `user_data` is stored and passed to allocator callbacks. It must
* outlive the `Tox_Memory` object, since it may be used by the callback invoked
* in `tox_memory_free`.
*
* @return NULL if allocation fails.
*/
Tox_Memory *_Nullable tox_memory_new(const Tox_Memory_Funcs *_Nonnull funcs, void *_Nullable user_data);
/**
* @brief Destroys the allocator using its own deallocation function.
*
* The stored `user_data` will not be deallocated.
*/
void tox_memory_free(Tox_Memory *_Nullable mem);
/**
* @brief Allocate an array of a given size for built-in types.
*
* The array will not be initialised. Supported built-in types are
* `uint8_t`, `int8_t`, and `int16_t`.
*/
void *_Nullable tox_memory_malloc(const Tox_Memory *_Nonnull mem, uint32_t size);
/**
* @brief Allocate a single zero-initialised object.
*
* Always use as `(T *)tox_memory_alloc(mem, sizeof(T))`. Unlike `calloc`, this
* does not support allocating arrays. Use `malloc` and `memset` for that.
*
* @param mem The memory allocator.
* @param size Size in bytes of each element.
*/
void *_Nullable tox_memory_alloc(const Tox_Memory *_Nonnull mem, uint32_t size);
/** @brief Resize a memory chunk vector. */
void *_Nullable tox_memory_realloc(const Tox_Memory *_Nonnull mem, void *_Nullable ptr, uint32_t size);
/** @brief Free an array, object, or object vector. */
void tox_memory_dealloc(const Tox_Memory *_Nonnull mem, void *_Nullable ptr);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* C_TOXCORE_TOXCORE_TOX_MEMORY_H */

49
toxcore/tox_memory_impl.h Normal file
View File

@@ -0,0 +1,49 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2016-2025 The TokTok team.
* Copyright © 2013 Tox project.
*/
/**
* Datatypes, functions and includes for the core networking.
*/
#ifndef C_TOXCORE_TOXCORE_TOX_MEMORY_IMPL_H
#define C_TOXCORE_TOXCORE_TOX_MEMORY_IMPL_H
#include <stdint.h> // uint*_t
#include "tox_memory.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Allocate a byte array, similar to malloc. */
typedef void *tox_memory_malloc_cb(void *self, uint32_t size);
/** @brief Reallocate a byte array, similar to realloc. */
typedef void *tox_memory_realloc_cb(void *self, void *ptr, uint32_t size);
/**
* @brief Deallocate a byte or object array, similar to free.
*
* Note that `tox_memory_free` will use this callback to deallocate itself, so
* once the deallocation is done, the allocator data structures can no longer be
* referenced.
*/
typedef void tox_memory_dealloc_cb(void *self, void *ptr);
/** @brief Functions wrapping standard C memory allocation functions. */
struct Tox_Memory_Funcs {
tox_memory_malloc_cb *malloc_callback;
tox_memory_realloc_cb *realloc_callback;
tox_memory_dealloc_cb *dealloc_callback;
};
struct Tox_Memory {
const Tox_Memory_Funcs *funcs;
void *user_data;
};
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* C_TOXCORE_TOXCORE_TOX_MEMORY_IMPL_H */

View File

@@ -22,6 +22,8 @@
#include "net_crypto.h"
#include "net_profile.h"
#include "network.h"
#include "os_memory.h"
#include "os_random.h"
#include "tox.h"
#include "tox_struct.h" // IWYU pragma: keep

View File

@@ -22,9 +22,9 @@ typedef uint64_t tox_mono_time_cb(void *user_data);
typedef struct Tox_System {
tox_mono_time_cb *mono_time_callback;
void *mono_time_user_data;
const struct Random *rng;
const struct Tox_Random *rng;
const struct Network *ns;
const struct Memory *mem;
const struct Tox_Memory *mem;
} Tox_System;
Tox_System tox_default_system(void);

42
toxcore/tox_random.c Normal file
View File

@@ -0,0 +1,42 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2022-2025 The TokTok team.
*/
#include "tox_random.h"
#include "ccompat.h"
#include "tox_memory.h"
#include "tox_random_impl.h"
Tox_Random *tox_random_new(const Tox_Random_Funcs *funcs, void *user_data, const Tox_Memory *mem)
{
Tox_Random *rng = (Tox_Random *)tox_memory_alloc(mem, sizeof(Tox_Random));
if (rng == nullptr) {
return nullptr;
}
rng->funcs = funcs;
rng->user_data = user_data;
rng->mem = mem;
return rng;
}
void tox_random_free(Tox_Random *rng)
{
if (rng == nullptr || rng->mem == nullptr) {
return;
}
tox_memory_dealloc(rng->mem, rng);
}
void tox_random_bytes(const Tox_Random *rng, uint8_t *bytes, uint32_t length)
{
rng->funcs->bytes_callback(rng->user_data, bytes, length);
}
uint32_t tox_random_uniform(const Tox_Random *rng, uint32_t upper_bound)
{
return rng->funcs->uniform_callback(rng->user_data, upper_bound);
}

33
toxcore/tox_random.h Normal file
View File

@@ -0,0 +1,33 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2022-2025 The TokTok team.
*/
#ifndef C_TOXCORE_TOXCORE_TOX_RANDOM_H
#define C_TOXCORE_TOXCORE_TOX_RANDOM_H
#include <stdbool.h>
#include <stdint.h>
#include "tox_attributes.h"
#include "tox_memory.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct Tox_Random_Funcs Tox_Random_Funcs;
typedef struct Tox_Random Tox_Random;
Tox_Random *_Nullable tox_random_new(const Tox_Random_Funcs *_Nonnull funcs, void *_Nullable user_data, const Tox_Memory *_Nonnull mem);
void tox_random_free(Tox_Random *_Nullable rng);
void tox_random_bytes(const Tox_Random *_Nonnull rng, uint8_t *_Nonnull bytes, uint32_t length);
uint32_t tox_random_uniform(const Tox_Random *_Nonnull rng, uint32_t upper_bound);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* C_TOXCORE_TOXCORE_TOX_RANDOM_H */

53
toxcore/tox_random_impl.h Normal file
View File

@@ -0,0 +1,53 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2022-2025 The TokTok team.
*/
#ifndef C_TOXCORE_TOXCORE_TOX_RANDOM_IMPL_H
#define C_TOXCORE_TOXCORE_TOX_RANDOM_IMPL_H
#include "tox_memory.h"
#include "tox_random.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Fill a byte array with random bytes.
*
* This is the key generator callback and as such must be a cryptographically
* secure pseudo-random number generator (CSPRNG). The security of Tox heavily
* depends on the security of this RNG.
*/
typedef void tox_random_bytes_cb(void *self, uint8_t *bytes, uint32_t length);
/** @brief Generate a random integer between 0 and @p upper_bound.
*
* Should produce a uniform random distribution, but Tox security does not
* depend on this being correct. In principle, it could even be a non-CSPRNG.
*/
typedef uint32_t tox_random_uniform_cb(void *self, uint32_t upper_bound);
/** @brief Virtual function table for Random. */
struct Tox_Random_Funcs {
tox_random_bytes_cb *bytes_callback;
tox_random_uniform_cb *uniform_callback;
};
/** @brief Random number generator object.
*
* Can be used by test code and fuzzers to make toxcore behave in specific
* well-defined (non-random) ways. Production code ought to use libsodium's
* CSPRNG and use `os_random` below.
*/
struct Tox_Random {
const Tox_Random_Funcs *funcs;
void *user_data;
const Tox_Memory *mem;
};
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* C_TOXCORE_TOXCORE_TOX_RANDOM_IMPL_H */

View File

@@ -6,6 +6,7 @@
#include <vector>
#include "crypto_core.h"
#include "os_random.h"
#include "tox_log_level.h"
#include "tox_options.h"
#include "tox_private.h"