diff --git a/auto_tests/TCP_test.c b/auto_tests/TCP_test.c index d41739f4..1f4626db 100644 --- a/auto_tests/TCP_test.c +++ b/auto_tests/TCP_test.c @@ -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); diff --git a/auto_tests/announce_test.c b/auto_tests/announce_test.c index 92f2d129..94b68bf1 100644 --- a/auto_tests/announce_test.c +++ b/auto_tests/announce_test.c @@ -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); diff --git a/auto_tests/auto_test_support.c b/auto_tests/auto_test_support.c index 256ebb5a..3b32a286 100644 --- a/auto_tests/auto_test_support.c +++ b/auto_tests/auto_test_support.c @@ -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; diff --git a/auto_tests/forwarding_test.c b/auto_tests/forwarding_test.c index 8182d607..a352e936 100644 --- a/auto_tests/forwarding_test.c +++ b/auto_tests/forwarding_test.c @@ -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); diff --git a/auto_tests/lan_discovery_test.c b/auto_tests/lan_discovery_test.c index b92fefe9..d7bf594b 100644 --- a/auto_tests/lan_discovery_test.c +++ b/auto_tests/lan_discovery_test.c @@ -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; diff --git a/auto_tests/onion_test.c b/auto_tests/onion_test.c index bb6ae243..fcc65975 100644 --- a/auto_tests/onion_test.c +++ b/auto_tests/onion_test.c @@ -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); diff --git a/auto_tests/save_load_test.c b/auto_tests/save_load_test.c index a06440e9..97077735 100644 --- a/auto_tests/save_load_test.c +++ b/auto_tests/save_load_test.c @@ -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); diff --git a/auto_tests/tox_events_test.c b/auto_tests/tox_events_test.c index 4831f058..04549b21 100644 --- a/auto_tests/tox_events_test.c +++ b/auto_tests/tox_events_test.c @@ -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]; diff --git a/auto_tests/toxav_many_test.c b/auto_tests/toxav_many_test.c index 86420509..725fe613 100644 --- a/auto_tests/toxav_many_test.c +++ b/auto_tests/toxav_many_test.c @@ -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]); diff --git a/other/DHT_bootstrap.c b/other/DHT_bootstrap.c index 1283b97b..56796ada 100644 --- a/other/DHT_bootstrap.c +++ b/other/DHT_bootstrap.c @@ -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(); diff --git a/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 b/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 index 36581325..7d90b8a8 100644 --- a/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 +++ b/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 @@ -1 +1 @@ -cfa2c61f92df59419af678ef9d6fcd4f5609a505235d77a54c1a4ec66f1c10af /usr/local/bin/tox-bootstrapd +5796f74532156d61d5c715914b5013ae0544892f7d6dca237b1f6a828f49fc9c /usr/local/bin/tox-bootstrapd diff --git a/other/bootstrap_daemon/src/tox-bootstrapd.c b/other/bootstrap_daemon/src/tox-bootstrapd.c index e9634216..735bf0c2 100644 --- a/other/bootstrap_daemon/src/tox-bootstrapd.c +++ b/other/bootstrap_daemon/src/tox-bootstrapd.c @@ -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"); diff --git a/testing/Messenger_test.c b/testing/Messenger_test.c index 0fd4aa32..b36d2a15 100644 --- a/testing/Messenger_test.c +++ b/testing/Messenger_test.c @@ -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); diff --git a/testing/fuzzing/BUILD.bazel b/testing/fuzzing/BUILD.bazel index 254c58e8..87cd5725 100644 --- a/testing/fuzzing/BUILD.bazel +++ b/testing/fuzzing/BUILD.bazel @@ -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", + ], ) diff --git a/testing/fuzzing/bootstrap_harness.cc b/testing/fuzzing/bootstrap_harness.cc index dfcf1d17..49869e29 100644 --- a/testing/fuzzing/bootstrap_harness.cc +++ b/testing/fuzzing/bootstrap_harness.cc @@ -1,27 +1,34 @@ #include #include +#include #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(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); diff --git a/testing/fuzzing/fuzz_support.cc b/testing/fuzzing/fuzz_support.cc index dc568801..b3e8ed32 100644 --- a/testing/fuzzing/fuzz_support.cc +++ b/testing/fuzzing/fuzz_support.cc @@ -3,3 +3,19 @@ */ #include "fuzz_support.h" + +#include + +#include "../../toxcore/crypto_core.h" +#include "../../toxcore/network.h" +#include "../../toxcore/tox_private.h" + +std::unique_ptr fuzz_system(uint64_t &clock) +{ + auto sys = std::make_unique(); + sys->mono_time_callback = [](void *user_data) { return *static_cast(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; +} diff --git a/testing/fuzzing/fuzz_support.h b/testing/fuzzing/fuzz_support.h index c751a86b..a8a1d8da 100644 --- a/testing/fuzzing/fuzz_support.h +++ b/testing/fuzzing/fuzz_support.h @@ -7,8 +7,11 @@ #include #include +#include #include +#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)...); } +std::unique_ptr fuzz_system(uint64_t &clock); + #endif // C_TOXCORE_TESTING_FUZZING_FUZZ_SUPPORT_H diff --git a/testing/fuzzing/toxsave_harness.cc b/testing/fuzzing/toxsave_harness.cc index 7005b3f7..068c9d9a 100644 --- a/testing/fuzzing/toxsave_harness.cc +++ b/testing/fuzzing/toxsave_harness.cc @@ -3,6 +3,8 @@ #include #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); diff --git a/toxav/toxav.c b/toxav/toxav.c index ef5f7b5f..4b14aa83 100644 --- a/toxav/toxav.c +++ b/toxav/toxav.c @@ -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) { diff --git a/toxcore/mono_time.c b/toxcore/mono_time.c index eac3f686..176dbf17 100644 --- a/toxcore/mono_time.c +++ b/toxcore/mono_time.c @@ -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 diff --git a/toxcore/mono_time.h b/toxcore/mono_time.h index 9336ee16..5a367247 100644 --- a/toxcore/mono_time.h +++ b/toxcore/mono_time.h @@ -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). * diff --git a/toxcore/mono_time_test.cc b/toxcore/mono_time_test.cc index 87216c4a..08ac41f3 100644 --- a/toxcore/mono_time_test.cc +++ b/toxcore/mono_time_test.cc @@ -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(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(user_data); }, &test_time); mono_time_update(mono_time); EXPECT_EQ(current_time_monotonic(mono_time), test_time); diff --git a/toxcore/ping_array_test.cc b/toxcore/ping_array_test.cc index 2ac76ddd..36441031 100644 --- a/toxcore/ping_array_test.cc +++ b/toxcore/ping_array_test.cc @@ -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{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{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)); diff --git a/toxcore/tox.c b/toxcore/tox.c index e6608d75..079f4040 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -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(); - } -} diff --git a/toxcore/tox.h b/toxcore/tox.h index 4cd0dea6..73ce452c 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -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. * diff --git a/toxcore/tox_api.c b/toxcore/tox_api.c index c74b4f6a..00051e49 100644 --- a/toxcore/tox_api.c +++ b/toxcore/tox_api.c @@ -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+ diff --git a/toxcore/tox_private.c b/toxcore/tox_private.c index cc171f1c..847e96d4 100644 --- a/toxcore/tox_private.c +++ b/toxcore/tox_private.c @@ -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) { diff --git a/toxcore/tox_private.h b/toxcore/tox_private.h index 714a6a3c..71d7a976 100644 --- a/toxcore/tox_private.h +++ b/toxcore/tox_private.h @@ -10,14 +10,23 @@ #include #include -#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