Commit 466259eb authored by Nick Mathewson's avatar Nick Mathewson 🦀
Browse files

Merge remote-tracking branch 'sebastian/libevent2'

parents 9a0bc462 e7b70b69
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -176,7 +176,7 @@ coverage-html-full: all
	genhtml --branch-coverage -o "$(HTML_COVER_DIR)" "$(HTML_COVER_DIR)/lcov.info"

# Avoid strlcpy.c, strlcat.c, aes.c, OpenBSD_malloc_Linux.c, sha256.c,
# eventdns.[hc], tinytest*.[ch]
# tinytest*.[ch]
check-spaces:
	$(top_srcdir)/scripts/maint/checkSpace.pl -C \
		$(top_srcdir)/src/common/*.[ch] \

changes/bug19554

0 → 100644
+4 −0
Original line number Diff line number Diff line
  o Dependency changes (Libevent)
    - Tor requires Libevent version 2.0.10-stable or later now.
      Implements ticket 19554.
+24 −35
Original line number Diff line number Diff line
@@ -481,7 +481,7 @@ TOR_SEARCH_LIBRARY(libevent, $trylibeventdir, [-levent $STATIC_LIBEVENT_FLAGS $T
#endif
#include <sys/time.h>
#include <sys/types.h>
#include <event.h>], [
#include <event2/event.h>], [
#ifdef _WIN32
#include <winsock2.h>
#endif
@@ -500,21 +500,10 @@ save_CPPFLAGS="$CPPFLAGS"
LIBS="-levent $STATIC_LIBEVENT_FLAGS $TOR_LIB_WS32 $LIBS"
LDFLAGS="$TOR_LDFLAGS_libevent $LDFLAGS"
CPPFLAGS="$TOR_CPPFLAGS_libevent $CPPFLAGS"
AC_CHECK_FUNCS([event_get_version_number \
                evutil_secure_rng_set_urandom_device_file \
                evutil_secure_rng_init \
               ])
AC_CHECK_MEMBERS([struct event.min_heap_idx], , ,
[#include <event.h>
])

AC_CHECK_HEADERS(event2/event.h event2/dns.h event2/bufferevent_ssl.h)
AC_CHECK_FUNCS([evutil_secure_rng_set_urandom_device_file])

LIBS="$STATIC_LIBEVENT_FLAGS $TOR_LIB_WS32 $save_LIBS"

AM_CONDITIONAL(USE_EXTERNAL_EVDNS,
  test "x$ac_cv_header_event2_dns_h" = "xyes")

if test "$enable_static_libevent" = "yes"; then
   if test "$tor_cv_library_libevent_dir" = "(system)"; then
     AC_MSG_ERROR("You must specify an explicit --with-libevent-dir=x option when using --enable-static-libevent")
@@ -541,30 +530,32 @@ LIBS="$save_LIBS"
LDFLAGS="$save_LDFLAGS"
CPPFLAGS="$save_CPPFLAGS"

dnl This isn't the best test for Libevent 2.0.3-alpha.  Once it's released,
dnl we can do much better.
if test "$enable_bufferevents" = "yes"; then
  if test "$ac_cv_header_event2_bufferevent_ssl_h" != "yes"; then
    AC_MSG_ERROR([You've asked for bufferevent support, but you're using a version of Libevent without SSL support.  This won't work.  We need Libevent 2.0.8-rc or later, and you don't seem to even have Libevent 2.0.3-alpha.])
  else

dnl Check that libevent is at least at version 2.0.10, the first stable
dnl release of its series
CPPFLAGS="$CPPFLAGS $TOR_CPPFLAGS_libevent"

    # Check for the right version.  First see if version detection works.
    AC_MSG_CHECKING([whether we can detect the Libevent version])
AC_MSG_CHECKING([whether Libevent is new enough])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include <event2/event.h>
#if !defined(LIBEVENT_VERSION_NUMBER) || LIBEVENT_VERSION_NUMBER < 10
#if !defined(LIBEVENT_VERSION_NUMBER) || LIBEVENT_VERSION_NUMBER < 0x02000a00
#error
int x = y(zz);
#else
int x = 1;
#endif
  ])], [event_version_number_works=yes; AC_MSG_RESULT([yes]) ],
     [event_version_number_works=no;  AC_MSG_RESULT([no])])
    if test "$event_version_number_works" != "yes"; then
      AC_MSG_WARN([Version detection on Libevent seems broken.  Your Libevent installation is probably screwed up or very old.])
    else
])], [ AC_MSG_RESULT([yes]) ],
   [ AC_MSG_RESULT([no])
     AC_MSG_ERROR([Libevent is not new enough.  We require 2.0.10-stable or later]) ] )

LIBS="$save_LIBS"
LDFLAGS="$save_LDFLAGS"
CPPFLAGS="$save_CPPFLAGS"

dnl bufferents require version 2.0.13
if test "$enable_bufferevents" = "yes"; then
   AC_CHECK_HEADERS(event2/bufferevent_ssl.h)

   CPPFLAGS="$CPPFLAGS $TOR_CPPFLAGS_libevent"

   AC_MSG_CHECKING([whether Libevent is new enough for bufferevents])
   AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include <event2/event.h>
@@ -578,8 +569,6 @@ int x = 1;
      [ AC_MSG_RESULT([no])
        AC_MSG_ERROR([Libevent does not seem new enough to support bufferevents.  We require 2.0.13-stable or later]) ] )
fi
  fi
fi

LIBS="$save_LIBS"
LDFLAGS="$save_LDFLAGS"
+0 −2
Original line number Diff line number Diff line
@@ -33,8 +33,6 @@
# files that we've snarfed in from somebody else, whose C we do no intend
# to document for them.
SKIP_FILES = [ "OpenBSD_malloc_Linux.c",
               "eventdns.c",
               "eventdns.h",
               "strlcat.c",
               "strlcpy.c",
               "sha256.c",
+5 −217
Original line number Diff line number Diff line
@@ -3,11 +3,8 @@

/**
 * \file compat_libevent.c
 * \brief Wrappers to handle porting between different versions of libevent.
 *
 * In an ideal world, we'd just use Libevent 2.0 from now on.  But as of June
 * 2012, Libevent 1.4 is still all over, and some poor souls are stuck on
 * Libevent 1.3e. */
 * \brief Wrappers and utility functions for Libevent.
 */

