From 0777279524456fbe986060d213f3cbb7f5c0edf8 Mon Sep 17 00:00:00 2001 From: shi_jq Date: Wed, 12 Mar 2025 19:14:12 +0800 Subject: [PATCH] =?UTF-8?q?[ref]=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/3rd/compiled_in/sigar/include/sigar.h | 5 + platform/src/3rd/compiled_in/sigar/sigar.pri | 4 +- .../src/3rd/compiled_in/sigar/src/sigar.c | 3 + .../src/3rd/include/hikvision/hikvision.pri | 2 +- .../oe2203/include/event2/buffer.h | 1076 +++++++++++ .../oe2203/include/event2/buffer_compat.h | 115 ++ .../oe2203/include/event2/bufferevent.h | 1021 ++++++++++ .../include/event2/bufferevent_compat.h | 100 + .../oe2203/include/event2/bufferevent_ssl.h | 134 ++ .../include/event2/bufferevent_struct.h | 116 ++ .../os_specific/oe2203/include/event2/dns.h | 717 +++++++ .../oe2203/include/event2/dns_compat.h | 336 ++++ .../oe2203/include/event2/dns_struct.h | 80 + .../oe2203/include/event2/event-config.h | 545 ++++++ .../os_specific/oe2203/include/event2/event.h | 1675 +++++++++++++++++ .../oe2203/include/event2/event_compat.h | 230 +++ .../oe2203/include/event2/event_struct.h | 180 ++ .../os_specific/oe2203/include/event2/http.h | 1189 ++++++++++++ .../oe2203/include/event2/http_compat.h | 90 + .../oe2203/include/event2/http_struct.h | 152 ++ .../oe2203/include/event2/keyvalq_struct.h | 80 + .../oe2203/include/event2/listener.h | 180 ++ .../os_specific/oe2203/include/event2/rpc.h | 596 ++++++ .../oe2203/include/event2/rpc_compat.h | 61 + .../oe2203/include/event2/rpc_struct.h | 100 + .../os_specific/oe2203/include/event2/tag.h | 146 ++ .../oe2203/include/event2/tag_compat.h | 49 + .../oe2203/include/event2/thread.h | 253 +++ .../os_specific/oe2203/include/event2/util.h | 866 +++++++++ .../oe2203/include/event2/visibility.h | 50 + .../oe2203/include/hiredis/adapters/ae.h | 128 ++ .../oe2203/include/hiredis/adapters/glib.h | 153 ++ .../oe2203/include/hiredis/adapters/ivykis.h | 81 + .../oe2203/include/hiredis/adapters/libev.h | 147 ++ .../include/hiredis/adapters/libevent.h | 108 ++ .../oe2203/include/hiredis/adapters/libuv.h | 122 ++ .../oe2203/include/hiredis/adapters/macosx.h | 114 ++ .../oe2203/include/hiredis/adapters/qt.h | 135 ++ .../oe2203/include/hiredis/async.h | 130 ++ .../oe2203/include/hiredis/hiredis.h | 199 ++ .../os_specific/oe2203/include/hiredis/read.h | 111 ++ .../os_specific/oe2203/include/hiredis/sds.h | 273 +++ .../3rd/os_specific/oe2203/include/libagent.h | 212 +++ .../3rd/os_specific/oe2203/include/libsnmp.h | 223 +++ .../oe2203/include/snmp_pp/config_snmp_pp.h | 289 +++ platform/src/3rd/src_package/Boost/ReadMe.txt | 7 + .../Lua/libreadline-dev_8.0-4_amd64.deb | Bin 0 -> 142900 bytes .../src/3rd/src_package/Lua/lua编译.txt | 8 + .../src/3rd/src_package/ProtoBuf/ReadMe.txt | 2 + .../src/3rd/src_package/ZeroMQ/ReadMe.txt | 9 + .../src/3rd/src_package/hiredis/README.txt | 2 +- .../src_package/log4cplus/编译说明.txt | 14 +- .../3rd/src_package/oatpp/HttpProcessor.cpp | 442 +++++ .../3rd/src_package/oatpp/HttpProcessor.patch | 21 + platform/src/3rd/src_package/oatpp/ReadMe.txt | 24 + 55 files changed, 13099 insertions(+), 6 deletions(-) create mode 100644 platform/src/3rd/os_specific/oe2203/include/event2/buffer.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/event2/buffer_compat.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/event2/bufferevent.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/event2/bufferevent_compat.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/event2/bufferevent_ssl.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/event2/bufferevent_struct.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/event2/dns.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/event2/dns_compat.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/event2/dns_struct.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/event2/event-config.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/event2/event.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/event2/event_compat.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/event2/event_struct.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/event2/http.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/event2/http_compat.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/event2/http_struct.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/event2/keyvalq_struct.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/event2/listener.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/event2/rpc.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/event2/rpc_compat.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/event2/rpc_struct.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/event2/tag.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/event2/tag_compat.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/event2/thread.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/event2/util.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/event2/visibility.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/ae.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/glib.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/ivykis.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/libev.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/libevent.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/libuv.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/macosx.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/qt.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/hiredis/async.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/hiredis/hiredis.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/hiredis/read.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/hiredis/sds.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/libagent.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/libsnmp.h create mode 100644 platform/src/3rd/os_specific/oe2203/include/snmp_pp/config_snmp_pp.h create mode 100644 platform/src/3rd/src_package/Lua/libreadline-dev_8.0-4_amd64.deb create mode 100644 platform/src/3rd/src_package/oatpp/HttpProcessor.cpp create mode 100644 platform/src/3rd/src_package/oatpp/HttpProcessor.patch diff --git a/platform/src/3rd/compiled_in/sigar/include/sigar.h b/platform/src/3rd/compiled_in/sigar/include/sigar.h index e3cc0410..dc217c5e 100644 --- a/platform/src/3rd/compiled_in/sigar/include/sigar.h +++ b/platform/src/3rd/compiled_in/sigar/include/sigar.h @@ -385,6 +385,11 @@ SIGAR_DECLARE(int) sigar_proc_cpu_get(sigar_t *sigar, sigar_pid_t pid, #define SIGAR_PROC_STATE_STOP 'T' #define SIGAR_PROC_STATE_ZOMBIE 'Z' #define SIGAR_PROC_STATE_IDLE 'I' +// added by yikenan,begin +#define SIGAR_PROC_STATE_DISK_SLEEP 'D' // 也叫uninterruptible sleep,在这个状态的进程通常会等待IO的结束 +#define SIGAR_PROC_STATE_DEAD 'X' // 死亡状态,CPU会进行资源的回收,暂态,较难看见 +#define SIGAR_PROC_STATE_TRACE 't' // stopped by debugger during trace +// yikenan,end #define SIGAR_PROC_NAME_LEN 128 diff --git a/platform/src/3rd/compiled_in/sigar/sigar.pri b/platform/src/3rd/compiled_in/sigar/sigar.pri index ef8d28eb..e2d5fa84 100644 --- a/platform/src/3rd/compiled_in/sigar/sigar.pri +++ b/platform/src/3rd/compiled_in/sigar/sigar.pri @@ -70,10 +70,10 @@ INCLUDEPATH += $$PWD/src/os/linux/ HEADERS += $$PWD/src/os/linux/sigar_os.h SOURCES += $$PWD/src/os/linux/linux_sigar.c -exists( /usr/include/rpc/rpc.h ) { +exists( /usr/include/rpc/rpc.h ): !linux-aarch64*{ #老版本系统,无需处理 }else { - INCLUDEPATH += /usr/include/tirpc/ + INCLUDEPATH += $$(ISCS6000_SYSROOT)/usr/include/tirpc/ LIBS += -ltirpc } } diff --git a/platform/src/3rd/compiled_in/sigar/src/sigar.c b/platform/src/3rd/compiled_in/sigar/src/sigar.c index 05d9c558..35025804 100644 --- a/platform/src/3rd/compiled_in/sigar/src/sigar.c +++ b/platform/src/3rd/compiled_in/sigar/src/sigar.c @@ -335,9 +335,12 @@ SIGAR_DECLARE(int) sigar_proc_stat_get(sigar_t *sigar, procstat->running++; break; case SIGAR_PROC_STATE_SLEEP: + case SIGAR_PROC_STATE_DISK_SLEEP: // added by yikenan procstat->sleeping++; break; case SIGAR_PROC_STATE_STOP: + case SIGAR_PROC_STATE_TRACE: // added by yikenan + case SIGAR_PROC_STATE_DEAD: // added by yikenan,是否合理待商榷 procstat->stopped++; break; case SIGAR_PROC_STATE_ZOMBIE: diff --git a/platform/src/3rd/include/hikvision/hikvision.pri b/platform/src/3rd/include/hikvision/hikvision.pri index df5a8041..35c3cfca 100644 --- a/platform/src/3rd/include/hikvision/hikvision.pri +++ b/platform/src/3rd/include/hikvision/hikvision.pri @@ -1,5 +1,5 @@ # 当前海康sdk只有X86版本 -contains(QMAKE_HOST.arch, x86_64){ +contains(QMAKE_HOST.arch, x86_64) : !linux-aarch64*{ #需在include src\common.pri 之后再include本文件,否则错误 diff --git a/platform/src/3rd/os_specific/oe2203/include/event2/buffer.h b/platform/src/3rd/os_specific/oe2203/include/event2/buffer.h new file mode 100644 index 00000000..468588b9 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/event2/buffer.h @@ -0,0 +1,1076 @@ +/* + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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 EVENT2_BUFFER_H_INCLUDED_ +#define EVENT2_BUFFER_H_INCLUDED_ + +/** @file event2/buffer.h + + Functions for buffering data for network sending or receiving. + + An evbuffer can be used for preparing data before sending it to + the network or conversely for reading data from the network. + Evbuffers try to avoid memory copies as much as possible. As a + result, evbuffers can be used to pass data around without actually + incurring the overhead of copying the data. + + A new evbuffer can be allocated with evbuffer_new(), and can be + freed with evbuffer_free(). Most users will be using evbuffers via + the bufferevent interface. To access a bufferevent's evbuffers, use + bufferevent_get_input() and bufferevent_get_output(). + + There are several guidelines for using evbuffers. + + - if you already know how much data you are going to add as a result + of calling evbuffer_add() multiple times, it makes sense to use + evbuffer_expand() first to make sure that enough memory is allocated + before hand. + + - evbuffer_add_buffer() adds the contents of one buffer to the other + without incurring any unnecessary memory copies. + + - evbuffer_add() and evbuffer_add_buffer() do not mix very well: + if you use them, you will wind up with fragmented memory in your + buffer. + + - For high-performance code, you may want to avoid copying data into and out + of buffers. You can skip the copy step by using + evbuffer_reserve_space()/evbuffer_commit_space() when writing into a + buffer, and evbuffer_peek() when reading. + + In Libevent 2.0 and later, evbuffers are represented using a linked + list of memory chunks, with pointers to the first and last chunk in + the chain. + + As the contents of an evbuffer can be stored in multiple different + memory blocks, it cannot be accessed directly. Instead, evbuffer_pullup() + can be used to force a specified number of bytes to be contiguous. This + will cause memory reallocation and memory copies if the data is split + across multiple blocks. It is more efficient, however, to use + evbuffer_peek() if you don't require that the memory to be contiguous. + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#ifdef EVENT__HAVE_SYS_TYPES_H +#include +#endif +#ifdef EVENT__HAVE_SYS_UIO_H +#include +#endif +#include + +/** + An evbuffer is an opaque data type for efficiently buffering data to be + sent or received on the network. + + @see event2/event.h for more information +*/ +struct evbuffer +#ifdef EVENT_IN_DOXYGEN_ +{} +#endif +; + +/** + Pointer to a position within an evbuffer. + + Used when repeatedly searching through a buffer. Calling any function + that modifies or re-packs the buffer contents may invalidate all + evbuffer_ptrs for that buffer. Do not modify or contruct these values + except with evbuffer_ptr_set. + + An evbuffer_ptr can represent any position from the start of a buffer up + to a position immediately after the end of a buffer. + + @see evbuffer_ptr_set() + */ +struct evbuffer_ptr { + ev_ssize_t pos; + + /* Do not alter or rely on the values of fields: they are for internal + * use */ + struct { + void *chain; + size_t pos_in_chain; + } internal_; +}; + +/** Describes a single extent of memory inside an evbuffer. Used for + direct-access functions. + + @see evbuffer_reserve_space, evbuffer_commit_space, evbuffer_peek + */ +#ifdef EVENT__HAVE_SYS_UIO_H +#define evbuffer_iovec iovec +/* Internal use -- defined only if we are using the native struct iovec */ +#define EVBUFFER_IOVEC_IS_NATIVE_ +#else +struct evbuffer_iovec { + /** The start of the extent of memory. */ + void *iov_base; + /** The length of the extent of memory. */ + size_t iov_len; +}; +#endif + +/** + Allocate storage for a new evbuffer. + + @return a pointer to a newly allocated evbuffer struct, or NULL if an error + occurred + */ +EVENT2_EXPORT_SYMBOL +struct evbuffer *evbuffer_new(void); +/** + Deallocate storage for an evbuffer. + + @param buf pointer to the evbuffer to be freed + */ +EVENT2_EXPORT_SYMBOL +void evbuffer_free(struct evbuffer *buf); + +/** + Enable locking on an evbuffer so that it can safely be used by multiple + threads at the same time. + + NOTE: when locking is enabled, the lock will be held when callbacks are + invoked. This could result in deadlock if you aren't careful. Plan + accordingly! + + @param buf An evbuffer to make lockable. + @param lock A lock object, or NULL if we should allocate our own. + @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_enable_locking(struct evbuffer *buf, void *lock); + +/** + Acquire the lock on an evbuffer. Has no effect if locking was not enabled + with evbuffer_enable_locking. +*/ +EVENT2_EXPORT_SYMBOL +void evbuffer_lock(struct evbuffer *buf); + +/** + Release the lock on an evbuffer. Has no effect if locking was not enabled + with evbuffer_enable_locking. +*/ +EVENT2_EXPORT_SYMBOL +void evbuffer_unlock(struct evbuffer *buf); + + +/** If this flag is set, then we will not use evbuffer_peek(), + * evbuffer_remove(), evbuffer_remove_buffer(), and so on to read bytes + * from this buffer: we'll only take bytes out of this buffer by + * writing them to the network (as with evbuffer_write_atmost), by + * removing them without observing them (as with evbuffer_drain), + * or by copying them all out at once (as with evbuffer_add_buffer). + * + * Using this option allows the implementation to use sendfile-based + * operations for evbuffer_add_file(); see that function for more + * information. + * + * This flag is on by default for bufferevents that can take advantage + * of it; you should never actually need to set it on a bufferevent's + * output buffer. + */ +#define EVBUFFER_FLAG_DRAINS_TO_FD 1 + +/** Change the flags that are set for an evbuffer by adding more. + * + * @param buffer the evbuffer that the callback is watching. + * @param cb the callback whose status we want to change. + * @param flags One or more EVBUFFER_FLAG_* options + * @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_set_flags(struct evbuffer *buf, ev_uint64_t flags); +/** Change the flags that are set for an evbuffer by removing some. + * + * @param buffer the evbuffer that the callback is watching. + * @param cb the callback whose status we want to change. + * @param flags One or more EVBUFFER_FLAG_* options + * @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_clear_flags(struct evbuffer *buf, ev_uint64_t flags); + +/** + Returns the total number of bytes stored in the evbuffer + + @param buf pointer to the evbuffer + @return the number of bytes stored in the evbuffer +*/ +EVENT2_EXPORT_SYMBOL +size_t evbuffer_get_length(const struct evbuffer *buf); + +/** + Returns the number of contiguous available bytes in the first buffer chain. + + This is useful when processing data that might be split into multiple + chains, or that might all be in the first chain. Calls to + evbuffer_pullup() that cause reallocation and copying of data can thus be + avoided. + + @param buf pointer to the evbuffer + @return 0 if no data is available, otherwise the number of available bytes + in the first buffer chain. +*/ +EVENT2_EXPORT_SYMBOL +size_t evbuffer_get_contiguous_space(const struct evbuffer *buf); + +/** + Expands the available space in an evbuffer. + + Expands the available space in the evbuffer to at least datlen, so that + appending datlen additional bytes will not require any new allocations. + + @param buf the evbuffer to be expanded + @param datlen the new minimum length requirement + @return 0 if successful, or -1 if an error occurred +*/ +EVENT2_EXPORT_SYMBOL +int evbuffer_expand(struct evbuffer *buf, size_t datlen); + +/** + Reserves space in the last chain or chains of an evbuffer. + + Makes space available in the last chain or chains of an evbuffer that can + be arbitrarily written to by a user. The space does not become + available for reading until it has been committed with + evbuffer_commit_space(). + + The space is made available as one or more extents, represented by + an initial pointer and a length. You can force the memory to be + available as only one extent. Allowing more extents, however, makes the + function more efficient. + + Multiple subsequent calls to this function will make the same space + available until evbuffer_commit_space() has been called. + + It is an error to do anything that moves around the buffer's internal + memory structures before committing the space. + + NOTE: The code currently does not ever use more than two extents. + This may change in future versions. + + @param buf the evbuffer in which to reserve space. + @param size how much space to make available, at minimum. The + total length of the extents may be greater than the requested + length. + @param vec an array of one or more evbuffer_iovec structures to + hold pointers to the reserved extents of memory. + @param n_vec The length of the vec array. Must be at least 1; + 2 is more efficient. + @return the number of provided extents, or -1 on error. + @see evbuffer_commit_space() +*/ +EVENT2_EXPORT_SYMBOL +int +evbuffer_reserve_space(struct evbuffer *buf, ev_ssize_t size, + struct evbuffer_iovec *vec, int n_vec); + +/** + Commits previously reserved space. + + Commits some of the space previously reserved with + evbuffer_reserve_space(). It then becomes available for reading. + + This function may return an error if the pointer in the extents do + not match those returned from evbuffer_reserve_space, or if data + has been added to the buffer since the space was reserved. + + If you want to commit less data than you got reserved space for, + modify the iov_len pointer of the appropriate extent to a smaller + value. Note that you may have received more space than you + requested if it was available! + + @param buf the evbuffer in which to reserve space. + @param vec one or two extents returned by evbuffer_reserve_space. + @param n_vecs the number of extents. + @return 0 on success, -1 on error + @see evbuffer_reserve_space() +*/ +EVENT2_EXPORT_SYMBOL +int evbuffer_commit_space(struct evbuffer *buf, + struct evbuffer_iovec *vec, int n_vecs); + +/** + Append data to the end of an evbuffer. + + @param buf the evbuffer to be appended to + @param data pointer to the beginning of the data buffer + @param datlen the number of bytes to be copied from the data buffer + @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_add(struct evbuffer *buf, const void *data, size_t datlen); + + +/** + Read data from an evbuffer and drain the bytes read. + + If more bytes are requested than are available in the evbuffer, we + only extract as many bytes as were available. + + @param buf the evbuffer to be read from + @param data the destination buffer to store the result + @param datlen the maximum size of the destination buffer + @return the number of bytes read, or -1 if we can't drain the buffer. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen); + +/** + Read data from an evbuffer, and leave the buffer unchanged. + + If more bytes are requested than are available in the evbuffer, we + only extract as many bytes as were available. + + @param buf the evbuffer to be read from + @param data_out the destination buffer to store the result + @param datlen the maximum size of the destination buffer + @return the number of bytes read, or -1 if we can't drain the buffer. + */ +EVENT2_EXPORT_SYMBOL +ev_ssize_t evbuffer_copyout(struct evbuffer *buf, void *data_out, size_t datlen); + +/** + Read data from the middle of an evbuffer, and leave the buffer unchanged. + + If more bytes are requested than are available in the evbuffer, we + only extract as many bytes as were available. + + @param buf the evbuffer to be read from + @param pos the position to start reading from + @param data_out the destination buffer to store the result + @param datlen the maximum size of the destination buffer + @return the number of bytes read, or -1 if we can't drain the buffer. + */ +EVENT2_EXPORT_SYMBOL +ev_ssize_t evbuffer_copyout_from(struct evbuffer *buf, const struct evbuffer_ptr *pos, void *data_out, size_t datlen); + +/** + Read data from an evbuffer into another evbuffer, draining + the bytes from the source buffer. This function avoids copy + operations to the extent possible. + + If more bytes are requested than are available in src, the src + buffer is drained completely. + + @param src the evbuffer to be read from + @param dst the destination evbuffer to store the result into + @param datlen the maximum numbers of bytes to transfer + @return the number of bytes read + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_remove_buffer(struct evbuffer *src, struct evbuffer *dst, + size_t datlen); + +/** Used to tell evbuffer_readln what kind of line-ending to look for. + */ +enum evbuffer_eol_style { + /** Any sequence of CR and LF characters is acceptable as an + * EOL. + * + * Note that this style can produce ambiguous results: the + * sequence "CRLF" will be treated as a single EOL if it is + * all in the buffer at once, but if you first read a CR from + * the network and later read an LF from the network, it will + * be treated as two EOLs. + */ + EVBUFFER_EOL_ANY, + /** An EOL is an LF, optionally preceded by a CR. This style is + * most useful for implementing text-based internet protocols. */ + EVBUFFER_EOL_CRLF, + /** An EOL is a CR followed by an LF. */ + EVBUFFER_EOL_CRLF_STRICT, + /** An EOL is a LF. */ + EVBUFFER_EOL_LF, + /** An EOL is a NUL character (that is, a single byte with value 0) */ + EVBUFFER_EOL_NUL +}; + +/** + * Read a single line from an evbuffer. + * + * Reads a line terminated by an EOL as determined by the evbuffer_eol_style + * argument. Returns a newly allocated nul-terminated string; the caller must + * free the returned value. The EOL is not included in the returned string. + * + * @param buffer the evbuffer to read from + * @param n_read_out if non-NULL, points to a size_t that is set to the + * number of characters in the returned string. This is useful for + * strings that can contain NUL characters. + * @param eol_style the style of line-ending to use. + * @return pointer to a single line, or NULL if an error occurred + */ +EVENT2_EXPORT_SYMBOL +char *evbuffer_readln(struct evbuffer *buffer, size_t *n_read_out, + enum evbuffer_eol_style eol_style); + +/** + Move all data from one evbuffer into another evbuffer. + + This is a destructive add. The data from one buffer moves into + the other buffer. However, no unnecessary memory copies occur. + + @param outbuf the output buffer + @param inbuf the input buffer + @return 0 if successful, or -1 if an error occurred + + @see evbuffer_remove_buffer() + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf); + +/** + Copy data from one evbuffer into another evbuffer. + + This is a non-destructive add. The data from one buffer is copied + into the other buffer. However, no unnecessary memory copies occur. + + Note that buffers already containing buffer references can't be added + to other buffers. + + @param outbuf the output buffer + @param inbuf the input buffer + @return 0 if successful, or -1 if an error occurred + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_add_buffer_reference(struct evbuffer *outbuf, + struct evbuffer *inbuf); + +/** + A cleanup function for a piece of memory added to an evbuffer by + reference. + + @see evbuffer_add_reference() + */ +typedef void (*evbuffer_ref_cleanup_cb)(const void *data, + size_t datalen, void *extra); + +/** + Reference memory into an evbuffer without copying. + + The memory needs to remain valid until all the added data has been + read. This function keeps just a reference to the memory without + actually incurring the overhead of a copy. + + @param outbuf the output buffer + @param data the memory to reference + @param datlen how memory to reference + @param cleanupfn callback to be invoked when the memory is no longer + referenced by this evbuffer. + @param cleanupfn_arg optional argument to the cleanup callback + @return 0 if successful, or -1 if an error occurred + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_add_reference(struct evbuffer *outbuf, + const void *data, size_t datlen, + evbuffer_ref_cleanup_cb cleanupfn, void *cleanupfn_arg); + +/** + Copy data from a file into the evbuffer for writing to a socket. + + This function avoids unnecessary data copies between userland and + kernel. If sendfile is available and the EVBUFFER_FLAG_DRAINS_TO_FD + flag is set, it uses those functions. Otherwise, it tries to use + mmap (or CreateFileMapping on Windows). + + The function owns the resulting file descriptor and will close it + when finished transferring data. + + The results of using evbuffer_remove() or evbuffer_pullup() on + evbuffers whose data was added using this function are undefined. + + For more fine-grained control, use evbuffer_add_file_segment. + + @param outbuf the output buffer + @param fd the file descriptor + @param offset the offset from which to read data + @param length how much data to read, or -1 to read as much as possible. + (-1 requires that 'fd' support fstat.) + @return 0 if successful, or -1 if an error occurred +*/ + +EVENT2_EXPORT_SYMBOL +int evbuffer_add_file(struct evbuffer *outbuf, int fd, ev_off_t offset, + ev_off_t length); + +/** + An evbuffer_file_segment holds a reference to a range of a file -- + possibly the whole file! -- for use in writing from an evbuffer to a + socket. It could be implemented with mmap, sendfile, splice, or (if all + else fails) by just pulling all the data into RAM. A single + evbuffer_file_segment can be added more than once, and to more than one + evbuffer. + */ +struct evbuffer_file_segment; + +/** + Flag for creating evbuffer_file_segment: If this flag is set, then when + the evbuffer_file_segment is freed and no longer in use by any + evbuffer, the underlying fd is closed. + */ +#define EVBUF_FS_CLOSE_ON_FREE 0x01 +/** + Flag for creating evbuffer_file_segment: Disable memory-map based + implementations. + */ +#define EVBUF_FS_DISABLE_MMAP 0x02 +/** + Flag for creating evbuffer_file_segment: Disable direct fd-to-fd + implementations (including sendfile and splice). + + You might want to use this option if data needs to be taken from the + evbuffer by any means other than writing it to the network: the sendfile + backend is fast, but it only works for sending files directly to the + network. + */ +#define EVBUF_FS_DISABLE_SENDFILE 0x04 +/** + Flag for creating evbuffer_file_segment: Do not allocate a lock for this + segment. If this option is set, then neither the segment nor any + evbuffer it is added to may ever be accessed from more than one thread + at a time. + */ +#define EVBUF_FS_DISABLE_LOCKING 0x08 + +/** + A cleanup function for a evbuffer_file_segment added to an evbuffer + for reference. + */ +typedef void (*evbuffer_file_segment_cleanup_cb)( + struct evbuffer_file_segment const* seg, int flags, void* arg); + +/** + Create and return a new evbuffer_file_segment for reading data from a + file and sending it out via an evbuffer. + + This function avoids unnecessary data copies between userland and + kernel. Where available, it uses sendfile or splice. + + The file descriptor must not be closed so long as any evbuffer is using + this segment. + + The results of using evbuffer_remove() or evbuffer_pullup() or any other + function that reads bytes from an evbuffer on any evbuffer containing + the newly returned segment are undefined, unless you pass the + EVBUF_FS_DISABLE_SENDFILE flag to this function. + + @param fd an open file to read from. + @param offset an index within the file at which to start reading + @param length how much data to read, or -1 to read as much as possible. + (-1 requires that 'fd' support fstat.) + @param flags any number of the EVBUF_FS_* flags + @return a new evbuffer_file_segment, or NULL on failure. + **/ +EVENT2_EXPORT_SYMBOL +struct evbuffer_file_segment *evbuffer_file_segment_new( + int fd, ev_off_t offset, ev_off_t length, unsigned flags); + +/** + Free an evbuffer_file_segment + + It is safe to call this function even if the segment has been added to + one or more evbuffers. The evbuffer_file_segment will not be freed + until no more references to it exist. + */ +EVENT2_EXPORT_SYMBOL +void evbuffer_file_segment_free(struct evbuffer_file_segment *seg); + +/** + Add cleanup callback and argument for the callback to an + evbuffer_file_segment. + + The cleanup callback will be invoked when no more references to the + evbuffer_file_segment exist. + **/ +EVENT2_EXPORT_SYMBOL +void evbuffer_file_segment_add_cleanup_cb(struct evbuffer_file_segment *seg, + evbuffer_file_segment_cleanup_cb cb, void* arg); + +/** + Insert some or all of an evbuffer_file_segment at the end of an evbuffer + + Note that the offset and length parameters of this function have a + different meaning from those provided to evbuffer_file_segment_new: When + you create the segment, the offset is the offset _within the file_, and + the length is the length _of the segment_, whereas when you add a + segment to an evbuffer, the offset is _within the segment_ and the + length is the length of the _part of the segment you want to use. + + In other words, if you have a 10 KiB file, and you create an + evbuffer_file_segment for it with offset 20 and length 1000, it will + refer to bytes 20..1019 inclusive. If you then pass this segment to + evbuffer_add_file_segment and specify an offset of 20 and a length of + 50, you will be adding bytes 40..99 inclusive. + + @param buf the evbuffer to append to + @param seg the segment to add + @param offset the offset within the segment to start from + @param length the amount of data to add, or -1 to add it all. + @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_add_file_segment(struct evbuffer *buf, + struct evbuffer_file_segment *seg, ev_off_t offset, ev_off_t length); + +/** + Append a formatted string to the end of an evbuffer. + + The string is formated as printf. + + @param buf the evbuffer that will be appended to + @param fmt a format string + @param ... arguments that will be passed to printf(3) + @return The number of bytes added if successful, or -1 if an error occurred. + + @see evutil_printf(), evbuffer_add_vprintf() + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_add_printf(struct evbuffer *buf, const char *fmt, ...) +#ifdef __GNUC__ + __attribute__((format(printf, 2, 3))) +#endif +; + +/** + Append a va_list formatted string to the end of an evbuffer. + + @param buf the evbuffer that will be appended to + @param fmt a format string + @param ap a varargs va_list argument array that will be passed to vprintf(3) + @return The number of bytes added if successful, or -1 if an error occurred. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap) +#ifdef __GNUC__ + __attribute__((format(printf, 2, 0))) +#endif +; + + +/** + Remove a specified number of bytes data from the beginning of an evbuffer. + + @param buf the evbuffer to be drained + @param len the number of bytes to drain from the beginning of the buffer + @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_drain(struct evbuffer *buf, size_t len); + + +/** + Write the contents of an evbuffer to a file descriptor. + + The evbuffer will be drained after the bytes have been successfully written. + + @param buffer the evbuffer to be written and drained + @param fd the file descriptor to be written to + @return the number of bytes written, or -1 if an error occurred + @see evbuffer_read() + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_write(struct evbuffer *buffer, evutil_socket_t fd); + +/** + Write some of the contents of an evbuffer to a file descriptor. + + The evbuffer will be drained after the bytes have been successfully written. + + @param buffer the evbuffer to be written and drained + @param fd the file descriptor to be written to + @param howmuch the largest allowable number of bytes to write, or -1 + to write as many bytes as we can. + @return the number of bytes written, or -1 if an error occurred + @see evbuffer_read() + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_write_atmost(struct evbuffer *buffer, evutil_socket_t fd, + ev_ssize_t howmuch); + +/** + Read from a file descriptor and store the result in an evbuffer. + + @param buffer the evbuffer to store the result + @param fd the file descriptor to read from + @param howmuch the number of bytes to be read + @return the number of bytes read, or -1 if an error occurred + @see evbuffer_write() + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_read(struct evbuffer *buffer, evutil_socket_t fd, int howmuch); + +/** + Search for a string within an evbuffer. + + @param buffer the evbuffer to be searched + @param what the string to be searched for + @param len the length of the search string + @param start NULL or a pointer to a valid struct evbuffer_ptr. + @return a struct evbuffer_ptr whose 'pos' field has the offset of the + first occurrence of the string in the buffer after 'start'. The 'pos' + field of the result is -1 if the string was not found. + */ +EVENT2_EXPORT_SYMBOL +struct evbuffer_ptr evbuffer_search(struct evbuffer *buffer, const char *what, size_t len, const struct evbuffer_ptr *start); + +/** + Search for a string within part of an evbuffer. + + @param buffer the evbuffer to be searched + @param what the string to be searched for + @param len the length of the search string + @param start NULL or a pointer to a valid struct evbuffer_ptr that + indicates where we should start searching. + @param end NULL or a pointer to a valid struct evbuffer_ptr that + indicates where we should stop searching. + @return a struct evbuffer_ptr whose 'pos' field has the offset of the + first occurrence of the string in the buffer after 'start'. The 'pos' + field of the result is -1 if the string was not found. + */ +EVENT2_EXPORT_SYMBOL +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); + +/** + Defines how to adjust an evbuffer_ptr by evbuffer_ptr_set() + + @see evbuffer_ptr_set() */ +enum evbuffer_ptr_how { + /** Sets the pointer to the position; can be called on with an + uninitialized evbuffer_ptr. */ + EVBUFFER_PTR_SET, + /** Advances the pointer by adding to the current position. */ + EVBUFFER_PTR_ADD +}; + +/** + Sets the search pointer in the buffer to position. + + There are two ways to use this function: you can call + evbuffer_ptr_set(buf, &pos, N, EVBUFFER_PTR_SET) + to move 'pos' to a position 'N' bytes after the start of the buffer, or + evbuffer_ptr_set(buf, &pos, N, EVBUFFER_PTR_ADD) + to move 'pos' forward by 'N' bytes. + + If evbuffer_ptr is not initialized, this function can only be called + with EVBUFFER_PTR_SET. + + An evbuffer_ptr can represent any position from the start of the buffer to + a position immediately after the end of the buffer. + + @param buffer the evbuffer to be search + @param ptr a pointer to a struct evbuffer_ptr + @param position the position at which to start the next search + @param how determines how the pointer should be manipulated. + @returns 0 on success or -1 otherwise +*/ +EVENT2_EXPORT_SYMBOL +int +evbuffer_ptr_set(struct evbuffer *buffer, struct evbuffer_ptr *ptr, + size_t position, enum evbuffer_ptr_how how); + +/** + Search for an end-of-line string within an evbuffer. + + @param buffer the evbuffer to be searched + @param start NULL or a pointer to a valid struct evbuffer_ptr to start + searching at. + @param eol_len_out If non-NULL, the pointed-to value will be set to + the length of the end-of-line string. + @param eol_style The kind of EOL to look for; see evbuffer_readln() for + more information + @return a struct evbuffer_ptr whose 'pos' field has the offset of the + first occurrence EOL in the buffer after 'start'. The 'pos' + field of the result is -1 if the string was not found. + */ +EVENT2_EXPORT_SYMBOL +struct evbuffer_ptr evbuffer_search_eol(struct evbuffer *buffer, + struct evbuffer_ptr *start, size_t *eol_len_out, + enum evbuffer_eol_style eol_style); + +/** Function to peek at data inside an evbuffer without removing it or + copying it out. + + Pointers to the data are returned by filling the 'vec_out' array + with pointers to one or more extents of data inside the buffer. + + The total data in the extents that you get back may be more than + you requested (if there is more data last extent than you asked + for), or less (if you do not provide enough evbuffer_iovecs, or if + the buffer does not have as much data as you asked to see). + + @param buffer the evbuffer to peek into, + @param len the number of bytes to try to peek. If len is negative, we + will try to fill as much of vec_out as we can. If len is negative + and vec_out is not provided, we return the number of evbuffer_iovecs + that would be needed to get all the data in the buffer. + @param start_at an evbuffer_ptr indicating the point at which we + should start looking for data. NULL means, "At the start of the + buffer." + @param vec_out an array of evbuffer_iovec + @param n_vec the length of vec_out. If 0, we only count how many + extents would be necessary to point to the requested amount of + data. + @return The number of extents needed. This may be less than n_vec + if we didn't need all the evbuffer_iovecs we were given, or more + than n_vec if we would need more to return all the data that was + requested. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_peek(struct evbuffer *buffer, ev_ssize_t len, + struct evbuffer_ptr *start_at, + struct evbuffer_iovec *vec_out, int n_vec); + + +/** Structure passed to an evbuffer_cb_func evbuffer callback + + @see evbuffer_cb_func, evbuffer_add_cb() + */ +struct evbuffer_cb_info { + /** The number of bytes in this evbuffer when callbacks were last + * invoked. */ + size_t orig_size; + /** The number of bytes added since callbacks were last invoked. */ + size_t n_added; + /** The number of bytes removed since callbacks were last invoked. */ + size_t n_deleted; +}; + +/** Type definition for a callback that is invoked whenever data is added or + removed from an evbuffer. + + An evbuffer may have one or more callbacks set at a time. The order + in which they are executed is undefined. + + A callback function may add more callbacks, or remove itself from the + list of callbacks, or add or remove data from the buffer. It may not + remove another callback from the list. + + If a callback adds or removes data from the buffer or from another + buffer, this can cause a recursive invocation of your callback or + other callbacks. If you ask for an infinite loop, you might just get + one: watch out! + + @param buffer the buffer whose size has changed + @param info a structure describing how the buffer changed. + @param arg a pointer to user data +*/ +typedef void (*evbuffer_cb_func)(struct evbuffer *buffer, const struct evbuffer_cb_info *info, void *arg); + +struct evbuffer_cb_entry; +/** Add a new callback to an evbuffer. + + Subsequent calls to evbuffer_add_cb() add new callbacks. To remove this + callback, call evbuffer_remove_cb or evbuffer_remove_cb_entry. + + @param buffer the evbuffer to be monitored + @param cb the callback function to invoke when the evbuffer is modified, + or NULL to remove all callbacks. + @param cbarg an argument to be provided to the callback function + @return a handle to the callback on success, or NULL on failure. + */ +EVENT2_EXPORT_SYMBOL +struct evbuffer_cb_entry *evbuffer_add_cb(struct evbuffer *buffer, evbuffer_cb_func cb, void *cbarg); + +/** Remove a callback from an evbuffer, given a handle returned from + evbuffer_add_cb. + + Calling this function invalidates the handle. + + @return 0 if a callback was removed, or -1 if no matching callback was + found. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_remove_cb_entry(struct evbuffer *buffer, + struct evbuffer_cb_entry *ent); + +/** Remove a callback from an evbuffer, given the function and argument + used to add it. + + @return 0 if a callback was removed, or -1 if no matching callback was + found. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_remove_cb(struct evbuffer *buffer, evbuffer_cb_func cb, void *cbarg); + +/** If this flag is not set, then a callback is temporarily disabled, and + * should not be invoked. + * + * @see evbuffer_cb_set_flags(), evbuffer_cb_clear_flags() + */ +#define EVBUFFER_CB_ENABLED 1 + +/** Change the flags that are set for a callback on a buffer by adding more. + + @param buffer the evbuffer that the callback is watching. + @param cb the callback whose status we want to change. + @param flags EVBUFFER_CB_ENABLED to re-enable the callback. + @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_cb_set_flags(struct evbuffer *buffer, + struct evbuffer_cb_entry *cb, ev_uint32_t flags); + +/** Change the flags that are set for a callback on a buffer by removing some + + @param buffer the evbuffer that the callback is watching. + @param cb the callback whose status we want to change. + @param flags EVBUFFER_CB_ENABLED to disable the callback. + @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_cb_clear_flags(struct evbuffer *buffer, + struct evbuffer_cb_entry *cb, ev_uint32_t flags); + +#if 0 +/** Postpone calling a given callback until unsuspend is called later. + + This is different from disabling the callback, since the callback will get + invoked later if the buffer size changes between now and when we unsuspend + it. + + @param the buffer that the callback is watching. + @param cb the callback we want to suspend. + */ +EVENT2_EXPORT_SYMBOL +void evbuffer_cb_suspend(struct evbuffer *buffer, struct evbuffer_cb_entry *cb); +/** Stop postponing a callback that we postponed with evbuffer_cb_suspend. + + If data was added to or removed from the buffer while the callback was + suspended, the callback will get called once now. + + @param the buffer that the callback is watching. + @param cb the callback we want to stop suspending. + */ +EVENT2_EXPORT_SYMBOL +void evbuffer_cb_unsuspend(struct evbuffer *buffer, struct evbuffer_cb_entry *cb); +#endif + +/** + Makes the data at the beginning of an evbuffer contiguous. + + @param buf the evbuffer to make contiguous + @param size the number of bytes to make contiguous, or -1 to make the + entire buffer contiguous. + @return a pointer to the contiguous memory array, or NULL if param size + requested more data than is present in the buffer. +*/ + +EVENT2_EXPORT_SYMBOL +unsigned char *evbuffer_pullup(struct evbuffer *buf, ev_ssize_t size); + +/** + Prepends data to the beginning of the evbuffer + + @param buf the evbuffer to which to prepend data + @param data a pointer to the memory to prepend + @param size the number of bytes to prepend + @return 0 if successful, or -1 otherwise +*/ + +EVENT2_EXPORT_SYMBOL +int evbuffer_prepend(struct evbuffer *buf, const void *data, size_t size); + +/** + Prepends all data from the src evbuffer to the beginning of the dst + evbuffer. + + @param dst the evbuffer to which to prepend data + @param src the evbuffer to prepend; it will be emptied as a result + @return 0 if successful, or -1 otherwise +*/ +EVENT2_EXPORT_SYMBOL +int evbuffer_prepend_buffer(struct evbuffer *dst, struct evbuffer* src); + +/** + Prevent calls that modify an evbuffer from succeeding. A buffer may + frozen at the front, at the back, or at both the front and the back. + + If the front of a buffer is frozen, operations that drain data from + the front of the buffer, or that prepend data to the buffer, will + fail until it is unfrozen. If the back a buffer is frozen, operations + that append data from the buffer will fail until it is unfrozen. + + @param buf The buffer to freeze + @param at_front If true, we freeze the front of the buffer. If false, + we freeze the back. + @return 0 on success, -1 on failure. +*/ +EVENT2_EXPORT_SYMBOL +int evbuffer_freeze(struct evbuffer *buf, int at_front); +/** + Re-enable calls that modify an evbuffer. + + @param buf The buffer to un-freeze + @param at_front If true, we unfreeze the front of the buffer. If false, + we unfreeze the back. + @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_unfreeze(struct evbuffer *buf, int at_front); + +struct event_base; +/** + Force all the callbacks on an evbuffer to be run, not immediately after + the evbuffer is altered, but instead from inside the event loop. + + This can be used to serialize all the callbacks to a single thread + of execution. + */ +EVENT2_EXPORT_SYMBOL +int evbuffer_defer_callbacks(struct evbuffer *buffer, struct event_base *base); + +/** + Append data from 1 or more iovec's to an evbuffer + + Calculates the number of bytes needed for an iovec structure and guarantees + all data will fit into a single chain. Can be used in lieu of functionality + which calls evbuffer_add() constantly before being used to increase + performance. + + @param buffer the destination buffer + @param vec the source iovec + @param n_vec the number of iovec structures. + @return the number of bytes successfully written to the output buffer. +*/ +EVENT2_EXPORT_SYMBOL +size_t evbuffer_add_iovec(struct evbuffer * buffer, struct evbuffer_iovec * vec, int n_vec); + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_BUFFER_H_INCLUDED_ */ diff --git a/platform/src/3rd/os_specific/oe2203/include/event2/buffer_compat.h b/platform/src/3rd/os_specific/oe2203/include/event2/buffer_compat.h new file mode 100644 index 00000000..24f828c2 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/event2/buffer_compat.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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 EVENT2_BUFFER_COMPAT_H_INCLUDED_ +#define EVENT2_BUFFER_COMPAT_H_INCLUDED_ + +#include + +/** @file event2/buffer_compat.h + + Obsolete and deprecated versions of the functions in buffer.h: provided + only for backward compatibility. + */ + + +/** + Obsolete alias for evbuffer_readln(buffer, NULL, EVBUFFER_EOL_ANY). + + @deprecated This function is deprecated because its behavior is not correct + for almost any protocol, and also because it's wholly subsumed by + evbuffer_readln(). + + @param buffer the evbuffer to read from + @return pointer to a single line, or NULL if an error occurred + +*/ +EVENT2_EXPORT_SYMBOL +char *evbuffer_readline(struct evbuffer *buffer); + +/** Type definition for a callback that is invoked whenever data is added or + removed from an evbuffer. + + An evbuffer may have one or more callbacks set at a time. The order + in which they are executed is undefined. + + A callback function may add more callbacks, or remove itself from the + list of callbacks, or add or remove data from the buffer. It may not + remove another callback from the list. + + If a callback adds or removes data from the buffer or from another + buffer, this can cause a recursive invocation of your callback or + other callbacks. If you ask for an infinite loop, you might just get + one: watch out! + + @param buffer the buffer whose size has changed + @param old_len the previous length of the buffer + @param new_len the current length of the buffer + @param arg a pointer to user data +*/ +typedef void (*evbuffer_cb)(struct evbuffer *buffer, size_t old_len, size_t new_len, void *arg); + +/** + Replace all callbacks on an evbuffer with a single new callback, or + remove them. + + Subsequent calls to evbuffer_setcb() replace callbacks set by previous + calls. Setting the callback to NULL removes any previously set callback. + + @deprecated This function is deprecated because it clears all previous + callbacks set on the evbuffer, which can cause confusing behavior if + multiple parts of the code all want to add their own callbacks on a + buffer. Instead, use evbuffer_add(), evbuffer_del(), and + evbuffer_setflags() to manage your own evbuffer callbacks without + interfering with callbacks set by others. + + @param buffer the evbuffer to be monitored + @param cb the callback function to invoke when the evbuffer is modified, + or NULL to remove all callbacks. + @param cbarg an argument to be provided to the callback function + */ +EVENT2_EXPORT_SYMBOL +void evbuffer_setcb(struct evbuffer *buffer, evbuffer_cb cb, void *cbarg); + + +/** + Find a string within an evbuffer. + + @param buffer the evbuffer to be searched + @param what the string to be searched for + @param len the length of the search string + @return a pointer to the beginning of the search string, or NULL if the search failed. + */ +EVENT2_EXPORT_SYMBOL +unsigned char *evbuffer_find(struct evbuffer *buffer, const unsigned char *what, size_t len); + +/** deprecated in favor of calling the functions directly */ +#define EVBUFFER_LENGTH(x) evbuffer_get_length(x) +/** deprecated in favor of calling the functions directly */ +#define EVBUFFER_DATA(x) evbuffer_pullup((x), -1) + +#endif + diff --git a/platform/src/3rd/os_specific/oe2203/include/event2/bufferevent.h b/platform/src/3rd/os_specific/oe2203/include/event2/bufferevent.h new file mode 100644 index 00000000..825918e3 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/event2/bufferevent.h @@ -0,0 +1,1021 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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 EVENT2_BUFFEREVENT_H_INCLUDED_ +#define EVENT2_BUFFEREVENT_H_INCLUDED_ + +/** + @file event2/bufferevent.h + + Functions for buffering data for network sending or receiving. Bufferevents + are higher level than evbuffers: each has an underlying evbuffer for reading + and one for writing, and callbacks that are invoked under certain + circumstances. + + A bufferevent provides input and output buffers that get filled and + drained automatically. The user of a bufferevent no longer deals + directly with the I/O, but instead is reading from input and writing + to output buffers. + + Once initialized, the bufferevent structure can be used repeatedly + with bufferevent_enable() and bufferevent_disable(). + + When reading is enabled, the bufferevent will try to read from the + file descriptor onto its input buffer, and call the read callback. + When writing is enabled, the bufferevent will try to write data onto its + file descriptor when the output buffer has enough data, and call the write + callback when the output buffer is sufficiently drained. + + Bufferevents come in several flavors, including: + +
+
Socket-based bufferevents
+
A bufferevent that reads and writes data onto a network + socket. Created with bufferevent_socket_new().
+ +
Paired bufferevents
+
A pair of bufferevents that send and receive data to one + another without touching the network. Created with + bufferevent_pair_new().
+ +
Filtering bufferevents
+
A bufferevent that transforms data, and sends or receives it + over another underlying bufferevent. Created with + bufferevent_filter_new().
+ +
SSL-backed bufferevents
+
A bufferevent that uses the openssl library to send and + receive data over an encrypted connection. Created with + bufferevent_openssl_socket_new() or + bufferevent_openssl_filter_new().
+
+ */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef EVENT__HAVE_SYS_TYPES_H +#include +#endif +#ifdef EVENT__HAVE_SYS_TIME_H +#include +#endif + +/* For int types. */ +#include + +/** @name Bufferevent event codes + + These flags are passed as arguments to a bufferevent's event callback. + + @{ +*/ +#define BEV_EVENT_READING 0x01 /**< error encountered while reading */ +#define BEV_EVENT_WRITING 0x02 /**< error encountered while writing */ +#define BEV_EVENT_EOF 0x10 /**< eof file reached */ +#define BEV_EVENT_ERROR 0x20 /**< unrecoverable error encountered */ +#define BEV_EVENT_TIMEOUT 0x40 /**< user-specified timeout reached */ +#define BEV_EVENT_CONNECTED 0x80 /**< connect operation finished. */ +/**@}*/ + +/** + An opaque type for handling buffered IO + + @see event2/bufferevent.h + */ +struct bufferevent +#ifdef EVENT_IN_DOXYGEN_ +{} +#endif +; +struct event_base; +struct evbuffer; +struct sockaddr; + +/** + A read or write callback for a bufferevent. + + The read callback is triggered when new data arrives in the input + buffer and the amount of readable data exceed the low watermark + which is 0 by default. + + The write callback is triggered if the write buffer has been + exhausted or fell below its low watermark. + + @param bev the bufferevent that triggered the callback + @param ctx the user-specified context for this bufferevent + */ +typedef void (*bufferevent_data_cb)(struct bufferevent *bev, void *ctx); + +/** + An event/error callback for a bufferevent. + + The event callback is triggered if either an EOF condition or another + unrecoverable error was encountered. + + For bufferevents with deferred callbacks, this is a bitwise OR of all errors + that have happened on the bufferevent since the last callback invocation. + + @param bev the bufferevent for which the error condition was reached + @param what a conjunction of flags: BEV_EVENT_READING or BEV_EVENT_WRITING + to indicate if the error was encountered on the read or write path, + and one of the following flags: BEV_EVENT_EOF, BEV_EVENT_ERROR, + BEV_EVENT_TIMEOUT, BEV_EVENT_CONNECTED. + + @param ctx the user-specified context for this bufferevent +*/ +typedef void (*bufferevent_event_cb)(struct bufferevent *bev, short what, void *ctx); + +/** Options that can be specified when creating a bufferevent */ +enum bufferevent_options { + /** If set, we close the underlying file + * descriptor/bufferevent/whatever when this bufferevent is freed. */ + BEV_OPT_CLOSE_ON_FREE = (1<<0), + + /** If set, and threading is enabled, operations on this bufferevent + * are protected by a lock */ + BEV_OPT_THREADSAFE = (1<<1), + + /** If set, callbacks are run deferred in the event loop. */ + BEV_OPT_DEFER_CALLBACKS = (1<<2), + + /** If set, callbacks are executed without locks being held on the + * bufferevent. This option currently requires that + * BEV_OPT_DEFER_CALLBACKS also be set; a future version of Libevent + * might remove the requirement.*/ + BEV_OPT_UNLOCK_CALLBACKS = (1<<3) +}; + +/** + Create a new socket bufferevent over an existing socket. + + @param base the event base to associate with the new bufferevent. + @param fd the file descriptor from which data is read and written to. + This file descriptor is not allowed to be a pipe(2). + It is safe to set the fd to -1, so long as you later + set it with bufferevent_setfd or bufferevent_socket_connect(). + @param options Zero or more BEV_OPT_* flags + @return a pointer to a newly allocated bufferevent struct, or NULL if an + error occurred + @see bufferevent_free() + */ +EVENT2_EXPORT_SYMBOL +struct bufferevent *bufferevent_socket_new(struct event_base *base, evutil_socket_t fd, int options); + +/** + Launch a connect() attempt with a socket-based bufferevent. + + When the connect succeeds, the eventcb will be invoked with + BEV_EVENT_CONNECTED set. + + If the bufferevent does not already have a socket set, we allocate a new + socket here and make it nonblocking before we begin. + + If no address is provided, we assume that the socket is already connecting, + and configure the bufferevent so that a BEV_EVENT_CONNECTED event will be + yielded when it is done connecting. + + @param bufev an existing bufferevent allocated with + bufferevent_socket_new(). + @param addr the address we should connect to + @param socklen The length of the address + @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_socket_connect(struct bufferevent *, const struct sockaddr *, int); + +struct evdns_base; +/** + Resolve the hostname 'hostname' and connect to it as with + bufferevent_socket_connect(). + + @param bufev An existing bufferevent allocated with bufferevent_socket_new() + @param evdns_base Optionally, an evdns_base to use for resolving hostnames + asynchronously. May be set to NULL for a blocking resolve. + @param family A preferred address family to resolve addresses to, or + AF_UNSPEC for no preference. Only AF_INET, AF_INET6, and AF_UNSPEC are + supported. + @param hostname The hostname to resolve; see below for notes on recognized + formats + @param port The port to connect to on the resolved address. + @return 0 if successful, -1 on failure. + + Recognized hostname formats are: + + www.example.com (hostname) + 1.2.3.4 (ipv4address) + ::1 (ipv6address) + [::1] ([ipv6address]) + + Performance note: If you do not provide an evdns_base, this function + may block while it waits for a DNS response. This is probably not + what you want. + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_socket_connect_hostname(struct bufferevent *, + struct evdns_base *, int, const char *, int); + +/** + Return the error code for the last failed DNS lookup attempt made by + bufferevent_socket_connect_hostname(). + + @param bev The bufferevent object. + @return DNS error code. + @see evutil_gai_strerror() +*/ +EVENT2_EXPORT_SYMBOL +int bufferevent_socket_get_dns_error(struct bufferevent *bev); + +/** + Assign a bufferevent to a specific event_base. + + NOTE that only socket bufferevents support this function. + + @param base an event_base returned by event_init() + @param bufev a bufferevent struct returned by bufferevent_new() + or bufferevent_socket_new() + @return 0 if successful, or -1 if an error occurred + @see bufferevent_new() + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_base_set(struct event_base *base, struct bufferevent *bufev); + +/** + Return the event_base used by a bufferevent +*/ +EVENT2_EXPORT_SYMBOL +struct event_base *bufferevent_get_base(struct bufferevent *bev); + +/** + Assign a priority to a bufferevent. + + Only supported for socket bufferevents. + + @param bufev a bufferevent struct + @param pri the priority to be assigned + @return 0 if successful, or -1 if an error occurred + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_priority_set(struct bufferevent *bufev, int pri); + +/** + Return the priority of a bufferevent. + + Only supported for socket bufferevents + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_get_priority(const struct bufferevent *bufev); + +/** + Deallocate the storage associated with a bufferevent structure. + + If there is pending data to write on the bufferevent, it probably won't be + flushed before the bufferevent is freed. + + @param bufev the bufferevent structure to be freed. + */ +EVENT2_EXPORT_SYMBOL +void bufferevent_free(struct bufferevent *bufev); + + +/** + Changes the callbacks for a bufferevent. + + @param bufev the bufferevent object for which to change callbacks + @param readcb callback to invoke when there is data to be read, or NULL if + no callback is desired + @param writecb callback to invoke when the file descriptor is ready for + writing, or NULL if no callback is desired + @param eventcb callback to invoke when there is an event on the file + descriptor + @param cbarg an argument that will be supplied to each of the callbacks + (readcb, writecb, and errorcb) + @see bufferevent_new() + */ +EVENT2_EXPORT_SYMBOL +void bufferevent_setcb(struct bufferevent *bufev, + bufferevent_data_cb readcb, bufferevent_data_cb writecb, + bufferevent_event_cb eventcb, void *cbarg); + +/** + Retrieves the callbacks for a bufferevent. + + @param bufev the bufferevent to examine. + @param readcb_ptr if readcb_ptr is nonnull, *readcb_ptr is set to the current + read callback for the bufferevent. + @param writecb_ptr if writecb_ptr is nonnull, *writecb_ptr is set to the + current write callback for the bufferevent. + @param eventcb_ptr if eventcb_ptr is nonnull, *eventcb_ptr is set to the + current event callback for the bufferevent. + @param cbarg_ptr if cbarg_ptr is nonnull, *cbarg_ptr is set to the current + callback argument for the bufferevent. + @see buffervent_setcb() +*/ +EVENT2_EXPORT_SYMBOL +void bufferevent_getcb(struct bufferevent *bufev, + bufferevent_data_cb *readcb_ptr, + bufferevent_data_cb *writecb_ptr, + bufferevent_event_cb *eventcb_ptr, + void **cbarg_ptr); + +/** + Changes the file descriptor on which the bufferevent operates. + Not supported for all bufferevent types. + + @param bufev the bufferevent object for which to change the file descriptor + @param fd the file descriptor to operate on +*/ +EVENT2_EXPORT_SYMBOL +int bufferevent_setfd(struct bufferevent *bufev, evutil_socket_t fd); + +/** + Returns the file descriptor associated with a bufferevent, or -1 if + no file descriptor is associated with the bufferevent. + */ +EVENT2_EXPORT_SYMBOL +evutil_socket_t bufferevent_getfd(struct bufferevent *bufev); + +/** + Returns the underlying bufferevent associated with a bufferevent (if + the bufferevent is a wrapper), or NULL if there is no underlying bufferevent. + */ +EVENT2_EXPORT_SYMBOL +struct bufferevent *bufferevent_get_underlying(struct bufferevent *bufev); + +/** + Write data to a bufferevent buffer. + + The bufferevent_write() function can be used to write data to the file + descriptor. The data is appended to the output buffer and written to the + descriptor automatically as it becomes available for writing. + + @param bufev the bufferevent to be written to + @param data a pointer to the data to be written + @param size the length of the data, in bytes + @return 0 if successful, or -1 if an error occurred + @see bufferevent_write_buffer() + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_write(struct bufferevent *bufev, + const void *data, size_t size); + + +/** + Write data from an evbuffer to a bufferevent buffer. The evbuffer is + being drained as a result. + + @param bufev the bufferevent to be written to + @param buf the evbuffer to be written + @return 0 if successful, or -1 if an error occurred + @see bufferevent_write() + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf); + + +/** + Read data from a bufferevent buffer. + + The bufferevent_read() function is used to read data from the input buffer. + + @param bufev the bufferevent to be read from + @param data pointer to a buffer that will store the data + @param size the size of the data buffer, in bytes + @return the amount of data read, in bytes. + */ +EVENT2_EXPORT_SYMBOL +size_t bufferevent_read(struct bufferevent *bufev, void *data, size_t size); + +/** + Read data from a bufferevent buffer into an evbuffer. This avoids + memory copies. + + @param bufev the bufferevent to be read from + @param buf the evbuffer to which to add data + @return 0 if successful, or -1 if an error occurred. + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_read_buffer(struct bufferevent *bufev, struct evbuffer *buf); + +/** + Returns the input buffer. + + The user MUST NOT set the callback on this buffer. + + @param bufev the bufferevent from which to get the evbuffer + @return the evbuffer object for the input buffer + */ + +EVENT2_EXPORT_SYMBOL +struct evbuffer *bufferevent_get_input(struct bufferevent *bufev); + +/** + Returns the output buffer. + + The user MUST NOT set the callback on this buffer. + + When filters are being used, the filters need to be manually + triggered if the output buffer was manipulated. + + @param bufev the bufferevent from which to get the evbuffer + @return the evbuffer object for the output buffer + */ + +EVENT2_EXPORT_SYMBOL +struct evbuffer *bufferevent_get_output(struct bufferevent *bufev); + +/** + Enable a bufferevent. + + @param bufev the bufferevent to be enabled + @param event any combination of EV_READ | EV_WRITE. + @return 0 if successful, or -1 if an error occurred + @see bufferevent_disable() + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_enable(struct bufferevent *bufev, short event); + +/** + Disable a bufferevent. + + @param bufev the bufferevent to be disabled + @param event any combination of EV_READ | EV_WRITE. + @return 0 if successful, or -1 if an error occurred + @see bufferevent_enable() + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_disable(struct bufferevent *bufev, short event); + +/** + Return the events that are enabled on a given bufferevent. + + @param bufev the bufferevent to inspect + @return A combination of EV_READ | EV_WRITE + */ +EVENT2_EXPORT_SYMBOL +short bufferevent_get_enabled(struct bufferevent *bufev); + +/** + Set the read and write timeout for a bufferevent. + + A bufferevent's timeout will fire the first time that the indicated + amount of time has elapsed since a successful read or write operation, + during which the bufferevent was trying to read or write. + + (In other words, if reading or writing is disabled, or if the + bufferevent's read or write operation has been suspended because + there's no data to write, or not enough banwidth, or so on, the + timeout isn't active. The timeout only becomes active when we we're + willing to actually read or write.) + + Calling bufferevent_enable or setting a timeout for a bufferevent + whose timeout is already pending resets its timeout. + + If the timeout elapses, the corresponding operation (EV_READ or + EV_WRITE) becomes disabled until you re-enable it again. The + bufferevent's event callback is called with the + BEV_EVENT_TIMEOUT|BEV_EVENT_READING or + BEV_EVENT_TIMEOUT|BEV_EVENT_WRITING. + + @param bufev the bufferevent to be modified + @param timeout_read the read timeout, or NULL + @param timeout_write the write timeout, or NULL + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_set_timeouts(struct bufferevent *bufev, + const struct timeval *timeout_read, const struct timeval *timeout_write); + +/** + Sets the watermarks for read and write events. + + On input, a bufferevent does not invoke the user read callback unless + there is at least low watermark data in the buffer. If the read buffer + is beyond the high watermark, the bufferevent stops reading from the network. + + On output, the user write callback is invoked whenever the buffered data + falls below the low watermark. Filters that write to this bufev will try + not to write more bytes to this buffer than the high watermark would allow, + except when flushing. + + @param bufev the bufferevent to be modified + @param events EV_READ, EV_WRITE or both + @param lowmark the lower watermark to set + @param highmark the high watermark to set +*/ + +EVENT2_EXPORT_SYMBOL +void bufferevent_setwatermark(struct bufferevent *bufev, short events, + size_t lowmark, size_t highmark); + +/** + Retrieves the watermarks for read or write events. + Returns non-zero if events contains not only EV_READ or EV_WRITE. + Returns zero if events equal EV_READ or EV_WRITE + + @param bufev the bufferevent to be examined + @param events EV_READ or EV_WRITE + @param lowmark receives the lower watermark if not NULL + @param highmark receives the high watermark if not NULL +*/ +EVENT2_EXPORT_SYMBOL +int bufferevent_getwatermark(struct bufferevent *bufev, short events, + size_t *lowmark, size_t *highmark); + +/** + Acquire the lock on a bufferevent. Has no effect if locking was not + enabled with BEV_OPT_THREADSAFE. + */ +EVENT2_EXPORT_SYMBOL +void bufferevent_lock(struct bufferevent *bufev); + +/** + Release the lock on a bufferevent. Has no effect if locking was not + enabled with BEV_OPT_THREADSAFE. + */ +EVENT2_EXPORT_SYMBOL +void bufferevent_unlock(struct bufferevent *bufev); + + +/** + * Public interface to manually increase the reference count of a bufferevent + * this is useful in situations where a user may reference the bufferevent + * somewhere eles (unknown to libevent) + * + * @param bufev the bufferevent to increase the refcount on + * + */ +EVENT2_EXPORT_SYMBOL +void bufferevent_incref(struct bufferevent *bufev); + +/** + * Public interface to manually decrement the reference count of a bufferevent + * + * Warning: make sure you know what you're doing. This is mainly used in + * conjunction with bufferevent_incref(). This will free up all data associated + * with a bufferevent if the reference count hits 0. + * + * @param bufev the bufferevent to decrement the refcount on + * + * @return 1 if the bufferevent was freed, otherwise 0 (still referenced) + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_decref(struct bufferevent *bufev); + +/** + Flags that can be passed into filters to let them know how to + deal with the incoming data. +*/ +enum bufferevent_flush_mode { + /** usually set when processing data */ + BEV_NORMAL = 0, + + /** want to checkpoint all data sent. */ + BEV_FLUSH = 1, + + /** encountered EOF on read or done sending data */ + BEV_FINISHED = 2 +}; + +/** + Triggers the bufferevent to produce more data if possible. + + @param bufev the bufferevent object + @param iotype either EV_READ or EV_WRITE or both. + @param mode either BEV_NORMAL or BEV_FLUSH or BEV_FINISHED + @return -1 on failure, 0 if no data was produces, 1 if data was produced + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_flush(struct bufferevent *bufev, + short iotype, + enum bufferevent_flush_mode mode); + +/** + Flags for bufferevent_trigger(_event) that modify when and how to trigger + the callback. +*/ +enum bufferevent_trigger_options { + /** trigger the callback regardless of the watermarks */ + BEV_TRIG_IGNORE_WATERMARKS = (1<<16), + + /** defer even if the callbacks are not */ + BEV_TRIG_DEFER_CALLBACKS = BEV_OPT_DEFER_CALLBACKS + + /* (Note: for internal reasons, these need to be disjoint from + * bufferevent_options, except when they mean the same thing. */ +}; + +/** + Triggers bufferevent data callbacks. + + The function will honor watermarks unless options contain + BEV_TRIG_IGNORE_WATERMARKS. If the options contain BEV_OPT_DEFER_CALLBACKS, + the callbacks are deferred. + + @param bufev the bufferevent object + @param iotype either EV_READ or EV_WRITE or both. + @param options + */ +EVENT2_EXPORT_SYMBOL +void bufferevent_trigger(struct bufferevent *bufev, short iotype, + int options); + +/** + Triggers the bufferevent event callback. + + If the options contain BEV_OPT_DEFER_CALLBACKS, the callbacks are deferred. + + @param bufev the bufferevent object + @param what the flags to pass onto the event callback + @param options + */ +EVENT2_EXPORT_SYMBOL +void bufferevent_trigger_event(struct bufferevent *bufev, short what, + int options); + +/** + @name Filtering support + + @{ +*/ +/** + Values that filters can return. + */ +enum bufferevent_filter_result { + /** everything is okay */ + BEV_OK = 0, + + /** the filter needs to read more data before output */ + BEV_NEED_MORE = 1, + + /** the filter encountered a critical error, no further data + can be processed. */ + BEV_ERROR = 2 +}; + +/** A callback function to implement a filter for a bufferevent. + + @param src An evbuffer to drain data from. + @param dst An evbuffer to add data to. + @param limit A suggested upper bound of bytes to write to dst. + The filter may ignore this value, but doing so means that + it will overflow the high-water mark associated with dst. + -1 means "no limit". + @param mode Whether we should write data as may be convenient + (BEV_NORMAL), or flush as much data as we can (BEV_FLUSH), + or flush as much as we can, possibly including an end-of-stream + marker (BEV_FINISH). + @param ctx A user-supplied pointer. + + @return BEV_OK if we wrote some data; BEV_NEED_MORE if we can't + produce any more output until we get some input; and BEV_ERROR + on an error. + */ +typedef enum bufferevent_filter_result (*bufferevent_filter_cb)( + struct evbuffer *src, struct evbuffer *dst, ev_ssize_t dst_limit, + enum bufferevent_flush_mode mode, void *ctx); + +/** + Allocate a new filtering bufferevent on top of an existing bufferevent. + + @param underlying the underlying bufferevent. + @param input_filter The filter to apply to data we read from the underlying + bufferevent + @param output_filter The filer to apply to data we write to the underlying + bufferevent + @param options A bitfield of bufferevent options. + @param free_context A function to use to free the filter context when + this bufferevent is freed. + @param ctx A context pointer to pass to the filter functions. + */ +EVENT2_EXPORT_SYMBOL +struct bufferevent * +bufferevent_filter_new(struct bufferevent *underlying, + bufferevent_filter_cb input_filter, + bufferevent_filter_cb output_filter, + int options, + void (*free_context)(void *), + void *ctx); +/**@}*/ + +/** + Allocate a pair of linked bufferevents. The bufferevents behave as would + two bufferevent_sock instances connected to opposite ends of a + socketpair(), except that no internal socketpair is allocated. + + @param base The event base to associate with the socketpair. + @param options A set of options for this bufferevent + @param pair A pointer to an array to hold the two new bufferevent objects. + @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_pair_new(struct event_base *base, int options, + struct bufferevent *pair[2]); + +/** + Given one bufferevent returned by bufferevent_pair_new(), returns the + other one if it still exists. Otherwise returns NULL. + */ +EVENT2_EXPORT_SYMBOL +struct bufferevent *bufferevent_pair_get_partner(struct bufferevent *bev); + +/** + Abstract type used to configure rate-limiting on a bufferevent or a group + of bufferevents. + */ +struct ev_token_bucket_cfg; + +/** + A group of bufferevents which are configured to respect the same rate + limit. +*/ +struct bufferevent_rate_limit_group; + +/** Maximum configurable rate- or burst-limit. */ +#define EV_RATE_LIMIT_MAX EV_SSIZE_MAX + +/** + Initialize and return a new object to configure the rate-limiting behavior + of bufferevents. + + @param read_rate The maximum number of bytes to read per tick on + average. + @param read_burst The maximum number of bytes to read in any single tick. + @param write_rate The maximum number of bytes to write per tick on + average. + @param write_burst The maximum number of bytes to write in any single tick. + @param tick_len The length of a single tick. Defaults to one second. + Any fractions of a millisecond are ignored. + + Note that all rate-limits hare are currently best-effort: future versions + of Libevent may implement them more tightly. + */ +EVENT2_EXPORT_SYMBOL +struct ev_token_bucket_cfg *ev_token_bucket_cfg_new( + size_t read_rate, size_t read_burst, + size_t write_rate, size_t write_burst, + const struct timeval *tick_len); + +/** Free all storage held in 'cfg'. + + Note: 'cfg' is not currently reference-counted; it is not safe to free it + until no bufferevent is using it. + */ +EVENT2_EXPORT_SYMBOL +void ev_token_bucket_cfg_free(struct ev_token_bucket_cfg *cfg); + +/** + Set the rate-limit of a the bufferevent 'bev' to the one specified in + 'cfg'. If 'cfg' is NULL, disable any per-bufferevent rate-limiting on + 'bev'. + + Note that only some bufferevent types currently respect rate-limiting. + They are: socket-based bufferevents (normal and IOCP-based), and SSL-based + bufferevents. + + Return 0 on sucess, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_set_rate_limit(struct bufferevent *bev, + struct ev_token_bucket_cfg *cfg); + +/** + Create a new rate-limit group for bufferevents. A rate-limit group + constrains the maximum number of bytes sent and received, in toto, + by all of its bufferevents. + + @param base An event_base to run any necessary timeouts for the group. + Note that all bufferevents in the group do not necessarily need to share + this event_base. + @param cfg The rate-limit for this group. + + Note that all rate-limits hare are currently best-effort: future versions + of Libevent may implement them more tightly. + + Note also that only some bufferevent types currently respect rate-limiting. + They are: socket-based bufferevents (normal and IOCP-based), and SSL-based + bufferevents. + */ +EVENT2_EXPORT_SYMBOL +struct bufferevent_rate_limit_group *bufferevent_rate_limit_group_new( + struct event_base *base, + const struct ev_token_bucket_cfg *cfg); +/** + Change the rate-limiting settings for a given rate-limiting group. + + Return 0 on success, -1 on failure. +*/ +EVENT2_EXPORT_SYMBOL +int bufferevent_rate_limit_group_set_cfg( + struct bufferevent_rate_limit_group *, + const struct ev_token_bucket_cfg *); + +/** + Change the smallest quantum we're willing to allocate to any single + bufferevent in a group for reading or writing at a time. + + The rationale is that, because of TCP/IP protocol overheads and kernel + behavior, if a rate-limiting group is so tight on bandwidth that you're + only willing to send 1 byte per tick per bufferevent, you might instead + want to batch up the reads and writes so that you send N bytes per + 1/N of the bufferevents (chosen at random) each tick, so you still wind + up send 1 byte per tick per bufferevent on average, but you don't send + so many tiny packets. + + The default min-share is currently 64 bytes. + + Returns 0 on success, -1 on faulre. + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_rate_limit_group_set_min_share( + struct bufferevent_rate_limit_group *, size_t); + +/** + Free a rate-limiting group. The group must have no members when + this function is called. +*/ +EVENT2_EXPORT_SYMBOL +void bufferevent_rate_limit_group_free(struct bufferevent_rate_limit_group *); + +/** + Add 'bev' to the list of bufferevents whose aggregate reading and writing + is restricted by 'g'. If 'g' is NULL, remove 'bev' from its current group. + + A bufferevent may belong to no more than one rate-limit group at a time. + If 'bev' is already a member of a group, it will be removed from its old + group before being added to 'g'. + + Return 0 on success and -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_add_to_rate_limit_group(struct bufferevent *bev, + struct bufferevent_rate_limit_group *g); + +/** Remove 'bev' from its current rate-limit group (if any). */ +EVENT2_EXPORT_SYMBOL +int bufferevent_remove_from_rate_limit_group(struct bufferevent *bev); + +/** + Set the size limit for single read operation. + + Set to 0 for a reasonable default. + + Return 0 on success and -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_set_max_single_read(struct bufferevent *bev, size_t size); + +/** + Set the size limit for single write operation. + + Set to 0 for a reasonable default. + + Return 0 on success and -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_set_max_single_write(struct bufferevent *bev, size_t size); + +/** Get the current size limit for single read operation. */ +EVENT2_EXPORT_SYMBOL +ev_ssize_t bufferevent_get_max_single_read(struct bufferevent *bev); + +/** Get the current size limit for single write operation. */ +EVENT2_EXPORT_SYMBOL +ev_ssize_t bufferevent_get_max_single_write(struct bufferevent *bev); + +/** + @name Rate limit inspection + + Return the current read or write bucket size for a bufferevent. + If it is not configured with a per-bufferevent ratelimit, return + EV_SSIZE_MAX. This function does not inspect the group limit, if any. + Note that it can return a negative value if the bufferevent has been + made to read or write more than its limit. + + @{ + */ +EVENT2_EXPORT_SYMBOL +ev_ssize_t bufferevent_get_read_limit(struct bufferevent *bev); +EVENT2_EXPORT_SYMBOL +ev_ssize_t bufferevent_get_write_limit(struct bufferevent *bev); +/*@}*/ + +EVENT2_EXPORT_SYMBOL +ev_ssize_t bufferevent_get_max_to_read(struct bufferevent *bev); +EVENT2_EXPORT_SYMBOL +ev_ssize_t bufferevent_get_max_to_write(struct bufferevent *bev); + +EVENT2_EXPORT_SYMBOL +const struct ev_token_bucket_cfg *bufferevent_get_token_bucket_cfg(const struct bufferevent * bev); + +/** + @name Group Rate limit inspection + + Return the read or write bucket size for a bufferevent rate limit + group. Note that it can return a negative value if bufferevents in + the group have been made to read or write more than their limits. + + @{ + */ +EVENT2_EXPORT_SYMBOL +ev_ssize_t bufferevent_rate_limit_group_get_read_limit( + struct bufferevent_rate_limit_group *); +EVENT2_EXPORT_SYMBOL +ev_ssize_t bufferevent_rate_limit_group_get_write_limit( + struct bufferevent_rate_limit_group *); +/*@}*/ + +/** + @name Rate limit manipulation + + Subtract a number of bytes from a bufferevent's read or write bucket. + The decrement value can be negative, if you want to manually refill + the bucket. If the change puts the bucket above or below zero, the + bufferevent will resume or suspend reading writing as appropriate. + These functions make no change in the buckets for the bufferevent's + group, if any. + + Returns 0 on success, -1 on internal error. + + @{ + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_decrement_read_limit(struct bufferevent *bev, ev_ssize_t decr); +EVENT2_EXPORT_SYMBOL +int bufferevent_decrement_write_limit(struct bufferevent *bev, ev_ssize_t decr); +/*@}*/ + +/** + @name Group rate limit manipulation + + Subtract a number of bytes from a bufferevent rate-limiting group's + read or write bucket. The decrement value can be negative, if you + want to manually refill the bucket. If the change puts the bucket + above or below zero, the bufferevents in the group will resume or + suspend reading writing as appropriate. + + Returns 0 on success, -1 on internal error. + + @{ + */ +EVENT2_EXPORT_SYMBOL +int bufferevent_rate_limit_group_decrement_read( + struct bufferevent_rate_limit_group *, ev_ssize_t); +EVENT2_EXPORT_SYMBOL +int bufferevent_rate_limit_group_decrement_write( + struct bufferevent_rate_limit_group *, ev_ssize_t); +/*@}*/ + + +/** + * Inspect the total bytes read/written on a group. + * + * Set the variable pointed to by total_read_out to the total number of bytes + * ever read on grp, and the variable pointed to by total_written_out to the + * total number of bytes ever written on grp. */ +EVENT2_EXPORT_SYMBOL +void bufferevent_rate_limit_group_get_totals( + struct bufferevent_rate_limit_group *grp, + ev_uint64_t *total_read_out, ev_uint64_t *total_written_out); + +/** + * Reset the total bytes read/written on a group. + * + * Reset the number of bytes read or written on grp as given by + * bufferevent_rate_limit_group_reset_totals(). */ +EVENT2_EXPORT_SYMBOL +void +bufferevent_rate_limit_group_reset_totals( + struct bufferevent_rate_limit_group *grp); + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_BUFFEREVENT_H_INCLUDED_ */ diff --git a/platform/src/3rd/os_specific/oe2203/include/event2/bufferevent_compat.h b/platform/src/3rd/os_specific/oe2203/include/event2/bufferevent_compat.h new file mode 100644 index 00000000..65482042 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/event2/bufferevent_compat.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2007-2012 Niels Provos, Nick Mathewson + * Copyright (c) 2000-2007 Niels Provos + * All rights reserved. + * + * 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 EVENT2_BUFFEREVENT_COMPAT_H_INCLUDED_ +#define EVENT2_BUFFEREVENT_COMPAT_H_INCLUDED_ + +#define evbuffercb bufferevent_data_cb +#define everrorcb bufferevent_event_cb + +/** + Create a new bufferevent for an fd. + + This function is deprecated. Use bufferevent_socket_new and + bufferevent_set_callbacks instead. + + Libevent provides an abstraction on top of the regular event callbacks. + This abstraction is called a buffered event. A buffered event provides + input and output buffers that get filled and drained automatically. The + user of a buffered event no longer deals directly with the I/O, but + instead is reading from input and writing to output buffers. + + Once initialized, the bufferevent structure can be used repeatedly with + bufferevent_enable() and bufferevent_disable(). + + When read enabled the bufferevent will try to read from the file descriptor + and call the read callback. The write callback is executed whenever the + output buffer is drained below the write low watermark, which is 0 by + default. + + If multiple bases are in use, bufferevent_base_set() must be called before + enabling the bufferevent for the first time. + + @deprecated This function is deprecated because it uses the current + event base, and as such can be error prone for multithreaded programs. + Use bufferevent_socket_new() instead. + + @param fd the file descriptor from which data is read and written to. + This file descriptor is not allowed to be a pipe(2). + @param readcb callback to invoke when there is data to be read, or NULL if + no callback is desired + @param writecb callback to invoke when the file descriptor is ready for + writing, or NULL if no callback is desired + @param errorcb callback to invoke when there is an error on the file + descriptor + @param cbarg an argument that will be supplied to each of the callbacks + (readcb, writecb, and errorcb) + @return a pointer to a newly allocated bufferevent struct, or NULL if an + error occurred + @see bufferevent_base_set(), bufferevent_free() + */ +struct bufferevent *bufferevent_new(evutil_socket_t fd, + evbuffercb readcb, evbuffercb writecb, everrorcb errorcb, void *cbarg); + + +/** + Set the read and write timeout for a buffered event. + + @param bufev the bufferevent to be modified + @param timeout_read the read timeout + @param timeout_write the write timeout + */ +void bufferevent_settimeout(struct bufferevent *bufev, + int timeout_read, int timeout_write); + +#define EVBUFFER_READ BEV_EVENT_READING +#define EVBUFFER_WRITE BEV_EVENT_WRITING +#define EVBUFFER_EOF BEV_EVENT_EOF +#define EVBUFFER_ERROR BEV_EVENT_ERROR +#define EVBUFFER_TIMEOUT BEV_EVENT_TIMEOUT + +/** macro for getting access to the input buffer of a bufferevent */ +#define EVBUFFER_INPUT(x) bufferevent_get_input(x) +/** macro for getting access to the output buffer of a bufferevent */ +#define EVBUFFER_OUTPUT(x) bufferevent_get_output(x) + +#endif diff --git a/platform/src/3rd/os_specific/oe2203/include/event2/bufferevent_ssl.h b/platform/src/3rd/os_specific/oe2203/include/event2/bufferevent_ssl.h new file mode 100644 index 00000000..bf39b844 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/event2/bufferevent_ssl.h @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson + * + * 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 EVENT2_BUFFEREVENT_SSL_H_INCLUDED_ +#define EVENT2_BUFFEREVENT_SSL_H_INCLUDED_ + +/** @file event2/bufferevent_ssl.h + + OpenSSL support for bufferevents. + */ +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* This is what openssl's SSL objects are underneath. */ +struct ssl_st; + +/** + The state of an SSL object to be used when creating a new + SSL bufferevent. + */ +enum bufferevent_ssl_state { + BUFFEREVENT_SSL_OPEN = 0, + BUFFEREVENT_SSL_CONNECTING = 1, + BUFFEREVENT_SSL_ACCEPTING = 2 +}; + +#if defined(EVENT__HAVE_OPENSSL) || defined(EVENT_IN_DOXYGEN_) +/** + Create a new SSL bufferevent to send its data over another bufferevent. + + @param base An event_base to use to detect reading and writing. It + must also be the base for the underlying bufferevent. + @param underlying A socket to use for this SSL + @param ssl A SSL* object from openssl. + @param state The current state of the SSL connection + @param options One or more bufferevent_options + @return A new bufferevent on success, or NULL on failure +*/ +EVENT2_EXPORT_SYMBOL +struct bufferevent * +bufferevent_openssl_filter_new(struct event_base *base, + struct bufferevent *underlying, + struct ssl_st *ssl, + enum bufferevent_ssl_state state, + int options); + +/** + Create a new SSL bufferevent to send its data over an SSL * on a socket. + + @param base An event_base to use to detect reading and writing + @param fd A socket to use for this SSL + @param ssl A SSL* object from openssl. + @param state The current state of the SSL connection + @param options One or more bufferevent_options + @return A new bufferevent on success, or NULL on failure. +*/ +EVENT2_EXPORT_SYMBOL +struct bufferevent * +bufferevent_openssl_socket_new(struct event_base *base, + evutil_socket_t fd, + struct ssl_st *ssl, + enum bufferevent_ssl_state state, + int options); + +/** Control how to report dirty SSL shutdowns. + + If the peer (or the network, or an attacker) closes the TCP + connection before closing the SSL channel, and the protocol is SSL >= v3, + this is a "dirty" shutdown. If allow_dirty_shutdown is 0 (default), + this is reported as BEV_EVENT_ERROR. + + If instead allow_dirty_shutdown=1, a dirty shutdown is reported as + BEV_EVENT_EOF. + + (Note that if the protocol is < SSLv3, you will always receive + BEV_EVENT_EOF, since SSL 2 and earlier cannot distinguish a secure + connection close from a dirty one. This is one reason (among many) + not to use SSL 2.) +*/ + +EVENT2_EXPORT_SYMBOL +int bufferevent_openssl_get_allow_dirty_shutdown(struct bufferevent *bev); +EVENT2_EXPORT_SYMBOL +void bufferevent_openssl_set_allow_dirty_shutdown(struct bufferevent *bev, + int allow_dirty_shutdown); + +/** Return the underlying openssl SSL * object for an SSL bufferevent. */ +EVENT2_EXPORT_SYMBOL +struct ssl_st * +bufferevent_openssl_get_ssl(struct bufferevent *bufev); + +/** Tells a bufferevent to begin SSL renegotiation. */ +EVENT2_EXPORT_SYMBOL +int bufferevent_ssl_renegotiate(struct bufferevent *bev); + +/** Return the most recent OpenSSL error reported on an SSL bufferevent. */ +EVENT2_EXPORT_SYMBOL +unsigned long bufferevent_get_openssl_error(struct bufferevent *bev); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_BUFFEREVENT_SSL_H_INCLUDED_ */ diff --git a/platform/src/3rd/os_specific/oe2203/include/event2/bufferevent_struct.h b/platform/src/3rd/os_specific/oe2203/include/event2/bufferevent_struct.h new file mode 100644 index 00000000..e84c082c --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/event2/bufferevent_struct.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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 EVENT2_BUFFEREVENT_STRUCT_H_INCLUDED_ +#define EVENT2_BUFFEREVENT_STRUCT_H_INCLUDED_ + +/** @file event2/bufferevent_struct.h + + Data structures for bufferevents. Using these structures may hurt forward + compatibility with later versions of Libevent: be careful! + + @deprecated Use of bufferevent_struct.h is completely deprecated; these + structures are only exposed for backward compatibility with programs + written before Libevent 2.0 that used them. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef EVENT__HAVE_SYS_TYPES_H +#include +#endif +#ifdef EVENT__HAVE_SYS_TIME_H +#include +#endif + +/* For int types. */ +#include +/* For struct event */ +#include + +struct event_watermark { + size_t low; + size_t high; +}; + +/** + Shared implementation of a bufferevent. + + This type is exposed only because it was exposed in previous versions, + and some people's code may rely on manipulating it. Otherwise, you + should really not rely on the layout, size, or contents of this structure: + it is fairly volatile, and WILL change in future versions of the code. +**/ +struct bufferevent { + /** Event base for which this bufferevent was created. */ + struct event_base *ev_base; + /** Pointer to a table of function pointers to set up how this + bufferevent behaves. */ + const struct bufferevent_ops *be_ops; + + /** A read event that triggers when a timeout has happened or a socket + is ready to read data. Only used by some subtypes of + bufferevent. */ + struct event ev_read; + /** A write event that triggers when a timeout has happened or a socket + is ready to write data. Only used by some subtypes of + bufferevent. */ + struct event ev_write; + + /** An input buffer. Only the bufferevent is allowed to add data to + this buffer, though the user is allowed to drain it. */ + struct evbuffer *input; + + /** An input buffer. Only the bufferevent is allowed to drain data + from this buffer, though the user is allowed to add it. */ + struct evbuffer *output; + + struct event_watermark wm_read; + struct event_watermark wm_write; + + bufferevent_data_cb readcb; + bufferevent_data_cb writecb; + /* This should be called 'eventcb', but renaming it would break + * backward compatibility */ + bufferevent_event_cb errorcb; + void *cbarg; + + struct timeval timeout_read; + struct timeval timeout_write; + + /** Events that are currently enabled: currently EV_READ and EV_WRITE + are supported. */ + short enabled; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_BUFFEREVENT_STRUCT_H_INCLUDED_ */ diff --git a/platform/src/3rd/os_specific/oe2203/include/event2/dns.h b/platform/src/3rd/os_specific/oe2203/include/event2/dns.h new file mode 100644 index 00000000..17cd86a2 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/event2/dns.h @@ -0,0 +1,717 @@ +/* + * Copyright (c) 2006-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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. + */ + +/* + * The original DNS code is due to Adam Langley with heavy + * modifications by Nick Mathewson. Adam put his DNS software in the + * public domain. You can find his original copyright below. Please, + * aware that the code as part of Libevent is governed by the 3-clause + * BSD license above. + * + * This software is Public Domain. To view a copy of the public domain dedication, + * visit http://creativecommons.org/licenses/publicdomain/ or send a letter to + * Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. + * + * I ask and expect, but do not require, that all derivative works contain an + * attribution similar to: + * Parts developed by Adam Langley + * + * You may wish to replace the word "Parts" with something else depending on + * the amount of original code. + * + * (Derivative works does not include programs which link against, run or include + * the source verbatim in their source distributions) + */ + +/** @file event2/dns.h + * + * Welcome, gentle reader + * + * Async DNS lookups are really a whole lot harder than they should be, + * mostly stemming from the fact that the libc resolver has never been + * very good at them. Before you use this library you should see if libc + * can do the job for you with the modern async call getaddrinfo_a + * (see http://www.imperialviolet.org/page25.html#e498). Otherwise, + * please continue. + * + * The library keeps track of the state of nameservers and will avoid + * them when they go down. Otherwise it will round robin between them. + * + * Quick start guide: + * #include "evdns.h" + * void callback(int result, char type, int count, int ttl, + * void *addresses, void *arg); + * evdns_resolv_conf_parse(DNS_OPTIONS_ALL, "/etc/resolv.conf"); + * evdns_resolve("www.hostname.com", 0, callback, NULL); + * + * When the lookup is complete the callback function is called. The + * first argument will be one of the DNS_ERR_* defines in evdns.h. + * Hopefully it will be DNS_ERR_NONE, in which case type will be + * DNS_IPv4_A, count will be the number of IP addresses, ttl is the time + * which the data can be cached for (in seconds), addresses will point + * to an array of uint32_t's and arg will be whatever you passed to + * evdns_resolve. + * + * Searching: + * + * In order for this library to be a good replacement for glibc's resolver it + * supports searching. This involves setting a list of default domains, in + * which names will be queried for. The number of dots in the query name + * determines the order in which this list is used. + * + * Searching appears to be a single lookup from the point of view of the API, + * although many DNS queries may be generated from a single call to + * evdns_resolve. Searching can also drastically slow down the resolution + * of names. + * + * To disable searching: + * 1. Never set it up. If you never call evdns_resolv_conf_parse or + * evdns_search_add then no searching will occur. + * + * 2. If you do call evdns_resolv_conf_parse then don't pass + * DNS_OPTION_SEARCH (or DNS_OPTIONS_ALL, which implies it). + * + * 3. When calling evdns_resolve, pass the DNS_QUERY_NO_SEARCH flag. + * + * The order of searches depends on the number of dots in the name. If the + * number is greater than the ndots setting then the names is first tried + * globally. Otherwise each search domain is appended in turn. + * + * The ndots setting can either be set from a resolv.conf, or by calling + * evdns_search_ndots_set. + * + * For example, with ndots set to 1 (the default) and a search domain list of + * ["myhome.net"]: + * Query: www + * Order: www.myhome.net, www. + * + * Query: www.abc + * Order: www.abc., www.abc.myhome.net + * + * Internals: + * + * Requests are kept in two queues. The first is the inflight queue. In + * this queue requests have an allocated transaction id and nameserver. + * They will soon be transmitted if they haven't already been. + * + * The second is the waiting queue. The size of the inflight ring is + * limited and all other requests wait in waiting queue for space. This + * bounds the number of concurrent requests so that we don't flood the + * nameserver. Several algorithms require a full walk of the inflight + * queue and so bounding its size keeps thing going nicely under huge + * (many thousands of requests) loads. + * + * If a nameserver loses too many requests it is considered down and we + * try not to use it. After a while we send a probe to that nameserver + * (a lookup for google.com) and, if it replies, we consider it working + * again. If the nameserver fails a probe we wait longer to try again + * with the next probe. + */ + +#ifndef EVENT2_DNS_H_INCLUDED_ +#define EVENT2_DNS_H_INCLUDED_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* For integer types. */ +#include + +/** Error codes 0-5 are as described in RFC 1035. */ +#define DNS_ERR_NONE 0 +/** The name server was unable to interpret the query */ +#define DNS_ERR_FORMAT 1 +/** The name server was unable to process this query due to a problem with the + * name server */ +#define DNS_ERR_SERVERFAILED 2 +/** The domain name does not exist */ +#define DNS_ERR_NOTEXIST 3 +/** The name server does not support the requested kind of query */ +#define DNS_ERR_NOTIMPL 4 +/** The name server refuses to reform the specified operation for policy + * reasons */ +#define DNS_ERR_REFUSED 5 +/** The reply was truncated or ill-formatted */ +#define DNS_ERR_TRUNCATED 65 +/** An unknown error occurred */ +#define DNS_ERR_UNKNOWN 66 +/** Communication with the server timed out */ +#define DNS_ERR_TIMEOUT 67 +/** The request was canceled because the DNS subsystem was shut down. */ +#define DNS_ERR_SHUTDOWN 68 +/** The request was canceled via a call to evdns_cancel_request */ +#define DNS_ERR_CANCEL 69 +/** There were no answers and no error condition in the DNS packet. + * This can happen when you ask for an address that exists, but a record + * type that doesn't. */ +#define DNS_ERR_NODATA 70 + +#define DNS_IPv4_A 1 +#define DNS_PTR 2 +#define DNS_IPv6_AAAA 3 + +#define DNS_QUERY_NO_SEARCH 1 + +#define DNS_OPTION_SEARCH 1 +#define DNS_OPTION_NAMESERVERS 2 +#define DNS_OPTION_MISC 4 +#define DNS_OPTION_HOSTSFILE 8 +#define DNS_OPTIONS_ALL 15 + +/* Obsolete name for DNS_QUERY_NO_SEARCH */ +#define DNS_NO_SEARCH DNS_QUERY_NO_SEARCH + +/** + * The callback that contains the results from a lookup. + * - result is one of the DNS_ERR_* values (DNS_ERR_NONE for success) + * - type is either DNS_IPv4_A or DNS_PTR or DNS_IPv6_AAAA + * - count contains the number of addresses of form type + * - ttl is the number of seconds the resolution may be cached for. + * - addresses needs to be cast according to type. It will be an array of + * 4-byte sequences for ipv4, or an array of 16-byte sequences for ipv6, + * or a nul-terminated string for PTR. + */ +typedef void (*evdns_callback_type) (int result, char type, int count, int ttl, void *addresses, void *arg); + +struct evdns_base; +struct event_base; + +/** Flag for evdns_base_new: process resolv.conf. */ +#define EVDNS_BASE_INITIALIZE_NAMESERVERS 1 +/** Flag for evdns_base_new: Do not prevent the libevent event loop from + * exiting when we have no active dns requests. */ +#define EVDNS_BASE_DISABLE_WHEN_INACTIVE 0x8000 + +/** + Initialize the asynchronous DNS library. + + This function initializes support for non-blocking name resolution by + calling evdns_resolv_conf_parse() on UNIX and + evdns_config_windows_nameservers() on Windows. + + @param event_base the event base to associate the dns client with + @param flags any of EVDNS_BASE_INITIALIZE_NAMESERVERS| + EVDNS_BASE_DISABLE_WHEN_INACTIVE + @return evdns_base object if successful, or NULL if an error occurred. + @see evdns_base_free() + */ +EVENT2_EXPORT_SYMBOL +struct evdns_base * evdns_base_new(struct event_base *event_base, int initialize_nameservers); + + +/** + Shut down the asynchronous DNS resolver and terminate all active requests. + + If the 'fail_requests' option is enabled, all active requests will return + an empty result with the error flag set to DNS_ERR_SHUTDOWN. Otherwise, + the requests will be silently discarded. + + @param evdns_base the evdns base to free + @param fail_requests if zero, active requests will be aborted; if non-zero, + active requests will return DNS_ERR_SHUTDOWN. + @see evdns_base_new() + */ +EVENT2_EXPORT_SYMBOL +void evdns_base_free(struct evdns_base *base, int fail_requests); + +/** + Remove all hosts entries that have been loaded into the event_base via + evdns_base_load_hosts or via event_base_resolv_conf_parse. + + @param evdns_base the evdns base to remove outdated host addresses from + */ +EVENT2_EXPORT_SYMBOL +void evdns_base_clear_host_addresses(struct evdns_base *base); + +/** + Convert a DNS error code to a string. + + @param err the DNS error code + @return a string containing an explanation of the error code +*/ +EVENT2_EXPORT_SYMBOL +const char *evdns_err_to_string(int err); + + +/** + Add a nameserver. + + The address should be an IPv4 address in network byte order. + The type of address is chosen so that it matches in_addr.s_addr. + + @param base the evdns_base to which to add the name server + @param address an IP address in network byte order + @return 0 if successful, or -1 if an error occurred + @see evdns_base_nameserver_ip_add() + */ +EVENT2_EXPORT_SYMBOL +int evdns_base_nameserver_add(struct evdns_base *base, + unsigned long int address); + +/** + Get the number of configured nameservers. + + This returns the number of configured nameservers (not necessarily the + number of running nameservers). This is useful for double-checking + whether our calls to the various nameserver configuration functions + have been successful. + + @param base the evdns_base to which to apply this operation + @return the number of configured nameservers + @see evdns_base_nameserver_add() + */ +EVENT2_EXPORT_SYMBOL +int evdns_base_count_nameservers(struct evdns_base *base); + +/** + Remove all configured nameservers, and suspend all pending resolves. + + Resolves will not necessarily be re-attempted until evdns_base_resume() is called. + + @param base the evdns_base to which to apply this operation + @return 0 if successful, or -1 if an error occurred + @see evdns_base_resume() + */ +EVENT2_EXPORT_SYMBOL +int evdns_base_clear_nameservers_and_suspend(struct evdns_base *base); + + +/** + Resume normal operation and continue any suspended resolve requests. + + Re-attempt resolves left in limbo after an earlier call to + evdns_base_clear_nameservers_and_suspend(). + + @param base the evdns_base to which to apply this operation + @return 0 if successful, or -1 if an error occurred + @see evdns_base_clear_nameservers_and_suspend() + */ +EVENT2_EXPORT_SYMBOL +int evdns_base_resume(struct evdns_base *base); + +/** + Add a nameserver by string address. + + This function parses a n IPv4 or IPv6 address from a string and adds it as a + nameserver. It supports the following formats: + - [IPv6Address]:port + - [IPv6Address] + - IPv6Address + - IPv4Address:port + - IPv4Address + + If no port is specified, it defaults to 53. + + @param base the evdns_base to which to apply this operation + @return 0 if successful, or -1 if an error occurred + @see evdns_base_nameserver_add() + */ +EVENT2_EXPORT_SYMBOL +int evdns_base_nameserver_ip_add(struct evdns_base *base, + const char *ip_as_string); + +/** + Add a nameserver by sockaddr. + **/ +EVENT2_EXPORT_SYMBOL +int +evdns_base_nameserver_sockaddr_add(struct evdns_base *base, + const struct sockaddr *sa, ev_socklen_t len, unsigned flags); + +struct evdns_request; + +/** + Lookup an A record for a given name. + + @param base the evdns_base to which to apply this operation + @param name a DNS hostname + @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query. + @param callback a callback function to invoke when the request is completed + @param ptr an argument to pass to the callback function + @return an evdns_request object if successful, or NULL if an error occurred. + @see evdns_resolve_ipv6(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6(), evdns_cancel_request() + */ +EVENT2_EXPORT_SYMBOL +struct evdns_request *evdns_base_resolve_ipv4(struct evdns_base *base, const char *name, int flags, evdns_callback_type callback, void *ptr); + +/** + Lookup an AAAA record for a given name. + + @param base the evdns_base to which to apply this operation + @param name a DNS hostname + @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query. + @param callback a callback function to invoke when the request is completed + @param ptr an argument to pass to the callback function + @return an evdns_request object if successful, or NULL if an error occurred. + @see evdns_resolve_ipv4(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6(), evdns_cancel_request() + */ +EVENT2_EXPORT_SYMBOL +struct evdns_request *evdns_base_resolve_ipv6(struct evdns_base *base, const char *name, int flags, evdns_callback_type callback, void *ptr); + +struct in_addr; +struct in6_addr; + +/** + Lookup a PTR record for a given IP address. + + @param base the evdns_base to which to apply this operation + @param in an IPv4 address + @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query. + @param callback a callback function to invoke when the request is completed + @param ptr an argument to pass to the callback function + @return an evdns_request object if successful, or NULL if an error occurred. + @see evdns_resolve_reverse_ipv6(), evdns_cancel_request() + */ +EVENT2_EXPORT_SYMBOL +struct evdns_request *evdns_base_resolve_reverse(struct evdns_base *base, const struct in_addr *in, int flags, evdns_callback_type callback, void *ptr); + + +/** + Lookup a PTR record for a given IPv6 address. + + @param base the evdns_base to which to apply this operation + @param in an IPv6 address + @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query. + @param callback a callback function to invoke when the request is completed + @param ptr an argument to pass to the callback function + @return an evdns_request object if successful, or NULL if an error occurred. + @see evdns_resolve_reverse_ipv6(), evdns_cancel_request() + */ +EVENT2_EXPORT_SYMBOL +struct evdns_request *evdns_base_resolve_reverse_ipv6(struct evdns_base *base, const struct in6_addr *in, int flags, evdns_callback_type callback, void *ptr); + +/** + Cancels a pending DNS resolution request. + + @param base the evdns_base that was used to make the request + @param req the evdns_request that was returned by calling a resolve function + @see evdns_base_resolve_ipv4(), evdns_base_resolve_ipv6, evdns_base_resolve_reverse +*/ +EVENT2_EXPORT_SYMBOL +void evdns_cancel_request(struct evdns_base *base, struct evdns_request *req); + +/** + Set the value of a configuration option. + + The currently available configuration options are: + + ndots, timeout, max-timeouts, max-inflight, attempts, randomize-case, + bind-to, initial-probe-timeout, getaddrinfo-allow-skew. + + In versions before Libevent 2.0.3-alpha, the option name needed to end with + a colon. + + @param base the evdns_base to which to apply this operation + @param option the name of the configuration option to be modified + @param val the value to be set + @return 0 if successful, or -1 if an error occurred + */ +EVENT2_EXPORT_SYMBOL +int evdns_base_set_option(struct evdns_base *base, const char *option, const char *val); + + +/** + Parse a resolv.conf file. + + The 'flags' parameter determines what information is parsed from the + resolv.conf file. See the man page for resolv.conf for the format of this + file. + + The following directives are not parsed from the file: sortlist, rotate, + no-check-names, inet6, debug. + + If this function encounters an error, the possible return values are: 1 = + failed to open file, 2 = failed to stat file, 3 = file too large, 4 = out of + memory, 5 = short read from file, 6 = no nameservers listed in the file + + @param base the evdns_base to which to apply this operation + @param flags any of DNS_OPTION_NAMESERVERS|DNS_OPTION_SEARCH|DNS_OPTION_MISC| + DNS_OPTION_HOSTSFILE|DNS_OPTIONS_ALL + @param filename the path to the resolv.conf file + @return 0 if successful, or various positive error codes if an error + occurred (see above) + @see resolv.conf(3), evdns_config_windows_nameservers() + */ +EVENT2_EXPORT_SYMBOL +int evdns_base_resolv_conf_parse(struct evdns_base *base, int flags, const char *const filename); + +/** + Load an /etc/hosts-style file from 'hosts_fname' into 'base'. + + If hosts_fname is NULL, add minimal entries for localhost, and nothing + else. + + Note that only evdns_getaddrinfo uses the /etc/hosts entries. + + This function does not replace previously loaded hosts entries; to do that, + call evdns_base_clear_host_addresses first. + + Return 0 on success, negative on failure. +*/ +EVENT2_EXPORT_SYMBOL +int evdns_base_load_hosts(struct evdns_base *base, const char *hosts_fname); + +/** + Obtain nameserver information using the Windows API. + + Attempt to configure a set of nameservers based on platform settings on + a win32 host. Preferentially tries to use GetNetworkParams; if that fails, + looks in the registry. + + @return 0 if successful, or -1 if an error occurred + @see evdns_resolv_conf_parse() + */ +#ifdef _WIN32 +EVENT2_EXPORT_SYMBOL +int evdns_base_config_windows_nameservers(struct evdns_base *); +#define EVDNS_BASE_CONFIG_WINDOWS_NAMESERVERS_IMPLEMENTED +#endif + + +/** + Clear the list of search domains. + */ +EVENT2_EXPORT_SYMBOL +void evdns_base_search_clear(struct evdns_base *base); + + +/** + Add a domain to the list of search domains + + @param domain the domain to be added to the search list + */ +EVENT2_EXPORT_SYMBOL +void evdns_base_search_add(struct evdns_base *base, const char *domain); + + +/** + Set the 'ndots' parameter for searches. + + Sets the number of dots which, when found in a name, causes + the first query to be without any search domain. + + @param ndots the new ndots parameter + */ +EVENT2_EXPORT_SYMBOL +void evdns_base_search_ndots_set(struct evdns_base *base, const int ndots); + +/** + A callback that is invoked when a log message is generated + + @param is_warning indicates if the log message is a 'warning' + @param msg the content of the log message + */ +typedef void (*evdns_debug_log_fn_type)(int is_warning, const char *msg); + + +/** + Set the callback function to handle DNS log messages. If this + callback is not set, evdns log messages are handled with the regular + Libevent logging system. + + @param fn the callback to be invoked when a log message is generated + */ +EVENT2_EXPORT_SYMBOL +void evdns_set_log_fn(evdns_debug_log_fn_type fn); + +/** + Set a callback that will be invoked to generate transaction IDs. By + default, we pick transaction IDs based on the current clock time, which + is bad for security. + + @param fn the new callback, or NULL to use the default. + + NOTE: This function has no effect in Libevent 2.0.4-alpha and later, + since Libevent now provides its own secure RNG. + */ +EVENT2_EXPORT_SYMBOL +void evdns_set_transaction_id_fn(ev_uint16_t (*fn)(void)); + +/** + Set a callback used to generate random bytes. By default, we use + the same function as passed to evdns_set_transaction_id_fn to generate + bytes two at a time. If a function is provided here, it's also used + to generate transaction IDs. + + NOTE: This function has no effect in Libevent 2.0.4-alpha and later, + since Libevent now provides its own secure RNG. +*/ +EVENT2_EXPORT_SYMBOL +void evdns_set_random_bytes_fn(void (*fn)(char *, size_t)); + +/* + * Functions used to implement a DNS server. + */ + +struct evdns_server_request; +struct evdns_server_question; + +/** + A callback to implement a DNS server. The callback function receives a DNS + request. It should then optionally add a number of answers to the reply + using the evdns_server_request_add_*_reply functions, before calling either + evdns_server_request_respond to send the reply back, or + evdns_server_request_drop to decline to answer the request. + + @param req A newly received request + @param user_data A pointer that was passed to + evdns_add_server_port_with_base(). + */ +typedef void (*evdns_request_callback_fn_type)(struct evdns_server_request *, void *); +#define EVDNS_ANSWER_SECTION 0 +#define EVDNS_AUTHORITY_SECTION 1 +#define EVDNS_ADDITIONAL_SECTION 2 + +#define EVDNS_TYPE_A 1 +#define EVDNS_TYPE_NS 2 +#define EVDNS_TYPE_CNAME 5 +#define EVDNS_TYPE_SOA 6 +#define EVDNS_TYPE_PTR 12 +#define EVDNS_TYPE_MX 15 +#define EVDNS_TYPE_TXT 16 +#define EVDNS_TYPE_AAAA 28 + +#define EVDNS_QTYPE_AXFR 252 +#define EVDNS_QTYPE_ALL 255 + +#define EVDNS_CLASS_INET 1 + +/* flags that can be set in answers; as part of the err parameter */ +#define EVDNS_FLAGS_AA 0x400 +#define EVDNS_FLAGS_RD 0x080 + +/** Create a new DNS server port. + + @param base The event base to handle events for the server port. + @param socket A UDP socket to accept DNS requests. + @param flags Always 0 for now. + @param callback A function to invoke whenever we get a DNS request + on the socket. + @param user_data Data to pass to the callback. + @return an evdns_server_port structure for this server port. + */ +EVENT2_EXPORT_SYMBOL +struct evdns_server_port *evdns_add_server_port_with_base(struct event_base *base, evutil_socket_t socket, int flags, evdns_request_callback_fn_type callback, void *user_data); +/** Close down a DNS server port, and free associated structures. */ +EVENT2_EXPORT_SYMBOL +void evdns_close_server_port(struct evdns_server_port *port); + +/** Sets some flags in a reply we're building. + Allows setting of the AA or RD flags + */ +EVENT2_EXPORT_SYMBOL +void evdns_server_request_set_flags(struct evdns_server_request *req, int flags); + +/* Functions to add an answer to an in-progress DNS reply. + */ +EVENT2_EXPORT_SYMBOL +int evdns_server_request_add_reply(struct evdns_server_request *req, int section, const char *name, int type, int dns_class, int ttl, int datalen, int is_name, const char *data); +EVENT2_EXPORT_SYMBOL +int evdns_server_request_add_a_reply(struct evdns_server_request *req, const char *name, int n, const void *addrs, int ttl); +EVENT2_EXPORT_SYMBOL +int evdns_server_request_add_aaaa_reply(struct evdns_server_request *req, const char *name, int n, const void *addrs, int ttl); +EVENT2_EXPORT_SYMBOL +int evdns_server_request_add_ptr_reply(struct evdns_server_request *req, struct in_addr *in, const char *inaddr_name, const char *hostname, int ttl); +EVENT2_EXPORT_SYMBOL +int evdns_server_request_add_cname_reply(struct evdns_server_request *req, const char *name, const char *cname, int ttl); + +/** + Send back a response to a DNS request, and free the request structure. +*/ +EVENT2_EXPORT_SYMBOL +int evdns_server_request_respond(struct evdns_server_request *req, int err); +/** + Free a DNS request without sending back a reply. +*/ +EVENT2_EXPORT_SYMBOL +int evdns_server_request_drop(struct evdns_server_request *req); +struct sockaddr; +/** + Get the address that made a DNS request. + */ +EVENT2_EXPORT_SYMBOL +int evdns_server_request_get_requesting_addr(struct evdns_server_request *req, struct sockaddr *sa, int addr_len); + +/** Callback for evdns_getaddrinfo. */ +typedef void (*evdns_getaddrinfo_cb)(int result, struct evutil_addrinfo *res, void *arg); + +struct evdns_base; +struct evdns_getaddrinfo_request; +/** Make a non-blocking getaddrinfo request using the dns_base in 'dns_base'. + * + * If we can answer the request immediately (with an error or not!), then we + * invoke cb immediately and return NULL. Otherwise we return + * an evdns_getaddrinfo_request and invoke cb later. + * + * When the callback is invoked, we pass as its first argument the error code + * that getaddrinfo would return (or 0 for no error). As its second argument, + * we pass the evutil_addrinfo structures we found (or NULL on error). We + * pass 'arg' as the third argument. + * + * Limitations: + * + * - The AI_V4MAPPED and AI_ALL flags are not currently implemented. + * - For ai_socktype, we only handle SOCKTYPE_STREAM, SOCKTYPE_UDP, and 0. + * - For ai_protocol, we only handle IPPROTO_TCP, IPPROTO_UDP, and 0. + */ +EVENT2_EXPORT_SYMBOL +struct evdns_getaddrinfo_request *evdns_getaddrinfo( + struct evdns_base *dns_base, + const char *nodename, const char *servname, + const struct evutil_addrinfo *hints_in, + evdns_getaddrinfo_cb cb, void *arg); + +/* Cancel an in-progress evdns_getaddrinfo. This MUST NOT be called after the + * getaddrinfo's callback has been invoked. The resolves will be canceled, + * and the callback will be invoked with the error EVUTIL_EAI_CANCEL. */ +EVENT2_EXPORT_SYMBOL +void evdns_getaddrinfo_cancel(struct evdns_getaddrinfo_request *req); + +/** + Retrieve the address of the 'idx'th configured nameserver. + + @param base The evdns_base to examine. + @param idx The index of the nameserver to get the address of. + @param sa A location to receive the server's address. + @param len The number of bytes available at sa. + + @return the number of bytes written into sa on success. On failure, returns + -1 if idx is greater than the number of configured nameservers, or a + value greater than 'len' if len was not high enough. + */ +EVENT2_EXPORT_SYMBOL +int evdns_base_get_nameserver_addr(struct evdns_base *base, int idx, + struct sockaddr *sa, ev_socklen_t len); + +#ifdef __cplusplus +} +#endif + +#endif /* !EVENT2_DNS_H_INCLUDED_ */ diff --git a/platform/src/3rd/os_specific/oe2203/include/event2/dns_compat.h b/platform/src/3rd/os_specific/oe2203/include/event2/dns_compat.h new file mode 100644 index 00000000..965fd654 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/event2/dns_compat.h @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2006-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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 EVENT2_DNS_COMPAT_H_INCLUDED_ +#define EVENT2_DNS_COMPAT_H_INCLUDED_ + +/** @file event2/dns_compat.h + + Potentially non-threadsafe versions of the functions in dns.h: provided + only for backwards compatibility. + + + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef EVENT__HAVE_SYS_TYPES_H +#include +#endif +#ifdef EVENT__HAVE_SYS_TIME_H +#include +#endif + +/* For int types. */ +#include + +/** + Initialize the asynchronous DNS library. + + This function initializes support for non-blocking name resolution by + calling evdns_resolv_conf_parse() on UNIX and + evdns_config_windows_nameservers() on Windows. + + @deprecated This function is deprecated because it always uses the current + event base, and is easily confused by multiple calls to event_init(), and + so is not safe for multithreaded use. Additionally, it allocates a global + structure that only one thread can use. The replacement is + evdns_base_new(). + + @return 0 if successful, or -1 if an error occurred + @see evdns_shutdown() + */ +int evdns_init(void); + +struct evdns_base; +/** + Return the global evdns_base created by event_init() and used by the other + deprecated functions. + + @deprecated This function is deprecated because use of the global + evdns_base is error-prone. + */ +struct evdns_base *evdns_get_global_base(void); + +/** + Shut down the asynchronous DNS resolver and terminate all active requests. + + If the 'fail_requests' option is enabled, all active requests will return + an empty result with the error flag set to DNS_ERR_SHUTDOWN. Otherwise, + the requests will be silently discarded. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_shutdown(). + + @param fail_requests if zero, active requests will be aborted; if non-zero, + active requests will return DNS_ERR_SHUTDOWN. + @see evdns_init() + */ +void evdns_shutdown(int fail_requests); + +/** + Add a nameserver. + + The address should be an IPv4 address in network byte order. + The type of address is chosen so that it matches in_addr.s_addr. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_nameserver_add(). + + @param address an IP address in network byte order + @return 0 if successful, or -1 if an error occurred + @see evdns_nameserver_ip_add() + */ +int evdns_nameserver_add(unsigned long int address); + +/** + Get the number of configured nameservers. + + This returns the number of configured nameservers (not necessarily the + number of running nameservers). This is useful for double-checking + whether our calls to the various nameserver configuration functions + have been successful. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_count_nameservers(). + + @return the number of configured nameservers + @see evdns_nameserver_add() + */ +int evdns_count_nameservers(void); + +/** + Remove all configured nameservers, and suspend all pending resolves. + + Resolves will not necessarily be re-attempted until evdns_resume() is called. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_clear_nameservers_and_suspend(). + + @return 0 if successful, or -1 if an error occurred + @see evdns_resume() + */ +int evdns_clear_nameservers_and_suspend(void); + +/** + Resume normal operation and continue any suspended resolve requests. + + Re-attempt resolves left in limbo after an earlier call to + evdns_clear_nameservers_and_suspend(). + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_resume(). + + @return 0 if successful, or -1 if an error occurred + @see evdns_clear_nameservers_and_suspend() + */ +int evdns_resume(void); + +/** + Add a nameserver. + + This wraps the evdns_nameserver_add() function by parsing a string as an IP + address and adds it as a nameserver. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_nameserver_ip_add(). + + @return 0 if successful, or -1 if an error occurred + @see evdns_nameserver_add() + */ +int evdns_nameserver_ip_add(const char *ip_as_string); + +/** + Lookup an A record for a given name. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_resolve_ipv4(). + + @param name a DNS hostname + @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query. + @param callback a callback function to invoke when the request is completed + @param ptr an argument to pass to the callback function + @return 0 if successful, or -1 if an error occurred + @see evdns_resolve_ipv6(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6() + */ +int evdns_resolve_ipv4(const char *name, int flags, evdns_callback_type callback, void *ptr); + +/** + Lookup an AAAA record for a given name. + + @param name a DNS hostname + @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query. + @param callback a callback function to invoke when the request is completed + @param ptr an argument to pass to the callback function + @return 0 if successful, or -1 if an error occurred + @see evdns_resolve_ipv4(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6() + */ +int evdns_resolve_ipv6(const char *name, int flags, evdns_callback_type callback, void *ptr); + +struct in_addr; +struct in6_addr; + +/** + Lookup a PTR record for a given IP address. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_resolve_reverse(). + + @param in an IPv4 address + @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query. + @param callback a callback function to invoke when the request is completed + @param ptr an argument to pass to the callback function + @return 0 if successful, or -1 if an error occurred + @see evdns_resolve_reverse_ipv6() + */ +int evdns_resolve_reverse(const struct in_addr *in, int flags, evdns_callback_type callback, void *ptr); + +/** + Lookup a PTR record for a given IPv6 address. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_resolve_reverse_ipv6(). + + @param in an IPv6 address + @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query. + @param callback a callback function to invoke when the request is completed + @param ptr an argument to pass to the callback function + @return 0 if successful, or -1 if an error occurred + @see evdns_resolve_reverse_ipv6() + */ +int evdns_resolve_reverse_ipv6(const struct in6_addr *in, int flags, evdns_callback_type callback, void *ptr); + +/** + Set the value of a configuration option. + + The currently available configuration options are: + + ndots, timeout, max-timeouts, max-inflight, and attempts + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_set_option(). + + @param option the name of the configuration option to be modified + @param val the value to be set + @param flags Ignored. + @return 0 if successful, or -1 if an error occurred + */ +int evdns_set_option(const char *option, const char *val, int flags); + +/** + Parse a resolv.conf file. + + The 'flags' parameter determines what information is parsed from the + resolv.conf file. See the man page for resolv.conf for the format of this + file. + + The following directives are not parsed from the file: sortlist, rotate, + no-check-names, inet6, debug. + + If this function encounters an error, the possible return values are: 1 = + failed to open file, 2 = failed to stat file, 3 = file too large, 4 = out of + memory, 5 = short read from file, 6 = no nameservers listed in the file + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_resolv_conf_parse(). + + @param flags any of DNS_OPTION_NAMESERVERS|DNS_OPTION_SEARCH|DNS_OPTION_MISC| + DNS_OPTIONS_ALL + @param filename the path to the resolv.conf file + @return 0 if successful, or various positive error codes if an error + occurred (see above) + @see resolv.conf(3), evdns_config_windows_nameservers() + */ +int evdns_resolv_conf_parse(int flags, const char *const filename); + +/** + Clear the list of search domains. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_search_clear(). + */ +void evdns_search_clear(void); + +/** + Add a domain to the list of search domains + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_search_add(). + + @param domain the domain to be added to the search list + */ +void evdns_search_add(const char *domain); + +/** + Set the 'ndots' parameter for searches. + + Sets the number of dots which, when found in a name, causes + the first query to be without any search domain. + + @deprecated This function is deprecated because it does not allow the + caller to specify which evdns_base it applies to. The recommended + function is evdns_base_search_ndots_set(). + + @param ndots the new ndots parameter + */ +void evdns_search_ndots_set(const int ndots); + +/** + As evdns_server_new_with_base. + + @deprecated This function is deprecated because it does not allow the + caller to specify which even_base it uses. The recommended + function is evdns_add_server_port_with_base(). + +*/ +struct evdns_server_port *evdns_add_server_port(evutil_socket_t socket, int flags, evdns_request_callback_fn_type callback, void *user_data); + +#ifdef _WIN32 +int evdns_config_windows_nameservers(void); +#define EVDNS_CONFIG_WINDOWS_NAMESERVERS_IMPLEMENTED +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_EVENT_COMPAT_H_INCLUDED_ */ diff --git a/platform/src/3rd/os_specific/oe2203/include/event2/dns_struct.h b/platform/src/3rd/os_specific/oe2203/include/event2/dns_struct.h new file mode 100644 index 00000000..593a8a70 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/event2/dns_struct.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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 EVENT2_DNS_STRUCT_H_INCLUDED_ +#define EVENT2_DNS_STRUCT_H_INCLUDED_ + +/** @file event2/dns_struct.h + + Data structures for dns. Using these structures may hurt forward + compatibility with later versions of Libevent: be careful! + + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef EVENT__HAVE_SYS_TYPES_H +#include +#endif +#ifdef EVENT__HAVE_SYS_TIME_H +#include +#endif + +/* For int types. */ +#include + +/* + * Structures used to implement a DNS server. + */ + +struct evdns_server_request { + int flags; + int nquestions; + struct evdns_server_question **questions; +}; +struct evdns_server_question { + int type; +#ifdef __cplusplus + int dns_question_class; +#else + /* You should refer to this field as "dns_question_class". The + * name "class" works in C for backward compatibility, and will be + * removed in a future version. (1.5 or later). */ + int class; +#define dns_question_class class +#endif + char name[1]; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_DNS_STRUCT_H_INCLUDED_ */ + diff --git a/platform/src/3rd/os_specific/oe2203/include/event2/event-config.h b/platform/src/3rd/os_specific/oe2203/include/event2/event-config.h new file mode 100644 index 00000000..457f98ea --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/event2/event-config.h @@ -0,0 +1,545 @@ +/* event2/event-config.h + * + * This file was generated by autoconf when libevent was built, and post- + * processed by Libevent so that its macros would have a uniform prefix. + * + * DO NOT EDIT THIS FILE. + * + * Do not rely on macros in this file existing in later versions. + */ + +#ifndef EVENT2_EVENT_CONFIG_H_INCLUDED_ +#define EVENT2_EVENT_CONFIG_H_INCLUDED_ + +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if libevent should build without support for a debug mode */ +/* #undef EVENT__DISABLE_DEBUG_MODE */ + +/* Define if libevent should not allow replacing the mm functions */ +/* #undef EVENT__DISABLE_MM_REPLACEMENT */ + +/* Define if libevent should not be compiled with thread support */ +/* #undef EVENT__DISABLE_THREAD_SUPPORT */ + +/* Define to 1 if you have the `accept4' function. */ +#define EVENT__HAVE_ACCEPT4 1 + +/* Define to 1 if you have the `arc4random' function. */ +/* #undef EVENT__HAVE_ARC4RANDOM */ + +/* Define to 1 if you have the `arc4random_buf' function. */ +/* #undef EVENT__HAVE_ARC4RANDOM_BUF */ + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the `clock_gettime' function. */ +#define EVENT__HAVE_CLOCK_GETTIME 1 + +/* Define to 1 if you have the declaration of `CTL_KERN', and to 0 if you + don't. */ +#define EVENT__HAVE_DECL_CTL_KERN 1 + +/* Define to 1 if you have the declaration of `KERN_ARND', and to 0 if you + don't. */ +#define EVENT__HAVE_DECL_KERN_ARND 0 + +/* Define to 1 if you have the declaration of `KERN_RANDOM', and to 0 if you + don't. */ +#define EVENT__HAVE_DECL_KERN_RANDOM 1 + +/* Define to 1 if you have the declaration of `RANDOM_UUID', and to 0 if you + don't. */ +#define EVENT__HAVE_DECL_RANDOM_UUID 1 + +/* Define if /dev/poll is available */ +/* #undef EVENT__HAVE_DEVPOLL */ + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_DLFCN_H 1 + +/* Define if your system supports the epoll system calls */ +#define EVENT__HAVE_EPOLL 1 + +/* Define to 1 if you have the `epoll_create1' function. */ +#define EVENT__HAVE_EPOLL_CREATE1 1 + +/* Define to 1 if you have the `epoll_ctl' function. */ +#define EVENT__HAVE_EPOLL_CTL 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_ERRNO_H 1 + +/* Define to 1 if you have ERR_remove_thread_stat(). */ +#define EVENT__HAVE_ERR_REMOVE_THREAD_STATE 1 + +/* Define to 1 if you have the `eventfd' function. */ +#define EVENT__HAVE_EVENTFD 1 + +/* Define if your system supports event ports */ +/* #undef EVENT__HAVE_EVENT_PORTS */ + +/* Define to 1 if you have the `fcntl' function. */ +#define EVENT__HAVE_FCNTL 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_FCNTL_H 1 + +/* Define to 1 if the system has the type `fd_mask'. */ +#define EVENT__HAVE_FD_MASK 1 + +/* Do we have getaddrinfo()? */ +#define EVENT__HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the `getegid' function. */ +#define EVENT__HAVE_GETEGID 1 + +/* Define to 1 if you have the `geteuid' function. */ +#define EVENT__HAVE_GETEUID 1 + +/* Define this if you have any gethostbyname_r() */ +/* #undef EVENT__HAVE_GETHOSTBYNAME_R */ + +/* Define this if gethostbyname_r takes 3 arguments */ +/* #undef EVENT__HAVE_GETHOSTBYNAME_R_3_ARG */ + +/* Define this if gethostbyname_r takes 5 arguments */ +/* #undef EVENT__HAVE_GETHOSTBYNAME_R_5_ARG */ + +/* Define this if gethostbyname_r takes 6 arguments */ +/* #undef EVENT__HAVE_GETHOSTBYNAME_R_6_ARG */ + +/* Define to 1 if you have the `getifaddrs' function. */ +#define EVENT__HAVE_GETIFADDRS 1 + +/* Define to 1 if you have the `getnameinfo' function. */ +#define EVENT__HAVE_GETNAMEINFO 1 + +/* Define to 1 if you have the `getprotobynumber' function. */ +#define EVENT__HAVE_GETPROTOBYNUMBER 1 + +/* Define to 1 if you have the `getservbyname' function. */ +#define EVENT__HAVE_GETSERVBYNAME 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#define EVENT__HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_IFADDRS_H 1 + +/* Define to 1 if you have the `inet_ntop' function. */ +#define EVENT__HAVE_INET_NTOP 1 + +/* Define to 1 if you have the `inet_pton' function. */ +#define EVENT__HAVE_INET_PTON 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `issetugid' function. */ +/* #undef EVENT__HAVE_ISSETUGID */ + +/* Define to 1 if you have the `kqueue' function. */ +/* #undef EVENT__HAVE_KQUEUE */ + +/* Define if the system has zlib */ +#define EVENT__HAVE_LIBZ 1 + +/* Define to 1 if you have the `mach_absolute_time' function. */ +/* #undef EVENT__HAVE_MACH_ABSOLUTE_TIME */ + +/* Define to 1 if you have the header file. */ +/* #undef EVENT__HAVE_MACH_MACH_TIME_H */ + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mmap' function. */ +#define EVENT__HAVE_MMAP 1 + +/* Define to 1 if you have the `nanosleep' function. */ +#define EVENT__HAVE_NANOSLEEP 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef EVENT__HAVE_NETINET_IN6_H */ + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_NETINET_TCP_H 1 + +/* Define if the system has openssl */ +#define EVENT__HAVE_OPENSSL 1 + +/* Define to 1 if you have the `pipe' function. */ +#define EVENT__HAVE_PIPE 1 + +/* Define to 1 if you have the `pipe2' function. */ +#define EVENT__HAVE_PIPE2 1 + +/* Define to 1 if you have the `poll' function. */ +#define EVENT__HAVE_POLL 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_POLL_H 1 + +/* Define to 1 if you have the `port_create' function. */ +/* #undef EVENT__HAVE_PORT_CREATE */ + +/* Define to 1 if you have the header file. */ +/* #undef EVENT__HAVE_PORT_H */ + +/* Define if you have POSIX threads libraries and header files. */ +/* #undef EVENT__HAVE_PTHREAD */ + +/* Define if we have pthreads on this system */ +#define EVENT__HAVE_PTHREADS 1 + +/* Define to 1 if you have the `putenv' function. */ +#define EVENT__HAVE_PUTENV 1 + +/* Define to 1 if the system has the type `sa_family_t'. */ +#define EVENT__HAVE_SA_FAMILY_T 1 + +/* Define to 1 if you have the `select' function. */ +#define EVENT__HAVE_SELECT 1 + +/* Define to 1 if you have the `sendfile' function. */ +#define EVENT__HAVE_SENDFILE 1 + +/* Define to 1 if you have the `setenv' function. */ +#define EVENT__HAVE_SETENV 1 + +/* Define if F_SETFD is defined in */ +#define EVENT__HAVE_SETFD 1 + +/* Define to 1 if you have the `setrlimit' function. */ +#define EVENT__HAVE_SETRLIMIT 1 + +/* Define to 1 if you have the `sigaction' function. */ +#define EVENT__HAVE_SIGACTION 1 + +/* Define to 1 if you have the `signal' function. */ +#define EVENT__HAVE_SIGNAL 1 + +/* Define to 1 if you have the `splice' function. */ +#define EVENT__HAVE_SPLICE 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_STDARG_H 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_STDDEF_H 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_STRING_H 1 + +/* Define to 1 if you have the `strlcpy' function. */ +/* #undef EVENT__HAVE_STRLCPY */ + +/* Define to 1 if you have the `strsep' function. */ +#define EVENT__HAVE_STRSEP 1 + +/* Define to 1 if you have the `strtok_r' function. */ +#define EVENT__HAVE_STRTOK_R 1 + +/* Define to 1 if you have the `strtoll' function. */ +#define EVENT__HAVE_STRTOLL 1 + +/* Define to 1 if the system has the type `struct addrinfo'. */ +#define EVENT__HAVE_STRUCT_ADDRINFO 1 + +/* Define to 1 if the system has the type `struct in6_addr'. */ +#define EVENT__HAVE_STRUCT_IN6_ADDR 1 + +/* Define to 1 if `s6_addr16' is a member of `struct in6_addr'. */ +#define EVENT__HAVE_STRUCT_IN6_ADDR_S6_ADDR16 1 + +/* Define to 1 if `s6_addr32' is a member of `struct in6_addr'. */ +#define EVENT__HAVE_STRUCT_IN6_ADDR_S6_ADDR32 1 + +/* Define to 1 if the system has the type `struct sockaddr_in6'. */ +#define EVENT__HAVE_STRUCT_SOCKADDR_IN6 1 + +/* Define to 1 if `sin6_len' is a member of `struct sockaddr_in6'. */ +/* #undef EVENT__HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN */ + +/* Define to 1 if `sin_len' is a member of `struct sockaddr_in'. */ +/* #undef EVENT__HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ + +/* Define to 1 if the system has the type `struct sockaddr_storage'. */ +#define EVENT__HAVE_STRUCT_SOCKADDR_STORAGE 1 + +/* Define to 1 if `ss_family' is a member of `struct sockaddr_storage'. */ +#define EVENT__HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY 1 + +/* Define to 1 if `__ss_family' is a member of `struct sockaddr_storage'. */ +/* #undef EVENT__HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY */ + +/* Define to 1 if the system has the type `struct so_linger'. */ +/* #undef EVENT__HAVE_STRUCT_SO_LINGER */ + +/* Define to 1 if you have the `sysctl' function. */ +#define EVENT__HAVE_SYSCTL 1 + +/* Define to 1 if you have the header file. */ +/* #undef EVENT__HAVE_SYS_DEVPOLL_H */ + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_SYS_EPOLL_H 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_SYS_EVENTFD_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef EVENT__HAVE_SYS_EVENT_H */ + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_SYS_MMAN_H 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_SYS_QUEUE_H 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_SYS_SENDFILE_H 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_SYS_SYSCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_SYS_TIMERFD_H 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_SYS_UIO_H 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_SYS_WAIT_H 1 + +/* Define if TAILQ_FOREACH is defined in */ +#define EVENT__HAVE_TAILQFOREACH 1 + +/* Define if timeradd is defined in */ +#define EVENT__HAVE_TIMERADD 1 + +/* Define if timerclear is defined in */ +#define EVENT__HAVE_TIMERCLEAR 1 + +/* Define if timercmp is defined in */ +#define EVENT__HAVE_TIMERCMP 1 + +/* Define to 1 if you have the `timerfd_create' function. */ +#define EVENT__HAVE_TIMERFD_CREATE 1 + +/* Define if timerisset is defined in */ +#define EVENT__HAVE_TIMERISSET 1 + +/* Define to 1 if the system has the type `uint16_t'. */ +#define EVENT__HAVE_UINT16_T 1 + +/* Define to 1 if the system has the type `uint32_t'. */ +#define EVENT__HAVE_UINT32_T 1 + +/* Define to 1 if the system has the type `uint64_t'. */ +#define EVENT__HAVE_UINT64_T 1 + +/* Define to 1 if the system has the type `uint8_t'. */ +#define EVENT__HAVE_UINT8_T 1 + +/* Define to 1 if the system has the type `uintptr_t'. */ +#define EVENT__HAVE_UINTPTR_T 1 + +/* Define to 1 if you have the `umask' function. */ +#define EVENT__HAVE_UMASK 1 + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `unsetenv' function. */ +#define EVENT__HAVE_UNSETENV 1 + +/* Define to 1 if you have the `usleep' function. */ +#define EVENT__HAVE_USLEEP 1 + +/* Define to 1 if you have the `vasprintf' function. */ +#define EVENT__HAVE_VASPRINTF 1 + +/* Define if waitpid() supports WNOWAIT */ +/* #undef EVENT__HAVE_WAITPID_WITH_WNOWAIT */ + +/* Define if kqueue works correctly with pipes */ +/* #undef EVENT__HAVE_WORKING_KQUEUE */ + +/* Define to 1 if you have the header file. */ +#define EVENT__HAVE_ZLIB_H 1 + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#define EVENT__LT_OBJDIR ".libs/" + +/* Numeric representation of the version */ +#define EVENT__NUMERIC_VERSION 0x02010800 + +/* Name of package */ +#define EVENT__PACKAGE "libevent" + +/* Define to the address where bug reports for this package should be sent. */ +#define EVENT__PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define EVENT__PACKAGE_NAME "libevent" + +/* Define to the full name and version of this package. */ +#define EVENT__PACKAGE_STRING "libevent 2.1.8-stable" + +/* Define to the one symbol short name of this package. */ +#define EVENT__PACKAGE_TARNAME "libevent" + +/* Define to the home page for this package. */ +#define EVENT__PACKAGE_URL "" + +/* Define to the version of this package. */ +#define EVENT__PACKAGE_VERSION "2.1.8-stable" + +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +/* #undef EVENT__PTHREAD_CREATE_JOINABLE */ + +/* The size of `int', as computed by sizeof. */ +#define EVENT__SIZEOF_INT 4 + +/* The size of `long', as computed by sizeof. */ +#define EVENT__SIZEOF_LONG 8 + +/* The size of `long long', as computed by sizeof. */ +#define EVENT__SIZEOF_LONG_LONG 8 + +/* The size of `off_t', as computed by sizeof. */ +#define EVENT__SIZEOF_OFF_T 8 + +/* The size of `pthread_t', as computed by sizeof. */ +#define EVENT__SIZEOF_PTHREAD_T 8 + +/* The size of `short', as computed by sizeof. */ +#define EVENT__SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#define EVENT__SIZEOF_SIZE_T 8 + +/* The size of `void *', as computed by sizeof. */ +#define EVENT__SIZEOF_VOID_P 8 + +/* Define to 1 if you have the ANSI C header files. */ +#define EVENT__STDC_HEADERS 1 + +/* Define to 1 if you can safely include both and . */ +#define EVENT__TIME_WITH_SYS_TIME 1 + +/* Enable extensions on AIX 3, Interix. */ +#ifndef EVENT___ALL_SOURCE +# define EVENT___ALL_SOURCE 1 +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef EVENT___GNU_SOURCE +# define EVENT___GNU_SOURCE 1 +#endif +/* Enable threading extensions on Solaris. */ +#ifndef EVENT___POSIX_PTHREAD_SEMANTICS +# define EVENT___POSIX_PTHREAD_SEMANTICS 1 +#endif +/* Enable extensions on HP NonStop. */ +#ifndef EVENT___TANDEM_SOURCE +# define EVENT___TANDEM_SOURCE 1 +#endif +/* Enable general extensions on Solaris. */ +#ifndef EVENT____EXTENSIONS__ +# define EVENT____EXTENSIONS__ 1 +#endif + + +/* Version number of package */ +#define EVENT__VERSION "2.1.8-stable" + +/* Enable large inode numbers on Mac OS X 10.5. */ +#ifndef EVENT___DARWIN_USE_64_BIT_INODE +# define EVENT___DARWIN_USE_64_BIT_INODE 1 +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef EVENT___FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef EVENT___LARGE_FILES */ + +/* Define to 1 if on MINIX. */ +/* #undef EVENT___MINIX */ + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +/* #undef EVENT___POSIX_1_SOURCE */ + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +/* #undef EVENT___POSIX_SOURCE */ + +/* Define to appropriate substitue if compiler doesnt have __func__ */ +/* #undef EVENT____func__ */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef EVENT__const */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef EVENT____cplusplus +/* #undef EVENT__inline */ +#endif + +/* Define to `int' if does not define. */ +/* #undef EVENT__pid_t */ + +/* Define to `unsigned int' if does not define. */ +/* #undef EVENT__size_t */ + +/* Define to unsigned int if you dont have it */ +/* #undef EVENT__socklen_t */ + +/* Define to `int' if does not define. */ +/* #undef EVENT__ssize_t */ + +#endif /* event2/event-config.h */ diff --git a/platform/src/3rd/os_specific/oe2203/include/event2/event.h b/platform/src/3rd/os_specific/oe2203/include/event2/event.h new file mode 100644 index 00000000..6e0a4f04 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/event2/event.h @@ -0,0 +1,1675 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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 EVENT2_EVENT_H_INCLUDED_ +#define EVENT2_EVENT_H_INCLUDED_ + +/** + @mainpage + + @section intro Introduction + + Libevent is an event notification library for developing scalable network + servers. The Libevent API provides a mechanism to execute a callback + function when a specific event occurs on a file descriptor or after a + timeout has been reached. Furthermore, Libevent also support callbacks due + to signals or regular timeouts. + + Libevent is meant to replace the event loop found in event driven network + servers. An application just needs to call event_base_dispatch() and then add or + remove events dynamically without having to change the event loop. + + + Currently, Libevent supports /dev/poll, kqueue(2), select(2), poll(2), + epoll(4), and evports. The internal event mechanism is completely + independent of the exposed event API, and a simple update of Libevent can + provide new functionality without having to redesign the applications. As a + result, Libevent allows for portable application development and provides + the most scalable event notification mechanism available on an operating + system. Libevent can also be used for multithreaded programs. Libevent + should compile on Linux, *BSD, Mac OS X, Solaris and, Windows. + + @section usage Standard usage + + Every program that uses Libevent must include the + header, and pass the -levent flag to the linker. (You can instead link + -levent_core if you only want the main event and buffered IO-based code, + and don't want to link any protocol code.) + + @section setup Library setup + + Before you call any other Libevent functions, you need to set up the + library. If you're going to use Libevent from multiple threads in a + multithreaded application, you need to initialize thread support -- + typically by using evthread_use_pthreads() or + evthread_use_windows_threads(). See for more + information. + + This is also the point where you can replace Libevent's memory + management functions with event_set_mem_functions, and enable debug mode + with event_enable_debug_mode(). + + @section base Creating an event base + + Next, you need to create an event_base structure, using event_base_new() + or event_base_new_with_config(). The event_base is responsible for + keeping track of which events are "pending" (that is to say, being + watched to see if they become active) and which events are "active". + Every event is associated with a single event_base. + + @section event Event notification + + For each file descriptor that you wish to monitor, you must create an + event structure with event_new(). (You may also declare an event + structure and call event_assign() to initialize the members of the + structure.) To enable notification, you add the structure to the list + of monitored events by calling event_add(). The event structure must + remain allocated as long as it is active, so it should generally be + allocated on the heap. + + @section loop Dispatching events. + + Finally, you call event_base_dispatch() to loop and dispatch events. + You can also use event_base_loop() for more fine-grained control. + + Currently, only one thread can be dispatching a given event_base at a + time. If you want to run events in multiple threads at once, you can + either have a single event_base whose events add work to a work queue, + or you can create multiple event_base objects. + + @section bufferevent I/O Buffers + + Libevent provides a buffered I/O abstraction on top of the regular event + callbacks. This abstraction is called a bufferevent. A bufferevent + provides input and output buffers that get filled and drained + automatically. The user of a buffered event no longer deals directly + with the I/O, but instead is reading from input and writing to output + buffers. + + Once initialized via bufferevent_socket_new(), the bufferevent structure + can be used repeatedly with bufferevent_enable() and + bufferevent_disable(). Instead of reading and writing directly to a + socket, you would call bufferevent_read() and bufferevent_write(). + + When read enabled the bufferevent will try to read from the file descriptor + and call the read callback. The write callback is executed whenever the + output buffer is drained below the write low watermark, which is 0 by + default. + + See for more information. + + @section timers Timers + + Libevent can also be used to create timers that invoke a callback after a + certain amount of time has expired. The evtimer_new() macro returns + an event struct to use as a timer. To activate the timer, call + evtimer_add(). Timers can be deactivated by calling evtimer_del(). + (These macros are thin wrappers around event_new(), event_add(), + and event_del(); you can also use those instead.) + + @section evdns Asynchronous DNS resolution + + Libevent provides an asynchronous DNS resolver that should be used instead + of the standard DNS resolver functions. See the + functions for more detail. + + @section evhttp Event-driven HTTP servers + + Libevent provides a very simple event-driven HTTP server that can be + embedded in your program and used to service HTTP requests. + + To use this capability, you need to include the header in your + program. See that header for more information. + + @section evrpc A framework for RPC servers and clients + + Libevent provides a framework for creating RPC servers and clients. It + takes care of marshaling and unmarshaling all data structures. + + @section api API Reference + + To browse the complete documentation of the libevent API, click on any of + the following links. + + event2/event.h + The primary libevent header + + event2/thread.h + Functions for use by multithreaded programs + + event2/buffer.h and event2/bufferevent.h + Buffer management for network reading and writing + + event2/util.h + Utility functions for portable nonblocking network code + + event2/dns.h + Asynchronous DNS resolution + + event2/http.h + An embedded libevent-based HTTP server + + event2/rpc.h + A framework for creating RPC servers and clients + + */ + +/** @file event2/event.h + + Core functions for waiting for and receiving events, and using event bases. +*/ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef EVENT__HAVE_SYS_TYPES_H +#include +#endif +#ifdef EVENT__HAVE_SYS_TIME_H +#include +#endif + +#include + +/* For int types. */ +#include + +/** + * Structure to hold information and state for a Libevent dispatch loop. + * + * The event_base lies at the center of Libevent; every application will + * have one. It keeps track of all pending and active events, and + * notifies your application of the active ones. + * + * This is an opaque structure; you can allocate one using + * event_base_new() or event_base_new_with_config(). + * + * @see event_base_new(), event_base_free(), event_base_loop(), + * event_base_new_with_config() + */ +struct event_base +#ifdef EVENT_IN_DOXYGEN_ +{/*Empty body so that doxygen will generate documentation here.*/} +#endif +; + +/** + * @struct event + * + * Structure to represent a single event. + * + * An event can have some underlying condition it represents: a socket + * becoming readable or writeable (or both), or a signal becoming raised. + * (An event that represents no underlying condition is still useful: you + * can use one to implement a timer, or to communicate between threads.) + * + * Generally, you can create events with event_new(), then make them + * pending with event_add(). As your event_base runs, it will run the + * callbacks of an events whose conditions are triggered. When you + * longer want the event, free it with event_free(). + * + * In more depth: + * + * An event may be "pending" (one whose condition we are watching), + * "active" (one whose condition has triggered and whose callback is about + * to run), neither, or both. Events come into existence via + * event_assign() or event_new(), and are then neither active nor pending. + * + * To make an event pending, pass it to event_add(). When doing so, you + * can also set a timeout for the event. + * + * Events become active during an event_base_loop() call when either their + * condition has triggered, or when their timeout has elapsed. You can + * also activate an event manually using event_active(). The even_base + * loop will run the callbacks of active events; after it has done so, it + * marks them as no longer active. + * + * You can make an event non-pending by passing it to event_del(). This + * also makes the event non-active. + * + * Events can be "persistent" or "non-persistent". A non-persistent event + * becomes non-pending as soon as it is triggered: thus, it only runs at + * most once per call to event_add(). A persistent event remains pending + * even when it becomes active: you'll need to event_del() it manually in + * order to make it non-pending. When a persistent event with a timeout + * becomes active, its timeout is reset: this means you can use persistent + * events to implement periodic timeouts. + * + * This should be treated as an opaque structure; you should never read or + * write any of its fields directly. For backward compatibility with old + * code, it is defined in the event2/event_struct.h header; including this + * header may make your code incompatible with other versions of Libevent. + * + * @see event_new(), event_free(), event_assign(), event_get_assignment(), + * event_add(), event_del(), event_active(), event_pending(), + * event_get_fd(), event_get_base(), event_get_events(), + * event_get_callback(), event_get_callback_arg(), + * event_priority_set() + */ +struct event +#ifdef EVENT_IN_DOXYGEN_ +{/*Empty body so that doxygen will generate documentation here.*/} +#endif +; + +/** + * Configuration for an event_base. + * + * There are many options that can be used to alter the behavior and + * implementation of an event_base. To avoid having to pass them all in a + * complex many-argument constructor, we provide an abstract data type + * wrhere you set up configation information before passing it to + * event_base_new_with_config(). + * + * @see event_config_new(), event_config_free(), event_base_new_with_config(), + * event_config_avoid_method(), event_config_require_features(), + * event_config_set_flag(), event_config_set_num_cpus_hint() + */ +struct event_config +#ifdef EVENT_IN_DOXYGEN_ +{/*Empty body so that doxygen will generate documentation here.*/} +#endif +; + +/** + * Enable some relatively expensive debugging checks in Libevent that + * would normally be turned off. Generally, these checks cause code that + * would otherwise crash mysteriously to fail earlier with an assertion + * failure. Note that this method MUST be called before any events or + * event_bases have been created. + * + * Debug mode can currently catch the following errors: + * An event is re-assigned while it is added + * Any function is called on a non-assigned event + * + * Note that debugging mode uses memory to track every event that has been + * initialized (via event_assign, event_set, or event_new) but not yet + * released (via event_free or event_debug_unassign). If you want to use + * debug mode, and you find yourself running out of memory, you will need + * to use event_debug_unassign to explicitly stop tracking events that + * are no longer considered set-up. + * + * @see event_debug_unassign() + */ +EVENT2_EXPORT_SYMBOL +void event_enable_debug_mode(void); + +/** + * When debugging mode is enabled, informs Libevent that an event should no + * longer be considered as assigned. When debugging mode is not enabled, does + * nothing. + * + * This function must only be called on a non-added event. + * + * @see event_enable_debug_mode() + */ +EVENT2_EXPORT_SYMBOL +void event_debug_unassign(struct event *); + +/** + * Create and return a new event_base to use with the rest of Libevent. + * + * @return a new event_base on success, or NULL on failure. + * + * @see event_base_free(), event_base_new_with_config() + */ +EVENT2_EXPORT_SYMBOL +struct event_base *event_base_new(void); + +/** + Reinitialize the event base after a fork + + Some event mechanisms do not survive across fork. The event base needs + to be reinitialized with the event_reinit() function. + + @param base the event base that needs to be re-initialized + @return 0 if successful, or -1 if some events could not be re-added. + @see event_base_new() +*/ +EVENT2_EXPORT_SYMBOL +int event_reinit(struct event_base *base); + +/** + Event dispatching loop + + This loop will run the event base until either there are no more pending or + active, or until something calls event_base_loopbreak() or + event_base_loopexit(). + + @param base the event_base structure returned by event_base_new() or + event_base_new_with_config() + @return 0 if successful, -1 if an error occurred, or 1 if we exited because + no events were pending or active. + @see event_base_loop() + */ +EVENT2_EXPORT_SYMBOL +int event_base_dispatch(struct event_base *); + +/** + Get the kernel event notification mechanism used by Libevent. + + @param eb the event_base structure returned by event_base_new() + @return a string identifying the kernel event mechanism (kqueue, epoll, etc.) + */ +EVENT2_EXPORT_SYMBOL +const char *event_base_get_method(const struct event_base *); + +/** + Gets all event notification mechanisms supported by Libevent. + + This functions returns the event mechanism in order preferred by + Libevent. Note that this list will include all backends that + Libevent has compiled-in support for, and will not necessarily check + your OS to see whether it has the required resources. + + @return an array with pointers to the names of support methods. + The end of the array is indicated by a NULL pointer. If an + error is encountered NULL is returned. +*/ +EVENT2_EXPORT_SYMBOL +const char **event_get_supported_methods(void); + +/** Query the current monotonic time from a the timer for a struct + * event_base. + */ +EVENT2_EXPORT_SYMBOL +int event_gettime_monotonic(struct event_base *base, struct timeval *tp); + +/** + @name event type flag + + Flags to pass to event_base_get_num_events() to specify the kinds of events + we want to aggregate counts for +*/ +/**@{*/ +/** count the number of active events, which have been triggered.*/ +#define EVENT_BASE_COUNT_ACTIVE 1U +/** count the number of virtual events, which is used to represent an internal + * condition, other than a pending event, that keeps the loop from exiting. */ +#define EVENT_BASE_COUNT_VIRTUAL 2U +/** count the number of events which have been added to event base, including + * internal events. */ +#define EVENT_BASE_COUNT_ADDED 4U +/**@}*/ + +/** + Gets the number of events in event_base, as specified in the flags. + + Since event base has some internal events added to make some of its + functionalities work, EVENT_BASE_COUNT_ADDED may return more than the + number of events you added using event_add(). + + If you pass EVENT_BASE_COUNT_ACTIVE and EVENT_BASE_COUNT_ADDED together, an + active event will be counted twice. However, this might not be the case in + future libevent versions. The return value is an indication of the work + load, but the user shouldn't rely on the exact value as this may change in + the future. + + @param eb the event_base structure returned by event_base_new() + @param flags a bitwise combination of the kinds of events to aggregate + counts for + @return the number of events specified in the flags +*/ +EVENT2_EXPORT_SYMBOL +int event_base_get_num_events(struct event_base *, unsigned int); + +/** + Get the maximum number of events in a given event_base as specified in the + flags. + + @param eb the event_base structure returned by event_base_new() + @param flags a bitwise combination of the kinds of events to aggregate + counts for + @param clear option used to reset the maximum count. + @return the number of events specified in the flags + */ +EVENT2_EXPORT_SYMBOL +int event_base_get_max_events(struct event_base *, unsigned int, int); + +/** + Allocates a new event configuration object. + + The event configuration object can be used to change the behavior of + an event base. + + @return an event_config object that can be used to store configuration, or + NULL if an error is encountered. + @see event_base_new_with_config(), event_config_free(), event_config +*/ +EVENT2_EXPORT_SYMBOL +struct event_config *event_config_new(void); + +/** + Deallocates all memory associated with an event configuration object + + @param cfg the event configuration object to be freed. +*/ +EVENT2_EXPORT_SYMBOL +void event_config_free(struct event_config *cfg); + +/** + Enters an event method that should be avoided into the configuration. + + This can be used to avoid event mechanisms that do not support certain + file descriptor types, or for debugging to avoid certain event + mechanisms. An application can make use of multiple event bases to + accommodate incompatible file descriptor types. + + @param cfg the event configuration object + @param method the name of the event method to avoid + @return 0 on success, -1 on failure. +*/ +EVENT2_EXPORT_SYMBOL +int event_config_avoid_method(struct event_config *cfg, const char *method); + +/** + A flag used to describe which features an event_base (must) provide. + + Because of OS limitations, not every Libevent backend supports every + possible feature. You can use this type with + event_config_require_features() to tell Libevent to only proceed if your + event_base implements a given feature, and you can receive this type from + event_base_get_features() to see which features are available. +*/ +enum event_method_feature { + /** Require an event method that allows edge-triggered events with EV_ET. */ + EV_FEATURE_ET = 0x01, + /** Require an event method where having one event triggered among + * many is [approximately] an O(1) operation. This excludes (for + * example) select and poll, which are approximately O(N) for N + * equal to the total number of possible events. */ + EV_FEATURE_O1 = 0x02, + /** Require an event method that allows file descriptors as well as + * sockets. */ + EV_FEATURE_FDS = 0x04, + /** Require an event method that allows you to use EV_CLOSED to detect + * connection close without the necessity of reading all the pending data. + * + * Methods that do support EV_CLOSED may not be able to provide support on + * all kernel versions. + **/ + EV_FEATURE_EARLY_CLOSE = 0x08 +}; + +/** + A flag passed to event_config_set_flag(). + + These flags change the behavior of an allocated event_base. + + @see event_config_set_flag(), event_base_new_with_config(), + event_method_feature + */ +enum event_base_config_flag { + /** Do not allocate a lock for the event base, even if we have + locking set up. + + Setting this option will make it unsafe and nonfunctional to call + functions on the base concurrently from multiple threads. + */ + EVENT_BASE_FLAG_NOLOCK = 0x01, + /** Do not check the EVENT_* environment variables when configuring + an event_base */ + EVENT_BASE_FLAG_IGNORE_ENV = 0x02, + /** Windows only: enable the IOCP dispatcher at startup + + If this flag is set then bufferevent_socket_new() and + evconn_listener_new() will use IOCP-backed implementations + instead of the usual select-based one on Windows. + */ + EVENT_BASE_FLAG_STARTUP_IOCP = 0x04, + /** Instead of checking the current time every time the event loop is + ready to run timeout callbacks, check after each timeout callback. + */ + EVENT_BASE_FLAG_NO_CACHE_TIME = 0x08, + + /** If we are using the epoll backend, this flag says that it is + safe to use Libevent's internal change-list code to batch up + adds and deletes in order to try to do as few syscalls as + possible. Setting this flag can make your code run faster, but + it may trigger a Linux bug: it is not safe to use this flag + if you have any fds cloned by dup() or its variants. Doing so + will produce strange and hard-to-diagnose bugs. + + This flag can also be activated by setting the + EVENT_EPOLL_USE_CHANGELIST environment variable. + + This flag has no effect if you wind up using a backend other than + epoll. + */ + EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST = 0x10, + + /** Ordinarily, Libevent implements its time and timeout code using + the fastest monotonic timer that we have. If this flag is set, + however, we use less efficient more precise timer, assuming one is + present. + */ + EVENT_BASE_FLAG_PRECISE_TIMER = 0x20 +}; + +/** + Return a bitmask of the features implemented by an event base. This + will be a bitwise OR of one or more of the values of + event_method_feature + + @see event_method_feature + */ +EVENT2_EXPORT_SYMBOL +int event_base_get_features(const struct event_base *base); + +/** + Enters a required event method feature that the application demands. + + Note that not every feature or combination of features is supported + on every platform. Code that requests features should be prepared + to handle the case where event_base_new_with_config() returns NULL, as in: +
+     event_config_require_features(cfg, EV_FEATURE_ET);
+     base = event_base_new_with_config(cfg);
+     if (base == NULL) {
+       // We can't get edge-triggered behavior here.
+       event_config_require_features(cfg, 0);
+       base = event_base_new_with_config(cfg);
+     }
+   
+ + @param cfg the event configuration object + @param feature a bitfield of one or more event_method_feature values. + Replaces values from previous calls to this function. + @return 0 on success, -1 on failure. + @see event_method_feature, event_base_new_with_config() +*/ +EVENT2_EXPORT_SYMBOL +int event_config_require_features(struct event_config *cfg, int feature); + +/** + * Sets one or more flags to configure what parts of the eventual event_base + * will be initialized, and how they'll work. + * + * @see event_base_config_flags, event_base_new_with_config() + **/ +EVENT2_EXPORT_SYMBOL +int event_config_set_flag(struct event_config *cfg, int flag); + +/** + * Records a hint for the number of CPUs in the system. This is used for + * tuning thread pools, etc, for optimal performance. In Libevent 2.0, + * it is only on Windows, and only when IOCP is in use. + * + * @param cfg the event configuration object + * @param cpus the number of cpus + * @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int event_config_set_num_cpus_hint(struct event_config *cfg, int cpus); + +/** + * Record an interval and/or a number of callbacks after which the event base + * should check for new events. By default, the event base will run as many + * events are as activated at the higest activated priority before checking + * for new events. If you configure it by setting max_interval, it will check + * the time after each callback, and not allow more than max_interval to + * elapse before checking for new events. If you configure it by setting + * max_callbacks to a value >= 0, it will run no more than max_callbacks + * callbacks before checking for new events. + * + * This option can decrease the latency of high-priority events, and + * avoid priority inversions where multiple low-priority events keep us from + * polling for high-priority events, but at the expense of slightly decreasing + * the throughput. Use it with caution! + * + * @param cfg The event_base configuration object. + * @param max_interval An interval after which Libevent should stop running + * callbacks and check for more events, or NULL if there should be + * no such interval. + * @param max_callbacks A number of callbacks after which Libevent should + * stop running callbacks and check for more events, or -1 if there + * should be no such limit. + * @param min_priority A priority below which max_interval and max_callbacks + * should not be enforced. If this is set to 0, they are enforced + * for events of every priority; if it's set to 1, they're enforced + * for events of priority 1 and above, and so on. + * @return 0 on success, -1 on failure. + **/ +EVENT2_EXPORT_SYMBOL +int event_config_set_max_dispatch_interval(struct event_config *cfg, + const struct timeval *max_interval, int max_callbacks, + int min_priority); + +/** + Initialize the event API. + + Use event_base_new_with_config() to initialize a new event base, taking + the specified configuration under consideration. The configuration object + can currently be used to avoid certain event notification mechanisms. + + @param cfg the event configuration object + @return an initialized event_base that can be used to registering events, + or NULL if no event base can be created with the requested event_config. + @see event_base_new(), event_base_free(), event_init(), event_assign() +*/ +EVENT2_EXPORT_SYMBOL +struct event_base *event_base_new_with_config(const struct event_config *); + +/** + Deallocate all memory associated with an event_base, and free the base. + + Note that this function will not close any fds or free any memory passed + to event_new as the argument to callback. + + If there are any pending finalizer callbacks, this function will invoke + them. + + @param eb an event_base to be freed + */ +EVENT2_EXPORT_SYMBOL +void event_base_free(struct event_base *); + +/** + As event_free, but do not run finalizers. + + THIS IS AN EXPERIMENTAL API. IT MIGHT CHANGE BEFORE THE LIBEVENT 2.1 SERIES + BECOMES STABLE. + */ +EVENT2_EXPORT_SYMBOL +void event_base_free_nofinalize(struct event_base *); + +/** @name Log severities + */ +/**@{*/ +#define EVENT_LOG_DEBUG 0 +#define EVENT_LOG_MSG 1 +#define EVENT_LOG_WARN 2 +#define EVENT_LOG_ERR 3 +/**@}*/ + +/* Obsolete names: these are deprecated, but older programs might use them. + * They violate the reserved-identifier namespace. */ +#define _EVENT_LOG_DEBUG EVENT_LOG_DEBUG +#define _EVENT_LOG_MSG EVENT_LOG_MSG +#define _EVENT_LOG_WARN EVENT_LOG_WARN +#define _EVENT_LOG_ERR EVENT_LOG_ERR + +/** + A callback function used to intercept Libevent's log messages. + + @see event_set_log_callback + */ +typedef void (*event_log_cb)(int severity, const char *msg); +/** + Redirect Libevent's log messages. + + @param cb a function taking two arguments: an integer severity between + EVENT_LOG_DEBUG and EVENT_LOG_ERR, and a string. If cb is NULL, + then the default log is used. + + NOTE: The function you provide *must not* call any other libevent + functionality. Doing so can produce undefined behavior. + */ +EVENT2_EXPORT_SYMBOL +void event_set_log_callback(event_log_cb cb); + +/** + A function to be called if Libevent encounters a fatal internal error. + + @see event_set_fatal_callback + */ +typedef void (*event_fatal_cb)(int err); + +/** + Override Libevent's behavior in the event of a fatal internal error. + + By default, Libevent will call exit(1) if a programming error makes it + impossible to continue correct operation. This function allows you to supply + another callback instead. Note that if the function is ever invoked, + something is wrong with your program, or with Libevent: any subsequent calls + to Libevent may result in undefined behavior. + + Libevent will (almost) always log an EVENT_LOG_ERR message before calling + this function; look at the last log message to see why Libevent has died. + */ +EVENT2_EXPORT_SYMBOL +void event_set_fatal_callback(event_fatal_cb cb); + +#define EVENT_DBG_ALL 0xffffffffu +#define EVENT_DBG_NONE 0 + +/** + Turn on debugging logs and have them sent to the default log handler. + + This is a global setting; if you are going to call it, you must call this + before any calls that create an event-base. You must call it before any + multithreaded use of Libevent. + + Debug logs are verbose. + + @param which Controls which debug messages are turned on. This option is + unused for now; for forward compatibility, you must pass in the constant + "EVENT_DBG_ALL" to turn debugging logs on, or "EVENT_DBG_NONE" to turn + debugging logs off. + */ +EVENT2_EXPORT_SYMBOL +void event_enable_debug_logging(ev_uint32_t which); + +/** + Associate a different event base with an event. + + The event to be associated must not be currently active or pending. + + @param eb the event base + @param ev the event + @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int event_base_set(struct event_base *, struct event *); + +/** @name Loop flags + + These flags control the behavior of event_base_loop(). + */ +/**@{*/ +/** Block until we have an active event, then exit once all active events + * have had their callbacks run. */ +#define EVLOOP_ONCE 0x01 +/** Do not block: see which events are ready now, run the callbacks + * of the highest-priority ones, then exit. */ +#define EVLOOP_NONBLOCK 0x02 +/** Do not exit the loop because we have no pending events. Instead, keep + * running until event_base_loopexit() or event_base_loopbreak() makes us + * stop. + */ +#define EVLOOP_NO_EXIT_ON_EMPTY 0x04 +/**@}*/ + +/** + Wait for events to become active, and run their callbacks. + + This is a more flexible version of event_base_dispatch(). + + By default, this loop will run the event base until either there are no more + pending or active events, or until something calls event_base_loopbreak() or + event_base_loopexit(). You can override this behavior with the 'flags' + argument. + + @param eb the event_base structure returned by event_base_new() or + event_base_new_with_config() + @param flags any combination of EVLOOP_ONCE | EVLOOP_NONBLOCK + @return 0 if successful, -1 if an error occurred, or 1 if we exited because + no events were pending or active. + @see event_base_loopexit(), event_base_dispatch(), EVLOOP_ONCE, + EVLOOP_NONBLOCK + */ +EVENT2_EXPORT_SYMBOL +int event_base_loop(struct event_base *, int); + +/** + Exit the event loop after the specified time + + The next event_base_loop() iteration after the given timer expires will + complete normally (handling all queued events) then exit without + blocking for events again. + + Subsequent invocations of event_base_loop() will proceed normally. + + @param eb the event_base structure returned by event_init() + @param tv the amount of time after which the loop should terminate, + or NULL to exit after running all currently active events. + @return 0 if successful, or -1 if an error occurred + @see event_base_loopbreak() + */ +EVENT2_EXPORT_SYMBOL +int event_base_loopexit(struct event_base *, const struct timeval *); + +/** + Abort the active event_base_loop() immediately. + + event_base_loop() will abort the loop after the next event is completed; + event_base_loopbreak() is typically invoked from this event's callback. + This behavior is analogous to the "break;" statement. + + Subsequent invocations of event_base_loop() will proceed normally. + + @param eb the event_base structure returned by event_init() + @return 0 if successful, or -1 if an error occurred + @see event_base_loopexit() + */ +EVENT2_EXPORT_SYMBOL +int event_base_loopbreak(struct event_base *); + +/** + Tell the active event_base_loop() to scan for new events immediately. + + Calling this function makes the currently active event_base_loop() + start the loop over again (scanning for new events) after the current + event callback finishes. If the event loop is not running, this + function has no effect. + + event_base_loopbreak() is typically invoked from this event's callback. + This behavior is analogous to the "continue;" statement. + + Subsequent invocations of event loop will proceed normally. + + @param eb the event_base structure returned by event_init() + @return 0 if successful, or -1 if an error occurred + @see event_base_loopbreak() + */ +EVENT2_EXPORT_SYMBOL +int event_base_loopcontinue(struct event_base *); + +/** + Checks if the event loop was told to exit by event_base_loopexit(). + + This function will return true for an event_base at every point after + event_loopexit() is called, until the event loop is next entered. + + @param eb the event_base structure returned by event_init() + @return true if event_base_loopexit() was called on this event base, + or 0 otherwise + @see event_base_loopexit() + @see event_base_got_break() + */ +EVENT2_EXPORT_SYMBOL +int event_base_got_exit(struct event_base *); + +/** + Checks if the event loop was told to abort immediately by event_base_loopbreak(). + + This function will return true for an event_base at every point after + event_base_loopbreak() is called, until the event loop is next entered. + + @param eb the event_base structure returned by event_init() + @return true if event_base_loopbreak() was called on this event base, + or 0 otherwise + @see event_base_loopbreak() + @see event_base_got_exit() + */ +EVENT2_EXPORT_SYMBOL +int event_base_got_break(struct event_base *); + +/** + * @name event flags + * + * Flags to pass to event_new(), event_assign(), event_pending(), and + * anything else with an argument of the form "short events" + */ +/**@{*/ +/** Indicates that a timeout has occurred. It's not necessary to pass + * this flag to event_for new()/event_assign() to get a timeout. */ +#define EV_TIMEOUT 0x01 +/** Wait for a socket or FD to become readable */ +#define EV_READ 0x02 +/** Wait for a socket or FD to become writeable */ +#define EV_WRITE 0x04 +/** Wait for a POSIX signal to be raised*/ +#define EV_SIGNAL 0x08 +/** + * Persistent event: won't get removed automatically when activated. + * + * When a persistent event with a timeout becomes activated, its timeout + * is reset to 0. + */ +#define EV_PERSIST 0x10 +/** Select edge-triggered behavior, if supported by the backend. */ +#define EV_ET 0x20 +/** + * If this option is provided, then event_del() will not block in one thread + * while waiting for the event callback to complete in another thread. + * + * To use this option safely, you may need to use event_finalize() or + * event_free_finalize() in order to safely tear down an event in a + * multithreaded application. See those functions for more information. + * + * THIS IS AN EXPERIMENTAL API. IT MIGHT CHANGE BEFORE THE LIBEVENT 2.1 SERIES + * BECOMES STABLE. + **/ +#define EV_FINALIZE 0x40 +/** + * Detects connection close events. You can use this to detect when a + * connection has been closed, without having to read all the pending data + * from a connection. + * + * Not all backends support EV_CLOSED. To detect or require it, use the + * feature flag EV_FEATURE_EARLY_CLOSE. + **/ +#define EV_CLOSED 0x80 +/**@}*/ + +/** + @name evtimer_* macros + + Aliases for working with one-shot timer events */ +/**@{*/ +#define evtimer_assign(ev, b, cb, arg) \ + event_assign((ev), (b), -1, 0, (cb), (arg)) +#define evtimer_new(b, cb, arg) event_new((b), -1, 0, (cb), (arg)) +#define evtimer_add(ev, tv) event_add((ev), (tv)) +#define evtimer_del(ev) event_del(ev) +#define evtimer_pending(ev, tv) event_pending((ev), EV_TIMEOUT, (tv)) +#define evtimer_initialized(ev) event_initialized(ev) +/**@}*/ + +/** + @name evsignal_* macros + + Aliases for working with signal events + */ +/**@{*/ +#define evsignal_add(ev, tv) event_add((ev), (tv)) +#define evsignal_assign(ev, b, x, cb, arg) \ + event_assign((ev), (b), (x), EV_SIGNAL|EV_PERSIST, cb, (arg)) +#define evsignal_new(b, x, cb, arg) \ + event_new((b), (x), EV_SIGNAL|EV_PERSIST, (cb), (arg)) +#define evsignal_del(ev) event_del(ev) +#define evsignal_pending(ev, tv) event_pending((ev), EV_SIGNAL, (tv)) +#define evsignal_initialized(ev) event_initialized(ev) +/**@}*/ + +/** + A callback function for an event. + + It receives three arguments: + + @param fd An fd or signal + @param events One or more EV_* flags + @param arg A user-supplied argument. + + @see event_new() + */ +typedef void (*event_callback_fn)(evutil_socket_t, short, void *); + +/** + Return a value used to specify that the event itself must be used as the callback argument. + + The function event_new() takes a callback argument which is passed + to the event's callback function. To specify that the argument to be + passed to the callback function is the event that event_new() returns, + pass in the return value of event_self_cbarg() as the callback argument + for event_new(). + + For example: +
+      struct event *ev = event_new(base, sock, events, callback, %event_self_cbarg());
+  
+ + For consistency with event_new(), it is possible to pass the return value + of this function as the callback argument for event_assign() – this + achieves the same result as passing the event in directly. + + @return a value to be passed as the callback argument to event_new() or + event_assign(). + @see event_new(), event_assign() + */ +EVENT2_EXPORT_SYMBOL +void *event_self_cbarg(void); + +/** + Allocate and asssign a new event structure, ready to be added. + + The function event_new() returns a new event that can be used in + future calls to event_add() and event_del(). The fd and events + arguments determine which conditions will trigger the event; the + callback and callback_arg arguments tell Libevent what to do when the + event becomes active. + + If events contains one of EV_READ, EV_WRITE, or EV_READ|EV_WRITE, then + fd is a file descriptor or socket that should get monitored for + readiness to read, readiness to write, or readiness for either operation + (respectively). If events contains EV_SIGNAL, then fd is a signal + number to wait for. If events contains none of those flags, then the + event can be triggered only by a timeout or by manual activation with + event_active(): In this case, fd must be -1. + + The EV_PERSIST flag can also be passed in the events argument: it makes + event_add() persistent until event_del() is called. + + The EV_ET flag is compatible with EV_READ and EV_WRITE, and supported + only by certain backends. It tells Libevent to use edge-triggered + events. + + The EV_TIMEOUT flag has no effect here. + + It is okay to have multiple events all listening on the same fds; but + they must either all be edge-triggered, or all not be edge triggerd. + + When the event becomes active, the event loop will run the provided + callbuck function, with three arguments. The first will be the provided + fd value. The second will be a bitfield of the events that triggered: + EV_READ, EV_WRITE, or EV_SIGNAL. Here the EV_TIMEOUT flag indicates + that a timeout occurred, and EV_ET indicates that an edge-triggered + event occurred. The third event will be the callback_arg pointer that + you provide. + + @param base the event base to which the event should be attached. + @param fd the file descriptor or signal to be monitored, or -1. + @param events desired events to monitor: bitfield of EV_READ, EV_WRITE, + EV_SIGNAL, EV_PERSIST, EV_ET. + @param callback callback function to be invoked when the event occurs + @param callback_arg an argument to be passed to the callback function + + @return a newly allocated struct event that must later be freed with + event_free(). + @see event_free(), event_add(), event_del(), event_assign() + */ +EVENT2_EXPORT_SYMBOL +struct event *event_new(struct event_base *, evutil_socket_t, short, event_callback_fn, void *); + + +/** + Prepare a new, already-allocated event structure to be added. + + The function event_assign() prepares the event structure ev to be used + in future calls to event_add() and event_del(). Unlike event_new(), it + doesn't allocate memory itself: it requires that you have already + allocated a struct event, probably on the heap. Doing this will + typically make your code depend on the size of the event structure, and + thereby create incompatibility with future versions of Libevent. + + The easiest way to avoid this problem is just to use event_new() and + event_free() instead. + + A slightly harder way to future-proof your code is to use + event_get_struct_event_size() to determine the required size of an event + at runtime. + + Note that it is NOT safe to call this function on an event that is + active or pending. Doing so WILL corrupt internal data structures in + Libevent, and lead to strange, hard-to-diagnose bugs. You _can_ use + event_assign to change an existing event, but only if it is not active + or pending! + + The arguments for this function, and the behavior of the events that it + makes, are as for event_new(). + + @param ev an event struct to be modified + @param base the event base to which ev should be attached. + @param fd the file descriptor to be monitored + @param events desired events to monitor; can be EV_READ and/or EV_WRITE + @param callback callback function to be invoked when the event occurs + @param callback_arg an argument to be passed to the callback function + + @return 0 if success, or -1 on invalid arguments. + + @see event_new(), event_add(), event_del(), event_base_once(), + event_get_struct_event_size() + */ +EVENT2_EXPORT_SYMBOL +int event_assign(struct event *, struct event_base *, evutil_socket_t, short, event_callback_fn, void *); + +/** + Deallocate a struct event * returned by event_new(). + + If the event is pending or active, first make it non-pending and + non-active. + */ +EVENT2_EXPORT_SYMBOL +void event_free(struct event *); + +/** + * Callback type for event_finalize and event_free_finalize(). + * + * THIS IS AN EXPERIMENTAL API. IT MIGHT CHANGE BEFORE THE LIBEVENT 2.1 SERIES + * BECOMES STABLE. + * + **/ +typedef void (*event_finalize_callback_fn)(struct event *, void *); +/** + @name Finalization functions + + These functions are used to safely tear down an event in a multithreaded + application. If you construct your events with EV_FINALIZE to avoid + deadlocks, you will need a way to remove an event in the certainty that + it will definitely not be running its callback when you deallocate it + and its callback argument. + + To do this, call one of event_finalize() or event_free_finalize with + 0 for its first argument, the event to tear down as its second argument, + and a callback function as its third argument. The callback will be + invoked as part of the event loop, with the event's priority. + + After you call a finalizer function, event_add() and event_active() will + no longer work on the event, and event_del() will produce a no-op. You + must not try to change the event's fields with event_assign() or + event_set() while the finalize callback is in progress. Once the + callback has been invoked, you should treat the event structure as + containing uninitialized memory. + + The event_free_finalize() function frees the event after it's finalized; + event_finalize() does not. + + A finalizer callback must not make events pending or active. It must not + add events, activate events, or attempt to "resucitate" the event being + finalized in any way. + + THIS IS AN EXPERIMENTAL API. IT MIGHT CHANGE BEFORE THE LIBEVENT 2.1 SERIES + BECOMES STABLE. + + @return 0 on succes, -1 on failure. + */ +/**@{*/ +EVENT2_EXPORT_SYMBOL +int event_finalize(unsigned, struct event *, event_finalize_callback_fn); +EVENT2_EXPORT_SYMBOL +int event_free_finalize(unsigned, struct event *, event_finalize_callback_fn); +/**@}*/ + +/** + Schedule a one-time event + + The function event_base_once() is similar to event_new(). However, it + schedules a callback to be called exactly once, and does not require the + caller to prepare an event structure. + + Note that in Libevent 2.0 and earlier, if the event is never triggered, the + internal memory used to hold it will never be freed. In Libevent 2.1, + the internal memory will get freed by event_base_free() if the event + is never triggered. The 'arg' value, however, will not get freed in either + case--you'll need to free that on your own if you want it to go away. + + @param base an event_base + @param fd a file descriptor to monitor, or -1 for no fd. + @param events event(s) to monitor; can be any of EV_READ | + EV_WRITE, or EV_TIMEOUT + @param callback callback function to be invoked when the event occurs + @param arg an argument to be passed to the callback function + @param timeout the maximum amount of time to wait for the event. NULL + makes an EV_READ/EV_WRITE event make forever; NULL makes an + EV_TIMEOUT event succees immediately. + @return 0 if successful, or -1 if an error occurred + */ +EVENT2_EXPORT_SYMBOL +int event_base_once(struct event_base *, evutil_socket_t, short, event_callback_fn, void *, const struct timeval *); + +/** + Add an event to the set of pending events. + + The function event_add() schedules the execution of the event 'ev' when the + condition specified by event_assign() or event_new() occurs, or when the time + specified in timeout has elapesed. If atimeout is NULL, no timeout + occurs and the function will only be + called if a matching event occurs. The event in the + ev argument must be already initialized by event_assign() or event_new() + and may not be used + in calls to event_assign() until it is no longer pending. + + If the event in the ev argument already has a scheduled timeout, calling + event_add() replaces the old timeout with the new one if tv is non-NULL. + + @param ev an event struct initialized via event_assign() or event_new() + @param timeout the maximum amount of time to wait for the event, or NULL + to wait forever + @return 0 if successful, or -1 if an error occurred + @see event_del(), event_assign(), event_new() + */ +EVENT2_EXPORT_SYMBOL +int event_add(struct event *ev, const struct timeval *timeout); + +/** + Remove a timer from a pending event without removing the event itself. + + If the event has a scheduled timeout, this function unschedules it but + leaves the event otherwise pending. + + @param ev an event struct initialized via event_assign() or event_new() + @return 0 on success, or -1 if an error occurrect. +*/ +EVENT2_EXPORT_SYMBOL +int event_remove_timer(struct event *ev); + +/** + Remove an event from the set of monitored events. + + The function event_del() will cancel the event in the argument ev. If the + event has already executed or has never been added the call will have no + effect. + + @param ev an event struct to be removed from the working set + @return 0 if successful, or -1 if an error occurred + @see event_add() + */ +EVENT2_EXPORT_SYMBOL +int event_del(struct event *); + +/** + As event_del(), but never blocks while the event's callback is running + in another thread, even if the event was constructed without the + EV_FINALIZE flag. + + THIS IS AN EXPERIMENTAL API. IT MIGHT CHANGE BEFORE THE LIBEVENT 2.1 SERIES + BECOMES STABLE. + */ +EVENT2_EXPORT_SYMBOL +int event_del_noblock(struct event *ev); +/** + As event_del(), but always blocks while the event's callback is running + in another thread, even if the event was constructed with the + EV_FINALIZE flag. + + THIS IS AN EXPERIMENTAL API. IT MIGHT CHANGE BEFORE THE LIBEVENT 2.1 SERIES + BECOMES STABLE. + */ +EVENT2_EXPORT_SYMBOL +int event_del_block(struct event *ev); + +/** + Make an event active. + + You can use this function on a pending or a non-pending event to make it + active, so that its callback will be run by event_base_dispatch() or + event_base_loop(). + + One common use in multithreaded programs is to wake the thread running + event_base_loop() from another thread. + + @param ev an event to make active. + @param res a set of flags to pass to the event's callback. + @param ncalls an obsolete argument: this is ignored. + **/ +EVENT2_EXPORT_SYMBOL +void event_active(struct event *ev, int res, short ncalls); + +/** + Checks if a specific event is pending or scheduled. + + @param ev an event struct previously passed to event_add() + @param events the requested event type; any of EV_TIMEOUT|EV_READ| + EV_WRITE|EV_SIGNAL + @param tv if this field is not NULL, and the event has a timeout, + this field is set to hold the time at which the timeout will + expire. + + @return true if the event is pending on any of the events in 'what', (that + is to say, it has been added), or 0 if the event is not added. + */ +EVENT2_EXPORT_SYMBOL +int event_pending(const struct event *ev, short events, struct timeval *tv); + +/** + If called from within the callback for an event, returns that event. + + The behavior of this function is not defined when called from outside the + callback function for an event. + */ +EVENT2_EXPORT_SYMBOL +struct event *event_base_get_running_event(struct event_base *base); + +/** + Test if an event structure might be initialized. + + The event_initialized() function can be used to check if an event has been + initialized. + + Warning: This function is only useful for distinguishing a a zeroed-out + piece of memory from an initialized event, it can easily be confused by + uninitialized memory. Thus, it should ONLY be used to distinguish an + initialized event from zero. + + @param ev an event structure to be tested + @return 1 if the structure might be initialized, or 0 if it has not been + initialized + */ +EVENT2_EXPORT_SYMBOL +int event_initialized(const struct event *ev); + +/** + Get the signal number assigned to a signal event +*/ +#define event_get_signal(ev) ((int)event_get_fd(ev)) + +/** + Get the socket or signal assigned to an event, or -1 if the event has + no socket. +*/ +EVENT2_EXPORT_SYMBOL +evutil_socket_t event_get_fd(const struct event *ev); + +/** + Get the event_base associated with an event. +*/ +EVENT2_EXPORT_SYMBOL +struct event_base *event_get_base(const struct event *ev); + +/** + Return the events (EV_READ, EV_WRITE, etc) assigned to an event. +*/ +EVENT2_EXPORT_SYMBOL +short event_get_events(const struct event *ev); + +/** + Return the callback assigned to an event. +*/ +EVENT2_EXPORT_SYMBOL +event_callback_fn event_get_callback(const struct event *ev); + +/** + Return the callback argument assigned to an event. +*/ +EVENT2_EXPORT_SYMBOL +void *event_get_callback_arg(const struct event *ev); + +/** + Return the priority of an event. + @see event_priority_init(), event_get_priority() +*/ +EVENT2_EXPORT_SYMBOL +int event_get_priority(const struct event *ev); + +/** + Extract _all_ of arguments given to construct a given event. The + event_base is copied into *base_out, the fd is copied into *fd_out, and so + on. + + If any of the "_out" arguments is NULL, it will be ignored. + */ +EVENT2_EXPORT_SYMBOL +void event_get_assignment(const struct event *event, + struct event_base **base_out, evutil_socket_t *fd_out, short *events_out, + event_callback_fn *callback_out, void **arg_out); + +/** + Return the size of struct event that the Libevent library was compiled + with. + + This will be NO GREATER than sizeof(struct event) if you're running with + the same version of Libevent that your application was built with, but + otherwise might not. + + Note that it might be SMALLER than sizeof(struct event) if some future + version of Libevent adds extra padding to the end of struct event. + We might do this to help ensure ABI-compatibility between different + versions of Libevent. + */ +EVENT2_EXPORT_SYMBOL +size_t event_get_struct_event_size(void); + +/** + Get the Libevent version. + + Note that this will give you the version of the library that you're + currently linked against, not the version of the headers that you've + compiled against. + + @return a string containing the version number of Libevent +*/ +EVENT2_EXPORT_SYMBOL +const char *event_get_version(void); + +/** + Return a numeric representation of Libevent's version. + + Note that this will give you the version of the library that you're + currently linked against, not the version of the headers you've used to + compile. + + The format uses one byte each for the major, minor, and patchlevel parts of + the version number. The low-order byte is unused. For example, version + 2.0.1-alpha has a numeric representation of 0x02000100 +*/ +EVENT2_EXPORT_SYMBOL +ev_uint32_t event_get_version_number(void); + +/** As event_get_version, but gives the version of Libevent's headers. */ +#define LIBEVENT_VERSION EVENT__VERSION +/** As event_get_version_number, but gives the version number of Libevent's + * headers. */ +#define LIBEVENT_VERSION_NUMBER EVENT__NUMERIC_VERSION + +/** Largest number of priorities that Libevent can support. */ +#define EVENT_MAX_PRIORITIES 256 +/** + Set the number of different event priorities + + By default Libevent schedules all active events with the same priority. + However, some time it is desirable to process some events with a higher + priority than others. For that reason, Libevent supports strict priority + queues. Active events with a lower priority are always processed before + events with a higher priority. + + The number of different priorities can be set initially with the + event_base_priority_init() function. This function should be called + before the first call to event_base_dispatch(). The + event_priority_set() function can be used to assign a priority to an + event. By default, Libevent assigns the middle priority to all events + unless their priority is explicitly set. + + Note that urgent-priority events can starve less-urgent events: after + running all urgent-priority callbacks, Libevent checks for more urgent + events again, before running less-urgent events. Less-urgent events + will not have their callbacks run until there are no events more urgent + than them that want to be active. + + @param eb the event_base structure returned by event_base_new() + @param npriorities the maximum number of priorities + @return 0 if successful, or -1 if an error occurred + @see event_priority_set() + */ +EVENT2_EXPORT_SYMBOL +int event_base_priority_init(struct event_base *, int); + +/** + Get the number of different event priorities. + + @param eb the event_base structure returned by event_base_new() + @return Number of different event priorities + @see event_base_priority_init() +*/ +EVENT2_EXPORT_SYMBOL +int event_base_get_npriorities(struct event_base *eb); + +/** + Assign a priority to an event. + + @param ev an event struct + @param priority the new priority to be assigned + @return 0 if successful, or -1 if an error occurred + @see event_priority_init(), event_get_priority() + */ +EVENT2_EXPORT_SYMBOL +int event_priority_set(struct event *, int); + +/** + Prepare an event_base to use a large number of timeouts with the same + duration. + + Libevent's default scheduling algorithm is optimized for having a large + number of timeouts with their durations more or less randomly + distributed. But if you have a large number of timeouts that all have + the same duration (for example, if you have a large number of + connections that all have a 10-second timeout), then you can improve + Libevent's performance by telling Libevent about it. + + To do this, call this function with the common duration. It will return a + pointer to a different, opaque timeout value. (Don't depend on its actual + contents!) When you use this timeout value in event_add(), Libevent will + schedule the event more efficiently. + + (This optimization probably will not be worthwhile until you have thousands + or tens of thousands of events with the same timeout.) + */ +EVENT2_EXPORT_SYMBOL +const struct timeval *event_base_init_common_timeout(struct event_base *base, + const struct timeval *duration); + +#if !defined(EVENT__DISABLE_MM_REPLACEMENT) || defined(EVENT_IN_DOXYGEN_) +/** + Override the functions that Libevent uses for memory management. + + Usually, Libevent uses the standard libc functions malloc, realloc, and + free to allocate memory. Passing replacements for those functions to + event_set_mem_functions() overrides this behavior. + + Note that all memory returned from Libevent will be allocated by the + replacement functions rather than by malloc() and realloc(). Thus, if you + have replaced those functions, it will not be appropriate to free() memory + that you get from Libevent. Instead, you must use the free_fn replacement + that you provided. + + Note also that if you are going to call this function, you should do so + before any call to any Libevent function that does allocation. + Otherwise, those funtions will allocate their memory using malloc(), but + then later free it using your provided free_fn. + + @param malloc_fn A replacement for malloc. + @param realloc_fn A replacement for realloc + @param free_fn A replacement for free. + **/ +EVENT2_EXPORT_SYMBOL +void event_set_mem_functions( + void *(*malloc_fn)(size_t sz), + void *(*realloc_fn)(void *ptr, size_t sz), + void (*free_fn)(void *ptr)); +/** This definition is present if Libevent was built with support for + event_set_mem_functions() */ +#define EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED +#endif + +/** + Writes a human-readable description of all inserted and/or active + events to a provided stdio stream. + + This is intended for debugging; its format is not guaranteed to be the same + between libevent versions. + + @param base An event_base on which to scan the events. + @param output A stdio file to write on. + */ +EVENT2_EXPORT_SYMBOL +void event_base_dump_events(struct event_base *, FILE *); + + +/** + Activates all pending events for the given fd and event mask. + + This function activates pending events only. Events which have not been + added will not become active. + + @param base the event_base on which to activate the events. + @param fd An fd to active events on. + @param events One or more of EV_{READ,WRITE}. + */ +EVENT2_EXPORT_SYMBOL +void event_base_active_by_fd(struct event_base *base, evutil_socket_t fd, short events); + +/** + Activates all pending signals with a given signal number + + This function activates pending events only. Events which have not been + added will not become active. + + @param base the event_base on which to activate the events. + @param fd The signal to active events on. + */ +EVENT2_EXPORT_SYMBOL +void event_base_active_by_signal(struct event_base *base, int sig); + +/** + * Callback for iterating events in an event base via event_base_foreach_event + */ +typedef int (*event_base_foreach_event_cb)(const struct event_base *, const struct event *, void *); + +/** + Iterate over all added or active events events in an event loop, and invoke + a given callback on each one. + + The callback must not call any function that modifies the event base, that + modifies any event in the event base, or that adds or removes any event to + the event base. Doing so is unsupported and will lead to undefined + behavior -- likely, to crashes. + + event_base_foreach_event() holds a lock on the event_base() for the whole + time it's running: slow callbacks are not advisable. + + Note that Libevent adds some events of its own to make pieces of its + functionality work. You must not assume that the only events you'll + encounter will be the ones you added yourself. + + The callback function must return 0 to continue iteration, or some other + integer to stop iterating. + + @param base An event_base on which to scan the events. + @param fn A callback function to receive the events. + @param arg An argument passed to the callback function. + @return 0 if we iterated over every event, or the value returned by the + callback function if the loop exited early. +*/ +EVENT2_EXPORT_SYMBOL +int event_base_foreach_event(struct event_base *base, event_base_foreach_event_cb fn, void *arg); + + +/** Sets 'tv' to the current time (as returned by gettimeofday()), + looking at the cached value in 'base' if possible, and calling + gettimeofday() or clock_gettime() as appropriate if there is no + cached time. + + Generally, this value will only be cached while actually + processing event callbacks, and may be very inaccuate if your + callbacks take a long time to execute. + + Returns 0 on success, negative on failure. + */ +EVENT2_EXPORT_SYMBOL +int event_base_gettimeofday_cached(struct event_base *base, + struct timeval *tv); + +/** Update cached_tv in the 'base' to the current time + * + * You can use this function is useful for selectively increasing + * the accuracy of the cached time value in 'base' during callbacks + * that take a long time to execute. + * + * This function has no effect if the base is currently not in its + * event loop, or if timeval caching is disabled via + * EVENT_BASE_FLAG_NO_CACHE_TIME. + * + * @return 0 on success, -1 on failure + */ +EVENT2_EXPORT_SYMBOL +int event_base_update_cache_time(struct event_base *base); + +/** Release up all globally-allocated resources allocated by Libevent. + + This function does not free developer-controlled resources like + event_bases, events, bufferevents, listeners, and so on. It only releases + resources like global locks that there is no other way to free. + + It is not actually necessary to call this function before exit: every + resource that it frees would be released anyway on exit. It mainly exists + so that resource-leak debugging tools don't see Libevent as holding + resources at exit. + + You should only call this function when no other Libevent functions will + be invoked -- e.g., when cleanly exiting a program. + */ +EVENT2_EXPORT_SYMBOL +void libevent_global_shutdown(void); + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_EVENT_H_INCLUDED_ */ diff --git a/platform/src/3rd/os_specific/oe2203/include/event2/event_compat.h b/platform/src/3rd/os_specific/oe2203/include/event2/event_compat.h new file mode 100644 index 00000000..5110175a --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/event2/event_compat.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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 EVENT2_EVENT_COMPAT_H_INCLUDED_ +#define EVENT2_EVENT_COMPAT_H_INCLUDED_ + +/** @file event2/event_compat.h + + Potentially non-threadsafe versions of the functions in event.h: provided + only for backwards compatibility. + + In the oldest versions of Libevent, event_base was not a first-class + structure. Instead, there was a single event base that every function + manipulated. Later, when separate event bases were added, the old functions + that didn't take an event_base argument needed to work by manipulating the + "current" event base. This could lead to thread-safety issues, and obscure, + hard-to-diagnose bugs. + + @deprecated All functions in this file are by definition deprecated. + */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef EVENT__HAVE_SYS_TYPES_H +#include +#endif +#ifdef EVENT__HAVE_SYS_TIME_H +#include +#endif + +/* For int types. */ +#include + +/** + Initialize the event API. + + The event API needs to be initialized with event_init() before it can be + used. Sets the global current base that gets used for events that have no + base associated with them. + + @deprecated This function is deprecated because it replaces the "current" + event_base, and is totally unsafe for multithreaded use. The replacement + is event_base_new(). + + @see event_base_set(), event_base_new() + */ +EVENT2_EXPORT_SYMBOL +struct event_base *event_init(void); + +/** + Loop to process events. + + Like event_base_dispatch(), but uses the "current" base. + + @deprecated This function is deprecated because it is easily confused by + multiple calls to event_init(), and because it is not safe for + multithreaded use. The replacement is event_base_dispatch(). + + @see event_base_dispatch(), event_init() + */ +EVENT2_EXPORT_SYMBOL +int event_dispatch(void); + +/** + Handle events. + + This function behaves like event_base_loop(), but uses the "current" base + + @deprecated This function is deprecated because it uses the event base from + the last call to event_init, and is therefore not safe for multithreaded + use. The replacement is event_base_loop(). + + @see event_base_loop(), event_init() +*/ +EVENT2_EXPORT_SYMBOL +int event_loop(int); + + +/** + Exit the event loop after the specified time. + + This function behaves like event_base_loopexit(), except that it uses the + "current" base. + + @deprecated This function is deprecated because it uses the event base from + the last call to event_init, and is therefore not safe for multithreaded + use. The replacement is event_base_loopexit(). + + @see event_init, event_base_loopexit() + */ +EVENT2_EXPORT_SYMBOL +int event_loopexit(const struct timeval *); + + +/** + Abort the active event_loop() immediately. + + This function behaves like event_base_loopbreakt(), except that it uses the + "current" base. + + @deprecated This function is deprecated because it uses the event base from + the last call to event_init, and is therefore not safe for multithreaded + use. The replacement is event_base_loopbreak(). + + @see event_base_loopbreak(), event_init() + */ +EVENT2_EXPORT_SYMBOL +int event_loopbreak(void); + +/** + Schedule a one-time event to occur. + + @deprecated This function is obsolete, and has been replaced by + event_base_once(). Its use is deprecated because it relies on the + "current" base configured by event_init(). + + @see event_base_once() + */ +EVENT2_EXPORT_SYMBOL +int event_once(evutil_socket_t , short, + void (*)(evutil_socket_t, short, void *), void *, const struct timeval *); + + +/** + Get the kernel event notification mechanism used by Libevent. + + @deprecated This function is obsolete, and has been replaced by + event_base_get_method(). Its use is deprecated because it relies on the + "current" base configured by event_init(). + + @see event_base_get_method() + */ +EVENT2_EXPORT_SYMBOL +const char *event_get_method(void); + + +/** + Set the number of different event priorities. + + @deprecated This function is deprecated because it is easily confused by + multiple calls to event_init(), and because it is not safe for + multithreaded use. The replacement is event_base_priority_init(). + + @see event_base_priority_init() + */ +EVENT2_EXPORT_SYMBOL +int event_priority_init(int); + +/** + Prepare an event structure to be added. + + @deprecated event_set() is not recommended for new code, because it requires + a subsequent call to event_base_set() to be safe under most circumstances. + Use event_assign() or event_new() instead. + */ +EVENT2_EXPORT_SYMBOL +void event_set(struct event *, evutil_socket_t, short, void (*)(evutil_socket_t, short, void *), void *); + +#define evtimer_set(ev, cb, arg) event_set((ev), -1, 0, (cb), (arg)) +#define evsignal_set(ev, x, cb, arg) \ + event_set((ev), (x), EV_SIGNAL|EV_PERSIST, (cb), (arg)) + + +/** + @name timeout_* macros + + @deprecated These macros are deprecated because their naming is inconsistent + with the rest of Libevent. Use the evtimer_* macros instead. + @{ + */ +#define timeout_add(ev, tv) event_add((ev), (tv)) +#define timeout_set(ev, cb, arg) event_set((ev), -1, 0, (cb), (arg)) +#define timeout_del(ev) event_del(ev) +#define timeout_pending(ev, tv) event_pending((ev), EV_TIMEOUT, (tv)) +#define timeout_initialized(ev) event_initialized(ev) +/**@}*/ + +/** + @name signal_* macros + + @deprecated These macros are deprecated because their naming is inconsistent + with the rest of Libevent. Use the evsignal_* macros instead. + @{ + */ +#define signal_add(ev, tv) event_add((ev), (tv)) +#define signal_set(ev, x, cb, arg) \ + event_set((ev), (x), EV_SIGNAL|EV_PERSIST, (cb), (arg)) +#define signal_del(ev) event_del(ev) +#define signal_pending(ev, tv) event_pending((ev), EV_SIGNAL, (tv)) +#define signal_initialized(ev) event_initialized(ev) +/**@}*/ + +#ifndef EVENT_FD +/* These macros are obsolete; use event_get_fd and event_get_signal instead. */ +#define EVENT_FD(ev) ((int)event_get_fd(ev)) +#define EVENT_SIGNAL(ev) event_get_signal(ev) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_EVENT_COMPAT_H_INCLUDED_ */ diff --git a/platform/src/3rd/os_specific/oe2203/include/event2/event_struct.h b/platform/src/3rd/os_specific/oe2203/include/event2/event_struct.h new file mode 100644 index 00000000..1c8b71b6 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/event2/event_struct.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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 EVENT2_EVENT_STRUCT_H_INCLUDED_ +#define EVENT2_EVENT_STRUCT_H_INCLUDED_ + +/** @file event2/event_struct.h + + Structures used by event.h. Using these structures directly WILL harm + forward compatibility: be careful. + + No field declared in this file should be used directly in user code. Except + for historical reasons, these fields would not be exposed at all. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef EVENT__HAVE_SYS_TYPES_H +#include +#endif +#ifdef EVENT__HAVE_SYS_TIME_H +#include +#endif + +/* For int types. */ +#include + +/* For evkeyvalq */ +#include + +#define EVLIST_TIMEOUT 0x01 +#define EVLIST_INSERTED 0x02 +#define EVLIST_SIGNAL 0x04 +#define EVLIST_ACTIVE 0x08 +#define EVLIST_INTERNAL 0x10 +#define EVLIST_ACTIVE_LATER 0x20 +#define EVLIST_FINALIZING 0x40 +#define EVLIST_INIT 0x80 + +#define EVLIST_ALL 0xff + +/* Fix so that people don't have to run with */ +#ifndef TAILQ_ENTRY +#define EVENT_DEFINED_TQENTRY_ +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} +#endif /* !TAILQ_ENTRY */ + +#ifndef TAILQ_HEAD +#define EVENT_DEFINED_TQHEAD_ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; \ + struct type **tqh_last; \ +} +#endif + +/* Fix so that people don't have to run with */ +#ifndef LIST_ENTRY +#define EVENT_DEFINED_LISTENTRY_ +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} +#endif /* !LIST_ENTRY */ + +#ifndef LIST_HEAD +#define EVENT_DEFINED_LISTHEAD_ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ + } +#endif /* !LIST_HEAD */ + +struct event; + +struct event_callback { + TAILQ_ENTRY(event_callback) evcb_active_next; + short evcb_flags; + ev_uint8_t evcb_pri; /* smaller numbers are higher priority */ + ev_uint8_t evcb_closure; + /* allows us to adopt for different types of events */ + union { + void (*evcb_callback)(evutil_socket_t, short, void *); + void (*evcb_selfcb)(struct event_callback *, void *); + void (*evcb_evfinalize)(struct event *, void *); + void (*evcb_cbfinalize)(struct event_callback *, void *); + } evcb_cb_union; + void *evcb_arg; +}; + +struct event_base; +struct event { + struct event_callback ev_evcallback; + + /* for managing timeouts */ + union { + TAILQ_ENTRY(event) ev_next_with_common_timeout; + int min_heap_idx; + } ev_timeout_pos; + evutil_socket_t ev_fd; + + struct event_base *ev_base; + + union { + /* used for io events */ + struct { + LIST_ENTRY (event) ev_io_next; + struct timeval ev_timeout; + } ev_io; + + /* used by signal events */ + struct { + LIST_ENTRY (event) ev_signal_next; + short ev_ncalls; + /* Allows deletes in callback */ + short *ev_pncalls; + } ev_signal; + } ev_; + + short ev_events; + short ev_res; /* result passed to event callback */ + struct timeval ev_timeout; +}; + +TAILQ_HEAD (event_list, event); + +#ifdef EVENT_DEFINED_TQENTRY_ +#undef TAILQ_ENTRY +#endif + +#ifdef EVENT_DEFINED_TQHEAD_ +#undef TAILQ_HEAD +#endif + +LIST_HEAD (event_dlist, event); + +#ifdef EVENT_DEFINED_LISTENTRY_ +#undef LIST_ENTRY +#endif + +#ifdef EVENT_DEFINED_LISTHEAD_ +#undef LIST_HEAD +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_EVENT_STRUCT_H_INCLUDED_ */ diff --git a/platform/src/3rd/os_specific/oe2203/include/event2/http.h b/platform/src/3rd/os_specific/oe2203/include/event2/http.h new file mode 100644 index 00000000..8fb5642f --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/event2/http.h @@ -0,0 +1,1189 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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 EVENT2_HTTP_H_INCLUDED_ +#define EVENT2_HTTP_H_INCLUDED_ + +/* For int types. */ +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* In case we haven't included the right headers yet. */ +struct evbuffer; +struct event_base; +struct bufferevent; +struct evhttp_connection; + +/** @file event2/http.h + * + * Basic support for HTTP serving. + * + * As Libevent is a library for dealing with event notification and most + * interesting applications are networked today, I have often found the + * need to write HTTP code. The following prototypes and definitions provide + * an application with a minimal interface for making HTTP requests and for + * creating a very simple HTTP server. + */ + +/* Response codes */ +#define HTTP_OK 200 /**< request completed ok */ +#define HTTP_NOCONTENT 204 /**< request does not have content */ +#define HTTP_MOVEPERM 301 /**< the uri moved permanently */ +#define HTTP_MOVETEMP 302 /**< the uri moved temporarily */ +#define HTTP_NOTMODIFIED 304 /**< page was not modified from last */ +#define HTTP_BADREQUEST 400 /**< invalid http request was made */ +#define HTTP_NOTFOUND 404 /**< could not find content for uri */ +#define HTTP_BADMETHOD 405 /**< method not allowed for this uri */ +#define HTTP_ENTITYTOOLARGE 413 /**< */ +#define HTTP_EXPECTATIONFAILED 417 /**< we can't handle this expectation */ +#define HTTP_INTERNAL 500 /**< internal error */ +#define HTTP_NOTIMPLEMENTED 501 /**< not implemented */ +#define HTTP_SERVUNAVAIL 503 /**< the server is not available */ + +struct evhttp; +struct evhttp_request; +struct evkeyvalq; +struct evhttp_bound_socket; +struct evconnlistener; +struct evdns_base; + +/** + * Create a new HTTP server. + * + * @param base (optional) the event base to receive the HTTP events + * @return a pointer to a newly initialized evhttp server structure + * @see evhttp_free() + */ +EVENT2_EXPORT_SYMBOL +struct evhttp *evhttp_new(struct event_base *base); + +/** + * Binds an HTTP server on the specified address and port. + * + * Can be called multiple times to bind the same http server + * to multiple different ports. + * + * @param http a pointer to an evhttp object + * @param address a string containing the IP address to listen(2) on + * @param port the port number to listen on + * @return 0 on success, -1 on failure. + * @see evhttp_accept_socket() + */ +EVENT2_EXPORT_SYMBOL +int evhttp_bind_socket(struct evhttp *http, const char *address, ev_uint16_t port); + +/** + * Like evhttp_bind_socket(), but returns a handle for referencing the socket. + * + * The returned pointer is not valid after \a http is freed. + * + * @param http a pointer to an evhttp object + * @param address a string containing the IP address to listen(2) on + * @param port the port number to listen on + * @return Handle for the socket on success, NULL on failure. + * @see evhttp_bind_socket(), evhttp_del_accept_socket() + */ +EVENT2_EXPORT_SYMBOL +struct evhttp_bound_socket *evhttp_bind_socket_with_handle(struct evhttp *http, const char *address, ev_uint16_t port); + +/** + * Makes an HTTP server accept connections on the specified socket. + * + * This may be useful to create a socket and then fork multiple instances + * of an http server, or when a socket has been communicated via file + * descriptor passing in situations where an http servers does not have + * permissions to bind to a low-numbered port. + * + * Can be called multiple times to have the http server listen to + * multiple different sockets. + * + * @param http a pointer to an evhttp object + * @param fd a socket fd that is ready for accepting connections + * @return 0 on success, -1 on failure. + * @see evhttp_bind_socket() + */ +EVENT2_EXPORT_SYMBOL +int evhttp_accept_socket(struct evhttp *http, evutil_socket_t fd); + +/** + * Like evhttp_accept_socket(), but returns a handle for referencing the socket. + * + * The returned pointer is not valid after \a http is freed. + * + * @param http a pointer to an evhttp object + * @param fd a socket fd that is ready for accepting connections + * @return Handle for the socket on success, NULL on failure. + * @see evhttp_accept_socket(), evhttp_del_accept_socket() + */ +EVENT2_EXPORT_SYMBOL +struct evhttp_bound_socket *evhttp_accept_socket_with_handle(struct evhttp *http, evutil_socket_t fd); + +/** + * The most low-level evhttp_bind/accept method: takes an evconnlistener, and + * returns an evhttp_bound_socket. The listener will be freed when the bound + * socket is freed. + */ +EVENT2_EXPORT_SYMBOL +struct evhttp_bound_socket *evhttp_bind_listener(struct evhttp *http, struct evconnlistener *listener); + +/** + * Return the listener used to implement a bound socket. + */ +EVENT2_EXPORT_SYMBOL +struct evconnlistener *evhttp_bound_socket_get_listener(struct evhttp_bound_socket *bound); + +typedef void evhttp_bound_socket_foreach_fn(struct evhttp_bound_socket *, void *); +/** + * Applies the function specified in the first argument to all + * evhttp_bound_sockets associated with "http". The user must not + * attempt to free or remove any connections, sockets or listeners + * in the callback "function". + * + * @param http pointer to an evhttp object + * @param function function to apply to every bound socket + * @param argument pointer value passed to function for every socket iterated + */ +EVENT2_EXPORT_SYMBOL +void evhttp_foreach_bound_socket(struct evhttp *http, evhttp_bound_socket_foreach_fn *function, void *argument); + +/** + * Makes an HTTP server stop accepting connections on the specified socket + * + * This may be useful when a socket has been sent via file descriptor passing + * and is no longer needed by the current process. + * + * If you created this bound socket with evhttp_bind_socket_with_handle or + * evhttp_accept_socket_with_handle, this function closes the fd you provided. + * If you created this bound socket with evhttp_bind_listener, this function + * frees the listener you provided. + * + * \a bound_socket is an invalid pointer after this call returns. + * + * @param http a pointer to an evhttp object + * @param bound_socket a handle returned by evhttp_{bind,accept}_socket_with_handle + * @see evhttp_bind_socket_with_handle(), evhttp_accept_socket_with_handle() + */ +EVENT2_EXPORT_SYMBOL +void evhttp_del_accept_socket(struct evhttp *http, struct evhttp_bound_socket *bound_socket); + +/** + * Get the raw file descriptor referenced by an evhttp_bound_socket. + * + * @param bound_socket a handle returned by evhttp_{bind,accept}_socket_with_handle + * @return the file descriptor used by the bound socket + * @see evhttp_bind_socket_with_handle(), evhttp_accept_socket_with_handle() + */ +EVENT2_EXPORT_SYMBOL +evutil_socket_t evhttp_bound_socket_get_fd(struct evhttp_bound_socket *bound_socket); + +/** + * Free the previously created HTTP server. + * + * Works only if no requests are currently being served. + * + * @param http the evhttp server object to be freed + * @see evhttp_start() + */ +EVENT2_EXPORT_SYMBOL +void evhttp_free(struct evhttp* http); + +/** XXX Document. */ +EVENT2_EXPORT_SYMBOL +void evhttp_set_max_headers_size(struct evhttp* http, ev_ssize_t max_headers_size); +/** XXX Document. */ +EVENT2_EXPORT_SYMBOL +void evhttp_set_max_body_size(struct evhttp* http, ev_ssize_t max_body_size); + +/** + Set the value to use for the Content-Type header when none was provided. If + the content type string is NULL, the Content-Type header will not be + automatically added. + + @param http the http server on which to set the default content type + @param content_type the value for the Content-Type header +*/ +EVENT2_EXPORT_SYMBOL +void evhttp_set_default_content_type(struct evhttp *http, + const char *content_type); + +/** + Sets the what HTTP methods are supported in requests accepted by this + server, and passed to user callbacks. + + If not supported they will generate a "405 Method not allowed" response. + + By default this includes the following methods: GET, POST, HEAD, PUT, DELETE + + @param http the http server on which to set the methods + @param methods bit mask constructed from evhttp_cmd_type values +*/ +EVENT2_EXPORT_SYMBOL +void evhttp_set_allowed_methods(struct evhttp* http, ev_uint16_t methods); + +/** + Set a callback for a specified URI + + @param http the http sever on which to set the callback + @param path the path for which to invoke the callback + @param cb the callback function that gets invoked on requesting path + @param cb_arg an additional context argument for the callback + @return 0 on success, -1 if the callback existed already, -2 on failure +*/ +EVENT2_EXPORT_SYMBOL +int evhttp_set_cb(struct evhttp *http, const char *path, + void (*cb)(struct evhttp_request *, void *), void *cb_arg); + +/** Removes the callback for a specified URI */ +EVENT2_EXPORT_SYMBOL +int evhttp_del_cb(struct evhttp *, const char *); + +/** + Set a callback for all requests that are not caught by specific callbacks + + Invokes the specified callback for all requests that do not match any of + the previously specified request paths. This is catchall for requests not + specifically configured with evhttp_set_cb(). + + @param http the evhttp server object for which to set the callback + @param cb the callback to invoke for any unmatched requests + @param arg an context argument for the callback +*/ +EVENT2_EXPORT_SYMBOL +void evhttp_set_gencb(struct evhttp *http, + void (*cb)(struct evhttp_request *, void *), void *arg); + +/** + Set a callback used to create new bufferevents for connections + to a given evhttp object. + + You can use this to override the default bufferevent type -- for example, + to make this evhttp object use SSL bufferevents rather than unencrypted + ones. + + New bufferevents must be allocated with no fd set on them. + + @param http the evhttp server object for which to set the callback + @param cb the callback to invoke for incoming connections + @param arg an context argument for the callback + */ +EVENT2_EXPORT_SYMBOL +void evhttp_set_bevcb(struct evhttp *http, + struct bufferevent *(*cb)(struct event_base *, void *), void *arg); + +/** + Adds a virtual host to the http server. + + A virtual host is a newly initialized evhttp object that has request + callbacks set on it via evhttp_set_cb() or evhttp_set_gencb(). It + most not have any listing sockets associated with it. + + If the virtual host has not been removed by the time that evhttp_free() + is called on the main http server, it will be automatically freed, too. + + It is possible to have hierarchical vhosts. For example: A vhost + with the pattern *.example.com may have other vhosts with patterns + foo.example.com and bar.example.com associated with it. + + @param http the evhttp object to which to add a virtual host + @param pattern the glob pattern against which the hostname is matched. + The match is case insensitive and follows otherwise regular shell + matching. + @param vhost the virtual host to add the regular http server. + @return 0 on success, -1 on failure + @see evhttp_remove_virtual_host() +*/ +EVENT2_EXPORT_SYMBOL +int evhttp_add_virtual_host(struct evhttp* http, const char *pattern, + struct evhttp* vhost); + +/** + Removes a virtual host from the http server. + + @param http the evhttp object from which to remove the virtual host + @param vhost the virtual host to remove from the regular http server. + @return 0 on success, -1 on failure + @see evhttp_add_virtual_host() +*/ +EVENT2_EXPORT_SYMBOL +int evhttp_remove_virtual_host(struct evhttp* http, struct evhttp* vhost); + +/** + Add a server alias to an http object. The http object can be a virtual + host or the main server. + + @param http the evhttp object + @param alias the alias to add + @see evhttp_add_remove_alias() +*/ +EVENT2_EXPORT_SYMBOL +int evhttp_add_server_alias(struct evhttp *http, const char *alias); + +/** + Remove a server alias from an http object. + + @param http the evhttp object + @param alias the alias to remove + @see evhttp_add_server_alias() +*/ +EVENT2_EXPORT_SYMBOL +int evhttp_remove_server_alias(struct evhttp *http, const char *alias); + +/** + * Set the timeout for an HTTP request. + * + * @param http an evhttp object + * @param timeout_in_secs the timeout, in seconds + */ +EVENT2_EXPORT_SYMBOL +void evhttp_set_timeout(struct evhttp *http, int timeout_in_secs); + +/** + * Set the timeout for an HTTP request. + * + * @param http an evhttp object + * @param tv the timeout, or NULL + */ +EVENT2_EXPORT_SYMBOL +void evhttp_set_timeout_tv(struct evhttp *http, const struct timeval* tv); + +/* Read all the clients body, and only after this respond with an error if the + * clients body exceed max_body_size */ +#define EVHTTP_SERVER_LINGERING_CLOSE 0x0001 +/** + * Set connection flags for HTTP server. + * + * @see EVHTTP_SERVER_* + * @return 0 on success, otherwise non zero (for example if flag doesn't + * supported). + */ +EVENT2_EXPORT_SYMBOL +int evhttp_set_flags(struct evhttp *http, int flags); + +/* Request/Response functionality */ + +/** + * Send an HTML error message to the client. + * + * @param req a request object + * @param error the HTTP error code + * @param reason a brief explanation of the error. If this is NULL, we'll + * just use the standard meaning of the error code. + */ +EVENT2_EXPORT_SYMBOL +void evhttp_send_error(struct evhttp_request *req, int error, + const char *reason); + +/** + * Send an HTML reply to the client. + * + * The body of the reply consists of the data in databuf. After calling + * evhttp_send_reply() databuf will be empty, but the buffer is still + * owned by the caller and needs to be deallocated by the caller if + * necessary. + * + * @param req a request object + * @param code the HTTP response code to send + * @param reason a brief message to send with the response code + * @param databuf the body of the response + */ +EVENT2_EXPORT_SYMBOL +void evhttp_send_reply(struct evhttp_request *req, int code, + const char *reason, struct evbuffer *databuf); + +/* Low-level response interface, for streaming/chunked replies */ + +/** + Initiate a reply that uses Transfer-Encoding chunked. + + This allows the caller to stream the reply back to the client and is + useful when either not all of the reply data is immediately available + or when sending very large replies. + + The caller needs to supply data chunks with evhttp_send_reply_chunk() + and complete the reply by calling evhttp_send_reply_end(). + + @param req a request object + @param code the HTTP response code to send + @param reason a brief message to send with the response code +*/ +EVENT2_EXPORT_SYMBOL +void evhttp_send_reply_start(struct evhttp_request *req, int code, + const char *reason); + +/** + Send another data chunk as part of an ongoing chunked reply. + + The reply chunk consists of the data in databuf. After calling + evhttp_send_reply_chunk() databuf will be empty, but the buffer is + still owned by the caller and needs to be deallocated by the caller + if necessary. + + @param req a request object + @param databuf the data chunk to send as part of the reply. +*/ +EVENT2_EXPORT_SYMBOL +void evhttp_send_reply_chunk(struct evhttp_request *req, + struct evbuffer *databuf); + +/** + Send another data chunk as part of an ongoing chunked reply. + + The reply chunk consists of the data in databuf. After calling + evhttp_send_reply_chunk() databuf will be empty, but the buffer is + still owned by the caller and needs to be deallocated by the caller + if necessary. + + @param req a request object + @param databuf the data chunk to send as part of the reply. + @param cb callback funcion + @param call back's argument. +*/ +EVENT2_EXPORT_SYMBOL +void evhttp_send_reply_chunk_with_cb(struct evhttp_request *, struct evbuffer *, + void (*cb)(struct evhttp_connection *, void *), void *arg); + +/** + Complete a chunked reply, freeing the request as appropriate. + + @param req a request object +*/ +EVENT2_EXPORT_SYMBOL +void evhttp_send_reply_end(struct evhttp_request *req); + +/* + * Interfaces for making requests + */ + +/** The different request types supported by evhttp. These are as specified + * in RFC2616, except for PATCH which is specified by RFC5789. + * + * By default, only some of these methods are accepted and passed to user + * callbacks; use evhttp_set_allowed_methods() to change which methods + * are allowed. + */ +enum evhttp_cmd_type { + EVHTTP_REQ_GET = 1 << 0, + EVHTTP_REQ_POST = 1 << 1, + EVHTTP_REQ_HEAD = 1 << 2, + EVHTTP_REQ_PUT = 1 << 3, + EVHTTP_REQ_DELETE = 1 << 4, + EVHTTP_REQ_OPTIONS = 1 << 5, + EVHTTP_REQ_TRACE = 1 << 6, + EVHTTP_REQ_CONNECT = 1 << 7, + EVHTTP_REQ_PATCH = 1 << 8 +}; + +/** a request object can represent either a request or a reply */ +enum evhttp_request_kind { EVHTTP_REQUEST, EVHTTP_RESPONSE }; + +/** + * Create and return a connection object that can be used to for making HTTP + * requests. The connection object tries to resolve address and establish the + * connection when it is given an http request object. + * + * @param base the event_base to use for handling the connection + * @param dnsbase the dns_base to use for resolving host names; if not + * specified host name resolution will block. + * @param bev a bufferevent to use for connecting to the server; if NULL, a + * socket-based bufferevent will be created. This buffrevent will be freed + * when the connection closes. It must have no fd set on it. + * @param address the address to which to connect + * @param port the port to connect to + * @return an evhttp_connection object that can be used for making requests + */ +EVENT2_EXPORT_SYMBOL +struct evhttp_connection *evhttp_connection_base_bufferevent_new( + struct event_base *base, struct evdns_base *dnsbase, struct bufferevent* bev, const char *address, ev_uint16_t port); + +/** + * Return the bufferevent that an evhttp_connection is using. + */ +EVENT2_EXPORT_SYMBOL +struct bufferevent* evhttp_connection_get_bufferevent(struct evhttp_connection *evcon); + +/** + * Return the HTTP server associated with this connection, or NULL. + */ +EVENT2_EXPORT_SYMBOL +struct evhttp *evhttp_connection_get_server(struct evhttp_connection *evcon); + +/** + * Creates a new request object that needs to be filled in with the request + * parameters. The callback is executed when the request completed or an + * error occurred. + */ +EVENT2_EXPORT_SYMBOL +struct evhttp_request *evhttp_request_new( + void (*cb)(struct evhttp_request *, void *), void *arg); + +/** + * Enable delivery of chunks to requestor. + * @param cb will be called after every read of data with the same argument + * as the completion callback. Will never be called on an empty + * response. May drain the input buffer; it will be drained + * automatically on return. + */ +EVENT2_EXPORT_SYMBOL +void evhttp_request_set_chunked_cb(struct evhttp_request *, + void (*cb)(struct evhttp_request *, void *)); + +/** + * Register callback for additional parsing of request headers. + * @param cb will be called after receiving and parsing the full header. + * It allows analyzing the header and possibly closing the connection + * by returning a value < 0. + */ +EVENT2_EXPORT_SYMBOL +void evhttp_request_set_header_cb(struct evhttp_request *, + int (*cb)(struct evhttp_request *, void *)); + +/** + * The different error types supported by evhttp + * + * @see evhttp_request_set_error_cb() + */ +enum evhttp_request_error { + /** + * Timeout reached, also @see evhttp_connection_set_timeout() + */ + EVREQ_HTTP_TIMEOUT, + /** + * EOF reached + */ + EVREQ_HTTP_EOF, + /** + * Error while reading header, or invalid header + */ + EVREQ_HTTP_INVALID_HEADER, + /** + * Error encountered while reading or writing + */ + EVREQ_HTTP_BUFFER_ERROR, + /** + * The evhttp_cancel_request() called on this request. + */ + EVREQ_HTTP_REQUEST_CANCEL, + /** + * Body is greater then evhttp_connection_set_max_body_size() + */ + EVREQ_HTTP_DATA_TOO_LONG +}; +/** + * Set a callback for errors + * @see evhttp_request_error for error types. + * + * On error, both the error callback and the regular callback will be called, + * error callback is called before the regular callback. + **/ +EVENT2_EXPORT_SYMBOL +void evhttp_request_set_error_cb(struct evhttp_request *, + void (*)(enum evhttp_request_error, void *)); + +/** + * Set a callback to be called on request completion of evhttp_send_* function. + * + * The callback function will be called on the completion of the request after + * the output data has been written and before the evhttp_request object + * is destroyed. This can be useful for tracking resources associated with a + * request (ex: timing metrics). + * + * @param req a request object + * @param cb callback function that will be called on request completion + * @param cb_arg an additional context argument for the callback + */ +EVENT2_EXPORT_SYMBOL +void evhttp_request_set_on_complete_cb(struct evhttp_request *req, + void (*cb)(struct evhttp_request *, void *), void *cb_arg); + +/** Frees the request object and removes associated events. */ +EVENT2_EXPORT_SYMBOL +void evhttp_request_free(struct evhttp_request *req); + +/** + * Create and return a connection object that can be used to for making HTTP + * requests. The connection object tries to resolve address and establish the + * connection when it is given an http request object. + * + * @param base the event_base to use for handling the connection + * @param dnsbase the dns_base to use for resolving host names; if not + * specified host name resolution will block. + * @param address the address to which to connect + * @param port the port to connect to + * @return an evhttp_connection object that can be used for making requests + */ +EVENT2_EXPORT_SYMBOL +struct evhttp_connection *evhttp_connection_base_new( + struct event_base *base, struct evdns_base *dnsbase, + const char *address, ev_uint16_t port); + +/** + * Set family hint for DNS requests. + */ +EVENT2_EXPORT_SYMBOL +void evhttp_connection_set_family(struct evhttp_connection *evcon, + int family); + +/* reuse connection address on retry */ +#define EVHTTP_CON_REUSE_CONNECTED_ADDR 0x0008 +/* Try to read error, since server may already send and close + * connection, but if at that time we have some data to send then we + * can send get EPIPE and fail, while we can read that HTTP error. */ +#define EVHTTP_CON_READ_ON_WRITE_ERROR 0x0010 +/* @see EVHTTP_SERVER_LINGERING_CLOSE */ +#define EVHTTP_CON_LINGERING_CLOSE 0x0020 +/* Padding for public flags, @see EVHTTP_CON_* in http-internal.h */ +#define EVHTTP_CON_PUBLIC_FLAGS_END 0x100000 +/** + * Set connection flags. + * + * @see EVHTTP_CON_* + * @return 0 on success, otherwise non zero (for example if flag doesn't + * supported). + */ +EVENT2_EXPORT_SYMBOL +int evhttp_connection_set_flags(struct evhttp_connection *evcon, + int flags); + +/** Takes ownership of the request object + * + * Can be used in a request callback to keep onto the request until + * evhttp_request_free() is explicitly called by the user. + */ +EVENT2_EXPORT_SYMBOL +void evhttp_request_own(struct evhttp_request *req); + +/** Returns 1 if the request is owned by the user */ +EVENT2_EXPORT_SYMBOL +int evhttp_request_is_owned(struct evhttp_request *req); + +/** + * Returns the connection object associated with the request or NULL + * + * The user needs to either free the request explicitly or call + * evhttp_send_reply_end(). + */ +EVENT2_EXPORT_SYMBOL +struct evhttp_connection *evhttp_request_get_connection(struct evhttp_request *req); + +/** + * Returns the underlying event_base for this connection + */ +EVENT2_EXPORT_SYMBOL +struct event_base *evhttp_connection_get_base(struct evhttp_connection *req); + +EVENT2_EXPORT_SYMBOL +void evhttp_connection_set_max_headers_size(struct evhttp_connection *evcon, + ev_ssize_t new_max_headers_size); + +EVENT2_EXPORT_SYMBOL +void evhttp_connection_set_max_body_size(struct evhttp_connection* evcon, + ev_ssize_t new_max_body_size); + +/** Frees an http connection */ +EVENT2_EXPORT_SYMBOL +void evhttp_connection_free(struct evhttp_connection *evcon); + +/** Disowns a given connection object + * + * Can be used to tell libevent to free the connection object after + * the last request has completed or failed. + */ +EVENT2_EXPORT_SYMBOL +void evhttp_connection_free_on_completion(struct evhttp_connection *evcon); + +/** sets the ip address from which http connections are made */ +EVENT2_EXPORT_SYMBOL +void evhttp_connection_set_local_address(struct evhttp_connection *evcon, + const char *address); + +/** sets the local port from which http connections are made */ +EVENT2_EXPORT_SYMBOL +void evhttp_connection_set_local_port(struct evhttp_connection *evcon, + ev_uint16_t port); + +/** Sets the timeout in seconds for events related to this connection */ +EVENT2_EXPORT_SYMBOL +void evhttp_connection_set_timeout(struct evhttp_connection *evcon, + int timeout_in_secs); + +/** Sets the timeout for events related to this connection. Takes a struct + * timeval. */ +EVENT2_EXPORT_SYMBOL +void evhttp_connection_set_timeout_tv(struct evhttp_connection *evcon, + const struct timeval *tv); + +/** Sets the delay before retrying requests on this connection. This is only + * used if evhttp_connection_set_retries is used to make the number of retries + * at least one. Each retry after the first is twice as long as the one before + * it. */ +EVENT2_EXPORT_SYMBOL +void evhttp_connection_set_initial_retry_tv(struct evhttp_connection *evcon, + const struct timeval *tv); + +/** Sets the retry limit for this connection - -1 repeats indefinitely */ +EVENT2_EXPORT_SYMBOL +void evhttp_connection_set_retries(struct evhttp_connection *evcon, + int retry_max); + +/** Set a callback for connection close. */ +EVENT2_EXPORT_SYMBOL +void evhttp_connection_set_closecb(struct evhttp_connection *evcon, + void (*)(struct evhttp_connection *, void *), void *); + +/** Get the remote address and port associated with this connection. */ +EVENT2_EXPORT_SYMBOL +void evhttp_connection_get_peer(struct evhttp_connection *evcon, + char **address, ev_uint16_t *port); + +/** Get the remote address associated with this connection. + * extracted from getpeername() OR from nameserver. + * + * @return NULL if getpeername() return non success, + * or connection is not connected, + * otherwise it return pointer to struct sockaddr_storage */ +EVENT2_EXPORT_SYMBOL +const struct sockaddr* +evhttp_connection_get_addr(struct evhttp_connection *evcon); + +/** + Make an HTTP request over the specified connection. + + The connection gets ownership of the request. On failure, the + request object is no longer valid as it has been freed. + + @param evcon the evhttp_connection object over which to send the request + @param req the previously created and configured request object + @param type the request type EVHTTP_REQ_GET, EVHTTP_REQ_POST, etc. + @param uri the URI associated with the request + @return 0 on success, -1 on failure + @see evhttp_cancel_request() +*/ +EVENT2_EXPORT_SYMBOL +int evhttp_make_request(struct evhttp_connection *evcon, + struct evhttp_request *req, + enum evhttp_cmd_type type, const char *uri); + +/** + Cancels a pending HTTP request. + + Cancels an ongoing HTTP request. The callback associated with this request + is not executed and the request object is freed. If the request is + currently being processed, e.g. it is ongoing, the corresponding + evhttp_connection object is going to get reset. + + A request cannot be canceled if its callback has executed already. A request + may be canceled reentrantly from its chunked callback. + + @param req the evhttp_request to cancel; req becomes invalid after this call. +*/ +EVENT2_EXPORT_SYMBOL +void evhttp_cancel_request(struct evhttp_request *req); + +/** + * A structure to hold a parsed URI or Relative-Ref conforming to RFC3986. + */ +struct evhttp_uri; + +/** Returns the request URI */ +EVENT2_EXPORT_SYMBOL +const char *evhttp_request_get_uri(const struct evhttp_request *req); +/** Returns the request URI (parsed) */ +EVENT2_EXPORT_SYMBOL +const struct evhttp_uri *evhttp_request_get_evhttp_uri(const struct evhttp_request *req); +/** Returns the request command */ +EVENT2_EXPORT_SYMBOL +enum evhttp_cmd_type evhttp_request_get_command(const struct evhttp_request *req); + +EVENT2_EXPORT_SYMBOL +int evhttp_request_get_response_code(const struct evhttp_request *req); +EVENT2_EXPORT_SYMBOL +const char * evhttp_request_get_response_code_line(const struct evhttp_request *req); + +/** Returns the input headers */ +EVENT2_EXPORT_SYMBOL +struct evkeyvalq *evhttp_request_get_input_headers(struct evhttp_request *req); +/** Returns the output headers */ +EVENT2_EXPORT_SYMBOL +struct evkeyvalq *evhttp_request_get_output_headers(struct evhttp_request *req); +/** Returns the input buffer */ +EVENT2_EXPORT_SYMBOL +struct evbuffer *evhttp_request_get_input_buffer(struct evhttp_request *req); +/** Returns the output buffer */ +EVENT2_EXPORT_SYMBOL +struct evbuffer *evhttp_request_get_output_buffer(struct evhttp_request *req); +/** Returns the host associated with the request. If a client sends an absolute + URI, the host part of that is preferred. Otherwise, the input headers are + searched for a Host: header. NULL is returned if no absolute URI or Host: + header is provided. */ +EVENT2_EXPORT_SYMBOL +const char *evhttp_request_get_host(struct evhttp_request *req); + +/* Interfaces for dealing with HTTP headers */ + +/** + Finds the value belonging to a header. + + @param headers the evkeyvalq object in which to find the header + @param key the name of the header to find + @returns a pointer to the value for the header or NULL if the header + could not be found. + @see evhttp_add_header(), evhttp_remove_header() +*/ +EVENT2_EXPORT_SYMBOL +const char *evhttp_find_header(const struct evkeyvalq *headers, + const char *key); + +/** + Removes a header from a list of existing headers. + + @param headers the evkeyvalq object from which to remove a header + @param key the name of the header to remove + @returns 0 if the header was removed, -1 otherwise. + @see evhttp_find_header(), evhttp_add_header() +*/ +EVENT2_EXPORT_SYMBOL +int evhttp_remove_header(struct evkeyvalq *headers, const char *key); + +/** + Adds a header to a list of existing headers. + + @param headers the evkeyvalq object to which to add a header + @param key the name of the header + @param value the value belonging to the header + @returns 0 on success, -1 otherwise. + @see evhttp_find_header(), evhttp_clear_headers() +*/ +EVENT2_EXPORT_SYMBOL +int evhttp_add_header(struct evkeyvalq *headers, const char *key, const char *value); + +/** + Removes all headers from the header list. + + @param headers the evkeyvalq object from which to remove all headers +*/ +EVENT2_EXPORT_SYMBOL +void evhttp_clear_headers(struct evkeyvalq *headers); + +/* Miscellaneous utility functions */ + + +/** + Helper function to encode a string for inclusion in a URI. All + characters are replaced by their hex-escaped (%22) equivalents, + except for characters explicitly unreserved by RFC3986 -- that is, + ASCII alphanumeric characters, hyphen, dot, underscore, and tilde. + + The returned string must be freed by the caller. + + @param str an unencoded string + @return a newly allocated URI-encoded string or NULL on failure + */ +EVENT2_EXPORT_SYMBOL +char *evhttp_encode_uri(const char *str); + +/** + As evhttp_encode_uri, but if 'size' is nonnegative, treat the string + as being 'size' bytes long. This allows you to encode strings that + may contain 0-valued bytes. + + The returned string must be freed by the caller. + + @param str an unencoded string + @param size the length of the string to encode, or -1 if the string + is NUL-terminated + @param space_to_plus if true, space characters in 'str' are encoded + as +, not %20. + @return a newly allocate URI-encoded string, or NULL on failure. + */ +EVENT2_EXPORT_SYMBOL +char *evhttp_uriencode(const char *str, ev_ssize_t size, int space_to_plus); + +/** + Helper function to sort of decode a URI-encoded string. Unlike + evhttp_get_decoded_uri, it decodes all plus characters that appear + _after_ the first question mark character, but no plusses that occur + before. This is not a good way to decode URIs in whole or in part. + + The returned string must be freed by the caller + + @deprecated This function is deprecated; you probably want to use + evhttp_get_decoded_uri instead. + + @param uri an encoded URI + @return a newly allocated unencoded URI or NULL on failure + */ +EVENT2_EXPORT_SYMBOL +char *evhttp_decode_uri(const char *uri); + +/** + Helper function to decode a URI-escaped string or HTTP parameter. + + If 'decode_plus' is 1, then we decode the string as an HTTP parameter + value, and convert all plus ('+') characters to spaces. If + 'decode_plus' is 0, we leave all plus characters unchanged. + + The returned string must be freed by the caller. + + @param uri a URI-encode encoded URI + @param decode_plus determines whether we convert '+' to space. + @param size_out if size_out is not NULL, *size_out is set to the size of the + returned string + @return a newly allocated unencoded URI or NULL on failure + */ +EVENT2_EXPORT_SYMBOL +char *evhttp_uridecode(const char *uri, int decode_plus, + size_t *size_out); + +/** + Helper function to parse out arguments in a query. + + Parsing a URI like + + http://foo.com/?q=test&s=some+thing + + will result in two entries in the key value queue. + + The first entry is: key="q", value="test" + The second entry is: key="s", value="some thing" + + @deprecated This function is deprecated as of Libevent 2.0.9. Use + evhttp_uri_parse and evhttp_parse_query_str instead. + + @param uri the request URI + @param headers the head of the evkeyval queue + @return 0 on success, -1 on failure + */ +EVENT2_EXPORT_SYMBOL +int evhttp_parse_query(const char *uri, struct evkeyvalq *headers); + +/** + Helper function to parse out arguments from the query portion of an + HTTP URI. + + Parsing a query string like + + q=test&s=some+thing + + will result in two entries in the key value queue. + + The first entry is: key="q", value="test" + The second entry is: key="s", value="some thing" + + @param query_parse the query portion of the URI + @param headers the head of the evkeyval queue + @return 0 on success, -1 on failure + */ +EVENT2_EXPORT_SYMBOL +int evhttp_parse_query_str(const char *uri, struct evkeyvalq *headers); + +/** + * Escape HTML character entities in a string. + * + * Replaces <, >, ", ' and & with <, >, ", + * ' and & correspondingly. + * + * The returned string needs to be freed by the caller. + * + * @param html an unescaped HTML string + * @return an escaped HTML string or NULL on error + */ +EVENT2_EXPORT_SYMBOL +char *evhttp_htmlescape(const char *html); + +/** + * Return a new empty evhttp_uri with no fields set. + */ +EVENT2_EXPORT_SYMBOL +struct evhttp_uri *evhttp_uri_new(void); + +/** + * Changes the flags set on a given URI. See EVHTTP_URI_* for + * a list of flags. + **/ +EVENT2_EXPORT_SYMBOL +void evhttp_uri_set_flags(struct evhttp_uri *uri, unsigned flags); + +/** Return the scheme of an evhttp_uri, or NULL if there is no scheme has + * been set and the evhttp_uri contains a Relative-Ref. */ +EVENT2_EXPORT_SYMBOL +const char *evhttp_uri_get_scheme(const struct evhttp_uri *uri); +/** + * Return the userinfo part of an evhttp_uri, or NULL if it has no userinfo + * set. + */ +EVENT2_EXPORT_SYMBOL +const char *evhttp_uri_get_userinfo(const struct evhttp_uri *uri); +/** + * Return the host part of an evhttp_uri, or NULL if it has no host set. + * The host may either be a regular hostname (conforming to the RFC 3986 + * "regname" production), or an IPv4 address, or the empty string, or a + * bracketed IPv6 address, or a bracketed 'IP-Future' address. + * + * Note that having a NULL host means that the URI has no authority + * section, but having an empty-string host means that the URI has an + * authority section with no host part. For example, + * "mailto:user@example.com" has a host of NULL, but "file:///etc/motd" + * has a host of "". + */ +EVENT2_EXPORT_SYMBOL +const char *evhttp_uri_get_host(const struct evhttp_uri *uri); +/** Return the port part of an evhttp_uri, or -1 if there is no port set. */ +EVENT2_EXPORT_SYMBOL +int evhttp_uri_get_port(const struct evhttp_uri *uri); +/** Return the path part of an evhttp_uri, or NULL if it has no path set */ +EVENT2_EXPORT_SYMBOL +const char *evhttp_uri_get_path(const struct evhttp_uri *uri); +/** Return the query part of an evhttp_uri (excluding the leading "?"), or + * NULL if it has no query set */ +EVENT2_EXPORT_SYMBOL +const char *evhttp_uri_get_query(const struct evhttp_uri *uri); +/** Return the fragment part of an evhttp_uri (excluding the leading "#"), + * or NULL if it has no fragment set */ +EVENT2_EXPORT_SYMBOL +const char *evhttp_uri_get_fragment(const struct evhttp_uri *uri); + +/** Set the scheme of an evhttp_uri, or clear the scheme if scheme==NULL. + * Returns 0 on success, -1 if scheme is not well-formed. */ +EVENT2_EXPORT_SYMBOL +int evhttp_uri_set_scheme(struct evhttp_uri *uri, const char *scheme); +/** Set the userinfo of an evhttp_uri, or clear the userinfo if userinfo==NULL. + * Returns 0 on success, -1 if userinfo is not well-formed. */ +EVENT2_EXPORT_SYMBOL +int evhttp_uri_set_userinfo(struct evhttp_uri *uri, const char *userinfo); +/** Set the host of an evhttp_uri, or clear the host if host==NULL. + * Returns 0 on success, -1 if host is not well-formed. */ +EVENT2_EXPORT_SYMBOL +int evhttp_uri_set_host(struct evhttp_uri *uri, const char *host); +/** Set the port of an evhttp_uri, or clear the port if port==-1. + * Returns 0 on success, -1 if port is not well-formed. */ +EVENT2_EXPORT_SYMBOL +int evhttp_uri_set_port(struct evhttp_uri *uri, int port); +/** Set the path of an evhttp_uri, or clear the path if path==NULL. + * Returns 0 on success, -1 if path is not well-formed. */ +EVENT2_EXPORT_SYMBOL +int evhttp_uri_set_path(struct evhttp_uri *uri, const char *path); +/** Set the query of an evhttp_uri, or clear the query if query==NULL. + * The query should not include a leading "?". + * Returns 0 on success, -1 if query is not well-formed. */ +EVENT2_EXPORT_SYMBOL +int evhttp_uri_set_query(struct evhttp_uri *uri, const char *query); +/** Set the fragment of an evhttp_uri, or clear the fragment if fragment==NULL. + * The fragment should not include a leading "#". + * Returns 0 on success, -1 if fragment is not well-formed. */ +EVENT2_EXPORT_SYMBOL +int evhttp_uri_set_fragment(struct evhttp_uri *uri, const char *fragment); + +/** + * Helper function to parse a URI-Reference as specified by RFC3986. + * + * This function matches the URI-Reference production from RFC3986, + * which includes both URIs like + * + * scheme://[[userinfo]@]foo.com[:port]]/[path][?query][#fragment] + * + * and relative-refs like + * + * [path][?query][#fragment] + * + * Any optional elements portions not present in the original URI are + * left set to NULL in the resulting evhttp_uri. If no port is + * specified, the port is set to -1. + * + * Note that no decoding is performed on percent-escaped characters in + * the string; if you want to parse them, use evhttp_uridecode or + * evhttp_parse_query_str as appropriate. + * + * Note also that most URI schemes will have additional constraints that + * this function does not know about, and cannot check. For example, + * mailto://www.example.com/cgi-bin/fortune.pl is not a reasonable + * mailto url, http://www.example.com:99999/ is not a reasonable HTTP + * URL, and ftp:username@example.com is not a reasonable FTP URL. + * Nevertheless, all of these URLs conform to RFC3986, and this function + * accepts all of them as valid. + * + * @param source_uri the request URI + * @param flags Zero or more EVHTTP_URI_* flags to affect the behavior + * of the parser. + * @return uri container to hold parsed data, or NULL if there is error + * @see evhttp_uri_free() + */ +EVENT2_EXPORT_SYMBOL +struct evhttp_uri *evhttp_uri_parse_with_flags(const char *source_uri, + unsigned flags); + +/** Tolerate URIs that do not conform to RFC3986. + * + * Unfortunately, some HTTP clients generate URIs that, according to RFC3986, + * are not conformant URIs. If you need to support these URIs, you can + * do so by passing this flag to evhttp_uri_parse_with_flags. + * + * Currently, these changes are: + *
    + *
  • Nonconformant URIs are allowed to contain otherwise unreasonable + * characters in their path, query, and fragment components. + *
+ */ +#define EVHTTP_URI_NONCONFORMANT 0x01 + +/** Alias for evhttp_uri_parse_with_flags(source_uri, 0) */ +EVENT2_EXPORT_SYMBOL +struct evhttp_uri *evhttp_uri_parse(const char *source_uri); + +/** + * Free all memory allocated for a parsed uri. Only use this for URIs + * generated by evhttp_uri_parse. + * + * @param uri container with parsed data + * @see evhttp_uri_parse() + */ +EVENT2_EXPORT_SYMBOL +void evhttp_uri_free(struct evhttp_uri *uri); + +/** + * Join together the uri parts from parsed data to form a URI-Reference. + * + * Note that no escaping of reserved characters is done on the members + * of the evhttp_uri, so the generated string might not be a valid URI + * unless the members of evhttp_uri are themselves valid. + * + * @param uri container with parsed data + * @param buf destination buffer + * @param limit destination buffer size + * @return an joined uri as string or NULL on error + * @see evhttp_uri_parse() + */ +EVENT2_EXPORT_SYMBOL +char *evhttp_uri_join(struct evhttp_uri *uri, char *buf, size_t limit); + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_HTTP_H_INCLUDED_ */ diff --git a/platform/src/3rd/os_specific/oe2203/include/event2/http_compat.h b/platform/src/3rd/os_specific/oe2203/include/event2/http_compat.h new file mode 100644 index 00000000..43c2c43e --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/event2/http_compat.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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 EVENT2_HTTP_COMPAT_H_INCLUDED_ +#define EVENT2_HTTP_COMPAT_H_INCLUDED_ + +/** @file event2/http_compat.h + + Potentially non-threadsafe versions of the functions in http.h: provided + only for backwards compatibility. + + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef EVENT__HAVE_SYS_TYPES_H +#include +#endif +#ifdef EVENT__HAVE_SYS_TIME_H +#include +#endif + +/* For int types. */ +#include + +/** + * Start an HTTP server on the specified address and port + * + * @deprecated It does not allow an event base to be specified + * + * @param address the address to which the HTTP server should be bound + * @param port the port number on which the HTTP server should listen + * @return an struct evhttp object + */ +struct evhttp *evhttp_start(const char *address, ev_uint16_t port); + +/** + * A connection object that can be used to for making HTTP requests. The + * connection object tries to establish the connection when it is given an + * http request object. + * + * @deprecated It does not allow an event base to be specified + */ +struct evhttp_connection *evhttp_connection_new( + const char *address, ev_uint16_t port); + +/** + * Associates an event base with the connection - can only be called + * on a freshly created connection object that has not been used yet. + * + * @deprecated XXXX Why? + */ +void evhttp_connection_set_base(struct evhttp_connection *evcon, + struct event_base *base); + + +/** Returns the request URI */ +#define evhttp_request_uri evhttp_request_get_uri + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_EVENT_COMPAT_H_INCLUDED_ */ diff --git a/platform/src/3rd/os_specific/oe2203/include/event2/http_struct.h b/platform/src/3rd/os_specific/oe2203/include/event2/http_struct.h new file mode 100644 index 00000000..4bf5b1ff --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/event2/http_struct.h @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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 EVENT2_HTTP_STRUCT_H_INCLUDED_ +#define EVENT2_HTTP_STRUCT_H_INCLUDED_ + +/** @file event2/http_struct.h + + Data structures for http. Using these structures may hurt forward + compatibility with later versions of Libevent: be careful! + + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef EVENT__HAVE_SYS_TYPES_H +#include +#endif +#ifdef EVENT__HAVE_SYS_TIME_H +#include +#endif + +/* For int types. */ +#include + +/** + * the request structure that a server receives. + * WARNING: expect this structure to change. I will try to provide + * reasonable accessors. + */ +struct evhttp_request { +#if defined(TAILQ_ENTRY) + TAILQ_ENTRY(evhttp_request) next; +#else +struct { + struct evhttp_request *tqe_next; + struct evhttp_request **tqe_prev; +} next; +#endif + + /* the connection object that this request belongs to */ + struct evhttp_connection *evcon; + int flags; +/** The request obj owns the evhttp connection and needs to free it */ +#define EVHTTP_REQ_OWN_CONNECTION 0x0001 +/** Request was made via a proxy */ +#define EVHTTP_PROXY_REQUEST 0x0002 +/** The request object is owned by the user; the user must free it */ +#define EVHTTP_USER_OWNED 0x0004 +/** The request will be used again upstack; freeing must be deferred */ +#define EVHTTP_REQ_DEFER_FREE 0x0008 +/** The request should be freed upstack */ +#define EVHTTP_REQ_NEEDS_FREE 0x0010 + + struct evkeyvalq *input_headers; + struct evkeyvalq *output_headers; + + /* address of the remote host and the port connection came from */ + char *remote_host; + ev_uint16_t remote_port; + + /* cache of the hostname for evhttp_request_get_host */ + char *host_cache; + + enum evhttp_request_kind kind; + enum evhttp_cmd_type type; + + size_t headers_size; + size_t body_size; + + char *uri; /* uri after HTTP request was parsed */ + struct evhttp_uri *uri_elems; /* uri elements */ + + char major; /* HTTP Major number */ + char minor; /* HTTP Minor number */ + + int response_code; /* HTTP Response code */ + char *response_code_line; /* Readable response */ + + struct evbuffer *input_buffer; /* read data */ + ev_int64_t ntoread; + unsigned chunked:1, /* a chunked request */ + userdone:1; /* the user has sent all data */ + + struct evbuffer *output_buffer; /* outgoing post or data */ + + /* Callback */ + void (*cb)(struct evhttp_request *, void *); + void *cb_arg; + + /* + * Chunked data callback - call for each completed chunk if + * specified. If not specified, all the data is delivered via + * the regular callback. + */ + void (*chunk_cb)(struct evhttp_request *, void *); + + /* + * Callback added for forked-daapd so they can collect ICY + * (shoutcast) metadata from the http header. If return + * int is negative the connection will be closed. + */ + int (*header_cb)(struct evhttp_request *, void *); + + /* + * Error callback - called when error is occured. + * @see evhttp_request_error for error types. + * + * @see evhttp_request_set_error_cb() + */ + void (*error_cb)(enum evhttp_request_error, void *); + + /* + * Send complete callback - called when the request is actually + * sent and completed. + */ + void (*on_complete_cb)(struct evhttp_request *, void *); + void *on_complete_cb_arg; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_HTTP_STRUCT_H_INCLUDED_ */ + diff --git a/platform/src/3rd/os_specific/oe2203/include/event2/keyvalq_struct.h b/platform/src/3rd/os_specific/oe2203/include/event2/keyvalq_struct.h new file mode 100644 index 00000000..bffa54b3 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/event2/keyvalq_struct.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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 EVENT2_KEYVALQ_STRUCT_H_INCLUDED_ +#define EVENT2_KEYVALQ_STRUCT_H_INCLUDED_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Fix so that people don't have to run with */ +/* XXXX This code is duplicated with event_struct.h */ +#ifndef TAILQ_ENTRY +#define EVENT_DEFINED_TQENTRY_ +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} +#endif /* !TAILQ_ENTRY */ + +#ifndef TAILQ_HEAD +#define EVENT_DEFINED_TQHEAD_ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; \ + struct type **tqh_last; \ +} +#endif + +/* + * Key-Value pairs. Can be used for HTTP headers but also for + * query argument parsing. + */ +struct evkeyval { + TAILQ_ENTRY(evkeyval) next; + + char *key; + char *value; +}; + +TAILQ_HEAD (evkeyvalq, evkeyval); + +/* XXXX This code is duplicated with event_struct.h */ +#ifdef EVENT_DEFINED_TQENTRY_ +#undef TAILQ_ENTRY +#endif + +#ifdef EVENT_DEFINED_TQHEAD_ +#undef TAILQ_HEAD +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/src/3rd/os_specific/oe2203/include/event2/listener.h b/platform/src/3rd/os_specific/oe2203/include/event2/listener.h new file mode 100644 index 00000000..84b4da05 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/event2/listener.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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 EVENT2_LISTENER_H_INCLUDED_ +#define EVENT2_LISTENER_H_INCLUDED_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +struct sockaddr; +struct evconnlistener; + +/** + A callback that we invoke when a listener has a new connection. + + @param listener The evconnlistener + @param fd The new file descriptor + @param addr The source address of the connection + @param socklen The length of addr + @param user_arg the pointer passed to evconnlistener_new() + */ +typedef void (*evconnlistener_cb)(struct evconnlistener *, evutil_socket_t, struct sockaddr *, int socklen, void *); + +/** + A callback that we invoke when a listener encounters a non-retriable error. + + @param listener The evconnlistener + @param user_arg the pointer passed to evconnlistener_new() + */ +typedef void (*evconnlistener_errorcb)(struct evconnlistener *, void *); + +/** Flag: Indicates that we should not make incoming sockets nonblocking + * before passing them to the callback. */ +#define LEV_OPT_LEAVE_SOCKETS_BLOCKING (1u<<0) +/** Flag: Indicates that freeing the listener should close the underlying + * socket. */ +#define LEV_OPT_CLOSE_ON_FREE (1u<<1) +/** Flag: Indicates that we should set the close-on-exec flag, if possible */ +#define LEV_OPT_CLOSE_ON_EXEC (1u<<2) +/** Flag: Indicates that we should disable the timeout (if any) between when + * this socket is closed and when we can listen again on the same port. */ +#define LEV_OPT_REUSEABLE (1u<<3) +/** Flag: Indicates that the listener should be locked so it's safe to use + * from multiple threadcs at once. */ +#define LEV_OPT_THREADSAFE (1u<<4) +/** Flag: Indicates that the listener should be created in disabled + * state. Use evconnlistener_enable() to enable it later. */ +#define LEV_OPT_DISABLED (1u<<5) +/** Flag: Indicates that the listener should defer accept() until data is + * available, if possible. Ignored on platforms that do not support this. + * + * This option can help performance for protocols where the client transmits + * immediately after connecting. Do not use this option if your protocol + * _doesn't_ start out with the client transmitting data, since in that case + * this option will sometimes cause the kernel to never tell you about the + * connection. + * + * This option is only supported by evconnlistener_new_bind(): it can't + * work with evconnlistener_new_fd(), since the listener needs to be told + * to use the option before it is actually bound. + */ +#define LEV_OPT_DEFERRED_ACCEPT (1u<<6) +/** Flag: Indicates that we ask to allow multiple servers (processes or + * threads) to bind to the same port if they each set the option. + * + * SO_REUSEPORT is what most people would expect SO_REUSEADDR to be, however + * SO_REUSEPORT does not imply SO_REUSEADDR. + * + * This is only available on Linux and kernel 3.9+ + */ +#define LEV_OPT_REUSEABLE_PORT (1u<<7) + +/** + Allocate a new evconnlistener object to listen for incoming TCP connections + on a given file descriptor. + + @param base The event base to associate the listener with. + @param cb A callback to be invoked when a new connection arrives. If the + callback is NULL, the listener will be treated as disabled until the + callback is set. + @param ptr A user-supplied pointer to give to the callback. + @param flags Any number of LEV_OPT_* flags + @param backlog Passed to the listen() call to determine the length of the + acceptable connection backlog. Set to -1 for a reasonable default. + Set to 0 if the socket is already listening. + @param fd The file descriptor to listen on. It must be a nonblocking + file descriptor, and it should already be bound to an appropriate + port and address. +*/ +EVENT2_EXPORT_SYMBOL +struct evconnlistener *evconnlistener_new(struct event_base *base, + evconnlistener_cb cb, void *ptr, unsigned flags, int backlog, + evutil_socket_t fd); +/** + Allocate a new evconnlistener object to listen for incoming TCP connections + on a given address. + + @param base The event base to associate the listener with. + @param cb A callback to be invoked when a new connection arrives. If the + callback is NULL, the listener will be treated as disabled until the + callback is set. + @param ptr A user-supplied pointer to give to the callback. + @param flags Any number of LEV_OPT_* flags + @param backlog Passed to the listen() call to determine the length of the + acceptable connection backlog. Set to -1 for a reasonable default. + @param addr The address to listen for connections on. + @param socklen The length of the address. + */ +EVENT2_EXPORT_SYMBOL +struct evconnlistener *evconnlistener_new_bind(struct event_base *base, + evconnlistener_cb cb, void *ptr, unsigned flags, int backlog, + const struct sockaddr *sa, int socklen); +/** + Disable and deallocate an evconnlistener. + */ +EVENT2_EXPORT_SYMBOL +void evconnlistener_free(struct evconnlistener *lev); +/** + Re-enable an evconnlistener that has been disabled. + */ +EVENT2_EXPORT_SYMBOL +int evconnlistener_enable(struct evconnlistener *lev); +/** + Stop listening for connections on an evconnlistener. + */ +EVENT2_EXPORT_SYMBOL +int evconnlistener_disable(struct evconnlistener *lev); + +/** Return an evconnlistener's associated event_base. */ +EVENT2_EXPORT_SYMBOL +struct event_base *evconnlistener_get_base(struct evconnlistener *lev); + +/** Return the socket that an evconnlistner is listening on. */ +EVENT2_EXPORT_SYMBOL +evutil_socket_t evconnlistener_get_fd(struct evconnlistener *lev); + +/** Change the callback on the listener to cb and its user_data to arg. + */ +EVENT2_EXPORT_SYMBOL +void evconnlistener_set_cb(struct evconnlistener *lev, + evconnlistener_cb cb, void *arg); + +/** Set an evconnlistener's error callback. */ +EVENT2_EXPORT_SYMBOL +void evconnlistener_set_error_cb(struct evconnlistener *lev, + evconnlistener_errorcb errorcb); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/src/3rd/os_specific/oe2203/include/event2/rpc.h b/platform/src/3rd/os_specific/oe2203/include/event2/rpc.h new file mode 100644 index 00000000..dd43df26 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/event2/rpc.h @@ -0,0 +1,596 @@ +/* + * Copyright (c) 2006-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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 EVENT2_RPC_H_INCLUDED_ +#define EVENT2_RPC_H_INCLUDED_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @file rpc.h + * + * This header files provides basic support for an RPC server and client. + * + * To support RPCs in a server, every supported RPC command needs to be + * defined and registered. + * + * EVRPC_HEADER(SendCommand, Request, Reply); + * + * SendCommand is the name of the RPC command. + * Request is the name of a structure generated by event_rpcgen.py. + * It contains all parameters relating to the SendCommand RPC. The + * server needs to fill in the Reply structure. + * Reply is the name of a structure generated by event_rpcgen.py. It + * contains the answer to the RPC. + * + * To register an RPC with an HTTP server, you need to first create an RPC + * base with: + * + * struct evrpc_base *base = evrpc_init(http); + * + * A specific RPC can then be registered with + * + * EVRPC_REGISTER(base, SendCommand, Request, Reply, FunctionCB, arg); + * + * when the server receives an appropriately formatted RPC, the user callback + * is invoked. The callback needs to fill in the reply structure. + * + * void FunctionCB(EVRPC_STRUCT(SendCommand)* rpc, void *arg); + * + * To send the reply, call EVRPC_REQUEST_DONE(rpc); + * + * See the regression test for an example. + */ + +/** + Determines if the member has been set in the message + + @param msg the message to inspect + @param member the member variable to test for presences + @return 1 if it's present or 0 otherwise. +*/ +#define EVTAG_HAS(msg, member) \ + ((msg)->member##_set == 1) + +#ifndef EVENT2_RPC_COMPAT_H_INCLUDED_ + +/** + Assigns a value to the member in the message. + + @param msg the message to which to assign a value + @param member the name of the member variable + @param value the value to assign +*/ +#define EVTAG_ASSIGN(msg, member, value) \ + (*(msg)->base->member##_assign)((msg), (value)) +/** + Assigns a value to the member in the message. + + @param msg the message to which to assign a value + @param member the name of the member variable + @param value the value to assign + @param len the length of the value +*/ +#define EVTAG_ASSIGN_WITH_LEN(msg, member, value, len) \ + (*(msg)->base->member##_assign)((msg), (value), (len)) +/** + Returns the value for a member. + + @param msg the message from which to get the value + @param member the name of the member variable + @param pvalue a pointer to the variable to hold the value + @return 0 on success, -1 otherwise. +*/ +#define EVTAG_GET(msg, member, pvalue) \ + (*(msg)->base->member##_get)((msg), (pvalue)) +/** + Returns the value for a member. + + @param msg the message from which to get the value + @param member the name of the member variable + @param pvalue a pointer to the variable to hold the value + @param plen a pointer to the length of the value + @return 0 on success, -1 otherwise. +*/ +#define EVTAG_GET_WITH_LEN(msg, member, pvalue, plen) \ + (*(msg)->base->member##_get)((msg), (pvalue), (plen)) + +#endif /* EVENT2_RPC_COMPAT_H_INCLUDED_ */ + +/** + Adds a value to an array. +*/ +#define EVTAG_ARRAY_ADD_VALUE(msg, member, value) \ + (*(msg)->base->member##_add)((msg), (value)) +/** + Allocates a new entry in the array and returns it. +*/ +#define EVTAG_ARRAY_ADD(msg, member) \ + (*(msg)->base->member##_add)(msg) +/** + Gets a variable at the specified offset from the array. +*/ +#define EVTAG_ARRAY_GET(msg, member, offset, pvalue) \ + (*(msg)->base->member##_get)((msg), (offset), (pvalue)) +/** + Returns the number of entries in the array. +*/ +#define EVTAG_ARRAY_LEN(msg, member) ((msg)->member##_length) + + +struct evbuffer; +struct event_base; +struct evrpc_req_generic; +struct evrpc_request_wrapper; +struct evrpc; + +/** The type of a specific RPC Message + * + * @param rpcname the name of the RPC message + */ +#define EVRPC_STRUCT(rpcname) struct evrpc_req__##rpcname + +struct evhttp_request; +struct evrpc_status; +struct evrpc_hook_meta; + +/** Creates the definitions and prototypes for an RPC + * + * You need to use EVRPC_HEADER to create structures and function prototypes + * needed by the server and client implementation. The structures have to be + * defined in an .rpc file and converted to source code via event_rpcgen.py + * + * @param rpcname the name of the RPC + * @param reqstruct the name of the RPC request structure + * @param replystruct the name of the RPC reply structure + * @see EVRPC_GENERATE() + */ +#define EVRPC_HEADER(rpcname, reqstruct, rplystruct) \ +EVRPC_STRUCT(rpcname) { \ + struct evrpc_hook_meta *hook_meta; \ + struct reqstruct* request; \ + struct rplystruct* reply; \ + struct evrpc* rpc; \ + struct evhttp_request* http_req; \ + struct evbuffer* rpc_data; \ +}; \ +int evrpc_send_request_##rpcname(struct evrpc_pool *, \ + struct reqstruct *, struct rplystruct *, \ + void (*)(struct evrpc_status *, \ + struct reqstruct *, struct rplystruct *, void *cbarg), \ + void *); + +struct evrpc_pool; + +/** use EVRPC_GENERATE instead */ +struct evrpc_request_wrapper *evrpc_make_request_ctx( + struct evrpc_pool *pool, void *request, void *reply, + const char *rpcname, + void (*req_marshal)(struct evbuffer*, void *), + void (*rpl_clear)(void *), + int (*rpl_unmarshal)(void *, struct evbuffer *), + void (*cb)(struct evrpc_status *, void *, void *, void *), + void *cbarg); + +/** Creates a context structure that contains rpc specific information. + * + * EVRPC_MAKE_CTX is used to populate a RPC specific context that + * contains information about marshaling the RPC data types. + * + * @param rpcname the name of the RPC + * @param reqstruct the name of the RPC request structure + * @param replystruct the name of the RPC reply structure + * @param pool the evrpc_pool over which to make the request + * @param request a pointer to the RPC request structure object + * @param reply a pointer to the RPC reply structure object + * @param cb the callback function to call when the RPC has completed + * @param cbarg the argument to supply to the callback + */ +#define EVRPC_MAKE_CTX(rpcname, reqstruct, rplystruct, \ + pool, request, reply, cb, cbarg) \ + evrpc_make_request_ctx(pool, request, reply, \ + #rpcname, \ + (void (*)(struct evbuffer *, void *))reqstruct##_marshal, \ + (void (*)(void *))rplystruct##_clear, \ + (int (*)(void *, struct evbuffer *))rplystruct##_unmarshal, \ + (void (*)(struct evrpc_status *, void *, void *, void *))cb, \ + cbarg) + +/** Generates the code for receiving and sending an RPC message + * + * EVRPC_GENERATE is used to create the code corresponding to sending + * and receiving a particular RPC message + * + * @param rpcname the name of the RPC + * @param reqstruct the name of the RPC request structure + * @param replystruct the name of the RPC reply structure + * @see EVRPC_HEADER() + */ +#define EVRPC_GENERATE(rpcname, reqstruct, rplystruct) \ + int evrpc_send_request_##rpcname(struct evrpc_pool *pool, \ + struct reqstruct *request, struct rplystruct *reply, \ + void (*cb)(struct evrpc_status *, \ + struct reqstruct *, struct rplystruct *, void *cbarg), \ + void *cbarg) { \ + return evrpc_send_request_generic(pool, request, reply, \ + (void (*)(struct evrpc_status *, void *, void *, void *))cb, \ + cbarg, \ + #rpcname, \ + (void (*)(struct evbuffer *, void *))reqstruct##_marshal, \ + (void (*)(void *))rplystruct##_clear, \ + (int (*)(void *, struct evbuffer *))rplystruct##_unmarshal); \ +} + +/** Provides access to the HTTP request object underlying an RPC + * + * Access to the underlying http object; can be used to look at headers or + * for getting the remote ip address + * + * @param rpc_req the rpc request structure provided to the server callback + * @return an struct evhttp_request object that can be inspected for + * HTTP headers or sender information. + */ +#define EVRPC_REQUEST_HTTP(rpc_req) (rpc_req)->http_req + +/** completes the server response to an rpc request */ +void evrpc_request_done(struct evrpc_req_generic *req); + +/** accessors for request and reply */ +void *evrpc_get_request(struct evrpc_req_generic *req); +void *evrpc_get_reply(struct evrpc_req_generic *req); + +/** Creates the reply to an RPC request + * + * EVRPC_REQUEST_DONE is used to answer a request; the reply is expected + * to have been filled in. The request and reply pointers become invalid + * after this call has finished. + * + * @param rpc_req the rpc request structure provided to the server callback + */ +#define EVRPC_REQUEST_DONE(rpc_req) do { \ + struct evrpc_req_generic *req_ = (struct evrpc_req_generic *)(rpc_req); \ + evrpc_request_done(req_); \ +} while (0) + + +struct evrpc_base; +struct evhttp; + +/* functions to start up the rpc system */ + +/** Creates a new rpc base from which RPC requests can be received + * + * @param server a pointer to an existing HTTP server + * @return a newly allocated evrpc_base struct + * @see evrpc_free() + */ +struct evrpc_base *evrpc_init(struct evhttp *server); + +/** + * Frees the evrpc base + * + * For now, you are responsible for making sure that no rpcs are ongoing. + * + * @param base the evrpc_base object to be freed + * @see evrpc_init + */ +void evrpc_free(struct evrpc_base *base); + +/** register RPCs with the HTTP Server + * + * registers a new RPC with the HTTP server, each RPC needs to have + * a unique name under which it can be identified. + * + * @param base the evrpc_base structure in which the RPC should be + * registered. + * @param name the name of the RPC + * @param request the name of the RPC request structure + * @param reply the name of the RPC reply structure + * @param callback the callback that should be invoked when the RPC + * is received. The callback has the following prototype + * void (*callback)(EVRPC_STRUCT(Message)* rpc, void *arg) + * @param cbarg an additional parameter that can be passed to the callback. + * The parameter can be used to carry around state. + */ +#define EVRPC_REGISTER(base, name, request, reply, callback, cbarg) \ + evrpc_register_generic(base, #name, \ + (void (*)(struct evrpc_req_generic *, void *))callback, cbarg, \ + (void *(*)(void *))request##_new, NULL, \ + (void (*)(void *))request##_free, \ + (int (*)(void *, struct evbuffer *))request##_unmarshal, \ + (void *(*)(void *))reply##_new, NULL, \ + (void (*)(void *))reply##_free, \ + (int (*)(void *))reply##_complete, \ + (void (*)(struct evbuffer *, void *))reply##_marshal) + +/** + Low level function for registering an RPC with a server. + + Use EVRPC_REGISTER() instead. + + @see EVRPC_REGISTER() +*/ +int evrpc_register_rpc(struct evrpc_base *, struct evrpc *, + void (*)(struct evrpc_req_generic*, void *), void *); + +/** + * Unregisters an already registered RPC + * + * @param base the evrpc_base object from which to unregister an RPC + * @param name the name of the rpc to unregister + * @return -1 on error or 0 when successful. + * @see EVRPC_REGISTER() + */ +#define EVRPC_UNREGISTER(base, name) evrpc_unregister_rpc((base), #name) + +int evrpc_unregister_rpc(struct evrpc_base *base, const char *name); + +/* + * Client-side RPC support + */ + +struct evhttp_connection; +struct evrpc_status; + +/** launches an RPC and sends it to the server + * + * EVRPC_MAKE_REQUEST() is used by the client to send an RPC to the server. + * + * @param name the name of the RPC + * @param pool the evrpc_pool that contains the connection objects over which + * the request should be sent. + * @param request a pointer to the RPC request structure - it contains the + * data to be sent to the server. + * @param reply a pointer to the RPC reply structure. It is going to be filled + * if the request was answered successfully + * @param cb the callback to invoke when the RPC request has been answered + * @param cbarg an additional argument to be passed to the client + * @return 0 on success, -1 on failure + */ +#define EVRPC_MAKE_REQUEST(name, pool, request, reply, cb, cbarg) \ + evrpc_send_request_##name((pool), (request), (reply), (cb), (cbarg)) + +/** + Makes an RPC request based on the provided context. + + This is a low-level function and should not be used directly + unless a custom context object is provided. Use EVRPC_MAKE_REQUEST() + instead. + + @param ctx a context from EVRPC_MAKE_CTX() + @returns 0 on success, -1 otherwise. + @see EVRPC_MAKE_REQUEST(), EVRPC_MAKE_CTX() +*/ +int evrpc_make_request(struct evrpc_request_wrapper *ctx); + +/** creates an rpc connection pool + * + * a pool has a number of connections associated with it. + * rpc requests are always made via a pool. + * + * @param base a pointer to an struct event_based object; can be left NULL + * in singled-threaded applications + * @return a newly allocated struct evrpc_pool object + * @see evrpc_pool_free() + */ +struct evrpc_pool *evrpc_pool_new(struct event_base *base); +/** frees an rpc connection pool + * + * @param pool a pointer to an evrpc_pool allocated via evrpc_pool_new() + * @see evrpc_pool_new() + */ +void evrpc_pool_free(struct evrpc_pool *pool); + +/** + * Adds a connection over which rpc can be dispatched to the pool. + * + * The connection object must have been newly created. + * + * @param pool the pool to which to add the connection + * @param evcon the connection to add to the pool. + */ +void evrpc_pool_add_connection(struct evrpc_pool *pool, + struct evhttp_connection *evcon); + +/** + * Removes a connection from the pool. + * + * The connection object must have been newly created. + * + * @param pool the pool from which to remove the connection + * @param evcon the connection to remove from the pool. + */ +void evrpc_pool_remove_connection(struct evrpc_pool *pool, + struct evhttp_connection *evcon); + +/** + * Sets the timeout in secs after which a request has to complete. The + * RPC is completely aborted if it does not complete by then. Setting + * the timeout to 0 means that it never timeouts and can be used to + * implement callback type RPCs. + * + * Any connection already in the pool will be updated with the new + * timeout. Connections added to the pool after set_timeout has be + * called receive the pool timeout only if no timeout has been set + * for the connection itself. + * + * @param pool a pointer to a struct evrpc_pool object + * @param timeout_in_secs the number of seconds after which a request should + * timeout and a failure be returned to the callback. + */ +void evrpc_pool_set_timeout(struct evrpc_pool *pool, int timeout_in_secs); + +/** + * Hooks for changing the input and output of RPCs; this can be used to + * implement compression, authentication, encryption, ... + */ + +enum EVRPC_HOOK_TYPE { + EVRPC_INPUT, /**< apply the function to an input hook */ + EVRPC_OUTPUT /**< apply the function to an output hook */ +}; + +#ifndef _WIN32 +/** Deprecated alias for EVRPC_INPUT. Not available on windows, where it + * conflicts with platform headers. */ +#define INPUT EVRPC_INPUT +/** Deprecated alias for EVRPC_OUTPUT. Not available on windows, where it + * conflicts with platform headers. */ +#define OUTPUT EVRPC_OUTPUT +#endif + +/** + * Return value from hook processing functions + */ + +enum EVRPC_HOOK_RESULT { + EVRPC_TERMINATE = -1, /**< indicates the rpc should be terminated */ + EVRPC_CONTINUE = 0, /**< continue processing the rpc */ + EVRPC_PAUSE = 1 /**< pause processing request until resumed */ +}; + +/** adds a processing hook to either an rpc base or rpc pool + * + * If a hook returns TERMINATE, the processing is aborted. On CONTINUE, + * the request is immediately processed after the hook returns. If the + * hook returns PAUSE, request processing stops until evrpc_resume_request() + * has been called. + * + * The add functions return handles that can be used for removing hooks. + * + * @param vbase a pointer to either struct evrpc_base or struct evrpc_pool + * @param hook_type either INPUT or OUTPUT + * @param cb the callback to call when the hook is activated + * @param cb_arg an additional argument for the callback + * @return a handle to the hook so it can be removed later + * @see evrpc_remove_hook() + */ +void *evrpc_add_hook(void *vbase, + enum EVRPC_HOOK_TYPE hook_type, + int (*cb)(void *, struct evhttp_request *, struct evbuffer *, void *), + void *cb_arg); + +/** removes a previously added hook + * + * @param vbase a pointer to either struct evrpc_base or struct evrpc_pool + * @param hook_type either INPUT or OUTPUT + * @param handle a handle returned by evrpc_add_hook() + * @return 1 on success or 0 on failure + * @see evrpc_add_hook() + */ +int evrpc_remove_hook(void *vbase, + enum EVRPC_HOOK_TYPE hook_type, + void *handle); + +/** resume a paused request + * + * @param vbase a pointer to either struct evrpc_base or struct evrpc_pool + * @param ctx the context pointer provided to the original hook call + */ +int +evrpc_resume_request(void *vbase, void *ctx, enum EVRPC_HOOK_RESULT res); + +/** adds meta data to request + * + * evrpc_hook_add_meta() allows hooks to add meta data to a request. for + * a client request, the meta data can be inserted by an outgoing request hook + * and retrieved by the incoming request hook. + * + * @param ctx the context provided to the hook call + * @param key a NUL-terminated c-string + * @param data the data to be associated with the key + * @param data_size the size of the data + */ +void evrpc_hook_add_meta(void *ctx, const char *key, + const void *data, size_t data_size); + +/** retrieves meta data previously associated + * + * evrpc_hook_find_meta() can be used to retrieve meta data associated to a + * request by a previous hook. + * @param ctx the context provided to the hook call + * @param key a NUL-terminated c-string + * @param data pointer to a data pointer that will contain the retrieved data + * @param data_size pointer to the size of the data + * @return 0 on success or -1 on failure + */ +int evrpc_hook_find_meta(void *ctx, const char *key, + void **data, size_t *data_size); + +/** + * returns the connection object associated with the request + * + * @param ctx the context provided to the hook call + * @return a pointer to the evhttp_connection object + */ +struct evhttp_connection *evrpc_hook_get_connection(void *ctx); + +/** + Function for sending a generic RPC request. + + Do not call this function directly, use EVRPC_MAKE_REQUEST() instead. + + @see EVRPC_MAKE_REQUEST() + */ +int evrpc_send_request_generic(struct evrpc_pool *pool, + void *request, void *reply, + void (*cb)(struct evrpc_status *, void *, void *, void *), + void *cb_arg, + const char *rpcname, + void (*req_marshal)(struct evbuffer *, void *), + void (*rpl_clear)(void *), + int (*rpl_unmarshal)(void *, struct evbuffer *)); + +/** + Function for registering a generic RPC with the RPC base. + + Do not call this function directly, use EVRPC_REGISTER() instead. + + @see EVRPC_REGISTER() + */ +int +evrpc_register_generic(struct evrpc_base *base, const char *name, + void (*callback)(struct evrpc_req_generic *, void *), void *cbarg, + void *(*req_new)(void *), void *req_new_arg, void (*req_free)(void *), + int (*req_unmarshal)(void *, struct evbuffer *), + void *(*rpl_new)(void *), void *rpl_new_arg, void (*rpl_free)(void *), + int (*rpl_complete)(void *), + void (*rpl_marshal)(struct evbuffer *, void *)); + +/** accessors for obscure and undocumented functionality */ +struct evrpc_pool* evrpc_request_get_pool(struct evrpc_request_wrapper *ctx); +void evrpc_request_set_pool(struct evrpc_request_wrapper *ctx, + struct evrpc_pool *pool); +void evrpc_request_set_cb(struct evrpc_request_wrapper *ctx, + void (*cb)(struct evrpc_status*, void *request, void *reply, void *arg), + void *cb_arg); + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_RPC_H_INCLUDED_ */ diff --git a/platform/src/3rd/os_specific/oe2203/include/event2/rpc_compat.h b/platform/src/3rd/os_specific/oe2203/include/event2/rpc_compat.h new file mode 100644 index 00000000..8d8334d2 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/event2/rpc_compat.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2006-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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 EVENT2_RPC_COMPAT_H_INCLUDED_ +#define EVENT2_RPC_COMPAT_H_INCLUDED_ + +/** @file event2/rpc_compat.h + + Deprecated versions of the functions in rpc.h: provided only for + backwards compatibility. + + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** backwards compatible accessors that work only with gcc */ +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) + +#undef EVTAG_ASSIGN +#undef EVTAG_GET +#undef EVTAG_ADD + +#define EVTAG_ASSIGN(msg, member, args...) \ + (*(msg)->base->member##_assign)(msg, ## args) +#define EVTAG_GET(msg, member, args...) \ + (*(msg)->base->member##_get)(msg, ## args) +#define EVTAG_ADD(msg, member, args...) \ + (*(msg)->base->member##_add)(msg, ## args) +#endif +#define EVTAG_LEN(msg, member) ((msg)->member##_length) + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_EVENT_COMPAT_H_INCLUDED_ */ diff --git a/platform/src/3rd/os_specific/oe2203/include/event2/rpc_struct.h b/platform/src/3rd/os_specific/oe2203/include/event2/rpc_struct.h new file mode 100644 index 00000000..8f691f49 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/event2/rpc_struct.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2006-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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 EVENT2_RPC_STRUCT_H_INCLUDED_ +#define EVENT2_RPC_STRUCT_H_INCLUDED_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @file event2/rpc_struct.h + + Structures used by rpc.h. Using these structures directly may harm + forward compatibility: be careful! + + */ + +/** + * provides information about the completed RPC request. + */ +struct evrpc_status { +#define EVRPC_STATUS_ERR_NONE 0 +#define EVRPC_STATUS_ERR_TIMEOUT 1 +#define EVRPC_STATUS_ERR_BADPAYLOAD 2 +#define EVRPC_STATUS_ERR_UNSTARTED 3 +#define EVRPC_STATUS_ERR_HOOKABORTED 4 + int error; + + /* for looking at headers or other information */ + struct evhttp_request *http_req; +}; + +/* the structure below needs to be synchronized with evrpc_req_generic */ + +/* Encapsulates a request */ +struct evrpc { + TAILQ_ENTRY(evrpc) next; + + /* the URI at which the request handler lives */ + const char* uri; + + /* creates a new request structure */ + void *(*request_new)(void *); + void *request_new_arg; + + /* frees the request structure */ + void (*request_free)(void *); + + /* unmarshals the buffer into the proper request structure */ + int (*request_unmarshal)(void *, struct evbuffer *); + + /* creates a new reply structure */ + void *(*reply_new)(void *); + void *reply_new_arg; + + /* frees the reply structure */ + void (*reply_free)(void *); + + /* verifies that the reply is valid */ + int (*reply_complete)(void *); + + /* marshals the reply into a buffer */ + void (*reply_marshal)(struct evbuffer*, void *); + + /* the callback invoked for each received rpc */ + void (*cb)(struct evrpc_req_generic *, void *); + void *cb_arg; + + /* reference for further configuration */ + struct evrpc_base *base; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_RPC_STRUCT_H_INCLUDED_ */ diff --git a/platform/src/3rd/os_specific/oe2203/include/event2/tag.h b/platform/src/3rd/os_specific/oe2203/include/event2/tag.h new file mode 100644 index 00000000..2f73bfc0 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/event2/tag.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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 EVENT2_TAG_H_INCLUDED_ +#define EVENT2_TAG_H_INCLUDED_ + +/** @file event2/tag.h + + Helper functions for reading and writing tagged data onto buffers. + + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef EVENT__HAVE_SYS_TYPES_H +#include +#endif +#ifdef EVENT__HAVE_SYS_TIME_H +#include +#endif + +/* For int types. */ +#include + +struct evbuffer; + +/* + * Marshaling tagged data - We assume that all tags are inserted in their + * numeric order - so that unknown tags will always be higher than the + * known ones - and we can just ignore the end of an event buffer. + */ + +EVENT2_EXPORT_SYMBOL +void evtag_init(void); + +/** + Unmarshals the header and returns the length of the payload + + @param evbuf the buffer from which to unmarshal data + @param ptag a pointer in which the tag id is being stored + @returns -1 on failure or the number of bytes in the remaining payload. +*/ +EVENT2_EXPORT_SYMBOL +int evtag_unmarshal_header(struct evbuffer *evbuf, ev_uint32_t *ptag); + +EVENT2_EXPORT_SYMBOL +void evtag_marshal(struct evbuffer *evbuf, ev_uint32_t tag, const void *data, + ev_uint32_t len); +EVENT2_EXPORT_SYMBOL +void evtag_marshal_buffer(struct evbuffer *evbuf, ev_uint32_t tag, + struct evbuffer *data); + +/** + Encode an integer and store it in an evbuffer. + + We encode integers by nybbles; the first nibble contains the number + of significant nibbles - 1; this allows us to encode up to 64-bit + integers. This function is byte-order independent. + + @param evbuf evbuffer to store the encoded number + @param number a 32-bit integer + */ +EVENT2_EXPORT_SYMBOL +void evtag_encode_int(struct evbuffer *evbuf, ev_uint32_t number); +EVENT2_EXPORT_SYMBOL +void evtag_encode_int64(struct evbuffer *evbuf, ev_uint64_t number); + +EVENT2_EXPORT_SYMBOL +void evtag_marshal_int(struct evbuffer *evbuf, ev_uint32_t tag, + ev_uint32_t integer); +EVENT2_EXPORT_SYMBOL +void evtag_marshal_int64(struct evbuffer *evbuf, ev_uint32_t tag, + ev_uint64_t integer); + +EVENT2_EXPORT_SYMBOL +void evtag_marshal_string(struct evbuffer *buf, ev_uint32_t tag, + const char *string); + +EVENT2_EXPORT_SYMBOL +void evtag_marshal_timeval(struct evbuffer *evbuf, ev_uint32_t tag, + struct timeval *tv); + +EVENT2_EXPORT_SYMBOL +int evtag_unmarshal(struct evbuffer *src, ev_uint32_t *ptag, + struct evbuffer *dst); +EVENT2_EXPORT_SYMBOL +int evtag_peek(struct evbuffer *evbuf, ev_uint32_t *ptag); +EVENT2_EXPORT_SYMBOL +int evtag_peek_length(struct evbuffer *evbuf, ev_uint32_t *plength); +EVENT2_EXPORT_SYMBOL +int evtag_payload_length(struct evbuffer *evbuf, ev_uint32_t *plength); +EVENT2_EXPORT_SYMBOL +int evtag_consume(struct evbuffer *evbuf); + +EVENT2_EXPORT_SYMBOL +int evtag_unmarshal_int(struct evbuffer *evbuf, ev_uint32_t need_tag, + ev_uint32_t *pinteger); +EVENT2_EXPORT_SYMBOL +int evtag_unmarshal_int64(struct evbuffer *evbuf, ev_uint32_t need_tag, + ev_uint64_t *pinteger); + +EVENT2_EXPORT_SYMBOL +int evtag_unmarshal_fixed(struct evbuffer *src, ev_uint32_t need_tag, + void *data, size_t len); + +EVENT2_EXPORT_SYMBOL +int evtag_unmarshal_string(struct evbuffer *evbuf, ev_uint32_t need_tag, + char **pstring); + +EVENT2_EXPORT_SYMBOL +int evtag_unmarshal_timeval(struct evbuffer *evbuf, ev_uint32_t need_tag, + struct timeval *ptv); + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_TAG_H_INCLUDED_ */ diff --git a/platform/src/3rd/os_specific/oe2203/include/event2/tag_compat.h b/platform/src/3rd/os_specific/oe2203/include/event2/tag_compat.h new file mode 100644 index 00000000..a276c0d3 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/event2/tag_compat.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2000-2007 Niels Provos + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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 EVENT2_TAG_COMPAT_H_INCLUDED_ +#define EVENT2_TAG_COMPAT_H_INCLUDED_ + +/** @file event2/tag_compat.h + + Obsolete/deprecated functions from tag.h; provided only for backwards + compatibility. + */ + +/** + @name Misnamed functions + + @deprecated These macros are deprecated because their names don't follow + Libevent's naming conventions. Use evtag_encode_int and + evtag_encode_int64 instead. + + @{ +*/ +#define encode_int(evbuf, number) evtag_encode_int((evbuf), (number)) +#define encode_int64(evbuf, number) evtag_encode_int64((evbuf), (number)) +/**@}*/ + +#endif /* EVENT2_TAG_H_INCLUDED_ */ diff --git a/platform/src/3rd/os_specific/oe2203/include/event2/thread.h b/platform/src/3rd/os_specific/oe2203/include/event2/thread.h new file mode 100644 index 00000000..b5199863 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/event2/thread.h @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2008-2012 Niels Provos and Nick Mathewson + * + * 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 EVENT2_THREAD_H_INCLUDED_ +#define EVENT2_THREAD_H_INCLUDED_ + +/** @file event2/thread.h + + Functions for multi-threaded applications using Libevent. + + When using a multi-threaded application in which multiple threads + add and delete events from a single event base, Libevent needs to + lock its data structures. + + Like the memory-management function hooks, all of the threading functions + _must_ be set up before an event_base is created if you want the base to + use them. + + Most programs will either be using Windows threads or Posix threads. You + can configure Libevent to use one of these event_use_windows_threads() or + event_use_pthreads() respectively. If you're using another threading + library, you'll need to configure threading functions manually using + evthread_set_lock_callbacks() and evthread_set_condition_callbacks(). + + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/** + @name Flags passed to lock functions + + @{ +*/ +/** A flag passed to a locking callback when the lock was allocated as a + * read-write lock, and we want to acquire or release the lock for writing. */ +#define EVTHREAD_WRITE 0x04 +/** A flag passed to a locking callback when the lock was allocated as a + * read-write lock, and we want to acquire or release the lock for reading. */ +#define EVTHREAD_READ 0x08 +/** A flag passed to a locking callback when we don't want to block waiting + * for the lock; if we can't get the lock immediately, we will instead + * return nonzero from the locking callback. */ +#define EVTHREAD_TRY 0x10 +/**@}*/ + +#if !defined(EVENT__DISABLE_THREAD_SUPPORT) || defined(EVENT_IN_DOXYGEN_) + +#define EVTHREAD_LOCK_API_VERSION 1 + +/** + @name Types of locks + + @{*/ +/** A recursive lock is one that can be acquired multiple times at once by the + * same thread. No other process can allocate the lock until the thread that + * has been holding it has unlocked it as many times as it locked it. */ +#define EVTHREAD_LOCKTYPE_RECURSIVE 1 +/* A read-write lock is one that allows multiple simultaneous readers, but + * where any one writer excludes all other writers and readers. */ +#define EVTHREAD_LOCKTYPE_READWRITE 2 +/**@}*/ + +/** This structure describes the interface a threading library uses for + * locking. It's used to tell evthread_set_lock_callbacks() how to use + * locking on this platform. + */ +struct evthread_lock_callbacks { + /** The current version of the locking API. Set this to + * EVTHREAD_LOCK_API_VERSION */ + int lock_api_version; + /** Which kinds of locks does this version of the locking API + * support? A bitfield of EVTHREAD_LOCKTYPE_RECURSIVE and + * EVTHREAD_LOCKTYPE_READWRITE. + * + * (Note that RECURSIVE locks are currently mandatory, and + * READWRITE locks are not currently used.) + **/ + unsigned supported_locktypes; + /** Function to allocate and initialize new lock of type 'locktype'. + * Returns NULL on failure. */ + void *(*alloc)(unsigned locktype); + /** Funtion to release all storage held in 'lock', which was created + * with type 'locktype'. */ + void (*free)(void *lock, unsigned locktype); + /** Acquire an already-allocated lock at 'lock' with mode 'mode'. + * Returns 0 on success, and nonzero on failure. */ + int (*lock)(unsigned mode, void *lock); + /** Release a lock at 'lock' using mode 'mode'. Returns 0 on success, + * and nonzero on failure. */ + int (*unlock)(unsigned mode, void *lock); +}; + +/** Sets a group of functions that Libevent should use for locking. + * For full information on the required callback API, see the + * documentation for the individual members of evthread_lock_callbacks. + * + * Note that if you're using Windows or the Pthreads threading library, you + * probably shouldn't call this function; instead, use + * evthread_use_windows_threads() or evthread_use_posix_threads() if you can. + */ +EVENT2_EXPORT_SYMBOL +int evthread_set_lock_callbacks(const struct evthread_lock_callbacks *); + +#define EVTHREAD_CONDITION_API_VERSION 1 + +struct timeval; + +/** This structure describes the interface a threading library uses for + * condition variables. It's used to tell evthread_set_condition_callbacks + * how to use locking on this platform. + */ +struct evthread_condition_callbacks { + /** The current version of the conditions API. Set this to + * EVTHREAD_CONDITION_API_VERSION */ + int condition_api_version; + /** Function to allocate and initialize a new condition variable. + * Returns the condition variable on success, and NULL on failure. + * The 'condtype' argument will be 0 with this API version. + */ + void *(*alloc_condition)(unsigned condtype); + /** Function to free a condition variable. */ + void (*free_condition)(void *cond); + /** Function to signal a condition variable. If 'broadcast' is 1, all + * threads waiting on 'cond' should be woken; otherwise, only on one + * thread is worken. Should return 0 on success, -1 on failure. + * This function will only be called while holding the associated + * lock for the condition. + */ + int (*signal_condition)(void *cond, int broadcast); + /** Function to wait for a condition variable. The lock 'lock' + * will be held when this function is called; should be released + * while waiting for the condition to be come signalled, and + * should be held again when this function returns. + * If timeout is provided, it is interval of seconds to wait for + * the event to become signalled; if it is NULL, the function + * should wait indefinitely. + * + * The function should return -1 on error; 0 if the condition + * was signalled, or 1 on a timeout. */ + int (*wait_condition)(void *cond, void *lock, + const struct timeval *timeout); +}; + +/** Sets a group of functions that Libevent should use for condition variables. + * For full information on the required callback API, see the + * documentation for the individual members of evthread_condition_callbacks. + * + * Note that if you're using Windows or the Pthreads threading library, you + * probably shouldn't call this function; instead, use + * evthread_use_windows_threads() or evthread_use_pthreads() if you can. + */ +EVENT2_EXPORT_SYMBOL +int evthread_set_condition_callbacks( + const struct evthread_condition_callbacks *); + +/** + Sets the function for determining the thread id. + + @param base the event base for which to set the id function + @param id_fn the identify function Libevent should invoke to + determine the identity of a thread. +*/ +EVENT2_EXPORT_SYMBOL +void evthread_set_id_callback( + unsigned long (*id_fn)(void)); + +#if (defined(_WIN32) && !defined(EVENT__DISABLE_THREAD_SUPPORT)) || defined(EVENT_IN_DOXYGEN_) +/** Sets up Libevent for use with Windows builtin locking and thread ID + functions. Unavailable if Libevent is not built for Windows. + + @return 0 on success, -1 on failure. */ +EVENT2_EXPORT_SYMBOL +int evthread_use_windows_threads(void); +/** + Defined if Libevent was built with support for evthread_use_windows_threads() +*/ +#define EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED 1 +#endif + +#if defined(EVENT__HAVE_PTHREADS) || defined(EVENT_IN_DOXYGEN_) +/** Sets up Libevent for use with Pthreads locking and thread ID functions. + Unavailable if Libevent is not build for use with pthreads. Requires + libraries to link against Libevent_pthreads as well as Libevent. + + @return 0 on success, -1 on failure. */ +EVENT2_EXPORT_SYMBOL +int evthread_use_pthreads(void); +/** Defined if Libevent was built with support for evthread_use_pthreads() */ +#define EVTHREAD_USE_PTHREADS_IMPLEMENTED 1 + +#endif + +/** Enable debugging wrappers around the current lock callbacks. If Libevent + * makes one of several common locking errors, exit with an assertion failure. + * + * If you're going to call this function, you must do so before any locks are + * allocated. + **/ +EVENT2_EXPORT_SYMBOL +void evthread_enable_lock_debugging(void); + +/* Old (misspelled) version: This is deprecated; use + * evthread_enable_log_debugging instead. */ +EVENT2_EXPORT_SYMBOL +void evthread_enable_lock_debuging(void); + +#endif /* EVENT__DISABLE_THREAD_SUPPORT */ + +struct event_base; +/** Make sure it's safe to tell an event base to wake up from another thread + or a signal handler. + + You shouldn't need to call this by hand; configuring the base with thread + support should be necessary and sufficient. + + @return 0 on success, -1 on failure. + */ +EVENT2_EXPORT_SYMBOL +int evthread_make_base_notifiable(struct event_base *base); + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT2_THREAD_H_INCLUDED_ */ diff --git a/platform/src/3rd/os_specific/oe2203/include/event2/util.h b/platform/src/3rd/os_specific/oe2203/include/event2/util.h new file mode 100644 index 00000000..dd4bbb69 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/event2/util.h @@ -0,0 +1,866 @@ +/* + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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 EVENT2_UTIL_H_INCLUDED_ +#define EVENT2_UTIL_H_INCLUDED_ + +/** @file event2/util.h + + Common convenience functions for cross-platform portability and + related socket manipulations. + + */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef EVENT__HAVE_SYS_TIME_H +#include +#endif +#ifdef EVENT__HAVE_STDINT_H +#include +#elif defined(EVENT__HAVE_INTTYPES_H) +#include +#endif +#ifdef EVENT__HAVE_SYS_TYPES_H +#include +#endif +#ifdef EVENT__HAVE_STDDEF_H +#include +#endif +#ifdef _MSC_VER +#include +#endif +#include +#ifdef EVENT__HAVE_NETDB_H +#if !defined(_GNU_SOURCE) +#define _GNU_SOURCE +#endif +#include +#endif + +#ifdef _WIN32 +#include +#ifdef EVENT__HAVE_GETADDRINFO +/* for EAI_* definitions. */ +#include +#endif +#else +#ifdef EVENT__HAVE_ERRNO_H +#include +#endif +#include +#endif + +#include + +/* Some openbsd autoconf versions get the name of this macro wrong. */ +#if defined(EVENT__SIZEOF_VOID__) && !defined(EVENT__SIZEOF_VOID_P) +#define EVENT__SIZEOF_VOID_P EVENT__SIZEOF_VOID__ +#endif + +/** + * @name Standard integer types. + * + * Integer type definitions for types that are supposed to be defined in the + * C99-specified stdint.h. Shamefully, some platforms do not include + * stdint.h, so we need to replace it. (If you are on a platform like this, + * your C headers are now over 10 years out of date. You should bug them to + * do something about this.) + * + * We define: + * + *
+ *
ev_uint64_t, ev_uint32_t, ev_uint16_t, ev_uint8_t
+ *
unsigned integer types of exactly 64, 32, 16, and 8 bits + * respectively.
+ *
ev_int64_t, ev_int32_t, ev_int16_t, ev_int8_t
+ *
signed integer types of exactly 64, 32, 16, and 8 bits + * respectively.
+ *
ev_uintptr_t, ev_intptr_t
+ *
unsigned/signed integers large enough + * to hold a pointer without loss of bits.
+ *
ev_ssize_t
+ *
A signed type of the same size as size_t
+ *
ev_off_t
+ *
A signed type typically used to represent offsets within a + * (potentially large) file
+ * + * @{ + */ +#ifdef EVENT__HAVE_UINT64_T +#define ev_uint64_t uint64_t +#define ev_int64_t int64_t +#elif defined(_WIN32) +#define ev_uint64_t unsigned __int64 +#define ev_int64_t signed __int64 +#elif EVENT__SIZEOF_LONG_LONG == 8 +#define ev_uint64_t unsigned long long +#define ev_int64_t long long +#elif EVENT__SIZEOF_LONG == 8 +#define ev_uint64_t unsigned long +#define ev_int64_t long +#elif defined(EVENT_IN_DOXYGEN_) +#define ev_uint64_t ... +#define ev_int64_t ... +#else +#error "No way to define ev_uint64_t" +#endif + +#ifdef EVENT__HAVE_UINT32_T +#define ev_uint32_t uint32_t +#define ev_int32_t int32_t +#elif defined(_WIN32) +#define ev_uint32_t unsigned int +#define ev_int32_t signed int +#elif EVENT__SIZEOF_LONG == 4 +#define ev_uint32_t unsigned long +#define ev_int32_t signed long +#elif EVENT__SIZEOF_INT == 4 +#define ev_uint32_t unsigned int +#define ev_int32_t signed int +#elif defined(EVENT_IN_DOXYGEN_) +#define ev_uint32_t ... +#define ev_int32_t ... +#else +#error "No way to define ev_uint32_t" +#endif + +#ifdef EVENT__HAVE_UINT16_T +#define ev_uint16_t uint16_t +#define ev_int16_t int16_t +#elif defined(_WIN32) +#define ev_uint16_t unsigned short +#define ev_int16_t signed short +#elif EVENT__SIZEOF_INT == 2 +#define ev_uint16_t unsigned int +#define ev_int16_t signed int +#elif EVENT__SIZEOF_SHORT == 2 +#define ev_uint16_t unsigned short +#define ev_int16_t signed short +#elif defined(EVENT_IN_DOXYGEN_) +#define ev_uint16_t ... +#define ev_int16_t ... +#else +#error "No way to define ev_uint16_t" +#endif + +#ifdef EVENT__HAVE_UINT8_T +#define ev_uint8_t uint8_t +#define ev_int8_t int8_t +#elif defined(EVENT_IN_DOXYGEN_) +#define ev_uint8_t ... +#define ev_int8_t ... +#else +#define ev_uint8_t unsigned char +#define ev_int8_t signed char +#endif + +#ifdef EVENT__HAVE_UINTPTR_T +#define ev_uintptr_t uintptr_t +#define ev_intptr_t intptr_t +#elif EVENT__SIZEOF_VOID_P <= 4 +#define ev_uintptr_t ev_uint32_t +#define ev_intptr_t ev_int32_t +#elif EVENT__SIZEOF_VOID_P <= 8 +#define ev_uintptr_t ev_uint64_t +#define ev_intptr_t ev_int64_t +#elif defined(EVENT_IN_DOXYGEN_) +#define ev_uintptr_t ... +#define ev_intptr_t ... +#else +#error "No way to define ev_uintptr_t" +#endif + +#ifdef EVENT__ssize_t +#define ev_ssize_t EVENT__ssize_t +#else +#define ev_ssize_t ssize_t +#endif + +/* Note that we define ev_off_t based on the compile-time size of off_t that + * we used to build Libevent, and not based on the current size of off_t. + * (For example, we don't define ev_off_t to off_t.). We do this because + * some systems let you build your software with different off_t sizes + * at runtime, and so putting in any dependency on off_t would risk API + * mismatch. + */ +#ifdef _WIN32 +#define ev_off_t ev_int64_t +#elif EVENT__SIZEOF_OFF_T == 8 +#define ev_off_t ev_int64_t +#elif EVENT__SIZEOF_OFF_T == 4 +#define ev_off_t ev_int32_t +#elif defined(EVENT_IN_DOXYGEN_) +#define ev_off_t ... +#else +#define ev_off_t off_t +#endif +/**@}*/ + +/* Limits for integer types. + + We're making two assumptions here: + - The compiler does constant folding properly. + - The platform does signed arithmetic in two's complement. +*/ + +/** + @name Limits for integer types + + These macros hold the largest or smallest values possible for the + ev_[u]int*_t types. + + @{ +*/ +#ifndef EVENT__HAVE_STDINT_H +#define EV_UINT64_MAX ((((ev_uint64_t)0xffffffffUL) << 32) | 0xffffffffUL) +#define EV_INT64_MAX ((((ev_int64_t) 0x7fffffffL) << 32) | 0xffffffffL) +#define EV_INT64_MIN ((-EV_INT64_MAX) - 1) +#define EV_UINT32_MAX ((ev_uint32_t)0xffffffffUL) +#define EV_INT32_MAX ((ev_int32_t) 0x7fffffffL) +#define EV_INT32_MIN ((-EV_INT32_MAX) - 1) +#define EV_UINT16_MAX ((ev_uint16_t)0xffffUL) +#define EV_INT16_MAX ((ev_int16_t) 0x7fffL) +#define EV_INT16_MIN ((-EV_INT16_MAX) - 1) +#define EV_UINT8_MAX 255 +#define EV_INT8_MAX 127 +#define EV_INT8_MIN ((-EV_INT8_MAX) - 1) +#else +#define EV_UINT64_MAX UINT64_MAX +#define EV_INT64_MAX INT64_MAX +#define EV_INT64_MIN INT64_MIN +#define EV_UINT32_MAX UINT32_MAX +#define EV_INT32_MAX INT32_MAX +#define EV_INT32_MIN INT32_MIN +#define EV_UINT16_MAX UINT16_MAX +#define EV_INT16_MAX INT16_MAX +#define EV_UINT8_MAX UINT8_MAX +#define EV_INT8_MAX INT8_MAX +#define EV_INT8_MIN INT8_MIN +/** @} */ +#endif + + +/** + @name Limits for SIZE_T and SSIZE_T + + @{ +*/ +#if EVENT__SIZEOF_SIZE_T == 8 +#define EV_SIZE_MAX EV_UINT64_MAX +#define EV_SSIZE_MAX EV_INT64_MAX +#elif EVENT__SIZEOF_SIZE_T == 4 +#define EV_SIZE_MAX EV_UINT32_MAX +#define EV_SSIZE_MAX EV_INT32_MAX +#elif defined(EVENT_IN_DOXYGEN_) +#define EV_SIZE_MAX ... +#define EV_SSIZE_MAX ... +#else +#error "No way to define SIZE_MAX" +#endif + +#define EV_SSIZE_MIN ((-EV_SSIZE_MAX) - 1) +/**@}*/ + +#ifdef _WIN32 +#define ev_socklen_t int +#elif defined(EVENT__socklen_t) +#define ev_socklen_t EVENT__socklen_t +#else +#define ev_socklen_t socklen_t +#endif + +#ifdef EVENT__HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY +#if !defined(EVENT__HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY) \ + && !defined(ss_family) +#define ss_family __ss_family +#endif +#endif + +/** + * A type wide enough to hold the output of "socket()" or "accept()". On + * Windows, this is an intptr_t; elsewhere, it is an int. */ +#ifdef _WIN32 +#define evutil_socket_t intptr_t +#else +#define evutil_socket_t int +#endif + +/** + * Structure to hold information about a monotonic timer + * + * Use this with evutil_configure_monotonic_time() and + * evutil_gettime_monotonic(). + * + * This is an opaque structure; you can allocate one using + * evutil_monotonic_timer_new(). + * + * @see evutil_monotonic_timer_new(), evutil_monotonic_timer_free(), + * evutil_configure_monotonic_time(), evutil_gettime_monotonic() + */ +struct evutil_monotonic_timer +#ifdef EVENT_IN_DOXYGEN_ +{/*Empty body so that doxygen will generate documentation here.*/} +#endif +; + +#define EV_MONOT_PRECISE 1 +#define EV_MONOT_FALLBACK 2 + +/** Format a date string using RFC 1123 format (used in HTTP). + * If `tm` is NULL, current system's time will be used. + * The number of characters written will be returned. + * One should check if the return value is smaller than `datelen` to check if + * the result is truncated or not. + */ +EVENT2_EXPORT_SYMBOL int +evutil_date_rfc1123(char *date, const size_t datelen, const struct tm *tm); + +/** Allocate a new struct evutil_monotonic_timer for use with the + * evutil_configure_monotonic_time() and evutil_gettime_monotonic() + * functions. You must configure the timer with + * evutil_configure_monotonic_time() before using it. + */ +EVENT2_EXPORT_SYMBOL +struct evutil_monotonic_timer * evutil_monotonic_timer_new(void); + +/** Free a struct evutil_monotonic_timer that was allocated using + * evutil_monotonic_timer_new(). + */ +EVENT2_EXPORT_SYMBOL +void evutil_monotonic_timer_free(struct evutil_monotonic_timer *timer); + +/** Set up a struct evutil_monotonic_timer; flags can include + * EV_MONOT_PRECISE and EV_MONOT_FALLBACK. + */ +EVENT2_EXPORT_SYMBOL +int evutil_configure_monotonic_time(struct evutil_monotonic_timer *timer, + int flags); + +/** Query the current monotonic time from a struct evutil_monotonic_timer + * previously configured with evutil_configure_monotonic_time(). Monotonic + * time is guaranteed never to run in reverse, but is not necessarily epoch- + * based, or relative to any other definite point. Use it to make reliable + * measurements of elapsed time between events even when the system time + * may be changed. + * + * It is not safe to use this funtion on the same timer from multiple + * threads. + */ +EVENT2_EXPORT_SYMBOL +int evutil_gettime_monotonic(struct evutil_monotonic_timer *timer, + struct timeval *tp); + +/** Create two new sockets that are connected to each other. + + On Unix, this simply calls socketpair(). On Windows, it uses the + loopback network interface on 127.0.0.1, and only + AF_INET,SOCK_STREAM are supported. + + (This may fail on some Windows hosts where firewall software has cleverly + decided to keep 127.0.0.1 from talking to itself.) + + Parameters and return values are as for socketpair() +*/ +EVENT2_EXPORT_SYMBOL +int evutil_socketpair(int d, int type, int protocol, evutil_socket_t sv[2]); +/** Do platform-specific operations as needed to make a socket nonblocking. + + @param sock The socket to make nonblocking + @return 0 on success, -1 on failure + */ +EVENT2_EXPORT_SYMBOL +int evutil_make_socket_nonblocking(evutil_socket_t sock); + +/** Do platform-specific operations to make a listener socket reusable. + + Specifically, we want to make sure that another program will be able + to bind this address right after we've closed the listener. + + This differs from Windows's interpretation of "reusable", which + allows multiple listeners to bind the same address at the same time. + + @param sock The socket to make reusable + @return 0 on success, -1 on failure + */ +EVENT2_EXPORT_SYMBOL +int evutil_make_listen_socket_reuseable(evutil_socket_t sock); + +/** Do platform-specific operations to make a listener port reusable. + + Specifically, we want to make sure that multiple programs which also + set the same socket option will be able to bind, listen at the same time. + + This is a feature available only to Linux 3.9+ + + @param sock The socket to make reusable + @return 0 on success, -1 on failure + */ +EVENT2_EXPORT_SYMBOL +int evutil_make_listen_socket_reuseable_port(evutil_socket_t sock); + +/** Do platform-specific operations as needed to close a socket upon a + successful execution of one of the exec*() functions. + + @param sock The socket to be closed + @return 0 on success, -1 on failure + */ +EVENT2_EXPORT_SYMBOL +int evutil_make_socket_closeonexec(evutil_socket_t sock); + +/** Do the platform-specific call needed to close a socket returned from + socket() or accept(). + + @param sock The socket to be closed + @return 0 on success, -1 on failure + */ +EVENT2_EXPORT_SYMBOL +int evutil_closesocket(evutil_socket_t sock); +#define EVUTIL_CLOSESOCKET(s) evutil_closesocket(s) + +/** Do platform-specific operations, if possible, to make a tcp listener + * socket defer accept()s until there is data to read. + * + * Not all platforms support this. You don't want to do this for every + * listener socket: only the ones that implement a protocol where the + * client transmits before the server needs to respond. + * + * @param sock The listening socket to to make deferred + * @return 0 on success (whether the operation is supported or not), + * -1 on failure +*/ +EVENT2_EXPORT_SYMBOL +int evutil_make_tcp_listen_socket_deferred(evutil_socket_t sock); + +#ifdef _WIN32 +/** Return the most recent socket error. Not idempotent on all platforms. */ +#define EVUTIL_SOCKET_ERROR() WSAGetLastError() +/** Replace the most recent socket error with errcode */ +#define EVUTIL_SET_SOCKET_ERROR(errcode) \ + do { WSASetLastError(errcode); } while (0) +/** Return the most recent socket error to occur on sock. */ +EVENT2_EXPORT_SYMBOL +int evutil_socket_geterror(evutil_socket_t sock); +/** Convert a socket error to a string. */ +EVENT2_EXPORT_SYMBOL +const char *evutil_socket_error_to_string(int errcode); +#elif defined(EVENT_IN_DOXYGEN_) +/** + @name Socket error functions + + These functions are needed for making programs compatible between + Windows and Unix-like platforms. + + You see, Winsock handles socket errors differently from the rest of + the world. Elsewhere, a socket error is like any other error and is + stored in errno. But winsock functions require you to retrieve the + error with a special function, and don't let you use strerror for + the error codes. And handling EWOULDBLOCK is ... different. + + @{ +*/ +/** Return the most recent socket error. Not idempotent on all platforms. */ +#define EVUTIL_SOCKET_ERROR() ... +/** Replace the most recent socket error with errcode */ +#define EVUTIL_SET_SOCKET_ERROR(errcode) ... +/** Return the most recent socket error to occur on sock. */ +#define evutil_socket_geterror(sock) ... +/** Convert a socket error to a string. */ +#define evutil_socket_error_to_string(errcode) ... +/**@}*/ +#else +#define EVUTIL_SOCKET_ERROR() (errno) +#define EVUTIL_SET_SOCKET_ERROR(errcode) \ + do { errno = (errcode); } while (0) +#define evutil_socket_geterror(sock) (errno) +#define evutil_socket_error_to_string(errcode) (strerror(errcode)) +#endif + + +/** + * @name Manipulation macros for struct timeval. + * + * We define replacements + * for timeradd, timersub, timerclear, timercmp, and timerisset. + * + * @{ + */ +#ifdef EVENT__HAVE_TIMERADD +#define evutil_timeradd(tvp, uvp, vvp) timeradd((tvp), (uvp), (vvp)) +#define evutil_timersub(tvp, uvp, vvp) timersub((tvp), (uvp), (vvp)) +#else +#define evutil_timeradd(tvp, uvp, vvp) \ + do { \ + (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \ + (vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \ + if ((vvp)->tv_usec >= 1000000) { \ + (vvp)->tv_sec++; \ + (vvp)->tv_usec -= 1000000; \ + } \ + } while (0) +#define evutil_timersub(tvp, uvp, vvp) \ + do { \ + (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ + (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \ + if ((vvp)->tv_usec < 0) { \ + (vvp)->tv_sec--; \ + (vvp)->tv_usec += 1000000; \ + } \ + } while (0) +#endif /* !EVENT__HAVE_TIMERADD */ + +#ifdef EVENT__HAVE_TIMERCLEAR +#define evutil_timerclear(tvp) timerclear(tvp) +#else +#define evutil_timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 +#endif +/**@}*/ + +/** Return true iff the tvp is related to uvp according to the relational + * operator cmp. Recognized values for cmp are ==, <=, <, >=, and >. */ +#define evutil_timercmp(tvp, uvp, cmp) \ + (((tvp)->tv_sec == (uvp)->tv_sec) ? \ + ((tvp)->tv_usec cmp (uvp)->tv_usec) : \ + ((tvp)->tv_sec cmp (uvp)->tv_sec)) + +#ifdef EVENT__HAVE_TIMERISSET +#define evutil_timerisset(tvp) timerisset(tvp) +#else +#define evutil_timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) +#endif + +/** Replacement for offsetof on platforms that don't define it. */ +#ifdef offsetof +#define evutil_offsetof(type, field) offsetof(type, field) +#else +#define evutil_offsetof(type, field) ((off_t)(&((type *)0)->field)) +#endif + +/* big-int related functions */ +/** Parse a 64-bit value from a string. Arguments are as for strtol. */ +EVENT2_EXPORT_SYMBOL +ev_int64_t evutil_strtoll(const char *s, char **endptr, int base); + +/** Replacement for gettimeofday on platforms that lack it. */ +#ifdef EVENT__HAVE_GETTIMEOFDAY +#define evutil_gettimeofday(tv, tz) gettimeofday((tv), (tz)) +#else +struct timezone; +EVENT2_EXPORT_SYMBOL +int evutil_gettimeofday(struct timeval *tv, struct timezone *tz); +#endif + +/** Replacement for snprintf to get consistent behavior on platforms for + which the return value of snprintf does not conform to C99. + */ +EVENT2_EXPORT_SYMBOL +int evutil_snprintf(char *buf, size_t buflen, const char *format, ...) +#ifdef __GNUC__ + __attribute__((format(printf, 3, 4))) +#endif +; +/** Replacement for vsnprintf to get consistent behavior on platforms for + which the return value of snprintf does not conform to C99. + */ +EVENT2_EXPORT_SYMBOL +int evutil_vsnprintf(char *buf, size_t buflen, const char *format, va_list ap) +#ifdef __GNUC__ + __attribute__((format(printf, 3, 0))) +#endif +; + +/** Replacement for inet_ntop for platforms which lack it. */ +EVENT2_EXPORT_SYMBOL +const char *evutil_inet_ntop(int af, const void *src, char *dst, size_t len); +/** Replacement for inet_pton for platforms which lack it. */ +EVENT2_EXPORT_SYMBOL +int evutil_inet_pton(int af, const char *src, void *dst); +struct sockaddr; + +/** Parse an IPv4 or IPv6 address, with optional port, from a string. + + Recognized formats are: + - [IPv6Address]:port + - [IPv6Address] + - IPv6Address + - IPv4Address:port + - IPv4Address + + If no port is specified, the port in the output is set to 0. + + @param str The string to parse. + @param out A struct sockaddr to hold the result. This should probably be + a struct sockaddr_storage. + @param outlen A pointer to the number of bytes that that 'out' can safely + hold. Set to the number of bytes used in 'out' on success. + @return -1 if the address is not well-formed, if the port is out of range, + or if out is not large enough to hold the result. Otherwise returns + 0 on success. +*/ +EVENT2_EXPORT_SYMBOL +int evutil_parse_sockaddr_port(const char *str, struct sockaddr *out, int *outlen); + +/** Compare two sockaddrs; return 0 if they are equal, or less than 0 if sa1 + * preceeds sa2, or greater than 0 if sa1 follows sa2. If include_port is + * true, consider the port as well as the address. Only implemented for + * AF_INET and AF_INET6 addresses. The ordering is not guaranteed to remain + * the same between Libevent versions. */ +EVENT2_EXPORT_SYMBOL +int evutil_sockaddr_cmp(const struct sockaddr *sa1, const struct sockaddr *sa2, + int include_port); + +/** As strcasecmp, but always compares the characters in locale-independent + ASCII. That's useful if you're handling data in ASCII-based protocols. + */ +EVENT2_EXPORT_SYMBOL +int evutil_ascii_strcasecmp(const char *str1, const char *str2); +/** As strncasecmp, but always compares the characters in locale-independent + ASCII. That's useful if you're handling data in ASCII-based protocols. + */ +EVENT2_EXPORT_SYMBOL +int evutil_ascii_strncasecmp(const char *str1, const char *str2, size_t n); + +/* Here we define evutil_addrinfo to the native addrinfo type, or redefine it + * if this system has no getaddrinfo(). */ +#ifdef EVENT__HAVE_STRUCT_ADDRINFO +#define evutil_addrinfo addrinfo +#else +/** A definition of struct addrinfo for systems that lack it. + + (This is just an alias for struct addrinfo if the system defines + struct addrinfo.) +*/ +struct evutil_addrinfo { + int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */ + int ai_family; /* PF_xxx */ + int ai_socktype; /* SOCK_xxx */ + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ + size_t ai_addrlen; /* length of ai_addr */ + char *ai_canonname; /* canonical name for nodename */ + struct sockaddr *ai_addr; /* binary address */ + struct evutil_addrinfo *ai_next; /* next structure in linked list */ +}; +#endif +/** @name evutil_getaddrinfo() error codes + + These values are possible error codes for evutil_getaddrinfo() and + related functions. + + @{ +*/ +#if defined(EAI_ADDRFAMILY) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_EAI_ADDRFAMILY EAI_ADDRFAMILY +#else +#define EVUTIL_EAI_ADDRFAMILY -901 +#endif +#if defined(EAI_AGAIN) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_EAI_AGAIN EAI_AGAIN +#else +#define EVUTIL_EAI_AGAIN -902 +#endif +#if defined(EAI_BADFLAGS) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_EAI_BADFLAGS EAI_BADFLAGS +#else +#define EVUTIL_EAI_BADFLAGS -903 +#endif +#if defined(EAI_FAIL) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_EAI_FAIL EAI_FAIL +#else +#define EVUTIL_EAI_FAIL -904 +#endif +#if defined(EAI_FAMILY) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_EAI_FAMILY EAI_FAMILY +#else +#define EVUTIL_EAI_FAMILY -905 +#endif +#if defined(EAI_MEMORY) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_EAI_MEMORY EAI_MEMORY +#else +#define EVUTIL_EAI_MEMORY -906 +#endif +/* This test is a bit complicated, since some MS SDKs decide to + * remove NODATA or redefine it to be the same as NONAME, in a + * fun interpretation of RFC 2553 and RFC 3493. */ +#if defined(EAI_NODATA) && defined(EVENT__HAVE_GETADDRINFO) && (!defined(EAI_NONAME) || EAI_NODATA != EAI_NONAME) +#define EVUTIL_EAI_NODATA EAI_NODATA +#else +#define EVUTIL_EAI_NODATA -907 +#endif +#if defined(EAI_NONAME) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_EAI_NONAME EAI_NONAME +#else +#define EVUTIL_EAI_NONAME -908 +#endif +#if defined(EAI_SERVICE) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_EAI_SERVICE EAI_SERVICE +#else +#define EVUTIL_EAI_SERVICE -909 +#endif +#if defined(EAI_SOCKTYPE) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_EAI_SOCKTYPE EAI_SOCKTYPE +#else +#define EVUTIL_EAI_SOCKTYPE -910 +#endif +#if defined(EAI_SYSTEM) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_EAI_SYSTEM EAI_SYSTEM +#else +#define EVUTIL_EAI_SYSTEM -911 +#endif + +#define EVUTIL_EAI_CANCEL -90001 + +#if defined(AI_PASSIVE) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_AI_PASSIVE AI_PASSIVE +#else +#define EVUTIL_AI_PASSIVE 0x1000 +#endif +#if defined(AI_CANONNAME) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_AI_CANONNAME AI_CANONNAME +#else +#define EVUTIL_AI_CANONNAME 0x2000 +#endif +#if defined(AI_NUMERICHOST) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_AI_NUMERICHOST AI_NUMERICHOST +#else +#define EVUTIL_AI_NUMERICHOST 0x4000 +#endif +#if defined(AI_NUMERICSERV) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_AI_NUMERICSERV AI_NUMERICSERV +#else +#define EVUTIL_AI_NUMERICSERV 0x8000 +#endif +#if defined(AI_V4MAPPED) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_AI_V4MAPPED AI_V4MAPPED +#else +#define EVUTIL_AI_V4MAPPED 0x10000 +#endif +#if defined(AI_ALL) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_AI_ALL AI_ALL +#else +#define EVUTIL_AI_ALL 0x20000 +#endif +#if defined(AI_ADDRCONFIG) && defined(EVENT__HAVE_GETADDRINFO) +#define EVUTIL_AI_ADDRCONFIG AI_ADDRCONFIG +#else +#define EVUTIL_AI_ADDRCONFIG 0x40000 +#endif +/**@}*/ + +struct evutil_addrinfo; +/** + * This function clones getaddrinfo for systems that don't have it. For full + * details, see RFC 3493, section 6.1. + * + * Limitations: + * - When the system has no getaddrinfo, we fall back to gethostbyname_r or + * gethostbyname, with their attendant issues. + * - The AI_V4MAPPED and AI_ALL flags are not currently implemented. + * + * For a nonblocking variant, see evdns_getaddrinfo. + */ +EVENT2_EXPORT_SYMBOL +int evutil_getaddrinfo(const char *nodename, const char *servname, + const struct evutil_addrinfo *hints_in, struct evutil_addrinfo **res); + +/** Release storage allocated by evutil_getaddrinfo or evdns_getaddrinfo. */ +EVENT2_EXPORT_SYMBOL +void evutil_freeaddrinfo(struct evutil_addrinfo *ai); + +EVENT2_EXPORT_SYMBOL +const char *evutil_gai_strerror(int err); + +/** Generate n bytes of secure pseudorandom data, and store them in buf. + * + * Current versions of Libevent use an ARC4-based random number generator, + * seeded using the platform's entropy source (/dev/urandom on Unix-like + * systems; CryptGenRandom on Windows). This is not actually as secure as it + * should be: ARC4 is a pretty lousy cipher, and the current implementation + * provides only rudimentary prediction- and backtracking-resistance. Don't + * use this for serious cryptographic applications. + */ +EVENT2_EXPORT_SYMBOL +void evutil_secure_rng_get_bytes(void *buf, size_t n); + +/** + * Seed the secure random number generator if needed, and return 0 on + * success or -1 on failure. + * + * It is okay to call this function more than once; it will still return + * 0 if the RNG has been successfully seeded and -1 if it can't be + * seeded. + * + * Ordinarily you don't need to call this function from your own code; + * Libevent will seed the RNG itself the first time it needs good random + * numbers. You only need to call it if (a) you want to double-check + * that one of the seeding methods did succeed, or (b) you plan to drop + * the capability to seed (by chrooting, or dropping capabilities, or + * whatever), and you want to make sure that seeding happens before your + * program loses the ability to do it. + */ +EVENT2_EXPORT_SYMBOL +int evutil_secure_rng_init(void); + +/** + * Set a filename to use in place of /dev/urandom for seeding the secure + * PRNG. Return 0 on success, -1 on failure. + * + * Call this function BEFORE calling any other initialization or RNG + * functions. + * + * (This string will _NOT_ be copied internally. Do not free it while any + * user of the secure RNG might be running. Don't pass anything other than a + * real /dev/...random device file here, or you might lose security.) + * + * This API is unstable, and might change in a future libevent version. + */ +EVENT2_EXPORT_SYMBOL +int evutil_secure_rng_set_urandom_device_file(char *fname); + +/** Seed the random number generator with extra random bytes. + + You should almost never need to call this function; it should be + sufficient to invoke evutil_secure_rng_init(), or let Libevent take + care of calling evutil_secure_rng_init() on its own. + + If you call this function as a _replacement_ for the regular + entropy sources, then you need to be sure that your input + contains a fairly large amount of strong entropy. Doing so is + notoriously hard: most people who try get it wrong. Watch out! + + @param dat a buffer full of a strong source of random numbers + @param datlen the number of bytes to read from datlen + */ +EVENT2_EXPORT_SYMBOL +void evutil_secure_rng_add_bytes(const char *dat, size_t datlen); + +#ifdef __cplusplus +} +#endif + +#endif /* EVENT1_EVUTIL_H_INCLUDED_ */ diff --git a/platform/src/3rd/os_specific/oe2203/include/event2/visibility.h b/platform/src/3rd/os_specific/oe2203/include/event2/visibility.h new file mode 100644 index 00000000..fb16dbee --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/event2/visibility.h @@ -0,0 +1,50 @@ +/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * 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 EVENT2_VISIBILITY_H_INCLUDED_ +#define EVENT2_VISIBILITY_H_INCLUDED_ + +#include + +#if defined(event_EXPORTS) || defined(event_extra_EXPORTS) || defined(event_core_EXPORTS) +# if defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550) +# define EVENT2_EXPORT_SYMBOL __global +# elif defined __GNUC__ +# define EVENT2_EXPORT_SYMBOL __attribute__ ((visibility("default"))) +# elif defined(_MSC_VER) +# define EVENT2_EXPORT_SYMBOL extern __declspec(dllexport) +# else +# define EVENT2_EXPORT_SYMBOL /* unknown compiler */ +# endif +#else +# if defined(EVENT__NEED_DLLIMPORT) && defined(_MSC_VER) && !defined(EVENT_BUILDING_REGRESS_TEST) +# define EVENT2_EXPORT_SYMBOL extern __declspec(dllimport) +# else +# define EVENT2_EXPORT_SYMBOL +# endif +#endif + +#endif /* EVENT2_VISIBILITY_H_INCLUDED_ */ diff --git a/platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/ae.h b/platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/ae.h new file mode 100644 index 00000000..def4df1b --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/ae.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2010-2011, Pieter Noordhuis + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Redis nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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 __HIREDIS_AE_H__ +#define __HIREDIS_AE_H__ +#include +//#include +#include +#include "../hiredis.h" +#include "../async.h" + +typedef struct redisAeEvents { + redisAsyncContext *context; + aeEventLoop *loop; + int fd; + int reading, writing; +} redisAeEvents; + +static void redisAeReadEvent(aeEventLoop *el, int fd, void *privdata, int mask) { + ((void)el); ((void)fd); ((void)mask); + + redisAeEvents *e = (redisAeEvents*)privdata; + redisAsyncHandleRead(e->context); +} + +static void redisAeWriteEvent(aeEventLoop *el, int fd, void *privdata, int mask) { + ((void)el); ((void)fd); ((void)mask); + + redisAeEvents *e = (redisAeEvents*)privdata; + redisAsyncHandleWrite(e->context); +} + +static void redisAeAddRead(void *privdata) { + redisAeEvents *e = (redisAeEvents*)privdata; + aeEventLoop *loop = e->loop; + if (!e->reading) { + e->reading = 1; + aeCreateFileEvent(loop,e->fd,AE_READABLE,redisAeReadEvent,e); + } +} + +static void redisAeDelRead(void *privdata) { + redisAeEvents *e = (redisAeEvents*)privdata; + aeEventLoop *loop = e->loop; + if (e->reading) { + e->reading = 0; + aeDeleteFileEvent(loop,e->fd,AE_READABLE); + } +} + +static void redisAeAddWrite(void *privdata) { + redisAeEvents *e = (redisAeEvents*)privdata; + aeEventLoop *loop = e->loop; + if (!e->writing) { + e->writing = 1; + aeCreateFileEvent(loop,e->fd,AE_WRITABLE,redisAeWriteEvent,e); + } +} + +static void redisAeDelWrite(void *privdata) { + redisAeEvents *e = (redisAeEvents*)privdata; + aeEventLoop *loop = e->loop; + if (e->writing) { + e->writing = 0; + aeDeleteFileEvent(loop,e->fd,AE_WRITABLE); + } +} + +static void redisAeCleanup(void *privdata) { + redisAeEvents *e = (redisAeEvents*)privdata; + redisAeDelRead(privdata); + redisAeDelWrite(privdata); + free(e); +} + +static int redisAeAttach(aeEventLoop *loop, redisAsyncContext *ac) { + redisContext *c = &(ac->c); + redisAeEvents *e; + + /* Nothing should be attached when something is already attached */ + if (ac->ev.data != NULL) + return REDIS_ERR; + + /* Create container for context and r/w events */ + e = (redisAeEvents*)malloc(sizeof(*e)); + e->context = ac; + e->loop = loop; + e->fd = c->fd; + e->reading = e->writing = 0; + + /* Register functions to start/stop listening for events */ + ac->ev.addRead = redisAeAddRead; + ac->ev.delRead = redisAeDelRead; + ac->ev.addWrite = redisAeAddWrite; + ac->ev.delWrite = redisAeDelWrite; + ac->ev.cleanup = redisAeCleanup; + ac->ev.data = e; + + return REDIS_OK; +} +#endif diff --git a/platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/glib.h b/platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/glib.h new file mode 100644 index 00000000..e0a6411d --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/glib.h @@ -0,0 +1,153 @@ +#ifndef __HIREDIS_GLIB_H__ +#define __HIREDIS_GLIB_H__ + +#include + +#include "../hiredis.h" +#include "../async.h" + +typedef struct +{ + GSource source; + redisAsyncContext *ac; + GPollFD poll_fd; +} RedisSource; + +static void +redis_source_add_read (gpointer data) +{ + RedisSource *source = (RedisSource *)data; + g_return_if_fail(source); + source->poll_fd.events |= G_IO_IN; + g_main_context_wakeup(g_source_get_context((GSource *)data)); +} + +static void +redis_source_del_read (gpointer data) +{ + RedisSource *source = (RedisSource *)data; + g_return_if_fail(source); + source->poll_fd.events &= ~G_IO_IN; + g_main_context_wakeup(g_source_get_context((GSource *)data)); +} + +static void +redis_source_add_write (gpointer data) +{ + RedisSource *source = (RedisSource *)data; + g_return_if_fail(source); + source->poll_fd.events |= G_IO_OUT; + g_main_context_wakeup(g_source_get_context((GSource *)data)); +} + +static void +redis_source_del_write (gpointer data) +{ + RedisSource *source = (RedisSource *)data; + g_return_if_fail(source); + source->poll_fd.events &= ~G_IO_OUT; + g_main_context_wakeup(g_source_get_context((GSource *)data)); +} + +static void +redis_source_cleanup (gpointer data) +{ + RedisSource *source = (RedisSource *)data; + + g_return_if_fail(source); + + redis_source_del_read(source); + redis_source_del_write(source); + /* + * It is not our responsibility to remove ourself from the + * current main loop. However, we will remove the GPollFD. + */ + if (source->poll_fd.fd >= 0) { + g_source_remove_poll((GSource *)data, &source->poll_fd); + source->poll_fd.fd = -1; + } +} + +static gboolean +redis_source_prepare (GSource *source, + gint *timeout_) +{ + RedisSource *redis = (RedisSource *)source; + *timeout_ = -1; + return !!(redis->poll_fd.events & redis->poll_fd.revents); +} + +static gboolean +redis_source_check (GSource *source) +{ + RedisSource *redis = (RedisSource *)source; + return !!(redis->poll_fd.events & redis->poll_fd.revents); +} + +static gboolean +redis_source_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + RedisSource *redis = (RedisSource *)source; + + if ((redis->poll_fd.revents & G_IO_OUT)) { + redisAsyncHandleWrite(redis->ac); + redis->poll_fd.revents &= ~G_IO_OUT; + } + + if ((redis->poll_fd.revents & G_IO_IN)) { + redisAsyncHandleRead(redis->ac); + redis->poll_fd.revents &= ~G_IO_IN; + } + + if (callback) { + return callback(user_data); + } + + return TRUE; +} + +static void +redis_source_finalize (GSource *source) +{ + RedisSource *redis = (RedisSource *)source; + + if (redis->poll_fd.fd >= 0) { + g_source_remove_poll(source, &redis->poll_fd); + redis->poll_fd.fd = -1; + } +} + +static GSource * +redis_source_new (redisAsyncContext *ac) +{ + static GSourceFuncs source_funcs = { + .prepare = redis_source_prepare, + .check = redis_source_check, + .dispatch = redis_source_dispatch, + .finalize = redis_source_finalize, + }; + redisContext *c = &ac->c; + RedisSource *source; + + g_return_val_if_fail(ac != NULL, NULL); + + source = (RedisSource *)g_source_new(&source_funcs, sizeof *source); + source->ac = ac; + source->poll_fd.fd = c->fd; + source->poll_fd.events = 0; + source->poll_fd.revents = 0; + g_source_add_poll((GSource *)source, &source->poll_fd); + + ac->ev.addRead = redis_source_add_read; + ac->ev.delRead = redis_source_del_read; + ac->ev.addWrite = redis_source_add_write; + ac->ev.delWrite = redis_source_del_write; + ac->ev.cleanup = redis_source_cleanup; + ac->ev.data = source; + + return (GSource *)source; +} + +#endif /* __HIREDIS_GLIB_H__ */ diff --git a/platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/ivykis.h b/platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/ivykis.h new file mode 100644 index 00000000..6a12a868 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/ivykis.h @@ -0,0 +1,81 @@ +#ifndef __HIREDIS_IVYKIS_H__ +#define __HIREDIS_IVYKIS_H__ +#include +#include "../hiredis.h" +#include "../async.h" + +typedef struct redisIvykisEvents { + redisAsyncContext *context; + struct iv_fd fd; +} redisIvykisEvents; + +static void redisIvykisReadEvent(void *arg) { + redisAsyncContext *context = (redisAsyncContext *)arg; + redisAsyncHandleRead(context); +} + +static void redisIvykisWriteEvent(void *arg) { + redisAsyncContext *context = (redisAsyncContext *)arg; + redisAsyncHandleWrite(context); +} + +static void redisIvykisAddRead(void *privdata) { + redisIvykisEvents *e = (redisIvykisEvents*)privdata; + iv_fd_set_handler_in(&e->fd, redisIvykisReadEvent); +} + +static void redisIvykisDelRead(void *privdata) { + redisIvykisEvents *e = (redisIvykisEvents*)privdata; + iv_fd_set_handler_in(&e->fd, NULL); +} + +static void redisIvykisAddWrite(void *privdata) { + redisIvykisEvents *e = (redisIvykisEvents*)privdata; + iv_fd_set_handler_out(&e->fd, redisIvykisWriteEvent); +} + +static void redisIvykisDelWrite(void *privdata) { + redisIvykisEvents *e = (redisIvykisEvents*)privdata; + iv_fd_set_handler_out(&e->fd, NULL); +} + +static void redisIvykisCleanup(void *privdata) { + redisIvykisEvents *e = (redisIvykisEvents*)privdata; + + iv_fd_unregister(&e->fd); + free(e); +} + +static int redisIvykisAttach(redisAsyncContext *ac) { + redisContext *c = &(ac->c); + redisIvykisEvents *e; + + /* Nothing should be attached when something is already attached */ + if (ac->ev.data != NULL) + return REDIS_ERR; + + /* Create container for context and r/w events */ + e = (redisIvykisEvents*)malloc(sizeof(*e)); + e->context = ac; + + /* Register functions to start/stop listening for events */ + ac->ev.addRead = redisIvykisAddRead; + ac->ev.delRead = redisIvykisDelRead; + ac->ev.addWrite = redisIvykisAddWrite; + ac->ev.delWrite = redisIvykisDelWrite; + ac->ev.cleanup = redisIvykisCleanup; + ac->ev.data = e; + + /* Initialize and install read/write events */ + IV_FD_INIT(&e->fd); + e->fd.fd = c->fd; + e->fd.handler_in = redisIvykisReadEvent; + e->fd.handler_out = redisIvykisWriteEvent; + e->fd.handler_err = NULL; + e->fd.cookie = e->context; + + iv_fd_register(&e->fd); + + return REDIS_OK; +} +#endif diff --git a/platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/libev.h b/platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/libev.h new file mode 100644 index 00000000..2bf8d521 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/libev.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2010-2011, Pieter Noordhuis + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Redis nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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 __HIREDIS_LIBEV_H__ +#define __HIREDIS_LIBEV_H__ +#include +#include +#include +#include "../hiredis.h" +#include "../async.h" + +typedef struct redisLibevEvents { + redisAsyncContext *context; + struct ev_loop *loop; + int reading, writing; + ev_io rev, wev; +} redisLibevEvents; + +static void redisLibevReadEvent(EV_P_ ev_io *watcher, int revents) { +#if EV_MULTIPLICITY + ((void)loop); +#endif + ((void)revents); + + redisLibevEvents *e = (redisLibevEvents*)watcher->data; + redisAsyncHandleRead(e->context); +} + +static void redisLibevWriteEvent(EV_P_ ev_io *watcher, int revents) { +#if EV_MULTIPLICITY + ((void)loop); +#endif + ((void)revents); + + redisLibevEvents *e = (redisLibevEvents*)watcher->data; + redisAsyncHandleWrite(e->context); +} + +static void redisLibevAddRead(void *privdata) { + redisLibevEvents *e = (redisLibevEvents*)privdata; + struct ev_loop *loop = e->loop; + ((void)loop); + if (!e->reading) { + e->reading = 1; + ev_io_start(EV_A_ &e->rev); + } +} + +static void redisLibevDelRead(void *privdata) { + redisLibevEvents *e = (redisLibevEvents*)privdata; + struct ev_loop *loop = e->loop; + ((void)loop); + if (e->reading) { + e->reading = 0; + ev_io_stop(EV_A_ &e->rev); + } +} + +static void redisLibevAddWrite(void *privdata) { + redisLibevEvents *e = (redisLibevEvents*)privdata; + struct ev_loop *loop = e->loop; + ((void)loop); + if (!e->writing) { + e->writing = 1; + ev_io_start(EV_A_ &e->wev); + } +} + +static void redisLibevDelWrite(void *privdata) { + redisLibevEvents *e = (redisLibevEvents*)privdata; + struct ev_loop *loop = e->loop; + ((void)loop); + if (e->writing) { + e->writing = 0; + ev_io_stop(EV_A_ &e->wev); + } +} + +static void redisLibevCleanup(void *privdata) { + redisLibevEvents *e = (redisLibevEvents*)privdata; + redisLibevDelRead(privdata); + redisLibevDelWrite(privdata); + free(e); +} + +static int redisLibevAttach(EV_P_ redisAsyncContext *ac) { + redisContext *c = &(ac->c); + redisLibevEvents *e; + + /* Nothing should be attached when something is already attached */ + if (ac->ev.data != NULL) + return REDIS_ERR; + + /* Create container for context and r/w events */ + e = (redisLibevEvents*)malloc(sizeof(*e)); + e->context = ac; +#if EV_MULTIPLICITY + e->loop = loop; +#else + e->loop = NULL; +#endif + e->reading = e->writing = 0; + e->rev.data = e; + e->wev.data = e; + + /* Register functions to start/stop listening for events */ + ac->ev.addRead = redisLibevAddRead; + ac->ev.delRead = redisLibevDelRead; + ac->ev.addWrite = redisLibevAddWrite; + ac->ev.delWrite = redisLibevDelWrite; + ac->ev.cleanup = redisLibevCleanup; + ac->ev.data = e; + + /* Initialize read/write events */ + ev_io_init(&e->rev,redisLibevReadEvent,c->fd,EV_READ); + ev_io_init(&e->wev,redisLibevWriteEvent,c->fd,EV_WRITE); + return REDIS_OK; +} + +#endif diff --git a/platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/libevent.h b/platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/libevent.h new file mode 100644 index 00000000..7d2bef18 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/libevent.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2010-2011, Pieter Noordhuis + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Redis nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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 __HIREDIS_LIBEVENT_H__ +#define __HIREDIS_LIBEVENT_H__ +#include +#include "../hiredis.h" +#include "../async.h" + +typedef struct redisLibeventEvents { + redisAsyncContext *context; + struct event *rev, *wev; +} redisLibeventEvents; + +static void redisLibeventReadEvent(int fd, short event, void *arg) { + ((void)fd); ((void)event); + redisLibeventEvents *e = (redisLibeventEvents*)arg; + redisAsyncHandleRead(e->context); +} + +static void redisLibeventWriteEvent(int fd, short event, void *arg) { + ((void)fd); ((void)event); + redisLibeventEvents *e = (redisLibeventEvents*)arg; + redisAsyncHandleWrite(e->context); +} + +static void redisLibeventAddRead(void *privdata) { + redisLibeventEvents *e = (redisLibeventEvents*)privdata; + event_add(e->rev,NULL); +} + +static void redisLibeventDelRead(void *privdata) { + redisLibeventEvents *e = (redisLibeventEvents*)privdata; + event_del(e->rev); +} + +static void redisLibeventAddWrite(void *privdata) { + redisLibeventEvents *e = (redisLibeventEvents*)privdata; + event_add(e->wev,NULL); +} + +static void redisLibeventDelWrite(void *privdata) { + redisLibeventEvents *e = (redisLibeventEvents*)privdata; + event_del(e->wev); +} + +static void redisLibeventCleanup(void *privdata) { + redisLibeventEvents *e = (redisLibeventEvents*)privdata; + event_free(e->rev); + event_free(e->wev); + free(e); +} + +static int redisLibeventAttach(redisAsyncContext *ac, struct event_base *base) { + redisContext *c = &(ac->c); + redisLibeventEvents *e; + + /* Nothing should be attached when something is already attached */ + if (ac->ev.data != NULL) + return REDIS_ERR; + + /* Create container for context and r/w events */ + e = (redisLibeventEvents*)malloc(sizeof(*e)); + e->context = ac; + + /* Register functions to start/stop listening for events */ + ac->ev.addRead = redisLibeventAddRead; + ac->ev.delRead = redisLibeventDelRead; + ac->ev.addWrite = redisLibeventAddWrite; + ac->ev.delWrite = redisLibeventDelWrite; + ac->ev.cleanup = redisLibeventCleanup; + ac->ev.data = e; + + /* Initialize and install read/write events */ + e->rev = event_new(base, c->fd, EV_READ, redisLibeventReadEvent, e); + e->wev = event_new(base, c->fd, EV_WRITE, redisLibeventWriteEvent, e); + event_add(e->rev, NULL); + event_add(e->wev, NULL); + return REDIS_OK; +} +#endif diff --git a/platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/libuv.h b/platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/libuv.h new file mode 100644 index 00000000..ff08c25e --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/libuv.h @@ -0,0 +1,122 @@ +#ifndef __HIREDIS_LIBUV_H__ +#define __HIREDIS_LIBUV_H__ +#include +#include +#include "../hiredis.h" +#include "../async.h" +#include + +typedef struct redisLibuvEvents { + redisAsyncContext* context; + uv_poll_t handle; + int events; +} redisLibuvEvents; + + +static void redisLibuvPoll(uv_poll_t* handle, int status, int events) { + redisLibuvEvents* p = (redisLibuvEvents*)handle->data; + + if (status != 0) { + return; + } + + if (p->context != NULL && (events & UV_READABLE)) { + redisAsyncHandleRead(p->context); + } + if (p->context != NULL && (events & UV_WRITABLE)) { + redisAsyncHandleWrite(p->context); + } +} + + +static void redisLibuvAddRead(void *privdata) { + redisLibuvEvents* p = (redisLibuvEvents*)privdata; + + p->events |= UV_READABLE; + + uv_poll_start(&p->handle, p->events, redisLibuvPoll); +} + + +static void redisLibuvDelRead(void *privdata) { + redisLibuvEvents* p = (redisLibuvEvents*)privdata; + + p->events &= ~UV_READABLE; + + if (p->events) { + uv_poll_start(&p->handle, p->events, redisLibuvPoll); + } else { + uv_poll_stop(&p->handle); + } +} + + +static void redisLibuvAddWrite(void *privdata) { + redisLibuvEvents* p = (redisLibuvEvents*)privdata; + + p->events |= UV_WRITABLE; + + uv_poll_start(&p->handle, p->events, redisLibuvPoll); +} + + +static void redisLibuvDelWrite(void *privdata) { + redisLibuvEvents* p = (redisLibuvEvents*)privdata; + + p->events &= ~UV_WRITABLE; + + if (p->events) { + uv_poll_start(&p->handle, p->events, redisLibuvPoll); + } else { + uv_poll_stop(&p->handle); + } +} + + +static void on_close(uv_handle_t* handle) { + redisLibuvEvents* p = (redisLibuvEvents*)handle->data; + + free(p); +} + + +static void redisLibuvCleanup(void *privdata) { + redisLibuvEvents* p = (redisLibuvEvents*)privdata; + + p->context = NULL; // indicate that context might no longer exist + uv_close((uv_handle_t*)&p->handle, on_close); +} + + +static int redisLibuvAttach(redisAsyncContext* ac, uv_loop_t* loop) { + redisContext *c = &(ac->c); + + if (ac->ev.data != NULL) { + return REDIS_ERR; + } + + ac->ev.addRead = redisLibuvAddRead; + ac->ev.delRead = redisLibuvDelRead; + ac->ev.addWrite = redisLibuvAddWrite; + ac->ev.delWrite = redisLibuvDelWrite; + ac->ev.cleanup = redisLibuvCleanup; + + redisLibuvEvents* p = (redisLibuvEvents*)malloc(sizeof(*p)); + + if (!p) { + return REDIS_ERR; + } + + memset(p, 0, sizeof(*p)); + + if (uv_poll_init(loop, &p->handle, c->fd) != 0) { + return REDIS_ERR; + } + + ac->ev.data = p; + p->handle.data = p; + p->context = ac; + + return REDIS_OK; +} +#endif diff --git a/platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/macosx.h b/platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/macosx.h new file mode 100644 index 00000000..72121f60 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/macosx.h @@ -0,0 +1,114 @@ +// +// Created by Дмитрий Бахвалов on 13.07.15. +// Copyright (c) 2015 Dmitry Bakhvalov. All rights reserved. +// + +#ifndef __HIREDIS_MACOSX_H__ +#define __HIREDIS_MACOSX_H__ + +#include + +#include "../hiredis.h" +#include "../async.h" + +typedef struct { + redisAsyncContext *context; + CFSocketRef socketRef; + CFRunLoopSourceRef sourceRef; +} RedisRunLoop; + +static int freeRedisRunLoop(RedisRunLoop* redisRunLoop) { + if( redisRunLoop != NULL ) { + if( redisRunLoop->sourceRef != NULL ) { + CFRunLoopSourceInvalidate(redisRunLoop->sourceRef); + CFRelease(redisRunLoop->sourceRef); + } + if( redisRunLoop->socketRef != NULL ) { + CFSocketInvalidate(redisRunLoop->socketRef); + CFRelease(redisRunLoop->socketRef); + } + free(redisRunLoop); + } + return REDIS_ERR; +} + +static void redisMacOSAddRead(void *privdata) { + RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata; + CFSocketEnableCallBacks(redisRunLoop->socketRef, kCFSocketReadCallBack); +} + +static void redisMacOSDelRead(void *privdata) { + RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata; + CFSocketDisableCallBacks(redisRunLoop->socketRef, kCFSocketReadCallBack); +} + +static void redisMacOSAddWrite(void *privdata) { + RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata; + CFSocketEnableCallBacks(redisRunLoop->socketRef, kCFSocketWriteCallBack); +} + +static void redisMacOSDelWrite(void *privdata) { + RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata; + CFSocketDisableCallBacks(redisRunLoop->socketRef, kCFSocketWriteCallBack); +} + +static void redisMacOSCleanup(void *privdata) { + RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata; + freeRedisRunLoop(redisRunLoop); +} + +static void redisMacOSAsyncCallback(CFSocketRef __unused s, CFSocketCallBackType callbackType, CFDataRef __unused address, const void __unused *data, void *info) { + redisAsyncContext* context = (redisAsyncContext*) info; + + switch (callbackType) { + case kCFSocketReadCallBack: + redisAsyncHandleRead(context); + break; + + case kCFSocketWriteCallBack: + redisAsyncHandleWrite(context); + break; + + default: + break; + } +} + +static int redisMacOSAttach(redisAsyncContext *redisAsyncCtx, CFRunLoopRef runLoop) { + redisContext *redisCtx = &(redisAsyncCtx->c); + + /* Nothing should be attached when something is already attached */ + if( redisAsyncCtx->ev.data != NULL ) return REDIS_ERR; + + RedisRunLoop* redisRunLoop = (RedisRunLoop*) calloc(1, sizeof(RedisRunLoop)); + if( !redisRunLoop ) return REDIS_ERR; + + /* Setup redis stuff */ + redisRunLoop->context = redisAsyncCtx; + + redisAsyncCtx->ev.addRead = redisMacOSAddRead; + redisAsyncCtx->ev.delRead = redisMacOSDelRead; + redisAsyncCtx->ev.addWrite = redisMacOSAddWrite; + redisAsyncCtx->ev.delWrite = redisMacOSDelWrite; + redisAsyncCtx->ev.cleanup = redisMacOSCleanup; + redisAsyncCtx->ev.data = redisRunLoop; + + /* Initialize and install read/write events */ + CFSocketContext socketCtx = { 0, redisAsyncCtx, NULL, NULL, NULL }; + + redisRunLoop->socketRef = CFSocketCreateWithNative(NULL, redisCtx->fd, + kCFSocketReadCallBack | kCFSocketWriteCallBack, + redisMacOSAsyncCallback, + &socketCtx); + if( !redisRunLoop->socketRef ) return freeRedisRunLoop(redisRunLoop); + + redisRunLoop->sourceRef = CFSocketCreateRunLoopSource(NULL, redisRunLoop->socketRef, 0); + if( !redisRunLoop->sourceRef ) return freeRedisRunLoop(redisRunLoop); + + CFRunLoopAddSource(runLoop, redisRunLoop->sourceRef, kCFRunLoopDefaultMode); + + return REDIS_OK; +} + +#endif + diff --git a/platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/qt.h b/platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/qt.h new file mode 100644 index 00000000..5cc02e6c --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/hiredis/adapters/qt.h @@ -0,0 +1,135 @@ +/*- + * Copyright (C) 2014 Pietro Cerutti + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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 __HIREDIS_QT_H__ +#define __HIREDIS_QT_H__ +#include +#include "../async.h" + +static void RedisQtAddRead(void *); +static void RedisQtDelRead(void *); +static void RedisQtAddWrite(void *); +static void RedisQtDelWrite(void *); +static void RedisQtCleanup(void *); + +class RedisQtAdapter : public QObject { + + Q_OBJECT + + friend + void RedisQtAddRead(void * adapter) { + RedisQtAdapter * a = static_cast(adapter); + a->addRead(); + } + + friend + void RedisQtDelRead(void * adapter) { + RedisQtAdapter * a = static_cast(adapter); + a->delRead(); + } + + friend + void RedisQtAddWrite(void * adapter) { + RedisQtAdapter * a = static_cast(adapter); + a->addWrite(); + } + + friend + void RedisQtDelWrite(void * adapter) { + RedisQtAdapter * a = static_cast(adapter); + a->delWrite(); + } + + friend + void RedisQtCleanup(void * adapter) { + RedisQtAdapter * a = static_cast(adapter); + a->cleanup(); + } + + public: + RedisQtAdapter(QObject * parent = 0) + : QObject(parent), m_ctx(0), m_read(0), m_write(0) { } + + ~RedisQtAdapter() { + if (m_ctx != 0) { + m_ctx->ev.data = NULL; + } + } + + int setContext(redisAsyncContext * ac) { + if (ac->ev.data != NULL) { + return REDIS_ERR; + } + m_ctx = ac; + m_ctx->ev.data = this; + m_ctx->ev.addRead = RedisQtAddRead; + m_ctx->ev.delRead = RedisQtDelRead; + m_ctx->ev.addWrite = RedisQtAddWrite; + m_ctx->ev.delWrite = RedisQtDelWrite; + m_ctx->ev.cleanup = RedisQtCleanup; + return REDIS_OK; + } + + private: + void addRead() { + if (m_read) return; + m_read = new QSocketNotifier(m_ctx->c.fd, QSocketNotifier::Read, 0); + connect(m_read, SIGNAL(activated(int)), this, SLOT(read())); + } + + void delRead() { + if (!m_read) return; + delete m_read; + m_read = 0; + } + + void addWrite() { + if (m_write) return; + m_write = new QSocketNotifier(m_ctx->c.fd, QSocketNotifier::Write, 0); + connect(m_write, SIGNAL(activated(int)), this, SLOT(write())); + } + + void delWrite() { + if (!m_write) return; + delete m_write; + m_write = 0; + } + + void cleanup() { + delRead(); + delWrite(); + } + + private slots: + void read() { redisAsyncHandleRead(m_ctx); } + void write() { redisAsyncHandleWrite(m_ctx); } + + private: + redisAsyncContext * m_ctx; + QSocketNotifier * m_read; + QSocketNotifier * m_write; +}; + +#endif /* !__HIREDIS_QT_H__ */ diff --git a/platform/src/3rd/os_specific/oe2203/include/hiredis/async.h b/platform/src/3rd/os_specific/oe2203/include/hiredis/async.h new file mode 100644 index 00000000..e69d8409 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/hiredis/async.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2009-2011, Salvatore Sanfilippo + * Copyright (c) 2010-2011, Pieter Noordhuis + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Redis nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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 __HIREDIS_ASYNC_H +#define __HIREDIS_ASYNC_H +#include "hiredis.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct redisAsyncContext; /* need forward declaration of redisAsyncContext */ +struct dict; /* dictionary header is included in async.c */ + +/* Reply callback prototype and container */ +typedef void (redisCallbackFn)(struct redisAsyncContext*, void*, void*); +typedef struct redisCallback { + struct redisCallback *next; /* simple singly linked list */ + redisCallbackFn *fn; + int pending_subs; + void *privdata; +} redisCallback; + +/* List of callbacks for either regular replies or pub/sub */ +typedef struct redisCallbackList { + redisCallback *head, *tail; +} redisCallbackList; + +/* Connection callback prototypes */ +typedef void (redisDisconnectCallback)(const struct redisAsyncContext*, int status); +typedef void (redisConnectCallback)(const struct redisAsyncContext*, int status); + +/* Context for an async connection to Redis */ +typedef struct redisAsyncContext { + /* Hold the regular context, so it can be realloc'ed. */ + redisContext c; + + /* Setup error flags so they can be used directly. */ + int err; + char *errstr; + + /* Not used by hiredis */ + void *data; + + /* Event library data and hooks */ + struct { + void *data; + + /* Hooks that are called when the library expects to start + * reading/writing. These functions should be idempotent. */ + void (*addRead)(void *privdata); + void (*delRead)(void *privdata); + void (*addWrite)(void *privdata); + void (*delWrite)(void *privdata); + void (*cleanup)(void *privdata); + } ev; + + /* Called when either the connection is terminated due to an error or per + * user request. The status is set accordingly (REDIS_OK, REDIS_ERR). */ + redisDisconnectCallback *onDisconnect; + + /* Called when the first write event was received. */ + redisConnectCallback *onConnect; + + /* Regular command callbacks */ + redisCallbackList replies; + + /* Subscription callbacks */ + struct { + redisCallbackList invalid; + struct dict *channels; + struct dict *patterns; + } sub; +} redisAsyncContext; + +/* Functions that proxy to hiredis */ +redisAsyncContext *redisAsyncConnect(const char *ip, int port); +redisAsyncContext *redisAsyncConnectBind(const char *ip, int port, const char *source_addr); +redisAsyncContext *redisAsyncConnectBindWithReuse(const char *ip, int port, + const char *source_addr); +redisAsyncContext *redisAsyncConnectUnix(const char *path); +int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn); +int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn); +void redisAsyncDisconnect(redisAsyncContext *ac); +void redisAsyncFree(redisAsyncContext *ac); + +/* Handle read/write events */ +void redisAsyncHandleRead(redisAsyncContext *ac); +void redisAsyncHandleWrite(redisAsyncContext *ac); + +/* Command functions for an async context. Write the command to the + * output buffer and register the provided callback. */ +int redisvAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, va_list ap); +int redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...); +int redisAsyncCommandArgv(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, int argc, const char **argv, const size_t *argvlen); +int redisAsyncFormattedCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *cmd, size_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/src/3rd/os_specific/oe2203/include/hiredis/hiredis.h b/platform/src/3rd/os_specific/oe2203/include/hiredis/hiredis.h new file mode 100644 index 00000000..bd53e7ec --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/hiredis/hiredis.h @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2009-2011, Salvatore Sanfilippo + * Copyright (c) 2010-2014, Pieter Noordhuis + * Copyright (c) 2015, Matt Stancliff , + * Jan-Erik Rediger + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Redis nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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 __HIREDIS_H +#define __HIREDIS_H +#include "read.h" +#include /* for va_list */ +#include /* for struct timeval */ +#include /* uintXX_t, etc */ +#include "sds.h" /* for sds */ + +#define HIREDIS_MAJOR 0 +#define HIREDIS_MINOR 14 +#define HIREDIS_PATCH 0 +#define HIREDIS_SONAME 0.14 + +/* Connection type can be blocking or non-blocking and is set in the + * least significant bit of the flags field in redisContext. */ +#define REDIS_BLOCK 0x1 + +/* Connection may be disconnected before being free'd. The second bit + * in the flags field is set when the context is connected. */ +#define REDIS_CONNECTED 0x2 + +/* The async API might try to disconnect cleanly and flush the output + * buffer and read all subsequent replies before disconnecting. + * This flag means no new commands can come in and the connection + * should be terminated once all replies have been read. */ +#define REDIS_DISCONNECTING 0x4 + +/* Flag specific to the async API which means that the context should be clean + * up as soon as possible. */ +#define REDIS_FREEING 0x8 + +/* Flag that is set when an async callback is executed. */ +#define REDIS_IN_CALLBACK 0x10 + +/* Flag that is set when the async context has one or more subscriptions. */ +#define REDIS_SUBSCRIBED 0x20 + +/* Flag that is set when monitor mode is active */ +#define REDIS_MONITORING 0x40 + +/* Flag that is set when we should set SO_REUSEADDR before calling bind() */ +#define REDIS_REUSEADDR 0x80 + +#define REDIS_KEEPALIVE_INTERVAL 15 /* seconds */ + +/* number of times we retry to connect in the case of EADDRNOTAVAIL and + * SO_REUSEADDR is being used. */ +#define REDIS_CONNECT_RETRIES 10 + +#ifdef __cplusplus +extern "C" { +#endif + +/* This is the reply object returned by redisCommand() */ +typedef struct redisReply { + int type; /* REDIS_REPLY_* */ + long long integer; /* The integer when type is REDIS_REPLY_INTEGER */ + size_t len; /* Length of string */ + char *str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */ + size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */ + struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */ +} redisReply; + +redisReader *redisReaderCreate(void); + +/* Function to free the reply objects hiredis returns by default. */ +void freeReplyObject(void *reply); + +/* Functions to format a command according to the protocol. */ +int redisvFormatCommand(char **target, const char *format, va_list ap); +int redisFormatCommand(char **target, const char *format, ...); +int redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen); +int redisFormatSdsCommandArgv(sds *target, int argc, const char ** argv, const size_t *argvlen); +void redisFreeCommand(char *cmd); +void redisFreeSdsCommand(sds cmd); + +enum redisConnectionType { + REDIS_CONN_TCP, + REDIS_CONN_UNIX +}; + +/* Context for a connection to Redis */ +typedef struct redisContext { + int err; /* Error flags, 0 when there is no error */ + char errstr[128]; /* String representation of error when applicable */ + int fd; + int flags; + char *obuf; /* Write buffer */ + redisReader *reader; /* Protocol reader */ + + enum redisConnectionType connection_type; + struct timeval *timeout; + + struct { + char *host; + char *source_addr; + int port; + } tcp; + + struct { + char *path; + } unix_sock; + +} redisContext; + +redisContext *redisConnect(const char *ip, int port); +redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv); +redisContext *redisConnectNonBlock(const char *ip, int port); +redisContext *redisConnectBindNonBlock(const char *ip, int port, + const char *source_addr); +redisContext *redisConnectBindNonBlockWithReuse(const char *ip, int port, + const char *source_addr); +redisContext *redisConnectUnix(const char *path); +redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv); +redisContext *redisConnectUnixNonBlock(const char *path); +redisContext *redisConnectFd(int fd); + +/** + * Reconnect the given context using the saved information. + * + * This re-uses the exact same connect options as in the initial connection. + * host, ip (or path), timeout and bind address are reused, + * flags are used unmodified from the existing context. + * + * Returns REDIS_OK on successful connect or REDIS_ERR otherwise. + */ +int redisReconnect(redisContext *c); + +int redisSetTimeout(redisContext *c, const struct timeval tv); +int redisEnableKeepAlive(redisContext *c); +void redisFree(redisContext *c); +int redisFreeKeepFd(redisContext *c); +int redisBufferRead(redisContext *c); +int redisBufferWrite(redisContext *c, int *done); + +/* In a blocking context, this function first checks if there are unconsumed + * replies to return and returns one if so. Otherwise, it flushes the output + * buffer to the socket and reads until it has a reply. In a non-blocking + * context, it will return unconsumed replies until there are no more. */ +int redisGetReply(redisContext *c, void **reply); +int redisGetReplyFromReader(redisContext *c, void **reply); + +/* Write a formatted command to the output buffer. Use these functions in blocking mode + * to get a pipeline of commands. */ +int redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len); + +/* Write a command to the output buffer. Use these functions in blocking mode + * to get a pipeline of commands. */ +int redisvAppendCommand(redisContext *c, const char *format, va_list ap); +int redisAppendCommand(redisContext *c, const char *format, ...); +int redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); + +/* Issue a command to Redis. In a blocking context, it is identical to calling + * redisAppendCommand, followed by redisGetReply. The function will return + * NULL if there was an error in performing the request, otherwise it will + * return the reply. In a non-blocking context, it is identical to calling + * only redisAppendCommand and will always return NULL. */ +void *redisvCommand(redisContext *c, const char *format, va_list ap); +void *redisCommand(redisContext *c, const char *format, ...); +void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/src/3rd/os_specific/oe2203/include/hiredis/read.h b/platform/src/3rd/os_specific/oe2203/include/hiredis/read.h new file mode 100644 index 00000000..2988aa45 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/hiredis/read.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2009-2011, Salvatore Sanfilippo + * Copyright (c) 2010-2011, Pieter Noordhuis + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Redis nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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 __HIREDIS_READ_H +#define __HIREDIS_READ_H +#include /* for size_t */ + +#define REDIS_ERR -1 +#define REDIS_OK 0 + +/* When an error occurs, the err flag in a context is set to hold the type of + * error that occurred. REDIS_ERR_IO means there was an I/O error and you + * should use the "errno" variable to find out what is wrong. + * For other values, the "errstr" field will hold a description. */ +#define REDIS_ERR_IO 1 /* Error in read or write */ +#define REDIS_ERR_EOF 3 /* End of file */ +#define REDIS_ERR_PROTOCOL 4 /* Protocol error */ +#define REDIS_ERR_OOM 5 /* Out of memory */ +#define REDIS_ERR_OTHER 2 /* Everything else... */ + +#define REDIS_REPLY_STRING 1 +#define REDIS_REPLY_ARRAY 2 +#define REDIS_REPLY_INTEGER 3 +#define REDIS_REPLY_NIL 4 +#define REDIS_REPLY_STATUS 5 +#define REDIS_REPLY_ERROR 6 + +#define REDIS_READER_MAX_BUF (1024*16) /* Default max unused reader buffer. */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct redisReadTask { + int type; + int elements; /* number of elements in multibulk container */ + int idx; /* index in parent (array) object */ + void *obj; /* holds user-generated value for a read task */ + struct redisReadTask *parent; /* parent task */ + void *privdata; /* user-settable arbitrary field */ +} redisReadTask; + +typedef struct redisReplyObjectFunctions { + void *(*createString)(const redisReadTask*, char*, size_t); + void *(*createArray)(const redisReadTask*, int); + void *(*createInteger)(const redisReadTask*, long long); + void *(*createNil)(const redisReadTask*); + void (*freeObject)(void*); +} redisReplyObjectFunctions; + +typedef struct redisReader { + int err; /* Error flags, 0 when there is no error */ + char errstr[128]; /* String representation of error when applicable */ + + char *buf; /* Read buffer */ + size_t pos; /* Buffer cursor */ + size_t len; /* Buffer length */ + size_t maxbuf; /* Max length of unused buffer */ + + redisReadTask rstack[9]; + int ridx; /* Index of current read task */ + void *reply; /* Temporary reply pointer */ + + redisReplyObjectFunctions *fn; + void *privdata; +} redisReader; + +/* Public API for the protocol parser. */ +redisReader *redisReaderCreateWithFunctions(redisReplyObjectFunctions *fn); +void redisReaderFree(redisReader *r); +int redisReaderFeed(redisReader *r, const char *buf, size_t len); +int redisReaderGetReply(redisReader *r, void **reply); + +#define redisReaderSetPrivdata(_r, _p) (int)(((redisReader*)(_r))->privdata = (_p)) +#define redisReaderGetObject(_r) (((redisReader*)(_r))->reply) +#define redisReaderGetError(_r) (((redisReader*)(_r))->errstr) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/src/3rd/os_specific/oe2203/include/hiredis/sds.h b/platform/src/3rd/os_specific/oe2203/include/hiredis/sds.h new file mode 100644 index 00000000..13be75a9 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/hiredis/sds.h @@ -0,0 +1,273 @@ +/* SDSLib 2.0 -- A C dynamic strings library + * + * Copyright (c) 2006-2015, Salvatore Sanfilippo + * Copyright (c) 2015, Oran Agra + * Copyright (c) 2015, Redis Labs, Inc + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Redis nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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 __SDS_H +#define __SDS_H + +#define SDS_MAX_PREALLOC (1024*1024) + +#include +#include +#include + +typedef char *sds; + +/* Note: sdshdr5 is never used, we just access the flags byte directly. + * However is here to document the layout of type 5 SDS strings. */ +struct __attribute__ ((__packed__)) sdshdr5 { + unsigned char flags; /* 3 lsb of type, and 5 msb of string length */ + char buf[]; +}; +struct __attribute__ ((__packed__)) sdshdr8 { + uint8_t len; /* used */ + uint8_t alloc; /* excluding the header and null terminator */ + unsigned char flags; /* 3 lsb of type, 5 unused bits */ + char buf[]; +}; +struct __attribute__ ((__packed__)) sdshdr16 { + uint16_t len; /* used */ + uint16_t alloc; /* excluding the header and null terminator */ + unsigned char flags; /* 3 lsb of type, 5 unused bits */ + char buf[]; +}; +struct __attribute__ ((__packed__)) sdshdr32 { + uint32_t len; /* used */ + uint32_t alloc; /* excluding the header and null terminator */ + unsigned char flags; /* 3 lsb of type, 5 unused bits */ + char buf[]; +}; +struct __attribute__ ((__packed__)) sdshdr64 { + uint64_t len; /* used */ + uint64_t alloc; /* excluding the header and null terminator */ + unsigned char flags; /* 3 lsb of type, 5 unused bits */ + char buf[]; +}; + +#define SDS_TYPE_5 0 +#define SDS_TYPE_8 1 +#define SDS_TYPE_16 2 +#define SDS_TYPE_32 3 +#define SDS_TYPE_64 4 +#define SDS_TYPE_MASK 7 +#define SDS_TYPE_BITS 3 +#define SDS_HDR_VAR(T,s) struct sdshdr##T *sh = (struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T))); +#define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T)))) +#define SDS_TYPE_5_LEN(f) ((f)>>SDS_TYPE_BITS) + +static inline size_t sdslen(const sds s) { + unsigned char flags = s[-1]; + switch(flags&SDS_TYPE_MASK) { + case SDS_TYPE_5: + return SDS_TYPE_5_LEN(flags); + case SDS_TYPE_8: + return SDS_HDR(8,s)->len; + case SDS_TYPE_16: + return SDS_HDR(16,s)->len; + case SDS_TYPE_32: + return SDS_HDR(32,s)->len; + case SDS_TYPE_64: + return SDS_HDR(64,s)->len; + } + return 0; +} + +static inline size_t sdsavail(const sds s) { + unsigned char flags = s[-1]; + switch(flags&SDS_TYPE_MASK) { + case SDS_TYPE_5: { + return 0; + } + case SDS_TYPE_8: { + SDS_HDR_VAR(8,s); + return sh->alloc - sh->len; + } + case SDS_TYPE_16: { + SDS_HDR_VAR(16,s); + return sh->alloc - sh->len; + } + case SDS_TYPE_32: { + SDS_HDR_VAR(32,s); + return sh->alloc - sh->len; + } + case SDS_TYPE_64: { + SDS_HDR_VAR(64,s); + return sh->alloc - sh->len; + } + } + return 0; +} + +static inline void sdssetlen(sds s, size_t newlen) { + unsigned char flags = s[-1]; + switch(flags&SDS_TYPE_MASK) { + case SDS_TYPE_5: + { + unsigned char *fp = ((unsigned char*)s)-1; + *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS); + } + break; + case SDS_TYPE_8: + SDS_HDR(8,s)->len = newlen; + break; + case SDS_TYPE_16: + SDS_HDR(16,s)->len = newlen; + break; + case SDS_TYPE_32: + SDS_HDR(32,s)->len = newlen; + break; + case SDS_TYPE_64: + SDS_HDR(64,s)->len = newlen; + break; + } +} + +static inline void sdsinclen(sds s, size_t inc) { + unsigned char flags = s[-1]; + switch(flags&SDS_TYPE_MASK) { + case SDS_TYPE_5: + { + unsigned char *fp = ((unsigned char*)s)-1; + unsigned char newlen = SDS_TYPE_5_LEN(flags)+inc; + *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS); + } + break; + case SDS_TYPE_8: + SDS_HDR(8,s)->len += inc; + break; + case SDS_TYPE_16: + SDS_HDR(16,s)->len += inc; + break; + case SDS_TYPE_32: + SDS_HDR(32,s)->len += inc; + break; + case SDS_TYPE_64: + SDS_HDR(64,s)->len += inc; + break; + } +} + +/* sdsalloc() = sdsavail() + sdslen() */ +static inline size_t sdsalloc(const sds s) { + unsigned char flags = s[-1]; + switch(flags&SDS_TYPE_MASK) { + case SDS_TYPE_5: + return SDS_TYPE_5_LEN(flags); + case SDS_TYPE_8: + return SDS_HDR(8,s)->alloc; + case SDS_TYPE_16: + return SDS_HDR(16,s)->alloc; + case SDS_TYPE_32: + return SDS_HDR(32,s)->alloc; + case SDS_TYPE_64: + return SDS_HDR(64,s)->alloc; + } + return 0; +} + +static inline void sdssetalloc(sds s, size_t newlen) { + unsigned char flags = s[-1]; + switch(flags&SDS_TYPE_MASK) { + case SDS_TYPE_5: + /* Nothing to do, this type has no total allocation info. */ + break; + case SDS_TYPE_8: + SDS_HDR(8,s)->alloc = newlen; + break; + case SDS_TYPE_16: + SDS_HDR(16,s)->alloc = newlen; + break; + case SDS_TYPE_32: + SDS_HDR(32,s)->alloc = newlen; + break; + case SDS_TYPE_64: + SDS_HDR(64,s)->alloc = newlen; + break; + } +} + +sds sdsnewlen(const void *init, size_t initlen); +sds sdsnew(const char *init); +sds sdsempty(void); +sds sdsdup(const sds s); +void sdsfree(sds s); +sds sdsgrowzero(sds s, size_t len); +sds sdscatlen(sds s, const void *t, size_t len); +sds sdscat(sds s, const char *t); +sds sdscatsds(sds s, const sds t); +sds sdscpylen(sds s, const char *t, size_t len); +sds sdscpy(sds s, const char *t); + +sds sdscatvprintf(sds s, const char *fmt, va_list ap); +#ifdef __GNUC__ +sds sdscatprintf(sds s, const char *fmt, ...) + __attribute__((format(printf, 2, 3))); +#else +sds sdscatprintf(sds s, const char *fmt, ...); +#endif + +sds sdscatfmt(sds s, char const *fmt, ...); +sds sdstrim(sds s, const char *cset); +void sdsrange(sds s, int start, int end); +void sdsupdatelen(sds s); +void sdsclear(sds s); +int sdscmp(const sds s1, const sds s2); +sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count); +void sdsfreesplitres(sds *tokens, int count); +void sdstolower(sds s); +void sdstoupper(sds s); +sds sdsfromlonglong(long long value); +sds sdscatrepr(sds s, const char *p, size_t len); +sds *sdssplitargs(const char *line, int *argc); +sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen); +sds sdsjoin(char **argv, int argc, char *sep); +sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen); + +/* Low level functions exposed to the user API */ +sds sdsMakeRoomFor(sds s, size_t addlen); +void sdsIncrLen(sds s, int incr); +sds sdsRemoveFreeSpace(sds s); +size_t sdsAllocSize(sds s); +void *sdsAllocPtr(sds s); + +/* Export the allocator used by SDS to the program using SDS. + * Sometimes the program SDS is linked to, may use a different set of + * allocators, but may want to allocate or free things that SDS will + * respectively free or allocate. */ +void *sds_malloc(size_t size); +void *sds_realloc(void *ptr, size_t size); +void sds_free(void *ptr); + +#ifdef REDIS_TEST +int sdsTest(int argc, char *argv[]); +#endif + +#endif diff --git a/platform/src/3rd/os_specific/oe2203/include/libagent.h b/platform/src/3rd/os_specific/oe2203/include/libagent.h new file mode 100644 index 00000000..51d18e1d --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/libagent.h @@ -0,0 +1,212 @@ +/*_############################################################################ + _## + _## AGENT++ 4.0 - libagent.h + _## + _## Copyright (C) 2000-2013 Frank Fock and Jochen Katz (agentpp.com) + _## + _## Licensed under the Apache License, Version 2.0 (the "License"); + _## you may not use this file except in compliance with the License. + _## You may obtain a copy of the License at + _## + _## http://www.apache.org/licenses/LICENSE-2.0 + _## + _## Unless required by applicable law or agreed to in writing, software + _## distributed under the License is distributed on an "AS IS" BASIS, + _## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + _## See the License for the specific language governing permissions and + _## limitations under the License. + _## + _##########################################################################*/ +#ifndef __LIBAGENT_H_INCLUDED__ +#define __LIBAGENT_H_INCLUDED__ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if 1 +# include +#endif +#if 1 +# include +#endif + +#if 1 +# include +# include +# include +# include +# include +# include +# include +# include +# include +#else +# include +# if 1 +# include +# include +# else +# if 1 +# include +# endif +# endif +# if 1 +# if ! 1 && 1 +# include +# endif +# include +# endif +# if 1 +# include +# endif +# if 1 +# include +# endif +# if 1 +# include +# endif +# if 1 +# include +# endif +# if 1 +# include +# endif +# if 1 +# include +#endif +#endif + +#if 1 +# include +#elif 1 +# include +#endif +#if 1 +# include +#endif + +#if 1 +#include +#endif +#if 1 +#include // and _ftime +#endif + +#if 0 +# include +# if 0 +# include +# endif +# if 0 +# include +# endif +#elif 0 + /* IIRC winsock.h must be included before windows.h */ +# include +#else +# if 1 +# include +# endif +# if 1 +# include +# endif +# if 1 +# include +# endif +# if 1 +# include +# endif +#endif + +#if 1 +# include +#endif +#if 1 +# include +#endif + +#ifdef _WIN32 +# if 0 +# include +# endif +# if 0 +# include +# endif +# include +#endif + +#if ! 0 +# if 0 +# define getpid _getpid +# endif +#endif + +#if ! 0 +# if 0 +# define ss_family __ss_family +# endif +#endif + +/* Minimum of signed integral types. */ +#ifndef INT8_MIN +# define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +# define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +# define INT32_MIN (-2147483647-1) +#endif +#ifndef INT64_MIN +# define INT64_MIN (-int64_t(9223372036854775807)-1) +#endif +/* Maximum of signed integral types. */ +#ifndef INT_MAX +# define INT8_MAX (127) +#endif +#ifndef INT16_MAX +# define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +# define INT32_MAX (2147483647) +#endif +#ifndef INT64_MAX +# define INT64_MAX (int64_t(9223372036854775807)) +#endif + +/* Maximum of unsigned integral types. */ +#ifndef UINT8_MAX +# define UINT8_MAX (255) +#endif +#ifndef UINT16_MAX +# define UINT16_MAX (65535) +#endif +#ifndef UINT32_MAX +# define UINT32_MAX (4294967295U) +#endif +#ifndef UINT64_MAX +# define UINT64_MAX (uint64_t(18446744073709551615)) +#endif + +#ifndef NULL +#define NULL 0 +#endif + +#if 1 +# include +#else +# include +#endif + +#include +#include +#ifdef _THREADS +#ifndef _WIN32THREADS +#include +#endif +#endif + +#include + +#endif /* ?__LIBAGENT_H_INCLUDED__ */ diff --git a/platform/src/3rd/os_specific/oe2203/include/libsnmp.h b/platform/src/3rd/os_specific/oe2203/include/libsnmp.h new file mode 100644 index 00000000..25fbd756 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/libsnmp.h @@ -0,0 +1,223 @@ +/*_############################################################################ + _## + _## libsnmp.h + _## + _## SNMP++ v3.3 + _## ----------------------------------------------- + _## Copyright (c) 2001-2013 Jochen Katz, Frank Fock + _## + _## This software is based on SNMP++2.6 from Hewlett Packard: + _## + _## Copyright (c) 1996 + _## Hewlett-Packard Company + _## + _## ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + _## Permission to use, copy, modify, distribute and/or sell this software + _## and/or its documentation is hereby granted without fee. User agrees + _## to display the above copyright notice and this license notice in all + _## copies of the software and any documentation of the software. User + _## agrees to assume all liability for the use of the software; + _## Hewlett-Packard and Jochen Katz make no representations about the + _## suitability of this software for any purpose. It is provided + _## "AS-IS" without warranty of any kind, either express or implied. User + _## hereby grants a royalty-free license to any and all derivatives based + _## upon this software code base. + _## + _##########################################################################*/ +#ifndef __LIBSNMP_H_INCLUDED__ +#define __LIBSNMP_H_INCLUDED__ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if 1 +# include +#endif +#if 1 +# include +#endif + +#if 1 +# include +# include +# include +# include +# include +# include +# include +# include +# include +#else +# include +# if 1 +# include +# include +# else +# if 1 +# include +# endif +# endif +# if 1 +# if !1 && 1 +# include +# endif +# include +# endif +# if 1 +# include +# endif +# if 1 +# include +# endif +# if 1 +# include +# endif +# if 1 +# include +# endif +# if 1 +# include +# endif +# if 1 +# include +#endif +#endif + +#if 1 +# include +#else +# if 1 +# include +# endif +#endif + +#if 1 +# include +#endif + +#if 1 +#include +#endif +#if 1 +#include +#endif +#if 1 +#include // and _ftime +#endif + +#if 0 +# include +# if 0 +# include +# endif +# if 0 +# include +# endif +#elif 0 + /* IIRC winsock.h must be included before windows.h */ +# include +#else +# if 1 +# include +# endif +# if 1 +# include +# endif +# if 1 +# include +# endif +# if 1 +# include +# endif +#endif + +#if 1 +# include +#endif +#if 1 +# include +#endif + +#ifdef _WIN32 +# if 0 +# include +# endif +# if 0 +# include +# endif +# include +#endif + +#if ! 1 +# if 0 +# define strcasecmp stricmp +# else +extern "C" int strcasecmp(const char *s1, const char *s2); +# endif +#endif + +#if ! 1 +# if 0 +# define getpid _getpid +# endif +#endif + +#if ! 1 +# if 0 +# define ss_family __ss_family +# endif +#endif + +/* Minimum of signed integral types. */ +#ifndef INT8_MIN +# define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +# define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +# define INT32_MIN (-2147483647-1) +#endif +#ifndef INT64_MIN +# define INT64_MIN (-int64_t(9223372036854775807)-1) +#endif +/* Maximum of signed integral types. */ +#ifndef INT_MAX +# define INT8_MAX (127) +#endif +#ifndef INT16_MAX +# define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +# define INT32_MAX (2147483647) +#endif +#ifndef INT64_MAX +# define INT64_MAX (int64_t(9223372036854775807)) +#endif + +/* Maximum of unsigned integral types. */ +#ifndef UINT8_MAX +# define UINT8_MAX (255) +#endif +#ifndef UINT16_MAX +# define UINT16_MAX (65535) +#endif +#ifndef UINT32_MAX +# define UINT32_MAX (4294967295U) +#endif +#ifndef UINT64_MAX +# define UINT64_MAX (uint64_t(18446744073709551615)) +#endif + +#ifndef NULL +#define NULL 0 +#endif + +#if 1 +# include +#else +# include +#endif + +#endif /* ?__LIBSNMP_H_INCLUDED__ */ diff --git a/platform/src/3rd/os_specific/oe2203/include/snmp_pp/config_snmp_pp.h b/platform/src/3rd/os_specific/oe2203/include/snmp_pp/config_snmp_pp.h new file mode 100644 index 00000000..c8375b75 --- /dev/null +++ b/platform/src/3rd/os_specific/oe2203/include/snmp_pp/config_snmp_pp.h @@ -0,0 +1,289 @@ +/*_############################################################################ + _## + _## config_snmp_pp.h.in + _## + _## SNMP++ v3.3 + _## ----------------------------------------------- + _## Copyright (c) 2001-2013 Jochen Katz, Frank Fock + _## + _## This software is based on SNMP++2.6 from Hewlett Packard: + _## + _## Copyright (c) 1996 + _## Hewlett-Packard Company + _## + _## ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS. + _## Permission to use, copy, modify, distribute and/or sell this software + _## and/or its documentation is hereby granted without fee. User agrees + _## to display the above copyright notice and this license notice in all + _## copies of the software and any documentation of the software. User + _## agrees to assume all liability for the use of the software; + _## Hewlett-Packard and Jochen Katz make no representations about the + _## suitability of this software for any purpose. It is provided + _## "AS-IS" without warranty of any kind, either express or implied. User + _## hereby grants a royalty-free license to any and all derivatives based + _## upon this software code base. + _## + _##########################################################################*/ + +#ifndef _CONFIG_SNMP_PP_H_ +#define _CONFIG_SNMP_PP_H_ + +#ifndef __LIBSNMP_H_INCLUDED__ +#include +#endif + +#define SNMP_PP_VERSION_STRING "3.3.12" +#define SNMP_PP_VERSION 3 +#define SNMP_PP_RELEASE 3 +#define SNMP_PP_PATCHLEVEL 12 + +//! The maximum size of a message that can be sent or received. +#define MAX_SNMP_PACKET 4096 + +#ifndef DLLOPT +#if defined (WIN32) && defined (SNMP_PP_DLL) +#ifdef SNMP_PP_EXPORTS +#define DLLOPT __declspec(dllexport) +#define DLLOPT_TEMPL +#else +#define DLLOPT __declspec(dllimport) +#define DLLOPT_TEMPL extern +#endif +#else +#define DLLOPT +#define DLLOPT_TEMPL +#endif +#endif + +/* + * some permanent parts from autoconf process + */ +#if 1 +#define _SNMPv3 1 +#else +#define _NO_SNMPv3 1 +#endif +#if 1 +#define SNMP_PP_IPv6 1 +#endif +#if 1 +#define ENABLE_THREADS 1 +#else +#define _NO_THREADS +#endif +#if 1 +#define HAVE_LIBSSL 1 +#endif +#if 0 +#define HAVE_LIBTOMCRYPT 1 +#endif +#if 0 +#define HAVE_LIBDES 1 +#endif +#if 1 +#define HAVE_PTHREAD 1 +#endif + +// define SNMP_PP_NAMESPACE to enclose all library names in Snmp_pp namespace +#if 1 +#define SNMP_PP_NAMESPACE +#else +#undef SNMP_PP_NAMESPACE +#endif + +// If you do not use SNMP++ for commercial purposes or if you +// have licensed IDEA (read README.v3) you may define the following +// to enable IDEA support. (note this is not defined by a rfc) +// #define _USE_IDEA + +#if defined(_SNMPv3) || !defined(_NO_SNMPv3) +# if defined(HAVE_LIBSSL) +# define _USE_OPENSSL +# elif defined(HAVE_LIBTOMCRYPT) +# define _USE_LIBTOMCRYPT +# elif HAVE_LIBDES +# define _USE_3DES_EDE +# else +# warn No crypto library found - disable SNMPv3 +# undef _SNMPv3 +# define _NO_SNMPv3 +# endif +#endif + +// define _NO_LOGGING if you do not want any logging output +// (increases performance drastically and minimizes memory consumption) +#if 1 +#undef _NO_LOGGING +#else +#define _NO_LOGGING +#endif + +#if 1 +#ifndef WITHOUT_LOG_PROFILES +#define WITH_LOG_PROFILES 1 +#endif +#else +#undef WITH_LOG_PROFILES +#endif + +// define _IPX_ADDRESS and/or _MAC_ADDRESS if you want to use the +// classess IpxAddress/IpxSockAddress and/or MacAddress +#if 0 +#define _MAC_ADDRESS +#else +#undef _MAC_ADDRESS +#endif +#if 0 +#define _IPX_ADDRESS +#else +#undef _IPX_ADDRESS +#endif + +// define this if you want to send out broadcasts +#define SNMP_BROADCAST + +// Some socket types +#if !(defined (CPU) && CPU == PPC603) && (defined __GNUC__ || defined __FreeBSD__ || defined _AIX) && ! defined __MINGW32__ + typedef socklen_t SocketLengthType; +#else + typedef int SocketLengthType; +#endif + +#ifdef SNMP_PP_IPv6 + typedef struct sockaddr_storage SocketAddrType; +#else + typedef struct sockaddr_in SocketAddrType; +#endif + +// Not fully tested! +//#define HAVE_POLL_SYSCALL + +// Some older(?) compilers need a special declaration of +// template classes +// #define _OLD_TEMPLATE_COLLECTION + +// can we use the reentrant version of these functions or +// are the standard functions thread safe +#ifdef __CYGWIN32__ +#define HAVE_REENTRANT_LOCALTIME +#define HAVE_REENTRANT_GETHOSTBYADDR +#define HAVE_REENTRANT_GETHOSTBYNAME +#elif __MINGW32__ +//FIXME: snmp++/src/address.cpp:865: error: `inet_ntop' was not declared in this scope +//FIXME: snmp++/src/address.cpp:988: error: `inet_pton' was not declared in this scope +//FIXME: snmp++/src/notifyqueue.cpp:538: error: `inet_pton' was not declared in this scope +#define HAVE_REENTRANT_GETHOSTBYNAME +#define HAVE_REENTRANT_LOCALTIME +#define HAVE_REENTRANT_GETHOSTBYADDR +#elif __DECCXX +#define HAVE_REENTRANT_GETHOSTBYNAME +#define HAVE_REENTRANT_GETHOSTBYADDR +#elif __HP_aCC +#define HAVE_REENTRANT_GETHOSTBYNAME +#define HAVE_REENTRANT_GETHOSTBYADDR +#elif _MSC_VER +#define HAVE_REENTRANT_GETHOSTBYNAME +#define HAVE_REENTRANT_LOCALTIME +#define HAVE_REENTRANT_GETHOSTBYADDR +#elif _AIX +#define HAVE_REENTRANT_GETHOSTBYNAME +#define HAVE_REENTRANT_GETHOSTBYADDR +#endif + +// Define a unsigned 64 bit integer: +#ifdef WIN32 +#include +#if defined(HAVE_WINSOCK2_H) +#include +#elif defined(HAVE_WINSOCK_H) +#include +#endif +#ifdef HAVE_WSTCPIP_H +#include +#endif +#ifdef HAVE_WSPIAPI_H +#include +#endif +#ifdef __BCPLUSPLUS__ +typedef unsigned __int64 pp_uint64; +typedef __int64 pp_int64; +#else +typedef ULONGLONG pp_uint64; +typedef LONGLONG pp_int64; +#endif +#else // not WIN32 +typedef unsigned long long pp_uint64; +typedef long long pp_int64; +#endif + +// Define a type used for sockets +#ifdef _MSC_VER + typedef SOCKET SnmpSocket; +#else + typedef int SnmpSocket; +#endif + +#ifdef HAVE_POLL_SYSCALL +#include +#endif + +#define SNMP_PP_DEFAULT_SNMP_PORT 161 // standard port # for SNMP +#define SNMP_PP_DEFAULT_SNMP_TRAP_PORT 162 // standard port # for SNMP traps + +/////////////////////////////////////////////////////////////////////// +// Changes below this line should not be necessary +/////////////////////////////////////////////////////////////////////// + + +// Make use of mutable keyword +//#define SNMP_PP_MUTABLE mutable +#define SNMP_PP_MUTABLE + +#define SAFE_INT_CAST(expr) ((int)(expr)) +#define SAFE_UINT_CAST(expr) ((unsigned int)(expr)) + +// Safe until 32 bit second counter wraps to zero (time functions) +#define SAFE_LONG_CAST(expr) ((long)(expr)) +#define SAFE_ULONG_CAST(expr) ((unsigned long)(expr)) + +#ifdef ENABLE_THREADS +#ifdef WIN32 + +#ifndef _THREADS +#define _WIN32THREADS +#define VC_EXTRALEAN +#define _THREADS +#endif + +#else // !WIN32 + +#ifndef _THREADS +#define _THREADS +#endif + +#ifdef __APPLE__ +#ifndef __unix +#define __unix +#endif +#endif + +#ifndef POSIX_THREADS +#ifdef HAVE_PTHREAD +#define POSIX_THREADS +// Use error checking by default since AGENT++ 4.0.8, define +// AGENTPP_PTHREAD_RECURSIVE here to get behavior of AGENT++ 4.0.7 and before: +// #define AGENTPP_PTHREAD_RECURSIVE +#endif +#endif + +#endif // WIN32 +#endif // ENABLE_THREADS + +#ifdef _THREADS +#ifndef _WIN32THREADS +#include +#endif +#endif + + +#endif // _CONFIG_SNMP_PP_H_ diff --git a/platform/src/3rd/src_package/Boost/ReadMe.txt b/platform/src/3rd/src_package/Boost/ReadMe.txt index 50e9e992..38a32f4e 100644 --- a/platform/src/3rd/src_package/Boost/ReadMe.txt +++ b/platform/src/3rd/src_package/Boost/ReadMe.txt @@ -3,6 +3,13 @@ writen by yikenan,2018-01-02 编译参数: +麒麟操作系统: + 先确认是不是安装了icu模块,boost-regex需要使用,否则在执行./bootstrap.sh 时会提示icu not found + + apt-get install libicu-dev + 会依赖安装icu-devtools libicu66 +安装后先执行 ./bootstrap.sh 生成b2等编译工具 + Linux: ./b2 stage --stagedir=/opt/boost/ linkflags="-Wl,-z,origin -Wl,-rpath,'\$ORIGIN'" --layout=system link=shared runtime-link=shared threading=multi variant=release -a -q -d+2 address-model=64 --with-regex --with-chrono --with-date_time --with-filesystem --with-program_options --with-system --with-thread --with-locale diff --git a/platform/src/3rd/src_package/Lua/libreadline-dev_8.0-4_amd64.deb b/platform/src/3rd/src_package/Lua/libreadline-dev_8.0-4_amd64.deb new file mode 100644 index 0000000000000000000000000000000000000000..04bac3f03543781e4164eed2ab584b0bea31b323 GIT binary patch literal 142900 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%0Abee+pQA2= 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 literal 0 HcmV?d00001 diff --git a/platform/src/3rd/src_package/Lua/lua编译.txt b/platform/src/3rd/src_package/Lua/lua编译.txt index 3e9cb02f..088cdd0d 100644 --- a/platform/src/3rd/src_package/Lua/lua编译.txt +++ b/platform/src/3rd/src_package/Lua/lua编译.txt @@ -9,6 +9,14 @@ linuxƽ̨ 2luaĬֻ뾲̬⣬޸makefileɶ̬⣬lua_makefileļеMakefileļ滻luaԴеļ 3ִmake linux +linux²luacᵼ豸ģfbd_designer﷨ʱʧܣΪ﷨ʹluacִеġ +(ubuntu)luac +1װreadlineִsudo apt -d download libreadline-devصأȻװ +2liblua.soĻϣsrc/Makefile43еLUAC_T=luacעʹ +3make linuxsrcĿ¼¾ͻluac +4luacֱ𿽱platformproductӦļ +5ʱIJֻҪڱ뻷װlibreadline-devͿԣлװҲ + 2LuaBridge LuaBridgeһluaװ⣬ģʵ֣Ҫ룬ѹļincludeĿ¼мɡ ڸÿڷֵͲƥ£ֱ⣬޸Դ룬޸ݲ鿴Stack.patch \ No newline at end of file diff --git a/platform/src/3rd/src_package/ProtoBuf/ReadMe.txt b/platform/src/3rd/src_package/ProtoBuf/ReadMe.txt index cc6ff86d..2527264a 100644 --- a/platform/src/3rd/src_package/ProtoBuf/ReadMe.txt +++ b/platform/src/3rd/src_package/ProtoBuf/ReadMe.txt @@ -12,6 +12,8 @@ gmake install 只需复制动态库到platform目录。 +以上编译指令默认使用的参数:-O2 -g -DNDEBUG + Windows: 在vsprojects\config.h增加: #define _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS diff --git a/platform/src/3rd/src_package/ZeroMQ/ReadMe.txt b/platform/src/3rd/src_package/ZeroMQ/ReadMe.txt index 8b92ebe0..32ab64bf 100644 --- a/platform/src/3rd/src_package/ZeroMQ/ReadMe.txt +++ b/platform/src/3rd/src_package/ZeroMQ/ReadMe.txt @@ -1,3 +1,12 @@ +######################################## +实际使用的版本已经升级到较高版本,与当前文档不一定一致了,通过查看老版本生成的Makefile文件,其使用的默认参数如下: +CXXFLAGS = -pedantic -Werror -Wall -Wno-long-long -g -O2 -ffat-lto-objects + +麒麟操作系统下: +./autogen.sh时有个提示configure.ac: not using Gettext +尝试安装gettext也没有解决,所以先跳过此问题,不知道是否有影响:apt-get install gettext + +######################################## writen by yikenan,2018-01-02 diff --git a/platform/src/3rd/src_package/hiredis/README.txt b/platform/src/3rd/src_package/hiredis/README.txt index 5911f902..bb4de707 100644 --- a/platform/src/3rd/src_package/hiredis/README.txt +++ b/platform/src/3rd/src_package/hiredis/README.txt @@ -1,4 +1,4 @@ -说明:分别是hiredis和它的异步依赖event的压缩包 +说明:分别是hiredis和它的异步依赖event的压缩包。编译生成了.a和.so,项目中暂时使用的.a的静态库 libevent编译: ./configure --prefix=/home/ykn/3rd_src/install/libevent/ --with-pic LDFLAGS="-Wl,-rpath,'\$\$ORIGIN' $LDFLAGS" diff --git a/platform/src/3rd/src_package/log4cplus/编译说明.txt b/platform/src/3rd/src_package/log4cplus/编译说明.txt index 84dfc5ee..effbf4b6 100644 --- a/platform/src/3rd/src_package/log4cplus/编译说明.txt +++ b/platform/src/3rd/src_package/log4cplus/编译说明.txt @@ -9,6 +9,16 @@ d)޸Դļ޸ݲ鿴consoleappender.cxx.patchloggingevent.cxx.patchloggingevent.h.patch 4ļlog4cplus.patch windowsƽ̨򲹶patch.exe -p1 --binary < ..\log4cplus.patch - linuxƽ̨򲹶patch.exe -p1 < ..\log4cplus.patch -4Unicode汾 + linuxƽ̨򲹶patch -p1 < ..\log4cplus.patch + ע + 鿴patchļǸwindowsأlinuxӦòҪϵͨldd鿴ǰsoûзʹboost_locale +5Unicode汾 +6 +Linux releaseδpatchиգloggingevent.hһʵlinuxԴļûУ +./configure CXXFLAGS="-std=c++0x" --prefix=/root/dev/3rd/log4cplus_bin +make +make install + +Linux debug˷ֻǼ-gʵʱ뻹ʹ-O2Ż +./configure CXXFLAGS="-std=c++0x -g" --prefix=/root/dev/3rd/log4cplus_bin diff --git a/platform/src/3rd/src_package/oatpp/HttpProcessor.cpp b/platform/src/3rd/src_package/oatpp/HttpProcessor.cpp new file mode 100644 index 00000000..be74a12a --- /dev/null +++ b/platform/src/3rd/src_package/oatpp/HttpProcessor.cpp @@ -0,0 +1,442 @@ +/*************************************************************************** + * + * Project _____ __ ____ _ _ + * ( _ ) /__\ (_ _)_| |_ _| |_ + * )(_)( /(__)\ )( (_ _)(_ _) + * (_____)(__)(__)(__) |_| |_| + * + * + * Copyright 2018-present, Leonid Stryzhevskyi + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************/ + +#include "HttpProcessor.hpp" + +#include "oatpp/web/protocol/http/incoming/SimpleBodyDecoder.hpp" +#include "oatpp/core/data/stream/BufferStream.hpp" + +namespace oatpp { namespace web { namespace server { + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Components + +HttpProcessor::Components::Components(const std::shared_ptr& pRouter, + const std::shared_ptr& pContentEncodingProviders, + const std::shared_ptr& pBodyDecoder, + const std::shared_ptr& pErrorHandler, + const RequestInterceptors& pRequestInterceptors, + const ResponseInterceptors& pResponseInterceptors, + const std::shared_ptr& pConfig) + : router(pRouter) + , contentEncodingProviders(pContentEncodingProviders) + , bodyDecoder(pBodyDecoder) + , errorHandler(pErrorHandler) + , requestInterceptors(pRequestInterceptors) + , responseInterceptors(pResponseInterceptors) + , config(pConfig) +{} + +HttpProcessor::Components::Components(const std::shared_ptr& pRouter) + : Components(pRouter, + nullptr, + std::make_shared(), + handler::DefaultErrorHandler::createShared(), + {}, + {}, + std::make_shared()) +{} + +HttpProcessor::Components::Components(const std::shared_ptr& pRouter, const std::shared_ptr& pConfig) + : Components(pRouter, + nullptr, + std::make_shared(), + handler::DefaultErrorHandler::createShared(), + {}, + {}, + pConfig) +{} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Other + +HttpProcessor::ProcessingResources::ProcessingResources(const std::shared_ptr& pComponents, + const provider::ResourceHandle& pConnection) + : components(pComponents) + , connection(pConnection) + , headersInBuffer(components->config->headersInBufferInitial) + , headersOutBuffer(components->config->headersOutBufferInitial) + , headersReader(&headersInBuffer, components->config->headersReaderChunkSize, components->config->headersReaderMaxSize) + , inStream(data::stream::InputStreamBufferedProxy::createShared(connection.object, std::make_shared(data::buffer::IOBuffer::BUFFER_SIZE, 0))) +{} + +std::shared_ptr +HttpProcessor::processNextRequest(ProcessingResources& resources, + const std::shared_ptr& request, + ConnectionState& connectionState) +{ + + std::shared_ptr response; + + try{ + + for(auto& interceptor : resources.components->requestInterceptors) { + response = interceptor->intercept(request); + if(response) { + return response; + } + } + + auto route = resources.components->router->getRoute(request->getStartingLine().method, request->getStartingLine().path); + + if(!route) { + + data::stream::BufferOutputStream ss; + ss << "No mapping for HTTP-method: '" << request->getStartingLine().method.toString() + << "'";//, URL: '" << request->getStartingLine().path.toString() << "'"; + + connectionState = ConnectionState::CLOSING; + return resources.components->errorHandler->handleError(protocol::http::Status::CODE_404, ss.toString()); + + } + + request->setPathVariables(route.getMatchMap()); + return route.getEndpoint()->handle(request); + + } catch (oatpp::web::protocol::http::HttpError& error) { + response = resources.components->errorHandler->handleError(error.getInfo().status, error.getMessage(), error.getHeaders()); + connectionState = ConnectionState::CLOSING; + } catch (std::exception& error) { + response = resources.components->errorHandler->handleError(protocol::http::Status::CODE_500, error.what()); + connectionState = ConnectionState::CLOSING; + } catch (...) { + response = resources.components->errorHandler->handleError(protocol::http::Status::CODE_500, "Unhandled Error"); + connectionState = ConnectionState::CLOSING; + } + + return response; + +} + +HttpProcessor::ConnectionState HttpProcessor::processNextRequest(ProcessingResources& resources) { + + oatpp::web::protocol::http::HttpError::Info error; + auto headersReadResult = resources.headersReader.readHeaders(resources.inStream.get(), error); + + if(error.ioStatus <= 0) { + return ConnectionState::DEAD; + } + + ConnectionState connectionState = ConnectionState::ALIVE; + std::shared_ptr request; + std::shared_ptr response; + + if(error.status.code != 0) { + response = resources.components->errorHandler->handleError(error.status, "Invalid Request Headers"); + connectionState = ConnectionState::CLOSING; + } else { + + request = protocol::http::incoming::Request::createShared(resources.connection.object, + headersReadResult.startingLine, + headersReadResult.headers, + resources.inStream, + resources.components->bodyDecoder); + + response = processNextRequest(resources, request, connectionState); + + try { + + for (auto& interceptor : resources.components->responseInterceptors) { + response = interceptor->intercept(request, response); + if (!response) { + response = resources.components->errorHandler->handleError( + protocol::http::Status::CODE_500, + "Response Interceptor returned an Invalid Response - 'null'" + ); + connectionState = ConnectionState::CLOSING; + } + } + + } catch (...) { + response = resources.components->errorHandler->handleError( + protocol::http::Status::CODE_500, + "Unhandled Error in Response Interceptor" + ); + connectionState = ConnectionState::CLOSING; + } + + response->putHeaderIfNotExists(protocol::http::Header::SERVER, protocol::http::Header::Value::SERVER); + protocol::http::utils::CommunicationUtils::considerConnectionState(request, response, connectionState); + + switch(connectionState) { + + case ConnectionState::ALIVE : + response->putHeaderIfNotExists(protocol::http::Header::CONNECTION, protocol::http::Header::Value::CONNECTION_KEEP_ALIVE); + break; + + case ConnectionState::CLOSING: + case ConnectionState::DEAD: + response->putHeaderIfNotExists(protocol::http::Header::CONNECTION, protocol::http::Header::Value::CONNECTION_CLOSE); + break; + + default: + break; + + } + + } + + auto contentEncoderProvider = + protocol::http::utils::CommunicationUtils::selectEncoder(request, resources.components->contentEncodingProviders); + + response->send(resources.connection.object.get(), &resources.headersOutBuffer, contentEncoderProvider.get()); + + /* Delegate connection handling to another handler only after the response is sent to the client */ + if(connectionState == ConnectionState::DELEGATED) { + auto handler = response->getConnectionUpgradeHandler(); + if(handler) { + handler->handleConnection(resources.connection, response->getConnectionUpgradeParameters()); + connectionState = ConnectionState::DELEGATED; + } else { + OATPP_LOGW("[oatpp::web::server::HttpProcessor::processNextRequest()]", "Warning. ConnectionUpgradeHandler not set!"); + connectionState = ConnectionState::CLOSING; + } + } + + return connectionState; + +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Task + +HttpProcessor::Task::Task(const std::shared_ptr& components, + const provider::ResourceHandle& connection, + TaskProcessingListener* taskListener) + : m_components(components) + , m_connection(connection) + , m_taskListener(taskListener) +{ + m_taskListener->onTaskStart(m_connection); +} + +HttpProcessor::Task::Task(HttpProcessor::Task &&other) + : m_components(std::move(other.m_components)) + , m_connection(std::move(other.m_connection)) + , m_taskListener(other.m_taskListener) +{ + other.m_taskListener = nullptr; +} + +HttpProcessor::Task::~Task() { + if (m_taskListener != nullptr) { + m_taskListener->onTaskEnd(m_connection); + } +} + +HttpProcessor::Task &HttpProcessor::Task::operator=(HttpProcessor::Task &&other) { + m_components = std::move(other.m_components); + m_connection = std::move(other.m_connection); + m_taskListener = other.m_taskListener; + other.m_taskListener = nullptr; + return *this; +} + +void HttpProcessor::Task::run(){ + + m_connection.object->initContexts(); + + ProcessingResources resources(m_components, m_connection); + + ConnectionState connectionState; + + try { + + do { + + connectionState = HttpProcessor::processNextRequest(resources); + + } while (connectionState == ConnectionState::ALIVE); + + } catch (...) { + // DO NOTHING + } + +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// HttpProcessor::Coroutine + +HttpProcessor::Coroutine::Coroutine(const std::shared_ptr& components, + const provider::ResourceHandle& connection, + TaskProcessingListener* taskListener) + : m_components(components) + , m_connection(connection) + , m_headersInBuffer(components->config->headersInBufferInitial) + , m_headersReader(&m_headersInBuffer, components->config->headersReaderChunkSize, components->config->headersReaderMaxSize) + , m_headersOutBuffer(std::make_shared(components->config->headersOutBufferInitial)) + , m_inStream(data::stream::InputStreamBufferedProxy::createShared(m_connection.object, std::make_shared(data::buffer::IOBuffer::BUFFER_SIZE, 0))) + , m_connectionState(ConnectionState::ALIVE) + , m_taskListener(taskListener) +{ + m_taskListener->onTaskStart(m_connection); +} + +HttpProcessor::Coroutine::~Coroutine() { + m_taskListener->onTaskEnd(m_connection); +} + +HttpProcessor::Coroutine::Action HttpProcessor::Coroutine::act() { + return m_connection.object->initContextsAsync().next(yieldTo(&HttpProcessor::Coroutine::parseHeaders)); +} + +HttpProcessor::Coroutine::Action HttpProcessor::Coroutine::parseHeaders() { + return m_headersReader.readHeadersAsync(m_inStream).callbackTo(&HttpProcessor::Coroutine::onHeadersParsed); +} + +oatpp::async::Action HttpProcessor::Coroutine::onHeadersParsed(const RequestHeadersReader::Result& headersReadResult) { + + m_currentRequest = protocol::http::incoming::Request::createShared(m_connection.object, + headersReadResult.startingLine, + headersReadResult.headers, + m_inStream, + m_components->bodyDecoder); + + for(auto& interceptor : m_components->requestInterceptors) { + m_currentResponse = interceptor->intercept(m_currentRequest); + if(m_currentResponse) { + return yieldTo(&HttpProcessor::Coroutine::onResponseFormed); + } + } + + m_currentRoute = m_components->router->getRoute(headersReadResult.startingLine.method.toString(), headersReadResult.startingLine.path.toString()); + + if(!m_currentRoute) { + + data::stream::BufferOutputStream ss; + ss << "No mapping for HTTP-method: '" << headersReadResult.startingLine.method.toString() + << "'"; //, URL: '" << headersReadResult.startingLine.path.toString() << "'"; + m_currentResponse = m_components->errorHandler->handleError(protocol::http::Status::CODE_404, ss.toString()); + m_connectionState = ConnectionState::CLOSING; + return yieldTo(&HttpProcessor::Coroutine::onResponseFormed); + } + + m_currentRequest->setPathVariables(m_currentRoute.getMatchMap()); + + return yieldTo(&HttpProcessor::Coroutine::onRequestFormed); + +} + +HttpProcessor::Coroutine::Action HttpProcessor::Coroutine::onRequestFormed() { + return m_currentRoute.getEndpoint()->handleAsync(m_currentRequest).callbackTo(&HttpProcessor::Coroutine::onResponse); +} + +HttpProcessor::Coroutine::Action HttpProcessor::Coroutine::onResponse(const std::shared_ptr& response) { + m_currentResponse = response; + return yieldTo(&HttpProcessor::Coroutine::onResponseFormed); +} + +HttpProcessor::Coroutine::Action HttpProcessor::Coroutine::onResponseFormed() { + + for(auto& interceptor : m_components->responseInterceptors) { + m_currentResponse = interceptor->intercept(m_currentRequest, m_currentResponse); + if(!m_currentResponse) { + m_currentResponse = m_components->errorHandler->handleError( + protocol::http::Status::CODE_500, + "Response Interceptor returned an Invalid Response - 'null'" + ); + } + } + + m_currentResponse->putHeaderIfNotExists(protocol::http::Header::SERVER, protocol::http::Header::Value::SERVER); + oatpp::web::protocol::http::utils::CommunicationUtils::considerConnectionState(m_currentRequest, m_currentResponse, m_connectionState); + + switch(m_connectionState) { + + case ConnectionState::ALIVE : + m_currentResponse->putHeaderIfNotExists(protocol::http::Header::CONNECTION, protocol::http::Header::Value::CONNECTION_KEEP_ALIVE); + break; + + case ConnectionState::CLOSING: + case ConnectionState::DEAD: + m_currentResponse->putHeaderIfNotExists(protocol::http::Header::CONNECTION, protocol::http::Header::Value::CONNECTION_CLOSE); + break; + + default: + break; + + } + + auto contentEncoderProvider = + protocol::http::utils::CommunicationUtils::selectEncoder(m_currentRequest, m_components->contentEncodingProviders); + + return protocol::http::outgoing::Response::sendAsync(m_currentResponse, m_connection.object, m_headersOutBuffer, contentEncoderProvider) + .next(yieldTo(&HttpProcessor::Coroutine::onRequestDone)); + +} + +HttpProcessor::Coroutine::Action HttpProcessor::Coroutine::onRequestDone() { + + switch (m_connectionState) { + case ConnectionState::ALIVE: + return yieldTo(&HttpProcessor::Coroutine::parseHeaders); + + /* Delegate connection handling to another handler only after the response is sent to the client */ + case ConnectionState::DELEGATED: { + auto handler = m_currentResponse->getConnectionUpgradeHandler(); + if(handler) { + handler->handleConnection(m_connection, m_currentResponse->getConnectionUpgradeParameters()); + m_connectionState = ConnectionState::DELEGATED; + } else { + OATPP_LOGW("[oatpp::web::server::HttpProcessor::Coroutine::onResponseFormed()]", "Warning. ConnectionUpgradeHandler not set!"); + m_connectionState = ConnectionState::CLOSING; + } + break; + } + + default: + break; + + } + + return finish(); + +} + +HttpProcessor::Coroutine::Action HttpProcessor::Coroutine::handleError(Error* error) { + + if(error) { + + if(error->is()) { + auto aioe = static_cast(error); + if(aioe->getCode() == oatpp::IOError::BROKEN_PIPE) { + return aioe; // do not report BROKEN_PIPE error + } + } + + if(m_currentResponse) { + //OATPP_LOGE("[oatpp::web::server::HttpProcessor::Coroutine::handleError()]", "Unhandled error. '%s'. Dropping connection", error->what()); + return error; + } + + m_currentResponse = m_components->errorHandler->handleError(protocol::http::Status::CODE_500, error->what()); + return yieldTo(&HttpProcessor::Coroutine::onResponseFormed); + + } + + return error; + +} + +}}} diff --git a/platform/src/3rd/src_package/oatpp/HttpProcessor.patch b/platform/src/3rd/src_package/oatpp/HttpProcessor.patch new file mode 100644 index 00000000..0bc9027a --- /dev/null +++ b/platform/src/3rd/src_package/oatpp/HttpProcessor.patch @@ -0,0 +1,21 @@ +--- /home/ykn/3rd/oatpp-master-20220214/oatpp-master/src/oatpp/web/server/HttpProcessor.cpp ++++ /media/ykn/tf128/00_svn/platform/platform/src/3rd/src_package/oatpp/HttpProcessor.cpp +@@ -104,7 +104,7 @@ + + data::stream::BufferOutputStream ss; + ss << "No mapping for HTTP-method: '" << request->getStartingLine().method.toString() +- << "', URL: '" << request->getStartingLine().path.toString() << "'"; ++ << "'";//, URL: '" << request->getStartingLine().path.toString() << "'"; + + connectionState = ConnectionState::CLOSING; + return resources.components->errorHandler->handleError(protocol::http::Status::CODE_404, ss.toString()); +@@ -326,7 +326,7 @@ + + data::stream::BufferOutputStream ss; + ss << "No mapping for HTTP-method: '" << headersReadResult.startingLine.method.toString() +- << "', URL: '" << headersReadResult.startingLine.path.toString() << "'"; ++ << "'"; //, URL: '" << headersReadResult.startingLine.path.toString() << "'"; + m_currentResponse = m_components->errorHandler->handleError(protocol::http::Status::CODE_404, ss.toString()); + m_connectionState = ConnectionState::CLOSING; + return yieldTo(&HttpProcessor::Coroutine::onResponseFormed); + diff --git a/platform/src/3rd/src_package/oatpp/ReadMe.txt b/platform/src/3rd/src_package/oatpp/ReadMe.txt index 11a87c67..7cba9c58 100644 --- a/platform/src/3rd/src_package/oatpp/ReadMe.txt +++ b/platform/src/3rd/src_package/oatpp/ReadMe.txt @@ -1,6 +1,14 @@ writen by yikenan,2021-11-29 +######################################################################################################### +2022-09-14,yikenan +为避免某些安全扫描工具报“跨站脚本编辑”漏洞问题,修改了代码: +oatpp-master/src/oatpp/web/server/HttpProcessor.cpp +当端点不存在时,不原样返回请求的url,避免被跨站攻击利用 + +将本路径下的该文件替换到代码路径,差异见HttpProcessor.patch + ######################################################################################################### Linux: @@ -23,10 +31,26 @@ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=~/3rd/install_path/ 麒麟: -DZLIB_INCLUDE_DIR=/home/ykn/00_svn/platform_home/platform/src/3rd/include -DZLIB_LIBRARY_RELEASE=/home/ykn/00_svn/platform_home/platform/kylin10d_debug/libz.so +######################################################################################################### +麒麟编译过程 +先编译oatpp-master-20220214 +1、将HttpProcessor.cpp补丁打上,用patch有错误,人工对照修改就行 +2、mkdir build && cd build +3、cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/root/code/3rd/bin/otapp +4、make && make install +再编译组件 oatpp-websocket-master-20220214 +1、解压后,mkdir build && cd build +2、cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/root/code/3rd/bin/otapp -DCMAKE_PREFIX_PATH=/root/code/3rd/bin/otapp +3、make && make install +再编译组件oatpp-zlib-master-20220214 +1、解压后,mkdir build && cd build +2、cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/root/code/3rd/bin/otapp -DCMAKE_PREFIX_PATH=/root/code/3rd/bin/otapp -DZLIB_INCLUDE_DIR=/root/code/platform/ISCS6000_HOME/platform/src/3rd/include -DZLIB_LIBRARY_RELEASE=/root/code/platform/ISCS6000_HOME/platform/kylin10d_release/libz.so +3、make && make install +暂时项目中使用的是.a的静态库 ######################################################################################################### Windows: