xref: /freebsd-src/contrib/pf/libevent/evbuffer.c (revision fc515400ab05695df359c4b4d5fab9285a642699)
1*67ecd4f3SMax Laier /*
2*67ecd4f3SMax Laier  * Copyright (c) 2002-2004 Niels Provos <provos@citi.umich.edu>
3*67ecd4f3SMax Laier  * All rights reserved.
4*67ecd4f3SMax Laier  *
5*67ecd4f3SMax Laier  * Redistribution and use in source and binary forms, with or without
6*67ecd4f3SMax Laier  * modification, are permitted provided that the following conditions
7*67ecd4f3SMax Laier  * are met:
8*67ecd4f3SMax Laier  * 1. Redistributions of source code must retain the above copyright
9*67ecd4f3SMax Laier  *    notice, this list of conditions and the following disclaimer.
10*67ecd4f3SMax Laier  * 2. Redistributions in binary form must reproduce the above copyright
11*67ecd4f3SMax Laier  *    notice, this list of conditions and the following disclaimer in the
12*67ecd4f3SMax Laier  *    documentation and/or other materials provided with the distribution.
13*67ecd4f3SMax Laier  * 3. The name of the author may not be used to endorse or promote products
14*67ecd4f3SMax Laier  *    derived from this software without specific prior written permission.
15*67ecd4f3SMax Laier  *
16*67ecd4f3SMax Laier  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17*67ecd4f3SMax Laier  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18*67ecd4f3SMax Laier  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19*67ecd4f3SMax Laier  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20*67ecd4f3SMax Laier  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21*67ecd4f3SMax Laier  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22*67ecd4f3SMax Laier  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23*67ecd4f3SMax Laier  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24*67ecd4f3SMax Laier  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25*67ecd4f3SMax Laier  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*67ecd4f3SMax Laier  */
27*67ecd4f3SMax Laier 
28*67ecd4f3SMax Laier #include <sys/types.h>
29*67ecd4f3SMax Laier 
30*67ecd4f3SMax Laier #ifdef HAVE_CONFIG_H
31*67ecd4f3SMax Laier #include "config.h"
32*67ecd4f3SMax Laier #endif
33*67ecd4f3SMax Laier 
34*67ecd4f3SMax Laier #ifdef HAVE_SYS_TIME_H
35*67ecd4f3SMax Laier #include <sys/time.h>
36*67ecd4f3SMax Laier #endif
37*67ecd4f3SMax Laier 
38*67ecd4f3SMax Laier #include <errno.h>
39*67ecd4f3SMax Laier #include <stdio.h>
40*67ecd4f3SMax Laier #include <stdlib.h>
41*67ecd4f3SMax Laier #include <string.h>
42*67ecd4f3SMax Laier #ifdef HAVE_STDARG_H
43*67ecd4f3SMax Laier #include <stdarg.h>
44*67ecd4f3SMax Laier #endif
45*67ecd4f3SMax Laier 
46*67ecd4f3SMax Laier #include "event.h"
47*67ecd4f3SMax Laier 
48*67ecd4f3SMax Laier /* prototypes */
49*67ecd4f3SMax Laier 
50*67ecd4f3SMax Laier void bufferevent_setwatermark(struct bufferevent *, short, size_t, size_t);
51*67ecd4f3SMax Laier void bufferevent_read_pressure_cb(struct evbuffer *, size_t, size_t, void *);
52*67ecd4f3SMax Laier 
53*67ecd4f3SMax Laier static int
bufferevent_add(struct event * ev,int timeout)54*67ecd4f3SMax Laier bufferevent_add(struct event *ev, int timeout)
55*67ecd4f3SMax Laier {
56*67ecd4f3SMax Laier 	struct timeval tv, *ptv = NULL;
57*67ecd4f3SMax Laier 
58*67ecd4f3SMax Laier 	if (timeout) {
59*67ecd4f3SMax Laier 		timerclear(&tv);
60*67ecd4f3SMax Laier 		tv.tv_sec = timeout;
61*67ecd4f3SMax Laier 		ptv = &tv;
62*67ecd4f3SMax Laier 	}
63*67ecd4f3SMax Laier 
64*67ecd4f3SMax Laier 	return (event_add(ev, ptv));
65*67ecd4f3SMax Laier }
66*67ecd4f3SMax Laier 
67*67ecd4f3SMax Laier /*
68*67ecd4f3SMax Laier  * This callback is executed when the size of the input buffer changes.
69*67ecd4f3SMax Laier  * We use it to apply back pressure on the reading side.
70*67ecd4f3SMax Laier  */
71*67ecd4f3SMax Laier 
72*67ecd4f3SMax Laier void
bufferevent_read_pressure_cb(struct evbuffer * buf,size_t old,size_t now,void * arg)73*67ecd4f3SMax Laier bufferevent_read_pressure_cb(struct evbuffer *buf, size_t old, size_t now,
74*67ecd4f3SMax Laier     void *arg) {
75*67ecd4f3SMax Laier 	struct bufferevent *bufev = arg;
76*67ecd4f3SMax Laier 	/*
77*67ecd4f3SMax Laier 	 * If we are below the watermark then reschedule reading if it's
78*67ecd4f3SMax Laier 	 * still enabled.
79*67ecd4f3SMax Laier 	 */
80*67ecd4f3SMax Laier 	if (bufev->wm_read.high == 0 || now < bufev->wm_read.high) {
81*67ecd4f3SMax Laier 		evbuffer_setcb(buf, NULL, NULL);
82*67ecd4f3SMax Laier 
83*67ecd4f3SMax Laier 		if (bufev->enabled & EV_READ)
84*67ecd4f3SMax Laier 			bufferevent_add(&bufev->ev_read, bufev->timeout_read);
85*67ecd4f3SMax Laier 	}
86*67ecd4f3SMax Laier }
87*67ecd4f3SMax Laier 
88*67ecd4f3SMax Laier static void
bufferevent_readcb(int fd,short event,void * arg)89*67ecd4f3SMax Laier bufferevent_readcb(int fd, short event, void *arg)
90*67ecd4f3SMax Laier {
91*67ecd4f3SMax Laier 	struct bufferevent *bufev = arg;
92*67ecd4f3SMax Laier 	int res = 0;
93*67ecd4f3SMax Laier 	short what = EVBUFFER_READ;
94*67ecd4f3SMax Laier 	size_t len;
95*67ecd4f3SMax Laier 	int howmuch = -1;
96*67ecd4f3SMax Laier 
97*67ecd4f3SMax Laier 	if (event == EV_TIMEOUT) {
98*67ecd4f3SMax Laier 		what |= EVBUFFER_TIMEOUT;
99*67ecd4f3SMax Laier 		goto error;
100*67ecd4f3SMax Laier 	}
101*67ecd4f3SMax Laier 
102*67ecd4f3SMax Laier 	/*
103*67ecd4f3SMax Laier 	 * If we have a high watermark configured then we don't want to
104*67ecd4f3SMax Laier 	 * read more data than would make us reach the watermark.
105*67ecd4f3SMax Laier 	 */
106*67ecd4f3SMax Laier 	if (bufev->wm_read.high != 0)
107*67ecd4f3SMax Laier 		howmuch = bufev->wm_read.high;
108*67ecd4f3SMax Laier 
109*67ecd4f3SMax Laier 	res = evbuffer_read(bufev->input, fd, howmuch);
110*67ecd4f3SMax Laier 	if (res == -1) {
111*67ecd4f3SMax Laier 		if (errno == EAGAIN || errno == EINTR)
112*67ecd4f3SMax Laier 			goto reschedule;
113*67ecd4f3SMax Laier 		/* error case */
114*67ecd4f3SMax Laier 		what |= EVBUFFER_ERROR;
115*67ecd4f3SMax Laier 	} else if (res == 0) {
116*67ecd4f3SMax Laier 		/* eof case */
117*67ecd4f3SMax Laier 		what |= EVBUFFER_EOF;
118*67ecd4f3SMax Laier 	}
119*67ecd4f3SMax Laier 
120*67ecd4f3SMax Laier 	if (res <= 0)
121*67ecd4f3SMax Laier 		goto error;
122*67ecd4f3SMax Laier 
123*67ecd4f3SMax Laier 	bufferevent_add(&bufev->ev_read, bufev->timeout_read);
124*67ecd4f3SMax Laier 
125*67ecd4f3SMax Laier 	/* See if this callbacks meets the water marks */
126*67ecd4f3SMax Laier 	len = EVBUFFER_LENGTH(bufev->input);
127*67ecd4f3SMax Laier 	if (bufev->wm_read.low != 0 && len < bufev->wm_read.low)
128*67ecd4f3SMax Laier 		return;
129*67ecd4f3SMax Laier 	if (bufev->wm_read.high != 0 && len > bufev->wm_read.high) {
130*67ecd4f3SMax Laier 		struct evbuffer *buf = bufev->input;
131*67ecd4f3SMax Laier 		event_del(&bufev->ev_read);
132*67ecd4f3SMax Laier 
133*67ecd4f3SMax Laier 		/* Now schedule a callback for us */
134*67ecd4f3SMax Laier 		evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev);
135*67ecd4f3SMax Laier 		return;
136*67ecd4f3SMax Laier 	}
137*67ecd4f3SMax Laier 
138*67ecd4f3SMax Laier 	/* Invoke the user callback - must always be called last */
139*67ecd4f3SMax Laier 	if (bufev->readcb != NULL)
140*67ecd4f3SMax Laier 		(*bufev->readcb)(bufev, bufev->cbarg);
141*67ecd4f3SMax Laier 	return;
142*67ecd4f3SMax Laier 
143*67ecd4f3SMax Laier  reschedule:
144*67ecd4f3SMax Laier 	bufferevent_add(&bufev->ev_read, bufev->timeout_read);
145*67ecd4f3SMax Laier 	return;
146*67ecd4f3SMax Laier 
147*67ecd4f3SMax Laier  error:
148*67ecd4f3SMax Laier 	(*bufev->errorcb)(bufev, what, bufev->cbarg);
149*67ecd4f3SMax Laier }
150*67ecd4f3SMax Laier 
151*67ecd4f3SMax Laier static void
bufferevent_writecb(int fd,short event,void * arg)152*67ecd4f3SMax Laier bufferevent_writecb(int fd, short event, void *arg)
153*67ecd4f3SMax Laier {
154*67ecd4f3SMax Laier 	struct bufferevent *bufev = arg;
155*67ecd4f3SMax Laier 	int res = 0;
156*67ecd4f3SMax Laier 	short what = EVBUFFER_WRITE;
157*67ecd4f3SMax Laier 
158*67ecd4f3SMax Laier 	if (event == EV_TIMEOUT) {
159*67ecd4f3SMax Laier 		what |= EVBUFFER_TIMEOUT;
160*67ecd4f3SMax Laier 		goto error;
161*67ecd4f3SMax Laier 	}
162*67ecd4f3SMax Laier 
163*67ecd4f3SMax Laier 	if (EVBUFFER_LENGTH(bufev->output)) {
164*67ecd4f3SMax Laier 	    res = evbuffer_write(bufev->output, fd);
165*67ecd4f3SMax Laier 	    if (res == -1) {
166*67ecd4f3SMax Laier #ifndef WIN32
167*67ecd4f3SMax Laier /*todo. evbuffer uses WriteFile when WIN32 is set. WIN32 system calls do not
168*67ecd4f3SMax Laier  *set errno. thus this error checking is not portable*/
169*67ecd4f3SMax Laier 		    if (errno == EAGAIN ||
170*67ecd4f3SMax Laier 			errno == EINTR ||
171*67ecd4f3SMax Laier 			errno == EINPROGRESS)
172*67ecd4f3SMax Laier 			    goto reschedule;
173*67ecd4f3SMax Laier 		    /* error case */
174*67ecd4f3SMax Laier 		    what |= EVBUFFER_ERROR;
175*67ecd4f3SMax Laier 
176*67ecd4f3SMax Laier #else
177*67ecd4f3SMax Laier 				goto reschedule;
178*67ecd4f3SMax Laier #endif
179*67ecd4f3SMax Laier 
180*67ecd4f3SMax Laier 	    } else if (res == 0) {
181*67ecd4f3SMax Laier 		    /* eof case */
182*67ecd4f3SMax Laier 		    what |= EVBUFFER_EOF;
183*67ecd4f3SMax Laier 	    }
184*67ecd4f3SMax Laier 	    if (res <= 0)
185*67ecd4f3SMax Laier 		    goto error;
186*67ecd4f3SMax Laier 	}
187*67ecd4f3SMax Laier 
188*67ecd4f3SMax Laier 	if (EVBUFFER_LENGTH(bufev->output) != 0)
189*67ecd4f3SMax Laier 		bufferevent_add(&bufev->ev_write, bufev->timeout_write);
190*67ecd4f3SMax Laier 
191*67ecd4f3SMax Laier 	/*
192*67ecd4f3SMax Laier 	 * Invoke the user callback if our buffer is drained or below the
193*67ecd4f3SMax Laier 	 * low watermark.
194*67ecd4f3SMax Laier 	 */
195*67ecd4f3SMax Laier 	if (bufev->writecb != NULL &&
196*67ecd4f3SMax Laier 	    EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low)
197*67ecd4f3SMax Laier 		(*bufev->writecb)(bufev, bufev->cbarg);
198*67ecd4f3SMax Laier 
199*67ecd4f3SMax Laier 	return;
200*67ecd4f3SMax Laier 
201*67ecd4f3SMax Laier  reschedule:
202*67ecd4f3SMax Laier 	if (EVBUFFER_LENGTH(bufev->output) != 0)
203*67ecd4f3SMax Laier 		bufferevent_add(&bufev->ev_write, bufev->timeout_write);
204*67ecd4f3SMax Laier 	return;
205*67ecd4f3SMax Laier 
206*67ecd4f3SMax Laier  error:
207*67ecd4f3SMax Laier 	(*bufev->errorcb)(bufev, what, bufev->cbarg);
208*67ecd4f3SMax Laier }
209*67ecd4f3SMax Laier 
210*67ecd4f3SMax Laier /*
211*67ecd4f3SMax Laier  * Create a new buffered event object.
212*67ecd4f3SMax Laier  *
213*67ecd4f3SMax Laier  * The read callback is invoked whenever we read new data.
214*67ecd4f3SMax Laier  * The write callback is invoked whenever the output buffer is drained.
215*67ecd4f3SMax Laier  * The error callback is invoked on a write/read error or on EOF.
216*67ecd4f3SMax Laier  *
217*67ecd4f3SMax Laier  * Both read and write callbacks maybe NULL.  The error callback is not
218*67ecd4f3SMax Laier  * allowed to be NULL and have to be provided always.
219*67ecd4f3SMax Laier  */
220*67ecd4f3SMax Laier 
221*67ecd4f3SMax Laier struct bufferevent *
bufferevent_new(int fd,evbuffercb readcb,evbuffercb writecb,everrorcb errorcb,void * cbarg)222*67ecd4f3SMax Laier bufferevent_new(int fd, evbuffercb readcb, evbuffercb writecb,
223*67ecd4f3SMax Laier     everrorcb errorcb, void *cbarg)
224*67ecd4f3SMax Laier {
225*67ecd4f3SMax Laier 	struct bufferevent *bufev;
226*67ecd4f3SMax Laier 
227*67ecd4f3SMax Laier 	if ((bufev = calloc(1, sizeof(struct bufferevent))) == NULL)
228*67ecd4f3SMax Laier 		return (NULL);
229*67ecd4f3SMax Laier 
230*67ecd4f3SMax Laier 	if ((bufev->input = evbuffer_new()) == NULL) {
231*67ecd4f3SMax Laier 		free(bufev);
232*67ecd4f3SMax Laier 		return (NULL);
233*67ecd4f3SMax Laier 	}
234*67ecd4f3SMax Laier 
235*67ecd4f3SMax Laier 	if ((bufev->output = evbuffer_new()) == NULL) {
236*67ecd4f3SMax Laier 		evbuffer_free(bufev->input);
237*67ecd4f3SMax Laier 		free(bufev);
238*67ecd4f3SMax Laier 		return (NULL);
239*67ecd4f3SMax Laier 	}
240*67ecd4f3SMax Laier 
241*67ecd4f3SMax Laier 	event_set(&bufev->ev_read, fd, EV_READ, bufferevent_readcb, bufev);
242*67ecd4f3SMax Laier 	event_set(&bufev->ev_write, fd, EV_WRITE, bufferevent_writecb, bufev);
243*67ecd4f3SMax Laier 
244*67ecd4f3SMax Laier 	bufev->readcb = readcb;
245*67ecd4f3SMax Laier 	bufev->writecb = writecb;
246*67ecd4f3SMax Laier 	bufev->errorcb = errorcb;
247*67ecd4f3SMax Laier 
248*67ecd4f3SMax Laier 	bufev->cbarg = cbarg;
249*67ecd4f3SMax Laier 
250*67ecd4f3SMax Laier 	/*
251*67ecd4f3SMax Laier 	 * Set to EV_WRITE so that using bufferevent_write is going to
252*67ecd4f3SMax Laier 	 * trigger a callback.  Reading needs to be explicitly enabled
253*67ecd4f3SMax Laier 	 * because otherwise no data will be available.
254*67ecd4f3SMax Laier 	 */
255*67ecd4f3SMax Laier 	bufev->enabled = EV_WRITE;
256*67ecd4f3SMax Laier 
257*67ecd4f3SMax Laier 	return (bufev);
258*67ecd4f3SMax Laier }
259*67ecd4f3SMax Laier 
260*67ecd4f3SMax Laier int
bufferevent_priority_set(struct bufferevent * bufev,int priority)261*67ecd4f3SMax Laier bufferevent_priority_set(struct bufferevent *bufev, int priority)
262*67ecd4f3SMax Laier {
263*67ecd4f3SMax Laier 	if (event_priority_set(&bufev->ev_read, priority) == -1)
264*67ecd4f3SMax Laier 		return (-1);
265*67ecd4f3SMax Laier 	if (event_priority_set(&bufev->ev_write, priority) == -1)
266*67ecd4f3SMax Laier 		return (-1);
267*67ecd4f3SMax Laier 
268*67ecd4f3SMax Laier 	return (0);
269*67ecd4f3SMax Laier }
270*67ecd4f3SMax Laier 
271*67ecd4f3SMax Laier /* Closing the file descriptor is the responsibility of the caller */
272*67ecd4f3SMax Laier 
273*67ecd4f3SMax Laier void
bufferevent_free(struct bufferevent * bufev)274*67ecd4f3SMax Laier bufferevent_free(struct bufferevent *bufev)
275*67ecd4f3SMax Laier {
276*67ecd4f3SMax Laier 	event_del(&bufev->ev_read);
277*67ecd4f3SMax Laier 	event_del(&bufev->ev_write);
278*67ecd4f3SMax Laier 
279*67ecd4f3SMax Laier 	evbuffer_free(bufev->input);
280*67ecd4f3SMax Laier 	evbuffer_free(bufev->output);
281*67ecd4f3SMax Laier 
282*67ecd4f3SMax Laier 	free(bufev);
283*67ecd4f3SMax Laier }
284*67ecd4f3SMax Laier 
285*67ecd4f3SMax Laier /*
286*67ecd4f3SMax Laier  * Returns 0 on success;
287*67ecd4f3SMax Laier  *        -1 on failure.
288*67ecd4f3SMax Laier  */
289*67ecd4f3SMax Laier 
290*67ecd4f3SMax Laier int
bufferevent_write(struct bufferevent * bufev,void * data,size_t size)291*67ecd4f3SMax Laier bufferevent_write(struct bufferevent *bufev, void *data, size_t size)
292*67ecd4f3SMax Laier {
293*67ecd4f3SMax Laier 	int res;
294*67ecd4f3SMax Laier 
295*67ecd4f3SMax Laier 	res = evbuffer_add(bufev->output, data, size);
296*67ecd4f3SMax Laier 
297*67ecd4f3SMax Laier 	if (res == -1)
298*67ecd4f3SMax Laier 		return (res);
299*67ecd4f3SMax Laier 
300*67ecd4f3SMax Laier 	/* If everything is okay, we need to schedule a write */
301*67ecd4f3SMax Laier 	if (size > 0 && (bufev->enabled & EV_WRITE))
302*67ecd4f3SMax Laier 		bufferevent_add(&bufev->ev_write, bufev->timeout_write);
303*67ecd4f3SMax Laier 
304*67ecd4f3SMax Laier 	return (res);
305*67ecd4f3SMax Laier }
306*67ecd4f3SMax Laier 
307*67ecd4f3SMax Laier int
bufferevent_write_buffer(struct bufferevent * bufev,struct evbuffer * buf)308*67ecd4f3SMax Laier bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf)
309*67ecd4f3SMax Laier {
310*67ecd4f3SMax Laier 	int res;
311*67ecd4f3SMax Laier 
312*67ecd4f3SMax Laier 	res = bufferevent_write(bufev, buf->buffer, buf->off);
313*67ecd4f3SMax Laier 	if (res != -1)
314*67ecd4f3SMax Laier 		evbuffer_drain(buf, buf->off);
315*67ecd4f3SMax Laier 
316*67ecd4f3SMax Laier 	return (res);
317*67ecd4f3SMax Laier }
318*67ecd4f3SMax Laier 
319*67ecd4f3SMax Laier size_t
bufferevent_read(struct bufferevent * bufev,void * data,size_t size)320*67ecd4f3SMax Laier bufferevent_read(struct bufferevent *bufev, void *data, size_t size)
321*67ecd4f3SMax Laier {
322*67ecd4f3SMax Laier 	struct evbuffer *buf = bufev->input;
323*67ecd4f3SMax Laier 
324*67ecd4f3SMax Laier 	if (buf->off < size)
325*67ecd4f3SMax Laier 		size = buf->off;
326*67ecd4f3SMax Laier 
327*67ecd4f3SMax Laier 	/* Copy the available data to the user buffer */
328*67ecd4f3SMax Laier 	memcpy(data, buf->buffer, size);
329*67ecd4f3SMax Laier 
330*67ecd4f3SMax Laier 	if (size)
331*67ecd4f3SMax Laier 		evbuffer_drain(buf, size);
332*67ecd4f3SMax Laier 
333*67ecd4f3SMax Laier 	return (size);
334*67ecd4f3SMax Laier }
335*67ecd4f3SMax Laier 
336*67ecd4f3SMax Laier int
bufferevent_enable(struct bufferevent * bufev,short event)337*67ecd4f3SMax Laier bufferevent_enable(struct bufferevent *bufev, short event)
338*67ecd4f3SMax Laier {
339*67ecd4f3SMax Laier 	if (event & EV_READ) {
340*67ecd4f3SMax Laier 		if (bufferevent_add(&bufev->ev_read, bufev->timeout_read) == -1)
341*67ecd4f3SMax Laier 			return (-1);
342*67ecd4f3SMax Laier 	}
343*67ecd4f3SMax Laier 	if (event & EV_WRITE) {
344*67ecd4f3SMax Laier 		if (bufferevent_add(&bufev->ev_write, bufev->timeout_write) == -1)
345*67ecd4f3SMax Laier 			return (-1);
346*67ecd4f3SMax Laier 	}
347*67ecd4f3SMax Laier 
348*67ecd4f3SMax Laier 	bufev->enabled |= event;
349*67ecd4f3SMax Laier 	return (0);
350*67ecd4f3SMax Laier }
351*67ecd4f3SMax Laier 
352*67ecd4f3SMax Laier int
bufferevent_disable(struct bufferevent * bufev,short event)353*67ecd4f3SMax Laier bufferevent_disable(struct bufferevent *bufev, short event)
354*67ecd4f3SMax Laier {
355*67ecd4f3SMax Laier 	if (event & EV_READ) {
356*67ecd4f3SMax Laier 		if (event_del(&bufev->ev_read) == -1)
357*67ecd4f3SMax Laier 			return (-1);
358*67ecd4f3SMax Laier 	}
359*67ecd4f3SMax Laier 	if (event & EV_WRITE) {
360*67ecd4f3SMax Laier 		if (event_del(&bufev->ev_write) == -1)
361*67ecd4f3SMax Laier 			return (-1);
362*67ecd4f3SMax Laier 	}
363*67ecd4f3SMax Laier 
364*67ecd4f3SMax Laier 	bufev->enabled &= ~event;
365*67ecd4f3SMax Laier 	return (0);
366*67ecd4f3SMax Laier }
367*67ecd4f3SMax Laier 
368*67ecd4f3SMax Laier /*
369*67ecd4f3SMax Laier  * Sets the read and write timeout for a buffered event.
370*67ecd4f3SMax Laier  */
371*67ecd4f3SMax Laier 
372*67ecd4f3SMax Laier void
bufferevent_settimeout(struct bufferevent * bufev,int timeout_read,int timeout_write)373*67ecd4f3SMax Laier bufferevent_settimeout(struct bufferevent *bufev,
374*67ecd4f3SMax Laier     int timeout_read, int timeout_write) {
375*67ecd4f3SMax Laier 	bufev->timeout_read = timeout_read;
376*67ecd4f3SMax Laier 	bufev->timeout_write = timeout_write;
377*67ecd4f3SMax Laier }
378*67ecd4f3SMax Laier 
379*67ecd4f3SMax Laier /*
380*67ecd4f3SMax Laier  * Sets the water marks
381*67ecd4f3SMax Laier  */
382*67ecd4f3SMax Laier 
383*67ecd4f3SMax Laier void
bufferevent_setwatermark(struct bufferevent * bufev,short events,size_t lowmark,size_t highmark)384*67ecd4f3SMax Laier bufferevent_setwatermark(struct bufferevent *bufev, short events,
385*67ecd4f3SMax Laier     size_t lowmark, size_t highmark)
386*67ecd4f3SMax Laier {
387*67ecd4f3SMax Laier 	if (events & EV_READ) {
388*67ecd4f3SMax Laier 		bufev->wm_read.low = lowmark;
389*67ecd4f3SMax Laier 		bufev->wm_read.high = highmark;
390*67ecd4f3SMax Laier 	}
391*67ecd4f3SMax Laier 
392*67ecd4f3SMax Laier 	if (events & EV_WRITE) {
393*67ecd4f3SMax Laier 		bufev->wm_write.low = lowmark;
394*67ecd4f3SMax Laier 		bufev->wm_write.high = highmark;
395*67ecd4f3SMax Laier 	}
396*67ecd4f3SMax Laier 
397*67ecd4f3SMax Laier 	/* If the watermarks changed then see if we should call read again */
398*67ecd4f3SMax Laier 	bufferevent_read_pressure_cb(bufev->input,
399*67ecd4f3SMax Laier 	    0, EVBUFFER_LENGTH(bufev->input), bufev);
400*67ecd4f3SMax Laier }
401*67ecd4f3SMax Laier 
402*67ecd4f3SMax Laier int
bufferevent_base_set(struct event_base * base,struct bufferevent * bufev)403*67ecd4f3SMax Laier bufferevent_base_set(struct event_base *base, struct bufferevent *bufev)
404*67ecd4f3SMax Laier {
405*67ecd4f3SMax Laier 	int res;
406*67ecd4f3SMax Laier 
407*67ecd4f3SMax Laier 	res = event_base_set(base, &bufev->ev_read);
408*67ecd4f3SMax Laier 	if (res == -1)
409*67ecd4f3SMax Laier 		return (res);
410*67ecd4f3SMax Laier 
411*67ecd4f3SMax Laier 	res = event_base_set(base, &bufev->ev_write);
412*67ecd4f3SMax Laier 	return (res);
413*67ecd4f3SMax Laier }
414