xref: /freebsd/contrib/pf/libevent/evbuffer.c (revision 67ecd4f3a477a0ca5b76a1694f89755df27a8679)
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