Merge local changes from libevent 2.1.8 and 2.1.12

This commit is contained in:
christos 2021-04-07 03:36:48 +00:00
parent 6a94664822
commit 7e68cdd730
52 changed files with 3497 additions and 17640 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile.inc,v 1.3 2017/01/31 23:17:39 christos Exp $
# $NetBSD: Makefile.inc,v 1.4 2021/04/07 03:36:48 christos Exp $
.include <bsd.own.mk>
@ -10,7 +10,7 @@ CPPFLAGS+= -I${LIBEVENT_DIST} -I${LIBEVENT_DIR}/include
CPPFLAGS+= -I${LIBEVENT_DIST}/include
SHLIB_MAJOR= 4
SHLIB_MINOR= 1
SHLIB_MINOR= 2
WARNS?= 4

View File

@ -17,11 +17,11 @@
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
# by quotes) that should identify the project.
PROJECT_NAME = libevent
PROJECT_NAME = $(PROJECT)-$(VERSION)
# Place all output under 'doxygen/'
OUTPUT_DIRECTORY = doxygen/
OUTPUT_DIRECTORY = $(DOCDIR)
# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
# will interpret the first line (until the first dot) of a JavaDoc-style
@ -64,24 +64,24 @@ STRIP_FROM_PATH = include/
# with spaces.
INPUT = \
include/event2/buffer.h \
include/event2/buffer_compat.h \
include/event2/bufferevent.h \
include/event2/bufferevent_compat.h \
include/event2/bufferevent_ssl.h \
include/event2/dns.h \
include/event2/dns_compat.h \
include/event2/event.h \
include/event2/event_compat.h \
include/event2/http.h \
include/event2/http_compat.h \
include/event2/listener.h \
include/event2/rpc.h \
include/event2/rpc_compat.h \
include/event2/tag.h \
include/event2/tag_compat.h \
include/event2/thread.h \
include/event2/util.h
$(SRCDIR)/include/event2/buffer.h \
$(SRCDIR)/include/event2/buffer_compat.h \
$(SRCDIR)/include/event2/bufferevent.h \
$(SRCDIR)/include/event2/bufferevent_compat.h \
$(SRCDIR)/include/event2/bufferevent_ssl.h \
$(SRCDIR)/include/event2/dns.h \
$(SRCDIR)/include/event2/dns_compat.h \
$(SRCDIR)/include/event2/event.h \
$(SRCDIR)/include/event2/event_compat.h \
$(SRCDIR)/include/event2/http.h \
$(SRCDIR)/include/event2/http_compat.h \
$(SRCDIR)/include/event2/listener.h \
$(SRCDIR)/include/event2/rpc.h \
$(SRCDIR)/include/event2/rpc_compat.h \
$(SRCDIR)/include/event2/tag.h \
$(SRCDIR)/include/event2/tag_compat.h \
$(SRCDIR)/include/event2/thread.h \
$(SRCDIR)/include/event2/util.h
#---------------------------------------------------------------------------
# configuration options related to the HTML output
@ -90,7 +90,7 @@ INPUT = \
# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
# generate HTML output.
GENERATE_HTML = YES
GENERATE_HTML = $(GENERATE_HTML)
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
@ -99,7 +99,7 @@ GENERATE_HTML = YES
# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
# generate Latex output.
GENERATE_LATEX = YES
GENERATE_LATEX = $(GENERATE_LATEX)
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
@ -175,7 +175,7 @@ LATEX_HIDE_INDICES = NO
# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
# generate man pages
GENERATE_MAN = YES
GENERATE_MAN = $(GENERATE_MAN)
# The MAN_EXTENSION tag determines the extension that is added to
# the generated man pages (default is the subroutine's section .3)

View File

@ -1,4 +1,5 @@
/* $NetBSD: buffer.c,v 1.4 2017/01/31 23:17:39 christos Exp $ */
/* $NetBSD: buffer.c,v 1.5 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2002-2007 Niels Provos <provos@citi.umich.edu>
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
@ -28,7 +29,7 @@
#include "event2/event-config.h"
#include <sys/cdefs.h>
__RCSID("$NetBSD: buffer.c,v 1.4 2017/01/31 23:17:39 christos Exp $");
__RCSID("$NetBSD: buffer.c,v 1.5 2021/04/07 03:36:48 christos Exp $");
#include "evconfig-private.h"
#ifdef _WIN32
@ -98,6 +99,7 @@ __RCSID("$NetBSD: buffer.c,v 1.4 2017/01/31 23:17:39 christos Exp $");
#include "evthread-internal.h"
#include "evbuffer-internal.h"
#include "bufferevent-internal.h"
#include "event-internal.h"
/* some systems do not have MAP_FAILED */
#ifndef MAP_FAILED
@ -525,8 +527,8 @@ evbuffer_invoke_callbacks_(struct evbuffer *buffer)
evbuffer_incref_and_lock_(buffer);
if (buffer->parent)
bufferevent_incref_(buffer->parent);
EVBUFFER_UNLOCK(buffer);
}
EVBUFFER_UNLOCK(buffer);
}
evbuffer_run_callbacks(buffer, 0);
@ -706,13 +708,17 @@ static int
advance_last_with_data(struct evbuffer *buf)
{
int n = 0;
struct evbuffer_chain **chainp = buf->last_with_datap;
ASSERT_EVBUFFER_LOCKED(buf);
if (!*buf->last_with_datap)
if (!*chainp)
return 0;
while ((*buf->last_with_datap)->next && (*buf->last_with_datap)->next->off) {
buf->last_with_datap = &(*buf->last_with_datap)->next;
while ((*chainp)->next) {
chainp = &(*chainp)->next;
if ((*chainp)->off)
buf->last_with_datap = chainp;
++n;
}
return n;
@ -1149,7 +1155,7 @@ evbuffer_drain(struct evbuffer *buf, size_t len)
}
buf->first = chain;
EVUTIL_ASSERT(chain && remaining <= chain->off);
EVUTIL_ASSERT(remaining <= chain->off);
chain->misalign += remaining;
chain->off -= remaining;
}
@ -1301,7 +1307,7 @@ evbuffer_remove_buffer(struct evbuffer *src, struct evbuffer *dst,
chain = chain->next;
}
if (nread) {
if (chain != src->first) {
/* we can remove the chain */
struct evbuffer_chain **chp;
chp = evbuffer_free_trailing_empty_chains(dst);
@ -1419,9 +1425,11 @@ evbuffer_pullup(struct evbuffer *buf, ev_ssize_t size)
for (; chain != NULL && (size_t)size >= chain->off; chain = next) {
next = chain->next;
memcpy(buffer, chain->buffer + chain->misalign, chain->off);
size -= chain->off;
buffer += chain->off;
if (chain->buffer) {
memcpy(buffer, chain->buffer + chain->misalign, chain->off);
size -= chain->off;
buffer += chain->off;
}
if (chain == last_with_data)
removed_last_with_data = 1;
if (&chain->next == buf->last_with_datap)
@ -1537,11 +1545,11 @@ evbuffer_find_eol_char(struct evbuffer_ptr *it)
return (-1);
}
static inline int
static inline size_t
evbuffer_strspn(
struct evbuffer_ptr *ptr, const char *chrset)
{
int count = 0;
size_t count = 0;
struct evbuffer_chain *chain = ptr->internal_.chain;
size_t i = ptr->internal_.pos_in_chain;
@ -1827,6 +1835,10 @@ evbuffer_prepend(struct evbuffer *buf, const void *data, size_t datlen)
EVBUFFER_LOCK(buf);
if (datlen == 0) {
result = 0;
goto done;
}
if (buf->freeze_start) {
goto done;
}
@ -1880,7 +1892,7 @@ evbuffer_prepend(struct evbuffer *buf, const void *data, size_t datlen)
if ((tmp = evbuffer_chain_new(datlen)) == NULL)
goto done;
buf->first = tmp;
if (buf->last_with_datap == &buf->first)
if (buf->last_with_datap == &buf->first && chain->off)
buf->last_with_datap = &tmp->next;
tmp->next = chain;
@ -2230,11 +2242,13 @@ evbuffer_read_setup_vecs_(struct evbuffer *buf, ev_ssize_t howmuch,
so_far = 0;
/* Let firstchain be the first chain with any space on it */
firstchainp = buf->last_with_datap;
EVUTIL_ASSERT(*firstchainp);
if (CHAIN_SPACE_LEN(*firstchainp) == 0) {
firstchainp = &(*firstchainp)->next;
}
chain = *firstchainp;
EVUTIL_ASSERT(chain);
for (i = 0; i < n_vecs_avail && so_far < (size_t)howmuch; ++i) {
size_t avail = (size_t) CHAIN_SPACE_LEN(chain);
if (avail > (howmuch - so_far) && exact)
@ -2468,7 +2482,7 @@ evbuffer_write_sendfile(struct evbuffer *buffer, evutil_socket_t dest_fd,
ev_off_t len = chain->off;
#elif defined(SENDFILE_IS_LINUX) || defined(SENDFILE_IS_SOLARIS)
ev_ssize_t res;
ev_off_t offset = chain->misalign;
off_t offset = chain->misalign;
#endif
ASSERT_EVBUFFER_LOCKED(buffer);
@ -3201,7 +3215,6 @@ evbuffer_add_file_segment(struct evbuffer *buf,
}
}
}
++seg->refcnt;
EVLOCK_UNLOCK(seg->lock, 0);
if (buf->freeze_end)
@ -3265,6 +3278,9 @@ evbuffer_add_file_segment(struct evbuffer *buf,
chain->off = length;
}
EVLOCK_LOCK(seg->lock, 0);
++seg->refcnt;
EVLOCK_UNLOCK(seg->lock, 0);
extra->segment = seg;
buf->n_add_for_cb += length;
evbuffer_chain_insert(buf, chain);
@ -3296,7 +3312,7 @@ evbuffer_add_file(struct evbuffer *buf, int fd, ev_off_t offset, ev_off_t length
return r;
}
void
int
evbuffer_setcb(struct evbuffer *buffer, evbuffer_cb cb, void *cbarg)
{
EVBUFFER_LOCK(buffer);
@ -3307,10 +3323,15 @@ evbuffer_setcb(struct evbuffer *buffer, evbuffer_cb cb, void *cbarg)
if (cb) {
struct evbuffer_cb_entry *ent =
evbuffer_add_cb(buffer, NULL, cbarg);
if (!ent) {
EVBUFFER_UNLOCK(buffer);
return -1;
}
ent->cb.cb_obsolete = cb;
ent->flags |= EVBUFFER_CB_OBSOLETE;
}
EVBUFFER_UNLOCK(buffer);
return 0;
}
struct evbuffer_cb_entry *

View File

@ -1,4 +1,5 @@
/* $NetBSD: bufferevent-internal.h,v 1.3 2017/01/31 23:17:39 christos Exp $ */
/* $NetBSD: bufferevent-internal.h,v 1.4 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2008-2012 Niels Provos and Nick Mathewson
*
@ -307,6 +308,13 @@ extern const struct bufferevent_ops bufferevent_ops_pair;
#define BEV_IS_FILTER(bevp) ((bevp)->be_ops == &bufferevent_ops_filter)
#define BEV_IS_PAIR(bevp) ((bevp)->be_ops == &bufferevent_ops_pair)
#if defined(EVENT__HAVE_OPENSSL)
extern const struct bufferevent_ops bufferevent_ops_openssl;
#define BEV_IS_OPENSSL(bevp) ((bevp)->be_ops == &bufferevent_ops_openssl)
#else
#define BEV_IS_OPENSSL(bevp) 0
#endif
#ifdef _WIN32
extern const struct bufferevent_ops bufferevent_ops_async;
#define BEV_IS_ASYNC(bevp) ((bevp)->be_ops == &bufferevent_ops_async)
@ -315,13 +323,16 @@ extern const struct bufferevent_ops bufferevent_ops_async;
#endif
/** Initialize the shared parts of a bufferevent. */
EVENT2_EXPORT_SYMBOL
int bufferevent_init_common_(struct bufferevent_private *, struct event_base *, const struct bufferevent_ops *, enum bufferevent_options options);
/** For internal use: temporarily stop all reads on bufev, until the conditions
* in 'what' are over. */
EVENT2_EXPORT_SYMBOL
void bufferevent_suspend_read_(struct bufferevent *bufev, bufferevent_suspend_flags what);
/** For internal use: clear the conditions 'what' on bufev, and re-enable
* reading if there are no conditions left. */
EVENT2_EXPORT_SYMBOL
void bufferevent_unsuspend_read_(struct bufferevent *bufev, bufferevent_suspend_flags what);
/** For internal use: temporarily stop all writes on bufev, until the conditions
@ -348,16 +359,19 @@ void bufferevent_unsuspend_write_(struct bufferevent *bufev, bufferevent_suspend
@return 0 if successful, or -1 if an error occurred
@see bufferevent_disable()
*/
EVENT2_EXPORT_SYMBOL
int bufferevent_disable_hard_(struct bufferevent *bufev, short event);
/** Internal: Set up locking on a bufferevent. If lock is set, use it.
* Otherwise, use a new lock. */
EVENT2_EXPORT_SYMBOL
int bufferevent_enable_locking_(struct bufferevent *bufev, void *lock);
/** Internal: backwards compat macro for the now public function
* Increment the reference count on bufev. */
#define bufferevent_incref_(bufev) bufferevent_incref(bufev)
/** Internal: Lock bufev and increase its reference count.
* unlocking it otherwise. */
EVENT2_EXPORT_SYMBOL
void bufferevent_incref_and_lock_(struct bufferevent *bufev);
/** Internal: backwards compat macro for the now public function
* Decrement the reference count on bufev. Returns 1 if it freed
@ -366,17 +380,21 @@ void bufferevent_incref_and_lock_(struct bufferevent *bufev);
/** Internal: Drop the reference count on bufev, freeing as necessary, and
* unlocking it otherwise. Returns 1 if it freed the bufferevent. */
EVENT2_EXPORT_SYMBOL
int bufferevent_decref_and_unlock_(struct bufferevent *bufev);
/** Internal: If callbacks are deferred and we have a read callback, schedule
* a readcb. Otherwise just run the readcb. Ignores watermarks. */
EVENT2_EXPORT_SYMBOL
void bufferevent_run_readcb_(struct bufferevent *bufev, int options);
/** Internal: If callbacks are deferred and we have a write callback, schedule
* a writecb. Otherwise just run the writecb. Ignores watermarks. */
EVENT2_EXPORT_SYMBOL
void bufferevent_run_writecb_(struct bufferevent *bufev, int options);
/** Internal: If callbacks are deferred and we have an eventcb, schedule
* it to run with events "what". Otherwise just run the eventcb.
* See bufferevent_trigger_event for meaning of "options". */
EVENT2_EXPORT_SYMBOL
void bufferevent_run_eventcb_(struct bufferevent *bufev, short what, int options);
/** Internal: Run or schedule (if deferred or options contain
@ -400,6 +418,7 @@ bufferevent_trigger_nolock_(struct bufferevent *bufev, short iotype, int options
/** Internal: Add the event 'ev' with timeout tv, unless tv is set to 0, in
* which case add ev with no timeout. */
EVENT2_EXPORT_SYMBOL
int bufferevent_add_event_(struct event *ev, const struct timeval *tv);
/* =========
@ -409,19 +428,33 @@ int bufferevent_add_event_(struct event *ev, const struct timeval *tv);
/** Internal use: Set up the ev_read and ev_write callbacks so that
* the other "generic_timeout" functions will work on it. Call this from
* the constructor function. */
EVENT2_EXPORT_SYMBOL
void bufferevent_init_generic_timeout_cbs_(struct bufferevent *bev);
/** Internal use: Add or delete the generic timeout events as appropriate.
* (If an event is enabled and a timeout is set, we add the event. Otherwise
* we delete it.) Call this from anything that changes the timeout values,
* that enabled EV_READ or EV_WRITE, or that disables EV_READ or EV_WRITE. */
EVENT2_EXPORT_SYMBOL
int bufferevent_generic_adj_timeouts_(struct bufferevent *bev);
EVENT2_EXPORT_SYMBOL
int bufferevent_generic_adj_existing_timeouts_(struct bufferevent *bev);
EVENT2_EXPORT_SYMBOL
enum bufferevent_options bufferevent_get_options_(struct bufferevent *bev);
EVENT2_EXPORT_SYMBOL
const struct sockaddr*
bufferevent_socket_get_conn_address_(struct bufferevent *bev);
EVENT2_EXPORT_SYMBOL
void
bufferevent_socket_set_conn_address_fd_(struct bufferevent *bev, evutil_socket_t fd);
EVENT2_EXPORT_SYMBOL
void
bufferevent_socket_set_conn_address_(struct bufferevent *bev, struct sockaddr *addr, size_t addrlen);
/** Internal use: We have just successfully read data into an inbuf, so
* reset the read timeout (if any). */
#define BEV_RESET_GENERIC_READ_TIMEOUT(bev) \
@ -466,11 +499,15 @@ bufferevent_socket_get_conn_address_(struct bufferevent *bev);
/* ==== For rate-limiting. */
EVENT2_EXPORT_SYMBOL
int bufferevent_decrement_write_buckets_(struct bufferevent_private *bev,
ev_ssize_t bytes);
EVENT2_EXPORT_SYMBOL
int bufferevent_decrement_read_buckets_(struct bufferevent_private *bev,
ev_ssize_t bytes);
EVENT2_EXPORT_SYMBOL
ev_ssize_t bufferevent_get_read_max_(struct bufferevent_private *bev);
EVENT2_EXPORT_SYMBOL
ev_ssize_t bufferevent_get_write_max_(struct bufferevent_private *bev);
int bufferevent_ratelim_init_(struct bufferevent_private *bev);

View File

@ -1,4 +1,5 @@
/* $NetBSD: bufferevent.c,v 1.4 2017/01/31 23:17:39 christos Exp $ */
/* $NetBSD: bufferevent.c,v 1.5 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2002-2007 Niels Provos <provos@citi.umich.edu>
* Copyright (c) 2007-2012 Niels Provos, Nick Mathewson
@ -28,7 +29,7 @@
#include "event2/event-config.h"
#include <sys/cdefs.h>
__RCSID("$NetBSD: bufferevent.c,v 1.4 2017/01/31 23:17:39 christos Exp $");
__RCSID("$NetBSD: bufferevent.c,v 1.5 2021/04/07 03:36:48 christos Exp $");
#include "evconfig-private.h"
#include <sys/types.h>
@ -69,8 +70,7 @@ static void bufferevent_finalize_cb_(struct event_callback *evcb, void *arg_);
void
bufferevent_suspend_read_(struct bufferevent *bufev, bufferevent_suspend_flags what)
{
struct bufferevent_private *bufev_private =
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
struct bufferevent_private *bufev_private = BEV_UPCAST(bufev);
BEV_LOCK(bufev);
if (!bufev_private->read_suspended)
bufev->be_ops->disable(bufev, EV_READ);
@ -81,8 +81,7 @@ bufferevent_suspend_read_(struct bufferevent *bufev, bufferevent_suspend_flags w
void
bufferevent_unsuspend_read_(struct bufferevent *bufev, bufferevent_suspend_flags what)
{
struct bufferevent_private *bufev_private =
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
struct bufferevent_private *bufev_private = BEV_UPCAST(bufev);
BEV_LOCK(bufev);
bufev_private->read_suspended &= ~what;
if (!bufev_private->read_suspended && (bufev->enabled & EV_READ))
@ -93,8 +92,7 @@ bufferevent_unsuspend_read_(struct bufferevent *bufev, bufferevent_suspend_flags
void
bufferevent_suspend_write_(struct bufferevent *bufev, bufferevent_suspend_flags what)
{
struct bufferevent_private *bufev_private =
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
struct bufferevent_private *bufev_private = BEV_UPCAST(bufev);
BEV_LOCK(bufev);
if (!bufev_private->write_suspended)
bufev->be_ops->disable(bufev, EV_WRITE);
@ -105,8 +103,7 @@ bufferevent_suspend_write_(struct bufferevent *bufev, bufferevent_suspend_flags
void
bufferevent_unsuspend_write_(struct bufferevent *bufev, bufferevent_suspend_flags what)
{
struct bufferevent_private *bufev_private =
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
struct bufferevent_private *bufev_private = BEV_UPCAST(bufev);
BEV_LOCK(bufev);
bufev_private->write_suspended &= ~what;
if (!bufev_private->write_suspended && (bufev->enabled & EV_WRITE))
@ -114,6 +111,28 @@ bufferevent_unsuspend_write_(struct bufferevent *bufev, bufferevent_suspend_flag
BEV_UNLOCK(bufev);
}
/**
* Sometimes bufferevent's implementation can overrun high watermarks
* (one of examples is openssl) and in this case if the read callback
* will not handle enough data do over condition above the read
* callback will never be called again (due to suspend above).
*
* To avoid this we are scheduling read callback again here, but only
* from the user callback to avoid multiple scheduling:
* - when the data had been added to it
* - when the data had been drained from it (user specified read callback)
*/
static void bufferevent_inbuf_wm_check(struct bufferevent *bev)
{
if (!bev->wm_read.high)
return;
if (!(bev->enabled & EV_READ))
return;
if (evbuffer_get_length(bev->input) < bev->wm_read.high)
return;
bufferevent_trigger(bev, EV_READ, BEV_OPT_DEFER_CALLBACKS);
}
/* Callback to implement watermarks on the input buffer. Only enabled
* if the watermark is set. */
@ -150,6 +169,7 @@ bufferevent_run_deferred_callbacks_locked(struct event_callback *cb, void *arg)
if (bufev_private->readcb_pending && bufev->readcb) {
bufev_private->readcb_pending = 0;
bufev->readcb(bufev, bufev->cbarg);
bufferevent_inbuf_wm_check(bufev);
}
if (bufev_private->writecb_pending && bufev->writecb) {
bufev_private->writecb_pending = 0;
@ -190,6 +210,7 @@ bufferevent_run_deferred_callbacks_unlocked(struct event_callback *cb, void *arg
void *cbarg = bufev->cbarg;
bufev_private->readcb_pending = 0;
UNLOCKED(readcb(bufev, cbarg));
bufferevent_inbuf_wm_check(bufev);
}
if (bufev_private->writecb_pending && bufev->writecb) {
bufferevent_data_cb writecb = bufev->writecb;
@ -224,8 +245,7 @@ void
bufferevent_run_readcb_(struct bufferevent *bufev, int options)
{
/* Requires that we hold the lock and a reference */
struct bufferevent_private *p =
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
struct bufferevent_private *p = BEV_UPCAST(bufev);
if (bufev->readcb == NULL)
return;
if ((p->options|options) & BEV_OPT_DEFER_CALLBACKS) {
@ -233,6 +253,7 @@ bufferevent_run_readcb_(struct bufferevent *bufev, int options)
SCHEDULE_DEFERRED(p);
} else {
bufev->readcb(bufev, bufev->cbarg);
bufferevent_inbuf_wm_check(bufev);
}
}
@ -240,8 +261,7 @@ void
bufferevent_run_writecb_(struct bufferevent *bufev, int options)
{
/* Requires that we hold the lock and a reference */
struct bufferevent_private *p =
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
struct bufferevent_private *p = BEV_UPCAST(bufev);
if (bufev->writecb == NULL)
return;
if ((p->options|options) & BEV_OPT_DEFER_CALLBACKS) {
@ -269,8 +289,7 @@ void
bufferevent_run_eventcb_(struct bufferevent *bufev, short what, int options)
{
/* Requires that we hold the lock and a reference */
struct bufferevent_private *p =
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
struct bufferevent_private *p = BEV_UPCAST(bufev);
if (bufev->errorcb == NULL)
return;
if ((p->options|options) & BEV_OPT_DEFER_CALLBACKS) {
@ -300,14 +319,12 @@ bufferevent_init_common_(struct bufferevent_private *bufev_private,
if (!bufev->input) {
if ((bufev->input = evbuffer_new()) == NULL)
return -1;
goto err;
}
if (!bufev->output) {
if ((bufev->output = evbuffer_new()) == NULL) {
evbuffer_free(bufev->input);
return -1;
}
if ((bufev->output = evbuffer_new()) == NULL)
goto err;
}
bufev_private->refcnt = 1;
@ -319,7 +336,8 @@ bufferevent_init_common_(struct bufferevent_private *bufev_private,
bufev->be_ops = ops;
bufferevent_ratelim_init_(bufev_private);
if (bufferevent_ratelim_init_(bufev_private))
goto err;
/*
* Set to EV_WRITE so that using bufferevent_write is going to
@ -330,20 +348,14 @@ bufferevent_init_common_(struct bufferevent_private *bufev_private,
#ifndef EVENT__DISABLE_THREAD_SUPPORT
if (options & BEV_OPT_THREADSAFE) {
if (bufferevent_enable_locking_(bufev, NULL) < 0) {
/* cleanup */
evbuffer_free(bufev->input);
evbuffer_free(bufev->output);
bufev->input = NULL;
bufev->output = NULL;
return -1;
}
if (bufferevent_enable_locking_(bufev, NULL) < 0)
goto err;
}
#endif
if ((options & (BEV_OPT_DEFER_CALLBACKS|BEV_OPT_UNLOCK_CALLBACKS))
== BEV_OPT_UNLOCK_CALLBACKS) {
event_warnx("UNLOCK_CALLBACKS requires DEFER_CALLBACKS");
return -1;
goto err;
}
if (options & BEV_OPT_UNLOCK_CALLBACKS)
event_deferred_cb_init_(
@ -364,6 +376,17 @@ bufferevent_init_common_(struct bufferevent_private *bufev_private,
evbuffer_set_parent_(bufev->output, bufev);
return 0;
err:
if (bufev->input) {
evbuffer_free(bufev->input);
bufev->input = NULL;
}
if (bufev->output) {
evbuffer_free(bufev->output);
bufev->output = NULL;
}
return -1;
}
void
@ -462,8 +485,7 @@ bufferevent_read_buffer(struct bufferevent *bufev, struct evbuffer *buf)
int
bufferevent_enable(struct bufferevent *bufev, short event)
{
struct bufferevent_private *bufev_private =
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
struct bufferevent_private *bufev_private = BEV_UPCAST(bufev);
short impl_events = event;
int r = 0;
@ -477,6 +499,8 @@ bufferevent_enable(struct bufferevent *bufev, short event)
if (impl_events && bufev->be_ops->enable(bufev, impl_events) < 0)
r = -1;
if (r)
event_debug(("%s: cannot enable 0x%hx on %p", __func__, event, bufev));
bufferevent_decref_and_unlock_(bufev);
return r;
@ -536,8 +560,7 @@ int
bufferevent_disable_hard_(struct bufferevent *bufev, short event)
{
int r = 0;
struct bufferevent_private *bufev_private =
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
struct bufferevent_private *bufev_private = BEV_UPCAST(bufev);
BEV_LOCK(bufev);
bufev->enabled &= ~event;
@ -560,6 +583,8 @@ bufferevent_disable(struct bufferevent *bufev, short event)
if (bufev->be_ops->disable(bufev, event) < 0)
r = -1;
if (r)
event_debug(("%s: cannot disable 0x%hx on %p", __func__, event, bufev));
BEV_UNLOCK(bufev);
return r;
@ -573,8 +598,7 @@ void
bufferevent_setwatermark(struct bufferevent *bufev, short events,
size_t lowmark, size_t highmark)
{
struct bufferevent_private *bufev_private =
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
struct bufferevent_private *bufev_private = BEV_UPCAST(bufev);
BEV_LOCK(bufev);
if (events & EV_WRITE) {
@ -659,8 +683,7 @@ bufferevent_flush(struct bufferevent *bufev,
void
bufferevent_incref_and_lock_(struct bufferevent *bufev)
{
struct bufferevent_private *bufev_private =
BEV_UPCAST(bufev);
struct bufferevent_private *bufev_private = BEV_UPCAST(bufev);
BEV_LOCK(bufev);
++bufev_private->refcnt;
}
@ -686,8 +709,7 @@ bufferevent_transfer_lock_ownership_(struct bufferevent *donor,
int
bufferevent_decref_and_unlock_(struct bufferevent *bufev)
{
struct bufferevent_private *bufev_private =
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
struct bufferevent_private *bufev_private = BEV_UPCAST(bufev);
int n_cbs = 0;
#define MAX_CBS 16
struct event_callback *cbs[MAX_CBS];
@ -730,8 +752,7 @@ bufferevent_finalize_cb_(struct event_callback *evcb, void *arg_)
{
struct bufferevent *bufev = arg_;
struct bufferevent *underlying;
struct bufferevent_private *bufev_private =
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
struct bufferevent_private *bufev_private = BEV_UPCAST(bufev);
BEV_LOCK(bufev);
underlying = bufferevent_get_underlying(bufev);
@ -797,8 +818,7 @@ bufferevent_free(struct bufferevent *bufev)
void
bufferevent_incref(struct bufferevent *bufev)
{
struct bufferevent_private *bufev_private =
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
struct bufferevent_private *bufev_private = BEV_UPCAST(bufev);
/* XXX: now that this function is public, we might want to
* - return the count from this function
@ -854,6 +874,8 @@ bufferevent_setfd(struct bufferevent *bev, evutil_socket_t fd)
BEV_LOCK(bev);
if (bev->be_ops->ctrl)
res = bev->be_ops->ctrl(bev, BEV_CTRL_SET_FD, &d);
if (res)
event_debug(("%s: cannot set fd for %p to "EV_SOCK_FMT, __func__, bev, fd));
BEV_UNLOCK(bev);
return res;
}
@ -867,6 +889,8 @@ bufferevent_getfd(struct bufferevent *bev)
BEV_LOCK(bev);
if (bev->be_ops->ctrl)
res = bev->be_ops->ctrl(bev, BEV_CTRL_GET_FD, &d);
if (res)
event_debug(("%s: cannot get fd for %p", __func__, bev));
BEV_UNLOCK(bev);
return (res<0) ? -1 : d.fd;
}
@ -874,8 +898,7 @@ bufferevent_getfd(struct bufferevent *bev)
enum bufferevent_options
bufferevent_get_options_(struct bufferevent *bev)
{
struct bufferevent_private *bev_p =
EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
struct bufferevent_private *bev_p = BEV_UPCAST(bev);
enum bufferevent_options options;
BEV_LOCK(bev);
@ -951,8 +974,7 @@ int
bufferevent_generic_adj_timeouts_(struct bufferevent *bev)
{
const short enabled = bev->enabled;
struct bufferevent_private *bev_p =
EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
struct bufferevent_private *bev_p = BEV_UPCAST(bev);
int r1=0, r2=0;
if ((enabled & EV_READ) && !bev_p->read_suspended &&
evutil_timerisset(&bev->timeout_read))

View File

@ -1,4 +1,4 @@
/* $NetBSD: bufferevent_openssl.c,v 1.1.1.3 2021/04/07 02:43:14 christos Exp $ */
/* $NetBSD: bufferevent_openssl.c,v 1.2 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2009-2012 Niels Provos and Nick Mathewson
*
@ -32,7 +32,7 @@
#include "event2/event-config.h"
#include <sys/cdefs.h>
__RCSID("$NetBSD: bufferevent_openssl.c,v 1.1.1.3 2021/04/07 02:43:14 christos Exp $");
__RCSID("$NetBSD: bufferevent_openssl.c,v 1.2 2021/04/07 03:36:48 christos Exp $");
#include "evconfig-private.h"
#include <sys/types.h>
@ -1466,7 +1466,7 @@ bufferevent_openssl_socket_new(struct event_base *base,
This is probably an error on our part. Fail. */
goto err;
}
BIO_set_close(bio, 0);
(void)BIO_set_close(bio, 0);
} else {
/* The SSL isn't configured with a BIO with an fd. */
if (fd >= 0) {

View File

@ -1,4 +1,5 @@
/* $NetBSD: bufferevent_ratelim.c,v 1.3 2017/01/31 23:17:39 christos Exp $ */
/* $NetBSD: bufferevent_ratelim.c,v 1.4 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
* Copyright (c) 2002-2006 Niels Provos <provos@citi.umich.edu>
@ -561,8 +562,7 @@ int
bufferevent_set_rate_limit(struct bufferevent *bev,
struct ev_token_bucket_cfg *cfg)
{
struct bufferevent_private *bevp =
EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
struct bufferevent_private *bevp = BEV_UPCAST(bev);
int r = -1;
struct bufferevent_rate_limit *rlim;
struct timeval now;
@ -738,8 +738,7 @@ bufferevent_add_to_rate_limit_group(struct bufferevent *bev,
struct bufferevent_rate_limit_group *g)
{
int wsuspend, rsuspend;
struct bufferevent_private *bevp =
EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
struct bufferevent_private *bevp = BEV_UPCAST(bev);
BEV_LOCK(bev);
if (!bevp->rate_limiting) {
@ -790,8 +789,7 @@ int
bufferevent_remove_from_rate_limit_group_internal_(struct bufferevent *bev,
int unsuspend)
{
struct bufferevent_private *bevp =
EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
struct bufferevent_private *bevp = BEV_UPCAST(bev);
BEV_LOCK(bev);
if (bevp->rate_limiting && bevp->rate_limiting->group) {
struct bufferevent_rate_limit_group *g =

View File

@ -1,347 +0,0 @@
#! /bin/sh
# Wrapper for compilers which do not understand '-c -o'.
scriptversion=2012-10-14.11; # UTC
# Copyright (C) 1999-2014 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
nl='
'
# We need space, tab and new line, in precisely that order. Quoting is
# there to prevent tools from complaining about whitespace usage.
IFS=" "" $nl"
file_conv=
# func_file_conv build_file lazy
# Convert a $build file to $host form and store it in $file
# Currently only supports Windows hosts. If the determined conversion
# type is listed in (the comma separated) LAZY, no conversion will
# take place.
func_file_conv ()
{
file=$1
case $file in
/ | /[!/]*) # absolute file, and not a UNC file
if test -z "$file_conv"; then
# lazily determine how to convert abs files
case `uname -s` in
MINGW*)
file_conv=mingw
;;
CYGWIN*)
file_conv=cygwin
;;
*)
file_conv=wine
;;
esac
fi
case $file_conv/,$2, in
*,$file_conv,*)
;;
mingw/*)
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
;;
cygwin/*)
file=`cygpath -m "$file" || echo "$file"`
;;
wine/*)
file=`winepath -w "$file" || echo "$file"`
;;
esac
;;
esac
}
# func_cl_dashL linkdir
# Make cl look for libraries in LINKDIR
func_cl_dashL ()
{
func_file_conv "$1"
if test -z "$lib_path"; then
lib_path=$file
else
lib_path="$lib_path;$file"
fi
linker_opts="$linker_opts -LIBPATH:$file"
}
# func_cl_dashl library
# Do a library search-path lookup for cl
func_cl_dashl ()
{
lib=$1
found=no
save_IFS=$IFS
IFS=';'
for dir in $lib_path $LIB
do
IFS=$save_IFS
if $shared && test -f "$dir/$lib.dll.lib"; then
found=yes
lib=$dir/$lib.dll.lib
break
fi
if test -f "$dir/$lib.lib"; then
found=yes
lib=$dir/$lib.lib
break
fi
if test -f "$dir/lib$lib.a"; then
found=yes
lib=$dir/lib$lib.a
break
fi
done
IFS=$save_IFS
if test "$found" != yes; then
lib=$lib.lib
fi
}
# func_cl_wrapper cl arg...
# Adjust compile command to suit cl
func_cl_wrapper ()
{
# Assume a capable shell
lib_path=
shared=:
linker_opts=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
eat=1
case $2 in
*.o | *.[oO][bB][jJ])
func_file_conv "$2"
set x "$@" -Fo"$file"
shift
;;
*)
func_file_conv "$2"
set x "$@" -Fe"$file"
shift
;;
esac
;;
-I)
eat=1
func_file_conv "$2" mingw
set x "$@" -I"$file"
shift
;;
-I*)
func_file_conv "${1#-I}" mingw
set x "$@" -I"$file"
shift
;;
-l)
eat=1
func_cl_dashl "$2"
set x "$@" "$lib"
shift
;;
-l*)
func_cl_dashl "${1#-l}"
set x "$@" "$lib"
shift
;;
-L)
eat=1
func_cl_dashL "$2"
;;
-L*)
func_cl_dashL "${1#-L}"
;;
-static)
shared=false
;;
-Wl,*)
arg=${1#-Wl,}
save_ifs="$IFS"; IFS=','
for flag in $arg; do
IFS="$save_ifs"
linker_opts="$linker_opts $flag"
done
IFS="$save_ifs"
;;
-Xlinker)
eat=1
linker_opts="$linker_opts $2"
;;
-*)
set x "$@" "$1"
shift
;;
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
func_file_conv "$1"
set x "$@" -Tp"$file"
shift
;;
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
func_file_conv "$1" mingw
set x "$@" "$file"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -n "$linker_opts"; then
linker_opts="-link$linker_opts"
fi
exec "$@" $linker_opts
exit 1
}
eat=
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: compile [--help] [--version] PROGRAM [ARGS]
Wrapper for compilers which do not understand '-c -o'.
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
arguments, and rename the output as expected.
If you are trying to build a whole package this is not the
right script to run: please start by reading the file 'INSTALL'.
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "compile $scriptversion"
exit $?
;;
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
func_cl_wrapper "$@" # Doesn't return...
;;
esac
ofile=
cfile=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
# So we strip '-o arg' only if arg is an object.
eat=1
case $2 in
*.o | *.obj)
ofile=$2
;;
*)
set x "$@" -o "$2"
shift
;;
esac
;;
*.c)
cfile=$1
set x "$@" "$1"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -z "$ofile" || test -z "$cfile"; then
# If no '-o' option was seen then we might have been invoked from a
# pattern rule where we don't need one. That is ok -- this is a
# normal compilation that the losing compiler can handle. If no
# '.c' file was seen then we are probably linking. That is also
# ok.
exec "$@"
fi
# Name of file we expect compiler to create.
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
# Create the lock directory.
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
# that we are using for the .o file. Also, base the name on the expected
# object file name, since that is what matters with a parallel build.
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
while true; do
if mkdir "$lockdir" >/dev/null 2>&1; then
break
fi
sleep 1
done
# FIXME: race condition here if user kills between mkdir and trap.
trap "rmdir '$lockdir'; exit 1" 1 2 15
# Run the compile.
"$@"
ret=$?
if test -f "$cofile"; then
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
elif test -f "${cofile}bj"; then
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
fi
rmdir "$lockdir"
exit $ret
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,791 +0,0 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2013-05-30.07; # UTC
# Copyright (C) 1999-2014 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
Run PROGRAMS ARGS to compile a file, generating dependencies
as side-effects.
Environment variables:
depmode Dependency tracking mode.
source Source file read by 'PROGRAMS ARGS'.
object Object file output by 'PROGRAMS ARGS'.
DEPDIR directory where to store dependencies.
depfile Dependency file to output.
tmpdepfile Temporary file to use when outputting dependencies.
libtool Whether libtool is used (yes/no).
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "depcomp $scriptversion"
exit $?
;;
esac
# Get the directory component of the given path, and save it in the
# global variables '$dir'. Note that this directory component will
# be either empty or ending with a '/' character. This is deliberate.
set_dir_from ()
{
case $1 in
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
*) dir=;;
esac
}
# Get the suffix-stripped basename of the given path, and save it the
# global variable '$base'.
set_base_from ()
{
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
}
# If no dependency file was actually created by the compiler invocation,
# we still have to create a dummy depfile, to avoid errors with the
# Makefile "include basename.Plo" scheme.
make_dummy_depfile ()
{
echo "#dummy" > "$depfile"
}
# Factor out some common post-processing of the generated depfile.
# Requires the auxiliary global variable '$tmpdepfile' to be set.
aix_post_process_depfile ()
{
# If the compiler actually managed to produce a dependency file,
# post-process it.
if test -f "$tmpdepfile"; then
# Each line is of the form 'foo.o: dependency.h'.
# Do two passes, one to just change these to
# $object: dependency.h
# and one to simply output
# dependency.h:
# which is needed to avoid the deleted-header problem.
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
} > "$depfile"
rm -f "$tmpdepfile"
else
make_dummy_depfile
fi
}
# A tabulation character.
tab=' '
# A newline character.
nl='
'
# Character ranges might be problematic outside the C locale.
# These definitions help.
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
lower=abcdefghijklmnopqrstuvwxyz
digits=0123456789
alpha=${upper}${lower}
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
fi
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
depfile=${depfile-`echo "$object" |
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
rm -f "$tmpdepfile"
# Avoid interferences from the environment.
gccflag= dashmflag=
# Some modes work just like other modes, but use different flags. We
# parameterize here, but still list the modes in the big case below,
# to make depend.m4 easier to write. Note that we *cannot* use a case
# here, because this file can only contain one case statement.
if test "$depmode" = hp; then
# HP compiler uses -M and no extra arg.
gccflag=-M
depmode=gcc
fi
if test "$depmode" = dashXmstdout; then
# This is just like dashmstdout with a different argument.
dashmflag=-xM
depmode=dashmstdout
fi
cygpath_u="cygpath -u -f -"
if test "$depmode" = msvcmsys; then
# This is just like msvisualcpp but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvisualcpp
fi
if test "$depmode" = msvc7msys; then
# This is just like msvc7 but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvc7
fi
if test "$depmode" = xlc; then
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
gccflag=-qmakedep=gcc,-MF
depmode=gcc
fi
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
## it if -MD -MP comes after the -MF stuff. Hmm.
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
## the command line argument order; so add the flags where they
## appear in depend2.am. Note that the slowdown incurred here
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
for arg
do
case $arg in
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
*) set fnord "$@" "$arg" ;;
esac
shift # fnord
shift # $arg
done
"$@"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
mv "$tmpdepfile" "$depfile"
;;
gcc)
## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
## (see the conditional assignment to $gccflag above).
## There are various ways to get dependency output from gcc. Here's
## why we pick this rather obscure method:
## - Don't want to use -MD because we'd like the dependencies to end
## up in a subdir. Having to rename by hand is ugly.
## (We might end up doing this anyway to support other compilers.)
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
## -MM, not -M (despite what the docs say). Also, it might not be
## supported by the other compilers which use the 'gcc' depmode.
## - Using -M directly means running the compiler twice (even worse
## than renaming).
if test -z "$gccflag"; then
gccflag=-MD,
fi
"$@" -Wp,"$gccflag$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The second -e expression handles DOS-style file names with drive
# letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
## This next piece of magic avoids the "deleted header file" problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
## Some versions of gcc put a space before the ':'. On the theory
## that the space means something, we add a space to the output as
## well. hp depmode also adds that space, but also prefixes the VPATH
## to the object. Take care to not repeat it in the output.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
sgi)
if test "$libtool" = yes; then
"$@" "-Wp,-MDupdate,$tmpdepfile"
else
"$@" -MDupdate "$tmpdepfile"
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
echo "$object : \\" > "$depfile"
# Clip off the initial element (the dependent). Don't try to be
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
# the IRIX cc adds comments like '#:fec' to the end of the
# dependency line.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
| tr "$nl" ' ' >> "$depfile"
echo >> "$depfile"
# The second pass generates a dummy entry for each header file.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile"
;;
xlc)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
# current directory. Also, the AIX compiler puts '$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.u
tmpdepfile2=$base.u
tmpdepfile3=$dir.libs/$base.u
"$@" -Wc,-M
else
tmpdepfile1=$dir$base.u
tmpdepfile2=$dir$base.u
tmpdepfile3=$dir$base.u
"$@" -M
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
aix_post_process_depfile
;;
tcc)
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
# FIXME: That version still under development at the moment of writing.
# Make that this statement remains true also for stable, released
# versions.
# It will wrap lines (doesn't matter whether long or short) with a
# trailing '\', as in:
#
# foo.o : \
# foo.c \
# foo.h \
#
# It will put a trailing '\' even on the last line, and will use leading
# spaces rather than leading tabs (at least since its commit 0394caf7
# "Emit spaces for -MD").
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
# We have to change lines of the first kind to '$object: \'.
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
# And for each line of the second kind, we have to emit a 'dep.h:'
# dummy dependency, to avoid the deleted-header problem.
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
rm -f "$tmpdepfile"
;;
## The order of this option in the case statement is important, since the
## shell code in configure will try each of these formats in the order
## listed in this file. A plain '-MD' option would be understood by many
## compilers, so we must ensure this comes after the gcc and icc options.
pgcc)
# Portland's C compiler understands '-MD'.
# Will always output deps to 'file.d' where file is the root name of the
# source file under compilation, even if file resides in a subdirectory.
# The object file name does not affect the name of the '.d' file.
# pgcc 10.2 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using '\' :
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
set_dir_from "$object"
# Use the source, not the object, to determine the base name, since
# that's sadly what pgcc will do too.
set_base_from "$source"
tmpdepfile=$base.d
# For projects that build the same source file twice into different object
# files, the pgcc approach of using the *source* file root name can cause
# problems in parallel builds. Use a locking strategy to avoid stomping on
# the same $tmpdepfile.
lockdir=$base.d-lock
trap "
echo '$0: caught signal, cleaning up...' >&2
rmdir '$lockdir'
exit 1
" 1 2 13 15
numtries=100
i=$numtries
while test $i -gt 0; do
# mkdir is a portable test-and-set.
if mkdir "$lockdir" 2>/dev/null; then
# This process acquired the lock.
"$@" -MD
stat=$?
# Release the lock.
rmdir "$lockdir"
break
else
# If the lock is being held by a different process, wait
# until the winning process is done or we timeout.
while test -d "$lockdir" && test $i -gt 0; do
sleep 1
i=`expr $i - 1`
done
fi
i=`expr $i - 1`
done
trap - 1 2 13 15
if test $i -le 0; then
echo "$0: failed to acquire lock after $numtries attempts" >&2
echo "$0: check lockdir '$lockdir'" >&2
exit 1
fi
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each line is of the form `foo.o: dependent.h',
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp2)
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
# compilers, which have integrated preprocessors. The correct option
# to use with these is +Maked; it writes dependencies to a file named
# 'foo.d', which lands next to the object file, wherever that
# happens to be.
# Much of this is similar to the tru64 case; see comments there.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir.libs/$base.d
"$@" -Wc,+Maked
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
"$@" +Maked
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
# Add 'dependent.h:' lines.
sed -ne '2,${
s/^ *//
s/ \\*$//
s/$/:/
p
}' "$tmpdepfile" >> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile" "$tmpdepfile2"
;;
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
# dependencies in 'foo.d' instead, so we check for that too.
# Subdirectories are respected.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
# Libtool generates 2 separate objects for the 2 libraries. These
# two compilations output dependencies in $dir.libs/$base.o.d and
# in $dir$base.o.d. We have to check for both files, because
# one of the two compilations can be disabled. We should prefer
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
# automatically cleaned when .libs/ is deleted, while ignoring
# the former would cause a distcleancheck panic.
tmpdepfile1=$dir$base.o.d # libtool 1.5
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
"$@" -Wc,-MD
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
tmpdepfile3=$dir$base.d
"$@" -MD
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
# Same post-processing that is required for AIX mode.
aix_post_process_depfile
;;
msvc7)
if test "$libtool" = yes; then
showIncludes=-Wc,-showIncludes
else
showIncludes=-showIncludes
fi
"$@" $showIncludes > "$tmpdepfile"
stat=$?
grep -v '^Note: including file: ' "$tmpdepfile"
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The first sed program below extracts the file names and escapes
# backslashes for cygpath. The second sed program outputs the file
# name when reading, but also accumulates all include files in the
# hold buffer in order to output them again at the end. This only
# works with sed implementations that can handle large buffers.
sed < "$tmpdepfile" -n '
/^Note: including file: *\(.*\)/ {
s//\1/
s/\\/\\\\/g
p
}' | $cygpath_u | sort -u | sed -n '
s/ /\\ /g
s/\(.*\)/'"$tab"'\1 \\/p
s/.\(.*\) \\/\1:/
H
$ {
s/.*/'"$tab"'/
G
p
}' >> "$depfile"
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
rm -f "$tmpdepfile"
;;
msvc7msys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
#nosideeffect)
# This comment above is used by automake to tell side-effect
# dependency tracking mechanisms from slower ones.
dashmstdout)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
test -z "$dashmflag" && dashmflag=-M
# Require at least two characters before searching for ':'
# in the target name. This is to cope with DOS-style filenames:
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
"$@" $dashmflag |
sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this sed invocation
# correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
dashXmstdout)
# This case only exists to satisfy depend.m4. It is never actually
# run, as this mode is specially recognized in the preamble.
exit 1
;;
makedepend)
"$@" || exit $?
# Remove any Libtool call
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# X makedepend
shift
cleared=no eat=no
for arg
do
case $cleared in
no)
set ""; shift
cleared=yes ;;
esac
if test $eat = yes; then
eat=no
continue
fi
case "$arg" in
-D*|-I*)
set fnord "$@" "$arg"; shift ;;
# Strip any option that makedepend may not understand. Remove
# the object too, otherwise makedepend will parse it as a source file.
-arch)
eat=yes ;;
-*|$object)
;;
*)
set fnord "$@" "$arg"; shift ;;
esac
done
obj_suffix=`echo "$object" | sed 's/^.*\././'`
touch "$tmpdepfile"
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
rm -f "$depfile"
# makedepend may prepend the VPATH from the source file name to the object.
# No need to regex-escape $object, excess matching of '.' is harmless.
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process the last invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed '1,2d' "$tmpdepfile" \
| tr ' ' "$nl" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile" "$tmpdepfile".bak
;;
cpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
"$@" -E \
| sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
| sed '$ s: \\$::' > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
cat < "$tmpdepfile" >> "$depfile"
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvisualcpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
IFS=" "
for arg
do
case "$arg" in
-o)
shift
;;
$object)
shift
;;
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
set fnord "$@"
shift
shift
;;
*)
set fnord "$@" "$arg"
shift
shift
;;
esac
done
"$@" -E 2>/dev/null |
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
echo "$tab" >> "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvcmsys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
none)
exec "$@"
;;
*)
echo "Unknown depmode $depmode" 1>&2
exit 1
;;
esac
exit 0
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

View File

@ -1,4 +1,5 @@
/* $NetBSD: evbuffer-internal.h,v 1.4 2017/01/31 23:17:39 christos Exp $ */
/* $NetBSD: evbuffer-internal.h,v 1.5 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
@ -93,7 +94,7 @@ struct evbuffer {
* If the buffer has no chains, it is NULL.
*
* The last_with_datap pointer points at _whatever 'next' pointer_
* points at the last_with_datap chain. If the last_with_data chain
* pointing at the last_with_data chain. If the last_with_data chain
* is the first chain, or it is NULL, then the last_with_datap pointer
* is &buf->first.
*/

View File

@ -1,50 +0,0 @@
/* $NetBSD: evconfig-private.h,v 1.1.1.1 2017/01/31 21:14:52 christos Exp $ */
/* evconfig-private.h. Generated from evconfig-private.h.in by configure. */
/* evconfig-private.h template - see "Configuration Header Templates" */
/* in AC manual. Kevin Bowling <kevin.bowling@kev009.com */
#ifndef EVCONFIG_PRIVATE_H_INCLUDED_
#define EVCONFIG_PRIVATE_H_INCLUDED_
/* Enable extensions on AIX 3, Interix. */
#ifndef _ALL_SOURCE
# define _ALL_SOURCE 1
#endif
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE 1
#endif
/* Enable threading extensions on Solaris. */
#ifndef _POSIX_PTHREAD_SEMANTICS
# define _POSIX_PTHREAD_SEMANTICS 1
#endif
/* Enable extensions on HP NonStop. */
#ifndef _TANDEM_SOURCE
# define _TANDEM_SOURCE 1
#endif
/* Enable general extensions on Solaris. */
#ifndef __EXTENSIONS__
# define __EXTENSIONS__ 1
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
/* #undef _FILE_OFFSET_BITS */
/* Define for large files, on AIX-style hosts. */
/* #undef _LARGE_FILES */
/* Define to 1 if on MINIX. */
#ifndef _MINIX
/* #undef _MINIX */
#endif
/* Define to 2 if the system does not provide POSIX.1 features except with
this defined. */
#ifndef _POSIX_1_SOURCE
/* #undef _POSIX_1_SOURCE */
#endif
/* Define to 1 if you need to in order for `stat' and other things to work. */
#ifndef _POSIX_SOURCE
/* #undef _POSIX_SOURCE */
#endif
#endif

View File

@ -1,4 +1,5 @@
/* $NetBSD: evdns.c,v 1.4 2017/01/31 23:17:39 christos Exp $ */
/* $NetBSD: evdns.c,v 1.5 2021/04/07 03:36:48 christos Exp $ */
/* Copyright 2006-2007 Niels Provos
* Copyright 2007-2012 Nick Mathewson and Niels Provos
*
@ -51,7 +52,7 @@
#include "event2/event-config.h"
#include <sys/cdefs.h>
__RCSID("$NetBSD: evdns.c,v 1.4 2017/01/31 23:17:39 christos Exp $");
__RCSID("$NetBSD: evdns.c,v 1.5 2021/04/07 03:36:48 christos Exp $");
#include "evconfig-private.h"
#include <sys/types.h>
@ -80,6 +81,7 @@ __RCSID("$NetBSD: evdns.c,v 1.4 2017/01/31 23:17:39 christos Exp $");
#include <stdarg.h>
#ifdef _WIN32
#include <winsock2.h>
#include <winerror.h>
#include <ws2tcpip.h>
#ifndef _WIN32_IE
#define _WIN32_IE 0x400
@ -349,6 +351,9 @@ struct evdns_base {
struct timeval global_getaddrinfo_allow_skew;
int so_rcvbuf;
int so_sndbuf;
int getaddrinfo_ipv4_timeouts;
int getaddrinfo_ipv6_timeouts;
int getaddrinfo_ipv4_answered;
@ -866,6 +871,19 @@ reply_schedule_callback(struct request *const req, u32 ttl, u32 err, struct repl
&d->deferred);
}
#define _QR_MASK 0x8000U
#define _OP_MASK 0x7800U
#define _AA_MASK 0x0400U
#define _TC_MASK 0x0200U
#define _RD_MASK 0x0100U
#define _RA_MASK 0x0080U
#define _Z_MASK 0x0040U
#define _AD_MASK 0x0020U
#define _CD_MASK 0x0010U
#define _RCODE_MASK 0x000fU
#define _Z_MASK_DEPRECATED 0x0070U
/* this processes a parsed reply packet */
static void
reply_handle(struct request *const req, u16 flags, u32 ttl, struct reply *reply) {
@ -879,12 +897,12 @@ reply_handle(struct request *const req, u16 flags, u32 ttl, struct reply *reply)
ASSERT_LOCKED(req->base);
ASSERT_VALID_REQUEST(req);
if (flags & 0x020f || !reply || !reply->have_answer) {
if (flags & (_RCODE_MASK | _TC_MASK) || !reply || !reply->have_answer) {
/* there was an error */
if (flags & 0x0200) {
if (flags & _TC_MASK) {
error = DNS_ERR_TRUNCATED;
} else if (flags & 0x000f) {
u16 error_code = (flags & 0x000f) - 1;
} else if (flags & _RCODE_MASK) {
u16 error_code = (flags & _RCODE_MASK) - 1;
if (error_code > 4) {
error = DNS_ERR_UNKNOWN;
} else {
@ -1049,8 +1067,8 @@ reply_parse(struct evdns_base *base, u8 *packet, int length) {
memset(&reply, 0, sizeof(reply));
/* If it's not an answer, it doesn't correspond to any request. */
if (!(flags & 0x8000)) return -1; /* must be an answer */
if ((flags & 0x020f) && (flags & 0x020f) != DNS_ERR_NOTEXIST) {
if (!(flags & _QR_MASK)) return -1; /* must be an answer */
if ((flags & (_RCODE_MASK|_TC_MASK)) && (flags & (_RCODE_MASK|_TC_MASK)) != DNS_ERR_NOTEXIST) {
/* there was an error and it's not NXDOMAIN */
goto err;
}
@ -1239,8 +1257,8 @@ request_parse(u8 *packet, int length, struct evdns_server_port *port, struct soc
(void)additional;
(void)authority;
if (flags & 0x8000) return -1; /* Must not be an answer. */
flags &= 0x0110; /* Only RD and CD get preserved. */
if (flags & _QR_MASK) return -1; /* Must not be an answer. */
flags &= (_RD_MASK|_CD_MASK); /* Only RD and CD get preserved. */
server_req = mm_malloc(sizeof(struct server_request));
if (server_req == NULL) return -1;
@ -1280,7 +1298,7 @@ request_parse(u8 *packet, int length, struct evdns_server_port *port, struct soc
port->refcnt++;
/* Only standard queries are supported. */
if (flags & 0x7800) {
if (flags & _OP_MASK) {
evdns_server_request_respond(&(server_req->base), DNS_ERR_NOTIMPL);
return -1;
}
@ -1289,14 +1307,12 @@ request_parse(u8 *packet, int length, struct evdns_server_port *port, struct soc
return 0;
err:
if (server_req) {
if (server_req->base.questions) {
for (i = 0; i < server_req->base.nquestions; ++i)
mm_free(server_req->base.questions[i]);
mm_free(server_req->base.questions);
}
mm_free(server_req);
if (server_req->base.questions) {
for (i = 0; i < server_req->base.nquestions; ++i)
mm_free(server_req->base.questions[i]);
mm_free(server_req->base.questions);
}
mm_free(server_req);
return -1;
#undef SKIP_NAME
@ -1754,6 +1770,7 @@ evdns_close_server_port(struct evdns_server_port *port)
server_port_free(port);
} else {
port->closing = 1;
EVDNS_UNLOCK(port);
}
}
@ -1907,7 +1924,7 @@ evdns_server_request_format_response(struct server_request *req, int err)
/* Set response bit and error code; copy OPCODE and RD fields from
* question; copy RA and AA if set by caller. */
flags = req->base.flags;
flags |= (0x8000 | err);
flags |= (_QR_MASK | err);
dnslabel_table_init(&table);
APPEND16(req->trans_id);
@ -2268,10 +2285,11 @@ evdns_request_transmit(struct request *req) {
nameserver_write_waiting(req->ns, 1);
return 1;
case 2:
/* failed to transmit the request entirely. */
/* failed to transmit the request entirely. we can fallthrough since
* we'll set a timeout, which will time out, and make us retransmit the
* request anyway. */
retcode = 1;
/* fall through: we'll set a timeout, which will time out,
* and make us retransmit the request anyway. */
EVUTIL_FALLTHROUGH;
default:
/* all ok */
log(EVDNS_LOG_DEBUG,
@ -2528,6 +2546,23 @@ evdns_nameserver_add_impl_(struct evdns_base *base, const struct sockaddr *addre
}
}
if (base->so_rcvbuf) {
if (setsockopt(ns->socket, SOL_SOCKET, SO_RCVBUF,
(void *)&base->so_rcvbuf, sizeof(base->so_rcvbuf))) {
log(EVDNS_LOG_WARN, "Couldn't set SO_RCVBUF to %i", base->so_rcvbuf);
err = -SO_RCVBUF;
goto out2;
}
}
if (base->so_sndbuf) {
if (setsockopt(ns->socket, SOL_SOCKET, SO_SNDBUF,
(void *)&base->so_sndbuf, sizeof(base->so_sndbuf))) {
log(EVDNS_LOG_WARN, "Couldn't set SO_SNDBUF to %i", base->so_sndbuf);
err = -SO_SNDBUF;
goto out2;
}
}
memcpy(&ns->address, address, addrlen);
ns->addrlen = addrlen;
ns->state = 1;
@ -3316,10 +3351,16 @@ search_request_finished(struct evdns_request *const handle) {
static void
evdns_resolv_set_defaults(struct evdns_base *base, int flags) {
int add_default = flags & DNS_OPTION_NAMESERVERS;
if (flags & DNS_OPTION_NAMESERVERS_NO_DEFAULT)
add_default = 0;
/* if the file isn't found then we assume a local resolver */
ASSERT_LOCKED(base);
if (flags & DNS_OPTION_SEARCH) search_set_from_hostname(base);
if (flags & DNS_OPTION_NAMESERVERS) evdns_base_nameserver_ip_add(base,"127.0.0.1");
if (flags & DNS_OPTION_SEARCH)
search_set_from_hostname(base);
if (add_default)
evdns_base_nameserver_ip_add(base, "127.0.0.1");
}
#ifndef EVENT__HAVE_STRTOK_R
@ -3494,6 +3535,7 @@ evdns_base_set_option_impl(struct evdns_base *base,
base->global_max_retransmits = retries;
} else if (str_matches_option(option, "randomize-case:")) {
int randcase = strtoint(val);
if (randcase == -1) return -1;
if (!(flags & DNS_OPTION_MISC)) return 0;
base->global_randomize_case = randcase;
} else if (str_matches_option(option, "bind-to:")) {
@ -3515,6 +3557,18 @@ evdns_base_set_option_impl(struct evdns_base *base,
val);
memcpy(&base->global_nameserver_probe_initial_timeout, &tv,
sizeof(tv));
} else if (str_matches_option(option, "so-rcvbuf:")) {
int buf = strtoint(val);
if (buf == -1) return -1;
if (!(flags & DNS_OPTION_MISC)) return 0;
log(EVDNS_LOG_DEBUG, "Setting SO_RCVBUF to %s", val);
base->so_rcvbuf = buf;
} else if (str_matches_option(option, "so-sndbuf:")) {
int buf = strtoint(val);
if (buf == -1) return -1;
if (!(flags & DNS_OPTION_MISC)) return 0;
log(EVDNS_LOG_DEBUG, "Setting SO_SNDBUF to %s", val);
base->so_sndbuf = buf;
}
return 0;
}
@ -3615,9 +3669,14 @@ evdns_base_resolv_conf_parse_impl(struct evdns_base *base, int flags, const char
char *resolv;
char *start;
int err = 0;
int add_default;
log(EVDNS_LOG_DEBUG, "Parsing resolv.conf file %s", filename);
add_default = flags & DNS_OPTION_NAMESERVERS;
if (flags & DNS_OPTION_NAMESERVERS_NO_DEFAULT)
add_default = 0;
if (flags & DNS_OPTION_HOSTSFILE) {
char *fname = evdns_get_default_hosts_filename();
evdns_base_load_hosts(base, fname);
@ -3625,6 +3684,11 @@ evdns_base_resolv_conf_parse_impl(struct evdns_base *base, int flags, const char
mm_free(fname);
}
if (!filename) {
evdns_resolv_set_defaults(base, flags);
return 1;
}
if ((err = evutil_read_file_(filename, &resolv, &n, 0)) < 0) {
if (err == -1) {
/* No file. */
@ -3648,7 +3712,7 @@ evdns_base_resolv_conf_parse_impl(struct evdns_base *base, int flags, const char
}
}
if (!base->server_head && (flags & DNS_OPTION_NAMESERVERS)) {
if (!base->server_head && add_default) {
/* no nameservers were configured. */
evdns_base_nameserver_ip_add(base, "127.0.0.1");
err = 6;
@ -3949,7 +4013,12 @@ evdns_base_new(struct event_base *event_base, int flags)
TAILQ_INIT(&base->hostsdb);
#define EVDNS_BASE_ALL_FLAGS (0x8001)
#define EVDNS_BASE_ALL_FLAGS ( \
EVDNS_BASE_INITIALIZE_NAMESERVERS | \
EVDNS_BASE_DISABLE_WHEN_INACTIVE | \
EVDNS_BASE_NAMESERVERS_NO_DEFAULT | \
0)
if (flags & ~EVDNS_BASE_ALL_FLAGS) {
flags = EVDNS_BASE_INITIALIZE_NAMESERVERS;
log(EVDNS_LOG_WARN,
@ -3960,12 +4029,17 @@ evdns_base_new(struct event_base *event_base, int flags)
if (flags & EVDNS_BASE_INITIALIZE_NAMESERVERS) {
int r;
int opts = DNS_OPTIONS_ALL;
if (flags & EVDNS_BASE_NAMESERVERS_NO_DEFAULT) {
opts |= DNS_OPTION_NAMESERVERS_NO_DEFAULT;
}
#ifdef _WIN32
r = evdns_base_config_windows_nameservers(base);
#else
r = evdns_base_resolv_conf_parse(base, DNS_OPTIONS_ALL, "/etc/resolv.conf");
r = evdns_base_resolv_conf_parse(base, opts, "/etc/resolv.conf");
#endif
if (r == -1) {
if (r) {
evdns_base_free_and_unlock(base, 0);
return NULL;
}
@ -4039,6 +4113,11 @@ evdns_base_free_and_unlock(struct evdns_base *base, int fail_requests)
/* TODO(nickm) we might need to refcount here. */
while (base->req_waiting_head) {
if (fail_requests)
reply_schedule_callback(base->req_waiting_head, 0, DNS_ERR_SHUTDOWN, NULL);
request_finished(base->req_waiting_head, &base->req_waiting_head, 1);
}
for (i = 0; i < base->n_req_heads; ++i) {
while (base->req_heads[i]) {
if (fail_requests)
@ -4046,11 +4125,6 @@ evdns_base_free_and_unlock(struct evdns_base *base, int fail_requests)
request_finished(base->req_heads[i], &REQ_HEAD(base, base->req_heads[i]->trans_id), 1);
}
}
while (base->req_waiting_head) {
if (fail_requests)
reply_schedule_callback(base->req_waiting_head, 0, DNS_ERR_SHUTDOWN, NULL);
request_finished(base->req_waiting_head, &base->req_waiting_head, 1);
}
base->global_requests_inflight = base->global_requests_waiting = 0;
for (server = base->server_head; server; server = server_next) {
@ -4639,6 +4713,7 @@ evdns_getaddrinfo(struct evdns_base *dns_base,
int err;
int port = 0;
int want_cname = 0;
int started = 0;
if (!dns_base) {
dns_base = current_base;
@ -4717,6 +4792,8 @@ evdns_getaddrinfo(struct evdns_base *dns_base,
* launching those requests. (XXX we don't do that yet.)
*/
EVDNS_LOCK(dns_base);
if (hints.ai_family != PF_INET6) {
log(EVDNS_LOG_DEBUG, "Sending request for %s on ipv4 as %p",
nodename, &data->ipv4_request);
@ -4743,7 +4820,11 @@ evdns_getaddrinfo(struct evdns_base *dns_base,
evtimer_assign(&data->timeout, dns_base->event_base,
evdns_getaddrinfo_timeout_cb, data);
if (data->ipv4_request.r || data->ipv6_request.r) {
started = (data->ipv4_request.r || data->ipv6_request.r);
EVDNS_UNLOCK(dns_base);
if (started) {
return data;
} else {
mm_free(data);

View File

@ -1,4 +1,5 @@
/* $NetBSD: event-internal.h,v 1.3 2017/01/31 23:17:39 christos Exp $ */
/* $NetBSD: event-internal.h,v 1.4 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
@ -220,7 +221,7 @@ struct event_base {
/** Function pointers used to describe the backend that this event_base
* uses for signals */
const struct eventop *evsigsel;
/** Data to implement the common signal handelr code. */
/** Data to implement the common signal handler code. */
struct evsig_info sig;
/** Number of virtual events */
@ -369,6 +370,10 @@ struct event_config {
};
/* Internal use only: Functions that might be missing from <sys/queue.h> */
#ifndef LIST_END
#define LIST_END(head) NULL
#endif
#ifndef TAILQ_FIRST
#define TAILQ_FIRST(head) ((head)->tqh_first)
#endif
@ -415,23 +420,26 @@ int event_add_nolock_(struct event *ev,
* if it is running in another thread and it doesn't have EV_FINALIZE set.
*/
#define EVENT_DEL_AUTOBLOCK 2
/** Argument for event_del_nolock_. Tells event_del to procede even if the
/** Argument for event_del_nolock_. Tells event_del to proceed even if the
* event is set up for finalization rather for regular use.*/
#define EVENT_DEL_EVEN_IF_FINALIZING 3
int event_del_nolock_(struct event *ev, int blocking);
int event_remove_timer_nolock_(struct event *ev);
void event_active_nolock_(struct event *ev, int res, short count);
EVENT2_EXPORT_SYMBOL
int event_callback_activate_(struct event_base *, struct event_callback *);
int event_callback_activate_nolock_(struct event_base *, struct event_callback *);
int event_callback_cancel_(struct event_base *base,
struct event_callback *evcb);
void event_callback_finalize_nolock_(struct event_base *base, unsigned flags, struct event_callback *evcb, void (*cb)(struct event_callback *, void *));
EVENT2_EXPORT_SYMBOL
void event_callback_finalize_(struct event_base *base, unsigned flags, struct event_callback *evcb, void (*cb)(struct event_callback *, void *));
int event_callback_finalize_many_(struct event_base *base, int n_cbs, struct event_callback **evcb, void (*cb)(struct event_callback *, void *));
EVENT2_EXPORT_SYMBOL
void event_active_later_(struct event *ev, int res);
void event_active_later_nolock_(struct event *ev, int res);
int event_callback_activate_later_nolock_(struct event_base *base,
@ -442,6 +450,7 @@ void event_callback_init_(struct event_base *base,
struct event_callback *cb);
/* FIXME document. */
EVENT2_EXPORT_SYMBOL
void event_base_add_virtual_(struct event_base *base);
void event_base_del_virtual_(struct event_base *base);
@ -451,6 +460,7 @@ void event_base_del_virtual_(struct event_base *base);
Returns on success; aborts on failure.
*/
EVENT2_EXPORT_SYMBOL
void event_base_assert_ok_(struct event_base *base);
void event_base_assert_ok_nolock_(struct event_base *base);

View File

@ -1,4 +1,5 @@
/* $NetBSD: event.c,v 1.4 2017/01/31 23:17:39 christos Exp $ */
/* $NetBSD: event.c,v 1.5 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
@ -27,7 +28,7 @@
*/
#include "event2/event-config.h"
#include <sys/cdefs.h>
__RCSID("$NetBSD: event.c,v 1.4 2017/01/31 23:17:39 christos Exp $");
__RCSID("$NetBSD: event.c,v 1.5 2021/04/07 03:36:48 christos Exp $");
#include "evconfig-private.h"
#ifdef _WIN32
@ -55,6 +56,9 @@ __RCSID("$NetBSD: event.c,v 1.4 2017/01/31 23:17:39 christos Exp $");
#include <string.h>
#include <time.h>
#include <limits.h>
#ifdef EVENT__HAVE_FCNTL_H
#include <fcntl.h>
#endif
#include "event2/event.h"
#include "event2/event_struct.h"
@ -126,6 +130,7 @@ static const struct eventop *eventops[] = {
};
/* Global state; deprecated */
EVENT2_EXPORT_SYMBOL
struct event_base *event_global_current_base_ = NULL;
#define current_base event_global_current_base_
@ -231,133 +236,169 @@ HT_PROTOTYPE(event_debug_map, event_debug_entry, node, hash_debug_entry,
HT_GENERATE(event_debug_map, event_debug_entry, node, hash_debug_entry,
eq_debug_entry, 0.5, mm_malloc, mm_realloc, mm_free)
/* Macro: record that ev is now setup (that is, ready for an add) */
#define event_debug_note_setup_(ev) do { \
if (event_debug_mode_on_) { \
struct event_debug_entry *dent,find; \
find.ptr = (ev); \
EVLOCK_LOCK(event_debug_map_lock_, 0); \
dent = HT_FIND(event_debug_map, &global_debug_map, &find); \
if (dent) { \
dent->added = 0; \
} else { \
dent = mm_malloc(sizeof(*dent)); \
if (!dent) \
event_err(1, \
"Out of memory in debugging code"); \
dent->ptr = (ev); \
dent->added = 0; \
HT_INSERT(event_debug_map, &global_debug_map, dent); \
} \
EVLOCK_UNLOCK(event_debug_map_lock_, 0); \
} \
event_debug_mode_too_late = 1; \
} while (/*CONSTCOND*/0)
/* Macro: record that ev is no longer setup */
#define event_debug_note_teardown_(ev) do { \
if (event_debug_mode_on_) { \
struct event_debug_entry *dent,find; \
find.ptr = (ev); \
EVLOCK_LOCK(event_debug_map_lock_, 0); \
dent = HT_REMOVE(event_debug_map, &global_debug_map, &find); \
if (dent) \
mm_free(dent); \
EVLOCK_UNLOCK(event_debug_map_lock_, 0); \
} \
event_debug_mode_too_late = 1; \
} while (/*CONSTCOND*/0)
/* record that ev is now setup (that is, ready for an add) */
static void event_debug_note_setup_(const struct event *ev)
{
struct event_debug_entry *dent, find;
if (!event_debug_mode_on_)
goto out;
find.ptr = ev;
EVLOCK_LOCK(event_debug_map_lock_, 0);
dent = HT_FIND(event_debug_map, &global_debug_map, &find);
if (dent) {
dent->added = 0;
} else {
dent = mm_malloc(sizeof(*dent));
if (!dent)
event_err(1,
"Out of memory in debugging code");
dent->ptr = ev;
dent->added = 0;
HT_INSERT(event_debug_map, &global_debug_map, dent);
}
EVLOCK_UNLOCK(event_debug_map_lock_, 0);
out:
event_debug_mode_too_late = 1;
}
/* record that ev is no longer setup */
static void event_debug_note_teardown_(const struct event *ev)
{
struct event_debug_entry *dent, find;
if (!event_debug_mode_on_)
goto out;
find.ptr = ev;
EVLOCK_LOCK(event_debug_map_lock_, 0);
dent = HT_REMOVE(event_debug_map, &global_debug_map, &find);
if (dent)
mm_free(dent);
EVLOCK_UNLOCK(event_debug_map_lock_, 0);
out:
event_debug_mode_too_late = 1;
}
/* Macro: record that ev is now added */
#define event_debug_note_add_(ev) do { \
if (event_debug_mode_on_) { \
struct event_debug_entry *dent,find; \
find.ptr = (ev); \
EVLOCK_LOCK(event_debug_map_lock_, 0); \
dent = HT_FIND(event_debug_map, &global_debug_map, &find); \
if (dent) { \
dent->added = 1; \
} else { \
event_errx(EVENT_ERR_ABORT_, \
"%s: noting an add on a non-setup event %p" \
" (events: 0x%x, fd: "EV_SOCK_FMT \
", flags: 0x%x)", \
__func__, (ev), (ev)->ev_events, \
EV_SOCK_ARG((ev)->ev_fd), (ev)->ev_flags); \
} \
EVLOCK_UNLOCK(event_debug_map_lock_, 0); \
} \
event_debug_mode_too_late = 1; \
} while (/*CONSTCOND*/0)
/* Macro: record that ev is no longer added */
#define event_debug_note_del_(ev) do { \
if (event_debug_mode_on_) { \
struct event_debug_entry *dent,find; \
find.ptr = (ev); \
EVLOCK_LOCK(event_debug_map_lock_, 0); \
dent = HT_FIND(event_debug_map, &global_debug_map, &find); \
if (dent) { \
dent->added = 0; \
} else { \
event_errx(EVENT_ERR_ABORT_, \
"%s: noting a del on a non-setup event %p" \
" (events: 0x%x, fd: "EV_SOCK_FMT \
", flags: 0x%x)", \
__func__, (ev), (ev)->ev_events, \
EV_SOCK_ARG((ev)->ev_fd), (ev)->ev_flags); \
} \
EVLOCK_UNLOCK(event_debug_map_lock_, 0); \
} \
event_debug_mode_too_late = 1; \
} while (/*CONSTCOND*/0)
/* Macro: assert that ev is setup (i.e., okay to add or inspect) */
#define event_debug_assert_is_setup_(ev) do { \
if (event_debug_mode_on_) { \
struct event_debug_entry *dent,find; \
find.ptr = (ev); \
EVLOCK_LOCK(event_debug_map_lock_, 0); \
dent = HT_FIND(event_debug_map, &global_debug_map, &find); \
if (!dent) { \
event_errx(EVENT_ERR_ABORT_, \
"%s called on a non-initialized event %p" \
" (events: 0x%x, fd: "EV_SOCK_FMT\
", flags: 0x%x)", \
__func__, (ev), (ev)->ev_events, \
EV_SOCK_ARG((ev)->ev_fd), (ev)->ev_flags); \
} \
EVLOCK_UNLOCK(event_debug_map_lock_, 0); \
} \
} while (/*CONSTCOND*/0)
/* Macro: assert that ev is not added (i.e., okay to tear down or set
* up again) */
#define event_debug_assert_not_added_(ev) do { \
if (event_debug_mode_on_) { \
struct event_debug_entry *dent,find; \
find.ptr = (ev); \
EVLOCK_LOCK(event_debug_map_lock_, 0); \
dent = HT_FIND(event_debug_map, &global_debug_map, &find); \
if (dent && dent->added) { \
event_errx(EVENT_ERR_ABORT_, \
"%s called on an already added event %p" \
" (events: 0x%x, fd: "EV_SOCK_FMT", " \
"flags: 0x%x)", \
__func__, (ev), (ev)->ev_events, \
EV_SOCK_ARG((ev)->ev_fd), (ev)->ev_flags); \
} \
EVLOCK_UNLOCK(event_debug_map_lock_, 0); \
} \
} while (/*CONSTCOND*/0)
static void event_debug_note_add_(const struct event *ev)
{
struct event_debug_entry *dent,find;
if (!event_debug_mode_on_)
goto out;
find.ptr = ev;
EVLOCK_LOCK(event_debug_map_lock_, 0);
dent = HT_FIND(event_debug_map, &global_debug_map, &find);
if (dent) {
dent->added = 1;
} else {
event_errx(EVENT_ERR_ABORT_,
"%s: noting an add on a non-setup event %p"
" (events: 0x%x, fd: "EV_SOCK_FMT
", flags: 0x%x)",
__func__, ev, ev->ev_events,
EV_SOCK_ARG(ev->ev_fd), ev->ev_flags);
}
EVLOCK_UNLOCK(event_debug_map_lock_, 0);
out:
event_debug_mode_too_late = 1;
}
/* record that ev is no longer added */
static void event_debug_note_del_(const struct event *ev)
{
struct event_debug_entry *dent, find;
if (!event_debug_mode_on_)
goto out;
find.ptr = ev;
EVLOCK_LOCK(event_debug_map_lock_, 0);
dent = HT_FIND(event_debug_map, &global_debug_map, &find);
if (dent) {
dent->added = 0;
} else {
event_errx(EVENT_ERR_ABORT_,
"%s: noting a del on a non-setup event %p"
" (events: 0x%x, fd: "EV_SOCK_FMT
", flags: 0x%x)",
__func__, ev, ev->ev_events,
EV_SOCK_ARG(ev->ev_fd), ev->ev_flags);
}
EVLOCK_UNLOCK(event_debug_map_lock_, 0);
out:
event_debug_mode_too_late = 1;
}
/* assert that ev is setup (i.e., okay to add or inspect) */
static void event_debug_assert_is_setup_(const struct event *ev)
{
struct event_debug_entry *dent, find;
if (!event_debug_mode_on_)
return;
find.ptr = ev;
EVLOCK_LOCK(event_debug_map_lock_, 0);
dent = HT_FIND(event_debug_map, &global_debug_map, &find);
if (!dent) {
event_errx(EVENT_ERR_ABORT_,
"%s called on a non-initialized event %p"
" (events: 0x%x, fd: "EV_SOCK_FMT
", flags: 0x%x)",
__func__, ev, ev->ev_events,
EV_SOCK_ARG(ev->ev_fd), ev->ev_flags);
}
EVLOCK_UNLOCK(event_debug_map_lock_, 0);
}
/* assert that ev is not added (i.e., okay to tear down or set up again) */
static void event_debug_assert_not_added_(const struct event *ev)
{
struct event_debug_entry *dent, find;
if (!event_debug_mode_on_)
return;
find.ptr = ev;
EVLOCK_LOCK(event_debug_map_lock_, 0);
dent = HT_FIND(event_debug_map, &global_debug_map, &find);
if (dent && dent->added) {
event_errx(EVENT_ERR_ABORT_,
"%s called on an already added event %p"
" (events: 0x%x, fd: "EV_SOCK_FMT", "
"flags: 0x%x)",
__func__, ev, ev->ev_events,
EV_SOCK_ARG(ev->ev_fd), ev->ev_flags);
}
EVLOCK_UNLOCK(event_debug_map_lock_, 0);
}
static void event_debug_assert_socket_nonblocking_(evutil_socket_t fd)
{
if (!event_debug_mode_on_)
return;
if (fd < 0)
return;
#ifndef _WIN32
{
int flags;
if ((flags = fcntl(fd, F_GETFL, NULL)) >= 0) {
EVUTIL_ASSERT(flags & O_NONBLOCK);
}
}
#endif
}
#else
#define event_debug_note_setup_(ev) \
((void)0)
#define event_debug_note_teardown_(ev) \
((void)0)
#define event_debug_note_add_(ev) \
((void)0)
#define event_debug_note_del_(ev) \
((void)0)
#define event_debug_assert_is_setup_(ev) \
((void)0)
#define event_debug_assert_not_added_(ev) \
((void)0)
static void event_debug_note_setup_(const struct event *ev) { (void)ev; }
static void event_debug_note_teardown_(const struct event *ev) { (void)ev; }
static void event_debug_note_add_(const struct event *ev) { (void)ev; }
static void event_debug_note_del_(const struct event *ev) { (void)ev; }
static void event_debug_assert_is_setup_(const struct event *ev) { (void)ev; }
static void event_debug_assert_not_added_(const struct event *ev) { (void)ev; }
static void event_debug_assert_socket_nonblocking_(evutil_socket_t fd) { (void)fd; }
#endif
#define EVENT_BASE_ASSERT_LOCKED(base) \
@ -593,7 +634,9 @@ event_base_new_with_config(const struct event_config *cfg)
int flags;
if (should_check_environment && !precise_time) {
precise_time = evutil_getenv_("EVENT_PRECISE_TIMER") != NULL;
base->flags |= EVENT_BASE_FLAG_PRECISE_TIMER;
if (precise_time) {
base->flags |= EVENT_BASE_FLAG_PRECISE_TIMER;
}
}
flags = precise_time ? EV_MONOT_PRECISE : 0;
evutil_configure_monotonic_time_(&base->monotonic_timer, flags);
@ -865,7 +908,8 @@ event_base_free_(struct event_base *base, int run_finalizers)
* A simple case is bufferevent with underlying (i.e. filters).
*/
int ii = event_base_free_queues_(base, run_finalizers);
if (!ii) {
event_debug(("%s: %d events freed", __func__, ii));
if (!i) {
break;
}
n_deleted += ii;
@ -1643,10 +1687,12 @@ event_process_active_single_queue(struct event_base *base,
break;
case EV_CLOSURE_EVENT: {
void (*evcb_callback)(evutil_socket_t, short, void *);
short res;
EVUTIL_ASSERT(ev != NULL);
evcb_callback = *ev->ev_callback;
res = ev->ev_res;
EVBASE_RELEASE_LOCK(base, th_base_lock);
evcb_callback(ev->ev_fd, ev->ev_res, ev->ev_arg);
evcb_callback(ev->ev_fd, res, ev->ev_arg);
}
break;
case EV_CLOSURE_CB_SELF: {
@ -1664,8 +1710,8 @@ event_process_active_single_queue(struct event_base *base,
evcb_evfinalize = ev->ev_evcallback.evcb_cb_union.evcb_evfinalize;
EVUTIL_ASSERT((evcb->evcb_flags & EVLIST_FINALIZING));
EVBASE_RELEASE_LOCK(base, th_base_lock);
evcb_evfinalize(ev, ev->ev_arg);
event_debug_note_teardown_(ev);
evcb_evfinalize(ev, ev->ev_arg);
if (evcb_closure == EV_CLOSURE_EVENT_FINALIZE_FREE)
mm_free(ev);
}
@ -2014,6 +2060,9 @@ event_base_once(struct event_base *base, evutil_socket_t fd, short events,
int res = 0;
int activate = 0;
if (!base)
return (-1);
/* We cannot support signals that just fire once, or persistent
* events. */
if (events & (EV_SIGNAL|EV_PERSIST))
@ -2072,6 +2121,8 @@ event_assign(struct event *ev, struct event_base *base, evutil_socket_t fd, shor
if (arg == &event_self_cbarg_ptr_)
arg = ev;
if (!(events & EV_SIGNAL))
event_debug_assert_socket_nonblocking_(fd);
event_debug_assert_not_added_(ev);
ev->ev_base = base;
@ -2722,17 +2773,16 @@ static int
event_del_(struct event *ev, int blocking)
{
int res;
struct event_base *base = ev->ev_base;
if (EVUTIL_FAILURE_CHECK(!ev->ev_base)) {
if (EVUTIL_FAILURE_CHECK(!base)) {
event_warnx("%s: event has no event_base set.", __func__);
return -1;
}
EVBASE_ACQUIRE_LOCK(ev->ev_base, th_base_lock);
EVBASE_ACQUIRE_LOCK(base, th_base_lock);
res = event_del_nolock_(ev, blocking);
EVBASE_RELEASE_LOCK(ev->ev_base, th_base_lock);
EVBASE_RELEASE_LOCK(base, th_base_lock);
return (res);
}
@ -2782,21 +2832,7 @@ event_del_nolock_(struct event *ev, int blocking)
}
}
/* If the main thread is currently executing this event's callback,
* and we are not the main thread, then we want to wait until the
* callback is done before we start removing the event. That way,
* when this function returns, it will be safe to free the
* user-supplied argument. */
base = ev->ev_base;
#ifndef EVENT__DISABLE_THREAD_SUPPORT
if (blocking != EVENT_DEL_NOBLOCK &&
base->current_event == event_to_event_callback(ev) &&
!EVBASE_IN_THREAD(base) &&
(blocking == EVENT_DEL_BLOCK || !(ev->ev_events & EV_FINALIZE))) {
++base->current_event_waiters;
EVTHREAD_COND_WAIT(base->current_event_cond, base->th_base_lock);
}
#endif
EVUTIL_ASSERT(!(ev->ev_flags & ~EVLIST_ALL));
@ -2835,6 +2871,10 @@ event_del_nolock_(struct event *ev, int blocking)
notify = 1;
res = 0;
}
/* If we do not have events, let's notify event base so it can
* exit without waiting */
if (!event_haveevents(base) && !N_ACTIVE_CALLBACKS(base))
notify = 1;
}
/* if we are not in the right thread, we need to wake up the loop */
@ -2843,6 +2883,21 @@ event_del_nolock_(struct event *ev, int blocking)
event_debug_note_del_(ev);
/* If the main thread is currently executing this event's callback,
* and we are not the main thread, then we want to wait until the
* callback is done before returning. That way, when this function
* returns, it will be safe to free the user-supplied argument.
*/
#ifndef EVENT__DISABLE_THREAD_SUPPORT
if (blocking != EVENT_DEL_NOBLOCK &&
base->current_event == event_to_event_callback(ev) &&
!EVBASE_IN_THREAD(base) &&
(blocking == EVENT_DEL_BLOCK || !(ev->ev_events & EV_FINALIZE))) {
++base->current_event_waiters;
EVTHREAD_COND_WAIT(base->current_event_cond, base->th_base_lock);
}
#endif
return (res);
}
@ -2963,6 +3018,7 @@ event_callback_activate_nolock_(struct event_base *base,
switch (evcb->evcb_flags & (EVLIST_ACTIVE|EVLIST_ACTIVE_LATER)) {
default:
EVUTIL_ASSERT(0);
EVUTIL_FALLTHROUGH;
case EVLIST_ACTIVE_LATER:
event_queue_remove_active_later(base, evcb);
r = 0;
@ -3151,10 +3207,6 @@ timeout_process(struct event_base *base)
}
}
#if (EVLIST_INTERNAL >> 4) != 1
#error "Mismatch for value of EVLIST_INTERNAL"
#endif
#ifndef MAX
#define MAX(a,b) (((a)>(b))?(a):(b))
#endif
@ -3162,13 +3214,13 @@ timeout_process(struct event_base *base)
#define MAX_EVENT_COUNT(var, v) var = MAX(var, v)
/* These are a fancy way to spell
if (flags & EVLIST_INTERNAL)
if (~flags & EVLIST_INTERNAL)
base->event_count--/++;
*/
#define DECR_EVENT_COUNT(base,flags) \
((base)->event_count -= (~((flags) >> 4) & 1))
((base)->event_count -= !((flags) & EVLIST_INTERNAL))
#define INCR_EVENT_COUNT(base,flags) do { \
((base)->event_count += (~((flags) >> 4) & 1)); \
((base)->event_count += !((flags) & EVLIST_INTERNAL)); \
MAX_EVENT_COUNT((base)->event_count_max, (base)->event_count); \
} while (0)
@ -3700,13 +3752,14 @@ dump_inserted_event_fn(const struct event_base *base, const struct event *e, voi
if (! (e->ev_flags & (EVLIST_INSERTED|EVLIST_TIMEOUT)))
return 0;
fprintf(output, " %p [%s "EV_SOCK_FMT"]%s%s%s%s%s%s",
fprintf(output, " %p [%s "EV_SOCK_FMT"]%s%s%s%s%s%s%s",
e, gloss, EV_SOCK_ARG(e->ev_fd),
(e->ev_events&EV_READ)?" Read":"",
(e->ev_events&EV_WRITE)?" Write":"",
(e->ev_events&EV_CLOSED)?" EOF":"",
(e->ev_events&EV_SIGNAL)?" Signal":"",
(e->ev_events&EV_PERSIST)?" Persist":"",
(e->ev_events&EV_ET)?" ET":"",
(e->ev_flags&EVLIST_INTERNAL)?" Internal":"");
if (e->ev_flags & EVLIST_TIMEOUT) {
struct timeval tv;
@ -3777,7 +3830,35 @@ void
event_base_active_by_fd(struct event_base *base, evutil_socket_t fd, short events)
{
EVBASE_ACQUIRE_LOCK(base, th_base_lock);
evmap_io_active_(base, fd, events & (EV_READ|EV_WRITE|EV_CLOSED));
/* Activate any non timer events */
if (!(events & EV_TIMEOUT)) {
evmap_io_active_(base, fd, events & (EV_READ|EV_WRITE|EV_CLOSED));
} else {
/* If we want to activate timer events, loop and activate each event with
* the same fd in both the timeheap and common timeouts list */
int i;
unsigned u;
struct event *ev;
for (u = 0; u < base->timeheap.n; ++u) {
ev = base->timeheap.p[u];
if (ev->ev_fd == fd) {
event_active_nolock_(ev, EV_TIMEOUT, 1);
}
}
for (i = 0; i < base->n_common_timeouts; ++i) {
struct common_timeout_list *ctl = base->common_timeout_queues[i];
TAILQ_FOREACH(ev, &ctl->events,
ev_timeout_pos.ev_next_with_common_timeout) {
if (ev->ev_fd == fd) {
event_active_nolock_(ev, EV_TIMEOUT, 1);
}
}
}
}
EVBASE_RELEASE_LOCK(base, th_base_lock);
}

View File

@ -1,4 +1,5 @@
/* $NetBSD: event_tagging.c,v 1.4 2017/01/31 23:17:39 christos Exp $ */
/* $NetBSD: event_tagging.c,v 1.5 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2003-2009 Niels Provos <provos@citi.umich.edu>
* Copyright (c) 2009-2012 Niels Provos and Nick Mathewson
@ -28,7 +29,7 @@
#include "event2/event-config.h"
#include <sys/cdefs.h>
__RCSID("$NetBSD: event_tagging.c,v 1.4 2017/01/31 23:17:39 christos Exp $");
__RCSID("$NetBSD: event_tagging.c,v 1.5 2021/04/07 03:36:48 christos Exp $");
#include "evconfig-private.h"
#ifdef EVENT__HAVE_SYS_TYPES_H
@ -96,9 +97,13 @@ __RCSID("$NetBSD: event_tagging.c,v 1.4 2017/01/31 23:17:39 christos Exp $");
a final padding nibble with value 0 is appended.
*/
EVENT2_EXPORT_SYMBOL
int evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf);
EVENT2_EXPORT_SYMBOL
int evtag_decode_int64(ev_uint64_t *pnumber, struct evbuffer *evbuf);
EVENT2_EXPORT_SYMBOL
int evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t tag);
EVENT2_EXPORT_SYMBOL
int evtag_decode_tag(ev_uint32_t *ptag, struct evbuffer *evbuf);
void

View File

@ -1,4 +1,5 @@
/* $NetBSD: evmap.c,v 1.3 2017/01/31 23:17:39 christos Exp $ */
/* $NetBSD: evmap.c,v 1.4 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
*
@ -26,7 +27,7 @@
*/
#include "event2/event-config.h"
#include <sys/cdefs.h>
__RCSID("$NetBSD: evmap.c,v 1.3 2017/01/31 23:17:39 christos Exp $");
__RCSID("$NetBSD: evmap.c,v 1.4 2021/04/07 03:36:48 christos Exp $");
#include "evconfig-private.h"
#ifdef _WIN32
@ -46,6 +47,7 @@ __RCSID("$NetBSD: evmap.c,v 1.3 2017/01/31 23:17:39 christos Exp $");
#include <unistd.h>
#endif
#include <errno.h>
#include <limits.h>
#include <signal.h>
#include <string.h>
#include <time.h>
@ -210,9 +212,15 @@ evmap_make_space(struct event_signal_map *map, int slot, int msize)
int nentries = map->nentries ? map->nentries : 32;
void **tmp;
if (slot > INT_MAX / 2)
return (-1);
while (nentries <= slot)
nentries <<= 1;
if (nentries > INT_MAX / msize)
return (-1);
tmp = (void **)mm_realloc(map->entries, nentries * msize);
if (tmp == NULL)
return (-1);
@ -396,7 +404,8 @@ evmap_io_del_(struct event_base *base, evutil_socket_t fd, struct event *ev)
if (res) {
void *extra = ((char*)ctx) + sizeof(struct evmap_io);
if (evsel->del(base, ev->ev_fd, old, res, extra) == -1) {
if (evsel->del(base, ev->ev_fd,
old, (ev->ev_events & EV_ET) | res, extra) == -1) {
retval = -1;
} else {
retval = 1;
@ -427,7 +436,7 @@ evmap_io_active_(struct event_base *base, evutil_socket_t fd, short events)
if (NULL == ctx)
return;
LIST_FOREACH(ev, &ctx->events, ev_io_next) {
if (ev->ev_events & events)
if (ev->ev_events & (events & ~EV_ET))
event_active_nolock_(ev, ev->ev_events & events, 1);
}
}
@ -448,6 +457,9 @@ evmap_signal_add_(struct event_base *base, int sig, struct event *ev)
struct event_signal_map *map = &base->sigmap;
struct evmap_signal *ctx = NULL;
if (sig < 0 || sig >= NSIG)
return (-1);
if (sig >= map->nentries) {
if (evmap_make_space(
map, sig, sizeof(struct evmap_signal *)) == -1)
@ -474,7 +486,7 @@ evmap_signal_del_(struct event_base *base, int sig, struct event *ev)
struct event_signal_map *map = &base->sigmap;
struct evmap_signal *ctx;
if (sig >= map->nentries)
if (sig < 0 || sig >= map->nentries)
return (-1);
GET_SIGNAL_SLOT(ctx, map, sig, evmap_signal);
@ -861,6 +873,7 @@ event_changelist_add_(struct event_base *base, evutil_socket_t fd, short old, sh
struct event_changelist *changelist = &base->changelist;
struct event_changelist_fdinfo *fdinfo = p;
struct event_change *change;
ev_uint8_t evchange = EV_CHANGE_ADD | (events & (EV_ET|EV_PERSIST|EV_SIGNAL));
event_changelist_check(base);
@ -872,18 +885,12 @@ event_changelist_add_(struct event_base *base, evutil_socket_t fd, short old, sh
* since the delete might fail (because the fd had been closed since
* the last add, for instance. */
if (events & (EV_READ|EV_SIGNAL)) {
change->read_change = EV_CHANGE_ADD |
(events & (EV_ET|EV_PERSIST|EV_SIGNAL));
}
if (events & EV_WRITE) {
change->write_change = EV_CHANGE_ADD |
(events & (EV_ET|EV_PERSIST|EV_SIGNAL));
}
if (events & EV_CLOSED) {
change->close_change = EV_CHANGE_ADD |
(events & (EV_ET|EV_PERSIST|EV_SIGNAL));
}
if (events & (EV_READ|EV_SIGNAL))
change->read_change = evchange;
if (events & EV_WRITE)
change->write_change = evchange;
if (events & EV_CLOSED)
change->close_change = evchange;
event_changelist_check(base);
return (0);
@ -896,6 +903,7 @@ event_changelist_del_(struct event_base *base, evutil_socket_t fd, short old, sh
struct event_changelist *changelist = &base->changelist;
struct event_changelist_fdinfo *fdinfo = p;
struct event_change *change;
ev_uint8_t del = EV_CHANGE_DEL | (events & EV_ET);
event_changelist_check(base);
change = event_changelist_get_or_construct(changelist, fd, old, fdinfo);
@ -922,19 +930,19 @@ event_changelist_del_(struct event_base *base, evutil_socket_t fd, short old, sh
if (!(change->old_events & (EV_READ | EV_SIGNAL)))
change->read_change = 0;
else
change->read_change = EV_CHANGE_DEL;
change->read_change = del;
}
if (events & EV_WRITE) {
if (!(change->old_events & EV_WRITE))
change->write_change = 0;
else
change->write_change = EV_CHANGE_DEL;
change->write_change = del;
}
if (events & EV_CLOSED) {
if (!(change->old_events & EV_CLOSED))
change->close_change = 0;
else
change->close_change = EV_CHANGE_DEL;
change->close_change = del;
}
event_changelist_check(base);

View File

@ -1,4 +1,5 @@
/* $NetBSD: evrpc.c,v 1.4 2017/01/31 23:17:39 christos Exp $ */
/* $NetBSD: evrpc.c,v 1.5 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
@ -27,7 +28,7 @@
*/
#include "event2/event-config.h"
#include <sys/cdefs.h>
__RCSID("$NetBSD: evrpc.c,v 1.4 2017/01/31 23:17:39 christos Exp $");
__RCSID("$NetBSD: evrpc.c,v 1.5 2021/04/07 03:36:48 christos Exp $");
#include "evconfig-private.h"
#ifdef _WIN32
@ -332,7 +333,8 @@ evrpc_request_cb(struct evhttp_request *req, void *arg)
return;
error:
evrpc_reqstate_free_(rpc_state);
if (rpc_state)
evrpc_reqstate_free_(rpc_state);
evhttp_send_error(req, HTTP_SERVUNAVAIL, NULL);
return;
}
@ -894,8 +896,7 @@ evrpc_reply_done(struct evhttp_request *req, void *arg)
* layer is going to free it. we need to
* request ownership explicitly
*/
if (req != NULL)
evhttp_request_own(req);
evhttp_request_own(req);
evrpc_pause_request(pool, ctx,
evrpc_reply_done_closure);

View File

@ -1,4 +1,5 @@
/* $NetBSD: evthread-internal.h,v 1.3 2017/01/31 23:17:39 christos Exp $ */
/* $NetBSD: evthread-internal.h,v 1.4 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2008-2012 Niels Provos, Nick Mathewson
*
@ -39,7 +40,7 @@ extern "C" {
struct event_base;
#ifndef _WIN32
#if !defined(_WIN32) && !defined(__CYGWIN__)
/* On Windows, the way we currently make DLLs, it's not allowed for us to
* have shared global structures. Thus, we only do the direct-call-to-function
* code path if we know that the local shared library system supports it.
@ -50,9 +51,12 @@ struct event_base;
#if ! defined(EVENT__DISABLE_THREAD_SUPPORT) && defined(EVTHREAD_EXPOSE_STRUCTS)
/* Global function pointers to lock-related functions. NULL if locking isn't
enabled. */
EVENT2_EXPORT_SYMBOL
extern struct evthread_lock_callbacks evthread_lock_fns_;
EVENT2_EXPORT_SYMBOL
extern struct evthread_condition_callbacks evthread_cond_fns_;
extern unsigned long (*evthread_id_fn_)(void);
EVENT2_EXPORT_SYMBOL
extern int evthread_lock_debugging_enabled_;
/** Return the ID of the current thread, or 1 if threading isn't enabled. */
@ -183,14 +187,23 @@ EVLOCK_TRY_LOCK_(void *lock)
#elif ! defined(EVENT__DISABLE_THREAD_SUPPORT)
unsigned long evthreadimpl_get_id_(void);
EVENT2_EXPORT_SYMBOL
int evthreadimpl_is_lock_debugging_enabled_(void);
EVENT2_EXPORT_SYMBOL
void *evthreadimpl_lock_alloc_(unsigned locktype);
EVENT2_EXPORT_SYMBOL
void evthreadimpl_lock_free_(void *lock, unsigned locktype);
EVENT2_EXPORT_SYMBOL
int evthreadimpl_lock_lock_(unsigned mode, void *lock);
EVENT2_EXPORT_SYMBOL
int evthreadimpl_lock_unlock_(unsigned mode, void *lock);
EVENT2_EXPORT_SYMBOL
void *evthreadimpl_cond_alloc_(unsigned condtype);
EVENT2_EXPORT_SYMBOL
void evthreadimpl_cond_free_(void *cond);
EVENT2_EXPORT_SYMBOL
int evthreadimpl_cond_signal_(void *cond, int broadcast);
EVENT2_EXPORT_SYMBOL
int evthreadimpl_cond_wait_(void *cond, void *lock, const struct timeval *tv);
int evthreadimpl_locking_enabled_(void);
@ -356,6 +369,7 @@ EVLOCK_TRY_LOCK_(void *lock)
EVLOCK_UNLOCK(lock1_tmplock_,mode1); \
} while (/*CONSTCOND*/0)
EVENT2_EXPORT_SYMBOL
int evthread_is_debug_lock_held_(void *lock);
void *evthread_debug_get_real_lock_(void *lock);
@ -378,6 +392,7 @@ int evutil_global_setup_locks_(const int enable_locks);
int evutil_secure_rng_global_setup_locks_(const int enable_locks);
/** Return current evthread_lock_callbacks */
EVENT2_EXPORT_SYMBOL
struct evthread_lock_callbacks *evthread_get_lock_callbacks(void);
/** Return current evthread_condition_callbacks */
struct evthread_condition_callbacks *evthread_get_condition_callbacks(void);

View File

@ -1,4 +1,5 @@
/* $NetBSD: evthread.c,v 1.2 2017/03/02 15:43:14 christos Exp $ */
/* $NetBSD: evthread.c,v 1.3 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2008-2012 Niels Provos, Nick Mathewson
*
@ -27,7 +28,7 @@
#include "event2/event-config.h"
#include <sys/cdefs.h>
__RCSID("$NetBSD: evthread.c,v 1.2 2017/03/02 15:43:14 christos Exp $");
__RCSID("$NetBSD: evthread.c,v 1.3 2021/04/07 03:36:48 christos Exp $");
#include "evconfig-private.h"
#ifndef EVENT__DISABLE_THREAD_SUPPORT
@ -49,7 +50,7 @@ __RCSID("$NetBSD: evthread.c,v 1.2 2017/03/02 15:43:14 christos Exp $");
#endif
#ifndef EVENT__DISABLE_DEBUG_MODE
extern int event_debug_created_threadable_ctx_;
extern int event_debug_created_threadable_ctx_;
extern int event_debug_mode_on_;
#endif

View File

@ -1,4 +1,5 @@
/* $NetBSD: evutil.c,v 1.6 2017/01/31 23:17:39 christos Exp $ */
/* $NetBSD: evutil.c,v 1.7 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
*
@ -27,11 +28,12 @@
#include "event2/event-config.h"
#include <sys/cdefs.h>
__RCSID("$NetBSD: evutil.c,v 1.6 2017/01/31 23:17:39 christos Exp $");
__RCSID("$NetBSD: evutil.c,v 1.7 2021/04/07 03:36:48 christos Exp $");
#include "evconfig-private.h"
#ifdef _WIN32
#include <winsock2.h>
#include <winerror.h>
#include <ws2tcpip.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
@ -43,6 +45,7 @@ __RCSID("$NetBSD: evutil.c,v 1.6 2017/01/31 23:17:39 christos Exp $");
/* For structs needed by GetAdaptersAddresses */
#define _WIN32_WINNT 0x0501
#include <iphlpapi.h>
#include <netioapi.h>
#endif
#include <sys/types.h>
@ -76,6 +79,9 @@ __RCSID("$NetBSD: evutil.c,v 1.6 2017/01/31 23:17:39 christos Exp $");
#endif
#include <time.h>
#include <sys/stat.h>
#ifndef _WIN32
#include <net/if.h>
#endif
#ifdef EVENT__HAVE_IFADDRS_H
#include <ifaddrs.h>
#endif
@ -388,6 +394,17 @@ evutil_make_listen_socket_reuseable_port(evutil_socket_t sock)
#endif
}
int
evutil_make_listen_socket_ipv6only(evutil_socket_t sock)
{
#if defined(IPV6_V6ONLY)
int one = 1;
return setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void*) &one,
(ev_socklen_t)sizeof(one));
#endif
return 0;
}
int
evutil_make_tcp_listen_socket_deferred(evutil_socket_t sock)
{
@ -598,45 +615,56 @@ evutil_socket_finished_connecting_(evutil_socket_t fd)
set by evutil_check_interfaces. */
static int have_checked_interfaces, had_ipv4_address, had_ipv6_address;
/* Macro: True iff the IPv4 address 'addr', in host order, is in 127.0.0.0/8
*/
#define EVUTIL_V4ADDR_IS_LOCALHOST(addr) (((addr)>>24) == 127)
/* True iff the IPv4 address 'addr', in host order, is in 127.0.0.0/8 */
static inline int evutil_v4addr_is_localhost(ev_uint32_t addr)
{ return addr>>24 == 127; }
/* Macro: True iff the IPv4 address 'addr', in host order, is a class D
* (multiclass) address.
*/
#define EVUTIL_V4ADDR_IS_CLASSD(addr) ((((addr)>>24) & 0xf0) == 0xe0)
/* True iff the IPv4 address 'addr', in host order, is link-local
* 169.254.0.0/16 (RFC3927) */
static inline int evutil_v4addr_is_linklocal(ev_uint32_t addr)
{ return ((addr & 0xffff0000U) == 0xa9fe0000U); }
/* True iff the IPv4 address 'addr', in host order, is a class D
* (multiclass) address. */
static inline int evutil_v4addr_is_classd(ev_uint32_t addr)
{ return ((addr>>24) & 0xf0) == 0xe0; }
int
evutil_v4addr_is_local_(const struct in_addr *in)
{
const ev_uint32_t addr = ntohl(in->s_addr);
return addr == INADDR_ANY ||
evutil_v4addr_is_localhost(addr) ||
evutil_v4addr_is_linklocal(addr) ||
evutil_v4addr_is_classd(addr);
}
int
evutil_v6addr_is_local_(const struct in6_addr *in)
{
static const char ZEROES[] =
"\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00";
const unsigned char *addr = (const unsigned char *)in->s6_addr;
return !memcmp(addr, ZEROES, 8) ||
((addr[0] & 0xfe) == 0xfc) ||
(addr[0] == 0xfe && (addr[1] & 0xc0) == 0x80) ||
(addr[0] == 0xfe && (addr[1] & 0xc0) == 0xc0) ||
(addr[0] == 0xff);
}
static void
evutil_found_ifaddr(const struct sockaddr *sa)
{
const char ZEROES[] = "\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00";
if (sa->sa_family == AF_INET) {
const struct sockaddr_in *sin = (const struct sockaddr_in *)sa;
ev_uint32_t addr = ntohl(sin->sin_addr.s_addr);
if (addr == 0 ||
EVUTIL_V4ADDR_IS_LOCALHOST(addr) ||
EVUTIL_V4ADDR_IS_CLASSD(addr)) {
/* Not actually a usable external address. */
} else {
if (!evutil_v4addr_is_local_(&sin->sin_addr)) {
event_debug(("Detected an IPv4 interface"));
had_ipv4_address = 1;
}
} else if (sa->sa_family == AF_INET6) {
const struct sockaddr_in6 *sin6 =
(const struct sockaddr_in6 *)sa;
const unsigned char *addr =
(const unsigned char*)sin6->sin6_addr.s6_addr;
if (!memcmp(addr, ZEROES, 8) ||
((addr[0] & 0xfe) == 0xfc) ||
(addr[0] == 0xfe && (addr[1] & 0xc0) == 0x80) ||
(addr[0] == 0xfe && (addr[1] & 0xc0) == 0xc0) ||
(addr[0] == 0xff)) {
/* This is a reserved, ipv4compat, ipv4map, loopback,
* link-local, multicast, or unspecified address. */
} else {
const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
if (!evutil_v6addr_is_local_(&sin6->sin6_addr)) {
event_debug(("Detected an IPv6 interface"));
had_ipv6_address = 1;
}
@ -674,7 +702,7 @@ evutil_check_ifaddrs(void)
"GetAdaptersInfo", but that's deprecated; let's just try
GetAdaptersAddresses and fall back to connect+getsockname.
*/
HMODULE lib = evutil_load_windows_system_library_(TEXT("ihplapi.dll"));
HMODULE lib = evutil_load_windows_system_library_(TEXT("iphlpapi.dll"));
GetAdaptersAddresses_fn_t fn;
ULONG size, res;
IP_ADAPTER_ADDRESSES *addresses = NULL, *address;
@ -731,7 +759,7 @@ done:
/* Test whether we have an ipv4 interface and an ipv6 interface. Return 0 if
* the test seemed successful. */
static int
evutil_check_interfaces(int force_recheck)
evutil_check_interfaces(void)
{
evutil_socket_t fd = -1;
struct sockaddr_in sin, sin_out;
@ -739,9 +767,12 @@ evutil_check_interfaces(int force_recheck)
ev_socklen_t sin_out_len = sizeof(sin_out);
ev_socklen_t sin6_out_len = sizeof(sin6_out);
int r;
if (have_checked_interfaces && !force_recheck)
if (have_checked_interfaces)
return 0;
/* From this point on we have done the ipv4/ipv6 interface check */
have_checked_interfaces = 1;
if (evutil_check_ifaddrs() == 0) {
/* Use a nice sane interface, if this system has one. */
return 0;
@ -967,6 +998,7 @@ evutil_getaddrinfo_common_(const char *nodename, const char *servname,
struct evutil_addrinfo *hints, struct evutil_addrinfo **res, int *portnum)
{
int port = 0;
unsigned int if_index;
const char *pname;
if (nodename == NULL && servname == NULL)
@ -1040,10 +1072,12 @@ evutil_getaddrinfo_common_(const char *nodename, const char *servname,
if (hints->ai_family == PF_INET6 || hints->ai_family == PF_UNSPEC) {
struct sockaddr_in6 sin6;
memset(&sin6, 0, sizeof(sin6));
if (1==evutil_inet_pton(AF_INET6, nodename, &sin6.sin6_addr)) {
if (1 == evutil_inet_pton_scope(
AF_INET6, nodename, &sin6.sin6_addr, &if_index)) {
/* Got an ipv6 address. */
sin6.sin6_family = AF_INET6;
sin6.sin6_port = htons(port);
sin6.sin6_scope_id = if_index;
*res = evutil_new_addrinfo_((struct sockaddr*)&sin6,
sizeof(sin6), hints);
if (!*res)
@ -1057,7 +1091,7 @@ evutil_getaddrinfo_common_(const char *nodename, const char *servname,
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
if (1==evutil_inet_pton(AF_INET, nodename, &sin.sin_addr)) {
/* Got an ipv6 address. */
/* Got an ipv4 address. */
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
*res = evutil_new_addrinfo_((struct sockaddr*)&sin,
@ -1209,8 +1243,7 @@ evutil_adjust_hints_for_addrconfig_(struct evutil_addrinfo *hints)
return;
if (hints->ai_family != PF_UNSPEC)
return;
if (!have_checked_interfaces)
evutil_check_interfaces(0);
evutil_check_interfaces();
if (had_ipv4_address && !had_ipv6_address) {
hints->ai_family = PF_INET;
} else if (!had_ipv4_address && had_ipv6_address) {
@ -1959,6 +1992,41 @@ evutil_inet_ntop(int af, const void *src, char *dst, size_t len)
#endif
}
int
evutil_inet_pton_scope(int af, const char *src, void *dst, unsigned *indexp)
{
int r;
unsigned if_index;
char *check, *cp, *tmp_src;
*indexp = 0; /* Reasonable default */
/* Bail out if not IPv6 */
if (af != AF_INET6)
return evutil_inet_pton(af, src, dst);
cp = strchr(src, '%');
/* Bail out if no zone ID */
if (cp == NULL)
return evutil_inet_pton(af, src, dst);
if_index = if_nametoindex(cp + 1);
if (if_index == 0) {
/* Could be numeric */
if_index = strtoul(cp + 1, &check, 10);
if (check[0] != '\0')
return 0;
}
*indexp = if_index;
tmp_src = mm_strdup(src);
cp = strchr(tmp_src, '%');
*cp = '\0';
r = evutil_inet_pton(af, tmp_src, dst);
free(tmp_src);
return r;
}
int
evutil_inet_pton(int af, const char *src, void *dst)
{
@ -2075,6 +2143,7 @@ int
evutil_parse_sockaddr_port(const char *ip_as_string, struct sockaddr *out, int *outlen)
{
int port;
unsigned int if_index;
char buf[128];
const char *cp, *addr_part, *port_part;
int is_ipv6;
@ -2144,10 +2213,13 @@ evutil_parse_sockaddr_port(const char *ip_as_string, struct sockaddr *out, int *
#endif
sin6.sin6_family = AF_INET6;
sin6.sin6_port = htons(port);
if (1 != evutil_inet_pton(AF_INET6, addr_part, &sin6.sin6_addr))
if (1 != evutil_inet_pton_scope(
AF_INET6, addr_part, &sin6.sin6_addr, &if_index)) {
return -1;
}
if ((int)sizeof(sin6) > *outlen)
return -1;
sin6.sin6_scope_id = if_index;
memset(out, 0, *outlen);
memcpy(out, &sin6, sizeof(sin6));
*outlen = sizeof(sin6);
@ -2301,7 +2373,7 @@ static const unsigned char EVUTIL_TOLOWER_TABLE[256] = {
#define IMPL_CTYPE_FN(name) \
int EVUTIL_##name##_(char c) { \
ev_uint8_t u = c; \
return !!(EVUTIL_##name##_TABLE[(u >> 5) & 7] & (1 << (u & 31))); \
return !!(EVUTIL_##name##_TABLE[(u >> 5) & 7] & (1U << (u & 31))); \
}
IMPL_CTYPE_FN(ISALPHA)
IMPL_CTYPE_FN(ISALNUM)
@ -2597,7 +2669,7 @@ evutil_accept4_(evutil_socket_t sockfd, struct sockaddr *addr,
}
/* Internal function: Set fd[0] and fd[1] to a pair of fds such that writes on
* fd[0] get read from fd[1]. Make both fds nonblocking and close-on-exec.
* fd[1] get read from fd[0]. Make both fds nonblocking and close-on-exec.
* Return 0 on success, -1 on failure.
*/
int

View File

@ -1,4 +1,5 @@
/* $NetBSD: evutil_rand.c,v 1.5 2017/01/31 23:17:39 christos Exp $ */
/* $NetBSD: evutil_rand.c,v 1.6 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
*
@ -35,7 +36,7 @@
#include "event2/event-config.h"
#include <sys/cdefs.h>
__RCSID("$NetBSD: evutil_rand.c,v 1.5 2017/01/31 23:17:39 christos Exp $");
__RCSID("$NetBSD: evutil_rand.c,v 1.6 2021/04/07 03:36:48 christos Exp $");
#include "evconfig-private.h"
#include <limits.h>
@ -177,9 +178,7 @@ evutil_secure_rng_init(void)
int val;
ARC4_LOCK_();
if (!arc4_seeded_ok)
arc4_stir();
val = arc4_seeded_ok ? 0 : -1;
val = (!arc4_stir()) ? 0 : -1;
ARC4_UNLOCK_();
return val;
}
@ -198,12 +197,14 @@ evutil_secure_rng_get_bytes(void *buf, size_t n)
ev_arc4random_buf(buf, n);
}
#if !defined(EVENT__HAVE_ARC4RANDOM) || defined(EVENT__HAVE_ARC4RANDOM_ADDRANDOM)
void
evutil_secure_rng_add_bytes(const char *buf, size_t n)
{
arc4random_addrandom(__UNCONST(buf),
n>(size_t)INT_MAX ? INT_MAX : (int)n);
}
#endif
void
evutil_free_secure_rng_globals_(void)

View File

@ -1,4 +1,5 @@
/* $NetBSD: http.c,v 1.4 2017/01/31 23:17:39 christos Exp $ */
/* $NetBSD: http.c,v 1.5 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2002-2007 Niels Provos <provos@citi.umich.edu>
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
@ -28,7 +29,7 @@
#include "event2/event-config.h"
#include <sys/cdefs.h>
__RCSID("$NetBSD: http.c,v 1.4 2017/01/31 23:17:39 christos Exp $");
__RCSID("$NetBSD: http.c,v 1.5 2021/04/07 03:36:48 christos Exp $");
#include "evconfig-private.h"
#ifdef EVENT__HAVE_SYS_PARAM_H
@ -54,9 +55,16 @@ __RCSID("$NetBSD: http.c,v 1.4 2017/01/31 23:17:39 christos Exp $");
#ifndef _WIN32
#include <sys/socket.h>
#include <sys/stat.h>
#else
#else /* _WIN32 */
#include <winsock2.h>
#include <ws2tcpip.h>
#endif /* _WIN32 */
#ifdef EVENT__HAVE_SYS_UN_H
#include <sys/un.h>
#endif
#ifdef EVENT__HAVE_AFUNIX_H
#include <afunix.h>
#endif
#include <sys/queue.h>
@ -81,7 +89,7 @@ __RCSID("$NetBSD: http.c,v 1.4 2017/01/31 23:17:39 christos Exp $");
#include <string.h>
#ifndef _WIN32
#include <syslog.h>
#endif
#endif /* !_WIN32 */
#include <signal.h>
#ifdef EVENT__HAVE_UNISTD_H
#include <unistd.h>
@ -173,9 +181,10 @@ fake_getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
extern int debug;
static evutil_socket_t bind_socket_ai(struct evutil_addrinfo *, int reuse);
static evutil_socket_t create_bind_socket_nonblock(struct evutil_addrinfo *, int reuse);
static evutil_socket_t bind_socket(const char *, ev_uint16_t, int reuse);
static void name_from_addr(struct sockaddr *, ev_socklen_t, char **, char **);
static struct evhttp_uri *evhttp_uri_parse_authority(char *source_uri);
static int evhttp_associate_new_request_with_connection(
struct evhttp_connection *evcon);
static void evhttp_connection_start_detectclose(
@ -353,6 +362,7 @@ evhttp_response_needs_body(struct evhttp_request *req)
return (req->response_code != HTTP_NOCONTENT &&
req->response_code != HTTP_NOTMODIFIED &&
(req->response_code < 100 || req->response_code >= 200) &&
req->type != EVHTTP_REQ_CONNECT &&
req->type != EVHTTP_REQ_HEAD);
}
@ -371,15 +381,15 @@ evhttp_write_buffer(struct evhttp_connection *evcon,
evcon->cb_arg = arg;
/* Disable the read callback: we don't actually care about data;
* we only care about close detection. (We don't disable reading,
* since we *do* want to learn about any close events.) */
* we only care about close detection. (We don't disable reading --
* EV_READ, since we *do* want to learn about any close events.) */
bufferevent_setcb(evcon->bufev,
NULL, /*read*/
evhttp_write_cb,
evhttp_error_cb,
evcon);
bufferevent_enable(evcon->bufev, EV_WRITE);
bufferevent_enable(evcon->bufev, EV_READ|EV_WRITE);
}
static void
@ -473,6 +483,9 @@ evhttp_is_connection_close(int flags, struct evkeyvalq* headers)
static int
evhttp_is_request_connection_close(struct evhttp_request *req)
{
if (req->type == EVHTTP_REQ_CONNECT)
return 0;
return
evhttp_is_connection_close(req->flags, req->input_headers) ||
evhttp_is_connection_close(req->flags, req->output_headers);
@ -773,6 +786,11 @@ evhttp_connection_fail_(struct evhttp_connection *evcon,
/* We are trying the next request that was queued on us */
if (TAILQ_FIRST(&evcon->requests) != NULL)
evhttp_connection_connect_(evcon);
else
if ((evcon->flags & EVHTTP_CON_OUTGOING) &&
(evcon->flags & EVHTTP_CON_AUTOFREE)) {
evhttp_connection_free(evcon);
}
/* The call to evhttp_connection_reset_ overwrote errno.
* Let's restore the original errno, so that the user's
@ -1173,7 +1191,9 @@ static void
evhttp_deferred_read_cb(struct event_callback *cb, void *data)
{
struct evhttp_connection *evcon = data;
evhttp_read_cb(evcon->bufev, evcon);
struct bufferevent *bev = evcon->bufev;
if (bev->readcb)
(bev->readcb)(evcon->bufev, evcon);
}
static void
@ -1205,6 +1225,7 @@ void
evhttp_connection_free(struct evhttp_connection *evcon)
{
struct evhttp_request *req;
int need_close = 0;
/* notify interested parties that this connection is going down */
if (evcon->fd != -1) {
@ -1231,21 +1252,22 @@ evhttp_connection_free(struct evhttp_connection *evcon)
event_debug_unassign(&evcon->retry_ev);
}
if (evcon->bufev != NULL)
bufferevent_free(evcon->bufev);
event_deferred_cb_cancel_(get_deferred_queue(evcon),
&evcon->read_more_deferred_cb);
if (evcon->fd == -1)
evcon->fd = bufferevent_getfd(evcon->bufev);
if (evcon->bufev != NULL) {
need_close =
!(bufferevent_get_options_(evcon->bufev) & BEV_OPT_CLOSE_ON_FREE);
if (evcon->fd == -1)
evcon->fd = bufferevent_getfd(evcon->bufev);
bufferevent_free(evcon->bufev);
}
if (evcon->fd != -1) {
bufferevent_disable(evcon->bufev, EV_READ|EV_WRITE);
shutdown(evcon->fd, EVUTIL_SHUT_WR);
if (!(bufferevent_get_options_(evcon->bufev) & BEV_OPT_CLOSE_ON_FREE)) {
if (need_close)
evutil_closesocket(evcon->fd);
}
}
if (evcon->bind_address != NULL)
@ -1290,6 +1312,8 @@ evhttp_request_dispatch(struct evhttp_connection* evcon)
if (req == NULL)
return;
EVUTIL_ASSERT(req->kind == EVHTTP_REQUEST);
/* delete possible close detection events */
evhttp_connection_stop_detectclose(evcon);
@ -1312,6 +1336,8 @@ evhttp_connection_reset_(struct evhttp_connection *evcon)
struct evbuffer *tmp;
int err;
bufferevent_setcb(evcon->bufev, NULL, NULL, NULL, NULL);
/* XXXX This is not actually an optimal fix. Instead we ought to have
an API for "stop connecting", or use bufferevent_setfd to turn off
connecting. But for Libevent 2.0, this seems like a minimal change
@ -1337,7 +1363,8 @@ evhttp_connection_reset_(struct evhttp_connection *evcon)
evutil_closesocket(evcon->fd);
evcon->fd = -1;
}
bufferevent_setfd(evcon->bufev, -1);
err = bufferevent_setfd(evcon->bufev, -1);
EVUTIL_ASSERT(!err && "setfd");
/* we need to clean up any buffered data */
tmp = bufferevent_get_output(evcon->bufev);
@ -1356,7 +1383,6 @@ static void
evhttp_connection_start_detectclose(struct evhttp_connection *evcon)
{
evcon->flags |= EVHTTP_CON_CLOSEDETECT;
bufferevent_enable(evcon->bufev, EV_READ);
}
@ -1364,7 +1390,6 @@ static void
evhttp_connection_stop_detectclose(struct evhttp_connection *evcon)
{
evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
bufferevent_disable(evcon->bufev, EV_READ);
}
@ -1529,6 +1554,14 @@ evhttp_error_cb(struct bufferevent *bufev, short what, void *arg)
return;
}
if (what & BEV_EVENT_READING &&
evcon->flags & EVHTTP_CON_READ_ON_WRITE_ERROR &&
evbuffer_get_length(bufferevent_get_input(bufev))) {
event_deferred_cb_schedule_(get_deferred_queue(evcon),
&evcon->read_more_deferred_cb);
return;
}
evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
} else if (what == BEV_EVENT_CONNECTED) {
} else {
@ -1686,8 +1719,9 @@ evhttp_parse_response_line(struct evhttp_request *req, char *line)
/* Parse the first line of a HTTP request */
static int
evhttp_parse_request_line(struct evhttp_request *req, char *line)
evhttp_parse_request_line(struct evhttp_request *req, char *line, size_t len)
{
char *eos = line + len;
char *method;
char *uri;
char *version;
@ -1696,16 +1730,24 @@ evhttp_parse_request_line(struct evhttp_request *req, char *line)
size_t method_len;
enum evhttp_cmd_type type;
while (eos > line && *(eos-1) == ' ') {
*(eos-1) = '\0';
--eos;
--len;
}
if (len < strlen("GET / HTTP/1.0"))
return -1;
/* Parse the request line */
method = strsep(&line, " ");
if (line == NULL)
return (-1);
uri = strsep(&line, " ");
if (line == NULL)
return (-1);
version = strsep(&line, " ");
if (line != NULL)
return (-1);
if (!line)
return -1;
uri = line;
version = strrchr(uri, ' ');
if (!version || uri == version)
return -1;
*version = '\0';
version++;
method_len = (uri - method) - 1;
type = EVHTTP_REQ_UNKNOWN_;
@ -1825,16 +1867,22 @@ evhttp_parse_request_line(struct evhttp_request *req, char *line)
req->type = type;
if (evhttp_parse_http_version(version, req) < 0)
return (-1);
return -1;
if ((req->uri = mm_strdup(uri)) == NULL) {
event_debug(("%s: mm_strdup", __func__));
return (-1);
return -1;
}
if ((req->uri_elems = evhttp_uri_parse_with_flags(req->uri,
EVHTTP_URI_NONCONFORMANT)) == NULL) {
return -1;
if (type == EVHTTP_REQ_CONNECT) {
if ((req->uri_elems = evhttp_uri_parse_authority(req->uri)) == NULL) {
return -1;
}
} else {
if ((req->uri_elems = evhttp_uri_parse_with_flags(req->uri,
EVHTTP_URI_NONCONFORMANT)) == NULL) {
return -1;
}
}
/* If we have an absolute-URI, check to see if it is an http request
@ -1848,7 +1896,7 @@ evhttp_parse_request_line(struct evhttp_request *req, char *line)
!evhttp_find_vhost(req->evcon->http_server, NULL, hostname))
req->flags |= EVHTTP_PROXY_REQUEST;
return (0);
return 0;
}
const char *
@ -1983,9 +2031,9 @@ evhttp_parse_firstline_(struct evhttp_request *req, struct evbuffer *buffer)
char *line;
enum message_read_status status = ALL_DATA_READ;
size_t line_length;
size_t len;
/* XXX try */
line = evbuffer_readln(buffer, &line_length, EVBUFFER_EOL_CRLF);
line = evbuffer_readln(buffer, &len, EVBUFFER_EOL_CRLF);
if (line == NULL) {
if (req->evcon != NULL &&
evbuffer_get_length(buffer) > req->evcon->max_headers_size)
@ -1994,17 +2042,16 @@ evhttp_parse_firstline_(struct evhttp_request *req, struct evbuffer *buffer)
return (MORE_DATA_EXPECTED);
}
if (req->evcon != NULL &&
line_length > req->evcon->max_headers_size) {
if (req->evcon != NULL && len > req->evcon->max_headers_size) {
mm_free(line);
return (DATA_TOO_LONG);
}
req->headers_size = line_length;
req->headers_size = len;
switch (req->kind) {
case EVHTTP_REQUEST:
if (evhttp_parse_request_line(req, line) == -1)
if (evhttp_parse_request_line(req, line, len) == -1)
status = DATA_CORRUPTED;
break;
case EVHTTP_RESPONSE:
@ -2057,12 +2104,12 @@ evhttp_parse_headers_(struct evhttp_request *req, struct evbuffer* buffer)
enum message_read_status status = MORE_DATA_EXPECTED;
struct evkeyvalq* headers = req->input_headers;
size_t line_length;
while ((line = evbuffer_readln(buffer, &line_length, EVBUFFER_EOL_CRLF))
size_t len;
while ((line = evbuffer_readln(buffer, &len, EVBUFFER_EOL_CRLF))
!= NULL) {
char *skey, *svalue;
req->headers_size += line_length;
req->headers_size += len;
if (req->evcon != NULL &&
req->headers_size > req->evcon->max_headers_size) {
@ -2126,11 +2173,7 @@ evhttp_get_body_length(struct evhttp_request *req)
req->ntoread = -1;
else if (content_length == NULL &&
evutil_ascii_strcasecmp(connection, "Close") != 0) {
/* Bad combination, we don't know when it will end */
event_warnx("%s: we got no content length, but the "
"server wants to keep the connection open: %s.",
__func__, connection);
return (-1);
req->ntoread = 0;
} else if (content_length == NULL) {
req->ntoread = -1;
} else {
@ -2158,16 +2201,15 @@ evhttp_method_may_have_body(enum evhttp_cmd_type type)
case EVHTTP_REQ_POST:
case EVHTTP_REQ_PUT:
case EVHTTP_REQ_PATCH:
return 1;
case EVHTTP_REQ_TRACE:
return 0;
/* XXX May any of the below methods have a body? */
case EVHTTP_REQ_GET:
case EVHTTP_REQ_HEAD:
case EVHTTP_REQ_DELETE:
case EVHTTP_REQ_OPTIONS:
case EVHTTP_REQ_CONNECT:
return 0;
return 1;
case EVHTTP_REQ_TRACE:
case EVHTTP_REQ_HEAD:
default:
return 0;
}
@ -2547,9 +2589,11 @@ evhttp_connection_connect_(struct evhttp_connection *evcon)
return (-1);
}
bufferevent_setfd(evcon->bufev, evcon->fd);
if (bufferevent_setfd(evcon->bufev, evcon->fd))
return (-1);
} else {
bufferevent_setfd(evcon->bufev, -1);
if (bufferevent_setfd(evcon->bufev, -1))
return (-1);
}
/* Set up a callback for successful connection setup */
@ -2565,7 +2609,8 @@ evhttp_connection_connect_(struct evhttp_connection *evcon)
bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
}
/* make sure that we get a write callback */
bufferevent_enable(evcon->bufev, EV_WRITE);
if (bufferevent_enable(evcon->bufev, EV_WRITE))
return (-1);
evcon->state = EVCON_CONNECTING;
@ -2631,6 +2676,10 @@ evhttp_make_request(struct evhttp_connection *evcon,
TAILQ_INSERT_TAIL(&evcon->requests, req, next);
/* We do not want to conflict with retry_ev */
if (evcon->retry_cnt)
return (0);
/* If the connection object is not connected; make it so */
if (!evhttp_connected(evcon)) {
int res = evhttp_connection_connect_(evcon);
@ -2641,7 +2690,7 @@ evhttp_make_request(struct evhttp_connection *evcon,
if (res != 0)
TAILQ_REMOVE(&evcon->requests, req, next);
return res;
return (res);
}
/*
@ -2823,6 +2872,10 @@ evhttp_send_reply_start(struct evhttp_request *req, int code,
const char *reason)
{
evhttp_response_code_(req, code, reason);
if (req->evcon == NULL)
return;
if (evhttp_find_header(req->output_headers, "Content-Length") == NULL &&
REQ_VERSION_ATLEAST(req, 1, 1) &&
evhttp_response_needs_body(req)) {
@ -3062,16 +3115,15 @@ evhttp_uriencode(const char *uri, ev_ssize_t len, int space_as_plus)
{
struct evbuffer *buf = evbuffer_new();
const char *p, *end;
char *result;
char *result = NULL;
if (buf == NULL) {
return (NULL);
if (!buf) {
goto out;
}
if (len >= 0) {
if (uri + len < uri) {
return (NULL);
goto out;
}
end = uri + len;
@ -3080,11 +3132,11 @@ evhttp_uriencode(const char *uri, ev_ssize_t len, int space_as_plus)
if (slen >= EV_SSIZE_MAX) {
/* we don't want to mix signed and unsigned */
return (NULL);
goto out;
}
if (uri + slen < uri) {
return (NULL);
goto out;
}
end = uri + slen;
@ -3106,9 +3158,10 @@ evhttp_uriencode(const char *uri, ev_ssize_t len, int space_as_plus)
if (result)
evbuffer_remove(buf, result, evbuffer_get_length(buf));
evbuffer_free(buf);
return (result);
out:
if (buf)
evbuffer_free(buf);
return result;
}
char *
@ -3237,6 +3290,7 @@ evhttp_parse_query_impl(const char *str, struct evkeyvalq *headers,
p = argument = line;
while (p != NULL && *p != '\0') {
char *key, *value, *decoded_value;
int err;
argument = strsep(&p, "&");
value = argument;
@ -3252,8 +3306,10 @@ evhttp_parse_query_impl(const char *str, struct evkeyvalq *headers,
evhttp_decode_uri_internal(value, strlen(value),
decoded_value, 1 /*always_decode_plus*/);
event_debug(("Query Param: %s -> %s\n", key, decoded_value));
evhttp_add_header_internal(headers, key, decoded_value);
err = evhttp_add_header_internal(headers, key, decoded_value);
mm_free(decoded_value);
if (err)
goto error;
}
result = 0;
@ -3419,6 +3475,8 @@ evhttp_handle_request(struct evhttp_request *req, void *arg)
/* we have a new request on which the user needs to take action */
req->userdone = 0;
bufferevent_disable(req->evcon->bufev, EV_READ);
if (req->type == 0 || req->uri == NULL) {
evhttp_send_error(req, req->response_code, NULL);
return;
@ -3506,13 +3564,16 @@ evhttp_bind_socket_with_handle(struct evhttp *http, const char *address, ev_uint
{
evutil_socket_t fd;
struct evhttp_bound_socket *bound;
int serrno;
if ((fd = bind_socket(address, port, 1 /*reuse*/)) == -1)
return (NULL);
if (listen(fd, 128) == -1) {
serrno = EVUTIL_SOCKET_ERROR();
event_sock_warn(fd, "%s: listen", __func__);
evutil_closesocket(fd);
EVUTIL_SET_SOCKET_ERROR(serrno);
return (NULL);
}
@ -4172,6 +4233,13 @@ evhttp_get_request_connection(
char *hostname = NULL, *portname = NULL;
struct bufferevent* bev = NULL;
#ifdef EVENT__HAVE_STRUCT_SOCKADDR_UN
if (sa->sa_family == AF_UNIX) {
struct sockaddr_un *sa_un = (struct sockaddr_un *)sa;
sa_un->sun_path[0] = '\0';
}
#endif
name_from_addr(sa, salen, &hostname, &portname);
if (hostname == NULL || portname == NULL) {
if (hostname) mm_free(hostname);
@ -4203,11 +4271,19 @@ evhttp_get_request_connection(
evcon->fd = fd;
bufferevent_enable(evcon->bufev, EV_READ);
bufferevent_disable(evcon->bufev, EV_WRITE);
bufferevent_setfd(evcon->bufev, fd);
if (bufferevent_setfd(evcon->bufev, fd))
goto err;
if (bufferevent_enable(evcon->bufev, EV_READ))
goto err;
if (bufferevent_disable(evcon->bufev, EV_WRITE))
goto err;
bufferevent_socket_set_conn_address_(evcon->bufev, sa, salen);
return (evcon);
err:
evhttp_connection_free(evcon);
return (NULL);
}
static int
@ -4316,9 +4392,8 @@ name_from_addr(struct sockaddr *sa, ev_socklen_t salen,
}
/* Create a non-blocking socket and bind it */
/* todo: rename this function */
static evutil_socket_t
bind_socket_ai(struct evutil_addrinfo *ai, int reuse)
create_bind_socket_nonblock(struct evutil_addrinfo *ai, int reuse)
{
evutil_socket_t fd;
@ -4392,14 +4467,14 @@ bind_socket(const char *address, ev_uint16_t port, int reuse)
/* just create an unbound socket */
if (address == NULL && port == 0)
return bind_socket_ai(NULL, 0);
return create_bind_socket_nonblock(NULL, 0);
aitop = make_addrinfo(address, port);
if (aitop == NULL)
return (-1);
fd = bind_socket_ai(aitop, reuse);
fd = create_bind_socket_nonblock(aitop, reuse);
evutil_freeaddrinfo(aitop);
@ -4824,6 +4899,36 @@ err:
return NULL;
}
static struct evhttp_uri *
evhttp_uri_parse_authority(char *source_uri)
{
struct evhttp_uri *uri = mm_calloc(1, sizeof(struct evhttp_uri));
char *end;
if (uri == NULL) {
event_warn("%s: calloc", __func__);
goto err;
}
uri->port = -1;
uri->flags = 0;
end = end_of_authority(source_uri);
if (parse_authority(uri, source_uri, end) < 0)
goto err;
uri->path = mm_strdup("");
if (uri->path == NULL) {
event_warn("%s: strdup", __func__);
goto err;
}
return uri;
err:
if (uri)
evhttp_uri_free(uri);
return NULL;
}
void
evhttp_uri_free(struct evhttp_uri *uri)
{

View File

@ -1,4 +1,5 @@
/* $NetBSD: rpc.h,v 1.4 2017/01/31 23:17:40 christos Exp $ */
/* $NetBSD: rpc.h,v 1.5 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2006-2007 Niels Provos <provos@citi.umich.edu>
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
@ -28,6 +29,10 @@
#ifndef EVENT2_RPC_H_INCLUDED_
#define EVENT2_RPC_H_INCLUDED_
/* For int types. */
#include <event2/util.h>
#include <event2/visibility.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -179,6 +184,7 @@ EVRPC_STRUCT(rpcname) { \
struct evhttp_request* http_req; \
struct evbuffer* rpc_data; \
}; \
EVENT2_EXPORT_SYMBOL \
int evrpc_send_request_##rpcname(struct evrpc_pool *, \
struct reqstruct *, struct rplystruct *, \
void (*)(struct evrpc_status *, \
@ -188,6 +194,7 @@ int evrpc_send_request_##rpcname(struct evrpc_pool *, \
struct evrpc_pool;
/** use EVRPC_GENERATE instead */
EVENT2_EXPORT_SYMBOL
struct evrpc_request_wrapper *evrpc_make_request_ctx(
struct evrpc_pool *pool, void *request, void *reply,
const char *rpcname,
@ -258,10 +265,13 @@ struct evrpc_request_wrapper *evrpc_make_request_ctx(
#define EVRPC_REQUEST_HTTP(rpc_req) (rpc_req)->http_req
/** completes the server response to an rpc request */
EVENT2_EXPORT_SYMBOL
void evrpc_request_done(struct evrpc_req_generic *req);
/** accessors for request and reply */
EVENT2_EXPORT_SYMBOL
void *evrpc_get_request(struct evrpc_req_generic *req);
EVENT2_EXPORT_SYMBOL
void *evrpc_get_reply(struct evrpc_req_generic *req);
/** Creates the reply to an RPC request
@ -286,9 +296,10 @@ struct evhttp;
/** Creates a new rpc base from which RPC requests can be received
*
* @param server a pointer to an existing HTTP server
* @return a newly allocated evrpc_base struct
* @return a newly allocated evrpc_base struct or NULL if an error occurred
* @see evrpc_free()
*/
EVENT2_EXPORT_SYMBOL
struct evrpc_base *evrpc_init(struct evhttp *server);
/**
@ -299,6 +310,7 @@ struct evrpc_base *evrpc_init(struct evhttp *server);
* @param base the evrpc_base object to be freed
* @see evrpc_init
*/
EVENT2_EXPORT_SYMBOL
void evrpc_free(struct evrpc_base *base);
/** register RPCs with the HTTP Server
@ -320,10 +332,10 @@ void evrpc_free(struct evrpc_base *base);
#define EVRPC_REGISTER(base, name, request, reply, callback, cbarg) \
evrpc_register_generic(base, #name, \
(void (*)(struct evrpc_req_generic *, void *))callback, cbarg, \
(void *(*)(void *))request##_new, NULL, \
(void *(*)(void *))request##_new_with_arg, NULL, \
(void (*)(void *))request##_free, \
(int (*)(void *, struct evbuffer *))request##_unmarshal, \
(void *(*)(void *))reply##_new, NULL, \
(void *(*)(void *))reply##_new_with_arg, NULL, \
(void (*)(void *))reply##_free, \
(int (*)(void *))reply##_complete, \
(void (*)(struct evbuffer *, void *))reply##_marshal)
@ -335,6 +347,7 @@ void evrpc_free(struct evrpc_base *base);
@see EVRPC_REGISTER()
*/
EVENT2_EXPORT_SYMBOL
int evrpc_register_rpc(struct evrpc_base *, struct evrpc *,
void (*)(struct evrpc_req_generic*, void *), void *);
@ -348,6 +361,7 @@ int evrpc_register_rpc(struct evrpc_base *, struct evrpc *,
*/
#define EVRPC_UNREGISTER(base, name) evrpc_unregister_rpc((base), #name)
EVENT2_EXPORT_SYMBOL
int evrpc_unregister_rpc(struct evrpc_base *base, const char *name);
/*
@ -386,6 +400,7 @@ struct evrpc_status;
@returns 0 on success, -1 otherwise.
@see EVRPC_MAKE_REQUEST(), EVRPC_MAKE_CTX()
*/
EVENT2_EXPORT_SYMBOL
int evrpc_make_request(struct evrpc_request_wrapper *ctx);
/** creates an rpc connection pool
@ -395,15 +410,18 @@ int evrpc_make_request(struct evrpc_request_wrapper *ctx);
*
* @param base a pointer to an struct event_based object; can be left NULL
* in singled-threaded applications
* @return a newly allocated struct evrpc_pool object
* @return a newly allocated struct evrpc_pool object or NULL if an error
* occurred
* @see evrpc_pool_free()
*/
EVENT2_EXPORT_SYMBOL
struct evrpc_pool *evrpc_pool_new(struct event_base *base);
/** frees an rpc connection pool
*
* @param pool a pointer to an evrpc_pool allocated via evrpc_pool_new()
* @see evrpc_pool_new()
*/
EVENT2_EXPORT_SYMBOL
void evrpc_pool_free(struct evrpc_pool *pool);
/**
@ -414,6 +432,7 @@ void evrpc_pool_free(struct evrpc_pool *pool);
* @param pool the pool to which to add the connection
* @param evcon the connection to add to the pool.
*/
EVENT2_EXPORT_SYMBOL
void evrpc_pool_add_connection(struct evrpc_pool *pool,
struct evhttp_connection *evcon);
@ -425,6 +444,7 @@ void evrpc_pool_add_connection(struct evrpc_pool *pool,
* @param pool the pool from which to remove the connection
* @param evcon the connection to remove from the pool.
*/
EVENT2_EXPORT_SYMBOL
void evrpc_pool_remove_connection(struct evrpc_pool *pool,
struct evhttp_connection *evcon);
@ -443,6 +463,7 @@ void evrpc_pool_remove_connection(struct evrpc_pool *pool,
* @param timeout_in_secs the number of seconds after which a request should
* timeout and a failure be returned to the callback.
*/
EVENT2_EXPORT_SYMBOL
void evrpc_pool_set_timeout(struct evrpc_pool *pool, int timeout_in_secs);
/**
@ -490,6 +511,7 @@ enum EVRPC_HOOK_RESULT {
* @return a handle to the hook so it can be removed later
* @see evrpc_remove_hook()
*/
EVENT2_EXPORT_SYMBOL
void *evrpc_add_hook(void *vbase,
enum EVRPC_HOOK_TYPE hook_type,
int (*cb)(void *, struct evhttp_request *, struct evbuffer *, void *),
@ -503,6 +525,7 @@ void *evrpc_add_hook(void *vbase,
* @return 1 on success or 0 on failure
* @see evrpc_add_hook()
*/
EVENT2_EXPORT_SYMBOL
int evrpc_remove_hook(void *vbase,
enum EVRPC_HOOK_TYPE hook_type,
void *handle);
@ -512,8 +535,8 @@ int evrpc_remove_hook(void *vbase,
* @param vbase a pointer to either struct evrpc_base or struct evrpc_pool
* @param ctx the context pointer provided to the original hook call
*/
int
evrpc_resume_request(void *vbase, void *ctx, enum EVRPC_HOOK_RESULT res);
EVENT2_EXPORT_SYMBOL
int evrpc_resume_request(void *vbase, void *ctx, enum EVRPC_HOOK_RESULT res);
/** adds meta data to request
*
@ -526,6 +549,7 @@ evrpc_resume_request(void *vbase, void *ctx, enum EVRPC_HOOK_RESULT res);
* @param data the data to be associated with the key
* @param data_size the size of the data
*/
EVENT2_EXPORT_SYMBOL
void evrpc_hook_add_meta(void *ctx, const char *key,
const void *data, size_t data_size);
@ -539,6 +563,7 @@ void evrpc_hook_add_meta(void *ctx, const char *key,
* @param data_size pointer to the size of the data
* @return 0 on success or -1 on failure
*/
EVENT2_EXPORT_SYMBOL
int evrpc_hook_find_meta(void *ctx, const char *key,
void **data, size_t *data_size);
@ -546,8 +571,10 @@ int evrpc_hook_find_meta(void *ctx, const char *key,
* returns the connection object associated with the request
*
* @param ctx the context provided to the hook call
* @return a pointer to the evhttp_connection object
* @return a pointer to the evhttp_connection object or NULL if an error
* occurred
*/
EVENT2_EXPORT_SYMBOL
struct evhttp_connection *evrpc_hook_get_connection(void *ctx);
/**
@ -557,6 +584,7 @@ struct evhttp_connection *evrpc_hook_get_connection(void *ctx);
@see EVRPC_MAKE_REQUEST()
*/
EVENT2_EXPORT_SYMBOL
int evrpc_send_request_generic(struct evrpc_pool *pool,
void *request, void *reply,
void (*cb)(struct evrpc_status *, void *, void *, void *),
@ -573,8 +601,8 @@ int evrpc_send_request_generic(struct evrpc_pool *pool,
@see EVRPC_REGISTER()
*/
int
evrpc_register_generic(struct evrpc_base *base, const char *name,
EVENT2_EXPORT_SYMBOL
int evrpc_register_generic(struct evrpc_base *base, const char *name,
void (*callback)(struct evrpc_req_generic *, void *), void *cbarg,
void *(*req_new)(void *), void *req_new_arg, void (*req_free)(void *),
int (*req_unmarshal)(void *, struct evbuffer *),
@ -583,9 +611,12 @@ evrpc_register_generic(struct evrpc_base *base, const char *name,
void (*rpl_marshal)(struct evbuffer *, void *));
/** accessors for obscure and undocumented functionality */
EVENT2_EXPORT_SYMBOL
struct evrpc_pool* evrpc_request_get_pool(struct evrpc_request_wrapper *ctx);
EVENT2_EXPORT_SYMBOL
void evrpc_request_set_pool(struct evrpc_request_wrapper *ctx,
struct evrpc_pool *pool);
EVENT2_EXPORT_SYMBOL
void evrpc_request_set_cb(struct evrpc_request_wrapper *ctx,
void (*cb)(struct evrpc_status*, void *request, void *reply, void *arg),
void *cb_arg);

View File

@ -1,4 +1,5 @@
/* $NetBSD: util.h,v 1.4 2017/01/31 23:17:40 christos Exp $ */
/* $NetBSD: util.h,v 1.5 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
*
@ -59,9 +60,6 @@ extern "C" {
#endif
#include <stdarg.h>
#ifdef EVENT__HAVE_NETDB_H
#if !defined(_GNU_SOURCE)
#define _GNU_SOURCE
#endif
#include <netdb.h>
#endif
@ -260,6 +258,7 @@ extern "C" {
#define EV_INT32_MAX INT32_MAX
#define EV_INT32_MIN INT32_MIN
#define EV_UINT16_MAX UINT16_MAX
#define EV_INT16_MIN INT16_MIN
#define EV_INT16_MAX INT16_MAX
#define EV_UINT8_MAX UINT8_MAX
#define EV_INT8_MAX INT8_MAX
@ -426,6 +425,18 @@ int evutil_make_listen_socket_reuseable(evutil_socket_t sock);
EVENT2_EXPORT_SYMBOL
int evutil_make_listen_socket_reuseable_port(evutil_socket_t sock);
/** Set ipv6 only bind socket option to make listener work only in ipv6 sockets.
According to RFC3493 and most Linux distributions, default value for the
sockets is to work in IPv4-mapped mode. In IPv4-mapped mode, it is not possible
to bind same port from different IPv4 and IPv6 handlers.
@param sock The socket to make in ipv6only working mode
@return 0 on success, -1 on failure
*/
EVENT2_EXPORT_SYMBOL
int evutil_make_listen_socket_ipv6only(evutil_socket_t sock);
/** Do platform-specific operations as needed to close a socket upon a
successful execution of one of the exec*() functions.
@ -439,7 +450,8 @@ int evutil_make_socket_closeonexec(evutil_socket_t sock);
socket() or accept().
@param sock The socket to be closed
@return 0 on success, -1 on failure
@return 0 on success (whether the operation is supported or not),
-1 on failure
*/
EVENT2_EXPORT_SYMBOL
int evutil_closesocket(evutil_socket_t sock);
@ -471,6 +483,7 @@ int evutil_socket_geterror(evutil_socket_t sock);
/** Convert a socket error to a string. */
EVENT2_EXPORT_SYMBOL
const char *evutil_socket_error_to_string(int errcode);
#define EVUTIL_INVALID_SOCKET INVALID_SOCKET
#elif defined(EVENT_IN_DOXYGEN_)
/**
@name Socket error functions
@ -494,14 +507,16 @@ const char *evutil_socket_error_to_string(int errcode);
#define evutil_socket_geterror(sock) ...
/** Convert a socket error to a string. */
#define evutil_socket_error_to_string(errcode) ...
#define EVUTIL_INVALID_SOCKET -1
/**@}*/
#else
#else /** !EVENT_IN_DOXYGEN_ && !_WIN32 */
#define EVUTIL_SOCKET_ERROR() (errno)
#define EVUTIL_SET_SOCKET_ERROR(errcode) \
do { errno = (errcode); } while (0)
#define evutil_socket_geterror(sock) (errno)
#define evutil_socket_error_to_string(errcode) (strerror(errcode))
#endif
#define EVUTIL_INVALID_SOCKET -1
#endif /** !_WIN32 */
/**
@ -599,6 +614,12 @@ int evutil_vsnprintf(char *buf, size_t buflen, const char *format, va_list ap)
/** Replacement for inet_ntop for platforms which lack it. */
EVENT2_EXPORT_SYMBOL
const char *evutil_inet_ntop(int af, const void *src, char *dst, size_t len);
/** Variation of inet_pton that also parses IPv6 scopes. Public for
unit tests. No reason to call this directly.
*/
EVENT2_EXPORT_SYMBOL
int evutil_inet_pton_scope(int af, const char *src, void *dst,
unsigned *indexp);
/** Replacement for inet_pton for platforms which lack it. */
EVENT2_EXPORT_SYMBOL
int evutil_inet_pton(int af, const char *src, void *dst);
@ -843,6 +864,7 @@ int evutil_secure_rng_init(void);
EVENT2_EXPORT_SYMBOL
int evutil_secure_rng_set_urandom_device_file(char *fname);
#if !defined(EVENT__HAVE_ARC4RANDOM) || defined(EVENT__HAVE_ARC4RANDOM_ADDRANDOM)
/** Seed the random number generator with extra random bytes.
You should almost never need to call this function; it should be
@ -859,6 +881,7 @@ int evutil_secure_rng_set_urandom_device_file(char *fname);
*/
EVENT2_EXPORT_SYMBOL
void evutil_secure_rng_add_bytes(const char *dat, size_t datlen);
#endif
#ifdef __cplusplus
}

View File

@ -1,501 +0,0 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2013-12-25.23; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# 'make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.
tab=' '
nl='
'
IFS=" $tab$nl"
# Set DOITPROG to "echo" to test this script.
doit=${DOITPROG-}
doit_exec=${doit:-exec}
# Put in absolute file names if you don't have them in your path;
# or use environment vars.
chgrpprog=${CHGRPPROG-chgrp}
chmodprog=${CHMODPROG-chmod}
chownprog=${CHOWNPROG-chown}
cmpprog=${CMPPROG-cmp}
cpprog=${CPPROG-cp}
mkdirprog=${MKDIRPROG-mkdir}
mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}
posix_mkdir=
# Desired mode of installed file.
mode=0755
chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
stripcmd=
src=
dst=
dir_arg=
dst_arg=
copy_on_change=false
is_target_a_directory=possibly
usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
or: $0 [OPTION]... -d DIRECTORIES...
In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.
Options:
--help display this help and exit.
--version display version info and exit.
-c (ignored)
-C install only if different (preserve the last data modification time)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-s $stripprog installed files.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
RMPROG STRIPPROG
"
while test $# -ne 0; do
case $1 in
-c) ;;
-C) copy_on_change=true;;
-d) dir_arg=true;;
-g) chgrpcmd="$chgrpprog $2"
shift;;
--help) echo "$usage"; exit $?;;
-m) mode=$2
case $mode in
*' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
echo "$0: invalid mode: $mode" >&2
exit 1;;
esac
shift;;
-o) chowncmd="$chownprog $2"
shift;;
-s) stripcmd=$stripprog;;
-t)
is_target_a_directory=always
dst_arg=$2
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
shift;;
-T) is_target_a_directory=never;;
--version) echo "$0 $scriptversion"; exit $?;;
--) shift
break;;
-*) echo "$0: invalid option: $1" >&2
exit 1;;
*) break;;
esac
shift
done
# We allow the use of options -d and -T together, by making -d
# take the precedence; this is for compatibility with GNU install.
if test -n "$dir_arg"; then
if test -n "$dst_arg"; then
echo "$0: target directory not allowed when installing a directory." >&2
exit 1
fi
fi
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
# When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
# Otherwise, the last argument is the destination. Remove it from $@.
for arg
do
if test -n "$dst_arg"; then
# $@ is not empty: it contains at least $arg.
set fnord "$@" "$dst_arg"
shift # fnord
fi
shift # arg
dst_arg=$arg
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
done
fi
if test $# -eq 0; then
if test -z "$dir_arg"; then
echo "$0: no input file specified." >&2
exit 1
fi
# It's OK to call 'install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
if test -z "$dir_arg"; then
if test $# -gt 1 || test "$is_target_a_directory" = always; then
if test ! -d "$dst_arg"; then
echo "$0: $dst_arg: Is not a directory." >&2
exit 1
fi
fi
fi
if test -z "$dir_arg"; then
do_exit='(exit $ret); exit $ret'
trap "ret=129; $do_exit" 1
trap "ret=130; $do_exit" 2
trap "ret=141; $do_exit" 13
trap "ret=143; $do_exit" 15
# Set umask so as not to create temps with too-generous modes.
# However, 'strip' requires both read and write access to temps.
case $mode in
# Optimize common cases.
*644) cp_umask=133;;
*755) cp_umask=22;;
*[0-7])
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw='% 200'
fi
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
*)
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw=,u+rw
fi
cp_umask=$mode$u_plus_rw;;
esac
fi
for src
do
# Protect names problematic for 'test' and other utilities.
case $src in
-* | [=\(\)!]) src=./$src;;
esac
if test -n "$dir_arg"; then
dst=$src
dstdir=$dst
test -d "$dstdir"
dstdir_status=$?
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if test ! -f "$src" && test ! -d "$src"; then
echo "$0: $src does not exist." >&2
exit 1
fi
if test -z "$dst_arg"; then
echo "$0: no destination specified." >&2
exit 1
fi
dst=$dst_arg
# If destination is a directory, append the input filename; won't work
# if double slashes aren't ignored.
if test -d "$dst"; then
if test "$is_target_a_directory" = never; then
echo "$0: $dst_arg: Is a directory" >&2
exit 1
fi
dstdir=$dst
dst=$dstdir/`basename "$src"`
dstdir_status=0
else
dstdir=`dirname "$dst"`
test -d "$dstdir"
dstdir_status=$?
fi
fi
obsolete_mkdir_used=false
if test $dstdir_status != 0; then
case $posix_mkdir in
'')
# Create intermediate dirs using mode 755 as modified by the umask.
# This is like FreeBSD 'install' as of 1997-10-28.
umask=`umask`
case $stripcmd.$umask in
# Optimize common cases.
*[2367][2367]) mkdir_umask=$umask;;
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
*[0-7])
mkdir_umask=`expr $umask + 22 \
- $umask % 100 % 40 + $umask % 20 \
- $umask % 10 % 4 + $umask % 2
`;;
*) mkdir_umask=$umask,go-w;;
esac
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
mkdir_mode=-m$mode
else
mkdir_mode=
fi
posix_mkdir=false
case $umask in
*[123567][0-7][0-7])
# POSIX mkdir -p sets u+wx bits regardless of umask, which
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
if (umask $mkdir_umask &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
ls_ld_tmpdir=`ls -ld "$tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/d" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
fi
trap '' 0;;
esac;;
esac
if
$posix_mkdir && (
umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
)
then :
else
# The umask is ridiculous, or mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go.
case $dstdir in
/*) prefix='/';;
[-=\(\)!]*) prefix='./';;
*) prefix='';;
esac
oIFS=$IFS
IFS=/
set -f
set fnord $dstdir
shift
set +f
IFS=$oIFS
prefixes=
for d
do
test X"$d" = X && continue
prefix=$prefix$d
if test -d "$prefix"; then
prefixes=
else
if $posix_mkdir; then
(umask=$mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
else
case $prefix in
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
*) qprefix=$prefix;;
esac
prefixes="$prefixes '$qprefix'"
fi
fi
prefix=$prefix/
done
if test -n "$prefixes"; then
# Don't fail if two instances are running concurrently.
(umask $mkdir_umask &&
eval "\$doit_exec \$mkdirprog $prefixes") ||
test -d "$dstdir" || exit 1
obsolete_mkdir_used=true
fi
fi
fi
if test -n "$dir_arg"; then
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
else
# Make a couple of temp file names in the proper directory.
dsttmp=$dstdir/_inst.$$_
rmtmp=$dstdir/_rm.$$_
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
# Copy the file name to the temp name.
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
# and set any options; do chmod last to preserve setuid bits.
#
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $cpprog $src $dsttmp" command.
#
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
# If -C, don't bother to copy if it wouldn't change the file.
if $copy_on_change &&
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
set -f &&
set X $old && old=:$2:$4:$5:$6 &&
set X $new && new=:$2:$4:$5:$6 &&
set +f &&
test "$old" = "$new" &&
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
then
rm -f "$dsttmp"
else
# Rename the file to the real destination.
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
# The rename failed, perhaps because mv can't rename something else
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
{
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
test ! -f "$dst" ||
$doit $rmcmd -f "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
} ||
{ echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1
}
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dst"
}
fi || exit 1
trap '' 0
fi
done
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

View File

@ -1,4 +1,4 @@
/* $NetBSD: kqueue.c,v 1.2 2019/10/03 22:16:52 kamil Exp $ */
/* $NetBSD: kqueue.c,v 1.3 2021/04/07 03:36:48 christos Exp $ */
/* $OpenBSD: kqueue.c,v 1.5 2002/07/10 14:41:31 art Exp $ */
/*
@ -29,7 +29,7 @@
*/
#include "event2/event-config.h"
#include <sys/cdefs.h>
__RCSID("$NetBSD: kqueue.c,v 1.2 2019/10/03 22:16:52 kamil Exp $");
__RCSID("$NetBSD: kqueue.c,v 1.3 2021/04/07 03:36:48 christos Exp $");
#include "evconfig-private.h"
#ifdef EVENT__HAVE_KQUEUE
@ -40,6 +40,7 @@ __RCSID("$NetBSD: kqueue.c,v 1.2 2019/10/03 22:16:52 kamil Exp $");
#endif
#include <sys/queue.h>
#include <sys/event.h>
#include <limits.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@ -68,6 +69,7 @@ __RCSID("$NetBSD: kqueue.c,v 1.2 2019/10/03 22:16:52 kamil Exp $");
#include "log-internal.h"
#include "evmap-internal.h"
#include "event2/thread.h"
#include "event2/util.h"
#include "evthread-internal.h"
#include "changelist-internal.h"
@ -213,9 +215,17 @@ kq_build_changes_list(const struct event_changelist *changelist,
struct event_change *in_ch = &changelist->changes[i];
struct kevent *out_ch;
if (n_changes >= kqop->changes_size - 1) {
int newsize = kqop->changes_size * 2;
int newsize;
struct kevent *newchanges;
if (kqop->changes_size > INT_MAX / 2 ||
(size_t)kqop->changes_size * 2 > EV_SIZE_MAX /
sizeof(struct kevent)) {
event_warnx("%s: int overflow", __func__);
return (-1);
}
newsize = kqop->changes_size * 2;
newchanges = mm_realloc(kqop->changes,
newsize * sizeof(struct kevent));
if (newchanges == NULL) {

View File

@ -1,4 +1,5 @@
/* $NetBSD: log-internal.h,v 1.5 2017/01/31 23:17:39 christos Exp $ */
/* $NetBSD: log-internal.h,v 1.6 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
@ -30,6 +31,10 @@
#include "event2/util.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __GNUC__
#define EV_CHECK_FMT(a,b) __attribute__((format(printf, a, b)))
#define EV_NORETURN __attribute__((noreturn))
@ -40,32 +45,35 @@
#define EVENT_ERR_ABORT_ ((int)0xdeaddead)
#define USE_GLOBAL_FOR_DEBUG_LOGGING
#if !defined(EVENT__DISABLE_DEBUG_MODE) || defined(USE_DEBUG)
#define EVENT_DEBUG_LOGGING_ENABLED
#endif
#ifdef EVENT_DEBUG_LOGGING_ENABLED
#ifdef USE_GLOBAL_FOR_DEBUG_LOGGING
extern ev_uint32_t event_debug_logging_mask_;
EVENT2_CORE_EXPORT_SYMBOL extern ev_uint32_t event_debug_logging_mask_;
#define event_debug_get_logging_mask_() (event_debug_logging_mask_)
#else
ev_uint32_t event_debug_get_logging_mask_(void);
#endif
#else
#define event_debug_get_logging_mask_() (0)
#endif
EVENT2_EXPORT_SYMBOL
void event_err(int eval, const char *fmt, ...) EV_CHECK_FMT(2,3) EV_NORETURN;
EVENT2_EXPORT_SYMBOL
void event_warn(const char *fmt, ...) EV_CHECK_FMT(1,2);
EVENT2_EXPORT_SYMBOL
void event_sock_err(int eval, evutil_socket_t sock, const char *fmt, ...) EV_CHECK_FMT(3,4) EV_NORETURN;
EVENT2_EXPORT_SYMBOL
void event_sock_warn(evutil_socket_t sock, const char *fmt, ...) EV_CHECK_FMT(2,3);
EVENT2_EXPORT_SYMBOL
void event_errx(int eval, const char *fmt, ...) EV_CHECK_FMT(2,3) EV_NORETURN;
EVENT2_EXPORT_SYMBOL
void event_warnx(const char *fmt, ...) EV_CHECK_FMT(1,2);
EVENT2_EXPORT_SYMBOL
void event_msgx(const char *fmt, ...) EV_CHECK_FMT(1,2);
EVENT2_EXPORT_SYMBOL
void event_debugx_(const char *fmt, ...) EV_CHECK_FMT(1,2);
EVENT2_EXPORT_SYMBOL
void event_logv_(int severity, const char *errstr, const char *fmt, va_list ap)
EV_CHECK_FMT(3,0);
@ -81,4 +89,8 @@ void event_logv_(int severity, const char *errstr, const char *fmt, va_list ap)
#undef EV_CHECK_FMT
#ifdef __cplusplus
}
#endif
#endif /* LOG_INTERNAL_H_INCLUDED_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: log.c,v 1.5 2017/01/31 23:17:39 christos Exp $ */
/* $NetBSD: log.c,v 1.6 2021/04/07 03:36:48 christos Exp $ */
/* $OpenBSD: err.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */
/*
@ -40,7 +40,7 @@
#include "event2/event-config.h"
#include <sys/cdefs.h>
__RCSID("$NetBSD: log.c,v 1.5 2017/01/31 23:17:39 christos Exp $");
__RCSID("$NetBSD: log.c,v 1.6 2021/04/07 03:36:48 christos Exp $");
#include "evconfig-private.h"
#ifdef _WIN32
@ -72,16 +72,7 @@ static event_fatal_cb fatal_fn = NULL;
#define DEFAULT_MASK 0
#endif
#ifdef USE_GLOBAL_FOR_DEBUG_LOGGING
ev_uint32_t event_debug_logging_mask_ = DEFAULT_MASK;
#else
static ev_uint32_t event_debug_logging_mask_ = DEFAULT_MASK;
ev_uint32_t
event_debug_get_logging_mask_(void)
{
return event_debug_logging_mask_;
}
#endif
EVENT2_EXPORT_SYMBOL ev_uint32_t event_debug_logging_mask_ = DEFAULT_MASK;
#endif /* EVENT_DEBUG_LOGGING_ENABLED */
void

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* $NetBSD: minheap-internal.h,v 1.3 2017/01/31 23:17:39 christos Exp $ */
/* $NetBSD: minheap-internal.h,v 1.4 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
*
@ -71,7 +71,7 @@ struct event* min_heap_top_(min_heap_t* s) { return s->n ? *s->p : 0; }
int min_heap_push_(min_heap_t* s, struct event* e)
{
if (min_heap_reserve_(s, s->n + 1))
if (s->n == UINT32_MAX || min_heap_reserve_(s, s->n + 1))
return -1;
min_heap_shift_up_(s, s->n++, e);
return 0;
@ -139,6 +139,10 @@ int min_heap_reserve_(min_heap_t* s, unsigned n)
unsigned a = s->a ? s->a * 2 : 8;
if (a < n)
a = n;
#if (SIZE_MAX == UINT32_MAX)
if (a > SIZE_MAX / sizeof *p)
return -1;
#endif
if (!(p = (struct event**)mm_realloc(s->p, a * sizeof *p)))
return -1;
s->p = p;

View File

@ -1,215 +0,0 @@
#! /bin/sh
# Common wrapper for a few potentially missing GNU programs.
scriptversion=2013-10-28.13; # UTC
# Copyright (C) 1996-2014 Free Software Foundation, Inc.
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
if test $# -eq 0; then
echo 1>&2 "Try '$0 --help' for more information"
exit 1
fi
case $1 in
--is-lightweight)
# Used by our autoconf macros to check whether the available missing
# script is modern enough.
exit 0
;;
--run)
# Back-compat with the calling convention used by older automake.
shift
;;
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
to PROGRAM being missing or too old.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
Supported PROGRAM values:
aclocal autoconf autoheader autom4te automake makeinfo
bison yacc flex lex help2man
Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
'g' are ignored when checking the name.
Send bug reports to <bug-automake@gnu.org>."
exit $?
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing $scriptversion (GNU Automake)"
exit $?
;;
-*)
echo 1>&2 "$0: unknown '$1' option"
echo 1>&2 "Try '$0 --help' for more information"
exit 1
;;
esac
# Run the given program, remember its exit status.
"$@"; st=$?
# If it succeeded, we are done.
test $st -eq 0 && exit 0
# Also exit now if we it failed (or wasn't found), and '--version' was
# passed; such an option is passed most likely to detect whether the
# program is present and works.
case $2 in --version|--help) exit $st;; esac
# Exit code 63 means version mismatch. This often happens when the user
# tries to use an ancient version of a tool on a file that requires a
# minimum version.
if test $st -eq 63; then
msg="probably too old"
elif test $st -eq 127; then
# Program was missing.
msg="missing on your system"
else
# Program was found and executed, but failed. Give up.
exit $st
fi
perl_URL=http://www.perl.org/
flex_URL=http://flex.sourceforge.net/
gnu_software_URL=http://www.gnu.org/software
program_details ()
{
case $1 in
aclocal|automake)
echo "The '$1' program is part of the GNU Automake package:"
echo "<$gnu_software_URL/automake>"
echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/autoconf>"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
autoconf|autom4te|autoheader)
echo "The '$1' program is part of the GNU Autoconf package:"
echo "<$gnu_software_URL/autoconf/>"
echo "It also requires GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
esac
}
give_advice ()
{
# Normalize program name to check for.
normalized_program=`echo "$1" | sed '
s/^gnu-//; t
s/^gnu//; t
s/^g//; t'`
printf '%s\n' "'$1' is $msg."
configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
case $normalized_program in
autoconf*)
echo "You should only need it if you modified 'configure.ac',"
echo "or m4 files included by it."
program_details 'autoconf'
;;
autoheader*)
echo "You should only need it if you modified 'acconfig.h' or"
echo "$configure_deps."
program_details 'autoheader'
;;
automake*)
echo "You should only need it if you modified 'Makefile.am' or"
echo "$configure_deps."
program_details 'automake'
;;
aclocal*)
echo "You should only need it if you modified 'acinclude.m4' or"
echo "$configure_deps."
program_details 'aclocal'
;;
autom4te*)
echo "You might have modified some maintainer files that require"
echo "the 'autom4te' program to be rebuilt."
program_details 'autom4te'
;;
bison*|yacc*)
echo "You should only need it if you modified a '.y' file."
echo "You may want to install the GNU Bison package:"
echo "<$gnu_software_URL/bison/>"
;;
lex*|flex*)
echo "You should only need it if you modified a '.l' file."
echo "You may want to install the Fast Lexical Analyzer package:"
echo "<$flex_URL>"
;;
help2man*)
echo "You should only need it if you modified a dependency" \
"of a man page."
echo "You may want to install the GNU Help2man package:"
echo "<$gnu_software_URL/help2man/>"
;;
makeinfo*)
echo "You should only need it if you modified a '.texi' file, or"
echo "any other file indirectly affecting the aspect of the manual."
echo "You might want to install the Texinfo package:"
echo "<$gnu_software_URL/texinfo/>"
echo "The spurious makeinfo call might also be the consequence of"
echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
echo "want to install GNU make:"
echo "<$gnu_software_URL/make/>"
;;
*)
echo "You might have modified some files without having the proper"
echo "tools for further handling them. Check the 'README' file, it"
echo "often tells you about the needed prerequisites for installing"
echo "this package. You may also peek at any GNU archive site, in"
echo "case some other package contains this missing '$1' program."
;;
esac
}
give_advice "$1" | sed -e '1s/^/WARNING: /' \
-e '2,$s/^/ /' >&2
# Propagate the correct exit status (expected to be 127 for a program
# not found, 63 for a program that failed due to version mismatch).
exit $st
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

View File

@ -1,4 +1,4 @@
/* $NetBSD: select.c,v 1.3 2017/01/31 23:17:39 christos Exp $ */
/* $NetBSD: select.c,v 1.4 2021/04/07 03:36:48 christos Exp $ */
/* $OpenBSD: select.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */
/*
@ -29,7 +29,7 @@
*/
#include "event2/event-config.h"
#include <sys/cdefs.h>
__RCSID("$NetBSD: select.c,v 1.3 2017/01/31 23:17:39 christos Exp $");
__RCSID("$NetBSD: select.c,v 1.4 2021/04/07 03:36:48 christos Exp $");
#include "evconfig-private.h"
#ifdef EVENT__HAVE_SELECT
@ -101,7 +101,7 @@ const struct eventop selectops = {
select_del,
select_dispatch,
select_dealloc,
0, /* doesn't need reinit. */
1, /* need_reinit. */
EV_FEATURE_FDS,
0,
};

View File

@ -1,148 +0,0 @@
#! /bin/sh
# test-driver - basic testsuite driver script.
scriptversion=2013-07-13.22; # UTC
# Copyright (C) 2011-2014 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
# Make unconditional expansion of undefined variables an error. This
# helps a lot in preventing typo-related bugs.
set -u
usage_error ()
{
echo "$0: $*" >&2
print_usage >&2
exit 2
}
print_usage ()
{
cat <<END
Usage:
test-driver --test-name=NAME --log-file=PATH --trs-file=PATH
[--expect-failure={yes|no}] [--color-tests={yes|no}]
[--enable-hard-errors={yes|no}] [--]
TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS]
The '--test-name', '--log-file' and '--trs-file' options are mandatory.
END
}
test_name= # Used for reporting.
log_file= # Where to save the output of the test script.
trs_file= # Where to save the metadata of the test run.
expect_failure=no
color_tests=no
enable_hard_errors=yes
while test $# -gt 0; do
case $1 in
--help) print_usage; exit $?;;
--version) echo "test-driver $scriptversion"; exit $?;;
--test-name) test_name=$2; shift;;
--log-file) log_file=$2; shift;;
--trs-file) trs_file=$2; shift;;
--color-tests) color_tests=$2; shift;;
--expect-failure) expect_failure=$2; shift;;
--enable-hard-errors) enable_hard_errors=$2; shift;;
--) shift; break;;
-*) usage_error "invalid option: '$1'";;
*) break;;
esac
shift
done
missing_opts=
test x"$test_name" = x && missing_opts="$missing_opts --test-name"
test x"$log_file" = x && missing_opts="$missing_opts --log-file"
test x"$trs_file" = x && missing_opts="$missing_opts --trs-file"
if test x"$missing_opts" != x; then
usage_error "the following mandatory options are missing:$missing_opts"
fi
if test $# -eq 0; then
usage_error "missing argument"
fi
if test $color_tests = yes; then
# Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'.
red='' # Red.
grn='' # Green.
lgn='' # Light green.
blu='' # Blue.
mgn='' # Magenta.
std='' # No color.
else
red= grn= lgn= blu= mgn= std=
fi
do_exit='rm -f $log_file $trs_file; (exit $st); exit $st'
trap "st=129; $do_exit" 1
trap "st=130; $do_exit" 2
trap "st=141; $do_exit" 13
trap "st=143; $do_exit" 15
# Test script is run here.
"$@" >$log_file 2>&1
estatus=$?
if test $enable_hard_errors = no && test $estatus -eq 99; then
tweaked_estatus=1
else
tweaked_estatus=$estatus
fi
case $tweaked_estatus:$expect_failure in
0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;
0:*) col=$grn res=PASS recheck=no gcopy=no;;
77:*) col=$blu res=SKIP recheck=no gcopy=yes;;
99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;;
*:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;;
*:*) col=$red res=FAIL recheck=yes gcopy=yes;;
esac
# Report the test outcome and exit status in the logs, so that one can
# know whether the test passed or failed simply by looking at the '.log'
# file, without the need of also peaking into the corresponding '.trs'
# file (automake bug#11814).
echo "$res $test_name (exit status: $estatus)" >>$log_file
# Report outcome to console.
echo "${col}${res}${std}: $test_name"
# Register the test result, and other relevant metadata.
echo ":test-result: $res" > $trs_file
echo ":global-test-result: $res" >> $trs_file
echo ":recheck: $recheck" >> $trs_file
echo ":copy-in-global-log: $gcopy" >> $trs_file
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

View File

@ -1,4 +1,5 @@
/* $NetBSD: regress.c,v 1.9 2017/01/31 23:17:40 christos Exp $ */
/* $NetBSD: regress.c,v 1.10 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu>
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
@ -32,13 +33,9 @@
#include <windows.h>
#endif
#ifdef EVENT__HAVE_PTHREADS
#include <pthread.h>
#endif
#include "event2/event-config.h"
#include <sys/cdefs.h>
__RCSID("$NetBSD: regress.c,v 1.9 2017/01/31 23:17:40 christos Exp $");
__RCSID("$NetBSD: regress.c,v 1.10 2021/04/07 03:36:48 christos Exp $");
#include <sys/types.h>
#include <sys/stat.h>
@ -49,6 +46,7 @@ __RCSID("$NetBSD: regress.c,v 1.9 2017/01/31 23:17:40 christos Exp $");
#ifndef _WIN32
#include <sys/socket.h>
#include <sys/wait.h>
#include <limits.h>
#include <signal.h>
#include <unistd.h>
#include <netdb.h>
@ -75,6 +73,7 @@ __RCSID("$NetBSD: regress.c,v 1.9 2017/01/31 23:17:40 christos Exp $");
#include "time-internal.h"
#include "regress.h"
#include "regress_thread.h"
#ifndef _WIN32
#include "regress.gen.h"
@ -392,7 +391,7 @@ record_event_cb(evutil_socket_t s, short what, void *ptr)
}
static void
test_simpleclose(void *ptr)
test_simpleclose_rw(void *ptr)
{
/* Test that a close of FD is detected as a read and as a write. */
struct event_base *base = event_base_new();
@ -474,6 +473,56 @@ end:
event_base_free(base);
}
static void
test_simpleclose(void *ptr)
{
struct basic_test_data *data = ptr;
struct event_base *base = data->base;
evutil_socket_t *xpair = data->pair;
const char *flags = (const char *)data->setup_data;
int et = !!strstr(flags, "ET");
int persist = !!strstr(flags, "persist");
short events = EV_CLOSED | (et ? EV_ET : 0) | (persist ? EV_PERSIST : 0);
struct event *ev = NULL;
short got_event;
if (!(event_base_get_features(data->base) & EV_FEATURE_EARLY_CLOSE))
tt_skip();
/* XXX: should this code moved to regress_et.c ? */
if (et && !(event_base_get_features(data->base) & EV_FEATURE_ET))
tt_skip();
ev = event_new(base, xpair[0], events, record_event_cb, &got_event);
tt_assert(ev);
tt_assert(!event_add(ev, NULL));
got_event = 0;
if (strstr(flags, "close")) {
tt_assert(!evutil_closesocket(xpair[1]));
/* avoid closing in setup routines */
xpair[1] = -1;
} else if (strstr(flags, "shutdown")) {
tt_assert(!shutdown(xpair[1], EVUTIL_SHUT_WR));
} else {
tt_abort_msg("unknown flags");
}
/* w/o edge-triggerd but w/ persist it will not stop */
if (!et && persist) {
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 10000;
tt_assert(!event_base_loopexit(base, &tv));
}
tt_int_op(event_base_loop(base, EVLOOP_NONBLOCK), ==, !persist);
tt_int_op(got_event, ==, (events & ~EV_PERSIST));
end:
if (ev)
event_free(ev);
}
static void
test_multiple(void)
@ -851,18 +900,36 @@ simple_child_read_cb(evutil_socket_t fd, short event, void *arg)
called++;
}
#define TEST_FORK_EXIT_SUCCESS 76
static void fork_wait_check(int pid)
{
int status;
TT_BLATHER(("Before waitpid"));
#ifdef WNOWAIT
if ((waitpid(pid, &status, WNOWAIT) == -1 && errno == EINVAL) &&
#else
if (
#endif
waitpid(pid, &status, 0) == -1) {
perror("waitpid");
exit(1);
}
TT_BLATHER(("After waitpid"));
if (WEXITSTATUS(status) != TEST_FORK_EXIT_SUCCESS) {
fprintf(stdout, "FAILED (exit): %d\n", WEXITSTATUS(status));
exit(1);
}
}
static void
test_fork(void)
{
char c;
int status;
struct event ev, sig_ev, usr_ev, existing_ev;
pid_t pid;
int wait_flags = 0;
#ifdef EVENT__HAVE_WAITPID_WITH_WNOWAIT
wait_flags |= WNOWAIT;
#endif
setup_test("After fork: ");
@ -913,8 +980,8 @@ test_fork(void)
evsignal_set(&usr_ev, SIGUSR1, fork_signal_cb, &usr_ev);
evsignal_add(&usr_ev, NULL);
raise(SIGUSR1);
raise(SIGUSR2);
kill(getpid(), SIGUSR1);
kill(getpid(), SIGUSR2);
called = 0;
@ -925,7 +992,7 @@ test_fork(void)
/* we do not send an EOF; simple_read_cb requires an EOF
* to set test_ok. we just verify that the callback was
* called. */
exit(test_ok != 0 || called != 2 ? -2 : 76);
exit(test_ok != 0 || called != 2 ? -2 : TEST_FORK_EXIT_SUCCESS);
}
/** wait until client read first message */
@ -936,17 +1003,7 @@ test_fork(void)
tt_fail_perror("write");
}
TT_BLATHER(("Before waitpid"));
if (waitpid(pid, &status, wait_flags) == -1) {
perror("waitpid");
exit(1);
}
TT_BLATHER(("After waitpid"));
if (WEXITSTATUS(status) != 76) {
fprintf(stdout, "FAILED (exit): %d\n", WEXITSTATUS(status));
exit(1);
}
fork_wait_check(pid);
/* test that the current event loop still works */
if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) {
@ -957,8 +1014,8 @@ test_fork(void)
evsignal_set(&usr_ev, SIGUSR1, fork_signal_cb, &usr_ev);
evsignal_add(&usr_ev, NULL);
raise(SIGUSR1);
raise(SIGUSR2);
kill(getpid(), SIGUSR1);
kill(getpid(), SIGUSR2);
event_dispatch();
@ -973,7 +1030,7 @@ test_fork(void)
evutil_closesocket(child_pair[1]);
}
#ifdef EVENT__HAVE_PTHREADS
#ifdef EVTHREAD_USE_PTHREADS_IMPLEMENTED
static void* del_wait_thread(void *arg)
{
struct timeval tv_start, tv_end;
@ -992,23 +1049,23 @@ static void
del_wait_cb(evutil_socket_t fd, short event, void *arg)
{
struct timeval delay = { 0, 300*1000 };
TT_BLATHER(("Sleeping"));
TT_BLATHER(("Sleeping: %i", test_ok));
evutil_usleep_(&delay);
test_ok = 1;
++test_ok;
}
static void
test_del_wait(void)
{
struct event ev;
pthread_t thread;
THREAD_T thread;
setup_test("event_del will wait: ");
event_set(&ev, pair[1], EV_READ, del_wait_cb, &ev);
event_set(&ev, pair[1], EV_READ|EV_PERSIST, del_wait_cb, &ev);
event_add(&ev, NULL);
pthread_create(&thread, NULL, del_wait_thread, NULL);
THREAD_START(thread, del_wait_thread, NULL);
if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) {
tt_fail_perror("write");
@ -1027,11 +1084,41 @@ test_del_wait(void)
test_timeval_diff_eq(&tv_start, &tv_end, 270);
}
pthread_join(thread, NULL);
THREAD_JOIN(thread);
tt_int_op(test_ok, ==, 1);
end:
;
}
static void null_cb(evutil_socket_t fd, short what, void *arg) {}
static void* test_del_notify_thread(void *arg)
{
event_dispatch();
return NULL;
}
static void
test_del_notify(void)
{
struct event ev;
THREAD_T thread;
test_ok = 1;
event_set(&ev, -1, EV_READ, null_cb, &ev);
event_add(&ev, NULL);
THREAD_START(thread, test_del_notify_thread, NULL);
{
struct timeval delay = { 0, 1000 };
evutil_usleep_(&delay);
}
event_del(&ev);
THREAD_JOIN(thread);
}
#endif
static void
@ -1130,7 +1217,7 @@ test_immediatesignal(void)
test_ok = 0;
evsignal_set(&ev, SIGUSR1, signal_cb, &ev);
evsignal_add(&ev, NULL);
raise(SIGUSR1);
kill(getpid(), SIGUSR1);
event_loop(EVLOOP_NONBLOCK);
evsignal_del(&ev);
cleanup_test();
@ -1203,7 +1290,7 @@ test_signal_switchbase(void)
test_ok = 0;
/* can handle signal before loop is called */
raise(SIGUSR1);
kill(getpid(), SIGUSR1);
event_base_loop(base2, EVLOOP_NONBLOCK);
if (is_kqueue) {
if (!test_ok)
@ -1216,7 +1303,7 @@ test_signal_switchbase(void)
/* set base1 to handle signals */
event_base_loop(base1, EVLOOP_NONBLOCK);
raise(SIGUSR1);
kill(getpid(), SIGUSR1);
event_base_loop(base1, EVLOOP_NONBLOCK);
event_base_loop(base2, EVLOOP_NONBLOCK);
}
@ -1245,7 +1332,7 @@ test_signal_assert(void)
*/
evsignal_del(&ev);
raise(SIGCONT);
kill(getpid(), SIGCONT);
#if 0
/* only way to verify we were in evsig_handler() */
/* XXXX Now there's no longer a good way. */
@ -1289,7 +1376,7 @@ test_signal_restore(void)
evsignal_add(&ev, NULL);
evsignal_del(&ev);
raise(SIGUSR1);
kill(getpid(), SIGUSR1);
/* 1 == signal_cb, 2 == signal_cb_sa, we want our previous handler */
if (test_ok != 2)
test_ok = 0;
@ -1304,7 +1391,7 @@ signal_cb_swp(int sig, short event, void *arg)
{
called++;
if (called < 5)
raise(sig);
kill(getpid(), sig);
else
event_loopexit(NULL);
}
@ -1316,7 +1403,7 @@ timeout_cb_swp(evutil_socket_t fd, short event, void *arg)
called = 0;
evtimer_add((struct event *)arg, &tv);
raise(SIGUSR1);
kill(getpid(), SIGUSR1);
return;
}
test_ok = 0;
@ -1354,18 +1441,14 @@ test_free_active_base(void *ptr)
struct event ev1;
base1 = event_init();
if (base1) {
event_assign(&ev1, base1, data->pair[1], EV_READ,
dummy_read_cb, NULL);
event_add(&ev1, NULL);
event_base_free(base1); /* should not crash */
} else {
tt_fail_msg("failed to create event_base for test");
}
tt_assert(base1);
event_assign(&ev1, base1, data->pair[1], EV_READ, dummy_read_cb, NULL);
event_add(&ev1, NULL);
event_base_free(base1); /* should not crash */
base1 = event_init();
tt_assert(base1);
event_assign(&ev1, base1, 0, 0, dummy_read_cb, NULL);
event_assign(&ev1, base1, data->pair[0], 0, dummy_read_cb, NULL);
event_active(&ev1, EV_READ, 1);
event_base_free(base1);
end:
@ -1843,7 +1926,8 @@ static void send_a_byte_cb(evutil_socket_t fd, short what, void *arg)
{
evutil_socket_t *sockp = arg;
(void) fd; (void) what;
(void) write(*sockp, "A", 1);
if (write(*sockp, "A", 1) < 0)
tt_fail_perror("write");
}
struct read_not_timeout_param
{
@ -2073,60 +2157,48 @@ re_add_read_cb(evutil_socket_t fd, short event, void *arg)
if (n_read < 0) {
tt_fail_perror("read");
event_base_loopbreak(event_get_base(ev_other));
return;
} else {
event_add(ev_other, NULL);
++test_ok;
}
}
static void
test_nonpersist_readd(void)
test_nonpersist_readd(void *_data)
{
struct event ev1, ev2;
struct basic_test_data *data = _data;
setup_test("Re-add nonpersistent events: ");
event_set(&ev1, pair[0], EV_READ, re_add_read_cb, &ev2);
event_set(&ev2, pair[1], EV_READ, re_add_read_cb, &ev1);
memset(&ev1, 0, sizeof(ev1));
memset(&ev2, 0, sizeof(ev2));
if (write(pair[0], "Hello", 5) < 0) {
tt_fail_perror("write(pair[0])");
}
tt_assert(!event_assign(&ev1, data->base, data->pair[0], EV_READ, re_add_read_cb, &ev2));
tt_assert(!event_assign(&ev2, data->base, data->pair[1], EV_READ, re_add_read_cb, &ev1));
if (write(pair[1], "Hello", 5) < 0) {
tt_fail_perror("write(pair[1])\n");
}
tt_int_op(write(data->pair[0], "Hello", 5), ==, 5);
tt_int_op(write(data->pair[1], "Hello", 5), ==, 5);
tt_int_op(event_add(&ev1, NULL), ==, 0);
tt_int_op(event_add(&ev2, NULL), ==, 0);
tt_int_op(event_base_loop(data->base, EVLOOP_ONCE), ==, 0);
tt_int_op(test_ok, ==, 2);
if (event_add(&ev1, NULL) == -1 ||
event_add(&ev2, NULL) == -1) {
test_ok = 0;
}
if (test_ok != 0)
exit(1);
event_loop(EVLOOP_ONCE);
if (test_ok != 2)
exit(1);
/* At this point, we executed both callbacks. Whichever one got
* called first added the second, but the second then immediately got
* deleted before its callback was called. At this point, though, it
* re-added the first.
*/
if (!readd_test_event_last_added) {
test_ok = 0;
} else if (readd_test_event_last_added == &ev1) {
if (!event_pending(&ev1, EV_READ, NULL) ||
event_pending(&ev2, EV_READ, NULL))
test_ok = 0;
tt_assert(readd_test_event_last_added);
if (readd_test_event_last_added == &ev1) {
tt_assert(event_pending(&ev1, EV_READ, NULL) && !event_pending(&ev2, EV_READ, NULL));
} else {
if (event_pending(&ev1, EV_READ, NULL) ||
!event_pending(&ev2, EV_READ, NULL))
test_ok = 0;
tt_assert(event_pending(&ev2, EV_READ, NULL) && !event_pending(&ev1, EV_READ, NULL));
}
event_del(&ev1);
event_del(&ev2);
cleanup_test();
end:
if (event_initialized(&ev1))
event_del(&ev1);
if (event_initialized(&ev2))
event_del(&ev2);
}
struct test_pri_event {
@ -3044,6 +3116,7 @@ test_many_events(void *arg)
* instance of that. */
sock[i] = socket(AF_INET, SOCK_DGRAM, 0);
tt_assert(sock[i] >= 0);
tt_assert(!evutil_make_socket_nonblocking(sock[i]));
xcalled[i] = 0;
ev[i] = event_new(base, sock[i], EV_WRITE|evflags,
many_event_cb, &xcalled[i]);
@ -3098,7 +3171,7 @@ test_get_assignment(void *arg)
event_get_assignment(ev1, &b, &s, &what, &cb, &cb_arg);
tt_ptr_op(b, ==, base);
tt_int_op(s, ==, data->pair[1]);
tt_fd_op(s, ==, data->pair[1]);
tt_int_op(what, ==, EV_READ);
tt_ptr_op(cb, ==, dummy_read_cb);
tt_ptr_op(cb_arg, ==, str);
@ -3283,6 +3356,46 @@ tabf_cb(evutil_socket_t fd, short what, void *arg)
*ptr += 0x10000;
}
static void
test_evmap_invalid_slots(void *arg)
{
struct basic_test_data *data = arg;
struct event_base *base = data->base;
struct event *ev1 = NULL, *ev2 = NULL;
int e1, e2;
#ifndef _WIN32
struct event *ev3 = NULL, *ev4 = NULL;
int e3, e4;
#endif
ev1 = evsignal_new(base, -1, dummy_read_cb, (void *)base);
ev2 = evsignal_new(base, NSIG, dummy_read_cb, (void *)base);
tt_assert(ev1);
tt_assert(ev2);
e1 = event_add(ev1, NULL);
e2 = event_add(ev2, NULL);
tt_int_op(e1, !=, 0);
tt_int_op(e2, !=, 0);
#ifndef _WIN32
ev3 = event_new(base, INT_MAX, EV_READ, dummy_read_cb, (void *)base);
ev4 = event_new(base, INT_MAX / 2, EV_READ, dummy_read_cb, (void *)base);
tt_assert(ev3);
tt_assert(ev4);
e3 = event_add(ev3, NULL);
e4 = event_add(ev4, NULL);
tt_int_op(e3, !=, 0);
tt_int_op(e4, !=, 0);
#endif
end:
event_free(ev1);
event_free(ev2);
#ifndef _WIN32
event_free(ev3);
event_free(ev4);
#endif
}
static void
test_active_by_fd(void *arg)
{
@ -3334,6 +3447,7 @@ test_active_by_fd(void *arg)
/* Trigger 2, 3, 4 */
event_base_active_by_fd(base, data->pair[0], EV_WRITE);
event_base_active_by_fd(base, data->pair[1], EV_READ);
event_base_active_by_fd(base, data->pair[1], EV_TIMEOUT);
#ifndef _WIN32
event_base_active_by_signal(base, SIGHUP);
#endif
@ -3346,7 +3460,7 @@ test_active_by_fd(void *arg)
tt_int_op(e2, ==, EV_WRITE | 0x10000);
tt_int_op(e3, ==, EV_READ | 0x10000);
/* Mask out EV_WRITE here, since it could be genuinely writeable. */
tt_int_op((e4 & ~EV_WRITE), ==, EV_READ | 0x10000);
tt_int_op((e4 & ~EV_WRITE), ==, EV_READ | EV_TIMEOUT | 0x10000);
#ifndef _WIN32
tt_int_op(es, ==, EV_SIGNAL | 0x10000);
#endif
@ -3381,17 +3495,18 @@ struct testcase_t main_testcases[] = {
BASIC(event_assign_selfarg, TT_FORK|TT_NEED_BASE),
BASIC(event_base_get_num_events, TT_FORK|TT_NEED_BASE),
BASIC(event_base_get_max_events, TT_FORK|TT_NEED_BASE),
BASIC(evmap_invalid_slots, TT_FORK|TT_NEED_BASE),
BASIC(bad_assign, TT_FORK|TT_NEED_BASE|TT_NO_LOGS),
BASIC(bad_reentrant, TT_FORK|TT_NEED_BASE|TT_NO_LOGS),
BASIC(active_later, TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR),
BASIC(active_later, TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR|TT_RETRIABLE),
BASIC(event_remove_timeout, TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR),
/* These are still using the old API */
LEGACY(persistent_timeout, TT_FORK|TT_NEED_BASE),
{ "persistent_timeout_jump", test_persistent_timeout_jump, TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
{ "persistent_active_timeout", test_persistent_active_timeout,
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
TT_FORK|TT_NEED_BASE|TT_RETRIABLE, &basic_setup, NULL },
LEGACY(priorities, TT_FORK|TT_NEED_BASE),
BASIC(priority_active_inversion, TT_FORK|TT_NEED_BASE),
{ "common_timeout", test_common_timeout, TT_FORK|TT_NEED_BASE,
@ -3401,8 +3516,35 @@ struct testcase_t main_testcases[] = {
LEGACY(simpleread, TT_ISOLATED),
LEGACY(simpleread_multiple, TT_ISOLATED),
LEGACY(simplewrite, TT_ISOLATED),
{ "simpleclose", test_simpleclose, TT_FORK, &basic_setup,
NULL },
{ "simpleclose_rw", test_simpleclose_rw, TT_FORK, &basic_setup, NULL },
/* simpleclose */
{ "simpleclose_close", test_simpleclose,
TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE,
&basic_setup, __UNCONST("close") },
{ "simpleclose_shutdown", test_simpleclose,
TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE,
&basic_setup, __UNCONST("shutdown") },
/* simpleclose_*_persist */
{ "simpleclose_close_persist", test_simpleclose,
TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE,
&basic_setup, __UNCONST("close_persist") },
{ "simpleclose_shutdown_persist", test_simpleclose,
TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE,
&basic_setup, __UNCONST("shutdown_persist") },
/* simpleclose_*_et */
{ "simpleclose_close_et", test_simpleclose,
TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE,
&basic_setup, __UNCONST("close_ET") },
{ "simpleclose_shutdown_et", test_simpleclose,
TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE,
&basic_setup, __UNCONST("shutdown_ET") },
/* simpleclose_*_persist_et */
{ "simpleclose_close_persist_et", test_simpleclose,
TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE,
&basic_setup, __UNCONST("close_persist_ET") },
{ "simpleclose_shutdown_persist_et", test_simpleclose,
TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE,
&basic_setup, __UNCONST("shutdown_persist_ET") },
LEGACY(multiple, TT_ISOLATED),
LEGACY(persistent, TT_ISOLATED),
LEGACY(combined, TT_ISOLATED),
@ -3410,7 +3552,7 @@ struct testcase_t main_testcases[] = {
LEGACY(loopbreak, TT_ISOLATED),
LEGACY(loopexit, TT_ISOLATED),
LEGACY(loopexit_multiple, TT_ISOLATED),
LEGACY(nonpersist_readd, TT_ISOLATED),
{ "nonpersist_readd", test_nonpersist_readd, TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE, &basic_setup, NULL },
LEGACY(multiple_events_for_same_fd, TT_ISOLATED),
LEGACY(want_only_once, TT_ISOLATED),
{ "event_once", test_event_once, TT_ISOLATED, &basic_setup, NULL },
@ -3442,9 +3584,10 @@ struct testcase_t main_testcases[] = {
#ifndef _WIN32
LEGACY(fork, TT_ISOLATED),
#endif
#ifdef EVENT__HAVE_PTHREADS
/** TODO: support win32 */
LEGACY(del_wait, TT_ISOLATED|TT_NEED_THREADS),
#ifdef EVTHREAD_USE_PTHREADS_IMPLEMENTED
LEGACY(del_wait, TT_ISOLATED|TT_NEED_THREADS|TT_RETRIABLE),
LEGACY(del_notify, TT_ISOLATED|TT_NEED_THREADS),
#endif
END_OF_TESTCASES

View File

@ -1,4 +1,5 @@
/* $NetBSD: regress.h,v 1.6 2017/01/31 23:17:40 christos Exp $ */
/* $NetBSD: regress.h,v 1.7 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
@ -44,6 +45,7 @@ extern struct testcase_t bufferevent_iocp_testcases[];
extern struct testcase_t util_testcases[];
extern struct testcase_t signal_testcases[];
extern struct testcase_t http_testcases[];
extern struct testcase_t http_iocp_testcases[];
extern struct testcase_t dns_testcases[];
extern struct testcase_t rpc_testcases[];
extern struct testcase_t edgetriggered_testcases[];
@ -95,6 +97,7 @@ extern int libevent_tests_running_in_debug_mode;
#define TT_NO_LOGS (TT_FIRST_USER_FLAG<<5)
#define TT_ENABLE_IOCP_FLAG (TT_FIRST_USER_FLAG<<6)
#define TT_ENABLE_IOCP (TT_ENABLE_IOCP_FLAG|TT_NEED_THREADS)
#define TT_ENABLE_DEBUG_MODE (TT_ENABLE_IOCP_FLAG<<7)
/* All the flags that a legacy test needs. */
#define TT_ISOLATED TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_BASE
@ -133,11 +136,14 @@ pid_t regress_fork(void);
#ifdef EVENT__HAVE_OPENSSL
#include <openssl/ssl.h>
EVP_PKEY *ssl_getkey(void);
X509 *ssl_getcert(void);
X509 *ssl_getcert(EVP_PKEY *key);
SSL_CTX *get_ssl_ctx(void);
void init_ssl(void);
#endif
void * basic_test_setup(const struct testcase_t *testcase);
int basic_test_cleanup(const struct testcase_t *testcase, void *ptr);
#ifdef __cplusplus
}
#endif

View File

@ -1,4 +1,5 @@
/* $NetBSD: regress_buffer.c,v 1.6 2017/01/31 23:17:40 christos Exp $ */
/* $NetBSD: regress_buffer.c,v 1.7 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu>
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
@ -34,7 +35,7 @@
#include "event2/event-config.h"
#include <sys/cdefs.h>
__RCSID("$NetBSD: regress_buffer.c,v 1.6 2017/01/31 23:17:40 christos Exp $");
__RCSID("$NetBSD: regress_buffer.c,v 1.7 2021/04/07 03:36:48 christos Exp $");
#include <sys/types.h>
#include <sys/stat.h>
@ -66,6 +67,8 @@ __RCSID("$NetBSD: regress_buffer.c,v 1.6 2017/01/31 23:17:40 christos Exp $");
#include "regress.h"
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
/* Validates that an evbuffer is good. Returns false if it isn't, true if it
* is*/
static int
@ -297,33 +300,39 @@ no_cleanup(const void *data, size_t datalen, void *extra)
static void
test_evbuffer_remove_buffer_with_empty(void *ptr)
{
struct evbuffer *src = evbuffer_new();
struct evbuffer *dst = evbuffer_new();
char buf[2];
struct evbuffer *src = evbuffer_new();
struct evbuffer *dst = evbuffer_new();
char buf[2] = { 'A', 'A' };
evbuffer_validate(src);
evbuffer_validate(dst);
evbuffer_validate(src);
evbuffer_validate(dst);
/* setup the buffers */
/* we need more data in src than we will move later */
evbuffer_add_reference(src, buf, sizeof(buf), no_cleanup, NULL);
evbuffer_add_reference(src, buf, sizeof(buf), no_cleanup, NULL);
/* we need one buffer in dst and one empty buffer at the end */
evbuffer_add(dst, buf, sizeof(buf));
evbuffer_add_reference(dst, buf, 0, no_cleanup, NULL);
/* setup the buffers */
/* we need more data in src than we will move later */
evbuffer_add_reference(src, buf, sizeof(buf), no_cleanup, NULL);
evbuffer_add_reference(src, buf, sizeof(buf), no_cleanup, NULL);
/* we need one buffer in dst and one empty buffer at the end */
evbuffer_add(dst, buf, sizeof(buf));
evbuffer_add_reference(dst, buf, 0, no_cleanup, NULL);
evbuffer_validate(src);
evbuffer_validate(dst);
evbuffer_validate(src);
evbuffer_validate(dst);
/* move three bytes over */
evbuffer_remove_buffer(src, dst, 3);
tt_mem_op(evbuffer_pullup(src, -1), ==, "AAAA", 4);
tt_mem_op(evbuffer_pullup(dst, -1), ==, "AA", 2);
evbuffer_validate(src);
evbuffer_validate(dst);
/* move three bytes over */
evbuffer_remove_buffer(src, dst, 3);
end:
evbuffer_free(src);
evbuffer_free(dst);
evbuffer_validate(src);
evbuffer_validate(dst);
tt_mem_op(evbuffer_pullup(src, -1), ==, "A", 1);
tt_mem_op(evbuffer_pullup(dst, -1), ==, "AAAAA", 5);
end:
evbuffer_free(src);
evbuffer_free(dst);
}
static void
@ -353,6 +362,9 @@ test_evbuffer_remove_buffer_with_empty2(void *ptr)
evbuffer_validate(src);
evbuffer_validate(dst);
tt_mem_op(evbuffer_pullup(src, -1), ==, "foofoofoo", 9);
tt_mem_op(evbuffer_pullup(dst, -1), ==, "foofoofoo", 9);
evbuffer_remove_buffer(src, dst, 8);
evbuffer_validate(src);
@ -361,6 +373,9 @@ test_evbuffer_remove_buffer_with_empty2(void *ptr)
tt_int_op(evbuffer_get_length(src), ==, 1);
tt_int_op(evbuffer_get_length(dst), ==, 17);
tt_mem_op(evbuffer_pullup(src, -1), ==, "o", 1);
tt_mem_op(evbuffer_pullup(dst, -1), ==, "foofoofoofoofoofo", 17);
end:
evbuffer_free(src);
evbuffer_free(dst);
@ -394,6 +409,9 @@ test_evbuffer_remove_buffer_with_empty3(void *ptr)
evbuffer_validate(src);
evbuffer_validate(dst);
tt_mem_op(evbuffer_pullup(src, -1), ==, "foofoo", 6);
tt_mem_op(evbuffer_pullup(dst, -1), ==, "foofoo", 6);
evbuffer_remove_buffer(src, dst, 5);
evbuffer_validate(src);
@ -402,12 +420,128 @@ test_evbuffer_remove_buffer_with_empty3(void *ptr)
tt_int_op(evbuffer_get_length(src), ==, 1);
tt_int_op(evbuffer_get_length(dst), ==, 11);
tt_mem_op(evbuffer_pullup(src, -1), ==, "o", 1);
tt_mem_op(evbuffer_pullup(dst, -1), ==, "foofoofoofo", 11);
end:
evbuffer_free(src);
evbuffer_free(dst);
evbuffer_free(buf);
}
static void
test_evbuffer_pullup_with_empty(void *ptr)
{
struct evbuffer *buf = NULL;
buf = evbuffer_new();
evbuffer_add(buf, "foo", 3);
evbuffer_add_reference(buf, NULL, 0, NULL, NULL);
evbuffer_validate(buf);
tt_int_op(evbuffer_get_length(buf), ==, 3);
tt_mem_op(evbuffer_pullup(buf, -1), ==, "foo", 3);
evbuffer_free(buf);
buf = evbuffer_new();
evbuffer_validate(buf);
tt_int_op(evbuffer_get_length(buf), ==, 0);
tt_int_op(evbuffer_pullup(buf, -1), ==, NULL);
evbuffer_free(buf);
buf = evbuffer_new();
evbuffer_add(buf, "foo", 3);
evbuffer_add_reference(buf, NULL, 0, NULL, NULL);
evbuffer_validate(buf);
tt_mem_op(evbuffer_pullup(buf, 3), ==, "foo", 3);
end:
if (buf)
evbuffer_free(buf);
}
static void
test_evbuffer_remove_buffer_with_empty_front(void *ptr)
{
struct evbuffer *buf1 = NULL, *buf2 = NULL;
buf1 = evbuffer_new();
tt_assert(buf1);
buf2 = evbuffer_new();
tt_assert(buf2);
tt_int_op(evbuffer_add_reference(buf1, "foo", 3, NULL, NULL), ==, 0);
tt_int_op(evbuffer_prepend(buf1, "", 0), ==, 0);
tt_int_op(evbuffer_remove_buffer(buf1, buf2, 1), ==, 1);
tt_int_op(evbuffer_add(buf1, "bar", 3), ==, 0);
tt_mem_op(evbuffer_pullup(buf1, -1), ==, "oobar", 5);
evbuffer_validate(buf1);
evbuffer_validate(buf2);
end:
if (buf1)
evbuffer_free(buf1);
if (buf2)
evbuffer_free(buf2);
}
static void
test_evbuffer_remove_buffer_adjust_last_with_datap_with_empty(void *ptr)
{
struct evbuffer *buf1 = NULL, *buf2 = NULL;
buf1 = evbuffer_new();
tt_assert(buf1);
buf2 = evbuffer_new();
tt_assert(buf2);
tt_int_op(evbuffer_add(buf1, "aaaaaa", 6), ==, 0);
// buf1: aaaaaab
// buf2:
{
struct evbuffer_iovec iovecs[2];
/** we want two chains, to leave one chain empty */
tt_int_op(evbuffer_reserve_space(buf1, 971, iovecs, 2), ==, 2);
tt_int_op(iovecs[0].iov_len, >=, 1);
tt_int_op(iovecs[1].iov_len, >=, 1);
tt_assert(*(char *)(iovecs[0].iov_base) = 'b');
tt_assert(iovecs[0].iov_len = 1);
tt_int_op(evbuffer_commit_space(buf1, iovecs, 1), ==, 0);
}
// buf1: aaaaaab
// buf2: dddcc
tt_int_op(evbuffer_add(buf2, "cc", 2), ==, 0);
tt_int_op(evbuffer_prepend(buf2, "ddd", 3), ==, 0);
// buf1:
// buf2: aaaaaabdddcc
tt_int_op(evbuffer_prepend_buffer(buf2, buf1), ==, 0);
// buf1: aaaaaabdddcc
// buf2:
tt_int_op(evbuffer_add_buffer(buf1, buf2), ==, 0);
// buf1: c
// buf2: aaaaaabdddc
tt_int_op(evbuffer_remove_buffer(buf1, buf2, 11), ==, 11);
// This fails today, we observe "aaaaaabcddd" instead!
tt_mem_op(evbuffer_pullup(buf2, -1), ==, "aaaaaabdddc", 11);
evbuffer_validate(buf1);
evbuffer_validate(buf2);
end:
if (buf1)
evbuffer_free(buf1);
if (buf2)
evbuffer_free(buf2);
}
static void
test_evbuffer_add_buffer_with_empty(void *ptr)
{
@ -637,6 +771,63 @@ end:
evbuffer_free(buf);
}
static void
test_evbuffer_reserve_with_empty(void *ptr)
{
struct evbuffer *buf;
struct evbuffer_iovec v[2];
tt_assert(buf = evbuffer_new());
evbuffer_add(buf, "a", 1);
tt_int_op(evbuffer_reserve_space(buf, 1<<12, v, 2), ==, 2);
v[0].iov_len = 1;
*(char *)v[0].iov_base = 'b';
tt_int_op(evbuffer_commit_space(buf, v, 1), ==, 0);
evbuffer_add(buf, "c", 1);
tt_mem_op(evbuffer_pullup(buf, -1), ==, "abc", 2);
evbuffer_validate(buf);
end:
if (buf)
evbuffer_free(buf);
}
/* regression for evbuffer_expand_fast_() with invalid last_with_datap that has
* been left after evbuffer_prepend() with empty chain in it */
static void
test_evbuffer_reserve_invalid_last_with_datap(void *ptr)
{
struct evbuffer *buf = NULL;
struct evbuffer_iovec vec[2];
const int nvec = ARRAY_SIZE(vec);
int i, avec;
buf = evbuffer_new();
tt_assert(buf);
/* prepend with an empty chain */
evbuffer_add_reference(buf, "", 0, NULL, NULL);
evbuffer_prepend(buf, "foo", 3);
/* after invalid last_with_datap will create new chain */
evbuffer_add(buf, "", 0);
/* we need to create at least 2 "used" (in evbuffer_expand_fast_()) chains */
tt_int_op(avec = evbuffer_reserve_space(buf, 1<<12, vec, nvec), >=, 1);
for (i = 0; i < avec; ++i)
vec[i].iov_len = 0;
tt_int_op(evbuffer_commit_space(buf, vec, avec), ==, 0);
/* and an actual problem, that triggers an assert(chain == buf->first) in
* evbuffer_expand_fast_() */
tt_int_op(evbuffer_reserve_space(buf, 1<<13, vec, nvec), >=, 1);
evbuffer_validate(buf);
end:
if (buf)
evbuffer_free(buf);
}
static void
test_evbuffer_expand(void *ptr)
{
@ -1799,12 +1990,12 @@ test_evbuffer_callbacks(void *ptr)
tt_assert(cb1 != NULL);
cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2);
tt_assert(cb2 != NULL);
evbuffer_setcb(buf, self_draining_callback, NULL);
tt_int_op(evbuffer_setcb(buf, self_draining_callback, NULL), ==, 0);
evbuffer_add_printf(buf, "This should get drained right away.");
tt_uint_op(evbuffer_get_length(buf), ==, 0);
tt_uint_op(evbuffer_get_length(buf_out1), ==, 0);
tt_uint_op(evbuffer_get_length(buf_out2), ==, 0);
evbuffer_setcb(buf, NULL, NULL);
tt_int_op(evbuffer_setcb(buf, NULL, NULL), ==, 0);
evbuffer_add_printf(buf, "This will not.");
tt_str_op((const char *) evbuffer_pullup(buf, -1), ==, "This will not.");
evbuffer_validate(buf);
@ -1830,6 +2021,14 @@ test_evbuffer_callbacks(void *ptr)
"0->15; 15->11; 11->0; ");
#endif
/* the next call to readline should fail */
#ifndef EVENT__DISABLE_MM_REPLACEMENT
event_set_mem_functions(failing_malloc, realloc, free);
tt_int_op(evbuffer_setcb(buf, self_draining_callback, NULL), ==, -1);
evbuffer_validate(buf);
event_set_mem_functions(malloc, realloc, free);
#endif
end:
if (buf)
evbuffer_free(buf);
@ -2120,6 +2319,58 @@ end:
}
static void
test_evbuffer_empty_reference_prepend(void *ptr)
{
struct evbuffer *buf = NULL;
buf = evbuffer_new();
tt_assert(buf);
/** empty chain could leave invalid last_with_datap */
evbuffer_add_reference(buf, "", 0, NULL, NULL);
evbuffer_validate(buf);
evbuffer_prepend(buf, "foo", 3);
evbuffer_validate(buf);
tt_assert(!strncmp((char *)evbuffer_pullup(buf, -1), "foo", 3));
evbuffer_validate(buf);
end:
if (buf)
evbuffer_free(buf);
}
static void
test_evbuffer_empty_reference_prepend_buffer(void *ptr)
{
struct evbuffer *buf1 = NULL, *buf2 = NULL;
buf1 = evbuffer_new();
tt_assert(buf1);
buf2 = evbuffer_new();
tt_assert(buf2);
/** empty chain could leave invalid last_with_datap */
evbuffer_add_reference(buf1, "", 0, NULL, NULL);
evbuffer_validate(buf1);
evbuffer_add(buf2, "foo", 3);
evbuffer_validate(buf2);
evbuffer_prepend_buffer(buf2, buf1);
evbuffer_validate(buf2);
tt_assert(!strncmp((char *)evbuffer_pullup(buf2, -1), "foo", 3));
evbuffer_validate(buf2);
tt_assert(evbuffer_pullup(buf1, -1) == NULL);
evbuffer_validate(buf2);
end:
if (buf1)
evbuffer_free(buf1);
if (buf2)
evbuffer_free(buf2);
}
static void
test_evbuffer_peek_first_gt(void *info)
{
@ -2277,28 +2528,37 @@ end:
static void
test_evbuffer_freeze(void *ptr)
{
struct evbuffer *buf = NULL, *tmp_buf=NULL;
struct basic_test_data *testdata = ptr;
evutil_socket_t *xpair = testdata->pair;
struct evbuffer *buf = NULL, *buf_two = NULL, *tmp_buf = NULL;
const char string[] = /* Year's End, Richard Wilbur */
"I've known the wind by water banks to shake\n"
"The late leaves down, which frozen where they fell\n"
"And held in ice as dancers in a spell\n"
"Fluttered all winter long into a lake...";
const int start = !strcmp(ptr, "start");
const int start = !strcmp(testdata->setup_data, "start");
const char tmpfilecontent[] = "file_freeze_test_file";
char *cp;
char charbuf[128];
char *tmpfilename = NULL;
int fd = -1;
int r;
size_t orig_length;
size_t orig_length, len;
struct evbuffer_iovec v[1];
if (!start)
tt_str_op(ptr, ==, "end");
tt_str_op(testdata->setup_data, ==, "end");
buf = evbuffer_new();
buf_two = evbuffer_new();
tmp_buf = evbuffer_new();
tt_assert(tmp_buf);
evbuffer_add(buf, string, strlen(string));
evbuffer_add(buf_two, "abc", 3);
evbuffer_add(tmp_buf, "xyz", 3);
evbuffer_freeze(buf, start); /* Freeze the start or the end.*/
evbuffer_freeze(buf_two, start);
#define FREEZE_EQ(a, startcase, endcase) \
do { \
@ -2327,7 +2587,22 @@ test_evbuffer_freeze(void *ptr)
FREEZE_EQ(r, 0, -1);
r = evbuffer_add_printf(buf, "Hello %s", "world");
FREEZE_EQ(r, 11, -1);
/* TODO: test add_buffer, add_file, read */
r = evbuffer_add_buffer(buf, tmp_buf);
FREEZE_EQ(r, 0, -1);
len = strlen(tmpfilecontent);
fd = regress_make_tmpfile(tmpfilecontent, len, &tmpfilename);
r = evbuffer_add_file(buf, fd, 0, len);
FREEZE_EQ(r, 0, -1);
if (start)
evbuffer_add(tmp_buf, "xyz", 3);
tt_assert(evbuffer_get_length(tmp_buf));
len = evbuffer_get_length(tmp_buf);
evbuffer_write(tmp_buf, xpair[0]);
r = evbuffer_read(buf, xpair[1], -1);
FREEZE_EQ(r, len, -1);
if (!start)
tt_int_op(orig_length, ==, evbuffer_get_length(buf));
@ -2345,7 +2620,24 @@ test_evbuffer_freeze(void *ptr)
FREEZE_EQ(cp==NULL, 1, 0);
if (cp)
free(cp);
/* TODO: Test remove_buffer, add_buffer, write, prepend_buffer */
evbuffer_add(tmp_buf, "xyz", 3);
tt_assert(evbuffer_get_length(tmp_buf));
r = evbuffer_remove_buffer(buf, tmp_buf, 3);
FREEZE_EQ(r, -1, 3);
r = evbuffer_drain(buf, 3);
FREEZE_EQ(r, -1, 0);
r = evbuffer_prepend_buffer(buf, tmp_buf);
FREEZE_EQ(r, -1, 0);
len = evbuffer_get_length(buf);
r = evbuffer_write(buf, xpair[0]);
evbuffer_read(tmp_buf, xpair[1], -1);
FREEZE_EQ(r, -1, len);
len = evbuffer_get_length(buf_two);
r = evbuffer_write_atmost(buf_two, xpair[0], -1);
evbuffer_read(tmp_buf, xpair[1], -1);
FREEZE_EQ(r, -1, len);
if (start)
tt_int_op(orig_length, ==, evbuffer_get_length(buf));
@ -2354,8 +2646,16 @@ end:
if (buf)
evbuffer_free(buf);
if (buf_two)
evbuffer_free(buf_two);
if (tmp_buf)
evbuffer_free(tmp_buf);
if (tmpfilename) {
unlink(tmpfilename);
free(tmpfilename);
}
}
static void
@ -2507,12 +2807,17 @@ struct testcase_t evbuffer_testcases[] = {
{ "remove_buffer_with_empty", test_evbuffer_remove_buffer_with_empty, 0, NULL, NULL },
{ "remove_buffer_with_empty2", test_evbuffer_remove_buffer_with_empty2, 0, NULL, NULL },
{ "remove_buffer_with_empty3", test_evbuffer_remove_buffer_with_empty3, 0, NULL, NULL },
{ "remove_buffer_with_empty_front", test_evbuffer_remove_buffer_with_empty_front, 0, NULL, NULL },
{ "remove_buffer_adjust_last_with_datap_with_empty",
test_evbuffer_remove_buffer_adjust_last_with_datap_with_empty, 0, NULL, NULL },
{ "add_buffer_with_empty", test_evbuffer_add_buffer_with_empty, 0, NULL, NULL },
{ "add_buffer_with_empty2", test_evbuffer_add_buffer_with_empty2, 0, NULL, NULL },
{ "reserve2", test_evbuffer_reserve2, 0, NULL, NULL },
{ "reserve_many", test_evbuffer_reserve_many, 0, NULL, NULL },
{ "reserve_many2", test_evbuffer_reserve_many, 0, &nil_setup, __UNCONST("add") },
{ "reserve_many3", test_evbuffer_reserve_many, 0, &nil_setup, __UNCONST("fill") },
{ "reserve_with_empty", test_evbuffer_reserve_with_empty, 0, NULL, NULL },
{ "reserve_invalid_last_with_datap", test_evbuffer_reserve_invalid_last_with_datap, TT_FORK, NULL, NULL },
{ "expand", test_evbuffer_expand, 0, NULL, NULL },
{ "expand_overflow", test_evbuffer_expand_overflow, 0, NULL, NULL },
{ "add1", test_evbuffer_add1, 0, NULL, NULL },
@ -2530,13 +2835,16 @@ struct testcase_t evbuffer_testcases[] = {
{ "multicast", test_evbuffer_multicast, 0, NULL, NULL },
{ "multicast_drain", test_evbuffer_multicast_drain, 0, NULL, NULL },
{ "prepend", test_evbuffer_prepend, TT_FORK, NULL, NULL },
{ "empty_reference_prepend", test_evbuffer_empty_reference_prepend, TT_FORK, NULL, NULL },
{ "empty_reference_prepend_buffer", test_evbuffer_empty_reference_prepend_buffer, TT_FORK, NULL, NULL },
{ "peek", test_evbuffer_peek, 0, NULL, NULL },
{ "peek_first_gt", test_evbuffer_peek_first_gt, 0, NULL, NULL },
{ "freeze_start", test_evbuffer_freeze, 0, &nil_setup, __UNCONST("start") },
{ "freeze_end", test_evbuffer_freeze, 0, &nil_setup, __UNCONST("end") },
{ "freeze_start", test_evbuffer_freeze, TT_NEED_SOCKETPAIR, &basic_setup, __UNCONST("start") },
{ "freeze_end", test_evbuffer_freeze, TT_NEED_SOCKETPAIR, &basic_setup, __UNCONST("end") },
{ "add_iovec", test_evbuffer_add_iovec, 0, NULL, NULL},
{ "copyout", test_evbuffer_copyout, 0, NULL, NULL},
{ "file_segment_add_cleanup_cb", test_evbuffer_file_segment_add_cleanup_cb, 0, NULL, NULL },
{ "pullup_with_empty", test_evbuffer_pullup_with_empty, 0, NULL, NULL },
#define ADDFILE_TEST(name, parameters) \
{ name, test_evbuffer_add_file, TT_FORK|TT_NEED_BASE, \

View File

@ -1,4 +1,5 @@
/* $NetBSD: regress_bufferevent.c,v 1.3 2017/01/31 23:17:40 christos Exp $ */
/* $NetBSD: regress_bufferevent.c,v 1.4 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu>
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
@ -30,6 +31,19 @@
/* The old tests here need assertions to work. */
#undef NDEBUG
/**
* - clang supports __has_feature
* - gcc supports __SANITIZE_ADDRESS__
*
* Let's set __SANITIZE_ADDRESS__ if __has_feature(address_sanitizer)
*/
#ifndef __has_feature
#define __has_feature(x) 0
#endif
#if !defined(__SANITIZE_ADDRESS__) && __has_feature(address_sanitizer)
#define __SANITIZE_ADDRESS__
#endif
#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
@ -37,7 +51,7 @@
#include "event2/event-config.h"
#include <sys/cdefs.h>
__RCSID("$NetBSD: regress_bufferevent.c,v 1.3 2017/01/31 23:17:40 christos Exp $");
__RCSID("$NetBSD: regress_bufferevent.c,v 1.4 2021/04/07 03:36:48 christos Exp $");
#include <sys/types.h>
#include <sys/stat.h>
@ -66,8 +80,6 @@ __RCSID("$NetBSD: regress_bufferevent.c,v 1.3 2017/01/31 23:17:40 christos Exp $
#endif
#include "event2/event-config.h"
#include <sys/cdefs.h>
__RCSID("$NetBSD: regress_bufferevent.c,v 1.3 2017/01/31 23:17:40 christos Exp $");
#include "event2/event.h"
#include "event2/event_struct.h"
#include "event2/event_compat.h"
@ -142,14 +154,14 @@ test_bufferevent_impl(int use_pair, int flush)
bev2 = xpair[1];
bufferevent_setcb(bev1, readcb, writecb, errorcb, bev1);
bufferevent_setcb(bev2, readcb, writecb, errorcb, NULL);
tt_int_op(bufferevent_getfd(bev1), ==, -1);
tt_fd_op(bufferevent_getfd(bev1), ==, EVUTIL_INVALID_SOCKET);
tt_ptr_op(bufferevent_get_underlying(bev1), ==, NULL);
tt_ptr_op(bufferevent_pair_get_partner(bev1), ==, bev2);
tt_ptr_op(bufferevent_pair_get_partner(bev2), ==, bev1);
} else {
bev1 = bufferevent_new(pair[0], readcb, writecb, errorcb, NULL);
bev2 = bufferevent_new(pair[1], readcb, writecb, errorcb, NULL);
tt_int_op(bufferevent_getfd(bev1), ==, pair[0]);
tt_fd_op(bufferevent_getfd(bev1), ==, pair[0]);
tt_ptr_op(bufferevent_get_underlying(bev1), ==, NULL);
tt_ptr_op(bufferevent_pair_get_partner(bev1), ==, NULL);
tt_ptr_op(bufferevent_pair_get_partner(bev2), ==, NULL);
@ -208,7 +220,7 @@ static void test_bufferevent_pair_flush_normal(void) { test_bufferevent_impl(1,
static void test_bufferevent_pair_flush_flush(void) { test_bufferevent_impl(1, BEV_FLUSH); }
static void test_bufferevent_pair_flush_finished(void) { test_bufferevent_impl(1, BEV_FINISHED); }
#if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED)
#if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED) && !defined(__SANITIZE_ADDRESS__)
/**
* Trace lock/unlock/alloc/free for locks.
* (More heavier then evthread_debug*)
@ -574,8 +586,8 @@ test_bufferevent_filters_impl(int use_pair, int disable)
tt_ptr_op(bufferevent_get_underlying(bev1), ==, bev1_base);
tt_ptr_op(bufferevent_get_underlying(bev2), ==, bev2_base);
tt_int_op(bufferevent_getfd(bev1), ==, -1);
tt_int_op(bufferevent_getfd(bev2), ==, -1);
tt_fd_op(bufferevent_getfd(bev1), ==, bufferevent_getfd(bev1_base));
tt_fd_op(bufferevent_getfd(bev2), ==, bufferevent_getfd(bev2_base));
bufferevent_disable(bev1, EV_READ);
bufferevent_enable(bev2, EV_READ);
@ -645,7 +657,7 @@ end:
;
}
static int
static evutil_socket_t
fake_listener_create(struct sockaddr_in *localhost)
{
struct sockaddr *sa = (struct sockaddr *)localhost;
@ -792,16 +804,29 @@ end:
bufferevent_free(bev2);
}
static void
close_socket_cb(evutil_socket_t fd, short what, void *arg)
{
evutil_socket_t *fdp = arg;
if (*fdp >= 0) {
evutil_closesocket(*fdp);
*fdp = -1;
}
}
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 event close_listener_event;
struct bufferevent *bev = NULL;
struct evconnlistener *lev = NULL;
struct sockaddr_in localhost;
struct timeval close_timeout = { 0, 300000 };
ev_socklen_t slen = sizeof(localhost);
evutil_socket_t fake_listener = -1;
int r;
fake_listener = fake_listener_create(&localhost);
@ -814,10 +839,22 @@ test_bufferevent_connect_fail_eventcb(void *arg)
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);
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);
tt_int_op(n_events_invoked, ==, 0);
tt_int_op(n_reads_invoked, ==, 0);
/* Close the listener socket after a delay. This should trigger
"connection refused" on some other platforms, including OSX. */
evtimer_assign(&close_listener_event, data->base, close_socket_cb,
&fake_listener);
event_add(&close_listener_event, &close_timeout);
event_base_dispatch(data->base);
tt_int_op(n_events_invoked, ==, 1);
tt_int_op(n_reads_invoked, ==, 0);
@ -851,16 +888,6 @@ want_fail_eventcb(struct bufferevent *bev, short what, void *ctx)
event_base_loopexit(base, NULL);
}
static void
close_socket_cb(evutil_socket_t fd, short what, void *arg)
{
evutil_socket_t *fdp = arg;
if (*fdp >= 0) {
evutil_closesocket(*fdp);
*fdp = -1;
}
}
static void
test_bufferevent_connect_fail(void *arg)
{
@ -868,7 +895,7 @@ test_bufferevent_connect_fail(void *arg)
struct bufferevent *bev=NULL;
struct event close_listener_event;
int close_listener_event_added = 0;
struct timeval one_second = { 1, 0 };
struct timeval close_timeout = { 0, 300000 };
struct sockaddr_in localhost;
ev_socklen_t slen = sizeof(localhost);
evutil_socket_t fake_listener = -1;
@ -887,11 +914,11 @@ test_bufferevent_connect_fail(void *arg)
* detects the error immediately, which is not really wrong of it. */
tt_want(r == 0 || r == -1);
/* Close the listener socket after a second. This should trigger
/* Close the listener socket after a delay. This should trigger
"connection refused" on some other platforms, including OSX. */
evtimer_assign(&close_listener_event, data->base, close_socket_cb,
&fake_listener);
event_add(&close_listener_event, &one_second);
event_add(&close_listener_event, &close_timeout);
close_listener_event_added = 1;
event_base_dispatch(data->base);
@ -913,18 +940,24 @@ struct timeout_cb_result {
struct timeval read_timeout_at;
struct timeval write_timeout_at;
struct timeval last_wrote_at;
struct timeval last_read_at;
int n_read_timeouts;
int n_write_timeouts;
int total_calls;
};
static void
bev_timeout_read_cb(struct bufferevent *bev, void *arg)
{
struct timeout_cb_result *res = arg;
evutil_gettimeofday(&res->last_read_at, NULL);
}
static void
bev_timeout_write_cb(struct bufferevent *bev, void *arg)
{
struct timeout_cb_result *res = arg;
evutil_gettimeofday(&res->last_wrote_at, NULL);
}
static void
bev_timeout_event_cb(struct bufferevent *bev, short what, void *arg)
{
@ -952,7 +985,6 @@ test_bufferevent_timeouts(void *arg)
int use_pair = 0, use_filter = 0;
struct timeval tv_w, tv_r, started_at;
struct timeout_cb_result res1, res2;
char buf[1024];
memset(&res1, 0, sizeof(res1));
memset(&res2, 0, sizeof(res2));
@ -971,7 +1003,6 @@ test_bufferevent_timeouts(void *arg)
bev1 = bufferevent_socket_new(data->base, data->pair[0], 0);
bev2 = bufferevent_socket_new(data->base, data->pair[1], 0);
}
tt_assert(bev1);
tt_assert(bev2);
@ -995,30 +1026,14 @@ test_bufferevent_timeouts(void *arg)
tv_w.tv_sec = tv_r.tv_sec = 0;
tv_w.tv_usec = 100*1000;
tv_r.tv_usec = 150*1000;
bufferevent_setcb(bev1, NULL, bev_timeout_write_cb,
bufferevent_setcb(bev1, bev_timeout_read_cb, bev_timeout_write_cb,
bev_timeout_event_cb, &res1);
bufferevent_setwatermark(bev1, EV_WRITE, 1024*1024+10, 0);
bufferevent_set_timeouts(bev1, &tv_r, &tv_w);
if (use_pair) {
/* For a pair, the fact that the other side isn't reading
* makes the writer stall */
bufferevent_write(bev1, "ABCDEFG", 7);
} else {
/* For a real socket, the kernel's TCP buffers can eat a
* fair number of bytes; make sure that at some point we
* have some bytes that will stall. */
struct evbuffer *output = bufferevent_get_output(bev1);
int i;
memset(buf, 0xbb, sizeof(buf));
for (i=0;i<1024;++i) {
evbuffer_add_reference(output, buf, sizeof(buf),
NULL, NULL);
}
}
bufferevent_write(bev1, "ABCDEFG", 7);
bufferevent_enable(bev1, EV_READ|EV_WRITE);
/* bev2 has nothing to say, and isn't listening. */
bufferevent_setcb(bev2, NULL, bev_timeout_write_cb,
bufferevent_setcb(bev2, bev_timeout_read_cb, bev_timeout_write_cb,
bev_timeout_event_cb, &res2);
tv_w.tv_sec = tv_r.tv_sec = 0;
tv_w.tv_usec = 200*1000;
@ -1035,15 +1050,26 @@ test_bufferevent_timeouts(void *arg)
/* XXXX Test that actually reading or writing a little resets the
* timeouts. */
/* Each buf1 timeout happens, and happens only once. */
tt_want(res1.n_read_timeouts);
tt_want(res1.n_write_timeouts);
tt_want(res1.total_calls == 2);
tt_want(res1.n_read_timeouts == 1);
tt_want(res1.n_write_timeouts == 1);
tt_want(res2.total_calls == !(use_pair && !use_filter));
tt_want(res2.n_write_timeouts == !(use_pair && !use_filter));
tt_want(!res2.n_read_timeouts);
test_timeval_diff_eq(&started_at, &res1.read_timeout_at, 150);
test_timeval_diff_eq(&started_at, &res1.write_timeout_at, 100);
#define tt_assert_timeval_empty(tv) do { \
tt_int_op((tv).tv_sec, ==, 0); \
tt_int_op((tv).tv_usec, ==, 0); \
} while(0)
tt_assert_timeval_empty(res1.last_read_at);
tt_assert_timeval_empty(res2.last_read_at);
tt_assert_timeval_empty(res2.last_wrote_at);
tt_assert_timeval_empty(res2.last_wrote_at);
#undef tt_assert_timeval_empty
end:
if (bev1)
bufferevent_free(bev1);
@ -1342,9 +1368,9 @@ struct testcase_t bufferevent_testcases[] = {
LEGACY(bufferevent_pair_flush_normal, TT_ISOLATED),
LEGACY(bufferevent_pair_flush_flush, TT_ISOLATED),
LEGACY(bufferevent_pair_flush_finished, TT_ISOLATED),
#if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED)
#if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED) && !defined(__SANITIZE_ADDRESS__)
{ "bufferevent_pair_release_lock", test_bufferevent_pair_release_lock,
TT_FORK|TT_ISOLATED|TT_NEED_THREADS|TT_NEED_BASE|TT_LEGACY,
TT_FORK|TT_ISOLATED|TT_NEED_THREADS|TT_NEED_BASE|TT_LEGACY|TT_NO_LOGS,
&basic_setup, NULL },
#endif
LEGACY(bufferevent_watermarks, TT_ISOLATED),
@ -1368,7 +1394,7 @@ struct testcase_t bufferevent_testcases[] = {
{ "bufferevent_connect_fail", test_bufferevent_connect_fail,
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
{ "bufferevent_timeout", test_bufferevent_timeouts,
TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR, &basic_setup, __UNCONST("") },
TT_FORK|TT_NEED_BASE, &basic_setup, __UNCONST("") },
{ "bufferevent_timeout_pair", test_bufferevent_timeouts,
TT_FORK|TT_NEED_BASE, &basic_setup, __UNCONST("pair") },
{ "bufferevent_timeout_filter", test_bufferevent_timeouts,
@ -1411,38 +1437,35 @@ struct testcase_t bufferevent_testcases[] = {
END_OF_TESTCASES,
};
#define TT_IOCP (TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP)
#define TT_IOCP_LEGACY (TT_ISOLATED|TT_ENABLE_IOCP)
struct testcase_t bufferevent_iocp_testcases[] = {
LEGACY(bufferevent, TT_ISOLATED|TT_ENABLE_IOCP),
LEGACY(bufferevent, TT_IOCP_LEGACY),
LEGACY(bufferevent_flush_normal, TT_ISOLATED),
LEGACY(bufferevent_flush_flush, TT_ISOLATED),
LEGACY(bufferevent_flush_finished, TT_ISOLATED),
LEGACY(bufferevent_watermarks, TT_ISOLATED|TT_ENABLE_IOCP),
LEGACY(bufferevent_filters, TT_ISOLATED|TT_ENABLE_IOCP),
LEGACY(bufferevent_filters_disable, TT_ISOLATED|TT_ENABLE_IOCP),
LEGACY(bufferevent_watermarks, TT_IOCP_LEGACY),
LEGACY(bufferevent_filters, TT_IOCP_LEGACY),
LEGACY(bufferevent_filters_disable, TT_IOCP_LEGACY),
{ "bufferevent_connect", test_bufferevent_connect,
TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, __UNCONST("") },
TT_IOCP, &basic_setup, __UNCONST("") },
{ "bufferevent_connect_defer", test_bufferevent_connect,
TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, __UNCONST("defer") },
TT_IOCP, &basic_setup, __UNCONST("defer") },
{ "bufferevent_connect_lock", test_bufferevent_connect,
TT_FORK|TT_NEED_BASE|TT_NEED_THREADS|TT_ENABLE_IOCP, &basic_setup,
__UNCONST("lock") },
TT_IOCP, &basic_setup, __UNCONST("lock") },
{ "bufferevent_connect_lock_defer", test_bufferevent_connect,
TT_FORK|TT_NEED_BASE|TT_NEED_THREADS|TT_ENABLE_IOCP, &basic_setup,
__UNCONST("defer lock") },
TT_IOCP, &basic_setup, __UNCONST("defer lock") },
{ "bufferevent_connect_fail", test_bufferevent_connect_fail,
TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, NULL },
TT_IOCP, &basic_setup, NULL },
{ "bufferevent_connect_nonblocking", test_bufferevent_connect,
TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup,
__UNCONST("unset_connectex") },
TT_IOCP, &basic_setup, __UNCONST("unset_connectex") },
{ "bufferevent_connect_fail_eventcb_defer",
test_bufferevent_connect_fail_eventcb,
TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup,
(void*)BEV_OPT_DEFER_CALLBACKS },
TT_IOCP, &basic_setup, (void*)BEV_OPT_DEFER_CALLBACKS },
{ "bufferevent_connect_fail_eventcb",
test_bufferevent_connect_fail_eventcb,
TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, NULL },
test_bufferevent_connect_fail_eventcb, TT_IOCP, &basic_setup, NULL },
END_OF_TESTCASES,
};

View File

@ -1,4 +1,5 @@
/* $NetBSD: regress_dns.c,v 1.5 2017/01/31 23:17:40 christos Exp $ */
/* $NetBSD: regress_dns.c,v 1.6 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu>
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
@ -35,7 +36,7 @@
#include "event2/event-config.h"
#include <sys/cdefs.h>
__RCSID("$NetBSD: regress_dns.c,v 1.5 2017/01/31 23:17:40 christos Exp $");
__RCSID("$NetBSD: regress_dns.c,v 1.6 2021/04/07 03:36:48 christos Exp $");
#include <sys/types.h>
#include <sys/stat.h>
@ -62,6 +63,10 @@ __RCSID("$NetBSD: regress_dns.c,v 1.5 2017/01/31 23:17:40 christos Exp $");
#include <string.h>
#include <errno.h>
#ifdef EVENT__HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#include "event2/dns.h"
#include "event2/dns_compat.h"
#include "event2/dns_struct.h"
@ -71,9 +76,12 @@ __RCSID("$NetBSD: regress_dns.c,v 1.5 2017/01/31 23:17:40 christos Exp $");
#include "event2/util.h"
#include "event2/listener.h"
#include "event2/bufferevent.h"
#include <event2/thread.h>
#include "log-internal.h"
#include "evthread-internal.h"
#include "regress.h"
#include "regress_testutils.h"
#include "regress_thread.h"
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
@ -200,7 +208,7 @@ dns_resolve_reverse(void *ptr)
{
struct in_addr in;
struct event_base *base = event_base_new();
struct evdns_base *dns = evdns_base_new(base, 1/* init name servers */);
struct evdns_base *dns = evdns_base_new(base, EVDNS_BASE_INITIALIZE_NAMESERVERS);
struct evdns_request *req = NULL;
tt_assert(base);
@ -615,16 +623,8 @@ end:
if (dns)
evdns_base_free(dns, 0);
}
static void
dns_search_test(void *arg)
{
return dns_search_test_impl(arg, 0);
}
static void
dns_search_lower_test(void *arg)
{
return dns_search_test_impl(arg, 1);
}
static void dns_search_test(void *arg) { dns_search_test_impl(arg, 0); }
static void dns_search_lower_test(void *arg) { dns_search_test_impl(arg, 1); }
static int request_count = 0;
static struct evdns_request *current_req = NULL;
@ -1008,6 +1008,59 @@ end:
event_base_free(inactive_base);
}
static void
dns_initialize_nameservers_test(void *arg)
{
struct basic_test_data *data = arg;
struct event_base *base = data->base;
struct evdns_base *dns = NULL;
dns = evdns_base_new(base, 0);
tt_assert(dns);
tt_int_op(evdns_base_get_nameserver_addr(dns, 0, NULL, 0), ==, -1);
evdns_base_free(dns, 0);
dns = evdns_base_new(base, EVDNS_BASE_INITIALIZE_NAMESERVERS);
tt_assert(dns);
tt_int_op(evdns_base_get_nameserver_addr(dns, 0, NULL, 0), ==, sizeof(struct sockaddr));
end:
if (dns)
evdns_base_free(dns, 0);
}
#ifndef _WIN32
#define RESOLV_FILE "empty-resolv.conf"
static void
dns_nameservers_no_default_test(void *arg)
{
struct basic_test_data *data = arg;
struct event_base *base = data->base;
struct evdns_base *dns = NULL;
int ok = access(RESOLV_FILE, R_OK);
tt_assert(ok);
dns = evdns_base_new(base, 0);
tt_assert(dns);
tt_int_op(evdns_base_get_nameserver_addr(dns, 0, NULL, 0), ==, -1);
/* We cannot test
* EVDNS_BASE_INITIALIZE_NAMESERVERS|EVDNS_BASE_NAMESERVERS_NO_DEFAULT
* because we cannot mock "/etc/resolv.conf" (yet). */
evdns_base_resolv_conf_parse(dns,
DNS_OPTIONS_ALL|DNS_OPTION_NAMESERVERS_NO_DEFAULT, RESOLV_FILE);
tt_int_op(evdns_base_get_nameserver_addr(dns, 0, NULL, 0), ==, -1);
evdns_base_resolv_conf_parse(dns, DNS_OPTIONS_ALL, RESOLV_FILE);
tt_int_op(evdns_base_get_nameserver_addr(dns, 0, NULL, 0), ==, sizeof(struct sockaddr));
end:
if (dns)
evdns_base_free(dns, 0);
}
#endif
/* === Test for bufferevent_socket_connect_hostname */
static int total_connected_or_failed = 0;
@ -1024,7 +1077,7 @@ be_getaddrinfo_server_cb(struct evdns_server_request *req, void *data)
int added_any=0;
++*n_got_p;
for (i=0;i<req->nquestions;++i) {
for (i = 0; i < req->nquestions; ++i) {
const int qtype = req->questions[i]->type;
const int qclass = req->questions[i]->dns_question_class;
const char *qname = req->questions[i]->name;
@ -1168,27 +1221,36 @@ static void
be_connect_hostname_event_cb(struct bufferevent *bev, short what, void *ctx)
{
struct be_conn_hostname_result *got = ctx;
if (!got->what) {
TT_BLATHER(("Got a bufferevent event %d", what));
got->what = what;
if ((what & BEV_EVENT_CONNECTED) || (what & BEV_EVENT_ERROR)) {
int r;
if ((r = bufferevent_socket_get_dns_error(bev))) {
got->dnserr = r;
TT_BLATHER(("DNS error %d: %s", r,
evutil_gai_strerror(r)));
} ++total_connected_or_failed;
TT_BLATHER(("Got %d connections or errors.", total_connected_or_failed));
if (total_n_accepted >= 3 && total_connected_or_failed >= 5)
event_base_loopexit(be_connect_hostname_base,
NULL);
}
} else {
if (got->what) {
TT_FAIL(("Two events on one bufferevent. %d,%d",
got->what, (int)what));
}
TT_BLATHER(("Got a bufferevent event %d", what));
got->what = what;
if ((what & BEV_EVENT_CONNECTED) || (what & BEV_EVENT_ERROR)) {
int expected = 3;
int r = bufferevent_socket_get_dns_error(bev);
if (r) {
got->dnserr = r;
TT_BLATHER(("DNS error %d: %s", r,
evutil_gai_strerror(r)));
}
++total_connected_or_failed;
TT_BLATHER(("Got %d connections or errors.", total_connected_or_failed));
/** emfile test */
if (errno == EMFILE) {
expected = 0;
}
if (total_n_accepted >= expected && total_connected_or_failed >= 5)
event_base_loopexit(be_connect_hostname_base,
NULL);
}
}
static void
@ -1196,10 +1258,9 @@ test_bufferevent_connect_hostname(void *arg)
{
struct basic_test_data *data = arg;
struct evconnlistener *listener = NULL;
struct bufferevent *be1=NULL, *be2=NULL, *be3=NULL, *be4=NULL, *be5=NULL;
struct be_conn_hostname_result be1_outcome={0,0}, be2_outcome={0,0},
be3_outcome={0,0}, be4_outcome={0,0}, be5_outcome={0,0};
int expect_err5;
struct bufferevent *be[5];
struct be_conn_hostname_result be_outcome[ARRAY_SIZE(be)];
int expect_err;
struct evdns_base *dns=NULL;
struct evdns_server_port *port=NULL;
struct sockaddr_in sin;
@ -1207,6 +1268,9 @@ test_bufferevent_connect_hostname(void *arg)
ev_uint16_t dns_port=0;
int n_accept=0, n_dns=0;
char buf[128];
int emfile = data->setup_data && !strcmp(data->setup_data, "emfile");
unsigned i;
int ret;
be_connect_hostname_base = data->base;
@ -1233,32 +1297,34 @@ test_bufferevent_connect_hostname(void *arg)
evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)dns_port);
evdns_base_nameserver_ip_add(dns, buf);
#ifdef EVENT__HAVE_SETRLIMIT
if (emfile) {
int fd = socket(AF_INET, SOCK_STREAM, 0);
struct rlimit file = { fd, fd };
tt_int_op(fd, >=, 0);
tt_assert(!close(fd));
tt_assert(!setrlimit(RLIMIT_NOFILE, &file));
}
#endif
/* Now, finally, at long last, launch the bufferevents. One should do
* a failing lookup IP, one should do a successful lookup by IP,
* and one should do a successful lookup by hostname. */
be1 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE);
be2 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE);
be3 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE);
be4 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE);
be5 = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(be1, NULL, NULL, be_connect_hostname_event_cb,
&be1_outcome);
bufferevent_setcb(be2, NULL, NULL, be_connect_hostname_event_cb,
&be2_outcome);
bufferevent_setcb(be3, NULL, NULL, be_connect_hostname_event_cb,
&be3_outcome);
bufferevent_setcb(be4, NULL, NULL, be_connect_hostname_event_cb,
&be4_outcome);
bufferevent_setcb(be5, NULL, NULL, be_connect_hostname_event_cb,
&be5_outcome);
for (i = 0; i < ARRAY_SIZE(be); ++i) {
memset(&be_outcome[i], 0, sizeof(be_outcome[i]));
be[i] = bufferevent_socket_new(data->base, -1, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(be[i], NULL, NULL, be_connect_hostname_event_cb,
&be_outcome[i]);
}
/* Use the blocking resolver. This one will fail if your resolver
* can't resolve localhost to 127.0.0.1 */
tt_assert(!bufferevent_socket_connect_hostname(be4, NULL, AF_INET,
tt_assert(!bufferevent_socket_connect_hostname(be[3], NULL, AF_INET,
"localhost", listener_port));
/* Use the blocking resolver with a nonexistent hostname. */
tt_assert(!bufferevent_socket_connect_hostname(be5, NULL, AF_INET,
tt_assert(!bufferevent_socket_connect_hostname(be[4], NULL, AF_INET,
"nonesuch.nowhere.example.com", 80));
{
/* The blocking resolver will use the system nameserver, which
@ -1269,35 +1335,53 @@ test_bufferevent_connect_hostname(void *arg)
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
expect_err5 = evutil_getaddrinfo(
expect_err = evutil_getaddrinfo(
"nonesuch.nowhere.example.com", "80", &hints, &ai);
}
/* Launch an async resolve that will fail. */
tt_assert(!bufferevent_socket_connect_hostname(be1, dns, AF_INET,
tt_assert(!bufferevent_socket_connect_hostname(be[0], dns, AF_INET,
"nosuchplace.example.com", listener_port));
/* Connect to the IP without resolving. */
tt_assert(!bufferevent_socket_connect_hostname(be2, dns, AF_INET,
tt_assert(!bufferevent_socket_connect_hostname(be[1], dns, AF_INET,
"127.0.0.1", listener_port));
/* Launch an async resolve that will succeed. */
tt_assert(!bufferevent_socket_connect_hostname(be3, dns, AF_INET,
tt_assert(!bufferevent_socket_connect_hostname(be[2], dns, AF_INET,
"nobodaddy.example.com", listener_port));
event_base_dispatch(data->base);
tt_int_op(be1_outcome.what, ==, BEV_EVENT_ERROR);
tt_int_op(be1_outcome.dnserr, ==, EVUTIL_EAI_NONAME);
tt_int_op(be2_outcome.what, ==, BEV_EVENT_CONNECTED);
tt_int_op(be2_outcome.dnserr, ==, 0);
tt_int_op(be3_outcome.what, ==, BEV_EVENT_CONNECTED);
tt_int_op(be3_outcome.dnserr, ==, 0);
tt_int_op(be4_outcome.what, ==, BEV_EVENT_CONNECTED);
tt_int_op(be4_outcome.dnserr, ==, 0);
if (expect_err5) {
tt_int_op(be5_outcome.what, ==, BEV_EVENT_ERROR);
tt_int_op(be5_outcome.dnserr, ==, expect_err5);
ret = event_base_dispatch(data->base);
#ifdef __sun__
if (emfile && !strcmp(event_base_get_method(data->base), "devpoll")) {
tt_int_op(ret, ==, -1);
/** DP_POLL failed */
tt_skip();
} else
#endif
{
tt_int_op(ret, ==, 0);
}
tt_int_op(n_accept, ==, 3);
tt_int_op(be_outcome[0].what, ==, BEV_EVENT_ERROR);
tt_int_op(be_outcome[0].dnserr, ==, EVUTIL_EAI_NONAME);
tt_int_op(be_outcome[1].what, ==, !emfile ? BEV_EVENT_CONNECTED : BEV_EVENT_ERROR);
tt_int_op(be_outcome[1].dnserr, ==, 0);
tt_int_op(be_outcome[2].what, ==, !emfile ? BEV_EVENT_CONNECTED : BEV_EVENT_ERROR);
tt_int_op(be_outcome[2].dnserr, ==, 0);
tt_int_op(be_outcome[3].what, ==, !emfile ? BEV_EVENT_CONNECTED : BEV_EVENT_ERROR);
if (!emfile) {
tt_int_op(be_outcome[3].dnserr, ==, 0);
} else {
tt_int_op(be_outcome[3].dnserr, !=, 0);
}
if (expect_err) {
tt_int_op(be_outcome[4].what, ==, BEV_EVENT_ERROR);
tt_int_op(be_outcome[4].dnserr, ==, expect_err);
}
if (emfile) {
tt_int_op(n_accept, ==, 0);
} else {
tt_int_op(n_accept, ==, 3);
}
tt_int_op(n_dns, ==, 2);
end:
@ -1307,16 +1391,10 @@ end:
evdns_close_server_port(port);
if (dns)
evdns_base_free(dns, 0);
if (be1)
bufferevent_free(be1);
if (be2)
bufferevent_free(be2);
if (be3)
bufferevent_free(be3);
if (be4)
bufferevent_free(be4);
if (be5)
bufferevent_free(be5);
for (i = 0; i < ARRAY_SIZE(be); ++i) {
if (be[i])
bufferevent_free(be[i]);
}
}
@ -1355,7 +1433,7 @@ test_getaddrinfo_async(void *arg)
struct evutil_addrinfo hints, *a;
struct gai_outcome local_outcome;
struct gai_outcome a_out[12];
int i;
unsigned i;
struct evdns_getaddrinfo_request *r;
char buf[128];
struct evdns_server_port *port = NULL;
@ -1713,7 +1791,7 @@ test_getaddrinfo_async(void *arg)
end:
if (local_outcome.ai)
evutil_freeaddrinfo(local_outcome.ai);
for (i=0;i<(int)ARRAY_SIZE(a_out);++i) {
for (i = 0; i < ARRAY_SIZE(a_out); ++i) {
if (a_out[i].ai)
evutil_freeaddrinfo(a_out[i].ai);
}
@ -1734,7 +1812,8 @@ struct gaic_request_status {
#define GAIC_MAGIC 0x1234abcd
static int pending = 0;
static int gaic_pending = 0;
static int gaic_freed = 0;
static void
gaic_cancel_request_cb(evutil_socket_t fd, short what, void *arg)
@ -1779,7 +1858,13 @@ gaic_getaddrinfo_cb(int result, struct evutil_addrinfo *res, void *arg)
free(status);
end:
if (--pending <= 0)
if (res)
{
TT_BLATHER(("evutil_freeaddrinfo(%p)", res));
evutil_freeaddrinfo(res);
++gaic_freed;
}
if (--gaic_pending <= 0)
event_base_loopexit(base, NULL);
}
@ -1797,7 +1882,7 @@ gaic_launch(struct event_base *base, struct evdns_base *dns_base)
"foobar.bazquux.example.com", "80", NULL, gaic_getaddrinfo_cb,
status);
event_add(&status->cancel_event, &tv);
++pending;
++gaic_pending;
}
#ifdef EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED
@ -1987,7 +2072,7 @@ test_getaddrinfo_async_cancel_stress(void *ptr)
struct sockaddr_in sin;
struct sockaddr_storage ss;
ev_socklen_t slen;
int i;
unsigned i;
base = event_base_new();
dns_base = evdns_base_new(base, 0);
@ -2020,6 +2105,9 @@ test_getaddrinfo_async_cancel_stress(void *ptr)
event_base_dispatch(base);
// at least some was canceled via external event
tt_int_op(gaic_freed, !=, 1000);
end:
if (dns_base)
evdns_base_free(dns_base, 1);
@ -2036,13 +2124,14 @@ dns_client_fail_requests_test(void *arg)
{
struct basic_test_data *data = arg;
struct event_base *base = data->base;
int limit_inflight = data->setup_data && !strcmp(data->setup_data, "limit-inflight");
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;
unsigned i;
dns_port = regress_get_dnsserver(base, &portnum, NULL,
regress_dns_server_cb, reissue_table);
@ -2053,6 +2142,9 @@ dns_client_fail_requests_test(void *arg)
dns = evdns_base_new(base, EVDNS_BASE_DISABLE_WHEN_INACTIVE);
tt_assert(!evdns_base_nameserver_ip_add(dns, buf));
if (limit_inflight)
tt_assert(!evdns_base_set_option(dns, "max-inflight:", "11"));
for (i = 0; i < 20; ++i)
evdns_base_resolve_ipv4(dns, "foof.example.com", 0, generic_dns_callback, &r[i]);
@ -2099,7 +2191,7 @@ dns_client_fail_requests_getaddrinfo_test(void *arg)
tt_assert(!evdns_base_nameserver_ip_add(dns, buf));
for (i = 0; i < 20; ++i)
tt_assert(evdns_getaddrinfo(dns, "foof.example.com", "ssh", NULL, getaddrinfo_cb, &r[i]));
tt_assert(evdns_getaddrinfo(dns, "foof.example.com", "80", NULL, getaddrinfo_cb, &r[i]));
n_replies_left = 20;
exit_base = base;
@ -2116,6 +2208,242 @@ end:
evdns_close_server_port(dns_port);
}
#ifdef EVTHREAD_USE_PTHREADS_IMPLEMENTED
struct race_param
{
void *lock;
void *reqs_cmpl_cond;
int bw_threads;
void *bw_threads_exited_cond;
volatile int stopping;
void *base;
void *dns;
int locked;
};
static void *
race_base_run(void *arg)
{
struct race_param *rp = (struct race_param *)arg;
event_base_loop(rp->base, EVLOOP_NO_EXIT_ON_EMPTY);
THREAD_RETURN();
}
static void *
race_busywait_run(void *arg)
{
struct race_param *rp = (struct race_param *)arg;
struct sockaddr_storage ss;
while (!rp->stopping)
evdns_base_get_nameserver_addr(rp->dns, 0, (struct sockaddr *)&ss, sizeof(ss));
EVLOCK_LOCK(rp->lock, 0);
if (--rp->bw_threads == 0)
EVTHREAD_COND_SIGNAL(rp->bw_threads_exited_cond);
EVLOCK_UNLOCK(rp->lock, 0);
THREAD_RETURN();
}
static void
race_gai_cb(int result, struct evutil_addrinfo *res, void *arg)
{
struct race_param *rp = arg;
(void)result;
(void)res;
--n_replies_left;
if (n_replies_left == 0) {
EVLOCK_LOCK(rp->lock, 0);
EVTHREAD_COND_SIGNAL(rp->reqs_cmpl_cond);
EVLOCK_UNLOCK(rp->lock, 0);
}
}
static void
getaddrinfo_race_gotresolve_test(void *arg)
{
struct race_param rp;
struct evdns_server_port *dns_port = NULL;
ev_uint16_t portnum = 0;
char buf[64];
int i;
// Some stress is needed to yield inside getaddrinfo between resolve_ipv4 and resolve_ipv6
int n_reqs = 16384;
#ifdef _SC_NPROCESSORS_ONLN
int n_threads = sysconf(_SC_NPROCESSORS_ONLN) + 1;
#else
int n_threads = 17;
#endif
THREAD_T *thread;
struct timeval tv;
(void)arg;
thread = calloc(n_threads, sizeof(*thread));
tt_assert(thread);
evthread_use_pthreads();
rp.base = event_base_new();
tt_assert(rp.base);
if (evthread_make_base_notifiable(rp.base) < 0)
tt_abort_msg("Couldn't make base notifiable!");
dns_port = regress_get_dnsserver(rp.base, &portnum, NULL,
regress_dns_server_cb, reissue_table);
tt_assert(dns_port);
evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum);
rp.dns = evdns_base_new(rp.base, 0);
tt_assert(!evdns_base_nameserver_ip_add(rp.dns, buf));
n_replies_left = n_reqs;
EVTHREAD_ALLOC_LOCK(rp.lock, 0);
EVTHREAD_ALLOC_COND(rp.reqs_cmpl_cond);
EVTHREAD_ALLOC_COND(rp.bw_threads_exited_cond);
tt_assert(rp.lock);
tt_assert(rp.reqs_cmpl_cond);
tt_assert(rp.bw_threads_exited_cond);
rp.bw_threads = 0;
rp.stopping = 0;
// Run resolver thread
THREAD_START(thread[0], race_base_run, &rp);
// Run busy-wait threads used to force yield this thread
for (i = 1; i < n_threads; i++) {
rp.bw_threads++;
THREAD_START(thread[i], race_busywait_run, &rp);
}
EVLOCK_LOCK(rp.lock, 0);
rp.locked = 1;
for (i = 0; i < n_reqs; ++i) {
tt_assert(evdns_getaddrinfo(rp.dns, "foof.example.com", "80", NULL, race_gai_cb, &rp));
// This magic along with busy-wait threads make this thread yield frequently
if (i % 100 == 0) {
tv.tv_sec = 0;
tv.tv_usec = 10000;
evutil_usleep_(&tv);
}
}
exit_base = rp.base;
// Wait for some time
tv.tv_sec = 5;
tv.tv_usec = 0;
EVTHREAD_COND_WAIT_TIMED(rp.reqs_cmpl_cond, rp.lock, &tv);
// Stop busy-wait threads
tv.tv_sec = 1;
tv.tv_usec = 0;
rp.stopping = 1;
tt_assert(EVTHREAD_COND_WAIT_TIMED(rp.bw_threads_exited_cond, rp.lock, &tv) == 0);
EVLOCK_UNLOCK(rp.lock, 0);
rp.locked = 0;
evdns_base_free(rp.dns, 1 /** fail requests */);
tt_int_op(n_replies_left, ==, 0);
end:
if (rp.locked)
EVLOCK_UNLOCK(rp.lock, 0);
EVTHREAD_FREE_LOCK(rp.lock, 0);
EVTHREAD_FREE_COND(rp.reqs_cmpl_cond);
EVTHREAD_FREE_COND(rp.bw_threads_exited_cond);
evdns_close_server_port(dns_port);
event_base_loopbreak(rp.base);
event_base_free(rp.base);
free(thread);
}
#endif
static void
test_set_so_rcvbuf_so_sndbuf(void *arg)
{
struct basic_test_data *data = arg;
struct evdns_base *dns_base;
dns_base = evdns_base_new(data->base, 0);
tt_assert(dns_base);
tt_assert(!evdns_base_set_option(dns_base, "so-rcvbuf", "10240"));
tt_assert(!evdns_base_set_option(dns_base, "so-sndbuf", "10240"));
/* actually check SO_RCVBUF/SO_SNDBUF not fails */
tt_assert(!evdns_base_nameserver_ip_add(dns_base, "127.0.0.1"));
end:
if (dns_base)
evdns_base_free(dns_base, 0);
}
static void
test_set_option(void *arg)
{
#define SUCCESS 0
#define FAIL -1
struct basic_test_data *data = arg;
struct evdns_base *dns_base;
size_t i;
/* Option names are allowed to have ':' at the end.
* So all test option names come in pairs.
*/
const char *int_options[] = {
"ndots", "ndots:",
"max-timeouts", "max-timeouts:",
"max-inflight", "max-inflight:",
"attempts", "attempts:",
"randomize-case", "randomize-case:",
"so-rcvbuf", "so-rcvbuf:",
"so-sndbuf", "so-sndbuf:",
};
const char *timeval_options[] = {
"timeout", "timeout:",
"getaddrinfo-allow-skew", "getaddrinfo-allow-skew:",
"initial-probe-timeout", "initial-probe-timeout:",
};
const char *addr_port_options[] = {
"bind-to", "bind-to:",
};
dns_base = evdns_base_new(data->base, 0);
tt_assert(dns_base);
for (i = 0; i < ARRAY_SIZE(int_options); ++i) {
tt_assert(SUCCESS == evdns_base_set_option(dns_base, int_options[i], "0"));
tt_assert(SUCCESS == evdns_base_set_option(dns_base, int_options[i], "1"));
tt_assert(SUCCESS == evdns_base_set_option(dns_base, int_options[i], "10000"));
tt_assert(FAIL == evdns_base_set_option(dns_base, int_options[i], "foo"));
tt_assert(FAIL == evdns_base_set_option(dns_base, int_options[i], "3.14"));
}
for (i = 0; i < ARRAY_SIZE(timeval_options); ++i) {
tt_assert(SUCCESS == evdns_base_set_option(dns_base, timeval_options[i], "1"));
tt_assert(SUCCESS == evdns_base_set_option(dns_base, timeval_options[i], "0.001"));
tt_assert(SUCCESS == evdns_base_set_option(dns_base, timeval_options[i], "3.14"));
tt_assert(SUCCESS == evdns_base_set_option(dns_base, timeval_options[i], "10000"));
tt_assert(FAIL == evdns_base_set_option(dns_base, timeval_options[i], "0"));
tt_assert(FAIL == evdns_base_set_option(dns_base, timeval_options[i], "foo"));
}
for (i = 0; i < ARRAY_SIZE(addr_port_options); ++i) {
tt_assert(SUCCESS == evdns_base_set_option(dns_base, addr_port_options[i], "8.8.8.8:80"));
tt_assert(SUCCESS == evdns_base_set_option(dns_base, addr_port_options[i], "1.2.3.4"));
tt_assert(SUCCESS == evdns_base_set_option(dns_base, addr_port_options[i], "::1:82"));
tt_assert(SUCCESS == evdns_base_set_option(dns_base, addr_port_options[i], "3::4"));
tt_assert(FAIL == evdns_base_set_option(dns_base, addr_port_options[i], "3.14"));
tt_assert(FAIL == evdns_base_set_option(dns_base, addr_port_options[i], "foo"));
}
#undef SUCCESS
#undef FAIL
end:
if (dns_base)
evdns_base_free(dns_base, 0);
}
#define DNS_LEGACY(name, flags) \
{ #name, run_legacy_test_fn, flags|TT_LEGACY, &legacy_setup, \
@ -2141,10 +2469,21 @@ struct testcase_t dns_testcases[] = {
{ "inflight", dns_inflight_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
{ "bufferevent_connect_hostname", test_bufferevent_connect_hostname,
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
#ifdef EVENT__HAVE_SETRLIMIT
{ "bufferevent_connect_hostname_emfile", test_bufferevent_connect_hostname,
TT_FORK|TT_NEED_BASE, &basic_setup, __UNCONST("emfile") },
#endif
{ "disable_when_inactive", dns_disable_when_inactive_test,
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
{ "disable_when_inactive_no_ns", dns_disable_when_inactive_no_ns_test,
TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL },
{ "initialize_nameservers", dns_initialize_nameservers_test,
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
#ifndef _WIN32
{ "nameservers_no_default", dns_nameservers_no_default_test,
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
#endif
{ "getaddrinfo_async", test_getaddrinfo_async,
TT_FORK|TT_NEED_BASE, &basic_setup, __UNCONST("") },
@ -2165,9 +2504,21 @@ struct testcase_t dns_testcases[] = {
#endif
{ "client_fail_requests", dns_client_fail_requests_test,
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL },
{ "client_fail_waiting_requests", dns_client_fail_requests_test,
TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, __UNCONST("limit-inflight") },
{ "client_fail_requests_getaddrinfo",
dns_client_fail_requests_getaddrinfo_test,
TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL },
#ifdef EVTHREAD_USE_PTHREADS_IMPLEMENTED
{ "getaddrinfo_race_gotresolve",
getaddrinfo_race_gotresolve_test,
TT_FORK|TT_OFF_BY_DEFAULT, NULL, NULL },
#endif
{ "set_SO_RCVBUF_SO_SNDBUF", test_set_so_rcvbuf_so_sndbuf,
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
{ "set_options", test_set_option,
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
END_OF_TESTCASES

View File

@ -1,4 +1,5 @@
/* $NetBSD: regress_et.c,v 1.3 2017/01/31 23:17:40 christos Exp $ */
/* $NetBSD: regress_et.c,v 1.4 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2009-2012 Niels Provos and Nick Mathewson
*
@ -27,7 +28,7 @@
#include "../util-internal.h"
#include "event2/event-config.h"
#include <sys/cdefs.h>
__RCSID("$NetBSD: regress_et.c,v 1.3 2017/01/31 23:17:40 christos Exp $");
__RCSID("$NetBSD: regress_et.c,v 1.4 2021/04/07 03:36:48 christos Exp $");
#ifdef _WIN32
#include <winsock2.h>
@ -54,6 +55,14 @@ __RCSID("$NetBSD: regress_et.c,v 1.3 2017/01/31 23:17:40 christos Exp $");
static int was_et = 0;
static int base_supports_et(struct event_base *base)
{
return
(!strcmp(event_base_get_method(base), "epoll") ||
!strcmp(event_base_get_method(base), "epoll (with changelist)") ||
!strcmp(event_base_get_method(base), "kqueue"));
}
static void
read_cb(evutil_socket_t fd, short event, void *arg)
{
@ -70,19 +79,14 @@ read_cb(evutil_socket_t fd, short event, void *arg)
event_del(arg);
}
#ifdef _WIN32
#define LOCAL_SOCKETPAIR_AF AF_INET
#else
#define LOCAL_SOCKETPAIR_AF AF_UNIX
#endif
static void
test_edgetriggered(void *et)
test_edgetriggered(void *data_)
{
struct basic_test_data *data = data_;
struct event_base *base = data->base;
evutil_socket_t *xpair = data->pair;
struct event *ev = NULL;
struct event_base *base = NULL;
const char *test = "test string";
evutil_socket_t xpair[2] = {-1,-1};
int supports_et;
/* On Linux 3.2.1 (at least, as patched by Fedora and tested by Nick),
@ -91,39 +95,21 @@ test_edgetriggered(void *et)
* get edge-triggered behavior. Yuck! Linux 3.1.9 didn't have this
* problem.
*/
#ifdef __linux__
if (evutil_ersatz_socketpair_(AF_INET, SOCK_STREAM, 0, xpair) == -1) {
tt_abort_perror("socketpair");
}
#else
if (evutil_socketpair(LOCAL_SOCKETPAIR_AF, SOCK_STREAM, 0, xpair) == -1) {
tt_abort_perror("socketpair");
}
#endif
called = was_et = 0;
tt_int_op(send(xpair[0], test, (int)strlen(test)+1, 0), >, 0);
shutdown(xpair[0], EVUTIL_SHUT_WR);
/* Initalize the event library */
base = event_base_new();
if (!strcmp(event_base_get_method(base), "epoll") ||
!strcmp(event_base_get_method(base), "epoll (with changelist)") ||
!strcmp(event_base_get_method(base), "kqueue"))
supports_et = 1;
else
supports_et = 0;
tt_int_op(shutdown(xpair[0], EVUTIL_SHUT_WR), ==, 0);
supports_et = base_supports_et(base);
TT_BLATHER(("Checking for edge-triggered events with %s, which should %s"
"support edge-triggering", event_base_get_method(base),
supports_et?"":"not "));
/* Initalize one event */
/* Initialize one event */
ev = event_new(base, xpair[1], EV_READ|EV_ET|EV_PERSIST, read_cb, &ev);
event_add(ev, NULL);
tt_assert(ev != NULL);
tt_int_op(event_add(ev, NULL), ==, 0);
/* We're going to call the dispatch function twice. The first invocation
* will read a single byte from xpair[1] in either case. If we're edge
@ -132,8 +118,8 @@ test_edgetriggered(void *et)
* do nothing. If we're level triggered, the second invocation of
* event_base_loop will also activate the event (because there's still
* data to read). */
event_base_loop(base,EVLOOP_NONBLOCK|EVLOOP_ONCE);
event_base_loop(base,EVLOOP_NONBLOCK|EVLOOP_ONCE);
tt_int_op(event_base_loop(base,EVLOOP_NONBLOCK|EVLOOP_ONCE), ==, 0);
tt_int_op(event_base_loop(base,EVLOOP_NONBLOCK|EVLOOP_ONCE), ==, 0);
if (supports_et) {
tt_int_op(called, ==, 1);
@ -143,15 +129,11 @@ test_edgetriggered(void *et)
tt_assert(!was_et);
}
end:
end:
if (ev) {
event_del(ev);
event_free(ev);
}
if (base)
event_base_free(base);
evutil_closesocket(xpair[0]);
evutil_closesocket(xpair[1]);
}
static void
@ -199,9 +181,94 @@ end:
event_base_free(base);
}
static int read_notification_count;
static int last_read_notification_was_et;
static void
read_notification_cb(evutil_socket_t fd, short event, void *arg)
{
read_notification_count++;
last_read_notification_was_et = (event & EV_ET);
}
static int write_notification_count;
static int last_write_notification_was_et;
static void
write_notification_cb(evutil_socket_t fd, short event, void *arg)
{
write_notification_count++;
last_write_notification_was_et = (event & EV_ET);
}
/* After two or more events have been registered for the same
* file descriptor using EV_ET, if one of the events is
* deleted, then the epoll_ctl() call issued by libevent drops
* the EPOLLET flag resulting in level triggered
* notifications.
*/
static void
test_edge_triggered_multiple_events(void *data_)
{
struct basic_test_data *data = data_;
struct event *read_ev = NULL;
struct event *write_ev = NULL;
const char c = 'A';
struct event_base *base = data->base;
evutil_socket_t *xpair = data->pair;
if (!base_supports_et(base)) {
tt_skip();
return;
}
read_notification_count = 0;
last_read_notification_was_et = 0;
write_notification_count = 0;
last_write_notification_was_et = 0;
/* Make xpair[1] readable */
tt_int_op(send(xpair[0], &c, 1, 0), >, 0);
read_ev = event_new(base, xpair[1], EV_READ|EV_ET|EV_PERSIST,
read_notification_cb, NULL);
write_ev = event_new(base, xpair[1], EV_WRITE|EV_ET|EV_PERSIST,
write_notification_cb, NULL);
event_add(read_ev, NULL);
event_add(write_ev, NULL);
event_base_loop(base, EVLOOP_NONBLOCK|EVLOOP_ONCE);
event_base_loop(base, EVLOOP_NONBLOCK|EVLOOP_ONCE);
tt_assert(last_read_notification_was_et);
tt_int_op(read_notification_count, ==, 1);
tt_assert(last_write_notification_was_et);
tt_int_op(write_notification_count, ==, 1);
event_del(read_ev);
/* trigger acitivity second time for the backend that can have multiple
* events for one fd (like kqueue) */
close(xpair[0]);
xpair[0] = -1;
/* Verify that we are still edge-triggered for write notifications */
event_base_loop(base, EVLOOP_NONBLOCK|EVLOOP_ONCE);
event_base_loop(base, EVLOOP_NONBLOCK|EVLOOP_ONCE);
tt_assert(last_write_notification_was_et);
tt_int_op(write_notification_count, ==, 2);
end:
if (read_ev)
event_free(read_ev);
if (write_ev)
event_free(write_ev);
}
struct testcase_t edgetriggered_testcases[] = {
{ "et", test_edgetriggered, TT_FORK, NULL, NULL },
{ "et", test_edgetriggered,
TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR, &basic_setup, NULL },
{ "et_mix_error", test_edgetriggered_mix_error,
TT_FORK|TT_NEED_SOCKETPAIR|TT_NO_LOGS, &basic_setup, NULL },
{ "et_multiple_events", test_edge_triggered_multiple_events,
TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR, &basic_setup, NULL },
END_OF_TESTCASES
};

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
/* $NetBSD: regress_listener.c,v 1.3 2017/01/31 23:17:40 christos Exp $ */
/* $NetBSD: regress_listener.c,v 1.4 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2009-2012 Niels Provos and Nick Mathewson
*
@ -81,8 +82,9 @@ regress_pick_a_port(void *arg)
ev_socklen_t slen1 = sizeof(ss1), slen2 = sizeof(ss2);
unsigned int flags =
LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_EXEC;
evutil_socket_t fd1, fd2, fd3;
evutil_socket_t fd1 = -1, fd2 = -1, fd3 = -1;
fd1 = fd2 = fd3 = EVUTIL_INVALID_SOCKET;
if (data->setup_data && strstr((char*)data->setup_data, "ts")) {
flags |= LEV_OPT_THREADSAFE;
@ -100,8 +102,8 @@ regress_pick_a_port(void *arg)
flags, -1, (struct sockaddr *)&sin, sizeof(sin));
tt_assert(listener2);
tt_int_op(evconnlistener_get_fd(listener1), >=, 0);
tt_int_op(evconnlistener_get_fd(listener2), >=, 0);
tt_assert(evconnlistener_get_fd(listener1) != EVUTIL_INVALID_SOCKET);
tt_assert(evconnlistener_get_fd(listener2) != EVUTIL_INVALID_SOCKET);
tt_assert(getsockname(evconnlistener_get_fd(listener1),
(struct sockaddr*)&ss1, &slen1) == 0);
tt_assert(getsockname(evconnlistener_get_fd(listener2),
@ -118,7 +120,7 @@ regress_pick_a_port(void *arg)
tt_ptr_op(evconnlistener_get_base(listener1), ==, base);
tt_ptr_op(evconnlistener_get_base(listener2), ==, base);
fd1 = fd2 = fd3 = -1;
fd1 = fd2 = fd3 = EVUTIL_INVALID_SOCKET;
evutil_socket_connect_(&fd1, (struct sockaddr*)&ss1, slen1);
evutil_socket_connect_(&fd2, (struct sockaddr*)&ss1, slen1);
evutil_socket_connect_(&fd3, (struct sockaddr*)&ss2, slen2);
@ -186,6 +188,89 @@ end:
evconnlistener_free(listener);
}
static void
acceptcb_free(struct evconnlistener *listener, evutil_socket_t fd,
struct sockaddr *addr, int socklen, void *arg)
{
int *ptr = arg;
--*ptr;
TT_BLATHER(("Got one for %p", ptr));
evutil_closesocket(fd);
if (! *ptr)
evconnlistener_free(listener);
}
static void
regress_listener_close_accepted_fd(void *arg)
{
struct basic_test_data *data = arg;
struct event_base *base = data->base;
struct evconnlistener *listener = NULL;
struct sockaddr_in sin;
struct sockaddr_storage ss;
ev_socklen_t slen = sizeof(ss);
int count = 1;
unsigned int flags = LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE;
evutil_socket_t fd = EVUTIL_INVALID_SOCKET;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */
sin.sin_port = 0; /* "You pick!" */
/* Start a listener with a bogus socket. */
listener = evconnlistener_new_bind(base, acceptcb_free, &count,
flags, -1, (struct sockaddr *)&sin, sizeof(sin));
tt_assert(listener);
tt_assert(getsockname(evconnlistener_get_fd(listener),
(struct sockaddr*)&ss, &slen) == 0);
evutil_socket_connect_(&fd, (struct sockaddr*)&ss, slen);
event_base_dispatch(base);
end:
;
}
static void
regress_listener_immediate_close(void *arg)
{
struct basic_test_data *data = arg;
struct event_base *base = data->base;
struct evconnlistener *listener = NULL;
struct sockaddr_in sin;
struct sockaddr_storage ss;
ev_socklen_t slen = sizeof(ss);
int count = 1;
unsigned int flags = LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE;
evutil_socket_t fd1 = EVUTIL_INVALID_SOCKET, fd2 = EVUTIL_INVALID_SOCKET;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */
sin.sin_port = 0; /* "You pick!" */
/* Start a listener with a bogus socket. */
listener = evconnlistener_new_bind(base, acceptcb, &count,
flags, -1, (struct sockaddr *)&sin, sizeof(sin));
tt_assert(listener);
tt_assert(getsockname(evconnlistener_get_fd(listener),
(struct sockaddr*)&ss, &slen) == 0);
evutil_socket_connect_(&fd1, (struct sockaddr*)&ss, slen);
evutil_socket_connect_(&fd2, (struct sockaddr*)&ss, slen);
event_base_dispatch(base);
tt_int_op(count, ==, 0);
end:
if (listener)
evconnlistener_free(listener);
}
#ifdef EVENT__HAVE_SETRLIMIT
static void
regress_listener_error_unlock(void *arg)
@ -231,7 +316,7 @@ struct testcase_t listener_testcases[] = {
#ifdef EVENT__HAVE_SETRLIMIT
{ "error_unlock", regress_listener_error_unlock,
TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR,
TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR|TT_NO_LOGS,
&basic_setup, NULL},
#endif
@ -243,6 +328,12 @@ struct testcase_t listener_testcases[] = {
TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR,
&basic_setup, __UNCONST("ts") },
{ "close_accepted_fd", regress_listener_close_accepted_fd,
TT_FORK|TT_NEED_BASE, &basic_setup, NULL, },
{ "immediate_close", regress_listener_immediate_close,
TT_FORK|TT_NEED_BASE, &basic_setup, NULL, },
END_OF_TESTCASES,
};

View File

@ -1,4 +1,5 @@
/* $NetBSD: regress_main.c,v 1.3 2017/01/31 23:17:40 christos Exp $ */
/* $NetBSD: regress_main.c,v 1.4 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu>
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
@ -34,6 +35,14 @@
#include <fcntl.h>
#endif
/* move_pthread_to_realtime_scheduling_class() */
#ifdef EVENT__HAVE_MACH_MACH_H
#include <mach/mach.h>
#endif
#ifdef EVENT__HAVE_MACH_MACH_TIME_H
#include <mach/mach_time.h>
#endif
#if defined(__APPLE__) && defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__)
#if (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060 && \
__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070)
@ -44,7 +53,7 @@
#include "event2/event-config.h"
#include <sys/cdefs.h>
__RCSID("$NetBSD: regress_main.c,v 1.3 2017/01/31 23:17:40 christos Exp $");
__RCSID("$NetBSD: regress_main.c,v 1.4 2021/04/07 03:36:48 christos Exp $");
#if 0
#include <sys/types.h>
@ -84,12 +93,13 @@ __RCSID("$NetBSD: regress_main.c,v 1.3 2017/01/31 23:17:40 christos Exp $");
#include "event2/event-config.h"
#include <sys/cdefs.h>
__RCSID("$NetBSD: regress_main.c,v 1.3 2017/01/31 23:17:40 christos Exp $");
#include "regress.h"
#include "regress_thread.h"
#include "tinytest.h"
#include "tinytest_macros.h"
#include "../iocp-internal.h"
#include "../event-internal.h"
#include "../evthread-internal.h"
struct evutil_weakrand_state test_weakrand_state;
@ -191,18 +201,65 @@ ignore_log_cb(int s, const char *msg)
{
}
static void *
/**
* Put into the real time scheduling class for better timers latency.
* https://developer.apple.com/library/archive/technotes/tn2169/_index.html#//apple_ref/doc/uid/DTS40013172-CH1-TNTAG6000
*/
#if defined(__APPLE__)
static void move_pthread_to_realtime_scheduling_class(pthread_t pthread)
{
mach_timebase_info_data_t info;
mach_timebase_info(&info);
const uint64_t NANOS_PER_MSEC = 1000000ULL;
double clock2abs =
((double)info.denom / (double)info.numer) * NANOS_PER_MSEC;
thread_time_constraint_policy_data_t policy;
policy.period = 0;
policy.computation = (uint32_t)(5 * clock2abs); // 5 ms of work
policy.constraint = (uint32_t)(10 * clock2abs);
policy.preemptible = FALSE;
int kr = thread_policy_set(pthread_mach_thread_np(pthread),
THREAD_TIME_CONSTRAINT_POLICY,
(thread_policy_t)&policy,
THREAD_TIME_CONSTRAINT_POLICY_COUNT);
if (kr != KERN_SUCCESS) {
mach_error("thread_policy_set:", kr);
exit(1);
}
}
void thread_setup(THREAD_T pthread)
{
move_pthread_to_realtime_scheduling_class(pthread);
}
#else /** \__APPLE__ */
void thread_setup(THREAD_T pthread) {}
#endif /** \!__APPLE__ */
void *
basic_test_setup(const struct testcase_t *testcase)
{
struct event_base *base = NULL;
evutil_socket_t spair[2] = { -1, -1 };
struct basic_test_data *data = NULL;
thread_setup(THREAD_SELF());
#ifndef _WIN32
if (testcase->flags & TT_ENABLE_IOCP_FLAG)
return (void*)TT_SKIP;
#endif
if (testcase->flags & TT_ENABLE_DEBUG_MODE &&
!libevent_tests_running_in_debug_mode) {
event_enable_debug_mode();
libevent_tests_running_in_debug_mode = 1;
}
if (testcase->flags & TT_NEED_THREADS) {
if (!(testcase->flags & TT_FORK))
return NULL;
@ -267,7 +324,7 @@ basic_test_setup(const struct testcase_t *testcase)
return data;
}
static int
int
basic_test_cleanup(const struct testcase_t *testcase, void *ptr)
{
struct basic_test_data *data = ptr;
@ -389,6 +446,7 @@ struct testgroup_t testgroups[] = {
{ "iocp/", iocp_testcases },
{ "iocp/bufferevent/", bufferevent_iocp_testcases },
{ "iocp/listener/", listener_iocp_testcases },
{ "iocp/http/", http_iocp_testcases },
#endif
#ifdef EVENT__HAVE_OPENSSL
{ "ssl/", ssl_testcases },
@ -440,6 +498,7 @@ main(int argc, const char **argv)
#ifdef _WIN32
tinytest_skip(testgroups, "http/connection_retry");
tinytest_skip(testgroups, "http/https_connection_retry");
tinytest_skip(testgroups, "http/read_on_write_error");
#endif
#ifndef EVENT__DISABLE_THREAD_SUPPORT
@ -459,6 +518,11 @@ main(int argc, const char **argv)
evutil_weakrand_seed_(&test_weakrand_state, 0);
if (getenv("EVENT_NO_FILE_BUFFERING")) {
setbuf(stdout, NULL);
setbuf(stderr, NULL);
}
if (tinytest_main(argc,argv,testgroups))
return 1;

View File

@ -1,4 +1,5 @@
/* $NetBSD: regress_rpc.c,v 1.4 2017/01/31 23:17:40 christos Exp $ */
/* $NetBSD: regress_rpc.c,v 1.5 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu>
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
@ -36,7 +37,7 @@
#include "event2/event-config.h"
#include <sys/cdefs.h>
__RCSID("$NetBSD: regress_rpc.c,v 1.4 2017/01/31 23:17:40 christos Exp $");
__RCSID("$NetBSD: regress_rpc.c,v 1.5 2021/04/07 03:36:48 christos Exp $");
#include <sys/types.h>
#include <sys/stat.h>
@ -64,7 +65,6 @@ __RCSID("$NetBSD: regress_rpc.c,v 1.4 2017/01/31 23:17:40 christos Exp $");
#include "event2/http_compat.h"
#include "event2/http_struct.h"
#include "event2/rpc.h"
#include "event2/rpc.h"
#include "event2/rpc_struct.h"
#include "event2/tag.h"
#include "log-internal.h"
@ -883,6 +883,53 @@ end:
evbuffer_free(tmp);
}
static void
rpc_invalid_type(void)
{
ev_uint16_t port;
struct evhttp *http = NULL;
struct evrpc_base *base = NULL;
struct evhttp_connection *evcon = NULL;
struct evhttp_request *req = NULL;
rpc_setup(&http, &port, &base);
evcon = evhttp_connection_new("127.0.0.1", port);
tt_assert(evcon);
/*
* At this point, we want to schedule an HTTP POST request
* server using our make request method.
*/
req = evhttp_request_new(rpc_postrequest_failure, NULL);
tt_assert(req);
/* Add the information that we care about */
evhttp_add_header(req->output_headers, "Host", "somehost");
evbuffer_add_printf(req->output_buffer, "Some Nonsense");
if (evhttp_make_request(evcon, req,
EVHTTP_REQ_GET,
"/.rpc.Message") == -1) {
tt_abort();
}
test_ok = 0;
event_dispatch();
evhttp_connection_free(evcon);
rpc_teardown(base);
tt_assert(test_ok == 1);
end:
evhttp_free(http);
}
#define RPC_LEGACY(name) \
{ #name, run_legacy_test_fn, TT_FORK|TT_NEED_BASE|TT_LEGACY, \
&legacy_setup, \
@ -901,6 +948,7 @@ struct testcase_t rpc_testcases[] = {
RPC_LEGACY(basic_client),
RPC_LEGACY(basic_queued_client),
RPC_LEGACY(basic_client_with_pause),
RPC_LEGACY(invalid_type),
RPC_LEGACY(client_timeout),
RPC_LEGACY(test),

View File

@ -1,4 +1,5 @@
/* $NetBSD: regress_ssl.c,v 1.4 2020/02/21 00:26:21 joerg Exp $ */
/* $NetBSD: regress_ssl.c,v 1.5 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2009-2012 Niels Provos and Nick Mathewson
*
@ -54,7 +55,6 @@
#include "tinytest.h"
#include "tinytest_macros.h"
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include "openssl-compat.h"
@ -121,14 +121,13 @@ end:
}
X509 *
ssl_getcert(void)
ssl_getcert(EVP_PKEY *key)
{
/* Dummy code to make a quick-and-dirty valid certificate with
OpenSSL. Don't copy this code into your own program! It does a
number of things in a stupid and insecure way. */
X509 *x509 = NULL;
X509_NAME *name = NULL;
EVP_PKEY *key = ssl_getkey();
int nid;
time_t now = time(NULL);
@ -150,16 +149,18 @@ ssl_getcert(void)
X509_set_subject_name(x509, name);
X509_set_issuer_name(x509, name);
X509_NAME_free(name);
X509_time_adj(X509_get_notBefore(x509), 0, &now);
X509_time_adj(X509_getm_notBefore(x509), 0, &now);
now += 3600;
X509_time_adj(X509_get_notAfter(x509), 0, &now);
X509_time_adj(X509_getm_notAfter(x509), 0, &now);
X509_set_pubkey(x509, key);
tt_assert(0 != X509_sign(x509, key, EVP_sha1()));
return x509;
end:
X509_free(x509);
X509_NAME_free(name);
return NULL;
}
@ -185,35 +186,86 @@ get_ssl_ctx(void)
return the_ssl_ctx;
}
static int test_is_done;
static int n_connected;
static int got_close;
static int got_error;
static int got_timeout;
static int renegotiate_at = -1;
static int stop_when_connected;
static int pending_connect_events;
static struct event_base *exit_base;
static X509 *the_cert;
EVP_PKEY *the_key;
void
init_ssl(void)
{
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
SSL_library_init();
ERR_load_crypto_strings();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
if (SSLeay() != OPENSSL_VERSION_NUMBER) {
TT_DECLARE("WARN", ("Version mismatch for openssl: compiled with %lx but running with %lx", (unsigned long)OPENSSL_VERSION_NUMBER, (unsigned long) SSLeay()));
TT_DECLARE("WARN",
("Version mismatch for openssl: compiled with %lx but running with %lx",
(unsigned long)OPENSSL_VERSION_NUMBER, (unsigned long)SSLeay()));
}
#endif
}
static void *
ssl_test_setup(const struct testcase_t *testcase)
{
init_ssl();
the_key = ssl_getkey();
EVUTIL_ASSERT(the_key);
the_cert = ssl_getcert(the_key);
EVUTIL_ASSERT(the_cert);
disable_tls_11_and_12 = 0;
return basic_test_setup(testcase);
}
static int
ssl_test_cleanup(const struct testcase_t *testcase, void *ptr)
{
int ret = basic_test_cleanup(testcase, ptr);
if (!ret) {
return ret;
}
test_is_done = 0;
n_connected = 0;
got_close = 0;
got_error = 0;
got_timeout = 0;
renegotiate_at = -1;
stop_when_connected = 0;
pending_connect_events = 0;
exit_base = NULL;
X509_free(the_cert);
EVP_PKEY_free(the_key);
SSL_CTX_free(the_ssl_ctx);
the_ssl_ctx = NULL;
return 1;
}
const struct testcase_setup_t ssl_setup = {
ssl_test_setup, ssl_test_cleanup
};
/* ====================
Here's a simple test: we read a number from the input, increment it, and
reply, until we get to 1001.
*/
static int test_is_done = 0;
static int n_connected = 0;
static int got_close = 0;
static int got_error = 0;
static int got_timeout = 0;
static int renegotiate_at = -1;
static int stop_when_connected = 0;
static int pending_connect_events = 0;
static struct event_base *exit_base = NULL;
enum regress_openssl_type
{
REGRESS_OPENSSL_SOCKETPAIR = 1,
@ -231,17 +283,19 @@ enum regress_openssl_type
REGRESS_OPENSSL_SLEEP = 1024,
REGRESS_OPENSSL_CLIENT_WRITE = 2048,
REGRESS_DEFERRED_CALLBACKS = 4096,
};
static void
bufferevent_openssl_check_fd(struct bufferevent *bev, int filter)
{
tt_int_op(bufferevent_getfd(bev), !=, -1);
tt_int_op(bufferevent_setfd(bev, -1), ==, 0);
tt_fd_op(bufferevent_getfd(bev), !=, EVUTIL_INVALID_SOCKET);
tt_fd_op(bufferevent_setfd(bev, EVUTIL_INVALID_SOCKET), ==, 0);
if (filter) {
tt_int_op(bufferevent_getfd(bev), !=, -1);
tt_fd_op(bufferevent_getfd(bev), !=, EVUTIL_INVALID_SOCKET);
} else {
tt_int_op(bufferevent_getfd(bev), ==, -1);
tt_fd_op(bufferevent_getfd(bev), ==, EVUTIL_INVALID_SOCKET);
}
end:
@ -257,6 +311,13 @@ end:
;
}
static void
free_on_cb(struct bufferevent *bev, void *ctx)
{
TT_BLATHER(("free_on_cb: %p", bev));
bufferevent_free(bev);
}
static void
respond_to_number(struct bufferevent *bev, void *ctx)
{
@ -305,13 +366,13 @@ done_writing_cb(struct bufferevent *bev, void *ctx)
static void
eventcb(struct bufferevent *bev, short what, void *ctx)
{
X509 *peer_cert = NULL;
enum regress_openssl_type type;
type = (enum regress_openssl_type)(uintptr_t)ctx;
TT_BLATHER(("Got event %d", (int)what));
if (what & BEV_EVENT_CONNECTED) {
SSL *ssl;
X509 *peer_cert;
++n_connected;
ssl = bufferevent_openssl_get_ssl(bev);
tt_assert(ssl);
@ -359,8 +420,10 @@ eventcb(struct bufferevent *bev, short what, void *ctx)
}
bufferevent_free(bev);
}
end:
;
if (peer_cert)
X509_free(peer_cert);
}
static void
@ -400,8 +463,6 @@ regress_bufferevent_openssl(void *arg)
struct bufferevent *bev1, *bev2;
SSL *ssl1, *ssl2;
X509 *cert = ssl_getcert();
EVP_PKEY *key = ssl_getkey();
int flags = BEV_OPT_DEFER_CALLBACKS;
struct bufferevent *bev_ll[2] = { NULL, NULL };
evutil_socket_t *fd_pair = NULL;
@ -409,14 +470,9 @@ regress_bufferevent_openssl(void *arg)
enum regress_openssl_type type;
type = (enum regress_openssl_type)(uintptr_t)data->setup_data;
tt_assert(cert);
tt_assert(key);
init_ssl();
if (type & REGRESS_OPENSSL_RENEGOTIATE) {
if (SSLeay() >= 0x10001000 &&
SSLeay() < 0x1000104f) {
if (OPENSSL_VERSION_NUMBER >= 0x10001000 &&
OPENSSL_VERSION_NUMBER < 0x1000104f) {
/* 1.0.1 up to 1.0.1c has a bug where TLS1.1 and 1.2
* can't renegotiate with themselves. Disable. */
disable_tls_11_and_12 = 1;
@ -427,8 +483,8 @@ regress_bufferevent_openssl(void *arg)
ssl1 = SSL_new(get_ssl_ctx());
ssl2 = SSL_new(get_ssl_ctx());
SSL_use_certificate(ssl2, cert);
SSL_use_PrivateKey(ssl2, key);
SSL_use_certificate(ssl2, the_cert);
SSL_use_PrivateKey(ssl2, the_key);
if (!(type & REGRESS_OPENSSL_OPEN))
flags |= BEV_OPT_CLOSE_ON_FREE;
@ -447,7 +503,7 @@ regress_bufferevent_openssl(void *arg)
fd_pair, bev_ll, type);
if (!(type & REGRESS_OPENSSL_FILTER)) {
tt_int_op(bufferevent_getfd(bev1), ==, data->pair[0]);
tt_fd_op(bufferevent_getfd(bev1), ==, data->pair[0]);
} else {
tt_ptr_op(bufferevent_get_underlying(bev1), ==, bev_ll[0]);
}
@ -506,7 +562,10 @@ regress_bufferevent_openssl(void *arg)
tt_int_op(got_close, ==, 0);
tt_int_op(got_error, ==, 0);
tt_int_op(got_timeout, ==, 1);
bufferevent_free(bev2);
}
end:
return;
}
@ -528,15 +587,13 @@ acceptcb(struct evconnlistener *listener, evutil_socket_t fd,
type = (enum regress_openssl_type)(uintptr_t)data->setup_data;
SSL_use_certificate(ssl, ssl_getcert());
SSL_use_PrivateKey(ssl, ssl_getkey());
SSL_use_certificate(ssl, the_cert);
SSL_use_PrivateKey(ssl, the_key);
bev = bufferevent_openssl_socket_new(
data->base,
fd,
ssl,
BUFFEREVENT_SSL_ACCEPTING,
data->base, fd, ssl, BUFFEREVENT_SSL_ACCEPTING,
BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
tt_assert(bev);
bufferevent_setcb(bev, respond_to_number, NULL, eventcb,
(void*)(REGRESS_OPENSSL_SERVER));
@ -552,11 +609,14 @@ acceptcb(struct evconnlistener *listener, evutil_socket_t fd,
/* Only accept once, then disable ourself. */
evconnlistener_disable(listener);
end:
;
}
struct rwcount
{
int fd;
evutil_socket_t fd;
size_t read;
size_t write;
};
@ -570,6 +630,7 @@ bio_rwcount_new(BIO *b)
static int
bio_rwcount_free(BIO *b)
{
TT_BLATHER(("bio_rwcount_free: %p", b));
if (!b)
return 0;
if (BIO_get_shutdown(b)) {
@ -592,7 +653,6 @@ bio_rwcount_read(BIO *b, char *out, int outlen)
static int
bio_rwcount_write(BIO *b, const char *in, int inlen)
{
struct rwcount *rw = BIO_get_data(b);
ev_ssize_t ret = send(rw->fd, in, inlen, 0);
++rw->write;
@ -604,8 +664,12 @@ bio_rwcount_write(BIO *b, const char *in, int inlen)
static long
bio_rwcount_ctrl(BIO *b, int cmd, long num, void *ptr)
{
struct rwcount *rw = BIO_get_data(b);
long ret = 0;
switch (cmd) {
case BIO_C_GET_FD:
ret = rw->fd;
break;
case BIO_CTRL_GET_CLOSE:
ret = BIO_get_shutdown(b);
break;
@ -674,14 +738,11 @@ regress_bufferevent_openssl_connect(void *arg)
struct sockaddr_storage ss;
ev_socklen_t slen;
SSL *ssl;
BIO *bio;
struct rwcount rw = { -1, 0, 0 };
enum regress_openssl_type type;
type = (enum regress_openssl_type)(uintptr_t)data->setup_data;
init_ssl();
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(0x7f000001);
@ -705,7 +766,7 @@ regress_bufferevent_openssl_connect(void *arg)
BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
tt_assert(bev);
bufferevent_setcb(bev, respond_to_number, NULL, eventcb,
bufferevent_setcb(bev, respond_to_number, free_on_cb, eventcb,
(void*)(REGRESS_OPENSSL_CLIENT));
tt_assert(getsockname(evconnlistener_get_fd(listener),
@ -718,6 +779,8 @@ regress_bufferevent_openssl_connect(void *arg)
/* Possible only when we have fd, since be_openssl can and will overwrite
* bio otherwise before */
if (type & REGRESS_OPENSSL_SLEEP) {
BIO *bio;
rw.fd = bufferevent_getfd(bev);
bio = BIO_new_rwcount(0);
tt_assert(bio);
@ -732,83 +795,284 @@ regress_bufferevent_openssl_connect(void *arg)
tt_int_op(rw.read, <=, 100);
tt_int_op(rw.write, <=, 100);
end:
;
evconnlistener_free(listener);
}
struct wm_context
{
int server;
int flags;
struct evbuffer *data;
size_t to_read;
size_t wm_high;
size_t limit;
size_t get;
struct bufferevent *bev;
struct wm_context *neighbour;
};
static void
wm_transfer(struct bufferevent *bev, void *arg)
{
struct wm_context *ctx = arg;
struct evbuffer *in = bufferevent_get_input(bev);
struct evbuffer *out = bufferevent_get_output(bev);
size_t len = evbuffer_get_length(in);
size_t drain = len < ctx->to_read ? len : ctx->to_read;
if (ctx->get >= ctx->limit) {
TT_BLATHER(("wm_transfer-%s(%p): break",
ctx->server ? "server" : "client", bev));
bufferevent_setcb(bev, NULL, NULL, NULL, NULL);
bufferevent_disable(bev, EV_READ);
if (ctx->neighbour->get >= ctx->neighbour->limit) {
event_base_loopbreak(bufferevent_get_base(bev));
}
} else {
ctx->get += drain;
evbuffer_drain(in, drain);
}
TT_BLATHER(("wm_transfer-%s(%p): "
"in: " EV_SIZE_FMT ", "
"out: " EV_SIZE_FMT ", "
"got: " EV_SIZE_FMT "",
ctx->server ? "server" : "client", bev,
evbuffer_get_length(in),
evbuffer_get_length(out),
ctx->get));
evbuffer_add_buffer_reference(out, ctx->data);
}
static void
wm_eventcb(struct bufferevent *bev, short what, void *arg)
{
struct wm_context *ctx = arg;
TT_BLATHER(("wm_eventcb-%s(%p): %i",
ctx->server ? "server" : "client", bev, what));
if (what & BEV_EVENT_CONNECTED) {
} else {
ctx->get = 0;
}
}
static void
wm_acceptcb(struct evconnlistener *listener, evutil_socket_t fd,
struct sockaddr *addr, int socklen, void *arg)
{
struct wm_context *ctx = arg;
struct bufferevent *bev;
struct event_base *base = evconnlistener_get_base(listener);
SSL *ssl = SSL_new(get_ssl_ctx());
SSL_use_certificate(ssl, the_cert);
SSL_use_PrivateKey(ssl, the_key);
bev = bufferevent_openssl_socket_new(
base, fd, ssl, BUFFEREVENT_SSL_ACCEPTING, ctx->flags);
TT_BLATHER(("wm_transfer-%s(%p): accept",
ctx->server ? "server" : "client", bev));
bufferevent_setwatermark(bev, EV_READ, 0, ctx->wm_high);
bufferevent_setcb(bev, wm_transfer, NULL, wm_eventcb, ctx);
bufferevent_enable(bev, EV_READ|EV_WRITE);
ctx->bev = bev;
/* Only accept once, then disable ourself. */
evconnlistener_disable(listener);
}
static void
regress_bufferevent_openssl_wm(void *arg)
{
struct basic_test_data *data = arg;
struct event_base *base = data->base;
struct evconnlistener *listener;
struct bufferevent *bev;
struct sockaddr_in sin;
struct sockaddr_storage ss;
enum regress_openssl_type type =
(enum regress_openssl_type)data->setup_data;
int bev_flags = BEV_OPT_CLOSE_ON_FREE;
ev_socklen_t slen;
SSL *ssl;
struct wm_context client, server;
char *payload;
size_t payload_len = 1<<10;
size_t wm_high = 5<<10;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(0x7f000001);
memset(&ss, 0, sizeof(ss));
slen = sizeof(ss);
if (type & REGRESS_DEFERRED_CALLBACKS)
bev_flags |= BEV_OPT_DEFER_CALLBACKS;
memset(&client, 0, sizeof(client));
memset(&server, 0, sizeof(server));
client.server = 0;
server.server = 1;
client.flags = server.flags = bev_flags;
client.data = evbuffer_new();
server.data = evbuffer_new();
payload = calloc(1, payload_len);
memset(payload, 'A', payload_len);
evbuffer_add(server.data, payload, payload_len);
evbuffer_add(client.data, payload, payload_len);
client.wm_high = server.wm_high = wm_high;
client.limit = server.limit = wm_high<<3;
client.to_read = server.to_read = payload_len>>1;
TT_BLATHER(("openssl_wm: "
"payload_len = " EV_SIZE_FMT ", "
"wm_high = " EV_SIZE_FMT ", "
"limit = " EV_SIZE_FMT ", "
"to_read: " EV_SIZE_FMT "",
payload_len,
wm_high,
server.limit,
server.to_read));
listener = evconnlistener_new_bind(base, wm_acceptcb, &server,
LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE,
-1, (struct sockaddr *)&sin, sizeof(sin));
tt_assert(listener);
tt_assert(evconnlistener_get_fd(listener) >= 0);
ssl = SSL_new(get_ssl_ctx());
tt_assert(ssl);
if (type & REGRESS_OPENSSL_FILTER) {
bev = bufferevent_socket_new(data->base, -1, client.flags);
tt_assert(bev);
bev = bufferevent_openssl_filter_new(
base, bev, ssl, BUFFEREVENT_SSL_CONNECTING, client.flags);
} else {
bev = bufferevent_openssl_socket_new(
data->base, -1, ssl,
BUFFEREVENT_SSL_CONNECTING,
client.flags);
}
tt_assert(bev);
client.bev = bev;
server.neighbour = &client;
client.neighbour = &server;
bufferevent_setwatermark(bev, EV_READ, 0, client.wm_high);
bufferevent_setcb(bev, wm_transfer, NULL, wm_eventcb, &client);
tt_assert(getsockname(evconnlistener_get_fd(listener),
(struct sockaddr*)&ss, &slen) == 0);
tt_assert(!bufferevent_socket_connect(bev, (struct sockaddr*)&ss, slen));
tt_assert(!evbuffer_add_buffer_reference(bufferevent_get_output(bev), client.data));
tt_assert(!bufferevent_enable(bev, EV_READ|EV_WRITE));
event_base_dispatch(base);
tt_int_op(client.get, ==, client.limit);
tt_int_op(server.get, ==, server.limit);
end:
free(payload);
evbuffer_free(client.data);
evbuffer_free(server.data);
evconnlistener_free(listener);
bufferevent_free(client.bev);
bufferevent_free(server.bev);
/* XXX: by some reason otherise there is a leak */
if (!(type & REGRESS_OPENSSL_FILTER))
event_base_loop(base, EVLOOP_ONCE);
}
struct testcase_t ssl_testcases[] = {
#define T(a) ((void *)(a))
{ "bufferevent_socketpair", regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup, T(REGRESS_OPENSSL_SOCKETPAIR) },
TT_ISOLATED, &ssl_setup, T(REGRESS_OPENSSL_SOCKETPAIR) },
{ "bufferevent_socketpair_write_after_connect", regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup,
TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_SOCKETPAIR|REGRESS_OPENSSL_CLIENT_WRITE) },
{ "bufferevent_filter", regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup, T(REGRESS_OPENSSL_FILTER) },
TT_ISOLATED, &ssl_setup, T(REGRESS_OPENSSL_FILTER) },
{ "bufferevent_filter_write_after_connect", regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup,
TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_FILTER|REGRESS_OPENSSL_CLIENT_WRITE) },
{ "bufferevent_renegotiate_socketpair", regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup,
TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_RENEGOTIATE) },
{ "bufferevent_renegotiate_filter", regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup,
TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_RENEGOTIATE) },
{ "bufferevent_socketpair_startopen", regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup,
TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_OPEN) },
{ "bufferevent_filter_startopen", regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup,
TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_OPEN) },
{ "bufferevent_socketpair_dirty_shutdown", regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup,
TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
{ "bufferevent_filter_dirty_shutdown", regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup,
TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
{ "bufferevent_renegotiate_socketpair_dirty_shutdown",
regress_bufferevent_openssl,
TT_ISOLATED,
&basic_setup,
&ssl_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_RENEGOTIATE | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
{ "bufferevent_renegotiate_filter_dirty_shutdown",
regress_bufferevent_openssl,
TT_ISOLATED,
&basic_setup,
&ssl_setup,
T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_RENEGOTIATE | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
{ "bufferevent_socketpair_startopen_dirty_shutdown",
regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup,
TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_OPEN | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
{ "bufferevent_filter_startopen_dirty_shutdown",
regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup,
TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_OPEN | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
{ "bufferevent_socketpair_fd", regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup,
TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_FD) },
{ "bufferevent_socketpair_freed", regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup,
TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_FREED) },
{ "bufferevent_socketpair_freed_fd", regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup,
TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_FREED | REGRESS_OPENSSL_FD) },
{ "bufferevent_filter_freed_fd", regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup,
TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_FREED | REGRESS_OPENSSL_FD) },
{ "bufferevent_socketpair_timeout", regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup,
TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_TIMEOUT) },
{ "bufferevent_socketpair_timeout_freed_fd", regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup,
TT_ISOLATED, &ssl_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_TIMEOUT | REGRESS_OPENSSL_FREED | REGRESS_OPENSSL_FD) },
{ "bufferevent_connect", regress_bufferevent_openssl_connect,
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
TT_FORK|TT_NEED_BASE, &ssl_setup, NULL },
{ "bufferevent_connect_sleep", regress_bufferevent_openssl_connect,
TT_FORK|TT_NEED_BASE, &basic_setup, T(REGRESS_OPENSSL_SLEEP) },
TT_FORK|TT_NEED_BASE, &ssl_setup, T(REGRESS_OPENSSL_SLEEP) },
{ "bufferevent_wm", regress_bufferevent_openssl_wm,
TT_FORK|TT_NEED_BASE, &ssl_setup, NULL },
{ "bufferevent_wm_filter", regress_bufferevent_openssl_wm,
TT_FORK|TT_NEED_BASE, &ssl_setup, T(REGRESS_OPENSSL_FILTER) },
{ "bufferevent_wm_defer", regress_bufferevent_openssl_wm,
TT_FORK|TT_NEED_BASE, &ssl_setup, T(REGRESS_DEFERRED_CALLBACKS) },
{ "bufferevent_wm_filter_defer", regress_bufferevent_openssl_wm,
TT_FORK|TT_NEED_BASE, &ssl_setup, T(REGRESS_OPENSSL_FILTER|REGRESS_DEFERRED_CALLBACKS) },
#undef T

View File

@ -1,4 +1,5 @@
/* $NetBSD: regress_thread.c,v 1.5 2017/01/31 23:17:40 christos Exp $ */
/* $NetBSD: regress_thread.c,v 1.6 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
*
@ -31,7 +32,7 @@
#include "event2/event-config.h"
#include <sys/cdefs.h>
__RCSID("$NetBSD: regress_thread.c,v 1.5 2017/01/31 23:17:40 christos Exp $");
__RCSID("$NetBSD: regress_thread.c,v 1.6 2021/04/07 03:36:48 christos Exp $");
#include <sys/types.h>
#include <stdio.h>
@ -571,8 +572,8 @@ end:
;
}
#define TEST(name) \
{ #name, thread_##name, TT_FORK|TT_NEED_THREADS|TT_NEED_BASE, \
#define TEST(name, f) \
{ #name, thread_##name, TT_FORK|TT_NEED_THREADS|TT_NEED_BASE|(f), \
&basic_setup, NULL }
struct testcase_t thread_testcases[] = {
@ -583,7 +584,7 @@ struct testcase_t thread_testcases[] = {
&basic_setup, __UNCONST("forking") },
#endif
#if 0
TEST(conditions_simple),
TEST(conditions_simple, TT_RETRIABLE),
#endif
{ "deferred_cb_skew", thread_deferred_cb_skew,
TT_FORK|TT_NEED_THREADS|TT_OFF_BY_DEFAULT,
@ -592,7 +593,7 @@ struct testcase_t thread_testcases[] = {
/****** XXX TODO FIXME windows seems to be having some timing trouble,
* looking into it now. / ellzey
******/
TEST(no_events),
TEST(no_events, TT_RETRIABLE),
#endif
END_OF_TESTCASES
};

View File

@ -1,4 +1,5 @@
/* $NetBSD: regress_util.c,v 1.3 2017/01/31 23:17:40 christos Exp $ */
/* $NetBSD: regress_util.c,v 1.4 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2009-2012 Nick Mathewson and Niels Provos
*
@ -24,6 +25,10 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** For event_debug() usage/coverage */
#define EVENT_VISIBILITY_WANT_DLLIMPORT
#include "../util-internal.h"
#ifdef _WIN32
@ -34,7 +39,7 @@
#include "event2/event-config.h"
#include <sys/cdefs.h>
__RCSID("$NetBSD: regress_util.c,v 1.3 2017/01/31 23:17:40 christos Exp $");
__RCSID("$NetBSD: regress_util.c,v 1.4 2021/04/07 03:36:48 christos Exp $");
#include <sys/types.h>
@ -211,6 +216,65 @@ regress_ipv6_parse(void *ptr)
#endif
}
static struct ipv6_entry_scope {
const char *addr;
ev_uint32_t res[4];
unsigned scope;
enum entry_status status;
} ipv6_entries_scope[] = {
{ "2001:DB8::", { 0x20010db8, 0, 0 }, 0, NORMAL },
{ "2001:DB8::%0", { 0x20010db8, 0, 0, 0 }, 0, NORMAL },
{ "2001:DB8::%1", { 0x20010db8, 0, 0, 0 }, 1, NORMAL },
{ "foobar.", { 0, 0, 0, 0 }, 0, BAD },
{ "2001:DB8::%does-not-exist", { 0, 0, 0, 0 }, 0, BAD },
{ NULL, { 0, 0, 0, 0, }, 0, BAD },
};
static void
regress_ipv6_parse_scope(void *ptr)
{
#ifdef AF_INET6
int i, j;
unsigned if_scope;
for (i = 0; ipv6_entries_scope[i].addr; ++i) {
struct ipv6_entry_scope *ent = &ipv6_entries_scope[i];
struct in6_addr in6;
int r;
r = evutil_inet_pton_scope(AF_INET6, ent->addr, &in6,
&if_scope);
if (r == 0) {
if (ent->status != BAD)
TT_FAIL(("%s did not parse, but it's a good address!",
ent->addr));
continue;
}
if (ent->status == BAD) {
TT_FAIL(("%s parsed, but we expected an error", ent->addr));
continue;
}
for (j = 0; j < 4; ++j) {
/* Can't use s6_addr32 here; some don't have it. */
ev_uint32_t u =
((ev_uint32_t)in6.s6_addr[j*4 ] << 24) |
((ev_uint32_t)in6.s6_addr[j*4+1] << 16) |
((ev_uint32_t)in6.s6_addr[j*4+2] << 8) |
((ev_uint32_t)in6.s6_addr[j*4+3]);
if (u != ent->res[j]) {
TT_FAIL(("%s did not parse as expected.", ent->addr));
continue;
}
}
if (if_scope != ent->scope) {
TT_FAIL(("%s did not parse as expected.", ent->addr));
continue;
}
}
#else
TT_BLATHER(("Skipping IPv6 address parsing."));
#endif
}
static struct sa_port_ent {
const char *parse;
int safamily;
@ -925,6 +989,16 @@ end:
;
}
static void
test_EVUTIL_IS_(void *arg)
{
tt_int_op(EVUTIL_ISDIGIT_('0'), ==, 1);
tt_int_op(EVUTIL_ISDIGIT_('a'), ==, 0);
tt_int_op(EVUTIL_ISDIGIT_('\xff'), ==, 0);
end:
;
}
static void
test_evutil_getaddrinfo(void *arg)
{
@ -1121,6 +1195,41 @@ end:
evutil_freeaddrinfo(ai);
}
static void
test_evutil_getaddrinfo_AI_ADDRCONFIG(void *arg)
{
struct evutil_addrinfo *ai = NULL;
struct evutil_addrinfo hints;
int r;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = EVUTIL_AI_PASSIVE|EVUTIL_AI_ADDRCONFIG;
/* IPv4 */
r = evutil_getaddrinfo("127.0.0.1", "80", &hints, &ai);
tt_int_op(r, ==, 0);
tt_assert(ai);
tt_ptr_op(ai->ai_next, ==, NULL);
test_ai_eq(ai, "127.0.0.1:80", SOCK_STREAM, IPPROTO_TCP);
evutil_freeaddrinfo(ai);
ai = NULL;
/* IPv6 */
r = evutil_getaddrinfo("::1", "80", &hints, &ai);
tt_int_op(r, ==, 0);
tt_assert(ai);
tt_ptr_op(ai->ai_next, ==, NULL);
test_ai_eq(ai, "[::1]:80", SOCK_STREAM, IPPROTO_TCP);
evutil_freeaddrinfo(ai);
ai = NULL;
end:
if (ai)
evutil_freeaddrinfo(ai);
}
#ifdef _WIN32
static void
test_evutil_loadsyslib(void *arg)
@ -1416,10 +1525,12 @@ static struct date_rfc1123_case {
{ 1289433600, "Thu, 11 Nov 2010 00:00:00 GMT"},
{ 1323648000, "Mon, 12 Dec 2011 00:00:00 GMT"},
#ifndef _WIN32
#if EVENT__SIZEOF_TIME_T > 4
/** In win32 case we have max "23:59:59 January 18, 2038, UTC" for time32 */
{ 4294967296, "Sun, 07 Feb 2106 06:28:16 GMT"} /* 2^32 */,
/** In win32 case we have max "23:59:59, December 31, 3000, UTC" for time64 */
{253402300799, "Fri, 31 Dec 9999 23:59:59 GMT"} /* long long future no one can imagine */,
#endif /* time_t != 32bit */
{ 1456704000, "Mon, 29 Feb 2016 00:00:00 GMT"} /* leap year */,
#endif
{ 1435708800, "Wed, 01 Jul 2015 00:00:00 GMT"} /* leap second */,
@ -1457,9 +1568,87 @@ end:
;
}
static void
test_evutil_v4addr_is_local(void *arg)
{
struct sockaddr_in sin;
sin.sin_family = AF_INET;
/* we use evutil_inet_pton() here to fill in network-byte order */
#define LOCAL(str, yes) do { \
tt_int_op(evutil_inet_pton(AF_INET, str, &sin.sin_addr), ==, 1); \
tt_int_op(evutil_v4addr_is_local_(&sin.sin_addr), ==, yes); \
} while (0)
/** any */
sin.sin_addr.s_addr = INADDR_ANY;
tt_int_op(evutil_v4addr_is_local_(&sin.sin_addr), ==, 1);
/** loopback */
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
tt_int_op(evutil_v4addr_is_local_(&sin.sin_addr), ==, 1);
LOCAL("127.0.0.1", 1);
LOCAL("127.255.255.255", 1);
LOCAL("121.0.0.1", 0);
/** link-local */
LOCAL("169.254.0.1", 1);
LOCAL("169.254.255.255", 1);
LOCAL("170.0.0.0", 0);
/** Multicast */
LOCAL("224.0.0.0", 1);
LOCAL("239.255.255.255", 1);
LOCAL("240.0.0.0", 0);
end:
;
}
static void
test_evutil_v6addr_is_local(void *arg)
{
struct sockaddr_in6 sin6;
struct in6_addr anyaddr = IN6ADDR_ANY_INIT;
struct in6_addr loopback = IN6ADDR_LOOPBACK_INIT;
sin6.sin6_family = AF_INET6;
#define LOCAL6(str, yes) do { \
tt_int_op(evutil_inet_pton(AF_INET6, str, &sin6.sin6_addr), ==, 1);\
tt_int_op(evutil_v6addr_is_local_(&sin6.sin6_addr), ==, yes); \
} while (0)
/** any */
tt_int_op(evutil_v6addr_is_local_(&anyaddr), ==, 1);
LOCAL6("::0", 1);
/** loopback */
tt_int_op(evutil_v6addr_is_local_(&loopback), ==, 1);
LOCAL6("::1", 1);
/** IPV4 mapped */
LOCAL6("::ffff:0:0", 1);
/** IPv4 translated */
LOCAL6("::ffff:0:0:0", 1);
/** IPv4/IPv6 translation */
LOCAL6("64:ff9b::", 0);
/** Link-local */
LOCAL6("fe80::", 1);
/** Multicast */
LOCAL6("ff00::", 1);
/** Unspecified */
LOCAL6("::", 1);
/** Global Internet */
LOCAL6("2001::", 0);
LOCAL6("2001:4860:4802:32::1b", 0);
end:
;
}
struct testcase_t util_testcases[] = {
{ "ipv4_parse", regress_ipv4_parse, 0, NULL, NULL },
{ "ipv6_parse", regress_ipv6_parse, 0, NULL, NULL },
{ "ipv6_parse_scope", regress_ipv6_parse_scope, 0, NULL, NULL },
{ "sockaddr_port_parse", regress_sockaddr_port_parse, 0, NULL, NULL },
{ "sockaddr_port_format", regress_sockaddr_port_format, 0, NULL, NULL },
{ "sockaddr_predicates", test_evutil_sockaddr_predicates, 0,NULL,NULL },
@ -1472,22 +1661,26 @@ struct testcase_t util_testcases[] = {
{ "upcast", test_evutil_upcast, 0, NULL, NULL },
{ "integers", test_evutil_integers, 0, NULL, NULL },
{ "rand", test_evutil_rand, TT_FORK, NULL, NULL },
{ "EVUTIL_IS_", test_EVUTIL_IS_, 0, NULL, NULL },
{ "getaddrinfo", test_evutil_getaddrinfo, TT_FORK, NULL, NULL },
{ "getaddrinfo_live", test_evutil_getaddrinfo_live, TT_FORK|TT_OFF_BY_DEFAULT, NULL, NULL },
{ "getaddrinfo_AI_ADDRCONFIG", test_evutil_getaddrinfo_AI_ADDRCONFIG, TT_FORK|TT_OFF_BY_DEFAULT, NULL, NULL },
#ifdef _WIN32
{ "loadsyslib", test_evutil_loadsyslib, TT_FORK, NULL, NULL },
#endif
{ "mm_malloc", test_event_malloc, 0, NULL, NULL },
{ "mm_calloc", test_event_calloc, 0, NULL, NULL },
{ "mm_strdup", test_event_strdup, 0, NULL, NULL },
{ "usleep", test_evutil_usleep, 0, NULL, NULL },
{ "usleep", test_evutil_usleep, TT_RETRIABLE, NULL, NULL },
{ "monotonic_res", test_evutil_monotonic_res, 0, &basic_setup, __UNCONST("") },
{ "monotonic_res_precise", test_evutil_monotonic_res, TT_OFF_BY_DEFAULT, &basic_setup, __UNCONST("precise") },
{ "monotonic_res_fallback", test_evutil_monotonic_res, TT_OFF_BY_DEFAULT, &basic_setup, __UNCONST("fallback") },
{ "monotonic_prc", test_evutil_monotonic_prc, 0, &basic_setup, __UNCONST("") },
{ "monotonic_prc_precise", test_evutil_monotonic_prc, 0, &basic_setup, __UNCONST("precise") },
{ "monotonic_prc_precise", test_evutil_monotonic_prc, TT_RETRIABLE, &basic_setup, __UNCONST("precise") },
{ "monotonic_prc_fallback", test_evutil_monotonic_prc, 0, &basic_setup, __UNCONST("fallback") },
{ "date_rfc1123", test_evutil_date_rfc1123, 0, NULL, NULL },
{ "evutil_v4addr_is_local", test_evutil_v4addr_is_local, 0, NULL, NULL },
{ "evutil_v6addr_is_local", test_evutil_v6addr_is_local, 0, NULL, NULL },
END_OF_TESTCASES,
};

View File

@ -1,4 +1,5 @@
/* $NetBSD: tinytest_macros.h,v 1.4 2017/01/31 23:17:40 christos Exp $ */
/* $NetBSD: tinytest_macros.h,v 1.5 2021/04/07 03:36:48 christos Exp $ */
/* tinytest_macros.h -- Copyright 2009-2012 Nick Mathewson
*
* Redistribution and use in source and binary forms, with or without
@ -114,8 +115,8 @@
#define tt_assert_test_fmt_type(a,b,str_test,type,test,printf_type,printf_fmt, \
setup_block,cleanup_block,die_on_fail) \
TT_STMT_BEGIN \
type val1_ = (a); \
type val2_ = (b); \
type val1_ = (type)(a); \
type val2_ = (type)(b); \
int tt_status_ = (test); \
if (!tt_status_ || tinytest_get_verbosity_()>1) { \
printf_type print_; \
@ -159,6 +160,14 @@
tt_assert_test_type(a,b,#a" "#op" "#b,long,(val1_ op val2_), \
"%ld",TT_EXIT_TEST_FUNCTION)
/** To compare SOCKET(windows)/fd */
#define tt_fd_op(a,op,b) do { \
int _a = (int)(a); \
int _b = (int)(b); \
tt_assert_test_type(_a,_b,#a" "#op" "#b,long,(val1_ op val2_), \
"%ld",TT_EXIT_TEST_FUNCTION); \
} while (0)
#define tt_uint_op(a,op,b) \
tt_assert_test_type(a,b,#a" "#op" "#b,unsigned long, \
(val1_ op val2_),"%lu",TT_EXIT_TEST_FUNCTION)

View File

@ -1,4 +1,5 @@
/* $NetBSD: util-internal.h,v 1.4 2017/01/31 23:17:39 christos Exp $ */
/* $NetBSD: util-internal.h,v 1.5 2021/04/07 03:36:48 christos Exp $ */
/*
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
*
@ -51,12 +52,40 @@
extern "C" {
#endif
/* __has_attribute() wrapper */
#ifdef __has_attribute
# define EVUTIL_HAS_ATTRIBUTE __has_attribute
#endif
/** clang 3 __has_attribute misbehaves in some versions */
#if defined(__clang__) && __clang__ == 1
# if defined(__apple_build_version__)
# if __clang_major__ <= 6
# undef EVUTIL_HAS_ATTRIBUTE
# endif
# else /* !__apple_build_version__ */
# if __clang_major__ == 3 && __clang_minor__ >= 2 && __clang_minor__ <= 5
# undef EVUTIL_HAS_ATTRIBUTE
# endif
# endif /* __apple_build_version__ */
#endif /*\ defined(__clang__) && __clang__ == 1 */
#ifndef EVUTIL_HAS_ATTRIBUTE
# define EVUTIL_HAS_ATTRIBUTE(x) 0
#endif
/* If we need magic to say "inline", get it for free internally. */
#ifdef EVENT__inline
#define inline EVENT__inline
#endif
#if defined(EVENT____func__) && !defined(__func__)
#define __func__ EVENT____func__
/* Define to appropriate substitute if compiler doesnt have __func__ */
#if defined(EVENT__HAVE___func__)
# ifndef __func__
# define __func__ __func__
# endif
#elif defined(EVENT__HAVE___FUNCTION__)
# define __func__ __FUNCTION__
#else
# define __func__ __FILE__
#endif
/* A good no-op to use in macro definitions. */
@ -220,19 +249,26 @@ extern "C" {
* when you care about ASCII's notion of character types, because you are about
* to send those types onto the wire.
*/
EVENT2_EXPORT_SYMBOL
int EVUTIL_ISALPHA_(char c);
EVENT2_EXPORT_SYMBOL
int EVUTIL_ISALNUM_(char c);
int EVUTIL_ISSPACE_(char c);
EVENT2_EXPORT_SYMBOL
int EVUTIL_ISDIGIT_(char c);
EVENT2_EXPORT_SYMBOL
int EVUTIL_ISXDIGIT_(char c);
int EVUTIL_ISPRINT_(char c);
int EVUTIL_ISLOWER_(char c);
int EVUTIL_ISUPPER_(char c);
EVENT2_EXPORT_SYMBOL
char EVUTIL_TOUPPER_(char c);
EVENT2_EXPORT_SYMBOL
char EVUTIL_TOLOWER_(char c);
/** Remove all trailing horizontal whitespace (space or tab) from the end of a
* string */
EVENT2_EXPORT_SYMBOL
void evutil_rtrim_lws_(char *);
@ -259,13 +295,16 @@ void evutil_rtrim_lws_(char *);
*/
int evutil_open_closeonexec_(const char *pathname, int flags, unsigned mode);
EVENT2_EXPORT_SYMBOL
int evutil_read_file_(const char *filename, char **content_out, size_t *len_out,
int is_binary);
EVENT2_EXPORT_SYMBOL
int evutil_socket_connect_(evutil_socket_t *fd_ptr, const struct sockaddr *sa, int socklen);
int evutil_socket_finished_connecting_(evutil_socket_t fd);
EVENT2_EXPORT_SYMBOL
int evutil_ersatz_socketpair_(int, int , int, evutil_socket_t[]);
int evutil_resolve_(int family, const char *hostname, struct sockaddr *sa,
@ -290,15 +329,18 @@ struct evutil_weakrand_state {
* attacker can't predict, or which passes strong statistical tests, use the
* evutil_secure_rng* functions instead.
*/
EVENT2_EXPORT_SYMBOL
ev_uint32_t evutil_weakrand_seed_(struct evutil_weakrand_state *state, ev_uint32_t seed);
/* Return a pseudorandom value between 0 and EVUTIL_WEAKRAND_MAX inclusive.
* Updates the state in 'seed' as needed -- this value must be protected by a
* lock.
*/
EVENT2_EXPORT_SYMBOL
ev_int32_t evutil_weakrand_(struct evutil_weakrand_state *seed);
/* Return a pseudorandom value x such that 0 <= x < top. top must be no more
* than EVUTIL_WEAKRAND_MAX. Updates the state in 'seed' as needed -- this
* value must be proteced by a lock */
EVENT2_EXPORT_SYMBOL
ev_int32_t evutil_weakrand_range_(struct evutil_weakrand_state *seed, ev_int32_t top);
/* Evaluates to the same boolean value as 'p', and hints to the compiler that
@ -309,6 +351,12 @@ ev_int32_t evutil_weakrand_range_(struct evutil_weakrand_state *seed, ev_int32_t
#define EVUTIL_UNLIKELY(p) (p)
#endif
#if EVUTIL_HAS_ATTRIBUTE(fallthrough) && !defined(__lint__) // XXX: fixme
#define EVUTIL_FALLTHROUGH __attribute__((fallthrough))
#else
#define EVUTIL_FALLTHROUGH /* fallthrough */
#endif
/* Replacement for assert() that calls event_errx on failure. */
#ifdef NDEBUG
#define EVUTIL_ASSERT(cond) EVUTIL_NIL_CONDITION_(cond)
@ -358,16 +406,22 @@ typedef struct evdns_getaddrinfo_request* (*evdns_getaddrinfo_fn)(
const char *nodename, const char *servname,
const struct evutil_addrinfo *hints_in,
void (*cb)(int, struct evutil_addrinfo *, void *), void *arg);
EVENT2_EXPORT_SYMBOL
void evutil_set_evdns_getaddrinfo_fn_(evdns_getaddrinfo_fn fn);
typedef void (*evdns_getaddrinfo_cancel_fn)(
struct evdns_getaddrinfo_request *req);
EVENT2_EXPORT_SYMBOL
void evutil_set_evdns_getaddrinfo_cancel_fn_(evdns_getaddrinfo_cancel_fn fn);
EVENT2_EXPORT_SYMBOL
struct evutil_addrinfo *evutil_new_addrinfo_(struct sockaddr *sa,
ev_socklen_t socklen, const struct evutil_addrinfo *hints);
EVENT2_EXPORT_SYMBOL
struct evutil_addrinfo *evutil_addrinfo_append_(struct evutil_addrinfo *first,
struct evutil_addrinfo *append);
EVENT2_EXPORT_SYMBOL
void evutil_adjust_hints_for_addrconfig_(struct evutil_addrinfo *hints);
EVENT2_EXPORT_SYMBOL
int evutil_getaddrinfo_common_(const char *nodename, const char *servname,
struct evutil_addrinfo *hints, struct evutil_addrinfo **res, int *portnum);
@ -380,6 +434,7 @@ void evutil_getaddrinfo_cancel_async_(struct evdns_getaddrinfo_request *data);
/** Return true iff sa is a looback address. (That is, it is 127.0.0.1/8, or
* ::1). */
EVENT2_EXPORT_SYMBOL
int evutil_sockaddr_is_loopback_(const struct sockaddr *sa);
@ -388,6 +443,7 @@ int evutil_sockaddr_is_loopback_(const struct sockaddr *sa);
Returns a pointer to out. Always writes something into out, so it's safe
to use the output of this function without checking it for NULL.
*/
EVENT2_EXPORT_SYMBOL
const char *evutil_format_sockaddr_port_(const struct sockaddr *sa, char *out, size_t outlen);
int evutil_hex_char_to_int_(char c);
@ -397,6 +453,7 @@ void evutil_free_secure_rng_globals_(void);
void evutil_free_globals_(void);
#ifdef _WIN32
EVENT2_EXPORT_SYMBOL
HMODULE evutil_load_windows_system_library_(const TCHAR *library_name);
#endif
@ -445,6 +502,7 @@ HMODULE evutil_load_windows_system_library_(const TCHAR *library_name);
#endif
#endif
EVENT2_EXPORT_SYMBOL
evutil_socket_t evutil_socket_(int domain, int type, int protocol);
evutil_socket_t evutil_accept4_(evutil_socket_t sockfd, struct sockaddr *addr,
ev_socklen_t *addrlen, int flags);
@ -477,6 +535,17 @@ evutil_socket_t evutil_eventfd_(unsigned initval, int flags);
void evutil_memclear_(void *mem, size_t len);
struct in_addr;
struct in6_addr;
/* This is a any, loopback, link-local, multicast */
EVENT2_EXPORT_SYMBOL
int evutil_v4addr_is_local_(const struct in_addr *in);
/* This is a reserved, ipv4compat, ipv4map, loopback,
* link-local, multicast, or unspecified address. */
EVENT2_EXPORT_SYMBOL
int evutil_v6addr_is_local_(const struct in6_addr *in);
#ifdef __cplusplus
}
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: event-config.h,v 1.4 2017/02/01 01:15:34 christos Exp $ */
/* $NetBSD: event-config.h,v 1.5 2021/04/07 03:36:48 christos Exp $ */
/* event2/event-config.h
*
* This file was generated by autoconf when libevent was built, and post-
@ -25,11 +25,17 @@
/* #undef EVENT__DISABLE_THREAD_SUPPORT */
/* Define to 1 if you have the `accept4' function. */
/* #undef EVENT__HAVE_ACCEPT4 */
#define EVENT__HAVE_ACCEPT4 1
/* Define to 1 if you have the <afunix.h> header file. */
/* #undef EVENT__HAVE_AFUNIX_H */
/* Define to 1 if you have the `arc4random' function. */
#define EVENT__HAVE_ARC4RANDOM 1
/* Define to 1 if you have the `arc4random_addrandom' function. */
#define EVENT__HAVE_ARC4RANDOM_ADDRANDOM 1
/* Define to 1 if you have the `arc4random_buf' function. */
#define EVENT__HAVE_ARC4RANDOM_BUF 1
@ -47,14 +53,6 @@
don't. */
#define EVENT__HAVE_DECL_KERN_ARND 1
/* Define to 1 if you have the declaration of `KERN_RANDOM', and to 0 if you
don't. */
#define EVENT__HAVE_DECL_KERN_RANDOM 0
/* Define to 1 if you have the declaration of `RANDOM_UUID', and to 0 if you
don't. */
#define EVENT__HAVE_DECL_RANDOM_UUID 0
/* Define if /dev/poll is available */
/* #undef EVENT__HAVE_DEVPOLL */
@ -73,9 +71,6 @@
/* Define to 1 if you have the <errno.h> header file. */
#define EVENT__HAVE_ERRNO_H 1
/* Define to 1 if you have ERR_remove_thread_stat(). */
#define EVENT__HAVE_ERR_REMOVE_THREAD_STATE 1
/* Define to 1 if you have the `eventfd' function. */
/* #undef EVENT__HAVE_EVENTFD */
@ -121,6 +116,9 @@
/* Define to 1 if you have the `getprotobynumber' function. */
#define EVENT__HAVE_GETPROTOBYNUMBER 1
/* Define to 1 if you have the `getrandom' function. */
#define EVENT__HAVE_GETRANDOM 1
/* Define to 1 if you have the `getservbyname' function. */
#define EVENT__HAVE_GETSERVBYNAME 1
@ -145,12 +143,18 @@
/* Define to 1 if you have the `kqueue' function. */
#define EVENT__HAVE_KQUEUE 1
/* Define to 1 if you have the `ws2_32' library (-lws2_32). */
/* #undef EVENT__HAVE_LIBWS2_32 */
/* Define if the system has zlib */
#define EVENT__HAVE_LIBZ 1
/* Define to 1 if you have the `mach_absolute_time' function. */
/* #undef EVENT__HAVE_MACH_ABSOLUTE_TIME */
/* Define to 1 if you have the <mach/mach.h> header file. */
/* #undef EVENT__HAVE_MACH_MACH_H */
/* Define to 1 if you have the <mach/mach_time.h> header file. */
/* #undef EVENT__HAVE_MACH_MACH_TIME_H */
@ -178,6 +182,9 @@
/* Define if the system has openssl */
#define EVENT__HAVE_OPENSSL 1
/* Define to 1 if you have the <openssl/ssl.h> header file. */
#define EVENT__HAVE_OPENSSL_SSL_H 1
/* Define to 1 if you have the `pipe' function. */
#define EVENT__HAVE_PIPE 1
@ -274,6 +281,9 @@
/* Define to 1 if `s6_addr32' is a member of `struct in6_addr'. */
/* #undef EVENT__HAVE_STRUCT_IN6_ADDR_S6_ADDR32 */
/* Define to 1 if the system has the type `struct linger'. */
#define EVENT__HAVE_STRUCT_LINGER 1
/* Define to 1 if the system has the type `struct sockaddr_in6'. */
#define EVENT__HAVE_STRUCT_SOCKADDR_IN6 1
@ -292,8 +302,8 @@
/* Define to 1 if `__ss_family' is a member of `struct sockaddr_storage'. */
/* #undef EVENT__HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY */
/* Define to 1 if the system has the type `struct so_linger'. */
/* #undef EVENT__HAVE_STRUCT_SO_LINGER */
/* Define to 1 if the system has the type `struct sockaddr_un'. */
#define EVENT__HAVE_STRUCT_SOCKADDR_UN 1
/* Define to 1 if you have the `sysctl' function. */
#define EVENT__HAVE_SYSCTL 1
@ -322,6 +332,9 @@
/* Define to 1 if you have the <sys/queue.h> header file. */
#define EVENT__HAVE_SYS_QUEUE_H 1
/* Define to 1 if you have the <sys/random.h> header file. */
#define EVENT__HAVE_SYS_RANDOM_H 1
/* Define to 1 if you have the <sys/resource.h> header file. */
#define EVENT__HAVE_SYS_RESOURCE_H 1
@ -352,6 +365,9 @@
/* Define to 1 if you have the <sys/uio.h> header file. */
#define EVENT__HAVE_SYS_UIO_H 1
/* Define to 1 if you have the <sys/un.h> header file. */
#define EVENT__HAVE_SYS_UN_H 1
/* Define to 1 if you have the <sys/wait.h> header file. */
#define EVENT__HAVE_SYS_WAIT_H 1
@ -403,20 +419,29 @@
/* Define to 1 if you have the `vasprintf' function. */
#define EVENT__HAVE_VASPRINTF 1
/* Define if waitpid() supports WNOWAIT */
#define EVENT__HAVE_WAITPID_WITH_WNOWAIT 1
/* Define if kqueue works correctly with pipes */
#define EVENT__HAVE_WORKING_KQUEUE 1
/* Define to 1 if you have the <zlib.h> header file. */
#define EVENT__HAVE_ZLIB_H 1
/* Define to 1 if you have the `_gmtime64' function. */
/* #undef EVENT__HAVE__GMTIME64 */
/* Define to 1 if you have the `_gmtime64_s' function. */
/* #undef EVENT__HAVE__GMTIME64_S */
/* Define to 1 if compiler have __FUNCTION__ */
#define EVENT__HAVE___FUNCTION__ 1
/* Define to 1 if compiler have __func__ */
#define EVENT__HAVE___func__ 1
/* Define to the sub-directory where libtool stores uninstalled libraries. */
#define EVENT__LT_OBJDIR ".libs/"
/* Numeric representation of the version */
#define EVENT__NUMERIC_VERSION 0x02010800
#define EVENT__NUMERIC_VERSION 0x02010c00
/* Name of package */
#define EVENT__PACKAGE "libevent"
@ -428,7 +453,7 @@
#define EVENT__PACKAGE_NAME "libevent"
/* Define to the full name and version of this package. */
#define EVENT__PACKAGE_STRING "libevent 2.1.8-stable"
#define EVENT__PACKAGE_STRING "libevent 2.1.12-stable"
/* Define to the one symbol short name of this package. */
#define EVENT__PACKAGE_TARNAME "libevent"
@ -437,7 +462,7 @@
#define EVENT__PACKAGE_URL ""
/* Define to the version of this package. */
#define EVENT__PACKAGE_VERSION "2.1.8-stable"
#define EVENT__PACKAGE_VERSION "2.1.12-stable"
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
@ -476,6 +501,9 @@
#define EVENT__SIZEOF_SIZE_T 4
#endif
/* The size of `time_t', as computed by sizeof. */
#define EVENT__SIZEOF_TIME_T 8
/* The size of `void *', as computed by sizeof. */
#ifdef _LP64
#define EVENT__SIZEOF_VOID_P 8
@ -484,79 +512,76 @@
#endif
/* Define to 1 if you have the ANSI C header files. */
#define EVENT__STDC_HEADERS 1
#define STDC_HEADERS 1
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#define EVENT__TIME_WITH_SYS_TIME 1
/* Enable extensions on AIX 3, Interix. */
#ifndef EVENT___ALL_SOURCE
# define EVENT___ALL_SOURCE 1
#ifndef _ALL_SOURCE
# define _ALL_SOURCE 1
#endif
/* Enable GNU extensions on systems that have them. */
#ifndef EVENT___GNU_SOURCE
# define EVENT___GNU_SOURCE 1
#ifndef _GNU_SOURCE
# define _GNU_SOURCE 1
#endif
/* Enable threading extensions on Solaris. */
#ifndef EVENT___POSIX_PTHREAD_SEMANTICS
# define EVENT___POSIX_PTHREAD_SEMANTICS 1
#ifndef _POSIX_PTHREAD_SEMANTICS
# define _POSIX_PTHREAD_SEMANTICS 1
#endif
/* Enable extensions on HP NonStop. */
#ifndef EVENT___TANDEM_SOURCE
# define EVENT___TANDEM_SOURCE 1
#ifndef _TANDEM_SOURCE
# define _TANDEM_SOURCE 1
#endif
/* Enable general extensions on Solaris. */
#ifndef EVENT____EXTENSIONS__
# define EVENT____EXTENSIONS__ 1
#ifndef __EXTENSIONS__
# define __EXTENSIONS__ 1
#endif
/* Version number of package */
#define EVENT__VERSION "2.1.8-stable"
#define EVENT__VERSION "2.1.12-stable"
/* Enable large inode numbers on Mac OS X 10.5. */
#ifndef EVENT___DARWIN_USE_64_BIT_INODE
# define EVENT___DARWIN_USE_64_BIT_INODE 1
#ifndef _DARWIN_USE_64_BIT_INODE
# define _DARWIN_USE_64_BIT_INODE 1
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
/* #undef EVENT___FILE_OFFSET_BITS */
/* #undef _FILE_OFFSET_BITS */
/* Define for large files, on AIX-style hosts. */
/* #undef EVENT___LARGE_FILES */
/* #undef _LARGE_FILES */
/* Define to 1 if on MINIX. */
/* #undef EVENT___MINIX */
/* #undef _MINIX */
/* Define to 2 if the system does not provide POSIX.1 features except with
this defined. */
/* #undef EVENT___POSIX_1_SOURCE */
/* #undef _POSIX_1_SOURCE */
/* Define to 1 if you need to in order for `stat' and other things to work. */
/* #undef EVENT___POSIX_SOURCE */
/* Define to appropriate substitue if compiler doesnt have __func__ */
/* #undef EVENT____func__ */
/* #undef _POSIX_SOURCE */
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef EVENT__const */
/* #undef const */
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef EVENT____cplusplus
/* #undef EVENT__inline */
#ifndef __cplusplus
/* #undef inline */
#endif
/* Define to `int' if <sys/types.h> does not define. */
/* #undef EVENT__pid_t */
/* #undef pid_t */
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef EVENT__size_t */
/* #undef size_t */
/* Define to unsigned int if you dont have it */
/* #undef EVENT__socklen_t */
/* #undef socklen_t */
/* Define to `int' if <sys/types.h> does not define. */
/* #undef EVENT__ssize_t */
/* #undef ssize_t */
#endif /* event2/event-config.h */

View File

@ -1,5 +1,5 @@
#!/bin/sh
# $NetBSD: libevent2netbsd,v 1.2 2015/01/29 07:26:02 spz Exp $
# $NetBSD: libevent2netbsd,v 1.3 2021/04/07 03:36:48 christos Exp $
# Extract the new tarball and rename the libevent-X.Y.Z directory
# to dist. Run this script and check for additional files and
@ -88,6 +88,7 @@ for f in $(grep -RL '\$NetBSD.*\$' $d include | grep -v CVS); do
*.c)
sed -e '1i\
/* \$NetBSD\$ */
' -e '/#include "event2\/event-config.h"/ {
a\
#include <sys/cdefs.h>\