Squashed 'external/toxcore/c-toxcore/' changes from 1828c5356..c9cdae001

c9cdae001 fix(toxav): remove extra copy of video frame on encode
4f6d4546b test: Improve the fake network library.
a2581e700 refactor(toxcore): generate `Friend_Request` and `Dht_Nodes_Response`
2aaa11770 refactor(toxcore): use Tox_Memory in generated events
5c367452b test(toxcore): fix incorrect mutex in tox_scenario_get_time
8f92e710f perf: Add a timed limit of number of cookie requests.
695b6417a test: Add some more simulated network support.
815ae9ce9 test(toxcore): fix thread-safety in scenario framework
6d85c754e test(toxcore): add unit tests for net_crypto
9c22e79cc test(support): add SimulatedEnvironment for deterministic testing
f34fcb195 chore: Update windows Dockerfile to debian stable (trixie).
ece0e8980 fix(group_moderation): allow validating unsorted sanction list signatures
a4fa754d7 refactor: rename struct Packet to struct Net_Packet
d6f330f85 cleanup: Fix some warnings from coverity.
e206bffa2 fix(group_chats): fix sync packets reverting topics
0e4715598 test: Add new scenario testing framework.
668291f44 refactor(toxcore): decouple Network_Funcs from sockaddr via IP_Port
fc4396cef fix: potential division by zero in toxav and unsafe hex parsing
8e8b352ab refactor: Add nullable annotations to struct members.
7740bb421 refactor: decouple net_crypto from DHT
1936d4296 test: add benchmark for toxav audio and video
46bfdc2df fix: correct printf format specifiers for unsigned integers
REVERT: 1828c5356 fix(toxav): remove extra copy of video frame on encode

git-subtree-dir: external/toxcore/c-toxcore
git-subtree-split: c9cdae001341e701fca980c9bb9febfeb95d2902
This commit is contained in:
Green Sky
2026-01-11 14:42:31 +01:00
parent e95f2cbb1c
commit 565efa4f39
328 changed files with 19057 additions and 13982 deletions

View File

