2017-03-15 16:13:17 -04:00
|
|
|
/* Copyright (c) 2009-2017, The Tor Project, Inc. */
|
2009-06-04 01:05:23 -04:00
|
|
|
/* See LICENSE for licensing information */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \file compat_libevent.c
|
2016-07-04 16:27:46 +02:00
|
|
|
* \brief Wrappers and utility functions for Libevent.
|
|
|
|
*/
|
2009-06-04 01:05:23 -04:00
|
|
|
|
|
|
|
#include "orconfig.h"
|
2010-04-19 16:41:25 -04:00
|
|
|
#include "compat.h"
|
2015-09-15 17:20:44 +02:00
|
|
|
#define COMPAT_LIBEVENT_PRIVATE
|
2009-06-04 01:05:23 -04:00
|
|
|
#include "compat_libevent.h"
|
|
|
|
|
2014-04-16 14:54:39 -04:00
|
|
|
#include "crypto.h"
|
|
|
|
|
2009-06-04 01:05:23 -04:00
|
|
|
#include "util.h"
|
2010-07-09 21:52:20 -04:00
|
|
|
#include "torlog.h"
|
2009-06-04 01:05:23 -04:00
|
|
|
|
|
|
|
#include <event2/event.h>
|
2011-08-17 14:44:16 -04:00
|
|
|
#include <event2/thread.h>
|
2009-06-04 01:05:23 -04:00
|
|
|
|
|
|
|
/** A string which, if it appears in a libevent log, should be ignored. */
|
|
|
|
static const char *suppress_msg = NULL;
|
|
|
|
/** Callback function passed to event_set_log() so we can intercept
|
|
|
|
* log messages from libevent. */
|
2015-09-15 17:20:44 +02:00
|
|
|
STATIC void
|
2009-06-04 01:05:23 -04:00
|
|
|
libevent_logging_callback(int severity, const char *msg)
|
|
|
|
{
|
|
|
|
char buf[1024];
|
|
|
|
size_t n;
|
|
|
|
if (suppress_msg && strstr(msg, suppress_msg))
|
|
|
|
return;
|
|
|
|
n = strlcpy(buf, msg, sizeof(buf));
|
|
|
|
if (n && n < sizeof(buf) && buf[n-1] == '\n') {
|
|
|
|
buf[n-1] = '\0';
|
|
|
|
}
|
|
|
|
switch (severity) {
|
|
|
|
case _EVENT_LOG_DEBUG:
|
2013-02-01 15:43:37 -05:00
|
|
|
log_debug(LD_NOCB|LD_NET, "Message from libevent: %s", buf);
|
2009-06-04 01:05:23 -04:00
|
|
|
break;
|
|
|
|
case _EVENT_LOG_MSG:
|
2013-02-01 15:43:37 -05:00
|
|
|
log_info(LD_NOCB|LD_NET, "Message from libevent: %s", buf);
|
2009-06-04 01:05:23 -04:00
|
|
|
break;
|
|
|
|
case _EVENT_LOG_WARN:
|
2013-02-01 15:43:37 -05:00
|
|
|
log_warn(LD_NOCB|LD_GENERAL, "Warning from libevent: %s", buf);
|
2009-06-04 01:05:23 -04:00
|
|
|
break;
|
|
|
|
case _EVENT_LOG_ERR:
|
2013-02-01 15:43:37 -05:00
|
|
|
log_err(LD_NOCB|LD_GENERAL, "Error from libevent: %s", buf);
|
2009-06-04 01:05:23 -04:00
|
|
|
break;
|
|
|
|
default:
|
2013-02-01 15:43:37 -05:00
|
|
|
log_warn(LD_NOCB|LD_GENERAL, "Message [%d] from libevent: %s",
|
2009-06-04 01:05:23 -04:00
|
|
|
severity, buf);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/** Set hook to intercept log messages from libevent. */
|
|
|
|
void
|
|
|
|
configure_libevent_logging(void)
|
|
|
|
{
|
|
|
|
event_set_log_callback(libevent_logging_callback);
|
|
|
|
}
|
2016-07-03 19:42:36 +02:00
|
|
|
|
2009-06-04 01:05:23 -04:00
|
|
|
/** Ignore any libevent log message that contains <b>msg</b>. */
|
|
|
|
void
|
|
|
|
suppress_libevent_log_msg(const char *msg)
|
|
|
|
{
|
|
|
|
suppress_msg = msg;
|
|
|
|
}
|
|
|
|
|
2014-08-29 11:33:05 -04:00
|
|
|
/* Wrapper for event_free() that tolerates tor_event_free(NULL) */
|
|
|
|
void
|
2017-11-17 12:27:25 -05:00
|
|
|
tor_event_free_(struct event *ev)
|
2014-08-29 11:33:05 -04:00
|
|
|
{
|
|
|
|
if (ev == NULL)
|
|
|
|
return;
|
|
|
|
event_free(ev);
|
|
|
|
}
|
2009-06-04 01:05:23 -04:00
|
|
|
|
|
|
|
/** Global event base for use by the main thread. */
|
2016-06-02 09:46:12 -04:00
|
|
|
static struct event_base *the_event_base = NULL;
|
2009-06-04 01:05:23 -04:00
|
|
|
|
2009-06-04 03:16:26 -04:00
|
|
|
/* This is what passes for version detection on OSX. We set
|
|
|
|
* MACOSX_KQUEUE_IS_BROKEN to true iff we're on a version of OSX before
|
|
|
|
* 10.4.0 (aka 1040). */
|
|
|
|
#ifdef __APPLE__
|
|
|
|
#ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
|
|
|
|
#define MACOSX_KQUEUE_IS_BROKEN \
|
|
|
|
(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1040)
|
|
|
|
#else
|
|
|
|
#define MACOSX_KQUEUE_IS_BROKEN 0
|
2017-09-15 16:24:44 -04:00
|
|
|
#endif /* defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) */
|
|
|
|
#endif /* defined(__APPLE__) */
|
2009-06-04 03:16:26 -04:00
|
|
|
|
2009-06-04 01:05:23 -04:00
|
|
|
/** Initialize the Libevent library and set up the event base. */
|
|
|
|
void
|
2010-09-28 14:01:45 -04:00
|
|
|
tor_libevent_initialize(tor_libevent_cfg *torcfg)
|
2009-06-04 01:05:23 -04:00
|
|
|
{
|
|
|
|
tor_assert(the_event_base == NULL);
|
2010-09-29 02:50:46 -04:00
|
|
|
/* some paths below don't use torcfg, so avoid unused variable warnings */
|
|
|
|
(void)torcfg;
|
2009-06-04 03:16:26 -04:00
|
|
|
|
2010-09-28 14:01:45 -04:00
|
|
|
{
|
2011-11-14 18:12:29 -05:00
|
|
|
int attempts = 0;
|
|
|
|
struct event_config *cfg;
|
|
|
|
|
|
|
|
++attempts;
|
|
|
|
cfg = event_config_new();
|
2011-11-14 17:53:45 -05:00
|
|
|
tor_assert(cfg);
|
2010-09-28 14:01:45 -04:00
|
|
|
|
2016-08-02 13:20:59 -04:00
|
|
|
/* Telling Libevent not to try to turn locking on can avoid a needless
|
|
|
|
* socketpair() attempt. */
|
|
|
|
event_config_set_flag(cfg, EVENT_BASE_FLAG_NOLOCK);
|
2011-11-14 18:12:29 -05:00
|
|
|
|
2010-09-28 14:01:45 -04:00
|
|
|
if (torcfg->num_cpus > 0)
|
|
|
|
event_config_set_num_cpus_hint(cfg, torcfg->num_cpus);
|
|
|
|
|
2010-12-16 13:35:09 -05:00
|
|
|
/* We can enable changelist support with epoll, since we don't give
|
|
|
|
* Libevent any dup'd fds. This lets us avoid some syscalls. */
|
|
|
|
event_config_set_flag(cfg, EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST);
|
|
|
|
|
2010-09-28 14:01:45 -04:00
|
|
|
the_event_base = event_base_new_with_config(cfg);
|
2010-10-15 17:14:04 -04:00
|
|
|
|
|
|
|
event_config_free(cfg);
|
2010-09-28 14:01:45 -04:00
|
|
|
}
|
2009-06-04 03:16:26 -04:00
|
|
|
|
2011-11-14 17:53:45 -05:00
|
|
|
if (!the_event_base) {
|
2016-06-16 09:50:52 -04:00
|
|
|
/* LCOV_EXCL_START */
|
2011-11-14 17:53:45 -05:00
|
|
|
log_err(LD_GENERAL, "Unable to initialize Libevent: cannot continue.");
|
2017-10-19 13:42:28 -04:00
|
|
|
exit(1); // exit ok: libevent is broken.
|
2016-06-16 09:50:52 -04:00
|
|
|
/* LCOV_EXCL_STOP */
|
2011-11-14 17:53:45 -05:00
|
|
|
}
|
2009-06-04 03:16:26 -04:00
|
|
|
|
2013-02-01 15:43:37 -05:00
|
|
|
log_info(LD_GENERAL,
|
2009-06-04 03:16:26 -04:00
|
|
|
"Initialized libevent version %s using method %s. Good.",
|
|
|
|
event_get_version(), tor_libevent_get_method());
|
2009-06-04 01:05:23 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Return the current Libevent event base that we're set up to use. */
|
2014-01-23 20:54:50 -08:00
|
|
|
MOCK_IMPL(struct event_base *,
|
|
|
|
tor_libevent_get_base, (void))
|
2009-06-04 01:05:23 -04:00
|
|
|
{
|
2016-02-04 12:37:00 -05:00
|
|
|
tor_assert(the_event_base != NULL);
|
2009-06-04 01:05:23 -04:00
|
|
|
return the_event_base;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Return the name of the Libevent backend we're using. */
|
|
|
|
const char *
|
|
|
|
tor_libevent_get_method(void)
|
|
|
|
{
|
|
|
|
return event_base_get_method(the_event_base);
|
2009-06-04 03:16:26 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Return a string representation of the version of the currently running
|
|
|
|
* version of Libevent. */
|
|
|
|
const char *
|
|
|
|
tor_libevent_get_version_str(void)
|
|
|
|
{
|
|
|
|
return event_get_version();
|
|
|
|
}
|
|
|
|
|
2013-09-01 17:38:01 +01:00
|
|
|
/** Return a string representation of the version of Libevent that was used
|
|
|
|
* at compilation time. */
|
|
|
|
const char *
|
|
|
|
tor_libevent_get_header_version_str(void)
|
|
|
|
{
|
2016-07-03 19:42:36 +02:00
|
|
|
return LIBEVENT_VERSION;
|
2013-09-01 17:38:01 +01:00
|
|
|
}
|
|
|
|
|
2010-06-25 15:31:46 -04:00
|
|
|
/** Represents a timer that's run every N microseconds by Libevent. */
|
|
|
|
struct periodic_timer_t {
|
|
|
|
/** Underlying event used to implement this periodic event. */
|
|
|
|
struct event *ev;
|
|
|
|
/** The callback we'll be invoking whenever the event triggers */
|
|
|
|
void (*cb)(struct periodic_timer_t *, void *);
|
|
|
|
/** User-supplied data for the callback */
|
|
|
|
void *data;
|
|
|
|
};
|
|
|
|
|
|
|
|
/** Libevent callback to implement a periodic event. */
|
|
|
|
static void
|
|
|
|
periodic_timer_cb(evutil_socket_t fd, short what, void *arg)
|
|
|
|
{
|
|
|
|
periodic_timer_t *timer = arg;
|
|
|
|
(void) what;
|
|
|
|
(void) fd;
|
|
|
|
timer->cb(timer, timer->data);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Create and schedule a new timer that will run every <b>tv</b> in
|
|
|
|
* the event loop of <b>base</b>. When the timer fires, it will
|
|
|
|
* run the timer in <b>cb</b> with the user-supplied data in <b>data</b>. */
|
|
|
|
periodic_timer_t *
|
|
|
|
periodic_timer_new(struct event_base *base,
|
|
|
|
const struct timeval *tv,
|
|
|
|
void (*cb)(periodic_timer_t *timer, void *data),
|
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
periodic_timer_t *timer;
|
|
|
|
tor_assert(base);
|
|
|
|
tor_assert(tv);
|
|
|
|
tor_assert(cb);
|
|
|
|
timer = tor_malloc_zero(sizeof(periodic_timer_t));
|
2016-07-03 19:42:36 +02:00
|
|
|
if (!(timer->ev = tor_event_new(base, -1, EV_PERSIST,
|
2010-06-25 15:31:46 -04:00
|
|
|
periodic_timer_cb, timer))) {
|
|
|
|
tor_free(timer);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
timer->cb = cb;
|
|
|
|
timer->data = data;
|
2010-06-25 16:14:21 -04:00
|
|
|
event_add(timer->ev, (struct timeval *)tv); /*drop const for old libevent*/
|
2010-06-25 15:31:46 -04:00
|
|
|
return timer;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Stop and free a periodic timer */
|
|
|
|
void
|
2017-11-17 12:27:25 -05:00
|
|
|
periodic_timer_free_(periodic_timer_t *timer)
|
2010-06-25 15:31:46 -04:00
|
|
|
{
|
|
|
|
if (!timer)
|
|
|
|
return;
|
|
|
|
tor_event_free(timer->ev);
|
|
|
|
tor_free(timer);
|
|
|
|
}
|
2010-07-25 13:24:31 +02:00
|
|
|
|
2017-10-03 10:44:45 -04:00
|
|
|
/**
|
|
|
|
* Type used to represent events that run directly from the main loop,
|
|
|
|
* either because they are activated from elsewhere in the code, or
|
|
|
|
* because they have a simple timeout.
|
|
|
|
*
|
|
|
|
* We use this type to avoid exposing Libevent's API throughout the rest
|
|
|
|
* of the codebase.
|
|
|
|
*
|
|
|
|
* This type can't be used for all events: it doesn't handle events that
|
|
|
|
* are triggered by signals or by sockets.
|
|
|
|
*/
|
|
|
|
struct mainloop_event_t {
|
|
|
|
struct event *ev;
|
|
|
|
void (*cb)(mainloop_event_t *, void *);
|
|
|
|
void *userdata;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Internal: Implements mainloop event using a libevent event.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
mainloop_event_cb(evutil_socket_t fd, short what, void *arg)
|
|
|
|
{
|
|
|
|
(void)fd;
|
|
|
|
(void)what;
|
|
|
|
mainloop_event_t *mev = arg;
|
|
|
|
mev->cb(mev, mev->userdata);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create and return a new mainloop_event_t to run the function <b>cb</b>.
|
|
|
|
*
|
|
|
|
* When run, the callback function will be passed the mainloop_event_t
|
|
|
|
* and <b>userdata</b> as its arguments. The <b>userdata</b> pointer
|
|
|
|
* must remain valid for as long as the mainloop_event_t event exists:
|
|
|
|
* it is your responsibility to free it.
|
|
|
|
*
|
|
|
|
* The event is not scheduled by default: Use mainloop_event_activate()
|
|
|
|
* or mainloop_event_schedule() to make it run.
|
|
|
|
*/
|
|
|
|
mainloop_event_t *
|
|
|
|
mainloop_event_new(void (*cb)(mainloop_event_t *, void *),
|
|
|
|
void *userdata)
|
|
|
|
{
|
|
|
|
tor_assert(cb);
|
|
|
|
|
|
|
|
struct event_base *base = tor_libevent_get_base();
|
|
|
|
mainloop_event_t *mev = tor_malloc_zero(sizeof(mainloop_event_t));
|
|
|
|
mev->ev = tor_event_new(base, -1, 0, mainloop_event_cb, mev);
|
|
|
|
tor_assert(mev->ev);
|
|
|
|
mev->cb = cb;
|
|
|
|
mev->userdata = userdata;
|
|
|
|
return mev;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Schedule <b>event</b> to run in the main loop, immediately. If it is
|
|
|
|
* not scheduled, it will run anyway. If it is already scheduled to run
|
|
|
|
* later, it will run now instead. This function will have no effect if
|
|
|
|
* the event is already scheduled to run.
|
|
|
|
*
|
|
|
|
* This function may only be called from the main thread.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
mainloop_event_activate(mainloop_event_t *event)
|
|
|
|
{
|
|
|
|
tor_assert(event);
|
|
|
|
event_active(event->ev, EV_READ, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Schedule <b>event</b> to run in the main loop, after a delay of <b>tv</b>.
|
|
|
|
*
|
|
|
|
* If the event is scheduled for a different time, cancel it and run
|
|
|
|
* after this delay instead. If the event is currently pending to run
|
|
|
|
* <em>now</b>, has no effect.
|
|
|
|
*
|
|
|
|
* Do not call this function with <b>tv</b> == NULL -- use
|
|
|
|
* mainloop_event_activate() instead.
|
|
|
|
*
|
|
|
|
* This function may only be called from the main thread.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
mainloop_event_schedule(mainloop_event_t *event, const struct timeval *tv)
|
|
|
|
{
|
|
|
|
tor_assert(event);
|
|
|
|
if (BUG(tv == NULL)) {
|
|
|
|
// LCOV_EXCL_START
|
|
|
|
mainloop_event_activate(event);
|
|
|
|
return 0;
|
|
|
|
// LCOV_EXCL_STOP
|
|
|
|
}
|
|
|
|
return event_add(event->ev, tv);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Cancel <b>event</b> if it is currently active or pending. (Do nothing if
|
|
|
|
* the event is not currently active or pending.) */
|
|
|
|
void
|
|
|
|
mainloop_event_cancel(mainloop_event_t *event)
|
|
|
|
{
|
|
|
|
if (!event)
|
|
|
|
return;
|
|
|
|
event_del(event->ev);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Cancel <b>event</b> and release all storage associated with it. */
|
|
|
|
void
|
|
|
|
mainloop_event_free_(mainloop_event_t *event)
|
|
|
|
{
|
|
|
|
if (!event)
|
|
|
|
return;
|
|
|
|
tor_event_free(event->ev);
|
|
|
|
memset(event, 0xb8, sizeof(*event));
|
|
|
|
tor_free(event);
|
|
|
|
}
|
|
|
|
|
2014-04-16 14:54:39 -04:00
|
|
|
int
|
|
|
|
tor_init_libevent_rng(void)
|
|
|
|
{
|
|
|
|
int rv = 0;
|
|
|
|
char buf[256];
|
|
|
|
if (evutil_secure_rng_init() < 0) {
|
|
|
|
rv = -1;
|
|
|
|
}
|
|
|
|
crypto_rand(buf, 32);
|
2016-08-11 20:37:18 -04:00
|
|
|
#ifdef HAVE_EVUTIL_SECURE_RNG_ADD_BYTES
|
2014-04-16 14:54:39 -04:00
|
|
|
evutil_secure_rng_add_bytes(buf, 32);
|
2016-08-11 20:37:18 -04:00
|
|
|
#endif
|
2014-04-16 14:54:39 -04:00
|
|
|
evutil_secure_rng_get_bytes(buf, sizeof(buf));
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2017-12-11 11:33:54 -05:00
|
|
|
/**
|
|
|
|
* Un-initialize libevent in preparation for an exit
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
tor_libevent_free_all(void)
|
|
|
|
{
|
2018-01-19 09:45:10 -05:00
|
|
|
if (the_event_base)
|
|
|
|
event_base_free(the_event_base);
|
2017-12-11 11:33:54 -05:00
|
|
|
the_event_base = NULL;
|
|
|
|
}
|
|
|
|
|
2017-09-15 16:15:27 -04:00
|
|
|
#if defined(LIBEVENT_VERSION_NUMBER) && \
|
|
|
|
LIBEVENT_VERSION_NUMBER >= V(2,1,1) && \
|
|
|
|
!defined(TOR_UNIT_TESTS)
|
2012-06-15 10:31:34 -04:00
|
|
|
void
|
|
|
|
tor_gettimeofday_cached(struct timeval *tv)
|
|
|
|
{
|
|
|
|
event_base_gettimeofday_cached(the_event_base, tv);
|
|
|
|
}
|
|
|
|
void
|
|
|
|
tor_gettimeofday_cache_clear(void)
|
|
|
|
{
|
|
|
|
event_base_update_cache_time(the_event_base);
|
|
|
|
}
|
2017-09-15 16:24:44 -04:00
|
|
|
#else /* !(defined(LIBEVENT_VERSION_NUMBER) && ...) */
|
2012-06-15 10:31:34 -04:00
|
|
|
/** Cache the current hi-res time; the cache gets reset when libevent
|
|
|
|
* calls us. */
|
|
|
|
static struct timeval cached_time_hires = {0, 0};
|
|
|
|
|
|
|
|
/** Return a fairly recent view of the current time. */
|
|
|
|
void
|
|
|
|
tor_gettimeofday_cached(struct timeval *tv)
|
|
|
|
{
|
|
|
|
if (cached_time_hires.tv_sec == 0) {
|
|
|
|
tor_gettimeofday(&cached_time_hires);
|
|
|
|
}
|
|
|
|
*tv = cached_time_hires;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Reset the cached view of the current time, so that the next time we try
|
|
|
|
* to learn it, we will get an up-to-date value. */
|
|
|
|
void
|
|
|
|
tor_gettimeofday_cache_clear(void)
|
|
|
|
{
|
|
|
|
cached_time_hires.tv_sec = 0;
|
|
|
|
}
|
2014-01-09 12:47:24 -05:00
|
|
|
|
|
|
|
#ifdef TOR_UNIT_TESTS
|
|
|
|
/** For testing: force-update the cached time to a given value. */
|
|
|
|
void
|
|
|
|
tor_gettimeofday_cache_set(const struct timeval *tv)
|
|
|
|
{
|
|
|
|
tor_assert(tv);
|
|
|
|
memcpy(&cached_time_hires, tv, sizeof(*tv));
|
|
|
|
}
|
2017-05-10 11:00:07 -04:00
|
|
|
|
|
|
|
/** For testing: called post-fork to make libevent reinitialize
|
|
|
|
* kernel structures. */
|
|
|
|
void
|
|
|
|
tor_libevent_postfork(void)
|
|
|
|
{
|
|
|
|
int r = event_reinit(tor_libevent_get_base());
|
|
|
|
tor_assert(r == 0);
|
|
|
|
}
|
2017-09-15 16:24:44 -04:00
|
|
|
#endif /* defined(TOR_UNIT_TESTS) */
|
|
|
|
#endif /* defined(LIBEVENT_VERSION_NUMBER) && ... */
|
2012-06-15 16:12:24 -04:00
|
|
|
|