#include "orconfig.h"
#include "compat.h"
@@ -19,15 +16,11 @@
#include "util.h"
#include "torlog.h"

#ifdef HAVE_EVENT2_EVENT_H
#include <event2/event.h>
#include <event2/thread.h>
#ifdef USE_BUFFEREVENTS
#include <event2/bufferevent.h>
#endif
#else
#include <event.h>
#endif

/** A string which, if it appears in a libevent log, should be ignored. */
static const char *suppress_msg = NULL;
@@ -69,6 +62,7 @@ configure_libevent_logging(void)
{
  event_set_log_callback(libevent_logging_callback);
}

/** Ignore any libevent log message that contains <b>msg</b>. */
void
suppress_libevent_log_msg(const char *msg)
@@ -76,44 +70,6 @@ suppress_libevent_log_msg(const char *msg)
  suppress_msg = msg;
}

#ifndef HAVE_EVENT2_EVENT_H
/** Work-alike replacement for event_new() on pre-Libevent-2.0 systems. */
struct event *
tor_event_new(struct event_base *base, int sock, short what,
              void (*cb)(int, short, void *), void *arg)
{
  struct event *e = tor_malloc_zero(sizeof(struct event));
  event_set(e, sock, what, cb, arg);
  if (! base)
    base = tor_libevent_get_base();
  event_base_set(base, e);
  return e;
}
/** Work-alike replacement for evtimer_new() on pre-Libevent-2.0 systems. */
struct event *
tor_evtimer_new(struct event_base *base,
                void (*cb)(int, short, void *), void *arg)
{
  return tor_event_new(base, -1, 0, cb, arg);
}
/** Work-alike replacement for evsignal_new() on pre-Libevent-2.0 systems. */
struct event *
tor_evsignal_new(struct event_base * base, int sig,
                 void (*cb)(int, short, void *), void *arg)
{
  return tor_event_new(base, sig, EV_SIGNAL|EV_PERSIST, cb, arg);
}
/** Work-alike replacement for event_free() on pre-Libevent-2.0 systems,
 * except tolerate tor_event_free(NULL). */
void
tor_event_free(struct event *ev)
{
  if (ev == NULL)
    return;
  event_del(ev);
  tor_free(ev);
}
#else
/* Wrapper for event_free() that tolerates tor_event_free(NULL) */
void
tor_event_free(struct event *ev)
@@ -122,7 +78,6 @@ tor_event_free(struct event *ev)
    return;
  event_free(ev);
}
#endif

/** Global event base for use by the main thread. */
static struct event_base *the_event_base = NULL;
@@ -158,7 +113,6 @@ tor_libevent_initialize(tor_libevent_cfg *torcfg)
  /* some paths below don't use torcfg, so avoid unused variable warnings */
  (void)torcfg;

#ifdef HAVE_EVENT2_EVENT_H
  {
    int attempts = 0;
    int using_threads;
@@ -190,16 +144,12 @@ tor_libevent_initialize(tor_libevent_cfg *torcfg)
      event_config_set_flag(cfg, EVENT_BASE_FLAG_NOLOCK);
    }

#if defined(LIBEVENT_VERSION_NUMBER) && LIBEVENT_VERSION_NUMBER >= V(2,0,7)
    if (torcfg->num_cpus > 0)
      event_config_set_num_cpus_hint(cfg, torcfg->num_cpus);
#endif

#if LIBEVENT_VERSION_NUMBER >= V(2,0,9)
    /* 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);
#endif

    the_event_base = event_base_new_with_config(cfg);

@@ -223,9 +173,6 @@ tor_libevent_initialize(tor_libevent_cfg *torcfg)
      goto retry;
    }
  }
#else
  the_event_base = event_init();
#endif

  if (!the_event_base) {
    /* LCOV_EXCL_START */
@@ -234,8 +181,6 @@ tor_libevent_initialize(tor_libevent_cfg *torcfg)
    /* LCOV_EXCL_STOP */
  }

  /* Making this a NOTICE for now so we can link bugs to a libevent versions
   * or methods better. */
  log_info(LD_GENERAL,
      "Initialized libevent version %s using method %s. Good.",
      event_get_version(), tor_libevent_get_method());
@@ -257,62 +202,7 @@ tor_libevent_get_base, (void))
const char *
tor_libevent_get_method(void)
{
#ifdef HAVE_EVENT2_EVENT_H
  return event_base_get_method(the_event_base);
#else
  return event_get_method();
#endif
}

/** Return the le_version_t for the version of libevent specified in the
 * string <b>v</b>.  If the version is very new or uses an unrecognized
 * version, format, return LE_OTHER. */
STATIC le_version_t
tor_decode_libevent_version(const char *v)
{
  unsigned major, minor, patchlevel;
  char c, e, extra;
  int fields;

  /* Try the new preferred "1.4.11-stable" format.
   * Also accept "1.4.14b-stable". */
  fields = tor_sscanf(v, "%u.%u.%u%c%c", &major, &minor, &patchlevel, &c, &e);
  if (fields == 3 ||
      ((fields == 4 || fields == 5 ) && (c == '-' || c == '_')) ||
      (fields == 5 && TOR_ISALPHA(c) && (e == '-' || e == '_'))) {
    return V(major,minor,patchlevel);
  }

  /* Try the old "1.3e" format. */
  fields = tor_sscanf(v, "%u.%u%c%c", &major, &minor, &c, &extra);
  if (fields == 3 && TOR_ISALPHA(c)) {
    return V_OLD(major, minor, c);
  } else if (fields == 2) {
    return V(major, minor, 0);
  }

  return LE_OTHER;
}

/** Return an integer representing the binary interface of a Libevent library.
 * Two different versions with different numbers are sure not to be binary
 * compatible.  Two different versions with the same numbers have a decent
 * chance of binary compatibility.*/
STATIC int
le_versions_compatibility(le_version_t v)
{
  if (v == LE_OTHER)
    return 0;
  if (v < V_OLD(1,0,'c'))
    return 1;
  else if (v < V(1,4,0))
    return 2;
  else if (v < V(1,4,99))
    return 3;
  else if (v < V(2,0,1))
    return 4;
  else /* Everything 2.0 and later should be compatible. */
    return 5;
}

/** Return a string representation of the version of the currently running
@@ -323,101 +213,14 @@ tor_libevent_get_version_str(void)
  return event_get_version();
}

#if defined(LIBEVENT_VERSION)
#define HEADER_VERSION LIBEVENT_VERSION
#elif defined(_EVENT_VERSION)
#define HEADER_VERSION _EVENT_VERSION
#endif

/** Return a string representation of the version of Libevent that was used
* at compilation time. */
const char *
tor_libevent_get_header_version_str(void)
{
  return HEADER_VERSION;
  return LIBEVENT_VERSION;
}

/** See whether the headers we were built against differ from the library we
 * linked against so much that we're likely to crash.  If so, warn the
 * user. */
