From abc17b0f8997ab07ae66130edd5dc8c43e72c886 Mon Sep 17 00:00:00 2001 From: iphydf Date: Sun, 8 Jul 2018 08:43:42 +0000 Subject: Factor out time keeping code into its own module: mono_time.c. It turns out, `unix_time` is also monotonic, and is used as such, so I've renamed the new functions to `mono_time_*`. 2018-07-08: ``` 00:01 <@irungentoo> the idea used to be that the unix_time() function could go backward in time but I think I might have started using it like if it could not after I changed it so that it would never go back in time ``` --- toxcore/BUILD.bazel | 17 +++++ toxcore/DHT.c | 1 + toxcore/Makefile.inc | 2 + toxcore/Messenger.c | 5 +- toxcore/TCP_client.c | 1 + toxcore/TCP_connection.c | 1 + toxcore/TCP_server.c | 1 + toxcore/friend_connection.c | 1 + toxcore/group.c | 1 + toxcore/mono_time.c | 157 ++++++++++++++++++++++++++++++++++++++++++++ toxcore/mono_time.h | 35 ++++++++++ toxcore/mono_time_test.cc | 30 +++++++++ toxcore/net_crypto.c | 1 + toxcore/network.c | 69 +------------------ toxcore/network.h | 3 - toxcore/onion.c | 1 + toxcore/onion_announce.c | 1 + toxcore/onion_client.c | 1 + toxcore/ping.c | 1 + toxcore/ping_array.c | 1 + toxcore/tox.c | 7 ++ toxcore/util.c | 63 ------------------ toxcore/util.h | 15 ----- toxcore/util_test.cc | 25 +------ 24 files changed, 267 insertions(+), 173 deletions(-) create mode 100644 toxcore/mono_time.c create mode 100644 toxcore/mono_time.h create mode 100644 toxcore/mono_time_test.cc (limited to 'toxcore') diff --git a/toxcore/BUILD.bazel b/toxcore/BUILD.bazel index 381a1255..543bb59f 100644 --- a/toxcore/BUILD.bazel +++ b/toxcore/BUILD.bazel @@ -58,6 +58,22 @@ cc_library( deps = [":logger"], ) +cc_library( + name = "mono_time", + srcs = ["mono_time.c"], + hdrs = ["mono_time.h"], + deps = [":ccompat"], +) + +cc_test( + name = "mono_time_test", + srcs = ["mono_time_test.cc"], + deps = [ + ":mono_time", + "@com_google_googletest//:gtest_main", + ], +) + cc_library( name = "network", srcs = [ @@ -77,6 +93,7 @@ cc_library( ":ccompat", ":crypto_core", ":logger", + ":mono_time", ], ) diff --git a/toxcore/DHT.c b/toxcore/DHT.c index fe3c1159..2572b28a 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -29,6 +29,7 @@ #include "LAN_discovery.h" #include "logger.h" +#include "mono_time.h" #include "network.h" #include "ping.h" #include "state.h" diff --git a/toxcore/Makefile.inc b/toxcore/Makefile.inc index 4a007a66..a68b2a7d 100644 --- a/toxcore/Makefile.inc +++ b/toxcore/Makefile.inc @@ -8,6 +8,8 @@ libtoxcore_la_includedir = $(includedir)/tox libtoxcore_la_SOURCES = ../toxcore/ccompat.h \ ../toxcore/DHT.h \ ../toxcore/DHT.c \ + ../toxcore/mono_time.h \ + ../toxcore/mono_time.c \ ../toxcore/network.h \ ../toxcore/network.c \ ../toxcore/crypto_core.h \ diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 404827c6..a5d15a34 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -34,6 +34,7 @@ #include #include "logger.h" +#include "mono_time.h" #include "network.h" #include "state.h" #include "util.h" @@ -1764,8 +1765,8 @@ static int handle_filecontrol(Messenger *m, int32_t friendnumber, uint8_t receiv if (position >= ft->size) { LOGGER_DEBUG(m->log, - "file control (friend %d, file %d): seek position %lld exceeds file size %lld", - friendnumber, filenumber, (unsigned long long)position, (unsigned long long)ft->size); + "file control (friend %d, file %d): seek position %ld exceeds file size %ld", + friendnumber, filenumber, (unsigned long)position, (unsigned long)ft->size); return -1; } diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index d1cd4d66..1291d276 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c @@ -31,6 +31,7 @@ #include #include +#include "mono_time.h" #include "util.h" struct TCP_Client_Connection { diff --git a/toxcore/TCP_connection.c b/toxcore/TCP_connection.c index 06cb6e34..cd1fb565 100644 --- a/toxcore/TCP_connection.c +++ b/toxcore/TCP_connection.c @@ -31,6 +31,7 @@ #include #include +#include "mono_time.h" #include "util.h" diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c index b31fab72..032b07b3 100644 --- a/toxcore/TCP_server.c +++ b/toxcore/TCP_server.c @@ -39,6 +39,7 @@ #include #endif +#include "mono_time.h" #include "util.h" typedef struct TCP_Secure_Connection { diff --git a/toxcore/friend_connection.c b/toxcore/friend_connection.c index 64a04773..4d245871 100644 --- a/toxcore/friend_connection.c +++ b/toxcore/friend_connection.c @@ -31,6 +31,7 @@ #include #include +#include "mono_time.h" #include "util.h" #define PORTS_PER_DISCOVERY 10 diff --git a/toxcore/group.c b/toxcore/group.c index b7042f2f..4942d872 100644 --- a/toxcore/group.c +++ b/toxcore/group.c @@ -30,6 +30,7 @@ #include #include +#include "mono_time.h" #include "util.h" /* return 1 if the groupnumber is not valid. diff --git a/toxcore/mono_time.c b/toxcore/mono_time.c new file mode 100644 index 00000000..6f54731b --- /dev/null +++ b/toxcore/mono_time.c @@ -0,0 +1,157 @@ +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 600 +#endif + +#if !defined(OS_WIN32) && (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) +#define OS_WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif + +#ifdef __APPLE__ +#include +#include +#endif + +#ifndef OS_WIN32 +#include +#endif + +#include "mono_time.h" + +#include +#include + +#include "ccompat.h" + +/* don't call into system billions of times for no reason */ +struct Mono_Time { + uint64_t time; + uint64_t base_time; +}; + +Mono_Time *mono_time_new(void) +{ + Mono_Time *monotime = (Mono_Time *)malloc(sizeof(Mono_Time)); + + if (monotime == nullptr) { + return nullptr; + } + + monotime->time = 0; + monotime->base_time = 0; + + return monotime; +} + +void mono_time_free(Mono_Time *monotime) +{ + free(monotime); +} + +void mono_time_update(Mono_Time *monotime) +{ + if (monotime->base_time == 0) { + monotime->base_time = ((uint64_t)time(nullptr) - (current_time_monotonic() / 1000ULL)); + } + + monotime->time = (current_time_monotonic() / 1000ULL) + monotime->base_time; +} + +uint64_t mono_time_get(const Mono_Time *monotime) +{ + return monotime->time; +} + +bool mono_time_is_timeout(const Mono_Time *monotime, uint64_t timestamp, uint64_t timeout) +{ + return timestamp + timeout <= mono_time_get(monotime); +} + + +static Mono_Time global_time; + +/* XXX: note that this is not thread-safe; if multiple threads call unix_time_update() concurrently, the return value of + * unix_time() may fail to increase monotonically with increasing time */ +void unix_time_update(void) +{ + mono_time_update(&global_time); +} +uint64_t unix_time(void) +{ + return mono_time_get(&global_time); +} +int is_timeout(uint64_t timestamp, uint64_t timeout) +{ + return mono_time_is_timeout(&global_time, timestamp, timeout); +} + + + +/* return current UNIX time in microseconds (us). */ +uint64_t current_time_actual(void) +{ + uint64_t time; +#ifdef OS_WIN32 + /* This probably works fine */ + FILETIME ft; + GetSystemTimeAsFileTime(&ft); + time = ft.dwHighDateTime; + time <<= 32; + time |= ft.dwLowDateTime; + time -= 116444736000000000ULL; + return time / 10; +#else + struct timeval a; + gettimeofday(&a, nullptr); + time = 1000000ULL * a.tv_sec + a.tv_usec; + return time; +#endif +} + + +#ifdef OS_WIN32 +static uint64_t last_monotime; +static uint64_t add_monotime; +#endif + +/* return current monotonic time in milliseconds (ms). */ +uint64_t current_time_monotonic(void) +{ + uint64_t time; +#ifdef OS_WIN32 + uint64_t old_add_monotime = add_monotime; + time = (uint64_t)GetTickCount() + add_monotime; + + /* Check if time has decreased because of 32 bit wrap from GetTickCount(), while avoiding false positives from race + * conditions when multiple threads call this function at once */ + if (time + 0x10000 < last_monotime) { + uint32_t add = ~0; + /* use old_add_monotime rather than simply incrementing add_monotime, to handle the case that many threads + * simultaneously detect an overflow */ + add_monotime = old_add_monotime + add; + time += add; + } + + last_monotime = time; +#else + struct timespec monotime; +#if defined(__linux__) && defined(CLOCK_MONOTONIC_RAW) + clock_gettime(CLOCK_MONOTONIC_RAW, &monotime); +#elif defined(__APPLE__) + clock_serv_t muhclock; + mach_timespec_t machtime; + + host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &muhclock); + clock_get_time(muhclock, &machtime); + mach_port_deallocate(mach_task_self(), muhclock); + + monotime.tv_sec = machtime.tv_sec; + monotime.tv_nsec = machtime.tv_nsec; +#else + clock_gettime(CLOCK_MONOTONIC, &monotime); +#endif + time = 1000ULL * monotime.tv_sec + (monotime.tv_nsec / 1000000ULL); +#endif + return time; +} diff --git a/toxcore/mono_time.h b/toxcore/mono_time.h new file mode 100644 index 00000000..63e0f49d --- /dev/null +++ b/toxcore/mono_time.h @@ -0,0 +1,35 @@ +#ifndef C_TOXCORE_TOXCORE_MONO_TIME_H +#define C_TOXCORE_TOXCORE_MONO_TIME_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct Mono_Time Mono_Time; + +Mono_Time *mono_time_new(void); +void mono_time_free(Mono_Time *monotime); + +void mono_time_update(Mono_Time *monotime); +uint64_t mono_time_get(const Mono_Time *monotime); +bool mono_time_is_timeout(const Mono_Time *monotime, uint64_t timestamp, uint64_t timeout); + +// TODO(#405): Use per-tox monotime, delete these functions. +void unix_time_update(void); +uint64_t unix_time(void); +int is_timeout(uint64_t timestamp, uint64_t timeout); + +/* return current UNIX time in microseconds (us). */ +uint64_t current_time_actual(void); + +/* return current monotonic time in milliseconds (ms). */ +uint64_t current_time_monotonic(void); + +#ifdef __cplusplus +} +#endif + +#endif // C_TOXCORE_TOXCORE_MONO_TIME_H diff --git a/toxcore/mono_time_test.cc b/toxcore/mono_time_test.cc new file mode 100644 index 00000000..5ad91322 --- /dev/null +++ b/toxcore/mono_time_test.cc @@ -0,0 +1,30 @@ +#include "mono_time.h" + +#include + +namespace { + +TEST(Util, UnixTimeIncreasesOverTime) { + unix_time_update(); + uint64_t const start = unix_time(); + + while (start == unix_time()) { + unix_time_update(); + } + + uint64_t const end = unix_time(); + EXPECT_GT(end, start); +} + +TEST(Util, IsTimeout) { + uint64_t const start = unix_time(); + EXPECT_FALSE(is_timeout(start, 1)); + + while (start == unix_time()) { + unix_time_update(); + } + + EXPECT_TRUE(is_timeout(start, 1)); +} + +} // namespace diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index f4c6335b..b9ffaf21 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -33,6 +33,7 @@ #include #include +#include "mono_time.h" #include "util.h" typedef struct Packet_Data { diff --git a/toxcore/network.c b/toxcore/network.c index 2a32a170..24e53c47 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -170,6 +170,7 @@ static int inet_pton(int family, const char *addrString, void *addrbuf) #include #include "logger.h" +#include "mono_time.h" #include "util.h" // Disable MSG_NOSIGNAL on systems not supporting it, e.g. Windows, FreeBSD @@ -418,74 +419,6 @@ int set_socket_dualstack(Socket sock) } -/* return current UNIX time in microseconds (us). */ -static uint64_t current_time_actual(void) -{ - uint64_t time; -#ifdef OS_WIN32 - /* This probably works fine */ - FILETIME ft; - GetSystemTimeAsFileTime(&ft); - time = ft.dwHighDateTime; - time <<= 32; - time |= ft.dwLowDateTime; - time -= 116444736000000000ULL; - return time / 10; -#else - struct timeval a; - gettimeofday(&a, nullptr); - time = 1000000ULL * a.tv_sec + a.tv_usec; - return time; -#endif -} - - -#ifdef OS_WIN32 -static uint64_t last_monotime; -static uint64_t add_monotime; -#endif - -/* return current monotonic time in milliseconds (ms). */ -uint64_t current_time_monotonic(void) -{ - uint64_t time; -#ifdef OS_WIN32 - uint64_t old_add_monotime = add_monotime; - time = (uint64_t)GetTickCount() + add_monotime; - - /* Check if time has decreased because of 32 bit wrap from GetTickCount(), while avoiding false positives from race - * conditions when multiple threads call this function at once */ - if (time + 0x10000 < last_monotime) { - uint32_t add = ~0; - /* use old_add_monotime rather than simply incrementing add_monotime, to handle the case that many threads - * simultaneously detect an overflow */ - add_monotime = old_add_monotime + add; - time += add; - } - - last_monotime = time; -#else - struct timespec monotime; -#if defined(__linux__) && defined(CLOCK_MONOTONIC_RAW) - clock_gettime(CLOCK_MONOTONIC_RAW, &monotime); -#elif defined(__APPLE__) - clock_serv_t muhclock; - mach_timespec_t machtime; - - host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &muhclock); - clock_get_time(muhclock, &machtime); - mach_port_deallocate(mach_task_self(), muhclock); - - monotime.tv_sec = machtime.tv_sec; - monotime.tv_nsec = machtime.tv_nsec; -#else - clock_gettime(CLOCK_MONOTONIC, &monotime); -#endif - time = 1000ULL * monotime.tv_sec + (monotime.tv_nsec / 1000000ULL); -#endif - return time; -} - static uint32_t data_0(uint16_t buflen, const uint8_t *buffer) { return buflen > 4 ? net_ntohl(*(const uint32_t *)&buffer[1]) : 0; diff --git a/toxcore/network.h b/toxcore/network.h index fbd12bb7..8f166c67 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -381,9 +381,6 @@ int set_socket_reuseaddr(Socket sock); */ int set_socket_dualstack(Socket sock); -/* return current monotonic time in milliseconds (ms). */ -uint64_t current_time_monotonic(void); - /* Basic network functions: */ /* Function to send packet(data) of length length to ip_port. */ diff --git a/toxcore/onion.c b/toxcore/onion.c index cfe12a05..5ba716fd 100644 --- a/toxcore/onion.c +++ b/toxcore/onion.c @@ -30,6 +30,7 @@ #include #include +#include "mono_time.h" #include "util.h" #define RETURN_1 ONION_RETURN_1 diff --git a/toxcore/onion_announce.c b/toxcore/onion_announce.c index 8f122fe6..d368face 100644 --- a/toxcore/onion_announce.c +++ b/toxcore/onion_announce.c @@ -31,6 +31,7 @@ #include #include "LAN_discovery.h" +#include "mono_time.h" #include "util.h" #define PING_ID_TIMEOUT ONION_ANNOUNCE_TIMEOUT diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 483d6409..9c59343d 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -32,6 +32,7 @@ #include #include "LAN_discovery.h" +#include "mono_time.h" #include "util.h" /* defines for the array size and diff --git a/toxcore/ping.c b/toxcore/ping.c index 3767805d..1bf096bf 100644 --- a/toxcore/ping.c +++ b/toxcore/ping.c @@ -33,6 +33,7 @@ #include #include "DHT.h" +#include "mono_time.h" #include "network.h" #include "ping_array.h" #include "util.h" diff --git a/toxcore/ping_array.c b/toxcore/ping_array.c index ded3ed3a..142640dd 100644 --- a/toxcore/ping_array.c +++ b/toxcore/ping_array.c @@ -31,6 +31,7 @@ #include #include "crypto_core.h" +#include "mono_time.h" #include "util.h" diff --git a/toxcore/tox.c b/toxcore/tox.c index c121eb2e..4c764aeb 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -518,6 +518,11 @@ static void set_friend_error(int32_t ret, Tox_Err_Friend_Add *error) case FAERR_NOMEM: SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_MALLOC); break; + + default: + /* can't happen */ + assert(!"impossible: unknown friend-add error"); + break; } } @@ -826,7 +831,9 @@ static void set_message_error(int ret, Tox_Err_Friend_Send_Message *error) break; case -5: + default: /* can't happen */ + assert(!"impossible: unknown send-message error"); break; } } diff --git a/toxcore/util.c b/toxcore/util.c index 0bc77c05..5ab092ce 100644 --- a/toxcore/util.c +++ b/toxcore/util.c @@ -34,75 +34,12 @@ #include "util.h" #include "crypto_core.h" /* for CRYPTO_PUBLIC_KEY_SIZE */ -#include "network.h" /* for current_time_monotonic */ #include #include #include -/* don't call into system billions of times for no reason */ -struct Unix_Time { - uint64_t time; - uint64_t base_time; -}; - -Unix_Time *unix_time_new(void) -{ - Unix_Time *unixtime = (Unix_Time *)malloc(sizeof(Unix_Time)); - - if (unixtime == nullptr) { - return nullptr; - } - - unixtime->time = 0; - unixtime->base_time = 0; - - return unixtime; -} - -void unix_time_free(Unix_Time *unixtime) -{ - free(unixtime); -} - -void unix_time_update_r(Unix_Time *unixtime) -{ - if (unixtime->base_time == 0) { - unixtime->base_time = ((uint64_t)time(nullptr) - (current_time_monotonic() / 1000ULL)); - } - - unixtime->time = (current_time_monotonic() / 1000ULL) + unixtime->base_time; -} - -uint64_t unix_time_get(const Unix_Time *unixtime) -{ - return unixtime->time; -} - -int unix_time_is_timeout(const Unix_Time *unixtime, uint64_t timestamp, uint64_t timeout) -{ - return timestamp + timeout <= unix_time_get(unixtime); -} - -static Unix_Time global_time; - -/* XXX: note that this is not thread-safe; if multiple threads call unix_time_update() concurrently, the return value of - * unix_time() may fail to increase monotonically with increasing time */ -void unix_time_update(void) -{ - unix_time_update_r(&global_time); -} -uint64_t unix_time(void) -{ - return unix_time_get(&global_time); -} -int is_timeout(uint64_t timestamp, uint64_t timeout) -{ - return unix_time_is_timeout(&global_time, timestamp, timeout); -} - - /* id functions */ bool id_equal(const uint8_t *dest, const uint8_t *src) { diff --git a/toxcore/util.h b/toxcore/util.h index de493ebe..4c5023cf 100644 --- a/toxcore/util.h +++ b/toxcore/util.h @@ -39,21 +39,6 @@ extern "C" { #define MIN(a,b) (((a)<(b))?(a):(b)) #define PAIR(TYPE1__, TYPE2__) struct { TYPE1__ first; TYPE2__ second; } -typedef struct Unix_Time Unix_Time; - -Unix_Time *unix_time_new(void); -void unix_time_free(Unix_Time *unixtime); - -// TODO(#405): Use per-tox unixtime, remove unix_time_update, and rename -// unix_time_update_r to unix_time_update. -void unix_time_update_r(Unix_Time *unixtime); -uint64_t unix_time_get(const Unix_Time *unixtime); -int unix_time_is_timeout(const Unix_Time *unixtime, uint64_t timestamp, uint64_t timeout); - -void unix_time_update(void); -uint64_t unix_time(void); -int is_timeout(uint64_t timestamp, uint64_t timeout); - /* id functions */ bool id_equal(const uint8_t *dest, const uint8_t *src); uint32_t id_copy(uint8_t *dest, const uint8_t *src); /* return value is CLIENT_ID_SIZE */ diff --git a/toxcore/util_test.cc b/toxcore/util_test.cc index 541aa61f..ff57f3fb 100644 --- a/toxcore/util_test.cc +++ b/toxcore/util_test.cc @@ -4,28 +4,7 @@ #include -TEST(Util, UnixTimeIncreasesOverTime) { - unix_time_update(); - uint64_t const start = unix_time(); - - while (start == unix_time()) { - unix_time_update(); - } - - uint64_t const end = unix_time(); - EXPECT_GT(end, start); -} - -TEST(Util, IsTimeout) { - uint64_t const start = unix_time(); - EXPECT_FALSE(is_timeout(start, 1)); - - while (start == unix_time()) { - unix_time_update(); - } - - EXPECT_TRUE(is_timeout(start, 1)); -} +namespace { TEST(Util, TwoRandomIdsAreNotEqual) { uint8_t pk1[CRYPTO_PUBLIC_KEY_SIZE]; @@ -49,3 +28,5 @@ TEST(Util, IdCopyMakesKeysEqual) { EXPECT_TRUE(id_equal(pk1, pk2)); } + +} // namespace -- cgit v1.2.3