Generally, LIST_ can be a little faster than TAILQ_ for most
operations. We only need to use TAILQ_ when we care about traversing
lists from tail-to-head, or we need to be able to add items to the end
of the list.
Once, for reasons that made sense at the time, we had evdns.c use its
own logging subsystem with two levels, "warn" and "debug". This leads
to problems, since setting a log handler for Libevent wouldn't actually
trap these messages, since they weren't on by default, and since some of
the warns should really be msgs.
This patch changes the default behavior of evdns.c to log to
event_(debugx,warnx,msgx) by default, and adds a new (internal-use-only)
log level of EVDNS_LOG_MSG. Programs that set a evdns logging
function will see no change. Programs that don't will now see evdns
warnings reported like other warnings.
These were introduced and deprecated in the same version (2.0.1-alpha),
presumably in two-stage process. Everybody sane should be using
evsignal_assign() and evsignal_new() instead.
The different bufferevent implementations had different behavior for
their timeouts. Some of them kept re-triggering the timeouts
indefinitely; some disabled the event immediately the first time a
timeout triggered. Some of them made the timeouts only count when
the bufferevent was actively trying to read or write; some did not.
The new behavior is modeled after old socket bufferevents, since
they were here first and their behavior is relatively sane.
Basically, each timeout disables the bufferevent's corresponding
read or write operation when it fires. Timeouts are stopped
whenever we suspend writing or reading, and reset whenever we
unsuspend writing or reading. Calling bufferevent_enable resets a
timeout, as does changing the timeout value.
Previously, evdns was at the mercy of the user for providing a good
entropy source; without one, it would be vulnerable to various
active attacks.
This patch adds a port of OpenBSD's arc4random() calls to Libevent
[port by Chris Davis], and wraps it up a little bit so we can use it
more safely.
The 'flags' argument made sense when passed to
evdns_(base_)?parse_resolv_conf when it said which parts of the
resolv.conf file to obey. But for evdns_set_option(), it was really
silly, since you wouldn't be calling evdns_set_option() unless you
actually wanted to set the option. Its meaning was basically, "set
this to DNS_OPTIONS_ALL unless you want a funny surprise."
evdns_base_set_option was new in 2.0.1-alpha, so we aren't committed
to keeping it source-compatible.
when sending chunked requests via multiple calls to evhttp_send_reply_chunk,
the client may close the connection before the server is done sending. this
used to cause a crash.
we introduce a new function evhttp_request_get_connection() that allows the
server to determine if the request is still associated with a connection.
If it's not, evhttp_request_free() needs to be called explicitly or the user
can call evhttp_send_reply_end() which just frees the request, too.
We need these for Tor, and other projects probably need them too. Uses
include:
- Checking whether bandwidth is mostly-used, and only taking some
actions when there's plenty of bandwidth.
- Deducting some non-bufferevent activities from a rate-limit group.
It turns out that absolutely everything that was including
windows.h was doing so needlessly; our headers don't need it,
so we should just include winsock2.h (since that's where
struct timeval is defined).
Pre-2.0 code will use the old headers, which include windows.h
for them, so we aren't breaking source compatibility with 1.4.
This solves the bug where we were leaving WIN32_LEAN_AND_MEAN
defined, in roughly the same way that buying an automobile
solves the question of what to give your coachman for boxing
day.
This was never supposed to be an exposed API, so its name should have been
more like _EVUTIL_CHECK_FMT. But it was only used in one place, so let's
just eliminate it.
These are old aliases for event_get_fd and event_get_signal, and they
haven't been the preferred way of doing things since 2.0.1-alpha.
For a while, we made them use struct event if it was included, but call
event_get_(fd|signal) if it wasn't. This was entirely too cute.
We already emulate most of the other useful bits of stdint.h, and
we seem to have started to use uintptr_t in a few places throughout
the code. Let's make sure we can continue to do so even on backwards
platforms that don't do C99.
Right now it only catches cases where we aren't initializing events,
or where we are re-initializing events without deleting them first.
These are however shockingly common.
Nothing in evrpc.c was using rpc_compat.h, so it's best to take it
out, especially since it polluted our build process with GCC variadic
macros.
While we're at it, this patch puts an extra restriction on when the
variadic macros in rpc_compat.h are defined. Not only must GCC be the
compiler, but GCC must not be running in -ansi mode.
Most of these should be unable to fail, since adding a timeout
generally always works. Still, it's better not to try to be "too
smart for our own good here."
There are some remaining event_add() calls that I didn't add checks
for; I've marked those with "XXXX" comments.
Once event_assign() or event_new() had been called, there was no way
to get at a copy of the event's callback, callback argument, or
configured events. This patch adds an accessor function for each, and
an all-fields accessor for code that wants to re-assign one field of
an event.
This patch also adds a function to return sizeof(struct event), so
that code with intense RAM needs can still retain ABI compatibility
between versions of Libevent without having to heap-allocate every
struct event individually.
The code here was first proposed by Pavel Pisa.
This was as simple as using bufferevent_connect_hostname instead of
calling connect() ourself, which already knows how to use an
evdns_base if it gets one.
Untangling the bind code might be a little trickier.
The regular blocking evutil_getaddrinfo() already supported /etc/hosts
by falling back to getaddrinfo() or gethostbyname(). But
evdns_getaddrinfo() had no such facility. Now it does.
The data structure here isn't very clever. I guess people with huge
/etc/hosts files will either need to get out of the 1980s, or submit a
patch to this code so that it uses a hashtable instead of a linked
list.
Includes basic unit tests.
When we decide that a nameserver is down, we stop sending queries to
it, except to periodically probe it to see if it has come back up.
Our previous probe sechedule was an ad-hoc and hard-wired "10 seconds,
one minute, 5 minues, 15 minutes, 1 hour, 1 hour, 1 hour...". There
was nothing wrong with having it be ad-hoc, but making it hard-wired
served no good purpose.
Now the user can set the initial timeout via a new
"initial-probe-timeout:" option; future timeouts back off by a factor
of 3 on every failure to a maximum of 1 hour.
As a side-benefit, this lets us cut the runtime of the dns/retry test
from about 40 seconds to about 3 seconds. Faster unit tests are
always a good thing.
The fairness algorithms are not the best, not every bufferevent type
is supported, and some of the locking tricks here are simply absurd.
Still, this code should be a good first step.
Previously, there was no good way to request different kinds of lock
(say, read/write vs writeonly or recursive vs nonrecursive), or for a
lock function to signal failure (which would be important for a
trylock mode).
This patch revises the lock API to be a bit more useful. The older
lock calls are still supported for now.
We also add a debugging mode to catch common errors in using the
locking APIs.