[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] [tor/master] Merge remote branch 'origin/maint-0.2.2'



commit a6c811313af3cfda1fca1d7595e9259f51d6ffd0
Merge: cb9ac03 f9e251c
Author: Nick Mathewson <nickm@xxxxxxxxxxxxxx>
Date:   Thu Feb 3 14:21:14 2011 -0500

    Merge remote branch 'origin/maint-0.2.2'

 changes/bug2358 |    5 +++++
 configure.in    |   14 ++++++++++++++
 src/or/main.c   |   13 +++++++++++++
 3 files changed, 32 insertions(+), 0 deletions(-)

diff --combined configure.in
index eddab67,9cbfbb1..2669511
--- a/configure.in
+++ b/configure.in
@@@ -4,7 -4,7 +4,7 @@@ dnl Copyright (c) 2007-2008, The Tor Pr
  dnl See LICENSE for licensing information
  
  AC_INIT
 -AM_INIT_AUTOMAKE(tor, 0.2.2.19-alpha)
 +AM_INIT_AUTOMAKE(tor, 0.2.3.0-alpha-dev)
  AM_CONFIG_HEADER(orconfig.h)
  
  AC_CANONICAL_HOST
@@@ -59,24 -59,6 +59,24 @@@ AC_ARG_ENABLE(asciidoc
          *) AC_MSG_ERROR(bad value for --disable-asciidoc) ;;
        esac], [asciidoc=true])
  
 +# By default, we're not ready to ship a NAT-PMP aware Tor
 +AC_ARG_ENABLE(nat-pmp,
 +     AS_HELP_STRING(--enable-nat-pmp, enable NAT-PMP support),
 +     [case "${enableval}" in
 +        yes) natpmp=true ;;
 +        no)  natpmp=false ;;
 +        * ) AC_MSG_ERROR(bad value for --enable-nat-pmp) ;;
 +      esac], [natpmp=false])
 +
 +# By default, we're not ready to ship a UPnP aware Tor
 +AC_ARG_ENABLE(upnp,
 +     AS_HELP_STRING(--enable-upnp, enable UPnP support),
 +     [case "${enableval}" in
 +        yes) upnp=true ;;
 +        no)  upnp=false ;;
 +        * ) AC_MSG_ERROR(bad value for --enable-upnp) ;;
 +      esac], [upnp=false])
 +
  
  AC_ARG_ENABLE(threads,
       AS_HELP_STRING(--disable-threads, disable multi-threading support))
@@@ -136,9 -118,6 +136,9 @@@ if test "$enable_local_appdata" = "yes"
              [Defined if we default to host local appdata paths on Windows])
  fi
  
 +AC_ARG_ENABLE(bufferevents,
 +     AS_HELP_STRING(--enable-bufferevents, use Libevent's buffered IO.))
 +
  AC_PROG_CC
  AC_PROG_CPP
  AC_PROG_MAKE_SET
@@@ -153,33 -132,6 +153,33 @@@ AC_PATH_PROG([A2X], [a2x], none
  
  AM_CONDITIONAL(USE_ASCIIDOC, test x$asciidoc = xtrue)
  
 +AM_CONDITIONAL(USE_FW_HELPER, test x$natpmp = xtrue || test x$upnp = xtrue)
 +AM_CONDITIONAL(NAT_PMP, test x$natpmp = xtrue)
 +AM_CONDITIONAL(MINIUPNPC, test x$upnp = xtrue)
 +AM_PROG_CC_C_O
 +
 +ifdef([AC_C_FLEXIBLE_ARRAY_MEMBER], [
 +AC_C_FLEXIBLE_ARRAY_MEMBER
 +], [
 + dnl Maybe we've got an old autoconf...
 + AC_CACHE_CHECK([for flexible array members],
 +     tor_cv_c_flexarray,
 +     [AC_COMPILE_IFELSE(
 +       AC_LANG_PROGRAM([
 + struct abc { int a; char b[]; };
 +], [
 + struct abc *def = malloc(sizeof(struct abc)+sizeof(char));
 + def->b[0] = 33;
 +]),
 +  [tor_cv_c_flexarray=yes],
 +  [tor_cv_c_flexarray=no])])
 + if test $tor_cv_flexarray = yes ; then
 +   AC_DEFINE([FLEXIBLE_ARRAY_MEMBER], [])
 + else
 +   AC_DEFINE([FLEXIBLE_ARRAY_MEMBER], [1])
 + fi
 +])
 +
  AC_PATH_PROG([SHA1SUM], [sha1sum], none)
  AC_PATH_PROG([OPENSSL], [openssl], none)
  
@@@ -271,28 -223,7 +271,28 @@@ dnl -----------------------------------
  dnl Check for functions before libevent, since libevent-1.2 apparently
  dnl exports strlcpy without defining it in a header.
  
 -AC_CHECK_FUNCS(gettimeofday ftime socketpair uname inet_aton strptime getrlimit strlcat strlcpy strtoull getaddrinfo localtime_r gmtime_r memmem strtok_r writev readv flock prctl vasprintf)
 +AC_CHECK_FUNCS(
 +	accept4 \
 +        flock \
 +        ftime \
 +        getaddrinfo \
 +        getrlimit \
 +        gettimeofday \
 +        gmtime_r \
 +        inet_aton \
 +        localtime_r \
 +        memmem \
 +        prctl \
 +        socketpair \
 +        strlcat \
 +        strlcpy \
 +        strptime \
 +        strtok_r \
 +        strtoull \
 +        sysconf \
 +        uname \
 +        vasprintf \
 +)
  
  using_custom_malloc=no
  if test x$enable_openbsd_malloc = xyes ; then
@@@ -371,7 -302,7 +371,7 @@@ AC_CHECK_MEMBERS([struct event.min_heap
  [#include <event.h>
  ])
  
 -AC_CHECK_HEADERS(event2/event.h event2/dns.h)
 +AC_CHECK_HEADERS(event2/event.h event2/dns.h event2/bufferevent_ssl.h)
  
  LIBS="$save_LIBS"
  LDFLAGS="$save_LDFLAGS"
@@@ -391,54 -322,6 +391,54 @@@ els
  fi
  AC_SUBST(TOR_LIBEVENT_LIBS)
  
 +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
 +
 +    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_COMPILE_IFELSE([AC_LANG_SOURCE([
 +#include <event2/event.h>
 +#if !defined(LIBEVENT_VERSION_NUMBER) || LIBEVENT_VERSION_NUMBER < 10
 +#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_CHECKING([whether Libevent is new enough for bufferevents])
 +      AC_COMPILE_IFELSE([AC_LANG_SOURCE([
 +#include <event2/event.h>
 +#if !defined(LIBEVENT_VERSION_NUMBER) || LIBEVENT_VERSION_NUMBER < 0x02000800
 +#error
 +int x = y(zz);
 +#else
 +int x = 1;
 +#endif
 +   ])], [ AC_MSG_RESULT([yes]) ],
 +      [ AC_MSG_RESULT([no])
 +        AC_MSG_ERROR([Libevent does not seem new enough to support bufferevents.  We require 2.0.8-rc or later]) ] )
 +    fi
 +  fi
 +fi
 +
 +LIBS="$save_LIBS"
 +LDFLAGS="$save_LDFLAGS"
 +CPPFLAGS="$save_CPPFLAGS"
 +
 +AM_CONDITIONAL(USE_BUFFEREVENTS, test "$enable_bufferevents" = "yes")
 +if test "$enable_bufferevents" = "yes"; then
 +   AC_DEFINE(USE_BUFFEREVENTS, 1, [Defined if we're going to use Libevent's buffered IO API])
 +fi
  
  dnl ------------------------------------------------------
  dnl Where do you live, openssl?  And how do we call you?
@@@ -506,94 -389,15 +506,94 @@@ AC_SUBST(TOR_ZLIB_LIBS
  
  dnl Make sure to enable support for large off_t if available.
  
 -AC_SYS_LARGEFILE
  
 -AC_CHECK_HEADERS(unistd.h string.h signal.h sys/stat.h sys/types.h fcntl.h sys/fcntl.h sys/time.h errno.h assert.h time.h, , AC_MSG_WARN(Some headers were not found, compilation may fail.  If compilation succeeds, please send your orconfig.h to the developers so we can fix this warning.))
 +dnl ------------------------------------------------------
 +dnl Where do you live, libnatpmp?  And how do we call you?
 +dnl There are no packages for Debian or Redhat as of this patch
 +
 +if test "$natpmp" = "true"; then
 +    AC_DEFINE(NAT_PMP, 1, [Define to 1 if we are building with nat-pmp.])
 +    TOR_SEARCH_LIBRARY(libnatpmp, $trylibnatpmpdir, [-lnatpmp],
 +        [#include <natpmp.h>],
 +        [#include <natpmp.h>],
 +        [   int r;
 +            natpmp_t natpmp;
 +            natpmpresp_t response;
 +            r = initnatpmp(&natpmp);],
 +            [printf("initnatpmp() returned %d (%s)\n", r, r?"FAILED":"SUCCESS");
 +            exit(0);],
 +        [--with-libnatpmp-dir],
 +        [/usr/lib/])
 +fi
 +
  
 -AC_CHECK_HEADERS(netdb.h sys/ioctl.h sys/socket.h arpa/inet.h netinet/in.h pwd.h grp.h sys/un.h sys/uio.h)
 +dnl ------------------------------------------------------
 +dnl Where do you live, libminiupnpc?  And how do we call you?
 +dnl There are no packages for Debian or Redhat as of this patch
 +
 +if test "$upnp" = "true"; then
 +    AC_DEFINE(MINIUPNPC, 1, [Define to 1 if we are building with UPnP.])
 +    TOR_SEARCH_LIBRARY(libminiupnpc, $trylibminiupnpcdir, [-lminiupnpc],
 +        [#include <miniupnpc/miniwget.h>
 +         #include <miniupnpc/miniupnpc.h>
 +         #include <miniupnpc/upnpcommands.h>],
 +        [void upnpDiscover(int delay, const char * multicastif,
 +         const char * minissdpdsock, int sameport);],
 +        [upnpDiscover(1, 0, 0, 0); exit(0);],
 +        [--with-libminiupnpc-dir],
 +        [/usr/lib/])
 +fi
 +
 +AC_SYS_LARGEFILE
 +
 +AC_CHECK_HEADERS(
 +        assert.h \
 +        errno.h \
 +        fcntl.h \
 +        signal.h \
 +        string.h \
 +        sys/fcntl.h \
 +        sys/stat.h \
 +        sys/time.h \
 +        sys/types.h \
 +        time.h \
 +        unistd.h
 + , , AC_MSG_WARN(Some headers were not found, compilation may fail.  If compilation succeeds, please send your orconfig.h to the developers so we can fix this warning.))
  
  dnl These headers are not essential
  
 -AC_CHECK_HEADERS(stdint.h sys/types.h inttypes.h sys/param.h sys/wait.h limits.h sys/limits.h netinet/in.h arpa/inet.h machine/limits.h syslog.h sys/time.h sys/resource.h inttypes.h utime.h sys/utime.h sys/mman.h netinet/in6.h malloc.h sys/syslimits.h malloc/malloc.h linux/types.h sys/file.h malloc_np.h sys/prctl.h)
 +AC_CHECK_HEADERS(
 +        arpa/inet.h \
 +        grp.h \
 +        inttypes.h \
 +        limits.h \
 +        linux/types.h \
 +        machine/limits.h \
 +        malloc.h \
 +        malloc/malloc.h \
 +        malloc_np.h \
 +        netdb.h \
 +        netinet/in.h \
 +        netinet/in6.h \
 +        pwd.h \
 +        stdint.h \
 +        sys/file.h \
 +        sys/ioctl.h \
 +        sys/limits.h \
 +        sys/mman.h \
 +        sys/param.h \
 +        sys/prctl.h \
 +        sys/resource.h \
 +        sys/socket.h \
 +        sys/syslimits.h \
 +        sys/time.h \
 +        sys/types.h \
 +        sys/un.h \
 +        sys/utime.h \
 +        sys/wait.h \
 +        syslog.h \
 +        utime.h
 +)
  
  TOR_CHECK_PROTOTYPE(malloc_good_size, HAVE_MALLOC_GOOD_SIZE_PROTOTYPE,
  [#ifdef HAVE_MALLOC_H
@@@ -1032,13 -836,6 +1032,13 @@@ if test "x$exec_prefix" = "xNONE"; the
    exec_prefix=$prefix
  fi
  
 +if test "x$BUILDDIR" = "x"; then
 +  BUILDDIR=`pwd`
 +fi
 +AC_SUBST(BUILDDIR)
 +AH_TEMPLATE([BUILDDIR],[tor's build directory])
 +AC_DEFINE_UNQUOTED(BUILDDIR,"$BUILDDIR")
 +
  if test "x$CONFDIR" = "x"; then
    CONFDIR=`eval echo $sysconfdir/tor`
  fi
@@@ -1051,6 -848,20 +1051,20 @@@ AC_SUBST(BINDIR
  LOCALSTATEDIR=`eval echo $localstatedir`
  AC_SUBST(LOCALSTATEDIR)
  
+ if test "$bwin32" = true; then
+   # Test if the linker supports the --nxcompat and --dynamicbase options
+   # for Windows
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="-Wl,--nxcompat -Wl,--dynamicbase"
+   AC_MSG_CHECKING([whether the linker supports DllCharacteristics])
+   AC_LINK_IFELSE([AC_LANG_PROGRAM([])],
+     [AC_MSG_RESULT([yes])]
+     [save_LDFLAGS="$save_LDFLAGS $LDFLAGS"],
+     [AC_MSG_RESULT([no])]
+   )
+   LDFLAGS="$save_LDFLAGS"
+ fi
+ 
  # Set CFLAGS _after_ all the above checks, since our warnings are stricter
  # than autoconf's macros like.
  if test "$GCC" = yes; then
@@@ -1098,12 -909,7 +1112,12 @@@ if test x$enable_gcc_warnings = xyes |
        CFLAGS="$CFLAGS -Wno-system-headers" ;;
    esac
  
 -  CFLAGS="$CFLAGS -W -Wfloat-equal -Wundef -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings -Wredundant-decls -Wchar-subscripts -Wcomment -Wformat=2 -Wwrite-strings -Wmissing-declarations -Wredundant-decls -Wnested-externs -Wbad-function-cast -Wswitch-enum"
 +  CFLAGS="$CFLAGS -W -Wfloat-equal -Wundef -Wpointer-arith"
 +  CFLAGS="$CFLAGS -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings"
 +  CFLAGS="$CFLAGS -Wredundant-decls -Wchar-subscripts -Wcomment -Wformat=2"
 +  CFLAGS="$CFLAGS -Wwrite-strings -Wmissing-declarations -Wredundant-decls"
 +  CFLAGS="$CFLAGS -Wnested-externs -Wbad-function-cast -Wswitch-enum"
 +
    if test x$enable_gcc_warnings = xyes; then
      CFLAGS="$CFLAGS -Werror"
    fi
@@@ -1115,14 -921,14 +1129,14 @@@
      CFLAGS="$CFLAGS -Winit-self -Wmissing-field-initializers -Wdeclaration-after-statement -Wold-style-definition"
    fi
  
 -  if test x$have_gcc42 = xyes ; then 
 +  if test x$have_gcc42 = xyes ; then
      # These warnings break gcc 4.0.2 and work on gcc 4.2
      # XXXX020 See if any of these work with earlier versions.
      CFLAGS="$CFLAGS -Waddress -Wmissing-noreturn -Wnormalized=id -Woverride-init -Wstrict-overflow=1"
      # We used to use -Wstrict-overflow=5, but that breaks us heavily under 4.3.
    fi
  
 -  if test x$have_gcc43 = xyes ; then 
 +  if test x$have_gcc43 = xyes ; then
      # These warnings break gcc 4.2 and work on gcc 4.3
      # XXXX020 See if any of these work with earlier versions.
      CFLAGS="$CFLAGS -Wextra -Warray-bounds"
@@@ -1140,30 -946,7 +1154,30 @@@ f
  
  CPPFLAGS="$CPPFLAGS $TOR_CPPFLAGS_libevent $TOR_CPPFLAGS_openssl $TOR_CPPFLAGS_zlib"
  
 -AC_CONFIG_FILES([Makefile tor.spec Doxyfile contrib/tor.sh contrib/torctl contrib/torify contrib/tor.logrotate contrib/Makefile src/config/torrc.sample src/Makefile doc/Makefile doc/spec/Makefile src/config/Makefile src/common/Makefile src/or/Makefile src/test/Makefile src/win32/Makefile src/tools/Makefile contrib/suse/Makefile contrib/suse/tor.sh])
 +AC_CONFIG_FILES([
 +        Doxyfile
 +        Makefile
 +        contrib/Makefile
 +        contrib/suse/Makefile
 +        contrib/suse/tor.sh
 +        contrib/tor.logrotate
 +        contrib/tor.sh
 +        contrib/torctl
 +        contrib/torify
 +        doc/Makefile
 +        doc/spec/Makefile
 +        src/Makefile
 +        src/common/Makefile
 +        src/config/Makefile
 +        src/config/torrc.sample
 +        src/or/Makefile
 +        src/test/Makefile
 +        src/tools/Makefile
 +        src/tools/tor-fw-helper/Makefile
 +        src/win32/Makefile
 +        tor.spec
 +])
 +
  AC_OUTPUT
  
  if test -x /usr/bin/perl && test -x ./contrib/updateVersions.pl ; then
diff --combined src/or/main.c
index aa97609,979a2be..3a77f62
--- a/src/or/main.c
+++ b/src/or/main.c
@@@ -33,7 -33,6 +33,7 @@@
  #include "main.h"
  #include "microdesc.h"
  #include "networkstatus.h"
 +#include "nodelist.h"
  #include "ntmain.h"
  #include "onion.h"
  #include "policies.h"
@@@ -57,10 -56,6 +57,10 @@@
  #include <event.h>
  #endif
  
 +#ifdef USE_BUFFEREVENTS
 +#include <event2/bufferevent.h>
 +#endif
 +
  void evdns_shutdown(int);
  
  /********* PROTOTYPES **********/
@@@ -77,7 -72,6 +77,7 @@@ static int connection_should_read_from_
  
  /********* START VARIABLES **********/
  
 +#ifndef USE_BUFFEREVENTS
  int global_read_bucket; /**< Max number of bytes I can read this second. */
  int global_write_bucket; /**< Max number of bytes I can write this second. */
  
@@@ -85,17 -79,13 +85,17 @@@
  int global_relayed_read_bucket;
  /** Max number of relayed (bandwidth class 1) bytes I can write this second. */
  int global_relayed_write_bucket;
 -
  /** What was the read bucket before the last second_elapsed_callback() call?
   * (used to determine how many bytes we've read). */
  static int stats_prev_global_read_bucket;
  /** What was the write bucket before the last second_elapsed_callback() call?
   * (used to determine how many bytes we've written). */
  static int stats_prev_global_write_bucket;
 +#else
 +static uint64_t stats_prev_n_read = 0;
 +static uint64_t stats_prev_n_written = 0;
 +#endif
 +
  /* XXX we might want to keep stats about global_relayed_*_bucket too. Or not.*/
  /** How many bytes have we read since we started the process? */
  static uint64_t stats_n_bytes_read = 0;
@@@ -161,38 -151,12 +161,38 @@@ int can_complete_circuit=0
  *
  ****************************************************************************/
  
 +#if 0 && defined(USE_BUFFEREVENTS)
 +static void
 +free_old_inbuf(connection_t *conn)
 +{
 +  if (! conn->inbuf)
 +    return;
 +
 +  tor_assert(conn->outbuf);
 +  tor_assert(buf_datalen(conn->inbuf) == 0);
 +  tor_assert(buf_datalen(conn->outbuf) == 0);
 +  buf_free(conn->inbuf);
 +  buf_free(conn->outbuf);
 +  conn->inbuf = conn->outbuf = NULL;
 +
 +  if (conn->read_event) {
 +    event_del(conn->read_event);
 +    tor_event_free(conn->read_event);
 +  }
 +  if (conn->write_event) {
 +    event_del(conn->read_event);
 +    tor_event_free(conn->write_event);
 +  }
 +  conn->read_event = conn->write_event = NULL;
 +}
 +#endif
 +
  /** Add <b>conn</b> to the array of connections that we can poll on.  The
   * connection's socket must be set; the connection starts out
   * non-reading and non-writing.
   */
  int
 -connection_add(connection_t *conn)
 +connection_add_impl(connection_t *conn, int is_connecting)
  {
    tor_assert(conn);
    tor_assert(conn->s >= 0 ||
@@@ -204,63 -168,11 +204,63 @@@
    conn->conn_array_index = smartlist_len(connection_array);
    smartlist_add(connection_array, conn);
  
 -  if (conn->s >= 0 || conn->linked) {
 +#ifdef USE_BUFFEREVENTS
 +  if (connection_type_uses_bufferevent(conn)) {
 +    if (conn->s >= 0 && !conn->linked) {
 +      conn->bufev = bufferevent_socket_new(
 +                         tor_libevent_get_base(),
 +                         conn->s,
 +                         BEV_OPT_DEFER_CALLBACKS);
 +      if (!conn->bufev) {
 +        log_warn(LD_BUG, "Unable to create socket bufferevent");
 +        smartlist_del(connection_array, conn->conn_array_index);
 +        conn->conn_array_index = -1;
 +        return -1;
 +      }
 +      if (is_connecting) {
 +        /* Put the bufferevent into a "connecting" state so that we'll get
 +         * a "connected" event callback on successful write. */
 +        bufferevent_socket_connect(conn->bufev, NULL, 0);
 +      }
 +      connection_configure_bufferevent_callbacks(conn);
 +    } else if (conn->linked && conn->linked_conn &&
 +               connection_type_uses_bufferevent(conn->linked_conn)) {
 +      tor_assert(conn->s < 0);
 +      if (!conn->bufev) {
 +        struct bufferevent *pair[2] = { NULL, NULL };
 +        if (bufferevent_pair_new(tor_libevent_get_base(),
 +                                 BEV_OPT_DEFER_CALLBACKS,
 +                                 pair) < 0) {
 +          log_warn(LD_BUG, "Unable to create bufferevent pair");
 +          smartlist_del(connection_array, conn->conn_array_index);
 +          conn->conn_array_index = -1;
 +          return -1;
 +        }
 +        tor_assert(pair[0]);
 +        conn->bufev = pair[0];
 +        conn->linked_conn->bufev = pair[1];
 +      } /* else the other side already was added, and got a bufferevent_pair */
 +      connection_configure_bufferevent_callbacks(conn);
 +    } else {
 +      tor_assert(!conn->linked);
 +    }
 +
 +    if (conn->bufev)
 +      tor_assert(conn->inbuf == NULL);
 +
 +    if (conn->linked_conn && conn->linked_conn->bufev)
 +      tor_assert(conn->linked_conn->inbuf == NULL);
 +  }
 +#else
 +  (void) is_connecting;
 +#endif
 +
 +  if (!HAS_BUFFEREVENT(conn) && (conn->s >= 0 || conn->linked)) {
      conn->read_event = tor_event_new(tor_libevent_get_base(),
           conn->s, EV_READ|EV_PERSIST, conn_read_callback, conn);
      conn->write_event = tor_event_new(tor_libevent_get_base(),
           conn->s, EV_WRITE|EV_PERSIST, conn_write_callback, conn);
 +    /* XXXX CHECK FOR NULL RETURN! */
    }
  
    log_debug(LD_NET,"new conn type %s, socket %d, address %s, n_conns %d.",
@@@ -284,12 -196,6 +284,12 @@@ connection_unregister_events(connection
        log_warn(LD_BUG, "Error removing write event for %d", conn->s);
      tor_free(conn->write_event);
    }
 +#ifdef USE_BUFFEREVENTS
 +  if (conn->bufev) {
 +    bufferevent_free(conn->bufev);
 +    conn->bufev = NULL;
 +  }
 +#endif
    if (conn->dns_server_port) {
      dnsserv_close_listener(conn);
    }
@@@ -398,37 -304,12 +398,37 @@@ get_connection_array(void
    return connection_array;
  }
  
 +/** Provides the traffic read and written over the life of the process. */
 +
 +uint64_t
 +get_bytes_read(void)
 +{
 +  return stats_n_bytes_read;
 +}
 +
 +uint64_t
 +get_bytes_written(void)
 +{
 +  return stats_n_bytes_written;
 +}
 +
  /** Set the event mask on <b>conn</b> to <b>events</b>.  (The event
   * mask is a bitmask whose bits are READ_EVENT and WRITE_EVENT)
   */
  void
  connection_watch_events(connection_t *conn, watchable_events_t events)
  {
 +  IF_HAS_BUFFEREVENT(conn, {
 +      short ev = ((short)events) & (EV_READ|EV_WRITE);
 +      short old_ev = bufferevent_get_enabled(conn->bufev);
 +      if ((ev & ~old_ev) != 0) {
 +        bufferevent_enable(conn->bufev, ev);
 +      }
 +      if ((old_ev & ~ev) != 0) {
 +        bufferevent_disable(conn->bufev, old_ev & ~ev);
 +      }
 +      return;
 +  });
    if (events & READ_EVENT)
      connection_start_reading(conn);
    else
@@@ -446,9 -327,6 +446,9 @@@ connection_is_reading(connection_t *con
  {
    tor_assert(conn);
  
 +  IF_HAS_BUFFEREVENT(conn,
 +    return (bufferevent_get_enabled(conn->bufev) & EV_READ) != 0;
 +  );
    return conn->reading_from_linked_conn ||
      (conn->read_event && event_pending(conn->read_event, EV_READ, NULL));
  }
@@@ -458,12 -336,6 +458,12 @@@ voi
  connection_stop_reading(connection_t *conn)
  {
    tor_assert(conn);
 +
 +  IF_HAS_BUFFEREVENT(conn, {
 +      bufferevent_disable(conn->bufev, EV_READ);
 +      return;
 +  });
 +
    tor_assert(conn->read_event);
  
    if (conn->linked) {
@@@ -483,12 -355,6 +483,12 @@@ voi
  connection_start_reading(connection_t *conn)
  {
    tor_assert(conn);
 +
 +  IF_HAS_BUFFEREVENT(conn, {
 +      bufferevent_enable(conn->bufev, EV_READ);
 +      return;
 +  });
 +
    tor_assert(conn->read_event);
  
    if (conn->linked) {
@@@ -510,10 -376,6 +510,10 @@@ connection_is_writing(connection_t *con
  {
    tor_assert(conn);
  
 +  IF_HAS_BUFFEREVENT(conn,
 +    return (bufferevent_get_enabled(conn->bufev) & EV_WRITE) != 0;
 +  );
 +
    return conn->writing_to_linked_conn ||
      (conn->write_event && event_pending(conn->write_event, EV_WRITE, NULL));
  }
@@@ -523,12 -385,6 +523,12 @@@ voi
  connection_stop_writing(connection_t *conn)
  {
    tor_assert(conn);
 +
 +  IF_HAS_BUFFEREVENT(conn, {
 +      bufferevent_disable(conn->bufev, EV_WRITE);
 +      return;
 +  });
 +
    tor_assert(conn->write_event);
  
    if (conn->linked) {
@@@ -549,12 -405,6 +549,12 @@@ voi
  connection_start_writing(connection_t *conn)
  {
    tor_assert(conn);
 +
 +  IF_HAS_BUFFEREVENT(conn, {
 +      bufferevent_enable(conn->bufev, EV_WRITE);
 +      return;
 +  });
 +
    tor_assert(conn->write_event);
  
    if (conn->linked) {
@@@ -740,23 -590,7 +740,23 @@@ conn_close_if_marked(int i
    assert_connection_ok(conn, now);
    /* assert_all_pending_dns_resolves_ok(); */
  
 +#ifdef USE_BUFFEREVENTS
 +  if (conn->bufev) {
 +    if (conn->hold_open_until_flushed &&
 +        evbuffer_get_length(bufferevent_get_output(conn->bufev))) {
 +      /* don't close yet. */
 +      return 0;
 +    }
 +    if (conn->linked_conn && ! conn->linked_conn->marked_for_close) {
 +      /* We need to do this explicitly so that the linked connection
 +       * notices that there was an EOF. */
 +      bufferevent_flush(conn->bufev, EV_WRITE, BEV_FINISHED);
 +    }
 +  }
 +#endif
 +
    log_debug(LD_NET,"Cleaning up connection (fd %d).",conn->s);
 +  IF_HAS_BUFFEREVENT(conn, goto unlink);
    if ((conn->s >= 0 || conn->linked_conn) && connection_wants_to_flush(conn)) {
      /* s == -1 means it's an incomplete edge connection, or that the socket
       * has already been closed as unflushable. */
@@@ -779,8 -613,8 +779,8 @@@
        }
        log_debug(LD_GENERAL, "Flushed last %d bytes from a linked conn; "
                 "%d left; flushlen %d; wants-to-flush==%d", retval,
 -               (int)buf_datalen(conn->outbuf),
 -               (int)conn->outbuf_flushlen,
 +                (int)connection_get_outbuf_len(conn),
 +                (int)conn->outbuf_flushlen,
                  connection_wants_to_flush(conn));
      } else if (connection_speaks_cells(conn)) {
        if (conn->state == OR_CONN_STATE_OPEN) {
@@@ -817,17 -651,13 +817,17 @@@
               "something is wrong with your network connection, or "
               "something is wrong with theirs. "
               "(fd %d, type %s, state %d, marked at %s:%d).",
 -             (int)buf_datalen(conn->outbuf),
 +             (int)connection_get_outbuf_len(conn),
               escaped_safe_str_client(conn->address),
               conn->s, conn_type_to_string(conn->type), conn->state,
               conn->marked_for_close_file,
               conn->marked_for_close);
      }
    }
 +
 +#ifdef USE_BUFFEREVENTS
 + unlink:
 +#endif
    connection_unlink(conn); /* unlink, remove, free */
    return 1;
  }
@@@ -873,13 -703,10 +873,13 @@@ directory_info_has_arrived(time_t now, 
          "I learned some more directory information, but not enough to "
          "build a circuit: %s", get_dir_info_status_string());
      update_router_descriptor_downloads(now);
 +    update_microdesc_downloads(now);
      return;
    } else {
 -    if (directory_fetches_from_authorities(options))
 +    if (directory_fetches_from_authorities(options)) {
        update_router_descriptor_downloads(now);
 +      update_microdesc_downloads(now);
 +    }
  
      /* if we have enough dir info, then update our guard status with
       * whatever we just learned. */
@@@ -917,8 -744,7 +917,8 @@@ run_connection_housekeeping(int i, time
    int past_keepalive =
      now >= conn->timestamp_lastwritten + options->KeepalivePeriod;
  
 -  if (conn->outbuf && !buf_datalen(conn->outbuf) && conn->type == CONN_TYPE_OR)
 +  if (conn->outbuf && !connection_get_outbuf_len(conn) &&
 +      conn->type == CONN_TYPE_OR)
      TO_OR_CONN(conn)->timestamp_lastempty = now;
  
    if (conn->marked_for_close) {
@@@ -938,7 -764,7 +938,7 @@@
      /* This check is temporary; it's to let us know whether we should consider
       * parsing partial serverdesc responses. */
      if (conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC &&
 -        buf_datalen(conn->inbuf)>=1024) {
 +        connection_get_inbuf_len(conn) >= 1024) {
        log_info(LD_DIR,"Trying to extract information from wedged server desc "
                 "download.");
        connection_dir_reached_eof(TO_DIR_CONN(conn));
@@@ -955,11 -781,7 +955,11 @@@
       the connection or send a keepalive, depending. */
  
    or_conn = TO_OR_CONN(conn);
 +#ifdef USE_BUFFEREVENTS
 +  tor_assert(conn->bufev);
 +#else
    tor_assert(conn->outbuf);
 +#endif
  
    if (or_conn->is_bad_for_new_circs && !or_conn->n_circuits) {
      /* It's bad for new circuits, and has no unmarked circuits on it:
@@@ -971,7 -793,8 +971,7 @@@
        connection_or_connect_failed(TO_OR_CONN(conn),
                                     END_OR_CONN_REASON_TIMEOUT,
                                     "Tor gave up on the connection");
 -    connection_mark_for_close(conn);
 -    conn->hold_open_until_flushed = 1;
 +    connection_mark_and_flush(conn);
    } else if (!connection_state_is_open(conn)) {
      if (past_keepalive) {
        /* We never managed to actually get this connection open and happy. */
@@@ -980,12 -803,13 +980,12 @@@
        connection_mark_for_close(conn);
      }
    } else if (we_are_hibernating() && !or_conn->n_circuits &&
 -             !buf_datalen(conn->outbuf)) {
 +             !connection_get_outbuf_len(conn)) {
      /* We're hibernating, there's no circuits, and nothing to flush.*/
      log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) "
               "[Hibernating or exiting].",
               conn->s,conn->address, conn->port);
 -    connection_mark_for_close(conn);
 -    conn->hold_open_until_flushed = 1;
 +    connection_mark_and_flush(conn);
    } else if (!or_conn->n_circuits &&
               now >= or_conn->timestamp_last_added_nonpadding +
                                           IDLE_OR_CONN_TIMEOUT) {
@@@ -993,6 -817,7 +993,6 @@@
               "[idle %d].", conn->s,conn->address, conn->port,
               (int)(now - or_conn->timestamp_last_added_nonpadding));
      connection_mark_for_close(conn);
 -    conn->hold_open_until_flushed = 1;
    } else if (
        now >= or_conn->timestamp_lastempty + options->KeepalivePeriod*10 &&
        now >= conn->timestamp_lastwritten + options->KeepalivePeriod*10) {
@@@ -1000,10 -825,10 +1000,10 @@@
             "Expiring stuck OR connection to fd %d (%s:%d). (%d bytes to "
             "flush; %d seconds since last write)",
             conn->s, conn->address, conn->port,
 -           (int)buf_datalen(conn->outbuf),
 +           (int)connection_get_outbuf_len(conn),
             (int)(now-conn->timestamp_lastwritten));
      connection_mark_for_close(conn);
 -  } else if (past_keepalive && !buf_datalen(conn->outbuf)) {
 +  } else if (past_keepalive && !connection_get_outbuf_len(conn)) {
      /* send a padding cell */
      log_fn(LOG_DEBUG,LD_OR,"Sending keepalive to (%s:%d)",
             conn->address, conn->port);
@@@ -1047,7 -872,6 +1047,7 @@@ run_scheduled_events(time_t now
    static time_t time_to_check_for_expired_networkstatus = 0;
    static time_t time_to_write_stats_files = 0;
    static time_t time_to_write_bridge_stats = 0;
 +  static time_t time_to_check_port_forwarding = 0;
    static int should_init_bridge_stats = 1;
    static time_t time_to_retry_dns_init = 0;
    or_options_t *options = get_options();
@@@ -1061,16 -885,6 +1061,16 @@@
     */
    consider_hibernation(now);
  
 +#if 0
 +  {
 +    static time_t nl_check_time = 0;
 +    if (nl_check_time <= now) {
 +      nodelist_assert_ok();
 +      nl_check_time = now + 30;
 +    }
 +  }
 +#endif
 +
    /* 0b. If we've deferred a signewnym, make sure it gets handled
     * eventually. */
    if (signewnym_is_pending &&
@@@ -1101,7 -915,6 +1101,7 @@@
    if (time_to_try_getting_descriptors < now) {
      update_router_descriptor_downloads(now);
      update_extrainfo_downloads(now);
 +    update_microdesc_downloads(now);
      if (options->UseBridges)
        fetch_bridge_descriptors(options, now);
      if (router_have_minimum_dir_info())
@@@ -1221,11 -1034,6 +1221,11 @@@
        if (next_write && next_write < next_time_to_write_stats_files)
          next_time_to_write_stats_files = next_write;
      }
 +    if (options->ConnDirectionStatistics) {
 +      time_t next_write = rep_hist_conn_stats_write(time_to_write_stats_files);
 +      if (next_write && next_write < next_time_to_write_stats_files)
 +        next_time_to_write_stats_files = next_write;
 +    }
      time_to_write_stats_files = next_time_to_write_stats_files;
    }
  
@@@ -1306,7 -1114,7 +1306,7 @@@
          /* If we haven't checked for 12 hours and our bandwidth estimate is
           * low, do another bandwidth test. This is especially important for
           * bridges, since they might go long periods without much use. */
 -        routerinfo_t *me = router_get_my_routerinfo();
 +        const routerinfo_t *me = router_get_my_routerinfo();
          if (time_to_recheck_bandwidth && me &&
              me->bandwidthcapacity < me->bandwidthrate &&
              me->bandwidthcapacity < 51200) {
@@@ -1429,17 -1237,6 +1429,17 @@@
  #define BRIDGE_STATUSFILE_INTERVAL (30*60)
      time_to_write_bridge_status_file = now+BRIDGE_STATUSFILE_INTERVAL;
    }
 +
 +  if (time_to_check_port_forwarding < now &&
 +      options->PortForwarding &&
 +      server_mode(options)) {
 +#define PORT_FORWARDING_CHECK_INTERVAL 5
 +    tor_check_port_forwarding(options->PortForwardingHelper,
 +                              options->DirPort,
 +                              options->ORPort,
 +                              now);
 +    time_to_check_port_forwarding = now+PORT_FORWARDING_CHECK_INTERVAL;
 +  }
  }
  
  /** Timer: used to invoke second_elapsed_callback() once per second. */
@@@ -1459,9 -1256,6 +1459,9 @@@ second_elapsed_callback(periodic_timer_
    size_t bytes_written;
    size_t bytes_read;
    int seconds_elapsed;
 +#ifdef USE_BUFFEREVENTS
 +  uint64_t cur_read,cur_written;
 +#endif
    or_options_t *options = get_options();
    (void)timer;
    (void)arg;
@@@ -1473,15 -1267,9 +1473,15 @@@
    update_approx_time(now);
  
    /* the second has rolled over. check more stuff. */
 +  seconds_elapsed = current_second ? (int)(now - current_second) : 0;
 +#ifdef USE_BUFFEREVENTS
 +  connection_get_rate_limit_totals(&cur_read, &cur_written);
 +  bytes_written = (size_t)(cur_written - stats_prev_n_written);
 +  bytes_read = (size_t)(cur_read - stats_prev_n_read);
 +#else
    bytes_written = stats_prev_global_write_bucket - global_write_bucket;
    bytes_read = stats_prev_global_read_bucket - global_read_bucket;
 -  seconds_elapsed = current_second ? (int)(now - current_second) : 0;
 +#endif
    stats_n_bytes_read += bytes_read;
    stats_n_bytes_written += bytes_written;
    if (accounting_is_enabled(options) && seconds_elapsed >= 0)
@@@ -1491,13 -1279,8 +1491,13 @@@
  
    if (seconds_elapsed > 0)
      connection_bucket_refill(seconds_elapsed, now);
 +#ifdef USE_BUFFEREVENTS
 +  stats_prev_n_written = cur_written;
 +  stats_prev_n_read = cur_read;
 +#else
    stats_prev_global_read_bucket = global_read_bucket;
    stats_prev_global_write_bucket = global_write_bucket;
 +#endif
  
    if (server_mode(options) &&
        !we_are_hibernating() &&
@@@ -1507,7 -1290,7 +1507,7 @@@
        (stats_n_seconds_working+seconds_elapsed) /
          TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT) {
      /* every 20 minutes, check and complain if necessary */
 -    routerinfo_t *me = router_get_my_routerinfo();
 +    const routerinfo_t *me = router_get_my_routerinfo();
      if (me && !check_whether_orport_reachable()) {
        log_warn(LD_CONFIG,"Your server (%s:%d) has not managed to confirm that "
                 "its ORPort is reachable. Please check your firewalls, ports, "
@@@ -1698,10 -1481,8 +1698,10 @@@ do_main_loop(void
  
    /* Set up our buckets */
    connection_bucket_init();
 +#ifndef USE_BUFFEREVENTS
    stats_prev_global_read_bucket = global_read_bucket;
    stats_prev_global_write_bucket = global_write_bucket;
 +#endif
  
    /* initialize the bootstrap status events to know we're starting up */
    control_event_bootstrap(BOOTSTRAP_STATUS_STARTING, 0);
@@@ -1862,13 -1643,11 +1862,13 @@@ signal_callback(int fd, short events, v
      case SIGUSR1:
        /* prefer to log it at INFO, but make sure we always see it */
        dumpstats(get_min_log_level()<LOG_INFO ? get_min_log_level() : LOG_INFO);
 +      control_event_signal(sig);
        break;
      case SIGUSR2:
        switch_logs_debug();
        log_debug(LD_GENERAL,"Caught USR2, going to loglevel debug. "
                  "Send HUP to change back.");
 +      control_event_signal(sig);
        break;
      case SIGHUP:
        if (do_hup() < 0) {
@@@ -1876,7 -1655,6 +1876,7 @@@
          tor_cleanup();
          exit(1);
        }
 +      control_event_signal(sig);
        break;
  #ifdef SIGCHLD
      case SIGCHLD:
@@@ -1893,13 -1671,11 +1893,13 @@@
              (int)(MAX_SIGNEWNYM_RATE+time_of_last_signewnym-now));
        } else {
          signewnym_impl(now);
 +        control_event_signal(sig);
        }
        break;
      }
      case SIGCLEARDNSCACHE:
        addressmap_clear_transient();
 +      control_event_signal(sig);
        break;
    }
  }
@@@ -1950,13 -1726,13 +1950,13 @@@ dumpstats(int severity
        log(severity,LD_GENERAL,
            "Conn %d: %d bytes waiting on inbuf (len %d, last read %d secs ago)",
            i,
 -          (int)buf_datalen(conn->inbuf),
 +          (int)connection_get_inbuf_len(conn),
            (int)buf_allocation(conn->inbuf),
            (int)(now - conn->timestamp_lastread));
        log(severity,LD_GENERAL,
            "Conn %d: %d bytes waiting on outbuf "
            "(len %d, last written %d secs ago)",i,
 -          (int)buf_datalen(conn->outbuf),
 +          (int)connection_get_outbuf_len(conn),
            (int)buf_allocation(conn->outbuf),
            (int)(now - conn->timestamp_lastwritten));
        if (conn->type == CONN_TYPE_OR) {
@@@ -2253,7 -2029,6 +2253,7 @@@ tor_free_all(int postfork
    connection_free_all();
    buf_shrink_freelists(1);
    memarea_clear_freelist();
 +  nodelist_free_all();
    microdesc_free_all();
    if (!postfork) {
      config_free_all();
@@@ -2419,6 -2194,19 +2419,19 @@@ tor_main(int argc, char *argv[]
    }
  #endif
  
+ #ifdef MS_WINDOWS
+   /* Call SetProcessDEPPolicy to permanently enable DEP.
+      The function will not resolve on earlier versions of Windows,
+      and failure is not dangerous. */
+   HMODULE hMod = GetModuleHandleA("Kernel32.dll");
+   if (hMod) {
+     typedef BOOL (WINAPI *PSETDEP)(DWORD);
+     PSETDEP setdeppolicy = (PSETDEP)GetProcAddress(hMod,
+                            "SetProcessDEPPolicy");
+     if (setdeppolicy) setdeppolicy(1); /* PROCESS_DEP_ENABLE */
+   }
+ #endif
+ 
    update_approx_time(time(NULL));
    tor_threads_init();
    init_logging();