167ecd4f3SMax Laier /*
267ecd4f3SMax Laier * Copyright (c) 2002-2004 Niels Provos <provos@citi.umich.edu>
367ecd4f3SMax Laier * All rights reserved.
467ecd4f3SMax Laier *
567ecd4f3SMax Laier * Redistribution and use in source and binary forms, with or without
667ecd4f3SMax Laier * modification, are permitted provided that the following conditions
767ecd4f3SMax Laier * are met:
867ecd4f3SMax Laier * 1. Redistributions of source code must retain the above copyright
967ecd4f3SMax Laier * notice, this list of conditions and the following disclaimer.
1067ecd4f3SMax Laier * 2. Redistributions in binary form must reproduce the above copyright
1167ecd4f3SMax Laier * notice, this list of conditions and the following disclaimer in the
1267ecd4f3SMax Laier * documentation and/or other materials provided with the distribution.
1367ecd4f3SMax Laier * 3. The name of the author may not be used to endorse or promote products
1467ecd4f3SMax Laier * derived from this software without specific prior written permission.
1567ecd4f3SMax Laier *
1667ecd4f3SMax Laier * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1767ecd4f3SMax Laier * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1867ecd4f3SMax Laier * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1967ecd4f3SMax Laier * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2067ecd4f3SMax Laier * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2167ecd4f3SMax Laier * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2267ecd4f3SMax Laier * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2367ecd4f3SMax Laier * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2467ecd4f3SMax Laier * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2567ecd4f3SMax Laier * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2667ecd4f3SMax Laier */
2767ecd4f3SMax Laier
2867ecd4f3SMax Laier #include <sys/types.h>
2967ecd4f3SMax Laier
3067ecd4f3SMax Laier #ifdef HAVE_CONFIG_H
3167ecd4f3SMax Laier #include "config.h"
3267ecd4f3SMax Laier #endif
3367ecd4f3SMax Laier
3467ecd4f3SMax Laier #ifdef HAVE_SYS_TIME_H
3567ecd4f3SMax Laier #include <sys/time.h>
3667ecd4f3SMax Laier #endif
3767ecd4f3SMax Laier
3867ecd4f3SMax Laier #include <errno.h>
3967ecd4f3SMax Laier #include <stdio.h>
4067ecd4f3SMax Laier #include <stdlib.h>
4167ecd4f3SMax Laier #include <string.h>
4267ecd4f3SMax Laier #ifdef HAVE_STDARG_H
4367ecd4f3SMax Laier #include <stdarg.h>
4467ecd4f3SMax Laier #endif
4567ecd4f3SMax Laier
4667ecd4f3SMax Laier #include "event.h"
4767ecd4f3SMax Laier
4867ecd4f3SMax Laier /* prototypes */
4967ecd4f3SMax Laier
5067ecd4f3SMax Laier void bufferevent_setwatermark(struct bufferevent *, short, size_t, size_t);
5167ecd4f3SMax Laier void bufferevent_read_pressure_cb(struct evbuffer *, size_t, size_t, void *);
5267ecd4f3SMax Laier
5367ecd4f3SMax Laier static int
bufferevent_add(struct event * ev,int timeout)5467ecd4f3SMax Laier bufferevent_add(struct event *ev, int timeout)
5567ecd4f3SMax Laier {
5667ecd4f3SMax Laier struct timeval tv, *ptv = NULL;
5767ecd4f3SMax Laier
5867ecd4f3SMax Laier if (timeout) {
5967ecd4f3SMax Laier timerclear(&tv);
6067ecd4f3SMax Laier tv.tv_sec = timeout;
6167ecd4f3SMax Laier ptv = &tv;
6267ecd4f3SMax Laier }
6367ecd4f3SMax Laier
6467ecd4f3SMax Laier return (event_add(ev, ptv));
6567ecd4f3SMax Laier }
6667ecd4f3SMax Laier
6767ecd4f3SMax Laier /*
6867ecd4f3SMax Laier * This callback is executed when the size of the input buffer changes.
6967ecd4f3SMax Laier * We use it to apply back pressure on the reading side.
7067ecd4f3SMax Laier */
7167ecd4f3SMax Laier
7267ecd4f3SMax Laier void
bufferevent_read_pressure_cb(struct evbuffer * buf,size_t old,size_t now,void * arg)7367ecd4f3SMax Laier bufferevent_read_pressure_cb(struct evbuffer *buf, size_t old, size_t now,
7467ecd4f3SMax Laier void *arg) {
7567ecd4f3SMax Laier struct bufferevent *bufev = arg;
7667ecd4f3SMax Laier /*
7767ecd4f3SMax Laier * If we are below the watermark then reschedule reading if it's
7867ecd4f3SMax Laier * still enabled.
7967ecd4f3SMax Laier */
8067ecd4f3SMax Laier if (bufev->wm_read.high == 0 || now < bufev->wm_read.high) {
8167ecd4f3SMax Laier evbuffer_setcb(buf, NULL, NULL);
8267ecd4f3SMax Laier
8367ecd4f3SMax Laier if (bufev->enabled & EV_READ)
8467ecd4f3SMax Laier bufferevent_add(&bufev->ev_read, bufev->timeout_read);
8567ecd4f3SMax Laier }
8667ecd4f3SMax Laier }
8767ecd4f3SMax Laier
8867ecd4f3SMax Laier static void
bufferevent_readcb(int fd,short event,void * arg)8967ecd4f3SMax Laier bufferevent_readcb(int fd, short event, void *arg)
9067ecd4f3SMax Laier {
9167ecd4f3SMax Laier struct bufferevent *bufev = arg;
9267ecd4f3SMax Laier int res = 0;
9367ecd4f3SMax Laier short what = EVBUFFER_READ;
9467ecd4f3SMax Laier size_t len;
9567ecd4f3SMax Laier int howmuch = -1;
9667ecd4f3SMax Laier
9767ecd4f3SMax Laier if (event == EV_TIMEOUT) {
9867ecd4f3SMax Laier what |= EVBUFFER_TIMEOUT;
9967ecd4f3SMax Laier goto error;
10067ecd4f3SMax Laier }
10167ecd4f3SMax Laier
10267ecd4f3SMax Laier /*
10367ecd4f3SMax Laier * If we have a high watermark configured then we don't want to
10467ecd4f3SMax Laier * read more data than would make us reach the watermark.
10567ecd4f3SMax Laier */
10667ecd4f3SMax Laier if (bufev->wm_read.high != 0)
10767ecd4f3SMax Laier howmuch = bufev->wm_read.high;
10867ecd4f3SMax Laier
10967ecd4f3SMax Laier res = evbuffer_read(bufev->input, fd, howmuch);
11067ecd4f3SMax Laier if (res == -1) {
11167ecd4f3SMax Laier if (errno == EAGAIN || errno == EINTR)
11267ecd4f3SMax Laier goto reschedule;
11367ecd4f3SMax Laier /* error case */
11467ecd4f3SMax Laier what |= EVBUFFER_ERROR;
11567ecd4f3SMax Laier } else if (res == 0) {
11667ecd4f3SMax Laier /* eof case */
11767ecd4f3SMax Laier what |= EVBUFFER_EOF;
11867ecd4f3SMax Laier }
11967ecd4f3SMax Laier
12067ecd4f3SMax Laier if (res <= 0)
12167ecd4f3SMax Laier goto error;
12267ecd4f3SMax Laier
12367ecd4f3SMax Laier bufferevent_add(&bufev->ev_read, bufev->timeout_read);
12467ecd4f3SMax Laier
12567ecd4f3SMax Laier /* See if this callbacks meets the water marks */
12667ecd4f3SMax Laier len = EVBUFFER_LENGTH(bufev->input);
12767ecd4f3SMax Laier if (bufev->wm_read.low != 0 && len < bufev->wm_read.low)
12867ecd4f3SMax Laier return;
12967ecd4f3SMax Laier if (bufev->wm_read.high != 0 && len > bufev->wm_read.high) {
13067ecd4f3SMax Laier struct evbuffer *buf = bufev->input;
13167ecd4f3SMax Laier event_del(&bufev->ev_read);
13267ecd4f3SMax Laier
13367ecd4f3SMax Laier /* Now schedule a callback for us */
13467ecd4f3SMax Laier evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev);
13567ecd4f3SMax Laier return;
13667ecd4f3SMax Laier }
13767ecd4f3SMax Laier
13867ecd4f3SMax Laier /* Invoke the user callback - must always be called last */
13967ecd4f3SMax Laier if (bufev->readcb != NULL)
14067ecd4f3SMax Laier (*bufev->readcb)(bufev, bufev->cbarg);
14167ecd4f3SMax Laier return;
14267ecd4f3SMax Laier
14367ecd4f3SMax Laier reschedule:
14467ecd4f3SMax Laier bufferevent_add(&bufev->ev_read, bufev->timeout_read);
14567ecd4f3SMax Laier return;
14667ecd4f3SMax Laier
14767ecd4f3SMax Laier error:
14867ecd4f3SMax Laier (*bufev->errorcb)(bufev, what, bufev->cbarg);
14967ecd4f3SMax Laier }
15067ecd4f3SMax Laier
15167ecd4f3SMax Laier static void
bufferevent_writecb(int fd,short event,void * arg)15267ecd4f3SMax Laier bufferevent_writecb(int fd, short event, void *arg)
15367ecd4f3SMax Laier {
15467ecd4f3SMax Laier struct bufferevent *bufev = arg;
15567ecd4f3SMax Laier int res = 0;
15667ecd4f3SMax Laier short what = EVBUFFER_WRITE;
15767ecd4f3SMax Laier
15867ecd4f3SMax Laier if (event == EV_TIMEOUT) {
15967ecd4f3SMax Laier what |= EVBUFFER_TIMEOUT;
16067ecd4f3SMax Laier goto error;
16167ecd4f3SMax Laier }
16267ecd4f3SMax Laier
16367ecd4f3SMax Laier if (EVBUFFER_LENGTH(bufev->output)) {
16467ecd4f3SMax Laier res = evbuffer_write(bufev->output, fd);
16567ecd4f3SMax Laier if (res == -1) {
16667ecd4f3SMax Laier #ifndef WIN32
16767ecd4f3SMax Laier /*todo. evbuffer uses WriteFile when WIN32 is set. WIN32 system calls do not
16867ecd4f3SMax Laier *set errno. thus this error checking is not portable*/
16967ecd4f3SMax Laier if (errno == EAGAIN ||
17067ecd4f3SMax Laier errno == EINTR ||
17167ecd4f3SMax Laier errno == EINPROGRESS)
17267ecd4f3SMax Laier goto reschedule;
17367ecd4f3SMax Laier /* error case */
17467ecd4f3SMax Laier what |= EVBUFFER_ERROR;
17567ecd4f3SMax Laier
17667ecd4f3SMax Laier #else
17767ecd4f3SMax Laier goto reschedule;
17867ecd4f3SMax Laier #endif
17967ecd4f3SMax Laier
18067ecd4f3SMax Laier } else if (res == 0) {
18167ecd4f3SMax Laier /* eof case */
18267ecd4f3SMax Laier what |= EVBUFFER_EOF;
18367ecd4f3SMax Laier }
18467ecd4f3SMax Laier if (res <= 0)
18567ecd4f3SMax Laier goto error;
18667ecd4f3SMax Laier }
18767ecd4f3SMax Laier
18867ecd4f3SMax Laier if (EVBUFFER_LENGTH(bufev->output) != 0)
18967ecd4f3SMax Laier bufferevent_add(&bufev->ev_write, bufev->timeout_write);
19067ecd4f3SMax Laier
19167ecd4f3SMax Laier /*
19267ecd4f3SMax Laier * Invoke the user callback if our buffer is drained or below the
19367ecd4f3SMax Laier * low watermark.
19467ecd4f3SMax Laier */
19567ecd4f3SMax Laier if (bufev->writecb != NULL &&
19667ecd4f3SMax Laier EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low)
19767ecd4f3SMax Laier (*bufev->writecb)(bufev, bufev->cbarg);
19867ecd4f3SMax Laier
19967ecd4f3SMax Laier return;
20067ecd4f3SMax Laier
20167ecd4f3SMax Laier reschedule:
20267ecd4f3SMax Laier if (EVBUFFER_LENGTH(bufev->output) != 0)
20367ecd4f3SMax Laier bufferevent_add(&bufev->ev_write, bufev->timeout_write);
20467ecd4f3SMax Laier return;
20567ecd4f3SMax Laier
20667ecd4f3SMax Laier error:
20767ecd4f3SMax Laier (*bufev->errorcb)(bufev, what, bufev->cbarg);
20867ecd4f3SMax Laier }
20967ecd4f3SMax Laier
21067ecd4f3SMax Laier /*
21167ecd4f3SMax Laier * Create a new buffered event object.
21267ecd4f3SMax Laier *
21367ecd4f3SMax Laier * The read callback is invoked whenever we read new data.
21467ecd4f3SMax Laier * The write callback is invoked whenever the output buffer is drained.
21567ecd4f3SMax Laier * The error callback is invoked on a write/read error or on EOF.
21667ecd4f3SMax Laier *
21767ecd4f3SMax Laier * Both read and write callbacks maybe NULL. The error callback is not
21867ecd4f3SMax Laier * allowed to be NULL and have to be provided always.
21967ecd4f3SMax Laier */
22067ecd4f3SMax Laier
22167ecd4f3SMax Laier struct bufferevent *
bufferevent_new(int fd,evbuffercb readcb,evbuffercb writecb,everrorcb errorcb,void * cbarg)22267ecd4f3SMax Laier bufferevent_new(int fd, evbuffercb readcb, evbuffercb writecb,
22367ecd4f3SMax Laier everrorcb errorcb, void *cbarg)
22467ecd4f3SMax Laier {
22567ecd4f3SMax Laier struct bufferevent *bufev;
22667ecd4f3SMax Laier
22767ecd4f3SMax Laier if ((bufev = calloc(1, sizeof(struct bufferevent))) == NULL)
22867ecd4f3SMax Laier return (NULL);
22967ecd4f3SMax Laier
23067ecd4f3SMax Laier if ((bufev->input = evbuffer_new()) == NULL) {
23167ecd4f3SMax Laier free(bufev);
23267ecd4f3SMax Laier return (NULL);
23367ecd4f3SMax Laier }
23467ecd4f3SMax Laier
23567ecd4f3SMax Laier if ((bufev->output = evbuffer_new()) == NULL) {
23667ecd4f3SMax Laier evbuffer_free(bufev->input);
23767ecd4f3SMax Laier free(bufev);
23867ecd4f3SMax Laier return (NULL);
23967ecd4f3SMax Laier }
24067ecd4f3SMax Laier
24167ecd4f3SMax Laier event_set(&bufev->ev_read, fd, EV_READ, bufferevent_readcb, bufev);
24267ecd4f3SMax Laier event_set(&bufev->ev_write, fd, EV_WRITE, bufferevent_writecb, bufev);
24367ecd4f3SMax Laier
24467ecd4f3SMax Laier bufev->readcb = readcb;
24567ecd4f3SMax Laier bufev->writecb = writecb;
24667ecd4f3SMax Laier bufev->errorcb = errorcb;
24767ecd4f3SMax Laier
24867ecd4f3SMax Laier bufev->cbarg = cbarg;
24967ecd4f3SMax Laier
25067ecd4f3SMax Laier /*
25167ecd4f3SMax Laier * Set to EV_WRITE so that using bufferevent_write is going to
25267ecd4f3SMax Laier * trigger a callback. Reading needs to be explicitly enabled
25367ecd4f3SMax Laier * because otherwise no data will be available.
25467ecd4f3SMax Laier */
25567ecd4f3SMax Laier bufev->enabled = EV_WRITE;
25667ecd4f3SMax Laier
25767ecd4f3SMax Laier return (bufev);
25867ecd4f3SMax Laier }
25967ecd4f3SMax Laier
26067ecd4f3SMax Laier int
bufferevent_priority_set(struct bufferevent * bufev,int priority)26167ecd4f3SMax Laier bufferevent_priority_set(struct bufferevent *bufev, int priority)
26267ecd4f3SMax Laier {
26367ecd4f3SMax Laier if (event_priority_set(&bufev->ev_read, priority) == -1)
26467ecd4f3SMax Laier return (-1);
26567ecd4f3SMax Laier if (event_priority_set(&bufev->ev_write, priority) == -1)
26667ecd4f3SMax Laier return (-1);
26767ecd4f3SMax Laier
26867ecd4f3SMax Laier return (0);
26967ecd4f3SMax Laier }
27067ecd4f3SMax Laier
27167ecd4f3SMax Laier /* Closing the file descriptor is the responsibility of the caller */
27267ecd4f3SMax Laier
27367ecd4f3SMax Laier void
bufferevent_free(struct bufferevent * bufev)27467ecd4f3SMax Laier bufferevent_free(struct bufferevent *bufev)
27567ecd4f3SMax Laier {
27667ecd4f3SMax Laier event_del(&bufev->ev_read);
27767ecd4f3SMax Laier event_del(&bufev->ev_write);
27867ecd4f3SMax Laier
27967ecd4f3SMax Laier evbuffer_free(bufev->input);
28067ecd4f3SMax Laier evbuffer_free(bufev->output);
28167ecd4f3SMax Laier
28267ecd4f3SMax Laier free(bufev);
28367ecd4f3SMax Laier }
28467ecd4f3SMax Laier
28567ecd4f3SMax Laier /*
28667ecd4f3SMax Laier * Returns 0 on success;
28767ecd4f3SMax Laier * -1 on failure.
28867ecd4f3SMax Laier */
28967ecd4f3SMax Laier
29067ecd4f3SMax Laier int
bufferevent_write(struct bufferevent * bufev,void * data,size_t size)29167ecd4f3SMax Laier bufferevent_write(struct bufferevent *bufev, void *data, size_t size)
29267ecd4f3SMax Laier {
29367ecd4f3SMax Laier int res;
29467ecd4f3SMax Laier
29567ecd4f3SMax Laier res = evbuffer_add(bufev->output, data, size);
29667ecd4f3SMax Laier
29767ecd4f3SMax Laier if (res == -1)
29867ecd4f3SMax Laier return (res);
29967ecd4f3SMax Laier
30067ecd4f3SMax Laier /* If everything is okay, we need to schedule a write */
30167ecd4f3SMax Laier if (size > 0 && (bufev->enabled & EV_WRITE))
30267ecd4f3SMax Laier bufferevent_add(&bufev->ev_write, bufev->timeout_write);
30367ecd4f3SMax Laier
30467ecd4f3SMax Laier return (res);
30567ecd4f3SMax Laier }
30667ecd4f3SMax Laier
30767ecd4f3SMax Laier int
bufferevent_write_buffer(struct bufferevent * bufev,struct evbuffer * buf)30867ecd4f3SMax Laier bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf)
30967ecd4f3SMax Laier {
31067ecd4f3SMax Laier int res;
31167ecd4f3SMax Laier
31267ecd4f3SMax Laier res = bufferevent_write(bufev, buf->buffer, buf->off);
31367ecd4f3SMax Laier if (res != -1)
31467ecd4f3SMax Laier evbuffer_drain(buf, buf->off);
31567ecd4f3SMax Laier
31667ecd4f3SMax Laier return (res);
31767ecd4f3SMax Laier }
31867ecd4f3SMax Laier
31967ecd4f3SMax Laier size_t
bufferevent_read(struct bufferevent * bufev,void * data,size_t size)32067ecd4f3SMax Laier bufferevent_read(struct bufferevent *bufev, void *data, size_t size)
32167ecd4f3SMax Laier {
32267ecd4f3SMax Laier struct evbuffer *buf = bufev->input;
32367ecd4f3SMax Laier
32467ecd4f3SMax Laier if (buf->off < size)
32567ecd4f3SMax Laier size = buf->off;
32667ecd4f3SMax Laier
32767ecd4f3SMax Laier /* Copy the available data to the user buffer */
32867ecd4f3SMax Laier memcpy(data, buf->buffer, size);
32967ecd4f3SMax Laier
33067ecd4f3SMax Laier if (size)
33167ecd4f3SMax Laier evbuffer_drain(buf, size);
33267ecd4f3SMax Laier
33367ecd4f3SMax Laier return (size);
33467ecd4f3SMax Laier }
33567ecd4f3SMax Laier
33667ecd4f3SMax Laier int
bufferevent_enable(struct bufferevent * bufev,short event)33767ecd4f3SMax Laier bufferevent_enable(struct bufferevent *bufev, short event)
33867ecd4f3SMax Laier {
33967ecd4f3SMax Laier if (event & EV_READ) {
34067ecd4f3SMax Laier if (bufferevent_add(&bufev->ev_read, bufev->timeout_read) == -1)
34167ecd4f3SMax Laier return (-1);
34267ecd4f3SMax Laier }
34367ecd4f3SMax Laier if (event & EV_WRITE) {
34467ecd4f3SMax Laier if (bufferevent_add(&bufev->ev_write, bufev->timeout_write) == -1)
34567ecd4f3SMax Laier return (-1);
34667ecd4f3SMax Laier }
34767ecd4f3SMax Laier
34867ecd4f3SMax Laier bufev->enabled |= event;
34967ecd4f3SMax Laier return (0);
35067ecd4f3SMax Laier }
35167ecd4f3SMax Laier
35267ecd4f3SMax Laier int
bufferevent_disable(struct bufferevent * bufev,short event)35367ecd4f3SMax Laier bufferevent_disable(struct bufferevent *bufev, short event)
35467ecd4f3SMax Laier {
35567ecd4f3SMax Laier if (event & EV_READ) {
35667ecd4f3SMax Laier if (event_del(&bufev->ev_read) == -1)
35767ecd4f3SMax Laier return (-1);
35867ecd4f3SMax Laier }
35967ecd4f3SMax Laier if (event & EV_WRITE) {
36067ecd4f3SMax Laier if (event_del(&bufev->ev_write) == -1)
36167ecd4f3SMax Laier return (-1);
36267ecd4f3SMax Laier }
36367ecd4f3SMax Laier
36467ecd4f3SMax Laier bufev->enabled &= ~event;
36567ecd4f3SMax Laier return (0);
36667ecd4f3SMax Laier }
36767ecd4f3SMax Laier
36867ecd4f3SMax Laier /*
36967ecd4f3SMax Laier * Sets the read and write timeout for a buffered event.
37067ecd4f3SMax Laier */
37167ecd4f3SMax Laier
37267ecd4f3SMax Laier void
bufferevent_settimeout(struct bufferevent * bufev,int timeout_read,int timeout_write)37367ecd4f3SMax Laier bufferevent_settimeout(struct bufferevent *bufev,
37467ecd4f3SMax Laier int timeout_read, int timeout_write) {
37567ecd4f3SMax Laier bufev->timeout_read = timeout_read;
37667ecd4f3SMax Laier bufev->timeout_write = timeout_write;
37767ecd4f3SMax Laier }
37867ecd4f3SMax Laier
37967ecd4f3SMax Laier /*
38067ecd4f3SMax Laier * Sets the water marks
38167ecd4f3SMax Laier */
38267ecd4f3SMax Laier
38367ecd4f3SMax Laier void
bufferevent_setwatermark(struct bufferevent * bufev,short events,size_t lowmark,size_t highmark)38467ecd4f3SMax Laier bufferevent_setwatermark(struct bufferevent *bufev, short events,
38567ecd4f3SMax Laier size_t lowmark, size_t highmark)
38667ecd4f3SMax Laier {
38767ecd4f3SMax Laier if (events & EV_READ) {
38867ecd4f3SMax Laier bufev->wm_read.low = lowmark;
38967ecd4f3SMax Laier bufev->wm_read.high = highmark;
39067ecd4f3SMax Laier }
39167ecd4f3SMax Laier
39267ecd4f3SMax Laier if (events & EV_WRITE) {
39367ecd4f3SMax Laier bufev->wm_write.low = lowmark;
39467ecd4f3SMax Laier bufev->wm_write.high = highmark;
39567ecd4f3SMax Laier }
39667ecd4f3SMax Laier
39767ecd4f3SMax Laier /* If the watermarks changed then see if we should call read again */
39867ecd4f3SMax Laier bufferevent_read_pressure_cb(bufev->input,
39967ecd4f3SMax Laier 0, EVBUFFER_LENGTH(bufev->input), bufev);
40067ecd4f3SMax Laier }
40167ecd4f3SMax Laier
40267ecd4f3SMax Laier int
bufferevent_base_set(struct event_base * base,struct bufferevent * bufev)40367ecd4f3SMax Laier bufferevent_base_set(struct event_base *base, struct bufferevent *bufev)
40467ecd4f3SMax Laier {
40567ecd4f3SMax Laier int res;
40667ecd4f3SMax Laier
40767ecd4f3SMax Laier res = event_base_set(base, &bufev->ev_read);
40867ecd4f3SMax Laier if (res == -1)
40967ecd4f3SMax Laier return (res);
41067ecd4f3SMax Laier
41167ecd4f3SMax Laier res = event_base_set(base, &bufev->ev_write);
41267ecd4f3SMax Laier return (res);
41367ecd4f3SMax Laier }
414