refactor: Allow overriding mono_time in tox_new.

This makes it so if mono_time is overridden, no monotonic time-related
system call is invoked in tox_new.
This commit is contained in:
iphydf 2022-03-28 22:42:42 +00:00
parent 6baabee695
commit 941026266e
No known key found for this signature in database
GPG Key ID: 3855DBA2D74403C9
28 changed files with 181 additions and 114 deletions

View File

@ -45,7 +45,7 @@ static uint16_t ports[NUM_PORTS] = {13215, 33445, 25643};
static void test_basic(void)
{
Mono_Time *mono_time = mono_time_new();
Mono_Time *mono_time = mono_time_new(nullptr, nullptr);
const Random *rng = system_random();
ck_assert(rng != nullptr);
Logger *logger = logger_new();
@ -297,7 +297,7 @@ static int read_packet_sec_TCP(const Logger *logger, struct sec_TCP_con *con, ui
static void test_some(void)
{
Mono_Time *mono_time = mono_time_new();
Mono_Time *mono_time = mono_time_new(nullptr, nullptr);
const Random *rng = system_random();
ck_assert(rng != nullptr);
Logger *logger = logger_new();
@ -488,9 +488,9 @@ static int oob_data_callback(void *object, const uint8_t *public_key, const uint
static void test_client(void)
{
Mono_Time *mono_time = mono_time_new(nullptr, nullptr);
const Random *rng = system_random();
ck_assert(rng != nullptr);
Mono_Time *mono_time = mono_time_new();
Logger *logger = logger_new();
uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
@ -619,9 +619,9 @@ static void test_client(void)
// Test how the client handles servers that don't respond.
static void test_client_invalid(void)
{
Mono_Time *mono_time = mono_time_new(nullptr, nullptr);
const Random *rng = system_random();
ck_assert(rng != nullptr);
Mono_Time *mono_time = mono_time_new();
Logger *logger = logger_new();
const Network *ns = system_network();
@ -694,7 +694,7 @@ static int tcp_data_callback(void *object, int id, const uint8_t *data, uint16_t
static void test_tcp_connection(void)
{
Mono_Time *mono_time = mono_time_new();
Mono_Time *mono_time = mono_time_new(nullptr, nullptr);
Logger *logger = logger_new();
const Random *rng = system_random();
ck_assert(rng != nullptr);
@ -803,7 +803,7 @@ static int tcp_oobdata_callback(void *object, const uint8_t *public_key, unsigne
static void test_tcp_connection2(void)
{
Mono_Time *mono_time = mono_time_new();
Mono_Time *mono_time = mono_time_new(nullptr, nullptr);
Logger *logger = logger_new();
const Random *rng = system_random();
ck_assert(rng != nullptr);

View File

@ -57,7 +57,7 @@ static void test_store_data(void)
Logger *log = logger_new();
ck_assert(log != nullptr);
logger_callback_log(log, (logger_cb *)print_debug_log, nullptr, nullptr);
Mono_Time *mono_time = mono_time_new();
Mono_Time *mono_time = mono_time_new(nullptr, nullptr);
Networking_Core *net = new_networking_no_udp(log, ns);
DHT *dht = new_dht(log, rng, ns, mono_time, net, true, true);
Forwarding *forwarding = new_forwarding(log, rng, mono_time, dht);

View File

@ -144,7 +144,7 @@ void iterate_all_wait(AutoTox *autotoxes, uint32_t tox_count, uint32_t wait)
c_sleep(5);
}
static uint64_t get_state_clock_callback(Mono_Time *mono_time, void *user_data)
static uint64_t get_state_clock_callback(void *user_data)
{
const uint64_t *clock = (const uint64_t *)user_data;
return *clock;

View File

@ -110,7 +110,7 @@ static Forwarding_Subtox *new_forwarding_subtox(bool no_udp, uint32_t *index, ui
subtox->log = logger_new();
ck_assert(subtox->log != nullptr);
logger_callback_log(subtox->log, (logger_cb *)print_debug_log, nullptr, index);
subtox->mono_time = mono_time_new();
subtox->mono_time = mono_time_new(nullptr, nullptr);
const Random *rng= system_random();
ck_assert(rng != nullptr);

View File

@ -6,7 +6,7 @@
#include "../toxcore/tox_struct.h"
#include "auto_test_support.h"
static uint64_t get_state_clock_callback(Mono_Time *mono_time, void *user_data)
static uint64_t get_state_clock_callback(void *user_data)
{
const uint64_t *clock = (const uint64_t *)user_data;
return *clock;

View File

@ -197,8 +197,8 @@ static void test_basic(void)
const Random *rng = system_random();
ck_assert(rng != nullptr);
Mono_Time *mono_time1 = mono_time_new();
Mono_Time *mono_time2 = mono_time_new();
Mono_Time *mono_time1 = mono_time_new(nullptr, nullptr);
Mono_Time *mono_time2 = mono_time_new(nullptr, nullptr);
IP ip = get_loopback();
Onion *onion1 = new_onion(log1, mono_time1, rng, new_dht(log1, rng, ns, mono_time1, new_networking(log1, ns, &ip, 36567), true, false));
@ -293,7 +293,7 @@ static void test_basic(void)
Logger *log3 = logger_new();
logger_callback_log(log3, (logger_cb *)print_debug_log, nullptr, &index[2]);
Mono_Time *mono_time3 = mono_time_new();
Mono_Time *mono_time3 = mono_time_new(nullptr, nullptr);
Onion *onion3 = new_onion(log3, mono_time3, rng, new_dht(log3, rng, ns, mono_time3, new_networking(log3, ns, &ip, 36569), true, false));
ck_assert_msg((onion3 != nullptr), "Onion failed initializing.");
@ -380,7 +380,7 @@ static Onions *new_onions(const Random *rng, uint16_t port, uint32_t *index)
logger_callback_log(on->log, (logger_cb *)print_debug_log, nullptr, index);
on->mono_time = mono_time_new();
on->mono_time = mono_time_new(nullptr, nullptr);
if (!on->mono_time) {
logger_kill(on->log);

View File

@ -9,6 +9,7 @@
#include "../testing/misc_tools.h"
#include "../toxcore/ccompat.h"
#include "../toxcore/tox.h"
#include "../toxcore/tox_struct.h"
#include "../toxcore/util.h"
#include "auto_test_support.h"
#include "check_compat.h"
@ -109,7 +110,7 @@ typedef struct Time_Data {
uint64_t clock;
} Time_Data;
static uint64_t get_state_clock_callback(Mono_Time *mono_time, void *user_data)
static uint64_t get_state_clock_callback(void *user_data)
{
Time_Data *time_data = (Time_Data *)user_data;
pthread_mutex_lock(&time_data->lock);
@ -127,8 +128,7 @@ static void increment_clock(Time_Data *time_data, uint64_t count)
static void set_current_time_callback(Tox *tox, Time_Data *time_data)
{
// TODO(iphydf): Don't rely on toxcore internals.
Mono_Time *mono_time = ((Messenger *)tox)->mono_time;
Mono_Time *mono_time = tox->mono_time;
mono_time_set_current_time_callback(mono_time, get_state_clock_callback, time_data);
}
@ -160,7 +160,7 @@ static void test_few_clients(void)
Time_Data time_data;
ck_assert_msg(pthread_mutex_init(&time_data.lock, nullptr) == 0, "Failed to init time_data mutex");
time_data.clock = current_time_monotonic(((Messenger *)tox1)->mono_time);
time_data.clock = current_time_monotonic(tox1->mono_time);
set_current_time_callback(tox1, &time_data);
set_current_time_callback(tox2, &time_data);
set_current_time_callback(tox3, &time_data);

View File

@ -9,6 +9,7 @@
#include "../testing/misc_tools.h"
#include "../toxcore/tox.h"
#include "../toxcore/tox_events.h"
#include "../toxcore/tox_struct.h"
#include "auto_test_support.h"
#include "check_compat.h"
@ -37,7 +38,7 @@ static bool await_message(Tox **toxes)
return false;
}
static uint64_t get_state_clock_callback(Mono_Time *mono_time, void *user_data)
static uint64_t get_state_clock_callback(void *user_data)
{
const uint64_t *clock = (const uint64_t *)user_data;
return *clock;
@ -58,14 +59,12 @@ static void test_tox_events(void)
ck_assert_msg(toxes[i] != nullptr, "failed to create tox instances %u", i);
}
// TODO(iphydf): Don't rely on toxcore internals.
uint64_t clock = current_time_monotonic(((Messenger *)toxes[0])->mono_time);
uint64_t clock = current_time_monotonic(toxes[0]->mono_time);
Mono_Time *mono_time;
// TODO(iphydf): Don't rely on toxcore internals.
mono_time = ((Messenger *)toxes[0])->mono_time;
mono_time = toxes[0]->mono_time;
mono_time_set_current_time_callback(mono_time, get_state_clock_callback, &clock);
mono_time = ((Messenger *)toxes[1])->mono_time;
mono_time = toxes[1]->mono_time;
mono_time_set_current_time_callback(mono_time, get_state_clock_callback, &clock);
uint8_t pk[TOX_PUBLIC_KEY_SIZE];

View File

@ -16,6 +16,7 @@
#include "../toxcore/crypto_core.h"
#include "../toxcore/logger.h"
#include "../toxcore/tox.h"
#include "../toxcore/tox_struct.h"
#include "../toxcore/util.h"
#include "auto_test_support.h"
#include "check_compat.h"
@ -134,7 +135,7 @@ typedef struct Time_Data {
uint64_t clock;
} Time_Data;
static uint64_t get_state_clock_callback(Mono_Time *mono_time, void *user_data)
static uint64_t get_state_clock_callback(void *user_data)
{
Time_Data *time_data = (Time_Data *)user_data;
pthread_mutex_lock(&time_data->lock);
@ -152,8 +153,7 @@ static void increment_clock(Time_Data *time_data, uint64_t count)
static void set_current_time_callback(Tox *tox, Time_Data *time_data)
{
// TODO(iphydf): Don't rely on toxcore internals.
Mono_Time *mono_time = ((Messenger *)tox)->mono_time;
Mono_Time *mono_time = tox->mono_time;
mono_time_set_current_time_callback(mono_time, get_state_clock_callback, time_data);
}
@ -174,8 +174,7 @@ static void test_av_three_calls(void)
bootstrap = tox_new_log(nullptr, &error, &index[0]);
ck_assert(error == TOX_ERR_NEW_OK);
// TODO(iphydf): Don't rely on toxcore internals.
time_data.clock = current_time_monotonic(((Messenger *)bootstrap)->mono_time);
time_data.clock = current_time_monotonic(bootstrap->mono_time);
set_current_time_callback(bootstrap, &time_data);
Alice = tox_new_log(nullptr, &error, &index[1]);

View File

@ -142,8 +142,8 @@ int main(int argc, char *argv[])
logger_callback_log(logger, print_log, nullptr, nullptr);
}
Mono_Time *mono_time = mono_time_new();
const Random *rng = system_random();
Mono_Time *mono_time = mono_time_new(nullptr, nullptr);
const uint16_t start_port = PORT;
const uint16_t end_port = start_port + (TOX_PORTRANGE_TO - TOX_PORTRANGE_FROM);
const Network *ns = system_network();

View File

@ -1 +1 @@
cfa2c61f92df59419af678ef9d6fcd4f5609a505235d77a54c1a4ec66f1c10af /usr/local/bin/tox-bootstrapd
5796f74532156d61d5c715914b5013ae0544892f7d6dca237b1f6a828f49fc9c /usr/local/bin/tox-bootstrapd

View File

@ -307,7 +307,7 @@ int main(int argc, char *argv[])
}
}
Mono_Time *const mono_time = mono_time_new();
Mono_Time *const mono_time = mono_time_new(nullptr, nullptr);
if (mono_time == nullptr) {
log_write(LOG_LEVEL_ERROR, "Couldn't initialize monotonic timer. Exiting.\n");

View File

@ -92,7 +92,7 @@ int main(int argc, char *argv[])
exit(0);
}
Mono_Time *const mono_time = mono_time_new();
Mono_Time *const mono_time = mono_time_new(nullptr, nullptr);
if (mono_time == nullptr) {
fputs("Failed to allocate monotonic timer datastructure\n", stderr);

View File

@ -13,6 +13,7 @@ cc_library(
srcs = ["fuzz_support.cc"],
hdrs = ["fuzz_support.h"],
visibility = ["//c-toxcore:__subpackages__"],
deps = ["//c-toxcore/toxcore:tox"],
)
cc_library(
@ -27,7 +28,10 @@ cc_fuzz_test(
srcs = ["bootstrap_harness.cc"],
copts = ["-UNDEBUG"],
corpus = ["//tools/toktok-fuzzer/corpus:bootstrap_fuzzer"],
deps = ["//c-toxcore/toxcore:tox"],
deps = [
":fuzz_support",
"//c-toxcore/toxcore:tox",
],
)
cc_fuzz_test(
@ -35,5 +39,8 @@ cc_fuzz_test(
srcs = ["toxsave_harness.cc"],
copts = ["-UNDEBUG"],
corpus = ["//tools/toktok-fuzzer/corpus:toxsave_fuzzer"],
deps = ["//c-toxcore/toxcore:tox"],
deps = [
":fuzz_support",
"//c-toxcore/toxcore:tox",
],
)

View File

@ -1,27 +1,34 @@
#include <cassert>
#include <cstring>
#include <memory>
#include "../../toxcore/tox.h"
#include "../../toxcore/tox_struct.h"
#include "../../toxcore/tox_private.h"
#include "fuzz_adapter.h"
#include "fuzz_support.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
network_adapter_init(data, size);
Tox_Err_New error_new;
Tox *tox = tox_new(nullptr, &error_new);
uint64_t clock = 0;
mono_time_set_current_time_callback(
tox->mono_time,
[](Mono_Time *mono_time, void *user_data) { return *static_cast<uint64_t *>(user_data); },
&clock);
auto sys = fuzz_system(clock);
assert(sys->mono_time_callback != nullptr);
assert(sys->mono_time_user_data != nullptr);
Tox_Options *opts = tox_options_new(nullptr);
assert(opts != nullptr);
tox_options_set_operating_system(opts, sys.get());
Tox_Err_New error_new;
Tox *tox = tox_new(opts, &error_new);
assert(tox != nullptr);
assert(error_new == TOX_ERR_NEW_OK);
tox_options_free(opts);
uint8_t pub_key[TOX_PUBLIC_KEY_SIZE] = {0};
const bool success = tox_bootstrap(tox, "127.0.0.1", 12345, pub_key, nullptr);

View File

@ -3,3 +3,19 @@
*/
#include "fuzz_support.h"
#include <memory>
#include "../../toxcore/crypto_core.h"
#include "../../toxcore/network.h"
#include "../../toxcore/tox_private.h"
std::unique_ptr<Tox_System> fuzz_system(uint64_t &clock)
{
auto sys = std::make_unique<Tox_System>();
sys->mono_time_callback = [](void *user_data) { return *static_cast<uint64_t *>(user_data); };
sys->mono_time_user_data = &clock;
sys->rng = system_random(); // TODO(iphydf): Put fuzz_random here.
sys->ns = system_network(); // TODO(iphydf): Put fuzz_network here.
return sys;
}

View File

@ -7,8 +7,11 @@
#include <cstdint>
#include <cstdlib>
#include <memory>
#include <utility>
#include "../../toxcore/tox.h"
struct Fuzz_Data {
const uint8_t *data;
std::size_t size;
@ -94,4 +97,6 @@ void fuzz_select_target(const uint8_t *data, std::size_t size, Args &&... args)
return fuzz_select_target(selector, input, std::forward<Args>(args)...);
}
std::unique_ptr<Tox_System> fuzz_system(uint64_t &clock);
#endif // C_TOXCORE_TESTING_FUZZING_FUZZ_SUPPORT_H

View File

@ -3,6 +3,8 @@
#include <vector>
#include "../../toxcore/tox.h"
#include "../../toxcore/tox_private.h"
#include "fuzz_support.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
@ -14,6 +16,10 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
assert(tox_options != nullptr);
assert(error_options == TOX_ERR_OPTIONS_NEW_OK);
uint64_t clock = 0;
auto sys = fuzz_system(clock);
tox_options_set_operating_system(tox_options, sys.get());
// pass test data to Tox
tox_options_set_savedata_data(tox_options, data, size);
tox_options_set_savedata_type(tox_options, TOX_SAVEDATA_TYPE_TOX_SAVE);

View File

@ -181,7 +181,7 @@ ToxAV *toxav_new(Tox *tox, Toxav_Err_New *error)
av->tox = tox;
av->m = m;
av->toxav_mono_time = mono_time_new();
av->toxav_mono_time = mono_time_new(nullptr, nullptr);
av->msi = msi_new(av->m);
if (av->msi == nullptr) {

View File

@ -52,9 +52,11 @@ struct Mono_Time {
};
#ifdef OS_WIN32
non_null(1) nullable(2)
static uint64_t current_time_monotonic_default(Mono_Time *mono_time, void *user_data)
non_null()
static uint64_t current_time_monotonic_default(void *user_data)
{
Mono_Time *const mono_time = (Mono_Time *)user_data;
/* Must hold mono_time->last_clock_lock here */
/* GetTickCount provides only a 32 bit counter, but we can't use
@ -86,8 +88,8 @@ static uint64_t timespec_to_u64(struct timespec clock_mono)
return 1000ULL * clock_mono.tv_sec + (clock_mono.tv_nsec / 1000000ULL);
}
#ifdef __APPLE__
non_null(1) nullable(2)
static uint64_t current_time_monotonic_default(Mono_Time *mono_time, void *user_data)
non_null()
static uint64_t current_time_monotonic_default(void *user_data)
{
struct timespec clock_mono;
clock_serv_t muhclock;
@ -102,13 +104,13 @@ static uint64_t current_time_monotonic_default(Mono_Time *mono_time, void *user_
return timespec_to_u64(clock_mono);
}
#else // !__APPLE__
non_null(1) nullable(2)
static uint64_t current_time_monotonic_default(Mono_Time *mono_time, void *user_data)
non_null()
static uint64_t current_time_monotonic_default(void *user_data)
{
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
// This assert should always fail. If it does, the fuzzing harness didn't
// override the mono time callback.
assert(mono_time == nullptr);
assert(user_data == nullptr);
#endif
struct timespec clock_mono;
clock_gettime(CLOCK_MONOTONIC, &clock_mono);
@ -118,7 +120,7 @@ static uint64_t current_time_monotonic_default(Mono_Time *mono_time, void *user_
#endif // !OS_WIN32
Mono_Time *mono_time_new(void)
Mono_Time *mono_time_new(mono_time_current_time_cb *current_time_callback, void *user_data)
{
Mono_Time *mono_time = (Mono_Time *)calloc(1, sizeof(Mono_Time));
@ -139,8 +141,7 @@ Mono_Time *mono_time_new(void)
return nullptr;
}
mono_time->current_time_callback = current_time_monotonic_default;
mono_time->user_data = nullptr;
mono_time_set_current_time_callback(mono_time, current_time_callback, user_data);
#ifdef OS_WIN32
@ -157,16 +158,14 @@ Mono_Time *mono_time_new(void)
mono_time->cur_time = 0;
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
// Maximum reproducibility and don't update mono_time before the harness has
// had a chance to set the callback.
// TODO(iphydf): Put mono time callback into Tox_Options with accessors only
// in tox_private.h.
mono_time->base_time = 0;
// Maximum reproducibility. Never return time = 0.
mono_time->base_time = 1;
#else
mono_time->base_time = (uint64_t)time(nullptr) - (current_time_monotonic(mono_time) / 1000ULL);
mono_time_update(mono_time);
#endif
mono_time_update(mono_time);
return mono_time;
}
@ -191,7 +190,7 @@ void mono_time_update(Mono_Time *mono_time)
pthread_mutex_lock(&mono_time->last_clock_lock);
mono_time->last_clock_update = true;
#endif
cur_time = mono_time->current_time_callback(mono_time, mono_time->user_data) / 1000ULL;
cur_time = mono_time->current_time_callback(mono_time->user_data) / 1000ULL;
cur_time += mono_time->base_time;
#ifdef OS_WIN32
pthread_mutex_unlock(&mono_time->last_clock_lock);
@ -225,7 +224,7 @@ void mono_time_set_current_time_callback(Mono_Time *mono_time,
{
if (current_time_callback == nullptr) {
mono_time->current_time_callback = current_time_monotonic_default;
mono_time->user_data = nullptr;
mono_time->user_data = mono_time;
} else {
mono_time->current_time_callback = current_time_callback;
mono_time->user_data = user_data;
@ -244,7 +243,7 @@ uint64_t current_time_monotonic(Mono_Time *mono_time)
* but must protect against other threads */
pthread_mutex_lock(&mono_time->last_clock_lock);
#endif
const uint64_t cur_time = mono_time->current_time_callback(mono_time, mono_time->user_data);
const uint64_t cur_time = mono_time->current_time_callback(mono_time->user_data);
#ifdef OS_WIN32
pthread_mutex_unlock(&mono_time->last_clock_lock);
#endif

View File

@ -45,7 +45,10 @@ extern "C" {
*/
typedef struct Mono_Time Mono_Time;
Mono_Time *mono_time_new(void);
typedef uint64_t mono_time_current_time_cb(void *user_data);
nullable(1, 2)
Mono_Time *mono_time_new(mono_time_current_time_cb *current_time_callback, void *user_data);
nullable(1)
void mono_time_free(Mono_Time *mono_time);
@ -76,8 +79,6 @@ bool mono_time_is_timeout(const Mono_Time *mono_time, uint64_t timestamp, uint64
non_null()
uint64_t current_time_monotonic(Mono_Time *mono_time);
typedef uint64_t mono_time_current_time_cb(Mono_Time *mono_time, void *user_data);
/**
* Override implementation of `current_time_monotonic()` (for tests).
*

View File

@ -6,7 +6,7 @@ namespace {
TEST(MonoTime, UnixTimeIncreasesOverTime)
{
Mono_Time *mono_time = mono_time_new();
Mono_Time *mono_time = mono_time_new(nullptr, nullptr);
ASSERT_NE(mono_time, nullptr);
mono_time_update(mono_time);
@ -24,7 +24,7 @@ TEST(MonoTime, UnixTimeIncreasesOverTime)
TEST(MonoTime, IsTimeout)
{
Mono_Time *mono_time = mono_time_new();
Mono_Time *mono_time = mono_time_new(nullptr, nullptr);
ASSERT_NE(mono_time, nullptr);
uint64_t const start = mono_time_get(mono_time);
@ -39,19 +39,15 @@ TEST(MonoTime, IsTimeout)
mono_time_free(mono_time);
}
uint64_t test_current_time_callback(Mono_Time *mono_time, void *user_data)
{
return *static_cast<uint64_t *>(user_data);
}
TEST(MonoTime, CustomTime)
{
Mono_Time *mono_time = mono_time_new();
Mono_Time *mono_time = mono_time_new(nullptr, nullptr);
ASSERT_NE(mono_time, nullptr);
uint64_t test_time = current_time_monotonic(mono_time) + 42137;
mono_time_set_current_time_callback(mono_time, test_current_time_callback, &test_time);
mono_time_set_current_time_callback(
mono_time, [](void *user_data) { return *static_cast<uint64_t *>(user_data); }, &test_time);
mono_time_update(mono_time);
EXPECT_EQ(current_time_monotonic(mono_time), test_time);

View File

@ -49,10 +49,10 @@ TEST(PingArray, ArraySizeMustBePowerOfTwo)
TEST(PingArray, StoredDataCanBeRetrieved)
{
Ping_Array_Ptr const arr(ping_array_new(2, 1));
Mono_Time_Ptr const mono_time(mono_time_new());
Mono_Time_Ptr const mono_time(mono_time_new(nullptr, nullptr));
ASSERT_NE(mono_time, nullptr);
const Random *rng = system_random();
ASSERT_NE(rng, nullptr);
ASSERT_NE(mono_time, nullptr);
uint64_t const ping_id = ping_array_add(
arr.get(), mono_time.get(), rng, std::vector<uint8_t>{1, 2, 3, 4}.data(), 4);
@ -66,10 +66,10 @@ TEST(PingArray, StoredDataCanBeRetrieved)
TEST(PingArray, RetrievingDataWithTooSmallOutputBufferHasNoEffect)
{
Ping_Array_Ptr const arr(ping_array_new(2, 1));
Mono_Time_Ptr const mono_time(mono_time_new());
Mono_Time_Ptr const mono_time(mono_time_new(nullptr, nullptr));
ASSERT_NE(mono_time, nullptr);
const Random *rng = system_random();
ASSERT_NE(rng, nullptr);
ASSERT_NE(mono_time, nullptr);
uint64_t const ping_id = ping_array_add(
arr.get(), mono_time.get(), rng, (std::vector<uint8_t>{1, 2, 3, 4}).data(), 4);
@ -87,10 +87,10 @@ TEST(PingArray, RetrievingDataWithTooSmallOutputBufferHasNoEffect)
TEST(PingArray, ZeroLengthDataCanBeAdded)
{
Ping_Array_Ptr const arr(ping_array_new(2, 1));
Mono_Time_Ptr const mono_time(mono_time_new());
Mono_Time_Ptr const mono_time(mono_time_new(nullptr, nullptr));
ASSERT_NE(mono_time, nullptr);
const Random *rng = system_random();
ASSERT_NE(rng, nullptr);
ASSERT_NE(mono_time, nullptr);
uint8_t c = 0;
uint64_t const ping_id = ping_array_add(arr.get(), mono_time.get(), rng, &c, sizeof(c));
@ -102,7 +102,7 @@ TEST(PingArray, ZeroLengthDataCanBeAdded)
TEST(PingArray, PingId0IsInvalid)
{
Ping_Array_Ptr const arr(ping_array_new(2, 1));
Mono_Time_Ptr const mono_time(mono_time_new());
Mono_Time_Ptr const mono_time(mono_time_new(nullptr, nullptr));
ASSERT_NE(mono_time, nullptr);
uint8_t c = 0;
@ -113,10 +113,10 @@ TEST(PingArray, PingId0IsInvalid)
TEST(PingArray, DataCanOnlyBeRetrievedOnce)
{
Ping_Array_Ptr const arr(ping_array_new(2, 1));
Mono_Time_Ptr const mono_time(mono_time_new());
Mono_Time_Ptr const mono_time(mono_time_new(nullptr, nullptr));
ASSERT_NE(mono_time, nullptr);
const Random *rng = system_random();
ASSERT_NE(rng, nullptr);
ASSERT_NE(mono_time, nullptr);
uint8_t c = 0;
uint64_t const ping_id = ping_array_add(arr.get(), mono_time.get(), rng, &c, sizeof(c));
@ -129,10 +129,10 @@ TEST(PingArray, DataCanOnlyBeRetrievedOnce)
TEST(PingArray, PingIdMustMatchOnCheck)
{
Ping_Array_Ptr const arr(ping_array_new(1, 1));
Mono_Time_Ptr const mono_time(mono_time_new());
Mono_Time_Ptr const mono_time(mono_time_new(nullptr, nullptr));
ASSERT_NE(mono_time, nullptr);
const Random *rng = system_random();
ASSERT_NE(rng, nullptr);
ASSERT_NE(mono_time, nullptr);
uint8_t c = 0;
uint64_t const ping_id = ping_array_add(arr.get(), mono_time.get(), rng, &c, sizeof(c));

View File

@ -520,7 +520,22 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
}
}
tox_set_network(tox, nullptr);
const Tox_System *sys = tox_options_get_operating_system(opts);
const Tox_System default_system = tox_default_system();
if (sys == nullptr) {
sys = &default_system;
}
if (sys->rng == nullptr || sys->ns == nullptr) {
// TODO(iphydf): Not quite right, but similar.
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
tox_options_free(default_options);
free(tox);
return nullptr;
}
tox->rng = *sys->rng;
tox->ns = *sys->ns;
if (m_options.proxy_info.proxy_type != TCP_PROXY_NONE) {
if (tox_options_get_proxy_port(opts) == 0) {
@ -549,18 +564,7 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
m_options.proxy_info.ip_port.port = net_htons(tox_options_get_proxy_port(opts));
}
const Random *rng = system_random();
if (rng == nullptr) {
// TODO(iphydf): Not quite right, but similar.
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
tox_options_free(default_options);
free(tox);
return nullptr;
}
tox->rng = *rng;
tox->mono_time = mono_time_new();
tox->mono_time = mono_time_new(sys->mono_time_callback, sys->mono_time_user_data);
if (tox->mono_time == nullptr) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
@ -2576,13 +2580,3 @@ uint16_t tox_self_get_tcp_port(const Tox *tox, Tox_Err_Get_Port *error)
tox_unlock(tox);
return 0;
}
void tox_set_network(Tox *tox, const Network *ns)
{
assert(tox != nullptr);
if (ns != nullptr) {
tox->ns = *ns;
} else {
tox->ns = *system_network();
}
}

View File

@ -501,6 +501,16 @@ typedef void tox_log_cb(Tox *tox, Tox_Log_Level level, const char *file, uint32_
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.
*
@ -673,6 +683,12 @@ struct Tox_Options {
*/
bool experimental_thread_safety;
/**
* Low level operating system functionality such as send/recv and random
* number generation.
*/
const Tox_System *operating_system;
};
@ -744,6 +760,10 @@ bool tox_options_get_experimental_thread_safety(const struct Tox_Options *option
void tox_options_set_experimental_thread_safety(struct Tox_Options *options, bool experimental_thread_safety);
const Tox_System *tox_options_get_operating_system(const struct Tox_Options *options);
void tox_options_set_operating_system(struct Tox_Options *options, const Tox_System *operating_system);
/**
* @brief Initialises a Tox_Options object with the default options.
*

View File

@ -97,7 +97,6 @@ uint32_t tox_dht_node_public_key_size(void)
return TOX_DHT_NODE_PUBLIC_KEY_SIZE;
}
//!TOKSTYLE-
#define ACCESSORS(type, ns, name) \
@ -126,6 +125,7 @@ ACCESSORS(void *, log_, user_data)
ACCESSORS(bool,, local_discovery_enabled)
ACCESSORS(bool,, dht_announcements_enabled)
ACCESSORS(bool,, experimental_thread_safety)
ACCESSORS(const Tox_System *,, operating_system)
//!TOKSTYLE+

View File

@ -21,6 +21,17 @@
} \
} while (0)
Tox_System tox_default_system(void)
{
const Tox_System sys = {
nullptr, // mono_time_callback
nullptr, // mono_time_user_data
system_random(),
system_network(),
};
return sys;
}
void tox_lock(const Tox *tox)
{
if (tox->mutex != nullptr) {

View File

@ -10,14 +10,23 @@
#include <stddef.h>
#include <stdint.h>
#include "DHT.h"
#include "network.h"
#include "tox.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef uint64_t tox_mono_time_cb(void *user_data);
struct Tox_System {
tox_mono_time_cb *mono_time_callback;
void *mono_time_user_data;
const struct Random *rng;
const struct Network *ns;
};
Tox_System tox_default_system(void);
void tox_lock(const Tox *tox);
void tox_unlock(const Tox *tox);
@ -130,8 +139,6 @@ typedef enum Tox_Err_Dht_Get_Nodes {
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);
void tox_set_network(Tox *tox, const Network *ns);
#ifdef __cplusplus
}
#endif