diff options
author | Brad Smith <brad@cvs.openbsd.org> | 2004-04-28 06:53:13 +0000 |
---|---|---|
committer | Brad Smith <brad@cvs.openbsd.org> | 2004-04-28 06:53:13 +0000 |
commit | f1a8f8a8a269fc9130712441a11947ca19cb17ad (patch) | |
tree | 4155a71d2ace6ece769bb248b1a8c3ae38b5c77e | |
parent | c81d4960d450e1bb563668a3ebacc0638dcfc7d0 (diff) |
update to libevent 0.8; keep local changes
ok markus@
-rw-r--r-- | lib/libevent/Makefile | 26 | ||||
-rw-r--r-- | lib/libevent/buffer.c | 222 | ||||
-rw-r--r-- | lib/libevent/evbuffer.c | 357 | ||||
-rw-r--r-- | lib/libevent/event.3 | 140 | ||||
-rw-r--r-- | lib/libevent/event.c | 178 | ||||
-rw-r--r-- | lib/libevent/event.h | 111 | ||||
-rw-r--r-- | lib/libevent/evsignal.h | 7 | ||||
-rw-r--r-- | lib/libevent/kqueue.c | 42 | ||||
-rw-r--r-- | lib/libevent/poll.c | 28 | ||||
-rw-r--r-- | lib/libevent/select.c | 7 | ||||
-rw-r--r-- | lib/libevent/signal.c | 20 |
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)); |