xref: /aosp_15_r20/external/libevent/buffer.c (revision 663afb9b963571284e0f0a60f257164ab54f64bf)
1*663afb9bSAndroid Build Coastguard Worker /*
2*663afb9bSAndroid Build Coastguard Worker  * Copyright (c) 2002-2007 Niels Provos <[email protected]>
3*663afb9bSAndroid Build Coastguard Worker  * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
4*663afb9bSAndroid Build Coastguard Worker  *
5*663afb9bSAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
6*663afb9bSAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions
7*663afb9bSAndroid Build Coastguard Worker  * are met:
8*663afb9bSAndroid Build Coastguard Worker  * 1. Redistributions of source code must retain the above copyright
9*663afb9bSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer.
10*663afb9bSAndroid Build Coastguard Worker  * 2. Redistributions in binary form must reproduce the above copyright
11*663afb9bSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer in the
12*663afb9bSAndroid Build Coastguard Worker  *    documentation and/or other materials provided with the distribution.
13*663afb9bSAndroid Build Coastguard Worker  * 3. The name of the author may not be used to endorse or promote products
14*663afb9bSAndroid Build Coastguard Worker  *    derived from this software without specific prior written permission.
15*663afb9bSAndroid Build Coastguard Worker  *
16*663afb9bSAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17*663afb9bSAndroid Build Coastguard Worker  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18*663afb9bSAndroid Build Coastguard Worker  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19*663afb9bSAndroid Build Coastguard Worker  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20*663afb9bSAndroid Build Coastguard Worker  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21*663afb9bSAndroid Build Coastguard Worker  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22*663afb9bSAndroid Build Coastguard Worker  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23*663afb9bSAndroid Build Coastguard Worker  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24*663afb9bSAndroid Build Coastguard Worker  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25*663afb9bSAndroid Build Coastguard Worker  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*663afb9bSAndroid Build Coastguard Worker  */
27*663afb9bSAndroid Build Coastguard Worker 
28*663afb9bSAndroid Build Coastguard Worker #include "event2/event-config.h"
29*663afb9bSAndroid Build Coastguard Worker #include "evconfig-private.h"
30*663afb9bSAndroid Build Coastguard Worker 
31*663afb9bSAndroid Build Coastguard Worker #ifdef _WIN32
32*663afb9bSAndroid Build Coastguard Worker #include <winsock2.h>
33*663afb9bSAndroid Build Coastguard Worker #include <windows.h>
34*663afb9bSAndroid Build Coastguard Worker #include <io.h>
35*663afb9bSAndroid Build Coastguard Worker #endif
36*663afb9bSAndroid Build Coastguard Worker 
37*663afb9bSAndroid Build Coastguard Worker #ifdef EVENT__HAVE_VASPRINTF
38*663afb9bSAndroid Build Coastguard Worker /* If we have vasprintf, we need to define _GNU_SOURCE before we include
39*663afb9bSAndroid Build Coastguard Worker  * stdio.h.  This comes from evconfig-private.h.
40*663afb9bSAndroid Build Coastguard Worker  */
41*663afb9bSAndroid Build Coastguard Worker #endif
42*663afb9bSAndroid Build Coastguard Worker 
43*663afb9bSAndroid Build Coastguard Worker #include <sys/types.h>
44*663afb9bSAndroid Build Coastguard Worker 
45*663afb9bSAndroid Build Coastguard Worker #ifdef EVENT__HAVE_SYS_TIME_H
46*663afb9bSAndroid Build Coastguard Worker #include <sys/time.h>
47*663afb9bSAndroid Build Coastguard Worker #endif
48*663afb9bSAndroid Build Coastguard Worker 
49*663afb9bSAndroid Build Coastguard Worker #ifdef EVENT__HAVE_SYS_SOCKET_H
50*663afb9bSAndroid Build Coastguard Worker #include <sys/socket.h>
51*663afb9bSAndroid Build Coastguard Worker #endif
52*663afb9bSAndroid Build Coastguard Worker 
53*663afb9bSAndroid Build Coastguard Worker #ifdef EVENT__HAVE_SYS_UIO_H
54*663afb9bSAndroid Build Coastguard Worker #include <sys/uio.h>
55*663afb9bSAndroid Build Coastguard Worker #endif
56*663afb9bSAndroid Build Coastguard Worker 
57*663afb9bSAndroid Build Coastguard Worker #ifdef EVENT__HAVE_SYS_IOCTL_H
58*663afb9bSAndroid Build Coastguard Worker #include <sys/ioctl.h>
59*663afb9bSAndroid Build Coastguard Worker #endif
60*663afb9bSAndroid Build Coastguard Worker 
61*663afb9bSAndroid Build Coastguard Worker #ifdef EVENT__HAVE_SYS_MMAN_H
62*663afb9bSAndroid Build Coastguard Worker #include <sys/mman.h>
63*663afb9bSAndroid Build Coastguard Worker #endif
64*663afb9bSAndroid Build Coastguard Worker 
65*663afb9bSAndroid Build Coastguard Worker #ifdef EVENT__HAVE_SYS_SENDFILE_H
66*663afb9bSAndroid Build Coastguard Worker #include <sys/sendfile.h>
67*663afb9bSAndroid Build Coastguard Worker #endif
68*663afb9bSAndroid Build Coastguard Worker #ifdef EVENT__HAVE_SYS_STAT_H
69*663afb9bSAndroid Build Coastguard Worker #include <sys/stat.h>
70*663afb9bSAndroid Build Coastguard Worker #endif
71*663afb9bSAndroid Build Coastguard Worker 
72*663afb9bSAndroid Build Coastguard Worker 
73*663afb9bSAndroid Build Coastguard Worker #include <errno.h>
74*663afb9bSAndroid Build Coastguard Worker #include <stdio.h>
75*663afb9bSAndroid Build Coastguard Worker #include <stdlib.h>
76*663afb9bSAndroid Build Coastguard Worker #include <string.h>
77*663afb9bSAndroid Build Coastguard Worker #ifdef EVENT__HAVE_STDARG_H
78*663afb9bSAndroid Build Coastguard Worker #include <stdarg.h>
79*663afb9bSAndroid Build Coastguard Worker #endif
80*663afb9bSAndroid Build Coastguard Worker #ifdef EVENT__HAVE_UNISTD_H
81*663afb9bSAndroid Build Coastguard Worker #include <unistd.h>
82*663afb9bSAndroid Build Coastguard Worker #endif
83*663afb9bSAndroid Build Coastguard Worker #include <limits.h>
84*663afb9bSAndroid Build Coastguard Worker 
85*663afb9bSAndroid Build Coastguard Worker #include "event2/event.h"
86*663afb9bSAndroid Build Coastguard Worker #include "event2/buffer.h"
87*663afb9bSAndroid Build Coastguard Worker #include "event2/buffer_compat.h"
88*663afb9bSAndroid Build Coastguard Worker #include "event2/bufferevent.h"
89*663afb9bSAndroid Build Coastguard Worker #include "event2/bufferevent_compat.h"
90*663afb9bSAndroid Build Coastguard Worker #include "event2/bufferevent_struct.h"
91*663afb9bSAndroid Build Coastguard Worker #include "event2/thread.h"
92*663afb9bSAndroid Build Coastguard Worker #include "log-internal.h"
93*663afb9bSAndroid Build Coastguard Worker #include "mm-internal.h"
94*663afb9bSAndroid Build Coastguard Worker #include "util-internal.h"
95*663afb9bSAndroid Build Coastguard Worker #include "evthread-internal.h"
96*663afb9bSAndroid Build Coastguard Worker #include "evbuffer-internal.h"
97*663afb9bSAndroid Build Coastguard Worker #include "bufferevent-internal.h"
98*663afb9bSAndroid Build Coastguard Worker #include "event-internal.h"
99*663afb9bSAndroid Build Coastguard Worker 
100*663afb9bSAndroid Build Coastguard Worker /* some systems do not have MAP_FAILED */
101*663afb9bSAndroid Build Coastguard Worker #ifndef MAP_FAILED
102*663afb9bSAndroid Build Coastguard Worker #define MAP_FAILED	((void *)-1)
103*663afb9bSAndroid Build Coastguard Worker #endif
104*663afb9bSAndroid Build Coastguard Worker 
105*663afb9bSAndroid Build Coastguard Worker /* send file support */
106*663afb9bSAndroid Build Coastguard Worker #if defined(EVENT__HAVE_SYS_SENDFILE_H) && defined(EVENT__HAVE_SENDFILE) && defined(__linux__)
107*663afb9bSAndroid Build Coastguard Worker #define USE_SENDFILE		1
108*663afb9bSAndroid Build Coastguard Worker #define SENDFILE_IS_LINUX	1
109*663afb9bSAndroid Build Coastguard Worker #elif defined(EVENT__HAVE_SENDFILE) && defined(__FreeBSD__)
110*663afb9bSAndroid Build Coastguard Worker #define USE_SENDFILE		1
111*663afb9bSAndroid Build Coastguard Worker #define SENDFILE_IS_FREEBSD	1
112*663afb9bSAndroid Build Coastguard Worker #elif defined(EVENT__HAVE_SENDFILE) && defined(__APPLE__)
113*663afb9bSAndroid Build Coastguard Worker #define USE_SENDFILE		1
114*663afb9bSAndroid Build Coastguard Worker #define SENDFILE_IS_MACOSX	1
115*663afb9bSAndroid Build Coastguard Worker #elif defined(EVENT__HAVE_SENDFILE) && defined(__sun__) && defined(__svr4__)
116*663afb9bSAndroid Build Coastguard Worker #define USE_SENDFILE		1
117*663afb9bSAndroid Build Coastguard Worker #define SENDFILE_IS_SOLARIS	1
118*663afb9bSAndroid Build Coastguard Worker #endif
119*663afb9bSAndroid Build Coastguard Worker 
120*663afb9bSAndroid Build Coastguard Worker /* Mask of user-selectable callback flags. */
121*663afb9bSAndroid Build Coastguard Worker #define EVBUFFER_CB_USER_FLAGS	    0xffff
122*663afb9bSAndroid Build Coastguard Worker /* Mask of all internal-use-only flags. */
123*663afb9bSAndroid Build Coastguard Worker #define EVBUFFER_CB_INTERNAL_FLAGS  0xffff0000
124*663afb9bSAndroid Build Coastguard Worker 
125*663afb9bSAndroid Build Coastguard Worker /* Flag set if the callback is using the cb_obsolete function pointer  */
126*663afb9bSAndroid Build Coastguard Worker #define EVBUFFER_CB_OBSOLETE	       0x00040000
127*663afb9bSAndroid Build Coastguard Worker 
128*663afb9bSAndroid Build Coastguard Worker /* evbuffer_chain support */
129*663afb9bSAndroid Build Coastguard Worker #define CHAIN_SPACE_PTR(ch) ((ch)->buffer + (ch)->misalign + (ch)->off)
130*663afb9bSAndroid Build Coastguard Worker #define CHAIN_SPACE_LEN(ch) ((ch)->flags & EVBUFFER_IMMUTABLE ? \
131*663afb9bSAndroid Build Coastguard Worker 	    0 : (ch)->buffer_len - ((ch)->misalign + (ch)->off))
132*663afb9bSAndroid Build Coastguard Worker 
133*663afb9bSAndroid Build Coastguard Worker #define CHAIN_PINNED(ch)  (((ch)->flags & EVBUFFER_MEM_PINNED_ANY) != 0)
134*663afb9bSAndroid Build Coastguard Worker #define CHAIN_PINNED_R(ch)  (((ch)->flags & EVBUFFER_MEM_PINNED_R) != 0)
135*663afb9bSAndroid Build Coastguard Worker 
136*663afb9bSAndroid Build Coastguard Worker /* evbuffer_ptr support */
137*663afb9bSAndroid Build Coastguard Worker #define PTR_NOT_FOUND(ptr) do {			\
138*663afb9bSAndroid Build Coastguard Worker 	(ptr)->pos = -1;					\
139*663afb9bSAndroid Build Coastguard Worker 	(ptr)->internal_.chain = NULL;		\
140*663afb9bSAndroid Build Coastguard Worker 	(ptr)->internal_.pos_in_chain = 0;	\
141*663afb9bSAndroid Build Coastguard Worker } while (0)
142*663afb9bSAndroid Build Coastguard Worker 
143*663afb9bSAndroid Build Coastguard Worker static void evbuffer_chain_align(struct evbuffer_chain *chain);
144*663afb9bSAndroid Build Coastguard Worker static int evbuffer_chain_should_realign(struct evbuffer_chain *chain,
145*663afb9bSAndroid Build Coastguard Worker     size_t datalen);
146*663afb9bSAndroid Build Coastguard Worker static void evbuffer_deferred_callback(struct event_callback *cb, void *arg);
147*663afb9bSAndroid Build Coastguard Worker static int evbuffer_ptr_memcmp(const struct evbuffer *buf,
148*663afb9bSAndroid Build Coastguard Worker     const struct evbuffer_ptr *pos, const char *mem, size_t len);
149*663afb9bSAndroid Build Coastguard Worker static struct evbuffer_chain *evbuffer_expand_singlechain(struct evbuffer *buf,
150*663afb9bSAndroid Build Coastguard Worker     size_t datlen);
151*663afb9bSAndroid Build Coastguard Worker static int evbuffer_ptr_subtract(struct evbuffer *buf, struct evbuffer_ptr *pos,
152*663afb9bSAndroid Build Coastguard Worker     size_t howfar);
153*663afb9bSAndroid Build Coastguard Worker static int evbuffer_file_segment_materialize(struct evbuffer_file_segment *seg);
154*663afb9bSAndroid Build Coastguard Worker static inline void evbuffer_chain_incref(struct evbuffer_chain *chain);
155*663afb9bSAndroid Build Coastguard Worker 
156*663afb9bSAndroid Build Coastguard Worker static struct evbuffer_chain *
evbuffer_chain_new(size_t size)157*663afb9bSAndroid Build Coastguard Worker evbuffer_chain_new(size_t size)
158*663afb9bSAndroid Build Coastguard Worker {
159*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain;
160*663afb9bSAndroid Build Coastguard Worker 	size_t to_alloc;
161*663afb9bSAndroid Build Coastguard Worker 
162*663afb9bSAndroid Build Coastguard Worker 	if (size > EVBUFFER_CHAIN_MAX - EVBUFFER_CHAIN_SIZE)
163*663afb9bSAndroid Build Coastguard Worker 		return (NULL);
164*663afb9bSAndroid Build Coastguard Worker 
165*663afb9bSAndroid Build Coastguard Worker 	size += EVBUFFER_CHAIN_SIZE;
166*663afb9bSAndroid Build Coastguard Worker 
167*663afb9bSAndroid Build Coastguard Worker 	/* get the next largest memory that can hold the buffer */
168*663afb9bSAndroid Build Coastguard Worker 	if (size < EVBUFFER_CHAIN_MAX / 2) {
169*663afb9bSAndroid Build Coastguard Worker 		to_alloc = MIN_BUFFER_SIZE;
170*663afb9bSAndroid Build Coastguard Worker 		while (to_alloc < size) {
171*663afb9bSAndroid Build Coastguard Worker 			to_alloc <<= 1;
172*663afb9bSAndroid Build Coastguard Worker 		}
173*663afb9bSAndroid Build Coastguard Worker 	} else {
174*663afb9bSAndroid Build Coastguard Worker 		to_alloc = size;
175*663afb9bSAndroid Build Coastguard Worker 	}
176*663afb9bSAndroid Build Coastguard Worker 
177*663afb9bSAndroid Build Coastguard Worker 	/* we get everything in one chunk */
178*663afb9bSAndroid Build Coastguard Worker 	if ((chain = mm_malloc(to_alloc)) == NULL)
179*663afb9bSAndroid Build Coastguard Worker 		return (NULL);
180*663afb9bSAndroid Build Coastguard Worker 
181*663afb9bSAndroid Build Coastguard Worker 	memset(chain, 0, EVBUFFER_CHAIN_SIZE);
182*663afb9bSAndroid Build Coastguard Worker 
183*663afb9bSAndroid Build Coastguard Worker 	chain->buffer_len = to_alloc - EVBUFFER_CHAIN_SIZE;
184*663afb9bSAndroid Build Coastguard Worker 
185*663afb9bSAndroid Build Coastguard Worker 	/* this way we can manipulate the buffer to different addresses,
186*663afb9bSAndroid Build Coastguard Worker 	 * which is required for mmap for example.
187*663afb9bSAndroid Build Coastguard Worker 	 */
188*663afb9bSAndroid Build Coastguard Worker 	chain->buffer = EVBUFFER_CHAIN_EXTRA(unsigned char, chain);
189*663afb9bSAndroid Build Coastguard Worker 
190*663afb9bSAndroid Build Coastguard Worker 	chain->refcnt = 1;
191*663afb9bSAndroid Build Coastguard Worker 
192*663afb9bSAndroid Build Coastguard Worker 	return (chain);
193*663afb9bSAndroid Build Coastguard Worker }
194*663afb9bSAndroid Build Coastguard Worker 
195*663afb9bSAndroid Build Coastguard Worker static inline void
evbuffer_chain_free(struct evbuffer_chain * chain)196*663afb9bSAndroid Build Coastguard Worker evbuffer_chain_free(struct evbuffer_chain *chain)
197*663afb9bSAndroid Build Coastguard Worker {
198*663afb9bSAndroid Build Coastguard Worker 	EVUTIL_ASSERT(chain->refcnt > 0);
199*663afb9bSAndroid Build Coastguard Worker 	if (--chain->refcnt > 0) {
200*663afb9bSAndroid Build Coastguard Worker 		/* chain is still referenced by other chains */
201*663afb9bSAndroid Build Coastguard Worker 		return;
202*663afb9bSAndroid Build Coastguard Worker 	}
203*663afb9bSAndroid Build Coastguard Worker 
204*663afb9bSAndroid Build Coastguard Worker 	if (CHAIN_PINNED(chain)) {
205*663afb9bSAndroid Build Coastguard Worker 		/* will get freed once no longer dangling */
206*663afb9bSAndroid Build Coastguard Worker 		chain->refcnt++;
207*663afb9bSAndroid Build Coastguard Worker 		chain->flags |= EVBUFFER_DANGLING;
208*663afb9bSAndroid Build Coastguard Worker 		return;
209*663afb9bSAndroid Build Coastguard Worker 	}
210*663afb9bSAndroid Build Coastguard Worker 
211*663afb9bSAndroid Build Coastguard Worker 	/* safe to release chain, it's either a referencing
212*663afb9bSAndroid Build Coastguard Worker 	 * chain or all references to it have been freed */
213*663afb9bSAndroid Build Coastguard Worker 	if (chain->flags & EVBUFFER_REFERENCE) {
214*663afb9bSAndroid Build Coastguard Worker 		struct evbuffer_chain_reference *info =
215*663afb9bSAndroid Build Coastguard Worker 		    EVBUFFER_CHAIN_EXTRA(
216*663afb9bSAndroid Build Coastguard Worker 			    struct evbuffer_chain_reference,
217*663afb9bSAndroid Build Coastguard Worker 			    chain);
218*663afb9bSAndroid Build Coastguard Worker 		if (info->cleanupfn)
219*663afb9bSAndroid Build Coastguard Worker 			(*info->cleanupfn)(chain->buffer,
220*663afb9bSAndroid Build Coastguard Worker 			    chain->buffer_len,
221*663afb9bSAndroid Build Coastguard Worker 			    info->extra);
222*663afb9bSAndroid Build Coastguard Worker 	}
223*663afb9bSAndroid Build Coastguard Worker 	if (chain->flags & EVBUFFER_FILESEGMENT) {
224*663afb9bSAndroid Build Coastguard Worker 		struct evbuffer_chain_file_segment *info =
225*663afb9bSAndroid Build Coastguard Worker 		    EVBUFFER_CHAIN_EXTRA(
226*663afb9bSAndroid Build Coastguard Worker 			    struct evbuffer_chain_file_segment,
227*663afb9bSAndroid Build Coastguard Worker 			    chain);
228*663afb9bSAndroid Build Coastguard Worker 		if (info->segment) {
229*663afb9bSAndroid Build Coastguard Worker #ifdef _WIN32
230*663afb9bSAndroid Build Coastguard Worker 			if (info->segment->is_mapping)
231*663afb9bSAndroid Build Coastguard Worker 				UnmapViewOfFile(chain->buffer);
232*663afb9bSAndroid Build Coastguard Worker #endif
233*663afb9bSAndroid Build Coastguard Worker 			evbuffer_file_segment_free(info->segment);
234*663afb9bSAndroid Build Coastguard Worker 		}
235*663afb9bSAndroid Build Coastguard Worker 	}
236*663afb9bSAndroid Build Coastguard Worker 	if (chain->flags & EVBUFFER_MULTICAST) {
237*663afb9bSAndroid Build Coastguard Worker 		struct evbuffer_multicast_parent *info =
238*663afb9bSAndroid Build Coastguard Worker 		    EVBUFFER_CHAIN_EXTRA(
239*663afb9bSAndroid Build Coastguard Worker 			    struct evbuffer_multicast_parent,
240*663afb9bSAndroid Build Coastguard Worker 			    chain);
241*663afb9bSAndroid Build Coastguard Worker 		/* referencing chain is being freed, decrease
242*663afb9bSAndroid Build Coastguard Worker 		 * refcounts of source chain and associated
243*663afb9bSAndroid Build Coastguard Worker 		 * evbuffer (which get freed once both reach
244*663afb9bSAndroid Build Coastguard Worker 		 * zero) */
245*663afb9bSAndroid Build Coastguard Worker 		EVUTIL_ASSERT(info->source != NULL);
246*663afb9bSAndroid Build Coastguard Worker 		EVUTIL_ASSERT(info->parent != NULL);
247*663afb9bSAndroid Build Coastguard Worker 		EVBUFFER_LOCK(info->source);
248*663afb9bSAndroid Build Coastguard Worker 		evbuffer_chain_free(info->parent);
249*663afb9bSAndroid Build Coastguard Worker 		evbuffer_decref_and_unlock_(info->source);
250*663afb9bSAndroid Build Coastguard Worker 	}
251*663afb9bSAndroid Build Coastguard Worker 
252*663afb9bSAndroid Build Coastguard Worker 	mm_free(chain);
253*663afb9bSAndroid Build Coastguard Worker }
254*663afb9bSAndroid Build Coastguard Worker 
255*663afb9bSAndroid Build Coastguard Worker static void
evbuffer_free_all_chains(struct evbuffer_chain * chain)256*663afb9bSAndroid Build Coastguard Worker evbuffer_free_all_chains(struct evbuffer_chain *chain)
257*663afb9bSAndroid Build Coastguard Worker {
258*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *next;
259*663afb9bSAndroid Build Coastguard Worker 	for (; chain; chain = next) {
260*663afb9bSAndroid Build Coastguard Worker 		next = chain->next;
261*663afb9bSAndroid Build Coastguard Worker 		evbuffer_chain_free(chain);
262*663afb9bSAndroid Build Coastguard Worker 	}
263*663afb9bSAndroid Build Coastguard Worker }
264*663afb9bSAndroid Build Coastguard Worker 
265*663afb9bSAndroid Build Coastguard Worker #ifndef NDEBUG
266*663afb9bSAndroid Build Coastguard Worker static int
evbuffer_chains_all_empty(struct evbuffer_chain * chain)267*663afb9bSAndroid Build Coastguard Worker evbuffer_chains_all_empty(struct evbuffer_chain *chain)
268*663afb9bSAndroid Build Coastguard Worker {
269*663afb9bSAndroid Build Coastguard Worker 	for (; chain; chain = chain->next) {
270*663afb9bSAndroid Build Coastguard Worker 		if (chain->off)
271*663afb9bSAndroid Build Coastguard Worker 			return 0;
272*663afb9bSAndroid Build Coastguard Worker 	}
273*663afb9bSAndroid Build Coastguard Worker 	return 1;
274*663afb9bSAndroid Build Coastguard Worker }
275*663afb9bSAndroid Build Coastguard Worker #else
276*663afb9bSAndroid Build Coastguard Worker /* The definition is needed for EVUTIL_ASSERT, which uses sizeof to avoid
277*663afb9bSAndroid Build Coastguard Worker "unused variable" warnings. */
evbuffer_chains_all_empty(struct evbuffer_chain * chain)278*663afb9bSAndroid Build Coastguard Worker static inline int evbuffer_chains_all_empty(struct evbuffer_chain *chain) {
279*663afb9bSAndroid Build Coastguard Worker 	return 1;
280*663afb9bSAndroid Build Coastguard Worker }
281*663afb9bSAndroid Build Coastguard Worker #endif
282*663afb9bSAndroid Build Coastguard Worker 
283*663afb9bSAndroid Build Coastguard Worker /* Free all trailing chains in 'buf' that are neither pinned nor empty, prior
284*663afb9bSAndroid Build Coastguard Worker  * to replacing them all with a new chain.  Return a pointer to the place
285*663afb9bSAndroid Build Coastguard Worker  * where the new chain will go.
286*663afb9bSAndroid Build Coastguard Worker  *
287*663afb9bSAndroid Build Coastguard Worker  * Internal; requires lock.  The caller must fix up buf->last and buf->first
288*663afb9bSAndroid Build Coastguard Worker  * as needed; they might have been freed.
289*663afb9bSAndroid Build Coastguard Worker  */
290*663afb9bSAndroid Build Coastguard Worker static struct evbuffer_chain **
evbuffer_free_trailing_empty_chains(struct evbuffer * buf)291*663afb9bSAndroid Build Coastguard Worker evbuffer_free_trailing_empty_chains(struct evbuffer *buf)
292*663afb9bSAndroid Build Coastguard Worker {
293*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain **ch = buf->last_with_datap;
294*663afb9bSAndroid Build Coastguard Worker 	/* Find the first victim chain.  It might be *last_with_datap */
295*663afb9bSAndroid Build Coastguard Worker 	while ((*ch) && ((*ch)->off != 0 || CHAIN_PINNED(*ch)))
296*663afb9bSAndroid Build Coastguard Worker 		ch = &(*ch)->next;
297*663afb9bSAndroid Build Coastguard Worker 	if (*ch) {
298*663afb9bSAndroid Build Coastguard Worker 		EVUTIL_ASSERT(evbuffer_chains_all_empty(*ch));
299*663afb9bSAndroid Build Coastguard Worker 		evbuffer_free_all_chains(*ch);
300*663afb9bSAndroid Build Coastguard Worker 		*ch = NULL;
301*663afb9bSAndroid Build Coastguard Worker 	}
302*663afb9bSAndroid Build Coastguard Worker 	return ch;
303*663afb9bSAndroid Build Coastguard Worker }
304*663afb9bSAndroid Build Coastguard Worker 
305*663afb9bSAndroid Build Coastguard Worker /* Add a single chain 'chain' to the end of 'buf', freeing trailing empty
306*663afb9bSAndroid Build Coastguard Worker  * chains as necessary.  Requires lock.  Does not schedule callbacks.
307*663afb9bSAndroid Build Coastguard Worker  */
308*663afb9bSAndroid Build Coastguard Worker static void
evbuffer_chain_insert(struct evbuffer * buf,struct evbuffer_chain * chain)309*663afb9bSAndroid Build Coastguard Worker evbuffer_chain_insert(struct evbuffer *buf,
310*663afb9bSAndroid Build Coastguard Worker     struct evbuffer_chain *chain)
311*663afb9bSAndroid Build Coastguard Worker {
312*663afb9bSAndroid Build Coastguard Worker 	ASSERT_EVBUFFER_LOCKED(buf);
313*663afb9bSAndroid Build Coastguard Worker 	if (*buf->last_with_datap == NULL) {
314*663afb9bSAndroid Build Coastguard Worker 		/* There are no chains data on the buffer at all. */
315*663afb9bSAndroid Build Coastguard Worker 		EVUTIL_ASSERT(buf->last_with_datap == &buf->first);
316*663afb9bSAndroid Build Coastguard Worker 		EVUTIL_ASSERT(buf->first == NULL);
317*663afb9bSAndroid Build Coastguard Worker 		buf->first = buf->last = chain;
318*663afb9bSAndroid Build Coastguard Worker 	} else {
319*663afb9bSAndroid Build Coastguard Worker 		struct evbuffer_chain **chp;
320*663afb9bSAndroid Build Coastguard Worker 		chp = evbuffer_free_trailing_empty_chains(buf);
321*663afb9bSAndroid Build Coastguard Worker 		*chp = chain;
322*663afb9bSAndroid Build Coastguard Worker 		if (chain->off)
323*663afb9bSAndroid Build Coastguard Worker 			buf->last_with_datap = chp;
324*663afb9bSAndroid Build Coastguard Worker 		buf->last = chain;
325*663afb9bSAndroid Build Coastguard Worker 	}
326*663afb9bSAndroid Build Coastguard Worker 	buf->total_len += chain->off;
327*663afb9bSAndroid Build Coastguard Worker }
328*663afb9bSAndroid Build Coastguard Worker 
329*663afb9bSAndroid Build Coastguard Worker static inline struct evbuffer_chain *
evbuffer_chain_insert_new(struct evbuffer * buf,size_t datlen)330*663afb9bSAndroid Build Coastguard Worker evbuffer_chain_insert_new(struct evbuffer *buf, size_t datlen)
331*663afb9bSAndroid Build Coastguard Worker {
332*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain;
333*663afb9bSAndroid Build Coastguard Worker 	if ((chain = evbuffer_chain_new(datlen)) == NULL)
334*663afb9bSAndroid Build Coastguard Worker 		return NULL;
335*663afb9bSAndroid Build Coastguard Worker 	evbuffer_chain_insert(buf, chain);
336*663afb9bSAndroid Build Coastguard Worker 	return chain;
337*663afb9bSAndroid Build Coastguard Worker }
338*663afb9bSAndroid Build Coastguard Worker 
339*663afb9bSAndroid Build Coastguard Worker void
evbuffer_chain_pin_(struct evbuffer_chain * chain,unsigned flag)340*663afb9bSAndroid Build Coastguard Worker evbuffer_chain_pin_(struct evbuffer_chain *chain, unsigned flag)
341*663afb9bSAndroid Build Coastguard Worker {
342*663afb9bSAndroid Build Coastguard Worker 	EVUTIL_ASSERT((chain->flags & flag) == 0);
343*663afb9bSAndroid Build Coastguard Worker 	chain->flags |= flag;
344*663afb9bSAndroid Build Coastguard Worker }
345*663afb9bSAndroid Build Coastguard Worker 
346*663afb9bSAndroid Build Coastguard Worker void
evbuffer_chain_unpin_(struct evbuffer_chain * chain,unsigned flag)347*663afb9bSAndroid Build Coastguard Worker evbuffer_chain_unpin_(struct evbuffer_chain *chain, unsigned flag)
348*663afb9bSAndroid Build Coastguard Worker {
349*663afb9bSAndroid Build Coastguard Worker 	EVUTIL_ASSERT((chain->flags & flag) != 0);
350*663afb9bSAndroid Build Coastguard Worker 	chain->flags &= ~flag;
351*663afb9bSAndroid Build Coastguard Worker 	if (chain->flags & EVBUFFER_DANGLING)
352*663afb9bSAndroid Build Coastguard Worker 		evbuffer_chain_free(chain);
353*663afb9bSAndroid Build Coastguard Worker }
354*663afb9bSAndroid Build Coastguard Worker 
355*663afb9bSAndroid Build Coastguard Worker static inline void
evbuffer_chain_incref(struct evbuffer_chain * chain)356*663afb9bSAndroid Build Coastguard Worker evbuffer_chain_incref(struct evbuffer_chain *chain)
357*663afb9bSAndroid Build Coastguard Worker {
358*663afb9bSAndroid Build Coastguard Worker     ++chain->refcnt;
359*663afb9bSAndroid Build Coastguard Worker }
360*663afb9bSAndroid Build Coastguard Worker 
361*663afb9bSAndroid Build Coastguard Worker struct evbuffer *
evbuffer_new(void)362*663afb9bSAndroid Build Coastguard Worker evbuffer_new(void)
363*663afb9bSAndroid Build Coastguard Worker {
364*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer *buffer;
365*663afb9bSAndroid Build Coastguard Worker 
366*663afb9bSAndroid Build Coastguard Worker 	buffer = mm_calloc(1, sizeof(struct evbuffer));
367*663afb9bSAndroid Build Coastguard Worker 	if (buffer == NULL)
368*663afb9bSAndroid Build Coastguard Worker 		return (NULL);
369*663afb9bSAndroid Build Coastguard Worker 
370*663afb9bSAndroid Build Coastguard Worker 	LIST_INIT(&buffer->callbacks);
371*663afb9bSAndroid Build Coastguard Worker 	buffer->refcnt = 1;
372*663afb9bSAndroid Build Coastguard Worker 	buffer->last_with_datap = &buffer->first;
373*663afb9bSAndroid Build Coastguard Worker 
374*663afb9bSAndroid Build Coastguard Worker 	return (buffer);
375*663afb9bSAndroid Build Coastguard Worker }
376*663afb9bSAndroid Build Coastguard Worker 
377*663afb9bSAndroid Build Coastguard Worker int
evbuffer_set_flags(struct evbuffer * buf,ev_uint64_t flags)378*663afb9bSAndroid Build Coastguard Worker evbuffer_set_flags(struct evbuffer *buf, ev_uint64_t flags)
379*663afb9bSAndroid Build Coastguard Worker {
380*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buf);
381*663afb9bSAndroid Build Coastguard Worker 	buf->flags |= (ev_uint32_t)flags;
382*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buf);
383*663afb9bSAndroid Build Coastguard Worker 	return 0;
384*663afb9bSAndroid Build Coastguard Worker }
385*663afb9bSAndroid Build Coastguard Worker 
386*663afb9bSAndroid Build Coastguard Worker int
evbuffer_clear_flags(struct evbuffer * buf,ev_uint64_t flags)387*663afb9bSAndroid Build Coastguard Worker evbuffer_clear_flags(struct evbuffer *buf, ev_uint64_t flags)
388*663afb9bSAndroid Build Coastguard Worker {
389*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buf);
390*663afb9bSAndroid Build Coastguard Worker 	buf->flags &= ~(ev_uint32_t)flags;
391*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buf);
392*663afb9bSAndroid Build Coastguard Worker 	return 0;
393*663afb9bSAndroid Build Coastguard Worker }
394*663afb9bSAndroid Build Coastguard Worker 
395*663afb9bSAndroid Build Coastguard Worker void
evbuffer_incref_(struct evbuffer * buf)396*663afb9bSAndroid Build Coastguard Worker evbuffer_incref_(struct evbuffer *buf)
397*663afb9bSAndroid Build Coastguard Worker {
398*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buf);
399*663afb9bSAndroid Build Coastguard Worker 	++buf->refcnt;
400*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buf);
401*663afb9bSAndroid Build Coastguard Worker }
402*663afb9bSAndroid Build Coastguard Worker 
403*663afb9bSAndroid Build Coastguard Worker void
evbuffer_incref_and_lock_(struct evbuffer * buf)404*663afb9bSAndroid Build Coastguard Worker evbuffer_incref_and_lock_(struct evbuffer *buf)
405*663afb9bSAndroid Build Coastguard Worker {
406*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buf);
407*663afb9bSAndroid Build Coastguard Worker 	++buf->refcnt;
408*663afb9bSAndroid Build Coastguard Worker }
409*663afb9bSAndroid Build Coastguard Worker 
410*663afb9bSAndroid Build Coastguard Worker int
evbuffer_defer_callbacks(struct evbuffer * buffer,struct event_base * base)411*663afb9bSAndroid Build Coastguard Worker evbuffer_defer_callbacks(struct evbuffer *buffer, struct event_base *base)
412*663afb9bSAndroid Build Coastguard Worker {
413*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buffer);
414*663afb9bSAndroid Build Coastguard Worker 	buffer->cb_queue = base;
415*663afb9bSAndroid Build Coastguard Worker 	buffer->deferred_cbs = 1;
416*663afb9bSAndroid Build Coastguard Worker 	event_deferred_cb_init_(&buffer->deferred,
417*663afb9bSAndroid Build Coastguard Worker 	    event_base_get_npriorities(base) / 2,
418*663afb9bSAndroid Build Coastguard Worker 	    evbuffer_deferred_callback, buffer);
419*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buffer);
420*663afb9bSAndroid Build Coastguard Worker 	return 0;
421*663afb9bSAndroid Build Coastguard Worker }
422*663afb9bSAndroid Build Coastguard Worker 
423*663afb9bSAndroid Build Coastguard Worker int
evbuffer_enable_locking(struct evbuffer * buf,void * lock)424*663afb9bSAndroid Build Coastguard Worker evbuffer_enable_locking(struct evbuffer *buf, void *lock)
425*663afb9bSAndroid Build Coastguard Worker {
426*663afb9bSAndroid Build Coastguard Worker #ifdef EVENT__DISABLE_THREAD_SUPPORT
427*663afb9bSAndroid Build Coastguard Worker 	return -1;
428*663afb9bSAndroid Build Coastguard Worker #else
429*663afb9bSAndroid Build Coastguard Worker 	if (buf->lock)
430*663afb9bSAndroid Build Coastguard Worker 		return -1;
431*663afb9bSAndroid Build Coastguard Worker 
432*663afb9bSAndroid Build Coastguard Worker 	if (!lock) {
433*663afb9bSAndroid Build Coastguard Worker 		EVTHREAD_ALLOC_LOCK(lock, EVTHREAD_LOCKTYPE_RECURSIVE);
434*663afb9bSAndroid Build Coastguard Worker 		if (!lock)
435*663afb9bSAndroid Build Coastguard Worker 			return -1;
436*663afb9bSAndroid Build Coastguard Worker 		buf->lock = lock;
437*663afb9bSAndroid Build Coastguard Worker 		buf->own_lock = 1;
438*663afb9bSAndroid Build Coastguard Worker 	} else {
439*663afb9bSAndroid Build Coastguard Worker 		buf->lock = lock;
440*663afb9bSAndroid Build Coastguard Worker 		buf->own_lock = 0;
441*663afb9bSAndroid Build Coastguard Worker 	}
442*663afb9bSAndroid Build Coastguard Worker 
443*663afb9bSAndroid Build Coastguard Worker 	return 0;
444*663afb9bSAndroid Build Coastguard Worker #endif
445*663afb9bSAndroid Build Coastguard Worker }
446*663afb9bSAndroid Build Coastguard Worker 
447*663afb9bSAndroid Build Coastguard Worker void
evbuffer_set_parent_(struct evbuffer * buf,struct bufferevent * bev)448*663afb9bSAndroid Build Coastguard Worker evbuffer_set_parent_(struct evbuffer *buf, struct bufferevent *bev)
449*663afb9bSAndroid Build Coastguard Worker {
450*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buf);
451*663afb9bSAndroid Build Coastguard Worker 	buf->parent = bev;
452*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buf);
453*663afb9bSAndroid Build Coastguard Worker }
454*663afb9bSAndroid Build Coastguard Worker 
455*663afb9bSAndroid Build Coastguard Worker static void
evbuffer_run_callbacks(struct evbuffer * buffer,int running_deferred)456*663afb9bSAndroid Build Coastguard Worker evbuffer_run_callbacks(struct evbuffer *buffer, int running_deferred)
457*663afb9bSAndroid Build Coastguard Worker {
458*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_cb_entry *cbent, *next;
459*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_cb_info info;
460*663afb9bSAndroid Build Coastguard Worker 	size_t new_size;
461*663afb9bSAndroid Build Coastguard Worker 	ev_uint32_t mask, masked_val;
462*663afb9bSAndroid Build Coastguard Worker 	int clear = 1;
463*663afb9bSAndroid Build Coastguard Worker 
464*663afb9bSAndroid Build Coastguard Worker 	if (running_deferred) {
465*663afb9bSAndroid Build Coastguard Worker 		mask = EVBUFFER_CB_NODEFER|EVBUFFER_CB_ENABLED;
466*663afb9bSAndroid Build Coastguard Worker 		masked_val = EVBUFFER_CB_ENABLED;
467*663afb9bSAndroid Build Coastguard Worker 	} else if (buffer->deferred_cbs) {
468*663afb9bSAndroid Build Coastguard Worker 		mask = EVBUFFER_CB_NODEFER|EVBUFFER_CB_ENABLED;
469*663afb9bSAndroid Build Coastguard Worker 		masked_val = EVBUFFER_CB_NODEFER|EVBUFFER_CB_ENABLED;
470*663afb9bSAndroid Build Coastguard Worker 		/* Don't zero-out n_add/n_del, since the deferred callbacks
471*663afb9bSAndroid Build Coastguard Worker 		   will want to see them. */
472*663afb9bSAndroid Build Coastguard Worker 		clear = 0;
473*663afb9bSAndroid Build Coastguard Worker 	} else {
474*663afb9bSAndroid Build Coastguard Worker 		mask = EVBUFFER_CB_ENABLED;
475*663afb9bSAndroid Build Coastguard Worker 		masked_val = EVBUFFER_CB_ENABLED;
476*663afb9bSAndroid Build Coastguard Worker 	}
477*663afb9bSAndroid Build Coastguard Worker 
478*663afb9bSAndroid Build Coastguard Worker 	ASSERT_EVBUFFER_LOCKED(buffer);
479*663afb9bSAndroid Build Coastguard Worker 
480*663afb9bSAndroid Build Coastguard Worker 	if (LIST_EMPTY(&buffer->callbacks)) {
481*663afb9bSAndroid Build Coastguard Worker 		buffer->n_add_for_cb = buffer->n_del_for_cb = 0;
482*663afb9bSAndroid Build Coastguard Worker 		return;
483*663afb9bSAndroid Build Coastguard Worker 	}
484*663afb9bSAndroid Build Coastguard Worker 	if (buffer->n_add_for_cb == 0 && buffer->n_del_for_cb == 0)
485*663afb9bSAndroid Build Coastguard Worker 		return;
486*663afb9bSAndroid Build Coastguard Worker 
487*663afb9bSAndroid Build Coastguard Worker 	new_size = buffer->total_len;
488*663afb9bSAndroid Build Coastguard Worker 	info.orig_size = new_size + buffer->n_del_for_cb - buffer->n_add_for_cb;
489*663afb9bSAndroid Build Coastguard Worker 	info.n_added = buffer->n_add_for_cb;
490*663afb9bSAndroid Build Coastguard Worker 	info.n_deleted = buffer->n_del_for_cb;
491*663afb9bSAndroid Build Coastguard Worker 	if (clear) {
492*663afb9bSAndroid Build Coastguard Worker 		buffer->n_add_for_cb = 0;
493*663afb9bSAndroid Build Coastguard Worker 		buffer->n_del_for_cb = 0;
494*663afb9bSAndroid Build Coastguard Worker 	}
495*663afb9bSAndroid Build Coastguard Worker 	for (cbent = LIST_FIRST(&buffer->callbacks);
496*663afb9bSAndroid Build Coastguard Worker 	     cbent != LIST_END(&buffer->callbacks);
497*663afb9bSAndroid Build Coastguard Worker 	     cbent = next) {
498*663afb9bSAndroid Build Coastguard Worker 		/* Get the 'next' pointer now in case this callback decides
499*663afb9bSAndroid Build Coastguard Worker 		 * to remove itself or something. */
500*663afb9bSAndroid Build Coastguard Worker 		next = LIST_NEXT(cbent, next);
501*663afb9bSAndroid Build Coastguard Worker 
502*663afb9bSAndroid Build Coastguard Worker 		if ((cbent->flags & mask) != masked_val)
503*663afb9bSAndroid Build Coastguard Worker 			continue;
504*663afb9bSAndroid Build Coastguard Worker 
505*663afb9bSAndroid Build Coastguard Worker 		if ((cbent->flags & EVBUFFER_CB_OBSOLETE))
506*663afb9bSAndroid Build Coastguard Worker 			cbent->cb.cb_obsolete(buffer,
507*663afb9bSAndroid Build Coastguard Worker 			    info.orig_size, new_size, cbent->cbarg);
508*663afb9bSAndroid Build Coastguard Worker 		else
509*663afb9bSAndroid Build Coastguard Worker 			cbent->cb.cb_func(buffer, &info, cbent->cbarg);
510*663afb9bSAndroid Build Coastguard Worker 	}
511*663afb9bSAndroid Build Coastguard Worker }
512*663afb9bSAndroid Build Coastguard Worker 
513*663afb9bSAndroid Build Coastguard Worker void
evbuffer_invoke_callbacks_(struct evbuffer * buffer)514*663afb9bSAndroid Build Coastguard Worker evbuffer_invoke_callbacks_(struct evbuffer *buffer)
515*663afb9bSAndroid Build Coastguard Worker {
516*663afb9bSAndroid Build Coastguard Worker 	if (LIST_EMPTY(&buffer->callbacks)) {
517*663afb9bSAndroid Build Coastguard Worker 		buffer->n_add_for_cb = buffer->n_del_for_cb = 0;
518*663afb9bSAndroid Build Coastguard Worker 		return;
519*663afb9bSAndroid Build Coastguard Worker 	}
520*663afb9bSAndroid Build Coastguard Worker 
521*663afb9bSAndroid Build Coastguard Worker 	if (buffer->deferred_cbs) {
522*663afb9bSAndroid Build Coastguard Worker 		if (event_deferred_cb_schedule_(buffer->cb_queue, &buffer->deferred)) {
523*663afb9bSAndroid Build Coastguard Worker 			evbuffer_incref_and_lock_(buffer);
524*663afb9bSAndroid Build Coastguard Worker 			if (buffer->parent)
525*663afb9bSAndroid Build Coastguard Worker 				bufferevent_incref_(buffer->parent);
526*663afb9bSAndroid Build Coastguard Worker 			EVBUFFER_UNLOCK(buffer);
527*663afb9bSAndroid Build Coastguard Worker 		}
528*663afb9bSAndroid Build Coastguard Worker 	}
529*663afb9bSAndroid Build Coastguard Worker 
530*663afb9bSAndroid Build Coastguard Worker 	evbuffer_run_callbacks(buffer, 0);
531*663afb9bSAndroid Build Coastguard Worker }
532*663afb9bSAndroid Build Coastguard Worker 
533*663afb9bSAndroid Build Coastguard Worker static void
evbuffer_deferred_callback(struct event_callback * cb,void * arg)534*663afb9bSAndroid Build Coastguard Worker evbuffer_deferred_callback(struct event_callback *cb, void *arg)
535*663afb9bSAndroid Build Coastguard Worker {
536*663afb9bSAndroid Build Coastguard Worker 	struct bufferevent *parent = NULL;
537*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer *buffer = arg;
538*663afb9bSAndroid Build Coastguard Worker 
539*663afb9bSAndroid Build Coastguard Worker 	/* XXXX It would be better to run these callbacks without holding the
540*663afb9bSAndroid Build Coastguard Worker 	 * lock */
541*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buffer);
542*663afb9bSAndroid Build Coastguard Worker 	parent = buffer->parent;
543*663afb9bSAndroid Build Coastguard Worker 	evbuffer_run_callbacks(buffer, 1);
544*663afb9bSAndroid Build Coastguard Worker 	evbuffer_decref_and_unlock_(buffer);
545*663afb9bSAndroid Build Coastguard Worker 	if (parent)
546*663afb9bSAndroid Build Coastguard Worker 		bufferevent_decref_(parent);
547*663afb9bSAndroid Build Coastguard Worker }
548*663afb9bSAndroid Build Coastguard Worker 
549*663afb9bSAndroid Build Coastguard Worker static void
evbuffer_remove_all_callbacks(struct evbuffer * buffer)550*663afb9bSAndroid Build Coastguard Worker evbuffer_remove_all_callbacks(struct evbuffer *buffer)
551*663afb9bSAndroid Build Coastguard Worker {
552*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_cb_entry *cbent;
553*663afb9bSAndroid Build Coastguard Worker 
554*663afb9bSAndroid Build Coastguard Worker 	while ((cbent = LIST_FIRST(&buffer->callbacks))) {
555*663afb9bSAndroid Build Coastguard Worker 		LIST_REMOVE(cbent, next);
556*663afb9bSAndroid Build Coastguard Worker 		mm_free(cbent);
557*663afb9bSAndroid Build Coastguard Worker 	}
558*663afb9bSAndroid Build Coastguard Worker }
559*663afb9bSAndroid Build Coastguard Worker 
560*663afb9bSAndroid Build Coastguard Worker void
evbuffer_decref_and_unlock_(struct evbuffer * buffer)561*663afb9bSAndroid Build Coastguard Worker evbuffer_decref_and_unlock_(struct evbuffer *buffer)
562*663afb9bSAndroid Build Coastguard Worker {
563*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain, *next;
564*663afb9bSAndroid Build Coastguard Worker 	ASSERT_EVBUFFER_LOCKED(buffer);
565*663afb9bSAndroid Build Coastguard Worker 
566*663afb9bSAndroid Build Coastguard Worker 	EVUTIL_ASSERT(buffer->refcnt > 0);
567*663afb9bSAndroid Build Coastguard Worker 
568*663afb9bSAndroid Build Coastguard Worker 	if (--buffer->refcnt > 0) {
569*663afb9bSAndroid Build Coastguard Worker 		EVBUFFER_UNLOCK(buffer);
570*663afb9bSAndroid Build Coastguard Worker 		return;
571*663afb9bSAndroid Build Coastguard Worker 	}
572*663afb9bSAndroid Build Coastguard Worker 
573*663afb9bSAndroid Build Coastguard Worker 	for (chain = buffer->first; chain != NULL; chain = next) {
574*663afb9bSAndroid Build Coastguard Worker 		next = chain->next;
575*663afb9bSAndroid Build Coastguard Worker 		evbuffer_chain_free(chain);
576*663afb9bSAndroid Build Coastguard Worker 	}
577*663afb9bSAndroid Build Coastguard Worker 	evbuffer_remove_all_callbacks(buffer);
578*663afb9bSAndroid Build Coastguard Worker 	if (buffer->deferred_cbs)
579*663afb9bSAndroid Build Coastguard Worker 		event_deferred_cb_cancel_(buffer->cb_queue, &buffer->deferred);
580*663afb9bSAndroid Build Coastguard Worker 
581*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buffer);
582*663afb9bSAndroid Build Coastguard Worker 	if (buffer->own_lock)
583*663afb9bSAndroid Build Coastguard Worker 		EVTHREAD_FREE_LOCK(buffer->lock, EVTHREAD_LOCKTYPE_RECURSIVE);
584*663afb9bSAndroid Build Coastguard Worker 	mm_free(buffer);
585*663afb9bSAndroid Build Coastguard Worker }
586*663afb9bSAndroid Build Coastguard Worker 
587*663afb9bSAndroid Build Coastguard Worker void
evbuffer_free(struct evbuffer * buffer)588*663afb9bSAndroid Build Coastguard Worker evbuffer_free(struct evbuffer *buffer)
589*663afb9bSAndroid Build Coastguard Worker {
590*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buffer);
591*663afb9bSAndroid Build Coastguard Worker 	evbuffer_decref_and_unlock_(buffer);
592*663afb9bSAndroid Build Coastguard Worker }
593*663afb9bSAndroid Build Coastguard Worker 
594*663afb9bSAndroid Build Coastguard Worker void
evbuffer_lock(struct evbuffer * buf)595*663afb9bSAndroid Build Coastguard Worker evbuffer_lock(struct evbuffer *buf)
596*663afb9bSAndroid Build Coastguard Worker {
597*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buf);
598*663afb9bSAndroid Build Coastguard Worker }
599*663afb9bSAndroid Build Coastguard Worker 
600*663afb9bSAndroid Build Coastguard Worker void
evbuffer_unlock(struct evbuffer * buf)601*663afb9bSAndroid Build Coastguard Worker evbuffer_unlock(struct evbuffer *buf)
602*663afb9bSAndroid Build Coastguard Worker {
603*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buf);
604*663afb9bSAndroid Build Coastguard Worker }
605*663afb9bSAndroid Build Coastguard Worker 
606*663afb9bSAndroid Build Coastguard Worker size_t
evbuffer_get_length(const struct evbuffer * buffer)607*663afb9bSAndroid Build Coastguard Worker evbuffer_get_length(const struct evbuffer *buffer)
608*663afb9bSAndroid Build Coastguard Worker {
609*663afb9bSAndroid Build Coastguard Worker 	size_t result;
610*663afb9bSAndroid Build Coastguard Worker 
611*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buffer);
612*663afb9bSAndroid Build Coastguard Worker 
613*663afb9bSAndroid Build Coastguard Worker 	result = (buffer->total_len);
614*663afb9bSAndroid Build Coastguard Worker 
615*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buffer);
616*663afb9bSAndroid Build Coastguard Worker 
617*663afb9bSAndroid Build Coastguard Worker 	return result;
618*663afb9bSAndroid Build Coastguard Worker }
619*663afb9bSAndroid Build Coastguard Worker 
620*663afb9bSAndroid Build Coastguard Worker size_t
evbuffer_get_contiguous_space(const struct evbuffer * buf)621*663afb9bSAndroid Build Coastguard Worker evbuffer_get_contiguous_space(const struct evbuffer *buf)
622*663afb9bSAndroid Build Coastguard Worker {
623*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain;
624*663afb9bSAndroid Build Coastguard Worker 	size_t result;
625*663afb9bSAndroid Build Coastguard Worker 
626*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buf);
627*663afb9bSAndroid Build Coastguard Worker 	chain = buf->first;
628*663afb9bSAndroid Build Coastguard Worker 	result = (chain != NULL ? chain->off : 0);
629*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buf);
630*663afb9bSAndroid Build Coastguard Worker 
631*663afb9bSAndroid Build Coastguard Worker 	return result;
632*663afb9bSAndroid Build Coastguard Worker }
633*663afb9bSAndroid Build Coastguard Worker 
634*663afb9bSAndroid Build Coastguard Worker size_t
evbuffer_add_iovec(struct evbuffer * buf,struct evbuffer_iovec * vec,int n_vec)635*663afb9bSAndroid Build Coastguard Worker evbuffer_add_iovec(struct evbuffer * buf, struct evbuffer_iovec * vec, int n_vec) {
636*663afb9bSAndroid Build Coastguard Worker 	int n;
637*663afb9bSAndroid Build Coastguard Worker 	size_t res;
638*663afb9bSAndroid Build Coastguard Worker 	size_t to_alloc;
639*663afb9bSAndroid Build Coastguard Worker 
640*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buf);
641*663afb9bSAndroid Build Coastguard Worker 
642*663afb9bSAndroid Build Coastguard Worker 	res = to_alloc = 0;
643*663afb9bSAndroid Build Coastguard Worker 
644*663afb9bSAndroid Build Coastguard Worker 	for (n = 0; n < n_vec; n++) {
645*663afb9bSAndroid Build Coastguard Worker 		to_alloc += vec[n].iov_len;
646*663afb9bSAndroid Build Coastguard Worker 	}
647*663afb9bSAndroid Build Coastguard Worker 
648*663afb9bSAndroid Build Coastguard Worker 	if (evbuffer_expand_fast_(buf, to_alloc, 2) < 0) {
649*663afb9bSAndroid Build Coastguard Worker 		goto done;
650*663afb9bSAndroid Build Coastguard Worker 	}
651*663afb9bSAndroid Build Coastguard Worker 
652*663afb9bSAndroid Build Coastguard Worker 	for (n = 0; n < n_vec; n++) {
653*663afb9bSAndroid Build Coastguard Worker 		/* XXX each 'add' call here does a bunch of setup that's
654*663afb9bSAndroid Build Coastguard Worker 		 * obviated by evbuffer_expand_fast_, and some cleanup that we
655*663afb9bSAndroid Build Coastguard Worker 		 * would like to do only once.  Instead we should just extract
656*663afb9bSAndroid Build Coastguard Worker 		 * the part of the code that's needed. */
657*663afb9bSAndroid Build Coastguard Worker 
658*663afb9bSAndroid Build Coastguard Worker 		if (evbuffer_add(buf, vec[n].iov_base, vec[n].iov_len) < 0) {
659*663afb9bSAndroid Build Coastguard Worker 			goto done;
660*663afb9bSAndroid Build Coastguard Worker 		}
661*663afb9bSAndroid Build Coastguard Worker 
662*663afb9bSAndroid Build Coastguard Worker 		res += vec[n].iov_len;
663*663afb9bSAndroid Build Coastguard Worker 	}
664*663afb9bSAndroid Build Coastguard Worker 
665*663afb9bSAndroid Build Coastguard Worker done:
666*663afb9bSAndroid Build Coastguard Worker     EVBUFFER_UNLOCK(buf);
667*663afb9bSAndroid Build Coastguard Worker     return res;
668*663afb9bSAndroid Build Coastguard Worker }
669*663afb9bSAndroid Build Coastguard Worker 
670*663afb9bSAndroid Build Coastguard Worker int
evbuffer_reserve_space(struct evbuffer * buf,ev_ssize_t size,struct evbuffer_iovec * vec,int n_vecs)671*663afb9bSAndroid Build Coastguard Worker evbuffer_reserve_space(struct evbuffer *buf, ev_ssize_t size,
672*663afb9bSAndroid Build Coastguard Worker     struct evbuffer_iovec *vec, int n_vecs)
673*663afb9bSAndroid Build Coastguard Worker {
674*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain, **chainp;
675*663afb9bSAndroid Build Coastguard Worker 	int n = -1;
676*663afb9bSAndroid Build Coastguard Worker 
677*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buf);
678*663afb9bSAndroid Build Coastguard Worker 	if (buf->freeze_end)
679*663afb9bSAndroid Build Coastguard Worker 		goto done;
680*663afb9bSAndroid Build Coastguard Worker 	if (n_vecs < 1)
681*663afb9bSAndroid Build Coastguard Worker 		goto done;
682*663afb9bSAndroid Build Coastguard Worker 	if (n_vecs == 1) {
683*663afb9bSAndroid Build Coastguard Worker 		if ((chain = evbuffer_expand_singlechain(buf, size)) == NULL)
684*663afb9bSAndroid Build Coastguard Worker 			goto done;
685*663afb9bSAndroid Build Coastguard Worker 
686*663afb9bSAndroid Build Coastguard Worker 		vec[0].iov_base = (void *)CHAIN_SPACE_PTR(chain);
687*663afb9bSAndroid Build Coastguard Worker 		vec[0].iov_len = (size_t)CHAIN_SPACE_LEN(chain);
688*663afb9bSAndroid Build Coastguard Worker 		EVUTIL_ASSERT(size<0 || (size_t)vec[0].iov_len >= (size_t)size);
689*663afb9bSAndroid Build Coastguard Worker 		n = 1;
690*663afb9bSAndroid Build Coastguard Worker 	} else {
691*663afb9bSAndroid Build Coastguard Worker 		if (evbuffer_expand_fast_(buf, size, n_vecs)<0)
692*663afb9bSAndroid Build Coastguard Worker 			goto done;
693*663afb9bSAndroid Build Coastguard Worker 		n = evbuffer_read_setup_vecs_(buf, size, vec, n_vecs,
694*663afb9bSAndroid Build Coastguard Worker 				&chainp, 0);
695*663afb9bSAndroid Build Coastguard Worker 	}
696*663afb9bSAndroid Build Coastguard Worker 
697*663afb9bSAndroid Build Coastguard Worker done:
698*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buf);
699*663afb9bSAndroid Build Coastguard Worker 	return n;
700*663afb9bSAndroid Build Coastguard Worker 
701*663afb9bSAndroid Build Coastguard Worker }
702*663afb9bSAndroid Build Coastguard Worker 
703*663afb9bSAndroid Build Coastguard Worker static int
advance_last_with_data(struct evbuffer * buf)704*663afb9bSAndroid Build Coastguard Worker advance_last_with_data(struct evbuffer *buf)
705*663afb9bSAndroid Build Coastguard Worker {
706*663afb9bSAndroid Build Coastguard Worker 	int n = 0;
707*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain **chainp = buf->last_with_datap;
708*663afb9bSAndroid Build Coastguard Worker 
709*663afb9bSAndroid Build Coastguard Worker 	ASSERT_EVBUFFER_LOCKED(buf);
710*663afb9bSAndroid Build Coastguard Worker 
711*663afb9bSAndroid Build Coastguard Worker 	if (!*chainp)
712*663afb9bSAndroid Build Coastguard Worker 		return 0;
713*663afb9bSAndroid Build Coastguard Worker 
714*663afb9bSAndroid Build Coastguard Worker 	while ((*chainp)->next) {
715*663afb9bSAndroid Build Coastguard Worker 		chainp = &(*chainp)->next;
716*663afb9bSAndroid Build Coastguard Worker 		if ((*chainp)->off)
717*663afb9bSAndroid Build Coastguard Worker 			buf->last_with_datap = chainp;
718*663afb9bSAndroid Build Coastguard Worker 		++n;
719*663afb9bSAndroid Build Coastguard Worker 	}
720*663afb9bSAndroid Build Coastguard Worker 	return n;
721*663afb9bSAndroid Build Coastguard Worker }
722*663afb9bSAndroid Build Coastguard Worker 
723*663afb9bSAndroid Build Coastguard Worker int
evbuffer_commit_space(struct evbuffer * buf,struct evbuffer_iovec * vec,int n_vecs)724*663afb9bSAndroid Build Coastguard Worker evbuffer_commit_space(struct evbuffer *buf,
725*663afb9bSAndroid Build Coastguard Worker     struct evbuffer_iovec *vec, int n_vecs)
726*663afb9bSAndroid Build Coastguard Worker {
727*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain, **firstchainp, **chainp;
728*663afb9bSAndroid Build Coastguard Worker 	int result = -1;
729*663afb9bSAndroid Build Coastguard Worker 	size_t added = 0;
730*663afb9bSAndroid Build Coastguard Worker 	int i;
731*663afb9bSAndroid Build Coastguard Worker 
732*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buf);
733*663afb9bSAndroid Build Coastguard Worker 
734*663afb9bSAndroid Build Coastguard Worker 	if (buf->freeze_end)
735*663afb9bSAndroid Build Coastguard Worker 		goto done;
736*663afb9bSAndroid Build Coastguard Worker 	if (n_vecs == 0) {
737*663afb9bSAndroid Build Coastguard Worker 		result = 0;
738*663afb9bSAndroid Build Coastguard Worker 		goto done;
739*663afb9bSAndroid Build Coastguard Worker 	} else if (n_vecs == 1 &&
740*663afb9bSAndroid Build Coastguard Worker 	    (buf->last && vec[0].iov_base == (void *)CHAIN_SPACE_PTR(buf->last))) {
741*663afb9bSAndroid Build Coastguard Worker 		/* The user only got or used one chain; it might not
742*663afb9bSAndroid Build Coastguard Worker 		 * be the first one with space in it. */
743*663afb9bSAndroid Build Coastguard Worker 		if ((size_t)vec[0].iov_len > (size_t)CHAIN_SPACE_LEN(buf->last))
744*663afb9bSAndroid Build Coastguard Worker 			goto done;
745*663afb9bSAndroid Build Coastguard Worker 		buf->last->off += vec[0].iov_len;
746*663afb9bSAndroid Build Coastguard Worker 		added = vec[0].iov_len;
747*663afb9bSAndroid Build Coastguard Worker 		if (added)
748*663afb9bSAndroid Build Coastguard Worker 			advance_last_with_data(buf);
749*663afb9bSAndroid Build Coastguard Worker 		goto okay;
750*663afb9bSAndroid Build Coastguard Worker 	}
751*663afb9bSAndroid Build Coastguard Worker 
752*663afb9bSAndroid Build Coastguard Worker 	/* Advance 'firstchain' to the first chain with space in it. */
753*663afb9bSAndroid Build Coastguard Worker 	firstchainp = buf->last_with_datap;
754*663afb9bSAndroid Build Coastguard Worker 	if (!*firstchainp)
755*663afb9bSAndroid Build Coastguard Worker 		goto done;
756*663afb9bSAndroid Build Coastguard Worker 	if (CHAIN_SPACE_LEN(*firstchainp) == 0) {
757*663afb9bSAndroid Build Coastguard Worker 		firstchainp = &(*firstchainp)->next;
758*663afb9bSAndroid Build Coastguard Worker 	}
759*663afb9bSAndroid Build Coastguard Worker 
760*663afb9bSAndroid Build Coastguard Worker 	chain = *firstchainp;
761*663afb9bSAndroid Build Coastguard Worker 	/* pass 1: make sure that the pointers and lengths of vecs[] are in
762*663afb9bSAndroid Build Coastguard Worker 	 * bounds before we try to commit anything. */
763*663afb9bSAndroid Build Coastguard Worker 	for (i=0; i<n_vecs; ++i) {
764*663afb9bSAndroid Build Coastguard Worker 		if (!chain)
765*663afb9bSAndroid Build Coastguard Worker 			goto done;
766*663afb9bSAndroid Build Coastguard Worker 		if (vec[i].iov_base != (void *)CHAIN_SPACE_PTR(chain) ||
767*663afb9bSAndroid Build Coastguard Worker 		    (size_t)vec[i].iov_len > CHAIN_SPACE_LEN(chain))
768*663afb9bSAndroid Build Coastguard Worker 			goto done;
769*663afb9bSAndroid Build Coastguard Worker 		chain = chain->next;
770*663afb9bSAndroid Build Coastguard Worker 	}
771*663afb9bSAndroid Build Coastguard Worker 	/* pass 2: actually adjust all the chains. */
772*663afb9bSAndroid Build Coastguard Worker 	chainp = firstchainp;
773*663afb9bSAndroid Build Coastguard Worker 	for (i=0; i<n_vecs; ++i) {
774*663afb9bSAndroid Build Coastguard Worker 		(*chainp)->off += vec[i].iov_len;
775*663afb9bSAndroid Build Coastguard Worker 		added += vec[i].iov_len;
776*663afb9bSAndroid Build Coastguard Worker 		if (vec[i].iov_len) {
777*663afb9bSAndroid Build Coastguard Worker 			buf->last_with_datap = chainp;
778*663afb9bSAndroid Build Coastguard Worker 		}
779*663afb9bSAndroid Build Coastguard Worker 		chainp = &(*chainp)->next;
780*663afb9bSAndroid Build Coastguard Worker 	}
781*663afb9bSAndroid Build Coastguard Worker 
782*663afb9bSAndroid Build Coastguard Worker okay:
783*663afb9bSAndroid Build Coastguard Worker 	buf->total_len += added;
784*663afb9bSAndroid Build Coastguard Worker 	buf->n_add_for_cb += added;
785*663afb9bSAndroid Build Coastguard Worker 	result = 0;
786*663afb9bSAndroid Build Coastguard Worker 	evbuffer_invoke_callbacks_(buf);
787*663afb9bSAndroid Build Coastguard Worker 
788*663afb9bSAndroid Build Coastguard Worker done:
789*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buf);
790*663afb9bSAndroid Build Coastguard Worker 	return result;
791*663afb9bSAndroid Build Coastguard Worker }
792*663afb9bSAndroid Build Coastguard Worker 
793*663afb9bSAndroid Build Coastguard Worker static inline int
HAS_PINNED_R(struct evbuffer * buf)794*663afb9bSAndroid Build Coastguard Worker HAS_PINNED_R(struct evbuffer *buf)
795*663afb9bSAndroid Build Coastguard Worker {
796*663afb9bSAndroid Build Coastguard Worker 	return (buf->last && CHAIN_PINNED_R(buf->last));
797*663afb9bSAndroid Build Coastguard Worker }
798*663afb9bSAndroid Build Coastguard Worker 
799*663afb9bSAndroid Build Coastguard Worker static inline void
ZERO_CHAIN(struct evbuffer * dst)800*663afb9bSAndroid Build Coastguard Worker ZERO_CHAIN(struct evbuffer *dst)
801*663afb9bSAndroid Build Coastguard Worker {
802*663afb9bSAndroid Build Coastguard Worker 	ASSERT_EVBUFFER_LOCKED(dst);
803*663afb9bSAndroid Build Coastguard Worker 	dst->first = NULL;
804*663afb9bSAndroid Build Coastguard Worker 	dst->last = NULL;
805*663afb9bSAndroid Build Coastguard Worker 	dst->last_with_datap = &(dst)->first;
806*663afb9bSAndroid Build Coastguard Worker 	dst->total_len = 0;
807*663afb9bSAndroid Build Coastguard Worker }
808*663afb9bSAndroid Build Coastguard Worker 
809*663afb9bSAndroid Build Coastguard Worker /* Prepares the contents of src to be moved to another buffer by removing
810*663afb9bSAndroid Build Coastguard Worker  * read-pinned chains. The first pinned chain is saved in first, and the
811*663afb9bSAndroid Build Coastguard Worker  * last in last. If src has no read-pinned chains, first and last are set
812*663afb9bSAndroid Build Coastguard Worker  * to NULL. */
813*663afb9bSAndroid Build Coastguard Worker static int
PRESERVE_PINNED(struct evbuffer * src,struct evbuffer_chain ** first,struct evbuffer_chain ** last)814*663afb9bSAndroid Build Coastguard Worker PRESERVE_PINNED(struct evbuffer *src, struct evbuffer_chain **first,
815*663afb9bSAndroid Build Coastguard Worker 		struct evbuffer_chain **last)
816*663afb9bSAndroid Build Coastguard Worker {
817*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain, **pinned;
818*663afb9bSAndroid Build Coastguard Worker 
819*663afb9bSAndroid Build Coastguard Worker 	ASSERT_EVBUFFER_LOCKED(src);
820*663afb9bSAndroid Build Coastguard Worker 
821*663afb9bSAndroid Build Coastguard Worker 	if (!HAS_PINNED_R(src)) {
822*663afb9bSAndroid Build Coastguard Worker 		*first = *last = NULL;
823*663afb9bSAndroid Build Coastguard Worker 		return 0;
824*663afb9bSAndroid Build Coastguard Worker 	}
825*663afb9bSAndroid Build Coastguard Worker 
826*663afb9bSAndroid Build Coastguard Worker 	pinned = src->last_with_datap;
827*663afb9bSAndroid Build Coastguard Worker 	if (!CHAIN_PINNED_R(*pinned))
828*663afb9bSAndroid Build Coastguard Worker 		pinned = &(*pinned)->next;
829*663afb9bSAndroid Build Coastguard Worker 	EVUTIL_ASSERT(CHAIN_PINNED_R(*pinned));
830*663afb9bSAndroid Build Coastguard Worker 	chain = *first = *pinned;
831*663afb9bSAndroid Build Coastguard Worker 	*last = src->last;
832*663afb9bSAndroid Build Coastguard Worker 
833*663afb9bSAndroid Build Coastguard Worker 	/* If there's data in the first pinned chain, we need to allocate
834*663afb9bSAndroid Build Coastguard Worker 	 * a new chain and copy the data over. */
835*663afb9bSAndroid Build Coastguard Worker 	if (chain->off) {
836*663afb9bSAndroid Build Coastguard Worker 		struct evbuffer_chain *tmp;
837*663afb9bSAndroid Build Coastguard Worker 
838*663afb9bSAndroid Build Coastguard Worker 		EVUTIL_ASSERT(pinned == src->last_with_datap);
839*663afb9bSAndroid Build Coastguard Worker 		tmp = evbuffer_chain_new(chain->off);
840*663afb9bSAndroid Build Coastguard Worker 		if (!tmp)
841*663afb9bSAndroid Build Coastguard Worker 			return -1;
842*663afb9bSAndroid Build Coastguard Worker 		memcpy(tmp->buffer, chain->buffer + chain->misalign,
843*663afb9bSAndroid Build Coastguard Worker 			chain->off);
844*663afb9bSAndroid Build Coastguard Worker 		tmp->off = chain->off;
845*663afb9bSAndroid Build Coastguard Worker 		*src->last_with_datap = tmp;
846*663afb9bSAndroid Build Coastguard Worker 		src->last = tmp;
847*663afb9bSAndroid Build Coastguard Worker 		chain->misalign += chain->off;
848*663afb9bSAndroid Build Coastguard Worker 		chain->off = 0;
849*663afb9bSAndroid Build Coastguard Worker 	} else {
850*663afb9bSAndroid Build Coastguard Worker 		src->last = *src->last_with_datap;
851*663afb9bSAndroid Build Coastguard Worker 		*pinned = NULL;
852*663afb9bSAndroid Build Coastguard Worker 	}
853*663afb9bSAndroid Build Coastguard Worker 
854*663afb9bSAndroid Build Coastguard Worker 	return 0;
855*663afb9bSAndroid Build Coastguard Worker }
856*663afb9bSAndroid Build Coastguard Worker 
857*663afb9bSAndroid Build Coastguard Worker static inline void
RESTORE_PINNED(struct evbuffer * src,struct evbuffer_chain * pinned,struct evbuffer_chain * last)858*663afb9bSAndroid Build Coastguard Worker RESTORE_PINNED(struct evbuffer *src, struct evbuffer_chain *pinned,
859*663afb9bSAndroid Build Coastguard Worker 		struct evbuffer_chain *last)
860*663afb9bSAndroid Build Coastguard Worker {
861*663afb9bSAndroid Build Coastguard Worker 	ASSERT_EVBUFFER_LOCKED(src);
862*663afb9bSAndroid Build Coastguard Worker 
863*663afb9bSAndroid Build Coastguard Worker 	if (!pinned) {
864*663afb9bSAndroid Build Coastguard Worker 		ZERO_CHAIN(src);
865*663afb9bSAndroid Build Coastguard Worker 		return;
866*663afb9bSAndroid Build Coastguard Worker 	}
867*663afb9bSAndroid Build Coastguard Worker 
868*663afb9bSAndroid Build Coastguard Worker 	src->first = pinned;
869*663afb9bSAndroid Build Coastguard Worker 	src->last = last;
870*663afb9bSAndroid Build Coastguard Worker 	src->last_with_datap = &src->first;
871*663afb9bSAndroid Build Coastguard Worker 	src->total_len = 0;
872*663afb9bSAndroid Build Coastguard Worker }
873*663afb9bSAndroid Build Coastguard Worker 
874*663afb9bSAndroid Build Coastguard Worker static inline void
COPY_CHAIN(struct evbuffer * dst,struct evbuffer * src)875*663afb9bSAndroid Build Coastguard Worker COPY_CHAIN(struct evbuffer *dst, struct evbuffer *src)
876*663afb9bSAndroid Build Coastguard Worker {
877*663afb9bSAndroid Build Coastguard Worker 	ASSERT_EVBUFFER_LOCKED(dst);
878*663afb9bSAndroid Build Coastguard Worker 	ASSERT_EVBUFFER_LOCKED(src);
879*663afb9bSAndroid Build Coastguard Worker 	dst->first = src->first;
880*663afb9bSAndroid Build Coastguard Worker 	if (src->last_with_datap == &src->first)
881*663afb9bSAndroid Build Coastguard Worker 		dst->last_with_datap = &dst->first;
882*663afb9bSAndroid Build Coastguard Worker 	else
883*663afb9bSAndroid Build Coastguard Worker 		dst->last_with_datap = src->last_with_datap;
884*663afb9bSAndroid Build Coastguard Worker 	dst->last = src->last;
885*663afb9bSAndroid Build Coastguard Worker 	dst->total_len = src->total_len;
886*663afb9bSAndroid Build Coastguard Worker }
887*663afb9bSAndroid Build Coastguard Worker 
888*663afb9bSAndroid Build Coastguard Worker static void
APPEND_CHAIN(struct evbuffer * dst,struct evbuffer * src)889*663afb9bSAndroid Build Coastguard Worker APPEND_CHAIN(struct evbuffer *dst, struct evbuffer *src)
890*663afb9bSAndroid Build Coastguard Worker {
891*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain **chp;
892*663afb9bSAndroid Build Coastguard Worker 
893*663afb9bSAndroid Build Coastguard Worker 	ASSERT_EVBUFFER_LOCKED(dst);
894*663afb9bSAndroid Build Coastguard Worker 	ASSERT_EVBUFFER_LOCKED(src);
895*663afb9bSAndroid Build Coastguard Worker 
896*663afb9bSAndroid Build Coastguard Worker 	chp = evbuffer_free_trailing_empty_chains(dst);
897*663afb9bSAndroid Build Coastguard Worker 	*chp = src->first;
898*663afb9bSAndroid Build Coastguard Worker 
899*663afb9bSAndroid Build Coastguard Worker 	if (src->last_with_datap == &src->first)
900*663afb9bSAndroid Build Coastguard Worker 		dst->last_with_datap = chp;
901*663afb9bSAndroid Build Coastguard Worker 	else
902*663afb9bSAndroid Build Coastguard Worker 		dst->last_with_datap = src->last_with_datap;
903*663afb9bSAndroid Build Coastguard Worker 	dst->last = src->last;
904*663afb9bSAndroid Build Coastguard Worker 	dst->total_len += src->total_len;
905*663afb9bSAndroid Build Coastguard Worker }
906*663afb9bSAndroid Build Coastguard Worker 
907*663afb9bSAndroid Build Coastguard Worker static inline void
APPEND_CHAIN_MULTICAST(struct evbuffer * dst,struct evbuffer * src)908*663afb9bSAndroid Build Coastguard Worker APPEND_CHAIN_MULTICAST(struct evbuffer *dst, struct evbuffer *src)
909*663afb9bSAndroid Build Coastguard Worker {
910*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *tmp;
911*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain = src->first;
912*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_multicast_parent *extra;
913*663afb9bSAndroid Build Coastguard Worker 
914*663afb9bSAndroid Build Coastguard Worker 	ASSERT_EVBUFFER_LOCKED(dst);
915*663afb9bSAndroid Build Coastguard Worker 	ASSERT_EVBUFFER_LOCKED(src);
916*663afb9bSAndroid Build Coastguard Worker 
917*663afb9bSAndroid Build Coastguard Worker 	for (; chain; chain = chain->next) {
918*663afb9bSAndroid Build Coastguard Worker 		if (!chain->off || chain->flags & EVBUFFER_DANGLING) {
919*663afb9bSAndroid Build Coastguard Worker 			/* skip empty chains */
920*663afb9bSAndroid Build Coastguard Worker 			continue;
921*663afb9bSAndroid Build Coastguard Worker 		}
922*663afb9bSAndroid Build Coastguard Worker 
923*663afb9bSAndroid Build Coastguard Worker 		tmp = evbuffer_chain_new(sizeof(struct evbuffer_multicast_parent));
924*663afb9bSAndroid Build Coastguard Worker 		if (!tmp) {
925*663afb9bSAndroid Build Coastguard Worker 			event_warn("%s: out of memory", __func__);
926*663afb9bSAndroid Build Coastguard Worker 			return;
927*663afb9bSAndroid Build Coastguard Worker 		}
928*663afb9bSAndroid Build Coastguard Worker 		extra = EVBUFFER_CHAIN_EXTRA(struct evbuffer_multicast_parent, tmp);
929*663afb9bSAndroid Build Coastguard Worker 		/* reference evbuffer containing source chain so it
930*663afb9bSAndroid Build Coastguard Worker 		 * doesn't get released while the chain is still
931*663afb9bSAndroid Build Coastguard Worker 		 * being referenced to */
932*663afb9bSAndroid Build Coastguard Worker 		evbuffer_incref_(src);
933*663afb9bSAndroid Build Coastguard Worker 		extra->source = src;
934*663afb9bSAndroid Build Coastguard Worker 		/* reference source chain which now becomes immutable */
935*663afb9bSAndroid Build Coastguard Worker 		evbuffer_chain_incref(chain);
936*663afb9bSAndroid Build Coastguard Worker 		extra->parent = chain;
937*663afb9bSAndroid Build Coastguard Worker 		chain->flags |= EVBUFFER_IMMUTABLE;
938*663afb9bSAndroid Build Coastguard Worker 		tmp->buffer_len = chain->buffer_len;
939*663afb9bSAndroid Build Coastguard Worker 		tmp->misalign = chain->misalign;
940*663afb9bSAndroid Build Coastguard Worker 		tmp->off = chain->off;
941*663afb9bSAndroid Build Coastguard Worker 		tmp->flags |= EVBUFFER_MULTICAST|EVBUFFER_IMMUTABLE;
942*663afb9bSAndroid Build Coastguard Worker 		tmp->buffer = chain->buffer;
943*663afb9bSAndroid Build Coastguard Worker 		evbuffer_chain_insert(dst, tmp);
944*663afb9bSAndroid Build Coastguard Worker 	}
945*663afb9bSAndroid Build Coastguard Worker }
946*663afb9bSAndroid Build Coastguard Worker 
947*663afb9bSAndroid Build Coastguard Worker static void
PREPEND_CHAIN(struct evbuffer * dst,struct evbuffer * src)948*663afb9bSAndroid Build Coastguard Worker PREPEND_CHAIN(struct evbuffer *dst, struct evbuffer *src)
949*663afb9bSAndroid Build Coastguard Worker {
950*663afb9bSAndroid Build Coastguard Worker 	ASSERT_EVBUFFER_LOCKED(dst);
951*663afb9bSAndroid Build Coastguard Worker 	ASSERT_EVBUFFER_LOCKED(src);
952*663afb9bSAndroid Build Coastguard Worker 	src->last->next = dst->first;
953*663afb9bSAndroid Build Coastguard Worker 	dst->first = src->first;
954*663afb9bSAndroid Build Coastguard Worker 	dst->total_len += src->total_len;
955*663afb9bSAndroid Build Coastguard Worker 	if (*dst->last_with_datap == NULL) {
956*663afb9bSAndroid Build Coastguard Worker 		if (src->last_with_datap == &(src)->first)
957*663afb9bSAndroid Build Coastguard Worker 			dst->last_with_datap = &dst->first;
958*663afb9bSAndroid Build Coastguard Worker 		else
959*663afb9bSAndroid Build Coastguard Worker 			dst->last_with_datap = src->last_with_datap;
960*663afb9bSAndroid Build Coastguard Worker 	} else if (dst->last_with_datap == &dst->first) {
961*663afb9bSAndroid Build Coastguard Worker 		dst->last_with_datap = &src->last->next;
962*663afb9bSAndroid Build Coastguard Worker 	}
963*663afb9bSAndroid Build Coastguard Worker }
964*663afb9bSAndroid Build Coastguard Worker 
965*663afb9bSAndroid Build Coastguard Worker int
evbuffer_add_buffer(struct evbuffer * outbuf,struct evbuffer * inbuf)966*663afb9bSAndroid Build Coastguard Worker evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf)
967*663afb9bSAndroid Build Coastguard Worker {
968*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *pinned, *last;
969*663afb9bSAndroid Build Coastguard Worker 	size_t in_total_len, out_total_len;
970*663afb9bSAndroid Build Coastguard Worker 	int result = 0;
971*663afb9bSAndroid Build Coastguard Worker 
972*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK2(inbuf, outbuf);
973*663afb9bSAndroid Build Coastguard Worker 	in_total_len = inbuf->total_len;
974*663afb9bSAndroid Build Coastguard Worker 	out_total_len = outbuf->total_len;
975*663afb9bSAndroid Build Coastguard Worker 
976*663afb9bSAndroid Build Coastguard Worker 	if (in_total_len == 0 || outbuf == inbuf)
977*663afb9bSAndroid Build Coastguard Worker 		goto done;
978*663afb9bSAndroid Build Coastguard Worker 
979*663afb9bSAndroid Build Coastguard Worker 	if (outbuf->freeze_end || inbuf->freeze_start) {
980*663afb9bSAndroid Build Coastguard Worker 		result = -1;
981*663afb9bSAndroid Build Coastguard Worker 		goto done;
982*663afb9bSAndroid Build Coastguard Worker 	}
983*663afb9bSAndroid Build Coastguard Worker 
984*663afb9bSAndroid Build Coastguard Worker 	if (PRESERVE_PINNED(inbuf, &pinned, &last) < 0) {
985*663afb9bSAndroid Build Coastguard Worker 		result = -1;
986*663afb9bSAndroid Build Coastguard Worker 		goto done;
987*663afb9bSAndroid Build Coastguard Worker 	}
988*663afb9bSAndroid Build Coastguard Worker 
989*663afb9bSAndroid Build Coastguard Worker 	if (out_total_len == 0) {
990*663afb9bSAndroid Build Coastguard Worker 		/* There might be an empty chain at the start of outbuf; free
991*663afb9bSAndroid Build Coastguard Worker 		 * it. */
992*663afb9bSAndroid Build Coastguard Worker 		evbuffer_free_all_chains(outbuf->first);
993*663afb9bSAndroid Build Coastguard Worker 		COPY_CHAIN(outbuf, inbuf);
994*663afb9bSAndroid Build Coastguard Worker 	} else {
995*663afb9bSAndroid Build Coastguard Worker 		APPEND_CHAIN(outbuf, inbuf);
996*663afb9bSAndroid Build Coastguard Worker 	}
997*663afb9bSAndroid Build Coastguard Worker 
998*663afb9bSAndroid Build Coastguard Worker 	RESTORE_PINNED(inbuf, pinned, last);
999*663afb9bSAndroid Build Coastguard Worker 
1000*663afb9bSAndroid Build Coastguard Worker 	inbuf->n_del_for_cb += in_total_len;
1001*663afb9bSAndroid Build Coastguard Worker 	outbuf->n_add_for_cb += in_total_len;
1002*663afb9bSAndroid Build Coastguard Worker 
1003*663afb9bSAndroid Build Coastguard Worker 	evbuffer_invoke_callbacks_(inbuf);
1004*663afb9bSAndroid Build Coastguard Worker 	evbuffer_invoke_callbacks_(outbuf);
1005*663afb9bSAndroid Build Coastguard Worker 
1006*663afb9bSAndroid Build Coastguard Worker done:
1007*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK2(inbuf, outbuf);
1008*663afb9bSAndroid Build Coastguard Worker 	return result;
1009*663afb9bSAndroid Build Coastguard Worker }
1010*663afb9bSAndroid Build Coastguard Worker 
1011*663afb9bSAndroid Build Coastguard Worker int
evbuffer_add_buffer_reference(struct evbuffer * outbuf,struct evbuffer * inbuf)1012*663afb9bSAndroid Build Coastguard Worker evbuffer_add_buffer_reference(struct evbuffer *outbuf, struct evbuffer *inbuf)
1013*663afb9bSAndroid Build Coastguard Worker {
1014*663afb9bSAndroid Build Coastguard Worker 	size_t in_total_len, out_total_len;
1015*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain;
1016*663afb9bSAndroid Build Coastguard Worker 	int result = 0;
1017*663afb9bSAndroid Build Coastguard Worker 
1018*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK2(inbuf, outbuf);
1019*663afb9bSAndroid Build Coastguard Worker 	in_total_len = inbuf->total_len;
1020*663afb9bSAndroid Build Coastguard Worker 	out_total_len = outbuf->total_len;
1021*663afb9bSAndroid Build Coastguard Worker 	chain = inbuf->first;
1022*663afb9bSAndroid Build Coastguard Worker 
1023*663afb9bSAndroid Build Coastguard Worker 	if (in_total_len == 0)
1024*663afb9bSAndroid Build Coastguard Worker 		goto done;
1025*663afb9bSAndroid Build Coastguard Worker 
1026*663afb9bSAndroid Build Coastguard Worker 	if (outbuf->freeze_end || outbuf == inbuf) {
1027*663afb9bSAndroid Build Coastguard Worker 		result = -1;
1028*663afb9bSAndroid Build Coastguard Worker 		goto done;
1029*663afb9bSAndroid Build Coastguard Worker 	}
1030*663afb9bSAndroid Build Coastguard Worker 
1031*663afb9bSAndroid Build Coastguard Worker 	for (; chain; chain = chain->next) {
1032*663afb9bSAndroid Build Coastguard Worker 		if ((chain->flags & (EVBUFFER_FILESEGMENT|EVBUFFER_SENDFILE|EVBUFFER_MULTICAST)) != 0) {
1033*663afb9bSAndroid Build Coastguard Worker 			/* chain type can not be referenced */
1034*663afb9bSAndroid Build Coastguard Worker 			result = -1;
1035*663afb9bSAndroid Build Coastguard Worker 			goto done;
1036*663afb9bSAndroid Build Coastguard Worker 		}
1037*663afb9bSAndroid Build Coastguard Worker 	}
1038*663afb9bSAndroid Build Coastguard Worker 
1039*663afb9bSAndroid Build Coastguard Worker 	if (out_total_len == 0) {
1040*663afb9bSAndroid Build Coastguard Worker 		/* There might be an empty chain at the start of outbuf; free
1041*663afb9bSAndroid Build Coastguard Worker 		 * it. */
1042*663afb9bSAndroid Build Coastguard Worker 		evbuffer_free_all_chains(outbuf->first);
1043*663afb9bSAndroid Build Coastguard Worker 	}
1044*663afb9bSAndroid Build Coastguard Worker 	APPEND_CHAIN_MULTICAST(outbuf, inbuf);
1045*663afb9bSAndroid Build Coastguard Worker 
1046*663afb9bSAndroid Build Coastguard Worker 	outbuf->n_add_for_cb += in_total_len;
1047*663afb9bSAndroid Build Coastguard Worker 	evbuffer_invoke_callbacks_(outbuf);
1048*663afb9bSAndroid Build Coastguard Worker 
1049*663afb9bSAndroid Build Coastguard Worker done:
1050*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK2(inbuf, outbuf);
1051*663afb9bSAndroid Build Coastguard Worker 	return result;
1052*663afb9bSAndroid Build Coastguard Worker }
1053*663afb9bSAndroid Build Coastguard Worker 
1054*663afb9bSAndroid Build Coastguard Worker int
evbuffer_prepend_buffer(struct evbuffer * outbuf,struct evbuffer * inbuf)1055*663afb9bSAndroid Build Coastguard Worker evbuffer_prepend_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf)
1056*663afb9bSAndroid Build Coastguard Worker {
1057*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *pinned, *last;
1058*663afb9bSAndroid Build Coastguard Worker 	size_t in_total_len, out_total_len;
1059*663afb9bSAndroid Build Coastguard Worker 	int result = 0;
1060*663afb9bSAndroid Build Coastguard Worker 
1061*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK2(inbuf, outbuf);
1062*663afb9bSAndroid Build Coastguard Worker 
1063*663afb9bSAndroid Build Coastguard Worker 	in_total_len = inbuf->total_len;
1064*663afb9bSAndroid Build Coastguard Worker 	out_total_len = outbuf->total_len;
1065*663afb9bSAndroid Build Coastguard Worker 
1066*663afb9bSAndroid Build Coastguard Worker 	if (!in_total_len || inbuf == outbuf)
1067*663afb9bSAndroid Build Coastguard Worker 		goto done;
1068*663afb9bSAndroid Build Coastguard Worker 
1069*663afb9bSAndroid Build Coastguard Worker 	if (outbuf->freeze_start || inbuf->freeze_start) {
1070*663afb9bSAndroid Build Coastguard Worker 		result = -1;
1071*663afb9bSAndroid Build Coastguard Worker 		goto done;
1072*663afb9bSAndroid Build Coastguard Worker 	}
1073*663afb9bSAndroid Build Coastguard Worker 
1074*663afb9bSAndroid Build Coastguard Worker 	if (PRESERVE_PINNED(inbuf, &pinned, &last) < 0) {
1075*663afb9bSAndroid Build Coastguard Worker 		result = -1;
1076*663afb9bSAndroid Build Coastguard Worker 		goto done;
1077*663afb9bSAndroid Build Coastguard Worker 	}
1078*663afb9bSAndroid Build Coastguard Worker 
1079*663afb9bSAndroid Build Coastguard Worker 	if (out_total_len == 0) {
1080*663afb9bSAndroid Build Coastguard Worker 		/* There might be an empty chain at the start of outbuf; free
1081*663afb9bSAndroid Build Coastguard Worker 		 * it. */
1082*663afb9bSAndroid Build Coastguard Worker 		evbuffer_free_all_chains(outbuf->first);
1083*663afb9bSAndroid Build Coastguard Worker 		COPY_CHAIN(outbuf, inbuf);
1084*663afb9bSAndroid Build Coastguard Worker 	} else {
1085*663afb9bSAndroid Build Coastguard Worker 		PREPEND_CHAIN(outbuf, inbuf);
1086*663afb9bSAndroid Build Coastguard Worker 	}
1087*663afb9bSAndroid Build Coastguard Worker 
1088*663afb9bSAndroid Build Coastguard Worker 	RESTORE_PINNED(inbuf, pinned, last);
1089*663afb9bSAndroid Build Coastguard Worker 
1090*663afb9bSAndroid Build Coastguard Worker 	inbuf->n_del_for_cb += in_total_len;
1091*663afb9bSAndroid Build Coastguard Worker 	outbuf->n_add_for_cb += in_total_len;
1092*663afb9bSAndroid Build Coastguard Worker 
1093*663afb9bSAndroid Build Coastguard Worker 	evbuffer_invoke_callbacks_(inbuf);
1094*663afb9bSAndroid Build Coastguard Worker 	evbuffer_invoke_callbacks_(outbuf);
1095*663afb9bSAndroid Build Coastguard Worker done:
1096*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK2(inbuf, outbuf);
1097*663afb9bSAndroid Build Coastguard Worker 	return result;
1098*663afb9bSAndroid Build Coastguard Worker }
1099*663afb9bSAndroid Build Coastguard Worker 
1100*663afb9bSAndroid Build Coastguard Worker int
evbuffer_drain(struct evbuffer * buf,size_t len)1101*663afb9bSAndroid Build Coastguard Worker evbuffer_drain(struct evbuffer *buf, size_t len)
1102*663afb9bSAndroid Build Coastguard Worker {
1103*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain, *next;
1104*663afb9bSAndroid Build Coastguard Worker 	size_t remaining, old_len;
1105*663afb9bSAndroid Build Coastguard Worker 	int result = 0;
1106*663afb9bSAndroid Build Coastguard Worker 
1107*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buf);
1108*663afb9bSAndroid Build Coastguard Worker 	old_len = buf->total_len;
1109*663afb9bSAndroid Build Coastguard Worker 
1110*663afb9bSAndroid Build Coastguard Worker 	if (old_len == 0)
1111*663afb9bSAndroid Build Coastguard Worker 		goto done;
1112*663afb9bSAndroid Build Coastguard Worker 
1113*663afb9bSAndroid Build Coastguard Worker 	if (buf->freeze_start) {
1114*663afb9bSAndroid Build Coastguard Worker 		result = -1;
1115*663afb9bSAndroid Build Coastguard Worker 		goto done;
1116*663afb9bSAndroid Build Coastguard Worker 	}
1117*663afb9bSAndroid Build Coastguard Worker 
1118*663afb9bSAndroid Build Coastguard Worker 	if (len >= old_len && !HAS_PINNED_R(buf)) {
1119*663afb9bSAndroid Build Coastguard Worker 		len = old_len;
1120*663afb9bSAndroid Build Coastguard Worker 		for (chain = buf->first; chain != NULL; chain = next) {
1121*663afb9bSAndroid Build Coastguard Worker 			next = chain->next;
1122*663afb9bSAndroid Build Coastguard Worker 			evbuffer_chain_free(chain);
1123*663afb9bSAndroid Build Coastguard Worker 		}
1124*663afb9bSAndroid Build Coastguard Worker 
1125*663afb9bSAndroid Build Coastguard Worker 		ZERO_CHAIN(buf);
1126*663afb9bSAndroid Build Coastguard Worker 	} else {
1127*663afb9bSAndroid Build Coastguard Worker 		if (len >= old_len)
1128*663afb9bSAndroid Build Coastguard Worker 			len = old_len;
1129*663afb9bSAndroid Build Coastguard Worker 
1130*663afb9bSAndroid Build Coastguard Worker 		buf->total_len -= len;
1131*663afb9bSAndroid Build Coastguard Worker 		remaining = len;
1132*663afb9bSAndroid Build Coastguard Worker 		for (chain = buf->first;
1133*663afb9bSAndroid Build Coastguard Worker 		     remaining >= chain->off;
1134*663afb9bSAndroid Build Coastguard Worker 		     chain = next) {
1135*663afb9bSAndroid Build Coastguard Worker 			next = chain->next;
1136*663afb9bSAndroid Build Coastguard Worker 			remaining -= chain->off;
1137*663afb9bSAndroid Build Coastguard Worker 
1138*663afb9bSAndroid Build Coastguard Worker 			if (chain == *buf->last_with_datap) {
1139*663afb9bSAndroid Build Coastguard Worker 				buf->last_with_datap = &buf->first;
1140*663afb9bSAndroid Build Coastguard Worker 			}
1141*663afb9bSAndroid Build Coastguard Worker 			if (&chain->next == buf->last_with_datap)
1142*663afb9bSAndroid Build Coastguard Worker 				buf->last_with_datap = &buf->first;
1143*663afb9bSAndroid Build Coastguard Worker 
1144*663afb9bSAndroid Build Coastguard Worker 			if (CHAIN_PINNED_R(chain)) {
1145*663afb9bSAndroid Build Coastguard Worker 				EVUTIL_ASSERT(remaining == 0);
1146*663afb9bSAndroid Build Coastguard Worker 				chain->misalign += chain->off;
1147*663afb9bSAndroid Build Coastguard Worker 				chain->off = 0;
1148*663afb9bSAndroid Build Coastguard Worker 				break;
1149*663afb9bSAndroid Build Coastguard Worker 			} else
1150*663afb9bSAndroid Build Coastguard Worker 				evbuffer_chain_free(chain);
1151*663afb9bSAndroid Build Coastguard Worker 		}
1152*663afb9bSAndroid Build Coastguard Worker 
1153*663afb9bSAndroid Build Coastguard Worker 		buf->first = chain;
1154*663afb9bSAndroid Build Coastguard Worker 		EVUTIL_ASSERT(remaining <= chain->off);
1155*663afb9bSAndroid Build Coastguard Worker 		chain->misalign += remaining;
1156*663afb9bSAndroid Build Coastguard Worker 		chain->off -= remaining;
1157*663afb9bSAndroid Build Coastguard Worker 	}
1158*663afb9bSAndroid Build Coastguard Worker 
1159*663afb9bSAndroid Build Coastguard Worker 	buf->n_del_for_cb += len;
1160*663afb9bSAndroid Build Coastguard Worker 	/* Tell someone about changes in this buffer */
1161*663afb9bSAndroid Build Coastguard Worker 	evbuffer_invoke_callbacks_(buf);
1162*663afb9bSAndroid Build Coastguard Worker 
1163*663afb9bSAndroid Build Coastguard Worker done:
1164*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buf);
1165*663afb9bSAndroid Build Coastguard Worker 	return result;
1166*663afb9bSAndroid Build Coastguard Worker }
1167*663afb9bSAndroid Build Coastguard Worker 
1168*663afb9bSAndroid Build Coastguard Worker /* Reads data from an event buffer and drains the bytes read */
1169*663afb9bSAndroid Build Coastguard Worker int
evbuffer_remove(struct evbuffer * buf,void * data_out,size_t datlen)1170*663afb9bSAndroid Build Coastguard Worker evbuffer_remove(struct evbuffer *buf, void *data_out, size_t datlen)
1171*663afb9bSAndroid Build Coastguard Worker {
1172*663afb9bSAndroid Build Coastguard Worker 	ev_ssize_t n;
1173*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buf);
1174*663afb9bSAndroid Build Coastguard Worker 	n = evbuffer_copyout_from(buf, NULL, data_out, datlen);
1175*663afb9bSAndroid Build Coastguard Worker 	if (n > 0) {
1176*663afb9bSAndroid Build Coastguard Worker 		if (evbuffer_drain(buf, n)<0)
1177*663afb9bSAndroid Build Coastguard Worker 			n = -1;
1178*663afb9bSAndroid Build Coastguard Worker 	}
1179*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buf);
1180*663afb9bSAndroid Build Coastguard Worker 	return (int)n;
1181*663afb9bSAndroid Build Coastguard Worker }
1182*663afb9bSAndroid Build Coastguard Worker 
1183*663afb9bSAndroid Build Coastguard Worker ev_ssize_t
evbuffer_copyout(struct evbuffer * buf,void * data_out,size_t datlen)1184*663afb9bSAndroid Build Coastguard Worker evbuffer_copyout(struct evbuffer *buf, void *data_out, size_t datlen)
1185*663afb9bSAndroid Build Coastguard Worker {
1186*663afb9bSAndroid Build Coastguard Worker 	return evbuffer_copyout_from(buf, NULL, data_out, datlen);
1187*663afb9bSAndroid Build Coastguard Worker }
1188*663afb9bSAndroid Build Coastguard Worker 
1189*663afb9bSAndroid Build Coastguard Worker ev_ssize_t
evbuffer_copyout_from(struct evbuffer * buf,const struct evbuffer_ptr * pos,void * data_out,size_t datlen)1190*663afb9bSAndroid Build Coastguard Worker evbuffer_copyout_from(struct evbuffer *buf, const struct evbuffer_ptr *pos,
1191*663afb9bSAndroid Build Coastguard Worker     void *data_out, size_t datlen)
1192*663afb9bSAndroid Build Coastguard Worker {
1193*663afb9bSAndroid Build Coastguard Worker 	/*XXX fails badly on sendfile case. */
1194*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain;
1195*663afb9bSAndroid Build Coastguard Worker 	char *data = data_out;
1196*663afb9bSAndroid Build Coastguard Worker 	size_t nread;
1197*663afb9bSAndroid Build Coastguard Worker 	ev_ssize_t result = 0;
1198*663afb9bSAndroid Build Coastguard Worker 	size_t pos_in_chain;
1199*663afb9bSAndroid Build Coastguard Worker 
1200*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buf);
1201*663afb9bSAndroid Build Coastguard Worker 
1202*663afb9bSAndroid Build Coastguard Worker 	if (pos) {
1203*663afb9bSAndroid Build Coastguard Worker 		if (datlen > (size_t)(EV_SSIZE_MAX - pos->pos)) {
1204*663afb9bSAndroid Build Coastguard Worker 			result = -1;
1205*663afb9bSAndroid Build Coastguard Worker 			goto done;
1206*663afb9bSAndroid Build Coastguard Worker 		}
1207*663afb9bSAndroid Build Coastguard Worker 		chain = pos->internal_.chain;
1208*663afb9bSAndroid Build Coastguard Worker 		pos_in_chain = pos->internal_.pos_in_chain;
1209*663afb9bSAndroid Build Coastguard Worker 		if (datlen + pos->pos > buf->total_len)
1210*663afb9bSAndroid Build Coastguard Worker 			datlen = buf->total_len - pos->pos;
1211*663afb9bSAndroid Build Coastguard Worker 	} else {
1212*663afb9bSAndroid Build Coastguard Worker 		chain = buf->first;
1213*663afb9bSAndroid Build Coastguard Worker 		pos_in_chain = 0;
1214*663afb9bSAndroid Build Coastguard Worker 		if (datlen > buf->total_len)
1215*663afb9bSAndroid Build Coastguard Worker 			datlen = buf->total_len;
1216*663afb9bSAndroid Build Coastguard Worker 	}
1217*663afb9bSAndroid Build Coastguard Worker 
1218*663afb9bSAndroid Build Coastguard Worker 
1219*663afb9bSAndroid Build Coastguard Worker 	if (datlen == 0)
1220*663afb9bSAndroid Build Coastguard Worker 		goto done;
1221*663afb9bSAndroid Build Coastguard Worker 
1222*663afb9bSAndroid Build Coastguard Worker 	if (buf->freeze_start) {
1223*663afb9bSAndroid Build Coastguard Worker 		result = -1;
1224*663afb9bSAndroid Build Coastguard Worker 		goto done;
1225*663afb9bSAndroid Build Coastguard Worker 	}
1226*663afb9bSAndroid Build Coastguard Worker 
1227*663afb9bSAndroid Build Coastguard Worker 	nread = datlen;
1228*663afb9bSAndroid Build Coastguard Worker 
1229*663afb9bSAndroid Build Coastguard Worker 	while (datlen && datlen >= chain->off - pos_in_chain) {
1230*663afb9bSAndroid Build Coastguard Worker 		size_t copylen = chain->off - pos_in_chain;
1231*663afb9bSAndroid Build Coastguard Worker 		memcpy(data,
1232*663afb9bSAndroid Build Coastguard Worker 		    chain->buffer + chain->misalign + pos_in_chain,
1233*663afb9bSAndroid Build Coastguard Worker 		    copylen);
1234*663afb9bSAndroid Build Coastguard Worker 		data += copylen;
1235*663afb9bSAndroid Build Coastguard Worker 		datlen -= copylen;
1236*663afb9bSAndroid Build Coastguard Worker 
1237*663afb9bSAndroid Build Coastguard Worker 		chain = chain->next;
1238*663afb9bSAndroid Build Coastguard Worker 		pos_in_chain = 0;
1239*663afb9bSAndroid Build Coastguard Worker 		EVUTIL_ASSERT(chain || datlen==0);
1240*663afb9bSAndroid Build Coastguard Worker 	}
1241*663afb9bSAndroid Build Coastguard Worker 
1242*663afb9bSAndroid Build Coastguard Worker 	if (datlen) {
1243*663afb9bSAndroid Build Coastguard Worker 		EVUTIL_ASSERT(chain);
1244*663afb9bSAndroid Build Coastguard Worker 		EVUTIL_ASSERT(datlen+pos_in_chain <= chain->off);
1245*663afb9bSAndroid Build Coastguard Worker 
1246*663afb9bSAndroid Build Coastguard Worker 		memcpy(data, chain->buffer + chain->misalign + pos_in_chain,
1247*663afb9bSAndroid Build Coastguard Worker 		    datlen);
1248*663afb9bSAndroid Build Coastguard Worker 	}
1249*663afb9bSAndroid Build Coastguard Worker 
1250*663afb9bSAndroid Build Coastguard Worker 	result = nread;
1251*663afb9bSAndroid Build Coastguard Worker done:
1252*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buf);
1253*663afb9bSAndroid Build Coastguard Worker 	return result;
1254*663afb9bSAndroid Build Coastguard Worker }
1255*663afb9bSAndroid Build Coastguard Worker 
1256*663afb9bSAndroid Build Coastguard Worker /* reads data from the src buffer to the dst buffer, avoids memcpy as
1257*663afb9bSAndroid Build Coastguard Worker  * possible. */
1258*663afb9bSAndroid Build Coastguard Worker /*  XXXX should return ev_ssize_t */
1259*663afb9bSAndroid Build Coastguard Worker int
evbuffer_remove_buffer(struct evbuffer * src,struct evbuffer * dst,size_t datlen)1260*663afb9bSAndroid Build Coastguard Worker evbuffer_remove_buffer(struct evbuffer *src, struct evbuffer *dst,
1261*663afb9bSAndroid Build Coastguard Worker     size_t datlen)
1262*663afb9bSAndroid Build Coastguard Worker {
1263*663afb9bSAndroid Build Coastguard Worker 	/*XXX We should have an option to force this to be zero-copy.*/
1264*663afb9bSAndroid Build Coastguard Worker 
1265*663afb9bSAndroid Build Coastguard Worker 	/*XXX can fail badly on sendfile case. */
1266*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain, *previous;
1267*663afb9bSAndroid Build Coastguard Worker 	size_t nread = 0;
1268*663afb9bSAndroid Build Coastguard Worker 	int result;
1269*663afb9bSAndroid Build Coastguard Worker 
1270*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK2(src, dst);
1271*663afb9bSAndroid Build Coastguard Worker 
1272*663afb9bSAndroid Build Coastguard Worker 	chain = previous = src->first;
1273*663afb9bSAndroid Build Coastguard Worker 
1274*663afb9bSAndroid Build Coastguard Worker 	if (datlen == 0 || dst == src) {
1275*663afb9bSAndroid Build Coastguard Worker 		result = 0;
1276*663afb9bSAndroid Build Coastguard Worker 		goto done;
1277*663afb9bSAndroid Build Coastguard Worker 	}
1278*663afb9bSAndroid Build Coastguard Worker 
1279*663afb9bSAndroid Build Coastguard Worker 	if (dst->freeze_end || src->freeze_start) {
1280*663afb9bSAndroid Build Coastguard Worker 		result = -1;
1281*663afb9bSAndroid Build Coastguard Worker 		goto done;
1282*663afb9bSAndroid Build Coastguard Worker 	}
1283*663afb9bSAndroid Build Coastguard Worker 
1284*663afb9bSAndroid Build Coastguard Worker 	/* short-cut if there is no more data buffered */
1285*663afb9bSAndroid Build Coastguard Worker 	if (datlen >= src->total_len) {
1286*663afb9bSAndroid Build Coastguard Worker 		datlen = src->total_len;
1287*663afb9bSAndroid Build Coastguard Worker 		evbuffer_add_buffer(dst, src);
1288*663afb9bSAndroid Build Coastguard Worker 		result = (int)datlen; /*XXXX should return ev_ssize_t*/
1289*663afb9bSAndroid Build Coastguard Worker 		goto done;
1290*663afb9bSAndroid Build Coastguard Worker 	}
1291*663afb9bSAndroid Build Coastguard Worker 
1292*663afb9bSAndroid Build Coastguard Worker 	/* removes chains if possible */
1293*663afb9bSAndroid Build Coastguard Worker 	while (chain->off <= datlen) {
1294*663afb9bSAndroid Build Coastguard Worker 		/* We can't remove the last with data from src unless we
1295*663afb9bSAndroid Build Coastguard Worker 		 * remove all chains, in which case we would have done the if
1296*663afb9bSAndroid Build Coastguard Worker 		 * block above */
1297*663afb9bSAndroid Build Coastguard Worker 		EVUTIL_ASSERT(chain != *src->last_with_datap);
1298*663afb9bSAndroid Build Coastguard Worker 		nread += chain->off;
1299*663afb9bSAndroid Build Coastguard Worker 		datlen -= chain->off;
1300*663afb9bSAndroid Build Coastguard Worker 		previous = chain;
1301*663afb9bSAndroid Build Coastguard Worker 		if (src->last_with_datap == &chain->next)
1302*663afb9bSAndroid Build Coastguard Worker 			src->last_with_datap = &src->first;
1303*663afb9bSAndroid Build Coastguard Worker 		chain = chain->next;
1304*663afb9bSAndroid Build Coastguard Worker 	}
1305*663afb9bSAndroid Build Coastguard Worker 
1306*663afb9bSAndroid Build Coastguard Worker 	if (chain != src->first) {
1307*663afb9bSAndroid Build Coastguard Worker 		/* we can remove the chain */
1308*663afb9bSAndroid Build Coastguard Worker 		struct evbuffer_chain **chp;
1309*663afb9bSAndroid Build Coastguard Worker 		chp = evbuffer_free_trailing_empty_chains(dst);
1310*663afb9bSAndroid Build Coastguard Worker 
1311*663afb9bSAndroid Build Coastguard Worker 		if (dst->first == NULL) {
1312*663afb9bSAndroid Build Coastguard Worker 			dst->first = src->first;
1313*663afb9bSAndroid Build Coastguard Worker 		} else {
1314*663afb9bSAndroid Build Coastguard Worker 			*chp = src->first;
1315*663afb9bSAndroid Build Coastguard Worker 		}
1316*663afb9bSAndroid Build Coastguard Worker 		dst->last = previous;
1317*663afb9bSAndroid Build Coastguard Worker 		previous->next = NULL;
1318*663afb9bSAndroid Build Coastguard Worker 		src->first = chain;
1319*663afb9bSAndroid Build Coastguard Worker 		advance_last_with_data(dst);
1320*663afb9bSAndroid Build Coastguard Worker 
1321*663afb9bSAndroid Build Coastguard Worker 		dst->total_len += nread;
1322*663afb9bSAndroid Build Coastguard Worker 		dst->n_add_for_cb += nread;
1323*663afb9bSAndroid Build Coastguard Worker 	}
1324*663afb9bSAndroid Build Coastguard Worker 
1325*663afb9bSAndroid Build Coastguard Worker 	/* we know that there is more data in the src buffer than
1326*663afb9bSAndroid Build Coastguard Worker 	 * we want to read, so we manually drain the chain */
1327*663afb9bSAndroid Build Coastguard Worker 	evbuffer_add(dst, chain->buffer + chain->misalign, datlen);
1328*663afb9bSAndroid Build Coastguard Worker 	chain->misalign += datlen;
1329*663afb9bSAndroid Build Coastguard Worker 	chain->off -= datlen;
1330*663afb9bSAndroid Build Coastguard Worker 	nread += datlen;
1331*663afb9bSAndroid Build Coastguard Worker 
1332*663afb9bSAndroid Build Coastguard Worker 	/* You might think we would want to increment dst->n_add_for_cb
1333*663afb9bSAndroid Build Coastguard Worker 	 * here too.  But evbuffer_add above already took care of that.
1334*663afb9bSAndroid Build Coastguard Worker 	 */
1335*663afb9bSAndroid Build Coastguard Worker 	src->total_len -= nread;
1336*663afb9bSAndroid Build Coastguard Worker 	src->n_del_for_cb += nread;
1337*663afb9bSAndroid Build Coastguard Worker 
1338*663afb9bSAndroid Build Coastguard Worker 	if (nread) {
1339*663afb9bSAndroid Build Coastguard Worker 		evbuffer_invoke_callbacks_(dst);
1340*663afb9bSAndroid Build Coastguard Worker 		evbuffer_invoke_callbacks_(src);
1341*663afb9bSAndroid Build Coastguard Worker 	}
1342*663afb9bSAndroid Build Coastguard Worker 	result = (int)nread;/*XXXX should change return type */
1343*663afb9bSAndroid Build Coastguard Worker 
1344*663afb9bSAndroid Build Coastguard Worker done:
1345*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK2(src, dst);
1346*663afb9bSAndroid Build Coastguard Worker 	return result;
1347*663afb9bSAndroid Build Coastguard Worker }
1348*663afb9bSAndroid Build Coastguard Worker 
1349*663afb9bSAndroid Build Coastguard Worker unsigned char *
evbuffer_pullup(struct evbuffer * buf,ev_ssize_t size)1350*663afb9bSAndroid Build Coastguard Worker evbuffer_pullup(struct evbuffer *buf, ev_ssize_t size)
1351*663afb9bSAndroid Build Coastguard Worker {
1352*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain, *next, *tmp, *last_with_data;
1353*663afb9bSAndroid Build Coastguard Worker 	unsigned char *buffer, *result = NULL;
1354*663afb9bSAndroid Build Coastguard Worker 	ev_ssize_t remaining;
1355*663afb9bSAndroid Build Coastguard Worker 	int removed_last_with_data = 0;
1356*663afb9bSAndroid Build Coastguard Worker 	int removed_last_with_datap = 0;
1357*663afb9bSAndroid Build Coastguard Worker 
1358*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buf);
1359*663afb9bSAndroid Build Coastguard Worker 
1360*663afb9bSAndroid Build Coastguard Worker 	chain = buf->first;
1361*663afb9bSAndroid Build Coastguard Worker 
1362*663afb9bSAndroid Build Coastguard Worker 	if (size < 0)
1363*663afb9bSAndroid Build Coastguard Worker 		size = buf->total_len;
1364*663afb9bSAndroid Build Coastguard Worker 	/* if size > buf->total_len, we cannot guarantee to the user that she
1365*663afb9bSAndroid Build Coastguard Worker 	 * is going to have a long enough buffer afterwards; so we return
1366*663afb9bSAndroid Build Coastguard Worker 	 * NULL */
1367*663afb9bSAndroid Build Coastguard Worker 	if (size == 0 || (size_t)size > buf->total_len)
1368*663afb9bSAndroid Build Coastguard Worker 		goto done;
1369*663afb9bSAndroid Build Coastguard Worker 
1370*663afb9bSAndroid Build Coastguard Worker 	/* No need to pull up anything; the first size bytes are
1371*663afb9bSAndroid Build Coastguard Worker 	 * already here. */
1372*663afb9bSAndroid Build Coastguard Worker 	if (chain->off >= (size_t)size) {
1373*663afb9bSAndroid Build Coastguard Worker 		result = chain->buffer + chain->misalign;
1374*663afb9bSAndroid Build Coastguard Worker 		goto done;
1375*663afb9bSAndroid Build Coastguard Worker 	}
1376*663afb9bSAndroid Build Coastguard Worker 
1377*663afb9bSAndroid Build Coastguard Worker 	/* Make sure that none of the chains we need to copy from is pinned. */
1378*663afb9bSAndroid Build Coastguard Worker 	remaining = size - chain->off;
1379*663afb9bSAndroid Build Coastguard Worker 	EVUTIL_ASSERT(remaining >= 0);
1380*663afb9bSAndroid Build Coastguard Worker 	for (tmp=chain->next; tmp; tmp=tmp->next) {
1381*663afb9bSAndroid Build Coastguard Worker 		if (CHAIN_PINNED(tmp))
1382*663afb9bSAndroid Build Coastguard Worker 			goto done;
1383*663afb9bSAndroid Build Coastguard Worker 		if (tmp->off >= (size_t)remaining)
1384*663afb9bSAndroid Build Coastguard Worker 			break;
1385*663afb9bSAndroid Build Coastguard Worker 		remaining -= tmp->off;
1386*663afb9bSAndroid Build Coastguard Worker 	}
1387*663afb9bSAndroid Build Coastguard Worker 
1388*663afb9bSAndroid Build Coastguard Worker 	if (CHAIN_PINNED(chain)) {
1389*663afb9bSAndroid Build Coastguard Worker 		size_t old_off = chain->off;
1390*663afb9bSAndroid Build Coastguard Worker 		if (CHAIN_SPACE_LEN(chain) < size - chain->off) {
1391*663afb9bSAndroid Build Coastguard Worker 			/* not enough room at end of chunk. */
1392*663afb9bSAndroid Build Coastguard Worker 			goto done;
1393*663afb9bSAndroid Build Coastguard Worker 		}
1394*663afb9bSAndroid Build Coastguard Worker 		buffer = CHAIN_SPACE_PTR(chain);
1395*663afb9bSAndroid Build Coastguard Worker 		tmp = chain;
1396*663afb9bSAndroid Build Coastguard Worker 		tmp->off = size;
1397*663afb9bSAndroid Build Coastguard Worker 		size -= old_off;
1398*663afb9bSAndroid Build Coastguard Worker 		chain = chain->next;
1399*663afb9bSAndroid Build Coastguard Worker 	} else if (chain->buffer_len - chain->misalign >= (size_t)size) {
1400*663afb9bSAndroid Build Coastguard Worker 		/* already have enough space in the first chain */
1401*663afb9bSAndroid Build Coastguard Worker 		size_t old_off = chain->off;
1402*663afb9bSAndroid Build Coastguard Worker 		buffer = chain->buffer + chain->misalign + chain->off;
1403*663afb9bSAndroid Build Coastguard Worker 		tmp = chain;
1404*663afb9bSAndroid Build Coastguard Worker 		tmp->off = size;
1405*663afb9bSAndroid Build Coastguard Worker 		size -= old_off;
1406*663afb9bSAndroid Build Coastguard Worker 		chain = chain->next;
1407*663afb9bSAndroid Build Coastguard Worker 	} else {
1408*663afb9bSAndroid Build Coastguard Worker 		if ((tmp = evbuffer_chain_new(size)) == NULL) {
1409*663afb9bSAndroid Build Coastguard Worker 			event_warn("%s: out of memory", __func__);
1410*663afb9bSAndroid Build Coastguard Worker 			goto done;
1411*663afb9bSAndroid Build Coastguard Worker 		}
1412*663afb9bSAndroid Build Coastguard Worker 		buffer = tmp->buffer;
1413*663afb9bSAndroid Build Coastguard Worker 		tmp->off = size;
1414*663afb9bSAndroid Build Coastguard Worker 		buf->first = tmp;
1415*663afb9bSAndroid Build Coastguard Worker 	}
1416*663afb9bSAndroid Build Coastguard Worker 
1417*663afb9bSAndroid Build Coastguard Worker 	/* TODO(niels): deal with buffers that point to NULL like sendfile */
1418*663afb9bSAndroid Build Coastguard Worker 
1419*663afb9bSAndroid Build Coastguard Worker 	/* Copy and free every chunk that will be entirely pulled into tmp */
1420*663afb9bSAndroid Build Coastguard Worker 	last_with_data = *buf->last_with_datap;
1421*663afb9bSAndroid Build Coastguard Worker 	for (; chain != NULL && (size_t)size >= chain->off; chain = next) {
1422*663afb9bSAndroid Build Coastguard Worker 		next = chain->next;
1423*663afb9bSAndroid Build Coastguard Worker 
1424*663afb9bSAndroid Build Coastguard Worker 		if (chain->buffer) {
1425*663afb9bSAndroid Build Coastguard Worker 			memcpy(buffer, chain->buffer + chain->misalign, chain->off);
1426*663afb9bSAndroid Build Coastguard Worker 			size -= chain->off;
1427*663afb9bSAndroid Build Coastguard Worker 			buffer += chain->off;
1428*663afb9bSAndroid Build Coastguard Worker 		}
1429*663afb9bSAndroid Build Coastguard Worker 		if (chain == last_with_data)
1430*663afb9bSAndroid Build Coastguard Worker 			removed_last_with_data = 1;
1431*663afb9bSAndroid Build Coastguard Worker 		if (&chain->next == buf->last_with_datap)
1432*663afb9bSAndroid Build Coastguard Worker 			removed_last_with_datap = 1;
1433*663afb9bSAndroid Build Coastguard Worker 
1434*663afb9bSAndroid Build Coastguard Worker 		evbuffer_chain_free(chain);
1435*663afb9bSAndroid Build Coastguard Worker 	}
1436*663afb9bSAndroid Build Coastguard Worker 
1437*663afb9bSAndroid Build Coastguard Worker 	if (chain != NULL) {
1438*663afb9bSAndroid Build Coastguard Worker 		memcpy(buffer, chain->buffer + chain->misalign, size);
1439*663afb9bSAndroid Build Coastguard Worker 		chain->misalign += size;
1440*663afb9bSAndroid Build Coastguard Worker 		chain->off -= size;
1441*663afb9bSAndroid Build Coastguard Worker 	} else {
1442*663afb9bSAndroid Build Coastguard Worker 		buf->last = tmp;
1443*663afb9bSAndroid Build Coastguard Worker 	}
1444*663afb9bSAndroid Build Coastguard Worker 
1445*663afb9bSAndroid Build Coastguard Worker 	tmp->next = chain;
1446*663afb9bSAndroid Build Coastguard Worker 
1447*663afb9bSAndroid Build Coastguard Worker 	if (removed_last_with_data) {
1448*663afb9bSAndroid Build Coastguard Worker 		buf->last_with_datap = &buf->first;
1449*663afb9bSAndroid Build Coastguard Worker 	} else if (removed_last_with_datap) {
1450*663afb9bSAndroid Build Coastguard Worker 		if (buf->first->next && buf->first->next->off)
1451*663afb9bSAndroid Build Coastguard Worker 			buf->last_with_datap = &buf->first->next;
1452*663afb9bSAndroid Build Coastguard Worker 		else
1453*663afb9bSAndroid Build Coastguard Worker 			buf->last_with_datap = &buf->first;
1454*663afb9bSAndroid Build Coastguard Worker 	}
1455*663afb9bSAndroid Build Coastguard Worker 
1456*663afb9bSAndroid Build Coastguard Worker 	result = (tmp->buffer + tmp->misalign);
1457*663afb9bSAndroid Build Coastguard Worker 
1458*663afb9bSAndroid Build Coastguard Worker done:
1459*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buf);
1460*663afb9bSAndroid Build Coastguard Worker 	return result;
1461*663afb9bSAndroid Build Coastguard Worker }
1462*663afb9bSAndroid Build Coastguard Worker 
1463*663afb9bSAndroid Build Coastguard Worker /*
1464*663afb9bSAndroid Build Coastguard Worker  * Reads a line terminated by either '\r\n', '\n\r' or '\r' or '\n'.
1465*663afb9bSAndroid Build Coastguard Worker  * The returned buffer needs to be freed by the called.
1466*663afb9bSAndroid Build Coastguard Worker  */
1467*663afb9bSAndroid Build Coastguard Worker char *
evbuffer_readline(struct evbuffer * buffer)1468*663afb9bSAndroid Build Coastguard Worker evbuffer_readline(struct evbuffer *buffer)
1469*663afb9bSAndroid Build Coastguard Worker {
1470*663afb9bSAndroid Build Coastguard Worker 	return evbuffer_readln(buffer, NULL, EVBUFFER_EOL_ANY);
1471*663afb9bSAndroid Build Coastguard Worker }
1472*663afb9bSAndroid Build Coastguard Worker 
1473*663afb9bSAndroid Build Coastguard Worker static inline ev_ssize_t
evbuffer_strchr(struct evbuffer_ptr * it,const char chr)1474*663afb9bSAndroid Build Coastguard Worker evbuffer_strchr(struct evbuffer_ptr *it, const char chr)
1475*663afb9bSAndroid Build Coastguard Worker {
1476*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain = it->internal_.chain;
1477*663afb9bSAndroid Build Coastguard Worker 	size_t i = it->internal_.pos_in_chain;
1478*663afb9bSAndroid Build Coastguard Worker 	while (chain != NULL) {
1479*663afb9bSAndroid Build Coastguard Worker 		char *buffer = (char *)chain->buffer + chain->misalign;
1480*663afb9bSAndroid Build Coastguard Worker 		char *cp = memchr(buffer+i, chr, chain->off-i);
1481*663afb9bSAndroid Build Coastguard Worker 		if (cp) {
1482*663afb9bSAndroid Build Coastguard Worker 			it->internal_.chain = chain;
1483*663afb9bSAndroid Build Coastguard Worker 			it->internal_.pos_in_chain = cp - buffer;
1484*663afb9bSAndroid Build Coastguard Worker 			it->pos += (cp - buffer - i);
1485*663afb9bSAndroid Build Coastguard Worker 			return it->pos;
1486*663afb9bSAndroid Build Coastguard Worker 		}
1487*663afb9bSAndroid Build Coastguard Worker 		it->pos += chain->off - i;
1488*663afb9bSAndroid Build Coastguard Worker 		i = 0;
1489*663afb9bSAndroid Build Coastguard Worker 		chain = chain->next;
1490*663afb9bSAndroid Build Coastguard Worker 	}
1491*663afb9bSAndroid Build Coastguard Worker 
1492*663afb9bSAndroid Build Coastguard Worker 	return (-1);
1493*663afb9bSAndroid Build Coastguard Worker }
1494*663afb9bSAndroid Build Coastguard Worker 
1495*663afb9bSAndroid Build Coastguard Worker static inline char *
find_eol_char(char * s,size_t len)1496*663afb9bSAndroid Build Coastguard Worker find_eol_char(char *s, size_t len)
1497*663afb9bSAndroid Build Coastguard Worker {
1498*663afb9bSAndroid Build Coastguard Worker #define CHUNK_SZ 128
1499*663afb9bSAndroid Build Coastguard Worker 	/* Lots of benchmarking found this approach to be faster in practice
1500*663afb9bSAndroid Build Coastguard Worker 	 * than doing two memchrs over the whole buffer, doin a memchr on each
1501*663afb9bSAndroid Build Coastguard Worker 	 * char of the buffer, or trying to emulate memchr by hand. */
1502*663afb9bSAndroid Build Coastguard Worker 	char *s_end, *cr, *lf;
1503*663afb9bSAndroid Build Coastguard Worker 	s_end = s+len;
1504*663afb9bSAndroid Build Coastguard Worker 	while (s < s_end) {
1505*663afb9bSAndroid Build Coastguard Worker 		size_t chunk = (s + CHUNK_SZ < s_end) ? CHUNK_SZ : (s_end - s);
1506*663afb9bSAndroid Build Coastguard Worker 		cr = memchr(s, '\r', chunk);
1507*663afb9bSAndroid Build Coastguard Worker 		lf = memchr(s, '\n', chunk);
1508*663afb9bSAndroid Build Coastguard Worker 		if (cr) {
1509*663afb9bSAndroid Build Coastguard Worker 			if (lf && lf < cr)
1510*663afb9bSAndroid Build Coastguard Worker 				return lf;
1511*663afb9bSAndroid Build Coastguard Worker 			return cr;
1512*663afb9bSAndroid Build Coastguard Worker 		} else if (lf) {
1513*663afb9bSAndroid Build Coastguard Worker 			return lf;
1514*663afb9bSAndroid Build Coastguard Worker 		}
1515*663afb9bSAndroid Build Coastguard Worker 		s += CHUNK_SZ;
1516*663afb9bSAndroid Build Coastguard Worker 	}
1517*663afb9bSAndroid Build Coastguard Worker 
1518*663afb9bSAndroid Build Coastguard Worker 	return NULL;
1519*663afb9bSAndroid Build Coastguard Worker #undef CHUNK_SZ
1520*663afb9bSAndroid Build Coastguard Worker }
1521*663afb9bSAndroid Build Coastguard Worker 
1522*663afb9bSAndroid Build Coastguard Worker static ev_ssize_t
evbuffer_find_eol_char(struct evbuffer_ptr * it)1523*663afb9bSAndroid Build Coastguard Worker evbuffer_find_eol_char(struct evbuffer_ptr *it)
1524*663afb9bSAndroid Build Coastguard Worker {
1525*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain = it->internal_.chain;
1526*663afb9bSAndroid Build Coastguard Worker 	size_t i = it->internal_.pos_in_chain;
1527*663afb9bSAndroid Build Coastguard Worker 	while (chain != NULL) {
1528*663afb9bSAndroid Build Coastguard Worker 		char *buffer = (char *)chain->buffer + chain->misalign;
1529*663afb9bSAndroid Build Coastguard Worker 		char *cp = find_eol_char(buffer+i, chain->off-i);
1530*663afb9bSAndroid Build Coastguard Worker 		if (cp) {
1531*663afb9bSAndroid Build Coastguard Worker 			it->internal_.chain = chain;
1532*663afb9bSAndroid Build Coastguard Worker 			it->internal_.pos_in_chain = cp - buffer;
1533*663afb9bSAndroid Build Coastguard Worker 			it->pos += (cp - buffer) - i;
1534*663afb9bSAndroid Build Coastguard Worker 			return it->pos;
1535*663afb9bSAndroid Build Coastguard Worker 		}
1536*663afb9bSAndroid Build Coastguard Worker 		it->pos += chain->off - i;
1537*663afb9bSAndroid Build Coastguard Worker 		i = 0;
1538*663afb9bSAndroid Build Coastguard Worker 		chain = chain->next;
1539*663afb9bSAndroid Build Coastguard Worker 	}
1540*663afb9bSAndroid Build Coastguard Worker 
1541*663afb9bSAndroid Build Coastguard Worker 	return (-1);
1542*663afb9bSAndroid Build Coastguard Worker }
1543*663afb9bSAndroid Build Coastguard Worker 
1544*663afb9bSAndroid Build Coastguard Worker static inline size_t
evbuffer_strspn(struct evbuffer_ptr * ptr,const char * chrset)1545*663afb9bSAndroid Build Coastguard Worker evbuffer_strspn(
1546*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_ptr *ptr, const char *chrset)
1547*663afb9bSAndroid Build Coastguard Worker {
1548*663afb9bSAndroid Build Coastguard Worker 	size_t count = 0;
1549*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain = ptr->internal_.chain;
1550*663afb9bSAndroid Build Coastguard Worker 	size_t i = ptr->internal_.pos_in_chain;
1551*663afb9bSAndroid Build Coastguard Worker 
1552*663afb9bSAndroid Build Coastguard Worker 	if (!chain)
1553*663afb9bSAndroid Build Coastguard Worker 		return 0;
1554*663afb9bSAndroid Build Coastguard Worker 
1555*663afb9bSAndroid Build Coastguard Worker 	while (1) {
1556*663afb9bSAndroid Build Coastguard Worker 		char *buffer = (char *)chain->buffer + chain->misalign;
1557*663afb9bSAndroid Build Coastguard Worker 		for (; i < chain->off; ++i) {
1558*663afb9bSAndroid Build Coastguard Worker 			const char *p = chrset;
1559*663afb9bSAndroid Build Coastguard Worker 			while (*p) {
1560*663afb9bSAndroid Build Coastguard Worker 				if (buffer[i] == *p++)
1561*663afb9bSAndroid Build Coastguard Worker 					goto next;
1562*663afb9bSAndroid Build Coastguard Worker 			}
1563*663afb9bSAndroid Build Coastguard Worker 			ptr->internal_.chain = chain;
1564*663afb9bSAndroid Build Coastguard Worker 			ptr->internal_.pos_in_chain = i;
1565*663afb9bSAndroid Build Coastguard Worker 			ptr->pos += count;
1566*663afb9bSAndroid Build Coastguard Worker 			return count;
1567*663afb9bSAndroid Build Coastguard Worker 		next:
1568*663afb9bSAndroid Build Coastguard Worker 			++count;
1569*663afb9bSAndroid Build Coastguard Worker 		}
1570*663afb9bSAndroid Build Coastguard Worker 		i = 0;
1571*663afb9bSAndroid Build Coastguard Worker 
1572*663afb9bSAndroid Build Coastguard Worker 		if (! chain->next) {
1573*663afb9bSAndroid Build Coastguard Worker 			ptr->internal_.chain = chain;
1574*663afb9bSAndroid Build Coastguard Worker 			ptr->internal_.pos_in_chain = i;
1575*663afb9bSAndroid Build Coastguard Worker 			ptr->pos += count;
1576*663afb9bSAndroid Build Coastguard Worker 			return count;
1577*663afb9bSAndroid Build Coastguard Worker 		}
1578*663afb9bSAndroid Build Coastguard Worker 
1579*663afb9bSAndroid Build Coastguard Worker 		chain = chain->next;
1580*663afb9bSAndroid Build Coastguard Worker 	}
1581*663afb9bSAndroid Build Coastguard Worker }
1582*663afb9bSAndroid Build Coastguard Worker 
1583*663afb9bSAndroid Build Coastguard Worker 
1584*663afb9bSAndroid Build Coastguard Worker static inline int
evbuffer_getchr(struct evbuffer_ptr * it)1585*663afb9bSAndroid Build Coastguard Worker evbuffer_getchr(struct evbuffer_ptr *it)
1586*663afb9bSAndroid Build Coastguard Worker {
1587*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain = it->internal_.chain;
1588*663afb9bSAndroid Build Coastguard Worker 	size_t off = it->internal_.pos_in_chain;
1589*663afb9bSAndroid Build Coastguard Worker 
1590*663afb9bSAndroid Build Coastguard Worker 	if (chain == NULL)
1591*663afb9bSAndroid Build Coastguard Worker 		return -1;
1592*663afb9bSAndroid Build Coastguard Worker 
1593*663afb9bSAndroid Build Coastguard Worker 	return (unsigned char)chain->buffer[chain->misalign + off];
1594*663afb9bSAndroid Build Coastguard Worker }
1595*663afb9bSAndroid Build Coastguard Worker 
1596*663afb9bSAndroid Build Coastguard Worker struct evbuffer_ptr
evbuffer_search_eol(struct evbuffer * buffer,struct evbuffer_ptr * start,size_t * eol_len_out,enum evbuffer_eol_style eol_style)1597*663afb9bSAndroid Build Coastguard Worker evbuffer_search_eol(struct evbuffer *buffer,
1598*663afb9bSAndroid Build Coastguard Worker     struct evbuffer_ptr *start, size_t *eol_len_out,
1599*663afb9bSAndroid Build Coastguard Worker     enum evbuffer_eol_style eol_style)
1600*663afb9bSAndroid Build Coastguard Worker {
1601*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_ptr it, it2;
1602*663afb9bSAndroid Build Coastguard Worker 	size_t extra_drain = 0;
1603*663afb9bSAndroid Build Coastguard Worker 	int ok = 0;
1604*663afb9bSAndroid Build Coastguard Worker 
1605*663afb9bSAndroid Build Coastguard Worker 	/* Avoid locking in trivial edge cases */
1606*663afb9bSAndroid Build Coastguard Worker 	if (start && start->internal_.chain == NULL) {
1607*663afb9bSAndroid Build Coastguard Worker 		PTR_NOT_FOUND(&it);
1608*663afb9bSAndroid Build Coastguard Worker 		if (eol_len_out)
1609*663afb9bSAndroid Build Coastguard Worker 			*eol_len_out = extra_drain;
1610*663afb9bSAndroid Build Coastguard Worker 		return it;
1611*663afb9bSAndroid Build Coastguard Worker 	}
1612*663afb9bSAndroid Build Coastguard Worker 
1613*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buffer);
1614*663afb9bSAndroid Build Coastguard Worker 
1615*663afb9bSAndroid Build Coastguard Worker 	if (start) {
1616*663afb9bSAndroid Build Coastguard Worker 		memcpy(&it, start, sizeof(it));
1617*663afb9bSAndroid Build Coastguard Worker 	} else {
1618*663afb9bSAndroid Build Coastguard Worker 		it.pos = 0;
1619*663afb9bSAndroid Build Coastguard Worker 		it.internal_.chain = buffer->first;
1620*663afb9bSAndroid Build Coastguard Worker 		it.internal_.pos_in_chain = 0;
1621*663afb9bSAndroid Build Coastguard Worker 	}
1622*663afb9bSAndroid Build Coastguard Worker 
1623*663afb9bSAndroid Build Coastguard Worker 	/* the eol_style determines our first stop character and how many
1624*663afb9bSAndroid Build Coastguard Worker 	 * characters we are going to drain afterwards. */
1625*663afb9bSAndroid Build Coastguard Worker 	switch (eol_style) {
1626*663afb9bSAndroid Build Coastguard Worker 	case EVBUFFER_EOL_ANY:
1627*663afb9bSAndroid Build Coastguard Worker 		if (evbuffer_find_eol_char(&it) < 0)
1628*663afb9bSAndroid Build Coastguard Worker 			goto done;
1629*663afb9bSAndroid Build Coastguard Worker 		memcpy(&it2, &it, sizeof(it));
1630*663afb9bSAndroid Build Coastguard Worker 		extra_drain = evbuffer_strspn(&it2, "\r\n");
1631*663afb9bSAndroid Build Coastguard Worker 		break;
1632*663afb9bSAndroid Build Coastguard Worker 	case EVBUFFER_EOL_CRLF_STRICT: {
1633*663afb9bSAndroid Build Coastguard Worker 		it = evbuffer_search(buffer, "\r\n", 2, &it);
1634*663afb9bSAndroid Build Coastguard Worker 		if (it.pos < 0)
1635*663afb9bSAndroid Build Coastguard Worker 			goto done;
1636*663afb9bSAndroid Build Coastguard Worker 		extra_drain = 2;
1637*663afb9bSAndroid Build Coastguard Worker 		break;
1638*663afb9bSAndroid Build Coastguard Worker 	}
1639*663afb9bSAndroid Build Coastguard Worker 	case EVBUFFER_EOL_CRLF: {
1640*663afb9bSAndroid Build Coastguard Worker 		ev_ssize_t start_pos = it.pos;
1641*663afb9bSAndroid Build Coastguard Worker 		/* Look for a LF ... */
1642*663afb9bSAndroid Build Coastguard Worker 		if (evbuffer_strchr(&it, '\n') < 0)
1643*663afb9bSAndroid Build Coastguard Worker 			goto done;
1644*663afb9bSAndroid Build Coastguard Worker 		extra_drain = 1;
1645*663afb9bSAndroid Build Coastguard Worker 		/* ... optionally preceeded by a CR. */
1646*663afb9bSAndroid Build Coastguard Worker 		if (it.pos == start_pos)
1647*663afb9bSAndroid Build Coastguard Worker 			break; /* If the first character is \n, don't back up */
1648*663afb9bSAndroid Build Coastguard Worker 		/* This potentially does an extra linear walk over the first
1649*663afb9bSAndroid Build Coastguard Worker 		 * few chains.  Probably, that's not too expensive unless you
1650*663afb9bSAndroid Build Coastguard Worker 		 * have a really pathological setup. */
1651*663afb9bSAndroid Build Coastguard Worker 		memcpy(&it2, &it, sizeof(it));
1652*663afb9bSAndroid Build Coastguard Worker 		if (evbuffer_ptr_subtract(buffer, &it2, 1)<0)
1653*663afb9bSAndroid Build Coastguard Worker 			break;
1654*663afb9bSAndroid Build Coastguard Worker 		if (evbuffer_getchr(&it2) == '\r') {
1655*663afb9bSAndroid Build Coastguard Worker 			memcpy(&it, &it2, sizeof(it));
1656*663afb9bSAndroid Build Coastguard Worker 			extra_drain = 2;
1657*663afb9bSAndroid Build Coastguard Worker 		}
1658*663afb9bSAndroid Build Coastguard Worker 		break;
1659*663afb9bSAndroid Build Coastguard Worker 	}
1660*663afb9bSAndroid Build Coastguard Worker 	case EVBUFFER_EOL_LF:
1661*663afb9bSAndroid Build Coastguard Worker 		if (evbuffer_strchr(&it, '\n') < 0)
1662*663afb9bSAndroid Build Coastguard Worker 			goto done;
1663*663afb9bSAndroid Build Coastguard Worker 		extra_drain = 1;
1664*663afb9bSAndroid Build Coastguard Worker 		break;
1665*663afb9bSAndroid Build Coastguard Worker 	case EVBUFFER_EOL_NUL:
1666*663afb9bSAndroid Build Coastguard Worker 		if (evbuffer_strchr(&it, '\0') < 0)
1667*663afb9bSAndroid Build Coastguard Worker 			goto done;
1668*663afb9bSAndroid Build Coastguard Worker 		extra_drain = 1;
1669*663afb9bSAndroid Build Coastguard Worker 		break;
1670*663afb9bSAndroid Build Coastguard Worker 	default:
1671*663afb9bSAndroid Build Coastguard Worker 		goto done;
1672*663afb9bSAndroid Build Coastguard Worker 	}
1673*663afb9bSAndroid Build Coastguard Worker 
1674*663afb9bSAndroid Build Coastguard Worker 	ok = 1;
1675*663afb9bSAndroid Build Coastguard Worker done:
1676*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buffer);
1677*663afb9bSAndroid Build Coastguard Worker 
1678*663afb9bSAndroid Build Coastguard Worker 	if (!ok)
1679*663afb9bSAndroid Build Coastguard Worker 		PTR_NOT_FOUND(&it);
1680*663afb9bSAndroid Build Coastguard Worker 	if (eol_len_out)
1681*663afb9bSAndroid Build Coastguard Worker 		*eol_len_out = extra_drain;
1682*663afb9bSAndroid Build Coastguard Worker 
1683*663afb9bSAndroid Build Coastguard Worker 	return it;
1684*663afb9bSAndroid Build Coastguard Worker }
1685*663afb9bSAndroid Build Coastguard Worker 
1686*663afb9bSAndroid Build Coastguard Worker char *
evbuffer_readln(struct evbuffer * buffer,size_t * n_read_out,enum evbuffer_eol_style eol_style)1687*663afb9bSAndroid Build Coastguard Worker evbuffer_readln(struct evbuffer *buffer, size_t *n_read_out,
1688*663afb9bSAndroid Build Coastguard Worker 		enum evbuffer_eol_style eol_style)
1689*663afb9bSAndroid Build Coastguard Worker {
1690*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_ptr it;
1691*663afb9bSAndroid Build Coastguard Worker 	char *line;
1692*663afb9bSAndroid Build Coastguard Worker 	size_t n_to_copy=0, extra_drain=0;
1693*663afb9bSAndroid Build Coastguard Worker 	char *result = NULL;
1694*663afb9bSAndroid Build Coastguard Worker 
1695*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buffer);
1696*663afb9bSAndroid Build Coastguard Worker 
1697*663afb9bSAndroid Build Coastguard Worker 	if (buffer->freeze_start) {
1698*663afb9bSAndroid Build Coastguard Worker 		goto done;
1699*663afb9bSAndroid Build Coastguard Worker 	}
1700*663afb9bSAndroid Build Coastguard Worker 
1701*663afb9bSAndroid Build Coastguard Worker 	it = evbuffer_search_eol(buffer, NULL, &extra_drain, eol_style);
1702*663afb9bSAndroid Build Coastguard Worker 	if (it.pos < 0)
1703*663afb9bSAndroid Build Coastguard Worker 		goto done;
1704*663afb9bSAndroid Build Coastguard Worker 	n_to_copy = it.pos;
1705*663afb9bSAndroid Build Coastguard Worker 
1706*663afb9bSAndroid Build Coastguard Worker 	if ((line = mm_malloc(n_to_copy+1)) == NULL) {
1707*663afb9bSAndroid Build Coastguard Worker 		event_warn("%s: out of memory", __func__);
1708*663afb9bSAndroid Build Coastguard Worker 		goto done;
1709*663afb9bSAndroid Build Coastguard Worker 	}
1710*663afb9bSAndroid Build Coastguard Worker 
1711*663afb9bSAndroid Build Coastguard Worker 	evbuffer_remove(buffer, line, n_to_copy);
1712*663afb9bSAndroid Build Coastguard Worker 	line[n_to_copy] = '\0';
1713*663afb9bSAndroid Build Coastguard Worker 
1714*663afb9bSAndroid Build Coastguard Worker 	evbuffer_drain(buffer, extra_drain);
1715*663afb9bSAndroid Build Coastguard Worker 	result = line;
1716*663afb9bSAndroid Build Coastguard Worker done:
1717*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buffer);
1718*663afb9bSAndroid Build Coastguard Worker 
1719*663afb9bSAndroid Build Coastguard Worker 	if (n_read_out)
1720*663afb9bSAndroid Build Coastguard Worker 		*n_read_out = result ? n_to_copy : 0;
1721*663afb9bSAndroid Build Coastguard Worker 
1722*663afb9bSAndroid Build Coastguard Worker 	return result;
1723*663afb9bSAndroid Build Coastguard Worker }
1724*663afb9bSAndroid Build Coastguard Worker 
1725*663afb9bSAndroid Build Coastguard Worker #define EVBUFFER_CHAIN_MAX_AUTO_SIZE 4096
1726*663afb9bSAndroid Build Coastguard Worker 
1727*663afb9bSAndroid Build Coastguard Worker /* Adds data to an event buffer */
1728*663afb9bSAndroid Build Coastguard Worker 
1729*663afb9bSAndroid Build Coastguard Worker int
evbuffer_add(struct evbuffer * buf,const void * data_in,size_t datlen)1730*663afb9bSAndroid Build Coastguard Worker evbuffer_add(struct evbuffer *buf, const void *data_in, size_t datlen)
1731*663afb9bSAndroid Build Coastguard Worker {
1732*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain, *tmp;
1733*663afb9bSAndroid Build Coastguard Worker 	const unsigned char *data = data_in;
1734*663afb9bSAndroid Build Coastguard Worker 	size_t remain, to_alloc;
1735*663afb9bSAndroid Build Coastguard Worker 	int result = -1;
1736*663afb9bSAndroid Build Coastguard Worker 
1737*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buf);
1738*663afb9bSAndroid Build Coastguard Worker 
1739*663afb9bSAndroid Build Coastguard Worker 	if (buf->freeze_end) {
1740*663afb9bSAndroid Build Coastguard Worker 		goto done;
1741*663afb9bSAndroid Build Coastguard Worker 	}
1742*663afb9bSAndroid Build Coastguard Worker 	/* Prevent buf->total_len overflow */
1743*663afb9bSAndroid Build Coastguard Worker 	if (datlen > EV_SIZE_MAX - buf->total_len) {
1744*663afb9bSAndroid Build Coastguard Worker 		goto done;
1745*663afb9bSAndroid Build Coastguard Worker 	}
1746*663afb9bSAndroid Build Coastguard Worker 
1747*663afb9bSAndroid Build Coastguard Worker 	if (*buf->last_with_datap == NULL) {
1748*663afb9bSAndroid Build Coastguard Worker 		chain = buf->last;
1749*663afb9bSAndroid Build Coastguard Worker 	} else {
1750*663afb9bSAndroid Build Coastguard Worker 		chain = *buf->last_with_datap;
1751*663afb9bSAndroid Build Coastguard Worker 	}
1752*663afb9bSAndroid Build Coastguard Worker 
1753*663afb9bSAndroid Build Coastguard Worker 	/* If there are no chains allocated for this buffer, allocate one
1754*663afb9bSAndroid Build Coastguard Worker 	 * big enough to hold all the data. */
1755*663afb9bSAndroid Build Coastguard Worker 	if (chain == NULL) {
1756*663afb9bSAndroid Build Coastguard Worker 		chain = evbuffer_chain_new(datlen);
1757*663afb9bSAndroid Build Coastguard Worker 		if (!chain)
1758*663afb9bSAndroid Build Coastguard Worker 			goto done;
1759*663afb9bSAndroid Build Coastguard Worker 		evbuffer_chain_insert(buf, chain);
1760*663afb9bSAndroid Build Coastguard Worker 	}
1761*663afb9bSAndroid Build Coastguard Worker 
1762*663afb9bSAndroid Build Coastguard Worker 	if ((chain->flags & EVBUFFER_IMMUTABLE) == 0) {
1763*663afb9bSAndroid Build Coastguard Worker 		/* Always true for mutable buffers */
1764*663afb9bSAndroid Build Coastguard Worker 		EVUTIL_ASSERT(chain->misalign >= 0 &&
1765*663afb9bSAndroid Build Coastguard Worker 		    (ev_uint64_t)chain->misalign <= EVBUFFER_CHAIN_MAX);
1766*663afb9bSAndroid Build Coastguard Worker 		remain = chain->buffer_len - (size_t)chain->misalign - chain->off;
1767*663afb9bSAndroid Build Coastguard Worker 		if (remain >= datlen) {
1768*663afb9bSAndroid Build Coastguard Worker 			/* there's enough space to hold all the data in the
1769*663afb9bSAndroid Build Coastguard Worker 			 * current last chain */
1770*663afb9bSAndroid Build Coastguard Worker 			memcpy(chain->buffer + chain->misalign + chain->off,
1771*663afb9bSAndroid Build Coastguard Worker 			    data, datlen);
1772*663afb9bSAndroid Build Coastguard Worker 			chain->off += datlen;
1773*663afb9bSAndroid Build Coastguard Worker 			buf->total_len += datlen;
1774*663afb9bSAndroid Build Coastguard Worker 			buf->n_add_for_cb += datlen;
1775*663afb9bSAndroid Build Coastguard Worker 			goto out;
1776*663afb9bSAndroid Build Coastguard Worker 		} else if (!CHAIN_PINNED(chain) &&
1777*663afb9bSAndroid Build Coastguard Worker 		    evbuffer_chain_should_realign(chain, datlen)) {
1778*663afb9bSAndroid Build Coastguard Worker 			/* we can fit the data into the misalignment */
1779*663afb9bSAndroid Build Coastguard Worker 			evbuffer_chain_align(chain);
1780*663afb9bSAndroid Build Coastguard Worker 
1781*663afb9bSAndroid Build Coastguard Worker 			memcpy(chain->buffer + chain->off, data, datlen);
1782*663afb9bSAndroid Build Coastguard Worker 			chain->off += datlen;
1783*663afb9bSAndroid Build Coastguard Worker 			buf->total_len += datlen;
1784*663afb9bSAndroid Build Coastguard Worker 			buf->n_add_for_cb += datlen;
1785*663afb9bSAndroid Build Coastguard Worker 			goto out;
1786*663afb9bSAndroid Build Coastguard Worker 		}
1787*663afb9bSAndroid Build Coastguard Worker 	} else {
1788*663afb9bSAndroid Build Coastguard Worker 		/* we cannot write any data to the last chain */
1789*663afb9bSAndroid Build Coastguard Worker 		remain = 0;
1790*663afb9bSAndroid Build Coastguard Worker 	}
1791*663afb9bSAndroid Build Coastguard Worker 
1792*663afb9bSAndroid Build Coastguard Worker 	/* we need to add another chain */
1793*663afb9bSAndroid Build Coastguard Worker 	to_alloc = chain->buffer_len;
1794*663afb9bSAndroid Build Coastguard Worker 	if (to_alloc <= EVBUFFER_CHAIN_MAX_AUTO_SIZE/2)
1795*663afb9bSAndroid Build Coastguard Worker 		to_alloc <<= 1;
1796*663afb9bSAndroid Build Coastguard Worker 	if (datlen > to_alloc)
1797*663afb9bSAndroid Build Coastguard Worker 		to_alloc = datlen;
1798*663afb9bSAndroid Build Coastguard Worker 	tmp = evbuffer_chain_new(to_alloc);
1799*663afb9bSAndroid Build Coastguard Worker 	if (tmp == NULL)
1800*663afb9bSAndroid Build Coastguard Worker 		goto done;
1801*663afb9bSAndroid Build Coastguard Worker 
1802*663afb9bSAndroid Build Coastguard Worker 	if (remain) {
1803*663afb9bSAndroid Build Coastguard Worker 		memcpy(chain->buffer + chain->misalign + chain->off,
1804*663afb9bSAndroid Build Coastguard Worker 		    data, remain);
1805*663afb9bSAndroid Build Coastguard Worker 		chain->off += remain;
1806*663afb9bSAndroid Build Coastguard Worker 		buf->total_len += remain;
1807*663afb9bSAndroid Build Coastguard Worker 		buf->n_add_for_cb += remain;
1808*663afb9bSAndroid Build Coastguard Worker 	}
1809*663afb9bSAndroid Build Coastguard Worker 
1810*663afb9bSAndroid Build Coastguard Worker 	data += remain;
1811*663afb9bSAndroid Build Coastguard Worker 	datlen -= remain;
1812*663afb9bSAndroid Build Coastguard Worker 
1813*663afb9bSAndroid Build Coastguard Worker 	memcpy(tmp->buffer, data, datlen);
1814*663afb9bSAndroid Build Coastguard Worker 	tmp->off = datlen;
1815*663afb9bSAndroid Build Coastguard Worker 	evbuffer_chain_insert(buf, tmp);
1816*663afb9bSAndroid Build Coastguard Worker 	buf->n_add_for_cb += datlen;
1817*663afb9bSAndroid Build Coastguard Worker 
1818*663afb9bSAndroid Build Coastguard Worker out:
1819*663afb9bSAndroid Build Coastguard Worker 	evbuffer_invoke_callbacks_(buf);
1820*663afb9bSAndroid Build Coastguard Worker 	result = 0;
1821*663afb9bSAndroid Build Coastguard Worker done:
1822*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buf);
1823*663afb9bSAndroid Build Coastguard Worker 	return result;
1824*663afb9bSAndroid Build Coastguard Worker }
1825*663afb9bSAndroid Build Coastguard Worker 
1826*663afb9bSAndroid Build Coastguard Worker int
evbuffer_prepend(struct evbuffer * buf,const void * data,size_t datlen)1827*663afb9bSAndroid Build Coastguard Worker evbuffer_prepend(struct evbuffer *buf, const void *data, size_t datlen)
1828*663afb9bSAndroid Build Coastguard Worker {
1829*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain, *tmp;
1830*663afb9bSAndroid Build Coastguard Worker 	int result = -1;
1831*663afb9bSAndroid Build Coastguard Worker 
1832*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buf);
1833*663afb9bSAndroid Build Coastguard Worker 
1834*663afb9bSAndroid Build Coastguard Worker 	if (datlen == 0) {
1835*663afb9bSAndroid Build Coastguard Worker 		result = 0;
1836*663afb9bSAndroid Build Coastguard Worker 		goto done;
1837*663afb9bSAndroid Build Coastguard Worker 	}
1838*663afb9bSAndroid Build Coastguard Worker 	if (buf->freeze_start) {
1839*663afb9bSAndroid Build Coastguard Worker 		goto done;
1840*663afb9bSAndroid Build Coastguard Worker 	}
1841*663afb9bSAndroid Build Coastguard Worker 	if (datlen > EV_SIZE_MAX - buf->total_len) {
1842*663afb9bSAndroid Build Coastguard Worker 		goto done;
1843*663afb9bSAndroid Build Coastguard Worker 	}
1844*663afb9bSAndroid Build Coastguard Worker 
1845*663afb9bSAndroid Build Coastguard Worker 	chain = buf->first;
1846*663afb9bSAndroid Build Coastguard Worker 
1847*663afb9bSAndroid Build Coastguard Worker 	if (chain == NULL) {
1848*663afb9bSAndroid Build Coastguard Worker 		chain = evbuffer_chain_new(datlen);
1849*663afb9bSAndroid Build Coastguard Worker 		if (!chain)
1850*663afb9bSAndroid Build Coastguard Worker 			goto done;
1851*663afb9bSAndroid Build Coastguard Worker 		evbuffer_chain_insert(buf, chain);
1852*663afb9bSAndroid Build Coastguard Worker 	}
1853*663afb9bSAndroid Build Coastguard Worker 
1854*663afb9bSAndroid Build Coastguard Worker 	/* we cannot touch immutable buffers */
1855*663afb9bSAndroid Build Coastguard Worker 	if ((chain->flags & EVBUFFER_IMMUTABLE) == 0) {
1856*663afb9bSAndroid Build Coastguard Worker 		/* Always true for mutable buffers */
1857*663afb9bSAndroid Build Coastguard Worker 		EVUTIL_ASSERT(chain->misalign >= 0 &&
1858*663afb9bSAndroid Build Coastguard Worker 		    (ev_uint64_t)chain->misalign <= EVBUFFER_CHAIN_MAX);
1859*663afb9bSAndroid Build Coastguard Worker 
1860*663afb9bSAndroid Build Coastguard Worker 		/* If this chain is empty, we can treat it as
1861*663afb9bSAndroid Build Coastguard Worker 		 * 'empty at the beginning' rather than 'empty at the end' */
1862*663afb9bSAndroid Build Coastguard Worker 		if (chain->off == 0)
1863*663afb9bSAndroid Build Coastguard Worker 			chain->misalign = chain->buffer_len;
1864*663afb9bSAndroid Build Coastguard Worker 
1865*663afb9bSAndroid Build Coastguard Worker 		if ((size_t)chain->misalign >= datlen) {
1866*663afb9bSAndroid Build Coastguard Worker 			/* we have enough space to fit everything */
1867*663afb9bSAndroid Build Coastguard Worker 			memcpy(chain->buffer + chain->misalign - datlen,
1868*663afb9bSAndroid Build Coastguard Worker 			    data, datlen);
1869*663afb9bSAndroid Build Coastguard Worker 			chain->off += datlen;
1870*663afb9bSAndroid Build Coastguard Worker 			chain->misalign -= datlen;
1871*663afb9bSAndroid Build Coastguard Worker 			buf->total_len += datlen;
1872*663afb9bSAndroid Build Coastguard Worker 			buf->n_add_for_cb += datlen;
1873*663afb9bSAndroid Build Coastguard Worker 			goto out;
1874*663afb9bSAndroid Build Coastguard Worker 		} else if (chain->misalign) {
1875*663afb9bSAndroid Build Coastguard Worker 			/* we can only fit some of the data. */
1876*663afb9bSAndroid Build Coastguard Worker 			memcpy(chain->buffer,
1877*663afb9bSAndroid Build Coastguard Worker 			    (char*)data + datlen - chain->misalign,
1878*663afb9bSAndroid Build Coastguard Worker 			    (size_t)chain->misalign);
1879*663afb9bSAndroid Build Coastguard Worker 			chain->off += (size_t)chain->misalign;
1880*663afb9bSAndroid Build Coastguard Worker 			buf->total_len += (size_t)chain->misalign;
1881*663afb9bSAndroid Build Coastguard Worker 			buf->n_add_for_cb += (size_t)chain->misalign;
1882*663afb9bSAndroid Build Coastguard Worker 			datlen -= (size_t)chain->misalign;
1883*663afb9bSAndroid Build Coastguard Worker 			chain->misalign = 0;
1884*663afb9bSAndroid Build Coastguard Worker 		}
1885*663afb9bSAndroid Build Coastguard Worker 	}
1886*663afb9bSAndroid Build Coastguard Worker 
1887*663afb9bSAndroid Build Coastguard Worker 	/* we need to add another chain */
1888*663afb9bSAndroid Build Coastguard Worker 	if ((tmp = evbuffer_chain_new(datlen)) == NULL)
1889*663afb9bSAndroid Build Coastguard Worker 		goto done;
1890*663afb9bSAndroid Build Coastguard Worker 	buf->first = tmp;
1891*663afb9bSAndroid Build Coastguard Worker 	if (buf->last_with_datap == &buf->first && chain->off)
1892*663afb9bSAndroid Build Coastguard Worker 		buf->last_with_datap = &tmp->next;
1893*663afb9bSAndroid Build Coastguard Worker 
1894*663afb9bSAndroid Build Coastguard Worker 	tmp->next = chain;
1895*663afb9bSAndroid Build Coastguard Worker 
1896*663afb9bSAndroid Build Coastguard Worker 	tmp->off = datlen;
1897*663afb9bSAndroid Build Coastguard Worker 	EVUTIL_ASSERT(datlen <= tmp->buffer_len);
1898*663afb9bSAndroid Build Coastguard Worker 	tmp->misalign = tmp->buffer_len - datlen;
1899*663afb9bSAndroid Build Coastguard Worker 
1900*663afb9bSAndroid Build Coastguard Worker 	memcpy(tmp->buffer + tmp->misalign, data, datlen);
1901*663afb9bSAndroid Build Coastguard Worker 	buf->total_len += datlen;
1902*663afb9bSAndroid Build Coastguard Worker 	buf->n_add_for_cb += datlen;
1903*663afb9bSAndroid Build Coastguard Worker 
1904*663afb9bSAndroid Build Coastguard Worker out:
1905*663afb9bSAndroid Build Coastguard Worker 	evbuffer_invoke_callbacks_(buf);
1906*663afb9bSAndroid Build Coastguard Worker 	result = 0;
1907*663afb9bSAndroid Build Coastguard Worker done:
1908*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buf);
1909*663afb9bSAndroid Build Coastguard Worker 	return result;
1910*663afb9bSAndroid Build Coastguard Worker }
1911*663afb9bSAndroid Build Coastguard Worker 
1912*663afb9bSAndroid Build Coastguard Worker /** Helper: realigns the memory in chain->buffer so that misalign is 0. */
1913*663afb9bSAndroid Build Coastguard Worker static void
evbuffer_chain_align(struct evbuffer_chain * chain)1914*663afb9bSAndroid Build Coastguard Worker evbuffer_chain_align(struct evbuffer_chain *chain)
1915*663afb9bSAndroid Build Coastguard Worker {
1916*663afb9bSAndroid Build Coastguard Worker 	EVUTIL_ASSERT(!(chain->flags & EVBUFFER_IMMUTABLE));
1917*663afb9bSAndroid Build Coastguard Worker 	EVUTIL_ASSERT(!(chain->flags & EVBUFFER_MEM_PINNED_ANY));
1918*663afb9bSAndroid Build Coastguard Worker 	memmove(chain->buffer, chain->buffer + chain->misalign, chain->off);
1919*663afb9bSAndroid Build Coastguard Worker 	chain->misalign = 0;
1920*663afb9bSAndroid Build Coastguard Worker }
1921*663afb9bSAndroid Build Coastguard Worker 
1922*663afb9bSAndroid Build Coastguard Worker #define MAX_TO_COPY_IN_EXPAND 4096
1923*663afb9bSAndroid Build Coastguard Worker #define MAX_TO_REALIGN_IN_EXPAND 2048
1924*663afb9bSAndroid Build Coastguard Worker 
1925*663afb9bSAndroid Build Coastguard Worker /** Helper: return true iff we should realign chain to fit datalen bytes of
1926*663afb9bSAndroid Build Coastguard Worker     data in it. */
1927*663afb9bSAndroid Build Coastguard Worker static int
evbuffer_chain_should_realign(struct evbuffer_chain * chain,size_t datlen)1928*663afb9bSAndroid Build Coastguard Worker evbuffer_chain_should_realign(struct evbuffer_chain *chain,
1929*663afb9bSAndroid Build Coastguard Worker     size_t datlen)
1930*663afb9bSAndroid Build Coastguard Worker {
1931*663afb9bSAndroid Build Coastguard Worker 	return chain->buffer_len - chain->off >= datlen &&
1932*663afb9bSAndroid Build Coastguard Worker 	    (chain->off < chain->buffer_len / 2) &&
1933*663afb9bSAndroid Build Coastguard Worker 	    (chain->off <= MAX_TO_REALIGN_IN_EXPAND);
1934*663afb9bSAndroid Build Coastguard Worker }
1935*663afb9bSAndroid Build Coastguard Worker 
1936*663afb9bSAndroid Build Coastguard Worker /* Expands the available space in the event buffer to at least datlen, all in
1937*663afb9bSAndroid Build Coastguard Worker  * a single chunk.  Return that chunk. */
1938*663afb9bSAndroid Build Coastguard Worker static struct evbuffer_chain *
evbuffer_expand_singlechain(struct evbuffer * buf,size_t datlen)1939*663afb9bSAndroid Build Coastguard Worker evbuffer_expand_singlechain(struct evbuffer *buf, size_t datlen)
1940*663afb9bSAndroid Build Coastguard Worker {
1941*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain, **chainp;
1942*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *result = NULL;
1943*663afb9bSAndroid Build Coastguard Worker 	ASSERT_EVBUFFER_LOCKED(buf);
1944*663afb9bSAndroid Build Coastguard Worker 
1945*663afb9bSAndroid Build Coastguard Worker 	chainp = buf->last_with_datap;
1946*663afb9bSAndroid Build Coastguard Worker 
1947*663afb9bSAndroid Build Coastguard Worker 	/* XXX If *chainp is no longer writeable, but has enough space in its
1948*663afb9bSAndroid Build Coastguard Worker 	 * misalign, this might be a bad idea: we could still use *chainp, not
1949*663afb9bSAndroid Build Coastguard Worker 	 * (*chainp)->next. */
1950*663afb9bSAndroid Build Coastguard Worker 	if (*chainp && CHAIN_SPACE_LEN(*chainp) == 0)
1951*663afb9bSAndroid Build Coastguard Worker 		chainp = &(*chainp)->next;
1952*663afb9bSAndroid Build Coastguard Worker 
1953*663afb9bSAndroid Build Coastguard Worker 	/* 'chain' now points to the first chain with writable space (if any)
1954*663afb9bSAndroid Build Coastguard Worker 	 * We will either use it, realign it, replace it, or resize it. */
1955*663afb9bSAndroid Build Coastguard Worker 	chain = *chainp;
1956*663afb9bSAndroid Build Coastguard Worker 
1957*663afb9bSAndroid Build Coastguard Worker 	if (chain == NULL ||
1958*663afb9bSAndroid Build Coastguard Worker 	    (chain->flags & (EVBUFFER_IMMUTABLE|EVBUFFER_MEM_PINNED_ANY))) {
1959*663afb9bSAndroid Build Coastguard Worker 		/* We can't use the last_with_data chain at all.  Just add a
1960*663afb9bSAndroid Build Coastguard Worker 		 * new one that's big enough. */
1961*663afb9bSAndroid Build Coastguard Worker 		goto insert_new;
1962*663afb9bSAndroid Build Coastguard Worker 	}
1963*663afb9bSAndroid Build Coastguard Worker 
1964*663afb9bSAndroid Build Coastguard Worker 	/* If we can fit all the data, then we don't have to do anything */
1965*663afb9bSAndroid Build Coastguard Worker 	if (CHAIN_SPACE_LEN(chain) >= datlen) {
1966*663afb9bSAndroid Build Coastguard Worker 		result = chain;
1967*663afb9bSAndroid Build Coastguard Worker 		goto ok;
1968*663afb9bSAndroid Build Coastguard Worker 	}
1969*663afb9bSAndroid Build Coastguard Worker 
1970*663afb9bSAndroid Build Coastguard Worker 	/* If the chain is completely empty, just replace it by adding a new
1971*663afb9bSAndroid Build Coastguard Worker 	 * empty chain. */
1972*663afb9bSAndroid Build Coastguard Worker 	if (chain->off == 0) {
1973*663afb9bSAndroid Build Coastguard Worker 		goto insert_new;
1974*663afb9bSAndroid Build Coastguard Worker 	}
1975*663afb9bSAndroid Build Coastguard Worker 
1976*663afb9bSAndroid Build Coastguard Worker 	/* If the misalignment plus the remaining space fulfills our data
1977*663afb9bSAndroid Build Coastguard Worker 	 * needs, we could just force an alignment to happen.  Afterwards, we
1978*663afb9bSAndroid Build Coastguard Worker 	 * have enough space.  But only do this if we're saving a lot of space
1979*663afb9bSAndroid Build Coastguard Worker 	 * and not moving too much data.  Otherwise the space savings are
1980*663afb9bSAndroid Build Coastguard Worker 	 * probably offset by the time lost in copying.
1981*663afb9bSAndroid Build Coastguard Worker 	 */
1982*663afb9bSAndroid Build Coastguard Worker 	if (evbuffer_chain_should_realign(chain, datlen)) {
1983*663afb9bSAndroid Build Coastguard Worker 		evbuffer_chain_align(chain);
1984*663afb9bSAndroid Build Coastguard Worker 		result = chain;
1985*663afb9bSAndroid Build Coastguard Worker 		goto ok;
1986*663afb9bSAndroid Build Coastguard Worker 	}
1987*663afb9bSAndroid Build Coastguard Worker 
1988*663afb9bSAndroid Build Coastguard Worker 	/* At this point, we can either resize the last chunk with space in
1989*663afb9bSAndroid Build Coastguard Worker 	 * it, use the next chunk after it, or   If we add a new chunk, we waste
1990*663afb9bSAndroid Build Coastguard Worker 	 * CHAIN_SPACE_LEN(chain) bytes in the former last chunk.  If we
1991*663afb9bSAndroid Build Coastguard Worker 	 * resize, we have to copy chain->off bytes.
1992*663afb9bSAndroid Build Coastguard Worker 	 */
1993*663afb9bSAndroid Build Coastguard Worker 
1994*663afb9bSAndroid Build Coastguard Worker 	/* Would expanding this chunk be affordable and worthwhile? */
1995*663afb9bSAndroid Build Coastguard Worker 	if (CHAIN_SPACE_LEN(chain) < chain->buffer_len / 8 ||
1996*663afb9bSAndroid Build Coastguard Worker 	    chain->off > MAX_TO_COPY_IN_EXPAND ||
1997*663afb9bSAndroid Build Coastguard Worker 		datlen >= (EVBUFFER_CHAIN_MAX - chain->off)) {
1998*663afb9bSAndroid Build Coastguard Worker 		/* It's not worth resizing this chain. Can the next one be
1999*663afb9bSAndroid Build Coastguard Worker 		 * used? */
2000*663afb9bSAndroid Build Coastguard Worker 		if (chain->next && CHAIN_SPACE_LEN(chain->next) >= datlen) {
2001*663afb9bSAndroid Build Coastguard Worker 			/* Yes, we can just use the next chain (which should
2002*663afb9bSAndroid Build Coastguard Worker 			 * be empty. */
2003*663afb9bSAndroid Build Coastguard Worker 			result = chain->next;
2004*663afb9bSAndroid Build Coastguard Worker 			goto ok;
2005*663afb9bSAndroid Build Coastguard Worker 		} else {
2006*663afb9bSAndroid Build Coastguard Worker 			/* No; append a new chain (which will free all
2007*663afb9bSAndroid Build Coastguard Worker 			 * terminal empty chains.) */
2008*663afb9bSAndroid Build Coastguard Worker 			goto insert_new;
2009*663afb9bSAndroid Build Coastguard Worker 		}
2010*663afb9bSAndroid Build Coastguard Worker 	} else {
2011*663afb9bSAndroid Build Coastguard Worker 		/* Okay, we're going to try to resize this chain: Not doing so
2012*663afb9bSAndroid Build Coastguard Worker 		 * would waste at least 1/8 of its current allocation, and we
2013*663afb9bSAndroid Build Coastguard Worker 		 * can do so without having to copy more than
2014*663afb9bSAndroid Build Coastguard Worker 		 * MAX_TO_COPY_IN_EXPAND bytes. */
2015*663afb9bSAndroid Build Coastguard Worker 		/* figure out how much space we need */
2016*663afb9bSAndroid Build Coastguard Worker 		size_t length = chain->off + datlen;
2017*663afb9bSAndroid Build Coastguard Worker 		struct evbuffer_chain *tmp = evbuffer_chain_new(length);
2018*663afb9bSAndroid Build Coastguard Worker 		if (tmp == NULL)
2019*663afb9bSAndroid Build Coastguard Worker 			goto err;
2020*663afb9bSAndroid Build Coastguard Worker 
2021*663afb9bSAndroid Build Coastguard Worker 		/* copy the data over that we had so far */
2022*663afb9bSAndroid Build Coastguard Worker 		tmp->off = chain->off;
2023*663afb9bSAndroid Build Coastguard Worker 		memcpy(tmp->buffer, chain->buffer + chain->misalign,
2024*663afb9bSAndroid Build Coastguard Worker 		    chain->off);
2025*663afb9bSAndroid Build Coastguard Worker 		/* fix up the list */
2026*663afb9bSAndroid Build Coastguard Worker 		EVUTIL_ASSERT(*chainp == chain);
2027*663afb9bSAndroid Build Coastguard Worker 		result = *chainp = tmp;
2028*663afb9bSAndroid Build Coastguard Worker 
2029*663afb9bSAndroid Build Coastguard Worker 		if (buf->last == chain)
2030*663afb9bSAndroid Build Coastguard Worker 			buf->last = tmp;
2031*663afb9bSAndroid Build Coastguard Worker 
2032*663afb9bSAndroid Build Coastguard Worker 		tmp->next = chain->next;
2033*663afb9bSAndroid Build Coastguard Worker 		evbuffer_chain_free(chain);
2034*663afb9bSAndroid Build Coastguard Worker 		goto ok;
2035*663afb9bSAndroid Build Coastguard Worker 	}
2036*663afb9bSAndroid Build Coastguard Worker 
2037*663afb9bSAndroid Build Coastguard Worker insert_new:
2038*663afb9bSAndroid Build Coastguard Worker 	result = evbuffer_chain_insert_new(buf, datlen);
2039*663afb9bSAndroid Build Coastguard Worker 	if (!result)
2040*663afb9bSAndroid Build Coastguard Worker 		goto err;
2041*663afb9bSAndroid Build Coastguard Worker ok:
2042*663afb9bSAndroid Build Coastguard Worker 	EVUTIL_ASSERT(result);
2043*663afb9bSAndroid Build Coastguard Worker 	EVUTIL_ASSERT(CHAIN_SPACE_LEN(result) >= datlen);
2044*663afb9bSAndroid Build Coastguard Worker err:
2045*663afb9bSAndroid Build Coastguard Worker 	return result;
2046*663afb9bSAndroid Build Coastguard Worker }
2047*663afb9bSAndroid Build Coastguard Worker 
2048*663afb9bSAndroid Build Coastguard Worker /* Make sure that datlen bytes are available for writing in the last n
2049*663afb9bSAndroid Build Coastguard Worker  * chains.  Never copies or moves data. */
2050*663afb9bSAndroid Build Coastguard Worker int
evbuffer_expand_fast_(struct evbuffer * buf,size_t datlen,int n)2051*663afb9bSAndroid Build Coastguard Worker evbuffer_expand_fast_(struct evbuffer *buf, size_t datlen, int n)
2052*663afb9bSAndroid Build Coastguard Worker {
2053*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain = buf->last, *tmp, *next;
2054*663afb9bSAndroid Build Coastguard Worker 	size_t avail;
2055*663afb9bSAndroid Build Coastguard Worker 	int used;
2056*663afb9bSAndroid Build Coastguard Worker 
2057*663afb9bSAndroid Build Coastguard Worker 	ASSERT_EVBUFFER_LOCKED(buf);
2058*663afb9bSAndroid Build Coastguard Worker 	EVUTIL_ASSERT(n >= 2);
2059*663afb9bSAndroid Build Coastguard Worker 
2060*663afb9bSAndroid Build Coastguard Worker 	if (chain == NULL || (chain->flags & EVBUFFER_IMMUTABLE)) {
2061*663afb9bSAndroid Build Coastguard Worker 		/* There is no last chunk, or we can't touch the last chunk.
2062*663afb9bSAndroid Build Coastguard Worker 		 * Just add a new chunk. */
2063*663afb9bSAndroid Build Coastguard Worker 		chain = evbuffer_chain_new(datlen);
2064*663afb9bSAndroid Build Coastguard Worker 		if (chain == NULL)
2065*663afb9bSAndroid Build Coastguard Worker 			return (-1);
2066*663afb9bSAndroid Build Coastguard Worker 
2067*663afb9bSAndroid Build Coastguard Worker 		evbuffer_chain_insert(buf, chain);
2068*663afb9bSAndroid Build Coastguard Worker 		return (0);
2069*663afb9bSAndroid Build Coastguard Worker 	}
2070*663afb9bSAndroid Build Coastguard Worker 
2071*663afb9bSAndroid Build Coastguard Worker 	used = 0; /* number of chains we're using space in. */
2072*663afb9bSAndroid Build Coastguard Worker 	avail = 0; /* how much space they have. */
2073*663afb9bSAndroid Build Coastguard Worker 	/* How many bytes can we stick at the end of buffer as it is?  Iterate
2074*663afb9bSAndroid Build Coastguard Worker 	 * over the chains at the end of the buffer, tring to see how much
2075*663afb9bSAndroid Build Coastguard Worker 	 * space we have in the first n. */
2076*663afb9bSAndroid Build Coastguard Worker 	for (chain = *buf->last_with_datap; chain; chain = chain->next) {
2077*663afb9bSAndroid Build Coastguard Worker 		if (chain->off) {
2078*663afb9bSAndroid Build Coastguard Worker 			size_t space = (size_t) CHAIN_SPACE_LEN(chain);
2079*663afb9bSAndroid Build Coastguard Worker 			EVUTIL_ASSERT(chain == *buf->last_with_datap);
2080*663afb9bSAndroid Build Coastguard Worker 			if (space) {
2081*663afb9bSAndroid Build Coastguard Worker 				avail += space;
2082*663afb9bSAndroid Build Coastguard Worker 				++used;
2083*663afb9bSAndroid Build Coastguard Worker 			}
2084*663afb9bSAndroid Build Coastguard Worker 		} else {
2085*663afb9bSAndroid Build Coastguard Worker 			/* No data in chain; realign it. */
2086*663afb9bSAndroid Build Coastguard Worker 			chain->misalign = 0;
2087*663afb9bSAndroid Build Coastguard Worker 			avail += chain->buffer_len;
2088*663afb9bSAndroid Build Coastguard Worker 			++used;
2089*663afb9bSAndroid Build Coastguard Worker 		}
2090*663afb9bSAndroid Build Coastguard Worker 		if (avail >= datlen) {
2091*663afb9bSAndroid Build Coastguard Worker 			/* There is already enough space.  Just return */
2092*663afb9bSAndroid Build Coastguard Worker 			return (0);
2093*663afb9bSAndroid Build Coastguard Worker 		}
2094*663afb9bSAndroid Build Coastguard Worker 		if (used == n)
2095*663afb9bSAndroid Build Coastguard Worker 			break;
2096*663afb9bSAndroid Build Coastguard Worker 	}
2097*663afb9bSAndroid Build Coastguard Worker 
2098*663afb9bSAndroid Build Coastguard Worker 	/* There wasn't enough space in the first n chains with space in
2099*663afb9bSAndroid Build Coastguard Worker 	 * them. Either add a new chain with enough space, or replace all
2100*663afb9bSAndroid Build Coastguard Worker 	 * empty chains with one that has enough space, depending on n. */
2101*663afb9bSAndroid Build Coastguard Worker 	if (used < n) {
2102*663afb9bSAndroid Build Coastguard Worker 		/* The loop ran off the end of the chains before it hit n
2103*663afb9bSAndroid Build Coastguard Worker 		 * chains; we can add another. */
2104*663afb9bSAndroid Build Coastguard Worker 		EVUTIL_ASSERT(chain == NULL);
2105*663afb9bSAndroid Build Coastguard Worker 
2106*663afb9bSAndroid Build Coastguard Worker 		tmp = evbuffer_chain_new(datlen - avail);
2107*663afb9bSAndroid Build Coastguard Worker 		if (tmp == NULL)
2108*663afb9bSAndroid Build Coastguard Worker 			return (-1);
2109*663afb9bSAndroid Build Coastguard Worker 
2110*663afb9bSAndroid Build Coastguard Worker 		buf->last->next = tmp;
2111*663afb9bSAndroid Build Coastguard Worker 		buf->last = tmp;
2112*663afb9bSAndroid Build Coastguard Worker 		/* (we would only set last_with_data if we added the first
2113*663afb9bSAndroid Build Coastguard Worker 		 * chain. But if the buffer had no chains, we would have
2114*663afb9bSAndroid Build Coastguard Worker 		 * just allocated a new chain earlier) */
2115*663afb9bSAndroid Build Coastguard Worker 		return (0);
2116*663afb9bSAndroid Build Coastguard Worker 	} else {
2117*663afb9bSAndroid Build Coastguard Worker 		/* Nuke _all_ the empty chains. */
2118*663afb9bSAndroid Build Coastguard Worker 		int rmv_all = 0; /* True iff we removed last_with_data. */
2119*663afb9bSAndroid Build Coastguard Worker 		chain = *buf->last_with_datap;
2120*663afb9bSAndroid Build Coastguard Worker 		if (!chain->off) {
2121*663afb9bSAndroid Build Coastguard Worker 			EVUTIL_ASSERT(chain == buf->first);
2122*663afb9bSAndroid Build Coastguard Worker 			rmv_all = 1;
2123*663afb9bSAndroid Build Coastguard Worker 			avail = 0;
2124*663afb9bSAndroid Build Coastguard Worker 		} else {
2125*663afb9bSAndroid Build Coastguard Worker 			/* can't overflow, since only mutable chains have
2126*663afb9bSAndroid Build Coastguard Worker 			 * huge misaligns. */
2127*663afb9bSAndroid Build Coastguard Worker 			avail = (size_t) CHAIN_SPACE_LEN(chain);
2128*663afb9bSAndroid Build Coastguard Worker 			chain = chain->next;
2129*663afb9bSAndroid Build Coastguard Worker 		}
2130*663afb9bSAndroid Build Coastguard Worker 
2131*663afb9bSAndroid Build Coastguard Worker 
2132*663afb9bSAndroid Build Coastguard Worker 		for (; chain; chain = next) {
2133*663afb9bSAndroid Build Coastguard Worker 			next = chain->next;
2134*663afb9bSAndroid Build Coastguard Worker 			EVUTIL_ASSERT(chain->off == 0);
2135*663afb9bSAndroid Build Coastguard Worker 			evbuffer_chain_free(chain);
2136*663afb9bSAndroid Build Coastguard Worker 		}
2137*663afb9bSAndroid Build Coastguard Worker 		EVUTIL_ASSERT(datlen >= avail);
2138*663afb9bSAndroid Build Coastguard Worker 		tmp = evbuffer_chain_new(datlen - avail);
2139*663afb9bSAndroid Build Coastguard Worker 		if (tmp == NULL) {
2140*663afb9bSAndroid Build Coastguard Worker 			if (rmv_all) {
2141*663afb9bSAndroid Build Coastguard Worker 				ZERO_CHAIN(buf);
2142*663afb9bSAndroid Build Coastguard Worker 			} else {
2143*663afb9bSAndroid Build Coastguard Worker 				buf->last = *buf->last_with_datap;
2144*663afb9bSAndroid Build Coastguard Worker 				(*buf->last_with_datap)->next = NULL;
2145*663afb9bSAndroid Build Coastguard Worker 			}
2146*663afb9bSAndroid Build Coastguard Worker 			return (-1);
2147*663afb9bSAndroid Build Coastguard Worker 		}
2148*663afb9bSAndroid Build Coastguard Worker 
2149*663afb9bSAndroid Build Coastguard Worker 		if (rmv_all) {
2150*663afb9bSAndroid Build Coastguard Worker 			buf->first = buf->last = tmp;
2151*663afb9bSAndroid Build Coastguard Worker 			buf->last_with_datap = &buf->first;
2152*663afb9bSAndroid Build Coastguard Worker 		} else {
2153*663afb9bSAndroid Build Coastguard Worker 			(*buf->last_with_datap)->next = tmp;
2154*663afb9bSAndroid Build Coastguard Worker 			buf->last = tmp;
2155*663afb9bSAndroid Build Coastguard Worker 		}
2156*663afb9bSAndroid Build Coastguard Worker 		return (0);
2157*663afb9bSAndroid Build Coastguard Worker 	}
2158*663afb9bSAndroid Build Coastguard Worker }
2159*663afb9bSAndroid Build Coastguard Worker 
2160*663afb9bSAndroid Build Coastguard Worker int
evbuffer_expand(struct evbuffer * buf,size_t datlen)2161*663afb9bSAndroid Build Coastguard Worker evbuffer_expand(struct evbuffer *buf, size_t datlen)
2162*663afb9bSAndroid Build Coastguard Worker {
2163*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain;
2164*663afb9bSAndroid Build Coastguard Worker 
2165*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buf);
2166*663afb9bSAndroid Build Coastguard Worker 	chain = evbuffer_expand_singlechain(buf, datlen);
2167*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buf);
2168*663afb9bSAndroid Build Coastguard Worker 	return chain ? 0 : -1;
2169*663afb9bSAndroid Build Coastguard Worker }
2170*663afb9bSAndroid Build Coastguard Worker 
2171*663afb9bSAndroid Build Coastguard Worker /*
2172*663afb9bSAndroid Build Coastguard Worker  * Reads data from a file descriptor into a buffer.
2173*663afb9bSAndroid Build Coastguard Worker  */
2174*663afb9bSAndroid Build Coastguard Worker 
2175*663afb9bSAndroid Build Coastguard Worker #if defined(EVENT__HAVE_SYS_UIO_H) || defined(_WIN32)
2176*663afb9bSAndroid Build Coastguard Worker #define USE_IOVEC_IMPL
2177*663afb9bSAndroid Build Coastguard Worker #endif
2178*663afb9bSAndroid Build Coastguard Worker 
2179*663afb9bSAndroid Build Coastguard Worker #ifdef USE_IOVEC_IMPL
2180*663afb9bSAndroid Build Coastguard Worker 
2181*663afb9bSAndroid Build Coastguard Worker #ifdef EVENT__HAVE_SYS_UIO_H
2182*663afb9bSAndroid Build Coastguard Worker /* number of iovec we use for writev, fragmentation is going to determine
2183*663afb9bSAndroid Build Coastguard Worker  * how much we end up writing */
2184*663afb9bSAndroid Build Coastguard Worker 
2185*663afb9bSAndroid Build Coastguard Worker #define DEFAULT_WRITE_IOVEC 128
2186*663afb9bSAndroid Build Coastguard Worker 
2187*663afb9bSAndroid Build Coastguard Worker #if defined(UIO_MAXIOV) && UIO_MAXIOV < DEFAULT_WRITE_IOVEC
2188*663afb9bSAndroid Build Coastguard Worker #define NUM_WRITE_IOVEC UIO_MAXIOV
2189*663afb9bSAndroid Build Coastguard Worker #elif defined(IOV_MAX) && IOV_MAX < DEFAULT_WRITE_IOVEC
2190*663afb9bSAndroid Build Coastguard Worker #define NUM_WRITE_IOVEC IOV_MAX
2191*663afb9bSAndroid Build Coastguard Worker #else
2192*663afb9bSAndroid Build Coastguard Worker #define NUM_WRITE_IOVEC DEFAULT_WRITE_IOVEC
2193*663afb9bSAndroid Build Coastguard Worker #endif
2194*663afb9bSAndroid Build Coastguard Worker 
2195*663afb9bSAndroid Build Coastguard Worker #define IOV_TYPE struct iovec
2196*663afb9bSAndroid Build Coastguard Worker #define IOV_PTR_FIELD iov_base
2197*663afb9bSAndroid Build Coastguard Worker #define IOV_LEN_FIELD iov_len
2198*663afb9bSAndroid Build Coastguard Worker #define IOV_LEN_TYPE size_t
2199*663afb9bSAndroid Build Coastguard Worker #else
2200*663afb9bSAndroid Build Coastguard Worker #define NUM_WRITE_IOVEC 16
2201*663afb9bSAndroid Build Coastguard Worker #define IOV_TYPE WSABUF
2202*663afb9bSAndroid Build Coastguard Worker #define IOV_PTR_FIELD buf
2203*663afb9bSAndroid Build Coastguard Worker #define IOV_LEN_FIELD len
2204*663afb9bSAndroid Build Coastguard Worker #define IOV_LEN_TYPE unsigned long
2205*663afb9bSAndroid Build Coastguard Worker #endif
2206*663afb9bSAndroid Build Coastguard Worker #endif
2207*663afb9bSAndroid Build Coastguard Worker #define NUM_READ_IOVEC 4
2208*663afb9bSAndroid Build Coastguard Worker 
2209*663afb9bSAndroid Build Coastguard Worker #define EVBUFFER_MAX_READ	4096
2210*663afb9bSAndroid Build Coastguard Worker 
2211*663afb9bSAndroid Build Coastguard Worker /** Helper function to figure out which space to use for reading data into
2212*663afb9bSAndroid Build Coastguard Worker     an evbuffer.  Internal use only.
2213*663afb9bSAndroid Build Coastguard Worker 
2214*663afb9bSAndroid Build Coastguard Worker     @param buf The buffer to read into
2215*663afb9bSAndroid Build Coastguard Worker     @param howmuch How much we want to read.
2216*663afb9bSAndroid Build Coastguard Worker     @param vecs An array of two or more iovecs or WSABUFs.
2217*663afb9bSAndroid Build Coastguard Worker     @param n_vecs_avail The length of vecs
2218*663afb9bSAndroid Build Coastguard Worker     @param chainp A pointer to a variable to hold the first chain we're
2219*663afb9bSAndroid Build Coastguard Worker       reading into.
2220*663afb9bSAndroid Build Coastguard Worker     @param exact Boolean: if true, we do not provide more than 'howmuch'
2221*663afb9bSAndroid Build Coastguard Worker       space in the vectors, even if more space is available.
2222*663afb9bSAndroid Build Coastguard Worker     @return The number of buffers we're using.
2223*663afb9bSAndroid Build Coastguard Worker  */
2224*663afb9bSAndroid Build Coastguard Worker int
evbuffer_read_setup_vecs_(struct evbuffer * buf,ev_ssize_t howmuch,struct evbuffer_iovec * vecs,int n_vecs_avail,struct evbuffer_chain *** chainp,int exact)2225*663afb9bSAndroid Build Coastguard Worker evbuffer_read_setup_vecs_(struct evbuffer *buf, ev_ssize_t howmuch,
2226*663afb9bSAndroid Build Coastguard Worker     struct evbuffer_iovec *vecs, int n_vecs_avail,
2227*663afb9bSAndroid Build Coastguard Worker     struct evbuffer_chain ***chainp, int exact)
2228*663afb9bSAndroid Build Coastguard Worker {
2229*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain;
2230*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain **firstchainp;
2231*663afb9bSAndroid Build Coastguard Worker 	size_t so_far;
2232*663afb9bSAndroid Build Coastguard Worker 	int i;
2233*663afb9bSAndroid Build Coastguard Worker 	ASSERT_EVBUFFER_LOCKED(buf);
2234*663afb9bSAndroid Build Coastguard Worker 
2235*663afb9bSAndroid Build Coastguard Worker 	if (howmuch < 0)
2236*663afb9bSAndroid Build Coastguard Worker 		return -1;
2237*663afb9bSAndroid Build Coastguard Worker 
2238*663afb9bSAndroid Build Coastguard Worker 	so_far = 0;
2239*663afb9bSAndroid Build Coastguard Worker 	/* Let firstchain be the first chain with any space on it */
2240*663afb9bSAndroid Build Coastguard Worker 	firstchainp = buf->last_with_datap;
2241*663afb9bSAndroid Build Coastguard Worker 	EVUTIL_ASSERT(*firstchainp);
2242*663afb9bSAndroid Build Coastguard Worker 	if (CHAIN_SPACE_LEN(*firstchainp) == 0) {
2243*663afb9bSAndroid Build Coastguard Worker 		firstchainp = &(*firstchainp)->next;
2244*663afb9bSAndroid Build Coastguard Worker 	}
2245*663afb9bSAndroid Build Coastguard Worker 
2246*663afb9bSAndroid Build Coastguard Worker 	chain = *firstchainp;
2247*663afb9bSAndroid Build Coastguard Worker 	EVUTIL_ASSERT(chain);
2248*663afb9bSAndroid Build Coastguard Worker 	for (i = 0; i < n_vecs_avail && so_far < (size_t)howmuch; ++i) {
2249*663afb9bSAndroid Build Coastguard Worker 		size_t avail = (size_t) CHAIN_SPACE_LEN(chain);
2250*663afb9bSAndroid Build Coastguard Worker 		if (avail > (howmuch - so_far) && exact)
2251*663afb9bSAndroid Build Coastguard Worker 			avail = howmuch - so_far;
2252*663afb9bSAndroid Build Coastguard Worker 		vecs[i].iov_base = (void *)CHAIN_SPACE_PTR(chain);
2253*663afb9bSAndroid Build Coastguard Worker 		vecs[i].iov_len = avail;
2254*663afb9bSAndroid Build Coastguard Worker 		so_far += avail;
2255*663afb9bSAndroid Build Coastguard Worker 		chain = chain->next;
2256*663afb9bSAndroid Build Coastguard Worker 	}
2257*663afb9bSAndroid Build Coastguard Worker 
2258*663afb9bSAndroid Build Coastguard Worker 	*chainp = firstchainp;
2259*663afb9bSAndroid Build Coastguard Worker 	return i;
2260*663afb9bSAndroid Build Coastguard Worker }
2261*663afb9bSAndroid Build Coastguard Worker 
2262*663afb9bSAndroid Build Coastguard Worker static int
get_n_bytes_readable_on_socket(evutil_socket_t fd)2263*663afb9bSAndroid Build Coastguard Worker get_n_bytes_readable_on_socket(evutil_socket_t fd)
2264*663afb9bSAndroid Build Coastguard Worker {
2265*663afb9bSAndroid Build Coastguard Worker #if defined(FIONREAD) && defined(_WIN32)
2266*663afb9bSAndroid Build Coastguard Worker 	unsigned long lng = EVBUFFER_MAX_READ;
2267*663afb9bSAndroid Build Coastguard Worker 	if (ioctlsocket(fd, FIONREAD, &lng) < 0)
2268*663afb9bSAndroid Build Coastguard Worker 		return -1;
2269*663afb9bSAndroid Build Coastguard Worker 	/* Can overflow, but mostly harmlessly. XXXX */
2270*663afb9bSAndroid Build Coastguard Worker 	return (int)lng;
2271*663afb9bSAndroid Build Coastguard Worker #elif defined(FIONREAD)
2272*663afb9bSAndroid Build Coastguard Worker 	int n = EVBUFFER_MAX_READ;
2273*663afb9bSAndroid Build Coastguard Worker 	if (ioctl(fd, FIONREAD, &n) < 0)
2274*663afb9bSAndroid Build Coastguard Worker 		return -1;
2275*663afb9bSAndroid Build Coastguard Worker 	return n;
2276*663afb9bSAndroid Build Coastguard Worker #else
2277*663afb9bSAndroid Build Coastguard Worker 	return EVBUFFER_MAX_READ;
2278*663afb9bSAndroid Build Coastguard Worker #endif
2279*663afb9bSAndroid Build Coastguard Worker }
2280*663afb9bSAndroid Build Coastguard Worker 
2281*663afb9bSAndroid Build Coastguard Worker /* TODO(niels): should this function return ev_ssize_t and take ev_ssize_t
2282*663afb9bSAndroid Build Coastguard Worker  * as howmuch? */
2283*663afb9bSAndroid Build Coastguard Worker int
evbuffer_read(struct evbuffer * buf,evutil_socket_t fd,int howmuch)2284*663afb9bSAndroid Build Coastguard Worker evbuffer_read(struct evbuffer *buf, evutil_socket_t fd, int howmuch)
2285*663afb9bSAndroid Build Coastguard Worker {
2286*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain **chainp;
2287*663afb9bSAndroid Build Coastguard Worker 	int n;
2288*663afb9bSAndroid Build Coastguard Worker 	int result;
2289*663afb9bSAndroid Build Coastguard Worker 
2290*663afb9bSAndroid Build Coastguard Worker #ifdef USE_IOVEC_IMPL
2291*663afb9bSAndroid Build Coastguard Worker 	int nvecs, i, remaining;
2292*663afb9bSAndroid Build Coastguard Worker #else
2293*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain;
2294*663afb9bSAndroid Build Coastguard Worker 	unsigned char *p;
2295*663afb9bSAndroid Build Coastguard Worker #endif
2296*663afb9bSAndroid Build Coastguard Worker 
2297*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buf);
2298*663afb9bSAndroid Build Coastguard Worker 
2299*663afb9bSAndroid Build Coastguard Worker 	if (buf->freeze_end) {
2300*663afb9bSAndroid Build Coastguard Worker 		result = -1;
2301*663afb9bSAndroid Build Coastguard Worker 		goto done;
2302*663afb9bSAndroid Build Coastguard Worker 	}
2303*663afb9bSAndroid Build Coastguard Worker 
2304*663afb9bSAndroid Build Coastguard Worker 	n = get_n_bytes_readable_on_socket(fd);
2305*663afb9bSAndroid Build Coastguard Worker 	if (n <= 0 || n > EVBUFFER_MAX_READ)
2306*663afb9bSAndroid Build Coastguard Worker 		n = EVBUFFER_MAX_READ;
2307*663afb9bSAndroid Build Coastguard Worker 	if (howmuch < 0 || howmuch > n)
2308*663afb9bSAndroid Build Coastguard Worker 		howmuch = n;
2309*663afb9bSAndroid Build Coastguard Worker 
2310*663afb9bSAndroid Build Coastguard Worker #ifdef USE_IOVEC_IMPL
2311*663afb9bSAndroid Build Coastguard Worker 	/* Since we can use iovecs, we're willing to use the last
2312*663afb9bSAndroid Build Coastguard Worker 	 * NUM_READ_IOVEC chains. */
2313*663afb9bSAndroid Build Coastguard Worker 	if (evbuffer_expand_fast_(buf, howmuch, NUM_READ_IOVEC) == -1) {
2314*663afb9bSAndroid Build Coastguard Worker 		result = -1;
2315*663afb9bSAndroid Build Coastguard Worker 		goto done;
2316*663afb9bSAndroid Build Coastguard Worker 	} else {
2317*663afb9bSAndroid Build Coastguard Worker 		IOV_TYPE vecs[NUM_READ_IOVEC];
2318*663afb9bSAndroid Build Coastguard Worker #ifdef EVBUFFER_IOVEC_IS_NATIVE_
2319*663afb9bSAndroid Build Coastguard Worker 		nvecs = evbuffer_read_setup_vecs_(buf, howmuch, vecs,
2320*663afb9bSAndroid Build Coastguard Worker 		    NUM_READ_IOVEC, &chainp, 1);
2321*663afb9bSAndroid Build Coastguard Worker #else
2322*663afb9bSAndroid Build Coastguard Worker 		/* We aren't using the native struct iovec.  Therefore,
2323*663afb9bSAndroid Build Coastguard Worker 		   we are on win32. */
2324*663afb9bSAndroid Build Coastguard Worker 		struct evbuffer_iovec ev_vecs[NUM_READ_IOVEC];
2325*663afb9bSAndroid Build Coastguard Worker 		nvecs = evbuffer_read_setup_vecs_(buf, howmuch, ev_vecs, 2,
2326*663afb9bSAndroid Build Coastguard Worker 		    &chainp, 1);
2327*663afb9bSAndroid Build Coastguard Worker 
2328*663afb9bSAndroid Build Coastguard Worker 		for (i=0; i < nvecs; ++i)
2329*663afb9bSAndroid Build Coastguard Worker 			WSABUF_FROM_EVBUFFER_IOV(&vecs[i], &ev_vecs[i]);
2330*663afb9bSAndroid Build Coastguard Worker #endif
2331*663afb9bSAndroid Build Coastguard Worker 
2332*663afb9bSAndroid Build Coastguard Worker #ifdef _WIN32
2333*663afb9bSAndroid Build Coastguard Worker 		{
2334*663afb9bSAndroid Build Coastguard Worker 			DWORD bytesRead;
2335*663afb9bSAndroid Build Coastguard Worker 			DWORD flags=0;
2336*663afb9bSAndroid Build Coastguard Worker 			if (WSARecv(fd, vecs, nvecs, &bytesRead, &flags, NULL, NULL)) {
2337*663afb9bSAndroid Build Coastguard Worker 				/* The read failed. It might be a close,
2338*663afb9bSAndroid Build Coastguard Worker 				 * or it might be an error. */
2339*663afb9bSAndroid Build Coastguard Worker 				if (WSAGetLastError() == WSAECONNABORTED)
2340*663afb9bSAndroid Build Coastguard Worker 					n = 0;
2341*663afb9bSAndroid Build Coastguard Worker 				else
2342*663afb9bSAndroid Build Coastguard Worker 					n = -1;
2343*663afb9bSAndroid Build Coastguard Worker 			} else
2344*663afb9bSAndroid Build Coastguard Worker 				n = bytesRead;
2345*663afb9bSAndroid Build Coastguard Worker 		}
2346*663afb9bSAndroid Build Coastguard Worker #else
2347*663afb9bSAndroid Build Coastguard Worker 		n = readv(fd, vecs, nvecs);
2348*663afb9bSAndroid Build Coastguard Worker #endif
2349*663afb9bSAndroid Build Coastguard Worker 	}
2350*663afb9bSAndroid Build Coastguard Worker 
2351*663afb9bSAndroid Build Coastguard Worker #else /*!USE_IOVEC_IMPL*/
2352*663afb9bSAndroid Build Coastguard Worker 	/* If we don't have FIONREAD, we might waste some space here */
2353*663afb9bSAndroid Build Coastguard Worker 	/* XXX we _will_ waste some space here if there is any space left
2354*663afb9bSAndroid Build Coastguard Worker 	 * over on buf->last. */
2355*663afb9bSAndroid Build Coastguard Worker 	if ((chain = evbuffer_expand_singlechain(buf, howmuch)) == NULL) {
2356*663afb9bSAndroid Build Coastguard Worker 		result = -1;
2357*663afb9bSAndroid Build Coastguard Worker 		goto done;
2358*663afb9bSAndroid Build Coastguard Worker 	}
2359*663afb9bSAndroid Build Coastguard Worker 
2360*663afb9bSAndroid Build Coastguard Worker 	/* We can append new data at this point */
2361*663afb9bSAndroid Build Coastguard Worker 	p = chain->buffer + chain->misalign + chain->off;
2362*663afb9bSAndroid Build Coastguard Worker 
2363*663afb9bSAndroid Build Coastguard Worker #ifndef _WIN32
2364*663afb9bSAndroid Build Coastguard Worker 	n = read(fd, p, howmuch);
2365*663afb9bSAndroid Build Coastguard Worker #else
2366*663afb9bSAndroid Build Coastguard Worker 	n = recv(fd, p, howmuch, 0);
2367*663afb9bSAndroid Build Coastguard Worker #endif
2368*663afb9bSAndroid Build Coastguard Worker #endif /* USE_IOVEC_IMPL */
2369*663afb9bSAndroid Build Coastguard Worker 
2370*663afb9bSAndroid Build Coastguard Worker 	if (n == -1) {
2371*663afb9bSAndroid Build Coastguard Worker 		result = -1;
2372*663afb9bSAndroid Build Coastguard Worker 		goto done;
2373*663afb9bSAndroid Build Coastguard Worker 	}
2374*663afb9bSAndroid Build Coastguard Worker 	if (n == 0) {
2375*663afb9bSAndroid Build Coastguard Worker 		result = 0;
2376*663afb9bSAndroid Build Coastguard Worker 		goto done;
2377*663afb9bSAndroid Build Coastguard Worker 	}
2378*663afb9bSAndroid Build Coastguard Worker 
2379*663afb9bSAndroid Build Coastguard Worker #ifdef USE_IOVEC_IMPL
2380*663afb9bSAndroid Build Coastguard Worker 	remaining = n;
2381*663afb9bSAndroid Build Coastguard Worker 	for (i=0; i < nvecs; ++i) {
2382*663afb9bSAndroid Build Coastguard Worker 		/* can't overflow, since only mutable chains have
2383*663afb9bSAndroid Build Coastguard Worker 		 * huge misaligns. */
2384*663afb9bSAndroid Build Coastguard Worker 		size_t space = (size_t) CHAIN_SPACE_LEN(*chainp);
2385*663afb9bSAndroid Build Coastguard Worker 		/* XXXX This is a kludge that can waste space in perverse
2386*663afb9bSAndroid Build Coastguard Worker 		 * situations. */
2387*663afb9bSAndroid Build Coastguard Worker 		if (space > EVBUFFER_CHAIN_MAX)
2388*663afb9bSAndroid Build Coastguard Worker 			space = EVBUFFER_CHAIN_MAX;
2389*663afb9bSAndroid Build Coastguard Worker 		if ((ev_ssize_t)space < remaining) {
2390*663afb9bSAndroid Build Coastguard Worker 			(*chainp)->off += space;
2391*663afb9bSAndroid Build Coastguard Worker 			remaining -= (int)space;
2392*663afb9bSAndroid Build Coastguard Worker 		} else {
2393*663afb9bSAndroid Build Coastguard Worker 			(*chainp)->off += remaining;
2394*663afb9bSAndroid Build Coastguard Worker 			buf->last_with_datap = chainp;
2395*663afb9bSAndroid Build Coastguard Worker 			break;
2396*663afb9bSAndroid Build Coastguard Worker 		}
2397*663afb9bSAndroid Build Coastguard Worker 		chainp = &(*chainp)->next;
2398*663afb9bSAndroid Build Coastguard Worker 	}
2399*663afb9bSAndroid Build Coastguard Worker #else
2400*663afb9bSAndroid Build Coastguard Worker 	chain->off += n;
2401*663afb9bSAndroid Build Coastguard Worker 	advance_last_with_data(buf);
2402*663afb9bSAndroid Build Coastguard Worker #endif
2403*663afb9bSAndroid Build Coastguard Worker 	buf->total_len += n;
2404*663afb9bSAndroid Build Coastguard Worker 	buf->n_add_for_cb += n;
2405*663afb9bSAndroid Build Coastguard Worker 
2406*663afb9bSAndroid Build Coastguard Worker 	/* Tell someone about changes in this buffer */
2407*663afb9bSAndroid Build Coastguard Worker 	evbuffer_invoke_callbacks_(buf);
2408*663afb9bSAndroid Build Coastguard Worker 	result = n;
2409*663afb9bSAndroid Build Coastguard Worker done:
2410*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buf);
2411*663afb9bSAndroid Build Coastguard Worker 	return result;
2412*663afb9bSAndroid Build Coastguard Worker }
2413*663afb9bSAndroid Build Coastguard Worker 
2414*663afb9bSAndroid Build Coastguard Worker #ifdef USE_IOVEC_IMPL
2415*663afb9bSAndroid Build Coastguard Worker static inline int
evbuffer_write_iovec(struct evbuffer * buffer,evutil_socket_t fd,ev_ssize_t howmuch)2416*663afb9bSAndroid Build Coastguard Worker evbuffer_write_iovec(struct evbuffer *buffer, evutil_socket_t fd,
2417*663afb9bSAndroid Build Coastguard Worker     ev_ssize_t howmuch)
2418*663afb9bSAndroid Build Coastguard Worker {
2419*663afb9bSAndroid Build Coastguard Worker 	IOV_TYPE iov[NUM_WRITE_IOVEC];
2420*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain = buffer->first;
2421*663afb9bSAndroid Build Coastguard Worker 	int n, i = 0;
2422*663afb9bSAndroid Build Coastguard Worker 
2423*663afb9bSAndroid Build Coastguard Worker 	if (howmuch < 0)
2424*663afb9bSAndroid Build Coastguard Worker 		return -1;
2425*663afb9bSAndroid Build Coastguard Worker 
2426*663afb9bSAndroid Build Coastguard Worker 	ASSERT_EVBUFFER_LOCKED(buffer);
2427*663afb9bSAndroid Build Coastguard Worker 	/* XXX make this top out at some maximal data length?  if the
2428*663afb9bSAndroid Build Coastguard Worker 	 * buffer has (say) 1MB in it, split over 128 chains, there's
2429*663afb9bSAndroid Build Coastguard Worker 	 * no way it all gets written in one go. */
2430*663afb9bSAndroid Build Coastguard Worker 	while (chain != NULL && i < NUM_WRITE_IOVEC && howmuch) {
2431*663afb9bSAndroid Build Coastguard Worker #ifdef USE_SENDFILE
2432*663afb9bSAndroid Build Coastguard Worker 		/* we cannot write the file info via writev */
2433*663afb9bSAndroid Build Coastguard Worker 		if (chain->flags & EVBUFFER_SENDFILE)
2434*663afb9bSAndroid Build Coastguard Worker 			break;
2435*663afb9bSAndroid Build Coastguard Worker #endif
2436*663afb9bSAndroid Build Coastguard Worker 		iov[i].IOV_PTR_FIELD = (void *) (chain->buffer + chain->misalign);
2437*663afb9bSAndroid Build Coastguard Worker 		if ((size_t)howmuch >= chain->off) {
2438*663afb9bSAndroid Build Coastguard Worker 			/* XXXcould be problematic when windows supports mmap*/
2439*663afb9bSAndroid Build Coastguard Worker 			iov[i++].IOV_LEN_FIELD = (IOV_LEN_TYPE)chain->off;
2440*663afb9bSAndroid Build Coastguard Worker 			howmuch -= chain->off;
2441*663afb9bSAndroid Build Coastguard Worker 		} else {
2442*663afb9bSAndroid Build Coastguard Worker 			/* XXXcould be problematic when windows supports mmap*/
2443*663afb9bSAndroid Build Coastguard Worker 			iov[i++].IOV_LEN_FIELD = (IOV_LEN_TYPE)howmuch;
2444*663afb9bSAndroid Build Coastguard Worker 			break;
2445*663afb9bSAndroid Build Coastguard Worker 		}
2446*663afb9bSAndroid Build Coastguard Worker 		chain = chain->next;
2447*663afb9bSAndroid Build Coastguard Worker 	}
2448*663afb9bSAndroid Build Coastguard Worker 	if (! i)
2449*663afb9bSAndroid Build Coastguard Worker 		return 0;
2450*663afb9bSAndroid Build Coastguard Worker 
2451*663afb9bSAndroid Build Coastguard Worker #ifdef _WIN32
2452*663afb9bSAndroid Build Coastguard Worker 	{
2453*663afb9bSAndroid Build Coastguard Worker 		DWORD bytesSent;
2454*663afb9bSAndroid Build Coastguard Worker 		if (WSASend(fd, iov, i, &bytesSent, 0, NULL, NULL))
2455*663afb9bSAndroid Build Coastguard Worker 			n = -1;
2456*663afb9bSAndroid Build Coastguard Worker 		else
2457*663afb9bSAndroid Build Coastguard Worker 			n = bytesSent;
2458*663afb9bSAndroid Build Coastguard Worker 	}
2459*663afb9bSAndroid Build Coastguard Worker #else
2460*663afb9bSAndroid Build Coastguard Worker 	n = writev(fd, iov, i);
2461*663afb9bSAndroid Build Coastguard Worker #endif
2462*663afb9bSAndroid Build Coastguard Worker 	return (n);
2463*663afb9bSAndroid Build Coastguard Worker }
2464*663afb9bSAndroid Build Coastguard Worker #endif
2465*663afb9bSAndroid Build Coastguard Worker 
2466*663afb9bSAndroid Build Coastguard Worker #ifdef USE_SENDFILE
2467*663afb9bSAndroid Build Coastguard Worker static inline int
evbuffer_write_sendfile(struct evbuffer * buffer,evutil_socket_t dest_fd,ev_ssize_t howmuch)2468*663afb9bSAndroid Build Coastguard Worker evbuffer_write_sendfile(struct evbuffer *buffer, evutil_socket_t dest_fd,
2469*663afb9bSAndroid Build Coastguard Worker     ev_ssize_t howmuch)
2470*663afb9bSAndroid Build Coastguard Worker {
2471*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain = buffer->first;
2472*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain_file_segment *info =
2473*663afb9bSAndroid Build Coastguard Worker 	    EVBUFFER_CHAIN_EXTRA(struct evbuffer_chain_file_segment,
2474*663afb9bSAndroid Build Coastguard Worker 		chain);
2475*663afb9bSAndroid Build Coastguard Worker 	const int source_fd = info->segment->fd;
2476*663afb9bSAndroid Build Coastguard Worker #if defined(SENDFILE_IS_MACOSX) || defined(SENDFILE_IS_FREEBSD)
2477*663afb9bSAndroid Build Coastguard Worker 	int res;
2478*663afb9bSAndroid Build Coastguard Worker 	ev_off_t len = chain->off;
2479*663afb9bSAndroid Build Coastguard Worker #elif defined(SENDFILE_IS_LINUX) || defined(SENDFILE_IS_SOLARIS)
2480*663afb9bSAndroid Build Coastguard Worker 	ev_ssize_t res;
2481*663afb9bSAndroid Build Coastguard Worker 	off_t offset = chain->misalign;
2482*663afb9bSAndroid Build Coastguard Worker #endif
2483*663afb9bSAndroid Build Coastguard Worker 
2484*663afb9bSAndroid Build Coastguard Worker 	ASSERT_EVBUFFER_LOCKED(buffer);
2485*663afb9bSAndroid Build Coastguard Worker 
2486*663afb9bSAndroid Build Coastguard Worker #if defined(SENDFILE_IS_MACOSX)
2487*663afb9bSAndroid Build Coastguard Worker 	res = sendfile(source_fd, dest_fd, chain->misalign, &len, NULL, 0);
2488*663afb9bSAndroid Build Coastguard Worker 	if (res == -1 && !EVUTIL_ERR_RW_RETRIABLE(errno))
2489*663afb9bSAndroid Build Coastguard Worker 		return (-1);
2490*663afb9bSAndroid Build Coastguard Worker 
2491*663afb9bSAndroid Build Coastguard Worker 	return (len);
2492*663afb9bSAndroid Build Coastguard Worker #elif defined(SENDFILE_IS_FREEBSD)
2493*663afb9bSAndroid Build Coastguard Worker 	res = sendfile(source_fd, dest_fd, chain->misalign, chain->off, NULL, &len, 0);
2494*663afb9bSAndroid Build Coastguard Worker 	if (res == -1 && !EVUTIL_ERR_RW_RETRIABLE(errno))
2495*663afb9bSAndroid Build Coastguard Worker 		return (-1);
2496*663afb9bSAndroid Build Coastguard Worker 
2497*663afb9bSAndroid Build Coastguard Worker 	return (len);
2498*663afb9bSAndroid Build Coastguard Worker #elif defined(SENDFILE_IS_LINUX)
2499*663afb9bSAndroid Build Coastguard Worker 	/* TODO(niels): implement splice */
2500*663afb9bSAndroid Build Coastguard Worker 	res = sendfile(dest_fd, source_fd, &offset, chain->off);
2501*663afb9bSAndroid Build Coastguard Worker 	if (res == -1 && EVUTIL_ERR_RW_RETRIABLE(errno)) {
2502*663afb9bSAndroid Build Coastguard Worker 		/* if this is EAGAIN or EINTR return 0; otherwise, -1 */
2503*663afb9bSAndroid Build Coastguard Worker 		return (0);
2504*663afb9bSAndroid Build Coastguard Worker 	}
2505*663afb9bSAndroid Build Coastguard Worker 	return (res);
2506*663afb9bSAndroid Build Coastguard Worker #elif defined(SENDFILE_IS_SOLARIS)
2507*663afb9bSAndroid Build Coastguard Worker 	{
2508*663afb9bSAndroid Build Coastguard Worker 		const off_t offset_orig = offset;
2509*663afb9bSAndroid Build Coastguard Worker 		res = sendfile(dest_fd, source_fd, &offset, chain->off);
2510*663afb9bSAndroid Build Coastguard Worker 		if (res == -1 && EVUTIL_ERR_RW_RETRIABLE(errno)) {
2511*663afb9bSAndroid Build Coastguard Worker 			if (offset - offset_orig)
2512*663afb9bSAndroid Build Coastguard Worker 				return offset - offset_orig;
2513*663afb9bSAndroid Build Coastguard Worker 			/* if this is EAGAIN or EINTR and no bytes were
2514*663afb9bSAndroid Build Coastguard Worker 			 * written, return 0 */
2515*663afb9bSAndroid Build Coastguard Worker 			return (0);
2516*663afb9bSAndroid Build Coastguard Worker 		}
2517*663afb9bSAndroid Build Coastguard Worker 		return (res);
2518*663afb9bSAndroid Build Coastguard Worker 	}
2519*663afb9bSAndroid Build Coastguard Worker #endif
2520*663afb9bSAndroid Build Coastguard Worker }
2521*663afb9bSAndroid Build Coastguard Worker #endif
2522*663afb9bSAndroid Build Coastguard Worker 
2523*663afb9bSAndroid Build Coastguard Worker int
evbuffer_write_atmost(struct evbuffer * buffer,evutil_socket_t fd,ev_ssize_t howmuch)2524*663afb9bSAndroid Build Coastguard Worker evbuffer_write_atmost(struct evbuffer *buffer, evutil_socket_t fd,
2525*663afb9bSAndroid Build Coastguard Worker     ev_ssize_t howmuch)
2526*663afb9bSAndroid Build Coastguard Worker {
2527*663afb9bSAndroid Build Coastguard Worker 	int n = -1;
2528*663afb9bSAndroid Build Coastguard Worker 
2529*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buffer);
2530*663afb9bSAndroid Build Coastguard Worker 
2531*663afb9bSAndroid Build Coastguard Worker 	if (buffer->freeze_start) {
2532*663afb9bSAndroid Build Coastguard Worker 		goto done;
2533*663afb9bSAndroid Build Coastguard Worker 	}
2534*663afb9bSAndroid Build Coastguard Worker 
2535*663afb9bSAndroid Build Coastguard Worker 	if (howmuch < 0 || (size_t)howmuch > buffer->total_len)
2536*663afb9bSAndroid Build Coastguard Worker 		howmuch = buffer->total_len;
2537*663afb9bSAndroid Build Coastguard Worker 
2538*663afb9bSAndroid Build Coastguard Worker 	if (howmuch > 0) {
2539*663afb9bSAndroid Build Coastguard Worker #ifdef USE_SENDFILE
2540*663afb9bSAndroid Build Coastguard Worker 		struct evbuffer_chain *chain = buffer->first;
2541*663afb9bSAndroid Build Coastguard Worker 		if (chain != NULL && (chain->flags & EVBUFFER_SENDFILE))
2542*663afb9bSAndroid Build Coastguard Worker 			n = evbuffer_write_sendfile(buffer, fd, howmuch);
2543*663afb9bSAndroid Build Coastguard Worker 		else {
2544*663afb9bSAndroid Build Coastguard Worker #endif
2545*663afb9bSAndroid Build Coastguard Worker #ifdef USE_IOVEC_IMPL
2546*663afb9bSAndroid Build Coastguard Worker 		n = evbuffer_write_iovec(buffer, fd, howmuch);
2547*663afb9bSAndroid Build Coastguard Worker #elif defined(_WIN32)
2548*663afb9bSAndroid Build Coastguard Worker 		/* XXX(nickm) Don't disable this code until we know if
2549*663afb9bSAndroid Build Coastguard Worker 		 * the WSARecv code above works. */
2550*663afb9bSAndroid Build Coastguard Worker 		void *p = evbuffer_pullup(buffer, howmuch);
2551*663afb9bSAndroid Build Coastguard Worker 		EVUTIL_ASSERT(p || !howmuch);
2552*663afb9bSAndroid Build Coastguard Worker 		n = send(fd, p, howmuch, 0);
2553*663afb9bSAndroid Build Coastguard Worker #else
2554*663afb9bSAndroid Build Coastguard Worker 		void *p = evbuffer_pullup(buffer, howmuch);
2555*663afb9bSAndroid Build Coastguard Worker 		EVUTIL_ASSERT(p || !howmuch);
2556*663afb9bSAndroid Build Coastguard Worker 		n = write(fd, p, howmuch);
2557*663afb9bSAndroid Build Coastguard Worker #endif
2558*663afb9bSAndroid Build Coastguard Worker #ifdef USE_SENDFILE
2559*663afb9bSAndroid Build Coastguard Worker 		}
2560*663afb9bSAndroid Build Coastguard Worker #endif
2561*663afb9bSAndroid Build Coastguard Worker 	}
2562*663afb9bSAndroid Build Coastguard Worker 
2563*663afb9bSAndroid Build Coastguard Worker 	if (n > 0)
2564*663afb9bSAndroid Build Coastguard Worker 		evbuffer_drain(buffer, n);
2565*663afb9bSAndroid Build Coastguard Worker 
2566*663afb9bSAndroid Build Coastguard Worker done:
2567*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buffer);
2568*663afb9bSAndroid Build Coastguard Worker 	return (n);
2569*663afb9bSAndroid Build Coastguard Worker }
2570*663afb9bSAndroid Build Coastguard Worker 
2571*663afb9bSAndroid Build Coastguard Worker int
evbuffer_write(struct evbuffer * buffer,evutil_socket_t fd)2572*663afb9bSAndroid Build Coastguard Worker evbuffer_write(struct evbuffer *buffer, evutil_socket_t fd)
2573*663afb9bSAndroid Build Coastguard Worker {
2574*663afb9bSAndroid Build Coastguard Worker 	return evbuffer_write_atmost(buffer, fd, -1);
2575*663afb9bSAndroid Build Coastguard Worker }
2576*663afb9bSAndroid Build Coastguard Worker 
2577*663afb9bSAndroid Build Coastguard Worker unsigned char *
evbuffer_find(struct evbuffer * buffer,const unsigned char * what,size_t len)2578*663afb9bSAndroid Build Coastguard Worker evbuffer_find(struct evbuffer *buffer, const unsigned char *what, size_t len)
2579*663afb9bSAndroid Build Coastguard Worker {
2580*663afb9bSAndroid Build Coastguard Worker 	unsigned char *search;
2581*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_ptr ptr;
2582*663afb9bSAndroid Build Coastguard Worker 
2583*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buffer);
2584*663afb9bSAndroid Build Coastguard Worker 
2585*663afb9bSAndroid Build Coastguard Worker 	ptr = evbuffer_search(buffer, (const char *)what, len, NULL);
2586*663afb9bSAndroid Build Coastguard Worker 	if (ptr.pos < 0) {
2587*663afb9bSAndroid Build Coastguard Worker 		search = NULL;
2588*663afb9bSAndroid Build Coastguard Worker 	} else {
2589*663afb9bSAndroid Build Coastguard Worker 		search = evbuffer_pullup(buffer, ptr.pos + len);
2590*663afb9bSAndroid Build Coastguard Worker 		if (search)
2591*663afb9bSAndroid Build Coastguard Worker 			search += ptr.pos;
2592*663afb9bSAndroid Build Coastguard Worker 	}
2593*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buffer);
2594*663afb9bSAndroid Build Coastguard Worker 	return search;
2595*663afb9bSAndroid Build Coastguard Worker }
2596*663afb9bSAndroid Build Coastguard Worker 
2597*663afb9bSAndroid Build Coastguard Worker /* Subract <b>howfar</b> from the position of <b>pos</b> within
2598*663afb9bSAndroid Build Coastguard Worker  * <b>buf</b>. Returns 0 on success, -1 on failure.
2599*663afb9bSAndroid Build Coastguard Worker  *
2600*663afb9bSAndroid Build Coastguard Worker  * This isn't exposed yet, because of potential inefficiency issues.
2601*663afb9bSAndroid Build Coastguard Worker  * Maybe it should be. */
2602*663afb9bSAndroid Build Coastguard Worker static int
evbuffer_ptr_subtract(struct evbuffer * buf,struct evbuffer_ptr * pos,size_t howfar)2603*663afb9bSAndroid Build Coastguard Worker evbuffer_ptr_subtract(struct evbuffer *buf, struct evbuffer_ptr *pos,
2604*663afb9bSAndroid Build Coastguard Worker     size_t howfar)
2605*663afb9bSAndroid Build Coastguard Worker {
2606*663afb9bSAndroid Build Coastguard Worker 	if (pos->pos < 0)
2607*663afb9bSAndroid Build Coastguard Worker 		return -1;
2608*663afb9bSAndroid Build Coastguard Worker 	if (howfar > (size_t)pos->pos)
2609*663afb9bSAndroid Build Coastguard Worker 		return -1;
2610*663afb9bSAndroid Build Coastguard Worker 	if (pos->internal_.chain && howfar <= pos->internal_.pos_in_chain) {
2611*663afb9bSAndroid Build Coastguard Worker 		pos->internal_.pos_in_chain -= howfar;
2612*663afb9bSAndroid Build Coastguard Worker 		pos->pos -= howfar;
2613*663afb9bSAndroid Build Coastguard Worker 		return 0;
2614*663afb9bSAndroid Build Coastguard Worker 	} else {
2615*663afb9bSAndroid Build Coastguard Worker 		const size_t newpos = pos->pos - howfar;
2616*663afb9bSAndroid Build Coastguard Worker 		/* Here's the inefficient part: it walks over the
2617*663afb9bSAndroid Build Coastguard Worker 		 * chains until we hit newpos. */
2618*663afb9bSAndroid Build Coastguard Worker 		return evbuffer_ptr_set(buf, pos, newpos, EVBUFFER_PTR_SET);
2619*663afb9bSAndroid Build Coastguard Worker 	}
2620*663afb9bSAndroid Build Coastguard Worker }
2621*663afb9bSAndroid Build Coastguard Worker 
2622*663afb9bSAndroid Build Coastguard Worker int
evbuffer_ptr_set(struct evbuffer * buf,struct evbuffer_ptr * pos,size_t position,enum evbuffer_ptr_how how)2623*663afb9bSAndroid Build Coastguard Worker evbuffer_ptr_set(struct evbuffer *buf, struct evbuffer_ptr *pos,
2624*663afb9bSAndroid Build Coastguard Worker     size_t position, enum evbuffer_ptr_how how)
2625*663afb9bSAndroid Build Coastguard Worker {
2626*663afb9bSAndroid Build Coastguard Worker 	size_t left = position;
2627*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain = NULL;
2628*663afb9bSAndroid Build Coastguard Worker 	int result = 0;
2629*663afb9bSAndroid Build Coastguard Worker 
2630*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buf);
2631*663afb9bSAndroid Build Coastguard Worker 
2632*663afb9bSAndroid Build Coastguard Worker 	switch (how) {
2633*663afb9bSAndroid Build Coastguard Worker 	case EVBUFFER_PTR_SET:
2634*663afb9bSAndroid Build Coastguard Worker 		chain = buf->first;
2635*663afb9bSAndroid Build Coastguard Worker 		pos->pos = position;
2636*663afb9bSAndroid Build Coastguard Worker 		position = 0;
2637*663afb9bSAndroid Build Coastguard Worker 		break;
2638*663afb9bSAndroid Build Coastguard Worker 	case EVBUFFER_PTR_ADD:
2639*663afb9bSAndroid Build Coastguard Worker 		/* this avoids iterating over all previous chains if
2640*663afb9bSAndroid Build Coastguard Worker 		   we just want to advance the position */
2641*663afb9bSAndroid Build Coastguard Worker 		if (pos->pos < 0 || EV_SIZE_MAX - position < (size_t)pos->pos) {
2642*663afb9bSAndroid Build Coastguard Worker 			EVBUFFER_UNLOCK(buf);
2643*663afb9bSAndroid Build Coastguard Worker 			return -1;
2644*663afb9bSAndroid Build Coastguard Worker 		}
2645*663afb9bSAndroid Build Coastguard Worker 		chain = pos->internal_.chain;
2646*663afb9bSAndroid Build Coastguard Worker 		pos->pos += position;
2647*663afb9bSAndroid Build Coastguard Worker 		position = pos->internal_.pos_in_chain;
2648*663afb9bSAndroid Build Coastguard Worker 		break;
2649*663afb9bSAndroid Build Coastguard Worker 	}
2650*663afb9bSAndroid Build Coastguard Worker 
2651*663afb9bSAndroid Build Coastguard Worker 	EVUTIL_ASSERT(EV_SIZE_MAX - left >= position);
2652*663afb9bSAndroid Build Coastguard Worker 	while (chain && position + left >= chain->off) {
2653*663afb9bSAndroid Build Coastguard Worker 		left -= chain->off - position;
2654*663afb9bSAndroid Build Coastguard Worker 		chain = chain->next;
2655*663afb9bSAndroid Build Coastguard Worker 		position = 0;
2656*663afb9bSAndroid Build Coastguard Worker 	}
2657*663afb9bSAndroid Build Coastguard Worker 	if (chain) {
2658*663afb9bSAndroid Build Coastguard Worker 		pos->internal_.chain = chain;
2659*663afb9bSAndroid Build Coastguard Worker 		pos->internal_.pos_in_chain = position + left;
2660*663afb9bSAndroid Build Coastguard Worker 	} else if (left == 0) {
2661*663afb9bSAndroid Build Coastguard Worker 		/* The first byte in the (nonexistent) chain after the last chain */
2662*663afb9bSAndroid Build Coastguard Worker 		pos->internal_.chain = NULL;
2663*663afb9bSAndroid Build Coastguard Worker 		pos->internal_.pos_in_chain = 0;
2664*663afb9bSAndroid Build Coastguard Worker 	} else {
2665*663afb9bSAndroid Build Coastguard Worker 		PTR_NOT_FOUND(pos);
2666*663afb9bSAndroid Build Coastguard Worker 		result = -1;
2667*663afb9bSAndroid Build Coastguard Worker 	}
2668*663afb9bSAndroid Build Coastguard Worker 
2669*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buf);
2670*663afb9bSAndroid Build Coastguard Worker 
2671*663afb9bSAndroid Build Coastguard Worker 	return result;
2672*663afb9bSAndroid Build Coastguard Worker }
2673*663afb9bSAndroid Build Coastguard Worker 
2674*663afb9bSAndroid Build Coastguard Worker /**
2675*663afb9bSAndroid Build Coastguard Worker    Compare the bytes in buf at position pos to the len bytes in mem.  Return
2676*663afb9bSAndroid Build Coastguard Worker    less than 0, 0, or greater than 0 as memcmp.
2677*663afb9bSAndroid Build Coastguard Worker  */
2678*663afb9bSAndroid Build Coastguard Worker static int
evbuffer_ptr_memcmp(const struct evbuffer * buf,const struct evbuffer_ptr * pos,const char * mem,size_t len)2679*663afb9bSAndroid Build Coastguard Worker evbuffer_ptr_memcmp(const struct evbuffer *buf, const struct evbuffer_ptr *pos,
2680*663afb9bSAndroid Build Coastguard Worker     const char *mem, size_t len)
2681*663afb9bSAndroid Build Coastguard Worker {
2682*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain;
2683*663afb9bSAndroid Build Coastguard Worker 	size_t position;
2684*663afb9bSAndroid Build Coastguard Worker 	int r;
2685*663afb9bSAndroid Build Coastguard Worker 
2686*663afb9bSAndroid Build Coastguard Worker 	ASSERT_EVBUFFER_LOCKED(buf);
2687*663afb9bSAndroid Build Coastguard Worker 
2688*663afb9bSAndroid Build Coastguard Worker 	if (pos->pos < 0 ||
2689*663afb9bSAndroid Build Coastguard Worker 	    EV_SIZE_MAX - len < (size_t)pos->pos ||
2690*663afb9bSAndroid Build Coastguard Worker 	    pos->pos + len > buf->total_len)
2691*663afb9bSAndroid Build Coastguard Worker 		return -1;
2692*663afb9bSAndroid Build Coastguard Worker 
2693*663afb9bSAndroid Build Coastguard Worker 	chain = pos->internal_.chain;
2694*663afb9bSAndroid Build Coastguard Worker 	position = pos->internal_.pos_in_chain;
2695*663afb9bSAndroid Build Coastguard Worker 	while (len && chain) {
2696*663afb9bSAndroid Build Coastguard Worker 		size_t n_comparable;
2697*663afb9bSAndroid Build Coastguard Worker 		if (len + position > chain->off)
2698*663afb9bSAndroid Build Coastguard Worker 			n_comparable = chain->off - position;
2699*663afb9bSAndroid Build Coastguard Worker 		else
2700*663afb9bSAndroid Build Coastguard Worker 			n_comparable = len;
2701*663afb9bSAndroid Build Coastguard Worker 		r = memcmp(chain->buffer + chain->misalign + position, mem,
2702*663afb9bSAndroid Build Coastguard Worker 		    n_comparable);
2703*663afb9bSAndroid Build Coastguard Worker 		if (r)
2704*663afb9bSAndroid Build Coastguard Worker 			return r;
2705*663afb9bSAndroid Build Coastguard Worker 		mem += n_comparable;
2706*663afb9bSAndroid Build Coastguard Worker 		len -= n_comparable;
2707*663afb9bSAndroid Build Coastguard Worker 		position = 0;
2708*663afb9bSAndroid Build Coastguard Worker 		chain = chain->next;
2709*663afb9bSAndroid Build Coastguard Worker 	}
2710*663afb9bSAndroid Build Coastguard Worker 
2711*663afb9bSAndroid Build Coastguard Worker 	return 0;
2712*663afb9bSAndroid Build Coastguard Worker }
2713*663afb9bSAndroid Build Coastguard Worker 
2714*663afb9bSAndroid Build Coastguard Worker struct evbuffer_ptr
evbuffer_search(struct evbuffer * buffer,const char * what,size_t len,const struct evbuffer_ptr * start)2715*663afb9bSAndroid Build Coastguard Worker evbuffer_search(struct evbuffer *buffer, const char *what, size_t len, const struct evbuffer_ptr *start)
2716*663afb9bSAndroid Build Coastguard Worker {
2717*663afb9bSAndroid Build Coastguard Worker 	return evbuffer_search_range(buffer, what, len, start, NULL);
2718*663afb9bSAndroid Build Coastguard Worker }
2719*663afb9bSAndroid Build Coastguard Worker 
2720*663afb9bSAndroid Build Coastguard Worker struct evbuffer_ptr
evbuffer_search_range(struct evbuffer * buffer,const char * what,size_t len,const struct evbuffer_ptr * start,const struct evbuffer_ptr * end)2721*663afb9bSAndroid Build Coastguard Worker evbuffer_search_range(struct evbuffer *buffer, const char *what, size_t len, const struct evbuffer_ptr *start, const struct evbuffer_ptr *end)
2722*663afb9bSAndroid Build Coastguard Worker {
2723*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_ptr pos;
2724*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain, *last_chain = NULL;
2725*663afb9bSAndroid Build Coastguard Worker 	const unsigned char *p;
2726*663afb9bSAndroid Build Coastguard Worker 	char first;
2727*663afb9bSAndroid Build Coastguard Worker 
2728*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buffer);
2729*663afb9bSAndroid Build Coastguard Worker 
2730*663afb9bSAndroid Build Coastguard Worker 	if (start) {
2731*663afb9bSAndroid Build Coastguard Worker 		memcpy(&pos, start, sizeof(pos));
2732*663afb9bSAndroid Build Coastguard Worker 		chain = pos.internal_.chain;
2733*663afb9bSAndroid Build Coastguard Worker 	} else {
2734*663afb9bSAndroid Build Coastguard Worker 		pos.pos = 0;
2735*663afb9bSAndroid Build Coastguard Worker 		chain = pos.internal_.chain = buffer->first;
2736*663afb9bSAndroid Build Coastguard Worker 		pos.internal_.pos_in_chain = 0;
2737*663afb9bSAndroid Build Coastguard Worker 	}
2738*663afb9bSAndroid Build Coastguard Worker 
2739*663afb9bSAndroid Build Coastguard Worker 	if (end)
2740*663afb9bSAndroid Build Coastguard Worker 		last_chain = end->internal_.chain;
2741*663afb9bSAndroid Build Coastguard Worker 
2742*663afb9bSAndroid Build Coastguard Worker 	if (!len || len > EV_SSIZE_MAX)
2743*663afb9bSAndroid Build Coastguard Worker 		goto done;
2744*663afb9bSAndroid Build Coastguard Worker 
2745*663afb9bSAndroid Build Coastguard Worker 	first = what[0];
2746*663afb9bSAndroid Build Coastguard Worker 
2747*663afb9bSAndroid Build Coastguard Worker 	while (chain) {
2748*663afb9bSAndroid Build Coastguard Worker 		const unsigned char *start_at =
2749*663afb9bSAndroid Build Coastguard Worker 		    chain->buffer + chain->misalign +
2750*663afb9bSAndroid Build Coastguard Worker 		    pos.internal_.pos_in_chain;
2751*663afb9bSAndroid Build Coastguard Worker 		p = memchr(start_at, first,
2752*663afb9bSAndroid Build Coastguard Worker 		    chain->off - pos.internal_.pos_in_chain);
2753*663afb9bSAndroid Build Coastguard Worker 		if (p) {
2754*663afb9bSAndroid Build Coastguard Worker 			pos.pos += p - start_at;
2755*663afb9bSAndroid Build Coastguard Worker 			pos.internal_.pos_in_chain += p - start_at;
2756*663afb9bSAndroid Build Coastguard Worker 			if (!evbuffer_ptr_memcmp(buffer, &pos, what, len)) {
2757*663afb9bSAndroid Build Coastguard Worker 				if (end && pos.pos + (ev_ssize_t)len > end->pos)
2758*663afb9bSAndroid Build Coastguard Worker 					goto not_found;
2759*663afb9bSAndroid Build Coastguard Worker 				else
2760*663afb9bSAndroid Build Coastguard Worker 					goto done;
2761*663afb9bSAndroid Build Coastguard Worker 			}
2762*663afb9bSAndroid Build Coastguard Worker 			++pos.pos;
2763*663afb9bSAndroid Build Coastguard Worker 			++pos.internal_.pos_in_chain;
2764*663afb9bSAndroid Build Coastguard Worker 			if (pos.internal_.pos_in_chain == chain->off) {
2765*663afb9bSAndroid Build Coastguard Worker 				chain = pos.internal_.chain = chain->next;
2766*663afb9bSAndroid Build Coastguard Worker 				pos.internal_.pos_in_chain = 0;
2767*663afb9bSAndroid Build Coastguard Worker 			}
2768*663afb9bSAndroid Build Coastguard Worker 		} else {
2769*663afb9bSAndroid Build Coastguard Worker 			if (chain == last_chain)
2770*663afb9bSAndroid Build Coastguard Worker 				goto not_found;
2771*663afb9bSAndroid Build Coastguard Worker 			pos.pos += chain->off - pos.internal_.pos_in_chain;
2772*663afb9bSAndroid Build Coastguard Worker 			chain = pos.internal_.chain = chain->next;
2773*663afb9bSAndroid Build Coastguard Worker 			pos.internal_.pos_in_chain = 0;
2774*663afb9bSAndroid Build Coastguard Worker 		}
2775*663afb9bSAndroid Build Coastguard Worker 	}
2776*663afb9bSAndroid Build Coastguard Worker 
2777*663afb9bSAndroid Build Coastguard Worker not_found:
2778*663afb9bSAndroid Build Coastguard Worker 	PTR_NOT_FOUND(&pos);
2779*663afb9bSAndroid Build Coastguard Worker done:
2780*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buffer);
2781*663afb9bSAndroid Build Coastguard Worker 	return pos;
2782*663afb9bSAndroid Build Coastguard Worker }
2783*663afb9bSAndroid Build Coastguard Worker 
2784*663afb9bSAndroid Build Coastguard Worker int
evbuffer_peek(struct evbuffer * buffer,ev_ssize_t len,struct evbuffer_ptr * start_at,struct evbuffer_iovec * vec,int n_vec)2785*663afb9bSAndroid Build Coastguard Worker evbuffer_peek(struct evbuffer *buffer, ev_ssize_t len,
2786*663afb9bSAndroid Build Coastguard Worker     struct evbuffer_ptr *start_at,
2787*663afb9bSAndroid Build Coastguard Worker     struct evbuffer_iovec *vec, int n_vec)
2788*663afb9bSAndroid Build Coastguard Worker {
2789*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain;
2790*663afb9bSAndroid Build Coastguard Worker 	int idx = 0;
2791*663afb9bSAndroid Build Coastguard Worker 	ev_ssize_t len_so_far = 0;
2792*663afb9bSAndroid Build Coastguard Worker 
2793*663afb9bSAndroid Build Coastguard Worker 	/* Avoid locking in trivial edge cases */
2794*663afb9bSAndroid Build Coastguard Worker 	if (start_at && start_at->internal_.chain == NULL)
2795*663afb9bSAndroid Build Coastguard Worker 		return 0;
2796*663afb9bSAndroid Build Coastguard Worker 
2797*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buffer);
2798*663afb9bSAndroid Build Coastguard Worker 
2799*663afb9bSAndroid Build Coastguard Worker 	if (start_at) {
2800*663afb9bSAndroid Build Coastguard Worker 		chain = start_at->internal_.chain;
2801*663afb9bSAndroid Build Coastguard Worker 		len_so_far = chain->off
2802*663afb9bSAndroid Build Coastguard Worker 		    - start_at->internal_.pos_in_chain;
2803*663afb9bSAndroid Build Coastguard Worker 		idx = 1;
2804*663afb9bSAndroid Build Coastguard Worker 		if (n_vec > 0) {
2805*663afb9bSAndroid Build Coastguard Worker 			vec[0].iov_base = (void *)(chain->buffer + chain->misalign
2806*663afb9bSAndroid Build Coastguard Worker 			    + start_at->internal_.pos_in_chain);
2807*663afb9bSAndroid Build Coastguard Worker 			vec[0].iov_len = len_so_far;
2808*663afb9bSAndroid Build Coastguard Worker 		}
2809*663afb9bSAndroid Build Coastguard Worker 		chain = chain->next;
2810*663afb9bSAndroid Build Coastguard Worker 	} else {
2811*663afb9bSAndroid Build Coastguard Worker 		chain = buffer->first;
2812*663afb9bSAndroid Build Coastguard Worker 	}
2813*663afb9bSAndroid Build Coastguard Worker 
2814*663afb9bSAndroid Build Coastguard Worker 	if (n_vec == 0 && len < 0) {
2815*663afb9bSAndroid Build Coastguard Worker 		/* If no vectors are provided and they asked for "everything",
2816*663afb9bSAndroid Build Coastguard Worker 		 * pretend they asked for the actual available amount. */
2817*663afb9bSAndroid Build Coastguard Worker 		len = buffer->total_len;
2818*663afb9bSAndroid Build Coastguard Worker 		if (start_at) {
2819*663afb9bSAndroid Build Coastguard Worker 			len -= start_at->pos;
2820*663afb9bSAndroid Build Coastguard Worker 		}
2821*663afb9bSAndroid Build Coastguard Worker 	}
2822*663afb9bSAndroid Build Coastguard Worker 
2823*663afb9bSAndroid Build Coastguard Worker 	while (chain) {
2824*663afb9bSAndroid Build Coastguard Worker 		if (len >= 0 && len_so_far >= len)
2825*663afb9bSAndroid Build Coastguard Worker 			break;
2826*663afb9bSAndroid Build Coastguard Worker 		if (idx<n_vec) {
2827*663afb9bSAndroid Build Coastguard Worker 			vec[idx].iov_base = (void *)(chain->buffer + chain->misalign);
2828*663afb9bSAndroid Build Coastguard Worker 			vec[idx].iov_len = chain->off;
2829*663afb9bSAndroid Build Coastguard Worker 		} else if (len<0) {
2830*663afb9bSAndroid Build Coastguard Worker 			break;
2831*663afb9bSAndroid Build Coastguard Worker 		}
2832*663afb9bSAndroid Build Coastguard Worker 		++idx;
2833*663afb9bSAndroid Build Coastguard Worker 		len_so_far += chain->off;
2834*663afb9bSAndroid Build Coastguard Worker 		chain = chain->next;
2835*663afb9bSAndroid Build Coastguard Worker 	}
2836*663afb9bSAndroid Build Coastguard Worker 
2837*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buffer);
2838*663afb9bSAndroid Build Coastguard Worker 
2839*663afb9bSAndroid Build Coastguard Worker 	return idx;
2840*663afb9bSAndroid Build Coastguard Worker }
2841*663afb9bSAndroid Build Coastguard Worker 
2842*663afb9bSAndroid Build Coastguard Worker 
2843*663afb9bSAndroid Build Coastguard Worker int
evbuffer_add_vprintf(struct evbuffer * buf,const char * fmt,va_list ap)2844*663afb9bSAndroid Build Coastguard Worker evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap)
2845*663afb9bSAndroid Build Coastguard Worker {
2846*663afb9bSAndroid Build Coastguard Worker 	char *buffer;
2847*663afb9bSAndroid Build Coastguard Worker 	size_t space;
2848*663afb9bSAndroid Build Coastguard Worker 	int sz, result = -1;
2849*663afb9bSAndroid Build Coastguard Worker 	va_list aq;
2850*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain;
2851*663afb9bSAndroid Build Coastguard Worker 
2852*663afb9bSAndroid Build Coastguard Worker 
2853*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buf);
2854*663afb9bSAndroid Build Coastguard Worker 
2855*663afb9bSAndroid Build Coastguard Worker 	if (buf->freeze_end) {
2856*663afb9bSAndroid Build Coastguard Worker 		goto done;
2857*663afb9bSAndroid Build Coastguard Worker 	}
2858*663afb9bSAndroid Build Coastguard Worker 
2859*663afb9bSAndroid Build Coastguard Worker 	/* make sure that at least some space is available */
2860*663afb9bSAndroid Build Coastguard Worker 	if ((chain = evbuffer_expand_singlechain(buf, 64)) == NULL)
2861*663afb9bSAndroid Build Coastguard Worker 		goto done;
2862*663afb9bSAndroid Build Coastguard Worker 
2863*663afb9bSAndroid Build Coastguard Worker 	for (;;) {
2864*663afb9bSAndroid Build Coastguard Worker #if 0
2865*663afb9bSAndroid Build Coastguard Worker 		size_t used = chain->misalign + chain->off;
2866*663afb9bSAndroid Build Coastguard Worker 		buffer = (char *)chain->buffer + chain->misalign + chain->off;
2867*663afb9bSAndroid Build Coastguard Worker 		EVUTIL_ASSERT(chain->buffer_len >= used);
2868*663afb9bSAndroid Build Coastguard Worker 		space = chain->buffer_len - used;
2869*663afb9bSAndroid Build Coastguard Worker #endif
2870*663afb9bSAndroid Build Coastguard Worker 		buffer = (char*) CHAIN_SPACE_PTR(chain);
2871*663afb9bSAndroid Build Coastguard Worker 		space = (size_t) CHAIN_SPACE_LEN(chain);
2872*663afb9bSAndroid Build Coastguard Worker 
2873*663afb9bSAndroid Build Coastguard Worker #ifndef va_copy
2874*663afb9bSAndroid Build Coastguard Worker #define	va_copy(dst, src)	memcpy(&(dst), &(src), sizeof(va_list))
2875*663afb9bSAndroid Build Coastguard Worker #endif
2876*663afb9bSAndroid Build Coastguard Worker 		va_copy(aq, ap);
2877*663afb9bSAndroid Build Coastguard Worker 
2878*663afb9bSAndroid Build Coastguard Worker 		sz = evutil_vsnprintf(buffer, space, fmt, aq);
2879*663afb9bSAndroid Build Coastguard Worker 
2880*663afb9bSAndroid Build Coastguard Worker 		va_end(aq);
2881*663afb9bSAndroid Build Coastguard Worker 
2882*663afb9bSAndroid Build Coastguard Worker 		if (sz < 0)
2883*663afb9bSAndroid Build Coastguard Worker 			goto done;
2884*663afb9bSAndroid Build Coastguard Worker 		if (INT_MAX >= EVBUFFER_CHAIN_MAX &&
2885*663afb9bSAndroid Build Coastguard Worker 		    (size_t)sz >= EVBUFFER_CHAIN_MAX)
2886*663afb9bSAndroid Build Coastguard Worker 			goto done;
2887*663afb9bSAndroid Build Coastguard Worker 		if ((size_t)sz < space) {
2888*663afb9bSAndroid Build Coastguard Worker 			chain->off += sz;
2889*663afb9bSAndroid Build Coastguard Worker 			buf->total_len += sz;
2890*663afb9bSAndroid Build Coastguard Worker 			buf->n_add_for_cb += sz;
2891*663afb9bSAndroid Build Coastguard Worker 
2892*663afb9bSAndroid Build Coastguard Worker 			advance_last_with_data(buf);
2893*663afb9bSAndroid Build Coastguard Worker 			evbuffer_invoke_callbacks_(buf);
2894*663afb9bSAndroid Build Coastguard Worker 			result = sz;
2895*663afb9bSAndroid Build Coastguard Worker 			goto done;
2896*663afb9bSAndroid Build Coastguard Worker 		}
2897*663afb9bSAndroid Build Coastguard Worker 		if ((chain = evbuffer_expand_singlechain(buf, sz + 1)) == NULL)
2898*663afb9bSAndroid Build Coastguard Worker 			goto done;
2899*663afb9bSAndroid Build Coastguard Worker 	}
2900*663afb9bSAndroid Build Coastguard Worker 	/* NOTREACHED */
2901*663afb9bSAndroid Build Coastguard Worker 
2902*663afb9bSAndroid Build Coastguard Worker done:
2903*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buf);
2904*663afb9bSAndroid Build Coastguard Worker 	return result;
2905*663afb9bSAndroid Build Coastguard Worker }
2906*663afb9bSAndroid Build Coastguard Worker 
2907*663afb9bSAndroid Build Coastguard Worker int
evbuffer_add_printf(struct evbuffer * buf,const char * fmt,...)2908*663afb9bSAndroid Build Coastguard Worker evbuffer_add_printf(struct evbuffer *buf, const char *fmt, ...)
2909*663afb9bSAndroid Build Coastguard Worker {
2910*663afb9bSAndroid Build Coastguard Worker 	int res = -1;
2911*663afb9bSAndroid Build Coastguard Worker 	va_list ap;
2912*663afb9bSAndroid Build Coastguard Worker 
2913*663afb9bSAndroid Build Coastguard Worker 	va_start(ap, fmt);
2914*663afb9bSAndroid Build Coastguard Worker 	res = evbuffer_add_vprintf(buf, fmt, ap);
2915*663afb9bSAndroid Build Coastguard Worker 	va_end(ap);
2916*663afb9bSAndroid Build Coastguard Worker 
2917*663afb9bSAndroid Build Coastguard Worker 	return (res);
2918*663afb9bSAndroid Build Coastguard Worker }
2919*663afb9bSAndroid Build Coastguard Worker 
2920*663afb9bSAndroid Build Coastguard Worker int
evbuffer_add_reference(struct evbuffer * outbuf,const void * data,size_t datlen,evbuffer_ref_cleanup_cb cleanupfn,void * extra)2921*663afb9bSAndroid Build Coastguard Worker evbuffer_add_reference(struct evbuffer *outbuf,
2922*663afb9bSAndroid Build Coastguard Worker     const void *data, size_t datlen,
2923*663afb9bSAndroid Build Coastguard Worker     evbuffer_ref_cleanup_cb cleanupfn, void *extra)
2924*663afb9bSAndroid Build Coastguard Worker {
2925*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain;
2926*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain_reference *info;
2927*663afb9bSAndroid Build Coastguard Worker 	int result = -1;
2928*663afb9bSAndroid Build Coastguard Worker 
2929*663afb9bSAndroid Build Coastguard Worker 	chain = evbuffer_chain_new(sizeof(struct evbuffer_chain_reference));
2930*663afb9bSAndroid Build Coastguard Worker 	if (!chain)
2931*663afb9bSAndroid Build Coastguard Worker 		return (-1);
2932*663afb9bSAndroid Build Coastguard Worker 	chain->flags |= EVBUFFER_REFERENCE | EVBUFFER_IMMUTABLE;
2933*663afb9bSAndroid Build Coastguard Worker 	chain->buffer = (unsigned char *)data;
2934*663afb9bSAndroid Build Coastguard Worker 	chain->buffer_len = datlen;
2935*663afb9bSAndroid Build Coastguard Worker 	chain->off = datlen;
2936*663afb9bSAndroid Build Coastguard Worker 
2937*663afb9bSAndroid Build Coastguard Worker 	info = EVBUFFER_CHAIN_EXTRA(struct evbuffer_chain_reference, chain);
2938*663afb9bSAndroid Build Coastguard Worker 	info->cleanupfn = cleanupfn;
2939*663afb9bSAndroid Build Coastguard Worker 	info->extra = extra;
2940*663afb9bSAndroid Build Coastguard Worker 
2941*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(outbuf);
2942*663afb9bSAndroid Build Coastguard Worker 	if (outbuf->freeze_end) {
2943*663afb9bSAndroid Build Coastguard Worker 		/* don't call chain_free; we do not want to actually invoke
2944*663afb9bSAndroid Build Coastguard Worker 		 * the cleanup function */
2945*663afb9bSAndroid Build Coastguard Worker 		mm_free(chain);
2946*663afb9bSAndroid Build Coastguard Worker 		goto done;
2947*663afb9bSAndroid Build Coastguard Worker 	}
2948*663afb9bSAndroid Build Coastguard Worker 	evbuffer_chain_insert(outbuf, chain);
2949*663afb9bSAndroid Build Coastguard Worker 	outbuf->n_add_for_cb += datlen;
2950*663afb9bSAndroid Build Coastguard Worker 
2951*663afb9bSAndroid Build Coastguard Worker 	evbuffer_invoke_callbacks_(outbuf);
2952*663afb9bSAndroid Build Coastguard Worker 
2953*663afb9bSAndroid Build Coastguard Worker 	result = 0;
2954*663afb9bSAndroid Build Coastguard Worker done:
2955*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(outbuf);
2956*663afb9bSAndroid Build Coastguard Worker 
2957*663afb9bSAndroid Build Coastguard Worker 	return result;
2958*663afb9bSAndroid Build Coastguard Worker }
2959*663afb9bSAndroid Build Coastguard Worker 
2960*663afb9bSAndroid Build Coastguard Worker /* TODO(niels): we may want to add to automagically convert to mmap, in
2961*663afb9bSAndroid Build Coastguard Worker  * case evbuffer_remove() or evbuffer_pullup() are being used.
2962*663afb9bSAndroid Build Coastguard Worker  */
2963*663afb9bSAndroid Build Coastguard Worker struct evbuffer_file_segment *
evbuffer_file_segment_new(int fd,ev_off_t offset,ev_off_t length,unsigned flags)2964*663afb9bSAndroid Build Coastguard Worker evbuffer_file_segment_new(
2965*663afb9bSAndroid Build Coastguard Worker 	int fd, ev_off_t offset, ev_off_t length, unsigned flags)
2966*663afb9bSAndroid Build Coastguard Worker {
2967*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_file_segment *seg =
2968*663afb9bSAndroid Build Coastguard Worker 	    mm_calloc(sizeof(struct evbuffer_file_segment), 1);
2969*663afb9bSAndroid Build Coastguard Worker 	if (!seg)
2970*663afb9bSAndroid Build Coastguard Worker 		return NULL;
2971*663afb9bSAndroid Build Coastguard Worker 	seg->refcnt = 1;
2972*663afb9bSAndroid Build Coastguard Worker 	seg->fd = fd;
2973*663afb9bSAndroid Build Coastguard Worker 	seg->flags = flags;
2974*663afb9bSAndroid Build Coastguard Worker 	seg->file_offset = offset;
2975*663afb9bSAndroid Build Coastguard Worker 	seg->cleanup_cb = NULL;
2976*663afb9bSAndroid Build Coastguard Worker 	seg->cleanup_cb_arg = NULL;
2977*663afb9bSAndroid Build Coastguard Worker #ifdef _WIN32
2978*663afb9bSAndroid Build Coastguard Worker #ifndef lseek
2979*663afb9bSAndroid Build Coastguard Worker #define lseek _lseeki64
2980*663afb9bSAndroid Build Coastguard Worker #endif
2981*663afb9bSAndroid Build Coastguard Worker #ifndef fstat
2982*663afb9bSAndroid Build Coastguard Worker #define fstat _fstat
2983*663afb9bSAndroid Build Coastguard Worker #endif
2984*663afb9bSAndroid Build Coastguard Worker #ifndef stat
2985*663afb9bSAndroid Build Coastguard Worker #define stat _stat
2986*663afb9bSAndroid Build Coastguard Worker #endif
2987*663afb9bSAndroid Build Coastguard Worker #endif
2988*663afb9bSAndroid Build Coastguard Worker 	if (length == -1) {
2989*663afb9bSAndroid Build Coastguard Worker 		struct stat st;
2990*663afb9bSAndroid Build Coastguard Worker 		if (fstat(fd, &st) < 0)
2991*663afb9bSAndroid Build Coastguard Worker 			goto err;
2992*663afb9bSAndroid Build Coastguard Worker 		length = st.st_size;
2993*663afb9bSAndroid Build Coastguard Worker 	}
2994*663afb9bSAndroid Build Coastguard Worker 	seg->length = length;
2995*663afb9bSAndroid Build Coastguard Worker 
2996*663afb9bSAndroid Build Coastguard Worker 	if (offset < 0 || length < 0 ||
2997*663afb9bSAndroid Build Coastguard Worker 	    ((ev_uint64_t)length > EVBUFFER_CHAIN_MAX) ||
2998*663afb9bSAndroid Build Coastguard Worker 	    (ev_uint64_t)offset > (ev_uint64_t)(EVBUFFER_CHAIN_MAX - length))
2999*663afb9bSAndroid Build Coastguard Worker 		goto err;
3000*663afb9bSAndroid Build Coastguard Worker 
3001*663afb9bSAndroid Build Coastguard Worker #if defined(USE_SENDFILE)
3002*663afb9bSAndroid Build Coastguard Worker 	if (!(flags & EVBUF_FS_DISABLE_SENDFILE)) {
3003*663afb9bSAndroid Build Coastguard Worker 		seg->can_sendfile = 1;
3004*663afb9bSAndroid Build Coastguard Worker 		goto done;
3005*663afb9bSAndroid Build Coastguard Worker 	}
3006*663afb9bSAndroid Build Coastguard Worker #endif
3007*663afb9bSAndroid Build Coastguard Worker 
3008*663afb9bSAndroid Build Coastguard Worker 	if (evbuffer_file_segment_materialize(seg)<0)
3009*663afb9bSAndroid Build Coastguard Worker 		goto err;
3010*663afb9bSAndroid Build Coastguard Worker 
3011*663afb9bSAndroid Build Coastguard Worker #if defined(USE_SENDFILE)
3012*663afb9bSAndroid Build Coastguard Worker done:
3013*663afb9bSAndroid Build Coastguard Worker #endif
3014*663afb9bSAndroid Build Coastguard Worker 	if (!(flags & EVBUF_FS_DISABLE_LOCKING)) {
3015*663afb9bSAndroid Build Coastguard Worker 		EVTHREAD_ALLOC_LOCK(seg->lock, 0);
3016*663afb9bSAndroid Build Coastguard Worker 	}
3017*663afb9bSAndroid Build Coastguard Worker 	return seg;
3018*663afb9bSAndroid Build Coastguard Worker err:
3019*663afb9bSAndroid Build Coastguard Worker 	mm_free(seg);
3020*663afb9bSAndroid Build Coastguard Worker 	return NULL;
3021*663afb9bSAndroid Build Coastguard Worker }
3022*663afb9bSAndroid Build Coastguard Worker 
3023*663afb9bSAndroid Build Coastguard Worker #ifdef EVENT__HAVE_MMAP
3024*663afb9bSAndroid Build Coastguard Worker static long
get_page_size(void)3025*663afb9bSAndroid Build Coastguard Worker get_page_size(void)
3026*663afb9bSAndroid Build Coastguard Worker {
3027*663afb9bSAndroid Build Coastguard Worker #ifdef SC_PAGE_SIZE
3028*663afb9bSAndroid Build Coastguard Worker 	return sysconf(SC_PAGE_SIZE);
3029*663afb9bSAndroid Build Coastguard Worker #elif defined(_SC_PAGE_SIZE)
3030*663afb9bSAndroid Build Coastguard Worker 	return sysconf(_SC_PAGE_SIZE);
3031*663afb9bSAndroid Build Coastguard Worker #else
3032*663afb9bSAndroid Build Coastguard Worker 	return 1;
3033*663afb9bSAndroid Build Coastguard Worker #endif
3034*663afb9bSAndroid Build Coastguard Worker }
3035*663afb9bSAndroid Build Coastguard Worker #endif
3036*663afb9bSAndroid Build Coastguard Worker 
3037*663afb9bSAndroid Build Coastguard Worker /* DOCDOC */
3038*663afb9bSAndroid Build Coastguard Worker /* Requires lock */
3039*663afb9bSAndroid Build Coastguard Worker static int
evbuffer_file_segment_materialize(struct evbuffer_file_segment * seg)3040*663afb9bSAndroid Build Coastguard Worker evbuffer_file_segment_materialize(struct evbuffer_file_segment *seg)
3041*663afb9bSAndroid Build Coastguard Worker {
3042*663afb9bSAndroid Build Coastguard Worker 	const unsigned flags = seg->flags;
3043*663afb9bSAndroid Build Coastguard Worker 	const int fd = seg->fd;
3044*663afb9bSAndroid Build Coastguard Worker 	const ev_off_t length = seg->length;
3045*663afb9bSAndroid Build Coastguard Worker 	const ev_off_t offset = seg->file_offset;
3046*663afb9bSAndroid Build Coastguard Worker 
3047*663afb9bSAndroid Build Coastguard Worker 	if (seg->contents)
3048*663afb9bSAndroid Build Coastguard Worker 		return 0; /* already materialized */
3049*663afb9bSAndroid Build Coastguard Worker 
3050*663afb9bSAndroid Build Coastguard Worker #if defined(EVENT__HAVE_MMAP)
3051*663afb9bSAndroid Build Coastguard Worker 	if (!(flags & EVBUF_FS_DISABLE_MMAP)) {
3052*663afb9bSAndroid Build Coastguard Worker 		off_t offset_rounded = 0, offset_leftover = 0;
3053*663afb9bSAndroid Build Coastguard Worker 		void *mapped;
3054*663afb9bSAndroid Build Coastguard Worker 		if (offset) {
3055*663afb9bSAndroid Build Coastguard Worker 			/* mmap implementations don't generally like us
3056*663afb9bSAndroid Build Coastguard Worker 			 * to have an offset that isn't a round  */
3057*663afb9bSAndroid Build Coastguard Worker 			long page_size = get_page_size();
3058*663afb9bSAndroid Build Coastguard Worker 			if (page_size == -1)
3059*663afb9bSAndroid Build Coastguard Worker 				goto err;
3060*663afb9bSAndroid Build Coastguard Worker 			offset_leftover = offset % page_size;
3061*663afb9bSAndroid Build Coastguard Worker 			offset_rounded = offset - offset_leftover;
3062*663afb9bSAndroid Build Coastguard Worker 		}
3063*663afb9bSAndroid Build Coastguard Worker 		mapped = mmap(NULL, length + offset_leftover,
3064*663afb9bSAndroid Build Coastguard Worker 		    PROT_READ,
3065*663afb9bSAndroid Build Coastguard Worker #ifdef MAP_NOCACHE
3066*663afb9bSAndroid Build Coastguard Worker 		    MAP_NOCACHE | /* ??? */
3067*663afb9bSAndroid Build Coastguard Worker #endif
3068*663afb9bSAndroid Build Coastguard Worker #ifdef MAP_FILE
3069*663afb9bSAndroid Build Coastguard Worker 		    MAP_FILE |
3070*663afb9bSAndroid Build Coastguard Worker #endif
3071*663afb9bSAndroid Build Coastguard Worker 		    MAP_PRIVATE,
3072*663afb9bSAndroid Build Coastguard Worker 		    fd, offset_rounded);
3073*663afb9bSAndroid Build Coastguard Worker 		if (mapped == MAP_FAILED) {
3074*663afb9bSAndroid Build Coastguard Worker 			event_warn("%s: mmap(%d, %d, %zu) failed",
3075*663afb9bSAndroid Build Coastguard Worker 			    __func__, fd, 0, (size_t)(offset + length));
3076*663afb9bSAndroid Build Coastguard Worker 		} else {
3077*663afb9bSAndroid Build Coastguard Worker 			seg->mapping = mapped;
3078*663afb9bSAndroid Build Coastguard Worker 			seg->contents = (char*)mapped+offset_leftover;
3079*663afb9bSAndroid Build Coastguard Worker 			seg->mmap_offset = 0;
3080*663afb9bSAndroid Build Coastguard Worker 			seg->is_mapping = 1;
3081*663afb9bSAndroid Build Coastguard Worker 			goto done;
3082*663afb9bSAndroid Build Coastguard Worker 		}
3083*663afb9bSAndroid Build Coastguard Worker 	}
3084*663afb9bSAndroid Build Coastguard Worker #endif
3085*663afb9bSAndroid Build Coastguard Worker #ifdef _WIN32
3086*663afb9bSAndroid Build Coastguard Worker 	if (!(flags & EVBUF_FS_DISABLE_MMAP)) {
3087*663afb9bSAndroid Build Coastguard Worker 		intptr_t h = _get_osfhandle(fd);
3088*663afb9bSAndroid Build Coastguard Worker 		HANDLE m;
3089*663afb9bSAndroid Build Coastguard Worker 		ev_uint64_t total_size = length+offset;
3090*663afb9bSAndroid Build Coastguard Worker 		if ((HANDLE)h == INVALID_HANDLE_VALUE)
3091*663afb9bSAndroid Build Coastguard Worker 			goto err;
3092*663afb9bSAndroid Build Coastguard Worker 		m = CreateFileMapping((HANDLE)h, NULL, PAGE_READONLY,
3093*663afb9bSAndroid Build Coastguard Worker 		    (total_size >> 32), total_size & 0xfffffffful,
3094*663afb9bSAndroid Build Coastguard Worker 		    NULL);
3095*663afb9bSAndroid Build Coastguard Worker 		if (m != INVALID_HANDLE_VALUE) { /* Does h leak? */
3096*663afb9bSAndroid Build Coastguard Worker 			seg->mapping_handle = m;
3097*663afb9bSAndroid Build Coastguard Worker 			seg->mmap_offset = offset;
3098*663afb9bSAndroid Build Coastguard Worker 			seg->is_mapping = 1;
3099*663afb9bSAndroid Build Coastguard Worker 			goto done;
3100*663afb9bSAndroid Build Coastguard Worker 		}
3101*663afb9bSAndroid Build Coastguard Worker 	}
3102*663afb9bSAndroid Build Coastguard Worker #endif
3103*663afb9bSAndroid Build Coastguard Worker 	{
3104*663afb9bSAndroid Build Coastguard Worker 		ev_off_t start_pos = lseek(fd, 0, SEEK_CUR), pos;
3105*663afb9bSAndroid Build Coastguard Worker 		ev_off_t read_so_far = 0;
3106*663afb9bSAndroid Build Coastguard Worker 		char *mem;
3107*663afb9bSAndroid Build Coastguard Worker 		int e;
3108*663afb9bSAndroid Build Coastguard Worker 		ev_ssize_t n = 0;
3109*663afb9bSAndroid Build Coastguard Worker 		if (!(mem = mm_malloc(length)))
3110*663afb9bSAndroid Build Coastguard Worker 			goto err;
3111*663afb9bSAndroid Build Coastguard Worker 		if (start_pos < 0) {
3112*663afb9bSAndroid Build Coastguard Worker 			mm_free(mem);
3113*663afb9bSAndroid Build Coastguard Worker 			goto err;
3114*663afb9bSAndroid Build Coastguard Worker 		}
3115*663afb9bSAndroid Build Coastguard Worker 		if (lseek(fd, offset, SEEK_SET) < 0) {
3116*663afb9bSAndroid Build Coastguard Worker 			mm_free(mem);
3117*663afb9bSAndroid Build Coastguard Worker 			goto err;
3118*663afb9bSAndroid Build Coastguard Worker 		}
3119*663afb9bSAndroid Build Coastguard Worker 		while (read_so_far < length) {
3120*663afb9bSAndroid Build Coastguard Worker 			n = read(fd, mem+read_so_far, length-read_so_far);
3121*663afb9bSAndroid Build Coastguard Worker 			if (n <= 0)
3122*663afb9bSAndroid Build Coastguard Worker 				break;
3123*663afb9bSAndroid Build Coastguard Worker 			read_so_far += n;
3124*663afb9bSAndroid Build Coastguard Worker 		}
3125*663afb9bSAndroid Build Coastguard Worker 
3126*663afb9bSAndroid Build Coastguard Worker 		e = errno;
3127*663afb9bSAndroid Build Coastguard Worker 		pos = lseek(fd, start_pos, SEEK_SET);
3128*663afb9bSAndroid Build Coastguard Worker 		if (n < 0 || (n == 0 && length > read_so_far)) {
3129*663afb9bSAndroid Build Coastguard Worker 			mm_free(mem);
3130*663afb9bSAndroid Build Coastguard Worker 			errno = e;
3131*663afb9bSAndroid Build Coastguard Worker 			goto err;
3132*663afb9bSAndroid Build Coastguard Worker 		} else if (pos < 0) {
3133*663afb9bSAndroid Build Coastguard Worker 			mm_free(mem);
3134*663afb9bSAndroid Build Coastguard Worker 			goto err;
3135*663afb9bSAndroid Build Coastguard Worker 		}
3136*663afb9bSAndroid Build Coastguard Worker 
3137*663afb9bSAndroid Build Coastguard Worker 		seg->contents = mem;
3138*663afb9bSAndroid Build Coastguard Worker 	}
3139*663afb9bSAndroid Build Coastguard Worker 
3140*663afb9bSAndroid Build Coastguard Worker done:
3141*663afb9bSAndroid Build Coastguard Worker 	return 0;
3142*663afb9bSAndroid Build Coastguard Worker err:
3143*663afb9bSAndroid Build Coastguard Worker 	return -1;
3144*663afb9bSAndroid Build Coastguard Worker }
3145*663afb9bSAndroid Build Coastguard Worker 
evbuffer_file_segment_add_cleanup_cb(struct evbuffer_file_segment * seg,evbuffer_file_segment_cleanup_cb cb,void * arg)3146*663afb9bSAndroid Build Coastguard Worker void evbuffer_file_segment_add_cleanup_cb(struct evbuffer_file_segment *seg,
3147*663afb9bSAndroid Build Coastguard Worker 	evbuffer_file_segment_cleanup_cb cb, void* arg)
3148*663afb9bSAndroid Build Coastguard Worker {
3149*663afb9bSAndroid Build Coastguard Worker 	EVUTIL_ASSERT(seg->refcnt > 0);
3150*663afb9bSAndroid Build Coastguard Worker 	seg->cleanup_cb = cb;
3151*663afb9bSAndroid Build Coastguard Worker 	seg->cleanup_cb_arg = arg;
3152*663afb9bSAndroid Build Coastguard Worker }
3153*663afb9bSAndroid Build Coastguard Worker 
3154*663afb9bSAndroid Build Coastguard Worker void
evbuffer_file_segment_free(struct evbuffer_file_segment * seg)3155*663afb9bSAndroid Build Coastguard Worker evbuffer_file_segment_free(struct evbuffer_file_segment *seg)
3156*663afb9bSAndroid Build Coastguard Worker {
3157*663afb9bSAndroid Build Coastguard Worker 	int refcnt;
3158*663afb9bSAndroid Build Coastguard Worker 	EVLOCK_LOCK(seg->lock, 0);
3159*663afb9bSAndroid Build Coastguard Worker 	refcnt = --seg->refcnt;
3160*663afb9bSAndroid Build Coastguard Worker 	EVLOCK_UNLOCK(seg->lock, 0);
3161*663afb9bSAndroid Build Coastguard Worker 	if (refcnt > 0)
3162*663afb9bSAndroid Build Coastguard Worker 		return;
3163*663afb9bSAndroid Build Coastguard Worker 	EVUTIL_ASSERT(refcnt == 0);
3164*663afb9bSAndroid Build Coastguard Worker 
3165*663afb9bSAndroid Build Coastguard Worker 	if (seg->is_mapping) {
3166*663afb9bSAndroid Build Coastguard Worker #ifdef _WIN32
3167*663afb9bSAndroid Build Coastguard Worker 		CloseHandle(seg->mapping_handle);
3168*663afb9bSAndroid Build Coastguard Worker #elif defined (EVENT__HAVE_MMAP)
3169*663afb9bSAndroid Build Coastguard Worker 		off_t offset_leftover;
3170*663afb9bSAndroid Build Coastguard Worker 		offset_leftover = seg->file_offset % get_page_size();
3171*663afb9bSAndroid Build Coastguard Worker 		if (munmap(seg->mapping, seg->length + offset_leftover) == -1)
3172*663afb9bSAndroid Build Coastguard Worker 			event_warn("%s: munmap failed", __func__);
3173*663afb9bSAndroid Build Coastguard Worker #endif
3174*663afb9bSAndroid Build Coastguard Worker 	} else if (seg->contents) {
3175*663afb9bSAndroid Build Coastguard Worker 		mm_free(seg->contents);
3176*663afb9bSAndroid Build Coastguard Worker 	}
3177*663afb9bSAndroid Build Coastguard Worker 
3178*663afb9bSAndroid Build Coastguard Worker 	if ((seg->flags & EVBUF_FS_CLOSE_ON_FREE) && seg->fd >= 0) {
3179*663afb9bSAndroid Build Coastguard Worker 		close(seg->fd);
3180*663afb9bSAndroid Build Coastguard Worker 	}
3181*663afb9bSAndroid Build Coastguard Worker 
3182*663afb9bSAndroid Build Coastguard Worker 	if (seg->cleanup_cb) {
3183*663afb9bSAndroid Build Coastguard Worker 		(*seg->cleanup_cb)((struct evbuffer_file_segment const*)seg,
3184*663afb9bSAndroid Build Coastguard Worker 		    seg->flags, seg->cleanup_cb_arg);
3185*663afb9bSAndroid Build Coastguard Worker 		seg->cleanup_cb = NULL;
3186*663afb9bSAndroid Build Coastguard Worker 		seg->cleanup_cb_arg = NULL;
3187*663afb9bSAndroid Build Coastguard Worker 	}
3188*663afb9bSAndroid Build Coastguard Worker 
3189*663afb9bSAndroid Build Coastguard Worker 	EVTHREAD_FREE_LOCK(seg->lock, 0);
3190*663afb9bSAndroid Build Coastguard Worker 	mm_free(seg);
3191*663afb9bSAndroid Build Coastguard Worker }
3192*663afb9bSAndroid Build Coastguard Worker 
3193*663afb9bSAndroid Build Coastguard Worker int
evbuffer_add_file_segment(struct evbuffer * buf,struct evbuffer_file_segment * seg,ev_off_t offset,ev_off_t length)3194*663afb9bSAndroid Build Coastguard Worker evbuffer_add_file_segment(struct evbuffer *buf,
3195*663afb9bSAndroid Build Coastguard Worker     struct evbuffer_file_segment *seg, ev_off_t offset, ev_off_t length)
3196*663afb9bSAndroid Build Coastguard Worker {
3197*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain *chain;
3198*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_chain_file_segment *extra;
3199*663afb9bSAndroid Build Coastguard Worker 	int can_use_sendfile = 0;
3200*663afb9bSAndroid Build Coastguard Worker 
3201*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buf);
3202*663afb9bSAndroid Build Coastguard Worker 	EVLOCK_LOCK(seg->lock, 0);
3203*663afb9bSAndroid Build Coastguard Worker 	if (buf->flags & EVBUFFER_FLAG_DRAINS_TO_FD) {
3204*663afb9bSAndroid Build Coastguard Worker 		can_use_sendfile = 1;
3205*663afb9bSAndroid Build Coastguard Worker 	} else {
3206*663afb9bSAndroid Build Coastguard Worker 		if (!seg->contents) {
3207*663afb9bSAndroid Build Coastguard Worker 			if (evbuffer_file_segment_materialize(seg)<0) {
3208*663afb9bSAndroid Build Coastguard Worker 				EVLOCK_UNLOCK(seg->lock, 0);
3209*663afb9bSAndroid Build Coastguard Worker 				EVBUFFER_UNLOCK(buf);
3210*663afb9bSAndroid Build Coastguard Worker 				return -1;
3211*663afb9bSAndroid Build Coastguard Worker 			}
3212*663afb9bSAndroid Build Coastguard Worker 		}
3213*663afb9bSAndroid Build Coastguard Worker 	}
3214*663afb9bSAndroid Build Coastguard Worker 	EVLOCK_UNLOCK(seg->lock, 0);
3215*663afb9bSAndroid Build Coastguard Worker 
3216*663afb9bSAndroid Build Coastguard Worker 	if (buf->freeze_end)
3217*663afb9bSAndroid Build Coastguard Worker 		goto err;
3218*663afb9bSAndroid Build Coastguard Worker 
3219*663afb9bSAndroid Build Coastguard Worker 	if (length < 0) {
3220*663afb9bSAndroid Build Coastguard Worker 		if (offset > seg->length)
3221*663afb9bSAndroid Build Coastguard Worker 			goto err;
3222*663afb9bSAndroid Build Coastguard Worker 		length = seg->length - offset;
3223*663afb9bSAndroid Build Coastguard Worker 	}
3224*663afb9bSAndroid Build Coastguard Worker 
3225*663afb9bSAndroid Build Coastguard Worker 	/* Can we actually add this? */
3226*663afb9bSAndroid Build Coastguard Worker 	if (offset+length > seg->length)
3227*663afb9bSAndroid Build Coastguard Worker 		goto err;
3228*663afb9bSAndroid Build Coastguard Worker 
3229*663afb9bSAndroid Build Coastguard Worker 	chain = evbuffer_chain_new(sizeof(struct evbuffer_chain_file_segment));
3230*663afb9bSAndroid Build Coastguard Worker 	if (!chain)
3231*663afb9bSAndroid Build Coastguard Worker 		goto err;
3232*663afb9bSAndroid Build Coastguard Worker 	extra = EVBUFFER_CHAIN_EXTRA(struct evbuffer_chain_file_segment, chain);
3233*663afb9bSAndroid Build Coastguard Worker 
3234*663afb9bSAndroid Build Coastguard Worker 	chain->flags |= EVBUFFER_IMMUTABLE|EVBUFFER_FILESEGMENT;
3235*663afb9bSAndroid Build Coastguard Worker 	if (can_use_sendfile && seg->can_sendfile) {
3236*663afb9bSAndroid Build Coastguard Worker 		chain->flags |= EVBUFFER_SENDFILE;
3237*663afb9bSAndroid Build Coastguard Worker 		chain->misalign = seg->file_offset + offset;
3238*663afb9bSAndroid Build Coastguard Worker 		chain->off = length;
3239*663afb9bSAndroid Build Coastguard Worker 		chain->buffer_len = chain->misalign + length;
3240*663afb9bSAndroid Build Coastguard Worker 	} else if (seg->is_mapping) {
3241*663afb9bSAndroid Build Coastguard Worker #ifdef _WIN32
3242*663afb9bSAndroid Build Coastguard Worker 		ev_uint64_t total_offset = seg->mmap_offset+offset;
3243*663afb9bSAndroid Build Coastguard Worker 		ev_uint64_t offset_rounded=0, offset_remaining=0;
3244*663afb9bSAndroid Build Coastguard Worker 		LPVOID data;
3245*663afb9bSAndroid Build Coastguard Worker 		if (total_offset) {
3246*663afb9bSAndroid Build Coastguard Worker 			SYSTEM_INFO si;
3247*663afb9bSAndroid Build Coastguard Worker 			memset(&si, 0, sizeof(si)); /* cargo cult */
3248*663afb9bSAndroid Build Coastguard Worker 			GetSystemInfo(&si);
3249*663afb9bSAndroid Build Coastguard Worker 			offset_remaining = total_offset % si.dwAllocationGranularity;
3250*663afb9bSAndroid Build Coastguard Worker 			offset_rounded = total_offset - offset_remaining;
3251*663afb9bSAndroid Build Coastguard Worker 		}
3252*663afb9bSAndroid Build Coastguard Worker 		data = MapViewOfFile(
3253*663afb9bSAndroid Build Coastguard Worker 			seg->mapping_handle,
3254*663afb9bSAndroid Build Coastguard Worker 			FILE_MAP_READ,
3255*663afb9bSAndroid Build Coastguard Worker 			offset_rounded >> 32,
3256*663afb9bSAndroid Build Coastguard Worker 			offset_rounded & 0xfffffffful,
3257*663afb9bSAndroid Build Coastguard Worker 			length + offset_remaining);
3258*663afb9bSAndroid Build Coastguard Worker 		if (data == NULL) {
3259*663afb9bSAndroid Build Coastguard Worker 			mm_free(chain);
3260*663afb9bSAndroid Build Coastguard Worker 			goto err;
3261*663afb9bSAndroid Build Coastguard Worker 		}
3262*663afb9bSAndroid Build Coastguard Worker 		chain->buffer = (unsigned char*) data;
3263*663afb9bSAndroid Build Coastguard Worker 		chain->buffer_len = length+offset_remaining;
3264*663afb9bSAndroid Build Coastguard Worker 		chain->misalign = offset_remaining;
3265*663afb9bSAndroid Build Coastguard Worker 		chain->off = length;
3266*663afb9bSAndroid Build Coastguard Worker #else
3267*663afb9bSAndroid Build Coastguard Worker 		chain->buffer = (unsigned char*)(seg->contents + offset);
3268*663afb9bSAndroid Build Coastguard Worker 		chain->buffer_len = length;
3269*663afb9bSAndroid Build Coastguard Worker 		chain->off = length;
3270*663afb9bSAndroid Build Coastguard Worker #endif
3271*663afb9bSAndroid Build Coastguard Worker 	} else {
3272*663afb9bSAndroid Build Coastguard Worker 		chain->buffer = (unsigned char*)(seg->contents + offset);
3273*663afb9bSAndroid Build Coastguard Worker 		chain->buffer_len = length;
3274*663afb9bSAndroid Build Coastguard Worker 		chain->off = length;
3275*663afb9bSAndroid Build Coastguard Worker 	}
3276*663afb9bSAndroid Build Coastguard Worker 
3277*663afb9bSAndroid Build Coastguard Worker 	EVLOCK_LOCK(seg->lock, 0);
3278*663afb9bSAndroid Build Coastguard Worker 	++seg->refcnt;
3279*663afb9bSAndroid Build Coastguard Worker 	EVLOCK_UNLOCK(seg->lock, 0);
3280*663afb9bSAndroid Build Coastguard Worker 	extra->segment = seg;
3281*663afb9bSAndroid Build Coastguard Worker 	buf->n_add_for_cb += length;
3282*663afb9bSAndroid Build Coastguard Worker 	evbuffer_chain_insert(buf, chain);
3283*663afb9bSAndroid Build Coastguard Worker 
3284*663afb9bSAndroid Build Coastguard Worker 	evbuffer_invoke_callbacks_(buf);
3285*663afb9bSAndroid Build Coastguard Worker 
3286*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buf);
3287*663afb9bSAndroid Build Coastguard Worker 
3288*663afb9bSAndroid Build Coastguard Worker 	return 0;
3289*663afb9bSAndroid Build Coastguard Worker err:
3290*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buf);
3291*663afb9bSAndroid Build Coastguard Worker 	evbuffer_file_segment_free(seg); /* Lowers the refcount */
3292*663afb9bSAndroid Build Coastguard Worker 	return -1;
3293*663afb9bSAndroid Build Coastguard Worker }
3294*663afb9bSAndroid Build Coastguard Worker 
3295*663afb9bSAndroid Build Coastguard Worker int
evbuffer_add_file(struct evbuffer * buf,int fd,ev_off_t offset,ev_off_t length)3296*663afb9bSAndroid Build Coastguard Worker evbuffer_add_file(struct evbuffer *buf, int fd, ev_off_t offset, ev_off_t length)
3297*663afb9bSAndroid Build Coastguard Worker {
3298*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_file_segment *seg;
3299*663afb9bSAndroid Build Coastguard Worker 	unsigned flags = EVBUF_FS_CLOSE_ON_FREE;
3300*663afb9bSAndroid Build Coastguard Worker 	int r;
3301*663afb9bSAndroid Build Coastguard Worker 
3302*663afb9bSAndroid Build Coastguard Worker 	seg = evbuffer_file_segment_new(fd, offset, length, flags);
3303*663afb9bSAndroid Build Coastguard Worker 	if (!seg)
3304*663afb9bSAndroid Build Coastguard Worker 		return -1;
3305*663afb9bSAndroid Build Coastguard Worker 	r = evbuffer_add_file_segment(buf, seg, 0, length);
3306*663afb9bSAndroid Build Coastguard Worker 	if (r == 0)
3307*663afb9bSAndroid Build Coastguard Worker 		evbuffer_file_segment_free(seg);
3308*663afb9bSAndroid Build Coastguard Worker 	return r;
3309*663afb9bSAndroid Build Coastguard Worker }
3310*663afb9bSAndroid Build Coastguard Worker 
3311*663afb9bSAndroid Build Coastguard Worker int
evbuffer_setcb(struct evbuffer * buffer,evbuffer_cb cb,void * cbarg)3312*663afb9bSAndroid Build Coastguard Worker evbuffer_setcb(struct evbuffer *buffer, evbuffer_cb cb, void *cbarg)
3313*663afb9bSAndroid Build Coastguard Worker {
3314*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buffer);
3315*663afb9bSAndroid Build Coastguard Worker 
3316*663afb9bSAndroid Build Coastguard Worker 	if (!LIST_EMPTY(&buffer->callbacks))
3317*663afb9bSAndroid Build Coastguard Worker 		evbuffer_remove_all_callbacks(buffer);
3318*663afb9bSAndroid Build Coastguard Worker 
3319*663afb9bSAndroid Build Coastguard Worker 	if (cb) {
3320*663afb9bSAndroid Build Coastguard Worker 		struct evbuffer_cb_entry *ent =
3321*663afb9bSAndroid Build Coastguard Worker 		    evbuffer_add_cb(buffer, NULL, cbarg);
3322*663afb9bSAndroid Build Coastguard Worker 		if (!ent) {
3323*663afb9bSAndroid Build Coastguard Worker 			EVBUFFER_UNLOCK(buffer);
3324*663afb9bSAndroid Build Coastguard Worker 			return -1;
3325*663afb9bSAndroid Build Coastguard Worker 		}
3326*663afb9bSAndroid Build Coastguard Worker 		ent->cb.cb_obsolete = cb;
3327*663afb9bSAndroid Build Coastguard Worker 		ent->flags |= EVBUFFER_CB_OBSOLETE;
3328*663afb9bSAndroid Build Coastguard Worker 	}
3329*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buffer);
3330*663afb9bSAndroid Build Coastguard Worker 	return 0;
3331*663afb9bSAndroid Build Coastguard Worker }
3332*663afb9bSAndroid Build Coastguard Worker 
3333*663afb9bSAndroid Build Coastguard Worker struct evbuffer_cb_entry *
evbuffer_add_cb(struct evbuffer * buffer,evbuffer_cb_func cb,void * cbarg)3334*663afb9bSAndroid Build Coastguard Worker evbuffer_add_cb(struct evbuffer *buffer, evbuffer_cb_func cb, void *cbarg)
3335*663afb9bSAndroid Build Coastguard Worker {
3336*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_cb_entry *e;
3337*663afb9bSAndroid Build Coastguard Worker 	if (! (e = mm_calloc(1, sizeof(struct evbuffer_cb_entry))))
3338*663afb9bSAndroid Build Coastguard Worker 		return NULL;
3339*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buffer);
3340*663afb9bSAndroid Build Coastguard Worker 	e->cb.cb_func = cb;
3341*663afb9bSAndroid Build Coastguard Worker 	e->cbarg = cbarg;
3342*663afb9bSAndroid Build Coastguard Worker 	e->flags = EVBUFFER_CB_ENABLED;
3343*663afb9bSAndroid Build Coastguard Worker 	LIST_INSERT_HEAD(&buffer->callbacks, e, next);
3344*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buffer);
3345*663afb9bSAndroid Build Coastguard Worker 	return e;
3346*663afb9bSAndroid Build Coastguard Worker }
3347*663afb9bSAndroid Build Coastguard Worker 
3348*663afb9bSAndroid Build Coastguard Worker int
evbuffer_remove_cb_entry(struct evbuffer * buffer,struct evbuffer_cb_entry * ent)3349*663afb9bSAndroid Build Coastguard Worker evbuffer_remove_cb_entry(struct evbuffer *buffer,
3350*663afb9bSAndroid Build Coastguard Worker 			 struct evbuffer_cb_entry *ent)
3351*663afb9bSAndroid Build Coastguard Worker {
3352*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buffer);
3353*663afb9bSAndroid Build Coastguard Worker 	LIST_REMOVE(ent, next);
3354*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buffer);
3355*663afb9bSAndroid Build Coastguard Worker 	mm_free(ent);
3356*663afb9bSAndroid Build Coastguard Worker 	return 0;
3357*663afb9bSAndroid Build Coastguard Worker }
3358*663afb9bSAndroid Build Coastguard Worker 
3359*663afb9bSAndroid Build Coastguard Worker int
evbuffer_remove_cb(struct evbuffer * buffer,evbuffer_cb_func cb,void * cbarg)3360*663afb9bSAndroid Build Coastguard Worker evbuffer_remove_cb(struct evbuffer *buffer, evbuffer_cb_func cb, void *cbarg)
3361*663afb9bSAndroid Build Coastguard Worker {
3362*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer_cb_entry *cbent;
3363*663afb9bSAndroid Build Coastguard Worker 	int result = -1;
3364*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buffer);
3365*663afb9bSAndroid Build Coastguard Worker 	LIST_FOREACH(cbent, &buffer->callbacks, next) {
3366*663afb9bSAndroid Build Coastguard Worker 		if (cb == cbent->cb.cb_func && cbarg == cbent->cbarg) {
3367*663afb9bSAndroid Build Coastguard Worker 			result = evbuffer_remove_cb_entry(buffer, cbent);
3368*663afb9bSAndroid Build Coastguard Worker 			goto done;
3369*663afb9bSAndroid Build Coastguard Worker 		}
3370*663afb9bSAndroid Build Coastguard Worker 	}
3371*663afb9bSAndroid Build Coastguard Worker done:
3372*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buffer);
3373*663afb9bSAndroid Build Coastguard Worker 	return result;
3374*663afb9bSAndroid Build Coastguard Worker }
3375*663afb9bSAndroid Build Coastguard Worker 
3376*663afb9bSAndroid Build Coastguard Worker int
evbuffer_cb_set_flags(struct evbuffer * buffer,struct evbuffer_cb_entry * cb,ev_uint32_t flags)3377*663afb9bSAndroid Build Coastguard Worker evbuffer_cb_set_flags(struct evbuffer *buffer,
3378*663afb9bSAndroid Build Coastguard Worker 		      struct evbuffer_cb_entry *cb, ev_uint32_t flags)
3379*663afb9bSAndroid Build Coastguard Worker {
3380*663afb9bSAndroid Build Coastguard Worker 	/* the user isn't allowed to mess with these. */
3381*663afb9bSAndroid Build Coastguard Worker 	flags &= ~EVBUFFER_CB_INTERNAL_FLAGS;
3382*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buffer);
3383*663afb9bSAndroid Build Coastguard Worker 	cb->flags |= flags;
3384*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buffer);
3385*663afb9bSAndroid Build Coastguard Worker 	return 0;
3386*663afb9bSAndroid Build Coastguard Worker }
3387*663afb9bSAndroid Build Coastguard Worker 
3388*663afb9bSAndroid Build Coastguard Worker int
evbuffer_cb_clear_flags(struct evbuffer * buffer,struct evbuffer_cb_entry * cb,ev_uint32_t flags)3389*663afb9bSAndroid Build Coastguard Worker evbuffer_cb_clear_flags(struct evbuffer *buffer,
3390*663afb9bSAndroid Build Coastguard Worker 		      struct evbuffer_cb_entry *cb, ev_uint32_t flags)
3391*663afb9bSAndroid Build Coastguard Worker {
3392*663afb9bSAndroid Build Coastguard Worker 	/* the user isn't allowed to mess with these. */
3393*663afb9bSAndroid Build Coastguard Worker 	flags &= ~EVBUFFER_CB_INTERNAL_FLAGS;
3394*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buffer);
3395*663afb9bSAndroid Build Coastguard Worker 	cb->flags &= ~flags;
3396*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buffer);
3397*663afb9bSAndroid Build Coastguard Worker 	return 0;
3398*663afb9bSAndroid Build Coastguard Worker }
3399*663afb9bSAndroid Build Coastguard Worker 
3400*663afb9bSAndroid Build Coastguard Worker int
evbuffer_freeze(struct evbuffer * buffer,int start)3401*663afb9bSAndroid Build Coastguard Worker evbuffer_freeze(struct evbuffer *buffer, int start)
3402*663afb9bSAndroid Build Coastguard Worker {
3403*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buffer);
3404*663afb9bSAndroid Build Coastguard Worker 	if (start)
3405*663afb9bSAndroid Build Coastguard Worker 		buffer->freeze_start = 1;
3406*663afb9bSAndroid Build Coastguard Worker 	else
3407*663afb9bSAndroid Build Coastguard Worker 		buffer->freeze_end = 1;
3408*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buffer);
3409*663afb9bSAndroid Build Coastguard Worker 	return 0;
3410*663afb9bSAndroid Build Coastguard Worker }
3411*663afb9bSAndroid Build Coastguard Worker 
3412*663afb9bSAndroid Build Coastguard Worker int
evbuffer_unfreeze(struct evbuffer * buffer,int start)3413*663afb9bSAndroid Build Coastguard Worker evbuffer_unfreeze(struct evbuffer *buffer, int start)
3414*663afb9bSAndroid Build Coastguard Worker {
3415*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buffer);
3416*663afb9bSAndroid Build Coastguard Worker 	if (start)
3417*663afb9bSAndroid Build Coastguard Worker 		buffer->freeze_start = 0;
3418*663afb9bSAndroid Build Coastguard Worker 	else
3419*663afb9bSAndroid Build Coastguard Worker 		buffer->freeze_end = 0;
3420*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buffer);
3421*663afb9bSAndroid Build Coastguard Worker 	return 0;
3422*663afb9bSAndroid Build Coastguard Worker }
3423*663afb9bSAndroid Build Coastguard Worker 
3424*663afb9bSAndroid Build Coastguard Worker #if 0
3425*663afb9bSAndroid Build Coastguard Worker void
3426*663afb9bSAndroid Build Coastguard Worker evbuffer_cb_suspend(struct evbuffer *buffer, struct evbuffer_cb_entry *cb)
3427*663afb9bSAndroid Build Coastguard Worker {
3428*663afb9bSAndroid Build Coastguard Worker 	if (!(cb->flags & EVBUFFER_CB_SUSPENDED)) {
3429*663afb9bSAndroid Build Coastguard Worker 		cb->size_before_suspend = evbuffer_get_length(buffer);
3430*663afb9bSAndroid Build Coastguard Worker 		cb->flags |= EVBUFFER_CB_SUSPENDED;
3431*663afb9bSAndroid Build Coastguard Worker 	}
3432*663afb9bSAndroid Build Coastguard Worker }
3433*663afb9bSAndroid Build Coastguard Worker 
3434*663afb9bSAndroid Build Coastguard Worker void
3435*663afb9bSAndroid Build Coastguard Worker evbuffer_cb_unsuspend(struct evbuffer *buffer, struct evbuffer_cb_entry *cb)
3436*663afb9bSAndroid Build Coastguard Worker {
3437*663afb9bSAndroid Build Coastguard Worker 	if ((cb->flags & EVBUFFER_CB_SUSPENDED)) {
3438*663afb9bSAndroid Build Coastguard Worker 		unsigned call = (cb->flags & EVBUFFER_CB_CALL_ON_UNSUSPEND);
3439*663afb9bSAndroid Build Coastguard Worker 		size_t sz = cb->size_before_suspend;
3440*663afb9bSAndroid Build Coastguard Worker 		cb->flags &= ~(EVBUFFER_CB_SUSPENDED|
3441*663afb9bSAndroid Build Coastguard Worker 			       EVBUFFER_CB_CALL_ON_UNSUSPEND);
3442*663afb9bSAndroid Build Coastguard Worker 		cb->size_before_suspend = 0;
3443*663afb9bSAndroid Build Coastguard Worker 		if (call && (cb->flags & EVBUFFER_CB_ENABLED)) {
3444*663afb9bSAndroid Build Coastguard Worker 			cb->cb(buffer, sz, evbuffer_get_length(buffer), cb->cbarg);
3445*663afb9bSAndroid Build Coastguard Worker 		}
3446*663afb9bSAndroid Build Coastguard Worker 	}
3447*663afb9bSAndroid Build Coastguard Worker }
3448*663afb9bSAndroid Build Coastguard Worker #endif
3449*663afb9bSAndroid Build Coastguard Worker 
3450*663afb9bSAndroid Build Coastguard Worker int
evbuffer_get_callbacks_(struct evbuffer * buffer,struct event_callback ** cbs,int max_cbs)3451*663afb9bSAndroid Build Coastguard Worker evbuffer_get_callbacks_(struct evbuffer *buffer, struct event_callback **cbs,
3452*663afb9bSAndroid Build Coastguard Worker     int max_cbs)
3453*663afb9bSAndroid Build Coastguard Worker {
3454*663afb9bSAndroid Build Coastguard Worker 	int r = 0;
3455*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_LOCK(buffer);
3456*663afb9bSAndroid Build Coastguard Worker 	if (buffer->deferred_cbs) {
3457*663afb9bSAndroid Build Coastguard Worker 		if (max_cbs < 1) {
3458*663afb9bSAndroid Build Coastguard Worker 			r = -1;
3459*663afb9bSAndroid Build Coastguard Worker 			goto done;
3460*663afb9bSAndroid Build Coastguard Worker 		}
3461*663afb9bSAndroid Build Coastguard Worker 		cbs[0] = &buffer->deferred;
3462*663afb9bSAndroid Build Coastguard Worker 		r = 1;
3463*663afb9bSAndroid Build Coastguard Worker 	}
3464*663afb9bSAndroid Build Coastguard Worker done:
3465*663afb9bSAndroid Build Coastguard Worker 	EVBUFFER_UNLOCK(buffer);
3466*663afb9bSAndroid Build Coastguard Worker 	return r;
3467*663afb9bSAndroid Build Coastguard Worker }
3468