From: Guus Sliepen Date: Sun, 29 Mar 2020 19:52:24 +0000 (+0200) Subject: Update UTCP and replace gettimeofday() with clock_gettime(). X-Git-Url: https://git.meshlink.io/?a=commitdiff_plain;h=4c57e6902219ecca1872e18e34365d8e54a0f407;p=meshlink Update UTCP and replace gettimeofday() with clock_gettime(). --- diff --git a/configure.ac b/configure.ac index 00e47fae..1b0b2e06 100644 --- a/configure.ac +++ b/configure.ac @@ -134,7 +134,7 @@ AC_CHECK_TYPES([struct sockaddr_storage], ,AC_MSG_ERROR([System must support str dnl Checks for library functions. AC_TYPE_SIGNAL -AC_CHECK_FUNCS([asprintf fchmod fork gettimeofday random select setns strdup usleep getifaddrs freeifaddrs], +AC_CHECK_FUNCS([asprintf fchmod fork gettimeofday random pselect select setns strdup usleep getifaddrs freeifaddrs], [], [], [#include "$srcdir/src/have.h"] ) diff --git a/src/conf.c b/src/conf.c index 9527c1ed..7cf923bc 100644 --- a/src/conf.c +++ b/src/conf.c @@ -903,7 +903,7 @@ bool invitation_read(meshlink_handle_t *mesh, const char *conf_subdir, const cha return false; } - if(mesh->loop.now.tv_sec >= st.st_mtime + mesh->invitation_timeout) { + if(time(NULL) >= st.st_mtime + mesh->invitation_timeout) { logger(mesh, MESHLINK_ERROR, "Peer tried to use an outdated invitation file %s\n", name); fclose(f); unlink(used_path); diff --git a/src/discovery.c b/src/discovery.c index da4a1d7d..2a74cc35 100644 --- a/src/discovery.c +++ b/src/discovery.c @@ -257,7 +257,7 @@ static void discovery_resolve_callback(CattaSServiceResolver *resolver, CattaIfI c->outgoing->timeout = 0; if(c->outgoing->ev.cb) { - timeout_set(&mesh->loop, &c->outgoing->ev, &(struct timeval) { + timeout_set(&mesh->loop, &c->outgoing->ev, &(struct timespec) { 0, 0 }); } diff --git a/src/dropin.c b/src/dropin.c index ff3e8c02..552998bc 100644 --- a/src/dropin.c +++ b/src/dropin.c @@ -57,29 +57,3 @@ int vasprintf(char **buf, const char *fmt, va_list ap) { return status; } #endif - -#ifndef HAVE_GETTIMEOFDAY -int gettimeofday(struct timeval *tv, void *tz) { -#ifdef HAVE_MINGW - FILETIME ft; - GetSystemTimeAsFileTime(&ft); - uint64_t lt = (uint64_t)ft.dwLowDateTime | ((uint64_t)ft.dwHighDateTime << 32); - lt -= 116444736000000000ULL; - tv->tv_sec = lt / 10000000; - tv->tv_usec = (lt / 10) % 1000000; -#else -#warning No high resolution time source! - tv->tv_sec = time(NULL); - tv->tv_usec = 0; -#endif - return 0; -} -#endif - -#ifndef HAVE_USLEEP -int usleep(long long usec) { - struct timeval tv = {usec / 1000000, (usec / 1000) % 1000}; - select(0, NULL, NULL, NULL, &tv); - return 0; -} -#endif diff --git a/src/dropin.h b/src/dropin.h index fe2b8589..568a6e52 100644 --- a/src/dropin.h +++ b/src/dropin.h @@ -28,34 +28,6 @@ extern int asprintf(char **, const char *, ...); extern int vasprintf(char **, const char *, va_list ap); #endif -#ifndef HAVE_GETTIMEOFDAY -extern int gettimeofday(struct timeval *, void *); -#endif - -#ifndef HAVE_USLEEP -extern int usleep(long long usec); -#endif - -#ifndef timeradd -#define timeradd(a, b, r)\ - do {\ - (r)->tv_sec = (a)->tv_sec + (b)->tv_sec;\ - (r)->tv_usec = (a)->tv_usec + (b)->tv_usec;\ - if((r)->tv_usec >= 1000000)\ - (r)->tv_sec++, (r)->tv_usec -= 1000000;\ - } while (0) -#endif - -#ifndef timersub -#define timersub(a, b, r)\ - do {\ - (r)->tv_sec = (a)->tv_sec - (b)->tv_sec;\ - (r)->tv_usec = (a)->tv_usec - (b)->tv_usec;\ - if((r)->tv_usec < 0)\ - (r)->tv_sec--, (r)->tv_usec += 1000000;\ - } while (0) -#endif - #ifdef HAVE_MINGW #define mkdir(a, b) mkdir(a) #ifndef SHUT_RDWR diff --git a/src/event.c b/src/event.c index 11f1ed81..739ff35d 100644 --- a/src/event.c +++ b/src/event.c @@ -26,39 +26,68 @@ #include "utils.h" #include "xalloc.h" -static int io_compare(const io_t *a, const io_t *b) { - return a->fd - b->fd; +#ifndef EVENT_CLOCK +#if defined(CLOCK_MONOTONIC_RAW) && defined(__x86_64__) +#define EVENT_CLOCK CLOCK_MONOTONIC_RAW +#else +#define EVENT_CLOCK CLOCK_MONOTONIC +#endif +#endif + +static void timespec_add(const struct timespec *a, const struct timespec *b, struct timespec *r) { + r->tv_sec = a->tv_sec + b->tv_sec; + r->tv_nsec = a->tv_nsec + b->tv_nsec; + + if(r->tv_nsec > 1000000000) { + r->tv_sec++, r->tv_nsec -= 1000000000; + } } -static int timeout_compare(const timeout_t *a, const timeout_t *b) { - struct timeval diff; - timersub(&a->tv, &b->tv, &diff); +static void timespec_sub(const struct timespec *a, const struct timespec *b, struct timespec *r) { + r->tv_sec = a->tv_sec - b->tv_sec; + r->tv_nsec = a->tv_nsec - b->tv_nsec; - if(diff.tv_sec < 0) { - return -1; + if(r->tv_nsec < 0) { + r->tv_sec--, r->tv_nsec += 1000000000; } +} - if(diff.tv_sec > 0) { - return 1; +static bool timespec_lt(const struct timespec *a, const struct timespec *b) { + if(a->tv_sec == b->tv_sec) { + return a->tv_nsec < b->tv_nsec; + } else { + return a->tv_sec < b->tv_sec; } +} - if(diff.tv_usec < 0) { - return -1; - } +static void timespec_clear(struct timespec *a) { + a->tv_sec = 0; +} - if(diff.tv_usec > 0) { - return 1; - } +static bool timespec_isset(const struct timespec *a) { + return a->tv_sec; +} - if(a < b) { - return -1; - } +static int io_compare(const io_t *a, const io_t *b) { + return a->fd - b->fd; +} - if(a > b) { +static int timeout_compare(const timeout_t *a, const timeout_t *b) { + if(a->tv.tv_sec < b->tv.tv_sec) { + return -1; + } else if(a->tv.tv_sec > b->tv.tv_sec) { + return 1; + } else if(a->tv.tv_nsec < b->tv.tv_nsec) { + return -1; + } else if(a->tv.tv_nsec > b->tv.tv_nsec) { return 1; + } else if(a < b) { + return -1; + } else if(a > b) { + return 1; + } else { + return 0; } - - return 0; } void io_add(event_loop_t *loop, io_t *io, io_cb_t cb, void *data, int fd, int flags) { @@ -105,7 +134,7 @@ void io_del(event_loop_t *loop, io_t *io) { io->cb = NULL; } -void timeout_add(event_loop_t *loop, timeout_t *timeout, timeout_cb_t cb, void *data, struct timeval *tv) { +void timeout_add(event_loop_t *loop, timeout_t *timeout, timeout_cb_t cb, void *data, struct timespec *tv) { timeout->cb = cb; timeout->data = data; timeout->node.data = timeout; @@ -113,18 +142,18 @@ void timeout_add(event_loop_t *loop, timeout_t *timeout, timeout_cb_t cb, void * timeout_set(loop, timeout, tv); } -void timeout_set(event_loop_t *loop, timeout_t *timeout, struct timeval *tv) { +void timeout_set(event_loop_t *loop, timeout_t *timeout, struct timespec *tv) { assert(timeout->cb); - if(timerisset(&timeout->tv)) { + if(timespec_isset(&timeout->tv)) { splay_unlink_node(&loop->timeouts, &timeout->node); } if(!loop->now.tv_sec) { - gettimeofday(&loop->now, NULL); + clock_gettime(EVENT_CLOCK, &loop->now); } - timeradd(&loop->now, tv, &timeout->tv); + timespec_add(&loop->now, tv, &timeout->tv); if(!splay_insert_node(&loop->timeouts, &timeout->node)) { abort(); @@ -135,9 +164,7 @@ void timeout_set(event_loop_t *loop, timeout_t *timeout, struct timeval *tv) { static void timeout_disable(event_loop_t *loop, timeout_t *timeout) { splay_unlink_node(&loop->timeouts, &timeout->node); - timeout->tv = (struct timeval) { - 0, 0 - }; + timespec_clear(&timeout->tv); } void timeout_del(event_loop_t *loop, timeout_t *timeout) { @@ -145,7 +172,7 @@ void timeout_del(event_loop_t *loop, timeout_t *timeout) { return; } - if(timerisset(&timeout->tv)) { + if(timespec_isset(&timeout->tv)) { timeout_disable(loop, timeout); } @@ -249,18 +276,17 @@ bool event_loop_run(event_loop_t *loop, pthread_mutex_t *mutex) { fd_set writable; while(loop->running) { - gettimeofday(&loop->now, NULL); - struct timeval diff, it, *tv = NULL; + clock_gettime(EVENT_CLOCK, &loop->now); + struct timespec it, ts = {3600, 0}; while(loop->timeouts.head) { timeout_t *timeout = loop->timeouts.head->data; - timersub(&timeout->tv, &loop->now, &diff); - if(diff.tv_sec < 0) { + if(timespec_lt(&timeout->tv, &loop->now)) { timeout_disable(loop, timeout); timeout->cb(loop, timeout->data); } else { - tv = &diff; + timespec_sub(&timeout->tv, &loop->now, &ts); break; } } @@ -268,8 +294,8 @@ bool event_loop_run(event_loop_t *loop, pthread_mutex_t *mutex) { if(loop->idle_cb) { it = loop->idle_cb(loop, loop->idle_data); - if(it.tv_sec >= 0 && (!tv || timercmp(&it, tv, <))) { - tv = ⁢ + if(it.tv_sec >= 0 && timespec_lt(&it, &ts)) { + ts = it; } } @@ -286,11 +312,16 @@ bool event_loop_run(event_loop_t *loop, pthread_mutex_t *mutex) { // release mesh mutex during select pthread_mutex_unlock(mutex); - int n = select(fds, &readable, &writable, NULL, tv); +#ifdef HAVE_PSELECT + int n = pselect(fds, &readable, &writable, NULL, &ts, NULL); +#else + struct timeval tv = {ts.tv_sec, ts.tv_nsec / 1000}; + int n = select(fds, &readable, &writable, NULL, (struct timeval *)&tv); +#endif pthread_mutex_lock(mutex); - gettimeofday(&loop->now, NULL); + clock_gettime(EVENT_CLOCK, &loop->now); if(n < 0) { if(sockwouldblock(errno)) { @@ -353,7 +384,7 @@ void event_loop_init(event_loop_t *loop) { loop->signals.compare = (splay_compare_t)signal_compare; loop->pipefd[0] = -1; loop->pipefd[1] = -1; - gettimeofday(&loop->now, NULL); + clock_gettime(EVENT_CLOCK, &loop->now); } void event_loop_exit(event_loop_t *loop) { diff --git a/src/event.h b/src/event.h index f2ebf498..31c326be 100644 --- a/src/event.h +++ b/src/event.h @@ -32,7 +32,7 @@ typedef struct event_loop_t event_loop_t; typedef void (*io_cb_t)(event_loop_t *loop, void *data, int flags); typedef void (*timeout_cb_t)(event_loop_t *loop, void *data); typedef void (*signal_cb_t)(event_loop_t *loop, void *data); -typedef struct timeval(*idle_cb_t)(event_loop_t *loop, void *data); +typedef struct timespec(*idle_cb_t)(event_loop_t *loop, void *data); typedef struct io_t { struct splay_node_t node; @@ -44,7 +44,7 @@ typedef struct io_t { typedef struct timeout_t { struct splay_node_t node; - struct timeval tv; + struct timespec tv; timeout_cb_t cb; void *data; } timeout_t; @@ -63,7 +63,7 @@ struct event_loop_t { volatile bool running; bool deletion; - struct timeval now; + struct timespec now; splay_tree_t timeouts; idle_cb_t idle_cb; @@ -82,9 +82,9 @@ extern void io_add(event_loop_t *loop, io_t *io, io_cb_t cb, void *data, int fd, extern void io_del(event_loop_t *loop, io_t *io); extern void io_set(event_loop_t *loop, io_t *io, int flags); -extern void timeout_add(event_loop_t *loop, timeout_t *timeout, timeout_cb_t cb, void *data, struct timeval *tv); +extern void timeout_add(event_loop_t *loop, timeout_t *timeout, timeout_cb_t cb, void *data, struct timespec *tv); extern void timeout_del(event_loop_t *loop, timeout_t *timeout); -extern void timeout_set(event_loop_t *loop, timeout_t *timeout, struct timeval *tv); +extern void timeout_set(event_loop_t *loop, timeout_t *timeout, struct timespec *tv); extern void signal_add(event_loop_t *loop, signal_t *sig, signal_cb_t cb, void *data, uint8_t signum); extern void signal_trigger(event_loop_t *loop, signal_t *sig); diff --git a/src/graph.c b/src/graph.c index 431a72a5..b0e0b77a 100644 --- a/src/graph.c +++ b/src/graph.c @@ -177,7 +177,7 @@ static void check_reachability(meshlink_handle_t *mesh) { if(n->status.reachable) { logger(mesh, MESHLINK_DEBUG, "Node %s became reachable", n->name); bool first_time_reachable = !n->last_reachable; - n->last_reachable = mesh->loop.now.tv_sec; + n->last_reachable = time(NULL); if(first_time_reachable) { if(!node_write_config(mesh, n)) { @@ -187,7 +187,7 @@ static void check_reachability(meshlink_handle_t *mesh) { } } else { logger(mesh, MESHLINK_DEBUG, "Node %s became unreachable", n->name); - n->last_unreachable = mesh->loop.now.tv_sec; + n->last_unreachable = time(NULL); } } @@ -229,7 +229,7 @@ static void check_reachability(meshlink_handle_t *mesh) { mesh->last_unreachable = mesh->loop.now.tv_sec; if(mesh->threadstarted) { - timeout_set(&mesh->loop, &mesh->periodictimer, &(struct timeval) { + timeout_set(&mesh->loop, &mesh->periodictimer, &(struct timespec) { 0, prng(mesh, TIMER_FUDGE) }); } diff --git a/src/meshlink.c b/src/meshlink.c index fccfecbc..747bd3b5 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -995,10 +995,18 @@ static bool ecdsa_keygen(meshlink_handle_t *mesh) { return true; } -static struct timeval idle(event_loop_t *loop, void *data) { +static bool timespec_lt(const struct timespec *a, const struct timespec *b) { + if(a->tv_sec == b->tv_sec) { + return a->tv_nsec < b->tv_nsec; + } else { + return a->tv_sec < b->tv_sec; + } +} + +static struct timespec idle(event_loop_t *loop, void *data) { (void)loop; meshlink_handle_t *mesh = data; - struct timeval t, tmin = {3600, 0}; + struct timespec t, tmin = {3600, 0}; for splay_each(node_t, n, mesh->nodes) { if(!n->utcp) { @@ -1007,7 +1015,7 @@ static struct timeval idle(event_loop_t *loop, void *data) { t = utcp_timeout(n->utcp); - if(timercmp(&t, &tmin, <)) { + if(timespec_lt(&t, &tmin)) { tmin = t; } } @@ -3234,7 +3242,7 @@ static bool blacklist(meshlink_handle_t *mesh, node_t *n) { n->status.udp_confirmed = false; if(n->status.reachable) { - n->last_unreachable = mesh->loop.now.tv_sec; + n->last_unreachable = time(NULL); } /* Graph updates will suppress status updates for blacklisted nodes, so we need to @@ -3308,7 +3316,7 @@ static bool whitelist(meshlink_handle_t *mesh, node_t *n) { n->status.blacklisted = false; if(n->status.reachable) { - n->last_reachable = mesh->loop.now.tv_sec; + n->last_reachable = time(NULL); update_node_status(mesh, n); } diff --git a/src/meshlink_internal.h b/src/meshlink_internal.h index eaa89c5d..f0ffed8e 100644 --- a/src/meshlink_internal.h +++ b/src/meshlink_internal.h @@ -127,7 +127,6 @@ struct meshlink_handle { int contradicting_del_edge; int sleeptime; time_t connection_burst_time; - time_t last_config_check; time_t last_hard_try; time_t last_unreachable; timeout_t pingtimer; @@ -260,6 +259,6 @@ static inline int prng(meshlink_handle_t *mesh, uint64_t max) { } /// Fudge value of ~0.1 seconds, in microseconds. -static const unsigned int TIMER_FUDGE = 0x20000; +static const unsigned int TIMER_FUDGE = 0x8000000; #endif diff --git a/src/net.c b/src/net.c index 304c6268..3c1ad3e6 100644 --- a/src/net.c +++ b/src/net.c @@ -151,7 +151,7 @@ static void timeout_handler(event_loop_t *loop, void *data) { } } - timeout_set(&mesh->loop, data, &(struct timeval) { + timeout_set(&mesh->loop, data, &(struct timespec) { 1, prng(mesh, TIMER_FUDGE) }); } @@ -346,7 +346,8 @@ static void periodic_handler(event_loop_t *loop, void *data) { if(mesh->contradicting_del_edge > 100 && mesh->contradicting_add_edge > 100) { logger(mesh, MESHLINK_WARNING, "Possible node with same Name as us! Sleeping %d seconds.", mesh->sleeptime); - usleep(mesh->sleeptime * 1000000LL); + struct timespec ts = {mesh->sleeptime, 0}; + clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL); mesh->sleeptime *= 2; if(mesh->sleeptime < 0) { @@ -616,7 +617,7 @@ static void periodic_handler(event_loop_t *loop, void *data) { } } - timeout_set(&mesh->loop, data, &(struct timeval) { + timeout_set(&mesh->loop, data, &(struct timespec) { timeout, prng(mesh, TIMER_FUDGE) }); } @@ -633,10 +634,11 @@ void retry(meshlink_handle_t *mesh) { for list_each(outgoing_t, outgoing, mesh->outgoings) { outgoing->timeout = 0; - if(outgoing->ev.cb) - timeout_set(&mesh->loop, &outgoing->ev, &(struct timeval) { - 0, 0 - }); + if(outgoing->ev.cb) { + timeout_set(&mesh->loop, &outgoing->ev, &(struct timespec) { + 0, 0 + }); + } } /* For active connections, check if their addresses are still valid. @@ -685,7 +687,7 @@ void retry(meshlink_handle_t *mesh) { } /* Kick the ping timeout handler */ - timeout_set(&mesh->loop, &mesh->pingtimer, &(struct timeval) { + timeout_set(&mesh->loop, &mesh->pingtimer, &(struct timespec) { 0, 0 }); } @@ -694,10 +696,10 @@ void retry(meshlink_handle_t *mesh) { this is where it all happens... */ void main_loop(meshlink_handle_t *mesh) { - timeout_add(&mesh->loop, &mesh->pingtimer, timeout_handler, &mesh->pingtimer, &(struct timeval) { + timeout_add(&mesh->loop, &mesh->pingtimer, timeout_handler, &mesh->pingtimer, &(struct timespec) { 1, prng(mesh, TIMER_FUDGE) }); - timeout_add(&mesh->loop, &mesh->periodictimer, periodic_handler, &mesh->periodictimer, &(struct timeval) { + timeout_add(&mesh->loop, &mesh->periodictimer, periodic_handler, &mesh->periodictimer, &(struct timespec) { 0, 0 }); diff --git a/src/net_packet.c b/src/net_packet.c index 2d3d7c77..7dae0fe0 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -148,13 +148,13 @@ static void send_mtu_probe_handler(event_loop_t *loop, void *data) { n->status.broadcast = false; end: - timeout_set(&mesh->loop, &n->mtutimeout, &(struct timeval) { + timeout_set(&mesh->loop, &n->mtutimeout, &(struct timespec) { timeout, prng(mesh, TIMER_FUDGE) }); } void send_mtu_probe(meshlink_handle_t *mesh, node_t *n) { - timeout_add(&mesh->loop, &n->mtutimeout, send_mtu_probe_handler, n, &(struct timeval) { + timeout_add(&mesh->loop, &n->mtutimeout, send_mtu_probe_handler, n, &(struct timespec) { 1, 0 }); send_mtu_probe_handler(&mesh->loop, n); diff --git a/src/net_setup.c b/src/net_setup.c index 238ae2d3..9cbdeb26 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -565,7 +565,6 @@ bool setup_myself(meshlink_handle_t *mesh) { /* Done. */ - mesh->last_config_check = mesh->loop.now.tv_sec; mesh->last_unreachable = mesh->loop.now.tv_sec; return true; diff --git a/src/net_socket.c b/src/net_socket.c index fcadd90c..63bf49ea 100644 --- a/src/net_socket.c +++ b/src/net_socket.c @@ -91,7 +91,7 @@ void retry_outgoing(meshlink_handle_t *mesh, outgoing_t *outgoing) { outgoing->timeout = mesh->maxtimeout; } - timeout_add(&mesh->loop, &outgoing->ev, retry_outgoing_handler, outgoing, &(struct timeval) { + timeout_add(&mesh->loop, &outgoing->ev, retry_outgoing_handler, outgoing, &(struct timespec) { outgoing->timeout, prng(mesh, TIMER_FUDGE) }); diff --git a/src/protocol.c b/src/protocol.c index b4cb5ad5..482808a7 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -207,7 +207,7 @@ static void age_past_requests(event_loop_t *loop, void *data) { } if(left) { - timeout_set(&mesh->loop, &mesh->past_request_timeout, &(struct timeval) { + timeout_set(&mesh->loop, &mesh->past_request_timeout, &(struct timespec) { 10, prng(mesh, TIMER_FUDGE) }); } @@ -228,7 +228,7 @@ bool seen_request(meshlink_handle_t *mesh, const char *request) { new->firstseen = mesh->loop.now.tv_sec; if(!mesh->past_request_tree->head) { - timeout_set(&mesh->loop, &mesh->past_request_timeout, &(struct timeval) { + timeout_set(&mesh->loop, &mesh->past_request_timeout, &(struct timespec) { 10, prng(mesh, TIMER_FUDGE) }); } @@ -242,7 +242,7 @@ void init_requests(meshlink_handle_t *mesh) { assert(!mesh->past_request_tree); mesh->past_request_tree = splay_alloc_tree((splay_compare_t) past_request_compare, (splay_action_t) free_past_request); - timeout_add(&mesh->loop, &mesh->past_request_timeout, age_past_requests, NULL, &(struct timeval) { + timeout_add(&mesh->loop, &mesh->past_request_timeout, age_past_requests, NULL, &(struct timespec) { 0, 0 }); } diff --git a/src/protocol_key.c b/src/protocol_key.c index 480019e7..b614494b 100644 --- a/src/protocol_key.c +++ b/src/protocol_key.c @@ -135,7 +135,7 @@ static bool req_key_ext_h(meshlink_handle_t *mesh, connection_t *c, const char * for list_each(outgoing_t, outgoing, mesh->outgoings) { if(outgoing->node == from && outgoing->ev.cb) { outgoing->timeout = 0; - timeout_set(&mesh->loop, &outgoing->ev, &(struct timeval) { + timeout_set(&mesh->loop, &outgoing->ev, &(struct timespec) { 0, 0 }); } diff --git a/src/utcp b/src/utcp index 96b97ab1..0c3abf9e 160000 --- a/src/utcp +++ b/src/utcp @@ -1 +1 @@ -Subproject commit 96b97ab1291e339a36952532db8ce72e7efc45a1 +Subproject commit 0c3abf9e3538c482639ed32b0e85104495db5b4f