mirror of
https://github.com/libevent/libevent.git
synced 2025-01-31 09:12:55 +08:00
commit
01c7b45111
6
.gitignore
vendored
6
.gitignore
vendored
@ -23,6 +23,9 @@
|
|||||||
*.gcov
|
*.gcov
|
||||||
*.gcda
|
*.gcda
|
||||||
|
|
||||||
|
# gdb stuff
|
||||||
|
.gdb_history
|
||||||
|
|
||||||
# Autotools stuff
|
# Autotools stuff
|
||||||
.deps
|
.deps
|
||||||
.dirstamp
|
.dirstamp
|
||||||
@ -36,6 +39,7 @@ Makefile.in
|
|||||||
|
|
||||||
# ctags stuff
|
# ctags stuff
|
||||||
TAGS
|
TAGS
|
||||||
|
tags
|
||||||
|
|
||||||
# Stuff made by our makefiles
|
# Stuff made by our makefiles
|
||||||
libevent.pc
|
libevent.pc
|
||||||
@ -80,10 +84,12 @@ libevent_openssl.pc
|
|||||||
/sample/event-read-fifo
|
/sample/event-read-fifo
|
||||||
/sample/hello-world
|
/sample/hello-world
|
||||||
/sample/http-server
|
/sample/http-server
|
||||||
|
/sample/http-connect
|
||||||
/sample/le-proxy
|
/sample/le-proxy
|
||||||
/sample/https-client
|
/sample/https-client
|
||||||
/sample/signal-test
|
/sample/signal-test
|
||||||
/sample/time-test
|
/sample/time-test
|
||||||
|
/sample/event-test
|
||||||
|
|
||||||
/test-driver
|
/test-driver
|
||||||
/test/bench
|
/test/bench
|
||||||
|
@ -3,7 +3,9 @@ env:
|
|||||||
- EVENT_BUILD_METHOD=cmake EVENT_CMAKE_OPTIONS=""
|
- EVENT_BUILD_METHOD=cmake EVENT_CMAKE_OPTIONS=""
|
||||||
- EVENT_BUILD_METHOD=cmake EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_OPENSSL=ON"
|
- EVENT_BUILD_METHOD=cmake EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_OPENSSL=ON"
|
||||||
- EVENT_BUILD_METHOD=cmake EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_THREAD_SUPPORT=ON"
|
- EVENT_BUILD_METHOD=cmake EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_THREAD_SUPPORT=ON"
|
||||||
- EVENT_BUILD_METHOD=autotools
|
- EVENT_BUILD_METHOD=cmake EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_DEBUG_MODE=ON"
|
||||||
|
- EVENT_BUILD_METHOD=autotools EVENT_CONFIGURE_OPTIONS=""
|
||||||
|
- EVENT_BUILD_METHOD=autotools EVENT_CONFIGURE_OPTIONS="--disable-debug-mode"
|
||||||
language: c
|
language: c
|
||||||
compiler:
|
compiler:
|
||||||
- gcc
|
- gcc
|
||||||
@ -12,5 +14,8 @@ install:
|
|||||||
- sudo apt-get update -qq
|
- sudo apt-get update -qq
|
||||||
- sudo apt-get install -y -qq zlib1g-dev libssl-dev build-essential automake autoconf cmake
|
- sudo apt-get install -y -qq zlib1g-dev libssl-dev build-essential automake autoconf cmake
|
||||||
script:
|
script:
|
||||||
- if [ "$EVENT_BUILD_METHOD" = "autotools" ]; then ./autogen.sh && ./configure && make && make verify; fi
|
- if [ "$EVENT_BUILD_METHOD" = "autotools" ]; then ./autogen.sh && ./configure $EVENT_CONFIGURE_OPTIONS && make && make verify; fi
|
||||||
- if [ "$EVENT_BUILD_METHOD" = "cmake" ]; then mkdir build && cd build && cmake .. $EVENT_CMAKE_OPTIONS && cmake --build . && CTEST_OUTPUT_ON_FAILURE=1 cmake --build . --target verify; fi
|
- if [ "$EVENT_BUILD_METHOD" = "cmake" ]; then mkdir build && cd build && cmake .. $EVENT_CMAKE_OPTIONS && cmake --build . && CTEST_OUTPUT_ON_FAILURE=1 cmake --build . --target verify; fi
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
irc: "irc.oftc.net#libevent"
|
||||||
|
685
CMakeLists.txt
685
CMakeLists.txt
File diff suppressed because it is too large
Load Diff
77
README.md
77
README.md
@ -1,3 +1,14 @@
|
|||||||
|
<p align="center">
|
||||||
|
<img src="https://strcpy.net/libevent3.png" alt="libevent logo"/>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[![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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 0. BUILDING AND INSTALLATION (Briefly)
|
# 0. BUILDING AND INSTALLATION (Briefly)
|
||||||
|
|
||||||
## Autoconf
|
## Autoconf
|
||||||
@ -7,6 +18,72 @@
|
|||||||
$ make verify # (optional)
|
$ make verify # (optional)
|
||||||
$ sudo make install
|
$ sudo make install
|
||||||
|
|
||||||
|
## Cmake (General)
|
||||||
|
|
||||||
|
|
||||||
|
The following Libevent specific Cmake variables ar as follows (the values being
|
||||||
|
the default).
|
||||||
|
|
||||||
|
```
|
||||||
|
# Installation directory for executables
|
||||||
|
EVENT_INSTALL_BIN_DIR:PATH=bin
|
||||||
|
|
||||||
|
# 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
|
||||||
|
EVENT__DISABLE_BENCHMARK:BOOL=OFF
|
||||||
|
|
||||||
|
# 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
|
||||||
|
EVENT__DISABLE_MM_REPLACEMENT:BOOL=OFF
|
||||||
|
|
||||||
|
# Define if libevent should build without support for OpenSSL encrpytion
|
||||||
|
EVENT__DISABLE_OPENSSL:BOOL=ON
|
||||||
|
|
||||||
|
# Disable the regress tests
|
||||||
|
EVENT__DISABLE_REGRESS:BOOL=OFF
|
||||||
|
|
||||||
|
# Disable sample files
|
||||||
|
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
|
||||||
|
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
|
||||||
|
# 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
|
||||||
|
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>`__
|
||||||
|
|
||||||
|
|
||||||
## CMake (Windows)
|
## CMake (Windows)
|
||||||
|
|
||||||
Install CMake: <http://www.cmake.org>
|
Install CMake: <http://www.cmake.org>
|
||||||
|
48
appveyor.yml
48
appveyor.yml
@ -1,11 +1,45 @@
|
|||||||
|
version: 2.1.5.{build}
|
||||||
|
shallow_clone: true
|
||||||
|
|
||||||
|
os: Visual Studio 2015 RC
|
||||||
|
|
||||||
|
build:
|
||||||
|
verbosity: detailed
|
||||||
|
|
||||||
|
environment:
|
||||||
|
global:
|
||||||
|
CYG_ROOT: C:/MinGW/msys/1.0
|
||||||
|
|
||||||
|
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%'
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- appveyor DownloadFile http://slproweb.com/download/Win32OpenSSL-1_0_1L.exe
|
- set PATH=%PATH%;C:\MinGW\msys\1.0\bin;C:\MinGW\bin
|
||||||
- Win32OpenSSL-1_0_1L.exe /silent /verysilent /sp- /suppressmsgboxes
|
- appveyor DownloadFile https://strcpy.net/packages/Win32OpenSSL-1_0_2a.exe
|
||||||
|
- Win32OpenSSL-1_0_2a.exe /silent /verysilent /sp- /suppressmsgboxes
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
- md build
|
- cmd: 'echo Cygwin root is: %CYG_ROOT%'
|
||||||
- cd build
|
- cmd: 'echo Build folder is: %APPVEYOR_BUILD_FOLDER%'
|
||||||
- cmake ..
|
- cmd: 'echo Repo build branch is: %APPVEYOR_REPO_BRANCH%'
|
||||||
- cmake --build .
|
- cmd: 'echo Repo build commit is: %APPVEYOR_REPO_COMMIT%'
|
||||||
- ctest --output-on-failure
|
- cmd: "echo installing stuff"
|
||||||
|
- cmd: 'echo "C:\MinGW /mingw" >%CYG_ROOT%/etc/fstab'
|
||||||
|
- cmd: 'C:\MinGW\bin\mingw-get install autotools autoconf automake python'
|
||||||
|
- cmd: 'echo Autogen running...'
|
||||||
|
- cmd: '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null;mount C:/MinGW /mingw; bash -x ./autogen.sh; ./configure; make; make verify"'
|
||||||
|
|
||||||
|
#install:
|
||||||
|
# - appveyor DownloadFile https://strcpy.net/packages/Win32OpenSSL-1_0_2a.exe
|
||||||
|
# - Win32OpenSSL-1_0_2a.exe /silent /verysilent /sp- /suppressmsgboxes
|
||||||
|
#build_script:
|
||||||
|
# - md build
|
||||||
|
# - cd build
|
||||||
|
# - cmake ..
|
||||||
|
# - cmake --build .
|
||||||
|
# - ctest --output-on-failure
|
||||||
cache:
|
cache:
|
||||||
- C:\OpenSSL-Win32
|
- C:\OpenSSL-Win32
|
||||||
|
4
buffer.c
4
buffer.c
@ -184,7 +184,7 @@ evbuffer_chain_new(size_t size)
|
|||||||
/* this way we can manipulate the buffer to different addresses,
|
/* this way we can manipulate the buffer to different addresses,
|
||||||
* which is required for mmap for example.
|
* which is required for mmap for example.
|
||||||
*/
|
*/
|
||||||
chain->buffer = EVBUFFER_CHAIN_EXTRA(u_char, chain);
|
chain->buffer = EVBUFFER_CHAIN_EXTRA(unsigned char, chain);
|
||||||
|
|
||||||
chain->refcnt = 1;
|
chain->refcnt = 1;
|
||||||
|
|
||||||
@ -2909,7 +2909,7 @@ evbuffer_add_reference(struct evbuffer *outbuf,
|
|||||||
if (!chain)
|
if (!chain)
|
||||||
return (-1);
|
return (-1);
|
||||||
chain->flags |= EVBUFFER_REFERENCE | EVBUFFER_IMMUTABLE;
|
chain->flags |= EVBUFFER_REFERENCE | EVBUFFER_IMMUTABLE;
|
||||||
chain->buffer = (u_char *)data;
|
chain->buffer = (unsigned char *)data;
|
||||||
chain->buffer_len = datlen;
|
chain->buffer_len = datlen;
|
||||||
chain->off = datlen;
|
chain->off = datlen;
|
||||||
|
|
||||||
|
@ -40,6 +40,17 @@ extern "C" {
|
|||||||
#include "ratelim-internal.h"
|
#include "ratelim-internal.h"
|
||||||
#include "event2/bufferevent_struct.h"
|
#include "event2/bufferevent_struct.h"
|
||||||
|
|
||||||
|
#include "ipv6-internal.h"
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
#endif
|
||||||
|
#ifdef EVENT__HAVE_NETINET_IN_H
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
#ifdef EVENT__HAVE_NETINET_IN6_H
|
||||||
|
#include <netinet/in6.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* These flags are reasons that we might be declining to actually enable
|
/* These flags are reasons that we might be declining to actually enable
|
||||||
reading or writing on a bufferevent.
|
reading or writing on a bufferevent.
|
||||||
*/
|
*/
|
||||||
@ -205,6 +216,18 @@ struct bufferevent_private {
|
|||||||
|
|
||||||
/** Rate-limiting information for this bufferevent */
|
/** Rate-limiting information for this bufferevent */
|
||||||
struct bufferevent_rate_limit *rate_limiting;
|
struct bufferevent_rate_limit *rate_limiting;
|
||||||
|
|
||||||
|
/* Saved conn_addr, to extract IP address from it.
|
||||||
|
*
|
||||||
|
* Because some servers may reset/close connection without waiting clients,
|
||||||
|
* in that case we can't extract IP address even in close_cb.
|
||||||
|
* So we need to save it, just after we connected to remote server, or
|
||||||
|
* after resolving (to avoid extra dns requests during retrying, since UDP
|
||||||
|
* is slow) */
|
||||||
|
union {
|
||||||
|
struct sockaddr_in6 in6;
|
||||||
|
struct sockaddr_in in;
|
||||||
|
} conn_address;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Possible operations for a control callback. */
|
/** Possible operations for a control callback. */
|
||||||
@ -327,14 +350,17 @@ int bufferevent_disable_hard_(struct bufferevent *bufev, short event);
|
|||||||
/** Internal: Set up locking on a bufferevent. If lock is set, use it.
|
/** Internal: Set up locking on a bufferevent. If lock is set, use it.
|
||||||
* Otherwise, use a new lock. */
|
* Otherwise, use a new lock. */
|
||||||
int bufferevent_enable_locking_(struct bufferevent *bufev, void *lock);
|
int bufferevent_enable_locking_(struct bufferevent *bufev, void *lock);
|
||||||
/** Internal: Increment the reference count on bufev. */
|
/** Internal: backwards compat macro for the now public function
|
||||||
void bufferevent_incref_(struct bufferevent *bufev);
|
* Increment the reference count on bufev. */
|
||||||
|
#define bufferevent_incref_(bufev) bufferevent_incref(bufev)
|
||||||
/** Internal: Lock bufev and increase its reference count.
|
/** Internal: Lock bufev and increase its reference count.
|
||||||
* unlocking it otherwise. */
|
* unlocking it otherwise. */
|
||||||
void bufferevent_incref_and_lock_(struct bufferevent *bufev);
|
void bufferevent_incref_and_lock_(struct bufferevent *bufev);
|
||||||
/** Internal: Decrement the reference count on bufev. Returns 1 if it freed
|
/** Internal: backwards compat macro for the now public function
|
||||||
|
* Decrement the reference count on bufev. Returns 1 if it freed
|
||||||
* the bufferevent.*/
|
* the bufferevent.*/
|
||||||
int bufferevent_decref_(struct bufferevent *bufev);
|
#define bufferevent_decref_(bufev) bufferevent_decref(bufev)
|
||||||
|
|
||||||
/** Internal: Drop the reference count on bufev, freeing as necessary, and
|
/** Internal: Drop the reference count on bufev, freeing as necessary, and
|
||||||
* unlocking it otherwise. Returns 1 if it freed the bufferevent. */
|
* unlocking it otherwise. Returns 1 if it freed the bufferevent. */
|
||||||
int bufferevent_decref_and_unlock_(struct bufferevent *bufev);
|
int bufferevent_decref_and_unlock_(struct bufferevent *bufev);
|
||||||
@ -386,9 +412,13 @@ void bufferevent_init_generic_timeout_cbs_(struct bufferevent *bev);
|
|||||||
* we delete it.) Call this from anything that changes the timeout values,
|
* 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. */
|
* that enabled EV_READ or EV_WRITE, or that disables EV_READ or EV_WRITE. */
|
||||||
int bufferevent_generic_adj_timeouts_(struct bufferevent *bev);
|
int bufferevent_generic_adj_timeouts_(struct bufferevent *bev);
|
||||||
|
int bufferevent_generic_adj_existing_timeouts_(struct bufferevent *bev);
|
||||||
|
|
||||||
enum bufferevent_options bufferevent_get_options_(struct bufferevent *bev);
|
enum bufferevent_options bufferevent_get_options_(struct bufferevent *bev);
|
||||||
|
|
||||||
|
const struct sockaddr*
|
||||||
|
bufferevent_socket_get_conn_address_(struct bufferevent *bev);
|
||||||
|
|
||||||
/** Internal use: We have just successfully read data into an inbuf, so
|
/** Internal use: We have just successfully read data into an inbuf, so
|
||||||
* reset the read timeout (if any). */
|
* reset the read timeout (if any). */
|
||||||
#define BEV_RESET_GENERIC_READ_TIMEOUT(bev) \
|
#define BEV_RESET_GENERIC_READ_TIMEOUT(bev) \
|
||||||
|
@ -777,7 +777,7 @@ bufferevent_finalize_cb_(struct event_callback *evcb, void *arg_)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
bufferevent_decref_(struct bufferevent *bufev)
|
bufferevent_decref(struct bufferevent *bufev)
|
||||||
{
|
{
|
||||||
BEV_LOCK(bufev);
|
BEV_LOCK(bufev);
|
||||||
return bufferevent_decref_and_unlock_(bufev);
|
return bufferevent_decref_and_unlock_(bufev);
|
||||||
@ -793,11 +793,15 @@ bufferevent_free(struct bufferevent *bufev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
bufferevent_incref_(struct bufferevent *bufev)
|
bufferevent_incref(struct bufferevent *bufev)
|
||||||
{
|
{
|
||||||
struct bufferevent_private *bufev_private =
|
struct bufferevent_private *bufev_private =
|
||||||
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
|
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
|
||||||
|
|
||||||
|
/* XXX: now that this function is public, we might want to
|
||||||
|
* - return the count from this function
|
||||||
|
* - create a new function to atomically grab the current refcount
|
||||||
|
*/
|
||||||
BEV_LOCK(bufev);
|
BEV_LOCK(bufev);
|
||||||
++bufev_private->refcnt;
|
++bufev_private->refcnt;
|
||||||
BEV_UNLOCK(bufev);
|
BEV_UNLOCK(bufev);
|
||||||
@ -965,10 +969,33 @@ bufferevent_generic_adj_timeouts_(struct bufferevent *bev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
bufferevent_generic_adj_existing_timeouts_(struct bufferevent *bev)
|
||||||
|
{
|
||||||
|
int r = 0;
|
||||||
|
if (event_pending(&bev->ev_read, EV_READ, NULL)) {
|
||||||
|
if (evutil_timerisset(&bev->timeout_read)) {
|
||||||
|
if (bufferevent_add_event_(&bev->ev_read, &bev->timeout_read) < 0)
|
||||||
|
r = -1;
|
||||||
|
} else {
|
||||||
|
event_remove_timer(&bev->ev_read);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (event_pending(&bev->ev_write, EV_WRITE, NULL)) {
|
||||||
|
if (evutil_timerisset(&bev->timeout_write)) {
|
||||||
|
if (bufferevent_add_event_(&bev->ev_write, &bev->timeout_write) < 0)
|
||||||
|
r = -1;
|
||||||
|
} else {
|
||||||
|
event_remove_timer(&bev->ev_write);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
bufferevent_add_event_(struct event *ev, const struct timeval *tv)
|
bufferevent_add_event_(struct event *ev, const struct timeval *tv)
|
||||||
{
|
{
|
||||||
if (tv->tv_sec == 0 && tv->tv_usec == 0)
|
if (!evutil_timerisset(tv))
|
||||||
return event_add(ev, NULL);
|
return event_add(ev, NULL);
|
||||||
else
|
else
|
||||||
return event_add(ev, tv);
|
return event_add(ev, tv);
|
||||||
|
@ -536,10 +536,20 @@ be_filter_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op,
|
|||||||
bevf = upcast(bev);
|
bevf = upcast(bev);
|
||||||
data->ptr = bevf->underlying;
|
data->ptr = bevf->underlying;
|
||||||
return 0;
|
return 0;
|
||||||
case BEV_CTRL_GET_FD:
|
|
||||||
case BEV_CTRL_SET_FD:
|
case BEV_CTRL_SET_FD:
|
||||||
|
bevf = upcast(bev);
|
||||||
|
|
||||||
|
if (bevf->underlying &&
|
||||||
|
bevf->underlying->be_ops &&
|
||||||
|
bevf->underlying->be_ops->ctrl) {
|
||||||
|
return (bevf->underlying->be_ops->ctrl)(bevf->underlying, op, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
case BEV_CTRL_GET_FD:
|
||||||
case BEV_CTRL_CANCEL_ALL:
|
case BEV_CTRL_CANCEL_ALL:
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -320,8 +320,6 @@ struct bufferevent_openssl {
|
|||||||
unsigned write_blocked_on_read : 1;
|
unsigned write_blocked_on_read : 1;
|
||||||
/* Treat TCP close before SSL close on SSL >= v3 as clean EOF. */
|
/* Treat TCP close before SSL close on SSL >= v3 as clean EOF. */
|
||||||
unsigned allow_dirty_shutdown : 1;
|
unsigned allow_dirty_shutdown : 1;
|
||||||
/* XXXX */
|
|
||||||
unsigned fd_is_set : 1;
|
|
||||||
/* XXX */
|
/* XXX */
|
||||||
unsigned n_errors : 2;
|
unsigned n_errors : 2;
|
||||||
|
|
||||||
@ -957,6 +955,18 @@ be_openssl_writeeventcb(evutil_socket_t fd, short what, void *ptr)
|
|||||||
bufferevent_decref_and_unlock_(&bev_ssl->bev.bev);
|
bufferevent_decref_and_unlock_(&bev_ssl->bev.bev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
be_openssl_auto_fd(struct bufferevent_openssl *bev_ssl, int fd)
|
||||||
|
{
|
||||||
|
if (!bev_ssl->underlying) {
|
||||||
|
struct bufferevent *bev = &bev_ssl->bev.bev;
|
||||||
|
if (event_initialized(&bev->ev_read) && fd < 0) {
|
||||||
|
fd = event_get_fd(&bev->ev_read);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
set_open_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
|
set_open_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
|
||||||
{
|
{
|
||||||
@ -968,30 +978,36 @@ set_open_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
|
|||||||
} else {
|
} else {
|
||||||
struct bufferevent *bev = &bev_ssl->bev.bev;
|
struct bufferevent *bev = &bev_ssl->bev.bev;
|
||||||
int rpending=0, wpending=0, r1=0, r2=0;
|
int rpending=0, wpending=0, r1=0, r2=0;
|
||||||
if (fd < 0 && bev_ssl->fd_is_set)
|
|
||||||
fd = event_get_fd(&bev->ev_read);
|
if (event_initialized(&bev->ev_read)) {
|
||||||
if (bev_ssl->fd_is_set) {
|
|
||||||
rpending = event_pending(&bev->ev_read, EV_READ, NULL);
|
rpending = event_pending(&bev->ev_read, EV_READ, NULL);
|
||||||
wpending = event_pending(&bev->ev_write, EV_WRITE, NULL);
|
wpending = event_pending(&bev->ev_write, EV_WRITE, NULL);
|
||||||
|
|
||||||
event_del(&bev->ev_read);
|
event_del(&bev->ev_read);
|
||||||
event_del(&bev->ev_write);
|
event_del(&bev->ev_write);
|
||||||
}
|
}
|
||||||
|
|
||||||
event_assign(&bev->ev_read, bev->ev_base, fd,
|
event_assign(&bev->ev_read, bev->ev_base, fd,
|
||||||
EV_READ|EV_PERSIST|EV_FINALIZE,
|
EV_READ|EV_PERSIST|EV_FINALIZE,
|
||||||
be_openssl_readeventcb, bev_ssl);
|
be_openssl_readeventcb, bev_ssl);
|
||||||
event_assign(&bev->ev_write, bev->ev_base, fd,
|
event_assign(&bev->ev_write, bev->ev_base, fd,
|
||||||
EV_WRITE|EV_PERSIST|EV_FINALIZE,
|
EV_WRITE|EV_PERSIST|EV_FINALIZE,
|
||||||
be_openssl_writeeventcb, bev_ssl);
|
be_openssl_writeeventcb, bev_ssl);
|
||||||
|
|
||||||
if (rpending)
|
if (rpending)
|
||||||
r1 = bufferevent_add_event_(&bev->ev_read, &bev->timeout_read);
|
r1 = bufferevent_add_event_(&bev->ev_read, &bev->timeout_read);
|
||||||
if (wpending)
|
if (wpending)
|
||||||
r2 = bufferevent_add_event_(&bev->ev_write, &bev->timeout_write);
|
r2 = bufferevent_add_event_(&bev->ev_write, &bev->timeout_write);
|
||||||
if (fd >= 0) {
|
|
||||||
bev_ssl->fd_is_set = 1;
|
|
||||||
}
|
|
||||||
return (r1<0 || r2<0) ? -1 : 0;
|
return (r1<0 || r2<0) ? -1 : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static int
|
||||||
|
set_open_callbacks_auto(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
|
||||||
|
{
|
||||||
|
fd = be_openssl_auto_fd(bev_ssl, fd);
|
||||||
|
return set_open_callbacks(bev_ssl, fd);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
do_handshake(struct bufferevent_openssl *bev_ssl)
|
do_handshake(struct bufferevent_openssl *bev_ssl)
|
||||||
@ -1011,9 +1027,10 @@ do_handshake(struct bufferevent_openssl *bev_ssl)
|
|||||||
decrement_buckets(bev_ssl);
|
decrement_buckets(bev_ssl);
|
||||||
|
|
||||||
if (r==1) {
|
if (r==1) {
|
||||||
|
int fd = event_get_fd(&bev_ssl->bev.bev.ev_read);
|
||||||
/* We're done! */
|
/* We're done! */
|
||||||
bev_ssl->state = BUFFEREVENT_SSL_OPEN;
|
bev_ssl->state = BUFFEREVENT_SSL_OPEN;
|
||||||
set_open_callbacks(bev_ssl, -1); /* XXXX handle failure */
|
set_open_callbacks(bev_ssl, fd); /* XXXX handle failure */
|
||||||
/* Call do_read and do_write as needed */
|
/* Call do_read and do_write as needed */
|
||||||
bufferevent_enable(&bev_ssl->bev.bev, bev_ssl->bev.bev.enabled);
|
bufferevent_enable(&bev_ssl->bev.bev, bev_ssl->bev.bev.enabled);
|
||||||
bufferevent_run_eventcb_(&bev_ssl->bev.bev,
|
bufferevent_run_eventcb_(&bev_ssl->bev.bev,
|
||||||
@ -1073,28 +1090,31 @@ set_handshake_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
|
|||||||
return do_handshake(bev_ssl);
|
return do_handshake(bev_ssl);
|
||||||
} else {
|
} else {
|
||||||
struct bufferevent *bev = &bev_ssl->bev.bev;
|
struct bufferevent *bev = &bev_ssl->bev.bev;
|
||||||
int r1=0, r2=0;
|
|
||||||
if (fd < 0 && bev_ssl->fd_is_set)
|
if (event_initialized(&bev->ev_read)) {
|
||||||
fd = event_get_fd(&bev->ev_read);
|
|
||||||
if (bev_ssl->fd_is_set) {
|
|
||||||
event_del(&bev->ev_read);
|
event_del(&bev->ev_read);
|
||||||
event_del(&bev->ev_write);
|
event_del(&bev->ev_write);
|
||||||
}
|
}
|
||||||
|
|
||||||
event_assign(&bev->ev_read, bev->ev_base, fd,
|
event_assign(&bev->ev_read, bev->ev_base, fd,
|
||||||
EV_READ|EV_PERSIST|EV_FINALIZE,
|
EV_READ|EV_PERSIST|EV_FINALIZE,
|
||||||
be_openssl_handshakeeventcb, bev_ssl);
|
be_openssl_handshakeeventcb, bev_ssl);
|
||||||
event_assign(&bev->ev_write, bev->ev_base, fd,
|
event_assign(&bev->ev_write, bev->ev_base, fd,
|
||||||
EV_WRITE|EV_PERSIST|EV_FINALIZE,
|
EV_WRITE|EV_PERSIST|EV_FINALIZE,
|
||||||
be_openssl_handshakeeventcb, bev_ssl);
|
be_openssl_handshakeeventcb, bev_ssl);
|
||||||
if (fd >= 0) {
|
if (fd >= 0)
|
||||||
r1 = bufferevent_add_event_(&bev->ev_read, &bev->timeout_read);
|
bufferevent_enable(bev, bev->enabled);
|
||||||
r2 = bufferevent_add_event_(&bev->ev_write, &bev->timeout_write);
|
return 0;
|
||||||
bev_ssl->fd_is_set = 1;
|
|
||||||
}
|
|
||||||
return (r1<0 || r2<0) ? -1 : 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
set_handshake_callbacks_auto(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
|
||||||
|
{
|
||||||
|
fd = be_openssl_auto_fd(bev_ssl, fd);
|
||||||
|
return set_handshake_callbacks(bev_ssl, fd);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
bufferevent_ssl_renegotiate(struct bufferevent *bev)
|
bufferevent_ssl_renegotiate(struct bufferevent *bev)
|
||||||
{
|
{
|
||||||
@ -1104,7 +1124,7 @@ bufferevent_ssl_renegotiate(struct bufferevent *bev)
|
|||||||
if (SSL_renegotiate(bev_ssl->ssl) < 0)
|
if (SSL_renegotiate(bev_ssl->ssl) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
bev_ssl->state = BUFFEREVENT_SSL_CONNECTING;
|
bev_ssl->state = BUFFEREVENT_SSL_CONNECTING;
|
||||||
if (set_handshake_callbacks(bev_ssl, -1) < 0)
|
if (set_handshake_callbacks_auto(bev_ssl, -1) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (!bev_ssl->underlying)
|
if (!bev_ssl->underlying)
|
||||||
return do_handshake(bev_ssl);
|
return do_handshake(bev_ssl);
|
||||||
@ -1119,14 +1139,13 @@ be_openssl_outbuf_cb(struct evbuffer *buf,
|
|||||||
int r = 0;
|
int r = 0;
|
||||||
/* XXX need to hold a reference here. */
|
/* XXX need to hold a reference here. */
|
||||||
|
|
||||||
if (cbinfo->n_added && bev_ssl->state == BUFFEREVENT_SSL_OPEN) {
|
if (cbinfo->n_added && bev_ssl->state == BUFFEREVENT_SSL_OPEN &&
|
||||||
if (cbinfo->orig_size == 0)
|
cbinfo->orig_size == 0) {
|
||||||
r = bufferevent_add_event_(&bev_ssl->bev.bev.ev_write,
|
r = bufferevent_add_event_(&bev_ssl->bev.bev.ev_write,
|
||||||
&bev_ssl->bev.bev.timeout_write);
|
&bev_ssl->bev.bev.timeout_write);
|
||||||
consider_writing(bev_ssl);
|
|
||||||
}
|
}
|
||||||
/* XXX Handle r < 0 */
|
/* XXX Handle r < 0 */
|
||||||
(void)r;
|
(void)r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1136,9 +1155,6 @@ be_openssl_enable(struct bufferevent *bev, short events)
|
|||||||
struct bufferevent_openssl *bev_ssl = upcast(bev);
|
struct bufferevent_openssl *bev_ssl = upcast(bev);
|
||||||
int r1 = 0, r2 = 0;
|
int r1 = 0, r2 = 0;
|
||||||
|
|
||||||
if (bev_ssl->state != BUFFEREVENT_SSL_OPEN)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (events & EV_READ)
|
if (events & EV_READ)
|
||||||
r1 = start_reading(bev_ssl);
|
r1 = start_reading(bev_ssl);
|
||||||
if (events & EV_WRITE)
|
if (events & EV_WRITE)
|
||||||
@ -1162,8 +1178,6 @@ static int
|
|||||||
be_openssl_disable(struct bufferevent *bev, short events)
|
be_openssl_disable(struct bufferevent *bev, short events)
|
||||||
{
|
{
|
||||||
struct bufferevent_openssl *bev_ssl = upcast(bev);
|
struct bufferevent_openssl *bev_ssl = upcast(bev);
|
||||||
if (bev_ssl->state != BUFFEREVENT_SSL_OPEN)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (events & EV_READ)
|
if (events & EV_READ)
|
||||||
stop_reading(bev_ssl);
|
stop_reading(bev_ssl);
|
||||||
@ -1233,23 +1247,7 @@ be_openssl_adj_timeouts(struct bufferevent *bev)
|
|||||||
if (bev_ssl->underlying) {
|
if (bev_ssl->underlying) {
|
||||||
return bufferevent_generic_adj_timeouts_(bev);
|
return bufferevent_generic_adj_timeouts_(bev);
|
||||||
} else {
|
} else {
|
||||||
int r1=0, r2=0;
|
return bufferevent_generic_adj_existing_timeouts_(bev);
|
||||||
if (event_pending(&bev->ev_read, EV_READ, NULL)) {
|
|
||||||
if (evutil_timerisset(&bev->timeout_read)) {
|
|
||||||
r1 = bufferevent_add_event_(&bev->ev_read, &bev->timeout_read);
|
|
||||||
} else {
|
|
||||||
event_remove_timer(&bev->ev_read);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (event_pending(&bev->ev_write, EV_WRITE, NULL)) {
|
|
||||||
if (evutil_timerisset(&bev->timeout_write)) {
|
|
||||||
r2 = bufferevent_add_event_(&bev->ev_write, &bev->timeout_write);
|
|
||||||
} else {
|
|
||||||
event_remove_timer(&bev->ev_write);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (r1<0 || r2<0) ? -1 : 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1274,25 +1272,16 @@ be_openssl_ctrl(struct bufferevent *bev,
|
|||||||
BIO *bio;
|
BIO *bio;
|
||||||
bio = BIO_new_socket(data->fd, 0);
|
bio = BIO_new_socket(data->fd, 0);
|
||||||
SSL_set_bio(bev_ssl->ssl, bio, bio);
|
SSL_set_bio(bev_ssl->ssl, bio, bio);
|
||||||
bev_ssl->fd_is_set = 1;
|
|
||||||
}
|
}
|
||||||
if (data->fd == -1)
|
if (bev_ssl->state == BUFFEREVENT_SSL_OPEN && data->fd >= 0)
|
||||||
bev_ssl->fd_is_set = 0;
|
|
||||||
if (bev_ssl->state == BUFFEREVENT_SSL_OPEN)
|
|
||||||
return set_open_callbacks(bev_ssl, data->fd);
|
return set_open_callbacks(bev_ssl, data->fd);
|
||||||
else {
|
else {
|
||||||
return set_handshake_callbacks(bev_ssl, data->fd);
|
return set_handshake_callbacks(bev_ssl, data->fd);
|
||||||
}
|
}
|
||||||
case BEV_CTRL_GET_FD:
|
case BEV_CTRL_GET_FD:
|
||||||
if (bev_ssl->underlying)
|
|
||||||
return -1;
|
|
||||||
if (!bev_ssl->fd_is_set)
|
|
||||||
return -1;
|
|
||||||
data->fd = event_get_fd(&bev->ev_read);
|
data->fd = event_get_fd(&bev->ev_read);
|
||||||
return 0;
|
return 0;
|
||||||
case BEV_CTRL_GET_UNDERLYING:
|
case BEV_CTRL_GET_UNDERLYING:
|
||||||
if (!bev_ssl->underlying)
|
|
||||||
return -1;
|
|
||||||
data->ptr = bev_ssl->underlying;
|
data->ptr = bev_ssl->underlying;
|
||||||
return 0;
|
return 0;
|
||||||
case BEV_CTRL_CANCEL_ALL:
|
case BEV_CTRL_CANCEL_ALL:
|
||||||
@ -1360,16 +1349,16 @@ bufferevent_openssl_new_impl(struct event_base *base,
|
|||||||
switch (state) {
|
switch (state) {
|
||||||
case BUFFEREVENT_SSL_ACCEPTING:
|
case BUFFEREVENT_SSL_ACCEPTING:
|
||||||
SSL_set_accept_state(bev_ssl->ssl);
|
SSL_set_accept_state(bev_ssl->ssl);
|
||||||
if (set_handshake_callbacks(bev_ssl, fd) < 0)
|
if (set_handshake_callbacks_auto(bev_ssl, fd) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
break;
|
break;
|
||||||
case BUFFEREVENT_SSL_CONNECTING:
|
case BUFFEREVENT_SSL_CONNECTING:
|
||||||
SSL_set_connect_state(bev_ssl->ssl);
|
SSL_set_connect_state(bev_ssl->ssl);
|
||||||
if (set_handshake_callbacks(bev_ssl, fd) < 0)
|
if (set_handshake_callbacks_auto(bev_ssl, fd) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
break;
|
break;
|
||||||
case BUFFEREVENT_SSL_OPEN:
|
case BUFFEREVENT_SSL_OPEN:
|
||||||
if (set_open_callbacks(bev_ssl, fd) < 0)
|
if (set_open_callbacks_auto(bev_ssl, fd) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -1382,15 +1371,6 @@ bufferevent_openssl_new_impl(struct event_base *base,
|
|||||||
if (state == BUFFEREVENT_SSL_OPEN)
|
if (state == BUFFEREVENT_SSL_OPEN)
|
||||||
bufferevent_suspend_read_(underlying,
|
bufferevent_suspend_read_(underlying,
|
||||||
BEV_SUSPEND_FILT_READ);
|
BEV_SUSPEND_FILT_READ);
|
||||||
} else {
|
|
||||||
bev_ssl->bev.bev.enabled = EV_READ|EV_WRITE;
|
|
||||||
if (bev_ssl->fd_is_set) {
|
|
||||||
if (state != BUFFEREVENT_SSL_OPEN)
|
|
||||||
if (event_add(&bev_ssl->bev.bev.ev_read, NULL) < 0)
|
|
||||||
goto err;
|
|
||||||
if (event_add(&bev_ssl->bev.bev.ev_write, NULL) < 0)
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &bev_ssl->bev.bev;
|
return &bev_ssl->bev.bev;
|
||||||
|
@ -307,15 +307,17 @@ be_pair_flush(struct bufferevent *bev, short iotype,
|
|||||||
{
|
{
|
||||||
struct bufferevent_pair *bev_p = upcast(bev);
|
struct bufferevent_pair *bev_p = upcast(bev);
|
||||||
struct bufferevent *partner;
|
struct bufferevent *partner;
|
||||||
incref_and_lock(bev);
|
|
||||||
if (!bev_p->partner)
|
if (!bev_p->partner)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
partner = downcast(bev_p->partner);
|
|
||||||
|
|
||||||
if (mode == BEV_NORMAL)
|
if (mode == BEV_NORMAL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
incref_and_lock(bev);
|
||||||
|
|
||||||
|
partner = downcast(bev_p->partner);
|
||||||
|
|
||||||
if ((iotype & EV_READ) != 0)
|
if ((iotype & EV_READ) != 0)
|
||||||
be_pair_transfer(partner, bev, 1);
|
be_pair_transfer(partner, bev, 1);
|
||||||
|
|
||||||
|
@ -79,7 +79,6 @@
|
|||||||
static int be_socket_enable(struct bufferevent *, short);
|
static int be_socket_enable(struct bufferevent *, short);
|
||||||
static int be_socket_disable(struct bufferevent *, short);
|
static int be_socket_disable(struct bufferevent *, short);
|
||||||
static void be_socket_destruct(struct bufferevent *);
|
static void be_socket_destruct(struct bufferevent *);
|
||||||
static int be_socket_adj_timeouts(struct bufferevent *);
|
|
||||||
static int be_socket_flush(struct bufferevent *, short, enum bufferevent_flush_mode);
|
static int be_socket_flush(struct bufferevent *, short, enum bufferevent_flush_mode);
|
||||||
static int be_socket_ctrl(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *);
|
static int be_socket_ctrl(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *);
|
||||||
|
|
||||||
@ -92,13 +91,35 @@ const struct bufferevent_ops bufferevent_ops_socket = {
|
|||||||
be_socket_disable,
|
be_socket_disable,
|
||||||
NULL, /* unlink */
|
NULL, /* unlink */
|
||||||
be_socket_destruct,
|
be_socket_destruct,
|
||||||
be_socket_adj_timeouts,
|
bufferevent_generic_adj_existing_timeouts_,
|
||||||
be_socket_flush,
|
be_socket_flush,
|
||||||
be_socket_ctrl,
|
be_socket_ctrl,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define be_socket_add(ev, t) \
|
const struct sockaddr*
|
||||||
bufferevent_add_event_((ev), (t))
|
bufferevent_socket_get_conn_address_(struct bufferevent *bev)
|
||||||
|
{
|
||||||
|
struct bufferevent_private *bev_p =
|
||||||
|
EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
|
||||||
|
|
||||||
|
return (struct sockaddr *)&bev_p->conn_address;
|
||||||
|
}
|
||||||
|
static void
|
||||||
|
bufferevent_socket_set_conn_address_fd(struct bufferevent_private *bev_p, int fd)
|
||||||
|
{
|
||||||
|
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,
|
||||||
|
struct sockaddr *addr, size_t addrlen)
|
||||||
|
{
|
||||||
|
EVUTIL_ASSERT(addrlen <= sizeof(bev_p->conn_address));
|
||||||
|
memcpy(&bev_p->conn_address, addr, addrlen);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bufferevent_socket_outbuf_cb(struct evbuffer *buf,
|
bufferevent_socket_outbuf_cb(struct evbuffer *buf,
|
||||||
@ -115,7 +136,7 @@ bufferevent_socket_outbuf_cb(struct evbuffer *buf,
|
|||||||
!bufev_p->write_suspended) {
|
!bufev_p->write_suspended) {
|
||||||
/* Somebody added data to the buffer, and we would like to
|
/* Somebody added data to the buffer, and we would like to
|
||||||
* write, and we were not writing. So, start writing. */
|
* write, and we were not writing. So, start writing. */
|
||||||
if (be_socket_add(&bufev->ev_write, &bufev->timeout_write) == -1) {
|
if (bufferevent_add_event_(&bufev->ev_write, &bufev->timeout_write) == -1) {
|
||||||
/* Should we log this? */
|
/* Should we log this? */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -239,6 +260,7 @@ bufferevent_writecb(evutil_socket_t fd, short event, void *arg)
|
|||||||
goto done;
|
goto done;
|
||||||
} else {
|
} else {
|
||||||
connected = 1;
|
connected = 1;
|
||||||
|
bufferevent_socket_set_conn_address_fd(bufev_p, fd);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (BEV_IS_ASYNC(bufev)) {
|
if (BEV_IS_ASYNC(bufev)) {
|
||||||
event_del(&bufev->ev_write);
|
event_del(&bufev->ev_write);
|
||||||
@ -351,7 +373,7 @@ bufferevent_socket_new(struct event_base *base, evutil_socket_t fd,
|
|||||||
|
|
||||||
int
|
int
|
||||||
bufferevent_socket_connect(struct bufferevent *bev,
|
bufferevent_socket_connect(struct bufferevent *bev,
|
||||||
struct sockaddr *sa, int socklen)
|
const struct sockaddr *sa, int socklen)
|
||||||
{
|
{
|
||||||
struct bufferevent_private *bufev_p =
|
struct bufferevent_private *bufev_p =
|
||||||
EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
|
EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
|
||||||
@ -457,6 +479,7 @@ bufferevent_connect_getaddrinfo_cb(int result, struct evutil_addrinfo *ai,
|
|||||||
|
|
||||||
/* XXX use the other addrinfos? */
|
/* XXX use the other addrinfos? */
|
||||||
/* XXX use this return value */
|
/* XXX use this return value */
|
||||||
|
bufferevent_socket_set_conn_address(bev_p, ai->ai_addr, (int)ai->ai_addrlen);
|
||||||
r = bufferevent_socket_connect(bev, ai->ai_addr, (int)ai->ai_addrlen);
|
r = bufferevent_socket_connect(bev, ai->ai_addr, (int)ai->ai_addrlen);
|
||||||
(void)r;
|
(void)r;
|
||||||
bufferevent_decref_and_unlock_(bev);
|
bufferevent_decref_and_unlock_(bev);
|
||||||
@ -478,23 +501,23 @@ bufferevent_socket_connect_hostname(struct bufferevent *bev,
|
|||||||
if (port < 1 || port > 65535)
|
if (port < 1 || port > 65535)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
BEV_LOCK(bev);
|
|
||||||
bev_p->dns_error = 0;
|
|
||||||
BEV_UNLOCK(bev);
|
|
||||||
|
|
||||||
evutil_snprintf(portbuf, sizeof(portbuf), "%d", port);
|
|
||||||
|
|
||||||
memset(&hint, 0, sizeof(hint));
|
memset(&hint, 0, sizeof(hint));
|
||||||
hint.ai_family = family;
|
hint.ai_family = family;
|
||||||
hint.ai_protocol = IPPROTO_TCP;
|
hint.ai_protocol = IPPROTO_TCP;
|
||||||
hint.ai_socktype = SOCK_STREAM;
|
hint.ai_socktype = SOCK_STREAM;
|
||||||
|
|
||||||
|
evutil_snprintf(portbuf, sizeof(portbuf), "%d", port);
|
||||||
|
|
||||||
|
BEV_LOCK(bev);
|
||||||
|
bev_p->dns_error = 0;
|
||||||
|
|
||||||
bufferevent_suspend_write_(bev, BEV_SUSPEND_LOOKUP);
|
bufferevent_suspend_write_(bev, BEV_SUSPEND_LOOKUP);
|
||||||
bufferevent_suspend_read_(bev, BEV_SUSPEND_LOOKUP);
|
bufferevent_suspend_read_(bev, BEV_SUSPEND_LOOKUP);
|
||||||
|
|
||||||
bufferevent_incref_(bev);
|
bufferevent_incref_(bev);
|
||||||
err = evutil_getaddrinfo_async_(evdns_base, hostname, portbuf,
|
err = evutil_getaddrinfo_async_(evdns_base, hostname, portbuf,
|
||||||
&hint, bufferevent_connect_getaddrinfo_cb, bev);
|
&hint, bufferevent_connect_getaddrinfo_cb, bev);
|
||||||
|
BEV_UNLOCK(bev);
|
||||||
|
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -550,14 +573,12 @@ bufferevent_new(evutil_socket_t fd,
|
|||||||
static int
|
static int
|
||||||
be_socket_enable(struct bufferevent *bufev, short event)
|
be_socket_enable(struct bufferevent *bufev, short event)
|
||||||
{
|
{
|
||||||
if (event & EV_READ) {
|
if (event & EV_READ &&
|
||||||
if (be_socket_add(&bufev->ev_read,&bufev->timeout_read) == -1)
|
bufferevent_add_event_(&bufev->ev_read, &bufev->timeout_read) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
if (event & EV_WRITE &&
|
||||||
if (event & EV_WRITE) {
|
bufferevent_add_event_(&bufev->ev_write, &bufev->timeout_write) == -1)
|
||||||
if (be_socket_add(&bufev->ev_write,&bufev->timeout_write) == -1)
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -592,29 +613,6 @@ be_socket_destruct(struct bufferevent *bufev)
|
|||||||
EVUTIL_CLOSESOCKET(fd);
|
EVUTIL_CLOSESOCKET(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
be_socket_adj_timeouts(struct bufferevent *bufev)
|
|
||||||
{
|
|
||||||
int r = 0;
|
|
||||||
if (event_pending(&bufev->ev_read, EV_READ, NULL)) {
|
|
||||||
if (evutil_timerisset(&bufev->timeout_read)) {
|
|
||||||
if (be_socket_add(&bufev->ev_read, &bufev->timeout_read) < 0)
|
|
||||||
r = -1;
|
|
||||||
} else {
|
|
||||||
event_remove_timer(&bufev->ev_read);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (event_pending(&bufev->ev_write, EV_WRITE, NULL)) {
|
|
||||||
if (evutil_timerisset(&bufev->timeout_write)) {
|
|
||||||
if (be_socket_add(&bufev->ev_write, &bufev->timeout_write) < 0)
|
|
||||||
r = -1;
|
|
||||||
} else {
|
|
||||||
event_remove_timer(&bufev->ev_write);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
be_socket_flush(struct bufferevent *bev, short iotype,
|
be_socket_flush(struct bufferevent *bev, short iotype,
|
||||||
enum bufferevent_flush_mode mode)
|
enum bufferevent_flush_mode mode)
|
||||||
|
15
cmake/AddCompilerFlags.cmake
Normal file
15
cmake/AddCompilerFlags.cmake
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
include(CheckCCompilerFlag)
|
||||||
|
|
||||||
|
macro(add_compiler_flags _flags)
|
||||||
|
foreach(flag ${_flags})
|
||||||
|
string(REGEX REPLACE "[-.+/:= ]" "_" _flag_esc "${flag}")
|
||||||
|
|
||||||
|
check_c_compiler_flag("${flag}" check_c_compiler_flag_${_flag_esc})
|
||||||
|
|
||||||
|
if (check_c_compiler_flag_${_flag_esc})
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${flag}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
|
14
cmake/CheckFunctionKeywords.cmake
Normal file
14
cmake/CheckFunctionKeywords.cmake
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
include(CheckCSourceCompiles)
|
||||||
|
|
||||||
|
macro(check_function_keywords _wordlist)
|
||||||
|
set(${_result} "")
|
||||||
|
foreach(flag ${_wordlist})
|
||||||
|
string(REGEX REPLACE "[-+/ ()]" "_" flagname "${flag}")
|
||||||
|
string(TOUPPER "${flagname}" flagname)
|
||||||
|
set(have_flag "HAVE_${flagname}")
|
||||||
|
check_c_source_compiles("${flag} void func(); void func() { } int main() { func(); return 0; }" ${have_flag})
|
||||||
|
if(${have_flag} AND NOT ${_result})
|
||||||
|
set(${_result} "${flag}")
|
||||||
|
endif(${have_flag} AND NOT ${_result})
|
||||||
|
endforeach(flag)
|
||||||
|
endmacro(check_function_keywords)
|
45
cmake/FindGit.cmake
Normal file
45
cmake/FindGit.cmake
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
# The module defines the following variables:
|
||||||
|
# GIT_EXECUTABLE - path to git command line client
|
||||||
|
# GIT_FOUND - true if the command line client was found
|
||||||
|
# Example usage:
|
||||||
|
# find_package(Git)
|
||||||
|
# if(GIT_FOUND)
|
||||||
|
# message("git found: ${GIT_EXECUTABLE}")
|
||||||
|
# endif()
|
||||||
|
|
||||||
|
#=============================================================================
|
||||||
|
# Copyright 2010 Kitware, Inc.
|
||||||
|
#
|
||||||
|
# Distributed under the OSI-approved BSD License (the "License");
|
||||||
|
# see accompanying file Copyright.txt for details.
|
||||||
|
#
|
||||||
|
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||||
|
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
# See the License for more information.
|
||||||
|
#=============================================================================
|
||||||
|
# (To distributed this file outside of CMake, substitute the full
|
||||||
|
# License text for the above reference.)
|
||||||
|
|
||||||
|
# Look for 'git' or 'eg' (easy git)
|
||||||
|
set(git_names git eg)
|
||||||
|
|
||||||
|
# Prefer .cmd variants on Windows unless running in a Makefile
|
||||||
|
# in the MSYS shell.
|
||||||
|
if(WIN32)
|
||||||
|
if(NOT CMAKE_GENERATOR MATCHES "MSYS")
|
||||||
|
set(git_names git.cmd git eg.cmd eg)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_program(GIT_EXECUTABLE
|
||||||
|
NAMES ${git_names}
|
||||||
|
DOC "git command line client")
|
||||||
|
|
||||||
|
mark_as_advanced(GIT_EXECUTABLE)
|
||||||
|
|
||||||
|
# Handle the QUIETLY and REQUIRED arguments and set GIT_FOUND to TRUE if
|
||||||
|
# all listed variables are TRUE
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(Git DEFAULT_MSG GIT_EXECUTABLE)
|
||||||
|
|
53
cmake/VersionViaGit.cmake
Normal file
53
cmake/VersionViaGit.cmake
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# This module defines the following variables utilizing
|
||||||
|
# git to determine the parent tag. And if found the macro
|
||||||
|
# will attempt to parse them in the github tag fomat
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
#
|
||||||
|
# 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}")
|
||||||
|
# message(" stage=${EVENT_GIT___VERSION_STAGE}")
|
||||||
|
# endif()
|
||||||
|
|
||||||
|
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 5)
|
||||||
|
set(EVENT_GIT___VERSION_STAGE "beta")
|
||||||
|
|
||||||
|
find_package(Git)
|
||||||
|
|
||||||
|
if (GIT_FOUND)
|
||||||
|
execute_process(
|
||||||
|
COMMAND
|
||||||
|
${GIT_EXECUTABLE} describe --abbrev=0
|
||||||
|
WORKING_DIRECTORY
|
||||||
|
${PROJECT_SOURCE_DIR}
|
||||||
|
RESULT_VARIABLE
|
||||||
|
GITRET
|
||||||
|
OUTPUT_VARIABLE
|
||||||
|
GITVERSION)
|
||||||
|
|
||||||
|
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})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endmacro()
|
@ -369,6 +369,7 @@ AC_CHECK_FUNCS([ \
|
|||||||
unsetenv \
|
unsetenv \
|
||||||
usleep \
|
usleep \
|
||||||
vasprintf \
|
vasprintf \
|
||||||
|
getservbyname \
|
||||||
])
|
])
|
||||||
AM_CONDITIONAL(STRLCPY_IMPL, [test x"$ac_cv_func_strlcpy" = xno])
|
AM_CONDITIONAL(STRLCPY_IMPL, [test x"$ac_cv_func_strlcpy" = xno])
|
||||||
|
|
||||||
@ -394,7 +395,6 @@ if test "$libevent_cv_getaddrinfo" = "yes" ; then
|
|||||||
AC_DEFINE([HAVE_GETADDRINFO], [1], [Do we have getaddrinfo()?])
|
AC_DEFINE([HAVE_GETADDRINFO], [1], [Do we have getaddrinfo()?])
|
||||||
else
|
else
|
||||||
|
|
||||||
AC_CHECK_FUNCS([getservbyname])
|
|
||||||
# Check for gethostbyname_r in all its glorious incompatible versions.
|
# Check for gethostbyname_r in all its glorious incompatible versions.
|
||||||
# (This is cut-and-pasted from Tor, which based its logic on
|
# (This is cut-and-pasted from Tor, which based its logic on
|
||||||
# Python's configure.in.)
|
# Python's configure.in.)
|
||||||
@ -763,6 +763,10 @@ fi
|
|||||||
|
|
||||||
# check if we have and should use openssl
|
# check if we have and should use openssl
|
||||||
AM_CONDITIONAL(OPENSSL, [test "$enable_openssl" != "no" && test "$have_openssl" = "yes"])
|
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],
|
||||||
|
[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
|
# Add some more warnings which we use in development but not in the
|
||||||
# released versions. (Some relevant gcc versions can't handle these.)
|
# released versions. (Some relevant gcc versions can't handle these.)
|
||||||
|
39
epoll.c
39
epoll.c
@ -246,6 +246,23 @@ epoll_op_to_string(int op)
|
|||||||
"???";
|
"???";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define PRINT_CHANGES(op, events, ch, status) \
|
||||||
|
"Epoll %s(%d) on fd %d " status ". " \
|
||||||
|
"Old events were %d; " \
|
||||||
|
"read change was %d (%s); " \
|
||||||
|
"write change was %d (%s); " \
|
||||||
|
"close change was %d (%s)", \
|
||||||
|
epoll_op_to_string(op), \
|
||||||
|
events, \
|
||||||
|
ch->fd, \
|
||||||
|
ch->old_events, \
|
||||||
|
ch->read_change, \
|
||||||
|
change_to_string(ch->read_change), \
|
||||||
|
ch->write_change, \
|
||||||
|
change_to_string(ch->write_change), \
|
||||||
|
ch->close_change, \
|
||||||
|
change_to_string(ch->close_change)
|
||||||
|
|
||||||
static int
|
static int
|
||||||
epoll_apply_one_change(struct event_base *base,
|
epoll_apply_one_change(struct event_base *base,
|
||||||
struct epollop *epollop,
|
struct epollop *epollop,
|
||||||
@ -271,14 +288,7 @@ epoll_apply_one_change(struct event_base *base,
|
|||||||
epev.data.fd = ch->fd;
|
epev.data.fd = ch->fd;
|
||||||
epev.events = events;
|
epev.events = events;
|
||||||
if (epoll_ctl(epollop->epfd, op, ch->fd, &epev) == 0) {
|
if (epoll_ctl(epollop->epfd, op, ch->fd, &epev) == 0) {
|
||||||
event_debug(("Epoll %s(%d) on fd %d okay. [old events were %d; read change was %d; write change was %d; close change was %d]",
|
event_debug((PRINT_CHANGES(op, epev.events, ch, "okay")));
|
||||||
epoll_op_to_string(op),
|
|
||||||
(int)epev.events,
|
|
||||||
(int)ch->fd,
|
|
||||||
ch->old_events,
|
|
||||||
ch->read_change,
|
|
||||||
ch->write_change,
|
|
||||||
ch->close_change));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,18 +348,7 @@ epoll_apply_one_change(struct event_base *base,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
event_warn("Epoll %s(%d) on fd %d failed. Old events were %d; read change was %d (%s); write change was %d (%s); close change was %d (%s)",
|
event_warn(PRINT_CHANGES(op, epev.events, ch, "failed"));
|
||||||
epoll_op_to_string(op),
|
|
||||||
(int)epev.events,
|
|
||||||
ch->fd,
|
|
||||||
ch->old_events,
|
|
||||||
ch->read_change,
|
|
||||||
change_to_string(ch->read_change),
|
|
||||||
ch->write_change,
|
|
||||||
change_to_string(ch->write_change),
|
|
||||||
ch->close_change,
|
|
||||||
change_to_string(ch->close_change));
|
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
85
evdns.c
85
evdns.c
@ -1060,24 +1060,6 @@ reply_parse(struct evdns_base *base, u8 *packet, int length) {
|
|||||||
sizeof(tmp_name))<0) \
|
sizeof(tmp_name))<0) \
|
||||||
goto err; \
|
goto err; \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define TEST_NAME \
|
|
||||||
do { tmp_name[0] = '\0'; \
|
|
||||||
cmp_name[0] = '\0'; \
|
|
||||||
k = j; \
|
|
||||||
if (name_parse(packet, length, &j, tmp_name, \
|
|
||||||
sizeof(tmp_name))<0) \
|
|
||||||
goto err; \
|
|
||||||
if (name_parse(req->request, req->request_len, &k, \
|
|
||||||
cmp_name, sizeof(cmp_name))<0) \
|
|
||||||
goto err; \
|
|
||||||
if (base->global_randomize_case) { \
|
|
||||||
if (strcmp(tmp_name, cmp_name) == 0) \
|
|
||||||
name_matches = 1; \
|
|
||||||
} else { \
|
|
||||||
if (evutil_ascii_strcasecmp(tmp_name, cmp_name) == 0) \
|
|
||||||
name_matches = 1; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
reply.type = req->request_type;
|
reply.type = req->request_type;
|
||||||
|
|
||||||
@ -1086,9 +1068,25 @@ reply_parse(struct evdns_base *base, u8 *packet, int length) {
|
|||||||
/* the question looks like
|
/* the question looks like
|
||||||
* <label:name><u16:type><u16:class>
|
* <label:name><u16:type><u16:class>
|
||||||
*/
|
*/
|
||||||
TEST_NAME;
|
tmp_name[0] = '\0';
|
||||||
|
cmp_name[0] = '\0';
|
||||||
|
k = j;
|
||||||
|
if (name_parse(packet, length, &j, tmp_name, sizeof(tmp_name)) < 0)
|
||||||
|
goto err;
|
||||||
|
if (name_parse(req->request, req->request_len, &k,
|
||||||
|
cmp_name, sizeof(cmp_name))<0)
|
||||||
|
goto err;
|
||||||
|
if (!base->global_randomize_case) {
|
||||||
|
if (strcmp(tmp_name, cmp_name) == 0)
|
||||||
|
name_matches = 1;
|
||||||
|
} else {
|
||||||
|
if (evutil_ascii_strcasecmp(tmp_name, cmp_name) == 0)
|
||||||
|
name_matches = 1;
|
||||||
|
}
|
||||||
|
|
||||||
j += 4;
|
j += 4;
|
||||||
if (j > length) goto err;
|
if (j > length)
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!name_matches)
|
if (!name_matches)
|
||||||
@ -4034,15 +4032,6 @@ evdns_base_free_and_unlock(struct evdns_base *base, int fail_requests)
|
|||||||
|
|
||||||
/* TODO(nickm) we might need to refcount here. */
|
/* TODO(nickm) we might need to refcount here. */
|
||||||
|
|
||||||
for (server = base->server_head; server; server = server_next) {
|
|
||||||
server_next = server->next;
|
|
||||||
evdns_nameserver_free(server);
|
|
||||||
if (server_next == base->server_head)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
base->server_head = NULL;
|
|
||||||
base->global_good_nameservers = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < base->n_req_heads; ++i) {
|
for (i = 0; i < base->n_req_heads; ++i) {
|
||||||
while (base->req_heads[i]) {
|
while (base->req_heads[i]) {
|
||||||
if (fail_requests)
|
if (fail_requests)
|
||||||
@ -4057,6 +4046,14 @@ evdns_base_free_and_unlock(struct evdns_base *base, int fail_requests)
|
|||||||
}
|
}
|
||||||
base->global_requests_inflight = base->global_requests_waiting = 0;
|
base->global_requests_inflight = base->global_requests_waiting = 0;
|
||||||
|
|
||||||
|
for (server = base->server_head; server; server = server_next) {
|
||||||
|
server_next = server->next;
|
||||||
|
evdns_nameserver_free(server);
|
||||||
|
if (server_next == base->server_head)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
base->server_head = NULL;
|
||||||
|
base->global_good_nameservers = 0;
|
||||||
|
|
||||||
if (base->global_search_state) {
|
if (base->global_search_state) {
|
||||||
for (dom = base->global_search_state->head; dom; dom = dom_next) {
|
for (dom = base->global_search_state->head; dom; dom = dom_next) {
|
||||||
@ -4406,17 +4403,23 @@ evdns_getaddrinfo_gotresolve(int result, char type, int count,
|
|||||||
other_req = &data->ipv4_request;
|
other_req = &data->ipv4_request;
|
||||||
}
|
}
|
||||||
|
|
||||||
EVDNS_LOCK(data->evdns_base);
|
/** Called from evdns_base_free() with @fail_requests == 1 */
|
||||||
if (evdns_result_is_answer(result)) {
|
if (result != DNS_ERR_SHUTDOWN) {
|
||||||
if (req->type == DNS_IPv4_A)
|
EVDNS_LOCK(data->evdns_base);
|
||||||
++data->evdns_base->getaddrinfo_ipv4_answered;
|
if (evdns_result_is_answer(result)) {
|
||||||
else
|
if (req->type == DNS_IPv4_A)
|
||||||
++data->evdns_base->getaddrinfo_ipv6_answered;
|
++data->evdns_base->getaddrinfo_ipv4_answered;
|
||||||
|
else
|
||||||
|
++data->evdns_base->getaddrinfo_ipv6_answered;
|
||||||
|
}
|
||||||
|
user_canceled = data->user_canceled;
|
||||||
|
if (other_req->r == NULL)
|
||||||
|
data->request_done = 1;
|
||||||
|
EVDNS_UNLOCK(data->evdns_base);
|
||||||
|
} else {
|
||||||
|
data->evdns_base = NULL;
|
||||||
|
user_canceled = data->user_canceled;
|
||||||
}
|
}
|
||||||
user_canceled = data->user_canceled;
|
|
||||||
if (other_req->r == NULL)
|
|
||||||
data->request_done = 1;
|
|
||||||
EVDNS_UNLOCK(data->evdns_base);
|
|
||||||
|
|
||||||
req->r = NULL;
|
req->r = NULL;
|
||||||
|
|
||||||
@ -4450,7 +4453,9 @@ evdns_getaddrinfo_gotresolve(int result, char type, int count,
|
|||||||
/* The other request is still working; maybe it will
|
/* The other request is still working; maybe it will
|
||||||
* succeed. */
|
* succeed. */
|
||||||
/* XXXX handle failure from set_timeout */
|
/* XXXX handle failure from set_timeout */
|
||||||
evdns_getaddrinfo_set_timeout(data->evdns_base, data);
|
if (result != DNS_ERR_SHUTDOWN) {
|
||||||
|
evdns_getaddrinfo_set_timeout(data->evdns_base, data);
|
||||||
|
}
|
||||||
data->pending_error = err;
|
data->pending_error = err;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,11 @@
|
|||||||
|
|
||||||
/* Numeric representation of the version */
|
/* Numeric representation of the version */
|
||||||
#define EVENT__NUMERIC_VERSION @EVENT_NUMERIC_VERSION@
|
#define EVENT__NUMERIC_VERSION @EVENT_NUMERIC_VERSION@
|
||||||
|
#define EVENT__PACKAGE_VERSION "@EVENT_PACKAGE_VERSION@"
|
||||||
|
|
||||||
#define EVENT__PACKAGE_VERSION @EVENT_PACKAGE_VERSION@
|
#define EVENT__VERSION_MAJOR @EVENT_VERSION_MAJOR@
|
||||||
|
#define EVENT__VERSION_MINOR @EVENT_VERSION_MINOR@
|
||||||
|
#define EVENT__VERSION_PATCH @EVENT_VERSION_PATCH@
|
||||||
|
|
||||||
/* Version number of package */
|
/* Version number of package */
|
||||||
#define EVENT__VERSION "@EVENT_VERSION@"
|
#define EVENT__VERSION "@EVENT_VERSION@"
|
||||||
@ -33,467 +36,499 @@
|
|||||||
#define EVENT__PACKAGE_TARNAME ""
|
#define EVENT__PACKAGE_TARNAME ""
|
||||||
|
|
||||||
/* Define if libevent should build without support for a debug mode */
|
/* Define if libevent should build without support for a debug mode */
|
||||||
#cmakedefine EVENT__DISABLE_DEBUG_MODE 0
|
#cmakedefine EVENT__DISABLE_DEBUG_MODE
|
||||||
|
|
||||||
/* Define if libevent should not allow replacing the mm functions */
|
/* Define if libevent should not allow replacing the mm functions */
|
||||||
#cmakedefine EVENT__DISABLE_MM_REPLACEMENT 0
|
#cmakedefine EVENT__DISABLE_MM_REPLACEMENT
|
||||||
|
|
||||||
/* Define if libevent should not be compiled with thread support */
|
/* Define if libevent should not be compiled with thread support */
|
||||||
#cmakedefine EVENT__DISABLE_THREAD_SUPPORT 0
|
#cmakedefine EVENT__DISABLE_THREAD_SUPPORT
|
||||||
|
|
||||||
/* Define to 1 if you have the `accept4' function. */
|
/* Define to 1 if you have the `accept4' function. */
|
||||||
#cmakedefine EVENT__HAVE_ACCEPT4 1
|
#cmakedefine EVENT__HAVE_ACCEPT4
|
||||||
|
|
||||||
/* Define to 1 if you have the `arc4random' function. */
|
/* Define to 1 if you have the `arc4random' function. */
|
||||||
#cmakedefine EVENT__HAVE_ARC4RANDOM 1
|
#cmakedefine EVENT__HAVE_ARC4RANDOM
|
||||||
|
|
||||||
/* Define to 1 if you have the `arc4random_buf' function. */
|
/* Define to 1 if you have the `arc4random_buf' function. */
|
||||||
#cmakedefine EVENT__HAVE_ARC4RANDOM_BUF 1
|
#cmakedefine EVENT__HAVE_ARC4RANDOM_BUF
|
||||||
|
|
||||||
/* Define if clock_gettime is available in libc */
|
/* Define if clock_gettime is available in libc */
|
||||||
#cmakedefine EVENT__DNS_USE_CPU_CLOCK_FOR_ID 1
|
#cmakedefine EVENT__DNS_USE_CPU_CLOCK_FOR_ID
|
||||||
|
|
||||||
/* Define is no secure id variant is available */
|
/* Define is no secure id variant is available */
|
||||||
#cmakedefine EVENT__DNS_USE_GETTIMEOFDAY_FOR_ID 1
|
#cmakedefine EVENT__DNS_USE_GETTIMEOFDAY_FOR_ID
|
||||||
#cmakedefine EVENT__DNS_USE_FTIME_FOR_ID 1
|
#cmakedefine EVENT__DNS_USE_FTIME_FOR_ID
|
||||||
|
|
||||||
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_ARPA_INET_H 1
|
#cmakedefine EVENT__HAVE_ARPA_INET_H
|
||||||
|
|
||||||
/* Define to 1 if you have the `clock_gettime' function. */
|
/* Define to 1 if you have the `clock_gettime' function. */
|
||||||
#cmakedefine EVENT__HAVE_CLOCK_GETTIME 1
|
#cmakedefine EVENT__HAVE_CLOCK_GETTIME
|
||||||
|
|
||||||
/* Define to 1 if you have the declaration of `CTL_KERN'. */
|
/* Define to 1 if you have the declaration of `CTL_KERN'. */
|
||||||
#cmakedefine EVENT__HAVE_DECL_CTL_KERN 1
|
#cmakedefine EVENT__HAVE_DECL_CTL_KERN
|
||||||
|
|
||||||
/* Define to 1 if you have the declaration of `KERN_ARND'. */
|
/* Define to 1 if you have the declaration of `KERN_ARND'. */
|
||||||
#cmakedefine EVENT__HAVE_DECL_KERN_ARND 0
|
#cmakedefine EVENT__HAVE_DECL_KERN_ARND
|
||||||
|
|
||||||
/* Define to 1 if you have the declaration of `KERN_RANDOM'. */
|
/* Define to 1 if you have the declaration of `KERN_RANDOM'. */
|
||||||
#cmakedefine EVENT__HAVE_DECL_KERN_RANDOM 1
|
#cmakedefine EVENT__HAVE_DECL_KERN_RANDOM
|
||||||
|
|
||||||
/* Define if /dev/poll is available */
|
/* Define if /dev/poll is available */
|
||||||
#cmakedefine EVENT__HAVE_DEVPOLL 1
|
#cmakedefine EVENT__HAVE_DEVPOLL
|
||||||
|
|
||||||
/* Define to 1 if you have the <netdb.h> header file. */
|
/* Define to 1 if you have the <netdb.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_NETDB_H 1
|
#cmakedefine EVENT__HAVE_NETDB_H
|
||||||
|
|
||||||
/* Define to 1 if fd_mask type is defined */
|
/* Define to 1 if fd_mask type is defined */
|
||||||
#cmakedefine EVENT__HAVE_FD_MASK 1
|
#cmakedefine EVENT__HAVE_FD_MASK
|
||||||
|
|
||||||
/* Define to 1 if the <sys/queue.h> header file defines TAILQ_FOREACH. */
|
/* Define to 1 if the <sys/queue.h> header file defines TAILQ_FOREACH. */
|
||||||
#cmakedefine EVENT__HAVE_TAILQFOREACH 1
|
#cmakedefine EVENT__HAVE_TAILQFOREACH
|
||||||
|
|
||||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_DLFCN_H 1
|
#cmakedefine EVENT__HAVE_DLFCN_H
|
||||||
|
|
||||||
/* Define if your system supports the epoll system calls */
|
/* Define if your system supports the epoll system calls */
|
||||||
#cmakedefine EVENT__HAVE_EPOLL 1
|
#cmakedefine EVENT__HAVE_EPOLL
|
||||||
|
|
||||||
/* Define to 1 if you have the `epoll_create1' function. */
|
/* Define to 1 if you have the `epoll_create1' function. */
|
||||||
#cmakedefine EVENT__HAVE_EPOLL_CREATE1 1
|
#cmakedefine EVENT__HAVE_EPOLL_CREATE1
|
||||||
|
|
||||||
/* Define to 1 if you have the `epoll_ctl' function. */
|
/* Define to 1 if you have the `epoll_ctl' function. */
|
||||||
#cmakedefine EVENT__HAVE_EPOLL_CTL 1
|
#cmakedefine EVENT__HAVE_EPOLL_CTL
|
||||||
|
|
||||||
/* Define to 1 if you have the `eventfd' function. */
|
/* Define to 1 if you have the `eventfd' function. */
|
||||||
#cmakedefine EVENT__HAVE_EVENTFD 1
|
#cmakedefine EVENT__HAVE_EVENTFD
|
||||||
|
|
||||||
/* Define if your system supports event ports */
|
/* Define if your system supports event ports */
|
||||||
#cmakedefine EVENT__HAVE_EVENT_PORTS 1
|
#cmakedefine EVENT__HAVE_EVENT_PORTS
|
||||||
|
|
||||||
/* Define to 1 if you have the `fcntl' function. */
|
/* Define to 1 if you have the `fcntl' function. */
|
||||||
#cmakedefine EVENT__HAVE_FCNTL 1
|
#cmakedefine EVENT__HAVE_FCNTL
|
||||||
|
|
||||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_FCNTL_H 1
|
#cmakedefine EVENT__HAVE_FCNTL_H
|
||||||
|
|
||||||
/* Define to 1 if you have the `getaddrinfo' function. */
|
/* Define to 1 if you have the `getaddrinfo' function. */
|
||||||
#cmakedefine EVENT__HAVE_GETADDRINFO 1
|
#cmakedefine EVENT__HAVE_GETADDRINFO
|
||||||
|
|
||||||
/* Define to 1 if you have the `getegid' function. */
|
/* Define to 1 if you have the `getegid' function. */
|
||||||
#cmakedefine EVENT__HAVE_GETEGID 1
|
#cmakedefine EVENT__HAVE_GETEGID
|
||||||
|
|
||||||
/* Define to 1 if you have the `geteuid' function. */
|
/* Define to 1 if you have the `geteuid' function. */
|
||||||
#cmakedefine EVENT__HAVE_GETEUID 1
|
#cmakedefine EVENT__HAVE_GETEUID
|
||||||
|
|
||||||
/* TODO: Check for different gethostname argument counts. CheckPrototypeDefinition.cmake can be used. */
|
/* TODO: Check for different gethostname argument counts. CheckPrototypeDefinition.cmake can be used. */
|
||||||
/* Define this if you have any gethostbyname_r() */
|
/* Define this if you have any gethostbyname_r() */
|
||||||
#cmakedefine EVENT__HAVE_GETHOSTBYNAME_R 1
|
#cmakedefine EVENT__HAVE_GETHOSTBYNAME_R
|
||||||
|
|
||||||
/* Define this if gethostbyname_r takes 3 arguments */
|
/* Define this if gethostbyname_r takes 3 arguments */
|
||||||
#cmakedefine EVENT__HAVE_GETHOSTBYNAME_R_3_ARG 1
|
#cmakedefine EVENT__HAVE_GETHOSTBYNAME_R_3_ARG
|
||||||
|
|
||||||
/* Define this if gethostbyname_r takes 5 arguments */
|
/* Define this if gethostbyname_r takes 5 arguments */
|
||||||
#cmakedefine EVENT__HAVE_GETHOSTBYNAME_R_5_ARG 1
|
#cmakedefine EVENT__HAVE_GETHOSTBYNAME_R_5_ARG
|
||||||
|
|
||||||
/* Define this if gethostbyname_r takes 6 arguments */
|
/* Define this if gethostbyname_r takes 6 arguments */
|
||||||
#cmakedefine EVENT__HAVE_GETHOSTBYNAME_R_6_ARG 1
|
#cmakedefine EVENT__HAVE_GETHOSTBYNAME_R_6_ARG
|
||||||
|
|
||||||
/* Define to 1 if you have the `getifaddrs' function. */
|
/* Define to 1 if you have the `getifaddrs' function. */
|
||||||
#cmakedefine EVENT__HAVE_GETIFADDRS 1
|
#cmakedefine EVENT__HAVE_GETIFADDRS
|
||||||
|
|
||||||
/* Define to 1 if you have the `getnameinfo' function. */
|
/* Define to 1 if you have the `getnameinfo' function. */
|
||||||
#cmakedefine EVENT__HAVE_GETNAMEINFO 1
|
#cmakedefine EVENT__HAVE_GETNAMEINFO
|
||||||
|
|
||||||
/* Define to 1 if you have the `getprotobynumber' function. */
|
/* Define to 1 if you have the `getprotobynumber' function. */
|
||||||
#cmakedefine EVENT__HAVE_GETPROTOBYNUMBER 1
|
#cmakedefine EVENT__HAVE_GETPROTOBYNUMBER
|
||||||
|
|
||||||
/* Define to 1 if you have the `getservbyname' function. */
|
/* Define to 1 if you have the `getservbyname' function. */
|
||||||
#cmakedefine EVENT__HAVE_GETSERVBYNAME 1
|
#cmakedefine EVENT__HAVE_GETSERVBYNAME
|
||||||
|
|
||||||
/* Define to 1 if you have the `gettimeofday' function. */
|
/* Define to 1 if you have the `gettimeofday' function. */
|
||||||
#cmakedefine EVENT__HAVE_GETTIMEOFDAY 1
|
#cmakedefine EVENT__HAVE_GETTIMEOFDAY
|
||||||
|
|
||||||
/* Define to 1 if you have the <ifaddrs.h> header file. */
|
/* Define to 1 if you have the <ifaddrs.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_IFADDRS_H 1
|
#cmakedefine EVENT__HAVE_IFADDRS_H
|
||||||
|
|
||||||
/* Define to 1 if you have the `inet_ntop' function. */
|
/* Define to 1 if you have the `inet_ntop' function. */
|
||||||
#cmakedefine EVENT__HAVE_INET_NTOP 1
|
#cmakedefine EVENT__HAVE_INET_NTOP
|
||||||
|
|
||||||
/* Define to 1 if you have the `inet_pton' function. */
|
/* Define to 1 if you have the `inet_pton' function. */
|
||||||
#cmakedefine EVENT__HAVE_INET_PTON 1
|
#cmakedefine EVENT__HAVE_INET_PTON
|
||||||
|
|
||||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_INTTYPES_H 1
|
#cmakedefine EVENT__HAVE_INTTYPES_H
|
||||||
|
|
||||||
/* Define to 1 if you have the `issetugid' function. */
|
/* Define to 1 if you have the `issetugid' function. */
|
||||||
#cmakedefine EVENT__HAVE_ISSETUGID 1
|
#cmakedefine EVENT__HAVE_ISSETUGID
|
||||||
|
|
||||||
/* Define to 1 if you have the `kqueue' function. */
|
/* Define to 1 if you have the `kqueue' function. */
|
||||||
#cmakedefine EVENT__HAVE_KQUEUE 1
|
#cmakedefine EVENT__HAVE_KQUEUE
|
||||||
|
|
||||||
/* Define if the system has zlib */
|
/* Define if the system has zlib */
|
||||||
#cmakedefine EVENT__HAVE_LIBZ 1
|
#cmakedefine EVENT__HAVE_LIBZ
|
||||||
|
|
||||||
/* Define to 1 if you have the `mach_absolute_time' function. */
|
/* Define to 1 if you have the `mach_absolute_time' function. */
|
||||||
#cmakedefine EVENT__HAVE_MACH_ABSOLUTE_TIME 1
|
#cmakedefine EVENT__HAVE_MACH_ABSOLUTE_TIME
|
||||||
|
|
||||||
/* Define to 1 if you have the <mach/mach_time.h> header file. */
|
/* Define to 1 if you have the <mach/mach_time.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_MACH_MACH_TIME_H 1
|
#cmakedefine EVENT__HAVE_MACH_MACH_TIME_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <memory.h> header file. */
|
/* Define to 1 if you have the <memory.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_MEMORY_H 1
|
#cmakedefine EVENT__HAVE_MEMORY_H
|
||||||
|
|
||||||
/* Define to 1 if you have the `mmap' function. */
|
/* Define to 1 if you have the `mmap' function. */
|
||||||
#cmakedefine EVENT__HAVE_MMAP 1
|
#cmakedefine EVENT__HAVE_MMAP
|
||||||
|
|
||||||
/* Define to 1 if you have the `nanosleep' function. */
|
/* Define to 1 if you have the `nanosleep' function. */
|
||||||
#cmakedefine EVENT__HAVE_NANOSLEEP 1
|
#cmakedefine EVENT__HAVE_NANOSLEEP
|
||||||
|
|
||||||
/* Define to 1 if you have the `usleep' function. */
|
/* Define to 1 if you have the `usleep' function. */
|
||||||
#cmakedefine EVENT__HAVE_USLEEP 1
|
#cmakedefine EVENT__HAVE_USLEEP
|
||||||
|
|
||||||
/* Define to 1 if you have the <netdb.h> header file. */
|
/* Define to 1 if you have the <netdb.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_NETDB_H 1
|
#cmakedefine EVENT__HAVE_NETDB_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <netinet/in6.h> header file. */
|
/* Define to 1 if you have the <netinet/in6.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_NETINET_IN6_H 1
|
#cmakedefine EVENT__HAVE_NETINET_IN6_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_NETINET_IN_H 1
|
#cmakedefine EVENT__HAVE_NETINET_IN_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <netinet/tcp.h> header file. */
|
/* Define to 1 if you have the <netinet/tcp.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_NETINET_TCP_H 1
|
#cmakedefine EVENT__HAVE_NETINET_TCP_H
|
||||||
|
|
||||||
/* Define if the system has openssl */
|
/* Define if the system has openssl */
|
||||||
#cmakedefine EVENT__HAVE_OPENSSL 1
|
#cmakedefine EVENT__HAVE_OPENSSL
|
||||||
|
|
||||||
/* Defines if the system has zlib */
|
/* Defines if the system has zlib */
|
||||||
#cmakedefine EVENT__HAVE_ZLIB 1
|
#cmakedefine EVENT__HAVE_ZLIB
|
||||||
|
|
||||||
/* Define to 1 if you have the `pipe' function. */
|
/* Define to 1 if you have the `pipe' function. */
|
||||||
#cmakedefine EVENT__HAVE_PIPE 1
|
#cmakedefine EVENT__HAVE_PIPE
|
||||||
|
|
||||||
/* Define to 1 if you have the `pipe2' function. */
|
/* Define to 1 if you have the `pipe2' function. */
|
||||||
#cmakedefine EVENT__HAVE_PIPE2 1
|
#cmakedefine EVENT__HAVE_PIPE2
|
||||||
|
|
||||||
/* Define to 1 if you have the `poll' function. */
|
/* Define to 1 if you have the `poll' function. */
|
||||||
#cmakedefine EVENT__HAVE_POLL 1
|
#cmakedefine EVENT__HAVE_POLL
|
||||||
|
|
||||||
/* Define to 1 if you have the <poll.h> header file. */
|
/* Define to 1 if you have the <poll.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_POLL_H 1
|
#cmakedefine EVENT__HAVE_POLL_H
|
||||||
|
|
||||||
/* Define to 1 if you have the `port_create' function. */
|
/* Define to 1 if you have the `port_create' function. */
|
||||||
#cmakedefine EVENT__HAVE_PORT_CREATE 1
|
#cmakedefine EVENT__HAVE_PORT_CREATE
|
||||||
|
|
||||||
/* Define to 1 if you have the <port.h> header file. */
|
/* Define to 1 if you have the <port.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_PORT_H 1
|
#cmakedefine EVENT__HAVE_PORT_H
|
||||||
|
|
||||||
/* Define if you have POSIX threads libraries and header files. */
|
/* Define if you have POSIX threads libraries and header files. */
|
||||||
#cmakedefine EVENT__HAVE_PTHREAD 1
|
#cmakedefine EVENT__HAVE_PTHREAD
|
||||||
|
|
||||||
/* Define if we have pthreads on this system */
|
/* Define if we have pthreads on this system */
|
||||||
#cmakedefine EVENT__HAVE_PTHREADS 1
|
#cmakedefine EVENT__HAVE_PTHREADS
|
||||||
|
|
||||||
/* Define to 1 if you have the `putenv' function. */
|
/* Define to 1 if you have the `putenv' function. */
|
||||||
#cmakedefine EVENT__HAVE_PUTENV 1
|
#cmakedefine EVENT__HAVE_PUTENV
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `sa_family_t'. */
|
/* Define to 1 if the system has the type `sa_family_t'. */
|
||||||
#cmakedefine EVENT__HAVE_SA_FAMILY_T 1
|
#cmakedefine EVENT__HAVE_SA_FAMILY_T
|
||||||
|
|
||||||
/* Define to 1 if you have the `select' function. */
|
/* Define to 1 if you have the `select' function. */
|
||||||
#cmakedefine EVENT__HAVE_SELECT 1
|
#cmakedefine EVENT__HAVE_SELECT
|
||||||
|
|
||||||
/* Define to 1 if you have the `setenv' function. */
|
/* Define to 1 if you have the `setenv' function. */
|
||||||
#cmakedefine EVENT__HAVE_SETENV 1
|
#cmakedefine EVENT__HAVE_SETENV
|
||||||
|
|
||||||
/* Define if F_SETFD is defined in <fcntl.h> */
|
/* Define if F_SETFD is defined in <fcntl.h> */
|
||||||
#cmakedefine EVENT__HAVE_SETFD 1
|
#cmakedefine EVENT__HAVE_SETFD
|
||||||
|
|
||||||
/* Define to 1 if you have the `setrlimit' function. */
|
/* Define to 1 if you have the `setrlimit' function. */
|
||||||
#cmakedefine EVENT__HAVE_SETRLIMIT 1
|
#cmakedefine EVENT__HAVE_SETRLIMIT
|
||||||
|
|
||||||
/* Define to 1 if you have the `sendfile' function. */
|
/* Define to 1 if you have the `sendfile' function. */
|
||||||
#cmakedefine EVENT__HAVE_SENDFILE 1
|
#cmakedefine EVENT__HAVE_SENDFILE
|
||||||
|
|
||||||
/* Define if F_SETFD is defined in <fcntl.h> */
|
/* Define if F_SETFD is defined in <fcntl.h> */
|
||||||
#cmakedefine EVENT__HAVE_SETFD 1
|
#cmakedefine EVENT__HAVE_SETFD
|
||||||
|
|
||||||
/* Define to 1 if you have the `sigaction' function. */
|
/* Define to 1 if you have the `sigaction' function. */
|
||||||
#cmakedefine EVENT__HAVE_SIGACTION 1
|
#cmakedefine EVENT__HAVE_SIGACTION
|
||||||
|
|
||||||
/* Define to 1 if you have the `signal' function. */
|
/* Define to 1 if you have the `signal' function. */
|
||||||
#cmakedefine EVENT__HAVE_SIGNAL 1
|
#cmakedefine EVENT__HAVE_SIGNAL
|
||||||
|
|
||||||
/* Define to 1 if you have the `splice' function. */
|
/* Define to 1 if you have the `splice' function. */
|
||||||
#cmakedefine EVENT__HAVE_SPLICE 1
|
#cmakedefine EVENT__HAVE_SPLICE
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdarg.h> header file. */
|
/* Define to 1 if you have the <stdarg.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_STDARG_H 1
|
#cmakedefine EVENT__HAVE_STDARG_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <stddef.h> header file. */
|
/* Define to 1 if you have the <stddef.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_STDDEF_H 1
|
#cmakedefine EVENT__HAVE_STDDEF_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdint.h> header file. */
|
/* Define to 1 if you have the <stdint.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_STDINT_H 1
|
#cmakedefine EVENT__HAVE_STDINT_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_STDLIB_H 1
|
#cmakedefine EVENT__HAVE_STDLIB_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <strings.h> header file. */
|
/* Define to 1 if you have the <strings.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_STRINGS_H 1
|
#cmakedefine EVENT__HAVE_STRINGS_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <string.h> header file. */
|
/* Define to 1 if you have the <string.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_STRING_H 1
|
#cmakedefine EVENT__HAVE_STRING_H
|
||||||
|
|
||||||
/* Define to 1 if you have the `strlcpy' function. */
|
/* Define to 1 if you have the `strlcpy' function. */
|
||||||
#cmakedefine EVENT__HAVE_STRLCPY 1
|
#cmakedefine EVENT__HAVE_STRLCPY
|
||||||
|
|
||||||
/* Define to 1 if you have the `strsep' function. */
|
/* Define to 1 if you have the `strsep' function. */
|
||||||
#cmakedefine EVENT__HAVE_STRSEP 1
|
#cmakedefine EVENT__HAVE_STRSEP
|
||||||
|
|
||||||
/* Define to 1 if you have the `strtok_r' function. */
|
/* Define to 1 if you have the `strtok_r' function. */
|
||||||
#cmakedefine EVENT__HAVE_STRTOK_R 1
|
#cmakedefine EVENT__HAVE_STRTOK_R
|
||||||
|
|
||||||
/* Define to 1 if you have the `strtoll' function. */
|
/* Define to 1 if you have the `strtoll' function. */
|
||||||
#cmakedefine EVENT__HAVE_STRTOLL 1
|
#cmakedefine EVENT__HAVE_STRTOLL
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `struct addrinfo'. */
|
/* Define to 1 if the system has the type `struct addrinfo'. */
|
||||||
#cmakedefine EVENT__HAVE_STRUCT_ADDRINFO 1
|
#cmakedefine EVENT__HAVE_STRUCT_ADDRINFO
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `struct in6_addr'. */
|
/* Define to 1 if the system has the type `struct in6_addr'. */
|
||||||
#cmakedefine EVENT__HAVE_STRUCT_IN6_ADDR 1
|
#cmakedefine EVENT__HAVE_STRUCT_IN6_ADDR
|
||||||
|
|
||||||
/* Define to 1 if `s6_addr16' is member of `struct in6_addr'. */
|
/* Define to 1 if `s6_addr16' is member of `struct in6_addr'. */
|
||||||
#cmakedefine EVENT__HAVE_STRUCT_IN6_ADDR_S6_ADDR16 1
|
#cmakedefine EVENT__HAVE_STRUCT_IN6_ADDR_S6_ADDR16
|
||||||
|
|
||||||
/* Define to 1 if `s6_addr32' is member of `struct in6_addr'. */
|
/* Define to 1 if `s6_addr32' is member of `struct in6_addr'. */
|
||||||
#cmakedefine EVENT__HAVE_STRUCT_IN6_ADDR_S6_ADDR32 1
|
#cmakedefine EVENT__HAVE_STRUCT_IN6_ADDR_S6_ADDR32
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `struct sockaddr_in6'. */
|
/* Define to 1 if the system has the type `struct sockaddr_in6'. */
|
||||||
#cmakedefine EVENT__HAVE_STRUCT_SOCKADDR_IN6 1
|
#cmakedefine EVENT__HAVE_STRUCT_SOCKADDR_IN6
|
||||||
|
|
||||||
/* Define to 1 if `sin6_len' is member of `struct sockaddr_in6'. */
|
/* Define to 1 if `sin6_len' is member of `struct sockaddr_in6'. */
|
||||||
#cmakedefine EVENT__HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN 1
|
#cmakedefine EVENT__HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
|
||||||
|
|
||||||
/* Define to 1 if `sin_len' is member of `struct sockaddr_in'. */
|
/* Define to 1 if `sin_len' is member of `struct sockaddr_in'. */
|
||||||
#cmakedefine EVENT__HAVE_STRUCT_SOCKADDR_IN_SIN_LEN 1
|
#cmakedefine EVENT__HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `struct sockaddr_storage'. */
|
/* Define to 1 if the system has the type `struct sockaddr_storage'. */
|
||||||
#cmakedefine EVENT__HAVE_STRUCT_SOCKADDR_STORAGE 1
|
#cmakedefine EVENT__HAVE_STRUCT_SOCKADDR_STORAGE
|
||||||
|
|
||||||
/* Define to 1 if `ss_family' is a member of `struct sockaddr_storage'. */
|
/* Define to 1 if `ss_family' is a member of `struct sockaddr_storage'. */
|
||||||
#cmakedefine EVENT__HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY 1
|
#cmakedefine EVENT__HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY
|
||||||
|
|
||||||
/* Define to 1 if `__ss_family' is a member of `struct sockaddr_storage'. */
|
/* Define to 1 if `__ss_family' is a member of `struct sockaddr_storage'. */
|
||||||
#cmakedefine EVENT__HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY 1
|
#cmakedefine EVENT__HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY
|
||||||
|
|
||||||
/* Define to 1 if you have the `sysctl' function. */
|
/* Define to 1 if you have the `sysctl' function. */
|
||||||
#cmakedefine EVENT__HAVE_SYSCTL 1
|
#cmakedefine EVENT__HAVE_SYSCTL
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/devpoll.h> header file. */
|
/* Define to 1 if you have the <sys/devpoll.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_SYS_DEVPOLL_H 1
|
#cmakedefine EVENT__HAVE_SYS_DEVPOLL_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/epoll.h> header file. */
|
/* Define to 1 if you have the <sys/epoll.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_SYS_EPOLL_H 1
|
#cmakedefine EVENT__HAVE_SYS_EPOLL_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/eventfd.h> header file. */
|
/* Define to 1 if you have the <sys/eventfd.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_SYS_EVENTFD_H 1
|
#cmakedefine EVENT__HAVE_SYS_EVENTFD_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/event.h> header file. */
|
/* Define to 1 if you have the <sys/event.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_SYS_EVENT_H 1
|
#cmakedefine EVENT__HAVE_SYS_EVENT_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_SYS_IOCTL_H 1
|
#cmakedefine EVENT__HAVE_SYS_IOCTL_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/mman.h> header file. */
|
/* Define to 1 if you have the <sys/mman.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_SYS_MMAN_H 1
|
#cmakedefine EVENT__HAVE_SYS_MMAN_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_SYS_PARAM_H 1
|
#cmakedefine EVENT__HAVE_SYS_PARAM_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/queue.h> header file. */
|
/* Define to 1 if you have the <sys/queue.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_SYS_QUEUE_H 1
|
#cmakedefine EVENT__HAVE_SYS_QUEUE_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/resource.h> header file. */
|
/* Define to 1 if you have the <sys/resource.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_SYS_RESOURCE_H 1
|
#cmakedefine EVENT__HAVE_SYS_RESOURCE_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/select.h> header file. */
|
/* Define to 1 if you have the <sys/select.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_SYS_SELECT_H 1
|
#cmakedefine EVENT__HAVE_SYS_SELECT_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/sendfile.h> header file. */
|
/* Define to 1 if you have the <sys/sendfile.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_SYS_SENDFILE_H 1
|
#cmakedefine EVENT__HAVE_SYS_SENDFILE_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_SYS_SOCKET_H 1
|
#cmakedefine EVENT__HAVE_SYS_SOCKET_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_SYS_STAT_H 1
|
#cmakedefine EVENT__HAVE_SYS_STAT_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/sysctl.h> header file. */
|
/* Define to 1 if you have the <sys/sysctl.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_SYS_SYSCTL_H 1
|
#cmakedefine EVENT__HAVE_SYS_SYSCTL_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/timerfd.h> header file. */
|
/* Define to 1 if you have the <sys/timerfd.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_SYS_TIMERFD_H */
|
#cmakedefine EVENT__HAVE_SYS_TIMERFD_H */
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_SYS_TIME_H 1
|
#cmakedefine EVENT__HAVE_SYS_TIME_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_SYS_TYPES_H 1
|
#cmakedefine EVENT__HAVE_SYS_TYPES_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/uio.h> header file. */
|
/* Define to 1 if you have the <sys/uio.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_SYS_UIO_H 1
|
#cmakedefine EVENT__HAVE_SYS_UIO_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/wait.h> header file. */
|
/* Define to 1 if you have the <sys/wait.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_SYS_WAIT_H 1
|
#cmakedefine EVENT__HAVE_SYS_WAIT_H
|
||||||
|
|
||||||
/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */
|
/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */
|
||||||
#cmakedefine EVENT__HAVE_TAILQFOREACH 1
|
#cmakedefine EVENT__HAVE_TAILQFOREACH
|
||||||
|
|
||||||
/* Define if timeradd is defined in <sys/time.h> */
|
/* Define if timeradd is defined in <sys/time.h> */
|
||||||
#cmakedefine EVENT__HAVE_TIMERADD 1
|
#cmakedefine EVENT__HAVE_TIMERADD
|
||||||
|
|
||||||
/* Define if timerclear is defined in <sys/time.h> */
|
/* Define if timerclear is defined in <sys/time.h> */
|
||||||
#cmakedefine EVENT__HAVE_TIMERCLEAR 1
|
#cmakedefine EVENT__HAVE_TIMERCLEAR
|
||||||
|
|
||||||
/* Define if timercmp is defined in <sys/time.h> */
|
/* Define if timercmp is defined in <sys/time.h> */
|
||||||
#cmakedefine EVENT__HAVE_TIMERCMP 1
|
#cmakedefine EVENT__HAVE_TIMERCMP
|
||||||
|
|
||||||
/* Define to 1 if you have the `timerfd_create' function. */
|
/* Define to 1 if you have the `timerfd_create' function. */
|
||||||
#cmakedefine EVENT__HAVE_TIMERFD_CREATE 1
|
#cmakedefine EVENT__HAVE_TIMERFD_CREATE
|
||||||
|
|
||||||
/* Define if timerisset is defined in <sys/time.h> */
|
/* Define if timerisset is defined in <sys/time.h> */
|
||||||
#cmakedefine EVENT__HAVE_TIMERISSET 1
|
#cmakedefine EVENT__HAVE_TIMERISSET
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `uint8_t'. */
|
/* Define to 1 if the system has the type `uint8_t'. */
|
||||||
#cmakedefine EVENT__HAVE_UINT8_T 1
|
#cmakedefine EVENT__HAVE_UINT8_T
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `uint16_t'. */
|
/* Define to 1 if the system has the type `uint16_t'. */
|
||||||
#cmakedefine EVENT__HAVE_UINT16_T 1
|
#cmakedefine EVENT__HAVE_UINT16_T
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `uint32_t'. */
|
/* Define to 1 if the system has the type `uint32_t'. */
|
||||||
#cmakedefine EVENT__HAVE_UINT32_T 1
|
#cmakedefine EVENT__HAVE_UINT32_T
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `uint64_t'. */
|
/* Define to 1 if the system has the type `uint64_t'. */
|
||||||
#cmakedefine EVENT__HAVE_UINT64_T 1
|
#cmakedefine EVENT__HAVE_UINT64_T
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `uintptr_t'. */
|
/* Define to 1 if the system has the type `uintptr_t'. */
|
||||||
#cmakedefine EVENT__HAVE_UINTPTR_T 1
|
#cmakedefine EVENT__HAVE_UINTPTR_T
|
||||||
|
|
||||||
/* Define to 1 if you have the `umask' function. */
|
/* Define to 1 if you have the `umask' function. */
|
||||||
#cmakedefine EVENT__HAVE_UMASK 1
|
#cmakedefine EVENT__HAVE_UMASK
|
||||||
|
|
||||||
/* Define to 1 if you have the <unistd.h> header file. */
|
/* Define to 1 if you have the <unistd.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_UNISTD_H 1
|
#cmakedefine EVENT__HAVE_UNISTD_H
|
||||||
|
|
||||||
/* Define to 1 if you have the `unsetenv' function. */
|
/* Define to 1 if you have the `unsetenv' function. */
|
||||||
#cmakedefine EVENT__HAVE_UNSETENV 1
|
#cmakedefine EVENT__HAVE_UNSETENV
|
||||||
|
|
||||||
/* Define to 1 if you have the `vasprintf' function. */
|
/* Define to 1 if you have the `vasprintf' function. */
|
||||||
#cmakedefine EVENT__HAVE_VASPRINTF 1
|
#cmakedefine EVENT__HAVE_VASPRINTF
|
||||||
|
|
||||||
/* Define if kqueue works correctly with pipes */
|
/* Define if kqueue works correctly with pipes */
|
||||||
#cmakedefine EVENT__HAVE_WORKING_KQUEUE 1
|
#cmakedefine EVENT__HAVE_WORKING_KQUEUE
|
||||||
|
|
||||||
/* Define to necessary symbol if this constant uses a non-standard name on
|
#ifdef __USE_UNUSED_DEFINITIONS__
|
||||||
your system. */
|
/* Define to necessary symbol if this constant uses a non-standard name on your system. */
|
||||||
#cmakedefine EVENT__PTHREAD_CREATE_JOINABLE ${EVENT__PTHREAD_CREATE_JOINABLE}
|
/* XXX: Hello, this isn't even used, nor is it defined anywhere... - Ellzey */
|
||||||
|
#define EVENT__PTHREAD_CREATE_JOINABLE ${EVENT__PTHREAD_CREATE_JOINABLE}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* The size of `pthread_t', as computed by sizeof. */
|
/* The size of `pthread_t', as computed by sizeof. */
|
||||||
#cmakedefine EVENT__SIZEOF_PTHREAD_T ${EVENT__SIZEOF_PTHREAD_T}
|
#define EVENT__SIZEOF_PTHREAD_T @EVENT__SIZEOF_PTHREAD_T@
|
||||||
|
|
||||||
/* The size of a `int', as computed by sizeof. */
|
/* The size of a `int', as computed by sizeof. */
|
||||||
#cmakedefine EVENT__SIZEOF_INT ${EVENT__SIZEOF_INT}
|
#define EVENT__SIZEOF_INT @EVENT__SIZEOF_INT@
|
||||||
|
|
||||||
/* The size of a `long', as computed by sizeof. */
|
/* The size of a `long', as computed by sizeof. */
|
||||||
#cmakedefine EVENT__SIZEOF_LONG ${EVENT__SIZEOF_LONG}
|
#define EVENT__SIZEOF_LONG @EVENT__SIZEOF_LONG@
|
||||||
|
|
||||||
/* The size of a `long long', as computed by sizeof. */
|
/* The size of a `long long', as computed by sizeof. */
|
||||||
#cmakedefine EVENT__SIZEOF_LONG_LONG ${EVENT__SIZEOF_LONG_LONG}
|
#define EVENT__SIZEOF_LONG_LONG @EVENT__SIZEOF_LONG_LONG@
|
||||||
|
|
||||||
/* The size of `off_t', as computed by sizeof. */
|
/* The size of `off_t', as computed by sizeof. */
|
||||||
#cmakedefine EVENT__SIZEOF_OFF_T ${EVENT__SIZEOF_OFF_T}
|
#define EVENT__SIZEOF_OFF_T @EVENT__SIZEOF_OFF_T@
|
||||||
|
|
||||||
|
#define EVENT__SIZEOF_SSIZE_T @EVENT__SIZEOF_SSIZE_T@
|
||||||
|
|
||||||
|
|
||||||
/* The size of a `short', as computed by sizeof. */
|
/* The size of a `short', as computed by sizeof. */
|
||||||
#cmakedefine EVENT__SIZEOF_SHORT ${EVENT__SIZEOF_SHORT}
|
#define EVENT__SIZEOF_SHORT @EVENT__SIZEOF_SHORT@
|
||||||
|
|
||||||
/* The size of `size_t', as computed by sizeof. */
|
/* The size of `size_t', as computed by sizeof. */
|
||||||
#cmakedefine EVENT__SIZEOF_SIZE_T ${EVENT__SIZEOF_SIZE_T}
|
#define EVENT__SIZEOF_SIZE_T @EVENT__SIZEOF_SIZE_T@
|
||||||
|
|
||||||
/* Define to 1 if you have the ANSI C header files. */
|
/* Define to 1 if you have the ANSI C header files. */
|
||||||
#cmakedefine EVENT__STDC_HEADERS ${EVENT__STDC_HEADERS}
|
#cmakedefine EVENT__STDC_HEADERS
|
||||||
|
|
||||||
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
|
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
|
||||||
#cmakedefine EVENT__TIME_WITH_SYS_TIME ${EVENT__TIME_WITH_SYS_TIME}
|
#cmakedefine EVENT__TIME_WITH_SYS_TIME
|
||||||
|
|
||||||
/* The size of `socklen_t', as computed by sizeof. */
|
/* The size of `socklen_t', as computed by sizeof. */
|
||||||
#cmakedefine EVENT__SIZEOF_SOCKLEN_T ${EVENT__SIZEOF_SOCKLEN_T}
|
#define EVENT__SIZEOF_SOCKLEN_T @EVENT__SIZEOF_SOCKLEN_T@
|
||||||
|
|
||||||
/* The size of 'void *', as computer by sizeof */
|
/* The size of 'void *', as computer by sizeof */
|
||||||
#cmakedefine EVENT__SIZEOF_VOID_P ${EVENT__SIZEOF_VOID_P}
|
#define EVENT__SIZEOF_VOID_P @EVENT__SIZEOF_VOID_P@
|
||||||
|
|
||||||
/* Define to appropriate substitute if compiler doesnt have __func__ */
|
/* set an alias for whatever __func__ __FUNCTION__ is, what sillyness */
|
||||||
#cmakedefine EVENT____func__ ${EVENT____func__}
|
#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. */
|
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||||
#cmakedefine EVENT___FILE_OFFSET_BITS ${EVENT___FILE_OFFSET_BITS}
|
/* Ellzey is not satisfied */
|
||||||
|
#define EVENT___FILE_OFFSET_BITS @EVENT___FILE_OFFSET_BITS@
|
||||||
|
|
||||||
/* Define for large files, on AIX-style hosts. */
|
/* Define for large files, on AIX-style hosts. */
|
||||||
/* #undef _LARGE_FILES */
|
#define @_LARGE_FILES@
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WhAT_DOES_THIS_EVEN_DO_
|
||||||
/* Define to empty if `const' does not conform to ANSI C. */
|
/* Define to empty if `const' does not conform to ANSI C. */
|
||||||
/* #undef EVENT__const */
|
/* lolwut? - ellzey */
|
||||||
|
#undef EVENT__const
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
/* 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. */
|
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
#cmakedefine EVENT__inline ${EVENT__inline}
|
/* why not c++?
|
||||||
|
*
|
||||||
|
* and are we really expected to use EVENT__inline everywhere,
|
||||||
|
* shouldn't we just do:
|
||||||
|
* ifdef EVENT__inline
|
||||||
|
* define inline EVENT__inline
|
||||||
|
*
|
||||||
|
* - Ellzey
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define EVENT__inline @EVENT__inline@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Define to `int' if <sys/types.h> does not define. */
|
/* Define to `int' if <sys/tyes.h> does not define. */
|
||||||
#cmakedefine EVENT__pid_t ${EVENT__pid_t}
|
#define EVENT__pid_t @EVENT__pid_t@
|
||||||
|
|
||||||
/* Define to `unsigned' if <sys/types.h> does not define. */
|
/* Define to `unsigned' if <sys/types.h> does not define. */
|
||||||
#cmakedefine EVENT__size_t ${EVENT__size_t}
|
#define EVENT__size_t @EVENT__size_t@
|
||||||
|
|
||||||
/* Define to unsigned int if you dont have it */
|
/* Define to unsigned int if you dont have it */
|
||||||
#cmakedefine EVENT__socklen_t ${EVENT__socklen_t}
|
#define EVENT__socklen_t @EVENT__socklen_t@
|
||||||
|
|
||||||
/* Define to `int' if <sys/types.h> does not define. */
|
/* Define to `int' if <sys/types.h> does not define. */
|
||||||
#cmakedefine EVENT__ssize_t ${EVENT__ssize_t}
|
#define EVENT__ssize_t @EVENT__ssize_t@
|
||||||
|
|
||||||
#cmakedefine EVENT__NEED_DLLIMPORT ${EVENT__NEED_DLLIMPORT}
|
#define EVENT__NEED_DLLIMPORT @EVENT__NEED_DLLIMPORT@
|
||||||
|
|
||||||
|
/* Define to 1 if you have ERR_remove_thread_stat(). */
|
||||||
|
#cmakedefine EVENT__HAVE_ERR_REMOVE_THREAD_STATE
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -368,7 +368,6 @@ struct event_config {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Internal use only: Functions that might be missing from <sys/queue.h> */
|
/* Internal use only: Functions that might be missing from <sys/queue.h> */
|
||||||
#if defined(EVENT__HAVE_SYS_QUEUE_H) && !defined(EVENT__HAVE_TAILQFOREACH)
|
|
||||||
#ifndef TAILQ_FIRST
|
#ifndef TAILQ_FIRST
|
||||||
#define TAILQ_FIRST(head) ((head)->tqh_first)
|
#define TAILQ_FIRST(head) ((head)->tqh_first)
|
||||||
#endif
|
#endif
|
||||||
@ -394,7 +393,6 @@ struct event_config {
|
|||||||
(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
|
(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
|
||||||
} while (0)
|
} while (0)
|
||||||
#endif
|
#endif
|
||||||
#endif /* TAILQ_FOREACH */
|
|
||||||
|
|
||||||
#define N_ACTIVE_CALLBACKS(base) \
|
#define N_ACTIVE_CALLBACKS(base) \
|
||||||
((base)->event_count_active)
|
((base)->event_count_active)
|
||||||
@ -467,6 +465,13 @@ void event_base_assert_ok_nolock_(struct event_base *base);
|
|||||||
int event_base_foreach_event_nolock_(struct event_base *base,
|
int event_base_foreach_event_nolock_(struct event_base *base,
|
||||||
event_base_foreach_event_cb cb, void *arg);
|
event_base_foreach_event_cb cb, void *arg);
|
||||||
|
|
||||||
|
/* Cleanup function to reset debug mode during shutdown.
|
||||||
|
*
|
||||||
|
* Calling this function doesn't mean it'll be possible to re-enable
|
||||||
|
* debug mode if any events were added.
|
||||||
|
*/
|
||||||
|
void event_disable_debug_mode(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
6
event.3
6
event.3
@ -183,14 +183,14 @@
|
|||||||
.Fn "evbuffer_write" "struct evbuffer *buf" "int fd"
|
.Fn "evbuffer_write" "struct evbuffer *buf" "int fd"
|
||||||
.Ft int
|
.Ft int
|
||||||
.Fn "evbuffer_read" "struct evbuffer *buf" "int fd" "int size"
|
.Fn "evbuffer_read" "struct evbuffer *buf" "int fd" "int size"
|
||||||
.Ft "u_char *"
|
.Ft "unsigned char *"
|
||||||
.Fn "evbuffer_find" "struct evbuffer *buf" "const u_char *data" "size_t size"
|
.Fn "evbuffer_find" "struct evbuffer *buf" "const unsigned char *data" "size_t size"
|
||||||
.Ft "char *"
|
.Ft "char *"
|
||||||
.Fn "evbuffer_readline" "struct evbuffer *buf"
|
.Fn "evbuffer_readline" "struct evbuffer *buf"
|
||||||
.Ft "struct evhttp *"
|
.Ft "struct evhttp *"
|
||||||
.Fn "evhttp_new" "struct event_base *base"
|
.Fn "evhttp_new" "struct event_base *base"
|
||||||
.Ft int
|
.Ft int
|
||||||
.Fn "evhttp_bind_socket" "struct evhttp *http" "const char *address" "u_short port"
|
.Fn "evhttp_bind_socket" "struct evhttp *http" "const char *address" "unsigned short port"
|
||||||
.Ft "void"
|
.Ft "void"
|
||||||
.Fn "evhttp_free" "struct evhttp *http"
|
.Fn "evhttp_free" "struct evhttp *http"
|
||||||
.Ft int
|
.Ft int
|
||||||
|
69
event.c
69
event.c
@ -199,6 +199,22 @@ eq_debug_entry(const struct event_debug_entry *a,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int event_debug_mode_on_ = 0;
|
int event_debug_mode_on_ = 0;
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(EVENT__DISABLE_THREAD_SUPPORT) && !defined(EVENT__DISABLE_DEBUG_MODE)
|
||||||
|
/**
|
||||||
|
* @brief debug mode variable which is set for any function/structure that needs
|
||||||
|
* to be shared across threads (if thread support is enabled).
|
||||||
|
*
|
||||||
|
* When and if evthreads are initialized, this variable will be evaluated,
|
||||||
|
* and if set to something other than zero, this means the evthread setup
|
||||||
|
* functions were called out of order.
|
||||||
|
*
|
||||||
|
* See: "Locks and threading" in the documentation.
|
||||||
|
*/
|
||||||
|
int event_debug_created_threadable_ctx_ = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Set if it's too late to enable event_debug_mode. */
|
/* Set if it's too late to enable event_debug_mode. */
|
||||||
static int event_debug_mode_too_late = 0;
|
static int event_debug_mode_too_late = 0;
|
||||||
#ifndef EVENT__DISABLE_THREAD_SUPPORT
|
#ifndef EVENT__DISABLE_THREAD_SUPPORT
|
||||||
@ -655,6 +671,10 @@ event_base_new_with_config(const struct event_config *cfg)
|
|||||||
|
|
||||||
/* prepare for threading */
|
/* prepare for threading */
|
||||||
|
|
||||||
|
#if !defined(EVENT__DISABLE_THREAD_SUPPORT) && !defined(EVENT__DISABLE_DEBUG_MODE)
|
||||||
|
event_debug_created_threadable_ctx_ = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef EVENT__DISABLE_THREAD_SUPPORT
|
#ifndef EVENT__DISABLE_THREAD_SUPPORT
|
||||||
if (EVTHREAD_LOCKING_ENABLED() &&
|
if (EVTHREAD_LOCKING_ENABLED() &&
|
||||||
(!cfg || !(cfg->flags & EVENT_BASE_FLAG_NOLOCK))) {
|
(!cfg || !(cfg->flags & EVENT_BASE_FLAG_NOLOCK))) {
|
||||||
@ -749,6 +769,29 @@ event_base_cancel_single_callback_(struct event_base *base,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int event_base_free_queues_(struct event_base *base, int run_finalizers)
|
||||||
|
{
|
||||||
|
int deleted = 0, i;
|
||||||
|
|
||||||
|
for (i = 0; i < base->nactivequeues; ++i) {
|
||||||
|
struct event_callback *evcb, *next;
|
||||||
|
for (evcb = TAILQ_FIRST(&base->activequeues[i]); evcb; ) {
|
||||||
|
next = TAILQ_NEXT(evcb, evcb_active_next);
|
||||||
|
deleted += event_base_cancel_single_callback_(base, evcb, run_finalizers);
|
||||||
|
evcb = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
struct event_callback *evcb;
|
||||||
|
while ((evcb = TAILQ_FIRST(&base->active_later_queue))) {
|
||||||
|
deleted += event_base_cancel_single_callback_(base, evcb, run_finalizers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return deleted;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
event_base_free_(struct event_base *base, int run_finalizers)
|
event_base_free_(struct event_base *base, int run_finalizers)
|
||||||
{
|
{
|
||||||
@ -809,21 +852,21 @@ event_base_free_(struct event_base *base, int run_finalizers)
|
|||||||
if (base->common_timeout_queues)
|
if (base->common_timeout_queues)
|
||||||
mm_free(base->common_timeout_queues);
|
mm_free(base->common_timeout_queues);
|
||||||
|
|
||||||
for (i = 0; i < base->nactivequeues; ++i) {
|
for (;;) {
|
||||||
struct event_callback *evcb, *next;
|
/* For finalizers we can register yet another finalizer out from
|
||||||
for (evcb = TAILQ_FIRST(&base->activequeues[i]); evcb; ) {
|
* finalizer, and iff finalizer will be in active_later_queue we can
|
||||||
next = TAILQ_NEXT(evcb, evcb_active_next);
|
* add finalizer to activequeues, and we will have events in
|
||||||
n_deleted += event_base_cancel_single_callback_(base, evcb, run_finalizers);
|
* activequeues after this function returns, which is not what we want
|
||||||
evcb = next;
|
* (we even have an assertion for this).
|
||||||
|
*
|
||||||
|
* A simple case is bufferevent with underlying (i.e. filters).
|
||||||
|
*/
|
||||||
|
int i = event_base_free_queues_(base, run_finalizers);
|
||||||
|
if (!i) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
n_deleted += i;
|
||||||
}
|
}
|
||||||
{
|
|
||||||
struct event_callback *evcb;
|
|
||||||
while ((evcb = TAILQ_FIRST(&base->active_later_queue))) {
|
|
||||||
n_deleted += event_base_cancel_single_callback_(base, evcb, run_finalizers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (n_deleted)
|
if (n_deleted)
|
||||||
event_debug(("%s: %d events were still set in base",
|
event_debug(("%s: %d events were still set in base",
|
||||||
|
@ -40,10 +40,11 @@
|
|||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#undef WIN32_LEAN_AND_MEAN
|
#undef WIN32_LEAN_AND_MEAN
|
||||||
#else
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef EVENT__HAVE_SYS_IOCTL_H
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#endif
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
#ifdef EVENT__HAVE_SYS_TIME_H
|
#ifdef EVENT__HAVE_SYS_TIME_H
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
48
evthread.c
48
evthread.c
@ -45,6 +45,11 @@
|
|||||||
#define GLOBAL static
|
#define GLOBAL static
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef EVENT__DISABLE_DEBUG_MODE
|
||||||
|
extern int event_debug_created_threadable_ctx_;
|
||||||
|
extern int event_debug_mode_on_;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* globals */
|
/* globals */
|
||||||
GLOBAL int evthread_lock_debugging_enabled_ = 0;
|
GLOBAL int evthread_lock_debugging_enabled_ = 0;
|
||||||
GLOBAL struct evthread_lock_callbacks evthread_lock_fns_ = {
|
GLOBAL struct evthread_lock_callbacks evthread_lock_fns_ = {
|
||||||
@ -89,6 +94,14 @@ evthread_set_lock_callbacks(const struct evthread_lock_callbacks *cbs)
|
|||||||
{
|
{
|
||||||
struct evthread_lock_callbacks *target = evthread_get_lock_callbacks();
|
struct evthread_lock_callbacks *target = evthread_get_lock_callbacks();
|
||||||
|
|
||||||
|
#ifndef EVENT__DISABLE_DEBUG_MODE
|
||||||
|
if (event_debug_mode_on_) {
|
||||||
|
if (event_debug_created_threadable_ctx_) {
|
||||||
|
event_errx(1, "evthread initialization must be called BEFORE anything else!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!cbs) {
|
if (!cbs) {
|
||||||
if (target->alloc)
|
if (target->alloc)
|
||||||
event_warnx("Trying to disable lock functions after "
|
event_warnx("Trying to disable lock functions after "
|
||||||
@ -124,6 +137,14 @@ evthread_set_condition_callbacks(const struct evthread_condition_callbacks *cbs)
|
|||||||
{
|
{
|
||||||
struct evthread_condition_callbacks *target = evthread_get_condition_callbacks();
|
struct evthread_condition_callbacks *target = evthread_get_condition_callbacks();
|
||||||
|
|
||||||
|
#ifndef EVENT__DISABLE_DEBUG_MODE
|
||||||
|
if (event_debug_mode_on_) {
|
||||||
|
if (event_debug_created_threadable_ctx_) {
|
||||||
|
event_errx(1, "evthread initialization must be called BEFORE anything else!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!cbs) {
|
if (!cbs) {
|
||||||
if (target->alloc_condition)
|
if (target->alloc_condition)
|
||||||
event_warnx("Trying to disable condition functions "
|
event_warnx("Trying to disable condition functions "
|
||||||
@ -380,17 +401,18 @@ evthread_setup_global_lock_(void *lock_, unsigned locktype, int enable_locks)
|
|||||||
return evthread_lock_fns_.alloc(locktype);
|
return evthread_lock_fns_.alloc(locktype);
|
||||||
} else {
|
} else {
|
||||||
/* Case 4: Fill in a debug lock with a real lock */
|
/* Case 4: Fill in a debug lock with a real lock */
|
||||||
struct debug_lock *lock = lock_;
|
struct debug_lock *lock = lock_ ? lock_ : debug_lock_alloc(locktype);
|
||||||
EVUTIL_ASSERT(enable_locks &&
|
EVUTIL_ASSERT(enable_locks &&
|
||||||
evthread_lock_debugging_enabled_);
|
evthread_lock_debugging_enabled_);
|
||||||
EVUTIL_ASSERT(lock->locktype == locktype);
|
EVUTIL_ASSERT(lock->locktype == locktype);
|
||||||
EVUTIL_ASSERT(lock->lock == NULL);
|
|
||||||
lock->lock = original_lock_fns_.alloc(
|
|
||||||
locktype|EVTHREAD_LOCKTYPE_RECURSIVE);
|
|
||||||
if (!lock->lock) {
|
if (!lock->lock) {
|
||||||
lock->count = -200;
|
lock->lock = original_lock_fns_.alloc(
|
||||||
mm_free(lock);
|
locktype|EVTHREAD_LOCKTYPE_RECURSIVE);
|
||||||
return NULL;
|
if (!lock->lock) {
|
||||||
|
lock->count = -200;
|
||||||
|
mm_free(lock);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return lock;
|
return lock;
|
||||||
}
|
}
|
||||||
@ -406,6 +428,12 @@ evthreadimpl_get_id_()
|
|||||||
void *
|
void *
|
||||||
evthreadimpl_lock_alloc_(unsigned locktype)
|
evthreadimpl_lock_alloc_(unsigned locktype)
|
||||||
{
|
{
|
||||||
|
#ifndef EVENT__DISABLE_DEBUG_MODE
|
||||||
|
if (event_debug_mode_on_) {
|
||||||
|
event_debug_created_threadable_ctx_ = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return evthread_lock_fns_.alloc ?
|
return evthread_lock_fns_.alloc ?
|
||||||
evthread_lock_fns_.alloc(locktype) : NULL;
|
evthread_lock_fns_.alloc(locktype) : NULL;
|
||||||
}
|
}
|
||||||
@ -434,6 +462,12 @@ evthreadimpl_lock_unlock_(unsigned mode, void *lock)
|
|||||||
void *
|
void *
|
||||||
evthreadimpl_cond_alloc_(unsigned condtype)
|
evthreadimpl_cond_alloc_(unsigned condtype)
|
||||||
{
|
{
|
||||||
|
#ifndef EVENT__DISABLE_DEBUG_MODE
|
||||||
|
if (event_debug_mode_on_) {
|
||||||
|
event_debug_created_threadable_ctx_ = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return evthread_cond_fns_.alloc_condition ?
|
return evthread_cond_fns_.alloc_condition ?
|
||||||
evthread_cond_fns_.alloc_condition(condtype) : NULL;
|
evthread_cond_fns_.alloc_condition(condtype) : NULL;
|
||||||
}
|
}
|
||||||
|
26
evutil.c
26
evutil.c
@ -226,16 +226,17 @@ evutil_ersatz_socketpair_(int family, int type, int protocol,
|
|||||||
struct sockaddr_in connect_addr;
|
struct sockaddr_in connect_addr;
|
||||||
ev_socklen_t size;
|
ev_socklen_t size;
|
||||||
int saved_errno = -1;
|
int saved_errno = -1;
|
||||||
|
int family_test;
|
||||||
if (protocol
|
|
||||||
|| (family != AF_INET
|
family_test = family != AF_INET;
|
||||||
#ifdef AF_UNIX
|
#ifdef AF_UNIX
|
||||||
&& family != AF_UNIX
|
family_test = family_test && (family != AF_UNIX);
|
||||||
#endif
|
#endif
|
||||||
)) {
|
if (protocol || family_test) {
|
||||||
EVUTIL_SET_SOCKET_ERROR(ERR(EAFNOSUPPORT));
|
EVUTIL_SET_SOCKET_ERROR(ERR(EAFNOSUPPORT));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fd) {
|
if (!fd) {
|
||||||
EVUTIL_SET_SOCKET_ERROR(ERR(EINVAL));
|
EVUTIL_SET_SOCKET_ERROR(ERR(EINVAL));
|
||||||
return -1;
|
return -1;
|
||||||
@ -257,6 +258,9 @@ evutil_ersatz_socketpair_(int family, int type, int protocol,
|
|||||||
connector = socket(AF_INET, type, 0);
|
connector = socket(AF_INET, type, 0);
|
||||||
if (connector < 0)
|
if (connector < 0)
|
||||||
goto tidy_up_and_fail;
|
goto tidy_up_and_fail;
|
||||||
|
|
||||||
|
memset(&connect_addr, 0, sizeof(connect_addr));
|
||||||
|
|
||||||
/* We want to find out the port number to connect to. */
|
/* We want to find out the port number to connect to. */
|
||||||
size = sizeof(connect_addr);
|
size = sizeof(connect_addr);
|
||||||
if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1)
|
if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1)
|
||||||
@ -310,7 +314,7 @@ evutil_make_socket_nonblocking(evutil_socket_t fd)
|
|||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
{
|
{
|
||||||
u_long nonblocking = 1;
|
unsigned long nonblocking = 1;
|
||||||
if (ioctlsocket(fd, FIONBIO, &nonblocking) == SOCKET_ERROR) {
|
if (ioctlsocket(fd, FIONBIO, &nonblocking) == SOCKET_ERROR) {
|
||||||
event_sock_warn(fd, "fcntl(%d, F_GETFL)", (int)fd);
|
event_sock_warn(fd, "fcntl(%d, F_GETFL)", (int)fd);
|
||||||
return -1;
|
return -1;
|
||||||
@ -355,7 +359,7 @@ evutil_fast_socket_nonblocking(evutil_socket_t fd)
|
|||||||
int
|
int
|
||||||
evutil_make_listen_socket_reuseable(evutil_socket_t sock)
|
evutil_make_listen_socket_reuseable(evutil_socket_t sock)
|
||||||
{
|
{
|
||||||
#ifndef _WIN32
|
#if defined(SO_REUSEADDR) && !defined(_WIN32)
|
||||||
int one = 1;
|
int one = 1;
|
||||||
/* REUSEADDR on Unix means, "don't hang on to this address after the
|
/* REUSEADDR on Unix means, "don't hang on to this address after the
|
||||||
* listener is closed." On Windows, though, it means "don't keep other
|
* listener is closed." On Windows, though, it means "don't keep other
|
||||||
@ -520,7 +524,7 @@ evutil_socket_geterror(evutil_socket_t sock)
|
|||||||
/* XXX we should use an enum here. */
|
/* XXX we should use an enum here. */
|
||||||
/* 2 for connection refused, 1 for connected, 0 for not yet, -1 for error. */
|
/* 2 for connection refused, 1 for connected, 0 for not yet, -1 for error. */
|
||||||
int
|
int
|
||||||
evutil_socket_connect_(evutil_socket_t *fd_ptr, struct sockaddr *sa, int socklen)
|
evutil_socket_connect_(evutil_socket_t *fd_ptr, const struct sockaddr *sa, int socklen)
|
||||||
{
|
{
|
||||||
int made_fd = 0;
|
int made_fd = 0;
|
||||||
|
|
||||||
@ -1159,7 +1163,7 @@ addrinfo_from_hostent(const struct hostent *ent,
|
|||||||
sin6.sin6_family = AF_INET6;
|
sin6.sin6_family = AF_INET6;
|
||||||
sin6.sin6_port = htons(port);
|
sin6.sin6_port = htons(port);
|
||||||
sa = (struct sockaddr *)&sin6;
|
sa = (struct sockaddr *)&sin6;
|
||||||
socklen = sizeof(struct sockaddr_in);
|
socklen = sizeof(struct sockaddr_in6);
|
||||||
addrp = &sin6.sin6_addr;
|
addrp = &sin6.sin6_addr;
|
||||||
if (ent->h_length != sizeof(sin6.sin6_addr)) {
|
if (ent->h_length != sizeof(sin6.sin6_addr)) {
|
||||||
event_warnx("Weird h_length from gethostbyname");
|
event_warnx("Weird h_length from gethostbyname");
|
||||||
@ -1705,10 +1709,10 @@ evutil_socket_error_to_string(int errcode)
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 != FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
|
if (0 != FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
|
||||||
FORMAT_MESSAGE_IGNORE_INSERTS |
|
FORMAT_MESSAGE_IGNORE_INSERTS |
|
||||||
FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
||||||
NULL, errcode, 0, (LPTSTR)&msg, 0, NULL))
|
NULL, errcode, 0, (char *)&msg, 0, NULL))
|
||||||
chomp (msg); /* because message has trailing newline */
|
chomp (msg); /* because message has trailing newline */
|
||||||
else {
|
else {
|
||||||
size_t len = 50;
|
size_t len = 50;
|
||||||
|
@ -62,10 +62,10 @@ struct evhttp_connection {
|
|||||||
struct event retry_ev; /* for retrying connects */
|
struct event retry_ev; /* for retrying connects */
|
||||||
|
|
||||||
char *bind_address; /* address to use for binding the src */
|
char *bind_address; /* address to use for binding the src */
|
||||||
u_short bind_port; /* local port for binding the src */
|
unsigned short bind_port; /* local port for binding the src */
|
||||||
|
|
||||||
char *address; /* address to connect to */
|
char *address; /* address to connect to */
|
||||||
u_short port;
|
unsigned short port;
|
||||||
|
|
||||||
size_t max_headers_size;
|
size_t max_headers_size;
|
||||||
ev_uint64_t max_body_size;
|
ev_uint64_t max_body_size;
|
||||||
@ -101,13 +101,6 @@ struct evhttp_connection {
|
|||||||
struct event_base *base;
|
struct event_base *base;
|
||||||
struct evdns_base *dns_base;
|
struct evdns_base *dns_base;
|
||||||
int ai_family;
|
int ai_family;
|
||||||
|
|
||||||
/* Saved conn_addr, to extract IP address from it.
|
|
||||||
*
|
|
||||||
* Because some servers may reset/close connection without waiting clients,
|
|
||||||
* in that case we can't extract IP address even in close_cb.
|
|
||||||
* So we need to save it, just after we connected to remote server. */
|
|
||||||
struct sockaddr_storage *conn_address;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A callback for an http server */
|
/* A callback for an http server */
|
||||||
|
139
http.c
139
http.c
@ -35,18 +35,22 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef EVENT__HAVE_SYS_TIME_H
|
|
||||||
#include <sys/time.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SYS_IOCCOM_H
|
#ifdef HAVE_SYS_IOCCOM_H
|
||||||
#include <sys/ioccom.h>
|
#include <sys/ioccom.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef EVENT__HAVE_SYS_RESOURCE_H
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#endif
|
||||||
|
#ifdef EVENT__HAVE_SYS_TIME_H
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
#ifdef EVENT__HAVE_SYS_WAIT_H
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include <sys/resource.h>
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/wait.h>
|
|
||||||
#else
|
#else
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
@ -461,6 +465,13 @@ evhttp_is_connection_close(int flags, struct evkeyvalq* headers)
|
|||||||
return (connection != NULL && evutil_ascii_strcasecmp(connection, "close") == 0);
|
return (connection != NULL && evutil_ascii_strcasecmp(connection, "close") == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static int
|
||||||
|
evhttp_is_request_connection_close(struct evhttp_request *req)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
evhttp_is_connection_close(req->flags, req->input_headers) ||
|
||||||
|
evhttp_is_connection_close(req->flags, req->output_headers);
|
||||||
|
}
|
||||||
|
|
||||||
/* Return true iff 'headers' contains 'Connection: keep-alive' */
|
/* Return true iff 'headers' contains 'Connection: keep-alive' */
|
||||||
static int
|
static int
|
||||||
@ -674,6 +685,23 @@ evhttp_connection_incoming_fail(struct evhttp_request *req,
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Free connection ownership of which can be acquired by user using
|
||||||
|
* evhttp_request_own(). */
|
||||||
|
static inline void
|
||||||
|
evhttp_request_free_auto(struct evhttp_request *req)
|
||||||
|
{
|
||||||
|
if (!(req->flags & EVHTTP_USER_OWNED)) {
|
||||||
|
evhttp_request_free(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
evhttp_request_free_(struct evhttp_connection *evcon, struct evhttp_request *req)
|
||||||
|
{
|
||||||
|
TAILQ_REMOVE(&evcon->requests, req, next);
|
||||||
|
evhttp_request_free_auto(req);
|
||||||
|
}
|
||||||
|
|
||||||
/* Called when evcon has experienced a (non-recoverable? -NM) error, as
|
/* Called when evcon has experienced a (non-recoverable? -NM) error, as
|
||||||
* given in error. If it's an outgoing connection, reset the connection,
|
* given in error. If it's an outgoing connection, reset the connection,
|
||||||
* retry any pending requests, and inform the user. If it's incoming,
|
* retry any pending requests, and inform the user. If it's incoming,
|
||||||
@ -722,8 +750,7 @@ evhttp_connection_fail_(struct evhttp_connection *evcon,
|
|||||||
* send over a new connection. when a user cancels a request,
|
* send over a new connection. when a user cancels a request,
|
||||||
* all other pending requests should be processed as normal
|
* all other pending requests should be processed as normal
|
||||||
*/
|
*/
|
||||||
TAILQ_REMOVE(&evcon->requests, req, next);
|
evhttp_request_free_(evcon, req);
|
||||||
evhttp_request_free(req);
|
|
||||||
|
|
||||||
/* reset the connection */
|
/* reset the connection */
|
||||||
evhttp_connection_reset_(evcon);
|
evhttp_connection_reset_(evcon);
|
||||||
@ -773,16 +800,12 @@ evhttp_connection_done(struct evhttp_connection *evcon)
|
|||||||
|
|
||||||
if (con_outgoing) {
|
if (con_outgoing) {
|
||||||
/* idle or close the connection */
|
/* idle or close the connection */
|
||||||
int need_close;
|
int need_close = evhttp_is_request_connection_close(req);
|
||||||
TAILQ_REMOVE(&evcon->requests, req, next);
|
TAILQ_REMOVE(&evcon->requests, req, next);
|
||||||
req->evcon = NULL;
|
req->evcon = NULL;
|
||||||
|
|
||||||
evcon->state = EVCON_IDLE;
|
evcon->state = EVCON_IDLE;
|
||||||
|
|
||||||
need_close =
|
|
||||||
evhttp_is_connection_close(req->flags, req->input_headers)||
|
|
||||||
evhttp_is_connection_close(req->flags, req->output_headers);
|
|
||||||
|
|
||||||
/* check if we got asked to close the connection */
|
/* check if we got asked to close the connection */
|
||||||
if (need_close)
|
if (need_close)
|
||||||
evhttp_connection_reset_(evcon);
|
evhttp_connection_reset_(evcon);
|
||||||
@ -820,11 +843,9 @@ evhttp_connection_done(struct evhttp_connection *evcon)
|
|||||||
/* notify the user of the request */
|
/* notify the user of the request */
|
||||||
(*req->cb)(req, req->cb_arg);
|
(*req->cb)(req, req->cb_arg);
|
||||||
|
|
||||||
/* if this was an outgoing request, we own and it's done. so free it.
|
/* if this was an outgoing request, we own and it's done. so free it. */
|
||||||
* unless the callback specifically requested to own the request.
|
if (con_outgoing) {
|
||||||
*/
|
evhttp_request_free_auto(req);
|
||||||
if (con_outgoing && ((req->flags & EVHTTP_USER_OWNED) == 0)) {
|
|
||||||
evhttp_request_free(req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If this was the last request of an outgoing connection and we're
|
/* If this was the last request of an outgoing connection and we're
|
||||||
@ -960,7 +981,6 @@ evhttp_read_trailer(struct evhttp_connection *evcon, struct evhttp_request *req)
|
|||||||
case MORE_DATA_EXPECTED:
|
case MORE_DATA_EXPECTED:
|
||||||
case REQUEST_CANCELED: /* ??? */
|
case REQUEST_CANCELED: /* ??? */
|
||||||
default:
|
default:
|
||||||
bufferevent_enable(evcon->bufev, EV_READ);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -985,7 +1005,7 @@ evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
|
|||||||
return;
|
return;
|
||||||
case REQUEST_CANCELED:
|
case REQUEST_CANCELED:
|
||||||
/* request canceled */
|
/* request canceled */
|
||||||
evhttp_request_free(req);
|
evhttp_request_free_auto(req);
|
||||||
return;
|
return;
|
||||||
case MORE_DATA_EXPECTED:
|
case MORE_DATA_EXPECTED:
|
||||||
default:
|
default:
|
||||||
@ -1031,7 +1051,7 @@ evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
|
|||||||
evbuffer_drain(req->input_buffer,
|
evbuffer_drain(req->input_buffer,
|
||||||
evbuffer_get_length(req->input_buffer));
|
evbuffer_get_length(req->input_buffer));
|
||||||
if ((req->flags & EVHTTP_REQ_NEEDS_FREE) != 0) {
|
if ((req->flags & EVHTTP_REQ_NEEDS_FREE) != 0) {
|
||||||
evhttp_request_free(req);
|
evhttp_request_free_auto(req);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1042,9 +1062,6 @@ evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
|
|||||||
evhttp_connection_done(evcon);
|
evhttp_connection_done(evcon);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read more! */
|
|
||||||
bufferevent_enable(evcon->bufev, EV_READ);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define get_deferred_queue(evcon) \
|
#define get_deferred_queue(evcon) \
|
||||||
@ -1125,6 +1142,9 @@ evhttp_write_connectioncb(struct evhttp_connection *evcon, void *arg)
|
|||||||
|
|
||||||
EVUTIL_ASSERT(evcon->state == EVCON_WRITING);
|
EVUTIL_ASSERT(evcon->state == EVCON_WRITING);
|
||||||
|
|
||||||
|
/* We need to wait until we've written all of our output data before we can continue */
|
||||||
|
if (evbuffer_get_length(bufferevent_get_output(evcon->bufev)) > 0) { return; }
|
||||||
|
|
||||||
/* We are done writing our header and are now expecting the response */
|
/* We are done writing our header and are now expecting the response */
|
||||||
req->kind = EVHTTP_RESPONSE;
|
req->kind = EVHTTP_RESPONSE;
|
||||||
|
|
||||||
@ -1152,8 +1172,7 @@ evhttp_connection_free(struct evhttp_connection *evcon)
|
|||||||
* evhttp_connection_fail_.
|
* evhttp_connection_fail_.
|
||||||
*/
|
*/
|
||||||
while ((req = TAILQ_FIRST(&evcon->requests)) != NULL) {
|
while ((req = TAILQ_FIRST(&evcon->requests)) != NULL) {
|
||||||
TAILQ_REMOVE(&evcon->requests, req, next);
|
evhttp_request_free_(evcon, req);
|
||||||
evhttp_request_free(req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (evcon->http_server != NULL) {
|
if (evcon->http_server != NULL) {
|
||||||
@ -1173,6 +1192,7 @@ evhttp_connection_free(struct evhttp_connection *evcon)
|
|||||||
&evcon->read_more_deferred_cb);
|
&evcon->read_more_deferred_cb);
|
||||||
|
|
||||||
if (evcon->fd != -1) {
|
if (evcon->fd != -1) {
|
||||||
|
bufferevent_disable(evcon->bufev, EV_READ|EV_WRITE);
|
||||||
shutdown(evcon->fd, EVUTIL_SHUT_WR);
|
shutdown(evcon->fd, EVUTIL_SHUT_WR);
|
||||||
if (!(bufferevent_get_options_(evcon->bufev) & BEV_OPT_CLOSE_ON_FREE)) {
|
if (!(bufferevent_get_options_(evcon->bufev) & BEV_OPT_CLOSE_ON_FREE)) {
|
||||||
evutil_closesocket(evcon->fd);
|
evutil_closesocket(evcon->fd);
|
||||||
@ -1185,9 +1205,6 @@ evhttp_connection_free(struct evhttp_connection *evcon)
|
|||||||
if (evcon->address != NULL)
|
if (evcon->address != NULL)
|
||||||
mm_free(evcon->address);
|
mm_free(evcon->address);
|
||||||
|
|
||||||
if (evcon->conn_address != NULL)
|
|
||||||
mm_free(evcon->conn_address);
|
|
||||||
|
|
||||||
mm_free(evcon);
|
mm_free(evcon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1352,7 +1369,7 @@ evhttp_connection_cb_cleanup(struct evhttp_connection *evcon)
|
|||||||
|
|
||||||
/* we might want to set an error here */
|
/* we might want to set an error here */
|
||||||
request->cb(request, request->cb_arg);
|
request->cb(request, request->cb_arg);
|
||||||
evhttp_request_free(request);
|
evhttp_request_free_auto(request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1441,7 +1458,6 @@ evhttp_connection_cb(struct bufferevent *bufev, short what, void *arg)
|
|||||||
struct evhttp_connection *evcon = arg;
|
struct evhttp_connection *evcon = arg;
|
||||||
int error;
|
int error;
|
||||||
ev_socklen_t errsz = sizeof(error);
|
ev_socklen_t errsz = sizeof(error);
|
||||||
socklen_t conn_address_len = sizeof(*evcon->conn_address);
|
|
||||||
|
|
||||||
if (evcon->fd == -1)
|
if (evcon->fd == -1)
|
||||||
evcon->fd = bufferevent_getfd(bufev);
|
evcon->fd = bufferevent_getfd(bufev);
|
||||||
@ -1492,14 +1508,6 @@ evhttp_connection_cb(struct bufferevent *bufev, short what, void *arg)
|
|||||||
evcon->retry_cnt = 0;
|
evcon->retry_cnt = 0;
|
||||||
evcon->state = EVCON_IDLE;
|
evcon->state = EVCON_IDLE;
|
||||||
|
|
||||||
if (!evcon->conn_address) {
|
|
||||||
evcon->conn_address = mm_malloc(sizeof(*evcon->conn_address));
|
|
||||||
}
|
|
||||||
if (getpeername(evcon->fd, (struct sockaddr *)evcon->conn_address, &conn_address_len)) {
|
|
||||||
mm_free(evcon->conn_address);
|
|
||||||
evcon->conn_address = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* reset the bufferevent cbs */
|
/* reset the bufferevent cbs */
|
||||||
bufferevent_setcb(evcon->bufev,
|
bufferevent_setcb(evcon->bufev,
|
||||||
evhttp_read_cb,
|
evhttp_read_cb,
|
||||||
@ -2181,9 +2189,6 @@ evhttp_read_header(struct evhttp_connection *evcon,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disable reading for now */
|
|
||||||
bufferevent_disable(evcon->bufev, EV_READ);
|
|
||||||
|
|
||||||
/* Callback can shut down connection with negative return value */
|
/* Callback can shut down connection with negative return value */
|
||||||
if (req->header_cb != NULL) {
|
if (req->header_cb != NULL) {
|
||||||
if ((*req->header_cb)(req, req->cb_arg) < 0) {
|
if ((*req->header_cb)(req, req->cb_arg) < 0) {
|
||||||
@ -2335,6 +2340,20 @@ void evhttp_connection_set_family(struct evhttp_connection *evcon,
|
|||||||
evcon->ai_family = family;
|
evcon->ai_family = family;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int evhttp_connection_set_flags(struct evhttp_connection *evcon,
|
||||||
|
int flags)
|
||||||
|
{
|
||||||
|
if (flags & ~(EVHTTP_CON_REUSE_CONNECTED_ADDR)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
evcon->flags &= ~(EVHTTP_CON_REUSE_CONNECTED_ADDR);
|
||||||
|
|
||||||
|
evcon->flags |= EVHTTP_CON_REUSE_CONNECTED_ADDR;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
evhttp_connection_set_base(struct evhttp_connection *evcon,
|
evhttp_connection_set_base(struct evhttp_connection *evcon,
|
||||||
struct event_base *base)
|
struct event_base *base)
|
||||||
@ -2412,13 +2431,16 @@ evhttp_connection_get_peer(struct evhttp_connection *evcon,
|
|||||||
const struct sockaddr*
|
const struct sockaddr*
|
||||||
evhttp_connection_get_addr(struct evhttp_connection *evcon)
|
evhttp_connection_get_addr(struct evhttp_connection *evcon)
|
||||||
{
|
{
|
||||||
return (struct sockaddr *)evcon->conn_address;
|
return bufferevent_socket_get_conn_address_(evcon->bufev);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
evhttp_connection_connect_(struct evhttp_connection *evcon)
|
evhttp_connection_connect_(struct evhttp_connection *evcon)
|
||||||
{
|
{
|
||||||
int old_state = evcon->state;
|
int old_state = evcon->state;
|
||||||
|
const char *address = evcon->address;
|
||||||
|
const struct sockaddr *sa = evhttp_connection_get_addr(evcon);
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (evcon->state == EVCON_CONNECTING)
|
if (evcon->state == EVCON_CONNECTING)
|
||||||
return (0);
|
return (0);
|
||||||
@ -2450,17 +2472,29 @@ evhttp_connection_connect_(struct evhttp_connection *evcon)
|
|||||||
evcon);
|
evcon);
|
||||||
if (!evutil_timerisset(&evcon->timeout)) {
|
if (!evutil_timerisset(&evcon->timeout)) {
|
||||||
const struct timeval conn_tv = { HTTP_CONNECT_TIMEOUT, 0 };
|
const struct timeval conn_tv = { HTTP_CONNECT_TIMEOUT, 0 };
|
||||||
bufferevent_set_timeouts(evcon->bufev, NULL, &conn_tv);
|
bufferevent_set_timeouts(evcon->bufev, &conn_tv, &conn_tv);
|
||||||
} else {
|
} else {
|
||||||
bufferevent_set_timeouts(evcon->bufev, NULL, &evcon->timeout);
|
bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
|
||||||
}
|
}
|
||||||
/* make sure that we get a write callback */
|
/* make sure that we get a write callback */
|
||||||
bufferevent_enable(evcon->bufev, EV_WRITE);
|
bufferevent_enable(evcon->bufev, EV_WRITE);
|
||||||
|
|
||||||
evcon->state = EVCON_CONNECTING;
|
evcon->state = EVCON_CONNECTING;
|
||||||
|
|
||||||
if (bufferevent_socket_connect_hostname(evcon->bufev, evcon->dns_base,
|
if (evcon->flags & EVHTTP_CON_REUSE_CONNECTED_ADDR &&
|
||||||
evcon->ai_family, evcon->address, evcon->port) < 0) {
|
sa &&
|
||||||
|
(sa->sa_family == AF_INET || sa->sa_family == AF_INET6)) {
|
||||||
|
int socklen = sizeof(struct sockaddr_in);
|
||||||
|
if (sa->sa_family == AF_INET6) {
|
||||||
|
socklen = sizeof(struct sockaddr_in6);
|
||||||
|
}
|
||||||
|
ret = bufferevent_socket_connect(evcon->bufev, sa, socklen);
|
||||||
|
} else {
|
||||||
|
ret = bufferevent_socket_connect_hostname(evcon->bufev,
|
||||||
|
evcon->dns_base, evcon->ai_family, address, evcon->port);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
evcon->state = old_state;
|
evcon->state = old_state;
|
||||||
event_sock_warn(evcon->fd, "%s: connection to \"%s\" failed",
|
event_sock_warn(evcon->fd, "%s: connection to \"%s\" failed",
|
||||||
__func__, evcon->address);
|
__func__, evcon->address);
|
||||||
@ -2493,7 +2527,7 @@ evhttp_make_request(struct evhttp_connection *evcon,
|
|||||||
mm_free(req->uri);
|
mm_free(req->uri);
|
||||||
if ((req->uri = mm_strdup(uri)) == NULL) {
|
if ((req->uri = mm_strdup(uri)) == NULL) {
|
||||||
event_warn("%s: strdup", __func__);
|
event_warn("%s: strdup", __func__);
|
||||||
evhttp_request_free(req);
|
evhttp_request_free_auto(req);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2556,7 +2590,7 @@ evhttp_cancel_request(struct evhttp_request *req)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
evhttp_request_free(req);
|
evhttp_request_free_auto(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2567,9 +2601,9 @@ evhttp_cancel_request(struct evhttp_request *req)
|
|||||||
void
|
void
|
||||||
evhttp_start_read_(struct evhttp_connection *evcon)
|
evhttp_start_read_(struct evhttp_connection *evcon)
|
||||||
{
|
{
|
||||||
/* Set up an event to read the headers */
|
|
||||||
bufferevent_disable(evcon->bufev, EV_WRITE);
|
bufferevent_disable(evcon->bufev, EV_WRITE);
|
||||||
bufferevent_enable(evcon->bufev, EV_READ);
|
bufferevent_enable(evcon->bufev, EV_READ);
|
||||||
|
|
||||||
evcon->state = EVCON_READING_FIRSTLINE;
|
evcon->state = EVCON_READING_FIRSTLINE;
|
||||||
/* Reset the bufferevent callbacks */
|
/* Reset the bufferevent callbacks */
|
||||||
bufferevent_setcb(evcon->bufev,
|
bufferevent_setcb(evcon->bufev,
|
||||||
@ -2599,9 +2633,8 @@ evhttp_send_done(struct evhttp_connection *evcon, void *arg)
|
|||||||
|
|
||||||
need_close =
|
need_close =
|
||||||
(REQ_VERSION_BEFORE(req, 1, 1) &&
|
(REQ_VERSION_BEFORE(req, 1, 1) &&
|
||||||
!evhttp_is_connection_keepalive(req->input_headers))||
|
!evhttp_is_connection_keepalive(req->input_headers)) ||
|
||||||
evhttp_is_connection_close(req->flags, req->input_headers) ||
|
evhttp_is_request_connection_close(req);
|
||||||
evhttp_is_connection_close(req->flags, req->output_headers);
|
|
||||||
|
|
||||||
EVUTIL_ASSERT(req->flags & EVHTTP_REQ_OWN_CONNECTION);
|
EVUTIL_ASSERT(req->flags & EVHTTP_REQ_OWN_CONNECTION);
|
||||||
evhttp_request_free(req);
|
evhttp_request_free(req);
|
||||||
@ -4035,6 +4068,8 @@ evhttp_get_request_connection(
|
|||||||
|
|
||||||
evcon->fd = fd;
|
evcon->fd = fd;
|
||||||
|
|
||||||
|
bufferevent_enable(evcon->bufev, EV_READ);
|
||||||
|
bufferevent_disable(evcon->bufev, EV_WRITE);
|
||||||
bufferevent_setfd(evcon->bufev, fd);
|
bufferevent_setfd(evcon->bufev, fd);
|
||||||
|
|
||||||
return (evcon);
|
return (evcon);
|
||||||
|
@ -63,8 +63,6 @@ extern "C" {
|
|||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#undef WIN32_LEAN_AND_MEAN
|
#undef WIN32_LEAN_AND_MEAN
|
||||||
typedef unsigned char u_char;
|
|
||||||
typedef unsigned short u_short;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <event2/event_struct.h>
|
#include <event2/event_struct.h>
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Obsolete alias for evbuffer_readln(buffer, NULL, EOL_STYLE_ANY).
|
Obsolete alias for evbuffer_readln(buffer, NULL, EVBUFFER_EOL_ANY).
|
||||||
|
|
||||||
@deprecated This function is deprecated because its behavior is not correct
|
@deprecated This function is deprecated because its behavior is not correct
|
||||||
for almost any protocol, and also because it's wholly subsumed by
|
for almost any protocol, and also because it's wholly subsumed by
|
||||||
|
@ -209,7 +209,7 @@ struct bufferevent *bufferevent_socket_new(struct event_base *base, evutil_socke
|
|||||||
@return 0 on success, -1 on failure.
|
@return 0 on success, -1 on failure.
|
||||||
*/
|
*/
|
||||||
EVENT2_EXPORT_SYMBOL
|
EVENT2_EXPORT_SYMBOL
|
||||||
int bufferevent_socket_connect(struct bufferevent *, struct sockaddr *, int);
|
int bufferevent_socket_connect(struct bufferevent *, const struct sockaddr *, int);
|
||||||
|
|
||||||
struct evdns_base;
|
struct evdns_base;
|
||||||
/**
|
/**
|
||||||
@ -562,6 +562,32 @@ void bufferevent_lock(struct bufferevent *bufev);
|
|||||||
EVENT2_EXPORT_SYMBOL
|
EVENT2_EXPORT_SYMBOL
|
||||||
void bufferevent_unlock(struct bufferevent *bufev);
|
void bufferevent_unlock(struct bufferevent *bufev);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public interface to manually increase the reference count of a bufferevent
|
||||||
|
* this is useful in situations where a user may reference the bufferevent
|
||||||
|
* somewhere eles (unknown to libevent)
|
||||||
|
*
|
||||||
|
* @param bufev the bufferevent to increase the refcount on
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
EVENT2_EXPORT_SYMBOL
|
||||||
|
void bufferevent_incref(struct bufferevent *bufev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public interface to manually decrement the reference count of a bufferevent
|
||||||
|
*
|
||||||
|
* Warning: make sure you know what you're doing. This is mainly used in
|
||||||
|
* conjunction with bufferevent_incref(). This will free up all data associated
|
||||||
|
* with a bufferevent if the reference count hits 0.
|
||||||
|
*
|
||||||
|
* @param bufev the bufferevent to decrement the refcount on
|
||||||
|
*
|
||||||
|
* @return 1 if the bufferevent was freed, otherwise 0 (still referenced)
|
||||||
|
*/
|
||||||
|
EVENT2_EXPORT_SYMBOL
|
||||||
|
int bufferevent_decref(struct bufferevent *bufev);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Flags that can be passed into filters to let them know how to
|
Flags that can be passed into filters to let them know how to
|
||||||
deal with the incoming data.
|
deal with the incoming data.
|
||||||
|
@ -633,9 +633,22 @@ struct evhttp_connection *evhttp_connection_base_new(
|
|||||||
/**
|
/**
|
||||||
* Set family hint for DNS requests.
|
* Set family hint for DNS requests.
|
||||||
*/
|
*/
|
||||||
|
EVENT2_EXPORT_SYMBOL
|
||||||
void evhttp_connection_set_family(struct evhttp_connection *evcon,
|
void evhttp_connection_set_family(struct evhttp_connection *evcon,
|
||||||
int family);
|
int family);
|
||||||
|
|
||||||
|
#define EVHTTP_CON_REUSE_CONNECTED_ADDR 0x0008 /* reuse connection address on retry */
|
||||||
|
/**
|
||||||
|
* Set connection flags.
|
||||||
|
*
|
||||||
|
* @see EVHTTP_CON_*
|
||||||
|
* @return 0 on success, otherwise non zero (for example if flag doesn't
|
||||||
|
* supported).
|
||||||
|
*/
|
||||||
|
EVENT2_EXPORT_SYMBOL
|
||||||
|
int evhttp_connection_set_flags(struct evhttp_connection *evcon,
|
||||||
|
int flags);
|
||||||
|
|
||||||
/** Takes ownership of the request object
|
/** Takes ownership of the request object
|
||||||
*
|
*
|
||||||
* Can be used in a request callback to keep onto the request until
|
* Can be used in a request callback to keep onto the request until
|
||||||
@ -728,7 +741,7 @@ void evhttp_connection_get_peer(struct evhttp_connection *evcon,
|
|||||||
char **address, ev_uint16_t *port);
|
char **address, ev_uint16_t *port);
|
||||||
|
|
||||||
/** Get the remote address associated with this connection.
|
/** Get the remote address associated with this connection.
|
||||||
* extracted from getpeername().
|
* extracted from getpeername() OR from nameserver.
|
||||||
*
|
*
|
||||||
* @return NULL if getpeername() return non success,
|
* @return NULL if getpeername() return non success,
|
||||||
* or connection is not connected,
|
* or connection is not connected,
|
||||||
|
@ -233,6 +233,7 @@ extern "C" {
|
|||||||
|
|
||||||
@{
|
@{
|
||||||
*/
|
*/
|
||||||
|
#ifndef EVENT__HAVE_STDINT_H
|
||||||
#define EV_UINT64_MAX ((((ev_uint64_t)0xffffffffUL) << 32) | 0xffffffffUL)
|
#define EV_UINT64_MAX ((((ev_uint64_t)0xffffffffUL) << 32) | 0xffffffffUL)
|
||||||
#define EV_INT64_MAX ((((ev_int64_t) 0x7fffffffL) << 32) | 0xffffffffL)
|
#define EV_INT64_MAX ((((ev_int64_t) 0x7fffffffL) << 32) | 0xffffffffL)
|
||||||
#define EV_INT64_MIN ((-EV_INT64_MAX) - 1)
|
#define EV_INT64_MIN ((-EV_INT64_MAX) - 1)
|
||||||
@ -245,7 +246,21 @@ extern "C" {
|
|||||||
#define EV_UINT8_MAX 255
|
#define EV_UINT8_MAX 255
|
||||||
#define EV_INT8_MAX 127
|
#define EV_INT8_MAX 127
|
||||||
#define EV_INT8_MIN ((-EV_INT8_MAX) - 1)
|
#define EV_INT8_MIN ((-EV_INT8_MAX) - 1)
|
||||||
|
#else
|
||||||
|
#define EV_UINT64_MAX UINT64_MAX
|
||||||
|
#define EV_INT64_MAX INT64_MAX
|
||||||
|
#define EV_INT64_MIN INT64_MIN
|
||||||
|
#define EV_UINT32_MAX UINT32_MAX
|
||||||
|
#define EV_INT32_MAX INT32_MAX
|
||||||
|
#define EV_INT32_MIN INT32_MIN
|
||||||
|
#define EV_UINT16_MAX UINT16_MAX
|
||||||
|
#define EV_INT16_MAX INT16_MAX
|
||||||
|
#define EV_UINT8_MAX UINT8_MAX
|
||||||
|
#define EV_INT8_MAX INT8_MAX
|
||||||
|
#define EV_INT8_MIN INT8_MIN
|
||||||
/** @} */
|
/** @} */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@name Limits for SIZE_T and SSIZE_T
|
@name Limits for SIZE_T and SSIZE_T
|
||||||
|
5
kqueue.c
5
kqueue.c
@ -50,7 +50,7 @@
|
|||||||
/* Some platforms apparently define the udata field of struct kevent as
|
/* Some platforms apparently define the udata field of struct kevent as
|
||||||
* intptr_t, whereas others define it as void*. There doesn't seem to be an
|
* intptr_t, whereas others define it as void*. There doesn't seem to be an
|
||||||
* easy way to tell them apart via autoconf, so we need to use OS macros. */
|
* easy way to tell them apart via autoconf, so we need to use OS macros. */
|
||||||
#if defined(EVENT__HAVE_INTTYPES_H) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__darwin__) && !defined(__APPLE__)
|
#if defined(EVENT__HAVE_INTTYPES_H) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__darwin__) && !defined(__APPLE__) && !defined(__CloudABI__)
|
||||||
#define PTR_TO_UDATA(x) ((intptr_t)(x))
|
#define PTR_TO_UDATA(x) ((intptr_t)(x))
|
||||||
#define INT_TO_UDATA(x) ((intptr_t)(x))
|
#define INT_TO_UDATA(x) ((intptr_t)(x))
|
||||||
#else
|
#else
|
||||||
@ -260,7 +260,8 @@ kq_dispatch(struct event_base *base, struct timeval *tv)
|
|||||||
int i, n_changes, res;
|
int i, n_changes, res;
|
||||||
|
|
||||||
if (tv != NULL) {
|
if (tv != NULL) {
|
||||||
TIMEVAL_TO_TIMESPEC(tv, &ts);
|
ts.tv_sec = tv->tv_sec;
|
||||||
|
ts.tv_nsec = tv->tv_usec * 1000;
|
||||||
ts_p = &ts;
|
ts_p = &ts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,6 +421,8 @@ listener_read_cb(evutil_socket_t fd, short what, void *p)
|
|||||||
if (lev->refcnt == 1) {
|
if (lev->refcnt == 1) {
|
||||||
int freed = listener_decref_and_unlock(lev);
|
int freed = listener_decref_and_unlock(lev);
|
||||||
EVUTIL_ASSERT(freed);
|
EVUTIL_ASSERT(freed);
|
||||||
|
|
||||||
|
evutil_closesocket(new_fd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
--lev->refcnt;
|
--lev->refcnt;
|
||||||
|
@ -12,9 +12,14 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#ifdef EVENT__HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
|
#include <getopt.h>
|
||||||
#else
|
#else
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
@ -141,34 +146,36 @@ logfn(int is_warn, const char *msg) {
|
|||||||
|
|
||||||
int
|
int
|
||||||
main(int c, char **v) {
|
main(int c, char **v) {
|
||||||
int idx;
|
struct options {
|
||||||
int reverse = 0, servertest = 0, use_getaddrinfo = 0;
|
int reverse;
|
||||||
|
int use_getaddrinfo;
|
||||||
|
int servertest;
|
||||||
|
const char *resolv_conf;
|
||||||
|
const char *ns;
|
||||||
|
};
|
||||||
|
struct options o;
|
||||||
|
char opt;
|
||||||
struct event_base *event_base = NULL;
|
struct event_base *event_base = NULL;
|
||||||
struct evdns_base *evdns_base = NULL;
|
struct evdns_base *evdns_base = NULL;
|
||||||
const char *resolv_conf = NULL;
|
|
||||||
if (c<2) {
|
memset(&o, 0, sizeof(o));
|
||||||
fprintf(stderr, "syntax: %s [-x] [-v] [-c resolv.conf] hostname\n", v[0]);
|
|
||||||
fprintf(stderr, "syntax: %s [-servertest]\n", v[0]);
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
idx = 1;
|
|
||||||
while (idx < c && v[idx][0] == '-') {
|
while ((opt = getopt(c, v, "xvc:Ts:")) != -1) {
|
||||||
if (!strcmp(v[idx], "-x"))
|
switch (opt) {
|
||||||
reverse = 1;
|
case 'x': o.reverse = 1; break;
|
||||||
else if (!strcmp(v[idx], "-v"))
|
case 'v': ++verbose; break;
|
||||||
verbose = 1;
|
case 'g': o.use_getaddrinfo = 1; break;
|
||||||
else if (!strcmp(v[idx], "-g"))
|
case 'T': o.servertest = 1; break;
|
||||||
use_getaddrinfo = 1;
|
case 'c': o.resolv_conf = optarg; break;
|
||||||
else if (!strcmp(v[idx], "-servertest"))
|
case 's': o.ns = optarg; break;
|
||||||
servertest = 1;
|
default : fprintf(stderr, "Unknown option %c\n", opt); break;
|
||||||
else if (!strcmp(v[idx], "-c")) {
|
}
|
||||||
if (idx + 1 < c)
|
|
||||||
resolv_conf = v[++idx];
|
|
||||||
else
|
|
||||||
fprintf(stderr, "-c needs an argument\n");
|
|
||||||
} else
|
|
||||||
fprintf(stderr, "Unknown option %s\n", v[idx]);
|
|
||||||
++idx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -182,7 +189,7 @@ main(int c, char **v) {
|
|||||||
evdns_base = evdns_base_new(event_base, EVDNS_BASE_DISABLE_WHEN_INACTIVE);
|
evdns_base = evdns_base_new(event_base, EVDNS_BASE_DISABLE_WHEN_INACTIVE);
|
||||||
evdns_set_log_fn(logfn);
|
evdns_set_log_fn(logfn);
|
||||||
|
|
||||||
if (servertest) {
|
if (o.servertest) {
|
||||||
evutil_socket_t sock;
|
evutil_socket_t sock;
|
||||||
struct sockaddr_in my_addr;
|
struct sockaddr_in my_addr;
|
||||||
sock = socket(PF_INET, SOCK_DGRAM, 0);
|
sock = socket(PF_INET, SOCK_DGRAM, 0);
|
||||||
@ -200,16 +207,18 @@ main(int c, char **v) {
|
|||||||
}
|
}
|
||||||
evdns_add_server_port_with_base(event_base, sock, 0, evdns_server_callback, NULL);
|
evdns_add_server_port_with_base(event_base, sock, 0, evdns_server_callback, NULL);
|
||||||
}
|
}
|
||||||
if (idx < c) {
|
if (optind < c) {
|
||||||
int res;
|
int res;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (resolv_conf == NULL)
|
if (o.resolv_conf == NULL && !o.ns)
|
||||||
res = evdns_base_config_windows_nameservers(evdns_base);
|
res = evdns_base_config_windows_nameservers(evdns_base);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
if (o.ns)
|
||||||
|
res = evdns_base_nameserver_ip_add(evdns_base, o.ns);
|
||||||
|
else
|
||||||
res = evdns_base_resolv_conf_parse(evdns_base,
|
res = evdns_base_resolv_conf_parse(evdns_base,
|
||||||
DNS_OPTION_NAMESERVERS,
|
DNS_OPTION_NAMESERVERS, o.resolv_conf);
|
||||||
resolv_conf ? resolv_conf : "/etc/resolv.conf");
|
|
||||||
|
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
fprintf(stderr, "Couldn't configure nameservers");
|
fprintf(stderr, "Couldn't configure nameservers");
|
||||||
@ -218,27 +227,27 @@ main(int c, char **v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
printf("EVUTIL_AI_CANONNAME in example = %d\n", EVUTIL_AI_CANONNAME);
|
printf("EVUTIL_AI_CANONNAME in example = %d\n", EVUTIL_AI_CANONNAME);
|
||||||
for (; idx < c; ++idx) {
|
for (; optind < c; ++optind) {
|
||||||
if (reverse) {
|
if (o.reverse) {
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
if (evutil_inet_pton(AF_INET, v[idx], &addr)!=1) {
|
if (evutil_inet_pton(AF_INET, v[optind], &addr)!=1) {
|
||||||
fprintf(stderr, "Skipping non-IP %s\n", v[idx]);
|
fprintf(stderr, "Skipping non-IP %s\n", v[optind]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
fprintf(stderr, "resolving %s...\n",v[idx]);
|
fprintf(stderr, "resolving %s...\n",v[optind]);
|
||||||
evdns_base_resolve_reverse(evdns_base, &addr, 0, main_callback, v[idx]);
|
evdns_base_resolve_reverse(evdns_base, &addr, 0, main_callback, v[optind]);
|
||||||
} else if (use_getaddrinfo) {
|
} else if (o.use_getaddrinfo) {
|
||||||
struct evutil_addrinfo hints;
|
struct evutil_addrinfo hints;
|
||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
hints.ai_family = PF_UNSPEC;
|
hints.ai_family = PF_UNSPEC;
|
||||||
hints.ai_protocol = IPPROTO_TCP;
|
hints.ai_protocol = IPPROTO_TCP;
|
||||||
hints.ai_flags = EVUTIL_AI_CANONNAME;
|
hints.ai_flags = EVUTIL_AI_CANONNAME;
|
||||||
fprintf(stderr, "resolving (fwd) %s...\n",v[idx]);
|
fprintf(stderr, "resolving (fwd) %s...\n",v[optind]);
|
||||||
evdns_getaddrinfo(evdns_base, v[idx], NULL, &hints,
|
evdns_getaddrinfo(evdns_base, v[optind], NULL, &hints,
|
||||||
gai_callback, v[idx]);
|
gai_callback, v[optind]);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "resolving (fwd) %s...\n",v[idx]);
|
fprintf(stderr, "resolving (fwd) %s...\n",v[optind]);
|
||||||
evdns_base_resolve_ipv4(evdns_base, v[idx], 0, main_callback, v[idx]);
|
evdns_base_resolve_ipv4(evdns_base, v[optind], 0, main_callback, v[optind]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
109
sample/http-connect.c
Normal file
109
sample/http-connect.c
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
#include <event2/event.h>
|
||||||
|
#include <event2/http.h>
|
||||||
|
#include <event2/http_struct.h>
|
||||||
|
#include <event2/buffer.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#define VERIFY(cond) do { \
|
||||||
|
if (!(cond)) { \
|
||||||
|
fprintf(stderr, "[error] %s\n", #cond); \
|
||||||
|
} \
|
||||||
|
} while (0); \
|
||||||
|
|
||||||
|
struct connect_base
|
||||||
|
{
|
||||||
|
struct evhttp_connection *evcon;
|
||||||
|
struct evhttp_uri *location;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void get_cb(struct evhttp_request *req, void *arg)
|
||||||
|
{
|
||||||
|
VERIFY(req);
|
||||||
|
evbuffer_write(req->input_buffer, STDOUT_FILENO);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void connect_cb(struct evhttp_request *proxy_req, void *arg)
|
||||||
|
{
|
||||||
|
char buffer[PATH_MAX];
|
||||||
|
|
||||||
|
struct connect_base *base = arg;
|
||||||
|
struct evhttp_connection *evcon = base->evcon;
|
||||||
|
struct evhttp_uri *location = base->location;
|
||||||
|
|
||||||
|
VERIFY(proxy_req);
|
||||||
|
if (evcon) {
|
||||||
|
struct evhttp_request *req = evhttp_request_new(get_cb, NULL);
|
||||||
|
evhttp_add_header(req->output_headers, "Connection", "close");
|
||||||
|
VERIFY(!evhttp_make_request(evcon, req, EVHTTP_REQ_GET,
|
||||||
|
evhttp_uri_join(location, buffer, PATH_MAX)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, const char **argv)
|
||||||
|
{
|
||||||
|
char buffer[PATH_MAX];
|
||||||
|
|
||||||
|
struct evhttp_uri *host_port;
|
||||||
|
struct evhttp_uri *location;
|
||||||
|
struct evhttp_uri *proxy;
|
||||||
|
|
||||||
|
struct event_base *base;
|
||||||
|
struct evhttp_connection *evcon;
|
||||||
|
struct evhttp_request *req;
|
||||||
|
|
||||||
|
struct connect_base connect_base;
|
||||||
|
|
||||||
|
if (argc != 3) {
|
||||||
|
printf("Usage: %s proxy url\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
proxy = evhttp_uri_parse(argv[1]);
|
||||||
|
VERIFY(evhttp_uri_get_host(proxy));
|
||||||
|
VERIFY(evhttp_uri_get_port(proxy) > 0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
host_port = evhttp_uri_parse(argv[2]);
|
||||||
|
evhttp_uri_set_scheme(host_port, NULL);
|
||||||
|
evhttp_uri_set_userinfo(host_port, NULL);
|
||||||
|
evhttp_uri_set_path(host_port, NULL);
|
||||||
|
evhttp_uri_set_query(host_port, NULL);
|
||||||
|
evhttp_uri_set_fragment(host_port, NULL);
|
||||||
|
VERIFY(evhttp_uri_get_host(host_port));
|
||||||
|
VERIFY(evhttp_uri_get_port(host_port) > 0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
location = evhttp_uri_parse(argv[2]);
|
||||||
|
evhttp_uri_set_scheme(location, NULL);
|
||||||
|
evhttp_uri_set_userinfo(location, 0);
|
||||||
|
evhttp_uri_set_host(location, NULL);
|
||||||
|
evhttp_uri_set_port(location, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
VERIFY(base = event_base_new());
|
||||||
|
VERIFY(evcon = evhttp_connection_base_new(base, NULL,
|
||||||
|
evhttp_uri_get_host(proxy), evhttp_uri_get_port(proxy)));
|
||||||
|
connect_base = (struct connect_base){
|
||||||
|
.evcon = evcon,
|
||||||
|
.location = location,
|
||||||
|
};
|
||||||
|
VERIFY(req = evhttp_request_new(connect_cb, &connect_base));
|
||||||
|
|
||||||
|
evhttp_add_header(req->output_headers, "Connection", "keep-alive");
|
||||||
|
evhttp_add_header(req->output_headers, "Proxy-Connection", "keep-alive");
|
||||||
|
evutil_snprintf(buffer, PATH_MAX, "%s:%d",
|
||||||
|
evhttp_uri_get_host(host_port), evhttp_uri_get_port(host_port));
|
||||||
|
evhttp_make_request(evcon, req, EVHTTP_REQ_CONNECT, buffer);
|
||||||
|
|
||||||
|
event_base_dispatch(base);
|
||||||
|
evhttp_connection_free(evcon);
|
||||||
|
event_base_free(base);
|
||||||
|
evhttp_uri_free(proxy);
|
||||||
|
evhttp_uri_free(host_port);
|
||||||
|
evhttp_uri_free(location);
|
||||||
|
return 0;
|
||||||
|
}
|
@ -96,22 +96,19 @@ static void
|
|||||||
syntax(void)
|
syntax(void)
|
||||||
{
|
{
|
||||||
fputs("Syntax:\n", stderr);
|
fputs("Syntax:\n", stderr);
|
||||||
fputs(" https-client -url <https-url> [-data data-file.bin] [-ignore-cert] [-retries num]\n", stderr);
|
fputs(" https-client -url <https-url> [-data data-file.bin] [-ignore-cert] [-retries num] [-timeout sec] [-crt crt]\n", stderr);
|
||||||
fputs("Example:\n", stderr);
|
fputs("Example:\n", stderr);
|
||||||
fputs(" https-client -url https://ip.appspot.com/\n", stderr);
|
fputs(" https-client -url https://ip.appspot.com/\n", stderr);
|
||||||
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
die(const char *msg)
|
err(const char *msg)
|
||||||
{
|
{
|
||||||
fputs(msg, stderr);
|
fputs(msg, stderr);
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
die_openssl(const char *func)
|
err_openssl(const char *func)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "%s failed:\n", func);
|
fprintf (stderr, "%s failed:\n", func);
|
||||||
|
|
||||||
@ -190,22 +187,26 @@ main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
struct evhttp_uri *http_uri;
|
struct evhttp_uri *http_uri = NULL;
|
||||||
const char *url = NULL, *data_file = NULL;
|
const char *url = NULL, *data_file = NULL;
|
||||||
|
const char *crt = "/etc/ssl/certs/ca-certificates.crt";
|
||||||
const char *scheme, *host, *path, *query;
|
const char *scheme, *host, *path, *query;
|
||||||
char uri[256];
|
char uri[256];
|
||||||
int port;
|
int port;
|
||||||
int retries = 0;
|
int retries = 0;
|
||||||
|
int timeout = -1;
|
||||||
|
|
||||||
SSL_CTX *ssl_ctx;
|
SSL_CTX *ssl_ctx = NULL;
|
||||||
SSL *ssl;
|
SSL *ssl = NULL;
|
||||||
struct bufferevent *bev;
|
struct bufferevent *bev;
|
||||||
struct evhttp_connection *evcon;
|
struct evhttp_connection *evcon = NULL;
|
||||||
struct evhttp_request *req;
|
struct evhttp_request *req;
|
||||||
struct evkeyvalq *output_headers;
|
struct evkeyvalq *output_headers;
|
||||||
struct evbuffer * output_buffer;
|
struct evbuffer *output_buffer;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
int ret = 0;
|
||||||
|
enum { HTTP, HTTPS } type = HTTP;
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
if (!strcmp("-url", argv[i])) {
|
if (!strcmp("-url", argv[i])) {
|
||||||
@ -213,6 +214,14 @@ main(int argc, char **argv)
|
|||||||
url = argv[i + 1];
|
url = argv[i + 1];
|
||||||
} else {
|
} else {
|
||||||
syntax();
|
syntax();
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
} else if (!strcmp("-crt", argv[i])) {
|
||||||
|
if (i < argc - 1) {
|
||||||
|
crt = argv[i + 1];
|
||||||
|
} else {
|
||||||
|
syntax();
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
} else if (!strcmp("-ignore-cert", argv[i])) {
|
} else if (!strcmp("-ignore-cert", argv[i])) {
|
||||||
ignore_cert = 1;
|
ignore_cert = 1;
|
||||||
@ -221,20 +230,31 @@ main(int argc, char **argv)
|
|||||||
data_file = argv[i + 1];
|
data_file = argv[i + 1];
|
||||||
} else {
|
} else {
|
||||||
syntax();
|
syntax();
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
} else if (!strcmp("-retries", argv[i])) {
|
} else if (!strcmp("-retries", argv[i])) {
|
||||||
if (i < argc - 1) {
|
if (i < argc - 1) {
|
||||||
retries = atoi(argv[i + 1]);
|
retries = atoi(argv[i + 1]);
|
||||||
} else {
|
} else {
|
||||||
syntax();
|
syntax();
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
} else if (!strcmp("-timeout", argv[i])) {
|
||||||
|
if (i < argc - 1) {
|
||||||
|
timeout = atoi(argv[i + 1]);
|
||||||
|
} else {
|
||||||
|
syntax();
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
} else if (!strcmp("-help", argv[i])) {
|
} else if (!strcmp("-help", argv[i])) {
|
||||||
syntax();
|
syntax();
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!url) {
|
if (!url) {
|
||||||
syntax();
|
syntax();
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -248,25 +268,28 @@ main(int argc, char **argv)
|
|||||||
err = WSAStartup(wVersionRequested, &wsaData);
|
err = WSAStartup(wVersionRequested, &wsaData);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
printf("WSAStartup failed with error: %d\n", err);
|
printf("WSAStartup failed with error: %d\n", err);
|
||||||
return 1;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
||||||
http_uri = evhttp_uri_parse(url);
|
http_uri = evhttp_uri_parse(url);
|
||||||
if (http_uri == NULL) {
|
if (http_uri == NULL) {
|
||||||
die("malformed url");
|
err("malformed url");
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
scheme = evhttp_uri_get_scheme(http_uri);
|
scheme = evhttp_uri_get_scheme(http_uri);
|
||||||
if (scheme == NULL || (strcasecmp(scheme, "https") != 0 &&
|
if (scheme == NULL || (strcasecmp(scheme, "https") != 0 &&
|
||||||
strcasecmp(scheme, "http") != 0)) {
|
strcasecmp(scheme, "http") != 0)) {
|
||||||
die("url must be http or https");
|
err("url must be http or https");
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
host = evhttp_uri_get_host(http_uri);
|
host = evhttp_uri_get_host(http_uri);
|
||||||
if (host == NULL) {
|
if (host == NULL) {
|
||||||
die("url must have a host");
|
err("url must have a host");
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
port = evhttp_uri_get_port(http_uri);
|
port = evhttp_uri_get_port(http_uri);
|
||||||
@ -275,7 +298,7 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
path = evhttp_uri_get_path(http_uri);
|
path = evhttp_uri_get_path(http_uri);
|
||||||
if (path == NULL) {
|
if (strlen(path) == 0) {
|
||||||
path = "/";
|
path = "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,23 +320,26 @@ main(int argc, char **argv)
|
|||||||
* automatically on first use of random number generator. */
|
* automatically on first use of random number generator. */
|
||||||
r = RAND_poll();
|
r = RAND_poll();
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
die_openssl("RAND_poll");
|
err_openssl("RAND_poll");
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a new OpenSSL context */
|
/* Create a new OpenSSL context */
|
||||||
ssl_ctx = SSL_CTX_new(SSLv23_method());
|
ssl_ctx = SSL_CTX_new(SSLv23_method());
|
||||||
if (!ssl_ctx)
|
if (!ssl_ctx) {
|
||||||
die_openssl("SSL_CTX_new");
|
err_openssl("SSL_CTX_new");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
/* TODO: Add certificate loading on Windows as well */
|
/* TODO: Add certificate loading on Windows as well */
|
||||||
|
|
||||||
/* Attempt to use the system's trusted root certificates.
|
/* Attempt to use the system's trusted root certificates.
|
||||||
* (This path is only valid for Debian-based systems.) */
|
* (This path is only valid for Debian-based systems.) */
|
||||||
if (1 != SSL_CTX_load_verify_locations(ssl_ctx,
|
if (1 != SSL_CTX_load_verify_locations(ssl_ctx, crt, NULL)) {
|
||||||
"/etc/ssl/certs/ca-certificates.crt",
|
err_openssl("SSL_CTX_load_verify_locations");
|
||||||
NULL))
|
goto error;
|
||||||
die_openssl("SSL_CTX_load_verify_locations");
|
}
|
||||||
/* Ask OpenSSL to verify the server certificate. Note that this
|
/* Ask OpenSSL to verify the server certificate. Note that this
|
||||||
* does NOT include verifying that the hostname is correct.
|
* does NOT include verifying that the hostname is correct.
|
||||||
* So, by itself, this means anyone with any legitimate
|
* So, by itself, this means anyone with any legitimate
|
||||||
@ -336,21 +362,22 @@ main(int argc, char **argv)
|
|||||||
* OpenSSL's built-in routine which would have been called if
|
* OpenSSL's built-in routine which would have been called if
|
||||||
* we hadn't set the callback. Therefore, we're just
|
* we hadn't set the callback. Therefore, we're just
|
||||||
* "wrapping" OpenSSL's routine, not replacing it. */
|
* "wrapping" OpenSSL's routine, not replacing it. */
|
||||||
SSL_CTX_set_cert_verify_callback (ssl_ctx, cert_verify_callback,
|
SSL_CTX_set_cert_verify_callback(ssl_ctx, cert_verify_callback,
|
||||||
(void *) host);
|
(void *) host);
|
||||||
#endif // not _WIN32
|
#endif // not _WIN32
|
||||||
|
|
||||||
// Create event base
|
// Create event base
|
||||||
base = event_base_new();
|
base = event_base_new();
|
||||||
if (!base) {
|
if (!base) {
|
||||||
perror("event_base_new()");
|
perror("event_base_new()");
|
||||||
return 1;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create OpenSSL bufferevent and stack evhttp on top of it
|
// Create OpenSSL bufferevent and stack evhttp on top of it
|
||||||
ssl = SSL_new(ssl_ctx);
|
ssl = SSL_new(ssl_ctx);
|
||||||
if (ssl == NULL) {
|
if (ssl == NULL) {
|
||||||
die_openssl("SSL_new()");
|
err_openssl("SSL_new()");
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
||||||
@ -361,6 +388,7 @@ main(int argc, char **argv)
|
|||||||
if (strcasecmp(scheme, "http") == 0) {
|
if (strcasecmp(scheme, "http") == 0) {
|
||||||
bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
|
bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
|
||||||
} else {
|
} else {
|
||||||
|
type = HTTPS;
|
||||||
bev = bufferevent_openssl_socket_new(base, -1, ssl,
|
bev = bufferevent_openssl_socket_new(base, -1, ssl,
|
||||||
BUFFEREVENT_SSL_CONNECTING,
|
BUFFEREVENT_SSL_CONNECTING,
|
||||||
BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
|
BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
|
||||||
@ -368,7 +396,7 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
if (bev == NULL) {
|
if (bev == NULL) {
|
||||||
fprintf(stderr, "bufferevent_openssl_socket_new() failed\n");
|
fprintf(stderr, "bufferevent_openssl_socket_new() failed\n");
|
||||||
return 1;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
bufferevent_openssl_set_allow_dirty_shutdown(bev, 1);
|
bufferevent_openssl_set_allow_dirty_shutdown(bev, 1);
|
||||||
@ -379,18 +407,21 @@ main(int argc, char **argv)
|
|||||||
host, port);
|
host, port);
|
||||||
if (evcon == NULL) {
|
if (evcon == NULL) {
|
||||||
fprintf(stderr, "evhttp_connection_base_bufferevent_new() failed\n");
|
fprintf(stderr, "evhttp_connection_base_bufferevent_new() failed\n");
|
||||||
return 1;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (retries > 0) {
|
if (retries > 0) {
|
||||||
evhttp_connection_set_retries(evcon, retries);
|
evhttp_connection_set_retries(evcon, retries);
|
||||||
}
|
}
|
||||||
|
if (timeout >= 0) {
|
||||||
|
evhttp_connection_set_timeout(evcon, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
// Fire off the request
|
// Fire off the request
|
||||||
req = evhttp_request_new(http_request_done, bev);
|
req = evhttp_request_new(http_request_done, bev);
|
||||||
if (req == NULL) {
|
if (req == NULL) {
|
||||||
fprintf(stderr, "evhttp_request_new() failed\n");
|
fprintf(stderr, "evhttp_request_new() failed\n");
|
||||||
return 1;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
output_headers = evhttp_request_get_output_headers(req);
|
output_headers = evhttp_request_get_output_headers(req);
|
||||||
@ -408,6 +439,7 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
if (!f) {
|
if (!f) {
|
||||||
syntax();
|
syntax();
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
output_buffer = evhttp_request_get_output_buffer(req);
|
output_buffer = evhttp_request_get_output_buffer(req);
|
||||||
@ -423,17 +455,40 @@ main(int argc, char **argv)
|
|||||||
r = evhttp_make_request(evcon, req, data_file ? EVHTTP_REQ_POST : EVHTTP_REQ_GET, uri);
|
r = evhttp_make_request(evcon, req, data_file ? EVHTTP_REQ_POST : EVHTTP_REQ_GET, uri);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
fprintf(stderr, "evhttp_make_request() failed\n");
|
fprintf(stderr, "evhttp_make_request() failed\n");
|
||||||
return 1;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
event_base_dispatch(base);
|
event_base_dispatch(base);
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
evhttp_connection_free(evcon);
|
error:
|
||||||
|
ret = 1;
|
||||||
|
cleanup:
|
||||||
|
if (evcon)
|
||||||
|
evhttp_connection_free(evcon);
|
||||||
|
if (http_uri)
|
||||||
|
evhttp_uri_free(http_uri);
|
||||||
event_base_free(base);
|
event_base_free(base);
|
||||||
|
|
||||||
|
if (ssl_ctx)
|
||||||
|
SSL_CTX_free(ssl_ctx);
|
||||||
|
if (type == HTTP && ssl)
|
||||||
|
SSL_free(ssl);
|
||||||
|
EVP_cleanup();
|
||||||
|
ERR_free_strings();
|
||||||
|
|
||||||
|
#ifdef EVENT__HAVE_ERR_REMOVE_THREAD_STATE
|
||||||
|
ERR_remove_thread_state(NULL);
|
||||||
|
#else
|
||||||
|
ERR_remove_state(0);
|
||||||
|
#endif
|
||||||
|
CRYPTO_cleanup_all_ex_data();
|
||||||
|
|
||||||
|
sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ SAMPLES = \
|
|||||||
sample/event-read-fifo \
|
sample/event-read-fifo \
|
||||||
sample/hello-world \
|
sample/hello-world \
|
||||||
sample/http-server \
|
sample/http-server \
|
||||||
|
sample/http-connect \
|
||||||
sample/signal-test \
|
sample/signal-test \
|
||||||
sample/time-test
|
sample/time-test
|
||||||
|
|
||||||
@ -48,6 +49,5 @@ sample_hello_world_SOURCES = sample/hello-world.c
|
|||||||
sample_hello_world_LDADD = $(LIBEVENT_GC_SECTIONS) libevent.la
|
sample_hello_world_LDADD = $(LIBEVENT_GC_SECTIONS) libevent.la
|
||||||
sample_http_server_SOURCES = sample/http-server.c
|
sample_http_server_SOURCES = sample/http-server.c
|
||||||
sample_http_server_LDADD = $(LIBEVENT_GC_SECTIONS) libevent.la
|
sample_http_server_LDADD = $(LIBEVENT_GC_SECTIONS) libevent.la
|
||||||
|
sample_http_connect_SOURCES = sample/http-connect.c
|
||||||
|
sample_http_connect_LDADD = $(LIBEVENT_GC_SECTIONS) libevent.la
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ SOFTWARE.
|
|||||||
|
|
||||||
#include <openssl/x509v3.h>
|
#include <openssl/x509v3.h>
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "openssl_hostname_validation.h"
|
#include "openssl_hostname_validation.h"
|
||||||
#include "hostcheck.h"
|
#include "hostcheck.h"
|
||||||
|
@ -74,7 +74,7 @@ static void
|
|||||||
read_cb(evutil_socket_t fd, short which, void *arg)
|
read_cb(evutil_socket_t fd, short which, void *arg)
|
||||||
{
|
{
|
||||||
ev_intptr_t idx = (ev_intptr_t) arg, widx = idx + 1;
|
ev_intptr_t idx = (ev_intptr_t) arg, widx = idx + 1;
|
||||||
u_char ch;
|
unsigned char ch;
|
||||||
ev_ssize_t n;
|
ev_ssize_t n;
|
||||||
|
|
||||||
n = recv(fd, (char*)&ch, sizeof(ch), 0);
|
n = recv(fd, (char*)&ch, sizeof(ch), 0);
|
||||||
|
@ -151,7 +151,7 @@ launch_request(void)
|
|||||||
}
|
}
|
||||||
frob_socket(sock);
|
frob_socket(sock);
|
||||||
if (connect(sock, (struct sockaddr*)&sin, sizeof(sin)) < 0) {
|
if (connect(sock, (struct sockaddr*)&sin, sizeof(sin)) < 0) {
|
||||||
int e = errno;
|
int e = evutil_socket_geterror(sock);
|
||||||
if (! EVUTIL_ERR_CONNECT_RETRIABLE(e)) {
|
if (! EVUTIL_ERR_CONNECT_RETRIABLE(e)) {
|
||||||
evutil_closesocket(sock);
|
evutil_closesocket(sock);
|
||||||
return -1;
|
return -1;
|
||||||
@ -183,6 +183,11 @@ main(int argc, char **argv)
|
|||||||
double throughput;
|
double throughput;
|
||||||
resource = "/ref";
|
resource = "/ref";
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
WSADATA WSAData;
|
||||||
|
WSAStartup(0x101, &WSAData);
|
||||||
|
#endif
|
||||||
|
|
||||||
setvbuf(stdout, NULL, _IONBF, 0);
|
setvbuf(stdout, NULL, _IONBF, 0);
|
||||||
|
|
||||||
base = event_base_new();
|
base = event_base_new();
|
||||||
@ -226,5 +231,9 @@ main(int argc, char **argv)
|
|||||||
(double)(usec/1000) / total_n_handled,
|
(double)(usec/1000) / total_n_handled,
|
||||||
(I64_TYP)total_n_bytes, n_errors);
|
(I64_TYP)total_n_bytes, n_errors);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
WSACleanup();
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2290,7 +2290,7 @@ end:
|
|||||||
static void
|
static void
|
||||||
evtag_fuzz(void *ptr)
|
evtag_fuzz(void *ptr)
|
||||||
{
|
{
|
||||||
u_char buffer[4096];
|
unsigned char buffer[4096];
|
||||||
struct evbuffer *tmp = evbuffer_new();
|
struct evbuffer *tmp = evbuffer_new();
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
@ -129,6 +129,14 @@ long timeval_msec_diff(const struct timeval *start, const struct timeval *end);
|
|||||||
pid_t regress_fork(void);
|
pid_t regress_fork(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef EVENT__HAVE_OPENSSL
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
EVP_PKEY *ssl_getkey(void);
|
||||||
|
X509 *ssl_getcert(void);
|
||||||
|
SSL_CTX *get_ssl_ctx(void);
|
||||||
|
void init_ssl(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -198,7 +198,7 @@ test_evbuffer(void *ptr)
|
|||||||
|
|
||||||
tt_assert(evbuffer_get_length(evb_two) == 0);
|
tt_assert(evbuffer_get_length(evb_two) == 0);
|
||||||
tt_assert(evbuffer_get_length(evb) == 7);
|
tt_assert(evbuffer_get_length(evb) == 7);
|
||||||
tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "1/hello", 7) != 0);
|
tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "1/hello", 7));
|
||||||
|
|
||||||
memset(buffer, 0, sizeof(buffer));
|
memset(buffer, 0, sizeof(buffer));
|
||||||
evbuffer_add(evb, buffer, sizeof(buffer));
|
evbuffer_add(evb, buffer, sizeof(buffer));
|
||||||
@ -1292,7 +1292,7 @@ test_evbuffer_iterative(void *ptr)
|
|||||||
static void
|
static void
|
||||||
test_evbuffer_find(void *ptr)
|
test_evbuffer_find(void *ptr)
|
||||||
{
|
{
|
||||||
u_char* p;
|
unsigned char* p;
|
||||||
const char* test1 = "1234567890\r\n";
|
const char* test1 = "1234567890\r\n";
|
||||||
const char* test2 = "1234567890\r";
|
const char* test2 = "1234567890\r";
|
||||||
#define EVBUFFER_INITIAL_LENGTH 256
|
#define EVBUFFER_INITIAL_LENGTH 256
|
||||||
@ -1303,13 +1303,13 @@ test_evbuffer_find(void *ptr)
|
|||||||
tt_assert(buf);
|
tt_assert(buf);
|
||||||
|
|
||||||
/* make sure evbuffer_find doesn't match past the end of the buffer */
|
/* make sure evbuffer_find doesn't match past the end of the buffer */
|
||||||
evbuffer_add(buf, (u_char*)test1, strlen(test1));
|
evbuffer_add(buf, (unsigned char*)test1, strlen(test1));
|
||||||
evbuffer_validate(buf);
|
evbuffer_validate(buf);
|
||||||
evbuffer_drain(buf, strlen(test1));
|
evbuffer_drain(buf, strlen(test1));
|
||||||
evbuffer_validate(buf);
|
evbuffer_validate(buf);
|
||||||
evbuffer_add(buf, (u_char*)test2, strlen(test2));
|
evbuffer_add(buf, (unsigned char*)test2, strlen(test2));
|
||||||
evbuffer_validate(buf);
|
evbuffer_validate(buf);
|
||||||
p = evbuffer_find(buf, (u_char*)"\r\n", 2);
|
p = evbuffer_find(buf, (unsigned char*)"\r\n", 2);
|
||||||
tt_want(p == NULL);
|
tt_want(p == NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1321,13 +1321,13 @@ test_evbuffer_find(void *ptr)
|
|||||||
for (i = 0; i < EVBUFFER_INITIAL_LENGTH; ++i)
|
for (i = 0; i < EVBUFFER_INITIAL_LENGTH; ++i)
|
||||||
test3[i] = 'a';
|
test3[i] = 'a';
|
||||||
test3[EVBUFFER_INITIAL_LENGTH - 1] = 'x';
|
test3[EVBUFFER_INITIAL_LENGTH - 1] = 'x';
|
||||||
evbuffer_add(buf, (u_char *)test3, EVBUFFER_INITIAL_LENGTH);
|
evbuffer_add(buf, (unsigned char *)test3, EVBUFFER_INITIAL_LENGTH);
|
||||||
evbuffer_validate(buf);
|
evbuffer_validate(buf);
|
||||||
p = evbuffer_find(buf, (u_char *)"xy", 2);
|
p = evbuffer_find(buf, (unsigned char *)"xy", 2);
|
||||||
tt_want(p == NULL);
|
tt_want(p == NULL);
|
||||||
|
|
||||||
/* simple test for match at end of allocated buffer */
|
/* simple test for match at end of allocated buffer */
|
||||||
p = evbuffer_find(buf, (u_char *)"ax", 2);
|
p = evbuffer_find(buf, (unsigned char *)"ax", 2);
|
||||||
tt_assert(p != NULL);
|
tt_assert(p != NULL);
|
||||||
tt_want(strncmp((char*)p, "ax", 2) == 0);
|
tt_want(strncmp((char*)p, "ax", 2) == 0);
|
||||||
|
|
||||||
|
@ -123,11 +123,12 @@ errorcb(struct bufferevent *bev, short what, void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_bufferevent_impl(int use_pair)
|
test_bufferevent_impl(int use_pair, int flush)
|
||||||
{
|
{
|
||||||
struct bufferevent *bev1 = NULL, *bev2 = NULL;
|
struct bufferevent *bev1 = NULL, *bev2 = NULL;
|
||||||
char buffer[8333];
|
char buffer[8333];
|
||||||
int i;
|
int i;
|
||||||
|
int expected = 2;
|
||||||
|
|
||||||
if (use_pair) {
|
if (use_pair) {
|
||||||
struct bufferevent *pair[2];
|
struct bufferevent *pair[2];
|
||||||
@ -171,6 +172,9 @@ test_bufferevent_impl(int use_pair)
|
|||||||
buffer[i] = i;
|
buffer[i] = i;
|
||||||
|
|
||||||
bufferevent_write(bev1, buffer, sizeof(buffer));
|
bufferevent_write(bev1, buffer, sizeof(buffer));
|
||||||
|
if (flush >= 0) {
|
||||||
|
tt_int_op(bufferevent_flush(bev1, EV_WRITE, flush), >=, 0);
|
||||||
|
}
|
||||||
|
|
||||||
event_dispatch();
|
event_dispatch();
|
||||||
|
|
||||||
@ -178,23 +182,26 @@ test_bufferevent_impl(int use_pair)
|
|||||||
tt_ptr_op(bufferevent_pair_get_partner(bev1), ==, NULL);
|
tt_ptr_op(bufferevent_pair_get_partner(bev1), ==, NULL);
|
||||||
bufferevent_free(bev1);
|
bufferevent_free(bev1);
|
||||||
|
|
||||||
if (test_ok != 2)
|
/** Only pair call errorcb for BEV_FINISHED */
|
||||||
|
if (use_pair && flush == BEV_FINISHED) {
|
||||||
|
expected = -1;
|
||||||
|
}
|
||||||
|
if (test_ok != expected)
|
||||||
test_ok = 0;
|
test_ok = 0;
|
||||||
end:
|
end:
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void test_bufferevent(void) { test_bufferevent_impl(0, -1); }
|
||||||
test_bufferevent(void)
|
static void test_bufferevent_pair(void) { test_bufferevent_impl(1, -1); }
|
||||||
{
|
|
||||||
test_bufferevent_impl(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void test_bufferevent_flush_normal(void) { test_bufferevent_impl(0, BEV_NORMAL); }
|
||||||
test_bufferevent_pair(void)
|
static void test_bufferevent_flush_flush(void) { test_bufferevent_impl(0, BEV_FLUSH); }
|
||||||
{
|
static void test_bufferevent_flush_finished(void) { test_bufferevent_impl(0, BEV_FINISHED); }
|
||||||
test_bufferevent_impl(1);
|
|
||||||
}
|
static void test_bufferevent_pair_flush_normal(void) { test_bufferevent_impl(1, BEV_NORMAL); }
|
||||||
|
static void test_bufferevent_pair_flush_flush(void) { test_bufferevent_impl(1, BEV_FLUSH); }
|
||||||
|
static void test_bufferevent_pair_flush_finished(void) { test_bufferevent_impl(1, BEV_FINISHED); }
|
||||||
|
|
||||||
#if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED)
|
#if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED)
|
||||||
/**
|
/**
|
||||||
@ -245,7 +252,6 @@ static void trace_lock_free(void *lock_, unsigned locktype)
|
|||||||
{
|
{
|
||||||
lock_wrapper *lock = lu_find(lock_);
|
lock_wrapper *lock = lu_find(lock_);
|
||||||
if (!lock || lock->status == FREE || lock->locked) {
|
if (!lock || lock->status == FREE || lock->locked) {
|
||||||
__asm__("int3");
|
|
||||||
TT_FAIL(("lock: free error"));
|
TT_FAIL(("lock: free error"));
|
||||||
} else {
|
} else {
|
||||||
lock->status = FREE;
|
lock->status = FREE;
|
||||||
@ -278,6 +284,9 @@ static void lock_unlock_free_thread_cbs(void)
|
|||||||
{
|
{
|
||||||
event_base_free(NULL);
|
event_base_free(NULL);
|
||||||
|
|
||||||
|
if (libevent_tests_running_in_debug_mode)
|
||||||
|
libevent_global_shutdown();
|
||||||
|
|
||||||
/** drop immutable flag */
|
/** drop immutable flag */
|
||||||
evthread_set_lock_callbacks(NULL);
|
evthread_set_lock_callbacks(NULL);
|
||||||
/** avoid calling of event_global_setup_locks_() for new cbs */
|
/** avoid calling of event_global_setup_locks_() for new cbs */
|
||||||
@ -311,6 +320,9 @@ static int use_lock_unlock_profiler(void)
|
|||||||
}
|
}
|
||||||
static void free_lock_unlock_profiler(struct basic_test_data *data)
|
static void free_lock_unlock_profiler(struct basic_test_data *data)
|
||||||
{
|
{
|
||||||
|
/** fix "held_by" for kqueue */
|
||||||
|
evthread_set_lock_callbacks(NULL);
|
||||||
|
|
||||||
lock_unlock_free_thread_cbs();
|
lock_unlock_free_thread_cbs();
|
||||||
free(lu_base.locks);
|
free(lu_base.locks);
|
||||||
data->base = NULL;
|
data->base = NULL;
|
||||||
@ -594,6 +606,7 @@ static int bufferevent_connect_test_flags = 0;
|
|||||||
static int bufferevent_trigger_test_flags = 0;
|
static int bufferevent_trigger_test_flags = 0;
|
||||||
static int n_strings_read = 0;
|
static int n_strings_read = 0;
|
||||||
static int n_reads_invoked = 0;
|
static int n_reads_invoked = 0;
|
||||||
|
static int n_events_invoked = 0;
|
||||||
|
|
||||||
#define TEST_STR "Now is the time for all good events to signal for " \
|
#define TEST_STR "Now is the time for all good events to signal for " \
|
||||||
"the good of their protocol"
|
"the good of their protocol"
|
||||||
@ -613,6 +626,31 @@ end:
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
fake_listener_create(struct sockaddr_in *localhost)
|
||||||
|
{
|
||||||
|
struct sockaddr *sa = (struct sockaddr *)localhost;
|
||||||
|
evutil_socket_t fd = -1;
|
||||||
|
ev_socklen_t slen = sizeof(*localhost);
|
||||||
|
|
||||||
|
memset(localhost, 0, sizeof(*localhost));
|
||||||
|
localhost->sin_port = 0; /* have the kernel pick a port */
|
||||||
|
localhost->sin_addr.s_addr = htonl(0x7f000001L);
|
||||||
|
localhost->sin_family = AF_INET;
|
||||||
|
|
||||||
|
/* bind, but don't listen or accept. should trigger
|
||||||
|
"Connection refused" reliably on most platforms. */
|
||||||
|
fd = socket(localhost->sin_family, SOCK_STREAM, 0);
|
||||||
|
tt_assert(fd >= 0);
|
||||||
|
tt_assert(bind(fd, sa, slen) == 0);
|
||||||
|
tt_assert(getsockname(fd, sa, &slen) == 0);
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
|
||||||
|
end:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
reader_eventcb(struct bufferevent *bev, short what, void *ctx)
|
reader_eventcb(struct bufferevent *bev, short what, void *ctx)
|
||||||
{
|
{
|
||||||
@ -642,6 +680,14 @@ end:
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
reader_eventcb_simple(struct bufferevent *bev, short what, void *ctx)
|
||||||
|
{
|
||||||
|
TT_BLATHER(("Read eventcb simple invoked on %d.",
|
||||||
|
(int)bufferevent_getfd(bev)));
|
||||||
|
n_events_invoked++;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
reader_readcb(struct bufferevent *bev, void *ctx)
|
reader_readcb(struct bufferevent *bev, void *ctx)
|
||||||
{
|
{
|
||||||
@ -727,6 +773,45 @@ end:
|
|||||||
bufferevent_free(bev2);
|
bufferevent_free(bev2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_bufferevent_connect_fail_eventcb(void *arg)
|
||||||
|
{
|
||||||
|
struct basic_test_data *data = arg;
|
||||||
|
int flags = BEV_OPT_CLOSE_ON_FREE | (long)data->setup_data;
|
||||||
|
struct bufferevent *bev = NULL;
|
||||||
|
struct evconnlistener *lev = NULL;
|
||||||
|
struct sockaddr_in localhost;
|
||||||
|
ev_socklen_t slen = sizeof(localhost);
|
||||||
|
evutil_socket_t fake_listener = -1;
|
||||||
|
|
||||||
|
fake_listener = fake_listener_create(&localhost);
|
||||||
|
|
||||||
|
tt_int_op(n_events_invoked, ==, 0);
|
||||||
|
|
||||||
|
bev = bufferevent_socket_new(data->base, -1, flags);
|
||||||
|
tt_assert(bev);
|
||||||
|
bufferevent_setcb(bev, reader_readcb, reader_readcb,
|
||||||
|
reader_eventcb_simple, data->base);
|
||||||
|
bufferevent_enable(bev, EV_READ|EV_WRITE);
|
||||||
|
tt_int_op(n_events_invoked, ==, 0);
|
||||||
|
tt_int_op(n_reads_invoked, ==, 0);
|
||||||
|
/** @see also test_bufferevent_connect_fail() */
|
||||||
|
bufferevent_socket_connect(bev, (struct sockaddr *)&localhost, slen);
|
||||||
|
tt_int_op(n_events_invoked, ==, 0);
|
||||||
|
tt_int_op(n_reads_invoked, ==, 0);
|
||||||
|
event_base_dispatch(data->base);
|
||||||
|
tt_int_op(n_events_invoked, ==, 1);
|
||||||
|
tt_int_op(n_reads_invoked, ==, 0);
|
||||||
|
|
||||||
|
end:
|
||||||
|
if (lev)
|
||||||
|
evconnlistener_free(lev);
|
||||||
|
if (bev)
|
||||||
|
bufferevent_free(bev);
|
||||||
|
if (fake_listener >= 0)
|
||||||
|
evutil_closesocket(fake_listener);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
want_fail_eventcb(struct bufferevent *bev, short what, void *ctx)
|
want_fail_eventcb(struct bufferevent *bev, short what, void *ctx)
|
||||||
{
|
{
|
||||||
@ -762,34 +847,23 @@ test_bufferevent_connect_fail(void *arg)
|
|||||||
{
|
{
|
||||||
struct basic_test_data *data = (struct basic_test_data *)arg;
|
struct basic_test_data *data = (struct basic_test_data *)arg;
|
||||||
struct bufferevent *bev=NULL;
|
struct bufferevent *bev=NULL;
|
||||||
struct sockaddr_in localhost;
|
|
||||||
struct sockaddr *sa = (struct sockaddr*)&localhost;
|
|
||||||
evutil_socket_t fake_listener = -1;
|
|
||||||
ev_socklen_t slen = sizeof(localhost);
|
|
||||||
struct event close_listener_event;
|
struct event close_listener_event;
|
||||||
int close_listener_event_added = 0;
|
int close_listener_event_added = 0;
|
||||||
struct timeval one_second = { 1, 0 };
|
struct timeval one_second = { 1, 0 };
|
||||||
|
struct sockaddr_in localhost;
|
||||||
|
ev_socklen_t slen = sizeof(localhost);
|
||||||
|
evutil_socket_t fake_listener = -1;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
test_ok = 0;
|
test_ok = 0;
|
||||||
|
|
||||||
memset(&localhost, 0, sizeof(localhost));
|
fake_listener = fake_listener_create(&localhost);
|
||||||
localhost.sin_port = 0; /* have the kernel pick a port */
|
|
||||||
localhost.sin_addr.s_addr = htonl(0x7f000001L);
|
|
||||||
localhost.sin_family = AF_INET;
|
|
||||||
|
|
||||||
/* bind, but don't listen or accept. should trigger
|
|
||||||
"Connection refused" reliably on most platforms. */
|
|
||||||
fake_listener = socket(localhost.sin_family, SOCK_STREAM, 0);
|
|
||||||
tt_assert(fake_listener >= 0);
|
|
||||||
tt_assert(bind(fake_listener, sa, slen) == 0);
|
|
||||||
tt_assert(getsockname(fake_listener, sa, &slen) == 0);
|
|
||||||
bev = bufferevent_socket_new(data->base, -1,
|
bev = bufferevent_socket_new(data->base, -1,
|
||||||
BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
|
BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
|
||||||
tt_assert(bev);
|
tt_assert(bev);
|
||||||
bufferevent_setcb(bev, NULL, NULL, want_fail_eventcb, data->base);
|
bufferevent_setcb(bev, NULL, NULL, want_fail_eventcb, data->base);
|
||||||
|
|
||||||
r = bufferevent_socket_connect(bev, sa, slen);
|
r = bufferevent_socket_connect(bev, (struct sockaddr *)&localhost, slen);
|
||||||
/* XXXX we'd like to test the '0' case everywhere, but FreeBSD tells
|
/* XXXX we'd like to test the '0' case everywhere, but FreeBSD tells
|
||||||
* detects the error immediately, which is not really wrong of it. */
|
* detects the error immediately, which is not really wrong of it. */
|
||||||
tt_want(r == 0 || r == -1);
|
tt_want(r == 0 || r == -1);
|
||||||
@ -1084,10 +1158,35 @@ end:
|
|||||||
bufferevent_free(bev);
|
bufferevent_free(bev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_bufferevent_socket_filter_inactive(void *arg)
|
||||||
|
{
|
||||||
|
struct basic_test_data *data = arg;
|
||||||
|
struct bufferevent *bev = NULL, *bevf = NULL;
|
||||||
|
|
||||||
|
bev = bufferevent_socket_new(data->base, -1, 0);
|
||||||
|
tt_assert(bev);
|
||||||
|
bevf = bufferevent_filter_new(bev, NULL, NULL, 0, NULL, NULL);
|
||||||
|
tt_assert(bevf);
|
||||||
|
|
||||||
|
end:
|
||||||
|
if (bevf)
|
||||||
|
bufferevent_free(bevf);
|
||||||
|
if (bev)
|
||||||
|
bufferevent_free(bev);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct testcase_t bufferevent_testcases[] = {
|
struct testcase_t bufferevent_testcases[] = {
|
||||||
|
|
||||||
LEGACY(bufferevent, TT_ISOLATED),
|
LEGACY(bufferevent, TT_ISOLATED),
|
||||||
LEGACY(bufferevent_pair, TT_ISOLATED),
|
LEGACY(bufferevent_pair, TT_ISOLATED),
|
||||||
|
LEGACY(bufferevent_flush_normal, TT_ISOLATED),
|
||||||
|
LEGACY(bufferevent_flush_flush, TT_ISOLATED),
|
||||||
|
LEGACY(bufferevent_flush_finished, TT_ISOLATED),
|
||||||
|
LEGACY(bufferevent_pair_flush_normal, TT_ISOLATED),
|
||||||
|
LEGACY(bufferevent_pair_flush_flush, TT_ISOLATED),
|
||||||
|
LEGACY(bufferevent_pair_flush_finished, TT_ISOLATED),
|
||||||
#if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED)
|
#if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED)
|
||||||
{ "bufferevent_pair_release_lock", test_bufferevent_pair_release_lock,
|
{ "bufferevent_pair_release_lock", test_bufferevent_pair_release_lock,
|
||||||
TT_FORK|TT_ISOLATED|TT_NEED_THREADS|TT_NEED_BASE|TT_LEGACY,
|
TT_FORK|TT_ISOLATED|TT_NEED_THREADS|TT_NEED_BASE|TT_LEGACY,
|
||||||
@ -1135,12 +1234,26 @@ struct testcase_t bufferevent_testcases[] = {
|
|||||||
{ "bufferevent_zlib", NULL, TT_SKIP, NULL, NULL },
|
{ "bufferevent_zlib", NULL, TT_SKIP, NULL, NULL },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
{ "bufferevent_connect_fail_eventcb_defer",
|
||||||
|
test_bufferevent_connect_fail_eventcb,
|
||||||
|
TT_FORK|TT_NEED_BASE, &basic_setup, (void*)BEV_OPT_DEFER_CALLBACKS },
|
||||||
|
{ "bufferevent_connect_fail_eventcb",
|
||||||
|
test_bufferevent_connect_fail_eventcb,
|
||||||
|
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
|
||||||
|
|
||||||
|
{ "bufferevent_socket_filter_inactive",
|
||||||
|
test_bufferevent_socket_filter_inactive,
|
||||||
|
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
|
||||||
|
|
||||||
END_OF_TESTCASES,
|
END_OF_TESTCASES,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct testcase_t bufferevent_iocp_testcases[] = {
|
struct testcase_t bufferevent_iocp_testcases[] = {
|
||||||
|
|
||||||
LEGACY(bufferevent, TT_ISOLATED|TT_ENABLE_IOCP),
|
LEGACY(bufferevent, TT_ISOLATED|TT_ENABLE_IOCP),
|
||||||
|
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_watermarks, TT_ISOLATED|TT_ENABLE_IOCP),
|
||||||
LEGACY(bufferevent_filters, TT_ISOLATED|TT_ENABLE_IOCP),
|
LEGACY(bufferevent_filters, TT_ISOLATED|TT_ENABLE_IOCP),
|
||||||
{ "bufferevent_connect", test_bufferevent_connect,
|
{ "bufferevent_connect", test_bufferevent_connect,
|
||||||
@ -1159,5 +1272,13 @@ struct testcase_t bufferevent_iocp_testcases[] = {
|
|||||||
TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup,
|
TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup,
|
||||||
(void*)"unset_connectex" },
|
(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 },
|
||||||
|
{ "bufferevent_connect_fail",
|
||||||
|
test_bufferevent_connect_fail_eventcb,
|
||||||
|
TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, NULL },
|
||||||
|
|
||||||
END_OF_TESTCASES,
|
END_OF_TESTCASES,
|
||||||
};
|
};
|
||||||
|
@ -72,6 +72,8 @@
|
|||||||
#include "regress.h"
|
#include "regress.h"
|
||||||
#include "regress_testutils.h"
|
#include "regress_testutils.h"
|
||||||
|
|
||||||
|
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
|
||||||
|
|
||||||
static int dns_ok = 0;
|
static int dns_ok = 0;
|
||||||
static int dns_got_cancel = 0;
|
static int dns_got_cancel = 0;
|
||||||
static int dns_err = 0;
|
static int dns_err = 0;
|
||||||
@ -511,25 +513,25 @@ generic_dns_callback(int result, char type, int count, int ttl, void *addresses,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct regress_dns_server_table search_table[] = {
|
static struct regress_dns_server_table search_table[] = {
|
||||||
{ "host.a.example.com", "err", "3", 0 },
|
{ "host.a.example.com", "err", "3", 0, 0 },
|
||||||
{ "host.b.example.com", "err", "3", 0 },
|
{ "host.b.example.com", "err", "3", 0, 0 },
|
||||||
{ "host.c.example.com", "A", "11.22.33.44", 0 },
|
{ "host.c.example.com", "A", "11.22.33.44", 0, 0 },
|
||||||
{ "host2.a.example.com", "err", "3", 0 },
|
{ "host2.a.example.com", "err", "3", 0, 0 },
|
||||||
{ "host2.b.example.com", "A", "200.100.0.100", 0 },
|
{ "host2.b.example.com", "A", "200.100.0.100", 0, 0 },
|
||||||
{ "host2.c.example.com", "err", "3", 0 },
|
{ "host2.c.example.com", "err", "3", 0, 0 },
|
||||||
{ "hostn.a.example.com", "errsoa", "0", 0 },
|
{ "hostn.a.example.com", "errsoa", "0", 0, 0 },
|
||||||
{ "hostn.b.example.com", "errsoa", "3", 0 },
|
{ "hostn.b.example.com", "errsoa", "3", 0, 0 },
|
||||||
{ "hostn.c.example.com", "err", "0", 0 },
|
{ "hostn.c.example.com", "err", "0", 0, 0 },
|
||||||
|
|
||||||
{ "host", "err", "3", 0 },
|
{ "host", "err", "3", 0, 0 },
|
||||||
{ "host2", "err", "3", 0 },
|
{ "host2", "err", "3", 0, 0 },
|
||||||
{ "*", "err", "3", 0 },
|
{ "*", "err", "3", 0, 0 },
|
||||||
{ NULL, NULL, NULL, 0 }
|
{ NULL, NULL, NULL, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dns_search_test(void *arg)
|
dns_search_test_impl(void *arg, int lower)
|
||||||
{
|
{
|
||||||
|
struct regress_dns_server_table table[ARRAY_SIZE(search_table)];
|
||||||
struct basic_test_data *data = arg;
|
struct basic_test_data *data = arg;
|
||||||
struct event_base *base = data->base;
|
struct event_base *base = data->base;
|
||||||
struct evdns_base *dns = NULL;
|
struct evdns_base *dns = NULL;
|
||||||
@ -537,8 +539,14 @@ dns_search_test(void *arg)
|
|||||||
char buf[64];
|
char buf[64];
|
||||||
|
|
||||||
struct generic_dns_callback_result r[8];
|
struct generic_dns_callback_result r[8];
|
||||||
|
size_t i;
|
||||||
|
|
||||||
tt_assert(regress_dnsserver(base, &portnum, search_table));
|
for (i = 0; i < ARRAY_SIZE(table); ++i) {
|
||||||
|
table[i] = search_table[i];
|
||||||
|
table[i].lower = lower;
|
||||||
|
}
|
||||||
|
|
||||||
|
tt_assert(regress_dnsserver(base, &portnum, table));
|
||||||
evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum);
|
evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum);
|
||||||
|
|
||||||
dns = evdns_base_new(base, 0);
|
dns = evdns_base_new(base, 0);
|
||||||
@ -548,7 +556,7 @@ dns_search_test(void *arg)
|
|||||||
evdns_base_search_add(dns, "b.example.com");
|
evdns_base_search_add(dns, "b.example.com");
|
||||||
evdns_base_search_add(dns, "c.example.com");
|
evdns_base_search_add(dns, "c.example.com");
|
||||||
|
|
||||||
n_replies_left = sizeof(r)/sizeof(r[0]);
|
n_replies_left = ARRAY_SIZE(r);
|
||||||
exit_base = base;
|
exit_base = base;
|
||||||
|
|
||||||
evdns_base_resolve_ipv4(dns, "host", 0, generic_dns_callback, &r[0]);
|
evdns_base_resolve_ipv4(dns, "host", 0, generic_dns_callback, &r[0]);
|
||||||
@ -584,6 +592,16 @@ end:
|
|||||||
|
|
||||||
regress_clean_dnsserver();
|
regress_clean_dnsserver();
|
||||||
}
|
}
|
||||||
|
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 int request_count = 0;
|
static int request_count = 0;
|
||||||
static struct evdns_request *current_req = NULL;
|
static struct evdns_request *current_req = NULL;
|
||||||
@ -776,13 +794,13 @@ static struct regress_dns_server_table internal_error_table[] = {
|
|||||||
|
|
||||||
XXXX we should reissue under a much wider set of circumstances!
|
XXXX we should reissue under a much wider set of circumstances!
|
||||||
*/
|
*/
|
||||||
{ "foof.example.com", "err", "4", 0 },
|
{ "foof.example.com", "err", "4", 0, 0 },
|
||||||
{ NULL, NULL, NULL, 0 }
|
{ NULL, NULL, NULL, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct regress_dns_server_table reissue_table[] = {
|
static struct regress_dns_server_table reissue_table[] = {
|
||||||
{ "foof.example.com", "A", "240.15.240.15", 0 },
|
{ "foof.example.com", "A", "240.15.240.15", 0, 0 },
|
||||||
{ NULL, NULL, NULL, 0 }
|
{ NULL, NULL, NULL, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1672,7 +1690,6 @@ test_getaddrinfo_async(void *arg)
|
|||||||
end:
|
end:
|
||||||
if (local_outcome.ai)
|
if (local_outcome.ai)
|
||||||
evutil_freeaddrinfo(local_outcome.ai);
|
evutil_freeaddrinfo(local_outcome.ai);
|
||||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
|
|
||||||
for (i=0;i<(int)ARRAY_SIZE(a_out);++i) {
|
for (i=0;i<(int)ARRAY_SIZE(a_out);++i) {
|
||||||
if (a_out[i].ai)
|
if (a_out[i].ai)
|
||||||
evutil_freeaddrinfo(a_out[i].ai);
|
evutil_freeaddrinfo(a_out[i].ai);
|
||||||
@ -1885,29 +1902,22 @@ dbg_leak_resume(void *env_, int cancel, int send_err_shutdown)
|
|||||||
tt_assert(!evdns_base_resume(env->dns_base));
|
tt_assert(!evdns_base_resume(env->dns_base));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event_base_loop(env->base, EVLOOP_NONBLOCK);
|
||||||
/**
|
/**
|
||||||
* Because we don't cancel request,
|
* Because we don't cancel request, and want our callback to recieve
|
||||||
* and want our callback to recieve DNS_ERR_SHUTDOWN,
|
* DNS_ERR_SHUTDOWN, we use deferred callback, and there was:
|
||||||
* we use deferred callback, and there was
|
|
||||||
* - one extra malloc(),
|
* - one extra malloc(),
|
||||||
* @see reply_schedule_callback()
|
* @see reply_schedule_callback()
|
||||||
* - and one missing free
|
* - and one missing free
|
||||||
* @see request_finished() (req->handle->pending_cb = 1)
|
* @see request_finished() (req->handle->pending_cb = 1)
|
||||||
* than we don't need to count in testleak_cleanup()
|
* than we don't need to count in testleak_cleanup(), but we can clean them
|
||||||
*
|
* if we will run loop once again, but *after* evdns base freed.
|
||||||
* So just decrement allocated_chunks to 2,
|
|
||||||
* like we already take care about it.
|
|
||||||
*/
|
*/
|
||||||
if (!cancel && send_err_shutdown) {
|
evdns_base_free(env->dns_base, send_err_shutdown);
|
||||||
allocated_chunks -= 2;
|
env->dns_base = 0;
|
||||||
}
|
|
||||||
|
|
||||||
event_base_loop(env->base, EVLOOP_NONBLOCK);
|
event_base_loop(env->base, EVLOOP_NONBLOCK);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
evdns_base_free(env->dns_base, send_err_shutdown);
|
|
||||||
env->dns_base = 0;
|
|
||||||
|
|
||||||
event_base_free(env->base);
|
event_base_free(env->base);
|
||||||
env->base = 0;
|
env->base = 0;
|
||||||
}
|
}
|
||||||
@ -1998,6 +2008,91 @@ end:
|
|||||||
evutil_closesocket(fd);
|
evutil_closesocket(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dns_client_fail_requests_test(void *arg)
|
||||||
|
{
|
||||||
|
struct basic_test_data *data = arg;
|
||||||
|
struct event_base *base = data->base;
|
||||||
|
struct evdns_base *dns = NULL;
|
||||||
|
struct evdns_server_port *dns_port = NULL;
|
||||||
|
ev_uint16_t portnum = 0;
|
||||||
|
char buf[64];
|
||||||
|
|
||||||
|
struct generic_dns_callback_result r[20];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
dns_port = regress_get_dnsserver(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);
|
||||||
|
|
||||||
|
dns = evdns_base_new(base, EVDNS_BASE_DISABLE_WHEN_INACTIVE);
|
||||||
|
tt_assert(!evdns_base_nameserver_ip_add(dns, buf));
|
||||||
|
|
||||||
|
for (i = 0; i < 20; ++i)
|
||||||
|
evdns_base_resolve_ipv4(dns, "foof.example.com", 0, generic_dns_callback, &r[i]);
|
||||||
|
|
||||||
|
n_replies_left = 20;
|
||||||
|
exit_base = base;
|
||||||
|
|
||||||
|
evdns_base_free(dns, 1 /** fail requests */);
|
||||||
|
/** run defered callbacks, to trigger UAF */
|
||||||
|
event_base_dispatch(base);
|
||||||
|
|
||||||
|
tt_int_op(n_replies_left, ==, 0);
|
||||||
|
for (i = 0; i < 20; ++i)
|
||||||
|
tt_int_op(r[i].result, ==, DNS_ERR_SHUTDOWN);
|
||||||
|
|
||||||
|
end:
|
||||||
|
evdns_close_server_port(dns_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
getaddrinfo_cb(int err, struct evutil_addrinfo *res, void *ptr)
|
||||||
|
{
|
||||||
|
generic_dns_callback(err, 0, 0, 0, NULL, ptr);
|
||||||
|
}
|
||||||
|
static void
|
||||||
|
dns_client_fail_requests_getaddrinfo_test(void *arg)
|
||||||
|
{
|
||||||
|
struct basic_test_data *data = arg;
|
||||||
|
struct event_base *base = data->base;
|
||||||
|
struct evdns_base *dns = NULL;
|
||||||
|
struct evdns_server_port *dns_port = NULL;
|
||||||
|
ev_uint16_t portnum = 0;
|
||||||
|
char buf[64];
|
||||||
|
|
||||||
|
struct generic_dns_callback_result r[20];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
dns_port = regress_get_dnsserver(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);
|
||||||
|
|
||||||
|
dns = evdns_base_new(base, EVDNS_BASE_DISABLE_WHEN_INACTIVE);
|
||||||
|
tt_assert(!evdns_base_nameserver_ip_add(dns, buf));
|
||||||
|
|
||||||
|
for (i = 0; i < 20; ++i)
|
||||||
|
tt_assert(evdns_getaddrinfo(dns, "foof.example.com", "http", NULL, getaddrinfo_cb, &r[i]));
|
||||||
|
|
||||||
|
n_replies_left = 20;
|
||||||
|
exit_base = base;
|
||||||
|
|
||||||
|
evdns_base_free(dns, 1 /** fail requests */);
|
||||||
|
/** run defered callbacks, to trigger UAF */
|
||||||
|
event_base_dispatch(base);
|
||||||
|
|
||||||
|
tt_int_op(n_replies_left, ==, 0);
|
||||||
|
for (i = 0; i < 20; ++i)
|
||||||
|
tt_int_op(r[i].result, ==, EVUTIL_EAI_FAIL);
|
||||||
|
|
||||||
|
end:
|
||||||
|
evdns_close_server_port(dns_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define DNS_LEGACY(name, flags) \
|
#define DNS_LEGACY(name, flags) \
|
||||||
{ #name, run_legacy_test_fn, flags|TT_LEGACY, &legacy_setup, \
|
{ #name, run_legacy_test_fn, flags|TT_LEGACY, &legacy_setup, \
|
||||||
@ -2010,6 +2105,7 @@ struct testcase_t dns_testcases[] = {
|
|||||||
DNS_LEGACY(gethostbyaddr, TT_FORK|TT_NEED_BASE|TT_NEED_DNS|TT_OFF_BY_DEFAULT),
|
DNS_LEGACY(gethostbyaddr, TT_FORK|TT_NEED_BASE|TT_NEED_DNS|TT_OFF_BY_DEFAULT),
|
||||||
{ "resolve_reverse", dns_resolve_reverse, TT_FORK|TT_OFF_BY_DEFAULT, NULL, NULL },
|
{ "resolve_reverse", dns_resolve_reverse, TT_FORK|TT_OFF_BY_DEFAULT, NULL, NULL },
|
||||||
{ "search", dns_search_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
|
{ "search", dns_search_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
|
||||||
|
{ "search_lower", dns_search_lower_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
|
||||||
{ "search_cancel", dns_search_cancel_test,
|
{ "search_cancel", dns_search_cancel_test,
|
||||||
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
|
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
|
||||||
{ "retry", dns_retry_test, TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL },
|
{ "retry", dns_retry_test, TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL },
|
||||||
@ -2044,6 +2140,12 @@ struct testcase_t dns_testcases[] = {
|
|||||||
TT_FORK, &testleak_funcs, NULL },
|
TT_FORK, &testleak_funcs, NULL },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
{ "client_fail_requests", dns_client_fail_requests_test,
|
||||||
|
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
|
||||||
|
{ "client_fail_requests_getaddrinfo",
|
||||||
|
dns_client_fail_requests_getaddrinfo_test,
|
||||||
|
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
|
||||||
|
|
||||||
END_OF_TESTCASES
|
END_OF_TESTCASES
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -58,7 +58,9 @@
|
|||||||
#include "event2/http.h"
|
#include "event2/http.h"
|
||||||
#include "event2/buffer.h"
|
#include "event2/buffer.h"
|
||||||
#include "event2/bufferevent.h"
|
#include "event2/bufferevent.h"
|
||||||
|
#include "event2/bufferevent_ssl.h"
|
||||||
#include "event2/util.h"
|
#include "event2/util.h"
|
||||||
|
#include "event2/listener.h"
|
||||||
#include "log-internal.h"
|
#include "log-internal.h"
|
||||||
#include "http-internal.h"
|
#include "http-internal.h"
|
||||||
#include "regress.h"
|
#include "regress.h"
|
||||||
@ -84,6 +86,7 @@ static char const BASIC_REQUEST_BODY[] = "This is funny";
|
|||||||
IMPL_HTTP_REQUEST_ERROR_CB(cancel, EVREQ_HTTP_REQUEST_CANCEL)
|
IMPL_HTTP_REQUEST_ERROR_CB(cancel, EVREQ_HTTP_REQUEST_CANCEL)
|
||||||
|
|
||||||
static void http_basic_cb(struct evhttp_request *req, void *arg);
|
static void http_basic_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_chunked_cb(struct evhttp_request *req, void *arg);
|
||||||
static void http_post_cb(struct evhttp_request *req, void *arg);
|
static void http_post_cb(struct evhttp_request *req, void *arg);
|
||||||
static void http_put_cb(struct evhttp_request *req, void *arg);
|
static void http_put_cb(struct evhttp_request *req, void *arg);
|
||||||
@ -94,11 +97,14 @@ static void http_badreq_cb(struct evhttp_request *req, void *arg);
|
|||||||
static void http_dispatcher_cb(struct evhttp_request *req, void *arg);
|
static void http_dispatcher_cb(struct evhttp_request *req, void *arg);
|
||||||
static void http_on_complete_cb(struct evhttp_request *req, void *arg);
|
static void http_on_complete_cb(struct evhttp_request *req, void *arg);
|
||||||
|
|
||||||
|
#define HTTP_BIND_IPV6 1
|
||||||
|
#define HTTP_BIND_SSL 2
|
||||||
static int
|
static int
|
||||||
http_bind(struct evhttp *myhttp, ev_uint16_t *pport, int ipv6)
|
http_bind(struct evhttp *myhttp, ev_uint16_t *pport, int mask)
|
||||||
{
|
{
|
||||||
int port;
|
int port;
|
||||||
struct evhttp_bound_socket *sock;
|
struct evhttp_bound_socket *sock;
|
||||||
|
int ipv6 = mask & HTTP_BIND_IPV6;
|
||||||
|
|
||||||
if (ipv6)
|
if (ipv6)
|
||||||
sock = evhttp_bind_socket_with_handle(myhttp, "::1", *pport);
|
sock = evhttp_bind_socket_with_handle(myhttp, "::1", *pport);
|
||||||
@ -120,19 +126,40 @@ http_bind(struct evhttp *myhttp, ev_uint16_t *pport, int ipv6)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef EVENT__HAVE_OPENSSL
|
||||||
|
static struct bufferevent *
|
||||||
|
https_bev(struct event_base *base, void *arg)
|
||||||
|
{
|
||||||
|
SSL *ssl = SSL_new(get_ssl_ctx());
|
||||||
|
|
||||||
|
SSL_use_certificate(ssl, ssl_getcert());
|
||||||
|
SSL_use_PrivateKey(ssl, ssl_getkey());
|
||||||
|
|
||||||
|
return bufferevent_openssl_socket_new(
|
||||||
|
base, -1, ssl, BUFFEREVENT_SSL_ACCEPTING,
|
||||||
|
BEV_OPT_CLOSE_ON_FREE);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
static struct evhttp *
|
static struct evhttp *
|
||||||
http_setup(ev_uint16_t *pport, struct event_base *base, int ipv6)
|
http_setup(ev_uint16_t *pport, struct event_base *base, int mask)
|
||||||
{
|
{
|
||||||
struct evhttp *myhttp;
|
struct evhttp *myhttp;
|
||||||
|
|
||||||
/* Try a few different ports */
|
/* Try a few different ports */
|
||||||
myhttp = evhttp_new(base);
|
myhttp = evhttp_new(base);
|
||||||
|
|
||||||
if (http_bind(myhttp, pport, ipv6) < 0)
|
if (http_bind(myhttp, pport, mask) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
#ifdef EVENT__HAVE_OPENSSL
|
||||||
|
if (mask & HTTP_BIND_SSL) {
|
||||||
|
init_ssl();
|
||||||
|
evhttp_set_bevcb(myhttp, https_bev, NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Register a callback for certain types of requests */
|
/* Register a callback for certain types of requests */
|
||||||
evhttp_set_cb(myhttp, "/test", http_basic_cb, base);
|
evhttp_set_cb(myhttp, "/test", http_basic_cb, base);
|
||||||
|
evhttp_set_cb(myhttp, "/large", http_large_cb, base);
|
||||||
evhttp_set_cb(myhttp, "/chunked", http_chunked_cb, base);
|
evhttp_set_cb(myhttp, "/chunked", http_chunked_cb, base);
|
||||||
evhttp_set_cb(myhttp, "/streamed", http_chunked_cb, base);
|
evhttp_set_cb(myhttp, "/streamed", http_chunked_cb, base);
|
||||||
evhttp_set_cb(myhttp, "/postit", http_post_cb, base);
|
evhttp_set_cb(myhttp, "/postit", http_post_cb, base);
|
||||||
@ -151,7 +178,7 @@ http_setup(ev_uint16_t *pport, struct event_base *base, int ipv6)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static evutil_socket_t
|
static evutil_socket_t
|
||||||
http_connect(const char *address, u_short port)
|
http_connect(const char *address, unsigned short port)
|
||||||
{
|
{
|
||||||
/* Stupid code for connecting */
|
/* Stupid code for connecting */
|
||||||
struct evutil_addrinfo ai, *aitop;
|
struct evutil_addrinfo ai, *aitop;
|
||||||
@ -276,6 +303,9 @@ http_writecb(struct bufferevent *bev, void *arg)
|
|||||||
static void
|
static void
|
||||||
http_errorcb(struct bufferevent *bev, short what, void *arg)
|
http_errorcb(struct bufferevent *bev, short what, void *arg)
|
||||||
{
|
{
|
||||||
|
/** For ssl */
|
||||||
|
if (what & BEV_EVENT_CONNECTED)
|
||||||
|
return;
|
||||||
test_ok = -2;
|
test_ok = -2;
|
||||||
event_base_loopexit(arg, NULL);
|
event_base_loopexit(arg, NULL);
|
||||||
}
|
}
|
||||||
@ -329,6 +359,19 @@ end:
|
|||||||
evbuffer_free(evb);
|
evbuffer_free(evb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
http_large_cb(struct evhttp_request *req, void *arg)
|
||||||
|
{
|
||||||
|
struct evbuffer *evb = evbuffer_new();
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 1<<20; ++i) {
|
||||||
|
evbuffer_add_printf(evb, BASIC_REQUEST_BODY);
|
||||||
|
}
|
||||||
|
evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb);
|
||||||
|
evbuffer_free(evb);
|
||||||
|
}
|
||||||
|
|
||||||
static char const* const CHUNKS[] = {
|
static char const* const CHUNKS[] = {
|
||||||
"This is funny",
|
"This is funny",
|
||||||
"but not hilarious.",
|
"but not hilarious.",
|
||||||
@ -394,8 +437,28 @@ http_complete_write(evutil_socket_t fd, short what, void *arg)
|
|||||||
bufferevent_write(bev, http_request, strlen(http_request));
|
bufferevent_write(bev, http_request, strlen(http_request));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct bufferevent *
|
||||||
|
create_bev(struct event_base *base, int fd, int ssl)
|
||||||
|
{
|
||||||
|
int flags = BEV_OPT_DEFER_CALLBACKS;
|
||||||
|
struct bufferevent *bev = NULL;
|
||||||
|
|
||||||
|
if (!ssl) {
|
||||||
|
bev = bufferevent_socket_new(base, fd, flags);
|
||||||
|
} else {
|
||||||
|
#ifdef EVENT__HAVE_OPENSSL
|
||||||
|
SSL *ssl = SSL_new(get_ssl_ctx());
|
||||||
|
bev = bufferevent_openssl_socket_new(
|
||||||
|
base, fd, ssl, BUFFEREVENT_SSL_CONNECTING, flags);
|
||||||
|
bufferevent_openssl_set_allow_dirty_shutdown(bev, 1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return bev;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
http_basic_test(void *arg)
|
http_basic_test_impl(void *arg, int ssl)
|
||||||
{
|
{
|
||||||
struct basic_test_data *data = arg;
|
struct basic_test_data *data = arg;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
@ -403,13 +466,14 @@ http_basic_test(void *arg)
|
|||||||
evutil_socket_t fd;
|
evutil_socket_t fd;
|
||||||
const char *http_request;
|
const char *http_request;
|
||||||
ev_uint16_t port = 0, port2 = 0;
|
ev_uint16_t port = 0, port2 = 0;
|
||||||
|
int server_flags = ssl ? HTTP_BIND_SSL : 0;
|
||||||
|
|
||||||
test_ok = 0;
|
test_ok = 0;
|
||||||
|
|
||||||
http = http_setup(&port, data->base, 0);
|
http = http_setup(&port, data->base, server_flags);
|
||||||
|
|
||||||
/* bind to a second socket */
|
/* bind to a second socket */
|
||||||
if (http_bind(http, &port2, 0) == -1) {
|
if (http_bind(http, &port2, server_flags) == -1) {
|
||||||
fprintf(stdout, "FAILED (bind)\n");
|
fprintf(stdout, "FAILED (bind)\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -417,7 +481,7 @@ http_basic_test(void *arg)
|
|||||||
fd = http_connect("127.0.0.1", port);
|
fd = http_connect("127.0.0.1", port);
|
||||||
|
|
||||||
/* Stupid thing to send a request */
|
/* Stupid thing to send a request */
|
||||||
bev = bufferevent_socket_new(data->base, fd, 0);
|
bev = create_bev(data->base, fd, ssl);
|
||||||
bufferevent_setcb(bev, http_readcb, http_writecb,
|
bufferevent_setcb(bev, http_readcb, http_writecb,
|
||||||
http_errorcb, data->base);
|
http_errorcb, data->base);
|
||||||
|
|
||||||
@ -443,7 +507,7 @@ http_basic_test(void *arg)
|
|||||||
fd = http_connect("127.0.0.1", port2);
|
fd = http_connect("127.0.0.1", port2);
|
||||||
|
|
||||||
/* Stupid thing to send a request */
|
/* Stupid thing to send a request */
|
||||||
bev = bufferevent_socket_new(data->base, fd, 0);
|
bev = create_bev(data->base, fd, ssl);
|
||||||
bufferevent_setcb(bev, http_readcb, http_writecb,
|
bufferevent_setcb(bev, http_readcb, http_writecb,
|
||||||
http_errorcb, data->base);
|
http_errorcb, data->base);
|
||||||
|
|
||||||
@ -466,7 +530,7 @@ http_basic_test(void *arg)
|
|||||||
fd = http_connect("127.0.0.1", port2);
|
fd = http_connect("127.0.0.1", port2);
|
||||||
|
|
||||||
/* Stupid thing to send a request */
|
/* Stupid thing to send a request */
|
||||||
bev = bufferevent_socket_new(data->base, fd, 0);
|
bev = create_bev(data->base, fd, ssl);
|
||||||
bufferevent_setcb(bev, http_readcb, http_writecb,
|
bufferevent_setcb(bev, http_readcb, http_writecb,
|
||||||
http_errorcb, data->base);
|
http_errorcb, data->base);
|
||||||
|
|
||||||
@ -487,6 +551,8 @@ http_basic_test(void *arg)
|
|||||||
if (bev)
|
if (bev)
|
||||||
bufferevent_free(bev);
|
bufferevent_free(bev);
|
||||||
}
|
}
|
||||||
|
static void http_basic_test(void *arg)
|
||||||
|
{ return http_basic_test_impl(arg, 0); }
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -956,6 +1022,7 @@ http_allowed_methods_test(void *arg)
|
|||||||
evutil_closesocket(fd3);
|
evutil_closesocket(fd3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void http_request_no_action_done(struct evhttp_request *, void *);
|
||||||
static void http_request_done(struct evhttp_request *, void *);
|
static void http_request_done(struct evhttp_request *, void *);
|
||||||
static void http_request_empty_done(struct evhttp_request *, void *);
|
static void http_request_empty_done(struct evhttp_request *, void *);
|
||||||
|
|
||||||
@ -1060,8 +1127,8 @@ http_persist_connection_test(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct regress_dns_server_table search_table[] = {
|
static struct regress_dns_server_table search_table[] = {
|
||||||
{ "localhost", "A", "127.0.0.1", 0 },
|
{ "localhost", "A", "127.0.0.1", 0, 0 },
|
||||||
{ NULL, NULL, NULL, 0 }
|
{ NULL, NULL, NULL, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1319,6 +1386,13 @@ http_cancel_test(void *arg)
|
|||||||
evhttp_free(http);
|
evhttp_free(http);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
http_request_no_action_done(struct evhttp_request *req, void *arg)
|
||||||
|
{
|
||||||
|
EVUTIL_ASSERT(exit_base);
|
||||||
|
event_base_loopexit(exit_base, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
http_request_done(struct evhttp_request *req, void *arg)
|
http_request_done(struct evhttp_request *req, void *arg)
|
||||||
{
|
{
|
||||||
@ -1583,6 +1657,11 @@ http_dispatcher_test_done(struct evhttp_request *req, void *arg)
|
|||||||
struct event_base *base = arg;
|
struct event_base *base = arg;
|
||||||
const char *what = "DISPATCHER_TEST";
|
const char *what = "DISPATCHER_TEST";
|
||||||
|
|
||||||
|
if (!req) {
|
||||||
|
fprintf(stderr, "FAILED\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if (evhttp_request_get_response_code(req) != HTTP_OK) {
|
if (evhttp_request_get_response_code(req) != HTTP_OK) {
|
||||||
fprintf(stderr, "FAILED\n");
|
fprintf(stderr, "FAILED\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -2750,6 +2829,10 @@ http_incomplete_readcb(struct bufferevent *bev, void *arg)
|
|||||||
static void
|
static void
|
||||||
http_incomplete_errorcb(struct bufferevent *bev, short what, void *arg)
|
http_incomplete_errorcb(struct bufferevent *bev, short what, void *arg)
|
||||||
{
|
{
|
||||||
|
/** For ssl */
|
||||||
|
if (what & BEV_EVENT_CONNECTED)
|
||||||
|
return;
|
||||||
|
|
||||||
if (what == (BEV_EVENT_READING|BEV_EVENT_EOF))
|
if (what == (BEV_EVENT_READING|BEV_EVENT_EOF))
|
||||||
test_ok++;
|
test_ok++;
|
||||||
else
|
else
|
||||||
@ -2773,7 +2856,7 @@ http_incomplete_writecb(struct bufferevent *bev, void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
http_incomplete_test_(struct basic_test_data *data, int use_timeout)
|
http_incomplete_test_(struct basic_test_data *data, int use_timeout, int ssl)
|
||||||
{
|
{
|
||||||
struct bufferevent *bev;
|
struct bufferevent *bev;
|
||||||
evutil_socket_t fd;
|
evutil_socket_t fd;
|
||||||
@ -2785,14 +2868,14 @@ http_incomplete_test_(struct basic_test_data *data, int use_timeout)
|
|||||||
|
|
||||||
test_ok = 0;
|
test_ok = 0;
|
||||||
|
|
||||||
http = http_setup(&port, data->base, 0);
|
http = http_setup(&port, data->base, ssl ? HTTP_BIND_SSL : 0);
|
||||||
evhttp_set_timeout(http, 1);
|
evhttp_set_timeout(http, 1);
|
||||||
|
|
||||||
fd = http_connect("127.0.0.1", port);
|
fd = http_connect("127.0.0.1", port);
|
||||||
tt_int_op(fd, >=, 0);
|
tt_int_op(fd, >=, 0);
|
||||||
|
|
||||||
/* Stupid thing to send a request */
|
/* Stupid thing to send a request */
|
||||||
bev = bufferevent_socket_new(data->base, fd, 0);
|
bev = create_bev(data->base, fd, ssl);
|
||||||
bufferevent_setcb(bev,
|
bufferevent_setcb(bev,
|
||||||
http_incomplete_readcb, http_incomplete_writecb,
|
http_incomplete_readcb, http_incomplete_writecb,
|
||||||
http_incomplete_errorcb, use_timeout ? NULL : &fd);
|
http_incomplete_errorcb, use_timeout ? NULL : &fd);
|
||||||
@ -2830,16 +2913,11 @@ http_incomplete_test_(struct basic_test_data *data, int use_timeout)
|
|||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
evutil_closesocket(fd);
|
evutil_closesocket(fd);
|
||||||
}
|
}
|
||||||
static void
|
static void http_incomplete_test(void *arg)
|
||||||
http_incomplete_test(void *arg)
|
{ http_incomplete_test_(arg, 0, 0); }
|
||||||
{
|
static void http_incomplete_timeout_test(void *arg)
|
||||||
http_incomplete_test_(arg, 0);
|
{ http_incomplete_test_(arg, 1, 0); }
|
||||||
}
|
|
||||||
static void
|
|
||||||
http_incomplete_timeout_test(void *arg)
|
|
||||||
{
|
|
||||||
http_incomplete_test_(arg, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* the server is going to reply with chunked data.
|
* the server is going to reply with chunked data.
|
||||||
@ -2856,6 +2934,10 @@ http_chunked_errorcb(struct bufferevent *bev, short what, void *arg)
|
|||||||
{
|
{
|
||||||
struct evhttp_request *req = NULL;
|
struct evhttp_request *req = NULL;
|
||||||
|
|
||||||
|
/** SSL */
|
||||||
|
if (what & BEV_EVENT_CONNECTED)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!test_ok)
|
if (!test_ok)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -2990,7 +3072,7 @@ http_chunked_request_done(struct evhttp_request *req, void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
http_chunk_out_test(void *arg)
|
http_chunk_out_test_impl(void *arg, int ssl)
|
||||||
{
|
{
|
||||||
struct basic_test_data *data = arg;
|
struct basic_test_data *data = arg;
|
||||||
struct bufferevent *bev;
|
struct bufferevent *bev;
|
||||||
@ -3005,12 +3087,12 @@ http_chunk_out_test(void *arg)
|
|||||||
exit_base = data->base;
|
exit_base = data->base;
|
||||||
test_ok = 0;
|
test_ok = 0;
|
||||||
|
|
||||||
http = http_setup(&port, data->base, 0);
|
http = http_setup(&port, data->base, ssl ? HTTP_BIND_SSL : 0);
|
||||||
|
|
||||||
fd = http_connect("127.0.0.1", port);
|
fd = http_connect("127.0.0.1", port);
|
||||||
|
|
||||||
/* Stupid thing to send a request */
|
/* Stupid thing to send a request */
|
||||||
bev = bufferevent_socket_new(data->base, fd, 0);
|
bev = create_bev(data->base, fd, ssl);
|
||||||
bufferevent_setcb(bev,
|
bufferevent_setcb(bev,
|
||||||
http_chunked_readcb, http_chunked_writecb,
|
http_chunked_readcb, http_chunked_writecb,
|
||||||
http_chunked_errorcb, data->base);
|
http_chunked_errorcb, data->base);
|
||||||
@ -3037,7 +3119,9 @@ http_chunk_out_test(void *arg)
|
|||||||
tt_int_op(test_ok, ==, 2);
|
tt_int_op(test_ok, ==, 2);
|
||||||
|
|
||||||
/* now try again with the regular connection object */
|
/* now try again with the regular connection object */
|
||||||
evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
|
bev = create_bev(data->base, -1, ssl);
|
||||||
|
evcon = evhttp_connection_base_bufferevent_new(
|
||||||
|
data->base, NULL, bev, "127.0.0.1", port);
|
||||||
tt_assert(evcon);
|
tt_assert(evcon);
|
||||||
|
|
||||||
/* make two requests to check the keepalive behavior */
|
/* make two requests to check the keepalive behavior */
|
||||||
@ -3065,21 +3149,26 @@ http_chunk_out_test(void *arg)
|
|||||||
if (http)
|
if (http)
|
||||||
evhttp_free(http);
|
evhttp_free(http);
|
||||||
}
|
}
|
||||||
|
static void http_chunk_out_test(void *arg)
|
||||||
|
{ return http_chunk_out_test_impl(arg, 0); }
|
||||||
|
|
||||||
static void
|
static void
|
||||||
http_stream_out_test(void *arg)
|
http_stream_out_test_impl(void *arg, int ssl)
|
||||||
{
|
{
|
||||||
struct basic_test_data *data = arg;
|
struct basic_test_data *data = arg;
|
||||||
ev_uint16_t port = 0;
|
ev_uint16_t port = 0;
|
||||||
struct evhttp_connection *evcon = NULL;
|
struct evhttp_connection *evcon = NULL;
|
||||||
struct evhttp_request *req = NULL;
|
struct evhttp_request *req = NULL;
|
||||||
|
struct bufferevent *bev;
|
||||||
|
|
||||||
test_ok = 0;
|
test_ok = 0;
|
||||||
exit_base = data->base;
|
exit_base = data->base;
|
||||||
|
|
||||||
http = http_setup(&port, data->base, 0);
|
http = http_setup(&port, data->base, ssl ? HTTP_BIND_SSL : 0);
|
||||||
|
|
||||||
evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
|
bev = create_bev(data->base, -1, ssl);
|
||||||
|
evcon = evhttp_connection_base_bufferevent_new(
|
||||||
|
data->base, NULL, bev, "127.0.0.1", port);
|
||||||
tt_assert(evcon);
|
tt_assert(evcon);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3107,6 +3196,8 @@ http_stream_out_test(void *arg)
|
|||||||
if (http)
|
if (http)
|
||||||
evhttp_free(http);
|
evhttp_free(http);
|
||||||
}
|
}
|
||||||
|
static void http_stream_out_test(void *arg)
|
||||||
|
{ return http_stream_out_test_impl(arg, 0); }
|
||||||
|
|
||||||
static void
|
static void
|
||||||
http_stream_in_chunk(struct evhttp_request *req, void *arg)
|
http_stream_in_chunk(struct evhttp_request *req, void *arg)
|
||||||
@ -3241,65 +3332,70 @@ http_stream_in_cancel_test(void *arg)
|
|||||||
static void
|
static void
|
||||||
http_connection_fail_done(struct evhttp_request *req, void *arg)
|
http_connection_fail_done(struct evhttp_request *req, void *arg)
|
||||||
{
|
{
|
||||||
struct evhttp_connection *evcon = arg;
|
struct evhttp_connection *evcon = arg;
|
||||||
struct event_base *base = evhttp_connection_get_base(evcon);
|
struct event_base *base = evhttp_connection_get_base(evcon);
|
||||||
|
|
||||||
/* An ENETUNREACH error results in an unrecoverable
|
/* An ENETUNREACH error results in an unrecoverable
|
||||||
* evhttp_connection error (see evhttp_connection_fail_()). The
|
* evhttp_connection error (see evhttp_connection_fail_()). The
|
||||||
* connection will be reset, and the user will be notified with a NULL
|
* connection will be reset, and the user will be notified with a NULL
|
||||||
* req parameter. */
|
* req parameter. */
|
||||||
tt_assert(!req);
|
tt_assert(!req);
|
||||||
|
|
||||||
evhttp_connection_free(evcon);
|
evhttp_connection_free(evcon);
|
||||||
|
|
||||||
test_ok = 1;
|
test_ok = 1;
|
||||||
|
|
||||||
end:
|
end:
|
||||||
event_base_loopexit(base, NULL);
|
event_base_loopexit(base, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test unrecoverable evhttp_connection errors by generating an ENETUNREACH
|
/* Test unrecoverable evhttp_connection errors by generating an ENETUNREACH
|
||||||
* error on connection. */
|
* error on connection. */
|
||||||
static void
|
static void
|
||||||
http_connection_fail_test(void *arg)
|
http_connection_fail_test_impl(void *arg, int ssl)
|
||||||
{
|
{
|
||||||
struct basic_test_data *data = arg;
|
struct basic_test_data *data = arg;
|
||||||
ev_uint16_t port = 0;
|
ev_uint16_t port = 0;
|
||||||
struct evhttp_connection *evcon = NULL;
|
struct evhttp_connection *evcon = NULL;
|
||||||
struct evhttp_request *req = NULL;
|
struct evhttp_request *req = NULL;
|
||||||
|
struct bufferevent *bev;
|
||||||
|
|
||||||
exit_base = data->base;
|
exit_base = data->base;
|
||||||
test_ok = 0;
|
test_ok = 0;
|
||||||
|
|
||||||
/* auto detect a port */
|
/* auto detect a port */
|
||||||
http = http_setup(&port, data->base, 0);
|
http = http_setup(&port, data->base, ssl ? HTTP_BIND_SSL : 0);
|
||||||
evhttp_free(http);
|
evhttp_free(http);
|
||||||
http = NULL;
|
http = NULL;
|
||||||
|
|
||||||
/* Pick an unroutable address. This administratively scoped multicast
|
bev = create_bev(data->base, -1, ssl);
|
||||||
* address should do when working with TCP. */
|
/* Pick an unroutable address. This administratively scoped multicast
|
||||||
evcon = evhttp_connection_base_new(data->base, NULL, "239.10.20.30", 80);
|
* address should do when working with TCP. */
|
||||||
tt_assert(evcon);
|
evcon = evhttp_connection_base_bufferevent_new(
|
||||||
|
data->base, NULL, bev, "239.10.20.30", 80);
|
||||||
|
tt_assert(evcon);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* At this point, we want to schedule an HTTP GET request
|
* At this point, we want to schedule an HTTP GET request
|
||||||
* server using our make request method.
|
* server using our make request method.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
req = evhttp_request_new(http_connection_fail_done, evcon);
|
req = evhttp_request_new(http_connection_fail_done, evcon);
|
||||||
tt_assert(req);
|
tt_assert(req);
|
||||||
|
|
||||||
if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/") == -1) {
|
if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/") == -1) {
|
||||||
tt_abort_msg("Couldn't make request");
|
tt_abort_msg("Couldn't make request");
|
||||||
}
|
}
|
||||||
|
|
||||||
event_base_dispatch(data->base);
|
event_base_dispatch(data->base);
|
||||||
|
|
||||||
tt_int_op(test_ok, ==, 1);
|
tt_int_op(test_ok, ==, 1);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
static void http_connection_fail_test(void *arg)
|
||||||
|
{ return http_connection_fail_test_impl(arg, 0); }
|
||||||
|
|
||||||
static void
|
static void
|
||||||
http_connection_retry_done(struct evhttp_request *req, void *arg)
|
http_connection_retry_done(struct evhttp_request *req, void *arg)
|
||||||
@ -3317,33 +3413,81 @@ http_connection_retry_done(struct evhttp_request *req, void *arg)
|
|||||||
event_base_loopexit(arg,NULL);
|
event_base_loopexit(arg,NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct http_server
|
||||||
|
{
|
||||||
|
ev_uint16_t port;
|
||||||
|
int ssl;
|
||||||
|
};
|
||||||
static struct event_base *http_make_web_server_base=NULL;
|
static struct event_base *http_make_web_server_base=NULL;
|
||||||
static void
|
static void
|
||||||
http_make_web_server(evutil_socket_t fd, short what, void *arg)
|
http_make_web_server(evutil_socket_t fd, short what, void *arg)
|
||||||
{
|
{
|
||||||
ev_uint16_t port = *(ev_uint16_t*)arg;
|
struct http_server *hs = (struct http_server *)arg;
|
||||||
http = http_setup(&port, http_make_web_server_base, 0);
|
http = http_setup(&hs->port, http_make_web_server_base, hs->ssl ? HTTP_BIND_SSL : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
http_connection_retry_test(void *arg)
|
http_simple_test_impl(void *arg, int ssl, int dirty)
|
||||||
|
{
|
||||||
|
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, };
|
||||||
|
|
||||||
|
exit_base = data->base;
|
||||||
|
test_ok = 0;
|
||||||
|
|
||||||
|
http = http_setup(&hs.port, data->base, ssl ? HTTP_BIND_SSL : 0);
|
||||||
|
|
||||||
|
bev = create_bev(data->base, -1, ssl);
|
||||||
|
evcon = evhttp_connection_base_bufferevent_new(
|
||||||
|
data->base, NULL, bev, "127.0.0.1", hs.port);
|
||||||
|
tt_assert(evcon);
|
||||||
|
evhttp_connection_set_local_address(evcon, "127.0.0.1");
|
||||||
|
|
||||||
|
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) {
|
||||||
|
tt_abort_msg("Couldn't make request");
|
||||||
|
}
|
||||||
|
|
||||||
|
event_base_dispatch(data->base);
|
||||||
|
tt_int_op(test_ok, ==, 1);
|
||||||
|
|
||||||
|
end:
|
||||||
|
if (evcon)
|
||||||
|
evhttp_connection_free(evcon);
|
||||||
|
if (http)
|
||||||
|
evhttp_free(http);
|
||||||
|
}
|
||||||
|
static void http_simple_test(void *arg)
|
||||||
|
{ return http_simple_test_impl(arg, 0, 0); }
|
||||||
|
|
||||||
|
static void
|
||||||
|
http_connection_retry_test_basic(void *arg, const char *addr, struct evdns_base *dns_base, int ssl)
|
||||||
{
|
{
|
||||||
struct basic_test_data *data = arg;
|
struct basic_test_data *data = arg;
|
||||||
ev_uint16_t port = 0;
|
|
||||||
struct evhttp_connection *evcon = NULL;
|
struct evhttp_connection *evcon = NULL;
|
||||||
struct evhttp_request *req = NULL;
|
struct evhttp_request *req = NULL;
|
||||||
struct timeval tv, tv_start, tv_end;
|
struct timeval tv, tv_start, tv_end;
|
||||||
|
struct bufferevent *bev;
|
||||||
|
struct http_server hs = { .port = 0, .ssl = ssl, };
|
||||||
|
|
||||||
exit_base = data->base;
|
exit_base = data->base;
|
||||||
test_ok = 0;
|
test_ok = 0;
|
||||||
|
|
||||||
/* auto detect a port */
|
/* auto detect a port */
|
||||||
http = http_setup(&port, data->base, 0);
|
http = http_setup(&hs.port, data->base, ssl ? HTTP_BIND_SSL : 0);
|
||||||
evhttp_free(http);
|
evhttp_free(http);
|
||||||
http = NULL;
|
http = NULL;
|
||||||
|
|
||||||
evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
|
bev = create_bev(data->base, -1, ssl);
|
||||||
|
evcon = evhttp_connection_base_bufferevent_new(data->base, dns_base, bev, addr, hs.port);
|
||||||
tt_assert(evcon);
|
tt_assert(evcon);
|
||||||
|
if (dns_base)
|
||||||
|
tt_assert(!evhttp_connection_set_flags(evcon, EVHTTP_CON_REUSE_CONNECTED_ADDR));
|
||||||
|
|
||||||
evhttp_connection_set_timeout(evcon, 1);
|
evhttp_connection_set_timeout(evcon, 1);
|
||||||
/* also bind to local host */
|
/* also bind to local host */
|
||||||
@ -3377,6 +3521,9 @@ http_connection_retry_test(void *arg)
|
|||||||
* now test the same but with retries
|
* now test the same but with retries
|
||||||
*/
|
*/
|
||||||
test_ok = 0;
|
test_ok = 0;
|
||||||
|
/** Shutdown dns server, to test conn_address reusing */
|
||||||
|
if (dns_base)
|
||||||
|
regress_clean_dnsserver();
|
||||||
|
|
||||||
{
|
{
|
||||||
const struct timeval tv_timeout = { 0, 500000 };
|
const struct timeval tv_timeout = { 0, 500000 };
|
||||||
@ -3432,7 +3579,7 @@ http_connection_retry_test(void *arg)
|
|||||||
evutil_timerclear(&tv);
|
evutil_timerclear(&tv);
|
||||||
tv.tv_usec = 200000;
|
tv.tv_usec = 200000;
|
||||||
http_make_web_server_base = data->base;
|
http_make_web_server_base = data->base;
|
||||||
event_base_once(data->base, -1, EV_TIMEOUT, http_make_web_server, &port, &tv);
|
event_base_once(data->base, -1, EV_TIMEOUT, http_make_web_server, &hs, &tv);
|
||||||
|
|
||||||
evutil_gettimeofday(&tv_start, NULL);
|
evutil_gettimeofday(&tv_start, NULL);
|
||||||
event_base_dispatch(data->base);
|
event_base_dispatch(data->base);
|
||||||
@ -3449,6 +3596,42 @@ http_connection_retry_test(void *arg)
|
|||||||
evhttp_free(http);
|
evhttp_free(http);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
http_connection_retry_conn_address_test_impl(void *arg, int ssl)
|
||||||
|
{
|
||||||
|
struct basic_test_data *data = arg;
|
||||||
|
ev_uint16_t portnum = 0;
|
||||||
|
struct evdns_base *dns_base = NULL;
|
||||||
|
char address[64];
|
||||||
|
|
||||||
|
tt_assert(regress_dnsserver(data->base, &portnum, search_table));
|
||||||
|
dns_base = evdns_base_new(data->base, 0/* init name servers */);
|
||||||
|
tt_assert(dns_base);
|
||||||
|
|
||||||
|
/* Add ourself as the only nameserver, and make sure we really are
|
||||||
|
* the only nameserver. */
|
||||||
|
evutil_snprintf(address, sizeof(address), "127.0.0.1:%d", portnum);
|
||||||
|
evdns_base_nameserver_ip_add(dns_base, address);
|
||||||
|
|
||||||
|
http_connection_retry_test_basic(arg, "localhost", dns_base, ssl);
|
||||||
|
|
||||||
|
end:
|
||||||
|
if (dns_base)
|
||||||
|
evdns_base_free(dns_base, 0);
|
||||||
|
/** 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); }
|
||||||
|
|
||||||
|
static void
|
||||||
|
http_connection_retry_test_impl(void *arg, int ssl)
|
||||||
|
{
|
||||||
|
return 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); }
|
||||||
|
|
||||||
static void
|
static void
|
||||||
http_primitives(void *ptr)
|
http_primitives(void *ptr)
|
||||||
{
|
{
|
||||||
@ -3688,6 +3871,7 @@ struct terminate_state {
|
|||||||
struct bufferevent *bev;
|
struct bufferevent *bev;
|
||||||
evutil_socket_t fd;
|
evutil_socket_t fd;
|
||||||
int gotclosecb: 1;
|
int gotclosecb: 1;
|
||||||
|
int oneshot: 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -3695,7 +3879,10 @@ terminate_chunked_trickle_cb(evutil_socket_t fd, short events, void *arg)
|
|||||||
{
|
{
|
||||||
struct terminate_state *state = arg;
|
struct terminate_state *state = arg;
|
||||||
struct evbuffer *evb;
|
struct evbuffer *evb;
|
||||||
struct timeval tv;
|
|
||||||
|
if (!state->req) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (evhttp_request_get_connection(state->req) == NULL) {
|
if (evhttp_request_get_connection(state->req) == NULL) {
|
||||||
test_ok = 1;
|
test_ok = 1;
|
||||||
@ -3709,11 +3896,14 @@ terminate_chunked_trickle_cb(evutil_socket_t fd, short events, void *arg)
|
|||||||
evhttp_send_reply_chunk(state->req, evb);
|
evhttp_send_reply_chunk(state->req, evb);
|
||||||
evbuffer_free(evb);
|
evbuffer_free(evb);
|
||||||
|
|
||||||
tv.tv_sec = 0;
|
if (!state->oneshot) {
|
||||||
tv.tv_usec = 3000;
|
struct timeval tv;
|
||||||
EVUTIL_ASSERT(state);
|
tv.tv_sec = 0;
|
||||||
EVUTIL_ASSERT(state->base);
|
tv.tv_usec = 3000;
|
||||||
event_base_once(state->base, -1, EV_TIMEOUT, terminate_chunked_trickle_cb, arg, &tv);
|
EVUTIL_ASSERT(state);
|
||||||
|
EVUTIL_ASSERT(state->base);
|
||||||
|
event_base_once(state->base, -1, EV_TIMEOUT, terminate_chunked_trickle_cb, arg, &tv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -3721,6 +3911,13 @@ terminate_chunked_close_cb(struct evhttp_connection *evcon, void *arg)
|
|||||||
{
|
{
|
||||||
struct terminate_state *state = arg;
|
struct terminate_state *state = arg;
|
||||||
state->gotclosecb = 1;
|
state->gotclosecb = 1;
|
||||||
|
|
||||||
|
/** TODO: though we can do this unconditionally */
|
||||||
|
if (state->oneshot) {
|
||||||
|
evhttp_request_free(state->req);
|
||||||
|
state->req = NULL;
|
||||||
|
event_base_loopexit(state->base,NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -3760,7 +3957,7 @@ terminate_readcb(struct bufferevent *bev, void *arg)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
http_terminate_chunked_test(void *arg)
|
http_terminate_chunked_test_impl(void *arg, int oneshot)
|
||||||
{
|
{
|
||||||
struct basic_test_data *data = arg;
|
struct basic_test_data *data = arg;
|
||||||
struct bufferevent *bev = NULL;
|
struct bufferevent *bev = NULL;
|
||||||
@ -3789,6 +3986,7 @@ http_terminate_chunked_test(void *arg)
|
|||||||
terminate_state.fd = fd;
|
terminate_state.fd = fd;
|
||||||
terminate_state.bev = bev;
|
terminate_state.bev = bev;
|
||||||
terminate_state.gotclosecb = 0;
|
terminate_state.gotclosecb = 0;
|
||||||
|
terminate_state.oneshot = oneshot;
|
||||||
|
|
||||||
/* first half of the http request */
|
/* first half of the http request */
|
||||||
http_request =
|
http_request =
|
||||||
@ -3812,10 +4010,20 @@ http_terminate_chunked_test(void *arg)
|
|||||||
if (http)
|
if (http)
|
||||||
evhttp_free(http);
|
evhttp_free(http);
|
||||||
}
|
}
|
||||||
|
static void
|
||||||
|
http_terminate_chunked_test(void *arg)
|
||||||
|
{
|
||||||
|
http_terminate_chunked_test_impl(arg, 0);
|
||||||
|
}
|
||||||
|
static void
|
||||||
|
http_terminate_chunked_oneshot_test(void *arg)
|
||||||
|
{
|
||||||
|
http_terminate_chunked_test_impl(arg, 1);
|
||||||
|
}
|
||||||
|
|
||||||
static struct regress_dns_server_table ipv6_search_table[] = {
|
static struct regress_dns_server_table ipv6_search_table[] = {
|
||||||
{ "localhost", "AAAA", "::1", 0 },
|
{ "localhost", "AAAA", "::1", 0, 0 },
|
||||||
{ NULL, NULL, NULL, 0 }
|
{ NULL, NULL, NULL, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -3929,12 +4137,126 @@ http_set_family_ipv6_test(void *arg)
|
|||||||
http_ipv6_for_domain_test_impl(arg, AF_INET6);
|
http_ipv6_for_domain_test_impl(arg, AF_INET6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
http_write_during_read(evutil_socket_t fd, short what, void *arg)
|
||||||
|
{
|
||||||
|
struct bufferevent *bev = arg;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
bufferevent_write(bev, "foobar", strlen("foobar"));
|
||||||
|
|
||||||
|
evutil_timerclear(&tv);
|
||||||
|
tv.tv_sec = 1;
|
||||||
|
event_base_loopexit(exit_base, &tv);
|
||||||
|
}
|
||||||
|
static void
|
||||||
|
http_write_during_read_test_impl(void *arg, int ssl)
|
||||||
|
{
|
||||||
|
struct basic_test_data *data = arg;
|
||||||
|
ev_uint16_t port = 0;
|
||||||
|
struct bufferevent *bev = NULL;
|
||||||
|
struct timeval tv;
|
||||||
|
int fd;
|
||||||
|
const char *http_request;
|
||||||
|
|
||||||
|
test_ok = 0;
|
||||||
|
exit_base = data->base;
|
||||||
|
|
||||||
|
http = http_setup(&port, data->base, ssl ? HTTP_BIND_SSL : 0);
|
||||||
|
|
||||||
|
fd = http_connect("127.0.0.1", port);
|
||||||
|
bev = create_bev(data->base, fd, 0);
|
||||||
|
bufferevent_setcb(bev, NULL, NULL, NULL, data->base);
|
||||||
|
bufferevent_disable(bev, EV_READ);
|
||||||
|
|
||||||
|
http_request =
|
||||||
|
"GET /large HTTP/1.1\r\n"
|
||||||
|
"Host: somehost\r\n"
|
||||||
|
"\r\n";
|
||||||
|
|
||||||
|
bufferevent_write(bev, http_request, strlen(http_request));
|
||||||
|
evutil_timerclear(&tv);
|
||||||
|
tv.tv_usec = 10000;
|
||||||
|
event_base_once(data->base, -1, EV_TIMEOUT, http_write_during_read, bev, &tv);
|
||||||
|
|
||||||
|
event_base_dispatch(data->base);
|
||||||
|
|
||||||
|
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); }
|
||||||
|
|
||||||
|
static void
|
||||||
|
http_request_own_test(void *arg)
|
||||||
|
{
|
||||||
|
struct basic_test_data *data = arg;
|
||||||
|
ev_uint16_t port = 0;
|
||||||
|
struct evhttp_connection *evcon = NULL;
|
||||||
|
struct evhttp_request *req = NULL;
|
||||||
|
|
||||||
|
test_ok = 0;
|
||||||
|
exit_base = data->base;
|
||||||
|
|
||||||
|
http = http_setup(&port, data->base, 0);
|
||||||
|
evhttp_free(http);
|
||||||
|
|
||||||
|
evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
|
||||||
|
tt_assert(evcon);
|
||||||
|
|
||||||
|
req = evhttp_request_new(http_request_no_action_done, NULL);
|
||||||
|
|
||||||
|
if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) {
|
||||||
|
tt_abort_msg("Couldn't make request");
|
||||||
|
}
|
||||||
|
evhttp_request_own(req);
|
||||||
|
|
||||||
|
event_base_dispatch(data->base);
|
||||||
|
|
||||||
|
end:
|
||||||
|
if (evcon)
|
||||||
|
evhttp_connection_free(evcon);
|
||||||
|
if (req)
|
||||||
|
evhttp_request_free(req);
|
||||||
|
|
||||||
|
test_ok = 1;
|
||||||
|
}
|
||||||
|
|
||||||
#define HTTP_LEGACY(name) \
|
#define HTTP_LEGACY(name) \
|
||||||
{ #name, run_legacy_test_fn, TT_ISOLATED|TT_LEGACY, &legacy_setup, \
|
{ #name, run_legacy_test_fn, TT_ISOLATED|TT_LEGACY, &legacy_setup, \
|
||||||
http_##name##_test }
|
http_##name##_test }
|
||||||
|
|
||||||
#define HTTP(name) \
|
#define HTTP(name) \
|
||||||
{ #name, http_##name##_test, TT_ISOLATED, &basic_setup, NULL }
|
{ #name, http_##name##_test, TT_ISOLATED, &basic_setup, NULL }
|
||||||
|
#define HTTPS(name) \
|
||||||
|
{ "https_" #name, https_##name##_test, TT_ISOLATED, &basic_setup, NULL }
|
||||||
|
|
||||||
|
#ifdef EVENT__HAVE_OPENSSL
|
||||||
|
static void https_basic_test(void *arg)
|
||||||
|
{ return http_basic_test_impl(arg, 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); }
|
||||||
|
static void https_simple_dirty_test(void *arg)
|
||||||
|
{ return http_simple_test_impl(arg, 1, 1); }
|
||||||
|
static void https_connection_retry_conn_address_test(void *arg)
|
||||||
|
{ return 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); }
|
||||||
|
static void https_chunk_out_test(void *arg)
|
||||||
|
{ return http_chunk_out_test_impl(arg, 1); }
|
||||||
|
static void https_stream_out_test(void *arg)
|
||||||
|
{ return http_stream_out_test_impl(arg, 1); }
|
||||||
|
static void https_connection_fail_test(void *arg)
|
||||||
|
{ return 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); }
|
||||||
|
#endif
|
||||||
|
|
||||||
struct testcase_t http_testcases[] = {
|
struct testcase_t http_testcases[] = {
|
||||||
{ "primitives", http_primitives, 0, NULL, NULL },
|
{ "primitives", http_primitives, 0, NULL, NULL },
|
||||||
@ -3945,6 +4267,7 @@ struct testcase_t http_testcases[] = {
|
|||||||
{ "parse_uri_nc", http_parse_uri_test, 0, &basic_setup, (void*)"nc" },
|
{ "parse_uri_nc", http_parse_uri_test, 0, &basic_setup, (void*)"nc" },
|
||||||
{ "uriencode", http_uriencode_test, 0, NULL, NULL },
|
{ "uriencode", http_uriencode_test, 0, NULL, NULL },
|
||||||
HTTP(basic),
|
HTTP(basic),
|
||||||
|
HTTP(simple),
|
||||||
HTTP(cancel),
|
HTTP(cancel),
|
||||||
HTTP(virtual_host),
|
HTTP(virtual_host),
|
||||||
HTTP(post),
|
HTTP(post),
|
||||||
@ -3962,6 +4285,7 @@ struct testcase_t http_testcases[] = {
|
|||||||
HTTP(incomplete),
|
HTTP(incomplete),
|
||||||
HTTP(incomplete_timeout),
|
HTTP(incomplete_timeout),
|
||||||
HTTP(terminate_chunked),
|
HTTP(terminate_chunked),
|
||||||
|
HTTP(terminate_chunked_oneshot),
|
||||||
HTTP(on_complete),
|
HTTP(on_complete),
|
||||||
|
|
||||||
HTTP(highport),
|
HTTP(highport),
|
||||||
@ -3976,6 +4300,8 @@ struct testcase_t http_testcases[] = {
|
|||||||
|
|
||||||
HTTP(connection_fail),
|
HTTP(connection_fail),
|
||||||
{ "connection_retry", http_connection_retry_test, TT_ISOLATED|TT_OFF_BY_DEFAULT, &basic_setup, NULL },
|
{ "connection_retry", http_connection_retry_test, TT_ISOLATED|TT_OFF_BY_DEFAULT, &basic_setup, NULL },
|
||||||
|
{ "connection_retry_conn_address", http_connection_retry_conn_address_test,
|
||||||
|
TT_ISOLATED|TT_OFF_BY_DEFAULT, &basic_setup, NULL },
|
||||||
|
|
||||||
HTTP(data_length_constraints),
|
HTTP(data_length_constraints),
|
||||||
|
|
||||||
@ -3986,6 +4312,24 @@ struct testcase_t http_testcases[] = {
|
|||||||
HTTP(set_family_ipv4),
|
HTTP(set_family_ipv4),
|
||||||
HTTP(set_family_ipv6),
|
HTTP(set_family_ipv6),
|
||||||
|
|
||||||
|
HTTP(write_during_read),
|
||||||
|
HTTP(request_own),
|
||||||
|
|
||||||
|
#ifdef EVENT__HAVE_OPENSSL
|
||||||
|
HTTPS(basic),
|
||||||
|
HTTPS(simple),
|
||||||
|
HTTPS(simple_dirty),
|
||||||
|
HTTPS(incomplete),
|
||||||
|
HTTPS(incomplete_timeout),
|
||||||
|
{ "https_connection_retry", https_connection_retry_test, TT_ISOLATED|TT_OFF_BY_DEFAULT, &basic_setup, NULL },
|
||||||
|
{ "https_connection_retry_conn_address", https_connection_retry_conn_address_test,
|
||||||
|
TT_ISOLATED|TT_OFF_BY_DEFAULT, &basic_setup, NULL },
|
||||||
|
HTTPS(chunk_out),
|
||||||
|
HTTPS(stream_out),
|
||||||
|
HTTPS(connection_fail),
|
||||||
|
HTTPS(write_during_read),
|
||||||
|
#endif
|
||||||
|
|
||||||
END_OF_TESTCASES
|
END_OF_TESTCASES
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -407,6 +407,7 @@ const char *finetimetests[] = {
|
|||||||
"+util/monotonic_res_fallback",
|
"+util/monotonic_res_fallback",
|
||||||
"+thread/deferred_cb_skew",
|
"+thread/deferred_cb_skew",
|
||||||
"+http/connection_retry",
|
"+http/connection_retry",
|
||||||
|
"+http/https_connection_retry",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
struct testlist_alias_t testaliases[] = {
|
struct testlist_alias_t testaliases[] = {
|
||||||
@ -437,6 +438,7 @@ main(int argc, const char **argv)
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
tinytest_skip(testgroups, "http/connection_retry");
|
tinytest_skip(testgroups, "http/connection_retry");
|
||||||
|
tinytest_skip(testgroups, "http/https_connection_retry");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef EVENT__DISABLE_THREAD_SUPPORT
|
#ifndef EVENT__DISABLE_THREAD_SUPPORT
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#include "event2/util.h"
|
#include "event2/util.h"
|
||||||
#include "event2/event.h"
|
#include "event2/event.h"
|
||||||
#include "event2/bufferevent_ssl.h"
|
#include "event2/bufferevent_ssl.h"
|
||||||
|
#include "event2/bufferevent_struct.h"
|
||||||
#include "event2/buffer.h"
|
#include "event2/buffer.h"
|
||||||
#include "event2/listener.h"
|
#include "event2/listener.h"
|
||||||
|
|
||||||
@ -50,12 +51,12 @@
|
|||||||
#include "tinytest.h"
|
#include "tinytest.h"
|
||||||
#include "tinytest_macros.h"
|
#include "tinytest_macros.h"
|
||||||
|
|
||||||
#include <openssl/ssl.h>
|
|
||||||
#include <openssl/bio.h>
|
#include <openssl/bio.h>
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
#include <openssl/pem.h>
|
#include <openssl/pem.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
/* A short pre-generated key, to save the cost of doing an RSA key generation
|
/* A short pre-generated key, to save the cost of doing an RSA key generation
|
||||||
* step during the unit tests. It's only 512 bits long, and it is published
|
* step during the unit tests. It's only 512 bits long, and it is published
|
||||||
@ -72,8 +73,8 @@ static const char KEY[] =
|
|||||||
"U6GFEQTZ3IfuiVabG5pummdC4DNbcdI+WKrSFNmQ\n"
|
"U6GFEQTZ3IfuiVabG5pummdC4DNbcdI+WKrSFNmQ\n"
|
||||||
"-----END RSA PRIVATE KEY-----\n";
|
"-----END RSA PRIVATE KEY-----\n";
|
||||||
|
|
||||||
static EVP_PKEY *
|
EVP_PKEY *
|
||||||
getkey(void)
|
ssl_getkey(void)
|
||||||
{
|
{
|
||||||
EVP_PKEY *key;
|
EVP_PKEY *key;
|
||||||
BIO *bio;
|
BIO *bio;
|
||||||
@ -91,15 +92,15 @@ end:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static X509 *
|
X509 *
|
||||||
getcert(void)
|
ssl_getcert(void)
|
||||||
{
|
{
|
||||||
/* Dummy code to make a quick-and-dirty valid certificate with
|
/* Dummy code to make a quick-and-dirty valid certificate with
|
||||||
OpenSSL. Don't copy this code into your own program! It does a
|
OpenSSL. Don't copy this code into your own program! It does a
|
||||||
number of things in a stupid and insecure way. */
|
number of things in a stupid and insecure way. */
|
||||||
X509 *x509 = NULL;
|
X509 *x509 = NULL;
|
||||||
X509_NAME *name = NULL;
|
X509_NAME *name = NULL;
|
||||||
EVP_PKEY *key = getkey();
|
EVP_PKEY *key = ssl_getkey();
|
||||||
int nid;
|
int nid;
|
||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
|
|
||||||
@ -137,7 +138,7 @@ end:
|
|||||||
static int disable_tls_11_and_12 = 0;
|
static int disable_tls_11_and_12 = 0;
|
||||||
static SSL_CTX *the_ssl_ctx = NULL;
|
static SSL_CTX *the_ssl_ctx = NULL;
|
||||||
|
|
||||||
static SSL_CTX *
|
SSL_CTX *
|
||||||
get_ssl_ctx(void)
|
get_ssl_ctx(void)
|
||||||
{
|
{
|
||||||
if (the_ssl_ctx)
|
if (the_ssl_ctx)
|
||||||
@ -156,7 +157,7 @@ get_ssl_ctx(void)
|
|||||||
return the_ssl_ctx;
|
return the_ssl_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
init_ssl(void)
|
init_ssl(void)
|
||||||
{
|
{
|
||||||
SSL_library_init();
|
SSL_library_init();
|
||||||
@ -177,17 +178,64 @@ static int test_is_done = 0;
|
|||||||
static int n_connected = 0;
|
static int n_connected = 0;
|
||||||
static int got_close = 0;
|
static int got_close = 0;
|
||||||
static int got_error = 0;
|
static int got_error = 0;
|
||||||
|
static int got_timeout = 0;
|
||||||
static int renegotiate_at = -1;
|
static int renegotiate_at = -1;
|
||||||
static int stop_when_connected = 0;
|
static int stop_when_connected = 0;
|
||||||
static int pending_connect_events = 0;
|
static int pending_connect_events = 0;
|
||||||
static struct event_base *exit_base = NULL;
|
static struct event_base *exit_base = NULL;
|
||||||
|
|
||||||
|
enum regress_openssl_type
|
||||||
|
{
|
||||||
|
REGRESS_OPENSSL_SOCKETPAIR = 1,
|
||||||
|
REGRESS_OPENSSL_FILTER = 2,
|
||||||
|
REGRESS_OPENSSL_RENEGOTIATE = 4,
|
||||||
|
REGRESS_OPENSSL_OPEN = 8,
|
||||||
|
REGRESS_OPENSSL_DIRTY_SHUTDOWN = 16,
|
||||||
|
REGRESS_OPENSSL_FD = 32,
|
||||||
|
|
||||||
|
REGRESS_OPENSSL_CLIENT = 64,
|
||||||
|
REGRESS_OPENSSL_SERVER = 128,
|
||||||
|
|
||||||
|
REGRESS_OPENSSL_FREED = 256,
|
||||||
|
REGRESS_OPENSSL_TIMEOUT = 512,
|
||||||
|
REGRESS_OPENSSL_SLEEP = 1024,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
bufferevent_openssl_check_fd(struct bufferevent *bev, int filter)
|
||||||
|
{
|
||||||
|
if (filter) {
|
||||||
|
tt_int_op(bufferevent_getfd(bev), ==, -1);
|
||||||
|
tt_int_op(bufferevent_setfd(bev, -1), ==, -1);
|
||||||
|
} else {
|
||||||
|
tt_int_op(bufferevent_getfd(bev), !=, -1);
|
||||||
|
tt_int_op(bufferevent_setfd(bev, -1), ==, 0);
|
||||||
|
}
|
||||||
|
tt_int_op(bufferevent_getfd(bev), ==, -1);
|
||||||
|
|
||||||
|
end:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
static void
|
||||||
|
bufferevent_openssl_check_freed(struct bufferevent *bev)
|
||||||
|
{
|
||||||
|
tt_int_op(event_pending(&bev->ev_read, EVLIST_ALL, NULL), ==, 0);
|
||||||
|
tt_int_op(event_pending(&bev->ev_write, EVLIST_ALL, NULL), ==, 0);
|
||||||
|
|
||||||
|
end:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
respond_to_number(struct bufferevent *bev, void *ctx)
|
respond_to_number(struct bufferevent *bev, void *ctx)
|
||||||
{
|
{
|
||||||
struct evbuffer *b = bufferevent_get_input(bev);
|
struct evbuffer *b = bufferevent_get_input(bev);
|
||||||
char *line;
|
char *line;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
|
enum regress_openssl_type type;
|
||||||
|
type = (enum regress_openssl_type)ctx;
|
||||||
|
|
||||||
line = evbuffer_readln(b, NULL, EVBUFFER_EOL_LF);
|
line = evbuffer_readln(b, NULL, EVBUFFER_EOL_LF);
|
||||||
if (! line)
|
if (! line)
|
||||||
return;
|
return;
|
||||||
@ -201,7 +249,7 @@ respond_to_number(struct bufferevent *bev, void *ctx)
|
|||||||
bufferevent_free(bev); /* Should trigger close on other side. */
|
bufferevent_free(bev); /* Should trigger close on other side. */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!strcmp(ctx, "client") && n == renegotiate_at) {
|
if ((type & REGRESS_OPENSSL_CLIENT) && n == renegotiate_at) {
|
||||||
SSL_renegotiate(bufferevent_openssl_get_ssl(bev));
|
SSL_renegotiate(bufferevent_openssl_get_ssl(bev));
|
||||||
}
|
}
|
||||||
++n;
|
++n;
|
||||||
@ -226,6 +274,9 @@ done_writing_cb(struct bufferevent *bev, void *ctx)
|
|||||||
static void
|
static void
|
||||||
eventcb(struct bufferevent *bev, short what, void *ctx)
|
eventcb(struct bufferevent *bev, short what, void *ctx)
|
||||||
{
|
{
|
||||||
|
enum regress_openssl_type type;
|
||||||
|
type = (enum regress_openssl_type)ctx;
|
||||||
|
|
||||||
TT_BLATHER(("Got event %d", (int)what));
|
TT_BLATHER(("Got event %d", (int)what));
|
||||||
if (what & BEV_EVENT_CONNECTED) {
|
if (what & BEV_EVENT_CONNECTED) {
|
||||||
SSL *ssl;
|
SSL *ssl;
|
||||||
@ -234,7 +285,7 @@ eventcb(struct bufferevent *bev, short what, void *ctx)
|
|||||||
ssl = bufferevent_openssl_get_ssl(bev);
|
ssl = bufferevent_openssl_get_ssl(bev);
|
||||||
tt_assert(ssl);
|
tt_assert(ssl);
|
||||||
peer_cert = SSL_get_peer_certificate(ssl);
|
peer_cert = SSL_get_peer_certificate(ssl);
|
||||||
if (0==strcmp(ctx, "server")) {
|
if (type & REGRESS_OPENSSL_SERVER) {
|
||||||
tt_assert(peer_cert == NULL);
|
tt_assert(peer_cert == NULL);
|
||||||
} else {
|
} else {
|
||||||
tt_assert(peer_cert != NULL);
|
tt_assert(peer_cert != NULL);
|
||||||
@ -246,10 +297,32 @@ eventcb(struct bufferevent *bev, short what, void *ctx)
|
|||||||
} else if (what & BEV_EVENT_EOF) {
|
} else if (what & BEV_EVENT_EOF) {
|
||||||
TT_BLATHER(("Got a good EOF"));
|
TT_BLATHER(("Got a good EOF"));
|
||||||
++got_close;
|
++got_close;
|
||||||
|
if (type & REGRESS_OPENSSL_FD) {
|
||||||
|
bufferevent_openssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER);
|
||||||
|
}
|
||||||
|
if (type & REGRESS_OPENSSL_FREED) {
|
||||||
|
bufferevent_openssl_check_freed(bev);
|
||||||
|
}
|
||||||
bufferevent_free(bev);
|
bufferevent_free(bev);
|
||||||
} else if (what & BEV_EVENT_ERROR) {
|
} else if (what & BEV_EVENT_ERROR) {
|
||||||
TT_BLATHER(("Got an error."));
|
TT_BLATHER(("Got an error."));
|
||||||
++got_error;
|
++got_error;
|
||||||
|
if (type & REGRESS_OPENSSL_FD) {
|
||||||
|
bufferevent_openssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER);
|
||||||
|
}
|
||||||
|
if (type & REGRESS_OPENSSL_FREED) {
|
||||||
|
bufferevent_openssl_check_freed(bev);
|
||||||
|
}
|
||||||
|
bufferevent_free(bev);
|
||||||
|
} else if (what & BEV_EVENT_TIMEOUT) {
|
||||||
|
TT_BLATHER(("Got timeout."));
|
||||||
|
++got_timeout;
|
||||||
|
if (type & REGRESS_OPENSSL_FD) {
|
||||||
|
bufferevent_openssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER);
|
||||||
|
}
|
||||||
|
if (type & REGRESS_OPENSSL_FREED) {
|
||||||
|
bufferevent_openssl_check_freed(bev);
|
||||||
|
}
|
||||||
bufferevent_free(bev);
|
bufferevent_free(bev);
|
||||||
}
|
}
|
||||||
end:
|
end:
|
||||||
@ -259,10 +332,12 @@ end:
|
|||||||
static void
|
static void
|
||||||
open_ssl_bufevs(struct bufferevent **bev1_out, struct bufferevent **bev2_out,
|
open_ssl_bufevs(struct bufferevent **bev1_out, struct bufferevent **bev2_out,
|
||||||
struct event_base *base, int is_open, int flags, SSL *ssl1, SSL *ssl2,
|
struct event_base *base, int is_open, int flags, SSL *ssl1, SSL *ssl2,
|
||||||
evutil_socket_t *fd_pair, struct bufferevent **underlying_pair)
|
evutil_socket_t *fd_pair, struct bufferevent **underlying_pair,
|
||||||
|
enum regress_openssl_type type)
|
||||||
{
|
{
|
||||||
int state1 = is_open ? BUFFEREVENT_SSL_OPEN :BUFFEREVENT_SSL_CONNECTING;
|
int state1 = is_open ? BUFFEREVENT_SSL_OPEN :BUFFEREVENT_SSL_CONNECTING;
|
||||||
int state2 = is_open ? BUFFEREVENT_SSL_OPEN :BUFFEREVENT_SSL_ACCEPTING;
|
int state2 = is_open ? BUFFEREVENT_SSL_OPEN :BUFFEREVENT_SSL_ACCEPTING;
|
||||||
|
int dirty_shutdown = type & REGRESS_OPENSSL_DIRTY_SHUTDOWN;
|
||||||
if (fd_pair) {
|
if (fd_pair) {
|
||||||
*bev1_out = bufferevent_openssl_socket_new(
|
*bev1_out = bufferevent_openssl_socket_new(
|
||||||
base, fd_pair[0], ssl1, state1, flags);
|
base, fd_pair[0], ssl1, state1, flags);
|
||||||
@ -276,9 +351,12 @@ open_ssl_bufevs(struct bufferevent **bev1_out, struct bufferevent **bev2_out,
|
|||||||
|
|
||||||
}
|
}
|
||||||
bufferevent_setcb(*bev1_out, respond_to_number, done_writing_cb,
|
bufferevent_setcb(*bev1_out, respond_to_number, done_writing_cb,
|
||||||
eventcb, (void*)"client");
|
eventcb, (void*)(REGRESS_OPENSSL_CLIENT | (long)type));
|
||||||
bufferevent_setcb(*bev2_out, respond_to_number, done_writing_cb,
|
bufferevent_setcb(*bev2_out, respond_to_number, done_writing_cb,
|
||||||
eventcb, (void*)"server");
|
eventcb, (void*)(REGRESS_OPENSSL_SERVER | (long)type));
|
||||||
|
|
||||||
|
bufferevent_openssl_set_allow_dirty_shutdown(*bev1_out, dirty_shutdown);
|
||||||
|
bufferevent_openssl_set_allow_dirty_shutdown(*bev2_out, dirty_shutdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -288,20 +366,21 @@ regress_bufferevent_openssl(void *arg)
|
|||||||
|
|
||||||
struct bufferevent *bev1, *bev2;
|
struct bufferevent *bev1, *bev2;
|
||||||
SSL *ssl1, *ssl2;
|
SSL *ssl1, *ssl2;
|
||||||
X509 *cert = getcert();
|
X509 *cert = ssl_getcert();
|
||||||
EVP_PKEY *key = getkey();
|
EVP_PKEY *key = ssl_getkey();
|
||||||
const int start_open = strstr((char*)data->setup_data, "open")!=NULL;
|
|
||||||
const int filter = strstr((char*)data->setup_data, "filter")!=NULL;
|
|
||||||
int flags = BEV_OPT_DEFER_CALLBACKS;
|
int flags = BEV_OPT_DEFER_CALLBACKS;
|
||||||
struct bufferevent *bev_ll[2] = { NULL, NULL };
|
struct bufferevent *bev_ll[2] = { NULL, NULL };
|
||||||
evutil_socket_t *fd_pair = NULL;
|
evutil_socket_t *fd_pair = NULL;
|
||||||
|
|
||||||
|
enum regress_openssl_type type;
|
||||||
|
type = (enum regress_openssl_type)data->setup_data;
|
||||||
|
|
||||||
tt_assert(cert);
|
tt_assert(cert);
|
||||||
tt_assert(key);
|
tt_assert(key);
|
||||||
|
|
||||||
init_ssl();
|
init_ssl();
|
||||||
|
|
||||||
if (strstr((char*)data->setup_data, "renegotiate")) {
|
if (type & REGRESS_OPENSSL_RENEGOTIATE) {
|
||||||
if (SSLeay() >= 0x10001000 &&
|
if (SSLeay() >= 0x10001000 &&
|
||||||
SSLeay() < 0x1000104f) {
|
SSLeay() < 0x1000104f) {
|
||||||
/* 1.0.1 up to 1.0.1c has a bug where TLS1.1 and 1.2
|
/* 1.0.1 up to 1.0.1c has a bug where TLS1.1 and 1.2
|
||||||
@ -317,11 +396,11 @@ regress_bufferevent_openssl(void *arg)
|
|||||||
SSL_use_certificate(ssl2, cert);
|
SSL_use_certificate(ssl2, cert);
|
||||||
SSL_use_PrivateKey(ssl2, key);
|
SSL_use_PrivateKey(ssl2, key);
|
||||||
|
|
||||||
if (! start_open)
|
if (!(type & REGRESS_OPENSSL_OPEN))
|
||||||
flags |= BEV_OPT_CLOSE_ON_FREE;
|
flags |= BEV_OPT_CLOSE_ON_FREE;
|
||||||
|
|
||||||
if (!filter) {
|
if (!(type & REGRESS_OPENSSL_FILTER)) {
|
||||||
tt_assert(strstr((char*)data->setup_data, "socketpair"));
|
tt_assert(type & REGRESS_OPENSSL_SOCKETPAIR);
|
||||||
fd_pair = data->pair;
|
fd_pair = data->pair;
|
||||||
} else {
|
} else {
|
||||||
bev_ll[0] = bufferevent_socket_new(data->base, data->pair[0],
|
bev_ll[0] = bufferevent_socket_new(data->base, data->pair[0],
|
||||||
@ -331,15 +410,15 @@ regress_bufferevent_openssl(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
open_ssl_bufevs(&bev1, &bev2, data->base, 0, flags, ssl1, ssl2,
|
open_ssl_bufevs(&bev1, &bev2, data->base, 0, flags, ssl1, ssl2,
|
||||||
fd_pair, bev_ll);
|
fd_pair, bev_ll, type);
|
||||||
|
|
||||||
if (!filter) {
|
if (!(type & REGRESS_OPENSSL_FILTER)) {
|
||||||
tt_int_op(bufferevent_getfd(bev1), ==, data->pair[0]);
|
tt_int_op(bufferevent_getfd(bev1), ==, data->pair[0]);
|
||||||
} else {
|
} else {
|
||||||
tt_ptr_op(bufferevent_get_underlying(bev1), ==, bev_ll[0]);
|
tt_ptr_op(bufferevent_get_underlying(bev1), ==, bev_ll[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (start_open) {
|
if (type & REGRESS_OPENSSL_OPEN) {
|
||||||
pending_connect_events = 2;
|
pending_connect_events = 2;
|
||||||
stop_when_connected = 1;
|
stop_when_connected = 1;
|
||||||
exit_base = data->base;
|
exit_base = data->base;
|
||||||
@ -351,37 +430,70 @@ regress_bufferevent_openssl(void *arg)
|
|||||||
bufferevent_free(bev2);
|
bufferevent_free(bev2);
|
||||||
bev1 = bev2 = NULL;
|
bev1 = bev2 = NULL;
|
||||||
open_ssl_bufevs(&bev1, &bev2, data->base, 1, flags, ssl1, ssl2,
|
open_ssl_bufevs(&bev1, &bev2, data->base, 1, flags, ssl1, ssl2,
|
||||||
fd_pair, bev_ll);
|
fd_pair, bev_ll, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
bufferevent_enable(bev1, EV_READ|EV_WRITE);
|
if (!(type & REGRESS_OPENSSL_TIMEOUT)) {
|
||||||
bufferevent_enable(bev2, EV_READ|EV_WRITE);
|
bufferevent_enable(bev1, EV_READ|EV_WRITE);
|
||||||
|
bufferevent_enable(bev2, EV_READ|EV_WRITE);
|
||||||
|
|
||||||
evbuffer_add_printf(bufferevent_get_output(bev1), "1\n");
|
evbuffer_add_printf(bufferevent_get_output(bev1), "1\n");
|
||||||
|
|
||||||
event_base_dispatch(data->base);
|
event_base_dispatch(data->base);
|
||||||
|
|
||||||
tt_assert(test_is_done == 1);
|
tt_assert(test_is_done == 1);
|
||||||
tt_assert(n_connected == 2);
|
tt_assert(n_connected == 2);
|
||||||
|
|
||||||
/* We don't handle shutdown properly yet.
|
/* We don't handle shutdown properly yet */
|
||||||
tt_int_op(got_close, ==, 1);
|
if (type & REGRESS_OPENSSL_DIRTY_SHUTDOWN) {
|
||||||
tt_int_op(got_error, ==, 0);
|
tt_int_op(got_close, ==, 1);
|
||||||
*/
|
tt_int_op(got_error, ==, 0);
|
||||||
|
} else {
|
||||||
|
tt_int_op(got_error, ==, 1);
|
||||||
|
}
|
||||||
|
tt_int_op(got_timeout, ==, 0);
|
||||||
|
} else {
|
||||||
|
struct timeval t = { 2, 0 };
|
||||||
|
|
||||||
|
bufferevent_enable(bev1, EV_READ|EV_WRITE);
|
||||||
|
bufferevent_disable(bev2, EV_READ|EV_WRITE);
|
||||||
|
|
||||||
|
bufferevent_set_timeouts(bev1, &t, &t);
|
||||||
|
|
||||||
|
evbuffer_add_printf(bufferevent_get_output(bev1), "1\n");
|
||||||
|
|
||||||
|
event_base_dispatch(data->base);
|
||||||
|
|
||||||
|
tt_assert(test_is_done == 0);
|
||||||
|
tt_assert(n_connected == 0);
|
||||||
|
|
||||||
|
tt_int_op(got_close, ==, 0);
|
||||||
|
tt_int_op(got_error, ==, 0);
|
||||||
|
tt_int_op(got_timeout, ==, 1);
|
||||||
|
}
|
||||||
end:
|
end:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
acceptcb_deferred(evutil_socket_t fd, short events, void *arg)
|
||||||
|
{
|
||||||
|
struct bufferevent *bev = arg;
|
||||||
|
bufferevent_enable(bev, EV_READ|EV_WRITE);
|
||||||
|
}
|
||||||
static void
|
static void
|
||||||
acceptcb(struct evconnlistener *listener, evutil_socket_t fd,
|
acceptcb(struct evconnlistener *listener, evutil_socket_t fd,
|
||||||
struct sockaddr *addr, int socklen, void *arg)
|
struct sockaddr *addr, int socklen, void *arg)
|
||||||
{
|
{
|
||||||
struct basic_test_data *data = arg;
|
struct basic_test_data *data = arg;
|
||||||
struct bufferevent *bev;
|
struct bufferevent *bev;
|
||||||
|
enum regress_openssl_type type;
|
||||||
SSL *ssl = SSL_new(get_ssl_ctx());
|
SSL *ssl = SSL_new(get_ssl_ctx());
|
||||||
|
|
||||||
SSL_use_certificate(ssl, getcert());
|
type = (enum regress_openssl_type)data->setup_data;
|
||||||
SSL_use_PrivateKey(ssl, getkey());
|
|
||||||
|
SSL_use_certificate(ssl, ssl_getcert());
|
||||||
|
SSL_use_PrivateKey(ssl, ssl_getkey());
|
||||||
|
|
||||||
bev = bufferevent_openssl_socket_new(
|
bev = bufferevent_openssl_socket_new(
|
||||||
data->base,
|
data->base,
|
||||||
@ -391,14 +503,129 @@ acceptcb(struct evconnlistener *listener, evutil_socket_t fd,
|
|||||||
BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
|
BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
|
||||||
|
|
||||||
bufferevent_setcb(bev, respond_to_number, NULL, eventcb,
|
bufferevent_setcb(bev, respond_to_number, NULL, eventcb,
|
||||||
(void*)"server");
|
(void*)(REGRESS_OPENSSL_SERVER));
|
||||||
|
|
||||||
bufferevent_enable(bev, EV_READ|EV_WRITE);
|
if (type & REGRESS_OPENSSL_SLEEP) {
|
||||||
|
struct timeval when = { 1, 0 };
|
||||||
|
event_base_once(data->base, -1, EV_TIMEOUT,
|
||||||
|
acceptcb_deferred, bev, &when);
|
||||||
|
bufferevent_disable(bev, EV_READ|EV_WRITE);
|
||||||
|
} else {
|
||||||
|
bufferevent_enable(bev, EV_READ|EV_WRITE);
|
||||||
|
}
|
||||||
|
|
||||||
/* Only accept once, then disable ourself. */
|
/* Only accept once, then disable ourself. */
|
||||||
evconnlistener_disable(listener);
|
evconnlistener_disable(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct rwcount
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
size_t read;
|
||||||
|
size_t write;
|
||||||
|
};
|
||||||
|
static int
|
||||||
|
bio_rwcount_new(BIO *b)
|
||||||
|
{
|
||||||
|
b->init = 0;
|
||||||
|
b->num = -1;
|
||||||
|
b->ptr = NULL;
|
||||||
|
b->flags = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
static int
|
||||||
|
bio_rwcount_free(BIO *b)
|
||||||
|
{
|
||||||
|
if (!b)
|
||||||
|
return 0;
|
||||||
|
if (b->shutdown) {
|
||||||
|
b->init = 0;
|
||||||
|
b->flags = 0;
|
||||||
|
b->ptr = NULL;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
static int
|
||||||
|
bio_rwcount_read(BIO *b, char *out, int outlen)
|
||||||
|
{
|
||||||
|
struct rwcount *rw = b->ptr;
|
||||||
|
ssize_t ret = read(rw->fd, out, outlen);
|
||||||
|
++rw->read;
|
||||||
|
if (ret == -1 && errno == EAGAIN) {
|
||||||
|
BIO_set_retry_read(b);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
static int
|
||||||
|
bio_rwcount_write(BIO *b, const char *in, int inlen)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct rwcount *rw = b->ptr;
|
||||||
|
ssize_t ret = write(rw->fd, in, inlen);
|
||||||
|
++rw->write;
|
||||||
|
if (ret == -1 && errno == EAGAIN) {
|
||||||
|
BIO_set_retry_write(b);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
static long
|
||||||
|
bio_rwcount_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||||
|
{
|
||||||
|
long ret = 0;
|
||||||
|
switch (cmd) {
|
||||||
|
case BIO_CTRL_GET_CLOSE:
|
||||||
|
ret = b->shutdown;
|
||||||
|
break;
|
||||||
|
case BIO_CTRL_SET_CLOSE:
|
||||||
|
b->shutdown = (int)num;
|
||||||
|
break;
|
||||||
|
case BIO_CTRL_PENDING:
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
case BIO_CTRL_WPENDING:
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
case BIO_CTRL_DUP:
|
||||||
|
case BIO_CTRL_FLUSH:
|
||||||
|
ret = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
static int
|
||||||
|
bio_rwcount_puts(BIO *b, const char *s)
|
||||||
|
{
|
||||||
|
return bio_rwcount_write(b, s, strlen(s));
|
||||||
|
}
|
||||||
|
#define BIO_TYPE_LIBEVENT_RWCOUNT 0xff1
|
||||||
|
static BIO_METHOD methods_rwcount = {
|
||||||
|
BIO_TYPE_LIBEVENT_RWCOUNT, "rwcount",
|
||||||
|
bio_rwcount_write,
|
||||||
|
bio_rwcount_read,
|
||||||
|
bio_rwcount_puts,
|
||||||
|
NULL /* bio_rwcount_gets */,
|
||||||
|
bio_rwcount_ctrl,
|
||||||
|
bio_rwcount_new,
|
||||||
|
bio_rwcount_free,
|
||||||
|
NULL /* callback_ctrl */,
|
||||||
|
};
|
||||||
|
static BIO_METHOD *
|
||||||
|
BIO_s_rwcount(void)
|
||||||
|
{
|
||||||
|
return &methods_rwcount;
|
||||||
|
}
|
||||||
|
static BIO *
|
||||||
|
BIO_new_rwcount(int close_flag)
|
||||||
|
{
|
||||||
|
BIO *result;
|
||||||
|
if (!(result = BIO_new(BIO_s_rwcount())))
|
||||||
|
return NULL;
|
||||||
|
result->init = 1;
|
||||||
|
result->ptr = NULL;
|
||||||
|
result->shutdown = !!close_flag;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
regress_bufferevent_openssl_connect(void *arg)
|
regress_bufferevent_openssl_connect(void *arg)
|
||||||
{
|
{
|
||||||
@ -411,6 +638,12 @@ regress_bufferevent_openssl_connect(void *arg)
|
|||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
struct sockaddr_storage ss;
|
struct sockaddr_storage ss;
|
||||||
ev_socklen_t slen;
|
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();
|
init_ssl();
|
||||||
|
|
||||||
@ -428,51 +661,115 @@ regress_bufferevent_openssl_connect(void *arg)
|
|||||||
tt_assert(listener);
|
tt_assert(listener);
|
||||||
tt_assert(evconnlistener_get_fd(listener) >= 0);
|
tt_assert(evconnlistener_get_fd(listener) >= 0);
|
||||||
|
|
||||||
|
ssl = SSL_new(get_ssl_ctx());
|
||||||
|
tt_assert(ssl);
|
||||||
|
|
||||||
bev = bufferevent_openssl_socket_new(
|
bev = bufferevent_openssl_socket_new(
|
||||||
data->base, -1, SSL_new(get_ssl_ctx()),
|
data->base, -1, ssl,
|
||||||
BUFFEREVENT_SSL_CONNECTING,
|
BUFFEREVENT_SSL_CONNECTING,
|
||||||
BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
|
BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
|
||||||
tt_assert(bev);
|
tt_assert(bev);
|
||||||
|
|
||||||
bufferevent_setcb(bev, respond_to_number, NULL, eventcb,
|
bufferevent_setcb(bev, respond_to_number, NULL, eventcb,
|
||||||
(void*)"client");
|
(void*)(REGRESS_OPENSSL_CLIENT));
|
||||||
|
|
||||||
tt_assert(getsockname(evconnlistener_get_fd(listener),
|
tt_assert(getsockname(evconnlistener_get_fd(listener),
|
||||||
(struct sockaddr*)&ss, &slen) == 0);
|
(struct sockaddr*)&ss, &slen) == 0);
|
||||||
tt_assert(slen == sizeof(struct sockaddr_in));
|
tt_assert(slen == sizeof(struct sockaddr_in));
|
||||||
tt_int_op(((struct sockaddr*)&ss)->sa_family, ==, AF_INET);
|
tt_int_op(((struct sockaddr*)&ss)->sa_family, ==, AF_INET);
|
||||||
tt_int_op(((struct sockaddr*)&ss)->sa_family, ==, AF_INET);
|
|
||||||
|
|
||||||
tt_assert(0 ==
|
tt_assert(0 ==
|
||||||
bufferevent_socket_connect(bev, (struct sockaddr*)&ss, slen));
|
bufferevent_socket_connect(bev, (struct sockaddr*)&ss, slen));
|
||||||
|
/* Possible only when we have fd, since be_openssl can and will overwrite
|
||||||
|
* bio otherwise before */
|
||||||
|
if (type & REGRESS_OPENSSL_SLEEP) {
|
||||||
|
rw.fd = bufferevent_getfd(bev);
|
||||||
|
bio = BIO_new_rwcount(0);
|
||||||
|
tt_assert(bio);
|
||||||
|
bio->ptr = &rw;
|
||||||
|
SSL_set_bio(ssl, bio, bio);
|
||||||
|
}
|
||||||
evbuffer_add_printf(bufferevent_get_output(bev), "1\n");
|
evbuffer_add_printf(bufferevent_get_output(bev), "1\n");
|
||||||
bufferevent_enable(bev, EV_READ|EV_WRITE);
|
bufferevent_enable(bev, EV_READ|EV_WRITE);
|
||||||
|
|
||||||
event_base_dispatch(base);
|
event_base_dispatch(base);
|
||||||
|
|
||||||
|
tt_int_op(rw.read, <=, 100);
|
||||||
|
tt_int_op(rw.write, <=, 100);
|
||||||
end:
|
end:
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct testcase_t ssl_testcases[] = {
|
struct testcase_t ssl_testcases[] = {
|
||||||
|
#define T(a) ((void *)(a))
|
||||||
{ "bufferevent_socketpair", regress_bufferevent_openssl, TT_ISOLATED,
|
{ "bufferevent_socketpair", regress_bufferevent_openssl,
|
||||||
&basic_setup, (void*)"socketpair" },
|
TT_ISOLATED, &basic_setup, T(REGRESS_OPENSSL_SOCKETPAIR) },
|
||||||
{ "bufferevent_filter", regress_bufferevent_openssl,
|
{ "bufferevent_filter", regress_bufferevent_openssl,
|
||||||
TT_ISOLATED,
|
TT_ISOLATED, &basic_setup, T(REGRESS_OPENSSL_FILTER) },
|
||||||
&basic_setup, (void*)"filter" },
|
|
||||||
{ "bufferevent_renegotiate_socketpair", regress_bufferevent_openssl,
|
{ "bufferevent_renegotiate_socketpair", regress_bufferevent_openssl,
|
||||||
TT_ISOLATED,
|
TT_ISOLATED, &basic_setup,
|
||||||
&basic_setup, (void*)"socketpair renegotiate" },
|
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_RENEGOTIATE) },
|
||||||
{ "bufferevent_renegotiate_filter", regress_bufferevent_openssl,
|
{ "bufferevent_renegotiate_filter", regress_bufferevent_openssl,
|
||||||
TT_ISOLATED,
|
TT_ISOLATED, &basic_setup,
|
||||||
&basic_setup, (void*)"filter renegotiate" },
|
T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_RENEGOTIATE) },
|
||||||
{ "bufferevent_socketpair_startopen", regress_bufferevent_openssl,
|
{ "bufferevent_socketpair_startopen", regress_bufferevent_openssl,
|
||||||
TT_ISOLATED, &basic_setup, (void*)"socketpair open" },
|
TT_ISOLATED, &basic_setup,
|
||||||
|
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_OPEN) },
|
||||||
{ "bufferevent_filter_startopen", regress_bufferevent_openssl,
|
{ "bufferevent_filter_startopen", regress_bufferevent_openssl,
|
||||||
TT_ISOLATED, &basic_setup, (void*)"filter open" },
|
TT_ISOLATED, &basic_setup,
|
||||||
|
T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_OPEN) },
|
||||||
|
|
||||||
|
{ "bufferevent_socketpair_dirty_shutdown", regress_bufferevent_openssl,
|
||||||
|
TT_ISOLATED, &basic_setup,
|
||||||
|
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
|
||||||
|
{ "bufferevent_filter_dirty_shutdown", regress_bufferevent_openssl,
|
||||||
|
TT_ISOLATED, &basic_setup,
|
||||||
|
T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
|
||||||
|
{ "bufferevent_renegotiate_socketpair_dirty_shutdown",
|
||||||
|
regress_bufferevent_openssl,
|
||||||
|
TT_ISOLATED,
|
||||||
|
&basic_setup,
|
||||||
|
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_RENEGOTIATE | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
|
||||||
|
{ "bufferevent_renegotiate_filter_dirty_shutdown",
|
||||||
|
regress_bufferevent_openssl,
|
||||||
|
TT_ISOLATED,
|
||||||
|
&basic_setup,
|
||||||
|
T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_RENEGOTIATE | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
|
||||||
|
{ "bufferevent_socketpair_startopen_dirty_shutdown",
|
||||||
|
regress_bufferevent_openssl,
|
||||||
|
TT_ISOLATED, &basic_setup,
|
||||||
|
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_OPEN | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
|
||||||
|
{ "bufferevent_filter_startopen_dirty_shutdown",
|
||||||
|
regress_bufferevent_openssl,
|
||||||
|
TT_ISOLATED, &basic_setup,
|
||||||
|
T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_OPEN | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
|
||||||
|
|
||||||
|
{ "bufferevent_socketpair_fd", regress_bufferevent_openssl,
|
||||||
|
TT_ISOLATED, &basic_setup,
|
||||||
|
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_FD) },
|
||||||
|
{ "bufferevent_socketpair_freed", regress_bufferevent_openssl,
|
||||||
|
TT_ISOLATED, &basic_setup,
|
||||||
|
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_FREED) },
|
||||||
|
{ "bufferevent_socketpair_freed_fd", regress_bufferevent_openssl,
|
||||||
|
TT_ISOLATED, &basic_setup,
|
||||||
|
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_FREED | REGRESS_OPENSSL_FD) },
|
||||||
|
{ "bufferevent_filter_freed_fd", regress_bufferevent_openssl,
|
||||||
|
TT_ISOLATED, &basic_setup,
|
||||||
|
T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_FREED | REGRESS_OPENSSL_FD) },
|
||||||
|
|
||||||
|
{ "bufferevent_socketpair_timeout", regress_bufferevent_openssl,
|
||||||
|
TT_ISOLATED, &basic_setup,
|
||||||
|
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_TIMEOUT) },
|
||||||
|
{ "bufferevent_socketpair_timeout_freed_fd", regress_bufferevent_openssl,
|
||||||
|
TT_ISOLATED, &basic_setup,
|
||||||
|
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_TIMEOUT | REGRESS_OPENSSL_FREED | REGRESS_OPENSSL_FD) },
|
||||||
|
|
||||||
{ "bufferevent_connect", regress_bufferevent_openssl_connect,
|
{ "bufferevent_connect", regress_bufferevent_openssl_connect,
|
||||||
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
|
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
|
||||||
|
{ "bufferevent_connect_sleep", regress_bufferevent_openssl_connect,
|
||||||
|
TT_FORK|TT_NEED_BASE, &basic_setup, T(REGRESS_OPENSSL_SLEEP) },
|
||||||
|
|
||||||
|
#undef T
|
||||||
|
|
||||||
END_OF_TESTCASES,
|
END_OF_TESTCASES,
|
||||||
};
|
};
|
||||||
|
@ -135,11 +135,18 @@ regress_clean_dnsserver(void)
|
|||||||
evutil_closesocket(dns_sock);
|
evutil_closesocket(dns_sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void strtolower(char *s)
|
||||||
|
{
|
||||||
|
while (*s) {
|
||||||
|
*s = EVUTIL_TOLOWER_(*s);
|
||||||
|
++s;
|
||||||
|
}
|
||||||
|
}
|
||||||
void
|
void
|
||||||
regress_dns_server_cb(struct evdns_server_request *req, void *data)
|
regress_dns_server_cb(struct evdns_server_request *req, void *data)
|
||||||
{
|
{
|
||||||
struct regress_dns_server_table *tab = data;
|
struct regress_dns_server_table *tab = data;
|
||||||
const char *question;
|
char *question;
|
||||||
|
|
||||||
if (req->nquestions != 1)
|
if (req->nquestions != 1)
|
||||||
TT_DIE(("Only handling one question at a time; got %d",
|
TT_DIE(("Only handling one question at a time; got %d",
|
||||||
@ -155,6 +162,9 @@ regress_dns_server_cb(struct evdns_server_request *req, void *data)
|
|||||||
|
|
||||||
++tab->seen;
|
++tab->seen;
|
||||||
|
|
||||||
|
if (tab->lower)
|
||||||
|
strtolower(question);
|
||||||
|
|
||||||
if (!strcmp(tab->anstype, "err")) {
|
if (!strcmp(tab->anstype, "err")) {
|
||||||
int err = atoi(tab->ans);
|
int err = atoi(tab->ans);
|
||||||
tt_assert(! evdns_server_request_respond(req, err));
|
tt_assert(! evdns_server_request_respond(req, err));
|
||||||
|
@ -34,6 +34,7 @@ struct regress_dns_server_table {
|
|||||||
const char *anstype;
|
const char *anstype;
|
||||||
const char *ans;
|
const char *ans;
|
||||||
int seen;
|
int seen;
|
||||||
|
int lower;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct evdns_server_port *
|
struct evdns_server_port *
|
||||||
|
@ -579,7 +579,12 @@ struct testcase_t thread_testcases[] = {
|
|||||||
{ "deferred_cb_skew", thread_deferred_cb_skew,
|
{ "deferred_cb_skew", thread_deferred_cb_skew,
|
||||||
TT_FORK|TT_NEED_THREADS|TT_OFF_BY_DEFAULT,
|
TT_FORK|TT_NEED_THREADS|TT_OFF_BY_DEFAULT,
|
||||||
&basic_setup, NULL },
|
&basic_setup, NULL },
|
||||||
|
#ifndef _WIN32
|
||||||
|
/****** XXX TODO FIXME windows seems to be having some timing trouble,
|
||||||
|
* looking into it now. / ellzey
|
||||||
|
******/
|
||||||
TEST(no_events),
|
TEST(no_events),
|
||||||
|
#endif
|
||||||
END_OF_TESTCASES
|
END_OF_TESTCASES
|
||||||
};
|
};
|
||||||
|
|
||||||
|
16
test/test.sh
16
test/test.sh
@ -97,6 +97,7 @@ run_tests () {
|
|||||||
announce "FAILED (output not checked)" ;
|
announce "FAILED (output not checked)" ;
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
test -x $TEST_DIR/regress || return
|
test -x $TEST_DIR/regress || return
|
||||||
announce_n " regress: "
|
announce_n " regress: "
|
||||||
if test "$TEST_OUTPUT_FILE" = "/dev/null" ;
|
if test "$TEST_OUTPUT_FILE" = "/dev/null" ;
|
||||||
@ -112,6 +113,21 @@ run_tests () {
|
|||||||
announce FAILED ;
|
announce FAILED ;
|
||||||
FAILED=yes
|
FAILED=yes
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
announce_n " regress_debug: "
|
||||||
|
if test "$TEST_OUTPUT_FILE" = "/dev/null" ;
|
||||||
|
then
|
||||||
|
EVENT_DEBUG_MODE=1 $TEST_DIR/regress --quiet $REGRESS_ARGS
|
||||||
|
else
|
||||||
|
EVENT_DEBUG_MODE=1 $TEST_DIR/regress $REGRESS_ARGS >>"$TEST_OUTPUT_FILE"
|
||||||
|
fi
|
||||||
|
if test "$?" = "0" ;
|
||||||
|
then
|
||||||
|
announce OKAY ;
|
||||||
|
else
|
||||||
|
announce FAILED ;
|
||||||
|
FAILED=yes
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
do_test() {
|
do_test() {
|
||||||
|
@ -261,7 +261,7 @@ int evutil_open_closeonexec_(const char *pathname, int flags, unsigned mode);
|
|||||||
int evutil_read_file_(const char *filename, char **content_out, size_t *len_out,
|
int evutil_read_file_(const char *filename, char **content_out, size_t *len_out,
|
||||||
int is_binary);
|
int is_binary);
|
||||||
|
|
||||||
int evutil_socket_connect_(evutil_socket_t *fd_ptr, struct sockaddr *sa, int socklen);
|
int evutil_socket_connect_(evutil_socket_t *fd_ptr, const struct sockaddr *sa, int socklen);
|
||||||
|
|
||||||
int evutil_socket_finished_connecting_(evutil_socket_t fd);
|
int evutil_socket_finished_connecting_(evutil_socket_t fd);
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ extern struct event_list timequeue;
|
|||||||
extern struct event_list addqueue;
|
extern struct event_list addqueue;
|
||||||
|
|
||||||
struct win_fd_set {
|
struct win_fd_set {
|
||||||
u_int fd_count;
|
unsigned int fd_count;
|
||||||
SOCKET fd_array[1];
|
SOCKET fd_array[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user