1275970Scy/*
2275970Scy * Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
3275970Scy * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
4275970Scy *
5275970Scy * Redistribution and use in source and binary forms, with or without
6275970Scy * modification, are permitted provided that the following conditions
7275970Scy * are met:
8275970Scy * 1. Redistributions of source code must retain the above copyright
9275970Scy *    notice, this list of conditions and the following disclaimer.
10275970Scy * 2. Redistributions in binary form must reproduce the above copyright
11275970Scy *    notice, this list of conditions and the following disclaimer in the
12275970Scy *    documentation and/or other materials provided with the distribution.
13275970Scy * 3. The name of the author may not be used to endorse or promote products
14275970Scy *    derived from this software without specific prior written permission.
15275970Scy *
16275970Scy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17275970Scy * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18275970Scy * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19275970Scy * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20275970Scy * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21275970Scy * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22275970Scy * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23275970Scy * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24275970Scy * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25275970Scy * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26275970Scy */
27275970Scy#ifndef EVBUFFER_INTERNAL_H_INCLUDED_
28275970Scy#define EVBUFFER_INTERNAL_H_INCLUDED_
29275970Scy
30275970Scy#ifdef __cplusplus
31275970Scyextern "C" {
32275970Scy#endif
33275970Scy
34275970Scy#include "event2/event-config.h"
35275970Scy#include "evconfig-private.h"
36275970Scy#include "event2/util.h"
37275970Scy#include "event2/event_struct.h"
38275970Scy#include "util-internal.h"
39275970Scy#include "defer-internal.h"
40275970Scy
41275970Scy/* Experimental cb flag: "never deferred."  Implementation note:
42275970Scy * these callbacks may get an inaccurate view of n_del/n_added in their
43275970Scy * arguments. */
44275970Scy#define EVBUFFER_CB_NODEFER 2
45275970Scy
46275970Scy#ifdef _WIN32
47275970Scy#include <winsock2.h>
48275970Scy#endif
49275970Scy#include <sys/queue.h>
50275970Scy
51275970Scy/* Minimum allocation for a chain.  We define this so that we're burning no
52275970Scy * more than 5% of each allocation on overhead.  It would be nice to lose even
53275970Scy * less space, though. */
54275970Scy#if EVENT__SIZEOF_VOID_P < 8
55275970Scy#define MIN_BUFFER_SIZE	512
56275970Scy#else
57275970Scy#define MIN_BUFFER_SIZE	1024
58275970Scy#endif
59275970Scy
60275970Scy/** A single evbuffer callback for an evbuffer. This function will be invoked
61275970Scy * when bytes are added to or removed from the evbuffer. */
62275970Scystruct evbuffer_cb_entry {
63275970Scy	/** Structures to implement a doubly-linked queue of callbacks */
64275970Scy	LIST_ENTRY(evbuffer_cb_entry) next;
65275970Scy	/** The callback function to invoke when this callback is called.
66275970Scy	    If EVBUFFER_CB_OBSOLETE is set in flags, the cb_obsolete field is
67275970Scy	    valid; otherwise, cb_func is valid. */
68275970Scy	union {
69275970Scy		evbuffer_cb_func cb_func;
70275970Scy		evbuffer_cb cb_obsolete;
71275970Scy	} cb;
72275970Scy	/** Argument to pass to cb. */
73275970Scy	void *cbarg;
74275970Scy	/** Currently set flags on this callback. */
75275970Scy	ev_uint32_t flags;
76275970Scy};
77275970Scy
78275970Scystruct bufferevent;
79275970Scystruct evbuffer_chain;
80275970Scystruct evbuffer {
81275970Scy	/** The first chain in this buffer's linked list of chains. */
82275970Scy	struct evbuffer_chain *first;
83275970Scy	/** The last chain in this buffer's linked list of chains. */
84275970Scy	struct evbuffer_chain *last;
85275970Scy
86275970Scy	/** Pointer to the next pointer pointing at the 'last_with_data' chain.
87275970Scy	 *
88275970Scy	 * To unpack:
89275970Scy	 *
90275970Scy	 * The last_with_data chain is the last chain that has any data in it.
91275970Scy	 * If all chains in the buffer are empty, it is the first chain.
92275970Scy	 * If the buffer has no chains, it is NULL.
93275970Scy	 *
94275970Scy	 * The last_with_datap pointer points at _whatever 'next' pointer_
95275970Scy	 * points at the last_with_datap chain.  If the last_with_data chain
96275970Scy	 * is the first chain, or it is NULL, then the last_with_datap pointer
97275970Scy	 * is &buf->first.
98275970Scy	 */
99275970Scy	struct evbuffer_chain **last_with_datap;
100275970Scy
101275970Scy	/** Total amount of bytes stored in all chains.*/
102275970Scy	size_t total_len;
103275970Scy
104275970Scy	/** Number of bytes we have added to the buffer since we last tried to
105275970Scy	 * invoke callbacks. */
106275970Scy	size_t n_add_for_cb;
107275970Scy	/** Number of bytes we have removed from the buffer since we last
108275970Scy	 * tried to invoke callbacks. */
109275970Scy	size_t n_del_for_cb;
110275970Scy
111275970Scy#ifndef EVENT__DISABLE_THREAD_SUPPORT
112275970Scy	/** A lock used to mediate access to this buffer. */
113275970Scy	void *lock;
114275970Scy#endif
115275970Scy	/** True iff we should free the lock field when we free this
116275970Scy	 * evbuffer. */
117275970Scy	unsigned own_lock : 1;
118275970Scy	/** True iff we should not allow changes to the front of the buffer
119275970Scy	 * (drains or prepends). */
120275970Scy	unsigned freeze_start : 1;
121275970Scy	/** True iff we should not allow changes to the end of the buffer
122275970Scy	 * (appends) */
123275970Scy	unsigned freeze_end : 1;
124275970Scy	/** True iff this evbuffer's callbacks are not invoked immediately
125275970Scy	 * upon a change in the buffer, but instead are deferred to be invoked
126275970Scy	 * from the event_base's loop.	Useful for preventing enormous stack
127275970Scy	 * overflows when we have mutually recursive callbacks, and for
128275970Scy	 * serializing callbacks in a single thread. */
129275970Scy	unsigned deferred_cbs : 1;
130275970Scy#ifdef _WIN32
131275970Scy	/** True iff this buffer is set up for overlapped IO. */
132275970Scy	unsigned is_overlapped : 1;
133275970Scy#endif
134275970Scy	/** Zero or more EVBUFFER_FLAG_* bits */
135275970Scy	ev_uint32_t flags;
136275970Scy
137275970Scy	/** Used to implement deferred callbacks. */
138275970Scy	struct event_base *cb_queue;
139275970Scy
140275970Scy	/** A reference count on this evbuffer.	 When the reference count
141275970Scy	 * reaches 0, the buffer is destroyed.	Manipulated with
142275970Scy	 * evbuffer_incref and evbuffer_decref_and_unlock and
143275970Scy	 * evbuffer_free. */
144275970Scy	int refcnt;
145275970Scy
146275970Scy	/** A struct event_callback handle to make all of this buffer's callbacks
147275970Scy	 * invoked from the event loop. */
148275970Scy	struct event_callback deferred;
149275970Scy
150275970Scy	/** A doubly-linked-list of callback functions */
151275970Scy	LIST_HEAD(evbuffer_cb_queue, evbuffer_cb_entry) callbacks;
152275970Scy
153275970Scy	/** The parent bufferevent object this evbuffer belongs to.
154275970Scy	 * NULL if the evbuffer stands alone. */
155275970Scy	struct bufferevent *parent;
156275970Scy};
157275970Scy
158282408Scy#if EVENT__SIZEOF_OFF_T < EVENT__SIZEOF_SIZE_T
159282408Scytypedef ev_ssize_t ev_misalign_t;
160282408Scy#define EVBUFFER_CHAIN_MAX ((size_t)EV_SSIZE_MAX)
161282408Scy#else
162282408Scytypedef ev_off_t ev_misalign_t;
163282408Scy#if EVENT__SIZEOF_OFF_T > EVENT__SIZEOF_SIZE_T
164282408Scy#define EVBUFFER_CHAIN_MAX EV_SIZE_MAX
165282408Scy#else
166282408Scy#define EVBUFFER_CHAIN_MAX ((size_t)EV_SSIZE_MAX)
167282408Scy#endif
168282408Scy#endif
169282408Scy
170275970Scy/** A single item in an evbuffer. */
171275970Scystruct evbuffer_chain {
172275970Scy	/** points to next buffer in the chain */
173275970Scy	struct evbuffer_chain *next;
174275970Scy
175275970Scy	/** total allocation available in the buffer field. */
176275970Scy	size_t buffer_len;
177275970Scy
178275970Scy	/** unused space at the beginning of buffer or an offset into a
179275970Scy	 * file for sendfile buffers. */
180282408Scy	ev_misalign_t misalign;
181275970Scy
182275970Scy	/** Offset into buffer + misalign at which to start writing.
183275970Scy	 * In other words, the total number of bytes actually stored
184275970Scy	 * in buffer. */
185275970Scy	size_t off;
186275970Scy
187275970Scy	/** Set if special handling is required for this chain */
188275970Scy	unsigned flags;
189275970Scy#define EVBUFFER_FILESEGMENT	0x0001  /**< A chain used for a file segment */
190275970Scy#define EVBUFFER_SENDFILE	0x0002	/**< a chain used with sendfile */
191275970Scy#define EVBUFFER_REFERENCE	0x0004	/**< a chain with a mem reference */
192275970Scy#define EVBUFFER_IMMUTABLE	0x0008	/**< read-only chain */
193275970Scy	/** a chain that mustn't be reallocated or freed, or have its contents
194275970Scy	 * memmoved, until the chain is un-pinned. */
195275970Scy#define EVBUFFER_MEM_PINNED_R	0x0010
196275970Scy#define EVBUFFER_MEM_PINNED_W	0x0020
197275970Scy#define EVBUFFER_MEM_PINNED_ANY (EVBUFFER_MEM_PINNED_R|EVBUFFER_MEM_PINNED_W)
198275970Scy	/** a chain that should be freed, but can't be freed until it is
199275970Scy	 * un-pinned. */
200275970Scy#define EVBUFFER_DANGLING	0x0040
201275970Scy	/** a chain that is a referenced copy of another chain */
202275970Scy#define EVBUFFER_MULTICAST	0x0080
203275970Scy
204275970Scy	/** number of references to this chain */
205275970Scy	int refcnt;
206275970Scy
207275970Scy	/** Usually points to the read-write memory belonging to this
208275970Scy	 * buffer allocated as part of the evbuffer_chain allocation.
209275970Scy	 * For mmap, this can be a read-only buffer and
210275970Scy	 * EVBUFFER_IMMUTABLE will be set in flags.  For sendfile, it
211275970Scy	 * may point to NULL.
212275970Scy	 */
213275970Scy	unsigned char *buffer;
214275970Scy};
215275970Scy
216275970Scy/** callback for a reference chain; lets us know what to do with it when
217275970Scy * we're done with it. Lives at the end of an evbuffer_chain with the
218275970Scy * EVBUFFER_REFERENCE flag set */
219275970Scystruct evbuffer_chain_reference {
220275970Scy	evbuffer_ref_cleanup_cb cleanupfn;
221275970Scy	void *extra;
222275970Scy};
223275970Scy
224275970Scy/** File segment for a file-segment chain.  Lives at the end of an
225275970Scy * evbuffer_chain with the EVBUFFER_FILESEGMENT flag set.  */
226275970Scystruct evbuffer_chain_file_segment {
227275970Scy	struct evbuffer_file_segment *segment;
228275970Scy#ifdef _WIN32
229275970Scy	/** If we're using CreateFileMapping, this is the handle to the view. */
230275970Scy	HANDLE view_handle;
231275970Scy#endif
232275970Scy};
233275970Scy
234275970Scy/* Declared in event2/buffer.h; defined here. */
235275970Scystruct evbuffer_file_segment {
236275970Scy	void *lock; /**< lock prevent concurrent access to refcnt */
237275970Scy	int refcnt; /**< Reference count for this file segment */
238275970Scy	unsigned flags; /**< combination of EVBUF_FS_* flags  */
239275970Scy
240275970Scy	/** What kind of file segment is this? */
241275970Scy	unsigned can_sendfile : 1;
242275970Scy	unsigned is_mapping : 1;
243275970Scy
244275970Scy	/** The fd that we read the data from. */
245275970Scy	int fd;
246275970Scy	/** If we're using mmap, this is the raw mapped memory. */
247275970Scy	void *mapping;
248275970Scy#ifdef _WIN32
249275970Scy	/** If we're using CreateFileMapping, this is the mapping */
250275970Scy	HANDLE mapping_handle;
251275970Scy#endif
252275970Scy	/** If we're using mmap or IO, this is the content of the file
253275970Scy	 * segment. */
254275970Scy	char *contents;
255275970Scy	/** Position of this segment within the file. */
256275970Scy	ev_off_t file_offset;
257275970Scy	/** If we're using mmap, this is the offset within 'mapping' where
258275970Scy	 * this data segment begins. */
259275970Scy	ev_off_t mmap_offset;
260275970Scy	/** The length of this segment. */
261275970Scy	ev_off_t length;
262275970Scy	/** Cleanup callback function */
263275970Scy	evbuffer_file_segment_cleanup_cb cleanup_cb;
264275970Scy	/** Argument to be pass to cleanup callback function */
265275970Scy	void *cleanup_cb_arg;
266275970Scy};
267275970Scy
268275970Scy/** Information about the multicast parent of a chain.  Lives at the
269275970Scy * end of an evbuffer_chain with the EVBUFFER_MULTICAST flag set.  */
270275970Scystruct evbuffer_multicast_parent {
271275970Scy	/** source buffer the multicast parent belongs to */
272275970Scy	struct evbuffer *source;
273275970Scy	/** multicast parent for this chain */
274275970Scy	struct evbuffer_chain *parent;
275275970Scy};
276275970Scy
277275970Scy#define EVBUFFER_CHAIN_SIZE sizeof(struct evbuffer_chain)
278275970Scy/** Return a pointer to extra data allocated along with an evbuffer. */
279275970Scy#define EVBUFFER_CHAIN_EXTRA(t, c) (t *)((struct evbuffer_chain *)(c) + 1)
280275970Scy
281275970Scy/** Assert that we are holding the lock on an evbuffer */
282275970Scy#define ASSERT_EVBUFFER_LOCKED(buffer)			\
283275970Scy	EVLOCK_ASSERT_LOCKED((buffer)->lock)
284275970Scy
285275970Scy#define EVBUFFER_LOCK(buffer)						\
286275970Scy	do {								\
287275970Scy		EVLOCK_LOCK((buffer)->lock, 0);				\
288275970Scy	} while (0)
289275970Scy#define EVBUFFER_UNLOCK(buffer)						\
290275970Scy	do {								\
291275970Scy		EVLOCK_UNLOCK((buffer)->lock, 0);			\
292275970Scy	} while (0)
293275970Scy#define EVBUFFER_LOCK2(buffer1, buffer2)				\
294275970Scy	do {								\
295275970Scy		EVLOCK_LOCK2((buffer1)->lock, (buffer2)->lock, 0, 0);	\
296275970Scy	} while (0)
297275970Scy#define EVBUFFER_UNLOCK2(buffer1, buffer2)				\
298275970Scy	do {								\
299275970Scy		EVLOCK_UNLOCK2((buffer1)->lock, (buffer2)->lock, 0, 0);	\
300275970Scy	} while (0)
301275970Scy
302275970Scy/** Increase the reference count of buf by one. */
303275970Scyvoid evbuffer_incref_(struct evbuffer *buf);
304275970Scy/** Increase the reference count of buf by one and acquire the lock. */
305275970Scyvoid evbuffer_incref_and_lock_(struct evbuffer *buf);
306275970Scy/** Pin a single buffer chain using a given flag. A pinned chunk may not be
307275970Scy * moved or freed until it is unpinned. */
308275970Scyvoid evbuffer_chain_pin_(struct evbuffer_chain *chain, unsigned flag);
309275970Scy/** Unpin a single buffer chain using a given flag. */
310275970Scyvoid evbuffer_chain_unpin_(struct evbuffer_chain *chain, unsigned flag);
311275970Scy/** As evbuffer_free, but requires that we hold a lock on the buffer, and
312275970Scy * releases the lock before freeing it and the buffer. */
313275970Scyvoid evbuffer_decref_and_unlock_(struct evbuffer *buffer);
314275970Scy
315275970Scy/** As evbuffer_expand, but does not guarantee that the newly allocated memory
316275970Scy * is contiguous.  Instead, it may be split across two or more chunks. */
317275970Scyint evbuffer_expand_fast_(struct evbuffer *, size_t, int);
318275970Scy
319275970Scy/** Helper: prepares for a readv/WSARecv call by expanding the buffer to
320275970Scy * hold enough memory to read 'howmuch' bytes in possibly noncontiguous memory.
321275970Scy * Sets up the one or two iovecs in 'vecs' to point to the free memory and its
322275970Scy * extent, and *chainp to point to the first chain that we'll try to read into.
323275970Scy * Returns the number of vecs used.
324275970Scy */
325275970Scyint evbuffer_read_setup_vecs_(struct evbuffer *buf, ev_ssize_t howmuch,
326275970Scy    struct evbuffer_iovec *vecs, int n_vecs, struct evbuffer_chain ***chainp,
327275970Scy    int exact);
328275970Scy
329275970Scy/* Helper macro: copies an evbuffer_iovec in ei to a win32 WSABUF in i. */
330275970Scy#define WSABUF_FROM_EVBUFFER_IOV(i,ei) do {		\
331275970Scy		(i)->buf = (ei)->iov_base;		\
332275970Scy		(i)->len = (unsigned long)(ei)->iov_len;	\
333275970Scy	} while (0)
334275970Scy/* XXXX the cast above is safe for now, but not if we allow mmaps on win64.
335275970Scy * See note in buffer_iocp's launch_write function */
336275970Scy
337275970Scy/** Set the parent bufferevent object for buf to bev */
338275970Scyvoid evbuffer_set_parent_(struct evbuffer *buf, struct bufferevent *bev);
339275970Scy
340275970Scyvoid evbuffer_invoke_callbacks_(struct evbuffer *buf);
341275970Scy
342275970Scy
343275970Scyint evbuffer_get_callbacks_(struct evbuffer *buffer,
344275970Scy    struct event_callback **cbs,
345275970Scy    int max_cbs);
346275970Scy
347275970Scy#ifdef __cplusplus
348275970Scy}
349275970Scy#endif
350275970Scy
351275970Scy#endif /* EVBUFFER_INTERNAL_H_INCLUDED_ */
352