2008-02-28 02:47:43 +00:00
|
|
|
/*
|
2009-01-27 22:34:36 +00:00
|
|
|
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
2010-03-04 01:25:51 -05:00
|
|
|
* Copyright (c) 2007-2010 Niels Provos and Nick Mathewson
|
2008-02-28 02:47:43 +00:00
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. The name of the author may not be used to endorse or promote products
|
|
|
|
* derived from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
#ifndef _EVBUFFER_INTERNAL_H_
|
|
|
|
#define _EVBUFFER_INTERNAL_H_
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
2010-07-07 16:45:03 -04:00
|
|
|
#include "event2/event-config.h"
|
2011-01-02 08:43:45 -07:00
|
|
|
#include "evconfig-private.h"
|
2009-05-01 00:54:14 +00:00
|
|
|
#include "event2/util.h"
|
|
|
|
#include "util-internal.h"
|
2009-04-10 20:43:08 +00:00
|
|
|
#include "defer-internal.h"
|
2008-02-28 02:47:43 +00:00
|
|
|
|
2010-01-06 18:42:59 -05:00
|
|
|
/* Experimental cb flag: "never deferred." Implementation note:
|
|
|
|
* these callbacks may get an inaccurate view of n_del/n_added in their
|
|
|
|
* arguments. */
|
2009-12-22 15:52:02 -05:00
|
|
|
#define EVBUFFER_CB_NODEFER 2
|
|
|
|
|
2011-05-25 19:50:56 -04:00
|
|
|
#ifdef _WIN32
|
2009-05-01 00:54:14 +00:00
|
|
|
#include <winsock2.h>
|
|
|
|
#endif
|
2009-01-23 01:11:13 +00:00
|
|
|
#include <sys/queue.h>
|
2010-03-26 14:30:14 -04:00
|
|
|
|
|
|
|
/* Minimum allocation for a chain. We define this so that we're burning no
|
|
|
|
* more than 5% of each allocation on overhead. It would be nice to lose even
|
|
|
|
* less space, though. */
|
|
|
|
#if _EVENT_SIZEOF_VOID_P < 8
|
|
|
|
#define MIN_BUFFER_SIZE 512
|
|
|
|
#else
|
|
|
|
#define MIN_BUFFER_SIZE 1024
|
|
|
|
#endif
|
2008-02-28 02:47:43 +00:00
|
|
|
|
2009-04-17 06:55:08 +00:00
|
|
|
/** A single evbuffer callback for an evbuffer. This function will be invoked
|
|
|
|
* when bytes are added to or removed from the evbuffer. */
|
2009-01-23 01:11:13 +00:00
|
|
|
struct evbuffer_cb_entry {
|
2010-02-18 17:41:15 -05:00
|
|
|
/** Structures to implement a doubly-linked queue of callbacks */
|
2009-01-23 01:11:13 +00:00
|
|
|
TAILQ_ENTRY(evbuffer_cb_entry) next;
|
2010-02-18 17:41:15 -05:00
|
|
|
/** The callback function to invoke when this callback is called.
|
2009-04-17 06:55:08 +00:00
|
|
|
If EVBUFFER_CB_OBSOLETE is set in flags, the cb_obsolete field is
|
|
|
|
valid; otherwise, cb_func is valid. */
|
2010-02-18 17:41:15 -05:00
|
|
|
union {
|
|
|
|
evbuffer_cb_func cb_func;
|
|
|
|
evbuffer_cb cb_obsolete;
|
|
|
|
} cb;
|
|
|
|
/** Argument to pass to cb. */
|
2009-01-23 01:11:13 +00:00
|
|
|
void *cbarg;
|
2010-02-18 17:41:15 -05:00
|
|
|
/** Currently set flags on this callback. */
|
2009-02-01 01:43:58 +00:00
|
|
|
ev_uint32_t flags;
|
2009-01-23 01:11:13 +00:00
|
|
|
};
|
|
|
|
|
2009-11-17 20:31:09 +00:00
|
|
|
struct bufferevent;
|
2008-02-28 02:47:43 +00:00
|
|
|
struct evbuffer_chain;
|
|
|
|
struct evbuffer {
|
2009-04-17 06:55:08 +00:00
|
|
|
/** The first chain in this buffer's linked list of chains. */
|
2008-02-28 02:47:43 +00:00
|
|
|
struct evbuffer_chain *first;
|
2009-04-17 06:55:08 +00:00
|
|
|
/** The last chain in this buffer's linked list of chains. */
|
2008-02-28 02:47:43 +00:00
|
|
|
struct evbuffer_chain *last;
|
|
|
|
|
2010-03-26 23:18:40 -04:00
|
|
|
/** Pointer to the next pointer pointing at the 'last_with_data' chain.
|
|
|
|
*
|
|
|
|
* To unpack:
|
|
|
|
*
|
|
|
|
* The last_with_data chain is the last chain that has any data in it.
|
|
|
|
* If all chains in the buffer are empty, it is the first chain.
|
|
|
|
* If the buffer has no chains, it is NULL.
|
|
|
|
*
|
|
|
|
* The last_with_datap pointer points at _whatever 'next' pointer_
|
|
|
|
* points at the last_with_datap chain. If the last_with_data chain
|
|
|
|
* is the first chain, or it is NULL, then the last_with_datap pointer
|
|
|
|
* is &buf->first.
|
|
|
|
*/
|
|
|
|
struct evbuffer_chain **last_with_datap;
|
Revise evbuffer to add last_with_data
This is the first patch in a series to replace previous_to_last with
last_with_data. Currently, we can only use two partially empty chains
at the end of an evbuffer, so if we have one with 511 bytes free, and
another with 512 bytes free, and we try to do a 1024 byte read, we
can't just stick another chain on the end: we need to reallocate the
last one. That's stupid and inefficient.
Instead, this patch adds a last_with_data pointer to eventually
replace previous_to_last. Instead of pointing to the penultimated
chain (if any) as previous_to_last does, last_with_data points to the
last chain that has any data in it, if any. If all chains are empty,
last_with_data points to the first chain. If there are no chains,
last_with_data is NULL.
The next step is to start using last_with_data everywhere that we
currently use previous_to_last. When that's done, we can remove
previous_to_last and the code that maintains it.
2010-03-10 22:16:14 -05:00
|
|
|
|
2009-04-17 06:55:08 +00:00
|
|
|
/** Total amount of bytes stored in all chains.*/
|
|
|
|
size_t total_len;
|
2009-01-23 01:11:13 +00:00
|
|
|
|
2009-04-17 06:55:08 +00:00
|
|
|
/** Number of bytes we have added to the buffer since we last tried to
|
|
|
|
* invoke callbacks. */
|
2010-02-18 17:41:15 -05:00
|
|
|
size_t n_add_for_cb;
|
2009-04-17 06:55:08 +00:00
|
|
|
/** Number of bytes we have removed from the buffer since we last
|
|
|
|
* tried to invoke callbacks. */
|
2010-02-18 17:41:15 -05:00
|
|
|
size_t n_del_for_cb;
|
2009-04-03 14:27:03 +00:00
|
|
|
|
2009-04-05 02:44:17 +00:00
|
|
|
#ifndef _EVENT_DISABLE_THREAD_SUPPORT
|
2009-04-17 06:55:08 +00:00
|
|
|
/** A lock used to mediate access to this buffer. */
|
2010-02-18 17:41:15 -05:00
|
|
|
void *lock;
|
2009-04-05 02:44:17 +00:00
|
|
|
#endif
|
2009-04-17 06:55:08 +00:00
|
|
|
/** True iff we should free the lock field when we free this
|
|
|
|
* evbuffer. */
|
2009-04-05 02:44:17 +00:00
|
|
|
unsigned own_lock : 1;
|
2009-04-17 06:55:08 +00:00
|
|
|
/** True iff we should not allow changes to the front of the buffer
|
|
|
|
* (drains or prepends). */
|
2009-04-08 03:04:39 +00:00
|
|
|
unsigned freeze_start : 1;
|
2009-04-17 06:55:08 +00:00
|
|
|
/** True iff we should not allow changes to the end of the buffer
|
|
|
|
* (appends) */
|
2009-04-08 03:04:39 +00:00
|
|
|
unsigned freeze_end : 1;
|
2009-04-17 06:55:08 +00:00
|
|
|
/** True iff this evbuffer's callbacks are not invoked immediately
|
|
|
|
* upon a change in the buffer, but instead are deferred to be invoked
|
2010-02-18 17:41:15 -05:00
|
|
|
* from the event_base's loop. Useful for preventing enormous stack
|
2009-04-17 06:55:08 +00:00
|
|
|
* overflows when we have mutually recursive callbacks, and for
|
|
|
|
* serializing callbacks in a single thread. */
|
2009-04-10 20:43:08 +00:00
|
|
|
unsigned deferred_cbs : 1;
|
2011-05-25 19:50:56 -04:00
|
|
|
#ifdef _WIN32
|
2009-04-17 06:55:08 +00:00
|
|
|
/** True iff this buffer is set up for overlapped IO. */
|
2009-04-14 20:11:10 +00:00
|
|
|
unsigned is_overlapped : 1;
|
|
|
|
#endif
|
2009-04-10 20:43:08 +00:00
|
|
|
|
2009-07-26 01:29:39 +00:00
|
|
|
/** Used to implement deferred callbacks. */
|
|
|
|
struct deferred_cb_queue *cb_queue;
|
2009-04-08 03:03:59 +00:00
|
|
|
|
2010-02-18 17:41:15 -05:00
|
|
|
/** A reference count on this evbuffer. When the reference count
|
|
|
|
* reaches 0, the buffer is destroyed. Manipulated with
|
2009-04-17 06:55:08 +00:00
|
|
|
* evbuffer_incref and evbuffer_decref_and_unlock and
|
|
|
|
* evbuffer_free. */
|
2009-04-13 03:06:27 +00:00
|
|
|
int refcnt;
|
2009-04-05 02:44:17 +00:00
|
|
|
|
2009-04-17 06:55:08 +00:00
|
|
|
/** A deferred_cb handle to make all of this buffer's callbacks
|
|
|
|
* invoked from the event loop. */
|
2009-04-10 20:43:08 +00:00
|
|
|
struct deferred_cb deferred;
|
|
|
|
|
2009-04-17 06:55:08 +00:00
|
|
|
/** A doubly-linked-list of callback functions */
|
2009-01-23 01:11:13 +00:00
|
|
|
TAILQ_HEAD(evbuffer_cb_queue, evbuffer_cb_entry) callbacks;
|
2009-11-17 20:31:09 +00:00
|
|
|
|
|
|
|
/** The parent bufferevent object this evbuffer belongs to.
|
|
|
|
* NULL if the evbuffer stands alone. */
|
|
|
|
struct bufferevent *parent;
|
2008-02-28 02:47:43 +00:00
|
|
|
};
|
|
|
|
|
2009-04-17 06:55:08 +00:00
|
|
|
/** A single item in an evbuffer. */
|
2008-02-28 02:47:43 +00:00
|
|
|
struct evbuffer_chain {
|
|
|
|
/** points to next buffer in the chain */
|
|
|
|
struct evbuffer_chain *next;
|
2009-02-10 19:38:43 +00:00
|
|
|
|
2009-01-27 06:05:38 +00:00
|
|
|
/** total allocation available in the buffer field. */
|
|
|
|
size_t buffer_len;
|
2008-02-28 02:47:43 +00:00
|
|
|
|
2009-02-10 19:38:43 +00:00
|
|
|
/** unused space at the beginning of buffer or an offset into a
|
2009-01-27 06:05:38 +00:00
|
|
|
* file for sendfile buffers. */
|
2010-11-01 13:43:43 -04:00
|
|
|
ev_off_t misalign;
|
2008-02-28 02:47:43 +00:00
|
|
|
|
2009-01-27 06:05:38 +00:00
|
|
|
/** Offset into buffer + misalign at which to start writing.
|
|
|
|
* In other words, the total number of bytes actually stored
|
|
|
|
* in buffer. */
|
|
|
|
size_t off;
|
|
|
|
|
|
|
|
/** Set if special handling is required for this chain */
|
|
|
|
unsigned flags;
|
2010-10-21 19:45:49 -04:00
|
|
|
#define EVBUFFER_FILESEGMENT 0x0001 /**< A chain used for a file segment */
|
|
|
|
#define EVBUFFER_SENDFILE 0x0002 /**< a chain used with sendfile */
|
2009-01-27 06:05:38 +00:00
|
|
|
#define EVBUFFER_REFERENCE 0x0004 /**< a chain with a mem reference */
|
2010-02-18 17:41:15 -05:00
|
|
|
#define EVBUFFER_IMMUTABLE 0x0008 /**< read-only chain */
|
2009-04-08 03:03:59 +00:00
|
|
|
/** a chain that mustn't be reallocated or freed, or have its contents
|
|
|
|
* memmoved, until the chain is un-pinned. */
|
|
|
|
#define EVBUFFER_MEM_PINNED_R 0x0010
|
|
|
|
#define EVBUFFER_MEM_PINNED_W 0x0020
|
|
|
|
#define EVBUFFER_MEM_PINNED_ANY (EVBUFFER_MEM_PINNED_R|EVBUFFER_MEM_PINNED_W)
|
|
|
|
/** a chain that should be freed, but can't be freed until it is
|
|
|
|
* un-pinned. */
|
|
|
|
#define EVBUFFER_DANGLING 0x0040
|
2009-01-27 06:05:38 +00:00
|
|
|
|
|
|
|
/** Usually points to the read-write memory belonging to this
|
|
|
|
* buffer allocated as part of the evbuffer_chain allocation.
|
|
|
|
* For mmap, this can be a read-only buffer and
|
|
|
|
* EVBUFFER_IMMUTABLE will be set in flags. For sendfile, it
|
|
|
|
* may point to NULL.
|
|
|
|
*/
|
2009-04-14 20:11:10 +00:00
|
|
|
unsigned char *buffer;
|
2009-01-27 06:05:38 +00:00
|
|
|
};
|
|
|
|
|
2010-10-21 19:45:49 -04:00
|
|
|
/** callback for a reference chain; lets us know what to do with it when
|
|
|
|
* we're done with it. Lives at the end of an evbuffer_chain with the
|
|
|
|
* EVBUFFER_REFERENCE flag set */
|
2009-01-27 06:05:38 +00:00
|
|
|
struct evbuffer_chain_reference {
|
2009-05-15 22:44:18 +00:00
|
|
|
evbuffer_ref_cleanup_cb cleanupfn;
|
2009-01-27 06:05:38 +00:00
|
|
|
void *extra;
|
2008-02-28 02:47:43 +00:00
|
|
|
};
|
|
|
|
|
2010-10-21 19:45:49 -04:00
|
|
|
/** File segment for a file-segment chain. Lives at the end of an
|
|
|
|
* evbuffer_chain with the EVBUFFER_FILESEGMENT flag set. */
|
|
|
|
struct evbuffer_chain_file_segment {
|
|
|
|
struct evbuffer_file_segment *segment;
|
2011-05-25 19:50:56 -04:00
|
|
|
#ifdef _WIN32
|
2010-10-25 12:29:39 -04:00
|
|
|
/** If we're using CreateFileMapping, this is the handle to the view. */
|
|
|
|
HANDLE view_handle;
|
|
|
|
#endif
|
2010-10-21 19:45:49 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Declared in event2/buffer.h; defined here. */
|
|
|
|
struct evbuffer_file_segment {
|
|
|
|
void *lock; /**< lock prevent concurrent access to refcnt */
|
|
|
|
int refcnt; /**< Reference count for this file segment */
|
|
|
|
unsigned flags; /**< combination of EVBUF_FS_* flags */
|
|
|
|
|
|
|
|
/** What kind of file segment is this? */
|
|
|
|
enum {EVBUF_FS_MMAP, EVBUF_FS_SENDFILE, EVBUF_FS_IO} type;
|
|
|
|
|
|
|
|
/** The fd that we read the data from. */
|
|
|
|
int fd;
|
|
|
|
/** If we're using mmap, this is the raw mapped memory. */
|
|
|
|
void *mapping;
|
2011-05-25 19:50:56 -04:00
|
|
|
#ifdef _WIN32
|
2010-10-25 12:29:39 -04:00
|
|
|
/** If we're using CreateFileMapping, this is the mapping */
|
|
|
|
HANDLE mapping_handle;
|
|
|
|
#endif
|
2010-10-21 19:45:49 -04:00
|
|
|
/** If we're using mmap or IO, this is the content of the file
|
|
|
|
* segment. */
|
|
|
|
char *contents;
|
|
|
|
/** If we're using mmap, this is the offset within 'mapping' where
|
|
|
|
* this data segment begins. If we're using sendfile, this is the
|
|
|
|
* offset within the file where this data begins. If we're using IO,
|
|
|
|
* this is 0. */
|
2010-10-25 12:29:39 -04:00
|
|
|
ev_off_t offset;
|
2010-10-21 19:45:49 -04:00
|
|
|
/** The length of this segment. */
|
2010-10-25 12:29:39 -04:00
|
|
|
ev_off_t length;
|
2010-10-21 19:45:49 -04:00
|
|
|
};
|
|
|
|
|
2009-01-27 06:05:38 +00:00
|
|
|
#define EVBUFFER_CHAIN_SIZE sizeof(struct evbuffer_chain)
|
2009-04-17 06:55:08 +00:00
|
|
|
/** Return a pointer to extra data allocated along with an evbuffer. */
|
2009-01-27 06:05:38 +00:00
|
|
|
#define EVBUFFER_CHAIN_EXTRA(t, c) (t *)((struct evbuffer_chain *)(c) + 1)
|
2008-02-28 02:47:43 +00:00
|
|
|
|
2009-11-27 17:22:19 -05:00
|
|
|
/** Assert that we are holding the lock on an evbuffer */
|
2010-02-18 17:41:15 -05:00
|
|
|
#define ASSERT_EVBUFFER_LOCKED(buffer) \
|
2009-11-27 17:22:19 -05:00
|
|
|
EVLOCK_ASSERT_LOCKED((buffer)->lock)
|
2009-04-05 02:44:17 +00:00
|
|
|
|
2009-11-27 16:44:47 -05:00
|
|
|
#define EVBUFFER_LOCK(buffer) \
|
2009-04-05 02:44:17 +00:00
|
|
|
do { \
|
2009-11-27 16:44:47 -05:00
|
|
|
EVLOCK_LOCK((buffer)->lock, 0); \
|
2010-03-05 13:00:15 -05:00
|
|
|
} while (0)
|
2009-11-27 16:44:47 -05:00
|
|
|
#define EVBUFFER_UNLOCK(buffer) \
|
2009-04-05 02:44:17 +00:00
|
|
|
do { \
|
2009-11-27 16:44:47 -05:00
|
|
|
EVLOCK_UNLOCK((buffer)->lock, 0); \
|
2010-03-05 13:00:15 -05:00
|
|
|
} while (0)
|
2009-04-05 02:44:17 +00:00
|
|
|
#define EVBUFFER_LOCK2(buffer1, buffer2) \
|
|
|
|
do { \
|
2009-11-27 16:44:47 -05:00
|
|
|
EVLOCK_LOCK2((buffer1)->lock, (buffer2)->lock, 0, 0); \
|
2010-03-05 13:00:15 -05:00
|
|
|
} while (0)
|
2009-04-05 02:44:17 +00:00
|
|
|
#define EVBUFFER_UNLOCK2(buffer1, buffer2) \
|
|
|
|
do { \
|
2009-11-27 16:44:47 -05:00
|
|
|
EVLOCK_UNLOCK2((buffer1)->lock, (buffer2)->lock, 0, 0); \
|
2010-03-05 13:00:15 -05:00
|
|
|
} while (0)
|
2009-04-05 02:44:17 +00:00
|
|
|
|
2009-04-17 06:55:08 +00:00
|
|
|
/** Increase the reference count of buf by one. */
|
2009-04-13 03:06:27 +00:00
|
|
|
void _evbuffer_incref(struct evbuffer *buf);
|
2009-11-17 20:31:09 +00:00
|
|
|
/** Increase the reference count of buf by one and acquire the lock. */
|
|
|
|
void _evbuffer_incref_and_lock(struct evbuffer *buf);
|
2009-04-17 06:55:08 +00:00
|
|
|
/** Pin a single buffer chain using a given flag. A pinned chunk may not be
|
|
|
|
* moved or freed until it is unpinned. */
|
2009-04-13 03:06:47 +00:00
|
|
|
void _evbuffer_chain_pin(struct evbuffer_chain *chain, unsigned flag);
|
2009-04-17 06:55:08 +00:00
|
|
|
/** Unpin a single buffer chain using a given flag. */
|
2009-04-13 03:06:47 +00:00
|
|
|
void _evbuffer_chain_unpin(struct evbuffer_chain *chain, unsigned flag);
|
2009-04-17 06:55:08 +00:00
|
|
|
/** As evbuffer_free, but requires that we hold a lock on the buffer, and
|
|
|
|
* releases the lock before freeing it and the buffer. */
|
2009-04-13 03:06:47 +00:00
|
|
|
void _evbuffer_decref_and_unlock(struct evbuffer *buffer);
|
2009-05-21 20:59:00 +00:00
|
|
|
|
2009-04-17 06:55:08 +00:00
|
|
|
/** As evbuffer_expand, but does not guarantee that the newly allocated memory
|
2010-03-10 23:24:14 -05:00
|
|
|
* is contiguous. Instead, it may be split across two or more chunks. */
|
|
|
|
int _evbuffer_expand_fast(struct evbuffer *, size_t, int);
|
2009-04-13 03:06:27 +00:00
|
|
|
|
2009-04-17 06:55:08 +00:00
|
|
|
/** Helper: prepares for a readv/WSARecv call by expanding the buffer to
|
|
|
|
* hold enough memory to read 'howmuch' bytes in possibly noncontiguous memory.
|
|
|
|
* Sets up the one or two iovecs in 'vecs' to point to the free memory and its
|
2009-10-16 13:19:57 +00:00
|
|
|
* extent, and *chainp to point to the first chain that we'll try to read into.
|
2009-04-17 06:55:08 +00:00
|
|
|
* Returns the number of vecs used.
|
|
|
|
*/
|
2009-05-22 19:11:48 +00:00
|
|
|
int _evbuffer_read_setup_vecs(struct evbuffer *buf, ev_ssize_t howmuch,
|
2010-08-16 01:23:57 -07:00
|
|
|
struct evbuffer_iovec *vecs, int n_vecs, struct evbuffer_chain ***chainp,
|
|
|
|
int exact);
|
2009-04-13 03:05:46 +00:00
|
|
|
|
2009-05-21 20:59:00 +00:00
|
|
|
/* Helper macro: copies an evbuffer_iovec in ei to a win32 WSABUF in i. */
|
|
|
|
#define WSABUF_FROM_EVBUFFER_IOV(i,ei) do { \
|
|
|
|
(i)->buf = (ei)->iov_base; \
|
2010-11-01 13:43:43 -04:00
|
|
|
(i)->len = (unsigned long)(ei)->iov_len; \
|
2010-03-05 13:00:15 -05:00
|
|
|
} while (0)
|
2010-11-01 13:43:43 -04:00
|
|
|
/* XXXX the cast above is safe for now, but not if we allow mmaps on win64.
|
|
|
|
* See note in buffer_iocp's launch_write function */
|
2009-05-21 20:59:00 +00:00
|
|
|
|
2009-11-17 20:31:09 +00:00
|
|
|
/** Set the parent bufferevent object for buf to bev */
|
|
|
|
void evbuffer_set_parent(struct evbuffer *buf, struct bufferevent *bev);
|
|
|
|
|
2008-02-28 02:47:43 +00:00
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif /* _EVBUFFER_INTERNAL_H_ */
|