summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAzat Khuzhin <azat@libevent.org>2019-02-10 16:23:11 +0300
committerAzat Khuzhin <azat@libevent.org>2019-02-10 16:23:58 +0300
commit9c75c24caa7689c010864579e27b159665c8dd63 (patch)
treef1927df666ed30684005191765cb07da857984b3
parente7ff4ef2b4fc950a765008c18e74281cdb5e7668 (diff)
parent900f5c4503208c654c0e9ef64ac196c0deac5c18 (diff)
downloadlibevent-release-2.1.9-beta.tar.gz
Merge branch 'release-2.1.9-beta-pull' into patches-2.1release-2.1.9-beta
* release-2.1.9-beta-pull: Bump version to 2.1.9-beta everywhere Bump ChangeLog Bump AUTHORS section ... Tested on (cmake/autotools): - ubuntu - freebsd - osx - windows - netbsd - solaris - centos Closes: #744
-rw-r--r--.gitignore45
-rw-r--r--.mailmap5
-rw-r--r--.travis.yml42
-rw-r--r--CMakeLists.txt838
-rw-r--r--ChangeLog136
-rw-r--r--Makefile.am42
-rw-r--r--README.md121
-rw-r--r--WIN32-Code/nmake/event2/event-config.h26
-rw-r--r--appveyor.yml94
-rw-r--r--buffer.c13
-rw-r--r--bufferevent-internal.h36
-rw-r--r--bufferevent.c81
-rw-r--r--bufferevent_async.c65
-rw-r--r--bufferevent_filter.c10
-rw-r--r--bufferevent_openssl.c72
-rw-r--r--bufferevent_pair.c4
-rw-r--r--bufferevent_ratelim.c9
-rw-r--r--bufferevent_sock.c74
-rw-r--r--cmake/AddEventLibrary.cmake125
-rw-r--r--cmake/CheckConstExists.cmake25
-rw-r--r--cmake/CheckFunctionExistsEx.c28
-rw-r--r--cmake/CheckWaitpidSupportWNOWAIT.cmake18
-rw-r--r--cmake/CheckWorkingKqueue.cmake6
-rw-r--r--cmake/LibeventConfig.cmake.in9
-rw-r--r--cmake/VersionViaGit.cmake33
-rw-r--r--configure.ac94
-rw-r--r--defer-internal.h3
-rw-r--r--epoll.c9
-rw-r--r--epolltable-internal.h2
-rw-r--r--evbuffer-internal.h2
-rw-r--r--evconfig-private.h.cmake5
-rw-r--r--evconfig-private.h.in7
-rw-r--r--evdns.c21
-rw-r--r--event-config.h.cmake316
-rw-r--r--event-internal.h11
-rw-r--r--event.c357
-rw-r--r--event_iocp.c2
-rwxr-xr-xevent_rpcgen.py177
-rw-r--r--event_tagging.c4
-rw-r--r--evmap.c29
-rw-r--r--evrpc.c3
-rw-r--r--evthread-internal.h14
-rw-r--r--evthread.c2
-rw-r--r--evutil.c79
-rw-r--r--evutil_rand.c2
-rw-r--r--evutil_time.c7
-rw-r--r--http-internal.h4
-rw-r--r--http.c213
-rw-r--r--include/event2/bufferevent.h3
-rw-r--r--include/event2/bufferevent_compat.h4
-rw-r--r--include/event2/dns.h5
-rw-r--r--include/event2/dns_compat.h24
-rw-r--r--include/event2/event.h52
-rw-r--r--include/event2/http.h13
-rw-r--r--include/event2/http_compat.h6
-rw-r--r--include/event2/listener.h12
-rw-r--r--include/event2/rpc.h48
-rw-r--r--include/event2/rpc_struct.h14
-rw-r--r--include/event2/util.h25
-rw-r--r--include/event2/visibility.h31
-rw-r--r--iocp-internal.h14
-rw-r--r--listener.c28
-rw-r--r--log-internal.h25
-rw-r--r--log.c11
-rw-r--r--m4/libevent_openssl.m44
-rw-r--r--make-event-config.sed10
-rw-r--r--mm-internal.h5
-rw-r--r--openssl-compat.h13
-rw-r--r--sample/dns-example.c13
-rw-r--r--sample/http-connect.c6
-rw-r--r--sample/http-server.c136
-rw-r--r--sample/https-client.c36
-rw-r--r--sample/include.am8
-rw-r--r--sample/le-proxy.c5
-rw-r--r--sample/openssl_hostname_validation.c3
-rw-r--r--strlcpy-internal.h2
-rw-r--r--test/bench.c4
-rw-r--r--test/bench_cascade.c8
-rw-r--r--test/bench_http.c3
-rw-r--r--test/bench_httpclient.c4
-rwxr-xr-xtest/check-dumpevents.py10
-rw-r--r--test/include.am41
-rw-r--r--test/regress.c167
-rw-r--r--test/regress.h6
-rw-r--r--test/regress_bufferevent.c94
-rw-r--r--test/regress_dns.c360
-rw-r--r--test/regress_et.c144
-rw-r--r--test/regress_http.c404
-rw-r--r--test/regress_listener.c98
-rw-r--r--test/regress_main.c11
-rw-r--r--test/regress_rpc.c49
-rw-r--r--test/regress_ssl.c391
-rw-r--r--test/regress_thread.c8
-rw-r--r--test/regress_thread.h1
-rw-r--r--test/regress_util.c89
-rwxr-xr-xtest/rpcgen_wrapper.sh11
-rw-r--r--test/test-fdleak.c15
-rwxr-xr-xtest/test.sh4
-rw-r--r--test/tinytest.c37
-rw-r--r--test/tinytest.h5
-rw-r--r--test/tinytest_demo.c30
-rw-r--r--test/tinytest_macros.h8
-rw-r--r--time-internal.h3
-rw-r--r--util-internal.h66
-rw-r--r--win32select.c2
105 files changed, 3997 insertions, 1952 deletions
diff --git a/.gitignore b/.gitignore
index 99610045..4af03587 100644
--- a/.gitignore
+++ b/.gitignore
@@ -84,9 +84,6 @@ cscope*
/stamp-h1
/stamp-h2
-/include/event2/event-config.h
-/evconfig-private.h
-
/sample/dns-example
/sample/event-read-fifo
/sample/hello-world
@@ -118,29 +115,37 @@ cscope*
/test/test-changelist
/test/test-fdleak
+**/include/event2/event-config.h
+**/include/evconfig-private.h
+/evconfig-private.h
# Files generated by cmake
-/CMakeCache.txt
-/CMakeFiles/
-/CTestTestfile.cmake
-/DartConfiguration.tcl
-/LibeventConfig.cmake
-/LibeventConfigVersion.cmake
-/LibeventTargets.cmake
-/bin/
-/cmake_install.cmake
-/include/evconfig-private.h
-/lib/
-/tmp/
-/verify_tests.sh
-/verify_tests.bat
-/event.dir
-/event_core.dir
-/event_extra.dir
+CMakeCache.txt
+CMakeFiles/
+CTestTestfile.cmake
+DartConfiguration.tcl
+LibeventConfig.cmake
+LibeventConfigVersion.cmake
+LibeventTargets.cmake
+bin/
+cmake_install.cmake
+lib/
+tmp/
+verify_tests.sh
+verify_tests.bat
+event.dir
+event_core.dir
+event_extra.dir
*.vcxproj
*.sln
*.filters
+# ninja
+build.ninja
+rules.ninja
+.ninja_deps
+.ninja_log
+
# make dist
/COPYING
/INSTALL
diff --git a/.mailmap b/.mailmap
new file mode 100644
index 00000000..0aec4646
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1,5 @@
+# name -> email
+Azat Khuzhin <azat@libevent.org>
+
+# email -> email
+<azat@libevent.org> <a3at.mail@gmail.com>
diff --git a/.travis.yml b/.travis.yml
index cc370e9f..f7bd6d85 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,6 +3,17 @@ os:
- osx
sudo: false
dist: trusty
+osx_image: xcode10.1
+
+branches:
+ except:
+ - /.*appveyor.*/
+ - /.*win.*/
+ - /.*mingw.*/
+ - /.*freebsd.*/
+
+git:
+ quiet: true
env:
matrix:
@@ -12,31 +23,38 @@ env:
- EVENT_BUILD_METHOD=cmake EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_THREAD_SUPPORT=ON"
- EVENT_BUILD_METHOD=cmake EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_DEBUG_MODE=ON"
- EVENT_BUILD_METHOD=cmake EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_MM_REPLACEMENT=ON"
- - EVENT_BUILD_METHOD=cmake EVENT_CMAKE_OPTIONS="-DEVENT__ENABLE_VERBOSE_DEBUG=ON"
- EVENT_BUILD_METHOD=autotools EVENT_CONFIGURE_OPTIONS=""
- EVENT_BUILD_METHOD=autotools EVENT_CONFIGURE_OPTIONS="--disable-openssl"
- EVENT_BUILD_METHOD=autotools EVENT_CONFIGURE_OPTIONS="--disable-thread-support"
- EVENT_BUILD_METHOD=autotools EVENT_CONFIGURE_OPTIONS="--disable-debug-mode"
- EVENT_BUILD_METHOD=autotools EVENT_CONFIGURE_OPTIONS="--disable-malloc-replacement"
+matrix:
+ exclude:
+ - os: osx
+ env: EVENT_BUILD_METHOD=cmake EVENT_CMAKE_OPTIONS="-DEVENT__COVERAGE=ON -DCMAKE_BUILD_TYPE=debug" COVERALLS=yes
+ allow_failures:
+ - os: osx
+ fast_finish: true
+
language: c
compiler:
- gcc
- clang
before_install:
+ # do not run with clang, since it fails (SIGSEGV)
+ - if [ "$CC" = "clang" ]; then
+ unset COVERALLS;
+ fi
- if [ -n "$COVERALLS" ]; then
pip install --user cpp-coveralls;
fi
- export JOBS=20
- export TIMEOUT=50
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then
- brew update;
- brew uninstall libtool && brew install libtool;
- brew install openssl;
- brew install lcov;
if [ "$CC" == "gcc" ]; then
- export CC=$(ls -t /usr/local/bin/gcc-?.?);
+ export CC=$(ls /usr/local/Cellar/gcc/*/bin/gcc-?);
fi
export OPENSSL_ROOT=$(echo /usr/local/Cellar/openssl/*);
@@ -47,7 +65,7 @@ before_install:
CFLAGS=-I$CMAKE_INCLUDE_PATH
LDFLAGS=-L$CMAKE_LIBRARY_PATH;
- export JOBS=4;
+ export JOBS=1;
fi
addons:
@@ -63,6 +81,13 @@ addons:
- autoconf
- cmake
- lcov
+ homebrew:
+ packages:
+ - openssl
+ - lcov
+ - libtool
+ - gcc
+
script:
- if [ "$EVENT_BUILD_METHOD" = "autotools" ]; then
@@ -95,6 +120,3 @@ after_script:
--exclude build/CMakeFiles/CompilerIdC
--gcov-options '\-lp';
fi
-
-notifications:
- irc: "irc.oftc.net#libevent"
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b4a34f3d..98082cde 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -18,10 +18,17 @@
# cmake -G "Visual Studio 10" ..
# start libevent.sln
#
-if (WIN32)
- cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
-else()
- cmake_minimum_required(VERSION 2.8.0 FATAL_ERROR)
+
+cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
+
+if (POLICY CMP0054)
+ cmake_policy(SET CMP0054 NEW)
+endif()
+if (POLICY CMP0074)
+ cmake_policy(SET CMP0074 NEW)
+endif()
+if (POLICY CMP0075)
+ cmake_policy(SET CMP0075 NEW)
endif()
if(NOT CMAKE_BUILD_TYPE)
@@ -34,6 +41,9 @@ string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
# what? why would you get id of other useful build types? - Ellzey
set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "Limited configurations" FORCE)
+set(EVENT__LIBRARY_TYPE DEFAULT CACHE STRING
+ "Set library type to SHARED/STATIC/BOTH (default SHARED for MSVC, otherwise BOTH)")
+
project(libevent C)
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/")
@@ -52,6 +62,7 @@ include(CheckStructHasMember)
include(CheckCSourceCompiles)
include(CheckPrototypeDefinition)
include(CheckFunctionKeywords)
+include(CheckConstExists)
include(AddCompilerFlags)
include(VersionViaGit)
@@ -73,37 +84,34 @@ set(EVENT_ABI_LIBVERSION
set(EVENT_PACKAGE_VERSION
"${EVENT_VERSION_MAJOR}.${EVENT_VERSION_MINOR}.${EVENT_VERSION_PATCH}")
-set(EVENT_NUMERIC_VERSION 0x02010800)
+set(EVENT_NUMERIC_VERSION 0x02010900)
# only a subset of names can be used, defaults to "beta"
-set(EVENT_STAGE_NAME ${EVENT_VERSION_STAGE}
- CACHE STRING "set the stage name (beta|alpha|release)")
+set(EVENT_STAGE_NAME ${EVENT_VERSION_STAGE})
# a list that defines what can set for EVENT_STAGE_VERSION
set(EVENT__ALLOWED_STAGE_NAMES
- rc
- beta
- alpha
- release)
-
-# attempt to find the EVENT__STAGE_VERSION in the allowed list
-# of accepted stage names, the return value is stord in
-# EVENT__STAGE_RET
-
-list(FIND EVENT__ALLOWED_STAGE_NAMES
- ${EVENT_STAGE_NAME}
- EVENT__STAGE_RET)
-
-if (EVENT__STAGE_RET EQUAL "-1")
+ rc
+ beta
+ alpha
+ alpha-dev
+ release
+ stable
+)
+list(
+ FIND EVENT__ALLOWED_STAGE_NAMES
+ "${EVENT_STAGE_NAME}"
+ EVENT__STAGE_RET
+)
+if (EVENT__STAGE_RET EQUAL -1)
+ message(WARNING
+ "stage ${EVENT_STAGE_NAME} is not allowed, reset to beta")
set(EVENT_STAGE_NAME beta)
endif()
set(EVENT_VERSION
"${EVENT_VERSION_MAJOR}.${EVENT_VERSION_MINOR}.${EVENT_VERSION_PATCH}-${EVENT_STAGE_NAME}")
-option(EVENT__BUILD_SHARED_LIBRARIES
- "Define if libevent should be built with shared libraries instead of archives" OFF)
-
option(EVENT__DISABLE_DEBUG_MODE
"Define if libevent should build without support for a debug mode" OFF)
@@ -117,10 +125,10 @@ option(EVENT__DISABLE_THREAD_SUPPORT
"Define if libevent should not be compiled with thread support" OFF)
option(EVENT__DISABLE_OPENSSL
- "Define if libevent should build without support for OpenSSL encrpytion" OFF)
+ "Define if libevent should build without support for OpenSSL encryption" OFF)
option(EVENT__DISABLE_BENCHMARK
- "Defines if libevent should build without the benchmark exectuables" OFF)
+ "Defines if libevent should build without the benchmark executables" OFF)
option(EVENT__DISABLE_TESTS
"If tests should be compiled or not" OFF)
@@ -135,7 +143,7 @@ option(EVENT__DISABLE_CLOCK_GETTIME
"Do not use clock_gettime even if it is available" OFF)
option(EVENT__FORCE_KQUEUE_CHECK
- "When crosscompiling forces running a test program that verifies that Kqueue works with pipes. Note that this requires you to manually run the test program on the the cross compilation target to verify that it works. See cmake documentation for try_run for more details" OFF)
+ "When crosscompiling forces running a test program that verifies that Kqueue works with pipes. Note that this requires you to manually run the test program on the cross compilation target to verify that it works. See cmake documentation for try_run for more details" OFF)
# TODO: Add --disable-largefile omit support for large files
option(EVENT__COVERAGE
@@ -151,6 +159,11 @@ if (EVENT__ENABLE_VERBOSE_DEBUG)
add_definitions(-DUSE_DEBUG=1)
endif()
+# make it colorful under ninja-build
+if ("${CMAKE_GENERATOR}" STREQUAL "Ninja")
+ add_compiler_flags(-fdiagnostics-color=always)
+endif()
+
# Setup compiler flags for coverage.
if (EVENT__COVERAGE)
if (NOT "${CMAKE_BUILD_TYPE_LOWER}" STREQUAL "debug")
@@ -164,14 +177,106 @@ if (EVENT__COVERAGE)
set(CMAKE_REQUIRED_LIBRARIES "")
endif()
-# GCC specific options.
-if (CMAKE_COMPILER_IS_GNUCC)
+set(GNUC 0)
+set(CLANG 0)
+set(MSVC 0)
+if (("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") OR
+ ("${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang"))
+ set(CLANG 1)
+endif()
+if (("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") OR (${CLANG}))
+ set(GNUC 1)
+endif()
+if (("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC") OR (${CLANG}))
+ set(MSVC 1)
+endif()
+
+# Detect library type
+set(EVENT_LIBRARY_TYPE)
+if ("${EVENT__LIBRARY_TYPE}" STREQUAL "DEFAULT")
+ if (${MSVC})
+ set(EVENT_LIBRARY_TYPE SHARED)
+ else()
+ set(EVENT_LIBRARY_TYPE BOTH)
+ endif()
+else()
+ string(TOUPPER "${EVENT__LIBRARY_TYPE}" EVENT_LIBRARY_TYPE)
+endif()
+if ((${MSVC}) AND ("${EVENT_LIBRARY_TYPE}" STREQUAL "BOTH"))
+ message(WARNING
+ "Building SHARED and STATIC is not supported for MSVC "
+ "(due to conflicts in library name"
+ " between STATIC library and IMPORTED library for SHARED libraries)")
+endif()
+set(EVENT_LIBRARY_STATIC OFF)
+set(EVENT_LIBRARY_SHARED OFF)
+if ("${EVENT_LIBRARY_TYPE}" STREQUAL "BOTH")
+ set(EVENT_LIBRARY_STATIC ON)
+ set(EVENT_LIBRARY_SHARED ON)
+elseif ("${EVENT_LIBRARY_TYPE}" STREQUAL "STATIC")
+ set(EVENT_LIBRARY_STATIC ON)
+elseif ("${EVENT_LIBRARY_TYPE}" STREQUAL "SHARED")
+ set(EVENT_LIBRARY_SHARED ON)
+else()
+ message(FATAL_ERROR "${EVENT_LIBRARY_TYPE} is not supported")
+endif()
+
+if (${MSVC})
+ set(msvc_static_runtime OFF)
+ if ("${EVENT_LIBRARY_TYPE}" STREQUAL "STATIC")
+ set(msvc_static_runtime ON)
+ endif()
+
+ # For more info:
+ # - https://docs.microsoft.com/en-us/cpp/build/reference/md-mt-ld-use-run-time-library?view=vs-2017
+ # - https://gitlab.kitware.com/cmake/community/wikis/FAQ#how-can-i-build-my-msvc-application-with-a-static-runtime
+ option(EVENT__MSVC_STATIC_RUNTIME
+ "Link static runtime libraries"
+ ${msvc_static_runtime})
+
+ if (EVENT__MSVC_STATIC_RUNTIME)
+ foreach (flag_var
+ CMAKE_C_FLAGS
+ CMAKE_C_FLAGS_DEBUG
+ CMAKE_C_FLAGS_RELEASE
+ CMAKE_C_FLAGS_MINSIZEREL
+ CMAKE_C_FLAGS_RELWITHDEBINFO
+ )
+ if (${flag_var} MATCHES "/MD")
+ string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
+ endif()
+ endforeach()
+ endif()
+endif()
+
+# GNUC specific options.
+if (${GNUC})
option(EVENT__DISABLE_GCC_WARNINGS "Disable verbose warnings with GCC" OFF)
option(EVENT__ENABLE_GCC_HARDENING "Enable compiler security checks" OFF)
option(EVENT__ENABLE_GCC_FUNCTION_SECTIONS "Enable gcc function sections" OFF)
option(EVENT__ENABLE_GCC_WARNINGS "Make all GCC warnings into errors" OFF)
- list(APPEND __FLAGS -Wall -Wswitch)
+ set(GCC_V ${CMAKE_C_COMPILER_VERSION})
+
+ list(APPEND __FLAGS
+ -Wall -Wextra -Wno-unused-parameter -Wstrict-aliasing
+
+ -fno-strict-aliasing # gcc 2.9.5+
+
+ # gcc 4
+ -Winit-self
+ -Wmissing-field-initializers
+ -Wdeclaration-after-statement
+
+ # gcc 4.2
+ -Waddress
+ -Wno-unused-function
+ -Wnormalized=id
+ -Woverride-init
+
+ # gcc 4.5
+ -Wlogical-op
+ )
if (EVENT__DISABLE_GCC_WARNINGS)
list(APPEND __FLAGS -w)
@@ -197,10 +302,6 @@ if (CMAKE_COMPILER_IS_GNUCC)
list(APPEND __FLAGS -Werror)
endif()
- # We need to test for at least gcc 2.95 here, because older versions don't
- # have -fno-strict-aliasing
- list(APPEND __FLAGS -fno-strict-aliasing)
-
add_compiler_flags(${__FLAGS})
endif()
@@ -223,7 +324,14 @@ if (SOLARIS)
endif()
# Check if _GNU_SOURCE is available.
-CHECK_SYMBOL_EXISTS(__GNU_LIBRARY__ "features.h" _GNU_SOURCE)
+if (NOT DEFINED _GNU_SOURCE)
+ CHECK_SYMBOL_EXISTS(__GNU_LIBRARY__ "features.h" _GNU_SOURCE)
+
+ if (NOT _GNU_SOURCE)
+ unset(_GNU_SOURCE CACHE)
+ CHECK_SYMBOL_EXISTS(_GNU_SOURCE "features.h" _GNU_SOURCE)
+ endif()
+endif()
if (_GNU_SOURCE)
add_definitions(-D_GNU_SOURCE)
@@ -271,7 +379,7 @@ CHECK_INCLUDE_FILE(stdint.h EVENT__HAVE_STDINT_H)
CHECK_INCLUDE_FILE(stdlib.h EVENT__HAVE_STDLIB_H)
CHECK_INCLUDE_FILE(strings.h EVENT__HAVE_STRINGS_H)
CHECK_INCLUDE_FILE(string.h EVENT__HAVE_STRING_H)
-CHECK_INCLUDE_FILE(sys/devpoll.h EVENT__HAVE_SYS_DEVPOLL_H)
+CHECK_INCLUDE_FILE(sys/devpoll.h EVENT__HAVE_DEVPOLL)
CHECK_INCLUDE_FILE(sys/epoll.h EVENT__HAVE_SYS_EPOLL_H)
CHECK_INCLUDE_FILE(sys/eventfd.h EVENT__HAVE_SYS_EVENTFD_H)
CHECK_INCLUDE_FILE(sys/event.h EVENT__HAVE_SYS_EVENT_H)
@@ -330,6 +438,7 @@ CHECK_FUNCTION_EXISTS_EX(sysctl EVENT__HAVE_SYSCTL)
CHECK_FUNCTION_EXISTS_EX(accept4 EVENT__HAVE_ACCEPT4)
CHECK_FUNCTION_EXISTS_EX(arc4random EVENT__HAVE_ARC4RANDOM)
CHECK_FUNCTION_EXISTS_EX(arc4random_buf EVENT__HAVE_ARC4RANDOM_BUF)
+CHECK_FUNCTION_EXISTS_EX(arc4random_addrandom EVENT__HAVE_ARC4RANDOM_ADDRANDOM)
CHECK_FUNCTION_EXISTS_EX(epoll_create1 EVENT__HAVE_EPOLL_CREATE1)
CHECK_FUNCTION_EXISTS_EX(getegid EVENT__HAVE_GETEGID)
CHECK_FUNCTION_EXISTS_EX(geteuid EVENT__HAVE_GETEUID)
@@ -341,7 +450,7 @@ CHECK_FUNCTION_EXISTS_EX(usleep EVENT__HAVE_USLEEP)
CHECK_FUNCTION_EXISTS_EX(timeradd EVENT__HAVE_TIMERADD)
CHECK_FUNCTION_EXISTS_EX(timerclear EVENT__HAVE_TIMERCLEAR)
CHECK_FUNCTION_EXISTS_EX(timercmp EVENT__HAVE_TIMERCMP)
-CHECK_FUNCTION_EXISTS_EX(timerfd_create HAVE_TIMERFD_CREATE)
+CHECK_FUNCTION_EXISTS_EX(timerfd_create EVENT__HAVE_TIMERFD_CREATE)
CHECK_FUNCTION_EXISTS_EX(timerisset EVENT__HAVE_TIMERISSET)
CHECK_FUNCTION_EXISTS_EX(putenv EVENT__HAVE_PUTENV)
CHECK_FUNCTION_EXISTS_EX(setenv EVENT__HAVE_SETENV)
@@ -402,7 +511,7 @@ endif()
check_function_keywords("inline" "__inline" "__inline__")
if (HAVE_INLINE)
- set (EVENT__inline inline)
+ set(EVENT__inline inline)
elseif (HAVE___INLINE)
set(EVENT__inline __inline)
elseif(HAVE___INLINE__)
@@ -411,16 +520,20 @@ else()
set(EVENT__inline)
endif()
+# __func__/__FUNCTION__ is not a macros in general
+CHECK_SYMBOL_EXISTS("__func__" "" EVENT__HAVE___func__)
+CHECK_SYMBOL_EXISTS("__FUNCTION__" "" EVENT__HAVE___FUNCTION__)
+
CHECK_SYMBOL_EXISTS(TAILQ_FOREACH sys/queue.h EVENT__HAVE_TAILQFOREACH)
-CHECK_SYMBOL_EXISTS(CTL_KERN sys/sysctl.h EVENT__HAVE_DECL_CTL_KERN)
-CHECK_SYMBOL_EXISTS(KERN_ARND sys/sysctl.h EVENT__HAVE_DECL_KERN_ARND)
-CHECK_SYMBOL_EXISTS(KERN_RANDOM sys/sysctl.h EVENT__HAVE_DECL_KERN_RANDOM)
-CHECK_SYMBOL_EXISTS(RANDOM_UUID sys/sysctl.h EVENT__HAVE_DECL_RANDOM_UUID)
+CHECK_CONST_EXISTS(CTL_KERN sys/sysctl.h EVENT__HAVE_DECL_CTL_KERN)
+CHECK_CONST_EXISTS(KERN_ARND sys/sysctl.h EVENT__HAVE_DECL_KERN_ARND)
+CHECK_CONST_EXISTS(KERN_RANDOM sys/sysctl.h EVENT__HAVE_DECL_KERN_RANDOM)
+CHECK_CONST_EXISTS(RANDOM_UUID sys/sysctl.h EVENT__HAVE_DECL_RANDOM_UUID)
CHECK_SYMBOL_EXISTS(F_SETFD fcntl.h EVENT__HAVE_SETFD)
CHECK_TYPE_SIZE(fd_mask EVENT__HAVE_FD_MASK)
-CHECK_TYPE_SIZE(size_t EVENT__SIZEOF_SIZEE_T)
+CHECK_TYPE_SIZE(size_t EVENT__SIZEOF_SIZE_T)
if(NOT EVENT__SIZEOF_SIZE_T)
set(EVENT__size_t "unsigned")
set(EVENT__SIZEOF_SIZE_T ${EVENT__SIZEOF_UNSIGNED})
@@ -451,7 +564,6 @@ else()
set(EVENT__SIZEOF_SSIZE_T ${EVENT__SIZEOF_INT})
endif()
-
CHECK_TYPE_SIZE(socklen_t EVENT__SIZEOF_SOCKLEN_T)
if(NOT EVENT__SIZEOF_SOCKLEN_T)
set(EVENT__socklen_t "unsigned int")
@@ -462,14 +574,15 @@ endif()
CHECK_TYPE_SIZE(pid_t EVENT__SIZEOF_PID_T)
if(NOT EVENT__SIZEOF_PID_T)
- set(EVENT__pid_t "int")
set(EVENT__SIZEOF_PID_T ${EVENT__SIZEOF_INT})
else()
- set(EVENT__pid_t "pid_t")
set(EVENT__SIZEOF_PID_T EVENT__SIZEOF_PID_T)
endif()
if (NOT EVENT__DISABLE_THREAD_SUPPORT)
+ if (NOT WIN32)
+ list(APPEND CMAKE_EXTRA_INCLUDE_FILES pthread.h)
+ endif()
CHECK_TYPE_SIZE(pthread_t EVENT__SIZEOF_PTHREAD_T)
endif()
@@ -480,6 +593,7 @@ endif()
# we're just getting lazy now.
CHECK_TYPE_SIZE("uintptr_t" EVENT__HAVE_UINTPTR_T)
CHECK_TYPE_SIZE("void *" EVENT__SIZEOF_VOID_P)
+CHECK_TYPE_SIZE("time_t" EVENT__SIZEOF_TIME_T)
# Tests file offset bits.
# TODO: Add AIX test for if -D_LARGE_FILES is needed.
@@ -490,9 +604,6 @@ CHECK_TYPE_SIZE("void *" EVENT__SIZEOF_VOID_P)
# - ellzey
#CHECK_FILE_OFFSET_BITS()
-#set(EVENT___FILE_OFFSET_BITS _FILE_OFFSET_BITS)
-
-include(CheckWaitpidSupportWNOWAIT)
# Verify kqueue works with pipes.
if (EVENT__HAVE_KQUEUE)
@@ -505,10 +616,6 @@ if (EVENT__HAVE_KQUEUE)
endif()
endif()
-CHECK_SYMBOL_EXISTS(_MINIX "stdio.h" EVENT___MINIX)
-CHECK_SYMBOL_EXISTS(_POSIX_1_SOURCE "stdio.h" EVENT___POSIX_1_SOURCE)
-CHECK_SYMBOL_EXISTS(_POSIX_SOURCE "stdio.h" EVENT___POSIX_SOURCE)
-
if(EVENT__HAVE_NETDB_H)
list(APPEND CMAKE_EXTRA_INCLUDE_FILES netdb.h)
CHECK_TYPE_SIZE("struct addrinfo" EVENT__HAVE_STRUCT_ADDRINFO)
@@ -578,6 +685,8 @@ if(EVENT__HAVE_STRUCT_SOCKADDR_STORAGE)
__ss_family "${SOCKADDR_HEADERS}" EVENT__HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY)
endif()
+CHECK_TYPE_SIZE("struct linger" EVENT__HAVE_STRUCT_LINGER)
+
# Group the source files.
set(HDR_PRIVATE
bufferevent-internal.h
@@ -672,7 +781,7 @@ if(EVENT__HAVE_DEVPOLL)
endif()
if(EVENT__HAVE_EPOLL)
- list(APPEND SRC_CORE epoll_sub.c epoll.c)
+ list(APPEND SRC_CORE epoll.c)
endif()
if(EVENT__HAVE_EVENT_PORTS)
@@ -689,7 +798,7 @@ if (NOT EVENT__DISABLE_OPENSSL)
include_directories(${OPENSSL_INCLUDE_DIR})
- list(APPEND SRC_CORE bufferevent_openssl.c)
+ list(APPEND SRC_OPENSSL bufferevent_openssl.c)
list(APPEND HDR_PUBLIC include/event2/bufferevent_ssl.h)
list(APPEND LIB_APPS ${OPENSSL_LIBRARIES})
endif()
@@ -701,11 +810,10 @@ if (NOT EVENT__DISABLE_THREAD_SUPPORT)
find_package(Threads REQUIRED)
if (NOT CMAKE_USE_PTHREADS_INIT)
message(FATAL_ERROR
- "Failed to find Pthreads, set EVENT__DISABLE_THREAD_SUPPORT to disable")
+ "Failed to find Pthreads, set EVENT__DISABLE_THREAD_SUPPORT to disable")
endif()
set(EVENT__HAVE_PTHREADS 1)
- list(APPEND SRC_CORE evthread_pthread.c)
list(APPEND LIB_APPS ${CMAKE_THREAD_LIBS_INIT})
endif()
endif()
@@ -754,10 +862,6 @@ if(WIN32)
include_directories(./WIN32-Code)
endif()
-if (UNIX)
- list(APPEND LIB_PLATFORM m)
-endif()
-
if (SOLARIS)
list(APPEND LIB_PLATFORM socket nsl)
endif()
@@ -772,19 +876,11 @@ source_group("Source Extra" FILES ${SRC_EXTRA})
# (Place them in the build dir so we don't polute the source tree with generated files).
include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}/include)
-if (EVENT__BUILD_SHARED_LIBRARIES)
- set(EVENT__LIBRARY_TYPE SHARED)
-
- if ((CMAKE_COMPILER_IS_GNUCC) OR (${CMAKE_C_COMPILER_ID} STREQUAL "Clang"))
- add_compiler_flags(-fvisibility=hidden)
- elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "SunPro")
- add_compiler_flags(-xldscope=hidden)
- endif()
-
- set(EVENT__NEED_DLLIMPORT 1)
-else (EVENT__BUILD_SHARED_LIBRARIES)
- set(EVENT__LIBRARY_TYPE STATIC)
-endif (EVENT__BUILD_SHARED_LIBRARIES)
+if (${GNUC})
+ set(EVENT_SHARED_FLAGS -fvisibility=hidden)
+elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "SunPro")
+ set(EVENT_SHARED_FLAGS -xldscope=hidden)
+endif()
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/event-config.h.cmake
@@ -798,164 +894,132 @@ configure_file(
#
# Create the libraries.
#
+include(AddEventLibrary)
+add_event_library(event_core SOURCES ${SRC_CORE})
+add_event_library(event_extra
+ LIBRARIES event_core_shared
+ SOURCES ${SRC_EXTRA})
-# TODO: Add dynamic versions of the libraries as well.
-add_library(event_core ${EVENT__LIBRARY_TYPE}
- ${HDR_PRIVATE}
- ${HDR_COMPAT}
- ${HDR_PUBLIC}
- ${SRC_CORE})
+if (NOT EVENT__DISABLE_OPENSSL)
+ add_event_library(event_openssl
+ LIBRARIES event_core_shared ${OPENSSL_LIBRARIES}
+ SOURCES ${SRC_OPENSSL})
+endif()
-add_library(event_extra ${EVENT__LIBRARY_TYPE}
- ${HDR_PRIVATE}
- ${HDR_COMPAT}
- ${HDR_PUBLIC}
- ${SRC_CORE}
- ${SRC_EXTRA})
+if (CMAKE_USE_PTHREADS_INIT)
+ set(SRC_PTHREADS evthread_pthread.c)
+ add_event_library(event_pthreads
+ LIBRARIES event_core_shared
+ SOURCES ${SRC_PTHREADS})
+endif()
# library exists for historical reasons; it contains the contents of
# both libevent_core and libevent_extra. You shouldn’t use it; it may
# go away in a future version of Libevent.
-add_library(event ${EVENT__LIBRARY_TYPE}
- ${HDR_PRIVATE}
- ${HDR_COMPAT}
- ${HDR_PUBLIC}
- ${SRC_CORE}
- ${SRC_EXTRA})
-
-if (EVENT__BUILD_SHARED_LIBRARIES)
- # Prepare static library to be linked to tests that need hidden symbols
- add_library(event_extra_static STATIC
- ${HDR_PRIVATE}
- ${HDR_COMPAT}
- ${HDR_PUBLIC}
- ${SRC_CORE}
- ${SRC_EXTRA})
-
- set(EVENT_EXTRA_FOR_TEST event_extra_static)
-
- target_link_libraries(event_core ${OPENSSL_LIBRARIES}
- ${CMAKE_THREAD_LIBS_INIT}
- ${LIB_PLATFORM})
-
- target_link_libraries(event ${OPENSSL_LIBRARIES}
- ${CMAKE_THREAD_LIBS_INIT}
- ${LIB_PLATFORM})
-
- target_link_libraries(event_extra ${OPENSSL_LIBRARIES}
- ${CMAKE_THREAD_LIBS_INIT}
- ${LIB_PLATFORM})
-
- set_target_properties(event
- PROPERTIES SOVERSION
- ${EVENT_ABI_LIBVERSION})
-
- set_target_properties(event_core
- PROPERTIES SOVERSION
- ${EVENT_ABI_LIBVERSION})
-
- set_target_properties(event_extra
- PROPERTIES SOVERSION
- ${EVENT_ABI_LIBVERSION})
-
-else (EVENT__BUILD_SHARED_LIBRARIES)
- set(EVENT_EXTRA_FOR_TEST event_extra)
-endif (EVENT__BUILD_SHARED_LIBRARIES)
+add_event_library(event SOURCES ${SRC_CORE} ${SRC_EXTRA})
+
+set(WIN32_GETOPT)
+if (WIN32)
+ list(APPEND WIN32_GETOPT
+ WIN32-Code/getopt.c
+ WIN32-Code/getopt_long.c)
+endif()
#
# Samples.
#
+macro(add_sample_prog ssl name)
+ add_executable(${name} ${ARGN})
+
+ target_link_libraries(${name}
+ event_extra
+ event_core
+ ${LIB_APPS}
+ ${LIB_PLATFORM})
+ if (${ssl})
+ target_link_libraries(${name} event_openssl)
+ endif()
+endmacro()
if (NOT EVENT__DISABLE_SAMPLES)
set(SAMPLES
- dns-example
event-read-fifo
hello-world
signal-test
- http-server
http-connect
time-test)
- if (NOT EVENT__DISABLE_OPENSSL AND OPENSSL_LIBRARIES)
- set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_LIBRARIES})
- CHECK_FUNCTION_EXISTS_EX(ERR_remove_thread_state EVENT__HAVE_ERR_REMOVE_THREAD_STATE)
- set(CMAKE_REQUIRED_LIBRARIES "")
-
- # Special sample with more than one file.
- add_executable(https-client
- sample/https-client.c
- sample/openssl_hostname_validation.c
- sample/hostcheck.c)
-
- target_link_libraries(https-client
- event_extra
- ${LIB_APPS}
- ${LIB_PLATFORM})
-
- add_dependencies(https-client event_extra)
-
- # Requires OpenSSL.
- list(APPEND SAMPLES le-proxy)
- endif()
-
foreach(SAMPLE ${SAMPLES})
- add_executable(${SAMPLE}
- sample/${SAMPLE}.c)
-
- target_link_libraries(${SAMPLE}
- event_extra
- ${LIB_APPS}
- ${LIB_PLATFORM})
-
- add_dependencies(${SAMPLE} event_extra)
+ add_sample_prog(OFF ${SAMPLE} sample/${SAMPLE}.c)
endforeach()
- if (WIN32)
- target_sources(dns-example PUBLIC
- WIN32-Code/getopt.c
- WIN32-Code/getopt_long.c)
+ if (NOT EVENT__DISABLE_OPENSSL)
+ add_sample_prog(ON https-client
+ sample/https-client.c
+ sample/openssl_hostname_validation.c
+ sample/hostcheck.c)
+ add_sample_prog(ON le-proxy
+ sample/le-proxy.c)
endif()
+
+ set(SAMPLES_WOPT
+ dns-example
+ http-server
+ )
+ foreach (SAMPLE ${SAMPLES_WOPT})
+ add_sample_prog(OFF ${SAMPLE} sample/${SAMPLE}.c ${WIN32_GETOPT})
+ endforeach()
endif()
+#
+# Benchmarks
+#
+macro(add_bench_prog prog)
+ add_executable(${prog} ${ARGN})
+ target_link_libraries(${prog}
+ event_extra
+ event_core
+ ${LIB_APPS}
+ ${LIB_PLATFORM})
+endmacro()
if (NOT EVENT__DISABLE_BENCHMARK)
- foreach (BENCHMARK bench bench_cascade bench_http bench_httpclient)
- set(BENCH_SRC test/${BENCHMARK}.c)
-
- if (WIN32)
- list(APPEND BENCH_SRC
- WIN32-Code/getopt.c
- WIN32-Code/getopt_long.c)
- endif()
-
- add_executable(${BENCHMARK} ${BENCH_SRC})
-
- target_link_libraries(${BENCHMARK}
- event_extra
- ${LIB_PLATFORM})
-
- add_dependencies(${BENCHMARK} event_extra)
+ foreach (BENCHMARK bench_http bench_httpclient)
+ add_bench_prog(${BENCHMARK} test/${BENCHMARK}.c)
endforeach()
+
+ add_bench_prog(bench test/bench.c ${WIN32_GETOPT})
+ add_bench_prog(bench_cascade test/bench_cascade.c ${WIN32_GETOPT})
endif()
+#
+# Tests
+#
+macro(add_test_prog prog)
+ add_executable(${prog} test/${prog}.c)
+ target_link_libraries(${prog}
+ ${LIB_APPS}
+ ${LIB_PLATFORM}
+ event_core
+ event_extra
+ ${ARGN})
+endmacro()
if (NOT EVENT__DISABLE_TESTS)
#
# Generate Regress tests.
#
if (NOT EVENT__DISABLE_REGRESS)
+ # (We require python to generate the regress tests)
+ find_package(PythonInterp 3)
- # (We require python2 to generate the regress tests)
- foreach (PY python2.6 python2.7 python2)
- unset(FIND_PYTHON2 CACHE)
- find_program(FIND_PYTHON2 ${PY})
- if (FIND_PYTHON2)
- set(PYTHON_EXECUTABLE "${PY}")
- break()
- endif()
- endforeach()
- find_package(PythonInterp)
-
- if (PYTHONINTERP_FOUND AND PYTHON_VERSION_STRING VERSION_LESS "3.0.0")
+ if (PYTHONINTERP_FOUND)
set(__FOUND_USABLE_PYTHON 1)
+ else()
+ find_package(PythonInterp 2)
+ if (PYTHONINTERP_FOUND)
+ set(__FOUND_USABLE_PYTHON 1)
+ else()
+ message(ERROR "No suitable Python version found, bailing...")
+ endif()
endif()
if (__FOUND_USABLE_PYTHON)
@@ -974,34 +1038,30 @@ if (NOT EVENT__DISABLE_TESTS)
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/test)
list(APPEND SRC_REGRESS
- test/regress.c
- test/regress.gen.c
- test/regress.gen.h
- test/regress_buffer.c
- test/regress_bufferevent.c
- test/regress_dns.c
- test/regress_et.c
- test/regress_finalize.c
- test/regress_http.c
- test/regress_listener.c
- test/regress_main.c
- test/regress_minheap.c
- test/regress_rpc.c
- test/regress_testutils.c
- test/regress_testutils.h
- test/regress_util.c
- test/tinytest.c
- ${SRC_CORE}
- ${SRC_EXTRA})
+ test/regress.c
+ test/regress.gen.c
+ test/regress.gen.h
+ test/regress_buffer.c
+ test/regress_bufferevent.c
+ test/regress_dns.c
+ test/regress_et.c
+ test/regress_finalize.c
+ test/regress_http.c
+ test/regress_listener.c
+ test/regress_main.c
+ test/regress_minheap.c
+ test/regress_rpc.c
+ test/regress_testutils.c
+ test/regress_testutils.h
+ test/regress_util.c
+ test/tinytest.c)
if (WIN32)
list(APPEND SRC_REGRESS test/regress_iocp.c)
if (NOT EVENT__DISABLE_THREAD_SUPPORT)
list(APPEND SRC_REGRESS test/regress_thread.c)
endif()
- endif()
-
- if (CMAKE_USE_PTHREADS_INIT)
+ elseif (CMAKE_USE_PTHREADS_INIT)
list(APPEND SRC_REGRESS test/regress_thread.c)
endif()
@@ -1009,23 +1069,23 @@ if (NOT EVENT__DISABLE_TESTS)
list(APPEND SRC_REGRESS test/regress_zlib.c)
endif()
- if (OPENSSL_LIBRARIES)
+ if (NOT EVENT__DISABLE_OPENSSL)
list(APPEND SRC_REGRESS test/regress_ssl.c)
endif()
add_executable(regress ${SRC_REGRESS})
- # While building the test suite we don't want the visibility
- # header trying to "dllimport" the symbols on windows (it
- # generates a ton of warnings due to different link
- # attributes for all of the symbols)
- SET_TARGET_PROPERTIES(regress
- PROPERTIES COMPILE_DEFINITIONS
- "EVENT_BUILDING_REGRESS_TEST=1")
-
target_link_libraries(regress
- ${LIB_APPS}
- ${LIB_PLATFORM})
+ ${LIB_APPS}
+ ${LIB_PLATFORM}
+ event_core
+ event_extra)
+ if (NOT EVENT__DISABLE_OPENSSL)
+ target_link_libraries(regress event_openssl)
+ endif()
+ if (CMAKE_USE_PTHREADS_INIT)
+ target_link_libraries(regress event_pthreads)
+ endif()
else()
message(WARNING "No suitable Python interpreter found, cannot generate regress tests!")
endif()
@@ -1034,44 +1094,41 @@ if (NOT EVENT__DISABLE_TESTS)
#
# Test programs.
#
- # all of these, including the cmakelists.txt should be moved
- # into the dirctory 'tests' first.
- #
- # doing this, we can remove all the DISABLE_TESTS stuff, and simply
- # do something like:
- #
- # add_custom_targets(tests)
- # add_executable(... EXCLUDE_FROM_ALL ...c)
- # add_dependencis(tests testa testb testc)
- # add_test(....)
- #
- # then you can just run 'make tests' instead of them all
- # auto-compile|running
- # - ellzey
- set(TESTPROGS test-changelist
- test-eof
- test-fdleak
- test-init
- test-time
- test-weof)
+ # all of these, including the cmakelists.txt should be moved
+ # into the dirctory 'tests' first.
+ #
+ # doing this, we can remove all the DISABLE_TESTS stuff, and simply
+ # do something like:
+ #
+ # add_custom_targets(tests)
+ # add_executable(... EXCLUDE_FROM_ALL ...c)
+ # add_dependencis(tests testa testb testc)
+ # add_test(....)
+ #
+ # then you can just run 'make tests' instead of them all
+ # auto-compile|running
+ # - ellzey
+ set(TESTPROGS test-changelist
+ test-eof
+ test-fdleak
+ test-init
+ test-time
+ test-weof)
+
+ foreach (TESTPROG ${TESTPROGS} test-dumpevents)
+ add_test_prog(${TESTPROG})
+ endforeach()
+ if (UNIX)
+ add_test_prog(test-ratelim m)
+ else()
+ add_test_prog(test-ratelim)
+ endif()
set(ALL_TESTPROGS
- ${TESTPROGS}
- test-dumpevents
- test-ratelim)
-
- # Create test program executables.
- foreach (TESTPROG ${ALL_TESTPROGS})
- add_executable(${TESTPROG}
- test/${TESTPROG}.c)
-
- target_link_libraries(${TESTPROG}
- ${EVENT_EXTRA_FOR_TEST}
- ${LIB_PLATFORM})
-
- add_dependencies(${TESTPROG}
- ${EVENT_EXTRA_FOR_TEST})
- endforeach()
+ ${TESTPROGS}
+ test-dumpevents
+ test-ratelim
+ )
#
# We run all tests with the different backends turned on one at a time.
@@ -1125,12 +1182,12 @@ if (NOT EVENT__DISABLE_TESTS)
set(TEST_NAME ${TESTPROG}__${BACKEND_TEST_NAME})
add_test(${TEST_NAME}
- ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TESTPROG})
+ ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TESTPROG})
list(APPEND TEST_NAMES ${TEST_NAME})
set_tests_properties(${TEST_NAME}
- PROPERTIES ENVIRONMENT "${ENV_VARS}")
+ PROPERTIES ENVIRONMENT "${ENV_VARS}")
endforeach()
# Dump events test.
@@ -1138,21 +1195,21 @@ if (NOT EVENT__DISABLE_TESTS)
set(TEST_NAME test-dumpevents__${BACKEND_TEST_NAME})
add_test(${TEST_NAME}
- ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-dumpevents |
- ${PYTHON_EXECUTABLE}
- ${CMAKE_CURRENT_SOURCE_DIR}/test/check-dumpevents.py)
+ ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-dumpevents |
+ ${PYTHON_EXECUTABLE}
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/check-dumpevents.py)
set_tests_properties(${TEST_NAME}
- PROPERTIES ENVIRONMENT "${ENV_VARS}")
+ PROPERTIES ENVIRONMENT "${ENV_VARS}")
else()
message(WARNING "test-dumpevents will be run without output check since python was not found!")
set(TEST_NAME test-dumpevents__${BACKEND_TEST_NAME}_no_check)
add_test(${TEST_NAME}
- ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-dumpevents)
+ ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-dumpevents)
set_tests_properties(${TEST_NAME}
- PROPERTIES ENVIRONMENT "${ENV_VARS}")
+ PROPERTIES ENVIRONMENT "${ENV_VARS}")
endif()
# Regress tests.
@@ -1160,16 +1217,16 @@ if (NOT EVENT__DISABLE_TESTS)
set(TEST_NAME regress__${BACKEND_TEST_NAME})
add_test(${TEST_NAME}
- ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/regress)
+ ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/regress)
set_tests_properties(${TEST_NAME}
- PROPERTIES ENVIRONMENT "${ENV_VARS}")
+ PROPERTIES ENVIRONMENT "${ENV_VARS}")
add_test(${TEST_NAME}_debug
- ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/regress)
+ ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/regress)
set_tests_properties(${TEST_NAME}_debug
- PROPERTIES ENVIRONMENT "${ENV_VARS};EVENT_DEBUG_MODE=1")
+ PROPERTIES ENVIRONMENT "${ENV_VARS};EVENT_DEBUG_MODE=1")
endif()
endmacro()
@@ -1199,47 +1256,47 @@ if (NOT EVENT__DISABLE_TESTS)
#
# Group limits, no connection limit.
- set(RL_BIN ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-ratelim)
+ set(RL_BIN ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-ratelim)
add_test(test-ratelim__group_lim
- ${RL_BIN}
- -g 30000
- -n 30
- -t 100
- --check-grouplimit 1000
- --check-stddev 100)
+ ${RL_BIN}
+ -g 30000
+ -n 30
+ -t 100
+ --check-grouplimit 1000
+ --check-stddev 100)
# Connection limit, no group limit.
add_test(test-ratelim__con_lim
- ${RL_BIN}
- -c 1000
- -n 30
- -t 100
- --check-connlimit 50
- --check-stddev 50)
+ ${RL_BIN}
+ -c 1000
+ -n 30
+ -t 100
+ --check-connlimit 50
+ --check-stddev 50)
# Connection limit and group limit.
add_test(test-ratelim__group_con_lim
- ${RL_BIN}
- -c 1000
- -g 30000
- -n 30
- -t 100
- --check-grouplimit 1000
- --check-connlimit 50
- --check-stddev 50)
+ ${RL_BIN}
+ -c 1000
+ -g 30000
+ -n 30
+ -t 100
+ --check-grouplimit 1000
+ --check-connlimit 50
+ --check-stddev 50)
# Connection limit and group limit with independent drain.
add_test(test-ratelim__group_con_lim_drain
- ${RL_BIN}
- -c 1000
- -g 35000
- -n 30
- -t 100
- -G 500
- --check-grouplimit 1000
- --check-connlimit 50
- --check-stddev 50)
+ ${RL_BIN}
+ -c 1000
+ -g 35000
+ -n 30
+ -t 100
+ -G 500
+ --check-grouplimit 1000
+ --check-connlimit 50
+ --check-stddev 50)
# Add a "make verify" target, same as for autoconf.
# (Important! This will unset all EVENT_NO* environment variables.
@@ -1259,21 +1316,20 @@ if (NOT EVENT__DISABLE_TESTS)
message(STATUS "${WINDOWS_CTEST_COMMAND}")
file(COPY ${CMAKE_CURRENT_BINARY_DIR}/tmp/verify_tests.bat
- DESTINATION
- ${CMAKE_CURRENT_BINARY_DIR}
- FILE_PERMISSIONS
- OWNER_READ
- OWNER_WRITE
- OWNER_EXECUTE
- GROUP_READ
- GROUP_EXECUTE
- WORLD_READ WORLD_EXECUTE)
+ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
+ FILE_PERMISSIONS
+ OWNER_READ
+ OWNER_WRITE
+ OWNER_EXECUTE
+ GROUP_READ
+ GROUP_EXECUTE
+ WORLD_READ WORLD_EXECUTE)
file(TO_NATIVE_PATH
"${CMAKE_CURRENT_BINARY_DIR}/verify_tests.bat" VERIFY_PATH)
add_custom_target(verify COMMAND "${VERIFY_PATH}"
- DEPENDS event ${ALL_TESTPROGS})
+ DEPENDS event ${ALL_TESTPROGS})
else()
# On some platforms doing exec(unset) as CMake does won't work, so make sure
# we run the unset command in a shell instead.
@@ -1287,23 +1343,20 @@ if (NOT EVENT__DISABLE_TESTS)
# Then we copy the file (this allows us to set execute permission on it)
file(COPY ${CMAKE_CURRENT_BINARY_DIR}/tmp/verify_tests.sh
- DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
- FILE_PERMISSIONS
- OWNER_READ
- OWNER_WRITE
- OWNER_EXECUTE
- GROUP_READ
- GROUP_EXECUTE
- WORLD_READ
- WORLD_EXECUTE)
+ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
+ FILE_PERMISSIONS
+ OWNER_READ
+ OWNER_WRITE
+ OWNER_EXECUTE
+ GROUP_READ
+ GROUP_EXECUTE
+ WORLD_READ
+ WORLD_EXECUTE)
# Create the target that runs the script.
add_custom_target(verify
- COMMAND
- ${CMAKE_CURRENT_BINARY_DIR}/verify_tests.sh
- DEPENDS
- event
- ${ALL_TESTPROGS})
+ COMMAND ${CMAKE_CURRENT_BINARY_DIR}/verify_tests.sh
+ DEPENDS event ${ALL_TESTPROGS})
endif()
if (NOT EVENT__DISABLE_REGRESS AND __FOUND_USABLE_PYTHON)
@@ -1329,30 +1382,16 @@ endif()
# Installation preparation.
#
-# Allow the user to override installation directories.
-set(EVENT_INSTALL_LIB_DIR lib CACHE PATH "Installation directory for libraries")
-set(EVENT_INSTALL_BIN_DIR bin CACHE PATH "Installation directory for executables")
-set(EVENT_INSTALL_INCLUDE_DIR include CACHE PATH "Installation directory for header files")
-
if(WIN32 AND NOT CYGWIN)
set(DEF_INSTALL_CMAKE_DIR cmake)
else()
set(DEF_INSTALL_CMAKE_DIR lib/cmake/libevent)
endif()
-set(EVENT_INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Installation directory for CMake files")
-
-# Make sure the paths are absolute.
-foreach(p LIB BIN INCLUDE CMAKE)
- set(var EVENT_INSTALL_${p}_DIR)
- if(NOT IS_ABSOLUTE "${${var}}")
- set(${var} "${CMAKE_INSTALL_PREFIX}/${${var}}")
- endif()
-endforeach()
+set(EVENT_INSTALL_CMAKE_DIR
+ "${CMAKE_INSTALL_PREFIX}/${DEF_INSTALL_CMAKE_DIR}"
+ CACHE PATH "Installation directory for CMake files")
-# Export targets (This is used for other CMake projects to easily find the libraries and include files).
-export(TARGETS event event_extra event_core
- FILE "${PROJECT_BINARY_DIR}/LibeventTargets.cmake")
export(PACKAGE libevent)
# Generate the config file for the build-tree.
@@ -1365,94 +1404,71 @@ set(LIBEVENT_INCLUDE_DIRS
CACHE PATH "Libevent include directories")
configure_file(${PROJECT_SOURCE_DIR}/cmake/LibeventConfigBuildTree.cmake.in
- ${PROJECT_BINARY_DIR}/LibeventConfig.cmake
- @ONLY)
+ ${PROJECT_BINARY_DIR}/LibeventConfig.cmake
+ @ONLY)
# Generate the config file for the installation tree.
+# Calculate the relative directory from the Cmake dir.
file(RELATIVE_PATH
- REL_INCLUDE_DIR
- "${EVENT_INSTALL_CMAKE_DIR}"
- "${EVENT_INSTALL_INCLUDE_DIR}") # Calculate the relative directory from the Cmake dir.
+ REL_INCLUDE_DIR
+ "${EVENT_INSTALL_CMAKE_DIR}"
+ "${CMAKE_INSTALL_PREFIX}/include")
-# Note the EVENT_CMAKE_DIR is defined in LibeventConfig.cmake.in,
+# Note the LIBEVENT_CMAKE_DIR is defined in LibeventConfig.cmake.in,
# we escape it here so it's evaluated when it is included instead
-# so that the include dirs are givenrelative to where the
+# so that the include dirs are given relative to where the
# config file is located.
-set(EVENT__INCLUDE_DIRS
- "\${EVENT_CMAKE_DIR}/${REL_INCLUDE_DIR}")
+set(EVENT_INSTALL_INCLUDE_DIR "\${LIBEVENT_CMAKE_DIR}/${REL_INCLUDE_DIR}")
configure_file(${PROJECT_SOURCE_DIR}/cmake/LibeventConfig.cmake.in
- ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/LibeventConfig.cmake
- @ONLY)
+ ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/LibeventConfig.cmake
+ @ONLY)
# Generate version info for both build-tree and install-tree.
configure_file(${PROJECT_SOURCE_DIR}/cmake/LibeventConfigVersion.cmake.in
- ${PROJECT_BINARY_DIR}/LibeventConfigVersion.cmake
- @ONLY)
-
-# Define the public headers.
-set_target_properties(event event_core event_extra
- PROPERTIES PUBLIC_HEADER "${HDR_PUBLIC}")
-
-#
-# Install targets.
-#
-install(TARGETS event event_core event_extra
- EXPORT LibeventTargets
- RUNTIME DESTINATION "${EVENT_INSTALL_BIN_DIR}" COMPONENT bin
- LIBRARY DESTINATION "${EVENT_INSTALL_LIB_DIR}" COMPONENT lib
- ARCHIVE DESTINATION "${EVENT_INSTALL_LIB_DIR}" COMPONENT lib
- PUBLIC_HEADER DESTINATION "${EVENT_INSTALL_INCLUDE_DIR}/event2" COMPONENT dev)
+ ${PROJECT_BINARY_DIR}/LibeventConfigVersion.cmake
+ @ONLY)
# Install compat headers
install(FILES ${HDR_COMPAT}
- DESTINATION
- "${EVENT_INSTALL_INCLUDE_DIR}"
- COMPONENT dev)
+ DESTINATION "include"
+ COMPONENT dev)
# Install the configs.
install(FILES
- ${PROJECT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/LibeventConfig.cmake
- ${PROJECT_BINARY_DIR}/LibeventConfigVersion.cmake
- DESTINATION
- "${EVENT_INSTALL_CMAKE_DIR}"
+ ${PROJECT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/LibeventConfig.cmake
+ ${PROJECT_BINARY_DIR}/LibeventConfigVersion.cmake
+ DESTINATION "${EVENT_INSTALL_CMAKE_DIR}"
COMPONENT dev)
# Install exports for the install-tree.
install(EXPORT LibeventTargets
- DESTINATION
- "${EVENT_INSTALL_CMAKE_DIR}"
- COMPONENT dev)
-
-set(LIBEVENT_LIBRARIES
- event
- event_core
- event_extra
- CACHE STRING "Libevent libraries")
+ DESTINATION "${DEF_INSTALL_CMAKE_DIR}"
+ COMPONENT dev)
message(STATUS "")
message(STATUS " ---( Libevent " ${EVENT_VERSION} " )---")
message(STATUS "")
message(STATUS "Available event backends: ${BACKENDS}")
-message(STATUS "CMAKE_BINARY_DIR: " ${CMAKE_BINARY_DIR})
-message(STATUS "CMAKE_CURRENT_BINARY_DIR: " ${CMAKE_CURRENT_BINARY_DIR})
-message(STATUS "CMAKE_SOURCE_DIR: " ${CMAKE_SOURCE_DIR})
-message(STATUS "CMAKE_CURRENT_SOURCE_DIR: " ${CMAKE_CURRENT_SOURCE_DIR})
-message(STATUS "PROJECT_BINARY_DIR: " ${PROJECT_BINARY_DIR})
-message(STATUS "PROJECT_SOURCE_DIR: " ${PROJECT_SOURCE_DIR})
-message(STATUS "CMAKE_MODULE_PATH: " ${CMAKE_MODULE_PATH})
-message(STATUS "CMAKE_COMMAND: " ${CMAKE_COMMAND})
-message(STATUS "CMAKE_ROOT: " ${CMAKE_ROOT} )
-message(STATUS "CMAKE_SYSTEM: " ${CMAKE_SYSTEM} )
-message(STATUS "CMAKE_SYSTEM_NAME: " ${CMAKE_SYSTEM_NAME} )
-message(STATUS "CMAKE_SYSTEM_VERSION: " ${CMAKE_SYSTEM_VERSION} )
-message(STATUS "CMAKE_SYSTEM_PROCESSOR: " ${CMAKE_SYSTEM_PROCESSOR} )
-message(STATUS "CMAKE_SKIP_RPATH: " ${CMAKE_SKIP_RPATH} )
-message(STATUS "CMAKE_VERBOSE_MAKEFILE: " ${CMAKE_VERBOSE_MAKEFILE} )
-message(STATUS "CMAKE_C_FLAGS: " ${CMAKE_C_FLAGS} )
-message(STATUS "CMAKE_BUILD_TYPE: " ${CMAKE_BUILD_TYPE} )
-message(STATUS "CMAKE_C_COMPILER: " ${CMAKE_C_COMPILER} )
-message(STATUS "CMAKE_AR: " ${CMAKE_AR} )
-message(STATUS "CMAKE_RANLIB: " ${CMAKE_RANLIB} )
+message(STATUS "CMAKE_BINARY_DIR: ${CMAKE_BINARY_DIR}")
+message(STATUS "CMAKE_CURRENT_BINARY_DIR: ${CMAKE_CURRENT_BINARY_DIR}")
+message(STATUS "CMAKE_SOURCE_DIR: ${CMAKE_SOURCE_DIR}")
+message(STATUS "CMAKE_CURRENT_SOURCE_DIR: ${CMAKE_CURRENT_SOURCE_DIR}")
+message(STATUS "PROJECT_BINARY_DIR: ${PROJECT_BINARY_DIR}")
+message(STATUS "PROJECT_SOURCE_DIR: ${PROJECT_SOURCE_DIR}")
+message(STATUS "CMAKE_MODULE_PATH: ${CMAKE_MODULE_PATH}")
+message(STATUS "CMAKE_COMMAND: ${CMAKE_COMMAND}")
+message(STATUS "CMAKE_ROOT: ${CMAKE_ROOT}")
+message(STATUS "CMAKE_SYSTEM: ${CMAKE_SYSTEM}")
+message(STATUS "CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}")
+message(STATUS "CMAKE_SYSTEM_VERSION: ${CMAKE_SYSTEM_VERSION}")
+message(STATUS "CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}")
+message(STATUS "CMAKE_SKIP_RPATH: ${CMAKE_SKIP_RPATH}")
+message(STATUS "CMAKE_VERBOSE_MAKEFILE: ${CMAKE_VERBOSE_MAKEFILE}")
+message(STATUS "CMAKE_C_FLAGS: ${CMAKE_C_FLAGS}")
+message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")
+message(STATUS "CMAKE_C_COMPILER: ${CMAKE_C_COMPILER} (id ${CMAKE_C_COMPILER_ID}, clang ${CLANG}, GNUC ${GNUC})")
+message(STATUS "CMAKE_AR: ${CMAKE_AR}")
+message(STATUS "CMAKE_RANLIB: ${CMAKE_RANLIB}")
message(STATUS "")
diff --git a/ChangeLog b/ChangeLog
index 740bdfcc..4d0dfba4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,139 @@
+Changes in version 2.1.9-beta (10 February 2019)
+
+ This changelog will differs from other releases in the next few clauses:
+ - contains only highlighted changes (so now it will not contains a lot of
+ patches that fixes some stuff in regression tests, typos, leaks fixes in
+ samples and so forth)
+ - no authors (since merge commits breaks them anyway, but AUTHORS sections in
+ README will be kept up to date)
+ - group name trimmed from commit subjects trimmed
+ - it's been 2 years since the previoius release, so it is pretty huge
+
+ And I think that this is more useful, so from now on it will always has the
+ same look (until there will too many objections of course).
+
+ To view full changelog please use git:
+ git log --format=' o %s (%h %aN)' release-2.1.8-stable...release-2.1.9-beta
+
+
+ dist archive:
+ o Add cmake rules into dist archive (bf3a67cfg)
+ o Add missing print-winsock-errors.c into dist archive (822d6462g)
+ o Include openssl-compat.h into dist archive (08658136g)
+
+ core:
+ o Merge branch 'check-O_NONBLOCK-in-debug' (a39898f3g, a8155c62g)
+ o Merge branch 'event-ET-#636-v2' (ca4b6404g)
+ o Fix visibility issues under (mostly on win32)
+ (349081e1g, 802be13ag, a1f28e2fg)
+ o Define __EXT_POSIX2 for QNX (a2176f2c)
+ o Cleanup __func__ detection (b3af7bddg)
+ o Add convenience macros for user-triggered events (06ec5de6)
+ o Notify event base if there are no more events, so it can exit without delay (d9d1c09eg)
+ o Fix base unlocking in event_del() if event_base_set() runned in another thread (4f0f40e3g)
+ o If precise_time is false, we should not set EVENT_BASE_FLAG_PRECISE_TIMER (27dee54d)
+ o Fix race in access to ev_res from event loop with event_active() (43d92a6d)
+ o Return from event_del() after the last event callback termination (876c7ac7)
+
+ http:
+ o Merge branch 'http-EVHTTP_CON_READ_ON_WRITE_ERROR-fixes-v2' (eb7b472bg)
+ o Preserve socket error from listen across closesocket cleanup (2ccd00a6)
+ o fix connection retries when there more then one request for connection (d30e7bbag)
+ o improve error path for bufferevent_{setfd,enable,disable}() (a8cc449eg)
+ o Fix conceivable UAF of the bufferevent in evhttp_connection_free() (6ac2ec25g)
+ o Merge branch 'http-request-line-parsing' (cdcfbafeg)
+ o Fix evhttp_connection_get_addr() fox incomming http connections (4215c003)
+ o fix leaks in evhttp_uriencode() (123362e9g)
+ o CONNECT method only takes an authority (7d1ffe64)
+ o Allow bodies for GET/DELETE/OPTIONS/CONNECT (23eb38b9g)
+ o Do not crash when evhttp_send_reply_start() is called after a timeout. (826f1134)
+ o Fix crashing http server when callback do not reply in place (5b40744dg, b2581380g)
+ o fix handling of close_notify (ssl) in http with openssl bufferevents (7e91622bg)
+
+ evprc:
+ o use *_new_with_arg() to match function prototype (a95cc9e3g)
+ o avoid NULL dereference on request is not EVHTTP_REQ_POST (e05136c7g)
+
+ regression tests:
+ o Merge branch 'TT_RETRIABLE' (6ea1ec68g, f9b592aag)
+
+ bufferevent:
+ o Merge branch 'iocp-fixes' (6bfac964g)
+ o Merge branch 'be-wm-overrun-v2' (3f692fffg)
+ o bufferevent_socket_connect{,_hostname}() missing event callback and use ret code (1dde74ef)
+ o don't fail be_null_filter if bytes are copied (b92b0792)
+ o Call underlying bev ctrl GET_FD on filtered bufferevents (ebfac517)
+
+ bufferevent_openssl/openssl:
+ o Merge branch 'ssl_bufferevent_wm_filter-fix' (30020a35g)
+ o be_openssl: avoid leaking of SSL structure (e86ccfe5g)
+ o Fix build with LibreSSL 2.7 (894ca48a)
+ o Add missing includes into openssl-compat.h (01bc36c1g)
+ o Explicitly call SSL_clear when reseting the fd. (29b7a516)
+ o Unbreak build with LibreSSL after openssl 1.1 support added (230af9f0)
+
+ samples:
+ o Merge branch 'sample-http-server' (b6309bccg)
+ o sample/https-client: use host SSL certificate store by default (5c0132f3)
+
+ listener:
+ o ipv6only socket bind support (ba148796)
+ o Merge branch 'listener-immediate-close' (df2ed13fg)
+ o Merge branch 'evconnlistener-do-not-close-client-fd' (42e851bbg)
+
+ evdns:
+ o evdns: handle NULL filename explicitly (0033f5cc)
+ o Merge branch 'evdns_getaddrinfo-race-fix' (3237d697g)
+ o Generating evdns_base_config_windows_nameservers docs on all platforms (3bd2ce43)
+
+ utils:
+ o Merge branch 'evutil_found_ifaddr-dev' (b07e43e6g)
+ o Avoid possible SEGVs in select() (in unit tests) (8818c86c)
+ o Port `event_rpcgen.py` and `test/check-dumpevents.py` to Python 3. (532a8cc3)
+
+ buffer:
+ o Fix assert() condition in evbuffer_drain() for IOCP (d6326104)
+ o fix incorrect unlock of the buffer mutex (for deferred callbacks) (2b4d127dg)
+ o Fix wrong assert in evbuffer_drain() (9f4d0dceg)
+
+ cmake:
+ o fix checking of devpoll backend (like in autotools, by devpoll.h existence) (7f161902)
+ o support static runtime (MSVC) (c8b3ec17, 61fb055a)
+ o do not build both (SHARED and STATIC) for MSVC/win32 (bc7f2fd9g)
+ o introduce EVENT__LIBRARY_TYPE option (eb10a738g)
+ o ensure windows dll's are installed as well as lib files (29590718)
+ o Fix generation of LibeventConfig.cmake for the installation tree (7fa08c4b)
+ o fix pkgconfig generation (copy-paste typo) (cc554d87g)
+ o Merge branch 'cmake-missing-bits' (9806b126g)
+ o Fix detection of timerfd_create() in CMake. (e50af331)
+ o Merge branch 'cmake-configure-fixes-v2' (a0bfe2c4g)
+ o Do not add epoll_sub (syscall wrappers) for epoll in cmake (cea61de6g)
+ o Fix RPATH for APPLE (45b1f379)
+
+ autotools:
+ o include win32 specific headers for socklen_t detection on win32/mingw (d7579fb9g)
+ o Ignore evconfig-private.h for autotools (37423849g)
+ o config.h can't be prefixed unconditionally (63a054f8)
+ o Merge branch 'pull-628' (7e56c8b2g)
+ o Provide Makefile variables LIBEVENT_{CFLAGS,CPPFLAGS,LDFLAGS} (2f060c5f)
+ o confirm openssl is working before using (b39ccf8e)
+ o pass $(OPENSSL_INCS) for samples (FTBFS macOS) (c2495265)
+ o Add configure check for midipix (d433201e)
+ o Fix tests with detached builds (c46ff439)
+
+ build:
+ o Fix arc4random_addrandom() detecting and fallback (regression) (303d6d77g)
+ o Merge branch 'win32-fixes' (ebd12e6dg)
+ o Merge branch 'fix-openssl-linking' (e7bd9e03g)
+ o Merge branch 'fix-struct-linger' (8567f2f5g)
+
+ CI:
+ o travis-ci/appveyor now uses fast_finish+allow_failures
+ (5e97b6e6, dd472e7d, dfb5fc167)
+ o Merge branch 'travis-ci-osx-fixes' (9f02b39c)
+ o Merge branch 'win64-fixes' (aee0fcd5)
+
+
Changes in version 2.1.8-stable (22 January 2017)
Libevent 2.1.8-stable, it contains openssl fixes for resetting fd and using
diff --git a/Makefile.am b/Makefile.am
index 0f741bc9..9ebce429 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -38,7 +38,7 @@ RELEASE = -release 2.1
#
# Once an RC is out, DO NOT MAKE ANY ABI-BREAKING CHANGES IN THAT SERIES
# UNLESS YOU REALLY REALLY HAVE TO.
-VERSION_INFO = 6:2:0
+VERSION_INFO = 6:3:0
# History: RELEASE VERSION_INFO
# 2.0.1-alpha -- 2.0 1:0:0
@@ -71,7 +71,8 @@ VERSION_INFO = 6:2:0
# 2.1.5-beta -- 2.1 5:0:0 (ABI changed slightly)
# 2.1.6-beta -- 2.1 6:0:0 (ABI changed slightly)
# 2.1.7-beta -- 2.1 6:1:0 (ABI changed slightly)
-# 2.1.8-stable-- 2.1 6:2:0 (ABI changed slightly)
+# 2.1.8-stable-- 2.1 6:2:0 (No ABI change)
+# 2.1.9-beta-- 2.1 6:3:0 (No ABI change)
# ABI version history for this package effectively restarts every time
# we change RELEASE. Version 1.4.x had RELEASE of 1.4.
@@ -104,6 +105,30 @@ PLATFORM_DEPENDENT_SRC = \
arc4random.c \
epoll_sub.c
+CMAKE_FILES = \
+ cmake/AddCompilerFlags.cmake \
+ cmake/AddEventLibrary.cmake \
+ cmake/CheckConstExists.cmake \
+ cmake/CheckFileOffsetBits.c \
+ cmake/CheckFileOffsetBits.cmake \
+ cmake/CheckFunctionExistsEx.c \
+ cmake/CheckFunctionExistsEx.cmake \
+ cmake/CheckFunctionKeywords.cmake \
+ cmake/CheckPrototypeDefinition.c.in \
+ cmake/CheckPrototypeDefinition.cmake \
+ cmake/CheckWorkingKqueue.cmake \
+ cmake/CodeCoverage.cmake \
+ cmake/COPYING-CMAKE-SCRIPTS \
+ cmake/Copyright.txt \
+ cmake/FindGit.cmake \
+ cmake/LibeventConfigBuildTree.cmake.in \
+ cmake/LibeventConfig.cmake.in \
+ cmake/LibeventConfigVersion.cmake.in \
+ cmake/VersionViaGit.cmake \
+ event-config.h.cmake \
+ evconfig-private.h.cmake \
+ CMakeLists.txt
+
EXTRA_DIST = \
ChangeLog-1.4 \
ChangeLog-2.0 \
@@ -116,6 +141,7 @@ EXTRA_DIST = \
make-event-config.sed \
whatsnew-2.0.txt \
whatsnew-2.1.txt \
+ $(CMAKE_FILES) \
$(PLATFORM_DEPENDENT_SRC)
LIBEVENT_LIBS_LA = libevent.la libevent_core.la libevent_extra.la
@@ -228,7 +254,11 @@ NO_UNDEFINED =
MAYBE_CORE =
endif
-GENERIC_LDFLAGS = -version-info $(VERSION_INFO) $(RELEASE) $(NO_UNDEFINED)
+AM_CFLAGS = $(LIBEVENT_CFLAGS)
+AM_CPPFLAGS = -I$(srcdir)/compat -I./include -I$(srcdir)/include $(SYS_INCLUDES) $(LIBEVENT_CPPFLAGS)
+AM_LDFLAGS = $(LIBEVENT_LDFLAGS)
+
+GENERIC_LDFLAGS = -version-info $(VERSION_INFO) $(RELEASE) $(NO_UNDEFINED) $(AM_LDFLAGS)
libevent_la_SOURCES = $(CORE_SRC) $(EXTRAS_SRC)
libevent_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS)
@@ -265,7 +295,6 @@ noinst_HEADERS += \
defer-internal.h \
epolltable-internal.h \
evbuffer-internal.h \
- evconfig-private.h \
event-internal.h \
evmap-internal.h \
evrpc-internal.h \
@@ -283,7 +312,8 @@ noinst_HEADERS += \
ratelim-internal.h \
strlcpy-internal.h \
time-internal.h \
- util-internal.h
+ util-internal.h \
+ openssl-compat.h
EVENT1_HDRS = \
include/evdns.h \
@@ -298,8 +328,6 @@ else
noinst_HEADERS += $(EVENT1_HDRS)
endif
-AM_CPPFLAGS = -I$(srcdir)/compat -I$(srcdir)/include -I./include $(SYS_INCLUDES)
-
verify: check
doxygen: FORCE
diff --git a/README.md b/README.md
index 5e3eb4df..f550c677 100644
--- a/README.md
+++ b/README.md
@@ -7,6 +7,7 @@
[![Appveyor Win32 Build Status](https://ci.appveyor.com/api/projects/status/github/libevent/libevent?branch=master&svg=true)](https://ci.appveyor.com/project/nmathewson/libevent)
[![Travis Build Status](https://travis-ci.org/libevent/libevent.svg?branch=master)](https://travis-ci.org/libevent/libevent)
[![Coverage Status](https://coveralls.io/repos/github/libevent/libevent/badge.svg)](https://coveralls.io/github/libevent/libevent)
+[![Join the chat at https://gitter.im/libevent/libevent](https://badges.gitter.im/libevent/libevent.svg)](https://gitter.im/libevent/libevent?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
@@ -19,42 +20,34 @@
$ make verify # (optional)
$ sudo make install
-## Cmake (General)
+## CMake (General)
-The following Libevent specific Cmake variables are as follows (the values being
+The following Libevent specific CMake variables are as follows (the values being
the default).
```
-# Installation directory for executables
-EVENT_INSTALL_BIN_DIR:PATH=bin
+# Type of the library to build (SHARED or STATIC)
+# Default is: SHARED for MSVC, otherwise BOTH
+EVENT__LIBRARY_TYPE:STRING=DEFAULT
# Installation directory for CMake files
EVENT_INSTALL_CMAKE_DIR:PATH=lib/cmake/libevent
-## Installation directory for header files
-EVENT_INSTALL_INCLUDE_DIR:PATH=include
-
-## Installation directory for libraries
-EVENT_INSTALL_LIB_DIR:PATH=lib
-
-## Define if libevent should be built with shared libraries instead of archives
-EVENT__BUILD_SHARED_LIBRARIES:BOOL=OFF
-
# Enable running gcov to get a test coverage report (only works with
# GCC/CLang). Make sure to enable -DCMAKE_BUILD_TYPE=Debug as well.
EVENT__COVERAGE:BOOL=OFF
-# Defines if libevent should build without the benchmark exectuables
+# Defines if Libevent should build without the benchmark executables
EVENT__DISABLE_BENCHMARK:BOOL=OFF
-# Define if libevent should build without support for a debug mode
+# Define if Libevent should build without support for a debug mode
EVENT__DISABLE_DEBUG_MODE:BOOL=OFF
-# Define if libevent should not allow replacing the mm functions
+# Define if Libevent should not allow replacing the mm functions
EVENT__DISABLE_MM_REPLACEMENT:BOOL=OFF
-# Define if libevent should build without support for OpenSSL encrpytion
+# Define if Libevent should build without support for OpenSSL encryption
EVENT__DISABLE_OPENSSL:BOOL=OFF
# Disable the regress tests
@@ -66,20 +59,17 @@ EVENT__DISABLE_SAMPLES:BOOL=OFF
# If tests should be compiled or not
EVENT__DISABLE_TESTS:BOOL=OFF
-# Define if libevent should not be compiled with thread support
+# Define if Libevent should not be compiled with thread support
EVENT__DISABLE_THREAD_SUPPORT:BOOL=OFF
# Enables verbose debugging
EVENT__ENABLE_VERBOSE_DEBUG:BOOL=OFF
-# When crosscompiling forces running a test program that verifies that Kqueue
+# When cross compiling, forces running a test program that verifies that Kqueue
# works with pipes. Note that this requires you to manually run the test program
-# on the the cross compilation target to verify that it works. See cmake
+# on the the cross compilation target to verify that it works. See CMake
# documentation for try_run for more details
EVENT__FORCE_KQUEUE_CHECK:BOOL=OFF
-
-# set EVENT_STAGE_VERSION
-EVENT__STAGE_VERSION:STRING=beta
```
__More variables can be found by running `cmake -LAH <sourcedir_path>`__
@@ -87,7 +77,7 @@ __More variables can be found by running `cmake -LAH <sourcedir_path>`__
## CMake (Windows)
-Install CMake: <http://www.cmake.org>
+Install CMake: <https://www.cmake.org>
$ md build && cd build
@@ -106,12 +96,12 @@ Install CMake: <http://www.cmake.org>
## Autoconf
-To build libevent, type
+To build Libevent, type
$ ./configure && make
- (If you got libevent from the git repository, you will
+ (If you got Libevent from the git repository, you will
first need to run the included "autogen.sh" script in order to
generate the configure script.)
@@ -125,36 +115,36 @@ Install as root via
Before reporting any problems, please run the regression tests.
-To enable the low-level tracing build the library as:
+To enable low-level tracing, build the library as:
$ CFLAGS=-DUSE_DEBUG ./configure [...]
Standard configure flags should work. In particular, see:
- --disable-shared Only build static libraries
- --prefix Install all files relative to this directory.
+ --disable-shared Only build static libraries.
+ --prefix Install all files relative to this directory.
The configure script also supports the following flags:
- --enable-gcc-warnings Enable extra compiler checking with GCC.
- --disable-malloc-replacement
- Don't let applications replace our memory
- management functions
- --disable-openssl Disable support for OpenSSL encryption.
- --disable-thread-support Don't support multithreaded environments.
+ --enable-gcc-warnings Enable extra compiler checking with GCC.
+ --disable-malloc-replacement
+ Don't let applications replace our memory
+ management functions.
+ --disable-openssl Disable support for OpenSSL encryption.
+ --disable-thread-support Don't support multithreaded environments.
## CMake (Windows)
(Note that autoconf is currently the most mature and supported build
-enviroment for libevent; the cmake instructions here are new and
-experimental, though they _should_ be solid. We hope that cmake will
+environment for Libevent; the CMake instructions here are new and
+experimental, though they _should_ be solid. We hope that CMake will
still be supported in future versions of Libevent, and will try to
make sure that happens.)
-First of all install <http://www.cmake.org>.
+First of all install <https://www.cmake.org>.
-To build libevent using Microsoft Visual studio open the "Visual Studio Command prompt" and type:
+To build Libevent using Microsoft Visual studio open the "Visual Studio Command prompt" and type:
```
$ cd <libevent source dir>
@@ -183,11 +173,6 @@ $ cmake -LH ..
CMake also provides a GUI that lets you specify the source directory and output (binary) directory
that the build should be placed in.
-### OpenSSL support
-
-To build Libevent with OpenSSL support you will need to have OpenSSL binaries available when building,
-these can be found here: <http://www.openssl.org/related/binaries.html>
-
# 2. USEFUL LINKS:
For the latest released version of Libevent, see the official website at
@@ -205,15 +190,15 @@ $ git clone https://github.com/libevent/libevent.git
You can browse the git repository online at:
-<https://github.com/libevent/Libevent>
+<https://github.com/libevent/libevent>
To report bugs, issues, or ask for new features:
__Patches__: https://github.com/libevent/libevent/pulls
-> OK, those are not really _patches_ You fork, modify, and hit the "Create Pull Request" button.
-> You can still submit normal git patchs via the mailing list.
+> OK, those are not really _patches_. You fork, modify, and hit the "Create Pull Request" button.
+> You can still submit normal git patches via the mailing list.
-__Bugs, Features [RFC], and Issus__: https://github.com/libevent/libevent/issues
+__Bugs, Features [RFC], and Issues__: https://github.com/libevent/libevent/issues
> Or you can do it via the mailing list.
There's also a libevent-users mailing list for talking about Libevent
@@ -427,5 +412,45 @@ fixing bugs:
* johnsonlee
* Philip Prindeville
* Vis Virial
+ * Andreas Gustafsson
+ * Andrey Okoshkin
+ * an-tao
+ * baixiangcpp
+ * Bernard Spil
+ * Bogdan Harjoc
+ * Carlo Marcelo Arenas Belón
+ * David Benjamin
+ * David Disseldorp
+ * Dmitry Alimov
+ * Dominic Chen
+ * dpayne
+ * ejurgensen
+ * Fredrik Strupe
+ * Gonçalo Ribeiro
+ * James Synge
+ * Jan Beich
+ * Jesse Fang
+ * Jiri Luznicky
+ * José Luis Millán
+ * Kiyoshi Aman
+ * Leo Zhang
+ * lightningkay
+ * Luke Dashjr
+ * Marcin Szewczyk
+ * Maximilian Brunner
+ * Maya Rashish
+ * Murat Demirten
+ * Nathan French
+ * Nikolay Edigaryev
+ * Philip Herron
+ * Redfoxmoon
+ * stenn
+ * SuckShit
+ * The Gitter Badger
+ * tim-le
+ * Vincent JARDIN
+ * Xiang Zhang
+ * Xiaozhou Liu
+ * yongqing.jiao
If we have forgotten your name, please contact us.
diff --git a/WIN32-Code/nmake/event2/event-config.h b/WIN32-Code/nmake/event2/event-config.h
index e6ed3aa4..3d1439b3 100644
--- a/WIN32-Code/nmake/event2/event-config.h
+++ b/WIN32-Code/nmake/event2/event-config.h
@@ -192,9 +192,6 @@
/* Define to 1 if the system has the type `struct sockaddr_storage'. */
#define EVENT__HAVE_STRUCT_SOCKADDR_STORAGE 1
-/* Define to 1 if you have the <sys/devpoll.h> header file. */
-/* #undef EVENT__HAVE_SYS_DEVPOLL_H */
-
/* Define to 1 if you have the <sys/epoll.h> header file. */
/* #undef EVENT__HAVE_SYS_EPOLL_H */
@@ -274,7 +271,7 @@
/* #undef EVENT__HAVE_WORKING_KQUEUE */
/* Numeric representation of the version */
-#define EVENT__NUMERIC_VERSION 0x02010800
+#define EVENT__NUMERIC_VERSION 0x02010900
/* Name of package */
#define EVENT__PACKAGE "libevent"
@@ -324,29 +321,22 @@
#define EVENT__SIZEOF_VOID_P 4
#endif
-/* Define to 1 if you have the ANSI C header files. */
-#define EVENT__STDC_HEADERS 1
+/* The size of `time_t`, as computed by sizeof. */
+#ifdef _WIN64
+#define EVENT__SIZEOF_TIME_T 8
+#else
+#define EVENT__SIZEOF_TIME_T 4
+#endif
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#define EVENT__TIME_WITH_SYS_TIME 1
/* Version number of package */
-#define EVENT__VERSION "2.1.8-stable"
-
-/* Define to appropriate substitue if compiler doesnt have __func__ */
-#define EVENT____func__ __FUNCTION__
-
-/* Define to empty if `const' does not conform to ANSI C. */
-/* #undef EVENT__const */
+#define EVENT__VERSION "2.1.9-beta"
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
-#ifndef _EVENT___cplusplus
#define EVENT__inline __inline
-#endif
-
-/* Define to `int' if <sys/types.h> does not define. */
-/* #undef EVENT__pid_t */
/* Define to `unsigned' if <sys/types.h> does not define. */
/* #undef EVENT__size_t */
diff --git a/appveyor.yml b/appveyor.yml
index 6beb5457..2d7cee2c 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,60 +1,104 @@
-version: 2.1.8.{build}
+version: 2.1.9.{build}
-os: Visual Studio 2015
+os: Visual Studio 2017
+platform:
+ - x64
-build:
- verbosity: detailed
+branches:
+ except:
+ - /.*travis.*/
+ - /.*linux.*/
+ - /.*freebsd.*/
+ - /.*osx.*/
+skip_commits:
+ message: /travis/
+ files:
+ - .travis.yml
environment:
global:
- CYG_ROOT: C:/MinGW/msys/1.0
+ APPVEYOR_SAVE_CACHE_ON_ERROR: true
+ MINGW_ROOT: C:/mingw-w64/x86_64-7.2.0-posix-seh-rt_v5-rev1
+ OPENSSL_ROOT: C:/OpenSSL-Win64
+ MPATH: C:/mingw-w64/x86_64-7.2.0-posix-seh-rt_v5-rev1/bin;C:/msys64/bin;C:/cygwin64/bin
+ EVENT_TESTS_PARALLEL: 20
+ EVENT_BUILD_PARALLEL: 10
matrix:
+ # !EVENT_ALLOW_FAILURE
+ - EVENT_BUILD_METHOD: "cmake"
+ EVENT_CMAKE_OPTIONS: ""
+ - EVENT_BUILD_METHOD: "cmake"
+ EVENT_CMAKE_OPTIONS: "-DEVENT__LIBRARY_TYPE=STATIC"
+ # EVENT_ALLOW_FAILURE
- EVENT_BUILD_METHOD: "autotools"
EVENT_CONFIGURE_OPTIONS: ""
+ EVENT_ALLOW_FAILURE: 1
- EVENT_BUILD_METHOD: "autotools"
EVENT_CONFIGURE_OPTIONS: "--disable-openssl"
+ EVENT_ALLOW_FAILURE: 1
- EVENT_BUILD_METHOD: "autotools"
EVENT_CONFIGURE_OPTIONS: "--disable-thread-support"
+ EVENT_ALLOW_FAILURE: 1
- EVENT_BUILD_METHOD: "autotools"
EVENT_CONFIGURE_OPTIONS: "--disable-debug-mode"
+ EVENT_ALLOW_FAILURE: 1
- EVENT_BUILD_METHOD: "autotools"
EVENT_CONFIGURE_OPTIONS: "--disable-malloc-replacement"
- - EVENT_BUILD_METHOD: "cmake"
- EVENT_CMAKE_OPTIONS: ""
+ EVENT_ALLOW_FAILURE: 1
- EVENT_BUILD_METHOD: "cmake"
EVENT_CMAKE_OPTIONS: "-DEVENT__DISABLE_OPENSSL=ON"
+ EVENT_ALLOW_FAILURE: 1
- EVENT_BUILD_METHOD: "cmake"
EVENT_CMAKE_OPTIONS: "-DEVENT__DISABLE_THREAD_SUPPORT=ON"
+ EVENT_ALLOW_FAILURE: 1
- EVENT_BUILD_METHOD: "cmake"
EVENT_CMAKE_OPTIONS: "-DEVENT__DISABLE_DEBUG_MODE=ON"
+ EVENT_ALLOW_FAILURE: 1
- EVENT_BUILD_METHOD: "cmake"
EVENT_CMAKE_OPTIONS: "-DEVENT__DISABLE_MM_REPLACEMENT=ON"
- - EVENT_BUILD_METHOD: "cmake"
- EVENT_CMAKE_OPTIONS: "-DEVENT__ENABLE_VERBOSE_DEBUG=ON"
+ EVENT_ALLOW_FAILURE: 1
- EVENT_BUILD_METHOD: "cmake"
EVENT_CMAKE_OPTIONS: "-DCMAKE_C_FLAGS='-DUNICODE -D_UNICODE'"
+ EVENT_ALLOW_FAILURE: 1
+
+matrix:
+ allow_failures:
+ - EVENT_ALLOW_FAILURE: 1
+ fast_finish: true
+
init:
- - 'echo Building libevent %version% for Windows'
- - 'echo System architecture: %PLATFORM%'
- 'echo Repo build branch is: %APPVEYOR_REPO_BRANCH%'
- 'echo Build folder is: %APPVEYOR_BUILD_FOLDER%'
- 'echo Repo build commit is: %APPVEYOR_REPO_COMMIT%'
- - 'echo Cygwin root is: %CYG_ROOT%'
-install:
- - C:\MinGW\bin\mingw-get install autotools autoconf automake
+ - 'echo PATH is: %PATH%'
+
build_script:
- ps: |
if ($env:EVENT_BUILD_METHOD -eq 'autotools') {
- $env:PATH="$env:CYG_ROOT\bin;C:\MinGW\bin;$($env:PATH)"
- bash -lc "echo 'C:\MinGW /mingw' > /etc/fstab"
- bash -lc "echo 'C:\OpenSSL-Win32 /ssl' >> /etc/fstab"
- $env:APPVEYOR_BUILD_FOLDER = $env:APPVEYOR_BUILD_FOLDER -replace "\\", "/"
- bash -lc "exec 0</dev/null; exec 2>&1; cd $env:APPVEYOR_BUILD_FOLDER; bash -x ./autogen.sh && ./configure LDFLAGS='-L/ssl -L/ssl/lib -L/ssl/lib/MinGW' CFLAGS=-I/ssl/include $env:EVENT_CONFIGURE_OPTIONS && make && make verify -j20"
+ $env:PATH="$env:MPATH;$env:OPENSSL_ROOT/bin;$env:PATH"
+ $env:LDFLAGS="-L$($env:OPENSSL_ROOT)/lib -L$($env:OPENSSL_ROOT)"
+ $env:CFLAGS="-I$($env:OPENSSL_ROOT)/include"
+
+ bash ./autogen.sh 2>&1 3>&1
+
+ md build-autotools 2> $null
+ cd build-autotools
+
+ bash ../configure $env:EVENT_CONFIGURE_OPTIONS 2>&1
+ make -j $env:EVENT_BUILD_PARALLEL 2>&1
+ make verify -j $env:EVENT_TESTS_PARALLEL 2>&1
} else {
- md build
- cd build
- cmake .. $env:EVENT_CMAKE_OPTIONS
- cmake --build .
- $env:CTEST_PARALLEL_LEVEL="20"
- ctest --output-on-failure
+ md build-cmake 2> $null
+ cd build-cmake
+ cmake -G "Visual Studio 15 2017 Win64" .. $env:EVENT_CMAKE_OPTIONS
+ cmake --build . -j $env:EVENT_BUILD_PARALLEL -- /nologo /verbosity:minimal
+ ctest --output-on-failure -j $env:EVENT_TESTS_PARALLEL
}
+
+cache:
+ - build-cmake
+ - build-autotools
+
+on_failure:
+ - 7z a libevent.zip .
+ - appveyor PushArtifact libevent.zip
diff --git a/buffer.c b/buffer.c
index b7e3a69f..f6ff8431 100644
--- a/buffer.c
+++ b/buffer.c
@@ -95,6 +95,7 @@
#include "evthread-internal.h"
#include "evbuffer-internal.h"
#include "bufferevent-internal.h"
+#include "event-internal.h"
/* some systems do not have MAP_FAILED */
#ifndef MAP_FAILED
@@ -522,8 +523,8 @@ evbuffer_invoke_callbacks_(struct evbuffer *buffer)
evbuffer_incref_and_lock_(buffer);
if (buffer->parent)
bufferevent_incref_(buffer->parent);
+ EVBUFFER_UNLOCK(buffer);
}
- EVBUFFER_UNLOCK(buffer);
}
evbuffer_run_callbacks(buffer, 0);
@@ -1146,7 +1147,7 @@ evbuffer_drain(struct evbuffer *buf, size_t len)
}
buf->first = chain;
- EVUTIL_ASSERT(chain && remaining <= chain->off);
+ EVUTIL_ASSERT(remaining <= chain->off);
chain->misalign += remaining;
chain->off -= remaining;
}
@@ -1534,11 +1535,11 @@ evbuffer_find_eol_char(struct evbuffer_ptr *it)
return (-1);
}
-static inline int
+static inline size_t
evbuffer_strspn(
struct evbuffer_ptr *ptr, const char *chrset)
{
- int count = 0;
+ size_t count = 0;
struct evbuffer_chain *chain = ptr->internal_.chain;
size_t i = ptr->internal_.pos_in_chain;
@@ -2227,11 +2228,13 @@ evbuffer_read_setup_vecs_(struct evbuffer *buf, ev_ssize_t howmuch,
so_far = 0;
/* Let firstchain be the first chain with any space on it */
firstchainp = buf->last_with_datap;
+ EVUTIL_ASSERT(*firstchainp);
if (CHAIN_SPACE_LEN(*firstchainp) == 0) {
firstchainp = &(*firstchainp)->next;
}
chain = *firstchainp;
+ EVUTIL_ASSERT(chain);
for (i = 0; i < n_vecs_avail && so_far < (size_t)howmuch; ++i) {
size_t avail = (size_t) CHAIN_SPACE_LEN(chain);
if (avail > (howmuch - so_far) && exact)
@@ -2465,7 +2468,7 @@ evbuffer_write_sendfile(struct evbuffer *buffer, evutil_socket_t dest_fd,
ev_off_t len = chain->off;
#elif defined(SENDFILE_IS_LINUX) || defined(SENDFILE_IS_SOLARIS)
ev_ssize_t res;
- ev_off_t offset = chain->misalign;
+ off_t offset = chain->misalign;
#endif
ASSERT_EVBUFFER_LOCKED(buffer);
diff --git a/bufferevent-internal.h b/bufferevent-internal.h
index 9960aefa..c3f6b60b 100644
--- a/bufferevent-internal.h
+++ b/bufferevent-internal.h
@@ -306,6 +306,13 @@ extern const struct bufferevent_ops bufferevent_ops_pair;
#define BEV_IS_FILTER(bevp) ((bevp)->be_ops == &bufferevent_ops_filter)
#define BEV_IS_PAIR(bevp) ((bevp)->be_ops == &bufferevent_ops_pair)
+#if defined(EVENT__HAVE_OPENSSL)
+extern const struct bufferevent_ops bufferevent_ops_openssl;
+#define BEV_IS_OPENSSL(bevp) ((bevp)->be_ops == &bufferevent_ops_openssl)
+#else
+#define BEV_IS_OPENSSL(bevp) 0
+#endif
+
#ifdef _WIN32
extern const struct bufferevent_ops bufferevent_ops_async;
#define BEV_IS_ASYNC(bevp) ((bevp)->be_ops == &bufferevent_ops_async)
@@ -314,13 +321,16 @@ extern const struct bufferevent_ops bufferevent_ops_async;
#endif
/** Initialize the shared parts of a bufferevent. */
+EVENT2_EXPORT_SYMBOL
int bufferevent_init_common_(struct bufferevent_private *, struct event_base *, const struct bufferevent_ops *, enum bufferevent_options options);
/** For internal use: temporarily stop all reads on bufev, until the conditions
* in 'what' are over. */
+EVENT2_EXPORT_SYMBOL
void bufferevent_suspend_read_(struct bufferevent *bufev, bufferevent_suspend_flags what);
/** For internal use: clear the conditions 'what' on bufev, and re-enable
* reading if there are no conditions left. */
+EVENT2_EXPORT_SYMBOL
void bufferevent_unsuspend_read_(struct bufferevent *bufev, bufferevent_suspend_flags what);
/** For internal use: temporarily stop all writes on bufev, until the conditions
@@ -347,16 +357,19 @@ void bufferevent_unsuspend_write_(struct bufferevent *bufev, bufferevent_suspend
@return 0 if successful, or -1 if an error occurred
@see bufferevent_disable()
*/
+EVENT2_EXPORT_SYMBOL
int bufferevent_disable_hard_(struct bufferevent *bufev, short event);
/** Internal: Set up locking on a bufferevent. If lock is set, use it.
* Otherwise, use a new lock. */
+EVENT2_EXPORT_SYMBOL
int bufferevent_enable_locking_(struct bufferevent *bufev, void *lock);
/** Internal: backwards compat macro for the now public function
* Increment the reference count on bufev. */
#define bufferevent_incref_(bufev) bufferevent_incref(bufev)
/** Internal: Lock bufev and increase its reference count.
* unlocking it otherwise. */
+EVENT2_EXPORT_SYMBOL
void bufferevent_incref_and_lock_(struct bufferevent *bufev);
/** Internal: backwards compat macro for the now public function
* Decrement the reference count on bufev. Returns 1 if it freed
@@ -365,17 +378,21 @@ void bufferevent_incref_and_lock_(struct bufferevent *bufev);
/** Internal: Drop the reference count on bufev, freeing as necessary, and
* unlocking it otherwise. Returns 1 if it freed the bufferevent. */
+EVENT2_EXPORT_SYMBOL
int bufferevent_decref_and_unlock_(struct bufferevent *bufev);
/** Internal: If callbacks are deferred and we have a read callback, schedule
* a readcb. Otherwise just run the readcb. Ignores watermarks. */
+EVENT2_EXPORT_SYMBOL
void bufferevent_run_readcb_(struct bufferevent *bufev, int options);
/** Internal: If callbacks are deferred and we have a write callback, schedule
* a writecb. Otherwise just run the writecb. Ignores watermarks. */
+EVENT2_EXPORT_SYMBOL
void bufferevent_run_writecb_(struct bufferevent *bufev, int options);
/** Internal: If callbacks are deferred and we have an eventcb, schedule
* it to run with events "what". Otherwise just run the eventcb.
* See bufferevent_trigger_event for meaning of "options". */
+EVENT2_EXPORT_SYMBOL
void bufferevent_run_eventcb_(struct bufferevent *bufev, short what, int options);
/** Internal: Run or schedule (if deferred or options contain
@@ -399,6 +416,7 @@ bufferevent_trigger_nolock_(struct bufferevent *bufev, short iotype, int options
/** Internal: Add the event 'ev' with timeout tv, unless tv is set to 0, in
* which case add ev with no timeout. */
+EVENT2_EXPORT_SYMBOL
int bufferevent_add_event_(struct event *ev, const struct timeval *tv);
/* =========
@@ -408,19 +426,33 @@ int bufferevent_add_event_(struct event *ev, const struct timeval *tv);
/** Internal use: Set up the ev_read and ev_write callbacks so that
* the other "generic_timeout" functions will work on it. Call this from
* the constructor function. */
+EVENT2_EXPORT_SYMBOL
void bufferevent_init_generic_timeout_cbs_(struct bufferevent *bev);
/** Internal use: Add or delete the generic timeout events as appropriate.
* (If an event is enabled and a timeout is set, we add the event. Otherwise
* we delete it.) Call this from anything that changes the timeout values,
* that enabled EV_READ or EV_WRITE, or that disables EV_READ or EV_WRITE. */
+EVENT2_EXPORT_SYMBOL
int bufferevent_generic_adj_timeouts_(struct bufferevent *bev);
+EVENT2_EXPORT_SYMBOL
int bufferevent_generic_adj_existing_timeouts_(struct bufferevent *bev);
+EVENT2_EXPORT_SYMBOL
enum bufferevent_options bufferevent_get_options_(struct bufferevent *bev);
+EVENT2_EXPORT_SYMBOL
const struct sockaddr*
bufferevent_socket_get_conn_address_(struct bufferevent *bev);
+EVENT2_EXPORT_SYMBOL
+void
+bufferevent_socket_set_conn_address_fd_(struct bufferevent *bev, int fd);
+
+EVENT2_EXPORT_SYMBOL
+void
+bufferevent_socket_set_conn_address_(struct bufferevent *bev, struct sockaddr *addr, size_t addrlen);
+
+
/** Internal use: We have just successfully read data into an inbuf, so
* reset the read timeout (if any). */
#define BEV_RESET_GENERIC_READ_TIMEOUT(bev) \
@@ -465,11 +497,15 @@ bufferevent_socket_get_conn_address_(struct bufferevent *bev);
/* ==== For rate-limiting. */
+EVENT2_EXPORT_SYMBOL
int bufferevent_decrement_write_buckets_(struct bufferevent_private *bev,
ev_ssize_t bytes);
+EVENT2_EXPORT_SYMBOL
int bufferevent_decrement_read_buckets_(struct bufferevent_private *bev,
ev_ssize_t bytes);
+EVENT2_EXPORT_SYMBOL
ev_ssize_t bufferevent_get_read_max_(struct bufferevent_private *bev);
+EVENT2_EXPORT_SYMBOL
ev_ssize_t bufferevent_get_write_max_(struct bufferevent_private *bev);
int bufferevent_ratelim_init_(struct bufferevent_private *bev);
diff --git a/bufferevent.c b/bufferevent.c
index 490b5983..ef7c2eaf 100644
--- a/bufferevent.c
+++ b/bufferevent.c
@@ -66,8 +66,7 @@ static void bufferevent_finalize_cb_(struct event_callback *evcb, void *arg_);
void
bufferevent_suspend_read_(struct bufferevent *bufev, bufferevent_suspend_flags what)
{
- struct bufferevent_private *bufev_private =
- EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
+ struct bufferevent_private *bufev_private = BEV_UPCAST(bufev);
BEV_LOCK(bufev);
if (!bufev_private->read_suspended)
bufev->be_ops->disable(bufev, EV_READ);
@@ -78,8 +77,7 @@ bufferevent_suspend_read_(struct bufferevent *bufev, bufferevent_suspend_flags w
void
bufferevent_unsuspend_read_(struct bufferevent *bufev, bufferevent_suspend_flags what)
{
- struct bufferevent_private *bufev_private =
- EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
+ struct bufferevent_private *bufev_private = BEV_UPCAST(bufev);
BEV_LOCK(bufev);
bufev_private->read_suspended &= ~what;
if (!bufev_private->read_suspended && (bufev->enabled & EV_READ))
@@ -90,8 +88,7 @@ bufferevent_unsuspend_read_(struct bufferevent *bufev, bufferevent_suspend_flags
void
bufferevent_suspend_write_(struct bufferevent *bufev, bufferevent_suspend_flags what)
{
- struct bufferevent_private *bufev_private =
- EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
+ struct bufferevent_private *bufev_private = BEV_UPCAST(bufev);
BEV_LOCK(bufev);
if (!bufev_private->write_suspended)
bufev->be_ops->disable(bufev, EV_WRITE);
@@ -102,8 +99,7 @@ bufferevent_suspend_write_(struct bufferevent *bufev, bufferevent_suspend_flags
void
bufferevent_unsuspend_write_(struct bufferevent *bufev, bufferevent_suspend_flags what)
{
- struct bufferevent_private *bufev_private =
- EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
+ struct bufferevent_private *bufev_private = BEV_UPCAST(bufev);
BEV_LOCK(bufev);
bufev_private->write_suspended &= ~what;
if (!bufev_private->write_suspended && (bufev->enabled & EV_WRITE))
@@ -111,6 +107,28 @@ bufferevent_unsuspend_write_(struct bufferevent *bufev, bufferevent_suspend_flag
BEV_UNLOCK(bufev);
}
+/**
+ * Sometimes bufferevent's implementation can overrun high watermarks
+ * (one of examples is openssl) and in this case if the read callback
+ * will not handle enough data do over condition above the read
+ * callback will never be called again (due to suspend above).
+ *
+ * To avoid this we are scheduling read callback again here, but only
+ * from the user callback to avoid multiple scheduling:
+ * - when the data had been added to it
+ * - when the data had been drained from it (user specified read callback)
+ */
+static void bufferevent_inbuf_wm_check(struct bufferevent *bev)
+{
+ if (!bev->wm_read.high)
+ return;
+ if (!(bev->enabled & EV_READ))
+ return;
+ if (evbuffer_get_length(bev->input) < bev->wm_read.high)
+ return;
+
+ bufferevent_trigger(bev, EV_READ, BEV_OPT_DEFER_CALLBACKS);
+}
/* Callback to implement watermarks on the input buffer. Only enabled
* if the watermark is set. */
@@ -147,6 +165,7 @@ bufferevent_run_deferred_callbacks_locked(struct event_callback *cb, void *arg)
if (bufev_private->readcb_pending && bufev->readcb) {
bufev_private->readcb_pending = 0;
bufev->readcb(bufev, bufev->cbarg);
+ bufferevent_inbuf_wm_check(bufev);
}
if (bufev_private->writecb_pending && bufev->writecb) {
bufev_private->writecb_pending = 0;
@@ -187,6 +206,7 @@ bufferevent_run_deferred_callbacks_unlocked(struct event_callback *cb, void *arg
void *cbarg = bufev->cbarg;
bufev_private->readcb_pending = 0;
UNLOCKED(readcb(bufev, cbarg));
+ bufferevent_inbuf_wm_check(bufev);
}
if (bufev_private->writecb_pending && bufev->writecb) {
bufferevent_data_cb writecb = bufev->writecb;
@@ -221,8 +241,7 @@ void
bufferevent_run_readcb_(struct bufferevent *bufev, int options)
{
/* Requires that we hold the lock and a reference */
- struct bufferevent_private *p =
- EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
+ struct bufferevent_private *p = BEV_UPCAST(bufev);
if (bufev->readcb == NULL)
return;
if ((p->options|options) & BEV_OPT_DEFER_CALLBACKS) {
@@ -230,6 +249,7 @@ bufferevent_run_readcb_(struct bufferevent *bufev, int options)
SCHEDULE_DEFERRED(p);
} else {
bufev->readcb(bufev, bufev->cbarg);
+ bufferevent_inbuf_wm_check(bufev);
}
}
@@ -237,8 +257,7 @@ void
bufferevent_run_writecb_(struct bufferevent *bufev, int options)
{
/* Requires that we hold the lock and a reference */
- struct bufferevent_private *p =
- EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
+ struct bufferevent_private *p = BEV_UPCAST(bufev);
if (bufev->writecb == NULL)
return;
if ((p->options|options) & BEV_OPT_DEFER_CALLBACKS) {
@@ -266,8 +285,7 @@ void
bufferevent_run_eventcb_(struct bufferevent *bufev, short what, int options)
{
/* Requires that we hold the lock and a reference */
- struct bufferevent_private *p =
- EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
+ struct bufferevent_private *p = BEV_UPCAST(bufev);
if (bufev->errorcb == NULL)
return;
if ((p->options|options) & BEV_OPT_DEFER_CALLBACKS) {
@@ -459,8 +477,7 @@ bufferevent_read_buffer(struct bufferevent *bufev, struct evbuffer *buf)
int
bufferevent_enable(struct bufferevent *bufev, short event)
{
- struct bufferevent_private *bufev_private =
- EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
+ struct bufferevent_private *bufev_private = BEV_UPCAST(bufev);
short impl_events = event;
int r = 0;
@@ -474,6 +491,8 @@ bufferevent_enable(struct bufferevent *bufev, short event)
if (impl_events && bufev->be_ops->enable(bufev, impl_events) < 0)
r = -1;
+ if (r)
+ event_debug(("%s: cannot enable 0x%hx on %p", __func__, event, bufev));
bufferevent_decref_and_unlock_(bufev);
return r;
@@ -533,8 +552,7 @@ int
bufferevent_disable_hard_(struct bufferevent *bufev, short event)
{
int r = 0;
- struct bufferevent_private *bufev_private =
- EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
+ struct bufferevent_private *bufev_private = BEV_UPCAST(bufev);
BEV_LOCK(bufev);
bufev->enabled &= ~event;
@@ -557,6 +575,8 @@ bufferevent_disable(struct bufferevent *bufev, short event)
if (bufev->be_ops->disable(bufev, event) < 0)
r = -1;
+ if (r)
+ event_debug(("%s: cannot disable 0x%hx on %p", __func__, event, bufev));
BEV_UNLOCK(bufev);
return r;
@@ -570,8 +590,7 @@ void
bufferevent_setwatermark(struct bufferevent *bufev, short events,
size_t lowmark, size_t highmark)
{
- struct bufferevent_private *bufev_private =
- EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
+ struct bufferevent_private *bufev_private = BEV_UPCAST(bufev);
BEV_LOCK(bufev);
if (events & EV_WRITE) {
@@ -656,8 +675,7 @@ bufferevent_flush(struct bufferevent *bufev,
void
bufferevent_incref_and_lock_(struct bufferevent *bufev)
{
- struct bufferevent_private *bufev_private =
- BEV_UPCAST(bufev);
+ struct bufferevent_private *bufev_private = BEV_UPCAST(bufev);
BEV_LOCK(bufev);
++bufev_private->refcnt;
}
@@ -683,8 +701,7 @@ bufferevent_transfer_lock_ownership_(struct bufferevent *donor,
int
bufferevent_decref_and_unlock_(struct bufferevent *bufev)
{
- struct bufferevent_private *bufev_private =
- EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
+ struct bufferevent_private *bufev_private = BEV_UPCAST(bufev);
int n_cbs = 0;
#define MAX_CBS 16
struct event_callback *cbs[MAX_CBS];
@@ -727,8 +744,7 @@ bufferevent_finalize_cb_(struct event_callback *evcb, void *arg_)
{
struct bufferevent *bufev = arg_;
struct bufferevent *underlying;
- struct bufferevent_private *bufev_private =
- EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
+ struct bufferevent_private *bufev_private = BEV_UPCAST(bufev);
BEV_LOCK(bufev);
underlying = bufferevent_get_underlying(bufev);
@@ -794,8 +810,7 @@ bufferevent_free(struct bufferevent *bufev)
void
bufferevent_incref(struct bufferevent *bufev)
{
- struct bufferevent_private *bufev_private =
- EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
+ struct bufferevent_private *bufev_private = BEV_UPCAST(bufev);
/* XXX: now that this function is public, we might want to
* - return the count from this function
@@ -851,6 +866,8 @@ bufferevent_setfd(struct bufferevent *bev, evutil_socket_t fd)
BEV_LOCK(bev);
if (bev->be_ops->ctrl)
res = bev->be_ops->ctrl(bev, BEV_CTRL_SET_FD, &d);
+ if (res)
+ event_debug(("%s: cannot set fd for %p to "EV_SOCK_FMT, __func__, bev, fd));
BEV_UNLOCK(bev);
return res;
}
@@ -864,6 +881,8 @@ bufferevent_getfd(struct bufferevent *bev)
BEV_LOCK(bev);
if (bev->be_ops->ctrl)
res = bev->be_ops->ctrl(bev, BEV_CTRL_GET_FD, &d);
+ if (res)
+ event_debug(("%s: cannot get fd for %p", __func__, bev));
BEV_UNLOCK(bev);
return (res<0) ? -1 : d.fd;
}
@@ -871,8 +890,7 @@ bufferevent_getfd(struct bufferevent *bev)
enum bufferevent_options
bufferevent_get_options_(struct bufferevent *bev)
{
- struct bufferevent_private *bev_p =
- EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
+ struct bufferevent_private *bev_p = BEV_UPCAST(bev);
enum bufferevent_options options;
BEV_LOCK(bev);
@@ -948,8 +966,7 @@ int
bufferevent_generic_adj_timeouts_(struct bufferevent *bev)
{
const short enabled = bev->enabled;
- struct bufferevent_private *bev_p =
- EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
+ struct bufferevent_private *bev_p = BEV_UPCAST(bev);
int r1=0, r2=0;
if ((enabled & EV_READ) && !bev_p->read_suspended &&
evutil_timerisset(&bev->timeout_read))
diff --git a/bufferevent_async.c b/bufferevent_async.c
index 6395e57a..141cf34f 100644
--- a/bufferevent_async.c
+++ b/bufferevent_async.c
@@ -100,11 +100,32 @@ const struct bufferevent_ops bufferevent_ops_async = {
be_async_ctrl,
};
+static inline void
+be_async_run_eventcb(struct bufferevent *bev, short what, int options)
+{ bufferevent_run_eventcb_(bev, what, options|BEV_TRIG_DEFER_CALLBACKS); }
+
+static inline void
+be_async_trigger_nolock(struct bufferevent *bev, short what, int options)
+{ bufferevent_trigger_nolock_(bev, what, options|BEV_TRIG_DEFER_CALLBACKS); }
+
+static inline int
+fatal_error(int err)
+{
+ switch (err) {
+ /* We may have already associated this fd with a port.
+ * Let's hope it's this port, and that the error code
+ * for doing this neer changes. */
+ case ERROR_INVALID_PARAMETER:
+ return 0;
+ }
+ return 1;
+}
+
static inline struct bufferevent_async *
upcast(struct bufferevent *bev)
{
struct bufferevent_async *bev_a;
- if (bev->be_ops != &bufferevent_ops_async)
+ if (!BEV_IS_ASYNC(bev))
return NULL;
bev_a = EVUTIL_UPCAST(bev, struct bufferevent_async, bev.bev);
return bev_a;
@@ -217,7 +238,7 @@ bev_async_consider_writing(struct bufferevent_async *beva)
&beva->write_overlapped)) {
bufferevent_decref_(bev);
beva->ok = 0;
- bufferevent_run_eventcb_(bev, BEV_EVENT_ERROR, 0);
+ be_async_run_eventcb(bev, BEV_EVENT_ERROR, 0);
} else {
beva->write_in_progress = at_most;
bufferevent_decrement_write_buckets_(&beva->bev, at_most);
@@ -270,7 +291,7 @@ bev_async_consider_reading(struct bufferevent_async *beva)
bufferevent_incref_(bev);
if (evbuffer_launch_read_(bev->input, at_most, &beva->read_overlapped)) {
beva->ok = 0;
- bufferevent_run_eventcb_(bev, BEV_EVENT_ERROR, 0);
+ be_async_run_eventcb(bev, BEV_EVENT_ERROR, 0);
bufferevent_decref_(bev);
} else {
beva->read_in_progress = at_most;
@@ -381,10 +402,10 @@ be_async_destruct(struct bufferevent *bev)
bev_async_del_write(bev_async);
fd = evbuffer_overlapped_get_fd_(bev->input);
- if (fd != (evutil_socket_t)INVALID_SOCKET &&
+ if (fd != (evutil_socket_t)EVUTIL_INVALID_SOCKET &&
(bev_p->options & BEV_OPT_CLOSE_ON_FREE)) {
evutil_closesocket(fd);
- evbuffer_overlapped_set_fd_(bev->input, INVALID_SOCKET);
+ evbuffer_overlapped_set_fd_(bev->input, EVUTIL_INVALID_SOCKET);
}
}
@@ -428,8 +449,7 @@ connect_complete(struct event_overlapped *eo, ev_uintptr_t key,
else
bev_async_set_wsa_error(bev, eo);
- bufferevent_run_eventcb_(bev,
- ok? BEV_EVENT_CONNECTED : BEV_EVENT_ERROR, 0);
+ be_async_run_eventcb(bev, ok ? BEV_EVENT_CONNECTED : BEV_EVENT_ERROR, 0);
event_base_del_virtual_(bev->ev_base);
@@ -459,16 +479,16 @@ read_complete(struct event_overlapped *eo, ev_uintptr_t key,
if (bev_a->ok) {
if (ok && nbytes) {
BEV_RESET_GENERIC_READ_TIMEOUT(bev);
- bufferevent_trigger_nolock_(bev, EV_READ, 0);
+ be_async_trigger_nolock(bev, EV_READ, 0);
bev_async_consider_reading(bev_a);
} else if (!ok) {
what |= BEV_EVENT_ERROR;
bev_a->ok = 0;
- bufferevent_run_eventcb_(bev, what, 0);
+ be_async_run_eventcb(bev, what, 0);
} else if (!nbytes) {
what |= BEV_EVENT_EOF;
bev_a->ok = 0;
- bufferevent_run_eventcb_(bev, what, 0);
+ be_async_run_eventcb(bev, what, 0);
}
}
@@ -502,16 +522,16 @@ write_complete(struct event_overlapped *eo, ev_uintptr_t key,
if (bev_a->ok) {
if (ok && nbytes) {
BEV_RESET_GENERIC_WRITE_TIMEOUT(bev);
- bufferevent_trigger_nolock_(bev, EV_WRITE, 0);
+ be_async_trigger_nolock(bev, EV_WRITE, 0);
bev_async_consider_writing(bev_a);
} else if (!ok) {
what |= BEV_EVENT_ERROR;
bev_a->ok = 0;
- bufferevent_run_eventcb_(bev, what, 0);
+ be_async_run_eventcb(bev, what, 0);
} else if (!nbytes) {
what |= BEV_EVENT_EOF;
bev_a->ok = 0;
- bufferevent_run_eventcb_(bev, what, 0);
+ be_async_run_eventcb(bev, what, 0);
}
}
@@ -532,11 +552,7 @@ bufferevent_async_new_(struct event_base *base,
return NULL;
if (fd >= 0 && event_iocp_port_associate_(iocp, fd, 1)<0) {
- int err = GetLastError();
- /* We may have alrady associated this fd with a port.
- * Let's hope it's this port, and that the error code
- * for doing this neer changes. */
- if (err != ERROR_INVALID_PARAMETER)
+ if (fatal_error(GetLastError()))
return NULL;
}
@@ -580,7 +596,6 @@ bufferevent_async_set_connected_(struct bufferevent *bev)
{
struct bufferevent_async *bev_async = upcast(bev);
bev_async->ok = 1;
- bufferevent_init_generic_timeout_cbs_(bev);
/* Now's a good time to consider reading/writing */
be_async_enable(bev, bev->enabled);
}
@@ -654,25 +669,29 @@ be_async_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op,
data->fd = evbuffer_overlapped_get_fd_(bev->input);
return 0;
case BEV_CTRL_SET_FD: {
+ struct bufferevent_async *bev_a = upcast(bev);
struct event_iocp_port *iocp;
if (data->fd == evbuffer_overlapped_get_fd_(bev->input))
return 0;
if (!(iocp = event_base_get_iocp_(bev->ev_base)))
return -1;
- if (event_iocp_port_associate_(iocp, data->fd, 1) < 0)
- return -1;
+ if (event_iocp_port_associate_(iocp, data->fd, 1) < 0) {
+ if (fatal_error(GetLastError()))
+ return -1;
+ }
evbuffer_overlapped_set_fd_(bev->input, data->fd);
evbuffer_overlapped_set_fd_(bev->output, data->fd);
+ bev_a->ok = data->fd >= 0;
return 0;
}
case BEV_CTRL_CANCEL_ALL: {
struct bufferevent_async *bev_a = upcast(bev);
evutil_socket_t fd = evbuffer_overlapped_get_fd_(bev->input);
- if (fd != (evutil_socket_t)INVALID_SOCKET &&
+ if (fd != (evutil_socket_t)EVUTIL_INVALID_SOCKET &&
(bev_a->bev.options & BEV_OPT_CLOSE_ON_FREE)) {
closesocket(fd);
- evbuffer_overlapped_set_fd_(bev->input, INVALID_SOCKET);
+ evbuffer_overlapped_set_fd_(bev->input, EVUTIL_INVALID_SOCKET);
}
bev_a->ok = 0;
return 0;
diff --git a/bufferevent_filter.c b/bufferevent_filter.c
index d47f9452..a7bdeddd 100644
--- a/bufferevent_filter.c
+++ b/bufferevent_filter.c
@@ -118,11 +118,11 @@ static inline struct bufferevent_filtered *
upcast(struct bufferevent *bev)
{
struct bufferevent_filtered *bev_f;
- if (bev->be_ops != &bufferevent_ops_filter)
+ if (!BEV_IS_FILTER(bev))
return NULL;
bev_f = (void*)( ((char*)bev) -
evutil_offsetof(struct bufferevent_filtered, bev.bev));
- EVUTIL_ASSERT(bev_f->bev.bev.be_ops == &bufferevent_ops_filter);
+ EVUTIL_ASSERT(BEV_IS_FILTER(&bev_f->bev.bev));
return bev_f;
}
@@ -160,7 +160,7 @@ be_null_filter(struct evbuffer *src, struct evbuffer *dst, ev_ssize_t lim,
enum bufferevent_flush_mode state, void *ctx)
{
(void)state;
- if (evbuffer_remove_buffer(src, dst, lim) == 0)
+ if (evbuffer_remove_buffer(src, dst, lim) >= 0)
return BEV_OK;
else
return BEV_ERROR;
@@ -605,6 +605,7 @@ be_filter_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op,
data->ptr = bevf->underlying;
return 0;
case BEV_CTRL_SET_FD:
+ case BEV_CTRL_GET_FD:
bevf = upcast(bev);
if (bevf->underlying &&
@@ -612,9 +613,10 @@ be_filter_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op,
bevf->underlying->be_ops->ctrl) {
return (bevf->underlying->be_ops->ctrl)(bevf->underlying, op, data);
}
+ EVUTIL_FALLTHROUGH;
- case BEV_CTRL_GET_FD:
case BEV_CTRL_CANCEL_ALL:
+ EVUTIL_FALLTHROUGH;
default:
return -1;
}
diff --git a/bufferevent_openssl.c b/bufferevent_openssl.c
index da3963af..beebe071 100644
--- a/bufferevent_openssl.c
+++ b/bufferevent_openssl.c
@@ -63,7 +63,6 @@
#include "bufferevent-internal.h"
#include "log-internal.h"
-#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include "openssl-compat.h"
@@ -155,7 +154,7 @@ bio_bufferevent_read(BIO *b, char *out, int outlen)
return r;
}
-/* Called to write data info the BIO */
+/* Called to write data into the BIO */
static int
bio_bufferevent_write(BIO *b, const char *in, int inlen)
{
@@ -251,7 +250,7 @@ BIO_s_bufferevent(void)
/* Create a new BIO to wrap communication around a bufferevent. If close_flag
* is true, the bufferevent will be freed when the BIO is closed. */
static BIO *
-BIO_new_bufferevent(struct bufferevent *bufferevent, int close_flag)
+BIO_new_bufferevent(struct bufferevent *bufferevent)
{
BIO *result;
if (!bufferevent)
@@ -260,7 +259,9 @@ BIO_new_bufferevent(struct bufferevent *bufferevent, int close_flag)
return NULL;
BIO_set_init(result, 1);
BIO_set_data(result, bufferevent);
- BIO_set_shutdown(result, close_flag ? 1 : 0);
+ /* We don't tell the BIO to close the bufferevent; we do it ourselves on
+ * be_openssl_destruct() */
+ BIO_set_shutdown(result, 0);
return result;
}
@@ -354,11 +355,11 @@ static inline struct bufferevent_openssl *
upcast(struct bufferevent *bev)
{
struct bufferevent_openssl *bev_o;
- if (bev->be_ops != &bufferevent_ops_openssl)
+ if (!BEV_IS_OPENSSL(bev))
return NULL;
bev_o = (void*)( ((char*)bev) -
evutil_offsetof(struct bufferevent_openssl, bev.bev));
- EVUTIL_ASSERT(bev_o->bev.bev.be_ops == &bufferevent_ops_openssl);
+ EVUTIL_ASSERT(BEV_IS_OPENSSL(&bev_o->bev.bev));
return bev_o;
}
@@ -803,7 +804,7 @@ consider_reading(struct bufferevent_openssl *bev_ssl)
if (bev_ssl->bev.read_suspended)
break;
-
+
/* Read all pending data. This won't hit the network
* again, and will (most importantly) put us in a state
* where we don't need to read anything else until the
@@ -963,8 +964,8 @@ be_openssl_writeeventcb(evutil_socket_t fd, short what, void *ptr)
bufferevent_decref_and_unlock_(&bev_ssl->bev.bev);
}
-static int
-be_openssl_auto_fd(struct bufferevent_openssl *bev_ssl, int fd)
+static evutil_socket_t
+be_openssl_auto_fd(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
{
if (!bev_ssl->underlying) {
struct bufferevent *bev = &bev_ssl->bev.bev;
@@ -1030,7 +1031,7 @@ do_handshake(struct bufferevent_openssl *bev_ssl)
decrement_buckets(bev_ssl);
if (r==1) {
- int fd = event_get_fd(&bev_ssl->bev.bev.ev_read);
+ evutil_socket_t fd = event_get_fd(&bev_ssl->bev.bev.ev_read);
/* We're done! */
bev_ssl->state = BUFFEREVENT_SSL_OPEN;
set_open_callbacks(bev_ssl, fd); /* XXXX handle failure */
@@ -1228,7 +1229,7 @@ be_openssl_destruct(struct bufferevent *bev)
if (bev_ssl->bev.options & BEV_OPT_CLOSE_ON_FREE) {
if (! bev_ssl->underlying) {
- evutil_socket_t fd = -1;
+ evutil_socket_t fd = EVUTIL_INVALID_SOCKET;
BIO *bio = SSL_get_wbio(bev_ssl->ssl);
if (bio)
fd = BIO_get_fd(bio, NULL);
@@ -1261,17 +1262,21 @@ be_openssl_flush(struct bufferevent *bufev,
static int
be_openssl_set_fd(struct bufferevent_openssl *bev_ssl,
- enum bufferevent_ssl_state state, int fd)
+ enum bufferevent_ssl_state state, evutil_socket_t fd)
{
bev_ssl->state = state;
switch (state) {
case BUFFEREVENT_SSL_ACCEPTING:
+ if (!SSL_clear(bev_ssl->ssl))
+ return -1;
SSL_set_accept_state(bev_ssl->ssl);
if (set_handshake_callbacks(bev_ssl, fd) < 0)
return -1;
break;
case BUFFEREVENT_SSL_CONNECTING:
+ if (!SSL_clear(bev_ssl->ssl))
+ return -1;
SSL_set_connect_state(bev_ssl->ssl);
if (set_handshake_callbacks(bev_ssl, fd) < 0)
return -1;
@@ -1296,11 +1301,11 @@ be_openssl_ctrl(struct bufferevent *bev,
case BEV_CTRL_SET_FD:
if (!bev_ssl->underlying) {
BIO *bio;
- bio = BIO_new_socket(data->fd, 0);
+ bio = BIO_new_socket((int)data->fd, 0);
SSL_set_bio(bev_ssl->ssl, bio, bio);
} else {
BIO *bio;
- if (!(bio = BIO_new_bufferevent(bev_ssl->underlying, 0)))
+ if (!(bio = BIO_new_bufferevent(bev_ssl->underlying)))
return -1;
SSL_set_bio(bev_ssl->ssl, bio, bio);
}
@@ -1343,8 +1348,9 @@ bufferevent_openssl_new_impl(struct event_base *base,
struct bufferevent_private *bev_p = NULL;
int tmp_options = options & ~BEV_OPT_THREADSAFE;
+ /* Only one can be set. */
if (underlying != NULL && fd >= 0)
- return NULL; /* Only one can be set. */
+ goto err;
if (!(bev_ssl = mm_calloc(1, sizeof(struct bufferevent_openssl))))
goto err;
@@ -1392,8 +1398,12 @@ bufferevent_openssl_new_impl(struct event_base *base,
return &bev_ssl->bev.bev;
err:
- if (bev_ssl)
+ if (options & BEV_OPT_CLOSE_ON_FREE)
+ SSL_free(ssl);
+ if (bev_ssl) {
+ bev_ssl->ssl = NULL;
bufferevent_free(&bev_ssl->bev.bev);
+ }
return NULL;
}
@@ -1404,19 +1414,24 @@ bufferevent_openssl_filter_new(struct event_base *base,
enum bufferevent_ssl_state state,
int options)
{
- /* We don't tell the BIO to close the bufferevent; we do it ourselves
- * on be_openssl_destruct */
- int close_flag = 0; /* options & BEV_OPT_CLOSE_ON_FREE; */
BIO *bio;
+ struct bufferevent *bev;
+
if (!underlying)
- return NULL;
- if (!(bio = BIO_new_bufferevent(underlying, close_flag)))
- return NULL;
+ goto err;
+ if (!(bio = BIO_new_bufferevent(underlying)))
+ goto err;
SSL_set_bio(ssl, bio, bio);
- return bufferevent_openssl_new_impl(
+ bev = bufferevent_openssl_new_impl(
base, underlying, -1, ssl, state, options);
+ return bev;
+
+err:
+ if (options & BEV_OPT_CLOSE_ON_FREE)
+ SSL_free(ssl);
+ return NULL;
}
struct bufferevent *
@@ -1443,14 +1458,14 @@ bufferevent_openssl_socket_new(struct event_base *base,
} else {
/* We specified an fd different from that of the SSL.
This is probably an error on our part. Fail. */
- return NULL;
+ goto err;
}
- (void) BIO_set_close(bio, 0);
+ BIO_set_close(bio, 0);
} else {
/* The SSL isn't configured with a BIO with an fd. */
if (fd >= 0) {
/* ... and we have an fd we want to use. */
- bio = BIO_new_socket(fd, 0);
+ bio = BIO_new_socket((int)fd, 0);
SSL_set_bio(ssl, bio, bio);
} else {
/* Leave the fd unset. */
@@ -1459,6 +1474,11 @@ bufferevent_openssl_socket_new(struct event_base *base,
return bufferevent_openssl_new_impl(
base, NULL, fd, ssl, state, options);
+
+err:
+ if (options & BEV_OPT_CLOSE_ON_FREE)
+ SSL_free(ssl);
+ return NULL;
}
int
diff --git a/bufferevent_pair.c b/bufferevent_pair.c
index 1e93f572..f88cd751 100644
--- a/bufferevent_pair.c
+++ b/bufferevent_pair.c
@@ -56,10 +56,10 @@ static inline struct bufferevent_pair *
upcast(struct bufferevent *bev)
{
struct bufferevent_pair *bev_p;
- if (bev->be_ops != &bufferevent_ops_pair)
+ if (!BEV_IS_PAIR(bev))
return NULL;
bev_p = EVUTIL_UPCAST(bev, struct bufferevent_pair, bev.bev);
- EVUTIL_ASSERT(bev_p->bev.bev.be_ops == &bufferevent_ops_pair);
+ EVUTIL_ASSERT(BEV_IS_PAIR(&bev_p->bev.bev));
return bev_p;
}
diff --git a/bufferevent_ratelim.c b/bufferevent_ratelim.c
index bde19202..25874968 100644
--- a/bufferevent_ratelim.c
+++ b/bufferevent_ratelim.c
@@ -560,8 +560,7 @@ int
bufferevent_set_rate_limit(struct bufferevent *bev,
struct ev_token_bucket_cfg *cfg)
{
- struct bufferevent_private *bevp =
- EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
+ struct bufferevent_private *bevp = BEV_UPCAST(bev);
int r = -1;
struct bufferevent_rate_limit *rlim;
struct timeval now;
@@ -737,8 +736,7 @@ bufferevent_add_to_rate_limit_group(struct bufferevent *bev,
struct bufferevent_rate_limit_group *g)
{
int wsuspend, rsuspend;
- struct bufferevent_private *bevp =
- EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
+ struct bufferevent_private *bevp = BEV_UPCAST(bev);
BEV_LOCK(bev);
if (!bevp->rate_limiting) {
@@ -789,8 +787,7 @@ int
bufferevent_remove_from_rate_limit_group_internal_(struct bufferevent *bev,
int unsuspend)
{
- struct bufferevent_private *bevp =
- EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
+ struct bufferevent_private *bevp = BEV_UPCAST(bev);
BEV_LOCK(bev);
if (bevp->rate_limiting && bevp->rate_limiting->group) {
struct bufferevent_rate_limit_group *g =
diff --git a/bufferevent_sock.c b/bufferevent_sock.c
index 93aedb33..f275b023 100644
--- a/bufferevent_sock.c
+++ b/bufferevent_sock.c
@@ -99,24 +99,28 @@ const struct bufferevent_ops bufferevent_ops_socket = {
const struct sockaddr*
bufferevent_socket_get_conn_address_(struct bufferevent *bev)
{
- struct bufferevent_private *bev_p =
- EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
-
+ struct bufferevent_private *bev_p = BEV_UPCAST(bev);
return (struct sockaddr *)&bev_p->conn_address;
}
-static void
-bufferevent_socket_set_conn_address_fd(struct bufferevent_private *bev_p, int fd)
+
+void
+bufferevent_socket_set_conn_address_fd_(struct bufferevent *bev,
+ evutil_socket_t fd)
{
+ struct bufferevent_private *bev_p = BEV_UPCAST(bev);
+
socklen_t len = sizeof(bev_p->conn_address);
struct sockaddr *addr = (struct sockaddr *)&bev_p->conn_address;
if (addr->sa_family != AF_UNSPEC)
getpeername(fd, addr, &len);
}
-static void
-bufferevent_socket_set_conn_address(struct bufferevent_private *bev_p,
+
+void
+bufferevent_socket_set_conn_address_(struct bufferevent *bev,
struct sockaddr *addr, size_t addrlen)
{
+ struct bufferevent_private *bev_p = BEV_UPCAST(bev);
EVUTIL_ASSERT(addrlen <= sizeof(bev_p->conn_address));
memcpy(&bev_p->conn_address, addr, addrlen);
}
@@ -127,8 +131,7 @@ bufferevent_socket_outbuf_cb(struct evbuffer *buf,
void *arg)
{
struct bufferevent *bufev = arg;
- struct bufferevent_private *bufev_p =
- EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
+ struct bufferevent_private *bufev_p = BEV_UPCAST(bufev);
if (cbinfo->n_added &&
(bufev->enabled & EV_WRITE) &&
@@ -146,8 +149,7 @@ static void
bufferevent_readcb(evutil_socket_t fd, short event, void *arg)
{
struct bufferevent *bufev = arg;
- struct bufferevent_private *bufev_p =
- EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
+ struct bufferevent_private *bufev_p = BEV_UPCAST(bufev);
struct evbuffer *input;
int res = 0;
short what = BEV_EVENT_READING;
@@ -228,8 +230,7 @@ static void
bufferevent_writecb(evutil_socket_t fd, short event, void *arg)
{
struct bufferevent *bufev = arg;
- struct bufferevent_private *bufev_p =
- EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
+ struct bufferevent_private *bufev_p = BEV_UPCAST(bufev);
int res = 0;
short what = BEV_EVENT_WRITING;
int connected = 0;
@@ -264,7 +265,7 @@ bufferevent_writecb(evutil_socket_t fd, short event, void *arg)
goto done;
} else {
connected = 1;
- bufferevent_socket_set_conn_address_fd(bufev_p, fd);
+ bufferevent_socket_set_conn_address_fd_(bufev, fd);
#ifdef _WIN32
if (BEV_IS_ASYNC(bufev)) {
event_del(&bufev->ev_write);
@@ -379,8 +380,7 @@ int
bufferevent_socket_connect(struct bufferevent *bev,
const struct sockaddr *sa, int socklen)
{
- struct bufferevent_private *bufev_p =
- EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
+ struct bufferevent_private *bufev_p = BEV_UPCAST(bev);
evutil_socket_t fd;
int r = 0;
@@ -389,9 +389,6 @@ bufferevent_socket_connect(struct bufferevent *bev,
bufferevent_incref_and_lock_(bev);
- if (!bufev_p)
- goto done;
-
fd = bufferevent_getfd(bev);
if (fd < 0) {
if (!sa)
@@ -399,7 +396,7 @@ bufferevent_socket_connect(struct bufferevent *bev,
fd = evutil_socket_(sa->sa_family,
SOCK_STREAM|EVUTIL_SOCK_NONBLOCK, 0);
if (fd < 0)
- goto done;
+ goto freesock;
ownfd = 1;
}
if (sa) {
@@ -449,10 +446,8 @@ bufferevent_socket_connect(struct bufferevent *bev,
goto done;
freesock:
- bufferevent_run_eventcb_(bev, BEV_EVENT_ERROR, 0);
if (ownfd)
evutil_closesocket(fd);
- /* do something about the error? */
done:
bufferevent_decref_and_unlock_(bev);
return result;
@@ -463,8 +458,7 @@ bufferevent_connect_getaddrinfo_cb(int result, struct evutil_addrinfo *ai,
void *arg)
{
struct bufferevent *bev = arg;
- struct bufferevent_private *bev_p =
- EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
+ struct bufferevent_private *bev_p = BEV_UPCAST(bev);
int r;
BEV_LOCK(bev);
@@ -488,10 +482,10 @@ bufferevent_connect_getaddrinfo_cb(int result, struct evutil_addrinfo *ai,
}
/* XXX use the other addrinfos? */
- /* XXX use this return value */
- bufferevent_socket_set_conn_address(bev_p, ai->ai_addr, (int)ai->ai_addrlen);
+ bufferevent_socket_set_conn_address_(bev, ai->ai_addr, (int)ai->ai_addrlen);
r = bufferevent_socket_connect(bev, ai->ai_addr, (int)ai->ai_addrlen);
- (void)r;
+ if (r < 0)
+ bufferevent_run_eventcb_(bev, BEV_EVENT_ERROR, 0);
bufferevent_decref_and_unlock_(bev);
evutil_freeaddrinfo(ai);
}
@@ -502,8 +496,7 @@ bufferevent_socket_connect_hostname(struct bufferevent *bev,
{
char portbuf[10];
struct evutil_addrinfo hint;
- struct bufferevent_private *bev_p =
- EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
+ struct bufferevent_private *bev_p = BEV_UPCAST(bev);
if (family != AF_INET && family != AF_INET6 && family != AF_UNSPEC)
return -1;
@@ -535,8 +528,7 @@ int
bufferevent_socket_get_dns_error(struct bufferevent *bev)
{
int rv;
- struct bufferevent_private *bev_p =
- EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
+ struct bufferevent_private *bev_p = BEV_UPCAST(bev);
BEV_LOCK(bev);
rv = bev_p->dns_error;
@@ -587,8 +579,7 @@ be_socket_enable(struct bufferevent *bufev, short event)
static int
be_socket_disable(struct bufferevent *bufev, short event)
{
- struct bufferevent_private *bufev_p =
- EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
+ struct bufferevent_private *bufev_p = BEV_UPCAST(bufev);
if (event & EV_READ) {
if (event_del(&bufev->ev_read) == -1)
return -1;
@@ -604,10 +595,9 @@ be_socket_disable(struct bufferevent *bufev, short event)
static void
be_socket_destruct(struct bufferevent *bufev)
{
- struct bufferevent_private *bufev_p =
- EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
+ struct bufferevent_private *bufev_p = BEV_UPCAST(bufev);
evutil_socket_t fd;
- EVUTIL_ASSERT(bufev->be_ops == &bufferevent_ops_socket);
+ EVUTIL_ASSERT(BEV_IS_SOCKET(bufev));
fd = event_get_fd(&bufev->ev_read);
@@ -628,11 +618,10 @@ be_socket_flush(struct bufferevent *bev, short iotype,
static void
be_socket_setfd(struct bufferevent *bufev, evutil_socket_t fd)
{
- struct bufferevent_private *bufev_p =
- EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
+ struct bufferevent_private *bufev_p = BEV_UPCAST(bufev);
BEV_LOCK(bufev);
- EVUTIL_ASSERT(bufev->be_ops == &bufferevent_ops_socket);
+ EVUTIL_ASSERT(BEV_IS_SOCKET(bufev));
event_del(&bufev->ev_read);
event_del(&bufev->ev_write);
@@ -658,11 +647,10 @@ int
bufferevent_priority_set(struct bufferevent *bufev, int priority)
{
int r = -1;
- struct bufferevent_private *bufev_p =
- EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
+ struct bufferevent_private *bufev_p = BEV_UPCAST(bufev);
BEV_LOCK(bufev);
- if (bufev->be_ops != &bufferevent_ops_socket)
+ if (!BEV_IS_SOCKET(bufev))
goto done;
if (event_priority_set(&bufev->ev_read, priority) == -1)
@@ -685,7 +673,7 @@ bufferevent_base_set(struct event_base *base, struct bufferevent *bufev)
int res = -1;
BEV_LOCK(bufev);
- if (bufev->be_ops != &bufferevent_ops_socket)
+ if (!BEV_IS_SOCKET(bufev))
goto done;
bufev->ev_base = base;
diff --git a/cmake/AddEventLibrary.cmake b/cmake/AddEventLibrary.cmake
new file mode 100644
index 00000000..9de4484c
--- /dev/null
+++ b/cmake/AddEventLibrary.cmake
@@ -0,0 +1,125 @@
+include(CMakeParseArguments)
+
+set(LIBEVENT_SHARED_LIBRARIES "")
+set(LIBEVENT_STATIC_LIBRARIES "")
+
+macro(set_event_shared_lib_flags LIB_NAME)
+ set_target_properties("${LIB_NAME}_shared" PROPERTIES
+ COMPILE_FLAGS ${ARGN})
+ set_target_properties("${LIB_NAME}_shared" PROPERTIES
+ LINK_FLAGS ${ARGN})
+endmacro()
+
+macro(generate_pkgconfig LIB_NAME)
+ set(prefix ${CMAKE_INSTALL_PREFIX})
+ set(exec_prefix ${CMAKE_INSTALL_PREFIX})
+ set(libdir ${CMAKE_INSTALL_PREFIX}/lib)
+ set(includedir ${CMAKE_INSTALL_PREFIX}/include)
+
+ set(VERSION ${EVENT_ABI_LIBVERSION})
+
+ set(LIBS "")
+ foreach (LIB ${LIB_PLATFORM})
+ set(LIBS "${LIBS} -L${LIB}")
+ endforeach()
+
+ set(OPENSSL_LIBS "")
+ foreach(LIB ${OPENSSL_LIBRARIES})
+ set(OPENSSL_LIBS "${OPENSSL_LIBS} -L${LIB}")
+ endforeach()
+
+ configure_file("lib${LIB_NAME}.pc.in" "lib${LIB_NAME}.pc" @ONLY)
+ install(
+ FILES "${CMAKE_CURRENT_BINARY_DIR}/lib${LIB_NAME}.pc"
+ DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig"
+ )
+endmacro()
+
+
+# Global variables that it uses:
+# - EVENT_ABI_LIBVERSION
+# - CMAKE_THREAD_LIBS_INIT LIB_PLATFORM
+# - OPENSSL_LIBRARIES
+# - HDR_PUBLIC
+# - EVENT_INSTALL_INCLUDE_DIR
+# - EVENT_SHARED_FLAGS
+# - EVENT_LIBRARY_STATIC
+# - EVENT_LIBRARY_SHARED
+#
+# Exported variables:
+# - LIBEVENT_SHARED_LIBRARIES
+# - LIBEVENT_STATIC_LIBRARIES
+macro(add_event_library LIB_NAME)
+ cmake_parse_arguments(LIB
+ "" # Options
+ "VERSION" # One val
+ "SOURCES;LIBRARIES" # Multi val
+ ${ARGN}
+ )
+
+ set(ADD_EVENT_LIBRARY_TARGETS)
+ set(ADD_EVENT_LIBRARY_INTERFACE)
+
+ if (${EVENT_LIBRARY_STATIC})
+ add_library("${LIB_NAME}_static" STATIC ${LIB_SOURCES})
+ set_target_properties("${LIB_NAME}_static" PROPERTIES
+ OUTPUT_NAME "${LIB_NAME}"
+ CLEAN_DIRECT_OUTPUT 1)
+ set_target_properties(
+ "${LIB_NAME}_static" PROPERTIES
+ PUBLIC_HEADER "${HDR_PUBLIC}")
+
+ list(APPEND LIBEVENT_STATIC_LIBRARIES "${LIB_NAME}_static")
+ list(APPEND ADD_EVENT_LIBRARY_TARGETS "${LIB_NAME}_static")
+
+ set(ADD_EVENT_LIBRARY_INTERFACE "${LIB_NAME}_static")
+ endif()
+
+ if (${EVENT_LIBRARY_SHARED})
+ add_library("${LIB_NAME}_shared" SHARED ${LIB_SOURCES})
+
+ target_link_libraries("${LIB_NAME}_shared"
+ ${CMAKE_THREAD_LIBS_INIT}
+ ${LIB_PLATFORM}
+ ${LIB_LIBRARIES})
+
+ if (EVENT_SHARED_FLAGS)
+ set_event_shared_lib_flags("${LIB_NAME}" "${EVENT_SHARED_FLAGS}")
+ endif()
+
+ set_target_properties("${LIB_NAME}_shared" PROPERTIES
+ OUTPUT_NAME "${LIB_NAME}"
+ CLEAN_DIRECT_OUTPUT 1)
+ set_target_properties(
+ "${LIB_NAME}_shared" PROPERTIES
+ PUBLIC_HEADER "${HDR_PUBLIC}")
+ set_target_properties(
+ "${LIB_NAME}_shared" PROPERTIES
+ SOVERSION ${EVENT_ABI_LIBVERSION}
+ )
+
+ list(APPEND LIBEVENT_SHARED_LIBRARIES "${LIB_NAME}_shared")
+ list(APPEND ADD_EVENT_LIBRARY_TARGETS "${LIB_NAME}_shared")
+
+ set(ADD_EVENT_LIBRARY_INTERFACE "${LIB_NAME}_shared")
+ endif()
+
+ export(TARGETS ${ADD_EVENT_LIBRARY_TARGETS}
+ FILE "${PROJECT_BINARY_DIR}/LibeventTargets.cmake"
+ APPEND
+ )
+
+ install(TARGETS ${ADD_EVENT_LIBRARY_TARGETS}
+ EXPORT LibeventTargets
+ LIBRARY DESTINATION "lib" COMPONENT lib
+ ARCHIVE DESTINATION "lib" COMPONENT lib
+ RUNTIME DESTINATION "lib" COMPONENT lib
+ PUBLIC_HEADER DESTINATION "include/event2"
+ COMPONENT dev
+ )
+
+ add_library(${LIB_NAME} INTERFACE)
+ target_link_libraries(${LIB_NAME} INTERFACE ${ADD_EVENT_LIBRARY_INTERFACE})
+
+ generate_pkgconfig("${LIB_NAME}")
+endmacro()
diff --git a/cmake/CheckConstExists.cmake b/cmake/CheckConstExists.cmake
new file mode 100644
index 00000000..de074581
--- /dev/null
+++ b/cmake/CheckConstExists.cmake
@@ -0,0 +1,25 @@
+include(CheckCSourceCompiles)
+
+macro(check_const_exists CONST FILES VARIABLE)
+ if (NOT DEFINED ${VARIABLE})
+ set(check_const_exists_source "")
+ foreach(file ${FILES})
+ set(check_const_exists_source
+ "${check_const_exists_source}
+ #include <${file}>")
+ endforeach()
+ set(check_const_exists_source
+ "${check_const_exists_source}
+ int main() { (void)${CONST}; return 0; }")
+
+ check_c_source_compiles("${check_const_exists_source}" ${VARIABLE})
+
+ if (${${VARIABLE}})
+ set(${VARIABLE} 1 CACHE INTERNAL "Have const ${CONST}")
+ message(STATUS "Looking for ${CONST} - found")
+ else()
+ set(${VARIABLE} 0 CACHE INTERNAL "Have const ${CONST}")
+ message(STATUS "Looking for ${CONST} - not found")
+ endif()
+ endif()
+endmacro(check_const_exists)
diff --git a/cmake/CheckFunctionExistsEx.c b/cmake/CheckFunctionExistsEx.c
index 5ee3e591..224e3404 100644
--- a/cmake/CheckFunctionExistsEx.c
+++ b/cmake/CheckFunctionExistsEx.c
@@ -1,30 +1,28 @@
#ifdef CHECK_FUNCTION_EXISTS
-#ifndef _WIN32
-char CHECK_FUNCTION_EXISTS();
+#ifdef __cplusplus
+extern "C"
#endif
-
+ char
+ CHECK_FUNCTION_EXISTS(void);
#ifdef __CLASSIC_C__
-int main(){
+int main()
+{
int ac;
- char*av[];
+ char* av[];
#else
-int main(int ac, char*av[]){
+int main(int ac, char* av[])
+{
#endif
-#ifdef _WIN32
- void * p = &CHECK_FUNCTION_EXISTS;
-#else
CHECK_FUNCTION_EXISTS();
-#endif
- if(ac > 1000)
- {
+ if (ac > 1000) {
return *av[0];
- }
+ }
return 0;
}
-#else /* CHECK_FUNCTION_EXISTS */
+#else /* CHECK_FUNCTION_EXISTS */
-# error "CHECK_FUNCTION_EXISTS has to specify the function"
+#error "CHECK_FUNCTION_EXISTS has to specify the function"
#endif /* CHECK_FUNCTION_EXISTS */
diff --git a/cmake/CheckWaitpidSupportWNOWAIT.cmake b/cmake/CheckWaitpidSupportWNOWAIT.cmake
deleted file mode 100644
index 1a73db37..00000000
--- a/cmake/CheckWaitpidSupportWNOWAIT.cmake
+++ /dev/null
@@ -1,18 +0,0 @@
-include(CheckCSourceRuns)
-
-check_c_source_runs(
-"
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <stdlib.h>
-
-int
-main(int argc, char** argv)
-{
- pid_t pid;
- int status;
- if ((pid = fork()) == 0) _exit(0);
- _exit(waitpid(pid, &status, WNOWAIT) == -1);
-}"
-EVENT__HAVE_WAITPID_WITH_WNOWAIT)
diff --git a/cmake/CheckWorkingKqueue.cmake b/cmake/CheckWorkingKqueue.cmake
index 47bf4e83..f22f011b 100644
--- a/cmake/CheckWorkingKqueue.cmake
+++ b/cmake/CheckWorkingKqueue.cmake
@@ -17,7 +17,7 @@ main(int argc, char **argv)
int fd[2];
struct kevent ev;
struct timespec ts;
- char buf[8000];
+ char buf[80000];
if (pipe(fd) == -1)
exit(1);
@@ -27,7 +27,7 @@ main(int argc, char **argv)
while ((n = write(fd[1], buf, sizeof(buf))) == sizeof(buf))
;
- if ((kq = kqueue()) == -1)
+ if ((kq = kqueue()) == -1)
exit(1);
memset(&ev, 0, sizeof(ev));
@@ -49,4 +49,4 @@ main(int argc, char **argv)
exit(0);
}
-" EVENT__HAVE_WORKING_KQUEUE) \ No newline at end of file
+" EVENT__HAVE_WORKING_KQUEUE)
diff --git a/cmake/LibeventConfig.cmake.in b/cmake/LibeventConfig.cmake.in
index b28cacb5..54223360 100644
--- a/cmake/LibeventConfig.cmake.in
+++ b/cmake/LibeventConfig.cmake.in
@@ -1,7 +1,8 @@
# - Config file for the Libevent package
# It defines the following variables
-# LIBEVENT_INCLUDE_DIRS - include directories for FooBar
-# LIBEVENT_LIBRARIES - libraries to link against
+# LIBEVENT_INCLUDE_DIRS - include directories
+# LIBEVENT_STATIC_LIBRARIES - libraries to link against (archive/static)
+# LIBEVENT_SHARED_LIBRARIES - libraries to link against (shared)
# Get the path of the current file.
get_filename_component(LIBEVENT_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
@@ -13,5 +14,5 @@ set(LIBEVENT_INCLUDE_DIRS "@EVENT_INSTALL_INCLUDE_DIR@")
include(${LIBEVENT_CMAKE_DIR}/LibeventTargets.cmake)
# IMPORTED targets from LibeventTargets.cmake
-set(LIBEVENT_LIBRARIES event event_core event_extra)
-
+set(LIBEVENT_STATIC_LIBRARIES "@LIBEVENT_STATIC_LIBRARIES@")
+set(LIBEVENT_SHARED_LIBRARIES "@LIBEVENT_SHARED_LIBRARIES@")
diff --git a/cmake/VersionViaGit.cmake b/cmake/VersionViaGit.cmake
index a9882d8a..008d0188 100644
--- a/cmake/VersionViaGit.cmake
+++ b/cmake/VersionViaGit.cmake
@@ -4,7 +4,6 @@
#
# Usful for auto-versionin in ou CMakeLists
#
-# EVENT_GIT___VERSION_FOUND - Version variables foud
# EVENT_GIT___VERSION_MAJOR - Major version.
# EVENT_GIT___VERSION_MINOR - Minor version
# EVENT_GIT___VERSION_STAGE - Stage version
@@ -12,7 +11,6 @@
# Example usage:
#
# event_fuzzy_version_from_git()
-# if (EVENT_GIT___VERSION_FOUND)
# message("Libvent major=${EVENT_GIT___VERSION_MAJOR}")
# message(" minor=${EVENT_GIT___VERSION_MINOR}")
# message(" patch=${EVENT_GIT___VERSION_PATCH}")
@@ -22,12 +20,10 @@
include(FindGit)
macro(event_fuzzy_version_from_git)
- set(EVENT_GIT___VERSION_FOUND FALSE)
-
# set our defaults.
set(EVENT_GIT___VERSION_MAJOR 2)
set(EVENT_GIT___VERSION_MINOR 1)
- set(EVENT_GIT___VERSION_PATCH 8)
+ set(EVENT_GIT___VERSION_PATCH 9)
set(EVENT_GIT___VERSION_STAGE "beta")
find_package(Git)
@@ -41,13 +37,28 @@ macro(event_fuzzy_version_from_git)
RESULT_VARIABLE
GITRET
OUTPUT_VARIABLE
- GITVERSION)
+ GITVERSION
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+
+ string(REGEX REPLACE "[\\._-]" ";" VERSION_LIST "${GITVERSION}")
+ list(LENGTH VERSION_LIST VERSION_LIST_LENGTH)
+
+ if ((GITRET EQUAL 0) AND (VERSION_LIST_LENGTH EQUAL 5))
+ list(GET VERSION_LIST 1 _MAJOR)
+ list(GET VERSION_LIST 2 _MINOR)
+ list(GET VERSION_LIST 3 _PATCH)
+ list(GET VERSION_LIST 4 _STAGE)
+
+ set(_DEFAULT_VERSION "${EVENT_GIT___VERSION_MAJOR}.${EVENT_GIT___VERSION_MINOR}.${EVENT_GIT___VERSION_PATCH}-${EVENT_GIT___VERSION_STAGE}")
+ set(_GIT_VERSION "${_MAJOR}.${_MINOR}.${_PATCH}-${_STAGE}")
- if (GITRET EQUAL 0)
- string(REGEX REPLACE "^release-([0-9]+)\\.([0-9]+)\\.([0-9]+)-(.*)" "\\1" EVENT_GIT___VERSION_MAJOR ${GITVERSION})
- string(REGEX REPLACE "^release-([0-9]+)\\.([0-9]+)\\.([0-9]+)-(.*)" "\\2" EVENT_GIT___VERSION_MINOR ${GITVERSION})
- string(REGEX REPLACE "^release-([0-9]+)\\.([0-9]+)\\.([0-9]+)-(.*)" "\\3" EVENT_GIT___VERSION_PATCH ${GITVERSION})
- string(REGEX REPLACE "^release-([0-9]+)\\.([0-9]+)\\.([0-9]+)-([aA-zZ]+)" "\\4" EVENT_GIT___VERSION_STAGE ${GITVERSION})
+ if (${_DEFAULT_VERSION} VERSION_LESS ${_GIT_VERSION})
+ set(EVENT_GIT___VERSION_MAJOR ${_MAJOR})
+ set(EVENT_GIT___VERSION_MINOR ${_MINOR})
+ set(EVENT_GIT___VERSION_PATCH ${_PATCH})
+ set(EVENT_GIT___VERSION_STAGE ${_STAGE})
endif()
endif()
+ endif()
endmacro()
diff --git a/configure.ac b/configure.ac
index 7528d37e..0f5495d6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5,7 +5,7 @@ dnl See LICENSE for copying information.
dnl
dnl Original version Dug Song <dugsong@monkey.org>
-AC_INIT(libevent,2.1.8-stable)
+AC_INIT(libevent,2.1.9-beta)
AC_PREREQ(2.59)
AC_CONFIG_SRCDIR(event.c)
@@ -14,7 +14,7 @@ AM_INIT_AUTOMAKE
dnl AM_SILENT_RULES req. automake 1.11. [no] defaults V=1
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
AC_CONFIG_HEADERS(config.h evconfig-private.h:evconfig-private.h.in)
-AC_DEFINE(NUMERIC_VERSION, 0x02010800, [Numeric representation of the version])
+AC_DEFINE(NUMERIC_VERSION, 0x02010900, [Numeric representation of the version])
dnl Initialize prefix.
if test "$prefix" = "NONE"; then
@@ -160,6 +160,19 @@ die horribly
bwin32=false; AC_MSG_RESULT(no),
)
+dnl - check if the macro __midipix__ is defined on this compiler.
+dnl - (this is how we check for a midipix version of GCC)
+AC_MSG_CHECKING(for MIDIPIX)
+AC_TRY_COMPILE(,
+ [
+#ifndef __midipix__
+die horribly
+#endif
+ ],
+ midipix=true; AC_MSG_RESULT(yes),
+ midipix=false; AC_MSG_RESULT(no),
+)
+
dnl - check if the macro __CYGWIN__ is defined on this compiler.
dnl - (this is how we check for a cygwin version of GCC)
AC_MSG_CHECKING(for CYGWIN)
@@ -326,7 +339,8 @@ fi
AM_CONDITIONAL(BUILD_WIN32, test x$bwin32 = xtrue)
AM_CONDITIONAL(BUILD_CYGWIN, test x$cygwin = xtrue)
-AM_CONDITIONAL(BUILD_WITH_NO_UNDEFINED, test x$bwin32 = xtrue || test x$cygwin = xtrue)
+AM_CONDITIONAL(BUILD_MIDIPIX, test x$midipix = xtrue)
+AM_CONDITIONAL(BUILD_WITH_NO_UNDEFINED, test x$bwin32 = xtrue || test x$cygwin = xtrue || test x$midipix = xtrue)
if test x$bwin32 = xtrue; then
AC_SEARCH_LIBS([getservbyname],[ws2_32])
@@ -342,6 +356,7 @@ AC_CHECK_FUNCS([ \
accept4 \
arc4random \
arc4random_buf \
+ arc4random_addrandom \
eventfd \
epoll_create1 \
fcntl \
@@ -502,6 +517,12 @@ if test "x$ac_cv_header_sys_event_h" = "xyes"; then
if test "x$havekqueue" = "xyes" ; then
AC_MSG_CHECKING(for working kqueue)
AC_TRY_RUN(
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
#include <sys/types.h>
#include <sys/time.h>
#include <sys/event.h>
@@ -517,7 +538,7 @@ main(int argc, char **argv)
int fd[[2]];
struct kevent ev;
struct timespec ts;
- char buf[[8000]];
+ char buf[[80000]];
if (pipe(fd) == -1)
exit(1);
@@ -599,26 +620,6 @@ main(int argc, char **argv)
fi
AM_CONDITIONAL(EPOLL_BACKEND, [test "x$haveepoll" = "xyes"])
-AC_MSG_CHECKING(waitpid support WNOWAIT)
-AC_TRY_RUN(
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <stdlib.h>
-
-int
-main(int argc, char** argv)
-{
- pid_t pid;
- int status;
- if ((pid = fork()) == 0) _exit(0);
- _exit(waitpid(pid, &status, WNOWAIT) == -1);
-}, [AC_MSG_RESULT(yes)
-AC_DEFINE(HAVE_WAITPID_WITH_WNOWAIT, 1,
-[Define if waitpid() supports WNOWAIT])
-], AC_MSG_RESULT(no), AC_MSG_RESULT(no))
-
-
haveeventports=no
AC_CHECK_FUNCS(port_create, [haveeventports=yes], )
if test "x$haveeventports" = "xyes" ; then
@@ -663,6 +664,7 @@ AC_CHECK_SIZEOF(short)
AC_CHECK_SIZEOF(size_t)
AC_CHECK_SIZEOF(void *)
AC_CHECK_SIZEOF(off_t)
+AC_CHECK_SIZEOF(time_t)
AC_CHECK_TYPES([struct in6_addr, struct sockaddr_in6, sa_family_t, struct addrinfo, struct sockaddr_storage], , ,
[#define _GNU_SOURCE
@@ -715,8 +717,7 @@ AC_CHECK_MEMBERS([struct in6_addr.s6_addr32, struct in6_addr.s6_addr16, struct s
#endif
])
-AC_CHECK_TYPES([struct so_linger],
-[#define HAVE_SO_LINGER], ,
+AC_CHECK_TYPES([struct linger],,,
[
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
@@ -726,7 +727,11 @@ AC_CHECK_TYPES([struct so_linger],
AC_MSG_CHECKING([for socklen_t])
AC_TRY_COMPILE([
#include <sys/types.h>
- #include <sys/socket.h>],
+ #ifdef _WIN32
+ #include <ws2tcpip.h>
+ #else
+ #include <sys/socket.h>
+ #endif],
[socklen_t x;],
AC_MSG_RESULT([yes]),
[AC_MSG_RESULT([no])
@@ -734,21 +739,23 @@ AC_TRY_COMPILE([
[Define to unsigned int if you dont have it])]
)
+# __func__/__FUNCTION__ is not a macros in general
AC_MSG_CHECKING([whether our compiler supports __func__])
AC_TRY_COMPILE([],
- [ const char *cp = __func__; ],
- AC_MSG_RESULT([yes]),
- AC_MSG_RESULT([no])
- AC_MSG_CHECKING([whether our compiler supports __FUNCTION__])
- AC_TRY_COMPILE([],
- [ const char *cp = __FUNCTION__; ],
- AC_MSG_RESULT([yes])
- AC_DEFINE(__func__, __FUNCTION__,
- [Define to appropriate substitue if compiler doesnt have __func__]),
- AC_MSG_RESULT([no])
- AC_DEFINE(__func__, __FILE__,
- [Define to appropriate substitue if compiler doesnt have __func__])))
-
+ [ const char *cp = __func__; ],
+ [ AC_DEFINE(HAVE___func__, 1, [Define to 1 if compiler have __func__])
+ AC_MSG_RESULT([yes])
+ ],
+ AC_MSG_RESULT([no])
+)
+AC_MSG_CHECKING([whether our compiler supports __FUNCTION__])
+AC_TRY_COMPILE([],
+ [ const char *cp = __FUNCTION__; ],
+ [ AC_DEFINE(HAVE___FUNCTION__, 1, [Define to 1 if compiler have __FUNCTION__])
+ AC_MSG_RESULT([yes])
+ ],
+ AC_MSG_RESULT([no])
+)
# check if we can compile with pthreads
have_pthreads=no
@@ -791,10 +798,6 @@ fi
# check if we have and should use openssl
AM_CONDITIONAL(OPENSSL, [test "$enable_openssl" != "no" && test "$have_openssl" = "yes"])
-if test "x$enable_openssl" = "xyes"; then
- AC_SEARCH_LIBS([ERR_remove_thread_state], [crypto eay32],
- [AC_DEFINE(HAVE_ERR_REMOVE_THREAD_STATE, 1, [Define to 1 if you have ERR_remove_thread_stat().])])
-fi
# Add some more warnings which we use in development but not in the
# released versions. (Some relevant gcc versions can't handle these.)
@@ -820,7 +823,8 @@ if test x$enable_gcc_warnings != xno && test "$GCC" = "yes"; then
#error
#endif])], have_clang=yes, have_clang=no)
- CFLAGS="$CFLAGS -W -Wfloat-equal -Wundef -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings -Wredundant-decls -Wchar-subscripts -Wcomment -Wformat -Wwrite-strings -Wmissing-declarations -Wredundant-decls -Wnested-externs -Wbad-function-cast -Wswitch"
+ # -W is the same as -Wextra
+ CFLAGS="$CFLAGS -W -Wfloat-equal -Wundef -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings -Wredundant-decls -Wmissing-declarations -Wredundant-decls -Wnested-externs -Wbad-function-cast"
if test x$enable_gcc_warnings = xyes; then
CFLAGS="$CFLAGS -Werror"
fi
diff --git a/defer-internal.h b/defer-internal.h
index e3c7d7da..d6f80a11 100644
--- a/defer-internal.h
+++ b/defer-internal.h
@@ -46,6 +46,7 @@ typedef void (*deferred_cb_fn)(struct event_callback *, void *);
@param cb The function to run when the struct event_callback executes.
@param arg The function's second argument.
*/
+EVENT2_EXPORT_SYMBOL
void event_deferred_cb_init_(struct event_callback *, ev_uint8_t, deferred_cb_fn, void *);
/**
Change the priority of a non-pending event_callback.
@@ -54,12 +55,14 @@ void event_deferred_cb_set_priority_(struct event_callback *, ev_uint8_t);
/**
Cancel a struct event_callback if it is currently scheduled in an event_base.
*/
+EVENT2_EXPORT_SYMBOL
void event_deferred_cb_cancel_(struct event_base *, struct event_callback *);
/**
Activate a struct event_callback if it is not currently scheduled in an event_base.
Return true if it was not previously scheduled.
*/
+EVENT2_EXPORT_SYMBOL
int event_deferred_cb_schedule_(struct event_base *, struct event_callback *);
#ifdef __cplusplus
diff --git a/epoll.c b/epoll.c
index bf730b23..a0df0d21 100644
--- a/epoll.c
+++ b/epoll.c
@@ -401,11 +401,14 @@ epoll_nochangelist_del(struct event_base *base, evutil_socket_t fd,
ch.old_events = old;
ch.read_change = ch.write_change = ch.close_change = 0;
if (events & EV_WRITE)
- ch.write_change = EV_CHANGE_DEL;
+ ch.write_change = EV_CHANGE_DEL |
+ (events & EV_ET);
if (events & EV_READ)
- ch.read_change = EV_CHANGE_DEL;
+ ch.read_change = EV_CHANGE_DEL |
+ (events & EV_ET);
if (events & EV_CLOSED)
- ch.close_change = EV_CHANGE_DEL;
+ ch.close_change = EV_CHANGE_DEL |
+ (events & EV_ET);
return epoll_apply_one_change(base, base->evbase, &ch);
}
diff --git a/epolltable-internal.h b/epolltable-internal.h
index da30e097..73c2e364 100644
--- a/epolltable-internal.h
+++ b/epolltable-internal.h
@@ -34,7 +34,7 @@
Note also that this table is a little sparse, since ADD+DEL is
nonsensical ("xxx" in the list below.)
- Note also also that we are shifting old_events by only 5 bits, since
+ Note also that we are shifting old_events by only 5 bits, since
EV_READ is 2 and EV_WRITE is 4.
The table was auto-generated with a python script, according to this
diff --git a/evbuffer-internal.h b/evbuffer-internal.h
index cf4bddc8..d09b4f1d 100644
--- a/evbuffer-internal.h
+++ b/evbuffer-internal.h
@@ -92,7 +92,7 @@ struct evbuffer {
* If the buffer has no chains, it is NULL.
*
* The last_with_datap pointer points at _whatever 'next' pointer_
- * points at the last_with_datap chain. If the last_with_data chain
+ * pointing at the last_with_data chain. If the last_with_data chain
* is the first chain, or it is NULL, then the last_with_datap pointer
* is &buf->first.
*/
diff --git a/evconfig-private.h.cmake b/evconfig-private.h.cmake
index 32f04794..1adf9c03 100644
--- a/evconfig-private.h.cmake
+++ b/evconfig-private.h.cmake
@@ -32,4 +32,9 @@
/* Define to 1 if you need to in order for `stat' and other things to work. */
#cmakedefine _POSIX_SOURCE 1
+/* Enable POSIX.2 extensions on QNX for getopt */
+#ifdef __QNX__
+#cmakedefine __EXT_POSIX2 1
+#endif
+
#endif
diff --git a/evconfig-private.h.in b/evconfig-private.h.in
index 7b3dfdb1..8cd64787 100644
--- a/evconfig-private.h.in
+++ b/evconfig-private.h.in
@@ -45,4 +45,11 @@
#undef _POSIX_SOURCE
#endif
+/* Enable POSIX.2 extensions on QNX for getopt */
+#ifdef __QNX__
+# ifndef __EXT_POSIX2
+# define __EXT_POSIX2
+# endif
+#endif
+
#endif
diff --git a/evdns.c b/evdns.c
index e9dbc35c..58209626 100644
--- a/evdns.c
+++ b/evdns.c
@@ -2265,10 +2265,11 @@ evdns_request_transmit(struct request *req) {
nameserver_write_waiting(req->ns, 1);
return 1;
case 2:
- /* failed to transmit the request entirely. */
+ /* failed to transmit the request entirely. we can fallthrough since
+ * we'll set a timeout, which will time out, and make us retransmit the
+ * request anyway. */
retcode = 1;
- /* fall through: we'll set a timeout, which will time out,
- * and make us retransmit the request anyway. */
+ EVUTIL_FALLTHROUGH;
default:
/* all ok */
log(EVDNS_LOG_DEBUG,
@@ -3622,6 +3623,11 @@ evdns_base_resolv_conf_parse_impl(struct evdns_base *base, int flags, const char
mm_free(fname);
}
+ if (!filename) {
+ evdns_resolv_set_defaults(base, flags);
+ return 1;
+ }
+
if ((err = evutil_read_file_(filename, &resolv, &n, 0)) < 0) {
if (err == -1) {
/* No file. */
@@ -4636,6 +4642,7 @@ evdns_getaddrinfo(struct evdns_base *dns_base,
int err;
int port = 0;
int want_cname = 0;
+ int started = 0;
if (!dns_base) {
dns_base = current_base;
@@ -4714,6 +4721,8 @@ evdns_getaddrinfo(struct evdns_base *dns_base,
* launching those requests. (XXX we don't do that yet.)
*/
+ EVDNS_LOCK(dns_base);
+
if (hints.ai_family != PF_INET6) {
log(EVDNS_LOG_DEBUG, "Sending request for %s on ipv4 as %p",
nodename, &data->ipv4_request);
@@ -4740,7 +4749,11 @@ evdns_getaddrinfo(struct evdns_base *dns_base,
evtimer_assign(&data->timeout, dns_base->event_base,
evdns_getaddrinfo_timeout_cb, data);
- if (data->ipv4_request.r || data->ipv6_request.r) {
+ started = (data->ipv4_request.r || data->ipv6_request.r);
+
+ EVDNS_UNLOCK(dns_base);
+
+ if (started) {
return data;
} else {
mm_free(data);
diff --git a/event-config.h.cmake b/event-config.h.cmake
index c1355be9..ee0df54b 100644
--- a/event-config.h.cmake
+++ b/event-config.h.cmake
@@ -36,394 +36,397 @@
#define EVENT__PACKAGE_TARNAME ""
/* Define if libevent should build without support for a debug mode */
-#cmakedefine EVENT__DISABLE_DEBUG_MODE
+#cmakedefine EVENT__DISABLE_DEBUG_MODE 1
/* Define if libevent should not allow replacing the mm functions */
-#cmakedefine EVENT__DISABLE_MM_REPLACEMENT
+#cmakedefine EVENT__DISABLE_MM_REPLACEMENT 1
/* Define if libevent should not be compiled with thread support */
-#cmakedefine EVENT__DISABLE_THREAD_SUPPORT
+#cmakedefine EVENT__DISABLE_THREAD_SUPPORT 1
/* Define to 1 if you have the `accept4' function. */
-#cmakedefine EVENT__HAVE_ACCEPT4
+#cmakedefine EVENT__HAVE_ACCEPT4 1
/* Define to 1 if you have the `arc4random' function. */
-#cmakedefine EVENT__HAVE_ARC4RANDOM
+#cmakedefine EVENT__HAVE_ARC4RANDOM 1
/* Define to 1 if you have the `arc4random_buf' function. */
-#cmakedefine EVENT__HAVE_ARC4RANDOM_BUF
+#cmakedefine EVENT__HAVE_ARC4RANDOM_BUF 1
+
+/* Define to 1 if you have the `arc4random_addrandom' function. */
+#cmakedefine EVENT__HAVE_ARC4RANDOM_ADDRANDOM 1
/* Define if clock_gettime is available in libc */
-#cmakedefine EVENT__DNS_USE_CPU_CLOCK_FOR_ID
+#cmakedefine EVENT__DNS_USE_CPU_CLOCK_FOR_ID 1
/* Define is no secure id variant is available */
-#cmakedefine EVENT__DNS_USE_GETTIMEOFDAY_FOR_ID
-#cmakedefine EVENT__DNS_USE_FTIME_FOR_ID
+#cmakedefine EVENT__DNS_USE_GETTIMEOFDAY_FOR_ID 1
+#cmakedefine EVENT__DNS_USE_FTIME_FOR_ID 1
/* Define to 1 if you have the <arpa/inet.h> header file. */
-#cmakedefine EVENT__HAVE_ARPA_INET_H
+#cmakedefine EVENT__HAVE_ARPA_INET_H 1
/* Define to 1 if you have the `clock_gettime' function. */
-#cmakedefine EVENT__HAVE_CLOCK_GETTIME
+#cmakedefine EVENT__HAVE_CLOCK_GETTIME 1
/* Define to 1 if you have the declaration of `CTL_KERN'. */
-#cmakedefine EVENT__HAVE_DECL_CTL_KERN
+#define EVENT__HAVE_DECL_CTL_KERN @EVENT__HAVE_DECL_CTL_KERN@
/* Define to 1 if you have the declaration of `KERN_ARND'. */
-#cmakedefine EVENT__HAVE_DECL_KERN_ARND
+#define EVENT__HAVE_DECL_KERN_ARND @EVENT__HAVE_DECL_KERN_ARND@
/* Define to 1 if you have the declaration of `KERN_RANDOM'. */
-#cmakedefine EVENT__HAVE_DECL_KERN_RANDOM
+#define EVENT__HAVE_DECL_KERN_RANDOM @EVENT__HAVE_DECL_KERN_RANDOM@
+
+/* Define to 1 if you have the declaration of `RANDOM_UUID'. */
+#define EVENT__HAVE_DECL_RANDOM_UUID @EVENT__HAVE_DECL_RANDOM_UUID@
/* Define if /dev/poll is available */
-#cmakedefine EVENT__HAVE_DEVPOLL
+#cmakedefine EVENT__HAVE_DEVPOLL 1
/* Define to 1 if you have the <netdb.h> header file. */
-#cmakedefine EVENT__HAVE_NETDB_H
+#cmakedefine EVENT__HAVE_NETDB_H 1
/* Define to 1 if fd_mask type is defined */
-#cmakedefine EVENT__HAVE_FD_MASK
+#cmakedefine EVENT__HAVE_FD_MASK 1
/* Define to 1 if the <sys/queue.h> header file defines TAILQ_FOREACH. */
-#cmakedefine EVENT__HAVE_TAILQFOREACH
+#cmakedefine EVENT__HAVE_TAILQFOREACH 1
/* Define to 1 if you have the <dlfcn.h> header file. */
-#cmakedefine EVENT__HAVE_DLFCN_H
+#cmakedefine EVENT__HAVE_DLFCN_H 1
/* Define if your system supports the epoll system calls */
-#cmakedefine EVENT__HAVE_EPOLL
+#cmakedefine EVENT__HAVE_EPOLL 1
/* Define to 1 if you have the `epoll_create1' function. */
-#cmakedefine EVENT__HAVE_EPOLL_CREATE1
+#cmakedefine EVENT__HAVE_EPOLL_CREATE1 1
/* Define to 1 if you have the `epoll_ctl' function. */
-#cmakedefine EVENT__HAVE_EPOLL_CTL
+#cmakedefine EVENT__HAVE_EPOLL_CTL 1
/* Define to 1 if you have the `eventfd' function. */
-#cmakedefine EVENT__HAVE_EVENTFD
+#cmakedefine EVENT__HAVE_EVENTFD 1
/* Define if your system supports event ports */
-#cmakedefine EVENT__HAVE_EVENT_PORTS
+#cmakedefine EVENT__HAVE_EVENT_PORTS 1
/* Define to 1 if you have the `fcntl' function. */
-#cmakedefine EVENT__HAVE_FCNTL
+#cmakedefine EVENT__HAVE_FCNTL 1
/* Define to 1 if you have the <fcntl.h> header file. */
-#cmakedefine EVENT__HAVE_FCNTL_H
+#cmakedefine EVENT__HAVE_FCNTL_H 1
/* Define to 1 if you have the `getaddrinfo' function. */
-#cmakedefine EVENT__HAVE_GETADDRINFO
+#cmakedefine EVENT__HAVE_GETADDRINFO 1
/* Define to 1 if you have the `getegid' function. */
-#cmakedefine EVENT__HAVE_GETEGID
+#cmakedefine EVENT__HAVE_GETEGID 1
/* Define to 1 if you have the `geteuid' function. */
-#cmakedefine EVENT__HAVE_GETEUID
+#cmakedefine EVENT__HAVE_GETEUID 1
/* TODO: Check for different gethostname argument counts. CheckPrototypeDefinition.cmake can be used. */
/* Define this if you have any gethostbyname_r() */
-#cmakedefine EVENT__HAVE_GETHOSTBYNAME_R
+#cmakedefine EVENT__HAVE_GETHOSTBYNAME_R 1
/* Define this if gethostbyname_r takes 3 arguments */
-#cmakedefine EVENT__HAVE_GETHOSTBYNAME_R_3_ARG
+#cmakedefine EVENT__HAVE_GETHOSTBYNAME_R_3_ARG 1
/* Define this if gethostbyname_r takes 5 arguments */
-#cmakedefine EVENT__HAVE_GETHOSTBYNAME_R_5_ARG
+#cmakedefine EVENT__HAVE_GETHOSTBYNAME_R_5_ARG 1
/* Define this if gethostbyname_r takes 6 arguments */
-#cmakedefine EVENT__HAVE_GETHOSTBYNAME_R_6_ARG
+#cmakedefine EVENT__HAVE_GETHOSTBYNAME_R_6_ARG 1
/* Define to 1 if you have the `getifaddrs' function. */
-#cmakedefine EVENT__HAVE_GETIFADDRS
+#cmakedefine EVENT__HAVE_GETIFADDRS 1
/* Define to 1 if you have the `getnameinfo' function. */
-#cmakedefine EVENT__HAVE_GETNAMEINFO
+#cmakedefine EVENT__HAVE_GETNAMEINFO 1
/* Define to 1 if you have the `getprotobynumber' function. */
-#cmakedefine EVENT__HAVE_GETPROTOBYNUMBER
+#cmakedefine EVENT__HAVE_GETPROTOBYNUMBER 1
/* Define to 1 if you have the `getservbyname' function. */
-#cmakedefine EVENT__HAVE_GETSERVBYNAME
+#cmakedefine EVENT__HAVE_GETSERVBYNAME 1
/* Define to 1 if you have the `gettimeofday' function. */
-#cmakedefine EVENT__HAVE_GETTIMEOFDAY
+#cmakedefine EVENT__HAVE_GETTIMEOFDAY 1
/* Define to 1 if you have the <ifaddrs.h> header file. */
-#cmakedefine EVENT__HAVE_IFADDRS_H
+#cmakedefine EVENT__HAVE_IFADDRS_H 1
/* Define to 1 if you have the `inet_ntop' function. */
-#cmakedefine EVENT__HAVE_INET_NTOP
+#cmakedefine EVENT__HAVE_INET_NTOP 1
/* Define to 1 if you have the `inet_pton' function. */
-#cmakedefine EVENT__HAVE_INET_PTON
+#cmakedefine EVENT__HAVE_INET_PTON 1
/* Define to 1 if you have the <inttypes.h> header file. */
-#cmakedefine EVENT__HAVE_INTTYPES_H
+#cmakedefine EVENT__HAVE_INTTYPES_H 1
/* Define to 1 if you have the `issetugid' function. */
-#cmakedefine EVENT__HAVE_ISSETUGID
+#cmakedefine EVENT__HAVE_ISSETUGID 1
/* Define to 1 if you have the `kqueue' function. */
-#cmakedefine EVENT__HAVE_KQUEUE
+#cmakedefine EVENT__HAVE_KQUEUE 1
/* Define if the system has zlib */
-#cmakedefine EVENT__HAVE_LIBZ
+#cmakedefine EVENT__HAVE_LIBZ 1
/* Define to 1 if you have the `mach_absolute_time' function. */
-#cmakedefine EVENT__HAVE_MACH_ABSOLUTE_TIME
+#cmakedefine EVENT__HAVE_MACH_ABSOLUTE_TIME 1
/* Define to 1 if you have the <mach/mach_time.h> header file. */
-#cmakedefine EVENT__HAVE_MACH_MACH_TIME_H
+#cmakedefine EVENT__HAVE_MACH_MACH_TIME_H 1
/* Define to 1 if you have the <memory.h> header file. */
-#cmakedefine EVENT__HAVE_MEMORY_H
+#cmakedefine EVENT__HAVE_MEMORY_H 1
/* Define to 1 if you have the `mmap' function. */
-#cmakedefine EVENT__HAVE_MMAP
+#cmakedefine EVENT__HAVE_MMAP 1
/* Define to 1 if you have the `nanosleep' function. */
-#cmakedefine EVENT__HAVE_NANOSLEEP
+#cmakedefine EVENT__HAVE_NANOSLEEP 1
/* Define to 1 if you have the `usleep' function. */
-#cmakedefine EVENT__HAVE_USLEEP
+#cmakedefine EVENT__HAVE_USLEEP 1
/* Define to 1 if you have the <netinet/in6.h> header file. */
-#cmakedefine EVENT__HAVE_NETINET_IN6_H
+#cmakedefine EVENT__HAVE_NETINET_IN6_H 1
/* Define to 1 if you have the <netinet/in.h> header file. */
-#cmakedefine EVENT__HAVE_NETINET_IN_H
+#cmakedefine EVENT__HAVE_NETINET_IN_H 1
/* Define to 1 if you have the <netinet/tcp.h> header file. */
-#cmakedefine EVENT__HAVE_NETINET_TCP_H
+#cmakedefine EVENT__HAVE_NETINET_TCP_H 1
/* Define if the system has openssl */
-#cmakedefine EVENT__HAVE_OPENSSL
+#cmakedefine EVENT__HAVE_OPENSSL 1
/* Define to 1 if you have the `pipe' function. */
-#cmakedefine EVENT__HAVE_PIPE
+#cmakedefine EVENT__HAVE_PIPE 1
/* Define to 1 if you have the `pipe2' function. */
-#cmakedefine EVENT__HAVE_PIPE2
+#cmakedefine EVENT__HAVE_PIPE2 1
/* Define to 1 if you have the `poll' function. */
-#cmakedefine EVENT__HAVE_POLL
+#cmakedefine EVENT__HAVE_POLL 1
/* Define to 1 if you have the <poll.h> header file. */
-#cmakedefine EVENT__HAVE_POLL_H
+#cmakedefine EVENT__HAVE_POLL_H 1
/* Define to 1 if you have the `port_create' function. */
-#cmakedefine EVENT__HAVE_PORT_CREATE
+#cmakedefine EVENT__HAVE_PORT_CREATE 1
/* Define to 1 if you have the <port.h> header file. */
-#cmakedefine EVENT__HAVE_PORT_H
+#cmakedefine EVENT__HAVE_PORT_H 1
/* Define if we have pthreads on this system */
-#cmakedefine EVENT__HAVE_PTHREADS
+#cmakedefine EVENT__HAVE_PTHREADS 1
/* Define to 1 if you have the `putenv' function. */
-#cmakedefine EVENT__HAVE_PUTENV
+#cmakedefine EVENT__HAVE_PUTENV 1
/* Define to 1 if the system has the type `sa_family_t'. */
-#cmakedefine EVENT__HAVE_SA_FAMILY_T
+#cmakedefine EVENT__HAVE_SA_FAMILY_T 1
/* Define to 1 if you have the `select' function. */
-#cmakedefine EVENT__HAVE_SELECT
+#cmakedefine EVENT__HAVE_SELECT 1
/* Define to 1 if you have the `setenv' function. */
-#cmakedefine EVENT__HAVE_SETENV
+#cmakedefine EVENT__HAVE_SETENV 1
/* Define if F_SETFD is defined in <fcntl.h> */
-#cmakedefine EVENT__HAVE_SETFD
+#cmakedefine EVENT__HAVE_SETFD 1
/* Define to 1 if you have the `setrlimit' function. */
-#cmakedefine EVENT__HAVE_SETRLIMIT
+#cmakedefine EVENT__HAVE_SETRLIMIT 1
/* Define to 1 if you have the `sendfile' function. */
-#cmakedefine EVENT__HAVE_SENDFILE
-
-/* Define if F_SETFD is defined in <fcntl.h> */
-#cmakedefine EVENT__HAVE_SETFD
+#cmakedefine EVENT__HAVE_SENDFILE 1
/* Define to 1 if you have the `sigaction' function. */
-#cmakedefine EVENT__HAVE_SIGACTION
+#cmakedefine EVENT__HAVE_SIGACTION 1
/* Define to 1 if you have the `signal' function. */
-#cmakedefine EVENT__HAVE_SIGNAL
+#cmakedefine EVENT__HAVE_SIGNAL 1
/* Define to 1 if you have the `splice' function. */
-#cmakedefine EVENT__HAVE_SPLICE
+#cmakedefine EVENT__HAVE_SPLICE 1
/* Define to 1 if you have the <stdarg.h> header file. */
-#cmakedefine EVENT__HAVE_STDARG_H
+#cmakedefine EVENT__HAVE_STDARG_H 1
/* Define to 1 if you have the <stddef.h> header file. */
-#cmakedefine EVENT__HAVE_STDDEF_H
+#cmakedefine EVENT__HAVE_STDDEF_H 1
/* Define to 1 if you have the <stdint.h> header file. */
-#cmakedefine EVENT__HAVE_STDINT_H
+#cmakedefine EVENT__HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
-#cmakedefine EVENT__HAVE_STDLIB_H
+#cmakedefine EVENT__HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
-#cmakedefine EVENT__HAVE_STRINGS_H
+#cmakedefine EVENT__HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
-#cmakedefine EVENT__HAVE_STRING_H
+#cmakedefine EVENT__HAVE_STRING_H 1
/* Define to 1 if you have the `strlcpy' function. */
-#cmakedefine EVENT__HAVE_STRLCPY
+#cmakedefine EVENT__HAVE_STRLCPY 1
/* Define to 1 if you have the `strsep' function. */
-#cmakedefine EVENT__HAVE_STRSEP
+#cmakedefine EVENT__HAVE_STRSEP 1
/* Define to 1 if you have the `strtok_r' function. */
-#cmakedefine EVENT__HAVE_STRTOK_R
+#cmakedefine EVENT__HAVE_STRTOK_R 1
/* Define to 1 if you have the `strtoll' function. */
-#cmakedefine EVENT__HAVE_STRTOLL
+#cmakedefine EVENT__HAVE_STRTOLL 1
/* Define to 1 if the system has the type `struct addrinfo'. */
-#cmakedefine EVENT__HAVE_STRUCT_ADDRINFO
+#cmakedefine EVENT__HAVE_STRUCT_ADDRINFO 1
/* Define to 1 if the system has the type `struct in6_addr'. */
-#cmakedefine EVENT__HAVE_STRUCT_IN6_ADDR
+#cmakedefine EVENT__HAVE_STRUCT_IN6_ADDR 1
/* Define to 1 if `s6_addr16' is member of `struct in6_addr'. */
-#cmakedefine EVENT__HAVE_STRUCT_IN6_ADDR_S6_ADDR16
+#cmakedefine EVENT__HAVE_STRUCT_IN6_ADDR_S6_ADDR16 1
/* Define to 1 if `s6_addr32' is member of `struct in6_addr'. */
-#cmakedefine EVENT__HAVE_STRUCT_IN6_ADDR_S6_ADDR32
+#cmakedefine EVENT__HAVE_STRUCT_IN6_ADDR_S6_ADDR32 1
/* Define to 1 if the system has the type `struct sockaddr_in6'. */
-#cmakedefine EVENT__HAVE_STRUCT_SOCKADDR_IN6
+#cmakedefine EVENT__HAVE_STRUCT_SOCKADDR_IN6 1
/* Define to 1 if `sin6_len' is member of `struct sockaddr_in6'. */
-#cmakedefine EVENT__HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
+#cmakedefine EVENT__HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN 1
/* Define to 1 if `sin_len' is member of `struct sockaddr_in'. */
-#cmakedefine EVENT__HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
+#cmakedefine EVENT__HAVE_STRUCT_SOCKADDR_IN_SIN_LEN 1
/* Define to 1 if the system has the type `struct sockaddr_storage'. */
-#cmakedefine EVENT__HAVE_STRUCT_SOCKADDR_STORAGE
+#cmakedefine EVENT__HAVE_STRUCT_SOCKADDR_STORAGE 1
/* Define to 1 if `ss_family' is a member of `struct sockaddr_storage'. */
-#cmakedefine EVENT__HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY
+#cmakedefine EVENT__HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY 1
/* Define to 1 if `__ss_family' is a member of `struct sockaddr_storage'. */
-#cmakedefine EVENT__HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY
+#cmakedefine EVENT__HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY 1
-/* Define to 1 if you have the `sysctl' function. */
-#cmakedefine EVENT__HAVE_SYSCTL
+/* Define to 1 if the system has the type `struct linger'. */
+#cmakedefine EVENT__HAVE_STRUCT_LINGER 1
-/* Define to 1 if you have the <sys/devpoll.h> header file. */
-#cmakedefine EVENT__HAVE_SYS_DEVPOLL_H
+/* Define to 1 if you have the `sysctl' function. */
+#cmakedefine EVENT__HAVE_SYSCTL 1
/* Define to 1 if you have the <sys/epoll.h> header file. */
-#cmakedefine EVENT__HAVE_SYS_EPOLL_H
+#cmakedefine EVENT__HAVE_SYS_EPOLL_H 1
/* Define to 1 if you have the <sys/eventfd.h> header file. */
-#cmakedefine EVENT__HAVE_SYS_EVENTFD_H
+#cmakedefine EVENT__HAVE_SYS_EVENTFD_H 1
/* Define to 1 if you have the <sys/event.h> header file. */
-#cmakedefine EVENT__HAVE_SYS_EVENT_H
+#cmakedefine EVENT__HAVE_SYS_EVENT_H 1
/* Define to 1 if you have the <sys/ioctl.h> header file. */
-#cmakedefine EVENT__HAVE_SYS_IOCTL_H
+#cmakedefine EVENT__HAVE_SYS_IOCTL_H 1
/* Define to 1 if you have the <sys/mman.h> header file. */
-#cmakedefine EVENT__HAVE_SYS_MMAN_H
+#cmakedefine EVENT__HAVE_SYS_MMAN_H 1
/* Define to 1 if you have the <sys/param.h> header file. */
-#cmakedefine EVENT__HAVE_SYS_PARAM_H
+#cmakedefine EVENT__HAVE_SYS_PARAM_H 1
/* Define to 1 if you have the <sys/queue.h> header file. */
-#cmakedefine EVENT__HAVE_SYS_QUEUE_H
+#cmakedefine EVENT__HAVE_SYS_QUEUE_H 1
/* Define to 1 if you have the <sys/resource.h> header file. */
-#cmakedefine EVENT__HAVE_SYS_RESOURCE_H
+#cmakedefine EVENT__HAVE_SYS_RESOURCE_H 1
/* Define to 1 if you have the <sys/select.h> header file. */
-#cmakedefine EVENT__HAVE_SYS_SELECT_H
+#cmakedefine EVENT__HAVE_SYS_SELECT_H 1
/* Define to 1 if you have the <sys/sendfile.h> header file. */
-#cmakedefine EVENT__HAVE_SYS_SENDFILE_H
+#cmakedefine EVENT__HAVE_SYS_SENDFILE_H 1
/* Define to 1 if you have the <sys/socket.h> header file. */
-#cmakedefine EVENT__HAVE_SYS_SOCKET_H
+#cmakedefine EVENT__HAVE_SYS_SOCKET_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
-#cmakedefine EVENT__HAVE_SYS_STAT_H
+#cmakedefine EVENT__HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/sysctl.h> header file. */
-#cmakedefine EVENT__HAVE_SYS_SYSCTL_H
+#cmakedefine EVENT__HAVE_SYS_SYSCTL_H 1
/* Define to 1 if you have the <sys/timerfd.h> header file. */
-#cmakedefine EVENT__HAVE_SYS_TIMERFD_H */
+#cmakedefine EVENT__HAVE_SYS_TIMERFD_H 1
/* Define to 1 if you have the <sys/time.h> header file. */
-#cmakedefine EVENT__HAVE_SYS_TIME_H
+#cmakedefine EVENT__HAVE_SYS_TIME_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
-#cmakedefine EVENT__HAVE_SYS_TYPES_H
+#cmakedefine EVENT__HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <sys/uio.h> header file. */
-#cmakedefine EVENT__HAVE_SYS_UIO_H
+#cmakedefine EVENT__HAVE_SYS_UIO_H 1
/* Define to 1 if you have the <sys/wait.h> header file. */
-#cmakedefine EVENT__HAVE_SYS_WAIT_H
+#cmakedefine EVENT__HAVE_SYS_WAIT_H 1
/* Define to 1 if you have the <errno.h> header file. */
-#cmakedefine EVENT__HAVE_ERRNO_H
+#cmakedefine EVENT__HAVE_ERRNO_H 1
/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */
-#cmakedefine EVENT__HAVE_TAILQFOREACH
+#cmakedefine EVENT__HAVE_TAILQFOREACH 1
/* Define if timeradd is defined in <sys/time.h> */
-#cmakedefine EVENT__HAVE_TIMERADD
+#cmakedefine EVENT__HAVE_TIMERADD 1
/* Define if timerclear is defined in <sys/time.h> */
-#cmakedefine EVENT__HAVE_TIMERCLEAR
+#cmakedefine EVENT__HAVE_TIMERCLEAR 1
/* Define if timercmp is defined in <sys/time.h> */
-#cmakedefine EVENT__HAVE_TIMERCMP
+#cmakedefine EVENT__HAVE_TIMERCMP 1
/* Define to 1 if you have the `timerfd_create' function. */
-#cmakedefine EVENT__HAVE_TIMERFD_CREATE
+#cmakedefine EVENT__HAVE_TIMERFD_CREATE 1
/* Define if timerisset is defined in <sys/time.h> */
-#cmakedefine EVENT__HAVE_TIMERISSET
+#cmakedefine EVENT__HAVE_TIMERISSET 1
/* Define to 1 if the system has the type `uint8_t'. */
-#cmakedefine EVENT__HAVE_UINT8_T
+#cmakedefine EVENT__HAVE_UINT8_T 1
/* Define to 1 if the system has the type `uint16_t'. */
-#cmakedefine EVENT__HAVE_UINT16_T
+#cmakedefine EVENT__HAVE_UINT16_T 1
/* Define to 1 if the system has the type `uint32_t'. */
-#cmakedefine EVENT__HAVE_UINT32_T
+#cmakedefine EVENT__HAVE_UINT32_T 1
/* Define to 1 if the system has the type `uint64_t'. */
-#cmakedefine EVENT__HAVE_UINT64_T
+#cmakedefine EVENT__HAVE_UINT64_T 1
/* Define to 1 if the system has the type `uintptr_t'. */
-#cmakedefine EVENT__HAVE_UINTPTR_T
+#cmakedefine EVENT__HAVE_UINTPTR_T 1
/* Define to 1 if you have the `umask' function. */
-#cmakedefine EVENT__HAVE_UMASK
+#cmakedefine EVENT__HAVE_UMASK 1
/* Define to 1 if you have the <unistd.h> header file. */
-#cmakedefine EVENT__HAVE_UNISTD_H
+#cmakedefine EVENT__HAVE_UNISTD_H 1
/* Define to 1 if you have the `unsetenv' function. */
-#cmakedefine EVENT__HAVE_UNSETENV
+#cmakedefine EVENT__HAVE_UNSETENV 1
/* Define to 1 if you have the `vasprintf' function. */
-#cmakedefine EVENT__HAVE_VASPRINTF
+#cmakedefine EVENT__HAVE_VASPRINTF 1
/* Define if kqueue works correctly with pipes */
-#cmakedefine EVENT__HAVE_WORKING_KQUEUE
+#cmakedefine EVENT__HAVE_WORKING_KQUEUE 1
#ifdef __USE_UNUSED_DEFINITIONS__
/* Define to necessary symbol if this constant uses a non-standard name on your system. */
@@ -455,11 +458,8 @@
/* The size of `size_t', as computed by sizeof. */
#define EVENT__SIZEOF_SIZE_T @EVENT__SIZEOF_SIZE_T@
-/* Define to 1 if you have the ANSI C header files. */
-#cmakedefine EVENT__STDC_HEADERS
-
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
-#cmakedefine EVENT__TIME_WITH_SYS_TIME
+#cmakedefine EVENT__TIME_WITH_SYS_TIME 1
/* The size of `socklen_t', as computed by sizeof. */
#define EVENT__SIZEOF_SOCKLEN_T @EVENT__SIZEOF_SOCKLEN_T@
@@ -467,32 +467,6 @@
/* The size of 'void *', as computer by sizeof */
#define EVENT__SIZEOF_VOID_P @EVENT__SIZEOF_VOID_P@
-/* set an alias for whatever __func__ __FUNCTION__ is, what sillyness */
-#if defined (__func__)
-#define EVENT____func__ __func__
-#elif defined(__FUNCTION__)
-#define EVENT____func__ __FUNCTION__
-#else
-#define EVENT____func__ __FILE__
-#endif
-
-
-#ifdef __THESE_ARE_NOT_CONFIG_H_THINGS_THEY_ARE_DASH_D_THINGS__
-/* Number of bits in a file offset, on hosts where this is settable. */
-/* Ellzey is not satisfied */
-#define EVENT___FILE_OFFSET_BITS @EVENT___FILE_OFFSET_BITS@
-
-/* Define for large files, on AIX-style hosts. */
-#define @_LARGE_FILES@
-#endif
-
-#ifdef _WhAT_DOES_THIS_EVEN_DO_
-/* Define to empty if `const' does not conform to ANSI C. */
-/* lolwut? - ellzey */
-#undef EVENT__const
-#endif
-
-
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
@@ -509,8 +483,8 @@
#define EVENT__inline @EVENT__inline@
#endif
-/* Define to `int' if <sys/tyes.h> does not define. */
-#define EVENT__pid_t @EVENT__pid_t@
+#cmakedefine EVENT__HAVE___func__ 1
+#cmakedefine EVENT__HAVE___FUNCTION__ 1
/* Define to `unsigned' if <sys/types.h> does not define. */
#define EVENT__size_t @EVENT__size_t@
@@ -521,12 +495,4 @@
/* Define to `int' if <sys/types.h> does not define. */
#define EVENT__ssize_t @EVENT__ssize_t@
-#cmakedefine EVENT__NEED_DLLIMPORT
-
-/* Define to 1 if you have ERR_remove_thread_stat(). */
-#cmakedefine EVENT__HAVE_ERR_REMOVE_THREAD_STATE
-
-/* Define if waitpid() supports WNOWAIT */
-#cmakedefine EVENT__HAVE_WAITPID_WITH_WNOWAIT
-
-#endif
+#endif /* \EVENT2_EVENT_CONFIG_H_INCLUDED_ */
diff --git a/event-internal.h b/event-internal.h
index 66dcfc32..92941b71 100644
--- a/event-internal.h
+++ b/event-internal.h
@@ -219,7 +219,7 @@ struct event_base {
/** Function pointers used to describe the backend that this event_base
* uses for signals */
const struct eventop *evsigsel;
- /** Data to implement the common signal handelr code. */
+ /** Data to implement the common signal handler code. */
struct evsig_info sig;
/** Number of virtual events */
@@ -368,6 +368,10 @@ struct event_config {
};
/* Internal use only: Functions that might be missing from <sys/queue.h> */
+#ifndef LIST_END
+#define LIST_END(head) NULL
+#endif
+
#ifndef TAILQ_FIRST
#define TAILQ_FIRST(head) ((head)->tqh_first)
#endif
@@ -421,16 +425,19 @@ int event_del_nolock_(struct event *ev, int blocking);
int event_remove_timer_nolock_(struct event *ev);
void event_active_nolock_(struct event *ev, int res, short count);
+EVENT2_EXPORT_SYMBOL
int event_callback_activate_(struct event_base *, struct event_callback *);
int event_callback_activate_nolock_(struct event_base *, struct event_callback *);
int event_callback_cancel_(struct event_base *base,
struct event_callback *evcb);
void event_callback_finalize_nolock_(struct event_base *base, unsigned flags, struct event_callback *evcb, void (*cb)(struct event_callback *, void *));
+EVENT2_EXPORT_SYMBOL
void event_callback_finalize_(struct event_base *base, unsigned flags, struct event_callback *evcb, void (*cb)(struct event_callback *, void *));
int event_callback_finalize_many_(struct event_base *base, int n_cbs, struct event_callback **evcb, void (*cb)(struct event_callback *, void *));
+EVENT2_EXPORT_SYMBOL
void event_active_later_(struct event *ev, int res);
void event_active_later_nolock_(struct event *ev, int res);
int event_callback_activate_later_nolock_(struct event_base *base,
@@ -441,6 +448,7 @@ void event_callback_init_(struct event_base *base,
struct event_callback *cb);
/* FIXME document. */
+EVENT2_EXPORT_SYMBOL
void event_base_add_virtual_(struct event_base *base);
void event_base_del_virtual_(struct event_base *base);
@@ -450,6 +458,7 @@ void event_base_del_virtual_(struct event_base *base);
Returns on success; aborts on failure.
*/
+EVENT2_EXPORT_SYMBOL
void event_base_assert_ok_(struct event_base *base);
void event_base_assert_ok_nolock_(struct event_base *base);
diff --git a/event.c b/event.c
index 503003e2..3816650e 100644
--- a/event.c
+++ b/event.c
@@ -52,6 +52,9 @@
#include <string.h>
#include <time.h>
#include <limits.h>
+#ifdef EVENT__HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
#include "event2/event.h"
#include "event2/event_struct.h"
@@ -123,6 +126,7 @@ static const struct eventop *eventops[] = {
};
/* Global state; deprecated */
+EVENT2_EXPORT_SYMBOL
struct event_base *event_global_current_base_ = NULL;
#define current_base event_global_current_base_
@@ -228,133 +232,169 @@ HT_PROTOTYPE(event_debug_map, event_debug_entry, node, hash_debug_entry,
HT_GENERATE(event_debug_map, event_debug_entry, node, hash_debug_entry,
eq_debug_entry, 0.5, mm_malloc, mm_realloc, mm_free)
-/* Macro: record that ev is now setup (that is, ready for an add) */
-#define event_debug_note_setup_(ev) do { \
- if (event_debug_mode_on_) { \
- struct event_debug_entry *dent,find; \
- find.ptr = (ev); \
- EVLOCK_LOCK(event_debug_map_lock_, 0); \
- dent = HT_FIND(event_debug_map, &global_debug_map, &find); \
- if (dent) { \
- dent->added = 0; \
- } else { \
- dent = mm_malloc(sizeof(*dent)); \
- if (!dent) \
- event_err(1, \
- "Out of memory in debugging code"); \
- dent->ptr = (ev); \
- dent->added = 0; \
- HT_INSERT(event_debug_map, &global_debug_map, dent); \
- } \
- EVLOCK_UNLOCK(event_debug_map_lock_, 0); \
- } \
- event_debug_mode_too_late = 1; \
- } while (0)
-/* Macro: record that ev is no longer setup */
-#define event_debug_note_teardown_(ev) do { \
- if (event_debug_mode_on_) { \
- struct event_debug_entry *dent,find; \
- find.ptr = (ev); \
- EVLOCK_LOCK(event_debug_map_lock_, 0); \
- dent = HT_REMOVE(event_debug_map, &global_debug_map, &find); \
- if (dent) \
- mm_free(dent); \
- EVLOCK_UNLOCK(event_debug_map_lock_, 0); \
- } \
- event_debug_mode_too_late = 1; \
- } while (0)
+/* record that ev is now setup (that is, ready for an add) */
+static void event_debug_note_setup_(const struct event *ev)
+{
+ struct event_debug_entry *dent, find;
+
+ if (!event_debug_mode_on_)
+ goto out;
+
+ find.ptr = ev;
+ EVLOCK_LOCK(event_debug_map_lock_, 0);
+ dent = HT_FIND(event_debug_map, &global_debug_map, &find);
+ if (dent) {
+ dent->added = 0;
+ } else {
+ dent = mm_malloc(sizeof(*dent));
+ if (!dent)
+ event_err(1,
+ "Out of memory in debugging code");
+ dent->ptr = ev;
+ dent->added = 0;
+ HT_INSERT(event_debug_map, &global_debug_map, dent);
+ }
+ EVLOCK_UNLOCK(event_debug_map_lock_, 0);
+
+out:
+ event_debug_mode_too_late = 1;
+}
+/* record that ev is no longer setup */
+static void event_debug_note_teardown_(const struct event *ev)
+{
+ struct event_debug_entry *dent, find;
+
+ if (!event_debug_mode_on_)
+ goto out;
+
+ find.ptr = ev;
+ EVLOCK_LOCK(event_debug_map_lock_, 0);
+ dent = HT_REMOVE(event_debug_map, &global_debug_map, &find);
+ if (dent)
+ mm_free(dent);
+ EVLOCK_UNLOCK(event_debug_map_lock_, 0);
+
+out:
+ event_debug_mode_too_late = 1;
+}
/* Macro: record that ev is now added */
-#define event_debug_note_add_(ev) do { \
- if (event_debug_mode_on_) { \
- struct event_debug_entry *dent,find; \
- find.ptr = (ev); \
- EVLOCK_LOCK(event_debug_map_lock_, 0); \
- dent = HT_FIND(event_debug_map, &global_debug_map, &find); \
- if (dent) { \
- dent->added = 1; \
- } else { \
- event_errx(EVENT_ERR_ABORT_, \
- "%s: noting an add on a non-setup event %p" \
- " (events: 0x%x, fd: "EV_SOCK_FMT \
- ", flags: 0x%x)", \
- __func__, (ev), (ev)->ev_events, \
- EV_SOCK_ARG((ev)->ev_fd), (ev)->ev_flags); \
- } \
- EVLOCK_UNLOCK(event_debug_map_lock_, 0); \
- } \
- event_debug_mode_too_late = 1; \
- } while (0)
-/* Macro: record that ev is no longer added */
-#define event_debug_note_del_(ev) do { \
- if (event_debug_mode_on_) { \
- struct event_debug_entry *dent,find; \
- find.ptr = (ev); \
- EVLOCK_LOCK(event_debug_map_lock_, 0); \
- dent = HT_FIND(event_debug_map, &global_debug_map, &find); \
- if (dent) { \
- dent->added = 0; \
- } else { \
- event_errx(EVENT_ERR_ABORT_, \
- "%s: noting a del on a non-setup event %p" \
- " (events: 0x%x, fd: "EV_SOCK_FMT \
- ", flags: 0x%x)", \
- __func__, (ev), (ev)->ev_events, \
- EV_SOCK_ARG((ev)->ev_fd), (ev)->ev_flags); \
- } \
- EVLOCK_UNLOCK(event_debug_map_lock_, 0); \
- } \
- event_debug_mode_too_late = 1; \
- } while (0)
-/* Macro: assert that ev is setup (i.e., okay to add or inspect) */
-#define event_debug_assert_is_setup_(ev) do { \
- if (event_debug_mode_on_) { \
- struct event_debug_entry *dent,find; \
- find.ptr = (ev); \
- EVLOCK_LOCK(event_debug_map_lock_, 0); \
- dent = HT_FIND(event_debug_map, &global_debug_map, &find); \
- if (!dent) { \
- event_errx(EVENT_ERR_ABORT_, \
- "%s called on a non-initialized event %p" \
- " (events: 0x%x, fd: "EV_SOCK_FMT\
- ", flags: 0x%x)", \
- __func__, (ev), (ev)->ev_events, \
- EV_SOCK_ARG((ev)->ev_fd), (ev)->ev_flags); \
- } \
- EVLOCK_UNLOCK(event_debug_map_lock_, 0); \
- } \
- } while (0)
-/* Macro: assert that ev is not added (i.e., okay to tear down or set
- * up again) */
-#define event_debug_assert_not_added_(ev) do { \
- if (event_debug_mode_on_) { \
- struct event_debug_entry *dent,find; \
- find.ptr = (ev); \
- EVLOCK_LOCK(event_debug_map_lock_, 0); \
- dent = HT_FIND(event_debug_map, &global_debug_map, &find); \
- if (dent && dent->added) { \
- event_errx(EVENT_ERR_ABORT_, \
- "%s called on an already added event %p" \
- " (events: 0x%x, fd: "EV_SOCK_FMT", " \
- "flags: 0x%x)", \
- __func__, (ev), (ev)->ev_events, \
- EV_SOCK_ARG((ev)->ev_fd), (ev)->ev_flags); \
- } \
- EVLOCK_UNLOCK(event_debug_map_lock_, 0); \
- } \
- } while (0)
+static void event_debug_note_add_(const struct event *ev)
+{
+ struct event_debug_entry *dent,find;
+
+ if (!event_debug_mode_on_)
+ goto out;
+
+ find.ptr = ev;
+ EVLOCK_LOCK(event_debug_map_lock_, 0);
+ dent = HT_FIND(event_debug_map, &global_debug_map, &find);
+ if (dent) {
+ dent->added = 1;
+ } else {
+ event_errx(EVENT_ERR_ABORT_,
+ "%s: noting an add on a non-setup event %p"
+ " (events: 0x%x, fd: "EV_SOCK_FMT
+ ", flags: 0x%x)",
+ __func__, ev, ev->ev_events,
+ EV_SOCK_ARG(ev->ev_fd), ev->ev_flags);
+ }
+ EVLOCK_UNLOCK(event_debug_map_lock_, 0);
+
+out:
+ event_debug_mode_too_late = 1;
+}
+/* record that ev is no longer added */
+static void event_debug_note_del_(const struct event *ev)
+{
+ struct event_debug_entry *dent, find;
+
+ if (!event_debug_mode_on_)
+ goto out;
+
+ find.ptr = ev;
+ EVLOCK_LOCK(event_debug_map_lock_, 0);
+ dent = HT_FIND(event_debug_map, &global_debug_map, &find);
+ if (dent) {
+ dent->added = 0;
+ } else {
+ event_errx(EVENT_ERR_ABORT_,
+ "%s: noting a del on a non-setup event %p"
+ " (events: 0x%x, fd: "EV_SOCK_FMT
+ ", flags: 0x%x)",
+ __func__, ev, ev->ev_events,
+ EV_SOCK_ARG(ev->ev_fd), ev->ev_flags);
+ }
+ EVLOCK_UNLOCK(event_debug_map_lock_, 0);
+
+out:
+ event_debug_mode_too_late = 1;
+}
+/* assert that ev is setup (i.e., okay to add or inspect) */
+static void event_debug_assert_is_setup_(const struct event *ev)
+{
+ struct event_debug_entry *dent, find;
+
+ if (!event_debug_mode_on_)
+ return;
+
+ find.ptr = ev;
+ EVLOCK_LOCK(event_debug_map_lock_, 0);
+ dent = HT_FIND(event_debug_map, &global_debug_map, &find);
+ if (!dent) {
+ event_errx(EVENT_ERR_ABORT_,
+ "%s called on a non-initialized event %p"
+ " (events: 0x%x, fd: "EV_SOCK_FMT
+ ", flags: 0x%x)",
+ __func__, ev, ev->ev_events,
+ EV_SOCK_ARG(ev->ev_fd), ev->ev_flags);
+ }
+ EVLOCK_UNLOCK(event_debug_map_lock_, 0);
+}
+/* assert that ev is not added (i.e., okay to tear down or set up again) */
+static void event_debug_assert_not_added_(const struct event *ev)
+{
+ struct event_debug_entry *dent, find;
+
+ if (!event_debug_mode_on_)
+ return;
+
+ find.ptr = ev;
+ EVLOCK_LOCK(event_debug_map_lock_, 0);
+ dent = HT_FIND(event_debug_map, &global_debug_map, &find);
+ if (dent && dent->added) {
+ event_errx(EVENT_ERR_ABORT_,
+ "%s called on an already added event %p"
+ " (events: 0x%x, fd: "EV_SOCK_FMT", "
+ "flags: 0x%x)",
+ __func__, ev, ev->ev_events,
+ EV_SOCK_ARG(ev->ev_fd), ev->ev_flags);
+ }
+ EVLOCK_UNLOCK(event_debug_map_lock_, 0);
+}
+static void event_debug_assert_socket_nonblocking_(evutil_socket_t fd)
+{
+ if (!event_debug_mode_on_)
+ return;
+ if (fd < 0)
+ return;
+
+#ifndef _WIN32
+ {
+ int flags;
+ if ((flags = fcntl(fd, F_GETFL, NULL)) >= 0) {
+ EVUTIL_ASSERT(flags & O_NONBLOCK);
+ }
+ }
+#endif
+}
#else
-#define event_debug_note_setup_(ev) \
- ((void)0)
-#define event_debug_note_teardown_(ev) \
- ((void)0)
-#define event_debug_note_add_(ev) \
- ((void)0)
-#define event_debug_note_del_(ev) \
- ((void)0)
-#define event_debug_assert_is_setup_(ev) \
- ((void)0)
-#define event_debug_assert_not_added_(ev) \
- ((void)0)
+static void event_debug_note_setup_(const struct event *ev) { (void)ev; }
+static void event_debug_note_teardown_(const struct event *ev) { (void)ev; }
+static void event_debug_note_add_(const struct event *ev) { (void)ev; }
+static void event_debug_note_del_(const struct event *ev) { (void)ev; }
+static void event_debug_assert_is_setup_(const struct event *ev) { (void)ev; }
+static void event_debug_assert_not_added_(const struct event *ev) { (void)ev; }
+static void event_debug_assert_socket_nonblocking_(evutil_socket_t fd) { (void)fd; }
#endif
#define EVENT_BASE_ASSERT_LOCKED(base) \
@@ -590,7 +630,9 @@ event_base_new_with_config(const struct event_config *cfg)
int flags;
if (should_check_environment && !precise_time) {
precise_time = evutil_getenv_("EVENT_PRECISE_TIMER") != NULL;
- base->flags |= EVENT_BASE_FLAG_PRECISE_TIMER;
+ if (precise_time) {
+ base->flags |= EVENT_BASE_FLAG_PRECISE_TIMER;
+ }
}
flags = precise_time ? EV_MONOT_PRECISE : 0;
evutil_configure_monotonic_time_(&base->monotonic_timer, flags);
@@ -862,6 +904,7 @@ event_base_free_(struct event_base *base, int run_finalizers)
* A simple case is bufferevent with underlying (i.e. filters).
*/
int i = event_base_free_queues_(base, run_finalizers);
+ event_debug(("%s: %d events freed", __func__, i));
if (!i) {
break;
}
@@ -1640,10 +1683,12 @@ event_process_active_single_queue(struct event_base *base,
break;
case EV_CLOSURE_EVENT: {
void (*evcb_callback)(evutil_socket_t, short, void *);
+ short res;
EVUTIL_ASSERT(ev != NULL);
evcb_callback = *ev->ev_callback;
+ res = ev->ev_res;
EVBASE_RELEASE_LOCK(base, th_base_lock);
- evcb_callback(ev->ev_fd, ev->ev_res, ev->ev_arg);
+ evcb_callback(ev->ev_fd, res, ev->ev_arg);
}
break;
case EV_CLOSURE_CB_SELF: {
@@ -2069,6 +2114,8 @@ event_assign(struct event *ev, struct event_base *base, evutil_socket_t fd, shor
if (arg == &event_self_cbarg_ptr_)
arg = ev;
+ if (!(events & EV_SIGNAL))
+ event_debug_assert_socket_nonblocking_(fd);
event_debug_assert_not_added_(ev);
ev->ev_base = base;
@@ -2719,17 +2766,16 @@ static int
event_del_(struct event *ev, int blocking)
{
int res;
+ struct event_base *base = ev->ev_base;
- if (EVUTIL_FAILURE_CHECK(!ev->ev_base)) {
+ if (EVUTIL_FAILURE_CHECK(!base)) {
event_warnx("%s: event has no event_base set.", __func__);
return -1;
}
- EVBASE_ACQUIRE_LOCK(ev->ev_base, th_base_lock);
-
+ EVBASE_ACQUIRE_LOCK(base, th_base_lock);
res = event_del_nolock_(ev, blocking);
-
- EVBASE_RELEASE_LOCK(ev->ev_base, th_base_lock);
+ EVBASE_RELEASE_LOCK(base, th_base_lock);
return (res);
}
@@ -2779,21 +2825,7 @@ event_del_nolock_(struct event *ev, int blocking)
}
}
- /* If the main thread is currently executing this event's callback,
- * and we are not the main thread, then we want to wait until the
- * callback is done before we start removing the event. That way,
- * when this function returns, it will be safe to free the
- * user-supplied argument. */
base = ev->ev_base;
-#ifndef EVENT__DISABLE_THREAD_SUPPORT
- if (blocking != EVENT_DEL_NOBLOCK &&
- base->current_event == event_to_event_callback(ev) &&
- !EVBASE_IN_THREAD(base) &&
- (blocking == EVENT_DEL_BLOCK || !(ev->ev_events & EV_FINALIZE))) {
- ++base->current_event_waiters;
- EVTHREAD_COND_WAIT(base->current_event_cond, base->th_base_lock);
- }
-#endif
EVUTIL_ASSERT(!(ev->ev_flags & ~EVLIST_ALL));
@@ -2832,6 +2864,10 @@ event_del_nolock_(struct event *ev, int blocking)
notify = 1;
res = 0;
}
+ /* If we do not have events, let's notify event base so it can
+ * exit without waiting */
+ if (!event_haveevents(base) && !N_ACTIVE_CALLBACKS(base))
+ notify = 1;
}
/* if we are not in the right thread, we need to wake up the loop */
@@ -2840,6 +2876,21 @@ event_del_nolock_(struct event *ev, int blocking)
event_debug_note_del_(ev);
+ /* If the main thread is currently executing this event's callback,
+ * and we are not the main thread, then we want to wait until the
+ * callback is done before returning. That way, when this function
+ * returns, it will be safe to free the user-supplied argument.
+ */
+#ifndef EVENT__DISABLE_THREAD_SUPPORT
+ if (blocking != EVENT_DEL_NOBLOCK &&
+ base->current_event == event_to_event_callback(ev) &&
+ !EVBASE_IN_THREAD(base) &&
+ (blocking == EVENT_DEL_BLOCK || !(ev->ev_events & EV_FINALIZE))) {
+ ++base->current_event_waiters;
+ EVTHREAD_COND_WAIT(base->current_event_cond, base->th_base_lock);
+ }
+#endif
+
return (res);
}
@@ -2960,6 +3011,7 @@ event_callback_activate_nolock_(struct event_base *base,
switch (evcb->evcb_flags & (EVLIST_ACTIVE|EVLIST_ACTIVE_LATER)) {
default:
EVUTIL_ASSERT(0);
+ EVUTIL_FALLTHROUGH;
case EVLIST_ACTIVE_LATER:
event_queue_remove_active_later(base, evcb);
r = 0;
@@ -3148,10 +3200,6 @@ timeout_process(struct event_base *base)
}
}
-#if (EVLIST_INTERNAL >> 4) != 1
-#error "Mismatch for value of EVLIST_INTERNAL"
-#endif
-
#ifndef MAX
#define MAX(a,b) (((a)>(b))?(a):(b))
#endif
@@ -3159,13 +3207,13 @@ timeout_process(struct event_base *base)
#define MAX_EVENT_COUNT(var, v) var = MAX(var, v)
/* These are a fancy way to spell
- if (flags & EVLIST_INTERNAL)
+ if (~flags & EVLIST_INTERNAL)
base->event_count--/++;
*/
#define DECR_EVENT_COUNT(base,flags) \
- ((base)->event_count -= (~((flags) >> 4) & 1))
+ ((base)->event_count -= !((flags) & EVLIST_INTERNAL))
#define INCR_EVENT_COUNT(base,flags) do { \
- ((base)->event_count += (~((flags) >> 4) & 1)); \
+ ((base)->event_count += !((flags) & EVLIST_INTERNAL)); \
MAX_EVENT_COUNT((base)->event_count_max, (base)->event_count); \
} while (0)
@@ -3697,13 +3745,14 @@ dump_inserted_event_fn(const struct event_base *base, const struct event *e, voi
if (! (e->ev_flags & (EVLIST_INSERTED|EVLIST_TIMEOUT)))
return 0;
- fprintf(output, " %p [%s "EV_SOCK_FMT"]%s%s%s%s%s%s",
+ fprintf(output, " %p [%s "EV_SOCK_FMT"]%s%s%s%s%s%s%s",
(void*)e, gloss, EV_SOCK_ARG(e->ev_fd),
(e->ev_events&EV_READ)?" Read":"",
(e->ev_events&EV_WRITE)?" Write":"",
(e->ev_events&EV_CLOSED)?" EOF":"",
(e->ev_events&EV_SIGNAL)?" Signal":"",
(e->ev_events&EV_PERSIST)?" Persist":"",
+ (e->ev_events&EV_ET)?" ET":"",
(e->ev_flags&EVLIST_INTERNAL)?" Internal":"");
if (e->ev_flags & EVLIST_TIMEOUT) {
struct timeval tv;
diff --git a/event_iocp.c b/event_iocp.c
index a9902fbc..6b2a2e15 100644
--- a/event_iocp.c
+++ b/event_iocp.c
@@ -151,7 +151,7 @@ init_extension_functions(struct win32_extension_fns *ext)
const GUID connectex = WSAID_CONNECTEX;
const GUID getacceptexsockaddrs = WSAID_GETACCEPTEXSOCKADDRS;
SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
- if (s == INVALID_SOCKET)
+ if (s == EVUTIL_INVALID_SOCKET)
return;
ext->AcceptEx = get_extension_function(s, &acceptex);
ext->ConnectEx = get_extension_function(s, &connectex);
diff --git a/event_rpcgen.py b/event_rpcgen.py
index 9baf7302..0911ca25 100755
--- a/event_rpcgen.py
+++ b/event_rpcgen.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python
#
# Copyright (c) 2005-2007 Niels Provos <provos@citi.umich.edu>
# Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
@@ -36,10 +36,10 @@ QUIETLY = 0
def declare(s):
if not QUIETLY:
- print s
+ print(s)
def TranslateList(mylist, mydict):
- return map(lambda x: x % mydict, mylist)
+ return [x % mydict for x in mylist]
# Exception class for parse errors
class RpcGenError(Exception):
@@ -57,7 +57,7 @@ class Struct:
declare(' Created struct: %s' % name)
def AddEntry(self, entry):
- if self._tags.has_key(entry.Tag()):
+ if entry.Tag() in self._tags:
raise RpcGenError(
'Entry "%s" duplicates tag number %d from "%s" '
'around line %d' % (entry.Name(), entry.Tag(),
@@ -78,7 +78,7 @@ class Struct:
def PrintIndented(self, file, ident, code):
"""Takes an array, add indentation to each entry and prints it."""
for entry in code:
- print >>file, '%s%s' % (ident, entry)
+ file.write('%s%s\n' % (ident, entry))
class StructCCode(Struct):
""" Knows how to generate C code for a struct """
@@ -88,20 +88,19 @@ class StructCCode(Struct):
def PrintTags(self, file):
"""Prints the tag definitions for a structure."""
- print >>file, '/* Tag definition for %s */' % self._name
- print >>file, 'enum %s_ {' % self._name.lower()
+ file.write('/* Tag definition for %s */\n' % self._name)
+ file.write('enum %s_ {\n' % self._name.lower())
for entry in self._entries:
- print >>file, ' %s=%d,' % (self.EntryTagName(entry),
- entry.Tag())
- print >>file, ' %s_MAX_TAGS' % (self._name.upper())
- print >>file, '};\n'
+ file.write(' %s=%d,\n' % (self.EntryTagName(entry), entry.Tag()))
+ file.write(' %s_MAX_TAGS\n' % (self._name.upper()))
+ file.write('};\n\n')
def PrintForwardDeclaration(self, file):
- print >>file, 'struct %s;' % self._name
+ file.write('struct %s;\n' % self._name)
def PrintDeclaration(self, file):
- print >>file, '/* Structure declaration for %s */' % self._name
- print >>file, 'struct %s_access_ {' % self._name
+ file.write('/* Structure declaration for %s */\n' % self._name)
+ file.write('struct %s_access_ {\n' % self._name)
for entry in self._entries:
dcl = entry.AssignDeclaration('(*%s_assign)' % entry.Name())
dcl.extend(
@@ -110,20 +109,19 @@ class StructCCode(Struct):
dcl.extend(
entry.AddDeclaration('(*%s_add)' % entry.Name()))
self.PrintIndented(file, ' ', dcl)
- print >>file, '};\n'
+ file.write('};\n\n')
- print >>file, 'struct %s {' % self._name
- print >>file, ' struct %s_access_ *base;\n' % self._name
+ file.write('struct %s {\n' % self._name)
+ file.write(' struct %s_access_ *base;\n\n' % self._name)
for entry in self._entries:
dcl = entry.Declaration()
self.PrintIndented(file, ' ', dcl)
- print >>file, ''
+ file.write('\n')
for entry in self._entries:
- print >>file, ' ev_uint8_t %s_set;' % entry.Name()
- print >>file, '};\n'
+ file.write(' ev_uint8_t %s_set;\n' % entry.Name())
+ file.write('};\n\n')
- print >>file, \
-"""struct %(name)s *%(name)s_new(void);
+ file.write("""struct %(name)s *%(name)s_new(void);
struct %(name)s *%(name)s_new_with_arg(void *);
void %(name)s_free(struct %(name)s *);
void %(name)s_clear(struct %(name)s *);
@@ -133,7 +131,7 @@ int %(name)s_complete(struct %(name)s *);
void evtag_marshal_%(name)s(struct evbuffer *, ev_uint32_t,
const struct %(name)s *);
int evtag_unmarshal_%(name)s(struct evbuffer *, ev_uint32_t,
- struct %(name)s *);""" % { 'name' : self._name }
+ struct %(name)s *);\n""" % { 'name' : self._name })
# Write a setting function of every variable
@@ -146,22 +144,21 @@ int evtag_unmarshal_%(name)s(struct evbuffer *, ev_uint32_t,
self.PrintIndented(file, '', entry.AddDeclaration(
entry.AddFuncName()))
- print >>file, '/* --- %s done --- */\n' % self._name
+ file.write('/* --- %s done --- */\n\n' % self._name)
def PrintCode(self, file):
- print >>file, ('/*\n'
+ file.write(('/*\n'
' * Implementation of %s\n'
- ' */\n') % self._name
+ ' */\n\n') % self._name)
- print >>file, \
- 'static struct %(name)s_access_ %(name)s_base__ = {' % \
- { 'name' : self._name }
+ file.write('static struct %(name)s_access_ %(name)s_base__ = {\n' % \
+ { 'name' : self._name })
for entry in self._entries:
self.PrintIndented(file, ' ', entry.CodeBase())
- print >>file, '};\n'
+ file.write('};\n\n')
# Creation
- print >>file, (
+ file.write((
'struct %(name)s *\n'
'%(name)s_new(void)\n'
'{\n'
@@ -176,77 +173,77 @@ int evtag_unmarshal_%(name)s(struct evbuffer *, ev_uint32_t,
' event_warn("%%s: malloc", __func__);\n'
' return (NULL);\n'
' }\n'
- ' tmp->base = &%(name)s_base__;\n') % { 'name' : self._name }
+ ' tmp->base = &%(name)s_base__;\n\n') % { 'name' : self._name })
for entry in self._entries:
self.PrintIndented(file, ' ', entry.CodeInitialize('tmp'))
- print >>file, ' tmp->%s_set = 0;\n' % entry.Name()
+ file.write(' tmp->%s_set = 0;\n\n' % entry.Name())
- print >>file, (
+ file.write((
' return (tmp);\n'
- '}\n')
+ '}\n\n'))
# Adding
for entry in self._entries:
if entry.Array():
self.PrintIndented(file, '', entry.CodeAdd())
- print >>file, ''
+ file.write('\n')
# Assigning
for entry in self._entries:
self.PrintIndented(file, '', entry.CodeAssign())
- print >>file, ''
+ file.write('\n')
# Getting
for entry in self._entries:
self.PrintIndented(file, '', entry.CodeGet())
- print >>file, ''
+ file.write('\n')
# Clearing
- print >>file, ( 'void\n'
+ file.write(( 'void\n'
'%(name)s_clear(struct %(name)s *tmp)\n'
'{'
- ) % { 'name' : self._name }
+ '\n') % { 'name' : self._name })
for entry in self._entries:
self.PrintIndented(file, ' ', entry.CodeClear('tmp'))
- print >>file, '}\n'
+ file.write('}\n\n')
# Freeing
- print >>file, ( 'void\n'
+ file.write(( 'void\n'
'%(name)s_free(struct %(name)s *tmp)\n'
'{'
- ) % { 'name' : self._name }
+ '\n') % { 'name' : self._name })
for entry in self._entries:
self.PrintIndented(file, ' ', entry.CodeFree('tmp'))
- print >>file, (' free(tmp);\n'
- '}\n')
+ file.write((' free(tmp);\n'
+ '}\n\n'))
# Marshaling
- print >>file, ('void\n'
+ file.write(('void\n'
'%(name)s_marshal(struct evbuffer *evbuf, '
'const struct %(name)s *tmp)'
- '{') % { 'name' : self._name }
+ '{\n') % { 'name' : self._name })
for entry in self._entries:
indent = ' '
# Optional entries do not have to be set
if entry.Optional():
indent += ' '
- print >>file, ' if (tmp->%s_set) {' % entry.Name()
+ file.write(' if (tmp->%s_set) {\n' % entry.Name())
self.PrintIndented(
file, indent,
entry.CodeMarshal('evbuf', self.EntryTagName(entry),
entry.GetVarName('tmp'),
entry.GetVarLen('tmp')))
if entry.Optional():
- print >>file, ' }'
+ file.write(' }\n')
- print >>file, '}\n'
+ file.write('}\n\n')
# Unmarshaling
- print >>file, ('int\n'
+ file.write(('int\n'
'%(name)s_unmarshal(struct %(name)s *tmp, '
' struct evbuffer *evbuf)\n'
'{\n'
@@ -255,14 +252,14 @@ int evtag_unmarshal_%(name)s(struct evbuffer *, ev_uint32_t,
' if (evtag_peek(evbuf, &tag) == -1)\n'
' return (-1);\n'
' switch (tag) {\n'
- ) % { 'name' : self._name }
+ '\n') % { 'name' : self._name })
for entry in self._entries:
- print >>file, ' case %s:\n' % self.EntryTagName(entry)
+ file.write(' case %s:\n' % self.EntryTagName(entry))
if not entry.Array():
- print >>file, (
+ file.write((
' if (tmp->%s_set)\n'
' return (-1);'
- ) % (entry.Name())
+ '\n') % (entry.Name()))
self.PrintIndented(
file, ' ',
@@ -271,26 +268,26 @@ int evtag_unmarshal_%(name)s(struct evbuffer *, ev_uint32_t,
entry.GetVarName('tmp'),
entry.GetVarLen('tmp')))
- print >>file, ( ' tmp->%s_set = 1;\n' % entry.Name() +
- ' break;\n' )
- print >>file, ( ' default:\n'
+ file.write(( ' tmp->%s_set = 1;\n' % entry.Name() +
+ ' break;\n' ))
+ file.write(( ' default:\n'
' return -1;\n'
' }\n'
- ' }\n' )
+ ' }\n\n' ))
# Check if it was decoded completely
- print >>file, ( ' if (%(name)s_complete(tmp) == -1)\n'
+ file.write(( ' if (%(name)s_complete(tmp) == -1)\n'
' return (-1);'
- ) % { 'name' : self._name }
+ '\n') % { 'name' : self._name })
# Successfully decoded
- print >>file, ( ' return (0);\n'
- '}\n')
+ file.write(( ' return (0);\n'
+ '}\n\n'))
# Checking if a structure has all the required data
- print >>file, (
+ file.write((
'int\n'
'%(name)s_complete(struct %(name)s *msg)\n'
- '{' ) % { 'name' : self._name }
+ '{\n' ) % { 'name' : self._name })
for entry in self._entries:
if not entry.Optional():
code = [
@@ -303,12 +300,12 @@ int evtag_unmarshal_%(name)s(struct evbuffer *, ev_uint32_t,
self.PrintIndented(
file, ' ',
entry.CodeComplete('msg', entry.GetVarName('msg')))
- print >>file, (
+ file.write((
' return (0);\n'
- '}\n' )
+ '}\n\n' ))
# Complete message unmarshaling
- print >>file, (
+ file.write((
'int\n'
'evtag_unmarshal_%(name)s(struct evbuffer *evbuf, '
'ev_uint32_t need_tag, struct %(name)s *msg)\n'
@@ -330,10 +327,10 @@ int evtag_unmarshal_%(name)s(struct evbuffer *, ev_uint32_t,
' error:\n'
' evbuffer_free(tmp);\n'
' return (res);\n'
- '}\n' ) % { 'name' : self._name }
+ '}\n\n' ) % { 'name' : self._name })
# Complete message marshaling
- print >>file, (
+ file.write((
'void\n'
'evtag_marshal_%(name)s(struct evbuffer *evbuf, ev_uint32_t tag, '
'const struct %(name)s *msg)\n'
@@ -343,7 +340,7 @@ int evtag_unmarshal_%(name)s(struct evbuffer *, ev_uint32_t,
' %(name)s_marshal(buf_, msg);\n'
' evtag_marshal_buffer(evbuf, tag, buf_);\n '
' evbuffer_free(buf_);\n'
- '}\n' ) % { 'name' : self._name }
+ '}\n\n' ) % { 'name' : self._name })
class Entry:
def __init__(self, type, name, tag):
@@ -420,7 +417,7 @@ class Entry:
"optaddarg" :
self._optaddarg and ", const %s value" % self._ctype or ""
}
- for (k, v) in extradict.items():
+ for (k, v) in list(extradict.items()):
mapping[k] = v
return mapping
@@ -1127,7 +1124,7 @@ class EntryArray(Entry):
codearrayassign = self._entry.CodeArrayAssign(
'msg->%(name)s_data[off]' % self.GetTranslation(), 'value')
- code += map(lambda x: ' ' + x, codearrayassign)
+ code += [' ' + x for x in codearrayassign]
code += TranslateList([
' }',
@@ -1168,7 +1165,7 @@ class EntryArray(Entry):
code = TranslateList(code, self.GetTranslation())
- code += map(lambda x: ' ' + x, codearrayadd)
+ code += [' ' + x for x in codearrayadd]
code += TranslateList([
' msg->%(name)s_set = 1;',
@@ -1196,7 +1193,7 @@ class EntryArray(Entry):
code = TranslateList(code, translate)
- code += map(lambda x: ' ' + x, tmp)
+ code += [' ' + x for x in tmp]
code += [
' }',
@@ -1261,7 +1258,7 @@ class EntryArray(Entry):
code = TranslateList(code, translate)
if codearrayfree:
- code += map(lambda x: ' ' + x, codearrayfree)
+ code += [' ' + x for x in codearrayfree]
code += [
' }' ]
@@ -1585,8 +1582,14 @@ class CCodeGenerator:
'#include <event2/event.h>\n'
'#include <event2/buffer.h>\n'
'#include <event2/tag.h>\n\n'
- '#if defined(EVENT____func__) && !defined(__func__)\n'
- '#define __func__ EVENT____func__\n'
+ '#if defined(EVENT__HAVE___func__)\n'
+ '# ifndef __func__\n'
+ '# define __func__ __func__\n'
+ '# endif\n'
+ '#elif defined(EVENT__HAVE___FUNCTION__)\n'
+ '# define __func__ __FUNCTION__\n'
+ '#else\n'
+ '# define __func__ __FILE__\n'
'#endif\n\n'
)
@@ -1687,23 +1690,23 @@ class CommandLine:
declare('... creating "%s"' % header_file)
header_fp = open(header_file, 'w')
- print >>header_fp, factory.HeaderPreamble(filename)
+ header_fp.write(factory.HeaderPreamble(filename))
# Create forward declarations: allows other structs to reference
# each other
for entry in entities:
entry.PrintForwardDeclaration(header_fp)
- print >>header_fp, ''
+ header_fp.write('\n')
for entry in entities:
entry.PrintTags(header_fp)
entry.PrintDeclaration(header_fp)
- print >>header_fp, factory.HeaderPostamble(filename)
+ header_fp.write(factory.HeaderPostamble(filename))
header_fp.close()
declare('... creating "%s"' % impl_file)
impl_fp = open(impl_file, 'w')
- print >>impl_fp, factory.BodyPreamble(filename, header_file)
+ impl_fp.write(factory.BodyPreamble(filename, header_file))
for entry in entities:
entry.PrintCode(impl_fp)
impl_fp.close()
@@ -1713,16 +1716,16 @@ if __name__ == '__main__':
CommandLine(sys.argv).run()
sys.exit(0)
- except RpcGenError, e:
- print >>sys.stderr, e
+ except RpcGenError as e:
+ sys.stderr.write(e)
sys.exit(1)
- except EnvironmentError, e:
+ except EnvironmentError as e:
if e.filename and e.strerror:
- print >>sys.stderr, "%s: %s" % (e.filename, e.strerror)
+ sys.stderr.write("%s: %s" % (e.filename, e.strerror))
sys.exit(1)
elif e.strerror:
- print >> sys.stderr, e.strerror
+ sys.stderr.write(e.strerror)
sys.exit(1)
else:
raise
diff --git a/event_tagging.c b/event_tagging.c
index 6459dfa7..b021e8c8 100644
--- a/event_tagging.c
+++ b/event_tagging.c
@@ -93,9 +93,13 @@
a final padding nibble with value 0 is appended.
*/
+EVENT2_EXPORT_SYMBOL
int evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf);
+EVENT2_EXPORT_SYMBOL
int evtag_decode_int64(ev_uint64_t *pnumber, struct evbuffer *evbuf);
+EVENT2_EXPORT_SYMBOL
int evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t tag);
+EVENT2_EXPORT_SYMBOL
int evtag_decode_tag(ev_uint32_t *ptag, struct evbuffer *evbuf);
void
diff --git a/evmap.c b/evmap.c
index 3f76dd0a..9f46dd0f 100644
--- a/evmap.c
+++ b/evmap.c
@@ -393,7 +393,8 @@ evmap_io_del_(struct event_base *base, evutil_socket_t fd, struct event *ev)
if (res) {
void *extra = ((char*)ctx) + sizeof(struct evmap_io);
- if (evsel->del(base, ev->ev_fd, old, res, extra) == -1) {
+ if (evsel->del(base, ev->ev_fd,
+ old, (ev->ev_events & EV_ET) | res, extra) == -1) {
retval = -1;
} else {
retval = 1;
@@ -858,6 +859,7 @@ event_changelist_add_(struct event_base *base, evutil_socket_t fd, short old, sh
struct event_changelist *changelist = &base->changelist;
struct event_changelist_fdinfo *fdinfo = p;
struct event_change *change;
+ ev_uint8_t evchange = EV_CHANGE_ADD | (events & (EV_ET|EV_PERSIST|EV_SIGNAL));
event_changelist_check(base);
@@ -869,18 +871,12 @@ event_changelist_add_(struct event_base *base, evutil_socket_t fd, short old, sh
* since the delete might fail (because the fd had been closed since
* the last add, for instance. */
- if (events & (EV_READ|EV_SIGNAL)) {
- change->read_change = EV_CHANGE_ADD |
- (events & (EV_ET|EV_PERSIST|EV_SIGNAL));
- }
- if (events & EV_WRITE) {
- change->write_change = EV_CHANGE_ADD |
- (events & (EV_ET|EV_PERSIST|EV_SIGNAL));
- }
- if (events & EV_CLOSED) {
- change->close_change = EV_CHANGE_ADD |
- (events & (EV_ET|EV_PERSIST|EV_SIGNAL));
- }
+ if (events & (EV_READ|EV_SIGNAL))
+ change->read_change = evchange;
+ if (events & EV_WRITE)
+ change->write_change = evchange;
+ if (events & EV_CLOSED)
+ change->close_change = evchange;
event_changelist_check(base);
return (0);
@@ -893,6 +889,7 @@ event_changelist_del_(struct event_base *base, evutil_socket_t fd, short old, sh
struct event_changelist *changelist = &base->changelist;
struct event_changelist_fdinfo *fdinfo = p;
struct event_change *change;
+ ev_uint8_t del = EV_CHANGE_DEL | (events & EV_ET);
event_changelist_check(base);
change = event_changelist_get_or_construct(changelist, fd, old, fdinfo);
@@ -919,19 +916,19 @@ event_changelist_del_(struct event_base *base, evutil_socket_t fd, short old, sh
if (!(change->old_events & (EV_READ | EV_SIGNAL)))
change->read_change = 0;
else
- change->read_change = EV_CHANGE_DEL;
+ change->read_change = del;
}
if (events & EV_WRITE) {
if (!(change->old_events & EV_WRITE))
change->write_change = 0;
else
- change->write_change = EV_CHANGE_DEL;
+ change->write_change = del;
}
if (events & EV_CLOSED) {
if (!(change->old_events & EV_CLOSED))
change->close_change = 0;
else
- change->close_change = EV_CHANGE_DEL;
+ change->close_change = del;
}
event_changelist_check(base);
diff --git a/evrpc.c b/evrpc.c
index 2443ab27..68fa1b90 100644
--- a/evrpc.c
+++ b/evrpc.c
@@ -329,7 +329,8 @@ evrpc_request_cb(struct evhttp_request *req, void *arg)
return;
error:
- evrpc_reqstate_free_(rpc_state);
+ if (rpc_state)
+ evrpc_reqstate_free_(rpc_state);
evhttp_send_error(req, HTTP_SERVUNAVAIL, NULL);
return;
}
diff --git a/evthread-internal.h b/evthread-internal.h
index efdecf81..5fdf3161 100644
--- a/evthread-internal.h
+++ b/evthread-internal.h
@@ -49,9 +49,12 @@ struct event_base;
#if ! defined(EVENT__DISABLE_THREAD_SUPPORT) && defined(EVTHREAD_EXPOSE_STRUCTS)
/* Global function pointers to lock-related functions. NULL if locking isn't
enabled. */
+EVENT2_EXPORT_SYMBOL
extern struct evthread_lock_callbacks evthread_lock_fns_;
+EVENT2_EXPORT_SYMBOL
extern struct evthread_condition_callbacks evthread_cond_fns_;
extern unsigned long (*evthread_id_fn_)(void);
+EVENT2_EXPORT_SYMBOL
extern int evthread_lock_debugging_enabled_;
/** Return the ID of the current thread, or 1 if threading isn't enabled. */
@@ -182,14 +185,23 @@ EVLOCK_TRY_LOCK_(void *lock)
#elif ! defined(EVENT__DISABLE_THREAD_SUPPORT)
unsigned long evthreadimpl_get_id_(void);
+EVENT2_EXPORT_SYMBOL
int evthreadimpl_is_lock_debugging_enabled_(void);
+EVENT2_EXPORT_SYMBOL
void *evthreadimpl_lock_alloc_(unsigned locktype);
+EVENT2_EXPORT_SYMBOL
void evthreadimpl_lock_free_(void *lock, unsigned locktype);
+EVENT2_EXPORT_SYMBOL
int evthreadimpl_lock_lock_(unsigned mode, void *lock);
+EVENT2_EXPORT_SYMBOL
int evthreadimpl_lock_unlock_(unsigned mode, void *lock);
+EVENT2_EXPORT_SYMBOL
void *evthreadimpl_cond_alloc_(unsigned condtype);
+EVENT2_EXPORT_SYMBOL
void evthreadimpl_cond_free_(void *cond);
+EVENT2_EXPORT_SYMBOL
int evthreadimpl_cond_signal_(void *cond, int broadcast);
+EVENT2_EXPORT_SYMBOL
int evthreadimpl_cond_wait_(void *cond, void *lock, const struct timeval *tv);
int evthreadimpl_locking_enabled_(void);
@@ -355,6 +367,7 @@ EVLOCK_TRY_LOCK_(void *lock)
EVLOCK_UNLOCK(lock1_tmplock_,mode1); \
} while (0)
+EVENT2_EXPORT_SYMBOL
int evthread_is_debug_lock_held_(void *lock);
void *evthread_debug_get_real_lock_(void *lock);
@@ -377,6 +390,7 @@ int evutil_global_setup_locks_(const int enable_locks);
int evutil_secure_rng_global_setup_locks_(const int enable_locks);
/** Return current evthread_lock_callbacks */
+EVENT2_EXPORT_SYMBOL
struct evthread_lock_callbacks *evthread_get_lock_callbacks(void);
/** Return current evthread_condition_callbacks */
struct evthread_condition_callbacks *evthread_get_condition_callbacks(void);
diff --git a/evthread.c b/evthread.c
index f3f1eddc..3eac594d 100644
--- a/evthread.c
+++ b/evthread.c
@@ -46,7 +46,7 @@
#endif
#ifndef EVENT__DISABLE_DEBUG_MODE
-extern int event_debug_created_threadable_ctx_;
+extern int event_debug_created_threadable_ctx_;
extern int event_debug_mode_on_;
#endif
diff --git a/evutil.c b/evutil.c
index 1e8ef7bd..402ab0d8 100644
--- a/evutil.c
+++ b/evutil.c
@@ -386,6 +386,17 @@ evutil_make_listen_socket_reuseable_port(evutil_socket_t sock)
}
int
+evutil_make_listen_socket_ipv6only(evutil_socket_t sock)
+{
+#if defined(IPV6_V6ONLY)
+ int one = 1;
+ return setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void*) &one,
+ (ev_socklen_t)sizeof(one));
+#endif
+ return 0;
+}
+
+int
evutil_make_tcp_listen_socket_deferred(evutil_socket_t sock)
{
#if defined(EVENT__HAVE_NETINET_TCP_H) && defined(TCP_DEFER_ACCEPT)
@@ -595,44 +606,56 @@ evutil_socket_finished_connecting_(evutil_socket_t fd)
set by evutil_check_interfaces. */
static int have_checked_interfaces, had_ipv4_address, had_ipv6_address;
-/* Macro: True iff the IPv4 address 'addr', in host order, is in 127.0.0.0/8
- */
-#define EVUTIL_V4ADDR_IS_LOCALHOST(addr) (((addr)>>24) == 127)
+/* True iff the IPv4 address 'addr', in host order, is in 127.0.0.0/8 */
+static inline int evutil_v4addr_is_localhost(ev_uint32_t addr)
+{ return addr>>24 == 127; }
-/* Macro: True iff the IPv4 address 'addr', in host order, is a class D
- * (multiclass) address.
- */
-#define EVUTIL_V4ADDR_IS_CLASSD(addr) ((((addr)>>24) & 0xf0) == 0xe0)
+/* True iff the IPv4 address 'addr', in host order, is link-local
+ * 169.254.0.0/16 (RFC3927) */
+static inline int evutil_v4addr_is_linklocal(ev_uint32_t addr)
+{ return ((addr & 0xffff0000U) == 0xa9fe0000U); }
+
+/* True iff the IPv4 address 'addr', in host order, is a class D
+ * (multiclass) address. */
+static inline int evutil_v4addr_is_classd(ev_uint32_t addr)
+{ return ((addr>>24) & 0xf0) == 0xe0; }
+
+int
+evutil_v4addr_is_local_(const struct in_addr *in)
+{
+ const ev_uint32_t addr = ntohl(in->s_addr);
+ return addr == INADDR_ANY ||
+ evutil_v4addr_is_localhost(addr) ||
+ evutil_v4addr_is_linklocal(addr) ||
+ evutil_v4addr_is_classd(addr);
+}
+int
+evutil_v6addr_is_local_(const struct in6_addr *in)
+{
+ static const char ZEROES[] =
+ "\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00";
+
+ const unsigned char *addr = (const unsigned char *)in->s6_addr;
+ return !memcmp(addr, ZEROES, 8) ||
+ ((addr[0] & 0xfe) == 0xfc) ||
+ (addr[0] == 0xfe && (addr[1] & 0xc0) == 0x80) ||
+ (addr[0] == 0xfe && (addr[1] & 0xc0) == 0xc0) ||
+ (addr[0] == 0xff);
+}
static void
evutil_found_ifaddr(const struct sockaddr *sa)
{
- const char ZEROES[] = "\x00\x00\x00\x00\x00\x00\x00\x00"
- "\x00\x00\x00\x00\x00\x00\x00\x00";
-
if (sa->sa_family == AF_INET) {
const struct sockaddr_in *sin = (struct sockaddr_in *)sa;
- ev_uint32_t addr = ntohl(sin->sin_addr.s_addr);
- if (addr == 0 ||
- EVUTIL_V4ADDR_IS_LOCALHOST(addr) ||
- EVUTIL_V4ADDR_IS_CLASSD(addr)) {
- /* Not actually a usable external address. */
- } else {
+ if (!evutil_v4addr_is_local_(&sin->sin_addr)) {
event_debug(("Detected an IPv4 interface"));
had_ipv4_address = 1;
}
} else if (sa->sa_family == AF_INET6) {
const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
- const unsigned char *addr =
- (unsigned char*)sin6->sin6_addr.s6_addr;
- if (!memcmp(addr, ZEROES, 8) ||
- ((addr[0] & 0xfe) == 0xfc) ||
- (addr[0] == 0xfe && (addr[1] & 0xc0) == 0x80) ||
- (addr[0] == 0xfe && (addr[1] & 0xc0) == 0xc0) ||
- (addr[0] == 0xff)) {
- /* This is a reserved, ipv4compat, ipv4map, loopback,
- * link-local, multicast, or unspecified address. */
- } else {
+ if (!evutil_v6addr_is_local_(&sin6->sin6_addr)) {
event_debug(("Detected an IPv6 interface"));
had_ipv6_address = 1;
}
@@ -1053,7 +1076,7 @@ evutil_getaddrinfo_common_(const char *nodename, const char *servname,
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
if (1==evutil_inet_pton(AF_INET, nodename, &sin.sin_addr)) {
- /* Got an ipv6 address. */
+ /* Got an ipv4 address. */
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
*res = evutil_new_addrinfo_((struct sockaddr*)&sin,
@@ -2593,7 +2616,7 @@ evutil_accept4_(evutil_socket_t sockfd, struct sockaddr *addr,
}
/* Internal function: Set fd[0] and fd[1] to a pair of fds such that writes on
- * fd[0] get read from fd[1]. Make both fds nonblocking and close-on-exec.
+ * fd[1] get read from fd[0]. Make both fds nonblocking and close-on-exec.
* Return 0 on success, -1 on failure.
*/
int
diff --git a/evutil_rand.c b/evutil_rand.c
index 046a14b0..4be0b1c5 100644
--- a/evutil_rand.c
+++ b/evutil_rand.c
@@ -192,12 +192,14 @@ evutil_secure_rng_get_bytes(void *buf, size_t n)
ev_arc4random_buf(buf, n);
}
+#if !defined(EVENT__HAVE_ARC4RANDOM) || defined(EVENT__HAVE_ARC4RANDOM_ADDRANDOM)
void
evutil_secure_rng_add_bytes(const char *buf, size_t n)
{
arc4random_addrandom((unsigned char*)buf,
n>(size_t)INT_MAX ? INT_MAX : (int)n);
}
+#endif
void
evutil_free_secure_rng_globals_(void)
diff --git a/evutil_time.c b/evutil_time.c
index 00fd5fb4..c3a23589 100644
--- a/evutil_time.c
+++ b/evutil_time.c
@@ -43,7 +43,7 @@
#ifndef EVENT__HAVE_GETTIMEOFDAY
#include <sys/timeb.h>
#endif
-#if !defined(EVENT__HAVE_NANOSLEEP) && !defined(EVENT_HAVE_USLEEP) && \
+#if !defined(EVENT__HAVE_NANOSLEEP) && !defined(EVENT__HAVE_USLEEP) && \
!defined(_WIN32)
#include <sys/select.h>
#endif
@@ -141,7 +141,10 @@ evutil_usleep_(const struct timeval *tv)
sleep(tv->tv_sec);
usleep(tv->tv_usec);
#else
- select(0, NULL, NULL, NULL, tv);
+ {
+ struct timeval tv2 = *tv;
+ select(0, NULL, NULL, NULL, &tv2);
+ }
#endif
}
diff --git a/http-internal.h b/http-internal.h
index 45555171..b7d21ef9 100644
--- a/http-internal.h
+++ b/http-internal.h
@@ -184,12 +184,15 @@ int evhttp_connection_connect_(struct evhttp_connection *);
enum evhttp_request_error;
/* notifies the current request that it failed; resets connection */
+EVENT2_EXPORT_SYMBOL
void evhttp_connection_fail_(struct evhttp_connection *,
enum evhttp_request_error error);
enum message_read_status;
+EVENT2_EXPORT_SYMBOL
enum message_read_status evhttp_parse_firstline_(struct evhttp_request *, struct evbuffer*);
+EVENT2_EXPORT_SYMBOL
enum message_read_status evhttp_parse_headers_(struct evhttp_request *, struct evbuffer*);
void evhttp_start_read_(struct evhttp_connection *);
@@ -199,6 +202,7 @@ void evhttp_start_write_(struct evhttp_connection *);
void evhttp_response_code_(struct evhttp_request *, int, const char *);
void evhttp_send_page_(struct evhttp_request *, struct evbuffer *);
+EVENT2_EXPORT_SYMBOL
int evhttp_decode_uri_internal(const char *uri, size_t length,
char *ret, int decode_plus);
diff --git a/http.c b/http.c
index f5a2ef93..5bc4a24c 100644
--- a/http.c
+++ b/http.c
@@ -173,6 +173,7 @@ extern int debug;
static evutil_socket_t bind_socket_ai(struct evutil_addrinfo *, int reuse);
static evutil_socket_t bind_socket(const char *, ev_uint16_t, int reuse);
static void name_from_addr(struct sockaddr *, ev_socklen_t, char **, char **);
+static struct evhttp_uri *evhttp_uri_parse_authority(char *source_uri);
static int evhttp_associate_new_request_with_connection(
struct evhttp_connection *evcon);
static void evhttp_connection_start_detectclose(
@@ -368,15 +369,15 @@ evhttp_write_buffer(struct evhttp_connection *evcon,
evcon->cb_arg = arg;
/* Disable the read callback: we don't actually care about data;
- * we only care about close detection. (We don't disable reading,
- * since we *do* want to learn about any close events.) */
+ * we only care about close detection. (We don't disable reading --
+ * EV_READ, since we *do* want to learn about any close events.) */
bufferevent_setcb(evcon->bufev,
NULL, /*read*/
evhttp_write_cb,
evhttp_error_cb,
evcon);
- bufferevent_enable(evcon->bufev, EV_WRITE);
+ bufferevent_enable(evcon->bufev, EV_READ|EV_WRITE);
}
static void
@@ -1170,7 +1171,9 @@ static void
evhttp_deferred_read_cb(struct event_callback *cb, void *data)
{
struct evhttp_connection *evcon = data;
- evhttp_read_cb(evcon->bufev, evcon);
+ struct bufferevent *bev = evcon->bufev;
+ if (bev->readcb)
+ (bev->readcb)(evcon->bufev, evcon);
}
static void
@@ -1202,6 +1205,7 @@ void
evhttp_connection_free(struct evhttp_connection *evcon)
{
struct evhttp_request *req;
+ int need_close = 0;
/* notify interested parties that this connection is going down */
if (evcon->fd != -1) {
@@ -1228,21 +1232,22 @@ evhttp_connection_free(struct evhttp_connection *evcon)
event_debug_unassign(&evcon->retry_ev);
}
- if (evcon->bufev != NULL)
- bufferevent_free(evcon->bufev);
-
event_deferred_cb_cancel_(get_deferred_queue(evcon),
&evcon->read_more_deferred_cb);
- if (evcon->fd == -1)
- evcon->fd = bufferevent_getfd(evcon->bufev);
+ if (evcon->bufev != NULL) {
+ need_close =
+ !(bufferevent_get_options_(evcon->bufev) & BEV_OPT_CLOSE_ON_FREE);
+ if (evcon->fd == -1)
+ evcon->fd = bufferevent_getfd(evcon->bufev);
+
+ bufferevent_free(evcon->bufev);
+ }
if (evcon->fd != -1) {
- bufferevent_disable(evcon->bufev, EV_READ|EV_WRITE);
shutdown(evcon->fd, EVUTIL_SHUT_WR);
- if (!(bufferevent_get_options_(evcon->bufev) & BEV_OPT_CLOSE_ON_FREE)) {
+ if (need_close)
evutil_closesocket(evcon->fd);
- }
}
if (evcon->bind_address != NULL)
@@ -1287,6 +1292,8 @@ evhttp_request_dispatch(struct evhttp_connection* evcon)
if (req == NULL)
return;
+ EVUTIL_ASSERT(req->kind == EVHTTP_REQUEST);
+
/* delete possible close detection events */
evhttp_connection_stop_detectclose(evcon);
@@ -1309,6 +1316,8 @@ evhttp_connection_reset_(struct evhttp_connection *evcon)
struct evbuffer *tmp;
int err;
+ bufferevent_setcb(evcon->bufev, NULL, NULL, NULL, NULL);
+
/* XXXX This is not actually an optimal fix. Instead we ought to have
an API for "stop connecting", or use bufferevent_setfd to turn off
connecting. But for Libevent 2.0, this seems like a minimal change
@@ -1334,7 +1343,8 @@ evhttp_connection_reset_(struct evhttp_connection *evcon)
evutil_closesocket(evcon->fd);
evcon->fd = -1;
}
- bufferevent_setfd(evcon->bufev, -1);
+ err = bufferevent_setfd(evcon->bufev, -1);
+ EVUTIL_ASSERT(!err && "setfd");
/* we need to clean up any buffered data */
tmp = bufferevent_get_output(evcon->bufev);
@@ -1353,7 +1363,6 @@ static void
evhttp_connection_start_detectclose(struct evhttp_connection *evcon)
{
evcon->flags |= EVHTTP_CON_CLOSEDETECT;
-
bufferevent_enable(evcon->bufev, EV_READ);
}
@@ -1361,7 +1370,6 @@ static void
evhttp_connection_stop_detectclose(struct evhttp_connection *evcon)
{
evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
-
bufferevent_disable(evcon->bufev, EV_READ);
}
@@ -1526,6 +1534,14 @@ evhttp_error_cb(struct bufferevent *bufev, short what, void *arg)
return;
}
+ if (what & BEV_EVENT_READING &&
+ evcon->flags & EVHTTP_CON_READ_ON_WRITE_ERROR &&
+ evbuffer_get_length(bufferevent_get_input(bufev))) {
+ event_deferred_cb_schedule_(get_deferred_queue(evcon),
+ &evcon->read_more_deferred_cb);
+ return;
+ }
+
evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
} else if (what == BEV_EVENT_CONNECTED) {
} else {
@@ -1683,8 +1699,9 @@ evhttp_parse_response_line(struct evhttp_request *req, char *line)
/* Parse the first line of a HTTP request */
static int
-evhttp_parse_request_line(struct evhttp_request *req, char *line)
+evhttp_parse_request_line(struct evhttp_request *req, char *line, size_t len)
{
+ char *eos = line + len;
char *method;
char *uri;
char *version;
@@ -1693,16 +1710,24 @@ evhttp_parse_request_line(struct evhttp_request *req, char *line)
size_t method_len;
enum evhttp_cmd_type type;
+ while (eos > line && *(eos-1) == ' ') {
+ *(eos-1) = '\0';
+ --eos;
+ --len;
+ }
+ if (len < strlen("GET / HTTP/1.0"))
+ return -1;
+
/* Parse the request line */
method = strsep(&line, " ");
- if (line == NULL)
- return (-1);
- uri = strsep(&line, " ");
- if (line == NULL)
- return (-1);
- version = strsep(&line, " ");
- if (line != NULL)
- return (-1);
+ if (!line)
+ return -1;
+ uri = line;
+ version = strrchr(uri, ' ');
+ if (!version || uri == version)
+ return -1;
+ *version = '\0';
+ version++;
method_len = (uri - method) - 1;
type = EVHTTP_REQ_UNKNOWN_;
@@ -1822,16 +1847,22 @@ evhttp_parse_request_line(struct evhttp_request *req, char *line)
req->type = type;
if (evhttp_parse_http_version(version, req) < 0)
- return (-1);
+ return -1;
if ((req->uri = mm_strdup(uri)) == NULL) {
event_debug(("%s: mm_strdup", __func__));
- return (-1);
+ return -1;
}
- if ((req->uri_elems = evhttp_uri_parse_with_flags(req->uri,
- EVHTTP_URI_NONCONFORMANT)) == NULL) {
- return -1;
+ if (type == EVHTTP_REQ_CONNECT) {
+ if ((req->uri_elems = evhttp_uri_parse_authority(req->uri)) == NULL) {
+ return -1;
+ }
+ } else {
+ if ((req->uri_elems = evhttp_uri_parse_with_flags(req->uri,
+ EVHTTP_URI_NONCONFORMANT)) == NULL) {
+ return -1;
+ }
}
/* If we have an absolute-URI, check to see if it is an http request
@@ -1845,7 +1876,7 @@ evhttp_parse_request_line(struct evhttp_request *req, char *line)
!evhttp_find_vhost(req->evcon->http_server, NULL, hostname))
req->flags |= EVHTTP_PROXY_REQUEST;
- return (0);
+ return 0;
}
const char *
@@ -1980,9 +2011,9 @@ evhttp_parse_firstline_(struct evhttp_request *req, struct evbuffer *buffer)
char *line;
enum message_read_status status = ALL_DATA_READ;
- size_t line_length;
+ size_t len;
/* XXX try */
- line = evbuffer_readln(buffer, &line_length, EVBUFFER_EOL_CRLF);
+ line = evbuffer_readln(buffer, &len, EVBUFFER_EOL_CRLF);
if (line == NULL) {
if (req->evcon != NULL &&
evbuffer_get_length(buffer) > req->evcon->max_headers_size)
@@ -1991,17 +2022,16 @@ evhttp_parse_firstline_(struct evhttp_request *req, struct evbuffer *buffer)
return (MORE_DATA_EXPECTED);
}
- if (req->evcon != NULL &&
- line_length > req->evcon->max_headers_size) {
+ if (req->evcon != NULL && len > req->evcon->max_headers_size) {
mm_free(line);
return (DATA_TOO_LONG);
}
- req->headers_size = line_length;
+ req->headers_size = len;
switch (req->kind) {
case EVHTTP_REQUEST:
- if (evhttp_parse_request_line(req, line) == -1)
+ if (evhttp_parse_request_line(req, line, len) == -1)
status = DATA_CORRUPTED;
break;
case EVHTTP_RESPONSE:
@@ -2054,12 +2084,12 @@ evhttp_parse_headers_(struct evhttp_request *req, struct evbuffer* buffer)
enum message_read_status status = MORE_DATA_EXPECTED;
struct evkeyvalq* headers = req->input_headers;
- size_t line_length;
- while ((line = evbuffer_readln(buffer, &line_length, EVBUFFER_EOL_CRLF))
+ size_t len;
+ while ((line = evbuffer_readln(buffer, &len, EVBUFFER_EOL_CRLF))
!= NULL) {
char *skey, *svalue;
- req->headers_size += line_length;
+ req->headers_size += len;
if (req->evcon != NULL &&
req->headers_size > req->evcon->max_headers_size) {
@@ -2123,11 +2153,7 @@ evhttp_get_body_length(struct evhttp_request *req)
req->ntoread = -1;
else if (content_length == NULL &&
evutil_ascii_strcasecmp(connection, "Close") != 0) {
- /* Bad combination, we don't know when it will end */
- event_warnx("%s: we got no content length, but the "
- "server wants to keep the connection open: %s.",
- __func__, connection);
- return (-1);
+ req->ntoread = 0;
} else if (content_length == NULL) {
req->ntoread = -1;
} else {
@@ -2155,16 +2181,15 @@ evhttp_method_may_have_body(enum evhttp_cmd_type type)
case EVHTTP_REQ_POST:
case EVHTTP_REQ_PUT:
case EVHTTP_REQ_PATCH:
- return 1;
- case EVHTTP_REQ_TRACE:
- return 0;
- /* XXX May any of the below methods have a body? */
+
case EVHTTP_REQ_GET:
- case EVHTTP_REQ_HEAD:
case EVHTTP_REQ_DELETE:
case EVHTTP_REQ_OPTIONS:
case EVHTTP_REQ_CONNECT:
- return 0;
+ return 1;
+
+ case EVHTTP_REQ_TRACE:
+ case EVHTTP_REQ_HEAD:
default:
return 0;
}
@@ -2544,9 +2569,11 @@ evhttp_connection_connect_(struct evhttp_connection *evcon)
return (-1);
}
- bufferevent_setfd(evcon->bufev, evcon->fd);
+ if (bufferevent_setfd(evcon->bufev, evcon->fd))
+ return (-1);
} else {
- bufferevent_setfd(evcon->bufev, -1);
+ if (bufferevent_setfd(evcon->bufev, -1))
+ return (-1);
}
/* Set up a callback for successful connection setup */
@@ -2562,7 +2589,8 @@ evhttp_connection_connect_(struct evhttp_connection *evcon)
bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
}
/* make sure that we get a write callback */
- bufferevent_enable(evcon->bufev, EV_WRITE);
+ if (bufferevent_enable(evcon->bufev, EV_WRITE))
+ return (-1);
evcon->state = EVCON_CONNECTING;
@@ -2628,6 +2656,10 @@ evhttp_make_request(struct evhttp_connection *evcon,
TAILQ_INSERT_TAIL(&evcon->requests, req, next);
+ /* We do not want to conflict with retry_ev */
+ if (evcon->retry_cnt)
+ return (0);
+
/* If the connection object is not connected; make it so */
if (!evhttp_connected(evcon)) {
int res = evhttp_connection_connect_(evcon);
@@ -2638,7 +2670,7 @@ evhttp_make_request(struct evhttp_connection *evcon,
if (res != 0)
TAILQ_REMOVE(&evcon->requests, req, next);
- return res;
+ return (res);
}
/*
@@ -2820,6 +2852,10 @@ evhttp_send_reply_start(struct evhttp_request *req, int code,
const char *reason)
{
evhttp_response_code_(req, code, reason);
+
+ if (req->evcon == NULL)
+ return;
+
if (evhttp_find_header(req->output_headers, "Content-Length") == NULL &&
REQ_VERSION_ATLEAST(req, 1, 1) &&
evhttp_response_needs_body(req)) {
@@ -3059,16 +3095,15 @@ evhttp_uriencode(const char *uri, ev_ssize_t len, int space_as_plus)
{
struct evbuffer *buf = evbuffer_new();
const char *p, *end;
- char *result;
+ char *result = NULL;
- if (buf == NULL) {
- return (NULL);
+ if (!buf) {
+ goto out;
}
-
if (len >= 0) {
if (uri + len < uri) {
- return (NULL);
+ goto out;
}
end = uri + len;
@@ -3077,11 +3112,11 @@ evhttp_uriencode(const char *uri, ev_ssize_t len, int space_as_plus)
if (slen >= EV_SSIZE_MAX) {
/* we don't want to mix signed and unsigned */
- return (NULL);
+ goto out;
}
if (uri + slen < uri) {
- return (NULL);
+ goto out;
}
end = uri + slen;
@@ -3103,9 +3138,10 @@ evhttp_uriencode(const char *uri, ev_ssize_t len, int space_as_plus)
if (result)
evbuffer_remove(buf, result, evbuffer_get_length(buf));
- evbuffer_free(buf);
-
- return (result);
+out:
+ if (buf)
+ evbuffer_free(buf);
+ return result;
}
char *
@@ -3416,6 +3452,8 @@ evhttp_handle_request(struct evhttp_request *req, void *arg)
/* we have a new request on which the user needs to take action */
req->userdone = 0;
+ bufferevent_disable(req->evcon->bufev, EV_READ);
+
if (req->type == 0 || req->uri == NULL) {
evhttp_send_error(req, req->response_code, NULL);
return;
@@ -3503,13 +3541,16 @@ evhttp_bind_socket_with_handle(struct evhttp *http, const char *address, ev_uint
{
evutil_socket_t fd;
struct evhttp_bound_socket *bound;
+ int serrno;
if ((fd = bind_socket(address, port, 1 /*reuse*/)) == -1)
return (NULL);
if (listen(fd, 128) == -1) {
+ serrno = EVUTIL_SOCKET_ERROR();
event_sock_warn(fd, "%s: listen", __func__);
evutil_closesocket(fd);
+ EVUTIL_SET_SOCKET_ERROR(serrno);
return (NULL);
}
@@ -4200,11 +4241,19 @@ evhttp_get_request_connection(
evcon->fd = fd;
- bufferevent_enable(evcon->bufev, EV_READ);
- bufferevent_disable(evcon->bufev, EV_WRITE);
- bufferevent_setfd(evcon->bufev, fd);
+ if (bufferevent_setfd(evcon->bufev, fd))
+ goto err;
+ if (bufferevent_enable(evcon->bufev, EV_READ))
+ goto err;
+ if (bufferevent_disable(evcon->bufev, EV_WRITE))
+ goto err;
+ bufferevent_socket_set_conn_address_(evcon->bufev, sa, salen);
return (evcon);
+
+err:
+ evhttp_connection_free(evcon);
+ return (NULL);
}
static int
@@ -4821,6 +4870,36 @@ err:
return NULL;
}
+static struct evhttp_uri *
+evhttp_uri_parse_authority(char *source_uri)
+{
+ struct evhttp_uri *uri = mm_calloc(1, sizeof(struct evhttp_uri));
+ char *end;
+
+ if (uri == NULL) {
+ event_warn("%s: calloc", __func__);
+ goto err;
+ }
+ uri->port = -1;
+ uri->flags = 0;
+
+ end = end_of_authority(source_uri);
+ if (parse_authority(uri, source_uri, end) < 0)
+ goto err;
+
+ uri->path = mm_strdup("");
+ if (uri->path == NULL) {
+ event_warn("%s: strdup", __func__);
+ goto err;
+ }
+
+ return uri;
+err:
+ if (uri)
+ evhttp_uri_free(uri);
+ return NULL;
+}
+
void
evhttp_uri_free(struct evhttp_uri *uri)
{
diff --git a/include/event2/bufferevent.h b/include/event2/bufferevent.h
index 825918e3..dac34dc7 100644
--- a/include/event2/bufferevent.h
+++ b/include/event2/bufferevent.h
@@ -518,6 +518,9 @@ int bufferevent_set_timeouts(struct bufferevent *bufev,
On input, a bufferevent does not invoke the user read callback unless
there is at least low watermark data in the buffer. If the read buffer
is beyond the high watermark, the bufferevent stops reading from the network.
+ But be aware that bufferevent input/read buffer can overrun high watermark
+ limit (typical example is openssl bufferevent), so you should not relay in
+ this.
On output, the user write callback is invoked whenever the buffered data
falls below the low watermark. Filters that write to this bufev will try
diff --git a/include/event2/bufferevent_compat.h b/include/event2/bufferevent_compat.h
index 65482042..a5a3c720 100644
--- a/include/event2/bufferevent_compat.h
+++ b/include/event2/bufferevent_compat.h
@@ -28,6 +28,8 @@
#ifndef EVENT2_BUFFEREVENT_COMPAT_H_INCLUDED_
#define EVENT2_BUFFEREVENT_COMPAT_H_INCLUDED_
+#include <event2/visibility.h>
+
#define evbuffercb bufferevent_data_cb
#define everrorcb bufferevent_event_cb
@@ -72,6 +74,7 @@
error occurred
@see bufferevent_base_set(), bufferevent_free()
*/
+EVENT2_EXPORT_SYMBOL
struct bufferevent *bufferevent_new(evutil_socket_t fd,
evbuffercb readcb, evbuffercb writecb, everrorcb errorcb, void *cbarg);
@@ -83,6 +86,7 @@ struct bufferevent *bufferevent_new(evutil_socket_t fd,
@param timeout_read the read timeout
@param timeout_write the write timeout
*/
+EVENT2_EXPORT_SYMBOL
void bufferevent_settimeout(struct bufferevent *bufev,
int timeout_read, int timeout_write);
diff --git a/include/event2/dns.h b/include/event2/dns.h
index 17cd86a2..902544c2 100644
--- a/include/event2/dns.h
+++ b/include/event2/dns.h
@@ -478,6 +478,7 @@ int evdns_base_resolv_conf_parse(struct evdns_base *base, int flags, const char
EVENT2_EXPORT_SYMBOL
int evdns_base_load_hosts(struct evdns_base *base, const char *hosts_fname);
+#if defined(EVENT_IN_DOXYGEN_) || defined(_WIN32)
/**
Obtain nameserver information using the Windows API.
@@ -488,7 +489,6 @@ int evdns_base_load_hosts(struct evdns_base *base, const char *hosts_fname);
@return 0 if successful, or -1 if an error occurred
@see evdns_resolv_conf_parse()
*/
-#ifdef _WIN32
EVENT2_EXPORT_SYMBOL
int evdns_base_config_windows_nameservers(struct evdns_base *);
#define EVDNS_BASE_CONFIG_WINDOWS_NAMESERVERS_IMPLEMENTED
@@ -615,7 +615,8 @@ typedef void (*evdns_request_callback_fn_type)(struct evdns_server_request *, vo
@param callback A function to invoke whenever we get a DNS request
on the socket.
@param user_data Data to pass to the callback.
- @return an evdns_server_port structure for this server port.
+ @return an evdns_server_port structure for this server port or NULL if
+ an error occurred.
*/
EVENT2_EXPORT_SYMBOL
struct evdns_server_port *evdns_add_server_port_with_base(struct event_base *base, evutil_socket_t socket, int flags, evdns_request_callback_fn_type callback, void *user_data);
diff --git a/include/event2/dns_compat.h b/include/event2/dns_compat.h
index 965fd654..a58c4b29 100644
--- a/include/event2/dns_compat.h
+++ b/include/event2/dns_compat.h
@@ -49,6 +49,7 @@ extern "C" {
/* For int types. */
#include <event2/util.h>
+#include <event2/visibility.h>
/**
Initialize the asynchronous DNS library.
@@ -66,6 +67,7 @@ extern "C" {
@return 0 if successful, or -1 if an error occurred
@see evdns_shutdown()
*/
+EVENT2_EXPORT_SYMBOL
int evdns_init(void);
struct evdns_base;
@@ -76,6 +78,7 @@ struct evdns_base;
@deprecated This function is deprecated because use of the global
evdns_base is error-prone.
*/
+EVENT2_EXPORT_SYMBOL
struct evdns_base *evdns_get_global_base(void);
/**
@@ -93,6 +96,7 @@ struct evdns_base *evdns_get_global_base(void);
active requests will return DNS_ERR_SHUTDOWN.
@see evdns_init()
*/
+EVENT2_EXPORT_SYMBOL
void evdns_shutdown(int fail_requests);
/**
@@ -109,6 +113,7 @@ void evdns_shutdown(int fail_requests);
@return 0 if successful, or -1 if an error occurred
@see evdns_nameserver_ip_add()
*/
+EVENT2_EXPORT_SYMBOL
int evdns_nameserver_add(unsigned long int address);
/**
@@ -126,6 +131,7 @@ int evdns_nameserver_add(unsigned long int address);
@return the number of configured nameservers
@see evdns_nameserver_add()
*/
+EVENT2_EXPORT_SYMBOL
int evdns_count_nameservers(void);
/**
@@ -140,6 +146,7 @@ int evdns_count_nameservers(void);
@return 0 if successful, or -1 if an error occurred
@see evdns_resume()
*/
+EVENT2_EXPORT_SYMBOL
int evdns_clear_nameservers_and_suspend(void);
/**
@@ -155,6 +162,7 @@ int evdns_clear_nameservers_and_suspend(void);
@return 0 if successful, or -1 if an error occurred
@see evdns_clear_nameservers_and_suspend()
*/
+EVENT2_EXPORT_SYMBOL
int evdns_resume(void);
/**
@@ -170,6 +178,7 @@ int evdns_resume(void);
@return 0 if successful, or -1 if an error occurred
@see evdns_nameserver_add()
*/
+EVENT2_EXPORT_SYMBOL
int evdns_nameserver_ip_add(const char *ip_as_string);
/**
@@ -186,6 +195,7 @@ int evdns_nameserver_ip_add(const char *ip_as_string);
@return 0 if successful, or -1 if an error occurred
@see evdns_resolve_ipv6(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6()
*/
+EVENT2_EXPORT_SYMBOL
int evdns_resolve_ipv4(const char *name, int flags, evdns_callback_type callback, void *ptr);
/**
@@ -198,6 +208,7 @@ int evdns_resolve_ipv4(const char *name, int flags, evdns_callback_type callback
@return 0 if successful, or -1 if an error occurred
@see evdns_resolve_ipv4(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6()
*/
+EVENT2_EXPORT_SYMBOL
int evdns_resolve_ipv6(const char *name, int flags, evdns_callback_type callback, void *ptr);
struct in_addr;
@@ -217,6 +228,7 @@ struct in6_addr;
@return 0 if successful, or -1 if an error occurred
@see evdns_resolve_reverse_ipv6()
*/
+EVENT2_EXPORT_SYMBOL
int evdns_resolve_reverse(const struct in_addr *in, int flags, evdns_callback_type callback, void *ptr);
/**
@@ -233,6 +245,7 @@ int evdns_resolve_reverse(const struct in_addr *in, int flags, evdns_callback_ty
@return 0 if successful, or -1 if an error occurred
@see evdns_resolve_reverse_ipv6()
*/
+EVENT2_EXPORT_SYMBOL
int evdns_resolve_reverse_ipv6(const struct in6_addr *in, int flags, evdns_callback_type callback, void *ptr);
/**
@@ -251,6 +264,7 @@ int evdns_resolve_reverse_ipv6(const struct in6_addr *in, int flags, evdns_callb
@param flags Ignored.
@return 0 if successful, or -1 if an error occurred
*/
+EVENT2_EXPORT_SYMBOL
int evdns_set_option(const char *option, const char *val, int flags);
/**
@@ -278,6 +292,7 @@ int evdns_set_option(const char *option, const char *val, int flags);
occurred (see above)
@see resolv.conf(3), evdns_config_windows_nameservers()
*/
+EVENT2_EXPORT_SYMBOL
int evdns_resolv_conf_parse(int flags, const char *const filename);
/**
@@ -287,6 +302,7 @@ int evdns_resolv_conf_parse(int flags, const char *const filename);
caller to specify which evdns_base it applies to. The recommended
function is evdns_base_search_clear().
*/
+EVENT2_EXPORT_SYMBOL
void evdns_search_clear(void);
/**
@@ -298,6 +314,7 @@ void evdns_search_clear(void);
@param domain the domain to be added to the search list
*/
+EVENT2_EXPORT_SYMBOL
void evdns_search_add(const char *domain);
/**
@@ -312,6 +329,7 @@ void evdns_search_add(const char *domain);
@param ndots the new ndots parameter
*/
+EVENT2_EXPORT_SYMBOL
void evdns_search_ndots_set(const int ndots);
/**
@@ -322,9 +340,13 @@ void evdns_search_ndots_set(const int ndots);
function is evdns_add_server_port_with_base().
*/
-struct evdns_server_port *evdns_add_server_port(evutil_socket_t socket, int flags, evdns_request_callback_fn_type callback, void *user_data);
+EVENT2_EXPORT_SYMBOL
+struct evdns_server_port *
+evdns_add_server_port(evutil_socket_t socket, int flags,
+ evdns_request_callback_fn_type callback, void *user_data);
#ifdef _WIN32
+EVENT2_EXPORT_SYMBOL
int evdns_config_windows_nameservers(void);
#define EVDNS_CONFIG_WINDOWS_NAMESERVERS_IMPLEMENTED
#endif
diff --git a/include/event2/event.h b/include/event2/event.h
index 6e0a4f04..1e106f76 100644
--- a/include/event2/event.h
+++ b/include/event2/event.h
@@ -232,7 +232,7 @@ struct event_base
*
* Generally, you can create events with event_new(), then make them
* pending with event_add(). As your event_base runs, it will run the
- * callbacks of an events whose conditions are triggered. When you
+ * callbacks of an events whose conditions are triggered. When you no
* longer want the event, free it with event_free().
*
* In more depth:
@@ -285,7 +285,7 @@ struct event
* There are many options that can be used to alter the behavior and
* implementation of an event_base. To avoid having to pass them all in a
* complex many-argument constructor, we provide an abstract data type
- * wrhere you set up configation information before passing it to
+ * where you set up configation information before passing it to
* event_base_new_with_config().
*
* @see event_config_new(), event_config_free(), event_base_new_with_config(),
@@ -692,7 +692,7 @@ EVENT2_EXPORT_SYMBOL
void event_base_free(struct event_base *);
/**
- As event_free, but do not run finalizers.
+ As event_base_free, but do not run finalizers.
THIS IS AN EXPERIMENTAL API. IT MIGHT CHANGE BEFORE THE LIBEVENT 2.1 SERIES
BECOMES STABLE.
@@ -963,11 +963,13 @@ int event_base_got_break(struct event_base *);
/**
@name evtimer_* macros
- Aliases for working with one-shot timer events */
+ Aliases for working with one-shot timer events
+ If you need EV_PERSIST timer use event_*() functions.
+ */
/**@{*/
#define evtimer_assign(ev, b, cb, arg) \
event_assign((ev), (b), -1, 0, (cb), (arg))
-#define evtimer_new(b, cb, arg) event_new((b), -1, 0, (cb), (arg))
+#define evtimer_new(b, cb, arg) event_new((b), -1, 0, (cb), (arg))
#define evtimer_add(ev, tv) event_add((ev), (tv))
#define evtimer_del(ev) event_del(ev)
#define evtimer_pending(ev, tv) event_pending((ev), EV_TIMEOUT, (tv))
@@ -991,6 +993,20 @@ int event_base_got_break(struct event_base *);
/**@}*/
/**
+ @name evuser_* macros
+
+ Aliases for working with user-triggered events
+ If you need EV_PERSIST event use event_*() functions.
+ */
+/**@{*/
+#define evuser_new(b, cb, arg) event_new((b), -1, 0, (cb), (arg))
+#define evuser_del(ev) event_del(ev)
+#define evuser_pending(ev, tv) event_pending((ev), 0, (tv))
+#define evuser_initialized(ev) event_initialized(ev)
+#define evuser_trigger(ev) event_active((ev), 0, 0)
+/**@}*/
+
+/**
A callback function for an event.
It receives three arguments:
@@ -1029,7 +1045,7 @@ EVENT2_EXPORT_SYMBOL
void *event_self_cbarg(void);
/**
- Allocate and asssign a new event structure, ready to be added.
+ Allocate and assign a new event structure, ready to be added.
The function event_new() returns a new event that can be used in
future calls to event_add() and event_del(). The fd and events
@@ -1055,10 +1071,10 @@ void *event_self_cbarg(void);
The EV_TIMEOUT flag has no effect here.
It is okay to have multiple events all listening on the same fds; but
- they must either all be edge-triggered, or all not be edge triggerd.
+ they must either all be edge-triggered, or all not be edge triggered.
When the event becomes active, the event loop will run the provided
- callbuck function, with three arguments. The first will be the provided
+ callback function, with three arguments. The first will be the provided
fd value. The second will be a bitfield of the events that triggered:
EV_READ, EV_WRITE, or EV_SIGNAL. Here the EV_TIMEOUT flag indicates
that a timeout occurred, and EV_ET indicates that an edge-triggered
@@ -1073,7 +1089,7 @@ void *event_self_cbarg(void);
@param callback_arg an argument to be passed to the callback function
@return a newly allocated struct event that must later be freed with
- event_free().
+ event_free() or NULL if an error occurred.
@see event_free(), event_add(), event_del(), event_assign()
*/
EVENT2_EXPORT_SYMBOL
@@ -1124,8 +1140,8 @@ int event_assign(struct event *, struct event_base *, evutil_socket_t, short, ev
/**
Deallocate a struct event * returned by event_new().
- If the event is pending or active, first make it non-pending and
- non-active.
+ If the event is pending or active, this function makes it non-pending
+ and non-active first.
*/
EVENT2_EXPORT_SYMBOL
void event_free(struct event *);
@@ -1163,13 +1179,13 @@ typedef void (*event_finalize_callback_fn)(struct event *, void *);
event_finalize() does not.
A finalizer callback must not make events pending or active. It must not
- add events, activate events, or attempt to "resucitate" the event being
+ add events, activate events, or attempt to "resuscitate" the event being
finalized in any way.
THIS IS AN EXPERIMENTAL API. IT MIGHT CHANGE BEFORE THE LIBEVENT 2.1 SERIES
BECOMES STABLE.
- @return 0 on succes, -1 on failure.
+ @return 0 on success, -1 on failure.
*/
/**@{*/
EVENT2_EXPORT_SYMBOL
@@ -1199,7 +1215,7 @@ int event_free_finalize(unsigned, struct event *, event_finalize_callback_fn);
@param arg an argument to be passed to the callback function
@param timeout the maximum amount of time to wait for the event. NULL
makes an EV_READ/EV_WRITE event make forever; NULL makes an
- EV_TIMEOUT event succees immediately.
+ EV_TIMEOUT event success immediately.
@return 0 if successful, or -1 if an error occurred
*/
EVENT2_EXPORT_SYMBOL
@@ -1210,7 +1226,7 @@ int event_base_once(struct event_base *, evutil_socket_t, short, event_callback_
The function event_add() schedules the execution of the event 'ev' when the
condition specified by event_assign() or event_new() occurs, or when the time
- specified in timeout has elapesed. If atimeout is NULL, no timeout
+ specified in timeout has elapsed. If a timeout is NULL, no timeout
occurs and the function will only be
called if a matching event occurs. The event in the
ev argument must be already initialized by event_assign() or event_new()
@@ -1236,7 +1252,7 @@ int event_add(struct event *ev, const struct timeval *timeout);
leaves the event otherwise pending.
@param ev an event struct initialized via event_assign() or event_new()
- @return 0 on success, or -1 if an error occurrect.
+ @return 0 on success, or -1 if an error occurred.
*/
EVENT2_EXPORT_SYMBOL
int event_remove_timer(struct event *ev);
@@ -1531,7 +1547,7 @@ const struct timeval *event_base_init_common_timeout(struct event_base *base,
Note also that if you are going to call this function, you should do so
before any call to any Libevent function that does allocation.
- Otherwise, those funtions will allocate their memory using malloc(), but
+ Otherwise, those functions will allocate their memory using malloc(), but
then later free it using your provided free_fn.
@param malloc_fn A replacement for malloc.
@@ -1627,7 +1643,7 @@ int event_base_foreach_event(struct event_base *base, event_base_foreach_event_c
cached time.
Generally, this value will only be cached while actually
- processing event callbacks, and may be very inaccuate if your
+ processing event callbacks, and may be very inaccurate if your
callbacks take a long time to execute.
Returns 0 on success, negative on failure.
diff --git a/include/event2/http.h b/include/event2/http.h
index 8fb5642f..2a41303e 100644
--- a/include/event2/http.h
+++ b/include/event2/http.h
@@ -78,7 +78,8 @@ struct evdns_base;
* Create a new HTTP server.
*
* @param base (optional) the event base to receive the HTTP events
- * @return a pointer to a newly initialized evhttp server structure
+ * @return a pointer to a newly initialized evhttp server structure or NULL
+ * on error
* @see evhttp_free()
*/
EVENT2_EXPORT_SYMBOL
@@ -516,7 +517,8 @@ enum evhttp_request_kind { EVHTTP_REQUEST, EVHTTP_RESPONSE };
* when the connection closes. It must have no fd set on it.
* @param address the address to which to connect
* @param port the port to connect to
- * @return an evhttp_connection object that can be used for making requests
+ * @return an evhttp_connection object that can be used for making requests or
+ * NULL on error
*/
EVENT2_EXPORT_SYMBOL
struct evhttp_connection *evhttp_connection_base_bufferevent_new(
@@ -636,7 +638,8 @@ void evhttp_request_free(struct evhttp_request *req);
* specified host name resolution will block.
* @param address the address to which to connect
* @param port the port to connect to
- * @return an evhttp_connection object that can be used for making requests
+ * @return an evhttp_connection object that can be used for making requests or
+ * NULL on error
*/
EVENT2_EXPORT_SYMBOL
struct evhttp_connection *evhttp_connection_base_new(
@@ -927,14 +930,14 @@ char *evhttp_uriencode(const char *str, ev_ssize_t size, int space_to_plus);
/**
Helper function to sort of decode a URI-encoded string. Unlike
- evhttp_get_decoded_uri, it decodes all plus characters that appear
+ evhttp_uridecode, it decodes all plus characters that appear
_after_ the first question mark character, but no plusses that occur
before. This is not a good way to decode URIs in whole or in part.
The returned string must be freed by the caller
@deprecated This function is deprecated; you probably want to use
- evhttp_get_decoded_uri instead.
+ evhttp_uridecode instead.
@param uri an encoded URI
@return a newly allocated unencoded URI or NULL on failure
diff --git a/include/event2/http_compat.h b/include/event2/http_compat.h
index 43c2c43e..794a5810 100644
--- a/include/event2/http_compat.h
+++ b/include/event2/http_compat.h
@@ -56,8 +56,10 @@ extern "C" {
*
* @param address the address to which the HTTP server should be bound
* @param port the port number on which the HTTP server should listen
- * @return an struct evhttp object
+ * @return a pointer to a newly initialized evhttp server structure
+ * or NULL on error
*/
+EVENT2_EXPORT_SYMBOL
struct evhttp *evhttp_start(const char *address, ev_uint16_t port);
/**
@@ -67,6 +69,7 @@ struct evhttp *evhttp_start(const char *address, ev_uint16_t port);
*
* @deprecated It does not allow an event base to be specified
*/
+EVENT2_EXPORT_SYMBOL
struct evhttp_connection *evhttp_connection_new(
const char *address, ev_uint16_t port);
@@ -76,6 +79,7 @@ struct evhttp_connection *evhttp_connection_new(
*
* @deprecated XXXX Why?
*/
+EVENT2_EXPORT_SYMBOL
void evhttp_connection_set_base(struct evhttp_connection *evcon,
struct event_base *base);
diff --git a/include/event2/listener.h b/include/event2/listener.h
index 84b4da05..789a27c2 100644
--- a/include/event2/listener.h
+++ b/include/event2/listener.h
@@ -97,6 +97,18 @@ typedef void (*evconnlistener_errorcb)(struct evconnlistener *, void *);
* This is only available on Linux and kernel 3.9+
*/
#define LEV_OPT_REUSEABLE_PORT (1u<<7)
+/** Flag: Indicates that the listener wants to work only in IPv6 socket.
+ *
+ * According to RFC3493 and most Linux distributions, default value is to
+ * work in IPv4-mapped mode. If there is a requirement to bind same port
+ * on same ip addresses but different handlers for both IPv4 and IPv6,
+ * it is required to set IPV6_V6ONLY socket option to be sure that the
+ * code works as expected without affected by bindv6only sysctl setting in
+ * system.
+ *
+ * This socket option also supported by Windows.
+ */
+#define LEV_OPT_BIND_IPV6ONLY (1u<<8)
/**
Allocate a new evconnlistener object to listen for incoming TCP connections
diff --git a/include/event2/rpc.h b/include/event2/rpc.h
index dd43df26..1bc31d57 100644
--- a/include/event2/rpc.h
+++ b/include/event2/rpc.h
@@ -27,6 +27,10 @@
#ifndef EVENT2_RPC_H_INCLUDED_
#define EVENT2_RPC_H_INCLUDED_
+/* For int types. */
+#include <event2/util.h>
+#include <event2/visibility.h>
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -178,6 +182,7 @@ EVRPC_STRUCT(rpcname) { \
struct evhttp_request* http_req; \
struct evbuffer* rpc_data; \
}; \
+EVENT2_EXPORT_SYMBOL \
int evrpc_send_request_##rpcname(struct evrpc_pool *, \
struct reqstruct *, struct rplystruct *, \
void (*)(struct evrpc_status *, \
@@ -187,6 +192,7 @@ int evrpc_send_request_##rpcname(struct evrpc_pool *, \
struct evrpc_pool;
/** use EVRPC_GENERATE instead */
+EVENT2_EXPORT_SYMBOL
struct evrpc_request_wrapper *evrpc_make_request_ctx(
struct evrpc_pool *pool, void *request, void *reply,
const char *rpcname,
@@ -257,10 +263,13 @@ struct evrpc_request_wrapper *evrpc_make_request_ctx(
#define EVRPC_REQUEST_HTTP(rpc_req) (rpc_req)->http_req
/** completes the server response to an rpc request */
+EVENT2_EXPORT_SYMBOL
void evrpc_request_done(struct evrpc_req_generic *req);
/** accessors for request and reply */
+EVENT2_EXPORT_SYMBOL
void *evrpc_get_request(struct evrpc_req_generic *req);
+EVENT2_EXPORT_SYMBOL
void *evrpc_get_reply(struct evrpc_req_generic *req);
/** Creates the reply to an RPC request
@@ -285,9 +294,10 @@ struct evhttp;
/** Creates a new rpc base from which RPC requests can be received
*
* @param server a pointer to an existing HTTP server
- * @return a newly allocated evrpc_base struct
+ * @return a newly allocated evrpc_base struct or NULL if an error occurred
* @see evrpc_free()
*/
+EVENT2_EXPORT_SYMBOL
struct evrpc_base *evrpc_init(struct evhttp *server);
/**
@@ -298,6 +308,7 @@ struct evrpc_base *evrpc_init(struct evhttp *server);
* @param base the evrpc_base object to be freed
* @see evrpc_init
*/
+EVENT2_EXPORT_SYMBOL
void evrpc_free(struct evrpc_base *base);
/** register RPCs with the HTTP Server
@@ -319,10 +330,10 @@ void evrpc_free(struct evrpc_base *base);
#define EVRPC_REGISTER(base, name, request, reply, callback, cbarg) \
evrpc_register_generic(base, #name, \
(void (*)(struct evrpc_req_generic *, void *))callback, cbarg, \
- (void *(*)(void *))request##_new, NULL, \
+ (void *(*)(void *))request##_new_with_arg, NULL, \
(void (*)(void *))request##_free, \
(int (*)(void *, struct evbuffer *))request##_unmarshal, \
- (void *(*)(void *))reply##_new, NULL, \
+ (void *(*)(void *))reply##_new_with_arg, NULL, \
(void (*)(void *))reply##_free, \
(int (*)(void *))reply##_complete, \
(void (*)(struct evbuffer *, void *))reply##_marshal)
@@ -334,6 +345,7 @@ void evrpc_free(struct evrpc_base *base);
@see EVRPC_REGISTER()
*/
+EVENT2_EXPORT_SYMBOL
int evrpc_register_rpc(struct evrpc_base *, struct evrpc *,
void (*)(struct evrpc_req_generic*, void *), void *);
@@ -347,6 +359,7 @@ int evrpc_register_rpc(struct evrpc_base *, struct evrpc *,
*/
#define EVRPC_UNREGISTER(base, name) evrpc_unregister_rpc((base), #name)
+EVENT2_EXPORT_SYMBOL
int evrpc_unregister_rpc(struct evrpc_base *base, const char *name);
/*
@@ -385,6 +398,7 @@ struct evrpc_status;
@returns 0 on success, -1 otherwise.
@see EVRPC_MAKE_REQUEST(), EVRPC_MAKE_CTX()
*/
+EVENT2_EXPORT_SYMBOL
int evrpc_make_request(struct evrpc_request_wrapper *ctx);
/** creates an rpc connection pool
@@ -394,15 +408,18 @@ int evrpc_make_request(struct evrpc_request_wrapper *ctx);
*
* @param base a pointer to an struct event_based object; can be left NULL
* in singled-threaded applications
- * @return a newly allocated struct evrpc_pool object
+ * @return a newly allocated struct evrpc_pool object or NULL if an error
+ * occurred
* @see evrpc_pool_free()
*/
+EVENT2_EXPORT_SYMBOL
struct evrpc_pool *evrpc_pool_new(struct event_base *base);
/** frees an rpc connection pool
*
* @param pool a pointer to an evrpc_pool allocated via evrpc_pool_new()
* @see evrpc_pool_new()
*/
+EVENT2_EXPORT_SYMBOL
void evrpc_pool_free(struct evrpc_pool *pool);
/**
@@ -413,6 +430,7 @@ void evrpc_pool_free(struct evrpc_pool *pool);
* @param pool the pool to which to add the connection
* @param evcon the connection to add to the pool.
*/
+EVENT2_EXPORT_SYMBOL
void evrpc_pool_add_connection(struct evrpc_pool *pool,
struct evhttp_connection *evcon);
@@ -424,6 +442,7 @@ void evrpc_pool_add_connection(struct evrpc_pool *pool,
* @param pool the pool from which to remove the connection
* @param evcon the connection to remove from the pool.
*/
+EVENT2_EXPORT_SYMBOL
void evrpc_pool_remove_connection(struct evrpc_pool *pool,
struct evhttp_connection *evcon);
@@ -442,6 +461,7 @@ void evrpc_pool_remove_connection(struct evrpc_pool *pool,
* @param timeout_in_secs the number of seconds after which a request should
* timeout and a failure be returned to the callback.
*/
+EVENT2_EXPORT_SYMBOL
void evrpc_pool_set_timeout(struct evrpc_pool *pool, int timeout_in_secs);
/**
@@ -489,6 +509,7 @@ enum EVRPC_HOOK_RESULT {
* @return a handle to the hook so it can be removed later
* @see evrpc_remove_hook()
*/
+EVENT2_EXPORT_SYMBOL
void *evrpc_add_hook(void *vbase,
enum EVRPC_HOOK_TYPE hook_type,
int (*cb)(void *, struct evhttp_request *, struct evbuffer *, void *),
@@ -502,6 +523,7 @@ void *evrpc_add_hook(void *vbase,
* @return 1 on success or 0 on failure
* @see evrpc_add_hook()
*/
+EVENT2_EXPORT_SYMBOL
int evrpc_remove_hook(void *vbase,
enum EVRPC_HOOK_TYPE hook_type,
void *handle);
@@ -511,8 +533,8 @@ int evrpc_remove_hook(void *vbase,
* @param vbase a pointer to either struct evrpc_base or struct evrpc_pool
* @param ctx the context pointer provided to the original hook call
*/
-int
-evrpc_resume_request(void *vbase, void *ctx, enum EVRPC_HOOK_RESULT res);
+EVENT2_EXPORT_SYMBOL
+int evrpc_resume_request(void *vbase, void *ctx, enum EVRPC_HOOK_RESULT res);
/** adds meta data to request
*
@@ -525,6 +547,7 @@ evrpc_resume_request(void *vbase, void *ctx, enum EVRPC_HOOK_RESULT res);
* @param data the data to be associated with the key
* @param data_size the size of the data
*/
+EVENT2_EXPORT_SYMBOL
void evrpc_hook_add_meta(void *ctx, const char *key,
const void *data, size_t data_size);
@@ -538,6 +561,7 @@ void evrpc_hook_add_meta(void *ctx, const char *key,
* @param data_size pointer to the size of the data
* @return 0 on success or -1 on failure
*/
+EVENT2_EXPORT_SYMBOL
int evrpc_hook_find_meta(void *ctx, const char *key,
void **data, size_t *data_size);
@@ -545,8 +569,10 @@ int evrpc_hook_find_meta(void *ctx, const char *key,
* returns the connection object associated with the request
*
* @param ctx the context provided to the hook call
- * @return a pointer to the evhttp_connection object
+ * @return a pointer to the evhttp_connection object or NULL if an error
+ * occurred
*/
+EVENT2_EXPORT_SYMBOL
struct evhttp_connection *evrpc_hook_get_connection(void *ctx);
/**
@@ -556,6 +582,7 @@ struct evhttp_connection *evrpc_hook_get_connection(void *ctx);
@see EVRPC_MAKE_REQUEST()
*/
+EVENT2_EXPORT_SYMBOL
int evrpc_send_request_generic(struct evrpc_pool *pool,
void *request, void *reply,
void (*cb)(struct evrpc_status *, void *, void *, void *),
@@ -572,8 +599,8 @@ int evrpc_send_request_generic(struct evrpc_pool *pool,
@see EVRPC_REGISTER()
*/
-int
-evrpc_register_generic(struct evrpc_base *base, const char *name,
+EVENT2_EXPORT_SYMBOL
+int evrpc_register_generic(struct evrpc_base *base, const char *name,
void (*callback)(struct evrpc_req_generic *, void *), void *cbarg,
void *(*req_new)(void *), void *req_new_arg, void (*req_free)(void *),
int (*req_unmarshal)(void *, struct evbuffer *),
@@ -582,9 +609,12 @@ evrpc_register_generic(struct evrpc_base *base, const char *name,
void (*rpl_marshal)(struct evbuffer *, void *));
/** accessors for obscure and undocumented functionality */
+EVENT2_EXPORT_SYMBOL
struct evrpc_pool* evrpc_request_get_pool(struct evrpc_request_wrapper *ctx);
+EVENT2_EXPORT_SYMBOL
void evrpc_request_set_pool(struct evrpc_request_wrapper *ctx,
struct evrpc_pool *pool);
+EVENT2_EXPORT_SYMBOL
void evrpc_request_set_cb(struct evrpc_request_wrapper *ctx,
void (*cb)(struct evrpc_status*, void *request, void *reply, void *arg),
void *cb_arg);
diff --git a/include/event2/rpc_struct.h b/include/event2/rpc_struct.h
index 8f691f49..f3cb460a 100644
--- a/include/event2/rpc_struct.h
+++ b/include/event2/rpc_struct.h
@@ -38,6 +38,16 @@ extern "C" {
*/
+/* Fix so that people don't have to run with <sys/queue.h> */
+#ifndef TAILQ_ENTRY
+#define EVENT_DEFINED_TQENTRY_
+#define TAILQ_ENTRY(type) \
+struct { \
+ struct type *tqe_next; /* next element */ \
+ struct type **tqe_prev; /* address of previous next element */ \
+}
+#endif /* !TAILQ_ENTRY */
+
/**
* provides information about the completed RPC request.
*/
@@ -93,6 +103,10 @@ struct evrpc {
struct evrpc_base *base;
};
+#ifdef EVENT_DEFINED_TQENTRY_
+#undef TAILQ_ENTRY
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/include/event2/util.h b/include/event2/util.h
index dd4bbb69..7c872737 100644
--- a/include/event2/util.h
+++ b/include/event2/util.h
@@ -259,6 +259,7 @@ extern "C" {
#define EV_INT32_MAX INT32_MAX
#define EV_INT32_MIN INT32_MIN
#define EV_UINT16_MAX UINT16_MAX
+#define EV_INT16_MIN INT16_MIN
#define EV_INT16_MAX INT16_MAX
#define EV_UINT8_MAX UINT8_MAX
#define EV_INT8_MAX INT8_MAX
@@ -425,6 +426,18 @@ int evutil_make_listen_socket_reuseable(evutil_socket_t sock);
EVENT2_EXPORT_SYMBOL
int evutil_make_listen_socket_reuseable_port(evutil_socket_t sock);
+/** Set ipv6 only bind socket option to make listener work only in ipv6 sockets.
+
+ According to RFC3493 and most Linux distributions, default value for the
+ sockets is to work in IPv4-mapped mode. In IPv4-mapped mode, it is not possible
+ to bind same port from different IPv4 and IPv6 handlers.
+
+ @param sock The socket to make in ipv6only working mode
+ @return 0 on success, -1 on failure
+ */
+EVENT2_EXPORT_SYMBOL
+int evutil_make_listen_socket_ipv6only(evutil_socket_t sock);
+
/** Do platform-specific operations as needed to close a socket upon a
successful execution of one of the exec*() functions.
@@ -438,7 +451,8 @@ int evutil_make_socket_closeonexec(evutil_socket_t sock);
socket() or accept().
@param sock The socket to be closed
- @return 0 on success, -1 on failure
+ @return 0 on success (whether the operation is supported or not),
+ -1 on failure
*/
EVENT2_EXPORT_SYMBOL
int evutil_closesocket(evutil_socket_t sock);
@@ -470,6 +484,7 @@ int evutil_socket_geterror(evutil_socket_t sock);
/** Convert a socket error to a string. */
EVENT2_EXPORT_SYMBOL
const char *evutil_socket_error_to_string(int errcode);
+#define EVUTIL_INVALID_SOCKET INVALID_SOCKET
#elif defined(EVENT_IN_DOXYGEN_)
/**
@name Socket error functions
@@ -493,14 +508,16 @@ const char *evutil_socket_error_to_string(int errcode);
#define evutil_socket_geterror(sock) ...
/** Convert a socket error to a string. */
#define evutil_socket_error_to_string(errcode) ...
+#define EVUTIL_INVALID_SOCKET -1
/**@}*/
-#else
+#else /** !EVENT_IN_DOXYGEN_ && !_WIN32 */
#define EVUTIL_SOCKET_ERROR() (errno)
#define EVUTIL_SET_SOCKET_ERROR(errcode) \
do { errno = (errcode); } while (0)
#define evutil_socket_geterror(sock) (errno)
#define evutil_socket_error_to_string(errcode) (strerror(errcode))
-#endif
+#define EVUTIL_INVALID_SOCKET -1
+#endif /** !_WIN32 */
/**
@@ -842,6 +859,7 @@ int evutil_secure_rng_init(void);
EVENT2_EXPORT_SYMBOL
int evutil_secure_rng_set_urandom_device_file(char *fname);
+#if !defined(EVENT__HAVE_ARC4RANDOM) || defined(EVENT__HAVE_ARC4RANDOM_ADDRANDOM)
/** Seed the random number generator with extra random bytes.
You should almost never need to call this function; it should be
@@ -858,6 +876,7 @@ int evutil_secure_rng_set_urandom_device_file(char *fname);
*/
EVENT2_EXPORT_SYMBOL
void evutil_secure_rng_add_bytes(const char *dat, size_t datlen);
+#endif
#ifdef __cplusplus
}
diff --git a/include/event2/visibility.h b/include/event2/visibility.h
index fb16dbee..006bbf06 100644
--- a/include/event2/visibility.h
+++ b/include/event2/visibility.h
@@ -29,22 +29,39 @@
#include <event2/event-config.h>
-#if defined(event_EXPORTS) || defined(event_extra_EXPORTS) || defined(event_core_EXPORTS)
+#if defined(event_shared_EXPORTS) || \
+ defined(event_extra_shared_EXPORTS) || \
+ defined(event_core_shared_EXPORTS) || \
+ defined(event_pthreads_shared_EXPORTS) || \
+ defined(event_openssl_shared_EXPORTS)
+
# if defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
# define EVENT2_EXPORT_SYMBOL __global
# elif defined __GNUC__
# define EVENT2_EXPORT_SYMBOL __attribute__ ((visibility("default")))
# elif defined(_MSC_VER)
-# define EVENT2_EXPORT_SYMBOL extern __declspec(dllexport)
+# define EVENT2_EXPORT_SYMBOL __declspec(dllexport)
# else
# define EVENT2_EXPORT_SYMBOL /* unknown compiler */
# endif
-#else
-# if defined(EVENT__NEED_DLLIMPORT) && defined(_MSC_VER) && !defined(EVENT_BUILDING_REGRESS_TEST)
-# define EVENT2_EXPORT_SYMBOL extern __declspec(dllimport)
-# else
-# define EVENT2_EXPORT_SYMBOL
+
+#else /* event_*_EXPORTS */
+
+# define EVENT2_EXPORT_SYMBOL
+
+#endif /* event_*_EXPORTS */
+
+/** We need to dllimport event_debug_logging_mask_ into event_extra */
+#if defined(_MSC_VER)
+# if defined(event_core_shared_EXPORTS) /** from core export */
+# define EVENT2_CORE_EXPORT_SYMBOL __declspec(dllexport)
+# elif defined(event_extra_shared_EXPORTS) || /** from extra import */ \
+ defined(EVENT_VISIBILITY_WANT_DLLIMPORT)
+# define EVENT2_CORE_EXPORT_SYMBOL __declspec(dllimport)
# endif
+#endif /* _MSC_VER */
+#if !defined(EVENT2_CORE_EXPORT_SYMBOL)
+# define EVENT2_CORE_EXPORT_SYMBOL EVENT2_EXPORT_SYMBOL
#endif
#endif /* EVENT2_VISIBILITY_H_INCLUDED_ */
diff --git a/iocp-internal.h b/iocp-internal.h
index 93dbe2b1..21e0e0af 100644
--- a/iocp-internal.h
+++ b/iocp-internal.h
@@ -92,6 +92,7 @@ struct event_iocp_port {
HANDLE *shutdownSemaphore;
};
+EVENT2_EXPORT_SYMBOL
const struct win32_extension_fns *event_get_win32_extension_fns_(void);
#else
/* Dummy definition so we can test-compile more things on unix. */
@@ -106,12 +107,14 @@ struct event_overlapped {
@param cb The callback that should be invoked once the IO operation has
finished.
*/
+EVENT2_EXPORT_SYMBOL
void event_overlapped_init_(struct event_overlapped *, iocp_callback cb);
/** Allocate and return a new evbuffer that supports overlapped IO on a given
socket. The socket must be associated with an IO completion port using
event_iocp_port_associate_.
*/
+EVENT2_EXPORT_SYMBOL
struct evbuffer *evbuffer_overlapped_new_(evutil_socket_t fd);
/** XXXX Document (nickm) */
@@ -131,6 +134,7 @@ void evbuffer_overlapped_set_fd_(struct evbuffer *buf, evutil_socket_t fd);
@param ol Overlapped object with associated completion callback.
@return 0 on success, -1 on error.
*/
+EVENT2_EXPORT_SYMBOL
int evbuffer_launch_read_(struct evbuffer *buf, size_t n, struct event_overlapped *ol);
/** Start writing data from the start of an evbuffer.
@@ -145,21 +149,26 @@ int evbuffer_launch_read_(struct evbuffer *buf, size_t n, struct event_overlappe
@param ol Overlapped object with associated completion callback.
@return 0 on success, -1 on error.
*/
+EVENT2_EXPORT_SYMBOL
int evbuffer_launch_write_(struct evbuffer *buf, ev_ssize_t n, struct event_overlapped *ol);
/** XXX document */
+EVENT2_EXPORT_SYMBOL
void evbuffer_commit_read_(struct evbuffer *, ev_ssize_t);
+EVENT2_EXPORT_SYMBOL
void evbuffer_commit_write_(struct evbuffer *, ev_ssize_t);
/** Create an IOCP, and launch its worker threads. Internal use only.
This interface is unstable, and will change.
*/
+EVENT2_EXPORT_SYMBOL
struct event_iocp_port *event_iocp_port_launch_(int n_cpus);
/** Associate a file descriptor with an iocp, such that overlapped IO on the
fd will happen on one of the iocp's worker threads.
*/
+EVENT2_EXPORT_SYMBOL
int event_iocp_port_associate_(struct event_iocp_port *port, evutil_socket_t fd,
ev_uintptr_t key);
@@ -169,22 +178,27 @@ int event_iocp_port_associate_(struct event_iocp_port *port, evutil_socket_t fd,
0. Otherwise, return -1. If you get a -1 return value, it is safe to call
this function again.
*/
+EVENT2_EXPORT_SYMBOL
int event_iocp_shutdown_(struct event_iocp_port *port, long waitMsec);
/* FIXME document. */
+EVENT2_EXPORT_SYMBOL
int event_iocp_activate_overlapped_(struct event_iocp_port *port,
struct event_overlapped *o,
ev_uintptr_t key, ev_uint32_t n_bytes);
struct event_base;
/* FIXME document. */
+EVENT2_EXPORT_SYMBOL
struct event_iocp_port *event_base_get_iocp_(struct event_base *base);
/* FIXME document. */
+EVENT2_EXPORT_SYMBOL
int event_base_start_iocp_(struct event_base *base, int n_cpus);
void event_base_stop_iocp_(struct event_base *base);
/* FIXME document. */
+EVENT2_EXPORT_SYMBOL
struct bufferevent *bufferevent_async_new_(struct event_base *base,
evutil_socket_t fd, int options);
diff --git a/listener.c b/listener.c
index 2862d32e..387a89e9 100644
--- a/listener.c
+++ b/listener.c
@@ -245,6 +245,11 @@ evconnlistener_new_bind(struct event_base *base, evconnlistener_cb cb,
goto err;
}
+ if (flags & LEV_OPT_BIND_IPV6ONLY) {
+ if (evutil_make_listen_socket_ipv6only(fd) < 0)
+ goto err;
+ }
+
if (sa) {
if (bind(fd, sa, socklen)<0)
goto err;
@@ -421,11 +426,14 @@ listener_read_cb(evutil_socket_t fd, short what, void *p)
if (lev->refcnt == 1) {
int freed = listener_decref_and_unlock(lev);
EVUTIL_ASSERT(freed);
-
- evutil_closesocket(new_fd);
return;
}
--lev->refcnt;
+ if (!lev->enabled) {
+ /* the callback could have disabled the listener */
+ UNLOCK(lev);
+ return;
+ }
}
err = evutil_socket_geterror(fd);
if (EVUTIL_ERR_ACCEPT_RETRIABLE(err)) {
@@ -504,7 +512,7 @@ new_accepting_socket(struct evconnlistener_iocp *lev, int family)
return NULL;
event_overlapped_init_(&res->overlapped, accepted_socket_cb);
- res->s = INVALID_SOCKET;
+ res->s = EVUTIL_INVALID_SOCKET;
res->lev = lev;
res->buflen = buflen;
res->family = family;
@@ -522,7 +530,7 @@ static void
free_and_unlock_accepting_socket(struct accepting_socket *as)
{
/* requires lock. */
- if (as->s != INVALID_SOCKET)
+ if (as->s != EVUTIL_INVALID_SOCKET)
closesocket(as->s);
LeaveCriticalSection(&as->lock);
@@ -542,7 +550,7 @@ start_accepting(struct accepting_socket *as)
if (!as->lev->base.enabled)
return 0;
- if (s == INVALID_SOCKET) {
+ if (s == EVUTIL_INVALID_SOCKET) {
error = WSAGetLastError();
goto report_err;
}
@@ -589,7 +597,7 @@ stop_accepting(struct accepting_socket *as)
{
/* requires lock. */
SOCKET s = as->s;
- as->s = INVALID_SOCKET;
+ as->s = EVUTIL_INVALID_SOCKET;
closesocket(s);
}
@@ -631,7 +639,7 @@ accepted_socket_invoke_user_cb(struct event_callback *dcb, void *arg)
&socklen_remote);
sock = as->s;
cb = lev->cb;
- as->s = INVALID_SOCKET;
+ as->s = EVUTIL_INVALID_SOCKET;
/* We need to call this so getsockname, getpeername, and
* shutdown work correctly on the accepted socket. */
@@ -679,7 +687,7 @@ accepted_socket_cb(struct event_overlapped *o, ev_uintptr_t key, ev_ssize_t n, i
free_and_unlock_accepting_socket(as);
listener_decref_and_unlock(lev);
return;
- } else if (as->s == INVALID_SOCKET) {
+ } else if (as->s == EVUTIL_INVALID_SOCKET) {
/* This is okay; we were disabled by iocp_listener_disable. */
LeaveCriticalSection(&as->lock);
} else {
@@ -717,7 +725,7 @@ iocp_listener_enable(struct evconnlistener *lev)
if (!as)
continue;
EnterCriticalSection(&as->lock);
- if (!as->free_on_cb && as->s == INVALID_SOCKET)
+ if (!as->free_on_cb && as->s == EVUTIL_INVALID_SOCKET)
start_accepting(as);
LeaveCriticalSection(&as->lock);
}
@@ -739,7 +747,7 @@ iocp_listener_disable_impl(struct evconnlistener *lev, int shutdown)
if (!as)
continue;
EnterCriticalSection(&as->lock);
- if (!as->free_on_cb && as->s != INVALID_SOCKET) {
+ if (!as->free_on_cb && as->s != EVUTIL_INVALID_SOCKET) {
if (shutdown)
as->free_on_cb = 1;
stop_accepting(as);
diff --git a/log-internal.h b/log-internal.h
index 330478a9..2c31608b 100644
--- a/log-internal.h
+++ b/log-internal.h
@@ -29,6 +29,10 @@
#include "event2/util.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#ifdef __GNUC__
#define EV_CHECK_FMT(a,b) __attribute__((format(printf, a, b)))
#define EV_NORETURN __attribute__((noreturn))
@@ -39,32 +43,35 @@
#define EVENT_ERR_ABORT_ ((int)0xdeaddead)
-#define USE_GLOBAL_FOR_DEBUG_LOGGING
-
#if !defined(EVENT__DISABLE_DEBUG_MODE) || defined(USE_DEBUG)
#define EVENT_DEBUG_LOGGING_ENABLED
#endif
#ifdef EVENT_DEBUG_LOGGING_ENABLED
-#ifdef USE_GLOBAL_FOR_DEBUG_LOGGING
-extern ev_uint32_t event_debug_logging_mask_;
+EVENT2_CORE_EXPORT_SYMBOL extern ev_uint32_t event_debug_logging_mask_;
#define event_debug_get_logging_mask_() (event_debug_logging_mask_)
#else
-ev_uint32_t event_debug_get_logging_mask_(void);
-#endif
-#else
#define event_debug_get_logging_mask_() (0)
#endif
+EVENT2_EXPORT_SYMBOL
void event_err(int eval, const char *fmt, ...) EV_CHECK_FMT(2,3) EV_NORETURN;
+EVENT2_EXPORT_SYMBOL
void event_warn(const char *fmt, ...) EV_CHECK_FMT(1,2);
+EVENT2_EXPORT_SYMBOL
void event_sock_err(int eval, evutil_socket_t sock, const char *fmt, ...) EV_CHECK_FMT(3,4) EV_NORETURN;
+EVENT2_EXPORT_SYMBOL
void event_sock_warn(evutil_socket_t sock, const char *fmt, ...) EV_CHECK_FMT(2,3);
+EVENT2_EXPORT_SYMBOL
void event_errx(int eval, const char *fmt, ...) EV_CHECK_FMT(2,3) EV_NORETURN;
+EVENT2_EXPORT_SYMBOL
void event_warnx(const char *fmt, ...) EV_CHECK_FMT(1,2);
+EVENT2_EXPORT_SYMBOL
void event_msgx(const char *fmt, ...) EV_CHECK_FMT(1,2);
+EVENT2_EXPORT_SYMBOL
void event_debugx_(const char *fmt, ...) EV_CHECK_FMT(1,2);
+EVENT2_EXPORT_SYMBOL
void event_logv_(int severity, const char *errstr, const char *fmt, va_list ap)
EV_CHECK_FMT(3,0);
@@ -80,4 +87,8 @@ void event_logv_(int severity, const char *errstr, const char *fmt, va_list ap)
#undef EV_CHECK_FMT
+#ifdef __cplusplus
+}
#endif
+
+#endif /* LOG_INTERNAL_H_INCLUDED_ */
diff --git a/log.c b/log.c
index e8ae9fdc..a9debb86 100644
--- a/log.c
+++ b/log.c
@@ -69,16 +69,7 @@ static event_fatal_cb fatal_fn = NULL;
#define DEFAULT_MASK 0
#endif
-#ifdef USE_GLOBAL_FOR_DEBUG_LOGGING
-ev_uint32_t event_debug_logging_mask_ = DEFAULT_MASK;
-#else
-static ev_uint32_t event_debug_logging_mask_ = DEFAULT_MASK;
-ev_uint32_t
-event_debug_get_logging_mask_(void)
-{
- return event_debug_logging_mask_;
-}
-#endif
+EVENT2_EXPORT_SYMBOL ev_uint32_t event_debug_logging_mask_ = DEFAULT_MASK;
#endif /* EVENT_DEBUG_LOGGING_ENABLED */
void
diff --git a/m4/libevent_openssl.m4 b/m4/libevent_openssl.m4
index c2040595..7b458134 100644
--- a/m4/libevent_openssl.m4
+++ b/m4/libevent_openssl.m4
@@ -39,6 +39,10 @@ case "$enable_openssl" in
done
;;
esac
+ CPPFLAGS_SAVE=$CPPFLAGS
+ CPPFLAGS+=$OPENSSL_INCS
+ AC_CHECK_HEADERS([openssl/ssl.h], [], [have_openssl=no])
+ CPPFLAGS=$CPPFLAGS_SAVE
AC_SUBST(OPENSSL_INCS)
AC_SUBST(OPENSSL_LIBS)
case "$have_openssl" in
diff --git a/make-event-config.sed b/make-event-config.sed
index e31018a2..3dc404b5 100644
--- a/make-event-config.sed
+++ b/make-event-config.sed
@@ -18,6 +18,10 @@ $a\
\
#endif /* event2/event-config.h */
-s/#\( *\)define /#\1define EVENT__/
-s/#\( *\)undef /#\1undef EVENT__/
-s/#\( *\)if\(n*\)def /#\1if\2def EVENT__/
+/#\( *\)undef STDC_HEADERS\>/b
+/#\( *\)define STDC_HEADERS\>/b
+
+# Only rewrite symbols starting with capitals
+s/#\( *\)define \([A-Z]\)/#\1define EVENT__\2/
+s/#\( *\)undef \([A-Z]\)/#\1undef EVENT__\2/
+s/#\( *\)if\(n*\)def \([A-Z]\)/#\1if\2def EVENT__\2/
diff --git a/mm-internal.h b/mm-internal.h
index 4ba6fce4..7a95c995 100644
--- a/mm-internal.h
+++ b/mm-internal.h
@@ -43,6 +43,7 @@ extern "C" {
* On failure, set errno to ENOMEM and return NULL.
* If the argument sz is 0, simply return NULL.
*/
+EVENT2_EXPORT_SYMBOL
void *event_mm_malloc_(size_t sz);
/** Allocate memory initialized to zero.
@@ -53,6 +54,7 @@ void *event_mm_malloc_(size_t sz);
* set errno to ENOMEM and return NULL.
* If either arguments are 0, simply return NULL.
*/
+EVENT2_EXPORT_SYMBOL
void *event_mm_calloc_(size_t count, size_t size);
/** Duplicate a string.
@@ -63,9 +65,12 @@ void *event_mm_calloc_(size_t count, size_t size);
* occurs (or would occur) in the process.
* If the argument str is NULL, set errno to EINVAL and return NULL.
*/
+EVENT2_EXPORT_SYMBOL
char *event_mm_strdup_(const char *str);
+EVENT2_EXPORT_SYMBOL
void *event_mm_realloc_(void *p, size_t sz);
+EVENT2_EXPORT_SYMBOL
void event_mm_free_(void *p);
#define mm_malloc(sz) event_mm_malloc_(sz)
#define mm_calloc(count, size) event_mm_calloc_((count), (size))
diff --git a/openssl-compat.h b/openssl-compat.h
index 69afc716..5d91ac64 100644
--- a/openssl-compat.h
+++ b/openssl-compat.h
@@ -1,7 +1,11 @@
#ifndef OPENSSL_COMPAT_H
#define OPENSSL_COMPAT_H
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#include <openssl/bio.h>
+#include "util-internal.h"
+
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
static inline BIO_METHOD *BIO_meth_new(int type, const char *name)
{
@@ -30,6 +34,11 @@ static inline BIO_METHOD *BIO_meth_new(int type, const char *name)
#define TLS_method SSLv23_method
-#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
+#endif /* (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L) */
+
+#if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x20700000L
+#define BIO_get_init(b) (b)->init
+#endif
#endif /* OPENSSL_COMPAT_H */
diff --git a/sample/dns-example.c b/sample/dns-example.c
index fb705664..21a75de8 100644
--- a/sample/dns-example.c
+++ b/sample/dns-example.c
@@ -78,6 +78,8 @@ gai_callback(int err, struct evutil_addrinfo *ai, void *arg)
{
const char *name = arg;
int i;
+ struct evutil_addrinfo *first_ai = ai;
+
if (err) {
printf("%s: %s\n", name, evutil_gai_strerror(err));
}
@@ -99,6 +101,9 @@ gai_callback(int err, struct evutil_addrinfo *ai, void *arg)
printf("[%d] %s: %s\n",i,name,buf);
}
}
+
+ if (first_ai)
+ evutil_freeaddrinfo(first_ai);
}
static void
@@ -154,19 +159,19 @@ main(int c, char **v) {
const char *ns;
};
struct options o;
- char opt;
+ int opt;
struct event_base *event_base = NULL;
struct evdns_base *evdns_base = NULL;
memset(&o, 0, sizeof(o));
-
+
if (c < 2) {
fprintf(stderr, "syntax: %s [-x] [-v] [-c resolv.conf] [-s ns] hostname\n", v[0]);
fprintf(stderr, "syntax: %s [-T]\n", v[0]);
return 1;
}
- while ((opt = getopt(c, v, "xvc:Ts:")) != -1) {
+ while ((opt = getopt(c, v, "xvc:Ts:g")) != -1) {
switch (opt) {
case 'x': o.reverse = 1; break;
case 'v': ++verbose; break;
@@ -252,6 +257,8 @@ main(int c, char **v) {
}
fflush(stdout);
event_base_dispatch(event_base);
+ evdns_base_free(evdns_base, 1);
+ event_base_free(event_base);
return 0;
}
diff --git a/sample/http-connect.c b/sample/http-connect.c
index a44d001a..af2c86a8 100644
--- a/sample/http-connect.c
+++ b/sample/http-connect.c
@@ -11,6 +11,7 @@
#define VERIFY(cond) do { \
if (!(cond)) { \
fprintf(stderr, "[error] %s\n", #cond); \
+ exit(EXIT_FAILURE); \
} \
} while (0); \
@@ -26,8 +27,11 @@ static void get_cb(struct evhttp_request *req, void *arg)
{
ev_ssize_t len;
struct evbuffer *evbuf;
+ struct evhttp_connection *evcon;
VERIFY(req);
+ evcon = evhttp_request_get_connection(req);
+ VERIFY(evcon);
evbuf = evhttp_request_get_input_buffer(req);
len = evbuffer_get_length(evbuf);
@@ -72,7 +76,7 @@ int main(int argc, const char **argv)
}
{
- proxy = evhttp_uri_parse(argv[1]);
+ VERIFY(proxy = evhttp_uri_parse(argv[1]));
VERIFY(evhttp_uri_get_host(proxy));
VERIFY(evhttp_uri_get_port(proxy) > 0);
}
diff --git a/sample/http-server.c b/sample/http-server.c
index 579feea6..75379968 100644
--- a/sample/http-server.c
+++ b/sample/http-server.c
@@ -20,6 +20,7 @@
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
+#include <getopt.h>
#include <io.h>
#include <fcntl.h>
#ifndef S_ISDIR
@@ -28,11 +29,11 @@
#else
#include <sys/stat.h>
#include <sys/socket.h>
-#include <signal.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#endif
+#include <signal.h>
#include <event2/event.h>
#include <event2/http.h>
@@ -40,6 +41,10 @@
#include <event2/util.h>
#include <event2/keyvalq_struct.h>
+#ifdef _WIN32
+#include <event2/thread.h>
+#endif
+
#ifdef EVENT__HAVE_NETINET_IN_H
#include <netinet/in.h>
# ifdef _XOPEN_SOURCE_EXTENDED
@@ -86,6 +91,13 @@ static const struct table_entry {
{ NULL, NULL },
};
+struct options
+{
+ int port;
+ int iocp;
+ int verbose;
+};
+
/* Try to guess a good content-type for 'path' */
static const char *
guess_content_type(const char *path)
@@ -320,43 +332,95 @@ done:
evbuffer_free(evb);
}
+static struct options
+parse_opts(int argc, char **argv)
+{
+ struct options o;
+ int opt;
+
+ memset(&o, 0, sizeof(o));
+
+ while ((opt = getopt(argc, argv, "p:Iv")) != -1) {
+ switch (opt) {
+ case 'p': o.port = atoi(optarg); break;
+ case 'I': o.iocp = 1; break;
+ case 'v': ++o.verbose; break;
+ default : fprintf(stderr, "Unknown option %c\n", opt); break;
+ }
+ }
+
+ if (optind >= argc || (argc-optind) > 1) {
+ fprintf(stdout, "Syntax: %s <docroot>\n", argv[0]);
+ exit(1);
+ }
+
+ return o;
+}
+
static void
-syntax(void)
+do_term(int sig, short events, void *arg)
{
- fprintf(stdout, "Syntax: http-server <docroot>\n");
+ struct event_base *base = arg;
+ event_base_loopbreak(base);
+ fprintf(stderr, "Got %i, Terminating\n", sig);
}
int
main(int argc, char **argv)
{
- struct event_base *base;
- struct evhttp *http;
- struct evhttp_bound_socket *handle;
+ struct event_config *cfg = NULL;
+ struct event_base *base = NULL;
+ struct evhttp *http = NULL;
+ struct evhttp_bound_socket *handle = NULL;
+ struct event *term = NULL;
+ struct options o = parse_opts(argc, argv);
+ int ret = 0;
- ev_uint16_t port = 0;
#ifdef _WIN32
- WSADATA WSAData;
- WSAStartup(0x101, &WSAData);
+ {
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ wVersionRequested = MAKEWORD(2, 2);
+ WSAStartup(wVersionRequested, &wsaData);
+ }
#else
- if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
- return (1);
+ if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
+ ret = 1;
+ goto err;
+ }
+#endif
+
+ setbuf(stdout, NULL);
+ setbuf(stderr, NULL);
+
+ /** Read env like in regress" */
+ if (o.verbose || getenv("EVENT_DEBUG_LOGGING_ALL"))
+ event_enable_debug_logging(EVENT_DBG_ALL);
+
+ cfg = event_config_new();
+#ifdef _WIN32
+ if (o.iocp) {
+#ifdef EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED
+ evthread_use_windows_threads();
+ event_config_set_num_cpus_hint(cfg, 8);
#endif
- if (argc < 2) {
- syntax();
- return 1;
+ event_config_set_flag(cfg, EVENT_BASE_FLAG_STARTUP_IOCP);
}
+#endif
- base = event_base_new();
+ base = event_base_new_with_config(cfg);
if (!base) {
fprintf(stderr, "Couldn't create an event_base: exiting\n");
- return 1;
+ ret = 1;
}
+ event_config_free(cfg);
+ cfg = NULL;
/* Create a new evhttp object to handle requests. */
http = evhttp_new(base);
if (!http) {
fprintf(stderr, "couldn't create evhttp. Exiting.\n");
- return 1;
+ ret = 1;
}
/* The /dump URI will dump all requests to stdout and say 200 ok. */
@@ -367,11 +431,11 @@ main(int argc, char **argv)
evhttp_set_gencb(http, send_document_cb, argv[1]);
/* Now we tell the evhttp what port to listen on */
- handle = evhttp_bind_socket_with_handle(http, "0.0.0.0", port);
+ handle = evhttp_bind_socket_with_handle(http, "0.0.0.0", o.port);
if (!handle) {
- fprintf(stderr, "couldn't bind to port %d. Exiting.\n",
- (int)port);
- return 1;
+ fprintf(stderr, "couldn't bind to port %d. Exiting.\n", o.port);
+ ret = 1;
+ goto err;
}
{
@@ -387,7 +451,7 @@ main(int argc, char **argv)
memset(&ss, 0, sizeof(ss));
if (getsockname(fd, (struct sockaddr *)&ss, &socklen)) {
perror("getsockname() failed");
- return 1;
+ ret = 1;
}
if (ss.ss_family == AF_INET) {
got_port = ntohs(((struct sockaddr_in*)&ss)->sin_port);
@@ -398,7 +462,8 @@ main(int argc, char **argv)
} else {
fprintf(stderr, "Weird address family %d\n",
ss.ss_family);
- return 1;
+ ret = 1;
+ goto err;
}
addr = evutil_inet_ntop(ss.ss_family, inaddr, addrbuf,
sizeof(addrbuf));
@@ -408,11 +473,32 @@ main(int argc, char **argv)
"http://%s:%d",addr,got_port);
} else {
fprintf(stderr, "evutil_inet_ntop failed\n");
- return 1;
+ ret = 1;
+ goto err;
}
}
+ term = evsignal_new(base, SIGINT, do_term, base);
+ if (!term)
+ goto err;
+ if (event_add(term, NULL))
+ goto err;
+
event_base_dispatch(base);
- return 0;
+#ifdef _WIN32
+ WSACleanup();
+#endif
+
+err:
+ if (cfg)
+ event_config_free(cfg);
+ if (http)
+ evhttp_free(http);
+ if (term)
+ event_free(term);
+ if (base)
+ event_base_free(base);
+
+ return ret;
}
diff --git a/sample/https-client.c b/sample/https-client.c
index 74839565..4292f094 100644
--- a/sample/https-client.c
+++ b/sample/https-client.c
@@ -191,7 +191,7 @@ main(int argc, char **argv)
struct evhttp_uri *http_uri = NULL;
const char *url = NULL, *data_file = NULL;
- const char *crt = "/etc/ssl/certs/ca-certificates.crt";
+ const char *crt = NULL;
const char *scheme, *host, *path, *query;
char uri[256];
int port;
@@ -312,7 +312,8 @@ main(int argc, char **argv)
}
uri[sizeof(uri) - 1] = '\0';
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
// Initialize OpenSSL
SSL_library_init();
ERR_load_crypto_strings();
@@ -338,11 +339,19 @@ main(int argc, char **argv)
#ifndef _WIN32
/* TODO: Add certificate loading on Windows as well */
- /* Attempt to use the system's trusted root certificates.
- * (This path is only valid for Debian-based systems.) */
- if (1 != SSL_CTX_load_verify_locations(ssl_ctx, crt, NULL)) {
- err_openssl("SSL_CTX_load_verify_locations");
- goto error;
+ if (crt == NULL) {
+ X509_STORE *store;
+ /* Attempt to use the system's trusted root certificates. */
+ store = SSL_CTX_get_cert_store(ssl_ctx);
+ if (X509_STORE_set_default_paths(store) != 1) {
+ err_openssl("X509_STORE_set_default_paths");
+ goto error;
+ }
+ } else {
+ if (SSL_CTX_load_verify_locations(ssl_ctx, crt, NULL) != 1) {
+ err_openssl("SSL_CTX_load_verify_locations");
+ goto error;
+ }
}
/* Ask OpenSSL to verify the server certificate. Note that this
* does NOT include verifying that the hostname is correct.
@@ -480,19 +489,22 @@ cleanup:
SSL_CTX_free(ssl_ctx);
if (type == HTTP && ssl)
SSL_free(ssl);
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
EVP_cleanup();
ERR_free_strings();
-#ifdef EVENT__HAVE_ERR_REMOVE_THREAD_STATE
- ERR_remove_thread_state(NULL);
-#else
+#if OPENSSL_VERSION_NUMBER < 0x10000000L
ERR_remove_state(0);
+#else
+ ERR_remove_thread_state(NULL);
#endif
+
CRYPTO_cleanup_all_ex_data();
sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
-#endif /*OPENSSL_VERSION_NUMBER < 0x10100000L */
+#endif /* (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L) */
#ifdef _WIN32
WSACleanup();
diff --git a/sample/include.am b/sample/include.am
index d1a7242f..cc003b78 100644
--- a/sample/include.am
+++ b/sample/include.am
@@ -16,16 +16,16 @@ SAMPLES = \
if OPENSSL
SAMPLES += sample/le-proxy
sample_le_proxy_SOURCES = sample/le-proxy.c
-sample_le_proxy_LDADD = libevent.la libevent_openssl.la ${OPENSSL_LIBS} ${OPENSSL_LIBADD}
-sample_le_proxy_INCLUDES = $(OPENSSL_INCS)
+sample_le_proxy_LDADD = libevent.la libevent_openssl.la $(OPENSSL_LIBS) $(OPENSSL_LIBADD)
+sample_le_proxy_CPPFLAGS = $(AM_CPPFLAGS) $(OPENSSL_INCS)
SAMPLES += sample/https-client
sample_https_client_SOURCES = \
sample/https-client.c \
sample/hostcheck.c \
sample/openssl_hostname_validation.c
-sample_https_client_LDADD = libevent.la libevent_openssl.la ${OPENSSL_LIBS} ${OPENSSL_LIBADD}
-sample_https_client_INCLUDES = $(OPENSSL_INCS)
+sample_https_client_LDADD = libevent.la libevent_openssl.la $(OPENSSL_LIBS) $(OPENSSL_LIBADD)
+sample_https_client_CPPFLAGS = $(AM_CPPFLAGS) $(OPENSSL_INCS)
noinst_HEADERS += \
sample/hostcheck.h \
sample/openssl_hostname_validation.h
diff --git a/sample/le-proxy.c b/sample/le-proxy.c
index 8d9b529e..73c48881 100644
--- a/sample/le-proxy.c
+++ b/sample/le-proxy.c
@@ -30,6 +30,7 @@
#include <event2/listener.h>
#include <event2/util.h>
+#include "util-internal.h"
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/rand.h>
@@ -194,6 +195,7 @@ accept_cb(struct evconnlistener *listener, evutil_socket_t fd,
perror("Bufferevent_openssl_new");
bufferevent_free(b_out);
bufferevent_free(b_in);
+ return;
}
b_out = b_ssl;
}
@@ -259,7 +261,8 @@ main(int argc, char **argv)
if (use_ssl) {
int r;
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
SSL_library_init();
ERR_load_crypto_strings();
SSL_load_error_strings();
diff --git a/sample/openssl_hostname_validation.c b/sample/openssl_hostname_validation.c
index 40312f2e..4036ccba 100644
--- a/sample/openssl_hostname_validation.c
+++ b/sample/openssl_hostname_validation.c
@@ -48,7 +48,8 @@ SOFTWARE.
#define HOSTNAME_MAX_SIZE 255
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
#define ASN1_STRING_get0_data ASN1_STRING_data
#endif
diff --git a/strlcpy-internal.h b/strlcpy-internal.h
index cfc27ec6..4151d601 100644
--- a/strlcpy-internal.h
+++ b/strlcpy-internal.h
@@ -6,10 +6,12 @@ extern "C" {
#endif
#include "event2/event-config.h"
+#include "event2/visibility.h"
#include "evconfig-private.h"
#ifndef EVENT__HAVE_STRLCPY
#include <string.h>
+EVENT2_EXPORT_SYMBOL
size_t event_strlcpy_(char *dst, const char *src, size_t siz);
#define strlcpy event_strlcpy_
#endif
diff --git a/test/bench.c b/test/bench.c
index 214479c1..c2c8983d 100644
--- a/test/bench.c
+++ b/test/bench.c
@@ -136,7 +136,7 @@ run_once(void)
int
main(int argc, char **argv)
{
-#ifdef HAVE_SETRLIMIT
+#ifdef EVENT__HAVE_SETRLIMIT
struct rlimit rl;
#endif
int i, c;
@@ -167,7 +167,7 @@ main(int argc, char **argv)
}
}
-#ifdef HAVE_SETRLIMIT
+#ifdef EVENT__HAVE_SETRLIMIT
rl.rlim_cur = rl.rlim_max = num_pipes * 2 + 50;
if (setrlimit(RLIMIT_NOFILE, &rl) == -1) {
perror("setrlimit");
diff --git a/test/bench_cascade.c b/test/bench_cascade.c
index 2d85cc1f..29a3203e 100644
--- a/test/bench_cascade.c
+++ b/test/bench_cascade.c
@@ -35,7 +35,8 @@
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
-#else
+#include <getopt.h>
+#else /* _WIN32 */
#include <sys/socket.h>
#include <sys/resource.h>
#endif
@@ -48,7 +49,6 @@
#include <unistd.h>
#endif
#include <errno.h>
-#include <getopt.h>
#include <event.h>
#include <evutil.h>
@@ -139,7 +139,7 @@ run_once(int num_pipes)
int
main(int argc, char **argv)
{
-#ifdef HAVE_SETRLIMIT
+#ifdef EVENT__HAVE_SETRLIMIT
struct rlimit rl;
#endif
int i, c;
@@ -162,7 +162,7 @@ main(int argc, char **argv)
}
}
-#ifdef HAVE_SETRLIMIT
+#ifdef EVENT__HAVE_SETRLIMIT
rl.rlim_cur = rl.rlim_max = num_pipes * 2 + 50;
if (setrlimit(RLIMIT_NOFILE, &rl) == -1) {
perror("setrlimit");
diff --git a/test/bench_http.c b/test/bench_http.c
index d20d3bc7..80377ee6 100644
--- a/test/bench_http.c
+++ b/test/bench_http.c
@@ -101,6 +101,9 @@ main(int argc, char **argv)
return (1);
#endif
+ setbuf(stdout, NULL);
+ setbuf(stderr, NULL);
+
for (i = 1; i < argc; ++i) {
if (*argv[i] != '-')
continue;
diff --git a/test/bench_httpclient.c b/test/bench_httpclient.c
index e1592951..7c7ee470 100644
--- a/test/bench_httpclient.c
+++ b/test/bench_httpclient.c
@@ -113,13 +113,13 @@ errorcb(struct bufferevent *b, short what, void *arg)
static void
frob_socket(evutil_socket_t sock)
{
-#ifdef HAVE_SO_LINGER
+#ifdef EVENT__HAVE_STRUCT_LINGER
struct linger l;
#endif
int one = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*)&one, sizeof(one))<0)
perror("setsockopt(SO_REUSEADDR)");
-#ifdef HAVE_SO_LINGER
+#ifdef EVENT__HAVE_STRUCT_LINGER
l.l_onoff = 1;
l.l_linger = 0;
if (setsockopt(sock, SOL_SOCKET, SO_LINGER, (void*)&l, sizeof(l))<0)
diff --git a/test/check-dumpevents.py b/test/check-dumpevents.py
index 16fe9bc9..3e1df30c 100755
--- a/test/check-dumpevents.py
+++ b/test/check-dumpevents.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python2
+#!/usr/bin/env python
#
# Post-process the output of test-dumpevents and check it for correctness.
#
@@ -15,12 +15,12 @@ try:
got_inserted_pos = text.index("Inserted events:\n")
got_active_pos = text.index("Active events:\n")
except ValueError:
- print >>sys.stderr, "Missing expected dividing line in dumpevents output"
+ sys.stderr.write("Missing expected dividing line in dumpevents output")
sys.exit(1)
if not (expect_inserted_pos < expect_active_pos <
got_inserted_pos < got_active_pos):
- print >>sys.stderr, "Sections out of order in dumpevents output"
+ sys.stderr.write("Sections out of order in dumpevents output")
sys.exit(1)
now,T= text[1].split()
@@ -45,10 +45,10 @@ cleaned_inserted = set( pat.sub(replace_time, s) for s in got_inserted
if "Internal" not in s)
if cleaned_inserted != want_inserted:
- print >>sys.stderr, "Inserted event lists were not as expected!"
+ sys.stderr.write("Inserted event lists were not as expected!")
sys.exit(1)
if set(got_active) != set(want_active):
- print >>sys.stderr, "Active event lists were not as expected!"
+ sys.stderr.write("Active event lists were not as expected!")
sys.exit(1)
diff --git a/test/include.am b/test/include.am
index eea249f8..ee2ab5ff 100644
--- a/test/include.am
+++ b/test/include.am
@@ -12,6 +12,7 @@ EXTRA_DIST+= \
test/regress.gen.h \
test/regress.rpc \
test/rpcgen_wrapper.sh \
+ test/print-winsock-errors.c \
test/test.sh
TESTPROGRAMS = \
@@ -56,26 +57,26 @@ TESTS = \
LOG_COMPILER = true
TESTS_COMPILER = true
-test_runner_epoll: test/test.sh
- test/test.sh -b EPOLL
-test_runner_select: test/test.sh
- test/test.sh -b SELECT
-test_runner_kqueue: test/test.sh
- test/test.sh -b KQUEUE
-test_runner_evport: test/test.sh
- test/test.sh -b EVPORT
-test_runner_devpoll: test/test.sh
- test/test.sh -b DEVPOLL
-test_runner_poll: test/test.sh
- test/test.sh -b POLL
-test_runner_win32: test/test.sh
- test/test.sh -b WIN32
-test_runner_timerfd: test/test.sh
- test/test.sh -b "" -t
-test_runner_changelist: test/test.sh
- test/test.sh -b "" -c
-test_runner_timerfd_changelist: test/test.sh
- test/test.sh -b "" -T
+test_runner_epoll: $(top_srcdir)/test/test.sh
+ $(top_srcdir)/test/test.sh -b EPOLL
+test_runner_select: $(top_srcdir)/test/test.sh
+ $(top_srcdir)/test/test.sh -b SELECT
+test_runner_kqueue: $(top_srcdir)/test/test.sh
+ $(top_srcdir)/test/test.sh -b KQUEUE
+test_runner_evport: $(top_srcdir)/test/test.sh
+ $(top_srcdir)/test/test.sh -b EVPORT
+test_runner_devpoll: $(top_srcdir)/test/test.sh
+ $(top_srcdir)/test/test.sh -b DEVPOLL
+test_runner_poll: $(top_srcdir)/test/test.sh
+ $(top_srcdir)/test/test.sh -b POLL
+test_runner_win32: $(top_srcdir)/test/test.sh
+ $(top_srcdir)/test/test.sh -b WIN32
+test_runner_timerfd: $(top_srcdir)/test/test.sh
+ $(top_srcdir)/test/test.sh -b "" -t
+test_runner_changelist: $(top_srcdir)/test/test.sh
+ $(top_srcdir)/test/test.sh -b "" -c
+test_runner_timerfd_changelist: $(top_srcdir)/test/test.sh
+ $(top_srcdir)/test/test.sh -b "" -T
DISTCLEANFILES += test/regress.gen.c test/regress.gen.h
diff --git a/test/regress.c b/test/regress.c
index d8a6b9b8..2c17dba3 100644
--- a/test/regress.c
+++ b/test/regress.c
@@ -848,18 +848,36 @@ simple_child_read_cb(evutil_socket_t fd, short event, void *arg)
called++;
}
+
+#define TEST_FORK_EXIT_SUCCESS 76
+static void fork_wait_check(int pid)
+{
+ int status;
+
+ TT_BLATHER(("Before waitpid"));
+
+#ifdef WNOWAIT
+ if ((waitpid(pid, &status, WNOWAIT) == -1 && errno == EINVAL) &&
+#else
+ if (
+#endif
+ waitpid(pid, &status, 0) == -1) {
+ perror("waitpid");
+ exit(1);
+ }
+ TT_BLATHER(("After waitpid"));
+
+ if (WEXITSTATUS(status) != TEST_FORK_EXIT_SUCCESS) {
+ fprintf(stdout, "FAILED (exit): %d\n", WEXITSTATUS(status));
+ exit(1);
+ }
+}
static void
test_fork(void)
{
char c;
- int status;
struct event ev, sig_ev, usr_ev, existing_ev;
pid_t pid;
- int wait_flags = 0;
-
-#ifdef EVENT__HAVE_WAITPID_WITH_WNOWAIT
- wait_flags |= WNOWAIT;
-#endif
setup_test("After fork: ");
@@ -922,7 +940,7 @@ test_fork(void)
/* we do not send an EOF; simple_read_cb requires an EOF
* to set test_ok. we just verify that the callback was
* called. */
- exit(test_ok != 0 || called != 2 ? -2 : 76);
+ exit(test_ok != 0 || called != 2 ? -2 : TEST_FORK_EXIT_SUCCESS);
}
/** wait until client read first message */
@@ -933,17 +951,7 @@ test_fork(void)
tt_fail_perror("write");
}
- TT_BLATHER(("Before waitpid"));
- if (waitpid(pid, &status, wait_flags) == -1) {
- perror("waitpid");
- exit(1);
- }
- TT_BLATHER(("After waitpid"));
-
- if (WEXITSTATUS(status) != 76) {
- fprintf(stdout, "FAILED (exit): %d\n", WEXITSTATUS(status));
- exit(1);
- }
+ fork_wait_check(pid);
/* test that the current event loop still works */
if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) {
@@ -989,9 +997,9 @@ static void
del_wait_cb(evutil_socket_t fd, short event, void *arg)
{
struct timeval delay = { 0, 300*1000 };
- TT_BLATHER(("Sleeping"));
+ TT_BLATHER(("Sleeping: %i", test_ok));
evutil_usleep_(&delay);
- test_ok = 1;
+ ++test_ok;
}
static void
@@ -1002,7 +1010,7 @@ test_del_wait(void)
setup_test("event_del will wait: ");
- event_set(&ev, pair[1], EV_READ, del_wait_cb, &ev);
+ event_set(&ev, pair[1], EV_READ|EV_PERSIST, del_wait_cb, &ev);
event_add(&ev, NULL);
pthread_create(&thread, NULL, del_wait_thread, NULL);
@@ -1026,9 +1034,39 @@ test_del_wait(void)
pthread_join(thread, NULL);
+ tt_int_op(test_ok, ==, 1);
+
end:
;
}
+
+static void null_cb(evutil_socket_t fd, short what, void *arg) {}
+static void* test_del_notify_thread(void *arg)
+{
+ event_dispatch();
+ return NULL;
+}
+static void
+test_del_notify(void)
+{
+ struct event ev;
+ pthread_t thread;
+
+ test_ok = 1;
+
+ event_set(&ev, -1, EV_READ, null_cb, &ev);
+ event_add(&ev, NULL);
+
+ pthread_create(&thread, NULL, test_del_notify_thread, NULL);
+
+ {
+ struct timeval delay = { 0, 1000 };
+ evutil_usleep_(&delay);
+ }
+
+ event_del(&ev);
+ pthread_join(thread, NULL);
+}
#endif
static void
@@ -1351,18 +1389,14 @@ test_free_active_base(void *ptr)
struct event ev1;
base1 = event_init();
- if (base1) {
- event_assign(&ev1, base1, data->pair[1], EV_READ,
- dummy_read_cb, NULL);
- event_add(&ev1, NULL);
- event_base_free(base1); /* should not crash */
- } else {
- tt_fail_msg("failed to create event_base for test");
- }
+ tt_assert(base1);
+ event_assign(&ev1, base1, data->pair[1], EV_READ, dummy_read_cb, NULL);
+ event_add(&ev1, NULL);
+ event_base_free(base1); /* should not crash */
base1 = event_init();
tt_assert(base1);
- event_assign(&ev1, base1, 0, 0, dummy_read_cb, NULL);
+ event_assign(&ev1, base1, data->pair[0], 0, dummy_read_cb, NULL);
event_active(&ev1, EV_READ, 1);
event_base_free(base1);
end:
@@ -1840,7 +1874,8 @@ static void send_a_byte_cb(evutil_socket_t fd, short what, void *arg)
{
evutil_socket_t *sockp = arg;
(void) fd; (void) what;
- (void) write(*sockp, "A", 1);
+ if (write(*sockp, "A", 1) < 0)
+ tt_fail_perror("write");
}
struct read_not_timeout_param
{
@@ -2070,60 +2105,48 @@ re_add_read_cb(evutil_socket_t fd, short event, void *arg)
if (n_read < 0) {
tt_fail_perror("read");
event_base_loopbreak(event_get_base(ev_other));
- return;
} else {
event_add(ev_other, NULL);
++test_ok;
}
}
-
static void
-test_nonpersist_readd(void)
+test_nonpersist_readd(void *_data)
{
struct event ev1, ev2;
+ struct basic_test_data *data = _data;
- setup_test("Re-add nonpersistent events: ");
- event_set(&ev1, pair[0], EV_READ, re_add_read_cb, &ev2);
- event_set(&ev2, pair[1], EV_READ, re_add_read_cb, &ev1);
+ memset(&ev1, 0, sizeof(ev1));
+ memset(&ev2, 0, sizeof(ev2));
- if (write(pair[0], "Hello", 5) < 0) {
- tt_fail_perror("write(pair[0])");
- }
+ tt_assert(!event_assign(&ev1, data->base, data->pair[0], EV_READ, re_add_read_cb, &ev2));
+ tt_assert(!event_assign(&ev2, data->base, data->pair[1], EV_READ, re_add_read_cb, &ev1));
- if (write(pair[1], "Hello", 5) < 0) {
- tt_fail_perror("write(pair[1])\n");
- }
+ tt_int_op(write(data->pair[0], "Hello", 5), ==, 5);
+ tt_int_op(write(data->pair[1], "Hello", 5), ==, 5);
+
+ tt_int_op(event_add(&ev1, NULL), ==, 0);
+ tt_int_op(event_add(&ev2, NULL), ==, 0);
+ tt_int_op(event_base_loop(data->base, EVLOOP_ONCE), ==, 0);
+ tt_int_op(test_ok, ==, 2);
- if (event_add(&ev1, NULL) == -1 ||
- event_add(&ev2, NULL) == -1) {
- test_ok = 0;
- }
- if (test_ok != 0)
- exit(1);
- event_loop(EVLOOP_ONCE);
- if (test_ok != 2)
- exit(1);
/* At this point, we executed both callbacks. Whichever one got
* called first added the second, but the second then immediately got
* deleted before its callback was called. At this point, though, it
* re-added the first.
*/
- if (!readd_test_event_last_added) {
- test_ok = 0;
- } else if (readd_test_event_last_added == &ev1) {
- if (!event_pending(&ev1, EV_READ, NULL) ||
- event_pending(&ev2, EV_READ, NULL))
- test_ok = 0;
+ tt_assert(readd_test_event_last_added);
+ if (readd_test_event_last_added == &ev1) {
+ tt_assert(event_pending(&ev1, EV_READ, NULL) && !event_pending(&ev2, EV_READ, NULL));
} else {
- if (event_pending(&ev1, EV_READ, NULL) ||
- !event_pending(&ev2, EV_READ, NULL))
- test_ok = 0;
+ tt_assert(event_pending(&ev2, EV_READ, NULL) && !event_pending(&ev1, EV_READ, NULL));
}
- event_del(&ev1);
- event_del(&ev2);
-
- cleanup_test();
+end:
+ if (event_initialized(&ev1))
+ event_del(&ev1);
+ if (event_initialized(&ev2))
+ event_del(&ev2);
}
struct test_pri_event {
@@ -3041,6 +3064,7 @@ test_many_events(void *arg)
* instance of that. */
sock[i] = socket(AF_INET, SOCK_DGRAM, 0);
tt_assert(sock[i] >= 0);
+ tt_assert(!evutil_make_socket_nonblocking(sock[i]));
called[i] = 0;
ev[i] = event_new(base, sock[i], EV_WRITE|evflags,
many_event_cb, &called[i]);
@@ -3094,7 +3118,7 @@ test_get_assignment(void *arg)
event_get_assignment(ev1, &b, &s, &what, &cb, &cb_arg);
tt_ptr_op(b, ==, base);
- tt_int_op(s, ==, data->pair[1]);
+ tt_fd_op(s, ==, data->pair[1]);
tt_int_op(what, ==, EV_READ);
tt_ptr_op(cb, ==, dummy_read_cb);
tt_ptr_op(cb_arg, ==, str);
@@ -3380,14 +3404,14 @@ struct testcase_t main_testcases[] = {
BASIC(bad_assign, TT_FORK|TT_NEED_BASE|TT_NO_LOGS),
BASIC(bad_reentrant, TT_FORK|TT_NEED_BASE|TT_NO_LOGS),
- BASIC(active_later, TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR),
+ BASIC(active_later, TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR|TT_RETRIABLE),
BASIC(event_remove_timeout, TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR),
/* These are still using the old API */
LEGACY(persistent_timeout, TT_FORK|TT_NEED_BASE),
{ "persistent_timeout_jump", test_persistent_timeout_jump, TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
{ "persistent_active_timeout", test_persistent_active_timeout,
- TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
+ TT_FORK|TT_NEED_BASE|TT_RETRIABLE, &basic_setup, NULL },
LEGACY(priorities, TT_FORK|TT_NEED_BASE),
BASIC(priority_active_inversion, TT_FORK|TT_NEED_BASE),
{ "common_timeout", test_common_timeout, TT_FORK|TT_NEED_BASE,
@@ -3406,7 +3430,7 @@ struct testcase_t main_testcases[] = {
LEGACY(loopbreak, TT_ISOLATED),
LEGACY(loopexit, TT_ISOLATED),
LEGACY(loopexit_multiple, TT_ISOLATED),
- LEGACY(nonpersist_readd, TT_ISOLATED),
+ { "nonpersist_readd", test_nonpersist_readd, TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE, &basic_setup, NULL },
LEGACY(multiple_events_for_same_fd, TT_ISOLATED),
LEGACY(want_only_once, TT_ISOLATED),
{ "event_once", test_event_once, TT_ISOLATED, &basic_setup, NULL },
@@ -3435,12 +3459,13 @@ struct testcase_t main_testcases[] = {
BASIC(active_by_fd, TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR),
-#ifndef _WIN32
+#if !defined(_WIN32) && !defined(__APPLE__)
LEGACY(fork, TT_ISOLATED),
#endif
#ifdef EVENT__HAVE_PTHREADS
/** TODO: support win32 */
- LEGACY(del_wait, TT_ISOLATED|TT_NEED_THREADS),
+ LEGACY(del_wait, TT_ISOLATED|TT_NEED_THREADS|TT_RETRIABLE),
+ LEGACY(del_notify, TT_ISOLATED|TT_NEED_THREADS),
#endif
END_OF_TESTCASES
diff --git a/test/regress.h b/test/regress.h
index de1aed30..643b82ba 100644
--- a/test/regress.h
+++ b/test/regress.h
@@ -43,6 +43,7 @@ extern struct testcase_t bufferevent_iocp_testcases[];
extern struct testcase_t util_testcases[];
extern struct testcase_t signal_testcases[];
extern struct testcase_t http_testcases[];
+extern struct testcase_t http_iocp_testcases[];
extern struct testcase_t dns_testcases[];
extern struct testcase_t rpc_testcases[];
extern struct testcase_t edgetriggered_testcases[];
@@ -132,11 +133,14 @@ pid_t regress_fork(void);
#ifdef EVENT__HAVE_OPENSSL
#include <openssl/ssl.h>
EVP_PKEY *ssl_getkey(void);
-X509 *ssl_getcert(void);
+X509 *ssl_getcert(EVP_PKEY *key);
SSL_CTX *get_ssl_ctx(void);
void init_ssl(void);
#endif
+void * basic_test_setup(const struct testcase_t *testcase);
+int basic_test_cleanup(const struct testcase_t *testcase, void *ptr);
+
#ifdef __cplusplus
}
#endif
diff --git a/test/regress_bufferevent.c b/test/regress_bufferevent.c
index 249985e9..3ed48fae 100644
--- a/test/regress_bufferevent.c
+++ b/test/regress_bufferevent.c
@@ -137,14 +137,14 @@ test_bufferevent_impl(int use_pair, int flush)
bev2 = pair[1];
bufferevent_setcb(bev1, readcb, writecb, errorcb, bev1);
bufferevent_setcb(bev2, readcb, writecb, errorcb, NULL);
- tt_int_op(bufferevent_getfd(bev1), ==, -1);
+ tt_fd_op(bufferevent_getfd(bev1), ==, EVUTIL_INVALID_SOCKET);
tt_ptr_op(bufferevent_get_underlying(bev1), ==, NULL);
tt_ptr_op(bufferevent_pair_get_partner(bev1), ==, bev2);
tt_ptr_op(bufferevent_pair_get_partner(bev2), ==, bev1);
} else {
bev1 = bufferevent_new(pair[0], readcb, writecb, errorcb, NULL);
bev2 = bufferevent_new(pair[1], readcb, writecb, errorcb, NULL);
- tt_int_op(bufferevent_getfd(bev1), ==, pair[0]);
+ tt_fd_op(bufferevent_getfd(bev1), ==, pair[0]);
tt_ptr_op(bufferevent_get_underlying(bev1), ==, NULL);
tt_ptr_op(bufferevent_pair_get_partner(bev1), ==, NULL);
tt_ptr_op(bufferevent_pair_get_partner(bev2), ==, NULL);
@@ -569,8 +569,8 @@ test_bufferevent_filters_impl(int use_pair, int disable)
tt_ptr_op(bufferevent_get_underlying(bev1), ==, bev1_base);
tt_ptr_op(bufferevent_get_underlying(bev2), ==, bev2_base);
- tt_int_op(bufferevent_getfd(bev1), ==, -1);
- tt_int_op(bufferevent_getfd(bev2), ==, -1);
+ tt_fd_op(bufferevent_getfd(bev1), ==, bufferevent_getfd(bev1_base));
+ tt_fd_op(bufferevent_getfd(bev2), ==, bufferevent_getfd(bev2_base));
bufferevent_disable(bev1, EV_READ);
bufferevent_enable(bev2, EV_READ);
@@ -640,7 +640,7 @@ end:
;
}
-static int
+static evutil_socket_t
fake_listener_create(struct sockaddr_in *localhost)
{
struct sockaddr *sa = (struct sockaddr *)localhost;
@@ -908,18 +908,24 @@ struct timeout_cb_result {
struct timeval read_timeout_at;
struct timeval write_timeout_at;
struct timeval last_wrote_at;
+ struct timeval last_read_at;
int n_read_timeouts;
int n_write_timeouts;
int total_calls;
};
static void
+bev_timeout_read_cb(struct bufferevent *bev, void *arg)
+{
+ struct timeout_cb_result *res = arg;
+ evutil_gettimeofday(&res->last_read_at, NULL);
+}
+static void
bev_timeout_write_cb(struct bufferevent *bev, void *arg)
{
struct timeout_cb_result *res = arg;
evutil_gettimeofday(&res->last_wrote_at, NULL);
}
-
static void
bev_timeout_event_cb(struct bufferevent *bev, short what, void *arg)
{
@@ -947,7 +953,6 @@ test_bufferevent_timeouts(void *arg)
int use_pair = 0, use_filter = 0;
struct timeval tv_w, tv_r, started_at;
struct timeout_cb_result res1, res2;
- char buf[1024];
memset(&res1, 0, sizeof(res1));
memset(&res2, 0, sizeof(res2));
@@ -966,7 +971,6 @@ test_bufferevent_timeouts(void *arg)
bev1 = bufferevent_socket_new(data->base, data->pair[0], 0);
bev2 = bufferevent_socket_new(data->base, data->pair[1], 0);
}
-
tt_assert(bev1);
tt_assert(bev2);
@@ -990,30 +994,14 @@ test_bufferevent_timeouts(void *arg)
tv_w.tv_sec = tv_r.tv_sec = 0;
tv_w.tv_usec = 100*1000;
tv_r.tv_usec = 150*1000;
- bufferevent_setcb(bev1, NULL, bev_timeout_write_cb,
+ bufferevent_setcb(bev1, bev_timeout_read_cb, bev_timeout_write_cb,
bev_timeout_event_cb, &res1);
- bufferevent_setwatermark(bev1, EV_WRITE, 1024*1024+10, 0);
bufferevent_set_timeouts(bev1, &tv_r, &tv_w);
- if (use_pair) {
- /* For a pair, the fact that the other side isn't reading
- * makes the writer stall */
- bufferevent_write(bev1, "ABCDEFG", 7);
- } else {
- /* For a real socket, the kernel's TCP buffers can eat a
- * fair number of bytes; make sure that at some point we
- * have some bytes that will stall. */
- struct evbuffer *output = bufferevent_get_output(bev1);
- int i;
- memset(buf, 0xbb, sizeof(buf));
- for (i=0;i<1024;++i) {
- evbuffer_add_reference(output, buf, sizeof(buf),
- NULL, NULL);
- }
- }
+ bufferevent_write(bev1, "ABCDEFG", 7);
bufferevent_enable(bev1, EV_READ|EV_WRITE);
/* bev2 has nothing to say, and isn't listening. */
- bufferevent_setcb(bev2, NULL, bev_timeout_write_cb,
+ bufferevent_setcb(bev2, bev_timeout_read_cb, bev_timeout_write_cb,
bev_timeout_event_cb, &res2);
tv_w.tv_sec = tv_r.tv_sec = 0;
tv_w.tv_usec = 200*1000;
@@ -1030,15 +1018,26 @@ test_bufferevent_timeouts(void *arg)
/* XXXX Test that actually reading or writing a little resets the
* timeouts. */
- /* Each buf1 timeout happens, and happens only once. */
- tt_want(res1.n_read_timeouts);
- tt_want(res1.n_write_timeouts);
+ tt_want(res1.total_calls == 2);
tt_want(res1.n_read_timeouts == 1);
tt_want(res1.n_write_timeouts == 1);
+ tt_want(res2.total_calls == !(use_pair && !use_filter));
+ tt_want(res2.n_write_timeouts == !(use_pair && !use_filter));
+ tt_want(!res2.n_read_timeouts);
test_timeval_diff_eq(&started_at, &res1.read_timeout_at, 150);
test_timeval_diff_eq(&started_at, &res1.write_timeout_at, 100);
+#define tt_assert_timeval_empty(tv) do { \
+ tt_int_op((tv).tv_sec, ==, 0); \
+ tt_int_op((tv).tv_usec, ==, 0); \
+} while(0)
+ tt_assert_timeval_empty(res1.last_read_at);
+ tt_assert_timeval_empty(res2.last_read_at);
+ tt_assert_timeval_empty(res2.last_wrote_at);
+ tt_assert_timeval_empty(res2.last_wrote_at);
+#undef tt_assert_timeval_empty
+
end:
if (bev1)
bufferevent_free(bev1);
@@ -1363,7 +1362,7 @@ struct testcase_t bufferevent_testcases[] = {
{ "bufferevent_connect_fail", test_bufferevent_connect_fail,
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
{ "bufferevent_timeout", test_bufferevent_timeouts,
- TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR, &basic_setup, (void*)"" },
+ TT_FORK|TT_NEED_BASE, &basic_setup, (void*)"" },
{ "bufferevent_timeout_pair", test_bufferevent_timeouts,
TT_FORK|TT_NEED_BASE, &basic_setup, (void*)"pair" },
{ "bufferevent_timeout_filter", test_bufferevent_timeouts,
@@ -1406,38 +1405,35 @@ struct testcase_t bufferevent_testcases[] = {
END_OF_TESTCASES,
};
+#define TT_IOCP (TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP)
+#define TT_IOCP_LEGACY (TT_ISOLATED|TT_ENABLE_IOCP)
struct testcase_t bufferevent_iocp_testcases[] = {
-
- LEGACY(bufferevent, TT_ISOLATED|TT_ENABLE_IOCP),
+ LEGACY(bufferevent, TT_IOCP_LEGACY),
LEGACY(bufferevent_flush_normal, TT_ISOLATED),
LEGACY(bufferevent_flush_flush, TT_ISOLATED),
LEGACY(bufferevent_flush_finished, TT_ISOLATED),
- LEGACY(bufferevent_watermarks, TT_ISOLATED|TT_ENABLE_IOCP),
- LEGACY(bufferevent_filters, TT_ISOLATED|TT_ENABLE_IOCP),
- LEGACY(bufferevent_filters_disable, TT_ISOLATED|TT_ENABLE_IOCP),
+ LEGACY(bufferevent_watermarks, TT_IOCP_LEGACY),
+ LEGACY(bufferevent_filters, TT_IOCP_LEGACY),
+ LEGACY(bufferevent_filters_disable, TT_IOCP_LEGACY),
+
{ "bufferevent_connect", test_bufferevent_connect,
- TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, (void*)"" },
+ TT_IOCP, &basic_setup, (void*)"" },
{ "bufferevent_connect_defer", test_bufferevent_connect,
- TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, (void*)"defer" },
+ TT_IOCP, &basic_setup, (void*)"defer" },
{ "bufferevent_connect_lock", test_bufferevent_connect,
- TT_FORK|TT_NEED_BASE|TT_NEED_THREADS|TT_ENABLE_IOCP, &basic_setup,
- (void*)"lock" },
+ TT_IOCP, &basic_setup, (void*)"lock" },
{ "bufferevent_connect_lock_defer", test_bufferevent_connect,
- TT_FORK|TT_NEED_BASE|TT_NEED_THREADS|TT_ENABLE_IOCP, &basic_setup,
- (void*)"defer lock" },
+ TT_IOCP, &basic_setup, (void*)"defer lock" },
{ "bufferevent_connect_fail", test_bufferevent_connect_fail,
- TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, NULL },
+ TT_IOCP, &basic_setup, NULL },
{ "bufferevent_connect_nonblocking", test_bufferevent_connect,
- TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup,
- (void*)"unset_connectex" },
+ TT_IOCP, &basic_setup, (void*)"unset_connectex" },
{ "bufferevent_connect_fail_eventcb_defer",
test_bufferevent_connect_fail_eventcb,
- TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup,
- (void*)BEV_OPT_DEFER_CALLBACKS },
+ TT_IOCP, &basic_setup, (void*)BEV_OPT_DEFER_CALLBACKS },
{ "bufferevent_connect_fail_eventcb",
- test_bufferevent_connect_fail_eventcb,
- TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, NULL },
+ test_bufferevent_connect_fail_eventcb, TT_IOCP, &basic_setup, NULL },
END_OF_TESTCASES,
};
diff --git a/test/regress_dns.c b/test/regress_dns.c
index 8950440f..9f1d6283 100644
--- a/test/regress_dns.c
+++ b/test/regress_dns.c
@@ -59,6 +59,10 @@
#include <string.h>
#include <errno.h>
+#ifdef EVENT__HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
#include "event2/dns.h"
#include "event2/dns_compat.h"
#include "event2/dns_struct.h"
@@ -68,9 +72,12 @@
#include "event2/util.h"
#include "event2/listener.h"
#include "event2/bufferevent.h"
+#include <event2/thread.h>
#include "log-internal.h"
+#include "evthread-internal.h"
#include "regress.h"
#include "regress_testutils.h"
+#include "regress_thread.h"
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
@@ -612,16 +619,8 @@ end:
if (dns)
evdns_base_free(dns, 0);
}
-static void
-dns_search_test(void *arg)
-{
- return dns_search_test_impl(arg, 0);
-}
-static void
-dns_search_lower_test(void *arg)
-{
- return dns_search_test_impl(arg, 1);
-}
+static void dns_search_test(void *arg) { dns_search_test_impl(arg, 0); }
+static void dns_search_lower_test(void *arg) { dns_search_test_impl(arg, 1); }
static int request_count = 0;
static struct evdns_request *current_req = NULL;
@@ -1021,7 +1020,7 @@ be_getaddrinfo_server_cb(struct evdns_server_request *req, void *data)
int added_any=0;
++*n_got_p;
- for (i=0;i<req->nquestions;++i) {
+ for (i = 0; i < req->nquestions; ++i) {
const int qtype = req->questions[i]->type;
const int qclass = req->questions[i]->dns_question_class;
const char *qname = req->questions[i]->name;
@@ -1165,27 +1164,36 @@ static void
be_connect_hostname_event_cb(struct bufferevent *bev, short what, void *ctx)
{
struct be_conn_hostname_result *got = ctx;
- if (!got->what) {
- TT_BLATHER(("Got a bufferevent event %d", what));
- got->what = what;
-
- if ((what & BEV_EVENT_CONNECTED) || (what & BEV_EVENT_ERROR)) {
- int r;
- if ((r = bufferevent_socket_get_dns_error(bev))) {
- got->dnserr = r;
- TT_BLATHER(("DNS error %d: %s", r,
- evutil_gai_strerror(r)));
- } ++total_connected_or_failed;
- TT_BLATHER(("Got %d connections or errors.", total_connected_or_failed));
-
- if (total_n_accepted >= 3 && total_connected_or_failed >= 5)
- event_base_loopexit(be_connect_hostname_base,
- NULL);
- }
- } else {
+
+ if (got->what) {
TT_FAIL(("Two events on one bufferevent. %d,%d",
got->what, (int)what));
}
+
+ TT_BLATHER(("Got a bufferevent event %d", what));
+ got->what = what;
+
+ if ((what & BEV_EVENT_CONNECTED) || (what & BEV_EVENT_ERROR)) {
+ int expected = 3;
+ int r = bufferevent_socket_get_dns_error(bev);
+
+ if (r) {
+ got->dnserr = r;
+ TT_BLATHER(("DNS error %d: %s", r,
+ evutil_gai_strerror(r)));
+ }
+ ++total_connected_or_failed;
+ TT_BLATHER(("Got %d connections or errors.", total_connected_or_failed));
+
+ /** emfile test */
+ if (errno == EMFILE) {
+ expected = 0;
+ }
+
+ if (total_n_accepted >= expected && total_connected_or_failed >= 5)
+ event_base_loopexit(be_connect_hostname_base,
+ NULL);
+ }
}
static void
@@ -1193,10 +1201,9 @@ test_bufferevent_connect_hostname(void *arg)
{
struct basic_test_data *data = arg;
struct evconnlistener *listener = NULL;
- struct bufferevent *be1=NULL, *be2=NULL, *be3=NULL, *be4=NULL, *be5=NULL;
- struct be_conn_hostname_result be1_outcome={0,0}, be2_outcome={0,0},
- be3_outcome={0,0}, be4_outcome={0,0}, be5_outcome={0,0};
- int expect_err5;
+ struct bufferevent *be[5];
+ struct be_conn_hostname_result be_outcome[ARRAY_SIZE(be)];
+ int expect_err;
struct evdns_base *dns=NULL;
struct evdns_server_port *port=NULL;
struct sockaddr_in sin;
@@ -1204,6 +1211,27 @@ test_bufferevent_connect_hostname(void *arg)
ev_uint16_t dns_port=0;
int n_accept=0, n_dns=0;
char buf[128];
+ int emfile = data->setup_data && !strcmp(data->setup_data, "emfile");
+ int success = BEV_EVENT_CONNECTED;
+ int default_error = 0;
+ unsigned i;
+ int ret;
+
+ if (emfile) {
+ success = BEV_EVENT_ERROR;
+#if defined(__linux__)
+ /* on linux glibc/musl reports EAI_SYSTEM, when getaddrinfo() cannot
+ * open file for resolving service. */
+ default_error = EVUTIL_EAI_SYSTEM;
+#elif defined(__sun__)
+ /* on solaris it returns EAI_FAIL */
+ default_error = EVUTIL_EAI_FAIL;
+ /** the DP_POLL can also fail with EINVAL under EMFILE */
+#else
+ /* on osx/freebsd it returns EAI_NONAME */
+ default_error = EVUTIL_EAI_NONAME;
+#endif
+ }
be_connect_hostname_base = data->base;
@@ -1230,32 +1258,34 @@ test_bufferevent_connect_hostname(void *arg)
evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)dns_port);
evdns_base_nameserver_ip_add(dns, buf);
+#ifdef EVENT__HAVE_SETRLIMIT
+ if (emfile) {
+ int fd = socket(AF_INET, SOCK_STREAM, 0);
+ struct rlimit file = { fd, fd };
+
+ tt_int_op(fd, >=, 0);
+ tt_assert(!close(fd));
+
+ tt_assert(!setrlimit(RLIMIT_NOFILE, &file));
+ }
+#endif
+
/* Now, finally, at long last, launch the bufferevents. One should do
* a failing lookup IP, one should do a successful lookup by IP,
* and one should do a successful lookup by hostname. */
- be1 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE);
- be2 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE);
- be3 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE);
- be4 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE);
- be5 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE);
-
- bufferevent_setcb(be1, NULL, NULL, be_connect_hostname_event_cb,
- &be1_outcome);
- bufferevent_setcb(be2, NULL, NULL, be_connect_hostname_event_cb,
- &be2_outcome);
- bufferevent_setcb(be3, NULL, NULL, be_connect_hostname_event_cb,
- &be3_outcome);
- bufferevent_setcb(be4, NULL, NULL, be_connect_hostname_event_cb,
- &be4_outcome);
- bufferevent_setcb(be5, NULL, NULL, be_connect_hostname_event_cb,
- &be5_outcome);
+ for (i = 0; i < ARRAY_SIZE(be); ++i) {
+ memset(&be_outcome[i], 0, sizeof(be_outcome[i]));
+ be[i] = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE);
+ bufferevent_setcb(be[i], NULL, NULL, be_connect_hostname_event_cb,
+ &be_outcome[i]);
+ }
/* Use the blocking resolver. This one will fail if your resolver
* can't resolve localhost to 127.0.0.1 */
- tt_assert(!bufferevent_socket_connect_hostname(be4, NULL, AF_INET,
+ tt_assert(!bufferevent_socket_connect_hostname(be[3], NULL, AF_INET,
"localhost", listener_port));
/* Use the blocking resolver with a nonexistent hostname. */
- tt_assert(!bufferevent_socket_connect_hostname(be5, NULL, AF_INET,
+ tt_assert(!bufferevent_socket_connect_hostname(be[4], NULL, AF_INET,
"nonesuch.nowhere.example.com", 80));
{
/* The blocking resolver will use the system nameserver, which
@@ -1266,35 +1296,49 @@ test_bufferevent_connect_hostname(void *arg)
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
- expect_err5 = evutil_getaddrinfo(
+ expect_err = evutil_getaddrinfo(
"nonesuch.nowhere.example.com", "80", &hints, &ai);
}
/* Launch an async resolve that will fail. */
- tt_assert(!bufferevent_socket_connect_hostname(be1, dns, AF_INET,
+ tt_assert(!bufferevent_socket_connect_hostname(be[0], dns, AF_INET,
"nosuchplace.example.com", listener_port));
/* Connect to the IP without resolving. */
- tt_assert(!bufferevent_socket_connect_hostname(be2, dns, AF_INET,
+ tt_assert(!bufferevent_socket_connect_hostname(be[1], dns, AF_INET,
"127.0.0.1", listener_port));
/* Launch an async resolve that will succeed. */
- tt_assert(!bufferevent_socket_connect_hostname(be3, dns, AF_INET,
+ tt_assert(!bufferevent_socket_connect_hostname(be[2], dns, AF_INET,
"nobodaddy.example.com", listener_port));
- event_base_dispatch(data->base);
+ ret = event_base_dispatch(data->base);
+#ifdef __sun__
+ if (emfile && !strcmp(event_base_get_method(data->base), "devpoll")) {
+ tt_int_op(ret, ==, -1);
+ /** DP_POLL failed */
+ tt_skip();
+ } else
+#endif
+ {
+ tt_int_op(ret, ==, 0);
+ }
- tt_int_op(be1_outcome.what, ==, BEV_EVENT_ERROR);
- tt_int_op(be1_outcome.dnserr, ==, EVUTIL_EAI_NONAME);
- tt_int_op(be2_outcome.what, ==, BEV_EVENT_CONNECTED);
- tt_int_op(be2_outcome.dnserr, ==, 0);
- tt_int_op(be3_outcome.what, ==, BEV_EVENT_CONNECTED);
- tt_int_op(be3_outcome.dnserr, ==, 0);
- tt_int_op(be4_outcome.what, ==, BEV_EVENT_CONNECTED);
- tt_int_op(be4_outcome.dnserr, ==, 0);
- if (expect_err5) {
- tt_int_op(be5_outcome.what, ==, BEV_EVENT_ERROR);
- tt_int_op(be5_outcome.dnserr, ==, expect_err5);
+ tt_int_op(be_outcome[0].what, ==, BEV_EVENT_ERROR);
+ tt_int_op(be_outcome[0].dnserr, ==, EVUTIL_EAI_NONAME);
+ tt_int_op(be_outcome[1].what, ==, success);
+ tt_int_op(be_outcome[1].dnserr, ==, 0);
+ tt_int_op(be_outcome[2].what, ==, success);
+ tt_int_op(be_outcome[2].dnserr, ==, 0);
+ tt_int_op(be_outcome[3].what, ==, success);
+ tt_int_op(be_outcome[3].dnserr, ==, default_error);
+ if (expect_err) {
+ tt_int_op(be_outcome[4].what, ==, BEV_EVENT_ERROR);
+ tt_int_op(be_outcome[4].dnserr, ==, expect_err);
}
- tt_int_op(n_accept, ==, 3);
+ if (emfile) {
+ tt_int_op(n_accept, ==, 0);
+ } else {
+ tt_int_op(n_accept, ==, 3);
+ }
tt_int_op(n_dns, ==, 2);
end:
@@ -1304,16 +1348,10 @@ end:
evdns_close_server_port(port);
if (dns)
evdns_base_free(dns, 0);
- if (be1)
- bufferevent_free(be1);
- if (be2)
- bufferevent_free(be2);
- if (be3)
- bufferevent_free(be3);
- if (be4)
- bufferevent_free(be4);
- if (be5)
- bufferevent_free(be5);
+ for (i = 0; i < ARRAY_SIZE(be); ++i) {
+ if (be[i])
+ bufferevent_free(be[i]);
+ }
}
@@ -1352,7 +1390,7 @@ test_getaddrinfo_async(void *arg)
struct evutil_addrinfo hints, *a;
struct gai_outcome local_outcome;
struct gai_outcome a_out[12];
- int i;
+ unsigned i;
struct evdns_getaddrinfo_request *r;
char buf[128];
struct evdns_server_port *port = NULL;
@@ -1710,7 +1748,7 @@ test_getaddrinfo_async(void *arg)
end:
if (local_outcome.ai)
evutil_freeaddrinfo(local_outcome.ai);
- for (i=0;i<(int)ARRAY_SIZE(a_out);++i) {
+ for (i = 0; i < ARRAY_SIZE(a_out); ++i) {
if (a_out[i].ai)
evutil_freeaddrinfo(a_out[i].ai);
}
@@ -1984,7 +2022,7 @@ test_getaddrinfo_async_cancel_stress(void *ptr)
struct sockaddr_in sin;
struct sockaddr_storage ss;
ev_socklen_t slen;
- int i;
+ unsigned i;
base = event_base_new();
dns_base = evdns_base_new(base, 0);
@@ -2039,7 +2077,7 @@ dns_client_fail_requests_test(void *arg)
char buf[64];
struct generic_dns_callback_result r[20];
- int i;
+ unsigned i;
dns_port = regress_get_dnsserver(base, &portnum, NULL,
regress_dns_server_cb, reissue_table);
@@ -2096,7 +2134,7 @@ dns_client_fail_requests_getaddrinfo_test(void *arg)
tt_assert(!evdns_base_nameserver_ip_add(dns, buf));
for (i = 0; i < 20; ++i)
- tt_assert(evdns_getaddrinfo(dns, "foof.example.com", "ssh", NULL, getaddrinfo_cb, &r[i]));
+ tt_assert(evdns_getaddrinfo(dns, "foof.example.com", "80", NULL, getaddrinfo_cb, &r[i]));
n_replies_left = 20;
exit_base = base;
@@ -2113,6 +2151,153 @@ end:
evdns_close_server_port(dns_port);
}
+#ifdef EVTHREAD_USE_PTHREADS_IMPLEMENTED
+struct race_param
+{
+ void *lock;
+ void *reqs_cmpl_cond;
+ int bw_threads;
+ void *bw_threads_exited_cond;
+ volatile int stopping;
+ void *base;
+ void *dns;
+
+ int locked;
+};
+static void *
+race_base_run(void *arg)
+{
+ struct race_param *rp = (struct race_param *)arg;
+ event_base_loop(rp->base, EVLOOP_NO_EXIT_ON_EMPTY);
+ THREAD_RETURN();
+}
+static void *
+race_busywait_run(void *arg)
+{
+ struct race_param *rp = (struct race_param *)arg;
+ struct sockaddr_storage ss;
+ while (!rp->stopping)
+ evdns_base_get_nameserver_addr(rp->dns, 0, (struct sockaddr *)&ss, sizeof(ss));
+ EVLOCK_LOCK(rp->lock, 0);
+ if (--rp->bw_threads == 0)
+ EVTHREAD_COND_SIGNAL(rp->bw_threads_exited_cond);
+ EVLOCK_UNLOCK(rp->lock, 0);
+ THREAD_RETURN();
+}
+static void
+race_gai_cb(int result, struct evutil_addrinfo *res, void *arg)
+{
+ struct race_param *rp = arg;
+ (void)result;
+ (void)res;
+
+ --n_replies_left;
+ if (n_replies_left == 0) {
+ EVLOCK_LOCK(rp->lock, 0);
+ EVTHREAD_COND_SIGNAL(rp->reqs_cmpl_cond);
+ EVLOCK_UNLOCK(rp->lock, 0);
+ }
+}
+static void
+getaddrinfo_race_gotresolve_test(void *arg)
+{
+ struct race_param rp;
+ struct evdns_server_port *dns_port = NULL;
+ ev_uint16_t portnum = 0;
+ char buf[64];
+ int i;
+
+ // Some stress is needed to yield inside getaddrinfo between resolve_ipv4 and resolve_ipv6
+ int n_reqs = 16384;
+#ifdef _SC_NPROCESSORS_ONLN
+ int n_threads = sysconf(_SC_NPROCESSORS_ONLN) + 1;
+#else
+ int n_threads = 17;
+#endif
+ THREAD_T thread[n_threads];
+ struct timeval tv;
+
+ (void)arg;
+
+ evthread_use_pthreads();
+
+ rp.base = event_base_new();
+ tt_assert(rp.base);
+ if (evthread_make_base_notifiable(rp.base) < 0)
+ tt_abort_msg("Couldn't make base notifiable!");
+
+ dns_port = regress_get_dnsserver(rp.base, &portnum, NULL,
+ regress_dns_server_cb, reissue_table);
+ tt_assert(dns_port);
+
+ evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum);
+
+ rp.dns = evdns_base_new(rp.base, 0);
+ tt_assert(!evdns_base_nameserver_ip_add(rp.dns, buf));
+
+ n_replies_left = n_reqs;
+
+ EVTHREAD_ALLOC_LOCK(rp.lock, 0);
+ EVTHREAD_ALLOC_COND(rp.reqs_cmpl_cond);
+ EVTHREAD_ALLOC_COND(rp.bw_threads_exited_cond);
+ tt_assert(rp.lock);
+ tt_assert(rp.reqs_cmpl_cond);
+ tt_assert(rp.bw_threads_exited_cond);
+ rp.bw_threads = 0;
+ rp.stopping = 0;
+
+ // Run resolver thread
+ THREAD_START(thread[0], race_base_run, &rp);
+ // Run busy-wait threads used to force yield this thread
+ for (i = 1; i < n_threads; i++) {
+ rp.bw_threads++;
+ THREAD_START(thread[i], race_busywait_run, &rp);
+ }
+
+ EVLOCK_LOCK(rp.lock, 0);
+ rp.locked = 1;
+
+ for (i = 0; i < n_reqs; ++i) {
+ tt_assert(evdns_getaddrinfo(rp.dns, "foof.example.com", "80", NULL, race_gai_cb, &rp));
+ // This magic along with busy-wait threads make this thread yield frequently
+ if (i % 100 == 0) {
+ tv.tv_sec = 0;
+ tv.tv_usec = 10000;
+ evutil_usleep_(&tv);
+ }
+ }
+
+ exit_base = rp.base;
+
+ // Wait for some time
+ tv.tv_sec = 5;
+ tv.tv_usec = 0;
+ EVTHREAD_COND_WAIT_TIMED(rp.reqs_cmpl_cond, rp.lock, &tv);
+
+ // Stop busy-wait threads
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ rp.stopping = 1;
+ tt_assert(EVTHREAD_COND_WAIT_TIMED(rp.bw_threads_exited_cond, rp.lock, &tv) == 0);
+
+ EVLOCK_UNLOCK(rp.lock, 0);
+ rp.locked = 0;
+
+ evdns_base_free(rp.dns, 1 /** fail requests */);
+
+ tt_int_op(n_replies_left, ==, 0);
+
+end:
+ if (rp.locked)
+ EVLOCK_UNLOCK(rp.lock, 0);
+ EVTHREAD_FREE_LOCK(rp.lock, 0);
+ EVTHREAD_FREE_COND(rp.reqs_cmpl_cond);
+ EVTHREAD_FREE_COND(rp.bw_threads_exited_cond);
+ evdns_close_server_port(dns_port);
+ event_base_loopbreak(rp.base);
+ event_base_free(rp.base);
+}
+#endif
#define DNS_LEGACY(name, flags) \
{ #name, run_legacy_test_fn, flags|TT_LEGACY, &legacy_setup, \
@@ -2138,6 +2323,10 @@ struct testcase_t dns_testcases[] = {
{ "inflight", dns_inflight_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
{ "bufferevent_connect_hostname", test_bufferevent_connect_hostname,
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
+#ifdef EVENT__HAVE_SETRLIMIT
+ { "bufferevent_connect_hostname_emfile", test_bufferevent_connect_hostname,
+ TT_FORK|TT_NEED_BASE, &basic_setup, (char*)"emfile" },
+#endif
{ "disable_when_inactive", dns_disable_when_inactive_test,
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
{ "disable_when_inactive_no_ns", dns_disable_when_inactive_no_ns_test,
@@ -2166,6 +2355,11 @@ struct testcase_t dns_testcases[] = {
{ "client_fail_requests_getaddrinfo",
dns_client_fail_requests_getaddrinfo_test,
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
+#ifdef EVTHREAD_USE_PTHREADS_IMPLEMENTED
+ { "getaddrinfo_race_gotresolve",
+ getaddrinfo_race_gotresolve_test,
+ TT_FORK|TT_OFF_BY_DEFAULT, NULL, NULL },
+#endif
END_OF_TESTCASES
};
diff --git a/test/regress_et.c b/test/regress_et.c
index f75c59b3..5fa87a39 100644
--- a/test/regress_et.c
+++ b/test/regress_et.c
@@ -51,6 +51,14 @@
static int was_et = 0;
+static int base_supports_et(struct event_base *base)
+{
+ return
+ (!strcmp(event_base_get_method(base), "epoll") ||
+ !strcmp(event_base_get_method(base), "epoll (with changelist)") ||
+ !strcmp(event_base_get_method(base), "kqueue"));
+}
+
static void
read_cb(evutil_socket_t fd, short event, void *arg)
{
@@ -67,19 +75,14 @@ read_cb(evutil_socket_t fd, short event, void *arg)
event_del(arg);
}
-#ifdef _WIN32
-#define LOCAL_SOCKETPAIR_AF AF_INET
-#else
-#define LOCAL_SOCKETPAIR_AF AF_UNIX
-#endif
-
static void
-test_edgetriggered(void *et)
+test_edgetriggered(void *data_)
{
+ struct basic_test_data *data = data_;
+ struct event_base *base = data->base;
+ evutil_socket_t *pair = data->pair;
struct event *ev = NULL;
- struct event_base *base = NULL;
const char *test = "test string";
- evutil_socket_t pair[2] = {-1,-1};
int supports_et;
/* On Linux 3.2.1 (at least, as patched by Fedora and tested by Nick),
@@ -88,39 +91,21 @@ test_edgetriggered(void *et)
* get edge-triggered behavior. Yuck! Linux 3.1.9 didn't have this
* problem.
*/
-#ifdef __linux__
- if (evutil_ersatz_socketpair_(AF_INET, SOCK_STREAM, 0, pair) == -1) {
- tt_abort_perror("socketpair");
- }
-#else
- if (evutil_socketpair(LOCAL_SOCKETPAIR_AF, SOCK_STREAM, 0, pair) == -1) {
- tt_abort_perror("socketpair");
- }
-#endif
called = was_et = 0;
tt_int_op(send(pair[0], test, (int)strlen(test)+1, 0), >, 0);
- shutdown(pair[0], EVUTIL_SHUT_WR);
-
- /* Initalize the event library */
- base = event_base_new();
-
- if (!strcmp(event_base_get_method(base), "epoll") ||
- !strcmp(event_base_get_method(base), "epoll (with changelist)") ||
- !strcmp(event_base_get_method(base), "kqueue"))
- supports_et = 1;
- else
- supports_et = 0;
+ tt_int_op(shutdown(pair[0], EVUTIL_SHUT_WR), ==, 0);
+ supports_et = base_supports_et(base);
TT_BLATHER(("Checking for edge-triggered events with %s, which should %s"
"support edge-triggering", event_base_get_method(base),
supports_et?"":"not "));
/* Initalize one event */
ev = event_new(base, pair[1], EV_READ|EV_ET|EV_PERSIST, read_cb, &ev);
-
- event_add(ev, NULL);
+ tt_assert(ev != NULL);
+ tt_int_op(event_add(ev, NULL), ==, 0);
/* We're going to call the dispatch function twice. The first invocation
* will read a single byte from pair[1] in either case. If we're edge
@@ -129,8 +114,8 @@ test_edgetriggered(void *et)
* do nothing. If we're level triggered, the second invocation of
* event_base_loop will also activate the event (because there's still
* data to read). */
- event_base_loop(base,EVLOOP_NONBLOCK|EVLOOP_ONCE);
- event_base_loop(base,EVLOOP_NONBLOCK|EVLOOP_ONCE);
+ tt_int_op(event_base_loop(base,EVLOOP_NONBLOCK|EVLOOP_ONCE), ==, 0);
+ tt_int_op(event_base_loop(base,EVLOOP_NONBLOCK|EVLOOP_ONCE), ==, 0);
if (supports_et) {
tt_int_op(called, ==, 1);
@@ -140,15 +125,11 @@ test_edgetriggered(void *et)
tt_assert(!was_et);
}
- end:
+end:
if (ev) {
event_del(ev);
event_free(ev);
}
- if (base)
- event_base_free(base);
- evutil_closesocket(pair[0]);
- evutil_closesocket(pair[1]);
}
static void
@@ -196,9 +177,94 @@ end:
event_base_free(base);
}
+static int read_notification_count;
+static int last_read_notification_was_et;
+static void
+read_notification_cb(evutil_socket_t fd, short event, void *arg)
+{
+ read_notification_count++;
+ last_read_notification_was_et = (event & EV_ET);
+}
+
+static int write_notification_count;
+static int last_write_notification_was_et;
+static void
+write_notification_cb(evutil_socket_t fd, short event, void *arg)
+{
+ write_notification_count++;
+ last_write_notification_was_et = (event & EV_ET);
+}
+
+/* After two or more events have been registered for the same
+ * file descriptor using EV_ET, if one of the events is
+ * deleted, then the epoll_ctl() call issued by libevent drops
+ * the EPOLLET flag resulting in level triggered
+ * notifications.
+ */
+static void
+test_edge_triggered_multiple_events(void *data_)
+{
+ struct basic_test_data *data = data_;
+ struct event *read_ev = NULL;
+ struct event *write_ev = NULL;
+ const char c = 'A';
+ struct event_base *base = data->base;
+ evutil_socket_t *pair = data->pair;
+
+ if (!base_supports_et(base)) {
+ tt_skip();
+ return;
+ }
+
+ read_notification_count = 0;
+ last_read_notification_was_et = 0;
+ write_notification_count = 0;
+ last_write_notification_was_et = 0;
+
+ /* Make pair[1] readable */
+ tt_int_op(send(pair[0], &c, 1, 0), >, 0);
+
+ read_ev = event_new(base, pair[1], EV_READ|EV_ET|EV_PERSIST,
+ read_notification_cb, NULL);
+ write_ev = event_new(base, pair[1], EV_WRITE|EV_ET|EV_PERSIST,
+ write_notification_cb, NULL);
+
+ event_add(read_ev, NULL);
+ event_add(write_ev, NULL);
+ event_base_loop(base, EVLOOP_NONBLOCK|EVLOOP_ONCE);
+ event_base_loop(base, EVLOOP_NONBLOCK|EVLOOP_ONCE);
+
+ tt_assert(last_read_notification_was_et);
+ tt_int_op(read_notification_count, ==, 1);
+ tt_assert(last_write_notification_was_et);
+ tt_int_op(write_notification_count, ==, 1);
+
+ event_del(read_ev);
+
+ /* trigger acitivity second time for the backend that can have multiple
+ * events for one fd (like kqueue) */
+ close(pair[0]);
+ pair[0] = -1;
+
+ /* Verify that we are still edge-triggered for write notifications */
+ event_base_loop(base, EVLOOP_NONBLOCK|EVLOOP_ONCE);
+ event_base_loop(base, EVLOOP_NONBLOCK|EVLOOP_ONCE);
+ tt_assert(last_write_notification_was_et);
+ tt_int_op(write_notification_count, ==, 2);
+
+end:
+ if (read_ev)
+ event_free(read_ev);
+ if (write_ev)
+ event_free(write_ev);
+}
+
struct testcase_t edgetriggered_testcases[] = {
- { "et", test_edgetriggered, TT_FORK, NULL, NULL },
+ { "et", test_edgetriggered,
+ TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR, &basic_setup, NULL },
{ "et_mix_error", test_edgetriggered_mix_error,
TT_FORK|TT_NEED_SOCKETPAIR|TT_NO_LOGS, &basic_setup, NULL },
+ { "et_multiple_events", test_edge_triggered_multiple_events,
+ TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR, &basic_setup, NULL },
END_OF_TESTCASES
};
diff --git a/test/regress_http.c b/test/regress_http.c
index 80100500..e6d3cdff 100644
--- a/test/regress_http.c
+++ b/test/regress_http.c
@@ -72,6 +72,7 @@ static struct event_base *exit_base;
static char const BASIC_REQUEST_BODY[] = "This is funny";
static void http_basic_cb(struct evhttp_request *req, void *arg);
+static void http_timeout_cb(struct evhttp_request *req, void *arg);
static void http_large_cb(struct evhttp_request *req, void *arg);
static void http_chunked_cb(struct evhttp_request *req, void *arg);
static void http_post_cb(struct evhttp_request *req, void *arg);
@@ -119,7 +120,7 @@ https_bev(struct event_base *base, void *arg)
{
SSL *ssl = SSL_new(get_ssl_ctx());
- SSL_use_certificate(ssl, ssl_getcert());
+ SSL_use_certificate(ssl, ssl_getcert(ssl_getkey()));
SSL_use_PrivateKey(ssl, ssl_getkey());
return bufferevent_openssl_socket_new(
@@ -128,7 +129,8 @@ https_bev(struct event_base *base, void *arg)
}
#endif
static struct evhttp *
-http_setup(ev_uint16_t *pport, struct event_base *base, int mask)
+http_setup_gencb(ev_uint16_t *pport, struct event_base *base, int mask,
+ void (*cb)(struct evhttp_request *, void *), void *cbarg)
{
struct evhttp *myhttp;
@@ -144,8 +146,12 @@ http_setup(ev_uint16_t *pport, struct event_base *base, int mask)
}
#endif
+ evhttp_set_gencb(myhttp, cb, cbarg);
+
/* Register a callback for certain types of requests */
evhttp_set_cb(myhttp, "/test", http_basic_cb, myhttp);
+ evhttp_set_cb(myhttp, "/test nonconformant", http_basic_cb, myhttp);
+ evhttp_set_cb(myhttp, "/timeout", http_timeout_cb, myhttp);
evhttp_set_cb(myhttp, "/large", http_large_cb, base);
evhttp_set_cb(myhttp, "/chunked", http_chunked_cb, base);
evhttp_set_cb(myhttp, "/streamed", http_chunked_cb, base);
@@ -159,6 +165,9 @@ http_setup(ev_uint16_t *pport, struct event_base *base, int mask)
evhttp_set_cb(myhttp, "/", http_dispatcher_cb, base);
return (myhttp);
}
+static struct evhttp *
+http_setup(ev_uint16_t *pport, struct event_base *base, int mask)
+{ return http_setup_gencb(pport, base, mask, NULL, NULL); }
#ifndef NI_MAXSERV
#define NI_MAXSERV 1024
@@ -172,7 +181,7 @@ http_connect(const char *address, ev_uint16_t port)
char strport[NI_MAXSERV];
struct sockaddr *sa;
- int slen;
+ size_t slen;
evutil_socket_t fd;
memset(&ai, 0, sizeof(ai));
@@ -306,12 +315,31 @@ http_basic_cb(struct evhttp_request *req, void *arg)
struct evbuffer *evb = evbuffer_new();
struct evhttp_connection *evcon;
int empty = evhttp_find_header(evhttp_request_get_input_headers(req), "Empty") != NULL;
- event_debug(("%s: called\n", __func__));
+
+ TT_BLATHER(("%s: called\n", __func__));
evbuffer_add_printf(evb, BASIC_REQUEST_BODY);
evcon = evhttp_request_get_connection(req);
tt_assert(evhttp_connection_get_server(evcon) == arg);
+ {
+ const struct sockaddr *sa;
+ char addrbuf[128];
+
+ sa = evhttp_connection_get_addr(evcon);
+ tt_assert(sa);
+
+ if (sa->sa_family == AF_INET) {
+ evutil_format_sockaddr_port_((struct sockaddr *)sa, addrbuf, sizeof(addrbuf));
+ tt_assert(!strncmp(addrbuf, "127.0.0.1:", strlen("127.0.0.1:")));
+ } else if (sa->sa_family == AF_INET6) {
+ evutil_format_sockaddr_port_((struct sockaddr *)sa, addrbuf, sizeof(addrbuf));
+ tt_assert(!strncmp(addrbuf, "[::1]:", strlen("[::1]:")));
+ } else {
+ tt_fail_msg("Unsupported family");
+ }
+ }
+
/* For multi-line headers test */
{
const char *multi =
@@ -346,6 +374,20 @@ end:
evbuffer_free(evb);
}
+static void http_timeout_reply_cb(evutil_socket_t fd, short events, void *arg)
+{
+ struct evhttp_request *req = arg;
+ evhttp_send_reply(req, HTTP_OK, "Everything is fine", NULL);
+ test_ok++;
+}
+static void
+http_timeout_cb(struct evhttp_request *req, void *arg)
+{
+ struct timeval when = { 0, 100 };
+ event_base_once(exit_base, -1, EV_TIMEOUT,
+ http_timeout_reply_cb, req, &when);
+}
+
static void
http_large_cb(struct evhttp_request *req, void *arg)
{
@@ -396,7 +438,7 @@ http_chunked_cb(struct evhttp_request *req, void *arg)
{
struct timeval when = { 0, 0 };
struct chunk_req_state *state = malloc(sizeof(struct chunk_req_state));
- event_debug(("%s: called\n", __func__));
+ TT_BLATHER(("%s: called\n", __func__));
memset(state, 0, sizeof(struct chunk_req_state));
state->req = req;
@@ -414,18 +456,8 @@ http_chunked_cb(struct evhttp_request *req, void *arg)
event_base_once(arg, -1, EV_TIMEOUT, http_chunked_trickle_cb, state, &when);
}
-static void
-http_complete_write(evutil_socket_t fd, short what, void *arg)
-{
- struct bufferevent *bev = arg;
- const char *http_request = "host\r\n"
- "Connection: close\r\n"
- "\r\n";
- bufferevent_write(bev, http_request, strlen(http_request));
-}
-
static struct bufferevent *
-create_bev(struct event_base *base, int fd, int ssl_mask)
+create_bev(struct event_base *base, evutil_socket_t fd, int ssl_mask)
{
int flags = BEV_OPT_DEFER_CALLBACKS;
struct bufferevent *bev = NULL;
@@ -452,19 +484,34 @@ create_bev(struct event_base *base, int fd, int ssl_mask)
}
static void
-http_basic_test_impl(void *arg, int ssl)
+http_half_writecb(struct bufferevent *bev, void *arg)
+{
+ if (evbuffer_get_length(bufferevent_get_output(bev)) == 0) {
+ if (!test_ok) {
+ const char http_request[] = "host\r\n"
+ "Connection: close\r\n"
+ "\r\n";
+ bufferevent_write(bev, http_request, strlen(http_request));
+ }
+ /* enable reading of the reply */
+ bufferevent_enable(bev, EV_READ);
+ test_ok++;
+ }
+}
+
+static void
+http_basic_test_impl(void *arg, int ssl, const char *request_line)
{
struct basic_test_data *data = arg;
- struct timeval tv;
struct bufferevent *bev = NULL;
evutil_socket_t fd;
const char *http_request;
ev_uint16_t port = 0, port2 = 0;
int server_flags = ssl ? HTTP_BIND_SSL : 0;
struct evhttp *http = http_setup(&port, data->base, server_flags);
+ struct evbuffer *out;
exit_base = data->base;
- test_ok = 0;
/* bind to a second socket */
if (http_bind(http, &port2, server_flags) == -1) {
@@ -476,23 +523,18 @@ http_basic_test_impl(void *arg, int ssl)
/* Stupid thing to send a request */
bev = create_bev(data->base, fd, ssl);
- bufferevent_setcb(bev, http_readcb, http_writecb,
+ bufferevent_setcb(bev, http_readcb, http_half_writecb,
http_errorcb, data->base);
+ out = bufferevent_get_output(bev);
/* first half of the http request */
- http_request =
- "GET /test HTTP/1.1\r\n"
- "Host: some";
-
- bufferevent_write(bev, http_request, strlen(http_request));
- evutil_timerclear(&tv);
- tv.tv_usec = 100000;
- event_base_once(data->base,
- -1, EV_TIMEOUT, http_complete_write, bev, &tv);
+ evbuffer_add_printf(out,
+ "%s\r\n"
+ "Host: some", request_line);
+ test_ok = 0;
event_base_dispatch(data->base);
-
- tt_assert(test_ok == 3);
+ tt_int_op(test_ok, ==, 3);
/* connect to the second port */
bufferevent_free(bev);
@@ -504,18 +546,17 @@ http_basic_test_impl(void *arg, int ssl)
bev = create_bev(data->base, fd, ssl);
bufferevent_setcb(bev, http_readcb, http_writecb,
http_errorcb, data->base);
+ out = bufferevent_get_output(bev);
- http_request =
- "GET /test HTTP/1.1\r\n"
+ evbuffer_add_printf(out,
+ "%s\r\n"
"Host: somehost\r\n"
"Connection: close\r\n"
- "\r\n";
-
- bufferevent_write(bev, http_request, strlen(http_request));
+ "\r\n", request_line);
+ test_ok = 0;
event_base_dispatch(data->base);
-
- tt_assert(test_ok == 5);
+ tt_int_op(test_ok, ==, 2);
/* Connect to the second port again. This time, send an absolute uri. */
bufferevent_free(bev);
@@ -536,17 +577,19 @@ http_basic_test_impl(void *arg, int ssl)
bufferevent_write(bev, http_request, strlen(http_request));
+ test_ok = 0;
event_base_dispatch(data->base);
-
- tt_assert(test_ok == 7);
+ tt_int_op(test_ok, ==, 2);
evhttp_free(http);
- end:
+end:
if (bev)
bufferevent_free(bev);
}
-static void http_basic_test(void *arg)
-{ return http_basic_test_impl(arg, 0); }
+static void http_basic_test(void *arg)\
+{ http_basic_test_impl(arg, 0, "GET /test HTTP/1.1"); }
+static void http_basic_trailing_space_test(void *arg)
+{ http_basic_test_impl(arg, 0, "GET /test HTTP/1.1 "); }
static void
@@ -585,7 +628,7 @@ http_badreq_cb(struct evhttp_request *req, void *arg)
static void
http_badreq_errorcb(struct bufferevent *bev, short what, void *arg)
{
- event_debug(("%s: called (what=%04x, arg=%p)", __func__, what, arg));
+ TT_BLATHER(("%s: called (what=%04x, arg=%p)", __func__, what, arg));
/* ignore */
}
@@ -631,7 +674,7 @@ http_badreq_readcb(struct bufferevent *bev, void *arg)
static void
http_badreq_successcb(evutil_socket_t fd, short what, void *arg)
{
- event_debug(("%s: called (what=%04x, arg=%p)", __func__, what, arg));
+ TT_BLATHER(("%s: called (what=%04x, arg=%p)", __func__, what, arg));
event_base_loopexit(exit_base, NULL);
}
@@ -641,7 +684,7 @@ http_bad_request_test(void *arg)
struct basic_test_data *data = arg;
struct timeval tv;
struct bufferevent *bev = NULL;
- evutil_socket_t fd = -1;
+ evutil_socket_t fd = EVUTIL_INVALID_SOCKET;
const char *http_request;
ev_uint16_t port=0, port2=0;
struct evhttp *http = http_setup(&port, data->base, 0);
@@ -655,7 +698,7 @@ http_bad_request_test(void *arg)
/* NULL request test */
fd = http_connect("127.0.0.1", port);
- tt_int_op(fd, >=, 0);
+ tt_assert(fd != EVUTIL_INVALID_SOCKET);
/* Stupid thing to send a request */
bev = bufferevent_socket_new(data->base, fd, 0);
@@ -687,6 +730,7 @@ http_bad_request_test(void *arg)
/* connect to the second port */
fd = http_connect("127.0.0.1", port2);
+ tt_assert(fd != EVUTIL_INVALID_SOCKET);
/* Stupid thing to send a request */
bev = bufferevent_socket_new(data->base, fd, 0);
@@ -747,7 +791,7 @@ http_delete_cb(struct evhttp_request *req, void *arg)
exit(1);
}
- event_debug(("%s: called\n", __func__));
+ TT_BLATHER(("%s: called\n", __func__));
evbuffer_add_printf(evb, BASIC_REQUEST_BODY);
/* allow sending of an empty reply */
@@ -762,7 +806,7 @@ http_delete_test(void *arg)
{
struct basic_test_data *data = arg;
struct bufferevent *bev;
- evutil_socket_t fd = -1;
+ evutil_socket_t fd = EVUTIL_INVALID_SOCKET;
const char *http_request;
ev_uint16_t port = 0;
struct evhttp *http = http_setup(&port, data->base, 0);
@@ -772,7 +816,7 @@ http_delete_test(void *arg)
tt_assert(http);
fd = http_connect("127.0.0.1", port);
- tt_int_op(fd, >=, 0);
+ tt_assert(fd != EVUTIL_INVALID_SOCKET);
/* Stupid thing to send a request */
bev = bufferevent_socket_new(data->base, fd, 0);
@@ -791,7 +835,7 @@ http_delete_test(void *arg)
bufferevent_free(bev);
evutil_closesocket(fd);
- fd = -1;
+ fd = EVUTIL_INVALID_SOCKET;
evhttp_free(http);
@@ -818,7 +862,7 @@ http_sent_cb(struct evhttp_request *req, void *arg)
exit(1);
}
- event_debug(("%s: called\n", __func__));
+ TT_BLATHER(("%s: called\n", __func__));
++test_ok;
}
@@ -830,7 +874,7 @@ http_on_complete_cb(struct evhttp_request *req, void *arg)
evhttp_request_set_on_complete_cb(req, http_sent_cb, (void *)0xDEADBEEF);
- event_debug(("%s: called\n", __func__));
+ TT_BLATHER(("%s: called\n", __func__));
evbuffer_add_printf(evb, BASIC_REQUEST_BODY);
/* allow sending of an empty reply */
@@ -846,7 +890,7 @@ http_on_complete_test(void *arg)
{
struct basic_test_data *data = arg;
struct bufferevent *bev;
- evutil_socket_t fd = -1;
+ evutil_socket_t fd = EVUTIL_INVALID_SOCKET;
const char *http_request;
ev_uint16_t port = 0;
struct evhttp *http = http_setup(&port, data->base, 0);
@@ -855,7 +899,7 @@ http_on_complete_test(void *arg)
test_ok = 0;
fd = http_connect("127.0.0.1", port);
- tt_int_op(fd, >=, 0);
+ tt_assert(fd != EVUTIL_INVALID_SOCKET);
/* Stupid thing to send a request */
bev = bufferevent_socket_new(data->base, fd, 0);
@@ -916,7 +960,7 @@ http_allowed_methods_test(void *arg)
test_ok = 0;
fd1 = http_connect("127.0.0.1", port);
- tt_int_op(fd1, >=, 0);
+ tt_assert(fd1 != EVUTIL_INVALID_SOCKET);
/* GET is out; PATCH is in. */
evhttp_set_allowed_methods(http, EVHTTP_REQ_PATCH);
@@ -938,7 +982,7 @@ http_allowed_methods_test(void *arg)
event_base_dispatch(data->base);
fd2 = http_connect("127.0.0.1", port);
- tt_int_op(fd2, >=, 0);
+ tt_assert(fd2 != EVUTIL_INVALID_SOCKET);
bev2 = bufferevent_socket_new(data->base, fd2, 0);
bufferevent_enable(bev2, EV_READ|EV_WRITE);
@@ -956,7 +1000,7 @@ http_allowed_methods_test(void *arg)
event_base_dispatch(data->base);
fd3 = http_connect("127.0.0.1", port);
- tt_int_op(fd3, >=, 0);
+ tt_assert(fd3 != EVUTIL_INVALID_SOCKET);
bev3 = bufferevent_socket_new(data->base, fd3, 0);
bufferevent_enable(bev3, EV_READ|EV_WRITE);
@@ -1744,6 +1788,7 @@ http_virtual_host_test(void *arg)
/* Now make a raw request with an absolute URI. */
fd = http_connect("127.0.0.1", port);
+ tt_assert(fd != EVUTIL_INVALID_SOCKET);
/* Stupid thing to send a request */
bev = bufferevent_socket_new(data->base, fd, 0);
@@ -1825,7 +1870,7 @@ http_dispatcher_cb(struct evhttp_request *req, void *arg)
{
struct evbuffer *evb = evbuffer_new();
- event_debug(("%s: called\n", __func__));
+ TT_BLATHER(("%s: called\n", __func__));
evbuffer_add_printf(evb, "DISPATCHER_TEST");
evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb);
@@ -1983,7 +2028,7 @@ void
http_post_cb(struct evhttp_request *req, void *arg)
{
struct evbuffer *evb;
- event_debug(("%s: called\n", __func__));
+ TT_BLATHER(("%s: called\n", __func__));
/* Yes, we are expecting a post request */
if (evhttp_request_get_command(req) != EVHTTP_REQ_POST) {
@@ -2100,7 +2145,7 @@ void
http_put_cb(struct evhttp_request *req, void *arg)
{
struct evbuffer *evb;
- event_debug(("%s: called\n", __func__));
+ TT_BLATHER(("%s: called\n", __func__));
/* Expecting a PUT request */
if (evhttp_request_get_command(req) != EVHTTP_REQ_PUT) {
@@ -2186,7 +2231,7 @@ http_failure_test(void *arg)
{
struct basic_test_data *data = arg;
struct bufferevent *bev;
- evutil_socket_t fd = -1;
+ evutil_socket_t fd = EVUTIL_INVALID_SOCKET;
const char *http_request;
ev_uint16_t port = 0;
struct evhttp *http = http_setup(&port, data->base, 0);
@@ -2194,7 +2239,7 @@ http_failure_test(void *arg)
test_ok = 0;
fd = http_connect("127.0.0.1", port);
- tt_int_op(fd, >=, 0);
+ tt_assert(fd != EVUTIL_INVALID_SOCKET);
/* Stupid thing to send a request */
bev = bufferevent_socket_new(data->base, fd, 0);
@@ -2453,6 +2498,27 @@ http_parse_query_test(void *ptr)
end:
evhttp_clear_headers(&headers);
}
+static void
+http_parse_query_str_test(void *ptr)
+{
+ struct evkeyvalq headers;
+ int r;
+
+ TAILQ_INIT(&headers);
+
+ r = evhttp_parse_query_str("http://www.test.com/?q=test", &headers);
+ tt_assert(evhttp_find_header(&headers, "q") == NULL);
+ tt_int_op(r, ==, 0);
+ evhttp_clear_headers(&headers);
+
+ r = evhttp_parse_query_str("q=test", &headers);
+ tt_want(validate_header(&headers, "q", "test") == 0);
+ tt_int_op(r, ==, 0);
+ evhttp_clear_headers(&headers);
+
+end:
+ evhttp_clear_headers(&headers);
+}
static void
http_parse_uri_test(void *ptr)
@@ -2963,7 +3029,7 @@ http_base_test(void *ptr)
http = http_setup(&port, base, 0);
fd = http_connect("127.0.0.1", port);
- tt_int_op(fd, >=, 0);
+ tt_assert(fd != EVUTIL_INVALID_SOCKET);
/* Stupid thing to send a request */
bev = bufferevent_socket_new(base, fd, 0);
@@ -3050,7 +3116,7 @@ http_incomplete_test_(struct basic_test_data *data, int use_timeout, int ssl)
evhttp_set_timeout(http, 1);
fd = http_connect("127.0.0.1", port);
- tt_int_op(fd, >=, 0);
+ tt_assert(fd != EVUTIL_INVALID_SOCKET);
/* Stupid thing to send a request */
bev = create_bev(data->base, fd, ssl);
@@ -3074,7 +3140,7 @@ http_incomplete_test_(struct basic_test_data *data, int use_timeout, int ssl)
bufferevent_free(bev);
if (use_timeout) {
evutil_closesocket(fd);
- fd = -1;
+ fd = EVUTIL_INVALID_SOCKET;
}
evhttp_free(http);
@@ -3267,6 +3333,7 @@ http_chunk_out_test_impl(void *arg, int ssl)
test_ok = 0;
fd = http_connect("127.0.0.1", port);
+ tt_assert(fd != EVUTIL_INVALID_SOCKET);
/* Stupid thing to send a request */
bev = create_bev(data->base, fd, ssl);
@@ -3327,7 +3394,7 @@ http_chunk_out_test_impl(void *arg, int ssl)
evhttp_free(http);
}
static void http_chunk_out_test(void *arg)
-{ return http_chunk_out_test_impl(arg, 0); }
+{ http_chunk_out_test_impl(arg, 0); }
static void
http_stream_out_test_impl(void *arg, int ssl)
@@ -3373,7 +3440,7 @@ http_stream_out_test_impl(void *arg, int ssl)
evhttp_free(http);
}
static void http_stream_out_test(void *arg)
-{ return http_stream_out_test_impl(arg, 0); }
+{ http_stream_out_test_impl(arg, 0); }
static void
http_stream_in_chunk(struct evhttp_request *req, void *arg)
@@ -3569,7 +3636,7 @@ http_connection_fail_test_impl(void *arg, int ssl)
;
}
static void http_connection_fail_test(void *arg)
-{ return http_connection_fail_test_impl(arg, 0); }
+{ http_connection_fail_test_impl(arg, 0); }
static void
http_connection_retry_done(struct evhttp_request *req, void *arg)
@@ -3602,13 +3669,13 @@ http_make_web_server(evutil_socket_t fd, short what, void *arg)
}
static void
-http_simple_test_impl(void *arg, int ssl, int dirty)
+http_simple_test_impl(void *arg, int ssl, int dirty, const char *uri)
{
struct basic_test_data *data = arg;
struct evhttp_connection *evcon = NULL;
struct evhttp_request *req = NULL;
struct bufferevent *bev;
- struct http_server hs = { .port = 0, .ssl = ssl, };
+ struct http_server hs = { 0, ssl, NULL, };
struct evhttp *http = http_setup(&hs.port, data->base, ssl ? HTTP_BIND_SSL : 0);
exit_base = data->base;
@@ -3627,9 +3694,8 @@ http_simple_test_impl(void *arg, int ssl, int dirty)
req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY);
tt_assert(req);
- if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) {
+ if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, uri) == -1)
tt_abort_msg("Couldn't make request");
- }
event_base_dispatch(data->base);
tt_int_op(test_ok, ==, 1);
@@ -3641,7 +3707,9 @@ http_simple_test_impl(void *arg, int ssl, int dirty)
evhttp_free(http);
}
static void http_simple_test(void *arg)
-{ return http_simple_test_impl(arg, 0, 0); }
+{ http_simple_test_impl(arg, 0, 0, "/test"); }
+static void http_simple_nonconformant_test(void *arg)
+{ http_simple_test_impl(arg, 0, 0, "/test nonconformant"); }
static void
http_connection_retry_test_basic(void *arg, const char *addr, struct evdns_base *dns_base, int ssl)
@@ -3651,7 +3719,7 @@ http_connection_retry_test_basic(void *arg, const char *addr, struct evdns_base
struct evhttp_request *req = NULL;
struct timeval tv, tv_start, tv_end;
struct bufferevent *bev;
- struct http_server hs = { .port = 0, .ssl = ssl, };
+ struct http_server hs = { 0, ssl, NULL, };
struct evhttp *http = http_setup(&hs.port, data->base, ssl ? HTTP_BIND_SSL : 0);
exit_base = data->base;
@@ -3798,16 +3866,16 @@ http_connection_retry_conn_address_test_impl(void *arg, int ssl)
/** dnsserver will be cleaned in http_connection_retry_test_basic() */
}
static void http_connection_retry_conn_address_test(void *arg)
-{ return http_connection_retry_conn_address_test_impl(arg, 0); }
+{ http_connection_retry_conn_address_test_impl(arg, 0); }
static void
http_connection_retry_test_impl(void *arg, int ssl)
{
- return http_connection_retry_test_basic(arg, "127.0.0.1", NULL, ssl);
+ http_connection_retry_test_basic(arg, "127.0.0.1", NULL, ssl);
}
static void
http_connection_retry_test(void *arg)
-{ return http_connection_retry_test_impl(arg, 0); }
+{ http_connection_retry_test_impl(arg, 0); }
static void
http_primitives(void *ptr)
@@ -3844,7 +3912,7 @@ http_multi_line_header_test(void *arg)
{
struct basic_test_data *data = arg;
struct bufferevent *bev= NULL;
- evutil_socket_t fd = -1;
+ evutil_socket_t fd = EVUTIL_INVALID_SOCKET;
const char *http_start_request;
ev_uint16_t port = 0;
struct evhttp *http = http_setup(&port, data->base, 0);
@@ -3855,8 +3923,7 @@ http_multi_line_header_test(void *arg)
tt_ptr_op(http, !=, NULL);
fd = http_connect("127.0.0.1", port);
-
- tt_int_op(fd, !=, -1);
+ tt_assert(fd != EVUTIL_INVALID_SOCKET);
/* Stupid thing to send a request */
bev = bufferevent_socket_new(data->base, fd, 0);
@@ -3960,7 +4027,6 @@ http_large_entity_test_done(struct evhttp_request *req, void *arg)
end:
event_base_loopexit(arg, NULL);
}
-#ifndef WIN32
static void
http_expectation_failed_done(struct evhttp_request *req, void *arg)
{
@@ -3969,7 +4035,6 @@ http_expectation_failed_done(struct evhttp_request *req, void *arg)
end:
event_base_loopexit(arg, NULL);
}
-#endif
static void
http_data_length_constraints_test_impl(void *arg, int read_on_write_error)
@@ -3986,38 +4051,32 @@ http_data_length_constraints_test_impl(void *arg, int read_on_write_error)
test_ok = 0;
cb = http_failed_request_done;
-#ifndef WIN32
if (read_on_write_error)
cb = http_data_length_constraints_test_done;
-#endif
tt_assert(continue_size < size);
+ long_str = malloc(size);
+ memset(long_str, 'a', size);
+ long_str[size - 1] = '\0';
+
+ TT_BLATHER(("Creating connection to :%i", port));
evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
tt_assert(evcon);
if (read_on_write_error)
tt_assert(!evhttp_connection_set_flags(evcon, EVHTTP_CON_READ_ON_WRITE_ERROR));
- /* also bind to local host */
evhttp_connection_set_local_address(evcon, "127.0.0.1");
- /*
- * At this point, we want to schedule an HTTP GET request
- * server using our make request method.
- */
+ evhttp_set_max_headers_size(http, size - 1);
+ TT_BLATHER(("Set max header size %zu", size - 1));
req = evhttp_request_new(http_data_length_constraints_test_done, data->base);
tt_assert(req);
-
- long_str = malloc(size);
- memset(long_str, 'a', size);
- long_str[size - 1] = '\0';
- /* Add the information that we care about */
- evhttp_set_max_headers_size(http, size - 1);
evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
evhttp_add_header(evhttp_request_get_output_headers(req), "Longheader", long_str);
-
+ TT_BLATHER(("GET /?arg=val"));
if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/?arg=val") == -1) {
tt_abort_msg("Couldn't make request");
}
@@ -4026,21 +4085,22 @@ http_data_length_constraints_test_impl(void *arg, int read_on_write_error)
req = evhttp_request_new(http_data_length_constraints_test_done, data->base);
tt_assert(req);
evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
-
/* GET /?arg=verylongvalue HTTP/1.1 */
+ TT_BLATHER(("GET %s", long_str));
if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, long_str) == -1) {
tt_abort_msg("Couldn't make request");
}
event_base_dispatch(data->base);
-#ifndef WIN32
+ evhttp_set_max_body_size(http, size - 2);
+ TT_BLATHER(("Set body header size %zu", size - 2));
+
if (read_on_write_error)
cb = http_large_entity_test_done;
-#endif
- evhttp_set_max_body_size(http, size - 2);
req = evhttp_request_new(cb, data->base);
evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
evbuffer_add_printf(evhttp_request_get_output_buffer(req), "%s", long_str);
+ TT_BLATHER(("POST /"));
if (evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/") == -1) {
tt_abort_msg("Couldn't make request");
}
@@ -4050,29 +4110,31 @@ http_data_length_constraints_test_impl(void *arg, int read_on_write_error)
evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
evhttp_add_header(evhttp_request_get_output_headers(req), "Expect", "100-continue");
evbuffer_add_printf(evhttp_request_get_output_buffer(req), "%s", long_str);
+ TT_BLATHER(("POST / (Expect: 100-continue, http_large_entity_test_done)"));
if (evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/") == -1) {
tt_abort_msg("Couldn't make request");
}
event_base_dispatch(data->base);
+ long_str[continue_size] = '\0';
+
req = evhttp_request_new(http_dispatcher_test_done, data->base);
evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
evhttp_add_header(evhttp_request_get_output_headers(req), "Expect", "100-continue");
- long_str[continue_size] = '\0';
evbuffer_add_printf(evhttp_request_get_output_buffer(req), "%s", long_str);
+ TT_BLATHER(("POST / (Expect: 100-continue, http_dispatcher_test_done)"));
if (evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/") == -1) {
tt_abort_msg("Couldn't make request");
}
event_base_dispatch(data->base);
-#ifndef WIN32
if (read_on_write_error)
cb = http_expectation_failed_done;
-#endif
req = evhttp_request_new(cb, data->base);
evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
evhttp_add_header(evhttp_request_get_output_headers(req), "Expect", "101-continue");
evbuffer_add_printf(evhttp_request_get_output_buffer(req), "%s", long_str);
+ TT_BLATHER(("POST / (Expect: 101-continue)"));
if (evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/") == -1) {
tt_abort_msg("Couldn't make request");
}
@@ -4253,7 +4315,7 @@ http_terminate_chunked_test_impl(void *arg, int oneshot)
struct timeval tv;
const char *http_request;
ev_uint16_t port = 0;
- evutil_socket_t fd = -1;
+ evutil_socket_t fd = EVUTIL_INVALID_SOCKET;
struct terminate_state terminate_state;
struct evhttp *http = http_setup(&port, data->base, 0);
@@ -4264,6 +4326,7 @@ http_terminate_chunked_test_impl(void *arg, int oneshot)
terminate_chunked_cb, &terminate_state) == 0);
fd = http_connect("127.0.0.1", port);
+ tt_assert(fd != EVUTIL_INVALID_SOCKET);
/* Stupid thing to send a request */
bev = bufferevent_socket_new(data->base, fd, 0);
@@ -4444,7 +4507,7 @@ http_write_during_read_test_impl(void *arg, int ssl)
ev_uint16_t port = 0;
struct bufferevent *bev = NULL;
struct timeval tv;
- int fd;
+ evutil_socket_t fd;
const char *http_request;
struct evhttp *http = http_setup(&port, data->base, ssl ? HTTP_BIND_SSL : 0);
@@ -4452,6 +4515,7 @@ http_write_during_read_test_impl(void *arg, int ssl)
exit_base = data->base;
fd = http_connect("127.0.0.1", port);
+ tt_assert(fd != EVUTIL_INVALID_SOCKET);
bev = create_bev(data->base, fd, 0);
bufferevent_setcb(bev, NULL, NULL, NULL, data->base);
bufferevent_disable(bev, EV_READ);
@@ -4468,13 +4532,14 @@ http_write_during_read_test_impl(void *arg, int ssl)
event_base_dispatch(data->base);
+end:
if (bev)
bufferevent_free(bev);
if (http)
evhttp_free(http);
}
static void http_write_during_read_test(void *arg)
-{ return http_write_during_read_test_impl(arg, 0); }
+{ http_write_during_read_test_impl(arg, 0); }
static void
http_request_own_test(void *arg)
@@ -4511,6 +4576,81 @@ http_request_own_test(void *arg)
test_ok = 1;
}
+static void http_run_bev_request(struct event_base *base, int port,
+ const char *fmt, ...)
+{
+ struct bufferevent *bev = NULL;
+ va_list ap;
+ evutil_socket_t fd;
+ struct evbuffer *out;
+
+ fd = http_connect("127.0.0.1", port);
+ tt_assert(fd != EVUTIL_INVALID_SOCKET);
+
+ /* Stupid thing to send a request */
+ bev = create_bev(base, fd, 0);
+ bufferevent_setcb(bev, http_readcb, http_writecb,
+ http_errorcb, base);
+ out = bufferevent_get_output(bev);
+
+ va_start(ap, fmt);
+ evbuffer_add_vprintf(out, fmt, ap);
+ va_end(ap);
+
+ event_base_dispatch(base);
+
+end:
+ if (bev)
+ bufferevent_free(bev);
+}
+static void
+http_request_extra_body_test(void *arg)
+{
+ struct basic_test_data *data = arg;
+ struct bufferevent *bev = NULL;
+ ev_uint16_t port = 0;
+ int i;
+ struct evhttp *http =
+ http_setup_gencb(&port, data->base, 0, http_timeout_cb, NULL);
+ struct evbuffer *body = NULL;
+
+ exit_base = data->base;
+ test_ok = 0;
+
+ body = evbuffer_new();
+ for (i = 0; i < 10000; ++i)
+ evbuffer_add_printf(body, "this is the body that HEAD should not have");
+
+ http_run_bev_request(data->base, port,
+ "HEAD /timeout HTTP/1.1\r\n"
+ "Host: somehost\r\n"
+ "Connection: close\r\n"
+ "Content-Length: %i\r\n"
+ "\r\n%s",
+ (int)evbuffer_get_length(body),
+ evbuffer_pullup(body, -1)
+ );
+ tt_assert(test_ok == -2);
+
+ http_run_bev_request(data->base, port,
+ "HEAD /__gencb__ HTTP/1.1\r\n"
+ "Host: somehost\r\n"
+ "Connection: close\r\n"
+ "Content-Length: %i\r\n"
+ "\r\n%s",
+ (int)evbuffer_get_length(body),
+ evbuffer_pullup(body, -1)
+ );
+ tt_assert(test_ok == -2);
+
+ end:
+ evhttp_free(http);
+ if (bev)
+ bufferevent_free(bev);
+ if (body)
+ evbuffer_free(body);
+}
+
#define HTTP_LEGACY(name) \
{ #name, run_legacy_test_fn, TT_ISOLATED|TT_LEGACY, &legacy_setup, \
http_##name##_test }
@@ -4518,6 +4658,8 @@ http_request_own_test(void *arg)
#define HTTP_CAST_ARG(a) ((void *)(a))
#define HTTP_OFF_N(title, name, arg) \
{ #title, http_##name##_test, TT_ISOLATED|TT_OFF_BY_DEFAULT, &basic_setup, HTTP_CAST_ARG(arg) }
+#define HTTP_RET_N(title, name, arg) \
+ { #title, http_##name##_test, TT_ISOLATED|TT_RETRIABLE, &basic_setup, HTTP_CAST_ARG(arg) }
#define HTTP_N(title, name, arg) \
{ #title, http_##name##_test, TT_ISOLATED, &basic_setup, HTTP_CAST_ARG(arg) }
#define HTTP(name) HTTP_N(name, name, NULL)
@@ -4526,35 +4668,35 @@ http_request_own_test(void *arg)
#ifdef EVENT__HAVE_OPENSSL
static void https_basic_test(void *arg)
-{ return http_basic_test_impl(arg, 1); }
+{ http_basic_test_impl(arg, 1, "GET /test HTTP/1.1"); }
static void https_filter_basic_test(void *arg)
-{ return http_basic_test_impl(arg, 1 | HTTP_SSL_FILTER); }
+{ http_basic_test_impl(arg, 1 | HTTP_SSL_FILTER, "GET /test HTTP/1.1"); }
static void https_incomplete_test(void *arg)
{ http_incomplete_test_(arg, 0, 1); }
static void https_incomplete_timeout_test(void *arg)
{ http_incomplete_test_(arg, 1, 1); }
static void https_simple_test(void *arg)
-{ return http_simple_test_impl(arg, 1, 0); }
+{ http_simple_test_impl(arg, 1, 0, "/test"); }
static void https_simple_dirty_test(void *arg)
-{ return http_simple_test_impl(arg, 1, 1); }
+{ http_simple_test_impl(arg, 1, 1, "/test"); }
static void https_connection_retry_conn_address_test(void *arg)
-{ return http_connection_retry_conn_address_test_impl(arg, 1); }
+{ http_connection_retry_conn_address_test_impl(arg, 1); }
static void https_connection_retry_test(void *arg)
-{ return http_connection_retry_test_impl(arg, 1); }
+{ http_connection_retry_test_impl(arg, 1); }
static void https_chunk_out_test(void *arg)
-{ return http_chunk_out_test_impl(arg, 1); }
+{ http_chunk_out_test_impl(arg, 1); }
static void https_filter_chunk_out_test(void *arg)
-{ return http_chunk_out_test_impl(arg, 1 | HTTP_SSL_FILTER); }
+{ http_chunk_out_test_impl(arg, 1 | HTTP_SSL_FILTER); }
static void https_stream_out_test(void *arg)
-{ return http_stream_out_test_impl(arg, 1); }
+{ http_stream_out_test_impl(arg, 1); }
static void https_connection_fail_test(void *arg)
-{ return http_connection_fail_test_impl(arg, 1); }
+{ http_connection_fail_test_impl(arg, 1); }
static void https_write_during_read_test(void *arg)
-{ return http_write_during_read_test_impl(arg, 1); }
+{ http_write_during_read_test_impl(arg, 1); }
static void https_connection_test(void *arg)
-{ return http_connection_test_(arg, 0, "127.0.0.1", NULL, 0, AF_UNSPEC, 1); }
+{ http_connection_test_(arg, 0, "127.0.0.1", NULL, 0, AF_UNSPEC, 1); }
static void https_persist_connection_test(void *arg)
-{ return http_connection_test_(arg, 1, "127.0.0.1", NULL, 0, AF_UNSPEC, 1); }
+{ http_connection_test_(arg, 1, "127.0.0.1", NULL, 0, AF_UNSPEC, 1); }
#endif
struct testcase_t http_testcases[] = {
@@ -4562,24 +4704,27 @@ struct testcase_t http_testcases[] = {
{ "base", http_base_test, TT_FORK, NULL, NULL },
{ "bad_headers", http_bad_header_test, 0, NULL, NULL },
{ "parse_query", http_parse_query_test, 0, NULL, NULL },
+ { "parse_query_str", http_parse_query_str_test, 0, NULL, NULL },
{ "parse_uri", http_parse_uri_test, 0, NULL, NULL },
{ "parse_uri_nc", http_parse_uri_test, 0, &basic_setup, (void*)"nc" },
{ "uriencode", http_uriencode_test, 0, NULL, NULL },
HTTP(basic),
+ HTTP(basic_trailing_space),
HTTP(simple),
+ HTTP(simple_nonconformant),
HTTP_N(cancel, cancel, BASIC),
- HTTP_N(cancel_by_host, cancel, BY_HOST),
- HTTP_N(cancel_by_host_no_ns, cancel, BY_HOST | NO_NS),
- HTTP_N(cancel_by_host_inactive_server, cancel, BY_HOST | INACTIVE_SERVER),
+ HTTP_RET_N(cancel_by_host, cancel, BY_HOST),
+ HTTP_RET_N(cancel_by_host_inactive_server, cancel, BY_HOST | INACTIVE_SERVER),
+ HTTP_RET_N(cancel_by_host_no_ns, cancel, BY_HOST | NO_NS),
HTTP_N(cancel_inactive_server, cancel, INACTIVE_SERVER),
HTTP_N(cancel_by_host_no_ns_inactive_server, cancel, BY_HOST | NO_NS | INACTIVE_SERVER),
HTTP_OFF_N(cancel_by_host_server_timeout, cancel, BY_HOST | INACTIVE_SERVER | SERVER_TIMEOUT),
HTTP_OFF_N(cancel_server_timeout, cancel, INACTIVE_SERVER | SERVER_TIMEOUT),
HTTP_OFF_N(cancel_by_host_no_ns_server_timeout, cancel, BY_HOST | NO_NS | INACTIVE_SERVER | SERVER_TIMEOUT),
HTTP_OFF_N(cancel_by_host_ns_timeout_server_timeout, cancel, BY_HOST | NO_NS | NS_TIMEOUT | INACTIVE_SERVER | SERVER_TIMEOUT),
- HTTP_N(cancel_by_host_ns_timeout, cancel, BY_HOST | NO_NS | NS_TIMEOUT),
- HTTP_N(cancel_by_host_ns_timeout_inactive_server, cancel, BY_HOST | NO_NS | NS_TIMEOUT | INACTIVE_SERVER),
+ HTTP_RET_N(cancel_by_host_ns_timeout, cancel, BY_HOST | NO_NS | NS_TIMEOUT),
+ HTTP_RET_N(cancel_by_host_ns_timeout_inactive_server, cancel, BY_HOST | NO_NS | NS_TIMEOUT | INACTIVE_SERVER),
HTTP(virtual_host),
HTTP(post),
@@ -4630,6 +4775,8 @@ struct testcase_t http_testcases[] = {
HTTP(write_during_read),
HTTP(request_own),
+ HTTP(request_extra_body),
+
#ifdef EVENT__HAVE_OPENSSL
HTTPS(basic),
HTTPS(filter_basic),
@@ -4652,3 +4799,10 @@ struct testcase_t http_testcases[] = {
END_OF_TESTCASES
};
+struct testcase_t http_iocp_testcases[] = {
+ { "simple", http_simple_test, TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, NULL },
+#ifdef EVENT__HAVE_OPENSSL
+ { "https_simple", https_simple_test, TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, NULL },
+#endif
+ END_OF_TESTCASES
+};
diff --git a/test/regress_listener.c b/test/regress_listener.c
index 72f7237b..b60529f2 100644
--- a/test/regress_listener.c
+++ b/test/regress_listener.c
@@ -80,8 +80,9 @@ regress_pick_a_port(void *arg)
ev_socklen_t slen1 = sizeof(ss1), slen2 = sizeof(ss2);
unsigned int flags =
LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_EXEC;
+ evutil_socket_t fd1, fd2, fd3;
- evutil_socket_t fd1 = -1, fd2 = -1, fd3 = -1;
+ fd1 = fd2 = fd3 = EVUTIL_INVALID_SOCKET;
if (data->setup_data && strstr((char*)data->setup_data, "ts")) {
flags |= LEV_OPT_THREADSAFE;
@@ -99,8 +100,8 @@ regress_pick_a_port(void *arg)
flags, -1, (struct sockaddr *)&sin, sizeof(sin));
tt_assert(listener2);
- tt_int_op(evconnlistener_get_fd(listener1), >=, 0);
- tt_int_op(evconnlistener_get_fd(listener2), >=, 0);
+ tt_assert(evconnlistener_get_fd(listener1) != EVUTIL_INVALID_SOCKET);
+ tt_assert(evconnlistener_get_fd(listener2) != EVUTIL_INVALID_SOCKET);
tt_assert(getsockname(evconnlistener_get_fd(listener1),
(struct sockaddr*)&ss1, &slen1) == 0);
tt_assert(getsockname(evconnlistener_get_fd(listener2),
@@ -117,7 +118,7 @@ regress_pick_a_port(void *arg)
tt_ptr_op(evconnlistener_get_base(listener1), ==, base);
tt_ptr_op(evconnlistener_get_base(listener2), ==, base);
- fd1 = fd2 = fd3 = -1;
+ fd1 = fd2 = fd3 = EVUTIL_INVALID_SOCKET;
evutil_socket_connect_(&fd1, (struct sockaddr*)&ss1, slen1);
evutil_socket_connect_(&fd2, (struct sockaddr*)&ss1, slen1);
evutil_socket_connect_(&fd3, (struct sockaddr*)&ss2, slen2);
@@ -185,6 +186,89 @@ end:
evconnlistener_free(listener);
}
+static void
+acceptcb_free(struct evconnlistener *listener, evutil_socket_t fd,
+ struct sockaddr *addr, int socklen, void *arg)
+{
+ int *ptr = arg;
+ --*ptr;
+ TT_BLATHER(("Got one for %p", ptr));
+ evutil_closesocket(fd);
+
+ if (! *ptr)
+ evconnlistener_free(listener);
+}
+static void
+regress_listener_close_accepted_fd(void *arg)
+{
+ struct basic_test_data *data = arg;
+ struct event_base *base = data->base;
+ struct evconnlistener *listener = NULL;
+ struct sockaddr_in sin;
+ struct sockaddr_storage ss;
+ ev_socklen_t slen = sizeof(ss);
+ int count = 1;
+ unsigned int flags = LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE;
+ evutil_socket_t fd = EVUTIL_INVALID_SOCKET;
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */
+ sin.sin_port = 0; /* "You pick!" */
+
+ /* Start a listener with a bogus socket. */
+ listener = evconnlistener_new_bind(base, acceptcb_free, &count,
+ flags, -1, (struct sockaddr *)&sin, sizeof(sin));
+ tt_assert(listener);
+
+ tt_assert(getsockname(evconnlistener_get_fd(listener),
+ (struct sockaddr*)&ss, &slen) == 0);
+ evutil_socket_connect_(&fd, (struct sockaddr*)&ss, slen);
+
+ event_base_dispatch(base);
+
+end:
+ ;
+}
+
+static void
+regress_listener_immediate_close(void *arg)
+{
+ struct basic_test_data *data = arg;
+ struct event_base *base = data->base;
+ struct evconnlistener *listener = NULL;
+ struct sockaddr_in sin;
+ struct sockaddr_storage ss;
+ ev_socklen_t slen = sizeof(ss);
+ int count = 1;
+ unsigned int flags = LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE;
+ evutil_socket_t fd1 = EVUTIL_INVALID_SOCKET, fd2 = EVUTIL_INVALID_SOCKET;
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */
+ sin.sin_port = 0; /* "You pick!" */
+
+ /* Start a listener with a bogus socket. */
+ listener = evconnlistener_new_bind(base, acceptcb, &count,
+ flags, -1, (struct sockaddr *)&sin, sizeof(sin));
+ tt_assert(listener);
+
+ tt_assert(getsockname(evconnlistener_get_fd(listener),
+ (struct sockaddr*)&ss, &slen) == 0);
+
+ evutil_socket_connect_(&fd1, (struct sockaddr*)&ss, slen);
+ evutil_socket_connect_(&fd2, (struct sockaddr*)&ss, slen);
+
+ event_base_dispatch(base);
+
+ tt_int_op(count, ==, 0);
+
+end:
+ if (listener)
+ evconnlistener_free(listener);
+}
+
#ifdef EVENT__HAVE_SETRLIMIT
static void
regress_listener_error_unlock(void *arg)
@@ -242,6 +326,12 @@ struct testcase_t listener_testcases[] = {
TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR,
&basic_setup, (char*)"ts"},
+ { "close_accepted_fd", regress_listener_close_accepted_fd,
+ TT_FORK|TT_NEED_BASE, &basic_setup, NULL, },
+
+ { "immediate_close", regress_listener_immediate_close,
+ TT_FORK|TT_NEED_BASE, &basic_setup, NULL, },
+
END_OF_TESTCASES,
};
diff --git a/test/regress_main.c b/test/regress_main.c
index 44e29111..c9372825 100644
--- a/test/regress_main.c
+++ b/test/regress_main.c
@@ -186,7 +186,7 @@ ignore_log_cb(int s, const char *msg)
{
}
-static void *
+void *
basic_test_setup(const struct testcase_t *testcase)
{
struct event_base *base = NULL;
@@ -262,7 +262,7 @@ basic_test_setup(const struct testcase_t *testcase)
return data;
}
-static int
+int
basic_test_cleanup(const struct testcase_t *testcase, void *ptr)
{
struct basic_test_data *data = ptr;
@@ -384,6 +384,7 @@ struct testgroup_t testgroups[] = {
{ "iocp/", iocp_testcases },
{ "iocp/bufferevent/", bufferevent_iocp_testcases },
{ "iocp/listener/", listener_iocp_testcases },
+ { "iocp/http/", http_iocp_testcases },
#endif
#ifdef EVENT__HAVE_OPENSSL
{ "ssl/", ssl_testcases },
@@ -435,6 +436,7 @@ main(int argc, const char **argv)
#ifdef _WIN32
tinytest_skip(testgroups, "http/connection_retry");
tinytest_skip(testgroups, "http/https_connection_retry");
+ tinytest_skip(testgroups, "http/read_on_write_error");
#endif
#ifndef EVENT__DISABLE_THREAD_SUPPORT
@@ -454,6 +456,11 @@ main(int argc, const char **argv)
evutil_weakrand_seed_(&test_weakrand_state, 0);
+ if (getenv("EVENT_NO_FILE_BUFFERING")) {
+ setbuf(stdout, NULL);
+ setbuf(stderr, NULL);
+ }
+
if (tinytest_main(argc,argv,testgroups))
return 1;
diff --git a/test/regress_rpc.c b/test/regress_rpc.c
index 01a058cb..87a7efa1 100644
--- a/test/regress_rpc.c
+++ b/test/regress_rpc.c
@@ -61,7 +61,6 @@
#include "event2/http_compat.h"
#include "event2/http_struct.h"
#include "event2/rpc.h"
-#include "event2/rpc.h"
#include "event2/rpc_struct.h"
#include "event2/tag.h"
#include "log-internal.h"
@@ -880,6 +879,53 @@ end:
evbuffer_free(tmp);
}
+static void
+rpc_invalid_type(void)
+{
+ ev_uint16_t port;
+ struct evhttp *http = NULL;
+ struct evrpc_base *base = NULL;
+ struct evhttp_connection *evcon = NULL;
+ struct evhttp_request *req = NULL;
+
+ rpc_setup(&http, &port, &base);
+
+ evcon = evhttp_connection_new("127.0.0.1", port);
+ tt_assert(evcon);
+
+ /*
+ * At this point, we want to schedule an HTTP POST request
+ * server using our make request method.
+ */
+
+ req = evhttp_request_new(rpc_postrequest_failure, NULL);
+ tt_assert(req);
+
+ /* Add the information that we care about */
+ evhttp_add_header(req->output_headers, "Host", "somehost");
+ evbuffer_add_printf(req->output_buffer, "Some Nonsense");
+
+ if (evhttp_make_request(evcon, req,
+ EVHTTP_REQ_GET,
+ "/.rpc.Message") == -1) {
+ tt_abort();
+ }
+
+ test_ok = 0;
+
+ event_dispatch();
+
+ evhttp_connection_free(evcon);
+
+ rpc_teardown(base);
+
+ tt_assert(test_ok == 1);
+
+end:
+ evhttp_free(http);
+}
+
+
#define RPC_LEGACY(name) \
{ #name, run_legacy_test_fn, TT_FORK|TT_NEED_BASE|TT_LEGACY, \
&legacy_setup, \
@@ -898,6 +944,7 @@ struct testcase_t rpc_testcases[] = {
RPC_LEGACY(basic_client),
RPC_LEGACY(basic_queued_client),
RPC_LEGACY(basic_client_with_pause),
+ RPC_LEGACY(invalid_type),
RPC_LEGACY(client_timeout),
RPC_LEGACY(test),
diff --git a/test/regress_ssl.c b/test/regress_ssl.c
index 681705fc..68c28114 100644
--- a/test/regress_ssl.c
+++ b/test/regress_ssl.c
@@ -53,7 +53,6 @@
#include "tinytest.h"
#include "tinytest_macros.h"
-#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include "openssl-compat.h"
@@ -119,14 +118,13 @@ end:
}
X509 *
-ssl_getcert(void)
+ssl_getcert(EVP_PKEY *key)
{
/* Dummy code to make a quick-and-dirty valid certificate with
OpenSSL. Don't copy this code into your own program! It does a
number of things in a stupid and insecure way. */
X509 *x509 = NULL;
X509_NAME *name = NULL;
- EVP_PKEY *key = ssl_getkey();
int nid;
time_t now = time(NULL);
@@ -148,6 +146,7 @@ ssl_getcert(void)
X509_set_subject_name(x509, name);
X509_set_issuer_name(x509, name);
+ X509_NAME_free(name);
X509_time_adj(X509_get_notBefore(x509), 0, &now);
now += 3600;
@@ -158,6 +157,7 @@ ssl_getcert(void)
return x509;
end:
X509_free(x509);
+ X509_NAME_free(name);
return NULL;
}
@@ -183,35 +183,86 @@ get_ssl_ctx(void)
return the_ssl_ctx;
}
+static int test_is_done;
+static int n_connected;
+static int got_close;
+static int got_error;
+static int got_timeout;
+static int renegotiate_at = -1;
+static int stop_when_connected;
+static int pending_connect_events;
+static struct event_base *exit_base;
+static X509 *the_cert;
+EVP_PKEY *the_key;
+
void
init_ssl(void)
{
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
SSL_library_init();
ERR_load_crypto_strings();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
if (SSLeay() != OPENSSL_VERSION_NUMBER) {
- TT_DECLARE("WARN", ("Version mismatch for openssl: compiled with %lx but running with %lx", (unsigned long)OPENSSL_VERSION_NUMBER, (unsigned long) SSLeay()));
+ TT_DECLARE("WARN",
+ ("Version mismatch for openssl: compiled with %lx but running with %lx",
+ (unsigned long)OPENSSL_VERSION_NUMBER, (unsigned long)SSLeay()));
}
#endif
}
+static void *
+ssl_test_setup(const struct testcase_t *testcase)
+{
+ init_ssl();
+
+ the_key = ssl_getkey();
+ EVUTIL_ASSERT(the_key);
+
+ the_cert = ssl_getcert(the_key);
+ EVUTIL_ASSERT(the_cert);
+
+ disable_tls_11_and_12 = 0;
+
+ return basic_test_setup(testcase);
+}
+static int
+ssl_test_cleanup(const struct testcase_t *testcase, void *ptr)
+{
+ int ret = basic_test_cleanup(testcase, ptr);
+ if (!ret) {
+ return ret;
+ }
+
+ test_is_done = 0;
+ n_connected = 0;
+ got_close = 0;
+ got_error = 0;
+ got_timeout = 0;
+ renegotiate_at = -1;
+ stop_when_connected = 0;
+ pending_connect_events = 0;
+ exit_base = NULL;
+
+ X509_free(the_cert);
+ EVP_PKEY_free(the_key);
+
+ SSL_CTX_free(the_ssl_ctx);
+ the_ssl_ctx = NULL;
+
+ return 1;
+}
+const struct testcase_setup_t ssl_setup = {
+ ssl_test_setup, ssl_test_cleanup
+};
+
+
/* ====================
Here's a simple test: we read a number from the input, increment it, and
reply, until we get to 1001.
*/
-static int test_is_done = 0;
-static int n_connected = 0;
-static int got_close = 0;
-static int got_error = 0;
-static int got_timeout = 0;
-static int renegotiate_at = -1;
-static int stop_when_connected = 0;
-static int pending_connect_events = 0;
-static struct event_base *exit_base = NULL;
-
enum regress_openssl_type
{
REGRESS_OPENSSL_SOCKETPAIR = 1,
@@ -229,17 +280,19 @@ enum regress_openssl_type
REGRESS_OPENSSL_SLEEP = 1024,
REGRESS_OPENSSL_CLIENT_WRITE = 2048,
+
+ REGRESS_DEFERRED_CALLBACKS = 4096,
};
static void
bufferevent_openssl_check_fd(struct bufferevent *bev, int filter)
{
- tt_int_op(bufferevent_getfd(bev), !=, -1);
- tt_int_op(bufferevent_setfd(bev, -1), ==, 0);
+ tt_fd_op(bufferevent_getfd(bev), !=, EVUTIL_INVALID_SOCKET);
+ tt_fd_op(bufferevent_setfd(bev, EVUTIL_INVALID_SOCKET), ==, 0);
if (filter) {
- tt_int_op(bufferevent_getfd(bev), !=, -1);
+ tt_fd_op(bufferevent_getfd(bev), !=, EVUTIL_INVALID_SOCKET);
} else {
- tt_int_op(bufferevent_getfd(bev), ==, -1);
+ tt_fd_op(bufferevent_getfd(bev), ==, EVUTIL_INVALID_SOCKET);
}
end:
@@ -256,6 +309,13 @@ end:
}
static void
+free_on_cb(struct bufferevent *bev, void *ctx)
+{
+ TT_BLATHER(("free_on_cb: %p", bev));
+ bufferevent_free(bev);
+}
+
+static void
respond_to_number(struct bufferevent *bev, void *ctx)
{
struct evbuffer *b = bufferevent_get_input(bev);
@@ -303,13 +363,14 @@ done_writing_cb(struct bufferevent *bev, void *ctx)
static void
eventcb(struct bufferevent *bev, short what, void *ctx)
{
+ X509 *peer_cert = NULL;
enum regress_openssl_type type;
+
type = (enum regress_openssl_type)ctx;
TT_BLATHER(("Got event %d", (int)what));
if (what & BEV_EVENT_CONNECTED) {
SSL *ssl;
- X509 *peer_cert;
++n_connected;
ssl = bufferevent_openssl_get_ssl(bev);
tt_assert(ssl);
@@ -357,8 +418,10 @@ eventcb(struct bufferevent *bev, short what, void *ctx)
}
bufferevent_free(bev);
}
+
end:
- ;
+ if (peer_cert)
+ X509_free(peer_cert);
}
static void
@@ -398,8 +461,6 @@ regress_bufferevent_openssl(void *arg)
struct bufferevent *bev1, *bev2;
SSL *ssl1, *ssl2;
- X509 *cert = ssl_getcert();
- EVP_PKEY *key = ssl_getkey();
int flags = BEV_OPT_DEFER_CALLBACKS;
struct bufferevent *bev_ll[2] = { NULL, NULL };
evutil_socket_t *fd_pair = NULL;
@@ -407,11 +468,6 @@ regress_bufferevent_openssl(void *arg)
enum regress_openssl_type type;
type = (enum regress_openssl_type)data->setup_data;
- tt_assert(cert);
- tt_assert(key);
-
- init_ssl();
-
if (type & REGRESS_OPENSSL_RENEGOTIATE) {
if (SSLeay() >= 0x10001000 &&
SSLeay() < 0x1000104f) {
@@ -425,8 +481,8 @@ regress_bufferevent_openssl(void *arg)
ssl1 = SSL_new(get_ssl_ctx());
ssl2 = SSL_new(get_ssl_ctx());
- SSL_use_certificate(ssl2, cert);
- SSL_use_PrivateKey(ssl2, key);
+ SSL_use_certificate(ssl2, the_cert);
+ SSL_use_PrivateKey(ssl2, the_key);
if (!(type & REGRESS_OPENSSL_OPEN))
flags |= BEV_OPT_CLOSE_ON_FREE;
@@ -445,7 +501,7 @@ regress_bufferevent_openssl(void *arg)
fd_pair, bev_ll, type);
if (!(type & REGRESS_OPENSSL_FILTER)) {
- tt_int_op(bufferevent_getfd(bev1), ==, data->pair[0]);
+ tt_fd_op(bufferevent_getfd(bev1), ==, data->pair[0]);
} else {
tt_ptr_op(bufferevent_get_underlying(bev1), ==, bev_ll[0]);
}
@@ -504,7 +560,10 @@ regress_bufferevent_openssl(void *arg)
tt_int_op(got_close, ==, 0);
tt_int_op(got_error, ==, 0);
tt_int_op(got_timeout, ==, 1);
+
+ bufferevent_free(bev2);
}
+
end:
return;
}
@@ -526,15 +585,13 @@ acceptcb(struct evconnlistener *listener, evutil_socket_t fd,
type = (enum regress_openssl_type)data->setup_data;
- SSL_use_certificate(ssl, ssl_getcert());
- SSL_use_PrivateKey(ssl, ssl_getkey());
+ SSL_use_certificate(ssl, the_cert);
+ SSL_use_PrivateKey(ssl, the_key);
bev = bufferevent_openssl_socket_new(
- data->base,
- fd,
- ssl,
- BUFFEREVENT_SSL_ACCEPTING,
+ data->base, fd, ssl, BUFFEREVENT_SSL_ACCEPTING,
BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
+ tt_assert(bev);
bufferevent_setcb(bev, respond_to_number, NULL, eventcb,
(void*)(REGRESS_OPENSSL_SERVER));
@@ -550,11 +607,14 @@ acceptcb(struct evconnlistener *listener, evutil_socket_t fd,
/* Only accept once, then disable ourself. */
evconnlistener_disable(listener);
+
+end:
+ ;
}
struct rwcount
{
- int fd;
+ evutil_socket_t fd;
size_t read;
size_t write;
};
@@ -568,6 +628,7 @@ bio_rwcount_new(BIO *b)
static int
bio_rwcount_free(BIO *b)
{
+ TT_BLATHER(("bio_rwcount_free: %p", b));
if (!b)
return 0;
if (BIO_get_shutdown(b)) {
@@ -590,7 +651,6 @@ bio_rwcount_read(BIO *b, char *out, int outlen)
static int
bio_rwcount_write(BIO *b, const char *in, int inlen)
{
-
struct rwcount *rw = BIO_get_data(b);
ev_ssize_t ret = send(rw->fd, in, inlen, 0);
++rw->write;
@@ -602,8 +662,12 @@ bio_rwcount_write(BIO *b, const char *in, int inlen)
static long
bio_rwcount_ctrl(BIO *b, int cmd, long num, void *ptr)
{
+ struct rwcount *rw = BIO_get_data(b);
long ret = 0;
switch (cmd) {
+ case BIO_C_GET_FD:
+ ret = rw->fd;
+ break;
case BIO_CTRL_GET_CLOSE:
ret = BIO_get_shutdown(b);
break;
@@ -672,14 +736,11 @@ regress_bufferevent_openssl_connect(void *arg)
struct sockaddr_storage ss;
ev_socklen_t slen;
SSL *ssl;
- BIO *bio;
struct rwcount rw = { -1, 0, 0 };
enum regress_openssl_type type;
type = (enum regress_openssl_type)data->setup_data;
- init_ssl();
-
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(0x7f000001);
@@ -703,7 +764,7 @@ regress_bufferevent_openssl_connect(void *arg)
BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
tt_assert(bev);
- bufferevent_setcb(bev, respond_to_number, NULL, eventcb,
+ bufferevent_setcb(bev, respond_to_number, free_on_cb, eventcb,
(void*)(REGRESS_OPENSSL_CLIENT));
tt_assert(getsockname(evconnlistener_get_fd(listener),
@@ -716,6 +777,8 @@ regress_bufferevent_openssl_connect(void *arg)
/* Possible only when we have fd, since be_openssl can and will overwrite
* bio otherwise before */
if (type & REGRESS_OPENSSL_SLEEP) {
+ BIO *bio;
+
rw.fd = bufferevent_getfd(bev);
bio = BIO_new_rwcount(0);
tt_assert(bio);
@@ -730,83 +793,279 @@ regress_bufferevent_openssl_connect(void *arg)
tt_int_op(rw.read, <=, 100);
tt_int_op(rw.write, <=, 100);
end:
- ;
+ evconnlistener_free(listener);
+}
+
+struct wm_context
+{
+ int server;
+ int flags;
+ struct evbuffer *data;
+ size_t to_read;
+ size_t wm_high;
+ size_t limit;
+ size_t get;
+ struct bufferevent *bev;
+ struct wm_context *neighbour;
+};
+static void
+wm_transfer(struct bufferevent *bev, void *arg)
+{
+ struct wm_context *ctx = arg;
+ struct evbuffer *in = bufferevent_get_input(bev);
+ struct evbuffer *out = bufferevent_get_output(bev);
+ size_t len = evbuffer_get_length(in);
+ size_t drain = len < ctx->to_read ? len : ctx->to_read;
+
+ if (ctx->get >= ctx->limit) {
+ TT_BLATHER(("wm_transfer-%s(%p): break",
+ ctx->server ? "server" : "client", bev));
+ bufferevent_setcb(bev, NULL, NULL, NULL, NULL);
+ bufferevent_disable(bev, EV_READ);
+ if (ctx->neighbour->get >= ctx->neighbour->limit) {
+ event_base_loopbreak(bufferevent_get_base(bev));
+ }
+ } else {
+ ctx->get += drain;
+ evbuffer_drain(in, drain);
+ }
+
+ TT_BLATHER(("wm_transfer-%s(%p): "
+ "in: " EV_SIZE_FMT ", "
+ "out: " EV_SIZE_FMT ", "
+ "got: " EV_SIZE_FMT "",
+ ctx->server ? "server" : "client", bev,
+ evbuffer_get_length(in),
+ evbuffer_get_length(out),
+ ctx->get));
+
+ evbuffer_add_buffer_reference(out, ctx->data);
+}
+static void
+wm_eventcb(struct bufferevent *bev, short what, void *arg)
+{
+ struct wm_context *ctx = arg;
+ TT_BLATHER(("wm_eventcb-%s(%p): %i",
+ ctx->server ? "server" : "client", bev, what));
+ if (what & BEV_EVENT_CONNECTED) {
+ } else {
+ ctx->get = 0;
+ }
+}
+static void
+wm_acceptcb(struct evconnlistener *listener, evutil_socket_t fd,
+ struct sockaddr *addr, int socklen, void *arg)
+{
+ struct wm_context *ctx = arg;
+ struct bufferevent *bev;
+ struct event_base *base = evconnlistener_get_base(listener);
+ SSL *ssl = SSL_new(get_ssl_ctx());
+
+ SSL_use_certificate(ssl, the_cert);
+ SSL_use_PrivateKey(ssl, the_key);
+
+ bev = bufferevent_openssl_socket_new(
+ base, fd, ssl, BUFFEREVENT_SSL_ACCEPTING, ctx->flags);
+
+ TT_BLATHER(("wm_transfer-%s(%p): accept",
+ ctx->server ? "server" : "client", bev));
+
+ bufferevent_setwatermark(bev, EV_READ, 0, ctx->wm_high);
+ bufferevent_setcb(bev, wm_transfer, NULL, wm_eventcb, ctx);
+ bufferevent_enable(bev, EV_READ|EV_WRITE);
+ ctx->bev = bev;
+
+ /* Only accept once, then disable ourself. */
+ evconnlistener_disable(listener);
+}
+static void
+regress_bufferevent_openssl_wm(void *arg)
+{
+ struct basic_test_data *data = arg;
+ struct event_base *base = data->base;
+
+ struct evconnlistener *listener;
+ struct bufferevent *bev;
+ struct sockaddr_in sin;
+ struct sockaddr_storage ss;
+ enum regress_openssl_type type =
+ (enum regress_openssl_type)data->setup_data;
+ int bev_flags = BEV_OPT_CLOSE_ON_FREE;
+ ev_socklen_t slen;
+ SSL *ssl;
+ struct wm_context client, server;
+ char *payload;
+ size_t payload_len = 1<<10;
+ size_t wm_high = 5<<10;
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = htonl(0x7f000001);
+
+ memset(&ss, 0, sizeof(ss));
+ slen = sizeof(ss);
+
+ if (type & REGRESS_DEFERRED_CALLBACKS)
+ bev_flags |= BEV_OPT_DEFER_CALLBACKS;
+
+ memset(&client, 0, sizeof(client));
+ memset(&server, 0, sizeof(server));
+ client.server = 0;
+ server.server = 1;
+ client.flags = server.flags = bev_flags;
+ client.data = evbuffer_new();
+ server.data = evbuffer_new();
+ payload = calloc(1, payload_len);
+ memset(payload, 'A', payload_len);
+ evbuffer_add(server.data, payload, payload_len);
+ evbuffer_add(client.data, payload, payload_len);
+ client.wm_high = server.wm_high = wm_high;
+ client.limit = server.limit = wm_high<<3;
+ client.to_read = server.to_read = payload_len>>1;
+
+ TT_BLATHER(("openssl_wm: "
+ "payload_len = " EV_SIZE_FMT ", "
+ "wm_high = " EV_SIZE_FMT ", "
+ "limit = " EV_SIZE_FMT ", "
+ "to_read: " EV_SIZE_FMT "",
+ payload_len,
+ wm_high,
+ server.limit,
+ server.to_read));
+
+ listener = evconnlistener_new_bind(base, wm_acceptcb, &server,
+ LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE,
+ -1, (struct sockaddr *)&sin, sizeof(sin));
+
+ tt_assert(listener);
+ tt_assert(evconnlistener_get_fd(listener) >= 0);
+
+ ssl = SSL_new(get_ssl_ctx());
+ tt_assert(ssl);
+
+ if (type & REGRESS_OPENSSL_FILTER) {
+ bev = bufferevent_socket_new(data->base, -1, client.flags);
+ tt_assert(bev);
+ bev = bufferevent_openssl_filter_new(
+ base, bev, ssl, BUFFEREVENT_SSL_CONNECTING, client.flags);
+ } else {
+ bev = bufferevent_openssl_socket_new(
+ data->base, -1, ssl,
+ BUFFEREVENT_SSL_CONNECTING,
+ client.flags);
+ }
+ tt_assert(bev);
+ client.bev = bev;
+
+ server.neighbour = &client;
+ client.neighbour = &server;
+
+ bufferevent_setwatermark(bev, EV_READ, 0, client.wm_high);
+ bufferevent_setcb(bev, wm_transfer, NULL, wm_eventcb, &client);
+
+ tt_assert(getsockname(evconnlistener_get_fd(listener),
+ (struct sockaddr*)&ss, &slen) == 0);
+
+ tt_assert(!bufferevent_socket_connect(bev, (struct sockaddr*)&ss, slen));
+ tt_assert(!evbuffer_add_buffer_reference(bufferevent_get_output(bev), client.data));
+ tt_assert(!bufferevent_enable(bev, EV_READ|EV_WRITE));
+
+ event_base_dispatch(base);
+
+ tt_int_op(client.get, ==, client.limit);
+ tt_int_op(server.get, ==, server.limit);
+end:
+ free(payload);
+ evbuffer_free(client.data);
+ evbuffer_free(server.data);
+ evconnlistener_free(listener);
+ bufferevent_free(client.bev);
+ bufferevent_free(server.bev);
}
struct testcase_t ssl_testcases[] = {
#define T(a) ((void *)(a))
{ "bufferevent_socketpair", regress_bufferevent_openssl,
- TT_ISOLATED, &basic_setup, T(REGRESS_OPENSSL_SOCKETPAIR) },
+ TT_ISOLATED, &ssl_setup, T(REGRESS_OPENSSL_SOCKETPAIR) },
{ "bufferevent_socketpair_write_after_connect", regress_bufferevent_openssl,
- TT_ISOLATED, &basic_setup,
+ TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_SOCKETPAIR|REGRESS_OPENSSL_CLIENT_WRITE) },
{ "bufferevent_filter", regress_bufferevent_openssl,
- TT_ISOLATED, &basic_setup, T(REGRESS_OPENSSL_FILTER) },
+ TT_ISOLATED, &ssl_setup, T(REGRESS_OPENSSL_FILTER) },
{ "bufferevent_filter_write_after_connect", regress_bufferevent_openssl,
- TT_ISOLATED, &basic_setup,
+ TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_FILTER|REGRESS_OPENSSL_CLIENT_WRITE) },
{ "bufferevent_renegotiate_socketpair", regress_bufferevent_openssl,
- TT_ISOLATED, &basic_setup,
+ TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_RENEGOTIATE) },
{ "bufferevent_renegotiate_filter", regress_bufferevent_openssl,
- TT_ISOLATED, &basic_setup,
+ TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_RENEGOTIATE) },
{ "bufferevent_socketpair_startopen", regress_bufferevent_openssl,
- TT_ISOLATED, &basic_setup,
+ TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_OPEN) },
{ "bufferevent_filter_startopen", regress_bufferevent_openssl,
- TT_ISOLATED, &basic_setup,
+ TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_OPEN) },
{ "bufferevent_socketpair_dirty_shutdown", regress_bufferevent_openssl,
- TT_ISOLATED, &basic_setup,
+ TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
{ "bufferevent_filter_dirty_shutdown", regress_bufferevent_openssl,
- TT_ISOLATED, &basic_setup,
+ TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
{ "bufferevent_renegotiate_socketpair_dirty_shutdown",
regress_bufferevent_openssl,
TT_ISOLATED,
- &basic_setup,
+ &ssl_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_RENEGOTIATE | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
{ "bufferevent_renegotiate_filter_dirty_shutdown",
regress_bufferevent_openssl,
TT_ISOLATED,
- &basic_setup,
+ &ssl_setup,
T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_RENEGOTIATE | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
{ "bufferevent_socketpair_startopen_dirty_shutdown",
regress_bufferevent_openssl,
- TT_ISOLATED, &basic_setup,
+ TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_OPEN | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
{ "bufferevent_filter_startopen_dirty_shutdown",
regress_bufferevent_openssl,
- TT_ISOLATED, &basic_setup,
+ TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_OPEN | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
{ "bufferevent_socketpair_fd", regress_bufferevent_openssl,
- TT_ISOLATED, &basic_setup,
+ TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_FD) },
{ "bufferevent_socketpair_freed", regress_bufferevent_openssl,
- TT_ISOLATED, &basic_setup,
+ TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_FREED) },
{ "bufferevent_socketpair_freed_fd", regress_bufferevent_openssl,
- TT_ISOLATED, &basic_setup,
+ TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_FREED | REGRESS_OPENSSL_FD) },
{ "bufferevent_filter_freed_fd", regress_bufferevent_openssl,
- TT_ISOLATED, &basic_setup,
+ TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_FREED | REGRESS_OPENSSL_FD) },
{ "bufferevent_socketpair_timeout", regress_bufferevent_openssl,
- TT_ISOLATED, &basic_setup,
+ TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_TIMEOUT) },
{ "bufferevent_socketpair_timeout_freed_fd", regress_bufferevent_openssl,
- TT_ISOLATED, &basic_setup,
+ TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_TIMEOUT | REGRESS_OPENSSL_FREED | REGRESS_OPENSSL_FD) },
{ "bufferevent_connect", regress_bufferevent_openssl_connect,
- TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
+ TT_FORK|TT_NEED_BASE, &ssl_setup, NULL },
{ "bufferevent_connect_sleep", regress_bufferevent_openssl_connect,
- TT_FORK|TT_NEED_BASE, &basic_setup, T(REGRESS_OPENSSL_SLEEP) },
+ TT_FORK|TT_NEED_BASE, &ssl_setup, T(REGRESS_OPENSSL_SLEEP) },
+
+ { "bufferevent_wm", regress_bufferevent_openssl_wm,
+ TT_FORK|TT_NEED_BASE, &ssl_setup, NULL },
+ { "bufferevent_wm_filter", regress_bufferevent_openssl_wm,
+ TT_FORK|TT_NEED_BASE, &ssl_setup, T(REGRESS_OPENSSL_FILTER) },
+ { "bufferevent_wm_defer", regress_bufferevent_openssl_wm,
+ TT_FORK|TT_NEED_BASE, &ssl_setup, T(REGRESS_DEFERRED_CALLBACKS) },
+ { "bufferevent_wm_filter_defer", regress_bufferevent_openssl_wm,
+ TT_FORK|TT_NEED_BASE, &ssl_setup, T(REGRESS_OPENSSL_FILTER|REGRESS_DEFERRED_CALLBACKS) },
#undef T
diff --git a/test/regress_thread.c b/test/regress_thread.c
index 689c23d1..1e0ce41f 100644
--- a/test/regress_thread.c
+++ b/test/regress_thread.c
@@ -564,8 +564,8 @@ end:
;
}
-#define TEST(name) \
- { #name, thread_##name, TT_FORK|TT_NEED_THREADS|TT_NEED_BASE, \
+#define TEST(name, f) \
+ { #name, thread_##name, TT_FORK|TT_NEED_THREADS|TT_NEED_BASE|(f), \
&basic_setup, NULL }
struct testcase_t thread_testcases[] = {
@@ -575,7 +575,7 @@ struct testcase_t thread_testcases[] = {
{ "forking", thread_basic, TT_FORK|TT_NEED_THREADS|TT_NEED_BASE,
&basic_setup, (char*)"forking" },
#endif
- TEST(conditions_simple),
+ TEST(conditions_simple, TT_RETRIABLE),
{ "deferred_cb_skew", thread_deferred_cb_skew,
TT_FORK|TT_NEED_THREADS|TT_OFF_BY_DEFAULT,
&basic_setup, NULL },
@@ -583,7 +583,7 @@ struct testcase_t thread_testcases[] = {
/****** XXX TODO FIXME windows seems to be having some timing trouble,
* looking into it now. / ellzey
******/
- TEST(no_events),
+ TEST(no_events, TT_RETRIABLE),
#endif
END_OF_TESTCASES
};
diff --git a/test/regress_thread.h b/test/regress_thread.h
index 831b51e5..db0d8d19 100644
--- a/test/regress_thread.h
+++ b/test/regress_thread.h
@@ -28,6 +28,7 @@
#define REGRESS_THREAD_H_INCLUDED_
#ifdef EVENT__HAVE_PTHREADS
+#include <pthread.h>
#define THREAD_T pthread_t
#define THREAD_FN void *
#define THREAD_RETURN() return (NULL)
diff --git a/test/regress_util.c b/test/regress_util.c
index ef6a1487..3da20703 100644
--- a/test/regress_util.c
+++ b/test/regress_util.c
@@ -23,6 +23,10 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+
+/** For event_debug() usage/coverage */
+#define EVENT_VISIBILITY_WANT_DLLIMPORT
+
#include "../util-internal.h"
#ifdef _WIN32
@@ -1412,10 +1416,12 @@ static struct date_rfc1123_case {
{ 1289433600, "Thu, 11 Nov 2010 00:00:00 GMT"},
{ 1323648000, "Mon, 12 Dec 2011 00:00:00 GMT"},
#ifndef _WIN32
+#if EVENT__SIZEOF_TIME_T > 4
/** In win32 case we have max "23:59:59 January 18, 2038, UTC" for time32 */
{ 4294967296, "Sun, 07 Feb 2106 06:28:16 GMT"} /* 2^32 */,
/** In win32 case we have max "23:59:59, December 31, 3000, UTC" for time64 */
{253402300799, "Fri, 31 Dec 9999 23:59:59 GMT"} /* long long future no one can imagine */,
+#endif /* time_t != 32bit */
{ 1456704000, "Mon, 29 Feb 2016 00:00:00 GMT"} /* leap year */,
#endif
{ 1435708800, "Wed, 01 Jul 2015 00:00:00 GMT"} /* leap second */,
@@ -1453,6 +1459,83 @@ end:
;
}
+static void
+test_evutil_v4addr_is_local(void *arg)
+{
+ struct sockaddr_in sin;
+ sin.sin_family = AF_INET;
+
+ /* we use evutil_inet_pton() here to fill in network-byte order */
+#define LOCAL(str, yes) do { \
+ tt_int_op(evutil_inet_pton(AF_INET, str, &sin.sin_addr), ==, 1); \
+ tt_int_op(evutil_v4addr_is_local_(&sin.sin_addr), ==, yes); \
+} while (0)
+
+ /** any */
+ sin.sin_addr.s_addr = INADDR_ANY;
+ tt_int_op(evutil_v4addr_is_local_(&sin.sin_addr), ==, 1);
+
+ /** loopback */
+ sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ tt_int_op(evutil_v4addr_is_local_(&sin.sin_addr), ==, 1);
+ LOCAL("127.0.0.1", 1);
+ LOCAL("127.255.255.255", 1);
+ LOCAL("121.0.0.1", 0);
+
+ /** link-local */
+ LOCAL("169.254.0.1", 1);
+ LOCAL("169.254.255.255", 1);
+ LOCAL("170.0.0.0", 0);
+
+ /** Multicast */
+ LOCAL("224.0.0.0", 1);
+ LOCAL("239.255.255.255", 1);
+ LOCAL("240.0.0.0", 0);
+end:
+ ;
+}
+
+static void
+test_evutil_v6addr_is_local(void *arg)
+{
+ struct sockaddr_in6 sin6;
+ struct in6_addr anyaddr = IN6ADDR_ANY_INIT;
+ struct in6_addr loopback = IN6ADDR_LOOPBACK_INIT;
+
+ sin6.sin6_family = AF_INET6;
+#define LOCAL6(str, yes) do { \
+ tt_int_op(evutil_inet_pton(AF_INET6, str, &sin6.sin6_addr), ==, 1);\
+ tt_int_op(evutil_v6addr_is_local_(&sin6.sin6_addr), ==, yes); \
+} while (0)
+
+ /** any */
+ tt_int_op(evutil_v6addr_is_local_(&anyaddr), ==, 1);
+ LOCAL6("::0", 1);
+
+ /** loopback */
+ tt_int_op(evutil_v6addr_is_local_(&loopback), ==, 1);
+ LOCAL6("::1", 1);
+
+ /** IPV4 mapped */
+ LOCAL6("::ffff:0:0", 1);
+ /** IPv4 translated */
+ LOCAL6("::ffff:0:0:0", 1);
+ /** IPv4/IPv6 translation */
+ LOCAL6("64:ff9b::", 0);
+ /** Link-local */
+ LOCAL6("fe80::", 1);
+ /** Multicast */
+ LOCAL6("ff00::", 1);
+ /** Unspecified */
+ LOCAL6("::", 1);
+
+ /** Global Internet */
+ LOCAL6("2001::", 0);
+ LOCAL6("2001:4860:4802:32::1b", 0);
+end:
+ ;
+}
+
struct testcase_t util_testcases[] = {
{ "ipv4_parse", regress_ipv4_parse, 0, NULL, NULL },
{ "ipv6_parse", regress_ipv6_parse, 0, NULL, NULL },
@@ -1476,14 +1559,16 @@ struct testcase_t util_testcases[] = {
{ "mm_malloc", test_event_malloc, 0, NULL, NULL },
{ "mm_calloc", test_event_calloc, 0, NULL, NULL },
{ "mm_strdup", test_event_strdup, 0, NULL, NULL },
- { "usleep", test_evutil_usleep, 0, NULL, NULL },
+ { "usleep", test_evutil_usleep, TT_RETRIABLE, NULL, NULL },
{ "monotonic_res", test_evutil_monotonic_res, 0, &basic_setup, (void*)"" },
{ "monotonic_res_precise", test_evutil_monotonic_res, TT_OFF_BY_DEFAULT, &basic_setup, (void*)"precise" },
{ "monotonic_res_fallback", test_evutil_monotonic_res, TT_OFF_BY_DEFAULT, &basic_setup, (void*)"fallback" },
{ "monotonic_prc", test_evutil_monotonic_prc, 0, &basic_setup, (void*)"" },
- { "monotonic_prc_precise", test_evutil_monotonic_prc, 0, &basic_setup, (void*)"precise" },
+ { "monotonic_prc_precise", test_evutil_monotonic_prc, TT_RETRIABLE, &basic_setup, (void*)"precise" },
{ "monotonic_prc_fallback", test_evutil_monotonic_prc, 0, &basic_setup, (void*)"fallback" },
{ "date_rfc1123", test_evutil_date_rfc1123, 0, NULL, NULL },
+ { "evutil_v4addr_is_local", test_evutil_v4addr_is_local, 0, NULL, NULL },
+ { "evutil_v6addr_is_local", test_evutil_v6addr_is_local, 0, NULL, NULL },
END_OF_TESTCASES,
};
diff --git a/test/rpcgen_wrapper.sh b/test/rpcgen_wrapper.sh
index aaa03031..fe582d57 100755
--- a/test/rpcgen_wrapper.sh
+++ b/test/rpcgen_wrapper.sh
@@ -25,19 +25,10 @@ exit_failed() {
echo "Could not generate regress.gen.\[ch\] using event_rpcgen.sh" >&2
exit 1
}
-
-if [ -x /usr/bin/python2 ] ; then
- PYTHON2=/usr/bin/python2
-elif [ "x`which python2`" != x ] ; then
- PYTHON2=python2
-else
- PYTHON2=python
-fi
-
srcdir=$1
srcdir=${srcdir:-.}
-${PYTHON2} ${srcdir}/../event_rpcgen.py --quiet ${srcdir}/regress.rpc \
+${srcdir}/../event_rpcgen.py --quiet ${srcdir}/regress.rpc \
test/regress.gen.h test/regress.gen.c
case "$?" in
diff --git a/test/test-fdleak.c b/test/test-fdleak.c
index 4c4eba25..a1fb4ed1 100644
--- a/test/test-fdleak.c
+++ b/test/test-fdleak.c
@@ -95,8 +95,11 @@ server_event_cb(struct bufferevent *bev, short events, void *ctx)
if (events & BEV_EVENT_ERROR) {
my_perror("Error from bufferevent");
exit(1);
- } else if (events & (BEV_EVENT_EOF | BEV_EVENT_ERROR)) {
+ } else if (events & BEV_EVENT_EOF) {
bufferevent_free(bev);
+ if (num_requests == MAX_REQUESTS) {
+ event_base_loopbreak(bufferevent_get_base(bev));
+ }
}
}
@@ -107,8 +110,7 @@ listener_accept_cb(struct evconnlistener *listener, evutil_socket_t sock,
{
struct event_base *base = evconnlistener_get_base(listener);
struct bufferevent *bev = bufferevent_socket_new(base, sock,
- BEV_OPT_CLOSE_ON_FREE);
-
+ BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(bev, server_read_cb, NULL, server_event_cb, NULL);
bufferevent_enable(bev, EV_READ|EV_WRITE);
}
@@ -154,6 +156,9 @@ start_loop(void)
start_client(base);
event_base_dispatch(base);
+
+ evconnlistener_free(listener);
+ event_base_free(base);
}
/*
@@ -178,9 +183,7 @@ client_read_cb(struct bufferevent *bev, void *ctx)
bufferevent_free(bev);
num_requests++;
- if (num_requests == MAX_REQUESTS) {
- event_base_loopbreak(base);
- } else {
+ if (++num_requests < MAX_REQUESTS) {
start_client(base);
}
}
diff --git a/test/test.sh b/test/test.sh
index dd3d9867..f91a8b04 100755
--- a/test/test.sh
+++ b/test/test.sh
@@ -82,8 +82,8 @@ run_tests () {
fi
done
announce_n " test-dumpevents: "
- if python2 -c 'import sys; assert(sys.version_info >= (2, 4))' 2>/dev/null && test -f $TEST_SRC_DIR/check-dumpevents.py; then
- if $TEST_DIR/test-dumpevents | python2 $TEST_SRC_DIR/check-dumpevents.py >> "$TEST_OUTPUT_FILE" ;
+ if python -c 'import sys; assert(sys.version_info >= (2, 4))' 2>/dev/null && test -f $TEST_SRC_DIR/check-dumpevents.py; then
+ if $TEST_DIR/test-dumpevents | $TEST_SRC_DIR/check-dumpevents.py >> "$TEST_OUTPUT_FILE" ;
then
announce OKAY ;
else
diff --git a/test/tinytest.c b/test/tinytest.c
index 3a8e3310..a27a906a 100644
--- a/test/tinytest.c
+++ b/test/tinytest.c
@@ -253,15 +253,12 @@ testcase_run_one(const struct testgroup_t *group,
}
if (outcome == OK) {
- ++n_ok;
if (opt_verbosity>0 && !opt_forked)
puts(opt_verbosity==1?"OK":"");
} else if (outcome == SKIP) {
- ++n_skipped;
if (opt_verbosity>0 && !opt_forked)
puts("SKIPPED");
} else {
- ++n_bad;
if (!opt_forked)
printf("\n [%s FAILED]\n", testcase->name);
}
@@ -428,11 +425,35 @@ tinytest_main(int c, const char **v, struct testgroup_t *groups)
#endif
++in_tinytest_main;
- for (i=0; groups[i].prefix; ++i)
- for (j=0; groups[i].cases[j].name; ++j)
- if (groups[i].cases[j].flags & TT_ENABLED_)
- testcase_run_one(&groups[i],
- &groups[i].cases[j]);
+ for (i = 0; groups[i].prefix; ++i) {
+ struct testgroup_t *group = &groups[i];
+ for (j = 0; group->cases[j].name; ++j) {
+ struct testcase_t *testcase = &group->cases[j];
+ int test_attempts = 3;
+ int test_ret_err;
+
+ if (!(testcase->flags & TT_ENABLED_))
+ continue;
+
+ for (;;) {
+ test_ret_err = testcase_run_one(group, testcase);
+
+ if (test_ret_err == OK)
+ break;
+ if (!(testcase->flags & TT_RETRIABLE))
+ break;
+ printf("\n [RETRYING %s (%i)]\n", testcase->name, test_attempts);
+ if (!test_attempts--)
+ break;
+ }
+
+ switch (test_ret_err) {
+ case OK: ++n_ok; break;
+ case SKIP: ++n_skipped; break;
+ default: ++n_bad; break;
+ }
+ }
+ }
--in_tinytest_main;
diff --git a/test/tinytest.h b/test/tinytest.h
index ed07b26b..d321dd46 100644
--- a/test/tinytest.h
+++ b/test/tinytest.h
@@ -34,8 +34,11 @@
#define TT_ENABLED_ (1<<2)
/** Flag for a test that's off by default. */
#define TT_OFF_BY_DEFAULT (1<<3)
+/** Flag for a test that should be runned again in case of failure (but not
+ * more then 3 times). */
+#define TT_RETRIABLE (1<<4)
/** If you add your own flags, make them start at this point. */
-#define TT_FIRST_USER_FLAG (1<<4)
+#define TT_FIRST_USER_FLAG (1<<5)
typedef void (*testcase_fn)(void *);
diff --git a/test/tinytest_demo.c b/test/tinytest_demo.c
index f6bfd66a..123855ff 100644
--- a/test/tinytest_demo.c
+++ b/test/tinytest_demo.c
@@ -192,6 +192,32 @@ test_timeout(void *ptr)
;
}
+void
+test_timeout_retry(void *ptr)
+{
+ static int i = 0;
+
+ ++i;
+ tt_int_op(i, !=, 1);
+
+ time_t t1, t2;
+ (void)ptr;
+ t1 = time(NULL);
+#ifdef _WIN32
+ Sleep(5000);
+#else
+ sleep(5);
+#endif
+ t2 = time(NULL);
+
+ tt_int_op(t2-t1, >=, 4);
+
+ tt_int_op(t2-t1, <=, 6);
+
+ end:
+ ;
+}
+
/* ============================================================ */
/* Now we need to make sure that our tests get invoked. First, you take
@@ -212,6 +238,10 @@ struct testcase_t demo_tests[] = {
* can enable it manually by passing +demo/timeout at the command line.*/
{ "timeout", test_timeout, TT_OFF_BY_DEFAULT },
+ /* This test will be retried. (and it will not pass from the first
+ * time) */
+ { "timeout_retry", test_timeout_retry, TT_RETRIABLE },
+
/* The array has to end with END_OF_TESTCASES. */
END_OF_TESTCASES
};
diff --git a/test/tinytest_macros.h b/test/tinytest_macros.h
index 2c02a741..e34e74ec 100644
--- a/test/tinytest_macros.h
+++ b/test/tinytest_macros.h
@@ -158,6 +158,14 @@
tt_assert_test_type(a,b,#a" "#op" "#b,long,(val1_ op val2_), \
"%ld",TT_EXIT_TEST_FUNCTION)
+/** To compare SOCKET(windows)/fd */
+#define tt_fd_op(a,op,b) do { \
+ int _a = (int)(a); \
+ int _b = (int)(b); \
+ tt_assert_test_type(_a,_b,#a" "#op" "#b,long,(val1_ op val2_), \
+ "%ld",TT_EXIT_TEST_FUNCTION); \
+} while (0)
+
#define tt_uint_op(a,op,b) \
tt_assert_test_type(a,b,#a" "#op" "#b,unsigned long, \
(val1_ op val2_),"%lu",TT_EXIT_TEST_FUNCTION)
diff --git a/time-internal.h b/time-internal.h
index 2c584fa7..e79e6a52 100644
--- a/time-internal.h
+++ b/time-internal.h
@@ -54,6 +54,7 @@ extern "C" {
#endif
long evutil_tv_to_msec_(const struct timeval *tv);
+EVENT2_EXPORT_SYMBOL
void evutil_usleep_(const struct timeval *tv);
#ifdef _WIN32
@@ -86,8 +87,10 @@ struct evutil_monotonic_timer {
struct timeval last_time;
};
+EVENT2_EXPORT_SYMBOL
int evutil_configure_monotonic_time_(struct evutil_monotonic_timer *mt,
int flags);
+EVENT2_EXPORT_SYMBOL
int evutil_gettime_monotonic_(struct evutil_monotonic_timer *mt, struct timeval *tv);
diff --git a/util-internal.h b/util-internal.h
index 38d0f595..b727bf1f 100644
--- a/util-internal.h
+++ b/util-internal.h
@@ -50,12 +50,34 @@
extern "C" {
#endif
+/* __has_attribute() wrapper */
+#ifdef __has_attribute
+#define EVUTIL_HAS_ATTRIBUTE __has_attribute
+#endif
+/** clang 3 __has_attribute misbehaves in some versions */
+#if defined(__clang__) && \
+ __clang__ == 1 && __clang_major__ == 3 && \
+ (__clang_minor__ >= 2 && __clang_minor__ <= 5)
+#undef EVUTIL_HAS_ATTRIBUTE
+#endif
+#ifndef EVUTIL_HAS_ATTRIBUTE
+#define EVUTIL_HAS_ATTRIBUTE(x) 0
+#endif
+
/* If we need magic to say "inline", get it for free internally. */
#ifdef EVENT__inline
#define inline EVENT__inline
#endif
-#if defined(EVENT____func__) && !defined(__func__)
-#define __func__ EVENT____func__
+
+/* Define to appropriate substitute if compiler doesnt have __func__ */
+#if defined(EVENT__HAVE___func__)
+# ifndef __func__
+# define __func__ __func__
+# endif
+#elif defined(EVENT__HAVE___FUNCTION__)
+# define __func__ __FUNCTION__
+#else
+# define __func__ __FILE__
#endif
/* A good no-op to use in macro definitions. */
@@ -219,19 +241,26 @@ extern "C" {
* when you care about ASCII's notion of character types, because you are about
* to send those types onto the wire.
*/
+EVENT2_EXPORT_SYMBOL
int EVUTIL_ISALPHA_(char c);
+EVENT2_EXPORT_SYMBOL
int EVUTIL_ISALNUM_(char c);
int EVUTIL_ISSPACE_(char c);
+EVENT2_EXPORT_SYMBOL
int EVUTIL_ISDIGIT_(char c);
+EVENT2_EXPORT_SYMBOL
int EVUTIL_ISXDIGIT_(char c);
int EVUTIL_ISPRINT_(char c);
int EVUTIL_ISLOWER_(char c);
int EVUTIL_ISUPPER_(char c);
+EVENT2_EXPORT_SYMBOL
char EVUTIL_TOUPPER_(char c);
+EVENT2_EXPORT_SYMBOL
char EVUTIL_TOLOWER_(char c);
/** Remove all trailing horizontal whitespace (space or tab) from the end of a
* string */
+EVENT2_EXPORT_SYMBOL
void evutil_rtrim_lws_(char *);
@@ -258,13 +287,16 @@ void evutil_rtrim_lws_(char *);
*/
int evutil_open_closeonexec_(const char *pathname, int flags, unsigned mode);
+EVENT2_EXPORT_SYMBOL
int evutil_read_file_(const char *filename, char **content_out, size_t *len_out,
int is_binary);
+EVENT2_EXPORT_SYMBOL
int evutil_socket_connect_(evutil_socket_t *fd_ptr, const struct sockaddr *sa, int socklen);
int evutil_socket_finished_connecting_(evutil_socket_t fd);
+EVENT2_EXPORT_SYMBOL
int evutil_ersatz_socketpair_(int, int , int, evutil_socket_t[]);
int evutil_resolve_(int family, const char *hostname, struct sockaddr *sa,
@@ -289,15 +321,18 @@ struct evutil_weakrand_state {
* attacker can't predict, or which passes strong statistical tests, use the
* evutil_secure_rng* functions instead.
*/
+EVENT2_EXPORT_SYMBOL
ev_uint32_t evutil_weakrand_seed_(struct evutil_weakrand_state *state, ev_uint32_t seed);
/* Return a pseudorandom value between 0 and EVUTIL_WEAKRAND_MAX inclusive.
* Updates the state in 'seed' as needed -- this value must be protected by a
* lock.
*/
+EVENT2_EXPORT_SYMBOL
ev_int32_t evutil_weakrand_(struct evutil_weakrand_state *seed);
/* Return a pseudorandom value x such that 0 <= x < top. top must be no more
* than EVUTIL_WEAKRAND_MAX. Updates the state in 'seed' as needed -- this
* value must be proteced by a lock */
+EVENT2_EXPORT_SYMBOL
ev_int32_t evutil_weakrand_range_(struct evutil_weakrand_state *seed, ev_int32_t top);
/* Evaluates to the same boolean value as 'p', and hints to the compiler that
@@ -308,6 +343,12 @@ ev_int32_t evutil_weakrand_range_(struct evutil_weakrand_state *seed, ev_int32_t
#define EVUTIL_UNLIKELY(p) (p)
#endif
+#if EVUTIL_HAS_ATTRIBUTE(fallthrough)
+#define EVUTIL_FALLTHROUGH __attribute__((fallthrough))
+#else
+#define EVUTIL_FALLTHROUGH /* fallthrough */
+#endif
+
/* Replacement for assert() that calls event_errx on failure. */
#ifdef NDEBUG
#define EVUTIL_ASSERT(cond) EVUTIL_NIL_CONDITION_(cond)
@@ -357,16 +398,22 @@ typedef struct evdns_getaddrinfo_request* (*evdns_getaddrinfo_fn)(
const char *nodename, const char *servname,
const struct evutil_addrinfo *hints_in,
void (*cb)(int, struct evutil_addrinfo *, void *), void *arg);
+EVENT2_EXPORT_SYMBOL
void evutil_set_evdns_getaddrinfo_fn_(evdns_getaddrinfo_fn fn);
typedef void (*evdns_getaddrinfo_cancel_fn)(
struct evdns_getaddrinfo_request *req);
+EVENT2_EXPORT_SYMBOL
void evutil_set_evdns_getaddrinfo_cancel_fn_(evdns_getaddrinfo_cancel_fn fn);
+EVENT2_EXPORT_SYMBOL
struct evutil_addrinfo *evutil_new_addrinfo_(struct sockaddr *sa,
ev_socklen_t socklen, const struct evutil_addrinfo *hints);
+EVENT2_EXPORT_SYMBOL
struct evutil_addrinfo *evutil_addrinfo_append_(struct evutil_addrinfo *first,
struct evutil_addrinfo *append);
+EVENT2_EXPORT_SYMBOL
void evutil_adjust_hints_for_addrconfig_(struct evutil_addrinfo *hints);
+EVENT2_EXPORT_SYMBOL
int evutil_getaddrinfo_common_(const char *nodename, const char *servname,
struct evutil_addrinfo *hints, struct evutil_addrinfo **res, int *portnum);
@@ -379,6 +426,7 @@ void evutil_getaddrinfo_cancel_async_(struct evdns_getaddrinfo_request *data);
/** Return true iff sa is a looback address. (That is, it is 127.0.0.1/8, or
* ::1). */
+EVENT2_EXPORT_SYMBOL
int evutil_sockaddr_is_loopback_(const struct sockaddr *sa);
@@ -387,6 +435,7 @@ int evutil_sockaddr_is_loopback_(const struct sockaddr *sa);
Returns a pointer to out. Always writes something into out, so it's safe
to use the output of this function without checking it for NULL.
*/
+EVENT2_EXPORT_SYMBOL
const char *evutil_format_sockaddr_port_(const struct sockaddr *sa, char *out, size_t outlen);
int evutil_hex_char_to_int_(char c);
@@ -396,6 +445,7 @@ void evutil_free_secure_rng_globals_(void);
void evutil_free_globals_(void);
#ifdef _WIN32
+EVENT2_EXPORT_SYMBOL
HMODULE evutil_load_windows_system_library_(const TCHAR *library_name);
#endif
@@ -444,6 +494,7 @@ HMODULE evutil_load_windows_system_library_(const TCHAR *library_name);
#endif
#endif
+EVENT2_EXPORT_SYMBOL
evutil_socket_t evutil_socket_(int domain, int type, int protocol);
evutil_socket_t evutil_accept4_(evutil_socket_t sockfd, struct sockaddr *addr,
ev_socklen_t *addrlen, int flags);
@@ -476,6 +527,17 @@ evutil_socket_t evutil_eventfd_(unsigned initval, int flags);
void evutil_memclear_(void *mem, size_t len);
+struct in_addr;
+struct in6_addr;
+
+/* This is a any, loopback, link-local, multicast */
+EVENT2_EXPORT_SYMBOL
+int evutil_v4addr_is_local_(const struct in_addr *in);
+/* This is a reserved, ipv4compat, ipv4map, loopback,
+ * link-local, multicast, or unspecified address. */
+EVENT2_EXPORT_SYMBOL
+int evutil_v6addr_is_local_(const struct in6_addr *in);
+
#ifdef __cplusplus
}
#endif
diff --git a/win32select.c b/win32select.c
index 1766858c..0ddfe4b4 100644
--- a/win32select.c
+++ b/win32select.c
@@ -326,6 +326,8 @@ win32_dispatch(struct event_base *base, struct timeval *tv)
event_debug(("%s: select returned %d", __func__, res));
if (res <= 0) {
+ event_debug(("%s: %s", __func__,
+ evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR())));
return res;
}