summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Smith <brad@cvs.openbsd.org>2004-04-28 06:53:13 +0000
committerBrad Smith <brad@cvs.openbsd.org>2004-04-28 06:53:13 +0000
commitf1a8f8a8a269fc9130712441a11947ca19cb17ad (patch)
tree4155a71d2ace6ece769bb248b1a8c3ae38b5c77e
parentc81d4960d450e1bb563668a3ebacc0638dcfc7d0 (diff)
update to libevent 0.8; keep local changes
ok markus@
-rw-r--r--lib/libevent/Makefile26
-rw-r--r--lib/libevent/buffer.c222
-rw-r--r--lib/libevent/evbuffer.c357
-rw-r--r--lib/libevent/event.3140
-rw-r--r--lib/libevent/event.c178
-rw-r--r--lib/libevent/event.h111
-rw-r--r--lib/libevent/evsignal.h7
-rw-r--r--lib/libevent/kqueue.c42
-rw-r--r--lib/libevent/poll.c28
-rw-r--r--lib/libevent/select.c7
-rw-r--r--lib/libevent/signal.c20
11 files changed, 1019 insertions, 119 deletions
diff --git a/lib/libevent/Makefile b/lib/libevent/Makefile
index 33cc7c32c15..8e16474e2f1 100644
--- a/lib/libevent/Makefile
+++ b/lib/libevent/Makefile
@@ -1,22 +1,32 @@
-# $OpenBSD: Makefile,v 1.7 2003/09/23 08:52:04 markus Exp $
+# $OpenBSD: Makefile,v 1.8 2004/04/28 06:53:12 brad Exp $
LIB= event
-SRCS= event.c select.c poll.c signal.c kqueue.c
+SRCS= buffer.c evbuffer.c event.c kqueue.c poll.c select.c signal.c
HDRS= event.h
MAN= event.3
MLINKS= event.3 event_init.3 event.3 event_dispatch.3 event.3 event_loop.3 \
- event.3 event_set.3 event.3 event_add.3 event.3 \
- event_del.3 event.3 event_pending.3 event.3 event_initialized.3 \
- event.3 evtimer_set.3 event.3 evtimer_add.3 event.3 \
- evtimer_del.3 event.3 evtimer_pending.3 event.3 evtimer_initialized.3 \
- event.3 signal_set.3 event.3 signal_add.3 event.3 signal_del.3 \
- event.3 signal_pending.3 event.3 signal_initialized.3
+ event.3 event_loopexit.3 event.3 event_set.3 event.3 event_add.3 event.3 \
+ event_del.3 event.3 event_once.3 event.3 event_pending.3 event.3 \
+ event_initialized.3 event.3 evtimer_set.3 event.3 evtimer_add.3 event.3 \
+ evtimer_del.3 event.3 evtimer_pending.3 event.3 evtimer_initialized.3 \
+ event.3 signal_set.3 event.3 signal_add.3 event.3 signal_del.3 \
+ event.3 signal_pending.3 event.3 signal_initialized.3 event.3 \
+ bufferevent_new.3 event.3 bufferevent_free.3 event.3 bufferevent_write.3 \
+ event.3 bufferevent_write_buffer.3 event.3 bufferevent_read.3 event.3 \
+ bufferevent_enable.3 event.3 bufferevent_disable.3 event.3 \
+ bufferevent_settimeout.3 event.3 evbuffer_new.3 event.3 evbuffer_free.3 \
+ event.3 evbuffer_add.3 event.3 evbuffer_add_buffer.3 event.3 \
+ evbuffer_add_printf.3 event.3 evbuffer_drain.3 event.3 evbuffer_write.3 \
+ event.3 evbuffer_read.3 event.3 evbuffer_find.3
CFLAGS+= -I${.CURDIR} \
-DHAVE_WORKING_KQUEUE \
-DHAVE_SELECT \
-DHAVE_POLL \
-DHAVE_SYS_TIME_H \
+ -DHAVE_STDARG_H \
+ -DHAVE_UNISTD_H \
+ -DNOTE_EOF
NOPIC=
diff --git a/lib/libevent/buffer.c b/lib/libevent/buffer.c
new file mode 100644
index 00000000000..f9a1f1b4d22
--- /dev/null
+++ b/lib/libevent/buffer.c
@@ -0,0 +1,222 @@
+/* $OpenBSD: buffer.c,v 1.1 2004/04/28 06:53:12 brad Exp $ */
+
+/*
+ * Copyright (c) 2002, 2003 Niels Provos <provos@citi.umich.edu>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "event.h"
+
+struct evbuffer *
+evbuffer_new(void)
+{
+ struct evbuffer *buffer;
+
+ buffer = calloc(1, sizeof(struct evbuffer));
+
+ return (buffer);
+}
+
+void
+evbuffer_free(struct evbuffer *buffer)
+{
+ if (buffer->buffer != NULL)
+ free(buffer->buffer);
+ free(buffer);
+}
+
+/*
+ * This is a destructive add. The data from one buffer moves into
+ * the other buffer.
+ */
+
+int
+evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf)
+{
+ int res;
+ res = evbuffer_add(outbuf, inbuf->buffer, inbuf->off);
+ if (res == 0)
+ evbuffer_drain(inbuf, inbuf->off);
+
+ return (res);
+}
+
+int
+evbuffer_add_printf(struct evbuffer *buf, char *fmt, ...)
+{
+ int res = -1;
+ char *msg;
+ va_list ap;
+
+ va_start(ap, fmt);
+
+ if (vasprintf(&msg, fmt, ap) == -1)
+ goto end;
+
+ res = strlen(msg);
+ if (evbuffer_add(buf, msg, res) == -1)
+ res = -1;
+ free(msg);
+
+ end:
+ va_end(ap);
+
+ return (res);
+}
+
+int
+evbuffer_add(struct evbuffer *buf, u_char *data, size_t datlen)
+{
+ size_t need = buf->off + datlen;
+ size_t oldoff = buf->off;
+
+ if (buf->totallen < need) {
+ void *newbuf;
+ int length = buf->totallen;
+
+ if (length < 256)
+ length = 256;
+ while (length < need)
+ length <<= 1;
+
+ if ((newbuf = realloc(buf->buffer, length)) == NULL)
+ return (-1);
+
+ buf->buffer = newbuf;
+ buf->totallen = length;
+ }
+
+ memcpy(buf->buffer + buf->off, data, datlen);
+ buf->off += datlen;
+
+ if (datlen && buf->cb != NULL)
+ (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
+
+ return (0);
+}
+
+void
+evbuffer_drain(struct evbuffer *buf, size_t len)
+{
+ size_t oldoff = buf->off;
+
+ if (len >= buf->off) {
+ buf->off = 0;
+ goto done;
+ }
+
+ memmove(buf->buffer, buf->buffer + len, buf->off - len);
+ buf->off -= len;
+
+ done:
+ /* Tell someone about changes in this buffer */
+ if (buf->off != oldoff && buf->cb != NULL)
+ (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
+
+}
+
+int
+evbuffer_read(struct evbuffer *buffer, int fd, int howmuch)
+{
+ u_char inbuf[4096];
+ int n;
+
+ if (howmuch < 0 || howmuch > sizeof(inbuf))
+ howmuch = sizeof(inbuf);
+
+ n = read(fd, inbuf, howmuch);
+ if (n == -1)
+ return (-1);
+ if (n == 0)
+ return (0);
+
+ evbuffer_add(buffer, inbuf, n);
+
+ return (n);
+}
+
+int
+evbuffer_write(struct evbuffer *buffer, int fd)
+{
+ int n;
+
+ n = write(fd, buffer->buffer, buffer->off);
+ if (n == -1)
+ return (-1);
+ if (n == 0)
+ return (0);
+
+ evbuffer_drain(buffer, n);
+
+ return (n);
+}
+
+u_char *
+evbuffer_find(struct evbuffer *buffer, u_char *what, size_t len)
+{
+ size_t remain = buffer->off;
+ u_char *search = buffer->buffer;
+ u_char *p;
+
+ while ((p = memchr(search, *what, remain)) != NULL && remain >= len) {
+ if (memcmp(p, what, len) == 0)
+ return (p);
+
+ search = p + 1;
+ remain = buffer->off - (size_t)(search - buffer->buffer);
+ }
+
+ return (NULL);
+}
+
+void evbuffer_setcb(struct evbuffer *buffer,
+ void (*cb)(struct evbuffer *, size_t, size_t, void *),
+ void *cbarg)
+{
+ buffer->cb = cb;
+ buffer->cbarg = cbarg;
+}
diff --git a/lib/libevent/evbuffer.c b/lib/libevent/evbuffer.c
new file mode 100644
index 00000000000..453edff08cd
--- /dev/null
+++ b/lib/libevent/evbuffer.c
@@ -0,0 +1,357 @@
+/* $OpenBSD: evbuffer.c,v 1.1 2004/04/28 06:53:12 brad Exp $ */
+
+/*
+ * Copyright (c) 2002-2004 Niels Provos <provos@citi.umich.edu>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+
+#include "event.h"
+
+static int
+bufferevent_add(struct event *ev, int timeout)
+{
+ struct timeval tv, *ptv = NULL;
+
+ if (timeout) {
+ timerclear(&tv);
+ tv.tv_sec = timeout;
+ ptv = &tv;
+ }
+
+ return (event_add(ev, ptv));
+}
+
+/*
+ * This callback is executed when the size of the input buffer changes.
+ * We use it to apply back pressure on the reading side.
+ */
+
+void
+bufferevent_read_pressure_cb(struct evbuffer *buf, size_t old, size_t now,
+ void *arg) {
+ struct bufferevent *bufev = arg;
+ /*
+ * If we are below the watermak then reschedule reading if it's
+ * still enabled.
+ */
+ if (bufev->wm_read.high == 0 || now < bufev->wm_read.high) {
+ evbuffer_setcb(buf, NULL, NULL);
+
+ if (bufev->enabled & EV_READ)
+ bufferevent_add(&bufev->ev_read, bufev->timeout_read);
+ }
+}
+
+static void
+bufferevent_readcb(int fd, short event, void *arg)
+{
+ struct bufferevent *bufev = arg;
+ int res = 0;
+ short what = EVBUFFER_READ;
+ size_t len;
+
+ if (event == EV_TIMEOUT) {
+ what |= EVBUFFER_TIMEOUT;
+ goto error;
+ }
+
+ res = evbuffer_read(bufev->input, fd, -1);
+ if (res == -1) {
+ if (errno == EAGAIN || errno == EINTR)
+ goto reschedule;
+ /* error case */
+ what |= EVBUFFER_ERROR;
+ } else if (res == 0) {
+ /* eof case */
+ what |= EVBUFFER_EOF;
+ }
+
+ if (res <= 0)
+ goto error;
+
+ bufferevent_add(&bufev->ev_read, bufev->timeout_read);
+
+ /* See if this callbacks meets the water marks */
+ len = EVBUFFER_LENGTH(bufev->input);
+ if (bufev->wm_read.low != 0 && len < bufev->wm_read.low)
+ return;
+ if (bufev->wm_read.high != 0 && len > bufev->wm_read.high) {
+ struct evbuffer *buf = bufev->input;
+ event_del(&bufev->ev_read);
+
+ /* Now schedule a callback for us */
+ evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev);
+ return;
+ }
+
+ /* Invoke the user callback - must always be called last */
+ (*bufev->readcb)(bufev, bufev->cbarg);
+ return;
+
+ reschedule:
+ bufferevent_add(&bufev->ev_read, bufev->timeout_read);
+ return;
+
+ error:
+ (*bufev->errorcb)(bufev, what, bufev->cbarg);
+}
+
+static void
+bufferevent_writecb(int fd, short event, void *arg)
+{
+ struct bufferevent *bufev = arg;
+ int res = 0;
+ short what = EVBUFFER_WRITE;
+
+ if (event == EV_TIMEOUT) {
+ what |= EVBUFFER_TIMEOUT;
+ goto error;
+ }
+
+ if (EVBUFFER_LENGTH(bufev->output)) {
+ res = evbuffer_write(bufev->output, fd);
+ if (res == -1) {
+ if (errno == EAGAIN || errno == EINTR)
+ goto reschedule;
+ /* error case */
+ what |= EVBUFFER_ERROR;
+ } else if (res == 0) {
+ /* eof case */
+ what |= EVBUFFER_EOF;
+ }
+ if (res <= 0)
+ goto error;
+ }
+
+ if (EVBUFFER_LENGTH(bufev->output) != 0)
+ bufferevent_add(&bufev->ev_write, bufev->timeout_write);
+
+ /*
+ * Invoke the user callback if our buffer is drained or below the
+ * low watermark.
+ */
+ if (EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low)
+ (*bufev->writecb)(bufev, bufev->cbarg);
+
+ return;
+
+ reschedule:
+ if (EVBUFFER_LENGTH(bufev->output) != 0)
+ bufferevent_add(&bufev->ev_write, bufev->timeout_write);
+ return;
+
+ error:
+ (*bufev->errorcb)(bufev, what, bufev->cbarg);
+}
+
+/*
+ * Create a new buffered event object.
+ *
+ * The read callback is invoked whenever we read new data.
+ * The write callback is invoked whenever the output buffer is drained.
+ * The error callback is invoked on a write/read error or on EOF.
+ */
+
+struct bufferevent *
+bufferevent_new(int fd, evbuffercb readcb, evbuffercb writecb,
+ everrorcb errorcb, void *cbarg)
+{
+ struct bufferevent *bufev;
+
+ if ((bufev = calloc(1, sizeof(struct bufferevent))) == NULL)
+ return (NULL);
+
+ if ((bufev->input = evbuffer_new()) == NULL) {
+ free(bufev);
+ return (NULL);
+ }
+
+ if ((bufev->output = evbuffer_new()) == NULL) {
+ evbuffer_free(bufev->input);
+ free(bufev);
+ return (NULL);
+ }
+
+ event_set(&bufev->ev_read, fd, EV_READ, bufferevent_readcb, bufev);
+ event_set(&bufev->ev_write, fd, EV_WRITE, bufferevent_writecb, bufev);
+
+ bufev->readcb = readcb;
+ bufev->writecb = writecb;
+ bufev->errorcb = errorcb;
+
+ bufev->cbarg = cbarg;
+
+ bufev->enabled = EV_READ | EV_WRITE;
+
+ return (bufev);
+}
+
+void
+bufferevent_free(struct bufferevent *bufev)
+{
+ event_del(&bufev->ev_read);
+ event_del(&bufev->ev_write);
+
+ evbuffer_free(bufev->input);
+ evbuffer_free(bufev->output);
+
+ free(bufev);
+}
+
+/*
+ * Returns 0 on success;
+ * -1 on failure.
+ */
+
+int
+bufferevent_write(struct bufferevent *bufev, void *data, size_t size)
+{
+ int res;
+
+ res = evbuffer_add(bufev->output, data, size);
+
+ if (res == -1)
+ return (res);
+
+ /* If everything is okay, we need to schedule a write */
+ if (size > 0 && (bufev->enabled & EV_WRITE))
+ bufferevent_add(&bufev->ev_write, bufev->timeout_write);
+
+ return (res);
+}
+
+int
+bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf)
+{
+ int res;
+
+ res = bufferevent_write(bufev, buf->buffer, buf->off);
+ if (res != -1)
+ evbuffer_drain(buf, buf->off);
+
+ return (res);
+}
+
+size_t
+bufferevent_read(struct bufferevent *bufev, void *data, size_t size)
+{
+ struct evbuffer *buf = bufev->input;
+
+ if (buf->off < size)
+ size = buf->off;
+
+ /* Copy the available data to the user buffer */
+ memcpy(data, buf->buffer, size);
+
+ if (size)
+ evbuffer_drain(buf, size);
+
+ return (size);
+}
+
+int
+bufferevent_enable(struct bufferevent *bufev, short event)
+{
+ if (event & EV_READ) {
+ if (bufferevent_add(&bufev->ev_read, bufev->timeout_read) == -1)
+ return (-1);
+ }
+ if (event & EV_WRITE) {
+ if (bufferevent_add(&bufev->ev_write, bufev->timeout_write) == -1)
+ return (-1);
+ }
+
+ bufev->enabled |= event;
+ return (0);
+}
+
+int
+bufferevent_disable(struct bufferevent *bufev, short event)
+{
+ if (event & EV_READ) {
+ if (event_del(&bufev->ev_read) == -1)
+ return (-1);
+ }
+ if (event & EV_WRITE) {
+ if (event_del(&bufev->ev_write) == -1)
+ return (-1);
+ }
+
+ bufev->enabled &= ~event;
+ return (0);
+}
+
+/*
+ * Sets the read and write timeout for a buffered event.
+ */
+
+void
+bufferevent_settimeout(struct bufferevent *bufev,
+ int timeout_read, int timeout_write) {
+ bufev->timeout_read = timeout_read;
+ bufev->timeout_write = timeout_write;
+}
+
+/*
+ * Sets the water marks
+ */
+
+void
+bufferevent_setwatermark(struct bufferevent *bufev, short events,
+ size_t lowmark, size_t highmark)
+{
+ if (events & EV_READ) {
+ bufev->wm_read.low = lowmark;
+ bufev->wm_read.high = highmark;
+ }
+
+ if (events & EV_WRITE) {
+ bufev->wm_write.low = lowmark;
+ bufev->wm_write.high = highmark;
+ }
+
+ /* If the watermarks changed then see if we should call read again */
+ bufferevent_read_pressure_cb(bufev->input,
+ 0, EVBUFFER_LENGTH(bufev->input), bufev);
+}
diff --git a/lib/libevent/event.3 b/lib/libevent/event.3
index 3db118f1e09..51b07c07743 100644
--- a/lib/libevent/event.3
+++ b/lib/libevent/event.3
@@ -1,4 +1,4 @@
-.\" $OpenBSD: event.3,v 1.10 2003/09/23 08:52:04 markus Exp $
+.\" $OpenBSD: event.3,v 1.11 2004/04/28 06:53:12 brad Exp $
.\"
.\" Copyright (c) 2000 Artur Grabowski <art@openbsd.org>
.\" All rights reserved.
@@ -30,9 +30,11 @@
.Nm event_init ,
.Nm event_dispatch ,
.Nm event_loop ,
+.Nm event_loopexit ,
.Nm event_set ,
.Nm event_add ,
.Nm event_del ,
+.Nm event_once ,
.Nm event_pending ,
.Nm event_initialized ,
.Nm evtimer_set ,
@@ -44,7 +46,24 @@
.Nm signal_add ,
.Nm signal_del ,
.Nm signal_pending ,
-.Nm signal_initialized
+.Nm signal_initialized ,
+.Nm bufferevent_new ,
+.Nm bufferevent_free ,
+.Nm bufferevent_write ,
+.Nm bufferevent_write_buffer ,
+.Nm bufferevent_read ,
+.Nm bufferevent_enable ,
+.Nm bufferevent_disable ,
+.Nm bufferevent_settimeout ,
+.Nm evbuffer_new ,
+.Nm evbuffer_free ,
+.Nm evbuffer_add ,
+.Nm evbuffer_add_buffer ,
+.Nm evbuffer_add_printf ,
+.Nm evbuffer_drain ,
+.Nm evbuffer_write ,
+.Nm evbuffer_read ,
+.Nm evbuffer_find
.Nd execute a function when a specific event occurs
.Sh SYNOPSIS
.Fd #include <sys/time.h>
@@ -55,6 +74,8 @@
.Fn "event_dispatch"
.Ft int
.Fn "event_loop" "int flags"
+.Ft int
+.Fn "event_loopexit" "struct timeval *tv"
.Ft void
.Fn "event_set" "struct event *ev" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg"
.Ft int
@@ -62,6 +83,8 @@
.Ft int
.Fn "event_del" "struct event *ev"
.Ft int
+.Fn "event_once" "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"
@@ -85,6 +108,40 @@
.Fn "signal_pending" "struct event *ev" "struct timeval *tv"
.Ft int
.Fn "signal_initialized" "struct event *ev"
+.Ft "struct bufferevent *"
+.Fn "bufferevent_new" "int fd" "evbuffercb readcb" "evbuffercb writecb" "everrorcb" "void *cbarg"
+.Ft void
+.Fn "bufferevent_free" "struct bufferevent *bufev"
+.Ft int
+.Fn "bufferevent_write" "struct bufferevent *bufev" "void *data" "size_t size"
+.Ft int
+.Fn "bufferevent_write_buffer" "struct bufferevent *bufev" "struct evbuffer *buf"
+.Ft size_t
+.Fn "bufferevent_read" "struct bufferevent *bufev" "void *data" "size_t size"
+.Ft int
+.Fn "bufferevent_enable" "struct bufferevent *bufev" "short event"
+.Ft int
+.Fn "bufferevent_disable" "struct bufferevent *bufev" "short event"
+.Ft void
+.Fn "bufferevent_settimeout" "struct bufferevent *bufev" "int timeout_read" "int timeout_write"
+.Ft "struct evbuffer *"
+.Fn "evbuffer_new" "void"
+.Ft void
+.Fn "evbuffer_free" "struct evbuffer *buf"
+.Ft int
+.Fn "evbuffer_add" "struct evbuffer *buf" "u_char *data" "size_t size"
+.Ft int
+.Fn "evbuffer_add_buffer" "struct evbuffer *dst" "struct evbuffer *src"
+.Ft int
+.Fn "evbuffer_add_printf" "struct evbuffer *buf" "char *fmt" "..."
+.Ft void
+.Fn "evbuffer_drain" "struct evbuffer *buf" "size_t size"
+.Ft int
+.Fn "evbuffer_write" "struct evbuffer *buf" "int fd"
+.Ft int
+.Fn "evbuffer_read" "struct evbuffer *buf" "int fd" "int size"
+.Ft "u_char *"
+.Fn "evbuffer_find" "struct evbuffer *buf" "u_char *data" "size_t size"
.Ft int
.Fa (*event_sigcb)(void) ;
.Ft int
@@ -142,6 +199,11 @@ The flags
and
.Va EVLOOP_NONBLOCK
are recognized.
+The
+.Nm event_loopexit
+function allows the loop to be terminated after some amount of time
+has passed.
+The parameter indicates the time after which the loop should terminate.
.Pp
It is the responsibility of the caller to provide these functions with
pre-allocated event structures.
@@ -233,6 +295,20 @@ will cancel the event in the argument
If the event has already executed or has never been added
the call will have no effect.
.Pp
+The function
+.Fn event_once
+is similiar to
+.Fn event_set .
+However, it schedules a callback to be called exactly once and does not
+require the caller to prepare an
+.Fa event
+structure.
+This function supports
+.Fa EV_TIMEOUT ,
+.Fa EV_READ
+and
+.Fa EV_WRITE .
+.Pp
The
.Fn event_pending
function can be used to check if the event specified by
@@ -278,13 +354,11 @@ adds
.Va EV_PERSIST .
.Pp
It is possible to disable support for
-.Xr kqueue 2 ,
-.Xr poll 2 ,
+.Va epoll , kqueue , poll
or
-.Xr select 2
+.Va select
by setting the environment variable
-.Va EVENT_NOKQUEUE ,
-.Va EVENT_NOPOLL ,
+.Va EVENT_NOEPOLL , EVENT_NOKQUEUE , EVENT_NOPOLL
or
.Va EVENT_NOSELECT .
By setting the environment variable
@@ -292,6 +366,47 @@ By setting the environment variable
.Nm libevent
displays the kernel notification method that it uses.
.Pp
+.Sh BUFFERED EVENTS
+.Nm libevent
+provides an abstraction on top of the regular event callbacks.
+This abstraction is called a
+.Va "buffered event" .
+A buffered event provides input and output buffer that get filled
+and drained automatically.
+The user of a buffered event no longer deals directly with the IO,
+but instead is reading from input and writing to output buffers.
+.Pp
+A new bufferevent is created by
+.Fn bufferevent_new .
+The parameter
+.Fa "fd"
+specifies the file descriptor from which data is read and written to.
+This file descriptor is not allowed to be a
+.Xr pipe 2 .
+The next three parameters are callbacks.
+The read and write callback have the following form
+.Ft void
+.Fn "(*cb)" "struct bufferevent *bufev" "void *arg"
+The argument is specified by the fourth parameter
+.Fa "cbarg" .
+.Pp
+By default the buffered event is read enabled and will try to read
+from the file descriptor.
+The write callback is executed whenever the output buffer is drained
+below the write low watermark which is
+.Va 0
+by default.
+.Pp
+The
+.Fn bufferevent_write
+function can be used to write data to the file descriptor.
+The data is appended to the output buffer and written to the descriptor
+automatically as it becomes available for writing.
+The
+.Fn bufferevent_read
+function is used to read data from the input buffer.
+Both functions return the amount of data written or read.
+.Pp
.Sh RETURN VALUES
Upon successful completion
.Fn event_add
@@ -311,7 +426,18 @@ The
API manpage is based on the
.Xr timeout 9
manpage by Artur Grabowski.
+The port of
+.Nm libevent
+to Windows is due to Michael A. Davis.
+Support for real-time signals is due to Taral.
.Sh AUTHORS
The
.Nm event
library was written by Niels Provos.
+.Pp
+.Sh BUGS
+This documentation is neither complete nor authorative.
+If you are in doubt about the usage of this API then
+check the source code to find out how it works, write
+up the missing piece of documentation and send it to
+me for inclusion in this man page.
diff --git a/lib/libevent/event.c b/lib/libevent/event.c
index a7896cf1dcc..ce774f4ead3 100644
--- a/lib/libevent/event.c
+++ b/lib/libevent/event.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: event.c,v 1.4 2003/07/09 10:54:38 markus Exp $ */
+/* $OpenBSD: event.c,v 1.5 2004/04/28 06:53:12 brad Exp $ */
/*
- * Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
+ * Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -12,10 +12,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Niels Provos.
- * 4. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
@@ -33,6 +30,12 @@
#include "config.h"
#endif
+#ifdef WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+#include "misc.h"
+#endif
#include <sys/types.h>
#include <sys/tree.h>
#ifdef HAVE_SYS_TIME_H
@@ -43,7 +46,9 @@
#include <sys/queue.h>
#include <stdio.h>
#include <stdlib.h>
+#ifndef WIN32
#include <unistd.h>
+#endif
#include <errno.h>
#include <string.h>
#include <err.h>
@@ -62,14 +67,20 @@
extern const struct eventop selectops;
#endif
#ifdef HAVE_POLL
-extern struct eventop pollops;
+extern const struct eventop pollops;
+#endif
+#ifdef HAVE_RTSIG
+extern const struct eventop rtsigops;
#endif
#ifdef HAVE_EPOLL
-extern struct eventop epollops;
+extern const struct eventop epollops;
#endif
#ifdef HAVE_WORKING_KQUEUE
extern const struct eventop kqops;
#endif
+#ifdef WIN32
+extern const struct eventop win32ops;
+#endif
/* In order of preference */
const struct eventop *eventops[] = {
@@ -79,25 +90,35 @@ const struct eventop *eventops[] = {
#ifdef HAVE_EPOLL
&epollops,
#endif
+#ifdef HAVE_RTSIG
+ &rtsigops,
+#endif
#ifdef HAVE_POLL
&pollops,
#endif
#ifdef HAVE_SELECT
&selectops,
#endif
+#ifdef WIN32
+ &win32ops,
+#endif
NULL
};
const struct eventop *evsel;
void *evbase;
-/* Handle signals */
+/* Handle signals - This is a deprecated interface */
int (*event_sigcb)(void); /* Signal callback when gotsig is set */
int event_gotsig; /* Set in signal handler */
+int event_gotterm; /* Set to terminate loop */
/* Prototypes */
-void event_queue_insert(struct event *, int);
-void event_queue_remove(struct event *, int);
+void event_queue_insert(struct event *, int);
+void event_queue_remove(struct event *, int);
+int event_haveevents(void);
+
+static void event_process_active(void);
static RB_HEAD(event_tree, event) timetree;
static struct event_list activequeue;
@@ -112,6 +133,10 @@ compare(struct event *a, struct event *b)
return (-1);
else if (timercmp(&a->ev_timeout, &b->ev_timeout, >))
return (1);
+ if (a < b)
+ return (-1);
+ if (a > b)
+ return (1);
return (0);
}
@@ -160,7 +185,7 @@ event_haveevents(void)
TAILQ_FIRST(&signalqueue) || TAILQ_FIRST(&activequeue));
}
-void
+static void
event_process_active(void)
{
struct event *ev;
@@ -176,17 +201,33 @@ event_process_active(void)
while (ncalls) {
ncalls--;
ev->ev_ncalls = ncalls;
- (*ev->ev_callback)(ev->ev_fd, ev->ev_res, ev->ev_arg);
+ (*ev->ev_callback)((int)ev->ev_fd, ev->ev_res, ev->ev_arg);
}
}
}
+/*
+ * Wait continously for events. We exit only if no events are left.
+ */
+
int
event_dispatch(void)
{
return (event_loop(0));
}
+static void
+event_loopexit_cb(int fd, short what, void *arg)
+{
+ event_gotterm = 1;
+}
+
+int
+event_loopexit(struct timeval *tv)
+{
+ return (event_once(-1, EV_TIMEOUT, event_loopexit_cb, NULL, tv));
+}
+
int
event_loop(int flags)
{
@@ -199,6 +240,12 @@ event_loop(int flags)
done = 0;
while (!done) {
+ /* Terminate the loop if we have been asked to */
+ if (event_gotterm) {
+ event_gotterm = 0;
+ break;
+ }
+
while (event_gotsig) {
event_gotsig = 0;
if (event_sigcb) {
@@ -214,7 +261,7 @@ event_loop(int flags)
gettimeofday(&tv, NULL);
if (timercmp(&tv, &event_tv, <)) {
struct timeval off;
- LOG_DBG((LOG_MIST, 10,
+ LOG_DBG((LOG_MISC, 10,
"%s: time is running backwards, corrected",
__func__));
@@ -253,13 +300,78 @@ event_loop(int flags)
return (0);
}
+/* Sets up an event for processing once */
+
+struct event_once {
+ struct event ev;
+
+ void (*cb)(int, short, void *);
+ void *arg;
+};
+
+/* One-time callback, it deletes itself */
+
+static void
+event_once_cb(int fd, short events, void *arg)
+{
+ struct event_once *eonce = arg;
+
+ (*eonce->cb)(fd, events, eonce->arg);
+ free(eonce);
+}
+
+/* Schedules an event once */
+
+int
+event_once(int fd, short events,
+ void (*callback)(int, short, void *), void *arg, struct timeval *tv)
+{
+ struct event_once *eonce;
+ struct timeval etv;
+
+ /* We cannot support signals that just fire once */
+ if (events & EV_SIGNAL)
+ return (-1);
+
+ if ((eonce = calloc(1, sizeof(struct event_once))) == NULL)
+ return (-1);
+
+ if (events == EV_TIMEOUT) {
+ if (tv == NULL) {
+ timerclear(&etv);
+ tv = &etv;
+ }
+
+ eonce->cb = callback;
+ eonce->arg = arg;
+
+ evtimer_set(&eonce->ev, event_once_cb, eonce);
+ } else if (events & (EV_READ|EV_WRITE)) {
+ events &= EV_READ|EV_WRITE;
+
+ event_set(&eonce->ev, fd, events, event_once_cb, eonce);
+ } else {
+ /* Bad event combination */
+ return (-1);
+ }
+
+ event_add(&eonce->ev, tv);
+
+ return (0);
+}
+
void
event_set(struct event *ev, int fd, short events,
void (*callback)(int, short, void *), void *arg)
{
ev->ev_callback = callback;
ev->ev_arg = arg;
+#ifdef WIN32
+ ev->ev_fd = (HANDLE)fd;
+ ev->overlap.hEvent = ev;
+#else
ev->ev_fd = fd;
+#endif
ev->ev_events = events;
ev->ev_flags = EVLIST_INIT;
ev->ev_ncalls = 0;
@@ -281,8 +393,10 @@ event_pending(struct event *ev, short event, struct timeval *tv)
flags |= ev->ev_res;
if (ev->ev_flags & EVLIST_TIMEOUT)
flags |= EV_TIMEOUT;
+ if (ev->ev_flags & EVLIST_SIGNAL)
+ flags |= EV_SIGNAL;
- event &= (EV_TIMEOUT|EV_READ|EV_WRITE);
+ event &= (EV_TIMEOUT|EV_READ|EV_WRITE|EV_SIGNAL);
/* See if there is a timeout that we should report */
if (tv != NULL && (flags & event & EV_TIMEOUT))
@@ -420,6 +534,9 @@ timeout_next(struct timeval *tv)
timersub(&ev->ev_timeout, &now, tv);
+ assert(tv->tv_sec >= 0);
+ assert(tv->tv_usec >= 0);
+
LOG_DBG((LOG_MISC, 60, "timeout_next: in %d seconds", tv->tv_sec));
return (0);
}
@@ -461,31 +578,6 @@ timeout_process(void)
}
void
-timeout_insert(struct event *ev)
-{
- struct event *tmp;
-
- tmp = RB_FIND(event_tree, &timetree, ev);
-
- if (tmp != NULL) {
- struct timeval tv;
- struct timeval add = {0,1};
-
- /* Find unique time */
- tv = ev->ev_timeout;
- do {
- timeradd(&tv, &add, &tv);
- tmp = RB_NEXT(event_tree, &timetree, tmp);
- } while (tmp != NULL && timercmp(&tmp->ev_timeout, &tv, ==));
-
- ev->ev_timeout = tv;
- }
-
- tmp = RB_INSERT(event_tree, &timetree, ev);
- assert(tmp == NULL);
-}
-
-void
event_queue_remove(struct event *ev, int queue)
{
if (!(ev->ev_flags & queue))
@@ -526,9 +618,11 @@ event_queue_insert(struct event *ev, int queue)
case EVLIST_SIGNAL:
TAILQ_INSERT_TAIL(&signalqueue, ev, ev_signal_next);
break;
- case EVLIST_TIMEOUT:
- timeout_insert(ev);
+ case EVLIST_TIMEOUT: {
+ struct event *tmp = RB_INSERT(event_tree, &timetree, ev);
+ assert(tmp == NULL);
break;
+ }
case EVLIST_INSERTED:
TAILQ_INSERT_TAIL(&eventqueue, ev, ev_next);
break;
diff --git a/lib/libevent/event.h b/lib/libevent/event.h
index e50050e2fe1..50f88f59c1b 100644
--- a/lib/libevent/event.h
+++ b/lib/libevent/event.h
@@ -1,7 +1,7 @@
-/* $OpenBSD: event.h,v 1.4 2002/07/12 18:50:48 provos Exp $ */
+/* $OpenBSD: event.h,v 1.5 2004/04/28 06:53:12 brad Exp $ */
/*
- * Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
+ * Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -12,10 +12,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Niels Provos.
- * 4. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
@@ -36,6 +33,10 @@
extern "C" {
#endif
+#ifdef WIN32
+#include <windows.h>
+#endif
+
#define EVLIST_TIMEOUT 0x01
#define EVLIST_INSERTED 0x02
#define EVLIST_SIGNAL 0x04
@@ -77,7 +78,12 @@ struct event {
TAILQ_ENTRY (event) ev_signal_next;
RB_ENTRY (event) ev_timeout_node;
+#ifdef WIN32
+ HANDLE ev_fd;
+ OVERLAPPED overlap;
+#else
int ev_fd;
+#endif
short ev_events;
short ev_ncalls;
short *ev_pncalls; /* Allows deletes in callback */
@@ -91,8 +97,8 @@ struct event {
int ev_flags;
};
-#define EVENT_SIGNAL(ev) ev->ev_fd
-#define EVENT_FD(ev) ev->ev_fd
+#define EVENT_SIGNAL(ev) (int)ev->ev_fd
+#define EVENT_FD(ev) (int)ev->ev_fd
#ifdef _EVENT_DEFINED_TQENTRY
#undef TAILQ_ENTRY
@@ -122,6 +128,7 @@ int event_dispatch(void);
#define EVLOOP_ONCE 0x01
#define EVLOOP_NONBLOCK 0x02
int event_loop(int);
+int event_loopexit(struct timeval *); /* Causes the loop to exit */
int timeout_next(struct timeval *);
void timeout_correct(struct timeval *);
@@ -133,6 +140,12 @@ void timeout_process(void);
#define evtimer_pending(ev, tv) event_pending(ev, EV_TIMEOUT, tv)
#define evtimer_initialized(ev) ((ev)->ev_flags & EVLIST_INIT)
+#define timeout_add(ev, tv) event_add(ev, tv)
+#define timeout_set(ev, cb, arg) event_set(ev, -1, 0, cb, arg)
+#define timeout_del(ev) event_del(ev)
+#define timeout_pending(ev, tv) event_pending(ev, EV_TIMEOUT, tv)
+#define timeout_initialized(ev) ((ev)->ev_flags & EVLIST_INIT)
+
#define signal_add(ev, tv) event_add(ev, tv)
#define signal_set(ev, x, cb, arg) \
event_set(ev, x, EV_SIGNAL|EV_PERSIST, cb, arg)
@@ -141,13 +154,95 @@ void timeout_process(void);
#define signal_initialized(ev) ((ev)->ev_flags & EVLIST_INIT)
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_add(struct event *, struct timeval *);
int event_del(struct event *);
void event_active(struct event *, int, short);
int event_pending(struct event *, short, struct timeval *);
+#ifdef WIN32
+#define event_initialized(ev) ((ev)->ev_flags & EVLIST_INIT && (ev)->ev_fd != INVALID_HANDLE_VALUE)
+#else
#define event_initialized(ev) ((ev)->ev_flags & EVLIST_INIT)
+#endif
+
+/* These functions deal with buffering input and output */
+
+struct evbuffer {
+ u_char *buffer;
+
+ size_t totallen;
+ size_t off;
+
+ void (*cb)(struct evbuffer *, size_t, size_t, void *);
+ void *cbarg;
+};
+
+/* Just for error reporting - use other constants otherwise */
+#define EVBUFFER_READ 0x01
+#define EVBUFFER_WRITE 0x02
+#define EVBUFFER_EOF 0x10
+#define EVBUFFER_ERROR 0x20
+#define EVBUFFER_TIMEOUT 0x40
+
+struct bufferevent;
+typedef void (*evbuffercb)(struct bufferevent *, void *);
+typedef void (*everrorcb)(struct bufferevent *, short what, void *);
+
+struct event_watermark {
+ size_t low;
+ size_t high;
+};
+
+struct bufferevent {
+ struct event ev_read;
+ struct event ev_write;
+
+ struct evbuffer *input;
+ struct evbuffer *output;
+
+ struct event_watermark wm_read;
+ struct event_watermark wm_write;
+
+ evbuffercb readcb;
+ evbuffercb writecb;
+ everrorcb errorcb;
+ void *cbarg;
+
+ int timeout_read; /* in seconds */
+ int timeout_write; /* in seconds */
+
+ short enabled; /* events that are currently enabled */
+};
+
+struct bufferevent *bufferevent_new(int fd,
+ evbuffercb readcb, evbuffercb writecb, everrorcb errorcb, void *cbarg);
+void bufferevent_free(struct bufferevent *bufev);
+int bufferevent_write(struct bufferevent *bufev, void *data, size_t size);
+int bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf);
+size_t bufferevent_read(struct bufferevent *bufev, void *data, size_t size);
+int bufferevent_enable(struct bufferevent *bufev, short event);
+int bufferevent_disable(struct bufferevent *bufev, short event);
+void bufferevent_settimeout(struct bufferevent *bufev,
+ int timeout_read, int timeout_write);
+
+#define EVBUFFER_LENGTH(x) (x)->off
+#define EVBUFFER_DATA(x) (x)->buffer
+#define EVBUFFER_INPUT(x) (x)->input
+#define EVBUFFER_OUTPUT(x) (x)->output
+
+struct evbuffer *evbuffer_new(void);
+void evbuffer_free(struct evbuffer *);
+int evbuffer_add(struct evbuffer *, u_char *, size_t);
+int evbuffer_add_buffer(struct evbuffer *, struct evbuffer *);
+int evbuffer_add_printf(struct evbuffer *, char *fmt, ...);
+void evbuffer_drain(struct evbuffer *, size_t);
+int evbuffer_write(struct evbuffer *, int);
+int evbuffer_read(struct evbuffer *, int, int);
+u_char *evbuffer_find(struct evbuffer *, u_char *, size_t);
+void evbuffer_setcb(struct evbuffer *, void (*)(struct evbuffer *, size_t, size_t, void *), void *);
#ifdef __cplusplus
}
diff --git a/lib/libevent/evsignal.h b/lib/libevent/evsignal.h
index 630c18f038a..aa77c9c8122 100644
--- a/lib/libevent/evsignal.h
+++ b/lib/libevent/evsignal.h
@@ -1,3 +1,5 @@
+/* $OpenBSD: evsignal.h,v 1.2 2004/04/28 06:53:12 brad Exp $ */
+
/*
* Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
@@ -10,10 +12,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Niels Provos.
- * 4. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
diff --git a/lib/libevent/kqueue.c b/lib/libevent/kqueue.c
index 0e9ee45f0b2..29625e1cd73 100644
--- a/lib/libevent/kqueue.c
+++ b/lib/libevent/kqueue.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kqueue.c,v 1.11 2004/01/05 19:20:18 markus Exp $ */
+/* $OpenBSD: kqueue.c,v 1.12 2004/04/28 06:53:12 brad Exp $ */
/*
* Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
@@ -12,10 +12,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Niels Provos.
- * 4. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
@@ -59,7 +56,7 @@
#define log_error warn
#endif
-#ifdef HAVE_INTTYPES_H
+#if defined(HAVE_INTTYPES_H) && !defined(__OpenBSD__)
#define INTPTR(x) (intptr_t)x
#else
#define INTPTR(x) x
@@ -81,13 +78,14 @@ struct kqop {
struct kevent *events;
int nevents;
int kq;
-} kqop;
+} kqueueop;
void *kq_init (void);
int kq_add (void *, struct event *);
int kq_del (void *, struct event *);
int kq_recalc (void *, int);
int kq_dispatch (void *, struct timeval *);
+int kq_insert (struct kqop *, struct kevent *);
const struct eventop kqops = {
"kqueue",
@@ -107,29 +105,29 @@ kq_init(void)
if (!issetugid() && getenv("EVENT_NOKQUEUE"))
return (NULL);
- memset(&kqop, 0, sizeof(kqop));
+ memset(&kqueueop, 0, sizeof(kqueueop));
- /* Initialize the kernel queue */
+ /* Initalize the kernel queue */
if ((kq = kqueue()) == -1) {
log_error("kqueue");
return (NULL);
}
- kqop.kq = kq;
+ kqueueop.kq = kq;
- /* Initialize fields */
- kqop.changes = malloc(NEVENT * sizeof(struct kevent));
- if (kqop.changes == NULL)
+ /* Initalize fields */
+ kqueueop.changes = malloc(NEVENT * sizeof(struct kevent));
+ if (kqueueop.changes == NULL)
return (NULL);
- kqop.events = malloc(NEVENT * sizeof(struct kevent));
- if (kqop.events == NULL) {
- free (kqop.changes);
+ kqueueop.events = malloc(NEVENT * sizeof(struct kevent));
+ if (kqueueop.events == NULL) {
+ free (kqueueop.changes);
return (NULL);
}
- kqop.nevents = NEVENT;
+ kqueueop.nevents = NEVENT;
- return (&kqop);
+ return (&kqueueop);
}
int
@@ -157,7 +155,7 @@ kq_insert(struct kqop *kqop, struct kevent *kev)
}
kqop->changes = newchange;
- newresult = realloc(kqop->changes,
+ newresult = realloc(kqop->events,
nevents * sizeof(struct kevent));
/*
@@ -168,7 +166,7 @@ kq_insert(struct kqop *kqop, struct kevent *kev)
log_error("%s: malloc", __func__);
return (-1);
}
- kqop->events = newchange;
+ kqop->events = newresult;
kqop->nevents = nevents;
}
@@ -292,9 +290,11 @@ kq_add(void *arg, struct event *ev)
memset(&kev, 0, sizeof(kev));
kev.ident = ev->ev_fd;
kev.filter = EVFILT_READ;
- kev.flags = EV_ADD;
+#ifdef NOTE_EOF
/* Make it behave like select() and poll() */
kev.fflags = NOTE_EOF;
+#endif
+ kev.flags = EV_ADD;
if (!(ev->ev_events & EV_PERSIST))
kev.flags |= EV_ONESHOT;
kev.udata = INTPTR(ev);
diff --git a/lib/libevent/poll.c b/lib/libevent/poll.c
index acb3911375f..4a9331b42c0 100644
--- a/lib/libevent/poll.c
+++ b/lib/libevent/poll.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: poll.c,v 1.2 2003/10/01 09:10:30 markus Exp $ */
+/* $OpenBSD: poll.c,v 1.3 2004/04/28 06:53:12 brad Exp $ */
/*
* Copyright 2000-2003 Niels Provos <provos@citi.umich.edu>
@@ -12,10 +12,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Niels Provos.
- * 4. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
@@ -68,7 +65,7 @@ struct pollop {
struct pollfd *event_set;
struct event **event_back;
sigset_t evsigmask;
-} pop;
+} pollop;
void *poll_init (void);
int poll_add (void *, struct event *);
@@ -92,11 +89,11 @@ poll_init(void)
if (!issetugid() && getenv("EVENT_NOPOLL"))
return (NULL);
- memset(&pop, 0, sizeof(pop));
+ memset(&pollop, 0, sizeof(pollop));
- evsignal_init(&pop.evsigmask);
+ evsignal_init(&pollop.evsigmask);
- return (&pop);
+ return (&pollop);
}
/*
@@ -192,13 +189,18 @@ poll_dispatch(void *arg, struct timeval *tv)
return (0);
for (i = 0; i < nfds; i++) {
+ int what = pop->event_set[i].revents;
+
res = 0;
+
/* If the file gets closed notify */
- if (pop->event_set[i].revents & POLLHUP)
- pop->event_set[i].revents = POLLIN|POLLOUT;
- if (pop->event_set[i].revents & POLLIN)
+ if (what & POLLHUP)
+ what |= POLLIN|POLLOUT;
+ if (what & POLLERR)
+ what |= POLLIN|POLLOUT;
+ if (what & POLLIN)
res |= EV_READ;
- if (pop->event_set[i].revents & POLLOUT)
+ if (what & POLLOUT)
res |= EV_WRITE;
if (res == 0)
continue;
diff --git a/lib/libevent/select.c b/lib/libevent/select.c
index b90f1171025..a6022cfef33 100644
--- a/lib/libevent/select.c
+++ b/lib/libevent/select.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: select.c,v 1.5 2003/07/09 10:54:38 markus Exp $ */
+/* $OpenBSD: select.c,v 1.6 2004/04/28 06:53:12 brad Exp $ */
/*
* Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
@@ -12,10 +12,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Niels Provos.
- * 4. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
diff --git a/lib/libevent/signal.c b/lib/libevent/signal.c
index f54bf62ff2f..fec8f117638 100644
--- a/lib/libevent/signal.c
+++ b/lib/libevent/signal.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: signal.c,v 1.2 2003/07/10 07:48:42 markus Exp $ */
+/* $OpenBSD: signal.c,v 1.3 2004/04/28 06:53:12 brad Exp $ */
/*
* Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
@@ -12,10 +12,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Niels Provos.
- * 4. The name of the author may not be used to endorse or promote products
+ * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
@@ -56,6 +53,7 @@
#endif
#include "event.h"
+#include "evsignal.h"
extern struct event_list signalqueue;
@@ -76,12 +74,12 @@ evsignal_init(sigset_t *evsigmask)
int
evsignal_add(sigset_t *evsigmask, struct event *ev)
{
- int signal;
+ int evsignal;
if (ev->ev_events & (EV_READ|EV_WRITE))
errx(1, "%s: EV_SIGNAL incompatible use", __func__);
- signal = EVENT_SIGNAL(ev);
- sigaddset(evsigmask, signal);
+ evsignal = EVENT_SIGNAL(ev);
+ sigaddset(evsigmask, evsignal);
return (0);
}
@@ -93,10 +91,10 @@ evsignal_add(sigset_t *evsigmask, struct event *ev)
int
evsignal_del(sigset_t *evsigmask, struct event *ev)
{
- int signal;
+ int evsignal;
- signal = EVENT_SIGNAL(ev);
- sigdelset(evsigmask, signal);
+ evsignal = EVENT_SIGNAL(ev);
+ sigdelset(evsigmask, evsignal);
needrecalc = 1;
return (sigaction(EVENT_SIGNAL(ev),(struct sigaction *)SIG_DFL, NULL));