@@ -8,6 +8,8 @@
#include "../toxcore/tox_dispatch.h"
#include "../toxcore/tox_events.h"
#include "../toxcore/tox_struct.h"
#include "../toxcore/net_crypto.h"
#include "../toxcore/DHT.h"
#include "auto_test_support.h"
@@ -15,20 +17,31 @@
#define ABORT_ON_LOG_ERROR true
#endif
static const uint8_t *auto_test_nc_dht_get_shared_key_sent_wrapper(void *dht, const uint8_t *public_key)
{
return dht_get_shared_key_sent((DHT *)dht, public_key);
}
static const uint8_t *auto_test_nc_dht_get_self_public_key_wrapper(const void *dht)
{
return dht_get_self_public_key((const DHT *)dht);
}
static const uint8_t *auto_test_nc_dht_get_self_secret_key_wrapper(const void *dht)
{
return dht_get_self_secret_key((const DHT *)dht);
}
const Net_Crypto_DHT_Funcs auto_test_dht_funcs = {
auto_test_nc_dht_get_shared_key_sent_wrapper,
auto_test_nc_dht_get_self_public_key_wrapper,
auto_test_nc_dht_get_self_secret_key_wrapper,
};
#ifndef USE_IPV6
#define USE_IPV6 1
#endif
Run_Auto_Options default_run_auto_options(void)
{
return (Run_Auto_Options) {
.graph = GRAPH_COMPLETE,
.init_autotox = nullptr,
.tcp_port = 33188,
.events = true,
};
}
// List of live bootstrap nodes. These nodes should have TCP server enabled.
static const struct BootstrapNodes {
const char *ip;
@@ -92,320 +105,8 @@ void bootstrap_tox_live_network(Tox *tox, bool enable_tcp)
}
}
bool all_connected(const AutoTox *autotoxes, uint32_t tox_count)
{
if (tox_count) {
ck_assert(autotoxes != nullptr);
}
for (uint32_t i = 0; i < tox_count; ++i) {
if (tox_self_get_connection_status(autotoxes[i].tox) == TOX_CONNECTION_NONE) {
return false;
}
}
return true;
}
bool all_friends_connected(const AutoTox *autotoxes, uint32_t tox_count)
{
if (tox_count) {
ck_assert(autotoxes != nullptr);
}
for (uint32_t i = 0; i < tox_count; ++i) {
const size_t friend_count = tox_self_get_friend_list_size(autotoxes[i].tox);
for (size_t j = 0; j < friend_count; ++j) {
if (tox_friend_get_connection_status(autotoxes[i].tox, j, nullptr) == TOX_CONNECTION_NONE) {
return false;
}
}
}
return true;
}
void iterate_all_wait(AutoTox *autotoxes, uint32_t tox_count, uint32_t wait)
{
if (tox_count) {
ck_assert(autotoxes != nullptr);
}
for (uint32_t i = 0; i < tox_count; ++i) {
if (autotoxes[i].alive) {
if (autotoxes[i].events) {
Tox_Err_Events_Iterate err;
Tox_Events *events = tox_events_iterate(autotoxes[i].tox, true, &err);
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
tox_dispatch_invoke(autotoxes[i].dispatch, events, &autotoxes[i]);
tox_events_free(events);
} else {
tox_iterate(autotoxes[i].tox, &autotoxes[i]);
}
autotoxes[i].clock += wait;
}
}
/* Also actually sleep a little, to allow for local network processing */
c_sleep(5);
}
static uint64_t get_state_clock_callback(void *user_data)
{
const uint64_t *clock = (const uint64_t *)user_data;
return *clock;
}
void set_mono_time_callback(AutoTox *autotox)
{
ck_assert(autotox != nullptr);
Mono_Time *mono_time = autotox->tox->mono_time;
autotox->clock = current_time_monotonic(mono_time);
ck_assert_msg(autotox->clock >= 1000,
"clock is too low (not initialised?): %lu", (unsigned long)autotox->clock);
mono_time_set_current_time_callback(mono_time, nullptr, nullptr); // set to default first
mono_time_set_current_time_callback(mono_time, get_state_clock_callback, &autotox->clock);
}
void save_autotox(AutoTox *autotox)
{
ck_assert(autotox != nullptr);
fprintf(stderr, "Saving #%u\n", autotox->index);
free(autotox->save_state);
autotox->save_state = nullptr;
autotox->save_size = tox_get_savedata_size(autotox->tox);
ck_assert_msg(autotox->save_size > 0, "save is invalid size %u", (unsigned)autotox->save_size);
autotox->save_state = (uint8_t *)malloc(autotox->save_size);
ck_assert_msg(autotox->save_state != nullptr, "malloc failed");
tox_get_savedata(autotox->tox, autotox->save_state);
}
void kill_autotox(AutoTox *autotox)
{
ck_assert(autotox != nullptr);
ck_assert(autotox->alive);
fprintf(stderr, "Killing #%u\n", autotox->index);
autotox->alive = false;
tox_dispatch_free(autotox->dispatch);
tox_kill(autotox->tox);
}
void reload(AutoTox *autotox)
{
ck_assert(autotox != nullptr);
if (autotox->alive) {
kill_autotox(autotox);
}
fprintf(stderr, "Reloading #%u\n", autotox->index);
ck_assert(autotox->save_state != nullptr);
struct Tox_Options *const options = tox_options_new(nullptr);
ck_assert(options != nullptr);
tox_options_set_ipv6_enabled(options, USE_IPV6);
tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE);
tox_options_set_savedata_data(options, autotox->save_state, autotox->save_size);
autotox->tox = tox_new_log(options, nullptr, &autotox->index);
ck_assert(autotox->tox != nullptr);
autotox->dispatch = tox_dispatch_new(nullptr);
ck_assert(autotox->dispatch != nullptr);
if (autotox->events) {
tox_events_init(autotox->tox);
}
tox_options_free(options);
set_mono_time_callback(autotox);
autotox->alive = true;
}
static void initialise_autotox(struct Tox_Options *options, AutoTox *autotox, uint32_t index, uint32_t state_size,
Run_Auto_Options *autotest_opts)
{
autotox->index = index;
autotox->events = autotest_opts->events;
Tox_Err_New err = TOX_ERR_NEW_OK;
if (index == 0) {
struct Tox_Options *default_opts = tox_options_new(nullptr);
ck_assert(default_opts != nullptr);
tox_options_set_ipv6_enabled(default_opts, USE_IPV6);
if (options == nullptr) {
options = default_opts;
}
if (tox_options_get_udp_enabled(options)) {
tox_options_set_tcp_port(options, 0);
autotest_opts->tcp_port = 0;
autotox->tox = tox_new_log(options, &err, &autotox->index);
ck_assert_msg(err == TOX_ERR_NEW_OK, "unexpected tox_new error: %u", err);
} else {
// Try a few ports for the TCP relay.
for (uint16_t tcp_port = autotest_opts->tcp_port; tcp_port < autotest_opts->tcp_port + 200; ++tcp_port) {
tox_options_set_tcp_port(options, tcp_port);
autotox->tox = tox_new_log(options, &err, &autotox->index);
if (autotox->tox != nullptr) {
autotest_opts->tcp_port = tcp_port;
break;
}
ck_assert_msg(err == TOX_ERR_NEW_PORT_ALLOC, "unexpected tox_new error (expected PORT_ALLOC): %u", err);
}
}
tox_options_free(default_opts);
} else {
// No TCP relay enabled for all the other toxes.
if (options != nullptr) {
tox_options_set_tcp_port(options, 0);
}
autotox->tox = tox_new_log(options, &err, &autotox->index);
}
ck_assert_msg(autotox->tox != nullptr, "failed to create tox instance #%u (error = %u)", index, err);
set_mono_time_callback(autotox);
autotox->dispatch = tox_dispatch_new(nullptr);
ck_assert(autotox->dispatch != nullptr);
if (autotox->events) {
tox_events_init(autotox->tox);
}
autotox->alive = true;
autotox->save_state = nullptr;
if (state_size > 0) {
autotox->state = calloc(1, state_size);
ck_assert(autotox->state != nullptr);
ck_assert_msg(autotox->state != nullptr, "failed to allocate state");
} else {
autotox->state = nullptr;
}
if (autotest_opts->init_autotox != nullptr) {
autotest_opts->init_autotox(autotox, index);
}
}
static void autotox_add_friend(AutoTox *autotoxes, uint32_t adding, uint32_t added)
{
uint8_t public_key[TOX_PUBLIC_KEY_SIZE];
tox_self_get_public_key(autotoxes[added].tox, public_key);
Tox_Err_Friend_Add err;
tox_friend_add_norequest(autotoxes[adding].tox, public_key, &err);
ck_assert(err == TOX_ERR_FRIEND_ADD_OK);
}
static void initialise_friend_graph(Graph_Type graph, uint32_t num_toxes, AutoTox *autotoxes)
{
if (graph == GRAPH_LINEAR) {
printf("toxes #%d-#%u each add adjacent toxes as friends\n", 0, num_toxes - 1);
for (uint32_t i = 0; i < num_toxes; ++i) {
for (uint32_t j = i - 1; j != i + 3; j += 2) {
if (j < num_toxes) {
autotox_add_friend(autotoxes, i, j);
}
}
}
} else if (graph == GRAPH_COMPLETE) {
printf("toxes #%d-#%u add each other as friends\n", 0, num_toxes - 1);
for (uint32_t i = 0; i < num_toxes; ++i) {
for (uint32_t j = 0; j < num_toxes; ++j) {
if (i != j) {
autotox_add_friend(autotoxes, i, j);
}
}
}
} else {
ck_abort_msg("Unknown graph type");
}
}
static void bootstrap_autotoxes(const Tox_Options *options, uint32_t tox_count, const Run_Auto_Options *autotest_opts,
AutoTox *autotoxes)
{
const bool udp_enabled = options != nullptr ? tox_options_get_udp_enabled(options) : true;
printf("bootstrapping all toxes off tox 0\n");
uint8_t dht_key[TOX_PUBLIC_KEY_SIZE];
tox_self_get_dht_id(autotoxes[0].tox, dht_key);
const uint16_t dht_port = tox_self_get_udp_port(autotoxes[0].tox, nullptr);
for (uint32_t i = 1; i < tox_count; ++i) {
Tox_Err_Bootstrap err;
tox_bootstrap(autotoxes[i].tox, "localhost", dht_port, dht_key, &err);
ck_assert_msg(err == TOX_ERR_BOOTSTRAP_OK, "bootstrap error for port %d: %u", dht_port, err);
}
if (!udp_enabled) {
ck_assert(autotest_opts->tcp_port != 0);
printf("bootstrapping all toxes to local TCP relay running on port %d\n", autotest_opts->tcp_port);
for (uint32_t i = 0; i < tox_count; ++i) {
Tox_Err_Bootstrap err;
tox_add_tcp_relay(autotoxes[i].tox, "localhost", autotest_opts->tcp_port, dht_key, &err);
ck_assert(err == TOX_ERR_BOOTSTRAP_OK);
}
}
}
typedef void autotox_test_cb(AutoTox *autotoxes);
void run_auto_test(struct Tox_Options *options, uint32_t tox_count, autotox_test_cb *test,
uint32_t state_size, Run_Auto_Options *autotest_opts)
{
printf("initialising %u toxes\n", tox_count);
AutoTox *autotoxes = (AutoTox *)calloc(tox_count, sizeof(AutoTox));
ck_assert(autotoxes != nullptr);
for (uint32_t i = 0; i < tox_count; ++i) {
initialise_autotox(options, &autotoxes[i], i, state_size, autotest_opts);
}
initialise_friend_graph(autotest_opts->graph, tox_count, autotoxes);
bootstrap_autotoxes(options, tox_count, autotest_opts, autotoxes);
do {
iterate_all_wait(autotoxes, tox_count, ITERATION_INTERVAL);
} while (!all_connected(autotoxes, tox_count));
printf("toxes are online\n");
do {
iterate_all_wait(autotoxes, tox_count, ITERATION_INTERVAL);
} while (!all_friends_connected(autotoxes, tox_count));
printf("tox clients connected\n");
test(autotoxes);
for (uint32_t i = 0; i < tox_count; ++i) {
tox_dispatch_free(autotoxes[i].dispatch);
tox_kill(autotoxes[i].tox);
free(autotoxes[i].state);
free(autotoxes[i].save_state);
}
free(autotoxes);
}
static const char *tox_log_level_name(Tox_Log_Level level)
{
switch (level) {