From: Guus Sliepen Date: Thu, 29 Nov 2012 11:28:23 +0000 (+0100) Subject: Drop libevent and use our own event handling again. X-Git-Tag: release-1.1pre4~14 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=6bc5d626a8726fc23365ee705761a3c666a08ad4;p=oweals%2Ftinc.git Drop libevent and use our own event handling again. There are several reasons for this: - MacOS/X doesn't support polling the tap device using kqueue, requiring a workaround to fall back to select(). - On Windows only sockets are properly handled, therefore tinc uses a second thread that does a blocking ReadFile() on the TAP-Win32/64 device. However, this does not mix well with libevent. - Libevent, event just the core, is quite large, and although it is easy to get and install on many platforms, it can be a burden. - Libev is more lightweight and seems technically superior, but it doesn't abstract away all the platform differences (for example, async events are not supported on Windows). --- diff --git a/README b/README index 10cb0b5..1566af9 100644 --- a/README +++ b/README @@ -50,7 +50,6 @@ In order to compile tinc, you will need a GNU C compiler environment. Please ensure you have the latest stable versions of all the required libraries: - OpenSSL (http://www.openssl.org/) version 1.0.0 or later. -- Libevent (http://monkey.org/~provos/libevent/) The following libraries are used by default, but can be disabled if necessary: diff --git a/README.git b/README.git index 77595d6..92aa113 100644 --- a/README.git +++ b/README.git @@ -8,7 +8,6 @@ to install the very latest versions of the following packages: - automake - autoconf - gettext -- libevent Then you have to let the autotools create all the autogenerated files, using this command: diff --git a/configure.in b/configure.in index c8a5341..1f0945f 100644 --- a/configure.in +++ b/configure.in @@ -183,7 +183,6 @@ AC_ARG_WITH(libgcrypt, AC_HELP_STRING([--with-libgcrypt], [enable use of libgcry tinc_CURSES tinc_READLINE -tinc_LIBEVENT tinc_ZLIB tinc_LZO diff --git a/doc/tinc.texi b/doc/tinc.texi index 452f9f5..c0115f4 100644 --- a/doc/tinc.texi +++ b/doc/tinc.texi @@ -339,7 +339,6 @@ having them installed, configure will give you an error message, and stop. * OpenSSL:: * zlib:: * lzo:: -* libevent:: * libcurses:: * libreadline:: @end menu @@ -458,27 +457,6 @@ make sure you build development and runtime libraries (which is the default). -@c ================================================================== -@node libevent -@subsection libevent - -@cindex libevent -For the main event loop, tinc uses the libevent library. - -If this library is not installed, you wil get an error when configuring -tinc for build. - -You can use your operating system's package manager to install this if -available. Make sure you install the development AND runtime versions -of this package. - -If you have to install libevent manually, you can get the source code -from @url{http://libevent.org/}. Instructions on how to configure, -build and install this package are included within the package. Please -make sure you build development and runtime libraries (which is the -default). - - @c ================================================================== @node libcurses @subsection libcurses diff --git a/have.h b/have.h index d040717..6d65bcd 100644 --- a/have.h +++ b/have.h @@ -196,10 +196,6 @@ #include #endif -#ifdef HAVE_EVENT_H -#include -#endif - #ifdef HAVE_MINGW #define SLASH "\\" #else diff --git a/m4/libevent.m4 b/m4/libevent.m4 deleted file mode 100644 index 34bdef7..0000000 --- a/m4/libevent.m4 +++ /dev/null @@ -1,33 +0,0 @@ -dnl Check to find the libevent headers/libraries - -AC_DEFUN([tinc_LIBEVENT], -[ - AC_ARG_WITH(libevent, - AS_HELP_STRING([--with-libevent=DIR], [libevent base directory, or:]), - [libevent="$withval" - CPPFLAGS="$CPPFLAGS -I$withval/include" - LDFLAGS="$LDFLAGS -L$withval/lib"] - ) - - AC_ARG_WITH(libevent-include, - AS_HELP_STRING([--with-libevent-include=DIR], [libevent headers directory]), - [libevent_include="$withval" - CPPFLAGS="$CPPFLAGS -I$withval"] - ) - - AC_ARG_WITH(libevent-lib, - AS_HELP_STRING([--with-libevent-lib=DIR], [libevent library directory]), - [libevent_lib="$withval" - LDFLAGS="$LDFLAGS -L$withval"] - ) - - AC_CHECK_HEADERS(event.h, - [], - [AC_MSG_ERROR("libevent header files not found."); break] - ) - - AC_CHECK_LIB(event, event_init, - [LIBS="-levent $LIBS"], - [AC_MSG_ERROR("libevent libraries not found.")] - ) -]) diff --git a/src/Makefile.am b/src/Makefile.am index 3bd8646..6a8737b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,7 +8,7 @@ tincd_SOURCES = \ utils.c getopt.c getopt1.c list.c splay_tree.c dropin.c fake-getaddrinfo.c fake-getnameinfo.c hash.c \ buffer.c conf.c connection.c control.c edge.c graph.c logger.c meta.c net.c net_packet.c net_setup.c \ net_socket.c netutl.c node.c process.c protocol.c protocol_auth.c protocol_edge.c protocol_misc.c \ - protocol_key.c protocol_subnet.c route.c sptps.c subnet.c subnet_parse.c tincd.c \ + protocol_key.c protocol_subnet.c route.c sptps.c subnet.c subnet_parse.c event.c tincd.c \ dummy_device.c raw_socket_device.c multicast_device.c if UML @@ -46,7 +46,7 @@ INCLUDES = @INCLUDES@ -I$(top_builddir) noinst_HEADERS = \ xalloc.h utils.h getopt.h list.h splay_tree.h dropin.h fake-getaddrinfo.h fake-getnameinfo.h fake-gai-errnos.h ipv6.h ipv4.h ethernet.h \ buffer.h conf.h connection.h control.h control_common.h device.h edge.h graph.h info.h logger.h meta.h net.h netutl.h node.h process.h \ - protocol.h route.h subnet.h sptps.h tincctl.h top.h bsd/tunemu.h hash.h + protocol.h route.h subnet.h sptps.h tincctl.h top.h bsd/tunemu.h hash.h event.h nodist_noinst_HEADERS = \ cipher.h crypto.h ecdh.h ecdsa.h digest.h prf.h rsa.h ecdsagen.h rsagen.h diff --git a/src/connection.c b/src/connection.c index d39f43f..4798c5a 100644 --- a/src/connection.c +++ b/src/connection.c @@ -68,11 +68,7 @@ void free_connection(connection_t *c) { buffer_clear(&c->inbuf); buffer_clear(&c->outbuf); - if(event_initialized(&c->inevent)) - event_del(&c->inevent); - - if(event_initialized(&c->outevent)) - event_del(&c->outevent); + io_del(&c->io); if(c->socket > 0) closesocket(c->socket); diff --git a/src/connection.h b/src/connection.h index 01c2bf4..10f4a76 100644 --- a/src/connection.h +++ b/src/connection.h @@ -90,8 +90,7 @@ typedef struct connection_t { struct buffer_t inbuf; struct buffer_t outbuf; - struct event inevent; /* input event on this metadata connection */ - struct event outevent; /* output event on this metadata connection */ + io_t io; /* input/output event on this metadata connection */ int tcplen; /* length of incoming TCPpacket */ int allow_request; /* defined if there's only one request possible */ diff --git a/src/control.c b/src/control.c index c166943..83a9d79 100644 --- a/src/control.c +++ b/src/control.c @@ -58,7 +58,7 @@ bool control_h(connection_t *c, const char *request) { switch (type) { case REQ_STOP: - event_loopexit(NULL); + event_exit(); return control_ok(c, REQ_STOP); case REQ_DUMP_NODES: @@ -156,7 +156,7 @@ bool init_control(void) { // Make sure we have a valid address, and map 0.0.0.0 and :: to 127.0.0.1 and ::1. - if(getsockname(listen_socket[0].tcp, (struct sockaddr *)&sa, &len)) { + if(getsockname(listen_socket[0].tcp.fd, (struct sockaddr *)&sa, &len)) { xasprintf(&localhost, "127.0.0.1 port %d", myport); } else { if(sa.sa.sa_family == AF_INET) { diff --git a/src/event.c b/src/event.c new file mode 100644 index 0000000..6827dc0 --- /dev/null +++ b/src/event.c @@ -0,0 +1,236 @@ +/* + event.c -- I/O, timeout and signal event handling + Copyright (C) 2012 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "system.h" + +#include "event.h" +#include "net.h" +#include "utils.h" + +struct timeval now; + +static fd_set readfds; +static fd_set writefds; +static volatile bool running; + +static int io_compare(const io_t *a, const io_t *b) { + return a->fd - b->fd; +} + +static int timeout_compare(const timeout_t *a, const timeout_t *b) { + struct timeval diff; + timersub(&a->tv, &b->tv, &diff); + return diff.tv_sec ?: diff.tv_usec; +} + +static int signal_compare(const signal_t *a, const signal_t *b) { + return a->signum - b->signum; +} + +static splay_tree_t io_tree = {.compare = (splay_compare_t)io_compare}; +static splay_tree_t timeout_tree = {.compare = (splay_compare_t)timeout_compare}; +static splay_tree_t signal_tree = {.compare = (splay_compare_t)signal_compare}; + +void io_add(io_t *io, io_cb_t cb, void *data, int fd, int flags) { + if(io->cb) + return; + + io->fd = fd; + io->cb = cb; + io->data = data; + io->node.data = io; + + io_set(io, flags); + + splay_insert_node(&io_tree, &io->node); +} + +void io_set(io_t *io, int flags) { + io->flags = flags; + + if(flags & IO_READ) + FD_SET(io->fd, &readfds); + else + FD_CLR(io->fd, &readfds); + + if(flags & IO_WRITE) + FD_SET(io->fd, &writefds); + else + FD_CLR(io->fd, &writefds); +} + +void io_del(io_t *io) { + if(!io->cb) + return; + + io_set(io, 0); + + splay_unlink_node(&io_tree, &io->node); + io->cb = NULL; +} + +void timeout_add(timeout_t *timeout, timeout_cb_t cb, void *data, struct timeval *tv) { + if(timeout->cb) + return; + + timeout->cb = cb; + timeout->data = data; + timeout->node.data = timeout; + + timeout_set(timeout, tv); +} + +void timeout_set(timeout_t *timeout, struct timeval *tv) { + if(timeout->tv.tv_sec) + splay_unlink_node(&timeout_tree, &timeout->node); + + if(!now.tv_sec) + gettimeofday(&now, NULL); + + timeradd(&now, tv, &timeout->tv); + + splay_insert_node(&timeout_tree, &timeout->node); +} + +void timeout_del(timeout_t *timeout) { + if(!timeout->cb) + return; + + splay_unlink_node(&timeout_tree, &timeout->node); + timeout->cb = NULL; +} + +#ifndef HAVE_MINGW +static io_t signalio; +static int pipefd[2] = {-1, -1}; + +static void signal_handler(int signum) { + unsigned char num = signum; + write(pipefd[1], &num, 1); +} + +static void signalio_handler(void *data, int flags) { + unsigned char signum; + if(read(pipefd[0], &signum, 1) != 1) + return; + + signal_t *sig = splay_search(&signal_tree, &((signal_t){.signum = signum})); + if(sig) + sig->cb(sig->data); +} + +static void pipe_init(void) { + if(!pipe(pipefd)) + io_add(&signalio, signalio_handler, NULL, pipefd[0], IO_READ); +} + +void signal_add(signal_t *sig, signal_cb_t cb, void *data, int signum) { + if(sig->cb) + return; + + sig->cb = cb; + sig->data = data; + sig->signum = signum; + sig->node.data = sig; + + if(pipefd[0] == -1) + pipe_init(); + + signal(sig->signum, signal_handler); + + splay_insert_node(&signal_tree, &sig->node); +} + +void signal_del(signal_t *sig) { + if(!sig->cb) + return; + + signal(sig->signum, SIG_DFL); + + splay_unlink_node(&signal_tree, &sig->node); + sig->cb = NULL; +} +#endif + +bool event_loop(void) { + running = true; + + fd_set readable; + fd_set writable; + + while(running) { + gettimeofday(&now, NULL); + struct timeval diff, *tv = NULL; + + while(timeout_tree.head) { + timeout_t *timeout = timeout_tree.head->data; + timersub(&timeout->tv, &now, &diff); + + if(diff.tv_sec <= 0) { + timeout->cb(timeout->data); + if(timercmp(&timeout->tv, &now, <)) + timeout_del(timeout); + } else { + tv = &diff; + break; + } + } + + memcpy(&readable, &readfds, sizeof readable); + memcpy(&writable, &writefds, sizeof writable); + + int fds = 0; + + if(io_tree.tail) { + io_t *last = io_tree.tail->data; + fds = last->fd + 1; + } + +#ifdef HAVE_MINGW + LeaveCriticalSection(&mutex); +#endif + int n = select(fds, &readable, &writable, NULL, tv); +#ifdef HAVE_MINGW + EnterCriticalSection(&mutex); +#endif + + if(n < 0) { + if(sockwouldblock(errno)) + continue; + else + return false; + } + + if(!n) + continue; + + for splay_each(io_t, io, &io_tree) { + if(FD_ISSET(io->fd, &writable)) + io->cb(io->data, IO_WRITE); + else if(FD_ISSET(io->fd, &readable)) + io->cb(io->data, IO_READ); + } + } + + return true; +} + +void event_exit(void) { + running = false; +} diff --git a/src/event.h b/src/event.h new file mode 100644 index 0000000..d0129d0 --- /dev/null +++ b/src/event.h @@ -0,0 +1,70 @@ +/* + event.h -- I/O, timeout and signal event handling + Copyright (C) 2012 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef __TINC_EVENT_H__ +#define __TINC_EVENT_H__ + +#include "splay_tree.h" + +#define IO_READ 1 +#define IO_WRITE 2 + +typedef void (*io_cb_t)(void *data, int flags); +typedef void (*timeout_cb_t)(void *data); +typedef void (*signal_cb_t)(void *data); + +typedef struct io_t { + int fd; + int flags; + io_cb_t cb; + void *data; + splay_node_t node; +} io_t; + +typedef struct timeout_t { + struct timeval tv; + timeout_cb_t cb; + void *data; + splay_node_t node; +} timeout_t; + +typedef struct signal_t { + int signum; + signal_cb_t cb; + void *data; + splay_node_t node; +} signal_t; + +extern struct timeval now; + +extern void io_add(io_t *io, io_cb_t cb, void *data, int fd, int flags); +extern void io_del(io_t *io); +extern void io_set(io_t *io, int flags); + +extern void timeout_add(timeout_t *timeout, timeout_cb_t cb, void *data, struct timeval *tv); +extern void timeout_del(timeout_t *timeout); +extern void timeout_set(timeout_t *timeout, struct timeval *tv); + +extern void signal_add(signal_t *sig, signal_cb_t cb, void *data, int signum); +extern void signal_del(signal_t *sig); + +extern bool event_loop(void); +extern void event_exit(void); + +#endif diff --git a/src/graph.c b/src/graph.c index 9036c52..73db3b2 100644 --- a/src/graph.c +++ b/src/graph.c @@ -213,8 +213,7 @@ static void check_reachability(void) { n->minmtu = 0; n->mtuprobes = 0; - if(timeout_initialized(&n->mtuevent)) - event_del(&n->mtuevent); + timeout_del(&n->mtutimeout); char *name; char *address; diff --git a/src/logger.c b/src/logger.c index 4527a37..6e3d2c0 100644 --- a/src/logger.c +++ b/src/logger.c @@ -41,7 +41,6 @@ bool logcontrol = false; static void real_logger(int level, int priority, const char *message) { char timestr[32] = ""; - time_t now; static bool suppress = false; // Bail out early if there is nothing to do. @@ -58,8 +57,9 @@ static void real_logger(int level, int priority, const char *message) { fflush(stderr); break; case LOGMODE_FILE: - now = time(NULL); - strftime(timestr, sizeof timestr, "%Y-%m-%d %H:%M:%S", localtime(&now)); + if(!now.tv_sec) + gettimeofday(&now, NULL); + strftime(timestr, sizeof timestr, "%Y-%m-%d %H:%M:%S", localtime(&now.tv_sec)); fprintf(logfile, "%s %s[%ld]: %s\n", timestr, logident, (long)logpid, message); fflush(logfile); break; diff --git a/src/meta.c b/src/meta.c index 84fb196..1244bfd 100644 --- a/src/meta.c +++ b/src/meta.c @@ -39,7 +39,7 @@ bool send_meta_sptps(void *handle, uint8_t type, const char *buffer, size_t leng } buffer_add(&c->outbuf, buffer, length); - event_add(&c->outevent, NULL); + io_set(&c->io, IO_READ | IO_WRITE); return true; } @@ -65,12 +65,11 @@ bool send_meta(connection_t *c, const char *buffer, int length) { c->name, c->hostname); return false; } - } else { buffer_add(&c->outbuf, buffer, length); } - event_add(&c->outevent, NULL); + io_set(&c->io, IO_READ | IO_WRITE); return true; } diff --git a/src/net.c b/src/net.c index 77ff1c8..fe272db 100644 --- a/src/net.c +++ b/src/net.c @@ -137,18 +137,16 @@ void terminate_connection(connection_t *c, bool report) { end does not reply in time, we consider them dead and close the connection. */ -static void timeout_handler(int fd, short events, void *event) { - time_t now = time(NULL); - +static void timeout_handler(void *data) { for list_each(connection_t, c, connection_list) { if(c->status.control) continue; - if(c->last_ping_time + pingtimeout <= now) { + if(c->last_ping_time + pingtimeout <= now.tv_sec) { if(c->status.active) { if(c->status.pinged) { - logger(DEBUG_CONNECTIONS, LOG_INFO, "%s (%s) didn't respond to PING in %ld seconds", c->name, c->hostname, (long)now - c->last_ping_time); - } else if(c->last_ping_time + pinginterval <= now) { + logger(DEBUG_CONNECTIONS, LOG_INFO, "%s (%s) didn't respond to PING in %ld seconds", c->name, c->hostname, (long)now.tv_sec - c->last_ping_time); + } else if(c->last_ping_time + pinginterval <= now.tv_sec) { send_ping(c); continue; } else { @@ -164,10 +162,10 @@ static void timeout_handler(int fd, short events, void *event) { } } - event_add(event, &(struct timeval){pingtimeout, rand() % 100000}); + timeout_set(data, &(struct timeval){pingtimeout, rand() % 100000}); } -static void periodic_handler(int fd, short events, void *event) { +static void periodic_handler(void *data) { /* Check if there are too many contradicting ADD_EDGE and DEL_EDGE messages. This usually only happens when another node has the same Name as this node. If so, sleep for a short while to prevent a storm of contradicting messages. @@ -278,11 +276,10 @@ static void periodic_handler(int fd, short events, void *event) { } } - event_add(event, &(struct timeval){5, rand() % 100000}); + timeout_set(data, &(struct timeval){5, rand() % 100000}); } -void handle_meta_connection_data(int fd, short events, void *data) { - connection_t *c = data; +void handle_meta_connection_data(connection_t *c) { int result; socklen_t len = sizeof result; @@ -306,19 +303,19 @@ void handle_meta_connection_data(int fd, short events, void *data) { } } -static void sigterm_handler(int signal, short events, void *data) { - logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(signal)); - event_loopexit(NULL); +static void sigterm_handler(void *data) { + logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(((signal_t *)data)->signum)); + event_exit(); } -static void sighup_handler(int signal, short events, void *data) { - logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(signal)); +static void sighup_handler(void *data) { + logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(((signal_t *)data)->signum)); reopenlogger(); reload_configuration(); } -static void sigalrm_handler(int signal, short events, void *data) { - logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(signal)); +static void sigalrm_handler(void *data) { + logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(((signal_t *)data)->signum)); retry(); } @@ -332,7 +329,7 @@ int reload_configuration(void) { if(!read_server_config()) { logger(DEBUG_ALWAYS, LOG_ERR, "Unable to reread configuration file, exitting."); - event_loopexit(NULL); + event_exit(); return EINVAL; } @@ -431,8 +428,7 @@ int reload_configuration(void) { void retry(void) { for list_each(connection_t, c, connection_list) { if(c->outgoing && !c->node) { - if(timeout_initialized(&c->outgoing->ev)) - event_del(&c->outgoing->ev); + timeout_del(&c->outgoing->ev); if(c->status.connecting) close(c->socket); c->outgoing->timeout = 0; @@ -445,44 +441,38 @@ void retry(void) { this is where it all happens... */ int main_loop(void) { - struct event timeout_event; - struct event periodic_event; - - timeout_set(&timeout_event, timeout_handler, &timeout_event); - event_add(&timeout_event, &(struct timeval){pingtimeout, rand() % 100000}); + timeout_t pingtimer = {{0}}; + timeout_t periodictimer = {{0}}; - timeout_set(&periodic_event, periodic_handler, &periodic_event); - event_add(&periodic_event, &(struct timeval){5, rand() % 100000}); + timeout_add(&pingtimer, timeout_handler, &pingtimer, &(struct timeval){pingtimeout, rand() % 100000}); + timeout_add(&periodictimer, periodic_handler, &periodictimer, &(struct timeval){pingtimeout, rand() % 100000}); #ifndef HAVE_MINGW - struct event sighup_event; - struct event sigterm_event; - struct event sigquit_event; - struct event sigalrm_event; - - signal_set(&sighup_event, SIGHUP, sighup_handler, NULL); - signal_add(&sighup_event, NULL); - signal_set(&sigterm_event, SIGTERM, sigterm_handler, NULL); - signal_add(&sigterm_event, NULL); - signal_set(&sigquit_event, SIGQUIT, sigterm_handler, NULL); - signal_add(&sigquit_event, NULL); - signal_set(&sigalrm_event, SIGALRM, sigalrm_handler, NULL); - signal_add(&sigalrm_event, NULL); + signal_t sighup = {0}; + signal_t sigterm = {0}; + signal_t sigquit = {0}; + signal_t sigalrm = {0}; + + signal_add(&sighup, sighup_handler, &sighup, SIGHUP); + signal_add(&sigterm, sigterm_handler, &sigterm, SIGTERM); + signal_add(&sigquit, sigterm_handler, &sigquit, SIGQUIT); + signal_add(&sigalrm, sigalrm_handler, &sigalrm, SIGALRM); #endif - if(event_loop(0) < 0) { + if(!event_loop()) { logger(DEBUG_ALWAYS, LOG_ERR, "Error while waiting for input: %s", strerror(errno)); return 1; } #ifndef HAVE_MINGW - signal_del(&sighup_event); - signal_del(&sigterm_event); - signal_del(&sigquit_event); - signal_del(&sigalrm_event); + signal_del(&sighup); + signal_del(&sigalrm); + signal_del(&sigquit); + signal_del(&sigterm); #endif - event_del(&timeout_event); + timeout_del(&periodictimer); + timeout_del(&pingtimer); return 0; } diff --git a/src/net.h b/src/net.h index 2cb7f94..4277279 100644 --- a/src/net.h +++ b/src/net.h @@ -24,6 +24,7 @@ #include "ipv6.h" #include "cipher.h" #include "digest.h" +#include "event.h" #ifdef ENABLE_JUMBOGRAMS #define MTU 9018 /* 9000 bytes payload + 14 bytes ethernet header + 4 bytes VLAN tag */ @@ -99,10 +100,8 @@ typedef enum packet_type_t { } packet_type_t; typedef struct listen_socket_t { - struct event ev_tcp; - struct event ev_udp; - int tcp; - int udp; + io_t tcp; + io_t udp; sockaddr_t sa; } listen_socket_t; @@ -116,7 +115,7 @@ typedef struct outgoing_t { struct config_t *cfg; struct addrinfo *ai; struct addrinfo *aip; - struct event ev; + timeout_t ev; } outgoing_t; extern list_t *outgoing_list; @@ -161,10 +160,10 @@ extern char *scriptextension; #include "node.h" extern void retry_outgoing(outgoing_t *); -extern void handle_incoming_vpn_data(int, short, void *); +extern void handle_incoming_vpn_data(void *, int); extern void finish_connecting(struct connection_t *); extern bool do_outgoing_connection(struct outgoing_t *); -extern void handle_new_meta_connection(int, short, void *); +extern void handle_new_meta_connection(void *, int); extern int setup_listen_socket(const sockaddr_t *); extern int setup_vpn_in_socket(const sockaddr_t *); extern bool send_sptps_data(void *handle, uint8_t type, const char *data, size_t len); @@ -184,8 +183,8 @@ extern bool node_read_ecdsa_public_key(struct node_t *); extern bool read_ecdsa_public_key(struct connection_t *); extern bool read_rsa_public_key(struct connection_t *); extern void send_mtu_probe(struct node_t *); -extern void handle_device_data(int, short, void *); -extern void handle_meta_connection_data(int, short, void *); +extern void handle_device_data(void *, int); +extern void handle_meta_connection_data(struct connection_t *); extern void regenerate_key(void); extern void purge(void); extern void retry(void); diff --git a/src/net_packet.c b/src/net_packet.c index e50135e..81ca70a 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -77,7 +77,7 @@ bool localdiscovery = false; which will be broadcast to the local network. */ -static void send_mtu_probe_handler(int fd, short events, void *data) { +static void send_mtu_probe_handler(void *data) { node_t *n = data; int timeout = 1; @@ -151,13 +151,12 @@ static void send_mtu_probe_handler(int fd, short events, void *data) { } end: - event_add(&n->mtuevent, &(struct timeval){timeout, rand() % 100000}); + timeout_set(&n->mtutimeout, &(struct timeval){timeout, rand() % 100000}); } void send_mtu_probe(node_t *n) { - if(!timeout_initialized(&n->mtuevent)) - timeout_set(&n->mtuevent, send_mtu_probe_handler, n); - send_mtu_probe_handler(0, 0, n); + timeout_add(&n->mtutimeout, send_mtu_probe_handler, n, &(struct timeval){1, 0}); + send_mtu_probe_handler(n); } static void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) { @@ -557,15 +556,13 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { /* Make sure we have a valid key */ if(!n->status.validkey) { - time_t now = time(NULL); - logger(DEBUG_TRAFFIC, LOG_INFO, "No valid key known yet for %s (%s), forwarding via TCP", n->name, n->hostname); - if(n->last_req_key + 10 <= now) { + if(n->last_req_key + 10 <= now.tv_sec) { send_req_key(n); - n->last_req_key = now; + n->last_req_key = now.tv_sec; } send_tcppacket(n->nexthop->connection, origpkt); @@ -644,12 +641,12 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { && listen_socket[n->sock].sa.sa.sa_family == AF_INET) { priority = origpriority; logger(DEBUG_TRAFFIC, LOG_DEBUG, "Setting outgoing packet priority to %d", priority); - if(setsockopt(listen_socket[n->sock].udp, SOL_IP, IP_TOS, &priority, sizeof(priority))) /* SO_PRIORITY doesn't seem to work */ + if(setsockopt(listen_socket[n->sock].udp.fd, SOL_IP, IP_TOS, &priority, sizeof(priority))) /* SO_PRIORITY doesn't seem to work */ logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "setsockopt", strerror(errno)); } #endif - if(sendto(listen_socket[sock].udp, (char *) &inpkt->seqno, inpkt->len, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) { + if(sendto(listen_socket[sock].udp.fd, (char *) &inpkt->seqno, inpkt->len, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) { if(sockmsgsize(sockerrno)) { if(n->maxmtu >= origlen) n->maxmtu = origlen - 1; @@ -686,7 +683,7 @@ bool send_sptps_data(void *handle, uint8_t type, const char *data, size_t len) { choose_udp_address(to, &sa, &sock); - if(sendto(listen_socket[sock].udp, data, len, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) { + if(sendto(listen_socket[sock].udp.fd, data, len, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) { if(sockmsgsize(sockerrno)) { if(to->maxmtu >= len) to->maxmtu = len - 1; @@ -869,14 +866,13 @@ static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) { node_t *n = NULL; bool hard = false; static time_t last_hard_try = 0; - time_t now = time(NULL); for splay_each(edge_t, e, edge_weight_tree) { if(!e->to->status.reachable || e->to == myself) continue; if(sockaddrcmp_noport(from, &e->address)) { - if(last_hard_try == now) + if(last_hard_try == now.tv_sec) continue; hard = true; } @@ -889,13 +885,14 @@ static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) { } if(hard) - last_hard_try = now; + last_hard_try = now.tv_sec; - last_hard_try = now; + last_hard_try = now.tv_sec; return n; } -void handle_incoming_vpn_data(int sock, short events, void *data) { +void handle_incoming_vpn_data(void *data, int flags) { + listen_socket_t *ls = data; vpn_packet_t pkt; char *hostname; sockaddr_t from = {{0}}; @@ -903,7 +900,7 @@ void handle_incoming_vpn_data(int sock, short events, void *data) { node_t *n; int len; - len = recvfrom(sock, (char *) &pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen); + len = recvfrom(ls->udp.fd, (char *) &pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen); if(len <= 0 || len > MAXSIZE) { if(!sockwouldblock(sockerrno)) @@ -931,12 +928,12 @@ void handle_incoming_vpn_data(int sock, short events, void *data) { return; } - n->sock = (intptr_t)data; + n->sock = ls - listen_socket; receive_udppacket(n, &pkt); } -void handle_device_data(int sock, short events, void *data) { +void handle_device_data(void *data, int flags) { vpn_packet_t packet; packet.priority = 0; diff --git a/src/net_setup.c b/src/net_setup.c index 7485d21..c5c83e7 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -42,7 +42,7 @@ #include "xalloc.h" char *myport; -static struct event device_ev; +static io_t device_io; devops_t devops; char *proxyhost; @@ -270,22 +270,16 @@ static bool read_rsa_private_key(void) { return result; } -static struct event keyexpire_event; +static timeout_t keyexpire_timeout; -static void keyexpire_handler(int fd, short events, void *data) { +static void keyexpire_handler(void *data) { regenerate_key(); + timeout_set(data, &(struct timeval){keylifetime, rand() % 100000}); } void regenerate_key(void) { - if(timeout_initialized(&keyexpire_event)) { - logger(DEBUG_STATUS, LOG_INFO, "Expiring symmetric keys"); - event_del(&keyexpire_event); - send_key_changed(); - } else { - timeout_set(&keyexpire_event, keyexpire_handler, NULL); - } - - event_add(&keyexpire_event, &(struct timeval){keylifetime, rand() % 100000}); + logger(DEBUG_STATUS, LOG_INFO, "Expiring symmetric keys"); + send_key_changed(); } /* @@ -716,7 +710,8 @@ static bool setup_myself(void) { free(cipher); - regenerate_key(); + send_key_changed(); + timeout_add(&keyexpire_timeout, keyexpire_handler, &keyexpire_timeout, &(struct timeval){keylifetime, rand() % 100000}); /* Check if we want to use message authentication codes... */ @@ -790,15 +785,8 @@ static bool setup_myself(void) { if(!devops.setup()) return false; - if(device_fd >= 0) { - event_set(&device_ev, device_fd, EV_READ|EV_PERSIST, handle_device_data, NULL); - - if (event_add(&device_ev, NULL) < 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "event_add failed: %s", strerror(errno)); - devops.close(); - return false; - } - } + if(device_fd >= 0) + io_add(&device_io, handle_device_data, NULL, device_fd, IO_READ); /* Run tinc-up script to further initialize the tap interface */ char *envp[5]; @@ -840,27 +828,16 @@ static bool setup_myself(void) { return false; } - listen_socket[i].tcp = i + 3; - #ifdef FD_CLOEXEC fcntl(i + 3, F_SETFD, FD_CLOEXEC); #endif - listen_socket[i].udp = setup_vpn_in_socket(&sa); - if(listen_socket[i].udp < 0) + int udp_fd = setup_vpn_in_socket(&sa); + if(udp_fd < 0) return false; - event_set(&listen_socket[i].ev_tcp, listen_socket[i].tcp, EV_READ|EV_PERSIST, handle_new_meta_connection, NULL); - if(event_add(&listen_socket[i].ev_tcp, NULL) < 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "event_add failed: %s", strerror(errno)); - abort(); - } - - event_set(&listen_socket[i].ev_udp, listen_socket[i].udp, EV_READ|EV_PERSIST, handle_incoming_vpn_data, (void *)(intptr_t)listen_sockets); - if(event_add(&listen_socket[listen_sockets].ev_udp, NULL) < 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "event_add failed: %s", strerror(errno)); - abort(); - } + io_add(&listen_socket[i].tcp, (io_cb_t)handle_new_meta_connection, &listen_socket[i], i + 3, IO_READ); + io_add(&listen_socket[i].udp, (io_cb_t)handle_incoming_vpn_data, &listen_socket[i], udp_fd, IO_READ); if(debug_level >= DEBUG_CONNECTIONS) { hostname = sockaddr2hostname(&sa); @@ -913,37 +890,20 @@ static bool setup_myself(void) { return false; } - listen_socket[listen_sockets].tcp = - setup_listen_socket((sockaddr_t *) aip->ai_addr); + int tcp_fd = setup_listen_socket((sockaddr_t *) aip->ai_addr); - if(listen_socket[listen_sockets].tcp < 0) + if(tcp_fd < 0) continue; - listen_socket[listen_sockets].udp = - setup_vpn_in_socket((sockaddr_t *) aip->ai_addr); + int udp_fd = setup_vpn_in_socket((sockaddr_t *) aip->ai_addr); - if(listen_socket[listen_sockets].udp < 0) { - close(listen_socket[listen_sockets].tcp); + if(tcp_fd < 0) { + close(tcp_fd); continue; } - event_set(&listen_socket[listen_sockets].ev_tcp, - listen_socket[listen_sockets].tcp, - EV_READ|EV_PERSIST, - handle_new_meta_connection, NULL); - if(event_add(&listen_socket[listen_sockets].ev_tcp, NULL) < 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "event_add failed: %s", strerror(errno)); - abort(); - } - - event_set(&listen_socket[listen_sockets].ev_udp, - listen_socket[listen_sockets].udp, - EV_READ|EV_PERSIST, - handle_incoming_vpn_data, (void *)(intptr_t)listen_sockets); - if(event_add(&listen_socket[listen_sockets].ev_udp, NULL) < 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "event_add failed: %s", strerror(errno)); - abort(); - } + io_add(&listen_socket[listen_sockets].tcp, handle_new_meta_connection, &listen_socket[listen_sockets], tcp_fd, IO_READ); + io_add(&listen_socket[listen_sockets].udp, handle_incoming_vpn_data, &listen_socket[listen_sockets], udp_fd, IO_READ); if(debug_level >= DEBUG_CONNECTIONS) { hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr); @@ -1025,10 +985,10 @@ void close_network_connections(void) { } for(int i = 0; i < listen_sockets; i++) { - event_del(&listen_socket[i].ev_tcp); - event_del(&listen_socket[i].ev_udp); - close(listen_socket[i].tcp); - close(listen_socket[i].udp); + io_del(&listen_socket[i].tcp); + io_del(&listen_socket[i].udp); + close(listen_socket[i].tcp.fd); + close(listen_socket[i].udp.fd); } char *envp[5]; diff --git a/src/net_socket.c b/src/net_socket.c index ce1e3aa..212649b 100644 --- a/src/net_socket.c +++ b/src/net_socket.c @@ -271,7 +271,7 @@ int setup_vpn_in_socket(const sockaddr_t *sa) { return nfd; } /* int setup_vpn_in_socket */ -static void retry_outgoing_handler(int fd, short events, void *data) { +static void retry_outgoing_handler(void *data) { setup_outgoing_connection(data); } @@ -281,12 +281,9 @@ void retry_outgoing(outgoing_t *outgoing) { if(outgoing->timeout > maxtimeout) outgoing->timeout = maxtimeout; - timeout_set(&outgoing->ev, retry_outgoing_handler, outgoing); - event_add(&outgoing->ev, &(struct timeval){outgoing->timeout, rand() % 100000}); + timeout_add(&outgoing->ev, retry_outgoing_handler, outgoing, &(struct timeval){outgoing->timeout, rand() % 100000}); - logger(DEBUG_CONNECTIONS, LOG_NOTICE, - "Trying to re-establish outgoing connection in %d seconds", - outgoing->timeout); + logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Trying to re-establish outgoing connection in %d seconds", outgoing->timeout); } void finish_connecting(connection_t *c) { @@ -349,9 +346,7 @@ static void do_outgoing_pipe(connection_t *c, char *command) { #endif } -static void handle_meta_write(int sock, short events, void *data) { - connection_t *c = data; - +static void handle_meta_write(connection_t *c) { ssize_t outlen = send(c->socket, c->outbuf.data + c->outbuf.offset, c->outbuf.len - c->outbuf.offset, 0); if(outlen <= 0) { if(!errno || errno == EPIPE) { @@ -368,10 +363,16 @@ static void handle_meta_write(int sock, short events, void *data) { } buffer_read(&c->outbuf, outlen); - if(!c->outbuf.len && event_initialized(&c->outevent)) - event_del(&c->outevent); + if(!c->outbuf.len) + io_set(&c->io, IO_READ); } +static void handle_meta_io(void *data, int flags) { + if(flags & IO_WRITE) + handle_meta_write(data); + else + handle_meta_connection_data(data); +} bool do_outgoing_connection(outgoing_t *outgoing) { char *address, *port, *space; @@ -487,16 +488,13 @@ begin: connection_add(c); - event_set(&c->inevent, c->socket, EV_READ | EV_PERSIST, handle_meta_connection_data, c); - event_set(&c->outevent, c->socket, EV_WRITE | EV_PERSIST, handle_meta_write, c); - event_add(&c->inevent, NULL); + io_add(&c->io, handle_meta_io, c, c->socket, IO_READ); return true; } void setup_outgoing_connection(outgoing_t *outgoing) { - if(event_initialized(&outgoing->ev)) - event_del(&outgoing->ev); + timeout_del(&outgoing->ev); node_t *n = lookup_node(outgoing->name); @@ -523,13 +521,14 @@ void setup_outgoing_connection(outgoing_t *outgoing) { accept a new tcp connect and create a new connection */ -void handle_new_meta_connection(int sock, short events, void *data) { +void handle_new_meta_connection(void *data, int flags) { + listen_socket_t *l = data; connection_t *c; sockaddr_t sa; int fd; socklen_t len = sizeof sa; - fd = accept(sock, &sa.sa, &len); + fd = accept(l->tcp.fd, &sa.sa, &len); if(fd < 0) { logger(DEBUG_ALWAYS, LOG_ERR, "Accepting a new connection failed: %s", sockstrerror(sockerrno)); @@ -552,9 +551,7 @@ void handle_new_meta_connection(int sock, short events, void *data) { logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection from %s", c->hostname); - event_set(&c->inevent, c->socket, EV_READ | EV_PERSIST, handle_meta_connection_data, c); - event_set(&c->outevent, c->socket, EV_WRITE | EV_PERSIST, handle_meta_write, c); - event_add(&c->inevent, NULL); + io_add(&c->io, handle_meta_io, c, c->socket, IO_READ); configure_tcp(c); @@ -565,8 +562,7 @@ void handle_new_meta_connection(int sock, short events, void *data) { } static void free_outgoing(outgoing_t *outgoing) { - if(event_initialized(&outgoing->ev)) - event_del(&outgoing->ev); + timeout_del(&outgoing->ev); if(outgoing->ai) freeaddrinfo(outgoing->ai); diff --git a/src/node.c b/src/node.c index 5dc3119..465a48a 100644 --- a/src/node.c +++ b/src/node.c @@ -78,8 +78,7 @@ void free_node(node_t *n) { ecdsa_free(&n->ecdsa); sptps_stop(&n->sptps); - if(timeout_initialized(&n->mtuevent)) - event_del(&n->mtuevent); + timeout_del(&n->mtutimeout); if(n->hostname) free(n->hostname); diff --git a/src/node.h b/src/node.h index 3327fca..c567ad9 100644 --- a/src/node.h +++ b/src/node.h @@ -25,6 +25,7 @@ #include "cipher.h" #include "connection.h" #include "digest.h" +#include "event.h" #include "subnet.h" typedef struct node_status_t { @@ -83,7 +84,7 @@ typedef struct node_t { length_t minmtu; /* Probed minimum MTU */ length_t maxmtu; /* Probed maximum MTU */ int mtuprobes; /* Number of probes */ - struct event mtuevent; /* Probe event */ + timeout_t mtutimeout; /* Probe event */ uint64_t in_packets; uint64_t in_bytes; diff --git a/src/protocol.c b/src/protocol.c index 34c3f3b..bdc0378 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -165,7 +165,24 @@ static void free_past_request(past_request_t *r) { free(r); } -static struct event past_request_event; +static timeout_t past_request_timeout; + +static void age_past_requests(void *data) { + int left = 0, deleted = 0; + + for splay_each(past_request_t, p, past_request_tree) { + if(p->firstseen + pinginterval <= now.tv_sec) + splay_delete_node(past_request_tree, node), deleted++; + else + left++; + } + + if(left || deleted) + logger(DEBUG_SCARY_THINGS, LOG_DEBUG, "Aging past requests: deleted %d, left %d", deleted, left); + + if(left) + timeout_set(&past_request_timeout, &(struct timeval){10, rand() % 100000}); +} bool seen_request(const char *request) { past_request_t *new, p = {NULL}; @@ -180,39 +197,17 @@ bool seen_request(const char *request) { new->request = xstrdup(request); new->firstseen = time(NULL); splay_insert(past_request_tree, new); - event_add(&past_request_event, &(struct timeval){10, rand() % 100000}); + timeout_add(&past_request_timeout, age_past_requests, NULL, &(struct timeval){10, rand() % 100000}); return false; } } -static void age_past_requests(int fd, short events, void *data) { - int left = 0, deleted = 0; - time_t now = time(NULL); - - for splay_each(past_request_t, p, past_request_tree) { - if(p->firstseen + pinginterval <= now) - splay_delete_node(past_request_tree, node), deleted++; - else - left++; - } - - if(left || deleted) - logger(DEBUG_SCARY_THINGS, LOG_DEBUG, "Aging past requests: deleted %d, left %d", - deleted, left); - - if(left) - event_add(&past_request_event, &(struct timeval){10, rand() % 100000}); -} - void init_requests(void) { past_request_tree = splay_alloc_tree((splay_compare_t) past_request_compare, (splay_action_t) free_past_request); - - timeout_set(&past_request_event, age_past_requests, NULL); } void exit_requests(void) { splay_delete_tree(past_request_tree); - if(timeout_initialized(&past_request_event)) - event_del(&past_request_event); + timeout_del(&past_request_timeout); } diff --git a/src/route.c b/src/route.c index 46867d9..7bb9996 100644 --- a/src/route.c +++ b/src/route.c @@ -59,7 +59,7 @@ static const size_t opt_size = sizeof(struct nd_opt_hdr); #define MAX(a, b) ((a) > (b) ? (a) : (b)) #endif -static struct event age_subnets_event; +static timeout_t age_subnets_timeout; /* RFC 1071 */ @@ -84,13 +84,12 @@ static uint16_t inet_checksum(void *data, int len, uint16_t prevsum) { static bool ratelimit(int frequency) { static time_t lasttime = 0; static int count = 0; - time_t now = time(NULL); - if(lasttime == now) { + if(lasttime == now.tv_sec) { if(count >= frequency) return true; } else { - lasttime = now; + lasttime = now.tv_sec; count = 0; } @@ -192,12 +191,11 @@ static void swap_mac_addresses(vpn_packet_t *packet) { memcpy(&packet->data[6], &tmp, sizeof tmp); } -static void age_subnets(int fd, short events, void *data) { +static void age_subnets(void *data) { bool left = false; - time_t now = time(NULL); for splay_each(subnet_t, s, myself->subnet_tree) { - if(s->expires && s->expires < now) { + if(s->expires && s->expires < now.tv_sec) { if(debug_level >= DEBUG_TRAFFIC) { char netstr[MAXNETSTR]; if(net2str(netstr, sizeof netstr, s)) @@ -216,7 +214,7 @@ static void age_subnets(int fd, short events, void *data) { } if(left) - event_add(&age_subnets_event, &(struct timeval){10, rand() % 100000}); + timeout_set(&age_subnets_timeout, &(struct timeval){10, rand() % 100000}); } static void learn_mac(mac_t *address) { @@ -243,9 +241,7 @@ static void learn_mac(mac_t *address) { if(c->status.active) send_add_subnet(c, subnet); - if(!timeout_initialized(&age_subnets_event)) - timeout_set(&age_subnets_event, age_subnets, NULL); - event_add(&age_subnets_event, &(struct timeval){10, rand() % 100000}); + timeout_add(&age_subnets_timeout, age_subnets, NULL, &(struct timeval){10, rand() % 100000}); } else { if(subnet->expires) subnet->expires = time(NULL) + macexpire; diff --git a/src/sptps_test.c b/src/sptps_test.c index 7aafbbe..9db63ff 100644 --- a/src/sptps_test.c +++ b/src/sptps_test.c @@ -29,6 +29,7 @@ bool send_request(void *c, const char *msg, ...) { return false; } struct list_t *connection_list = NULL; bool send_meta(void *c, const char *msg , int len) { return false; } char *logfilename = NULL; +struct timeval now; ecdsa_t mykey, hiskey; diff --git a/src/tincctl.c b/src/tincctl.c index 344aa97..130ddde 100644 --- a/src/tincctl.c +++ b/src/tincctl.c @@ -62,6 +62,7 @@ char *netname = NULL; char *confbase = NULL; static char *tinc_conf = NULL; static char *hosts_dir = NULL; +struct timeval now; // Horrible global variables... static int pid = 0; diff --git a/src/tincd.c b/src/tincd.c index be13164..3883ec2 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -450,18 +450,6 @@ int main2(int argc, char **argv) { } #endif -#ifdef HAVE_DARWIN - if(!getenv("EVENT_KQUEUE")) - setenv("EVENT_NOKQUEUE", "1", 0); - if(!getenv("EVENT_POLL")) - setenv("EVENT_NOPOLL", "1", 0); -#endif - - if(!event_init()) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error initializing libevent!"); - return 1; - } - /* Setup sockets and open device. */ if(!setup_network()) diff --git a/src/top.c b/src/top.c index 8232c7a..7504889 100644 --- a/src/top.c +++ b/src/top.c @@ -57,7 +57,7 @@ static int sortmode = 0; static bool cumulative = false; static list_t node_list; -static struct timeval now, prev, diff; +static struct timeval cur, prev, diff; static int delay = 1000; static bool changed = true; static const char *unit = "bytes"; @@ -69,10 +69,10 @@ static float scale = 1; static void update(int fd) { sendline(fd, "%d %d", CONTROL, REQ_DUMP_TRAFFIC); - gettimeofday(&now, NULL); + gettimeofday(&cur, NULL); - timersub(&now, &prev, &diff); - prev = now; + timersub(&cur, &prev, &diff); + prev = cur; float interval = diff.tv_sec + diff.tv_usec * 1e-6; char line[4096];