spiped-1.6.4/000755 001751 001751 00000000000 14773265560 014461 5ustar00cpercivacperciva000000 000000 spiped-1.6.4/spiped/000755 001751 001751 00000000000 14773265560 015745 5ustar00cpercivacperciva000000 000000 spiped-1.6.4/COPYRIGHT000644 001751 001751 00000003407 14745205620 015746 0ustar00cpercivacperciva000000 000000 The code in the "libcperciva/external" directory is distributed under the terms specified in each file. The included code and documentation ("spiped") is distributed under the following terms: Copyright 2005-2025 Colin Percival. All rights reserved. Copyright 2011-2025 Tarsnap Backup Inc. All rights reserved. Copyright 2014 Sean Kelly. 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. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. In addition to the above, some files are: Copyright 2012 Andreas Olsson Copyright 2016 Tim Duesterhus and distributed under the same terms. Such files contain individual copyright statements and licenses. spiped-1.6.4/DESIGN.md000644 001751 001751 00000011520 13042745752 015745 0ustar00cpercivacperciva000000 000000 spiped design ============= Encrypted protocol ------------------ The client and server share a key file with 256 or more bits of entropy. On launch, they read the key file and compute K = SHA256(key file). When a connection is established: - C1. The client generates a 256-bit random value nonce_C and sends it. S1. The server generates a 256-bit random value nonce_S and sends it. - C2. The client receives a 256-bit value nonce_S. S2. The server receives a 256-bit value nonce_C. - C3/S3. Both parties now compute the 512-bit value dk_1 = PBKDF2-SHA256(K, nonce_C || nonce_S, 1) and parse it as a pair of 256-bit values dhmac_C || dhmac_S = dk_1. - C4. The client picks* a value x_C and computes** y_C = 2^x_C mod p, where p is the Diffie-Hellman "group #14" modulus, and h_C = HMAC-SHA256(dhmac_C, y_C). The client sends y_C || h_C to the server. S4. The server receives a 2304-bit value which it parses as y_C || h_C, where y_C is 2048 bits and h_C is 256 bits; and drops the connection if h_C is not equal to HMAC-SHA256(dhmac_C, y_C) or y_C >= p. - S5. The server picks\* a value x_S and computes\*\* y_S = 2^x_S mod p and h_S = HMAC-SHA256(dhmac_S, y_S). The server sends y_S || h_S to the client. C5. The client receives a 2304-bit value which it parses as y_S || h_S, where y_S is 2048 bits and h_S is 256 bits; and drops the connection if h_S is not equal to HMAC-SHA256(dhmac_S, y_S) or y_S >= p. - C6. The client computes\*\* y_SC = y_S^x_C mod p. S6. The server computes\*\* y_SC = y_C^x_S mod p. (Note that these two compute values are identical.) - C7/S7. Both parties now compute the 1024-bit value dk_2 = PBKDF2-SHA256(K, nonce_C || nonce_S || y_SC, 1) and parse it as a 4-tuple of 256-bit values E_C || H_C || E_S || H_S. Thereafter, the client and server exchange 1060-byte packets P generated from plaintext messages M of 1--1024 bytes msg_padded = M || ( 0x00 x (1024 - length(M))) || bigendian32(length(M)) msg_encrypted = AES256-CTR(E, msg_padded, packet#) P = msg_encrypted || HMAC-SHA256(H, msg_encrypted || bigendian64(packet#)) where E and H are E_C and H_C or E_S and H_S depending on whether the packet is being sent by the client or the server, and AES256-CTR is computed with nonce equal to the packet #, which starts at zero and increments for each packet sent in the same direction. \* The values x_C, x_S picked must either be 0 (if perfect forward secrecy is not desired) or have 256 bits of entropy (if perfect forward secrecy is desired). \*\* The values y_C, y_S, and y_SC are 2048 bits and big-endian. Security proof -------------- 1. Under the random oracle model, K has at least 255 bits of entropy (it's a 256-bit hash computed from a value with at least 256 bits of entropy). 2. Provided that at least one party is following the protocol and the key file has been used for fewer than 2^64 connections, the probability that the tuple (K, nonce_C, nonce_S) has occurred before is less than 2^(-192). 3. Under the random oracle model, the probability of an attacker without access to K guessing either of dhmac_C and dhmac_S is less than P(attacker guesses K) + P(the tuple has been input to the oracle before) + P(the attacker directly guesses), which is less than 2^(-255) + 2^(-192) + 2^(-255) = 2^(-192) + 2^(-254). 4. Consequently, in order for an attacker to convince a protocol-obeying party that a tuple (y, h) is legitimate, the attacker must do at least 2^190 expected work (which we consider to be computationally infeasible and do not consider any further). 5. If one of the parties opts to not have perfect forward secrecy, then the value y_SC will be equal to 1 and dk_2 will have the same security properties as dk_1, i.e., it will be computationally infeasible for an attacker without access to K to compute dk_2. 6. If both parties opt for perfect forward secrecy, an attacker who can compute y_SC has solved a Diffie-Hellman problem over the 2048-bit group #14, which is (under the CDH assumption) computationally infeasible. 7. Consequently, if both parties opt for perfect forward secrecy, an attacker who obtains access to K after the handshake has completed will continue to be unable to compute dk_2 from information exchanged during the handshake. 8. Under the random oracle model, the packets P are indistinguishable from random 1060-byte packets; thus no information about the keys used or the plaintext being transmitted is revealed by post-key-exchange communications. 9. Because the values (msg_encrypted || bigendian(packet#)) are distinct for each packet, under the random oracle model it is infeasible for an attacker without access to the value H to generate a packet which will be accepted as valid. spiped-1.6.4/README.md000644 001751 001751 00000007056 13561473171 015741 0ustar00cpercivacperciva000000 000000 spiped ====== Official signed releases are published at: > https://www.tarsnap.com/spiped.html **`spiped`** (pronounced "ess-pipe-dee") is a utility for creating symmetrically encrypted and authenticated pipes between socket addresses, so that one may connect to one address (e.g., a UNIX socket on localhost) and transparently have a connection established to another address (e.g., a UNIX socket on a different system). This is similar to `ssh -L` functionality, but does not use SSH and requires a pre-shared symmetric key. **`spipe`** (pronounced "ess-pipe") is a utility which acts as an spiped protocol client (i.e., connects to an spiped daemon), taking input from the standard input and writing data read back to the standard output. Note that spiped: 1. Requires a strong key file: The file specified via the `-k` option should have at least 256 bits of entropy. (`dd if=/dev/urandom bs=32 count=1` is your friend.) 2. Requires strong entropy from `/dev/urandom`. (Make sure your kernel's random number generator is seeded at boot time!) 3. Does not provide any protection against information leakage via packet timing: Running telnet over spiped will protect a password from being directly read from the network, but will not obscure the typing rhythm. 4. Can significantly increase bandwidth usage for interactive sessions: It sends data in packets of 1024 bytes, and pads smaller messages up to this length, so a 1 byte write could be expanded to 1024 bytes if it cannot be coalesced with adjacent bytes. 5. Uses a symmetric key -- so anyone who can connect to an spiped "server" is also able to impersonate it. Example usage ------------- Examples of spiped protecting SMTP and SSH are given on: > https://www.tarsnap.com/spiped.html For a detailed list of the command-line options to spiped and spipe, see the man pages. Security requirements --------------------- The user is responsible for ensuring that: 1. The key file contains 256 or more bits of entropy. 2. The same key file is not used for more than 2^64 connections. 3. Any individual connection does not transmit more than 2^64 bytes. Building -------- The official releases should build and install on almost any POSIX-compliant operating system, using the included Makefiles: make BINDIR=/path/to/target/directory install See the [BUILDING](BUILDING) file for more details (e.g. how to install man pages). Testing ------- A small test suite can be run with: make test Memory-testing with valgrind (takes approximately twice as long as without valgrind) can be enabled with: make test USE_VALGRIND=1 Code layout ----------- ``` spiped/* -- Code specific to the spiped utility. main.c -- Command-line parsing, initialization, and event loop. dispatch.c -- Accepts connections and hands them off to protocol code. spipe/* -- Code specific to the spipe utility. main.c -- Command-line parsing, initialization, and event loop. pushbits.c -- Copies data between standard input/output and a socket. proto/* -- Implements the spiped protocol. _conn.c -- Manages the lifecycle of a connection. _handshake.c -- Performs the handshaking portion of the protocol. _pipe.c -- Performs the data-shuttling portion of the protocol. _crypt.c -- Does the cryptographic bits needed by _handshake and _pipe. lib/dnsthread -- Spawns a thread for background DNS (re)resolution. libcperciva/* -- Library code from libcperciva ``` More info --------- For more details about spiped, read the [DESIGN.md](DESIGN.md) file. spiped-1.6.4/CHANGELOG000644 001751 001751 00000006665 14770676363 015714 0ustar00cpercivacperciva000000 000000 spiped-1.6.4 * Fixes a bug which can cause spiped to abort if a RST packet arrives from one side of a pipe at the same time as a FIN packet arrives from the other end. spiped-1.6.3 * Add -b (spiped and spipe) to bind the outgoing address. spiped-1.6.2 * Warn if the maximum number of connections is reached in spiped. * Add --syslog (spiped) to send warnings to syslog when daemonized. * Significantly improve performance of AES-CTR and SHA256 on amd64 and aarch64. * Add ability to suppress POSIX runtime checks during compilation to simplify cross-compiling. spiped-1.6.1 * New option -u username:groupname (spiped): change the user and/or group ownership of the process. * Use RDRAND as an additional source of entropy on CPUs which support it. * Use SHANI instructions on CPUs which support them. * Warn about failed connections and exit with non-zero status (spipe). spiped-1.6.0 * The -n option (spiped) is no longer limited to a maximum limit of 500 simultaneous connections. * The -k option now accepts "-" as a synonym for standard input. * New option -v (spipe/spiped): Print version number. * Add workaround for docker signal-handling bug in spiped. * Perform a graceful shutdown on SIGTERM. spiped-1.5.0 * Attempt to set the TCP_NODELAY socket option on connections, in order to avoid punishing latencies from TCP nagling. spiped-1.4.2 * Fix crash on platforms which support AESNI (i386, amd64) but do not automatically provide 16-byte alignment to large memory allocations (glibc, possibly others). spiped-1.4.1 * Fix build on OS X, and improve strict POSIX compliance. * Improved zeroing of sensitive cryptographic data. spiped-1.4.0 * Add automatic detection of compiler support (at compile-time) and CPU support (at run-time) for x86 "AES New Instructions"; and when available, use these to improve cryptographic performance. * Add support for -g option, which makes {spiped, spipe} require perfect forward secrecy by dropping connections if the peer endpoint is detected to be running using the -f option. spiped-1.3.1 * Fix build by adding missing #include. * Minor code cleanups. spiped-1.3.0 * Bug fix: spiped now correctly closes connections which have been reset; in earlier versions spiped could erroneously hold "dead" connections open as long as they remained idle. * Man pages added. * Protocol-layer keep-alives are now enabled by default. * New option -j (spipe/spiped): Disable protocol-layer keep-alives. * In spiped the target address is now re-resolved every 60 seconds by default. * New option -R (spiped): Do not re-resolve target address. * New option -r (spiped): Re-resolve target address every seconds. spiped-1.2.2 * Build fixes for some strictly POSIX-conforming platforms. * Detect and work around compilers which are POSIX-noncompliant in their handling of -rt and -lxnet options. * Minor documentation and typo fixes. spiped-1.2.1 * Fix build by adding missing #include. spiped-1.2.0 * New utility "spipe": A client for the spiped protocol, handling a single connection with standard input/output as one end. * Code rearrangement with no functional consequences. * Minor bug and documentation fixes. spiped-1.1.0 * New option -D: Wait until DNS lookups succeed. * New option -F: Don't daemonize. * Use SO_REUSEADDR to avoid 'socket address already in use' error (most importantly, if spiped is killed and restarted). * Minor bug and style fixes. spiped-1.0.0 * Initial release spiped-1.6.4/spipe/000755 001751 001751 00000000000 14773265560 015601 5ustar00cpercivacperciva000000 000000 spiped-1.6.4/tests/000755 001751 001751 00000000000 14743020337 015607 5ustar00cpercivacperciva000000 000000 spiped-1.6.4/BUILDING000644 001751 001751 00000006447 13723620112 015572 0ustar00cpercivacperciva000000 000000 Installing ---------- To build and install spiped, run: # make BINDIR=/path/to/target/directory install To install man pages, add MAN1DIR=/path/to/man.1/directory to the command line (e.g., MAN1DIR=/usr/local/man/man1 on FreeBSD). Spiped should build and run on any IEEE Std 1003.1 (POSIX) compliant system which 1. Includes the Software Development Utilities option, 2. Has OpenSSL available via -lcrypto and #include , and 3. Provides /dev/urandom. Platform-specific notes ----------------------- - On OS X, the version of OpenSSL included with the operating system is outdated (0.9.8) and deprecated, and it is recommended that spiped be built with an updated version of OpenSSL. On OS X 10.11 "El Capitan", OpenSSL was removed entirely. After installing a newer version of OpenSSL, use CFLAGS="-I /path/to/openssl/headers" LDADD_EXTRA="-L /path/to/openssl/lib" to build spiped. Note that spiped will still build (on pre-10.11) if you set these options wrong: If you see warning: 'AES_set_encrypt_key' is deprecated during the build then spiped is still using the outdated version of OpenSSL from OS X. - On Cygwin the following command must be run before building spiped in order order to work around a bug in Cygwin's C library: sed -i.orig s/-D_POSIX_C_SOURCE=200809L// */Makefile Without this command, spiped will still build but it will crash. - On some platforms (Solaris, maybe others), additional compiler and/or linker options are required to find OpenSSL or system libraries; these can be provided by adding e.g., CFLAGS="-I/path/to/openssl/headers" (compiler option) or LDADD_EXTRA="-L/usr/sfw/lib -lsocket -lnsl" (linker option) to the make command line. - On Solaris, the command-line utilities in /usr/bin are not necessarily POSIX-compatible. According to standards(7), in order to use POSIX.1-2008 standard-conforming utilities, you must set your PATH so that certain directories (such as /usr/xpg4/bin/) take precedence over /usr/bin. Please check the documentation in your version of Solaris by: $ man standards and carefully read the "Utilities" section. - On some platforms (OpenBSD prior to 5.4, and possibly others) you will need to add #include at the start of lib/dnsthread/dnsthread.c libcperciva/util/sock_util.c proto/proto_conn.c spipe/main.c spipe/pushbits.c due to a POSIX-compliance bug on those platforms. - On some platforms (mostly Linuxes) it is possible to install OpenSSL libraries without the associated header files; the header files are usually in packages named "openssl-devel", "libssl-dev", or similar. - If your OS provides random bytes via some mechanism other than /dev/urandom, please make local changes to lib/util/entropy.c and notify the author. If spiped fails to build or run for other reasons, please notify the author. Updating build code and releasing --------------------------------- The POSIX-compatible Makefiles are generated via `make Makefiles` from the included (far more readable) BSD Makefiles. To run this target, you will need to have a BSD `make(1)` utility; NetBSD's `make(1)` is available for many operating systems as `bmake`. Release tarballs are generated via `make VERSION=x.y.z publish`, subject to the same caveat of needing a BSD-compatible make. spiped-1.6.4/perftests/000755 001751 001751 00000000000 13762775424 016502 5ustar00cpercivacperciva000000 000000 spiped-1.6.4/lib/000755 001751 001751 00000000000 14070374447 015222 5ustar00cpercivacperciva000000 000000 spiped-1.6.4/STYLE000644 001751 001751 00000015575 14650270210 015277 0ustar00cpercivacperciva000000 000000 Code style ========== In general, FreeBSD style(9) should be followed unless it is irrelevant (e.g., $FreeBSD$ tags). Functions with external linkage are declared like this: /** * module_func(arg1, arg2): * Description of what the function does, referring to arguments as * ${arg1} or suchlike. */ int module_func(void *, int); The identical comment appears in the C file where the function is defined. Static functions may have the above form of comment, or simply a /* Brief description of what the function does. */ line before the function. "Unrewrappable" comments starting in the first column should be /** * Written like this. * * Because (some of) the line-breaks are important. */ whereas when such comments are indented, they should be /*- * Written like this. * * Because (some of) the line-breaks are important. */ Line lengths should generally be 78 characters, and not more than 80 characters. In general, functions should return (int)(-1) or NULL to indicate error. Errors should be printed via warnp (if errno is relevant) or warn0 (if errno is not relevant) when they are first detected and also at higher levels where useful. As an exception to this, malloc failures (i.e., errno = ENOMEM) can result in failure being passed back up the call chain without being printed immediately. (Naturally, other errors can be passed back where a function definition so specifies; e.g., ENOENT in cases where a file not existing is not erroneous.) The first statement in main(), after variable declarations, should be "WARNP_INIT;" in order to set the program name used for printing warnings. We use %d rather than %i in printf and warn0/warnp strings. In general, functions should be structured with one return statement per status, e.g., one return() for success and one return() for failure. Errors should be handled by using goto to enter the error return path, e.g., int foo(int bar) { if (something fails) goto err0; /* ... */ if (something else fails) goto err1; /* ... */ if (yet another operation fails) goto err2; /* Success! */ return (0); err2: /* Clean up something. */ err1: /* Clean up something else. */ err0: /* Failure! */ return (-1); } As an exception to the above, if there is only one way for the function to fail, the idioms return (baz(bar)); and int rc; rc = baz(bar); /* ... cleanup code here ... */ return (rc); are allowed; furthermore, in cases such as foo_free(), the idiom if (we shouldn't do anything) return; is preferred over if (we shouldn't do anything) goto done; at the start of a function. Headers should be included in the following groups, with a blank line after each (non-empty) group: 1. , with first followed by others alphabetically. 2. , in alphabetical order. 3. <*.h>, in alphabetical order. 4. header files from /lib/, in alphabetical order. 5. header files from the program being built, in alphabetical order. 6. header files (usually just one) defining the interface for this C file. If ssize_t is needed, should be included to provide it. If size_t is needed, should be included to provide it unless , , , or is already required. If the C99 integer types (uint8_t, int64_t, etc.) are required, should be included to provide them unless is already required. The type 'char' should only be used to represent human-readable characters (input from users, output to users, pathnames, et cetera). The type 'char *' should normally be a NUL-terminated string. The types 'signed char' and 'unsigned char' should never be used; C99 integer types should be used instead. When a variable is declared to have a pointer type, there should be a space between the '*' and the variable name, e.g., int main(int argc, char * argv[]) { char * opt_p = NULL; Note that this is inconsistent with FreeBSD style(9). When used as a unary operator, '*' is not separated from its argument, e.g., while (*p != '\0') p++; When a struct is referenced, the idiom /* Opaque types. */ struct foo; struct bar * bar_from_foo(struct foo *); is preferable to #include "foo.h" /* needed for struct foo */ struct bar * bar_from_foo(struct foo *); unless there is some reason why the internal layout of struct foo is needed (e.g., if struct bar contains a struct foo rather than a struct foo *). Such struct declarations should be sorted alphabetically. The file foo.c should only export symbols of the following forms: foo_* -- most symbols should be of this form. FOO_* / BAR_FOO_* -- allowed in cases where FOO or BAR_FOO is idiomatic (e.g., MD5, HMAC_SHA256). foo() / defoo() / unfoo() -- where "foo" is a verb and this improves code clarity. Functions named foo_free should return void, and foo_free(NULL) should have no effect. The right way to spell a comment about this is /* Behave consistently with free(NULL). */ If static variables need to be initialized to 0 (or NULL) then they should be explicitly declared that way; implicit initialization should not be used. In non-trivial code, comments should be included which describe in English what is being done by the surrounding code with sufficient detail that if the code were removed, it could be replaced based on reading the comments without requiring any significant creativity. Comments and documentation should be written in en-GB-oed; i.e., with the 'u' included in words such as "honour", "colour", and "neighbour", and the ending '-ize' in words such as "organize" and "realize". The Oxford (aka. serial) comma should be used in lists. Quotation marks should be placed logically, i.e., not including punctuation marks which do not form a logical part of the quoted text. Two spaces should be used after a period which ends a sentence. The first local variable declaration in cookie-using functions should be struct foo * bar = cookie; When versions of functions are written to exploit special CPU features (using the cpusupport framework), that code should be placed into a separate file (e.g., crypto_aes_aesni.c) so that it can be compiled with different compiler flags. Such a file should start with #include "cpusupport.h" #ifdef CPUSUPPORT_FOO_BAR /** * CPUSUPPORT CFLAGS: FOO_BAR FOO_BAZ */ and end with #endif /* CPUSUPPORT_FOO_BAR */ For example, we could have #if defined(CPUSUPPORT_X86_SHANI) && defined(CPUSUPPORT_X86_SSSE3) /** * CPUSUPPORT CFLAGS: X86_SHANI X86_SSSE3 */ Functions for which special CPU-feature-exploiting variants exist should take the form { /* Variable declarations here. */ /* Asserts here, if any. */ #ifdef CPUSUPPORT_FOO_BAR if (/* We've decided we can use the variant code */) { /* Call variant code and return. */ } #endif /* Normal implementation of the function. */ } If there are multiple CPU-feature-exploiting variants, the `if` could instead be a `switch` which invokes the appropriate variant function. spiped-1.6.4/libcperciva/000755 001751 001751 00000000000 14650270210 016722 5ustar00cpercivacperciva000000 000000 spiped-1.6.4/Makefile000644 001751 001751 00000007062 14650270210 016104 0ustar00cpercivacperciva000000 000000 .POSIX: PROGS= spipe \ spiped LIBS= liball \ liball/optional_mutex_normal \ liball/optional_mutex_pthread TESTS= perftests/recv-zeros \ perftests/send-zeros \ perftests/standalone-enc \ tests/dnsthread-resolve \ tests/msleep \ tests/nc-client \ tests/nc-server \ tests/pthread_create_blocking_np \ tests/pushbits \ tests/valgrind BINDIR_DEFAULT= /usr/local/bin CFLAGS_DEFAULT= -O2 LIBCPERCIVA_DIR= libcperciva TEST_CMD= tests/test_spiped.sh ### Shared code between Tarsnap projects. .PHONY: all all: toplevel export CFLAGS="$${CFLAGS:-${CFLAGS_DEFAULT}}"; \ . ./posix-flags.sh; \ . ./cpusupport-config.h; \ . ./cflags-filter.sh; \ . ./apisupport-config.h; \ export HAVE_BUILD_FLAGS=1; \ for D in ${PROGS} ${TESTS}; do \ ( cd $${D} && ${MAKE} all ) || exit 2; \ done .PHONY: toplevel toplevel: apisupport-config.h cflags-filter.sh \ cpusupport-config.h libs \ posix-flags.sh # For "loop-back" building of a subdirectory .PHONY: buildsubdir buildsubdir: toplevel export CFLAGS="$${CFLAGS:-${CFLAGS_DEFAULT}}"; \ . ./posix-flags.sh; \ . ./cpusupport-config.h; \ . ./cflags-filter.sh; \ . ./apisupport-config.h; \ export HAVE_BUILD_FLAGS=1; \ cd ${BUILD_SUBDIR} && ${MAKE} ${BUILD_TARGET} # For "loop-back" building of libraries .PHONY: libs libs: apisupport-config.h cflags-filter.sh cpusupport-config.h posix-flags.sh export CFLAGS="$${CFLAGS:-${CFLAGS_DEFAULT}}"; \ . ./posix-flags.sh; \ . ./cpusupport-config.h; \ . ./cflags-filter.sh; \ . ./apisupport-config.h; \ export HAVE_BUILD_FLAGS=1; \ for D in ${LIBS}; do \ ( cd $${D} && make all ) || exit 2; \ done posix-flags.sh: if [ -d ${LIBCPERCIVA_DIR}/POSIX/ ]; then \ export CC="${CC}"; \ cd ${LIBCPERCIVA_DIR}/POSIX; \ printf "export \"LDADD_POSIX="; \ command -p sh posix-l.sh "$$PATH"; \ printf "\"\n"; \ printf "export \"CFLAGS_POSIX="; \ command -p sh posix-cflags.sh "$$PATH"; \ printf "\"\n"; \ fi > $@ if [ ! -s $@ ]; then \ printf "#define POSIX_COMPATIBILITY_NOT_CHECKED 1\n"; \ fi >> $@ cflags-filter.sh: if [ -d ${LIBCPERCIVA_DIR}/POSIX/ ]; then \ export CC="${CC}"; \ cd ${LIBCPERCIVA_DIR}/POSIX; \ command -p sh posix-cflags-filter.sh "$$PATH"; \ fi > $@ if [ ! -s $@ ]; then \ printf "# Compiler understands normal flags; "; \ printf "nothing to filter out\n"; \ fi >> $@ apisupport-config.h: if [ -d ${LIBCPERCIVA_DIR}/apisupport/ ]; then \ export CC="${CC}"; \ command -p sh \ ${LIBCPERCIVA_DIR}/apisupport/Build/apisupport.sh \ "$$PATH"; \ else \ :; \ fi > $@ cpusupport-config.h: if [ -d ${LIBCPERCIVA_DIR}/cpusupport/ ]; then \ export CC="${CC}"; \ command -p sh \ ${LIBCPERCIVA_DIR}/cpusupport/Build/cpusupport.sh \ "$$PATH"; \ fi > $@ if [ ! -s $@ ]; then \ printf "#define CPUSUPPORT_NONE 1\n"; \ fi >> $@ .PHONY: install install: all export BINDIR=$${BINDIR:-${BINDIR_DEFAULT}}; \ for D in ${PROGS}; do \ ( cd $${D} && ${MAKE} install ) || exit 2; \ done .PHONY: clean clean: test-clean rm -f apisupport-config.h cflags-filter.sh cpusupport-config.h posix-flags.sh for D in ${LIBS} ${PROGS} ${TESTS}; do \ ( cd $${D} && ${MAKE} clean ) || exit 2; \ done .PHONY: test test: all ${TEST_CMD} .PHONY: test-clean test-clean: rm -rf tests-output/ tests-valgrind/ # Developer targets: These only work with BSD make .PHONY: Makefiles Makefiles: ${MAKE} -f Makefile.BSD Makefiles .PHONY: publish publish: ${MAKE} -f Makefile.BSD publish spiped-1.6.4/liball/000755 001751 001751 00000000000 14773265543 015721 5ustar00cpercivacperciva000000 000000 spiped-1.6.4/liball/optional_mutex_normal/000755 001751 001751 00000000000 14773265543 022340 5ustar00cpercivacperciva000000 000000 spiped-1.6.4/liball/Makefile000644 001751 001751 00000064316 14773265555 017376 0ustar00cpercivacperciva000000 000000 .POSIX: # AUTOGENERATED FILE, DO NOT EDIT LIB=liball.a SRCS=sha256.c sha256_arm.c sha256_shani.c sha256_sse2.c cpusupport_arm_aes.c cpusupport_arm_sha256.c cpusupport_x86_aesni.c cpusupport_x86_rdrand.c cpusupport_x86_shani.c cpusupport_x86_sse2.c cpusupport_x86_ssse3.c crypto_aes.c crypto_aes_aesni.c crypto_aes_arm.c crypto_aesctr.c crypto_aesctr_aesni.c crypto_aesctr_arm.c crypto_dh.c crypto_dh_group14.c crypto_entropy.c crypto_entropy_rdrand.c crypto_verify_bytes.c elasticarray.c ptrheap.c timerqueue.c events.c events_immediate.c events_network.c events_network_selectstats.c events_timer.c netbuf_read.c network_accept.c network_connect.c network_read.c network_write.c asprintf.c daemonize.c entropy.c fork_func.c getopt.c insecure_memzero.c ipc_sync.c monoclock.c noeintr.c perftest.c setgroups_none.c setuidgid.c sock.c sock_util.c warnp.c dnsthread.c proto_conn.c proto_crypt.c proto_handshake.c proto_pipe.c graceful_shutdown.c pthread_create_blocking_np.c IDIRS=-I../libcperciva/alg -I../libcperciva/cpusupport -I../libcperciva/crypto -I../libcperciva/datastruct -I../libcperciva/events -I../libcperciva/netbuf -I../libcperciva/network -I../libcperciva/util -I../libcperciva/external/queue -I../lib/dnsthread -I../lib/proto -I../lib/util SUBDIR_DEPTH=.. RELATIVE_DIR=liball all: if [ -z "$${HAVE_BUILD_FLAGS}" ]; then \ cd ${SUBDIR_DEPTH}; \ ${MAKE} BUILD_SUBDIR=${RELATIVE_DIR} \ BUILD_TARGET=${PROG} buildsubdir; \ else \ ${MAKE} ${LIB}; \ fi clean: rm -f ${LIB} ${SRCS:.c=.o} ${LIB}:${SRCS:.c=.o} ${AR} ${ARFLAGS} ${LIB} ${SRCS:.c=.o} sha256.o: ../libcperciva/alg/sha256.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/util/insecure_memzero.h ../libcperciva/alg/sha256_arm.h ../libcperciva/alg/sha256_shani.h ../libcperciva/alg/sha256_sse2.h ../libcperciva/util/sysendian.h ../libcperciva/util/warnp.h ../libcperciva/alg/sha256.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/alg/sha256.c -o sha256.o sha256_arm.o: ../libcperciva/alg/sha256_arm.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/alg/sha256_arm.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} ${CFLAGS_ARM_SHA256} -c ../libcperciva/alg/sha256_arm.c -o sha256_arm.o sha256_shani.o: ../libcperciva/alg/sha256_shani.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/alg/sha256_shani.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} ${CFLAGS_X86_SHANI} ${CFLAGS_X86_SSSE3} -c ../libcperciva/alg/sha256_shani.c -o sha256_shani.o sha256_sse2.o: ../libcperciva/alg/sha256_sse2.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/alg/sha256_sse2.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} ${CFLAGS_X86_SSE2} -c ../libcperciva/alg/sha256_sse2.c -o sha256_sse2.o cpusupport_arm_aes.o: ../libcperciva/cpusupport/cpusupport_arm_aes.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/cpusupport/cpusupport_arm_aes.c -o cpusupport_arm_aes.o cpusupport_arm_sha256.o: ../libcperciva/cpusupport/cpusupport_arm_sha256.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/cpusupport/cpusupport_arm_sha256.c -o cpusupport_arm_sha256.o cpusupport_x86_aesni.o: ../libcperciva/cpusupport/cpusupport_x86_aesni.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/cpusupport/cpusupport_x86_aesni.c -o cpusupport_x86_aesni.o cpusupport_x86_rdrand.o: ../libcperciva/cpusupport/cpusupport_x86_rdrand.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/cpusupport/cpusupport_x86_rdrand.c -o cpusupport_x86_rdrand.o cpusupport_x86_shani.o: ../libcperciva/cpusupport/cpusupport_x86_shani.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/cpusupport/cpusupport_x86_shani.c -o cpusupport_x86_shani.o cpusupport_x86_sse2.o: ../libcperciva/cpusupport/cpusupport_x86_sse2.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/cpusupport/cpusupport_x86_sse2.c -o cpusupport_x86_sse2.o cpusupport_x86_ssse3.o: ../libcperciva/cpusupport/cpusupport_x86_ssse3.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/cpusupport/cpusupport_x86_ssse3.c -o cpusupport_x86_ssse3.o crypto_aes.o: ../libcperciva/crypto/crypto_aes.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/crypto/crypto_aes_aesni.h ../libcperciva/crypto/crypto_aes_arm.h ../libcperciva/util/insecure_memzero.h ../libcperciva/util/warnp.h ../libcperciva/crypto/crypto_aes.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} ${CFLAGS_LIBCRYPTO_LOW_LEVEL_AES} -c ../libcperciva/crypto/crypto_aes.c -o crypto_aes.o crypto_aes_aesni.o: ../libcperciva/crypto/crypto_aes_aesni.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/util/align_ptr.h ../libcperciva/util/insecure_memzero.h ../libcperciva/util/warnp.h ../libcperciva/crypto/crypto_aes_aesni.h ../libcperciva/crypto/crypto_aes_aesni_m128i.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} ${CFLAGS_X86_AESNI} -c ../libcperciva/crypto/crypto_aes_aesni.c -o crypto_aes_aesni.o crypto_aes_arm.o: ../libcperciva/crypto/crypto_aes_arm.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/util/align_ptr.h ../libcperciva/util/insecure_memzero.h ../libcperciva/util/warnp.h ../libcperciva/crypto/crypto_aes_arm.h ../libcperciva/crypto/crypto_aes_arm_u8.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} ${CFLAGS_ARM_AES} -c ../libcperciva/crypto/crypto_aes_arm.c -o crypto_aes_arm.o crypto_aesctr.o: ../libcperciva/crypto/crypto_aesctr.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/crypto/crypto_aes.h ../libcperciva/crypto/crypto_aesctr_aesni.h ../libcperciva/crypto/crypto_aesctr_arm.h ../libcperciva/util/insecure_memzero.h ../libcperciva/util/sysendian.h ../libcperciva/crypto/crypto_aesctr.h ../libcperciva/crypto/crypto_aesctr_shared.c ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_aesctr.c -o crypto_aesctr.o crypto_aesctr_aesni.o: ../libcperciva/crypto/crypto_aesctr_aesni.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/crypto/crypto_aes.h ../libcperciva/crypto/crypto_aes_aesni_m128i.h ../libcperciva/util/sysendian.h ../libcperciva/crypto/crypto_aesctr_aesni.h ../libcperciva/crypto/crypto_aesctr_shared.c ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} ${CFLAGS_X86_AESNI} -c ../libcperciva/crypto/crypto_aesctr_aesni.c -o crypto_aesctr_aesni.o crypto_aesctr_arm.o: ../libcperciva/crypto/crypto_aesctr_arm.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/crypto/crypto_aes.h ../libcperciva/crypto/crypto_aes_arm_u8.h ../libcperciva/util/sysendian.h ../libcperciva/crypto/crypto_aesctr_arm.h ../libcperciva/crypto/crypto_aesctr_shared.c ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} ${CFLAGS_ARM_AES} -c ../libcperciva/crypto/crypto_aesctr_arm.c -o crypto_aesctr_arm.o crypto_dh.o: ../libcperciva/crypto/crypto_dh.c ../libcperciva/util/warnp.h ../libcperciva/crypto/crypto_dh_group14.h ../libcperciva/crypto/crypto_entropy.h ../libcperciva/crypto/crypto_dh.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_dh.c -o crypto_dh.o crypto_dh_group14.o: ../libcperciva/crypto/crypto_dh_group14.c ../libcperciva/crypto/crypto_dh_group14.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_dh_group14.c -o crypto_dh_group14.o crypto_entropy.o: ../libcperciva/crypto/crypto_entropy.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/crypto/crypto_entropy_rdrand.h ../libcperciva/util/entropy.h ../libcperciva/util/insecure_memzero.h ../libcperciva/alg/sha256.h ../libcperciva/crypto/crypto_entropy.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_entropy.c -o crypto_entropy.o crypto_entropy_rdrand.o: ../libcperciva/crypto/crypto_entropy_rdrand.c ../libcperciva/cpusupport/cpusupport.h ../cpusupport-config.h ../libcperciva/crypto/crypto_entropy_rdrand.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} ${CFLAGS_X86_RDRAND} -c ../libcperciva/crypto/crypto_entropy_rdrand.c -o crypto_entropy_rdrand.o crypto_verify_bytes.o: ../libcperciva/crypto/crypto_verify_bytes.c ../libcperciva/crypto/crypto_verify_bytes.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/crypto/crypto_verify_bytes.c -o crypto_verify_bytes.o elasticarray.o: ../libcperciva/datastruct/elasticarray.c ../libcperciva/datastruct/elasticarray.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/datastruct/elasticarray.c -o elasticarray.o ptrheap.o: ../libcperciva/datastruct/ptrheap.c ../libcperciva/datastruct/elasticarray.h ../libcperciva/datastruct/ptrheap.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/datastruct/ptrheap.c -o ptrheap.o timerqueue.o: ../libcperciva/datastruct/timerqueue.c ../libcperciva/datastruct/ptrheap.h ../libcperciva/datastruct/timerqueue.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/datastruct/timerqueue.c -o timerqueue.o events.o: ../libcperciva/events/events.c ../libcperciva/datastruct/mpool.h ../libcperciva/util/ctassert.h ../libcperciva/events/events.h ../libcperciva/events/events_internal.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/events/events.c -o events.o events_immediate.o: ../libcperciva/events/events_immediate.c ../libcperciva/datastruct/mpool.h ../libcperciva/util/ctassert.h ../libcperciva/external/queue/queue.h ../libcperciva/events/events.h ../libcperciva/events/events_internal.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/events/events_immediate.c -o events_immediate.o events_network.o: ../libcperciva/events/events_network.c ../libcperciva/util/ctassert.h ../libcperciva/datastruct/elasticarray.h ../libcperciva/util/warnp.h ../libcperciva/events/events.h ../libcperciva/events/events_internal.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/events/events_network.c -o events_network.o events_network_selectstats.o: ../libcperciva/events/events_network_selectstats.c ../libcperciva/util/monoclock.h ../libcperciva/events/events.h ../libcperciva/events/events_internal.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/events/events_network_selectstats.c -o events_network_selectstats.o events_timer.o: ../libcperciva/events/events_timer.c ../libcperciva/util/monoclock.h ../libcperciva/datastruct/timerqueue.h ../libcperciva/events/events.h ../libcperciva/events/events_internal.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/events/events_timer.c -o events_timer.o netbuf_read.o: ../libcperciva/netbuf/netbuf_read.c ../libcperciva/events/events.h ../libcperciva/network/network.h ../libcperciva/netbuf/netbuf.h ../libcperciva/netbuf/netbuf_ssl_internal.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/netbuf/netbuf_read.c -o netbuf_read.o network_accept.o: ../libcperciva/network/network_accept.c ../libcperciva/events/events.h ../libcperciva/network/network.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/network/network_accept.c -o network_accept.o network_connect.o: ../libcperciva/network/network_connect.c ../libcperciva/events/events.h ../libcperciva/util/sock.h ../libcperciva/util/warnp.h ../libcperciva/network/network.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/network/network_connect.c -o network_connect.o network_read.o: ../libcperciva/network/network_read.c ../libcperciva/events/events.h ../libcperciva/datastruct/mpool.h ../libcperciva/util/ctassert.h ../libcperciva/network/network.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/network/network_read.c -o network_read.o network_write.o: ../libcperciva/network/network_write.c ../libcperciva/events/events.h ../libcperciva/datastruct/mpool.h ../libcperciva/util/ctassert.h ../libcperciva/util/warnp.h ../libcperciva/network/network.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/network/network_write.c -o network_write.o asprintf.o: ../libcperciva/util/asprintf.c ../libcperciva/util/asprintf.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/asprintf.c -o asprintf.o daemonize.o: ../libcperciva/util/daemonize.c ../libcperciva/util/ipc_sync.h ../libcperciva/util/warnp.h ../libcperciva/util/daemonize.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/daemonize.c -o daemonize.o entropy.o: ../libcperciva/util/entropy.c ../libcperciva/util/warnp.h ../libcperciva/util/entropy.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/entropy.c -o entropy.o fork_func.o: ../libcperciva/util/fork_func.c ../libcperciva/util/warnp.h ../libcperciva/util/fork_func.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/fork_func.c -o fork_func.o getopt.o: ../libcperciva/util/getopt.c ../libcperciva/util/getopt.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/getopt.c -o getopt.o insecure_memzero.o: ../libcperciva/util/insecure_memzero.c ../libcperciva/util/insecure_memzero.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/insecure_memzero.c -o insecure_memzero.o ipc_sync.o: ../libcperciva/util/ipc_sync.c ../libcperciva/util/noeintr.h ../libcperciva/util/warnp.h ../libcperciva/util/ipc_sync.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/ipc_sync.c -o ipc_sync.o monoclock.o: ../libcperciva/util/monoclock.c ../libcperciva/util/warnp.h ../libcperciva/util/monoclock.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/monoclock.c -o monoclock.o noeintr.o: ../libcperciva/util/noeintr.c ../libcperciva/util/noeintr.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/noeintr.c -o noeintr.o perftest.o: ../libcperciva/util/perftest.c ../libcperciva/util/monoclock.h ../libcperciva/util/warnp.h ../libcperciva/util/perftest.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/perftest.c -o perftest.o setgroups_none.o: ../libcperciva/util/setgroups_none.c ../libcperciva/util/setgroups_none.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} ${CFLAGS_NONPOSIX_SETGROUPS} -c ../libcperciva/util/setgroups_none.c -o setgroups_none.o setuidgid.o: ../libcperciva/util/setuidgid.c ../libcperciva/util/parsenum.h ../libcperciva/util/setgroups_none.h ../libcperciva/util/warnp.h ../libcperciva/util/setuidgid.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/setuidgid.c -o setuidgid.o sock.o: ../libcperciva/util/sock.c ../libcperciva/util/imalloc.h ../libcperciva/util/parsenum.h ../libcperciva/util/warnp.h ../libcperciva/util/sock.h ../libcperciva/util/sock_internal.h ../libcperciva/util/sock_util.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/sock.c -o sock.o sock_util.o: ../libcperciva/util/sock_util.c ../libcperciva/util/asprintf.h ../libcperciva/util/sock.h ../libcperciva/util/warnp.h ../libcperciva/util/sock_internal.h ../libcperciva/util/sock_util.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/sock_util.c -o sock_util.o warnp.o: ../libcperciva/util/warnp.c ../libcperciva/util/warnp.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../libcperciva/util/warnp.c -o warnp.o dnsthread.o: ../lib/dnsthread/dnsthread.c ../libcperciva/events/events.h ../libcperciva/util/noeintr.h ../libcperciva/util/sock.h ../libcperciva/util/warnp.h ../lib/dnsthread/dnsthread.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../lib/dnsthread/dnsthread.c -o dnsthread.o proto_conn.o: ../lib/proto/proto_conn.c ../libcperciva/events/events.h ../libcperciva/network/network.h ../libcperciva/util/sock.h ../libcperciva/util/warnp.h ../lib/proto/proto_crypt.h ../libcperciva/crypto/crypto_dh.h ../lib/proto/proto_handshake.h ../lib/proto/proto_pipe.h ../lib/proto/proto_conn.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../lib/proto/proto_conn.c -o proto_conn.o proto_crypt.o: ../lib/proto/proto_crypt.c ../libcperciva/crypto/crypto_aes.h ../libcperciva/crypto/crypto_aesctr.h ../libcperciva/crypto/crypto_verify_bytes.h ../libcperciva/util/insecure_memzero.h ../libcperciva/alg/sha256.h ../libcperciva/util/sysendian.h ../libcperciva/util/warnp.h ../lib/proto/proto_crypt.h ../libcperciva/crypto/crypto_dh.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../lib/proto/proto_crypt.c -o proto_crypt.o proto_handshake.o: ../lib/proto/proto_handshake.c ../libcperciva/crypto/crypto_entropy.h ../libcperciva/network/network.h ../lib/proto/proto_crypt.h ../libcperciva/crypto/crypto_dh.h ../lib/proto/proto_handshake.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../lib/proto/proto_handshake.c -o proto_handshake.o proto_pipe.o: ../lib/proto/proto_pipe.c ../libcperciva/netbuf/netbuf.h ../libcperciva/network/network.h ../libcperciva/util/warnp.h ../lib/proto/proto_crypt.h ../libcperciva/crypto/crypto_dh.h ../lib/proto/proto_pipe.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../lib/proto/proto_pipe.c -o proto_pipe.o graceful_shutdown.o: ../lib/util/graceful_shutdown.c ../libcperciva/events/events.h ../libcperciva/util/warnp.h ../lib/util/graceful_shutdown.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../lib/util/graceful_shutdown.c -o graceful_shutdown.o pthread_create_blocking_np.o: ../lib/util/pthread_create_blocking_np.c ../lib/util/pthread_create_blocking_np.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -c ../lib/util/pthread_create_blocking_np.c -o pthread_create_blocking_np.o spiped-1.6.4/liball/optional_mutex_pthread/000755 001751 001751 00000000000 14773265543 022477 5ustar00cpercivacperciva000000 000000 spiped-1.6.4/liball/optional_mutex_pthread/Makefile000644 001751 001751 00000001552 14773265556 024146 0ustar00cpercivacperciva000000 000000 .POSIX: # AUTOGENERATED FILE, DO NOT EDIT LIB=liball_optional_mutex_pthread.a SRCS=optional_mutex.c IDIRS=-I../../libcperciva/util SUBDIR_DEPTH=../.. RELATIVE_DIR=liball/optional_mutex_pthread all: if [ -z "$${HAVE_BUILD_FLAGS}" ]; then \ cd ${SUBDIR_DEPTH}; \ ${MAKE} BUILD_SUBDIR=${RELATIVE_DIR} \ BUILD_TARGET=${PROG} buildsubdir; \ else \ ${MAKE} ${LIB}; \ fi clean: rm -f ${LIB} ${SRCS:.c=.o} ${LIB}:${SRCS:.c=.o} ${AR} ${ARFLAGS} ${LIB} ${SRCS:.c=.o} optional_mutex.o: ../../libcperciva/util/optional_mutex.c ../../libcperciva/util/optional_mutex.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -DOPTIONAL_MUTEX_PTHREAD_YES -c ../../libcperciva/util/optional_mutex.c -o optional_mutex.o spiped-1.6.4/liball/optional_mutex_normal/Makefile000644 001751 001751 00000001547 14773265556 024013 0ustar00cpercivacperciva000000 000000 .POSIX: # AUTOGENERATED FILE, DO NOT EDIT LIB=liball_optional_mutex_normal.a SRCS=optional_mutex.c IDIRS=-I../../libcperciva/util SUBDIR_DEPTH=../.. RELATIVE_DIR=liball/optional_mutex_normal all: if [ -z "$${HAVE_BUILD_FLAGS}" ]; then \ cd ${SUBDIR_DEPTH}; \ ${MAKE} BUILD_SUBDIR=${RELATIVE_DIR} \ BUILD_TARGET=${PROG} buildsubdir; \ else \ ${MAKE} ${LIB}; \ fi clean: rm -f ${LIB} ${SRCS:.c=.o} ${LIB}:${SRCS:.c=.o} ${AR} ${ARFLAGS} ${LIB} ${SRCS:.c=.o} optional_mutex.o: ../../libcperciva/util/optional_mutex.c ../../libcperciva/util/optional_mutex.h ${CC} ${CFLAGS_POSIX} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I../.. ${IDIRS} ${CPPFLAGS} ${CFLAGS} -DOPTIONAL_MUTEX_PTHREAD_NO -c ../../libcperciva/util/optional_mutex.c -o optional_mutex.o spiped-1.6.4/libcperciva/crypto/000755 001751 001751 00000000000 14650270210 020242 5ustar00cpercivacperciva000000 000000 spiped-1.6.4/libcperciva/alg/000755 001751 001751 00000000000 14743020337 017473 5ustar00cpercivacperciva000000 000000 spiped-1.6.4/libcperciva/util/000755 001751 001751 00000000000 14770676363 017725 5ustar00cpercivacperciva000000 000000 spiped-1.6.4/libcperciva/events/000755 001751 001751 00000000000 14650270210 020226 5ustar00cpercivacperciva000000 000000 spiped-1.6.4/libcperciva/network/000755 001751 001751 00000000000 14650270210 020413 5ustar00cpercivacperciva000000 000000 spiped-1.6.4/libcperciva/POSIX/000755 001751 001751 00000000000 14773265536 017651 5ustar00cpercivacperciva000000 000000 spiped-1.6.4/libcperciva/cpusupport/000755 001751 001751 00000000000 14743020337 021154 5ustar00cpercivacperciva000000 000000 spiped-1.6.4/libcperciva/datastruct/000755 001751 001751 00000000000 14743020337 021106 5ustar00cpercivacperciva000000 000000 spiped-1.6.4/libcperciva/apisupport/000755 001751 001751 00000000000 14650270210 021130 5ustar00cpercivacperciva000000 000000 spiped-1.6.4/libcperciva/external/000755 001751 001751 00000000000 14650270210 020544 5ustar00cpercivacperciva000000 000000 spiped-1.6.4/libcperciva/netbuf/000755 001751 001751 00000000000 14743020337 020213 5ustar00cpercivacperciva000000 000000 spiped-1.6.4/libcperciva/netbuf/netbuf_ssl_internal.h000644 001751 001751 00000002264 14650270210 024422 0ustar00cpercivacperciva000000 000000 #ifndef NETBUF_SSL_H_ #define NETBUF_SSL_H_ #include #include /* Opaque type. */ struct network_ssl_ctx; /* * Function pointers defined in netbuf_read and netbuf_write; we set them * from our _init functions in order to avoid unnecessary linkage. */ extern void * (* netbuf_read_ssl_func)(struct network_ssl_ctx *, uint8_t *, size_t, size_t, int (*)(void *, ssize_t), void *); extern void (* netbuf_read_ssl_cancel_func)(void *); extern void * (* netbuf_write_ssl_func)(struct network_ssl_ctx *, const uint8_t *, size_t, size_t, int (*)(void *, ssize_t), void *); extern void (* netbuf_write_ssl_cancel_func)(void *); /** * netbuf_read_init2(s, ssl): * Behave like netbuf_read_init() if ${ssl} is NULL. If the SSL context * ${ssl} is not NULL, use it and ignore ${s}. */ struct netbuf_read * netbuf_read_init2(int, struct network_ssl_ctx *); /** * netbuf_write_init2(s, ssl, fail_callback, fail_cookie): * Behave like netbuf_write_init() if ${ssl} is NULL. If the SSL context * ${ssl} is not NULL, use it and ignore ${s}. */ struct netbuf_write * netbuf_write_init2(int, struct network_ssl_ctx *, int (*)(void *), void *); #endif /* !NETBUF_SSL_H_ */ spiped-1.6.4/libcperciva/netbuf/netbuf_read.c000644 001751 001751 00000016277 14743020337 022652 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include #include #include "events.h" #include "network.h" #include "netbuf.h" #include "netbuf_ssl_internal.h" /* * Set to NULL here; initialized by netbuf_ssl if SSL is being used. This * allows us to avoid needing to link libssl into binaries which aren't * going to be using SSL. */ void * (* netbuf_read_ssl_func)(struct network_ssl_ctx *, uint8_t *, size_t, size_t, int (*)(void *, ssize_t), void *) = NULL; void (* netbuf_read_ssl_cancel_func)(void *) = NULL; /* Buffered reader structure. */ struct netbuf_read { /* Reader state. */ int s; /* Source socket for reads... */ struct network_ssl_ctx * ssl; /* ... unless we're using this. */ int (* callback)(void *, int); /* Callback for _wait. */ void * cookie; /* Cookie for _wait. */ void * read_cookie; /* From network_read. */ void * immediate_cookie; /* From events_immediate_register. */ /* Buffer state. */ uint8_t * buf; /* Current read buffer. */ size_t buflen; /* Length of buf. */ size_t bufpos; /* Position of read pointer in buf. */ size_t datalen; /* Position of write pointer in buf. */ }; static int callback_success(void *); static int callback_read(void *, ssize_t); /** * netbuf_read_init(s): * Create and return a buffered reader attached to socket ${s}. The caller * is responsible for ensuring that no attempts are made to read from said * socket except via the returned reader. */ struct netbuf_read * netbuf_read_init(int s) { /* Call the real function (without SSL). */ return (netbuf_read_init2(s, NULL)); } /** * netbuf_read_init2(s, ssl): * Behave like netbuf_read_init() if ${ssl} is NULL. If the SSL context * ${ssl} is not NULL, use it and ignore ${s}. */ struct netbuf_read * netbuf_read_init2(int s, struct network_ssl_ctx * ssl) { struct netbuf_read * R; /* Bake a cookie. */ if ((R = malloc(sizeof(struct netbuf_read))) == NULL) goto err0; R->s = s; R->ssl = ssl; R->read_cookie = NULL; R->immediate_cookie = NULL; /* Allocate buffer. */ R->buflen = 4096; if ((R->buf = malloc(R->buflen)) == NULL) goto err1; R->bufpos = 0; R->datalen = 0; /* Success! */ return (R); err1: free(R); err0: /* Failure! */ return (NULL); } /** * netbuf_read_peek(R, data, datalen): * Set ${data} to point to the currently buffered data in the reader ${R}; set * ${datalen} to the number of bytes buffered. */ void netbuf_read_peek(struct netbuf_read * R, uint8_t ** data, size_t * datalen) { /* Point at current buffered data. */ *data = &R->buf[R->bufpos]; *datalen = R->datalen - R->bufpos; } /* Ensure that ${R} can store at least ${len} bytes. */ static int netbuf_read_resize_buffer(struct netbuf_read * R, size_t len) { uint8_t * nbuf; size_t nbuflen; /* Compute new buffer size. */ nbuflen = R->buflen * 2; if (nbuflen < len) nbuflen = len; /* Allocate new buffer. */ if ((nbuf = malloc(nbuflen)) == NULL) goto err0; /* Copy data into new buffer. */ memcpy(nbuf, &R->buf[R->bufpos], R->datalen - R->bufpos); /* Free old buffer and use new buffer. */ free(R->buf); R->buf = nbuf; R->buflen = nbuflen; R->datalen -= R->bufpos; R->bufpos = 0; /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * netbuf_read_wait(R, len, callback, cookie): * Wait until ${R} has ${len} or more bytes of data buffered or an error * occurs; then invoke ${callback}(${cookie}, status) with status set to 0 * if the data is available, -1 on error, or 1 on EOF. */ int netbuf_read_wait(struct netbuf_read * R, size_t len, int (* callback)(void *, int), void * cookie) { /* Sanity-check: We shouldn't be reading already. */ assert(R->read_cookie == NULL); assert(R->immediate_cookie == NULL); /* Record parameters for future reference. */ R->callback = callback; R->cookie = cookie; /* If we have enough data already, schedule a callback. */ if (R->datalen - R->bufpos >= len) { if ((R->immediate_cookie = events_immediate_register(callback_success, R, 0)) == NULL) goto err0; else goto done; } /* Resize the buffer if needed. */ if ((R->buflen < len) && netbuf_read_resize_buffer(R, len)) goto err0; /* Move data to start of buffer if needed. */ if (R->buflen - R->bufpos < len) { memmove(R->buf, &R->buf[R->bufpos], R->datalen - R->bufpos); R->datalen -= R->bufpos; R->bufpos = 0; } /* Read data into the buffer. */ if (R->ssl) { if ((R->read_cookie = (netbuf_read_ssl_func)(R->ssl, &R->buf[R->datalen], R->buflen - R->datalen, R->bufpos + len - R->datalen, callback_read, R)) == NULL) goto err0; } else { if ((R->read_cookie = network_read(R->s, &R->buf[R->datalen], R->buflen - R->datalen, R->bufpos + len - R->datalen, callback_read, R)) == NULL) goto err0; } done: /* Success! */ return (0); err0: /* Failure! */ return (-1); } /* Perform immediate callback for netbuf_read_wait. */ static int callback_success(void * cookie) { struct netbuf_read * R = cookie; /* Sanity-check: We should be expecting this callback. */ assert(R->immediate_cookie != NULL); /* This callback is no longer pending. */ R->immediate_cookie = NULL; /* Perform callback. */ return ((R->callback)(R->cookie, 0)); } /* Callback for a completed network read. */ static int callback_read(void * cookie, ssize_t lenread) { struct netbuf_read * R = cookie; /* Sanity-check: We should be reading. */ assert(R->read_cookie != NULL); /* This callback is no longer pending. */ R->read_cookie = NULL; /* Did the read fail? */ if (lenread < 0) goto failed; /* Did we hit EOF? */ if (lenread == 0) goto eof; /* We've got more data. */ R->datalen += (size_t)lenread; /* Perform callback. */ return ((R->callback)(R->cookie, 0)); eof: /* Perform EOF callback. */ return ((R->callback)(R->cookie, 1)); failed: /* Perform failure callback. */ return ((R->callback)(R->cookie, -1)); } /** * netbuf_read_wait_cancel(R): * Cancel any in-progress wait on the reader ${R}. Do not invoke the callback * associated with the wait. */ void netbuf_read_wait_cancel(struct netbuf_read * R) { /* If we have an in-progress read, cancel it. */ if (R->read_cookie != NULL) { if (R->ssl) (netbuf_read_ssl_cancel_func)(R->read_cookie); else network_read_cancel(R->read_cookie); R->read_cookie = NULL; } /* If we have an immediate callback pending, cancel it. */ if (R->immediate_cookie != NULL) { events_immediate_cancel(R->immediate_cookie); R->immediate_cookie = NULL; } } /** * netbuf_read_consume(R, len): * Advance the reader pointer for the reader ${R} by ${len} bytes. */ void netbuf_read_consume(struct netbuf_read * R, size_t len) { /* Sanity-check: We can't consume data we don't have. */ assert(R->datalen - R->bufpos >= len); /* Advance the buffer pointer. */ R->bufpos += len; } /** * netbuf_read_free(R): * Free the reader ${R}. Note that an indeterminate amount of data may have * been buffered and will be lost. */ void netbuf_read_free(struct netbuf_read * R) { /* Behave consistently with free(NULL). */ if (R == NULL) return; /* Can't free a reader which is busy. */ assert(R->read_cookie == NULL); assert(R->immediate_cookie == NULL); /* Free the buffer and the reader. */ free(R->buf); free(R); } spiped-1.6.4/libcperciva/netbuf/netbuf.h000644 001751 001751 00000006560 14650270210 021650 0ustar00cpercivacperciva000000 000000 #ifndef NETBUF_H_ #define NETBUF_H_ #include #include /* Opaque types. */ struct network_ssl_ctx; struct netbuf_read; struct netbuf_write; /** * netbuf_read_init(s): * Create and return a buffered reader attached to socket ${s}. The caller * is responsible for ensuring that no attempts are made to read from said * socket except via the returned reader. */ struct netbuf_read * netbuf_read_init(int); /** * netbuf_read_peek(R, data, datalen): * Set ${data} to point to the currently buffered data in the reader ${R}; set * ${datalen} to the number of bytes buffered. */ void netbuf_read_peek(struct netbuf_read *, uint8_t **, size_t *); /** * netbuf_read_wait(R, len, callback, cookie): * Wait until ${R} has ${len} or more bytes of data buffered or an error * occurs; then invoke ${callback}(${cookie}, status) with status set to 0 * if the data is available, -1 on error, or 1 on EOF. */ int netbuf_read_wait(struct netbuf_read *, size_t, int (*)(void *, int), void *); /** * netbuf_read_wait_cancel(R): * Cancel any in-progress wait on the reader ${R}. Do not invoke the callback * associated with the wait. */ void netbuf_read_wait_cancel(struct netbuf_read *); /** * netbuf_read_consume(R, len): * Advance the reader pointer for the reader ${R} by ${len} bytes. */ void netbuf_read_consume(struct netbuf_read *, size_t); /** * netbuf_read_free(R): * Free the reader ${R}. Note that an indeterminate amount of data may have * been buffered and will be lost. */ void netbuf_read_free(struct netbuf_read *); /** * netbuf_write_init(s, fail_callback, fail_cookie): * Create and return a buffered writer attached to socket ${s}. The caller * is responsible for ensuring that no attempts are made to write to said * socket except via the returned writer until netbuf_write_free() is called. * If a write fails, ${fail_callback} will be invoked with the parameter * ${fail_cookie}. */ struct netbuf_write * netbuf_write_init(int, int (*)(void *), void *); /** * netbuf_write_reserve(W, len): * Reserve ${len} bytes of space in the buffered writer ${W} and return a * pointer to the buffer. This operation must be followed by a call to * netbuf_write_consume() before the next call to _reserve() or _write() and * before a callback could be made into netbuf_write() (i.e., before control * returns to the event loop). */ uint8_t * netbuf_write_reserve(struct netbuf_write *, size_t); /** * netbuf_write_consume(W, len): * Consume a reservation previously made by netbuf_write_reserve(); the value * ${len} must be <= the value passed to netbuf_write_reserve(). */ int netbuf_write_consume(struct netbuf_write *, size_t); /** * netbuf_write_write(W, buf, buflen): * Write ${buflen} bytes from the buffer ${buf} via the buffered writer ${W}. */ int netbuf_write_write(struct netbuf_write *, const uint8_t *, size_t); /** * netbuf_write_free(W): * Free the writer ${W}. */ void netbuf_write_free(struct netbuf_write *); /** * netbuf_ssl_read_init(ssl): * Behave as netbuf_read_init() but take an SSL context instead. */ struct netbuf_read * netbuf_ssl_read_init(struct network_ssl_ctx *); /** * netbuf_ssl_write_init(ssl, fail_callback, fail_cookie): * Behave as netbuf_write_init() but take an SSL context instead. */ struct netbuf_write * netbuf_ssl_write_init(struct network_ssl_ctx *, int (*)(void *), void *); #endif /* !NETBUF_H_ */ spiped-1.6.4/libcperciva/external/queue/000755 001751 001751 00000000000 14650270210 021670 5ustar00cpercivacperciva000000 000000 spiped-1.6.4/libcperciva/external/queue/queue.h000644 001751 001751 00000054776 14650270210 023210 0ustar00cpercivacperciva000000 000000 /* $NetBSD: queue.h,v 1.75.2.1 2021/04/03 22:29:03 thorpej Exp $ */ /* * Copyright (c) 1991, 1993 * The Regents of the University of California. 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. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. * * @(#)queue.h 8.5 (Berkeley) 8/20/94 */ #ifndef SYS_QUEUE_H_ #define SYS_QUEUE_H_ /* * This file defines five types of data structures: singly-linked lists, * lists, simple queues, tail queues, and circular queues. * * A singly-linked list is headed by a single forward pointer. The * elements are singly linked for minimum space and pointer manipulation * overhead at the expense of O(n) removal for arbitrary elements. New * elements can be added to the list after an existing element or at the * head of the list. Elements being removed from the head of the list * should use the explicit macro for this purpose for optimum * efficiency. A singly-linked list may only be traversed in the forward * direction. Singly-linked lists are ideal for applications with large * datasets and few or no removals or for implementing a LIFO queue. * * A list is headed by a single forward pointer (or an array of forward * pointers for a hash table header). The elements are doubly linked * so that an arbitrary element can be removed without a need to * traverse the list. New elements can be added to the list before * or after an existing element or at the head of the list. A list * may only be traversed in the forward direction. * * A simple queue is headed by a pair of pointers, one the head of the * list and the other to the tail of the list. The elements are singly * linked to save space, so elements can only be removed from the * head of the list. New elements can be added to the list after * an existing element, at the head of the list, or at the end of the * list. A simple queue may only be traversed in the forward direction. * * A tail queue is headed by a pair of pointers, one to the head of the * list and the other to the tail of the list. The elements are doubly * linked so that an arbitrary element can be removed without a need to * traverse the list. New elements can be added to the list before or * after an existing element, at the head of the list, or at the end of * the list. A tail queue may be traversed in either direction. * * For details on the use of these macros, see the queue(3) manual page. */ /* * Include the definition of NULL only on NetBSD because sys/null.h * is not available elsewhere. This conditional makes the header * portable and it can simply be dropped verbatim into any system. * The caveat is that on other systems some other header * must provide NULL before the macros can be used. */ #ifdef __NetBSD__ #include #endif #if defined(_KERNEL) && defined(DIAGNOSTIC) #define QUEUEDEBUG 1 #endif #if defined(QUEUEDEBUG) # if defined(_KERNEL) # define QUEUEDEBUG_ABORT(...) panic(__VA_ARGS__) # else # include # define QUEUEDEBUG_ABORT(...) err(1, __VA_ARGS__) # endif #endif /* * Singly-linked List definitions. */ #define SLIST_HEAD(name, type) \ struct name { \ struct type *slh_first; /* first element */ \ } #define SLIST_HEAD_INITIALIZER(head) \ { NULL } #define SLIST_ENTRY(type) \ struct { \ struct type *sle_next; /* next element */ \ } /* * Singly-linked List access methods. */ #define SLIST_FIRST(head) ((head)->slh_first) #define SLIST_END(head) NULL #define SLIST_EMPTY(head) ((head)->slh_first == NULL) #define SLIST_NEXT(elm, field) ((elm)->field.sle_next) #define SLIST_FOREACH(var, head, field) \ for((var) = (head)->slh_first; \ (var) != SLIST_END(head); \ (var) = (var)->field.sle_next) #define SLIST_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = SLIST_FIRST((head)); \ (var) != SLIST_END(head) && \ ((tvar) = SLIST_NEXT((var), field), 1); \ (var) = (tvar)) /* * Singly-linked List functions. */ #define SLIST_INIT(head) do { \ (head)->slh_first = SLIST_END(head); \ } while (/*CONSTCOND*/0) #define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ (elm)->field.sle_next = (slistelm)->field.sle_next; \ (slistelm)->field.sle_next = (elm); \ } while (/*CONSTCOND*/0) #define SLIST_INSERT_HEAD(head, elm, field) do { \ (elm)->field.sle_next = (head)->slh_first; \ (head)->slh_first = (elm); \ } while (/*CONSTCOND*/0) #define SLIST_REMOVE_AFTER(slistelm, field) do { \ (slistelm)->field.sle_next = \ SLIST_NEXT(SLIST_NEXT((slistelm), field), field); \ } while (/*CONSTCOND*/0) #define SLIST_REMOVE_HEAD(head, field) do { \ (head)->slh_first = (head)->slh_first->field.sle_next; \ } while (/*CONSTCOND*/0) #define SLIST_REMOVE(head, elm, type, field) do { \ if ((head)->slh_first == (elm)) { \ SLIST_REMOVE_HEAD((head), field); \ } \ else { \ struct type *curelm = (head)->slh_first; \ while(curelm->field.sle_next != (elm)) \ curelm = curelm->field.sle_next; \ curelm->field.sle_next = \ curelm->field.sle_next->field.sle_next; \ } \ } while (/*CONSTCOND*/0) /* * List definitions. */ #define LIST_HEAD(name, type) \ struct name { \ struct type *lh_first; /* first element */ \ } #define LIST_HEAD_INITIALIZER(head) \ { NULL } #define LIST_ENTRY(type) \ struct { \ struct type *le_next; /* next element */ \ struct type **le_prev; /* address of previous next element */ \ } /* * List access methods. */ #define LIST_FIRST(head) ((head)->lh_first) #define LIST_END(head) NULL #define LIST_EMPTY(head) ((head)->lh_first == LIST_END(head)) #define LIST_NEXT(elm, field) ((elm)->field.le_next) #define LIST_FOREACH(var, head, field) \ for ((var) = ((head)->lh_first); \ (var) != LIST_END(head); \ (var) = ((var)->field.le_next)) #define LIST_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = LIST_FIRST((head)); \ (var) != LIST_END(head) && \ ((tvar) = LIST_NEXT((var), field), 1); \ (var) = (tvar)) #define LIST_MOVE(head1, head2, field) do { \ LIST_INIT((head2)); \ if (!LIST_EMPTY((head1))) { \ (head2)->lh_first = (head1)->lh_first; \ (head2)->lh_first->field.le_prev = &(head2)->lh_first; \ LIST_INIT((head1)); \ } \ } while (/*CONSTCOND*/0) /* * List functions. */ #if defined(QUEUEDEBUG) #define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field) \ if ((head)->lh_first && \ (head)->lh_first->field.le_prev != &(head)->lh_first) \ QUEUEDEBUG_ABORT("LIST_INSERT_HEAD %p %s:%d", (head), \ __FILE__, __LINE__); #define QUEUEDEBUG_LIST_OP(elm, field) \ if ((elm)->field.le_next && \ (elm)->field.le_next->field.le_prev != \ &(elm)->field.le_next) \ QUEUEDEBUG_ABORT("LIST_* forw %p %s:%d", (elm), \ __FILE__, __LINE__); \ if (*(elm)->field.le_prev != (elm)) \ QUEUEDEBUG_ABORT("LIST_* back %p %s:%d", (elm), \ __FILE__, __LINE__); #define QUEUEDEBUG_LIST_POSTREMOVE(elm, field) \ (elm)->field.le_next = (void *)1L; \ (elm)->field.le_prev = (void *)1L; #else #define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field) #define QUEUEDEBUG_LIST_OP(elm, field) #define QUEUEDEBUG_LIST_POSTREMOVE(elm, field) #endif #define LIST_INIT(head) do { \ (head)->lh_first = LIST_END(head); \ } while (/*CONSTCOND*/0) #define LIST_INSERT_AFTER(listelm, elm, field) do { \ QUEUEDEBUG_LIST_OP((listelm), field) \ if (((elm)->field.le_next = (listelm)->field.le_next) != \ LIST_END(head)) \ (listelm)->field.le_next->field.le_prev = \ &(elm)->field.le_next; \ (listelm)->field.le_next = (elm); \ (elm)->field.le_prev = &(listelm)->field.le_next; \ } while (/*CONSTCOND*/0) #define LIST_INSERT_BEFORE(listelm, elm, field) do { \ QUEUEDEBUG_LIST_OP((listelm), field) \ (elm)->field.le_prev = (listelm)->field.le_prev; \ (elm)->field.le_next = (listelm); \ *(listelm)->field.le_prev = (elm); \ (listelm)->field.le_prev = &(elm)->field.le_next; \ } while (/*CONSTCOND*/0) #define LIST_INSERT_HEAD(head, elm, field) do { \ QUEUEDEBUG_LIST_INSERT_HEAD((head), (elm), field) \ if (((elm)->field.le_next = (head)->lh_first) != LIST_END(head))\ (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ (head)->lh_first = (elm); \ (elm)->field.le_prev = &(head)->lh_first; \ } while (/*CONSTCOND*/0) #define LIST_REMOVE(elm, field) do { \ QUEUEDEBUG_LIST_OP((elm), field) \ if ((elm)->field.le_next != NULL) \ (elm)->field.le_next->field.le_prev = \ (elm)->field.le_prev; \ *(elm)->field.le_prev = (elm)->field.le_next; \ QUEUEDEBUG_LIST_POSTREMOVE((elm), field) \ } while (/*CONSTCOND*/0) #define LIST_REPLACE(elm, elm2, field) do { \ if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ (elm2)->field.le_next->field.le_prev = \ &(elm2)->field.le_next; \ (elm2)->field.le_prev = (elm)->field.le_prev; \ *(elm2)->field.le_prev = (elm2); \ QUEUEDEBUG_LIST_POSTREMOVE((elm), field) \ } while (/*CONSTCOND*/0) /* * Simple queue definitions. */ #define SIMPLEQ_HEAD(name, type) \ struct name { \ struct type *sqh_first; /* first element */ \ struct type **sqh_last; /* addr of last next element */ \ } #define SIMPLEQ_HEAD_INITIALIZER(head) \ { NULL, &(head).sqh_first } #define SIMPLEQ_ENTRY(type) \ struct { \ struct type *sqe_next; /* next element */ \ } /* * Simple queue access methods. */ #define SIMPLEQ_FIRST(head) ((head)->sqh_first) #define SIMPLEQ_END(head) NULL #define SIMPLEQ_EMPTY(head) ((head)->sqh_first == SIMPLEQ_END(head)) #define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) #define SIMPLEQ_FOREACH(var, head, field) \ for ((var) = ((head)->sqh_first); \ (var) != SIMPLEQ_END(head); \ (var) = ((var)->field.sqe_next)) #define SIMPLEQ_FOREACH_SAFE(var, head, field, next) \ for ((var) = ((head)->sqh_first); \ (var) != SIMPLEQ_END(head) && \ ((next = ((var)->field.sqe_next)), 1); \ (var) = (next)) /* * Simple queue functions. */ #define SIMPLEQ_INIT(head) do { \ (head)->sqh_first = NULL; \ (head)->sqh_last = &(head)->sqh_first; \ } while (/*CONSTCOND*/0) #define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ (head)->sqh_last = &(elm)->field.sqe_next; \ (head)->sqh_first = (elm); \ } while (/*CONSTCOND*/0) #define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ (elm)->field.sqe_next = NULL; \ *(head)->sqh_last = (elm); \ (head)->sqh_last = &(elm)->field.sqe_next; \ } while (/*CONSTCOND*/0) #define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ (head)->sqh_last = &(elm)->field.sqe_next; \ (listelm)->field.sqe_next = (elm); \ } while (/*CONSTCOND*/0) #define SIMPLEQ_REMOVE_HEAD(head, field) do { \ if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ (head)->sqh_last = &(head)->sqh_first; \ } while (/*CONSTCOND*/0) #define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \ == NULL) \ (head)->sqh_last = &(elm)->field.sqe_next; \ } while (/*CONSTCOND*/0) #define SIMPLEQ_REMOVE(head, elm, type, field) do { \ if ((head)->sqh_first == (elm)) { \ SIMPLEQ_REMOVE_HEAD((head), field); \ } else { \ struct type *curelm = (head)->sqh_first; \ while (curelm->field.sqe_next != (elm)) \ curelm = curelm->field.sqe_next; \ if ((curelm->field.sqe_next = \ curelm->field.sqe_next->field.sqe_next) == NULL) \ (head)->sqh_last = &(curelm)->field.sqe_next; \ } \ } while (/*CONSTCOND*/0) #define SIMPLEQ_CONCAT(head1, head2) do { \ if (!SIMPLEQ_EMPTY((head2))) { \ *(head1)->sqh_last = (head2)->sqh_first; \ (head1)->sqh_last = (head2)->sqh_last; \ SIMPLEQ_INIT((head2)); \ } \ } while (/*CONSTCOND*/0) #define SIMPLEQ_LAST(head, type, field) \ (SIMPLEQ_EMPTY((head)) ? \ NULL : \ ((struct type *)(void *) \ ((char *)((head)->sqh_last) - offsetof(struct type, field)))) /* * Tail queue definitions. */ #define TAILQ_HEAD_(name, type, qual) \ struct name { \ qual type *tqh_first; /* first element */ \ qual type *qual *tqh_last; /* addr of last next element */ \ } #define TAILQ_HEAD(name, type) TAILQ_HEAD_(name, struct type,) #define TAILQ_HEAD_INITIALIZER(head) \ { TAILQ_END(head), &(head).tqh_first } #define TAILQ_ENTRY_(type, qual) \ struct { \ qual type *tqe_next; /* next element */ \ qual type *qual *tqe_prev; /* address of previous next element */\ } #define TAILQ_ENTRY(type) TAILQ_ENTRY_(struct type,) /* * Tail queue access methods. */ #define TAILQ_FIRST(head) ((head)->tqh_first) #define TAILQ_END(head) (NULL) #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) #define TAILQ_LAST(head, headname) \ (*(((struct headname *)(void *)((head)->tqh_last))->tqh_last)) #define TAILQ_PREV(elm, headname, field) \ (*(((struct headname *)(void *)((elm)->field.tqe_prev))->tqh_last)) #define TAILQ_EMPTY(head) (TAILQ_FIRST(head) == TAILQ_END(head)) #define TAILQ_FOREACH(var, head, field) \ for ((var) = ((head)->tqh_first); \ (var) != TAILQ_END(head); \ (var) = ((var)->field.tqe_next)) #define TAILQ_FOREACH_SAFE(var, head, field, next) \ for ((var) = ((head)->tqh_first); \ (var) != TAILQ_END(head) && \ ((next) = TAILQ_NEXT(var, field), 1); (var) = (next)) #define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ for ((var) = TAILQ_LAST((head), headname); \ (var) != TAILQ_END(head); \ (var) = TAILQ_PREV((var), headname, field)) #define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, prev) \ for ((var) = TAILQ_LAST((head), headname); \ (var) != TAILQ_END(head) && \ ((prev) = TAILQ_PREV((var), headname, field), 1); (var) = (prev)) /* * Tail queue functions. */ #if defined(QUEUEDEBUG) #define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field) \ if ((head)->tqh_first && \ (head)->tqh_first->field.tqe_prev != &(head)->tqh_first) \ QUEUEDEBUG_ABORT("TAILQ_INSERT_HEAD %p %s:%d", (head), \ __FILE__, __LINE__); #define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field) \ if (*(head)->tqh_last != NULL) \ QUEUEDEBUG_ABORT("TAILQ_INSERT_TAIL %p %s:%d", (head), \ __FILE__, __LINE__); #define QUEUEDEBUG_TAILQ_OP(elm, field) \ if ((elm)->field.tqe_next && \ (elm)->field.tqe_next->field.tqe_prev != \ &(elm)->field.tqe_next) \ QUEUEDEBUG_ABORT("TAILQ_* forw %p %s:%d", (elm), \ __FILE__, __LINE__); \ if (*(elm)->field.tqe_prev != (elm)) \ QUEUEDEBUG_ABORT("TAILQ_* back %p %s:%d", (elm), \ __FILE__, __LINE__); #define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field) \ if ((elm)->field.tqe_next == NULL && \ (head)->tqh_last != &(elm)->field.tqe_next) \ QUEUEDEBUG_ABORT("TAILQ_PREREMOVE head %p elm %p %s:%d",\ (head), (elm), __FILE__, __LINE__); #define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field) \ (elm)->field.tqe_next = (void *)1L; \ (elm)->field.tqe_prev = (void *)1L; #else #define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field) #define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field) #define QUEUEDEBUG_TAILQ_OP(elm, field) #define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field) #define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field) #endif #define TAILQ_INIT(head) do { \ (head)->tqh_first = TAILQ_END(head); \ (head)->tqh_last = &(head)->tqh_first; \ } while (/*CONSTCOND*/0) #define TAILQ_INSERT_HEAD(head, elm, field) do { \ QUEUEDEBUG_TAILQ_INSERT_HEAD((head), (elm), field) \ if (((elm)->field.tqe_next = (head)->tqh_first) != TAILQ_END(head))\ (head)->tqh_first->field.tqe_prev = \ &(elm)->field.tqe_next; \ else \ (head)->tqh_last = &(elm)->field.tqe_next; \ (head)->tqh_first = (elm); \ (elm)->field.tqe_prev = &(head)->tqh_first; \ } while (/*CONSTCOND*/0) #define TAILQ_INSERT_TAIL(head, elm, field) do { \ QUEUEDEBUG_TAILQ_INSERT_TAIL((head), (elm), field) \ (elm)->field.tqe_next = TAILQ_END(head); \ (elm)->field.tqe_prev = (head)->tqh_last; \ *(head)->tqh_last = (elm); \ (head)->tqh_last = &(elm)->field.tqe_next; \ } while (/*CONSTCOND*/0) #define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ QUEUEDEBUG_TAILQ_OP((listelm), field) \ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != \ TAILQ_END(head)) \ (elm)->field.tqe_next->field.tqe_prev = \ &(elm)->field.tqe_next; \ else \ (head)->tqh_last = &(elm)->field.tqe_next; \ (listelm)->field.tqe_next = (elm); \ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ } while (/*CONSTCOND*/0) #define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ QUEUEDEBUG_TAILQ_OP((listelm), field) \ (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) #define TAILQ_REMOVE(head, elm, field) do { \ QUEUEDEBUG_TAILQ_PREREMOVE((head), (elm), field) \ QUEUEDEBUG_TAILQ_OP((elm), field) \ if (((elm)->field.tqe_next) != TAILQ_END(head)) \ (elm)->field.tqe_next->field.tqe_prev = \ (elm)->field.tqe_prev; \ else \ (head)->tqh_last = (elm)->field.tqe_prev; \ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field); \ } while (/*CONSTCOND*/0) #define TAILQ_REPLACE(head, elm, elm2, field) do { \ if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != \ TAILQ_END(head)) \ (elm2)->field.tqe_next->field.tqe_prev = \ &(elm2)->field.tqe_next; \ else \ (head)->tqh_last = &(elm2)->field.tqe_next; \ (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ *(elm2)->field.tqe_prev = (elm2); \ QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field); \ } while (/*CONSTCOND*/0) #define TAILQ_CONCAT(head1, head2, field) do { \ if (!TAILQ_EMPTY(head2)) { \ *(head1)->tqh_last = (head2)->tqh_first; \ (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ (head1)->tqh_last = (head2)->tqh_last; \ TAILQ_INIT((head2)); \ } \ } while (/*CONSTCOND*/0) /* * Singly-linked Tail queue declarations. */ #define STAILQ_HEAD(name, type) \ struct name { \ struct type *stqh_first; /* first element */ \ struct type **stqh_last; /* addr of last next element */ \ } #define STAILQ_HEAD_INITIALIZER(head) \ { NULL, &(head).stqh_first } #define STAILQ_ENTRY(type) \ struct { \ struct type *stqe_next; /* next element */ \ } /* * Singly-linked Tail queue access methods. */ #define STAILQ_FIRST(head) ((head)->stqh_first) #define STAILQ_END(head) NULL #define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) #define STAILQ_EMPTY(head) (STAILQ_FIRST(head) == STAILQ_END(head)) /* * Singly-linked Tail queue functions. */ #define STAILQ_INIT(head) do { \ (head)->stqh_first = NULL; \ (head)->stqh_last = &(head)->stqh_first; \ } while (/*CONSTCOND*/0) #define STAILQ_INSERT_HEAD(head, elm, field) do { \ if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \ (head)->stqh_last = &(elm)->field.stqe_next; \ (head)->stqh_first = (elm); \ } while (/*CONSTCOND*/0) #define STAILQ_INSERT_TAIL(head, elm, field) do { \ (elm)->field.stqe_next = NULL; \ *(head)->stqh_last = (elm); \ (head)->stqh_last = &(elm)->field.stqe_next; \ } while (/*CONSTCOND*/0) #define STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ if (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\ (head)->stqh_last = &(elm)->field.stqe_next; \ (listelm)->field.stqe_next = (elm); \ } while (/*CONSTCOND*/0) #define STAILQ_REMOVE_HEAD(head, field) do { \ if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == NULL) \ (head)->stqh_last = &(head)->stqh_first; \ } while (/*CONSTCOND*/0) #define STAILQ_REMOVE(head, elm, type, field) do { \ if ((head)->stqh_first == (elm)) { \ STAILQ_REMOVE_HEAD((head), field); \ } else { \ struct type *curelm = (head)->stqh_first; \ while (curelm->field.stqe_next != (elm)) \ curelm = curelm->field.stqe_next; \ if ((curelm->field.stqe_next = \ curelm->field.stqe_next->field.stqe_next) == NULL) \ (head)->stqh_last = &(curelm)->field.stqe_next; \ } \ } while (/*CONSTCOND*/0) #define STAILQ_FOREACH(var, head, field) \ for ((var) = ((head)->stqh_first); \ (var); \ (var) = ((var)->field.stqe_next)) #define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = STAILQ_FIRST((head)); \ (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ (var) = (tvar)) #define STAILQ_CONCAT(head1, head2) do { \ if (!STAILQ_EMPTY((head2))) { \ *(head1)->stqh_last = (head2)->stqh_first; \ (head1)->stqh_last = (head2)->stqh_last; \ STAILQ_INIT((head2)); \ } \ } while (/*CONSTCOND*/0) #define STAILQ_LAST(head, type, field) \ (STAILQ_EMPTY((head)) ? \ NULL : \ ((struct type *)(void *) \ ((char *)((head)->stqh_last) - offsetof(struct type, field)))) #endif /* !SYS_QUEUE_H_ */ spiped-1.6.4/libcperciva/apisupport/Build/000755 001751 001751 00000000000 14653532061 022177 5ustar00cpercivacperciva000000 000000 spiped-1.6.4/libcperciva/apisupport/Build/apisupport-NONPOSIX-SETGROUPS.c000644 001751 001751 00000000452 14653532061 027416 0ustar00cpercivacperciva000000 000000 #include /* * Including a .c file is unusual, but setgroups_none.c contains a number of * system-specific header includes, which we do not want to duplicate here. */ #include "../../util/setgroups_none.c" int main(void) { (void)setgroups(0, NULL); /* Success! */ return (0); } spiped-1.6.4/libcperciva/apisupport/Build/apisupport.sh000755 001751 001751 00000004234 14650270210 024737 0ustar00cpercivacperciva000000 000000 # Should be sourced by `command -p sh path/to/apisupport.sh "$PATH"` from # within a Makefile. if ! [ "${PATH}" = "$1" ]; then echo "WARNING: POSIX violation: ${SHELL}'s command -p resets \$PATH" 1>&2 PATH=$1 fi # Standard output should be written to apisupport-config.h, which is both a # C header file defining APISUPPORT_PLATFORM_FEATURE macros and sourceable sh # code which sets CFLAGS_PLATFORM_FEATURE environment variables. SRCDIR=$(command -p dirname "$0") CFLAGS_HARDCODED="-D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700" # Do we want to record stderr to a file? if [ "${DEBUG:-0}" -eq "0" ]; then outcc="/dev/null" else outcc="apisupport-stderr.log" rm -f "${outcc}" fi feature() { PLATFORM=$1 FEATURE=$2 EXTRALIB=$3 shift 3; # Bail if we didn't include this feature in this source tree. feature_filename="${SRCDIR}/apisupport-${PLATFORM}-${FEATURE}.c" if ! [ -f "${feature_filename}" ]; then return fi # Check if we can compile this feature (and any required arguments). printf "Checking if compiler supports %s %s feature..." \ "${PLATFORM}" "${FEATURE}" 1>&2 for API_CFLAGS in "$@"; do if ${CC} ${CPPFLAGS} ${CFLAGS} ${CFLAGS_HARDCODED} \ ${API_CFLAGS} "${feature_filename}" ${LDADD_EXTRA} \ ${EXTRALIB} 2>>"${outcc}"; then rm -f a.out break; fi API_CFLAGS=NOTSUPPORTED; done case ${API_CFLAGS} in NOTSUPPORTED) echo " no" 1>&2 ;; "") echo " yes" 1>&2 echo "#define APISUPPORT_${PLATFORM}_${FEATURE} 1" ;; *) echo " yes, via ${API_CFLAGS}" 1>&2 echo "#define APISUPPORT_${PLATFORM}_${FEATURE} 1" echo "#ifdef apisupport_dummy" echo "export CFLAGS_${PLATFORM}_${FEATURE}=\"${API_CFLAGS}\"" echo "#endif" ;; esac } if [ "$2" = "--all" ]; then feature() { PLATFORM=$1 FEATURE=$2 echo "#define APISUPPORT_${PLATFORM}_${FEATURE} 1" } fi # Detect how to compile non-POSIX code. feature NONPOSIX SETGROUPS "" "" \ "-U_POSIX_C_SOURCE -U_XOPEN_SOURCE" \ "-U_POSIX_C_SOURCE -U_XOPEN_SOURCE -Wno-reserved-id-macro" # Detect how to compile libssl and libcrypto code. feature LIBSSL HOST_NAME "-lssl" "" \ "-Wno-cast-qual" feature LIBCRYPTO LOW_LEVEL_AES "-lcrypto" "" \ "-Wno-deprecated-declarations" spiped-1.6.4/libcperciva/apisupport/Build/apisupport-LIBCRYPTO-LOW_LEVEL_AES.c000644 001751 001751 00000000333 14650270210 030163 0ustar00cpercivacperciva000000 000000 #include #include int main(void) { AES_KEY kexp_actual; const uint8_t key_unexpanded[16] = { 0 }; AES_set_encrypt_key(key_unexpanded, 128, &kexp_actual); /* Success! */ return (0); } spiped-1.6.4/libcperciva/datastruct/timerqueue.c000644 001751 001751 00000011552 14743020337 023443 0ustar00cpercivacperciva000000 000000 #include #include #include #include "ptrheap.h" #include "timerqueue.h" struct timerqueue { struct ptrheap * H; }; struct timerrec { struct timeval tv; size_t rc; void * ptr; }; /* Compare two timevals. */ static int tvcmp(const struct timeval * x, const struct timeval * y) { /* Does one have more seconds? */ if (x->tv_sec > y->tv_sec) return (1); if (x->tv_sec < y->tv_sec) return (-1); /* Does one have more microseconds? */ if (x->tv_usec > y->tv_usec) return (1); if (x->tv_usec < y->tv_usec) return (-1); /* They must be equal. */ return (0); } /* Record-comparison callback from ptrheap. */ static int compar(void * cookie, const void * x, const void * y) { const struct timerrec * _x = x; const struct timerrec * _y = y; (void)cookie; /* UNUSED */ /* Compare the times. */ return (tvcmp(&_x->tv, &_y->tv)); } /* Cookie-recording callback from ptrheap. */ static void setreccookie(void * cookie, void * ptr, size_t rc) { struct timerrec * rec = ptr; (void)cookie; /* UNUSED */ rec->rc = rc; } /** * timerqueue_init(void): * Create and return an empty timer priority queue. */ struct timerqueue * timerqueue_init(void) { struct timerqueue * Q; /* Allocate structure. */ if ((Q = malloc(sizeof(struct timerqueue))) == NULL) goto err0; /* Allocate heap. */ if ((Q->H = ptrheap_init(compar, setreccookie, Q)) == NULL) goto err1; /* Success! */ return (Q); err1: free(Q); err0: /* Failure! */ return (NULL); } /** * timerqueue_add(Q, tv, ptr): * Add the pair (${tv}, ${ptr}) to the priority queue ${Q}. Return a cookie * which can be passed to timerqueue_delete() or timerqueue_increase(). */ void * timerqueue_add(struct timerqueue * Q, const struct timeval * tv, void * ptr) { struct timerrec * r; /* Allocate (timeval, ptr) pair record. */ if ((r = malloc(sizeof(struct timerrec))) == NULL) goto err0; /* Fill in values. */ memcpy(&r->tv, tv, sizeof(struct timeval)); r->ptr = ptr; /* * Add the record to the heap. The value r->rc will be filled in * by setreccookie which will be called by ptrheap_add. */ if (ptrheap_add(Q->H, r)) goto err1; /* Success! */ return (r); err1: free(r); err0: /* Failure! */ return (NULL); } /** * timerqueue_delete(Q, cookie): * Delete the (timeval, ptr) pair associated with the cookie ${cookie} from * the priority queue ${Q}. */ void timerqueue_delete(struct timerqueue * Q, void * cookie) { struct timerrec * r = cookie; /* Remove the record from the heap. */ ptrheap_delete(Q->H, r->rc); /* Free the record. */ free(r); } /** * timerqueue_increase(Q, cookie, tv): * Increase the timer associated with the cookie ${cookie} in the priority * queue ${Q} to ${tv}. */ void timerqueue_increase(struct timerqueue * Q, void * cookie, const struct timeval * tv) { struct timerrec * r = cookie; /* Adjust timer value. */ memcpy(&r->tv, tv, sizeof(struct timeval)); /* Inform the heap that the record value has increased. */ ptrheap_increase(Q->H, r->rc); } /** * timerqueue_getmin(Q): * Return a pointer to the least timeval in ${Q}, or NULL if the priority * queue is empty. The pointer will remain valid until the next call to a * timerqueue_* function. This function cannot fail. */ const struct timeval * timerqueue_getmin(struct timerqueue * Q) { struct timerrec * r; /* Get the minimum element from the heap. */ r = ptrheap_getmin(Q->H); /* If we have an element, return its timeval; otherwise, NULL. */ if (r != NULL) return (&r->tv); else return (NULL); } /** * timerqueue_getptr(Q, tv): * If the least timeval in ${Q} is less than or equal to ${tv}, return the * associated pointer and remove the pair from the priority queue. If not, * return NULL. This function cannot fail. */ void * timerqueue_getptr(struct timerqueue * Q, const struct timeval * tv) { struct timerrec * r; void * ptr; /* * Get the minimum element from the heap. Return NULL if the heap * has no minimum element (i.e., is empty). */ if ((r = ptrheap_getmin(Q->H)) == NULL) return (NULL); /* If the minimum timeval is greater than ${tv}, return NULL. */ if (tvcmp(&r->tv, tv) > 0) return (NULL); /* Remove this record from the heap. */ ptrheap_deletemin(Q->H); /* Extract its pointer. */ ptr = r->ptr; /* Free the record. */ free(r); /* * And finally return the pointer which was associated with the * (formerly) minimum timeval in the heap. */ return (ptr); } /** * timerqueue_free(Q): * Free the timer priority queue ${Q}. */ void timerqueue_free(struct timerqueue * Q) { struct timerrec * r; /* Behave consistently with free(NULL). */ if (Q == NULL) return; /* Extract elements from the heap and free them one by one. */ while ((r = ptrheap_getmin(Q->H)) != NULL) { free(r); ptrheap_deletemin(Q->H); } /* Free the heap. */ ptrheap_free(Q->H); /* Free the timer priority queue structure. */ free(Q); } spiped-1.6.4/libcperciva/datastruct/elasticarray.c000644 001751 001751 00000017616 14743020337 023750 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include #include "elasticarray.h" struct elasticarray { size_t size; size_t alloc; void * buf; }; /** * resize(EA, nsize): * Resize the virtual buffer for ${EA} to length ${nsize} bytes. The actual * buffer may or may not need to be resized. On failure, the buffer will be * unmodified. */ static int resize(struct elasticarray * EA, size_t nsize) { size_t nalloc; void * nbuf; /* Figure out how large an allocation we want. */ if (EA->alloc < nsize) { /* We need to enlarge the buffer. */ nalloc = EA->alloc * 2; /* * Handle if nalloc is not large enough to hold nsize, which can * happen when: 1) EA->alloc is small enough that EA->alloc * 2 * is still smaller than nsize, or 2) EA->alloc is large enough * that EA->alloc * 2 wraps around, becoming smaller than nsize. */ if (nalloc < nsize) nalloc = nsize; } else if (EA->alloc / 4 > nsize) { /* We need to shrink the buffer. */ nalloc = nsize * 2; } else { nalloc = EA->alloc; } /* * Resizing to zero needs special handling due to some strange * interpretations of what realloc(p, 0) should do if it fails * to allocate zero bytes of memory. */ if (nalloc == 0) { /* We can only get here if we set nsize to 0. */ assert(nsize == 0); free(EA->buf); EA->buf = NULL; EA->alloc = 0; } else if (nalloc != EA->alloc) { /* Reallocate to a nonzero size if necessary. */ if ((nbuf = realloc(EA->buf, nalloc)) == NULL) goto err0; EA->buf = nbuf; EA->alloc = nalloc; } /* Record the new array size. */ EA->size = nsize; /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * elasticarray_init(nrec, reclen): * Create and return an elastic array holding ${nrec} (uninitialized) records * of length ${reclen}. Takes O(nrec * reclen) time. The value ${reclen} * must be positive. */ struct elasticarray * elasticarray_init(size_t nrec, size_t reclen) { struct elasticarray * EA; /* Sanity check. */ assert(reclen > 0); /* Allocate structure. */ if ((EA = malloc(sizeof(struct elasticarray))) == NULL) goto err0; /* The array is empty for now. */ EA->size = EA->alloc = 0; EA->buf = NULL; /* Reallocate to the requested length. */ if (elasticarray_resize(EA, nrec, reclen)) goto err1; /* Success! */ return (EA); err1: elasticarray_free(EA); err0: /* Failure! */ return (NULL); } /** * elasticarray_resize(EA, nrec, reclen): * Resize the elastic array pointed to by ${EA} to hold ${nrec} records of * length ${reclen}. If ${nrec} exceeds the number of records previously * held by the array, the additional records will be uninitialized. Takes * O(nrec * reclen) time. The value ${reclen} must be positive. */ int elasticarray_resize(struct elasticarray * EA, size_t nrec, size_t reclen) { /* Check for overflow. */ if (nrec > SIZE_MAX / reclen) { errno = ENOMEM; goto err0; } /* Resize the buffer. */ if (resize(EA, nrec * reclen)) goto err0; /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * elasticarray_getsize(EA, reclen): * Return the number of length-${reclen} records in the array, rounding down * if there is a partial record (which can only occur if elasticarray_* * functions have been called with different values of reclen). The value * ${reclen} must be positive. */ size_t elasticarray_getsize(const struct elasticarray * EA, size_t reclen) { return (EA->size / reclen); } /** * elasticarray_append(EA, buf, nrec, reclen): * Append to the elastic array ${EA} the ${nrec} records of length ${reclen} * stored in ${buf}. Takes O(nrec * reclen) amortized time. The value * ${reclen} must be positive. */ int elasticarray_append(struct elasticarray * EA, const void * buf, size_t nrec, size_t reclen) { size_t bufpos = EA->size; size_t nsize; /* Check for overflow. */ if ((nrec > SIZE_MAX / reclen) || (nrec * reclen > SIZE_MAX - EA->size)) { errno = ENOMEM; goto err0; } /* Resize the buffer. */ nsize = EA->size + nrec * reclen; if (resize(EA, nsize)) goto err0; /* Copy bytes in. */ if (nrec > 0) { /* We shouldn't have requested a 0-size array. */ assert(nsize > 0); /* Copy bytes in. */ memcpy((uint8_t *)(EA->buf) + bufpos, buf, nrec * reclen); } /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * elasticarray_shrink(EA, nrec, reclen): * Delete the final ${nrec} records of length ${reclen} from the elastic * array ${EA}. If there are fewer than ${nrec} records, all records * present will be deleted. The value ${reclen} must be positive. * * As an exception to the normal rule, an elastic array may occupy more than * 4 times the optimal storage immediately following an elasticarray_shrink() * call; but only if realloc(3) failed to shrink a memory allocation. */ void elasticarray_shrink(struct elasticarray * EA, size_t nrec, size_t reclen) { size_t nsize; /* Figure out how much to keep. */ if ((nrec > SIZE_MAX / reclen) || (nrec * reclen > EA->size)) nsize = 0; else nsize = EA->size - nrec * reclen; /* Resize the buffer... */ if (resize(EA, nsize)) { /* * ... and if we fail to reallocate, just record the new * length and continue using the old buffer. */ EA->size = nsize; } } /** * elasticarray_truncate(EA): * Release any spare space in the elastic array ${EA}. */ int elasticarray_truncate(struct elasticarray * EA) { void * nbuf; /* * Truncating down to zero needs special handling due to some strange * interpretations of what realloc(p, 0) should do if it fails to * allocate zero bytes of memory. */ if (EA->size == 0) { free(EA->buf); EA->buf = NULL; EA->alloc = 0; } else if (EA->alloc > EA->size) { /* Reallocate to eliminate spare space if necessary. */ if ((nbuf = realloc(EA->buf, EA->size)) == NULL) goto err0; EA->buf = nbuf; EA->alloc = EA->size; } /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * elasticarray_get(EA, pos, reclen): * Return a pointer to record number ${pos} of length ${reclen} in the * elastic array ${EA}. Takes O(1) time. */ void * elasticarray_get(struct elasticarray * EA, size_t pos, size_t reclen) { /* Calculate the pointer address. */ return ((uint8_t *)(EA->buf) + pos * reclen); } /** * elasticarray_free(EA): * Free the elastic array ${EA}. Takes O(1) time. */ void elasticarray_free(struct elasticarray * EA) { /* Behave consistently with free(NULL). */ if (EA == NULL) return; free(EA->buf); free(EA); } /** * elasticarray_export(EA, buf, nrec, reclen): * Return the data in the elastic array ${EA} as a buffer ${buf} containing * ${nrec} records of length ${reclen}. Free the elastic array ${EA}. * The value ${reclen} must be positive. */ int elasticarray_export(struct elasticarray * EA, void ** buf, size_t * nrec, size_t reclen) { /* Remove any spare space. */ if (elasticarray_truncate(EA)) goto err0; /* Return the buffer and number of records. */ *buf = EA->buf; *nrec = elasticarray_getsize(EA, reclen); /* * Free the elastic array structure -- but not its buffer, since we've * passed the buffer out to the caller. */ free(EA); /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * elasticarray_exportdup(EA, buf, nrec, reclen): * Duplicate the data in the elastic array ${EA} into a buffer ${buf} * containing ${nrec} records of length ${reclen}. (Same as _export, except * that the elastic array remains intact.) The value ${reclen} must be * positive. */ int elasticarray_exportdup(const struct elasticarray * EA, void ** buf, size_t * nrec, size_t reclen) { /* Allocate buffer for the caller's copy of the data. */ if ((*buf = malloc(EA->size)) == NULL) goto err0; /* Copy the data in. */ memcpy(*buf, EA->buf, EA->size); /* Tell the caller how many records we have. */ *nrec = elasticarray_getsize(EA, reclen); /* Success! */ return (0); err0: /* Failure! */ return (-1); } spiped-1.6.4/libcperciva/datastruct/ptrheap.c000644 001751 001751 00000021340 13723620112 022707 0ustar00cpercivacperciva000000 000000 #include #include "elasticarray.h" #include "ptrheap.h" ELASTICARRAY_DECL(PTRLIST, ptrlist, void *); struct ptrheap { int (* compar)(void *, const void *, const void *); void (* setreccookie)(void *, void *, size_t); void * cookie; PTRLIST elems; size_t nelems; }; /** * swap(elems, i, j, setreccookie, cookie): * Swap elements ${i} and ${j} in ${elems}. If ${setreccookie} is non-NULL, * invoke ${setreccookie}(${cookie}, elem, pos) for each of the elements and * their new positions in the tree. */ static void swap(PTRLIST elems, size_t i, size_t j, void (* setreccookie)(void *, void *, size_t), void * cookie) { void * tmp; /* Swap the elements. */ tmp = *ptrlist_get(elems, i); *ptrlist_get(elems, i) = *ptrlist_get(elems, j); *ptrlist_get(elems, j) = tmp; /* Notify about the moved elements. */ if (setreccookie != NULL) { setreccookie(cookie, *ptrlist_get(elems, i), i); setreccookie(cookie, *ptrlist_get(elems, j), j); } } /** * heapifyup(elems, i, compar, setreccookie, cookie): * Sift up element ${i} of the elements ${elems}, using the comparison * function ${compar} and the cookie ${cookie}. If elements move and * ${setreccookie} is non-NULL, use it to notify about the updated position * of elements in the heap. */ static void heapifyup(PTRLIST elems, size_t i, int (* compar)(void *, const void *, const void *), void (* setreccookie)(void *, void *, size_t), void * cookie) { /* Iterate up the tree. */ do { /* If we're at the root, we have nothing to do. */ if (i == 0) break; /* If this is >= its parent, we're done. */ if (compar(cookie, *ptrlist_get(elems, i), *ptrlist_get(elems, (i - 1) / 2)) >= 0) break; /* Swap with the parent. */ swap(elems, i, (i - 1) / 2, setreccookie, cookie); /* Move up the tree. */ i = (i - 1) / 2; } while (1); } /** * heapify(elems, i, N, compar, setreccookie, cookie): * Sift down element number ${i} out of ${N} of the elements ${elems}, using * the comparison function ${compar} and the cookie ${cookie}. If elements * move and ${setreccookie} is non-NULL, use it to notify about the updated * position of elements in the heap. */ static void heapify(PTRLIST elems, size_t i, size_t N, int (* compar)(void *, const void *, const void *), void (* setreccookie)(void *, void *, size_t), void * cookie) { size_t min; /* Iterate down the tree. */ do { /* Look for the minimum element out of {i, 2i+1, 2i+2}. */ min = i; /* Is this bigger than element 2i+1? */ if ((2 * i + 1 < N) && (compar(cookie, *ptrlist_get(elems, min), *ptrlist_get(elems, 2 * i + 1)) > 0)) min = 2 * i + 1; /* Is this bigger than element 2i+2? */ if ((2 * i + 2 < N) && (compar(cookie, *ptrlist_get(elems, min), *ptrlist_get(elems, 2 * i + 2)) > 0)) min = 2 * i + 2; /* If the minimum is i, we have heap-property. */ if (min == i) break; /* Move the minimum into position i. */ swap(elems, min, i, setreccookie, cookie); /* Move down the tree. */ i = min; } while (1); } /** * ptrheap_init(compar, setreccookie, cookie): * Create and return an empty heap. The function ${compar}(${cookie}, x, y) * should return less than, equal to, or greater than 0 depending on whether * x is less than, equal to, or greater than y; and if ${setreccookie} is * non-zero it will be called as ${setreccookie}(${cookie}, ${ptr}, ${rc}) to * indicate that the value ${rc} is the current record cookie for the pointer * ${ptr}. The function ${setreccookie} may not make any ptrheap_* calls. */ struct ptrheap * ptrheap_init(int (* compar)(void *, const void *, const void *), void (* setreccookie)(void *, void *, size_t), void * cookie) { /* Let ptrheap_create handle this. */ return (ptrheap_create(compar, setreccookie, cookie, 0, NULL)); } /** * ptrheap_create(compar, setreccookie, cookie, N, ptrs): * Create and return a heap, as in ptrheap_init(), but with the ${N} pointers * in ${ptrs} as heap elements. This is faster than creating an empty heap * and adding the elements individually. */ struct ptrheap * ptrheap_create(int (* compar)(void *, const void *, const void *), void (* setreccookie)(void *, void *, size_t), void * cookie, size_t N, void ** ptrs) { struct ptrheap * H; size_t i; /* Allocate structure. */ if ((H = malloc(sizeof(struct ptrheap))) == NULL) goto err0; /* Store parameters. */ H->compar = compar; H->setreccookie = setreccookie; H->cookie = cookie; /* We will have N elements. */ H->nelems = N; /* Allocate space for N heap elements. */ if ((H->elems = ptrlist_init(N)) == NULL) goto err1; /* Copy the heap elements in. */ for (i = 0; i < N; i++) *ptrlist_get(H->elems, i) = ptrs[i]; /* Turn this into a heap. */ for (i = N - 1; i < N; i--) heapify(H->elems, i, N, H->compar, NULL, H->cookie); /* Advise the caller about the record cookies. */ if (H->setreccookie != NULL) for (i = 0; i < N; i++) (H->setreccookie)(H->cookie, *ptrlist_get(H->elems, i), i); /* Success! */ return (H); err1: free(H); err0: /* Failure! */ return (NULL); } /** * ptrheap_add(H, ptr): * Add the pointer ${ptr} to the heap ${H}. */ int ptrheap_add(struct ptrheap * H, void * ptr) { /* Add the element to the end of the heap. */ if (ptrlist_append(H->elems, &ptr, 1)) goto err0; H->nelems += 1; /* Advise the caller about the current location of this record. */ if (H->setreccookie != NULL) (H->setreccookie)(H->cookie, ptr, H->nelems - 1); /* Move the new element up in the tree if necessary. */ heapifyup(H->elems, H->nelems - 1, H->compar, H->setreccookie, H->cookie); /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * ptrheap_getmin(H): * Return the minimum pointer in the heap ${H}. If the heap is empty, NULL * is returned. */ void * ptrheap_getmin(struct ptrheap * H) { /* If we have any elements, the minimum is in position 0. */ if (H->nelems) return (*ptrlist_get(H->elems, 0)); else return (NULL); } /** * ptrheap_delete(H, rc): * Delete from the heap ${H} the element ptr for which the function call * setreccookie(cookie, ptr, ${rc}) was most recently made. */ void ptrheap_delete(struct ptrheap * H, size_t rc) { /* * If the element we're deleting is not at the end of the heap, * replace it with the element which is currently at the end. */ if (rc != H->nelems - 1) { /* Move ptr from position H->nelems - 1 into position rc. */ *ptrlist_get(H->elems, rc) = *ptrlist_get(H->elems, H->nelems - 1); if (H->setreccookie != NULL) (H->setreccookie)(H->cookie, *ptrlist_get(H->elems, rc), rc); /* Is this too small to be in position ${rc}? */ if ((rc > 0) && (H->compar(H->cookie, *ptrlist_get(H->elems, rc), *ptrlist_get(H->elems, (rc - 1) / 2)) < 0)) { /* Swap with the parent, and keep moving up. */ swap(H->elems, rc, (rc - 1) / 2, H->setreccookie, H->cookie); heapifyup(H->elems, (rc - 1) / 2, H->compar, H->setreccookie, H->cookie); } else { /* Maybe we need to move it down instead? */ heapify(H->elems, rc, H->nelems, H->compar, H->setreccookie, H->cookie); } } /* * We've got everything we want to keep in positions 0 .. nelems - 2, * and we have heap-nature, so all we need to do is strip off the * final pointer. */ ptrlist_shrink(H->elems, 1); H->nelems--; } /** * ptrheap_deletemin(H): * Delete the minimum element in the heap ${H}. The heap must not be empty. */ void ptrheap_deletemin(struct ptrheap * H) { /* Let ptrheap_delete handle this. */ ptrheap_delete(H, 0); } /** * ptrheap_decrease(H, rc): * Adjust the heap ${H} to account for the fact that the element ptr for * which the function call setreccookie(cookie, ptr, ${rc}) was most recently * made has decreased. */ void ptrheap_decrease(struct ptrheap * H, size_t rc) { /* Move the element up if necessary. */ heapifyup(H->elems, rc, H->compar, H->setreccookie, H->cookie); } /** * ptrheap_increase(H, rc): * Adjust the heap ${H} to account for the fact that the element ptr for * which the function call setreccookie(cookie, ptr, ${rc}) was most recently * made has increased. */ void ptrheap_increase(struct ptrheap * H, size_t rc) { /* Move the element down if necessary. */ heapify(H->elems, rc, H->nelems, H->compar, H->setreccookie, H->cookie); } /** * ptrheap_increasemin(H): * Adjust the heap ${H} to account for the fact that the (formerly) minimum * element has increased. */ void ptrheap_increasemin(struct ptrheap * H) { /* Move the element down if necessary. */ heapify(H->elems, 0, H->nelems, H->compar, H->setreccookie, H->cookie); } /** * ptrheap_free(H): * Free the pointer heap ${H}. */ void ptrheap_free(struct ptrheap * H) { /* Behave consistently with free(NULL). */ if (H == NULL) return; ptrlist_free(H->elems); free(H); } spiped-1.6.4/libcperciva/datastruct/ptrheap.h000644 001751 001751 00000006333 14650270210 022721 0ustar00cpercivacperciva000000 000000 #ifndef PTRHEAP_H_ #define PTRHEAP_H_ #include /** * Pointer-heap data structure. Arbitrary pointers can be inserted and are * compared using a provided callback; the usual heapy getmin / increasemin / * deletemin algorithms are supported. To use three additional functions, * ptrheap_{delete, increase, decrease}, a setreccookie callback needs to be * provided. These functions require a record cookie to identify the element * to operate upon; each time a record's record cookie changes, the * setreccookie callback will be called. Functions return NULL or (int)(-1) * on error and set errno; other return types indicate that failure is not * possible. On error, the heap will be unmodified. */ /* Opaque pointer-heap type. */ struct ptrheap; /** * ptrheap_init(compar, setreccookie, cookie): * Create and return an empty heap. The function ${compar}(${cookie}, x, y) * should return less than, equal to, or greater than 0 depending on whether * x is less than, equal to, or greater than y; and if ${setreccookie} is * non-zero it will be called as ${setreccookie}(${cookie}, ${ptr}, ${rc}) to * indicate that the value ${rc} is the current record cookie for the pointer * ${ptr}. The function ${setreccookie} may not make any ptrheap_* calls. */ struct ptrheap * ptrheap_init(int (*)(void *, const void *, const void *), void (*)(void *, void *, size_t), void *); /** * ptrheap_create(compar, setreccookie, cookie, N, ptrs): * Create and return a heap, as in ptrheap_init(), but with the ${N} pointers * in ${ptrs} as heap elements. This is faster than creating an empty heap * and adding the elements individually. */ struct ptrheap * ptrheap_create(int (*)(void *, const void *, const void *), void (*)(void *, void *, size_t), void *, size_t, void **); /** * ptrheap_add(H, ptr): * Add the pointer ${ptr} to the heap ${H}. */ int ptrheap_add(struct ptrheap *, void *); /** * ptrheap_getmin(H): * Return the minimum pointer in the heap ${H}. If the heap is empty, NULL * is returned. */ void * ptrheap_getmin(struct ptrheap *); /** * ptrheap_delete(H, rc): * Delete from the heap ${H} the element ptr for which the function call * setreccookie(cookie, ptr, ${rc}) was most recently made. */ void ptrheap_delete(struct ptrheap *, size_t); /** * ptrheap_deletemin(H): * Delete the minimum element in the heap ${H}. The heap must not be empty. */ void ptrheap_deletemin(struct ptrheap *); /** * ptrheap_decrease(H, rc): * Adjust the heap ${H} to account for the fact that the element ptr for * which the function call setreccookie(cookie, ptr, ${rc}) was most recently * made has decreased. */ void ptrheap_decrease(struct ptrheap *, size_t); /** * ptrheap_increase(H, rc): * Adjust the heap ${H} to account for the fact that the element ptr for * which the function call setreccookie(cookie, ptr, ${rc}) was most recently * made has increased. */ void ptrheap_increase(struct ptrheap *, size_t); /** * ptrheap_increasemin(H): * Adjust the heap ${H} to account for the fact that the (formerly) minimum * element has increased. */ void ptrheap_increasemin(struct ptrheap *); /** * ptrheap_free(H): * Free the pointer heap ${H}. */ void ptrheap_free(struct ptrheap *); #endif /* !PTRHEAP_H_ */ spiped-1.6.4/libcperciva/datastruct/elasticarray.h000644 001751 001751 00000016643 14650270210 023746 0ustar00cpercivacperciva000000 000000 #ifndef ELASTICARRAY_H_ #define ELASTICARRAY_H_ #include /** * Elastic Arrays are dynamically resizing arrays which remain within a * factor of 4 of the optimal size for the data they contain and have (within * a constant factor) amortized optimal running time providing that all of * the allocated space is accessed at some point. Functions return NULL or * (int)(-1) on error and set errno; other return types indicate that failure * is not possible. On error, the array will be unmodified. * * The ELASTICARRAY_DECL(type, prefix, rectype) macro can be used to create a * more friendly interface, at the expense of restricting the array to only * holding a single data type. */ /* Opaque elastic array type. */ struct elasticarray; /** * elasticarray_init(nrec, reclen): * Create and return an elastic array holding ${nrec} (uninitialized) records * of length ${reclen}. Takes O(nrec * reclen) time. The value ${reclen} * must be positive. */ struct elasticarray * elasticarray_init(size_t, size_t); /** * elasticarray_resize(EA, nrec, reclen): * Resize the elastic array pointed to by ${EA} to hold ${nrec} records of * length ${reclen}. If ${nrec} exceeds the number of records previously * held by the array, the additional records will be uninitialized. Takes * O(nrec * reclen) time. The value ${reclen} must be positive. */ int elasticarray_resize(struct elasticarray *, size_t, size_t); /** * elasticarray_getsize(EA, reclen): * Return the number of length-${reclen} records in the array, rounding down * if there is a partial record (which can only occur if elasticarray_* * functions have been called with different values of reclen). The value * ${reclen} must be positive. */ size_t elasticarray_getsize(const struct elasticarray *, size_t); /** * elasticarray_append(EA, buf, nrec, reclen): * Append to the elastic array ${EA} the ${nrec} records of length ${reclen} * stored in ${buf}. Takes O(nrec * reclen) amortized time. The value * ${reclen} must be positive. */ int elasticarray_append(struct elasticarray *, const void *, size_t, size_t); /** * elasticarray_shrink(EA, nrec, reclen): * Delete the final ${nrec} records of length ${reclen} from the elastic * array ${EA}. If there are fewer than ${nrec} records, all records * present will be deleted. The value ${reclen} must be positive. * * As an exception to the normal rule, an elastic array may occupy more than * 4 times the optimal storage immediately following an elasticarray_shrink() * call; but only if realloc(3) failed to shrink a memory allocation. */ void elasticarray_shrink(struct elasticarray *, size_t, size_t); /** * elasticarray_truncate(EA): * Release any spare space in the elastic array ${EA}. */ int elasticarray_truncate(struct elasticarray *); /** * elasticarray_get(EA, pos, reclen): * Return a pointer to record number ${pos} of length ${reclen} in the * elastic array ${EA}. Takes O(1) time. */ void * elasticarray_get(struct elasticarray *, size_t, size_t); /** * elasticarray_free(EA): * Free the elastic array ${EA}. Takes O(1) time. */ void elasticarray_free(struct elasticarray *); /** * elasticarray_export(EA, buf, nrec, reclen): * Return the data in the elastic array ${EA} as a buffer ${buf} containing * ${nrec} records of length ${reclen}. Free the elastic array ${EA}. * The value ${reclen} must be positive. */ int elasticarray_export(struct elasticarray *, void **, size_t *, size_t); /** * elasticarray_exportdup(EA, buf, nrec, reclen): * Duplicate the data in the elastic array ${EA} into a buffer ${buf} * containing ${nrec} records of length ${reclen}. (Same as _export, except * that the elastic array remains intact.) The value ${reclen} must be * positive. */ int elasticarray_exportdup(const struct elasticarray *, void **, size_t *, size_t); /** * ELASTICARRAY_DECL(type, prefix, rectype): * Declare the type ${type} and the following functions: * ${type} ${prefix}_init(size_t nrec); * int ${prefix}_resize(${type} EA, size_t nrec); * size_t ${prefix}_getsize(const ${type} EA); * int ${prefix}_append(${type} EA, const void * buf, size_t nrec); * void ${prefix}_shrink(${type} EA, size_t nrec); * int ${prefix}_truncate(${type} EA); * ${rectype} * ${prefix}_get(${type} EA, size_t pos); * void ${prefix}_iter(${type} EA, void (*)(void *)); * void ${prefix}_free(${type} EA); */ #define ELASTICARRAY_DECL(type, prefix, rectype) \ static inline struct prefix##_struct * \ prefix##_init(size_t nrec) \ { \ struct elasticarray * EA; \ \ EA = elasticarray_init(nrec, sizeof(rectype)); \ return ((struct prefix##_struct *)EA); \ } \ static inline int \ prefix##_resize(struct prefix##_struct * EA, size_t nrec) \ { \ return (elasticarray_resize((struct elasticarray *)EA, \ nrec, sizeof(rectype))); \ } \ static inline size_t \ prefix##_getsize(const struct prefix##_struct * EA) \ { \ return (elasticarray_getsize( \ (const struct elasticarray *)EA, \ sizeof(rectype))); \ } \ static inline int \ prefix##_append(struct prefix##_struct * EA, \ rectype const * buf, size_t nrec) \ { \ return (elasticarray_append((struct elasticarray *)EA, \ buf, nrec, sizeof(rectype))); \ } \ static inline void \ prefix##_shrink(struct prefix##_struct * EA, size_t nrec) \ { \ elasticarray_shrink((struct elasticarray *)EA, \ nrec, sizeof(rectype)); \ } \ static inline int \ prefix##_truncate(struct prefix##_struct * EA) \ { \ return (elasticarray_truncate( \ (struct elasticarray *)EA)); \ } \ static inline rectype * \ prefix##_get(struct prefix##_struct * EA, size_t pos) \ { \ rectype * rec; \ \ rec = elasticarray_get((struct elasticarray *)EA, \ pos, sizeof(rectype)); \ return (rec); \ } \ static inline void \ prefix##_iter(struct prefix##_struct * EA, \ void (* fp)(rectype *)) \ { \ size_t i; \ \ for (i = 0; i < prefix##_getsize(EA); i++) \ fp(prefix##_get(EA, i)); \ } \ static inline void \ prefix##_free(struct prefix##_struct * EA) \ { \ elasticarray_free((struct elasticarray *)EA); \ } \ static inline int \ prefix##_export(struct prefix##_struct * EA, rectype ** buf, \ size_t * nrec) \ { \ return (elasticarray_export((struct elasticarray *)EA, \ (void **)buf, nrec, sizeof(rectype))); \ } \ static inline int \ prefix##_exportdup(const struct prefix##_struct * EA, \ rectype ** buf, size_t * nrec) \ { \ return (elasticarray_exportdup( \ (const struct elasticarray *)EA, \ (void **)buf, nrec, sizeof(rectype))); \ } \ static void (* prefix##_dummyptr)(void); \ static inline void \ prefix##_dummy(void) \ { \ \ (void)prefix##_init; \ (void)prefix##_resize; \ (void)prefix##_getsize; \ (void)prefix##_append; \ (void)prefix##_shrink; \ (void)prefix##_truncate; \ (void)prefix##_get; \ (void)prefix##_iter; \ (void)prefix##_free; \ (void)prefix##_export; \ (void)prefix##_exportdup; \ (void)prefix##_dummyptr; \ } \ static void (* prefix##_dummyptr)(void) = prefix##_dummy; \ typedef struct prefix##_struct * type #endif /* !ELASTICARRAY_H_ */ spiped-1.6.4/libcperciva/datastruct/timerqueue.h000644 001751 001751 00000003333 14650270210 023440 0ustar00cpercivacperciva000000 000000 #ifndef TIMERQUEUE_H_ #define TIMERQUEUE_H_ #include /* Timer priority queue. Contains (timeval, ptr) pairs. */ /* Opaque timer priority queue type. */ struct timerqueue; /** * timerqueue_init(void): * Create and return an empty timer priority queue. */ struct timerqueue * timerqueue_init(void); /** * timerqueue_add(Q, tv, ptr): * Add the pair (${tv}, ${ptr}) to the priority queue ${Q}. Return a cookie * which can be passed to timerqueue_delete() or timerqueue_increase(). */ void * timerqueue_add(struct timerqueue *, const struct timeval *, void *); /** * timerqueue_delete(Q, cookie): * Delete the (timeval, ptr) pair associated with the cookie ${cookie} from * the priority queue ${Q}. */ void timerqueue_delete(struct timerqueue *, void *); /** * timerqueue_increase(Q, cookie, tv): * Increase the timer associated with the cookie ${cookie} in the priority * queue ${Q} to ${tv}. */ void timerqueue_increase(struct timerqueue *, void *, const struct timeval *); /** * timerqueue_getmin(Q): * Return a pointer to the least timeval in ${Q}, or NULL if the priority * queue is empty. The pointer will remain valid until the next call to a * timerqueue_* function. This function cannot fail. */ const struct timeval * timerqueue_getmin(struct timerqueue *); /** * timerqueue_getptr(Q, tv): * If the least timeval in ${Q} is less than or equal to ${tv}, return the * associated pointer and remove the pair from the priority queue. If not, * return NULL. This function cannot fail. */ void * timerqueue_getptr(struct timerqueue *, const struct timeval *); /** * timerqueue_free(Q): * Free the timer priority queue ${Q}. */ void timerqueue_free(struct timerqueue *); #endif /* !TIMERQUEUE_H_ */ spiped-1.6.4/libcperciva/datastruct/mpool.h000644 001751 001751 00000010120 14743020337 022377 0ustar00cpercivacperciva000000 000000 #ifndef MPOOL_H_ #define MPOOL_H_ #include #include #include #include #include "ctassert.h" /** * Memory allocator cache. Memory allocations can be returned to the pool * and reused by a subsequent allocation without returning all the way to * free/malloc. In effect, this is an optimization for the case where we * know we will want another allocation of the same size soon, at the expense * of keeping memory allocated (and thus preventing any other code from * allocating the same memory). */ /* Internal data. */ struct mpool { size_t stacklen; size_t allocsize; void ** allocs; uint64_t nallocs; uint64_t nempties; int state; void ** allocs_static; void (* atexitfunc)(void); }; static inline void mpool_atexit(struct mpool * M) { /* Free all items on the stack. */ while (M->stacklen) free(M->allocs[--M->stacklen]); /* If we allocated a stack, free it. */ if (M->allocs != M->allocs_static) free(M->allocs); } static inline void * mpool_malloc(struct mpool * M, size_t len) { /* Count the total number of allocation requests. */ M->nallocs++; /* If we have an object on the stack, use that. */ if (M->stacklen) return (M->allocs[--(M->stacklen)]); /* Count allocation requests where the pool was already empty. */ M->nempties++; /* Initialize the atexit function (the first time we reach here). */ if (M->state == 0) { atexit(M->atexitfunc); M->state = 1; } /* Allocate a new object. */ return (malloc(len)); } static inline void mpool_free(struct mpool * M, void * p) { void ** allocs_new; /* Behave consistently with free(NULL). */ if (p == NULL) return; /* If we have space in the stack, cache the object. */ if (M->stacklen < M->allocsize) { M->allocs[M->stacklen++] = p; return; } /* * Autotuning: If more than 1/256 of mpool_malloc() calls resulted in * a malloc(), double the stack. */ if (M->nempties > (M->nallocs >> 8)) { /* Sanity check. */ assert(M->allocsize > 0); /* Allocate new stack and copy pointers into it. */ allocs_new = (void **)malloc(M->allocsize * 2 * sizeof(void *)); if (allocs_new) { memcpy(allocs_new, M->allocs, M->allocsize * sizeof(void *)); if (M->allocs != M->allocs_static) free(M->allocs); M->allocs = allocs_new; M->allocsize = M->allocsize * 2; M->allocs[M->stacklen++] = p; } else free(p); } else free(p); /* Reset statistics. */ M->nempties = 0; M->nallocs = 0; } /** * MPOOL(name, type, size): * Define the functions * * ${type} * mpool_${name}_malloc(void); * void mpool_${name}_free(${type} *); * * which allocate and free structures of type ${type}. A minimum of ${size} * such structures are kept cached after _free is called in order to allow * future _malloc calls to be rapidly serviced; this limit will be autotuned * upwards depending on the allocation/free pattern. * * Cached structures will be freed at program exit time in order to aid * in the detection of memory leaks. */ #define MPOOL(name, type, size) \ static void mpool_##name##_atexit(void); \ static void * mpool_##name##_static[size]; \ static struct mpool mpool_##name##_rec = \ {0, size, mpool_##name##_static, 0, 0, 0, \ mpool_##name##_static, mpool_##name##_atexit}; \ \ CTASSERT(size > 0); \ \ static void \ mpool_##name##_atexit(void) \ { \ \ mpool_atexit(&mpool_##name##_rec); \ } \ \ static inline type * \ mpool_##name##_malloc(void) \ { \ \ return (mpool_malloc(&mpool_##name##_rec, sizeof(type))); \ } \ \ static inline void \ mpool_##name##_free(type * p) \ { \ \ mpool_free(&mpool_##name##_rec, p); \ } \ \ static void (* mpool_##name##_dummyptr)(void); \ static inline void \ mpool_##name##_dummyfunc(void) \ { \ \ (void)mpool_##name##_malloc; \ (void)mpool_##name##_free; \ (void)mpool_##name##_dummyptr; \ } \ static void (* mpool_##name##_dummyptr)(void) = mpool_##name##_dummyfunc; \ struct mpool_##name##_dummy #endif /* !MPOOL_H_ */ spiped-1.6.4/libcperciva/cpusupport/cpusupport_x86_ssse3.c000644 001751 001751 00000001136 14743020337 025372 0ustar00cpercivacperciva000000 000000 #include "cpusupport.h" #ifdef CPUSUPPORT_X86_CPUID #include #define CPUID_SSSE3_BIT (1 << 9) #endif CPUSUPPORT_FEATURE_DECL(x86, ssse3) { #ifdef CPUSUPPORT_X86_CPUID unsigned int eax, ebx, ecx, edx; /* Check if CPUID supports the level we need. */ if (!__get_cpuid(0, &eax, &ebx, &ecx, &edx)) goto unsupported; if (eax < 1) goto unsupported; /* Ask about CPU features. */ if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx)) goto unsupported; /* Return the relevant feature bit. */ return ((ecx & CPUID_SSSE3_BIT) ? 1 : 0); unsupported: #endif /* Not supported. */ return (0); } spiped-1.6.4/libcperciva/cpusupport/cpusupport_arm_aes.c000644 001751 001751 00000002711 14101630450 025223 0ustar00cpercivacperciva000000 000000 #include "cpusupport.h" #ifdef CPUSUPPORT_HWCAP_GETAUXVAL #include #if defined(__arm__) /** * Workaround for a glibc bug: contains a comment saying: * The following must match the kernel's . * However, it does not contain any of the HWCAP2_* entries from . */ #ifndef HWCAP2_AES #include #endif #endif /* __arm__ */ #endif /* CPUSUPPORT_HWCAP_GETAUXVAL */ #if defined(CPUSUPPORT_HWCAP_ELF_AUX_INFO) #include #endif /* CPUSUPPORT_HWCAP_ELF_AUX_INFO */ CPUSUPPORT_FEATURE_DECL(arm, aes) { int supported = 0; #if defined(CPUSUPPORT_ARM_AES) #if defined(CPUSUPPORT_HWCAP_GETAUXVAL) unsigned long capabilities; #if defined(__aarch64__) capabilities = getauxval(AT_HWCAP); supported = (capabilities & HWCAP_AES) ? 1 : 0; #elif defined(__arm__) capabilities = getauxval(AT_HWCAP2); supported = (capabilities & HWCAP2_AES) ? 1 : 0; #endif #endif /* CPUSUPPORT_HWCAP_GETAUXVAL */ #if defined(CPUSUPPORT_HWCAP_ELF_AUX_INFO) unsigned long capabilities; #if defined(__aarch64__) if (elf_aux_info(AT_HWCAP, &capabilities, sizeof(unsigned long))) return (0); supported = (capabilities & HWCAP_AES) ? 1 : 0; #else if (elf_aux_info(AT_HWCAP2, &capabilities, sizeof(unsigned long))) return (0); supported = (capabilities & HWCAP2_AES) ? 1 : 0; #endif #endif /* CPUSUPPORT_HWCAP_ELF_AUX_INFO */ #endif /* CPUSUPPORT_ARM_AES */ /* Return the supported status. */ return (supported); } spiped-1.6.4/libcperciva/cpusupport/cpusupport_x86_sse2.c000644 001751 001751 00000001134 14743020337 025204 0ustar00cpercivacperciva000000 000000 #include "cpusupport.h" #ifdef CPUSUPPORT_X86_CPUID #include #define CPUID_SSE2_BIT (1 << 26) #endif CPUSUPPORT_FEATURE_DECL(x86, sse2) { #ifdef CPUSUPPORT_X86_CPUID unsigned int eax, ebx, ecx, edx; /* Check if CPUID supports the level we need. */ if (!__get_cpuid(0, &eax, &ebx, &ecx, &edx)) goto unsupported; if (eax < 1) goto unsupported; /* Ask about CPU features. */ if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx)) goto unsupported; /* Return the relevant feature bit. */ return ((edx & CPUID_SSE2_BIT) ? 1 : 0); unsupported: #endif /* Not supported. */ return (0); } spiped-1.6.4/libcperciva/cpusupport/cpusupport_x86_aesni.c000644 001751 001751 00000001137 14743020337 025432 0ustar00cpercivacperciva000000 000000 #include "cpusupport.h" #ifdef CPUSUPPORT_X86_CPUID #include #define CPUID_AESNI_BIT (1 << 25) #endif CPUSUPPORT_FEATURE_DECL(x86, aesni) { #ifdef CPUSUPPORT_X86_CPUID unsigned int eax, ebx, ecx, edx; /* Check if CPUID supports the level we need. */ if (!__get_cpuid(0, &eax, &ebx, &ecx, &edx)) goto unsupported; if (eax < 1) goto unsupported; /* Ask about CPU features. */ if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx)) goto unsupported; /* Return the relevant feature bit. */ return ((ecx & CPUID_AESNI_BIT) ? 1 : 0); unsupported: #endif /* Not supported. */ return (0); } spiped-1.6.4/libcperciva/cpusupport/cpusupport.h000644 001751 001751 00000015336 14650270210 023553 0ustar00cpercivacperciva000000 000000 #ifndef CPUSUPPORT_H_ #define CPUSUPPORT_H_ /* * To enable support for non-portable CPU features at compile time, one or * more CPUSUPPORT_ARCH_FEATURE macros should be defined. This can be done * directly on the compiler command line via -D CPUSUPPORT_ARCH_FEATURE or * -D CPUSUPPORT_ARCH_FEATURE=1; or a file can be created with the * necessary #define lines and then -D CPUSUPPORT_CONFIG_FILE=cpuconfig.h * (or similar) can be provided to include that file here. */ #ifdef CPUSUPPORT_CONFIG_FILE #include CPUSUPPORT_CONFIG_FILE #endif /** * The CPUSUPPORT_FEATURE macro declares the necessary variables and * functions for detecting CPU feature support at run time. The function * defined in the macro acts to cache the result of the ..._detect function * using the ..._present and ..._init variables. The _detect function and the * _present and _init variables are turn defined by CPUSUPPORT_FEATURE_DECL in * appropriate cpusupport_foo_bar.c file. * * In order to allow CPUSUPPORT_FEATURE to be used for features which do not * have corresponding CPUSUPPORT_FEATURE_DECL blocks in another source file, * we abuse the C preprocessor: If CPUSUPPORT_${enabler} is defined to 1, then * we access _present_1, _init_1, and _detect_1; but if it is not defined, we * access _present_CPUSUPPORT_${enabler} etc., which we define as static, thus * preventing the compiler from emitting a reference to an external symbol. * * In this way, it becomes possible to issue CPUSUPPORT_FEATURE invocations * for nonexistent features without running afoul of the requirement that * "If an identifier declared with external linkage is used... in the entire * program there shall be exactly one external definition" (C99 standard, 6.9 * paragraph 5). In practice, this means that users of the cpusupport code * can omit build and runtime detection files without changing the framework * code. */ #define CPUSUPPORT_FEATURE__(arch_feature, enabler, enabled) \ static int cpusupport_ ## arch_feature ## _present ## _CPUSUPPORT_ ## enabler; \ static int cpusupport_ ## arch_feature ## _init ## _CPUSUPPORT_ ## enabler; \ static inline int cpusupport_ ## arch_feature ## _detect ## _CPUSUPPORT_ ## enabler(void) { return (0); } \ extern int cpusupport_ ## arch_feature ## _present_ ## enabled; \ extern int cpusupport_ ## arch_feature ## _init_ ## enabled; \ int cpusupport_ ## arch_feature ## _detect_ ## enabled(void); \ \ static inline int \ cpusupport_ ## arch_feature(void) \ { \ \ if (cpusupport_ ## arch_feature ## _present_ ## enabled) \ return (1); \ else if (cpusupport_ ## arch_feature ## _init_ ## enabled) \ return (0); \ cpusupport_ ## arch_feature ## _present_ ## enabled = \ cpusupport_ ## arch_feature ## _detect_ ## enabled(); \ cpusupport_ ## arch_feature ## _init_ ## enabled = 1; \ return (cpusupport_ ## arch_feature ## _present_ ## enabled); \ } \ static void (* cpusupport_ ## arch_feature ## _dummyptr)(void); \ static inline void \ cpusupport_ ## arch_feature ## _dummyfunc(void) \ { \ \ (void)cpusupport_ ## arch_feature ## _present ## _CPUSUPPORT_ ## enabler; \ (void)cpusupport_ ## arch_feature ## _init ## _CPUSUPPORT_ ## enabler; \ (void)cpusupport_ ## arch_feature ## _detect ## _CPUSUPPORT_ ## enabler; \ (void)cpusupport_ ## arch_feature ## _present_ ## enabled; \ (void)cpusupport_ ## arch_feature ## _init_ ## enabled; \ (void)cpusupport_ ## arch_feature ## _detect_ ## enabled; \ (void)cpusupport_ ## arch_feature ## _dummyptr; \ } \ static void (* cpusupport_ ## arch_feature ## _dummyptr)(void) = cpusupport_ ## arch_feature ## _dummyfunc; \ struct cpusupport_ ## arch_feature ## _dummy #define CPUSUPPORT_FEATURE_(arch_feature, enabler, enabled) \ CPUSUPPORT_FEATURE__(arch_feature, enabler, enabled) #define CPUSUPPORT_FEATURE(arch, feature, enabler) \ CPUSUPPORT_FEATURE_(arch ## _ ## feature, enabler, CPUSUPPORT_ ## enabler) /** * CPUSUPPORT_FEATURE_DECL(arch, feature): * Macro which defines variables and provides a function declaration for * detecting the presence of "feature" on the "arch" architecture. The * function body following this macro expansion must return nonzero if the * feature is present, or zero if the feature is not present or the detection * fails for any reason. */ #define CPUSUPPORT_FEATURE_DECL(arch, feature) \ extern int cpusupport_ ## arch ## _ ## feature ## _present_1; \ extern int cpusupport_ ## arch ## _ ## feature ## _init_1; \ int cpusupport_ ## arch ## _ ## feature ## _present_1 = 0; \ int cpusupport_ ## arch ## _ ## feature ## _init_1 = 0; \ int cpusupport_ ## arch ## _ ## feature ## _detect_1(void); \ int \ cpusupport_ ## arch ## _ ## feature ## _detect_1(void) /** * CPUSUPPORT_VALIDATE(hwvar, success_value, cpusupport_checks, check): * Check if we can enable ${success_value}, given the ${cpusupport_checks} and * ${check}; if so, write to ${hwvar}. If the ${cpusupport_checks} pass but * the ${check} is non-zero, produce a warning which includes a stringified * ${success_value}, then fallthrough. */ #define CPUSUPPORT_VALIDATE(hwvar, success_value, cpusupport_checks, \ check) do { \ if ((cpusupport_checks)) { \ if ((check) == 0) { \ (hwvar) = (success_value); \ return; \ } else { \ warn0("Disabling " #success_value \ " due to failed self-test"); \ } \ } \ } while (0) /** * List of features. If a feature here is not enabled by the appropriate * CPUSUPPORT_ARCH_FEATURE macro being defined, it has no effect; but if the * relevant macro may be defined (e.g., by Build/cpusupport.sh successfully * compiling Build/cpusupport-ARCH-FEATURE.c) then the C file containing the * corresponding run-time detection code (cpusupport_arch_feature.c) must be * compiled and linked in. * * There are a few features for which we do not have run-time checks: * - X86_CPUID: compile-time is enough; if __get_cpuid() fails, then all the * x86 detection features will fail, but there's nothing we can * do about that. * - X86_CPUID_COUNT: ditto. * - X86_SSE42_64: the cpuid check tells us if the CPU supports SSE4.2, but * that says nothing about whether it's in 64-bit mode. */ CPUSUPPORT_FEATURE(x86, aesni, X86_AESNI); CPUSUPPORT_FEATURE(x86, rdrand, X86_RDRAND); CPUSUPPORT_FEATURE(x86, shani, X86_SHANI); CPUSUPPORT_FEATURE(x86, sse2, X86_SSE2); CPUSUPPORT_FEATURE(x86, sse42, X86_SSE42); CPUSUPPORT_FEATURE(x86, ssse3, X86_SSSE3); CPUSUPPORT_FEATURE(arm, aes, ARM_AES); CPUSUPPORT_FEATURE(arm, crc32_64, ARM_CRC32_64); CPUSUPPORT_FEATURE(arm, sha256, ARM_SHA256); #endif /* !CPUSUPPORT_H_ */ spiped-1.6.4/libcperciva/cpusupport/Build/000755 001751 001751 00000000000 14743020337 022213 5ustar00cpercivacperciva000000 000000 spiped-1.6.4/libcperciva/cpusupport/cpusupport_x86_rdrand.c000644 001751 001751 00000001142 14743020337 025601 0ustar00cpercivacperciva000000 000000 #include "cpusupport.h" #ifdef CPUSUPPORT_X86_CPUID #include #define CPUID_RDRAND_BIT (1 << 30) #endif CPUSUPPORT_FEATURE_DECL(x86, rdrand) { #ifdef CPUSUPPORT_X86_CPUID unsigned int eax, ebx, ecx, edx; /* Check if CPUID supports the level we need. */ if (!__get_cpuid(0, &eax, &ebx, &ecx, &edx)) goto unsupported; if (eax < 1) goto unsupported; /* Ask about CPU features. */ if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx)) goto unsupported; /* Return the relevant feature bit. */ return ((ecx & CPUID_RDRAND_BIT) ? 1 : 0); unsupported: #endif /* Not supported. */ return (0); } spiped-1.6.4/libcperciva/cpusupport/cpusupport_arm_sha256.c000644 001751 001751 00000002730 14101630450 025464 0ustar00cpercivacperciva000000 000000 #include "cpusupport.h" #ifdef CPUSUPPORT_HWCAP_GETAUXVAL #include #if defined(__arm__) /** * Workaround for a glibc bug: contains a comment saying: * The following must match the kernel's . * However, it does not contain any of the HWCAP2_* entries from . */ #ifndef HWCAP2_CRC32 #include #endif #endif /* __arm__ */ #endif /* CPUSUPPORT_HWCAP_GETAUXVAL */ #if defined(CPUSUPPORT_HWCAP_ELF_AUX_INFO) #include #endif /* CPUSUPPORT_HWCAP_ELF_AUX_INFO */ CPUSUPPORT_FEATURE_DECL(arm, sha256) { int supported = 0; #if defined(CPUSUPPORT_ARM_SHA256) #if defined(CPUSUPPORT_HWCAP_GETAUXVAL) unsigned long capabilities; #if defined(__aarch64__) capabilities = getauxval(AT_HWCAP); supported = (capabilities & HWCAP_SHA2) ? 1 : 0; #elif defined(__arm__) capabilities = getauxval(AT_HWCAP2); supported = (capabilities & HWCAP2_SHA2) ? 1 : 0; #endif #endif /* CPUSUPPORT_HWCAP_GETAUXVAL */ #if defined(CPUSUPPORT_HWCAP_ELF_AUX_INFO) unsigned long capabilities; #if defined(__aarch64__) if (elf_aux_info(AT_HWCAP, &capabilities, sizeof(unsigned long))) return (0); supported = (capabilities & HWCAP_SHA2) ? 1 : 0; #else if (elf_aux_info(AT_HWCAP2, &capabilities, sizeof(unsigned long))) return (0); supported = (capabilities & HWCAP2_SHA2) ? 1 : 0; #endif #endif /* CPUSUPPORT_HWCAP_ELF_AUX_INFO */ #endif /* CPUSUPPORT_ARM_SHA256 */ /* Return the supported status. */ return (supported); } spiped-1.6.4/libcperciva/cpusupport/cpusupport_x86_shani.c000644 001751 001751 00000001533 14743020337 025435 0ustar00cpercivacperciva000000 000000 #include "cpusupport.h" #ifdef CPUSUPPORT_X86_CPUID_COUNT #include #define CPUID_SHANI_BIT (1 << 29) #endif CPUSUPPORT_FEATURE_DECL(x86, shani) { #ifdef CPUSUPPORT_X86_CPUID_COUNT unsigned int eax, ebx, ecx, edx; /* Check if CPUID supports the level we need. */ if (!__get_cpuid(0, &eax, &ebx, &ecx, &edx)) goto unsupported; if (eax < 7) goto unsupported; /* * Ask about extended CPU features. Note that this macro violates * the principle of being "function-like" by taking the variables * used for holding output registers as named parameters rather than * as pointers (which would be necessary if __cpuid_count were a * function). */ __cpuid_count(7, 0, eax, ebx, ecx, edx); /* Return the relevant feature bit. */ return ((ebx & CPUID_SHANI_BIT) ? 1 : 0); unsupported: #endif /* Not supported. */ return (0); } spiped-1.6.4/libcperciva/cpusupport/Build/cpusupport-ARM-AES.c000644 001751 001751 00000000657 14743020337 025636 0ustar00cpercivacperciva000000 000000 #include #ifdef __ARM_NEON #include #endif int main(void) { uint8x16_t data; uint8x16_t key = {0}; uint8x16_t output; uint32x4_t lanes = {0}; uint8_t arr[16] = {0}; /* Check AES. */ data = vld1q_u8(arr); output = vaeseq_u8(data, key); (void)output; /* UNUSED */ /* Check _u32: some compilers only support the _u8 variant. */ lanes = vdupq_laneq_u32(lanes, 0); /* Success! */ return (0); } spiped-1.6.4/libcperciva/cpusupport/Build/cpusupport-HWCAP-GETAUXVAL.c000644 001751 001751 00000000160 14014627713 027000 0ustar00cpercivacperciva000000 000000 #include int main(void) { unsigned long val; val = getauxval(AT_HWCAP); return (val != 0); } spiped-1.6.4/libcperciva/cpusupport/Build/cpusupport-X86-SHANI.c000644 001751 001751 00000000762 14650270210 026025 0ustar00cpercivacperciva000000 000000 #include #include /* * Use a separate function for this, because that means that the alignment of * the _mm_loadu_si128() will move to function level, which may require * -Wno-cast-align. */ static __m128i load_128(const uint8_t * src) { __m128i x; x = _mm_loadu_si128((const __m128i *)src); return (x); } int main(void) { __m128i x; uint8_t a[16] = {0}; x = load_128(a); x = _mm_sha256msg1_epu32(x, x); _mm_storeu_si128((__m128i *)a, x); return (a[0]); } spiped-1.6.4/libcperciva/cpusupport/Build/cpusupport-X86-SSE2.c000644 001751 001751 00000000670 14014627713 025705 0ustar00cpercivacperciva000000 000000 #include static char a[16]; /* * Use a separate function for this, because that means that the alignment of * the _mm_loadu_si128() will move to function level, which may require * -Wno-cast-align. */ static __m128i load_128(const char * src) { __m128i x; x = _mm_loadu_si128((const __m128i *)src); return (x); } int main(void) { __m128i x; x = load_128(a); _mm_storeu_si128((__m128i *)a, x); return (a[0]); } spiped-1.6.4/libcperciva/cpusupport/Build/cpusupport.sh000755 001751 001751 00000006406 14650270210 024776 0ustar00cpercivacperciva000000 000000 # Should be sourced by `command -p sh path/to/cpusupport.sh "$PATH"` from # within a Makefile. if ! [ "${PATH}" = "$1" ]; then echo "WARNING: POSIX violation: ${SHELL}'s command -p resets \$PATH" 1>&2 PATH=$1 fi # Standard output should be written to cpusupport-config.h, which is both a # C header file defining CPUSUPPORT_ARCH_FEATURE macros and sourceable sh # code which sets CFLAGS_ARCH_FEATURE environment variables. SRCDIR=$(command -p dirname "$0") CFLAGS_HARDCODED="-D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700" # Do we want to record stderr to a file? if [ "${DEBUG:-0}" -eq "0" ]; then outcc="/dev/null" else outcc="cpusupport-stderr.log" rm -f "${outcc}" fi feature() { ARCH=$1 FEATURE=$2 shift 2; # Bail if we didn't include this feature in this source tree. feature_filename="${SRCDIR}/cpusupport-${ARCH}-${FEATURE}.c" if ! [ -f "${feature_filename}" ]; then return fi # Check if we can compile this feature (and any required arguments). printf "Checking if compiler supports %s %s feature..." \ "${ARCH}" "${FEATURE}" 1>&2 for CPU_CFLAGS in "$@"; do if ${CC} ${CPPFLAGS} ${CFLAGS} ${CFLAGS_HARDCODED} \ ${CPU_CFLAGS} "${feature_filename}" 2>>"${outcc}"; then rm -f a.out break; fi CPU_CFLAGS=NOTSUPPORTED; done case ${CPU_CFLAGS} in NOTSUPPORTED) echo " no" 1>&2 ;; "") echo " yes" 1>&2 echo "#define CPUSUPPORT_${ARCH}_${FEATURE} 1" ;; *) echo " yes, via ${CPU_CFLAGS}" 1>&2 echo "#define CPUSUPPORT_${ARCH}_${FEATURE} 1" echo "#ifdef cpusupport_dummy" echo "export CFLAGS_${ARCH}_${FEATURE}=\"${CPU_CFLAGS}\"" echo "#endif" ;; esac } if [ "$2" = "--all" ]; then feature() { ARCH=$1 FEATURE=$2 echo "#define CPUSUPPORT_${ARCH}_${FEATURE} 1" } fi # Detect CPU-detection features feature HWCAP ELF_AUX_INFO "" feature HWCAP GETAUXVAL "" feature X86 CPUID "" feature X86 CPUID_COUNT "" # Detect specific features feature X86 AESNI "" "-maes" \ "-maes -Wno-cast-align" \ "-maes -Wno-missing-prototypes -Wno-cast-qual" \ "-maes -Wno-missing-prototypes -Wno-cast-qual -Wno-cast-align" \ "-maes -Wno-missing-prototypes -Wno-cast-qual -Wno-cast-align \ -DBROKEN_MM_LOADU_SI64" feature X86 RDRAND "" "-mrdrnd" feature X86 SHANI "" "-msse2 -msha" \ "-msse2 -msha -Wno-cast-align" feature X86 SSE2 "" \ "-Wno-cast-align" \ "-msse2" \ "-msse2 -Wno-cast-align" feature X86 SSE42 "" "-msse4.2" \ "-msse4.2 -Wno-cast-align" \ "-msse4.2 -Wno-cast-align -fno-strict-aliasing" \ "-msse4.2 -Wno-cast-align -fno-strict-aliasing -Wno-cast-qual" feature X86 SSE42_64 "" "-msse4.2" \ "-msse4.2 -Wno-cast-align" \ "-msse4.2 -Wno-cast-align -fno-strict-aliasing" \ "-msse4.2 -Wno-cast-align -fno-strict-aliasing -Wno-cast-qual" feature X86 SSSE3 "" "-mssse3" \ "-mssse3 -Wno-cast-align" # Detect specific ARM features feature ARM AES "-march=armv8.1-a+crypto" \ "-march=armv8.1-a+crypto -D__ARM_ACLE=200" feature ARM CRC32_64 "-march=armv8.1-a" \ "-march=armv8.1-a+crc" \ "-march=armv8.1-a+crc -Wno-cast-align" \ "-march=armv8.1-a -D__ARM_ACLE=200" feature ARM SHA256 "-march=armv8.1-a+crypto" \ "-march=armv8.1-a+crypto -Wno-cast-align" \ "-march=armv8.1-a+crypto -D__ARM_ACLE=200" spiped-1.6.4/libcperciva/cpusupport/Build/cpusupport-ARM-SHA256.c000644 001751 001751 00000000341 14650270210 026056 0ustar00cpercivacperciva000000 000000 #ifdef __ARM_NEON #include #endif int main(void) { uint32x4_t w0 = {0}; uint32x4_t w4 = {0}; uint32x4_t output; output = vsha256su0q_u32(w0, w4); (void)output; /* UNUSED */ /* Success! */ return (0); } spiped-1.6.4/libcperciva/cpusupport/Build/cpusupport-X86-CPUID.c000644 001751 001751 00000000154 14650270210 026022 0ustar00cpercivacperciva000000 000000 #include int main(void) { unsigned int a, b, c, d; return (__get_cpuid(0, &a, &b, &c, &d)); } spiped-1.6.4/libcperciva/cpusupport/Build/cpusupport-X86-SSSE3.c000644 001751 001751 00000000756 13777161017 026043 0ustar00cpercivacperciva000000 000000 #include #include static char a[16]; /* * Use a separate function for this, because that means that the alignment of * the _mm_loadu_si128() will move to function level, which may require * -Wno-cast-align. */ static __m128i load_128(const char * src) { __m128i x; x = _mm_loadu_si128((const __m128i *)src); return (x); } int main(void) { __m128i x; x = load_128(a); x = _mm_alignr_epi8(x, x, 8); _mm_storeu_si128((__m128i *)a, x); return (a[0]); } spiped-1.6.4/libcperciva/cpusupport/Build/cpusupport-HWCAP-ELF_AUX_INFO.c000644 001751 001751 00000000246 14101630450 027370 0ustar00cpercivacperciva000000 000000 #include int main(void) { int res; unsigned long val; res = elf_aux_info(AT_HWCAP, &val, sizeof(unsigned long)); (void)res; return (val != 0); } spiped-1.6.4/libcperciva/cpusupport/Build/cpusupport-X86-AESNI.c000644 001751 001751 00000001141 14650270210 026012 0ustar00cpercivacperciva000000 000000 #include #include /* * Use a separate function for this, because that means that the alignment of * the _mm_loadu_si128() will move to function level, which may require * -Wno-cast-align. */ static __m128i load_128(const uint8_t * src) { __m128i x; x = _mm_loadu_si128((const __m128i *)src); return (x); } int main(void) { __m128i x, y; uint8_t a[16] = {0}; x = load_128(a); #ifdef BROKEN_MM_LOADU_SI64 y = _mm_loadu_si128((const __m128i *)a); #else y = _mm_loadu_si64(a); #endif y = _mm_aesenc_si128(x, y); _mm_storeu_si128((__m128i *)&a[0], y); return (a[0]); } spiped-1.6.4/libcperciva/cpusupport/Build/cpusupport-X86-CPUID_COUNT.c000644 001751 001751 00000000166 13762775424 027021 0ustar00cpercivacperciva000000 000000 #include int main(void) { unsigned int a, b, c, d; __cpuid_count(7, 0, a, b, c, d); return ((int)a); } spiped-1.6.4/libcperciva/cpusupport/Build/cpusupport-X86-RDRAND.c000644 001751 001751 00000000134 14154500003 026121 0ustar00cpercivacperciva000000 000000 #include int main(void) { unsigned int x; return (!_rdrand32_step(&x)); } spiped-1.6.4/libcperciva/POSIX/posix-cflags-filter.sh000644 001751 001751 00000001607 14650270210 024046 0ustar00cpercivacperciva000000 000000 # Should be sourced by # command -p sh posix-cflags-filter.sh "$PATH" # from within a Makefile. # Produces a file to be sourced which edits CFLAGS. # Sanity check environment variables if [ -z "${CC}" ]; then echo "\$CC is not defined! Cannot run any compiler tests." 1>&2 exit 1 fi if ! [ "${PATH}" = "$1" ]; then echo "WARNING: POSIX violation: ${SHELL}'s command -p resets \$PATH" 1>&2 PATH=$1 fi # Find directory of this script and the source files D=$(dirname "$0") if ! ${CC} -O2 "${D}/posix-trivial.c" 2>/dev/null; then if ${CC} "${D}/posix-trivial.c" 2>/dev/null; then echo 'CFLAGS_FILTERED=""' echo 'for OPT in $CFLAGS; do' echo ' if [ "$OPT" = "-O2" ]; then' echo ' continue' echo ' fi' echo ' CFLAGS_FILTERED="$CFLAGS $OPT"' echo 'done' echo 'CFLAGS="$CFLAGS_FILTERED"' echo "WARNING: POSIX violation: make's CC doesn't understand -O2" 1>&2 fi fi rm -f a.out spiped-1.6.4/libcperciva/POSIX/posix-inet6-addrstrlen.c000644 001751 001751 00000000111 13723620112 024306 0ustar00cpercivacperciva000000 000000 #include int main(void) { return (INET6_ADDRSTRLEN); } spiped-1.6.4/libcperciva/POSIX/posix-trivial.c000644 001751 001751 00000000061 14650270210 022577 0ustar00cpercivacperciva000000 000000 int main(void) { /* Success! */ return (0); } spiped-1.6.4/libcperciva/POSIX/posix-clock_gettime.c000644 001751 001751 00000000152 13360750213 023742 0ustar00cpercivacperciva000000 000000 #include int main(void) { struct timespec ts; return (clock_gettime(CLOCK_REALTIME, &ts)); } spiped-1.6.4/libcperciva/POSIX/posix-l.sh000755 001751 001751 00000001316 14650270210 021557 0ustar00cpercivacperciva000000 000000 # Should be sourced by # command -p sh posix-l.sh "$PATH" # from within a Makefile. # Sanity check environment variables if [ -z "${CC}" ]; then echo "\$CC is not defined! Cannot run any compiler tests." 1>&2 exit 1 fi if ! [ "${PATH}" = "$1" ]; then echo "WARNING: POSIX violation: ${SHELL}'s command -p resets \$PATH" 1>&2 PATH=$1 fi # Find directory of this script and the source files D=$(dirname "$0") FIRST=YES for LIB in rt xnet; do if ${CC} ${CFLAGS} -l"${LIB}" "${D}/posix-trivial.c" 2>/dev/null; then if [ "${FIRST}" = "NO" ]; then printf " "; fi printf "%s" "-l${LIB}"; FIRST=NO; else echo "WARNING: POSIX violation: ${CC} does not understand -l${LIB}" 1>&2 fi rm -f a.out done spiped-1.6.4/libcperciva/POSIX/README000644 001751 001751 00000003742 14154500003 020505 0ustar00cpercivacperciva000000 000000 POSIX compatibility code ------------------------ This code exists to work around some common POSIX compatibility issues. POSIX specifies that if the first line of a Makefile is ".POSIX:" then the Makefile should be processed according to POSIX rules, including with CC=c99; thus we should see behaviour consistent with a standard-compliant C99 compiler. One POSIX compatibility check requires a runtime test. This will be automatically disabled if the build system detects that you are cross-compiling for another platform, or it can be manually disabled by setting DISABLE_POSIX_RUNTIME_CHECKS to a non-zero value. - posix-cflags.sh: Detects if ${CC} supports certain POSIX features, and outputs a POSIXFAIL_ define if it is not supported so that we can work around the problem. The potential command-line flags are: - DPOSIXFAIL_MSG_NOSIGNAL: not defining MSG_NOSIGNAL. - DPOSIXFAIL_CLOCK_REALTIME: not defining CLOCK_REALTIME. - DPOSIXFAIL_CLOCK_GETTIME: not declaring clock_gettime(), or clock_gettime() is not linkable. The latter test requires a runtime check. - DPOSIXFAIL_INET_ADDRSTRLEN: not defining INET_ADDRSTRLEN. - DPOSIXFAIL_INET6_ADDRSTRLEN: not defining INET6_ADDRSTRLEN. - DPOSIXFAIL_ABSTRACT_DECLARATOR: ${CC} does not accept qualifiers in an abstract declarator. - DPOSIXFAIL_STAT_ST_MTIM: struct stat does not contain st_mtim. - std=c99: ${CC} does not accept the `restrict` keyword by default, but accepts it when given this flag. - posix-cflags-filter.sh: Detects if ${CC} supports expected ${CFLAG} value(s). The potential ${CFLAGS} flags it checks are: - O2: some compilers only accept -O. - posix-l.sh: Detects whether the linker supports certain POSIX features. The potential command-line flags are: - lrt lxnet: c99 is required to understand these options, and ignore them if the routines for which they specify linkage are already in the standard C library spiped-1.6.4/libcperciva/POSIX/posix-clock_realtime.c000644 001751 001751 00000000101 13360750213 024100 0ustar00cpercivacperciva000000 000000 #include int main(void) { return (CLOCK_REALTIME); } spiped-1.6.4/libcperciva/POSIX/posix-cflags.sh000755 001751 001751 00000010334 14650270210 022563 0ustar00cpercivacperciva000000 000000 # Should be sourced by # command -p sh posix-cflags.sh "$PATH" # from within a Makefile. # Sanity check environment variables if [ -z "${CC}" ]; then echo "\$CC is not defined! Cannot run any compiler tests." 1>&2 exit 1 fi if ! [ "${PATH}" = "$1" ]; then echo "WARNING: POSIX violation: ${SHELL}'s command -p resets \$PATH" 1>&2 PATH=$1 fi # Find directory of this script and the source files D=$(dirname "$0") # Check if we can compile & run a binary. if ! ${CC} ${CFLAGS} "${D}/posix-trivial.c" 2>/dev/null; then echo "WARNING: failed to compile posix-trivial.c" 1>&2 else # If the user hasn't disabled runtime checks... if [ "${DISABLE_POSIX_RUNTIME_CHECKS:-0}" -eq "0" ]; then # ... test if we can run the trivial binary. if ! ./a.out ; then echo "WARNING: failed to run a trivial binary; " 1>&2 echo "disabling runtime POSIX compatibility checks" 1>&2 DISABLE_POSIX_RUNTIME_CHECKS=1 fi fi fi FIRST=YES if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L "${D}/posix-msg_nosignal.c" 2>/dev/null; then [ "${FIRST}" = "NO" ] && printf " "; FIRST=NO printf %s "-DPOSIXFAIL_MSG_NOSIGNAL" echo "WARNING: POSIX violation: not defining MSG_NOSIGNAL" 1>&2 fi if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L "${D}/posix-clock_realtime.c" 2>/dev/null; then [ "${FIRST}" = "NO" ] && printf " "; FIRST=NO printf %s "-DPOSIXFAIL_CLOCK_REALTIME" echo "WARNING: POSIX violation: not defining CLOCK_REALTIME" 1>&2 fi if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 "${D}/posix-inet-addrstrlen.c" 2>/dev/null; then [ "${FIRST}" = "NO" ] && printf " "; FIRST=NO printf %s "-DPOSIXFAIL_INET_ADDRSTRLEN" echo "WARNING: POSIX violation: not defining INET_ADDRSTRLEN" 1>&2 fi if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 "${D}/posix-inet6-addrstrlen.c" 2>/dev/null; then [ "${FIRST}" = "NO" ] && printf " "; FIRST=NO printf %s "-DPOSIXFAIL_INET6_ADDRSTRLEN" echo "WARNING: POSIX violation: not defining INET6_ADDRSTRLEN" 1>&2 fi if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L "${D}/posix-clock_gettime.c" 2>/dev/null; then [ "${FIRST}" = "NO" ] && printf " "; FIRST=NO printf %s "-DPOSIXFAIL_CLOCK_GETTIME" echo "WARNING: POSIX violation: not declaring clock_gettime()" 1>&2 elif [ "${DISABLE_POSIX_RUNTIME_CHECKS:-0}" -ne "0" ]; then # Do nothing true else # Even if the compilation succeeds, we still need to run the binary # because OS X 10.11 with XCode 8 _will_ contain clock_gettime() in the # header (because it was added in 10.12 and they only use one SDK per # XCode version), but it will link to the 10.11 library (which doesn't # include it). Annoyingly, there's two levels of error output on OS X: # one from the binary itself, and one from the signal it sends to the # calling process. The "( ./x 2>y ) 2>y" captures both types of error # message. if ! ( ./a.out 2>/dev/null ) 2>/dev/null ; then [ "${FIRST}" = "NO" ] && printf " "; FIRST=NO printf %s "-DPOSIXFAIL_CLOCK_GETTIME" echo "WARNING: POSIX violation: clock_gettime() is not linkable" 1>&2 fi fi if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 "${D}/posix-stat-st_mtim.c" 2>/dev/null; then [ "${FIRST}" = "NO" ] && printf " "; FIRST=NO printf %s "-DPOSIXFAIL_STAT_ST_MTIM" echo "WARNING: POSIX violation: struct stat does not contain st_mtim" 1>&2 fi CFLAGS_C99="" if ! ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L "${D}/posix-restrict.c" 2>/dev/null; then echo "WARNING: POSIX violation: ${CC} does not accept the 'restrict' keyword" 1>&2 if ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L -std=c99 "${D}/posix-restrict.c" 2>/dev/null; then [ "${FIRST}" = "NO" ] && printf " "; FIRST=NO printf %s "-std=c99" CFLAGS_C99="-std=c99" fi fi if ! ${CC} ${CFLAGS} ${CFLAGS_C99} -D_POSIX_C_SOURCE=200809L -DARGNAME="" "${D}/posix-abstract-declarator.c" 2>/dev/null; then echo "WARNING: POSIX violation: ${CC} does not accept qualifiers in an abstract declarator" 1>&2 # Test compile with -DPOSIXFAIL_ABSTRACT_DECLARATOR if ${CC} ${CFLAGS} ${CFLAGS_C99} -D_POSIX_C_SOURCE=200809L -DPOSIXFAIL_ABSTRACT_DECLARATOR "${D}/posix-abstract-declarator.c" 2>/dev/null; then [ "${FIRST}" = "NO" ] && printf " "; FIRST=NO printf %s "-DPOSIXFAIL_ABSTRACT_DECLARATOR" fi fi rm -f a.out spiped-1.6.4/libcperciva/POSIX/posix-abstract-declarator.c000644 001751 001751 00000000474 14650270210 025056 0ustar00cpercivacperciva000000 000000 #ifdef POSIXFAIL_ABSTRACT_DECLARATOR static int func(int ARGNAME[static restrict 1]); #else static int func(int [static restrict 1]); #endif int func(int arr[static restrict 1]) { (void)arr; /* UNUSED */ /* Success! */ return (0); } int main(void) { (void)func; /* UNUSED */ /* Success! */ return (0); } spiped-1.6.4/libcperciva/POSIX/posix-restrict.c000644 001751 001751 00000000234 14650270210 022766 0ustar00cpercivacperciva000000 000000 static int foo(const char * restrict x, const char * restrict y) { return (x == y); } int main(void) { char x[10]; char y[10]; return (foo(x, y)); } spiped-1.6.4/libcperciva/POSIX/posix-inet-addrstrlen.c000644 001751 001751 00000000110 13723620112 024217 0ustar00cpercivacperciva000000 000000 #include int main(void) { return (INET_ADDRSTRLEN); } spiped-1.6.4/libcperciva/POSIX/posix-stat-st_mtim.c000644 001751 001751 00000000225 14650270210 023554 0ustar00cpercivacperciva000000 000000 #include int main(void) { struct stat sb; /* Can we reference st_mtim? */ (void)sb.st_mtim.tv_sec; /* Success! */ return (0); } spiped-1.6.4/libcperciva/POSIX/posix-msg_nosignal.c000644 001751 001751 00000000105 13360750213 023607 0ustar00cpercivacperciva000000 000000 #include int main(void) { return (MSG_NOSIGNAL); } spiped-1.6.4/libcperciva/network/network_read.c000644 001751 001751 00000007272 14650270210 023253 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include #include #include "events.h" #include "mpool.h" #include "network.h" struct network_read_cookie { int (* callback)(void *, ssize_t); void * cookie; int fd; uint8_t * buf; size_t buflen; size_t minlen; size_t bufpos; }; MPOOL(network_read_cookie, struct network_read_cookie, 16); /* Invoke the callback, clean up, and return the callback's status. */ static int docallback(struct network_read_cookie * C, ssize_t nbytes) { int rc; /* Invoke the callback. */ rc = (C->callback)(C->cookie, nbytes); /* Clean up. */ mpool_network_read_cookie_free(C); /* Return the callback's status. */ return (rc); } /* The socket is ready for reading/writing. */ static int callback_buf(void * cookie) { struct network_read_cookie * C = cookie; size_t oplen; ssize_t len; /* Attempt to read/write data to/from the buffer. */ oplen = C->buflen - C->bufpos; len = recv(C->fd, C->buf + C->bufpos, oplen, 0); /* Failure? */ if (len == -1) { /* Was it really an error, or just a try-again? */ if ((errno == EAGAIN) || #if EAGAIN != EWOULDBLOCK (errno == EWOULDBLOCK) || #endif (errno == EINTR)) goto tryagain; /* Something went wrong. */ goto failed; } else if (len == 0) { /* The socket was shut down by the remote host. */ goto eof; } /* We processed some data. */ C->bufpos += (size_t)len; /* Do we need to keep going? */ if (C->bufpos < C->minlen) goto tryagain; /* Sanity-check: buffer position must fit into a ssize_t. */ assert(C->bufpos <= SSIZE_MAX); /* Invoke the callback and return. */ return (docallback(C, (ssize_t)C->bufpos)); tryagain: /* Reset the event. */ if (events_network_register(callback_buf, C, C->fd, EVENTS_NETWORK_OP_READ)) goto failed; /* Callback was reset. */ return (0); eof: /* Invoke the callback with an EOF status and return. */ return (docallback(C, 0)); failed: /* Invoke the callback with a failure status and return. */ return (docallback(C, -1)); } /** * network_read(fd, buf, buflen, minread, callback, cookie): * Asynchronously read up to ${buflen} bytes of data from ${fd} into ${buf}. * When at least ${minread} bytes have been read or on error, invoke * ${callback}(${cookie}, lenread), where lenread is 0 on EOF or -1 on error, * and the number of bytes read (between ${minread} and ${buflen} inclusive) * otherwise. Return a cookie which can be passed to network_read_cancel() in * order to cancel the read. */ void * network_read(int fd, uint8_t * buf, size_t buflen, size_t minread, int (* callback)(void *, ssize_t), void * cookie) { struct network_read_cookie * C; /* Make sure buflen is non-zero. */ assert(buflen != 0); /* Sanity-check: # bytes must fit into a ssize_t. */ assert(buflen <= SSIZE_MAX); /* Bake a cookie. */ if ((C = mpool_network_read_cookie_malloc()) == NULL) goto err0; C->callback = callback; C->cookie = cookie; C->fd = fd; C->buf = buf; C->buflen = buflen; C->minlen = minread; C->bufpos = 0; /* Register a callback for network readiness. */ if (events_network_register(callback_buf, C, C->fd, EVENTS_NETWORK_OP_READ)) goto err1; /* Success! */ return (C); err1: mpool_network_read_cookie_free(C); err0: /* Failure! */ return (NULL); } /** * network_read_cancel(cookie): * Cancel the buffer read for which the cookie ${cookie} was returned by * network_read(). Do not invoke the callback associated with the read. */ void network_read_cancel(void * cookie) { struct network_read_cookie * C = cookie; /* Kill the network event. */ events_network_cancel(C->fd, EVENTS_NETWORK_OP_READ); /* Free the cookie. */ mpool_network_read_cookie_free(C); } spiped-1.6.4/libcperciva/network/network_connect.c000644 001751 001751 00000017070 14650270210 023766 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include #include #include "events.h" #include "sock.h" #include "warnp.h" #include "network.h" struct connect_cookie { int (* callback)(void *, int); void * cookie; struct sock_addr * const * sas; const struct sock_addr * sa_b; struct timeval timeo; void * cookie_immediate; int s; int timeo_enabled; void * cookie_timeo; }; static int tryconnect(struct connect_cookie *); /* Invoke the upstream callback and clean up. */ static int docallback(void * cookie) { struct connect_cookie * C = cookie; int rc; /* Invoke the upstream callback. */ rc = (C->callback)(C->cookie, C->s); /* Free the cookie. */ free(C); /* Return status from upstream callback. */ return (rc); } /* An address failed to connect. */ static int dofailed(struct connect_cookie * C) { /* Close the socket which failed to connect. */ if (close(C->s)) warnp("close"); /* We don't have an open socket any more. */ C->s = -1; /* This address didn't work. */ C->sas++; /* Try other addresses until we run out of options. */ return (tryconnect(C)); } /* Callback when connect(2) succeeds or fails. */ static int callback_connect(void * cookie) { struct connect_cookie * C = cookie; int sockerr; socklen_t sockerrlen = sizeof(int); /* Stop waiting for the timer callback. */ if (C->cookie_timeo != NULL) { events_timer_cancel(C->cookie_timeo); C->cookie_timeo = NULL; } /* Did we succeed? */ if (getsockopt(C->s, SOL_SOCKET, SO_ERROR, &sockerr, &sockerrlen)) goto err1; if (sockerr != 0) return (dofailed(C)); /* * Perform the callback (this can be done here rather than being * scheduled as an immediate callback, as we're already running from * callback context). */ return (docallback(C)); err1: if (close(C->s)) warnp("close"); free(C); /* Fatal error! */ return (-1); } /* Callback when a timer expires. */ static int callback_timeo(void * cookie) { struct connect_cookie * C = cookie; /* We're not waiting for a timer callback any more. */ C->cookie_timeo = NULL; /* Stop listening for this socket. */ events_network_cancel(C->s, EVENTS_NETWORK_OP_WRITE); /* This connect attempt failed. */ return (dofailed(C)); } /* Try to launch a connection. Free the cookie on fatal errors. */ static int tryconnect(struct connect_cookie * C) { /* Try addresses until we find one which doesn't fail immediately. */ for (; C->sas[0] != NULL; C->sas++) { /* Can we try to connect to this address? */ if ((C->s = sock_connect_bind_nb(C->sas[0], C->sa_b)) != -1) break; } /* Did we run out of addresses to try? */ if (C->sas[0] == NULL) goto failed; /* If we've been asked to have a timeout, set one. */ if (C->timeo_enabled) { if ((C->cookie_timeo = events_timer_register(callback_timeo, C, &C->timeo)) == NULL) goto err1; } else { C->cookie_timeo = NULL; } /* Wait until this socket connects or fails to do so. */ if (events_network_register(callback_connect, C, C->s, EVENTS_NETWORK_OP_WRITE)) goto err2; /* Success! */ return (0); failed: /* Schedule a callback. */ if ((C->cookie_immediate = events_immediate_register(docallback, C, 0)) == NULL) goto err1; /* Failure successfully handled. */ return (0); err2: if (C->cookie_timeo != NULL) events_timer_cancel(C->cookie_timeo); err1: if ((C->s != -1) && close(C->s)) warnp("close"); free(C); /* Fatal error. */ return (-1); } /** * network_connect_internal(sas, sa_b, timeo, callback, cookie): * Iterate through the addresses in ${sas}, attempting to create and connect * a non-blocking socket. If ${timeo} is not NULL, wait a duration of at * most ${timeo} for each address which is being attempted. If ${sa_b} is * not NULL, then bind the socket to ${sa_b}. * * Once connected, invoke ${callback}(${cookie}, s) where s is the connected * socket; upon fatal error or if there are no addresses remaining to * attempt, invoke ${callback}(${cookie}, -1). Return a cookie which can be * passed to network_connect_cancel() in order to cancel the connection * attempt. */ static void * network_connect_internal(struct sock_addr * const * sas, const struct sock_addr * sa_b, const struct timeval * timeo, int (* callback)(void *, int), void * cookie) { struct connect_cookie * C; /* Bake a cookie. */ if ((C = malloc(sizeof(struct connect_cookie))) == NULL) goto err0; C->callback = callback; C->cookie = cookie; C->sas = sas; C->sa_b = sa_b; C->cookie_immediate = NULL; C->cookie_timeo = NULL; C->s = -1; /* Do we have a timeout? */ if (timeo != NULL) { memcpy(&C->timeo, timeo, sizeof(struct timeval)); C->timeo_enabled = 1; } else { C->timeo_enabled = 0; } /* Try to connect to the first address. */ if (tryconnect(C)) goto err0; /* Success! */ return (C); err0: /* Failure! */ return (NULL); } /** * network_connect(sas, callback, cookie): * Iterate through the addresses in ${sas}, attempting to create and connect * a non-blocking socket. Once connected, invoke ${callback}(${cookie}, s) * where s is the connected socket; upon fatal error or if there are no * addresses remaining to attempt, invoke ${callback}(${cookie}, -1). Return * a cookie which can be passed to network_connect_cancel() in order to cancel * the connection attempt. */ void * network_connect(struct sock_addr * const * sas, int (* callback)(void *, int), void * cookie) { /* Let network_connect_internal handle this. */ return (network_connect_internal(sas, NULL, NULL, callback, cookie)); } /** * network_connect_bind(sas, sa_b, callback, cookie): * Iterate through the addresses in ${sas}, attempting to create and connect * a non-blocking socket. If ${sa_b} is not NULL, bind the socket to ${sa_b} * immediately after creating it. Once connected, invoke * ${callback}(${cookie}, s) where s is the connected socket; upon fatal error * or if there are no addresses remaining to attempt, invoke * ${callback}(${cookie}, -1). Return a cookie which can be passed to * network_connect_cancel() in order to cancel the connection attempt. */ void * network_connect_bind(struct sock_addr * const * sas, const struct sock_addr * sa_b, int (* callback)(void *, int), void * cookie) { /* Let network_connect_internal handle this. */ return (network_connect_internal(sas, sa_b, NULL, callback, cookie)); } /** * network_connect_timeo(sas, timeo, callback, cookie): * Behave as network_connect(), but wait a duration of at most ${timeo} for * each address which is being attempted. */ void * network_connect_timeo(struct sock_addr * const * sas, const struct timeval * timeo, int (* callback)(void *, int), void * cookie) { /* Let network_connect_internal handle this. */ return (network_connect_internal(sas, NULL, timeo, callback, cookie)); } /** * network_connect_cancel(cookie): * Cancel the connection attempt for which ${cookie} was returned by * network_connect(). Do not invoke the associated callback. */ void network_connect_cancel(void * cookie) { struct connect_cookie * C = cookie; /* We should have either an immediate callback or a socket. */ assert((C->cookie_immediate != NULL) || (C->s != -1)); assert((C->cookie_immediate == NULL) || (C->s == -1)); /* Cancel any timer. */ if (C->cookie_timeo != NULL) events_timer_cancel(C->cookie_timeo); /* Cancel any immediate callback. */ if (C->cookie_immediate != NULL) events_immediate_cancel(C->cookie_immediate); /* Close any socket. */ if (C->s != -1) { events_network_cancel(C->s, EVENTS_NETWORK_OP_WRITE); if (close(C->s)) warnp("close"); } /* Free the cookie. */ free(C); } spiped-1.6.4/libcperciva/network/network_write.c000644 001751 001751 00000011523 14650270210 023464 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include #include #include #include "events.h" #include "mpool.h" #include "warnp.h" #include "network.h" /** * POSIX.1-2008 requires that MSG_NOSIGNAL be defined as a flag for send(2) * which has the effect of preventing SIGPIPE from being raised when writing * to a descriptor which has been shut down. Unfortunately there are some * platforms which are not POSIX.1-2008 compliant; we provide a workaround * (-DPOSIXFAIL_MSG_NOSIGNAL) which instead blocks the SIGPIPE signal on such * platforms. * * (This workaround could be used automatically, but requiring that it be * explicitly enabled helps to get platforms fixed.) */ #ifdef POSIXFAIL_MSG_NOSIGNAL #ifndef MSG_NOSIGNAL #define MSG_NOSIGNAL 0 #endif #endif struct network_write_cookie { int (* callback)(void *, ssize_t); void * cookie; int fd; const uint8_t * buf; size_t buflen; size_t minlen; size_t bufpos; }; MPOOL(network_write_cookie, struct network_write_cookie, 16); /* Invoke the callback, clean up, and return the callback's status. */ static int docallback(struct network_write_cookie * C, ssize_t nbytes) { int rc; /* Invoke the callback. */ rc = (C->callback)(C->cookie, nbytes); /* Clean up. */ mpool_network_write_cookie_free(C); /* Return the callback's status. */ return (rc); } /* The socket is ready for reading/writing. */ static int callback_buf(void * cookie) { struct network_write_cookie * C = cookie; size_t oplen; ssize_t len; #ifdef POSIXFAIL_MSG_NOSIGNAL void (* oldsig)(int); int saved_errno; #endif /* If we don't have MSG_NOSIGNAL, ignore SIGPIPE. */ #ifdef POSIXFAIL_MSG_NOSIGNAL if ((oldsig = signal(SIGPIPE, SIG_IGN)) == SIG_ERR) { warnp("signal(SIGPIPE)"); goto failed; } #endif /* Attempt to read/write data to/from the buffer. */ oplen = C->buflen - C->bufpos; len = send(C->fd, C->buf + C->bufpos, oplen, MSG_NOSIGNAL); /* We should never see a send length of zero. */ assert(len != 0); /* If we ignored SIGPIPE, restore the old handler. */ #ifdef POSIXFAIL_MSG_NOSIGNAL /* Save errno in case it gets clobbered by signal(). */ saved_errno = errno; if (signal(SIGPIPE, oldsig) == SIG_ERR) { warnp("signal(SIGPIPE)"); goto failed; } /* Restore saved errno. */ errno = saved_errno; #endif /* Failure? */ if (len == -1) { /* Was it really an error, or just a try-again? */ if ((errno == EAGAIN) || #if EAGAIN != EWOULDBLOCK (errno == EWOULDBLOCK) || #endif (errno == EINTR)) goto tryagain; /* Something went wrong. */ goto failed; } /* We processed some data. */ C->bufpos += (size_t)len; /* Do we need to keep going? */ if (C->bufpos < C->minlen) goto tryagain; /* Sanity-check: buffer position must fit into a ssize_t. */ assert(C->bufpos <= SSIZE_MAX); /* Invoke the callback and return. */ return (docallback(C, (ssize_t)C->bufpos)); tryagain: /* Reset the event. */ if (events_network_register(callback_buf, C, C->fd, EVENTS_NETWORK_OP_WRITE)) goto failed; /* Callback was reset. */ return (0); failed: /* Invoke the callback with a failure status and return. */ return (docallback(C, -1)); } /** * network_write(fd, buf, buflen, minwrite, callback, cookie): * Asynchronously write up to ${buflen} bytes of data from ${buf} to ${fd}. * When at least ${minwrite} bytes have been written or on error, invoke * ${callback}(${cookie}, lenwrit), where lenwrit is -1 on error and the * number of bytes written (between ${minwrite} and ${buflen} inclusive) * otherwise. Return a cookie which can be passed to network_write_cancel() in * order to cancel the write. */ void * network_write(int fd, const uint8_t * buf, size_t buflen, size_t minwrite, int (* callback)(void *, ssize_t), void * cookie) { struct network_write_cookie * C; /* Make sure buflen is non-zero. */ assert(buflen != 0); /* Sanity-check: # bytes must fit into a ssize_t. */ assert(buflen <= SSIZE_MAX); /* Bake a cookie. */ if ((C = mpool_network_write_cookie_malloc()) == NULL) goto err0; C->callback = callback; C->cookie = cookie; C->fd = fd; C->buf = buf; C->buflen = buflen; C->minlen = minwrite; C->bufpos = 0; /* Register a callback for network readiness. */ if (events_network_register(callback_buf, C, C->fd, EVENTS_NETWORK_OP_WRITE)) goto err1; /* Success! */ return (C); err1: mpool_network_write_cookie_free(C); err0: /* Failure! */ return (NULL); } /** * network_write_cancel(cookie): * Cancel the buffer write for which the cookie ${cookie} was returned by * network_write(). Do not invoke the callback associated with the write. */ void network_write_cancel(void * cookie) { struct network_write_cookie * C = cookie; /* Kill the network event. */ events_network_cancel(C->fd, EVENTS_NETWORK_OP_WRITE); /* Free the cookie. */ mpool_network_write_cookie_free(C); } spiped-1.6.4/libcperciva/network/network_accept.c000644 001751 001751 00000004503 13762775424 023615 0ustar00cpercivacperciva000000 000000 #include #include #include #include "events.h" #include "network.h" struct accept_cookie { int (* callback)(void *, int); void * cookie; int fd; }; /* Accept the connection and invoke the callback. */ static int callback_accept(void * cookie) { struct accept_cookie * C = cookie; int s; int rc; /* Attempt to accept a new connection. */ if ((s = accept(C->fd, NULL, NULL)) == -1) { /* If a connection isn't available, reset the callback. */ if ((errno == EAGAIN) || #if EAGAIN != EWOULDBLOCK (errno == EWOULDBLOCK) || #endif (errno == ECONNABORTED) || (errno == EINTR)) goto tryagain; } /* Call the upstream callback. */ rc = (C->callback)(C->cookie, s); /* Free the cookie. */ free(C); /* Return status from upstream callback. */ return (rc); tryagain: /* Reset the callback. */ return (events_network_register(callback_accept, C, C->fd, EVENTS_NETWORK_OP_READ)); } /** * network_accept(fd, callback, cookie): * Asynchronously accept a connection on the socket ${fd}, which must be * already marked as listening and non-blocking. When a connection has been * accepted or an error occurs, invoke ${callback}(${cookie}, s) where s is * the accepted connection or -1 on error. Return a cookie which can be * passed to network_accept_cancel() in order to cancel the accept. */ void * network_accept(int fd, int (* callback)(void *, int), void * cookie) { struct accept_cookie * C; /* Bake a cookie. */ if ((C = malloc(sizeof(struct accept_cookie))) == NULL) goto err0; C->callback = callback; C->cookie = cookie; C->fd = fd; /* * Register a network event. A connection arriving on a listening * socket is treated by select(2) as the socket becoming readable. */ if (events_network_register(callback_accept, C, C->fd, EVENTS_NETWORK_OP_READ)) goto err1; /* Success! */ return (C); err1: free(C); err0: /* Failure! */ return (NULL); } /** * network_accept_cancel(cookie): * Cancel the connection accept for which the cookie ${cookie} was returned * by network_accept(). Do not invoke the callback associated with the accept. */ void network_accept_cancel(void * cookie) { struct accept_cookie * C = cookie; /* Cancel the network event. */ events_network_cancel(C->fd, EVENTS_NETWORK_OP_READ); /* Free the cookie. */ free(C); } spiped-1.6.4/libcperciva/network/network.h000644 001751 001751 00000010214 14650270210 022253 0ustar00cpercivacperciva000000 000000 #ifndef NETWORK_H_ #define NETWORK_H_ #include #include #include #include /* Opaque address structure. */ struct sock_addr; /** * network_accept(fd, callback, cookie): * Asynchronously accept a connection on the socket ${fd}, which must be * already marked as listening and non-blocking. When a connection has been * accepted or an error occurs, invoke ${callback}(${cookie}, s) where s is * the accepted connection or -1 on error. Return a cookie which can be * passed to network_accept_cancel() in order to cancel the accept. */ void * network_accept(int, int (*)(void *, int), void *); /** * network_accept_cancel(cookie): * Cancel the connection accept for which the cookie ${cookie} was returned * by network_accept(). Do not invoke the callback associated with the accept. */ void network_accept_cancel(void *); /** * network_connect(sas, callback, cookie): * Iterate through the addresses in ${sas}, attempting to create and connect * a non-blocking socket. Once connected, invoke ${callback}(${cookie}, s) * where s is the connected socket; upon fatal error or if there are no * addresses remaining to attempt, invoke ${callback}(${cookie}, -1). Return * a cookie which can be passed to network_connect_cancel() in order to cancel * the connection attempt. */ void * network_connect(struct sock_addr * const *, int (*)(void *, int), void *); /** * network_connect_bind(sas, sa_b, callback, cookie): * Iterate through the addresses in ${sas}, attempting to create and connect * a non-blocking socket. If ${sa_b} is not NULL, bind the socket to ${sa_b} * immediately after creating it. Once connected, invoke * ${callback}(${cookie}, s) where s is the connected socket; upon fatal error * or if there are no addresses remaining to attempt, invoke * ${callback}(${cookie}, -1). Return a cookie which can be passed to * network_connect_cancel() in order to cancel the connection attempt. */ void * network_connect_bind(struct sock_addr * const *, const struct sock_addr *, int (*)(void *, int), void *); /** * network_connect_timeo(sas, timeo, callback, cookie): * Behave as network_connect(), but wait a duration of at most ${timeo} for * each address which is being attempted. */ void * network_connect_timeo(struct sock_addr * const *, const struct timeval *, int (*)(void *, int), void *); /** * network_connect_cancel(cookie): * Cancel the connection attempt for which ${cookie} was returned by * network_connect(). Do not invoke the associated callback. */ void network_connect_cancel(void *); /** * network_read(fd, buf, buflen, minread, callback, cookie): * Asynchronously read up to ${buflen} bytes of data from ${fd} into ${buf}. * When at least ${minread} bytes have been read or on error, invoke * ${callback}(${cookie}, lenread), where lenread is 0 on EOF or -1 on error, * and the number of bytes read (between ${minread} and ${buflen} inclusive) * otherwise. Return a cookie which can be passed to network_read_cancel() in * order to cancel the read. */ void * network_read(int, uint8_t *, size_t, size_t, int (*)(void *, ssize_t), void *); /** * network_read_cancel(cookie): * Cancel the buffer read for which the cookie ${cookie} was returned by * network_read(). Do not invoke the callback associated with the read. */ void network_read_cancel(void *); /** * network_write(fd, buf, buflen, minwrite, callback, cookie): * Asynchronously write up to ${buflen} bytes of data from ${buf} to ${fd}. * When at least ${minwrite} bytes have been written or on error, invoke * ${callback}(${cookie}, lenwrit), where lenwrit is -1 on error and the * number of bytes written (between ${minwrite} and ${buflen} inclusive) * otherwise. Return a cookie which can be passed to network_write_cancel() in * order to cancel the write. */ void * network_write(int, const uint8_t *, size_t, size_t, int (*)(void *, ssize_t), void *); /** * network_write_cancel(cookie): * Cancel the buffer write for which the cookie ${cookie} was returned by * network_write(). Do not invoke the callback associated with the write. */ void network_write_cancel(void *); #endif /* !NETWORK_H_ */ spiped-1.6.4/libcperciva/events/events.c000644 001751 001751 00000012303 14650270210 021675 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include "mpool.h" #include "events.h" #include "events_internal.h" /* Event structure. */ struct eventrec { int (* func)(void *); void * cookie; }; MPOOL(eventrec, struct eventrec, 4096); /* Zero timeval, for use with non-blocking event runs. */ static const struct timeval tv_zero = {0, 0}; /* We want to interrupt a running event loop. */ static volatile sig_atomic_t interrupt_requested = 0; /** * events_mkrec(func, cookie): * Package ${func}, ${cookie} into a struct eventrec. */ struct eventrec * events_mkrec(int (* func)(void *), void * cookie) { struct eventrec * r; /* Allocate structure. */ if ((r = mpool_eventrec_malloc()) == NULL) goto err0; /* Initialize. */ r->func = func; r->cookie = cookie; /* Success! */ return (r); err0: /* Failure! */ return (NULL); } /** * events_freerec(r): * Free the eventrec ${r}. */ void events_freerec(struct eventrec * r) { mpool_eventrec_free(r); } /* Do an event. This makes events_run cleaner. */ static inline int doevent(struct eventrec * r) { int rc; /* Invoke the callback. */ rc = (r->func)(r->cookie); /* Free the event record. */ mpool_eventrec_free(r); /* Return the status code from the callback. */ return (rc); } /** * events_run(void): * Run events. Events registered via events_immediate_register() will be run * first, in order of increasing ${prio} values; then events associated with * ready sockets registered via events_network_register(); finally, events * associated with expired timers registered via events_timer_register() will * be run. If any event function returns a non-zero result, no further events * will be run and said non-zero result will be returned; on error, * -1 will be returned. May be interrupted by events_interrupt(), in which * case 0 will be returned. If there are runnable events, events_run() is * guaranteed to run at least one; but it may return while there are still * more runnable events. */ static int events_run_internal(void) { struct eventrec * r; struct timeval * tv; struct timeval tv2; int rc = 0; /* If we have any immediate events, process them and return. */ if ((r = events_immediate_get()) != NULL) { while (r != NULL) { /* Process the event. */ if ((rc = doevent(r)) != 0) goto done; /* Interrupt loop if requested. */ if (interrupt_requested) goto done; /* Get the next event. */ r = events_immediate_get(); } /* We've processed at least one event; time to return. */ goto done; } /* * Figure out the maximum duration to block, and wait up to that * duration for network events to become available. */ if (events_timer_min(&tv)) goto err0; if (events_network_select(tv, &interrupt_requested)) goto err1; free(tv); /* * Check for available immediate events, network events, and timer * events, in that order of priority; exit only when no more events * are available or when interrupted. */ do { /* Interrupt loop if requested. */ if (interrupt_requested) goto done; /* Run an immediate event, if one is available. */ if ((r = events_immediate_get()) != NULL) { if ((rc = doevent(r)) != 0) goto done; continue; } /* Run a network event, if one is available. */ if ((r = events_network_get()) != NULL) { if ((rc = doevent(r)) != 0) goto done; continue; } /* Check if any new network events are available. */ memcpy(&tv2, &tv_zero, sizeof(struct timeval)); if (events_network_select(&tv2, &interrupt_requested)) goto err0; if ((r = events_network_get()) != NULL) { if ((rc = doevent(r)) != 0) goto done; continue; } /* Run a timer event, if one is available. */ if (events_timer_get(&r)) goto err0; if (r != NULL) { if ((rc = doevent(r)) != 0) goto done; continue; } /* No events available. */ break; } while (1); done: /* Success! */ return (rc); err1: free(tv); err0: /* Failure! */ return (-1); } /* Wrapper function for events_run to reset interrupt_requested. */ int events_run(void) { int rc; /* Call the real function. */ rc = events_run_internal(); /* Reset interrupt_requested after quitting the loop. */ interrupt_requested = 0; /* Return status. */ return (rc); } /** * events_spin(done): * Call events_run() until ${done} is non-zero (and return 0), an error occurs * (and return -1), or a callback returns a non-zero status (and return the * status code from the callback). May be interrupted by events_interrupt() * (and return 0). */ int events_spin(const int * done) { int rc = 0; /* Loop until we're done or have a non-zero status. */ while ((done[0] == 0) && (rc == 0) && (interrupt_requested == 0)) { /* Run events. */ rc = events_run_internal(); } /* Reset interrupt_requested after quitting the loop. */ interrupt_requested = 0; /* Return status code. */ return (rc); } /** * events_interrupt(void): * Halt the event loop after finishing the current event. This function can * be safely called from within a signal handler. */ void events_interrupt(void) { /* Interrupt the event loop. */ interrupt_requested = 1; } /** * events_shutdown(void): * Deprecated function; does nothing. */ void events_shutdown(void) { } spiped-1.6.4/libcperciva/events/events_timer.c000644 001751 001751 00000013327 14650270210 023104 0ustar00cpercivacperciva000000 000000 #include #include #include #include "monoclock.h" #include "timerqueue.h" #include "events.h" #include "events_internal.h" struct timerrec { struct eventrec * r; void * cookie; struct timeval tv_orig; }; /* This also tracks whether we've initialized the atexit function. */ static struct timerqueue * Q = NULL; static void events_timer_shutdown(void); /* Set tv := + tdelta. */ static int gettimeout(struct timeval * tv, const struct timeval * tdelta) { if (monoclock_get(tv)) goto err0; tv->tv_sec += tdelta->tv_sec; if ((tv->tv_usec += tdelta->tv_usec) >= 1000000) { tv->tv_usec -= 1000000; tv->tv_sec += 1; } /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * events_timer_register(func, cookie, timeo): * Register ${func}(${cookie}) to be run ${timeo} in the future. Return a * cookie which can be passed to events_timer_cancel() or events_timer_reset(). */ void * events_timer_register(int (* func)(void *), void * cookie, const struct timeval * timeo) { struct eventrec * r; struct timerrec * t; struct timeval tv; /* Create the timer queue if it doesn't exist yet. */ if (Q == NULL) { if ((Q = timerqueue_init()) == NULL) goto err0; /* Clean up the timer queue at exit. */ if (atexit(events_timer_shutdown)) goto err0; } /* Bundle into an eventrec record. */ if ((r = events_mkrec(func, cookie)) == NULL) goto err0; /* Create a timer record. */ if ((t = malloc(sizeof(struct timerrec))) == NULL) goto err1; t->r = r; memcpy(&t->tv_orig, timeo, sizeof(struct timeval)); /* Compute the absolute timeout. */ if (gettimeout(&tv, &t->tv_orig)) goto err2; /* Add this to the timer queue. */ if ((t->cookie = timerqueue_add(Q, &tv, t)) == NULL) goto err2; /* Success! */ return (t); err2: free(t); err1: events_freerec(r); err0: /* Failure! */ return (NULL); } /** * events_timer_register_double(func, cookie, timeo): * As events_timer_register(), but ${timeo} is a double-precision * floating-point value specifying a number of seconds. */ void * events_timer_register_double(int (* func)(void *), void * cookie, double timeo) { struct timeval tv; /* Convert timeo to a struct timeval. */ tv.tv_sec = (time_t)timeo; tv.tv_usec = (suseconds_t)((timeo - (double)tv.tv_sec) * 1000000.0); /* Schedule the timeout. */ return (events_timer_register(func, cookie, &tv)); } /** * events_timer_cancel(cookie): * Cancel the timer for which the cookie ${cookie} was returned by * events_timer_register(). */ void events_timer_cancel(void * cookie) { struct timerrec * t = cookie; /* Remove from the timer queue. */ timerqueue_delete(Q, t->cookie); /* Free the eventrec and timer records. */ events_freerec(t->r); free(t); } /** * events_timer_reset(cookie): * Reset the timer for which the cookie ${cookie} was returned by * events_timer_register() to its initial value. */ int events_timer_reset(void * cookie) { struct timerrec * t = cookie; struct timeval tv; /* Compute the new timeout. */ if (gettimeout(&tv, &t->tv_orig)) goto err0; /* Adjust the timer. */ timerqueue_increase(Q, t->cookie, &tv); /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * events_timer_min(timeo): * Return via ${timeo} a pointer to the minimum time which must be waited * before a timer will expire; or to NULL if there are no timers. The caller * is responsible for freeing the returned pointer. */ int events_timer_min(struct timeval ** timeo) { struct timeval tnow; const struct timeval * tv; /* If we have no queue, we have no timers; return NULL. */ if (Q == NULL) { *timeo = NULL; goto done; } /* Get the minimum timer from the queue. */ tv = timerqueue_getmin(Q); /* If there are no timers, return NULL. */ if (tv == NULL) { *timeo = NULL; goto done; } /* Allocate space for holding the returned timeval. */ if ((*timeo = malloc(sizeof(struct timeval))) == NULL) goto err0; /* Get the current time... */ if (monoclock_get(&tnow)) goto err1; /* ... and compare it to the minimum timer. */ if ((tnow.tv_sec > tv->tv_sec) || ((tnow.tv_sec == tv->tv_sec) && (tnow.tv_usec > tv->tv_usec))) { /* The timer has already expired, so return zero. */ (*timeo)->tv_sec = 0; (*timeo)->tv_usec = 0; } else { /* Compute the difference. */ (*timeo)->tv_sec = tv->tv_sec - tnow.tv_sec; (*timeo)->tv_usec = tv->tv_usec - tnow.tv_usec; if (tv->tv_usec < tnow.tv_usec) { (*timeo)->tv_usec += 1000000; (*timeo)->tv_sec -= 1; } } done: /* Success! */ return (0); err1: free(*timeo); err0: /* Failure! */ return (-1); } /** * events_timer_get(r): * Return via ${r} a pointer to an eventrec structure corresponding to an * expired timer, and delete said timer; or to NULL if there are no expired * timers. The caller is responsible for freeing the returned pointer. */ int events_timer_get(struct eventrec ** r) { struct timeval tnow; struct timerrec * t; /* If we have no queue, we have no timers; return NULL. */ if (Q == NULL) { *r = NULL; goto done; } /* Get current time. */ if (monoclock_get(&tnow)) goto err0; /* Get an expired timer, if there is one. */ t = timerqueue_getptr(Q, &tnow); /* If there is an expired timer... */ if (t != NULL) { /* ... pass back the eventrec and free the timer. */ *r = t->r; free(t); } else { /* Otherwise, return NULL. */ *r = NULL; } done: /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * events_timer_shutdown(void): * Clean up and free memory. This should run automatically via atexit. */ static void events_timer_shutdown(void) { /* If we have a queue and it is empty, free it. */ if ((Q != NULL) && (timerqueue_getmin(Q) == NULL)) { timerqueue_free(Q); Q = NULL; } } spiped-1.6.4/libcperciva/events/events_immediate.c000644 001751 001751 00000007321 14650270210 023717 0ustar00cpercivacperciva000000 000000 #include #include #include "mpool.h" #include "queue.h" #include "events.h" #include "events_internal.h" struct eventq { struct eventrec * r; TAILQ_ENTRY(eventq) entries; int prio; }; MPOOL(eventq, struct eventq, 4096); /* First nodes in the linked lists. */ static TAILQ_HEAD(tailhead, eventq) heads[32] = { TAILQ_HEAD_INITIALIZER(heads[0]), TAILQ_HEAD_INITIALIZER(heads[1]), TAILQ_HEAD_INITIALIZER(heads[2]), TAILQ_HEAD_INITIALIZER(heads[3]), TAILQ_HEAD_INITIALIZER(heads[4]), TAILQ_HEAD_INITIALIZER(heads[5]), TAILQ_HEAD_INITIALIZER(heads[6]), TAILQ_HEAD_INITIALIZER(heads[7]), TAILQ_HEAD_INITIALIZER(heads[8]), TAILQ_HEAD_INITIALIZER(heads[9]), TAILQ_HEAD_INITIALIZER(heads[10]), TAILQ_HEAD_INITIALIZER(heads[11]), TAILQ_HEAD_INITIALIZER(heads[12]), TAILQ_HEAD_INITIALIZER(heads[13]), TAILQ_HEAD_INITIALIZER(heads[14]), TAILQ_HEAD_INITIALIZER(heads[15]), TAILQ_HEAD_INITIALIZER(heads[16]), TAILQ_HEAD_INITIALIZER(heads[17]), TAILQ_HEAD_INITIALIZER(heads[18]), TAILQ_HEAD_INITIALIZER(heads[19]), TAILQ_HEAD_INITIALIZER(heads[20]), TAILQ_HEAD_INITIALIZER(heads[21]), TAILQ_HEAD_INITIALIZER(heads[22]), TAILQ_HEAD_INITIALIZER(heads[23]), TAILQ_HEAD_INITIALIZER(heads[24]), TAILQ_HEAD_INITIALIZER(heads[25]), TAILQ_HEAD_INITIALIZER(heads[26]), TAILQ_HEAD_INITIALIZER(heads[27]), TAILQ_HEAD_INITIALIZER(heads[28]), TAILQ_HEAD_INITIALIZER(heads[29]), TAILQ_HEAD_INITIALIZER(heads[30]), TAILQ_HEAD_INITIALIZER(heads[31]) }; /* For i < minq, heads[i] == NULL. */ static int minq = 32; /** * events_immediate_register(func, cookie, prio): * Register ${func}(${cookie}) to be run the next time events_run() is * invoked, after immediate events with smaller ${prio} values and before * events with larger ${prio} values. The value ${prio} must be in the range * [0, 31]. Return a cookie which can be passed to events_immediate_cancel(). */ void * events_immediate_register(int (* func)(void *), void * cookie, int prio) { struct eventrec * r; struct eventq * q; /* Sanity check. */ assert((prio >= 0) && (prio < 32)); /* Bundle into an eventrec record. */ if ((r = events_mkrec(func, cookie)) == NULL) goto err0; /* Create a linked list node. */ if ((q = mpool_eventq_malloc()) == NULL) goto err1; q->r = r; q->prio = prio; /* Add to the queue. */ TAILQ_INSERT_TAIL(&heads[prio], q, entries); /* Update minq if necessary. */ if (prio < minq) minq = prio; /* Success! */ return (q); err1: events_freerec(r); err0: /* Failure! */ return (NULL); } /** * events_immediate_cancel(cookie): * Cancel the immediate event for which the cookie ${cookie} was returned by * events_immediate_register(). */ void events_immediate_cancel(void * cookie) { struct eventq * q = cookie; int prio = q->prio; /* Remove it from the list. */ TAILQ_REMOVE(&heads[prio], q, entries); /* Free the eventrec. */ events_freerec(q->r); /* Return the node to the malloc pool. */ mpool_eventq_free(q); } /** * events_immediate_get(void): * Remove and return an eventrec structure from the immediate event queue, * or return NULL if there are no such events. The caller is responsible for * freeing the returned memory. */ struct eventrec * events_immediate_get(void) { struct eventq * q; struct eventrec * r; /* Advance past priorities which have no events. */ while ((minq < 32) && (TAILQ_EMPTY(&heads[minq]))) minq++; /* Are there any events? */ if (minq == 32) return (NULL); /* * Remove the first node from the highest priority non-empty linked * list. */ q = TAILQ_FIRST(&heads[minq]); TAILQ_REMOVE(&heads[minq], q, entries); /* Extract the eventrec. */ r = q->r; /* Return the node to the malloc pool. */ mpool_eventq_free(q); /* Return the eventrec. */ return (r); } spiped-1.6.4/libcperciva/events/events_internal.h000644 001751 001751 00000005022 14650270210 023576 0ustar00cpercivacperciva000000 000000 #ifndef EVENTS_INTERNAL_H_ #define EVENTS_INTERNAL_H_ #include #include /* Opaque event structure. */ struct eventrec; /** * events_mkrec(func, cookie): * Package ${func}, ${cookie} into a struct eventrec. */ struct eventrec * events_mkrec(int (*)(void *), void *); /** * events_freerec(r): * Free the eventrec ${r}. */ void events_freerec(struct eventrec *); /** * events_immediate_get(void): * Remove and return an eventrec structure from the immediate event queue, * or return NULL if there are no such events. The caller is responsible for * freeing the returned memory. */ struct eventrec * events_immediate_get(void); /** * events_network_select(tv, interrupt_requested): * Check for socket readiness events, waiting up to ${tv} time if there are * no sockets immediately ready, or indefinitely if ${tv} is NULL. The value * stored in ${tv} may be modified. If ${*interrupt_requested} is non-zero * and a signal is received, exit. */ int events_network_select(const struct timeval *, const volatile sig_atomic_t *); /** * events_network_selectstats_startclock(void): * Start the inter-select duration clock: There is a selectable event. */ void events_network_selectstats_startclock(void); /** * events_network_selectstats_stopclock(void): * Stop the inter-select duration clock: There are no selectable events. */ void events_network_selectstats_stopclock(void); /** * events_network_selectstats_select(void): * Update inter-select duration statistics in relation to an upcoming * select(2) call. */ void events_network_selectstats_select(void); /** * events_network_get(void): * Find a socket readiness event which was identified by a previous call to * events_network_select, and return it as an eventrec structure; or return * NULL if there are no such events available. The caller is responsible for * freeing the returned memory. */ struct eventrec * events_network_get(void); /** * events_timer_min(timeo): * Return via ${timeo} a pointer to the minimum time which must be waited * before a timer will expire; or to NULL if there are no timers. The caller * is responsible for freeing the returned pointer. */ int events_timer_min(struct timeval **); /** * events_timer_get(r): * Return via ${r} a pointer to an eventrec structure corresponding to an * expired timer, and delete said timer; or to NULL if there are no expired * timers. The caller is responsible for freeing the returned pointer. */ int events_timer_get(struct eventrec **); #endif /* !EVENTS_INTERNAL_H_ */ spiped-1.6.4/libcperciva/events/events_network_selectstats.c000644 001751 001751 00000004071 14650270210 026067 0ustar00cpercivacperciva000000 000000 #include #include "monoclock.h" #include "events.h" #include "events_internal.h" /* Time when inter-select duration clock started. */ static struct timeval st; static int running = 0; /* Statistics on inter-select durations. */ static double N = 0.0; static double mu = 0.0; static double M2 = 0.0; static double max = 0.0; /** * events_network_selectstats_startclock(void): * Start the inter-select duration clock: There is a selectable event. */ void events_network_selectstats_startclock(void) { /* If the clock is already running, return silently. */ if (running) return; /* Get the current time; return silently on error. */ if (monoclock_get(&st)) return; /* The clock is now running. */ running = 1; } /** * events_network_selectstats_stopclock(void): * Stop the inter-select duration clock: There are no selectable events. */ void events_network_selectstats_stopclock(void) { /* The clock is no longer running. */ running = 0; } /** * events_network_selectstats_select(void): * Update inter-select duration statistics in relation to an upcoming * select(2) call. */ void events_network_selectstats_select(void) { struct timeval tnow; double t, d; /* If the clock is not running, return silently. */ if (!running) return; /* If we can't get the current time, fail silently. */ if (monoclock_get(&tnow)) goto done; /* Compute inter-select duration in seconds. */ t = timeval_diff(st, tnow); /* Adjust statistics. We track running mean, variance * N, and max. */ N += 1.0; d = t - mu; mu += d / N; M2 += d * (t - mu); if (max < t) max = t; done: /* The clock is no longer running. */ running = 0; } /** * events_network_selectstats(N, mu, va, max): * Return statistics on the inter-select durations since the last time this * function was called. */ void events_network_selectstats(double * _n, double * _mu, double * _va, double * _max) { /* Copy statistics out. */ *_n = N; *_mu = mu; if (N > 1.0) *_va = M2 / (N - 1.0); else *_va = 0.0; *_max = max; /* Zero statistics. */ N = mu = M2 = max = 0.0; } spiped-1.6.4/libcperciva/events/events.h000644 001751 001751 00000007633 14650270210 021714 0ustar00cpercivacperciva000000 000000 #ifndef EVENTS_H_ #define EVENTS_H_ #include /** * events_immediate_register(func, cookie, prio): * Register ${func}(${cookie}) to be run the next time events_run() is * invoked, after immediate events with smaller ${prio} values and before * events with larger ${prio} values. The value ${prio} must be in the range * [0, 31]. Return a cookie which can be passed to events_immediate_cancel(). */ void * events_immediate_register(int (*)(void *), void *, int); /** * events_immediate_cancel(cookie): * Cancel the immediate event for which the cookie ${cookie} was returned by * events_immediate_register(). */ void events_immediate_cancel(void *); /* "op" parameter to events_network_register(). */ #define EVENTS_NETWORK_OP_READ 0 #define EVENTS_NETWORK_OP_WRITE 1 /** * events_network_register(func, cookie, s, op): * Register ${func}(${cookie}) to be run when socket ${s} is ready for * reading or writing depending on whether ${op} is EVENTS_NETWORK_OP_READ or * EVENTS_NETWORK_OP_WRITE. If there is already an event registration for * this ${s}/${op} pair, errno will be set to EEXIST and the function will * fail. */ int events_network_register(int (*)(void *), void *, int, int); /** * events_network_cancel(s, op): * Cancel the event registered for the socket/operation pair ${s}/${op}. If * there is no such registration, errno will be set to ENOENT and the * function will fail. */ int events_network_cancel(int, int); /** * events_network_selectstats(N, mu, va, max): * Return statistics on the inter-select durations since the last time this * function was called. */ void events_network_selectstats(double *, double *, double *, double *); /** * events_timer_register(func, cookie, timeo): * Register ${func}(${cookie}) to be run ${timeo} in the future. Return a * cookie which can be passed to events_timer_cancel() or events_timer_reset(). */ void * events_timer_register(int (*)(void *), void *, const struct timeval *); /** * events_timer_register_double(func, cookie, timeo): * As events_timer_register(), but ${timeo} is a double-precision * floating-point value specifying a number of seconds. */ void * events_timer_register_double(int (*)(void *), void *, double); /** * events_timer_cancel(cookie): * Cancel the timer for which the cookie ${cookie} was returned by * events_timer_register(). */ void events_timer_cancel(void *); /** * events_timer_reset(cookie): * Reset the timer for which the cookie ${cookie} was returned by * events_timer_register() to its initial value. */ int events_timer_reset(void *); /** * events_run(void): * Run events. Events registered via events_immediate_register() will be run * first, in order of increasing ${prio} values; then events associated with * ready sockets registered via events_network_register(); finally, events * associated with expired timers registered via events_timer_register() will * be run. If any event function returns a non-zero result, no further events * will be run and said non-zero result will be returned; on error, * -1 will be returned. May be interrupted by events_interrupt(), in which * case 0 will be returned. If there are runnable events, events_run() is * guaranteed to run at least one; but it may return while there are still * more runnable events. */ int events_run(void); /** * events_spin(done): * Call events_run() until ${done} is non-zero (and return 0), an error occurs * (and return -1), or a callback returns a non-zero status (and return the * status code from the callback). May be interrupted by events_interrupt() * (and return 0). */ int events_spin(const int *); /** * events_interrupt(void): * Halt the event loop after finishing the current event. This function can * be safely called from within a signal handler. */ void events_interrupt(void); /** * events_shutdown(void): * Deprecated function; does nothing. */ void events_shutdown(void); #endif /* !EVENTS_H_ */ spiped-1.6.4/libcperciva/events/events_network.c000644 001751 001751 00000027722 14650270210 023461 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include #include #include #include #include #include "ctassert.h" #include "elasticarray.h" #include "warnp.h" #include "events.h" #include "events_internal.h" /* * Sanity checks on the nfds_t type: POSIX simply says "an unsigned integer * type used for the number of file descriptors", but it doesn't make sense * for it to be larger than size_t unless there's an undocumented limit on * the number of descriptors which can be polled (since poll takes an array, * the size of which must fit into a size_t); and nfds_t should be able to * store the value INT_MAX + 1 (in case every possible file descriptor is in * use and being polled for). */ CTASSERT((nfds_t)(-1) <= (size_t)(-1)); CTASSERT((nfds_t)((size_t)(INT_MAX) + 1) == (size_t)(INT_MAX) + 1); /* Structure for holding readability and writability events for a socket. */ struct socketrec { struct eventrec * reader; struct eventrec * writer; size_t pollpos; }; /* List of sockets. */ ELASTICARRAY_DECL(SOCKETLIST, socketlist, struct socketrec); static SOCKETLIST S = NULL; /* Poll structures. */ static struct pollfd * fds; /* Number of poll structures allocated in array. */ static size_t fds_alloc; /* Number of poll structures initialized. */ static size_t nfds; /* Position to which events_network_get has scanned in *fds. */ static size_t fdscanpos; /** * Invariants: * 1. Initialized entries in S and fds point to each other: * S[i].pollpos < nfds ==> fds[S[i].pollpos].fd == i * j < nfds ==> S[fds[j].fd].pollpos == j * 2. Descriptors with events registered are in the right place: * S[i].reader != NULL ==> S[i].pollpos < nfds * S[i].writer != NULL ==> S[i].pollpos < nfds * 3. Descriptors without events registered aren't in the way: * (S[i].reader == NULL && S[i].writer == NULL) ==> S[i].pollpos == -1 * 4. Descriptors with events registered have the right masks: * S[i].reader != NULL <==> (fds[S[i].pollpos].events & POLLIN) != 0 * S[i].writer != NULL <==> (fds[S[i].pollpos].events & POLLOUT) != 0 * 5. We don't have events ready which we don't want: * (fds[j].revents & (POLLIN | POLLOUT) & (~fds[j].events)) == 0 * 6. Returned events are in position to be scanned later: * fds[j].revents != 0 ==> f < fdscanpos. */ static void events_network_shutdown(void); /* Initialize data structures if we haven't already done so. */ static int init(void) { /* If we're already initialized, do nothing. */ if (S != NULL) goto done; /* Initialize the socket list. */ if ((S = socketlist_init(0)) == NULL) goto err0; /* We have no poll structures allocated or initialized. */ fds = NULL; fds_alloc = nfds = fdscanpos = 0; /* Clean up the socket list at exit. */ if (atexit(events_network_shutdown)) goto err0; done: /* Success! */ return (0); err0: /* Failure! */ return (-1); } /* Grow the socket list and initialize new records. */ static int growsocketlist(size_t nrec) { size_t i; /* Get the old size. */ i = socketlist_getsize(S); /* Grow the list. */ if (socketlist_resize(S, nrec)) goto err0; /* Initialize new members. */ for (; i < nrec; i++) { socketlist_get(S, i)->reader = NULL; socketlist_get(S, i)->writer = NULL; socketlist_get(S, i)->pollpos = (size_t)(-1); } /* Success! */ return (0); err0: /* Failure! */ return (-1); } /* Add a new descriptor to the pollfd array. */ static int growpollfd(size_t fd) { size_t new_fds_alloc; struct pollfd * new_fds; /* We should not be called if the descriptor is already listed. */ assert(socketlist_get(S, fd)->pollpos == (size_t)(-1)); /* Expand the pollfd allocation if needed. */ if (fds_alloc == nfds) { new_fds_alloc = fds_alloc == 0 ? 16 : fds_alloc * 2; if (new_fds_alloc > SIZE_MAX / sizeof(struct pollfd)) { errno = ENOMEM; goto err0; } if ((new_fds = realloc(fds, new_fds_alloc * sizeof(struct pollfd))) == NULL) goto err0; fds = new_fds; fds_alloc = new_fds_alloc; } /* Sanity-check. */ assert(nfds < fds_alloc); assert(fd < INT_MAX); /* Initialize pollfd structure. */ fds[nfds].fd = (int)fd; fds[nfds].events = 0; fds[nfds].revents = 0; /* Point at pollfd structure. */ socketlist_get(S, fd)->pollpos = nfds; /* We now have one more pollfd structure. */ nfds++; /* Success! */ return (0); err0: /* Failure! */ return (-1); } /* Clear a bit from a pollfd and maintain invariants. */ static void clearbit(size_t pollpos, short bit) { /* Clear the bit. */ fds[pollpos].events &= (short)(~bit); fds[pollpos].revents &= (short)(~bit); /* Is this pollfd in the way? */ if (fds[pollpos].events == 0) { /* Clear the descriptor's pollpos pointer. */ socketlist_get(S, (size_t)fds[pollpos].fd)->pollpos = (size_t)(-1); /* If this wasn't the last pollfd, move another one up. */ if (pollpos != nfds - 1) { memcpy(&fds[pollpos], &fds[nfds-1], sizeof(struct pollfd)); socketlist_get(S, (size_t)fds[pollpos].fd)->pollpos = pollpos; } /* Shrink the pollfd array. */ nfds--; } } /** * events_network_register(func, cookie, s, op): * Register ${func}(${cookie}) to be run when socket ${s} is ready for * reading or writing depending on whether ${op} is EVENTS_NETWORK_OP_READ or * EVENTS_NETWORK_OP_WRITE. If there is already an event registration for * this ${s}/${op} pair, errno will be set to EEXIST and the function will * fail. */ int events_network_register(int (* func)(void *), void * cookie, int s, int op) { struct eventrec ** r; /* Initialize if necessary. */ if (init()) goto err0; /* Sanity-check socket number. */ if (s < 0) { warn0("Invalid file descriptor for network event: %d", s); goto err0; } /* Sanity-check operation. */ if ((op != EVENTS_NETWORK_OP_READ) && (op != EVENTS_NETWORK_OP_WRITE)) { warn0("Invalid operation for network event: %d", op); goto err0; } /* Grow the array if necessary. */ if (((size_t)(s) >= socketlist_getsize(S)) && (growsocketlist((size_t)s + 1) != 0)) goto err0; /* Look up the relevant event pointer. */ if (op == EVENTS_NETWORK_OP_READ) r = &socketlist_get(S, (size_t)s)->reader; else r = &socketlist_get(S, (size_t)s)->writer; /* Error out if we already have an event registered. */ if (*r != NULL) { errno = EEXIST; goto err0; } /* Register the new event. */ if ((*r = events_mkrec(func, cookie)) == NULL) goto err0; /* If we had no events registered, start a clock. */ if (nfds == 0) events_network_selectstats_startclock(); /* If this descriptor isn't in the pollfd array, add it. */ if (socketlist_get(S, (size_t)s)->pollpos == (size_t)(-1)) { if (growpollfd((size_t)s)) goto err1; } /* Set the appropriate event flag. */ if (op == EVENTS_NETWORK_OP_READ) fds[socketlist_get(S, (size_t)s)->pollpos].events |= POLLIN; else fds[socketlist_get(S, (size_t)s)->pollpos].events |= POLLOUT; /* Success! */ return (0); err1: events_freerec(*r); *r = NULL; err0: /* Failure! */ return (-1); } /** * events_network_cancel(s, op): * Cancel the event registered for the socket/operation pair ${s}/${op}. If * there is no such registration, errno will be set to ENOENT and the * function will fail. */ int events_network_cancel(int s, int op) { struct eventrec ** r; /* Initialize if necessary. */ if (init()) goto err0; /* Sanity-check socket number. */ if (s < 0) { warn0("Invalid file descriptor for network event: %d", s); goto err0; } /* Sanity-check operation. */ if ((op != EVENTS_NETWORK_OP_READ) && (op != EVENTS_NETWORK_OP_WRITE)) { warn0("Invalid operation for network event: %d", op); goto err0; } /* We have no events registered beyond the end of the array. */ if ((size_t)(s) >= socketlist_getsize(S)) { errno = ENOENT; goto err0; } /* Look up the relevant event pointer. */ if (op == EVENTS_NETWORK_OP_READ) r = &socketlist_get(S, (size_t)s)->reader; else r = &socketlist_get(S, (size_t)s)->writer; /* Check if we have an event. */ if (*r == NULL) { errno = ENOENT; goto err0; } /* Free the event. */ events_freerec(*r); *r = NULL; /* Clear the appropriate pollfd bit(s). */ if (op == EVENTS_NETWORK_OP_READ) clearbit(socketlist_get(S, (size_t)s)->pollpos, POLLIN); else clearbit(socketlist_get(S, (size_t)s)->pollpos, POLLOUT); /* If that was the last remaining event, stop the clock. */ if (nfds == 0) events_network_selectstats_stopclock(); /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * events_network_select(tv, interrupt_requested): * Check for socket readiness events, waiting up to ${tv} time if there are * no sockets immediately ready, or indefinitely if ${tv} is NULL. The value * stored in ${tv} may be modified. If ${*interrupt_requested} is non-zero * and a signal is received, exit. */ int events_network_select(const struct timeval * tv, const volatile sig_atomic_t * interrupt_requested) { int timeout; /* Initialize if necessary. */ if (init()) goto err0; /* * Convert timeout to an integer number of ms. We round up in order * to avoid creating busy loops when 0 < ${tv} < 1 ms. */ if (tv == NULL) timeout = -1; else if (tv->tv_sec >= INT_MAX / 1000) timeout = INT_MAX; else timeout = (int)(tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000); /* We're about to call poll! */ events_network_selectstats_select(); /* Poll. */ while (poll(fds, (nfds_t)nfds, timeout) == -1) { /* EINTR is harmless, unless we've requested an interrupt. */ if (errno == EINTR) { if (*interrupt_requested) break; continue; } /* Anything else is an error. */ warnp("poll()"); goto err0; } /* If we have any events registered, start the clock again. */ if (nfds > 0) events_network_selectstats_startclock(); /* Start scanning at the last registered descriptor and work down. */ fdscanpos = nfds - 1; /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * events_network_get(void): * Find a socket readiness event which was identified by a previous call to * events_network_select, and return it as an eventrec structure; or return * NULL if there are no such events available. The caller is responsible for * freeing the returned memory. */ struct eventrec * events_network_get(void) { struct eventrec * r; /* We haven't found any events yet. */ r = NULL; /* Scan through the pollfds looking for ready descriptors. */ for (; fdscanpos < nfds; fdscanpos--) { /* Did we poll on an invalid descriptor? */ assert((fds[fdscanpos].revents & POLLNVAL) == 0); /* * If either POLLERR ("an exceptional condition") or POLLHUP * ("has been disconnected") is set, then we should invoke * whatever callbacks we have available. */ if (fds[fdscanpos].revents & (POLLERR | POLLHUP)) { fds[fdscanpos].revents &= ~(POLLERR | POLLHUP); fds[fdscanpos].revents |= fds[fdscanpos].events; } /* Are we ready for reading? */ if (fds[fdscanpos].revents & POLLIN) { r = socketlist_get(S, (size_t)fds[fdscanpos].fd)->reader; socketlist_get(S, (size_t)fds[fdscanpos].fd)->reader = NULL; clearbit(fdscanpos, POLLIN); break; } /* Are we ready for writing? */ if (fds[fdscanpos].revents & POLLOUT) { r = socketlist_get(S, (size_t)fds[fdscanpos].fd)->writer; socketlist_get(S, (size_t)fds[fdscanpos].fd)->writer = NULL; clearbit(fdscanpos, POLLOUT); break; } } /* If we're returning the last registered event, stop the clock. */ if ((r != NULL) && (nfds == 0)) events_network_selectstats_stopclock(); /* Return the event we found, or NULL if we didn't find any. */ return (r); } /** * events_network_shutdown(void): * Clean up and free memory. This should run automatically via atexit. */ static void events_network_shutdown(void) { /* If we're not initialized, do nothing. */ if (S == NULL) return; /* If we have any registered events, do nothing. */ if (nfds > 0) return; /* Free the pollfd array. */ free(fds); fds = NULL; fds_alloc = 0; /* Free the socket list. */ socketlist_free(S); S = NULL; } spiped-1.6.4/libcperciva/util/fork_func.h000644 001751 001751 00000000721 14650270210 022024 0ustar00cpercivacperciva000000 000000 #ifndef FORK_FUNC_H_ #define FORK_FUNC_H_ #include /** * fork_func(func, cookie): * Fork and run ${func} in a new process, with ${cookie} as the sole argument. */ pid_t fork_func(int (*)(void *), void *); /** * fork_func_wait(pid): * Wait for the process ${pid} to finish. Print any error arising from ${pid}. * If ${pid} exited cleanly, return its exit code; otherwise, return -1. */ int fork_func_wait(pid_t); #endif /* !FORK_FUNC_H_ */ spiped-1.6.4/libcperciva/util/noeintr.c000644 001751 001751 00000002216 13723620112 021522 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include #include "noeintr.h" /** * noeintr_write(d, buf, nbytes): * Write ${nbytes} bytes of data from ${buf} to the file descriptor ${d} per * the write(2) system call, but looping until completion if interrupted by * a signal. Return ${nbytes} on success or -1 on error. */ ssize_t noeintr_write(int d, const void * buf, size_t nbytes) { const uint8_t * p = buf; size_t len = nbytes; ssize_t lenwrit; /* Implementation-defined: Don't allow oversized writes. */ assert(nbytes <= SSIZE_MAX); /* Loop until we have no data left to write. */ while (len > 0) { if ((lenwrit = write(d, p, len)) == -1) { /* EINTR is harmless. */ if (errno == EINTR) continue; /* Anything else isn't. */ goto err0; } /* Sanity check. */ assert(lenwrit >= 0); assert(lenwrit <= (ssize_t)len); /* * We might have done a partial write; advance the buffer * pointer and adjust the remaining write length. */ p += (size_t)lenwrit; len -= (size_t)lenwrit; } /* Success! */ return (ssize_t)(nbytes); err0: /* Failure! */ return (-1); } spiped-1.6.4/libcperciva/util/optional_mutex.h000644 001751 001751 00000001031 14650270210 023112 0ustar00cpercivacperciva000000 000000 #ifndef OPTIONAL_MUTEX_H_ #define OPTIONAL_MUTEX_H_ #include /** * optional_mutex_lock(mutex): * If OPTIONAL_MUTEX_PTHREAD_YES is defined, call pthread_mutex_lock(); * if OPTIONAL_MUTEX_PTHREAD_NO is defined, do nothing. */ int optional_mutex_lock(pthread_mutex_t *); /** * optional_mutex_unlock(mutex): * If OPTIONAL_MUTEX_PTHREAD_YES is defined, call pthread_mutex_unlock(); * if OPTIONAL_MUTEX_PTHREAD_NO is defined, do nothing. */ int optional_mutex_unlock(pthread_mutex_t *); #endif /* !OPTIONAL_MUTEX_H_ */ spiped-1.6.4/libcperciva/util/sock.c000644 001751 001751 00000031125 14743020337 021012 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include #include #include #include #include #include #include #include #include "imalloc.h" #include "parsenum.h" #include "warnp.h" #include "sock.h" #include "sock_internal.h" #include "sock_util.h" /* Convert a path into a socket address. */ static struct sock_addr ** sock_resolve_unix(const char * addr) { struct sock_addr ** sas; struct sock_addr * sa; struct sockaddr_un * sa_un; /* Allocate and populate a sockaddr_un structure. */ if ((sa_un = calloc(1, sizeof(struct sockaddr_un))) == NULL) goto err0; sa_un->sun_family = AF_UNIX; /* Safely copy addr into the structure. */ if (strlen(addr) >= sizeof(sa_un->sun_path)) { warn0("socket path too long: %s", addr); goto err1; } strcpy(sa_un->sun_path, addr); /* Allocate and populate our wrapper. */ if ((sa = malloc(sizeof(struct sock_addr))) == NULL) goto err1; sa->ai_family = AF_UNIX; sa->ai_socktype = SOCK_STREAM; sa->name = (struct sockaddr *)sa_un; sa->namelen = sizeof(struct sockaddr_un); /* Allocate and populate an array of pointers. */ if ((sas = malloc(2 * sizeof(struct sock_addr *))) == NULL) goto err2; sas[0] = sa; sas[1] = NULL; /* Success! */ return (sas); err2: free(sa); err1: free(sa_un); err0: /* Failure! */ return (NULL); } /* Resolve a host into a list of socket addresses. */ static struct sock_addr ** sock_resolve_host(const char * addr, const char * ports) { struct addrinfo hints; struct addrinfo * res; struct addrinfo * r; struct sock_addr ** sas; size_t n; int error; /* Create hints structure. */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; /* Perform DNS lookup. */ if ((error = getaddrinfo(addr, ports, &hints, &res)) != 0) { warn0("Error looking up %s: %s", addr, gai_strerror(error)); goto err0; } /* Count addresses returned. */ for (n = 0, r = res; r != NULL; r = r->ai_next) n++; /* Sanity check. */ assert(n < SIZE_MAX); /* Allocate our response array. */ if (IMALLOC(sas, n + 1, struct sock_addr *)) goto err1; /* Create address structures. */ for (n = 0, r = res; r != NULL; n++, r = r->ai_next) { /* Allocate a structure. */ if ((sas[n] = malloc(sizeof(struct sock_addr))) == NULL) goto err2; /* Copy in the address metadata. */ sas[n]->ai_family = r->ai_family; sas[n]->ai_socktype = r->ai_socktype; sas[n]->namelen = r->ai_addrlen; /* Duplicate the address. */ if ((sas[n]->name = malloc(sas[n]->namelen)) == NULL) goto err3; memcpy(sas[n]->name, r->ai_addr, sas[n]->namelen); } /* Terminate array with a NULL. */ sas[n] = NULL; /* Free the linked list of addresses returned by getaddrinfo. */ freeaddrinfo(res); /* Success! */ return (sas); err3: free(sas[n]); err2: for (; n > 0; n--) sock_addr_free(sas[n - 1]); free(sas); err1: freeaddrinfo(res); err0: /* Failure! */ return (NULL); } /* Parse an IPv6 address into a socket address. */ static struct sock_addr ** sock_resolve_ipv6(const char * addr, in_port_t p) { struct sock_addr ** sas; struct sock_addr * sa; struct sockaddr_in6 * sin6; /* Allocate and populate a sockaddr_in6 structure. */ if ((sin6 = calloc(1, sizeof(struct sockaddr_in6))) == NULL) goto err0; sin6->sin6_family = AF_INET6; sin6->sin6_port = htons(p); if (inet_pton(AF_INET6, addr, &sin6->sin6_addr) != 1) { warn0("Error parsing IP address: %s", addr); goto err1; } /* Allocate and populate our wrapper. */ if ((sa = malloc(sizeof(struct sock_addr))) == NULL) goto err1; sa->ai_family = AF_INET6; sa->ai_socktype = SOCK_STREAM; sa->name = (struct sockaddr *)sin6; sa->namelen = sizeof(struct sockaddr_in6); /* Allocate and populate an array of pointers. */ if ((sas = malloc(2 * sizeof(struct sock_addr *))) == NULL) goto err2; sas[0] = sa; sas[1] = NULL; /* Success! */ return (sas); err2: free(sa); err1: free(sin6); err0: /* Failure! */ return (NULL); } /* Parse an IPv4 address into a socket address. */ static struct sock_addr ** sock_resolve_ipv4(const char * addr, in_port_t p) { struct sock_addr ** sas; struct sock_addr * sa; struct sockaddr_in * sin; /* Allocate and populate a sockaddr_in structure. */ if ((sin = calloc(1, sizeof(struct sockaddr_in))) == NULL) goto err0; sin->sin_family = AF_INET; sin->sin_port = htons(p); if (inet_pton(AF_INET, addr, &sin->sin_addr) != 1) { warn0("Error parsing IP address: %s", addr); goto err1; } /* Allocate and populate our wrapper. */ if ((sa = malloc(sizeof(struct sock_addr))) == NULL) goto err1; sa->ai_family = AF_INET; sa->ai_socktype = SOCK_STREAM; sa->name = (struct sockaddr *)sin; sa->namelen = sizeof(struct sockaddr_in); /* Allocate and populate an array of pointers. */ if ((sas = malloc(2 * sizeof(struct sock_addr *))) == NULL) goto err2; sas[0] = sa; sas[1] = NULL; /* Success! */ return (sas); err2: free(sa); err1: free(sin); err0: /* Failure! */ return (NULL); } /** * sock_resolve(addr): * Return a NULL-terminated array of pointers to sock_addr structures. */ struct sock_addr ** sock_resolve(const char * addr) { struct sock_addr ** res; char * s; char * ports; char * ips; long p; /* Check syntax. */ if (sock_addr_validate(addr)) goto err0; /* If the address starts with '/', it's a Unix domain socket. */ if (addr[0] == '/') { res = sock_resolve_unix(addr); goto done0; } /* Copy the address so that we can mangle it. */ if ((s = strdup(addr)) == NULL) goto err0; /* The address should end with :port. Look for the last ':'. */ if ((ports = strrchr(s, ':')) == NULL) { warn0("Address must contain port number: %s", s); goto err1; } *ports++ = '\0'; /* If the address doesn't start with '[', it's a host name. */ if (s[0] != '[') { res = sock_resolve_host(s, ports); goto done1; } /* The address (sans :port) should end with ']'. */ if (s[strlen(s) - 1] != ']') { warn0("Invalid [IP address]: %s", s); goto err1; } /* Extract the IP address string. */ ips = &s[1]; ips[strlen(ips) - 1] = '\0'; /* Parse the port number in base 10, no trailing characters. */ if (PARSENUM_EX(&p, ports, 1, 65535, 10, 0)) { warn0("Invalid port number: %s", ports); goto err1; } /* If the IP address contains ':', it's IPv6; otherwise, IPv4. */ if (strchr(ips, ':') != NULL) res = sock_resolve_ipv6(ips, (in_port_t)p); else res = sock_resolve_ipv4(ips, (in_port_t)p); done1: /* Free string allocated by strdup. */ free(s); done0: /* Return result from sock_resolve_foo. */ return (res); err1: free(s); err0: /* Failure! */ return (NULL); } /** * sock_resolve_one(addr, addport): * Return a single sock_addr structure, or NULL if there are no addresses. * Warn if there is more than one address, and return the first one. * If ${addport} is non-zero, use sock_addr_ensure_port() to add a port number * of ":0" if appropriate. */ struct sock_addr * sock_resolve_one(const char * addr, int addport) { struct sock_addr ** sas; struct sock_addr * sa; struct sock_addr ** sa_tmp; char * addr_alloc = NULL; /* Prepare the address to resolve. */ if (addport && ((addr = addr_alloc = sock_addr_ensure_port(addr)) == NULL)) { warnp("sock_addr_ensure_port"); goto err0; } /* Resolve target address. */ if ((sas = sock_resolve(addr)) == NULL) { warnp("Error resolving socket address: %s", addr); goto err1; } /* Check that the array is not empty. */ if (sas[0] == NULL) { warn0("No addresses found for %s", addr); goto err2; } /* If there's more than one address, give a warning. */ if (sas[1] != NULL) warn0("Using the first of multiple addresses found for %s", addr); /* Keep the address we want. */ sa = sas[0]; /* Free the other addresses and list. */ for (sa_tmp = &sas[1]; *sa_tmp != NULL; sa_tmp++) sock_addr_free(*sa_tmp); free(sas); /* Clean up. */ free(addr_alloc); /* Success! */ return (sa); err2: sock_addr_freelist(sas); err1: free(addr_alloc); err0: /* Failure! */ return (NULL); } /** * sock_listener(sa): * Create a socket, attempt to set SO_REUSEADDR, bind it to the socket address * ${sa}, mark it for listening, and mark it as non-blocking. */ int sock_listener(const struct sock_addr * sa) { int s; int val = 1; /* Create a socket. */ if ((s = socket(sa->ai_family, sa->ai_socktype, 0)) == -1) { warnp("socket(%d, %d)", sa->ai_family, sa->ai_socktype); goto err0; } /* Attempt to set SO_REUSEADDR. */ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))) { /* ENOPROTOOPT is ok. */ if (errno != ENOPROTOOPT) { warnp("setsockopt(SO_REUSEADDR)"); goto err1; } } /* Bind the socket. */ if (bind(s, sa->name, sa->namelen)) { warnp("Error binding socket"); goto err1; } /* Mark the socket as listening. */ if (listen(s, 10)) { warnp("Error marking socket as listening"); goto err1; } /* Mark the socket as non-blocking. */ if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) { warnp("Error marking socket as non-blocking"); goto err1; } /* Success! */ return (s); err1: if (close(s)) warnp("close"); err0: /* Failure! */ return (-1); } /** * sock_connect(sas): * Iterate through the addresses in ${sas}, attempting to create a socket and * connect (blockingly). Once connected, stop iterating, mark the socket as * non-blocking, and return it. */ int sock_connect(struct sock_addr * const * sas) { int s = -1; /* Iterate through the addresses provided. */ for (; sas[0] != NULL; sas++) { /* Create a socket. */ if ((s = socket(sas[0]->ai_family, sas[0]->ai_socktype, 0)) == -1) continue; /* Attempt to connect. */ if (connect(s, sas[0]->name, sas[0]->namelen) == 0) break; /* Close the socket; this address didn't work. */ if (close(s)) warnp("close"); } /* Did we manage to connect? */ if (sas[0] == NULL) { warn0("Could not connect"); goto err0; } /* Mark the socket as non-blocking. */ if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) { warnp("Cannot make connection non-blocking"); goto err1; } /* Success! */ return (s); err1: if (close(s)) warnp("close"); err0: /* Failure! */ return (-1); } /** * sock_connect_nb(sa): * Create a socket, mark it as non-blocking, and attempt to connect to the * address ${sa}. Return the socket (connected or in the process of * connecting) or -1 on error. */ int sock_connect_nb(const struct sock_addr * sa) { /* Let sock_connect_bind_nb handle this. */ return (sock_connect_bind_nb(sa, NULL)); } /** * sock_connect_bind_nb(sa, sa_b): * Create a socket, mark it as non-blocking, and attempt to connect to the * address ${sa}. If ${sa_b} is not NULL, attempt to set SO_REUSEADDR on the * socket and bind it to ${sa_b} immediately after creating it. Return the * socket (connected or in the process of connecting) or -1 on error. */ int sock_connect_bind_nb(const struct sock_addr * sa, const struct sock_addr * sa_b) { int s; int val = 1; /* Create a socket. */ if ((s = socket(sa->ai_family, sa->ai_socktype, 0)) == -1) { warnp("socket(%d, %d)", sa->ai_family, sa->ai_socktype); goto err0; } /* Bind the socket to sa_b (if applicable). */ if (sa_b) { /* Attempt to set SO_REUSEADDR. */ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))) { /* ENOPROTOOPT is ok. */ if (errno != ENOPROTOOPT) { warnp("setsockopt(SO_REUSEADDR)"); goto err1; } } /* Bind socket. */ if ((bind(s, sa_b->name, sa_b->namelen)) == -1) { warnp("Error binding socket"); goto err1; } } /* Mark the socket as non-blocking. */ if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) { warnp("Cannot make socket non-blocking"); goto err1; } /* Attempt to connect. */ if ((connect(s, sa->name, sa->namelen) == -1) && (errno != EINPROGRESS) && (errno != EINTR)) { warnp("connect"); goto err1; } /* We have a connect(ed|ing) socket. */ return (s); err1: if (close(s)) warnp("close"); err0: /* We failed to connect to this address. */ return (-1); } /** * sock_addr_free(sa): * Free the provided sock_addr structure. */ void sock_addr_free(struct sock_addr * sa) { /* Behave consistently with free(NULL). */ if (sa == NULL) return; /* Free the protocol-specific address structure and our struct. */ free(sa->name); free(sa); } /** * sock_addr_freelist(sas): * Free the provided NULL-terminated array of sock_addr structures. */ void sock_addr_freelist(struct sock_addr ** sas) { struct sock_addr ** p; /* Behave consistently with free(NULL). */ if (sas == NULL) return; /* Free structures until we hit NULL. */ for (p = sas; *p != NULL; p++) sock_addr_free(*p); /* Free the list. */ free(sas); } spiped-1.6.4/libcperciva/util/imalloc.h000644 001751 001751 00000001607 14743020337 021502 0ustar00cpercivacperciva000000 000000 #ifndef IMALLOC_H_ #define IMALLOC_H_ #include #include #include #include /** * imalloc(nrec, reclen): * Allocate ${nrec} records of length ${reclen}. Check for size_t overflow. * ${reclen} must not be zero. If ${nrec} is zero, return NULL. */ static inline void * imalloc(size_t nrec, size_t reclen) { /* Sanity check. */ assert(reclen != 0); /* Handle cases where we don't allocate memory. */ if (nrec == 0) return (NULL); if (nrec > SIZE_MAX / reclen) { errno = ENOMEM; return (NULL); } /* Allocate memory. */ return (malloc(nrec * reclen)); } /** * IMALLOC(p, nrec, type): * Allocate ${nrec} records of type ${type} and store the pointer in ${p}. * Return non-zero on failure. */ #define IMALLOC(p, nrec, type) \ ((((p) = (type *)imalloc((nrec), sizeof(type))) == NULL) && \ ((nrec) > 0)) #endif /* !IMALLOC_H_ */ spiped-1.6.4/libcperciva/util/entropy.c000644 001751 001751 00000006226 14650270210 021551 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include #include #include #include "warnp.h" #include "entropy.h" /** * XXX Portability * XXX We obtain random bytes from the operating system by opening * XXX /dev/urandom and reading them from that device; this works on * XXX modern UNIX-like operating systems but not on systems like * XXX win32 where there is no concept of /dev/urandom. */ /** * Entropy reader state. At present it holds a file descriptor for * /dev/urandom, but in the future this structure may gain other OS-dependent * state, e.g. a Windows Handle. */ struct entropy_read_cookie { int fd; }; /** * entropy_read_init(void): * Initialize the ability to produce random bytes from the operating system, * and return a cookie. */ struct entropy_read_cookie * entropy_read_init(void) { struct entropy_read_cookie * er; /* Allocate cookie. */ if ((er = malloc(sizeof(struct entropy_read_cookie))) == NULL) { warnp("malloc"); goto err0; } /* Open /dev/urandom. */ if ((er->fd = open("/dev/urandom", O_RDONLY)) == -1) { warnp("open(/dev/urandom)"); goto err1; } /* Success! */ return (er); err1: free(er); err0: /* Failure! */ return (NULL); } /** * entropy_read_fill(er, buf, buflen): * Fill the given buffer with random bytes provided by the operating system * using the resources in ${er}. */ int entropy_read_fill(struct entropy_read_cookie * er, uint8_t * buf, size_t buflen) { ssize_t lenread; /* Sanity checks. */ assert(er != NULL); assert(buflen <= SSIZE_MAX); /* Read bytes until we have filled the buffer. */ while (buflen > 0) { if ((lenread = read(er->fd, buf, buflen)) == -1) { warnp("read(/dev/urandom)"); goto err0; } /* The random device should never EOF. */ if (lenread == 0) { warn0("EOF on /dev/urandom?"); goto err0; } /* We've filled a portion of the buffer. */ buf += (size_t)lenread; buflen -= (size_t)lenread; } /* Success! */ return (0); err0: /* Failure! */ return (-1); } /** * entropy_read_done(er): * Release any resources used by ${er}. */ int entropy_read_done(struct entropy_read_cookie * er) { /* Sanity check. */ assert(er != NULL); /* Close the device. */ while (close(er->fd) == -1) { if (errno != EINTR) { warnp("close(/dev/urandom)"); goto err1; } } /* Clean up. */ free(er); /* Success! */ return (0); err1: free(er); /* Failure! */ return (-1); } /** * entropy_read(buf, buflen): * Fill the given buffer with random bytes provided by the operating system. */ int entropy_read(uint8_t * buf, size_t buflen) { struct entropy_read_cookie * er; /* Sanity-check the buffer size. */ assert(buflen <= SSIZE_MAX); /* Open /dev/urandom. */ if ((er = entropy_read_init()) == NULL) { warn0("entropy_read_init"); goto err0; } /* Read bytes until we have filled the buffer. */ if (entropy_read_fill(er, buf, buflen)) { warn0("entropy_read_fill"); goto err1; } /* Close the device. */ if (entropy_read_done(er)) { warn0("entropy_read_done"); goto err0; } /* Success! */ return (0); err1: entropy_read_done(er); err0: /* Failure! */ return (-1); } spiped-1.6.4/libcperciva/util/getopt.c000644 001751 001751 00000020640 14650270210 021347 0ustar00cpercivacperciva000000 000000 #include #include #include #include #include "getopt.h" /* * Standard getopt global variables. optreset starts as non-zero in order to * trigger initialization behaviour. */ const char * optarg = NULL; int optind = 1; int opterr = 1; int optreset = 1; /* * Quasi-internal global variables -- these are used via GETOPT macros. */ const char * getopt_dummy = "(dummy)"; int getopt_initialized = 0; /* * Internal variables. */ static const char * cmdname = NULL; static struct opt { const char * os; size_t olen; int hasarg; } * opts = NULL; /* Probably a sparse array: some values, some NULLs. */ static size_t nopts; /* Maximum number of options. */ static size_t opt_missing; static size_t opt_default; static size_t opt_found; static const char * packedopts; static char popt[3]; static int atexit_registered = 0; /* Print a message. */ #define PRINTMSG(...) do { \ if (cmdname != NULL) \ fprintf(stderr, "%s: ", cmdname); \ fprintf(stderr, __VA_ARGS__); \ fprintf(stderr, "\n"); \ } while (0) /* Print an error message and die. */ #define DIE(...) do { \ PRINTMSG(__VA_ARGS__); \ abort(); \ } while (0) /* Print a warning, if warnings are enabled. */ #define WARN(...) do { \ if (opterr == 0) \ break; \ if (opt_missing != opt_default) \ break; \ PRINTMSG(__VA_ARGS__); \ } while (0) /* Free allocated options array. */ static void getopt_atexit(void) { free(opts); opts = NULL; } /* Reset internal state. */ static void reset(int argc, char * const argv[]) { const char * p; /* If we have arguments, stash argv[0] for error messages. */ if (argc > 0) { /* Find the basename, without leading directories. */ for (p = cmdname = argv[0]; *p != '\0'; p++) { if (*p == '/') cmdname = p + 1; } } /* Discard any registered command-line options. */ free(opts); opts = NULL; /* Register atexit handler if we haven't done so already. */ if (!atexit_registered) { atexit(getopt_atexit); atexit_registered = 1; } /* We will start scanning from the first option. */ optind = 1; /* We're not in the middle of any packed options. */ packedopts = NULL; /* We haven't found any option yet. */ opt_found = (size_t)(-1); /* We're not initialized yet. */ getopt_initialized = 0; /* Finished resetting state. */ optreset = 0; } /* Search for an option string. */ static size_t searchopt(const char * os) { size_t i; /* Scan the array of options. */ for (i = 0; i < nopts; i++) { /* Is there an option in this slot? */ if (opts[i].os == NULL) continue; /* Does this match up to the length of the option string? */ if (strncmp(opts[i].os, os, opts[i].olen)) continue; /* Do we have