void
tor_check_libevent_header_compatibility(void)
{
  (void) le_versions_compatibility;
  (void) tor_decode_libevent_version;

  /* In libevent versions before 2.0, it's hard to keep binary compatibility
   * between upgrades, and unpleasant to detect when the version we compiled
   * against is unlike the version we have linked against. Here's how. */
#if defined(HEADER_VERSION)
  /* We have a header-file version and a function-call version. Easy. */
  if (strcmp(HEADER_VERSION, event_get_version())) {
    le_version_t v1, v2;
    int compat1 = -1, compat2 = -1;
    int verybad;
    v1 = tor_decode_libevent_version(HEADER_VERSION);
    v2 = tor_decode_libevent_version(event_get_version());
    compat1 = le_versions_compatibility(v1);
    compat2 = le_versions_compatibility(v2);

    verybad = compat1 != compat2;

    tor_log(verybad ? LOG_WARN : LOG_NOTICE,
        LD_GENERAL, "We were compiled with headers from version %s "
        "of Libevent, but we're using a Libevent library that says it's "
        "version %s.", HEADER_VERSION, event_get_version());
    if (verybad)
      log_warn(LD_GENERAL, "This will almost certainly make Tor crash.");
    else
      log_info(LD_GENERAL, "I think these versions are binary-compatible.");
  }
#else
  /* event_get_version but no _EVENT_VERSION.  We might be in 1.4.0-beta or
     earlier, where that's normal.  To see whether we were compiled with an
     earlier version, let's see whether the struct event defines MIN_HEAP_IDX.
  */
#ifdef HAVE_STRUCT_EVENT_MIN_HEAP_IDX
  /* The header files are 1.4.0-beta or later. If the version is not
   * 1.4.0-beta, we are incompatible. */
  {
    if (strcmp(event_get_version(), "1.4.0-beta")) {
      log_warn(LD_GENERAL, "It's a little hard to tell, but you seem to have "
               "Libevent 1.4.0-beta header files, whereas you have linked "
               "against Libevent %s.  This will probably make Tor crash.",
               event_get_version());
    }
  }
#else
  /* Our headers are 1.3e or earlier. If the library version is not 1.4.x or
     later, we're probably fine. */
  {
    const char *v = event_get_version();
    if ((v[0] == '1' && v[2] == '.' && v[3] > '3') || v[0] > '1') {
      log_warn(LD_GENERAL, "It's a little hard to tell, but you seem to have "
               "Libevent header file from 1.3e or earlier, whereas you have "
               "linked against Libevent %s.  This will probably make Tor "
               "crash.", event_get_version());
    }
  }
#endif

  /* Your libevent is ancient. */
#endif
}

/*
  If possible, we're going to try to use Libevent's periodic timer support,
  since it does a pretty good job of making sure that periodic events get
  called exactly M seconds apart, rather than starting each one exactly M
  seconds after the time that the last one was run.
 */
#ifdef HAVE_EVENT2_EVENT_H
#define HAVE_PERIODIC
#define PERIODIC_FLAGS EV_PERSIST
#else
#define PERIODIC_FLAGS 0
#endif

/** Represents a timer that's run every N microseconds by Libevent. */
struct periodic_timer_t {
  /** Underlying event used to implement this periodic event. */
@@ -426,11 +229,6 @@ struct periodic_timer_t {
  void (*cb)(struct periodic_timer_t *, void *);
  /** User-supplied data for the callback */
  void *data;
#ifndef HAVE_PERIODIC
  /** If Libevent doesn't know how to invoke events every N microseconds,
   * we'll need to remember the timeout interval here. */
  struct timeval tv;
#endif
};

/** Libevent callback to implement a periodic event. */
@@ -440,10 +238,6 @@ periodic_timer_cb(evutil_socket_t fd, short what, void *arg)
  periodic_timer_t *timer = arg;
  (void) what;
  (void) fd;
#ifndef HAVE_PERIODIC
  /** reschedule the event as needed. */
  event_add(timer->ev, &timer->tv);
#endif
  timer->cb(timer, timer->data);
}

@@ -461,16 +255,13 @@ periodic_timer_new(struct event_base *base,
  tor_assert(tv);
  tor_assert(cb);
  timer = tor_malloc_zero(sizeof(periodic_timer_t));
  if (!(timer->ev = tor_event_new(base, -1, PERIODIC_FLAGS,
  if (!(timer->ev = tor_event_new(base, -1, EV_PERSIST,
                                  periodic_timer_cb, timer))) {
    tor_free(timer);
    return NULL;
  }
  timer->cb = cb;
  timer->data = data;
#ifndef HAVE_PERIODIC
  memcpy(&timer->tv, tv, sizeof(struct timeval));
#endif
  event_add(timer->ev, (struct timeval *)tv); /*drop const for old libevent*/
  return timer;
}
@@ -541,16 +332,13 @@ int
tor_init_libevent_rng(void)
{
  int rv = 0;
#ifdef HAVE_EVUTIL_SECURE_RNG_INIT
  char buf[256];
  if (evutil_secure_rng_init() < 0) {
    rv = -1;
  }
  /* Older libevent -- manually initialize the RNG */
  crypto_rand(buf, 32);
  evutil_secure_rng_add_bytes(buf, 32);
  evutil_secure_rng_get_bytes(buf, sizeof(buf));
#endif
  return rv;
}

Loading