summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Smith <brad@cvs.openbsd.org>2008-05-02 06:09:12 +0000
committerBrad Smith <brad@cvs.openbsd.org>2008-05-02 06:09:12 +0000
commitaca1b177e06cca0f06297751ac178ab96e04ae4f (patch)
tree40ed096e545ca29b466eb9e383e5d548f4a090ff
parent0a4d9575993ffee6da26d8e1d2569a946fce5f41 (diff)
Update to libevent 1.3e while retaining our local changes.
"No objection" millert@ "the diff looks and works fine" reyk@
-rw-r--r--lib/libevent/buffer.c22
-rw-r--r--lib/libevent/evdns.c802
-rw-r--r--lib/libevent/evdns.h6
-rw-r--r--lib/libevent/event-internal.h7
-rw-r--r--lib/libevent/event.38
-rw-r--r--lib/libevent/event.c173
-rw-r--r--lib/libevent/event.h45
-rw-r--r--lib/libevent/event_tagging.c68
-rw-r--r--lib/libevent/evsignal.h21
-rw-r--r--lib/libevent/kqueue.c34
-rw-r--r--lib/libevent/log.h4
-rw-r--r--lib/libevent/poll.c46
-rw-r--r--lib/libevent/select.c39
-rw-r--r--lib/libevent/shlib_version4
-rw-r--r--lib/libevent/signal.c147
-rw-r--r--regress/lib/libevent/eventtest.c18
16 files changed, 772 insertions, 672 deletions
diff --git a/lib/libevent/buffer.c b/lib/libevent/buffer.c
index 49495545585..264e6df0915 100644
--- a/lib/libevent/buffer.c
+++ b/lib/libevent/buffer.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: buffer.c,v 1.14 2007/03/19 15:12:49 millert Exp $ */
+/* $OpenBSD: buffer.c,v 1.15 2008/05/02 06:09:11 brad Exp $ */
/*
* Copyright (c) 2002, 2003 Niels Provos <provos@citi.umich.edu>
@@ -46,6 +46,7 @@
#include <sys/ioctl.h>
#endif
+#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@@ -136,9 +137,13 @@ evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap)
int sz;
va_list aq;
+ /* make sure that at least some space is available */
+ evbuffer_expand(buf, 64);
for (;;) {
+ size_t used = buf->misalign + buf->off;
buffer = (char *)buf->buffer + buf->off;
- space = buf->totallen - buf->misalign - buf->off;
+ assert(buf->totallen >= used);
+ space = buf->totallen - used;
#ifndef va_copy
#define va_copy(dst, src) memcpy(&(dst), &(src), sizeof(va_list))
@@ -154,7 +159,7 @@ evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap)
va_end(aq);
- if (sz == -1)
+ if (sz < 0)
return (-1);
if (sz < space) {
buf->off += sz;
@@ -246,7 +251,7 @@ evbuffer_readline(struct evbuffer *buffer)
/* Adds data to an event buffer */
-static inline void
+static void
evbuffer_align(struct evbuffer *buf)
{
memmove(buf->orig_buffer, buf->buffer, buf->off);
@@ -433,13 +438,12 @@ evbuffer_write(struct evbuffer *buffer, int fd)
u_char *
evbuffer_find(struct evbuffer *buffer, const u_char *what, size_t len)
{
- size_t remain = buffer->off;
- u_char *search = buffer->buffer;
+ u_char *search = buffer->buffer, *end = search + buffer->off;
u_char *p;
- while ((p = memchr(search, *what, remain)) != NULL) {
- remain = buffer->off - (size_t)(search - buffer->buffer);
- if (remain < len)
+ while (search < end &&
+ (p = memchr(search, *what, end - search)) != NULL) {
+ if (p + len > end)
break;
if (memcmp(p, what, len) == 0)
return (p);
diff --git a/lib/libevent/evdns.c b/lib/libevent/evdns.c
index 6c342a786d4..56d2d4f6a0b 100644
--- a/lib/libevent/evdns.c
+++ b/lib/libevent/evdns.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: evdns.c,v 1.2 2007/03/21 12:26:37 millert Exp $ */
+/* $OpenBSD: evdns.c,v 1.3 2008/05/02 06:09:11 brad Exp $ */
/* The original version of this module was written by Adam Langley; for
* a history of modifications, check out the subversion logs.
@@ -54,7 +54,7 @@
#endif
#endif
-// #define _POSIX_C_SOURCE 200507
+/* #define _POSIX_C_SOURCE 200507 */
#define _GNU_SOURCE
#ifdef DNS_USE_CPU_CLOCK_FOR_ID
@@ -79,7 +79,6 @@
#include <string.h>
#include <fcntl.h>
#include <sys/time.h>
-#include <stdio.h>
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
@@ -121,11 +120,15 @@ typedef int socklen_t;
#define HOST_NAME_MAX 255
#endif
+#ifndef NDEBUG
+#include <stdio.h>
+#endif
+
#undef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#ifdef __USE_ISOC99B
-// libevent doesn't work without this
+/* libevent doesn't work without this */
typedef uint8_t u_char;
typedef unsigned int uint;
#endif
@@ -136,8 +139,8 @@ typedef unsigned int uint;
#define u16 uint16_t
#define u8 uint8_t
-#define MAX_ADDRS 4 // maximum number of addresses from a single packet
-// which we bother recording
+#define MAX_ADDRS 4 /* maximum number of addresses from a single packet */
+/* which we bother recording */
#define TYPE_A EVDNS_TYPE_A
#define TYPE_CNAME 5
@@ -147,29 +150,29 @@ typedef unsigned int uint;
#define CLASS_INET EVDNS_CLASS_INET
struct request {
- u8 *request; // the dns packet data
+ u8 *request; /* the dns packet data */
unsigned int request_len;
int reissue_count;
- int tx_count; // the number of times that this packet has been sent
- unsigned int request_type; // TYPE_PTR or TYPE_A
- void *user_pointer; // the pointer given to us for this request
+ int tx_count; /* the number of times that this packet has been sent */
+ unsigned int request_type; /* TYPE_PTR or TYPE_A */
+ void *user_pointer; /* the pointer given to us for this request */
evdns_callback_type user_callback;
- struct nameserver *ns; // the server which we last sent it
+ struct nameserver *ns; /* the server which we last sent it */
- // elements used by the searching code
+ /* elements used by the searching code */
int search_index;
struct search_state *search_state;
- char *search_origname; // needs to be free()ed
+ char *search_origname; /* needs to be free()ed */
int search_flags;
- // these objects are kept in a circular list
+ /* these objects are kept in a circular list */
struct request *next, *prev;
struct event timeout_event;
- u16 trans_id; // the transaction id
- char request_appended; // true if the request pointer is data which follows this struct
- char transmit_me; // needs to be transmitted
+ u16 trans_id; /* the transaction id */
+ char request_appended; /* true if the request pointer is data which follows this struct */
+ char transmit_me; /* needs to be transmitted */
};
#ifndef HAVE_STRUCT_IN6_ADDR
@@ -197,115 +200,113 @@ struct reply {
};
struct nameserver {
- int socket; // a connected UDP socket
+ int socket; /* a connected UDP socket */
u32 address;
- int failed_times; // number of times which we have given this server a chance
- int timedout; // number of times in a row a request has timed out
+ int failed_times; /* number of times which we have given this server a chance */
+ int timedout; /* number of times in a row a request has timed out */
struct event event;
- // these objects are kept in a circular list
+ /* these objects are kept in a circular list */
struct nameserver *next, *prev;
- struct event timeout_event; // used to keep the timeout for
- // when we next probe this server.
- // Valid if state == 0
- char state; // zero if we think that this server is down
- char choked; // true if we have an EAGAIN from this server's socket
- char write_waiting; // true if we are waiting for EV_WRITE events
+ struct event timeout_event; /* used to keep the timeout for */
+ /* when we next probe this server. */
+ /* Valid if state == 0 */
+ char state; /* zero if we think that this server is down */
+ char choked; /* true if we have an EAGAIN from this server's socket */
+ char write_waiting; /* true if we are waiting for EV_WRITE events */
};
static struct request *req_head = NULL, *req_waiting_head = NULL;
static struct nameserver *server_head = NULL;
-// Represents a local port where we're listening for DNS requests. Right now,
-// only UDP is supported.
+/* Represents a local port where we're listening for DNS requests. Right now, */
+/* only UDP is supported. */
struct evdns_server_port {
- int socket; // socket we use to read queries and write replies.
- int refcnt; // reference count.
- char choked; // Are we currently blocked from writing?
- char closing; // Are we trying to close this port, pending writes?
- evdns_request_callback_fn_type user_callback; // Fn to handle requests
- void *user_data; // Opaque pointer passed to user_callback
- struct event event; // Read/write event
- // circular list of replies that we want to write.
+ int socket; /* socket we use to read queries and write replies. */
+ int refcnt; /* reference count. */
+ char choked; /* Are we currently blocked from writing? */
+ char closing; /* Are we trying to close this port, pending writes? */
+ evdns_request_callback_fn_type user_callback; /* Fn to handle requests */
+ void *user_data; /* Opaque pointer passed to user_callback */
+ struct event event; /* Read/write event */
+ /* circular list of replies that we want to write. */
struct server_request *pending_replies;
};
-// Represents part of a reply being built. (That is, a single RR.)
+/* Represents part of a reply being built. (That is, a single RR.) */
struct server_reply_item {
- struct server_reply_item *next; // next item in sequence.
- char *name; // name part of the RR
- u16 type : 16; // The RR type
- u16 class : 16; // The RR class (usually CLASS_INET)
- u32 ttl; // The RR TTL
- char is_name; // True iff data is a label
- u16 datalen; // Length of data; -1 if data is a label
- void *data; // The contents of the RR
+ struct server_reply_item *next; /* next item in sequence. */
+ char *name; /* name part of the RR */
+ u16 type : 16; /* The RR type */
+ u16 class : 16; /* The RR class (usually CLASS_INET) */
+ u32 ttl; /* The RR TTL */
+ char is_name; /* True iff data is a label */
+ u16 datalen; /* Length of data; -1 if data is a label */
+ void *data; /* The contents of the RR */
};
-// Represents a request that we've received as a DNS server, and holds
-// the components of the reply as we're constructing it.
+/* Represents a request that we've received as a DNS server, and holds */
+/* the components of the reply as we're constructing it. */
struct server_request {
- // Pointers to the next and previous entries on the list of replies
- // that we're waiting to write. Only set if we have tried to respond
- // and gotten EAGAIN.
+ /* Pointers to the next and previous entries on the list of replies */
+ /* that we're waiting to write. Only set if we have tried to respond */
+ /* and gotten EAGAIN. */
struct server_request *next_pending;
struct server_request *prev_pending;
- u16 trans_id; // Transaction id.
- struct evdns_server_port *port; // Which port received this request on?
- struct sockaddr_storage addr; // Where to send the response
- socklen_t addrlen; // length of addr
+ u16 trans_id; /* Transaction id. */
+ struct evdns_server_port *port; /* Which port received this request on? */
+ struct sockaddr_storage addr; /* Where to send the response */
+ socklen_t addrlen; /* length of addr */
- int n_answer; // how many answer RRs have been set?
- int n_authority; // how many authority RRs have been set?
- int n_additional; // how many additional RRs have been set?
+ int n_answer; /* how many answer RRs have been set? */
+ int n_authority; /* how many authority RRs have been set? */
+ int n_additional; /* how many additional RRs have been set? */
- struct server_reply_item *answer; // linked list of answer RRs
- struct server_reply_item *authority; // linked list of authority RRs
- struct server_reply_item *additional; // linked list of additional RRs
+ struct server_reply_item *answer; /* linked list of answer RRs */
+ struct server_reply_item *authority; /* linked list of authority RRs */
+ struct server_reply_item *additional; /* linked list of additional RRs */
- // Constructed response. Only set once we're ready to send a reply.
- // Once this is set, the RR fields are cleared, and no more should be set.
+ /* Constructed response. Only set once we're ready to send a reply. */
+ /* Once this is set, the RR fields are cleared, and no more should be set. */
char *response;
size_t response_len;
- // Caller-visible fields: flags, questions.
+ /* Caller-visible fields: flags, questions. */
struct evdns_server_request base;
};
-// helper macro
+/* helper macro */
#define OFFSET_OF(st, member) ((off_t) (((char*)&((st*)0)->member)-(char*)0))
-// Given a pointer to an evdns_server_request, get the corresponding
-// server_request.
+/* Given a pointer to an evdns_server_request, get the corresponding */
+/* server_request. */
#define TO_SERVER_REQUEST(base_ptr) \
((struct server_request*) \
(((char*)(base_ptr) - OFFSET_OF(struct server_request, base))))
-// The number of good nameservers that we have
+/* The number of good nameservers that we have */
static int global_good_nameservers = 0;
-// inflight requests are contained in the req_head list
-// and are actually going out across the network
+/* inflight requests are contained in the req_head list */
+/* and are actually going out across the network */
static int global_requests_inflight = 0;
-// requests which aren't inflight are in the waiting list
-// and are counted here
+/* requests which aren't inflight are in the waiting list */
+/* and are counted here */
static int global_requests_waiting = 0;
static int global_max_requests_inflight = 64;
-static struct timeval global_timeout = {5, 0}; // 5 seconds
-static int global_max_reissues = 1; // a reissue occurs when we get some errors from the server
-static int global_max_retransmits = 3; // number of times we'll retransmit a request which timed out
-// number of timeouts in a row before we consider this server to be down
+static struct timeval global_timeout = {5, 0}; /* 5 seconds */
+static int global_max_reissues = 1; /* a reissue occurs when we get some errors from the server */
+static int global_max_retransmits = 3; /* number of times we'll retransmit a request which timed out */
+/* number of timeouts in a row before we consider this server to be down */
static int global_max_nameserver_timeout = 3;
-// These are the timeout values for nameservers. If we find a nameserver is down
-// we try to probe it at intervals as given below. Values are in seconds.
+/* These are the timeout values for nameservers. If we find a nameserver is down */
+/* we try to probe it at intervals as given below. Values are in seconds. */
static const struct timeval global_nameserver_timeouts[] = {{10, 0}, {60, 0}, {300, 0}, {900, 0}, {3600, 0}};
static const int global_nameserver_timeouts_length = sizeof(global_nameserver_timeouts)/sizeof(struct timeval);
-static const char *const evdns_error_strings[] = {"no error", "The name server was unable to interpret the query", "The name server suffered an internal error", "The requested domain name does not exist", "The name server refused to reply to the request"};
-
static struct nameserver *nameserver_pick(void);
static void evdns_request_insert(struct request *req, struct request **head);
static void nameserver_ready_callback(int fd, short events, void *arg);
@@ -420,9 +421,9 @@ _evdns_log(int warn, const char *fmt, ...)
#define log _evdns_log
-// This walks the list of inflight requests to find the
-// one with a matching transaction id. Returns NULL on
-// failure
+/* This walks the list of inflight requests to find the */
+/* one with a matching transaction id. Returns NULL on */
+/* failure */
static struct request *
request_find_from_trans_id(u16 trans_id) {
struct request *req = req_head, *const started_at = req_head;
@@ -437,8 +438,8 @@ request_find_from_trans_id(u16 trans_id) {
return NULL;
}
-// a libevent callback function which is called when a nameserver
-// has gone down and we want to test if it has came back to life yet
+/* a libevent callback function which is called when a nameserver */
+/* has gone down and we want to test if it has came back to life yet */
static void
nameserver_prod_callback(int fd, short events, void *arg) {
struct nameserver *const ns = (struct nameserver *) arg;
@@ -448,16 +449,16 @@ nameserver_prod_callback(int fd, short events, void *arg) {
nameserver_send_probe(ns);
}
-// a libevent callback which is called when a nameserver probe (to see if
-// it has come back to life) times out. We increment the count of failed_times
-// and wait longer to send the next probe packet.
+/* a libevent callback which is called when a nameserver probe (to see if */
+/* it has come back to life) times out. We increment the count of failed_times */
+/* and wait longer to send the next probe packet. */
static void
nameserver_probe_failed(struct nameserver *const ns) {
const struct timeval * timeout;
(void) evtimer_del(&ns->timeout_event);
if (ns->state == 1) {
- // This can happen if the nameserver acts in a way which makes us mark
- // it as bad and then starts sending good replies.
+ /* This can happen if the nameserver acts in a way which makes us mark */
+ /* it as bad and then starts sending good replies. */
return;
}
@@ -471,17 +472,17 @@ nameserver_probe_failed(struct nameserver *const ns) {
log(EVDNS_LOG_WARN,
"Error from libevent when adding timer event for %s",
debug_ntoa(ns->address));
- // ???? Do more?
+ /* ???? Do more? */
}
}
-// called when a nameserver has been deemed to have failed. For example, too
-// many packets have timed out etc
+/* called when a nameserver has been deemed to have failed. For example, too */
+/* many packets have timed out etc */
static void
nameserver_failed(struct nameserver *const ns, const char *msg) {
struct request *req, *started_at;
- // if this nameserver has already been marked as failed
- // then don't do anything
+ /* if this nameserver has already been marked as failed */
+ /* then don't do anything */
if (!ns->state) return;
log(EVDNS_LOG_WARN, "Nameserver %s has failed: %s",
@@ -500,15 +501,15 @@ nameserver_failed(struct nameserver *const ns, const char *msg) {
log(EVDNS_LOG_WARN,
"Error from libevent when adding timer event for %s",
debug_ntoa(ns->address));
- // ???? Do more?
+ /* ???? Do more? */
}
- // walk the list of inflight requests to see if any can be reassigned to
- // a different server. Requests in the waiting queue don't have a
- // nameserver assigned yet
+ /* walk the list of inflight requests to see if any can be reassigned to */
+ /* a different server. Requests in the waiting queue don't have a */
+ /* nameserver assigned yet */
- // if we don't have *any* good nameservers then there's no point
- // trying to reassign requests to one
+ /* if we don't have *any* good nameservers then there's no point */
+ /* trying to reassign requests to one */
if (!global_good_nameservers) return;
req = req_head;
@@ -516,8 +517,8 @@ nameserver_failed(struct nameserver *const ns, const char *msg) {
if (req) {
do {
if (req->tx_count == 0 && req->ns == ns) {
- // still waiting to go out, can be moved
- // to another server
+ /* still waiting to go out, can be moved */
+ /* to another server */
req->ns = nameserver_pick();
}
req = req->next;
@@ -543,14 +544,14 @@ request_trans_id_set(struct request *const req, const u16 trans_id) {
*((u16 *) req->request) = htons(trans_id);
}
-// Called to remove a request from a list and dealloc it.
-// head is a pointer to the head of the list it should be
-// removed from or NULL if the request isn't in a list.
+/* Called to remove a request from a list and dealloc it. */
+/* head is a pointer to the head of the list it should be */
+/* removed from or NULL if the request isn't in a list. */
static void
request_finished(struct request *const req, struct request **head) {
if (head) {
if (req->next == req) {
- // only item in the list
+ /* only item in the list */
*head = NULL;
} else {
req->next->prev = req->prev;
@@ -567,11 +568,11 @@ request_finished(struct request *const req, struct request **head) {
global_requests_inflight--;
if (!req->request_appended) {
- // need to free the request data on it's own
+ /* need to free the request data on it's own */
free(req->request);
} else {
- // the request data is appended onto the header
- // so everything gets free()ed when we:
+ /* the request data is appended onto the header */
+ /* so everything gets free()ed when we: */
}
free(req);
@@ -579,23 +580,23 @@ request_finished(struct request *const req, struct request **head) {
evdns_requests_pump_waiting_queue();
}
-// This is called when a server returns a funny error code.
-// We try the request again with another server.
-//
-// return:
-// 0 ok
-// 1 failed/reissue is pointless
+/* This is called when a server returns a funny error code. */
+/* We try the request again with another server. */
+/* */
+/* return: */
+/* 0 ok */
+/* 1 failed/reissue is pointless */
static int
request_reissue(struct request *req) {
const struct nameserver *const last_ns = req->ns;
- // the last nameserver should have been marked as failing
- // by the caller of this function, therefore pick will try
- // not to return it
+ /* the last nameserver should have been marked as failing */
+ /* by the caller of this function, therefore pick will try */
+ /* not to return it */
req->ns = nameserver_pick();
if (req->ns == last_ns) {
- // ... but pick did return it
- // not a lot of point in trying again with the
- // same server
+ /* ... but pick did return it */
+ /* not a lot of point in trying again with the */
+ /* same server */
return 1;
}
@@ -606,17 +607,17 @@ request_reissue(struct request *req) {
return 0;
}
-// this function looks for space on the inflight queue and promotes
-// requests from the waiting queue if it can.
+/* this function looks for space on the inflight queue and promotes */
+/* requests from the waiting queue if it can. */
static void
evdns_requests_pump_waiting_queue(void) {
while (global_requests_inflight < global_max_requests_inflight &&
global_requests_waiting) {
struct request *req;
- // move a request from the waiting queue to the inflight queue
+ /* move a request from the waiting queue to the inflight queue */
assert(req_waiting_head);
if (req_waiting_head->next == req_waiting_head) {
- // only one item in the queue
+ /* only one item in the queue */
req = req_waiting_head;
req_waiting_head = NULL;
} else {
@@ -673,14 +674,14 @@ reply_callback(struct request *const req, u32 ttl, u32 err, struct reply *reply)
assert(0);
}
-// this processes a parsed reply packet
+/* this processes a parsed reply packet */
static void
reply_handle(struct request *const req, u16 flags, u32 ttl, struct reply *reply) {
int error;
static const int error_codes[] = {DNS_ERR_FORMAT, DNS_ERR_SERVERFAILED, DNS_ERR_NOTEXIST, DNS_ERR_NOTIMPL, DNS_ERR_REFUSED};
if (flags & 0x020f || !reply || !reply->have_answer) {
- // there was an error
+ /* there was an error */
if (flags & 0x0200) {
error = DNS_ERR_TRUNCATED;
} else {
@@ -693,10 +694,9 @@ reply_handle(struct request *const req, u16 flags, u32 ttl, struct reply *reply)
}
switch(error) {
- case DNS_ERR_SERVERFAILED:
case DNS_ERR_NOTIMPL:
case DNS_ERR_REFUSED:
- // we regard these errors as marking a bad nameserver
+ /* we regard these errors as marking a bad nameserver */
if (req->reissue_count < global_max_reissues) {
char msg[64];
snprintf(msg, sizeof(msg), "Bad response %d (%s)",
@@ -705,50 +705,59 @@ reply_handle(struct request *const req, u16 flags, u32 ttl, struct reply *reply)
if (!request_reissue(req)) return;
}
break;
+ case DNS_ERR_SERVERFAILED:
+ /* rcode 2 (servfailed) sometimes means "we are broken" and
+ * sometimes (with some binds) means "that request was very
+ * confusing." Treat this as a timeout, not a failure.
+ */
+ log(EVDNS_LOG_DEBUG, "Got a SERVERFAILED from nameserver %s; "
+ "will allow the request to time out.",
+ debug_ntoa(req->ns->address));
+ break;
default:
- // we got a good reply from the nameserver
+ /* we got a good reply from the nameserver */
nameserver_up(req->ns);
}
if (req->search_state && req->request_type != TYPE_PTR) {
- // if we have a list of domains to search in, try the next one
+ /* if we have a list of domains to search in, try the next one */
if (!search_try_next(req)) {
- // a new request was issued so this request is finished and
- // the user callback will be made when that request (or a
- // child of it) finishes.
+ /* a new request was issued so this request is finished and */
+ /* the user callback will be made when that request (or a */
+ /* child of it) finishes. */
request_finished(req, &req_head);
return;
}
}
- // all else failed. Pass the failure up
+ /* all else failed. Pass the failure up */
reply_callback(req, 0, error, NULL);
request_finished(req, &req_head);
} else {
- // all ok, tell the user
+ /* all ok, tell the user */
reply_callback(req, ttl, 0, reply);
nameserver_up(req->ns);
request_finished(req, &req_head);
}
}
-static inline int
+static int
name_parse(u8 *packet, int length, int *idx, char *name_out, int name_out_len) {
int name_end = -1;
int j = *idx;
int ptr_count = 0;
-#define GET32(x) do { if (j + 4 > length) goto err; memcpy(&_t32, packet + j, 4); j += 4; x = ntohl(_t32); } while(0);
-#define GET16(x) do { if (j + 2 > length) goto err; memcpy(&_t, packet + j, 2); j += 2; x = ntohs(_t); } while(0);
-#define GET8(x) do { if (j >= length) goto err; x = packet[j++]; } while(0);
+#define GET32(x) do { if (j + 4 > length) goto err; memcpy(&_t32, packet + j, 4); j += 4; x = ntohl(_t32); } while(0)
+#define GET16(x) do { if (j + 2 > length) goto err; memcpy(&_t, packet + j, 2); j += 2; x = ntohs(_t); } while(0)
+#define GET8(x) do { if (j >= length) goto err; x = packet[j++]; } while(0)
char *cp = name_out;
const char *const end = name_out + name_out_len;
- // Normally, names are a series of length prefixed strings terminated
- // with a length of 0 (the lengths are u8's < 63).
- // However, the length can start with a pair of 1 bits and that
- // means that the next 14 bits are a pointer within the current
- // packet.
+ /* Normally, names are a series of length prefixed strings terminated */
+ /* with a length of 0 (the lengths are u8's < 63). */
+ /* However, the length can start with a pair of 1 bits and that */
+ /* means that the next 14 bits are a pointer within the current */
+ /* packet. */
for(;;) {
u8 label_len;
@@ -788,18 +797,19 @@ name_parse(u8 *packet, int length, int *idx, char *name_out, int name_out_len) {
return -1;
}
-// parses a raw request from a nameserver
+/* parses a raw request from a nameserver */
static int
reply_parse(u8 *packet, int length) {
- int j = 0; // index into packet
- u16 _t; // used by the macros
- u32 _t32; // used by the macros
- char tmp_name[256]; // used by the macros
+ int j = 0; /* index into packet */
+ u16 _t; /* used by the macros */
+ u32 _t32; /* used by the macros */
+ char tmp_name[256]; /* used by the macros */
- u16 trans_id, flags, questions, answers, authority, additional, datalength;
+ u16 trans_id, questions, answers, authority, additional, datalength;
+ u16 flags = 0;
u32 ttl, ttl_r = 0xffffffff;
struct reply reply;
- struct request *req;
+ struct request *req = NULL;
unsigned int i;
GET16(trans_id);
@@ -813,19 +823,18 @@ reply_parse(u8 *packet, int length) {
req = request_find_from_trans_id(trans_id);
if (!req) return -1;
- // XXXX should the other return points also call reply_handle? -NM
memset(&reply, 0, sizeof(reply));
- if (!(flags & 0x8000)) return -1; // must be an answer
+ /* 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) {
- // there was an error
- reply_handle(req, flags, 0, NULL);
- return -1;
+ /* there was an error */
+ goto err;
}
- // if (!answers) return; // must have an answer of some form
+ /* if (!answers) return; */ /* must have an answer of some form */
- // This macro skips a name in the DNS reply.
+ /* This macro skips a name in the DNS reply. */
#define SKIP_NAME \
do { tmp_name[0] = '\0'; \
if (name_parse(packet, length, &j, tmp_name, sizeof(tmp_name))<0) \
@@ -834,17 +843,19 @@ reply_parse(u8 *packet, int length) {
reply.type = req->request_type;
- // skip over each question in the reply
+ /* skip over each question in the reply */
for (i = 0; i < questions; ++i) {
- // the question looks like
- // <label:name><u16:type><u16:class>
+ /* the question looks like
+ * <label:name><u16:type><u16:class>
+ */
SKIP_NAME;
j += 4;
- if (j >= length) return -1;
+ if (j >= length) goto err;
}
- // now we have the answer section which looks like
- // <label:name><u16:type><u16:class><u32:ttl><u16:len><data...>
+ /* now we have the answer section which looks like
+ * <label:name><u16:type><u16:class><u32:ttl><u16:len><data...>
+ */
for (i = 0; i < answers; ++i) {
u16 type, class;
@@ -861,13 +872,13 @@ reply_parse(u8 *packet, int length) {
j += datalength; continue;
}
if ((datalength & 3) != 0) /* not an even number of As. */
- return -1;
+ goto err;
addrcount = datalength >> 2;
addrtocopy = MIN(MAX_ADDRS - reply.data.a.addrcount, (unsigned)addrcount);
ttl_r = MIN(ttl_r, ttl);
- // we only bother with the first four addresses.
- if (j + 4*addrtocopy > length) return -1;
+ /* we only bother with the first four addresses. */
+ if (j + 4*addrtocopy > length) goto err;
memcpy(&reply.data.a.addresses[reply.data.a.addrcount],
packet + j, 4*addrtocopy);
j += 4*addrtocopy;
@@ -880,7 +891,7 @@ reply_parse(u8 *packet, int length) {
}
if (name_parse(packet, length, &j, reply.data.ptr.name,
sizeof(reply.data.ptr.name))<0)
- return -1;
+ goto err;
ttl_r = MIN(ttl_r, ttl);
reply.have_answer = 1;
break;
@@ -890,13 +901,13 @@ reply_parse(u8 *packet, int length) {
j += datalength; continue;
}
if ((datalength & 15) != 0) /* not an even number of AAAAs. */
- return -1;
- addrcount = datalength >> 4; // each address is 16 bytes long
+ goto err;
+ addrcount = datalength >> 4; /* each address is 16 bytes long */
addrtocopy = MIN(MAX_ADDRS - reply.data.aaaa.addrcount, (unsigned)addrcount);
ttl_r = MIN(ttl_r, ttl);
- // we only bother with the first four addresses.
- if (j + 16*addrtocopy > length) return -1;
+ /* we only bother with the first four addresses. */
+ if (j + 16*addrtocopy > length) goto err;
memcpy(&reply.data.aaaa.addresses[reply.data.aaaa.addrcount],
packet + j, 16*addrtocopy);
reply.data.aaaa.addrcount += addrtocopy;
@@ -904,7 +915,7 @@ reply_parse(u8 *packet, int length) {
reply.have_answer = 1;
if (reply.data.aaaa.addrcount == MAX_ADDRS) break;
} else {
- // skip over any other type of resource
+ /* skip over any other type of resource */
j += datalength;
}
}
@@ -912,24 +923,26 @@ reply_parse(u8 *packet, int length) {
reply_handle(req, flags, ttl_r, &reply);
return 0;
err:
+ if (req)
+ reply_handle(req, flags, 0, NULL);
return -1;
}
-// Parse a raw request (packet,length) sent to a nameserver port (port) from
-// a DNS client (addr,addrlen), and if it's well-formed, call the corresponding
-// callback.
+/* Parse a raw request (packet,length) sent to a nameserver port (port) from */
+/* a DNS client (addr,addrlen), and if it's well-formed, call the corresponding */
+/* callback. */
static int
request_parse(u8 *packet, int length, struct evdns_server_port *port, struct sockaddr *addr, socklen_t addrlen)
{
- int j = 0; // index into packet
- u16 _t; // used by the macros
- char tmp_name[256]; // used by the macros
+ int j = 0; /* index into packet */
+ u16 _t; /* used by the macros */
+ char tmp_name[256]; /* used by the macros */
int i;
u16 trans_id, flags, questions, answers, authority, additional;
struct server_request *server_req = NULL;
- // Get the header fields
+ /* Get the header fields */
GET16(trans_id);
GET16(flags);
GET16(questions);
@@ -937,9 +950,9 @@ request_parse(u8 *packet, int length, struct evdns_server_port *port, struct soc
GET16(authority);
GET16(additional);
- if (flags & 0x8000) return -1; // Must not be an answer.
- if (flags & 0x7800) return -1; // only standard queries are supported
- flags &= 0x0300; // Only TC and RD get preserved.
+ if (flags & 0x8000) return -1; /* Must not be an answer. */
+ if (flags & 0x7800) return -1; /* only standard queries are supported */
+ flags &= 0x0300; /* Only TC and RD get preserved. */
server_req = malloc(sizeof(struct server_request));
if (server_req == NULL) return -1;
@@ -973,7 +986,7 @@ request_parse(u8 *packet, int length, struct evdns_server_port *port, struct soc
server_req->base.questions[server_req->base.nquestions++] = q;
}
- // Ignore answers, authority, and additional.
+ /* Ignore answers, authority, and additional. */
server_req->port = port;
port->refcnt++;
@@ -997,7 +1010,7 @@ err:
#undef GET8
}
-// Try to choose a strong transaction id which isn't already in flight
+/* Try to choose a strong transaction id which isn't already in flight */
static u16
transaction_id_pick(void) {
for (;;) {
@@ -1024,8 +1037,8 @@ transaction_id_pick(void) {
#ifdef DNS_USE_OPENSSL_FOR_ID
u16 trans_id;
if (RAND_pseudo_bytes((u8 *) &trans_id, 2) == -1) {
- /* // in the case that the RAND call fails we back
- // down to using gettimeofday.
+ /* in the case that the RAND call fails we back */
+ /* down to using gettimeofday. */
struct timeval tv;
gettimeofday(&tv, NULL);
trans_id = tv.tv_usec & 0xffff; */
@@ -1039,7 +1052,7 @@ transaction_id_pick(void) {
#endif
if (trans_id == 0xffff) continue;
- // now check to see if that id is already inflight
+ /* now check to see if that id is already inflight */
req = started_at = req_head;
if (req) {
do {
@@ -1047,30 +1060,30 @@ transaction_id_pick(void) {
req = req->next;
} while (req != started_at);
}
- // we didn't find it, so this is a good id
+ /* we didn't find it, so this is a good id */
if (req == started_at) return trans_id;
}
}
-// choose a namesever to use. This function will try to ignore
-// nameservers which we think are down and load balance across the rest
-// by updating the server_head global each time.
+/* choose a namesever to use. This function will try to ignore */
+/* nameservers which we think are down and load balance across the rest */
+/* by updating the server_head global each time. */
static struct nameserver *
nameserver_pick(void) {
struct nameserver *started_at = server_head, *picked;
if (!server_head) return NULL;
- // if we don't have any good nameservers then there's no
- // point in trying to find one.
+ /* if we don't have any good nameservers then there's no */
+ /* point in trying to find one. */
if (!global_good_nameservers) {
server_head = server_head->next;
return server_head;
}
- // remember that nameservers are in a circular list
+ /* remember that nameservers are in a circular list */
for (;;) {
if (server_head->state) {
- // we think this server is currently good
+ /* we think this server is currently good */
picked = server_head;
server_head = server_head->next;
return picked;
@@ -1078,9 +1091,9 @@ nameserver_pick(void) {
server_head = server_head->next;
if (server_head == started_at) {
- // all the nameservers seem to be down
- // so we just return this one and hope for the
- // best
+ /* all the nameservers seem to be down */
+ /* so we just return this one and hope for the */
+ /* best */
assert(global_good_nameservers == 0);
picked = server_head;
server_head = server_head->next;
@@ -1089,7 +1102,7 @@ nameserver_pick(void) {
}
}
-// this is called when a namesever socket is ready for reading
+/* this is called when a namesever socket is ready for reading */
static void
nameserver_read(struct nameserver *ns) {
u8 packet[1500];
@@ -1107,8 +1120,8 @@ nameserver_read(struct nameserver *ns) {
}
}
-// Read a packet from a DNS client on a server port s, parse it, and
-// act accordingly.
+/* Read a packet from a DNS client on a server port s, parse it, and */
+/* act accordingly. */
static void
server_port_read(struct evdns_server_port *s) {
u8 packet[1500];
@@ -1131,7 +1144,7 @@ server_port_read(struct evdns_server_port *s) {
}
}
-// Try to write all pending replies on a given DNS server port.
+/* Try to write all pending replies on a given DNS server port. */
static void
server_port_flush(struct evdns_server_port *port)
{
@@ -1146,24 +1159,24 @@ server_port_flush(struct evdns_server_port *port)
log(EVDNS_LOG_WARN, "Error %s (%d) while writing response to port; dropping", strerror(err), err);
}
if (server_request_free(req)) {
- // we released the last reference to req->port.
+ /* we released the last reference to req->port. */
return;
}
}
- // We have no more pending requests; stop listening for 'writeable' events.
+ /* We have no more pending requests; stop listening for 'writeable' events. */
(void) event_del(&port->event);
event_set(&port->event, port->socket, EV_READ | EV_PERSIST,
server_port_ready_callback, port);
if (event_add(&port->event, NULL) < 0) {
log(EVDNS_LOG_WARN, "Error from libevent when adding event for DNS server.");
- // ???? Do more?
+ /* ???? Do more? */
}
}
-// set if we are waiting for the ability to write to this server.
-// if waiting is true then we ask libevent for EV_WRITE events, otherwise
-// we stop these events.
+/* set if we are waiting for the ability to write to this server. */
+/* if waiting is true then we ask libevent for EV_WRITE events, otherwise */
+/* we stop these events. */
static void
nameserver_write_waiting(struct nameserver *ns, char waiting) {
if (ns->write_waiting == waiting) return;
@@ -1175,12 +1188,12 @@ nameserver_write_waiting(struct nameserver *ns, char waiting) {
if (event_add(&ns->event, NULL) < 0) {
log(EVDNS_LOG_WARN, "Error from libevent when adding event for %s",
debug_ntoa(ns->address));
- // ???? Do more?
+ /* ???? Do more? */
}
}
-// a callback function. Called by libevent when the kernel says that
-// a nameserver socket is ready for writing or reading
+/* a callback function. Called by libevent when the kernel says that */
+/* a nameserver socket is ready for writing or reading */
static void
nameserver_ready_callback(int fd, short events, void *arg) {
struct nameserver *ns = (struct nameserver *) arg;
@@ -1197,8 +1210,8 @@ nameserver_ready_callback(int fd, short events, void *arg) {
}
}
-// a callback function. Called by libevent when the kernel says that
-// a server socket is ready for writing or reading.
+/* a callback function. Called by libevent when the kernel says that */
+/* a server socket is ready for writing or reading. */
static void
server_port_ready_callback(int fd, short events, void *arg) {
struct evdns_server_port *port = (struct evdns_server_port *) arg;
@@ -1216,22 +1229,22 @@ server_port_ready_callback(int fd, short events, void *arg) {
/* This is an inefficient representation; only use it via the dnslabel_table_*
* functions, so that is can be safely replaced with something smarter later. */
#define MAX_LABELS 128
-// Structures used to implement name compression
-struct dnslabel_entry { char *v; int pos; };
+/* Structures used to implement name compression */
+struct dnslabel_entry { char *v; off_t pos; };
struct dnslabel_table {
- int n_labels; // number of current entries
- // map from name to position in message
+ int n_labels; /* number of current entries */
+ /* map from name to position in message */
struct dnslabel_entry labels[MAX_LABELS];
};
-// Initialize dnslabel_table.
+/* Initialize dnslabel_table. */
static void
dnslabel_table_init(struct dnslabel_table *table)
{
table->n_labels = 0;
}
-// Free all storage held by table, but not the table itself.
+/* Free all storage held by table, but not the table itself. */
static void
dnslabel_clear(struct dnslabel_table *table)
{
@@ -1241,8 +1254,8 @@ dnslabel_clear(struct dnslabel_table *table)
table->n_labels = 0;
}
-// return the position of the label in the current message, or -1 if the label
-// hasn't been used yet.
+/* return the position of the label in the current message, or -1 if the label */
+/* hasn't been used yet. */
static int
dnslabel_table_get_pos(const struct dnslabel_table *table, const char *label)
{
@@ -1254,9 +1267,9 @@ dnslabel_table_get_pos(const struct dnslabel_table *table, const char *label)
return -1;
}
-// remember that we've used the label at position pos
+/* remember that we've used the label at position pos */
static int
-dnslabel_table_add(struct dnslabel_table *table, const char *label, int pos)
+dnslabel_table_add(struct dnslabel_table *table, const char *label, off_t pos)
{
char *v;
int p;
@@ -1272,17 +1285,17 @@ dnslabel_table_add(struct dnslabel_table *table, const char *label, int pos)
return (0);
}
-// Converts a string to a length-prefixed set of DNS labels, starting
-// at buf[j]. name and buf must not overlap. name_len should be the length
-// of name. table is optional, and is used for compression.
-//
-// Input: abc.def
-// Output: <3>abc<3>def<0>
-//
-// Returns the first index after the encoded name, or negative on error.
-// -1 label was > 63 bytes
-// -2 name too long to fit in buffer.
-//
+/* Converts a string to a length-prefixed set of DNS labels, starting */
+/* at buf[j]. name and buf must not overlap. name_len should be the length */
+/* of name. table is optional, and is used for compression. */
+/* */
+/* Input: abc.def */
+/* Output: <3>abc<3>def<0> */
+/* */
+/* Returns the first index after the encoded name, or negative on error. */
+/* -1 label was > 63 bytes */
+/* -2 name too long to fit in buffer. */
+/* */
static off_t
dnsname_to_labels(u8 *const buf, size_t buf_len, off_t j,
const char *name, const int name_len,
@@ -1326,7 +1339,7 @@ dnsname_to_labels(u8 *const buf, size_t buf_len, off_t j,
j += end - start;
break;
} else {
- // append length of the label.
+ /* append length of the label. */
const unsigned int label_len = name - start;
if (label_len > 63) return -1;
if ((size_t)(j+label_len+1) > buf_len) return -2;
@@ -1335,47 +1348,47 @@ dnsname_to_labels(u8 *const buf, size_t buf_len, off_t j,
memcpy(buf + j, start, name - start);
j += name - start;
- // hop over the '.'
+ /* hop over the '.' */
name++;
}
}
- // the labels must be terminated by a 0.
- // It's possible that the name ended in a .
- // in which case the zero is already there
+ /* the labels must be terminated by a 0. */
+ /* It's possible that the name ended in a . */
+ /* in which case the zero is already there */
if (!j || buf[j-1]) buf[j++] = 0;
return j;
overflow:
return (-2);
}
-// Finds the length of a dns request for a DNS name of the given
-// length. The actual request may be smaller than the value returned
-// here
+/* Finds the length of a dns request for a DNS name of the given */
+/* length. The actual request may be smaller than the value returned */
+/* here */
static int
evdns_request_len(const int name_len) {
- return 96 + // length of the DNS standard header
+ return 96 + /* length of the DNS standard header */
name_len + 2 +
- 4; // space for the resource type
+ 4; /* space for the resource type */
}
-// build a dns request packet into buf. buf should be at least as long
-// as evdns_request_len told you it should be.
-//
-// Returns the amount of space used. Negative on error.
+/* build a dns request packet into buf. buf should be at least as long */
+/* as evdns_request_len told you it should be. */
+/* */
+/* Returns the amount of space used. Negative on error. */
static int
evdns_request_data_build(const char *const name, const int name_len,
const u16 trans_id, const u16 type, const u16 class,
u8 *const buf, size_t buf_len) {
- off_t j = 0; // current offset into buf
- u16 _t; // used by the macros
+ off_t j = 0; /* current offset into buf */
+ u16 _t; /* used by the macros */
APPEND16(trans_id);
- APPEND16(0x0100); // standard query, recusion needed
- APPEND16(1); // one question
- APPEND16(0); // no answers
- APPEND16(0); // no authority
- APPEND16(0); // no additional
+ APPEND16(0x0100); /* standard query, recusion needed */
+ APPEND16(1); /* one question */
+ APPEND16(0); /* no answers */
+ APPEND16(0); /* no authority */
+ APPEND16(0); /* no additional */
j = dnsname_to_labels(buf, buf_len, j, name, name_len, NULL);
if (j < 0) {
@@ -1390,7 +1403,7 @@ evdns_request_data_build(const char *const name, const int name_len,
return (-1);
}
-// exported function
+/* exported function */
struct evdns_server_port *
evdns_add_server_port(int socket, int is_tcp, evdns_request_callback_fn_type cb, void *user_data)
{
@@ -1399,7 +1412,7 @@ evdns_add_server_port(int socket, int is_tcp, evdns_request_callback_fn_type cb,
return NULL;
memset(port, 0, sizeof(struct evdns_server_port));
- assert(!is_tcp); // TCP sockets not yet implemented
+ assert(!is_tcp); /* TCP sockets not yet implemented */
port->socket = socket;
port->refcnt = 1;
port->choked = 0;
@@ -1410,11 +1423,11 @@ evdns_add_server_port(int socket, int is_tcp, evdns_request_callback_fn_type cb,
event_set(&port->event, port->socket, EV_READ | EV_PERSIST,
server_port_ready_callback, port);
- event_add(&port->event, NULL); // check return.
+ event_add(&port->event, NULL); /* check return. */
return port;
}
-// exported function
+/* exported function */
void
evdns_close_server_port(struct evdns_server_port *port)
{
@@ -1423,7 +1436,7 @@ evdns_close_server_port(struct evdns_server_port *port)
port->closing = 1;
}
-// exported function
+/* exported function */
int
evdns_server_request_add_reply(struct evdns_server_request *_req, int section, const char *name, int type, int class, int ttl, int datalen, int is_name, const char *data)
{
@@ -1474,7 +1487,7 @@ evdns_server_request_add_reply(struct evdns_server_request *_req, int section, c
free(item);
return -1;
}
- item->datalen = -1;
+ item->datalen = (u16)-1;
} else {
if (!(item->data = malloc(datalen))) {
free(item->name);
@@ -1491,7 +1504,7 @@ evdns_server_request_add_reply(struct evdns_server_request *_req, int section, c
return 0;
}
-// exported function
+/* exported function */
int
evdns_server_request_add_a_reply(struct evdns_server_request *req, const char *name, int n, void *addrs, int ttl)
{
@@ -1500,7 +1513,7 @@ evdns_server_request_add_a_reply(struct evdns_server_request *req, const char *n
ttl, n*4, 0, addrs);
}
-// exported function
+/* exported function */
int
evdns_server_request_add_aaaa_reply(struct evdns_server_request *req, const char *name, int n, void *addrs, int ttl)
{
@@ -1509,7 +1522,7 @@ evdns_server_request_add_aaaa_reply(struct evdns_server_request *req, const char
ttl, n*16, 0, addrs);
}
-// exported function
+/* exported function */
int
evdns_server_request_add_ptr_reply(struct evdns_server_request *req, struct in_addr *in, const char *inaddr_name, const char *hostname, int ttl)
{
@@ -1531,7 +1544,7 @@ evdns_server_request_add_ptr_reply(struct evdns_server_request *req, struct in_a
ttl, -1, 1, hostname);
}
-// exported function
+/* exported function */
int
evdns_server_request_add_cname_reply(struct evdns_server_request *req, const char *name, const char *cname, int ttl)
{
@@ -1638,7 +1651,7 @@ overflow:
return (0);
}
-// exported function
+/* exported function */
int
evdns_server_request_respond(struct evdns_server_request *_req, int err)
{
@@ -1681,13 +1694,13 @@ evdns_server_request_respond(struct evdns_server_request *_req, int err)
if (server_request_free(req))
return 0;
- if (req->port->pending_replies)
+ if (port->pending_replies)
server_port_flush(port);
return 0;
}
-// Free all storage held by RRs in req.
+/* Free all storage held by RRs in req. */
static void
server_request_free_answers(struct server_request *req)
{
@@ -1707,15 +1720,15 @@ server_request_free_answers(struct server_request *req)
free(victim->name);
if (victim->data)
free(victim->data);
- /* XXXX free(victim?) -NM */
+ free(victim);
victim = next;
}
*list = NULL;
}
}
-// Free all storage held by req, and remove links to it.
-// return true iff we just wound up freeing the server_port.
+/* Free all storage held by req, and remove links to it. */
+/* return true iff we just wound up freeing the server_port. */
static int
server_request_free(struct server_request *req)
{
@@ -1723,6 +1736,7 @@ server_request_free(struct server_request *req)
if (req->base.questions) {
for (i = 0; i < req->base.nquestions; ++i)
free(req->base.questions[i]);
+ free(req->base.questions);
}
if (req->port) {
@@ -1755,7 +1769,7 @@ server_request_free(struct server_request *req)
return (0);
}
-// Free all storage held by an evdns_server_port. Only called when
+/* Free all storage held by an evdns_server_port. Only called when */
static void
server_port_free(struct evdns_server_port *port)
{
@@ -1767,10 +1781,10 @@ server_port_free(struct evdns_server_port *port)
port->socket = -1;
}
(void) event_del(&port->event);
- // XXXX actually free the port? -NM
+ /* XXXX actually free the port? -NM */
}
-// exported function
+/* exported function */
int
evdns_server_request_drop(struct evdns_server_request *_req)
{
@@ -1779,11 +1793,22 @@ evdns_server_request_drop(struct evdns_server_request *_req)
return 0;
}
+/* exported function */
+int
+evdns_server_request_get_requesting_addr(struct evdns_server_request *_req, struct sockaddr *sa, int addr_len)
+{
+ struct server_request *req = TO_SERVER_REQUEST(_req);
+ if (addr_len < (int)req->addrlen)
+ return -1;
+ memcpy(sa, &(req->addr), req->addrlen);
+ return req->addrlen;
+}
+
#undef APPEND16
#undef APPEND32
-// this is a libevent callback function which is called when a request
-// has timed out.
+/* this is a libevent callback function which is called when a request */
+/* has timed out. */
static void
evdns_request_timeout_callback(int fd, short events, void *arg) {
struct request *const req = (struct request *) arg;
@@ -1800,21 +1825,21 @@ evdns_request_timeout_callback(int fd, short events, void *arg) {
(void) evtimer_del(&req->timeout_event);
if (req->tx_count >= global_max_retransmits) {
- // this request has failed
+ /* this request has failed */
reply_callback(req, 0, DNS_ERR_TIMEOUT, NULL);
request_finished(req, &req_head);
} else {
- // retransmit it
+ /* retransmit it */
evdns_request_transmit(req);
}
}
-// try to send a request to a given server.
-//
-// return:
-// 0 ok
-// 1 temporary failure
-// 2 other failure
+/* try to send a request to a given server. */
+/* */
+/* return: */
+/* 0 ok */
+/* 1 temporary failure */
+/* 2 other failure */
static int
evdns_request_transmit_to(struct request *req, struct nameserver *server) {
const int r = send(server->socket, req->request, req->request_len, 0);
@@ -1824,46 +1849,46 @@ evdns_request_transmit_to(struct request *req, struct nameserver *server) {
nameserver_failed(req->ns, strerror(err));
return 2;
} else if (r != (int)req->request_len) {
- return 1; // short write
+ return 1; /* short write */
} else {
return 0;
}
}
-// try to send a request, updating the fields of the request
-// as needed
-//
-// return:
-// 0 ok
-// 1 failed
+/* try to send a request, updating the fields of the request */
+/* as needed */
+/* */
+/* return: */
+/* 0 ok */
+/* 1 failed */
static int
evdns_request_transmit(struct request *req) {
int retcode = 0, r;
- // if we fail to send this packet then this flag marks it
- // for evdns_transmit
+ /* if we fail to send this packet then this flag marks it */
+ /* for evdns_transmit */
req->transmit_me = 1;
if (req->trans_id == 0xffff) abort();
if (req->ns->choked) {
- // don't bother trying to write to a socket
- // which we have had EAGAIN from
+ /* don't bother trying to write to a socket */
+ /* which we have had EAGAIN from */
return 1;
}
r = evdns_request_transmit_to(req, req->ns);
switch (r) {
case 1:
- // temp failure
+ /* temp failure */
req->ns->choked = 1;
nameserver_write_waiting(req->ns, 1);
return 1;
case 2:
- // failed in some other way
+ /* failed in some other way */
retcode = 1;
- // fall through
+ /* fall through */
default:
- // all ok
+ /* all ok */
log(EVDNS_LOG_DEBUG,
"Setting timeout for request %lx", (unsigned long) req);
evtimer_set(&req->timeout_event, evdns_request_timeout_callback, req);
@@ -1871,7 +1896,7 @@ evdns_request_transmit(struct request *req) {
log(EVDNS_LOG_WARN,
"Error from libevent when adding timer for request %lx",
(unsigned long) req);
- // ???? Do more?
+ /* ???? Do more? */
}
req->tx_count++;
req->transmit_me = 0;
@@ -1888,7 +1913,7 @@ nameserver_probe_callback(int result, char type, int count, int ttl, void *addre
(void) addresses;
if (result == DNS_ERR_NONE || result == DNS_ERR_NOTEXIST) {
- // this is a good reply
+ /* this is a good reply */
nameserver_up(ns);
} else nameserver_probe_failed(ns);
}
@@ -1896,29 +1921,29 @@ nameserver_probe_callback(int result, char type, int count, int ttl, void *addre
static void
nameserver_send_probe(struct nameserver *const ns) {
struct request *req;
- // here we need to send a probe to a given nameserver
- // in the hope that it is up now.
+ /* here we need to send a probe to a given nameserver */
+ /* in the hope that it is up now. */
log(EVDNS_LOG_DEBUG, "Sending probe to %s", debug_ntoa(ns->address));
req = request_new(TYPE_A, "www.google.com", DNS_QUERY_NO_SEARCH, nameserver_probe_callback, ns);
if (!req) return;
- // we force this into the inflight queue no matter what
+ /* we force this into the inflight queue no matter what */
request_trans_id_set(req, transaction_id_pick());
req->ns = ns;
request_submit(req);
}
-// returns:
-// 0 didn't try to transmit anything
-// 1 tried to transmit something
+/* returns: */
+/* 0 didn't try to transmit anything */
+/* 1 tried to transmit something */
static int
evdns_transmit(void) {
char did_try_to_transmit = 0;
if (req_head) {
struct request *const started_at = req_head, *req = req_head;
- // first transmit all the requests which are currently waiting
+ /* first transmit all the requests which are currently waiting */
do {
if (req->transmit_me) {
did_try_to_transmit = 1;
@@ -1932,7 +1957,7 @@ evdns_transmit(void) {
return did_try_to_transmit;
}
-// exported function
+/* exported function */
int
evdns_count_nameservers(void)
{
@@ -1947,7 +1972,7 @@ evdns_count_nameservers(void)
return n;
}
-// exported function
+/* exported function */
int
evdns_clear_nameservers_and_suspend(void)
{
@@ -1974,7 +1999,7 @@ evdns_clear_nameservers_and_suspend(void)
struct request *next = req->next;
req->tx_count = req->reissue_count = 0;
req->ns = NULL;
- // ???? What to do about searches?
+ /* ???? What to do about searches? */
(void) evtimer_del(&req->timeout_event);
req->trans_id = 0;
req->transmit_me = 0;
@@ -1998,7 +2023,7 @@ evdns_clear_nameservers_and_suspend(void)
}
-// exported function
+/* exported function */
int
evdns_resume(void)
{
@@ -2008,7 +2033,7 @@ evdns_resume(void)
static int
_evdns_nameserver_add_impl(unsigned long int address, int port) {
- // first check to see if we already have this nameserver
+ /* first check to see if we already have this nameserver */
const struct nameserver *server = server_head, *const started_at = server_head;
struct nameserver *ns;
@@ -2054,7 +2079,7 @@ _evdns_nameserver_add_impl(unsigned long int address, int port) {
log(EVDNS_LOG_DEBUG, "Added nameserver %s", debug_ntoa(address));
- // insert this nameserver into the list of them
+ /* insert this nameserver into the list of them */
if (!server_head) {
ns->next = ns->prev = ns;
server_head = ns;
@@ -2079,13 +2104,13 @@ out1:
return err;
}
-// exported function
+/* exported function */
int
evdns_nameserver_add(unsigned long int address) {
return _evdns_nameserver_add_impl(address, 53);
}
-// exported function
+/* exported function */
int
evdns_nameserver_ip_add(const char *ip_as_string) {
struct in_addr ina;
@@ -2114,7 +2139,7 @@ evdns_nameserver_ip_add(const char *ip_as_string) {
return _evdns_nameserver_add_impl(ina.s_addr, port);
}
-// insert into the tail of the queue
+/* insert into the tail of the queue */
static void
evdns_request_insert(struct request *req, struct request **head) {
if (!*head) {
@@ -2148,7 +2173,7 @@ request_new(int type, const char *name, int flags,
const int name_len = strlen(name);
const int request_max_len = evdns_request_len(name_len);
const u16 trans_id = issuing_now ? transaction_id_pick() : 0xffff;
- // the request data is alloced in a single block with the header
+ /* the request data is alloced in a single block with the header */
struct request *const req =
(struct request *) malloc(sizeof(struct request) + request_max_len);
int rlen;
@@ -2157,9 +2182,9 @@ request_new(int type, const char *name, int flags,
if (!req) return NULL;
memset(req, 0, sizeof(struct request));
- // request data lives just after the header
+ /* request data lives just after the header */
req->request = ((u8 *) req) + sizeof(struct request);
- // denotes that the request data shouldn't be free()ed
+ /* denotes that the request data shouldn't be free()ed */
req->request_appended = 1;
rlen = evdns_request_data_build(name, name_len, trans_id,
type, CLASS_INET, req->request, request_max_len);
@@ -2183,8 +2208,8 @@ err1:
static void
request_submit(struct request *const req) {
if (req->ns) {
- // if it has a nameserver assigned then this is going
- // straight into the inflight queue
+ /* if it has a nameserver assigned then this is going */
+ /* straight into the inflight queue */
evdns_request_insert(req, &req_head);
global_requests_inflight++;
evdns_request_transmit(req);
@@ -2194,7 +2219,7 @@ request_submit(struct request *const req) {
}
}
-// exported function
+/* exported function */
int evdns_resolve_ipv4(const char *name, int flags,
evdns_callback_type callback, void *ptr) {
log(EVDNS_LOG_DEBUG, "Resolve requested for %s", name);
@@ -2210,7 +2235,7 @@ int evdns_resolve_ipv4(const char *name, int flags,
}
}
-// exported function
+/* exported function */
int evdns_resolve_ipv6(const char *name, int flags,
evdns_callback_type callback, void *ptr) {
log(EVDNS_LOG_DEBUG, "Resolve requested for %s", name);
@@ -2267,23 +2292,23 @@ int evdns_resolve_reverse_ipv6(struct in6_addr *in, int flags, evdns_callback_ty
return 0;
}
-/////////////////////////////////////////////////////////////////////
-// Search support
-//
-// the libc resolver has support for searching a number of domains
-// to find a name. If nothing else then it takes the single domain
-// from the gethostname() call.
-//
-// It can also be configured via the domain and search options in a
-// resolv.conf.
-//
-// The ndots option controls how many dots it takes for the resolver
-// to decide that a name is non-local and so try a raw lookup first.
+/*/////////////////////////////////////////////////////////////////// */
+/* Search support */
+/* */
+/* the libc resolver has support for searching a number of domains */
+/* to find a name. If nothing else then it takes the single domain */
+/* from the gethostname() call. */
+/* */
+/* It can also be configured via the domain and search options in a */
+/* resolv.conf. */
+/* */
+/* The ndots option controls how many dots it takes for the resolver */
+/* to decide that a name is non-local and so try a raw lookup first. */
struct search_domain {
int len;
struct search_domain *next;
- // the text string is appended to this structure
+ /* the text string is appended to this structure */
};
struct search_state {
@@ -2327,7 +2352,7 @@ search_postfix_clear(void) {
global_search_state = search_state_new();
}
-// exported function
+/* exported function */
void
evdns_search_clear(void) {
search_postfix_clear();
@@ -2353,8 +2378,8 @@ search_postfix_add(const char *domain) {
global_search_state->head = sdomain;
}
-// reverse the order of members in the postfix list. This is needed because,
-// when parsing resolv.conf we push elements in the wrong order
+/* reverse the order of members in the postfix list. This is needed because, */
+/* when parsing resolv.conf we push elements in the wrong order */
static void
search_reverse(void) {
struct search_domain *cur, *prev = NULL, *next;
@@ -2369,13 +2394,13 @@ search_reverse(void) {
global_search_state->head = prev;
}
-// exported function
+/* exported function */
void
evdns_search_add(const char *domain) {
search_postfix_add(domain);
}
-// exported function
+/* exported function */
void
evdns_search_ndots_set(const int ndots) {
if (!global_search_state) global_search_state = search_state_new();
@@ -2394,7 +2419,7 @@ search_set_from_hostname(void) {
search_postfix_add(domainname);
}
-// warning: returns malloced string
+/* warning: returns malloced string */
static char *
search_make_new(const struct search_state *const state, int n, const char *const base_name) {
const int base_len = strlen(base_name);
@@ -2403,8 +2428,8 @@ search_make_new(const struct search_state *const state, int n, const char *const
for (dom = state->head; dom; dom = dom->next) {
if (!n--) {
- // this is the postfix we want
- // the actual postfix string is kept at the end of the structure
+ /* this is the postfix we want */
+ /* the actual postfix string is kept at the end of the structure */
const u8 *const postfix = ((u8 *) dom) + sizeof(struct search_domain);
const int postfix_len = dom->len;
char *const newname = (char *) malloc(base_len + need_to_append_dot + postfix_len + 1);
@@ -2417,7 +2442,7 @@ search_make_new(const struct search_state *const state, int n, const char *const
}
}
- // we ran off the end of the list and still didn't find the requested string
+ /* we ran off the end of the list and still didn't find the requested string */
abort();
return NULL; /* unreachable; stops warnings in some compilers. */
}
@@ -2428,7 +2453,7 @@ search_request_new(int type, const char *const name, int flags, evdns_callback_t
if ( ((flags & DNS_QUERY_NO_SEARCH) == 0) &&
global_search_state &&
global_search_state->num_domains) {
- // we have some domains to search
+ /* we have some domains to search */
struct request *req;
if (string_num_dots(name) >= global_search_state->ndots) {
req = request_new(type, name, flags, user_callback, user_arg);
@@ -2456,23 +2481,23 @@ search_request_new(int type, const char *const name, int flags, evdns_callback_t
}
}
-// this is called when a request has failed to find a name. We need to check
-// if it is part of a search and, if so, try the next name in the list
-// returns:
-// 0 another request has been submitted
-// 1 no more requests needed
+/* this is called when a request has failed to find a name. We need to check */
+/* if it is part of a search and, if so, try the next name in the list */
+/* returns: */
+/* 0 another request has been submitted */
+/* 1 no more requests needed */
static int
search_try_next(struct request *const req) {
if (req->search_state) {
- // it is part of a search
+ /* it is part of a search */
char *new_name;
struct request *newreq;
req->search_index++;
if (req->search_index >= req->search_state->num_domains) {
- // no more postfixes to try, however we may need to try
- // this name without a postfix
+ /* no more postfixes to try, however we may need to try */
+ /* this name without a postfix */
if (string_num_dots(req->search_origname) < req->search_state->ndots) {
- // yep, we need to try it raw
+ /* yep, we need to try it raw */
struct request *const newreq = request_new(req->request_type, req->search_origname, req->search_flags, req->user_callback, req->user_pointer);
log(EVDNS_LOG_DEBUG, "Search: trying raw query %s", req->search_origname);
if (newreq) {
@@ -2513,12 +2538,12 @@ search_request_finished(struct request *const req) {
}
}
-/////////////////////////////////////////////////////////////////////
-// Parsing resolv.conf files
+/*/////////////////////////////////////////////////////////////////// */
+/* Parsing resolv.conf files */
static void
evdns_resolv_set_defaults(int flags) {
- // if the file isn't found then we assume a local resolver
+ /* if the file isn't found then we assume a local resolver */
if (flags & DNS_OPTION_SEARCH) search_set_from_hostname();
if (flags & DNS_OPTION_NAMESERVERS) evdns_nameserver_ip_add("127.0.0.1");
}
@@ -2530,7 +2555,7 @@ strtok_r(char *s, const char *delim, char **state) {
}
#endif
-// helper version of atoi which returns -1 on error
+/* helper version of atoi which returns -1 on error */
static int
strtoint(const char *const str) {
char *endptr;
@@ -2539,7 +2564,7 @@ strtoint(const char *const str) {
return r;
}
-// helper version of atoi that returns -1 on error and clips to bounds.
+/* helper version of atoi that returns -1 on error and clips to bounds. */
static int
strtoint_clipped(const char *const str, int min, int max)
{
@@ -2554,7 +2579,7 @@ strtoint_clipped(const char *const str, int min, int max)
return r;
}
-// exported function
+/* exported function */
int
evdns_set_option(const char *option, const char *val, int flags)
{
@@ -2611,7 +2636,7 @@ resolv_conf_parse_line(char *const start, int flags) {
struct in_addr ina;
if (inet_aton(nameserver, &ina)) {
- // address is valid
+ /* address is valid */
evdns_nameserver_add(ina.s_addr);
}
} else if (!strcmp(first_token, "domain") && (flags & DNS_OPTION_SEARCH)) {
@@ -2638,18 +2663,18 @@ resolv_conf_parse_line(char *const start, int flags) {
#undef NEXT_TOKEN
}
-// exported function
-// returns:
-// 0 no errors
-// 1 failed to open file
-// 2 failed to stat file
-// 3 file too large
-// 4 out of memory
-// 5 short read from file
+/* exported function */
+/* returns: */
+/* 0 no errors */
+/* 1 failed to open file */
+/* 2 failed to stat file */
+/* 3 file too large */
+/* 4 out of memory */
+/* 5 short read from file */
int
evdns_resolv_conf_parse(int flags, const char *const filename) {
struct stat st;
- int fd;
+ int fd, n, r;
u8 *resolv;
char *start;
int err = 0;
@@ -2668,15 +2693,20 @@ evdns_resolv_conf_parse(int flags, const char *const filename) {
err = (flags & DNS_OPTION_NAMESERVERS) ? 6 : 0;
goto out1;
}
- if (st.st_size > 65535) { err = 3; goto out1; } // no resolv.conf should be any bigger
+ if (st.st_size > 65535) { err = 3; goto out1; } /* no resolv.conf should be any bigger */
resolv = (u8 *) malloc((size_t)st.st_size + 1);
if (!resolv) { err = 4; goto out1; }
- if (read(fd, resolv, (size_t)st.st_size) != st.st_size) {
- err = 5; goto out2;
- }
- resolv[st.st_size] = 0; // we malloced an extra byte
+ n = 0;
+ while ((r = read(fd, resolv+n, (size_t)st.st_size-n)) > 0) {
+ n += r;
+ if (n == st.st_size)
+ break;
+ assert(n < st.st_size);
+ }
+ if (r < 0) { err = 5; goto out2; }
+ resolv[n] = 0; /* we malloced an extra byte; this should be fine. */
start = (char *) resolv;
for (;;) {
@@ -2692,7 +2722,7 @@ evdns_resolv_conf_parse(int flags, const char *const filename) {
}
if (!server_head && (flags & DNS_OPTION_NAMESERVERS)) {
- // no nameservers were configured.
+ /* no nameservers were configured. */
evdns_nameserver_ip_add("127.0.0.1");
err = 6;
}
@@ -2708,7 +2738,7 @@ out1:
}
#ifdef WIN32
-// Add multiple nameservers from a space-or-comma-separated list.
+/* Add multiple nameservers from a space-or-comma-separated list. */
static int
evdns_nameserver_ip_add_line(const char *ips) {
const char *addr;
@@ -2733,12 +2763,12 @@ evdns_nameserver_ip_add_line(const char *ips) {
typedef DWORD(WINAPI *GetNetworkParams_fn_t)(FIXED_INFO *, DWORD*);
-// Use the windows GetNetworkParams interface in iphlpapi.dll to
-// figure out what our nameservers are.
+/* Use the windows GetNetworkParams interface in iphlpapi.dll to */
+/* figure out what our nameservers are. */
static int
load_nameservers_with_getnetworkparams(void)
{
- // Based on MSDN examples and inspection of c-ares code.
+ /* Based on MSDN examples and inspection of c-ares code. */
FIXED_INFO *fixed;
HMODULE handle = 0;
ULONG size = sizeof(FIXED_INFO);
@@ -2954,6 +2984,8 @@ evdns_shutdown(int fail_requests)
if (server->socket >= 0)
CLOSE_SOCKET(server->socket);
(void) event_del(&server->event);
+ if (server->state == 0)
+ (void) event_del(&server->timeout_event);
free(server);
if (server_next == server_head)
break;
diff --git a/lib/libevent/evdns.h b/lib/libevent/evdns.h
index c524fc319f2..aa7b4f924a9 100644
--- a/lib/libevent/evdns.h
+++ b/lib/libevent/evdns.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: evdns.h,v 1.1 2007/03/19 15:12:49 millert Exp $ */
+/* $OpenBSD: evdns.h,v 1.2 2008/05/02 06:09:11 brad Exp $ */
/*
* Copyright (c) 2006 Niels Provos <provos@citi.umich.edu>
@@ -363,5 +363,7 @@ int evdns_server_request_add_cname_reply(struct evdns_server_request *req, const
int evdns_server_request_respond(struct evdns_server_request *req, int err);
int evdns_server_request_drop(struct evdns_server_request *req);
+struct sockaddr;
+int evdns_server_request_get_requesting_addr(struct evdns_server_request *_req, struct sockaddr *sa, int addr_len);
-#endif // !EVENTDNS_H
+#endif /* !EVENTDNS_H */
diff --git a/lib/libevent/event-internal.h b/lib/libevent/event-internal.h
index 9a944b3ef0e..0a44a5ea68e 100644
--- a/lib/libevent/event-internal.h
+++ b/lib/libevent/event-internal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: event-internal.h,v 1.4 2007/03/19 15:12:49 millert Exp $ */
+/* $OpenBSD: event-internal.h,v 1.5 2008/05/02 06:09:11 brad Exp $ */
/*
* Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu>
@@ -33,6 +33,8 @@
extern "C" {
#endif
+#include "evsignal.h"
+
struct event_base {
const struct eventop *evsel;
void *evbase;
@@ -45,6 +47,9 @@ struct event_base {
struct event_list **activequeues;
int nactivequeues;
+ /* signal handling info */
+ struct evsignal_info sig;
+
struct event_list eventqueue;
struct timeval event_tv;
diff --git a/lib/libevent/event.3 b/lib/libevent/event.3
index 75548dadf44..ba0307df13a 100644
--- a/lib/libevent/event.3
+++ b/lib/libevent/event.3
@@ -1,4 +1,4 @@
-.\" $OpenBSD: event.3,v 1.36 2007/05/31 19:19:35 jmc Exp $
+.\" $OpenBSD: event.3,v 1.37 2008/05/02 06:09:11 brad Exp $
.\"
.\" Copyright (c) 2000 Artur Grabowski <art@openbsd.org>
.\" All rights reserved.
@@ -23,7 +23,7 @@
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd $Mdocdate: May 31 2007 $
+.Dd $Mdocdate: May 2 2008 $
.Dt EVENT 3
.Os
.Sh NAME
@@ -41,6 +41,7 @@
.Nm event_add ,
.Nm event_del ,
.Nm event_once ,
+.Nm event_base_once ,
.\".Nm event_active ,
.Nm event_pending ,
.Nm event_initialized ,
@@ -159,6 +160,9 @@
.Ft int
.Fn "event_once" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg" "struct timeval *tv"
.Ft int
+.Fn "event_base_once" "struct event_base *base" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg" "struct timeval *tv"
+
+.Ft int
.Fn "event_pending" "struct event *ev" "short event" "struct timeval *tv"
.Ft int
.Fn "event_initialized" "struct event *ev"
diff --git a/lib/libevent/event.c b/lib/libevent/event.c
index 83d40bf97d3..a460467e330 100644
--- a/lib/libevent/event.c
+++ b/lib/libevent/event.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: event.c,v 1.17 2007/03/19 15:12:49 millert Exp $ */
+/* $OpenBSD: event.c,v 1.18 2008/05/02 06:09:11 brad Exp $ */
/*
* Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu>
@@ -53,6 +53,7 @@
#include <signal.h>
#include <string.h>
#include <assert.h>
+#include <time.h>
#include "event.h"
#include "event-internal.h"
@@ -113,9 +114,9 @@ const struct eventop *eventops[] = {
};
/* Global state */
-struct event_list signalqueue;
-
struct event_base *current_base = NULL;
+extern struct event_base *evsignal_base;
+static int use_monotonic;
/* Handle signals - This is a deprecated interface */
int (*event_sigcb)(void); /* Signal callback when gotsig is set */
@@ -128,7 +129,7 @@ static int event_haveevents(struct event_base *);
static void event_process_active(struct event_base *);
-static int timeout_next(struct event_base *, struct timeval *);
+static int timeout_next(struct event_base *, struct timeval **);
static void timeout_process(struct event_base *);
static void timeout_correct(struct event_base *, struct timeval *);
@@ -146,25 +147,34 @@ compare(struct event *a, struct event *b)
return (0);
}
+static void
+detect_monotonic(void)
+{
+#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
+ struct timespec ts;
+
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
+ use_monotonic = 1;
+#endif
+}
+
static int
gettime(struct timeval *tp)
{
-#ifdef HAVE_CLOCK_GETTIME
+#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
struct timespec ts;
-#ifdef HAVE_CLOCK_MONOTONIC
- if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
-#else
- if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
-#endif
- return (-1);
- tp->tv_sec = ts.tv_sec;
- tp->tv_usec = ts.tv_nsec / 1000;
-#else
- gettimeofday(tp, NULL);
+ if (use_monotonic) {
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
+ return (-1);
+
+ tp->tv_sec = ts.tv_sec;
+ tp->tv_usec = ts.tv_nsec / 1000;
+ return (0);
+ }
#endif
- return (0);
+ return (gettimeofday(tp, NULL));
}
RB_PROTOTYPE(event_tree, event, ev_timeout_node, compare);
@@ -176,36 +186,42 @@ void *
event_init(void)
{
int i;
+ struct event_base *base;
- if ((current_base = calloc(1, sizeof(struct event_base))) == NULL)
+ if ((base = calloc(1, sizeof(struct event_base))) == NULL)
event_err(1, "%s: calloc");
event_sigcb = NULL;
event_gotsig = 0;
- gettime(&current_base->event_tv);
- RB_INIT(&current_base->timetree);
- TAILQ_INIT(&current_base->eventqueue);
- TAILQ_INIT(&signalqueue);
+ detect_monotonic();
+ gettime(&base->event_tv);
+
+ RB_INIT(&base->timetree);
+ TAILQ_INIT(&base->eventqueue);
+ TAILQ_INIT(&base->sig.signalqueue);
+ base->sig.ev_signal_pair[0] = -1;
+ base->sig.ev_signal_pair[1] = -1;
- current_base->evbase = NULL;
- for (i = 0; eventops[i] && !current_base->evbase; i++) {
- current_base->evsel = eventops[i];
+ base->evbase = NULL;
+ for (i = 0; eventops[i] && !base->evbase; i++) {
+ base->evsel = eventops[i];
- current_base->evbase = current_base->evsel->init();
+ base->evbase = base->evsel->init(base);
}
- if (current_base->evbase == NULL)
+ if (base->evbase == NULL)
event_errx(1, "%s: no event mechanism available", __func__);
- if (!issetugid() && getenv("EVENT_SHOW_METHOD"))
+ if (getenv("EVENT_SHOW_METHOD"))
event_msgx("libevent using: %s\n",
- current_base->evsel->name);
+ base->evsel->name);
/* allocate a single active event queue */
- event_base_priority_init(current_base, 1);
+ event_base_priority_init(base, 1);
- return (current_base);
+ current_base = base;
+ return (base);
}
void
@@ -219,7 +235,8 @@ event_base_free(struct event_base *base)
current_base = NULL;
assert(base);
- assert(TAILQ_EMPTY(&base->eventqueue));
+ if (base->evsel->dealloc != NULL)
+ base->evsel->dealloc(base, base->evbase);
for (i=0; i < base->nactivequeues; ++i)
assert(TAILQ_EMPTY(base->activequeues[i]));
@@ -229,8 +246,7 @@ event_base_free(struct event_base *base)
free(base->activequeues[i]);
free(base->activequeues);
- if (base->evsel->dealloc != NULL)
- base->evsel->dealloc(base->evbase);
+ assert(TAILQ_EMPTY(&base->eventqueue));
free(base);
}
@@ -345,7 +361,6 @@ event_loopexit_cb(int fd, short what, void *arg)
}
/* not thread safe */
-
int
event_loopexit(struct timeval *tv)
{
@@ -356,7 +371,7 @@ event_loopexit(struct timeval *tv)
int
event_base_loopexit(struct event_base *event_base, struct timeval *tv)
{
- return (event_once(-1, EV_TIMEOUT, event_loopexit_cb,
+ return (event_base_once(event_base, -1, EV_TIMEOUT, event_loopexit_cb,
event_base, tv));
}
@@ -374,8 +389,13 @@ event_base_loop(struct event_base *base, int flags)
const struct eventop *evsel = base->evsel;
void *evbase = base->evbase;
struct timeval tv;
+ struct timeval *tv_p;
int res, done;
+#ifndef WIN32
+ if(!TAILQ_EMPTY(&base->sig.signalqueue))
+ evsignal_base = base;
+#endif
done = 0;
while (!done) {
/* Calculate the initial events that we are waiting for */
@@ -400,21 +420,18 @@ event_base_loop(struct event_base *base, int flags)
}
}
- /* Check if time is running backwards */
- gettime(&tv);
- if (timercmp(&tv, &base->event_tv, <)) {
- struct timeval off;
- event_debug(("%s: time is running backwards, corrected",
- __func__));
- timersub(&base->event_tv, &tv, &off);
- timeout_correct(base, &off);
- }
- base->event_tv = tv;
+ timeout_correct(base, &tv);
- if (!base->event_count_active && !(flags & EVLOOP_NONBLOCK))
- timeout_next(base, &tv);
- else
+ tv_p = &tv;
+ if (!base->event_count_active && !(flags & EVLOOP_NONBLOCK)) {
+ timeout_next(base, &tv_p);
+ } else {
+ /*
+ * if we have active events, we just poll new events
+ * without waiting.
+ */
timerclear(&tv);
+ }
/* If we have no events, we just exit */
if (!event_haveevents(base)) {
@@ -422,7 +439,7 @@ event_base_loop(struct event_base *base, int flags)
return (1);
}
- res = evsel->dispatch(base, evbase, &tv);
+ res = evsel->dispatch(base, evbase, tv_p);
if (res == -1)
return (-1);
@@ -461,12 +478,19 @@ event_once_cb(int fd, short events, void *arg)
free(eonce);
}
-/* Schedules an event once */
-
+/* not threadsafe, event scheduled once. */
int
event_once(int fd, short events,
void (*callback)(int, short, void *), void *arg, struct timeval *tv)
{
+ return event_base_once(current_base, fd, events, callback, arg, tv);
+}
+
+/* Schedules an event once */
+int
+event_base_once(struct event_base *base, int fd, short events,
+ void (*callback)(int, short, void *), void *arg, struct timeval *tv)
+{
struct event_once *eonce;
struct timeval etv;
int res;
@@ -498,7 +522,9 @@ event_once(int fd, short events,
return (-1);
}
- res = event_add(&eonce->ev, tv);
+ res = event_base_set(base, &eonce->ev);
+ if (res == 0)
+ res = event_add(&eonce->ev, tv);
if (res != 0) {
free(eonce);
return (res);
@@ -518,12 +544,14 @@ event_set(struct event *ev, int fd, short events,
ev->ev_arg = arg;
ev->ev_fd = fd;
ev->ev_events = events;
+ ev->ev_res = 0;
ev->ev_flags = EVLIST_INIT;
ev->ev_ncalls = 0;
ev->ev_pncalls = NULL;
/* by default, we put new events into the middle priority */
- ev->ev_pri = current_base->nactivequeues/2;
+ if(current_base)
+ ev->ev_pri = current_base->nactivequeues/2;
}
int
@@ -712,16 +740,16 @@ event_active(struct event *ev, int res, short ncalls)
event_queue_insert(ev->ev_base, ev, EVLIST_ACTIVE);
}
-int
-timeout_next(struct event_base *base, struct timeval *tv)
+static int
+timeout_next(struct event_base *base, struct timeval **tv_p)
{
- struct timeval dflt = TIMEOUT_DEFAULT;
-
struct timeval now;
struct event *ev;
+ struct timeval *tv = *tv_p;
if ((ev = RB_MIN(event_tree, &base->timetree)) == NULL) {
- *tv = dflt;
+ /* if no time-based events are active wait for I/O */
+ *tv_p = NULL;
return (0);
}
@@ -742,17 +770,38 @@ timeout_next(struct event_base *base, struct timeval *tv)
return (0);
}
+/*
+ * Determines if the time is running backwards by comparing the current
+ * time against the last time we checked. Not needed when using clock
+ * monotonic.
+ */
+
static void
-timeout_correct(struct event_base *base, struct timeval *off)
+timeout_correct(struct event_base *base, struct timeval *tv)
{
struct event *ev;
+ struct timeval off;
+
+ if (use_monotonic)
+ return;
+
+ /* Check if time is running backwards */
+ gettime(tv);
+ if (timercmp(tv, &base->event_tv, >=)) {
+ base->event_tv = *tv;
+ return;
+ }
+
+ event_debug(("%s: time is running backwards, corrected",
+ __func__));
+ timersub(&base->event_tv, tv, &off);
/*
* We can modify the key element of the node without destroying
* the key, beause we apply it to all in the right order.
*/
RB_FOREACH(ev, event_tree, &base->timetree)
- timersub(&ev->ev_timeout, off, &ev->ev_timeout);
+ timersub(&ev->ev_timeout, &off, &ev->ev_timeout);
}
void
@@ -803,7 +852,7 @@ event_queue_remove(struct event_base *base, struct event *ev, int queue)
ev, ev_active_next);
break;
case EVLIST_SIGNAL:
- TAILQ_REMOVE(&signalqueue, ev, ev_signal_next);
+ TAILQ_REMOVE(&base->sig.signalqueue, ev, ev_signal_next);
break;
case EVLIST_TIMEOUT:
RB_REMOVE(event_tree, &base->timetree, ev);
@@ -845,7 +894,7 @@ event_queue_insert(struct event_base *base, struct event *ev, int queue)
ev,ev_active_next);
break;
case EVLIST_SIGNAL:
- TAILQ_INSERT_TAIL(&signalqueue, ev, ev_signal_next);
+ TAILQ_INSERT_TAIL(&base->sig.signalqueue, ev, ev_signal_next);
break;
case EVLIST_TIMEOUT: {
struct event *tmp = RB_INSERT(event_tree, &base->timetree, ev);
diff --git a/lib/libevent/event.h b/lib/libevent/event.h
index 690322ee2af..82451393895 100644
--- a/lib/libevent/event.h
+++ b/lib/libevent/event.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: event.h,v 1.18 2007/03/19 15:12:49 millert Exp $ */
+/* $OpenBSD: event.h,v 1.19 2008/05/02 06:09:11 brad Exp $ */
/*
* Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu>
@@ -33,6 +33,8 @@
extern "C" {
#endif
+#include <sys/time.h>
+#include <stdint.h>
#include <stdarg.h>
#ifdef WIN32
@@ -43,7 +45,7 @@ typedef unsigned char u_char;
typedef unsigned short u_short;
#endif
-#define LIBEVENT_VERSION "1.3b"
+#define LIBEVENT_VERSION "1.3e"
#define EVLIST_TIMEOUT 0x01
#define EVLIST_INSERTED 0x02
@@ -135,16 +137,14 @@ TAILQ_HEAD (evkeyvalq, evkeyval);
struct eventop {
char *name;
- void *(*init)(void);
+ void *(*init)(struct event_base *);
int (*add)(void *, struct event *);
int (*del)(void *, struct event *);
int (*recalc)(struct event_base *, void *, int);
int (*dispatch)(struct event_base *, void *, struct timeval *);
- void (*dealloc)(void *);
+ void (*dealloc)(struct event_base *, void *);
};
-#define TIMEOUT_DEFAULT {5, 0}
-
void *event_init(void);
int event_dispatch(void);
int event_base_dispatch(struct event_base *);
@@ -182,6 +182,7 @@ int event_base_loopexit(struct event_base *, struct timeval *);
void event_set(struct event *, int, short, void (*)(int, short, void *), void *);
int event_once(int, short, void (*)(int, short, void *), void *, struct timeval *);
+int event_base_once(struct event_base *, int, short, void (*)(int, short, void *), void *, struct timeval *);
int event_add(struct event *, struct timeval *);
int event_del(struct event *);
@@ -297,39 +298,37 @@ void evbuffer_setcb(struct evbuffer *, void (*)(struct evbuffer *, size_t, size_
void evtag_init(void);
-void evtag_marshal(struct evbuffer *evbuf, u_int8_t tag, const void *data,
- u_int32_t len);
+void evtag_marshal(struct evbuffer *evbuf, uint8_t tag, const void *data,
+ uint32_t len);
-void encode_int(struct evbuffer *evbuf, u_int32_t number);
+void encode_int(struct evbuffer *evbuf, uint32_t number);
-void evtag_marshal_int(struct evbuffer *evbuf, u_int8_t tag,
- u_int32_t integer);
+void evtag_marshal_int(struct evbuffer *evbuf, uint8_t tag, uint32_t integer);
-void evtag_marshal_string(struct evbuffer *buf, u_int8_t tag,
+void evtag_marshal_string(struct evbuffer *buf, uint8_t tag,
const char *string);
-void evtag_marshal_timeval(struct evbuffer *evbuf, u_int8_t tag,
+void evtag_marshal_timeval(struct evbuffer *evbuf, uint8_t tag,
struct timeval *tv);
void evtag_test(void);
-int evtag_unmarshal(struct evbuffer *src, u_int8_t *ptag,
- struct evbuffer *dst);
-int evtag_peek(struct evbuffer *evbuf, u_int8_t *ptag);
-int evtag_peek_length(struct evbuffer *evbuf, u_int32_t *plength);
-int evtag_payload_length(struct evbuffer *evbuf, u_int32_t *plength);
+int evtag_unmarshal(struct evbuffer *src, uint8_t *ptag, struct evbuffer *dst);
+int evtag_peek(struct evbuffer *evbuf, uint8_t *ptag);
+int evtag_peek_length(struct evbuffer *evbuf, uint32_t *plength);
+int evtag_payload_length(struct evbuffer *evbuf, uint32_t *plength);
int evtag_consume(struct evbuffer *evbuf);
-int evtag_unmarshal_int(struct evbuffer *evbuf, u_int8_t need_tag,
- u_int32_t *pinteger);
+int evtag_unmarshal_int(struct evbuffer *evbuf, uint8_t need_tag,
+ uint32_t *pinteger);
-int evtag_unmarshal_fixed(struct evbuffer *src, u_int8_t need_tag, void *data,
+int evtag_unmarshal_fixed(struct evbuffer *src, uint8_t need_tag, void *data,
size_t len);
-int evtag_unmarshal_string(struct evbuffer *evbuf, u_int8_t need_tag,
+int evtag_unmarshal_string(struct evbuffer *evbuf, uint8_t need_tag,
char **pstring);
-int evtag_unmarshal_timeval(struct evbuffer *evbuf, u_int8_t need_tag,
+int evtag_unmarshal_timeval(struct evbuffer *evbuf, uint8_t need_tag,
struct timeval *ptv);
#ifdef __cplusplus
diff --git a/lib/libevent/event_tagging.c b/lib/libevent/event_tagging.c
index 4564fbb72b9..74ff08118df 100644
--- a/lib/libevent/event_tagging.c
+++ b/lib/libevent/event_tagging.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: event_tagging.c,v 1.1 2007/03/19 15:12:49 millert Exp $ */
+/* $OpenBSD: event_tagging.c,v 1.2 2008/05/02 06:09:11 brad Exp $ */
/*
* Copyright (c) 2003, 2004 Niels Provos <provos@citi.umich.edu>
@@ -60,7 +60,7 @@
#include "event.h"
#include "log.h"
-int decode_int(u_int32_t *pnumber, struct evbuffer *evbuf);
+int decode_int(uint32_t *pnumber, struct evbuffer *evbuf);
static struct evbuffer *_buf; /* not thread safe */
@@ -81,10 +81,10 @@ evtag_init()
*/
void
-encode_int(struct evbuffer *evbuf, u_int32_t number)
+encode_int(struct evbuffer *evbuf, uint32_t number)
{
int off = 1, nibbles = 0;
- u_int8_t data[5];
+ uint8_t data[5];
memset(data, 0, sizeof(data));
while (number) {
@@ -113,8 +113,8 @@ encode_int(struct evbuffer *evbuf, u_int32_t number)
*/
void
-evtag_marshal(struct evbuffer *evbuf, u_int8_t tag,
- const void *data, u_int32_t len)
+evtag_marshal(struct evbuffer *evbuf, uint8_t tag,
+ const void *data, uint32_t len)
{
evbuffer_add(evbuf, &tag, sizeof(tag));
encode_int(evbuf, len);
@@ -123,7 +123,7 @@ evtag_marshal(struct evbuffer *evbuf, u_int8_t tag,
/* Marshaling for integers */
void
-evtag_marshal_int(struct evbuffer *evbuf, u_int8_t tag, u_int32_t integer)
+evtag_marshal_int(struct evbuffer *evbuf, uint8_t tag, uint32_t integer)
{
evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
encode_int(_buf, integer);
@@ -134,13 +134,13 @@ evtag_marshal_int(struct evbuffer *evbuf, u_int8_t tag, u_int32_t integer)
}
void
-evtag_marshal_string(struct evbuffer *buf, u_int8_t tag, const char *string)
+evtag_marshal_string(struct evbuffer *buf, uint8_t tag, const char *string)
{
evtag_marshal(buf, tag, string, strlen(string));
}
void
-evtag_marshal_timeval(struct evbuffer *evbuf, u_int8_t tag, struct timeval *tv)
+evtag_marshal_timeval(struct evbuffer *evbuf, uint8_t tag, struct timeval *tv)
{
evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
@@ -151,11 +151,11 @@ evtag_marshal_timeval(struct evbuffer *evbuf, u_int8_t tag, struct timeval *tv)
EVBUFFER_LENGTH(_buf));
}
-static int __inline
-decode_int_internal(u_int32_t *pnumber, struct evbuffer *evbuf, int dodrain)
+static int
+decode_int_internal(uint32_t *pnumber, struct evbuffer *evbuf, int dodrain)
{
- u_int32_t number = 0;
- u_int8_t *data = EVBUFFER_DATA(evbuf);
+ uint32_t number = 0;
+ uint8_t *data = EVBUFFER_DATA(evbuf);
int len = EVBUFFER_LENGTH(evbuf);
int nibbles = 0, off;
@@ -186,13 +186,13 @@ decode_int_internal(u_int32_t *pnumber, struct evbuffer *evbuf, int dodrain)
}
int
-decode_int(u_int32_t *pnumber, struct evbuffer *evbuf)
+decode_int(uint32_t *pnumber, struct evbuffer *evbuf)
{
return (decode_int_internal(pnumber, evbuf, 1) == -1 ? -1 : 0);
}
int
-evtag_peek(struct evbuffer *evbuf, u_int8_t *ptag)
+evtag_peek(struct evbuffer *evbuf, uint8_t *ptag)
{
if (EVBUFFER_LENGTH(evbuf) < 2)
return (-1);
@@ -202,7 +202,7 @@ evtag_peek(struct evbuffer *evbuf, u_int8_t *ptag)
}
int
-evtag_peek_length(struct evbuffer *evbuf, u_int32_t *plength)
+evtag_peek_length(struct evbuffer *evbuf, uint32_t *plength)
{
struct evbuffer tmp;
int res;
@@ -224,7 +224,7 @@ evtag_peek_length(struct evbuffer *evbuf, u_int32_t *plength)
}
int
-evtag_payload_length(struct evbuffer *evbuf, u_int32_t *plength)
+evtag_payload_length(struct evbuffer *evbuf, uint32_t *plength)
{
struct evbuffer tmp;
int res;
@@ -246,7 +246,7 @@ evtag_payload_length(struct evbuffer *evbuf, u_int32_t *plength)
int
evtag_consume(struct evbuffer *evbuf)
{
- u_int32_t len;
+ uint32_t len;
evbuffer_drain(evbuf, 1);
if (decode_int(&len, evbuf) == -1)
return (-1);
@@ -258,11 +258,11 @@ evtag_consume(struct evbuffer *evbuf)
/* Reads the data type from an event buffer */
int
-evtag_unmarshal(struct evbuffer *src, u_int8_t *ptag, struct evbuffer *dst)
+evtag_unmarshal(struct evbuffer *src, uint8_t *ptag, struct evbuffer *dst)
{
- u_int8_t tag;
- u_int32_t len;
- u_int32_t integer;
+ uint8_t tag;
+ uint32_t len;
+ uint32_t integer;
if (evbuffer_remove(src, &tag, sizeof(tag)) != sizeof(tag))
return (-1);
@@ -285,12 +285,12 @@ evtag_unmarshal(struct evbuffer *src, u_int8_t *ptag, struct evbuffer *dst)
/* Marshaling for integers */
int
-evtag_unmarshal_int(struct evbuffer *evbuf, u_int8_t need_tag,
- u_int32_t *pinteger)
+evtag_unmarshal_int(struct evbuffer *evbuf, uint8_t need_tag,
+ uint32_t *pinteger)
{
- u_int8_t tag;
- u_int32_t len;
- u_int32_t integer;
+ uint8_t tag;
+ uint32_t len;
+ uint32_t integer;
if (evbuffer_remove(evbuf, &tag, sizeof(tag)) != sizeof(tag) ||
tag != need_tag)
@@ -314,10 +314,10 @@ evtag_unmarshal_int(struct evbuffer *evbuf, u_int8_t need_tag,
/* Unmarshal a fixed length tag */
int
-evtag_unmarshal_fixed(struct evbuffer *src, u_int8_t need_tag, void *data,
+evtag_unmarshal_fixed(struct evbuffer *src, uint8_t need_tag, void *data,
size_t len)
{
- u_int8_t tag;
+ uint8_t tag;
/* Initialize this event buffer so that we can read into it */
evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
@@ -334,10 +334,10 @@ evtag_unmarshal_fixed(struct evbuffer *src, u_int8_t need_tag, void *data,
}
int
-evtag_unmarshal_string(struct evbuffer *evbuf, u_int8_t need_tag,
+evtag_unmarshal_string(struct evbuffer *evbuf, uint8_t need_tag,
char **pstring)
{
- u_int8_t tag;
+ uint8_t tag;
evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
@@ -353,11 +353,11 @@ evtag_unmarshal_string(struct evbuffer *evbuf, u_int8_t need_tag,
}
int
-evtag_unmarshal_timeval(struct evbuffer *evbuf, u_int8_t need_tag,
+evtag_unmarshal_timeval(struct evbuffer *evbuf, uint8_t need_tag,
struct timeval *ptv)
{
- u_int8_t tag;
- u_int32_t integer;
+ uint8_t tag;
+ uint32_t integer;
evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
if (evtag_unmarshal(evbuf, &tag, _buf) == -1 || tag != need_tag)
diff --git a/lib/libevent/evsignal.h b/lib/libevent/evsignal.h
index aa77c9c8122..7949411de08 100644
--- a/lib/libevent/evsignal.h
+++ b/lib/libevent/evsignal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: evsignal.h,v 1.2 2004/04/28 06:53:12 brad Exp $ */
+/* $OpenBSD: evsignal.h,v 1.3 2008/05/02 06:09:11 brad Exp $ */
/*
* Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
@@ -29,11 +29,18 @@
#ifndef _EVSIGNAL_H_
#define _EVSIGNAL_H_
-void evsignal_init(sigset_t *);
-void evsignal_process(void);
-int evsignal_recalc(sigset_t *);
-int evsignal_deliver(sigset_t *);
-int evsignal_add(sigset_t *, struct event *);
-int evsignal_del(sigset_t *, struct event *);
+struct evsignal_info {
+ struct event_list signalqueue;
+ struct event ev_signal;
+ int ev_signal_pair[2];
+ int ev_signal_added;
+ volatile sig_atomic_t evsignal_caught;
+ sig_atomic_t evsigcaught[NSIG];
+};
+void evsignal_init(struct event_base *);
+void evsignal_process(struct event_base *);
+int evsignal_add(struct event *);
+int evsignal_del(struct event *);
+void evsignal_dealloc(struct event_base *);
#endif /* _EVSIGNAL_H_ */
diff --git a/lib/libevent/kqueue.c b/lib/libevent/kqueue.c
index 89eb3356ad1..560d6b120c5 100644
--- a/lib/libevent/kqueue.c
+++ b/lib/libevent/kqueue.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kqueue.c,v 1.23 2007/09/02 15:19:18 deraadt Exp $ */
+/* $OpenBSD: kqueue.c,v 1.24 2008/05/02 06:09:11 brad Exp $ */
/*
* Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
@@ -48,10 +48,13 @@
#include <inttypes.h>
#endif
-#if defined(HAVE_INTTYPES_H) && !defined(__OpenBSD__) && !defined(__FreeBSD__)
-#define INTPTR(x) (intptr_t)x
+/* Some platforms apparently define the udata field of struct kevent as
+ * ntptr_t, whereas others define it as void*. There doesn't seem to be an
+ * easy way to tell them apart via autoconf, so we need to use OS macros. */
+#if defined(HAVE_INTTYPES_H) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__darwin__) && !defined(__APPLE__)
+#define PTR_TO_UDATA(x) ((intptr_t)(x))
#else
-#define INTPTR(x) x
+#define PTR_TO_UDATA(x) (x)
#endif
#include "event.h"
@@ -69,13 +72,13 @@ struct kqop {
int kq;
};
-void *kq_init (void);
+void *kq_init (struct event_base *);
int kq_add (void *, struct event *);
int kq_del (void *, struct event *);
int kq_recalc (struct event_base *, void *, int);
int kq_dispatch (struct event_base *, void *, struct timeval *);
int kq_insert (struct kqop *, struct kevent *);
-void kq_dealloc (void *);
+void kq_dealloc (struct event_base *, void *);
const struct eventop kqops = {
"kqueue",
@@ -88,7 +91,7 @@ const struct eventop kqops = {
};
void *
-kq_init(void)
+kq_init(struct event_base *base)
{
int kq;
struct kqop *kqueueop;
@@ -212,13 +215,16 @@ kq_dispatch(struct event_base *base, void *arg, struct timeval *tv)
struct kevent *changes = kqop->changes;
struct kevent *events = kqop->events;
struct event *ev;
- struct timespec ts;
+ struct timespec ts, *ts_p = NULL;
int i, res;
- TIMEVAL_TO_TIMESPEC(tv, &ts);
+ if (tv != NULL) {
+ TIMEVAL_TO_TIMESPEC(tv, &ts);
+ ts_p = &ts;
+ }
res = kevent(kqop->kq, changes, kqop->nchanges,
- events, kqop->nevents, &ts);
+ events, kqop->nevents, ts_p);
kqop->nchanges = 0;
if (res == -1) {
if (errno != EINTR) {
@@ -294,7 +300,7 @@ kq_add(void *arg, struct event *ev)
kev.flags = EV_ADD;
if (!(ev->ev_events & EV_PERSIST))
kev.flags |= EV_ONESHOT;
- kev.udata = INTPTR(ev);
+ kev.udata = PTR_TO_UDATA(ev);
if (kq_insert(kqop, &kev) == -1)
return (-1);
@@ -317,7 +323,7 @@ kq_add(void *arg, struct event *ev)
kev.flags = EV_ADD;
if (!(ev->ev_events & EV_PERSIST))
kev.flags |= EV_ONESHOT;
- kev.udata = INTPTR(ev);
+ kev.udata = PTR_TO_UDATA(ev);
if (kq_insert(kqop, &kev) == -1)
return (-1);
@@ -332,7 +338,7 @@ kq_add(void *arg, struct event *ev)
kev.flags = EV_ADD;
if (!(ev->ev_events & EV_PERSIST))
kev.flags |= EV_ONESHOT;
- kev.udata = INTPTR(ev);
+ kev.udata = PTR_TO_UDATA(ev);
if (kq_insert(kqop, &kev) == -1)
return (-1);
@@ -398,7 +404,7 @@ kq_del(void *arg, struct event *ev)
}
void
-kq_dealloc(void *arg)
+kq_dealloc(struct event_base *base, void *arg)
{
struct kqop *kqop = arg;
diff --git a/lib/libevent/log.h b/lib/libevent/log.h
index 7aa4231b9b6..d39e0c2b541 100644
--- a/lib/libevent/log.h
+++ b/lib/libevent/log.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: log.h,v 1.4 2007/03/19 15:12:49 millert Exp $ */
+/* $OpenBSD: log.h,v 1.5 2008/05/02 06:09:11 brad Exp $ */
/*
* Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu>
@@ -35,7 +35,7 @@ void event_errx(int eval, const char *fmt, ...);
void event_warnx(const char *fmt, ...);
void event_msgx(const char *fmt, ...);
void _event_debugx(const char *fmt, ...);
-#undef USE_DEBUG
+
#ifdef USE_DEBUG
#define event_debug(x) _event_debugx x
#else
diff --git a/lib/libevent/poll.c b/lib/libevent/poll.c
index cd0eabd43e1..612b36370a3 100644
--- a/lib/libevent/poll.c
+++ b/lib/libevent/poll.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: poll.c,v 1.13 2006/11/26 15:24:34 brad Exp $ */
+/* $OpenBSD: poll.c,v 1.14 2008/05/02 06:09:11 brad Exp $ */
/*
* Copyright 2000-2003 Niels Provos <provos@citi.umich.edu>
@@ -54,8 +54,6 @@
#include "evsignal.h"
#include "log.h"
-extern volatile sig_atomic_t evsignal_caught;
-
struct pollop {
int event_count; /* Highest number alloc */
int nfds; /* Size of event_* */
@@ -66,15 +64,14 @@ struct pollop {
int *idxplus1_by_fd; /* Index into event_set by fd; we add 1 so
* that 0 (which is easy to memset) can mean
* "no entry." */
- sigset_t evsigmask;
};
-void *poll_init (void);
+void *poll_init (struct event_base *);
int poll_add (void *, struct event *);
int poll_del (void *, struct event *);
int poll_recalc (struct event_base *, void *, int);
int poll_dispatch (struct event_base *, void *, struct timeval *);
-void poll_dealloc (void *);
+void poll_dealloc (struct event_base *, void *);
const struct eventop pollops = {
"poll",
@@ -87,7 +84,7 @@ const struct eventop pollops = {
};
void *
-poll_init(void)
+poll_init(struct event_base *base)
{
struct pollop *pollop;
@@ -98,7 +95,7 @@ poll_init(void)
if (!(pollop = calloc(1, sizeof(struct pollop))))
return (NULL);
- evsignal_init(&pollop->evsigmask);
+ evsignal_init(base);
return (pollop);
}
@@ -111,9 +108,7 @@ poll_init(void)
int
poll_recalc(struct event_base *base, void *arg, int max)
{
- struct pollop *pop = arg;
-
- return (evsignal_recalc(&pop->evsigmask));
+ return (0);
}
#ifdef CHECK_INVARIANTS
@@ -153,19 +148,16 @@ poll_check_ok(struct pollop *pop)
int
poll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
{
- int res, i, sec, nfds;
+ int res, i, msec = -1, nfds;
struct pollop *pop = arg;
- if (evsignal_deliver(&pop->evsigmask) == -1)
- return (-1);
-
poll_check_ok(pop);
- sec = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
- nfds = pop->nfds;
- res = poll(pop->event_set, nfds, sec);
- if (evsignal_recalc(&pop->evsigmask) == -1)
- return (-1);
+ if (tv != NULL)
+ msec = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
+
+ nfds = pop->nfds;
+ res = poll(pop->event_set, nfds, msec);
if (res == -1) {
if (errno != EINTR) {
@@ -173,10 +165,11 @@ poll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
return (-1);
}
- evsignal_process();
+ evsignal_process(base);
return (0);
- } else if (evsignal_caught)
- evsignal_process();
+ } else if (base->sig.evsignal_caught) {
+ evsignal_process(base);
+ }
event_debug(("%s: poll reports %d", __func__, res));
@@ -229,7 +222,7 @@ poll_add(void *arg, struct event *ev)
int i;
if (ev->ev_events & EV_SIGNAL)
- return (evsignal_add(&pop->evsigmask, ev));
+ return (evsignal_add(ev));
if (!(ev->ev_events & (EV_READ|EV_WRITE)))
return (0);
@@ -334,7 +327,7 @@ poll_del(void *arg, struct event *ev)
int i;
if (ev->ev_events & EV_SIGNAL)
- return (evsignal_del(&pop->evsigmask, ev));
+ return (evsignal_del(ev));
if (!(ev->ev_events & (EV_READ|EV_WRITE)))
return (0);
@@ -380,10 +373,11 @@ poll_del(void *arg, struct event *ev)
}
void
-poll_dealloc(void *arg)
+poll_dealloc(struct event_base *base, void *arg)
{
struct pollop *pop = arg;
+ evsignal_dealloc(base);
if (pop->event_set)
free(pop->event_set);
if (pop->event_r_back)
diff --git a/lib/libevent/select.c b/lib/libevent/select.c
index 75a344a3a56..de55ae057fe 100644
--- a/lib/libevent/select.c
+++ b/lib/libevent/select.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: select.c,v 1.13 2007/03/19 15:12:49 millert Exp $ */
+/* $OpenBSD: select.c,v 1.14 2008/05/02 06:09:11 brad Exp $ */
/*
* Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
@@ -36,6 +36,9 @@
#else
#include <sys/_time.h>
#endif
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
#include <sys/queue.h>
#include <sys/tree.h>
#include <signal.h>
@@ -57,8 +60,6 @@
#define howmany(x, y) (((x)+((y)-1))/(y))
#endif
-extern volatile sig_atomic_t evsignal_caught;
-
struct selectop {
int event_fds; /* Highest fd in fd set */
int event_fdsz;
@@ -68,15 +69,14 @@ struct selectop {
fd_set *event_writeset_out;
struct event **event_r_by_fd;
struct event **event_w_by_fd;
- sigset_t evsigmask;
};
-void *select_init (void);
+void *select_init (struct event_base *);
int select_add (void *, struct event *);
int select_del (void *, struct event *);
int select_recalc (struct event_base *, void *, int);
int select_dispatch (struct event_base *, void *, struct timeval *);
-void select_dealloc (void *);
+void select_dealloc (struct event_base *, void *);
const struct eventop selectops = {
"select",
@@ -91,7 +91,7 @@ const struct eventop selectops = {
static int select_resize(struct selectop *sop, int fdsz);
void *
-select_init(void)
+select_init(struct event_base *base)
{
struct selectop *sop;
@@ -104,7 +104,7 @@ select_init(void)
select_resize(sop, howmany(32 + 1, NFDBITS)*sizeof(fd_mask));
- evsignal_init(&sop->evsigmask);
+ evsignal_init(base);
return (sop);
}
@@ -114,7 +114,7 @@ static void
check_selectop(struct selectop *sop)
{
int i;
- for (i=0;i<=sop->event_fds;++i) {
+ for (i = 0; i <= sop->event_fds; ++i) {
if (FD_ISSET(i, sop->event_readset_in)) {
assert(sop->event_r_by_fd[i]);
assert(sop->event_r_by_fd[i]->ev_events & EV_READ);
@@ -148,7 +148,7 @@ select_recalc(struct event_base *base, void *arg, int max)
check_selectop(sop);
- return (evsignal_recalc(&sop->evsigmask));
+ return (0);
}
int
@@ -164,15 +164,10 @@ select_dispatch(struct event_base *base, void *arg, struct timeval *tv)
memcpy(sop->event_writeset_out, sop->event_writeset_in,
sop->event_fdsz);
- if (evsignal_deliver(&sop->evsigmask) == -1)
- return (-1);
-
res = select(sop->event_fds + 1, sop->event_readset_out,
sop->event_writeset_out, NULL, tv);
check_selectop(sop);
- if (evsignal_recalc(&sop->evsigmask) == -1)
- return (-1);
if (res == -1) {
if (errno != EINTR) {
@@ -180,10 +175,11 @@ select_dispatch(struct event_base *base, void *arg, struct timeval *tv)
return (-1);
}
- evsignal_process();
+ evsignal_process(base);
return (0);
- } else if (evsignal_caught)
- evsignal_process();
+ } else if (base->sig.evsignal_caught) {
+ evsignal_process(base);
+ }
event_debug(("%s: select reports %d", __func__, res));
@@ -281,7 +277,7 @@ select_add(void *arg, struct event *ev)
struct selectop *sop = arg;
if (ev->ev_events & EV_SIGNAL)
- return (evsignal_add(&sop->evsigmask, ev));
+ return (evsignal_add(ev));
check_selectop(sop);
/*
@@ -332,7 +328,7 @@ select_del(void *arg, struct event *ev)
check_selectop(sop);
if (ev->ev_events & EV_SIGNAL)
- return (evsignal_del(&sop->evsigmask, ev));
+ return (evsignal_del(ev));
if (sop->event_fds < ev->ev_fd) {
check_selectop(sop);
@@ -354,10 +350,11 @@ select_del(void *arg, struct event *ev)
}
void
-select_dealloc(void *arg)
+select_dealloc(struct event_base *base, void *arg)
{
struct selectop *sop = arg;
+ evsignal_dealloc(base);
if (sop->event_readset_in)
free(sop->event_readset_in);
if (sop->event_writeset_in)
diff --git a/lib/libevent/shlib_version b/lib/libevent/shlib_version
index 1ce8f711fee..b52599a164f 100644
--- a/lib/libevent/shlib_version
+++ b/lib/libevent/shlib_version
@@ -1,2 +1,2 @@
-major=1
-minor=4
+major=2
+minor=0
diff --git a/lib/libevent/signal.c b/lib/libevent/signal.c
index 6b2d052d787..f3b2b9055f0 100644
--- a/lib/libevent/signal.c
+++ b/lib/libevent/signal.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: signal.c,v 1.11 2007/03/19 15:12:49 millert Exp $ */
+/* $OpenBSD: signal.c,v 1.12 2008/05/02 06:09:11 brad Exp $ */
/*
* Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
@@ -31,6 +31,7 @@
#endif
#include <sys/types.h>
+#include <sys/tree.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#else
@@ -47,20 +48,16 @@
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
+#include <assert.h>
#include "event.h"
+#include "event-internal.h"
#include "evsignal.h"
#include "log.h"
-extern struct event_list signalqueue;
+struct event_base *evsignal_base = NULL;
-static sig_atomic_t evsigcaught[NSIG];
-static int needrecalc;
-volatile sig_atomic_t evsignal_caught = 0;
-
-static struct event ev_signal;
-static int ev_signal_pair[2];
-static int ev_signal_added;
+static void evsignal_handler(int sig);
/* Callback for when the signal handler write a byte to our signaling socket */
static void
@@ -86,54 +83,61 @@ evsignal_cb(int fd, short what, void *arg)
#endif
void
-evsignal_init(sigset_t *evsigmask)
+evsignal_init(struct event_base *base)
{
- sigemptyset(evsigmask);
-
/*
* Our signal handler is going to write to one end of the socket
* pair to wake up our event loop. The event loop then scans for
* signals that got delivered.
*/
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, ev_signal_pair) == -1)
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, base->sig.ev_signal_pair) == -1)
event_err(1, "%s: socketpair", __func__);
- FD_CLOSEONEXEC(ev_signal_pair[0]);
- FD_CLOSEONEXEC(ev_signal_pair[1]);
+ FD_CLOSEONEXEC(base->sig.ev_signal_pair[0]);
+ FD_CLOSEONEXEC(base->sig.ev_signal_pair[1]);
+ base->sig.evsignal_caught = 0;
+ memset(&base->sig.evsigcaught, 0, sizeof(sig_atomic_t)*NSIG);
- fcntl(ev_signal_pair[0], F_SETFL, O_NONBLOCK);
+ fcntl(base->sig.ev_signal_pair[0], F_SETFL, O_NONBLOCK);
- event_set(&ev_signal, ev_signal_pair[1], EV_READ,
- evsignal_cb, &ev_signal);
- ev_signal.ev_flags |= EVLIST_INTERNAL;
+ event_set(&base->sig.ev_signal, base->sig.ev_signal_pair[1], EV_READ,
+ evsignal_cb, &base->sig.ev_signal);
+ base->sig.ev_signal.ev_base = base;
+ base->sig.ev_signal.ev_flags |= EVLIST_INTERNAL;
}
int
-evsignal_add(sigset_t *evsigmask, struct event *ev)
+evsignal_add(struct event *ev)
{
int evsignal;
+ struct sigaction sa;
+ struct event_base *base = ev->ev_base;
if (ev->ev_events & (EV_READ|EV_WRITE))
event_errx(1, "%s: EV_SIGNAL incompatible use", __func__);
evsignal = EVENT_SIGNAL(ev);
- sigaddset(evsigmask, evsignal);
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = evsignal_handler;
+ sigfillset(&sa.sa_mask);
+ sa.sa_flags |= SA_RESTART;
+ /* catch signals if they happen quickly */
+ evsignal_base = base;
+
+ if (sigaction(evsignal, &sa, NULL) == -1)
+ return (-1);
+
+ if (!base->sig.ev_signal_added) {
+ base->sig.ev_signal_added = 1;
+ event_add(&base->sig.ev_signal, NULL);
+ }
return (0);
}
-/*
- * Nothing to be done here.
- */
-
int
-evsignal_del(sigset_t *evsigmask, struct event *ev)
+evsignal_del(struct event *ev)
{
- int evsignal;
-
- evsignal = EVENT_SIGNAL(ev);
- sigdelset(evsigmask, evsignal);
- needrecalc = 1;
-
return (sigaction(EVENT_SIGNAL(ev),(struct sigaction *)SIG_DFL, NULL));
}
@@ -142,69 +146,50 @@ evsignal_handler(int sig)
{
int save_errno = errno;
- evsigcaught[sig]++;
- evsignal_caught = 1;
-
- /* Wake up our notification mechanism */
- write(ev_signal_pair[0], "a", 1);
- errno = save_errno;
-}
-
-int
-evsignal_recalc(sigset_t *evsigmask)
-{
- struct sigaction sa;
- struct event *ev;
-
- if (!ev_signal_added) {
- ev_signal_added = 1;
- event_add(&ev_signal, NULL);
- }
-
- if (TAILQ_FIRST(&signalqueue) == NULL && !needrecalc)
- return (0);
- needrecalc = 0;
-
- if (sigprocmask(SIG_BLOCK, evsigmask, NULL) == -1)
- return (-1);
-
- /* Reinstall our signal handler. */
- memset(&sa, 0, sizeof(sa));
- sa.sa_handler = evsignal_handler;
- sa.sa_mask = *evsigmask;
- sa.sa_flags |= SA_RESTART;
-
- TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
- if (sigaction(EVENT_SIGNAL(ev), &sa, NULL) == -1)
- return (-1);
+ if(evsignal_base == NULL) {
+ event_warn(
+ "%s: received signal %s, but have no base configured",
+ __func__, sig);
+ return;
}
- return (0);
-}
-int
-evsignal_deliver(sigset_t *evsigmask)
-{
- if (TAILQ_FIRST(&signalqueue) == NULL)
- return (0);
+ evsignal_base->sig.evsigcaught[sig]++;
+ evsignal_base->sig.evsignal_caught = 1;
- return (sigprocmask(SIG_UNBLOCK, evsigmask, NULL));
- /* XXX - pending signals handled here */
+ /* Wake up our notification mechanism */
+ write(evsignal_base->sig.ev_signal_pair[0], "a", 1);
+ errno = save_errno;
}
void
-evsignal_process(void)
+evsignal_process(struct event_base *base)
{
struct event *ev;
sig_atomic_t ncalls;
- evsignal_caught = 0;
- TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
- ncalls = evsigcaught[EVENT_SIGNAL(ev)];
+ base->sig.evsignal_caught = 0;
+ TAILQ_FOREACH(ev, &base->sig.signalqueue, ev_signal_next) {
+ ncalls = base->sig.evsigcaught[EVENT_SIGNAL(ev)];
if (ncalls) {
if (!(ev->ev_events & EV_PERSIST))
event_del(ev);
event_active(ev, EV_SIGNAL, ncalls);
- evsigcaught[EVENT_SIGNAL(ev)] = 0;
+ base->sig.evsigcaught[EVENT_SIGNAL(ev)] = 0;
}
}
}
+
+void
+evsignal_dealloc(struct event_base *base)
+{
+ if(base->sig.ev_signal_added) {
+ event_del(&base->sig.ev_signal);
+ base->sig.ev_signal_added = 0;
+ }
+ assert(TAILQ_EMPTY(&base->sig.signalqueue));
+
+ close(base->sig.ev_signal_pair[0]);
+ base->sig.ev_signal_pair[0] = -1;
+ close(base->sig.ev_signal_pair[1]);
+ base->sig.ev_signal_pair[1] = -1;
+}
diff --git a/regress/lib/libevent/eventtest.c b/regress/lib/libevent/eventtest.c
index 862c2734e7d..9baa324a269 100644
--- a/regress/lib/libevent/eventtest.c
+++ b/regress/lib/libevent/eventtest.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: eventtest.c,v 1.10 2007/09/19 02:06:45 todd Exp $ */
+/* $OpenBSD: eventtest.c,v 1.11 2008/05/02 06:09:11 brad Exp $ */
/* $NetBSD: eventtest.c,v 1.3 2004/08/07 21:09:47 provos Exp $ */
/*
@@ -430,6 +430,20 @@ test_simplesignal(void)
}
void
+test_immediatesignal(void)
+{
+ struct event ev;
+
+ printf("Immediate signal: ");
+ signal_set(&ev, SIGUSR1, signal_cb, &ev);
+ signal_add(&ev, NULL);
+ raise(SIGUSR1);
+ event_loop(EVLOOP_NONBLOCK);
+ signal_del(&ev);
+ cleanup_test();
+}
+
+void
test_loopexit(void)
{
struct timeval tv, tv_start, tv_end;
@@ -701,6 +715,8 @@ main (int argc, char **argv)
test_simplesignal();
+ test_immediatesignal();
+
test_loopexit();
test_evbuffer();