Import libevent
Change-Id: Ic75f4cac5eb07ffaba8f97d10673d7d7e2b1762d
This commit is contained in:
parent
65f76edb8f
commit
e985b92992
208 changed files with 128364 additions and 2 deletions
|
@ -837,6 +837,37 @@
|
|||
./usr/include/err.h minix-sys
|
||||
./usr/include/errno.h minix-sys
|
||||
./usr/include/eti.h minix-sys
|
||||
./usr/include/evdns.h minix-sys
|
||||
./usr/include/event.h minix-sys
|
||||
./usr/include/event2 minix-sys
|
||||
./usr/include/event2/buffer.h minix-sys
|
||||
./usr/include/event2/buffer_compat.h minix-sys
|
||||
./usr/include/event2/bufferevent.h minix-sys
|
||||
./usr/include/event2/bufferevent_compat.h minix-sys
|
||||
./usr/include/event2/bufferevent_ssl.h minix-sys
|
||||
./usr/include/event2/bufferevent_struct.h minix-sys
|
||||
./usr/include/event2/dns.h minix-sys
|
||||
./usr/include/event2/dns_compat.h minix-sys
|
||||
./usr/include/event2/dns_struct.h minix-sys
|
||||
./usr/include/event2/event-config.h minix-sys
|
||||
./usr/include/event2/event.h minix-sys
|
||||
./usr/include/event2/event_compat.h minix-sys
|
||||
./usr/include/event2/event_struct.h minix-sys
|
||||
./usr/include/event2/http.h minix-sys
|
||||
./usr/include/event2/http_compat.h minix-sys
|
||||
./usr/include/event2/http_struct.h minix-sys
|
||||
./usr/include/event2/keyvalq_struct.h minix-sys
|
||||
./usr/include/event2/listener.h minix-sys
|
||||
./usr/include/event2/rpc.h minix-sys
|
||||
./usr/include/event2/rpc_compat.h minix-sys
|
||||
./usr/include/event2/rpc_struct.h minix-sys
|
||||
./usr/include/event2/tag.h minix-sys
|
||||
./usr/include/event2/tag_compat.h minix-sys
|
||||
./usr/include/event2/thread.h minix-sys
|
||||
./usr/include/event2/util.h minix-sys
|
||||
./usr/include/evhttp.h minix-sys
|
||||
./usr/include/evrpc.h minix-sys
|
||||
./usr/include/evutil.h minix-sys
|
||||
./usr/include/execinfo.h minix-sys
|
||||
./usr/include/fcntl.h minix-sys
|
||||
./usr/include/fenv.h minix-sys
|
||||
|
@ -2042,6 +2073,11 @@
|
|||
./usr/lib/libelf.so.0.0 minix-sys
|
||||
./usr/lib/libelf.so.0 minix-sys
|
||||
./usr/lib/libelf.so minix-sys
|
||||
./usr/lib/libevent.a minix-sys
|
||||
./usr/lib/libevent_pic.a minix-sys
|
||||
./usr/lib/libevent.so.4.0 minix-sys
|
||||
./usr/lib/libevent.so.4 minix-sys
|
||||
./usr/lib/libevent.so minix-sys
|
||||
./usr/lib/libexec.a minix-sys
|
||||
./usr/lib/libexecinfo.a minix-sys
|
||||
./usr/lib/libexecinfo_pic.a minix-sys
|
||||
|
@ -2996,6 +3032,8 @@
|
|||
./usr/man/man3/bswap64.3 minix-sys
|
||||
./usr/man/man3/btowc.3 minix-sys
|
||||
./usr/man/man3/btree.3 minix-sys
|
||||
./usr/man/man3/bufferevent.3 minix-sys
|
||||
./usr/man/man3/bufferevent_ssl.3 minix-sys
|
||||
./usr/man/man3/__builtin_object_size.3 minix-sys
|
||||
./usr/man/man3/byteorder.3 minix-sys
|
||||
./usr/man/man3/bzero.3 minix-sys
|
||||
|
@ -3318,6 +3356,29 @@
|
|||
./usr/man/man3/ether_ntohost.3 minix-sys
|
||||
./usr/man/man3/ethers.3 minix-sys
|
||||
./usr/man/man3/evasprintf.3 minix-sys
|
||||
./usr/man/man3/evbuffer.3 minix-sys
|
||||
./usr/man/man3/evbuffer_cb_info.3 minix-sys
|
||||
./usr/man/man3/evbuffer_compat.3 minix-sys
|
||||
./usr/man/man3/evbuffer_iovec.3 minix-sys
|
||||
./usr/man/man3/evbuffer_ptr.3 minix-sys
|
||||
./usr/man/man3/evdeprecated.3 minix-sys
|
||||
./usr/man/man3/evdns.3 minix-sys
|
||||
./usr/man/man3/evdns_compat.3 minix-sys
|
||||
./usr/man/man3/event.3 minix-sys
|
||||
./usr/man/man3/event_base.3 minix-sys
|
||||
./usr/man/man3/event_compat.3 minix-sys
|
||||
./usr/man/man3/event_config.3 minix-sys
|
||||
./usr/man/man3/evhttp.3 minix-sys
|
||||
./usr/man/man3/evhttp_compat.3 minix-sys
|
||||
./usr/man/man3/evrpc.3 minix-sys
|
||||
./usr/man/man3/evrpc_compat.3 minix-sys
|
||||
./usr/man/man3/evtag.3 minix-sys
|
||||
./usr/man/man3/evtag_compat.3 minix-sys
|
||||
./usr/man/man3/evthread.3 minix-sys
|
||||
./usr/man/man3/evthread_condition_callbacks.3 minix-sys
|
||||
./usr/man/man3/evthread_lock_callbacks.3 minix-sys
|
||||
./usr/man/man3/evutil.3 minix-sys
|
||||
./usr/man/man3/evutil_addrinfo.3 minix-sys
|
||||
./usr/man/man3/exec.3 minix-sys
|
||||
./usr/man/man3/execl.3 minix-sys
|
||||
./usr/man/man3/execle.3 minix-sys
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
./usr/include/compat/machine
|
||||
./usr/include/ddekit
|
||||
./usr/include/ddekit/minix
|
||||
./usr/include/event2
|
||||
./usr/include/fs
|
||||
./usr/include/g++
|
||||
./usr/include/i386
|
||||
|
|
2
external/bsd/Makefile
vendored
2
external/bsd/Makefile
vendored
|
@ -3,7 +3,7 @@
|
|||
.include <bsd.own.mk>
|
||||
|
||||
SUBDIR= byacc file flex less \
|
||||
libarchive mdocml \
|
||||
libarchive libevent mdocml \
|
||||
|
||||
|
||||
.if (${MKATF} != "no")
|
||||
|
|
5
external/bsd/libevent/Makefile
vendored
Normal file
5
external/bsd/libevent/Makefile
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
# $NetBSD: Makefile,v 1.2 2013/04/11 16:59:16 christos Exp $
|
||||
|
||||
SUBDIR = include lib man
|
||||
|
||||
.include <bsd.subdir.mk>
|
17
external/bsd/libevent/Makefile.inc
vendored
Normal file
17
external/bsd/libevent/Makefile.inc
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
# $NetBSD: Makefile.inc,v 1.2 2013/04/11 16:59:16 christos Exp $
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
LIBEVENT_DIR= ${NETBSDSRCDIR}/external/bsd/libevent
|
||||
LIBEVENT_DIST= ${LIBEVENT_DIR}/dist
|
||||
|
||||
CPPFLAGS+= -DHAVE_CONFIG_H
|
||||
CPPFLAGS+= -I${LIBEVENT_DIST} -I${LIBEVENT_DIR}/include
|
||||
CPPFLAGS+= -I${LIBEVENT_DIST}/include
|
||||
|
||||
SHLIB_MAJOR= 4
|
||||
SHLIB_MINOR= 0
|
||||
|
||||
WARNS?= 4
|
||||
|
||||
.PATH: ${LIBEVENT_DIST} ${LIBEVENT_DIST}/include
|
1332
external/bsd/libevent/dist/ChangeLog
vendored
Normal file
1332
external/bsd/libevent/dist/ChangeLog
vendored
Normal file
File diff suppressed because it is too large
Load diff
257
external/bsd/libevent/dist/Doxyfile
vendored
Normal file
257
external/bsd/libevent/dist/Doxyfile
vendored
Normal file
|
@ -0,0 +1,257 @@
|
|||
# Doxyfile 1.5.1
|
||||
|
||||
# This file describes the settings to be used by the documentation system
|
||||
# doxygen (www.doxygen.org) for a project
|
||||
#
|
||||
# All text after a hash (#) is considered a comment and will be ignored
|
||||
# The format is:
|
||||
# TAG = value [value, ...]
|
||||
# For lists items can also be appended using:
|
||||
# TAG += value [value, ...]
|
||||
# Values that contain spaces should be placed between quotes (" ")
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
|
||||
# by quotes) that should identify the project.
|
||||
|
||||
PROJECT_NAME = libevent
|
||||
|
||||
# Place all output under 'doxygen/'
|
||||
|
||||
OUTPUT_DIRECTORY = doxygen/
|
||||
|
||||
# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
|
||||
# will interpret the first line (until the first dot) of a JavaDoc-style
|
||||
# comment as the brief description. If set to NO, the JavaDoc
|
||||
# comments will behave just like the Qt-style comments (thus requiring an
|
||||
# explicit @brief command for a brief description.
|
||||
|
||||
JAVADOC_AUTOBRIEF = YES
|
||||
|
||||
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
|
||||
# sources only. Doxygen will then generate output that is more tailored for C.
|
||||
# For instance, some of the names that are used will be different. The list
|
||||
# of all members will be omitted, etc.
|
||||
|
||||
OPTIMIZE_OUTPUT_FOR_C = YES
|
||||
|
||||
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
|
||||
# brief documentation of file, namespace and class members alphabetically
|
||||
# by member name. If set to NO (the default) the members will appear in
|
||||
# declaration order.
|
||||
|
||||
SORT_BRIEF_DOCS = YES
|
||||
|
||||
# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
|
||||
# can be used to strip a user-defined part of the path. Stripping is
|
||||
# only done if one of the specified strings matches the left-hand part of
|
||||
# the path. The tag can be used to show relative paths in the file list.
|
||||
# If left blank the directory from which doxygen is run is used as the
|
||||
# path to strip.
|
||||
|
||||
STRIP_FROM_PATH = include/
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# The INPUT tag can be used to specify the files and/or directories that contain
|
||||
# documented source files. You may enter file names like "myfile.cpp" or
|
||||
# directories like "/usr/src/myproject". Separate the files or directories
|
||||
# with spaces.
|
||||
|
||||
INPUT = \
|
||||
include/event2/buffer.h \
|
||||
include/event2/buffer_compat.h \
|
||||
include/event2/bufferevent.h \
|
||||
include/event2/bufferevent_compat.h \
|
||||
include/event2/bufferevent_ssl.h \
|
||||
include/event2/dns.h \
|
||||
include/event2/dns_compat.h \
|
||||
include/event2/event.h \
|
||||
include/event2/event_compat.h \
|
||||
include/event2/http.h \
|
||||
include/event2/http_compat.h \
|
||||
include/event2/listener.h \
|
||||
include/event2/rpc.h \
|
||||
include/event2/rpc_compat.h \
|
||||
include/event2/tag.h \
|
||||
include/event2/tag_compat.h \
|
||||
include/event2/thread.h \
|
||||
include/event2/util.h
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
|
||||
# generate HTML output.
|
||||
|
||||
GENERATE_HTML = YES
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the LaTeX output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
|
||||
# generate Latex output.
|
||||
|
||||
GENERATE_LATEX = YES
|
||||
|
||||
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
|
||||
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
|
||||
# put in front of it. If left blank `latex' will be used as the default path.
|
||||
|
||||
LATEX_OUTPUT = latex
|
||||
|
||||
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
|
||||
# invoked. If left blank `latex' will be used as the default command name.
|
||||
|
||||
LATEX_CMD_NAME = latex
|
||||
|
||||
# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
|
||||
# generate index for LaTeX. If left blank `makeindex' will be used as the
|
||||
# default command name.
|
||||
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
|
||||
# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
|
||||
# LaTeX documents. This may be useful for small projects and may help to
|
||||
# save some trees in general.
|
||||
|
||||
COMPACT_LATEX = NO
|
||||
|
||||
# The PAPER_TYPE tag can be used to set the paper type that is used
|
||||
# by the printer. Possible values are: a4, a4wide, letter, legal and
|
||||
# executive. If left blank a4wide will be used.
|
||||
|
||||
PAPER_TYPE = a4wide
|
||||
|
||||
# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
|
||||
# packages that should be included in the LaTeX output.
|
||||
|
||||
EXTRA_PACKAGES =
|
||||
|
||||
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
|
||||
# the generated latex document. The header should contain everything until
|
||||
# the first chapter. If it is left blank doxygen will generate a
|
||||
# standard header. Notice: only use this tag if you know what you are doing!
|
||||
|
||||
LATEX_HEADER =
|
||||
|
||||
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
|
||||
# is prepared for conversion to pdf (using ps2pdf). The pdf file will
|
||||
# contain links (just like the HTML output) instead of page references
|
||||
# This makes the output suitable for online browsing using a pdf viewer.
|
||||
|
||||
PDF_HYPERLINKS = NO
|
||||
|
||||
# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
|
||||
# plain latex in the generated Makefile. Set this option to YES to get a
|
||||
# higher quality PDF documentation.
|
||||
|
||||
USE_PDFLATEX = YES
|
||||
|
||||
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
|
||||
# command to the generated LaTeX files. This will instruct LaTeX to keep
|
||||
# running if errors occur, instead of asking the user for help.
|
||||
# This option is also used when generating formulas in HTML.
|
||||
|
||||
LATEX_BATCHMODE = NO
|
||||
|
||||
# If LATEX_HIDE_INDICES is set to YES then doxygen will not
|
||||
# include the index chapters (such as File Index, Compound Index, etc.)
|
||||
# in the output.
|
||||
|
||||
LATEX_HIDE_INDICES = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
|
||||
# generate man pages
|
||||
|
||||
GENERATE_MAN = YES
|
||||
|
||||
# The MAN_EXTENSION tag determines the extension that is added to
|
||||
# the generated man pages (default is the subroutine's section .3)
|
||||
|
||||
MAN_EXTENSION = .3
|
||||
|
||||
# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
|
||||
# then it will generate one additional man file for each entity
|
||||
# documented in the real man page(s). These additional files
|
||||
# only source the real man page, but without them the man command
|
||||
# would be unable to find the correct page. The default is NO.
|
||||
|
||||
MAN_LINKS = YES
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
|
||||
# evaluate all C-preprocessor directives found in the sources and include
|
||||
# files.
|
||||
|
||||
ENABLE_PREPROCESSING = YES
|
||||
|
||||
# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
|
||||
# names in the source code. If set to NO (the default) only conditional
|
||||
# compilation will be performed. Macro expansion can be done in a controlled
|
||||
# way by setting EXPAND_ONLY_PREDEF to YES.
|
||||
|
||||
MACRO_EXPANSION = NO
|
||||
|
||||
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
|
||||
# then the macro expansion is limited to the macros specified with the
|
||||
# PREDEFINED and EXPAND_AS_DEFINED tags.
|
||||
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
|
||||
# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
|
||||
# in the INCLUDE_PATH (see below) will be search if a #include is found.
|
||||
|
||||
SEARCH_INCLUDES = YES
|
||||
|
||||
# The INCLUDE_PATH tag can be used to specify one or more directories that
|
||||
# contain include files that are not input files but should be processed by
|
||||
# the preprocessor.
|
||||
|
||||
INCLUDE_PATH =
|
||||
|
||||
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
|
||||
# patterns (like *.h and *.hpp) to filter out the header-files in the
|
||||
# directories. If left blank, the patterns specified with FILE_PATTERNS will
|
||||
# be used.
|
||||
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
|
||||
# The PREDEFINED tag can be used to specify one or more macro names that
|
||||
# are defined before the preprocessor is started (similar to the -D option of
|
||||
# gcc). The argument of the tag is a list of macros of the form: name
|
||||
# or name=definition (no spaces). If the definition and the = are
|
||||
# omitted =1 is assumed. To prevent a macro definition from being
|
||||
# undefined via #undef or recursively expanded use the := operator
|
||||
# instead of the = operator.
|
||||
|
||||
PREDEFINED = TAILQ_ENTRY RB_ENTRY _EVENT_DEFINED_TQENTRY _EVENT_IN_DOXYGEN
|
||||
|
||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
|
||||
# this tag can be used to specify a list of macro names that should be expanded.
|
||||
# The macro definition that is found in the sources will be used.
|
||||
# Use the PREDEFINED tag if you want to use a different macro definition.
|
||||
|
||||
EXPAND_AS_DEFINED =
|
||||
|
||||
# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
|
||||
# doxygen's preprocessor will remove all function-like macros that are alone
|
||||
# on a line, have an all uppercase name, and do not end with a semicolon. Such
|
||||
# function macros are typically used for boiler-plate code, and will confuse
|
||||
# the parser if not removed.
|
||||
|
||||
SKIP_FUNCTION_MACROS = YES
|
74
external/bsd/libevent/dist/LICENSE
vendored
Normal file
74
external/bsd/libevent/dist/LICENSE
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
Libevent is available for use under the following license, commonly known
|
||||
as the 3-clause (or "modified") BSD license:
|
||||
|
||||
==============================
|
||||
Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
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.
|
||||
==============================
|
||||
|
||||
Portions of Libevent are based on works by others, also made available by
|
||||
them under the three-clause BSD license above. The copyright notices are
|
||||
available in the corresponding source files; the license is as above. Here's
|
||||
a list:
|
||||
|
||||
log.c:
|
||||
Copyright (c) 2000 Dug Song <dugsong@monkey.org>
|
||||
Copyright (c) 1993 The Regents of the University of California.
|
||||
|
||||
strlcpy.c:
|
||||
Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
|
||||
win32select.c:
|
||||
Copyright (c) 2003 Michael A. Davis <mike@datanerds.net>
|
||||
|
||||
evport.c:
|
||||
Copyright (c) 2007 Sun Microsystems
|
||||
|
||||
ht-internal.h:
|
||||
Copyright (c) 2002 Christopher Clark
|
||||
|
||||
minheap-internal.h:
|
||||
Copyright (c) 2006 Maxim Yegorushkin <maxim.yegorushkin@gmail.com>
|
||||
|
||||
==============================
|
||||
|
||||
The arc4module is available under the following, sometimes called the
|
||||
"OpenBSD" license:
|
||||
|
||||
Copyright (c) 1996, David Mazieres <dm@uun.org>
|
||||
Copyright (c) 2008, Damien Miller <djm@openbsd.org>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
243
external/bsd/libevent/dist/Makefile.am
vendored
Normal file
243
external/bsd/libevent/dist/Makefile.am
vendored
Normal file
|
@ -0,0 +1,243 @@
|
|||
# Makefile.am for libevent
|
||||
# Copyright 2000-2007 Niels Provos
|
||||
# Copyright 2007-2012 Niels Provos and Nick Mathewson
|
||||
#
|
||||
# See LICENSE for copying information.
|
||||
|
||||
# 'foreign' means that we're not enforcing GNU package rules strictly.
|
||||
# '1.7' means that we need automake 1.7 or later (and we do).
|
||||
AUTOMAKE_OPTIONS = foreign 1.7
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
# This is the "Release" of the Libevent ABI. It takes precedence over
|
||||
# the VERSION_INFO, so that two versions of Libevent with the same
|
||||
# "Release" are never binary-compatible.
|
||||
#
|
||||
# This number incremented once for the 2.0 release candidate, and
|
||||
# will increment for each series until we revise our interfaces enough
|
||||
# that we can seriously expect ABI compatibility between series.
|
||||
#
|
||||
RELEASE = -release 2.0
|
||||
|
||||
# This is the version info for the libevent binary API. It has three
|
||||
# numbers:
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
# API are we supplying?
|
||||
# Age -- How many previous binary API versions do we also
|
||||
# support?
|
||||
#
|
||||
# To increment a VERSION_INFO (current:revision:age):
|
||||
# If the ABI didn't change:
|
||||
# Return (current:revision+1:age)
|
||||
# If the ABI changed, but it's backward-compatible:
|
||||
# Return (current+1:0:age+1)
|
||||
# If the ABI changed and it isn't backward-compatible:
|
||||
# Return (current+1:0:0)
|
||||
#
|
||||
# Once an RC is out, DO NOT MAKE ANY ABI-BREAKING CHANGES IN THAT SERIES
|
||||
# UNLESS YOU REALLY REALLY HAVE TO.
|
||||
VERSION_INFO = 6:9:1
|
||||
|
||||
# History: RELEASE VERSION_INFO
|
||||
# 2.0.1-alpha -- 2.0 1:0:0
|
||||
# 2.0.2-alpha -- 2:0:0
|
||||
# 2.0.3-alpha -- 2:0:0 (should have incremented; didn't.)
|
||||
# 2.0.4-alpha -- 3:0:0
|
||||
# 2.0.5-beta -- 4:0:0
|
||||
# 2.0.6-rc -- 2.0 2:0:0
|
||||
# 2.0.7-rc -- 2.0 3:0:1
|
||||
# 2.0.8-rc -- 2.0 4:0:2
|
||||
# 2.0.9-rc -- 2.0 5:0:0 (ABI changed slightly)
|
||||
# 2.0.10-stable-- 2.0 5:1:0 (No ABI change)
|
||||
# 2.0.11-stable-- 2.0 6:0:1 (ABI changed, backward-compatible)
|
||||
# 2.0.12-stable-- 2.0 6:1:1 (No ABI change)
|
||||
# 2.0.13-stable-- 2.0 6:2:1 (No ABI change)
|
||||
# 2.0.14-stable-- 2.0 6:3:1 (No ABI change)
|
||||
# 2.0.15-stable-- 2.0 6:3:1 (Forgot to update :( )
|
||||
# 2.0.16-stable-- 2.0 6:4:1 (No ABI change)
|
||||
# 2.0.17-stable-- 2.0 6:5:1 (No ABI change)
|
||||
# 2.0.18-stable-- 2.0 6:6:1 (No ABI change)
|
||||
# 2.0.19-stable-- 2.0 6:7:1 (No ABI change)
|
||||
# 2.0.20-stable-- 2.0 6:8:1 (No ABI change)
|
||||
# 2.0.21-stable-- 2.0 6:9:1 (No ABI change)
|
||||
#
|
||||
# For Libevent 2.1:
|
||||
# 2.1.1-alpha -- 2.1 1:0:0
|
||||
|
||||
|
||||
# ABI version history for this package effectively restarts every time
|
||||
# we change RELEASE. Version 1.4.x had RELEASE of 1.4.
|
||||
#
|
||||
# Ideally, we would not be using RELEASE at all; instead we could just
|
||||
# use the VERSION_INFO field to label our backward-incompatible ABI
|
||||
# changes, and those would be few and far between. Unfortunately,
|
||||
# Libevent still exposes far too many volatile structures in its
|
||||
# headers, so we pretty much have to assume that most development
|
||||
# series will break ABI compatibility. For now, it's simplest just to
|
||||
# keep incrementing the RELEASE between series and resetting VERSION_INFO.
|
||||
#
|
||||
# Eventually, when we get to the point where the structures in the
|
||||
# headers are all non-changing (or not there at all!), we can shift to
|
||||
# a more normal worldview where backward-incompatible ABI changes are
|
||||
# nice and rare. For the next couple of years, though, 'struct event'
|
||||
# is user-visible, and so we can pretty much guarantee that release
|
||||
# series won't be binary-compatible.
|
||||
|
||||
if INSTALL_LIBEVENT
|
||||
dist_bin_SCRIPTS = event_rpcgen.py
|
||||
endif
|
||||
|
||||
pkgconfigdir=$(libdir)/pkgconfig
|
||||
LIBEVENT_PKGCONFIG=libevent.pc
|
||||
|
||||
# These sources are conditionally added by configure.in or conditionally
|
||||
# included from other files.
|
||||
PLATFORM_DEPENDENT_SRC = \
|
||||
epoll_sub.c \
|
||||
arc4random.c
|
||||
|
||||
EXTRA_DIST = \
|
||||
LICENSE \
|
||||
autogen.sh \
|
||||
event_rpcgen.py \
|
||||
libevent.pc.in \
|
||||
make-event-config.sed \
|
||||
Doxyfile \
|
||||
whatsnew-2.0.txt \
|
||||
Makefile.nmake test/Makefile.nmake \
|
||||
$(PLATFORM_DEPENDENT_SRC)
|
||||
|
||||
LIBEVENT_LIBS_LA = libevent.la libevent_core.la libevent_extra.la
|
||||
if PTHREADS
|
||||
LIBEVENT_LIBS_LA += libevent_pthreads.la
|
||||
LIBEVENT_PKGCONFIG += libevent_pthreads.pc
|
||||
endif
|
||||
if OPENSSL
|
||||
LIBEVENT_LIBS_LA += libevent_openssl.la
|
||||
LIBEVENT_PKGCONFIG += libevent_openssl.pc
|
||||
endif
|
||||
|
||||
if INSTALL_LIBEVENT
|
||||
lib_LTLIBRARIES = $(LIBEVENT_LIBS_LA)
|
||||
pkgconfig_DATA = $(LIBEVENT_PKGCONFIG)
|
||||
else
|
||||
noinst_LTLIBRARIES = $(LIBEVENT_LIBS_LA)
|
||||
endif
|
||||
|
||||
SUBDIRS = . include sample test
|
||||
|
||||
if BUILD_WIN32
|
||||
|
||||
SYS_LIBS = -lws2_32 -lshell32 -ladvapi32
|
||||
SYS_SRC = win32select.c evthread_win32.c buffer_iocp.c event_iocp.c \
|
||||
bufferevent_async.c
|
||||
SYS_INCLUDES = -IWIN32-Code
|
||||
|
||||
else
|
||||
|
||||
SYS_LIBS =
|
||||
SYS_SRC =
|
||||
SYS_INCLUDES =
|
||||
|
||||
endif
|
||||
|
||||
if SELECT_BACKEND
|
||||
SYS_SRC += select.c
|
||||
endif
|
||||
if POLL_BACKEND
|
||||
SYS_SRC += poll.c
|
||||
endif
|
||||
if DEVPOLL_BACKEND
|
||||
SYS_SRC += devpoll.c
|
||||
endif
|
||||
if KQUEUE_BACKEND
|
||||
SYS_SRC += kqueue.c
|
||||
endif
|
||||
if EPOLL_BACKEND
|
||||
SYS_SRC += epoll.c
|
||||
endif
|
||||
if EVPORT_BACKEND
|
||||
SYS_SRC += evport.c
|
||||
endif
|
||||
if SIGNAL_SUPPORT
|
||||
SYS_SRC += signal.c
|
||||
endif
|
||||
|
||||
BUILT_SOURCES = include/event2/event-config.h
|
||||
|
||||
include/event2/event-config.h: config.h make-event-config.sed
|
||||
test -d include/event2 || $(MKDIR_P) include/event2
|
||||
$(SED) -f $(srcdir)/make-event-config.sed < config.h > $@T
|
||||
mv -f $@T $@
|
||||
|
||||
CORE_SRC = event.c evthread.c buffer.c \
|
||||
bufferevent.c bufferevent_sock.c bufferevent_filter.c \
|
||||
bufferevent_pair.c listener.c bufferevent_ratelim.c \
|
||||
evmap.c log.c evutil.c evutil_rand.c strlcpy.c $(SYS_SRC)
|
||||
EXTRA_SRC = event_tagging.c http.c evdns.c evrpc.c
|
||||
|
||||
if BUILD_WITH_NO_UNDEFINED
|
||||
NO_UNDEFINED = -no-undefined
|
||||
MAYBE_CORE = libevent_core.la
|
||||
else
|
||||
NO_UNDEFINED =
|
||||
MAYBE_CORE =
|
||||
endif
|
||||
|
||||
GENERIC_LDFLAGS = -version-info $(VERSION_INFO) $(RELEASE) $(NO_UNDEFINED)
|
||||
|
||||
libevent_la_SOURCES = $(CORE_SRC) $(EXTRA_SRC)
|
||||
libevent_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS)
|
||||
libevent_la_LDFLAGS = $(GENERIC_LDFLAGS)
|
||||
|
||||
libevent_core_la_SOURCES = $(CORE_SRC)
|
||||
libevent_core_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS)
|
||||
libevent_core_la_LDFLAGS = $(GENERIC_LDFLAGS)
|
||||
|
||||
if PTHREADS
|
||||
libevent_pthreads_la_SOURCES = evthread_pthread.c
|
||||
libevent_pthreads_la_LIBADD = $(MAYBE_CORE)
|
||||
libevent_pthreads_la_LDFLAGS = $(GENERIC_LDFLAGS)
|
||||
endif
|
||||
|
||||
libevent_extra_la_SOURCES = $(EXTRA_SRC)
|
||||
libevent_extra_la_LIBADD = $(MAYBE_CORE) $(SYS_LIBS)
|
||||
libevent_extra_la_LDFLAGS = $(GENERIC_LDFLAGS)
|
||||
|
||||
if OPENSSL
|
||||
libevent_openssl_la_SOURCES = bufferevent_openssl.c
|
||||
libevent_openssl_la_LIBADD = $(MAYBE_CORE) $(OPENSSL_LIBS)
|
||||
libevent_openssl_la_LDFLAGS = $(GENERIC_LDFLAGS)
|
||||
endif
|
||||
|
||||
noinst_HEADERS = util-internal.h mm-internal.h ipv6-internal.h \
|
||||
evrpc-internal.h strlcpy-internal.h evbuffer-internal.h \
|
||||
bufferevent-internal.h http-internal.h event-internal.h \
|
||||
evthread-internal.h ht-internal.h defer-internal.h \
|
||||
minheap-internal.h log-internal.h evsignal-internal.h evmap-internal.h \
|
||||
changelist-internal.h iocp-internal.h \
|
||||
ratelim-internal.h \
|
||||
WIN32-Code/event2/event-config.h \
|
||||
WIN32-Code/tree.h \
|
||||
compat/sys/queue.h
|
||||
|
||||
EVENT1_HDRS = event.h evhttp.h evdns.h evrpc.h evutil.h
|
||||
|
||||
if INSTALL_LIBEVENT
|
||||
include_HEADERS = $(EVENT1_HDRS)
|
||||
else
|
||||
noinst_HEADERS += $(EVENT1_HDRS)
|
||||
endif
|
||||
|
||||
AM_CPPFLAGS = -I$(srcdir)/compat -I$(srcdir)/include -I./include $(SYS_INCLUDES)
|
||||
|
||||
verify: check
|
||||
|
||||
doxygen: FORCE
|
||||
doxygen $(srcdir)/Doxyfile
|
||||
FORCE:
|
||||
|
||||
DISTCLEANFILES = *~ libevent.pc ./include/event2/event-config.h
|
||||
|
1328
external/bsd/libevent/dist/Makefile.in
vendored
Normal file
1328
external/bsd/libevent/dist/Makefile.in
vendored
Normal file
File diff suppressed because it is too large
Load diff
47
external/bsd/libevent/dist/Makefile.nmake
vendored
Normal file
47
external/bsd/libevent/dist/Makefile.nmake
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
# WATCH OUT! This makefile is a work in progress. It is probably missing
|
||||
# tons of important things. DO NOT RELY ON IT TO BUILD A GOOD LIBEVENT.
|
||||
|
||||
# Needed for correctness
|
||||
CFLAGS=/IWIN32-Code /Iinclude /Icompat /DWIN32 /DHAVE_CONFIG_H /I.
|
||||
|
||||
# For optimization and warnings
|
||||
CFLAGS=$(CFLAGS) /Ox /W3 /wd4996 /nologo
|
||||
|
||||
# XXXX have a debug mode
|
||||
|
||||
LIBFLAGS=/nologo
|
||||
|
||||
CORE_OBJS=event.obj buffer.obj bufferevent.obj bufferevent_sock.obj \
|
||||
bufferevent_pair.obj listener.obj evmap.obj log.obj evutil.obj \
|
||||
strlcpy.obj signal.obj bufferevent_filter.obj evthread.obj \
|
||||
bufferevent_ratelim.obj evutil_rand.obj
|
||||
WIN_OBJS=win32select.obj evthread_win32.obj buffer_iocp.obj \
|
||||
event_iocp.obj bufferevent_async.obj
|
||||
EXTRA_OBJS=event_tagging.obj http.obj evdns.obj evrpc.obj
|
||||
|
||||
ALL_OBJS=$(CORE_OBJS) $(WIN_OBJS) $(EXTRA_OBJS)
|
||||
STATIC_LIBS=libevent_core.lib libevent_extras.lib libevent.lib
|
||||
|
||||
|
||||
all: static_libs tests
|
||||
|
||||
static_libs: $(STATIC_LIBS)
|
||||
|
||||
libevent_core.lib: $(CORE_OBJS) $(WIN_OBJS)
|
||||
lib $(LIBFLAGS) $(CORE_OBJS) $(WIN_OBJS) /out:libevent_core.lib
|
||||
|
||||
libevent_extras.lib: $(EXTRA_OBJS)
|
||||
lib $(LIBFLAGS) $(EXTRA_OBJS) /out:libevent_extras.lib
|
||||
|
||||
libevent.lib: $(CORE_OBJS) $(WIN_OBJS) $(EXTRA_OBJS)
|
||||
lib $(LIBFLAGS) $(CORE_OBJS) $(EXTRA_OBJS) $(WIN_OBJS) /out:libevent.lib
|
||||
|
||||
clean:
|
||||
del $(ALL_OBJS)
|
||||
del $(STATIC_LIBS)
|
||||
cd test
|
||||
$(MAKE) /F Makefile.nmake clean
|
||||
|
||||
tests:
|
||||
cd test
|
||||
$(MAKE) /F Makefile.nmake
|
198
external/bsd/libevent/dist/README
vendored
Normal file
198
external/bsd/libevent/dist/README
vendored
Normal file
|
@ -0,0 +1,198 @@
|
|||
0. BUILDING AND INSTALLATION (Briefly)
|
||||
|
||||
$ ./configure
|
||||
$ make
|
||||
$ make verify # (optional)
|
||||
$ sudo make install
|
||||
|
||||
1. BUILDING AND INSTALLATION (In Depth)
|
||||
|
||||
To build libevent, type
|
||||
|
||||
$ ./configure && make
|
||||
|
||||
(If you got libevent from the git repository, you will
|
||||
first need to run the included "autogen.sh" script in order to
|
||||
generate the configure script.)
|
||||
|
||||
You can run the regression tests by running
|
||||
|
||||
$ make verify
|
||||
|
||||
Install as root via
|
||||
|
||||
# make install
|
||||
|
||||
Before, reporting any problems, please run the regression tests.
|
||||
|
||||
To enable the low-level tracing build the library as:
|
||||
|
||||
CFLAGS=-DUSE_DEBUG ./configure [...]
|
||||
|
||||
Standard configure flags should work. In particular, see:
|
||||
|
||||
--disable-shared Only build static libraries
|
||||
--prefix Install all files relative to this directory.
|
||||
|
||||
|
||||
The configure script also supports the following flags:
|
||||
|
||||
--enable-gcc-warnings Enable extra compiler checking with GCC.
|
||||
--disable-malloc-replacement
|
||||
Don't let applications replace our memory
|
||||
management functions
|
||||
--disable-openssl Disable support for OpenSSL encryption.
|
||||
--disable-thread-support Don't support multithreaded environments.
|
||||
|
||||
2. USEFUL LINKS:
|
||||
|
||||
For the latest released version of Libevent, see the official website at
|
||||
http://libevent.org/ .
|
||||
|
||||
There's a pretty good work-in-progress manual up at
|
||||
http://www.wangafu.net/~nickm/libevent-book/ .
|
||||
|
||||
For the latest development versions of Libevent, access our Git repository
|
||||
via
|
||||
"git clone git://levent.git.sourceforge.net/gitroot/levent/libevent"
|
||||
|
||||
You can browse the git repository online at
|
||||
http://levent.git.sourceforge.net/git/gitweb-index.cgi .
|
||||
|
||||
To report bugs, request features, or submit patches to Libevent,
|
||||
use the Sourceforge trackers at
|
||||
https://sourceforge.net/tracker/?group_id=50884 .
|
||||
|
||||
There's also a libevent-users mailing list for talking about Libevent
|
||||
use and development: http://archives.seul.org/libevent/users/
|
||||
|
||||
3. ACKNOWLEDGMENTS
|
||||
|
||||
The following people have helped with suggestions, ideas, code or
|
||||
fixing bugs:
|
||||
|
||||
Arno Bakker
|
||||
Alejo
|
||||
Weston Andros Adamson
|
||||
William Ahern
|
||||
Ivan Andropov
|
||||
Sergey Avseyev
|
||||
Avi Bab
|
||||
Gilad Benjamini
|
||||
Stas Bekman
|
||||
Joachim Bauch
|
||||
Denis Bilenko
|
||||
Julien Blache
|
||||
Kevin Bowling
|
||||
Tomash Brechko
|
||||
Kelly Brock
|
||||
Ralph Castain
|
||||
Adrian Chadd
|
||||
Lawnstein Chan
|
||||
Shuo Chen
|
||||
Ka-Hing Cheung
|
||||
Andrew Cox
|
||||
George Danchev
|
||||
Andrew Danforth
|
||||
Antony Dovgal
|
||||
Ed Day
|
||||
Christopher Davis
|
||||
Mike Davis
|
||||
Mihai Draghicioiu
|
||||
Mark Ellzey
|
||||
Shie Erlich
|
||||
Leonid Evdokimov
|
||||
Juan Pablo Fernandez
|
||||
Christophe Fillot
|
||||
Mike Frysinger
|
||||
Remi Gacogne
|
||||
Alexander von Gernler
|
||||
Artur Grabowski
|
||||
Sebastian Hahn
|
||||
Dave Hart
|
||||
Greg Hazel
|
||||
Michael Herf
|
||||
Savg He
|
||||
Mark Heily
|
||||
Greg Hewgill
|
||||
Andrew Hochhaus
|
||||
Aaron Hopkins
|
||||
Tani Hosokawa
|
||||
Jamie Iles
|
||||
Claudio Jeker
|
||||
Evan Jones
|
||||
George Kadianakis
|
||||
Phua Keat
|
||||
Kevin Ko
|
||||
Brian Koehmstedt
|
||||
Marko Kreen
|
||||
Valery Kyholodov
|
||||
Ross Lagerwall
|
||||
Scott Lamb
|
||||
Christopher Layne
|
||||
Adam Langley
|
||||
Philip Lewis
|
||||
Zhou Li
|
||||
David Libenzi
|
||||
Yan Lin
|
||||
Moshe Litvin
|
||||
Simon Liu
|
||||
Mitchell Livingston
|
||||
Hagne Mahre
|
||||
Lubomir Marinov
|
||||
Abilio Marques
|
||||
Nick Mathewson
|
||||
James Mansion
|
||||
Nicholas Marriott
|
||||
Andrey Matveev
|
||||
Caitlin Mercer
|
||||
Dagobert Michelsen
|
||||
Mansour Moufid
|
||||
Felix Nawothnig
|
||||
Trond Norbye
|
||||
Linus Nordberg
|
||||
Richard Nyberg
|
||||
Jon Oberheide
|
||||
Phil Oleson
|
||||
Dave Pacheco
|
||||
Tassilo von Parseval
|
||||
Catalin Patulea
|
||||
Patrick Pelletier
|
||||
Simon Perreault
|
||||
Pierre Phaneuf
|
||||
Ryan Phillips
|
||||
Dimitre Piskyulev
|
||||
Pavel Plesov
|
||||
Jon Poland
|
||||
Nate R
|
||||
Robert Ransom
|
||||
Bert JW Regeer
|
||||
Peter Rosin
|
||||
Maseeb Abdul Qadir
|
||||
Wang Qin
|
||||
Alex S
|
||||
Hanna Schroeter
|
||||
Ralf Schmitt
|
||||
Mike Smellie
|
||||
Kevin Springborn
|
||||
Harlan Stenn
|
||||
Steve Snyder
|
||||
Dug Song
|
||||
Dongsheng Song
|
||||
Hannes Sowa
|
||||
Ferenc Szalai
|
||||
Brodie Thiesfield
|
||||
Jason Toffaletti
|
||||
Gisle Vanem
|
||||
Bas Verhoeven
|
||||
Constantine Verutin
|
||||
Colin Watt
|
||||
Zack Weinberg
|
||||
Jardel Weyrich
|
||||
Alex
|
||||
Taral
|
||||
propanbutan
|
||||
mmadia
|
||||
|
||||
|
||||
If we have forgotten your name, please contact us.
|
364
external/bsd/libevent/dist/WIN32-Code/event2/event-config.h
vendored
Normal file
364
external/bsd/libevent/dist/WIN32-Code/event2/event-config.h
vendored
Normal file
|
@ -0,0 +1,364 @@
|
|||
/* $NetBSD: event-config.h,v 1.1.1.1 2013/04/11 16:43:34 christos Exp $ */
|
||||
/* 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 _EVENT_CONFIG_H_
|
||||
#define _EVENT_CONFIG_H_
|
||||
/* config.h. Generated by configure. */
|
||||
/* config.h.in. Generated from configure.in by autoheader. */
|
||||
|
||||
/* 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 if clock_gettime is available in libc */
|
||||
/* #undef _EVENT_DNS_USE_CPU_CLOCK_FOR_ID */
|
||||
|
||||
/* Define is no secure id variant is available */
|
||||
/* #define _EVENT_DNS_USE_GETTIMEOFDAY_FOR_ID 1 */
|
||||
#define _EVENT_DNS_USE_FTIME_FOR_ID 1
|
||||
|
||||
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||
/* #undef _EVENT_HAVE_ARPA_INET_H */
|
||||
|
||||
/* Define to 1 if you have the `clock_gettime' function. */
|
||||
/* #undef _EVENT_HAVE_CLOCK_GETTIME */
|
||||
|
||||
/* Define if /dev/poll is available */
|
||||
/* #undef _EVENT_HAVE_DEVPOLL */
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
/* #undef _EVENT_HAVE_DLFCN_H */
|
||||
|
||||
/* Define if your system supports the epoll system calls */
|
||||
/* #undef _EVENT_HAVE_EPOLL */
|
||||
|
||||
/* Define to 1 if you have the `epoll_ctl' function. */
|
||||
/* #undef _EVENT_HAVE_EPOLL_CTL */
|
||||
|
||||
/* Define to 1 if you have the `eventfd' function. */
|
||||
/* #undef _EVENT_HAVE_EVENTFD */
|
||||
|
||||
/* Define if your system supports event ports */
|
||||
/* #undef _EVENT_HAVE_EVENT_PORTS */
|
||||
|
||||
/* Define to 1 if you have the `fcntl' function. */
|
||||
/* #undef _EVENT_HAVE_FCNTL */
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#define _EVENT_HAVE_FCNTL_H 1
|
||||
|
||||
/* Define to 1 if you have the `getaddrinfo' function. */
|
||||
#define _EVENT_HAVE_GETADDRINFO 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 `inet_aton' function. */
|
||||
/* #undef _EVENT_HAVE_INET_ATON */
|
||||
|
||||
/* Define to 1 if you have the `inet_ntop' function. */
|
||||
/* #undef _EVENT_HAVE_INET_NTOP */
|
||||
|
||||
/* Define to 1 if you have the `inet_pton' function. */
|
||||
/* #undef _EVENT_HAVE_INET_PTON */
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
/* #define _EVENT_HAVE_INTTYPES_H 1 */
|
||||
|
||||
/* Define to 1 if you have the `kqueue' function. */
|
||||
/* #undef _EVENT_HAVE_KQUEUE */
|
||||
|
||||
/* Define if the system has zlib */
|
||||
/* #undef _EVENT_HAVE_LIBZ */
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define _EVENT_HAVE_MEMORY_H 1
|
||||
|
||||
/* Define to 1 if you have the `mmap' function. */
|
||||
/* #undef _EVENT_HAVE_MMAP */
|
||||
|
||||
/* Define to 1 if you have the <netinet/in6.h> header file. */
|
||||
/* #undef _EVENT_HAVE_NETINET_IN6_H */
|
||||
|
||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||
/* #undef _EVENT_HAVE_NETINET_IN_H */
|
||||
|
||||
/* Define to 1 if you have the `pipe' function. */
|
||||
/* #undef _EVENT_HAVE_PIPE */
|
||||
|
||||
/* Define to 1 if you have the `poll' function. */
|
||||
/* #undef _EVENT_HAVE_POLL */
|
||||
|
||||
/* Define to 1 if you have the <poll.h> header file. */
|
||||
/* #undef _EVENT_HAVE_POLL_H */
|
||||
|
||||
/* Define to 1 if you have the `port_create' function. */
|
||||
/* #undef _EVENT_HAVE_PORT_CREATE */
|
||||
|
||||
/* Define to 1 if you have the <port.h> 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 */
|
||||
/* #undef _EVENT_HAVE_PTHREADS */
|
||||
|
||||
/* Define to 1 if the system has the type `sa_family_t'. */
|
||||
/* #undef _EVENT_HAVE_SA_FAMILY_T */
|
||||
|
||||
/* Define to 1 if you have the `select' function. */
|
||||
/* #undef _EVENT_HAVE_SELECT */
|
||||
|
||||
/* Define to 1 if you have the `sendfile' function. */
|
||||
/* #undef _EVENT_HAVE_SENDFILE */
|
||||
|
||||
/* Define if F_SETFD is defined in <fcntl.h> */
|
||||
/* #undef _EVENT_HAVE_SETFD */
|
||||
|
||||
/* Define to 1 if you have the `sigaction' function. */
|
||||
/* #undef _EVENT_HAVE_SIGACTION */
|
||||
|
||||
/* Define to 1 if you have the `signal' function. */
|
||||
#define _EVENT_HAVE_SIGNAL 1
|
||||
|
||||
/* Define to 1 if you have the `splice' function. */
|
||||
/* #undef _EVENT_HAVE_SPLICE */
|
||||
|
||||
/* Define to 1 if you have the <stdarg.h> header file. */
|
||||
#define _EVENT_HAVE_STDARG_H 1
|
||||
|
||||
/* Define to 1 if you have the <stddef.h> header file. */
|
||||
#define _EVENT_HAVE_STDDEF_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
/* #define _EVENT_HAVE_STDINT_H 1 */
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define _EVENT_HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define _EVENT_HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> 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. */
|
||||
/* #undef _EVENT_HAVE_STRSEP */
|
||||
|
||||
/* Define to 1 if you have the `strtok_r' function. */
|
||||
/* #undef _EVENT_HAVE_STRTOK_R */
|
||||
|
||||
/* Define to 1 if you have the `strtoll' function. */
|
||||
/* #define _EVENT_HAVE_STRTOLL 1 */
|
||||
|
||||
#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 member of `struct in6_addr'. */
|
||||
#define _EVENT_HAVE_STRUCT_IN6_ADDR_S6_ADDR16 1
|
||||
|
||||
/* Define to 1 if `s6_addr32' is 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 member of `struct sockaddr_in6'. */
|
||||
/* #undef _EVENT_HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN */
|
||||
|
||||
/* Define to 1 if `sin_len' is 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 you have the <sys/devpoll.h> header file. */
|
||||
/* #undef _EVENT_HAVE_SYS_DEVPOLL_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/epoll.h> header file. */
|
||||
/* #undef _EVENT_HAVE_SYS_EPOLL_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/eventfd.h> header file. */
|
||||
/* #undef _EVENT_HAVE_SYS_EVENTFD_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/event.h> header file. */
|
||||
/* #undef _EVENT_HAVE_SYS_EVENT_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
||||
/* #undef _EVENT_HAVE_SYS_IOCTL_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/mman.h> header file. */
|
||||
/* #undef _EVENT_HAVE_SYS_MMAN_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||
/* #define _EVENT_HAVE_SYS_PARAM_H 1 */
|
||||
|
||||
/* Define to 1 if you have the <sys/queue.h> header file. */
|
||||
/* #undef _EVENT_HAVE_SYS_QUEUE_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/select.h> header file. */
|
||||
/* #undef _EVENT_HAVE_SYS_SELECT_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/sendfile.h> header file. */
|
||||
/* #undef _EVENT_HAVE_SYS_SENDFILE_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
/* #undef _EVENT_HAVE_SYS_SOCKET_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define _EVENT_HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
/* #define _EVENT_HAVE_SYS_TIME_H 1 */
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define _EVENT_HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/uio.h> header file. */
|
||||
/* #undef _EVENT_HAVE_SYS_UIO_H */
|
||||
|
||||
/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */
|
||||
/* #undef _EVENT_HAVE_TAILQFOREACH */
|
||||
|
||||
/* Define if timeradd is defined in <sys/time.h> */
|
||||
/* #undef _EVENT_HAVE_TIMERADD */
|
||||
|
||||
/* Define if timerclear is defined in <sys/time.h> */
|
||||
#define _EVENT_HAVE_TIMERCLEAR 1
|
||||
|
||||
/* Define if timercmp is defined in <sys/time.h> */
|
||||
#define _EVENT_HAVE_TIMERCMP 1
|
||||
|
||||
/* Define if timerisset is defined in <sys/time.h> */
|
||||
#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 you have the <unistd.h> header file. */
|
||||
/* #define _EVENT_HAVE_UNISTD_H 1 */
|
||||
|
||||
/* Define to 1 if you have the `vasprintf' function. */
|
||||
/* #undef _EVENT_HAVE_VASPRINTF */
|
||||
|
||||
/* Define if kqueue works correctly with pipes */
|
||||
/* #undef _EVENT_HAVE_WORKING_KQUEUE */
|
||||
|
||||
/* Numeric representation of the version */
|
||||
#define _EVENT_NUMERIC_VERSION 0x02001500
|
||||
|
||||
/* 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 ""
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define _EVENT_PACKAGE_STRING ""
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define _EVENT_PACKAGE_TARNAME ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define _EVENT_PACKAGE_VERSION ""
|
||||
|
||||
/* Define to necessary symbol if this constant uses a non-standard name on
|
||||
your system. */
|
||||
/* #undef _EVENT_PTHREAD_CREATE_JOINABLE */
|
||||
|
||||
/* The size of a `int', as computed by sizeof. */
|
||||
#define _EVENT_SIZEOF_INT 4
|
||||
|
||||
/* The size of a `long', as computed by sizeof. */
|
||||
#define _EVENT_SIZEOF_LONG 4
|
||||
|
||||
/* The size of a `long long', as computed by sizeof. */
|
||||
#define _EVENT_SIZEOF_LONG_LONG 8
|
||||
|
||||
/* The size of a `short', as computed by sizeof. */
|
||||
#define _EVENT_SIZEOF_SHORT 2
|
||||
|
||||
/* The size of `size_t', as computed by sizeof. */
|
||||
#ifdef _WIN64
|
||||
#define _EVENT_SIZEOF_SIZE_T 8
|
||||
#else
|
||||
#define _EVENT_SIZEOF_SIZE_T 4
|
||||
#endif
|
||||
|
||||
/* The size of `void *', as computed by sizeof. */
|
||||
#ifdef _WIN64
|
||||
#define _EVENT_SIZEOF_VOID_P 8
|
||||
#else
|
||||
#define _EVENT_SIZEOF_VOID_P 4
|
||||
#endif
|
||||
|
||||
/* 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 <sys/time.h> and <time.h>. */
|
||||
#define _EVENT_TIME_WITH_SYS_TIME 1
|
||||
|
||||
/* Version number of package */
|
||||
#define _EVENT_VERSION "2.0.21-stable"
|
||||
|
||||
/* Define to appropriate substitue if compiler doesnt have __func__ */
|
||||
#define _EVENT___func__ __FUNCTION__
|
||||
|
||||
/* 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
|
||||
#define _EVENT_inline __inline
|
||||
#endif
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
/* #undef _EVENT_pid_t */
|
||||
|
||||
/* Define to `unsigned' if <sys/types.h> does not define. */
|
||||
/* #undef _EVENT_size_t */
|
||||
|
||||
/* Define to unsigned int if you dont have it */
|
||||
#define _EVENT_socklen_t unsigned int
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
#define _EVENT_ssize_t SSIZE_T
|
||||
|
||||
#endif
|
1355
external/bsd/libevent/dist/WIN32-Code/tree.h
vendored
Normal file
1355
external/bsd/libevent/dist/WIN32-Code/tree.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
1024
external/bsd/libevent/dist/aclocal.m4
vendored
Normal file
1024
external/bsd/libevent/dist/aclocal.m4
vendored
Normal file
File diff suppressed because it is too large
Load diff
540
external/bsd/libevent/dist/arc4random.c
vendored
Normal file
540
external/bsd/libevent/dist/arc4random.c
vendored
Normal file
|
@ -0,0 +1,540 @@
|
|||
/* $NetBSD: arc4random.c,v 1.1.1.1 2013/04/11 16:43:21 christos Exp $ */
|
||||
/* Portable arc4random.c based on arc4random.c from OpenBSD.
|
||||
* Portable version by Chris Davis, adapted for Libevent by Nick Mathewson
|
||||
* Copyright (c) 2010 Chris Davis, Niels Provos, and Nick Mathewson
|
||||
* Copyright (c) 2010-2012 Niels Provos and Nick Mathewson
|
||||
*
|
||||
* Note that in Libevent, this file isn't compiled directly. Instead,
|
||||
* it's included from evutil_rand.c
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996, David Mazieres <dm@uun.org>
|
||||
* Copyright (c) 2008, Damien Miller <djm@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Arc4 random number generator for OpenBSD.
|
||||
*
|
||||
* This code is derived from section 17.1 of Applied Cryptography,
|
||||
* second edition, which describes a stream cipher allegedly
|
||||
* compatible with RSA Labs "RC4" cipher (the actual description of
|
||||
* which is a trade secret). The same algorithm is used as a stream
|
||||
* cipher called "arcfour" in Tatu Ylonen's ssh package.
|
||||
*
|
||||
* Here the stream cipher has been modified always to include the time
|
||||
* when initializing the state. That makes it impossible to
|
||||
* regenerate the same random sequence twice, so this can't be used
|
||||
* for encryption, but will generate good random numbers.
|
||||
*
|
||||
* RC4 is a registered trademark of RSA Laboratories.
|
||||
*/
|
||||
|
||||
#ifndef ARC4RANDOM_EXPORT
|
||||
#define ARC4RANDOM_EXPORT
|
||||
#endif
|
||||
|
||||
#ifndef ARC4RANDOM_UINT32
|
||||
#define ARC4RANDOM_UINT32 uint32_t
|
||||
#endif
|
||||
|
||||
#ifndef ARC4RANDOM_NO_INCLUDES
|
||||
#ifdef WIN32
|
||||
#include <wincrypt.h>
|
||||
#include <process.h>
|
||||
#else
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#ifdef _EVENT_HAVE_SYS_SYSCTL_H
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
#endif
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
/* Add platform entropy 32 bytes (256 bits) at a time. */
|
||||
#define ADD_ENTROPY 32
|
||||
|
||||
/* Re-seed from the platform RNG after generating this many bytes. */
|
||||
#define BYTES_BEFORE_RESEED 1600000
|
||||
|
||||
struct arc4_stream {
|
||||
unsigned char i;
|
||||
unsigned char j;
|
||||
unsigned char s[256];
|
||||
};
|
||||
|
||||
#ifdef WIN32
|
||||
#define getpid _getpid
|
||||
#define pid_t int
|
||||
#endif
|
||||
|
||||
static int rs_initialized;
|
||||
static struct arc4_stream rs;
|
||||
static pid_t arc4_stir_pid;
|
||||
static int arc4_count;
|
||||
static int arc4_seeded_ok;
|
||||
|
||||
static inline unsigned char arc4_getbyte(void);
|
||||
|
||||
static inline void
|
||||
arc4_init(void)
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < 256; n++)
|
||||
rs.s[n] = n;
|
||||
rs.i = 0;
|
||||
rs.j = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
arc4_addrandom(const unsigned char *dat, int datlen)
|
||||
{
|
||||
int n;
|
||||
unsigned char si;
|
||||
|
||||
rs.i--;
|
||||
for (n = 0; n < 256; n++) {
|
||||
rs.i = (rs.i + 1);
|
||||
si = rs.s[rs.i];
|
||||
rs.j = (rs.j + si + dat[n % datlen]);
|
||||
rs.s[rs.i] = rs.s[rs.j];
|
||||
rs.s[rs.j] = si;
|
||||
}
|
||||
rs.j = rs.i;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
static ssize_t
|
||||
read_all(int fd, unsigned char *buf, size_t count)
|
||||
{
|
||||
size_t numread = 0;
|
||||
ssize_t result;
|
||||
|
||||
while (numread < count) {
|
||||
result = read(fd, buf+numread, count-numread);
|
||||
if (result<0)
|
||||
return -1;
|
||||
else if (result == 0)
|
||||
break;
|
||||
numread += result;
|
||||
}
|
||||
|
||||
return (ssize_t)numread;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#define TRY_SEED_WIN32
|
||||
static int
|
||||
arc4_seed_win32(void)
|
||||
{
|
||||
/* This is adapted from Tor's crypto_seed_rng() */
|
||||
static int provider_set = 0;
|
||||
static HCRYPTPROV provider;
|
||||
unsigned char buf[ADD_ENTROPY];
|
||||
|
||||
if (!provider_set) {
|
||||
if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL,
|
||||
CRYPT_VERIFYCONTEXT)) {
|
||||
if (GetLastError() != (DWORD)NTE_BAD_KEYSET)
|
||||
return -1;
|
||||
}
|
||||
provider_set = 1;
|
||||
}
|
||||
if (!CryptGenRandom(provider, sizeof(buf), buf))
|
||||
return -1;
|
||||
arc4_addrandom(buf, sizeof(buf));
|
||||
memset(buf, 0, sizeof(buf));
|
||||
arc4_seeded_ok = 1;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_EVENT_HAVE_SYS_SYSCTL_H) && defined(_EVENT_HAVE_SYSCTL)
|
||||
#if _EVENT_HAVE_DECL_CTL_KERN && _EVENT_HAVE_DECL_KERN_RANDOM && _EVENT_HAVE_DECL_RANDOM_UUID
|
||||
#define TRY_SEED_SYSCTL_LINUX
|
||||
static int
|
||||
arc4_seed_sysctl_linux(void)
|
||||
{
|
||||
/* Based on code by William Ahern, this function tries to use the
|
||||
* RANDOM_UUID sysctl to get entropy from the kernel. This can work
|
||||
* even if /dev/urandom is inaccessible for some reason (e.g., we're
|
||||
* running in a chroot). */
|
||||
int mib[] = { CTL_KERN, KERN_RANDOM, RANDOM_UUID };
|
||||
unsigned char buf[ADD_ENTROPY];
|
||||
size_t len, n;
|
||||
unsigned i;
|
||||
int any_set;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
for (len = 0; len < sizeof(buf); len += n) {
|
||||
n = sizeof(buf) - len;
|
||||
|
||||
if (0 != sysctl(mib, 3, &buf[len], &n, NULL, 0))
|
||||
return -1;
|
||||
}
|
||||
/* make sure that the buffer actually got set. */
|
||||
for (i=0,any_set=0; i<sizeof(buf); ++i) {
|
||||
any_set |= buf[i];
|
||||
}
|
||||
if (!any_set)
|
||||
return -1;
|
||||
|
||||
arc4_addrandom(buf, sizeof(buf));
|
||||
memset(buf, 0, sizeof(buf));
|
||||
arc4_seeded_ok = 1;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if _EVENT_HAVE_DECL_CTL_KERN && _EVENT_HAVE_DECL_KERN_ARND
|
||||
#define TRY_SEED_SYSCTL_BSD
|
||||
static int
|
||||
arc4_seed_sysctl_bsd(void)
|
||||
{
|
||||
/* Based on code from William Ahern and from OpenBSD, this function
|
||||
* tries to use the KERN_ARND syscall to get entropy from the kernel.
|
||||
* This can work even if /dev/urandom is inaccessible for some reason
|
||||
* (e.g., we're running in a chroot). */
|
||||
int mib[] = { CTL_KERN, KERN_ARND };
|
||||
unsigned char buf[ADD_ENTROPY];
|
||||
size_t len, n;
|
||||
int i, any_set;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
len = sizeof(buf);
|
||||
if (sysctl(mib, 2, buf, &len, NULL, 0) == -1) {
|
||||
for (len = 0; len < sizeof(buf); len += sizeof(unsigned)) {
|
||||
n = sizeof(unsigned);
|
||||
if (n + len > sizeof(buf))
|
||||
n = len - sizeof(buf);
|
||||
if (sysctl(mib, 2, &buf[len], &n, NULL, 0) == -1)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/* make sure that the buffer actually got set. */
|
||||
for (i=any_set=0; i<sizeof(buf); ++i) {
|
||||
any_set |= buf[i];
|
||||
}
|
||||
if (!any_set)
|
||||
return -1;
|
||||
|
||||
arc4_addrandom(buf, sizeof(buf));
|
||||
memset(buf, 0, sizeof(buf));
|
||||
arc4_seeded_ok = 1;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif /* defined(_EVENT_HAVE_SYS_SYSCTL_H) */
|
||||
|
||||
#ifdef __linux__
|
||||
#define TRY_SEED_PROC_SYS_KERNEL_RANDOM_UUID
|
||||
static int
|
||||
arc4_seed_proc_sys_kernel_random_uuid(void)
|
||||
{
|
||||
/* Occasionally, somebody will make /proc/sys accessible in a chroot,
|
||||
* but not /dev/urandom. Let's try /proc/sys/kernel/random/uuid.
|
||||
* Its format is stupid, so we need to decode it from hex.
|
||||
*/
|
||||
int fd;
|
||||
char buf[128];
|
||||
unsigned char entropy[64];
|
||||
int bytes, n, i, nybbles;
|
||||
for (bytes = 0; bytes<ADD_ENTROPY; ) {
|
||||
fd = evutil_open_closeonexec("/proc/sys/kernel/random/uuid", O_RDONLY, 0);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
n = read(fd, buf, sizeof(buf));
|
||||
close(fd);
|
||||
if (n<=0)
|
||||
return -1;
|
||||
memset(entropy, 0, sizeof(entropy));
|
||||
for (i=nybbles=0; i<n; ++i) {
|
||||
if (EVUTIL_ISXDIGIT(buf[i])) {
|
||||
int nyb = evutil_hex_char_to_int(buf[i]);
|
||||
if (nybbles & 1) {
|
||||
entropy[nybbles/2] |= nyb;
|
||||
} else {
|
||||
entropy[nybbles/2] |= nyb<<4;
|
||||
}
|
||||
++nybbles;
|
||||
}
|
||||
}
|
||||
if (nybbles < 2)
|
||||
return -1;
|
||||
arc4_addrandom(entropy, nybbles/2);
|
||||
bytes += nybbles/2;
|
||||
}
|
||||
memset(entropy, 0, sizeof(entropy));
|
||||
memset(buf, 0, sizeof(buf));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef WIN32
|
||||
#define TRY_SEED_URANDOM
|
||||
static int
|
||||
arc4_seed_urandom(void)
|
||||
{
|
||||
/* This is adapted from Tor's crypto_seed_rng() */
|
||||
static const char *filenames[] = {
|
||||
"/dev/srandom", "/dev/urandom", "/dev/random", NULL
|
||||
};
|
||||
unsigned char buf[ADD_ENTROPY];
|
||||
int fd, i;
|
||||
size_t n;
|
||||
|
||||
for (i = 0; filenames[i]; ++i) {
|
||||
fd = evutil_open_closeonexec(filenames[i], O_RDONLY, 0);
|
||||
if (fd<0)
|
||||
continue;
|
||||
n = read_all(fd, buf, sizeof(buf));
|
||||
close(fd);
|
||||
if (n != sizeof(buf))
|
||||
return -1;
|
||||
arc4_addrandom(buf, sizeof(buf));
|
||||
memset(buf, 0, sizeof(buf));
|
||||
arc4_seeded_ok = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
arc4_seed(void)
|
||||
{
|
||||
int ok = 0;
|
||||
/* We try every method that might work, and don't give up even if one
|
||||
* does seem to work. There's no real harm in over-seeding, and if
|
||||
* one of these sources turns out to be broken, that would be bad. */
|
||||
#ifdef TRY_SEED_WIN32
|
||||
if (0 == arc4_seed_win32())
|
||||
ok = 1;
|
||||
#endif
|
||||
#ifdef TRY_SEED_URANDOM
|
||||
if (0 == arc4_seed_urandom())
|
||||
ok = 1;
|
||||
#endif
|
||||
#ifdef TRY_SEED_PROC_SYS_KERNEL_RANDOM_UUID
|
||||
if (0 == arc4_seed_proc_sys_kernel_random_uuid())
|
||||
ok = 1;
|
||||
#endif
|
||||
#ifdef TRY_SEED_SYSCTL_LINUX
|
||||
/* Apparently Linux is deprecating sysctl, and spewing warning
|
||||
* messages when you try to use it. */
|
||||
if (!ok && 0 == arc4_seed_sysctl_linux())
|
||||
ok = 1;
|
||||
#endif
|
||||
#ifdef TRY_SEED_SYSCTL_BSD
|
||||
if (0 == arc4_seed_sysctl_bsd())
|
||||
ok = 1;
|
||||
#endif
|
||||
return ok ? 0 : -1;
|
||||
}
|
||||
|
||||
static int
|
||||
arc4_stir(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!rs_initialized) {
|
||||
arc4_init();
|
||||
rs_initialized = 1;
|
||||
}
|
||||
|
||||
arc4_seed();
|
||||
if (!arc4_seeded_ok)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Discard early keystream, as per recommendations in
|
||||
* "Weaknesses in the Key Scheduling Algorithm of RC4" by
|
||||
* Scott Fluhrer, Itsik Mantin, and Adi Shamir.
|
||||
* http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
|
||||
*
|
||||
* Ilya Mironov's "(Not So) Random Shuffles of RC4" suggests that
|
||||
* we drop at least 2*256 bytes, with 12*256 as a conservative
|
||||
* value.
|
||||
*
|
||||
* RFC4345 says to drop 6*256.
|
||||
*
|
||||
* At least some versions of this code drop 4*256, in a mistaken
|
||||
* belief that "words" in the Fluhrer/Mantin/Shamir paper refers
|
||||
* to processor words.
|
||||
*
|
||||
* We add another sect to the cargo cult, and choose 12*256.
|
||||
*/
|
||||
for (i = 0; i < 12*256; i++)
|
||||
(void)arc4_getbyte();
|
||||
arc4_count = BYTES_BEFORE_RESEED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
arc4_stir_if_needed(void)
|
||||
{
|
||||
pid_t pid = getpid();
|
||||
|
||||
if (arc4_count <= 0 || !rs_initialized || arc4_stir_pid != pid)
|
||||
{
|
||||
arc4_stir_pid = pid;
|
||||
arc4_stir();
|
||||
}
|
||||
}
|
||||
|
||||
static inline unsigned char
|
||||
arc4_getbyte(void)
|
||||
{
|
||||
unsigned char si, sj;
|
||||
|
||||
rs.i = (rs.i + 1);
|
||||
si = rs.s[rs.i];
|
||||
rs.j = (rs.j + si);
|
||||
sj = rs.s[rs.j];
|
||||
rs.s[rs.i] = sj;
|
||||
rs.s[rs.j] = si;
|
||||
return (rs.s[(si + sj) & 0xff]);
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
arc4_getword(void)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
val = arc4_getbyte() << 24;
|
||||
val |= arc4_getbyte() << 16;
|
||||
val |= arc4_getbyte() << 8;
|
||||
val |= arc4_getbyte();
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
#ifndef ARC4RANDOM_NOSTIR
|
||||
ARC4RANDOM_EXPORT int
|
||||
arc4random_stir(void)
|
||||
{
|
||||
int val;
|
||||
_ARC4_LOCK();
|
||||
val = arc4_stir();
|
||||
_ARC4_UNLOCK();
|
||||
return val;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef ARC4RANDOM_NOADDRANDOM
|
||||
ARC4RANDOM_EXPORT void
|
||||
arc4random_addrandom(const unsigned char *dat, int datlen)
|
||||
{
|
||||
int j;
|
||||
_ARC4_LOCK();
|
||||
if (!rs_initialized)
|
||||
arc4_stir();
|
||||
for (j = 0; j < datlen; j += 256) {
|
||||
/* arc4_addrandom() ignores all but the first 256 bytes of
|
||||
* its input. We want to make sure to look at ALL the
|
||||
* data in 'dat', just in case the user is doing something
|
||||
* crazy like passing us all the files in /var/log. */
|
||||
arc4_addrandom(dat + j, datlen - j);
|
||||
}
|
||||
_ARC4_UNLOCK();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef ARC4RANDOM_NORANDOM
|
||||
ARC4RANDOM_EXPORT ARC4RANDOM_UINT32
|
||||
arc4random(void)
|
||||
{
|
||||
ARC4RANDOM_UINT32 val;
|
||||
_ARC4_LOCK();
|
||||
arc4_count -= 4;
|
||||
arc4_stir_if_needed();
|
||||
val = arc4_getword();
|
||||
_ARC4_UNLOCK();
|
||||
return val;
|
||||
}
|
||||
#endif
|
||||
|
||||
ARC4RANDOM_EXPORT void
|
||||
arc4random_buf(void *_buf, size_t n)
|
||||
{
|
||||
unsigned char *buf = _buf;
|
||||
_ARC4_LOCK();
|
||||
arc4_stir_if_needed();
|
||||
while (n--) {
|
||||
if (--arc4_count <= 0)
|
||||
arc4_stir();
|
||||
buf[n] = arc4_getbyte();
|
||||
}
|
||||
_ARC4_UNLOCK();
|
||||
}
|
||||
|
||||
#ifndef ARC4RANDOM_NOUNIFORM
|
||||
/*
|
||||
* Calculate a uniformly distributed random number less than upper_bound
|
||||
* avoiding "modulo bias".
|
||||
*
|
||||
* Uniformity is achieved by generating new random numbers until the one
|
||||
* returned is outside the range [0, 2**32 % upper_bound). This
|
||||
* guarantees the selected random number will be inside
|
||||
* [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)
|
||||
* after reduction modulo upper_bound.
|
||||
*/
|
||||
ARC4RANDOM_EXPORT unsigned int
|
||||
arc4random_uniform(unsigned int upper_bound)
|
||||
{
|
||||
ARC4RANDOM_UINT32 r, min;
|
||||
|
||||
if (upper_bound < 2)
|
||||
return 0;
|
||||
|
||||
#if (UINT_MAX > 0xffffffffUL)
|
||||
min = 0x100000000UL % upper_bound;
|
||||
#else
|
||||
/* Calculate (2**32 % upper_bound) avoiding 64-bit math */
|
||||
if (upper_bound > 0x80000000)
|
||||
min = 1 + ~upper_bound; /* 2**32 - upper_bound */
|
||||
else {
|
||||
/* (2**32 - (x * 2)) % x == 2**32 % x when x <= 2**31 */
|
||||
min = ((0xffffffff - (upper_bound * 2)) + 1) % upper_bound;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This could theoretically loop forever but each retry has
|
||||
* p > 0.5 (worst case, usually far better) of selecting a
|
||||
* number inside the range we need, so it should rarely need
|
||||
* to re-roll.
|
||||
*/
|
||||
for (;;) {
|
||||
r = arc4random();
|
||||
if (r >= min)
|
||||
break;
|
||||
}
|
||||
|
||||
return r % upper_bound;
|
||||
}
|
||||
#endif
|
15
external/bsd/libevent/dist/autogen.sh
vendored
Executable file
15
external/bsd/libevent/dist/autogen.sh
vendored
Executable file
|
@ -0,0 +1,15 @@
|
|||
#!/bin/sh
|
||||
if [ -x "`which autoreconf 2>/dev/null`" ] ; then
|
||||
exec autoreconf -ivf
|
||||
fi
|
||||
|
||||
LIBTOOLIZE=libtoolize
|
||||
SYSNAME=`uname`
|
||||
if [ "x$SYSNAME" = "xDarwin" ] ; then
|
||||
LIBTOOLIZE=glibtoolize
|
||||
fi
|
||||
aclocal -I m4 && \
|
||||
autoheader && \
|
||||
$LIBTOOLIZE && \
|
||||
autoconf && \
|
||||
automake --add-missing --force-missing --copy
|
3069
external/bsd/libevent/dist/buffer.c
vendored
Normal file
3069
external/bsd/libevent/dist/buffer.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
328
external/bsd/libevent/dist/buffer_iocp.c
vendored
Normal file
328
external/bsd/libevent/dist/buffer_iocp.c
vendored
Normal file
|
@ -0,0 +1,328 @@
|
|||
/* $NetBSD: buffer_iocp.c,v 1.1.1.1 2013/04/11 16:43:25 christos Exp $ */
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
@file buffer_iocp.c
|
||||
|
||||
This module implements overlapped read and write functions for evbuffer
|
||||
objects on Windows.
|
||||
*/
|
||||
|
||||
#include "event2/buffer.h"
|
||||
#include "event2/buffer_compat.h"
|
||||
#include "event2/util.h"
|
||||
#include "event2/thread.h"
|
||||
#include "event2/event-config.h"
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: buffer_iocp.c,v 1.1.1.1 2013/04/11 16:43:25 christos Exp $");
|
||||
#include "util-internal.h"
|
||||
#include "evthread-internal.h"
|
||||
#include "evbuffer-internal.h"
|
||||
#include "iocp-internal.h"
|
||||
#include "mm-internal.h"
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define MAX_WSABUFS 16
|
||||
|
||||
/** An evbuffer that can handle overlapped IO. */
|
||||
struct evbuffer_overlapped {
|
||||
struct evbuffer buffer;
|
||||
/** The socket that we're doing overlapped IO on. */
|
||||
evutil_socket_t fd;
|
||||
|
||||
/** pending I/O type */
|
||||
unsigned read_in_progress : 1;
|
||||
unsigned write_in_progress : 1;
|
||||
|
||||
/** The first pinned chain in the buffer. */
|
||||
struct evbuffer_chain *first_pinned;
|
||||
|
||||
/** How many chains are pinned; how many of the fields in buffers
|
||||
* are we using. */
|
||||
int n_buffers;
|
||||
WSABUF buffers[MAX_WSABUFS];
|
||||
};
|
||||
|
||||
/** Given an evbuffer, return the correponding evbuffer structure, or NULL if
|
||||
* the evbuffer isn't overlapped. */
|
||||
static inline struct evbuffer_overlapped *
|
||||
upcast_evbuffer(struct evbuffer *buf)
|
||||
{
|
||||
if (!buf || !buf->is_overlapped)
|
||||
return NULL;
|
||||
return EVUTIL_UPCAST(buf, struct evbuffer_overlapped, buffer);
|
||||
}
|
||||
|
||||
/** Unpin all the chains noted as pinned in 'eo'. */
|
||||
static void
|
||||
pin_release(struct evbuffer_overlapped *eo, unsigned flag)
|
||||
{
|
||||
int i;
|
||||
struct evbuffer_chain *next, *chain = eo->first_pinned;
|
||||
|
||||
for (i = 0; i < eo->n_buffers; ++i) {
|
||||
EVUTIL_ASSERT(chain);
|
||||
next = chain->next;
|
||||
_evbuffer_chain_unpin(chain, flag);
|
||||
chain = next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
evbuffer_commit_read(struct evbuffer *evbuf, ev_ssize_t nBytes)
|
||||
{
|
||||
struct evbuffer_overlapped *buf = upcast_evbuffer(evbuf);
|
||||
struct evbuffer_chain **chainp;
|
||||
size_t remaining, len;
|
||||
unsigned i;
|
||||
|
||||
EVBUFFER_LOCK(evbuf);
|
||||
EVUTIL_ASSERT(buf->read_in_progress && !buf->write_in_progress);
|
||||
EVUTIL_ASSERT(nBytes >= 0); /* XXXX Can this be false? */
|
||||
|
||||
evbuffer_unfreeze(evbuf, 0);
|
||||
|
||||
chainp = evbuf->last_with_datap;
|
||||
if (!((*chainp)->flags & EVBUFFER_MEM_PINNED_R))
|
||||
chainp = &(*chainp)->next;
|
||||
remaining = nBytes;
|
||||
for (i = 0; remaining > 0 && i < (unsigned)buf->n_buffers; ++i) {
|
||||
EVUTIL_ASSERT(*chainp);
|
||||
len = buf->buffers[i].len;
|
||||
if (remaining < len)
|
||||
len = remaining;
|
||||
(*chainp)->off += len;
|
||||
evbuf->last_with_datap = chainp;
|
||||
remaining -= len;
|
||||
chainp = &(*chainp)->next;
|
||||
}
|
||||
|
||||
pin_release(buf, EVBUFFER_MEM_PINNED_R);
|
||||
|
||||
buf->read_in_progress = 0;
|
||||
|
||||
evbuf->total_len += nBytes;
|
||||
evbuf->n_add_for_cb += nBytes;
|
||||
|
||||
evbuffer_invoke_callbacks(evbuf);
|
||||
|
||||
_evbuffer_decref_and_unlock(evbuf);
|
||||
}
|
||||
|
||||
void
|
||||
evbuffer_commit_write(struct evbuffer *evbuf, ev_ssize_t nBytes)
|
||||
{
|
||||
struct evbuffer_overlapped *buf = upcast_evbuffer(evbuf);
|
||||
|
||||
EVBUFFER_LOCK(evbuf);
|
||||
EVUTIL_ASSERT(buf->write_in_progress && !buf->read_in_progress);
|
||||
evbuffer_unfreeze(evbuf, 1);
|
||||
evbuffer_drain(evbuf, nBytes);
|
||||
pin_release(buf,EVBUFFER_MEM_PINNED_W);
|
||||
buf->write_in_progress = 0;
|
||||
_evbuffer_decref_and_unlock(evbuf);
|
||||
}
|
||||
|
||||
struct evbuffer *
|
||||
evbuffer_overlapped_new(evutil_socket_t fd)
|
||||
{
|
||||
struct evbuffer_overlapped *evo;
|
||||
|
||||
evo = mm_calloc(1, sizeof(struct evbuffer_overlapped));
|
||||
if (!evo)
|
||||
return NULL;
|
||||
|
||||
TAILQ_INIT(&evo->buffer.callbacks);
|
||||
evo->buffer.refcnt = 1;
|
||||
evo->buffer.last_with_datap = &evo->buffer.first;
|
||||
|
||||
evo->buffer.is_overlapped = 1;
|
||||
evo->fd = fd;
|
||||
|
||||
return &evo->buffer;
|
||||
}
|
||||
|
||||
int
|
||||
evbuffer_launch_write(struct evbuffer *buf, ev_ssize_t at_most,
|
||||
struct event_overlapped *ol)
|
||||
{
|
||||
struct evbuffer_overlapped *buf_o = upcast_evbuffer(buf);
|
||||
int r = -1;
|
||||
int i;
|
||||
struct evbuffer_chain *chain;
|
||||
DWORD bytesSent;
|
||||
|
||||
if (!buf) {
|
||||
/* No buffer, or it isn't overlapped */
|
||||
return -1;
|
||||
}
|
||||
|
||||
EVBUFFER_LOCK(buf);
|
||||
EVUTIL_ASSERT(!buf_o->read_in_progress);
|
||||
if (buf->freeze_start || buf_o->write_in_progress)
|
||||
goto done;
|
||||
if (!buf->total_len) {
|
||||
/* Nothing to write */
|
||||
r = 0;
|
||||
goto done;
|
||||
} else if (at_most < 0 || (size_t)at_most > buf->total_len) {
|
||||
at_most = buf->total_len;
|
||||
}
|
||||
evbuffer_freeze(buf, 1);
|
||||
|
||||
buf_o->first_pinned = NULL;
|
||||
buf_o->n_buffers = 0;
|
||||
memset(buf_o->buffers, 0, sizeof(buf_o->buffers));
|
||||
|
||||
chain = buf_o->first_pinned = buf->first;
|
||||
|
||||
for (i=0; i < MAX_WSABUFS && chain; ++i, chain=chain->next) {
|
||||
WSABUF *b = &buf_o->buffers[i];
|
||||
b->buf = (char*)( chain->buffer + chain->misalign );
|
||||
_evbuffer_chain_pin(chain, EVBUFFER_MEM_PINNED_W);
|
||||
|
||||
if ((size_t)at_most > chain->off) {
|
||||
/* XXXX Cast is safe for now, since win32 has no
|
||||
mmaped chains. But later, we need to have this
|
||||
add more WSAbufs if chain->off is greater than
|
||||
ULONG_MAX */
|
||||
b->len = (unsigned long)chain->off;
|
||||
at_most -= chain->off;
|
||||
} else {
|
||||
b->len = (unsigned long)at_most;
|
||||
++i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
buf_o->n_buffers = i;
|
||||
_evbuffer_incref(buf);
|
||||
if (WSASend(buf_o->fd, buf_o->buffers, i, &bytesSent, 0,
|
||||
&ol->overlapped, NULL)) {
|
||||
int error = WSAGetLastError();
|
||||
if (error != WSA_IO_PENDING) {
|
||||
/* An actual error. */
|
||||
pin_release(buf_o, EVBUFFER_MEM_PINNED_W);
|
||||
evbuffer_unfreeze(buf, 1);
|
||||
evbuffer_free(buf); /* decref */
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
buf_o->write_in_progress = 1;
|
||||
r = 0;
|
||||
done:
|
||||
EVBUFFER_UNLOCK(buf);
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
evbuffer_launch_read(struct evbuffer *buf, size_t at_most,
|
||||
struct event_overlapped *ol)
|
||||
{
|
||||
struct evbuffer_overlapped *buf_o = upcast_evbuffer(buf);
|
||||
int r = -1, i;
|
||||
int nvecs;
|
||||
int npin=0;
|
||||
struct evbuffer_chain *chain=NULL, **chainp;
|
||||
DWORD bytesRead;
|
||||
DWORD flags = 0;
|
||||
struct evbuffer_iovec vecs[MAX_WSABUFS];
|
||||
|
||||
if (!buf_o)
|
||||
return -1;
|
||||
EVBUFFER_LOCK(buf);
|
||||
EVUTIL_ASSERT(!buf_o->write_in_progress);
|
||||
if (buf->freeze_end || buf_o->read_in_progress)
|
||||
goto done;
|
||||
|
||||
buf_o->first_pinned = NULL;
|
||||
buf_o->n_buffers = 0;
|
||||
memset(buf_o->buffers, 0, sizeof(buf_o->buffers));
|
||||
|
||||
if (_evbuffer_expand_fast(buf, at_most, MAX_WSABUFS) == -1)
|
||||
goto done;
|
||||
evbuffer_freeze(buf, 0);
|
||||
|
||||
nvecs = _evbuffer_read_setup_vecs(buf, at_most,
|
||||
vecs, MAX_WSABUFS, &chainp, 1);
|
||||
for (i=0;i<nvecs;++i) {
|
||||
WSABUF_FROM_EVBUFFER_IOV(
|
||||
&buf_o->buffers[i],
|
||||
&vecs[i]);
|
||||
}
|
||||
|
||||
buf_o->n_buffers = nvecs;
|
||||
buf_o->first_pinned = chain = *chainp;
|
||||
|
||||
npin=0;
|
||||
for ( ; chain; chain = chain->next) {
|
||||
_evbuffer_chain_pin(chain, EVBUFFER_MEM_PINNED_R);
|
||||
++npin;
|
||||
}
|
||||
EVUTIL_ASSERT(npin == nvecs);
|
||||
|
||||
_evbuffer_incref(buf);
|
||||
if (WSARecv(buf_o->fd, buf_o->buffers, nvecs, &bytesRead, &flags,
|
||||
&ol->overlapped, NULL)) {
|
||||
int error = WSAGetLastError();
|
||||
if (error != WSA_IO_PENDING) {
|
||||
/* An actual error. */
|
||||
pin_release(buf_o, EVBUFFER_MEM_PINNED_R);
|
||||
evbuffer_unfreeze(buf, 0);
|
||||
evbuffer_free(buf); /* decref */
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
buf_o->read_in_progress = 1;
|
||||
r = 0;
|
||||
done:
|
||||
EVBUFFER_UNLOCK(buf);
|
||||
return r;
|
||||
}
|
||||
|
||||
evutil_socket_t
|
||||
_evbuffer_overlapped_get_fd(struct evbuffer *buf)
|
||||
{
|
||||
struct evbuffer_overlapped *buf_o = upcast_evbuffer(buf);
|
||||
return buf_o ? buf_o->fd : -1;
|
||||
}
|
||||
|
||||
void
|
||||
_evbuffer_overlapped_set_fd(struct evbuffer *buf, evutil_socket_t fd)
|
||||
{
|
||||
struct evbuffer_overlapped *buf_o = upcast_evbuffer(buf);
|
||||
EVBUFFER_LOCK(buf);
|
||||
/* XXX is this right?, should it cancel current I/O operations? */
|
||||
if (buf_o)
|
||||
buf_o->fd = fd;
|
||||
EVBUFFER_UNLOCK(buf);
|
||||
}
|
411
external/bsd/libevent/dist/bufferevent-internal.h
vendored
Normal file
411
external/bsd/libevent/dist/bufferevent-internal.h
vendored
Normal file
|
@ -0,0 +1,411 @@
|
|||
/* $NetBSD: bufferevent-internal.h,v 1.2 2013/04/11 16:56:41 christos Exp $ */
|
||||
/*
|
||||
* 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 _BUFFEREVENT_INTERNAL_H_
|
||||
#define _BUFFEREVENT_INTERNAL_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "event2/event-config.h"
|
||||
#include "event2/util.h"
|
||||
#include "defer-internal.h"
|
||||
#include "evthread-internal.h"
|
||||
#include "event2/thread.h"
|
||||
#include "ratelim-internal.h"
|
||||
#include "event2/bufferevent_struct.h"
|
||||
|
||||
/* These flags are reasons that we might be declining to actually enable
|
||||
reading or writing on a bufferevent.
|
||||
*/
|
||||
|
||||
/* On a all bufferevents, for reading: used when we have read up to the
|
||||
watermark value.
|
||||
|
||||
On a filtering bufferevent, for writing: used when the underlying
|
||||
bufferevent's write buffer has been filled up to its watermark
|
||||
value.
|
||||
*/
|
||||
#define BEV_SUSPEND_WM 0x01
|
||||
/* On a base bufferevent: when we have emptied a bandwidth buckets */
|
||||
#define BEV_SUSPEND_BW 0x02
|
||||
/* On a base bufferevent: when we have emptied the group's bandwidth bucket. */
|
||||
#define BEV_SUSPEND_BW_GROUP 0x04
|
||||
/* On a socket bufferevent: can't do any operations while we're waiting for
|
||||
* name lookup to finish. */
|
||||
#define BEV_SUSPEND_LOOKUP 0x08
|
||||
/* On a base bufferevent, for reading: used when a filter has choked this
|
||||
* (underlying) bufferevent because it has stopped reading from it. */
|
||||
#define BEV_SUSPEND_FILT_READ 0x10
|
||||
|
||||
typedef ev_uint16_t bufferevent_suspend_flags;
|
||||
|
||||
struct bufferevent_rate_limit_group {
|
||||
/** List of all members in the group */
|
||||
TAILQ_HEAD(rlim_group_member_list, bufferevent_private) members;
|
||||
/** Current limits for the group. */
|
||||
struct ev_token_bucket rate_limit;
|
||||
struct ev_token_bucket_cfg rate_limit_cfg;
|
||||
|
||||
/** True iff we don't want to read from any member of the group.until
|
||||
* the token bucket refills. */
|
||||
unsigned read_suspended : 1;
|
||||
/** True iff we don't want to write from any member of the group.until
|
||||
* the token bucket refills. */
|
||||
unsigned write_suspended : 1;
|
||||
/** True iff we were unable to suspend one of the bufferevents in the
|
||||
* group for reading the last time we tried, and we should try
|
||||
* again. */
|
||||
unsigned pending_unsuspend_read : 1;
|
||||
/** True iff we were unable to suspend one of the bufferevents in the
|
||||
* group for writing the last time we tried, and we should try
|
||||
* again. */
|
||||
unsigned pending_unsuspend_write : 1;
|
||||
|
||||
/*@{*/
|
||||
/** Total number of bytes read or written in this group since last
|
||||
* reset. */
|
||||
ev_uint64_t total_read;
|
||||
ev_uint64_t total_written;
|
||||
/*@}*/
|
||||
|
||||
/** The number of bufferevents in the group. */
|
||||
int n_members;
|
||||
|
||||
/** The smallest number of bytes that any member of the group should
|
||||
* be limited to read or write at a time. */
|
||||
ev_ssize_t min_share;
|
||||
ev_ssize_t configured_min_share;
|
||||
|
||||
/** Timeout event that goes off once a tick, when the bucket is ready
|
||||
* to refill. */
|
||||
struct event master_refill_event;
|
||||
/** Lock to protect the members of this group. This lock should nest
|
||||
* within every bufferevent lock: if you are holding this lock, do
|
||||
* not assume you can lock another bufferevent. */
|
||||
void *lock;
|
||||
};
|
||||
|
||||
/** Fields for rate-limiting a single bufferevent. */
|
||||
struct bufferevent_rate_limit {
|
||||
/* Linked-list elements for storing this bufferevent_private in a
|
||||
* group.
|
||||
*
|
||||
* Note that this field is supposed to be protected by the group
|
||||
* lock */
|
||||
TAILQ_ENTRY(bufferevent_private) next_in_group;
|
||||
/** The rate-limiting group for this bufferevent, or NULL if it is
|
||||
* only rate-limited on its own. */
|
||||
struct bufferevent_rate_limit_group *group;
|
||||
|
||||
/* This bufferevent's current limits. */
|
||||
struct ev_token_bucket limit;
|
||||
/* Pointer to the rate-limit configuration for this bufferevent.
|
||||
* Can be shared. XXX reference-count this? */
|
||||
struct ev_token_bucket_cfg *cfg;
|
||||
|
||||
/* Timeout event used when one this bufferevent's buckets are
|
||||
* empty. */
|
||||
struct event refill_bucket_event;
|
||||
};
|
||||
|
||||
/** Parts of the bufferevent structure that are shared among all bufferevent
|
||||
* types, but not exposed in bufferevent_struct.h. */
|
||||
struct bufferevent_private {
|
||||
/** The underlying bufferevent structure. */
|
||||
struct bufferevent bev;
|
||||
|
||||
/** Evbuffer callback to enforce watermarks on input. */
|
||||
struct evbuffer_cb_entry *read_watermarks_cb;
|
||||
|
||||
/** If set, we should free the lock when we free the bufferevent. */
|
||||
unsigned own_lock : 1;
|
||||
|
||||
/** Flag: set if we have deferred callbacks and a read callback is
|
||||
* pending. */
|
||||
unsigned readcb_pending : 1;
|
||||
/** Flag: set if we have deferred callbacks and a write callback is
|
||||
* pending. */
|
||||
unsigned writecb_pending : 1;
|
||||
/** Flag: set if we are currently busy connecting. */
|
||||
unsigned connecting : 1;
|
||||
/** Flag: set if a connect failed prematurely; this is a hack for
|
||||
* getting around the bufferevent abstraction. */
|
||||
unsigned connection_refused : 1;
|
||||
/** Set to the events pending if we have deferred callbacks and
|
||||
* an events callback is pending. */
|
||||
short eventcb_pending;
|
||||
|
||||
/** If set, read is suspended until one or more conditions are over.
|
||||
* The actual value here is a bitfield of those conditions; see the
|
||||
* BEV_SUSPEND_* flags above. */
|
||||
bufferevent_suspend_flags read_suspended;
|
||||
|
||||
/** If set, writing is suspended until one or more conditions are over.
|
||||
* The actual value here is a bitfield of those conditions; see the
|
||||
* BEV_SUSPEND_* flags above. */
|
||||
bufferevent_suspend_flags write_suspended;
|
||||
|
||||
/** Set to the current socket errno if we have deferred callbacks and
|
||||
* an events callback is pending. */
|
||||
int errno_pending;
|
||||
|
||||
/** The DNS error code for bufferevent_socket_connect_hostname */
|
||||
int dns_error;
|
||||
|
||||
/** Used to implement deferred callbacks */
|
||||
struct deferred_cb deferred;
|
||||
|
||||
/** The options this bufferevent was constructed with */
|
||||
enum bufferevent_options options;
|
||||
|
||||
/** Current reference count for this bufferevent. */
|
||||
int refcnt;
|
||||
|
||||
/** Lock for this bufferevent. Shared by the inbuf and the outbuf.
|
||||
* If NULL, locking is disabled. */
|
||||
void *lock;
|
||||
|
||||
/** Rate-limiting information for this bufferevent */
|
||||
struct bufferevent_rate_limit *rate_limiting;
|
||||
};
|
||||
|
||||
/** Possible operations for a control callback. */
|
||||
enum bufferevent_ctrl_op {
|
||||
BEV_CTRL_SET_FD,
|
||||
BEV_CTRL_GET_FD,
|
||||
BEV_CTRL_GET_UNDERLYING,
|
||||
BEV_CTRL_CANCEL_ALL
|
||||
};
|
||||
|
||||
/** Possible data types for a control callback */
|
||||
union bufferevent_ctrl_data {
|
||||
void *ptr;
|
||||
evutil_socket_t fd;
|
||||
};
|
||||
|
||||
/**
|
||||
Implementation table for a bufferevent: holds function pointers and other
|
||||
information to make the various bufferevent types work.
|
||||
*/
|
||||
struct bufferevent_ops {
|
||||
/** The name of the bufferevent's type. */
|
||||
const char *type;
|
||||
/** At what offset into the implementation type will we find a
|
||||
bufferevent structure?
|
||||
|
||||
Example: if the type is implemented as
|
||||
struct bufferevent_x {
|
||||
int extra_data;
|
||||
struct bufferevent bev;
|
||||
}
|
||||
then mem_offset should be offsetof(struct bufferevent_x, bev)
|
||||
*/
|
||||
off_t mem_offset;
|
||||
|
||||
/** Enables one or more of EV_READ|EV_WRITE on a bufferevent. Does
|
||||
not need to adjust the 'enabled' field. Returns 0 on success, -1
|
||||
on failure.
|
||||
*/
|
||||
int (*enable)(struct bufferevent *, short);
|
||||
|
||||
/** Disables one or more of EV_READ|EV_WRITE on a bufferevent. Does
|
||||
not need to adjust the 'enabled' field. Returns 0 on success, -1
|
||||
on failure.
|
||||
*/
|
||||
int (*disable)(struct bufferevent *, short);
|
||||
|
||||
/** Free any storage and deallocate any extra data or structures used
|
||||
in this implementation.
|
||||
*/
|
||||
void (*destruct)(struct bufferevent *);
|
||||
|
||||
/** Called when the timeouts on the bufferevent have changed.*/
|
||||
int (*adj_timeouts)(struct bufferevent *);
|
||||
|
||||
/** Called to flush data. */
|
||||
int (*flush)(struct bufferevent *, short, enum bufferevent_flush_mode);
|
||||
|
||||
/** Called to access miscellaneous fields. */
|
||||
int (*ctrl)(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *);
|
||||
|
||||
};
|
||||
|
||||
extern const struct bufferevent_ops bufferevent_ops_socket;
|
||||
extern const struct bufferevent_ops bufferevent_ops_filter;
|
||||
extern const struct bufferevent_ops bufferevent_ops_pair;
|
||||
|
||||
#define BEV_IS_SOCKET(bevp) ((bevp)->be_ops == &bufferevent_ops_socket)
|
||||
#define BEV_IS_FILTER(bevp) ((bevp)->be_ops == &bufferevent_ops_filter)
|
||||
#define BEV_IS_PAIR(bevp) ((bevp)->be_ops == &bufferevent_ops_pair)
|
||||
|
||||
#ifdef WIN32
|
||||
extern const struct bufferevent_ops bufferevent_ops_async;
|
||||
#define BEV_IS_ASYNC(bevp) ((bevp)->be_ops == &bufferevent_ops_async)
|
||||
#else
|
||||
#define BEV_IS_ASYNC(bevp) 0
|
||||
#endif
|
||||
|
||||
/** Initialize the shared parts of a bufferevent. */
|
||||
int bufferevent_init_common(struct bufferevent_private *, struct event_base *, const struct bufferevent_ops *, enum bufferevent_options options);
|
||||
|
||||
/** For internal use: temporarily stop all reads on bufev, until the conditions
|
||||
* in 'what' are over. */
|
||||
void bufferevent_suspend_read(struct bufferevent *bufev, bufferevent_suspend_flags what);
|
||||
/** For internal use: clear the conditions 'what' on bufev, and re-enable
|
||||
* reading if there are no conditions left. */
|
||||
void bufferevent_unsuspend_read(struct bufferevent *bufev, bufferevent_suspend_flags what);
|
||||
|
||||
/** For internal use: temporarily stop all writes on bufev, until the conditions
|
||||
* in 'what' are over. */
|
||||
void bufferevent_suspend_write(struct bufferevent *bufev, bufferevent_suspend_flags what);
|
||||
/** For internal use: clear the conditions 'what' on bufev, and re-enable
|
||||
* writing if there are no conditions left. */
|
||||
void bufferevent_unsuspend_write(struct bufferevent *bufev, bufferevent_suspend_flags what);
|
||||
|
||||
#define bufferevent_wm_suspend_read(b) \
|
||||
bufferevent_suspend_read((b), BEV_SUSPEND_WM)
|
||||
#define bufferevent_wm_unsuspend_read(b) \
|
||||
bufferevent_unsuspend_read((b), BEV_SUSPEND_WM)
|
||||
|
||||
/*
|
||||
Disable a bufferevent. Equivalent to bufferevent_disable(), but
|
||||
first resets 'connecting' flag to force EV_WRITE down for sure.
|
||||
|
||||
XXXX this method will go away in the future; try not to add new users.
|
||||
See comment in evhttp_connection_reset() for discussion.
|
||||
|
||||
@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_disable()
|
||||
*/
|
||||
int bufferevent_disable_hard(struct bufferevent *bufev, short event);
|
||||
|
||||
/** Internal: Set up locking on a bufferevent. If lock is set, use it.
|
||||
* Otherwise, use a new lock. */
|
||||
int bufferevent_enable_locking(struct bufferevent *bufev, void *lock);
|
||||
/** Internal: Increment the reference count on bufev. */
|
||||
void bufferevent_incref(struct bufferevent *bufev);
|
||||
/** Internal: Lock bufev and increase its reference count.
|
||||
* unlocking it otherwise. */
|
||||
void _bufferevent_incref_and_lock(struct bufferevent *bufev);
|
||||
/** Internal: Decrement the reference count on bufev. Returns 1 if it freed
|
||||
* the bufferevent.*/
|
||||
int bufferevent_decref(struct bufferevent *bufev);
|
||||
/** Internal: Drop the reference count on bufev, freeing as necessary, and
|
||||
* unlocking it otherwise. Returns 1 if it freed the bufferevent. */
|
||||
int _bufferevent_decref_and_unlock(struct bufferevent *bufev);
|
||||
|
||||
/** Internal: If callbacks are deferred and we have a read callback, schedule
|
||||
* a readcb. Otherwise just run the readcb. */
|
||||
void _bufferevent_run_readcb(struct bufferevent *bufev);
|
||||
/** Internal: If callbacks are deferred and we have a write callback, schedule
|
||||
* a writecb. Otherwise just run the writecb. */
|
||||
void _bufferevent_run_writecb(struct bufferevent *bufev);
|
||||
/** Internal: If callbacks are deferred and we have an eventcb, schedule
|
||||
* it to run with events "what". Otherwise just run the eventcb. */
|
||||
void _bufferevent_run_eventcb(struct bufferevent *bufev, short what);
|
||||
|
||||
/** Internal: Add the event 'ev' with timeout tv, unless tv is set to 0, in
|
||||
* which case add ev with no timeout. */
|
||||
int _bufferevent_add_event(struct event *ev, const struct timeval *tv);
|
||||
|
||||
/* =========
|
||||
* These next functions implement timeouts for bufferevents that aren't doing
|
||||
* anything else with ev_read and ev_write, to handle timeouts.
|
||||
* ========= */
|
||||
/** Internal use: Set up the ev_read and ev_write callbacks so that
|
||||
* the other "generic_timeout" functions will work on it. Call this from
|
||||
* the constructor function. */
|
||||
void _bufferevent_init_generic_timeout_cbs(struct bufferevent *bev);
|
||||
/** Internal use: Delete the ev_read and ev_write callbacks if they're pending.
|
||||
* Call this from the destructor function. */
|
||||
int _bufferevent_del_generic_timeout_cbs(struct bufferevent *bev);
|
||||
/** Internal use: Add or delete the generic timeout events as appropriate.
|
||||
* (If an event is enabled and a timeout is set, we add the event. Otherwise
|
||||
* we delete it.) Call this from anything that changes the timeout values,
|
||||
* that enabled EV_READ or EV_WRITE, or that disables EV_READ or EV_WRITE. */
|
||||
int _bufferevent_generic_adj_timeouts(struct bufferevent *bev);
|
||||
|
||||
/** Internal use: We have just successfully read data into an inbuf, so
|
||||
* reset the read timeout (if any). */
|
||||
#define BEV_RESET_GENERIC_READ_TIMEOUT(bev) \
|
||||
do { \
|
||||
if (evutil_timerisset(&(bev)->timeout_read)) \
|
||||
event_add(&(bev)->ev_read, &(bev)->timeout_read); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
/** Internal use: We have just successfully written data from an inbuf, so
|
||||
* reset the read timeout (if any). */
|
||||
#define BEV_RESET_GENERIC_WRITE_TIMEOUT(bev) \
|
||||
do { \
|
||||
if (evutil_timerisset(&(bev)->timeout_write)) \
|
||||
event_add(&(bev)->ev_write, &(bev)->timeout_write); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define BEV_DEL_GENERIC_READ_TIMEOUT(bev) \
|
||||
event_del(&(bev)->ev_read)
|
||||
#define BEV_DEL_GENERIC_WRITE_TIMEOUT(bev) \
|
||||
event_del(&(bev)->ev_write)
|
||||
|
||||
|
||||
/** Internal: Given a bufferevent, return its corresponding
|
||||
* bufferevent_private. */
|
||||
#define BEV_UPCAST(b) EVUTIL_UPCAST((b), struct bufferevent_private, bev)
|
||||
|
||||
#ifdef _EVENT_DISABLE_THREAD_SUPPORT
|
||||
#define BEV_LOCK(b) _EVUTIL_NIL_STMT
|
||||
#define BEV_UNLOCK(b) _EVUTIL_NIL_STMT
|
||||
#else
|
||||
/** Internal: Grab the lock (if any) on a bufferevent */
|
||||
#define BEV_LOCK(b) do { \
|
||||
struct bufferevent_private *locking = BEV_UPCAST(b); \
|
||||
EVLOCK_LOCK(locking->lock, 0); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/** Internal: Release the lock (if any) on a bufferevent */
|
||||
#define BEV_UNLOCK(b) do { \
|
||||
struct bufferevent_private *locking = BEV_UPCAST(b); \
|
||||
EVLOCK_UNLOCK(locking->lock, 0); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#endif
|
||||
|
||||
|
||||
/* ==== For rate-limiting. */
|
||||
|
||||
int _bufferevent_decrement_write_buckets(struct bufferevent_private *bev,
|
||||
ev_ssize_t bytes);
|
||||
int _bufferevent_decrement_read_buckets(struct bufferevent_private *bev,
|
||||
ev_ssize_t bytes);
|
||||
ev_ssize_t _bufferevent_get_read_max(struct bufferevent_private *bev);
|
||||
ev_ssize_t _bufferevent_get_write_max(struct bufferevent_private *bev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _BUFFEREVENT_INTERNAL_H_ */
|
878
external/bsd/libevent/dist/bufferevent.c
vendored
Normal file
878
external/bsd/libevent/dist/bufferevent.c
vendored
Normal file
|
@ -0,0 +1,878 @@
|
|||
/* $NetBSD: bufferevent.c,v 1.2 2013/04/11 16:56:41 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2002-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright (c) 2007-2012 Niels Provos, 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.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "event2/event-config.h"
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: bufferevent.c,v 1.2 2013/04/11 16:56:41 christos Exp $");
|
||||
|
||||
#ifdef _EVENT_HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef _EVENT_HAVE_STDARG_H
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
#include "event2/util.h"
|
||||
#include "event2/buffer.h"
|
||||
#include "event2/buffer_compat.h"
|
||||
#include "event2/bufferevent.h"
|
||||
#include "event2/bufferevent_struct.h"
|
||||
#include "event2/bufferevent_compat.h"
|
||||
#include "event2/event.h"
|
||||
#include "log-internal.h"
|
||||
#include "mm-internal.h"
|
||||
#include "bufferevent-internal.h"
|
||||
#include "evbuffer-internal.h"
|
||||
#include "util-internal.h"
|
||||
|
||||
static void _bufferevent_cancel_all(struct bufferevent *bev);
|
||||
|
||||
|
||||
void
|
||||
bufferevent_suspend_read(struct bufferevent *bufev, bufferevent_suspend_flags what)
|
||||
{
|
||||
struct bufferevent_private *bufev_private =
|
||||
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
|
||||
BEV_LOCK(bufev);
|
||||
if (!bufev_private->read_suspended)
|
||||
bufev->be_ops->disable(bufev, EV_READ);
|
||||
bufev_private->read_suspended |= what;
|
||||
BEV_UNLOCK(bufev);
|
||||
}
|
||||
|
||||
void
|
||||
bufferevent_unsuspend_read(struct bufferevent *bufev, bufferevent_suspend_flags what)
|
||||
{
|
||||
struct bufferevent_private *bufev_private =
|
||||
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
|
||||
BEV_LOCK(bufev);
|
||||
bufev_private->read_suspended &= ~what;
|
||||
if (!bufev_private->read_suspended && (bufev->enabled & EV_READ))
|
||||
bufev->be_ops->enable(bufev, EV_READ);
|
||||
BEV_UNLOCK(bufev);
|
||||
}
|
||||
|
||||
void
|
||||
bufferevent_suspend_write(struct bufferevent *bufev, bufferevent_suspend_flags what)
|
||||
{
|
||||
struct bufferevent_private *bufev_private =
|
||||
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
|
||||
BEV_LOCK(bufev);
|
||||
if (!bufev_private->write_suspended)
|
||||
bufev->be_ops->disable(bufev, EV_WRITE);
|
||||
bufev_private->write_suspended |= what;
|
||||
BEV_UNLOCK(bufev);
|
||||
}
|
||||
|
||||
void
|
||||
bufferevent_unsuspend_write(struct bufferevent *bufev, bufferevent_suspend_flags what)
|
||||
{
|
||||
struct bufferevent_private *bufev_private =
|
||||
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
|
||||
BEV_LOCK(bufev);
|
||||
bufev_private->write_suspended &= ~what;
|
||||
if (!bufev_private->write_suspended && (bufev->enabled & EV_WRITE))
|
||||
bufev->be_ops->enable(bufev, EV_WRITE);
|
||||
BEV_UNLOCK(bufev);
|
||||
}
|
||||
|
||||
|
||||
/* Callback to implement watermarks on the input buffer. Only enabled
|
||||
* if the watermark is set. */
|
||||
static void
|
||||
bufferevent_inbuf_wm_cb(struct evbuffer *buf,
|
||||
const struct evbuffer_cb_info *cbinfo,
|
||||
void *arg)
|
||||
{
|
||||
struct bufferevent *bufev = arg;
|
||||
size_t size;
|
||||
|
||||
size = evbuffer_get_length(buf);
|
||||
|
||||
if (size >= bufev->wm_read.high)
|
||||
bufferevent_wm_suspend_read(bufev);
|
||||
else
|
||||
bufferevent_wm_unsuspend_read(bufev);
|
||||
}
|
||||
|
||||
static void
|
||||
bufferevent_run_deferred_callbacks_locked(struct deferred_cb *_, void *arg)
|
||||
{
|
||||
struct bufferevent_private *bufev_private = arg;
|
||||
struct bufferevent *bufev = &bufev_private->bev;
|
||||
|
||||
BEV_LOCK(bufev);
|
||||
if ((bufev_private->eventcb_pending & BEV_EVENT_CONNECTED) &&
|
||||
bufev->errorcb) {
|
||||
/* The "connected" happened before any reads or writes, so
|
||||
send it first. */
|
||||
bufev_private->eventcb_pending &= ~BEV_EVENT_CONNECTED;
|
||||
bufev->errorcb(bufev, BEV_EVENT_CONNECTED, bufev->cbarg);
|
||||
}
|
||||
if (bufev_private->readcb_pending && bufev->readcb) {
|
||||
bufev_private->readcb_pending = 0;
|
||||
bufev->readcb(bufev, bufev->cbarg);
|
||||
}
|
||||
if (bufev_private->writecb_pending && bufev->writecb) {
|
||||
bufev_private->writecb_pending = 0;
|
||||
bufev->writecb(bufev, bufev->cbarg);
|
||||
}
|
||||
if (bufev_private->eventcb_pending && bufev->errorcb) {
|
||||
short what = bufev_private->eventcb_pending;
|
||||
int err = bufev_private->errno_pending;
|
||||
bufev_private->eventcb_pending = 0;
|
||||
bufev_private->errno_pending = 0;
|
||||
EVUTIL_SET_SOCKET_ERROR(err);
|
||||
bufev->errorcb(bufev, what, bufev->cbarg);
|
||||
}
|
||||
_bufferevent_decref_and_unlock(bufev);
|
||||
}
|
||||
|
||||
static void
|
||||
bufferevent_run_deferred_callbacks_unlocked(struct deferred_cb *_, void *arg)
|
||||
{
|
||||
struct bufferevent_private *bufev_private = arg;
|
||||
struct bufferevent *bufev = &bufev_private->bev;
|
||||
|
||||
BEV_LOCK(bufev);
|
||||
#define UNLOCKED(stmt) \
|
||||
do { BEV_UNLOCK(bufev); stmt; BEV_LOCK(bufev); } while(0)
|
||||
|
||||
if ((bufev_private->eventcb_pending & BEV_EVENT_CONNECTED) &&
|
||||
bufev->errorcb) {
|
||||
/* The "connected" happened before any reads or writes, so
|
||||
send it first. */
|
||||
bufferevent_event_cb errorcb = bufev->errorcb;
|
||||
void *cbarg = bufev->cbarg;
|
||||
bufev_private->eventcb_pending &= ~BEV_EVENT_CONNECTED;
|
||||
UNLOCKED(errorcb(bufev, BEV_EVENT_CONNECTED, cbarg));
|
||||
}
|
||||
if (bufev_private->readcb_pending && bufev->readcb) {
|
||||
bufferevent_data_cb readcb = bufev->readcb;
|
||||
void *cbarg = bufev->cbarg;
|
||||
bufev_private->readcb_pending = 0;
|
||||
UNLOCKED(readcb(bufev, cbarg));
|
||||
}
|
||||
if (bufev_private->writecb_pending && bufev->writecb) {
|
||||
bufferevent_data_cb writecb = bufev->writecb;
|
||||
void *cbarg = bufev->cbarg;
|
||||
bufev_private->writecb_pending = 0;
|
||||
UNLOCKED(writecb(bufev, cbarg));
|
||||
}
|
||||
if (bufev_private->eventcb_pending && bufev->errorcb) {
|
||||
bufferevent_event_cb errorcb = bufev->errorcb;
|
||||
void *cbarg = bufev->cbarg;
|
||||
short what = bufev_private->eventcb_pending;
|
||||
int err = bufev_private->errno_pending;
|
||||
bufev_private->eventcb_pending = 0;
|
||||
bufev_private->errno_pending = 0;
|
||||
EVUTIL_SET_SOCKET_ERROR(err);
|
||||
UNLOCKED(errorcb(bufev,what,cbarg));
|
||||
}
|
||||
_bufferevent_decref_and_unlock(bufev);
|
||||
#undef UNLOCKED
|
||||
}
|
||||
|
||||
#define SCHEDULE_DEFERRED(bevp) \
|
||||
do { \
|
||||
bufferevent_incref(&(bevp)->bev); \
|
||||
event_deferred_cb_schedule( \
|
||||
event_base_get_deferred_cb_queue((bevp)->bev.ev_base), \
|
||||
&(bevp)->deferred); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
|
||||
void
|
||||
_bufferevent_run_readcb(struct bufferevent *bufev)
|
||||
{
|
||||
/* Requires that we hold the lock and a reference */
|
||||
struct bufferevent_private *p =
|
||||
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
|
||||
if (bufev->readcb == NULL)
|
||||
return;
|
||||
if (p->options & BEV_OPT_DEFER_CALLBACKS) {
|
||||
p->readcb_pending = 1;
|
||||
if (!p->deferred.queued)
|
||||
SCHEDULE_DEFERRED(p);
|
||||
} else {
|
||||
bufev->readcb(bufev, bufev->cbarg);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_bufferevent_run_writecb(struct bufferevent *bufev)
|
||||
{
|
||||
/* Requires that we hold the lock and a reference */
|
||||
struct bufferevent_private *p =
|
||||
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
|
||||
if (bufev->writecb == NULL)
|
||||
return;
|
||||
if (p->options & BEV_OPT_DEFER_CALLBACKS) {
|
||||
p->writecb_pending = 1;
|
||||
if (!p->deferred.queued)
|
||||
SCHEDULE_DEFERRED(p);
|
||||
} else {
|
||||
bufev->writecb(bufev, bufev->cbarg);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_bufferevent_run_eventcb(struct bufferevent *bufev, short what)
|
||||
{
|
||||
/* Requires that we hold the lock and a reference */
|
||||
struct bufferevent_private *p =
|
||||
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
|
||||
if (bufev->errorcb == NULL)
|
||||
return;
|
||||
if (p->options & BEV_OPT_DEFER_CALLBACKS) {
|
||||
p->eventcb_pending |= what;
|
||||
p->errno_pending = EVUTIL_SOCKET_ERROR();
|
||||
if (!p->deferred.queued)
|
||||
SCHEDULE_DEFERRED(p);
|
||||
} else {
|
||||
bufev->errorcb(bufev, what, bufev->cbarg);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_init_common(struct bufferevent_private *bufev_private,
|
||||
struct event_base *base,
|
||||
const struct bufferevent_ops *ops,
|
||||
enum bufferevent_options options)
|
||||
{
|
||||
struct bufferevent *bufev = &bufev_private->bev;
|
||||
|
||||
if (!bufev->input) {
|
||||
if ((bufev->input = evbuffer_new()) == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!bufev->output) {
|
||||
if ((bufev->output = evbuffer_new()) == NULL) {
|
||||
evbuffer_free(bufev->input);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
bufev_private->refcnt = 1;
|
||||
bufev->ev_base = base;
|
||||
|
||||
/* Disable timeouts. */
|
||||
evutil_timerclear(&bufev->timeout_read);
|
||||
evutil_timerclear(&bufev->timeout_write);
|
||||
|
||||
bufev->be_ops = ops;
|
||||
|
||||
/*
|
||||
* Set to EV_WRITE so that using bufferevent_write is going to
|
||||
* trigger a callback. Reading needs to be explicitly enabled
|
||||
* because otherwise no data will be available.
|
||||
*/
|
||||
bufev->enabled = EV_WRITE;
|
||||
|
||||
#ifndef _EVENT_DISABLE_THREAD_SUPPORT
|
||||
if (options & BEV_OPT_THREADSAFE) {
|
||||
if (bufferevent_enable_locking(bufev, NULL) < 0) {
|
||||
/* cleanup */
|
||||
evbuffer_free(bufev->input);
|
||||
evbuffer_free(bufev->output);
|
||||
bufev->input = NULL;
|
||||
bufev->output = NULL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if ((options & (BEV_OPT_DEFER_CALLBACKS|BEV_OPT_UNLOCK_CALLBACKS))
|
||||
== BEV_OPT_UNLOCK_CALLBACKS) {
|
||||
event_warnx("UNLOCK_CALLBACKS requires DEFER_CALLBACKS");
|
||||
return -1;
|
||||
}
|
||||
if (options & BEV_OPT_DEFER_CALLBACKS) {
|
||||
if (options & BEV_OPT_UNLOCK_CALLBACKS)
|
||||
event_deferred_cb_init(&bufev_private->deferred,
|
||||
bufferevent_run_deferred_callbacks_unlocked,
|
||||
bufev_private);
|
||||
else
|
||||
event_deferred_cb_init(&bufev_private->deferred,
|
||||
bufferevent_run_deferred_callbacks_locked,
|
||||
bufev_private);
|
||||
}
|
||||
|
||||
bufev_private->options = options;
|
||||
|
||||
evbuffer_set_parent(bufev->input, bufev);
|
||||
evbuffer_set_parent(bufev->output, bufev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
bufferevent_setcb(struct bufferevent *bufev,
|
||||
bufferevent_data_cb readcb, bufferevent_data_cb writecb,
|
||||
bufferevent_event_cb eventcb, void *cbarg)
|
||||
{
|
||||
BEV_LOCK(bufev);
|
||||
|
||||
bufev->readcb = readcb;
|
||||
bufev->writecb = writecb;
|
||||
bufev->errorcb = eventcb;
|
||||
|
||||
bufev->cbarg = cbarg;
|
||||
BEV_UNLOCK(bufev);
|
||||
}
|
||||
|
||||
struct evbuffer *
|
||||
bufferevent_get_input(struct bufferevent *bufev)
|
||||
{
|
||||
return bufev->input;
|
||||
}
|
||||
|
||||
struct evbuffer *
|
||||
bufferevent_get_output(struct bufferevent *bufev)
|
||||
{
|
||||
return bufev->output;
|
||||
}
|
||||
|
||||
struct event_base *
|
||||
bufferevent_get_base(struct bufferevent *bufev)
|
||||
{
|
||||
return bufev->ev_base;
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_write(struct bufferevent *bufev, const void *data, size_t size)
|
||||
{
|
||||
if (evbuffer_add(bufev->output, data, size) == -1)
|
||||
return (-1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf)
|
||||
{
|
||||
if (evbuffer_add_buffer(bufev->output, buf) == -1)
|
||||
return (-1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
bufferevent_read(struct bufferevent *bufev, void *data, size_t size)
|
||||
{
|
||||
return (evbuffer_remove(bufev->input, data, size));
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_read_buffer(struct bufferevent *bufev, struct evbuffer *buf)
|
||||
{
|
||||
return (evbuffer_add_buffer(buf, bufev->input));
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_enable(struct bufferevent *bufev, short event)
|
||||
{
|
||||
struct bufferevent_private *bufev_private =
|
||||
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
|
||||
short impl_events = event;
|
||||
int r = 0;
|
||||
|
||||
_bufferevent_incref_and_lock(bufev);
|
||||
if (bufev_private->read_suspended)
|
||||
impl_events &= ~EV_READ;
|
||||
if (bufev_private->write_suspended)
|
||||
impl_events &= ~EV_WRITE;
|
||||
|
||||
bufev->enabled |= event;
|
||||
|
||||
if (impl_events && bufev->be_ops->enable(bufev, impl_events) < 0)
|
||||
r = -1;
|
||||
|
||||
_bufferevent_decref_and_unlock(bufev);
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_set_timeouts(struct bufferevent *bufev,
|
||||
const struct timeval *tv_read,
|
||||
const struct timeval *tv_write)
|
||||
{
|
||||
int r = 0;
|
||||
BEV_LOCK(bufev);
|
||||
if (tv_read) {
|
||||
bufev->timeout_read = *tv_read;
|
||||
} else {
|
||||
evutil_timerclear(&bufev->timeout_read);
|
||||
}
|
||||
if (tv_write) {
|
||||
bufev->timeout_write = *tv_write;
|
||||
} else {
|
||||
evutil_timerclear(&bufev->timeout_write);
|
||||
}
|
||||
|
||||
if (bufev->be_ops->adj_timeouts)
|
||||
r = bufev->be_ops->adj_timeouts(bufev);
|
||||
BEV_UNLOCK(bufev);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/* Obsolete; use bufferevent_set_timeouts */
|
||||
void
|
||||
bufferevent_settimeout(struct bufferevent *bufev,
|
||||
int timeout_read, int timeout_write)
|
||||
{
|
||||
struct timeval tv_read, tv_write;
|
||||
struct timeval *ptv_read = NULL, *ptv_write = NULL;
|
||||
|
||||
memset(&tv_read, 0, sizeof(tv_read));
|
||||
memset(&tv_write, 0, sizeof(tv_write));
|
||||
|
||||
if (timeout_read) {
|
||||
tv_read.tv_sec = timeout_read;
|
||||
ptv_read = &tv_read;
|
||||
}
|
||||
if (timeout_write) {
|
||||
tv_write.tv_sec = timeout_write;
|
||||
ptv_write = &tv_write;
|
||||
}
|
||||
|
||||
bufferevent_set_timeouts(bufev, ptv_read, ptv_write);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
bufferevent_disable_hard(struct bufferevent *bufev, short event)
|
||||
{
|
||||
int r = 0;
|
||||
struct bufferevent_private *bufev_private =
|
||||
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
|
||||
|
||||
BEV_LOCK(bufev);
|
||||
bufev->enabled &= ~event;
|
||||
|
||||
bufev_private->connecting = 0;
|
||||
if (bufev->be_ops->disable(bufev, event) < 0)
|
||||
r = -1;
|
||||
|
||||
BEV_UNLOCK(bufev);
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_disable(struct bufferevent *bufev, short event)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
BEV_LOCK(bufev);
|
||||
bufev->enabled &= ~event;
|
||||
|
||||
if (bufev->be_ops->disable(bufev, event) < 0)
|
||||
r = -1;
|
||||
|
||||
BEV_UNLOCK(bufev);
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the water marks
|
||||
*/
|
||||
|
||||
void
|
||||
bufferevent_setwatermark(struct bufferevent *bufev, short events,
|
||||
size_t lowmark, size_t highmark)
|
||||
{
|
||||
struct bufferevent_private *bufev_private =
|
||||
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
|
||||
|
||||
BEV_LOCK(bufev);
|
||||
if (events & EV_WRITE) {
|
||||
bufev->wm_write.low = lowmark;
|
||||
bufev->wm_write.high = highmark;
|
||||
}
|
||||
|
||||
if (events & EV_READ) {
|
||||
bufev->wm_read.low = lowmark;
|
||||
bufev->wm_read.high = highmark;
|
||||
|
||||
if (highmark) {
|
||||
/* There is now a new high-water mark for read.
|
||||
enable the callback if needed, and see if we should
|
||||
suspend/bufferevent_wm_unsuspend. */
|
||||
|
||||
if (bufev_private->read_watermarks_cb == NULL) {
|
||||
bufev_private->read_watermarks_cb =
|
||||
evbuffer_add_cb(bufev->input,
|
||||
bufferevent_inbuf_wm_cb,
|
||||
bufev);
|
||||
}
|
||||
evbuffer_cb_set_flags(bufev->input,
|
||||
bufev_private->read_watermarks_cb,
|
||||
EVBUFFER_CB_ENABLED|EVBUFFER_CB_NODEFER);
|
||||
|
||||
if (evbuffer_get_length(bufev->input) > highmark)
|
||||
bufferevent_wm_suspend_read(bufev);
|
||||
else if (evbuffer_get_length(bufev->input) < highmark)
|
||||
bufferevent_wm_unsuspend_read(bufev);
|
||||
} else {
|
||||
/* There is now no high-water mark for read. */
|
||||
if (bufev_private->read_watermarks_cb)
|
||||
evbuffer_cb_clear_flags(bufev->input,
|
||||
bufev_private->read_watermarks_cb,
|
||||
EVBUFFER_CB_ENABLED);
|
||||
bufferevent_wm_unsuspend_read(bufev);
|
||||
}
|
||||
}
|
||||
BEV_UNLOCK(bufev);
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_flush(struct bufferevent *bufev,
|
||||
short iotype,
|
||||
enum bufferevent_flush_mode mode)
|
||||
{
|
||||
int r = -1;
|
||||
BEV_LOCK(bufev);
|
||||
if (bufev->be_ops->flush)
|
||||
r = bufev->be_ops->flush(bufev, iotype, mode);
|
||||
BEV_UNLOCK(bufev);
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
_bufferevent_incref_and_lock(struct bufferevent *bufev)
|
||||
{
|
||||
struct bufferevent_private *bufev_private =
|
||||
BEV_UPCAST(bufev);
|
||||
BEV_LOCK(bufev);
|
||||
++bufev_private->refcnt;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
_bufferevent_transfer_lock_ownership(struct bufferevent *donor,
|
||||
struct bufferevent *recipient)
|
||||
{
|
||||
struct bufferevent_private *d = BEV_UPCAST(donor);
|
||||
struct bufferevent_private *r = BEV_UPCAST(recipient);
|
||||
if (d->lock != r->lock)
|
||||
return;
|
||||
if (r->own_lock)
|
||||
return;
|
||||
if (d->own_lock) {
|
||||
d->own_lock = 0;
|
||||
r->own_lock = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
_bufferevent_decref_and_unlock(struct bufferevent *bufev)
|
||||
{
|
||||
struct bufferevent_private *bufev_private =
|
||||
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
|
||||
struct bufferevent *underlying;
|
||||
|
||||
EVUTIL_ASSERT(bufev_private->refcnt > 0);
|
||||
|
||||
if (--bufev_private->refcnt) {
|
||||
BEV_UNLOCK(bufev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
underlying = bufferevent_get_underlying(bufev);
|
||||
|
||||
/* Clean up the shared info */
|
||||
if (bufev->be_ops->destruct)
|
||||
bufev->be_ops->destruct(bufev);
|
||||
|
||||
/* XXX what happens if refcnt for these buffers is > 1?
|
||||
* The buffers can share a lock with this bufferevent object,
|
||||
* but the lock might be destroyed below. */
|
||||
/* evbuffer will free the callbacks */
|
||||
evbuffer_free(bufev->input);
|
||||
evbuffer_free(bufev->output);
|
||||
|
||||
if (bufev_private->rate_limiting) {
|
||||
if (bufev_private->rate_limiting->group)
|
||||
bufferevent_remove_from_rate_limit_group_internal(bufev,0);
|
||||
if (event_initialized(&bufev_private->rate_limiting->refill_bucket_event))
|
||||
event_del(&bufev_private->rate_limiting->refill_bucket_event);
|
||||
event_debug_unassign(&bufev_private->rate_limiting->refill_bucket_event);
|
||||
mm_free(bufev_private->rate_limiting);
|
||||
bufev_private->rate_limiting = NULL;
|
||||
}
|
||||
|
||||
event_debug_unassign(&bufev->ev_read);
|
||||
event_debug_unassign(&bufev->ev_write);
|
||||
|
||||
BEV_UNLOCK(bufev);
|
||||
if (bufev_private->own_lock)
|
||||
EVTHREAD_FREE_LOCK(bufev_private->lock,
|
||||
EVTHREAD_LOCKTYPE_RECURSIVE);
|
||||
|
||||
/* Free the actual allocated memory. */
|
||||
mm_free(((char*)bufev) - bufev->be_ops->mem_offset);
|
||||
|
||||
/* Release the reference to underlying now that we no longer need the
|
||||
* reference to it. We wait this long mainly in case our lock is
|
||||
* shared with underlying.
|
||||
*
|
||||
* The 'destruct' function will also drop a reference to underlying
|
||||
* if BEV_OPT_CLOSE_ON_FREE is set.
|
||||
*
|
||||
* XXX Should we/can we just refcount evbuffer/bufferevent locks?
|
||||
* It would probably save us some headaches.
|
||||
*/
|
||||
if (underlying)
|
||||
bufferevent_decref(underlying);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_decref(struct bufferevent *bufev)
|
||||
{
|
||||
BEV_LOCK(bufev);
|
||||
return _bufferevent_decref_and_unlock(bufev);
|
||||
}
|
||||
|
||||
void
|
||||
bufferevent_free(struct bufferevent *bufev)
|
||||
{
|
||||
BEV_LOCK(bufev);
|
||||
bufferevent_setcb(bufev, NULL, NULL, NULL, NULL);
|
||||
_bufferevent_cancel_all(bufev);
|
||||
_bufferevent_decref_and_unlock(bufev);
|
||||
}
|
||||
|
||||
void
|
||||
bufferevent_incref(struct bufferevent *bufev)
|
||||
{
|
||||
struct bufferevent_private *bufev_private =
|
||||
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
|
||||
|
||||
BEV_LOCK(bufev);
|
||||
++bufev_private->refcnt;
|
||||
BEV_UNLOCK(bufev);
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_enable_locking(struct bufferevent *bufev, void *lock)
|
||||
{
|
||||
#ifdef _EVENT_DISABLE_THREAD_SUPPORT
|
||||
return -1;
|
||||
#else
|
||||
struct bufferevent *underlying;
|
||||
|
||||
if (BEV_UPCAST(bufev)->lock)
|
||||
return -1;
|
||||
underlying = bufferevent_get_underlying(bufev);
|
||||
|
||||
if (!lock && underlying && BEV_UPCAST(underlying)->lock) {
|
||||
lock = BEV_UPCAST(underlying)->lock;
|
||||
BEV_UPCAST(bufev)->lock = lock;
|
||||
BEV_UPCAST(bufev)->own_lock = 0;
|
||||
} else if (!lock) {
|
||||
EVTHREAD_ALLOC_LOCK(lock, EVTHREAD_LOCKTYPE_RECURSIVE);
|
||||
if (!lock)
|
||||
return -1;
|
||||
BEV_UPCAST(bufev)->lock = lock;
|
||||
BEV_UPCAST(bufev)->own_lock = 1;
|
||||
} else {
|
||||
BEV_UPCAST(bufev)->lock = lock;
|
||||
BEV_UPCAST(bufev)->own_lock = 0;
|
||||
}
|
||||
evbuffer_enable_locking(bufev->input, lock);
|
||||
evbuffer_enable_locking(bufev->output, lock);
|
||||
|
||||
if (underlying && !BEV_UPCAST(underlying)->lock)
|
||||
bufferevent_enable_locking(underlying, lock);
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_setfd(struct bufferevent *bev, evutil_socket_t fd)
|
||||
{
|
||||
union bufferevent_ctrl_data d;
|
||||
int res = -1;
|
||||
d.fd = fd;
|
||||
BEV_LOCK(bev);
|
||||
if (bev->be_ops->ctrl)
|
||||
res = bev->be_ops->ctrl(bev, BEV_CTRL_SET_FD, &d);
|
||||
BEV_UNLOCK(bev);
|
||||
return res;
|
||||
}
|
||||
|
||||
evutil_socket_t
|
||||
bufferevent_getfd(struct bufferevent *bev)
|
||||
{
|
||||
union bufferevent_ctrl_data d;
|
||||
int res = -1;
|
||||
d.fd = -1;
|
||||
BEV_LOCK(bev);
|
||||
if (bev->be_ops->ctrl)
|
||||
res = bev->be_ops->ctrl(bev, BEV_CTRL_GET_FD, &d);
|
||||
BEV_UNLOCK(bev);
|
||||
return (res<0) ? -1 : d.fd;
|
||||
}
|
||||
|
||||
static void
|
||||
_bufferevent_cancel_all(struct bufferevent *bev)
|
||||
{
|
||||
union bufferevent_ctrl_data d;
|
||||
memset(&d, 0, sizeof(d));
|
||||
BEV_LOCK(bev);
|
||||
if (bev->be_ops->ctrl)
|
||||
bev->be_ops->ctrl(bev, BEV_CTRL_CANCEL_ALL, &d);
|
||||
BEV_UNLOCK(bev);
|
||||
}
|
||||
|
||||
short
|
||||
bufferevent_get_enabled(struct bufferevent *bufev)
|
||||
{
|
||||
short r;
|
||||
BEV_LOCK(bufev);
|
||||
r = bufev->enabled;
|
||||
BEV_UNLOCK(bufev);
|
||||
return r;
|
||||
}
|
||||
|
||||
struct bufferevent *
|
||||
bufferevent_get_underlying(struct bufferevent *bev)
|
||||
{
|
||||
union bufferevent_ctrl_data d;
|
||||
int res = -1;
|
||||
d.ptr = NULL;
|
||||
BEV_LOCK(bev);
|
||||
if (bev->be_ops->ctrl)
|
||||
res = bev->be_ops->ctrl(bev, BEV_CTRL_GET_UNDERLYING, &d);
|
||||
BEV_UNLOCK(bev);
|
||||
return (res<0) ? NULL : d.ptr;
|
||||
}
|
||||
|
||||
static void
|
||||
bufferevent_generic_read_timeout_cb(evutil_socket_t fd, short event, void *ctx)
|
||||
{
|
||||
struct bufferevent *bev = ctx;
|
||||
_bufferevent_incref_and_lock(bev);
|
||||
bufferevent_disable(bev, EV_READ);
|
||||
_bufferevent_run_eventcb(bev, BEV_EVENT_TIMEOUT|BEV_EVENT_READING);
|
||||
_bufferevent_decref_and_unlock(bev);
|
||||
}
|
||||
static void
|
||||
bufferevent_generic_write_timeout_cb(evutil_socket_t fd, short event, void *ctx)
|
||||
{
|
||||
struct bufferevent *bev = ctx;
|
||||
_bufferevent_incref_and_lock(bev);
|
||||
bufferevent_disable(bev, EV_WRITE);
|
||||
_bufferevent_run_eventcb(bev, BEV_EVENT_TIMEOUT|BEV_EVENT_WRITING);
|
||||
_bufferevent_decref_and_unlock(bev);
|
||||
}
|
||||
|
||||
void
|
||||
_bufferevent_init_generic_timeout_cbs(struct bufferevent *bev)
|
||||
{
|
||||
evtimer_assign(&bev->ev_read, bev->ev_base,
|
||||
bufferevent_generic_read_timeout_cb, bev);
|
||||
evtimer_assign(&bev->ev_write, bev->ev_base,
|
||||
bufferevent_generic_write_timeout_cb, bev);
|
||||
}
|
||||
|
||||
int
|
||||
_bufferevent_del_generic_timeout_cbs(struct bufferevent *bev)
|
||||
{
|
||||
int r1,r2;
|
||||
r1 = event_del(&bev->ev_read);
|
||||
r2 = event_del(&bev->ev_write);
|
||||
if (r1<0 || r2<0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_bufferevent_generic_adj_timeouts(struct bufferevent *bev)
|
||||
{
|
||||
const short enabled = bev->enabled;
|
||||
struct bufferevent_private *bev_p =
|
||||
EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
|
||||
int r1=0, r2=0;
|
||||
if ((enabled & EV_READ) && !bev_p->read_suspended &&
|
||||
evutil_timerisset(&bev->timeout_read))
|
||||
r1 = event_add(&bev->ev_read, &bev->timeout_read);
|
||||
else
|
||||
r1 = event_del(&bev->ev_read);
|
||||
|
||||
if ((enabled & EV_WRITE) && !bev_p->write_suspended &&
|
||||
evutil_timerisset(&bev->timeout_write) &&
|
||||
evbuffer_get_length(bev->output))
|
||||
r2 = event_add(&bev->ev_write, &bev->timeout_write);
|
||||
else
|
||||
r2 = event_del(&bev->ev_write);
|
||||
if (r1 < 0 || r2 < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_bufferevent_add_event(struct event *ev, const struct timeval *tv)
|
||||
{
|
||||
if (tv->tv_sec == 0 && tv->tv_usec == 0)
|
||||
return event_add(ev, NULL);
|
||||
else
|
||||
return event_add(ev, tv);
|
||||
}
|
||||
|
||||
/* For use by user programs only; internally, we should be calling
|
||||
either _bufferevent_incref_and_lock(), or BEV_LOCK. */
|
||||
void
|
||||
bufferevent_lock(struct bufferevent *bev)
|
||||
{
|
||||
_bufferevent_incref_and_lock(bev);
|
||||
}
|
||||
|
||||
void
|
||||
bufferevent_unlock(struct bufferevent *bev)
|
||||
{
|
||||
_bufferevent_decref_and_unlock(bev);
|
||||
}
|
693
external/bsd/libevent/dist/bufferevent_async.c
vendored
Normal file
693
external/bsd/libevent/dist/bufferevent_async.c
vendored
Normal file
|
@ -0,0 +1,693 @@
|
|||
/* $NetBSD: bufferevent_async.c,v 1.1.1.1 2013/04/11 16:43:28 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009-2012 Niels Provos and Nick Mathewson
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "event2/event-config.h"
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: bufferevent_async.c,v 1.1.1.1 2013/04/11 16:43:28 christos Exp $");
|
||||
|
||||
#ifdef _EVENT_HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef _EVENT_HAVE_STDARG_H
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
#ifdef _EVENT_HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include "event2/util.h"
|
||||
#include "event2/bufferevent.h"
|
||||
#include "event2/buffer.h"
|
||||
#include "event2/bufferevent_struct.h"
|
||||
#include "event2/event.h"
|
||||
#include "event2/util.h"
|
||||
#include "event-internal.h"
|
||||
#include "log-internal.h"
|
||||
#include "mm-internal.h"
|
||||
#include "bufferevent-internal.h"
|
||||
#include "util-internal.h"
|
||||
#include "iocp-internal.h"
|
||||
|
||||
#ifndef SO_UPDATE_CONNECT_CONTEXT
|
||||
/* Mingw is sometimes missing this */
|
||||
#define SO_UPDATE_CONNECT_CONTEXT 0x7010
|
||||
#endif
|
||||
|
||||
/* prototypes */
|
||||
static int be_async_enable(struct bufferevent *, short);
|
||||
static int be_async_disable(struct bufferevent *, short);
|
||||
static void be_async_destruct(struct bufferevent *);
|
||||
static int be_async_flush(struct bufferevent *, short, enum bufferevent_flush_mode);
|
||||
static int be_async_ctrl(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *);
|
||||
|
||||
struct bufferevent_async {
|
||||
struct bufferevent_private bev;
|
||||
struct event_overlapped connect_overlapped;
|
||||
struct event_overlapped read_overlapped;
|
||||
struct event_overlapped write_overlapped;
|
||||
size_t read_in_progress;
|
||||
size_t write_in_progress;
|
||||
unsigned ok : 1;
|
||||
unsigned read_added : 1;
|
||||
unsigned write_added : 1;
|
||||
};
|
||||
|
||||
const struct bufferevent_ops bufferevent_ops_async = {
|
||||
"socket_async",
|
||||
evutil_offsetof(struct bufferevent_async, bev.bev),
|
||||
be_async_enable,
|
||||
be_async_disable,
|
||||
be_async_destruct,
|
||||
_bufferevent_generic_adj_timeouts,
|
||||
be_async_flush,
|
||||
be_async_ctrl,
|
||||
};
|
||||
|
||||
static inline struct bufferevent_async *
|
||||
upcast(struct bufferevent *bev)
|
||||
{
|
||||
struct bufferevent_async *bev_a;
|
||||
if (bev->be_ops != &bufferevent_ops_async)
|
||||
return NULL;
|
||||
bev_a = EVUTIL_UPCAST(bev, struct bufferevent_async, bev.bev);
|
||||
return bev_a;
|
||||
}
|
||||
|
||||
static inline struct bufferevent_async *
|
||||
upcast_connect(struct event_overlapped *eo)
|
||||
{
|
||||
struct bufferevent_async *bev_a;
|
||||
bev_a = EVUTIL_UPCAST(eo, struct bufferevent_async, connect_overlapped);
|
||||
EVUTIL_ASSERT(BEV_IS_ASYNC(&bev_a->bev.bev));
|
||||
return bev_a;
|
||||
}
|
||||
|
||||
static inline struct bufferevent_async *
|
||||
upcast_read(struct event_overlapped *eo)
|
||||
{
|
||||
struct bufferevent_async *bev_a;
|
||||
bev_a = EVUTIL_UPCAST(eo, struct bufferevent_async, read_overlapped);
|
||||
EVUTIL_ASSERT(BEV_IS_ASYNC(&bev_a->bev.bev));
|
||||
return bev_a;
|
||||
}
|
||||
|
||||
static inline struct bufferevent_async *
|
||||
upcast_write(struct event_overlapped *eo)
|
||||
{
|
||||
struct bufferevent_async *bev_a;
|
||||
bev_a = EVUTIL_UPCAST(eo, struct bufferevent_async, write_overlapped);
|
||||
EVUTIL_ASSERT(BEV_IS_ASYNC(&bev_a->bev.bev));
|
||||
return bev_a;
|
||||
}
|
||||
|
||||
static void
|
||||
bev_async_del_write(struct bufferevent_async *beva)
|
||||
{
|
||||
struct bufferevent *bev = &beva->bev.bev;
|
||||
|
||||
if (beva->write_added) {
|
||||
beva->write_added = 0;
|
||||
event_base_del_virtual(bev->ev_base);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bev_async_del_read(struct bufferevent_async *beva)
|
||||
{
|
||||
struct bufferevent *bev = &beva->bev.bev;
|
||||
|
||||
if (beva->read_added) {
|
||||
beva->read_added = 0;
|
||||
event_base_del_virtual(bev->ev_base);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bev_async_add_write(struct bufferevent_async *beva)
|
||||
{
|
||||
struct bufferevent *bev = &beva->bev.bev;
|
||||
|
||||
if (!beva->write_added) {
|
||||
beva->write_added = 1;
|
||||
event_base_add_virtual(bev->ev_base);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bev_async_add_read(struct bufferevent_async *beva)
|
||||
{
|
||||
struct bufferevent *bev = &beva->bev.bev;
|
||||
|
||||
if (!beva->read_added) {
|
||||
beva->read_added = 1;
|
||||
event_base_add_virtual(bev->ev_base);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bev_async_consider_writing(struct bufferevent_async *beva)
|
||||
{
|
||||
size_t at_most;
|
||||
int limit;
|
||||
struct bufferevent *bev = &beva->bev.bev;
|
||||
|
||||
/* Don't write if there's a write in progress, or we do not
|
||||
* want to write, or when there's nothing left to write. */
|
||||
if (beva->write_in_progress || beva->bev.connecting)
|
||||
return;
|
||||
if (!beva->ok || !(bev->enabled&EV_WRITE) ||
|
||||
!evbuffer_get_length(bev->output)) {
|
||||
bev_async_del_write(beva);
|
||||
return;
|
||||
}
|
||||
|
||||
at_most = evbuffer_get_length(bev->output);
|
||||
|
||||
/* This is safe so long as bufferevent_get_write_max never returns
|
||||
* more than INT_MAX. That's true for now. XXXX */
|
||||
limit = (int)_bufferevent_get_write_max(&beva->bev);
|
||||
if (at_most >= (size_t)limit && limit >= 0)
|
||||
at_most = limit;
|
||||
|
||||
if (beva->bev.write_suspended) {
|
||||
bev_async_del_write(beva);
|
||||
return;
|
||||
}
|
||||
|
||||
/* XXXX doesn't respect low-water mark very well. */
|
||||
bufferevent_incref(bev);
|
||||
if (evbuffer_launch_write(bev->output, at_most,
|
||||
&beva->write_overlapped)) {
|
||||
bufferevent_decref(bev);
|
||||
beva->ok = 0;
|
||||
_bufferevent_run_eventcb(bev, BEV_EVENT_ERROR);
|
||||
} else {
|
||||
beva->write_in_progress = at_most;
|
||||
_bufferevent_decrement_write_buckets(&beva->bev, at_most);
|
||||
bev_async_add_write(beva);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bev_async_consider_reading(struct bufferevent_async *beva)
|
||||
{
|
||||
size_t cur_size;
|
||||
size_t read_high;
|
||||
size_t at_most;
|
||||
int limit;
|
||||
struct bufferevent *bev = &beva->bev.bev;
|
||||
|
||||
/* Don't read if there is a read in progress, or we do not
|
||||
* want to read. */
|
||||
if (beva->read_in_progress || beva->bev.connecting)
|
||||
return;
|
||||
if (!beva->ok || !(bev->enabled&EV_READ)) {
|
||||
bev_async_del_read(beva);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Don't read if we're full */
|
||||
cur_size = evbuffer_get_length(bev->input);
|
||||
read_high = bev->wm_read.high;
|
||||
if (read_high) {
|
||||
if (cur_size >= read_high) {
|
||||
bev_async_del_read(beva);
|
||||
return;
|
||||
}
|
||||
at_most = read_high - cur_size;
|
||||
} else {
|
||||
at_most = 16384; /* FIXME totally magic. */
|
||||
}
|
||||
|
||||
/* XXXX This over-commits. */
|
||||
/* XXXX see also not above on cast on _bufferevent_get_write_max() */
|
||||
limit = (int)_bufferevent_get_read_max(&beva->bev);
|
||||
if (at_most >= (size_t)limit && limit >= 0)
|
||||
at_most = limit;
|
||||
|
||||
if (beva->bev.read_suspended) {
|
||||
bev_async_del_read(beva);
|
||||
return;
|
||||
}
|
||||
|
||||
bufferevent_incref(bev);
|
||||
if (evbuffer_launch_read(bev->input, at_most, &beva->read_overlapped)) {
|
||||
beva->ok = 0;
|
||||
_bufferevent_run_eventcb(bev, BEV_EVENT_ERROR);
|
||||
bufferevent_decref(bev);
|
||||
} else {
|
||||
beva->read_in_progress = at_most;
|
||||
_bufferevent_decrement_read_buckets(&beva->bev, at_most);
|
||||
bev_async_add_read(beva);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
be_async_outbuf_callback(struct evbuffer *buf,
|
||||
const struct evbuffer_cb_info *cbinfo,
|
||||
void *arg)
|
||||
{
|
||||
struct bufferevent *bev = arg;
|
||||
struct bufferevent_async *bev_async = upcast(bev);
|
||||
|
||||
/* If we added data to the outbuf and were not writing before,
|
||||
* we may want to write now. */
|
||||
|
||||
_bufferevent_incref_and_lock(bev);
|
||||
|
||||
if (cbinfo->n_added)
|
||||
bev_async_consider_writing(bev_async);
|
||||
|
||||
_bufferevent_decref_and_unlock(bev);
|
||||
}
|
||||
|
||||
static void
|
||||
be_async_inbuf_callback(struct evbuffer *buf,
|
||||
const struct evbuffer_cb_info *cbinfo,
|
||||
void *arg)
|
||||
{
|
||||
struct bufferevent *bev = arg;
|
||||
struct bufferevent_async *bev_async = upcast(bev);
|
||||
|
||||
/* If we drained data from the inbuf and were not reading before,
|
||||
* we may want to read now */
|
||||
|
||||
_bufferevent_incref_and_lock(bev);
|
||||
|
||||
if (cbinfo->n_deleted)
|
||||
bev_async_consider_reading(bev_async);
|
||||
|
||||
_bufferevent_decref_and_unlock(bev);
|
||||
}
|
||||
|
||||
static int
|
||||
be_async_enable(struct bufferevent *buf, short what)
|
||||
{
|
||||
struct bufferevent_async *bev_async = upcast(buf);
|
||||
|
||||
if (!bev_async->ok)
|
||||
return -1;
|
||||
|
||||
if (bev_async->bev.connecting) {
|
||||
/* Don't launch anything during connection attempts. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (what & EV_READ)
|
||||
BEV_RESET_GENERIC_READ_TIMEOUT(buf);
|
||||
if (what & EV_WRITE)
|
||||
BEV_RESET_GENERIC_WRITE_TIMEOUT(buf);
|
||||
|
||||
/* If we newly enable reading or writing, and we aren't reading or
|
||||
writing already, consider launching a new read or write. */
|
||||
|
||||
if (what & EV_READ)
|
||||
bev_async_consider_reading(bev_async);
|
||||
if (what & EV_WRITE)
|
||||
bev_async_consider_writing(bev_async);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
be_async_disable(struct bufferevent *bev, short what)
|
||||
{
|
||||
struct bufferevent_async *bev_async = upcast(bev);
|
||||
/* XXXX If we disable reading or writing, we may want to consider
|
||||
* canceling any in-progress read or write operation, though it might
|
||||
* not work. */
|
||||
|
||||
if (what & EV_READ) {
|
||||
BEV_DEL_GENERIC_READ_TIMEOUT(bev);
|
||||
bev_async_del_read(bev_async);
|
||||
}
|
||||
if (what & EV_WRITE) {
|
||||
BEV_DEL_GENERIC_WRITE_TIMEOUT(bev);
|
||||
bev_async_del_write(bev_async);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
be_async_destruct(struct bufferevent *bev)
|
||||
{
|
||||
struct bufferevent_async *bev_async = upcast(bev);
|
||||
struct bufferevent_private *bev_p = BEV_UPCAST(bev);
|
||||
evutil_socket_t fd;
|
||||
|
||||
EVUTIL_ASSERT(!upcast(bev)->write_in_progress &&
|
||||
!upcast(bev)->read_in_progress);
|
||||
|
||||
bev_async_del_read(bev_async);
|
||||
bev_async_del_write(bev_async);
|
||||
|
||||
fd = _evbuffer_overlapped_get_fd(bev->input);
|
||||
if (bev_p->options & BEV_OPT_CLOSE_ON_FREE) {
|
||||
/* XXXX possible double-close */
|
||||
evutil_closesocket(fd);
|
||||
}
|
||||
/* delete this in case non-blocking connect was used */
|
||||
if (event_initialized(&bev->ev_write)) {
|
||||
event_del(&bev->ev_write);
|
||||
_bufferevent_del_generic_timeout_cbs(bev);
|
||||
}
|
||||
}
|
||||
|
||||
/* GetQueuedCompletionStatus doesn't reliably yield WSA error codes, so
|
||||
* we use WSAGetOverlappedResult to translate. */
|
||||
static void
|
||||
bev_async_set_wsa_error(struct bufferevent *bev, struct event_overlapped *eo)
|
||||
{
|
||||
DWORD bytes, flags;
|
||||
evutil_socket_t fd;
|
||||
|
||||
fd = _evbuffer_overlapped_get_fd(bev->input);
|
||||
WSAGetOverlappedResult(fd, &eo->overlapped, &bytes, FALSE, &flags);
|
||||
}
|
||||
|
||||
static int
|
||||
be_async_flush(struct bufferevent *bev, short what,
|
||||
enum bufferevent_flush_mode mode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
connect_complete(struct event_overlapped *eo, ev_uintptr_t key,
|
||||
ev_ssize_t nbytes, int ok)
|
||||
{
|
||||
struct bufferevent_async *bev_a = upcast_connect(eo);
|
||||
struct bufferevent *bev = &bev_a->bev.bev;
|
||||
evutil_socket_t sock;
|
||||
|
||||
BEV_LOCK(bev);
|
||||
|
||||
EVUTIL_ASSERT(bev_a->bev.connecting);
|
||||
bev_a->bev.connecting = 0;
|
||||
sock = _evbuffer_overlapped_get_fd(bev_a->bev.bev.input);
|
||||
/* XXXX Handle error? */
|
||||
setsockopt(sock, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0);
|
||||
|
||||
if (ok)
|
||||
bufferevent_async_set_connected(bev);
|
||||
else
|
||||
bev_async_set_wsa_error(bev, eo);
|
||||
|
||||
_bufferevent_run_eventcb(bev,
|
||||
ok? BEV_EVENT_CONNECTED : BEV_EVENT_ERROR);
|
||||
|
||||
event_base_del_virtual(bev->ev_base);
|
||||
|
||||
_bufferevent_decref_and_unlock(bev);
|
||||
}
|
||||
|
||||
static void
|
||||
read_complete(struct event_overlapped *eo, ev_uintptr_t key,
|
||||
ev_ssize_t nbytes, int ok)
|
||||
{
|
||||
struct bufferevent_async *bev_a = upcast_read(eo);
|
||||
struct bufferevent *bev = &bev_a->bev.bev;
|
||||
short what = BEV_EVENT_READING;
|
||||
ev_ssize_t amount_unread;
|
||||
BEV_LOCK(bev);
|
||||
EVUTIL_ASSERT(bev_a->read_in_progress);
|
||||
|
||||
amount_unread = bev_a->read_in_progress - nbytes;
|
||||
evbuffer_commit_read(bev->input, nbytes);
|
||||
bev_a->read_in_progress = 0;
|
||||
if (amount_unread)
|
||||
_bufferevent_decrement_read_buckets(&bev_a->bev, -amount_unread);
|
||||
|
||||
if (!ok)
|
||||
bev_async_set_wsa_error(bev, eo);
|
||||
|
||||
if (bev_a->ok) {
|
||||
if (ok && nbytes) {
|
||||
BEV_RESET_GENERIC_READ_TIMEOUT(bev);
|
||||
if (evbuffer_get_length(bev->input) >= bev->wm_read.low)
|
||||
_bufferevent_run_readcb(bev);
|
||||
bev_async_consider_reading(bev_a);
|
||||
} else if (!ok) {
|
||||
what |= BEV_EVENT_ERROR;
|
||||
bev_a->ok = 0;
|
||||
_bufferevent_run_eventcb(bev, what);
|
||||
} else if (!nbytes) {
|
||||
what |= BEV_EVENT_EOF;
|
||||
bev_a->ok = 0;
|
||||
_bufferevent_run_eventcb(bev, what);
|
||||
}
|
||||
}
|
||||
|
||||
_bufferevent_decref_and_unlock(bev);
|
||||
}
|
||||
|
||||
static void
|
||||
write_complete(struct event_overlapped *eo, ev_uintptr_t key,
|
||||
ev_ssize_t nbytes, int ok)
|
||||
{
|
||||
struct bufferevent_async *bev_a = upcast_write(eo);
|
||||
struct bufferevent *bev = &bev_a->bev.bev;
|
||||
short what = BEV_EVENT_WRITING;
|
||||
ev_ssize_t amount_unwritten;
|
||||
|
||||
BEV_LOCK(bev);
|
||||
EVUTIL_ASSERT(bev_a->write_in_progress);
|
||||
|
||||
amount_unwritten = bev_a->write_in_progress - nbytes;
|
||||
evbuffer_commit_write(bev->output, nbytes);
|
||||
bev_a->write_in_progress = 0;
|
||||
|
||||
if (amount_unwritten)
|
||||
_bufferevent_decrement_write_buckets(&bev_a->bev,
|
||||
-amount_unwritten);
|
||||
|
||||
|
||||
if (!ok)
|
||||
bev_async_set_wsa_error(bev, eo);
|
||||
|
||||
if (bev_a->ok) {
|
||||
if (ok && nbytes) {
|
||||
BEV_RESET_GENERIC_WRITE_TIMEOUT(bev);
|
||||
if (evbuffer_get_length(bev->output) <=
|
||||
bev->wm_write.low)
|
||||
_bufferevent_run_writecb(bev);
|
||||
bev_async_consider_writing(bev_a);
|
||||
} else if (!ok) {
|
||||
what |= BEV_EVENT_ERROR;
|
||||
bev_a->ok = 0;
|
||||
_bufferevent_run_eventcb(bev, what);
|
||||
} else if (!nbytes) {
|
||||
what |= BEV_EVENT_EOF;
|
||||
bev_a->ok = 0;
|
||||
_bufferevent_run_eventcb(bev, what);
|
||||
}
|
||||
}
|
||||
|
||||
_bufferevent_decref_and_unlock(bev);
|
||||
}
|
||||
|
||||
struct bufferevent *
|
||||
bufferevent_async_new(struct event_base *base,
|
||||
evutil_socket_t fd, int options)
|
||||
{
|
||||
struct bufferevent_async *bev_a;
|
||||
struct bufferevent *bev;
|
||||
struct event_iocp_port *iocp;
|
||||
|
||||
options |= BEV_OPT_THREADSAFE;
|
||||
|
||||
if (!(iocp = event_base_get_iocp(base)))
|
||||
return NULL;
|
||||
|
||||
if (fd >= 0 && event_iocp_port_associate(iocp, fd, 1)<0) {
|
||||
int err = GetLastError();
|
||||
/* We may have alrady associated this fd with a port.
|
||||
* Let's hope it's this port, and that the error code
|
||||
* for doing this neer changes. */
|
||||
if (err != ERROR_INVALID_PARAMETER)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(bev_a = mm_calloc(1, sizeof(struct bufferevent_async))))
|
||||
return NULL;
|
||||
|
||||
bev = &bev_a->bev.bev;
|
||||
if (!(bev->input = evbuffer_overlapped_new(fd))) {
|
||||
mm_free(bev_a);
|
||||
return NULL;
|
||||
}
|
||||
if (!(bev->output = evbuffer_overlapped_new(fd))) {
|
||||
evbuffer_free(bev->input);
|
||||
mm_free(bev_a);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (bufferevent_init_common(&bev_a->bev, base, &bufferevent_ops_async,
|
||||
options)<0)
|
||||
goto err;
|
||||
|
||||
evbuffer_add_cb(bev->input, be_async_inbuf_callback, bev);
|
||||
evbuffer_add_cb(bev->output, be_async_outbuf_callback, bev);
|
||||
|
||||
event_overlapped_init(&bev_a->connect_overlapped, connect_complete);
|
||||
event_overlapped_init(&bev_a->read_overlapped, read_complete);
|
||||
event_overlapped_init(&bev_a->write_overlapped, write_complete);
|
||||
|
||||
bev_a->ok = fd >= 0;
|
||||
if (bev_a->ok)
|
||||
_bufferevent_init_generic_timeout_cbs(bev);
|
||||
|
||||
return bev;
|
||||
err:
|
||||
bufferevent_free(&bev_a->bev.bev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
bufferevent_async_set_connected(struct bufferevent *bev)
|
||||
{
|
||||
struct bufferevent_async *bev_async = upcast(bev);
|
||||
bev_async->ok = 1;
|
||||
_bufferevent_init_generic_timeout_cbs(bev);
|
||||
/* Now's a good time to consider reading/writing */
|
||||
be_async_enable(bev, bev->enabled);
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_async_can_connect(struct bufferevent *bev)
|
||||
{
|
||||
const struct win32_extension_fns *ext =
|
||||
event_get_win32_extension_fns();
|
||||
|
||||
if (BEV_IS_ASYNC(bev) &&
|
||||
event_base_get_iocp(bev->ev_base) &&
|
||||
ext && ext->ConnectEx)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_async_connect(struct bufferevent *bev, evutil_socket_t fd,
|
||||
const struct sockaddr *sa, int socklen)
|
||||
{
|
||||
BOOL rc;
|
||||
struct bufferevent_async *bev_async = upcast(bev);
|
||||
struct sockaddr_storage ss;
|
||||
const struct win32_extension_fns *ext =
|
||||
event_get_win32_extension_fns();
|
||||
|
||||
EVUTIL_ASSERT(ext && ext->ConnectEx && fd >= 0 && sa != NULL);
|
||||
|
||||
/* ConnectEx() requires that the socket be bound to an address
|
||||
* with bind() before using, otherwise it will fail. We attempt
|
||||
* to issue a bind() here, taking into account that the error
|
||||
* code is set to WSAEINVAL when the socket is already bound. */
|
||||
memset(&ss, 0, sizeof(ss));
|
||||
if (sa->sa_family == AF_INET) {
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_addr.s_addr = INADDR_ANY;
|
||||
} else if (sa->sa_family == AF_INET6) {
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss;
|
||||
sin6->sin6_family = AF_INET6;
|
||||
sin6->sin6_addr = in6addr_any;
|
||||
} else {
|
||||
/* Well, the user will have to bind() */
|
||||
return -1;
|
||||
}
|
||||
if (bind(fd, (struct sockaddr *)&ss, sizeof(ss)) < 0 &&
|
||||
WSAGetLastError() != WSAEINVAL)
|
||||
return -1;
|
||||
|
||||
event_base_add_virtual(bev->ev_base);
|
||||
bufferevent_incref(bev);
|
||||
rc = ext->ConnectEx(fd, sa, socklen, NULL, 0, NULL,
|
||||
&bev_async->connect_overlapped.overlapped);
|
||||
if (rc || WSAGetLastError() == ERROR_IO_PENDING)
|
||||
return 0;
|
||||
|
||||
event_base_del_virtual(bev->ev_base);
|
||||
bufferevent_decref(bev);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
be_async_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op,
|
||||
union bufferevent_ctrl_data *data)
|
||||
{
|
||||
switch (op) {
|
||||
case BEV_CTRL_GET_FD:
|
||||
data->fd = _evbuffer_overlapped_get_fd(bev->input);
|
||||
return 0;
|
||||
case BEV_CTRL_SET_FD: {
|
||||
struct event_iocp_port *iocp;
|
||||
|
||||
if (data->fd == _evbuffer_overlapped_get_fd(bev->input))
|
||||
return 0;
|
||||
if (!(iocp = event_base_get_iocp(bev->ev_base)))
|
||||
return -1;
|
||||
if (event_iocp_port_associate(iocp, data->fd, 1) < 0)
|
||||
return -1;
|
||||
_evbuffer_overlapped_set_fd(bev->input, data->fd);
|
||||
_evbuffer_overlapped_set_fd(bev->output, data->fd);
|
||||
return 0;
|
||||
}
|
||||
case BEV_CTRL_CANCEL_ALL: {
|
||||
struct bufferevent_async *bev_a = upcast(bev);
|
||||
evutil_socket_t fd = _evbuffer_overlapped_get_fd(bev->input);
|
||||
if (fd != (evutil_socket_t)INVALID_SOCKET &&
|
||||
(bev_a->bev.options & BEV_OPT_CLOSE_ON_FREE)) {
|
||||
closesocket(fd);
|
||||
}
|
||||
bev_a->ok = 0;
|
||||
return 0;
|
||||
}
|
||||
case BEV_CTRL_GET_UNDERLYING:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
514
external/bsd/libevent/dist/bufferevent_filter.c
vendored
Normal file
514
external/bsd/libevent/dist/bufferevent_filter.c
vendored
Normal file
|
@ -0,0 +1,514 @@
|
|||
/* $NetBSD: bufferevent_filter.c,v 1.1.1.1 2013/04/11 16:43:26 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
|
||||
* Copyright (c) 2002-2006 Niels Provos <provos@citi.umich.edu>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "event2/event-config.h"
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: bufferevent_filter.c,v 1.1.1.1 2013/04/11 16:43:26 christos Exp $");
|
||||
|
||||
#ifdef _EVENT_HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef _EVENT_HAVE_STDARG_H
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#include "event2/util.h"
|
||||
#include "event2/bufferevent.h"
|
||||
#include "event2/buffer.h"
|
||||
#include "event2/bufferevent_struct.h"
|
||||
#include "event2/event.h"
|
||||
#include "log-internal.h"
|
||||
#include "mm-internal.h"
|
||||
#include "bufferevent-internal.h"
|
||||
#include "util-internal.h"
|
||||
|
||||
/* prototypes */
|
||||
static int be_filter_enable(struct bufferevent *, short);
|
||||
static int be_filter_disable(struct bufferevent *, short);
|
||||
static void be_filter_destruct(struct bufferevent *);
|
||||
|
||||
static void be_filter_readcb(struct bufferevent *, void *);
|
||||
static void be_filter_writecb(struct bufferevent *, void *);
|
||||
static void be_filter_eventcb(struct bufferevent *, short, void *);
|
||||
static int be_filter_flush(struct bufferevent *bufev,
|
||||
short iotype, enum bufferevent_flush_mode mode);
|
||||
static int be_filter_ctrl(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *);
|
||||
|
||||
static void bufferevent_filtered_outbuf_cb(struct evbuffer *buf,
|
||||
const struct evbuffer_cb_info *info, void *arg);
|
||||
|
||||
struct bufferevent_filtered {
|
||||
struct bufferevent_private bev;
|
||||
|
||||
/** The bufferevent that we read/write filtered data from/to. */
|
||||
struct bufferevent *underlying;
|
||||
/** A callback on our outbuf to notice when somebody adds data */
|
||||
struct evbuffer_cb_entry *outbuf_cb;
|
||||
/** True iff we have received an EOF callback from the underlying
|
||||
* bufferevent. */
|
||||
unsigned got_eof;
|
||||
|
||||
/** Function to free context when we're done. */
|
||||
void (*free_context)(void *);
|
||||
/** Input filter */
|
||||
bufferevent_filter_cb process_in;
|
||||
/** Output filter */
|
||||
bufferevent_filter_cb process_out;
|
||||
/** User-supplied argument to the filters. */
|
||||
void *context;
|
||||
};
|
||||
|
||||
const struct bufferevent_ops bufferevent_ops_filter = {
|
||||
"filter",
|
||||
evutil_offsetof(struct bufferevent_filtered, bev.bev),
|
||||
be_filter_enable,
|
||||
be_filter_disable,
|
||||
be_filter_destruct,
|
||||
_bufferevent_generic_adj_timeouts,
|
||||
be_filter_flush,
|
||||
be_filter_ctrl,
|
||||
};
|
||||
|
||||
/* Given a bufferevent that's really the bev filter of a bufferevent_filtered,
|
||||
* return that bufferevent_filtered. Returns NULL otherwise.*/
|
||||
static inline struct bufferevent_filtered *
|
||||
upcast(struct bufferevent *bev)
|
||||
{
|
||||
struct bufferevent_filtered *bev_f;
|
||||
if (bev->be_ops != &bufferevent_ops_filter)
|
||||
return NULL;
|
||||
bev_f = (void*)( ((char*)bev) -
|
||||
evutil_offsetof(struct bufferevent_filtered, bev.bev));
|
||||
EVUTIL_ASSERT(bev_f->bev.bev.be_ops == &bufferevent_ops_filter);
|
||||
return bev_f;
|
||||
}
|
||||
|
||||
#define downcast(bev_f) (&(bev_f)->bev.bev)
|
||||
|
||||
/** Return 1 iff bevf's underlying bufferevent's output buffer is at or
|
||||
* over its high watermark such that we should not write to it in a given
|
||||
* flush mode. */
|
||||
static int
|
||||
be_underlying_writebuf_full(struct bufferevent_filtered *bevf,
|
||||
enum bufferevent_flush_mode state)
|
||||
{
|
||||
struct bufferevent *u = bevf->underlying;
|
||||
return state == BEV_NORMAL &&
|
||||
u->wm_write.high &&
|
||||
evbuffer_get_length(u->output) >= u->wm_write.high;
|
||||
}
|
||||
|
||||
/** Return 1 if our input buffer is at or over its high watermark such that we
|
||||
* should not write to it in a given flush mode. */
|
||||
static int
|
||||
be_readbuf_full(struct bufferevent_filtered *bevf,
|
||||
enum bufferevent_flush_mode state)
|
||||
{
|
||||
struct bufferevent *bufev = downcast(bevf);
|
||||
return state == BEV_NORMAL &&
|
||||
bufev->wm_read.high &&
|
||||
evbuffer_get_length(bufev->input) >= bufev->wm_read.high;
|
||||
}
|
||||
|
||||
|
||||
/* Filter to use when we're created with a NULL filter. */
|
||||
static enum bufferevent_filter_result
|
||||
be_null_filter(struct evbuffer *src, struct evbuffer *dst, ev_ssize_t lim,
|
||||
enum bufferevent_flush_mode state, void *ctx)
|
||||
{
|
||||
(void)state;
|
||||
if (evbuffer_remove_buffer(src, dst, lim) == 0)
|
||||
return BEV_OK;
|
||||
else
|
||||
return BEV_ERROR;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct bufferevent_filtered *bufev_f;
|
||||
int tmp_options = options & ~BEV_OPT_THREADSAFE;
|
||||
|
||||
if (!underlying)
|
||||
return NULL;
|
||||
|
||||
if (!input_filter)
|
||||
input_filter = be_null_filter;
|
||||
if (!output_filter)
|
||||
output_filter = be_null_filter;
|
||||
|
||||
bufev_f = mm_calloc(1, sizeof(struct bufferevent_filtered));
|
||||
if (!bufev_f)
|
||||
return NULL;
|
||||
|
||||
if (bufferevent_init_common(&bufev_f->bev, underlying->ev_base,
|
||||
&bufferevent_ops_filter, tmp_options) < 0) {
|
||||
mm_free(bufev_f);
|
||||
return NULL;
|
||||
}
|
||||
if (options & BEV_OPT_THREADSAFE) {
|
||||
bufferevent_enable_locking(downcast(bufev_f), NULL);
|
||||
}
|
||||
|
||||
bufev_f->underlying = underlying;
|
||||
|
||||
bufev_f->process_in = input_filter;
|
||||
bufev_f->process_out = output_filter;
|
||||
bufev_f->free_context = free_context;
|
||||
bufev_f->context = ctx;
|
||||
|
||||
bufferevent_setcb(bufev_f->underlying,
|
||||
be_filter_readcb, be_filter_writecb, be_filter_eventcb, bufev_f);
|
||||
|
||||
bufev_f->outbuf_cb = evbuffer_add_cb(downcast(bufev_f)->output,
|
||||
bufferevent_filtered_outbuf_cb, bufev_f);
|
||||
|
||||
_bufferevent_init_generic_timeout_cbs(downcast(bufev_f));
|
||||
bufferevent_incref(underlying);
|
||||
|
||||
bufferevent_enable(underlying, EV_READ|EV_WRITE);
|
||||
bufferevent_suspend_read(underlying, BEV_SUSPEND_FILT_READ);
|
||||
|
||||
return downcast(bufev_f);
|
||||
}
|
||||
|
||||
static void
|
||||
be_filter_destruct(struct bufferevent *bev)
|
||||
{
|
||||
struct bufferevent_filtered *bevf = upcast(bev);
|
||||
EVUTIL_ASSERT(bevf);
|
||||
if (bevf->free_context)
|
||||
bevf->free_context(bevf->context);
|
||||
|
||||
if (bevf->bev.options & BEV_OPT_CLOSE_ON_FREE) {
|
||||
/* Yes, there is also a decref in bufferevent_decref.
|
||||
* That decref corresponds to the incref when we set
|
||||
* underlying for the first time. This decref is an
|
||||
* extra one to remove the last reference.
|
||||
*/
|
||||
if (BEV_UPCAST(bevf->underlying)->refcnt < 2) {
|
||||
event_warnx("BEV_OPT_CLOSE_ON_FREE set on an "
|
||||
"bufferevent with too few references");
|
||||
} else {
|
||||
bufferevent_free(bevf->underlying);
|
||||
}
|
||||
} else {
|
||||
if (bevf->underlying) {
|
||||
if (bevf->underlying->errorcb == be_filter_eventcb)
|
||||
bufferevent_setcb(bevf->underlying,
|
||||
NULL, NULL, NULL, NULL);
|
||||
bufferevent_unsuspend_read(bevf->underlying,
|
||||
BEV_SUSPEND_FILT_READ);
|
||||
}
|
||||
}
|
||||
|
||||
_bufferevent_del_generic_timeout_cbs(bev);
|
||||
}
|
||||
|
||||
static int
|
||||
be_filter_enable(struct bufferevent *bev, short event)
|
||||
{
|
||||
struct bufferevent_filtered *bevf = upcast(bev);
|
||||
if (event & EV_WRITE)
|
||||
BEV_RESET_GENERIC_WRITE_TIMEOUT(bev);
|
||||
|
||||
if (event & EV_READ) {
|
||||
BEV_RESET_GENERIC_READ_TIMEOUT(bev);
|
||||
bufferevent_unsuspend_read(bevf->underlying,
|
||||
BEV_SUSPEND_FILT_READ);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
be_filter_disable(struct bufferevent *bev, short event)
|
||||
{
|
||||
struct bufferevent_filtered *bevf = upcast(bev);
|
||||
if (event & EV_WRITE)
|
||||
BEV_DEL_GENERIC_WRITE_TIMEOUT(bev);
|
||||
if (event & EV_READ) {
|
||||
BEV_DEL_GENERIC_READ_TIMEOUT(bev);
|
||||
bufferevent_suspend_read(bevf->underlying,
|
||||
BEV_SUSPEND_FILT_READ);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum bufferevent_filter_result
|
||||
be_filter_process_input(struct bufferevent_filtered *bevf,
|
||||
enum bufferevent_flush_mode state,
|
||||
int *processed_out)
|
||||
{
|
||||
enum bufferevent_filter_result res;
|
||||
struct bufferevent *bev = downcast(bevf);
|
||||
|
||||
if (state == BEV_NORMAL) {
|
||||
/* If we're in 'normal' mode, don't urge data on the filter
|
||||
* unless we're reading data and under our high-water mark.*/
|
||||
if (!(bev->enabled & EV_READ) ||
|
||||
be_readbuf_full(bevf, state))
|
||||
return BEV_OK;
|
||||
}
|
||||
|
||||
do {
|
||||
ev_ssize_t limit = -1;
|
||||
if (state == BEV_NORMAL && bev->wm_read.high)
|
||||
limit = bev->wm_read.high -
|
||||
evbuffer_get_length(bev->input);
|
||||
|
||||
res = bevf->process_in(bevf->underlying->input,
|
||||
bev->input, limit, state, bevf->context);
|
||||
|
||||
if (res == BEV_OK)
|
||||
*processed_out = 1;
|
||||
} while (res == BEV_OK &&
|
||||
(bev->enabled & EV_READ) &&
|
||||
evbuffer_get_length(bevf->underlying->input) &&
|
||||
!be_readbuf_full(bevf, state));
|
||||
|
||||
if (*processed_out)
|
||||
BEV_RESET_GENERIC_READ_TIMEOUT(bev);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static enum bufferevent_filter_result
|
||||
be_filter_process_output(struct bufferevent_filtered *bevf,
|
||||
enum bufferevent_flush_mode state,
|
||||
int *processed_out)
|
||||
{
|
||||
/* Requires references and lock: might call writecb */
|
||||
enum bufferevent_filter_result res = BEV_OK;
|
||||
struct bufferevent *bufev = downcast(bevf);
|
||||
int again = 0;
|
||||
|
||||
if (state == BEV_NORMAL) {
|
||||
/* If we're in 'normal' mode, don't urge data on the
|
||||
* filter unless we're writing data, and the underlying
|
||||
* bufferevent is accepting data, and we have data to
|
||||
* give the filter. If we're in 'flush' or 'finish',
|
||||
* call the filter no matter what. */
|
||||
if (!(bufev->enabled & EV_WRITE) ||
|
||||
be_underlying_writebuf_full(bevf, state) ||
|
||||
!evbuffer_get_length(bufev->output))
|
||||
return BEV_OK;
|
||||
}
|
||||
|
||||
/* disable the callback that calls this function
|
||||
when the user adds to the output buffer. */
|
||||
evbuffer_cb_set_flags(bufev->output, bevf->outbuf_cb, 0);
|
||||
|
||||
do {
|
||||
int processed = 0;
|
||||
again = 0;
|
||||
|
||||
do {
|
||||
ev_ssize_t limit = -1;
|
||||
if (state == BEV_NORMAL &&
|
||||
bevf->underlying->wm_write.high)
|
||||
limit = bevf->underlying->wm_write.high -
|
||||
evbuffer_get_length(bevf->underlying->output);
|
||||
|
||||
res = bevf->process_out(downcast(bevf)->output,
|
||||
bevf->underlying->output,
|
||||
limit,
|
||||
state,
|
||||
bevf->context);
|
||||
|
||||
if (res == BEV_OK)
|
||||
processed = *processed_out = 1;
|
||||
} while (/* Stop if the filter wasn't successful...*/
|
||||
res == BEV_OK &&
|
||||
/* Or if we aren't writing any more. */
|
||||
(bufev->enabled & EV_WRITE) &&
|
||||
/* Of if we have nothing more to write and we are
|
||||
* not flushing. */
|
||||
evbuffer_get_length(bufev->output) &&
|
||||
/* Or if we have filled the underlying output buffer. */
|
||||
!be_underlying_writebuf_full(bevf,state));
|
||||
|
||||
if (processed &&
|
||||
evbuffer_get_length(bufev->output) <= bufev->wm_write.low) {
|
||||
/* call the write callback.*/
|
||||
_bufferevent_run_writecb(bufev);
|
||||
|
||||
if (res == BEV_OK &&
|
||||
(bufev->enabled & EV_WRITE) &&
|
||||
evbuffer_get_length(bufev->output) &&
|
||||
!be_underlying_writebuf_full(bevf, state)) {
|
||||
again = 1;
|
||||
}
|
||||
}
|
||||
} while (again);
|
||||
|
||||
/* reenable the outbuf_cb */
|
||||
evbuffer_cb_set_flags(bufev->output,bevf->outbuf_cb,
|
||||
EVBUFFER_CB_ENABLED);
|
||||
|
||||
if (*processed_out)
|
||||
BEV_RESET_GENERIC_WRITE_TIMEOUT(bufev);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Called when the size of our outbuf changes. */
|
||||
static void
|
||||
bufferevent_filtered_outbuf_cb(struct evbuffer *buf,
|
||||
const struct evbuffer_cb_info *cbinfo, void *arg)
|
||||
{
|
||||
struct bufferevent_filtered *bevf = arg;
|
||||
struct bufferevent *bev = downcast(bevf);
|
||||
|
||||
if (cbinfo->n_added) {
|
||||
int processed_any = 0;
|
||||
/* Somebody added more data to the output buffer. Try to
|
||||
* process it, if we should. */
|
||||
_bufferevent_incref_and_lock(bev);
|
||||
be_filter_process_output(bevf, BEV_NORMAL, &processed_any);
|
||||
_bufferevent_decref_and_unlock(bev);
|
||||
}
|
||||
}
|
||||
|
||||
/* Called when the underlying socket has read. */
|
||||
static void
|
||||
be_filter_readcb(struct bufferevent *underlying, void *_me)
|
||||
{
|
||||
struct bufferevent_filtered *bevf = _me;
|
||||
enum bufferevent_filter_result res;
|
||||
enum bufferevent_flush_mode state;
|
||||
struct bufferevent *bufev = downcast(bevf);
|
||||
int processed_any = 0;
|
||||
|
||||
_bufferevent_incref_and_lock(bufev);
|
||||
|
||||
if (bevf->got_eof)
|
||||
state = BEV_FINISHED;
|
||||
else
|
||||
state = BEV_NORMAL;
|
||||
|
||||
/* XXXX use return value */
|
||||
res = be_filter_process_input(bevf, state, &processed_any);
|
||||
(void)res;
|
||||
|
||||
/* XXX This should be in process_input, not here. There are
|
||||
* other places that can call process-input, and they should
|
||||
* force readcb calls as needed. */
|
||||
if (processed_any &&
|
||||
evbuffer_get_length(bufev->input) >= bufev->wm_read.low)
|
||||
_bufferevent_run_readcb(bufev);
|
||||
|
||||
_bufferevent_decref_and_unlock(bufev);
|
||||
}
|
||||
|
||||
/* Called when the underlying socket has drained enough that we can write to
|
||||
it. */
|
||||
static void
|
||||
be_filter_writecb(struct bufferevent *underlying, void *_me)
|
||||
{
|
||||
struct bufferevent_filtered *bevf = _me;
|
||||
struct bufferevent *bev = downcast(bevf);
|
||||
int processed_any = 0;
|
||||
|
||||
_bufferevent_incref_and_lock(bev);
|
||||
be_filter_process_output(bevf, BEV_NORMAL, &processed_any);
|
||||
_bufferevent_decref_and_unlock(bev);
|
||||
}
|
||||
|
||||
/* Called when the underlying socket has given us an error */
|
||||
static void
|
||||
be_filter_eventcb(struct bufferevent *underlying, short what, void *_me)
|
||||
{
|
||||
struct bufferevent_filtered *bevf = _me;
|
||||
struct bufferevent *bev = downcast(bevf);
|
||||
|
||||
_bufferevent_incref_and_lock(bev);
|
||||
/* All we can really to is tell our own eventcb. */
|
||||
_bufferevent_run_eventcb(bev, what);
|
||||
_bufferevent_decref_and_unlock(bev);
|
||||
}
|
||||
|
||||
static int
|
||||
be_filter_flush(struct bufferevent *bufev,
|
||||
short iotype, enum bufferevent_flush_mode mode)
|
||||
{
|
||||
struct bufferevent_filtered *bevf = upcast(bufev);
|
||||
int processed_any = 0;
|
||||
EVUTIL_ASSERT(bevf);
|
||||
|
||||
_bufferevent_incref_and_lock(bufev);
|
||||
|
||||
if (iotype & EV_READ) {
|
||||
be_filter_process_input(bevf, mode, &processed_any);
|
||||
}
|
||||
if (iotype & EV_WRITE) {
|
||||
be_filter_process_output(bevf, mode, &processed_any);
|
||||
}
|
||||
/* XXX check the return value? */
|
||||
/* XXX does this want to recursively call lower-level flushes? */
|
||||
bufferevent_flush(bevf->underlying, iotype, mode);
|
||||
|
||||
_bufferevent_decref_and_unlock(bufev);
|
||||
|
||||
return processed_any;
|
||||
}
|
||||
|
||||
static int
|
||||
be_filter_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op,
|
||||
union bufferevent_ctrl_data *data)
|
||||
{
|
||||
struct bufferevent_filtered *bevf;
|
||||
switch (op) {
|
||||
case BEV_CTRL_GET_UNDERLYING:
|
||||
bevf = upcast(bev);
|
||||
data->ptr = bevf->underlying;
|
||||
return 0;
|
||||
case BEV_CTRL_GET_FD:
|
||||
case BEV_CTRL_SET_FD:
|
||||
case BEV_CTRL_CANCEL_ALL:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
1457
external/bsd/libevent/dist/bufferevent_openssl.c
vendored
Normal file
1457
external/bsd/libevent/dist/bufferevent_openssl.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
336
external/bsd/libevent/dist/bufferevent_pair.c
vendored
Normal file
336
external/bsd/libevent/dist/bufferevent_pair.c
vendored
Normal file
|
@ -0,0 +1,336 @@
|
|||
/* $NetBSD: bufferevent_pair.c,v 1.1.1.1 2013/04/11 16:43:26 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009-2012 Niels Provos, 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.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#include "event2/event-config.h"
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: bufferevent_pair.c,v 1.1.1.1 2013/04/11 16:43:26 christos Exp $");
|
||||
|
||||
#include "event2/util.h"
|
||||
#include "event2/buffer.h"
|
||||
#include "event2/bufferevent.h"
|
||||
#include "event2/bufferevent_struct.h"
|
||||
#include "event2/event.h"
|
||||
#include "defer-internal.h"
|
||||
#include "bufferevent-internal.h"
|
||||
#include "mm-internal.h"
|
||||
#include "util-internal.h"
|
||||
|
||||
struct bufferevent_pair {
|
||||
struct bufferevent_private bev;
|
||||
struct bufferevent_pair *partner;
|
||||
};
|
||||
|
||||
|
||||
/* Given a bufferevent that's really a bev part of a bufferevent_pair,
|
||||
* return that bufferevent_filtered. Returns NULL otherwise.*/
|
||||
static inline struct bufferevent_pair *
|
||||
upcast(struct bufferevent *bev)
|
||||
{
|
||||
struct bufferevent_pair *bev_p;
|
||||
if (bev->be_ops != &bufferevent_ops_pair)
|
||||
return NULL;
|
||||
bev_p = EVUTIL_UPCAST(bev, struct bufferevent_pair, bev.bev);
|
||||
EVUTIL_ASSERT(bev_p->bev.bev.be_ops == &bufferevent_ops_pair);
|
||||
return bev_p;
|
||||
}
|
||||
|
||||
#define downcast(bev_pair) (&(bev_pair)->bev.bev)
|
||||
|
||||
static inline void
|
||||
incref_and_lock(struct bufferevent *b)
|
||||
{
|
||||
struct bufferevent_pair *bevp;
|
||||
_bufferevent_incref_and_lock(b);
|
||||
bevp = upcast(b);
|
||||
if (bevp->partner)
|
||||
_bufferevent_incref_and_lock(downcast(bevp->partner));
|
||||
}
|
||||
|
||||
static inline void
|
||||
decref_and_unlock(struct bufferevent *b)
|
||||
{
|
||||
struct bufferevent_pair *bevp = upcast(b);
|
||||
if (bevp->partner)
|
||||
_bufferevent_decref_and_unlock(downcast(bevp->partner));
|
||||
_bufferevent_decref_and_unlock(b);
|
||||
}
|
||||
|
||||
/* XXX Handle close */
|
||||
|
||||
static void be_pair_outbuf_cb(struct evbuffer *,
|
||||
const struct evbuffer_cb_info *, void *);
|
||||
|
||||
static struct bufferevent_pair *
|
||||
bufferevent_pair_elt_new(struct event_base *base,
|
||||
int options)
|
||||
{
|
||||
struct bufferevent_pair *bufev;
|
||||
if (! (bufev = mm_calloc(1, sizeof(struct bufferevent_pair))))
|
||||
return NULL;
|
||||
if (bufferevent_init_common(&bufev->bev, base, &bufferevent_ops_pair,
|
||||
options)) {
|
||||
mm_free(bufev);
|
||||
return NULL;
|
||||
}
|
||||
if (!evbuffer_add_cb(bufev->bev.bev.output, be_pair_outbuf_cb, bufev)) {
|
||||
bufferevent_free(downcast(bufev));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_bufferevent_init_generic_timeout_cbs(&bufev->bev.bev);
|
||||
|
||||
return bufev;
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_pair_new(struct event_base *base, int options,
|
||||
struct bufferevent *pair[2])
|
||||
{
|
||||
struct bufferevent_pair *bufev1 = NULL, *bufev2 = NULL;
|
||||
int tmp_options;
|
||||
|
||||
options |= BEV_OPT_DEFER_CALLBACKS;
|
||||
tmp_options = options & ~BEV_OPT_THREADSAFE;
|
||||
|
||||
bufev1 = bufferevent_pair_elt_new(base, options);
|
||||
if (!bufev1)
|
||||
return -1;
|
||||
bufev2 = bufferevent_pair_elt_new(base, tmp_options);
|
||||
if (!bufev2) {
|
||||
bufferevent_free(downcast(bufev1));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (options & BEV_OPT_THREADSAFE) {
|
||||
/*XXXX check return */
|
||||
bufferevent_enable_locking(downcast(bufev2), bufev1->bev.lock);
|
||||
}
|
||||
|
||||
bufev1->partner = bufev2;
|
||||
bufev2->partner = bufev1;
|
||||
|
||||
evbuffer_freeze(downcast(bufev1)->input, 0);
|
||||
evbuffer_freeze(downcast(bufev1)->output, 1);
|
||||
evbuffer_freeze(downcast(bufev2)->input, 0);
|
||||
evbuffer_freeze(downcast(bufev2)->output, 1);
|
||||
|
||||
pair[0] = downcast(bufev1);
|
||||
pair[1] = downcast(bufev2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
be_pair_transfer(struct bufferevent *src, struct bufferevent *dst,
|
||||
int ignore_wm)
|
||||
{
|
||||
size_t src_size, dst_size;
|
||||
size_t n;
|
||||
|
||||
evbuffer_unfreeze(src->output, 1);
|
||||
evbuffer_unfreeze(dst->input, 0);
|
||||
|
||||
if (dst->wm_read.high) {
|
||||
dst_size = evbuffer_get_length(dst->input);
|
||||
if (dst_size < dst->wm_read.high) {
|
||||
n = dst->wm_read.high - dst_size;
|
||||
evbuffer_remove_buffer(src->output, dst->input, n);
|
||||
} else {
|
||||
if (!ignore_wm)
|
||||
goto done;
|
||||
n = evbuffer_get_length(src->output);
|
||||
evbuffer_add_buffer(dst->input, src->output);
|
||||
}
|
||||
} else {
|
||||
n = evbuffer_get_length(src->output);
|
||||
evbuffer_add_buffer(dst->input, src->output);
|
||||
}
|
||||
|
||||
if (n) {
|
||||
BEV_RESET_GENERIC_READ_TIMEOUT(dst);
|
||||
|
||||
if (evbuffer_get_length(dst->output))
|
||||
BEV_RESET_GENERIC_WRITE_TIMEOUT(dst);
|
||||
else
|
||||
BEV_DEL_GENERIC_WRITE_TIMEOUT(dst);
|
||||
}
|
||||
|
||||
src_size = evbuffer_get_length(src->output);
|
||||
dst_size = evbuffer_get_length(dst->input);
|
||||
|
||||
if (dst_size >= dst->wm_read.low) {
|
||||
_bufferevent_run_readcb(dst);
|
||||
}
|
||||
if (src_size <= src->wm_write.low) {
|
||||
_bufferevent_run_writecb(src);
|
||||
}
|
||||
done:
|
||||
evbuffer_freeze(src->output, 1);
|
||||
evbuffer_freeze(dst->input, 0);
|
||||
}
|
||||
|
||||
static inline int
|
||||
be_pair_wants_to_talk(struct bufferevent_pair *src,
|
||||
struct bufferevent_pair *dst)
|
||||
{
|
||||
return (downcast(src)->enabled & EV_WRITE) &&
|
||||
(downcast(dst)->enabled & EV_READ) &&
|
||||
!dst->bev.read_suspended &&
|
||||
evbuffer_get_length(downcast(src)->output);
|
||||
}
|
||||
|
||||
static void
|
||||
be_pair_outbuf_cb(struct evbuffer *outbuf,
|
||||
const struct evbuffer_cb_info *info, void *arg)
|
||||
{
|
||||
struct bufferevent_pair *bev_pair = arg;
|
||||
struct bufferevent_pair *partner = bev_pair->partner;
|
||||
|
||||
incref_and_lock(downcast(bev_pair));
|
||||
|
||||
if (info->n_added > info->n_deleted && partner) {
|
||||
/* We got more data. If the other side's reading, then
|
||||
hand it over. */
|
||||
if (be_pair_wants_to_talk(bev_pair, partner)) {
|
||||
be_pair_transfer(downcast(bev_pair), downcast(partner), 0);
|
||||
}
|
||||
}
|
||||
|
||||
decref_and_unlock(downcast(bev_pair));
|
||||
}
|
||||
|
||||
static int
|
||||
be_pair_enable(struct bufferevent *bufev, short events)
|
||||
{
|
||||
struct bufferevent_pair *bev_p = upcast(bufev);
|
||||
struct bufferevent_pair *partner = bev_p->partner;
|
||||
|
||||
incref_and_lock(bufev);
|
||||
|
||||
if (events & EV_READ) {
|
||||
BEV_RESET_GENERIC_READ_TIMEOUT(bufev);
|
||||
}
|
||||
if ((events & EV_WRITE) && evbuffer_get_length(bufev->output))
|
||||
BEV_RESET_GENERIC_WRITE_TIMEOUT(bufev);
|
||||
|
||||
/* We're starting to read! Does the other side have anything to write?*/
|
||||
if ((events & EV_READ) && partner &&
|
||||
be_pair_wants_to_talk(partner, bev_p)) {
|
||||
be_pair_transfer(downcast(partner), bufev, 0);
|
||||
}
|
||||
/* We're starting to write! Does the other side want to read? */
|
||||
if ((events & EV_WRITE) && partner &&
|
||||
be_pair_wants_to_talk(bev_p, partner)) {
|
||||
be_pair_transfer(bufev, downcast(partner), 0);
|
||||
}
|
||||
decref_and_unlock(bufev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
be_pair_disable(struct bufferevent *bev, short events)
|
||||
{
|
||||
if (events & EV_READ) {
|
||||
BEV_DEL_GENERIC_READ_TIMEOUT(bev);
|
||||
}
|
||||
if (events & EV_WRITE)
|
||||
BEV_DEL_GENERIC_WRITE_TIMEOUT(bev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
be_pair_destruct(struct bufferevent *bev)
|
||||
{
|
||||
struct bufferevent_pair *bev_p = upcast(bev);
|
||||
|
||||
if (bev_p->partner) {
|
||||
bev_p->partner->partner = NULL;
|
||||
bev_p->partner = NULL;
|
||||
}
|
||||
|
||||
_bufferevent_del_generic_timeout_cbs(bev);
|
||||
}
|
||||
|
||||
static int
|
||||
be_pair_flush(struct bufferevent *bev, short iotype,
|
||||
enum bufferevent_flush_mode mode)
|
||||
{
|
||||
struct bufferevent_pair *bev_p = upcast(bev);
|
||||
struct bufferevent *partner;
|
||||
incref_and_lock(bev);
|
||||
if (!bev_p->partner)
|
||||
return -1;
|
||||
|
||||
partner = downcast(bev_p->partner);
|
||||
|
||||
if (mode == BEV_NORMAL)
|
||||
return 0;
|
||||
|
||||
if ((iotype & EV_READ) != 0)
|
||||
be_pair_transfer(partner, bev, 1);
|
||||
|
||||
if ((iotype & EV_WRITE) != 0)
|
||||
be_pair_transfer(bev, partner, 1);
|
||||
|
||||
if (mode == BEV_FINISHED) {
|
||||
_bufferevent_run_eventcb(partner, iotype|BEV_EVENT_EOF);
|
||||
}
|
||||
decref_and_unlock(bev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct bufferevent *
|
||||
bufferevent_pair_get_partner(struct bufferevent *bev)
|
||||
{
|
||||
struct bufferevent_pair *bev_p;
|
||||
struct bufferevent *partner;
|
||||
bev_p = upcast(bev);
|
||||
if (! bev_p)
|
||||
return NULL;
|
||||
|
||||
incref_and_lock(bev);
|
||||
partner = downcast(bev_p->partner);
|
||||
decref_and_unlock(bev);
|
||||
return partner;
|
||||
}
|
||||
|
||||
const struct bufferevent_ops bufferevent_ops_pair = {
|
||||
"pair_elt",
|
||||
evutil_offsetof(struct bufferevent_pair, bev.bev),
|
||||
be_pair_enable,
|
||||
be_pair_disable,
|
||||
be_pair_destruct,
|
||||
_bufferevent_generic_adj_timeouts,
|
||||
be_pair_flush,
|
||||
NULL, /* ctrl */
|
||||
};
|
1012
external/bsd/libevent/dist/bufferevent_ratelim.c
vendored
Normal file
1012
external/bsd/libevent/dist/bufferevent_ratelim.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
702
external/bsd/libevent/dist/bufferevent_sock.c
vendored
Normal file
702
external/bsd/libevent/dist/bufferevent_sock.c
vendored
Normal file
|
@ -0,0 +1,702 @@
|
|||
/* $NetBSD: bufferevent_sock.c,v 1.1.1.1 2013/04/11 16:43:24 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
|
||||
* Copyright (c) 2002-2006 Niels Provos <provos@citi.umich.edu>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "event2/event-config.h"
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: bufferevent_sock.c,v 1.1.1.1 2013/04/11 16:43:24 christos Exp $");
|
||||
|
||||
#ifdef _EVENT_HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef _EVENT_HAVE_STDARG_H
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
#ifdef _EVENT_HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
#ifdef _EVENT_HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef _EVENT_HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#ifdef _EVENT_HAVE_NETINET_IN6_H
|
||||
#include <netinet/in6.h>
|
||||
#endif
|
||||
|
||||
#include "event2/util.h"
|
||||
#include "event2/bufferevent.h"
|
||||
#include "event2/buffer.h"
|
||||
#include "event2/bufferevent_struct.h"
|
||||
#include "event2/bufferevent_compat.h"
|
||||
#include "event2/event.h"
|
||||
#include "log-internal.h"
|
||||
#include "mm-internal.h"
|
||||
#include "bufferevent-internal.h"
|
||||
#include "util-internal.h"
|
||||
#ifdef WIN32
|
||||
#include "iocp-internal.h"
|
||||
#endif
|
||||
|
||||
/* prototypes */
|
||||
static int be_socket_enable(struct bufferevent *, short);
|
||||
static int be_socket_disable(struct bufferevent *, short);
|
||||
static void be_socket_destruct(struct bufferevent *);
|
||||
static int be_socket_adj_timeouts(struct bufferevent *);
|
||||
static int be_socket_flush(struct bufferevent *, short, enum bufferevent_flush_mode);
|
||||
static int be_socket_ctrl(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *);
|
||||
|
||||
static void be_socket_setfd(struct bufferevent *, evutil_socket_t);
|
||||
|
||||
const struct bufferevent_ops bufferevent_ops_socket = {
|
||||
"socket",
|
||||
evutil_offsetof(struct bufferevent_private, bev),
|
||||
be_socket_enable,
|
||||
be_socket_disable,
|
||||
be_socket_destruct,
|
||||
be_socket_adj_timeouts,
|
||||
be_socket_flush,
|
||||
be_socket_ctrl,
|
||||
};
|
||||
|
||||
#define be_socket_add(ev, t) \
|
||||
_bufferevent_add_event((ev), (t))
|
||||
|
||||
static void
|
||||
bufferevent_socket_outbuf_cb(struct evbuffer *buf,
|
||||
const struct evbuffer_cb_info *cbinfo,
|
||||
void *arg)
|
||||
{
|
||||
struct bufferevent *bufev = arg;
|
||||
struct bufferevent_private *bufev_p =
|
||||
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
|
||||
|
||||
if (cbinfo->n_added &&
|
||||
(bufev->enabled & EV_WRITE) &&
|
||||
!event_pending(&bufev->ev_write, EV_WRITE, NULL) &&
|
||||
!bufev_p->write_suspended) {
|
||||
/* Somebody added data to the buffer, and we would like to
|
||||
* write, and we were not writing. So, start writing. */
|
||||
if (be_socket_add(&bufev->ev_write, &bufev->timeout_write) == -1) {
|
||||
/* Should we log this? */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bufferevent_readcb(evutil_socket_t fd, short event, void *arg)
|
||||
{
|
||||
struct bufferevent *bufev = arg;
|
||||
struct bufferevent_private *bufev_p =
|
||||
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
|
||||
struct evbuffer *input;
|
||||
int res = 0;
|
||||
short what = BEV_EVENT_READING;
|
||||
ev_ssize_t howmuch = -1, readmax=-1;
|
||||
|
||||
_bufferevent_incref_and_lock(bufev);
|
||||
|
||||
if (event == EV_TIMEOUT) {
|
||||
/* Note that we only check for event==EV_TIMEOUT. If
|
||||
* event==EV_TIMEOUT|EV_READ, we can safely ignore the
|
||||
* timeout, since a read has occurred */
|
||||
what |= BEV_EVENT_TIMEOUT;
|
||||
goto error;
|
||||
}
|
||||
|
||||
input = bufev->input;
|
||||
|
||||
/*
|
||||
* If we have a high watermark configured then we don't want to
|
||||
* read more data than would make us reach the watermark.
|
||||
*/
|
||||
if (bufev->wm_read.high != 0) {
|
||||
howmuch = bufev->wm_read.high - evbuffer_get_length(input);
|
||||
/* we somehow lowered the watermark, stop reading */
|
||||
if (howmuch <= 0) {
|
||||
bufferevent_wm_suspend_read(bufev);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
readmax = _bufferevent_get_read_max(bufev_p);
|
||||
if (howmuch < 0 || howmuch > readmax) /* The use of -1 for "unlimited"
|
||||
* uglifies this code. XXXX */
|
||||
howmuch = readmax;
|
||||
if (bufev_p->read_suspended)
|
||||
goto done;
|
||||
|
||||
evbuffer_unfreeze(input, 0);
|
||||
res = evbuffer_read(input, fd, (int)howmuch); /* XXXX evbuffer_read would do better to take and return ev_ssize_t */
|
||||
evbuffer_freeze(input, 0);
|
||||
|
||||
if (res == -1) {
|
||||
int err = evutil_socket_geterror(fd);
|
||||
if (EVUTIL_ERR_RW_RETRIABLE(err))
|
||||
goto reschedule;
|
||||
/* error case */
|
||||
what |= BEV_EVENT_ERROR;
|
||||
} else if (res == 0) {
|
||||
/* eof case */
|
||||
what |= BEV_EVENT_EOF;
|
||||
}
|
||||
|
||||
if (res <= 0)
|
||||
goto error;
|
||||
|
||||
_bufferevent_decrement_read_buckets(bufev_p, res);
|
||||
|
||||
/* Invoke the user callback - must always be called last */
|
||||
if (evbuffer_get_length(input) >= bufev->wm_read.low)
|
||||
_bufferevent_run_readcb(bufev);
|
||||
|
||||
goto done;
|
||||
|
||||
reschedule:
|
||||
goto done;
|
||||
|
||||
error:
|
||||
bufferevent_disable(bufev, EV_READ);
|
||||
_bufferevent_run_eventcb(bufev, what);
|
||||
|
||||
done:
|
||||
_bufferevent_decref_and_unlock(bufev);
|
||||
}
|
||||
|
||||
static void
|
||||
bufferevent_writecb(evutil_socket_t fd, short event, void *arg)
|
||||
{
|
||||
struct bufferevent *bufev = arg;
|
||||
struct bufferevent_private *bufev_p =
|
||||
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
|
||||
int res = 0;
|
||||
short what = BEV_EVENT_WRITING;
|
||||
int connected = 0;
|
||||
ev_ssize_t atmost = -1;
|
||||
|
||||
_bufferevent_incref_and_lock(bufev);
|
||||
|
||||
if (event == EV_TIMEOUT) {
|
||||
/* Note that we only check for event==EV_TIMEOUT. If
|
||||
* event==EV_TIMEOUT|EV_WRITE, we can safely ignore the
|
||||
* timeout, since a read has occurred */
|
||||
what |= BEV_EVENT_TIMEOUT;
|
||||
goto error;
|
||||
}
|
||||
if (bufev_p->connecting) {
|
||||
int c = evutil_socket_finished_connecting(fd);
|
||||
/* we need to fake the error if the connection was refused
|
||||
* immediately - usually connection to localhost on BSD */
|
||||
if (bufev_p->connection_refused) {
|
||||
bufev_p->connection_refused = 0;
|
||||
c = -1;
|
||||
}
|
||||
|
||||
if (c == 0)
|
||||
goto done;
|
||||
|
||||
bufev_p->connecting = 0;
|
||||
if (c < 0) {
|
||||
event_del(&bufev->ev_write);
|
||||
event_del(&bufev->ev_read);
|
||||
_bufferevent_run_eventcb(bufev, BEV_EVENT_ERROR);
|
||||
goto done;
|
||||
} else {
|
||||
connected = 1;
|
||||
#ifdef WIN32
|
||||
if (BEV_IS_ASYNC(bufev)) {
|
||||
event_del(&bufev->ev_write);
|
||||
bufferevent_async_set_connected(bufev);
|
||||
_bufferevent_run_eventcb(bufev,
|
||||
BEV_EVENT_CONNECTED);
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
_bufferevent_run_eventcb(bufev,
|
||||
BEV_EVENT_CONNECTED);
|
||||
if (!(bufev->enabled & EV_WRITE) ||
|
||||
bufev_p->write_suspended) {
|
||||
event_del(&bufev->ev_write);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
atmost = _bufferevent_get_write_max(bufev_p);
|
||||
|
||||
if (bufev_p->write_suspended)
|
||||
goto done;
|
||||
|
||||
if (evbuffer_get_length(bufev->output)) {
|
||||
evbuffer_unfreeze(bufev->output, 1);
|
||||
res = evbuffer_write_atmost(bufev->output, fd, atmost);
|
||||
evbuffer_freeze(bufev->output, 1);
|
||||
if (res == -1) {
|
||||
int err = evutil_socket_geterror(fd);
|
||||
if (EVUTIL_ERR_RW_RETRIABLE(err))
|
||||
goto reschedule;
|
||||
what |= BEV_EVENT_ERROR;
|
||||
} else if (res == 0) {
|
||||
/* eof case
|
||||
XXXX Actually, a 0 on write doesn't indicate
|
||||
an EOF. An ECONNRESET might be more typical.
|
||||
*/
|
||||
what |= BEV_EVENT_EOF;
|
||||
}
|
||||
if (res <= 0)
|
||||
goto error;
|
||||
|
||||
_bufferevent_decrement_write_buckets(bufev_p, res);
|
||||
}
|
||||
|
||||
if (evbuffer_get_length(bufev->output) == 0) {
|
||||
event_del(&bufev->ev_write);
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoke the user callback if our buffer is drained or below the
|
||||
* low watermark.
|
||||
*/
|
||||
if ((res || !connected) &&
|
||||
evbuffer_get_length(bufev->output) <= bufev->wm_write.low) {
|
||||
_bufferevent_run_writecb(bufev);
|
||||
}
|
||||
|
||||
goto done;
|
||||
|
||||
reschedule:
|
||||
if (evbuffer_get_length(bufev->output) == 0) {
|
||||
event_del(&bufev->ev_write);
|
||||
}
|
||||
goto done;
|
||||
|
||||
error:
|
||||
bufferevent_disable(bufev, EV_WRITE);
|
||||
_bufferevent_run_eventcb(bufev, what);
|
||||
|
||||
done:
|
||||
_bufferevent_decref_and_unlock(bufev);
|
||||
}
|
||||
|
||||
struct bufferevent *
|
||||
bufferevent_socket_new(struct event_base *base, evutil_socket_t fd,
|
||||
int options)
|
||||
{
|
||||
struct bufferevent_private *bufev_p;
|
||||
struct bufferevent *bufev;
|
||||
|
||||
#ifdef WIN32
|
||||
if (base && event_base_get_iocp(base))
|
||||
return bufferevent_async_new(base, fd, options);
|
||||
#endif
|
||||
|
||||
if ((bufev_p = mm_calloc(1, sizeof(struct bufferevent_private)))== NULL)
|
||||
return NULL;
|
||||
|
||||
if (bufferevent_init_common(bufev_p, base, &bufferevent_ops_socket,
|
||||
options) < 0) {
|
||||
mm_free(bufev_p);
|
||||
return NULL;
|
||||
}
|
||||
bufev = &bufev_p->bev;
|
||||
evbuffer_set_flags(bufev->output, EVBUFFER_FLAG_DRAINS_TO_FD);
|
||||
|
||||
event_assign(&bufev->ev_read, bufev->ev_base, fd,
|
||||
EV_READ|EV_PERSIST, bufferevent_readcb, bufev);
|
||||
event_assign(&bufev->ev_write, bufev->ev_base, fd,
|
||||
EV_WRITE|EV_PERSIST, bufferevent_writecb, bufev);
|
||||
|
||||
evbuffer_add_cb(bufev->output, bufferevent_socket_outbuf_cb, bufev);
|
||||
|
||||
evbuffer_freeze(bufev->input, 0);
|
||||
evbuffer_freeze(bufev->output, 1);
|
||||
|
||||
return bufev;
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_socket_connect(struct bufferevent *bev,
|
||||
struct sockaddr *sa, int socklen)
|
||||
{
|
||||
struct bufferevent_private *bufev_p =
|
||||
EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
|
||||
|
||||
evutil_socket_t fd;
|
||||
int r = 0;
|
||||
int result=-1;
|
||||
int ownfd = 0;
|
||||
|
||||
_bufferevent_incref_and_lock(bev);
|
||||
|
||||
if (!bufev_p)
|
||||
goto done;
|
||||
|
||||
fd = bufferevent_getfd(bev);
|
||||
if (fd < 0) {
|
||||
if (!sa)
|
||||
goto done;
|
||||
fd = socket(sa->sa_family, SOCK_STREAM, 0);
|
||||
if (fd < 0)
|
||||
goto done;
|
||||
if (evutil_make_socket_nonblocking(fd)<0)
|
||||
goto done;
|
||||
ownfd = 1;
|
||||
}
|
||||
if (sa) {
|
||||
#ifdef WIN32
|
||||
if (bufferevent_async_can_connect(bev)) {
|
||||
bufferevent_setfd(bev, fd);
|
||||
r = bufferevent_async_connect(bev, fd, sa, socklen);
|
||||
if (r < 0)
|
||||
goto freesock;
|
||||
bufev_p->connecting = 1;
|
||||
result = 0;
|
||||
goto done;
|
||||
} else
|
||||
#endif
|
||||
r = evutil_socket_connect(&fd, sa, socklen);
|
||||
if (r < 0)
|
||||
goto freesock;
|
||||
}
|
||||
#ifdef WIN32
|
||||
/* ConnectEx() isn't always around, even when IOCP is enabled.
|
||||
* Here, we borrow the socket object's write handler to fall back
|
||||
* on a non-blocking connect() when ConnectEx() is unavailable. */
|
||||
if (BEV_IS_ASYNC(bev)) {
|
||||
event_assign(&bev->ev_write, bev->ev_base, fd,
|
||||
EV_WRITE|EV_PERSIST, bufferevent_writecb, bev);
|
||||
}
|
||||
#endif
|
||||
bufferevent_setfd(bev, fd);
|
||||
if (r == 0) {
|
||||
if (! be_socket_enable(bev, EV_WRITE)) {
|
||||
bufev_p->connecting = 1;
|
||||
result = 0;
|
||||
goto done;
|
||||
}
|
||||
} else if (r == 1) {
|
||||
/* The connect succeeded already. How very BSD of it. */
|
||||
result = 0;
|
||||
bufev_p->connecting = 1;
|
||||
event_active(&bev->ev_write, EV_WRITE, 1);
|
||||
} else {
|
||||
/* The connect failed already. How very BSD of it. */
|
||||
bufev_p->connection_refused = 1;
|
||||
bufev_p->connecting = 1;
|
||||
result = 0;
|
||||
event_active(&bev->ev_write, EV_WRITE, 1);
|
||||
}
|
||||
|
||||
goto done;
|
||||
|
||||
freesock:
|
||||
_bufferevent_run_eventcb(bev, BEV_EVENT_ERROR);
|
||||
if (ownfd)
|
||||
evutil_closesocket(fd);
|
||||
/* do something about the error? */
|
||||
done:
|
||||
_bufferevent_decref_and_unlock(bev);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
bufferevent_connect_getaddrinfo_cb(int result, struct evutil_addrinfo *ai,
|
||||
void *arg)
|
||||
{
|
||||
struct bufferevent *bev = arg;
|
||||
struct bufferevent_private *bev_p =
|
||||
EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
|
||||
int r;
|
||||
BEV_LOCK(bev);
|
||||
|
||||
bufferevent_unsuspend_write(bev, BEV_SUSPEND_LOOKUP);
|
||||
bufferevent_unsuspend_read(bev, BEV_SUSPEND_LOOKUP);
|
||||
|
||||
if (result != 0) {
|
||||
bev_p->dns_error = result;
|
||||
_bufferevent_run_eventcb(bev, BEV_EVENT_ERROR);
|
||||
_bufferevent_decref_and_unlock(bev);
|
||||
if (ai)
|
||||
evutil_freeaddrinfo(ai);
|
||||
return;
|
||||
}
|
||||
|
||||
/* XXX use the other addrinfos? */
|
||||
/* XXX use this return value */
|
||||
r = bufferevent_socket_connect(bev, ai->ai_addr, (int)ai->ai_addrlen);
|
||||
(void)r;
|
||||
_bufferevent_decref_and_unlock(bev);
|
||||
evutil_freeaddrinfo(ai);
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_socket_connect_hostname(struct bufferevent *bev,
|
||||
struct evdns_base *evdns_base, int family, const char *hostname, int port)
|
||||
{
|
||||
char portbuf[10];
|
||||
struct evutil_addrinfo hint;
|
||||
int err;
|
||||
struct bufferevent_private *bev_p =
|
||||
EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
|
||||
|
||||
if (family != AF_INET && family != AF_INET6 && family != AF_UNSPEC)
|
||||
return -1;
|
||||
if (port < 1 || port > 65535)
|
||||
return -1;
|
||||
|
||||
BEV_LOCK(bev);
|
||||
bev_p->dns_error = 0;
|
||||
BEV_UNLOCK(bev);
|
||||
|
||||
evutil_snprintf(portbuf, sizeof(portbuf), "%d", port);
|
||||
|
||||
memset(&hint, 0, sizeof(hint));
|
||||
hint.ai_family = family;
|
||||
hint.ai_protocol = IPPROTO_TCP;
|
||||
hint.ai_socktype = SOCK_STREAM;
|
||||
|
||||
bufferevent_suspend_write(bev, BEV_SUSPEND_LOOKUP);
|
||||
bufferevent_suspend_read(bev, BEV_SUSPEND_LOOKUP);
|
||||
|
||||
bufferevent_incref(bev);
|
||||
err = evutil_getaddrinfo_async(evdns_base, hostname, portbuf,
|
||||
&hint, bufferevent_connect_getaddrinfo_cb, bev);
|
||||
|
||||
if (err == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
bufferevent_unsuspend_write(bev, BEV_SUSPEND_LOOKUP);
|
||||
bufferevent_unsuspend_read(bev, BEV_SUSPEND_LOOKUP);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_socket_get_dns_error(struct bufferevent *bev)
|
||||
{
|
||||
int rv;
|
||||
struct bufferevent_private *bev_p =
|
||||
EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
|
||||
|
||||
BEV_LOCK(bev);
|
||||
rv = bev_p->dns_error;
|
||||
BEV_LOCK(bev);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new buffered event object.
|
||||
*
|
||||
* The read callback is invoked whenever we read new data.
|
||||
* The write callback is invoked whenever the output buffer is drained.
|
||||
* The error callback is invoked on a write/read error or on EOF.
|
||||
*
|
||||
* Both read and write callbacks maybe NULL. The error callback is not
|
||||
* allowed to be NULL and have to be provided always.
|
||||
*/
|
||||
|
||||
struct bufferevent *
|
||||
bufferevent_new(evutil_socket_t fd,
|
||||
bufferevent_data_cb readcb, bufferevent_data_cb writecb,
|
||||
bufferevent_event_cb eventcb, void *cbarg)
|
||||
{
|
||||
struct bufferevent *bufev;
|
||||
|
||||
if (!(bufev = bufferevent_socket_new(NULL, fd, 0)))
|
||||
return NULL;
|
||||
|
||||
bufferevent_setcb(bufev, readcb, writecb, eventcb, cbarg);
|
||||
|
||||
return bufev;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
be_socket_enable(struct bufferevent *bufev, short event)
|
||||
{
|
||||
if (event & EV_READ) {
|
||||
if (be_socket_add(&bufev->ev_read,&bufev->timeout_read) == -1)
|
||||
return -1;
|
||||
}
|
||||
if (event & EV_WRITE) {
|
||||
if (be_socket_add(&bufev->ev_write,&bufev->timeout_write) == -1)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
be_socket_disable(struct bufferevent *bufev, short event)
|
||||
{
|
||||
struct bufferevent_private *bufev_p =
|
||||
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
|
||||
if (event & EV_READ) {
|
||||
if (event_del(&bufev->ev_read) == -1)
|
||||
return -1;
|
||||
}
|
||||
/* Don't actually disable the write if we are trying to connect. */
|
||||
if ((event & EV_WRITE) && ! bufev_p->connecting) {
|
||||
if (event_del(&bufev->ev_write) == -1)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
be_socket_destruct(struct bufferevent *bufev)
|
||||
{
|
||||
struct bufferevent_private *bufev_p =
|
||||
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
|
||||
evutil_socket_t fd;
|
||||
EVUTIL_ASSERT(bufev->be_ops == &bufferevent_ops_socket);
|
||||
|
||||
fd = event_get_fd(&bufev->ev_read);
|
||||
|
||||
event_del(&bufev->ev_read);
|
||||
event_del(&bufev->ev_write);
|
||||
|
||||
if ((bufev_p->options & BEV_OPT_CLOSE_ON_FREE) && fd >= 0)
|
||||
EVUTIL_CLOSESOCKET(fd);
|
||||
}
|
||||
|
||||
static int
|
||||
be_socket_adj_timeouts(struct bufferevent *bufev)
|
||||
{
|
||||
int r = 0;
|
||||
if (event_pending(&bufev->ev_read, EV_READ, NULL))
|
||||
if (be_socket_add(&bufev->ev_read, &bufev->timeout_read) < 0)
|
||||
r = -1;
|
||||
if (event_pending(&bufev->ev_write, EV_WRITE, NULL)) {
|
||||
if (be_socket_add(&bufev->ev_write, &bufev->timeout_write) < 0)
|
||||
r = -1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
be_socket_flush(struct bufferevent *bev, short iotype,
|
||||
enum bufferevent_flush_mode mode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
be_socket_setfd(struct bufferevent *bufev, evutil_socket_t fd)
|
||||
{
|
||||
BEV_LOCK(bufev);
|
||||
EVUTIL_ASSERT(bufev->be_ops == &bufferevent_ops_socket);
|
||||
|
||||
event_del(&bufev->ev_read);
|
||||
event_del(&bufev->ev_write);
|
||||
|
||||
event_assign(&bufev->ev_read, bufev->ev_base, fd,
|
||||
EV_READ|EV_PERSIST, bufferevent_readcb, bufev);
|
||||
event_assign(&bufev->ev_write, bufev->ev_base, fd,
|
||||
EV_WRITE|EV_PERSIST, bufferevent_writecb, bufev);
|
||||
|
||||
if (fd >= 0)
|
||||
bufferevent_enable(bufev, bufev->enabled);
|
||||
|
||||
BEV_UNLOCK(bufev);
|
||||
}
|
||||
|
||||
/* XXXX Should non-socket bufferevents support this? */
|
||||
int
|
||||
bufferevent_priority_set(struct bufferevent *bufev, int priority)
|
||||
{
|
||||
int r = -1;
|
||||
|
||||
BEV_LOCK(bufev);
|
||||
if (bufev->be_ops != &bufferevent_ops_socket)
|
||||
goto done;
|
||||
|
||||
if (event_priority_set(&bufev->ev_read, priority) == -1)
|
||||
goto done;
|
||||
if (event_priority_set(&bufev->ev_write, priority) == -1)
|
||||
goto done;
|
||||
|
||||
r = 0;
|
||||
done:
|
||||
BEV_UNLOCK(bufev);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* XXXX Should non-socket bufferevents support this? */
|
||||
int
|
||||
bufferevent_base_set(struct event_base *base, struct bufferevent *bufev)
|
||||
{
|
||||
int res = -1;
|
||||
|
||||
BEV_LOCK(bufev);
|
||||
if (bufev->be_ops != &bufferevent_ops_socket)
|
||||
goto done;
|
||||
|
||||
bufev->ev_base = base;
|
||||
|
||||
res = event_base_set(base, &bufev->ev_read);
|
||||
if (res == -1)
|
||||
goto done;
|
||||
|
||||
res = event_base_set(base, &bufev->ev_write);
|
||||
done:
|
||||
BEV_UNLOCK(bufev);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
be_socket_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op,
|
||||
union bufferevent_ctrl_data *data)
|
||||
{
|
||||
switch (op) {
|
||||
case BEV_CTRL_SET_FD:
|
||||
be_socket_setfd(bev, data->fd);
|
||||
return 0;
|
||||
case BEV_CTRL_GET_FD:
|
||||
data->fd = event_get_fd(&bev->ev_read);
|
||||
return 0;
|
||||
case BEV_CTRL_GET_UNDERLYING:
|
||||
case BEV_CTRL_CANCEL_ALL:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
102
external/bsd/libevent/dist/changelist-internal.h
vendored
Normal file
102
external/bsd/libevent/dist/changelist-internal.h
vendored
Normal file
|
@ -0,0 +1,102 @@
|
|||
/* $NetBSD: changelist-internal.h,v 1.1.1.1 2013/04/11 16:43:29 christos Exp $ */
|
||||
/*
|
||||
* 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 _CHANGELIST_H_
|
||||
#define _CHANGELIST_H_
|
||||
|
||||
/*
|
||||
A "changelist" is a list of all the fd status changes that should be made
|
||||
between calls to the backend's dispatch function. There are a few reasons
|
||||
that a backend would want to queue changes like this rather than processing
|
||||
them immediately.
|
||||
|
||||
1) Sometimes applications will add and delete the same event more than
|
||||
once between calls to dispatch. Processing these changes immediately
|
||||
is needless, and potentially expensive (especially if we're on a system
|
||||
that makes one syscall per changed event).
|
||||
|
||||
2) Sometimes we can coalesce multiple changes on the same fd into a single
|
||||
syscall if we know about them in advance. For example, epoll can do an
|
||||
add and a delete at the same time, but only if we have found out about
|
||||
both of them before we tell epoll.
|
||||
|
||||
3) Sometimes adding an event that we immediately delete can cause
|
||||
unintended consequences: in kqueue, this makes pending events get
|
||||
reported spuriously.
|
||||
*/
|
||||
|
||||
#include "event2/util.h"
|
||||
|
||||
/** Represents a */
|
||||
struct event_change {
|
||||
/** The fd or signal whose events are to be changed */
|
||||
evutil_socket_t fd;
|
||||
/* The events that were enabled on the fd before any of these changes
|
||||
were made. May include EV_READ or EV_WRITE. */
|
||||
short old_events;
|
||||
|
||||
/* The changes that we want to make in reading and writing on this fd.
|
||||
* If this is a signal, then read_change has EV_CHANGE_SIGNAL set,
|
||||
* and write_change is unused. */
|
||||
ev_uint8_t read_change;
|
||||
ev_uint8_t write_change;
|
||||
};
|
||||
|
||||
/* Flags for read_change and write_change. */
|
||||
|
||||
/* If set, add the event. */
|
||||
#define EV_CHANGE_ADD 0x01
|
||||
/* If set, delete the event. Exclusive with EV_CHANGE_ADD */
|
||||
#define EV_CHANGE_DEL 0x02
|
||||
/* If set, this event refers a signal, not an fd. */
|
||||
#define EV_CHANGE_SIGNAL EV_SIGNAL
|
||||
/* Set for persistent events. Currently not used. */
|
||||
#define EV_CHANGE_PERSIST EV_PERSIST
|
||||
/* Set for adding edge-triggered events. */
|
||||
#define EV_CHANGE_ET EV_ET
|
||||
|
||||
/* The value of fdinfo_size that a backend should use if it is letting
|
||||
* changelist handle its add and delete functions. */
|
||||
#define EVENT_CHANGELIST_FDINFO_SIZE sizeof(int)
|
||||
|
||||
/** Set up the data fields in a changelist. */
|
||||
void event_changelist_init(struct event_changelist *changelist);
|
||||
/** Remove every change in the changelist, and make corresponding changes
|
||||
* in the event maps in the base. This function is generally used right
|
||||
* after making all the changes in the changelist. */
|
||||
void event_changelist_remove_all(struct event_changelist *changelist,
|
||||
struct event_base *base);
|
||||
/** Free all memory held in a changelist. */
|
||||
void event_changelist_freemem(struct event_changelist *changelist);
|
||||
|
||||
/** Implementation of eventop_add that queues the event in a changelist. */
|
||||
int event_changelist_add(struct event_base *base, evutil_socket_t fd, short old, short events,
|
||||
void *p);
|
||||
/** Implementation of eventop_del that queues the event in a changelist. */
|
||||
int event_changelist_del(struct event_base *base, evutil_socket_t fd, short old, short events,
|
||||
void *p);
|
||||
|
||||
#endif
|
343
external/bsd/libevent/dist/compile
vendored
Executable file
343
external/bsd/libevent/dist/compile
vendored
Executable file
|
@ -0,0 +1,343 @@
|
|||
#! /bin/sh
|
||||
# Wrapper for compilers which do not understand '-c -o'.
|
||||
|
||||
scriptversion=2012-03-05.13; # UTC
|
||||
|
||||
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2009, 2010, 2012 Free
|
||||
# Software Foundation, Inc.
|
||||
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
nl='
|
||||
'
|
||||
|
||||
# We need space, tab and new line, in precisely that order. Quoting is
|
||||
# there to prevent tools from complaining about whitespace usage.
|
||||
IFS=" "" $nl"
|
||||
|
||||
file_conv=
|
||||
|
||||
# func_file_conv build_file lazy
|
||||
# Convert a $build file to $host form and store it in $file
|
||||
# Currently only supports Windows hosts. If the determined conversion
|
||||
# type is listed in (the comma separated) LAZY, no conversion will
|
||||
# take place.
|
||||
func_file_conv ()
|
||||
{
|
||||
file=$1
|
||||
case $file in
|
||||
/ | /[!/]*) # absolute file, and not a UNC file
|
||||
if test -z "$file_conv"; then
|
||||
# lazily determine how to convert abs files
|
||||
case `uname -s` in
|
||||
MINGW*)
|
||||
file_conv=mingw
|
||||
;;
|
||||
CYGWIN*)
|
||||
file_conv=cygwin
|
||||
;;
|
||||
*)
|
||||
file_conv=wine
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
case $file_conv/,$2, in
|
||||
*,$file_conv,*)
|
||||
;;
|
||||
mingw/*)
|
||||
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
|
||||
;;
|
||||
cygwin/*)
|
||||
file=`cygpath -m "$file" || echo "$file"`
|
||||
;;
|
||||
wine/*)
|
||||
file=`winepath -w "$file" || echo "$file"`
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# func_cl_dashL linkdir
|
||||
# Make cl look for libraries in LINKDIR
|
||||
func_cl_dashL ()
|
||||
{
|
||||
func_file_conv "$1"
|
||||
if test -z "$lib_path"; then
|
||||
lib_path=$file
|
||||
else
|
||||
lib_path="$lib_path;$file"
|
||||
fi
|
||||
linker_opts="$linker_opts -LIBPATH:$file"
|
||||
}
|
||||
|
||||
# func_cl_dashl library
|
||||
# Do a library search-path lookup for cl
|
||||
func_cl_dashl ()
|
||||
{
|
||||
lib=$1
|
||||
found=no
|
||||
save_IFS=$IFS
|
||||
IFS=';'
|
||||
for dir in $lib_path $LIB
|
||||
do
|
||||
IFS=$save_IFS
|
||||
if $shared && test -f "$dir/$lib.dll.lib"; then
|
||||
found=yes
|
||||
lib=$dir/$lib.dll.lib
|
||||
break
|
||||
fi
|
||||
if test -f "$dir/$lib.lib"; then
|
||||
found=yes
|
||||
lib=$dir/$lib.lib
|
||||
break
|
||||
fi
|
||||
done
|
||||
IFS=$save_IFS
|
||||
|
||||
if test "$found" != yes; then
|
||||
lib=$lib.lib
|
||||
fi
|
||||
}
|
||||
|
||||
# func_cl_wrapper cl arg...
|
||||
# Adjust compile command to suit cl
|
||||
func_cl_wrapper ()
|
||||
{
|
||||
# Assume a capable shell
|
||||
lib_path=
|
||||
shared=:
|
||||
linker_opts=
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.[oO][bB][jJ])
|
||||
func_file_conv "$2"
|
||||
set x "$@" -Fo"$file"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
func_file_conv "$2"
|
||||
set x "$@" -Fe"$file"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
-I)
|
||||
eat=1
|
||||
func_file_conv "$2" mingw
|
||||
set x "$@" -I"$file"
|
||||
shift
|
||||
;;
|
||||
-I*)
|
||||
func_file_conv "${1#-I}" mingw
|
||||
set x "$@" -I"$file"
|
||||
shift
|
||||
;;
|
||||
-l)
|
||||
eat=1
|
||||
func_cl_dashl "$2"
|
||||
set x "$@" "$lib"
|
||||
shift
|
||||
;;
|
||||
-l*)
|
||||
func_cl_dashl "${1#-l}"
|
||||
set x "$@" "$lib"
|
||||
shift
|
||||
;;
|
||||
-L)
|
||||
eat=1
|
||||
func_cl_dashL "$2"
|
||||
;;
|
||||
-L*)
|
||||
func_cl_dashL "${1#-L}"
|
||||
;;
|
||||
-static)
|
||||
shared=false
|
||||
;;
|
||||
-Wl,*)
|
||||
arg=${1#-Wl,}
|
||||
save_ifs="$IFS"; IFS=','
|
||||
for flag in $arg; do
|
||||
IFS="$save_ifs"
|
||||
linker_opts="$linker_opts $flag"
|
||||
done
|
||||
IFS="$save_ifs"
|
||||
;;
|
||||
-Xlinker)
|
||||
eat=1
|
||||
linker_opts="$linker_opts $2"
|
||||
;;
|
||||
-*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
|
||||
func_file_conv "$1"
|
||||
set x "$@" -Tp"$file"
|
||||
shift
|
||||
;;
|
||||
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
|
||||
func_file_conv "$1" mingw
|
||||
set x "$@" "$file"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
if test -n "$linker_opts"; then
|
||||
linker_opts="-link$linker_opts"
|
||||
fi
|
||||
exec "$@" $linker_opts
|
||||
exit 1
|
||||
}
|
||||
|
||||
eat=
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: compile [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Wrapper for compilers which do not understand '-c -o'.
|
||||
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
|
||||
arguments, and rename the output as expected.
|
||||
|
||||
If you are trying to build a whole package this is not the
|
||||
right script to run: please start by reading the file 'INSTALL'.
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "compile $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
|
||||
func_cl_wrapper "$@" # Doesn't return...
|
||||
;;
|
||||
esac
|
||||
|
||||
ofile=
|
||||
cfile=
|
||||
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||
# So we strip '-o arg' only if arg is an object.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.obj)
|
||||
ofile=$2
|
||||
;;
|
||||
*)
|
||||
set x "$@" -o "$2"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*.c)
|
||||
cfile=$1
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
|
||||
if test -z "$ofile" || test -z "$cfile"; then
|
||||
# If no '-o' option was seen then we might have been invoked from a
|
||||
# pattern rule where we don't need one. That is ok -- this is a
|
||||
# normal compilation that the losing compiler can handle. If no
|
||||
# '.c' file was seen then we are probably linking. That is also
|
||||
# ok.
|
||||
exec "$@"
|
||||
fi
|
||||
|
||||
# Name of file we expect compiler to create.
|
||||
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
|
||||
|
||||
# Create the lock directory.
|
||||
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
|
||||
# that we are using for the .o file. Also, base the name on the expected
|
||||
# object file name, since that is what matters with a parallel build.
|
||||
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
|
||||
while true; do
|
||||
if mkdir "$lockdir" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
# FIXME: race condition here if user kills between mkdir and trap.
|
||||
trap "rmdir '$lockdir'; exit 1" 1 2 15
|
||||
|
||||
# Run the compile.
|
||||
"$@"
|
||||
ret=$?
|
||||
|
||||
if test -f "$cofile"; then
|
||||
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
|
||||
elif test -f "${cofile}bj"; then
|
||||
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
|
||||
fi
|
||||
|
||||
rmdir "$lockdir"
|
||||
exit $ret
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
1530
external/bsd/libevent/dist/config.guess
vendored
Executable file
1530
external/bsd/libevent/dist/config.guess
vendored
Executable file
File diff suppressed because it is too large
Load diff
439
external/bsd/libevent/dist/config.h.in
vendored
Normal file
439
external/bsd/libevent/dist/config.h.in
vendored
Normal file
|
@ -0,0 +1,439 @@
|
|||
/* config.h.in. Generated from configure.in by autoheader. */
|
||||
|
||||
/* Define if libevent should build without support for a debug mode */
|
||||
#undef DISABLE_DEBUG_MODE
|
||||
|
||||
/* Define if libevent should not allow replacing the mm functions */
|
||||
#undef DISABLE_MM_REPLACEMENT
|
||||
|
||||
/* Define if libevent should not be compiled with thread support */
|
||||
#undef DISABLE_THREAD_SUPPORT
|
||||
|
||||
/* Define to 1 if you have the `arc4random' function. */
|
||||
#undef HAVE_ARC4RANDOM
|
||||
|
||||
/* Define to 1 if you have the `arc4random_buf' function. */
|
||||
#undef HAVE_ARC4RANDOM_BUF
|
||||
|
||||
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||
#undef HAVE_ARPA_INET_H
|
||||
|
||||
/* Define to 1 if you have the `clock_gettime' function. */
|
||||
#undef HAVE_CLOCK_GETTIME
|
||||
|
||||
/* Define to 1 if you have the declaration of `CTL_KERN', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_CTL_KERN
|
||||
|
||||
/* Define to 1 if you have the declaration of `KERN_ARND', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_KERN_ARND
|
||||
|
||||
/* Define to 1 if you have the declaration of `KERN_RANDOM', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_KERN_RANDOM
|
||||
|
||||
/* Define to 1 if you have the declaration of `RANDOM_UUID', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_RANDOM_UUID
|
||||
|
||||
/* Define if /dev/poll is available */
|
||||
#undef HAVE_DEVPOLL
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#undef HAVE_DLFCN_H
|
||||
|
||||
/* Define if your system supports the epoll system calls */
|
||||
#undef HAVE_EPOLL
|
||||
|
||||
/* Define to 1 if you have the `epoll_ctl' function. */
|
||||
#undef HAVE_EPOLL_CTL
|
||||
|
||||
/* Define to 1 if you have the `eventfd' function. */
|
||||
#undef HAVE_EVENTFD
|
||||
|
||||
/* Define if your system supports event ports */
|
||||
#undef HAVE_EVENT_PORTS
|
||||
|
||||
/* Define to 1 if you have the `fcntl' function. */
|
||||
#undef HAVE_FCNTL
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#undef HAVE_FCNTL_H
|
||||
|
||||
/* Define to 1 if the system has the type `fd_mask'. */
|
||||
#undef HAVE_FD_MASK
|
||||
|
||||
/* Do we have getaddrinfo()? */
|
||||
#undef HAVE_GETADDRINFO
|
||||
|
||||
/* Define to 1 if you have the `getegid' function. */
|
||||
#undef HAVE_GETEGID
|
||||
|
||||
/* Define to 1 if you have the `geteuid' function. */
|
||||
#undef HAVE_GETEUID
|
||||
|
||||
/* Define this if you have any gethostbyname_r() */
|
||||
#undef HAVE_GETHOSTBYNAME_R
|
||||
|
||||
/* Define this if gethostbyname_r takes 3 arguments */
|
||||
#undef HAVE_GETHOSTBYNAME_R_3_ARG
|
||||
|
||||
/* Define this if gethostbyname_r takes 5 arguments */
|
||||
#undef HAVE_GETHOSTBYNAME_R_5_ARG
|
||||
|
||||
/* Define this if gethostbyname_r takes 6 arguments */
|
||||
#undef HAVE_GETHOSTBYNAME_R_6_ARG
|
||||
|
||||
/* Define to 1 if you have the `getnameinfo' function. */
|
||||
#undef HAVE_GETNAMEINFO
|
||||
|
||||
/* Define to 1 if you have the `getprotobynumber' function. */
|
||||
#undef HAVE_GETPROTOBYNUMBER
|
||||
|
||||
/* Define to 1 if you have the `getservbyname' function. */
|
||||
#undef HAVE_GETSERVBYNAME
|
||||
|
||||
/* Define to 1 if you have the `gettimeofday' function. */
|
||||
#undef HAVE_GETTIMEOFDAY
|
||||
|
||||
/* Define to 1 if you have the `inet_aton' function. */
|
||||
#undef HAVE_INET_ATON
|
||||
|
||||
/* Define to 1 if you have the `inet_ntop' function. */
|
||||
#undef HAVE_INET_NTOP
|
||||
|
||||
/* Define to 1 if you have the `inet_pton' function. */
|
||||
#undef HAVE_INET_PTON
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the `issetugid' function. */
|
||||
#undef HAVE_ISSETUGID
|
||||
|
||||
/* Define to 1 if you have the `kqueue' function. */
|
||||
#undef HAVE_KQUEUE
|
||||
|
||||
/* Define if the system has zlib */
|
||||
#undef HAVE_LIBZ
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if you have the `mmap' function. */
|
||||
#undef HAVE_MMAP
|
||||
|
||||
/* Define to 1 if you have the <netdb.h> header file. */
|
||||
#undef HAVE_NETDB_H
|
||||
|
||||
/* Define to 1 if you have the <netinet/in6.h> header file. */
|
||||
#undef HAVE_NETINET_IN6_H
|
||||
|
||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||
#undef HAVE_NETINET_IN_H
|
||||
|
||||
/* Define if the system has openssl */
|
||||
#undef HAVE_OPENSSL
|
||||
|
||||
/* Define to 1 if you have the <openssl/bio.h> header file. */
|
||||
#undef HAVE_OPENSSL_BIO_H
|
||||
|
||||
/* Define to 1 if you have the `pipe' function. */
|
||||
#undef HAVE_PIPE
|
||||
|
||||
/* Define to 1 if you have the `poll' function. */
|
||||
#undef HAVE_POLL
|
||||
|
||||
/* Define to 1 if you have the <poll.h> header file. */
|
||||
#undef HAVE_POLL_H
|
||||
|
||||
/* Define to 1 if you have the `port_create' function. */
|
||||
#undef HAVE_PORT_CREATE
|
||||
|
||||
/* Define to 1 if you have the <port.h> header file. */
|
||||
#undef HAVE_PORT_H
|
||||
|
||||
/* Define if you have POSIX threads libraries and header files. */
|
||||
#undef HAVE_PTHREAD
|
||||
|
||||
/* Define if we have pthreads on this system */
|
||||
#undef HAVE_PTHREADS
|
||||
|
||||
/* Define to 1 if you have the `putenv' function. */
|
||||
#undef HAVE_PUTENV
|
||||
|
||||
/* Define to 1 if the system has the type `sa_family_t'. */
|
||||
#undef HAVE_SA_FAMILY_T
|
||||
|
||||
/* Define to 1 if you have the `select' function. */
|
||||
#undef HAVE_SELECT
|
||||
|
||||
/* Define to 1 if you have the `sendfile' function. */
|
||||
#undef HAVE_SENDFILE
|
||||
|
||||
/* Define to 1 if you have the `setenv' function. */
|
||||
#undef HAVE_SETENV
|
||||
|
||||
/* Define if F_SETFD is defined in <fcntl.h> */
|
||||
#undef HAVE_SETFD
|
||||
|
||||
/* Define to 1 if you have the `sigaction' function. */
|
||||
#undef HAVE_SIGACTION
|
||||
|
||||
/* Define to 1 if you have the `signal' function. */
|
||||
#undef HAVE_SIGNAL
|
||||
|
||||
/* Define to 1 if you have the `splice' function. */
|
||||
#undef HAVE_SPLICE
|
||||
|
||||
/* Define to 1 if you have the <stdarg.h> header file. */
|
||||
#undef HAVE_STDARG_H
|
||||
|
||||
/* Define to 1 if you have the <stddef.h> header file. */
|
||||
#undef HAVE_STDDEF_H
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the `strlcpy' function. */
|
||||
#undef HAVE_STRLCPY
|
||||
|
||||
/* Define to 1 if you have the `strsep' function. */
|
||||
#undef HAVE_STRSEP
|
||||
|
||||
/* Define to 1 if you have the `strtok_r' function. */
|
||||
#undef HAVE_STRTOK_R
|
||||
|
||||
/* Define to 1 if you have the `strtoll' function. */
|
||||
#undef HAVE_STRTOLL
|
||||
|
||||
/* Define to 1 if the system has the type `struct addrinfo'. */
|
||||
#undef HAVE_STRUCT_ADDRINFO
|
||||
|
||||
/* Define to 1 if the system has the type `struct in6_addr'. */
|
||||
#undef HAVE_STRUCT_IN6_ADDR
|
||||
|
||||
/* Define to 1 if `s6_addr16' is a member of `struct in6_addr'. */
|
||||
#undef HAVE_STRUCT_IN6_ADDR_S6_ADDR16
|
||||
|
||||
/* Define to 1 if `s6_addr32' is a member of `struct in6_addr'. */
|
||||
#undef HAVE_STRUCT_IN6_ADDR_S6_ADDR32
|
||||
|
||||
/* Define to 1 if the system has the type `struct sockaddr_in6'. */
|
||||
#undef HAVE_STRUCT_SOCKADDR_IN6
|
||||
|
||||
/* Define to 1 if `sin6_len' is a member of `struct sockaddr_in6'. */
|
||||
#undef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
|
||||
|
||||
/* Define to 1 if `sin_len' is a member of `struct sockaddr_in'. */
|
||||
#undef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
|
||||
|
||||
/* Define to 1 if the system has the type `struct sockaddr_storage'. */
|
||||
#undef HAVE_STRUCT_SOCKADDR_STORAGE
|
||||
|
||||
/* Define to 1 if `ss_family' is a member of `struct sockaddr_storage'. */
|
||||
#undef HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY
|
||||
|
||||
/* Define to 1 if `__ss_family' is a member of `struct sockaddr_storage'. */
|
||||
#undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY
|
||||
|
||||
/* Define to 1 if you have the `sysctl' function. */
|
||||
#undef HAVE_SYSCTL
|
||||
|
||||
/* Define to 1 if you have the <sys/devpoll.h> header file. */
|
||||
#undef HAVE_SYS_DEVPOLL_H
|
||||
|
||||
/* Define to 1 if you have the <sys/epoll.h> header file. */
|
||||
#undef HAVE_SYS_EPOLL_H
|
||||
|
||||
/* Define to 1 if you have the <sys/eventfd.h> header file. */
|
||||
#undef HAVE_SYS_EVENTFD_H
|
||||
|
||||
/* Define to 1 if you have the <sys/event.h> header file. */
|
||||
#undef HAVE_SYS_EVENT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
||||
#undef HAVE_SYS_IOCTL_H
|
||||
|
||||
/* Define to 1 if you have the <sys/mman.h> header file. */
|
||||
#undef HAVE_SYS_MMAN_H
|
||||
|
||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||
#undef HAVE_SYS_PARAM_H
|
||||
|
||||
/* Define to 1 if you have the <sys/queue.h> header file. */
|
||||
#undef HAVE_SYS_QUEUE_H
|
||||
|
||||
/* Define to 1 if you have the <sys/select.h> header file. */
|
||||
#undef HAVE_SYS_SELECT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/sendfile.h> header file. */
|
||||
#undef HAVE_SYS_SENDFILE_H
|
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
#undef HAVE_SYS_SOCKET_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/sysctl.h> header file. */
|
||||
#undef HAVE_SYS_SYSCTL_H
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#undef HAVE_SYS_TIME_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <sys/uio.h> header file. */
|
||||
#undef HAVE_SYS_UIO_H
|
||||
|
||||
/* Define to 1 if you have the <sys/wait.h> header file. */
|
||||
#undef HAVE_SYS_WAIT_H
|
||||
|
||||
/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */
|
||||
#undef HAVE_TAILQFOREACH
|
||||
|
||||
/* Define if timeradd is defined in <sys/time.h> */
|
||||
#undef HAVE_TIMERADD
|
||||
|
||||
/* Define if timerclear is defined in <sys/time.h> */
|
||||
#undef HAVE_TIMERCLEAR
|
||||
|
||||
/* Define if timercmp is defined in <sys/time.h> */
|
||||
#undef HAVE_TIMERCMP
|
||||
|
||||
/* Define if timerisset is defined in <sys/time.h> */
|
||||
#undef HAVE_TIMERISSET
|
||||
|
||||
/* Define to 1 if the system has the type `uint16_t'. */
|
||||
#undef HAVE_UINT16_T
|
||||
|
||||
/* Define to 1 if the system has the type `uint32_t'. */
|
||||
#undef HAVE_UINT32_T
|
||||
|
||||
/* Define to 1 if the system has the type `uint64_t'. */
|
||||
#undef HAVE_UINT64_T
|
||||
|
||||
/* Define to 1 if the system has the type `uint8_t'. */
|
||||
#undef HAVE_UINT8_T
|
||||
|
||||
/* Define to 1 if the system has the type `uintptr_t'. */
|
||||
#undef HAVE_UINTPTR_T
|
||||
|
||||
/* Define to 1 if you have the `umask' function. */
|
||||
#undef HAVE_UMASK
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define to 1 if you have the `unsetenv' function. */
|
||||
#undef HAVE_UNSETENV
|
||||
|
||||
/* Define to 1 if you have the `vasprintf' function. */
|
||||
#undef HAVE_VASPRINTF
|
||||
|
||||
/* Define if kqueue works correctly with pipes */
|
||||
#undef HAVE_WORKING_KQUEUE
|
||||
|
||||
/* Define to 1 if you have the <zlib.h> header file. */
|
||||
#undef HAVE_ZLIB_H
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#undef LT_OBJDIR
|
||||
|
||||
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
|
||||
#undef NO_MINUS_C_MINUS_O
|
||||
|
||||
/* Numeric representation of the version */
|
||||
#undef NUMERIC_VERSION
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#undef PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* Define to necessary symbol if this constant uses a non-standard name on
|
||||
your system. */
|
||||
#undef PTHREAD_CREATE_JOINABLE
|
||||
|
||||
/* The size of `int', as computed by sizeof. */
|
||||
#undef SIZEOF_INT
|
||||
|
||||
/* The size of `long', as computed by sizeof. */
|
||||
#undef SIZEOF_LONG
|
||||
|
||||
/* The size of `long long', as computed by sizeof. */
|
||||
#undef SIZEOF_LONG_LONG
|
||||
|
||||
/* The size of `pthread_t', as computed by sizeof. */
|
||||
#undef SIZEOF_PTHREAD_T
|
||||
|
||||
/* The size of `short', as computed by sizeof. */
|
||||
#undef SIZEOF_SHORT
|
||||
|
||||
/* The size of `size_t', as computed by sizeof. */
|
||||
#undef SIZEOF_SIZE_T
|
||||
|
||||
/* The size of `void *', as computed by sizeof. */
|
||||
#undef SIZEOF_VOID_P
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
|
||||
#undef TIME_WITH_SYS_TIME
|
||||
|
||||
/* Version number of package */
|
||||
#undef VERSION
|
||||
|
||||
/* Define to appropriate substitue if compiler doesnt have __func__ */
|
||||
#undef __func__
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
#undef 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 __cplusplus
|
||||
#undef inline
|
||||
#endif
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
#undef pid_t
|
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||
#undef size_t
|
||||
|
||||
/* Define to unsigned int if you dont have it */
|
||||
#undef socklen_t
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
#undef ssize_t
|
1773
external/bsd/libevent/dist/config.sub
vendored
Executable file
1773
external/bsd/libevent/dist/config.sub
vendored
Executable file
File diff suppressed because it is too large
Load diff
17532
external/bsd/libevent/dist/configure
vendored
Executable file
17532
external/bsd/libevent/dist/configure
vendored
Executable file
File diff suppressed because it is too large
Load diff
806
external/bsd/libevent/dist/configure.in
vendored
Normal file
806
external/bsd/libevent/dist/configure.in
vendored
Normal file
|
@ -0,0 +1,806 @@
|
|||
dnl configure.in for libevent
|
||||
dnl Copyright 2000-2007 Niels Provos
|
||||
dnl Copyright 2007-2012 Niels Provos and Nick Mathewson
|
||||
dnl
|
||||
dnl See LICENSE for copying information.
|
||||
dnl
|
||||
dnl Original version Dug Song <dugsong@monkey.org>
|
||||
|
||||
AC_PREREQ(2.59c)
|
||||
AC_INIT(event.c)
|
||||
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
AM_INIT_AUTOMAKE(libevent,2.0.21-stable)
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
AC_DEFINE(NUMERIC_VERSION, 0x02001500, [Numeric representation of the version])
|
||||
|
||||
dnl Initialize prefix.
|
||||
if test "$prefix" = "NONE"; then
|
||||
prefix="/usr/local"
|
||||
fi
|
||||
|
||||
AC_CANONICAL_BUILD
|
||||
AC_CANONICAL_HOST
|
||||
dnl the 'build' machine is where we run configure and compile
|
||||
dnl the 'host' machine is where the resulting stuff runs.
|
||||
|
||||
case "$host_os" in
|
||||
|
||||
osf5*)
|
||||
CFLAGS="$CFLAGS -D_OSF_SOURCE"
|
||||
;;
|
||||
esac
|
||||
|
||||
dnl Checks for programs.
|
||||
AC_PROG_CC
|
||||
AM_PROG_CC_C_O
|
||||
AC_PROG_SED
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LN_S
|
||||
AC_PROG_MKDIR_P
|
||||
|
||||
AC_PROG_GCC_TRADITIONAL
|
||||
|
||||
# We need to test for at least gcc 2.95 here, because older versions don't
|
||||
# have -fno-strict-aliasing
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [
|
||||
#if !defined(__GNUC__) || (__GNUC__ < 2) || (__GNUC__ == 2 && __GNUC_MINOR__ < 95)
|
||||
#error
|
||||
#endif])], have_gcc295=yes, have_gcc295=no)
|
||||
|
||||
if test "$GCC" = "yes" ; then
|
||||
# Enable many gcc warnings by default...
|
||||
CFLAGS="$CFLAGS -Wall"
|
||||
# And disable the strict-aliasing optimization, since it breaks
|
||||
# our sockaddr-handling code in strange ways.
|
||||
if test x$have_gcc295 = xyes; then
|
||||
CFLAGS="$CFLAGS -fno-strict-aliasing"
|
||||
fi
|
||||
fi
|
||||
|
||||
# OS X Lion started deprecating the system openssl. Let's just disable
|
||||
# all deprecation warnings on OS X.
|
||||
case "$host_os" in
|
||||
|
||||
darwin*)
|
||||
CFLAGS="$CFLAGS -Wno-deprecated-declarations"
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_ARG_ENABLE(gcc-warnings,
|
||||
AS_HELP_STRING(--enable-gcc-warnings, enable verbose warnings with GCC))
|
||||
AC_ARG_ENABLE(thread-support,
|
||||
AS_HELP_STRING(--disable-thread-support, disable support for threading),
|
||||
[], [enable_thread_support=yes])
|
||||
AC_ARG_ENABLE(malloc-replacement,
|
||||
AS_HELP_STRING(--disable-malloc-replacement, disable support for replacing the memory mgt functions),
|
||||
[], [enable_malloc_replacement=yes])
|
||||
AC_ARG_ENABLE(openssl,
|
||||
AS_HELP_STRING(--disable-openssl, disable support for openssl encryption),
|
||||
[], [enable_openssl=yes])
|
||||
AC_ARG_ENABLE(debug-mode,
|
||||
AS_HELP_STRING(--disable-debug-mode, disable support for running in debug mode),
|
||||
[], [enable_debug_mode=yes])
|
||||
AC_ARG_ENABLE([libevent-install],
|
||||
AS_HELP_STRING([--disable-libevent-install, disable installation of libevent]),
|
||||
[], [enable_libevent_install=yes])
|
||||
AC_ARG_ENABLE([libevent-regress],
|
||||
AS_HELP_STRING([--disable-libevent-regress, skip regress in make check]),
|
||||
[], [enable_libevent_regress=yes])
|
||||
AC_ARG_ENABLE([function-sections],
|
||||
AS_HELP_STRING([--enable-function-sections, make static library allow smaller binaries with --gc-sections]),
|
||||
[], [enable_function_sections=no])
|
||||
|
||||
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
dnl Uncomment "AC_DISABLE_SHARED" to make shared librraries not get
|
||||
dnl built by default. You can also turn shared libs on and off from
|
||||
dnl the command line with --enable-shared and --disable-shared.
|
||||
dnl AC_DISABLE_SHARED
|
||||
AC_SUBST(LIBTOOL_DEPS)
|
||||
|
||||
AM_CONDITIONAL([BUILD_REGRESS], [test "$enable_libevent_regress" = "yes"])
|
||||
|
||||
dnl Checks for libraries.
|
||||
AC_SEARCH_LIBS([inet_ntoa], [nsl])
|
||||
AC_SEARCH_LIBS([socket], [socket])
|
||||
AC_SEARCH_LIBS([inet_aton], [resolv])
|
||||
AC_SEARCH_LIBS([clock_gettime], [rt])
|
||||
AC_SEARCH_LIBS([sendfile], [sendfile])
|
||||
|
||||
dnl - check if the macro WIN32 is defined on this compiler.
|
||||
dnl - (this is how we check for a windows version of GCC)
|
||||
AC_MSG_CHECKING(for WIN32)
|
||||
AC_TRY_COMPILE(,
|
||||
[
|
||||
#ifndef WIN32
|
||||
die horribly
|
||||
#endif
|
||||
],
|
||||
bwin32=true; AC_MSG_RESULT(yes),
|
||||
bwin32=false; AC_MSG_RESULT(no),
|
||||
)
|
||||
|
||||
dnl - check if the macro __CYGWIN__ is defined on this compiler.
|
||||
dnl - (this is how we check for a cygwin version of GCC)
|
||||
AC_MSG_CHECKING(for CYGWIN)
|
||||
AC_TRY_COMPILE(,
|
||||
[
|
||||
#ifndef __CYGWIN__
|
||||
die horribly
|
||||
#endif
|
||||
],
|
||||
cygwin=true; AC_MSG_RESULT(yes),
|
||||
cygwin=false; AC_MSG_RESULT(no),
|
||||
)
|
||||
|
||||
AC_CHECK_HEADERS([zlib.h])
|
||||
|
||||
if test "x$ac_cv_header_zlib_h" = "xyes"; then
|
||||
dnl Determine if we have zlib for regression tests
|
||||
dnl Don't put this one in LIBS
|
||||
save_LIBS="$LIBS"
|
||||
LIBS=""
|
||||
ZLIB_LIBS=""
|
||||
have_zlib=no
|
||||
AC_SEARCH_LIBS([inflateEnd], [z],
|
||||
[have_zlib=yes
|
||||
ZLIB_LIBS="$LIBS"
|
||||
AC_DEFINE(HAVE_LIBZ, 1, [Define if the system has zlib])])
|
||||
LIBS="$save_LIBS"
|
||||
AC_SUBST(ZLIB_LIBS)
|
||||
fi
|
||||
AM_CONDITIONAL(ZLIB_REGRESS, [test "$have_zlib" = "yes"])
|
||||
|
||||
dnl See if we have openssl. This doesn't go in LIBS either.
|
||||
if test "$bwin32" = true; then
|
||||
EV_LIB_WS32=-lws2_32
|
||||
EV_LIB_GDI=-lgdi32
|
||||
else
|
||||
EV_LIB_WS32=
|
||||
EV_LIB_GDI=
|
||||
fi
|
||||
AC_SUBST(EV_LIB_WS32)
|
||||
AC_SUBST(EV_LIB_GDI)
|
||||
AC_SUBST(OPENSSL_LIBADD)
|
||||
|
||||
AC_CHECK_HEADERS([openssl/bio.h])
|
||||
|
||||
if test "$enable_openssl" = "yes"; then
|
||||
save_LIBS="$LIBS"
|
||||
LIBS=""
|
||||
OPENSSL_LIBS=""
|
||||
have_openssl=no
|
||||
AC_SEARCH_LIBS([SSL_new], [ssl],
|
||||
[have_openssl=yes
|
||||
OPENSSL_LIBS="$LIBS -lcrypto $EV_LIB_GDI $EV_LIB_WS32 $OPENSSL_LIBADD"
|
||||
AC_DEFINE(HAVE_OPENSSL, 1, [Define if the system has openssl])],
|
||||
[have_openssl=no],
|
||||
[-lcrypto $EV_LIB_GDI $EV_LIB_WS32 $OPENSSL_LIBADD])
|
||||
LIBS="$save_LIBS"
|
||||
AC_SUBST(OPENSSL_LIBS)
|
||||
fi
|
||||
|
||||
dnl Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS([fcntl.h stdarg.h inttypes.h stdint.h stddef.h poll.h unistd.h sys/epoll.h sys/time.h sys/queue.h sys/event.h sys/param.h sys/ioctl.h sys/select.h sys/devpoll.h port.h netinet/in.h netinet/in6.h sys/socket.h sys/uio.h arpa/inet.h sys/eventfd.h sys/mman.h sys/sendfile.h sys/wait.h netdb.h])
|
||||
AC_CHECK_HEADERS([sys/stat.h])
|
||||
AC_CHECK_HEADERS(sys/sysctl.h, [], [], [
|
||||
#ifdef HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
])
|
||||
if test "x$ac_cv_header_sys_queue_h" = "xyes"; then
|
||||
AC_MSG_CHECKING(for TAILQ_FOREACH in sys/queue.h)
|
||||
AC_EGREP_CPP(yes,
|
||||
[
|
||||
#include <sys/queue.h>
|
||||
#ifdef TAILQ_FOREACH
|
||||
yes
|
||||
#endif
|
||||
], [AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_TAILQFOREACH, 1,
|
||||
[Define if TAILQ_FOREACH is defined in <sys/queue.h>])],
|
||||
AC_MSG_RESULT(no)
|
||||
)
|
||||
fi
|
||||
|
||||
if test "x$ac_cv_header_sys_time_h" = "xyes"; then
|
||||
AC_MSG_CHECKING(for timeradd in sys/time.h)
|
||||
AC_EGREP_CPP(yes,
|
||||
[
|
||||
#include <sys/time.h>
|
||||
#ifdef timeradd
|
||||
yes
|
||||
#endif
|
||||
], [ AC_DEFINE(HAVE_TIMERADD, 1,
|
||||
[Define if timeradd is defined in <sys/time.h>])
|
||||
AC_MSG_RESULT(yes)] ,AC_MSG_RESULT(no)
|
||||
)
|
||||
fi
|
||||
|
||||
if test "x$ac_cv_header_sys_time_h" = "xyes"; then
|
||||
AC_MSG_CHECKING(for timercmp in sys/time.h)
|
||||
AC_EGREP_CPP(yes,
|
||||
[
|
||||
#include <sys/time.h>
|
||||
#ifdef timercmp
|
||||
yes
|
||||
#endif
|
||||
], [ AC_DEFINE(HAVE_TIMERCMP, 1,
|
||||
[Define if timercmp is defined in <sys/time.h>])
|
||||
AC_MSG_RESULT(yes)] ,AC_MSG_RESULT(no)
|
||||
)
|
||||
fi
|
||||
|
||||
if test "x$ac_cv_header_sys_time_h" = "xyes"; then
|
||||
AC_MSG_CHECKING(for timerclear in sys/time.h)
|
||||
AC_EGREP_CPP(yes,
|
||||
[
|
||||
#include <sys/time.h>
|
||||
#ifdef timerclear
|
||||
yes
|
||||
#endif
|
||||
], [ AC_DEFINE(HAVE_TIMERCLEAR, 1,
|
||||
[Define if timerclear is defined in <sys/time.h>])
|
||||
AC_MSG_RESULT(yes)] ,AC_MSG_RESULT(no)
|
||||
)
|
||||
fi
|
||||
|
||||
if test "x$ac_cv_header_sys_time_h" = "xyes"; then
|
||||
AC_MSG_CHECKING(for timerisset in sys/time.h)
|
||||
AC_EGREP_CPP(yes,
|
||||
[
|
||||
#include <sys/time.h>
|
||||
#ifdef timerisset
|
||||
yes
|
||||
#endif
|
||||
], [ AC_DEFINE(HAVE_TIMERISSET, 1,
|
||||
[Define if timerisset is defined in <sys/time.h>])
|
||||
AC_MSG_RESULT(yes)] ,AC_MSG_RESULT(no)
|
||||
)
|
||||
fi
|
||||
|
||||
if test "x$ac_cv_header_sys_sysctl_h" = "xyes"; then
|
||||
AC_CHECK_DECLS([CTL_KERN, KERN_RANDOM, RANDOM_UUID, KERN_ARND], [], [],
|
||||
[[#include <sys/types.h>
|
||||
#include <sys/sysctl.h>]]
|
||||
)
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(BUILD_WIN32, test x$bwin32 = xtrue)
|
||||
AM_CONDITIONAL(BUILD_CYGWIN, test x$cygwin = xtrue)
|
||||
AM_CONDITIONAL(BUILD_WITH_NO_UNDEFINED, test x$bwin32 = xtrue || test x$cygwin = xtrue)
|
||||
|
||||
if test x$bwin32 = xtrue; then
|
||||
AC_SEARCH_LIBS([getservbyname],[ws2_32])
|
||||
fi
|
||||
|
||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_C_CONST
|
||||
AC_C_INLINE
|
||||
AC_HEADER_TIME
|
||||
|
||||
dnl Checks for library functions.
|
||||
AC_CHECK_FUNCS([gettimeofday vasprintf fcntl clock_gettime strtok_r strsep])
|
||||
AC_CHECK_FUNCS([getnameinfo strlcpy inet_ntop inet_pton signal sigaction strtoll inet_aton pipe eventfd sendfile mmap splice arc4random arc4random_buf issetugid geteuid getegid getprotobynumber setenv unsetenv putenv sysctl])
|
||||
AC_CHECK_FUNCS([umask])
|
||||
|
||||
AC_CACHE_CHECK(
|
||||
[for getaddrinfo],
|
||||
[libevent_cv_getaddrinfo],
|
||||
[AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
]],
|
||||
[[
|
||||
getaddrinfo;
|
||||
]]
|
||||
)],
|
||||
[libevent_cv_getaddrinfo=yes],
|
||||
[libevent_cv_getaddrinfo=no]
|
||||
)]
|
||||
)
|
||||
if test "$libevent_cv_getaddrinfo" = "yes" ; then
|
||||
AC_DEFINE([HAVE_GETADDRINFO], [1], [Do we have getaddrinfo()?])
|
||||
else
|
||||
|
||||
AC_CHECK_FUNCS([getservbyname])
|
||||
# Check for gethostbyname_r in all its glorious incompatible versions.
|
||||
# (This is cut-and-pasted from Tor, which based its logic on
|
||||
# Python's configure.in.)
|
||||
AH_TEMPLATE(HAVE_GETHOSTBYNAME_R,
|
||||
[Define this if you have any gethostbyname_r()])
|
||||
|
||||
AC_CHECK_FUNC(gethostbyname_r, [
|
||||
AC_MSG_CHECKING([how many arguments gethostbyname_r() wants])
|
||||
OLD_CFLAGS=$CFLAGS
|
||||
CFLAGS="$CFLAGS $MY_CPPFLAGS $MY_THREAD_CPPFLAGS $MY_CFLAGS"
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
|
||||
#include <netdb.h>
|
||||
], [[
|
||||
char *cp1, *cp2;
|
||||
struct hostent *h1, *h2;
|
||||
int i1, i2;
|
||||
(void)gethostbyname_r(cp1,h1,cp2,i1,&h2,&i2);
|
||||
]])],[
|
||||
AC_DEFINE(HAVE_GETHOSTBYNAME_R)
|
||||
AC_DEFINE(HAVE_GETHOSTBYNAME_R_6_ARG, 1,
|
||||
[Define this if gethostbyname_r takes 6 arguments])
|
||||
AC_MSG_RESULT(6)
|
||||
], [
|
||||
AC_TRY_COMPILE([
|
||||
#include <netdb.h>
|
||||
], [
|
||||
char *cp1, *cp2;
|
||||
struct hostent *h1;
|
||||
int i1, i2;
|
||||
(void)gethostbyname_r(cp1,h1,cp2,i1,&i2);
|
||||
], [
|
||||
AC_DEFINE(HAVE_GETHOSTBYNAME_R)
|
||||
AC_DEFINE(HAVE_GETHOSTBYNAME_R_5_ARG, 1,
|
||||
[Define this if gethostbyname_r takes 5 arguments])
|
||||
AC_MSG_RESULT(5)
|
||||
], [
|
||||
AC_TRY_COMPILE([
|
||||
#include <netdb.h>
|
||||
], [
|
||||
char *cp1;
|
||||
struct hostent *h1;
|
||||
struct hostent_data hd;
|
||||
(void) gethostbyname_r(cp1,h1,&hd);
|
||||
], [
|
||||
AC_DEFINE(HAVE_GETHOSTBYNAME_R)
|
||||
AC_DEFINE(HAVE_GETHOSTBYNAME_R_3_ARG, 1,
|
||||
[Define this if gethostbyname_r takes 3 arguments])
|
||||
AC_MSG_RESULT(3)
|
||||
], [
|
||||
AC_MSG_RESULT(0)
|
||||
])
|
||||
])
|
||||
])
|
||||
CFLAGS=$OLD_CFLAGS
|
||||
])
|
||||
|
||||
fi
|
||||
|
||||
AC_CHECK_SIZEOF(long)
|
||||
|
||||
AC_MSG_CHECKING(for F_SETFD in fcntl.h)
|
||||
AC_EGREP_CPP(yes,
|
||||
[
|
||||
#define _GNU_SOURCE
|
||||
#include <fcntl.h>
|
||||
#ifdef F_SETFD
|
||||
yes
|
||||
#endif
|
||||
], [ AC_DEFINE(HAVE_SETFD, 1,
|
||||
[Define if F_SETFD is defined in <fcntl.h>])
|
||||
AC_MSG_RESULT(yes) ], AC_MSG_RESULT(no))
|
||||
|
||||
needsignal=no
|
||||
haveselect=no
|
||||
if test x$bwin32 != xtrue; then
|
||||
AC_CHECK_FUNCS(select, [haveselect=yes], )
|
||||
if test "x$haveselect" = "xyes" ; then
|
||||
needsignal=yes
|
||||
fi
|
||||
fi
|
||||
AM_CONDITIONAL(SELECT_BACKEND, [test "x$haveselect" = "xyes"])
|
||||
|
||||
havepoll=no
|
||||
AC_CHECK_FUNCS(poll, [havepoll=yes], )
|
||||
if test "x$havepoll" = "xyes" ; then
|
||||
needsignal=yes
|
||||
fi
|
||||
AM_CONDITIONAL(POLL_BACKEND, [test "x$havepoll" = "xyes"])
|
||||
|
||||
havedevpoll=no
|
||||
if test "x$ac_cv_header_sys_devpoll_h" = "xyes"; then
|
||||
AC_DEFINE(HAVE_DEVPOLL, 1,
|
||||
[Define if /dev/poll is available])
|
||||
fi
|
||||
AM_CONDITIONAL(DEVPOLL_BACKEND, [test "x$ac_cv_header_sys_devpoll_h" = "xyes"])
|
||||
|
||||
havekqueue=no
|
||||
if test "x$ac_cv_header_sys_event_h" = "xyes"; then
|
||||
AC_CHECK_FUNCS(kqueue, [havekqueue=yes], )
|
||||
if test "x$havekqueue" = "xyes" ; then
|
||||
AC_MSG_CHECKING(for working kqueue)
|
||||
AC_TRY_RUN(
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/event.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int kq;
|
||||
int n;
|
||||
int fd[[2]];
|
||||
struct kevent ev;
|
||||
struct timespec ts;
|
||||
char buf[[8000]];
|
||||
|
||||
if (pipe(fd) == -1)
|
||||
exit(1);
|
||||
if (fcntl(fd[[1]], F_SETFL, O_NONBLOCK) == -1)
|
||||
exit(1);
|
||||
|
||||
while ((n = write(fd[[1]], buf, sizeof(buf))) == sizeof(buf))
|
||||
;
|
||||
|
||||
if ((kq = kqueue()) == -1)
|
||||
exit(1);
|
||||
|
||||
memset(&ev, 0, sizeof(ev));
|
||||
ev.ident = fd[[1]];
|
||||
ev.filter = EVFILT_WRITE;
|
||||
ev.flags = EV_ADD | EV_ENABLE;
|
||||
n = kevent(kq, &ev, 1, NULL, 0, NULL);
|
||||
if (n == -1)
|
||||
exit(1);
|
||||
|
||||
read(fd[[0]], buf, sizeof(buf));
|
||||
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 0;
|
||||
n = kevent(kq, NULL, 0, &ev, 1, &ts);
|
||||
if (n == -1 || n == 0)
|
||||
exit(1);
|
||||
|
||||
exit(0);
|
||||
}, [AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_WORKING_KQUEUE, 1,
|
||||
[Define if kqueue works correctly with pipes])
|
||||
havekqueue=yes
|
||||
], AC_MSG_RESULT(no), AC_MSG_RESULT(no))
|
||||
fi
|
||||
fi
|
||||
AM_CONDITIONAL(KQUEUE_BACKEND, [test "x$havekqueue" = "xyes"])
|
||||
|
||||
haveepollsyscall=no
|
||||
haveepoll=no
|
||||
AC_CHECK_FUNCS(epoll_ctl, [haveepoll=yes], )
|
||||
if test "x$haveepoll" = "xyes" ; then
|
||||
AC_DEFINE(HAVE_EPOLL, 1,
|
||||
[Define if your system supports the epoll system calls])
|
||||
needsignal=yes
|
||||
fi
|
||||
if test "x$ac_cv_header_sys_epoll_h" = "xyes"; then
|
||||
if test "x$haveepoll" = "xno" ; then
|
||||
AC_MSG_CHECKING(for epoll system call)
|
||||
AC_TRY_RUN(
|
||||
#include <stdint.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int
|
||||
epoll_create(int size)
|
||||
{
|
||||
return (syscall(__NR_epoll_create, size));
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int epfd;
|
||||
|
||||
epfd = epoll_create(256);
|
||||
exit (epfd == -1 ? 1 : 0);
|
||||
}, [AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_EPOLL, 1,
|
||||
[Define if your system supports the epoll system calls])
|
||||
needsignal=yes
|
||||
have_epoll=yes
|
||||
AC_LIBOBJ(epoll_sub)
|
||||
], AC_MSG_RESULT(no), AC_MSG_RESULT(no))
|
||||
fi
|
||||
fi
|
||||
AM_CONDITIONAL(EPOLL_BACKEND, [test "x$haveepoll" = "xyes"])
|
||||
|
||||
haveeventports=no
|
||||
AC_CHECK_FUNCS(port_create, [haveeventports=yes], )
|
||||
if test "x$haveeventports" = "xyes" ; then
|
||||
AC_DEFINE(HAVE_EVENT_PORTS, 1,
|
||||
[Define if your system supports event ports])
|
||||
needsignal=yes
|
||||
fi
|
||||
AM_CONDITIONAL(EVPORT_BACKEND, [test "x$haveeventports" = "xyes"])
|
||||
|
||||
if test "x$bwin32" = "xtrue"; then
|
||||
needsignal=yes
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(SIGNAL_SUPPORT, [test "x$needsignal" = "xyes"])
|
||||
|
||||
AC_TYPE_PID_T
|
||||
AC_TYPE_SIZE_T
|
||||
AC_TYPE_SSIZE_T
|
||||
|
||||
AC_CHECK_TYPES([uint64_t, uint32_t, uint16_t, uint8_t, uintptr_t], , ,
|
||||
[#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#elif defined(HAVE_INTTYPES_H)
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif])
|
||||
|
||||
AC_CHECK_TYPES([fd_mask], , ,
|
||||
[#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
#endif])
|
||||
|
||||
AC_CHECK_SIZEOF(long long)
|
||||
AC_CHECK_SIZEOF(long)
|
||||
AC_CHECK_SIZEOF(int)
|
||||
AC_CHECK_SIZEOF(short)
|
||||
AC_CHECK_SIZEOF(size_t)
|
||||
AC_CHECK_SIZEOF(void *)
|
||||
|
||||
AC_CHECK_TYPES([struct in6_addr, struct sockaddr_in6, sa_family_t, struct addrinfo, struct sockaddr_storage], , ,
|
||||
[#define _GNU_SOURCE
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETINET_IN6_H
|
||||
#include <netinet/in6.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
#define WIN32_WINNT 0x400
|
||||
#define _WIN32_WINNT 0x400
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1300)
|
||||
#include <winsock.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
#endif
|
||||
])
|
||||
AC_CHECK_MEMBERS([struct in6_addr.s6_addr32, struct in6_addr.s6_addr16, struct sockaddr_in.sin_len, struct sockaddr_in6.sin6_len, struct sockaddr_storage.ss_family, struct sockaddr_storage.__ss_family], , ,
|
||||
[#include <sys/types.h>
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETINET_IN6_H
|
||||
#include <netinet/in6.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
#define WIN32_WINNT 0x400
|
||||
#define _WIN32_WINNT 0x400
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1300)
|
||||
#include <winsock.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
#endif
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING([for socklen_t])
|
||||
AC_TRY_COMPILE([
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>],
|
||||
[socklen_t x;],
|
||||
AC_MSG_RESULT([yes]),
|
||||
[AC_MSG_RESULT([no])
|
||||
AC_DEFINE(socklen_t, unsigned int,
|
||||
[Define to unsigned int if you dont have it])]
|
||||
)
|
||||
|
||||
AC_MSG_CHECKING([whether our compiler supports __func__])
|
||||
AC_TRY_COMPILE([],
|
||||
[ const char *cp = __func__; ],
|
||||
AC_MSG_RESULT([yes]),
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_CHECKING([whether our compiler supports __FUNCTION__])
|
||||
AC_TRY_COMPILE([],
|
||||
[ const char *cp = __FUNCTION__; ],
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_DEFINE(__func__, __FUNCTION__,
|
||||
[Define to appropriate substitue if compiler doesnt have __func__]),
|
||||
AC_MSG_RESULT([no])
|
||||
AC_DEFINE(__func__, __FILE__,
|
||||
[Define to appropriate substitue if compiler doesnt have __func__])))
|
||||
|
||||
|
||||
# check if we can compile with pthreads
|
||||
have_pthreads=no
|
||||
if test x$bwin32 != xtrue && test "$enable_thread_support" != "no"; then
|
||||
ACX_PTHREAD([
|
||||
AC_DEFINE(HAVE_PTHREADS, 1,
|
||||
[Define if we have pthreads on this system])
|
||||
have_pthreads=yes])
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
AC_CHECK_SIZEOF(pthread_t, ,
|
||||
[AC_INCLUDES_DEFAULT()
|
||||
#include <pthread.h> ]
|
||||
)
|
||||
fi
|
||||
AM_CONDITIONAL(PTHREADS, [test "$have_pthreads" != "no" && test "$enable_thread_support" != "no"])
|
||||
|
||||
# check if we should compile locking into the library
|
||||
if test x$enable_thread_support = xno; then
|
||||
AC_DEFINE(DISABLE_THREAD_SUPPORT, 1,
|
||||
[Define if libevent should not be compiled with thread support])
|
||||
fi
|
||||
|
||||
# check if we should hard-code the mm functions.
|
||||
if test x$enable_malloc_replacement = xno; then
|
||||
AC_DEFINE(DISABLE_MM_REPLACEMENT, 1,
|
||||
[Define if libevent should not allow replacing the mm functions])
|
||||
fi
|
||||
|
||||
# check if we should hard-code debugging out
|
||||
if test x$enable_debug_mode = xno; then
|
||||
AC_DEFINE(DISABLE_DEBUG_MODE, 1,
|
||||
[Define if libevent should build without support for a debug mode])
|
||||
fi
|
||||
|
||||
# check if we have and should use openssl
|
||||
AM_CONDITIONAL(OPENSSL, [test "$enable_openssl" != "no" && test "$have_openssl" = "yes"])
|
||||
|
||||
# Add some more warnings which we use in development but not in the
|
||||
# released versions. (Some relevant gcc versions can't handle these.)
|
||||
if test x$enable_gcc_warnings = xyes && test "$GCC" = "yes"; then
|
||||
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [
|
||||
#if !defined(__GNUC__) || (__GNUC__ < 4)
|
||||
#error
|
||||
#endif])], have_gcc4=yes, have_gcc4=no)
|
||||
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [
|
||||
#if !defined(__GNUC__) || (__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 2)
|
||||
#error
|
||||
#endif])], have_gcc42=yes, have_gcc42=no)
|
||||
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [
|
||||
#if !defined(__GNUC__) || (__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 5)
|
||||
#error
|
||||
#endif])], have_gcc45=yes, have_gcc45=no)
|
||||
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [
|
||||
#if !defined(__clang__)
|
||||
#error
|
||||
#endif])], have_clang=yes, have_clang=no)
|
||||
|
||||
CFLAGS="$CFLAGS -W -Wfloat-equal -Wundef -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings -Wredundant-decls -Wchar-subscripts -Wcomment -Wformat -Wwrite-strings -Wmissing-declarations -Wredundant-decls -Wnested-externs -Wbad-function-cast -Wswitch-enum -Werror"
|
||||
CFLAGS="$CFLAGS -Wno-unused-parameter -Wstrict-aliasing"
|
||||
|
||||
if test x$have_gcc4 = xyes ; then
|
||||
# These warnings break gcc 3.3.5 and work on gcc 4.0.2
|
||||
CFLAGS="$CFLAGS -Winit-self -Wmissing-field-initializers -Wdeclaration-after-statement"
|
||||
#CFLAGS="$CFLAGS -Wold-style-definition"
|
||||
fi
|
||||
|
||||
if test x$have_gcc42 = xyes ; then
|
||||
# These warnings break gcc 4.0.2 and work on gcc 4.2
|
||||
CFLAGS="$CFLAGS -Waddress"
|
||||
fi
|
||||
|
||||
if test x$have_gcc42 = xyes && test x$have_clang = xno; then
|
||||
# These warnings break gcc 4.0.2 and clang, but work on gcc 4.2
|
||||
CFLAGS="$CFLAGS -Wnormalized=id -Woverride-init"
|
||||
fi
|
||||
|
||||
if test x$have_gcc45 = xyes ; then
|
||||
# These warnings work on gcc 4.5
|
||||
CFLAGS="$CFLAGS -Wlogical-op"
|
||||
fi
|
||||
|
||||
if test x$have_clang = xyes; then
|
||||
# Disable the unused-function warnings, because these trigger
|
||||
# for minheap-internal.h related code.
|
||||
CFLAGS="$CFLAGS -Wno-unused-function"
|
||||
fi
|
||||
|
||||
##This will break the world on some 64-bit architectures
|
||||
# CFLAGS="$CFLAGS -Winline"
|
||||
|
||||
fi
|
||||
|
||||
LIBEVENT_GC_SECTIONS=
|
||||
if test "$GCC" = yes && test "$enable_function_sections" = yes ; then
|
||||
AC_CACHE_CHECK(
|
||||
[if linker supports omitting unused code and data],
|
||||
[libevent_cv_gc_sections_runs],
|
||||
[
|
||||
dnl NetBSD will link but likely not run with --gc-sections
|
||||
dnl http://bugs.ntp.org/1844
|
||||
dnl http://gnats.netbsd.org/40401
|
||||
dnl --gc-sections causes attempt to load as linux elf, with
|
||||
dnl wrong syscalls in place. Test a little gauntlet of
|
||||
dnl simple stdio read code checking for errors, expecting
|
||||
dnl enough syscall differences that the NetBSD code will
|
||||
dnl fail even with Linux emulation working as designed.
|
||||
dnl A shorter test could be refined by someone with access
|
||||
dnl to a NetBSD host with Linux emulation working.
|
||||
origCFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -Wl,--gc-sections"
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
]],
|
||||
[[
|
||||
FILE * fpC;
|
||||
char buf[32];
|
||||
size_t cch;
|
||||
int read_success_once;
|
||||
|
||||
fpC = fopen("conftest.c", "r");
|
||||
if (NULL == fpC)
|
||||
exit(1);
|
||||
do {
|
||||
cch = fread(buf, sizeof(buf), 1, fpC);
|
||||
read_success_once |= (0 != cch);
|
||||
} while (0 != cch);
|
||||
if (!read_success_once)
|
||||
exit(2);
|
||||
if (!feof(fpC))
|
||||
exit(3);
|
||||
if (0 != fclose(fpC))
|
||||
exit(4);
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
]]
|
||||
)],
|
||||
[
|
||||
dnl We have to do this invocation manually so that we can
|
||||
dnl get the output of conftest.err to make sure it doesn't
|
||||
dnl mention gc-sections.
|
||||
if test "X$cross_compiling" = "Xyes" || grep gc-sections conftest.err ; then
|
||||
libevent_cv_gc_sections_runs=no
|
||||
else
|
||||
libevent_cv_gc_sections_runs=no
|
||||
./conftest >/dev/null 2>&1 && libevent_cv_gc_sections_runs=yes
|
||||
fi
|
||||
],
|
||||
[libevent_cv_gc_sections_runs=no]
|
||||
)
|
||||
CFLAGS="$origCFLAGS"
|
||||
AS_UNSET([origCFLAGS])
|
||||
]
|
||||
)
|
||||
case "$libevent_cv_gc_sections_runs" in
|
||||
yes)
|
||||
CFLAGS="-ffunction-sections -fdata-sections $CFLAGS"
|
||||
LIBEVENT_GC_SECTIONS="-Wl,--gc-sections"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
AC_SUBST([LIBEVENT_GC_SECTIONS])
|
||||
|
||||
AM_CONDITIONAL([INSTALL_LIBEVENT], [test "$enable_libevent_install" = "yes"])
|
||||
|
||||
AC_CONFIG_FILES( [libevent.pc libevent_openssl.pc libevent_pthreads.pc] )
|
||||
AC_OUTPUT(Makefile include/Makefile test/Makefile sample/Makefile)
|
101
external/bsd/libevent/dist/defer-internal.h
vendored
Normal file
101
external/bsd/libevent/dist/defer-internal.h
vendored
Normal file
|
@ -0,0 +1,101 @@
|
|||
/* $NetBSD: defer-internal.h,v 1.1.1.1 2013/04/11 16:43:21 christos Exp $ */
|
||||
/*
|
||||
* 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 _DEFER_INTERNAL_H_
|
||||
#define _DEFER_INTERNAL_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "event2/event-config.h"
|
||||
#include <sys/queue.h>
|
||||
|
||||
struct deferred_cb;
|
||||
|
||||
typedef void (*deferred_cb_fn)(struct deferred_cb *, void *);
|
||||
|
||||
/** A deferred_cb is a callback that can be scheduled to run as part of
|
||||
* an event_base's event_loop, rather than running immediately. */
|
||||
struct deferred_cb {
|
||||
/** Links to the adjacent active (pending) deferred_cb objects. */
|
||||
TAILQ_ENTRY (deferred_cb) cb_next;
|
||||
/** True iff this deferred_cb is pending in an event_base. */
|
||||
unsigned queued : 1;
|
||||
/** The function to execute when the callback runs. */
|
||||
deferred_cb_fn cb;
|
||||
/** The function's second argument. */
|
||||
void *arg;
|
||||
};
|
||||
|
||||
/** A deferred_cb_queue is a list of deferred_cb that we can add to and run. */
|
||||
struct deferred_cb_queue {
|
||||
/** Lock used to protect the queue. */
|
||||
void *lock;
|
||||
|
||||
/** How many entries are in the queue? */
|
||||
int active_count;
|
||||
|
||||
/** Function called when adding to the queue from another thread. */
|
||||
void (*notify_fn)(struct deferred_cb_queue *, void *);
|
||||
void *notify_arg;
|
||||
|
||||
/** Deferred callback management: a list of deferred callbacks to
|
||||
* run active the active events. */
|
||||
TAILQ_HEAD (deferred_cb_list, deferred_cb) deferred_cb_list;
|
||||
};
|
||||
|
||||
/**
|
||||
Initialize an empty, non-pending deferred_cb.
|
||||
|
||||
@param deferred The deferred_cb structure to initialize.
|
||||
@param cb The function to run when the deferred_cb executes.
|
||||
@param arg The function's second argument.
|
||||
*/
|
||||
void event_deferred_cb_init(struct deferred_cb *, deferred_cb_fn, void *);
|
||||
/**
|
||||
Cancel a deferred_cb if it is currently scheduled in an event_base.
|
||||
*/
|
||||
void event_deferred_cb_cancel(struct deferred_cb_queue *, struct deferred_cb *);
|
||||
/**
|
||||
Activate a deferred_cb if it is not currently scheduled in an event_base.
|
||||
*/
|
||||
void event_deferred_cb_schedule(struct deferred_cb_queue *, struct deferred_cb *);
|
||||
|
||||
#define LOCK_DEFERRED_QUEUE(q) \
|
||||
EVLOCK_LOCK((q)->lock, 0)
|
||||
#define UNLOCK_DEFERRED_QUEUE(q) \
|
||||
EVLOCK_UNLOCK((q)->lock, 0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
void event_deferred_cb_queue_init(struct deferred_cb_queue *);
|
||||
struct deferred_cb_queue *event_base_get_deferred_cb_queue(struct event_base *);
|
||||
|
||||
#endif /* _EVENT_INTERNAL_H_ */
|
||||
|
708
external/bsd/libevent/dist/depcomp
vendored
Executable file
708
external/bsd/libevent/dist/depcomp
vendored
Executable file
|
@ -0,0 +1,708 @@
|
|||
#! /bin/sh
|
||||
# depcomp - compile a program generating dependencies as side-effects
|
||||
|
||||
scriptversion=2012-03-27.16; # UTC
|
||||
|
||||
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2010,
|
||||
# 2011, 2012 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Run PROGRAMS ARGS to compile a file, generating dependencies
|
||||
as side-effects.
|
||||
|
||||
Environment variables:
|
||||
depmode Dependency tracking mode.
|
||||
source Source file read by 'PROGRAMS ARGS'.
|
||||
object Object file output by 'PROGRAMS ARGS'.
|
||||
DEPDIR directory where to store dependencies.
|
||||
depfile Dependency file to output.
|
||||
tmpdepfile Temporary file to use when outputting dependencies.
|
||||
libtool Whether libtool is used (yes/no).
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "depcomp $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
# A tabulation character.
|
||||
tab=' '
|
||||
# A newline character.
|
||||
nl='
|
||||
'
|
||||
|
||||
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
|
||||
echo "depcomp: Variables source, object and depmode must be set" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
|
||||
depfile=${depfile-`echo "$object" |
|
||||
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
|
||||
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
|
||||
|
||||
rm -f "$tmpdepfile"
|
||||
|
||||
# Some modes work just like other modes, but use different flags. We
|
||||
# parameterize here, but still list the modes in the big case below,
|
||||
# to make depend.m4 easier to write. Note that we *cannot* use a case
|
||||
# here, because this file can only contain one case statement.
|
||||
if test "$depmode" = hp; then
|
||||
# HP compiler uses -M and no extra arg.
|
||||
gccflag=-M
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
if test "$depmode" = dashXmstdout; then
|
||||
# This is just like dashmstdout with a different argument.
|
||||
dashmflag=-xM
|
||||
depmode=dashmstdout
|
||||
fi
|
||||
|
||||
cygpath_u="cygpath -u -f -"
|
||||
if test "$depmode" = msvcmsys; then
|
||||
# This is just like msvisualcpp but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvisualcpp
|
||||
fi
|
||||
|
||||
if test "$depmode" = msvc7msys; then
|
||||
# This is just like msvc7 but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvc7
|
||||
fi
|
||||
|
||||
if test "$depmode" = xlc; then
|
||||
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency informations.
|
||||
gccflag=-qmakedep=gcc,-MF
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
case "$depmode" in
|
||||
gcc3)
|
||||
## gcc 3 implements dependency tracking that does exactly what
|
||||
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
|
||||
## it if -MD -MP comes after the -MF stuff. Hmm.
|
||||
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
|
||||
## the command line argument order; so add the flags where they
|
||||
## appear in depend2.am. Note that the slowdown incurred here
|
||||
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
|
||||
*) set fnord "$@" "$arg" ;;
|
||||
esac
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
done
|
||||
"$@"
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
mv "$tmpdepfile" "$depfile"
|
||||
;;
|
||||
|
||||
gcc)
|
||||
## There are various ways to get dependency output from gcc. Here's
|
||||
## why we pick this rather obscure method:
|
||||
## - Don't want to use -MD because we'd like the dependencies to end
|
||||
## up in a subdir. Having to rename by hand is ugly.
|
||||
## (We might end up doing this anyway to support other compilers.)
|
||||
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
|
||||
## -MM, not -M (despite what the docs say).
|
||||
## - Using -M directly means running the compiler twice (even worse
|
||||
## than renaming).
|
||||
if test -z "$gccflag"; then
|
||||
gccflag=-MD,
|
||||
fi
|
||||
"$@" -Wp,"$gccflag$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
|
||||
## The second -e expression handles DOS-style file names with drive letters.
|
||||
sed -e 's/^[^:]*: / /' \
|
||||
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
|
||||
## This next piece of magic avoids the "deleted header file" problem.
|
||||
## The problem is that when a header file which appears in a .P file
|
||||
## is deleted, the dependency causes make to die (because there is
|
||||
## typically no way to rebuild the header). We avoid this by adding
|
||||
## dummy dependencies for each header file. Too bad gcc doesn't do
|
||||
## this for us directly.
|
||||
tr ' ' "$nl" < "$tmpdepfile" |
|
||||
## Some versions of gcc put a space before the ':'. On the theory
|
||||
## that the space means something, we add a space to the output as
|
||||
## well. hp depmode also adds that space, but also prefixes the VPATH
|
||||
## to the object. Take care to not repeat it in the output.
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
sgi)
|
||||
if test "$libtool" = yes; then
|
||||
"$@" "-Wp,-MDupdate,$tmpdepfile"
|
||||
else
|
||||
"$@" -MDupdate "$tmpdepfile"
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
|
||||
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
|
||||
echo "$object : \\" > "$depfile"
|
||||
|
||||
# Clip off the initial element (the dependent). Don't try to be
|
||||
# clever and replace this with sed code, as IRIX sed won't handle
|
||||
# lines with more than a fixed number of characters (4096 in
|
||||
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
|
||||
# the IRIX cc adds comments like '#:fec' to the end of the
|
||||
# dependency line.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
|
||||
tr "$nl" ' ' >> "$depfile"
|
||||
echo >> "$depfile"
|
||||
|
||||
# The second pass generates a dummy entry for each header file.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
|
||||
>> "$depfile"
|
||||
else
|
||||
# The sourcefile does not contain any dependencies, so just
|
||||
# store a dummy comment line, to avoid errors with the Makefile
|
||||
# "include basename.Plo" scheme.
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
xlc)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
aix)
|
||||
# The C for AIX Compiler uses -M and outputs the dependencies
|
||||
# in a .u file. In older versions, this file always lives in the
|
||||
# current directory. Also, the AIX compiler puts '$object:' at the
|
||||
# start of each line; $object doesn't have directory information.
|
||||
# Version 6 uses the directory in both cases.
|
||||
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
|
||||
test "x$dir" = "x$object" && dir=
|
||||
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$base.u
|
||||
tmpdepfile3=$dir.libs/$base.u
|
||||
"$@" -Wc,-M
|
||||
else
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$dir$base.u
|
||||
tmpdepfile3=$dir$base.u
|
||||
"$@" -M
|
||||
fi
|
||||
stat=$?
|
||||
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
# Each line is of the form 'foo.o: dependent.h'.
|
||||
# Do two passes, one to just change these to
|
||||
# '$object: dependent.h' and one to simply 'dependent.h:'.
|
||||
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
|
||||
sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
# The sourcefile does not contain any dependencies, so just
|
||||
# store a dummy comment line, to avoid errors with the Makefile
|
||||
# "include basename.Plo" scheme.
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
icc)
|
||||
# Intel's C compiler anf tcc (Tiny C Compiler) understand '-MD -MF file'.
|
||||
# However on
|
||||
# $CC -MD -MF foo.d -c -o sub/foo.o sub/foo.c
|
||||
# ICC 7.0 will fill foo.d with something like
|
||||
# foo.o: sub/foo.c
|
||||
# foo.o: sub/foo.h
|
||||
# which is wrong. We want
|
||||
# sub/foo.o: sub/foo.c
|
||||
# sub/foo.o: sub/foo.h
|
||||
# sub/foo.c:
|
||||
# sub/foo.h:
|
||||
# ICC 7.1 will output
|
||||
# foo.o: sub/foo.c sub/foo.h
|
||||
# and will wrap long lines using '\':
|
||||
# foo.o: sub/foo.c ... \
|
||||
# sub/foo.h ... \
|
||||
# ...
|
||||
# tcc 0.9.26 (FIXME still under development at the moment of writing)
|
||||
# will emit a similar output, but also prepend the continuation lines
|
||||
# with horizontal tabulation characters.
|
||||
"$@" -MD -MF "$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
# Each line is of the form 'foo.o: dependent.h',
|
||||
# or 'foo.o: dep1.h dep2.h \', or ' dep3.h dep4.h \'.
|
||||
# Do two passes, one to just change these to
|
||||
# '$object: dependent.h' and one to simply 'dependent.h:'.
|
||||
sed -e "s/^[ $tab][ $tab]*/ /" -e "s,^[^:]*:,$object :," \
|
||||
< "$tmpdepfile" > "$depfile"
|
||||
sed '
|
||||
s/[ '"$tab"'][ '"$tab"']*/ /g
|
||||
s/^ *//
|
||||
s/ *\\*$//
|
||||
s/^[^:]*: *//
|
||||
/^$/d
|
||||
/:$/d
|
||||
s/$/ :/
|
||||
' < "$tmpdepfile" >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp2)
|
||||
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
|
||||
# compilers, which have integrated preprocessors. The correct option
|
||||
# to use with these is +Maked; it writes dependencies to a file named
|
||||
# 'foo.d', which lands next to the object file, wherever that
|
||||
# happens to be.
|
||||
# Much of this is similar to the tru64 case; see comments there.
|
||||
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
|
||||
test "x$dir" = "x$object" && dir=
|
||||
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir.libs/$base.d
|
||||
"$@" -Wc,+Maked
|
||||
else
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
"$@" +Maked
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
|
||||
# Add 'dependent.h:' lines.
|
||||
sed -ne '2,${
|
||||
s/^ *//
|
||||
s/ \\*$//
|
||||
s/$/:/
|
||||
p
|
||||
}' "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile" "$tmpdepfile2"
|
||||
;;
|
||||
|
||||
tru64)
|
||||
# The Tru64 compiler uses -MD to generate dependencies as a side
|
||||
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
|
||||
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
|
||||
# dependencies in 'foo.d' instead, so we check for that too.
|
||||
# Subdirectories are respected.
|
||||
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
|
||||
test "x$dir" = "x$object" && dir=
|
||||
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
|
||||
|
||||
if test "$libtool" = yes; then
|
||||
# With Tru64 cc, shared objects can also be used to make a
|
||||
# static library. This mechanism is used in libtool 1.4 series to
|
||||
# handle both shared and static libraries in a single compilation.
|
||||
# With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
|
||||
#
|
||||
# With libtool 1.5 this exception was removed, and libtool now
|
||||
# generates 2 separate objects for the 2 libraries. These two
|
||||
# compilations output dependencies in $dir.libs/$base.o.d and
|
||||
# in $dir$base.o.d. We have to check for both files, because
|
||||
# one of the two compilations can be disabled. We should prefer
|
||||
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
|
||||
# automatically cleaned when .libs/ is deleted, while ignoring
|
||||
# the former would cause a distcleancheck panic.
|
||||
tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
|
||||
tmpdepfile2=$dir$base.o.d # libtool 1.5
|
||||
tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
|
||||
tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
|
||||
"$@" -Wc,-MD
|
||||
else
|
||||
tmpdepfile1=$dir$base.o.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
tmpdepfile3=$dir$base.d
|
||||
tmpdepfile4=$dir$base.d
|
||||
"$@" -MD
|
||||
fi
|
||||
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
|
||||
sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvc7)
|
||||
if test "$libtool" = yes; then
|
||||
showIncludes=-Wc,-showIncludes
|
||||
else
|
||||
showIncludes=-showIncludes
|
||||
fi
|
||||
"$@" $showIncludes > "$tmpdepfile"
|
||||
stat=$?
|
||||
grep -v '^Note: including file: ' "$tmpdepfile"
|
||||
if test "$stat" = 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
# The first sed program below extracts the file names and escapes
|
||||
# backslashes for cygpath. The second sed program outputs the file
|
||||
# name when reading, but also accumulates all include files in the
|
||||
# hold buffer in order to output them again at the end. This only
|
||||
# works with sed implementations that can handle large buffers.
|
||||
sed < "$tmpdepfile" -n '
|
||||
/^Note: including file: *\(.*\)/ {
|
||||
s//\1/
|
||||
s/\\/\\\\/g
|
||||
p
|
||||
}' | $cygpath_u | sort -u | sed -n '
|
||||
s/ /\\ /g
|
||||
s/\(.*\)/'"$tab"'\1 \\/p
|
||||
s/.\(.*\) \\/\1:/
|
||||
H
|
||||
$ {
|
||||
s/.*/'"$tab"'/
|
||||
G
|
||||
p
|
||||
}' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvc7msys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
#nosideeffect)
|
||||
# This comment above is used by automake to tell side-effect
|
||||
# dependency tracking mechanisms from slower ones.
|
||||
|
||||
dashmstdout)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout, regardless of -o.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove '-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
test -z "$dashmflag" && dashmflag=-M
|
||||
# Require at least two characters before searching for ':'
|
||||
# in the target name. This is to cope with DOS-style filenames:
|
||||
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
|
||||
"$@" $dashmflag |
|
||||
sed 's:^['"$tab"' ]*[^:'"$tab"' ][^:][^:]*\:['"$tab"' ]*:'"$object"'\: :' > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
cat < "$tmpdepfile" > "$depfile"
|
||||
tr ' ' "$nl" < "$tmpdepfile" | \
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
dashXmstdout)
|
||||
# This case only exists to satisfy depend.m4. It is never actually
|
||||
# run, as this mode is specially recognized in the preamble.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
makedepend)
|
||||
"$@" || exit $?
|
||||
# Remove any Libtool call
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
# X makedepend
|
||||
shift
|
||||
cleared=no eat=no
|
||||
for arg
|
||||
do
|
||||
case $cleared in
|
||||
no)
|
||||
set ""; shift
|
||||
cleared=yes ;;
|
||||
esac
|
||||
if test $eat = yes; then
|
||||
eat=no
|
||||
continue
|
||||
fi
|
||||
case "$arg" in
|
||||
-D*|-I*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
# Strip any option that makedepend may not understand. Remove
|
||||
# the object too, otherwise makedepend will parse it as a source file.
|
||||
-arch)
|
||||
eat=yes ;;
|
||||
-*|$object)
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
esac
|
||||
done
|
||||
obj_suffix=`echo "$object" | sed 's/^.*\././'`
|
||||
touch "$tmpdepfile"
|
||||
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
|
||||
rm -f "$depfile"
|
||||
# makedepend may prepend the VPATH from the source file name to the object.
|
||||
# No need to regex-escape $object, excess matching of '.' is harmless.
|
||||
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
|
||||
sed '1,2d' "$tmpdepfile" | tr ' ' "$nl" | \
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile" "$tmpdepfile".bak
|
||||
;;
|
||||
|
||||
cpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove '-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
"$@" -E |
|
||||
sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
|
||||
sed '$ s: \\$::' > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
cat < "$tmpdepfile" >> "$depfile"
|
||||
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvisualcpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case "$arg" in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
|
||||
set fnord "$@"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
"$@" -E 2>/dev/null |
|
||||
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
|
||||
echo "$tab" >> "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvcmsys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
none)
|
||||
exec "$@"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Unknown depmode $depmode" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
309
external/bsd/libevent/dist/devpoll.c
vendored
Normal file
309
external/bsd/libevent/dist/devpoll.c
vendored
Normal file
|
@ -0,0 +1,309 @@
|
|||
/* $NetBSD: devpoll.c,v 1.1.1.1 2013/04/11 16:43:24 christos Exp $ */
|
||||
/*
|
||||
* Copyright 2000-2009 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright 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.
|
||||
*/
|
||||
#include "event2/event-config.h"
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: devpoll.c,v 1.1.1.1 2013/04/11 16:43:24 christos Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/resource.h>
|
||||
#ifdef _EVENT_HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include <sys/queue.h>
|
||||
#include <sys/devpoll.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "event2/event.h"
|
||||
#include "event2/event_struct.h"
|
||||
#include "event2/thread.h"
|
||||
#include "event-internal.h"
|
||||
#include "evsignal-internal.h"
|
||||
#include "log-internal.h"
|
||||
#include "evmap-internal.h"
|
||||
#include "evthread-internal.h"
|
||||
|
||||
struct devpollop {
|
||||
struct pollfd *events;
|
||||
int nevents;
|
||||
int dpfd;
|
||||
struct pollfd *changes;
|
||||
int nchanges;
|
||||
};
|
||||
|
||||
static void *devpoll_init(struct event_base *);
|
||||
static int devpoll_add(struct event_base *, int fd, short old, short events, void *);
|
||||
static int devpoll_del(struct event_base *, int fd, short old, short events, void *);
|
||||
static int devpoll_dispatch(struct event_base *, struct timeval *);
|
||||
static void devpoll_dealloc(struct event_base *);
|
||||
|
||||
const struct eventop devpollops = {
|
||||
"devpoll",
|
||||
devpoll_init,
|
||||
devpoll_add,
|
||||
devpoll_del,
|
||||
devpoll_dispatch,
|
||||
devpoll_dealloc,
|
||||
1, /* need reinit */
|
||||
EV_FEATURE_FDS|EV_FEATURE_O1,
|
||||
0
|
||||
};
|
||||
|
||||
#define NEVENT 32000
|
||||
|
||||
static int
|
||||
devpoll_commit(struct devpollop *devpollop)
|
||||
{
|
||||
/*
|
||||
* Due to a bug in Solaris, we have to use pwrite with an offset of 0.
|
||||
* Write is limited to 2GB of data, until it will fail.
|
||||
*/
|
||||
if (pwrite(devpollop->dpfd, devpollop->changes,
|
||||
sizeof(struct pollfd) * devpollop->nchanges, 0) == -1)
|
||||
return (-1);
|
||||
|
||||
devpollop->nchanges = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
devpoll_queue(struct devpollop *devpollop, int fd, int events) {
|
||||
struct pollfd *pfd;
|
||||
|
||||
if (devpollop->nchanges >= devpollop->nevents) {
|
||||
/*
|
||||
* Change buffer is full, must commit it to /dev/poll before
|
||||
* adding more
|
||||
*/
|
||||
if (devpoll_commit(devpollop) != 0)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
pfd = &devpollop->changes[devpollop->nchanges++];
|
||||
pfd->fd = fd;
|
||||
pfd->events = events;
|
||||
pfd->revents = 0;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void *
|
||||
devpoll_init(struct event_base *base)
|
||||
{
|
||||
int dpfd, nfiles = NEVENT;
|
||||
struct rlimit rl;
|
||||
struct devpollop *devpollop;
|
||||
|
||||
if (!(devpollop = mm_calloc(1, sizeof(struct devpollop))))
|
||||
return (NULL);
|
||||
|
||||
if (getrlimit(RLIMIT_NOFILE, &rl) == 0 &&
|
||||
rl.rlim_cur != RLIM_INFINITY)
|
||||
nfiles = rl.rlim_cur;
|
||||
|
||||
/* Initialize the kernel queue */
|
||||
if ((dpfd = evutil_open_closeonexec("/dev/poll", O_RDWR, 0)) == -1) {
|
||||
event_warn("open: /dev/poll");
|
||||
mm_free(devpollop);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
devpollop->dpfd = dpfd;
|
||||
|
||||
/* Initialize fields */
|
||||
/* FIXME: allocating 'nfiles' worth of space here can be
|
||||
* expensive and unnecessary. See how epoll.c does it instead. */
|
||||
devpollop->events = mm_calloc(nfiles, sizeof(struct pollfd));
|
||||
if (devpollop->events == NULL) {
|
||||
mm_free(devpollop);
|
||||
close(dpfd);
|
||||
return (NULL);
|
||||
}
|
||||
devpollop->nevents = nfiles;
|
||||
|
||||
devpollop->changes = mm_calloc(nfiles, sizeof(struct pollfd));
|
||||
if (devpollop->changes == NULL) {
|
||||
mm_free(devpollop->events);
|
||||
mm_free(devpollop);
|
||||
close(dpfd);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
evsig_init(base);
|
||||
|
||||
return (devpollop);
|
||||
}
|
||||
|
||||
static int
|
||||
devpoll_dispatch(struct event_base *base, struct timeval *tv)
|
||||
{
|
||||
struct devpollop *devpollop = base->evbase;
|
||||
struct pollfd *events = devpollop->events;
|
||||
struct dvpoll dvp;
|
||||
int i, res, timeout = -1;
|
||||
|
||||
if (devpollop->nchanges)
|
||||
devpoll_commit(devpollop);
|
||||
|
||||
if (tv != NULL)
|
||||
timeout = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
|
||||
|
||||
dvp.dp_fds = devpollop->events;
|
||||
dvp.dp_nfds = devpollop->nevents;
|
||||
dvp.dp_timeout = timeout;
|
||||
|
||||
EVBASE_RELEASE_LOCK(base, th_base_lock);
|
||||
|
||||
res = ioctl(devpollop->dpfd, DP_POLL, &dvp);
|
||||
|
||||
EVBASE_ACQUIRE_LOCK(base, th_base_lock);
|
||||
|
||||
if (res == -1) {
|
||||
if (errno != EINTR) {
|
||||
event_warn("ioctl: DP_POLL");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
event_debug(("%s: devpoll_wait reports %d", __func__, res));
|
||||
|
||||
for (i = 0; i < res; i++) {
|
||||
int which = 0;
|
||||
int what = events[i].revents;
|
||||
|
||||
if (what & POLLHUP)
|
||||
what |= POLLIN | POLLOUT;
|
||||
else if (what & POLLERR)
|
||||
what |= POLLIN | POLLOUT;
|
||||
|
||||
if (what & POLLIN)
|
||||
which |= EV_READ;
|
||||
if (what & POLLOUT)
|
||||
which |= EV_WRITE;
|
||||
|
||||
if (!which)
|
||||
continue;
|
||||
|
||||
/* XXX(niels): not sure if this works for devpoll */
|
||||
evmap_io_active(base, events[i].fd, which);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
devpoll_add(struct event_base *base, int fd, short old, short events, void *p)
|
||||
{
|
||||
struct devpollop *devpollop = base->evbase;
|
||||
int res;
|
||||
(void)p;
|
||||
|
||||
/*
|
||||
* It's not necessary to OR the existing read/write events that we
|
||||
* are currently interested in with the new event we are adding.
|
||||
* The /dev/poll driver ORs any new events with the existing events
|
||||
* that it has cached for the fd.
|
||||
*/
|
||||
|
||||
res = 0;
|
||||
if (events & EV_READ)
|
||||
res |= POLLIN;
|
||||
if (events & EV_WRITE)
|
||||
res |= POLLOUT;
|
||||
|
||||
if (devpoll_queue(devpollop, fd, res) != 0)
|
||||
return (-1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
devpoll_del(struct event_base *base, int fd, short old, short events, void *p)
|
||||
{
|
||||
struct devpollop *devpollop = base->evbase;
|
||||
int res;
|
||||
(void)p;
|
||||
|
||||
res = 0;
|
||||
if (events & EV_READ)
|
||||
res |= POLLIN;
|
||||
if (events & EV_WRITE)
|
||||
res |= POLLOUT;
|
||||
|
||||
/*
|
||||
* The only way to remove an fd from the /dev/poll monitored set is
|
||||
* to use POLLREMOVE by itself. This removes ALL events for the fd
|
||||
* provided so if we care about two events and are only removing one
|
||||
* we must re-add the other event after POLLREMOVE.
|
||||
*/
|
||||
|
||||
if (devpoll_queue(devpollop, fd, POLLREMOVE) != 0)
|
||||
return (-1);
|
||||
|
||||
if ((res & (POLLIN|POLLOUT)) != (POLLIN|POLLOUT)) {
|
||||
/*
|
||||
* We're not deleting all events, so we must resubmit the
|
||||
* event that we are still interested in if one exists.
|
||||
*/
|
||||
|
||||
if ((res & POLLIN) && (old & EV_WRITE)) {
|
||||
/* Deleting read, still care about write */
|
||||
devpoll_queue(devpollop, fd, POLLOUT);
|
||||
} else if ((res & POLLOUT) && (old & EV_READ)) {
|
||||
/* Deleting write, still care about read */
|
||||
devpoll_queue(devpollop, fd, POLLIN);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
devpoll_dealloc(struct event_base *base)
|
||||
{
|
||||
struct devpollop *devpollop = base->evbase;
|
||||
|
||||
evsig_dealloc(base);
|
||||
if (devpollop->events)
|
||||
mm_free(devpollop->events);
|
||||
if (devpollop->changes)
|
||||
mm_free(devpollop->changes);
|
||||
if (devpollop->dpfd >= 0)
|
||||
close(devpollop->dpfd);
|
||||
|
||||
memset(devpollop, 0, sizeof(struct devpollop));
|
||||
mm_free(devpollop);
|
||||
}
|
476
external/bsd/libevent/dist/epoll.c
vendored
Normal file
476
external/bsd/libevent/dist/epoll.c
vendored
Normal file
|
@ -0,0 +1,476 @@
|
|||
/* $NetBSD: epoll.c,v 1.1.1.1 2013/04/11 16:43:19 christos Exp $ */
|
||||
/*
|
||||
* Copyright 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright 2007-2012 Niels Provos, 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.
|
||||
*/
|
||||
#include "event2/event-config.h"
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: epoll.c,v 1.1.1.1 2013/04/11 16:43:19 christos Exp $");
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/resource.h>
|
||||
#ifdef _EVENT_HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include <sys/queue.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <signal.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#ifdef _EVENT_HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include "event-internal.h"
|
||||
#include "evsignal-internal.h"
|
||||
#include "event2/thread.h"
|
||||
#include "evthread-internal.h"
|
||||
#include "log-internal.h"
|
||||
#include "evmap-internal.h"
|
||||
#include "changelist-internal.h"
|
||||
|
||||
struct epollop {
|
||||
struct epoll_event *events;
|
||||
int nevents;
|
||||
int epfd;
|
||||
};
|
||||
|
||||
static void *epoll_init(struct event_base *);
|
||||
static int epoll_dispatch(struct event_base *, struct timeval *);
|
||||
static void epoll_dealloc(struct event_base *);
|
||||
|
||||
static const struct eventop epollops_changelist = {
|
||||
"epoll (with changelist)",
|
||||
epoll_init,
|
||||
event_changelist_add,
|
||||
event_changelist_del,
|
||||
epoll_dispatch,
|
||||
epoll_dealloc,
|
||||
1, /* need reinit */
|
||||
EV_FEATURE_ET|EV_FEATURE_O1,
|
||||
EVENT_CHANGELIST_FDINFO_SIZE
|
||||
};
|
||||
|
||||
|
||||
static int epoll_nochangelist_add(struct event_base *base, evutil_socket_t fd,
|
||||
short old, short events, void *p);
|
||||
static int epoll_nochangelist_del(struct event_base *base, evutil_socket_t fd,
|
||||
short old, short events, void *p);
|
||||
|
||||
const struct eventop epollops = {
|
||||
"epoll",
|
||||
epoll_init,
|
||||
epoll_nochangelist_add,
|
||||
epoll_nochangelist_del,
|
||||
epoll_dispatch,
|
||||
epoll_dealloc,
|
||||
1, /* need reinit */
|
||||
EV_FEATURE_ET|EV_FEATURE_O1,
|
||||
0
|
||||
};
|
||||
|
||||
#define INITIAL_NEVENT 32
|
||||
#define MAX_NEVENT 4096
|
||||
|
||||
/* On Linux kernels at least up to 2.6.24.4, epoll can't handle timeout
|
||||
* values bigger than (LONG_MAX - 999ULL)/HZ. HZ in the wild can be
|
||||
* as big as 1000, and LONG_MAX can be as small as (1<<31)-1, so the
|
||||
* largest number of msec we can support here is 2147482. Let's
|
||||
* round that down by 47 seconds.
|
||||
*/
|
||||
#define MAX_EPOLL_TIMEOUT_MSEC (35*60*1000)
|
||||
|
||||
static void *
|
||||
epoll_init(struct event_base *base)
|
||||
{
|
||||
int epfd;
|
||||
struct epollop *epollop;
|
||||
|
||||
/* Initialize the kernel queue. (The size field is ignored since
|
||||
* 2.6.8.) */
|
||||
if ((epfd = epoll_create(32000)) == -1) {
|
||||
if (errno != ENOSYS)
|
||||
event_warn("epoll_create");
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
evutil_make_socket_closeonexec(epfd);
|
||||
|
||||
if (!(epollop = mm_calloc(1, sizeof(struct epollop)))) {
|
||||
close(epfd);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
epollop->epfd = epfd;
|
||||
|
||||
/* Initialize fields */
|
||||
epollop->events = mm_calloc(INITIAL_NEVENT, sizeof(struct epoll_event));
|
||||
if (epollop->events == NULL) {
|
||||
mm_free(epollop);
|
||||
close(epfd);
|
||||
return (NULL);
|
||||
}
|
||||
epollop->nevents = INITIAL_NEVENT;
|
||||
|
||||
if ((base->flags & EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST) != 0 ||
|
||||
((base->flags & EVENT_BASE_FLAG_IGNORE_ENV) == 0 &&
|
||||
evutil_getenv("EVENT_EPOLL_USE_CHANGELIST") != NULL))
|
||||
base->evsel = &epollops_changelist;
|
||||
|
||||
evsig_init(base);
|
||||
|
||||
return (epollop);
|
||||
}
|
||||
|
||||
static const char *
|
||||
change_to_string(int change)
|
||||
{
|
||||
change &= (EV_CHANGE_ADD|EV_CHANGE_DEL);
|
||||
if (change == EV_CHANGE_ADD) {
|
||||
return "add";
|
||||
} else if (change == EV_CHANGE_DEL) {
|
||||
return "del";
|
||||
} else if (change == 0) {
|
||||
return "none";
|
||||
} else {
|
||||
return "???";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *
|
||||
epoll_op_to_string(int op)
|
||||
{
|
||||
return op == EPOLL_CTL_ADD?"ADD":
|
||||
op == EPOLL_CTL_DEL?"DEL":
|
||||
op == EPOLL_CTL_MOD?"MOD":
|
||||
"???";
|
||||
}
|
||||
|
||||
static int
|
||||
epoll_apply_one_change(struct event_base *base,
|
||||
struct epollop *epollop,
|
||||
const struct event_change *ch)
|
||||
{
|
||||
struct epoll_event epev;
|
||||
int op, events = 0;
|
||||
|
||||
if (1) {
|
||||
/* The logic here is a little tricky. If we had no events set
|
||||
on the fd before, we need to set op="ADD" and set
|
||||
events=the events we want to add. If we had any events set
|
||||
on the fd before, and we want any events to remain on the
|
||||
fd, we need to say op="MOD" and set events=the events we
|
||||
want to remain. But if we want to delete the last event,
|
||||
we say op="DEL" and set events=the remaining events. What
|
||||
fun!
|
||||
*/
|
||||
|
||||
/* TODO: Turn this into a switch or a table lookup. */
|
||||
|
||||
if ((ch->read_change & EV_CHANGE_ADD) ||
|
||||
(ch->write_change & EV_CHANGE_ADD)) {
|
||||
/* If we are adding anything at all, we'll want to do
|
||||
* either an ADD or a MOD. */
|
||||
events = 0;
|
||||
op = EPOLL_CTL_ADD;
|
||||
if (ch->read_change & EV_CHANGE_ADD) {
|
||||
events |= EPOLLIN;
|
||||
} else if (ch->read_change & EV_CHANGE_DEL) {
|
||||
;
|
||||
} else if (ch->old_events & EV_READ) {
|
||||
events |= EPOLLIN;
|
||||
}
|
||||
if (ch->write_change & EV_CHANGE_ADD) {
|
||||
events |= EPOLLOUT;
|
||||
} else if (ch->write_change & EV_CHANGE_DEL) {
|
||||
;
|
||||
} else if (ch->old_events & EV_WRITE) {
|
||||
events |= EPOLLOUT;
|
||||
}
|
||||
if ((ch->read_change|ch->write_change) & EV_ET)
|
||||
events |= EPOLLET;
|
||||
|
||||
if (ch->old_events) {
|
||||
/* If MOD fails, we retry as an ADD, and if
|
||||
* ADD fails we will retry as a MOD. So the
|
||||
* only hard part here is to guess which one
|
||||
* will work. As a heuristic, we'll try
|
||||
* MOD first if we think there were old
|
||||
* events and ADD if we think there were none.
|
||||
*
|
||||
* We can be wrong about the MOD if the file
|
||||
* has in fact been closed and re-opened.
|
||||
*
|
||||
* We can be wrong about the ADD if the
|
||||
* the fd has been re-created with a dup()
|
||||
* of the same file that it was before.
|
||||
*/
|
||||
op = EPOLL_CTL_MOD;
|
||||
}
|
||||
} else if ((ch->read_change & EV_CHANGE_DEL) ||
|
||||
(ch->write_change & EV_CHANGE_DEL)) {
|
||||
/* If we're deleting anything, we'll want to do a MOD
|
||||
* or a DEL. */
|
||||
op = EPOLL_CTL_DEL;
|
||||
|
||||
if (ch->read_change & EV_CHANGE_DEL) {
|
||||
if (ch->write_change & EV_CHANGE_DEL) {
|
||||
events = EPOLLIN|EPOLLOUT;
|
||||
} else if (ch->old_events & EV_WRITE) {
|
||||
events = EPOLLOUT;
|
||||
op = EPOLL_CTL_MOD;
|
||||
} else {
|
||||
events = EPOLLIN;
|
||||
}
|
||||
} else if (ch->write_change & EV_CHANGE_DEL) {
|
||||
if (ch->old_events & EV_READ) {
|
||||
events = EPOLLIN;
|
||||
op = EPOLL_CTL_MOD;
|
||||
} else {
|
||||
events = EPOLLOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!events)
|
||||
return 0;
|
||||
|
||||
memset(&epev, 0, sizeof(epev));
|
||||
epev.data.fd = ch->fd;
|
||||
epev.events = events;
|
||||
if (epoll_ctl(epollop->epfd, op, ch->fd, &epev) == -1) {
|
||||
if (op == EPOLL_CTL_MOD && errno == ENOENT) {
|
||||
/* If a MOD operation fails with ENOENT, the
|
||||
* fd was probably closed and re-opened. We
|
||||
* should retry the operation as an ADD.
|
||||
*/
|
||||
if (epoll_ctl(epollop->epfd, EPOLL_CTL_ADD, ch->fd, &epev) == -1) {
|
||||
event_warn("Epoll MOD(%d) on %d retried as ADD; that failed too",
|
||||
(int)epev.events, ch->fd);
|
||||
return -1;
|
||||
} else {
|
||||
event_debug(("Epoll MOD(%d) on %d retried as ADD; succeeded.",
|
||||
(int)epev.events,
|
||||
ch->fd));
|
||||
}
|
||||
} else if (op == EPOLL_CTL_ADD && errno == EEXIST) {
|
||||
/* If an ADD operation fails with EEXIST,
|
||||
* either the operation was redundant (as with a
|
||||
* precautionary add), or we ran into a fun
|
||||
* kernel bug where using dup*() to duplicate the
|
||||
* same file into the same fd gives you the same epitem
|
||||
* rather than a fresh one. For the second case,
|
||||
* we must retry with MOD. */
|
||||
if (epoll_ctl(epollop->epfd, EPOLL_CTL_MOD, ch->fd, &epev) == -1) {
|
||||
event_warn("Epoll ADD(%d) on %d retried as MOD; that failed too",
|
||||
(int)epev.events, ch->fd);
|
||||
return -1;
|
||||
} else {
|
||||
event_debug(("Epoll ADD(%d) on %d retried as MOD; succeeded.",
|
||||
(int)epev.events,
|
||||
ch->fd));
|
||||
}
|
||||
} else if (op == EPOLL_CTL_DEL &&
|
||||
(errno == ENOENT || errno == EBADF ||
|
||||
errno == EPERM)) {
|
||||
/* If a delete fails with one of these errors,
|
||||
* that's fine too: we closed the fd before we
|
||||
* got around to calling epoll_dispatch. */
|
||||
event_debug(("Epoll DEL(%d) on fd %d gave %s: DEL was unnecessary.",
|
||||
(int)epev.events,
|
||||
ch->fd,
|
||||
strerror(errno)));
|
||||
} else {
|
||||
event_warn("Epoll %s(%d) on fd %d failed. Old events were %d; read change was %d (%s); write change was %d (%s)",
|
||||
epoll_op_to_string(op),
|
||||
(int)epev.events,
|
||||
ch->fd,
|
||||
ch->old_events,
|
||||
ch->read_change,
|
||||
change_to_string(ch->read_change),
|
||||
ch->write_change,
|
||||
change_to_string(ch->write_change));
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
event_debug(("Epoll %s(%d) on fd %d okay. [old events were %d; read change was %d; write change was %d]",
|
||||
epoll_op_to_string(op),
|
||||
(int)epev.events,
|
||||
(int)ch->fd,
|
||||
ch->old_events,
|
||||
ch->read_change,
|
||||
ch->write_change));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
epoll_apply_changes(struct event_base *base)
|
||||
{
|
||||
struct event_changelist *changelist = &base->changelist;
|
||||
struct epollop *epollop = base->evbase;
|
||||
struct event_change *ch;
|
||||
|
||||
int r = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < changelist->n_changes; ++i) {
|
||||
ch = &changelist->changes[i];
|
||||
if (epoll_apply_one_change(base, epollop, ch) < 0)
|
||||
r = -1;
|
||||
}
|
||||
|
||||
return (r);
|
||||
}
|
||||
|
||||
static int
|
||||
epoll_nochangelist_add(struct event_base *base, evutil_socket_t fd,
|
||||
short old, short events, void *p)
|
||||
{
|
||||
struct event_change ch;
|
||||
ch.fd = fd;
|
||||
ch.old_events = old;
|
||||
ch.read_change = ch.write_change = 0;
|
||||
if (events & EV_WRITE)
|
||||
ch.write_change = EV_CHANGE_ADD |
|
||||
(events & EV_ET);
|
||||
if (events & EV_READ)
|
||||
ch.read_change = EV_CHANGE_ADD |
|
||||
(events & EV_ET);
|
||||
|
||||
return epoll_apply_one_change(base, base->evbase, &ch);
|
||||
}
|
||||
|
||||
static int
|
||||
epoll_nochangelist_del(struct event_base *base, evutil_socket_t fd,
|
||||
short old, short events, void *p)
|
||||
{
|
||||
struct event_change ch;
|
||||
ch.fd = fd;
|
||||
ch.old_events = old;
|
||||
ch.read_change = ch.write_change = 0;
|
||||
if (events & EV_WRITE)
|
||||
ch.write_change = EV_CHANGE_DEL;
|
||||
if (events & EV_READ)
|
||||
ch.read_change = EV_CHANGE_DEL;
|
||||
|
||||
return epoll_apply_one_change(base, base->evbase, &ch);
|
||||
}
|
||||
|
||||
static int
|
||||
epoll_dispatch(struct event_base *base, struct timeval *tv)
|
||||
{
|
||||
struct epollop *epollop = base->evbase;
|
||||
struct epoll_event *events = epollop->events;
|
||||
int i, res;
|
||||
long timeout = -1;
|
||||
|
||||
if (tv != NULL) {
|
||||
timeout = evutil_tv_to_msec(tv);
|
||||
if (timeout < 0 || timeout > MAX_EPOLL_TIMEOUT_MSEC) {
|
||||
/* Linux kernels can wait forever if the timeout is
|
||||
* too big; see comment on MAX_EPOLL_TIMEOUT_MSEC. */
|
||||
timeout = MAX_EPOLL_TIMEOUT_MSEC;
|
||||
}
|
||||
}
|
||||
|
||||
epoll_apply_changes(base);
|
||||
event_changelist_remove_all(&base->changelist, base);
|
||||
|
||||
EVBASE_RELEASE_LOCK(base, th_base_lock);
|
||||
|
||||
res = epoll_wait(epollop->epfd, events, epollop->nevents, timeout);
|
||||
|
||||
EVBASE_ACQUIRE_LOCK(base, th_base_lock);
|
||||
|
||||
if (res == -1) {
|
||||
if (errno != EINTR) {
|
||||
event_warn("epoll_wait");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
event_debug(("%s: epoll_wait reports %d", __func__, res));
|
||||
EVUTIL_ASSERT(res <= epollop->nevents);
|
||||
|
||||
for (i = 0; i < res; i++) {
|
||||
int what = events[i].events;
|
||||
short ev = 0;
|
||||
|
||||
if (what & (EPOLLHUP|EPOLLERR)) {
|
||||
ev = EV_READ | EV_WRITE;
|
||||
} else {
|
||||
if (what & EPOLLIN)
|
||||
ev |= EV_READ;
|
||||
if (what & EPOLLOUT)
|
||||
ev |= EV_WRITE;
|
||||
}
|
||||
|
||||
if (!ev)
|
||||
continue;
|
||||
|
||||
evmap_io_active(base, events[i].data.fd, ev | EV_ET);
|
||||
}
|
||||
|
||||
if (res == epollop->nevents && epollop->nevents < MAX_NEVENT) {
|
||||
/* We used all of the event space this time. We should
|
||||
be ready for more events next time. */
|
||||
int new_nevents = epollop->nevents * 2;
|
||||
struct epoll_event *new_events;
|
||||
|
||||
new_events = mm_realloc(epollop->events,
|
||||
new_nevents * sizeof(struct epoll_event));
|
||||
if (new_events) {
|
||||
epollop->events = new_events;
|
||||
epollop->nevents = new_nevents;
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
epoll_dealloc(struct event_base *base)
|
||||
{
|
||||
struct epollop *epollop = base->evbase;
|
||||
|
||||
evsig_dealloc(base);
|
||||
if (epollop->events)
|
||||
mm_free(epollop->events);
|
||||
if (epollop->epfd >= 0)
|
||||
close(epollop->epfd);
|
||||
|
||||
memset(epollop, 0, sizeof(struct epollop));
|
||||
mm_free(epollop);
|
||||
}
|
53
external/bsd/libevent/dist/epoll_sub.c
vendored
Normal file
53
external/bsd/libevent/dist/epoll_sub.c
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
/* $NetBSD: epoll_sub.c,v 1.1.1.1 2013/04/11 16:43:26 christos Exp $ */
|
||||
/*
|
||||
* Copyright 2003-2009 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright 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.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int
|
||||
epoll_create(int size)
|
||||
{
|
||||
return (syscall(__NR_epoll_create, size));
|
||||
}
|
||||
|
||||
int
|
||||
epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
|
||||
{
|
||||
|
||||
return (syscall(__NR_epoll_ctl, epfd, op, fd, event));
|
||||
}
|
||||
|
||||
int
|
||||
epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
|
||||
{
|
||||
return (syscall(__NR_epoll_wait, epfd, events, maxevents, timeout));
|
||||
}
|
282
external/bsd/libevent/dist/evbuffer-internal.h
vendored
Normal file
282
external/bsd/libevent/dist/evbuffer-internal.h
vendored
Normal file
|
@ -0,0 +1,282 @@
|
|||
/* $NetBSD: evbuffer-internal.h,v 1.2 2013/04/11 16:56:41 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* 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 _EVBUFFER_INTERNAL_H_
|
||||
#define _EVBUFFER_INTERNAL_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "event2/event-config.h"
|
||||
#include "event2/util.h"
|
||||
#include "util-internal.h"
|
||||
#include "defer-internal.h"
|
||||
|
||||
/* Experimental cb flag: "never deferred." Implementation note:
|
||||
* these callbacks may get an inaccurate view of n_del/n_added in their
|
||||
* arguments. */
|
||||
#define EVBUFFER_CB_NODEFER 2
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
#include <sys/queue.h>
|
||||
|
||||
/* Minimum allocation for a chain. We define this so that we're burning no
|
||||
* more than 5% of each allocation on overhead. It would be nice to lose even
|
||||
* less space, though. */
|
||||
#if _EVENT_SIZEOF_VOID_P < 8
|
||||
#define MIN_BUFFER_SIZE 512
|
||||
#else
|
||||
#define MIN_BUFFER_SIZE 1024
|
||||
#endif
|
||||
|
||||
/** A single evbuffer callback for an evbuffer. This function will be invoked
|
||||
* when bytes are added to or removed from the evbuffer. */
|
||||
struct evbuffer_cb_entry {
|
||||
/** Structures to implement a doubly-linked queue of callbacks */
|
||||
TAILQ_ENTRY(evbuffer_cb_entry) next;
|
||||
/** The callback function to invoke when this callback is called.
|
||||
If EVBUFFER_CB_OBSOLETE is set in flags, the cb_obsolete field is
|
||||
valid; otherwise, cb_func is valid. */
|
||||
union {
|
||||
evbuffer_cb_func cb_func;
|
||||
evbuffer_cb cb_obsolete;
|
||||
} cb;
|
||||
/** Argument to pass to cb. */
|
||||
void *cbarg;
|
||||
/** Currently set flags on this callback. */
|
||||
ev_uint32_t flags;
|
||||
};
|
||||
|
||||
struct bufferevent;
|
||||
struct evbuffer_chain;
|
||||
struct evbuffer {
|
||||
/** The first chain in this buffer's linked list of chains. */
|
||||
struct evbuffer_chain *first;
|
||||
/** The last chain in this buffer's linked list of chains. */
|
||||
struct evbuffer_chain *last;
|
||||
|
||||
/** Pointer to the next pointer pointing at the 'last_with_data' chain.
|
||||
*
|
||||
* To unpack:
|
||||
*
|
||||
* The last_with_data chain is the last chain that has any data in it.
|
||||
* If all chains in the buffer are empty, it is the first chain.
|
||||
* If the buffer has no chains, it is NULL.
|
||||
*
|
||||
* The last_with_datap pointer points at _whatever 'next' pointer_
|
||||
* points at the last_with_datap chain. If the last_with_data chain
|
||||
* is the first chain, or it is NULL, then the last_with_datap pointer
|
||||
* is &buf->first.
|
||||
*/
|
||||
struct evbuffer_chain **last_with_datap;
|
||||
|
||||
/** Total amount of bytes stored in all chains.*/
|
||||
size_t total_len;
|
||||
|
||||
/** Number of bytes we have added to the buffer since we last tried to
|
||||
* invoke callbacks. */
|
||||
size_t n_add_for_cb;
|
||||
/** Number of bytes we have removed from the buffer since we last
|
||||
* tried to invoke callbacks. */
|
||||
size_t n_del_for_cb;
|
||||
|
||||
#ifndef _EVENT_DISABLE_THREAD_SUPPORT
|
||||
/** A lock used to mediate access to this buffer. */
|
||||
void *lock;
|
||||
#endif
|
||||
/** True iff we should free the lock field when we free this
|
||||
* evbuffer. */
|
||||
unsigned own_lock : 1;
|
||||
/** True iff we should not allow changes to the front of the buffer
|
||||
* (drains or prepends). */
|
||||
unsigned freeze_start : 1;
|
||||
/** True iff we should not allow changes to the end of the buffer
|
||||
* (appends) */
|
||||
unsigned freeze_end : 1;
|
||||
/** True iff this evbuffer's callbacks are not invoked immediately
|
||||
* upon a change in the buffer, but instead are deferred to be invoked
|
||||
* from the event_base's loop. Useful for preventing enormous stack
|
||||
* overflows when we have mutually recursive callbacks, and for
|
||||
* serializing callbacks in a single thread. */
|
||||
unsigned deferred_cbs : 1;
|
||||
#ifdef WIN32
|
||||
/** True iff this buffer is set up for overlapped IO. */
|
||||
unsigned is_overlapped : 1;
|
||||
#endif
|
||||
/** Zero or more EVBUFFER_FLAG_* bits */
|
||||
ev_uint32_t flags;
|
||||
|
||||
/** Used to implement deferred callbacks. */
|
||||
struct deferred_cb_queue *cb_queue;
|
||||
|
||||
/** A reference count on this evbuffer. When the reference count
|
||||
* reaches 0, the buffer is destroyed. Manipulated with
|
||||
* evbuffer_incref and evbuffer_decref_and_unlock and
|
||||
* evbuffer_free. */
|
||||
int refcnt;
|
||||
|
||||
/** A deferred_cb handle to make all of this buffer's callbacks
|
||||
* invoked from the event loop. */
|
||||
struct deferred_cb deferred;
|
||||
|
||||
/** A doubly-linked-list of callback functions */
|
||||
TAILQ_HEAD(evbuffer_cb_queue, evbuffer_cb_entry) callbacks;
|
||||
|
||||
/** The parent bufferevent object this evbuffer belongs to.
|
||||
* NULL if the evbuffer stands alone. */
|
||||
struct bufferevent *parent;
|
||||
};
|
||||
|
||||
/** A single item in an evbuffer. */
|
||||
struct evbuffer_chain {
|
||||
/** points to next buffer in the chain */
|
||||
struct evbuffer_chain *next;
|
||||
|
||||
/** total allocation available in the buffer field. */
|
||||
size_t buffer_len;
|
||||
|
||||
/** unused space at the beginning of buffer or an offset into a
|
||||
* file for sendfile buffers. */
|
||||
ev_off_t misalign;
|
||||
|
||||
/** Offset into buffer + misalign at which to start writing.
|
||||
* In other words, the total number of bytes actually stored
|
||||
* in buffer. */
|
||||
size_t off;
|
||||
|
||||
/** Set if special handling is required for this chain */
|
||||
unsigned flags;
|
||||
#define EVBUFFER_MMAP 0x0001 /**< memory in buffer is mmaped */
|
||||
#define EVBUFFER_SENDFILE 0x0002 /**< a chain used for sendfile */
|
||||
#define EVBUFFER_REFERENCE 0x0004 /**< a chain with a mem reference */
|
||||
#define EVBUFFER_IMMUTABLE 0x0008 /**< read-only chain */
|
||||
/** a chain that mustn't be reallocated or freed, or have its contents
|
||||
* memmoved, until the chain is un-pinned. */
|
||||
#define EVBUFFER_MEM_PINNED_R 0x0010
|
||||
#define EVBUFFER_MEM_PINNED_W 0x0020
|
||||
#define EVBUFFER_MEM_PINNED_ANY (EVBUFFER_MEM_PINNED_R|EVBUFFER_MEM_PINNED_W)
|
||||
/** a chain that should be freed, but can't be freed until it is
|
||||
* un-pinned. */
|
||||
#define EVBUFFER_DANGLING 0x0040
|
||||
|
||||
/** Usually points to the read-write memory belonging to this
|
||||
* buffer allocated as part of the evbuffer_chain allocation.
|
||||
* For mmap, this can be a read-only buffer and
|
||||
* EVBUFFER_IMMUTABLE will be set in flags. For sendfile, it
|
||||
* may point to NULL.
|
||||
*/
|
||||
unsigned char *buffer;
|
||||
};
|
||||
|
||||
/* this is currently used by both mmap and sendfile */
|
||||
/* TODO(niels): something strange needs to happen for Windows here, I am not
|
||||
* sure what that is, but it needs to get looked into.
|
||||
*/
|
||||
struct evbuffer_chain_fd {
|
||||
int fd; /**< the fd associated with this chain */
|
||||
};
|
||||
|
||||
/** callback for a reference buffer; lets us know what to do with it when
|
||||
* we're done with it. */
|
||||
struct evbuffer_chain_reference {
|
||||
evbuffer_ref_cleanup_cb cleanupfn;
|
||||
void *extra;
|
||||
};
|
||||
|
||||
#define EVBUFFER_CHAIN_SIZE sizeof(struct evbuffer_chain)
|
||||
/** Return a pointer to extra data allocated along with an evbuffer. */
|
||||
#define EVBUFFER_CHAIN_EXTRA(t, c) (t *)((struct evbuffer_chain *)(c) + 1)
|
||||
|
||||
/** Assert that we are holding the lock on an evbuffer */
|
||||
#define ASSERT_EVBUFFER_LOCKED(buffer) \
|
||||
EVLOCK_ASSERT_LOCKED((buffer)->lock)
|
||||
|
||||
#define EVBUFFER_LOCK(buffer) \
|
||||
do { \
|
||||
EVLOCK_LOCK((buffer)->lock, 0); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define EVBUFFER_UNLOCK(buffer) \
|
||||
do { \
|
||||
EVLOCK_UNLOCK((buffer)->lock, 0); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define EVBUFFER_LOCK2(buffer1, buffer2) \
|
||||
do { \
|
||||
EVLOCK_LOCK2((buffer1)->lock, (buffer2)->lock, 0, 0); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define EVBUFFER_UNLOCK2(buffer1, buffer2) \
|
||||
do { \
|
||||
EVLOCK_UNLOCK2((buffer1)->lock, (buffer2)->lock, 0, 0); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/** Increase the reference count of buf by one. */
|
||||
void _evbuffer_incref(struct evbuffer *buf);
|
||||
/** Increase the reference count of buf by one and acquire the lock. */
|
||||
void _evbuffer_incref_and_lock(struct evbuffer *buf);
|
||||
/** Pin a single buffer chain using a given flag. A pinned chunk may not be
|
||||
* moved or freed until it is unpinned. */
|
||||
void _evbuffer_chain_pin(struct evbuffer_chain *chain, unsigned flag);
|
||||
/** Unpin a single buffer chain using a given flag. */
|
||||
void _evbuffer_chain_unpin(struct evbuffer_chain *chain, unsigned flag);
|
||||
/** As evbuffer_free, but requires that we hold a lock on the buffer, and
|
||||
* releases the lock before freeing it and the buffer. */
|
||||
void _evbuffer_decref_and_unlock(struct evbuffer *buffer);
|
||||
|
||||
/** As evbuffer_expand, but does not guarantee that the newly allocated memory
|
||||
* is contiguous. Instead, it may be split across two or more chunks. */
|
||||
int _evbuffer_expand_fast(struct evbuffer *, size_t, int);
|
||||
|
||||
/** Helper: prepares for a readv/WSARecv call by expanding the buffer to
|
||||
* hold enough memory to read 'howmuch' bytes in possibly noncontiguous memory.
|
||||
* Sets up the one or two iovecs in 'vecs' to point to the free memory and its
|
||||
* extent, and *chainp to point to the first chain that we'll try to read into.
|
||||
* Returns the number of vecs used.
|
||||
*/
|
||||
int _evbuffer_read_setup_vecs(struct evbuffer *buf, ev_ssize_t howmuch,
|
||||
struct evbuffer_iovec *vecs, int n_vecs, struct evbuffer_chain ***chainp,
|
||||
int exact);
|
||||
|
||||
/* Helper macro: copies an evbuffer_iovec in ei to a win32 WSABUF in i. */
|
||||
#define WSABUF_FROM_EVBUFFER_IOV(i,ei) do { \
|
||||
(i)->buf = (ei)->iov_base; \
|
||||
(i)->len = (unsigned long)(ei)->iov_len; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
/* XXXX the cast above is safe for now, but not if we allow mmaps on win64.
|
||||
* See note in buffer_iocp's launch_write function */
|
||||
|
||||
/** Set the parent bufferevent object for buf to bev */
|
||||
void evbuffer_set_parent(struct evbuffer *buf, struct bufferevent *bev);
|
||||
|
||||
void evbuffer_invoke_callbacks(struct evbuffer *buf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _EVBUFFER_INTERNAL_H_ */
|
4658
external/bsd/libevent/dist/evdns.c
vendored
Normal file
4658
external/bsd/libevent/dist/evdns.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
46
external/bsd/libevent/dist/evdns.h
vendored
Normal file
46
external/bsd/libevent/dist/evdns.h
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
/* $NetBSD: evdns.h,v 1.1.1.2 2013/04/11 16:43:28 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* 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 _EVDNS_H_
|
||||
#define _EVDNS_H_
|
||||
|
||||
/** @file evdns.h
|
||||
|
||||
A dns subsystem for Libevent.
|
||||
|
||||
The <evdns.h> header is deprecated in Libevent 2.0 and later; please
|
||||
use <event2/evdns.h> instead. Depending on what functionality you
|
||||
need, you may also want to include more of the other <event2/...>
|
||||
headers.
|
||||
*/
|
||||
|
||||
#include <event.h>
|
||||
#include <event2/dns.h>
|
||||
#include <event2/dns_compat.h>
|
||||
#include <event2/dns_struct.h>
|
||||
|
||||
#endif /* _EVDNS_H_ */
|
369
external/bsd/libevent/dist/event-internal.h
vendored
Normal file
369
external/bsd/libevent/dist/event-internal.h
vendored
Normal file
|
@ -0,0 +1,369 @@
|
|||
/* $NetBSD: event-internal.h,v 1.2 2013/04/11 16:56:41 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* 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 _EVENT_INTERNAL_H_
|
||||
#define _EVENT_INTERNAL_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "event2/event-config.h"
|
||||
#include <time.h>
|
||||
#include <sys/queue.h>
|
||||
#include "event2/event_struct.h"
|
||||
#include "minheap-internal.h"
|
||||
#include "evsignal-internal.h"
|
||||
#include "mm-internal.h"
|
||||
#include "defer-internal.h"
|
||||
|
||||
/* map union members back */
|
||||
|
||||
/* mutually exclusive */
|
||||
#define ev_signal_next _ev.ev_signal.ev_signal_next
|
||||
#define ev_io_next _ev.ev_io.ev_io_next
|
||||
#define ev_io_timeout _ev.ev_io.ev_timeout
|
||||
|
||||
/* used only by signals */
|
||||
#define ev_ncalls _ev.ev_signal.ev_ncalls
|
||||
#define ev_pncalls _ev.ev_signal.ev_pncalls
|
||||
|
||||
/* Possible values for ev_closure in struct event. */
|
||||
#define EV_CLOSURE_NONE 0
|
||||
#define EV_CLOSURE_SIGNAL 1
|
||||
#define EV_CLOSURE_PERSIST 2
|
||||
|
||||
/** Structure to define the backend of a given event_base. */
|
||||
struct eventop {
|
||||
/** The name of this backend. */
|
||||
const char *name;
|
||||
/** Function to set up an event_base to use this backend. It should
|
||||
* create a new structure holding whatever information is needed to
|
||||
* run the backend, and return it. The returned pointer will get
|
||||
* stored by event_init into the event_base.evbase field. On failure,
|
||||
* this function should return NULL. */
|
||||
void *(*init)(struct event_base *);
|
||||
/** Enable reading/writing on a given fd or signal. 'events' will be
|
||||
* the events that we're trying to enable: one or more of EV_READ,
|
||||
* EV_WRITE, EV_SIGNAL, and EV_ET. 'old' will be those events that
|
||||
* were enabled on this fd previously. 'fdinfo' will be a structure
|
||||
* associated with the fd by the evmap; its size is defined by the
|
||||
* fdinfo field below. It will be set to 0 the first time the fd is
|
||||
* added. The function should return 0 on success and -1 on error.
|
||||
*/
|
||||
int (*add)(struct event_base *, evutil_socket_t fd, short old, short events, void *fdinfo);
|
||||
/** As "add", except 'events' contains the events we mean to disable. */
|
||||
int (*del)(struct event_base *, evutil_socket_t fd, short old, short events, void *fdinfo);
|
||||
/** Function to implement the core of an event loop. It must see which
|
||||
added events are ready, and cause event_active to be called for each
|
||||
active event (usually via event_io_active or such). It should
|
||||
return 0 on success and -1 on error.
|
||||
*/
|
||||
int (*dispatch)(struct event_base *, struct timeval *);
|
||||
/** Function to clean up and free our data from the event_base. */
|
||||
void (*dealloc)(struct event_base *);
|
||||
/** Flag: set if we need to reinitialize the event base after we fork.
|
||||
*/
|
||||
int need_reinit;
|
||||
/** Bit-array of supported event_method_features that this backend can
|
||||
* provide. */
|
||||
enum event_method_feature features;
|
||||
/** Length of the extra information we should record for each fd that
|
||||
has one or more active events. This information is recorded
|
||||
as part of the evmap entry for each fd, and passed as an argument
|
||||
to the add and del functions above.
|
||||
*/
|
||||
size_t fdinfo_len;
|
||||
};
|
||||
|
||||
#ifdef WIN32
|
||||
/* If we're on win32, then file descriptors are not nice low densely packed
|
||||
integers. Instead, they are pointer-like windows handles, and we want to
|
||||
use a hashtable instead of an array to map fds to events.
|
||||
*/
|
||||
#define EVMAP_USE_HT
|
||||
#endif
|
||||
|
||||
/* #define HT_CACHE_HASH_VALS */
|
||||
|
||||
#ifdef EVMAP_USE_HT
|
||||
#include "ht-internal.h"
|
||||
struct event_map_entry;
|
||||
HT_HEAD(event_io_map, event_map_entry);
|
||||
#else
|
||||
#define event_io_map event_signal_map
|
||||
#endif
|
||||
|
||||
/* Used to map signal numbers to a list of events. If EVMAP_USE_HT is not
|
||||
defined, this structure is also used as event_io_map, which maps fds to a
|
||||
list of events.
|
||||
*/
|
||||
struct event_signal_map {
|
||||
/* An array of evmap_io * or of evmap_signal *; empty entries are
|
||||
* set to NULL. */
|
||||
void **entries;
|
||||
/* The number of entries available in entries */
|
||||
int nentries;
|
||||
};
|
||||
|
||||
/* A list of events waiting on a given 'common' timeout value. Ordinarily,
|
||||
* events waiting for a timeout wait on a minheap. Sometimes, however, a
|
||||
* queue can be faster.
|
||||
**/
|
||||
struct common_timeout_list {
|
||||
/* List of events currently waiting in the queue. */
|
||||
struct event_list events;
|
||||
/* 'magic' timeval used to indicate the duration of events in this
|
||||
* queue. */
|
||||
struct timeval duration;
|
||||
/* Event that triggers whenever one of the events in the queue is
|
||||
* ready to activate */
|
||||
struct event timeout_event;
|
||||
/* The event_base that this timeout list is part of */
|
||||
struct event_base *base;
|
||||
};
|
||||
|
||||
/** Mask used to get the real tv_usec value from a common timeout. */
|
||||
#define COMMON_TIMEOUT_MICROSECONDS_MASK 0x000fffff
|
||||
|
||||
struct event_change;
|
||||
|
||||
/* List of 'changes' since the last call to eventop.dispatch. Only maintained
|
||||
* if the backend is using changesets. */
|
||||
struct event_changelist {
|
||||
struct event_change *changes;
|
||||
int n_changes;
|
||||
int changes_size;
|
||||
};
|
||||
|
||||
#ifndef _EVENT_DISABLE_DEBUG_MODE
|
||||
/* Global internal flag: set to one if debug mode is on. */
|
||||
extern int _event_debug_mode_on;
|
||||
#define EVENT_DEBUG_MODE_IS_ON() (_event_debug_mode_on)
|
||||
#else
|
||||
#define EVENT_DEBUG_MODE_IS_ON() (0)
|
||||
#endif
|
||||
|
||||
struct event_base {
|
||||
/** Function pointers and other data to describe this event_base's
|
||||
* backend. */
|
||||
const struct eventop *evsel;
|
||||
/** Pointer to backend-specific data. */
|
||||
void *evbase;
|
||||
|
||||
/** List of changes to tell backend about at next dispatch. Only used
|
||||
* by the O(1) backends. */
|
||||
struct event_changelist changelist;
|
||||
|
||||
/** Function pointers used to describe the backend that this event_base
|
||||
* uses for signals */
|
||||
const struct eventop *evsigsel;
|
||||
/** Data to implement the common signal handelr code. */
|
||||
struct evsig_info sig;
|
||||
|
||||
/** Number of virtual events */
|
||||
int virtual_event_count;
|
||||
/** Number of total events added to this event_base */
|
||||
int event_count;
|
||||
/** Number of total events active in this event_base */
|
||||
int event_count_active;
|
||||
|
||||
/** Set if we should terminate the loop once we're done processing
|
||||
* events. */
|
||||
int event_gotterm;
|
||||
/** Set if we should terminate the loop immediately */
|
||||
int event_break;
|
||||
/** Set if we should start a new instance of the loop immediately. */
|
||||
int event_continue;
|
||||
|
||||
/** The currently running priority of events */
|
||||
int event_running_priority;
|
||||
|
||||
/** Set if we're running the event_base_loop function, to prevent
|
||||
* reentrant invocation. */
|
||||
int running_loop;
|
||||
|
||||
/* Active event management. */
|
||||
/** An array of nactivequeues queues for active events (ones that
|
||||
* have triggered, and whose callbacks need to be called). Low
|
||||
* priority numbers are more important, and stall higher ones.
|
||||
*/
|
||||
struct event_list *activequeues;
|
||||
/** The length of the activequeues array */
|
||||
int nactivequeues;
|
||||
|
||||
/* common timeout logic */
|
||||
|
||||
/** An array of common_timeout_list* for all of the common timeout
|
||||
* values we know. */
|
||||
struct common_timeout_list **common_timeout_queues;
|
||||
/** The number of entries used in common_timeout_queues */
|
||||
int n_common_timeouts;
|
||||
/** The total size of common_timeout_queues. */
|
||||
int n_common_timeouts_allocated;
|
||||
|
||||
/** List of defered_cb that are active. We run these after the active
|
||||
* events. */
|
||||
struct deferred_cb_queue defer_queue;
|
||||
|
||||
/** Mapping from file descriptors to enabled (added) events */
|
||||
struct event_io_map io;
|
||||
|
||||
/** Mapping from signal numbers to enabled (added) events. */
|
||||
struct event_signal_map sigmap;
|
||||
|
||||
/** All events that have been enabled (added) in this event_base */
|
||||
struct event_list eventqueue;
|
||||
|
||||
/** Stored timeval; used to detect when time is running backwards. */
|
||||
struct timeval event_tv;
|
||||
|
||||
/** Priority queue of events with timeouts. */
|
||||
struct min_heap timeheap;
|
||||
|
||||
/** Stored timeval: used to avoid calling gettimeofday/clock_gettime
|
||||
* too often. */
|
||||
struct timeval tv_cache;
|
||||
|
||||
#if defined(_EVENT_HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
|
||||
/** Difference between internal time (maybe from clock_gettime) and
|
||||
* gettimeofday. */
|
||||
struct timeval tv_clock_diff;
|
||||
/** Second in which we last updated tv_clock_diff, in monotonic time. */
|
||||
time_t last_updated_clock_diff;
|
||||
#endif
|
||||
|
||||
#ifndef _EVENT_DISABLE_THREAD_SUPPORT
|
||||
/* threading support */
|
||||
/** The thread currently running the event_loop for this base */
|
||||
unsigned long th_owner_id;
|
||||
/** A lock to prevent conflicting accesses to this event_base */
|
||||
void *th_base_lock;
|
||||
/** The event whose callback is executing right now */
|
||||
struct event *current_event;
|
||||
/** A condition that gets signalled when we're done processing an
|
||||
* event with waiters on it. */
|
||||
void *current_event_cond;
|
||||
/** Number of threads blocking on current_event_cond. */
|
||||
int current_event_waiters;
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
/** IOCP support structure, if IOCP is enabled. */
|
||||
struct event_iocp_port *iocp;
|
||||
#endif
|
||||
|
||||
/** Flags that this base was configured with */
|
||||
enum event_base_config_flag flags;
|
||||
|
||||
/* Notify main thread to wake up break, etc. */
|
||||
/** True if the base already has a pending notify, and we don't need
|
||||
* to add any more. */
|
||||
int is_notify_pending;
|
||||
/** A socketpair used by some th_notify functions to wake up the main
|
||||
* thread. */
|
||||
evutil_socket_t th_notify_fd[2];
|
||||
/** An event used by some th_notify functions to wake up the main
|
||||
* thread. */
|
||||
struct event th_notify;
|
||||
/** A function used to wake up the main thread from another thread. */
|
||||
int (*th_notify_fn)(struct event_base *base);
|
||||
};
|
||||
|
||||
struct event_config_entry {
|
||||
TAILQ_ENTRY(event_config_entry) next;
|
||||
|
||||
const char *avoid_method;
|
||||
};
|
||||
|
||||
/** Internal structure: describes the configuration we want for an event_base
|
||||
* that we're about to allocate. */
|
||||
struct event_config {
|
||||
TAILQ_HEAD(event_configq, event_config_entry) entries;
|
||||
|
||||
int n_cpus_hint;
|
||||
enum event_method_feature require_features;
|
||||
enum event_base_config_flag flags;
|
||||
};
|
||||
|
||||
/* Internal use only: Functions that might be missing from <sys/queue.h> */
|
||||
#if defined(_EVENT_HAVE_SYS_QUEUE_H) && !defined(_EVENT_HAVE_TAILQFOREACH)
|
||||
#ifndef TAILQ_FIRST
|
||||
#define TAILQ_FIRST(head) ((head)->tqh_first)
|
||||
#endif
|
||||
#ifndef TAILQ_END
|
||||
#define TAILQ_END(head) NULL
|
||||
#endif
|
||||
#ifndef TAILQ_NEXT
|
||||
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
|
||||
#endif
|
||||
|
||||
#ifndef TAILQ_FOREACH
|
||||
#define TAILQ_FOREACH(var, head, field) \
|
||||
for ((var) = TAILQ_FIRST(head); \
|
||||
(var) != TAILQ_END(head); \
|
||||
(var) = TAILQ_NEXT(var, field))
|
||||
#endif
|
||||
|
||||
#ifndef TAILQ_INSERT_BEFORE
|
||||
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
|
||||
(elm)->field.tqe_next = (listelm); \
|
||||
*(listelm)->field.tqe_prev = (elm); \
|
||||
(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#endif
|
||||
#endif /* TAILQ_FOREACH */
|
||||
|
||||
#define N_ACTIVE_CALLBACKS(base) \
|
||||
((base)->event_count_active + (base)->defer_queue.active_count)
|
||||
|
||||
int _evsig_set_handler(struct event_base *base, int evsignal,
|
||||
void (*fn)(int));
|
||||
int _evsig_restore_handler(struct event_base *base, int evsignal);
|
||||
|
||||
|
||||
void event_active_nolock(struct event *ev, int res, short count);
|
||||
|
||||
/* FIXME document. */
|
||||
void event_base_add_virtual(struct event_base *base);
|
||||
void event_base_del_virtual(struct event_base *base);
|
||||
|
||||
/** For debugging: unless assertions are disabled, verify the referential
|
||||
integrity of the internal data structures of 'base'. This operation can
|
||||
be expensive.
|
||||
|
||||
Returns on success; aborts on failure.
|
||||
*/
|
||||
void event_base_assert_ok(struct event_base *base);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _EVENT_INTERNAL_H_ */
|
||||
|
2928
external/bsd/libevent/dist/event.c
vendored
Normal file
2928
external/bsd/libevent/dist/event.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
86
external/bsd/libevent/dist/event.h
vendored
Normal file
86
external/bsd/libevent/dist/event.h
vendored
Normal file
|
@ -0,0 +1,86 @@
|
|||
/* $NetBSD: event.h,v 1.1.1.2 2013/04/11 16:43:20 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* 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 _EVENT_H_
|
||||
#define _EVENT_H_
|
||||
|
||||
/** @file event.h
|
||||
|
||||
A library for writing event-driven network servers.
|
||||
|
||||
The <event.h> header is deprecated in Libevent 2.0 and later; please
|
||||
use <event2/event.h> instead. Depending on what functionality you
|
||||
need, you may also want to include more of the other event2/
|
||||
headers.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <event2/event-config.h>
|
||||
#ifdef _EVENT_HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef _EVENT_HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#ifdef _EVENT_HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#include <stdarg.h>
|
||||
|
||||
/* For int types. */
|
||||
#include <evutil.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
typedef unsigned char u_char;
|
||||
typedef unsigned short u_short;
|
||||
#endif
|
||||
|
||||
#include <event2/event_struct.h>
|
||||
#include <event2/event.h>
|
||||
#include <event2/event_compat.h>
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/buffer_compat.h>
|
||||
#include <event2/bufferevent.h>
|
||||
#include <event2/bufferevent_struct.h>
|
||||
#include <event2/bufferevent_compat.h>
|
||||
#include <event2/tag.h>
|
||||
#include <event2/tag_compat.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _EVENT_H_ */
|
291
external/bsd/libevent/dist/event_iocp.c
vendored
Normal file
291
external/bsd/libevent/dist/event_iocp.c
vendored
Normal file
|
@ -0,0 +1,291 @@
|
|||
/* $NetBSD: event_iocp.c,v 1.1.1.1 2013/04/11 16:43:19 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009-2012 Niels Provos, 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 _WIN32_WINNT
|
||||
/* Minimum required for InitializeCriticalSectionAndSpinCount */
|
||||
#define _WIN32_WINNT 0x0403
|
||||
#endif
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
#include <stdio.h>
|
||||
#include <mswsock.h>
|
||||
|
||||
#include "event2/util.h"
|
||||
#include "util-internal.h"
|
||||
#include "iocp-internal.h"
|
||||
#include "log-internal.h"
|
||||
#include "mm-internal.h"
|
||||
#include "event-internal.h"
|
||||
#include "evthread-internal.h"
|
||||
|
||||
#define NOTIFICATION_KEY ((ULONG_PTR)-1)
|
||||
|
||||
void
|
||||
event_overlapped_init(struct event_overlapped *o, iocp_callback cb)
|
||||
{
|
||||
memset(o, 0, sizeof(struct event_overlapped));
|
||||
o->cb = cb;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_entry(OVERLAPPED *o, ULONG_PTR completion_key, DWORD nBytes, int ok)
|
||||
{
|
||||
struct event_overlapped *eo =
|
||||
EVUTIL_UPCAST(o, struct event_overlapped, overlapped);
|
||||
eo->cb(eo, completion_key, nBytes, ok);
|
||||
}
|
||||
|
||||
static void
|
||||
loop(void *_port)
|
||||
{
|
||||
struct event_iocp_port *port = _port;
|
||||
long ms = port->ms;
|
||||
HANDLE p = port->port;
|
||||
|
||||
if (ms <= 0)
|
||||
ms = INFINITE;
|
||||
|
||||
while (1) {
|
||||
OVERLAPPED *overlapped=NULL;
|
||||
ULONG_PTR key=0;
|
||||
DWORD bytes=0;
|
||||
int ok = GetQueuedCompletionStatus(p, &bytes, &key,
|
||||
&overlapped, ms);
|
||||
EnterCriticalSection(&port->lock);
|
||||
if (port->shutdown) {
|
||||
if (--port->n_live_threads == 0)
|
||||
ReleaseSemaphore(port->shutdownSemaphore, 1,
|
||||
NULL);
|
||||
LeaveCriticalSection(&port->lock);
|
||||
return;
|
||||
}
|
||||
LeaveCriticalSection(&port->lock);
|
||||
|
||||
if (key != NOTIFICATION_KEY && overlapped)
|
||||
handle_entry(overlapped, key, bytes, ok);
|
||||
else if (!overlapped)
|
||||
break;
|
||||
}
|
||||
event_warnx("GetQueuedCompletionStatus exited with no event.");
|
||||
EnterCriticalSection(&port->lock);
|
||||
if (--port->n_live_threads == 0)
|
||||
ReleaseSemaphore(port->shutdownSemaphore, 1, NULL);
|
||||
LeaveCriticalSection(&port->lock);
|
||||
}
|
||||
|
||||
int
|
||||
event_iocp_port_associate(struct event_iocp_port *port, evutil_socket_t fd,
|
||||
ev_uintptr_t key)
|
||||
{
|
||||
HANDLE h;
|
||||
h = CreateIoCompletionPort((HANDLE)fd, port->port, key, port->n_threads);
|
||||
if (!h)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *
|
||||
get_extension_function(SOCKET s, const GUID *which_fn)
|
||||
{
|
||||
void *ptr = NULL;
|
||||
DWORD bytes=0;
|
||||
WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER,
|
||||
(GUID*)which_fn, sizeof(*which_fn),
|
||||
&ptr, sizeof(ptr),
|
||||
&bytes, NULL, NULL);
|
||||
|
||||
/* No need to detect errors here: if ptr is set, then we have a good
|
||||
function pointer. Otherwise, we should behave as if we had no
|
||||
function pointer.
|
||||
*/
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* Mingw doesn't have these in its mswsock.h. The values are copied from
|
||||
wine.h. Perhaps if we copy them exactly, the cargo will come again.
|
||||
*/
|
||||
#ifndef WSAID_ACCEPTEX
|
||||
#define WSAID_ACCEPTEX \
|
||||
{0xb5367df1,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}}
|
||||
#endif
|
||||
#ifndef WSAID_CONNECTEX
|
||||
#define WSAID_CONNECTEX \
|
||||
{0x25a207b9,0xddf3,0x4660,{0x8e,0xe9,0x76,0xe5,0x8c,0x74,0x06,0x3e}}
|
||||
#endif
|
||||
#ifndef WSAID_GETACCEPTEXSOCKADDRS
|
||||
#define WSAID_GETACCEPTEXSOCKADDRS \
|
||||
{0xb5367df2,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}}
|
||||
#endif
|
||||
|
||||
static void
|
||||
init_extension_functions(struct win32_extension_fns *ext)
|
||||
{
|
||||
const GUID acceptex = WSAID_ACCEPTEX;
|
||||
const GUID connectex = WSAID_CONNECTEX;
|
||||
const GUID getacceptexsockaddrs = WSAID_GETACCEPTEXSOCKADDRS;
|
||||
SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (s == INVALID_SOCKET)
|
||||
return;
|
||||
ext->AcceptEx = get_extension_function(s, &acceptex);
|
||||
ext->ConnectEx = get_extension_function(s, &connectex);
|
||||
ext->GetAcceptExSockaddrs = get_extension_function(s,
|
||||
&getacceptexsockaddrs);
|
||||
closesocket(s);
|
||||
}
|
||||
|
||||
static struct win32_extension_fns the_extension_fns;
|
||||
static int extension_fns_initialized = 0;
|
||||
|
||||
const struct win32_extension_fns *
|
||||
event_get_win32_extension_fns(void)
|
||||
{
|
||||
return &the_extension_fns;
|
||||
}
|
||||
|
||||
#define N_CPUS_DEFAULT 2
|
||||
|
||||
struct event_iocp_port *
|
||||
event_iocp_port_launch(int n_cpus)
|
||||
{
|
||||
struct event_iocp_port *port;
|
||||
int i;
|
||||
|
||||
if (!extension_fns_initialized)
|
||||
init_extension_functions(&the_extension_fns);
|
||||
|
||||
if (!(port = mm_calloc(1, sizeof(struct event_iocp_port))))
|
||||
return NULL;
|
||||
|
||||
if (n_cpus <= 0)
|
||||
n_cpus = N_CPUS_DEFAULT;
|
||||
port->n_threads = n_cpus * 2;
|
||||
port->threads = mm_calloc(port->n_threads, sizeof(HANDLE));
|
||||
if (!port->threads)
|
||||
goto err;
|
||||
|
||||
port->port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0,
|
||||
n_cpus);
|
||||
port->ms = -1;
|
||||
if (!port->port)
|
||||
goto err;
|
||||
|
||||
port->shutdownSemaphore = CreateSemaphore(NULL, 0, 1, NULL);
|
||||
if (!port->shutdownSemaphore)
|
||||
goto err;
|
||||
|
||||
for (i=0; i<port->n_threads; ++i) {
|
||||
ev_uintptr_t th = _beginthread(loop, 0, port);
|
||||
if (th == (ev_uintptr_t)-1)
|
||||
goto err;
|
||||
port->threads[i] = (HANDLE)th;
|
||||
++port->n_live_threads;
|
||||
}
|
||||
|
||||
InitializeCriticalSectionAndSpinCount(&port->lock, 1000);
|
||||
|
||||
return port;
|
||||
err:
|
||||
if (port->port)
|
||||
CloseHandle(port->port);
|
||||
if (port->threads)
|
||||
mm_free(port->threads);
|
||||
if (port->shutdownSemaphore)
|
||||
CloseHandle(port->shutdownSemaphore);
|
||||
mm_free(port);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_event_iocp_port_unlock_and_free(struct event_iocp_port *port)
|
||||
{
|
||||
DeleteCriticalSection(&port->lock);
|
||||
CloseHandle(port->port);
|
||||
CloseHandle(port->shutdownSemaphore);
|
||||
mm_free(port->threads);
|
||||
mm_free(port);
|
||||
}
|
||||
|
||||
static int
|
||||
event_iocp_notify_all(struct event_iocp_port *port)
|
||||
{
|
||||
int i, r, ok=1;
|
||||
for (i=0; i<port->n_threads; ++i) {
|
||||
r = PostQueuedCompletionStatus(port->port, 0, NOTIFICATION_KEY,
|
||||
NULL);
|
||||
if (!r)
|
||||
ok = 0;
|
||||
}
|
||||
return ok ? 0 : -1;
|
||||
}
|
||||
|
||||
int
|
||||
event_iocp_shutdown(struct event_iocp_port *port, long waitMsec)
|
||||
{
|
||||
DWORD ms = INFINITE;
|
||||
int n;
|
||||
|
||||
EnterCriticalSection(&port->lock);
|
||||
port->shutdown = 1;
|
||||
LeaveCriticalSection(&port->lock);
|
||||
event_iocp_notify_all(port);
|
||||
|
||||
if (waitMsec >= 0)
|
||||
ms = waitMsec;
|
||||
|
||||
WaitForSingleObject(port->shutdownSemaphore, ms);
|
||||
EnterCriticalSection(&port->lock);
|
||||
n = port->n_live_threads;
|
||||
LeaveCriticalSection(&port->lock);
|
||||
if (n == 0) {
|
||||
_event_iocp_port_unlock_and_free(port);
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
event_iocp_activate_overlapped(
|
||||
struct event_iocp_port *port, struct event_overlapped *o,
|
||||
ev_uintptr_t key, ev_uint32_t n)
|
||||
{
|
||||
BOOL r;
|
||||
|
||||
r = PostQueuedCompletionStatus(port->port, n, key, &o->overlapped);
|
||||
return (r==0) ? -1 : 0;
|
||||
}
|
||||
|
||||
struct event_iocp_port *
|
||||
event_base_get_iocp(struct event_base *base)
|
||||
{
|
||||
#ifdef WIN32
|
||||
return base->iocp;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
1717
external/bsd/libevent/dist/event_rpcgen.py
vendored
Executable file
1717
external/bsd/libevent/dist/event_rpcgen.py
vendored
Executable file
File diff suppressed because it is too large
Load diff
593
external/bsd/libevent/dist/event_tagging.c
vendored
Normal file
593
external/bsd/libevent/dist/event_tagging.c
vendored
Normal file
|
@ -0,0 +1,593 @@
|
|||
/* $NetBSD: event_tagging.c,v 1.2 2013/04/11 16:56:41 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2003-2009 Niels Provos <provos@citi.umich.edu>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "event2/event-config.h"
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: event_tagging.c,v 1.2 2013/04/11 16:56:41 christos Exp $");
|
||||
|
||||
#ifdef _EVENT_HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef _EVENT_HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#else
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#include <sys/queue.h>
|
||||
#ifdef _EVENT_HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifndef WIN32
|
||||
#include <syslog.h>
|
||||
#endif
|
||||
#ifdef _EVENT_HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <limits.h>
|
||||
|
||||
#include "event2/event.h"
|
||||
#include "event2/tag.h"
|
||||
#include "event2/buffer.h"
|
||||
#include "log-internal.h"
|
||||
#include "mm-internal.h"
|
||||
#include "util-internal.h"
|
||||
|
||||
/*
|
||||
Here's our wire format:
|
||||
|
||||
Stream = TaggedData*
|
||||
|
||||
TaggedData = Tag Length Data
|
||||
where the integer value of 'Length' is the length of 'data'.
|
||||
|
||||
Tag = HByte* LByte
|
||||
where HByte is a byte with the high bit set, and LByte is a byte
|
||||
with the high bit clear. The integer value of the tag is taken
|
||||
by concatenating the lower 7 bits from all the tags. So for example,
|
||||
the tag 0x66 is encoded as [66], whereas the tag 0x166 is encoded as
|
||||
[82 66]
|
||||
|
||||
Length = Integer
|
||||
|
||||
Integer = NNibbles Nibble* Padding?
|
||||
where NNibbles is a 4-bit value encoding the number of nibbles-1,
|
||||
and each Nibble is 4 bits worth of encoded integer, in big-endian
|
||||
order. If the total encoded integer size is an odd number of nibbles,
|
||||
a final padding nibble with value 0 is appended.
|
||||
*/
|
||||
|
||||
int evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf);
|
||||
int evtag_decode_int64(ev_uint64_t *pnumber, struct evbuffer *evbuf);
|
||||
int evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t tag);
|
||||
int evtag_decode_tag(ev_uint32_t *ptag, struct evbuffer *evbuf);
|
||||
|
||||
void
|
||||
evtag_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* We encode integers by nibbles; 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 number a 32-bit unsigned integer to encode
|
||||
* @param data a pointer to where the data should be written. Must
|
||||
* have at least 5 bytes free.
|
||||
* @return the number of bytes written into data.
|
||||
*/
|
||||
|
||||
#define ENCODE_INT_INTERNAL(data, number) do { \
|
||||
int off = 1, nibbles = 0; \
|
||||
\
|
||||
memset(data, 0, sizeof(number)+1); \
|
||||
while (number) { \
|
||||
if (off & 0x1) \
|
||||
data[off/2] = (data[off/2] & 0xf0) | (number & 0x0f); \
|
||||
else \
|
||||
data[off/2] = (data[off/2] & 0x0f) | \
|
||||
((number & 0x0f) << 4); \
|
||||
number >>= 4; \
|
||||
off++; \
|
||||
} \
|
||||
\
|
||||
if (off > 2) \
|
||||
nibbles = off - 2; \
|
||||
\
|
||||
/* Off - 1 is the number of encoded nibbles */ \
|
||||
data[0] = (data[0] & 0x0f) | ((nibbles & 0x0f) << 4); \
|
||||
\
|
||||
return ((off + 1) / 2); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
static inline int
|
||||
encode_int_internal(ev_uint8_t *data, ev_uint32_t number)
|
||||
{
|
||||
ENCODE_INT_INTERNAL(data, number);
|
||||
}
|
||||
|
||||
static inline int
|
||||
encode_int64_internal(ev_uint8_t *data, ev_uint64_t number)
|
||||
{
|
||||
ENCODE_INT_INTERNAL(data, number);
|
||||
}
|
||||
|
||||
void
|
||||
evtag_encode_int(struct evbuffer *evbuf, ev_uint32_t number)
|
||||
{
|
||||
ev_uint8_t data[5];
|
||||
int len = encode_int_internal(data, number);
|
||||
evbuffer_add(evbuf, data, len);
|
||||
}
|
||||
|
||||
void
|
||||
evtag_encode_int64(struct evbuffer *evbuf, ev_uint64_t number)
|
||||
{
|
||||
ev_uint8_t data[9];
|
||||
int len = encode_int64_internal(data, number);
|
||||
evbuffer_add(evbuf, data, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Support variable length encoding of tags; we use the high bit in each
|
||||
* octet as a continuation signal.
|
||||
*/
|
||||
|
||||
int
|
||||
evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t tag)
|
||||
{
|
||||
int bytes = 0;
|
||||
ev_uint8_t data[5];
|
||||
|
||||
memset(data, 0, sizeof(data));
|
||||
do {
|
||||
ev_uint8_t lower = tag & 0x7f;
|
||||
tag >>= 7;
|
||||
|
||||
if (tag)
|
||||
lower |= 0x80;
|
||||
|
||||
data[bytes++] = lower;
|
||||
} while (tag);
|
||||
|
||||
if (evbuf != NULL)
|
||||
evbuffer_add(evbuf, data, bytes);
|
||||
|
||||
return (bytes);
|
||||
}
|
||||
|
||||
static int
|
||||
decode_tag_internal(ev_uint32_t *ptag, struct evbuffer *evbuf, int dodrain)
|
||||
{
|
||||
ev_uint32_t number = 0;
|
||||
size_t len = evbuffer_get_length(evbuf);
|
||||
ev_uint8_t *data;
|
||||
size_t count = 0;
|
||||
int shift = 0, done = 0;
|
||||
|
||||
/*
|
||||
* the encoding of a number is at most one byte more than its
|
||||
* storage size. however, it may also be much smaller.
|
||||
*/
|
||||
data = evbuffer_pullup(
|
||||
evbuf, len < sizeof(number) + 1 ? len : sizeof(number) + 1);
|
||||
|
||||
while (count++ < len) {
|
||||
ev_uint8_t lower = *data++;
|
||||
number |= (lower & 0x7f) << shift;
|
||||
shift += 7;
|
||||
|
||||
if (!(lower & 0x80)) {
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!done)
|
||||
return (-1);
|
||||
|
||||
if (dodrain)
|
||||
evbuffer_drain(evbuf, count);
|
||||
|
||||
if (ptag != NULL)
|
||||
*ptag = number;
|
||||
|
||||
return count > INT_MAX ? INT_MAX : (int)(count);
|
||||
}
|
||||
|
||||
int
|
||||
evtag_decode_tag(ev_uint32_t *ptag, struct evbuffer *evbuf)
|
||||
{
|
||||
return (decode_tag_internal(ptag, evbuf, 1 /* dodrain */));
|
||||
}
|
||||
|
||||
/*
|
||||
* Marshal a data type, the general format is as follows:
|
||||
*
|
||||
* tag number: one byte; length: var bytes; payload: var bytes
|
||||
*/
|
||||
|
||||
void
|
||||
evtag_marshal(struct evbuffer *evbuf, ev_uint32_t tag,
|
||||
const void *data, ev_uint32_t len)
|
||||
{
|
||||
evtag_encode_tag(evbuf, tag);
|
||||
evtag_encode_int(evbuf, len);
|
||||
evbuffer_add(evbuf, __UNCONST(data), len);
|
||||
}
|
||||
|
||||
void
|
||||
evtag_marshal_buffer(struct evbuffer *evbuf, ev_uint32_t tag,
|
||||
struct evbuffer *data)
|
||||
{
|
||||
evtag_encode_tag(evbuf, tag);
|
||||
/* XXX support more than UINT32_MAX data */
|
||||
evtag_encode_int(evbuf, (ev_uint32_t)evbuffer_get_length(data));
|
||||
evbuffer_add_buffer(evbuf, data);
|
||||
}
|
||||
|
||||
/* Marshaling for integers */
|
||||
void
|
||||
evtag_marshal_int(struct evbuffer *evbuf, ev_uint32_t tag, ev_uint32_t integer)
|
||||
{
|
||||
ev_uint8_t data[5];
|
||||
int len = encode_int_internal(data, integer);
|
||||
|
||||
evtag_encode_tag(evbuf, tag);
|
||||
evtag_encode_int(evbuf, len);
|
||||
evbuffer_add(evbuf, data, len);
|
||||
}
|
||||
|
||||
void
|
||||
evtag_marshal_int64(struct evbuffer *evbuf, ev_uint32_t tag,
|
||||
ev_uint64_t integer)
|
||||
{
|
||||
ev_uint8_t data[9];
|
||||
int len = encode_int64_internal(data, integer);
|
||||
|
||||
evtag_encode_tag(evbuf, tag);
|
||||
evtag_encode_int(evbuf, len);
|
||||
evbuffer_add(evbuf, data, len);
|
||||
}
|
||||
|
||||
void
|
||||
evtag_marshal_string(struct evbuffer *buf, ev_uint32_t tag, const char *string)
|
||||
{
|
||||
/* TODO support strings longer than UINT32_MAX ? */
|
||||
evtag_marshal(buf, tag, string, (ev_uint32_t)strlen(string));
|
||||
}
|
||||
|
||||
void
|
||||
evtag_marshal_timeval(struct evbuffer *evbuf, ev_uint32_t tag, struct timeval *tv)
|
||||
{
|
||||
ev_uint8_t data[10];
|
||||
int len = encode_int_internal(data, tv->tv_sec);
|
||||
len += encode_int_internal(data + len, tv->tv_usec);
|
||||
evtag_marshal(evbuf, tag, data, len);
|
||||
}
|
||||
|
||||
#define DECODE_INT_INTERNAL(number, maxnibbles, pnumber, evbuf, offset) \
|
||||
do { \
|
||||
ev_uint8_t *data; \
|
||||
ev_ssize_t len = evbuffer_get_length(evbuf) - offset; \
|
||||
int nibbles = 0; \
|
||||
\
|
||||
if (len <= 0) \
|
||||
return (-1); \
|
||||
\
|
||||
/* XXX(niels): faster? */ \
|
||||
data = evbuffer_pullup(evbuf, offset + 1) + offset; \
|
||||
\
|
||||
nibbles = ((data[0] & 0xf0) >> 4) + 1; \
|
||||
if (nibbles > maxnibbles || (nibbles >> 1) + 1 > len) \
|
||||
return (-1); \
|
||||
len = (nibbles >> 1) + 1; \
|
||||
\
|
||||
data = evbuffer_pullup(evbuf, offset + len) + offset; \
|
||||
\
|
||||
while (nibbles > 0) { \
|
||||
number <<= 4; \
|
||||
if (nibbles & 0x1) \
|
||||
number |= data[nibbles >> 1] & 0x0f; \
|
||||
else \
|
||||
number |= (data[nibbles >> 1] & 0xf0) >> 4; \
|
||||
nibbles--; \
|
||||
} \
|
||||
\
|
||||
*pnumber = number; \
|
||||
\
|
||||
return (int)(len); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/* Internal: decode an integer from an evbuffer, without draining it.
|
||||
* Only integers up to 32-bits are supported.
|
||||
*
|
||||
* @param evbuf the buffer to read from
|
||||
* @param offset an index into the buffer at which we should start reading.
|
||||
* @param pnumber a pointer to receive the integer.
|
||||
* @return The length of the number as encoded, or -1 on error.
|
||||
*/
|
||||
|
||||
static int
|
||||
decode_int_internal(ev_uint32_t *pnumber, struct evbuffer *evbuf, int offset)
|
||||
{
|
||||
ev_uint32_t number = 0;
|
||||
DECODE_INT_INTERNAL(number, 8, pnumber, evbuf, offset);
|
||||
}
|
||||
|
||||
static int
|
||||
decode_int64_internal(ev_uint64_t *pnumber, struct evbuffer *evbuf, int offset)
|
||||
{
|
||||
ev_uint64_t number = 0;
|
||||
DECODE_INT_INTERNAL(number, 16, pnumber, evbuf, offset);
|
||||
}
|
||||
|
||||
int
|
||||
evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf)
|
||||
{
|
||||
int res = decode_int_internal(pnumber, evbuf, 0);
|
||||
if (res != -1)
|
||||
evbuffer_drain(evbuf, res);
|
||||
|
||||
return (res == -1 ? -1 : 0);
|
||||
}
|
||||
|
||||
int
|
||||
evtag_decode_int64(ev_uint64_t *pnumber, struct evbuffer *evbuf)
|
||||
{
|
||||
int res = decode_int64_internal(pnumber, evbuf, 0);
|
||||
if (res != -1)
|
||||
evbuffer_drain(evbuf, res);
|
||||
|
||||
return (res == -1 ? -1 : 0);
|
||||
}
|
||||
|
||||
int
|
||||
evtag_peek(struct evbuffer *evbuf, ev_uint32_t *ptag)
|
||||
{
|
||||
return (decode_tag_internal(ptag, evbuf, 0 /* dodrain */));
|
||||
}
|
||||
|
||||
int
|
||||
evtag_peek_length(struct evbuffer *evbuf, ev_uint32_t *plength)
|
||||
{
|
||||
int res, len;
|
||||
|
||||
len = decode_tag_internal(NULL, evbuf, 0 /* dodrain */);
|
||||
if (len == -1)
|
||||
return (-1);
|
||||
|
||||
res = decode_int_internal(plength, evbuf, len);
|
||||
if (res == -1)
|
||||
return (-1);
|
||||
|
||||
*plength += res + len;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
evtag_payload_length(struct evbuffer *evbuf, ev_uint32_t *plength)
|
||||
{
|
||||
int res, len;
|
||||
|
||||
len = decode_tag_internal(NULL, evbuf, 0 /* dodrain */);
|
||||
if (len == -1)
|
||||
return (-1);
|
||||
|
||||
res = decode_int_internal(plength, evbuf, len);
|
||||
if (res == -1)
|
||||
return (-1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* just unmarshals the header and returns the length of the remaining data */
|
||||
|
||||
int
|
||||
evtag_unmarshal_header(struct evbuffer *evbuf, ev_uint32_t *ptag)
|
||||
{
|
||||
ev_uint32_t len;
|
||||
|
||||
if (decode_tag_internal(ptag, evbuf, 1 /* dodrain */) == -1)
|
||||
return (-1);
|
||||
if (evtag_decode_int(&len, evbuf) == -1)
|
||||
return (-1);
|
||||
|
||||
if (evbuffer_get_length(evbuf) < len)
|
||||
return (-1);
|
||||
|
||||
return (len);
|
||||
}
|
||||
|
||||
int
|
||||
evtag_consume(struct evbuffer *evbuf)
|
||||
{
|
||||
int len;
|
||||
if ((len = evtag_unmarshal_header(evbuf, NULL)) == -1)
|
||||
return (-1);
|
||||
evbuffer_drain(evbuf, len);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Reads the data type from an event buffer */
|
||||
|
||||
int
|
||||
evtag_unmarshal(struct evbuffer *src, ev_uint32_t *ptag, struct evbuffer *dst)
|
||||
{
|
||||
int len;
|
||||
|
||||
if ((len = evtag_unmarshal_header(src, ptag)) == -1)
|
||||
return (-1);
|
||||
|
||||
if (evbuffer_add(dst, evbuffer_pullup(src, len), len) == -1)
|
||||
return (-1);
|
||||
|
||||
evbuffer_drain(src, len);
|
||||
|
||||
return (len);
|
||||
}
|
||||
|
||||
/* Marshaling for integers */
|
||||
|
||||
int
|
||||
evtag_unmarshal_int(struct evbuffer *evbuf, ev_uint32_t need_tag,
|
||||
ev_uint32_t *pinteger)
|
||||
{
|
||||
ev_uint32_t tag;
|
||||
ev_uint32_t len;
|
||||
int result;
|
||||
|
||||
if (decode_tag_internal(&tag, evbuf, 1 /* dodrain */) == -1)
|
||||
return (-1);
|
||||
if (need_tag != tag)
|
||||
return (-1);
|
||||
if (evtag_decode_int(&len, evbuf) == -1)
|
||||
return (-1);
|
||||
|
||||
if (evbuffer_get_length(evbuf) < len)
|
||||
return (-1);
|
||||
|
||||
result = decode_int_internal(pinteger, evbuf, 0);
|
||||
evbuffer_drain(evbuf, len);
|
||||
if (result < 0 || (size_t)result > len) /* XXX Should this be != rather than > ?*/
|
||||
return (-1);
|
||||
else
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
evtag_unmarshal_int64(struct evbuffer *evbuf, ev_uint32_t need_tag,
|
||||
ev_uint64_t *pinteger)
|
||||
{
|
||||
ev_uint32_t tag;
|
||||
ev_uint32_t len;
|
||||
int result;
|
||||
|
||||
if (decode_tag_internal(&tag, evbuf, 1 /* dodrain */) == -1)
|
||||
return (-1);
|
||||
if (need_tag != tag)
|
||||
return (-1);
|
||||
if (evtag_decode_int(&len, evbuf) == -1)
|
||||
return (-1);
|
||||
|
||||
if (evbuffer_get_length(evbuf) < len)
|
||||
return (-1);
|
||||
|
||||
result = decode_int64_internal(pinteger, evbuf, 0);
|
||||
evbuffer_drain(evbuf, len);
|
||||
if (result < 0 || (size_t)result > len) /* XXX Should this be != rather than > ?*/
|
||||
return (-1);
|
||||
else
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Unmarshal a fixed length tag */
|
||||
|
||||
int
|
||||
evtag_unmarshal_fixed(struct evbuffer *src, ev_uint32_t need_tag, void *data,
|
||||
size_t len)
|
||||
{
|
||||
ev_uint32_t tag;
|
||||
int tag_len;
|
||||
|
||||
/* Now unmarshal a tag and check that it matches the tag we want */
|
||||
if ((tag_len = evtag_unmarshal_header(src, &tag)) < 0 ||
|
||||
tag != need_tag)
|
||||
return (-1);
|
||||
|
||||
if ((size_t)tag_len != len)
|
||||
return (-1);
|
||||
|
||||
evbuffer_remove(src, data, len);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
evtag_unmarshal_string(struct evbuffer *evbuf, ev_uint32_t need_tag,
|
||||
char **pstring)
|
||||
{
|
||||
ev_uint32_t tag;
|
||||
int tag_len;
|
||||
|
||||
if ((tag_len = evtag_unmarshal_header(evbuf, &tag)) == -1 ||
|
||||
tag != need_tag)
|
||||
return (-1);
|
||||
|
||||
*pstring = mm_malloc(tag_len + 1);
|
||||
if (*pstring == NULL) {
|
||||
event_warn("%s: malloc", __func__);
|
||||
return -1;
|
||||
}
|
||||
evbuffer_remove(evbuf, *pstring, tag_len);
|
||||
(*pstring)[tag_len] = '\0';
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
evtag_unmarshal_timeval(struct evbuffer *evbuf, ev_uint32_t need_tag,
|
||||
struct timeval *ptv)
|
||||
{
|
||||
ev_uint32_t tag;
|
||||
ev_uint32_t integer;
|
||||
int len, offset, offset2;
|
||||
int result = -1;
|
||||
|
||||
if ((len = evtag_unmarshal_header(evbuf, &tag)) == -1)
|
||||
return (-1);
|
||||
if (tag != need_tag)
|
||||
goto done;
|
||||
if ((offset = decode_int_internal(&integer, evbuf, 0)) == -1)
|
||||
goto done;
|
||||
ptv->tv_sec = integer;
|
||||
if ((offset2 = decode_int_internal(&integer, evbuf, offset)) == -1)
|
||||
goto done;
|
||||
ptv->tv_usec = integer;
|
||||
if (offset + offset2 > len) /* XXX Should this be != instead of > ? */
|
||||
goto done;
|
||||
|
||||
result = 0;
|
||||
done:
|
||||
evbuffer_drain(evbuf, len);
|
||||
return result;
|
||||
}
|
46
external/bsd/libevent/dist/evhttp.h
vendored
Normal file
46
external/bsd/libevent/dist/evhttp.h
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
/* $NetBSD: evhttp.h,v 1.1.1.2 2013/04/11 16:43:29 christos Exp $ */
|
||||
/*
|
||||
* Copyright 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright 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 _EVHTTP_H_
|
||||
#define _EVHTTP_H_
|
||||
|
||||
/** @file evhttp.h
|
||||
|
||||
An http implementation subsystem for Libevent.
|
||||
|
||||
The <evhttp.h> header is deprecated in Libevent 2.0 and later; please
|
||||
use <event2/http.h> instead. Depending on what functionality you
|
||||
need, you may also want to include more of the other <event2/...>
|
||||
headers.
|
||||
*/
|
||||
|
||||
#include <event.h>
|
||||
#include <event2/http.h>
|
||||
#include <event2/http_struct.h>
|
||||
#include <event2/http_compat.h>
|
||||
|
||||
#endif /* _EVHTTP_H_ */
|
93
external/bsd/libevent/dist/evmap-internal.h
vendored
Normal file
93
external/bsd/libevent/dist/evmap-internal.h
vendored
Normal file
|
@ -0,0 +1,93 @@
|
|||
/* $NetBSD: evmap-internal.h,v 1.1.1.1 2013/04/11 16:43:19 christos Exp $ */
|
||||
/*
|
||||
* 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 _EVMAP_H_
|
||||
#define _EVMAP_H_
|
||||
|
||||
/** @file evmap-internal.h
|
||||
*
|
||||
* An event_map is a utility structure to map each fd or signal to zero or
|
||||
* more events. Functions to manipulate event_maps should only be used from
|
||||
* inside libevent. They generally need to hold the lock on the corresponding
|
||||
* event_base.
|
||||
**/
|
||||
|
||||
struct event_base;
|
||||
struct event;
|
||||
|
||||
/** Initialize an event_map for use.
|
||||
*/
|
||||
void evmap_io_initmap(struct event_io_map* ctx);
|
||||
void evmap_signal_initmap(struct event_signal_map* ctx);
|
||||
|
||||
/** Remove all entries from an event_map.
|
||||
|
||||
@param ctx the map to clear.
|
||||
*/
|
||||
void evmap_io_clear(struct event_io_map* ctx);
|
||||
void evmap_signal_clear(struct event_signal_map* ctx);
|
||||
|
||||
/** Add an IO event (some combination of EV_READ or EV_WRITE) to an
|
||||
event_base's list of events on a given file descriptor, and tell the
|
||||
underlying eventops about the fd if its state has changed.
|
||||
|
||||
Requires that ev is not already added.
|
||||
|
||||
@param base the event_base to operate on.
|
||||
@param fd the file descriptor corresponding to ev.
|
||||
@param ev the event to add.
|
||||
*/
|
||||
int evmap_io_add(struct event_base *base, evutil_socket_t fd, struct event *ev);
|
||||
/** Remove an IO event (some combination of EV_READ or EV_WRITE) to an
|
||||
event_base's list of events on a given file descriptor, and tell the
|
||||
underlying eventops about the fd if its state has changed.
|
||||
|
||||
@param base the event_base to operate on.
|
||||
@param fd the file descriptor corresponding to ev.
|
||||
@param ev the event to remove.
|
||||
*/
|
||||
int evmap_io_del(struct event_base *base, evutil_socket_t fd, struct event *ev);
|
||||
/** Active the set of events waiting on an event_base for a given fd.
|
||||
|
||||
@param base the event_base to operate on.
|
||||
@param fd the file descriptor that has become active.
|
||||
@param events a bitmask of EV_READ|EV_WRITE|EV_ET.
|
||||
*/
|
||||
void evmap_io_active(struct event_base *base, evutil_socket_t fd, short events);
|
||||
|
||||
|
||||
/* These functions behave in the same way as evmap_io_*, except they work on
|
||||
* signals rather than fds. signals use a linear map everywhere; fds use
|
||||
* either a linear map or a hashtable. */
|
||||
int evmap_signal_add(struct event_base *base, int signum, struct event *ev);
|
||||
int evmap_signal_del(struct event_base *base, int signum, struct event *ev);
|
||||
void evmap_signal_active(struct event_base *base, evutil_socket_t signum, int ncalls);
|
||||
|
||||
void *evmap_io_get_fdinfo(struct event_io_map *ctx, evutil_socket_t fd);
|
||||
|
||||
void evmap_check_integrity(struct event_base *base);
|
||||
|
||||
#endif /* _EVMAP_H_ */
|
802
external/bsd/libevent/dist/evmap.c
vendored
Normal file
802
external/bsd/libevent/dist/evmap.c
vendored
Normal file
|
@ -0,0 +1,802 @@
|
|||
/* $NetBSD: evmap.c,v 1.2 2013/04/11 16:56:41 christos Exp $ */
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#include "event2/event-config.h"
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: evmap.c,v 1.2 2013/04/11 16:56:41 christos Exp $");
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#if !defined(WIN32) && defined(_EVENT_HAVE_SYS_TIME_H)
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include <sys/queue.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "event-internal.h"
|
||||
#include "evmap-internal.h"
|
||||
#include "mm-internal.h"
|
||||
#include "changelist-internal.h"
|
||||
|
||||
/** An entry for an evmap_io list: notes all the events that want to read or
|
||||
write on a given fd, and the number of each.
|
||||
*/
|
||||
struct evmap_io {
|
||||
struct event_list events;
|
||||
ev_uint16_t nread;
|
||||
ev_uint16_t nwrite;
|
||||
};
|
||||
|
||||
/* An entry for an evmap_signal list: notes all the events that want to know
|
||||
when a signal triggers. */
|
||||
struct evmap_signal {
|
||||
struct event_list events;
|
||||
};
|
||||
|
||||
/* On some platforms, fds start at 0 and increment by 1 as they are
|
||||
allocated, and old numbers get used. For these platforms, we
|
||||
implement io maps just like signal maps: as an array of pointers to
|
||||
struct evmap_io. But on other platforms (windows), sockets are not
|
||||
0-indexed, not necessarily consecutive, and not necessarily reused.
|
||||
There, we use a hashtable to implement evmap_io.
|
||||
*/
|
||||
#ifdef EVMAP_USE_HT
|
||||
struct event_map_entry {
|
||||
HT_ENTRY(event_map_entry) map_node;
|
||||
evutil_socket_t fd;
|
||||
union { /* This is a union in case we need to make more things that can
|
||||
be in the hashtable. */
|
||||
struct evmap_io evmap_io;
|
||||
} ent;
|
||||
};
|
||||
|
||||
/* Helper used by the event_io_map hashtable code; tries to return a good hash
|
||||
* of the fd in e->fd. */
|
||||
static inline unsigned
|
||||
hashsocket(struct event_map_entry *e)
|
||||
{
|
||||
/* On win32, in practice, the low 2-3 bits of a SOCKET seem not to
|
||||
* matter. Our hashtable implementation really likes low-order bits,
|
||||
* though, so let's do the rotate-and-add trick. */
|
||||
unsigned h = (unsigned) e->fd;
|
||||
h += (h >> 2) | (h << 30);
|
||||
return h;
|
||||
}
|
||||
|
||||
/* Helper used by the event_io_map hashtable code; returns true iff e1 and e2
|
||||
* have the same e->fd. */
|
||||
static inline int
|
||||
eqsocket(struct event_map_entry *e1, struct event_map_entry *e2)
|
||||
{
|
||||
return e1->fd == e2->fd;
|
||||
}
|
||||
|
||||
HT_PROTOTYPE(event_io_map, event_map_entry, map_node, hashsocket, eqsocket)
|
||||
HT_GENERATE(event_io_map, event_map_entry, map_node, hashsocket, eqsocket,
|
||||
0.5, mm_malloc, mm_realloc, mm_free)
|
||||
|
||||
#define GET_IO_SLOT(x, map, slot, type) \
|
||||
do { \
|
||||
struct event_map_entry _key, *_ent; \
|
||||
_key.fd = slot; \
|
||||
_ent = HT_FIND(event_io_map, map, &_key); \
|
||||
(x) = _ent ? &_ent->ent.type : NULL; \
|
||||
} while (/*CONSTCOND*/0);
|
||||
|
||||
#define GET_IO_SLOT_AND_CTOR(x, map, slot, type, ctor, fdinfo_len) \
|
||||
do { \
|
||||
struct event_map_entry _key, *_ent; \
|
||||
_key.fd = slot; \
|
||||
_HT_FIND_OR_INSERT(event_io_map, map_node, hashsocket, map, \
|
||||
event_map_entry, &_key, ptr, \
|
||||
{ \
|
||||
_ent = *ptr; \
|
||||
}, \
|
||||
{ \
|
||||
_ent = mm_calloc(1,sizeof(struct event_map_entry)+fdinfo_len); \
|
||||
if (EVUTIL_UNLIKELY(_ent == NULL)) \
|
||||
return (-1); \
|
||||
_ent->fd = slot; \
|
||||
(ctor)(&_ent->ent.type); \
|
||||
_HT_FOI_INSERT(map_node, map, &_key, _ent, ptr) \
|
||||
}); \
|
||||
(x) = &_ent->ent.type; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
void evmap_io_initmap(struct event_io_map *ctx)
|
||||
{
|
||||
HT_INIT(event_io_map, ctx);
|
||||
}
|
||||
|
||||
void evmap_io_clear(struct event_io_map *ctx)
|
||||
{
|
||||
struct event_map_entry **ent, **next, *this;
|
||||
for (ent = HT_START(event_io_map, ctx); ent; ent = next) {
|
||||
this = *ent;
|
||||
next = HT_NEXT_RMV(event_io_map, ctx, ent);
|
||||
mm_free(this);
|
||||
}
|
||||
HT_CLEAR(event_io_map, ctx); /* remove all storage held by the ctx. */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set the variable 'x' to the field in event_map 'map' with fields of type
|
||||
'struct type *' corresponding to the fd or signal 'slot'. Set 'x' to NULL
|
||||
if there are no entries for 'slot'. Does no bounds-checking. */
|
||||
#define GET_SIGNAL_SLOT(x, map, slot, type) \
|
||||
(x) = (struct type *)((map)->entries[slot])
|
||||
/* As GET_SLOT, but construct the entry for 'slot' if it is not present,
|
||||
by allocating enough memory for a 'struct type', and initializing the new
|
||||
value by calling the function 'ctor' on it. Makes the function
|
||||
return -1 on allocation failure.
|
||||
*/
|
||||
#define GET_SIGNAL_SLOT_AND_CTOR(x, map, slot, type, ctor, fdinfo_len) \
|
||||
do { \
|
||||
if ((map)->entries[slot] == NULL) { \
|
||||
(map)->entries[slot] = \
|
||||
mm_calloc(1,sizeof(struct type)+fdinfo_len); \
|
||||
if (EVUTIL_UNLIKELY((map)->entries[slot] == NULL)) \
|
||||
return (-1); \
|
||||
(ctor)((struct type *)(map)->entries[slot]); \
|
||||
} \
|
||||
(x) = (struct type *)((map)->entries[slot]); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/* If we aren't using hashtables, then define the IO_SLOT macros and functions
|
||||
as thin aliases over the SIGNAL_SLOT versions. */
|
||||
#ifndef EVMAP_USE_HT
|
||||
#define GET_IO_SLOT(x,map,slot,type) GET_SIGNAL_SLOT(x,map,slot,type)
|
||||
#define GET_IO_SLOT_AND_CTOR(x,map,slot,type,ctor,fdinfo_len) \
|
||||
GET_SIGNAL_SLOT_AND_CTOR(x,map,slot,type,ctor,fdinfo_len)
|
||||
#define FDINFO_OFFSET sizeof(struct evmap_io)
|
||||
void
|
||||
evmap_io_initmap(struct event_io_map* ctx)
|
||||
{
|
||||
evmap_signal_initmap(ctx);
|
||||
}
|
||||
void
|
||||
evmap_io_clear(struct event_io_map* ctx)
|
||||
{
|
||||
evmap_signal_clear(ctx);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/** Expand 'map' with new entries of width 'msize' until it is big enough
|
||||
to store a value in 'slot'.
|
||||
*/
|
||||
static int
|
||||
evmap_make_space(struct event_signal_map *map, int slot, int msize)
|
||||
{
|
||||
if (map->nentries <= slot) {
|
||||
int nentries = map->nentries ? map->nentries : 32;
|
||||
void **tmp;
|
||||
|
||||
while (nentries <= slot)
|
||||
nentries <<= 1;
|
||||
|
||||
tmp = (void **)mm_realloc(map->entries, nentries * msize);
|
||||
if (tmp == NULL)
|
||||
return (-1);
|
||||
|
||||
memset(&tmp[map->nentries], 0,
|
||||
(nentries - map->nentries) * msize);
|
||||
|
||||
map->nentries = nentries;
|
||||
map->entries = tmp;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
evmap_signal_initmap(struct event_signal_map *ctx)
|
||||
{
|
||||
ctx->nentries = 0;
|
||||
ctx->entries = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
evmap_signal_clear(struct event_signal_map *ctx)
|
||||
{
|
||||
if (ctx->entries != NULL) {
|
||||
int i;
|
||||
for (i = 0; i < ctx->nentries; ++i) {
|
||||
if (ctx->entries[i] != NULL)
|
||||
mm_free(ctx->entries[i]);
|
||||
}
|
||||
mm_free(ctx->entries);
|
||||
ctx->entries = NULL;
|
||||
}
|
||||
ctx->nentries = 0;
|
||||
}
|
||||
|
||||
|
||||
/* code specific to file descriptors */
|
||||
|
||||
/** Constructor for struct evmap_io */
|
||||
static void
|
||||
evmap_io_init(struct evmap_io *entry)
|
||||
{
|
||||
TAILQ_INIT(&entry->events);
|
||||
entry->nread = 0;
|
||||
entry->nwrite = 0;
|
||||
}
|
||||
|
||||
|
||||
/* return -1 on error, 0 on success if nothing changed in the event backend,
|
||||
* and 1 on success if something did. */
|
||||
int
|
||||
evmap_io_add(struct event_base *base, evutil_socket_t fd, struct event *ev)
|
||||
{
|
||||
const struct eventop *evsel = base->evsel;
|
||||
struct event_io_map *io = &base->io;
|
||||
struct evmap_io *ctx = NULL;
|
||||
int nread, nwrite, retval = 0;
|
||||
short res = 0, old = 0;
|
||||
struct event *old_ev;
|
||||
|
||||
EVUTIL_ASSERT(fd == ev->ev_fd);
|
||||
|
||||
if (fd < 0)
|
||||
return 0;
|
||||
|
||||
#ifndef EVMAP_USE_HT
|
||||
if (fd >= io->nentries) {
|
||||
if (evmap_make_space(io, fd, sizeof(struct evmap_io *)) == -1)
|
||||
return (-1);
|
||||
}
|
||||
#endif
|
||||
GET_IO_SLOT_AND_CTOR(ctx, io, fd, evmap_io, evmap_io_init,
|
||||
evsel->fdinfo_len);
|
||||
|
||||
nread = ctx->nread;
|
||||
nwrite = ctx->nwrite;
|
||||
|
||||
if (nread)
|
||||
old |= EV_READ;
|
||||
if (nwrite)
|
||||
old |= EV_WRITE;
|
||||
|
||||
if (ev->ev_events & EV_READ) {
|
||||
if (++nread == 1)
|
||||
res |= EV_READ;
|
||||
}
|
||||
if (ev->ev_events & EV_WRITE) {
|
||||
if (++nwrite == 1)
|
||||
res |= EV_WRITE;
|
||||
}
|
||||
if (EVUTIL_UNLIKELY(nread > 0xffff || nwrite > 0xffff)) {
|
||||
event_warnx("Too many events reading or writing on fd %d",
|
||||
(int)fd);
|
||||
return -1;
|
||||
}
|
||||
if (EVENT_DEBUG_MODE_IS_ON() &&
|
||||
(old_ev = TAILQ_FIRST(&ctx->events)) &&
|
||||
(old_ev->ev_events&EV_ET) != (ev->ev_events&EV_ET)) {
|
||||
event_warnx("Tried to mix edge-triggered and non-edge-triggered"
|
||||
" events on fd %d", (int)fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (res) {
|
||||
void *extra = ((char*)ctx) + sizeof(struct evmap_io);
|
||||
/* XXX(niels): we cannot mix edge-triggered and
|
||||
* level-triggered, we should probably assert on
|
||||
* this. */
|
||||
if (evsel->add(base, ev->ev_fd,
|
||||
old, (ev->ev_events & EV_ET) | res, extra) == -1)
|
||||
return (-1);
|
||||
retval = 1;
|
||||
}
|
||||
|
||||
ctx->nread = (ev_uint16_t) nread;
|
||||
ctx->nwrite = (ev_uint16_t) nwrite;
|
||||
TAILQ_INSERT_TAIL(&ctx->events, ev, ev_io_next);
|
||||
|
||||
return (retval);
|
||||
}
|
||||
|
||||
/* return -1 on error, 0 on success if nothing changed in the event backend,
|
||||
* and 1 on success if something did. */
|
||||
int
|
||||
evmap_io_del(struct event_base *base, evutil_socket_t fd, struct event *ev)
|
||||
{
|
||||
const struct eventop *evsel = base->evsel;
|
||||
struct event_io_map *io = &base->io;
|
||||
struct evmap_io *ctx;
|
||||
int nread, nwrite, retval = 0;
|
||||
short res = 0, old = 0;
|
||||
|
||||
if (fd < 0)
|
||||
return 0;
|
||||
|
||||
EVUTIL_ASSERT(fd == ev->ev_fd);
|
||||
|
||||
#ifndef EVMAP_USE_HT
|
||||
if (fd >= io->nentries)
|
||||
return (-1);
|
||||
#endif
|
||||
|
||||
GET_IO_SLOT(ctx, io, fd, evmap_io);
|
||||
|
||||
nread = ctx->nread;
|
||||
nwrite = ctx->nwrite;
|
||||
|
||||
if (nread)
|
||||
old |= EV_READ;
|
||||
if (nwrite)
|
||||
old |= EV_WRITE;
|
||||
|
||||
if (ev->ev_events & EV_READ) {
|
||||
if (--nread == 0)
|
||||
res |= EV_READ;
|
||||
EVUTIL_ASSERT(nread >= 0);
|
||||
}
|
||||
if (ev->ev_events & EV_WRITE) {
|
||||
if (--nwrite == 0)
|
||||
res |= EV_WRITE;
|
||||
EVUTIL_ASSERT(nwrite >= 0);
|
||||
}
|
||||
|
||||
if (res) {
|
||||
void *extra = ((char*)ctx) + sizeof(struct evmap_io);
|
||||
if (evsel->del(base, ev->ev_fd, old, res, extra) == -1)
|
||||
return (-1);
|
||||
retval = 1;
|
||||
}
|
||||
|
||||
ctx->nread = nread;
|
||||
ctx->nwrite = nwrite;
|
||||
TAILQ_REMOVE(&ctx->events, ev, ev_io_next);
|
||||
|
||||
return (retval);
|
||||
}
|
||||
|
||||
void
|
||||
evmap_io_active(struct event_base *base, evutil_socket_t fd, short events)
|
||||
{
|
||||
struct event_io_map *io = &base->io;
|
||||
struct evmap_io *ctx;
|
||||
struct event *ev;
|
||||
|
||||
#ifndef EVMAP_USE_HT
|
||||
EVUTIL_ASSERT(fd < io->nentries);
|
||||
#endif
|
||||
GET_IO_SLOT(ctx, io, fd, evmap_io);
|
||||
|
||||
EVUTIL_ASSERT(ctx);
|
||||
TAILQ_FOREACH(ev, &ctx->events, ev_io_next) {
|
||||
if (ev->ev_events & events)
|
||||
event_active_nolock(ev, ev->ev_events & events, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* code specific to signals */
|
||||
|
||||
static void
|
||||
evmap_signal_init(struct evmap_signal *entry)
|
||||
{
|
||||
TAILQ_INIT(&entry->events);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
evmap_signal_add(struct event_base *base, int sig, struct event *ev)
|
||||
{
|
||||
const struct eventop *evsel = base->evsigsel;
|
||||
struct event_signal_map *map = &base->sigmap;
|
||||
struct evmap_signal *ctx = NULL;
|
||||
|
||||
if (sig >= map->nentries) {
|
||||
if (evmap_make_space(
|
||||
map, sig, sizeof(struct evmap_signal *)) == -1)
|
||||
return (-1);
|
||||
}
|
||||
GET_SIGNAL_SLOT_AND_CTOR(ctx, map, sig, evmap_signal, evmap_signal_init,
|
||||
base->evsigsel->fdinfo_len);
|
||||
|
||||
if (TAILQ_EMPTY(&ctx->events)) {
|
||||
if (evsel->add(base, ev->ev_fd, 0, EV_SIGNAL, NULL)
|
||||
== -1)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
TAILQ_INSERT_TAIL(&ctx->events, ev, ev_signal_next);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
evmap_signal_del(struct event_base *base, int sig, struct event *ev)
|
||||
{
|
||||
const struct eventop *evsel = base->evsigsel;
|
||||
struct event_signal_map *map = &base->sigmap;
|
||||
struct evmap_signal *ctx;
|
||||
|
||||
if (sig >= map->nentries)
|
||||
return (-1);
|
||||
|
||||
GET_SIGNAL_SLOT(ctx, map, sig, evmap_signal);
|
||||
|
||||
if (TAILQ_FIRST(&ctx->events) == TAILQ_LAST(&ctx->events, event_list)) {
|
||||
if (evsel->del(base, ev->ev_fd, 0, EV_SIGNAL, NULL) == -1)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
TAILQ_REMOVE(&ctx->events, ev, ev_signal_next);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
evmap_signal_active(struct event_base *base, evutil_socket_t sig, int ncalls)
|
||||
{
|
||||
struct event_signal_map *map = &base->sigmap;
|
||||
struct evmap_signal *ctx;
|
||||
struct event *ev;
|
||||
|
||||
EVUTIL_ASSERT(sig < map->nentries);
|
||||
GET_SIGNAL_SLOT(ctx, map, sig, evmap_signal);
|
||||
|
||||
TAILQ_FOREACH(ev, &ctx->events, ev_signal_next)
|
||||
event_active_nolock(ev, EV_SIGNAL, ncalls);
|
||||
}
|
||||
|
||||
void *
|
||||
evmap_io_get_fdinfo(struct event_io_map *map, evutil_socket_t fd)
|
||||
{
|
||||
struct evmap_io *ctx;
|
||||
GET_IO_SLOT(ctx, map, fd, evmap_io);
|
||||
if (ctx)
|
||||
return ((char*)ctx) + sizeof(struct evmap_io);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Per-fd structure for use with changelists. It keeps track, for each fd or
|
||||
* signal using the changelist, of where its entry in the changelist is.
|
||||
*/
|
||||
struct event_changelist_fdinfo {
|
||||
int idxplus1; /* this is the index +1, so that memset(0) will make it
|
||||
* a no-such-element */
|
||||
};
|
||||
|
||||
void
|
||||
event_changelist_init(struct event_changelist *changelist)
|
||||
{
|
||||
changelist->changes = NULL;
|
||||
changelist->changes_size = 0;
|
||||
changelist->n_changes = 0;
|
||||
}
|
||||
|
||||
/** Helper: return the changelist_fdinfo corresponding to a given change. */
|
||||
static inline struct event_changelist_fdinfo *
|
||||
event_change_get_fdinfo(struct event_base *base,
|
||||
const struct event_change *change)
|
||||
{
|
||||
char *ptr;
|
||||
if (change->read_change & EV_CHANGE_SIGNAL) {
|
||||
struct evmap_signal *ctx;
|
||||
GET_SIGNAL_SLOT(ctx, &base->sigmap, change->fd, evmap_signal);
|
||||
ptr = ((char*)ctx) + sizeof(struct evmap_signal);
|
||||
} else {
|
||||
struct evmap_io *ctx;
|
||||
GET_IO_SLOT(ctx, &base->io, change->fd, evmap_io);
|
||||
ptr = ((char*)ctx) + sizeof(struct evmap_io);
|
||||
}
|
||||
return (void*)ptr;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CHANGELIST
|
||||
/** Make sure that the changelist is consistent with the evmap structures. */
|
||||
static void
|
||||
event_changelist_check(struct event_base *base)
|
||||
{
|
||||
int i;
|
||||
struct event_changelist *changelist = &base->changelist;
|
||||
|
||||
EVUTIL_ASSERT(changelist->changes_size >= changelist->n_changes);
|
||||
for (i = 0; i < changelist->n_changes; ++i) {
|
||||
struct event_change *c = &changelist->changes[i];
|
||||
struct event_changelist_fdinfo *f;
|
||||
EVUTIL_ASSERT(c->fd >= 0);
|
||||
f = event_change_get_fdinfo(base, c);
|
||||
EVUTIL_ASSERT(f);
|
||||
EVUTIL_ASSERT(f->idxplus1 == i + 1);
|
||||
}
|
||||
|
||||
for (i = 0; i < base->io.nentries; ++i) {
|
||||
struct evmap_io *io = base->io.entries[i];
|
||||
struct event_changelist_fdinfo *f;
|
||||
if (!io)
|
||||
continue;
|
||||
f = (void*)
|
||||
( ((char*)io) + sizeof(struct evmap_io) );
|
||||
if (f->idxplus1) {
|
||||
struct event_change *c = &changelist->changes[f->idxplus1 - 1];
|
||||
EVUTIL_ASSERT(c->fd == i);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define event_changelist_check(base) ((void)0)
|
||||
#endif
|
||||
|
||||
void
|
||||
event_changelist_remove_all(struct event_changelist *changelist,
|
||||
struct event_base *base)
|
||||
{
|
||||
int i;
|
||||
|
||||
event_changelist_check(base);
|
||||
|
||||
for (i = 0; i < changelist->n_changes; ++i) {
|
||||
struct event_change *ch = &changelist->changes[i];
|
||||
struct event_changelist_fdinfo *fdinfo =
|
||||
event_change_get_fdinfo(base, ch);
|
||||
EVUTIL_ASSERT(fdinfo->idxplus1 == i + 1);
|
||||
fdinfo->idxplus1 = 0;
|
||||
}
|
||||
|
||||
changelist->n_changes = 0;
|
||||
|
||||
event_changelist_check(base);
|
||||
}
|
||||
|
||||
void
|
||||
event_changelist_freemem(struct event_changelist *changelist)
|
||||
{
|
||||
if (changelist->changes)
|
||||
mm_free(changelist->changes);
|
||||
event_changelist_init(changelist); /* zero it all out. */
|
||||
}
|
||||
|
||||
/** Increase the size of 'changelist' to hold more changes. */
|
||||
static int
|
||||
event_changelist_grow(struct event_changelist *changelist)
|
||||
{
|
||||
int new_size;
|
||||
struct event_change *new_changes;
|
||||
if (changelist->changes_size < 64)
|
||||
new_size = 64;
|
||||
else
|
||||
new_size = changelist->changes_size * 2;
|
||||
|
||||
new_changes = mm_realloc(changelist->changes,
|
||||
new_size * sizeof(struct event_change));
|
||||
|
||||
if (EVUTIL_UNLIKELY(new_changes == NULL))
|
||||
return (-1);
|
||||
|
||||
changelist->changes = new_changes;
|
||||
changelist->changes_size = new_size;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/** Return a pointer to the changelist entry for the file descriptor or signal
|
||||
* 'fd', whose fdinfo is 'fdinfo'. If none exists, construct it, setting its
|
||||
* old_events field to old_events.
|
||||
*/
|
||||
static struct event_change *
|
||||
event_changelist_get_or_construct(struct event_changelist *changelist,
|
||||
evutil_socket_t fd,
|
||||
short old_events,
|
||||
struct event_changelist_fdinfo *fdinfo)
|
||||
{
|
||||
struct event_change *change;
|
||||
|
||||
if (fdinfo->idxplus1 == 0) {
|
||||
int idx;
|
||||
EVUTIL_ASSERT(changelist->n_changes <= changelist->changes_size);
|
||||
|
||||
if (changelist->n_changes == changelist->changes_size) {
|
||||
if (event_changelist_grow(changelist) < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
idx = changelist->n_changes++;
|
||||
change = &changelist->changes[idx];
|
||||
fdinfo->idxplus1 = idx + 1;
|
||||
|
||||
memset(change, 0, sizeof(struct event_change));
|
||||
change->fd = fd;
|
||||
change->old_events = old_events;
|
||||
} else {
|
||||
change = &changelist->changes[fdinfo->idxplus1 - 1];
|
||||
EVUTIL_ASSERT(change->fd == fd);
|
||||
}
|
||||
return change;
|
||||
}
|
||||
|
||||
int
|
||||
event_changelist_add(struct event_base *base, evutil_socket_t fd, short old, short events,
|
||||
void *p)
|
||||
{
|
||||
struct event_changelist *changelist = &base->changelist;
|
||||
struct event_changelist_fdinfo *fdinfo = p;
|
||||
struct event_change *change;
|
||||
|
||||
event_changelist_check(base);
|
||||
|
||||
change = event_changelist_get_or_construct(changelist, fd, old, fdinfo);
|
||||
if (!change)
|
||||
return -1;
|
||||
|
||||
/* An add replaces any previous delete, but doesn't result in a no-op,
|
||||
* since the delete might fail (because the fd had been closed since
|
||||
* the last add, for instance. */
|
||||
|
||||
if (events & (EV_READ|EV_SIGNAL)) {
|
||||
change->read_change = EV_CHANGE_ADD |
|
||||
(events & (EV_ET|EV_PERSIST|EV_SIGNAL));
|
||||
}
|
||||
if (events & EV_WRITE) {
|
||||
change->write_change = EV_CHANGE_ADD |
|
||||
(events & (EV_ET|EV_PERSIST|EV_SIGNAL));
|
||||
}
|
||||
|
||||
event_changelist_check(base);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
event_changelist_del(struct event_base *base, evutil_socket_t fd, short old, short events,
|
||||
void *p)
|
||||
{
|
||||
struct event_changelist *changelist = &base->changelist;
|
||||
struct event_changelist_fdinfo *fdinfo = p;
|
||||
struct event_change *change;
|
||||
|
||||
event_changelist_check(base);
|
||||
change = event_changelist_get_or_construct(changelist, fd, old, fdinfo);
|
||||
event_changelist_check(base);
|
||||
if (!change)
|
||||
return -1;
|
||||
|
||||
/* A delete removes any previous add, rather than replacing it:
|
||||
on those platforms where "add, delete, dispatch" is not the same
|
||||
as "no-op, dispatch", we want the no-op behavior.
|
||||
|
||||
As well as checking the current operation we should also check
|
||||
the original set of events to make sure were not ignoring
|
||||
the case where the add operation is present on an event that
|
||||
was already set.
|
||||
|
||||
If we have a no-op item, we could remove it it from the list
|
||||
entirely, but really there's not much point: skipping the no-op
|
||||
change when we do the dispatch later is far cheaper than rejuggling
|
||||
the array now.
|
||||
|
||||
As this stands, it also lets through deletions of events that are
|
||||
not currently set.
|
||||
*/
|
||||
|
||||
if (events & (EV_READ|EV_SIGNAL)) {
|
||||
if (!(change->old_events & (EV_READ | EV_SIGNAL)) &&
|
||||
(change->read_change & EV_CHANGE_ADD))
|
||||
change->read_change = 0;
|
||||
else
|
||||
change->read_change = EV_CHANGE_DEL;
|
||||
}
|
||||
if (events & EV_WRITE) {
|
||||
if (!(change->old_events & EV_WRITE) &&
|
||||
(change->write_change & EV_CHANGE_ADD))
|
||||
change->write_change = 0;
|
||||
else
|
||||
change->write_change = EV_CHANGE_DEL;
|
||||
}
|
||||
|
||||
event_changelist_check(base);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
evmap_check_integrity(struct event_base *base)
|
||||
{
|
||||
#define EVLIST_X_SIGFOUND 0x1000
|
||||
#define EVLIST_X_IOFOUND 0x2000
|
||||
|
||||
evutil_socket_t i;
|
||||
struct event *ev;
|
||||
struct event_io_map *io = &base->io;
|
||||
struct event_signal_map *sigmap = &base->sigmap;
|
||||
#ifdef EVMAP_USE_HT
|
||||
struct event_map_entry **mapent;
|
||||
#endif
|
||||
int nsignals, ntimers, nio;
|
||||
nsignals = ntimers = nio = 0;
|
||||
|
||||
TAILQ_FOREACH(ev, &base->eventqueue, ev_next) {
|
||||
EVUTIL_ASSERT(ev->ev_flags & EVLIST_INSERTED);
|
||||
EVUTIL_ASSERT(ev->ev_flags & EVLIST_INIT);
|
||||
ev->ev_flags &= ~(EVLIST_X_SIGFOUND|EVLIST_X_IOFOUND);
|
||||
}
|
||||
|
||||
#ifdef EVMAP_USE_HT
|
||||
HT_FOREACH(mapent, event_io_map, io) {
|
||||
struct evmap_io *ctx = &(*mapent)->ent.evmap_io;
|
||||
i = (*mapent)->fd;
|
||||
#else
|
||||
for (i = 0; i < io->nentries; ++i) {
|
||||
struct evmap_io *ctx = io->entries[i];
|
||||
|
||||
if (!ctx)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
TAILQ_FOREACH(ev, &ctx->events, ev_io_next) {
|
||||
EVUTIL_ASSERT(!(ev->ev_flags & EVLIST_X_IOFOUND));
|
||||
EVUTIL_ASSERT(ev->ev_fd == i);
|
||||
ev->ev_flags |= EVLIST_X_IOFOUND;
|
||||
nio++;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < sigmap->nentries; ++i) {
|
||||
struct evmap_signal *ctx = sigmap->entries[i];
|
||||
if (!ctx)
|
||||
continue;
|
||||
|
||||
TAILQ_FOREACH(ev, &ctx->events, ev_signal_next) {
|
||||
EVUTIL_ASSERT(!(ev->ev_flags & EVLIST_X_SIGFOUND));
|
||||
EVUTIL_ASSERT(ev->ev_fd == i);
|
||||
ev->ev_flags |= EVLIST_X_SIGFOUND;
|
||||
nsignals++;
|
||||
}
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(ev, &base->eventqueue, ev_next) {
|
||||
if (ev->ev_events & (EV_READ|EV_WRITE)) {
|
||||
EVUTIL_ASSERT(ev->ev_flags & EVLIST_X_IOFOUND);
|
||||
--nio;
|
||||
}
|
||||
if (ev->ev_events & EV_SIGNAL) {
|
||||
EVUTIL_ASSERT(ev->ev_flags & EVLIST_X_SIGFOUND);
|
||||
--nsignals;
|
||||
}
|
||||
}
|
||||
|
||||
EVUTIL_ASSERT(nio == 0);
|
||||
EVUTIL_ASSERT(nsignals == 0);
|
||||
/* There is no "EVUTIL_ASSERT(ntimers == 0)": eventqueue is only for
|
||||
* pending signals and io events.
|
||||
*/
|
||||
}
|
476
external/bsd/libevent/dist/evport.c
vendored
Normal file
476
external/bsd/libevent/dist/evport.c
vendored
Normal file
|
@ -0,0 +1,476 @@
|
|||
/* $NetBSD: evport.c,v 1.1.1.1 2013/04/11 16:43:25 christos Exp $ */
|
||||
/*
|
||||
* Submitted by David Pacheco (dp.spambait@gmail.com)
|
||||
*
|
||||
* Copyright 2006-2007 Niels Provos
|
||||
* Copyright 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 SUN MICROSYSTEMS, INC. ``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 SUN MICROSYSTEMS, INC. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Sun Microsystems. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
/*
|
||||
* evport.c: event backend using Solaris 10 event ports. See port_create(3C).
|
||||
* This implementation is loosely modeled after the one used for select(2) (in
|
||||
* select.c).
|
||||
*
|
||||
* The outstanding events are tracked in a data structure called evport_data.
|
||||
* Each entry in the ed_fds array corresponds to a file descriptor, and contains
|
||||
* pointers to the read and write events that correspond to that fd. (That is,
|
||||
* when the file is readable, the "read" event should handle it, etc.)
|
||||
*
|
||||
* evport_add and evport_del update this data structure. evport_dispatch uses it
|
||||
* to determine where to callback when an event occurs (which it gets from
|
||||
* port_getn).
|
||||
*
|
||||
* Helper functions are used: grow() grows the file descriptor array as
|
||||
* necessary when large fd's come in. reassociate() takes care of maintaining
|
||||
* the proper file-descriptor/event-port associations.
|
||||
*
|
||||
* As in the select(2) implementation, signals are handled by evsignal.
|
||||
*/
|
||||
|
||||
#include "event2/event-config.h"
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: evport.c,v 1.1.1.1 2013/04/11 16:43:25 christos Exp $");
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/queue.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <port.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "event2/thread.h"
|
||||
|
||||
#include "evthread-internal.h"
|
||||
#include "event-internal.h"
|
||||
#include "log-internal.h"
|
||||
#include "evsignal-internal.h"
|
||||
#include "evmap-internal.h"
|
||||
|
||||
/*
|
||||
* Default value for ed_nevents, which is the maximum file descriptor number we
|
||||
* can handle. If an event comes in for a file descriptor F > nevents, we will
|
||||
* grow the array of file descriptors, doubling its size.
|
||||
*/
|
||||
#define DEFAULT_NFDS 16
|
||||
|
||||
|
||||
/*
|
||||
* EVENTS_PER_GETN is the maximum number of events to retrieve from port_getn on
|
||||
* any particular call. You can speed things up by increasing this, but it will
|
||||
* (obviously) require more memory.
|
||||
*/
|
||||
#define EVENTS_PER_GETN 8
|
||||
|
||||
/*
|
||||
* Per-file-descriptor information about what events we're subscribed to. These
|
||||
* fields are NULL if no event is subscribed to either of them.
|
||||
*/
|
||||
|
||||
struct fd_info {
|
||||
short fdi_what; /* combinations of EV_READ and EV_WRITE */
|
||||
};
|
||||
|
||||
#define FDI_HAS_READ(fdi) ((fdi)->fdi_what & EV_READ)
|
||||
#define FDI_HAS_WRITE(fdi) ((fdi)->fdi_what & EV_WRITE)
|
||||
#define FDI_HAS_EVENTS(fdi) (FDI_HAS_READ(fdi) || FDI_HAS_WRITE(fdi))
|
||||
#define FDI_TO_SYSEVENTS(fdi) (FDI_HAS_READ(fdi) ? POLLIN : 0) | \
|
||||
(FDI_HAS_WRITE(fdi) ? POLLOUT : 0)
|
||||
|
||||
struct evport_data {
|
||||
int ed_port; /* event port for system events */
|
||||
int ed_nevents; /* number of allocated fdi's */
|
||||
struct fd_info *ed_fds; /* allocated fdi table */
|
||||
/* fdi's that we need to reassoc */
|
||||
int ed_pending[EVENTS_PER_GETN]; /* fd's with pending events */
|
||||
};
|
||||
|
||||
static void* evport_init(struct event_base *);
|
||||
static int evport_add(struct event_base *, int fd, short old, short events, void *);
|
||||
static int evport_del(struct event_base *, int fd, short old, short events, void *);
|
||||
static int evport_dispatch(struct event_base *, struct timeval *);
|
||||
static void evport_dealloc(struct event_base *);
|
||||
|
||||
const struct eventop evportops = {
|
||||
"evport",
|
||||
evport_init,
|
||||
evport_add,
|
||||
evport_del,
|
||||
evport_dispatch,
|
||||
evport_dealloc,
|
||||
1, /* need reinit */
|
||||
0, /* features */
|
||||
0, /* fdinfo length */
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize the event port implementation.
|
||||
*/
|
||||
|
||||
static void*
|
||||
evport_init(struct event_base *base)
|
||||
{
|
||||
struct evport_data *evpd;
|
||||
int i;
|
||||
|
||||
if (!(evpd = mm_calloc(1, sizeof(struct evport_data))))
|
||||
return (NULL);
|
||||
|
||||
if ((evpd->ed_port = port_create()) == -1) {
|
||||
mm_free(evpd);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize file descriptor structure
|
||||
*/
|
||||
evpd->ed_fds = mm_calloc(DEFAULT_NFDS, sizeof(struct fd_info));
|
||||
if (evpd->ed_fds == NULL) {
|
||||
close(evpd->ed_port);
|
||||
mm_free(evpd);
|
||||
return (NULL);
|
||||
}
|
||||
evpd->ed_nevents = DEFAULT_NFDS;
|
||||
for (i = 0; i < EVENTS_PER_GETN; i++)
|
||||
evpd->ed_pending[i] = -1;
|
||||
|
||||
evsig_init(base);
|
||||
|
||||
return (evpd);
|
||||
}
|
||||
|
||||
#ifdef CHECK_INVARIANTS
|
||||
/*
|
||||
* Checks some basic properties about the evport_data structure. Because it
|
||||
* checks all file descriptors, this function can be expensive when the maximum
|
||||
* file descriptor ever used is rather large.
|
||||
*/
|
||||
|
||||
static void
|
||||
check_evportop(struct evport_data *evpd)
|
||||
{
|
||||
EVUTIL_ASSERT(evpd);
|
||||
EVUTIL_ASSERT(evpd->ed_nevents > 0);
|
||||
EVUTIL_ASSERT(evpd->ed_port > 0);
|
||||
EVUTIL_ASSERT(evpd->ed_fds > 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Verifies very basic integrity of a given port_event.
|
||||
*/
|
||||
static void
|
||||
check_event(port_event_t* pevt)
|
||||
{
|
||||
/*
|
||||
* We've only registered for PORT_SOURCE_FD events. The only
|
||||
* other thing we can legitimately receive is PORT_SOURCE_ALERT,
|
||||
* but since we're not using port_alert either, we can assume
|
||||
* PORT_SOURCE_FD.
|
||||
*/
|
||||
EVUTIL_ASSERT(pevt->portev_source == PORT_SOURCE_FD);
|
||||
EVUTIL_ASSERT(pevt->portev_user == NULL);
|
||||
}
|
||||
|
||||
#else
|
||||
#define check_evportop(epop)
|
||||
#define check_event(pevt)
|
||||
#endif /* CHECK_INVARIANTS */
|
||||
|
||||
/*
|
||||
* Doubles the size of the allocated file descriptor array.
|
||||
*/
|
||||
static int
|
||||
grow(struct evport_data *epdp, int factor)
|
||||
{
|
||||
struct fd_info *tmp;
|
||||
int oldsize = epdp->ed_nevents;
|
||||
int newsize = factor * oldsize;
|
||||
EVUTIL_ASSERT(factor > 1);
|
||||
|
||||
check_evportop(epdp);
|
||||
|
||||
tmp = mm_realloc(epdp->ed_fds, sizeof(struct fd_info) * newsize);
|
||||
if (NULL == tmp)
|
||||
return -1;
|
||||
epdp->ed_fds = tmp;
|
||||
memset((char*) (epdp->ed_fds + oldsize), 0,
|
||||
(newsize - oldsize)*sizeof(struct fd_info));
|
||||
epdp->ed_nevents = newsize;
|
||||
|
||||
check_evportop(epdp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (Re)associates the given file descriptor with the event port. The OS events
|
||||
* are specified (implicitly) from the fd_info struct.
|
||||
*/
|
||||
static int
|
||||
reassociate(struct evport_data *epdp, struct fd_info *fdip, int fd)
|
||||
{
|
||||
int sysevents = FDI_TO_SYSEVENTS(fdip);
|
||||
|
||||
if (sysevents != 0) {
|
||||
if (port_associate(epdp->ed_port, PORT_SOURCE_FD,
|
||||
fd, sysevents, NULL) == -1) {
|
||||
event_warn("port_associate");
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
check_evportop(epdp);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Main event loop - polls port_getn for some number of events, and processes
|
||||
* them.
|
||||
*/
|
||||
|
||||
static int
|
||||
evport_dispatch(struct event_base *base, struct timeval *tv)
|
||||
{
|
||||
int i, res;
|
||||
struct evport_data *epdp = base->evbase;
|
||||
port_event_t pevtlist[EVENTS_PER_GETN];
|
||||
|
||||
/*
|
||||
* port_getn will block until it has at least nevents events. It will
|
||||
* also return how many it's given us (which may be more than we asked
|
||||
* for, as long as it's less than our maximum (EVENTS_PER_GETN)) in
|
||||
* nevents.
|
||||
*/
|
||||
int nevents = 1;
|
||||
|
||||
/*
|
||||
* We have to convert a struct timeval to a struct timespec
|
||||
* (only difference is nanoseconds vs. microseconds). If no time-based
|
||||
* events are active, we should wait for I/O (and tv == NULL).
|
||||
*/
|
||||
struct timespec ts;
|
||||
struct timespec *ts_p = NULL;
|
||||
if (tv != NULL) {
|
||||
ts.tv_sec = tv->tv_sec;
|
||||
ts.tv_nsec = tv->tv_usec * 1000;
|
||||
ts_p = &ts;
|
||||
}
|
||||
|
||||
/*
|
||||
* Before doing anything else, we need to reassociate the events we hit
|
||||
* last time which need reassociation. See comment at the end of the
|
||||
* loop below.
|
||||
*/
|
||||
for (i = 0; i < EVENTS_PER_GETN; ++i) {
|
||||
struct fd_info *fdi = NULL;
|
||||
if (epdp->ed_pending[i] != -1) {
|
||||
fdi = &(epdp->ed_fds[epdp->ed_pending[i]]);
|
||||
}
|
||||
|
||||
if (fdi != NULL && FDI_HAS_EVENTS(fdi)) {
|
||||
int fd = epdp->ed_pending[i];
|
||||
reassociate(epdp, fdi, fd);
|
||||
epdp->ed_pending[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
EVBASE_RELEASE_LOCK(base, th_base_lock);
|
||||
|
||||
res = port_getn(epdp->ed_port, pevtlist, EVENTS_PER_GETN,
|
||||
(unsigned int *) &nevents, ts_p);
|
||||
|
||||
EVBASE_ACQUIRE_LOCK(base, th_base_lock);
|
||||
|
||||
if (res == -1) {
|
||||
if (errno == EINTR || errno == EAGAIN) {
|
||||
return (0);
|
||||
} else if (errno == ETIME) {
|
||||
if (nevents == 0)
|
||||
return (0);
|
||||
} else {
|
||||
event_warn("port_getn");
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
event_debug(("%s: port_getn reports %d events", __func__, nevents));
|
||||
|
||||
for (i = 0; i < nevents; ++i) {
|
||||
struct fd_info *fdi;
|
||||
port_event_t *pevt = &pevtlist[i];
|
||||
int fd = (int) pevt->portev_object;
|
||||
|
||||
check_evportop(epdp);
|
||||
check_event(pevt);
|
||||
epdp->ed_pending[i] = fd;
|
||||
|
||||
/*
|
||||
* Figure out what kind of event it was
|
||||
* (because we have to pass this to the callback)
|
||||
*/
|
||||
res = 0;
|
||||
if (pevt->portev_events & (POLLERR|POLLHUP)) {
|
||||
res = EV_READ | EV_WRITE;
|
||||
} else {
|
||||
if (pevt->portev_events & POLLIN)
|
||||
res |= EV_READ;
|
||||
if (pevt->portev_events & POLLOUT)
|
||||
res |= EV_WRITE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for the error situations or a hangup situation
|
||||
*/
|
||||
if (pevt->portev_events & (POLLERR|POLLHUP|POLLNVAL))
|
||||
res |= EV_READ|EV_WRITE;
|
||||
|
||||
EVUTIL_ASSERT(epdp->ed_nevents > fd);
|
||||
fdi = &(epdp->ed_fds[fd]);
|
||||
|
||||
evmap_io_active(base, fd, res);
|
||||
} /* end of all events gotten */
|
||||
|
||||
check_evportop(epdp);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Adds the given event (so that you will be notified when it happens via
|
||||
* the callback function).
|
||||
*/
|
||||
|
||||
static int
|
||||
evport_add(struct event_base *base, int fd, short old, short events, void *p)
|
||||
{
|
||||
struct evport_data *evpd = base->evbase;
|
||||
struct fd_info *fdi;
|
||||
int factor;
|
||||
(void)p;
|
||||
|
||||
check_evportop(evpd);
|
||||
|
||||
/*
|
||||
* If necessary, grow the file descriptor info table
|
||||
*/
|
||||
|
||||
factor = 1;
|
||||
while (fd >= factor * evpd->ed_nevents)
|
||||
factor *= 2;
|
||||
|
||||
if (factor > 1) {
|
||||
if (-1 == grow(evpd, factor)) {
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
fdi = &evpd->ed_fds[fd];
|
||||
fdi->fdi_what |= events;
|
||||
|
||||
return reassociate(evpd, fdi, fd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes the given event from the list of events to wait for.
|
||||
*/
|
||||
|
||||
static int
|
||||
evport_del(struct event_base *base, int fd, short old, short events, void *p)
|
||||
{
|
||||
struct evport_data *evpd = base->evbase;
|
||||
struct fd_info *fdi;
|
||||
int i;
|
||||
int associated = 1;
|
||||
(void)p;
|
||||
|
||||
check_evportop(evpd);
|
||||
|
||||
if (evpd->ed_nevents < fd) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
for (i = 0; i < EVENTS_PER_GETN; ++i) {
|
||||
if (evpd->ed_pending[i] == fd) {
|
||||
associated = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fdi = &evpd->ed_fds[fd];
|
||||
if (events & EV_READ)
|
||||
fdi->fdi_what &= ~EV_READ;
|
||||
if (events & EV_WRITE)
|
||||
fdi->fdi_what &= ~EV_WRITE;
|
||||
|
||||
if (associated) {
|
||||
if (!FDI_HAS_EVENTS(fdi) &&
|
||||
port_dissociate(evpd->ed_port, PORT_SOURCE_FD, fd) == -1) {
|
||||
/*
|
||||
* Ignore EBADFD error the fd could have been closed
|
||||
* before event_del() was called.
|
||||
*/
|
||||
if (errno != EBADFD) {
|
||||
event_warn("port_dissociate");
|
||||
return (-1);
|
||||
}
|
||||
} else {
|
||||
if (FDI_HAS_EVENTS(fdi)) {
|
||||
return (reassociate(evpd, fdi, fd));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((fdi->fdi_what & (EV_READ|EV_WRITE)) == 0) {
|
||||
evpd->ed_pending[i] = -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
evport_dealloc(struct event_base *base)
|
||||
{
|
||||
struct evport_data *evpd = base->evbase;
|
||||
|
||||
evsig_dealloc(base);
|
||||
|
||||
close(evpd->ed_port);
|
||||
|
||||
if (evpd->ed_fds)
|
||||
mm_free(evpd->ed_fds);
|
||||
mm_free(evpd);
|
||||
}
|
205
external/bsd/libevent/dist/evrpc-internal.h
vendored
Normal file
205
external/bsd/libevent/dist/evrpc-internal.h
vendored
Normal file
|
@ -0,0 +1,205 @@
|
|||
/* $NetBSD: evrpc-internal.h,v 1.1.1.2 2013/04/11 16:43:20 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* 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 _EVRPC_INTERNAL_H_
|
||||
#define _EVRPC_INTERNAL_H_
|
||||
|
||||
#include "http-internal.h"
|
||||
|
||||
struct evrpc;
|
||||
struct evrpc_request_wrapper;
|
||||
|
||||
#define EVRPC_URI_PREFIX "/.rpc."
|
||||
|
||||
struct evrpc_hook {
|
||||
TAILQ_ENTRY(evrpc_hook) next;
|
||||
|
||||
/* returns EVRPC_TERMINATE; if the rpc should be aborted.
|
||||
* a hook is is allowed to rewrite the evbuffer
|
||||
*/
|
||||
int (*process)(void *, struct evhttp_request *,
|
||||
struct evbuffer *, void *);
|
||||
void *process_arg;
|
||||
};
|
||||
|
||||
TAILQ_HEAD(evrpc_hook_list, evrpc_hook);
|
||||
|
||||
/*
|
||||
* this is shared between the base and the pool, so that we can reuse
|
||||
* the hook adding functions; we alias both evrpc_pool and evrpc_base
|
||||
* to this common structure.
|
||||
*/
|
||||
|
||||
struct evrpc_hook_ctx;
|
||||
TAILQ_HEAD(evrpc_pause_list, evrpc_hook_ctx);
|
||||
|
||||
struct _evrpc_hooks {
|
||||
/* hooks for processing outbound and inbound rpcs */
|
||||
struct evrpc_hook_list in_hooks;
|
||||
struct evrpc_hook_list out_hooks;
|
||||
|
||||
struct evrpc_pause_list pause_requests;
|
||||
};
|
||||
|
||||
#define input_hooks common.in_hooks
|
||||
#define output_hooks common.out_hooks
|
||||
#define paused_requests common.pause_requests
|
||||
|
||||
struct evrpc_base {
|
||||
struct _evrpc_hooks common;
|
||||
|
||||
/* the HTTP server under which we register our RPC calls */
|
||||
struct evhttp* http_server;
|
||||
|
||||
/* a list of all RPCs registered with us */
|
||||
TAILQ_HEAD(evrpc_list, evrpc) registered_rpcs;
|
||||
};
|
||||
|
||||
struct evrpc_req_generic;
|
||||
void evrpc_reqstate_free(struct evrpc_req_generic* rpc_state);
|
||||
|
||||
/* A pool for holding evhttp_connection objects */
|
||||
struct evrpc_pool {
|
||||
struct _evrpc_hooks common;
|
||||
|
||||
struct event_base *base;
|
||||
|
||||
struct evconq connections;
|
||||
|
||||
int timeout;
|
||||
|
||||
TAILQ_HEAD(evrpc_requestq, evrpc_request_wrapper) (requests);
|
||||
};
|
||||
|
||||
struct evrpc_hook_ctx {
|
||||
TAILQ_ENTRY(evrpc_hook_ctx) next;
|
||||
|
||||
void *ctx;
|
||||
void (*cb)(void *, enum EVRPC_HOOK_RESULT);
|
||||
};
|
||||
|
||||
struct evrpc_meta {
|
||||
TAILQ_ENTRY(evrpc_meta) next;
|
||||
char *key;
|
||||
|
||||
void *data;
|
||||
size_t data_size;
|
||||
};
|
||||
|
||||
TAILQ_HEAD(evrpc_meta_list, evrpc_meta);
|
||||
|
||||
struct evrpc_hook_meta {
|
||||
struct evrpc_meta_list meta_data;
|
||||
struct evhttp_connection *evcon;
|
||||
};
|
||||
|
||||
/* allows association of meta data with a request */
|
||||
static void evrpc_hook_associate_meta(struct evrpc_hook_meta **pctx,
|
||||
struct evhttp_connection *evcon);
|
||||
|
||||
/* creates a new meta data store */
|
||||
static struct evrpc_hook_meta *evrpc_hook_meta_new(void);
|
||||
|
||||
/* frees the meta data associated with a request */
|
||||
static void evrpc_hook_context_free(struct evrpc_hook_meta *ctx);
|
||||
|
||||
/* the server side of an rpc */
|
||||
|
||||
/* We alias the RPC specific structs to this voided one */
|
||||
struct evrpc_req_generic {
|
||||
/*
|
||||
* allows association of meta data via hooks - needs to be
|
||||
* synchronized with evrpc_request_wrapper
|
||||
*/
|
||||
struct evrpc_hook_meta *hook_meta;
|
||||
|
||||
/* the unmarshaled request object */
|
||||
void *request;
|
||||
|
||||
/* the empty reply object that needs to be filled in */
|
||||
void *reply;
|
||||
|
||||
/*
|
||||
* the static structure for this rpc; that can be used to
|
||||
* automatically unmarshal and marshal the http buffers.
|
||||
*/
|
||||
struct evrpc *rpc;
|
||||
|
||||
/*
|
||||
* the http request structure on which we need to answer.
|
||||
*/
|
||||
struct evhttp_request* http_req;
|
||||
|
||||
/*
|
||||
* Temporary data store for marshaled data
|
||||
*/
|
||||
struct evbuffer* rpc_data;
|
||||
};
|
||||
|
||||
/* the client side of an rpc request */
|
||||
struct evrpc_request_wrapper {
|
||||
/*
|
||||
* allows association of meta data via hooks - needs to be
|
||||
* synchronized with evrpc_req_generic.
|
||||
*/
|
||||
struct evrpc_hook_meta *hook_meta;
|
||||
|
||||
TAILQ_ENTRY(evrpc_request_wrapper) next;
|
||||
|
||||
/* pool on which this rpc request is being made */
|
||||
struct evrpc_pool *pool;
|
||||
|
||||
/* connection on which the request is being sent */
|
||||
struct evhttp_connection *evcon;
|
||||
|
||||
/* the actual request */
|
||||
struct evhttp_request *req;
|
||||
|
||||
/* event for implementing request timeouts */
|
||||
struct event ev_timeout;
|
||||
|
||||
/* the name of the rpc */
|
||||
char *name;
|
||||
|
||||
/* callback */
|
||||
void (*cb)(struct evrpc_status*, void *request, void *reply, void *arg);
|
||||
void *cb_arg;
|
||||
|
||||
void *request;
|
||||
void *reply;
|
||||
|
||||
/* unmarshals the buffer into the proper request structure */
|
||||
void (*request_marshal)(struct evbuffer *, void *);
|
||||
|
||||
/* removes all stored state in the reply */
|
||||
void (*reply_clear)(void *);
|
||||
|
||||
/* marshals the reply into a buffer */
|
||||
int (*reply_unmarshal)(void *, struct evbuffer*);
|
||||
};
|
||||
|
||||
#endif /* _EVRPC_INTERNAL_H_ */
|
1177
external/bsd/libevent/dist/evrpc.c
vendored
Normal file
1177
external/bsd/libevent/dist/evrpc.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
46
external/bsd/libevent/dist/evrpc.h
vendored
Normal file
46
external/bsd/libevent/dist/evrpc.h
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
/* $NetBSD: evrpc.h,v 1.1.1.2 2013/04/11 16:43:29 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* 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 _EVRPC_H_
|
||||
#define _EVRPC_H_
|
||||
|
||||
/** @file evrpc.h
|
||||
|
||||
An RPC system for Libevent.
|
||||
|
||||
The <evrpc.h> header is deprecated in Libevent 2.0 and later; please
|
||||
use <event2/rpc.h> instead. Depending on what functionality you
|
||||
need, you may also want to include more of the other <event2/...>
|
||||
headers.
|
||||
*/
|
||||
|
||||
#include <event.h>
|
||||
#include <event2/rpc.h>
|
||||
#include <event2/rpc_struct.h>
|
||||
#include <event2/rpc_compat.h>
|
||||
|
||||
#endif /* _EVRPC_H_ */
|
65
external/bsd/libevent/dist/evsignal-internal.h
vendored
Normal file
65
external/bsd/libevent/dist/evsignal-internal.h
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
/* $NetBSD: evsignal-internal.h,v 1.1.1.1 2013/04/11 16:43:26 christos Exp $ */
|
||||
/*
|
||||
* Copyright 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright 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 _EVSIGNAL_H_
|
||||
#define _EVSIGNAL_H_
|
||||
|
||||
#ifndef evutil_socket_t
|
||||
#include "event2/util.h"
|
||||
#endif
|
||||
#include <signal.h>
|
||||
|
||||
typedef void (*ev_sighandler_t)(int);
|
||||
|
||||
/* Data structure for the default signal-handling implementation in signal.c
|
||||
*/
|
||||
struct evsig_info {
|
||||
/* Event watching ev_signal_pair[1] */
|
||||
struct event ev_signal;
|
||||
/* Socketpair used to send notifications from the signal handler */
|
||||
evutil_socket_t ev_signal_pair[2];
|
||||
/* True iff we've added the ev_signal event yet. */
|
||||
int ev_signal_added;
|
||||
/* Count of the number of signals we're currently watching. */
|
||||
int ev_n_signals_added;
|
||||
|
||||
/* Array of previous signal handler objects before Libevent started
|
||||
* messing with them. Used to restore old signal handlers. */
|
||||
#ifdef _EVENT_HAVE_SIGACTION
|
||||
struct sigaction **sh_old;
|
||||
#else
|
||||
ev_sighandler_t **sh_old;
|
||||
#endif
|
||||
/* Size of sh_old. */
|
||||
int sh_old_max;
|
||||
};
|
||||
int evsig_init(struct event_base *);
|
||||
void evsig_dealloc(struct event_base *);
|
||||
|
||||
void evsig_set_base(struct event_base *base);
|
||||
|
||||
#endif /* _EVSIGNAL_H_ */
|
383
external/bsd/libevent/dist/evthread-internal.h
vendored
Normal file
383
external/bsd/libevent/dist/evthread-internal.h
vendored
Normal file
|
@ -0,0 +1,383 @@
|
|||
/* $NetBSD: evthread-internal.h,v 1.2 2013/04/11 16:56:41 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008-2012 Niels Provos, 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 _EVTHREAD_INTERNAL_H_
|
||||
#define _EVTHREAD_INTERNAL_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "event2/thread.h"
|
||||
#include "event2/event-config.h"
|
||||
#include "util-internal.h"
|
||||
|
||||
struct event_base;
|
||||
|
||||
#ifndef WIN32
|
||||
/* On Windows, the way we currently make DLLs, it's not allowed for us to
|
||||
* have shared global structures. Thus, we only do the direct-call-to-function
|
||||
* code path if we know that the local shared library system supports it.
|
||||
*/
|
||||
#define EVTHREAD_EXPOSE_STRUCTS
|
||||
#endif
|
||||
|
||||
#if ! defined(_EVENT_DISABLE_THREAD_SUPPORT) && defined(EVTHREAD_EXPOSE_STRUCTS)
|
||||
/* Global function pointers to lock-related functions. NULL if locking isn't
|
||||
enabled. */
|
||||
extern struct evthread_lock_callbacks _evthread_lock_fns;
|
||||
extern struct evthread_condition_callbacks _evthread_cond_fns;
|
||||
extern unsigned long (*_evthread_id_fn)(void);
|
||||
extern int _evthread_lock_debugging_enabled;
|
||||
|
||||
/** Return the ID of the current thread, or 1 if threading isn't enabled. */
|
||||
#define EVTHREAD_GET_ID() \
|
||||
(_evthread_id_fn ? _evthread_id_fn() : 1)
|
||||
|
||||
/** Return true iff we're in the thread that is currently (or most recently)
|
||||
* running a given event_base's loop. Requires lock. */
|
||||
#define EVBASE_IN_THREAD(base) \
|
||||
(_evthread_id_fn == NULL || \
|
||||
(base)->th_owner_id == _evthread_id_fn())
|
||||
|
||||
/** Return true iff we need to notify the base's main thread about changes to
|
||||
* its state, because it's currently running the main loop in another
|
||||
* thread. Requires lock. */
|
||||
#define EVBASE_NEED_NOTIFY(base) \
|
||||
(_evthread_id_fn != NULL && \
|
||||
(base)->running_loop && \
|
||||
(base)->th_owner_id != _evthread_id_fn())
|
||||
|
||||
/** Allocate a new lock, and store it in lockvar, a void*. Sets lockvar to
|
||||
NULL if locking is not enabled. */
|
||||
#define EVTHREAD_ALLOC_LOCK(lockvar, locktype) \
|
||||
((lockvar) = _evthread_lock_fns.alloc ? \
|
||||
_evthread_lock_fns.alloc(locktype) : NULL)
|
||||
|
||||
/** Free a given lock, if it is present and locking is enabled. */
|
||||
#define EVTHREAD_FREE_LOCK(lockvar, locktype) \
|
||||
do { \
|
||||
void *_lock_tmp_ = (lockvar); \
|
||||
if (_lock_tmp_ && _evthread_lock_fns.free) \
|
||||
_evthread_lock_fns.free(_lock_tmp_, (locktype)); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/** Acquire a lock. */
|
||||
#define EVLOCK_LOCK(lockvar,mode) \
|
||||
do { \
|
||||
if (lockvar) \
|
||||
_evthread_lock_fns.lock(mode, lockvar); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/** Release a lock */
|
||||
#define EVLOCK_UNLOCK(lockvar,mode) \
|
||||
do { \
|
||||
if (lockvar) \
|
||||
_evthread_lock_fns.unlock(mode, lockvar); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/** Helper: put lockvar1 and lockvar2 into pointerwise ascending order. */
|
||||
#define _EVLOCK_SORTLOCKS(lockvar1, lockvar2) \
|
||||
do { \
|
||||
if (lockvar1 && lockvar2 && lockvar1 > lockvar2) { \
|
||||
void *tmp = lockvar1; \
|
||||
lockvar1 = lockvar2; \
|
||||
lockvar2 = tmp; \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/** Lock an event_base, if it is set up for locking. Acquires the lock
|
||||
in the base structure whose field is named 'lockvar'. */
|
||||
#define EVBASE_ACQUIRE_LOCK(base, lockvar) do { \
|
||||
EVLOCK_LOCK((base)->lockvar, 0); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/** Unlock an event_base, if it is set up for locking. */
|
||||
#define EVBASE_RELEASE_LOCK(base, lockvar) do { \
|
||||
EVLOCK_UNLOCK((base)->lockvar, 0); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/** If lock debugging is enabled, and lock is non-null, assert that 'lock' is
|
||||
* locked and held by us. */
|
||||
#define EVLOCK_ASSERT_LOCKED(lock) \
|
||||
do { \
|
||||
if ((lock) && _evthread_lock_debugging_enabled) { \
|
||||
EVUTIL_ASSERT(_evthread_is_debug_lock_held(lock)); \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/** Try to grab the lock for 'lockvar' without blocking, and return 1 if we
|
||||
* manage to get it. */
|
||||
static inline int EVLOCK_TRY_LOCK(void *lock);
|
||||
static inline int
|
||||
EVLOCK_TRY_LOCK(void *lock)
|
||||
{
|
||||
if (lock && _evthread_lock_fns.lock) {
|
||||
int r = _evthread_lock_fns.lock(EVTHREAD_TRY, lock);
|
||||
return !r;
|
||||
} else {
|
||||
/* Locking is disabled either globally or for this thing;
|
||||
* of course we count as having the lock. */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/** Allocate a new condition variable and store it in the void *, condvar */
|
||||
#define EVTHREAD_ALLOC_COND(condvar) \
|
||||
do { \
|
||||
(condvar) = _evthread_cond_fns.alloc_condition ? \
|
||||
_evthread_cond_fns.alloc_condition(0) : NULL; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
/** Deallocate and free a condition variable in condvar */
|
||||
#define EVTHREAD_FREE_COND(cond) \
|
||||
do { \
|
||||
if (cond) \
|
||||
_evthread_cond_fns.free_condition((cond)); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
/** Signal one thread waiting on cond */
|
||||
#define EVTHREAD_COND_SIGNAL(cond) \
|
||||
( (cond) ? _evthread_cond_fns.signal_condition((cond), 0) : 0 )
|
||||
/** Signal all threads waiting on cond */
|
||||
#define EVTHREAD_COND_BROADCAST(cond) \
|
||||
( (cond) ? _evthread_cond_fns.signal_condition((cond), 1) : 0 )
|
||||
/** Wait until the condition 'cond' is signalled. Must be called while
|
||||
* holding 'lock'. The lock will be released until the condition is
|
||||
* signalled, at which point it will be acquired again. Returns 0 for
|
||||
* success, -1 for failure. */
|
||||
#define EVTHREAD_COND_WAIT(cond, lock) \
|
||||
( (cond) ? _evthread_cond_fns.wait_condition((cond), (lock), NULL) : 0 )
|
||||
/** As EVTHREAD_COND_WAIT, but gives up after 'tv' has elapsed. Returns 1
|
||||
* on timeout. */
|
||||
#define EVTHREAD_COND_WAIT_TIMED(cond, lock, tv) \
|
||||
( (cond) ? _evthread_cond_fns.wait_condition((cond), (lock), (tv)) : 0 )
|
||||
|
||||
/** True iff locking functions have been configured. */
|
||||
#define EVTHREAD_LOCKING_ENABLED() \
|
||||
(_evthread_lock_fns.lock != NULL)
|
||||
|
||||
#elif ! defined(_EVENT_DISABLE_THREAD_SUPPORT)
|
||||
|
||||
unsigned long _evthreadimpl_get_id(void);
|
||||
int _evthreadimpl_is_lock_debugging_enabled(void);
|
||||
void *_evthreadimpl_lock_alloc(unsigned locktype);
|
||||
void _evthreadimpl_lock_free(void *lock, unsigned locktype);
|
||||
int _evthreadimpl_lock_lock(unsigned mode, void *lock);
|
||||
int _evthreadimpl_lock_unlock(unsigned mode, void *lock);
|
||||
void *_evthreadimpl_cond_alloc(unsigned condtype);
|
||||
void _evthreadimpl_cond_free(void *cond);
|
||||
int _evthreadimpl_cond_signal(void *cond, int broadcast);
|
||||
int _evthreadimpl_cond_wait(void *cond, void *lock, const struct timeval *tv);
|
||||
int _evthreadimpl_locking_enabled(void);
|
||||
|
||||
#define EVTHREAD_GET_ID() _evthreadimpl_get_id()
|
||||
#define EVBASE_IN_THREAD(base) \
|
||||
((base)->th_owner_id == _evthreadimpl_get_id())
|
||||
#define EVBASE_NEED_NOTIFY(base) \
|
||||
((base)->running_loop && \
|
||||
((base)->th_owner_id != _evthreadimpl_get_id()))
|
||||
|
||||
#define EVTHREAD_ALLOC_LOCK(lockvar, locktype) \
|
||||
((lockvar) = _evthreadimpl_lock_alloc(locktype))
|
||||
|
||||
#define EVTHREAD_FREE_LOCK(lockvar, locktype) \
|
||||
do { \
|
||||
void *_lock_tmp_ = (lockvar); \
|
||||
if (_lock_tmp_) \
|
||||
_evthreadimpl_lock_free(_lock_tmp_, (locktype)); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/** Acquire a lock. */
|
||||
#define EVLOCK_LOCK(lockvar,mode) \
|
||||
do { \
|
||||
if (lockvar) \
|
||||
_evthreadimpl_lock_lock(mode, lockvar); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/** Release a lock */
|
||||
#define EVLOCK_UNLOCK(lockvar,mode) \
|
||||
do { \
|
||||
if (lockvar) \
|
||||
_evthreadimpl_lock_unlock(mode, lockvar); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/** Lock an event_base, if it is set up for locking. Acquires the lock
|
||||
in the base structure whose field is named 'lockvar'. */
|
||||
#define EVBASE_ACQUIRE_LOCK(base, lockvar) do { \
|
||||
EVLOCK_LOCK((base)->lockvar, 0); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/** Unlock an event_base, if it is set up for locking. */
|
||||
#define EVBASE_RELEASE_LOCK(base, lockvar) do { \
|
||||
EVLOCK_UNLOCK((base)->lockvar, 0); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/** If lock debugging is enabled, and lock is non-null, assert that 'lock' is
|
||||
* locked and held by us. */
|
||||
#define EVLOCK_ASSERT_LOCKED(lock) \
|
||||
do { \
|
||||
if ((lock) && _evthreadimpl_is_lock_debugging_enabled()) { \
|
||||
EVUTIL_ASSERT(_evthread_is_debug_lock_held(lock)); \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/** Try to grab the lock for 'lockvar' without blocking, and return 1 if we
|
||||
* manage to get it. */
|
||||
static inline int EVLOCK_TRY_LOCK(void *lock);
|
||||
static inline int
|
||||
EVLOCK_TRY_LOCK(void *lock)
|
||||
{
|
||||
if (lock) {
|
||||
int r = _evthreadimpl_lock_lock(EVTHREAD_TRY, lock);
|
||||
return !r;
|
||||
} else {
|
||||
/* Locking is disabled either globally or for this thing;
|
||||
* of course we count as having the lock. */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/** Allocate a new condition variable and store it in the void *, condvar */
|
||||
#define EVTHREAD_ALLOC_COND(condvar) \
|
||||
do { \
|
||||
(condvar) = _evthreadimpl_cond_alloc(0); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
/** Deallocate and free a condition variable in condvar */
|
||||
#define EVTHREAD_FREE_COND(cond) \
|
||||
do { \
|
||||
if (cond) \
|
||||
_evthreadimpl_cond_free((cond)); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
/** Signal one thread waiting on cond */
|
||||
#define EVTHREAD_COND_SIGNAL(cond) \
|
||||
( (cond) ? _evthreadimpl_cond_signal((cond), 0) : 0 )
|
||||
/** Signal all threads waiting on cond */
|
||||
#define EVTHREAD_COND_BROADCAST(cond) \
|
||||
( (cond) ? _evthreadimpl_cond_signal((cond), 1) : 0 )
|
||||
/** Wait until the condition 'cond' is signalled. Must be called while
|
||||
* holding 'lock'. The lock will be released until the condition is
|
||||
* signalled, at which point it will be acquired again. Returns 0 for
|
||||
* success, -1 for failure. */
|
||||
#define EVTHREAD_COND_WAIT(cond, lock) \
|
||||
( (cond) ? _evthreadimpl_cond_wait((cond), (lock), NULL) : 0 )
|
||||
/** As EVTHREAD_COND_WAIT, but gives up after 'tv' has elapsed. Returns 1
|
||||
* on timeout. */
|
||||
#define EVTHREAD_COND_WAIT_TIMED(cond, lock, tv) \
|
||||
( (cond) ? _evthreadimpl_cond_wait((cond), (lock), (tv)) : 0 )
|
||||
|
||||
#define EVTHREAD_LOCKING_ENABLED() \
|
||||
(_evthreadimpl_locking_enabled())
|
||||
|
||||
#else /* _EVENT_DISABLE_THREAD_SUPPORT */
|
||||
|
||||
#define EVTHREAD_GET_ID() 1
|
||||
#define EVTHREAD_ALLOC_LOCK(lockvar, locktype) _EVUTIL_NIL_STMT
|
||||
#define EVTHREAD_FREE_LOCK(lockvar, locktype) _EVUTIL_NIL_STMT
|
||||
|
||||
#define EVLOCK_LOCK(lockvar, mode) _EVUTIL_NIL_STMT
|
||||
#define EVLOCK_UNLOCK(lockvar, mode) _EVUTIL_NIL_STMT
|
||||
#define EVLOCK_LOCK2(lock1,lock2,mode1,mode2) _EVUTIL_NIL_STMT
|
||||
#define EVLOCK_UNLOCK2(lock1,lock2,mode1,mode2) _EVUTIL_NIL_STMT
|
||||
|
||||
#define EVBASE_IN_THREAD(base) 1
|
||||
#define EVBASE_NEED_NOTIFY(base) 0
|
||||
#define EVBASE_ACQUIRE_LOCK(base, lock) _EVUTIL_NIL_STMT
|
||||
#define EVBASE_RELEASE_LOCK(base, lock) _EVUTIL_NIL_STMT
|
||||
#define EVLOCK_ASSERT_LOCKED(lock) _EVUTIL_NIL_STMT
|
||||
|
||||
#define EVLOCK_TRY_LOCK(lock) 1
|
||||
|
||||
#define EVTHREAD_ALLOC_COND(condvar) _EVUTIL_NIL_STMT
|
||||
#define EVTHREAD_FREE_COND(cond) _EVUTIL_NIL_STMT
|
||||
#define EVTHREAD_COND_SIGNAL(cond) _EVUTIL_NIL_STMT
|
||||
#define EVTHREAD_COND_BROADCAST(cond) _EVUTIL_NIL_STMT
|
||||
#define EVTHREAD_COND_WAIT(cond, lock) _EVUTIL_NIL_STMT
|
||||
#define EVTHREAD_COND_WAIT_TIMED(cond, lock, howlong) _EVUTIL_NIL_STMT
|
||||
|
||||
#define EVTHREAD_LOCKING_ENABLED() 0
|
||||
|
||||
#endif
|
||||
|
||||
/* This code is shared between both lock impls */
|
||||
#if ! defined(_EVENT_DISABLE_THREAD_SUPPORT)
|
||||
/** Helper: put lockvar1 and lockvar2 into pointerwise ascending order. */
|
||||
#define _EVLOCK_SORTLOCKS(lockvar1, lockvar2) \
|
||||
do { \
|
||||
if (lockvar1 && lockvar2 && lockvar1 > lockvar2) { \
|
||||
void *tmp = lockvar1; \
|
||||
lockvar1 = lockvar2; \
|
||||
lockvar2 = tmp; \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/** Acquire both lock1 and lock2. Always allocates locks in the same order,
|
||||
* so that two threads locking two locks with LOCK2 will not deadlock. */
|
||||
#define EVLOCK_LOCK2(lock1,lock2,mode1,mode2) \
|
||||
do { \
|
||||
void *_lock1_tmplock = (lock1); \
|
||||
void *_lock2_tmplock = (lock2); \
|
||||
_EVLOCK_SORTLOCKS(_lock1_tmplock,_lock2_tmplock); \
|
||||
EVLOCK_LOCK(_lock1_tmplock,mode1); \
|
||||
if (_lock2_tmplock != _lock1_tmplock) \
|
||||
EVLOCK_LOCK(_lock2_tmplock,mode2); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
/** Release both lock1 and lock2. */
|
||||
#define EVLOCK_UNLOCK2(lock1,lock2,mode1,mode2) \
|
||||
do { \
|
||||
void *_lock1_tmplock = (lock1); \
|
||||
void *_lock2_tmplock = (lock2); \
|
||||
_EVLOCK_SORTLOCKS(_lock1_tmplock,_lock2_tmplock); \
|
||||
if (_lock2_tmplock != _lock1_tmplock) \
|
||||
EVLOCK_UNLOCK(_lock2_tmplock,mode2); \
|
||||
EVLOCK_UNLOCK(_lock1_tmplock,mode1); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
int _evthread_is_debug_lock_held(void *lock);
|
||||
void *_evthread_debug_get_real_lock(void *lock);
|
||||
|
||||
void *evthread_setup_global_lock_(void *lock_, unsigned locktype,
|
||||
int enable_locks);
|
||||
|
||||
#define EVTHREAD_SETUP_GLOBAL_LOCK(lockvar, locktype) \
|
||||
do { \
|
||||
lockvar = evthread_setup_global_lock_(lockvar, \
|
||||
(locktype), enable_locks); \
|
||||
if (!lockvar) { \
|
||||
event_warn("Couldn't allocate %s", #lockvar); \
|
||||
return -1; \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0);
|
||||
|
||||
int event_global_setup_locks_(const int enable_locks);
|
||||
int evsig_global_setup_locks_(const int enable_locks);
|
||||
int evutil_secure_rng_global_setup_locks_(const int enable_locks);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _EVTHREAD_INTERNAL_H_ */
|
448
external/bsd/libevent/dist/evthread.c
vendored
Normal file
448
external/bsd/libevent/dist/evthread.c
vendored
Normal file
|
@ -0,0 +1,448 @@
|
|||
/* $NetBSD: evthread.c,v 1.1.1.1 2013/04/11 16:43:25 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008-2012 Niels Provos, 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.
|
||||
*/
|
||||
|
||||
#include "event2/event-config.h"
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: evthread.c,v 1.1.1.1 2013/04/11 16:43:25 christos Exp $");
|
||||
|
||||
#ifndef _EVENT_DISABLE_THREAD_SUPPORT
|
||||
|
||||
#include "event2/thread.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "log-internal.h"
|
||||
#include "mm-internal.h"
|
||||
#include "util-internal.h"
|
||||
#include "evthread-internal.h"
|
||||
|
||||
#ifdef EVTHREAD_EXPOSE_STRUCTS
|
||||
#define GLOBAL
|
||||
#else
|
||||
#define GLOBAL static
|
||||
#endif
|
||||
|
||||
/* globals */
|
||||
GLOBAL int _evthread_lock_debugging_enabled = 0;
|
||||
GLOBAL struct evthread_lock_callbacks _evthread_lock_fns = {
|
||||
0, 0, NULL, NULL, NULL, NULL
|
||||
};
|
||||
GLOBAL unsigned long (*_evthread_id_fn)(void) = NULL;
|
||||
GLOBAL struct evthread_condition_callbacks _evthread_cond_fns = {
|
||||
0, NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
/* Used for debugging */
|
||||
static struct evthread_lock_callbacks _original_lock_fns = {
|
||||
0, 0, NULL, NULL, NULL, NULL
|
||||
};
|
||||
static struct evthread_condition_callbacks _original_cond_fns = {
|
||||
0, NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
void
|
||||
evthread_set_id_callback(unsigned long (*id_fn)(void))
|
||||
{
|
||||
_evthread_id_fn = id_fn;
|
||||
}
|
||||
|
||||
int
|
||||
evthread_set_lock_callbacks(const struct evthread_lock_callbacks *cbs)
|
||||
{
|
||||
struct evthread_lock_callbacks *target =
|
||||
_evthread_lock_debugging_enabled
|
||||
? &_original_lock_fns : &_evthread_lock_fns;
|
||||
|
||||
if (!cbs) {
|
||||
if (target->alloc)
|
||||
event_warnx("Trying to disable lock functions after "
|
||||
"they have been set up will probaby not work.");
|
||||
memset(target, 0, sizeof(_evthread_lock_fns));
|
||||
return 0;
|
||||
}
|
||||
if (target->alloc) {
|
||||
/* Uh oh; we already had locking callbacks set up.*/
|
||||
if (target->lock_api_version == cbs->lock_api_version &&
|
||||
target->supported_locktypes == cbs->supported_locktypes &&
|
||||
target->alloc == cbs->alloc &&
|
||||
target->free == cbs->free &&
|
||||
target->lock == cbs->lock &&
|
||||
target->unlock == cbs->unlock) {
|
||||
/* no change -- allow this. */
|
||||
return 0;
|
||||
}
|
||||
event_warnx("Can't change lock callbacks once they have been "
|
||||
"initialized.");
|
||||
return -1;
|
||||
}
|
||||
if (cbs->alloc && cbs->free && cbs->lock && cbs->unlock) {
|
||||
memcpy(target, cbs, sizeof(_evthread_lock_fns));
|
||||
return event_global_setup_locks_(1);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
evthread_set_condition_callbacks(const struct evthread_condition_callbacks *cbs)
|
||||
{
|
||||
struct evthread_condition_callbacks *target =
|
||||
_evthread_lock_debugging_enabled
|
||||
? &_original_cond_fns : &_evthread_cond_fns;
|
||||
|
||||
if (!cbs) {
|
||||
if (target->alloc_condition)
|
||||
event_warnx("Trying to disable condition functions "
|
||||
"after they have been set up will probaby not "
|
||||
"work.");
|
||||
memset(target, 0, sizeof(_evthread_cond_fns));
|
||||
return 0;
|
||||
}
|
||||
if (target->alloc_condition) {
|
||||
/* Uh oh; we already had condition callbacks set up.*/
|
||||
if (target->condition_api_version == cbs->condition_api_version &&
|
||||
target->alloc_condition == cbs->alloc_condition &&
|
||||
target->free_condition == cbs->free_condition &&
|
||||
target->signal_condition == cbs->signal_condition &&
|
||||
target->wait_condition == cbs->wait_condition) {
|
||||
/* no change -- allow this. */
|
||||
return 0;
|
||||
}
|
||||
event_warnx("Can't change condition callbacks once they "
|
||||
"have been initialized.");
|
||||
return -1;
|
||||
}
|
||||
if (cbs->alloc_condition && cbs->free_condition &&
|
||||
cbs->signal_condition && cbs->wait_condition) {
|
||||
memcpy(target, cbs, sizeof(_evthread_cond_fns));
|
||||
}
|
||||
if (_evthread_lock_debugging_enabled) {
|
||||
_evthread_cond_fns.alloc_condition = cbs->alloc_condition;
|
||||
_evthread_cond_fns.free_condition = cbs->free_condition;
|
||||
_evthread_cond_fns.signal_condition = cbs->signal_condition;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct debug_lock {
|
||||
unsigned locktype;
|
||||
unsigned long held_by;
|
||||
/* XXXX if we ever use read-write locks, we will need a separate
|
||||
* lock to protect count. */
|
||||
int count;
|
||||
void *lock;
|
||||
};
|
||||
|
||||
static void *
|
||||
debug_lock_alloc(unsigned locktype)
|
||||
{
|
||||
struct debug_lock *result = mm_malloc(sizeof(struct debug_lock));
|
||||
if (!result)
|
||||
return NULL;
|
||||
if (_original_lock_fns.alloc) {
|
||||
if (!(result->lock = _original_lock_fns.alloc(
|
||||
locktype|EVTHREAD_LOCKTYPE_RECURSIVE))) {
|
||||
mm_free(result);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
result->lock = NULL;
|
||||
}
|
||||
result->locktype = locktype;
|
||||
result->count = 0;
|
||||
result->held_by = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
debug_lock_free(void *lock_, unsigned locktype)
|
||||
{
|
||||
struct debug_lock *lock = lock_;
|
||||
EVUTIL_ASSERT(lock->count == 0);
|
||||
EVUTIL_ASSERT(locktype == lock->locktype);
|
||||
if (_original_lock_fns.free) {
|
||||
_original_lock_fns.free(lock->lock,
|
||||
lock->locktype|EVTHREAD_LOCKTYPE_RECURSIVE);
|
||||
}
|
||||
lock->lock = NULL;
|
||||
lock->count = -100;
|
||||
mm_free(lock);
|
||||
}
|
||||
|
||||
static void
|
||||
evthread_debug_lock_mark_locked(unsigned mode, struct debug_lock *lock)
|
||||
{
|
||||
++lock->count;
|
||||
if (!(lock->locktype & EVTHREAD_LOCKTYPE_RECURSIVE))
|
||||
EVUTIL_ASSERT(lock->count == 1);
|
||||
if (_evthread_id_fn) {
|
||||
unsigned long me;
|
||||
me = _evthread_id_fn();
|
||||
if (lock->count > 1)
|
||||
EVUTIL_ASSERT(lock->held_by == me);
|
||||
lock->held_by = me;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
debug_lock_lock(unsigned mode, void *lock_)
|
||||
{
|
||||
struct debug_lock *lock = lock_;
|
||||
int res = 0;
|
||||
if (lock->locktype & EVTHREAD_LOCKTYPE_READWRITE)
|
||||
EVUTIL_ASSERT(mode & (EVTHREAD_READ|EVTHREAD_WRITE));
|
||||
else
|
||||
EVUTIL_ASSERT((mode & (EVTHREAD_READ|EVTHREAD_WRITE)) == 0);
|
||||
if (_original_lock_fns.lock)
|
||||
res = _original_lock_fns.lock(mode, lock->lock);
|
||||
if (!res) {
|
||||
evthread_debug_lock_mark_locked(mode, lock);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
evthread_debug_lock_mark_unlocked(unsigned mode, struct debug_lock *lock)
|
||||
{
|
||||
if (lock->locktype & EVTHREAD_LOCKTYPE_READWRITE)
|
||||
EVUTIL_ASSERT(mode & (EVTHREAD_READ|EVTHREAD_WRITE));
|
||||
else
|
||||
EVUTIL_ASSERT((mode & (EVTHREAD_READ|EVTHREAD_WRITE)) == 0);
|
||||
if (_evthread_id_fn) {
|
||||
EVUTIL_ASSERT(lock->held_by == _evthread_id_fn());
|
||||
if (lock->count == 1)
|
||||
lock->held_by = 0;
|
||||
}
|
||||
--lock->count;
|
||||
EVUTIL_ASSERT(lock->count >= 0);
|
||||
}
|
||||
|
||||
static int
|
||||
debug_lock_unlock(unsigned mode, void *lock_)
|
||||
{
|
||||
struct debug_lock *lock = lock_;
|
||||
int res = 0;
|
||||
evthread_debug_lock_mark_unlocked(mode, lock);
|
||||
if (_original_lock_fns.unlock)
|
||||
res = _original_lock_fns.unlock(mode, lock->lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
debug_cond_wait(void *_cond, void *_lock, const struct timeval *tv)
|
||||
{
|
||||
int r;
|
||||
struct debug_lock *lock = _lock;
|
||||
EVUTIL_ASSERT(lock);
|
||||
EVLOCK_ASSERT_LOCKED(_lock);
|
||||
evthread_debug_lock_mark_unlocked(0, lock);
|
||||
r = _original_cond_fns.wait_condition(_cond, lock->lock, tv);
|
||||
evthread_debug_lock_mark_locked(0, lock);
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
evthread_enable_lock_debuging(void)
|
||||
{
|
||||
struct evthread_lock_callbacks cbs = {
|
||||
EVTHREAD_LOCK_API_VERSION,
|
||||
EVTHREAD_LOCKTYPE_RECURSIVE,
|
||||
debug_lock_alloc,
|
||||
debug_lock_free,
|
||||
debug_lock_lock,
|
||||
debug_lock_unlock
|
||||
};
|
||||
if (_evthread_lock_debugging_enabled)
|
||||
return;
|
||||
memcpy(&_original_lock_fns, &_evthread_lock_fns,
|
||||
sizeof(struct evthread_lock_callbacks));
|
||||
memcpy(&_evthread_lock_fns, &cbs,
|
||||
sizeof(struct evthread_lock_callbacks));
|
||||
|
||||
memcpy(&_original_cond_fns, &_evthread_cond_fns,
|
||||
sizeof(struct evthread_condition_callbacks));
|
||||
_evthread_cond_fns.wait_condition = debug_cond_wait;
|
||||
_evthread_lock_debugging_enabled = 1;
|
||||
|
||||
/* XXX return value should get checked. */
|
||||
event_global_setup_locks_(0);
|
||||
}
|
||||
|
||||
int
|
||||
_evthread_is_debug_lock_held(void *lock_)
|
||||
{
|
||||
struct debug_lock *lock = lock_;
|
||||
if (! lock->count)
|
||||
return 0;
|
||||
if (_evthread_id_fn) {
|
||||
unsigned long me = _evthread_id_fn();
|
||||
if (lock->held_by != me)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *
|
||||
_evthread_debug_get_real_lock(void *lock_)
|
||||
{
|
||||
struct debug_lock *lock = lock_;
|
||||
return lock->lock;
|
||||
}
|
||||
|
||||
void *
|
||||
evthread_setup_global_lock_(void *lock_, unsigned locktype, int enable_locks)
|
||||
{
|
||||
/* there are four cases here:
|
||||
1) we're turning on debugging; locking is not on.
|
||||
2) we're turning on debugging; locking is on.
|
||||
3) we're turning on locking; debugging is not on.
|
||||
4) we're turning on locking; debugging is on. */
|
||||
|
||||
if (!enable_locks && _original_lock_fns.alloc == NULL) {
|
||||
/* Case 1: allocate a debug lock. */
|
||||
EVUTIL_ASSERT(lock_ == NULL);
|
||||
return debug_lock_alloc(locktype);
|
||||
} else if (!enable_locks && _original_lock_fns.alloc != NULL) {
|
||||
/* Case 2: wrap the lock in a debug lock. */
|
||||
struct debug_lock *lock;
|
||||
EVUTIL_ASSERT(lock_ != NULL);
|
||||
|
||||
if (!(locktype & EVTHREAD_LOCKTYPE_RECURSIVE)) {
|
||||
/* We can't wrap it: We need a recursive lock */
|
||||
_original_lock_fns.free(lock_, locktype);
|
||||
return debug_lock_alloc(locktype);
|
||||
}
|
||||
lock = mm_malloc(sizeof(struct debug_lock));
|
||||
if (!lock) {
|
||||
_original_lock_fns.free(lock_, locktype);
|
||||
return NULL;
|
||||
}
|
||||
lock->lock = lock_;
|
||||
lock->locktype = locktype;
|
||||
lock->count = 0;
|
||||
lock->held_by = 0;
|
||||
return lock;
|
||||
} else if (enable_locks && ! _evthread_lock_debugging_enabled) {
|
||||
/* Case 3: allocate a regular lock */
|
||||
EVUTIL_ASSERT(lock_ == NULL);
|
||||
return _evthread_lock_fns.alloc(locktype);
|
||||
} else {
|
||||
/* Case 4: Fill in a debug lock with a real lock */
|
||||
struct debug_lock *lock = lock_;
|
||||
EVUTIL_ASSERT(enable_locks &&
|
||||
_evthread_lock_debugging_enabled);
|
||||
EVUTIL_ASSERT(lock->locktype == locktype);
|
||||
EVUTIL_ASSERT(lock->lock == NULL);
|
||||
lock->lock = _original_lock_fns.alloc(
|
||||
locktype|EVTHREAD_LOCKTYPE_RECURSIVE);
|
||||
if (!lock->lock) {
|
||||
lock->count = -200;
|
||||
mm_free(lock);
|
||||
return NULL;
|
||||
}
|
||||
return lock;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef EVTHREAD_EXPOSE_STRUCTS
|
||||
unsigned long
|
||||
_evthreadimpl_get_id()
|
||||
{
|
||||
return _evthread_id_fn ? _evthread_id_fn() : 1;
|
||||
}
|
||||
void *
|
||||
_evthreadimpl_lock_alloc(unsigned locktype)
|
||||
{
|
||||
return _evthread_lock_fns.alloc ?
|
||||
_evthread_lock_fns.alloc(locktype) : NULL;
|
||||
}
|
||||
void
|
||||
_evthreadimpl_lock_free(void *lock, unsigned locktype)
|
||||
{
|
||||
if (_evthread_lock_fns.free)
|
||||
_evthread_lock_fns.free(lock, locktype);
|
||||
}
|
||||
int
|
||||
_evthreadimpl_lock_lock(unsigned mode, void *lock)
|
||||
{
|
||||
if (_evthread_lock_fns.lock)
|
||||
return _evthread_lock_fns.lock(mode, lock);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
int
|
||||
_evthreadimpl_lock_unlock(unsigned mode, void *lock)
|
||||
{
|
||||
if (_evthread_lock_fns.unlock)
|
||||
return _evthread_lock_fns.unlock(mode, lock);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
void *
|
||||
_evthreadimpl_cond_alloc(unsigned condtype)
|
||||
{
|
||||
return _evthread_cond_fns.alloc_condition ?
|
||||
_evthread_cond_fns.alloc_condition(condtype) : NULL;
|
||||
}
|
||||
void
|
||||
_evthreadimpl_cond_free(void *cond)
|
||||
{
|
||||
if (_evthread_cond_fns.free_condition)
|
||||
_evthread_cond_fns.free_condition(cond);
|
||||
}
|
||||
int
|
||||
_evthreadimpl_cond_signal(void *cond, int broadcast)
|
||||
{
|
||||
if (_evthread_cond_fns.signal_condition)
|
||||
return _evthread_cond_fns.signal_condition(cond, broadcast);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
int
|
||||
_evthreadimpl_cond_wait(void *cond, void *lock, const struct timeval *tv)
|
||||
{
|
||||
if (_evthread_cond_fns.wait_condition)
|
||||
return _evthread_cond_fns.wait_condition(cond, lock, tv);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
int
|
||||
_evthreadimpl_is_lock_debugging_enabled(void)
|
||||
{
|
||||
return _evthread_lock_debugging_enabled;
|
||||
}
|
||||
|
||||
int
|
||||
_evthreadimpl_locking_enabled(void)
|
||||
{
|
||||
return _evthread_lock_fns.lock != NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
192
external/bsd/libevent/dist/evthread_pthread.c
vendored
Normal file
192
external/bsd/libevent/dist/evthread_pthread.c
vendored
Normal file
|
@ -0,0 +1,192 @@
|
|||
/* $NetBSD: evthread_pthread.c,v 1.1.1.1 2013/04/11 16:43:25 christos Exp $ */
|
||||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#include "event2/event-config.h"
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: evthread_pthread.c,v 1.1.1.1 2013/04/11 16:43:25 christos Exp $");
|
||||
|
||||
/* With glibc we need to define this to get PTHREAD_MUTEX_RECURSIVE. */
|
||||
#define _GNU_SOURCE
|
||||
#include <pthread.h>
|
||||
|
||||
struct event_base;
|
||||
#include "event2/thread.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "mm-internal.h"
|
||||
#include "evthread-internal.h"
|
||||
|
||||
static pthread_mutexattr_t attr_recursive;
|
||||
|
||||
static void *
|
||||
evthread_posix_lock_alloc(unsigned locktype)
|
||||
{
|
||||
pthread_mutexattr_t *attr = NULL;
|
||||
pthread_mutex_t *lock = mm_malloc(sizeof(pthread_mutex_t));
|
||||
if (!lock)
|
||||
return NULL;
|
||||
if (locktype & EVTHREAD_LOCKTYPE_RECURSIVE)
|
||||
attr = &attr_recursive;
|
||||
if (pthread_mutex_init(lock, attr)) {
|
||||
mm_free(lock);
|
||||
return NULL;
|
||||
}
|
||||
return lock;
|
||||
}
|
||||
|
||||
static void
|
||||
evthread_posix_lock_free(void *_lock, unsigned locktype)
|
||||
{
|
||||
pthread_mutex_t *lock = _lock;
|
||||
pthread_mutex_destroy(lock);
|
||||
mm_free(lock);
|
||||
}
|
||||
|
||||
static int
|
||||
evthread_posix_lock(unsigned mode, void *_lock)
|
||||
{
|
||||
pthread_mutex_t *lock = _lock;
|
||||
if (mode & EVTHREAD_TRY)
|
||||
return pthread_mutex_trylock(lock);
|
||||
else
|
||||
return pthread_mutex_lock(lock);
|
||||
}
|
||||
|
||||
static int
|
||||
evthread_posix_unlock(unsigned mode, void *_lock)
|
||||
{
|
||||
pthread_mutex_t *lock = _lock;
|
||||
return pthread_mutex_unlock(lock);
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
evthread_posix_get_id(void)
|
||||
{
|
||||
union {
|
||||
pthread_t thr;
|
||||
#if _EVENT_SIZEOF_PTHREAD_T > _EVENT_SIZEOF_LONG
|
||||
ev_uint64_t id;
|
||||
#else
|
||||
unsigned long id;
|
||||
#endif
|
||||
} r;
|
||||
#if _EVENT_SIZEOF_PTHREAD_T < _EVENT_SIZEOF_LONG
|
||||
memset(&r, 0, sizeof(r));
|
||||
#endif
|
||||
r.thr = pthread_self();
|
||||
return (unsigned long)r.id;
|
||||
}
|
||||
|
||||
static void *
|
||||
evthread_posix_cond_alloc(unsigned condflags)
|
||||
{
|
||||
pthread_cond_t *cond = mm_malloc(sizeof(pthread_cond_t));
|
||||
if (!cond)
|
||||
return NULL;
|
||||
if (pthread_cond_init(cond, NULL)) {
|
||||
mm_free(cond);
|
||||
return NULL;
|
||||
}
|
||||
return cond;
|
||||
}
|
||||
|
||||
static void
|
||||
evthread_posix_cond_free(void *_cond)
|
||||
{
|
||||
pthread_cond_t *cond = _cond;
|
||||
pthread_cond_destroy(cond);
|
||||
mm_free(cond);
|
||||
}
|
||||
|
||||
static int
|
||||
evthread_posix_cond_signal(void *_cond, int broadcast)
|
||||
{
|
||||
pthread_cond_t *cond = _cond;
|
||||
int r;
|
||||
if (broadcast)
|
||||
r = pthread_cond_broadcast(cond);
|
||||
else
|
||||
r = pthread_cond_signal(cond);
|
||||
return r ? -1 : 0;
|
||||
}
|
||||
|
||||
static int
|
||||
evthread_posix_cond_wait(void *_cond, void *_lock, const struct timeval *tv)
|
||||
{
|
||||
int r;
|
||||
pthread_cond_t *cond = _cond;
|
||||
pthread_mutex_t *lock = _lock;
|
||||
|
||||
if (tv) {
|
||||
struct timeval now, abstime;
|
||||
struct timespec ts;
|
||||
evutil_gettimeofday(&now, NULL);
|
||||
evutil_timeradd(&now, tv, &abstime);
|
||||
ts.tv_sec = abstime.tv_sec;
|
||||
ts.tv_nsec = abstime.tv_usec*1000;
|
||||
r = pthread_cond_timedwait(cond, lock, &ts);
|
||||
if (r == ETIMEDOUT)
|
||||
return 1;
|
||||
else if (r)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
} else {
|
||||
r = pthread_cond_wait(cond, lock);
|
||||
return r ? -1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
evthread_use_pthreads(void)
|
||||
{
|
||||
struct evthread_lock_callbacks cbs = {
|
||||
EVTHREAD_LOCK_API_VERSION,
|
||||
EVTHREAD_LOCKTYPE_RECURSIVE,
|
||||
evthread_posix_lock_alloc,
|
||||
evthread_posix_lock_free,
|
||||
evthread_posix_lock,
|
||||
evthread_posix_unlock
|
||||
};
|
||||
struct evthread_condition_callbacks cond_cbs = {
|
||||
EVTHREAD_CONDITION_API_VERSION,
|
||||
evthread_posix_cond_alloc,
|
||||
evthread_posix_cond_free,
|
||||
evthread_posix_cond_signal,
|
||||
evthread_posix_cond_wait
|
||||
};
|
||||
/* Set ourselves up to get recursive locks. */
|
||||
if (pthread_mutexattr_init(&attr_recursive))
|
||||
return -1;
|
||||
if (pthread_mutexattr_settype(&attr_recursive, PTHREAD_MUTEX_RECURSIVE))
|
||||
return -1;
|
||||
|
||||
evthread_set_lock_callbacks(&cbs);
|
||||
evthread_set_condition_callbacks(&cond_cbs);
|
||||
evthread_set_id_callback(evthread_posix_get_id);
|
||||
return 0;
|
||||
}
|
342
external/bsd/libevent/dist/evthread_win32.c
vendored
Normal file
342
external/bsd/libevent/dist/evthread_win32.c
vendored
Normal file
|
@ -0,0 +1,342 @@
|
|||
/* $NetBSD: evthread_win32.c,v 1.1.1.1 2013/04/11 16:43:26 christos Exp $ */
|
||||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#include "event2/event-config.h"
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: evthread_win32.c,v 1.1.1.1 2013/04/11 16:43:26 christos Exp $");
|
||||
|
||||
#ifdef WIN32
|
||||
#ifndef _WIN32_WINNT
|
||||
/* Minimum required for InitializeCriticalSectionAndSpinCount */
|
||||
#define _WIN32_WINNT 0x0403
|
||||
#endif
|
||||
#include <winsock2.h>
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#include <sys/locking.h>
|
||||
#endif
|
||||
|
||||
struct event_base;
|
||||
#include "event2/thread.h"
|
||||
|
||||
#include "mm-internal.h"
|
||||
#include "evthread-internal.h"
|
||||
|
||||
#define SPIN_COUNT 2000
|
||||
|
||||
static void *
|
||||
evthread_win32_lock_create(unsigned locktype)
|
||||
{
|
||||
CRITICAL_SECTION *lock = mm_malloc(sizeof(CRITICAL_SECTION));
|
||||
if (!lock)
|
||||
return NULL;
|
||||
if (InitializeCriticalSectionAndSpinCount(lock, SPIN_COUNT) == 0) {
|
||||
mm_free(lock);
|
||||
return NULL;
|
||||
}
|
||||
return lock;
|
||||
}
|
||||
|
||||
static void
|
||||
evthread_win32_lock_free(void *_lock, unsigned locktype)
|
||||
{
|
||||
CRITICAL_SECTION *lock = _lock;
|
||||
DeleteCriticalSection(lock);
|
||||
mm_free(lock);
|
||||
}
|
||||
|
||||
static int
|
||||
evthread_win32_lock(unsigned mode, void *_lock)
|
||||
{
|
||||
CRITICAL_SECTION *lock = _lock;
|
||||
if ((mode & EVTHREAD_TRY)) {
|
||||
return ! TryEnterCriticalSection(lock);
|
||||
} else {
|
||||
EnterCriticalSection(lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
evthread_win32_unlock(unsigned mode, void *_lock)
|
||||
{
|
||||
CRITICAL_SECTION *lock = _lock;
|
||||
LeaveCriticalSection(lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
evthread_win32_get_id(void)
|
||||
{
|
||||
return (unsigned long) GetCurrentThreadId();
|
||||
}
|
||||
|
||||
#ifdef WIN32_HAVE_CONDITION_VARIABLES
|
||||
static void WINAPI (*InitializeConditionVariable_fn)(PCONDITION_VARIABLE)
|
||||
= NULL;
|
||||
static BOOL WINAPI (*SleepConditionVariableCS_fn)(
|
||||
PCONDITION_VARIABLE, PCRITICAL_SECTION, DWORD) = NULL;
|
||||
static void WINAPI (*WakeAllConditionVariable_fn)(PCONDITION_VARIABLE) = NULL;
|
||||
static void WINAPI (*WakeConditionVariable_fn)(PCONDITION_VARIABLE) = NULL;
|
||||
|
||||
static int
|
||||
evthread_win32_condvar_init(void)
|
||||
{
|
||||
HANDLE lib;
|
||||
|
||||
lib = GetModuleHandle(TEXT("kernel32.dll"));
|
||||
if (lib == NULL)
|
||||
return 0;
|
||||
|
||||
#define LOAD(name) \
|
||||
name##_fn = GetProcAddress(lib, #name)
|
||||
LOAD(InitializeConditionVariable);
|
||||
LOAD(SleepConditionVariable);
|
||||
LOAD(WakeAllConditionVariable);
|
||||
LOAD(WakeConditionVariable);
|
||||
|
||||
return InitializeConditionVariable_fn && SleepConditionVariableCS_fn &&
|
||||
WakeAllConditionVariable_fn && WakeConditionVariable_fn;
|
||||
}
|
||||
|
||||
/* XXXX Even if we can build this, we don't necessarily want to: the functions
|
||||
* in question didn't exist before Vista, so we'd better LoadProc them. */
|
||||
static void *
|
||||
evthread_win32_condvar_alloc(unsigned condflags)
|
||||
{
|
||||
CONDITION_VARIABLE *cond = mm_malloc(sizeof(CONDITION_VARIABLE));
|
||||
if (!cond)
|
||||
return NULL;
|
||||
InitializeConditionVariable_fn(cond);
|
||||
return cond;
|
||||
}
|
||||
|
||||
static void
|
||||
evthread_win32_condvar_free(void *_cond)
|
||||
{
|
||||
CONDITION_VARIABLE *cond = _cond;
|
||||
/* There doesn't _seem_ to be a cleaup fn here... */
|
||||
mm_free(cond);
|
||||
}
|
||||
|
||||
static int
|
||||
evthread_win32_condvar_signal(void *_cond, int broadcast)
|
||||
{
|
||||
CONDITION_VARIABLE *cond = _cond;
|
||||
if (broadcast)
|
||||
WakeAllConditionVariable_fn(cond);
|
||||
else
|
||||
WakeConditionVariable_fn(cond);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
evthread_win32_condvar_wait(void *_cond, void *_lock, const struct timeval *tv)
|
||||
{
|
||||
CONDITION_VARIABLE *cond = _cond;
|
||||
CRITICAL_SECTION *lock = _lock;
|
||||
DWORD ms, err;
|
||||
BOOL result;
|
||||
|
||||
if (tv)
|
||||
ms = evutil_tv_to_msec(tv);
|
||||
else
|
||||
ms = INFINITE;
|
||||
result = SleepConditionVariableCS_fn(cond, lock, ms);
|
||||
if (result) {
|
||||
if (GetLastError() == WAIT_TIMEOUT)
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
struct evthread_win32_cond {
|
||||
HANDLE event;
|
||||
|
||||
CRITICAL_SECTION lock;
|
||||
int n_waiting;
|
||||
int n_to_wake;
|
||||
int generation;
|
||||
};
|
||||
|
||||
static void *
|
||||
evthread_win32_cond_alloc(unsigned flags)
|
||||
{
|
||||
struct evthread_win32_cond *cond;
|
||||
if (!(cond = mm_malloc(sizeof(struct evthread_win32_cond))))
|
||||
return NULL;
|
||||
if (InitializeCriticalSectionAndSpinCount(&cond->lock, SPIN_COUNT)==0) {
|
||||
mm_free(cond);
|
||||
return NULL;
|
||||
}
|
||||
if ((cond->event = CreateEvent(NULL,TRUE,FALSE,NULL)) == NULL) {
|
||||
DeleteCriticalSection(&cond->lock);
|
||||
mm_free(cond);
|
||||
return NULL;
|
||||
}
|
||||
cond->n_waiting = cond->n_to_wake = cond->generation = 0;
|
||||
return cond;
|
||||
}
|
||||
|
||||
static void
|
||||
evthread_win32_cond_free(void *_cond)
|
||||
{
|
||||
struct evthread_win32_cond *cond = _cond;
|
||||
DeleteCriticalSection(&cond->lock);
|
||||
CloseHandle(cond->event);
|
||||
mm_free(cond);
|
||||
}
|
||||
|
||||
static int
|
||||
evthread_win32_cond_signal(void *_cond, int broadcast)
|
||||
{
|
||||
struct evthread_win32_cond *cond = _cond;
|
||||
EnterCriticalSection(&cond->lock);
|
||||
if (broadcast)
|
||||
cond->n_to_wake = cond->n_waiting;
|
||||
else
|
||||
++cond->n_to_wake;
|
||||
cond->generation++;
|
||||
SetEvent(cond->event);
|
||||
LeaveCriticalSection(&cond->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
evthread_win32_cond_wait(void *_cond, void *_lock, const struct timeval *tv)
|
||||
{
|
||||
struct evthread_win32_cond *cond = _cond;
|
||||
CRITICAL_SECTION *lock = _lock;
|
||||
int generation_at_start;
|
||||
int waiting = 1;
|
||||
int result = -1;
|
||||
DWORD ms = INFINITE, ms_orig = INFINITE, startTime, endTime;
|
||||
if (tv)
|
||||
ms_orig = ms = evutil_tv_to_msec(tv);
|
||||
|
||||
EnterCriticalSection(&cond->lock);
|
||||
++cond->n_waiting;
|
||||
generation_at_start = cond->generation;
|
||||
LeaveCriticalSection(&cond->lock);
|
||||
|
||||
LeaveCriticalSection(lock);
|
||||
|
||||
startTime = GetTickCount();
|
||||
do {
|
||||
DWORD res;
|
||||
res = WaitForSingleObject(cond->event, ms);
|
||||
EnterCriticalSection(&cond->lock);
|
||||
if (cond->n_to_wake &&
|
||||
cond->generation != generation_at_start) {
|
||||
--cond->n_to_wake;
|
||||
--cond->n_waiting;
|
||||
result = 0;
|
||||
waiting = 0;
|
||||
goto out;
|
||||
} else if (res != WAIT_OBJECT_0) {
|
||||
result = (res==WAIT_TIMEOUT) ? 1 : -1;
|
||||
--cond->n_waiting;
|
||||
waiting = 0;
|
||||
goto out;
|
||||
} else if (ms != INFINITE) {
|
||||
endTime = GetTickCount();
|
||||
if (startTime + ms_orig <= endTime) {
|
||||
result = 1; /* Timeout */
|
||||
--cond->n_waiting;
|
||||
waiting = 0;
|
||||
goto out;
|
||||
} else {
|
||||
ms = startTime + ms_orig - endTime;
|
||||
}
|
||||
}
|
||||
/* If we make it here, we are still waiting. */
|
||||
if (cond->n_to_wake == 0) {
|
||||
/* There is nobody else who should wake up; reset
|
||||
* the event. */
|
||||
ResetEvent(cond->event);
|
||||
}
|
||||
out:
|
||||
LeaveCriticalSection(&cond->lock);
|
||||
} while (waiting);
|
||||
|
||||
EnterCriticalSection(lock);
|
||||
|
||||
EnterCriticalSection(&cond->lock);
|
||||
if (!cond->n_waiting)
|
||||
ResetEvent(cond->event);
|
||||
LeaveCriticalSection(&cond->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
evthread_use_windows_threads(void)
|
||||
{
|
||||
struct evthread_lock_callbacks cbs = {
|
||||
EVTHREAD_LOCK_API_VERSION,
|
||||
EVTHREAD_LOCKTYPE_RECURSIVE,
|
||||
evthread_win32_lock_create,
|
||||
evthread_win32_lock_free,
|
||||
evthread_win32_lock,
|
||||
evthread_win32_unlock
|
||||
};
|
||||
|
||||
|
||||
struct evthread_condition_callbacks cond_cbs = {
|
||||
EVTHREAD_CONDITION_API_VERSION,
|
||||
evthread_win32_cond_alloc,
|
||||
evthread_win32_cond_free,
|
||||
evthread_win32_cond_signal,
|
||||
evthread_win32_cond_wait
|
||||
};
|
||||
#ifdef WIN32_HAVE_CONDITION_VARIABLES
|
||||
struct evthread_condition_callbacks condvar_cbs = {
|
||||
EVTHREAD_CONDITION_API_VERSION,
|
||||
evthread_win32_condvar_alloc,
|
||||
evthread_win32_condvar_free,
|
||||
evthread_win32_condvar_signal,
|
||||
evthread_win32_condvar_wait
|
||||
};
|
||||
#endif
|
||||
|
||||
evthread_set_lock_callbacks(&cbs);
|
||||
evthread_set_id_callback(evthread_win32_get_id);
|
||||
#ifdef WIN32_HAVE_CONDITION_VARIABLES
|
||||
if (evthread_win32_condvar_init()) {
|
||||
evthread_set_condition_callbacks(&condvar_cbs);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
evthread_set_condition_callbacks(&cond_cbs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
2181
external/bsd/libevent/dist/evutil.c
vendored
Normal file
2181
external/bsd/libevent/dist/evutil.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
40
external/bsd/libevent/dist/evutil.h
vendored
Normal file
40
external/bsd/libevent/dist/evutil.h
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
/* $NetBSD: evutil.h,v 1.1.1.2 2013/04/11 16:43:29 christos Exp $ */
|
||||
/*
|
||||
* 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 _EVUTIL_H_
|
||||
#define _EVUTIL_H_
|
||||
|
||||
/** @file evutil.h
|
||||
|
||||
Utility and compatibility functions for Libevent.
|
||||
|
||||
The <evutil.h> header is deprecated in Libevent 2.0 and later; please
|
||||
use <event2/util.h> instead.
|
||||
*/
|
||||
|
||||
#include <event2/util.h>
|
||||
|
||||
#endif /* _EVUTIL_H_ */
|
165
external/bsd/libevent/dist/evutil_rand.c
vendored
Normal file
165
external/bsd/libevent/dist/evutil_rand.c
vendored
Normal file
|
@ -0,0 +1,165 @@
|
|||
/* $NetBSD: evutil_rand.c,v 1.2 2013/04/11 16:56:41 christos Exp $ */
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* This file has our secure PRNG code. On platforms that have arc4random(),
|
||||
* we just use that. Otherwise, we include arc4random.c as a bunch of static
|
||||
* functions, and wrap it lightly. We don't expose the arc4random*() APIs
|
||||
* because A) they aren't in our namespace, and B) it's not nice to name your
|
||||
* APIs after their implementations. We keep them in a separate file
|
||||
* so that other people can rip it out and use it for whatever.
|
||||
*/
|
||||
|
||||
#include "event2/event-config.h"
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: evutil_rand.c,v 1.2 2013/04/11 16:56:41 christos Exp $");
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "util-internal.h"
|
||||
#include "evthread-internal.h"
|
||||
|
||||
#ifdef _EVENT_HAVE_ARC4RANDOM
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
int
|
||||
evutil_secure_rng_init(void)
|
||||
{
|
||||
/* call arc4random() now to force it to self-initialize */
|
||||
(void) arc4random();
|
||||
return 0;
|
||||
}
|
||||
int
|
||||
/*ARGSUSED*/
|
||||
evutil_secure_rng_global_setup_locks_(const int enable_locks)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
/*ARGSUED*/
|
||||
ev_arc4random_buf(void *buf, size_t n)
|
||||
{
|
||||
#if defined(_EVENT_HAVE_ARC4RANDOM_BUF) && !defined(__APPLE__)
|
||||
arc4random_buf(buf, n);
|
||||
return;
|
||||
#else
|
||||
unsigned char *b = buf;
|
||||
|
||||
#if defined(_EVENT_HAVE_ARC4RANDOM_BUF)
|
||||
/* OSX 10.7 introducd arc4random_buf, so if you build your program
|
||||
* there, you'll get surprised when older versions of OSX fail to run.
|
||||
* To solve this, we can check whether the function pointer is set,
|
||||
* and fall back otherwise. (OSX does this using some linker
|
||||
* trickery.)
|
||||
*/
|
||||
if (arc4random_buf != NULL) {
|
||||
return arc4random_buf(buf, n);
|
||||
}
|
||||
#endif
|
||||
/* Make sure that we start out with b at a 4-byte alignment; plenty
|
||||
* of CPUs care about this for 32-bit access. */
|
||||
if (n >= 4 && ((ev_uintptr_t)b) & 3) {
|
||||
ev_uint32_t u = arc4random();
|
||||
int n_bytes = 4 - (((ev_uintptr_t)b) & 3);
|
||||
memcpy(b, &u, n_bytes);
|
||||
b += n_bytes;
|
||||
n -= n_bytes;
|
||||
}
|
||||
while (n >= 4) {
|
||||
*(ev_uint32_t*)b = arc4random();
|
||||
b += 4;
|
||||
n -= 4;
|
||||
}
|
||||
if (n) {
|
||||
ev_uint32_t u = arc4random();
|
||||
memcpy(b, &u, n);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#else /* !_EVENT_HAVE_ARC4RANDOM { */
|
||||
|
||||
#ifdef _EVENT_ssize_t
|
||||
#define ssize_t _EVENT_SSIZE_t
|
||||
#endif
|
||||
#define ARC4RANDOM_EXPORT static
|
||||
#define _ARC4_LOCK() EVLOCK_LOCK(arc4rand_lock, 0)
|
||||
#define _ARC4_UNLOCK() EVLOCK_UNLOCK(arc4rand_lock, 0)
|
||||
#ifndef _EVENT_DISABLE_THREAD_SUPPORT
|
||||
static void *arc4rand_lock;
|
||||
#endif
|
||||
|
||||
#define ARC4RANDOM_UINT32 ev_uint32_t
|
||||
#define ARC4RANDOM_NOSTIR
|
||||
#define ARC4RANDOM_NORANDOM
|
||||
#define ARC4RANDOM_NOUNIFORM
|
||||
|
||||
#include "./arc4random.c"
|
||||
|
||||
#ifndef _EVENT_DISABLE_THREAD_SUPPORT
|
||||
int
|
||||
evutil_secure_rng_global_setup_locks_(const int enable_locks)
|
||||
{
|
||||
EVTHREAD_SETUP_GLOBAL_LOCK(arc4rand_lock, 0);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
evutil_secure_rng_init(void)
|
||||
{
|
||||
int val;
|
||||
|
||||
_ARC4_LOCK();
|
||||
if (!arc4_seeded_ok)
|
||||
arc4_stir();
|
||||
val = arc4_seeded_ok ? 0 : -1;
|
||||
_ARC4_UNLOCK();
|
||||
return val;
|
||||
}
|
||||
|
||||
static void
|
||||
ev_arc4random_buf(void *buf, size_t n)
|
||||
{
|
||||
arc4random_buf(buf, n);
|
||||
}
|
||||
|
||||
#endif /* } !_EVENT_HAVE_ARC4RANDOM */
|
||||
|
||||
void
|
||||
evutil_secure_rng_get_bytes(void *buf, size_t n)
|
||||
{
|
||||
ev_arc4random_buf(buf, n);
|
||||
}
|
||||
|
||||
void
|
||||
evutil_secure_rng_add_bytes(const char *buf, size_t n)
|
||||
{
|
||||
arc4random_addrandom(__UNCONST(buf),
|
||||
n>(size_t)INT_MAX ? INT_MAX : (int)n);
|
||||
}
|
||||
|
485
external/bsd/libevent/dist/ht-internal.h
vendored
Normal file
485
external/bsd/libevent/dist/ht-internal.h
vendored
Normal file
|
@ -0,0 +1,485 @@
|
|||
/* $NetBSD: ht-internal.h,v 1.2 2013/04/11 16:56:41 christos Exp $ */
|
||||
/* Based on work Copyright 2002 Christopher Clark */
|
||||
/* Copyright 2005-2012 Nick Mathewson */
|
||||
/* Copyright 2009-2012 Niels Provos and Nick Mathewson */
|
||||
/* See license at end. */
|
||||
|
||||
/* Based on ideas by Christopher Clark and interfaces from Niels Provos. */
|
||||
|
||||
#ifndef _EVENT_HT_H
|
||||
#define _EVENT_HT_H
|
||||
|
||||
#define HT_HEAD(name, type) \
|
||||
struct name { \
|
||||
/* The hash table itself. */ \
|
||||
struct type **hth_table; \
|
||||
/* How long is the hash table? */ \
|
||||
unsigned hth_table_length; \
|
||||
/* How many elements does the table contain? */ \
|
||||
unsigned hth_n_entries; \
|
||||
/* How many elements will we allow in the table before resizing it? */ \
|
||||
unsigned hth_load_limit; \
|
||||
/* Position of hth_table_length in the primes table. */ \
|
||||
int hth_prime_idx; \
|
||||
}
|
||||
|
||||
#define HT_INITIALIZER() \
|
||||
{ NULL, 0, 0, 0, -1 }
|
||||
|
||||
#ifdef HT_CACHE_HASH_VALUES
|
||||
#define HT_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *hte_next; \
|
||||
unsigned hte_hash; \
|
||||
}
|
||||
#else
|
||||
#define HT_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *hte_next; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define HT_EMPTY(head) \
|
||||
((head)->hth_n_entries == 0)
|
||||
|
||||
/* How many elements in 'head'? */
|
||||
#define HT_SIZE(head) \
|
||||
((head)->hth_n_entries)
|
||||
|
||||
#define HT_FIND(name, head, elm) name##_HT_FIND((head), (elm))
|
||||
#define HT_INSERT(name, head, elm) name##_HT_INSERT((head), (elm))
|
||||
#define HT_REPLACE(name, head, elm) name##_HT_REPLACE((head), (elm))
|
||||
#define HT_REMOVE(name, head, elm) name##_HT_REMOVE((head), (elm))
|
||||
#define HT_START(name, head) name##_HT_START(head)
|
||||
#define HT_NEXT(name, head, elm) name##_HT_NEXT((head), (elm))
|
||||
#define HT_NEXT_RMV(name, head, elm) name##_HT_NEXT_RMV((head), (elm))
|
||||
#define HT_CLEAR(name, head) name##_HT_CLEAR(head)
|
||||
#define HT_INIT(name, head) name##_HT_INIT(head)
|
||||
/* Helper: */
|
||||
static inline unsigned
|
||||
ht_improve_hash(unsigned h)
|
||||
{
|
||||
/* Aim to protect against poor hash functions by adding logic here
|
||||
* - logic taken from java 1.4 hashtable source */
|
||||
h += ~(h << 9);
|
||||
h ^= ((h >> 14) | (h << 18)); /* >>> */
|
||||
h += (h << 4);
|
||||
h ^= ((h >> 10) | (h << 22)); /* >>> */
|
||||
return h;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/** Basic string hash function, from Java standard String.hashCode(). */
|
||||
static inline unsigned
|
||||
ht_string_hash(const char *s)
|
||||
{
|
||||
unsigned h = 0;
|
||||
int m = 1;
|
||||
while (*s) {
|
||||
h += ((signed char)*s++)*m;
|
||||
m = (m<<5)-1; /* m *= 31 */
|
||||
}
|
||||
return h;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Basic string hash function, from Python's str.__hash__() */
|
||||
static inline unsigned
|
||||
ht_string_hash(const char *s)
|
||||
{
|
||||
unsigned h;
|
||||
const unsigned char *cp = (const unsigned char *)s;
|
||||
h = *cp << 7;
|
||||
while (*cp) {
|
||||
h = (1000003*h) ^ *cp++;
|
||||
}
|
||||
/* This conversion truncates the length of the string, but that's ok. */
|
||||
h ^= (unsigned)(cp-(const unsigned char*)s);
|
||||
return h;
|
||||
}
|
||||
|
||||
#ifdef HT_CACHE_HASH_VALUES
|
||||
#define _HT_SET_HASH(elm, field, hashfn) \
|
||||
do { (elm)->field.hte_hash = hashfn(elm); } while (/*CONSTCOND*/0)
|
||||
#define _HT_SET_HASHVAL(elm, field, val) \
|
||||
do { (elm)->field.hte_hash = (val); } while (/*CONSTCOND*/0)
|
||||
#define _HT_ELT_HASH(elm, field, hashfn) \
|
||||
((elm)->field.hte_hash)
|
||||
#else
|
||||
#define _HT_SET_HASH(elm, field, hashfn) \
|
||||
((void)0)
|
||||
#define _HT_ELT_HASH(elm, field, hashfn) \
|
||||
(hashfn(elm))
|
||||
#define _HT_SET_HASHVAL(elm, field, val) \
|
||||
((void)0)
|
||||
#endif
|
||||
|
||||
/* Helper: alias for the bucket containing 'elm'. */
|
||||
#define _HT_BUCKET(head, field, elm, hashfn) \
|
||||
((head)->hth_table[_HT_ELT_HASH(elm,field,hashfn) % head->hth_table_length])
|
||||
|
||||
#define HT_FOREACH(x, name, head) \
|
||||
for ((x) = HT_START(name, head); \
|
||||
(x) != NULL; \
|
||||
(x) = HT_NEXT(name, head, x))
|
||||
|
||||
#define HT_PROTOTYPE(name, type, field, hashfn, eqfn) \
|
||||
int name##_HT_GROW(struct name *ht, unsigned min_capacity); \
|
||||
void name##_HT_CLEAR(struct name *ht); \
|
||||
int _##name##_HT_REP_IS_BAD(const struct name *ht); \
|
||||
static inline void \
|
||||
name##_HT_INIT(struct name *head) { \
|
||||
head->hth_table_length = 0; \
|
||||
head->hth_table = NULL; \
|
||||
head->hth_n_entries = 0; \
|
||||
head->hth_load_limit = 0; \
|
||||
head->hth_prime_idx = -1; \
|
||||
} \
|
||||
/* Helper: returns a pointer to the right location in the table \
|
||||
* 'head' to find or insert the element 'elm'. */ \
|
||||
static inline struct type ** \
|
||||
_##name##_HT_FIND_P(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type **p; \
|
||||
if (!head->hth_table) \
|
||||
return NULL; \
|
||||
p = &_HT_BUCKET(head, field, elm, hashfn); \
|
||||
while (*p) { \
|
||||
if (eqfn(*p, elm)) \
|
||||
return p; \
|
||||
p = &(*p)->field.hte_next; \
|
||||
} \
|
||||
return p; \
|
||||
} \
|
||||
/* Return a pointer to the element in the table 'head' matching 'elm', \
|
||||
* or NULL if no such element exists */ \
|
||||
static inline struct type * \
|
||||
name##_HT_FIND(const struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type **p; \
|
||||
struct name *h = __UNCONST(head); \
|
||||
_HT_SET_HASH(elm, field, hashfn); \
|
||||
p = _##name##_HT_FIND_P(h, elm); \
|
||||
return p ? *p : NULL; \
|
||||
} \
|
||||
/* Insert the element 'elm' into the table 'head'. Do not call this \
|
||||
* function if the table might already contain a matching element. */ \
|
||||
static inline void \
|
||||
name##_HT_INSERT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type **p; \
|
||||
if (!head->hth_table || head->hth_n_entries >= head->hth_load_limit) \
|
||||
name##_HT_GROW(head, head->hth_n_entries+1); \
|
||||
++head->hth_n_entries; \
|
||||
_HT_SET_HASH(elm, field, hashfn); \
|
||||
p = &_HT_BUCKET(head, field, elm, hashfn); \
|
||||
elm->field.hte_next = *p; \
|
||||
*p = elm; \
|
||||
} \
|
||||
/* Insert the element 'elm' into the table 'head'. If there already \
|
||||
* a matching element in the table, replace that element and return \
|
||||
* it. */ \
|
||||
static inline struct type * \
|
||||
name##_HT_REPLACE(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type **p, *r; \
|
||||
if (!head->hth_table || head->hth_n_entries >= head->hth_load_limit) \
|
||||
name##_HT_GROW(head, head->hth_n_entries+1); \
|
||||
_HT_SET_HASH(elm, field, hashfn); \
|
||||
p = _##name##_HT_FIND_P(head, elm); \
|
||||
r = *p; \
|
||||
*p = elm; \
|
||||
if (r && (r!=elm)) { \
|
||||
elm->field.hte_next = r->field.hte_next; \
|
||||
r->field.hte_next = NULL; \
|
||||
return r; \
|
||||
} else { \
|
||||
++head->hth_n_entries; \
|
||||
return NULL; \
|
||||
} \
|
||||
} \
|
||||
/* Remove any element matching 'elm' from the table 'head'. If such \
|
||||
* an element is found, return it; otherwise return NULL. */ \
|
||||
static inline struct type * \
|
||||
name##_HT_REMOVE(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type **p, *r; \
|
||||
_HT_SET_HASH(elm, field, hashfn); \
|
||||
p = _##name##_HT_FIND_P(head,elm); \
|
||||
if (!p || !*p) \
|
||||
return NULL; \
|
||||
r = *p; \
|
||||
*p = r->field.hte_next; \
|
||||
r->field.hte_next = NULL; \
|
||||
--head->hth_n_entries; \
|
||||
return r; \
|
||||
} \
|
||||
/* Invoke the function 'fn' on every element of the table 'head', \
|
||||
* using 'data' as its second argument. If the function returns \
|
||||
* nonzero, remove the most recently examined element before invoking \
|
||||
* the function again. */ \
|
||||
static inline void \
|
||||
name##_HT_FOREACH_FN(struct name *head, \
|
||||
int (*fn)(struct type *, void *), \
|
||||
void *data) \
|
||||
{ \
|
||||
unsigned idx; \
|
||||
struct type **p, **nextp, *next; \
|
||||
if (!head->hth_table) \
|
||||
return; \
|
||||
for (idx=0; idx < head->hth_table_length; ++idx) { \
|
||||
p = &head->hth_table[idx]; \
|
||||
while (*p) { \
|
||||
nextp = &(*p)->field.hte_next; \
|
||||
next = *nextp; \
|
||||
if (fn(*p, data)) { \
|
||||
--head->hth_n_entries; \
|
||||
*p = next; \
|
||||
} else { \
|
||||
p = nextp; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
/* Return a pointer to the first element in the table 'head', under \
|
||||
* an arbitrary order. This order is stable under remove operations, \
|
||||
* but not under others. If the table is empty, return NULL. */ \
|
||||
static inline struct type ** \
|
||||
name##_HT_START(struct name *head) \
|
||||
{ \
|
||||
unsigned b = 0; \
|
||||
while (b < head->hth_table_length) { \
|
||||
if (head->hth_table[b]) \
|
||||
return &head->hth_table[b]; \
|
||||
++b; \
|
||||
} \
|
||||
return NULL; \
|
||||
} \
|
||||
/* Return the next element in 'head' after 'elm', under the arbitrary \
|
||||
* order used by HT_START. If there are no more elements, return \
|
||||
* NULL. If 'elm' is to be removed from the table, you must call \
|
||||
* this function for the next value before you remove it. \
|
||||
*/ \
|
||||
static inline struct type ** \
|
||||
name##_HT_NEXT(struct name *head, struct type **elm) \
|
||||
{ \
|
||||
if ((*elm)->field.hte_next) { \
|
||||
return &(*elm)->field.hte_next; \
|
||||
} else { \
|
||||
unsigned b = (_HT_ELT_HASH(*elm, field, hashfn) % head->hth_table_length)+1; \
|
||||
while (b < head->hth_table_length) { \
|
||||
if (head->hth_table[b]) \
|
||||
return &head->hth_table[b]; \
|
||||
++b; \
|
||||
} \
|
||||
return NULL; \
|
||||
} \
|
||||
} \
|
||||
static inline struct type ** \
|
||||
name##_HT_NEXT_RMV(struct name *head, struct type **elm) \
|
||||
{ \
|
||||
unsigned h = _HT_ELT_HASH(*elm, field, hashfn); \
|
||||
*elm = (*elm)->field.hte_next; \
|
||||
--head->hth_n_entries; \
|
||||
if (*elm) { \
|
||||
return elm; \
|
||||
} else { \
|
||||
unsigned b = (h % head->hth_table_length)+1; \
|
||||
while (b < head->hth_table_length) { \
|
||||
if (head->hth_table[b]) \
|
||||
return &head->hth_table[b]; \
|
||||
++b; \
|
||||
} \
|
||||
return NULL; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define HT_GENERATE(name, type, field, hashfn, eqfn, load, mallocfn, \
|
||||
reallocfn, freefn) \
|
||||
static unsigned name##_PRIMES[] = { \
|
||||
53, 97, 193, 389, \
|
||||
769, 1543, 3079, 6151, \
|
||||
12289, 24593, 49157, 98317, \
|
||||
196613, 393241, 786433, 1572869, \
|
||||
3145739, 6291469, 12582917, 25165843, \
|
||||
50331653, 100663319, 201326611, 402653189, \
|
||||
805306457, 1610612741 \
|
||||
}; \
|
||||
static unsigned name##_N_PRIMES = \
|
||||
(unsigned)(sizeof(name##_PRIMES)/sizeof(name##_PRIMES[0])); \
|
||||
/* Expand the internal table of 'head' until it is large enough to \
|
||||
* hold 'size' elements. Return 0 on success, -1 on allocation \
|
||||
* failure. */ \
|
||||
int \
|
||||
name##_HT_GROW(struct name *head, unsigned size) \
|
||||
{ \
|
||||
unsigned new_len, new_load_limit; \
|
||||
int prime_idx; \
|
||||
struct type **new_table; \
|
||||
if (head->hth_prime_idx == (int)name##_N_PRIMES - 1) \
|
||||
return 0; \
|
||||
if (head->hth_load_limit > size) \
|
||||
return 0; \
|
||||
prime_idx = head->hth_prime_idx; \
|
||||
do { \
|
||||
new_len = name##_PRIMES[++prime_idx]; \
|
||||
new_load_limit = (unsigned)(load*new_len); \
|
||||
} while (new_load_limit <= size && \
|
||||
prime_idx < (int)name##_N_PRIMES); \
|
||||
if ((new_table = mallocfn(new_len*sizeof(struct type*)))) { \
|
||||
unsigned b; \
|
||||
memset(new_table, 0, new_len*sizeof(struct type*)); \
|
||||
for (b = 0; b < head->hth_table_length; ++b) { \
|
||||
struct type *elm, *next; \
|
||||
unsigned b2; \
|
||||
elm = head->hth_table[b]; \
|
||||
while (elm) { \
|
||||
next = elm->field.hte_next; \
|
||||
b2 = _HT_ELT_HASH(elm, field, hashfn) % new_len; \
|
||||
elm->field.hte_next = new_table[b2]; \
|
||||
new_table[b2] = elm; \
|
||||
elm = next; \
|
||||
} \
|
||||
} \
|
||||
if (head->hth_table) \
|
||||
freefn(head->hth_table); \
|
||||
head->hth_table = new_table; \
|
||||
} else { \
|
||||
unsigned b, b2; \
|
||||
new_table = reallocfn(head->hth_table, new_len*sizeof(struct type*)); \
|
||||
if (!new_table) return -1; \
|
||||
memset(new_table + head->hth_table_length, 0, \
|
||||
(new_len - head->hth_table_length)*sizeof(struct type*)); \
|
||||
for (b=0; b < head->hth_table_length; ++b) { \
|
||||
struct type *e, **pE; \
|
||||
for (pE = &new_table[b], e = *pE; e != NULL; e = *pE) { \
|
||||
b2 = _HT_ELT_HASH(e, field, hashfn) % new_len; \
|
||||
if (b2 == b) { \
|
||||
pE = &e->field.hte_next; \
|
||||
} else { \
|
||||
*pE = e->field.hte_next; \
|
||||
e->field.hte_next = new_table[b2]; \
|
||||
new_table[b2] = e; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
head->hth_table = new_table; \
|
||||
} \
|
||||
head->hth_table_length = new_len; \
|
||||
head->hth_prime_idx = prime_idx; \
|
||||
head->hth_load_limit = new_load_limit; \
|
||||
return 0; \
|
||||
} \
|
||||
/* Free all storage held by 'head'. Does not free 'head' itself, or \
|
||||
* individual elements. */ \
|
||||
void \
|
||||
name##_HT_CLEAR(struct name *head) \
|
||||
{ \
|
||||
if (head->hth_table) \
|
||||
freefn(head->hth_table); \
|
||||
head->hth_table_length = 0; \
|
||||
name##_HT_INIT(head); \
|
||||
} \
|
||||
/* Debugging helper: return false iff the representation of 'head' is \
|
||||
* internally consistent. */ \
|
||||
int \
|
||||
_##name##_HT_REP_IS_BAD(const struct name *head) \
|
||||
{ \
|
||||
unsigned n, i; \
|
||||
struct type *elm; \
|
||||
if (!head->hth_table_length) { \
|
||||
if (!head->hth_table && !head->hth_n_entries && \
|
||||
!head->hth_load_limit && head->hth_prime_idx == -1) \
|
||||
return 0; \
|
||||
else \
|
||||
return 1; \
|
||||
} \
|
||||
if (!head->hth_table || head->hth_prime_idx < 0 || \
|
||||
!head->hth_load_limit) \
|
||||
return 2; \
|
||||
if (head->hth_n_entries > head->hth_load_limit) \
|
||||
return 3; \
|
||||
if (head->hth_table_length != name##_PRIMES[head->hth_prime_idx]) \
|
||||
return 4; \
|
||||
if (head->hth_load_limit != (unsigned)(load*head->hth_table_length)) \
|
||||
return 5; \
|
||||
for (n = i = 0; i < head->hth_table_length; ++i) { \
|
||||
for (elm = head->hth_table[i]; elm; elm = elm->field.hte_next) { \
|
||||
if (_HT_ELT_HASH(elm, field, hashfn) != hashfn(elm)) \
|
||||
return 1000 + i; \
|
||||
if ((_HT_ELT_HASH(elm, field, hashfn) % head->hth_table_length) != i) \
|
||||
return 10000 + i; \
|
||||
++n; \
|
||||
} \
|
||||
} \
|
||||
if (n != head->hth_n_entries) \
|
||||
return 6; \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
/** Implements an over-optimized "find and insert if absent" block;
|
||||
* not meant for direct usage by typical code, or usage outside the critical
|
||||
* path.*/
|
||||
#define _HT_FIND_OR_INSERT(name, field, hashfn, head, eltype, elm, var, y, n) \
|
||||
{ \
|
||||
struct name *_##var##_head = head; \
|
||||
struct eltype **var; \
|
||||
if (!_##var##_head->hth_table || \
|
||||
_##var##_head->hth_n_entries >= _##var##_head->hth_load_limit) \
|
||||
name##_HT_GROW(_##var##_head, _##var##_head->hth_n_entries+1); \
|
||||
_HT_SET_HASH((elm), field, hashfn); \
|
||||
var = _##name##_HT_FIND_P(_##var##_head, (elm)); \
|
||||
if (*var) { \
|
||||
y; \
|
||||
} else { \
|
||||
n; \
|
||||
} \
|
||||
}
|
||||
#define _HT_FOI_INSERT(field, head, elm, newent, var) \
|
||||
{ \
|
||||
_HT_SET_HASHVAL(newent, field, (elm)->field.hte_hash); \
|
||||
newent->field.hte_next = NULL; \
|
||||
*var = newent; \
|
||||
++((head)->hth_n_entries); \
|
||||
}
|
||||
|
||||
/*
|
||||
* Copyright 2005, Nick Mathewson. Implementation logic is adapted from code
|
||||
* by Cristopher Clark, retrofit to allow drop-in memory management, and to
|
||||
* use the same interface as Niels Provos's tree.h. This is probably still
|
||||
* a derived work, so the original license below still applies.
|
||||
*
|
||||
* Copyright (c) 2002, Christopher Clark
|
||||
* 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 the original author; nor the names of any 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.
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
196
external/bsd/libevent/dist/http-internal.h
vendored
Normal file
196
external/bsd/libevent/dist/http-internal.h
vendored
Normal file
|
@ -0,0 +1,196 @@
|
|||
/* $NetBSD: http-internal.h,v 1.1.1.2 2013/04/11 16:43:24 christos Exp $ */
|
||||
/*
|
||||
* Copyright 2001-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright 2007-2012 Niels Provos and Nick Mathewson
|
||||
*
|
||||
* This header file contains definitions for dealing with HTTP requests
|
||||
* that are internal to libevent. As user of the library, you should not
|
||||
* need to know about these.
|
||||
*/
|
||||
|
||||
#ifndef _HTTP_INTERNAL_H_
|
||||
#define _HTTP_INTERNAL_H_
|
||||
|
||||
#include "event2/event_struct.h"
|
||||
#include "util-internal.h"
|
||||
#include "defer-internal.h"
|
||||
|
||||
#define HTTP_CONNECT_TIMEOUT 45
|
||||
#define HTTP_WRITE_TIMEOUT 50
|
||||
#define HTTP_READ_TIMEOUT 50
|
||||
|
||||
#define HTTP_PREFIX "http://"
|
||||
#define HTTP_DEFAULTPORT 80
|
||||
|
||||
enum message_read_status {
|
||||
ALL_DATA_READ = 1,
|
||||
MORE_DATA_EXPECTED = 0,
|
||||
DATA_CORRUPTED = -1,
|
||||
REQUEST_CANCELED = -2,
|
||||
DATA_TOO_LONG = -3
|
||||
};
|
||||
|
||||
enum evhttp_connection_error {
|
||||
EVCON_HTTP_TIMEOUT,
|
||||
EVCON_HTTP_EOF,
|
||||
EVCON_HTTP_INVALID_HEADER,
|
||||
EVCON_HTTP_BUFFER_ERROR,
|
||||
EVCON_HTTP_REQUEST_CANCEL
|
||||
};
|
||||
|
||||
struct evbuffer;
|
||||
struct addrinfo;
|
||||
struct evhttp_request;
|
||||
|
||||
/* Indicates an unknown request method. */
|
||||
#define _EVHTTP_REQ_UNKNOWN (1<<15)
|
||||
|
||||
enum evhttp_connection_state {
|
||||
EVCON_DISCONNECTED, /**< not currently connected not trying either*/
|
||||
EVCON_CONNECTING, /**< tries to currently connect */
|
||||
EVCON_IDLE, /**< connection is established */
|
||||
EVCON_READING_FIRSTLINE,/**< reading Request-Line (incoming conn) or
|
||||
**< Status-Line (outgoing conn) */
|
||||
EVCON_READING_HEADERS, /**< reading request/response headers */
|
||||
EVCON_READING_BODY, /**< reading request/response body */
|
||||
EVCON_READING_TRAILER, /**< reading request/response chunked trailer */
|
||||
EVCON_WRITING /**< writing request/response headers/body */
|
||||
};
|
||||
|
||||
struct event_base;
|
||||
|
||||
/* A client or server connection. */
|
||||
struct evhttp_connection {
|
||||
/* we use this tailq only if this connection was created for an http
|
||||
* server */
|
||||
TAILQ_ENTRY(evhttp_connection) next;
|
||||
|
||||
evutil_socket_t fd;
|
||||
struct bufferevent *bufev;
|
||||
|
||||
struct event retry_ev; /* for retrying connects */
|
||||
|
||||
char *bind_address; /* address to use for binding the src */
|
||||
u_short bind_port; /* local port for binding the src */
|
||||
|
||||
char *address; /* address to connect to */
|
||||
u_short port;
|
||||
|
||||
size_t max_headers_size;
|
||||
ev_uint64_t max_body_size;
|
||||
|
||||
int flags;
|
||||
#define EVHTTP_CON_INCOMING 0x0001 /* only one request on it ever */
|
||||
#define EVHTTP_CON_OUTGOING 0x0002 /* multiple requests possible */
|
||||
#define EVHTTP_CON_CLOSEDETECT 0x0004 /* detecting if persistent close */
|
||||
|
||||
int timeout; /* timeout in seconds for events */
|
||||
int retry_cnt; /* retry count */
|
||||
int retry_max; /* maximum number of retries */
|
||||
|
||||
enum evhttp_connection_state state;
|
||||
|
||||
/* for server connections, the http server they are connected with */
|
||||
struct evhttp *http_server;
|
||||
|
||||
TAILQ_HEAD(evcon_requestq, evhttp_request) requests;
|
||||
|
||||
void (*cb)(struct evhttp_connection *, void *);
|
||||
void *cb_arg;
|
||||
|
||||
void (*closecb)(struct evhttp_connection *, void *);
|
||||
void *closecb_arg;
|
||||
|
||||
struct deferred_cb read_more_deferred_cb;
|
||||
|
||||
struct event_base *base;
|
||||
struct evdns_base *dns_base;
|
||||
};
|
||||
|
||||
/* A callback for an http server */
|
||||
struct evhttp_cb {
|
||||
TAILQ_ENTRY(evhttp_cb) next;
|
||||
|
||||
char *what;
|
||||
|
||||
void (*cb)(struct evhttp_request *req, void *);
|
||||
void *cbarg;
|
||||
};
|
||||
|
||||
/* both the http server as well as the rpc system need to queue connections */
|
||||
TAILQ_HEAD(evconq, evhttp_connection);
|
||||
|
||||
/* each bound socket is stored in one of these */
|
||||
struct evhttp_bound_socket {
|
||||
TAILQ_ENTRY(evhttp_bound_socket) next;
|
||||
|
||||
struct evconnlistener *listener;
|
||||
};
|
||||
|
||||
/* server alias list item. */
|
||||
struct evhttp_server_alias {
|
||||
TAILQ_ENTRY(evhttp_server_alias) next;
|
||||
|
||||
char *alias; /* the server alias. */
|
||||
};
|
||||
|
||||
struct evhttp {
|
||||
/* Next vhost, if this is a vhost. */
|
||||
TAILQ_ENTRY(evhttp) next_vhost;
|
||||
|
||||
/* All listeners for this host */
|
||||
TAILQ_HEAD(boundq, evhttp_bound_socket) sockets;
|
||||
|
||||
TAILQ_HEAD(httpcbq, evhttp_cb) callbacks;
|
||||
|
||||
/* All live connections on this host. */
|
||||
struct evconq connections;
|
||||
|
||||
TAILQ_HEAD(vhostsq, evhttp) virtualhosts;
|
||||
|
||||
TAILQ_HEAD(aliasq, evhttp_server_alias) aliases;
|
||||
|
||||
/* NULL if this server is not a vhost */
|
||||
char *vhost_pattern;
|
||||
|
||||
int timeout;
|
||||
|
||||
size_t default_max_headers_size;
|
||||
ev_uint64_t default_max_body_size;
|
||||
|
||||
/* Bitmask of all HTTP methods that we accept and pass to user
|
||||
* callbacks. */
|
||||
ev_uint16_t allowed_methods;
|
||||
|
||||
/* Fallback callback if all the other callbacks for this connection
|
||||
don't match. */
|
||||
void (*gencb)(struct evhttp_request *req, void *);
|
||||
void *gencbarg;
|
||||
|
||||
struct event_base *base;
|
||||
};
|
||||
|
||||
/* XXX most of these functions could be static. */
|
||||
|
||||
/* resets the connection; can be reused for more requests */
|
||||
void evhttp_connection_reset(struct evhttp_connection *);
|
||||
|
||||
/* connects if necessary */
|
||||
int evhttp_connection_connect(struct evhttp_connection *);
|
||||
|
||||
/* notifies the current request that it failed; resets connection */
|
||||
void evhttp_connection_fail(struct evhttp_connection *,
|
||||
enum evhttp_connection_error error);
|
||||
|
||||
enum message_read_status;
|
||||
|
||||
enum message_read_status evhttp_parse_firstline(struct evhttp_request *, struct evbuffer*);
|
||||
enum message_read_status evhttp_parse_headers(struct evhttp_request *, struct evbuffer*);
|
||||
|
||||
void evhttp_start_read(struct evhttp_connection *);
|
||||
|
||||
/* response sending HTML the data in the buffer */
|
||||
void evhttp_response_code(struct evhttp_request *, int, const char *);
|
||||
void evhttp_send_page(struct evhttp_request *, struct evbuffer *);
|
||||
|
||||
#endif /* _HTTP_H */
|
4529
external/bsd/libevent/dist/http.c
vendored
Normal file
4529
external/bsd/libevent/dist/http.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
47
external/bsd/libevent/dist/include/Makefile.am
vendored
Normal file
47
external/bsd/libevent/dist/include/Makefile.am
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
# include/Makefile.am for libevent
|
||||
# Copyright 2000-2007 Niels Provos
|
||||
# Copyright 2007-2012 Niels Provos and Nick Mathewson
|
||||
#
|
||||
# See LICENSE for copying information.
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
|
||||
EVENT2_EXPORT = \
|
||||
event2/buffer.h \
|
||||
event2/buffer_compat.h \
|
||||
event2/bufferevent.h \
|
||||
event2/bufferevent_compat.h \
|
||||
event2/bufferevent_ssl.h \
|
||||
event2/bufferevent_struct.h \
|
||||
event2/dns.h \
|
||||
event2/dns_compat.h \
|
||||
event2/dns_struct.h \
|
||||
event2/event.h \
|
||||
event2/event_compat.h \
|
||||
event2/event_struct.h \
|
||||
event2/http.h \
|
||||
event2/http_compat.h \
|
||||
event2/http_struct.h \
|
||||
event2/keyvalq_struct.h \
|
||||
event2/listener.h \
|
||||
event2/rpc.h \
|
||||
event2/rpc_compat.h \
|
||||
event2/rpc_struct.h \
|
||||
event2/tag.h \
|
||||
event2/tag_compat.h \
|
||||
event2/thread.h \
|
||||
event2/util.h
|
||||
|
||||
EXTRA_SRC = $(EVENT2_EXPORT)
|
||||
|
||||
## Without the nobase_ prefixing, Automake would strip "event2/" from
|
||||
## the source header filename to derive the installed header filename.
|
||||
## With nobase_ the installed path is $(includedir)/event2/ev*.h.
|
||||
|
||||
if INSTALL_LIBEVENT
|
||||
nobase_include_HEADERS = $(EVENT2_EXPORT)
|
||||
nobase_nodist_include_HEADERS = ./event2/event-config.h
|
||||
else
|
||||
noinst_HEADERS = $(EVENT2_EXPORT)
|
||||
nodist_noinst_HEADERS = ./event2/event-config.h
|
||||
endif
|
584
external/bsd/libevent/dist/include/Makefile.in
vendored
Normal file
584
external/bsd/libevent/dist/include/Makefile.in
vendored
Normal file
|
@ -0,0 +1,584 @@
|
|||
# Makefile.in generated by automake 1.11.6 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
|
||||
# Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
# include/Makefile.am for libevent
|
||||
# Copyright 2000-2007 Niels Provos
|
||||
# Copyright 2007-2012 Niels Provos and Nick Mathewson
|
||||
#
|
||||
# See LICENSE for copying information.
|
||||
|
||||
VPATH = @srcdir@
|
||||
am__make_dryrun = \
|
||||
{ \
|
||||
am__dry=no; \
|
||||
case $$MAKEFLAGS in \
|
||||
*\\[\ \ ]*) \
|
||||
echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
|
||||
| grep '^AM OK$$' >/dev/null || am__dry=yes;; \
|
||||
*) \
|
||||
for am__flg in $$MAKEFLAGS; do \
|
||||
case $$am__flg in \
|
||||
*=*|--*) ;; \
|
||||
*n*) am__dry=yes; break;; \
|
||||
esac; \
|
||||
done;; \
|
||||
esac; \
|
||||
test $$am__dry = yes; \
|
||||
}
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
subdir = include
|
||||
DIST_COMMON = $(am__nobase_include_HEADERS_DIST) \
|
||||
$(am__noinst_HEADERS_DIST) $(srcdir)/Makefile.am \
|
||||
$(srcdir)/Makefile.in
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/acx_pthread.m4 \
|
||||
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
|
||||
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
|
||||
$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.in
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
SOURCES =
|
||||
DIST_SOURCES =
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
am__nobase_include_HEADERS_DIST = event2/buffer.h \
|
||||
event2/buffer_compat.h event2/bufferevent.h \
|
||||
event2/bufferevent_compat.h event2/bufferevent_ssl.h \
|
||||
event2/bufferevent_struct.h event2/dns.h event2/dns_compat.h \
|
||||
event2/dns_struct.h event2/event.h event2/event_compat.h \
|
||||
event2/event_struct.h event2/http.h event2/http_compat.h \
|
||||
event2/http_struct.h event2/keyvalq_struct.h event2/listener.h \
|
||||
event2/rpc.h event2/rpc_compat.h event2/rpc_struct.h \
|
||||
event2/tag.h event2/tag_compat.h event2/thread.h event2/util.h
|
||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||
am__vpath_adj = case $$p in \
|
||||
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
*) f=$$p;; \
|
||||
esac;
|
||||
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
|
||||
am__install_max = 40
|
||||
am__nobase_strip_setup = \
|
||||
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
|
||||
am__nobase_strip = \
|
||||
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
|
||||
am__nobase_list = $(am__nobase_strip_setup); \
|
||||
for p in $$list; do echo "$$p $$p"; done | \
|
||||
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
|
||||
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
|
||||
if (++n[$$2] == $(am__install_max)) \
|
||||
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
|
||||
END { for (dir in files) print dir, files[dir] }'
|
||||
am__base_list = \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
|
||||
am__uninstall_files_from_dir = { \
|
||||
test -z "$$files" \
|
||||
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|
||||
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
|
||||
$(am__cd) "$$dir" && rm -f $$files; }; \
|
||||
}
|
||||
am__installdirs = "$(DESTDIR)$(includedir)" "$(DESTDIR)$(includedir)"
|
||||
am__noinst_HEADERS_DIST = event2/buffer.h event2/buffer_compat.h \
|
||||
event2/bufferevent.h event2/bufferevent_compat.h \
|
||||
event2/bufferevent_ssl.h event2/bufferevent_struct.h \
|
||||
event2/dns.h event2/dns_compat.h event2/dns_struct.h \
|
||||
event2/event.h event2/event_compat.h event2/event_struct.h \
|
||||
event2/http.h event2/http_compat.h event2/http_struct.h \
|
||||
event2/keyvalq_struct.h event2/listener.h event2/rpc.h \
|
||||
event2/rpc_compat.h event2/rpc_struct.h event2/tag.h \
|
||||
event2/tag_compat.h event2/thread.h event2/util.h
|
||||
HEADERS = $(nobase_include_HEADERS) $(nobase_nodist_include_HEADERS) \
|
||||
$(nodist_noinst_HEADERS) $(noinst_HEADERS)
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
DSYMUTIL = @DSYMUTIL@
|
||||
DUMPBIN = @DUMPBIN@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EV_LIB_GDI = @EV_LIB_GDI@
|
||||
EV_LIB_WS32 = @EV_LIB_WS32@
|
||||
EXEEXT = @EXEEXT@
|
||||
FGREP = @FGREP@
|
||||
GREP = @GREP@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LD = @LD@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBEVENT_GC_SECTIONS = @LIBEVENT_GC_SECTIONS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIBTOOL_DEPS = @LIBTOOL_DEPS@
|
||||
LIPO = @LIPO@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
OBJEXT = @OBJEXT@
|
||||
OPENSSL_LIBADD = @OPENSSL_LIBADD@
|
||||
OPENSSL_LIBS = @OPENSSL_LIBS@
|
||||
OTOOL = @OTOOL@
|
||||
OTOOL64 = @OTOOL64@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
PTHREAD_CC = @PTHREAD_CC@
|
||||
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
|
||||
PTHREAD_LIBS = @PTHREAD_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
ZLIB_LIBS = @ZLIB_LIBS@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
acx_pthread_config = @acx_pthread_config@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
EVENT2_EXPORT = \
|
||||
event2/buffer.h \
|
||||
event2/buffer_compat.h \
|
||||
event2/bufferevent.h \
|
||||
event2/bufferevent_compat.h \
|
||||
event2/bufferevent_ssl.h \
|
||||
event2/bufferevent_struct.h \
|
||||
event2/dns.h \
|
||||
event2/dns_compat.h \
|
||||
event2/dns_struct.h \
|
||||
event2/event.h \
|
||||
event2/event_compat.h \
|
||||
event2/event_struct.h \
|
||||
event2/http.h \
|
||||
event2/http_compat.h \
|
||||
event2/http_struct.h \
|
||||
event2/keyvalq_struct.h \
|
||||
event2/listener.h \
|
||||
event2/rpc.h \
|
||||
event2/rpc_compat.h \
|
||||
event2/rpc_struct.h \
|
||||
event2/tag.h \
|
||||
event2/tag_compat.h \
|
||||
event2/thread.h \
|
||||
event2/util.h
|
||||
|
||||
EXTRA_SRC = $(EVENT2_EXPORT)
|
||||
@INSTALL_LIBEVENT_TRUE@nobase_include_HEADERS = $(EVENT2_EXPORT)
|
||||
@INSTALL_LIBEVENT_TRUE@nobase_nodist_include_HEADERS = ./event2/event-config.h
|
||||
@INSTALL_LIBEVENT_FALSE@noinst_HEADERS = $(EVENT2_EXPORT)
|
||||
@INSTALL_LIBEVENT_FALSE@nodist_noinst_HEADERS = ./event2/event-config.h
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --foreign include/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
install-nobase_includeHEADERS: $(nobase_include_HEADERS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(nobase_include_HEADERS)'; test -n "$(includedir)" || list=; \
|
||||
if test -n "$$list"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \
|
||||
fi; \
|
||||
$(am__nobase_list) | while read dir files; do \
|
||||
xfiles=; for file in $$files; do \
|
||||
if test -f "$$file"; then xfiles="$$xfiles $$file"; \
|
||||
else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \
|
||||
test -z "$$xfiles" || { \
|
||||
test "x$$dir" = x. || { \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(includedir)/$$dir'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(includedir)/$$dir"; }; \
|
||||
echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(includedir)/$$dir'"; \
|
||||
$(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(includedir)/$$dir" || exit $$?; }; \
|
||||
done
|
||||
|
||||
uninstall-nobase_includeHEADERS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(nobase_include_HEADERS)'; test -n "$(includedir)" || list=; \
|
||||
$(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \
|
||||
dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir)
|
||||
install-nobase_nodist_includeHEADERS: $(nobase_nodist_include_HEADERS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(nobase_nodist_include_HEADERS)'; test -n "$(includedir)" || list=; \
|
||||
if test -n "$$list"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \
|
||||
fi; \
|
||||
$(am__nobase_list) | while read dir files; do \
|
||||
xfiles=; for file in $$files; do \
|
||||
if test -f "$$file"; then xfiles="$$xfiles $$file"; \
|
||||
else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \
|
||||
test -z "$$xfiles" || { \
|
||||
test "x$$dir" = x. || { \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(includedir)/$$dir'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(includedir)/$$dir"; }; \
|
||||
echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(includedir)/$$dir'"; \
|
||||
$(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(includedir)/$$dir" || exit $$?; }; \
|
||||
done
|
||||
|
||||
uninstall-nobase_nodist_includeHEADERS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(nobase_nodist_include_HEADERS)'; test -n "$(includedir)" || list=; \
|
||||
$(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \
|
||||
dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir)
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
set x; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
shift; \
|
||||
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
if test $$# -gt 0; then \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
"$$@" $$unique; \
|
||||
else \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$unique; \
|
||||
fi; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& $(am__cd) $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(HEADERS)
|
||||
installdirs:
|
||||
for dir in "$(DESTDIR)$(includedir)" "$(DESTDIR)$(includedir)"; do \
|
||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||
done
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
if test -z '$(STRIP)'; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
install; \
|
||||
else \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||
fi
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-libtool mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-generic distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am: install-nobase_includeHEADERS \
|
||||
install-nobase_nodist_includeHEADERS
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-nobase_includeHEADERS \
|
||||
uninstall-nobase_nodist_includeHEADERS
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
|
||||
clean-libtool ctags distclean distclean-generic \
|
||||
distclean-libtool distclean-tags distdir dvi dvi-am html \
|
||||
html-am info info-am install install-am install-data \
|
||||
install-data-am install-dvi install-dvi-am install-exec \
|
||||
install-exec-am install-html install-html-am install-info \
|
||||
install-info-am install-man install-nobase_includeHEADERS \
|
||||
install-nobase_nodist_includeHEADERS install-pdf \
|
||||
install-pdf-am install-ps install-ps-am install-strip \
|
||||
installcheck installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-generic \
|
||||
mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
|
||||
uninstall-am uninstall-nobase_includeHEADERS \
|
||||
uninstall-nobase_nodist_includeHEADERS
|
||||
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
843
external/bsd/libevent/dist/include/event2/buffer.h
vendored
Normal file
843
external/bsd/libevent/dist/include/event2/buffer.h
vendored
Normal file
|
@ -0,0 +1,843 @@
|
|||
/* $NetBSD: buffer.h,v 1.1.1.1 2013/04/11 16:43:34 christos Exp $ */
|
||||
/*
|
||||
* 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_
|
||||
#define _EVENT2_BUFFER_H_
|
||||
|
||||
/** @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.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <event2/event-config.h>
|
||||
#include <stdarg.h>
|
||||
#ifdef _EVENT_HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef _EVENT_HAVE_SYS_UIO_H
|
||||
#include <sys/uio.h>
|
||||
#endif
|
||||
#include <event2/util.h>
|
||||
|
||||
/**
|
||||
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 these values except with
|
||||
evbuffer_ptr_set.
|
||||
*/
|
||||
struct evbuffer_ptr {
|
||||
ev_ssize_t pos;
|
||||
|
||||
/* Do not alter the values of fields. */
|
||||
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
|
||||
*/
|
||||
struct evbuffer *evbuffer_new(void);
|
||||
/**
|
||||
Deallocate storage for an evbuffer.
|
||||
|
||||
@param buf pointer to the evbuffer to be freed
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
void evbuffer_lock(struct evbuffer *buf);
|
||||
|
||||
/**
|
||||
Release the lock on an evbuffer. Has no effect if locking was not enabled
|
||||
with evbuffer_enable_locking.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
ev_ssize_t evbuffer_copyout(struct evbuffer *buf, 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
|
||||
*/
|
||||
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
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
int evbuffer_add_buffer(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
|
||||
*/
|
||||
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.
|
||||
|
||||
@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
|
||||
@return 0 if successful, or -1 if an error occurred
|
||||
*/
|
||||
|
||||
int evbuffer_add_file(struct evbuffer *outbuf, int fd, 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()
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
|
||||
If evbuffer_ptr is not initialized. This function can only be called
|
||||
with EVBUFFER_PTR_SET.
|
||||
|
||||
@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
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
void evbuffer_cb_unsuspend(struct evbuffer *buffer, struct evbuffer_cb_entry *cb);
|
||||
#endif
|
||||
|
||||
/**
|
||||
Makes the data at the begging 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
|
||||
*/
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
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
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
int evbuffer_defer_callbacks(struct evbuffer *buffer, struct event_base *base);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _EVENT2_BUFFER_H_ */
|
111
external/bsd/libevent/dist/include/event2/buffer_compat.h
vendored
Normal file
111
external/bsd/libevent/dist/include/event2/buffer_compat.h
vendored
Normal file
|
@ -0,0 +1,111 @@
|
|||
/* $NetBSD: buffer_compat.h,v 1.1.1.1 2013/04/11 16:43:34 christos Exp $ */
|
||||
/*
|
||||
* 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_
|
||||
#define _EVENT2_BUFFER_COMPAT_H_
|
||||
|
||||
/** @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, EOL_STYLE_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
|
||||
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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
|
||||
|
822
external/bsd/libevent/dist/include/event2/bufferevent.h
vendored
Normal file
822
external/bsd/libevent/dist/include/event2/bufferevent.h
vendored
Normal file
|
@ -0,0 +1,822 @@
|
|||
/* $NetBSD: bufferevent.h,v 1.1.1.1 2013/04/11 16:43:34 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* 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_
|
||||
#define _EVENT2_BUFFEREVENT_H_
|
||||
|
||||
/**
|
||||
@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 and call the read callback.
|
||||
When writing is enabled, the bufferevent will try to write data onto its
|
||||
file descriptor when writing is enabled, and call the write callback
|
||||
when the output buffer is sufficiently drained.
|
||||
|
||||
Bufferevents come in several flavors, including:
|
||||
|
||||
<dl>
|
||||
<dt>Socket-based bufferevents</dt>
|
||||
<dd>A bufferevent that reads and writes data onto a network
|
||||
socket. Created with bufferevent_socket_new().</dd>
|
||||
|
||||
<dt>Paired bufferevents</dt>
|
||||
<dd>A pair of bufferevents that send and receive data to one
|
||||
another without touching the network. Created with
|
||||
bufferevent_pair_new().</dd>
|
||||
|
||||
<dt>Filtering bufferevents</dt>
|
||||
<dd>A bufferevent that transforms data, and sends or receives it
|
||||
over another underlying bufferevent. Created with
|
||||
bufferevent_filter_new().</dd>
|
||||
|
||||
<dt>SSL-backed bufferevents</dt>
|
||||
<dd>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().</dd>
|
||||
</dl>
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <event2/event-config.h>
|
||||
#ifdef _EVENT_HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef _EVENT_HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
/* For int types. */
|
||||
#include <event2/util.h>
|
||||
|
||||
/** @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.
|
||||
|
||||
@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()
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
int bufferevent_socket_connect(struct bufferevent *, 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.
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
int bufferevent_base_set(struct event_base *base, struct bufferevent *bufev);
|
||||
|
||||
/**
|
||||
Return the event_base used by a bufferevent
|
||||
*/
|
||||
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
|
||||
*/
|
||||
int bufferevent_priority_set(struct bufferevent *bufev, int pri);
|
||||
|
||||
|
||||
/**
|
||||
Deallocate the storage associated with a bufferevent structure.
|
||||
|
||||
@param bufev the bufferevent structure to be freed.
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
void bufferevent_setcb(struct bufferevent *bufev,
|
||||
bufferevent_data_cb readcb, bufferevent_data_cb writecb,
|
||||
bufferevent_event_cb eventcb, void *cbarg);
|
||||
|
||||
/**
|
||||
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
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
void bufferevent_setwatermark(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.
|
||||
*/
|
||||
void bufferevent_lock(struct bufferevent *bufev);
|
||||
|
||||
/**
|
||||
Release the lock on a bufferevent. Has no effect if locking was not
|
||||
enabled with BEV_OPT_THREADSAFE.
|
||||
*/
|
||||
void bufferevent_unlock(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
|
||||
*/
|
||||
int bufferevent_flush(struct bufferevent *bufev,
|
||||
short iotype,
|
||||
enum bufferevent_flush_mode mode);
|
||||
|
||||
/**
|
||||
@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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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). */
|
||||
int bufferevent_remove_from_rate_limit_group(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.
|
||||
|
||||
@{
|
||||
*/
|
||||
ev_ssize_t bufferevent_get_read_limit(struct bufferevent *bev);
|
||||
ev_ssize_t bufferevent_get_write_limit(struct bufferevent *bev);
|
||||
/*@}*/
|
||||
|
||||
ev_ssize_t bufferevent_get_max_to_read(struct bufferevent *bev);
|
||||
ev_ssize_t bufferevent_get_max_to_write(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.
|
||||
|
||||
@{
|
||||
*/
|
||||
ev_ssize_t bufferevent_rate_limit_group_get_read_limit(
|
||||
struct bufferevent_rate_limit_group *);
|
||||
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.
|
||||
|
||||
@{
|
||||
*/
|
||||
int bufferevent_decrement_read_limit(struct bufferevent *bev, ev_ssize_t decr);
|
||||
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.
|
||||
|
||||
@{
|
||||
*/
|
||||
int bufferevent_rate_limit_group_decrement_read(
|
||||
struct bufferevent_rate_limit_group *, ev_ssize_t);
|
||||
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. */
|
||||
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(). */
|
||||
void
|
||||
bufferevent_rate_limit_group_reset_totals(
|
||||
struct bufferevent_rate_limit_group *grp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _EVENT2_BUFFEREVENT_H_ */
|
101
external/bsd/libevent/dist/include/event2/bufferevent_compat.h
vendored
Normal file
101
external/bsd/libevent/dist/include/event2/bufferevent_compat.h
vendored
Normal file
|
@ -0,0 +1,101 @@
|
|||
/* $NetBSD: bufferevent_compat.h,v 1.1.1.1 2013/04/11 16:43:34 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2007-2012 Niels Provos, Nick Mathewson
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* 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_
|
||||
#define _EVENT2_BUFFEREVENT_COMPAT_H_
|
||||
|
||||
#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
|
108
external/bsd/libevent/dist/include/event2/bufferevent_ssl.h
vendored
Normal file
108
external/bsd/libevent/dist/include/event2/bufferevent_ssl.h
vendored
Normal file
|
@ -0,0 +1,108 @@
|
|||
/* $NetBSD: bufferevent_ssl.h,v 1.1.1.1 2013/04/11 16:43:34 christos Exp $ */
|
||||
/*
|
||||
* 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_
|
||||
#define _EVENT2_BUFFEREVENT_SSL_H_
|
||||
|
||||
/** @file event2/bufferevent_ssl.h
|
||||
|
||||
OpenSSL support for bufferevents.
|
||||
*/
|
||||
|
||||
#include <event2/event-config.h>
|
||||
#include <event2/bufferevent.h>
|
||||
#include <event2/util.h>
|
||||
|
||||
#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
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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);
|
||||
|
||||
/** Return the underlying openssl SSL * object for an SSL bufferevent. */
|
||||
struct ssl_st *
|
||||
bufferevent_openssl_get_ssl(struct bufferevent *bufev);
|
||||
|
||||
/** Tells a bufferevent to begin SSL renegotiation. */
|
||||
int bufferevent_ssl_renegotiate(struct bufferevent *bev);
|
||||
|
||||
/** Return the most recent OpenSSL error reported on an SSL bufferevent. */
|
||||
unsigned long bufferevent_get_openssl_error(struct bufferevent *bev);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _EVENT2_BUFFEREVENT_SSL_H_ */
|
117
external/bsd/libevent/dist/include/event2/bufferevent_struct.h
vendored
Normal file
117
external/bsd/libevent/dist/include/event2/bufferevent_struct.h
vendored
Normal file
|
@ -0,0 +1,117 @@
|
|||
/* $NetBSD: bufferevent_struct.h,v 1.1.1.1 2013/04/11 16:43:34 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* 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_
|
||||
#define _EVENT2_BUFFEREVENT_STRUCT_H_
|
||||
|
||||
/** @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 <event2/event-config.h>
|
||||
#ifdef _EVENT_HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef _EVENT_HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
/* For int types. */
|
||||
#include <event2/util.h>
|
||||
/* For struct event */
|
||||
#include <event2/event_struct.h>
|
||||
|
||||
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_ */
|
644
external/bsd/libevent/dist/include/event2/dns.h
vendored
Normal file
644
external/bsd/libevent/dist/include/event2/dns.h
vendored
Normal file
|
@ -0,0 +1,644 @@
|
|||
/* $NetBSD: dns.h,v 1.1.1.1 2013/04/11 16:43:35 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* 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 <agl@imperialviolet.org>
|
||||
*
|
||||
* 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_
|
||||
#define _EVENT2_DNS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* For integer types. */
|
||||
#include <event2/util.h>
|
||||
|
||||
/** 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;
|
||||
|
||||
/**
|
||||
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 initialize_nameservers 1 if resolve.conf processing should occur
|
||||
@return evdns_base object if successful, or NULL if an error occurred.
|
||||
@see evdns_base_free()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
void evdns_base_free(struct evdns_base *base, int fail_requests);
|
||||
|
||||
/**
|
||||
Convert a DNS error code to a string.
|
||||
|
||||
@param err the DNS error code
|
||||
@return a string containing an explanation of the error code
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
int evdns_base_nameserver_ip_add(struct evdns_base *base,
|
||||
const char *ip_as_string);
|
||||
|
||||
/**
|
||||
Add a nameserver by sockaddr.
|
||||
**/
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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_OPTIONS_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()
|
||||
*/
|
||||
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.
|
||||
|
||||
Return 0 on success, negative on failure.
|
||||
*/
|
||||
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
|
||||
int evdns_base_config_windows_nameservers(struct evdns_base *);
|
||||
#define EVDNS_BASE_CONFIG_WINDOWS_NAMESERVERS_IMPLEMENTED
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
Clear the list of search domains.
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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. */
|
||||
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
|
||||
*/
|
||||
void evdns_server_request_set_flags(struct evdns_server_request *req, int flags);
|
||||
|
||||
/* Functions to add an answer to an in-progress DNS reply.
|
||||
*/
|
||||
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);
|
||||
int evdns_server_request_add_a_reply(struct evdns_server_request *req, const char *name, int n, const void *addrs, int ttl);
|
||||
int evdns_server_request_add_aaaa_reply(struct evdns_server_request *req, const char *name, int n, const void *addrs, int ttl);
|
||||
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);
|
||||
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.
|
||||
*/
|
||||
int evdns_server_request_respond(struct evdns_server_request *req, int err);
|
||||
/**
|
||||
Free a DNS request without sending back a reply.
|
||||
*/
|
||||
int evdns_server_request_drop(struct evdns_server_request *req);
|
||||
struct sockaddr;
|
||||
/**
|
||||
Get the address that made a DNS request.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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. */
|
||||
void evdns_getaddrinfo_cancel(struct evdns_getaddrinfo_request *req);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !_EVENT2_DNS_H_ */
|
337
external/bsd/libevent/dist/include/event2/dns_compat.h
vendored
Normal file
337
external/bsd/libevent/dist/include/event2/dns_compat.h
vendored
Normal file
|
@ -0,0 +1,337 @@
|
|||
/* $NetBSD: dns_compat.h,v 1.1.1.1 2013/04/11 16:43:34 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* 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_
|
||||
#define _EVENT2_DNS_COMPAT_H_
|
||||
|
||||
/** @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 <event2/event-config.h>
|
||||
#ifdef _EVENT_HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef _EVENT_HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
/* For int types. */
|
||||
#include <event2/util.h>
|
||||
|
||||
/**
|
||||
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_ */
|
81
external/bsd/libevent/dist/include/event2/dns_struct.h
vendored
Normal file
81
external/bsd/libevent/dist/include/event2/dns_struct.h
vendored
Normal file
|
@ -0,0 +1,81 @@
|
|||
/* $NetBSD: dns_struct.h,v 1.1.1.1 2013/04/11 16:43:34 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* 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_
|
||||
#define _EVENT2_DNS_STRUCT_H_
|
||||
|
||||
/** @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 <event2/event-config.h>
|
||||
#ifdef _EVENT_HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef _EVENT_HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
/* For int types. */
|
||||
#include <event2/util.h>
|
||||
|
||||
/*
|
||||
* 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_ */
|
||||
|
1205
external/bsd/libevent/dist/include/event2/event.h
vendored
Normal file
1205
external/bsd/libevent/dist/include/event2/event.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
221
external/bsd/libevent/dist/include/event2/event_compat.h
vendored
Normal file
221
external/bsd/libevent/dist/include/event2/event_compat.h
vendored
Normal file
|
@ -0,0 +1,221 @@
|
|||
/* $NetBSD: event_compat.h,v 1.1.1.1 2013/04/11 16:43:34 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* 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_
|
||||
#define _EVENT2_EVENT_COMPAT_H_
|
||||
|
||||
/** @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.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <event2/event-config.h>
|
||||
#ifdef _EVENT_HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef _EVENT_HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
/* For int types. */
|
||||
#include <event2/util.h>
|
||||
|
||||
/**
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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_ */
|
142
external/bsd/libevent/dist/include/event2/event_struct.h
vendored
Normal file
142
external/bsd/libevent/dist/include/event2/event_struct.h
vendored
Normal file
|
@ -0,0 +1,142 @@
|
|||
/* $NetBSD: event_struct.h,v 1.1.1.1 2013/04/11 16:43:34 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* 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_
|
||||
#define _EVENT2_EVENT_STRUCT_H_
|
||||
|
||||
/** @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 <event2/event-config.h>
|
||||
#ifdef _EVENT_HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef _EVENT_HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
/* For int types. */
|
||||
#include <event2/util.h>
|
||||
|
||||
/* For evkeyvalq */
|
||||
#include <event2/keyvalq_struct.h>
|
||||
|
||||
#define EVLIST_TIMEOUT 0x01
|
||||
#define EVLIST_INSERTED 0x02
|
||||
#define EVLIST_SIGNAL 0x04
|
||||
#define EVLIST_ACTIVE 0x08
|
||||
#define EVLIST_INTERNAL 0x10
|
||||
#define EVLIST_INIT 0x80
|
||||
|
||||
/* EVLIST_X_ Private space: 0x1000-0xf000 */
|
||||
#define EVLIST_ALL (0xf000 | 0x9f)
|
||||
|
||||
/* Fix so that people don't have to run with <sys/queue.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
|
||||
|
||||
struct event_base;
|
||||
struct event {
|
||||
TAILQ_ENTRY(event) ev_active_next;
|
||||
TAILQ_ENTRY(event) ev_next;
|
||||
/* 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 {
|
||||
TAILQ_ENTRY(event) ev_io_next;
|
||||
struct timeval ev_timeout;
|
||||
} ev_io;
|
||||
|
||||
/* used by signal events */
|
||||
struct {
|
||||
TAILQ_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 */
|
||||
short ev_flags;
|
||||
ev_uint8_t ev_pri; /* smaller numbers are higher priority */
|
||||
ev_uint8_t ev_closure;
|
||||
struct timeval ev_timeout;
|
||||
|
||||
/* allows us to adopt for different types of events */
|
||||
void (*ev_callback)(evutil_socket_t, short, void *arg);
|
||||
void *ev_arg;
|
||||
};
|
||||
|
||||
TAILQ_HEAD (event_list, event);
|
||||
|
||||
#ifdef _EVENT_DEFINED_TQENTRY
|
||||
#undef TAILQ_ENTRY
|
||||
#endif
|
||||
|
||||
#ifdef _EVENT_DEFINED_TQHEAD
|
||||
#undef TAILQ_HEAD
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _EVENT2_EVENT_STRUCT_H_ */
|
864
external/bsd/libevent/dist/include/event2/http.h
vendored
Normal file
864
external/bsd/libevent/dist/include/event2/http.h
vendored
Normal file
|
@ -0,0 +1,864 @@
|
|||
/* $NetBSD: http.h,v 1.1.1.1 2013/04/11 16:43:35 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* 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_
|
||||
#define _EVENT2_HTTP_H_
|
||||
|
||||
/* For int types. */
|
||||
#include <event2/util.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* In case we haven't included the right headers yet. */
|
||||
struct evbuffer;
|
||||
struct event_base;
|
||||
|
||||
/** @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;
|
||||
|
||||
/**
|
||||
* 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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
struct evhttp_bound_socket *evhttp_bind_listener(struct evhttp *http, struct evconnlistener *listener);
|
||||
|
||||
/**
|
||||
* Return the listener used to implement a bound socket.
|
||||
*/
|
||||
struct evconnlistener *evhttp_bound_socket_get_listener(struct evhttp_bound_socket *bound);
|
||||
|
||||
/**
|
||||
* 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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
void evhttp_free(struct evhttp* http);
|
||||
|
||||
/** XXX Document. */
|
||||
void evhttp_set_max_headers_size(struct evhttp* http, ev_ssize_t max_headers_size);
|
||||
/** XXX Document. */
|
||||
void evhttp_set_max_body_size(struct evhttp* http, ev_ssize_t max_body_size);
|
||||
|
||||
/**
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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 */
|
||||
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
|
||||
*/
|
||||
void evhttp_set_gencb(struct evhttp *http,
|
||||
void (*cb)(struct evhttp_request *, 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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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
|
||||
*/
|
||||
void evhttp_set_timeout(struct evhttp *http, int timeout_in_secs);
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
void evhttp_send_reply_chunk(struct evhttp_request *req,
|
||||
struct evbuffer *databuf);
|
||||
/**
|
||||
Complete a chunked reply, freeing the request as appropriate.
|
||||
|
||||
@param req a request object
|
||||
*/
|
||||
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 };
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
void evhttp_request_set_chunked_cb(struct evhttp_request *,
|
||||
void (*cb)(struct evhttp_request *, void *));
|
||||
|
||||
/** Frees the request object and removes associated events. */
|
||||
void evhttp_request_free(struct evhttp_request *req);
|
||||
|
||||
struct evdns_base;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
struct evhttp_connection *evhttp_connection_base_new(
|
||||
struct event_base *base, struct evdns_base *dnsbase,
|
||||
const char *address, unsigned short port);
|
||||
|
||||
/**
|
||||
* Return the bufferevent that an evhttp_connection is using.
|
||||
*/
|
||||
struct bufferevent *evhttp_connection_get_bufferevent(
|
||||
struct evhttp_connection *evcon);
|
||||
|
||||
/** 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.
|
||||
*/
|
||||
void evhttp_request_own(struct evhttp_request *req);
|
||||
|
||||
/** Returns 1 if the request is owned by the user */
|
||||
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().
|
||||
*/
|
||||
struct evhttp_connection *evhttp_request_get_connection(struct evhttp_request *req);
|
||||
|
||||
/**
|
||||
* Returns the underlying event_base for this connection
|
||||
*/
|
||||
struct event_base *evhttp_connection_get_base(struct evhttp_connection *req);
|
||||
|
||||
void evhttp_connection_set_max_headers_size(struct evhttp_connection *evcon,
|
||||
ev_ssize_t new_max_headers_size);
|
||||
|
||||
void evhttp_connection_set_max_body_size(struct evhttp_connection* evcon,
|
||||
ev_ssize_t new_max_body_size);
|
||||
|
||||
/** Frees an http connection */
|
||||
void evhttp_connection_free(struct evhttp_connection *evcon);
|
||||
|
||||
/** sets the ip address from which http connections are made */
|
||||
void evhttp_connection_set_local_address(struct evhttp_connection *evcon,
|
||||
const char *address);
|
||||
|
||||
/** sets the local port from which http connections are made */
|
||||
void evhttp_connection_set_local_port(struct evhttp_connection *evcon,
|
||||
ev_uint16_t port);
|
||||
|
||||
/** Sets the timeout for events related to this connection */
|
||||
void evhttp_connection_set_timeout(struct evhttp_connection *evcon,
|
||||
int timeout_in_secs);
|
||||
|
||||
/** Sets the retry limit for this connection - -1 repeats indefinitely */
|
||||
void evhttp_connection_set_retries(struct evhttp_connection *evcon,
|
||||
int retry_max);
|
||||
|
||||
/** Set a callback for connection close. */
|
||||
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. */
|
||||
void evhttp_connection_get_peer(struct evhttp_connection *evcon,
|
||||
char **address, ev_uint16_t *port);
|
||||
|
||||
/**
|
||||
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()
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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 */
|
||||
const char *evhttp_request_get_uri(const struct evhttp_request *req);
|
||||
/** Returns the request URI (parsed) */
|
||||
const struct evhttp_uri *evhttp_request_get_evhttp_uri(const struct evhttp_request *req);
|
||||
/** Returns the request command */
|
||||
enum evhttp_cmd_type evhttp_request_get_command(const struct evhttp_request *req);
|
||||
|
||||
int evhttp_request_get_response_code(const struct evhttp_request *req);
|
||||
|
||||
/** Returns the input headers */
|
||||
struct evkeyvalq *evhttp_request_get_input_headers(struct evhttp_request *req);
|
||||
/** Returns the output headers */
|
||||
struct evkeyvalq *evhttp_request_get_output_headers(struct evhttp_request *req);
|
||||
/** Returns the input buffer */
|
||||
struct evbuffer *evhttp_request_get_input_buffer(struct evhttp_request *req);
|
||||
/** Returns the output buffer */
|
||||
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. */
|
||||
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
|
||||
count not be found.
|
||||
@see evhttp_add_header(), evhttp_remove_header()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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 sapce.
|
||||
@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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
char *evhttp_htmlescape(const char *html);
|
||||
|
||||
/**
|
||||
* Return a new empty evhttp_uri with no fields set.
|
||||
*/
|
||||
struct evhttp_uri *evhttp_uri_new(void);
|
||||
|
||||
/**
|
||||
* Changes the flags set on a given URI. See EVHTTP_URI_* for
|
||||
* a list of flags.
|
||||
**/
|
||||
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. */
|
||||
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.
|
||||
*/
|
||||
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 "".
|
||||
*/
|
||||
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. */
|
||||
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 */
|
||||
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 */
|
||||
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 */
|
||||
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. */
|
||||
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. */
|
||||
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. */
|
||||
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. */
|
||||
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. */
|
||||
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. */
|
||||
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. */
|
||||
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()
|
||||
*/
|
||||
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:
|
||||
* <ul>
|
||||
* <li> Nonconformant URIs are allowed to contain otherwise unreasonable
|
||||
* characters in their path, query, and fragment components.
|
||||
* </ul>
|
||||
*/
|
||||
#define EVHTTP_URI_NONCONFORMANT 0x01
|
||||
|
||||
/** Alias for evhttp_uri_parse_with_flags(source_uri, 0) */
|
||||
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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
char *evhttp_uri_join(struct evhttp_uri *uri, char *buf, size_t limit);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _EVENT2_HTTP_H_ */
|
91
external/bsd/libevent/dist/include/event2/http_compat.h
vendored
Normal file
91
external/bsd/libevent/dist/include/event2/http_compat.h
vendored
Normal file
|
@ -0,0 +1,91 @@
|
|||
/* $NetBSD: http_compat.h,v 1.1.1.1 2013/04/11 16:43:35 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* 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_
|
||||
#define _EVENT2_HTTP_COMPAT_H_
|
||||
|
||||
/** @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 <event2/event-config.h>
|
||||
#ifdef _EVENT_HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef _EVENT_HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
/* For int types. */
|
||||
#include <event2/util.h>
|
||||
|
||||
/**
|
||||
* 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, unsigned short 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, unsigned short 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_ */
|
131
external/bsd/libevent/dist/include/event2/http_struct.h
vendored
Normal file
131
external/bsd/libevent/dist/include/event2/http_struct.h
vendored
Normal file
|
@ -0,0 +1,131 @@
|
|||
/* $NetBSD: http_struct.h,v 1.1.1.1 2013/04/11 16:43:34 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* 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_
|
||||
#define _EVENT2_HTTP_STRUCT_H_
|
||||
|
||||
/** @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 <event2/event-config.h>
|
||||
#ifdef _EVENT_HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef _EVENT_HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
/* For int types. */
|
||||
#include <event2/util.h>
|
||||
|
||||
/**
|
||||
* 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 *);
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _EVENT2_HTTP_STRUCT_H_ */
|
||||
|
81
external/bsd/libevent/dist/include/event2/keyvalq_struct.h
vendored
Normal file
81
external/bsd/libevent/dist/include/event2/keyvalq_struct.h
vendored
Normal file
|
@ -0,0 +1,81 @@
|
|||
/* $NetBSD: keyvalq_struct.h,v 1.1.1.1 2013/04/11 16:43:34 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* 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_KEYVALQ_STRUCT_H_
|
||||
#define _EVENT2_EVENT_KEYVALQ_STRUCT_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Fix so that people don't have to run with <sys/queue.h> */
|
||||
/* 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
|
144
external/bsd/libevent/dist/include/event2/listener.h
vendored
Normal file
144
external/bsd/libevent/dist/include/event2/listener.h
vendored
Normal file
|
@ -0,0 +1,144 @@
|
|||
/* $NetBSD: listener.h,v 1.1.1.1 2013/04/11 16:43:34 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* 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_
|
||||
#define _EVENT2_LISTENER_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <event2/event.h>
|
||||
|
||||
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)
|
||||
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
void evconnlistener_free(struct evconnlistener *lev);
|
||||
/**
|
||||
Re-enable an evconnlistener that has been disabled.
|
||||
*/
|
||||
int evconnlistener_enable(struct evconnlistener *lev);
|
||||
/**
|
||||
Stop listening for connections on an evconnlistener.
|
||||
*/
|
||||
int evconnlistener_disable(struct evconnlistener *lev);
|
||||
|
||||
/** Return an evconnlistener's associated event_base. */
|
||||
struct event_base *evconnlistener_get_base(struct evconnlistener *lev);
|
||||
|
||||
/** Return the socket that an evconnlistner is listening on. */
|
||||
evutil_socket_t evconnlistener_get_fd(struct evconnlistener *lev);
|
||||
|
||||
/** Change the callback on the listener to cb and its user_data to arg.
|
||||
*/
|
||||
void evconnlistener_set_cb(struct evconnlistener *lev,
|
||||
evconnlistener_cb cb, void *arg);
|
||||
|
||||
/** Set an evconnlistener's error callback. */
|
||||
void evconnlistener_set_error_cb(struct evconnlistener *lev,
|
||||
evconnlistener_errorcb errorcb);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
597
external/bsd/libevent/dist/include/event2/rpc.h
vendored
Normal file
597
external/bsd/libevent/dist/include/event2/rpc.h
vendored
Normal file
|
@ -0,0 +1,597 @@
|
|||
/* $NetBSD: rpc.h,v 1.2 2013/04/11 16:56:42 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* 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_
|
||||
#define _EVENT2_RPC_H_
|
||||
|
||||
#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_
|
||||
|
||||
/**
|
||||
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_ */
|
||||
|
||||
/**
|
||||
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 (/*CONSTCOND*/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_ */
|
62
external/bsd/libevent/dist/include/event2/rpc_compat.h
vendored
Normal file
62
external/bsd/libevent/dist/include/event2/rpc_compat.h
vendored
Normal file
|
@ -0,0 +1,62 @@
|
|||
/* $NetBSD: rpc_compat.h,v 1.1.1.1 2013/04/11 16:43:34 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* 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_
|
||||
#define _EVENT2_RPC_COMPAT_H_
|
||||
|
||||
/** @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_ */
|
101
external/bsd/libevent/dist/include/event2/rpc_struct.h
vendored
Normal file
101
external/bsd/libevent/dist/include/event2/rpc_struct.h
vendored
Normal file
|
@ -0,0 +1,101 @@
|
|||
/* $NetBSD: rpc_struct.h,v 1.1.1.1 2013/04/11 16:43:34 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* 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_
|
||||
#define _EVENT2_RPC_STRUCT_H_
|
||||
|
||||
#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_ */
|
125
external/bsd/libevent/dist/include/event2/tag.h
vendored
Normal file
125
external/bsd/libevent/dist/include/event2/tag.h
vendored
Normal file
|
@ -0,0 +1,125 @@
|
|||
/* $NetBSD: tag.h,v 1.1.1.1 2013/04/11 16:43:34 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* 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_
|
||||
#define _EVENT2_TAG_H_
|
||||
|
||||
/** @file event2/tag.h
|
||||
|
||||
Helper functions for reading and writing tagged data onto buffers.
|
||||
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <event2/event-config.h>
|
||||
#ifdef _EVENT_HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef _EVENT_HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
/* For int types. */
|
||||
#include <event2/util.h>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
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.
|
||||
*/
|
||||
int evtag_unmarshal_header(struct evbuffer *evbuf, ev_uint32_t *ptag);
|
||||
|
||||
void evtag_marshal(struct evbuffer *evbuf, ev_uint32_t tag, const void *data,
|
||||
ev_uint32_t len);
|
||||
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
|
||||
*/
|
||||
void evtag_encode_int(struct evbuffer *evbuf, ev_uint32_t number);
|
||||
void evtag_encode_int64(struct evbuffer *evbuf, ev_uint64_t number);
|
||||
|
||||
void evtag_marshal_int(struct evbuffer *evbuf, ev_uint32_t tag,
|
||||
ev_uint32_t integer);
|
||||
void evtag_marshal_int64(struct evbuffer *evbuf, ev_uint32_t tag,
|
||||
ev_uint64_t integer);
|
||||
|
||||
void evtag_marshal_string(struct evbuffer *buf, ev_uint32_t tag,
|
||||
const char *string);
|
||||
|
||||
void evtag_marshal_timeval(struct evbuffer *evbuf, ev_uint32_t tag,
|
||||
struct timeval *tv);
|
||||
|
||||
int evtag_unmarshal(struct evbuffer *src, ev_uint32_t *ptag,
|
||||
struct evbuffer *dst);
|
||||
int evtag_peek(struct evbuffer *evbuf, ev_uint32_t *ptag);
|
||||
int evtag_peek_length(struct evbuffer *evbuf, ev_uint32_t *plength);
|
||||
int evtag_payload_length(struct evbuffer *evbuf, ev_uint32_t *plength);
|
||||
int evtag_consume(struct evbuffer *evbuf);
|
||||
|
||||
int evtag_unmarshal_int(struct evbuffer *evbuf, ev_uint32_t need_tag,
|
||||
ev_uint32_t *pinteger);
|
||||
int evtag_unmarshal_int64(struct evbuffer *evbuf, ev_uint32_t need_tag,
|
||||
ev_uint64_t *pinteger);
|
||||
|
||||
int evtag_unmarshal_fixed(struct evbuffer *src, ev_uint32_t need_tag,
|
||||
void *data, size_t len);
|
||||
|
||||
int evtag_unmarshal_string(struct evbuffer *evbuf, ev_uint32_t need_tag,
|
||||
char **pstring);
|
||||
|
||||
int evtag_unmarshal_timeval(struct evbuffer *evbuf, ev_uint32_t need_tag,
|
||||
struct timeval *ptv);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _EVENT2_TAG_H_ */
|
50
external/bsd/libevent/dist/include/event2/tag_compat.h
vendored
Normal file
50
external/bsd/libevent/dist/include/event2/tag_compat.h
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
/* $NetBSD: tag_compat.h,v 1.1.1.1 2013/04/11 16:43:35 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* 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_
|
||||
#define _EVENT2_TAG_COMPAT_H_
|
||||
|
||||
/** @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_ */
|
237
external/bsd/libevent/dist/include/event2/thread.h
vendored
Normal file
237
external/bsd/libevent/dist/include/event2/thread.h
vendored
Normal file
|
@ -0,0 +1,237 @@
|
|||
/* $NetBSD: thread.h,v 1.1.1.1 2013/04/11 16:43:34 christos Exp $ */
|
||||
/*
|
||||
* 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_
|
||||
#define _EVENT2_THREAD_H_
|
||||
|
||||
/** @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().
|
||||
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <event2/event-config.h>
|
||||
|
||||
/**
|
||||
@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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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. */
|
||||
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. */
|
||||
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.
|
||||
**/
|
||||
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.
|
||||
|
||||
@return 0 on success, -1 on failure.
|
||||
*/
|
||||
int evthread_make_base_notifiable(struct event_base *base);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _EVENT2_THREAD_H_ */
|
685
external/bsd/libevent/dist/include/event2/util.h
vendored
Normal file
685
external/bsd/libevent/dist/include/event2/util.h
vendored
Normal file
|
@ -0,0 +1,685 @@
|
|||
/* $NetBSD: util.h,v 1.2 2013/04/11 16:56:42 christos Exp $ */
|
||||
/*
|
||||
* 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_
|
||||
#define _EVENT2_UTIL_H_
|
||||
|
||||
/** @file event2/util.h
|
||||
|
||||
Common convenience functions for cross-platform portability and
|
||||
related socket manipulations.
|
||||
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <event2/event-config.h>
|
||||
#ifdef _EVENT_HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#ifdef _EVENT_HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#elif defined(_EVENT_HAVE_INTTYPES_H)
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
#ifdef _EVENT_HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef _EVENT_HAVE_STDDEF_H
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
#include <BaseTsd.h>
|
||||
#endif
|
||||
#include <stdarg.h>
|
||||
#ifdef _EVENT_HAVE_NETDB_H
|
||||
#if !defined(_GNU_SOURCE)
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
/* 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:
|
||||
*
|
||||
* <dl>
|
||||
* <dt>ev_uint64_t, ev_uint32_t, ev_uint16_t, ev_uint8_t</dt>
|
||||
* <dd>unsigned integer types of exactly 64, 32, 16, and 8 bits
|
||||
* respectively.</dd>
|
||||
* <dt>ev_int64_t, ev_int32_t, ev_int16_t, ev_int8_t</dt>
|
||||
* <dd>signed integer types of exactly 64, 32, 16, and 8 bits
|
||||
* respectively.</dd>
|
||||
* <dt>ev_uintptr_t, ev_intptr_t</dt>
|
||||
* <dd>unsigned/signed integers large enough
|
||||
* to hold a pointer without loss of bits.</dd>
|
||||
* <dt>ev_ssize_t</dt>
|
||||
* <dd>A signed type of the same size as size_t</dd>
|
||||
* <dt>ev_off_t</dt>
|
||||
* <dd>A signed type typically used to represent offsets within a
|
||||
* (potentially large) file</dd>
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
#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
|
||||
|
||||
#ifdef WIN32
|
||||
#define ev_off_t ev_int64_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.
|
||||
|
||||
@{
|
||||
*/
|
||||
#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_INT16_MIN INT16_MIN
|
||||
#define EV_UINT8_MAX UINT8_MAX
|
||||
#define EV_INT8_MAX INT8_MAX
|
||||
#define EV_INT8_MIN INT8_MIN
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
@name Limits for SIZE_T and SSIZE_T
|
||||
|
||||
@{
|
||||
*/
|
||||
#define EV_SIZE_MAX SIZE_MAX
|
||||
#define EV_SSIZE_MAX SSIZE_MAX
|
||||
#define EV_SSIZE_MIN SSIZE_MIN
|
||||
/**@}*/
|
||||
|
||||
#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
|
||||
|
||||
/** 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()
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
int evutil_make_listen_socket_reuseable(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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
int evutil_closesocket(evutil_socket_t sock);
|
||||
#define EVUTIL_CLOSESOCKET(s) evutil_closesocket(s)
|
||||
|
||||
|
||||
#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 (/*CONSTCOND*/0)
|
||||
/** Return the most recent socket error to occur on sock. */
|
||||
int evutil_socket_geterror(evutil_socket_t sock);
|
||||
/** Convert a socket error to a string. */
|
||||
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 (/*CONSTCOND*/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 (/*CONSTCOND*/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 (/*CONSTCOND*/0)
|
||||
#endif /* !_EVENT_HAVE_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. */
|
||||
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;
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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. */
|
||||
const char *evutil_inet_ntop(int af, const void *src, char *dst, size_t len);
|
||||
/** Replacement for inet_pton for platforms which lack it. */
|
||||
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.
|
||||
*/
|
||||
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. */
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
|
||||
@{
|
||||
*/
|
||||
#ifdef EAI_ADDRFAMILY
|
||||
#define EVUTIL_EAI_ADDRFAMILY EAI_ADDRFAMILY
|
||||
#else
|
||||
#define EVUTIL_EAI_ADDRFAMILY -901
|
||||
#endif
|
||||
#ifdef EAI_AGAIN
|
||||
#define EVUTIL_EAI_AGAIN EAI_AGAIN
|
||||
#else
|
||||
#define EVUTIL_EAI_AGAIN -902
|
||||
#endif
|
||||
#ifdef EAI_BADFLAGS
|
||||
#define EVUTIL_EAI_BADFLAGS EAI_BADFLAGS
|
||||
#else
|
||||
#define EVUTIL_EAI_BADFLAGS -903
|
||||
#endif
|
||||
#ifdef EAI_FAIL
|
||||
#define EVUTIL_EAI_FAIL EAI_FAIL
|
||||
#else
|
||||
#define EVUTIL_EAI_FAIL -904
|
||||
#endif
|
||||
#ifdef EAI_FAMILY
|
||||
#define EVUTIL_EAI_FAMILY EAI_FAMILY
|
||||
#else
|
||||
#define EVUTIL_EAI_FAMILY -905
|
||||
#endif
|
||||
#ifdef EAI_MEMORY
|
||||
#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(EAI_NONAME) || EAI_NODATA != EAI_NONAME)
|
||||
#define EVUTIL_EAI_NODATA EAI_NODATA
|
||||
#else
|
||||
#define EVUTIL_EAI_NODATA -907
|
||||
#endif
|
||||
#ifdef EAI_NONAME
|
||||
#define EVUTIL_EAI_NONAME EAI_NONAME
|
||||
#else
|
||||
#define EVUTIL_EAI_NONAME -908
|
||||
#endif
|
||||
#ifdef EAI_SERVICE
|
||||
#define EVUTIL_EAI_SERVICE EAI_SERVICE
|
||||
#else
|
||||
#define EVUTIL_EAI_SERVICE -909
|
||||
#endif
|
||||
#ifdef EAI_SOCKTYPE
|
||||
#define EVUTIL_EAI_SOCKTYPE EAI_SOCKTYPE
|
||||
#else
|
||||
#define EVUTIL_EAI_SOCKTYPE -910
|
||||
#endif
|
||||
#ifdef EAI_SYSTEM
|
||||
#define EVUTIL_EAI_SYSTEM EAI_SYSTEM
|
||||
#else
|
||||
#define EVUTIL_EAI_SYSTEM -911
|
||||
#endif
|
||||
|
||||
#define EVUTIL_EAI_CANCEL -90001
|
||||
|
||||
#ifdef AI_PASSIVE
|
||||
#define EVUTIL_AI_PASSIVE AI_PASSIVE
|
||||
#else
|
||||
#define EVUTIL_AI_PASSIVE 0x1000
|
||||
#endif
|
||||
#ifdef AI_CANONNAME
|
||||
#define EVUTIL_AI_CANONNAME AI_CANONNAME
|
||||
#else
|
||||
#define EVUTIL_AI_CANONNAME 0x2000
|
||||
#endif
|
||||
#ifdef AI_NUMERICHOST
|
||||
#define EVUTIL_AI_NUMERICHOST AI_NUMERICHOST
|
||||
#else
|
||||
#define EVUTIL_AI_NUMERICHOST 0x4000
|
||||
#endif
|
||||
#ifdef AI_NUMERICSERV
|
||||
#define EVUTIL_AI_NUMERICSERV AI_NUMERICSERV
|
||||
#else
|
||||
#define EVUTIL_AI_NUMERICSERV 0x8000
|
||||
#endif
|
||||
#ifdef AI_V4MAPPED
|
||||
#define EVUTIL_AI_V4MAPPED AI_V4MAPPED
|
||||
#else
|
||||
#define EVUTIL_AI_V4MAPPED 0x10000
|
||||
#endif
|
||||
#ifdef AI_ALL
|
||||
#define EVUTIL_AI_ALL AI_ALL
|
||||
#else
|
||||
#define EVUTIL_AI_ALL 0x20000
|
||||
#endif
|
||||
#ifdef AI_ADDRCONFIG
|
||||
#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.
|
||||
*/
|
||||
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. */
|
||||
void evutil_freeaddrinfo(struct evutil_addrinfo *ai);
|
||||
|
||||
const char *evutil_gai_strerror(int err);
|
||||
|
||||
/** Generate n bytes of secure pseudorandom data, and store them in buf.
|
||||
*
|
||||
* By default, Libevent uses an ARC4-based random number generator, seeded
|
||||
* using the platform's entropy source (/dev/urandom on Unix-like systems;
|
||||
* CryptGenRandom on Windows).
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
int evutil_secure_rng_init(void);
|
||||
|
||||
/** 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
|
||||
*/
|
||||
void evutil_secure_rng_add_bytes(const char *dat, size_t datlen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _EVUTIL_H_ */
|
527
external/bsd/libevent/dist/install-sh
vendored
Executable file
527
external/bsd/libevent/dist/install-sh
vendored
Executable file
|
@ -0,0 +1,527 @@
|
|||
#!/bin/sh
|
||||
# install - install a program, script, or datafile
|
||||
|
||||
scriptversion=2011-01-19.21; # UTC
|
||||
|
||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||
# following copyright and license.
|
||||
#
|
||||
# Copyright (C) 1994 X Consortium
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Except as contained in this notice, the name of the X Consortium shall not
|
||||
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||
# ings in this Software without prior written authorization from the X Consor-
|
||||
# tium.
|
||||
#
|
||||
#
|
||||
# FSF changes to this file are in the public domain.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# `make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch.
|
||||
|
||||
nl='
|
||||
'
|
||||
IFS=" "" $nl"
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit=${DOITPROG-}
|
||||
if test -z "$doit"; then
|
||||
doit_exec=exec
|
||||
else
|
||||
doit_exec=$doit
|
||||
fi
|
||||
|
||||
# Put in absolute file names if you don't have them in your path;
|
||||
# or use environment vars.
|
||||
|
||||
chgrpprog=${CHGRPPROG-chgrp}
|
||||
chmodprog=${CHMODPROG-chmod}
|
||||
chownprog=${CHOWNPROG-chown}
|
||||
cmpprog=${CMPPROG-cmp}
|
||||
cpprog=${CPPROG-cp}
|
||||
mkdirprog=${MKDIRPROG-mkdir}
|
||||
mvprog=${MVPROG-mv}
|
||||
rmprog=${RMPROG-rm}
|
||||
stripprog=${STRIPPROG-strip}
|
||||
|
||||
posix_glob='?'
|
||||
initialize_posix_glob='
|
||||
test "$posix_glob" != "?" || {
|
||||
if (set -f) 2>/dev/null; then
|
||||
posix_glob=
|
||||
else
|
||||
posix_glob=:
|
||||
fi
|
||||
}
|
||||
'
|
||||
|
||||
posix_mkdir=
|
||||
|
||||
# Desired mode of installed file.
|
||||
mode=0755
|
||||
|
||||
chgrpcmd=
|
||||
chmodcmd=$chmodprog
|
||||
chowncmd=
|
||||
mvcmd=$mvprog
|
||||
rmcmd="$rmprog -f"
|
||||
stripcmd=
|
||||
|
||||
src=
|
||||
dst=
|
||||
dir_arg=
|
||||
dst_arg=
|
||||
|
||||
copy_on_change=false
|
||||
no_target_directory=
|
||||
|
||||
usage="\
|
||||
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||
or: $0 [OPTION]... SRCFILES... DIRECTORY
|
||||
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
|
||||
or: $0 [OPTION]... -d DIRECTORIES...
|
||||
|
||||
In the 1st form, copy SRCFILE to DSTFILE.
|
||||
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
|
||||
In the 4th, create DIRECTORIES.
|
||||
|
||||
Options:
|
||||
--help display this help and exit.
|
||||
--version display version info and exit.
|
||||
|
||||
-c (ignored)
|
||||
-C install only if different (preserve the last data modification time)
|
||||
-d create directories instead of installing files.
|
||||
-g GROUP $chgrpprog installed files to GROUP.
|
||||
-m MODE $chmodprog installed files to MODE.
|
||||
-o USER $chownprog installed files to USER.
|
||||
-s $stripprog installed files.
|
||||
-t DIRECTORY install into DIRECTORY.
|
||||
-T report an error if DSTFILE is a directory.
|
||||
|
||||
Environment variables override the default commands:
|
||||
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
|
||||
RMPROG STRIPPROG
|
||||
"
|
||||
|
||||
while test $# -ne 0; do
|
||||
case $1 in
|
||||
-c) ;;
|
||||
|
||||
-C) copy_on_change=true;;
|
||||
|
||||
-d) dir_arg=true;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift;;
|
||||
|
||||
--help) echo "$usage"; exit $?;;
|
||||
|
||||
-m) mode=$2
|
||||
case $mode in
|
||||
*' '* | *' '* | *'
|
||||
'* | *'*'* | *'?'* | *'['*)
|
||||
echo "$0: invalid mode: $mode" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift;;
|
||||
|
||||
-s) stripcmd=$stripprog;;
|
||||
|
||||
-t) dst_arg=$2
|
||||
# Protect names problematic for `test' and other utilities.
|
||||
case $dst_arg in
|
||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-T) no_target_directory=true;;
|
||||
|
||||
--version) echo "$0 $scriptversion"; exit $?;;
|
||||
|
||||
--) shift
|
||||
break;;
|
||||
|
||||
-*) echo "$0: invalid option: $1" >&2
|
||||
exit 1;;
|
||||
|
||||
*) break;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
|
||||
# When -d is used, all remaining arguments are directories to create.
|
||||
# When -t is used, the destination is already specified.
|
||||
# Otherwise, the last argument is the destination. Remove it from $@.
|
||||
for arg
|
||||
do
|
||||
if test -n "$dst_arg"; then
|
||||
# $@ is not empty: it contains at least $arg.
|
||||
set fnord "$@" "$dst_arg"
|
||||
shift # fnord
|
||||
fi
|
||||
shift # arg
|
||||
dst_arg=$arg
|
||||
# Protect names problematic for `test' and other utilities.
|
||||
case $dst_arg in
|
||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
if test $# -eq 0; then
|
||||
if test -z "$dir_arg"; then
|
||||
echo "$0: no input file specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
# It's OK to call `install-sh -d' without argument.
|
||||
# This can happen when creating conditional directories.
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test -z "$dir_arg"; then
|
||||
do_exit='(exit $ret); exit $ret'
|
||||
trap "ret=129; $do_exit" 1
|
||||
trap "ret=130; $do_exit" 2
|
||||
trap "ret=141; $do_exit" 13
|
||||
trap "ret=143; $do_exit" 15
|
||||
|
||||
# Set umask so as not to create temps with too-generous modes.
|
||||
# However, 'strip' requires both read and write access to temps.
|
||||
case $mode in
|
||||
# Optimize common cases.
|
||||
*644) cp_umask=133;;
|
||||
*755) cp_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw='% 200'
|
||||
fi
|
||||
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
|
||||
*)
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw=,u+rw
|
||||
fi
|
||||
cp_umask=$mode$u_plus_rw;;
|
||||
esac
|
||||
fi
|
||||
|
||||
for src
|
||||
do
|
||||
# Protect names problematic for `test' and other utilities.
|
||||
case $src in
|
||||
-* | [=\(\)!]) src=./$src;;
|
||||
esac
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
dst=$src
|
||||
dstdir=$dst
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
if test ! -f "$src" && test ! -d "$src"; then
|
||||
echo "$0: $src does not exist." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -z "$dst_arg"; then
|
||||
echo "$0: no destination specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
dst=$dst_arg
|
||||
|
||||
# If destination is a directory, append the input filename; won't work
|
||||
# if double slashes aren't ignored.
|
||||
if test -d "$dst"; then
|
||||
if test -n "$no_target_directory"; then
|
||||
echo "$0: $dst_arg: Is a directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
dstdir=$dst
|
||||
dst=$dstdir/`basename "$src"`
|
||||
dstdir_status=0
|
||||
else
|
||||
# Prefer dirname, but fall back on a substitute if dirname fails.
|
||||
dstdir=`
|
||||
(dirname "$dst") 2>/dev/null ||
|
||||
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
||||
X"$dst" : 'X\(//\)[^/]' \| \
|
||||
X"$dst" : 'X\(//\)$' \| \
|
||||
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
|
||||
echo X"$dst" |
|
||||
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)[^/].*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\).*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
s/.*/./; q'
|
||||
`
|
||||
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
fi
|
||||
fi
|
||||
|
||||
obsolete_mkdir_used=false
|
||||
|
||||
if test $dstdir_status != 0; then
|
||||
case $posix_mkdir in
|
||||
'')
|
||||
# Create intermediate dirs using mode 755 as modified by the umask.
|
||||
# This is like FreeBSD 'install' as of 1997-10-28.
|
||||
umask=`umask`
|
||||
case $stripcmd.$umask in
|
||||
# Optimize common cases.
|
||||
*[2367][2367]) mkdir_umask=$umask;;
|
||||
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
mkdir_umask=`expr $umask + 22 \
|
||||
- $umask % 100 % 40 + $umask % 20 \
|
||||
- $umask % 10 % 4 + $umask % 2
|
||||
`;;
|
||||
*) mkdir_umask=$umask,go-w;;
|
||||
esac
|
||||
|
||||
# With -d, create the new directory with the user-specified mode.
|
||||
# Otherwise, rely on $mkdir_umask.
|
||||
if test -n "$dir_arg"; then
|
||||
mkdir_mode=-m$mode
|
||||
else
|
||||
mkdir_mode=
|
||||
fi
|
||||
|
||||
posix_mkdir=false
|
||||
case $umask in
|
||||
*[123567][0-7][0-7])
|
||||
# POSIX mkdir -p sets u+wx bits regardless of umask, which
|
||||
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
|
||||
;;
|
||||
*)
|
||||
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
|
||||
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
|
||||
|
||||
if (umask $mkdir_umask &&
|
||||
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
|
||||
then
|
||||
if test -z "$dir_arg" || {
|
||||
# Check for POSIX incompatibilities with -m.
|
||||
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
||||
# other-writeable bit of parent directory when it shouldn't.
|
||||
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
||||
ls_ld_tmpdir=`ls -ld "$tmpdir"`
|
||||
case $ls_ld_tmpdir in
|
||||
d????-?r-*) different_mode=700;;
|
||||
d????-?--*) different_mode=755;;
|
||||
*) false;;
|
||||
esac &&
|
||||
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
|
||||
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
|
||||
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
|
||||
}
|
||||
}
|
||||
then posix_mkdir=:
|
||||
fi
|
||||
rmdir "$tmpdir/d" "$tmpdir"
|
||||
else
|
||||
# Remove any dirs left behind by ancient mkdir implementations.
|
||||
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
|
||||
fi
|
||||
trap '' 0;;
|
||||
esac;;
|
||||
esac
|
||||
|
||||
if
|
||||
$posix_mkdir && (
|
||||
umask $mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
|
||||
)
|
||||
then :
|
||||
else
|
||||
|
||||
# The umask is ridiculous, or mkdir does not conform to POSIX,
|
||||
# or it failed possibly due to a race condition. Create the
|
||||
# directory the slow way, step by step, checking for races as we go.
|
||||
|
||||
case $dstdir in
|
||||
/*) prefix='/';;
|
||||
[-=\(\)!]*) prefix='./';;
|
||||
*) prefix='';;
|
||||
esac
|
||||
|
||||
eval "$initialize_posix_glob"
|
||||
|
||||
oIFS=$IFS
|
||||
IFS=/
|
||||
$posix_glob set -f
|
||||
set fnord $dstdir
|
||||
shift
|
||||
$posix_glob set +f
|
||||
IFS=$oIFS
|
||||
|
||||
prefixes=
|
||||
|
||||
for d
|
||||
do
|
||||
test X"$d" = X && continue
|
||||
|
||||
prefix=$prefix$d
|
||||
if test -d "$prefix"; then
|
||||
prefixes=
|
||||
else
|
||||
if $posix_mkdir; then
|
||||
(umask=$mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
|
||||
# Don't fail if two instances are running concurrently.
|
||||
test -d "$prefix" || exit 1
|
||||
else
|
||||
case $prefix in
|
||||
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
|
||||
*) qprefix=$prefix;;
|
||||
esac
|
||||
prefixes="$prefixes '$qprefix'"
|
||||
fi
|
||||
fi
|
||||
prefix=$prefix/
|
||||
done
|
||||
|
||||
if test -n "$prefixes"; then
|
||||
# Don't fail if two instances are running concurrently.
|
||||
(umask $mkdir_umask &&
|
||||
eval "\$doit_exec \$mkdirprog $prefixes") ||
|
||||
test -d "$dstdir" || exit 1
|
||||
obsolete_mkdir_used=true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
|
||||
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
|
||||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
|
||||
else
|
||||
|
||||
# Make a couple of temp file names in the proper directory.
|
||||
dsttmp=$dstdir/_inst.$$_
|
||||
rmtmp=$dstdir/_rm.$$_
|
||||
|
||||
# Trap to clean up those temp files at exit.
|
||||
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||
|
||||
# Copy the file name to the temp name.
|
||||
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits.
|
||||
#
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||
#
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
|
||||
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
|
||||
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
|
||||
|
||||
# If -C, don't bother to copy if it wouldn't change the file.
|
||||
if $copy_on_change &&
|
||||
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
|
||||
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
|
||||
|
||||
eval "$initialize_posix_glob" &&
|
||||
$posix_glob set -f &&
|
||||
set X $old && old=:$2:$4:$5:$6 &&
|
||||
set X $new && new=:$2:$4:$5:$6 &&
|
||||
$posix_glob set +f &&
|
||||
|
||||
test "$old" = "$new" &&
|
||||
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
|
||||
then
|
||||
rm -f "$dsttmp"
|
||||
else
|
||||
# Rename the file to the real destination.
|
||||
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
|
||||
|
||||
# The rename failed, perhaps because mv can't rename something else
|
||||
# to itself, or perhaps because mv is so ancient that it does not
|
||||
# support -f.
|
||||
{
|
||||
# Now remove or move aside any old file at destination location.
|
||||
# We try this two ways since rm can't unlink itself on some
|
||||
# systems and the destination file might be busy for other
|
||||
# reasons. In this case, the final cleanup might fail but the new
|
||||
# file should still install successfully.
|
||||
{
|
||||
test ! -f "$dst" ||
|
||||
$doit $rmcmd -f "$dst" 2>/dev/null ||
|
||||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
|
||||
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
|
||||
} ||
|
||||
{ echo "$0: cannot unlink or rename $dst" >&2
|
||||
(exit 1); exit 1
|
||||
}
|
||||
} &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
$doit $mvcmd "$dsttmp" "$dst"
|
||||
}
|
||||
fi || exit 1
|
||||
|
||||
trap '' 0
|
||||
fi
|
||||
done
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
202
external/bsd/libevent/dist/iocp-internal.h
vendored
Normal file
202
external/bsd/libevent/dist/iocp-internal.h
vendored
Normal file
|
@ -0,0 +1,202 @@
|
|||
/* $NetBSD: iocp-internal.h,v 1.1.1.1 2013/04/11 16:43:29 christos Exp $ */
|
||||
/*
|
||||
* 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 _EVENT_IOCP_INTERNAL_H
|
||||
#define _EVENT_IOCP_INTERNAL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct event_overlapped;
|
||||
struct event_iocp_port;
|
||||
struct evbuffer;
|
||||
typedef void (*iocp_callback)(struct event_overlapped *, ev_uintptr_t, ev_ssize_t, int success);
|
||||
|
||||
/* This whole file is actually win32 only. We wrap the structures in a win32
|
||||
* ifdef so that we can test-compile code that uses these interfaces on
|
||||
* non-win32 platforms. */
|
||||
#ifdef WIN32
|
||||
|
||||
/**
|
||||
Internal use only. Wraps an OVERLAPPED that we're using for libevent
|
||||
functionality. Whenever an event_iocp_port gets an event for a given
|
||||
OVERLAPPED*, it upcasts the pointer to an event_overlapped, and calls the
|
||||
iocp_callback function with the event_overlapped, the iocp key, and the
|
||||
number of bytes transferred as arguments.
|
||||
*/
|
||||
struct event_overlapped {
|
||||
OVERLAPPED overlapped;
|
||||
iocp_callback cb;
|
||||
};
|
||||
|
||||
/* Mingw's headers don't define LPFN_ACCEPTEX. */
|
||||
|
||||
typedef BOOL (WINAPI *AcceptExPtr)(SOCKET, SOCKET, PVOID, DWORD, DWORD, DWORD, LPDWORD, LPOVERLAPPED);
|
||||
typedef BOOL (WINAPI *ConnectExPtr)(SOCKET, const struct sockaddr *, int, PVOID, DWORD, LPDWORD, LPOVERLAPPED);
|
||||
typedef void (WINAPI *GetAcceptExSockaddrsPtr)(PVOID, DWORD, DWORD, DWORD, LPSOCKADDR *, LPINT, LPSOCKADDR *, LPINT);
|
||||
|
||||
/** Internal use only. Holds pointers to functions that only some versions of
|
||||
Windows provide.
|
||||
*/
|
||||
struct win32_extension_fns {
|
||||
AcceptExPtr AcceptEx;
|
||||
ConnectExPtr ConnectEx;
|
||||
GetAcceptExSockaddrsPtr GetAcceptExSockaddrs;
|
||||
};
|
||||
|
||||
/**
|
||||
Internal use only. Stores a Windows IO Completion port, along with
|
||||
related data.
|
||||
*/
|
||||
struct event_iocp_port {
|
||||
/** The port itself */
|
||||
HANDLE port;
|
||||
/* A lock to cover internal structures. */
|
||||
CRITICAL_SECTION lock;
|
||||
/** Number of threads ever open on the port. */
|
||||
short n_threads;
|
||||
/** True iff we're shutting down all the threads on this port */
|
||||
short shutdown;
|
||||
/** How often the threads on this port check for shutdown and other
|
||||
* conditions */
|
||||
long ms;
|
||||
/* The threads that are waiting for events. */
|
||||
HANDLE *threads;
|
||||
/** Number of threads currently open on this port. */
|
||||
short n_live_threads;
|
||||
/** A semaphore to signal when we are done shutting down. */
|
||||
HANDLE *shutdownSemaphore;
|
||||
};
|
||||
|
||||
const struct win32_extension_fns *event_get_win32_extension_fns(void);
|
||||
#else
|
||||
/* Dummy definition so we can test-compile more things on unix. */
|
||||
struct event_overlapped {
|
||||
iocp_callback cb;
|
||||
};
|
||||
#endif
|
||||
|
||||
/** Initialize the fields in an event_overlapped.
|
||||
|
||||
@param overlapped The struct event_overlapped to initialize
|
||||
@param cb The callback that should be invoked once the IO operation has
|
||||
finished.
|
||||
*/
|
||||
void event_overlapped_init(struct event_overlapped *, iocp_callback cb);
|
||||
|
||||
/** Allocate and return a new evbuffer that supports overlapped IO on a given
|
||||
socket. The socket must be associated with an IO completion port using
|
||||
event_iocp_port_associate.
|
||||
*/
|
||||
struct evbuffer *evbuffer_overlapped_new(evutil_socket_t fd);
|
||||
|
||||
/** XXXX Document (nickm) */
|
||||
evutil_socket_t _evbuffer_overlapped_get_fd(struct evbuffer *buf);
|
||||
|
||||
void _evbuffer_overlapped_set_fd(struct evbuffer *buf, evutil_socket_t fd);
|
||||
|
||||
/** Start reading data onto the end of an overlapped evbuffer.
|
||||
|
||||
An evbuffer can only have one read pending at a time. While the read
|
||||
is in progress, no other data may be added to the end of the buffer.
|
||||
The buffer must be created with event_overlapped_init().
|
||||
evbuffer_commit_read() must be called in the completion callback.
|
||||
|
||||
@param buf The buffer to read onto
|
||||
@param n The number of bytes to try to read.
|
||||
@param ol Overlapped object with associated completion callback.
|
||||
@return 0 on success, -1 on error.
|
||||
*/
|
||||
int evbuffer_launch_read(struct evbuffer *buf, size_t n, struct event_overlapped *ol);
|
||||
|
||||
/** Start writing data from the start of an evbuffer.
|
||||
|
||||
An evbuffer can only have one write pending at a time. While the write is
|
||||
in progress, no other data may be removed from the front of the buffer.
|
||||
The buffer must be created with event_overlapped_init().
|
||||
evbuffer_commit_write() must be called in the completion callback.
|
||||
|
||||
@param buf The buffer to read onto
|
||||
@param n The number of bytes to try to read.
|
||||
@param ol Overlapped object with associated completion callback.
|
||||
@return 0 on success, -1 on error.
|
||||
*/
|
||||
int evbuffer_launch_write(struct evbuffer *buf, ev_ssize_t n, struct event_overlapped *ol);
|
||||
|
||||
/** XXX document */
|
||||
void evbuffer_commit_read(struct evbuffer *, ev_ssize_t);
|
||||
void evbuffer_commit_write(struct evbuffer *, ev_ssize_t);
|
||||
|
||||
/** Create an IOCP, and launch its worker threads. Internal use only.
|
||||
|
||||
This interface is unstable, and will change.
|
||||
*/
|
||||
struct event_iocp_port *event_iocp_port_launch(int n_cpus);
|
||||
|
||||
/** Associate a file descriptor with an iocp, such that overlapped IO on the
|
||||
fd will happen on one of the iocp's worker threads.
|
||||
*/
|
||||
int event_iocp_port_associate(struct event_iocp_port *port, evutil_socket_t fd,
|
||||
ev_uintptr_t key);
|
||||
|
||||
/** Tell all threads serving an iocp to stop. Wait for up to waitMsec for all
|
||||
the threads to finish whatever they're doing. If waitMsec is -1, wait
|
||||
as long as required. If all the threads are done, free the port and return
|
||||
0. Otherwise, return -1. If you get a -1 return value, it is safe to call
|
||||
this function again.
|
||||
*/
|
||||
int event_iocp_shutdown(struct event_iocp_port *port, long waitMsec);
|
||||
|
||||
/* FIXME document. */
|
||||
int event_iocp_activate_overlapped(struct event_iocp_port *port,
|
||||
struct event_overlapped *o,
|
||||
ev_uintptr_t key, ev_uint32_t n_bytes);
|
||||
|
||||
struct event_base;
|
||||
/* FIXME document. */
|
||||
struct event_iocp_port *event_base_get_iocp(struct event_base *base);
|
||||
|
||||
/* FIXME document. */
|
||||
int event_base_start_iocp(struct event_base *base, int n_cpus);
|
||||
void event_base_stop_iocp(struct event_base *base);
|
||||
|
||||
/* FIXME document. */
|
||||
struct bufferevent *bufferevent_async_new(struct event_base *base,
|
||||
evutil_socket_t fd, int options);
|
||||
|
||||
/* FIXME document. */
|
||||
void bufferevent_async_set_connected(struct bufferevent *bev);
|
||||
int bufferevent_async_can_connect(struct bufferevent *bev);
|
||||
int bufferevent_async_connect(struct bufferevent *bev, evutil_socket_t fd,
|
||||
const struct sockaddr *sa, int socklen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
82
external/bsd/libevent/dist/ipv6-internal.h
vendored
Normal file
82
external/bsd/libevent/dist/ipv6-internal.h
vendored
Normal file
|
@ -0,0 +1,82 @@
|
|||
/* $NetBSD: ipv6-internal.h,v 1.1.1.1 2013/04/11 16:43:28 christos Exp $ */
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Internal use only: Fake IPv6 structures and values on platforms that
|
||||
* do not have them */
|
||||
|
||||
#ifndef _EVENT_IPV6_INTERNAL_H
|
||||
#define _EVENT_IPV6_INTERNAL_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef _EVENT_HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#include "event2/event-config.h"
|
||||
#include "event2/util.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @file ipv6-internal.h
|
||||
*
|
||||
* Replacement types and functions for platforms that don't support ipv6
|
||||
* properly.
|
||||
*/
|
||||
|
||||
#ifndef _EVENT_HAVE_STRUCT_IN6_ADDR
|
||||
struct in6_addr {
|
||||
ev_uint8_t s6_addr[16];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef _EVENT_HAVE_SA_FAMILY_T
|
||||
typedef int sa_family_t;
|
||||
#endif
|
||||
|
||||
#ifndef _EVENT_HAVE_STRUCT_SOCKADDR_IN6
|
||||
struct sockaddr_in6 {
|
||||
/* This will fail if we find a struct sockaddr that doesn't have
|
||||
* sa_family as the first element. */
|
||||
sa_family_t sin6_family;
|
||||
ev_uint16_t sin6_port;
|
||||
struct in6_addr sin6_addr;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef AF_INET6
|
||||
#define AF_INET6 3333
|
||||
#endif
|
||||
#ifndef PF_INET6
|
||||
#define PF_INET6 AF_INET6
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
478
external/bsd/libevent/dist/kqueue.c
vendored
Normal file
478
external/bsd/libevent/dist/kqueue.c
vendored
Normal file
|
@ -0,0 +1,478 @@
|
|||
/* $NetBSD: kqueue.c,v 1.1.1.2 2013/04/11 16:43:24 christos Exp $ */
|
||||
/* $OpenBSD: kqueue.c,v 1.5 2002/07/10 14:41:31 art Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2000-2007 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright 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.
|
||||
*/
|
||||
#include "event2/event-config.h"
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: kqueue.c,v 1.1.1.2 2013/04/11 16:43:24 christos Exp $");
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef _EVENT_HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include <sys/queue.h>
|
||||
#include <sys/event.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#ifdef _EVENT_HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
/* Some platforms apparently define the udata field of struct kevent as
|
||||
* intptr_t, whereas others define it as void*. There doesn't seem to be an
|
||||
* easy way to tell them apart via autoconf, so we need to use OS macros. */
|
||||
#if defined(_EVENT_HAVE_INTTYPES_H) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__darwin__) && !defined(__APPLE__)
|
||||
#define PTR_TO_UDATA(x) ((intptr_t)(x))
|
||||
#define INT_TO_UDATA(x) ((intptr_t)(x))
|
||||
#else
|
||||
#define PTR_TO_UDATA(x) (x)
|
||||
#define INT_TO_UDATA(x) ((void*)(x))
|
||||
#endif
|
||||
|
||||
#include "event-internal.h"
|
||||
#include "log-internal.h"
|
||||
#include "evmap-internal.h"
|
||||
#include "event2/thread.h"
|
||||
#include "evthread-internal.h"
|
||||
#include "changelist-internal.h"
|
||||
|
||||
#define NEVENT 64
|
||||
|
||||
struct kqop {
|
||||
struct kevent *changes;
|
||||
int changes_size;
|
||||
|
||||
struct kevent *events;
|
||||
int events_size;
|
||||
int kq;
|
||||
pid_t pid;
|
||||
};
|
||||
|
||||
static void kqop_free(struct kqop *kqop);
|
||||
|
||||
static void *kq_init(struct event_base *);
|
||||
static int kq_sig_add(struct event_base *, int, short, short, void *);
|
||||
static int kq_sig_del(struct event_base *, int, short, short, void *);
|
||||
static int kq_dispatch(struct event_base *, struct timeval *);
|
||||
static void kq_dealloc(struct event_base *);
|
||||
|
||||
const struct eventop kqops = {
|
||||
"kqueue",
|
||||
kq_init,
|
||||
event_changelist_add,
|
||||
event_changelist_del,
|
||||
kq_dispatch,
|
||||
kq_dealloc,
|
||||
1 /* need reinit */,
|
||||
EV_FEATURE_ET|EV_FEATURE_O1|EV_FEATURE_FDS,
|
||||
EVENT_CHANGELIST_FDINFO_SIZE
|
||||
};
|
||||
|
||||
static const struct eventop kqsigops = {
|
||||
"kqueue_signal",
|
||||
NULL,
|
||||
kq_sig_add,
|
||||
kq_sig_del,
|
||||
NULL,
|
||||
NULL,
|
||||
1 /* need reinit */,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
static void *
|
||||
kq_init(struct event_base *base)
|
||||
{
|
||||
int kq = -1;
|
||||
struct kqop *kqueueop = NULL;
|
||||
|
||||
if (!(kqueueop = mm_calloc(1, sizeof(struct kqop))))
|
||||
return (NULL);
|
||||
|
||||
/* Initialize the kernel queue */
|
||||
|
||||
if ((kq = kqueue()) == -1) {
|
||||
event_warn("kqueue");
|
||||
goto err;
|
||||
}
|
||||
|
||||
kqueueop->kq = kq;
|
||||
|
||||
kqueueop->pid = getpid();
|
||||
|
||||
/* Initialize fields */
|
||||
kqueueop->changes = mm_calloc(NEVENT, sizeof(struct kevent));
|
||||
if (kqueueop->changes == NULL)
|
||||
goto err;
|
||||
kqueueop->events = mm_calloc(NEVENT, sizeof(struct kevent));
|
||||
if (kqueueop->events == NULL)
|
||||
goto err;
|
||||
kqueueop->events_size = kqueueop->changes_size = NEVENT;
|
||||
|
||||
/* Check for Mac OS X kqueue bug. */
|
||||
memset(&kqueueop->changes[0], 0, sizeof kqueueop->changes[0]);
|
||||
kqueueop->changes[0].ident = -1;
|
||||
kqueueop->changes[0].filter = EVFILT_READ;
|
||||
kqueueop->changes[0].flags = EV_ADD;
|
||||
/*
|
||||
* If kqueue works, then kevent will succeed, and it will
|
||||
* stick an error in events[0]. If kqueue is broken, then
|
||||
* kevent will fail.
|
||||
*/
|
||||
if (kevent(kq,
|
||||
kqueueop->changes, 1, kqueueop->events, NEVENT, NULL) != 1 ||
|
||||
(int)kqueueop->events[0].ident != -1 ||
|
||||
kqueueop->events[0].flags != EV_ERROR) {
|
||||
event_warn("%s: detected broken kqueue; not using.", __func__);
|
||||
goto err;
|
||||
}
|
||||
|
||||
base->evsigsel = &kqsigops;
|
||||
|
||||
return (kqueueop);
|
||||
err:
|
||||
if (kqueueop)
|
||||
kqop_free(kqueueop);
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
kq_sighandler(int sig)
|
||||
{
|
||||
/* Do nothing here */
|
||||
}
|
||||
|
||||
#define ADD_UDATA 0x30303
|
||||
|
||||
static void
|
||||
kq_setup_kevent(struct kevent *out, evutil_socket_t fd, int filter, short change)
|
||||
{
|
||||
memset(out, 0, sizeof(struct kevent));
|
||||
out->ident = fd;
|
||||
out->filter = filter;
|
||||
|
||||
if (change & EV_CHANGE_ADD) {
|
||||
out->flags = EV_ADD;
|
||||
/* We set a magic number here so that we can tell 'add'
|
||||
* errors from 'del' errors. */
|
||||
out->udata = INT_TO_UDATA(ADD_UDATA);
|
||||
if (change & EV_ET)
|
||||
out->flags |= EV_CLEAR;
|
||||
#ifdef NOTE_EOF
|
||||
/* Make it behave like select() and poll() */
|
||||
if (filter == EVFILT_READ)
|
||||
out->fflags = NOTE_EOF;
|
||||
#endif
|
||||
} else {
|
||||
EVUTIL_ASSERT(change & EV_CHANGE_DEL);
|
||||
out->flags = EV_DELETE;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
kq_build_changes_list(const struct event_changelist *changelist,
|
||||
struct kqop *kqop)
|
||||
{
|
||||
int i;
|
||||
int n_changes = 0;
|
||||
|
||||
for (i = 0; i < changelist->n_changes; ++i) {
|
||||
struct event_change *in_ch = &changelist->changes[i];
|
||||
struct kevent *out_ch;
|
||||
if (n_changes >= kqop->changes_size - 1) {
|
||||
int newsize = kqop->changes_size * 2;
|
||||
struct kevent *newchanges;
|
||||
|
||||
newchanges = mm_realloc(kqop->changes,
|
||||
newsize * sizeof(struct kevent));
|
||||
if (newchanges == NULL) {
|
||||
event_warn("%s: realloc", __func__);
|
||||
return (-1);
|
||||
}
|
||||
kqop->changes = newchanges;
|
||||
kqop->changes_size = newsize;
|
||||
}
|
||||
if (in_ch->read_change) {
|
||||
out_ch = &kqop->changes[n_changes++];
|
||||
kq_setup_kevent(out_ch, in_ch->fd, EVFILT_READ,
|
||||
in_ch->read_change);
|
||||
}
|
||||
if (in_ch->write_change) {
|
||||
out_ch = &kqop->changes[n_changes++];
|
||||
kq_setup_kevent(out_ch, in_ch->fd, EVFILT_WRITE,
|
||||
in_ch->write_change);
|
||||
}
|
||||
}
|
||||
return n_changes;
|
||||
}
|
||||
|
||||
static int
|
||||
kq_grow_events(struct kqop *kqop, size_t new_size)
|
||||
{
|
||||
struct kevent *newresult;
|
||||
|
||||
newresult = mm_realloc(kqop->events,
|
||||
new_size * sizeof(struct kevent));
|
||||
|
||||
if (newresult) {
|
||||
kqop->events = newresult;
|
||||
kqop->events_size = new_size;
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
kq_dispatch(struct event_base *base, struct timeval *tv)
|
||||
{
|
||||
struct kqop *kqop = base->evbase;
|
||||
struct kevent *events = kqop->events;
|
||||
struct kevent *changes;
|
||||
struct timespec ts, *ts_p = NULL;
|
||||
int i, n_changes, res;
|
||||
|
||||
if (tv != NULL) {
|
||||
TIMEVAL_TO_TIMESPEC(tv, &ts);
|
||||
ts_p = &ts;
|
||||
}
|
||||
|
||||
/* Build "changes" from "base->changes" */
|
||||
EVUTIL_ASSERT(kqop->changes);
|
||||
n_changes = kq_build_changes_list(&base->changelist, kqop);
|
||||
if (n_changes < 0)
|
||||
return -1;
|
||||
|
||||
event_changelist_remove_all(&base->changelist, base);
|
||||
|
||||
/* steal the changes array in case some broken code tries to call
|
||||
* dispatch twice at once. */
|
||||
changes = kqop->changes;
|
||||
kqop->changes = NULL;
|
||||
|
||||
/* Make sure that 'events' is at least as long as the list of changes:
|
||||
* otherwise errors in the changes can get reported as a -1 return
|
||||
* value from kevent() rather than as EV_ERROR events in the events
|
||||
* array.
|
||||
*
|
||||
* (We could instead handle -1 return values from kevent() by
|
||||
* retrying with a smaller changes array or a larger events array,
|
||||
* but this approach seems less risky for now.)
|
||||
*/
|
||||
if (kqop->events_size < n_changes) {
|
||||
int new_size = kqop->events_size;
|
||||
do {
|
||||
new_size *= 2;
|
||||
} while (new_size < n_changes);
|
||||
|
||||
kq_grow_events(kqop, new_size);
|
||||
events = kqop->events;
|
||||
}
|
||||
|
||||
EVBASE_RELEASE_LOCK(base, th_base_lock);
|
||||
|
||||
res = kevent(kqop->kq, changes, n_changes,
|
||||
events, kqop->events_size, ts_p);
|
||||
|
||||
EVBASE_ACQUIRE_LOCK(base, th_base_lock);
|
||||
|
||||
EVUTIL_ASSERT(kqop->changes == NULL);
|
||||
kqop->changes = changes;
|
||||
|
||||
if (res == -1) {
|
||||
if (errno != EINTR) {
|
||||
event_warn("kevent");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
event_debug(("%s: kevent reports %d", __func__, res));
|
||||
|
||||
for (i = 0; i < res; i++) {
|
||||
int which = 0;
|
||||
|
||||
if (events[i].flags & EV_ERROR) {
|
||||
switch (events[i].data) {
|
||||
|
||||
/* Can occur on delete if we are not currently
|
||||
* watching any events on this fd. That can
|
||||
* happen when the fd was closed and another
|
||||
* file was opened with that fd. */
|
||||
case ENOENT:
|
||||
/* Can occur for reasons not fully understood
|
||||
* on FreeBSD. */
|
||||
case EINVAL:
|
||||
continue;
|
||||
|
||||
/* Can occur on a delete if the fd is closed. */
|
||||
case EBADF:
|
||||
/* XXXX On NetBSD, we can also get EBADF if we
|
||||
* try to add the write side of a pipe, but
|
||||
* the read side has already been closed.
|
||||
* Other BSDs call this situation 'EPIPE'. It
|
||||
* would be good if we had a way to report
|
||||
* this situation. */
|
||||
continue;
|
||||
/* These two can occur on an add if the fd was one side
|
||||
* of a pipe, and the other side was closed. */
|
||||
case EPERM:
|
||||
case EPIPE:
|
||||
/* Report read events, if we're listening for
|
||||
* them, so that the user can learn about any
|
||||
* add errors. (If the operation was a
|
||||
* delete, then udata should be cleared.) */
|
||||
if (events[i].udata) {
|
||||
/* The operation was an add:
|
||||
* report the error as a read. */
|
||||
which |= EV_READ;
|
||||
break;
|
||||
} else {
|
||||
/* The operation was a del:
|
||||
* report nothing. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Other errors shouldn't occur. */
|
||||
default:
|
||||
errno = events[i].data;
|
||||
return (-1);
|
||||
}
|
||||
} else if (events[i].filter == EVFILT_READ) {
|
||||
which |= EV_READ;
|
||||
} else if (events[i].filter == EVFILT_WRITE) {
|
||||
which |= EV_WRITE;
|
||||
} else if (events[i].filter == EVFILT_SIGNAL) {
|
||||
which |= EV_SIGNAL;
|
||||
}
|
||||
|
||||
if (!which)
|
||||
continue;
|
||||
|
||||
if (events[i].filter == EVFILT_SIGNAL) {
|
||||
evmap_signal_active(base, events[i].ident, 1);
|
||||
} else {
|
||||
evmap_io_active(base, events[i].ident, which | EV_ET);
|
||||
}
|
||||
}
|
||||
|
||||
if (res == kqop->events_size) {
|
||||
/* We used all the events space that we have. Maybe we should
|
||||
make it bigger. */
|
||||
kq_grow_events(kqop, kqop->events_size * 2);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
kqop_free(struct kqop *kqop)
|
||||
{
|
||||
if (kqop->changes)
|
||||
mm_free(kqop->changes);
|
||||
if (kqop->events)
|
||||
mm_free(kqop->events);
|
||||
if (kqop->kq >= 0 && kqop->pid == getpid())
|
||||
close(kqop->kq);
|
||||
memset(kqop, 0, sizeof(struct kqop));
|
||||
mm_free(kqop);
|
||||
}
|
||||
|
||||
static void
|
||||
kq_dealloc(struct event_base *base)
|
||||
{
|
||||
struct kqop *kqop = base->evbase;
|
||||
evsig_dealloc(base);
|
||||
kqop_free(kqop);
|
||||
}
|
||||
|
||||
/* signal handling */
|
||||
static int
|
||||
kq_sig_add(struct event_base *base, int nsignal, short old, short events, void *p)
|
||||
{
|
||||
struct kqop *kqop = base->evbase;
|
||||
struct kevent kev;
|
||||
struct timespec timeout = { 0, 0 };
|
||||
(void)p;
|
||||
|
||||
EVUTIL_ASSERT(nsignal >= 0 && nsignal < NSIG);
|
||||
|
||||
memset(&kev, 0, sizeof(kev));
|
||||
kev.ident = nsignal;
|
||||
kev.filter = EVFILT_SIGNAL;
|
||||
kev.flags = EV_ADD;
|
||||
|
||||
/* Be ready for the signal if it is sent any
|
||||
* time between now and the next call to
|
||||
* kq_dispatch. */
|
||||
if (kevent(kqop->kq, &kev, 1, NULL, 0, &timeout) == -1)
|
||||
return (-1);
|
||||
|
||||
/* XXXX The manpage suggest we could use SIG_IGN instead of a
|
||||
* do-nothing handler */
|
||||
if (_evsig_set_handler(base, nsignal, kq_sighandler) == -1)
|
||||
return (-1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
kq_sig_del(struct event_base *base, int nsignal, short old, short events, void *p)
|
||||
{
|
||||
struct kqop *kqop = base->evbase;
|
||||
struct kevent kev;
|
||||
|
||||
struct timespec timeout = { 0, 0 };
|
||||
(void)p;
|
||||
|
||||
EVUTIL_ASSERT(nsignal >= 0 && nsignal < NSIG);
|
||||
|
||||
memset(&kev, 0, sizeof(kev));
|
||||
kev.ident = nsignal;
|
||||
kev.filter = EVFILT_SIGNAL;
|
||||
kev.flags = EV_DELETE;
|
||||
|
||||
/* Because we insert signal events
|
||||
* immediately, we need to delete them
|
||||
* immediately, too */
|
||||
if (kevent(kqop->kq, &kev, 1, NULL, 0, &timeout) == -1)
|
||||
return (-1);
|
||||
|
||||
if (_evsig_restore_handler(base, nsignal) == -1)
|
||||
return (-1);
|
||||
|
||||
return (0);
|
||||
}
|
16
external/bsd/libevent/dist/libevent.pc.in
vendored
Normal file
16
external/bsd/libevent/dist/libevent.pc.in
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
#libevent pkg-config source file
|
||||
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: libevent
|
||||
Description: libevent is an asynchronous notification event loop library
|
||||
Version: @VERSION@
|
||||
Requires:
|
||||
Conflicts:
|
||||
Libs: -L${libdir} -levent
|
||||
Libs.private: @LIBS@
|
||||
Cflags: -I${includedir}
|
||||
|
16
external/bsd/libevent/dist/libevent_openssl.pc.in
vendored
Normal file
16
external/bsd/libevent/dist/libevent_openssl.pc.in
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
#libevent pkg-config source file
|
||||
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: libevent_openssl
|
||||
Description: libevent_openssl adds openssl-based TLS support to libevent
|
||||
Version: @VERSION@
|
||||
Requires: libevent
|
||||
Conflicts:
|
||||
Libs: -L${libdir} -levent_openssl
|
||||
Libs.private: @LIBS@ -lssl -lcrypto
|
||||
Cflags: -I${includedir}
|
||||
|
16
external/bsd/libevent/dist/libevent_pthreads.pc.in
vendored
Normal file
16
external/bsd/libevent/dist/libevent_pthreads.pc.in
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
#libevent pkg-config source file
|
||||
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: libevent_pthreads
|
||||
Description: libevent_pthreads adds pthreads-based threading support to libevent
|
||||
Version: @VERSION@
|
||||
Requires: libevent
|
||||
Conflicts:
|
||||
Libs: -L${libdir} -levent_pthreads
|
||||
Libs.private: @LIBS@ @PTHREAD_LIBS@
|
||||
Cflags: -I${includedir} @PTHREAD_CFLAGS@
|
||||
|
888
external/bsd/libevent/dist/listener.c
vendored
Normal file
888
external/bsd/libevent/dist/listener.c
vendored
Normal file
|
@ -0,0 +1,888 @@
|
|||
/* $NetBSD: listener.c,v 1.1.1.1 2013/04/11 16:43:26 christos Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009-2012 Niels Provos, 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.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "event2/event-config.h"
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: listener.c,v 1.1.1.1 2013/04/11 16:43:26 christos Exp $");
|
||||
|
||||
#ifdef WIN32
|
||||
#ifndef _WIN32_WINNT
|
||||
/* Minimum required for InitializeCriticalSectionAndSpinCount */
|
||||
#define _WIN32_WINNT 0x0403
|
||||
#endif
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <mswsock.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#ifdef _EVENT_HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef _EVENT_HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#ifdef _EVENT_HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "event2/listener.h"
|
||||
#include "event2/util.h"
|
||||
#include "event2/event.h"
|
||||
#include "event2/event_struct.h"
|
||||
#include "mm-internal.h"
|
||||
#include "util-internal.h"
|
||||
#include "log-internal.h"
|
||||
#include "evthread-internal.h"
|
||||
#ifdef WIN32
|
||||
#include "iocp-internal.h"
|
||||
#include "defer-internal.h"
|
||||
#include "event-internal.h"
|
||||
#endif
|
||||
|
||||
struct evconnlistener_ops {
|
||||
int (*enable)(struct evconnlistener *);
|
||||
int (*disable)(struct evconnlistener *);
|
||||
void (*destroy)(struct evconnlistener *);
|
||||
void (*shutdown)(struct evconnlistener *);
|
||||
evutil_socket_t (*getfd)(struct evconnlistener *);
|
||||
struct event_base *(*getbase)(struct evconnlistener *);
|
||||
};
|
||||
|
||||
struct evconnlistener {
|
||||
const struct evconnlistener_ops *ops;
|
||||
void *lock;
|
||||
evconnlistener_cb cb;
|
||||
evconnlistener_errorcb errorcb;
|
||||
void *user_data;
|
||||
unsigned flags;
|
||||
short refcnt;
|
||||
unsigned enabled : 1;
|
||||
};
|
||||
|
||||
struct evconnlistener_event {
|
||||
struct evconnlistener base;
|
||||
struct event listener;
|
||||
};
|
||||
|
||||
#ifdef WIN32
|
||||
struct evconnlistener_iocp {
|
||||
struct evconnlistener base;
|
||||
evutil_socket_t fd;
|
||||
struct event_base *event_base;
|
||||
struct event_iocp_port *port;
|
||||
short n_accepting;
|
||||
unsigned shutting_down : 1;
|
||||
unsigned event_added : 1;
|
||||
struct accepting_socket **accepting;
|
||||
};
|
||||
#endif
|
||||
|
||||
#define LOCK(listener) EVLOCK_LOCK((listener)->lock, 0)
|
||||
#define UNLOCK(listener) EVLOCK_UNLOCK((listener)->lock, 0)
|
||||
|
||||
struct evconnlistener *
|
||||
evconnlistener_new_async(struct event_base *base,
|
||||
evconnlistener_cb cb, void *ptr, unsigned flags, int backlog,
|
||||
evutil_socket_t fd); /* XXXX export this? */
|
||||
|
||||
static int event_listener_enable(struct evconnlistener *);
|
||||
static int event_listener_disable(struct evconnlistener *);
|
||||
static void event_listener_destroy(struct evconnlistener *);
|
||||
static evutil_socket_t event_listener_getfd(struct evconnlistener *);
|
||||
static struct event_base *event_listener_getbase(struct evconnlistener *);
|
||||
|
||||
#if 0
|
||||
static void
|
||||
listener_incref_and_lock(struct evconnlistener *listener)
|
||||
{
|
||||
LOCK(listener);
|
||||
++listener->refcnt;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
listener_decref_and_unlock(struct evconnlistener *listener)
|
||||
{
|
||||
int refcnt = --listener->refcnt;
|
||||
if (refcnt == 0) {
|
||||
listener->ops->destroy(listener);
|
||||
UNLOCK(listener);
|
||||
EVTHREAD_FREE_LOCK(listener->lock, EVTHREAD_LOCKTYPE_RECURSIVE);
|
||||
mm_free(listener);
|
||||
return 1;
|
||||
} else {
|
||||
UNLOCK(listener);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct evconnlistener_ops evconnlistener_event_ops = {
|
||||
event_listener_enable,
|
||||
event_listener_disable,
|
||||
event_listener_destroy,
|
||||
NULL, /* shutdown */
|
||||
event_listener_getfd,
|
||||
event_listener_getbase
|
||||
};
|
||||
|
||||
static void listener_read_cb(evutil_socket_t, short, void *);
|
||||
|
||||
struct evconnlistener *
|
||||
evconnlistener_new(struct event_base *base,
|
||||
evconnlistener_cb cb, void *ptr, unsigned flags, int backlog,
|
||||
evutil_socket_t fd)
|
||||
{
|
||||
struct evconnlistener_event *lev;
|
||||
|
||||
#ifdef WIN32
|
||||
if (base && event_base_get_iocp(base)) {
|
||||
const struct win32_extension_fns *ext =
|
||||
event_get_win32_extension_fns();
|
||||
if (ext->AcceptEx && ext->GetAcceptExSockaddrs)
|
||||
return evconnlistener_new_async(base, cb, ptr, flags,
|
||||
backlog, fd);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (backlog > 0) {
|
||||
if (listen(fd, backlog) < 0)
|
||||
return NULL;
|
||||
} else if (backlog < 0) {
|
||||
if (listen(fd, 128) < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lev = mm_calloc(1, sizeof(struct evconnlistener_event));
|
||||
if (!lev)
|
||||
return NULL;
|
||||
|
||||
lev->base.ops = &evconnlistener_event_ops;
|
||||
lev->base.cb = cb;
|
||||
lev->base.user_data = ptr;
|
||||
lev->base.flags = flags;
|
||||
lev->base.refcnt = 1;
|
||||
|
||||
if (flags & LEV_OPT_THREADSAFE) {
|
||||
EVTHREAD_ALLOC_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE);
|
||||
}
|
||||
|
||||
event_assign(&lev->listener, base, fd, EV_READ|EV_PERSIST,
|
||||
listener_read_cb, lev);
|
||||
|
||||
evconnlistener_enable(&lev->base);
|
||||
|
||||
return &lev->base;
|
||||
}
|
||||
|
||||
struct evconnlistener *
|
||||
evconnlistener_new_bind(struct event_base *base, evconnlistener_cb cb,
|
||||
void *ptr, unsigned flags, int backlog, const struct sockaddr *sa,
|
||||
int socklen)
|
||||
{
|
||||
struct evconnlistener *listener;
|
||||
evutil_socket_t fd;
|
||||
int on = 1;
|
||||
int family = sa ? sa->sa_family : AF_UNSPEC;
|
||||
|
||||
if (backlog == 0)
|
||||
return NULL;
|
||||
|
||||
fd = socket(family, SOCK_STREAM, 0);
|
||||
if (fd == -1)
|
||||
return NULL;
|
||||
|
||||
if (evutil_make_socket_nonblocking(fd) < 0) {
|
||||
evutil_closesocket(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (flags & LEV_OPT_CLOSE_ON_EXEC) {
|
||||
if (evutil_make_socket_closeonexec(fd) < 0) {
|
||||
evutil_closesocket(fd);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&on, sizeof(on))<0) {
|
||||
evutil_closesocket(fd);
|
||||
return NULL;
|
||||
}
|
||||
if (flags & LEV_OPT_REUSEABLE) {
|
||||
if (evutil_make_listen_socket_reuseable(fd) < 0) {
|
||||
evutil_closesocket(fd);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (sa) {
|
||||
if (bind(fd, sa, socklen)<0) {
|
||||
evutil_closesocket(fd);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
listener = evconnlistener_new(base, cb, ptr, flags, backlog, fd);
|
||||
if (!listener) {
|
||||
evutil_closesocket(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return listener;
|
||||
}
|
||||
|
||||
void
|
||||
evconnlistener_free(struct evconnlistener *lev)
|
||||
{
|
||||
LOCK(lev);
|
||||
lev->cb = NULL;
|
||||
lev->errorcb = NULL;
|
||||
if (lev->ops->shutdown)
|
||||
lev->ops->shutdown(lev);
|
||||
listener_decref_and_unlock(lev);
|
||||
}
|
||||
|
||||
static void
|
||||
event_listener_destroy(struct evconnlistener *lev)
|
||||
{
|
||||
struct evconnlistener_event *lev_e =
|
||||
EVUTIL_UPCAST(lev, struct evconnlistener_event, base);
|
||||
|
||||
event_del(&lev_e->listener);
|
||||
if (lev->flags & LEV_OPT_CLOSE_ON_FREE)
|
||||
evutil_closesocket(event_get_fd(&lev_e->listener));
|
||||
event_debug_unassign(&lev_e->listener);
|
||||
}
|
||||
|
||||
int
|
||||
evconnlistener_enable(struct evconnlistener *lev)
|
||||
{
|
||||
int r;
|
||||
LOCK(lev);
|
||||
lev->enabled = 1;
|
||||
if (lev->cb)
|
||||
r = lev->ops->enable(lev);
|
||||
else
|
||||
r = 0;
|
||||
UNLOCK(lev);
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
evconnlistener_disable(struct evconnlistener *lev)
|
||||
{
|
||||
int r;
|
||||
LOCK(lev);
|
||||
lev->enabled = 0;
|
||||
r = lev->ops->disable(lev);
|
||||
UNLOCK(lev);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
event_listener_enable(struct evconnlistener *lev)
|
||||
{
|
||||
struct evconnlistener_event *lev_e =
|
||||
EVUTIL_UPCAST(lev, struct evconnlistener_event, base);
|
||||
return event_add(&lev_e->listener, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
event_listener_disable(struct evconnlistener *lev)
|
||||
{
|
||||
struct evconnlistener_event *lev_e =
|
||||
EVUTIL_UPCAST(lev, struct evconnlistener_event, base);
|
||||
return event_del(&lev_e->listener);
|
||||
}
|
||||
|
||||
evutil_socket_t
|
||||
evconnlistener_get_fd(struct evconnlistener *lev)
|
||||
{
|
||||
evutil_socket_t fd;
|
||||
LOCK(lev);
|
||||
fd = lev->ops->getfd(lev);
|
||||
UNLOCK(lev);
|
||||
return fd;
|
||||
}
|
||||
|
||||
static evutil_socket_t
|
||||
event_listener_getfd(struct evconnlistener *lev)
|
||||
{
|
||||
struct evconnlistener_event *lev_e =
|
||||
EVUTIL_UPCAST(lev, struct evconnlistener_event, base);
|
||||
return event_get_fd(&lev_e->listener);
|
||||
}
|
||||
|
||||
struct event_base *
|
||||
evconnlistener_get_base(struct evconnlistener *lev)
|
||||
{
|
||||
struct event_base *base;
|
||||
LOCK(lev);
|
||||
base = lev->ops->getbase(lev);
|
||||
UNLOCK(lev);
|
||||
return base;
|
||||
}
|
||||
|
||||
static struct event_base *
|
||||
event_listener_getbase(struct evconnlistener *lev)
|
||||
{
|
||||
struct evconnlistener_event *lev_e =
|
||||
EVUTIL_UPCAST(lev, struct evconnlistener_event, base);
|
||||
return event_get_base(&lev_e->listener);
|
||||
}
|
||||
|
||||
void
|
||||
evconnlistener_set_cb(struct evconnlistener *lev,
|
||||
evconnlistener_cb cb, void *arg)
|
||||
{
|
||||
int enable = 0;
|
||||
LOCK(lev);
|
||||
if (lev->enabled && !lev->cb)
|
||||
enable = 1;
|
||||
lev->cb = cb;
|
||||
lev->user_data = arg;
|
||||
if (enable)
|
||||
evconnlistener_enable(lev);
|
||||
UNLOCK(lev);
|
||||
}
|
||||
|
||||
void
|
||||
evconnlistener_set_error_cb(struct evconnlistener *lev,
|
||||
evconnlistener_errorcb errorcb)
|
||||
{
|
||||
LOCK(lev);
|
||||
lev->errorcb = errorcb;
|
||||
UNLOCK(lev);
|
||||
}
|
||||
|
||||
static void
|
||||
listener_read_cb(evutil_socket_t fd, short what, void *p)
|
||||
{
|
||||
struct evconnlistener *lev = p;
|
||||
int err;
|
||||
evconnlistener_cb cb;
|
||||
evconnlistener_errorcb errorcb;
|
||||
void *user_data;
|
||||
LOCK(lev);
|
||||
while (1) {
|
||||
struct sockaddr_storage ss;
|
||||
#ifdef WIN32
|
||||
int socklen = sizeof(ss);
|
||||
#else
|
||||
socklen_t socklen = sizeof(ss);
|
||||
#endif
|
||||
evutil_socket_t new_fd = accept(fd, (struct sockaddr*)&ss, &socklen);
|
||||
if (new_fd < 0)
|
||||
break;
|
||||
if (socklen == 0) {
|
||||
/* This can happen with some older linux kernels in
|
||||
* response to nmap. */
|
||||
evutil_closesocket(new_fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(lev->flags & LEV_OPT_LEAVE_SOCKETS_BLOCKING))
|
||||
evutil_make_socket_nonblocking(new_fd);
|
||||
|
||||
if (lev->cb == NULL) {
|
||||
UNLOCK(lev);
|
||||
return;
|
||||
}
|
||||
++lev->refcnt;
|
||||
cb = lev->cb;
|
||||
user_data = lev->user_data;
|
||||
UNLOCK(lev);
|
||||
cb(lev, new_fd, (struct sockaddr*)&ss, (int)socklen,
|
||||
user_data);
|
||||
LOCK(lev);
|
||||
if (lev->refcnt == 1) {
|
||||
int freed = listener_decref_and_unlock(lev);
|
||||
EVUTIL_ASSERT(freed);
|
||||
return;
|
||||
}
|
||||
--lev->refcnt;
|
||||
}
|
||||
err = evutil_socket_geterror(fd);
|
||||
if (EVUTIL_ERR_ACCEPT_RETRIABLE(err)) {
|
||||
UNLOCK(lev);
|
||||
return;
|
||||
}
|
||||
if (lev->errorcb != NULL) {
|
||||
++lev->refcnt;
|
||||
errorcb = lev->errorcb;
|
||||
user_data = lev->user_data;
|
||||
UNLOCK(lev);
|
||||
errorcb(lev, user_data);
|
||||
LOCK(lev);
|
||||
listener_decref_and_unlock(lev);
|
||||
} else {
|
||||
event_sock_warn(fd, "Error from accept() call");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
struct accepting_socket {
|
||||
CRITICAL_SECTION lock;
|
||||
struct event_overlapped overlapped;
|
||||
SOCKET s;
|
||||
int error;
|
||||
struct deferred_cb deferred;
|
||||
struct evconnlistener_iocp *lev;
|
||||
ev_uint8_t buflen;
|
||||
ev_uint8_t family;
|
||||
unsigned free_on_cb:1;
|
||||
char addrbuf[1];
|
||||
};
|
||||
|
||||
static void accepted_socket_cb(struct event_overlapped *o, ev_uintptr_t key,
|
||||
ev_ssize_t n, int ok);
|
||||
static void accepted_socket_invoke_user_cb(struct deferred_cb *cb, void *arg);
|
||||
|
||||
static void
|
||||
iocp_listener_event_add(struct evconnlistener_iocp *lev)
|
||||
{
|
||||
if (lev->event_added)
|
||||
return;
|
||||
|
||||
lev->event_added = 1;
|
||||
event_base_add_virtual(lev->event_base);
|
||||
}
|
||||
|
||||
static void
|
||||
iocp_listener_event_del(struct evconnlistener_iocp *lev)
|
||||
{
|
||||
if (!lev->event_added)
|
||||
return;
|
||||
|
||||
lev->event_added = 0;
|
||||
event_base_del_virtual(lev->event_base);
|
||||
}
|
||||
|
||||
static struct accepting_socket *
|
||||
new_accepting_socket(struct evconnlistener_iocp *lev, int family)
|
||||
{
|
||||
struct accepting_socket *res;
|
||||
int addrlen;
|
||||
int buflen;
|
||||
|
||||
if (family == AF_INET)
|
||||
addrlen = sizeof(struct sockaddr_in);
|
||||
else if (family == AF_INET6)
|
||||
addrlen = sizeof(struct sockaddr_in6);
|
||||
else
|
||||
return NULL;
|
||||
buflen = (addrlen+16)*2;
|
||||
|
||||
res = mm_calloc(1,sizeof(struct accepting_socket)-1+buflen);
|
||||
if (!res)
|
||||
return NULL;
|
||||
|
||||
event_overlapped_init(&res->overlapped, accepted_socket_cb);
|
||||
res->s = INVALID_SOCKET;
|
||||
res->lev = lev;
|
||||
res->buflen = buflen;
|
||||
res->family = family;
|
||||
|
||||
event_deferred_cb_init(&res->deferred,
|
||||
accepted_socket_invoke_user_cb, res);
|
||||
|
||||
InitializeCriticalSectionAndSpinCount(&res->lock, 1000);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
free_and_unlock_accepting_socket(struct accepting_socket *as)
|
||||
{
|
||||
/* requires lock. */
|
||||
if (as->s != INVALID_SOCKET)
|
||||
closesocket(as->s);
|
||||
|
||||
LeaveCriticalSection(&as->lock);
|
||||
DeleteCriticalSection(&as->lock);
|
||||
mm_free(as);
|
||||
}
|
||||
|
||||
static int
|
||||
start_accepting(struct accepting_socket *as)
|
||||
{
|
||||
/* requires lock */
|
||||
const struct win32_extension_fns *ext = event_get_win32_extension_fns();
|
||||
DWORD pending = 0;
|
||||
SOCKET s = socket(as->family, SOCK_STREAM, 0);
|
||||
int error = 0;
|
||||
|
||||
if (!as->lev->base.enabled)
|
||||
return 0;
|
||||
|
||||
if (s == INVALID_SOCKET) {
|
||||
error = WSAGetLastError();
|
||||
goto report_err;
|
||||
}
|
||||
|
||||
/* XXXX It turns out we need to do this again later. Does this call
|
||||
* have any effect? */
|
||||
setsockopt(s, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
|
||||
(char *)&as->lev->fd, sizeof(&as->lev->fd));
|
||||
|
||||
if (!(as->lev->base.flags & LEV_OPT_LEAVE_SOCKETS_BLOCKING))
|
||||
evutil_make_socket_nonblocking(s);
|
||||
|
||||
if (event_iocp_port_associate(as->lev->port, s, 1) < 0) {
|
||||
closesocket(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
as->s = s;
|
||||
|
||||
if (ext->AcceptEx(as->lev->fd, s, as->addrbuf, 0,
|
||||
as->buflen/2, as->buflen/2, &pending, &as->overlapped.overlapped))
|
||||
{
|
||||
/* Immediate success! */
|
||||
accepted_socket_cb(&as->overlapped, 1, 0, 1);
|
||||
} else {
|
||||
error = WSAGetLastError();
|
||||
if (error != ERROR_IO_PENDING) {
|
||||
goto report_err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
report_err:
|
||||
as->error = error;
|
||||
event_deferred_cb_schedule(
|
||||
event_base_get_deferred_cb_queue(as->lev->event_base),
|
||||
&as->deferred);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
stop_accepting(struct accepting_socket *as)
|
||||
{
|
||||
/* requires lock. */
|
||||
SOCKET s = as->s;
|
||||
as->s = INVALID_SOCKET;
|
||||
closesocket(s);
|
||||
}
|
||||
|
||||
static void
|
||||
accepted_socket_invoke_user_cb(struct deferred_cb *dcb, void *arg)
|
||||
{
|
||||
struct accepting_socket *as = arg;
|
||||
|
||||
struct sockaddr *sa_local=NULL, *sa_remote=NULL;
|
||||
int socklen_local=0, socklen_remote=0;
|
||||
const struct win32_extension_fns *ext = event_get_win32_extension_fns();
|
||||
struct evconnlistener *lev = &as->lev->base;
|
||||
evutil_socket_t sock=-1;
|
||||
void *data;
|
||||
evconnlistener_cb cb=NULL;
|
||||
evconnlistener_errorcb errorcb=NULL;
|
||||
int error;
|
||||
|
||||
EVUTIL_ASSERT(ext->GetAcceptExSockaddrs);
|
||||
|
||||
LOCK(lev);
|
||||
EnterCriticalSection(&as->lock);
|
||||
if (as->free_on_cb) {
|
||||
free_and_unlock_accepting_socket(as);
|
||||
listener_decref_and_unlock(lev);
|
||||
return;
|
||||
}
|
||||
|
||||
++lev->refcnt;
|
||||
|
||||
error = as->error;
|
||||
if (error) {
|
||||
as->error = 0;
|
||||
errorcb = lev->errorcb;
|
||||
} else {
|
||||
ext->GetAcceptExSockaddrs(
|
||||
as->addrbuf, 0, as->buflen/2, as->buflen/2,
|
||||
&sa_local, &socklen_local, &sa_remote,
|
||||
&socklen_remote);
|
||||
sock = as->s;
|
||||
cb = lev->cb;
|
||||
as->s = INVALID_SOCKET;
|
||||
|
||||
/* We need to call this so getsockname, getpeername, and
|
||||
* shutdown work correctly on the accepted socket. */
|
||||
/* XXXX handle error? */
|
||||
setsockopt(sock, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
|
||||
(char *)&as->lev->fd, sizeof(&as->lev->fd));
|
||||
}
|
||||
data = lev->user_data;
|
||||
|
||||
LeaveCriticalSection(&as->lock);
|
||||
UNLOCK(lev);
|
||||
|
||||
if (errorcb) {
|
||||
WSASetLastError(error);
|
||||
errorcb(lev, data);
|
||||
} else if (cb) {
|
||||
cb(lev, sock, sa_remote, socklen_remote, data);
|
||||
}
|
||||
|
||||
LOCK(lev);
|
||||
if (listener_decref_and_unlock(lev))
|
||||
return;
|
||||
|
||||
EnterCriticalSection(&as->lock);
|
||||
start_accepting(as);
|
||||
LeaveCriticalSection(&as->lock);
|
||||
}
|
||||
|
||||
static void
|
||||
accepted_socket_cb(struct event_overlapped *o, ev_uintptr_t key, ev_ssize_t n, int ok)
|
||||
{
|
||||
struct accepting_socket *as =
|
||||
EVUTIL_UPCAST(o, struct accepting_socket, overlapped);
|
||||
|
||||
LOCK(&as->lev->base);
|
||||
EnterCriticalSection(&as->lock);
|
||||
if (ok) {
|
||||
/* XXXX Don't do this if some EV_MT flag is set. */
|
||||
event_deferred_cb_schedule(
|
||||
event_base_get_deferred_cb_queue(as->lev->event_base),
|
||||
&as->deferred);
|
||||
LeaveCriticalSection(&as->lock);
|
||||
} else if (as->free_on_cb) {
|
||||
struct evconnlistener *lev = &as->lev->base;
|
||||
free_and_unlock_accepting_socket(as);
|
||||
listener_decref_and_unlock(lev);
|
||||
return;
|
||||
} else if (as->s == INVALID_SOCKET) {
|
||||
/* This is okay; we were disabled by iocp_listener_disable. */
|
||||
LeaveCriticalSection(&as->lock);
|
||||
} else {
|
||||
/* Some error on accept that we couldn't actually handle. */
|
||||
BOOL ok;
|
||||
DWORD transfer = 0, flags=0;
|
||||
event_sock_warn(as->s, "Unexpected error on AcceptEx");
|
||||
ok = WSAGetOverlappedResult(as->s, &o->overlapped,
|
||||
&transfer, FALSE, &flags);
|
||||
if (ok) {
|
||||
/* well, that was confusing! */
|
||||
as->error = 1;
|
||||
} else {
|
||||
as->error = WSAGetLastError();
|
||||
}
|
||||
event_deferred_cb_schedule(
|
||||
event_base_get_deferred_cb_queue(as->lev->event_base),
|
||||
&as->deferred);
|
||||
LeaveCriticalSection(&as->lock);
|
||||
}
|
||||
UNLOCK(&as->lev->base);
|
||||
}
|
||||
|
||||
static int
|
||||
iocp_listener_enable(struct evconnlistener *lev)
|
||||
{
|
||||
int i;
|
||||
struct evconnlistener_iocp *lev_iocp =
|
||||
EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base);
|
||||
|
||||
LOCK(lev);
|
||||
iocp_listener_event_add(lev_iocp);
|
||||
for (i = 0; i < lev_iocp->n_accepting; ++i) {
|
||||
struct accepting_socket *as = lev_iocp->accepting[i];
|
||||
if (!as)
|
||||
continue;
|
||||
EnterCriticalSection(&as->lock);
|
||||
if (!as->free_on_cb && as->s == INVALID_SOCKET)
|
||||
start_accepting(as);
|
||||
LeaveCriticalSection(&as->lock);
|
||||
}
|
||||
UNLOCK(lev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
iocp_listener_disable_impl(struct evconnlistener *lev, int shutdown)
|
||||
{
|
||||
int i;
|
||||
struct evconnlistener_iocp *lev_iocp =
|
||||
EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base);
|
||||
|
||||
LOCK(lev);
|
||||
iocp_listener_event_del(lev_iocp);
|
||||
for (i = 0; i < lev_iocp->n_accepting; ++i) {
|
||||
struct accepting_socket *as = lev_iocp->accepting[i];
|
||||
if (!as)
|
||||
continue;
|
||||
EnterCriticalSection(&as->lock);
|
||||
if (!as->free_on_cb && as->s != INVALID_SOCKET) {
|
||||
if (shutdown)
|
||||
as->free_on_cb = 1;
|
||||
stop_accepting(as);
|
||||
}
|
||||
LeaveCriticalSection(&as->lock);
|
||||
}
|
||||
|
||||
if (shutdown && lev->flags & LEV_OPT_CLOSE_ON_FREE)
|
||||
evutil_closesocket(lev_iocp->fd);
|
||||
|
||||
UNLOCK(lev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
iocp_listener_disable(struct evconnlistener *lev)
|
||||
{
|
||||
return iocp_listener_disable_impl(lev,0);
|
||||
}
|
||||
|
||||
static void
|
||||
iocp_listener_destroy(struct evconnlistener *lev)
|
||||
{
|
||||
struct evconnlistener_iocp *lev_iocp =
|
||||
EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base);
|
||||
|
||||
if (! lev_iocp->shutting_down) {
|
||||
lev_iocp->shutting_down = 1;
|
||||
iocp_listener_disable_impl(lev,1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static evutil_socket_t
|
||||
iocp_listener_getfd(struct evconnlistener *lev)
|
||||
{
|
||||
struct evconnlistener_iocp *lev_iocp =
|
||||
EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base);
|
||||
return lev_iocp->fd;
|
||||
}
|
||||
static struct event_base *
|
||||
iocp_listener_getbase(struct evconnlistener *lev)
|
||||
{
|
||||
struct evconnlistener_iocp *lev_iocp =
|
||||
EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base);
|
||||
return lev_iocp->event_base;
|
||||
}
|
||||
|
||||
static const struct evconnlistener_ops evconnlistener_iocp_ops = {
|
||||
iocp_listener_enable,
|
||||
iocp_listener_disable,
|
||||
iocp_listener_destroy,
|
||||
iocp_listener_destroy, /* shutdown */
|
||||
iocp_listener_getfd,
|
||||
iocp_listener_getbase
|
||||
};
|
||||
|
||||
/* XXX define some way to override this. */
|
||||
#define N_SOCKETS_PER_LISTENER 4
|
||||
|
||||
struct evconnlistener *
|
||||
evconnlistener_new_async(struct event_base *base,
|
||||
evconnlistener_cb cb, void *ptr, unsigned flags, int backlog,
|
||||
evutil_socket_t fd)
|
||||
{
|
||||
struct sockaddr_storage ss;
|
||||
int socklen = sizeof(ss);
|
||||
struct evconnlistener_iocp *lev;
|
||||
int i;
|
||||
|
||||
flags |= LEV_OPT_THREADSAFE;
|
||||
|
||||
if (!base || !event_base_get_iocp(base))
|
||||
goto err;
|
||||
|
||||
/* XXXX duplicate code */
|
||||
if (backlog > 0) {
|
||||
if (listen(fd, backlog) < 0)
|
||||
goto err;
|
||||
} else if (backlog < 0) {
|
||||
if (listen(fd, 128) < 0)
|
||||
goto err;
|
||||
}
|
||||
if (getsockname(fd, (struct sockaddr*)&ss, &socklen)) {
|
||||
event_sock_warn(fd, "getsockname");
|
||||
goto err;
|
||||
}
|
||||
lev = mm_calloc(1, sizeof(struct evconnlistener_iocp));
|
||||
if (!lev) {
|
||||
event_warn("calloc");
|
||||
goto err;
|
||||
}
|
||||
lev->base.ops = &evconnlistener_iocp_ops;
|
||||
lev->base.cb = cb;
|
||||
lev->base.user_data = ptr;
|
||||
lev->base.flags = flags;
|
||||
lev->base.refcnt = 1;
|
||||
lev->base.enabled = 1;
|
||||
|
||||
lev->port = event_base_get_iocp(base);
|
||||
lev->fd = fd;
|
||||
lev->event_base = base;
|
||||
|
||||
|
||||
if (event_iocp_port_associate(lev->port, fd, 1) < 0)
|
||||
goto err_free_lev;
|
||||
|
||||
EVTHREAD_ALLOC_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE);
|
||||
|
||||
lev->n_accepting = N_SOCKETS_PER_LISTENER;
|
||||
lev->accepting = mm_calloc(lev->n_accepting,
|
||||
sizeof(struct accepting_socket *));
|
||||
if (!lev->accepting) {
|
||||
event_warn("calloc");
|
||||
goto err_delete_lock;
|
||||
}
|
||||
for (i = 0; i < lev->n_accepting; ++i) {
|
||||
lev->accepting[i] = new_accepting_socket(lev, ss.ss_family);
|
||||
if (!lev->accepting[i]) {
|
||||
event_warnx("Couldn't create accepting socket");
|
||||
goto err_free_accepting;
|
||||
}
|
||||
if (cb && start_accepting(lev->accepting[i]) < 0) {
|
||||
event_warnx("Couldn't start accepting on socket");
|
||||
EnterCriticalSection(&lev->accepting[i]->lock);
|
||||
free_and_unlock_accepting_socket(lev->accepting[i]);
|
||||
goto err_free_accepting;
|
||||
}
|
||||
++lev->base.refcnt;
|
||||
}
|
||||
|
||||
iocp_listener_event_add(lev);
|
||||
|
||||
return &lev->base;
|
||||
|
||||
err_free_accepting:
|
||||
mm_free(lev->accepting);
|
||||
/* XXXX free the other elements. */
|
||||
err_delete_lock:
|
||||
EVTHREAD_FREE_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE);
|
||||
err_free_lev:
|
||||
mm_free(lev);
|
||||
err:
|
||||
/* Don't close the fd, it is caller's responsibility. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue