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
|
||||
*.gcda
|
||||
|
||||
# gdb stuff
|
||||
.gdb_history
|
||||
|
||||
# Autotools stuff
|
||||
.deps
|
||||
.dirstamp
|
||||
@ -36,6 +39,7 @@ Makefile.in
|
||||
|
||||
# ctags stuff
|
||||
TAGS
|
||||
tags
|
||||
|
||||
# Stuff made by our makefiles
|
||||
libevent.pc
|
||||
@ -80,10 +84,12 @@ libevent_openssl.pc
|
||||
/sample/event-read-fifo
|
||||
/sample/hello-world
|
||||
/sample/http-server
|
||||
/sample/http-connect
|
||||
/sample/le-proxy
|
||||
/sample/https-client
|
||||
/sample/signal-test
|
||||
/sample/time-test
|
||||
/sample/event-test
|
||||
|
||||
/test-driver
|
||||
/test/bench
|
||||
|
@ -3,7 +3,9 @@ env:
|
||||
- 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_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
|
||||
compiler:
|
||||
- gcc
|
||||
@ -12,5 +14,8 @@ install:
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -y -qq zlib1g-dev libssl-dev build-essential automake autoconf cmake
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
## Autoconf
|
||||
@ -7,6 +18,72 @@
|
||||
$ make verify # (optional)
|
||||
$ 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)
|
||||
|
||||
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:
|
||||
- appveyor DownloadFile http://slproweb.com/download/Win32OpenSSL-1_0_1L.exe
|
||||
- Win32OpenSSL-1_0_1L.exe /silent /verysilent /sp- /suppressmsgboxes
|
||||
- set PATH=%PATH%;C:\MinGW\msys\1.0\bin;C:\MinGW\bin
|
||||
- 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
|
||||
- cmd: 'echo Cygwin root is: %CYG_ROOT%'
|
||||
- cmd: 'echo Build folder is: %APPVEYOR_BUILD_FOLDER%'
|
||||
- cmd: 'echo Repo build branch is: %APPVEYOR_REPO_BRANCH%'
|
||||
- cmd: 'echo Repo build commit is: %APPVEYOR_REPO_COMMIT%'
|
||||
- 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:
|
||||
- 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,
|
||||
* 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;
|
||||
|
||||
@ -2909,7 +2909,7 @@ evbuffer_add_reference(struct evbuffer *outbuf,
|
||||
if (!chain)
|
||||
return (-1);
|
||||
chain->flags |= EVBUFFER_REFERENCE | EVBUFFER_IMMUTABLE;
|
||||
chain->buffer = (u_char *)data;
|
||||
chain->buffer = (unsigned char *)data;
|
||||
chain->buffer_len = datlen;
|
||||
chain->off = datlen;
|
||||
|
||||
|
@ -40,6 +40,17 @@ extern "C" {
|
||||
#include "ratelim-internal.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
|
||||
reading or writing on a bufferevent.
|
||||
*/
|
||||
@ -205,6 +216,18 @@ struct bufferevent_private {
|
||||
|
||||
/** Rate-limiting information for this bufferevent */
|
||||
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. */
|
||||
@ -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.
|
||||
* Otherwise, use a new lock. */
|
||||
int bufferevent_enable_locking_(struct bufferevent *bufev, void *lock);
|
||||
/** Internal: Increment the reference count on bufev. */
|
||||
void bufferevent_incref_(struct bufferevent *bufev);
|
||||
/** Internal: backwards compat macro for the now public function
|
||||
* Increment the reference count on bufev. */
|
||||
#define bufferevent_incref_(bufev) bufferevent_incref(bufev)
|
||||
/** Internal: Lock bufev and increase its reference count.
|
||||
* unlocking it otherwise. */
|
||||
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.*/
|
||||
int bufferevent_decref_(struct bufferevent *bufev);
|
||||
#define bufferevent_decref_(bufev) bufferevent_decref(bufev)
|
||||
|
||||
/** Internal: Drop the reference count on bufev, freeing as necessary, and
|
||||
* unlocking it otherwise. Returns 1 if it freed the bufferevent. */
|
||||
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,
|
||||
* 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_existing_timeouts_(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
|
||||
* reset the read timeout (if any). */
|
||||
#define BEV_RESET_GENERIC_READ_TIMEOUT(bev) \
|
||||
|
@ -777,7 +777,7 @@ bufferevent_finalize_cb_(struct event_callback *evcb, void *arg_)
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_decref_(struct bufferevent *bufev)
|
||||
bufferevent_decref(struct bufferevent *bufev)
|
||||
{
|
||||
BEV_LOCK(bufev);
|
||||
return bufferevent_decref_and_unlock_(bufev);
|
||||
@ -793,11 +793,15 @@ bufferevent_free(struct bufferevent *bufev)
|
||||
}
|
||||
|
||||
void
|
||||
bufferevent_incref_(struct bufferevent *bufev)
|
||||
bufferevent_incref(struct bufferevent *bufev)
|
||||
{
|
||||
struct bufferevent_private *bufev_private =
|
||||
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);
|
||||
++bufev_private->refcnt;
|
||||
BEV_UNLOCK(bufev);
|
||||
@ -965,10 +969,33 @@ bufferevent_generic_adj_timeouts_(struct bufferevent *bev)
|
||||
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
|
||||
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);
|
||||
else
|
||||
return event_add(ev, tv);
|
||||
|
@ -536,10 +536,20 @@ be_filter_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op,
|
||||
bevf = upcast(bev);
|
||||
data->ptr = bevf->underlying;
|
||||
return 0;
|
||||
case BEV_CTRL_GET_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:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -320,8 +320,6 @@ struct bufferevent_openssl {
|
||||
unsigned write_blocked_on_read : 1;
|
||||
/* Treat TCP close before SSL close on SSL >= v3 as clean EOF. */
|
||||
unsigned allow_dirty_shutdown : 1;
|
||||
/* XXXX */
|
||||
unsigned fd_is_set : 1;
|
||||
/* XXX */
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
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 {
|
||||
struct bufferevent *bev = &bev_ssl->bev.bev;
|
||||
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 (bev_ssl->fd_is_set) {
|
||||
|
||||
if (event_initialized(&bev->ev_read)) {
|
||||
rpending = event_pending(&bev->ev_read, EV_READ, NULL);
|
||||
wpending = event_pending(&bev->ev_write, EV_WRITE, NULL);
|
||||
|
||||
event_del(&bev->ev_read);
|
||||
event_del(&bev->ev_write);
|
||||
}
|
||||
|
||||
event_assign(&bev->ev_read, bev->ev_base, fd,
|
||||
EV_READ|EV_PERSIST|EV_FINALIZE,
|
||||
be_openssl_readeventcb, bev_ssl);
|
||||
event_assign(&bev->ev_write, bev->ev_base, fd,
|
||||
EV_WRITE|EV_PERSIST|EV_FINALIZE,
|
||||
be_openssl_writeeventcb, bev_ssl);
|
||||
|
||||
if (rpending)
|
||||
r1 = bufferevent_add_event_(&bev->ev_read, &bev->timeout_read);
|
||||
if (wpending)
|
||||
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;
|
||||
}
|
||||
}
|
||||
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
|
||||
do_handshake(struct bufferevent_openssl *bev_ssl)
|
||||
@ -1011,9 +1027,10 @@ do_handshake(struct bufferevent_openssl *bev_ssl)
|
||||
decrement_buckets(bev_ssl);
|
||||
|
||||
if (r==1) {
|
||||
int fd = event_get_fd(&bev_ssl->bev.bev.ev_read);
|
||||
/* We're done! */
|
||||
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 */
|
||||
bufferevent_enable(&bev_ssl->bev.bev, bev_ssl->bev.bev.enabled);
|
||||
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);
|
||||
} else {
|
||||
struct bufferevent *bev = &bev_ssl->bev.bev;
|
||||
int r1=0, r2=0;
|
||||
if (fd < 0 && bev_ssl->fd_is_set)
|
||||
fd = event_get_fd(&bev->ev_read);
|
||||
if (bev_ssl->fd_is_set) {
|
||||
|
||||
if (event_initialized(&bev->ev_read)) {
|
||||
event_del(&bev->ev_read);
|
||||
event_del(&bev->ev_write);
|
||||
}
|
||||
|
||||
event_assign(&bev->ev_read, bev->ev_base, fd,
|
||||
EV_READ|EV_PERSIST|EV_FINALIZE,
|
||||
be_openssl_handshakeeventcb, bev_ssl);
|
||||
event_assign(&bev->ev_write, bev->ev_base, fd,
|
||||
EV_WRITE|EV_PERSIST|EV_FINALIZE,
|
||||
be_openssl_handshakeeventcb, bev_ssl);
|
||||
if (fd >= 0) {
|
||||
r1 = bufferevent_add_event_(&bev->ev_read, &bev->timeout_read);
|
||||
r2 = bufferevent_add_event_(&bev->ev_write, &bev->timeout_write);
|
||||
bev_ssl->fd_is_set = 1;
|
||||
}
|
||||
return (r1<0 || r2<0) ? -1 : 0;
|
||||
if (fd >= 0)
|
||||
bufferevent_enable(bev, bev->enabled);
|
||||
return 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
|
||||
bufferevent_ssl_renegotiate(struct bufferevent *bev)
|
||||
{
|
||||
@ -1104,7 +1124,7 @@ bufferevent_ssl_renegotiate(struct bufferevent *bev)
|
||||
if (SSL_renegotiate(bev_ssl->ssl) < 0)
|
||||
return -1;
|
||||
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;
|
||||
if (!bev_ssl->underlying)
|
||||
return do_handshake(bev_ssl);
|
||||
@ -1119,14 +1139,13 @@ be_openssl_outbuf_cb(struct evbuffer *buf,
|
||||
int r = 0;
|
||||
/* XXX need to hold a reference here. */
|
||||
|
||||
if (cbinfo->n_added && bev_ssl->state == BUFFEREVENT_SSL_OPEN) {
|
||||
if (cbinfo->orig_size == 0)
|
||||
r = bufferevent_add_event_(&bev_ssl->bev.bev.ev_write,
|
||||
&bev_ssl->bev.bev.timeout_write);
|
||||
consider_writing(bev_ssl);
|
||||
if (cbinfo->n_added && bev_ssl->state == BUFFEREVENT_SSL_OPEN &&
|
||||
cbinfo->orig_size == 0) {
|
||||
r = bufferevent_add_event_(&bev_ssl->bev.bev.ev_write,
|
||||
&bev_ssl->bev.bev.timeout_write);
|
||||
}
|
||||
/* 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);
|
||||
int r1 = 0, r2 = 0;
|
||||
|
||||
if (bev_ssl->state != BUFFEREVENT_SSL_OPEN)
|
||||
return 0;
|
||||
|
||||
if (events & EV_READ)
|
||||
r1 = start_reading(bev_ssl);
|
||||
if (events & EV_WRITE)
|
||||
@ -1162,8 +1178,6 @@ static int
|
||||
be_openssl_disable(struct bufferevent *bev, short events)
|
||||
{
|
||||
struct bufferevent_openssl *bev_ssl = upcast(bev);
|
||||
if (bev_ssl->state != BUFFEREVENT_SSL_OPEN)
|
||||
return 0;
|
||||
|
||||
if (events & EV_READ)
|
||||
stop_reading(bev_ssl);
|
||||
@ -1233,23 +1247,7 @@ be_openssl_adj_timeouts(struct bufferevent *bev)
|
||||
if (bev_ssl->underlying) {
|
||||
return bufferevent_generic_adj_timeouts_(bev);
|
||||
} else {
|
||||
int r1=0, r2=0;
|
||||
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;
|
||||
return bufferevent_generic_adj_existing_timeouts_(bev);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1274,25 +1272,16 @@ be_openssl_ctrl(struct bufferevent *bev,
|
||||
BIO *bio;
|
||||
bio = BIO_new_socket(data->fd, 0);
|
||||
SSL_set_bio(bev_ssl->ssl, bio, bio);
|
||||
bev_ssl->fd_is_set = 1;
|
||||
}
|
||||
if (data->fd == -1)
|
||||
bev_ssl->fd_is_set = 0;
|
||||
if (bev_ssl->state == BUFFEREVENT_SSL_OPEN)
|
||||
if (bev_ssl->state == BUFFEREVENT_SSL_OPEN && data->fd >= 0)
|
||||
return set_open_callbacks(bev_ssl, data->fd);
|
||||
else {
|
||||
return set_handshake_callbacks(bev_ssl, data->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);
|
||||
return 0;
|
||||
case BEV_CTRL_GET_UNDERLYING:
|
||||
if (!bev_ssl->underlying)
|
||||
return -1;
|
||||
data->ptr = bev_ssl->underlying;
|
||||
return 0;
|
||||
case BEV_CTRL_CANCEL_ALL:
|
||||
@ -1360,16 +1349,16 @@ bufferevent_openssl_new_impl(struct event_base *base,
|
||||
switch (state) {
|
||||
case BUFFEREVENT_SSL_ACCEPTING:
|
||||
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;
|
||||
break;
|
||||
case BUFFEREVENT_SSL_CONNECTING:
|
||||
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;
|
||||
break;
|
||||
case BUFFEREVENT_SSL_OPEN:
|
||||
if (set_open_callbacks(bev_ssl, fd) < 0)
|
||||
if (set_open_callbacks_auto(bev_ssl, fd) < 0)
|
||||
goto err;
|
||||
break;
|
||||
default:
|
||||
@ -1382,15 +1371,6 @@ bufferevent_openssl_new_impl(struct event_base *base,
|
||||
if (state == BUFFEREVENT_SSL_OPEN)
|
||||
bufferevent_suspend_read_(underlying,
|
||||
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;
|
||||
|
@ -307,15 +307,17 @@ be_pair_flush(struct bufferevent *bev, short iotype,
|
||||
{
|
||||
struct bufferevent_pair *bev_p = upcast(bev);
|
||||
struct bufferevent *partner;
|
||||
incref_and_lock(bev);
|
||||
|
||||
if (!bev_p->partner)
|
||||
return -1;
|
||||
|
||||
partner = downcast(bev_p->partner);
|
||||
|
||||
if (mode == BEV_NORMAL)
|
||||
return 0;
|
||||
|
||||
incref_and_lock(bev);
|
||||
|
||||
partner = downcast(bev_p->partner);
|
||||
|
||||
if ((iotype & EV_READ) != 0)
|
||||
be_pair_transfer(partner, bev, 1);
|
||||
|
||||
|
@ -79,7 +79,6 @@
|
||||
static int be_socket_enable(struct bufferevent *, short);
|
||||
static int be_socket_disable(struct bufferevent *, short);
|
||||
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_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,
|
||||
NULL, /* unlink */
|
||||
be_socket_destruct,
|
||||
be_socket_adj_timeouts,
|
||||
bufferevent_generic_adj_existing_timeouts_,
|
||||
be_socket_flush,
|
||||
be_socket_ctrl,
|
||||
};
|
||||
|
||||
#define be_socket_add(ev, t) \
|
||||
bufferevent_add_event_((ev), (t))
|
||||
const struct sockaddr*
|
||||
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
|
||||
bufferevent_socket_outbuf_cb(struct evbuffer *buf,
|
||||
@ -115,7 +136,7 @@ bufferevent_socket_outbuf_cb(struct evbuffer *buf,
|
||||
!bufev_p->write_suspended) {
|
||||
/* Somebody added data to the buffer, and we would like to
|
||||
* 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? */
|
||||
}
|
||||
}
|
||||
@ -239,6 +260,7 @@ bufferevent_writecb(evutil_socket_t fd, short event, void *arg)
|
||||
goto done;
|
||||
} else {
|
||||
connected = 1;
|
||||
bufferevent_socket_set_conn_address_fd(bufev_p, fd);
|
||||
#ifdef _WIN32
|
||||
if (BEV_IS_ASYNC(bufev)) {
|
||||
event_del(&bufev->ev_write);
|
||||
@ -351,7 +373,7 @@ bufferevent_socket_new(struct event_base *base, evutil_socket_t fd,
|
||||
|
||||
int
|
||||
bufferevent_socket_connect(struct bufferevent *bev,
|
||||
struct sockaddr *sa, int socklen)
|
||||
const struct sockaddr *sa, int socklen)
|
||||
{
|
||||
struct bufferevent_private *bufev_p =
|
||||
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 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);
|
||||
(void)r;
|
||||
bufferevent_decref_and_unlock_(bev);
|
||||
@ -478,23 +501,23 @@ bufferevent_socket_connect_hostname(struct bufferevent *bev,
|
||||
if (port < 1 || port > 65535)
|
||||
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));
|
||||
hint.ai_family = family;
|
||||
hint.ai_protocol = IPPROTO_TCP;
|
||||
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_read_(bev, BEV_SUSPEND_LOOKUP);
|
||||
|
||||
bufferevent_incref_(bev);
|
||||
err = evutil_getaddrinfo_async_(evdns_base, hostname, portbuf,
|
||||
&hint, bufferevent_connect_getaddrinfo_cb, bev);
|
||||
BEV_UNLOCK(bev);
|
||||
|
||||
if (err == 0) {
|
||||
return 0;
|
||||
@ -550,14 +573,12 @@ bufferevent_new(evutil_socket_t fd,
|
||||
static int
|
||||
be_socket_enable(struct bufferevent *bufev, short event)
|
||||
{
|
||||
if (event & EV_READ) {
|
||||
if (be_socket_add(&bufev->ev_read,&bufev->timeout_read) == -1)
|
||||
if (event & EV_READ &&
|
||||
bufferevent_add_event_(&bufev->ev_read, &bufev->timeout_read) == -1)
|
||||
return -1;
|
||||
}
|
||||
if (event & EV_WRITE) {
|
||||
if (be_socket_add(&bufev->ev_write,&bufev->timeout_write) == -1)
|
||||
if (event & EV_WRITE &&
|
||||
bufferevent_add_event_(&bufev->ev_write, &bufev->timeout_write) == -1)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -592,29 +613,6 @@ be_socket_destruct(struct bufferevent *bufev)
|
||||
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
|
||||
be_socket_flush(struct bufferevent *bev, short iotype,
|
||||
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 \
|
||||
usleep \
|
||||
vasprintf \
|
||||
getservbyname \
|
||||
])
|
||||
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()?])
|
||||
else
|
||||
|
||||
AC_CHECK_FUNCS([getservbyname])
|
||||
# Check for gethostbyname_r in all its glorious incompatible versions.
|
||||
# (This is cut-and-pasted from Tor, which based its logic on
|
||||
# Python's configure.in.)
|
||||
@ -763,6 +763,10 @@ fi
|
||||
|
||||
# check if we have and should use openssl
|
||||
AM_CONDITIONAL(OPENSSL, [test "$enable_openssl" != "no" && test "$have_openssl" = "yes"])
|
||||
if test "x$enable_openssl" = "xyes"; then
|
||||
AC_SEARCH_LIBS([ERR_remove_thread_state], [crypto],
|
||||
[AC_DEFINE(HAVE_ERR_REMOVE_THREAD_STATE, 1, [Define to 1 if you have ERR_remove_thread_stat().])])
|
||||
fi
|
||||
|
||||
# Add some more warnings which we use in development but not in the
|
||||
# released versions. (Some relevant gcc versions can't handle these.)
|
||||
|
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
|
||||
epoll_apply_one_change(struct event_base *base,
|
||||
struct epollop *epollop,
|
||||
@ -271,14 +288,7 @@ epoll_apply_one_change(struct event_base *base,
|
||||
epev.data.fd = ch->fd;
|
||||
epev.events = events;
|
||||
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]",
|
||||
epoll_op_to_string(op),
|
||||
(int)epev.events,
|
||||
(int)ch->fd,
|
||||
ch->old_events,
|
||||
ch->read_change,
|
||||
ch->write_change,
|
||||
ch->close_change));
|
||||
event_debug((PRINT_CHANGES(op, epev.events, ch, "okay")));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -338,18 +348,7 @@ epoll_apply_one_change(struct event_base *base,
|
||||
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)",
|
||||
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));
|
||||
|
||||
event_warn(PRINT_CHANGES(op, epev.events, ch, "failed"));
|
||||
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) \
|
||||
goto err; \
|
||||
} 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;
|
||||
|
||||
@ -1086,9 +1068,25 @@ reply_parse(struct evdns_base *base, u8 *packet, int length) {
|
||||
/* the question looks like
|
||||
* <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;
|
||||
if (j > length) goto err;
|
||||
if (j > length)
|
||||
goto err;
|
||||
}
|
||||
|
||||
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. */
|
||||
|
||||
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) {
|
||||
while (base->req_heads[i]) {
|
||||
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;
|
||||
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
EVDNS_LOCK(data->evdns_base);
|
||||
if (evdns_result_is_answer(result)) {
|
||||
if (req->type == DNS_IPv4_A)
|
||||
++data->evdns_base->getaddrinfo_ipv4_answered;
|
||||
else
|
||||
++data->evdns_base->getaddrinfo_ipv6_answered;
|
||||
/** Called from evdns_base_free() with @fail_requests == 1 */
|
||||
if (result != DNS_ERR_SHUTDOWN) {
|
||||
EVDNS_LOCK(data->evdns_base);
|
||||
if (evdns_result_is_answer(result)) {
|
||||
if (req->type == DNS_IPv4_A)
|
||||
++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;
|
||||
|
||||
@ -4450,7 +4453,9 @@ evdns_getaddrinfo_gotresolve(int result, char type, int count,
|
||||
/* The other request is still working; maybe it will
|
||||
* succeed. */
|
||||
/* 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;
|
||||
return;
|
||||
}
|
||||
|
@ -11,8 +11,11 @@
|
||||
|
||||
/* Numeric representation of the 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 */
|
||||
#define EVENT__VERSION "@EVENT_VERSION@"
|
||||
@ -33,467 +36,499 @@
|
||||
#define EVENT__PACKAGE_TARNAME ""
|
||||
|
||||
/* 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 */
|
||||
#cmakedefine EVENT__DISABLE_MM_REPLACEMENT 0
|
||||
#cmakedefine EVENT__DISABLE_MM_REPLACEMENT
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_ACCEPT4 1
|
||||
#cmakedefine EVENT__HAVE_ACCEPT4
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_ARC4RANDOM_BUF 1
|
||||
#cmakedefine EVENT__HAVE_ARC4RANDOM_BUF
|
||||
|
||||
/* 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 */
|
||||
#cmakedefine EVENT__DNS_USE_GETTIMEOFDAY_FOR_ID 1
|
||||
#cmakedefine EVENT__DNS_USE_FTIME_FOR_ID 1
|
||||
#cmakedefine EVENT__DNS_USE_GETTIMEOFDAY_FOR_ID
|
||||
#cmakedefine EVENT__DNS_USE_FTIME_FOR_ID
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_CLOCK_GETTIME 1
|
||||
#cmakedefine EVENT__HAVE_CLOCK_GETTIME
|
||||
|
||||
/* 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'. */
|
||||
#cmakedefine EVENT__HAVE_DECL_KERN_ARND 0
|
||||
#cmakedefine EVENT__HAVE_DECL_KERN_ARND
|
||||
|
||||
/* 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 */
|
||||
#cmakedefine EVENT__HAVE_DEVPOLL 1
|
||||
#cmakedefine EVENT__HAVE_DEVPOLL
|
||||
|
||||
/* 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 */
|
||||
#cmakedefine EVENT__HAVE_FD_MASK 1
|
||||
#cmakedefine EVENT__HAVE_FD_MASK
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_DLFCN_H 1
|
||||
#cmakedefine EVENT__HAVE_DLFCN_H
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_EPOLL_CREATE1 1
|
||||
#cmakedefine EVENT__HAVE_EPOLL_CREATE1
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_EVENTFD 1
|
||||
#cmakedefine EVENT__HAVE_EVENTFD
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_FCNTL 1
|
||||
#cmakedefine EVENT__HAVE_FCNTL
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_GETADDRINFO 1
|
||||
#cmakedefine EVENT__HAVE_GETADDRINFO
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_GETEUID 1
|
||||
#cmakedefine EVENT__HAVE_GETEUID
|
||||
|
||||
/* TODO: Check for different gethostname argument counts. CheckPrototypeDefinition.cmake can be used. */
|
||||
/* Define this if you have any gethostbyname_r() */
|
||||
#cmakedefine EVENT__HAVE_GETHOSTBYNAME_R 1
|
||||
#cmakedefine EVENT__HAVE_GETHOSTBYNAME_R
|
||||
|
||||
/* 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 */
|
||||
#cmakedefine EVENT__HAVE_GETHOSTBYNAME_R_5_ARG 1
|
||||
#cmakedefine EVENT__HAVE_GETHOSTBYNAME_R_5_ARG
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_GETIFADDRS 1
|
||||
#cmakedefine EVENT__HAVE_GETIFADDRS
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_GETPROTOBYNUMBER 1
|
||||
#cmakedefine EVENT__HAVE_GETPROTOBYNUMBER
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_GETTIMEOFDAY 1
|
||||
#cmakedefine EVENT__HAVE_GETTIMEOFDAY
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_INET_NTOP 1
|
||||
#cmakedefine EVENT__HAVE_INET_NTOP
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_INTTYPES_H 1
|
||||
#cmakedefine EVENT__HAVE_INTTYPES_H
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_KQUEUE 1
|
||||
#cmakedefine EVENT__HAVE_KQUEUE
|
||||
|
||||
/* 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. */
|
||||
#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. */
|
||||
#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. */
|
||||
#cmakedefine EVENT__HAVE_MEMORY_H 1
|
||||
#cmakedefine EVENT__HAVE_MEMORY_H
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_NANOSLEEP 1
|
||||
#cmakedefine EVENT__HAVE_NANOSLEEP
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_NETDB_H 1
|
||||
#cmakedefine EVENT__HAVE_NETDB_H
|
||||
|
||||
/* 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. */
|
||||
#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. */
|
||||
#cmakedefine EVENT__HAVE_NETINET_TCP_H 1
|
||||
#cmakedefine EVENT__HAVE_NETINET_TCP_H
|
||||
|
||||
/* Define if the system has openssl */
|
||||
#cmakedefine EVENT__HAVE_OPENSSL 1
|
||||
#cmakedefine EVENT__HAVE_OPENSSL
|
||||
|
||||
/* Defines if the system has zlib */
|
||||
#cmakedefine EVENT__HAVE_ZLIB 1
|
||||
#cmakedefine EVENT__HAVE_ZLIB
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_PIPE2 1
|
||||
#cmakedefine EVENT__HAVE_PIPE2
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_POLL_H 1
|
||||
#cmakedefine EVENT__HAVE_POLL_H
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_PORT_H 1
|
||||
#cmakedefine EVENT__HAVE_PORT_H
|
||||
|
||||
/* 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 */
|
||||
#cmakedefine EVENT__HAVE_PTHREADS 1
|
||||
#cmakedefine EVENT__HAVE_PTHREADS
|
||||
|
||||
/* 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'. */
|
||||
#cmakedefine EVENT__HAVE_SA_FAMILY_T 1
|
||||
#cmakedefine EVENT__HAVE_SA_FAMILY_T
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_SETENV 1
|
||||
#cmakedefine EVENT__HAVE_SETENV
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_SETRLIMIT 1
|
||||
#cmakedefine EVENT__HAVE_SETRLIMIT
|
||||
|
||||
/* 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> */
|
||||
#cmakedefine EVENT__HAVE_SETFD 1
|
||||
#cmakedefine EVENT__HAVE_SETFD
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_SIGNAL 1
|
||||
#cmakedefine EVENT__HAVE_SIGNAL
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_STDARG_H 1
|
||||
#cmakedefine EVENT__HAVE_STDARG_H
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_STDINT_H 1
|
||||
#cmakedefine EVENT__HAVE_STDINT_H
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_STRINGS_H 1
|
||||
#cmakedefine EVENT__HAVE_STRINGS_H
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_STRLCPY 1
|
||||
#cmakedefine EVENT__HAVE_STRLCPY
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_STRTOK_R 1
|
||||
#cmakedefine EVENT__HAVE_STRTOK_R
|
||||
|
||||
/* 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'. */
|
||||
#cmakedefine EVENT__HAVE_STRUCT_ADDRINFO 1
|
||||
#cmakedefine EVENT__HAVE_STRUCT_ADDRINFO
|
||||
|
||||
/* 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'. */
|
||||
#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'. */
|
||||
#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'. */
|
||||
#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'. */
|
||||
#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'. */
|
||||
#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'. */
|
||||
#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'. */
|
||||
#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'. */
|
||||
#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. */
|
||||
#cmakedefine EVENT__HAVE_SYSCTL 1
|
||||
#cmakedefine EVENT__HAVE_SYSCTL
|
||||
|
||||
/* 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. */
|
||||
#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. */
|
||||
#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. */
|
||||
#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. */
|
||||
#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. */
|
||||
#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. */
|
||||
#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. */
|
||||
#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. */
|
||||
#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. */
|
||||
#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. */
|
||||
#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. */
|
||||
#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. */
|
||||
#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. */
|
||||
#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. */
|
||||
#cmakedefine EVENT__HAVE_SYS_TIMERFD_H */
|
||||
|
||||
/* 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. */
|
||||
#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. */
|
||||
#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. */
|
||||
#cmakedefine EVENT__HAVE_SYS_WAIT_H 1
|
||||
#cmakedefine EVENT__HAVE_SYS_WAIT_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> */
|
||||
#cmakedefine EVENT__HAVE_TIMERADD 1
|
||||
#cmakedefine EVENT__HAVE_TIMERADD
|
||||
|
||||
/* 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> */
|
||||
#cmakedefine EVENT__HAVE_TIMERCMP 1
|
||||
#cmakedefine EVENT__HAVE_TIMERCMP
|
||||
|
||||
/* 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> */
|
||||
#cmakedefine EVENT__HAVE_TIMERISSET 1
|
||||
#cmakedefine EVENT__HAVE_TIMERISSET
|
||||
|
||||
/* 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'. */
|
||||
#cmakedefine EVENT__HAVE_UINT16_T 1
|
||||
#cmakedefine EVENT__HAVE_UINT16_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'. */
|
||||
#cmakedefine EVENT__HAVE_UINT64_T 1
|
||||
#cmakedefine EVENT__HAVE_UINT64_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. */
|
||||
#cmakedefine EVENT__HAVE_UMASK 1
|
||||
#cmakedefine EVENT__HAVE_UMASK
|
||||
|
||||
/* 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. */
|
||||
#cmakedefine EVENT__HAVE_UNSETENV 1
|
||||
#cmakedefine EVENT__HAVE_UNSETENV
|
||||
|
||||
/* 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 */
|
||||
#cmakedefine EVENT__HAVE_WORKING_KQUEUE 1
|
||||
#cmakedefine EVENT__HAVE_WORKING_KQUEUE
|
||||
|
||||
/* Define to necessary symbol if this constant uses a non-standard name on
|
||||
your system. */
|
||||
#cmakedefine EVENT__PTHREAD_CREATE_JOINABLE ${EVENT__PTHREAD_CREATE_JOINABLE}
|
||||
#ifdef __USE_UNUSED_DEFINITIONS__
|
||||
/* Define to necessary symbol if this constant uses a non-standard name on your system. */
|
||||
/* 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. */
|
||||
#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. */
|
||||
#cmakedefine EVENT__SIZEOF_INT ${EVENT__SIZEOF_INT}
|
||||
#define EVENT__SIZEOF_INT @EVENT__SIZEOF_INT@
|
||||
|
||||
/* 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. */
|
||||
#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. */
|
||||
#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. */
|
||||
#cmakedefine EVENT__SIZEOF_SHORT ${EVENT__SIZEOF_SHORT}
|
||||
#define EVENT__SIZEOF_SHORT @EVENT__SIZEOF_SHORT@
|
||||
|
||||
/* 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. */
|
||||
#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>. */
|
||||
#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. */
|
||||
#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 */
|
||||
#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__ */
|
||||
#cmakedefine EVENT____func__ ${EVENT____func__}
|
||||
/* set an alias for whatever __func__ __FUNCTION__ is, what sillyness */
|
||||
#if defined (__func__)
|
||||
#define EVENT____func__ __func__
|
||||
#elif defined(__FUNCTION__)
|
||||
#define EVENT____func__ __FUNCTION__
|
||||
#else
|
||||
#define EVENT____func__ __FILE__
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __THESE_ARE_NOT_CONFIG_H_THINGS_THEY_ARE_DASH_D_THINGS__
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
#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. */
|
||||
/* #undef _LARGE_FILES */
|
||||
#define @_LARGE_FILES@
|
||||
#endif
|
||||
|
||||
#ifdef _WhAT_DOES_THIS_EVEN_DO_
|
||||
/* 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
|
||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||
#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
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
#cmakedefine EVENT__pid_t ${EVENT__pid_t}
|
||||
/* Define to `int' if <sys/tyes.h> does not define. */
|
||||
#define EVENT__pid_t @EVENT__pid_t@
|
||||
|
||||
/* 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 */
|
||||
#cmakedefine EVENT__socklen_t ${EVENT__socklen_t}
|
||||
#define EVENT__socklen_t @EVENT__socklen_t@
|
||||
|
||||
/* 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
|
||||
|
@ -368,7 +368,6 @@ struct event_config {
|
||||
};
|
||||
|
||||
/* 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
|
||||
#define TAILQ_FIRST(head) ((head)->tqh_first)
|
||||
#endif
|
||||
@ -394,7 +393,6 @@ struct event_config {
|
||||
(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
|
||||
} while (0)
|
||||
#endif
|
||||
#endif /* TAILQ_FOREACH */
|
||||
|
||||
#define N_ACTIVE_CALLBACKS(base) \
|
||||
((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,
|
||||
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
|
||||
}
|
||||
#endif
|
||||
|
6
event.3
6
event.3
@ -183,14 +183,14 @@
|
||||
.Fn "evbuffer_write" "struct evbuffer *buf" "int fd"
|
||||
.Ft int
|
||||
.Fn "evbuffer_read" "struct evbuffer *buf" "int fd" "int size"
|
||||
.Ft "u_char *"
|
||||
.Fn "evbuffer_find" "struct evbuffer *buf" "const u_char *data" "size_t size"
|
||||
.Ft "unsigned char *"
|
||||
.Fn "evbuffer_find" "struct evbuffer *buf" "const unsigned char *data" "size_t size"
|
||||
.Ft "char *"
|
||||
.Fn "evbuffer_readline" "struct evbuffer *buf"
|
||||
.Ft "struct evhttp *"
|
||||
.Fn "evhttp_new" "struct event_base *base"
|
||||
.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"
|
||||
.Fn "evhttp_free" "struct evhttp *http"
|
||||
.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;
|
||||
|
||||
|
||||
#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. */
|
||||
static int event_debug_mode_too_late = 0;
|
||||
#ifndef EVENT__DISABLE_THREAD_SUPPORT
|
||||
@ -655,6 +671,10 @@ event_base_new_with_config(const struct event_config *cfg)
|
||||
|
||||
/* 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
|
||||
if (EVTHREAD_LOCKING_ENABLED() &&
|
||||
(!cfg || !(cfg->flags & EVENT_BASE_FLAG_NOLOCK))) {
|
||||
@ -749,6 +769,29 @@ event_base_cancel_single_callback_(struct event_base *base,
|
||||
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
|
||||
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)
|
||||
mm_free(base->common_timeout_queues);
|
||||
|
||||
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);
|
||||
n_deleted += event_base_cancel_single_callback_(base, evcb, run_finalizers);
|
||||
evcb = next;
|
||||
for (;;) {
|
||||
/* For finalizers we can register yet another finalizer out from
|
||||
* finalizer, and iff finalizer will be in active_later_queue we can
|
||||
* add finalizer to activequeues, and we will have events in
|
||||
* activequeues after this function returns, which is not what we want
|
||||
* (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)
|
||||
event_debug(("%s: %d events were still set in base",
|
||||
|
@ -40,10 +40,11 @@
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#else
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#ifdef EVENT__HAVE_SYS_IOCTL_H
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#include <sys/queue.h>
|
||||
#ifdef EVENT__HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
|
48
evthread.c
48
evthread.c
@ -45,6 +45,11 @@
|
||||
#define GLOBAL static
|
||||
#endif
|
||||
|
||||
#ifndef EVENT__DISABLE_DEBUG_MODE
|
||||
extern int event_debug_created_threadable_ctx_;
|
||||
extern int event_debug_mode_on_;
|
||||
#endif
|
||||
|
||||
/* globals */
|
||||
GLOBAL int evthread_lock_debugging_enabled_ = 0;
|
||||
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();
|
||||
|
||||
#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 (target->alloc)
|
||||
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();
|
||||
|
||||
#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 (target->alloc_condition)
|
||||
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);
|
||||
} else {
|
||||
/* 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 &&
|
||||
evthread_lock_debugging_enabled_);
|
||||
EVUTIL_ASSERT(lock->locktype == locktype);
|
||||
EVUTIL_ASSERT(lock->lock == NULL);
|
||||
lock->lock = original_lock_fns_.alloc(
|
||||
locktype|EVTHREAD_LOCKTYPE_RECURSIVE);
|
||||
if (!lock->lock) {
|
||||
lock->count = -200;
|
||||
mm_free(lock);
|
||||
return NULL;
|
||||
lock->lock = original_lock_fns_.alloc(
|
||||
locktype|EVTHREAD_LOCKTYPE_RECURSIVE);
|
||||
if (!lock->lock) {
|
||||
lock->count = -200;
|
||||
mm_free(lock);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return lock;
|
||||
}
|
||||
@ -406,6 +428,12 @@ evthreadimpl_get_id_()
|
||||
void *
|
||||
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 ?
|
||||
evthread_lock_fns_.alloc(locktype) : NULL;
|
||||
}
|
||||
@ -434,6 +462,12 @@ evthreadimpl_lock_unlock_(unsigned mode, void *lock)
|
||||
void *
|
||||
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 ?
|
||||
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;
|
||||
ev_socklen_t size;
|
||||
int saved_errno = -1;
|
||||
|
||||
if (protocol
|
||||
|| (family != AF_INET
|
||||
int family_test;
|
||||
|
||||
family_test = family != AF_INET;
|
||||
#ifdef AF_UNIX
|
||||
&& family != AF_UNIX
|
||||
family_test = family_test && (family != AF_UNIX);
|
||||
#endif
|
||||
)) {
|
||||
if (protocol || family_test) {
|
||||
EVUTIL_SET_SOCKET_ERROR(ERR(EAFNOSUPPORT));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!fd) {
|
||||
EVUTIL_SET_SOCKET_ERROR(ERR(EINVAL));
|
||||
return -1;
|
||||
@ -257,6 +258,9 @@ evutil_ersatz_socketpair_(int family, int type, int protocol,
|
||||
connector = socket(AF_INET, type, 0);
|
||||
if (connector < 0)
|
||||
goto tidy_up_and_fail;
|
||||
|
||||
memset(&connect_addr, 0, sizeof(connect_addr));
|
||||
|
||||
/* We want to find out the port number to connect to. */
|
||||
size = sizeof(connect_addr);
|
||||
if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1)
|
||||
@ -310,7 +314,7 @@ evutil_make_socket_nonblocking(evutil_socket_t fd)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
{
|
||||
u_long nonblocking = 1;
|
||||
unsigned long nonblocking = 1;
|
||||
if (ioctlsocket(fd, FIONBIO, &nonblocking) == SOCKET_ERROR) {
|
||||
event_sock_warn(fd, "fcntl(%d, F_GETFL)", (int)fd);
|
||||
return -1;
|
||||
@ -355,7 +359,7 @@ evutil_fast_socket_nonblocking(evutil_socket_t fd)
|
||||
int
|
||||
evutil_make_listen_socket_reuseable(evutil_socket_t sock)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
#if defined(SO_REUSEADDR) && !defined(_WIN32)
|
||||
int one = 1;
|
||||
/* 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
|
||||
@ -520,7 +524,7 @@ evutil_socket_geterror(evutil_socket_t sock)
|
||||
/* XXX we should use an enum here. */
|
||||
/* 2 for connection refused, 1 for connected, 0 for not yet, -1 for error. */
|
||||
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;
|
||||
|
||||
@ -1159,7 +1163,7 @@ addrinfo_from_hostent(const struct hostent *ent,
|
||||
sin6.sin6_family = AF_INET6;
|
||||
sin6.sin6_port = htons(port);
|
||||
sa = (struct sockaddr *)&sin6;
|
||||
socklen = sizeof(struct sockaddr_in);
|
||||
socklen = sizeof(struct sockaddr_in6);
|
||||
addrp = &sin6.sin6_addr;
|
||||
if (ent->h_length != sizeof(sin6.sin6_addr)) {
|
||||
event_warnx("Weird h_length from gethostbyname");
|
||||
@ -1705,10 +1709,10 @@ evutil_socket_error_to_string(int errcode)
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (0 != FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
if (0 != FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS |
|
||||
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 */
|
||||
else {
|
||||
size_t len = 50;
|
||||
|
@ -62,10 +62,10 @@ struct evhttp_connection {
|
||||
struct event retry_ev; /* for retrying connects */
|
||||
|
||||
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 */
|
||||
u_short port;
|
||||
unsigned short port;
|
||||
|
||||
size_t max_headers_size;
|
||||
ev_uint64_t max_body_size;
|
||||
@ -101,13 +101,6 @@ struct evhttp_connection {
|
||||
struct event_base *base;
|
||||
struct evdns_base *dns_base;
|
||||
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 */
|
||||
|
139
http.c
139
http.c
@ -35,18 +35,22 @@
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#ifdef EVENT__HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_IOCCOM_H
|
||||
#include <sys/ioccom.h>
|
||||
#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
|
||||
#include <sys/resource.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#else
|
||||
#include <winsock2.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);
|
||||
}
|
||||
}
|
||||
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' */
|
||||
static int
|
||||
@ -674,6 +685,23 @@ evhttp_connection_incoming_fail(struct evhttp_request *req,
|
||||
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
|
||||
* given in error. If it's an outgoing connection, reset the connection,
|
||||
* 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,
|
||||
* all other pending requests should be processed as normal
|
||||
*/
|
||||
TAILQ_REMOVE(&evcon->requests, req, next);
|
||||
evhttp_request_free(req);
|
||||
evhttp_request_free_(evcon, req);
|
||||
|
||||
/* reset the connection */
|
||||
evhttp_connection_reset_(evcon);
|
||||
@ -773,16 +800,12 @@ evhttp_connection_done(struct evhttp_connection *evcon)
|
||||
|
||||
if (con_outgoing) {
|
||||
/* idle or close the connection */
|
||||
int need_close;
|
||||
int need_close = evhttp_is_request_connection_close(req);
|
||||
TAILQ_REMOVE(&evcon->requests, req, next);
|
||||
req->evcon = NULL;
|
||||
|
||||
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 */
|
||||
if (need_close)
|
||||
evhttp_connection_reset_(evcon);
|
||||
@ -820,11 +843,9 @@ evhttp_connection_done(struct evhttp_connection *evcon)
|
||||
/* notify the user of the request */
|
||||
(*req->cb)(req, req->cb_arg);
|
||||
|
||||
/* 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 && ((req->flags & EVHTTP_USER_OWNED) == 0)) {
|
||||
evhttp_request_free(req);
|
||||
/* if this was an outgoing request, we own and it's done. so free it. */
|
||||
if (con_outgoing) {
|
||||
evhttp_request_free_auto(req);
|
||||
}
|
||||
|
||||
/* 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 REQUEST_CANCELED: /* ??? */
|
||||
default:
|
||||
bufferevent_enable(evcon->bufev, EV_READ);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -985,7 +1005,7 @@ evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
|
||||
return;
|
||||
case REQUEST_CANCELED:
|
||||
/* request canceled */
|
||||
evhttp_request_free(req);
|
||||
evhttp_request_free_auto(req);
|
||||
return;
|
||||
case MORE_DATA_EXPECTED:
|
||||
default:
|
||||
@ -1031,7 +1051,7 @@ evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
|
||||
evbuffer_drain(req->input_buffer,
|
||||
evbuffer_get_length(req->input_buffer));
|
||||
if ((req->flags & EVHTTP_REQ_NEEDS_FREE) != 0) {
|
||||
evhttp_request_free(req);
|
||||
evhttp_request_free_auto(req);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1042,9 +1062,6 @@ evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
|
||||
evhttp_connection_done(evcon);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Read more! */
|
||||
bufferevent_enable(evcon->bufev, EV_READ);
|
||||
}
|
||||
|
||||
#define get_deferred_queue(evcon) \
|
||||
@ -1125,6 +1142,9 @@ evhttp_write_connectioncb(struct evhttp_connection *evcon, void *arg)
|
||||
|
||||
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 */
|
||||
req->kind = EVHTTP_RESPONSE;
|
||||
|
||||
@ -1152,8 +1172,7 @@ evhttp_connection_free(struct evhttp_connection *evcon)
|
||||
* evhttp_connection_fail_.
|
||||
*/
|
||||
while ((req = TAILQ_FIRST(&evcon->requests)) != NULL) {
|
||||
TAILQ_REMOVE(&evcon->requests, req, next);
|
||||
evhttp_request_free(req);
|
||||
evhttp_request_free_(evcon, req);
|
||||
}
|
||||
|
||||
if (evcon->http_server != NULL) {
|
||||
@ -1173,6 +1192,7 @@ evhttp_connection_free(struct evhttp_connection *evcon)
|
||||
&evcon->read_more_deferred_cb);
|
||||
|
||||
if (evcon->fd != -1) {
|
||||
bufferevent_disable(evcon->bufev, EV_READ|EV_WRITE);
|
||||
shutdown(evcon->fd, EVUTIL_SHUT_WR);
|
||||
if (!(bufferevent_get_options_(evcon->bufev) & BEV_OPT_CLOSE_ON_FREE)) {
|
||||
evutil_closesocket(evcon->fd);
|
||||
@ -1185,9 +1205,6 @@ evhttp_connection_free(struct evhttp_connection *evcon)
|
||||
if (evcon->address != NULL)
|
||||
mm_free(evcon->address);
|
||||
|
||||
if (evcon->conn_address != NULL)
|
||||
mm_free(evcon->conn_address);
|
||||
|
||||
mm_free(evcon);
|
||||
}
|
||||
|
||||
@ -1352,7 +1369,7 @@ evhttp_connection_cb_cleanup(struct evhttp_connection *evcon)
|
||||
|
||||
/* we might want to set an error here */
|
||||
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;
|
||||
int error;
|
||||
ev_socklen_t errsz = sizeof(error);
|
||||
socklen_t conn_address_len = sizeof(*evcon->conn_address);
|
||||
|
||||
if (evcon->fd == -1)
|
||||
evcon->fd = bufferevent_getfd(bufev);
|
||||
@ -1492,14 +1508,6 @@ evhttp_connection_cb(struct bufferevent *bufev, short what, void *arg)
|
||||
evcon->retry_cnt = 0;
|
||||
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 */
|
||||
bufferevent_setcb(evcon->bufev,
|
||||
evhttp_read_cb,
|
||||
@ -2181,9 +2189,6 @@ evhttp_read_header(struct evhttp_connection *evcon,
|
||||
return;
|
||||
}
|
||||
|
||||
/* Disable reading for now */
|
||||
bufferevent_disable(evcon->bufev, EV_READ);
|
||||
|
||||
/* Callback can shut down connection with negative return value */
|
||||
if (req->header_cb != NULL) {
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
evhttp_connection_set_base(struct evhttp_connection *evcon,
|
||||
struct event_base *base)
|
||||
@ -2412,13 +2431,16 @@ evhttp_connection_get_peer(struct evhttp_connection *evcon,
|
||||
const struct sockaddr*
|
||||
evhttp_connection_get_addr(struct evhttp_connection *evcon)
|
||||
{
|
||||
return (struct sockaddr *)evcon->conn_address;
|
||||
return bufferevent_socket_get_conn_address_(evcon->bufev);
|
||||
}
|
||||
|
||||
int
|
||||
evhttp_connection_connect_(struct evhttp_connection *evcon)
|
||||
{
|
||||
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)
|
||||
return (0);
|
||||
@ -2450,17 +2472,29 @@ evhttp_connection_connect_(struct evhttp_connection *evcon)
|
||||
evcon);
|
||||
if (!evutil_timerisset(&evcon->timeout)) {
|
||||
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 {
|
||||
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 */
|
||||
bufferevent_enable(evcon->bufev, EV_WRITE);
|
||||
|
||||
evcon->state = EVCON_CONNECTING;
|
||||
|
||||
if (bufferevent_socket_connect_hostname(evcon->bufev, evcon->dns_base,
|
||||
evcon->ai_family, evcon->address, evcon->port) < 0) {
|
||||
if (evcon->flags & EVHTTP_CON_REUSE_CONNECTED_ADDR &&
|
||||
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;
|
||||
event_sock_warn(evcon->fd, "%s: connection to \"%s\" failed",
|
||||
__func__, evcon->address);
|
||||
@ -2493,7 +2527,7 @@ evhttp_make_request(struct evhttp_connection *evcon,
|
||||
mm_free(req->uri);
|
||||
if ((req->uri = mm_strdup(uri)) == NULL) {
|
||||
event_warn("%s: strdup", __func__);
|
||||
evhttp_request_free(req);
|
||||
evhttp_request_free_auto(req);
|
||||
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
|
||||
evhttp_start_read_(struct evhttp_connection *evcon)
|
||||
{
|
||||
/* Set up an event to read the headers */
|
||||
bufferevent_disable(evcon->bufev, EV_WRITE);
|
||||
bufferevent_enable(evcon->bufev, EV_READ);
|
||||
|
||||
evcon->state = EVCON_READING_FIRSTLINE;
|
||||
/* Reset the bufferevent callbacks */
|
||||
bufferevent_setcb(evcon->bufev,
|
||||
@ -2599,9 +2633,8 @@ evhttp_send_done(struct evhttp_connection *evcon, void *arg)
|
||||
|
||||
need_close =
|
||||
(REQ_VERSION_BEFORE(req, 1, 1) &&
|
||||
!evhttp_is_connection_keepalive(req->input_headers))||
|
||||
evhttp_is_connection_close(req->flags, req->input_headers) ||
|
||||
evhttp_is_connection_close(req->flags, req->output_headers);
|
||||
!evhttp_is_connection_keepalive(req->input_headers)) ||
|
||||
evhttp_is_request_connection_close(req);
|
||||
|
||||
EVUTIL_ASSERT(req->flags & EVHTTP_REQ_OWN_CONNECTION);
|
||||
evhttp_request_free(req);
|
||||
@ -4035,6 +4068,8 @@ evhttp_get_request_connection(
|
||||
|
||||
evcon->fd = fd;
|
||||
|
||||
bufferevent_enable(evcon->bufev, EV_READ);
|
||||
bufferevent_disable(evcon->bufev, EV_WRITE);
|
||||
bufferevent_setfd(evcon->bufev, fd);
|
||||
|
||||
return (evcon);
|
||||
|
@ -63,8 +63,6 @@ extern "C" {
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
typedef unsigned char u_char;
|
||||
typedef unsigned short u_short;
|
||||
#endif
|
||||
|
||||
#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
|
||||
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.
|
||||
*/
|
||||
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;
|
||||
/**
|
||||
@ -562,6 +562,32 @@ void bufferevent_lock(struct bufferevent *bufev);
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
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
|
||||
deal with the incoming data.
|
||||
|
@ -633,9 +633,22 @@ struct evhttp_connection *evhttp_connection_base_new(
|
||||
/**
|
||||
* Set family hint for DNS requests.
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evhttp_connection_set_family(struct evhttp_connection *evcon,
|
||||
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
|
||||
*
|
||||
* 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);
|
||||
|
||||
/** Get the remote address associated with this connection.
|
||||
* extracted from getpeername().
|
||||
* extracted from getpeername() OR from nameserver.
|
||||
*
|
||||
* @return NULL if getpeername() return non success,
|
||||
* 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_INT64_MAX ((((ev_int64_t) 0x7fffffffL) << 32) | 0xffffffffL)
|
||||
#define EV_INT64_MIN ((-EV_INT64_MAX) - 1)
|
||||
@ -245,7 +246,21 @@ extern "C" {
|
||||
#define EV_UINT8_MAX 255
|
||||
#define EV_INT8_MAX 127
|
||||
#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
|
||||
|
5
kqueue.c
5
kqueue.c
@ -50,7 +50,7 @@
|
||||
/* 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
|
||||
* 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 INT_TO_UDATA(x) ((intptr_t)(x))
|
||||
#else
|
||||
@ -260,7 +260,8 @@ kq_dispatch(struct event_base *base, struct timeval *tv)
|
||||
int i, n_changes, res;
|
||||
|
||||
if (tv != NULL) {
|
||||
TIMEVAL_TO_TIMESPEC(tv, &ts);
|
||||
ts.tv_sec = tv->tv_sec;
|
||||
ts.tv_nsec = tv->tv_usec * 1000;
|
||||
ts_p = &ts;
|
||||
}
|
||||
|
||||
|
@ -421,6 +421,8 @@ listener_read_cb(evutil_socket_t fd, short what, void *p)
|
||||
if (lev->refcnt == 1) {
|
||||
int freed = listener_decref_and_unlock(lev);
|
||||
EVUTIL_ASSERT(freed);
|
||||
|
||||
evutil_closesocket(new_fd);
|
||||
return;
|
||||
}
|
||||
--lev->refcnt;
|
||||
|
@ -12,9 +12,14 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef EVENT__HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <getopt.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
@ -141,34 +146,36 @@ logfn(int is_warn, const char *msg) {
|
||||
|
||||
int
|
||||
main(int c, char **v) {
|
||||
int idx;
|
||||
int reverse = 0, servertest = 0, use_getaddrinfo = 0;
|
||||
struct options {
|
||||
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 evdns_base *evdns_base = NULL;
|
||||
const char *resolv_conf = NULL;
|
||||
if (c<2) {
|
||||
fprintf(stderr, "syntax: %s [-x] [-v] [-c resolv.conf] hostname\n", v[0]);
|
||||
fprintf(stderr, "syntax: %s [-servertest]\n", v[0]);
|
||||
|
||||
memset(&o, 0, sizeof(o));
|
||||
|
||||
if (c < 2) {
|
||||
fprintf(stderr, "syntax: %s [-x] [-v] [-c resolv.conf] [-s ns] hostname\n", v[0]);
|
||||
fprintf(stderr, "syntax: %s [-T]\n", v[0]);
|
||||
return 1;
|
||||
}
|
||||
idx = 1;
|
||||
while (idx < c && v[idx][0] == '-') {
|
||||
if (!strcmp(v[idx], "-x"))
|
||||
reverse = 1;
|
||||
else if (!strcmp(v[idx], "-v"))
|
||||
verbose = 1;
|
||||
else if (!strcmp(v[idx], "-g"))
|
||||
use_getaddrinfo = 1;
|
||||
else if (!strcmp(v[idx], "-servertest"))
|
||||
servertest = 1;
|
||||
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;
|
||||
|
||||
while ((opt = getopt(c, v, "xvc:Ts:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'x': o.reverse = 1; break;
|
||||
case 'v': ++verbose; break;
|
||||
case 'g': o.use_getaddrinfo = 1; break;
|
||||
case 'T': o.servertest = 1; break;
|
||||
case 'c': o.resolv_conf = optarg; break;
|
||||
case 's': o.ns = optarg; break;
|
||||
default : fprintf(stderr, "Unknown option %c\n", opt); break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
@ -182,7 +189,7 @@ main(int c, char **v) {
|
||||
evdns_base = evdns_base_new(event_base, EVDNS_BASE_DISABLE_WHEN_INACTIVE);
|
||||
evdns_set_log_fn(logfn);
|
||||
|
||||
if (servertest) {
|
||||
if (o.servertest) {
|
||||
evutil_socket_t sock;
|
||||
struct sockaddr_in my_addr;
|
||||
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);
|
||||
}
|
||||
if (idx < c) {
|
||||
if (optind < c) {
|
||||
int res;
|
||||
#ifdef _WIN32
|
||||
if (resolv_conf == NULL)
|
||||
if (o.resolv_conf == NULL && !o.ns)
|
||||
res = evdns_base_config_windows_nameservers(evdns_base);
|
||||
else
|
||||
#endif
|
||||
if (o.ns)
|
||||
res = evdns_base_nameserver_ip_add(evdns_base, o.ns);
|
||||
else
|
||||
res = evdns_base_resolv_conf_parse(evdns_base,
|
||||
DNS_OPTION_NAMESERVERS,
|
||||
resolv_conf ? resolv_conf : "/etc/resolv.conf");
|
||||
DNS_OPTION_NAMESERVERS, o.resolv_conf);
|
||||
|
||||
if (res < 0) {
|
||||
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);
|
||||
for (; idx < c; ++idx) {
|
||||
if (reverse) {
|
||||
for (; optind < c; ++optind) {
|
||||
if (o.reverse) {
|
||||
struct in_addr addr;
|
||||
if (evutil_inet_pton(AF_INET, v[idx], &addr)!=1) {
|
||||
fprintf(stderr, "Skipping non-IP %s\n", v[idx]);
|
||||
if (evutil_inet_pton(AF_INET, v[optind], &addr)!=1) {
|
||||
fprintf(stderr, "Skipping non-IP %s\n", v[optind]);
|
||||
continue;
|
||||
}
|
||||
fprintf(stderr, "resolving %s...\n",v[idx]);
|
||||
evdns_base_resolve_reverse(evdns_base, &addr, 0, main_callback, v[idx]);
|
||||
} else if (use_getaddrinfo) {
|
||||
fprintf(stderr, "resolving %s...\n",v[optind]);
|
||||
evdns_base_resolve_reverse(evdns_base, &addr, 0, main_callback, v[optind]);
|
||||
} else if (o.use_getaddrinfo) {
|
||||
struct evutil_addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
hints.ai_flags = EVUTIL_AI_CANONNAME;
|
||||
fprintf(stderr, "resolving (fwd) %s...\n",v[idx]);
|
||||
evdns_getaddrinfo(evdns_base, v[idx], NULL, &hints,
|
||||
gai_callback, v[idx]);
|
||||
fprintf(stderr, "resolving (fwd) %s...\n",v[optind]);
|
||||
evdns_getaddrinfo(evdns_base, v[optind], NULL, &hints,
|
||||
gai_callback, v[optind]);
|
||||
} else {
|
||||
fprintf(stderr, "resolving (fwd) %s...\n",v[idx]);
|
||||
evdns_base_resolve_ipv4(evdns_base, v[idx], 0, main_callback, v[idx]);
|
||||
fprintf(stderr, "resolving (fwd) %s...\n",v[optind]);
|
||||
evdns_base_resolve_ipv4(evdns_base, v[optind], 0, main_callback, v[optind]);
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
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(" https-client -url https://ip.appspot.com/\n", stderr);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
die(const char *msg)
|
||||
err(const char *msg)
|
||||
{
|
||||
fputs(msg, stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
die_openssl(const char *func)
|
||||
err_openssl(const char *func)
|
||||
{
|
||||
fprintf (stderr, "%s failed:\n", func);
|
||||
|
||||
@ -190,22 +187,26 @@ main(int argc, char **argv)
|
||||
{
|
||||
int r;
|
||||
|
||||
struct evhttp_uri *http_uri;
|
||||
struct evhttp_uri *http_uri = NULL;
|
||||
const char *url = NULL, *data_file = NULL;
|
||||
const char *crt = "/etc/ssl/certs/ca-certificates.crt";
|
||||
const char *scheme, *host, *path, *query;
|
||||
char uri[256];
|
||||
int port;
|
||||
int retries = 0;
|
||||
int timeout = -1;
|
||||
|
||||
SSL_CTX *ssl_ctx;
|
||||
SSL *ssl;
|
||||
SSL_CTX *ssl_ctx = NULL;
|
||||
SSL *ssl = NULL;
|
||||
struct bufferevent *bev;
|
||||
struct evhttp_connection *evcon;
|
||||
struct evhttp_connection *evcon = NULL;
|
||||
struct evhttp_request *req;
|
||||
struct evkeyvalq *output_headers;
|
||||
struct evbuffer * output_buffer;
|
||||
struct evbuffer *output_buffer;
|
||||
|
||||
int i;
|
||||
int ret = 0;
|
||||
enum { HTTP, HTTPS } type = HTTP;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (!strcmp("-url", argv[i])) {
|
||||
@ -213,6 +214,14 @@ main(int argc, char **argv)
|
||||
url = argv[i + 1];
|
||||
} else {
|
||||
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])) {
|
||||
ignore_cert = 1;
|
||||
@ -221,20 +230,31 @@ main(int argc, char **argv)
|
||||
data_file = argv[i + 1];
|
||||
} else {
|
||||
syntax();
|
||||
goto error;
|
||||
}
|
||||
} else if (!strcmp("-retries", argv[i])) {
|
||||
if (i < argc - 1) {
|
||||
retries = atoi(argv[i + 1]);
|
||||
} else {
|
||||
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])) {
|
||||
syntax();
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (!url) {
|
||||
syntax();
|
||||
goto error;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
@ -248,25 +268,28 @@ main(int argc, char **argv)
|
||||
err = WSAStartup(wVersionRequested, &wsaData);
|
||||
if (err != 0) {
|
||||
printf("WSAStartup failed with error: %d\n", err);
|
||||
return 1;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
#endif // _WIN32
|
||||
|
||||
http_uri = evhttp_uri_parse(url);
|
||||
if (http_uri == NULL) {
|
||||
die("malformed url");
|
||||
err("malformed url");
|
||||
goto error;
|
||||
}
|
||||
|
||||
scheme = evhttp_uri_get_scheme(http_uri);
|
||||
if (scheme == NULL || (strcasecmp(scheme, "https") != 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);
|
||||
if (host == NULL) {
|
||||
die("url must have a host");
|
||||
err("url must have a host");
|
||||
goto error;
|
||||
}
|
||||
|
||||
port = evhttp_uri_get_port(http_uri);
|
||||
@ -275,7 +298,7 @@ main(int argc, char **argv)
|
||||
}
|
||||
|
||||
path = evhttp_uri_get_path(http_uri);
|
||||
if (path == NULL) {
|
||||
if (strlen(path) == 0) {
|
||||
path = "/";
|
||||
}
|
||||
|
||||
@ -297,23 +320,26 @@ main(int argc, char **argv)
|
||||
* automatically on first use of random number generator. */
|
||||
r = RAND_poll();
|
||||
if (r == 0) {
|
||||
die_openssl("RAND_poll");
|
||||
err_openssl("RAND_poll");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Create a new OpenSSL context */
|
||||
ssl_ctx = SSL_CTX_new(SSLv23_method());
|
||||
if (!ssl_ctx)
|
||||
die_openssl("SSL_CTX_new");
|
||||
if (!ssl_ctx) {
|
||||
err_openssl("SSL_CTX_new");
|
||||
goto error;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifndef _WIN32
|
||||
/* TODO: Add certificate loading on Windows as well */
|
||||
|
||||
/* Attempt to use the system's trusted root certificates.
|
||||
* (This path is only valid for Debian-based systems.) */
|
||||
if (1 != SSL_CTX_load_verify_locations(ssl_ctx,
|
||||
"/etc/ssl/certs/ca-certificates.crt",
|
||||
NULL))
|
||||
die_openssl("SSL_CTX_load_verify_locations");
|
||||
if (1 != SSL_CTX_load_verify_locations(ssl_ctx, crt, NULL)) {
|
||||
err_openssl("SSL_CTX_load_verify_locations");
|
||||
goto error;
|
||||
}
|
||||
/* Ask OpenSSL to verify the server certificate. Note that this
|
||||
* does NOT include verifying that the hostname is correct.
|
||||
* 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
|
||||
* we hadn't set the callback. Therefore, we're just
|
||||
* "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);
|
||||
#endif // not _WIN32
|
||||
#endif // not _WIN32
|
||||
|
||||
// Create event base
|
||||
base = event_base_new();
|
||||
if (!base) {
|
||||
perror("event_base_new()");
|
||||
return 1;
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Create OpenSSL bufferevent and stack evhttp on top of it
|
||||
ssl = SSL_new(ssl_ctx);
|
||||
if (ssl == NULL) {
|
||||
die_openssl("SSL_new()");
|
||||
err_openssl("SSL_new()");
|
||||
goto error;
|
||||
}
|
||||
|
||||
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
||||
@ -361,6 +388,7 @@ main(int argc, char **argv)
|
||||
if (strcasecmp(scheme, "http") == 0) {
|
||||
bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
|
||||
} else {
|
||||
type = HTTPS;
|
||||
bev = bufferevent_openssl_socket_new(base, -1, ssl,
|
||||
BUFFEREVENT_SSL_CONNECTING,
|
||||
BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
|
||||
@ -368,7 +396,7 @@ main(int argc, char **argv)
|
||||
|
||||
if (bev == NULL) {
|
||||
fprintf(stderr, "bufferevent_openssl_socket_new() failed\n");
|
||||
return 1;
|
||||
goto error;
|
||||
}
|
||||
|
||||
bufferevent_openssl_set_allow_dirty_shutdown(bev, 1);
|
||||
@ -379,18 +407,21 @@ main(int argc, char **argv)
|
||||
host, port);
|
||||
if (evcon == NULL) {
|
||||
fprintf(stderr, "evhttp_connection_base_bufferevent_new() failed\n");
|
||||
return 1;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (retries > 0) {
|
||||
evhttp_connection_set_retries(evcon, retries);
|
||||
}
|
||||
if (timeout >= 0) {
|
||||
evhttp_connection_set_timeout(evcon, timeout);
|
||||
}
|
||||
|
||||
// Fire off the request
|
||||
req = evhttp_request_new(http_request_done, bev);
|
||||
if (req == NULL) {
|
||||
fprintf(stderr, "evhttp_request_new() failed\n");
|
||||
return 1;
|
||||
goto error;
|
||||
}
|
||||
|
||||
output_headers = evhttp_request_get_output_headers(req);
|
||||
@ -408,6 +439,7 @@ main(int argc, char **argv)
|
||||
|
||||
if (!f) {
|
||||
syntax();
|
||||
goto error;
|
||||
}
|
||||
|
||||
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);
|
||||
if (r != 0) {
|
||||
fprintf(stderr, "evhttp_make_request() failed\n");
|
||||
return 1;
|
||||
goto error;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
WSACleanup();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ SAMPLES = \
|
||||
sample/event-read-fifo \
|
||||
sample/hello-world \
|
||||
sample/http-server \
|
||||
sample/http-connect \
|
||||
sample/signal-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_http_server_SOURCES = sample/http-server.c
|
||||
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/ssl.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "openssl_hostname_validation.h"
|
||||
#include "hostcheck.h"
|
||||
|
@ -74,7 +74,7 @@ static void
|
||||
read_cb(evutil_socket_t fd, short which, void *arg)
|
||||
{
|
||||
ev_intptr_t idx = (ev_intptr_t) arg, widx = idx + 1;
|
||||
u_char ch;
|
||||
unsigned char ch;
|
||||
ev_ssize_t n;
|
||||
|
||||
n = recv(fd, (char*)&ch, sizeof(ch), 0);
|
||||
|
@ -151,7 +151,7 @@ launch_request(void)
|
||||
}
|
||||
frob_socket(sock);
|
||||
if (connect(sock, (struct sockaddr*)&sin, sizeof(sin)) < 0) {
|
||||
int e = errno;
|
||||
int e = evutil_socket_geterror(sock);
|
||||
if (! EVUTIL_ERR_CONNECT_RETRIABLE(e)) {
|
||||
evutil_closesocket(sock);
|
||||
return -1;
|
||||
@ -183,6 +183,11 @@ main(int argc, char **argv)
|
||||
double throughput;
|
||||
resource = "/ref";
|
||||
|
||||
#ifdef _WIN32
|
||||
WSADATA WSAData;
|
||||
WSAStartup(0x101, &WSAData);
|
||||
#endif
|
||||
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
|
||||
base = event_base_new();
|
||||
@ -226,5 +231,9 @@ main(int argc, char **argv)
|
||||
(double)(usec/1000) / total_n_handled,
|
||||
(I64_TYP)total_n_bytes, n_errors);
|
||||
|
||||
#ifdef _WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2290,7 +2290,7 @@ end:
|
||||
static void
|
||||
evtag_fuzz(void *ptr)
|
||||
{
|
||||
u_char buffer[4096];
|
||||
unsigned char buffer[4096];
|
||||
struct evbuffer *tmp = evbuffer_new();
|
||||
struct timeval tv;
|
||||
int i, j;
|
||||
|
@ -129,6 +129,14 @@ long timeval_msec_diff(const struct timeval *start, const struct timeval *end);
|
||||
pid_t regress_fork(void);
|
||||
#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
|
||||
}
|
||||
#endif
|
||||
|
@ -198,7 +198,7 @@ test_evbuffer(void *ptr)
|
||||
|
||||
tt_assert(evbuffer_get_length(evb_two) == 0);
|
||||
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));
|
||||
evbuffer_add(evb, buffer, sizeof(buffer));
|
||||
@ -1292,7 +1292,7 @@ test_evbuffer_iterative(void *ptr)
|
||||
static void
|
||||
test_evbuffer_find(void *ptr)
|
||||
{
|
||||
u_char* p;
|
||||
unsigned char* p;
|
||||
const char* test1 = "1234567890\r\n";
|
||||
const char* test2 = "1234567890\r";
|
||||
#define EVBUFFER_INITIAL_LENGTH 256
|
||||
@ -1303,13 +1303,13 @@ test_evbuffer_find(void *ptr)
|
||||
tt_assert(buf);
|
||||
|
||||
/* 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_drain(buf, strlen(test1));
|
||||
evbuffer_validate(buf);
|
||||
evbuffer_add(buf, (u_char*)test2, strlen(test2));
|
||||
evbuffer_add(buf, (unsigned char*)test2, strlen(test2));
|
||||
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);
|
||||
|
||||
/*
|
||||
@ -1321,13 +1321,13 @@ test_evbuffer_find(void *ptr)
|
||||
for (i = 0; i < EVBUFFER_INITIAL_LENGTH; ++i)
|
||||
test3[i] = 'a';
|
||||
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);
|
||||
p = evbuffer_find(buf, (u_char *)"xy", 2);
|
||||
p = evbuffer_find(buf, (unsigned char *)"xy", 2);
|
||||
tt_want(p == NULL);
|
||||
|
||||
/* 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_want(strncmp((char*)p, "ax", 2) == 0);
|
||||
|
||||
|
@ -123,11 +123,12 @@ errorcb(struct bufferevent *bev, short what, void *arg)
|
||||
}
|
||||
|
||||
static void
|
||||
test_bufferevent_impl(int use_pair)
|
||||
test_bufferevent_impl(int use_pair, int flush)
|
||||
{
|
||||
struct bufferevent *bev1 = NULL, *bev2 = NULL;
|
||||
char buffer[8333];
|
||||
int i;
|
||||
int expected = 2;
|
||||
|
||||
if (use_pair) {
|
||||
struct bufferevent *pair[2];
|
||||
@ -171,6 +172,9 @@ test_bufferevent_impl(int use_pair)
|
||||
buffer[i] = i;
|
||||
|
||||
bufferevent_write(bev1, buffer, sizeof(buffer));
|
||||
if (flush >= 0) {
|
||||
tt_int_op(bufferevent_flush(bev1, EV_WRITE, flush), >=, 0);
|
||||
}
|
||||
|
||||
event_dispatch();
|
||||
|
||||
@ -178,23 +182,26 @@ test_bufferevent_impl(int use_pair)
|
||||
tt_ptr_op(bufferevent_pair_get_partner(bev1), ==, NULL);
|
||||
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;
|
||||
end:
|
||||
;
|
||||
}
|
||||
|
||||
static void
|
||||
test_bufferevent(void)
|
||||
{
|
||||
test_bufferevent_impl(0);
|
||||
}
|
||||
static void test_bufferevent(void) { test_bufferevent_impl(0, -1); }
|
||||
static void test_bufferevent_pair(void) { test_bufferevent_impl(1, -1); }
|
||||
|
||||
static void
|
||||
test_bufferevent_pair(void)
|
||||
{
|
||||
test_bufferevent_impl(1);
|
||||
}
|
||||
static void test_bufferevent_flush_normal(void) { test_bufferevent_impl(0, BEV_NORMAL); }
|
||||
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); }
|
||||
|
||||
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)
|
||||
/**
|
||||
@ -245,7 +252,6 @@ static void trace_lock_free(void *lock_, unsigned locktype)
|
||||
{
|
||||
lock_wrapper *lock = lu_find(lock_);
|
||||
if (!lock || lock->status == FREE || lock->locked) {
|
||||
__asm__("int3");
|
||||
TT_FAIL(("lock: free error"));
|
||||
} else {
|
||||
lock->status = FREE;
|
||||
@ -278,6 +284,9 @@ static void lock_unlock_free_thread_cbs(void)
|
||||
{
|
||||
event_base_free(NULL);
|
||||
|
||||
if (libevent_tests_running_in_debug_mode)
|
||||
libevent_global_shutdown();
|
||||
|
||||
/** drop immutable flag */
|
||||
evthread_set_lock_callbacks(NULL);
|
||||
/** 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)
|
||||
{
|
||||
/** fix "held_by" for kqueue */
|
||||
evthread_set_lock_callbacks(NULL);
|
||||
|
||||
lock_unlock_free_thread_cbs();
|
||||
free(lu_base.locks);
|
||||
data->base = NULL;
|
||||
@ -594,6 +606,7 @@ static int bufferevent_connect_test_flags = 0;
|
||||
static int bufferevent_trigger_test_flags = 0;
|
||||
static int n_strings_read = 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 " \
|
||||
"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
|
||||
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
|
||||
reader_readcb(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
@ -727,6 +773,45 @@ end:
|
||||
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
|
||||
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 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;
|
||||
int close_listener_event_added = 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;
|
||||
|
||||
test_ok = 0;
|
||||
|
||||
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. */
|
||||
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);
|
||||
fake_listener = fake_listener_create(&localhost);
|
||||
bev = bufferevent_socket_new(data->base, -1,
|
||||
BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
|
||||
tt_assert(bev);
|
||||
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
|
||||
* detects the error immediately, which is not really wrong of it. */
|
||||
tt_want(r == 0 || r == -1);
|
||||
@ -1084,10 +1158,35 @@ end:
|
||||
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[] = {
|
||||
|
||||
LEGACY(bufferevent, 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)
|
||||
{ "bufferevent_pair_release_lock", test_bufferevent_pair_release_lock,
|
||||
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 },
|
||||
#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,
|
||||
};
|
||||
|
||||
struct testcase_t bufferevent_iocp_testcases[] = {
|
||||
|
||||
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_filters, TT_ISOLATED|TT_ENABLE_IOCP),
|
||||
{ "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,
|
||||
(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,
|
||||
};
|
||||
|
@ -72,6 +72,8 @@
|
||||
#include "regress.h"
|
||||
#include "regress_testutils.h"
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
static int dns_ok = 0;
|
||||
static int dns_got_cancel = 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[] = {
|
||||
{ "host.a.example.com", "err", "3", 0 },
|
||||
{ "host.b.example.com", "err", "3", 0 },
|
||||
{ "host.c.example.com", "A", "11.22.33.44", 0 },
|
||||
{ "host2.a.example.com", "err", "3", 0 },
|
||||
{ "host2.b.example.com", "A", "200.100.0.100", 0 },
|
||||
{ "host2.c.example.com", "err", "3", 0 },
|
||||
{ "hostn.a.example.com", "errsoa", "0", 0 },
|
||||
{ "hostn.b.example.com", "errsoa", "3", 0 },
|
||||
{ "hostn.c.example.com", "err", "0", 0 },
|
||||
{ "host.a.example.com", "err", "3", 0, 0 },
|
||||
{ "host.b.example.com", "err", "3", 0, 0 },
|
||||
{ "host.c.example.com", "A", "11.22.33.44", 0, 0 },
|
||||
{ "host2.a.example.com", "err", "3", 0, 0 },
|
||||
{ "host2.b.example.com", "A", "200.100.0.100", 0, 0 },
|
||||
{ "host2.c.example.com", "err", "3", 0, 0 },
|
||||
{ "hostn.a.example.com", "errsoa", "0", 0, 0 },
|
||||
{ "hostn.b.example.com", "errsoa", "3", 0, 0 },
|
||||
{ "hostn.c.example.com", "err", "0", 0, 0 },
|
||||
|
||||
{ "host", "err", "3", 0 },
|
||||
{ "host2", "err", "3", 0 },
|
||||
{ "*", "err", "3", 0 },
|
||||
{ NULL, NULL, NULL, 0 }
|
||||
{ "host", "err", "3", 0, 0 },
|
||||
{ "host2", "err", "3", 0, 0 },
|
||||
{ "*", "err", "3", 0, 0 },
|
||||
{ NULL, NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
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 event_base *base = data->base;
|
||||
struct evdns_base *dns = NULL;
|
||||
@ -537,8 +539,14 @@ dns_search_test(void *arg)
|
||||
char buf[64];
|
||||
|
||||
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);
|
||||
|
||||
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, "c.example.com");
|
||||
|
||||
n_replies_left = sizeof(r)/sizeof(r[0]);
|
||||
n_replies_left = ARRAY_SIZE(r);
|
||||
exit_base = base;
|
||||
|
||||
evdns_base_resolve_ipv4(dns, "host", 0, generic_dns_callback, &r[0]);
|
||||
@ -584,6 +592,16 @@ end:
|
||||
|
||||
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 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!
|
||||
*/
|
||||
{ "foof.example.com", "err", "4", 0 },
|
||||
{ NULL, NULL, NULL, 0 }
|
||||
{ "foof.example.com", "err", "4", 0, 0 },
|
||||
{ NULL, NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
static struct regress_dns_server_table reissue_table[] = {
|
||||
{ "foof.example.com", "A", "240.15.240.15", 0 },
|
||||
{ NULL, NULL, NULL, 0 }
|
||||
{ "foof.example.com", "A", "240.15.240.15", 0, 0 },
|
||||
{ NULL, NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
static void
|
||||
@ -1672,7 +1690,6 @@ test_getaddrinfo_async(void *arg)
|
||||
end:
|
||||
if (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) {
|
||||
if (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));
|
||||
}
|
||||
|
||||
event_base_loop(env->base, EVLOOP_NONBLOCK);
|
||||
/**
|
||||
* Because we don't cancel request,
|
||||
* and want our callback to recieve DNS_ERR_SHUTDOWN,
|
||||
* we use deferred callback, and there was
|
||||
* Because we don't cancel request, and want our callback to recieve
|
||||
* DNS_ERR_SHUTDOWN, we use deferred callback, and there was:
|
||||
* - one extra malloc(),
|
||||
* @see reply_schedule_callback()
|
||||
* - and one missing free
|
||||
* @see request_finished() (req->handle->pending_cb = 1)
|
||||
* than we don't need to count in testleak_cleanup()
|
||||
*
|
||||
* So just decrement allocated_chunks to 2,
|
||||
* like we already take care about it.
|
||||
* 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.
|
||||
*/
|
||||
if (!cancel && send_err_shutdown) {
|
||||
allocated_chunks -= 2;
|
||||
}
|
||||
|
||||
evdns_base_free(env->dns_base, send_err_shutdown);
|
||||
env->dns_base = 0;
|
||||
event_base_loop(env->base, EVLOOP_NONBLOCK);
|
||||
|
||||
end:
|
||||
evdns_base_free(env->dns_base, send_err_shutdown);
|
||||
env->dns_base = 0;
|
||||
|
||||
event_base_free(env->base);
|
||||
env->base = 0;
|
||||
}
|
||||
@ -1998,6 +2008,91 @@ end:
|
||||
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) \
|
||||
{ #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),
|
||||
{ "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_lower", dns_search_lower_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
|
||||
{ "search_cancel", dns_search_cancel_test,
|
||||
TT_FORK|TT_NEED_BASE, &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 },
|
||||
#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
|
||||
};
|
||||
|
||||
|
@ -58,7 +58,9 @@
|
||||
#include "event2/http.h"
|
||||
#include "event2/buffer.h"
|
||||
#include "event2/bufferevent.h"
|
||||
#include "event2/bufferevent_ssl.h"
|
||||
#include "event2/util.h"
|
||||
#include "event2/listener.h"
|
||||
#include "log-internal.h"
|
||||
#include "http-internal.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)
|
||||
|
||||
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_post_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_on_complete_cb(struct evhttp_request *req, void *arg);
|
||||
|
||||
#define HTTP_BIND_IPV6 1
|
||||
#define HTTP_BIND_SSL 2
|
||||
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;
|
||||
struct evhttp_bound_socket *sock;
|
||||
int ipv6 = mask & HTTP_BIND_IPV6;
|
||||
|
||||
if (ipv6)
|
||||
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;
|
||||
}
|
||||
|
||||
#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 *
|
||||
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;
|
||||
|
||||
/* Try a few different ports */
|
||||
myhttp = evhttp_new(base);
|
||||
|
||||
if (http_bind(myhttp, pport, ipv6) < 0)
|
||||
if (http_bind(myhttp, pport, mask) < 0)
|
||||
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 */
|
||||
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, "/streamed", http_chunked_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
|
||||
|
||||
static evutil_socket_t
|
||||
http_connect(const char *address, u_short port)
|
||||
http_connect(const char *address, unsigned short port)
|
||||
{
|
||||
/* Stupid code for connecting */
|
||||
struct evutil_addrinfo ai, *aitop;
|
||||
@ -276,6 +303,9 @@ http_writecb(struct bufferevent *bev, void *arg)
|
||||
static void
|
||||
http_errorcb(struct bufferevent *bev, short what, void *arg)
|
||||
{
|
||||
/** For ssl */
|
||||
if (what & BEV_EVENT_CONNECTED)
|
||||
return;
|
||||
test_ok = -2;
|
||||
event_base_loopexit(arg, NULL);
|
||||
}
|
||||
@ -329,6 +359,19 @@ end:
|
||||
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[] = {
|
||||
"This is funny",
|
||||
"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));
|
||||
}
|
||||
|
||||
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
|
||||
http_basic_test(void *arg)
|
||||
http_basic_test_impl(void *arg, int ssl)
|
||||
{
|
||||
struct basic_test_data *data = arg;
|
||||
struct timeval tv;
|
||||
@ -403,13 +466,14 @@ http_basic_test(void *arg)
|
||||
evutil_socket_t fd;
|
||||
const char *http_request;
|
||||
ev_uint16_t port = 0, port2 = 0;
|
||||
int server_flags = ssl ? HTTP_BIND_SSL : 0;
|
||||
|
||||
test_ok = 0;
|
||||
|
||||
http = http_setup(&port, data->base, 0);
|
||||
http = http_setup(&port, data->base, server_flags);
|
||||
|
||||
/* 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");
|
||||
exit(1);
|
||||
}
|
||||
@ -417,7 +481,7 @@ http_basic_test(void *arg)
|
||||
fd = http_connect("127.0.0.1", port);
|
||||
|
||||
/* 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,
|
||||
http_errorcb, data->base);
|
||||
|
||||
@ -443,7 +507,7 @@ http_basic_test(void *arg)
|
||||
fd = http_connect("127.0.0.1", port2);
|
||||
|
||||
/* 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,
|
||||
http_errorcb, data->base);
|
||||
|
||||
@ -466,7 +530,7 @@ http_basic_test(void *arg)
|
||||
fd = http_connect("127.0.0.1", port2);
|
||||
|
||||
/* 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,
|
||||
http_errorcb, data->base);
|
||||
|
||||
@ -487,6 +551,8 @@ http_basic_test(void *arg)
|
||||
if (bev)
|
||||
bufferevent_free(bev);
|
||||
}
|
||||
static void http_basic_test(void *arg)
|
||||
{ return http_basic_test_impl(arg, 0); }
|
||||
|
||||
|
||||
static void
|
||||
@ -956,6 +1022,7 @@ http_allowed_methods_test(void *arg)
|
||||
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_empty_done(struct evhttp_request *, void *);
|
||||
|
||||
@ -1060,8 +1127,8 @@ http_persist_connection_test(void *arg)
|
||||
}
|
||||
|
||||
static struct regress_dns_server_table search_table[] = {
|
||||
{ "localhost", "A", "127.0.0.1", 0 },
|
||||
{ NULL, NULL, NULL, 0 }
|
||||
{ "localhost", "A", "127.0.0.1", 0, 0 },
|
||||
{ NULL, NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
static void
|
||||
@ -1319,6 +1386,13 @@ http_cancel_test(void *arg)
|
||||
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
|
||||
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;
|
||||
const char *what = "DISPATCHER_TEST";
|
||||
|
||||
if (!req) {
|
||||
fprintf(stderr, "FAILED\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (evhttp_request_get_response_code(req) != HTTP_OK) {
|
||||
fprintf(stderr, "FAILED\n");
|
||||
exit(1);
|
||||
@ -2750,6 +2829,10 @@ http_incomplete_readcb(struct bufferevent *bev, void *arg)
|
||||
static void
|
||||
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))
|
||||
test_ok++;
|
||||
else
|
||||
@ -2773,7 +2856,7 @@ http_incomplete_writecb(struct bufferevent *bev, void *arg)
|
||||
}
|
||||
|
||||
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;
|
||||
evutil_socket_t fd;
|
||||
@ -2785,14 +2868,14 @@ http_incomplete_test_(struct basic_test_data *data, int use_timeout)
|
||||
|
||||
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);
|
||||
|
||||
fd = http_connect("127.0.0.1", port);
|
||||
tt_int_op(fd, >=, 0);
|
||||
|
||||
/* 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_incomplete_readcb, http_incomplete_writecb,
|
||||
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)
|
||||
evutil_closesocket(fd);
|
||||
}
|
||||
static void
|
||||
http_incomplete_test(void *arg)
|
||||
{
|
||||
http_incomplete_test_(arg, 0);
|
||||
}
|
||||
static void
|
||||
http_incomplete_timeout_test(void *arg)
|
||||
{
|
||||
http_incomplete_test_(arg, 1);
|
||||
}
|
||||
static void http_incomplete_test(void *arg)
|
||||
{ http_incomplete_test_(arg, 0, 0); }
|
||||
static void http_incomplete_timeout_test(void *arg)
|
||||
{ http_incomplete_test_(arg, 1, 0); }
|
||||
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/** SSL */
|
||||
if (what & BEV_EVENT_CONNECTED)
|
||||
return;
|
||||
|
||||
if (!test_ok)
|
||||
goto out;
|
||||
|
||||
@ -2990,7 +3072,7 @@ http_chunked_request_done(struct evhttp_request *req, void *arg)
|
||||
}
|
||||
|
||||
static void
|
||||
http_chunk_out_test(void *arg)
|
||||
http_chunk_out_test_impl(void *arg, int ssl)
|
||||
{
|
||||
struct basic_test_data *data = arg;
|
||||
struct bufferevent *bev;
|
||||
@ -3005,12 +3087,12 @@ http_chunk_out_test(void *arg)
|
||||
exit_base = data->base;
|
||||
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);
|
||||
|
||||
/* 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_chunked_readcb, http_chunked_writecb,
|
||||
http_chunked_errorcb, data->base);
|
||||
@ -3037,7 +3119,9 @@ http_chunk_out_test(void *arg)
|
||||
tt_int_op(test_ok, ==, 2);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* make two requests to check the keepalive behavior */
|
||||
@ -3065,21 +3149,26 @@ http_chunk_out_test(void *arg)
|
||||
if (http)
|
||||
evhttp_free(http);
|
||||
}
|
||||
static void http_chunk_out_test(void *arg)
|
||||
{ return http_chunk_out_test_impl(arg, 0); }
|
||||
|
||||
static void
|
||||
http_stream_out_test(void *arg)
|
||||
http_stream_out_test_impl(void *arg, int ssl)
|
||||
{
|
||||
struct basic_test_data *data = arg;
|
||||
ev_uint16_t port = 0;
|
||||
struct evhttp_connection *evcon = NULL;
|
||||
struct evhttp_request *req = NULL;
|
||||
struct bufferevent *bev;
|
||||
|
||||
test_ok = 0;
|
||||
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);
|
||||
|
||||
/*
|
||||
@ -3107,6 +3196,8 @@ http_stream_out_test(void *arg)
|
||||
if (http)
|
||||
evhttp_free(http);
|
||||
}
|
||||
static void http_stream_out_test(void *arg)
|
||||
{ return http_stream_out_test_impl(arg, 0); }
|
||||
|
||||
static void
|
||||
http_stream_in_chunk(struct evhttp_request *req, void *arg)
|
||||
@ -3241,65 +3332,70 @@ http_stream_in_cancel_test(void *arg)
|
||||
static void
|
||||
http_connection_fail_done(struct evhttp_request *req, void *arg)
|
||||
{
|
||||
struct evhttp_connection *evcon = arg;
|
||||
struct event_base *base = evhttp_connection_get_base(evcon);
|
||||
struct evhttp_connection *evcon = arg;
|
||||
struct event_base *base = evhttp_connection_get_base(evcon);
|
||||
|
||||
/* An ENETUNREACH error results in an unrecoverable
|
||||
* evhttp_connection error (see evhttp_connection_fail_()). The
|
||||
* connection will be reset, and the user will be notified with a NULL
|
||||
* req parameter. */
|
||||
tt_assert(!req);
|
||||
/* An ENETUNREACH error results in an unrecoverable
|
||||
* evhttp_connection error (see evhttp_connection_fail_()). The
|
||||
* connection will be reset, and the user will be notified with a NULL
|
||||
* req parameter. */
|
||||
tt_assert(!req);
|
||||
|
||||
evhttp_connection_free(evcon);
|
||||
evhttp_connection_free(evcon);
|
||||
|
||||
test_ok = 1;
|
||||
test_ok = 1;
|
||||
|
||||
end:
|
||||
event_base_loopexit(base, NULL);
|
||||
event_base_loopexit(base, NULL);
|
||||
}
|
||||
|
||||
/* Test unrecoverable evhttp_connection errors by generating an ENETUNREACH
|
||||
* error on connection. */
|
||||
static void
|
||||
http_connection_fail_test(void *arg)
|
||||
http_connection_fail_test_impl(void *arg, int ssl)
|
||||
{
|
||||
struct basic_test_data *data = arg;
|
||||
ev_uint16_t port = 0;
|
||||
struct evhttp_connection *evcon = NULL;
|
||||
struct evhttp_request *req = NULL;
|
||||
struct basic_test_data *data = arg;
|
||||
ev_uint16_t port = 0;
|
||||
struct evhttp_connection *evcon = NULL;
|
||||
struct evhttp_request *req = NULL;
|
||||
struct bufferevent *bev;
|
||||
|
||||
exit_base = data->base;
|
||||
test_ok = 0;
|
||||
exit_base = data->base;
|
||||
test_ok = 0;
|
||||
|
||||
/* auto detect a port */
|
||||
http = http_setup(&port, data->base, 0);
|
||||
evhttp_free(http);
|
||||
http = NULL;
|
||||
/* auto detect a port */
|
||||
http = http_setup(&port, data->base, ssl ? HTTP_BIND_SSL : 0);
|
||||
evhttp_free(http);
|
||||
http = NULL;
|
||||
|
||||
/* Pick an unroutable address. This administratively scoped multicast
|
||||
* address should do when working with TCP. */
|
||||
evcon = evhttp_connection_base_new(data->base, NULL, "239.10.20.30", 80);
|
||||
tt_assert(evcon);
|
||||
bev = create_bev(data->base, -1, ssl);
|
||||
/* Pick an unroutable address. This administratively scoped multicast
|
||||
* address should do when working with TCP. */
|
||||
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
|
||||
* server using our make request method.
|
||||
*/
|
||||
/*
|
||||
* At this point, we want to schedule an HTTP GET request
|
||||
* server using our make request method.
|
||||
*/
|
||||
|
||||
req = evhttp_request_new(http_connection_fail_done, evcon);
|
||||
tt_assert(req);
|
||||
req = evhttp_request_new(http_connection_fail_done, evcon);
|
||||
tt_assert(req);
|
||||
|
||||
if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/") == -1) {
|
||||
tt_abort_msg("Couldn't make request");
|
||||
}
|
||||
if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/") == -1) {
|
||||
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:
|
||||
;
|
||||
;
|
||||
}
|
||||
static void http_connection_fail_test(void *arg)
|
||||
{ return http_connection_fail_test_impl(arg, 0); }
|
||||
|
||||
static void
|
||||
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);
|
||||
}
|
||||
|
||||
struct http_server
|
||||
{
|
||||
ev_uint16_t port;
|
||||
int ssl;
|
||||
};
|
||||
static struct event_base *http_make_web_server_base=NULL;
|
||||
static void
|
||||
http_make_web_server(evutil_socket_t fd, short what, void *arg)
|
||||
{
|
||||
ev_uint16_t port = *(ev_uint16_t*)arg;
|
||||
http = http_setup(&port, http_make_web_server_base, 0);
|
||||
struct http_server *hs = (struct http_server *)arg;
|
||||
http = http_setup(&hs->port, http_make_web_server_base, hs->ssl ? HTTP_BIND_SSL : 0);
|
||||
}
|
||||
|
||||
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;
|
||||
ev_uint16_t port = 0;
|
||||
struct evhttp_connection *evcon = NULL;
|
||||
struct evhttp_request *req = NULL;
|
||||
struct timeval tv, tv_start, tv_end;
|
||||
struct bufferevent *bev;
|
||||
struct http_server hs = { .port = 0, .ssl = ssl, };
|
||||
|
||||
exit_base = data->base;
|
||||
test_ok = 0;
|
||||
|
||||
/* 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);
|
||||
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);
|
||||
if (dns_base)
|
||||
tt_assert(!evhttp_connection_set_flags(evcon, EVHTTP_CON_REUSE_CONNECTED_ADDR));
|
||||
|
||||
evhttp_connection_set_timeout(evcon, 1);
|
||||
/* also bind to local host */
|
||||
@ -3377,6 +3521,9 @@ http_connection_retry_test(void *arg)
|
||||
* now test the same but with retries
|
||||
*/
|
||||
test_ok = 0;
|
||||
/** Shutdown dns server, to test conn_address reusing */
|
||||
if (dns_base)
|
||||
regress_clean_dnsserver();
|
||||
|
||||
{
|
||||
const struct timeval tv_timeout = { 0, 500000 };
|
||||
@ -3432,7 +3579,7 @@ http_connection_retry_test(void *arg)
|
||||
evutil_timerclear(&tv);
|
||||
tv.tv_usec = 200000;
|
||||
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);
|
||||
event_base_dispatch(data->base);
|
||||
@ -3449,6 +3596,42 @@ http_connection_retry_test(void *arg)
|
||||
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
|
||||
http_primitives(void *ptr)
|
||||
{
|
||||
@ -3688,6 +3871,7 @@ struct terminate_state {
|
||||
struct bufferevent *bev;
|
||||
evutil_socket_t fd;
|
||||
int gotclosecb: 1;
|
||||
int oneshot: 1;
|
||||
};
|
||||
|
||||
static void
|
||||
@ -3695,7 +3879,10 @@ terminate_chunked_trickle_cb(evutil_socket_t fd, short events, void *arg)
|
||||
{
|
||||
struct terminate_state *state = arg;
|
||||
struct evbuffer *evb;
|
||||
struct timeval tv;
|
||||
|
||||
if (!state->req) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (evhttp_request_get_connection(state->req) == NULL) {
|
||||
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);
|
||||
evbuffer_free(evb);
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 3000;
|
||||
EVUTIL_ASSERT(state);
|
||||
EVUTIL_ASSERT(state->base);
|
||||
event_base_once(state->base, -1, EV_TIMEOUT, terminate_chunked_trickle_cb, arg, &tv);
|
||||
if (!state->oneshot) {
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 3000;
|
||||
EVUTIL_ASSERT(state);
|
||||
EVUTIL_ASSERT(state->base);
|
||||
event_base_once(state->base, -1, EV_TIMEOUT, terminate_chunked_trickle_cb, arg, &tv);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -3721,6 +3911,13 @@ terminate_chunked_close_cb(struct evhttp_connection *evcon, void *arg)
|
||||
{
|
||||
struct terminate_state *state = arg;
|
||||
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
|
||||
@ -3760,7 +3957,7 @@ terminate_readcb(struct bufferevent *bev, void *arg)
|
||||
|
||||
|
||||
static void
|
||||
http_terminate_chunked_test(void *arg)
|
||||
http_terminate_chunked_test_impl(void *arg, int oneshot)
|
||||
{
|
||||
struct basic_test_data *data = arg;
|
||||
struct bufferevent *bev = NULL;
|
||||
@ -3789,6 +3986,7 @@ http_terminate_chunked_test(void *arg)
|
||||
terminate_state.fd = fd;
|
||||
terminate_state.bev = bev;
|
||||
terminate_state.gotclosecb = 0;
|
||||
terminate_state.oneshot = oneshot;
|
||||
|
||||
/* first half of the http request */
|
||||
http_request =
|
||||
@ -3812,10 +4010,20 @@ http_terminate_chunked_test(void *arg)
|
||||
if (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[] = {
|
||||
{ "localhost", "AAAA", "::1", 0 },
|
||||
{ NULL, NULL, NULL, 0 }
|
||||
{ "localhost", "AAAA", "::1", 0, 0 },
|
||||
{ NULL, NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
static void
|
||||
@ -3929,12 +4137,126 @@ http_set_family_ipv6_test(void *arg)
|
||||
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) \
|
||||
{ #name, run_legacy_test_fn, TT_ISOLATED|TT_LEGACY, &legacy_setup, \
|
||||
http_##name##_test }
|
||||
|
||||
#define HTTP(name) \
|
||||
{ #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[] = {
|
||||
{ "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" },
|
||||
{ "uriencode", http_uriencode_test, 0, NULL, NULL },
|
||||
HTTP(basic),
|
||||
HTTP(simple),
|
||||
HTTP(cancel),
|
||||
HTTP(virtual_host),
|
||||
HTTP(post),
|
||||
@ -3962,6 +4285,7 @@ struct testcase_t http_testcases[] = {
|
||||
HTTP(incomplete),
|
||||
HTTP(incomplete_timeout),
|
||||
HTTP(terminate_chunked),
|
||||
HTTP(terminate_chunked_oneshot),
|
||||
HTTP(on_complete),
|
||||
|
||||
HTTP(highport),
|
||||
@ -3976,6 +4300,8 @@ struct testcase_t http_testcases[] = {
|
||||
|
||||
HTTP(connection_fail),
|
||||
{ "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),
|
||||
|
||||
@ -3986,6 +4312,24 @@ struct testcase_t http_testcases[] = {
|
||||
HTTP(set_family_ipv4),
|
||||
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
|
||||
};
|
||||
|
||||
|
@ -407,6 +407,7 @@ const char *finetimetests[] = {
|
||||
"+util/monotonic_res_fallback",
|
||||
"+thread/deferred_cb_skew",
|
||||
"+http/connection_retry",
|
||||
"+http/https_connection_retry",
|
||||
NULL
|
||||
};
|
||||
struct testlist_alias_t testaliases[] = {
|
||||
@ -437,6 +438,7 @@ main(int argc, const char **argv)
|
||||
|
||||
#ifdef _WIN32
|
||||
tinytest_skip(testgroups, "http/connection_retry");
|
||||
tinytest_skip(testgroups, "http/https_connection_retry");
|
||||
#endif
|
||||
|
||||
#ifndef EVENT__DISABLE_THREAD_SUPPORT
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "event2/util.h"
|
||||
#include "event2/event.h"
|
||||
#include "event2/bufferevent_ssl.h"
|
||||
#include "event2/bufferevent_struct.h"
|
||||
#include "event2/buffer.h"
|
||||
#include "event2/listener.h"
|
||||
|
||||
@ -50,12 +51,12 @@
|
||||
#include "tinytest.h"
|
||||
#include "tinytest_macros.h"
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/pem.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* 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
|
||||
@ -72,8 +73,8 @@ static const char KEY[] =
|
||||
"U6GFEQTZ3IfuiVabG5pummdC4DNbcdI+WKrSFNmQ\n"
|
||||
"-----END RSA PRIVATE KEY-----\n";
|
||||
|
||||
static EVP_PKEY *
|
||||
getkey(void)
|
||||
EVP_PKEY *
|
||||
ssl_getkey(void)
|
||||
{
|
||||
EVP_PKEY *key;
|
||||
BIO *bio;
|
||||
@ -91,15 +92,15 @@ end:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static X509 *
|
||||
getcert(void)
|
||||
X509 *
|
||||
ssl_getcert(void)
|
||||
{
|
||||
/* Dummy code to make a quick-and-dirty valid certificate with
|
||||
OpenSSL. Don't copy this code into your own program! It does a
|
||||
number of things in a stupid and insecure way. */
|
||||
X509 *x509 = NULL;
|
||||
X509_NAME *name = NULL;
|
||||
EVP_PKEY *key = getkey();
|
||||
EVP_PKEY *key = ssl_getkey();
|
||||
int nid;
|
||||
time_t now = time(NULL);
|
||||
|
||||
@ -137,7 +138,7 @@ end:
|
||||
static int disable_tls_11_and_12 = 0;
|
||||
static SSL_CTX *the_ssl_ctx = NULL;
|
||||
|
||||
static SSL_CTX *
|
||||
SSL_CTX *
|
||||
get_ssl_ctx(void)
|
||||
{
|
||||
if (the_ssl_ctx)
|
||||
@ -156,7 +157,7 @@ get_ssl_ctx(void)
|
||||
return the_ssl_ctx;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
init_ssl(void)
|
||||
{
|
||||
SSL_library_init();
|
||||
@ -177,17 +178,64 @@ static int test_is_done = 0;
|
||||
static int n_connected = 0;
|
||||
static int got_close = 0;
|
||||
static int got_error = 0;
|
||||
static int got_timeout = 0;
|
||||
static int renegotiate_at = -1;
|
||||
static int stop_when_connected = 0;
|
||||
static int pending_connect_events = 0;
|
||||
static struct event_base *exit_base = NULL;
|
||||
|
||||
enum regress_openssl_type
|
||||
{
|
||||
REGRESS_OPENSSL_SOCKETPAIR = 1,
|
||||
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
|
||||
respond_to_number(struct bufferevent *bev, void *ctx)
|
||||
{
|
||||
struct evbuffer *b = bufferevent_get_input(bev);
|
||||
char *line;
|
||||
int n;
|
||||
|
||||
enum regress_openssl_type type;
|
||||
type = (enum regress_openssl_type)ctx;
|
||||
|
||||
line = evbuffer_readln(b, NULL, EVBUFFER_EOL_LF);
|
||||
if (! line)
|
||||
return;
|
||||
@ -201,7 +249,7 @@ respond_to_number(struct bufferevent *bev, void *ctx)
|
||||
bufferevent_free(bev); /* Should trigger close on other side. */
|
||||
return;
|
||||
}
|
||||
if (!strcmp(ctx, "client") && n == renegotiate_at) {
|
||||
if ((type & REGRESS_OPENSSL_CLIENT) && n == renegotiate_at) {
|
||||
SSL_renegotiate(bufferevent_openssl_get_ssl(bev));
|
||||
}
|
||||
++n;
|
||||
@ -226,6 +274,9 @@ done_writing_cb(struct bufferevent *bev, void *ctx)
|
||||
static void
|
||||
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));
|
||||
if (what & BEV_EVENT_CONNECTED) {
|
||||
SSL *ssl;
|
||||
@ -234,7 +285,7 @@ eventcb(struct bufferevent *bev, short what, void *ctx)
|
||||
ssl = bufferevent_openssl_get_ssl(bev);
|
||||
tt_assert(ssl);
|
||||
peer_cert = SSL_get_peer_certificate(ssl);
|
||||
if (0==strcmp(ctx, "server")) {
|
||||
if (type & REGRESS_OPENSSL_SERVER) {
|
||||
tt_assert(peer_cert == NULL);
|
||||
} else {
|
||||
tt_assert(peer_cert != NULL);
|
||||
@ -246,10 +297,32 @@ eventcb(struct bufferevent *bev, short what, void *ctx)
|
||||
} else if (what & BEV_EVENT_EOF) {
|
||||
TT_BLATHER(("Got a good EOF"));
|
||||
++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);
|
||||
} else if (what & BEV_EVENT_ERROR) {
|
||||
TT_BLATHER(("Got an 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);
|
||||
}
|
||||
end:
|
||||
@ -259,10 +332,12 @@ end:
|
||||
static void
|
||||
open_ssl_bufevs(struct bufferevent **bev1_out, struct bufferevent **bev2_out,
|
||||
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 state2 = is_open ? BUFFEREVENT_SSL_OPEN :BUFFEREVENT_SSL_ACCEPTING;
|
||||
int dirty_shutdown = type & REGRESS_OPENSSL_DIRTY_SHUTDOWN;
|
||||
if (fd_pair) {
|
||||
*bev1_out = bufferevent_openssl_socket_new(
|
||||
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,
|
||||
eventcb, (void*)"client");
|
||||
eventcb, (void*)(REGRESS_OPENSSL_CLIENT | (long)type));
|
||||
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
|
||||
@ -288,20 +366,21 @@ regress_bufferevent_openssl(void *arg)
|
||||
|
||||
struct bufferevent *bev1, *bev2;
|
||||
SSL *ssl1, *ssl2;
|
||||
X509 *cert = getcert();
|
||||
EVP_PKEY *key = getkey();
|
||||
const int start_open = strstr((char*)data->setup_data, "open")!=NULL;
|
||||
const int filter = strstr((char*)data->setup_data, "filter")!=NULL;
|
||||
X509 *cert = ssl_getcert();
|
||||
EVP_PKEY *key = ssl_getkey();
|
||||
int flags = BEV_OPT_DEFER_CALLBACKS;
|
||||
struct bufferevent *bev_ll[2] = { NULL, NULL };
|
||||
evutil_socket_t *fd_pair = NULL;
|
||||
|
||||
enum regress_openssl_type type;
|
||||
type = (enum regress_openssl_type)data->setup_data;
|
||||
|
||||
tt_assert(cert);
|
||||
tt_assert(key);
|
||||
|
||||
init_ssl();
|
||||
|
||||
if (strstr((char*)data->setup_data, "renegotiate")) {
|
||||
if (type & REGRESS_OPENSSL_RENEGOTIATE) {
|
||||
if (SSLeay() >= 0x10001000 &&
|
||||
SSLeay() < 0x1000104f) {
|
||||
/* 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_PrivateKey(ssl2, key);
|
||||
|
||||
if (! start_open)
|
||||
if (!(type & REGRESS_OPENSSL_OPEN))
|
||||
flags |= BEV_OPT_CLOSE_ON_FREE;
|
||||
|
||||
if (!filter) {
|
||||
tt_assert(strstr((char*)data->setup_data, "socketpair"));
|
||||
if (!(type & REGRESS_OPENSSL_FILTER)) {
|
||||
tt_assert(type & REGRESS_OPENSSL_SOCKETPAIR);
|
||||
fd_pair = data->pair;
|
||||
} else {
|
||||
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,
|
||||
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]);
|
||||
} else {
|
||||
tt_ptr_op(bufferevent_get_underlying(bev1), ==, bev_ll[0]);
|
||||
}
|
||||
|
||||
if (start_open) {
|
||||
if (type & REGRESS_OPENSSL_OPEN) {
|
||||
pending_connect_events = 2;
|
||||
stop_when_connected = 1;
|
||||
exit_base = data->base;
|
||||
@ -351,37 +430,70 @@ regress_bufferevent_openssl(void *arg)
|
||||
bufferevent_free(bev2);
|
||||
bev1 = bev2 = NULL;
|
||||
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);
|
||||
bufferevent_enable(bev2, EV_READ|EV_WRITE);
|
||||
if (!(type & REGRESS_OPENSSL_TIMEOUT)) {
|
||||
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(n_connected == 2);
|
||||
tt_assert(test_is_done == 1);
|
||||
tt_assert(n_connected == 2);
|
||||
|
||||
/* We don't handle shutdown properly yet.
|
||||
tt_int_op(got_close, ==, 1);
|
||||
tt_int_op(got_error, ==, 0);
|
||||
*/
|
||||
/* We don't handle shutdown properly yet */
|
||||
if (type & REGRESS_OPENSSL_DIRTY_SHUTDOWN) {
|
||||
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:
|
||||
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
|
||||
acceptcb(struct evconnlistener *listener, evutil_socket_t fd,
|
||||
struct sockaddr *addr, int socklen, void *arg)
|
||||
{
|
||||
struct basic_test_data *data = arg;
|
||||
struct bufferevent *bev;
|
||||
enum regress_openssl_type type;
|
||||
SSL *ssl = SSL_new(get_ssl_ctx());
|
||||
|
||||
SSL_use_certificate(ssl, getcert());
|
||||
SSL_use_PrivateKey(ssl, getkey());
|
||||
type = (enum regress_openssl_type)data->setup_data;
|
||||
|
||||
SSL_use_certificate(ssl, ssl_getcert());
|
||||
SSL_use_PrivateKey(ssl, ssl_getkey());
|
||||
|
||||
bev = bufferevent_openssl_socket_new(
|
||||
data->base,
|
||||
@ -391,14 +503,129 @@ acceptcb(struct evconnlistener *listener, evutil_socket_t fd,
|
||||
BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
|
||||
|
||||
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. */
|
||||
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
|
||||
regress_bufferevent_openssl_connect(void *arg)
|
||||
{
|
||||
@ -411,6 +638,12 @@ regress_bufferevent_openssl_connect(void *arg)
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_storage ss;
|
||||
ev_socklen_t slen;
|
||||
SSL *ssl;
|
||||
BIO *bio;
|
||||
struct rwcount rw = { -1, 0, 0 };
|
||||
enum regress_openssl_type type;
|
||||
|
||||
type = (enum regress_openssl_type)data->setup_data;
|
||||
|
||||
init_ssl();
|
||||
|
||||
@ -428,51 +661,115 @@ regress_bufferevent_openssl_connect(void *arg)
|
||||
tt_assert(listener);
|
||||
tt_assert(evconnlistener_get_fd(listener) >= 0);
|
||||
|
||||
ssl = SSL_new(get_ssl_ctx());
|
||||
tt_assert(ssl);
|
||||
|
||||
bev = bufferevent_openssl_socket_new(
|
||||
data->base, -1, SSL_new(get_ssl_ctx()),
|
||||
data->base, -1, ssl,
|
||||
BUFFEREVENT_SSL_CONNECTING,
|
||||
BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
|
||||
tt_assert(bev);
|
||||
|
||||
bufferevent_setcb(bev, respond_to_number, NULL, eventcb,
|
||||
(void*)"client");
|
||||
(void*)(REGRESS_OPENSSL_CLIENT));
|
||||
|
||||
tt_assert(getsockname(evconnlistener_get_fd(listener),
|
||||
(struct sockaddr*)&ss, &slen) == 0);
|
||||
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_assert(0 ==
|
||||
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");
|
||||
bufferevent_enable(bev, EV_READ|EV_WRITE);
|
||||
|
||||
event_base_dispatch(base);
|
||||
|
||||
tt_int_op(rw.read, <=, 100);
|
||||
tt_int_op(rw.write, <=, 100);
|
||||
end:
|
||||
;
|
||||
}
|
||||
|
||||
struct testcase_t ssl_testcases[] = {
|
||||
|
||||
{ "bufferevent_socketpair", regress_bufferevent_openssl, TT_ISOLATED,
|
||||
&basic_setup, (void*)"socketpair" },
|
||||
#define T(a) ((void *)(a))
|
||||
{ "bufferevent_socketpair", regress_bufferevent_openssl,
|
||||
TT_ISOLATED, &basic_setup, T(REGRESS_OPENSSL_SOCKETPAIR) },
|
||||
{ "bufferevent_filter", regress_bufferevent_openssl,
|
||||
TT_ISOLATED,
|
||||
&basic_setup, (void*)"filter" },
|
||||
TT_ISOLATED, &basic_setup, T(REGRESS_OPENSSL_FILTER) },
|
||||
{ "bufferevent_renegotiate_socketpair", regress_bufferevent_openssl,
|
||||
TT_ISOLATED,
|
||||
&basic_setup, (void*)"socketpair renegotiate" },
|
||||
TT_ISOLATED, &basic_setup,
|
||||
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_RENEGOTIATE) },
|
||||
{ "bufferevent_renegotiate_filter", regress_bufferevent_openssl,
|
||||
TT_ISOLATED,
|
||||
&basic_setup, (void*)"filter renegotiate" },
|
||||
TT_ISOLATED, &basic_setup,
|
||||
T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_RENEGOTIATE) },
|
||||
{ "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,
|
||||
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,
|
||||
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,
|
||||
};
|
||||
|
@ -135,11 +135,18 @@ regress_clean_dnsserver(void)
|
||||
evutil_closesocket(dns_sock);
|
||||
}
|
||||
|
||||
static void strtolower(char *s)
|
||||
{
|
||||
while (*s) {
|
||||
*s = EVUTIL_TOLOWER_(*s);
|
||||
++s;
|
||||
}
|
||||
}
|
||||
void
|
||||
regress_dns_server_cb(struct evdns_server_request *req, void *data)
|
||||
{
|
||||
struct regress_dns_server_table *tab = data;
|
||||
const char *question;
|
||||
char *question;
|
||||
|
||||
if (req->nquestions != 1)
|
||||
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;
|
||||
|
||||
if (tab->lower)
|
||||
strtolower(question);
|
||||
|
||||
if (!strcmp(tab->anstype, "err")) {
|
||||
int err = atoi(tab->ans);
|
||||
tt_assert(! evdns_server_request_respond(req, err));
|
||||
|
@ -34,6 +34,7 @@ struct regress_dns_server_table {
|
||||
const char *anstype;
|
||||
const char *ans;
|
||||
int seen;
|
||||
int lower;
|
||||
};
|
||||
|
||||
struct evdns_server_port *
|
||||
|
@ -579,7 +579,12 @@ struct testcase_t thread_testcases[] = {
|
||||
{ "deferred_cb_skew", thread_deferred_cb_skew,
|
||||
TT_FORK|TT_NEED_THREADS|TT_OFF_BY_DEFAULT,
|
||||
&basic_setup, NULL },
|
||||
#ifndef _WIN32
|
||||
/****** XXX TODO FIXME windows seems to be having some timing trouble,
|
||||
* looking into it now. / ellzey
|
||||
******/
|
||||
TEST(no_events),
|
||||
#endif
|
||||
END_OF_TESTCASES
|
||||
};
|
||||
|
||||
|
16
test/test.sh
16
test/test.sh
@ -97,6 +97,7 @@ run_tests () {
|
||||
announce "FAILED (output not checked)" ;
|
||||
fi
|
||||
fi
|
||||
|
||||
test -x $TEST_DIR/regress || return
|
||||
announce_n " regress: "
|
||||
if test "$TEST_OUTPUT_FILE" = "/dev/null" ;
|
||||
@ -112,6 +113,21 @@ run_tests () {
|
||||
announce FAILED ;
|
||||
FAILED=yes
|
||||
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() {
|
||||
|
@ -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 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);
|
||||
|
||||
|
@ -57,7 +57,7 @@ extern struct event_list timequeue;
|
||||
extern struct event_list addqueue;
|
||||
|
||||
struct win_fd_set {
|
||||
u_int fd_count;
|
||||
unsigned int fd_count;
|
||||
SOCKET fd_array[1];
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user