update libks

This commit is contained in:
Mike Jerris 2016-11-23 13:23:33 -06:00
parent 238e228942
commit 9fd0b6bd2f
128 changed files with 41586 additions and 2145 deletions

10
libs/libks/.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
Makefile
Makefile.in
build/compile
build/libtool.m4
build/ltoptions.m4
build/ltsugar.m4
build/ltversion.m4
build/lt~obsolete.m4
dht-example.id
configure

0
libs/libks/AUTHORS Normal file
View File

0
libs/libks/COPYING Normal file
View File

0
libs/libks/ChangeLog Normal file
View File

370
libs/libks/INSTALL Normal file
View File

@ -0,0 +1,370 @@
Installation Instructions
*************************
Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation,
Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. This file is offered as-is,
without warranty of any kind.
Basic Installation
==================
Briefly, the shell command `./configure && make && make install'
should configure, build, and install this package. The following
more-detailed instructions are generic; see the `README' file for
instructions specific to this package. Some packages provide this
`INSTALL' file but do not implement all of the features documented
below. The lack of an optional feature in a given package is not
necessarily a bug. More recommendations for GNU packages can be found
in *note Makefile Conventions: (standards)Makefile Conventions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. Caching is
disabled by default to prevent problems with accidental use of stale
cache files.
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You need `configure.ac' if
you want to change it or regenerate `configure' using a newer version
of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system.
Running `configure' might take a while. While running, it prints
some messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package, generally using the just-built uninstalled binaries.
4. Type `make install' to install the programs and any data files and
documentation. When installing into a prefix owned by root, it is
recommended that the package be configured and built as a regular
user, and only the `make install' phase executed with root
privileges.
5. Optionally, type `make installcheck' to repeat any self-tests, but
this time using the binaries in their final installed location.
This target does not install anything. Running this target as a
regular user, particularly if the prior `make install' required
root privileges, verifies that the installation completed
correctly.
6. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
7. Often, you can also type `make uninstall' to remove the installed
files again. In practice, not all packages have tested that
uninstallation works correctly, even though it is required by the
GNU Coding Standards.
8. Some packages, particularly those that use Automake, provide `make
distcheck', which can by used by developers to test that all other
targets like `make install' and `make uninstall' work correctly.
This target is generally not run by end users.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. Run `./configure --help'
for details on some of the pertinent environment variables.
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
./configure CC=c99 CFLAGS=-g LIBS=-lposix
*Note Defining Variables::, for more details.
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you can use GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'. This
is known as a "VPATH" build.
With a non-GNU `make', it is safer to compile the package for one
architecture at a time in the source code directory. After you have
installed the package for one architecture, use `make distclean' before
reconfiguring for another architecture.
On MacOS X 10.5 and later systems, you can create libraries and
executables that work on multiple system types--known as "fat" or
"universal" binaries--by specifying multiple `-arch' options to the
compiler but only a single `-arch' option to the preprocessor. Like
this:
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CPP="gcc -E" CXXCPP="g++ -E"
This is not guaranteed to produce working output in all cases, you
may have to build one architecture at a time and combine the results
using the `lipo' tool if you have problems.
Installation Names
==================
By default, `make install' installs the package's commands under
`/usr/local/bin', include files under `/usr/local/include', etc. You
can specify an installation prefix other than `/usr/local' by giving
`configure' the option `--prefix=PREFIX', where PREFIX must be an
absolute file name.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
PREFIX as the prefix for installing programs and libraries.
Documentation and other data files still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=DIR' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them. In general, the
default for these options is expressed in terms of `${prefix}', so that
specifying just `--prefix' will affect all of the other directory
specifications that were not explicitly provided.
The most portable way to affect installation locations is to pass the
correct locations to `configure'; however, many packages provide one or
both of the following shortcuts of passing variable assignments to the
`make install' command line to change installation locations without
having to reconfigure or recompile.
The first method involves providing an override variable for each
affected directory. For example, `make install
prefix=/alternate/directory' will choose an alternate location for all
directory configuration variables that were expressed in terms of
`${prefix}'. Any directories that were specified during `configure',
but not in terms of `${prefix}', must each be overridden at install
time for the entire installation to be relocated. The approach of
makefile variable overrides for each directory variable is required by
the GNU Coding Standards, and ideally causes no recompilation.
However, some platforms have known limitations with the semantics of
shared libraries that end up requiring recompilation when using this
method, particularly noticeable in packages that use GNU Libtool.
The second method involves providing the `DESTDIR' variable. For
example, `make install DESTDIR=/alternate/directory' will prepend
`/alternate/directory' before all installation names. The approach of
`DESTDIR' overrides is not required by the GNU Coding Standards, and
does not work on platforms that have drive letters. On the other hand,
it does better at avoiding recompilation issues, and works well even
when some directory options were not specified in terms of `${prefix}'
at `configure' time.
Optional Features
=================
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Some packages offer the ability to configure how verbose the
execution of `make' will be. For these packages, running `./configure
--enable-silent-rules' sets the default to minimal output, which can be
overridden with `make V=1'; while running `./configure
--disable-silent-rules' sets the default to verbose, which can be
overridden with `make V=0'.
Particular systems
==================
On HP-UX, the default C compiler is not ANSI C compatible. If GNU
CC is not installed, it is recommended to use the following options in
order to use an ANSI C compiler:
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
HP-UX `make' updates targets which have the same time stamps as
their prerequisites, which makes it generally unusable when shipped
generated files such as `configure' are involved. Use GNU `make'
instead.
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
a workaround. If GNU CC is not installed, it is therefore recommended
to try
./configure CC="cc"
and if that doesn't work, try
./configure CC="cc -nodtk"
On Solaris, don't put `/usr/ucb' early in your `PATH'. This
directory contains several dysfunctional programs; working variants of
these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
in your `PATH', put it _after_ `/usr/bin'.
On Haiku, software installed for all users goes in `/boot/common',
not `/usr/local'. It is recommended to use the following options:
./configure --prefix=/boot/common
Specifying the System Type
==========================
There may be some features `configure' cannot figure out
automatically, but needs to determine by the type of machine the package
will run on. Usually, assuming the package is built to be run on the
_same_ architectures, `configure' can figure that out, but if it prints
a message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
OS
KERNEL-OS
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the option `--target=TYPE' to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
causes the specified `gcc' to be used as the C compiler (unless it is
overridden in the site shell script).
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
an Autoconf limitation. Until the limitation is lifted, you can use
this workaround:
CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
`configure' Invocation
======================
`configure' recognizes the following options to control how it
operates.
`--help'
`-h'
Print a summary of all of the options to `configure', and exit.
`--help=short'
`--help=recursive'
Print a summary of the options unique to this package's
`configure', and exit. The `short' variant lists options used
only in the top level, while the `recursive' variant lists options
also present in any nested packages.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`--prefix=DIR'
Use DIR as the installation prefix. *note Installation Names::
for more details, including other options available for fine-tuning
the installation locations.
`--no-create'
`-n'
Run the configure checks, but stop before creating any output
files.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.

36
libs/libks/Makefile.am Normal file
View File

@ -0,0 +1,36 @@
ACLOCAL_AMFLAGS=-I build
EXTRA_DIST =
SUBDIRS = . test
AUTOMAKE_OPTIONS = subdir-objects
AM_CFLAGS += -I$(top_srcdir)/src -I$(top_srcdir)/src/include -I$(top_srcdir)/crypt
AM_CPPFLAGS = $(AM_CFLAGS)
lib_LTLIBRARIES = libks.la
libks_la_SOURCES = src/ks.c src/ks_string.c src/ks_json.c src/ks_thread.c src/ks_mutex.c src/ks_config.c
libks_la_SOURCES += src/ks_log.c src/ks_socket.c src/ks_buffer.c src/ks_pool.c src/simclist.c
libks_la_SOURCES += src/ks_time.c src/ks_printf.c src/ks_hash.c src/ks_q.c src/ks_dso.c src/ks_dht.c
libks_la_SOURCES += src/ks_ssl.c src/kws.c src/ks_rng.c
libks_la_SOURCES += src/utp/utp_api.cpp src/utp/utp_callbacks.cpp src/utp/utp_hash.cpp src/utp/utp_internal.cpp
libks_la_SOURCES += src/utp/utp_packedsockaddr.cpp src/utp/utp_utils.cpp src/ks_bencode.c
libks_la_SOURCES += crypt/aeskey.c crypt/aestab.c crypt/sha2.c crypt/twofish.c crypt/aes_modes.c crypt/aescrypt.c crypt/twofish_cfb.c
#aes.h aescpp.h brg_endian.h aesopt.h aestab.h brg_types.h sha2.h twofish.h
libks_la_CFLAGS = $(AM_CFLAGS)
libks_la_CPPFLAGS = -DPOSIX
libks_la_LDFLAGS = $(AM_LDFLAGS) -version-info 0:1:0 -lncurses -lpthread -lm
library_includedir = $(prefix)/include
library_include_HEADERS = src/include/ks_config.h src/include/ks.h src/include/ks_threadmutex.h src/include/ks_json.h src/include/ks_buffer.h
library_include_HEADERS += src/include/ks_pool.h src/include/simclist.h src/include/ks_time.h src/include/ks_q.h src/include/ks_socket.h
library_include_HEADERS += src/include/ks_dso.h src/include/ks_dht.h src/include/ks_platform.h src/include/ks_types.h # src/include/ks_rng.h
library_include_HEADERS += src/include/ks_printf.h src/include/ks_hash.h src/include/ks_ssl.h src/include/kws.h
library_include_HEADERS += src/utp/utp_internal.h src/utp/utp.h src/utp/utp_types.h src/utp/utp_callbacks.h src/utp/utp_templates.h
library_include_HEADERS += src/utp/utp_hash.h src/utp/utp_packedsockaddr.h src/utp/utp_utils.h src/include/ks_utp.h
tests: libks.la
$(MAKE) -C test tests

0
libs/libks/NEWS Normal file
View File

0
libs/libks/README Normal file
View File

7
libs/libks/acinclude.m4 Normal file
View File

@ -0,0 +1,7 @@
m4_include([build/config/ax_compiler_vendor.m4])
m4_include([build/config/ax_cflags_warn_all_ansi.m4])
m4_include([build/config/ax_cc_maxopt.m4])
m4_include([build/config/ax_check_compiler_flags.m4])
m4_include([build/config/ac_gcc_archflag.m4])
m4_include([build/config/ac_gcc_x86_cpuid.m4])
m4_include([build/config/sac-openssl.m4])

4
libs/libks/bootstrap.sh Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh
set -x
${AUTORECONF:-autoreconf} -fi

View File

@ -0,0 +1,142 @@
AC_DEFUN([AX_CFLAGS_GCC_OPTION_OLD], [dnl
AS_VAR_PUSHDEF([FLAGS],[CFLAGS])dnl
AS_VAR_PUSHDEF([VAR],[ac_cv_cflags_gcc_option_$2])dnl
AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for gcc m4_ifval($2,$2,-option)],
VAR,[VAR="no, unknown"
AC_LANG_SAVE
AC_LANG_C
ac_save_[]FLAGS="$[]FLAGS"
for ac_arg dnl
in "-pedantic % m4_ifval($2,$2,-option)" dnl GCC
#
do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
AC_TRY_COMPILE([],[return 0;],
[VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
done
FLAGS="$ac_save_[]FLAGS"
AC_LANG_RESTORE
])
case ".$VAR" in
.ok|.ok,*) m4_ifvaln($3,$3) ;;
.|.no|.no,*) m4_ifvaln($4,$4) ;;
*) m4_ifvaln($3,$3,[
if echo " $[]m4_ifval($1,$1,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
then AC_RUN_LOG([: m4_ifval($1,$1,FLAGS) does contain $VAR])
else AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"])
m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"
fi ]) ;;
esac
AS_VAR_POPDEF([VAR])dnl
AS_VAR_POPDEF([FLAGS])dnl
])
dnl the only difference - the LANG selection... and the default FLAGS
AC_DEFUN([AX_CXXFLAGS_GCC_OPTION_OLD], [dnl
AS_VAR_PUSHDEF([FLAGS],[CXXFLAGS])dnl
AS_VAR_PUSHDEF([VAR],[ac_cv_cxxflags_gcc_option_$2])dnl
AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for gcc m4_ifval($2,$2,-option)],
VAR,[VAR="no, unknown"
AC_LANG_SAVE
AC_LANG_CXX
ac_save_[]FLAGS="$[]FLAGS"
for ac_arg dnl
in "-pedantic % m4_ifval($2,$2,-option)" dnl GCC
#
do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
AC_TRY_COMPILE([],[return 0;],
[VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
done
FLAGS="$ac_save_[]FLAGS"
AC_LANG_RESTORE
])
case ".$VAR" in
.ok|.ok,*) m4_ifvaln($3,$3) ;;
.|.no|.no,*) m4_ifvaln($4,$4) ;;
*) m4_ifvaln($3,$3,[
if echo " $[]m4_ifval($1,$1,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
then AC_RUN_LOG([: m4_ifval($1,$1,FLAGS) does contain $VAR])
else AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"])
m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"
fi ]) ;;
esac
AS_VAR_POPDEF([VAR])dnl
AS_VAR_POPDEF([FLAGS])dnl
])
dnl -------------------------------------------------------------------------
AC_DEFUN([AX_CFLAGS_GCC_OPTION_NEW], [dnl
AS_VAR_PUSHDEF([FLAGS],[CFLAGS])dnl
AS_VAR_PUSHDEF([VAR],[ac_cv_cflags_gcc_option_$1])dnl
AC_CACHE_CHECK([m4_ifval($2,$2,FLAGS) for gcc m4_ifval($1,$1,-option)],
VAR,[VAR="no, unknown"
AC_LANG_SAVE
AC_LANG_C
ac_save_[]FLAGS="$[]FLAGS"
for ac_arg dnl
in "-pedantic % m4_ifval($1,$1,-option)" dnl GCC
#
do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
AC_TRY_COMPILE([],[return 0;],
[VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
done
FLAGS="$ac_save_[]FLAGS"
AC_LANG_RESTORE
])
case ".$VAR" in
.ok|.ok,*) m4_ifvaln($3,$3) ;;
.|.no|.no,*) m4_ifvaln($4,$4) ;;
*) m4_ifvaln($3,$3,[
if echo " $[]m4_ifval($2,$2,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
then AC_RUN_LOG([: m4_ifval($2,$2,FLAGS) does contain $VAR])
else AC_RUN_LOG([: m4_ifval($2,$2,FLAGS)="$m4_ifval($2,$2,FLAGS) $VAR"])
m4_ifval($2,$2,FLAGS)="$m4_ifval($2,$2,FLAGS) $VAR"
fi ]) ;;
esac
AS_VAR_POPDEF([VAR])dnl
AS_VAR_POPDEF([FLAGS])dnl
])
dnl the only difference - the LANG selection... and the default FLAGS
AC_DEFUN([AX_CXXFLAGS_GCC_OPTION_NEW], [dnl
AS_VAR_PUSHDEF([FLAGS],[CXXFLAGS])dnl
AS_VAR_PUSHDEF([VAR],[ac_cv_cxxflags_gcc_option_$1])dnl
AC_CACHE_CHECK([m4_ifval($2,$2,FLAGS) for gcc m4_ifval($1,$1,-option)],
VAR,[VAR="no, unknown"
AC_LANG_SAVE
AC_LANG_CXX
ac_save_[]FLAGS="$[]FLAGS"
for ac_arg dnl
in "-pedantic % m4_ifval($1,$1,-option)" dnl GCC
#
do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
AC_TRY_COMPILE([],[return 0;],
[VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
done
FLAGS="$ac_save_[]FLAGS"
AC_LANG_RESTORE
])
case ".$VAR" in
.ok|.ok,*) m4_ifvaln($3,$3) ;;
.|.no|.no,*) m4_ifvaln($4,$4) ;;
*) m4_ifvaln($3,$3,[
if echo " $[]m4_ifval($2,$2,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
then AC_RUN_LOG([: m4_ifval($2,$2,FLAGS) does contain $VAR])
else AC_RUN_LOG([: m4_ifval($2,$2,FLAGS)="$m4_ifval($2,$2,FLAGS) $VAR"])
m4_ifval($2,$2,FLAGS)="$m4_ifval($2,$2,FLAGS) $VAR"
fi ]) ;;
esac
AS_VAR_POPDEF([VAR])dnl
AS_VAR_POPDEF([FLAGS])dnl
])
AC_DEFUN([AX_CFLAGS_GCC_OPTION],[ifelse(m4_bregexp([$2],[-]),-1,
[AX_CFLAGS_GCC_OPTION_NEW($@)],[AX_CFLAGS_GCC_OPTION_OLD($@)])])
AC_DEFUN([AX_CXXFLAGS_GCC_OPTION],[ifelse(m4_bregexp([$2],[-]),-1,
[AX_CXXFLAGS_GCC_OPTION_NEW($@)],[AX_CXXFLAGS_GCC_OPTION_OLD($@)])])

View File

@ -0,0 +1,140 @@
AC_DEFUN([AX_CFLAGS_SUN_OPTION_OLD], [dnl
AS_VAR_PUSHDEF([FLAGS],[CFLAGS])dnl
AS_VAR_PUSHDEF([VAR],[ac_cv_cflags_sun_option_$2])dnl
AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for sun/cc m4_ifval($2,$2,-option)],
VAR,[VAR="no, unknown"
AC_LANG_SAVE
AC_LANG_C
ac_save_[]FLAGS="$[]FLAGS"
for ac_arg dnl
in "+xstrconst % -xc99=all m4_ifval($2,$2,-option)" dnl Solaris C
#
do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
AC_TRY_COMPILE([],[return 0;],
[VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
done
FLAGS="$ac_save_[]FLAGS"
AC_LANG_RESTORE
])
case ".$VAR" in
.ok|.ok,*) m4_ifvaln($3,$3) ;;
.|.no|.no,*) m4_ifvaln($4,$4) ;;
*) m4_ifvaln($3,$3,[
if echo " $[]m4_ifval($1,$1,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
then AC_RUN_LOG([: m4_ifval($1,$1,FLAGS) does contain $VAR])
else AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"])
m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"
fi ]) ;;
esac
AS_VAR_POPDEF([VAR])dnl
AS_VAR_POPDEF([FLAGS])dnl
])
dnl the only difference - the LANG selection... and the default FLAGS
AC_DEFUN([AX_CXXFLAGS_SUN_OPTION_OLD], [dnl
AS_VAR_PUSHDEF([FLAGS],[CXXFLAGS])dnl
AS_VAR_PUSHDEF([VAR],[ac_cv_cxxflags_sun_option_$2])dnl
AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for sun/cc m4_ifval($2,$2,-option)],
VAR,[VAR="no, unknown"
AC_LANG_SAVE
AC_LANG_CXX
ac_save_[]FLAGS="$[]FLAGS"
for ac_arg dnl
in "+xstrconst % -xc99=all m4_ifval($2,$2,-option)" dnl Solaris C
#
do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
AC_TRY_COMPILE([],[return 0;],
[VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
done
FLAGS="$ac_save_[]FLAGS"
AC_LANG_RESTORE
])
case ".$VAR" in
.ok|.ok,*) m4_ifvaln($3,$3) ;;
.|.no|.no,*) m4_ifvaln($4,$4) ;;
*) m4_ifvaln($3,$3,[
if echo " $[]m4_ifval($1,$1,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
then AC_RUN_LOG([: m4_ifval($1,$1,FLAGS) does contain $VAR])
else AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"])
m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"
fi ]) ;;
esac
AS_VAR_POPDEF([VAR])dnl
AS_VAR_POPDEF([FLAGS])dnl
])
dnl -----------------------------------------------------------------------
AC_DEFUN([AX_CFLAGS_SUN_OPTION_NEW], [dnl
AS_VAR_PUSHDEF([FLAGS],[CFLAGS])dnl
AS_VAR_PUSHDEF([VAR],[ac_cv_cflags_sun_option_$1])dnl
AC_CACHE_CHECK([m4_ifval($2,$2,FLAGS) for sun/cc m4_ifval($1,$1,-option)],
VAR,[VAR="no, unknown"
AC_LANG_SAVE
AC_LANG_C
ac_save_[]FLAGS="$[]FLAGS"
for ac_arg dnl
in "+xstrconst % -xc99=all m4_ifval($1,$1,-option)" dnl Solaris C
#
do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
AC_TRY_COMPILE([],[return 0;],
[VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
done
FLAGS="$ac_save_[]FLAGS"
AC_LANG_RESTORE
])
case ".$VAR" in
.ok|.ok,*) m4_ifvaln($3,$3) ;;
.|.no|.no,*) m4_ifvaln($4,$4) ;;
*) m4_ifvaln($3,$3,[
if echo " $[]m4_ifval($2,$2,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
then AC_RUN_LOG([: m4_ifval($2,$2,FLAGS) does contain $VAR])
else AC_RUN_LOG([: m4_ifval($2,$2,FLAGS)="$m4_ifval($2,$2,FLAGS) $VAR"])
m4_ifval($2,$2,FLAGS)="$m4_ifval($2,$2,FLAGS) $VAR"
fi ]) ;;
esac
AS_VAR_POPDEF([VAR])dnl
AS_VAR_POPDEF([FLAGS])dnl
])
dnl the only difference - the LANG selection... and the default FLAGS
AC_DEFUN([AX_CXXFLAGS_SUN_OPTION_NEW], [dnl
AS_VAR_PUSHDEF([FLAGS],[CXXFLAGS])dnl
AS_VAR_PUSHDEF([VAR],[ac_cv_cxxflags_sun_option_$1])dnl
AC_CACHE_CHECK([m4_ifval($2,$2,FLAGS) for sun/cc m4_ifval($1,$1,-option)],
VAR,[VAR="no, unknown"
AC_LANG_SAVE
AC_LANG_CXX
ac_save_[]FLAGS="$[]FLAGS"
for ac_arg dnl
in "+xstrconst % -xc99=all m4_ifval($1,$1,-option)" dnl Solaris C
#
do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
AC_TRY_COMPILE([],[return 0;],
[VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
done
FLAGS="$ac_save_[]FLAGS"
AC_LANG_RESTORE
])
case ".$VAR" in
.ok|.ok,*) m4_ifvaln($3,$3) ;;
.|.no|.no,*) m4_ifvaln($4,$4) ;;
*) m4_ifvaln($3,$3,[
if echo " $[]m4_ifval($2,$2,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
then AC_RUN_LOG([: m4_ifval($2,$2,FLAGS) does contain $VAR])
else AC_RUN_LOG([: m4_ifval($2,$2,FLAGS)="$m4_ifval($2,$2,FLAGS) $VAR"])
m4_ifval($2,$2,FLAGS)="$m4_ifval($2,$2,FLAGS) $VAR"
fi ]) ;;
esac
AS_VAR_POPDEF([VAR])dnl
AS_VAR_POPDEF([FLAGS])dnl
])
AC_DEFUN([AX_CFLAGS_SUN_OPTION],[ifelse(m4_regexp([$2],[-]),-1,
[AX_CFLAGS_SUN_OPTION_NEW($@)],[AX_CFLAGS_SUN_OPTION_OLD($@)])])
AC_DEFUN([AX_CXXFLAGS_SUN_OPTION],[ifelse(m4_regexp([$2],[-]),-1,
[AX_CXXFLAGS_SUN_OPTION_NEW($@)],[AX_CXXFLAGS_SUN_OPTION_OLD($@)])])

View File

@ -0,0 +1,148 @@
AC_DEFUN([AX_GCC_ARCHFLAG],
[AC_REQUIRE([AC_PROG_CC])
AC_ARG_WITH(gcc-arch, [AC_HELP_STRING([--with-gcc-arch=<arch>], [use architecture <arch> for gcc -march/-mtune, instead of guessing])],
ax_gcc_arch=$withval, ax_gcc_arch=yes)
AC_MSG_CHECKING([for gcc architecture flag])
AC_MSG_RESULT([])
AC_CACHE_VAL(ax_cv_gcc_archflag,
[
ax_cv_gcc_archflag="unknown"
if test "$GCC" = yes; then
if test "x$ax_gcc_arch" = xyes; then
ax_gcc_arch=""
if test "$cross_compiling" = no; then
case $host_cpu in
i[[3456]]86*|x86_64*) # use cpuid codes, in part from x86info-1.7 by D. Jones
AX_GCC_X86_CPUID(0)
AX_GCC_X86_CPUID(1)
case $ax_cv_gcc_x86_cpuid_0 in
*:756e6547:*:*) # Intel
case $ax_cv_gcc_x86_cpuid_1 in
*5[[48]]?:*:*:*) ax_gcc_arch="pentium-mmx pentium" ;;
*5??:*:*:*) ax_gcc_arch=pentium ;;
*6[[3456]]?:*:*:*) ax_gcc_arch="pentium2 pentiumpro" ;;
*6a?:*[[01]]:*:*) ax_gcc_arch="pentium2 pentiumpro" ;;
*6a?:*[[234]]:*:*) ax_gcc_arch="pentium3 pentiumpro" ;;
*6[[9d]]?:*:*:*) ax_gcc_arch="pentium-m pentium3 pentiumpro" ;;
*6[[78b]]?:*:*:*) ax_gcc_arch="pentium3 pentiumpro" ;;
*6??:*:*:*) ax_gcc_arch=pentiumpro ;;
*f3[[347]]:*:*:*|*f4[1347]:*:*:*)
case $host_cpu in
x86_64*) ax_gcc_arch="nocona pentium4 pentiumpro" ;;
*) ax_gcc_arch="prescott pentium4 pentiumpro" ;;
esac ;;
*f??:*:*:*) ax_gcc_arch="pentium4 pentiumpro";;
esac ;;
*:68747541:*:*) # AMD
case $ax_cv_gcc_x86_cpuid_1 in
*5[[67]]?:*:*:*) ax_gcc_arch=k6 ;;
*5[[8d]]?:*:*:*) ax_gcc_arch="k6-2 k6" ;;
*5[[9]]?:*:*:*) ax_gcc_arch="k6-3 k6" ;;
*60?:*:*:*) ax_gcc_arch=k7 ;;
*6[[12]]?:*:*:*) ax_gcc_arch="athlon k7" ;;
*6[[34]]?:*:*:*) ax_gcc_arch="athlon-tbird k7" ;;
*67?:*:*:*) ax_gcc_arch="athlon-4 athlon k7" ;;
*6[[68a]]?:*:*:*)
AX_GCC_X86_CPUID(0x80000006) # L2 cache size
case $ax_cv_gcc_x86_cpuid_0x80000006 in
*:*:*[[1-9a-f]]??????:*) # (L2 = ecx >> 16) >= 256
ax_gcc_arch="athlon-xp athlon-4 athlon k7" ;;
*) ax_gcc_arch="athlon-4 athlon k7" ;;
esac ;;
*f[[4cef8b]]?:*:*:*) ax_gcc_arch="athlon64 k8" ;;
*f5?:*:*:*) ax_gcc_arch="opteron k8" ;;
*f7?:*:*:*) ax_gcc_arch="athlon-fx opteron k8" ;;
*f??:*:*:*) ax_gcc_arch="k8" ;;
esac ;;
*:746e6543:*:*) # IDT
case $ax_cv_gcc_x86_cpuid_1 in
*54?:*:*:*) ax_gcc_arch=winchip-c6 ;;
*58?:*:*:*) ax_gcc_arch=winchip2 ;;
*6[[78]]?:*:*:*) ax_gcc_arch=c3 ;;
*69?:*:*:*) ax_gcc_arch="c3-2 c3" ;;
esac ;;
esac
if test x"$ax_gcc_arch" = x; then # fallback
case $host_cpu in
i586*) ax_gcc_arch=pentium ;;
i686*) ax_gcc_arch=pentiumpro ;;
esac
fi
;;
sparc*)
AC_PATH_PROG([PRTDIAG], [prtdiag], [prtdiag], [$PATH:/usr/platform/`uname -i`/sbin/:/usr/platform/`uname -m`/sbin/])
cputype=`(((grep cpu /proc/cpuinfo | cut -d: -f2) ; ($PRTDIAG -v |grep -i sparc) ; grep -i cpu /var/run/dmesg.boot ) | head -n 1) 2> /dev/null`
cputype=`echo "$cputype" | tr -d ' -' |tr $as_cr_LETTERS $as_cr_letters`
case $cputype in
*ultrasparciv*) ax_gcc_arch="ultrasparc4 ultrasparc3 ultrasparc v9" ;;
*ultrasparciii*) ax_gcc_arch="ultrasparc3 ultrasparc v9" ;;
*ultrasparc*) ax_gcc_arch="ultrasparc v9" ;;
*supersparc*|*tms390z5[[05]]*) ax_gcc_arch="supersparc v8" ;;
*hypersparc*|*rt62[[056]]*) ax_gcc_arch="hypersparc v8" ;;
*cypress*) ax_gcc_arch=cypress ;;
esac ;;
alphaev5) ax_gcc_arch=ev5 ;;
alphaev56) ax_gcc_arch=ev56 ;;
alphapca56) ax_gcc_arch="pca56 ev56" ;;
alphapca57) ax_gcc_arch="pca57 pca56 ev56" ;;
alphaev6) ax_gcc_arch=ev6 ;;
alphaev67) ax_gcc_arch=ev67 ;;
alphaev68) ax_gcc_arch="ev68 ev67" ;;
alphaev69) ax_gcc_arch="ev69 ev68 ev67" ;;
alphaev7) ax_gcc_arch="ev7 ev69 ev68 ev67" ;;
alphaev79) ax_gcc_arch="ev79 ev7 ev69 ev68 ev67" ;;
powerpc*)
cputype=`((grep cpu /proc/cpuinfo | head -n 1 | cut -d: -f2 | cut -d, -f1 | sed 's/ //g') ; /usr/bin/machine ; /bin/machine; grep CPU /var/run/dmesg.boot | head -n 1 | cut -d" " -f2) 2> /dev/null`
cputype=`echo $cputype | sed -e 's/ppc//g;s/ *//g'`
case $cputype in
*750*) ax_gcc_arch="750 G3" ;;
*740[[0-9]]*) ax_gcc_arch="$cputype 7400 G4" ;;
*74[[4-5]][[0-9]]*) ax_gcc_arch="$cputype 7450 G4" ;;
*74[[0-9]][[0-9]]*) ax_gcc_arch="$cputype G4" ;;
*970*) ax_gcc_arch="970 G5 power4";;
*POWER4*|*power4*|*gq*) ax_gcc_arch="power4 970";;
*POWER5*|*power5*|*gr*|*gs*) ax_gcc_arch="power5 power4 970";;
603ev|8240) ax_gcc_arch="$cputype 603e 603";;
*) ax_gcc_arch=$cputype ;;
esac
ax_gcc_arch="$ax_gcc_arch powerpc"
;;
esac
fi # not cross-compiling
fi # guess arch
if test "x$ax_gcc_arch" != x -a "x$ax_gcc_arch" != xno; then
for arch in $ax_gcc_arch; do
if test "x[]m4_default([$1],yes)" = xyes; then # if we require portable code
flags="-mtune=$arch"
# -mcpu=$arch and m$arch generate nonportable code on every arch except
# x86. And some other arches (e.g. Alpha) don't accept -mtune. Grrr.
case $host_cpu in i*86|x86_64*) flags="$flags -mcpu=$arch -m$arch";; esac
else
flags="-march=$arch -mcpu=$arch -m$arch"
fi
for flag in $flags; do
AX_CHECK_COMPILER_FLAGS($flag, [ax_cv_gcc_archflag=$flag; break])
done
test "x$ax_cv_gcc_archflag" = xunknown || break
done
fi
fi # $GCC=yes
])
AC_MSG_CHECKING([for gcc architecture flag])
AC_MSG_RESULT($ax_cv_gcc_archflag)
if test "x$ax_cv_gcc_archflag" = xunknown; then
m4_default([$3],:)
else
m4_default([$2], [CFLAGS="$CFLAGS $ax_cv_gcc_archflag"])
fi
])

View File

@ -0,0 +1,21 @@
AC_DEFUN([AX_GCC_X86_CPUID],
[AC_REQUIRE([AC_PROG_CC])
AC_LANG_PUSH([C])
AC_CACHE_CHECK(for x86 cpuid $1 output, ax_cv_gcc_x86_cpuid_$1,
[AC_RUN_IFELSE([AC_LANG_PROGRAM([#include <stdio.h>], [
int op = $1, eax, ebx, ecx, edx;
FILE *f;
__asm__("cpuid"
: "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
: "a" (op));
f = fopen("conftest_cpuid", "w"); if (!f) return 1;
fprintf(f, "%x:%x:%x:%x\n", eax, ebx, ecx, edx);
fclose(f);
return 0;
])],
[ax_cv_gcc_x86_cpuid_$1=`cat conftest_cpuid`; rm -f conftest_cpuid],
[ax_cv_gcc_x86_cpuid_$1=unknown; rm -f conftest_cpuid],
[ax_cv_gcc_x86_cpuid_$1=unknown])])
AC_LANG_POP([C])
])

View File

@ -0,0 +1,9 @@
AC_DEFUN([AC_PROG_GZIP],[
AC_CHECK_PROGS(gzip,[gzip],no)
export gzip;
if test $gzip = "no" ;
then
AC_MSG_ERROR([Unable to find the gzip application]);
fi
AC_SUBST(gzip)
])

View File

@ -0,0 +1,9 @@
AC_DEFUN([AC_PROG_WGET],[
AC_CHECK_PROGS(wget,[wget],no)
export wget;
if test $wget = "no" ;
then
AC_MSG_ERROR([Unable to find the wget application]);
fi
AC_SUBST(wget)
])

View File

@ -0,0 +1,120 @@
AC_DEFUN([AX_CC_MAXOPT],
[
AC_REQUIRE([AC_PROG_CC])
AC_REQUIRE([AX_COMPILER_VENDOR])
AC_ARG_ENABLE(portable-binary, [AC_HELP_STRING([--enable-portable-binary], [disable compiler optimizations that would produce unportable binaries])],
acx_maxopt_portable=$withval, acx_maxopt_portable=no)
# Try to determine "good" native compiler flags if none specified via CFLAGS
if test "$ac_test_CFLAGS" != "set"; then
CFLAGS=""
case $ax_cv_c_compiler_vendor in
dec) CFLAGS="-newc -w0 -O5 -ansi_alias -ansi_args -fp_reorder -tune host"
if test "x$acx_maxopt_portable" = xno; then
CFLAGS="$CFLAGS -arch host"
fi;;
sun) CFLAGS="-native -fast -xO5 -dalign -xc99=all"
if test "x$acx_maxopt_portable" = xyes; then
CFLAGS="$CFLAGS -xarch=generic"
fi;;
hp) CFLAGS="+Oall +Optrs_ansi +DSnative"
if test "x$acx_maxopt_portable" = xyes; then
CFLAGS="$CFLAGS +DAportable"
fi;;
ibm) if test "x$acx_maxopt_portable" = xno; then
xlc_opt="-qarch=auto -qtune=auto"
else
xlc_opt="-qtune=auto"
fi
AX_CHECK_COMPILER_FLAGS($xlc_opt,
CFLAGS="-O3 -qansialias -w $xlc_opt",
[CFLAGS="-O3 -qansialias -w"
echo "******************************************************"
echo "* You seem to have the IBM C compiler. It is *"
echo "* recommended for best performance that you use: *"
echo "* *"
echo "* CFLAGS=-O3 -qarch=xxx -qtune=xxx -qansialias -w *"
echo "* ^^^ ^^^ *"
echo "* where xxx is pwr2, pwr3, 604, or whatever kind of *"
echo "* CPU you have. (Set the CFLAGS environment var. *"
echo "* and re-run configure.) For more info, man cc. *"
echo "******************************************************"])
;;
intel) CFLAGS="-O3 -ansi_alias"
if test "x$acx_maxopt_portable" = xno; then
icc_archflag=unknown
icc_flags=""
case $host_cpu in
i686*|x86_64*)
# icc accepts gcc assembly syntax, so these should work:
AX_GCC_X86_CPUID(0)
AX_GCC_X86_CPUID(1)
case $ax_cv_gcc_x86_cpuid_0 in # see AX_GCC_ARCHFLAG
*:756e6547:*:*) # Intel
case $ax_cv_gcc_x86_cpuid_1 in
*6a?:*[[234]]:*:*|*6[[789b]]?:*:*:*) icc_flags="-xK";;
*f3[[347]]:*:*:*|*f4[1347]:*:*:*) icc_flags="-xP -xN -xW -xK";;
*f??:*:*:*) icc_flags="-xN -xW -xK";;
esac ;;
esac ;;
esac
if test "x$icc_flags" != x; then
for flag in $icc_flags; do
AX_CHECK_COMPILER_FLAGS($flag, [icc_archflag=$flag; break])
done
fi
AC_MSG_CHECKING([for icc architecture flag])
AC_MSG_RESULT($icc_archflag)
if test "x$icc_archflag" != xunknown; then
CFLAGS="$CFLAGS $icc_archflag"
fi
fi
;;
gnu)
# default optimization flags for gcc on all systems
CFLAGS="-O3 -fomit-frame-pointer"
# -malign-double for x86 systems
AX_CHECK_COMPILER_FLAGS(-malign-double, CFLAGS="$CFLAGS -malign-double")
# -fstrict-aliasing for gcc-2.95+
AX_CHECK_COMPILER_FLAGS(-fstrict-aliasing,
CFLAGS="$CFLAGS -fstrict-aliasing")
# note that we enable "unsafe" fp optimization with other compilers, too
AX_CHECK_COMPILER_FLAGS(-ffast-math, CFLAGS="$CFLAGS -ffast-math")
AX_GCC_ARCHFLAG($acx_maxopt_portable)
;;
esac
if test -z "$CFLAGS"; then
echo ""
echo "********************************************************"
echo "* WARNING: Don't know the best CFLAGS for this system *"
echo "* Use ./configure CFLAGS=... to specify your own flags *"
echo "* (otherwise, a default of CFLAGS=-O3 will be used) *"
echo "********************************************************"
echo ""
CFLAGS="-O3"
fi
AX_CHECK_COMPILER_FLAGS($CFLAGS, [], [
echo ""
echo "********************************************************"
echo "* WARNING: The guessed CFLAGS don't seem to work with *"
echo "* your compiler. *"
echo "* Use ./configure CFLAGS=... to specify your own flags *"
echo "********************************************************"
echo ""
CFLAGS=""
])
fi
])

View File

@ -0,0 +1,94 @@
AC_DEFUN([AX_CFLAGS_WARN_ALL_ANSI],[dnl
AS_VAR_PUSHDEF([FLAGS],[CFLAGS])dnl
AS_VAR_PUSHDEF([VAR],[ac_cv_cflags_warn_all_ansi])dnl
AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for maximum ansi warnings],
VAR,[VAR="no, unknown"
AC_LANG_SAVE
AC_LANG_C
ac_save_[]FLAGS="$[]FLAGS"
# IRIX C compiler:
# -use_readonly_const is the default for IRIX C,
# puts them into .rodata, but they are copied later.
# need to be "-G0 -rdatashared" for strictmode but
# I am not sure what effect that has really. - guidod
for ac_arg dnl
in "-pedantic % -Wall -std=c99 -pedantic" dnl GCC
"-xstrconst % -v -xc99=all" dnl Solaris C
"-std1 % -verbose -w0 -warnprotos -std1" dnl Digital Unix
" % -qlanglvl=ansi -qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd" dnl AIX
" % -ansi -ansiE -fullwarn" dnl IRIX
"+ESlit % +w1 -Aa" dnl HP-UX C
"-Xc % -pvctl[,]fullmsg -Xc" dnl NEC SX-5 (Super-UX 10)
"-h conform % -h msglevel 2 -h conform" dnl Cray C (Unicos)
#
do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
AC_TRY_COMPILE([],[return 0;],
[VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
done
FLAGS="$ac_save_[]FLAGS"
AC_LANG_RESTORE
])
case ".$VAR" in
.ok|.ok,*) m4_ifvaln($3,$3) ;;
.|.no|.no,*) m4_ifvaln($4,$4,[m4_ifval($2,[
AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $2"])
m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $2"])]) ;;
*) m4_ifvaln($3,$3,[
if echo " $[]m4_ifval($1,$1,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
then AC_RUN_LOG([: m4_ifval($1,$1,FLAGS) does contain $VAR])
else AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"])
m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"
fi ]) ;;
esac
AS_VAR_POPDEF([VAR])dnl
AS_VAR_POPDEF([FLAGS])dnl
])
dnl the only difference - the LANG selection... and the default FLAGS
AC_DEFUN([AX_CXXFLAGS_WARN_ALL_ANSI],[dnl
AS_VAR_PUSHDEF([FLAGS],[CXXFLAGS])dnl
AS_VAR_PUSHDEF([VAR],[ac_cv_cxxflags_warn_all_ansi])dnl
AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for maximum ansi warnings],
VAR,[VAR="no, unknown"
AC_LANG_SAVE
AC_LANG_CXX
ac_save_[]FLAGS="$[]FLAGS"
# IRIX C compiler:
# -use_readonly_const is the default for IRIX C,
# puts them into .rodata, but they are copied later.
# need to be "-G0 -rdatashared" for strictmode but
# I am not sure what effect that has really. - guidod
for ac_arg dnl
in "-pedantic % -Wall -ansi -pedantic" dnl GCC
"-xstrconst % -v -Xc" dnl Solaris C
"-std1 % -verbose -w0 -warnprotos -std1" dnl Digital Unix
" % -qlanglvl=ansi -qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd" dnl AIX
" % -ansi -ansiE -fullwarn" dnl IRIX
"+ESlit % +w1 -Aa" dnl HP-UX C
"-Xc % -pvctl[,]fullmsg -Xc" dnl NEC SX-5 (Super-UX 10)
"-h conform % -h msglevel 2 -h conform" dnl Cray C (Unicos)
#
do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
AC_TRY_COMPILE([],[return 0;],
[VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
done
FLAGS="$ac_save_[]FLAGS"
AC_LANG_RESTORE
])
case ".$VAR" in
.ok|.ok,*) m4_ifvaln($3,$3) ;;
.|.no|.no,*) m4_ifvaln($4,$4,[m4_ifval($2,[
AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $2"])
m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $2"])]) ;;
*) m4_ifvaln($3,$3,[
if echo " $[]m4_ifval($1,$1,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
then AC_RUN_LOG([: m4_ifval($1,$1,FLAGS) does contain $VAR])
else AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"])
m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"
fi ]) ;;
esac
AS_VAR_POPDEF([VAR])dnl
AS_VAR_POPDEF([FLAGS])dnl
])

View File

@ -0,0 +1,26 @@
AC_DEFUN([AX_CHECK_COMPILER_FLAGS],
[AC_PREREQ(2.59) dnl for _AC_LANG_PREFIX
AC_MSG_CHECKING([whether _AC_LANG compiler accepts $1])
dnl Some hackery here since AC_CACHE_VAL can't handle a non-literal varname:
AS_LITERAL_IF([$1],
[AC_CACHE_VAL(AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1), [
ax_save_FLAGS=$[]_AC_LANG_PREFIX[]FLAGS
_AC_LANG_PREFIX[]FLAGS="$1"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1)=yes,
AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1)=no)
_AC_LANG_PREFIX[]FLAGS=$ax_save_FLAGS])],
[ax_save_FLAGS=$[]_AC_LANG_PREFIX[]FLAGS
_AC_LANG_PREFIX[]FLAGS="$1"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
eval AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1)=yes,
eval AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1)=no)
_AC_LANG_PREFIX[]FLAGS=$ax_save_FLAGS])
eval ax_check_compiler_flags=$AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1)
AC_MSG_RESULT($ax_check_compiler_flags)
if test "x$ax_check_compiler_flags" = xyes; then
m4_default([$2], :)
else
m4_default([$3], :)
fi
])dnl AX_CHECK_COMPILER_FLAG

View File

@ -0,0 +1,15 @@
AC_DEFUN([AX_COMPILER_VENDOR],
[
AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor,
[ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=unknown
# note: don't check for gcc first since some other compilers define __GNUC__
for ventest in intel:__ICC,__ECC,__INTEL_COMPILER ibm:__xlc__,__xlC__,__IBMC__,__IBMCPP__ gnu:__GNUC__ sun:__SUNPRO_C,__SUNPRO_CC hp:__HP_cc,__HP_aCC dec:__DECC,__DECCXX,__DECC_VER,__DECCXX_VER borland:__BORLANDC__,__TURBOC__ comeau:__COMO__ cray:_CRAYC kai:__KCC lcc:__LCC__ metrowerks:__MWERKS__ sgi:__sgi,sgi microsoft:_MSC_VER watcom:__WATCOMC__ portland:__PGI; do
vencpp="defined("`echo $ventest | cut -d: -f2 | sed 's/,/) || defined(/g'`")"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[
#if !($vencpp)
thisisanerror;
#endif
])], [ax_cv_]_AC_LANG_ABBREV[_compiler_vendor=`echo $ventest | cut -d: -f1`; break])
done
])
])

View File

@ -0,0 +1,49 @@
dnl ======================================================================
dnl SAC_OPENSSL
dnl ======================================================================
AC_DEFUN([SAC_OPENSSL], [
AC_ARG_WITH(openssl,
[ --with-openssl use OpenSSL [[enabled]]],, with_openssl=pkg-config)
dnl SOSXXX:SAC_ASSERT_DEF([openssl libraries])
if test "$with_openssl" = no ;then
: # No openssl
else
if test "$with_openssl" = "pkg-config" ; then
PKG_CHECK_MODULES(openssl, openssl,
[HAVE_TLS=1 HAVE_OPENSSL=1 LIBS="$openssl_LIBS $LIBS"],
[HAVE_OPENSSL=0])
fi
if test x$HAVE_OPENSSL = x1 ; then
AC_DEFINE([HAVE_LIBCRYPTO], 1, [Define to 1 if you have the `crypto' library (-lcrypto).])
AC_DEFINE([HAVE_LIBSSL], 1, [Define to 1 if you have the `ssl' library (-lssl).])
else
AC_CHECK_HEADERS([openssl/tls1.h], [
HAVE_OPENSSL=1 HAVE_TLS=1
AC_CHECK_LIB(crypto, BIO_new,,
HAVE_OPENSSL=0
AC_MSG_WARN(OpenSSL crypto library was not found))
AC_CHECK_LIB(ssl, TLSv1_method,,
HAVE_TLS=0
AC_MSG_WARN(OpenSSL protocol library was not found))
],[AC_MSG_WARN(OpenSSL include files were not found)],[#include <openssl/safestack.h>])
fi
if test x$HAVE_OPENSSL = x1; then
AC_DEFINE([HAVE_OPENSSL], 1, [Define to 1 if you have OpenSSL])
fi
if test x$HAVE_TLS = x1; then
AC_DEFINE([HAVE_TLS], 1, [Define to 1 if you have TLS])
fi
fi
AM_CONDITIONAL(HAVE_TLS, test x$HAVE_TLS = x1)
])

258
libs/libks/configure.ac Normal file
View File

@ -0,0 +1,258 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
AC_INIT(libks, 0.1, bugs@freeswitch.org)
AC_CONFIG_AUX_DIR(build)
AC_CONFIG_MACRO_DIR([build])
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([src])
# disable checks
m4_defun([_LT_AC_LANG_CXX_CONFIG], [:])
m4_defun([_LT_AC_LANG_F77_CONFIG], [:])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
# Checks for programs.
AC_PROG_CC
AC_PROG_CXX
AC_PROG_MAKE_SET
AC_PROG_LIBTOOL
AC_PROG_INSTALL
# Optimize
AC_ARG_ENABLE(optimization,
[AC_HELP_STRING([--enable-optimization],[Set if you want us to add max optimising compiler flags])],[enable_optimizer="$enableval"],[enable_optimizer="no"])
if test "${enable_optimizer}" = "yes" ; then
AC_DEFINE([OPTIMZER],[],[Enable Optimization.])
AX_CC_MAXOPT
fi
# Enable debugging
AC_ARG_ENABLE(debug,
[AC_HELP_STRING([--enable-debug],[build with debug information])],[enable_debug="$enable_debug"],[enable_debug="no"])
if test "${enable_debug}" = "yes"; then
AC_DEFINE([DEBUG],[],[Enable extra debugging.])
fi
AM_CONDITIONAL([WANT_DEBUG],[test "${enable_debug}" = "yes"])
dnl check for the compiler used
AX_COMPILER_VENDOR
case "$host" in
*-solaris2*)
if test "x${ax_cv_c_compiler_vendor}" = "xsun" ; then
AM_CFLAGS="-KPIC -DPIC"
AM_LDFLAGS="-R${prefix}/lib"
fi
;;
*-darwin*)
if test "x${ax_cv_c_compiler_vendor}" = "xgnu" ; then
AM_CFLAGS="-DMACOSX"
fi
;;
x86_64-unknown-linux-gnu)
AM_CFLAGS="-fPIC"
AM_LDFLAGS=""
;;
i*6-unknown-linux-gnu)
AM_CFLAGS="-fpic"
AM_LDFLAGS=""
;;
x86_64-*-freebsd*|amd64-*-freebsd*)
AM_CFLAGS="-fpic"
AM_LDFLAGS=""
;;
i*6-*-freebsd*)
AM_CFLAGS="-fpic"
AM_LDFLAGS=""
;;
esac
AX_CFLAGS_WARN_ALL_ANSI
AC_CHECK_LIB(rt, clock_gettime, [AC_DEFINE(HAVE_CLOCK_GETTIME, 1, [Define if you have clock_gettime()])])
AC_CHECK_LIB(rt, clock_getres, [AC_DEFINE(HAVE_CLOCK_GETRES, 1, [Define if you have clock_getres()])])
AC_CHECK_LIB(rt, clock_nanosleep, [AC_DEFINE(HAVE_CLOCK_NANOSLEEP, 1, [Define if you have clock_nanosleep()])])
AC_CHECK_FUNCS([usleep])
#
# sched_setcheduler + round-robin scheduler prerequisites
#
AC_CHECK_HEADERS([sched.h byteswap.h sys/endian.h])
AC_CHECK_DECL([SCHED_RR],
[AC_DEFINE([HAVE_SCHED_RR],[1],[SCHED_RR constant for sched_setscheduler])],,
[#ifdef HAVE_SCHED_H
#include <sched.h>
#endif])
AC_CHECK_FUNCS([sched_setscheduler memmem])
if test "x${ac_cv_func_sched_setscheduler}" = "xyes" -a \
"x${ac_cv_have_decl_SCHED_RR}" = "xyes"
then
AC_DEFINE([USE_SCHED_SETSCHEDULER],[1],[Enable round-robin scheduler using sched_setscheduler])
AM_CFLAGS="${AM_CFLAGS} -DUSE_SCHED_SETSCHEDULER=1"
fi
#
# gcc visibility cflag checks
#
AC_ARG_ENABLE([visibility],
[AS_HELP_STRING([--disable-visibility], [Disable or enable API visibility support (default: use if available)])],
[enable_visibility="${enableval}"],
[enable_visibility="detect"]
)
HAVE_VISIBILITY="no"
if test "x${enable_visibility}" != "xno" ; then
case "${ax_cv_c_compiler_vendor}" in
gnu)
save_CFLAGS="${CFLAGS}"
CFLAGS="${CFLAGS} -fvisibility=hidden"
AC_MSG_CHECKING([whether the compiler supports -fvisibility=hidden])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[int foo __attribute__ ((visibility("default")));],
[;]
)],
[AC_MSG_RESULT([yes])
AM_CFLAGS="${AM_CFLAGS} -DKS_API_VISIBILITY=1 -fvisibility=hidden"
AC_DEFINE([HAVE_VISIBILITY], [1], [GCC visibility support available])
HAVE_VISIBILITY="yes"],
[AC_MSG_RESULT([no])]
)
CFLAGS="${save_CFLAGS}"
;;
sun)
save_CFLAGS="${CFLAGS}"
CFLAGS="${CFLAGS} -xldscope=hidden"
AC_MSG_CHECKING([whether the compiler supports -xldscope=hidden])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[int foo __attribute__ ((visibility("default")));],
[;]
)],
[AC_MSG_RESULT([yes])
AM_CFLAGS="${AM_CFLAGS} -DKS_API_VISIBILITY=1 -xldscope=hidden"
AC_DEFINE([HAVE_VISIBILITY], [1], [SUNCC visibility support available])
HAVE_VISIBILITY="yes"],
[AC_MSG_RESULT([no])]
)
CFLAGS="${save_CFLAGS}"
;;
*)
if test "x${enable_visibility}" = "xyes" ; then
AC_MSG_ERROR([Non-GNU / SUN compilers are currently unsupported])
else
AC_MSG_WARN([Non-GNU / SUN compilers are currently unsupported])
fi
;;
esac
#
# visibility explicitly requested but not supported by this compiler => error
#
if test "x${enable_visibility}" = "xyes" -a "x${HAVE_VISIBILITY}" = "xno" ; then
AC_MSG_ERROR([API visibility not supported by this compiler])
fi
fi
AM_CFLAGS="${AM_CFLAGS} -Werror"
AC_SUBST(AM_CFLAGS)
AC_SUBST(AM_LDFLAGS)
# Checks for header files.
AC_HEADER_DIRENT
AC_HEADER_STDC
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_C_INLINE
AC_TYPE_SIZE_T
AC_HEADER_TIME
AC_STRUCT_TM
# Checks for library functions.
AC_PROG_GCC_TRADITIONAL
AC_FUNC_MALLOC
AC_TYPE_SIGNAL
AC_FUNC_STRFTIME
AC_CHECK_LIB(pthread, pthread_setschedparam, [
AC_DEFINE(HAVE_PTHREAD_SETSCHEDPARAM, 1, [Define if you have pthread_setschedparam()])
AM_CFLAGS="${AM_CFLAGS} -DHAVE_PTHREAD_SETSCHEDPARAM=1"
])
AC_C_BIGENDIAN(AC_DEFINE([__BYTE_ORDER],__BIG_ENDIAN,[Big Endian]),AC_DEFINE([__BYTE_ORDER],__LITTLE_ENDIAN,[Little Endian]))
AC_DEFINE([__LITTLE_ENDIAN],1234,[for the places where it is not defined])
AC_DEFINE([__BIG_ENDIAN],4321,[for the places where it is not defined])
path_remove () {
echo "$1" | tr ':' '\n' | grep -Fxv "$2" | tr '\n' ':' | sed 's/:$//'
}
path_push_unique () {
x="$(eval echo \$$1)"
x="$(path_remove "$x" "$2")"
if test -z "$x"; then
eval export $1="$2"
else
eval export $1="$2:$x"
fi
}
case $host in
*-darwin*)
path_push_unique PKG_CONFIG_PATH /usr/local/opt/openssl/lib/pkgconfig
;;
esac
SAC_OPENSSL
if test x$HAVE_OPENSSL = x1; then
openssl_CFLAGS="$openssl_CFLAGS -DHAVE_OPENSSL";
AM_CFLAGS="${AM_CFLAGS} ${openssl_CFLAGS} -DHAVE_OPENSSL"
AM_LDFLAGS="${AM_LDFLAGS} ${openssl_LIBS}"
else
AC_MSG_ERROR([OpenSSL and associated developement headers required])
fi
# Enable clang address sanitizer bit build
AC_ARG_ENABLE(address_sanitizer,
[AC_HELP_STRING([--enable-address-sanitizer],[build with address sanitizer])],
[enable_address_sanitizer="$enable_address_sanitizer"],
[enable_address_sanitizer="no"])
if test "${enable_address_sanitizer}" = "yes"; then
if test "x${ax_cv_c_compiler_vendor}" = "xclang" ; then
AM_CFLAGS="${AM_CFLAGS} -fsanitize=address -fno-omit-frame-pointer"
AM_CXXFLAGS="${AM_CXXFLAGS} -fsanitize=address -fno-omit-frame-pointer"
AM_LDFLAGS="${AM_LDFLAGS} -fsanitize=address"
fi
fi
PKG_CHECK_MODULES([SODIUM], [libsodium >= 1.0.0],[AC_MSG_RESULT([yes])],[AC_MSG_ERROR([libsodium is required])])
PKG_CHECK_MODULES([UUID], [uuid >= 1.0.0],[AC_MSG_RESULT([yes])],[AC_MSG_ERROR([libuuid is required])])
AM_CFLAGS="${AM_CFLAGS} -Werror ${SODIUM_CFLAGS} ${UUID_CFLAGS}"
AM_LDFLAGS="${AM_LDFLAGS} ${SODIUM_LIBS} ${UUID_LIBS}"
AC_CONFIG_FILES([Makefile
test/Makefile
libks.pc
])
AC_OUTPUT

198
libs/libks/crypt/aes.h Normal file
View File

@ -0,0 +1,198 @@
/*
---------------------------------------------------------------------------
Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved.
The redistribution and use of this software (with or without changes)
is allowed without the payment of fees or royalties provided that:
source code distributions include the above copyright notice, this
list of conditions and the following disclaimer;
binary distributions include the above copyright notice, this list
of conditions and the following disclaimer in their documentation.
This software is provided 'as is' with no explicit or implied warranties
in respect of its operation, including, but not limited to, correctness
and fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 20/12/2007
This file contains the definitions required to use AES in C. See aesopt.h
for optimisation details.
*/
#ifndef _AES_H
#define _AES_H
#include <stdlib.h>
/* This include is used to find 8 & 32 bit unsigned integer types */
#include "brg_types.h"
#if defined(__cplusplus)
extern "C"
{
#endif
#define AES_128 /* if a fast 128 bit key scheduler is needed */
#define AES_192 /* if a fast 192 bit key scheduler is needed */
#define AES_256 /* if a fast 256 bit key scheduler is needed */
#define AES_VAR /* if variable key size scheduler is needed */
#define AES_MODES /* if support is needed for modes */
/* The following must also be set in assembler files if being used */
#define AES_ENCRYPT /* if support for encryption is needed */
#define AES_DECRYPT /* if support for decryption is needed */
#define AES_REV_DKS /* define to reverse decryption key schedule */
#define AES_BLOCK_SIZE 16 /* the AES block size in bytes */
#define N_COLS 4 /* the number of columns in the state */
/* The key schedule length is 11, 13 or 15 16-byte blocks for 128, */
/* 192 or 256-bit keys respectively. That is 176, 208 or 240 bytes */
/* or 44, 52 or 60 32-bit words. */
#if defined( AES_VAR ) || defined( AES_256 )
#define KS_LENGTH 60
#elif defined( AES_192 )
#define KS_LENGTH 52
#else
#define KS_LENGTH 44
#endif
#define AES_RETURN INT_RETURN
/* the character array 'inf' in the following structures is used */
/* to hold AES context information. This AES code uses cx->inf.b[0] */
/* to hold the number of rounds multiplied by 16. The other three */
/* elements can be used by code that implements additional modes */
typedef union
{ uint_32t l;
uint_8t b[4];
} aes_inf;
typedef struct
{ uint_32t ks[KS_LENGTH];
aes_inf inf;
} aes_encrypt_ctx;
typedef struct
{ uint_32t ks[KS_LENGTH];
aes_inf inf;
} aes_decrypt_ctx;
/* This routine must be called before first use if non-static */
/* tables are being used */
AES_RETURN ks_aes_init(void);
/* Key lengths in the range 16 <= key_len <= 32 are given in bytes, */
/* those in the range 128 <= key_len <= 256 are given in bits */
#if defined( AES_ENCRYPT )
#if defined( AES_128 ) || defined( AES_VAR)
AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]);
#endif
#if defined( AES_192 ) || defined( AES_VAR)
AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]);
#endif
#if defined( AES_256 ) || defined( AES_VAR)
AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]);
#endif
#if defined( AES_VAR )
AES_RETURN aes_encrypt_key(const unsigned char *key, int key_len, aes_encrypt_ctx cx[1]);
#endif
AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1]);
#endif
#if defined( AES_DECRYPT )
#if defined( AES_128 ) || defined( AES_VAR)
AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]);
#endif
#if defined( AES_192 ) || defined( AES_VAR)
AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]);
#endif
#if defined( AES_256 ) || defined( AES_VAR)
AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]);
#endif
#if defined( AES_VAR )
AES_RETURN aes_decrypt_key(const unsigned char *key, int key_len, aes_decrypt_ctx cx[1]);
#endif
AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1]);
#endif
#if defined( AES_MODES )
/* Multiple calls to the following subroutines for multiple block */
/* ECB, CBC, CFB, OFB and CTR mode encryption can be used to handle */
/* long messages incremantally provided that the context AND the iv */
/* are preserved between all such calls. For the ECB and CBC modes */
/* each individual call within a series of incremental calls must */
/* process only full blocks (i.e. len must be a multiple of 16) but */
/* the CFB, OFB and CTR mode calls can handle multiple incremental */
/* calls of any length. Each mode is reset when a new AES key is */
/* set but ECB and CBC operations can be reset without setting a */
/* new key by setting a new IV value. To reset CFB, OFB and CTR */
/* without setting the key, aes_mode_reset() must be called and the */
/* IV must be set. NOTE: All these calls update the IV on exit so */
/* this has to be reset if a new operation with the same IV as the */
/* previous one is required (or decryption follows encryption with */
/* the same IV array). */
AES_RETURN aes_test_alignment_detection(unsigned int n);
AES_RETURN aes_ecb_encrypt(const unsigned char *ibuf, unsigned char *obuf,
int len, const aes_encrypt_ctx cx[1]);
AES_RETURN aes_ecb_decrypt(const unsigned char *ibuf, unsigned char *obuf,
int len, const aes_decrypt_ctx cx[1]);
AES_RETURN aes_cbc_encrypt(const unsigned char *ibuf, unsigned char *obuf,
int len, unsigned char *iv, const aes_encrypt_ctx cx[1]);
AES_RETURN aes_cbc_decrypt(const unsigned char *ibuf, unsigned char *obuf,
int len, unsigned char *iv, const aes_decrypt_ctx cx[1]);
AES_RETURN aes_mode_reset(aes_encrypt_ctx cx[1]);
AES_RETURN aes_cfb_encrypt(const unsigned char *ibuf, unsigned char *obuf,
int len, unsigned char *iv, aes_encrypt_ctx cx[1]);
AES_RETURN aes_cfb_decrypt(const unsigned char *ibuf, unsigned char *obuf,
int len, unsigned char *iv, aes_encrypt_ctx cx[1]);
#define aes_ofb_encrypt aes_ofb_crypt
#define aes_ofb_decrypt aes_ofb_crypt
AES_RETURN aes_ofb_crypt(const unsigned char *ibuf, unsigned char *obuf,
int len, unsigned char *iv, aes_encrypt_ctx cx[1]);
typedef void cbuf_inc(unsigned char *cbuf);
#define aes_ctr_encrypt aes_ctr_crypt
#define aes_ctr_decrypt aes_ctr_crypt
AES_RETURN aes_ctr_crypt(const unsigned char *ibuf, unsigned char *obuf,
int len, unsigned char *cbuf, cbuf_inc ctr_inc, aes_encrypt_ctx cx[1]);
#endif
#if defined(__cplusplus)
}
#endif
#endif

View File

@ -0,0 +1,946 @@
/*
---------------------------------------------------------------------------
Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved.
The redistribution and use of this software (with or without changes)
is allowed without the payment of fees or royalties provided that:
source code distributions include the above copyright notice, this
list of conditions and the following disclaimer;
binary distributions include the above copyright notice, this list
of conditions and the following disclaimer in their documentation.
This software is provided 'as is' with no explicit or implied warranties
in respect of its operation, including, but not limited to, correctness
and fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 20/12/2007
These subroutines implement multiple block AES modes for ECB, CBC, CFB,
OFB and CTR encryption, The code provides support for the VIA Advanced
Cryptography Engine (ACE).
NOTE: In the following subroutines, the AES contexts (ctx) must be
16 byte aligned if VIA ACE is being used
*/
#include <string.h>
#include <assert.h>
#include "aesopt.h"
#if defined( AES_MODES )
#if defined(__cplusplus)
extern "C"
{
#endif
#if defined( _MSC_VER ) && ( _MSC_VER > 800 )
#pragma intrinsic(memcpy)
#endif
#define BFR_BLOCKS 8
/* These values are used to detect long word alignment in order to */
/* speed up some buffer operations. This facility may not work on */
/* some machines so this define can be commented out if necessary */
#define FAST_BUFFER_OPERATIONS
#define lp32(x) ((uint_32t*)(x))
#if defined( USE_VIA_ACE_IF_PRESENT )
#include "aes_via_ace.h"
#pragma pack(16)
aligned_array(unsigned long, enc_gen_table, 12, 16) = NEH_ENC_GEN_DATA;
aligned_array(unsigned long, enc_load_table, 12, 16) = NEH_ENC_LOAD_DATA;
aligned_array(unsigned long, enc_hybrid_table, 12, 16) = NEH_ENC_HYBRID_DATA;
aligned_array(unsigned long, dec_gen_table, 12, 16) = NEH_DEC_GEN_DATA;
aligned_array(unsigned long, dec_load_table, 12, 16) = NEH_DEC_LOAD_DATA;
aligned_array(unsigned long, dec_hybrid_table, 12, 16) = NEH_DEC_HYBRID_DATA;
/* NOTE: These control word macros must only be used after */
/* a key has been set up because they depend on key size */
/* See the VIA ACE documentation for key type information */
/* and aes_via_ace.h for non-default NEH_KEY_TYPE values */
#ifndef NEH_KEY_TYPE
# define NEH_KEY_TYPE NEH_HYBRID
#endif
#if NEH_KEY_TYPE == NEH_LOAD
#define kd_adr(c) ((uint_8t*)(c)->ks)
#elif NEH_KEY_TYPE == NEH_GENERATE
#define kd_adr(c) ((uint_8t*)(c)->ks + (c)->inf.b[0])
#elif NEH_KEY_TYPE == NEH_HYBRID
#define kd_adr(c) ((uint_8t*)(c)->ks + ((c)->inf.b[0] == 160 ? 160 : 0))
#else
#error no key type defined for VIA ACE
#endif
#else
#define aligned_array(type, name, no, stride) type name[no]
#define aligned_auto(type, name, no, stride) type name[no]
#endif
#if defined( _MSC_VER ) && _MSC_VER > 1200
#define via_cwd(cwd, ty, dir, len) \
unsigned long* cwd = (dir##_##ty##_table + ((len - 128) >> 4))
#else
#define via_cwd(cwd, ty, dir, len) \
aligned_auto(unsigned long, cwd, 4, 16); \
cwd[1] = cwd[2] = cwd[3] = 0; \
cwd[0] = neh_##dir##_##ty##_key(len)
#endif
/* test the code for detecting and setting pointer alignment */
AES_RETURN aes_test_alignment_detection(unsigned int n) /* 4 <= n <= 16 */
{ uint_8t p[16];
uint_32t i, count_eq = 0, count_neq = 0;
if(n < 4 || n > 16)
return EXIT_FAILURE;
for(i = 0; i < n; ++i)
{
uint_8t *qf = ALIGN_FLOOR(p + i, n),
*qh = ALIGN_CEIL(p + i, n);
if(qh == qf)
++count_eq;
else if(qh == qf + n)
++count_neq;
else
return EXIT_FAILURE;
}
return (count_eq != 1 || count_neq != n - 1 ? EXIT_FAILURE : EXIT_SUCCESS);
}
AES_RETURN aes_mode_reset(aes_encrypt_ctx ctx[1])
{
ctx->inf.b[2] = 0;
return EXIT_SUCCESS;
}
AES_RETURN aes_ecb_encrypt(const unsigned char *ibuf, unsigned char *obuf,
int len, const aes_encrypt_ctx ctx[1])
{ int nb = len >> 4;
if(len & (AES_BLOCK_SIZE - 1))
return EXIT_FAILURE;
#if defined( USE_VIA_ACE_IF_PRESENT )
if(ctx->inf.b[1] == 0xff)
{ uint_8t *ksp = (uint_8t*)(ctx->ks);
via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
if(ALIGN_OFFSET( ctx, 16 ))
return EXIT_FAILURE;
if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))
{
via_ecb_op5(ksp, cwd, ibuf, obuf, nb);
}
else
{ aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
uint_8t *ip, *op;
while(nb)
{
int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);
ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);
op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
if(ip != ibuf)
memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
via_ecb_op5(ksp, cwd, ip, op, m);
if(op != obuf)
memcpy(obuf, buf, m * AES_BLOCK_SIZE);
ibuf += m * AES_BLOCK_SIZE;
obuf += m * AES_BLOCK_SIZE;
nb -= m;
}
}
return EXIT_SUCCESS;
}
#endif
#if !defined( ASSUME_VIA_ACE_PRESENT )
while(nb--)
{
if(aes_encrypt(ibuf, obuf, ctx) != EXIT_SUCCESS)
return EXIT_FAILURE;
ibuf += AES_BLOCK_SIZE;
obuf += AES_BLOCK_SIZE;
}
#endif
return EXIT_SUCCESS;
}
AES_RETURN aes_ecb_decrypt(const unsigned char *ibuf, unsigned char *obuf,
int len, const aes_decrypt_ctx ctx[1])
{ int nb = len >> 4;
if(len & (AES_BLOCK_SIZE - 1))
return EXIT_FAILURE;
#if defined( USE_VIA_ACE_IF_PRESENT )
if(ctx->inf.b[1] == 0xff)
{ uint_8t *ksp = kd_adr(ctx);
via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192);
if(ALIGN_OFFSET( ctx, 16 ))
return EXIT_FAILURE;
if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))
{
via_ecb_op5(ksp, cwd, ibuf, obuf, nb);
}
else
{ aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
uint_8t *ip, *op;
while(nb)
{
int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);
ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);
op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
if(ip != ibuf)
memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
via_ecb_op5(ksp, cwd, ip, op, m);
if(op != obuf)
memcpy(obuf, buf, m * AES_BLOCK_SIZE);
ibuf += m * AES_BLOCK_SIZE;
obuf += m * AES_BLOCK_SIZE;
nb -= m;
}
}
return EXIT_SUCCESS;
}
#endif
#if !defined( ASSUME_VIA_ACE_PRESENT )
while(nb--)
{
if(aes_decrypt(ibuf, obuf, ctx) != EXIT_SUCCESS)
return EXIT_FAILURE;
ibuf += AES_BLOCK_SIZE;
obuf += AES_BLOCK_SIZE;
}
#endif
return EXIT_SUCCESS;
}
AES_RETURN aes_cbc_encrypt(const unsigned char *ibuf, unsigned char *obuf,
int len, unsigned char *iv, const aes_encrypt_ctx ctx[1])
{ int nb = len >> 4;
if(len & (AES_BLOCK_SIZE - 1))
return EXIT_FAILURE;
#if defined( USE_VIA_ACE_IF_PRESENT )
if(ctx->inf.b[1] == 0xff)
{ uint_8t *ksp = (uint_8t*)(ctx->ks), *ivp = iv;
aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16);
via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
if(ALIGN_OFFSET( ctx, 16 ))
return EXIT_FAILURE;
if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */
{
ivp = liv;
memcpy(liv, iv, AES_BLOCK_SIZE);
}
if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ) && !ALIGN_OFFSET( iv, 16 ))
{
via_cbc_op7(ksp, cwd, ibuf, obuf, nb, ivp, ivp);
}
else
{ aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
uint_8t *ip, *op;
while(nb)
{
int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);
ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);
op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
if(ip != ibuf)
memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
via_cbc_op7(ksp, cwd, ip, op, m, ivp, ivp);
if(op != obuf)
memcpy(obuf, buf, m * AES_BLOCK_SIZE);
ibuf += m * AES_BLOCK_SIZE;
obuf += m * AES_BLOCK_SIZE;
nb -= m;
}
}
if(iv != ivp)
memcpy(iv, ivp, AES_BLOCK_SIZE);
return EXIT_SUCCESS;
}
#endif
#if !defined( ASSUME_VIA_ACE_PRESENT )
# ifdef FAST_BUFFER_OPERATIONS
if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( iv, 4 ))
while(nb--)
{
lp32(iv)[0] ^= lp32(ibuf)[0];
lp32(iv)[1] ^= lp32(ibuf)[1];
lp32(iv)[2] ^= lp32(ibuf)[2];
lp32(iv)[3] ^= lp32(ibuf)[3];
if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
return EXIT_FAILURE;
memcpy(obuf, iv, AES_BLOCK_SIZE);
ibuf += AES_BLOCK_SIZE;
obuf += AES_BLOCK_SIZE;
}
else
# endif
while(nb--)
{
iv[ 0] ^= ibuf[ 0]; iv[ 1] ^= ibuf[ 1];
iv[ 2] ^= ibuf[ 2]; iv[ 3] ^= ibuf[ 3];
iv[ 4] ^= ibuf[ 4]; iv[ 5] ^= ibuf[ 5];
iv[ 6] ^= ibuf[ 6]; iv[ 7] ^= ibuf[ 7];
iv[ 8] ^= ibuf[ 8]; iv[ 9] ^= ibuf[ 9];
iv[10] ^= ibuf[10]; iv[11] ^= ibuf[11];
iv[12] ^= ibuf[12]; iv[13] ^= ibuf[13];
iv[14] ^= ibuf[14]; iv[15] ^= ibuf[15];
if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
return EXIT_FAILURE;
memcpy(obuf, iv, AES_BLOCK_SIZE);
ibuf += AES_BLOCK_SIZE;
obuf += AES_BLOCK_SIZE;
}
#endif
return EXIT_SUCCESS;
}
AES_RETURN aes_cbc_decrypt(const unsigned char *ibuf, unsigned char *obuf,
int len, unsigned char *iv, const aes_decrypt_ctx ctx[1])
{ unsigned char tmp[AES_BLOCK_SIZE];
int nb = len >> 4;
if(len & (AES_BLOCK_SIZE - 1))
return EXIT_FAILURE;
#if defined( USE_VIA_ACE_IF_PRESENT )
if(ctx->inf.b[1] == 0xff)
{ uint_8t *ksp = kd_adr(ctx), *ivp = iv;
aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16);
via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192);
if(ALIGN_OFFSET( ctx, 16 ))
return EXIT_FAILURE;
if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */
{
ivp = liv;
memcpy(liv, iv, AES_BLOCK_SIZE);
}
if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ) && !ALIGN_OFFSET( iv, 16 ))
{
via_cbc_op6(ksp, cwd, ibuf, obuf, nb, ivp);
}
else
{ aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
uint_8t *ip, *op;
while(nb)
{
int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);
ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);
op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
if(ip != ibuf)
memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
via_cbc_op6(ksp, cwd, ip, op, m, ivp);
if(op != obuf)
memcpy(obuf, buf, m * AES_BLOCK_SIZE);
ibuf += m * AES_BLOCK_SIZE;
obuf += m * AES_BLOCK_SIZE;
nb -= m;
}
}
if(iv != ivp)
memcpy(iv, ivp, AES_BLOCK_SIZE);
return EXIT_SUCCESS;
}
#endif
#if !defined( ASSUME_VIA_ACE_PRESENT )
# ifdef FAST_BUFFER_OPERATIONS
if(!ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( iv, 4 ))
while(nb--)
{
memcpy(tmp, ibuf, AES_BLOCK_SIZE);
if(aes_decrypt(ibuf, obuf, ctx) != EXIT_SUCCESS)
return EXIT_FAILURE;
lp32(obuf)[0] ^= lp32(iv)[0];
lp32(obuf)[1] ^= lp32(iv)[1];
lp32(obuf)[2] ^= lp32(iv)[2];
lp32(obuf)[3] ^= lp32(iv)[3];
memcpy(iv, tmp, AES_BLOCK_SIZE);
ibuf += AES_BLOCK_SIZE;
obuf += AES_BLOCK_SIZE;
}
else
# endif
while(nb--)
{
memcpy(tmp, ibuf, AES_BLOCK_SIZE);
if(aes_decrypt(ibuf, obuf, ctx) != EXIT_SUCCESS)
return EXIT_FAILURE;
obuf[ 0] ^= iv[ 0]; obuf[ 1] ^= iv[ 1];
obuf[ 2] ^= iv[ 2]; obuf[ 3] ^= iv[ 3];
obuf[ 4] ^= iv[ 4]; obuf[ 5] ^= iv[ 5];
obuf[ 6] ^= iv[ 6]; obuf[ 7] ^= iv[ 7];
obuf[ 8] ^= iv[ 8]; obuf[ 9] ^= iv[ 9];
obuf[10] ^= iv[10]; obuf[11] ^= iv[11];
obuf[12] ^= iv[12]; obuf[13] ^= iv[13];
obuf[14] ^= iv[14]; obuf[15] ^= iv[15];
memcpy(iv, tmp, AES_BLOCK_SIZE);
ibuf += AES_BLOCK_SIZE;
obuf += AES_BLOCK_SIZE;
}
#endif
return EXIT_SUCCESS;
}
AES_RETURN aes_cfb_encrypt(const unsigned char *ibuf, unsigned char *obuf,
int len, unsigned char *iv, aes_encrypt_ctx ctx[1])
{ int cnt = 0, b_pos = (int)ctx->inf.b[2], nb;
if(b_pos) /* complete any partial block */
{
while(b_pos < AES_BLOCK_SIZE && cnt < len)
{
*obuf++ = (iv[b_pos++] ^= *ibuf++);
cnt++;
}
b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
}
if((nb = (len - cnt) >> 4) != 0) /* process whole blocks */
{
#if defined( USE_VIA_ACE_IF_PRESENT )
if(ctx->inf.b[1] == 0xff)
{ int m;
uint_8t *ksp = (uint_8t*)(ctx->ks), *ivp = iv;
aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16);
via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
if(ALIGN_OFFSET( ctx, 16 ))
return EXIT_FAILURE;
if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */
{
ivp = liv;
memcpy(liv, iv, AES_BLOCK_SIZE);
}
if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))
{
via_cfb_op7(ksp, cwd, ibuf, obuf, nb, ivp, ivp);
ibuf += nb * AES_BLOCK_SIZE;
obuf += nb * AES_BLOCK_SIZE;
cnt += nb * AES_BLOCK_SIZE;
}
else /* input, output or both are unaligned */
{ aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
uint_8t *ip, *op;
while(nb)
{
m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m;
ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);
op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
if(ip != ibuf)
memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
via_cfb_op7(ksp, cwd, ip, op, m, ivp, ivp);
if(op != obuf)
memcpy(obuf, buf, m * AES_BLOCK_SIZE);
ibuf += m * AES_BLOCK_SIZE;
obuf += m * AES_BLOCK_SIZE;
cnt += m * AES_BLOCK_SIZE;
}
}
if(ivp != iv)
memcpy(iv, ivp, AES_BLOCK_SIZE);
}
#else
# ifdef FAST_BUFFER_OPERATIONS
if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( iv, 4 ))
while(cnt + AES_BLOCK_SIZE <= len)
{
assert(b_pos == 0);
if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
return EXIT_FAILURE;
lp32(obuf)[0] = lp32(iv)[0] ^= lp32(ibuf)[0];
lp32(obuf)[1] = lp32(iv)[1] ^= lp32(ibuf)[1];
lp32(obuf)[2] = lp32(iv)[2] ^= lp32(ibuf)[2];
lp32(obuf)[3] = lp32(iv)[3] ^= lp32(ibuf)[3];
ibuf += AES_BLOCK_SIZE;
obuf += AES_BLOCK_SIZE;
cnt += AES_BLOCK_SIZE;
}
else
# endif
while(cnt + AES_BLOCK_SIZE <= len)
{
assert(b_pos == 0);
if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
return EXIT_FAILURE;
obuf[ 0] = iv[ 0] ^= ibuf[ 0]; obuf[ 1] = iv[ 1] ^= ibuf[ 1];
obuf[ 2] = iv[ 2] ^= ibuf[ 2]; obuf[ 3] = iv[ 3] ^= ibuf[ 3];
obuf[ 4] = iv[ 4] ^= ibuf[ 4]; obuf[ 5] = iv[ 5] ^= ibuf[ 5];
obuf[ 6] = iv[ 6] ^= ibuf[ 6]; obuf[ 7] = iv[ 7] ^= ibuf[ 7];
obuf[ 8] = iv[ 8] ^= ibuf[ 8]; obuf[ 9] = iv[ 9] ^= ibuf[ 9];
obuf[10] = iv[10] ^= ibuf[10]; obuf[11] = iv[11] ^= ibuf[11];
obuf[12] = iv[12] ^= ibuf[12]; obuf[13] = iv[13] ^= ibuf[13];
obuf[14] = iv[14] ^= ibuf[14]; obuf[15] = iv[15] ^= ibuf[15];
ibuf += AES_BLOCK_SIZE;
obuf += AES_BLOCK_SIZE;
cnt += AES_BLOCK_SIZE;
}
#endif
}
while(cnt < len)
{
if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
return EXIT_FAILURE;
while(cnt < len && b_pos < AES_BLOCK_SIZE)
{
*obuf++ = (iv[b_pos++] ^= *ibuf++);
cnt++;
}
b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
}
ctx->inf.b[2] = (uint_8t)b_pos;
return EXIT_SUCCESS;
}
AES_RETURN aes_cfb_decrypt(const unsigned char *ibuf, unsigned char *obuf,
int len, unsigned char *iv, aes_encrypt_ctx ctx[1])
{ int cnt = 0, b_pos = (int)ctx->inf.b[2], nb;
if(b_pos) /* complete any partial block */
{ uint_8t t;
while(b_pos < AES_BLOCK_SIZE && cnt < len)
{
t = *ibuf++;
*obuf++ = t ^ iv[b_pos];
iv[b_pos++] = t;
cnt++;
}
b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
}
if((nb = (len - cnt) >> 4) != 0) /* process whole blocks */
{
#if defined( USE_VIA_ACE_IF_PRESENT )
if(ctx->inf.b[1] == 0xff)
{ int m;
uint_8t *ksp = (uint_8t*)(ctx->ks), *ivp = iv;
aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16);
via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192);
if(ALIGN_OFFSET( ctx, 16 ))
return EXIT_FAILURE;
if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */
{
ivp = liv;
memcpy(liv, iv, AES_BLOCK_SIZE);
}
if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))
{
via_cfb_op6(ksp, cwd, ibuf, obuf, nb, ivp);
ibuf += nb * AES_BLOCK_SIZE;
obuf += nb * AES_BLOCK_SIZE;
cnt += nb * AES_BLOCK_SIZE;
}
else /* input, output or both are unaligned */
{ aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
uint_8t *ip, *op;
while(nb)
{
m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m;
ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);
op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
if(ip != ibuf) /* input buffer is not aligned */
memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
via_cfb_op6(ksp, cwd, ip, op, m, ivp);
if(op != obuf) /* output buffer is not aligned */
memcpy(obuf, buf, m * AES_BLOCK_SIZE);
ibuf += m * AES_BLOCK_SIZE;
obuf += m * AES_BLOCK_SIZE;
cnt += m * AES_BLOCK_SIZE;
}
}
if(ivp != iv)
memcpy(iv, ivp, AES_BLOCK_SIZE);
}
#else
# ifdef FAST_BUFFER_OPERATIONS
if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) &&!ALIGN_OFFSET( iv, 4 ))
while(cnt + AES_BLOCK_SIZE <= len)
{ uint_32t t;
assert(b_pos == 0);
if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
return EXIT_FAILURE;
t = lp32(ibuf)[0], lp32(obuf)[0] = t ^ lp32(iv)[0], lp32(iv)[0] = t;
t = lp32(ibuf)[1], lp32(obuf)[1] = t ^ lp32(iv)[1], lp32(iv)[1] = t;
t = lp32(ibuf)[2], lp32(obuf)[2] = t ^ lp32(iv)[2], lp32(iv)[2] = t;
t = lp32(ibuf)[3], lp32(obuf)[3] = t ^ lp32(iv)[3], lp32(iv)[3] = t;
ibuf += AES_BLOCK_SIZE;
obuf += AES_BLOCK_SIZE;
cnt += AES_BLOCK_SIZE;
}
else
# endif
while(cnt + AES_BLOCK_SIZE <= len)
{ uint_8t t;
assert(b_pos == 0);
if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
return EXIT_FAILURE;
t = ibuf[ 0], obuf[ 0] = t ^ iv[ 0], iv[ 0] = t;
t = ibuf[ 1], obuf[ 1] = t ^ iv[ 1], iv[ 1] = t;
t = ibuf[ 2], obuf[ 2] = t ^ iv[ 2], iv[ 2] = t;
t = ibuf[ 3], obuf[ 3] = t ^ iv[ 3], iv[ 3] = t;
t = ibuf[ 4], obuf[ 4] = t ^ iv[ 4], iv[ 4] = t;
t = ibuf[ 5], obuf[ 5] = t ^ iv[ 5], iv[ 5] = t;
t = ibuf[ 6], obuf[ 6] = t ^ iv[ 6], iv[ 6] = t;
t = ibuf[ 7], obuf[ 7] = t ^ iv[ 7], iv[ 7] = t;
t = ibuf[ 8], obuf[ 8] = t ^ iv[ 8], iv[ 8] = t;
t = ibuf[ 9], obuf[ 9] = t ^ iv[ 9], iv[ 9] = t;
t = ibuf[10], obuf[10] = t ^ iv[10], iv[10] = t;
t = ibuf[11], obuf[11] = t ^ iv[11], iv[11] = t;
t = ibuf[12], obuf[12] = t ^ iv[12], iv[12] = t;
t = ibuf[13], obuf[13] = t ^ iv[13], iv[13] = t;
t = ibuf[14], obuf[14] = t ^ iv[14], iv[14] = t;
t = ibuf[15], obuf[15] = t ^ iv[15], iv[15] = t;
ibuf += AES_BLOCK_SIZE;
obuf += AES_BLOCK_SIZE;
cnt += AES_BLOCK_SIZE;
}
#endif
}
while(cnt < len)
{ uint_8t t;
if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
return EXIT_FAILURE;
while(cnt < len && b_pos < AES_BLOCK_SIZE)
{
t = *ibuf++;
*obuf++ = t ^ iv[b_pos];
iv[b_pos++] = t;
cnt++;
}
b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
}
ctx->inf.b[2] = (uint_8t)b_pos;
return EXIT_SUCCESS;
}
AES_RETURN aes_ofb_crypt(const unsigned char *ibuf, unsigned char *obuf,
int len, unsigned char *iv, aes_encrypt_ctx ctx[1])
{ int cnt = 0, b_pos = (int)ctx->inf.b[2], nb;
if(b_pos) /* complete any partial block */
{
while(b_pos < AES_BLOCK_SIZE && cnt < len)
{
*obuf++ = iv[b_pos++] ^ *ibuf++;
cnt++;
}
b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
}
if((nb = (len - cnt) >> 4) != 0) /* process whole blocks */
{
#if defined( USE_VIA_ACE_IF_PRESENT )
if(ctx->inf.b[1] == 0xff)
{ int m;
uint_8t *ksp = (uint_8t*)(ctx->ks), *ivp = iv;
aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16);
via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
if(ALIGN_OFFSET( ctx, 16 ))
return EXIT_FAILURE;
if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */
{
ivp = liv;
memcpy(liv, iv, AES_BLOCK_SIZE);
}
if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))
{
via_ofb_op6(ksp, cwd, ibuf, obuf, nb, ivp);
ibuf += nb * AES_BLOCK_SIZE;
obuf += nb * AES_BLOCK_SIZE;
cnt += nb * AES_BLOCK_SIZE;
}
else /* input, output or both are unaligned */
{ aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
uint_8t *ip, *op;
while(nb)
{
m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m;
ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);
op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
if(ip != ibuf)
memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
via_ofb_op6(ksp, cwd, ip, op, m, ivp);
if(op != obuf)
memcpy(obuf, buf, m * AES_BLOCK_SIZE);
ibuf += m * AES_BLOCK_SIZE;
obuf += m * AES_BLOCK_SIZE;
cnt += m * AES_BLOCK_SIZE;
}
}
if(ivp != iv)
memcpy(iv, ivp, AES_BLOCK_SIZE);
}
#else
# ifdef FAST_BUFFER_OPERATIONS
if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( iv, 4 ))
while(cnt + AES_BLOCK_SIZE <= len)
{
assert(b_pos == 0);
if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
return EXIT_FAILURE;
lp32(obuf)[0] = lp32(iv)[0] ^ lp32(ibuf)[0];
lp32(obuf)[1] = lp32(iv)[1] ^ lp32(ibuf)[1];
lp32(obuf)[2] = lp32(iv)[2] ^ lp32(ibuf)[2];
lp32(obuf)[3] = lp32(iv)[3] ^ lp32(ibuf)[3];
ibuf += AES_BLOCK_SIZE;
obuf += AES_BLOCK_SIZE;
cnt += AES_BLOCK_SIZE;
}
else
# endif
while(cnt + AES_BLOCK_SIZE <= len)
{
assert(b_pos == 0);
if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
return EXIT_FAILURE;
obuf[ 0] = iv[ 0] ^ ibuf[ 0]; obuf[ 1] = iv[ 1] ^ ibuf[ 1];
obuf[ 2] = iv[ 2] ^ ibuf[ 2]; obuf[ 3] = iv[ 3] ^ ibuf[ 3];
obuf[ 4] = iv[ 4] ^ ibuf[ 4]; obuf[ 5] = iv[ 5] ^ ibuf[ 5];
obuf[ 6] = iv[ 6] ^ ibuf[ 6]; obuf[ 7] = iv[ 7] ^ ibuf[ 7];
obuf[ 8] = iv[ 8] ^ ibuf[ 8]; obuf[ 9] = iv[ 9] ^ ibuf[ 9];
obuf[10] = iv[10] ^ ibuf[10]; obuf[11] = iv[11] ^ ibuf[11];
obuf[12] = iv[12] ^ ibuf[12]; obuf[13] = iv[13] ^ ibuf[13];
obuf[14] = iv[14] ^ ibuf[14]; obuf[15] = iv[15] ^ ibuf[15];
ibuf += AES_BLOCK_SIZE;
obuf += AES_BLOCK_SIZE;
cnt += AES_BLOCK_SIZE;
}
#endif
}
while(cnt < len)
{
if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
return EXIT_FAILURE;
while(cnt < len && b_pos < AES_BLOCK_SIZE)
{
*obuf++ = iv[b_pos++] ^ *ibuf++;
cnt++;
}
b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
}
ctx->inf.b[2] = (uint_8t)b_pos;
return EXIT_SUCCESS;
}
#define BFR_LENGTH (BFR_BLOCKS * AES_BLOCK_SIZE)
AES_RETURN aes_ctr_crypt(const unsigned char *ibuf, unsigned char *obuf,
int len, unsigned char *cbuf, cbuf_inc ctr_inc, aes_encrypt_ctx ctx[1])
{ unsigned char *ip;
int i, blen, b_pos = (int)(ctx->inf.b[2]);
#if defined( USE_VIA_ACE_IF_PRESENT )
aligned_auto(uint_8t, buf, BFR_LENGTH, 16);
if(ctx->inf.b[1] == 0xff && ALIGN_OFFSET( ctx, 16 ))
return EXIT_FAILURE;
#else
uint_8t buf[BFR_LENGTH];
#endif
if(b_pos)
{
memcpy(buf, cbuf, AES_BLOCK_SIZE);
if(aes_ecb_encrypt(buf, buf, AES_BLOCK_SIZE, ctx) != EXIT_SUCCESS)
return EXIT_FAILURE;
while(b_pos < AES_BLOCK_SIZE && len)
{
*obuf++ = *ibuf++ ^ buf[b_pos++];
--len;
}
if(len)
ctr_inc(cbuf), b_pos = 0;
}
while(len)
{
blen = (len > BFR_LENGTH ? BFR_LENGTH : len), len -= blen;
for(i = 0, ip = buf; i < (blen >> 4); ++i)
{
memcpy(ip, cbuf, AES_BLOCK_SIZE);
ctr_inc(cbuf);
ip += AES_BLOCK_SIZE;
}
if(blen & (AES_BLOCK_SIZE - 1))
memcpy(ip, cbuf, AES_BLOCK_SIZE), i++;
#if defined( USE_VIA_ACE_IF_PRESENT )
if(ctx->inf.b[1] == 0xff)
{
via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
via_ecb_op5((ctx->ks), cwd, buf, buf, i);
}
else
#endif
if(aes_ecb_encrypt(buf, buf, i * AES_BLOCK_SIZE, ctx) != EXIT_SUCCESS)
return EXIT_FAILURE;
i = 0; ip = buf;
# ifdef FAST_BUFFER_OPERATIONS
if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( ip, 4 ))
while(i + AES_BLOCK_SIZE <= blen)
{
lp32(obuf)[0] = lp32(ibuf)[0] ^ lp32(ip)[0];
lp32(obuf)[1] = lp32(ibuf)[1] ^ lp32(ip)[1];
lp32(obuf)[2] = lp32(ibuf)[2] ^ lp32(ip)[2];
lp32(obuf)[3] = lp32(ibuf)[3] ^ lp32(ip)[3];
i += AES_BLOCK_SIZE;
ip += AES_BLOCK_SIZE;
ibuf += AES_BLOCK_SIZE;
obuf += AES_BLOCK_SIZE;
}
else
#endif
while(i + AES_BLOCK_SIZE <= blen)
{
obuf[ 0] = ibuf[ 0] ^ ip[ 0]; obuf[ 1] = ibuf[ 1] ^ ip[ 1];
obuf[ 2] = ibuf[ 2] ^ ip[ 2]; obuf[ 3] = ibuf[ 3] ^ ip[ 3];
obuf[ 4] = ibuf[ 4] ^ ip[ 4]; obuf[ 5] = ibuf[ 5] ^ ip[ 5];
obuf[ 6] = ibuf[ 6] ^ ip[ 6]; obuf[ 7] = ibuf[ 7] ^ ip[ 7];
obuf[ 8] = ibuf[ 8] ^ ip[ 8]; obuf[ 9] = ibuf[ 9] ^ ip[ 9];
obuf[10] = ibuf[10] ^ ip[10]; obuf[11] = ibuf[11] ^ ip[11];
obuf[12] = ibuf[12] ^ ip[12]; obuf[13] = ibuf[13] ^ ip[13];
obuf[14] = ibuf[14] ^ ip[14]; obuf[15] = ibuf[15] ^ ip[15];
i += AES_BLOCK_SIZE;
ip += AES_BLOCK_SIZE;
ibuf += AES_BLOCK_SIZE;
obuf += AES_BLOCK_SIZE;
}
while(i++ < blen)
*obuf++ = *ibuf++ ^ ip[b_pos++];
}
ctx->inf.b[2] = (uint_8t)b_pos;
return EXIT_SUCCESS;
}
#if defined(__cplusplus)
}
#endif
#endif

141
libs/libks/crypt/aescpp.h Normal file
View File

@ -0,0 +1,141 @@
/*
---------------------------------------------------------------------------
Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved.
The redistribution and use of this software (with or without changes)
is allowed without the payment of fees or royalties provided that:
source code distributions include the above copyright notice, this
list of conditions and the following disclaimer;
binary distributions include the above copyright notice, this list
of conditions and the following disclaimer in their documentation.
This software is provided 'as is' with no explicit or implied warranties
in respect of its operation, including, but not limited to, correctness
and fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 20/12/2007
This file contains the definitions required to use AES (Rijndael) in C++.
*/
#ifndef _AESCPP_H
#define _AESCPP_H
#include "aes.h"
#if defined( AES_ENCRYPT )
class AESencrypt
{
public:
aes_encrypt_ctx cx[1];
AESencrypt(void) { aes_init_zrtp(); };
#if defined(AES_128)
AESencrypt(const unsigned char key[])
{ aes_encrypt_key128(key, cx); }
AES_RETURN key128(const unsigned char key[])
{ return aes_encrypt_key128(key, cx); }
#endif
#if defined(AES_192)
AES_RETURN key192(const unsigned char key[])
{ return aes_encrypt_key192(key, cx); }
#endif
#if defined(AES_256)
AES_RETURN key256(const unsigned char key[])
{ return aes_encrypt_key256(key, cx); }
#endif
#if defined(AES_VAR)
AES_RETURN key(const unsigned char key[], int key_len)
{ return aes_encrypt_key(key, key_len, cx); }
#endif
AES_RETURN encrypt(const unsigned char in[], unsigned char out[]) const
{ return aes_encrypt(in, out, cx); }
#ifndef AES_MODES
AES_RETURN ecb_encrypt(const unsigned char in[], unsigned char out[], int nb) const
{ while(nb--)
{ aes_encrypt(in, out, cx), in += AES_BLOCK_SIZE, out += AES_BLOCK_SIZE; }
}
#endif
#ifdef AES_MODES
AES_RETURN mode_reset(void) { return aes_mode_reset(cx); }
AES_RETURN ecb_encrypt(const unsigned char in[], unsigned char out[], int nb) const
{ return aes_ecb_encrypt(in, out, nb, cx); }
AES_RETURN cbc_encrypt(const unsigned char in[], unsigned char out[], int nb,
unsigned char iv[]) const
{ return aes_cbc_encrypt(in, out, nb, iv, cx); }
AES_RETURN cfb_encrypt(const unsigned char in[], unsigned char out[], int nb,
unsigned char iv[])
{ return aes_cfb_encrypt(in, out, nb, iv, cx); }
AES_RETURN cfb_decrypt(const unsigned char in[], unsigned char out[], int nb,
unsigned char iv[])
{ return aes_cfb_decrypt(in, out, nb, iv, cx); }
AES_RETURN ofb_crypt(const unsigned char in[], unsigned char out[], int nb,
unsigned char iv[])
{ return aes_ofb_crypt(in, out, nb, iv, cx); }
typedef void ctr_fn(unsigned char ctr[]);
AES_RETURN ctr_crypt(const unsigned char in[], unsigned char out[], int nb,
unsigned char iv[], ctr_fn cf)
{ return aes_ctr_crypt(in, out, nb, iv, cf, cx); }
#endif
};
#endif
#if defined( AES_DECRYPT )
class AESdecrypt
{
public:
aes_decrypt_ctx cx[1];
AESdecrypt(void) { aes_init_zrtp(); };
#if defined(AES_128)
AESdecrypt(const unsigned char key[])
{ aes_decrypt_key128(key, cx); }
AES_RETURN key128(const unsigned char key[])
{ return aes_decrypt_key128(key, cx); }
#endif
#if defined(AES_192)
AES_RETURN key192(const unsigned char key[])
{ return aes_decrypt_key192(key, cx); }
#endif
#if defined(AES_256)
AES_RETURN key256(const unsigned char key[])
{ return aes_decrypt_key256(key, cx); }
#endif
#if defined(AES_VAR)
AES_RETURN key(const unsigned char key[], int key_len)
{ return aes_decrypt_key(key, key_len, cx); }
#endif
AES_RETURN decrypt(const unsigned char in[], unsigned char out[]) const
{ return aes_decrypt(in, out, cx); }
#ifndef AES_MODES
AES_RETURN ecb_decrypt(const unsigned char in[], unsigned char out[], int nb) const
{ while(nb--)
{ aes_decrypt(in, out, cx), in += AES_BLOCK_SIZE, out += AES_BLOCK_SIZE; }
}
#endif
#ifdef AES_MODES
AES_RETURN ecb_decrypt(const unsigned char in[], unsigned char out[], int nb) const
{ return aes_ecb_decrypt(in, out, nb, cx); }
AES_RETURN cbc_decrypt(const unsigned char in[], unsigned char out[], int nb,
unsigned char iv[]) const
{ return aes_cbc_decrypt(in, out, nb, iv, cx); }
#endif
};
#endif
#endif

294
libs/libks/crypt/aescrypt.c Normal file
View File

@ -0,0 +1,294 @@
/*
---------------------------------------------------------------------------
Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved.
The redistribution and use of this software (with or without changes)
is allowed without the payment of fees or royalties provided that:
source code distributions include the above copyright notice, this
list of conditions and the following disclaimer;
binary distributions include the above copyright notice, this list
of conditions and the following disclaimer in their documentation.
This software is provided 'as is' with no explicit or implied warranties
in respect of its operation, including, but not limited to, correctness
and fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 20/12/2007
*/
#include "aesopt.h"
#include "aestab.h"
#if defined(__cplusplus)
extern "C"
{
#endif
#define si(y,x,k,c) (s(y,c) = word_in(x, c) ^ (k)[c])
#define so(y,x,c) word_out(y, c, s(x,c))
#if defined(ARRAYS)
#define locals(y,x) x[4],y[4]
#else
#define locals(y,x) x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3
#endif
#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \
s(y,2) = s(x,2); s(y,3) = s(x,3);
#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3)
#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3)
#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3)
#if ( FUNCS_IN_C & ENCRYPTION_IN_C )
/* Visual C++ .Net v7.1 provides the fastest encryption code when using
Pentium optimiation with small code but this is poor for decryption
so we need to control this with the following VC++ pragmas
*/
#if defined( _MSC_VER ) && !defined( _WIN64 )
#pragma optimize( "s", on )
#endif
/* Given the column (c) of the output state variable, the following
macros give the input state variables which are needed in its
computation for each row (r) of the state. All the alternative
macros give the same end values but expand into different ways
of calculating these values. In particular the complex macro
used for dynamically variable block sizes is designed to expand
to a compile time constant whenever possible but will expand to
conditional clauses on some branches (I am grateful to Frank
Yellin for this construction)
*/
#define fwd_var(x,r,c)\
( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\
: r == 1 ? ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))\
: r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\
: ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2)))
#if defined(FT4_SET)
#undef dec_fmvars
#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c))
#elif defined(FT1_SET)
#undef dec_fmvars
#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(f,n),fwd_var,rf1,c))
#else
#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ fwd_mcol(no_table(x,t_use(s,box),fwd_var,rf1,c)))
#endif
#if defined(FL4_SET)
#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,l),fwd_var,rf1,c))
#elif defined(FL1_SET)
#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(f,l),fwd_var,rf1,c))
#else
#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(s,box),fwd_var,rf1,c))
#endif
AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1])
{ uint_32t locals(b0, b1);
const uint_32t *kp;
#if defined( dec_fmvars )
dec_fmvars; /* declare variables for fwd_mcol() if needed */
#endif
if( cx->inf.b[0] != 10 * 16 && cx->inf.b[0] != 12 * 16 && cx->inf.b[0] != 14 * 16 )
return EXIT_FAILURE;
kp = cx->ks;
state_in(b0, in, kp);
#if (ENC_UNROLL == FULL)
switch(cx->inf.b[0])
{
case 14 * 16:
round(fwd_rnd, b1, b0, kp + 1 * N_COLS);
round(fwd_rnd, b0, b1, kp + 2 * N_COLS);
kp += 2 * N_COLS;
case 12 * 16:
round(fwd_rnd, b1, b0, kp + 1 * N_COLS);
round(fwd_rnd, b0, b1, kp + 2 * N_COLS);
kp += 2 * N_COLS;
case 10 * 16:
round(fwd_rnd, b1, b0, kp + 1 * N_COLS);
round(fwd_rnd, b0, b1, kp + 2 * N_COLS);
round(fwd_rnd, b1, b0, kp + 3 * N_COLS);
round(fwd_rnd, b0, b1, kp + 4 * N_COLS);
round(fwd_rnd, b1, b0, kp + 5 * N_COLS);
round(fwd_rnd, b0, b1, kp + 6 * N_COLS);
round(fwd_rnd, b1, b0, kp + 7 * N_COLS);
round(fwd_rnd, b0, b1, kp + 8 * N_COLS);
round(fwd_rnd, b1, b0, kp + 9 * N_COLS);
round(fwd_lrnd, b0, b1, kp +10 * N_COLS);
}
#else
#if (ENC_UNROLL == PARTIAL)
{ uint_32t rnd;
for(rnd = 0; rnd < (cx->inf.b[0] >> 5) - 1; ++rnd)
{
kp += N_COLS;
round(fwd_rnd, b1, b0, kp);
kp += N_COLS;
round(fwd_rnd, b0, b1, kp);
}
kp += N_COLS;
round(fwd_rnd, b1, b0, kp);
#else
{ uint_32t rnd;
for(rnd = 0; rnd < (cx->inf.b[0] >> 4) - 1; ++rnd)
{
kp += N_COLS;
round(fwd_rnd, b1, b0, kp);
l_copy(b0, b1);
}
#endif
kp += N_COLS;
round(fwd_lrnd, b0, b1, kp);
}
#endif
state_out(out, b0);
return EXIT_SUCCESS;
}
#endif
#if ( FUNCS_IN_C & DECRYPTION_IN_C)
/* Visual C++ .Net v7.1 provides the fastest encryption code when using
Pentium optimiation with small code but this is poor for decryption
so we need to control this with the following VC++ pragmas
*/
#if defined( _MSC_VER ) && !defined( _WIN64 )
#pragma optimize( "t", on )
#endif
/* Given the column (c) of the output state variable, the following
macros give the input state variables which are needed in its
computation for each row (r) of the state. All the alternative
macros give the same end values but expand into different ways
of calculating these values. In particular the complex macro
used for dynamically variable block sizes is designed to expand
to a compile time constant whenever possible but will expand to
conditional clauses on some branches (I am grateful to Frank
Yellin for this construction)
*/
#define inv_var(x,r,c)\
( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\
: r == 1 ? ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))\
: r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\
: ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0)))
#if defined(IT4_SET)
#undef dec_imvars
#define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,n),inv_var,rf1,c))
#elif defined(IT1_SET)
#undef dec_imvars
#define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(i,n),inv_var,rf1,c))
#else
#define inv_rnd(y,x,k,c) (s(y,c) = inv_mcol((k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c)))
#endif
#if defined(IL4_SET)
#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,l),inv_var,rf1,c))
#elif defined(IL1_SET)
#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(i,l),inv_var,rf1,c))
#else
#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c))
#endif
/* This code can work with the decryption key schedule in the */
/* order that is used for encrytpion (where the 1st decryption */
/* round key is at the high end ot the schedule) or with a key */
/* schedule that has been reversed to put the 1st decryption */
/* round key at the low end of the schedule in memory (when */
/* AES_REV_DKS is defined) */
#ifdef AES_REV_DKS
#define key_ofs 0
#define rnd_key(n) (kp + n * N_COLS)
#else
#define key_ofs 1
#define rnd_key(n) (kp - n * N_COLS)
#endif
AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1])
{ uint_32t locals(b0, b1);
#if defined( dec_imvars )
dec_imvars; /* declare variables for inv_mcol() if needed */
#endif
const uint_32t *kp;
if( cx->inf.b[0] != 10 * 16 && cx->inf.b[0] != 12 * 16 && cx->inf.b[0] != 14 * 16 )
return EXIT_FAILURE;
kp = cx->ks + (key_ofs ? (cx->inf.b[0] >> 2) : 0);
state_in(b0, in, kp);
#if (DEC_UNROLL == FULL)
kp = cx->ks + (key_ofs ? 0 : (cx->inf.b[0] >> 2));
switch(cx->inf.b[0])
{
case 14 * 16:
round(inv_rnd, b1, b0, rnd_key(-13));
round(inv_rnd, b0, b1, rnd_key(-12));
case 12 * 16:
round(inv_rnd, b1, b0, rnd_key(-11));
round(inv_rnd, b0, b1, rnd_key(-10));
case 10 * 16:
round(inv_rnd, b1, b0, rnd_key(-9));
round(inv_rnd, b0, b1, rnd_key(-8));
round(inv_rnd, b1, b0, rnd_key(-7));
round(inv_rnd, b0, b1, rnd_key(-6));
round(inv_rnd, b1, b0, rnd_key(-5));
round(inv_rnd, b0, b1, rnd_key(-4));
round(inv_rnd, b1, b0, rnd_key(-3));
round(inv_rnd, b0, b1, rnd_key(-2));
round(inv_rnd, b1, b0, rnd_key(-1));
round(inv_lrnd, b0, b1, rnd_key( 0));
}
#else
#if (DEC_UNROLL == PARTIAL)
{ uint_32t rnd;
for(rnd = 0; rnd < (cx->inf.b[0] >> 5) - 1; ++rnd)
{
kp = rnd_key(1);
round(inv_rnd, b1, b0, kp);
kp = rnd_key(1);
round(inv_rnd, b0, b1, kp);
}
kp = rnd_key(1);
round(inv_rnd, b1, b0, kp);
#else
{ uint_32t rnd;
for(rnd = 0; rnd < (cx->inf.b[0] >> 4) - 1; ++rnd)
{
kp = rnd_key(1);
round(inv_rnd, b1, b0, kp);
l_copy(b0, b1);
}
#endif
kp = rnd_key(1);
round(inv_lrnd, b0, b1, kp);
}
#endif
state_out(out, b0);
return EXIT_SUCCESS;
}
#endif
#if defined(__cplusplus)
}
#endif

556
libs/libks/crypt/aeskey.c Normal file
View File

@ -0,0 +1,556 @@
/*
---------------------------------------------------------------------------
Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved.
The redistribution and use of this software (with or without changes)
is allowed without the payment of fees or royalties provided that:
source code distributions include the above copyright notice, this
list of conditions and the following disclaimer;
binary distributions include the above copyright notice, this list
of conditions and the following disclaimer in their documentation.
This software is provided 'as is' with no explicit or implied warranties
in respect of its operation, including, but not limited to, correctness
and fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 20/12/2007
*/
#include "aesopt.h"
#include "aestab.h"
/*
#ifdef USE_VIA_ACE_IF_PRESENT
# include "aes_via_ace.h"
#endif
*/
#if defined(__cplusplus)
extern "C"
{
#endif
/* Initialise the key schedule from the user supplied key. The key
length can be specified in bytes, with legal values of 16, 24
and 32, or in bits, with legal values of 128, 192 and 256. These
values correspond with Nk values of 4, 6 and 8 respectively.
The following macros implement a single cycle in the key
schedule generation process. The number of cycles needed
for each cx->n_col and nk value is:
nk = 4 5 6 7 8
------------------------------
cx->n_col = 4 10 9 8 7 7
cx->n_col = 5 14 11 10 9 9
cx->n_col = 6 19 15 12 11 11
cx->n_col = 7 21 19 16 13 14
cx->n_col = 8 29 23 19 17 14
*/
#if defined( REDUCE_CODE_SIZE )
# define ls_box ls_sub
uint_32t ls_sub(const uint_32t t, const uint_32t n);
# define inv_mcol im_sub
uint_32t im_sub(const uint_32t x);
# ifdef ENC_KS_UNROLL
# undef ENC_KS_UNROLL
# endif
# ifdef DEC_KS_UNROLL
# undef DEC_KS_UNROLL
# endif
#endif
#if (FUNCS_IN_C & ENC_KEYING_IN_C)
#if defined(AES_128) || defined( AES_VAR )
#define ke4(k,i) \
{ k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; \
k[4*(i)+5] = ss[1] ^= ss[0]; \
k[4*(i)+6] = ss[2] ^= ss[1]; \
k[4*(i)+7] = ss[3] ^= ss[2]; \
}
AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1])
{ uint_32t ss[4];
cx->ks[0] = ss[0] = word_in(key, 0);
cx->ks[1] = ss[1] = word_in(key, 1);
cx->ks[2] = ss[2] = word_in(key, 2);
cx->ks[3] = ss[3] = word_in(key, 3);
#ifdef ENC_KS_UNROLL
ke4(cx->ks, 0); ke4(cx->ks, 1);
ke4(cx->ks, 2); ke4(cx->ks, 3);
ke4(cx->ks, 4); ke4(cx->ks, 5);
ke4(cx->ks, 6); ke4(cx->ks, 7);
ke4(cx->ks, 8);
#else
{ uint_32t i;
for(i = 0; i < 9; ++i)
ke4(cx->ks, i);
}
#endif
ke4(cx->ks, 9);
cx->inf.l = 0;
cx->inf.b[0] = 10 * 16;
#ifdef USE_VIA_ACE_IF_PRESENT
if(VIA_ACE_AVAILABLE)
cx->inf.b[1] = 0xff;
#endif
return EXIT_SUCCESS;
}
#endif
#if defined(AES_192) || defined( AES_VAR )
#define kef6(k,i) \
{ k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; \
k[6*(i)+ 7] = ss[1] ^= ss[0]; \
k[6*(i)+ 8] = ss[2] ^= ss[1]; \
k[6*(i)+ 9] = ss[3] ^= ss[2]; \
}
#define ke6(k,i) \
{ kef6(k,i); \
k[6*(i)+10] = ss[4] ^= ss[3]; \
k[6*(i)+11] = ss[5] ^= ss[4]; \
}
AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1])
{ uint_32t ss[6];
cx->ks[0] = ss[0] = word_in(key, 0);
cx->ks[1] = ss[1] = word_in(key, 1);
cx->ks[2] = ss[2] = word_in(key, 2);
cx->ks[3] = ss[3] = word_in(key, 3);
cx->ks[4] = ss[4] = word_in(key, 4);
cx->ks[5] = ss[5] = word_in(key, 5);
#ifdef ENC_KS_UNROLL
ke6(cx->ks, 0); ke6(cx->ks, 1);
ke6(cx->ks, 2); ke6(cx->ks, 3);
ke6(cx->ks, 4); ke6(cx->ks, 5);
ke6(cx->ks, 6);
#else
{ uint_32t i;
for(i = 0; i < 7; ++i)
ke6(cx->ks, i);
}
#endif
kef6(cx->ks, 7);
cx->inf.l = 0;
cx->inf.b[0] = 12 * 16;
#ifdef USE_VIA_ACE_IF_PRESENT
if(VIA_ACE_AVAILABLE)
cx->inf.b[1] = 0xff;
#endif
return EXIT_SUCCESS;
}
#endif
#if defined(AES_256) || defined( AES_VAR )
#define kef8(k,i) \
{ k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; \
k[8*(i)+ 9] = ss[1] ^= ss[0]; \
k[8*(i)+10] = ss[2] ^= ss[1]; \
k[8*(i)+11] = ss[3] ^= ss[2]; \
}
#define ke8(k,i) \
{ kef8(k,i); \
k[8*(i)+12] = ss[4] ^= ls_box(ss[3],0); \
k[8*(i)+13] = ss[5] ^= ss[4]; \
k[8*(i)+14] = ss[6] ^= ss[5]; \
k[8*(i)+15] = ss[7] ^= ss[6]; \
}
AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1])
{ uint_32t ss[8];
cx->ks[0] = ss[0] = word_in(key, 0);
cx->ks[1] = ss[1] = word_in(key, 1);
cx->ks[2] = ss[2] = word_in(key, 2);
cx->ks[3] = ss[3] = word_in(key, 3);
cx->ks[4] = ss[4] = word_in(key, 4);
cx->ks[5] = ss[5] = word_in(key, 5);
cx->ks[6] = ss[6] = word_in(key, 6);
cx->ks[7] = ss[7] = word_in(key, 7);
#ifdef ENC_KS_UNROLL
ke8(cx->ks, 0); ke8(cx->ks, 1);
ke8(cx->ks, 2); ke8(cx->ks, 3);
ke8(cx->ks, 4); ke8(cx->ks, 5);
#else
{ uint_32t i;
for(i = 0; i < 6; ++i)
ke8(cx->ks, i);
}
#endif
kef8(cx->ks, 6);
cx->inf.l = 0;
cx->inf.b[0] = 14 * 16;
#ifdef USE_VIA_ACE_IF_PRESENT
if(VIA_ACE_AVAILABLE)
cx->inf.b[1] = 0xff;
#endif
return EXIT_SUCCESS;
}
#endif
#if defined( AES_VAR )
AES_RETURN aes_encrypt_key(const unsigned char *key, int key_len, aes_encrypt_ctx cx[1])
{
switch(key_len)
{
case 16: case 128: return aes_encrypt_key128(key, cx);
case 24: case 192: return aes_encrypt_key192(key, cx);
case 32: case 256: return aes_encrypt_key256(key, cx);
default: return EXIT_FAILURE;
}
}
#endif
#endif
#if (FUNCS_IN_C & DEC_KEYING_IN_C)
/* this is used to store the decryption round keys */
/* in forward or reverse order */
#ifdef AES_REV_DKS
#define v(n,i) ((n) - (i) + 2 * ((i) & 3))
#else
#define v(n,i) (i)
#endif
#if DEC_ROUND == NO_TABLES
#define ff(x) (x)
#else
#define ff(x) inv_mcol(x)
#if defined( dec_imvars )
#define d_vars dec_imvars
#endif
#endif
#if defined(AES_128) || defined( AES_VAR )
#define k4e(k,i) \
{ k[v(40,(4*(i))+4)] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; \
k[v(40,(4*(i))+5)] = ss[1] ^= ss[0]; \
k[v(40,(4*(i))+6)] = ss[2] ^= ss[1]; \
k[v(40,(4*(i))+7)] = ss[3] ^= ss[2]; \
}
#if 1
#define kdf4(k,i) \
{ ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3]; \
ss[1] = ss[1] ^ ss[3]; \
ss[2] = ss[2] ^ ss[3]; \
ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; \
ss[i % 4] ^= ss[4]; \
ss[4] ^= k[v(40,(4*(i)))]; k[v(40,(4*(i))+4)] = ff(ss[4]); \
ss[4] ^= k[v(40,(4*(i))+1)]; k[v(40,(4*(i))+5)] = ff(ss[4]); \
ss[4] ^= k[v(40,(4*(i))+2)]; k[v(40,(4*(i))+6)] = ff(ss[4]); \
ss[4] ^= k[v(40,(4*(i))+3)]; k[v(40,(4*(i))+7)] = ff(ss[4]); \
}
#define kd4(k,i) \
{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; \
ss[i % 4] ^= ss[4]; ss[4] = ff(ss[4]); \
k[v(40,(4*(i))+4)] = ss[4] ^= k[v(40,(4*(i)))]; \
k[v(40,(4*(i))+5)] = ss[4] ^= k[v(40,(4*(i))+1)]; \
k[v(40,(4*(i))+6)] = ss[4] ^= k[v(40,(4*(i))+2)]; \
k[v(40,(4*(i))+7)] = ss[4] ^= k[v(40,(4*(i))+3)]; \
}
#define kdl4(k,i) \
{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; \
k[v(40,(4*(i))+4)] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3]; \
k[v(40,(4*(i))+5)] = ss[1] ^ ss[3]; \
k[v(40,(4*(i))+6)] = ss[0]; \
k[v(40,(4*(i))+7)] = ss[1]; \
}
#else
#define kdf4(k,i) \
{ ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[v(40,(4*(i))+ 4)] = ff(ss[0]); \
ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ff(ss[1]); \
ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ff(ss[2]); \
ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ff(ss[3]); \
}
#define kd4(k,i) \
{ ss[4] = ls_box(ss[3],3) ^ t_use(r,c)[i]; \
ss[0] ^= ss[4]; ss[4] = ff(ss[4]); k[v(40,(4*(i))+ 4)] = ss[4] ^= k[v(40,(4*(i)))]; \
ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ss[4] ^= k[v(40,(4*(i))+ 1)]; \
ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ss[4] ^= k[v(40,(4*(i))+ 2)]; \
ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ss[4] ^= k[v(40,(4*(i))+ 3)]; \
}
#define kdl4(k,i) \
{ ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[v(40,(4*(i))+ 4)] = ss[0]; \
ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ss[1]; \
ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ss[2]; \
ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ss[3]; \
}
#endif
AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1])
{ uint_32t ss[5];
#if defined( d_vars )
d_vars;
#endif
cx->ks[v(40,(0))] = ss[0] = word_in(key, 0);
cx->ks[v(40,(1))] = ss[1] = word_in(key, 1);
cx->ks[v(40,(2))] = ss[2] = word_in(key, 2);
cx->ks[v(40,(3))] = ss[3] = word_in(key, 3);
#ifdef DEC_KS_UNROLL
kdf4(cx->ks, 0); kd4(cx->ks, 1);
kd4(cx->ks, 2); kd4(cx->ks, 3);
kd4(cx->ks, 4); kd4(cx->ks, 5);
kd4(cx->ks, 6); kd4(cx->ks, 7);
kd4(cx->ks, 8); kdl4(cx->ks, 9);
#else
{ uint_32t i;
for(i = 0; i < 10; ++i)
k4e(cx->ks, i);
#if !(DEC_ROUND == NO_TABLES)
for(i = N_COLS; i < 10 * N_COLS; ++i)
cx->ks[i] = inv_mcol(cx->ks[i]);
#endif
}
#endif
cx->inf.l = 0;
cx->inf.b[0] = 10 * 16;
#ifdef USE_VIA_ACE_IF_PRESENT
if(VIA_ACE_AVAILABLE)
cx->inf.b[1] = 0xff;
#endif
return EXIT_SUCCESS;
}
#endif
#if defined(AES_192) || defined( AES_VAR )
#define k6ef(k,i) \
{ k[v(48,(6*(i))+ 6)] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; \
k[v(48,(6*(i))+ 7)] = ss[1] ^= ss[0]; \
k[v(48,(6*(i))+ 8)] = ss[2] ^= ss[1]; \
k[v(48,(6*(i))+ 9)] = ss[3] ^= ss[2]; \
}
#define k6e(k,i) \
{ k6ef(k,i); \
k[v(48,(6*(i))+10)] = ss[4] ^= ss[3]; \
k[v(48,(6*(i))+11)] = ss[5] ^= ss[4]; \
}
#define kdf6(k,i) \
{ ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[v(48,(6*(i))+ 6)] = ff(ss[0]); \
ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ff(ss[1]); \
ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ff(ss[2]); \
ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ff(ss[3]); \
ss[4] ^= ss[3]; k[v(48,(6*(i))+10)] = ff(ss[4]); \
ss[5] ^= ss[4]; k[v(48,(6*(i))+11)] = ff(ss[5]); \
}
#define kd6(k,i) \
{ ss[6] = ls_box(ss[5],3) ^ t_use(r,c)[i]; \
ss[0] ^= ss[6]; ss[6] = ff(ss[6]); k[v(48,(6*(i))+ 6)] = ss[6] ^= k[v(48,(6*(i)))]; \
ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ss[6] ^= k[v(48,(6*(i))+ 1)]; \
ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ss[6] ^= k[v(48,(6*(i))+ 2)]; \
ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ss[6] ^= k[v(48,(6*(i))+ 3)]; \
ss[4] ^= ss[3]; k[v(48,(6*(i))+10)] = ss[6] ^= k[v(48,(6*(i))+ 4)]; \
ss[5] ^= ss[4]; k[v(48,(6*(i))+11)] = ss[6] ^= k[v(48,(6*(i))+ 5)]; \
}
#define kdl6(k,i) \
{ ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[v(48,(6*(i))+ 6)] = ss[0]; \
ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ss[1]; \
ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ss[2]; \
ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ss[3]; \
}
AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1])
{ uint_32t ss[7];
#if defined( d_vars )
d_vars;
#endif
cx->ks[v(48,(0))] = ss[0] = word_in(key, 0);
cx->ks[v(48,(1))] = ss[1] = word_in(key, 1);
cx->ks[v(48,(2))] = ss[2] = word_in(key, 2);
cx->ks[v(48,(3))] = ss[3] = word_in(key, 3);
#ifdef DEC_KS_UNROLL
ss[4] = word_in(key, 4);
cx->ks[v(48,(4))] = ff(ss[4]);
ss[5] = word_in(key, 5);
cx->ks[v(48,(5))] = ff(ss[5]);
kdf6(cx->ks, 0); kd6(cx->ks, 1);
kd6(cx->ks, 2); kd6(cx->ks, 3);
kd6(cx->ks, 4); kd6(cx->ks, 5);
kd6(cx->ks, 6); kdl6(cx->ks, 7);
#else
cx->ks[v(48,(4))] = ss[4] = word_in(key, 4);
cx->ks[v(48,(5))] = ss[5] = word_in(key, 5);
{ uint_32t i;
for(i = 0; i < 7; ++i)
k6e(cx->ks, i);
k6ef(cx->ks, 7);
#if !(DEC_ROUND == NO_TABLES)
for(i = N_COLS; i < 12 * N_COLS; ++i)
cx->ks[i] = inv_mcol(cx->ks[i]);
#endif
}
#endif
cx->inf.l = 0;
cx->inf.b[0] = 12 * 16;
#ifdef USE_VIA_ACE_IF_PRESENT
if(VIA_ACE_AVAILABLE)
cx->inf.b[1] = 0xff;
#endif
return EXIT_SUCCESS;
}
#endif
#if defined(AES_256) || defined( AES_VAR )
#define k8ef(k,i) \
{ k[v(56,(8*(i))+ 8)] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; \
k[v(56,(8*(i))+ 9)] = ss[1] ^= ss[0]; \
k[v(56,(8*(i))+10)] = ss[2] ^= ss[1]; \
k[v(56,(8*(i))+11)] = ss[3] ^= ss[2]; \
}
#define k8e(k,i) \
{ k8ef(k,i); \
k[v(56,(8*(i))+12)] = ss[4] ^= ls_box(ss[3],0); \
k[v(56,(8*(i))+13)] = ss[5] ^= ss[4]; \
k[v(56,(8*(i))+14)] = ss[6] ^= ss[5]; \
k[v(56,(8*(i))+15)] = ss[7] ^= ss[6]; \
}
#define kdf8(k,i) \
{ ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[v(56,(8*(i))+ 8)] = ff(ss[0]); \
ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ff(ss[1]); \
ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ff(ss[2]); \
ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ff(ss[3]); \
ss[4] ^= ls_box(ss[3],0); k[v(56,(8*(i))+12)] = ff(ss[4]); \
ss[5] ^= ss[4]; k[v(56,(8*(i))+13)] = ff(ss[5]); \
ss[6] ^= ss[5]; k[v(56,(8*(i))+14)] = ff(ss[6]); \
ss[7] ^= ss[6]; k[v(56,(8*(i))+15)] = ff(ss[7]); \
}
#define kd8(k,i) \
{ ss[8] = ls_box(ss[7],3) ^ t_use(r,c)[i]; \
ss[0] ^= ss[8]; ss[8] = ff(ss[8]); k[v(56,(8*(i))+ 8)] = ss[8] ^= k[v(56,(8*(i)))]; \
ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ss[8] ^= k[v(56,(8*(i))+ 1)]; \
ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ss[8] ^= k[v(56,(8*(i))+ 2)]; \
ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ss[8] ^= k[v(56,(8*(i))+ 3)]; \
ss[8] = ls_box(ss[3],0); \
ss[4] ^= ss[8]; ss[8] = ff(ss[8]); k[v(56,(8*(i))+12)] = ss[8] ^= k[v(56,(8*(i))+ 4)]; \
ss[5] ^= ss[4]; k[v(56,(8*(i))+13)] = ss[8] ^= k[v(56,(8*(i))+ 5)]; \
ss[6] ^= ss[5]; k[v(56,(8*(i))+14)] = ss[8] ^= k[v(56,(8*(i))+ 6)]; \
ss[7] ^= ss[6]; k[v(56,(8*(i))+15)] = ss[8] ^= k[v(56,(8*(i))+ 7)]; \
}
#define kdl8(k,i) \
{ ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[v(56,(8*(i))+ 8)] = ss[0]; \
ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ss[1]; \
ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ss[2]; \
ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ss[3]; \
}
AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1])
{ uint_32t ss[9];
#if defined( d_vars )
d_vars;
#endif
cx->ks[v(56,(0))] = ss[0] = word_in(key, 0);
cx->ks[v(56,(1))] = ss[1] = word_in(key, 1);
cx->ks[v(56,(2))] = ss[2] = word_in(key, 2);
cx->ks[v(56,(3))] = ss[3] = word_in(key, 3);
#ifdef DEC_KS_UNROLL
ss[4] = word_in(key, 4);
cx->ks[v(56,(4))] = ff(ss[4]);
ss[5] = word_in(key, 5);
cx->ks[v(56,(5))] = ff(ss[5]);
ss[6] = word_in(key, 6);
cx->ks[v(56,(6))] = ff(ss[6]);
ss[7] = word_in(key, 7);
cx->ks[v(56,(7))] = ff(ss[7]);
kdf8(cx->ks, 0); kd8(cx->ks, 1);
kd8(cx->ks, 2); kd8(cx->ks, 3);
kd8(cx->ks, 4); kd8(cx->ks, 5);
kdl8(cx->ks, 6);
#else
cx->ks[v(56,(4))] = ss[4] = word_in(key, 4);
cx->ks[v(56,(5))] = ss[5] = word_in(key, 5);
cx->ks[v(56,(6))] = ss[6] = word_in(key, 6);
cx->ks[v(56,(7))] = ss[7] = word_in(key, 7);
{ uint_32t i;
for(i = 0; i < 6; ++i)
k8e(cx->ks, i);
k8ef(cx->ks, 6);
#if !(DEC_ROUND == NO_TABLES)
for(i = N_COLS; i < 14 * N_COLS; ++i)
cx->ks[i] = inv_mcol(cx->ks[i]);
#endif
}
#endif
cx->inf.l = 0;
cx->inf.b[0] = 14 * 16;
#ifdef USE_VIA_ACE_IF_PRESENT
if(VIA_ACE_AVAILABLE)
cx->inf.b[1] = 0xff;
#endif
return EXIT_SUCCESS;
}
#endif
#if defined( AES_VAR )
AES_RETURN aes_decrypt_key(const unsigned char *key, int key_len, aes_decrypt_ctx cx[1])
{
switch(key_len)
{
case 16: case 128: return aes_decrypt_key128(key, cx);
case 24: case 192: return aes_decrypt_key192(key, cx);
case 32: case 256: return aes_decrypt_key256(key, cx);
default: return EXIT_FAILURE;
}
}
#endif
#endif
#if defined(__cplusplus)
}
#endif

742
libs/libks/crypt/aesopt.h Normal file
View File

@ -0,0 +1,742 @@
/*
---------------------------------------------------------------------------
Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved.
The redistribution and use of this software (with or without changes)
is allowed without the payment of fees or royalties provided that:
source code distributions include the above copyright notice, this
list of conditions and the following disclaimer;
binary distributions include the above copyright notice, this list
of conditions and the following disclaimer in their documentation.
This software is provided 'as is' with no explicit or implied warranties
in respect of its operation, including, but not limited to, correctness
and fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 20/12/2007
This file contains the compilation options for AES (Rijndael) and code
that is common across encryption, key scheduling and table generation.
OPERATION
These source code files implement the AES algorithm Rijndael designed by
Joan Daemen and Vincent Rijmen. This version is designed for the standard
block size of 16 bytes and for key sizes of 128, 192 and 256 bits (16, 24
and 32 bytes).
This version is designed for flexibility and speed using operations on
32-bit words rather than operations on bytes. It can be compiled with
either big or little endian internal byte order but is faster when the
native byte order for the processor is used.
THE CIPHER INTERFACE
The cipher interface is implemented as an array of bytes in which lower
AES bit sequence indexes map to higher numeric significance within bytes.
uint_8t (an unsigned 8-bit type)
uint_32t (an unsigned 32-bit type)
struct aes_encrypt_ctx (structure for the cipher encryption context)
struct aes_decrypt_ctx (structure for the cipher decryption context)
AES_RETURN the function return type
C subroutine calls:
AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]);
AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]);
AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]);
AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out,
const aes_encrypt_ctx cx[1]);
AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]);
AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]);
AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]);
AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out,
const aes_decrypt_ctx cx[1]);
IMPORTANT NOTE: If you are using this C interface with dynamic tables make sure that
you call aes_init() before AES is used so that the tables are initialised.
C++ aes class subroutines:
Class AESencrypt for encryption
Construtors:
AESencrypt(void)
AESencrypt(const unsigned char *key) - 128 bit key
Members:
AES_RETURN key128(const unsigned char *key)
AES_RETURN key192(const unsigned char *key)
AES_RETURN key256(const unsigned char *key)
AES_RETURN encrypt(const unsigned char *in, unsigned char *out) const
Class AESdecrypt for encryption
Construtors:
AESdecrypt(void)
AESdecrypt(const unsigned char *key) - 128 bit key
Members:
AES_RETURN key128(const unsigned char *key)
AES_RETURN key192(const unsigned char *key)
AES_RETURN key256(const unsigned char *key)
AES_RETURN decrypt(const unsigned char *in, unsigned char *out) const
*/
#if !defined( _AESOPT_H )
#define _AESOPT_H
#if defined( __cplusplus )
#include "aescpp.h"
#else
#include "aes.h"
#endif
/* PLATFORM SPECIFIC INCLUDES */
#include "brg_endian.h"
/* CONFIGURATION - THE USE OF DEFINES
Later in this section there are a number of defines that control the
operation of the code. In each section, the purpose of each define is
explained so that the relevant form can be included or excluded by
setting either 1's or 0's respectively on the branches of the related
#if clauses. The following local defines should not be changed.
*/
#define ENCRYPTION_IN_C 1
#define DECRYPTION_IN_C 2
#define ENC_KEYING_IN_C 4
#define DEC_KEYING_IN_C 8
#define NO_TABLES 0
#define ONE_TABLE 1
#define FOUR_TABLES 4
#define NONE 0
#define PARTIAL 1
#define FULL 2
/* --- START OF USER CONFIGURED OPTIONS --- */
/* 1. BYTE ORDER WITHIN 32 BIT WORDS
The fundamental data processing units in Rijndael are 8-bit bytes. The
input, output and key input are all enumerated arrays of bytes in which
bytes are numbered starting at zero and increasing to one less than the
number of bytes in the array in question. This enumeration is only used
for naming bytes and does not imply any adjacency or order relationship
from one byte to another. When these inputs and outputs are considered
as bit sequences, bits 8*n to 8*n+7 of the bit sequence are mapped to
byte[n] with bit 8n+i in the sequence mapped to bit 7-i within the byte.
In this implementation bits are numbered from 0 to 7 starting at the
numerically least significant end of each byte (bit n represents 2^n).
However, Rijndael can be implemented more efficiently using 32-bit
words by packing bytes into words so that bytes 4*n to 4*n+3 are placed
into word[n]. While in principle these bytes can be assembled into words
in any positions, this implementation only supports the two formats in
which bytes in adjacent positions within words also have adjacent byte
numbers. This order is called big-endian if the lowest numbered bytes
in words have the highest numeric significance and little-endian if the
opposite applies.
This code can work in either order irrespective of the order used by the
machine on which it runs. Normally the internal byte order will be set
to the order of the processor on which the code is to be run but this
define can be used to reverse this in special situations
WARNING: Assembler code versions rely on PLATFORM_BYTE_ORDER being set.
This define will hence be redefined later (in section 4) if necessary
*/
#if 1
# define ALGORITHM_BYTE_ORDER PLATFORM_BYTE_ORDER
#elif 0
# define ALGORITHM_BYTE_ORDER IS_LITTLE_ENDIAN
#elif 0
# define ALGORITHM_BYTE_ORDER IS_BIG_ENDIAN
#else
# error The algorithm byte order is not defined
#endif
/* 2. VIA ACE SUPPORT */
#if defined( __GNUC__ ) && defined( __i386__ ) \
|| defined( _WIN32 ) && defined( _M_IX86 ) \
&& !(defined( _WIN64 ) || defined( _WIN32_WCE ) || defined( _MSC_VER ) && ( _MSC_VER <= 800 ))
# define VIA_ACE_POSSIBLE
#endif
/* Define this option if support for the VIA ACE is required. This uses
inline assembler instructions and is only implemented for the Microsoft,
Intel and GCC compilers. If VIA ACE is known to be present, then defining
ASSUME_VIA_ACE_PRESENT will remove the ordinary encryption/decryption
code. If USE_VIA_ACE_IF_PRESENT is defined then VIA ACE will be used if
it is detected (both present and enabled) but the normal AES code will
also be present.
When VIA ACE is to be used, all AES encryption contexts MUST be 16 byte
aligned; other input/output buffers do not need to be 16 byte aligned
but there are very large performance gains if this can be arranged.
VIA ACE also requires the decryption key schedule to be in reverse
order (which later checks below ensure).
*/
#if 1 && defined( VIA_ACE_POSSIBLE ) && !defined( USE_VIA_ACE_IF_PRESENT )
# define USE_VIA_ACE_IF_PRESENT
#endif
#if 0 && defined( VIA_ACE_POSSIBLE ) && !defined( ASSUME_VIA_ACE_PRESENT )
# define ASSUME_VIA_ACE_PRESENT
# endif
/* 3. ASSEMBLER SUPPORT
This define (which can be on the command line) enables the use of the
assembler code routines for encryption, decryption and key scheduling
as follows:
ASM_X86_V1C uses the assembler (aes_x86_v1.asm) with large tables for
encryption and decryption and but with key scheduling in C
ASM_X86_V2 uses assembler (aes_x86_v2.asm) with compressed tables for
encryption, decryption and key scheduling
ASM_X86_V2C uses assembler (aes_x86_v2.asm) with compressed tables for
encryption and decryption and but with key scheduling in C
ASM_AMD64_C uses assembler (aes_amd64.asm) with compressed tables for
encryption and decryption and but with key scheduling in C
Change one 'if 0' below to 'if 1' to select the version or define
as a compilation option.
*/
#if 0 && !defined( ASM_X86_V1C )
# define ASM_X86_V1C
#elif 0 && !defined( ASM_X86_V2 )
# define ASM_X86_V2
#elif 0 && !defined( ASM_X86_V2C )
# define ASM_X86_V2C
#elif 0 && !defined( ASM_AMD64_C )
# define ASM_AMD64_C
#endif
#if (defined ( ASM_X86_V1C ) || defined( ASM_X86_V2 ) || defined( ASM_X86_V2C )) \
&& !defined( _M_IX86 ) || defined( ASM_AMD64_C ) && !defined( _M_X64 )
# error Assembler code is only available for x86 and AMD64 systems
#endif
/* 4. FAST INPUT/OUTPUT OPERATIONS.
On some machines it is possible to improve speed by transferring the
bytes in the input and output arrays to and from the internal 32-bit
variables by addressing these arrays as if they are arrays of 32-bit
words. On some machines this will always be possible but there may
be a large performance penalty if the byte arrays are not aligned on
the normal word boundaries. On other machines this technique will
lead to memory access errors when such 32-bit word accesses are not
properly aligned. The option SAFE_IO avoids such problems but will
often be slower on those machines that support misaligned access
(especially so if care is taken to align the input and output byte
arrays on 32-bit word boundaries). If SAFE_IO is not defined it is
assumed that access to byte arrays as if they are arrays of 32-bit
words will not cause problems when such accesses are misaligned.
*/
#if 1 && !defined( _MSC_VER )
# define SAFE_IO
#endif
/* 5. LOOP UNROLLING
The code for encryption and decrytpion cycles through a number of rounds
that can be implemented either in a loop or by expanding the code into a
long sequence of instructions, the latter producing a larger program but
one that will often be much faster. The latter is called loop unrolling.
There are also potential speed advantages in expanding two iterations in
a loop with half the number of iterations, which is called partial loop
unrolling. The following options allow partial or full loop unrolling
to be set independently for encryption and decryption
*/
#if 1
# define ENC_UNROLL FULL
#elif 0
# define ENC_UNROLL PARTIAL
#else
# define ENC_UNROLL NONE
#endif
#if 1
# define DEC_UNROLL FULL
#elif 0
# define DEC_UNROLL PARTIAL
#else
# define DEC_UNROLL NONE
#endif
#if 1
# define ENC_KS_UNROLL
#endif
#if 1
# define DEC_KS_UNROLL
#endif
/* 6. FAST FINITE FIELD OPERATIONS
If this section is included, tables are used to provide faster finite
field arithmetic (this has no effect if FIXED_TABLES is defined).
*/
#if 1
# define FF_TABLES
#endif
/* 7. INTERNAL STATE VARIABLE FORMAT
The internal state of Rijndael is stored in a number of local 32-bit
word varaibles which can be defined either as an array or as individual
names variables. Include this section if you want to store these local
varaibles in arrays. Otherwise individual local variables will be used.
*/
#if 1
# define ARRAYS
#endif
/* 8. FIXED OR DYNAMIC TABLES
When this section is included the tables used by the code are compiled
statically into the binary file. Otherwise the subroutine aes_init()
must be called to compute them before the code is first used.
*/
#if 1 && !(defined( _MSC_VER ) && ( _MSC_VER <= 800 ))
# define FIXED_TABLES
#endif
/* 9. MASKING OR CASTING FROM LONGER VALUES TO BYTES
In some systems it is better to mask longer values to extract bytes
rather than using a cast. This option allows this choice.
*/
#if 0
# define to_byte(x) ((uint_8t)(x))
#else
# define to_byte(x) ((x) & 0xff)
#endif
/* 10. TABLE ALIGNMENT
On some sytsems speed will be improved by aligning the AES large lookup
tables on particular boundaries. This define should be set to a power of
two giving the desired alignment. It can be left undefined if alignment
is not needed. This option is specific to the Microsft VC++ compiler -
it seems to sometimes cause trouble for the VC++ version 6 compiler.
*/
#if 1 && defined( _MSC_VER ) && ( _MSC_VER >= 1300 )
# define TABLE_ALIGN 32
#endif
/* 11. REDUCE CODE AND TABLE SIZE
This replaces some expanded macros with function calls if AES_ASM_V2 or
AES_ASM_V2C are defined
*/
#if 1 && (defined( ASM_X86_V2 ) || defined( ASM_X86_V2C ))
# define REDUCE_CODE_SIZE
#endif
/* 12. TABLE OPTIONS
This cipher proceeds by repeating in a number of cycles known as 'rounds'
which are implemented by a round function which can optionally be speeded
up using tables. The basic tables are each 256 32-bit words, with either
one or four tables being required for each round function depending on
how much speed is required. The encryption and decryption round functions
are different and the last encryption and decrytpion round functions are
different again making four different round functions in all.
This means that:
1. Normal encryption and decryption rounds can each use either 0, 1
or 4 tables and table spaces of 0, 1024 or 4096 bytes each.
2. The last encryption and decryption rounds can also use either 0, 1
or 4 tables and table spaces of 0, 1024 or 4096 bytes each.
Include or exclude the appropriate definitions below to set the number
of tables used by this implementation.
*/
#if 1 /* set tables for the normal encryption round */
# define ENC_ROUND FOUR_TABLES
#elif 0
# define ENC_ROUND ONE_TABLE
#else
# define ENC_ROUND NO_TABLES
#endif
#if 1 /* set tables for the last encryption round */
# define LAST_ENC_ROUND FOUR_TABLES
#elif 0
# define LAST_ENC_ROUND ONE_TABLE
#else
# define LAST_ENC_ROUND NO_TABLES
#endif
#if 1 /* set tables for the normal decryption round */
# define DEC_ROUND FOUR_TABLES
#elif 0
# define DEC_ROUND ONE_TABLE
#else
# define DEC_ROUND NO_TABLES
#endif
#if 1 /* set tables for the last decryption round */
# define LAST_DEC_ROUND FOUR_TABLES
#elif 0
# define LAST_DEC_ROUND ONE_TABLE
#else
# define LAST_DEC_ROUND NO_TABLES
#endif
/* The decryption key schedule can be speeded up with tables in the same
way that the round functions can. Include or exclude the following
defines to set this requirement.
*/
#if 1
# define KEY_SCHED FOUR_TABLES
#elif 0
# define KEY_SCHED ONE_TABLE
#else
# define KEY_SCHED NO_TABLES
#endif
/* ---- END OF USER CONFIGURED OPTIONS ---- */
/* VIA ACE support is only available for VC++ and GCC */
#if !defined( _MSC_VER ) && !defined( __GNUC__ )
# if defined( ASSUME_VIA_ACE_PRESENT )
# undef ASSUME_VIA_ACE_PRESENT
# endif
# if defined( USE_VIA_ACE_IF_PRESENT )
# undef USE_VIA_ACE_IF_PRESENT
# endif
#endif
#if defined( ASSUME_VIA_ACE_PRESENT ) && !defined( USE_VIA_ACE_IF_PRESENT )
# define USE_VIA_ACE_IF_PRESENT
#endif
#if defined( USE_VIA_ACE_IF_PRESENT ) && !defined ( AES_REV_DKS )
# define AES_REV_DKS
#endif
/* ********** UNDEF - we don't use VIA stuff ****************** */
#undef USE_VIA_ACE_IF_PRESENT
/* Assembler support requires the use of platform byte order */
#if ( defined( ASM_X86_V1C ) || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C ) ) \
&& (ALGORITHM_BYTE_ORDER != PLATFORM_BYTE_ORDER)
# undef ALGORITHM_BYTE_ORDER
# define ALGORITHM_BYTE_ORDER PLATFORM_BYTE_ORDER
#endif
/* In this implementation the columns of the state array are each held in
32-bit words. The state array can be held in various ways: in an array
of words, in a number of individual word variables or in a number of
processor registers. The following define maps a variable name x and
a column number c to the way the state array variable is to be held.
The first define below maps the state into an array x[c] whereas the
second form maps the state into a number of individual variables x0,
x1, etc. Another form could map individual state colums to machine
register names.
*/
#if defined( ARRAYS )
# define s(x,c) x[c]
#else
# define s(x,c) x##c
#endif
/* This implementation provides subroutines for encryption, decryption
and for setting the three key lengths (separately) for encryption
and decryption. Since not all functions are needed, masks are set
up here to determine which will be implemented in C
*/
#if !defined( AES_ENCRYPT )
# define EFUNCS_IN_C 0
#elif defined( ASSUME_VIA_ACE_PRESENT ) || defined( ASM_X86_V1C ) \
|| defined( ASM_X86_V2C ) || defined( ASM_AMD64_C )
# define EFUNCS_IN_C ENC_KEYING_IN_C
#elif !defined( ASM_X86_V2 )
# define EFUNCS_IN_C ( ENCRYPTION_IN_C | ENC_KEYING_IN_C )
#else
# define EFUNCS_IN_C 0
#endif
#if !defined( AES_DECRYPT )
# define DFUNCS_IN_C 0
#elif defined( ASSUME_VIA_ACE_PRESENT ) || defined( ASM_X86_V1C ) \
|| defined( ASM_X86_V2C ) || defined( ASM_AMD64_C )
# define DFUNCS_IN_C DEC_KEYING_IN_C
#elif !defined( ASM_X86_V2 )
# define DFUNCS_IN_C ( DECRYPTION_IN_C | DEC_KEYING_IN_C )
#else
# define DFUNCS_IN_C 0
#endif
#define FUNCS_IN_C ( EFUNCS_IN_C | DFUNCS_IN_C )
/* END OF CONFIGURATION OPTIONS */
#define RC_LENGTH (5 * (AES_BLOCK_SIZE / 4 - 2))
/* Disable or report errors on some combinations of options */
#if ENC_ROUND == NO_TABLES && LAST_ENC_ROUND != NO_TABLES
# undef LAST_ENC_ROUND
# define LAST_ENC_ROUND NO_TABLES
#elif ENC_ROUND == ONE_TABLE && LAST_ENC_ROUND == FOUR_TABLES
# undef LAST_ENC_ROUND
# define LAST_ENC_ROUND ONE_TABLE
#endif
#if ENC_ROUND == NO_TABLES && ENC_UNROLL != NONE
# undef ENC_UNROLL
# define ENC_UNROLL NONE
#endif
#if DEC_ROUND == NO_TABLES && LAST_DEC_ROUND != NO_TABLES
# undef LAST_DEC_ROUND
# define LAST_DEC_ROUND NO_TABLES
#elif DEC_ROUND == ONE_TABLE && LAST_DEC_ROUND == FOUR_TABLES
# undef LAST_DEC_ROUND
# define LAST_DEC_ROUND ONE_TABLE
#endif
#if DEC_ROUND == NO_TABLES && DEC_UNROLL != NONE
# undef DEC_UNROLL
# define DEC_UNROLL NONE
#endif
#if defined( bswap32 )
# define aes_sw32 bswap32
#elif defined( bswap_32 )
# define aes_sw32 bswap_32
#else
# define brot(x,n) (((uint_32t)(x) << n) | ((uint_32t)(x) >> (32 - n)))
# define aes_sw32(x) ((brot((x),8) & 0x00ff00ff) | (brot((x),24) & 0xff00ff00))
#endif
/* upr(x,n): rotates bytes within words by n positions, moving bytes to
higher index positions with wrap around into low positions
ups(x,n): moves bytes by n positions to higher index positions in
words but without wrap around
bval(x,n): extracts a byte from a word
WARNING: The definitions given here are intended only for use with
unsigned variables and with shift counts that are compile
time constants
*/
#if ( ALGORITHM_BYTE_ORDER == IS_LITTLE_ENDIAN )
# define upr(x,n) (((uint_32t)(x) << (8 * (n))) | ((uint_32t)(x) >> (32 - 8 * (n))))
# define ups(x,n) ((uint_32t) (x) << (8 * (n)))
# define bval(x,n) to_byte((x) >> (8 * (n)))
# define bytes2word(b0, b1, b2, b3) \
(((uint_32t)(b3) << 24) | ((uint_32t)(b2) << 16) | ((uint_32t)(b1) << 8) | (b0))
#endif
#if ( ALGORITHM_BYTE_ORDER == IS_BIG_ENDIAN )
# define upr(x,n) (((uint_32t)(x) >> (8 * (n))) | ((uint_32t)(x) << (32 - 8 * (n))))
# define ups(x,n) ((uint_32t) (x) >> (8 * (n)))
# define bval(x,n) to_byte((x) >> (24 - 8 * (n)))
# define bytes2word(b0, b1, b2, b3) \
(((uint_32t)(b0) << 24) | ((uint_32t)(b1) << 16) | ((uint_32t)(b2) << 8) | (b3))
#endif
#if defined( SAFE_IO )
# define word_in(x,c) bytes2word(((const uint_8t*)(x)+4*c)[0], ((const uint_8t*)(x)+4*c)[1], \
((const uint_8t*)(x)+4*c)[2], ((const uint_8t*)(x)+4*c)[3])
# define word_out(x,c,v) { ((uint_8t*)(x)+4*c)[0] = bval(v,0); ((uint_8t*)(x)+4*c)[1] = bval(v,1); \
((uint_8t*)(x)+4*c)[2] = bval(v,2); ((uint_8t*)(x)+4*c)[3] = bval(v,3); }
#elif ( ALGORITHM_BYTE_ORDER == PLATFORM_BYTE_ORDER )
# define word_in(x,c) (*((uint_32t*)(x)+(c)))
# define word_out(x,c,v) (*((uint_32t*)(x)+(c)) = (v))
#else
# define word_in(x,c) aes_sw32(*((uint_32t*)(x)+(c)))
# define word_out(x,c,v) (*((uint_32t*)(x)+(c)) = aes_sw32(v))
#endif
/* the finite field modular polynomial and elements */
#define WPOLY 0x011b
#define BPOLY 0x1b
/* multiply four bytes in GF(2^8) by 'x' {02} in parallel */
#define gf_c1 0x80808080
#define gf_c2 0x7f7f7f7f
#define gf_mulx(x) ((((x) & gf_c2) << 1) ^ ((((x) & gf_c1) >> 7) * BPOLY))
/* The following defines provide alternative definitions of gf_mulx that might
give improved performance if a fast 32-bit multiply is not available. Note
that a temporary variable u needs to be defined where gf_mulx is used.
#define gf_mulx(x) (u = (x) & gf_c1, u |= (u >> 1), ((x) & gf_c2) << 1) ^ ((u >> 3) | (u >> 6))
#define gf_c4 (0x01010101 * BPOLY)
#define gf_mulx(x) (u = (x) & gf_c1, ((x) & gf_c2) << 1) ^ ((u - (u >> 7)) & gf_c4)
*/
/* Work out which tables are needed for the different options */
#if defined( ASM_X86_V1C )
# if defined( ENC_ROUND )
# undef ENC_ROUND
# endif
# define ENC_ROUND FOUR_TABLES
# if defined( LAST_ENC_ROUND )
# undef LAST_ENC_ROUND
# endif
# define LAST_ENC_ROUND FOUR_TABLES
# if defined( DEC_ROUND )
# undef DEC_ROUND
# endif
# define DEC_ROUND FOUR_TABLES
# if defined( LAST_DEC_ROUND )
# undef LAST_DEC_ROUND
# endif
# define LAST_DEC_ROUND FOUR_TABLES
# if defined( KEY_SCHED )
# undef KEY_SCHED
# define KEY_SCHED FOUR_TABLES
# endif
#endif
#if ( FUNCS_IN_C & ENCRYPTION_IN_C ) || defined( ASM_X86_V1C )
# if ENC_ROUND == ONE_TABLE
# define FT1_SET
# elif ENC_ROUND == FOUR_TABLES
# define FT4_SET
# else
# define SBX_SET
# endif
# if LAST_ENC_ROUND == ONE_TABLE
# define FL1_SET
# elif LAST_ENC_ROUND == FOUR_TABLES
# define FL4_SET
# elif !defined( SBX_SET )
# define SBX_SET
# endif
#endif
#if ( FUNCS_IN_C & DECRYPTION_IN_C ) || defined( ASM_X86_V1C )
# if DEC_ROUND == ONE_TABLE
# define IT1_SET
# elif DEC_ROUND == FOUR_TABLES
# define IT4_SET
# else
# define ISB_SET
# endif
# if LAST_DEC_ROUND == ONE_TABLE
# define IL1_SET
# elif LAST_DEC_ROUND == FOUR_TABLES
# define IL4_SET
# elif !defined(ISB_SET)
# define ISB_SET
# endif
#endif
#if !(defined( REDUCE_CODE_SIZE ) && (defined( ASM_X86_V2 ) || defined( ASM_X86_V2C )))
# if ((FUNCS_IN_C & ENC_KEYING_IN_C) || (FUNCS_IN_C & DEC_KEYING_IN_C))
# if KEY_SCHED == ONE_TABLE
# if !defined( FL1_SET ) && !defined( FL4_SET )
# define LS1_SET
# endif
# elif KEY_SCHED == FOUR_TABLES
# if !defined( FL4_SET )
# define LS4_SET
# endif
# elif !defined( SBX_SET )
# define SBX_SET
# endif
# endif
# if (FUNCS_IN_C & DEC_KEYING_IN_C)
# if KEY_SCHED == ONE_TABLE
# define IM1_SET
# elif KEY_SCHED == FOUR_TABLES
# define IM4_SET
# elif !defined( SBX_SET )
# define SBX_SET
# endif
# endif
#endif
/* generic definitions of Rijndael macros that use tables */
#define no_table(x,box,vf,rf,c) bytes2word( \
box[bval(vf(x,0,c),rf(0,c))], \
box[bval(vf(x,1,c),rf(1,c))], \
box[bval(vf(x,2,c),rf(2,c))], \
box[bval(vf(x,3,c),rf(3,c))])
#define one_table(x,op,tab,vf,rf,c) \
( tab[bval(vf(x,0,c),rf(0,c))] \
^ op(tab[bval(vf(x,1,c),rf(1,c))],1) \
^ op(tab[bval(vf(x,2,c),rf(2,c))],2) \
^ op(tab[bval(vf(x,3,c),rf(3,c))],3))
#define four_tables(x,tab,vf,rf,c) \
( tab[0][bval(vf(x,0,c),rf(0,c))] \
^ tab[1][bval(vf(x,1,c),rf(1,c))] \
^ tab[2][bval(vf(x,2,c),rf(2,c))] \
^ tab[3][bval(vf(x,3,c),rf(3,c))])
#define vf1(x,r,c) (x)
#define rf1(r,c) (r)
#define rf2(r,c) ((8+r-c)&3)
/* perform forward and inverse column mix operation on four bytes in long word x in */
/* parallel. NOTE: x must be a simple variable, NOT an expression in these macros. */
#if !(defined( REDUCE_CODE_SIZE ) && (defined( ASM_X86_V2 ) || defined( ASM_X86_V2C )))
#if defined( FM4_SET ) /* not currently used */
# define fwd_mcol(x) four_tables(x,t_use(f,m),vf1,rf1,0)
#elif defined( FM1_SET ) /* not currently used */
# define fwd_mcol(x) one_table(x,upr,t_use(f,m),vf1,rf1,0)
#else
# define dec_fmvars uint_32t g2
# define fwd_mcol(x) (g2 = gf_mulx(x), g2 ^ upr((x) ^ g2, 3) ^ upr((x), 2) ^ upr((x), 1))
#endif
#if defined( IM4_SET )
# define inv_mcol(x) four_tables(x,t_use(i,m),vf1,rf1,0)
#elif defined( IM1_SET )
# define inv_mcol(x) one_table(x,upr,t_use(i,m),vf1,rf1,0)
#else
# define dec_imvars uint_32t g2, g4, g9
# define inv_mcol(x) (g2 = gf_mulx(x), g4 = gf_mulx(g2), g9 = (x) ^ gf_mulx(g4), g4 ^= g9, \
(x) ^ g2 ^ g4 ^ upr(g2 ^ g9, 3) ^ upr(g4, 2) ^ upr(g9, 1))
#endif
#if defined( FL4_SET )
# define ls_box(x,c) four_tables(x,t_use(f,l),vf1,rf2,c)
#elif defined( LS4_SET )
# define ls_box(x,c) four_tables(x,t_use(l,s),vf1,rf2,c)
#elif defined( FL1_SET )
# define ls_box(x,c) one_table(x,upr,t_use(f,l),vf1,rf2,c)
#elif defined( LS1_SET )
# define ls_box(x,c) one_table(x,upr,t_use(l,s),vf1,rf2,c)
#else
# define ls_box(x,c) no_table(x,t_use(s,box),vf1,rf2,c)
#endif
#endif
#if defined( ASM_X86_V1C ) && defined( AES_DECRYPT ) && !defined( ISB_SET )
# define ISB_SET
#endif
#endif

391
libs/libks/crypt/aestab.c Normal file
View File

@ -0,0 +1,391 @@
/*
---------------------------------------------------------------------------
Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved.
The redistribution and use of this software (with or without changes)
is allowed without the payment of fees or royalties provided that:
source code distributions include the above copyright notice, this
list of conditions and the following disclaimer;
binary distributions include the above copyright notice, this list
of conditions and the following disclaimer in their documentation.
This software is provided 'as is' with no explicit or implied warranties
in respect of its operation, including, but not limited to, correctness
and fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 20/12/2007
*/
#define DO_TABLES
#include "aes.h"
#include "aesopt.h"
#if defined(FIXED_TABLES)
#define sb_data(w) {\
w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\
w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\
w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\
w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\
w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\
w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\
w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\
w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\
w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\
w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\
w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\
w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\
w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\
w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\
w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\
w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\
w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\
w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\
w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\
w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\
w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\
w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\
w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\
w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\
w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\
w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\
w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\
w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\
w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\
w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\
w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\
w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) }
#define isb_data(w) {\
w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\
w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\
w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\
w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\
w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\
w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\
w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\
w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\
w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\
w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\
w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\
w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\
w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\
w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\
w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\
w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\
w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\
w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\
w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\
w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\
w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\
w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\
w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\
w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\
w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\
w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\
w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\
w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\
w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\
w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\
w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\
w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d) }
#define mm_data(w) {\
w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\
w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\
w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\
w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\
w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\
w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\
w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\
w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\
w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\
w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\
w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\
w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\
w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\
w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\
w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\
w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\
w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\
w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\
w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\
w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\
w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\
w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\
w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\
w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\
w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\
w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\
w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\
w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\
w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\
w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\
w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\
w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) }
#define rc_data(w) {\
w(0x01), w(0x02), w(0x04), w(0x08), w(0x10),w(0x20), w(0x40), w(0x80),\
w(0x1b), w(0x36) }
#define h0(x) (x)
#define w0(p) bytes2word(p, 0, 0, 0)
#define w1(p) bytes2word(0, p, 0, 0)
#define w2(p) bytes2word(0, 0, p, 0)
#define w3(p) bytes2word(0, 0, 0, p)
#define u0(p) bytes2word(f2(p), p, p, f3(p))
#define u1(p) bytes2word(f3(p), f2(p), p, p)
#define u2(p) bytes2word(p, f3(p), f2(p), p)
#define u3(p) bytes2word(p, p, f3(p), f2(p))
#define v0(p) bytes2word(fe(p), f9(p), fd(p), fb(p))
#define v1(p) bytes2word(fb(p), fe(p), f9(p), fd(p))
#define v2(p) bytes2word(fd(p), fb(p), fe(p), f9(p))
#define v3(p) bytes2word(f9(p), fd(p), fb(p), fe(p))
#endif
#if defined(FIXED_TABLES) || !defined(FF_TABLES)
#define f2(x) ((x<<1) ^ (((x>>7) & 1) * WPOLY))
#define f4(x) ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY))
#define f8(x) ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) \
^ (((x>>5) & 4) * WPOLY))
#define f3(x) (f2(x) ^ x)
#define f9(x) (f8(x) ^ x)
#define fb(x) (f8(x) ^ f2(x) ^ x)
#define fd(x) (f8(x) ^ f4(x) ^ x)
#define fe(x) (f8(x) ^ f4(x) ^ f2(x))
#else
#define f2(x) ((x) ? pow[log[x] + 0x19] : 0)
#define f3(x) ((x) ? pow[log[x] + 0x01] : 0)
#define f9(x) ((x) ? pow[log[x] + 0xc7] : 0)
#define fb(x) ((x) ? pow[log[x] + 0x68] : 0)
#define fd(x) ((x) ? pow[log[x] + 0xee] : 0)
#define fe(x) ((x) ? pow[log[x] + 0xdf] : 0)
#endif
#include "aestab.h"
#if defined(__cplusplus)
extern "C"
{
#endif
#if defined(FIXED_TABLES)
/* implemented in case of wrong call for fixed tables */
AES_RETURN ks_aes_init(void)
{
return EXIT_SUCCESS;
}
#else /* Generate the tables for the dynamic table option */
#if defined(FF_TABLES)
#define gf_inv(x) ((x) ? pow[ 255 - log[x]] : 0)
#else
/* It will generally be sensible to use tables to compute finite
field multiplies and inverses but where memory is scarse this
code might sometimes be better. But it only has effect during
initialisation so its pretty unimportant in overall terms.
*/
/* return 2 ^ (n - 1) where n is the bit number of the highest bit
set in x with x in the range 1 < x < 0x00000200. This form is
used so that locals within fi can be bytes rather than words
*/
static uint_8t hibit(const uint_32t x)
{ uint_8t r = (uint_8t)((x >> 1) | (x >> 2));
r |= (r >> 2);
r |= (r >> 4);
return (r + 1) >> 1;
}
/* return the inverse of the finite field element x */
static uint_8t gf_inv(const uint_8t x)
{ uint_8t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0;
if(x < 2)
return x;
for( ; ; )
{
if(n1)
while(n2 >= n1) /* divide polynomial p2 by p1 */
{
n2 /= n1; /* shift smaller polynomial left */
p2 ^= (p1 * n2) & 0xff; /* and remove from larger one */
v2 ^= v1 * n2; /* shift accumulated value and */
n2 = hibit(p2); /* add into result */
}
else
return v1;
if(n2) /* repeat with values swapped */
while(n1 >= n2)
{
n1 /= n2;
p1 ^= p2 * n1;
v1 ^= v2 * n1;
n1 = hibit(p1);
}
else
return v2;
}
}
#endif
/* The forward and inverse affine transformations used in the S-box */
uint_8t fwd_affine(const uint_8t x)
{ uint_32t w = x;
w ^= (w << 1) ^ (w << 2) ^ (w << 3) ^ (w << 4);
return 0x63 ^ ((w ^ (w >> 8)) & 0xff);
}
uint_8t inv_affine(const uint_8t x)
{ uint_32t w = x;
w = (w << 1) ^ (w << 3) ^ (w << 6);
return 0x05 ^ ((w ^ (w >> 8)) & 0xff);
}
static int init = 0;
AES_RETURN ks_aes_init(void)
{ uint_32t i, w;
#if defined(FF_TABLES)
uint_8t pow[512], log[256];
if(init)
return EXIT_SUCCESS;
/* log and power tables for GF(2^8) finite field with
WPOLY as modular polynomial - the simplest primitive
root is 0x03, used here to generate the tables
*/
i = 0; w = 1;
do
{
pow[i] = (uint_8t)w;
pow[i + 255] = (uint_8t)w;
log[w] = (uint_8t)i++;
w ^= (w << 1) ^ (w & 0x80 ? WPOLY : 0);
}
while (w != 1);
#else
if(init)
return EXIT_SUCCESS;
#endif
for(i = 0, w = 1; i < RC_LENGTH; ++i)
{
t_set(r,c)[i] = bytes2word(w, 0, 0, 0);
w = f2(w);
}
for(i = 0; i < 256; ++i)
{ uint_8t b;
b = fwd_affine(gf_inv((uint_8t)i));
w = bytes2word(f2(b), b, b, f3(b));
#if defined( SBX_SET )
t_set(s,box)[i] = b;
#endif
#if defined( FT1_SET ) /* tables for a normal encryption round */
t_set(f,n)[i] = w;
#endif
#if defined( FT4_SET )
t_set(f,n)[0][i] = w;
t_set(f,n)[1][i] = upr(w,1);
t_set(f,n)[2][i] = upr(w,2);
t_set(f,n)[3][i] = upr(w,3);
#endif
w = bytes2word(b, 0, 0, 0);
#if defined( FL1_SET ) /* tables for last encryption round (may also */
t_set(f,l)[i] = w; /* be used in the key schedule) */
#endif
#if defined( FL4_SET )
t_set(f,l)[0][i] = w;
t_set(f,l)[1][i] = upr(w,1);
t_set(f,l)[2][i] = upr(w,2);
t_set(f,l)[3][i] = upr(w,3);
#endif
#if defined( LS1_SET ) /* table for key schedule if t_set(f,l) above is*/
t_set(l,s)[i] = w; /* not of the required form */
#endif
#if defined( LS4_SET )
t_set(l,s)[0][i] = w;
t_set(l,s)[1][i] = upr(w,1);
t_set(l,s)[2][i] = upr(w,2);
t_set(l,s)[3][i] = upr(w,3);
#endif
b = gf_inv(inv_affine((uint_8t)i));
w = bytes2word(fe(b), f9(b), fd(b), fb(b));
#if defined( IM1_SET ) /* tables for the inverse mix column operation */
t_set(i,m)[b] = w;
#endif
#if defined( IM4_SET )
t_set(i,m)[0][b] = w;
t_set(i,m)[1][b] = upr(w,1);
t_set(i,m)[2][b] = upr(w,2);
t_set(i,m)[3][b] = upr(w,3);
#endif
#if defined( ISB_SET )
t_set(i,box)[i] = b;
#endif
#if defined( IT1_SET ) /* tables for a normal decryption round */
t_set(i,n)[i] = w;
#endif
#if defined( IT4_SET )
t_set(i,n)[0][i] = w;
t_set(i,n)[1][i] = upr(w,1);
t_set(i,n)[2][i] = upr(w,2);
t_set(i,n)[3][i] = upr(w,3);
#endif
w = bytes2word(b, 0, 0, 0);
#if defined( IL1_SET ) /* tables for last decryption round */
t_set(i,l)[i] = w;
#endif
#if defined( IL4_SET )
t_set(i,l)[0][i] = w;
t_set(i,l)[1][i] = upr(w,1);
t_set(i,l)[2][i] = upr(w,2);
t_set(i,l)[3][i] = upr(w,3);
#endif
}
init = 1;
return EXIT_SUCCESS;
}
#endif
#if defined(__cplusplus)
}
#endif

173
libs/libks/crypt/aestab.h Normal file
View File

@ -0,0 +1,173 @@
/*
---------------------------------------------------------------------------
Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved.
The redistribution and use of this software (with or without changes)
is allowed without the payment of fees or royalties provided that:
source code distributions include the above copyright notice, this
list of conditions and the following disclaimer;
binary distributions include the above copyright notice, this list
of conditions and the following disclaimer in their documentation.
This software is provided 'as is' with no explicit or implied warranties
in respect of its operation, including, but not limited to, correctness
and fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 20/12/2007
This file contains the code for declaring the tables needed to implement
AES. The file aesopt.h is assumed to be included before this header file.
If there are no global variables, the definitions here can be used to put
the AES tables in a structure so that a pointer can then be added to the
AES context to pass them to the AES routines that need them. If this
facility is used, the calling program has to ensure that this pointer is
managed appropriately. In particular, the value of the t_dec(in,it) item
in the table structure must be set to zero in order to ensure that the
tables are initialised. In practice the three code sequences in aeskey.c
that control the calls to aes_init() and the aes_init() routine itself will
have to be changed for a specific implementation. If global variables are
available it will generally be preferable to use them with the precomputed
FIXED_TABLES option that uses static global tables.
The following defines can be used to control the way the tables
are defined, initialised and used in embedded environments that
require special features for these purposes
the 't_dec' construction is used to declare fixed table arrays
the 't_set' construction is used to set fixed table values
the 't_use' construction is used to access fixed table values
256 byte tables:
t_xxx(s,box) => forward S box
t_xxx(i,box) => inverse S box
256 32-bit word OR 4 x 256 32-bit word tables:
t_xxx(f,n) => forward normal round
t_xxx(f,l) => forward last round
t_xxx(i,n) => inverse normal round
t_xxx(i,l) => inverse last round
t_xxx(l,s) => key schedule table
t_xxx(i,m) => key schedule table
Other variables and tables:
t_xxx(r,c) => the rcon table
*/
#if !defined( _AESTAB_H )
#define _AESTAB_H
#if defined(__cplusplus)
extern "C" {
#endif
#define t_dec(m,n) t_##m##n
#define t_set(m,n) t_##m##n
#define t_use(m,n) t_##m##n
#if defined(FIXED_TABLES)
# if !defined( __GNUC__ ) && (defined( __MSDOS__ ) || defined( __WIN16__ ))
/* make tables far data to avoid using too much DGROUP space (PG) */
# define CONST const far
# else
# define CONST const
# endif
#else
# define CONST
#endif
#if defined(DO_TABLES)
# define EXTERN
#else
# define EXTERN extern
#endif
#if defined(_MSC_VER) && defined(TABLE_ALIGN)
#define ALIGN __declspec(align(TABLE_ALIGN))
#else
#define ALIGN
#endif
#if defined( __WATCOMC__ ) && ( __WATCOMC__ >= 1100 )
# define XP_DIR __cdecl
#else
# define XP_DIR
#endif
#if defined(DO_TABLES) && defined(FIXED_TABLES)
#define d_1(t,n,b,e) EXTERN ALIGN CONST XP_DIR t n[256] = b(e)
#define d_4(t,n,b,e,f,g,h) EXTERN ALIGN CONST XP_DIR t n[4][256] = { b(e), b(f), b(g), b(h) }
EXTERN ALIGN CONST uint_32t t_dec(r,c)[RC_LENGTH] = rc_data(w0);
#else
#define d_1(t,n,b,e) EXTERN ALIGN CONST XP_DIR t n[256]
#define d_4(t,n,b,e,f,g,h) EXTERN ALIGN CONST XP_DIR t n[4][256]
EXTERN ALIGN CONST uint_32t t_dec(r,c)[RC_LENGTH];
#endif
#if defined( SBX_SET )
d_1(uint_8t, t_dec(s,box), sb_data, h0);
#endif
#if defined( ISB_SET )
d_1(uint_8t, t_dec(i,box), isb_data, h0);
#endif
#if defined( FT1_SET )
d_1(uint_32t, t_dec(f,n), sb_data, u0);
#endif
#if defined( FT4_SET )
d_4(uint_32t, t_dec(f,n), sb_data, u0, u1, u2, u3);
#endif
#if defined( FL1_SET )
d_1(uint_32t, t_dec(f,l), sb_data, w0);
#endif
#if defined( FL4_SET )
d_4(uint_32t, t_dec(f,l), sb_data, w0, w1, w2, w3);
#endif
#if defined( IT1_SET )
d_1(uint_32t, t_dec(i,n), isb_data, v0);
#endif
#if defined( IT4_SET )
d_4(uint_32t, t_dec(i,n), isb_data, v0, v1, v2, v3);
#endif
#if defined( IL1_SET )
d_1(uint_32t, t_dec(i,l), isb_data, w0);
#endif
#if defined( IL4_SET )
d_4(uint_32t, t_dec(i,l), isb_data, w0, w1, w2, w3);
#endif
#if defined( LS1_SET )
#if defined( FL1_SET )
#undef LS1_SET
#else
d_1(uint_32t, t_dec(l,s), sb_data, w0);
#endif
#endif
#if defined( LS4_SET )
#if defined( FL4_SET )
#undef LS4_SET
#else
d_4(uint_32t, t_dec(l,s), sb_data, w0, w1, w2, w3);
#endif
#endif
#if defined( IM1_SET )
d_1(uint_32t, t_dec(i,m), mm_data, v0);
#endif
#if defined( IM4_SET )
d_4(uint_32t, t_dec(i,m), mm_data, v0, v1, v2, v3);
#endif
#if defined(__cplusplus)
}
#endif
#endif

View File

@ -0,0 +1,126 @@
/*
---------------------------------------------------------------------------
Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved.
The redistribution and use of this software (with or without changes)
is allowed without the payment of fees or royalties provided that:
source code distributions include the above copyright notice, this
list of conditions and the following disclaimer;
binary distributions include the above copyright notice, this list
of conditions and the following disclaimer in their documentation.
This software is provided 'as is' with no explicit or implied warranties
in respect of its operation, including, but not limited to, correctness
and fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 20/12/2007
*/
#ifndef _BRG_ENDIAN_H
#define _BRG_ENDIAN_H
#define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */
#define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */
/* Include files where endian defines and byteswap functions may reside */
#if defined( __sun )
# include <sys/isa_defs.h>
#elif defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __NetBSD__ )
# include <sys/endian.h>
#elif defined( BSD ) && ( BSD >= 199103 ) || defined( __APPLE__ ) || \
defined( __CYGWIN32__ ) || defined( __DJGPP__ ) || defined( __osf__ )
# include <machine/endian.h>
#elif defined( __linux__ ) || defined( __GNUC__ ) || defined( __GNU_LIBRARY__ )
# if !defined( __MINGW32__ ) && !defined( _AIX )
# include <endian.h>
# if !defined( __BEOS__ )
# include <byteswap.h>
# endif
# endif
#endif
/* Now attempt to set the define for platform byte order using any */
/* of the four forms SYMBOL, _SYMBOL, __SYMBOL & __SYMBOL__, which */
/* seem to encompass most endian symbol definitions */
#if defined( BIG_ENDIAN ) && defined( LITTLE_ENDIAN )
# if defined( BYTE_ORDER ) && BYTE_ORDER == BIG_ENDIAN
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( BYTE_ORDER ) && BYTE_ORDER == LITTLE_ENDIAN
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( BIG_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( LITTLE_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
#if defined( _BIG_ENDIAN ) && defined( _LITTLE_ENDIAN )
# if defined( _BYTE_ORDER ) && _BYTE_ORDER == _BIG_ENDIAN
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( _BYTE_ORDER ) && _BYTE_ORDER == _LITTLE_ENDIAN
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( _BIG_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( _LITTLE_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
#if defined( __BIG_ENDIAN ) && defined( __LITTLE_ENDIAN )
# if defined( __BYTE_ORDER ) && __BYTE_ORDER == __BIG_ENDIAN
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( __BYTE_ORDER ) && __BYTE_ORDER == __LITTLE_ENDIAN
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( __BIG_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( __LITTLE_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
#if defined( __BIG_ENDIAN__ ) && defined( __LITTLE_ENDIAN__ )
# if defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __BIG_ENDIAN__
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __LITTLE_ENDIAN__
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( __BIG_ENDIAN__ )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( __LITTLE_ENDIAN__ )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
/* if the platform byte order could not be determined, then try to */
/* set this define using common machine defines */
#if !defined(PLATFORM_BYTE_ORDER)
#if defined( __alpha__ ) || defined( __alpha ) || defined( i386 ) || \
defined( __i386__ ) || defined( _M_I86 ) || defined( _M_IX86 ) || \
defined( __OS2__ ) || defined( sun386 ) || defined( __TURBOC__ ) || \
defined( vax ) || defined( vms ) || defined( VMS ) || \
defined( __VMS ) || defined( _M_X64 )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#elif defined( AMIGA ) || defined( applec ) || defined( __AS400__ ) || \
defined( _CRAY ) || defined( __hppa ) || defined( __hp9000 ) || \
defined( ibm370 ) || defined( mc68000 ) || defined( m68k ) || \
defined( __MRC__ ) || defined( __MVS__ ) || defined( __MWERKS__ ) || \
defined( sparc ) || defined( __sparc) || defined( SYMANTEC_C ) || \
defined( __VOS__ ) || defined( __TIGCC__ ) || defined( __TANDEM ) || \
defined( THINK_C ) || defined( __VMCMS__ ) || defined( _AIX )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif 0 /* **** EDIT HERE IF NECESSARY **** */
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#elif 0 /* **** EDIT HERE IF NECESSARY **** */
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#else
# error Please edit lines 126 or 128 in brg_endian.h to set the platform byte order
#endif
#endif
#endif

View File

@ -0,0 +1,219 @@
/*
---------------------------------------------------------------------------
Copyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved.
The redistribution and use of this software (with or without changes)
is allowed without the payment of fees or royalties provided that:
source code distributions include the above copyright notice, this
list of conditions and the following disclaimer;
binary distributions include the above copyright notice, this list
of conditions and the following disclaimer in their documentation.
This software is provided 'as is' with no explicit or implied warranties
in respect of its operation, including, but not limited to, correctness
and fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 20/12/2007
The unsigned integer types defined here are of the form uint_<nn>t where
<nn> is the length of the type; for example, the unsigned 32-bit type is
'uint_32t'. These are NOT the same as the 'C99 integer types' that are
defined in the inttypes.h and stdint.h headers since attempts to use these
types have shown that support for them is still highly variable. However,
since the latter are of the form uint<nn>_t, a regular expression search
and replace (in VC++ search on 'uint_{:z}t' and replace with 'uint\1_t')
can be used to convert the types used here to the C99 standard types.
*/
#ifndef _BRG_TYPES_H
#define _BRG_TYPES_H
#if defined(__cplusplus)
extern "C" {
#endif
#include <limits.h>
#if defined( _MSC_VER ) && ( _MSC_VER >= 1300 )
# include <stddef.h>
# define ptrint_t intptr_t
#elif defined( __ECOS__ )
# define intptr_t unsigned int
# define ptrint_t intptr_t
#elif defined( __GNUC__ ) && ( __GNUC__ >= 3 )
# include <stdint.h>
# define ptrint_t intptr_t
#else
# define ptrint_t int
#endif
#ifndef BRG_UI8
# define BRG_UI8
# if UCHAR_MAX == 255u
typedef unsigned char uint_8t;
# else
# error Please define uint_8t as an 8-bit unsigned integer type in brg_types.h
# endif
#endif
#ifndef BRG_UI16
# define BRG_UI16
# if USHRT_MAX == 65535u
typedef unsigned short uint_16t;
# else
# error Please define uint_16t as a 16-bit unsigned short type in brg_types.h
# endif
#endif
#ifndef BRG_UI32
# define BRG_UI32
# if UINT_MAX == 4294967295u
# define li_32(h) 0x##h##u
typedef unsigned int uint_32t;
# elif ULONG_MAX == 4294967295u
# define li_32(h) 0x##h##ul
typedef unsigned long uint_32t;
# elif defined( _CRAY )
# error This code needs 32-bit data types, which Cray machines do not provide
# else
# error Please define uint_32t as a 32-bit unsigned integer type in brg_types.h
# endif
#endif
#ifndef BRG_UI64
# if defined( __BORLANDC__ ) && !defined( __MSDOS__ )
# define BRG_UI64
# define li_64(h) 0x##h##ui64
typedef unsigned __int64 uint_64t;
# elif defined( _MSC_VER ) && ( _MSC_VER < 1300 ) /* 1300 == VC++ 7.0 */
# define BRG_UI64
# define li_64(h) 0x##h##ui64
typedef unsigned __int64 uint_64t;
# elif defined( __sun ) && defined( ULONG_MAX ) && ULONG_MAX == 0xfffffffful
# define BRG_UI64
# define li_64(h) 0x##h##ull
typedef unsigned long long uint_64t;
# elif defined( __MVS__ )
# define BRG_UI64
# define li_64(h) 0x##h##ull
typedef unsigned int long long uint_64t;
# elif defined( UINT_MAX ) && UINT_MAX > 4294967295u
# if UINT_MAX == 18446744073709551615u
# define BRG_UI64
# define li_64(h) 0x##h##u
typedef unsigned int uint_64t;
# endif
# elif defined( ULONG_MAX ) && ULONG_MAX > 4294967295u
# if ULONG_MAX == 18446744073709551615ul
# define BRG_UI64
# define li_64(h) 0x##h##ul
typedef unsigned long uint_64t;
# endif
# elif defined( ULLONG_MAX ) && ULLONG_MAX > 4294967295u
# if ULLONG_MAX == 18446744073709551615ull
# define BRG_UI64
# define li_64(h) 0x##h##ull
typedef unsigned long long uint_64t;
# endif
# elif defined( ULONG_LONG_MAX ) && ULONG_LONG_MAX > 4294967295u
# if ULONG_LONG_MAX == 18446744073709551615ull
# define BRG_UI64
# define li_64(h) 0x##h##ull
typedef unsigned long long uint_64t;
# endif
# endif
#endif
#if !defined( BRG_UI64 )
# if defined( NEED_UINT_64T )
# error Please define uint_64t as an unsigned 64 bit type in brg_types.h
# endif
#endif
#ifndef RETURN_VALUES
# define RETURN_VALUES
# if defined( DLL_EXPORT )
# if defined( _MSC_VER ) || defined ( __INTEL_COMPILER )
# define VOID_RETURN __declspec( dllexport ) void __stdcall
# define INT_RETURN __declspec( dllexport ) int __stdcall
# elif defined( __GNUC__ )
# define VOID_RETURN __declspec( __dllexport__ ) void
# define INT_RETURN __declspec( __dllexport__ ) int
# else
# error Use of the DLL is only available on the Microsoft, Intel and GCC compilers
# endif
# elif defined( DLL_IMPORT )
# if defined( _MSC_VER ) || defined ( __INTEL_COMPILER )
# define VOID_RETURN __declspec( dllimport ) void __stdcall
# define INT_RETURN __declspec( dllimport ) int __stdcall
# elif defined( __GNUC__ )
# define VOID_RETURN __declspec( __dllimport__ ) void
# define INT_RETURN __declspec( __dllimport__ ) int
# else
# error Use of the DLL is only available on the Microsoft, Intel and GCC compilers
# endif
# elif defined( __WATCOMC__ )
# define VOID_RETURN void __cdecl
# define INT_RETURN int __cdecl
# else
# define VOID_RETURN void
# define INT_RETURN int
# endif
#endif
/* These defines are used to detect and set the memory alignment of pointers.
Note that offsets are in bytes.
ALIGN_OFFSET(x,n) return the positive or zero offset of
the memory addressed by the pointer 'x'
from an address that is aligned on an
'n' byte boundary ('n' is a power of 2)
ALIGN_FLOOR(x,n) return a pointer that points to memory
that is aligned on an 'n' byte boundary
and is not higher than the memory address
pointed to by 'x' ('n' is a power of 2)
ALIGN_CEIL(x,n) return a pointer that points to memory
that is aligned on an 'n' byte boundary
and is not lower than the memory address
pointed to by 'x' ('n' is a power of 2)
*/
#define ALIGN_OFFSET(x,n) (((ptrint_t)(x)) & ((n) - 1))
#define ALIGN_FLOOR(x,n) ((uint_8t*)(x) - ( ((ptrint_t)(x)) & ((n) - 1)))
#define ALIGN_CEIL(x,n) ((uint_8t*)(x) + (-((ptrint_t)(x)) & ((n) - 1)))
/* These defines are used to declare buffers in a way that allows
faster operations on longer variables to be used. In all these
defines 'size' must be a power of 2 and >= 8. NOTE that the
buffer size is in bytes but the type length is in bits
UNIT_TYPEDEF(x,size) declares a variable 'x' of length
'size' bits
BUFR_TYPEDEF(x,size,bsize) declares a buffer 'x' of length 'bsize'
bytes defined as an array of variables
each of 'size' bits (bsize must be a
multiple of size / 8)
UNIT_CAST(x,size) casts a variable to a type of
length 'size' bits
UPTR_CAST(x,size) casts a pointer to a pointer to a
varaiable of length 'size' bits
*/
#define UI_TYPE(size) uint_##size##t
#define UNIT_TYPEDEF(x,size) typedef UI_TYPE(size) x
#define BUFR_TYPEDEF(x,size,bsize) typedef UI_TYPE(size) x[bsize / (size >> 3)]
#define UNIT_CAST(x,size) ((UI_TYPE(size) )(x))
#define UPTR_CAST(x,size) ((UI_TYPE(size)*)(x))
#if defined(__cplusplus)
}
#endif
#endif

773
libs/libks/crypt/sha2.c Normal file
View File

@ -0,0 +1,773 @@
/*
---------------------------------------------------------------------------
Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
1. distributions of this source code include the above copyright
notice, this list of conditions and the following disclaimer;
2. distributions in binary form include the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other associated materials;
3. the copyright holder's name is not used to endorse products
built using this software without specific written permission.
ALTERNATIVELY, provided that this notice is retained in full, this product
may be distributed under the terms of the GNU General Public License (GPL),
in which case the provisions of the GPL apply INSTEAD OF those given above.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 01/08/2005
This is a byte oriented version of SHA2 that operates on arrays of bytes
stored in memory. This code implements sha256, sha384 and sha512 but the
latter two functions rely on efficient 64-bit integer operations that
may not be very efficient on 32-bit machines
The sha256 functions use a type 'sha256_ctx' to hold details of the
current hash state and uses the following three calls:
void sha256_begin(sha256_ctx ctx[1])
void sha256_hash(const unsigned char data[],
unsigned long len, sha256_ctx ctx[1])
void sha_end1(unsigned char hval[], sha256_ctx ctx[1])
The first subroutine initialises a hash computation by setting up the
context in the sha256_ctx context. The second subroutine hashes 8-bit
bytes from array data[] into the hash state withinh sha256_ctx context,
the number of bytes to be hashed being given by the the unsigned long
integer len. The third subroutine completes the hash calculation and
places the resulting digest value in the array of 8-bit bytes hval[].
The sha384 and sha512 functions are similar and use the interfaces:
void sha384_begin(sha384_ctx ctx[1]);
void sha384_hash(const unsigned char data[],
unsigned long len, sha384_ctx ctx[1]);
void sha384_end(unsigned char hval[], sha384_ctx ctx[1]);
void sha512_begin(sha512_ctx ctx[1]);
void sha512_hash(const unsigned char data[],
unsigned long len, sha512_ctx ctx[1]);
void sha512_end(unsigned char hval[], sha512_ctx ctx[1]);
In addition there is a function sha2 that can be used to call all these
functions using a call with a hash length parameter as follows:
int sha2_begin(unsigned long len, sha2_ctx ctx[1]);
void sha2_hash(const unsigned char data[],
unsigned long len, sha2_ctx ctx[1]);
void sha2_end(unsigned char hval[], sha2_ctx ctx[1]);
My thanks to Erik Andersen <andersen@codepoet.org> for testing this code
on big-endian systems and for his assistance with corrections
*/
#if 0
#define UNROLL_SHA2 /* for SHA2 loop unroll */
#endif
#include <string.h> /* for memcpy() etc. */
#include "sha2.h"
#include <crypt/brg_endian.h>
#if defined(__cplusplus)
extern "C"
{
#endif
#if defined( _MSC_VER ) && ( _MSC_VER > 800 )
#pragma intrinsic(memcpy)
#endif
#if 0 && defined(_MSC_VER)
#define rotl32 _lrotl
#define rotr32 _lrotr
#else
#define rotl32(x,n) (((x) << n) | ((x) >> (32 - n)))
#define rotr32(x,n) (((x) >> n) | ((x) << (32 - n)))
#endif
#if !defined(bswap_32)
#define bswap_32(x) ((rotr32((x), 24) & 0x00ff00ff) | (rotr32((x), 8) & 0xff00ff00))
#endif
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
#define SWAP_BYTES
#else
#undef SWAP_BYTES
#endif
#if 0
#define ch(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
#define maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#else /* Thanks to Rich Schroeppel and Colin Plumb for the following */
#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) ^ (y))))
#endif
/* round transforms for SHA256 and SHA512 compression functions */
#define vf(n,i) v[(n - i) & 7]
#define hf(i) (p[i & 15] += \
g_1(p[(i + 14) & 15]) + p[(i + 9) & 15] + g_0(p[(i + 1) & 15]))
#define v_cycle(i,j) \
vf(7,i) += (j ? hf(i) : p[i]) + k_0[i+j] \
+ s_1(vf(4,i)) + ch(vf(4,i),vf(5,i),vf(6,i)); \
vf(3,i) += vf(7,i); \
vf(7,i) += s_0(vf(0,i))+ maj(vf(0,i),vf(1,i),vf(2,i))
#if defined(SHA_224) || defined(SHA_256)
#define SHA256_MASK (SHA256_BLOCK_SIZE - 1)
#if defined(SWAP_BYTES)
#define bsw_32(p,n) \
{ int _i = (n); while(_i--) ((uint_32t*)p)[_i] = bswap_32(((uint_32t*)p)[_i]); }
#else
#define bsw_32(p,n)
#endif
#define s_0(x) (rotr32((x), 2) ^ rotr32((x), 13) ^ rotr32((x), 22))
#define s_1(x) (rotr32((x), 6) ^ rotr32((x), 11) ^ rotr32((x), 25))
#define g_0(x) (rotr32((x), 7) ^ rotr32((x), 18) ^ ((x) >> 3))
#define g_1(x) (rotr32((x), 17) ^ rotr32((x), 19) ^ ((x) >> 10))
#define k_0 k256
/* rotated SHA256 round definition. Rather than swapping variables as in */
/* FIPS-180, different variables are 'rotated' on each round, returning */
/* to their starting positions every eight rounds */
#define q(n) v##n
#define one_cycle(a,b,c,d,e,f,g,h,k,w) \
q(h) += s_1(q(e)) + ch(q(e), q(f), q(g)) + k + w; \
q(d) += q(h); q(h) += s_0(q(a)) + maj(q(a), q(b), q(c))
/* SHA256 mixing data */
const uint_32t k256[64] =
{ 0x428a2f98ul, 0x71374491ul, 0xb5c0fbcful, 0xe9b5dba5ul,
0x3956c25bul, 0x59f111f1ul, 0x923f82a4ul, 0xab1c5ed5ul,
0xd807aa98ul, 0x12835b01ul, 0x243185beul, 0x550c7dc3ul,
0x72be5d74ul, 0x80deb1feul, 0x9bdc06a7ul, 0xc19bf174ul,
0xe49b69c1ul, 0xefbe4786ul, 0x0fc19dc6ul, 0x240ca1ccul,
0x2de92c6ful, 0x4a7484aaul, 0x5cb0a9dcul, 0x76f988daul,
0x983e5152ul, 0xa831c66dul, 0xb00327c8ul, 0xbf597fc7ul,
0xc6e00bf3ul, 0xd5a79147ul, 0x06ca6351ul, 0x14292967ul,
0x27b70a85ul, 0x2e1b2138ul, 0x4d2c6dfcul, 0x53380d13ul,
0x650a7354ul, 0x766a0abbul, 0x81c2c92eul, 0x92722c85ul,
0xa2bfe8a1ul, 0xa81a664bul, 0xc24b8b70ul, 0xc76c51a3ul,
0xd192e819ul, 0xd6990624ul, 0xf40e3585ul, 0x106aa070ul,
0x19a4c116ul, 0x1e376c08ul, 0x2748774cul, 0x34b0bcb5ul,
0x391c0cb3ul, 0x4ed8aa4aul, 0x5b9cca4ful, 0x682e6ff3ul,
0x748f82eeul, 0x78a5636ful, 0x84c87814ul, 0x8cc70208ul,
0x90befffaul, 0xa4506cebul, 0xbef9a3f7ul, 0xc67178f2ul,
};
/* Compile 64 bytes of hash data into SHA256 digest value */
/* NOTE: this routine assumes that the byte order in the */
/* ctx->wbuf[] at this point is such that low address bytes */
/* in the ORIGINAL byte stream will go into the high end of */
/* words on BOTH big and little endian systems */
VOID_RETURN sha256_compile(sha256_ctx ctx[1])
{
#if !defined(UNROLL_SHA2)
uint_32t j, *p = ctx->wbuf, v[8];
memcpy(v, ctx->hash, 8 * sizeof(uint_32t));
for(j = 0; j < 64; j += 16)
{
v_cycle( 0, j); v_cycle( 1, j);
v_cycle( 2, j); v_cycle( 3, j);
v_cycle( 4, j); v_cycle( 5, j);
v_cycle( 6, j); v_cycle( 7, j);
v_cycle( 8, j); v_cycle( 9, j);
v_cycle(10, j); v_cycle(11, j);
v_cycle(12, j); v_cycle(13, j);
v_cycle(14, j); v_cycle(15, j);
}
ctx->hash[0] += v[0]; ctx->hash[1] += v[1];
ctx->hash[2] += v[2]; ctx->hash[3] += v[3];
ctx->hash[4] += v[4]; ctx->hash[5] += v[5];
ctx->hash[6] += v[6]; ctx->hash[7] += v[7];
#else
uint_32t *p = ctx->wbuf,v0,v1,v2,v3,v4,v5,v6,v7;
v0 = ctx->hash[0]; v1 = ctx->hash[1];
v2 = ctx->hash[2]; v3 = ctx->hash[3];
v4 = ctx->hash[4]; v5 = ctx->hash[5];
v6 = ctx->hash[6]; v7 = ctx->hash[7];
one_cycle(0,1,2,3,4,5,6,7,k256[ 0],p[ 0]);
one_cycle(7,0,1,2,3,4,5,6,k256[ 1],p[ 1]);
one_cycle(6,7,0,1,2,3,4,5,k256[ 2],p[ 2]);
one_cycle(5,6,7,0,1,2,3,4,k256[ 3],p[ 3]);
one_cycle(4,5,6,7,0,1,2,3,k256[ 4],p[ 4]);
one_cycle(3,4,5,6,7,0,1,2,k256[ 5],p[ 5]);
one_cycle(2,3,4,5,6,7,0,1,k256[ 6],p[ 6]);
one_cycle(1,2,3,4,5,6,7,0,k256[ 7],p[ 7]);
one_cycle(0,1,2,3,4,5,6,7,k256[ 8],p[ 8]);
one_cycle(7,0,1,2,3,4,5,6,k256[ 9],p[ 9]);
one_cycle(6,7,0,1,2,3,4,5,k256[10],p[10]);
one_cycle(5,6,7,0,1,2,3,4,k256[11],p[11]);
one_cycle(4,5,6,7,0,1,2,3,k256[12],p[12]);
one_cycle(3,4,5,6,7,0,1,2,k256[13],p[13]);
one_cycle(2,3,4,5,6,7,0,1,k256[14],p[14]);
one_cycle(1,2,3,4,5,6,7,0,k256[15],p[15]);
one_cycle(0,1,2,3,4,5,6,7,k256[16],hf( 0));
one_cycle(7,0,1,2,3,4,5,6,k256[17],hf( 1));
one_cycle(6,7,0,1,2,3,4,5,k256[18],hf( 2));
one_cycle(5,6,7,0,1,2,3,4,k256[19],hf( 3));
one_cycle(4,5,6,7,0,1,2,3,k256[20],hf( 4));
one_cycle(3,4,5,6,7,0,1,2,k256[21],hf( 5));
one_cycle(2,3,4,5,6,7,0,1,k256[22],hf( 6));
one_cycle(1,2,3,4,5,6,7,0,k256[23],hf( 7));
one_cycle(0,1,2,3,4,5,6,7,k256[24],hf( 8));
one_cycle(7,0,1,2,3,4,5,6,k256[25],hf( 9));
one_cycle(6,7,0,1,2,3,4,5,k256[26],hf(10));
one_cycle(5,6,7,0,1,2,3,4,k256[27],hf(11));
one_cycle(4,5,6,7,0,1,2,3,k256[28],hf(12));
one_cycle(3,4,5,6,7,0,1,2,k256[29],hf(13));
one_cycle(2,3,4,5,6,7,0,1,k256[30],hf(14));
one_cycle(1,2,3,4,5,6,7,0,k256[31],hf(15));
one_cycle(0,1,2,3,4,5,6,7,k256[32],hf( 0));
one_cycle(7,0,1,2,3,4,5,6,k256[33],hf( 1));
one_cycle(6,7,0,1,2,3,4,5,k256[34],hf( 2));
one_cycle(5,6,7,0,1,2,3,4,k256[35],hf( 3));
one_cycle(4,5,6,7,0,1,2,3,k256[36],hf( 4));
one_cycle(3,4,5,6,7,0,1,2,k256[37],hf( 5));
one_cycle(2,3,4,5,6,7,0,1,k256[38],hf( 6));
one_cycle(1,2,3,4,5,6,7,0,k256[39],hf( 7));
one_cycle(0,1,2,3,4,5,6,7,k256[40],hf( 8));
one_cycle(7,0,1,2,3,4,5,6,k256[41],hf( 9));
one_cycle(6,7,0,1,2,3,4,5,k256[42],hf(10));
one_cycle(5,6,7,0,1,2,3,4,k256[43],hf(11));
one_cycle(4,5,6,7,0,1,2,3,k256[44],hf(12));
one_cycle(3,4,5,6,7,0,1,2,k256[45],hf(13));
one_cycle(2,3,4,5,6,7,0,1,k256[46],hf(14));
one_cycle(1,2,3,4,5,6,7,0,k256[47],hf(15));
one_cycle(0,1,2,3,4,5,6,7,k256[48],hf( 0));
one_cycle(7,0,1,2,3,4,5,6,k256[49],hf( 1));
one_cycle(6,7,0,1,2,3,4,5,k256[50],hf( 2));
one_cycle(5,6,7,0,1,2,3,4,k256[51],hf( 3));
one_cycle(4,5,6,7,0,1,2,3,k256[52],hf( 4));
one_cycle(3,4,5,6,7,0,1,2,k256[53],hf( 5));
one_cycle(2,3,4,5,6,7,0,1,k256[54],hf( 6));
one_cycle(1,2,3,4,5,6,7,0,k256[55],hf( 7));
one_cycle(0,1,2,3,4,5,6,7,k256[56],hf( 8));
one_cycle(7,0,1,2,3,4,5,6,k256[57],hf( 9));
one_cycle(6,7,0,1,2,3,4,5,k256[58],hf(10));
one_cycle(5,6,7,0,1,2,3,4,k256[59],hf(11));
one_cycle(4,5,6,7,0,1,2,3,k256[60],hf(12));
one_cycle(3,4,5,6,7,0,1,2,k256[61],hf(13));
one_cycle(2,3,4,5,6,7,0,1,k256[62],hf(14));
one_cycle(1,2,3,4,5,6,7,0,k256[63],hf(15));
ctx->hash[0] += v0; ctx->hash[1] += v1;
ctx->hash[2] += v2; ctx->hash[3] += v3;
ctx->hash[4] += v4; ctx->hash[5] += v5;
ctx->hash[6] += v6; ctx->hash[7] += v7;
#endif
}
/* SHA256 hash data in an array of bytes into hash buffer */
/* and call the hash_compile function as required. */
VOID_RETURN sha256_hash(const unsigned char data[], unsigned long len, sha256_ctx ctx[1])
{ uint_32t pos = (uint_32t)(ctx->count[0] & SHA256_MASK),
space = SHA256_BLOCK_SIZE - pos;
const unsigned char *sp = data;
if((ctx->count[0] += len) < len)
++(ctx->count[1]);
while(len >= space) /* tranfer whole blocks while possible */
{
memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space);
sp += space; len -= space; space = SHA256_BLOCK_SIZE; pos = 0;
bsw_32(ctx->wbuf, SHA256_BLOCK_SIZE >> 2)
sha256_compile(ctx);
}
memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len);
}
/* SHA256 Final padding and digest calculation */
static void sha_end1(unsigned char hval[], sha256_ctx ctx[1], const unsigned int hlen)
{ uint_32t i = (uint_32t)(ctx->count[0] & SHA256_MASK);
/* put bytes in the buffer in an order in which references to */
/* 32-bit words will put bytes with lower addresses into the */
/* top of 32 bit words on BOTH big and little endian machines */
bsw_32(ctx->wbuf, (i + 3) >> 2)
/* we now need to mask valid bytes and add the padding which is */
/* a single 1 bit and as many zero bits as necessary. Note that */
/* we can always add the first padding byte here because the */
/* buffer always has at least one empty slot */
ctx->wbuf[i >> 2] &= 0xffffff80 << 8 * (~i & 3);
ctx->wbuf[i >> 2] |= 0x00000080 << 8 * (~i & 3);
/* we need 9 or more empty positions, one for the padding byte */
/* (above) and eight for the length count. If there is not */
/* enough space pad and empty the buffer */
if(i > SHA256_BLOCK_SIZE - 9)
{
if(i < 60) ctx->wbuf[15] = 0;
sha256_compile(ctx);
i = 0;
}
else /* compute a word index for the empty buffer positions */
i = (i >> 2) + 1;
while(i < 14) /* and zero pad all but last two positions */
ctx->wbuf[i++] = 0;
/* the following 32-bit length fields are assembled in the */
/* wrong byte order on little endian machines but this is */
/* corrected later since they are only ever used as 32-bit */
/* word values. */
ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 29);
ctx->wbuf[15] = ctx->count[0] << 3;
sha256_compile(ctx);
/* extract the hash value as bytes in case the hash buffer is */
/* mislaigned for 32-bit words */
for(i = 0; i < hlen; ++i)
hval[i] = (unsigned char)(ctx->hash[i >> 2] >> (8 * (~i & 3)));
}
#endif
#if defined(SHA_224)
const uint_32t i224[8] =
{
0xc1059ed8ul, 0x367cd507ul, 0x3070dd17ul, 0xf70e5939ul,
0xffc00b31ul, 0x68581511ul, 0x64f98fa7ul, 0xbefa4fa4ul
};
VOID_RETURN sha224_begin(sha224_ctx ctx[1])
{
ctx->count[0] = ctx->count[1] = 0;
memcpy(ctx->hash, i224, 8 * sizeof(uint_32t));
}
VOID_RETURN sha224_end(unsigned char hval[], sha224_ctx ctx[1])
{
sha_end1(hval, ctx, SHA224_DIGEST_SIZE);
}
VOID_RETURN sha224_zrtp(unsigned char hval[], const unsigned char data[], unsigned long len)
{ sha224_ctx cx[1];
sha224_begin(cx);
sha224_hash(data, len, cx);
sha_end1(hval, cx, SHA224_DIGEST_SIZE);
}
#endif
#if defined(SHA_256)
const uint_32t i256[8] =
{
0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul,
0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul
};
VOID_RETURN sha256_begin(sha256_ctx ctx[1])
{
ctx->count[0] = ctx->count[1] = 0;
memcpy(ctx->hash, i256, 8 * sizeof(uint_32t));
}
VOID_RETURN sha256_end(unsigned char hval[], sha256_ctx ctx[1])
{
sha_end1(hval, ctx, SHA256_DIGEST_SIZE);
}
VOID_RETURN sha256_zrtp(unsigned char hval[], const unsigned char data[], unsigned long len)
{ sha256_ctx cx[1];
sha256_begin(cx);
sha256_hash(data, len, cx);
sha_end1(hval, cx, SHA256_DIGEST_SIZE);
}
#endif
#if defined(SHA_384) || defined(SHA_512)
#define SHA512_MASK (SHA512_BLOCK_SIZE - 1)
#define rotr64(x,n) (((x) >> n) | ((x) << (64 - n)))
#if !defined(bswap_64)
#define bswap_64(x) (((uint_64t)(bswap_32((uint_32t)(x)))) << 32 | bswap_32((uint_32t)((x) >> 32)))
#endif
#if defined(SWAP_BYTES)
#define bsw_64(p,n) \
{ int _i = (n); while(_i--) ((uint_64t*)p)[_i] = bswap_64(((uint_64t*)p)[_i]); }
#else
#define bsw_64(p,n)
#endif
/* SHA512 mixing function definitions */
#ifdef s_0
# undef s_0
# undef s_1
# undef g_0
# undef g_1
# undef k_0
#endif
#define s_0(x) (rotr64((x), 28) ^ rotr64((x), 34) ^ rotr64((x), 39))
#define s_1(x) (rotr64((x), 14) ^ rotr64((x), 18) ^ rotr64((x), 41))
#define g_0(x) (rotr64((x), 1) ^ rotr64((x), 8) ^ ((x) >> 7))
#define g_1(x) (rotr64((x), 19) ^ rotr64((x), 61) ^ ((x) >> 6))
#define k_0 k512
/* SHA384/SHA512 mixing data */
const uint_64t k512[80] =
{
li_64(428a2f98d728ae22), li_64(7137449123ef65cd),
li_64(b5c0fbcfec4d3b2f), li_64(e9b5dba58189dbbc),
li_64(3956c25bf348b538), li_64(59f111f1b605d019),
li_64(923f82a4af194f9b), li_64(ab1c5ed5da6d8118),
li_64(d807aa98a3030242), li_64(12835b0145706fbe),
li_64(243185be4ee4b28c), li_64(550c7dc3d5ffb4e2),
li_64(72be5d74f27b896f), li_64(80deb1fe3b1696b1),
li_64(9bdc06a725c71235), li_64(c19bf174cf692694),
li_64(e49b69c19ef14ad2), li_64(efbe4786384f25e3),
li_64(0fc19dc68b8cd5b5), li_64(240ca1cc77ac9c65),
li_64(2de92c6f592b0275), li_64(4a7484aa6ea6e483),
li_64(5cb0a9dcbd41fbd4), li_64(76f988da831153b5),
li_64(983e5152ee66dfab), li_64(a831c66d2db43210),
li_64(b00327c898fb213f), li_64(bf597fc7beef0ee4),
li_64(c6e00bf33da88fc2), li_64(d5a79147930aa725),
li_64(06ca6351e003826f), li_64(142929670a0e6e70),
li_64(27b70a8546d22ffc), li_64(2e1b21385c26c926),
li_64(4d2c6dfc5ac42aed), li_64(53380d139d95b3df),
li_64(650a73548baf63de), li_64(766a0abb3c77b2a8),
li_64(81c2c92e47edaee6), li_64(92722c851482353b),
li_64(a2bfe8a14cf10364), li_64(a81a664bbc423001),
li_64(c24b8b70d0f89791), li_64(c76c51a30654be30),
li_64(d192e819d6ef5218), li_64(d69906245565a910),
li_64(f40e35855771202a), li_64(106aa07032bbd1b8),
li_64(19a4c116b8d2d0c8), li_64(1e376c085141ab53),
li_64(2748774cdf8eeb99), li_64(34b0bcb5e19b48a8),
li_64(391c0cb3c5c95a63), li_64(4ed8aa4ae3418acb),
li_64(5b9cca4f7763e373), li_64(682e6ff3d6b2b8a3),
li_64(748f82ee5defb2fc), li_64(78a5636f43172f60),
li_64(84c87814a1f0ab72), li_64(8cc702081a6439ec),
li_64(90befffa23631e28), li_64(a4506cebde82bde9),
li_64(bef9a3f7b2c67915), li_64(c67178f2e372532b),
li_64(ca273eceea26619c), li_64(d186b8c721c0c207),
li_64(eada7dd6cde0eb1e), li_64(f57d4f7fee6ed178),
li_64(06f067aa72176fba), li_64(0a637dc5a2c898a6),
li_64(113f9804bef90dae), li_64(1b710b35131c471b),
li_64(28db77f523047d84), li_64(32caab7b40c72493),
li_64(3c9ebe0a15c9bebc), li_64(431d67c49c100d4c),
li_64(4cc5d4becb3e42b6), li_64(597f299cfc657e2a),
li_64(5fcb6fab3ad6faec), li_64(6c44198c4a475817)
};
/* Compile 128 bytes of hash data into SHA384/512 digest */
/* NOTE: this routine assumes that the byte order in the */
/* ctx->wbuf[] at this point is such that low address bytes */
/* in the ORIGINAL byte stream will go into the high end of */
/* words on BOTH big and little endian systems */
VOID_RETURN sha512_compile(sha512_ctx ctx[1])
{ uint_64t v[8], *p = ctx->wbuf;
uint_32t j;
memcpy(v, ctx->hash, 8 * sizeof(uint_64t));
for(j = 0; j < 80; j += 16)
{
v_cycle( 0, j); v_cycle( 1, j);
v_cycle( 2, j); v_cycle( 3, j);
v_cycle( 4, j); v_cycle( 5, j);
v_cycle( 6, j); v_cycle( 7, j);
v_cycle( 8, j); v_cycle( 9, j);
v_cycle(10, j); v_cycle(11, j);
v_cycle(12, j); v_cycle(13, j);
v_cycle(14, j); v_cycle(15, j);
}
ctx->hash[0] += v[0]; ctx->hash[1] += v[1];
ctx->hash[2] += v[2]; ctx->hash[3] += v[3];
ctx->hash[4] += v[4]; ctx->hash[5] += v[5];
ctx->hash[6] += v[6]; ctx->hash[7] += v[7];
}
/* Compile 128 bytes of hash data into SHA256 digest value */
/* NOTE: this routine assumes that the byte order in the */
/* ctx->wbuf[] at this point is in such an order that low */
/* address bytes in the ORIGINAL byte stream placed in this */
/* buffer will now go to the high end of words on BOTH big */
/* and little endian systems */
VOID_RETURN sha512_hash(const unsigned char data[], unsigned long len, sha512_ctx ctx[1])
{ uint_32t pos = (uint_32t)(ctx->count[0] & SHA512_MASK),
space = SHA512_BLOCK_SIZE - pos;
const unsigned char *sp = data;
if((ctx->count[0] += len) < len)
++(ctx->count[1]);
while(len >= space) /* tranfer whole blocks while possible */
{
memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space);
sp += space; len -= space; space = SHA512_BLOCK_SIZE; pos = 0;
bsw_64(ctx->wbuf, SHA512_BLOCK_SIZE >> 3);
sha512_compile(ctx);
}
memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len);
}
/* SHA384/512 Final padding and digest calculation */
static void sha_end2(unsigned char hval[], sha512_ctx ctx[1], const unsigned int hlen)
{ uint_32t i = (uint_32t)(ctx->count[0] & SHA512_MASK);
/* put bytes in the buffer in an order in which references to */
/* 32-bit words will put bytes with lower addresses into the */
/* top of 32 bit words on BOTH big and little endian machines */
bsw_64(ctx->wbuf, (i + 7) >> 3);
/* we now need to mask valid bytes and add the padding which is */
/* a single 1 bit and as many zero bits as necessary. Note that */
/* we can always add the first padding byte here because the */
/* buffer always has at least one empty slot */
ctx->wbuf[i >> 3] &= li_64(ffffffffffffff00) << 8 * (~i & 7);
ctx->wbuf[i >> 3] |= li_64(0000000000000080) << 8 * (~i & 7);
/* we need 17 or more empty byte positions, one for the padding */
/* byte (above) and sixteen for the length count. If there is */
/* not enough space pad and empty the buffer */
if(i > SHA512_BLOCK_SIZE - 17)
{
if(i < 120) ctx->wbuf[15] = 0;
sha512_compile(ctx);
i = 0;
}
else
i = (i >> 3) + 1;
while(i < 14)
ctx->wbuf[i++] = 0;
/* the following 64-bit length fields are assembled in the */
/* wrong byte order on little endian machines but this is */
/* corrected later since they are only ever used as 64-bit */
/* word values. */
ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 61);
ctx->wbuf[15] = ctx->count[0] << 3;
sha512_compile(ctx);
/* extract the hash value as bytes in case the hash buffer is */
/* misaligned for 32-bit words */
for(i = 0; i < hlen; ++i)
hval[i] = (unsigned char)(ctx->hash[i >> 3] >> (8 * (~i & 7)));
}
#endif
#if defined(SHA_384)
/* SHA384 initialisation data */
const uint_64t i384[80] =
{
li_64(cbbb9d5dc1059ed8), li_64(629a292a367cd507),
li_64(9159015a3070dd17), li_64(152fecd8f70e5939),
li_64(67332667ffc00b31), li_64(8eb44a8768581511),
li_64(db0c2e0d64f98fa7), li_64(47b5481dbefa4fa4)
};
VOID_RETURN sha384_begin(sha384_ctx ctx[1])
{
ctx->count[0] = ctx->count[1] = 0;
memcpy(ctx->hash, i384, 8 * sizeof(uint_64t));
}
VOID_RETURN sha384_end(unsigned char hval[], sha384_ctx ctx[1])
{
sha_end2(hval, ctx, SHA384_DIGEST_SIZE);
}
VOID_RETURN sha384_zrtp(unsigned char hval[], const unsigned char data[], unsigned long len)
{ sha384_ctx cx[1];
sha384_begin(cx);
sha384_hash(data, len, cx);
sha_end2(hval, cx, SHA384_DIGEST_SIZE);
}
#endif
#if defined(SHA_512)
/* SHA512 initialisation data */
const uint_64t i512[80] =
{
li_64(6a09e667f3bcc908), li_64(bb67ae8584caa73b),
li_64(3c6ef372fe94f82b), li_64(a54ff53a5f1d36f1),
li_64(510e527fade682d1), li_64(9b05688c2b3e6c1f),
li_64(1f83d9abfb41bd6b), li_64(5be0cd19137e2179)
};
VOID_RETURN sha512_begin(sha512_ctx ctx[1])
{
ctx->count[0] = ctx->count[1] = 0;
memcpy(ctx->hash, i512, 8 * sizeof(uint_64t));
}
VOID_RETURN sha512_end(unsigned char hval[], sha512_ctx ctx[1])
{
sha_end2(hval, ctx, SHA512_DIGEST_SIZE);
}
VOID_RETURN sha512_zrtp(unsigned char hval[], const unsigned char data[], unsigned long len)
{ sha512_ctx cx[1];
sha512_begin(cx);
sha512_hash(data, len, cx);
sha_end2(hval, cx, SHA512_DIGEST_SIZE);
}
#endif
#if defined(SHA_2)
#define CTX_224(x) ((x)->uu->ctx256)
#define CTX_256(x) ((x)->uu->ctx256)
#define CTX_384(x) ((x)->uu->ctx512)
#define CTX_512(x) ((x)->uu->ctx512)
/* SHA2 initialisation */
INT_RETURN sha2_begin(unsigned long len, sha2_ctx ctx[1])
{
switch(len)
{
#if defined(SHA_224)
case 224:
case 28: CTX_256(ctx)->count[0] = CTX_256(ctx)->count[1] = 0;
memcpy(CTX_256(ctx)->hash, i224, 32);
ctx->sha2_len = 28; return EXIT_SUCCESS;
#endif
#if defined(SHA_256)
case 256:
case 32: CTX_256(ctx)->count[0] = CTX_256(ctx)->count[1] = 0;
memcpy(CTX_256(ctx)->hash, i256, 32);
ctx->sha2_len = 32; return EXIT_SUCCESS;
#endif
#if defined(SHA_384)
case 384:
case 48: CTX_384(ctx)->count[0] = CTX_384(ctx)->count[1] = 0;
memcpy(CTX_384(ctx)->hash, i384, 64);
ctx->sha2_len = 48; return EXIT_SUCCESS;
#endif
#if defined(SHA_512)
case 512:
case 64: CTX_512(ctx)->count[0] = CTX_512(ctx)->count[1] = 0;
memcpy(CTX_512(ctx)->hash, i512, 64);
ctx->sha2_len = 64; return EXIT_SUCCESS;
#endif
default: return EXIT_FAILURE;
}
}
VOID_RETURN sha2_hash(const unsigned char data[], unsigned long len, sha2_ctx ctx[1])
{
switch(ctx->sha2_len)
{
#if defined(SHA_224)
case 28: sha224_hash(data, len, CTX_224(ctx)); return;
#endif
#if defined(SHA_256)
case 32: sha256_hash(data, len, CTX_256(ctx)); return;
#endif
#if defined(SHA_384)
case 48: sha384_hash(data, len, CTX_384(ctx)); return;
#endif
#if defined(SHA_512)
case 64: sha512_hash(data, len, CTX_512(ctx)); return;
#endif
}
}
VOID_RETURN sha2_end(unsigned char hval[], sha2_ctx ctx[1])
{
switch(ctx->sha2_len)
{
#if defined(SHA_224)
case 28: sha_end1(hval, CTX_224(ctx), SHA224_DIGEST_SIZE); return;
#endif
#if defined(SHA_256)
case 32: sha_end1(hval, CTX_256(ctx), SHA256_DIGEST_SIZE); return;
#endif
#if defined(SHA_384)
case 48: sha_end2(hval, CTX_384(ctx), SHA384_DIGEST_SIZE); return;
#endif
#if defined(SHA_512)
case 64: sha_end2(hval, CTX_512(ctx), SHA512_DIGEST_SIZE); return;
#endif
}
}
INT_RETURN sha2_all(unsigned char hval[], unsigned long size,
const unsigned char data[], unsigned long len)
{ sha2_ctx cx[1];
if(sha2_begin(size, cx) == EXIT_SUCCESS)
{
sha2_hash(data, len, cx); sha2_end(hval, cx); return EXIT_SUCCESS;
}
else
return EXIT_FAILURE;
}
#endif
#if defined(__cplusplus)
}
#endif

151
libs/libks/crypt/sha2.h Normal file
View File

@ -0,0 +1,151 @@
/*
---------------------------------------------------------------------------
Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
1. distributions of this source code include the above copyright
notice, this list of conditions and the following disclaimer;
2. distributions in binary form include the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other associated materials;
3. the copyright holder's name is not used to endorse products
built using this software without specific written permission.
ALTERNATIVELY, provided that this notice is retained in full, this product
may be distributed under the terms of the GNU General Public License (GPL),
in which case the provisions of the GPL apply INSTEAD OF those given above.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 01/08/2005
*/
#ifndef _SHA2_H
#define _SHA2_H
#include <stdlib.h>
#define SHA_64BIT
/* define the hash functions that you need */
#define SHA_2 /* for dynamic hash length */
#define SHA_224
#define SHA_256
#ifdef SHA_64BIT
# define SHA_384
# define SHA_512
# define NEED_UINT_64T
#endif
#include <crypt/brg_types.h>
#if defined(__cplusplus)
extern "C"
{
#endif
/* Note that the following function prototypes are the same */
/* for both the bit and byte oriented implementations. But */
/* the length fields are in bytes or bits as is appropriate */
/* for the version used. Bit sequences are arrays of bytes */
/* in which bit sequence indexes increase from the most to */
/* the least significant end of each byte */
#define SHA224_DIGEST_SIZE 28
#define SHA224_BLOCK_SIZE 64
#define SHA256_DIGEST_SIZE 32
#define SHA256_BLOCK_SIZE 64
/* type to hold the SHA256 (and SHA224) context */
typedef struct
{ uint_32t count[2];
uint_32t hash[8];
uint_32t wbuf[16];
} sha256_ctx;
typedef sha256_ctx sha224_ctx;
VOID_RETURN sha256_compile(sha256_ctx ctx[1]);
VOID_RETURN sha224_begin(sha224_ctx ctx[1]);
#define sha224_hash sha256_hash
VOID_RETURN sha224_end(unsigned char hval[], sha224_ctx ctx[1]);
VOID_RETURN sha224_zrtp(unsigned char hval[], const unsigned char data[], unsigned long len);
VOID_RETURN sha256_begin(sha256_ctx ctx[1]);
VOID_RETURN sha256_hash(const unsigned char data[], unsigned long len, sha256_ctx ctx[1]);
VOID_RETURN sha256_end(unsigned char hval[], sha256_ctx ctx[1]);
VOID_RETURN sha256_zrtp(unsigned char hval[], const unsigned char data[], unsigned long len);
#ifndef SHA_64BIT
typedef struct
{ union
{ sha256_ctx ctx256[1];
} uu[1];
uint_32t sha2_len;
} sha2_ctx;
#define SHA2_MAX_DIGEST_SIZE SHA256_DIGEST_SIZE
#else
#define SHA384_DIGEST_SIZE 48
#define SHA384_BLOCK_SIZE 128
#define SHA512_DIGEST_SIZE 64
#define SHA512_BLOCK_SIZE 128
#define SHA2_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE
/* type to hold the SHA384 (and SHA512) context */
typedef struct
{ uint_64t count[2];
uint_64t hash[8];
uint_64t wbuf[16];
} sha512_ctx;
typedef sha512_ctx sha384_ctx;
typedef struct
{ union
{ sha256_ctx ctx256[1];
sha512_ctx ctx512[1];
} uu[1];
uint_32t sha2_len;
} sha2_ctx;
VOID_RETURN sha512_compile(sha512_ctx ctx[1]);
VOID_RETURN sha384_begin(sha384_ctx ctx[1]);
#define sha384_hash sha512_hash
VOID_RETURN sha384_end(unsigned char hval[], sha384_ctx ctx[1]);
VOID_RETURN sha384_zrtp(unsigned char hval[], const unsigned char data[], unsigned long len);
VOID_RETURN sha512_begin(sha512_ctx ctx[1]);
VOID_RETURN sha512_hash(const unsigned char data[], unsigned long len, sha512_ctx ctx[1]);
VOID_RETURN sha512_end(unsigned char hval[], sha512_ctx ctx[1]);
VOID_RETURN sha512_zrtp(unsigned char hval[], const unsigned char data[], unsigned long len);
INT_RETURN sha2_begin(unsigned long size, sha2_ctx ctx[1]);
VOID_RETURN sha2_hash(const unsigned char data[], unsigned long len, sha2_ctx ctx[1]);
VOID_RETURN sha2_end(unsigned char hval[], sha2_ctx ctx[1]);
INT_RETURN sha2_all(unsigned char hval[], unsigned long size, const unsigned char data[], unsigned long len);
#endif
#if defined(__cplusplus)
}
#endif
#endif

1750
libs/libks/crypt/twofish.c Normal file

File diff suppressed because it is too large Load Diff

265
libs/libks/crypt/twofish.h Executable file
View File

@ -0,0 +1,265 @@
/*
* Fast, portable, and easy-to-use Twofish implementation,
* Version 0.3.
* Copyright (c) 2002 by Niels Ferguson.
*
* See the twofish.c file for the details of the how and why of this code.
*
* The author hereby grants a perpetual license to everybody to
* use this code for any purpose as long as the copyright message is included
* in the source code of this or any derived work.
*/
/*
* PLATFORM FIXES
* ==============
*
* The following definitions have to be fixed for each particular platform
* you work on. If you have a multi-platform program, you no doubt have
* portable definitions that you can substitute here without changing
* the rest of the code.
*
* The defaults provided here should work on most PC compilers.
*/
#ifndef TWOFISH_H
#define TWOFISH_H
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @file twofish.h
* @brief Function that provide basic Twofish crypto support
*
* @ingroup GNU_ZRTP
* @{
*/
/**
* A Twofish_Byte must be an unsigned 8-bit integer.
*
* It must also be the elementary data size of your C platform,
* i.e. sizeof( Twofish_Byte ) == 1.
*/
typedef unsigned char Twofish_Byte;
/**
* A Twofish_UInt32 must be an unsigned integer of at least 32 bits.
*
* This type is used only internally in the implementation, so ideally it
* would not appear in the header file, but it is used inside the
* Twofish_key structure which means it has to be included here.
*/
typedef unsigned int Twofish_UInt32;
/*
* END OF PLATFORM FIXES
* =====================
*
* You should not have to touch the rest of this file, but the code
* in twofish.c has a few things you need to fix too.
*/
/**
* Return codes
*/
#define SUCCESS 1
#define ERR_UINT32 -2
#define ERR_BYTE -3
#define ERR_GET32 -4
#define ERR_PUT32 -5
#define ERR_ROLR -6
#define ERR_BSWAP -7
#define ERR_SELECTB -8
#define ERR_TEST_ENC -9
#define ERR_TEST_DEC -10
#define ERR_SEQ_ENC -11
#define ERR_SEQ_DEC -12
#define ERR_ODD_KEY -13
#define ERR_INIT -14
#define ERR_KEY_LEN -15
#define ERR_ILL_ARG -16
/**
* Structure that contains a prepared Twofish key.
*
* A cipher key is used in two stages. In the first stage it is converted
* form the original form to an internal representation.
* This internal form is then used to encrypt and decrypt data.
* This structure contains the internal form. It is rather large: 4256 bytes
* on a platform with 32-bit unsigned values.
*
* Treat this as an opague structure, and don't try to manipulate the
* elements in it. I wish I could hide the inside of the structure,
* but C doesn't allow that.
*/
typedef
struct
{
Twofish_UInt32 s[4][256]; /* pre-computed S-boxes */
Twofish_UInt32 K[40]; /* Round key words */
}
Twofish_key;
/**
* Initialise and test the Twofish implementation.
*
* This function MUST be called before any other function in the
* Twofish implementation is called.
* It only needs to be called once.
*
* Apart from initialising the implementation it performs a self test.
* If the Twofish_fatal function is not called, the code passed the test.
* (See the twofish.c file for details on the Twofish_fatal function.)
*
* @returns a negative number if an error happend, +1 otherwise
*/
extern int Twofish_initialise();
/**
* Convert a cipher key to the internal form used for
* encryption and decryption.
*
* The cipher key is an array of bytes; the Twofish_Byte type is
* defined above to a type suitable on your platform.
*
* Any key must be converted to an internal form in the Twofisk_key structure
* before it can be used.
* The encryption and decryption functions only work with the internal form.
* The conversion to internal form need only be done once for each key value.
*
* Be sure to wipe all key storage, including the Twofish_key structure,
* once you are done with the key data.
* A simple memset( TwofishKey, 0, sizeof( TwofishKey ) ) will do just fine.
*
* Unlike most implementations, this one allows any key size from 0 bytes
* to 32 bytes. According to the Twofish specifications,
* irregular key sizes are handled by padding the key with zeroes at the end
* until the key size is 16, 24, or 32 bytes, whichever
* comes first. Note that each key of irregular size is equivalent to exactly
* one key of 16, 24, or 32 bytes.
*
* WARNING: Short keys have low entropy, and result in low security.
* Anything less than 8 bytes is utterly insecure. For good security
* use at least 16 bytes. I prefer to use 32-byte keys to prevent
* any collision attacks on the key.
*
* The key length argument key_len must be in the proper range.
* If key_len is not in the range 0,...,32 this routine attempts to generate
* a fatal error (depending on the code environment),
* and at best (or worst) returns without having done anything.
*
* @param key Array of key bytes
* @param key_len Number of key bytes, must be in the range 0,1,...,32.
* @param xkey Pointer to an Twofish_key structure that will be filled
* with the internal form of the cipher key.
* @returns a negative number if an error happend, +1 otherwise
*/
extern int Twofish_prepare_key(
Twofish_Byte key[],
int key_len,
Twofish_key * xkey
);
/**
* Encrypt a single block of data.
*
* This function encrypts a single block of 16 bytes of data.
* If you want to encrypt a larger or variable-length message,
* you will have to use a cipher mode, such as CBC or CTR.
* These are outside the scope of this implementation.
*
* The xkey structure is not modified by this routine, and can be
* used for further encryption and decryption operations.
*
* @param xkey pointer to Twofish_key, internal form of the key
* produces by Twofish_prepare_key()
* @param p Plaintext to be encrypted
* @param c Place to store the ciphertext
*/
extern void Twofish_encrypt(
Twofish_key * xkey,
Twofish_Byte p[16],
Twofish_Byte c[16]
);
/**
* Decrypt a single block of data.
*
* This function decrypts a single block of 16 bytes of data.
* If you want to decrypt a larger or variable-length message,
* you will have to use a cipher mode, such as CBC or CTR.
* These are outside the scope of this implementation.
*
* The xkey structure is not modified by this routine, and can be
* used for further encryption and decryption operations.
*
* @param xkey pointer to Twofish_key, internal form of the key
* produces by Twofish_prepare_key()
* @param c Ciphertext to be decrypted
* @param p Place to store the plaintext
*/
extern void Twofish_decrypt(
Twofish_key * xkey,
Twofish_Byte c[16],
Twofish_Byte p[16]
);
/**
* Encrypt data in CFB mode.
*
* This function encrypts data in CFB mode.
*
* The key structure is not modified by this routine, and can be
* used for further encryption and decryption operations.
*
* @param keyCtx pointer to Twofish_key, internal form of the key
* produced by Twofish_prepare_key()
* @param in Plaintext to be encrypted
* @param out Place to store the ciphertext
* @param len number of bytes to encrypt.
* @param ivec initialization vector for this CFB mode encryption.
* @param num pointer to integer that holds number of available crypto bytes.
*/
void Twofish_cfb128_encrypt(Twofish_key* keyCtx, Twofish_Byte* in,
Twofish_Byte* out, size_t len,
Twofish_Byte* ivec, int *num);
/**
* Decrypt data in CFB mode.
*
* This function decrypts data in CFB.
*
* The key structure is not modified by this routine, and can be
* used for further encryption and decryption operations.
*
* @param keyCtx pointer to Twofish_key, internal form of the key
* produced by Twofish_prepare_key()
* @param in Ciphertext to be decrypted
* @param out Place to store the plaintext
* @param len number of bytes to decrypt.
* @param ivec initialization vector for this CFB mode encryption.
* @param num pointer to integer that holds number of available crypto bytes.
*/
void Twofish_cfb128_decrypt(Twofish_key* keyCtx, Twofish_Byte* in,
Twofish_Byte* out, size_t len,
Twofish_Byte* ivec, int *num);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif

98
libs/libks/crypt/twofish_cfb.c Executable file
View File

@ -0,0 +1,98 @@
#include <stdint.h>
#include <stdlib.h>
#include "twofish.h"
#ifdef ANDROID
void Two_debugDummy(Twofish_Byte* in, Twofish_Byte* out, Twofish_Byte* ivec);
#endif
void Twofish_cfb128_encrypt(Twofish_key* keyCtx, Twofish_Byte* in,
Twofish_Byte* out, size_t len,
Twofish_Byte* ivec, int32_t *num)
{
uint32_t n;
n = *num;
do {
while (n && len) {
*(out++) = ivec[n] ^= *(in++);
--len;
n = (n+1) % 16;
}
while (len>=16) {
Twofish_encrypt(keyCtx, ivec, ivec);
for (n=0; n<16; n+=sizeof(size_t)) {
/*
* Some GCC version(s) of Android's NDK produce code that leads to a crash (SIGBUS). The
* offending line if the line that produces the output by xor'ing the ivec. Somehow the
* compiler/optimizer seems to incorrectly setup the pointers. Adding a call to an
* external function that uses the pointer disabled or modifies this optimzing
* behaviour. This debug functions as such does nothing, it just disables some
* optimization. Don't use a local (static) function - the compiler sees that it does
* nothing and optimizes again :-) .
*/
#ifdef ANDROID
Two_debugDummy(in, out, ivec);
#endif
*(size_t*)(out+n) = *(size_t*)(ivec+n) ^= *(size_t*)(in+n);;
}
len -= 16;
out += 16;
in += 16;
}
n = 0;
if (len) {
Twofish_encrypt(keyCtx, ivec, ivec);
while (len--) {
out[n] = ivec[n] ^= in[n];
++n;
}
}
*num = n;
return;
} while (0);
}
void Twofish_cfb128_decrypt(Twofish_key* keyCtx, Twofish_Byte* in,
Twofish_Byte* out, size_t len,
Twofish_Byte* ivec, int32_t *num)
{
uint32_t n;
n = *num;
do {
while (n && len) {
unsigned char c;
*(out++) = ivec[n] ^ (c = *(in++)); ivec[n] = c;
--len;
n = (n+1) % 16;
}
while (len>=16) {
Twofish_encrypt(keyCtx, ivec, ivec);
for (n=0; n<16; n+=sizeof(size_t)) {
size_t t = *(size_t*)(in+n);
*(size_t*)(out+n) = *(size_t*)(ivec+n) ^ t;
*(size_t*)(ivec+n) = t;
}
len -= 16;
out += 16;
in += 16;
}
n = 0;
if (len) {
Twofish_encrypt(keyCtx, ivec, ivec);
while (len--) {
unsigned char c;
out[n] = ivec[n] ^ (c = in[n]); ivec[n] = c;
++n;
}
}
*num = n;
return;
} while (0);
}

View File

@ -0,0 +1,407 @@
diff --git a/libs/libks/src/ks_dht.c b/libs/libks/src/ks_dht.c
index 27bafd0..126686e 100644
--- a/libs/libks/src/ks_dht.c
+++ b/libs/libks/src/ks_dht.c
@@ -2438,96 +2438,84 @@ static int dht_send(dht_handle_t *h, const void *buf, size_t len, int flags, con
return sendto(s, buf, len, flags, sa, salen);
}
+/* Sample ping packet '{"t":"aa", "y":"q", "q":"ping", "a":{"id":"abcdefghij0123456789"}}' */
+/* http://www.bittorrent.org/beps/bep_0005.html */
int send_ping(dht_handle_t *h, const struct sockaddr *sa, int salen, const unsigned char *tid, int tid_len)
{
char buf[512];
- int i = 0;//, rc;
- struct bencode *bencode_p = NULL;
- struct bencode *bencode_a_p = NULL;
-
- /* Sets some default values for message, then encodes 20 characters worth of local node id */
- /* also adds the transaction id tid, then a few final key values. */
-
- /* Sample encoded ping 'd1:ad2:id20:Td2????#?)y1:q4:ping1:t4:pn' */
- /* 'd1:ad2:id20:Td2????#?)y1:q4:ping1:t4:pn' */
- /* https://en.wikipedia.org/wiki/Bencode */
- /* Sample ping packet '{"t":"aa", "y":"q", "q":"ping", "a":{"id":"abcdefghij0123456789"}}' */
- /* http://www.bittorrent.org/beps/bep_0005.html */
+ int i = 0;
+ struct bencode *bencode_p = ben_dict();
+ struct bencode *bencode_a_p = ben_dict();
- bencode_a_p = ben_dict(); /* Initialize empty bencode dictionary */
+ ben_dict_set(bencode_p, ben_blob("t", 1), ben_blob(tid, tid_len));
+ ben_dict_set(bencode_p, ben_blob("y", 1), ben_blob("q", 1));
+ ben_dict_set(bencode_p, ben_blob("q", 1), ben_blob("ping", 4));
ben_dict_set(bencode_a_p, ben_blob("id", 2), ben_blob(h->myid, 20));
-
- bencode_p = ben_dict();
ben_dict_set(bencode_p, ben_blob("a", 1), bencode_a_p);
- ben_dict_set(bencode_p, ben_blob("q", 1), ben_blob("ping", 4));
- ben_dict_set(bencode_p, ben_blob("t", 1), ben_blob(tid, tid_len));
- ben_dict_set(bencode_p, ben_blob("y", 1), ben_blob("q", 1));
- /*
- rc = ks_snprintf(buf + i, 512 - i, "d1:ad2:id20:"); INC(i, rc, 512);
- COPY(buf, i, h->myid, 20, 512);
- rc = ks_snprintf(buf + i, 512 - i, "e1:q4:ping1:t%d:", tid_len);
- INC(i, rc, 512);
- COPY(buf, i, tid, tid_len, 512);
- ADD_V(buf, i, 512);
- rc = ks_snprintf(buf + i, 512 - i, "1:y1:qe"); INC(i, rc, 512);
- */
ben_encode2(buf, 512, bencode_p);
ben_free(bencode_p); /* This SHOULD free the bencode_a_p as well */
ks_log(KS_LOG_DEBUG, "Encoded PING: %s\n\n", buf);
return dht_send(h, buf, i, 0, sa, salen);
-
- /*
- // Need to fix, not just disable error handling.
- fail:
- errno = ENOSPC;
- return -1; */
}
+/* Sample pong packet '{"t":"aa", "y":"r", "r": {"id":"mnopqrstuvwxyz123456"}}' */
+/* http://www.bittorrent.org/beps/bep_0005.html */
int send_pong(dht_handle_t *h, const struct sockaddr *sa, int salen, const unsigned char *tid, int tid_len)
{
char buf[512];
- int i = 0, rc;
- rc = ks_snprintf(buf + i, 512 - i, "d1:rd2:id20:"); INC(i, rc, 512);
- COPY(buf, i, h->myid, 20, 512);
- rc = ks_snprintf(buf + i, 512 - i, "e1:t%d:", tid_len); INC(i, rc, 512);
- COPY(buf, i, tid, tid_len, 512);
- ADD_V(buf, i, 512);
- rc = ks_snprintf(buf + i, 512 - i, "1:y1:re"); INC(i, rc, 512);
- return dht_send(h, buf, i, 0, sa, salen);
+ int i = 0;
+ struct bencode *bencode_p = ben_dict();
+ struct bencode *bencode_a_p = ben_dict();
- fail:
- errno = ENOSPC;
- return -1;
+ ben_dict_set(bencode_p, ben_blob("t", 1), ben_blob(tid, tid_len));
+ ben_dict_set(bencode_p, ben_blob("y", 1), ben_blob("r", 1));
+ ben_dict_set(bencode_a_p, ben_blob("id", 2), ben_blob(h->myid, 20));
+ ben_dict_set(bencode_p, ben_blob("r", 1), bencode_a_p);
+
+ ben_encode2(buf, 512, bencode_p);
+ ben_free(bencode_p); /* This SHOULD free the bencode_a_p as well */
+
+ ks_log(KS_LOG_DEBUG, "Encoded PONG: %s\n\n", buf);
+ return dht_send(h, buf, i, 0, sa, salen);
}
+/* Sample find_node packet '{"t":"aa", "y":"q", "q":"find_node", "a": {"id":"abcdefghij0123456789", "target":"mnopqrstuvwxyz123456"}}' */
+/* Sample find_node packet w/ want '{"t":"aa", "y":"q", "q":"find_node", "a": {"id":"abcdefghij0123456789", "target":"mnopqrstuvwxyz123456", "want":"n4"}}' */
+/* http://www.bittorrent.org/beps/bep_0005.html */
+/* http://www.bittorrent.org/beps/bep_0032.html for want parameter */
int send_find_node(dht_handle_t *h, const struct sockaddr *sa, int salen,
const unsigned char *tid, int tid_len,
const unsigned char *target, int want, int confirm)
{
char buf[512];
- int i = 0, rc;
- rc = ks_snprintf(buf + i, 512 - i, "d1:ad2:id20:"); INC(i, rc, 512);
- COPY(buf, i, h->myid, 20, 512);
- rc = ks_snprintf(buf + i, 512 - i, "6:target20:"); INC(i, rc, 512);
- COPY(buf, i, target, 20, 512);
- if (want > 0) {
- rc = ks_snprintf(buf + i, 512 - i, "4:wantl%s%se", (want & WANT4) ? "2:n4" : "", (want & WANT6) ? "2:n6" : "");
- INC(i, rc, 512);
- }
- rc = ks_snprintf(buf + i, 512 - i, "e1:q9:find_node1:t%d:", tid_len);
- INC(i, rc, 512);
- COPY(buf, i, tid, tid_len, 512);
- ADD_V(buf, i, 512);
- rc = ks_snprintf(buf + i, 512 - i, "1:y1:qe"); INC(i, rc, 512);
- return dht_send(h, buf, i, confirm ? MSG_CONFIRM : 0, sa, salen);
+ int i = 0;
+ struct bencode *bencode_p = ben_dict();
+ struct bencode *bencode_a_p = ben_dict();
+ int target_len = target ? strlen((const char*)target) : 0;
- fail:
- errno = ENOSPC;
- return -1;
-}
+ ben_dict_set(bencode_p, ben_blob("t", 1), ben_blob(tid, tid_len));
+ ben_dict_set(bencode_p, ben_blob("y", 1), ben_blob("q", 1));
+ ben_dict_set(bencode_p, ben_blob("q", 1), ben_blob("find_node", 9));
+ ben_dict_set(bencode_a_p, ben_blob("id", 2), ben_blob(h->myid, 20));
+ if (target) ben_dict_set(bencode_a_p, ben_blob("target", 6), ben_blob(target, target_len));
+ if (want > 0) {
+ char *w = NULL;
+ if (want & WANT4) w = "n4";
+ if (want & WANT6) w = "n6";
+ if (w) ben_dict_set(bencode_a_p, ben_blob("want", 4), ben_blob(w, 2));
+ }
+ ben_dict_set(bencode_p, ben_blob("a", 1), bencode_a_p);
+ ben_encode2(buf, 512, bencode_p);
+ ben_free(bencode_p); /* This SHOULD free the bencode_a_p as well */
+
+ ks_log(KS_LOG_DEBUG, "Encoded FIND_NODE: %s\n\n", buf);
+ return dht_send(h, buf, i, confirm ? MSG_CONFIRM : 0, sa, salen);
+}
+/* sample find_node response '{"t":"aa", "y":"r", "r": {"id":"0123456789abcdefghij", "nodes": "def456..."}}'*/
+/* http://www.bittorrent.org/beps/bep_0005.html */
int send_nodes_peers(dht_handle_t *h, const struct sockaddr *sa, int salen,
const unsigned char *tid, int tid_len,
const unsigned char *nodes, int nodes_len,
@@ -2536,30 +2524,28 @@ int send_nodes_peers(dht_handle_t *h, const struct sockaddr *sa, int salen,
const unsigned char *token, int token_len)
{
char buf[2048];
- int i = 0, rc, j0, j, k, len;
+ int i = 0;//, rc, j0, j, k, len;
+ struct bencode *bencode_p = ben_dict();
+ struct bencode *bencode_a_p = ben_dict();
+ struct bencode *ben_array = ben_list();
- rc = ks_snprintf(buf + i, 2048 - i, "d1:rd2:id20:"); INC(i, rc, 2048);
- COPY(buf, i, h->myid, 20, 2048);
- if (nodes_len > 0) {
- rc = ks_snprintf(buf + i, 2048 - i, "5:nodes%d:", nodes_len);
- INC(i, rc, 2048);
- COPY(buf, i, nodes, nodes_len, 2048);
- }
- if (nodes6_len > 0) {
- rc = ks_snprintf(buf + i, 2048 - i, "6:nodes6%d:", nodes6_len);
- INC(i, rc, 2048);
- COPY(buf, i, nodes6, nodes6_len, 2048);
- }
- if (token_len > 0) {
- rc = ks_snprintf(buf + i, 2048 - i, "5:token%d:", token_len);
- INC(i, rc, 2048);
- COPY(buf, i, token, token_len, 2048);
- }
+ ben_dict_set(bencode_p, ben_blob("t", 1), ben_blob(tid, tid_len));
+ ben_dict_set(bencode_p, ben_blob("y", 1), ben_blob("r", 1));
+ ben_dict_set(bencode_a_p, ben_blob("id", 2), ben_blob(h->myid, 20));
+ if (token_len) ben_dict_set(bencode_a_p, ben_blob("token", 5), ben_blob(token, token_len));
+ if (nodes_len) ben_dict_set(bencode_a_p, ben_blob("nodes", 5), ben_blob(token, nodes_len));
+ if (nodes6_len) ben_dict_set(bencode_a_p, ben_blob("nodes6", 6), ben_blob(token, nodes6_len));
+ /* its an array, how do i do this??
+
+Response with peers = {"t":"aa", "y":"r", "r": {"id":"abcdefghij0123456789", "token":"aoeusnth", "values": ["axje.u", "idhtnm"]}}
+ */
+
+ /* TODO XXXXXX find docs and add "values" stuff into this encode
if (st && st->numpeers > 0) {
- /* We treat the storage as a circular list, and serve a randomly
- chosen slice. In order to make sure we fit within 1024 octets,
- we limit ourselves to 50 peers. */
+ // We treat the storage as a circular list, and serve a randomly
+ // chosen slice. In order to make sure we fit within 1024 octets,
+ // we limit ourselves to 50 peers.
len = af == AF_INET ? 4 : 16;
j0 = random() % st->numpeers;
@@ -2582,19 +2568,13 @@ int send_nodes_peers(dht_handle_t *h, const struct sockaddr *sa, int salen,
rc = ks_snprintf(buf + i, 2048 - i, "e");
INC(i, rc, 2048);
}
-
- rc = ks_snprintf(buf + i, 2048 - i, "e1:t%d:", tid_len);
- INC(i, rc, 2048);
- COPY(buf, i, tid, tid_len, 2048);
- ADD_V(buf, i, 2048);
- rc = ks_snprintf(buf + i, 2048 - i, "1:y1:re");
- INC(i, rc, 2048);
-
- return dht_send(h, buf, i, 0, sa, salen);
-
- fail:
- errno = ENOSPC;
- return -1;
+*/
+ ben_dict_set(bencode_p, ben_blob("r", 1), bencode_a_p);
+ ben_encode2(buf, 512, bencode_p);
+ ben_free(bencode_p); /* This SHOULD free the bencode_a_p as well */
+
+ ks_log(KS_LOG_DEBUG, "Encoded FIND_NODE: %s\n\n", buf);
+ return dht_send(h, buf, i, 0, sa, salen);
}
static int insert_closest_node(unsigned char *nodes, int numnodes,
@@ -2706,104 +2686,107 @@ int send_closest_nodes(dht_handle_t *h, const struct sockaddr *sa, int salen,
af, st, token, token_len);
}
+/* sample get_peers request '{"t":"aa", "y":"q", "q":"get_peers", "a": {"id":"abcdefghij0123456789", "info_hash":"mnopqrstuvwxyz123456"}}'*/
+/* sample get_peers w/ want '{"t":"aa", "y":"q", "q":"get_peers", "a": {"id":"abcdefghij0123456789", "info_hash":"mnopqrstuvwxyz123456": "want":"n4"}}'*/
+/* http://www.bittorrent.org/beps/bep_0005.html */
+/* http://www.bittorrent.org/beps/bep_0032.html for want parameter */
int send_get_peers(dht_handle_t *h, const struct sockaddr *sa, int salen,
unsigned char *tid, int tid_len, unsigned char *infohash,
int want, int confirm)
{
char buf[512];
- int i = 0, rc;
-
- rc = ks_snprintf(buf + i, 512 - i, "d1:ad2:id20:"); INC(i, rc, 512);
- COPY(buf, i, h->myid, 20, 512);
- rc = ks_snprintf(buf + i, 512 - i, "9:info_hash20:"); INC(i, rc, 512);
- COPY(buf, i, infohash, 20, 512);
- if (want > 0) {
- rc = ks_snprintf(buf + i, 512 - i, "4:wantl%s%se", (want & WANT4) ? "2:n4" : "", (want & WANT6) ? "2:n6" : "");
- INC(i, rc, 512);
- }
- rc = ks_snprintf(buf + i, 512 - i, "e1:q9:get_peers1:t%d:", tid_len);
- INC(i, rc, 512);
- COPY(buf, i, tid, tid_len, 512);
- ADD_V(buf, i, 512);
- rc = ks_snprintf(buf + i, 512 - i, "1:y1:qe"); INC(i, rc, 512);
- return dht_send(h, buf, i, confirm ? MSG_CONFIRM : 0, sa, salen);
+ int i = 0;
+ struct bencode *bencode_p = ben_dict();
+ struct bencode *bencode_a_p = ben_dict();
+ int infohash_len = infohash ? strlen((const char*)infohash) : 0;
- fail:
- errno = ENOSPC;
- return -1;
-}
+ ben_dict_set(bencode_p, ben_blob("t", 1), ben_blob(tid, tid_len));
+ ben_dict_set(bencode_p, ben_blob("y", 1), ben_blob("q", 1));
+ ben_dict_set(bencode_p, ben_blob("q", 1), ben_blob("get_peers", 9));
+ ben_dict_set(bencode_a_p, ben_blob("id", 2), ben_blob(h->myid, 20));
+ if (want > 0) {
+ char *w = NULL;
+ if (want & WANT4) w = "n4";
+ if (want & WANT6) w = "n6";
+ if (w) ben_dict_set(bencode_a_p, ben_blob("want", 4), ben_blob(w, 2));
+ }
+ ben_dict_set(bencode_a_p, ben_blob("info_hash", 9), ben_blob(infohash, infohash_len));
+ ben_dict_set(bencode_p, ben_blob("a", 1), bencode_a_p);
+ ben_encode2(buf, 512, bencode_p);
+ ben_free(bencode_p); /* This SHOULD free the bencode_a_p as well */
+
+ ks_log(KS_LOG_DEBUG, "Encoded GET_PEERS: %s\n\n", buf);
+ return dht_send(h, buf, i, confirm ? MSG_CONFIRM : 0, sa, salen);
+}
+/* '{"t":"aa", "y":"q", "q":"announce_peer", "a": {"id":"abcdefghij0123456789", "implied_port": 1, "info_hash":"mnopqrstuvwxyz123456", "port": 6881, "token": "aoeusnth"}}'*/
int send_announce_peer(dht_handle_t *h, const struct sockaddr *sa, int salen,
unsigned char *tid, int tid_len,
unsigned char *infohash, unsigned short port,
unsigned char *token, int token_len, int confirm)
{
char buf[512];
- int i = 0, rc;
-
- rc = ks_snprintf(buf + i, 512 - i, "d1:ad2:id20:"); INC(i, rc, 512);
- COPY(buf, i, h->myid, 20, 512);
- rc = ks_snprintf(buf + i, 512 - i, "9:info_hash20:"); INC(i, rc, 512);
- COPY(buf, i, infohash, 20, 512);
- rc = ks_snprintf(buf + i, 512 - i, "4:porti%ue5:token%d:", (unsigned)port, token_len);
- INC(i, rc, 512);
- COPY(buf, i, token, token_len, 512);
- rc = ks_snprintf(buf + i, 512 - i, "e1:q13:announce_peer1:t%d:", tid_len);
- INC(i, rc, 512);
- COPY(buf, i, tid, tid_len, 512);
- ADD_V(buf, i, 512);
- rc = ks_snprintf(buf + i, 512 - i, "1:y1:qe"); INC(i, rc, 512);
+ int i = 0;
+ struct bencode *bencode_p = ben_dict();
+ struct bencode *bencode_a_p = ben_dict();
+ int infohash_len = infohash ? strlen((const char*)infohash) : 0;
- return dht_send(h, buf, i, confirm ? MSG_CONFIRM : 0, sa, salen);
+ ben_dict_set(bencode_p, ben_blob("t", 1), ben_blob(tid, tid_len));
+ ben_dict_set(bencode_p, ben_blob("y", 1), ben_blob("q", 1));
+ ben_dict_set(bencode_p, ben_blob("q", 1), ben_blob("announce_peer", 13));
+ ben_dict_set(bencode_a_p, ben_blob("id", 2), ben_blob(h->myid, 20));
+ ben_dict_set(bencode_a_p, ben_blob("info_hash", 9), ben_blob(infohash, infohash_len));
+ ben_dict_set(bencode_a_p, ben_blob("port", 5), ben_int(port));
+ ben_dict_set(bencode_a_p, ben_blob("token", 5), ben_blob(token, token_len));
+ ben_dict_set(bencode_p, ben_blob("a", 1), bencode_a_p);
- fail:
- errno = ENOSPC;
- return -1;
+ ben_encode2(buf, 512, bencode_p);
+ ben_free(bencode_p); /* This SHOULD free the bencode_a_p as well */
+
+ ks_log(KS_LOG_DEBUG, "Encoded ANNOUNCE_PEERS: %s\n\n", buf);
+ return dht_send(h, buf, i, confirm ? MSG_CONFIRM : 0, sa, salen);
}
-
+/* '{"t":"aa", "y":"r", "r": {"id":"mnopqrstuvwxyz123456"}}'*/
static int send_peer_announced(dht_handle_t *h, const struct sockaddr *sa, int salen, unsigned char *tid, int tid_len)
{
char buf[512];
- int i = 0, rc;
-
- rc = ks_snprintf(buf + i, 512 - i, "d1:rd2:id20:");
- INC(i, rc, 512);
- COPY(buf, i, h->myid, 20, 512);
- rc = ks_snprintf(buf + i, 512 - i, "e1:t%d:", tid_len);
- INC(i, rc, 512);
- COPY(buf, i, tid, tid_len, 512);
- ADD_V(buf, i, 512);
- rc = ks_snprintf(buf + i, 512 - i, "1:y1:re");
- INC(i, rc, 512);
- return dht_send(h, buf, i, 0, sa, salen);
+ int i = 0;
+ struct bencode *bencode_p = ben_dict();
+ struct bencode *bencode_a_p = ben_dict();
- fail:
- errno = ENOSPC;
- return -1;
+ ben_dict_set(bencode_p, ben_blob("t", 1), ben_blob(tid, tid_len));
+ ben_dict_set(bencode_p, ben_blob("y", 1), ben_blob("r", 1));
+ ben_dict_set(bencode_a_p, ben_blob("id", 2), ben_blob(h->myid, 20));
+ ben_dict_set(bencode_p, ben_blob("r", 1), bencode_a_p);
+
+ ben_encode2(buf, 512, bencode_p);
+ ben_free(bencode_p); /* This SHOULD free the bencode_a_p as well */
+
+ ks_log(KS_LOG_DEBUG, "Encoded peer_announced: %s\n\n", buf);
+ return dht_send(h, buf, i, 0, sa, salen);
}
+/* '{"t":"aa", "y":"e", "e":[201, "A Generic Error Ocurred"]}'*/
static int send_error(dht_handle_t *h, const struct sockaddr *sa, int salen,
unsigned char *tid, int tid_len,
int code, const char *message)
{
char buf[512];
- int i = 0, rc, message_len;
-
- message_len = strlen(message);
- rc = ks_snprintf(buf + i, 512 - i, "d1:eli%de%d:", code, message_len);
- INC(i, rc, 512);
- COPY(buf, i, message, message_len, 512);
- rc = ks_snprintf(buf + i, 512 - i, "e1:t%d:", tid_len);
- INC(i, rc, 512);
- COPY(buf, i, tid, tid_len, 512);
- ADD_V(buf, i, 512);
- rc = ks_snprintf(buf + i, 512 - i, "1:y1:ee");
- INC(i, rc, 512);
- return dht_send(h, buf, i, 0, sa, salen);
+ int i = 0;
+ struct bencode *bencode_p = ben_dict();
+ struct bencode *ben_array = ben_list();
- fail:
- errno = ENOSPC;
- return -1;
+ ben_dict_set(bencode_p, ben_blob("t", 1), ben_blob(tid, tid_len));
+ ben_dict_set(bencode_p, ben_blob("y", 1), ben_blob("e", 1));
+ ben_list_append(ben_array, ben_int(code));
+ ben_list_append(ben_array, ben_blob(message, strlen(message)));
+ ben_dict_set(bencode_p, ben_blob("e", 1), ben_array);
+
+ ben_encode2(buf, 512, bencode_p);
+ ben_free(bencode_p);
+
+ ks_log(KS_LOG_DEBUG, "Encoded error: %s\n\n", buf);
+ return dht_send(h, buf, i, 0, sa, salen);
}
#undef CHECK

11
libs/libks/libks.pc.in Normal file
View File

@ -0,0 +1,11 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: @PACKAGE_NAME@
Version: @PACKAGE_VERSION@
Description: A cross platform kitchen sink library.
Cflags: -I${includedir}
Libs: -L${libdir} -lks

View File

@ -5,9 +5,9 @@
<PropertyGroup />
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>SIMCLIST_NO_DUMPRESTORE;_CRT_SECURE_NO_WARNINGS;KS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>UNICODE;SIMCLIST_NO_DUMPRESTORE;_CRT_SECURE_NO_WARNINGS;KS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(ProjectDir)\src\include;$(ProjectDir)\src\win\sys;$(ProjectDir)\src\win;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4574;4100;4127;4668;4255;4706;4710;4820</DisableSpecificWarnings>
<DisableSpecificWarnings>4711;4574;4100;4127;4668;4255;4706;4710;4820</DisableSpecificWarnings>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup />

View File

@ -5,10 +5,17 @@ VisualStudioVersion = 14.0.23107.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libks", "libks.vcxproj", "{70D178D8-1100-4152-86C0-809A91CFF832}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testpools", "test\testpools\testpools.vcxproj", "{766F7FF4-CF39-4CDF-ABDC-4E9C88568F1F}"
ProjectSection(ProjectDependencies) = postProject
{70D178D8-1100-4152-86C0-809A91CFF832} = {70D178D8-1100-4152-86C0-809A91CFF832}
EndProjectSection
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testpools", "test\testpools.vcxproj", "{5825A3B2-31A0-475A-AF32-44FB0D8B52D4}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testthreadmutex", "test\testthreadmutex.vcxproj", "{AE572500-7266-4692-ACA4-5E37B7B4409A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testhash", "test\testhash.vcxproj", "{43724CF4-FCE1-44FE-AB36-C86E3979B350}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testq", "test\testq.vcxproj", "{3F8E0DF3-F402-40E0-8D78-44A094625D25}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testsock", "test\testsock.vcxproj", "{5DC38E2B-0512-4140-8A1B-59952A5DC9CB}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testtime", "test\testtime.vcxproj", "{B74812A1-C67D-4568-AF84-26CE2004D8BF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -26,14 +33,54 @@ Global
{70D178D8-1100-4152-86C0-809A91CFF832}.Release|x64.Build.0 = Release|x64
{70D178D8-1100-4152-86C0-809A91CFF832}.Release|x86.ActiveCfg = Release|Win32
{70D178D8-1100-4152-86C0-809A91CFF832}.Release|x86.Build.0 = Release|Win32
{766F7FF4-CF39-4CDF-ABDC-4E9C88568F1F}.Debug|x64.ActiveCfg = Debug|x64
{766F7FF4-CF39-4CDF-ABDC-4E9C88568F1F}.Debug|x64.Build.0 = Debug|x64
{766F7FF4-CF39-4CDF-ABDC-4E9C88568F1F}.Debug|x86.ActiveCfg = Debug|Win32
{766F7FF4-CF39-4CDF-ABDC-4E9C88568F1F}.Debug|x86.Build.0 = Debug|Win32
{766F7FF4-CF39-4CDF-ABDC-4E9C88568F1F}.Release|x64.ActiveCfg = Release|x64
{766F7FF4-CF39-4CDF-ABDC-4E9C88568F1F}.Release|x64.Build.0 = Release|x64
{766F7FF4-CF39-4CDF-ABDC-4E9C88568F1F}.Release|x86.ActiveCfg = Release|Win32
{766F7FF4-CF39-4CDF-ABDC-4E9C88568F1F}.Release|x86.Build.0 = Release|Win32
{5825A3B2-31A0-475A-AF32-44FB0D8B52D4}.Debug|x64.ActiveCfg = Debug|x64
{5825A3B2-31A0-475A-AF32-44FB0D8B52D4}.Debug|x64.Build.0 = Debug|x64
{5825A3B2-31A0-475A-AF32-44FB0D8B52D4}.Debug|x86.ActiveCfg = Debug|Win32
{5825A3B2-31A0-475A-AF32-44FB0D8B52D4}.Debug|x86.Build.0 = Debug|Win32
{5825A3B2-31A0-475A-AF32-44FB0D8B52D4}.Release|x64.ActiveCfg = Release|x64
{5825A3B2-31A0-475A-AF32-44FB0D8B52D4}.Release|x64.Build.0 = Release|x64
{5825A3B2-31A0-475A-AF32-44FB0D8B52D4}.Release|x86.ActiveCfg = Release|Win32
{5825A3B2-31A0-475A-AF32-44FB0D8B52D4}.Release|x86.Build.0 = Release|Win32
{AE572500-7266-4692-ACA4-5E37B7B4409A}.Debug|x64.ActiveCfg = Debug|x64
{AE572500-7266-4692-ACA4-5E37B7B4409A}.Debug|x64.Build.0 = Debug|x64
{AE572500-7266-4692-ACA4-5E37B7B4409A}.Debug|x86.ActiveCfg = Debug|Win32
{AE572500-7266-4692-ACA4-5E37B7B4409A}.Debug|x86.Build.0 = Debug|Win32
{AE572500-7266-4692-ACA4-5E37B7B4409A}.Release|x64.ActiveCfg = Release|x64
{AE572500-7266-4692-ACA4-5E37B7B4409A}.Release|x64.Build.0 = Release|x64
{AE572500-7266-4692-ACA4-5E37B7B4409A}.Release|x86.ActiveCfg = Release|Win32
{AE572500-7266-4692-ACA4-5E37B7B4409A}.Release|x86.Build.0 = Release|Win32
{43724CF4-FCE1-44FE-AB36-C86E3979B350}.Debug|x64.ActiveCfg = Debug|x64
{43724CF4-FCE1-44FE-AB36-C86E3979B350}.Debug|x64.Build.0 = Debug|x64
{43724CF4-FCE1-44FE-AB36-C86E3979B350}.Debug|x86.ActiveCfg = Debug|Win32
{43724CF4-FCE1-44FE-AB36-C86E3979B350}.Debug|x86.Build.0 = Debug|Win32
{43724CF4-FCE1-44FE-AB36-C86E3979B350}.Release|x64.ActiveCfg = Release|x64
{43724CF4-FCE1-44FE-AB36-C86E3979B350}.Release|x64.Build.0 = Release|x64
{43724CF4-FCE1-44FE-AB36-C86E3979B350}.Release|x86.ActiveCfg = Release|Win32
{43724CF4-FCE1-44FE-AB36-C86E3979B350}.Release|x86.Build.0 = Release|Win32
{3F8E0DF3-F402-40E0-8D78-44A094625D25}.Debug|x64.ActiveCfg = Debug|x64
{3F8E0DF3-F402-40E0-8D78-44A094625D25}.Debug|x64.Build.0 = Debug|x64
{3F8E0DF3-F402-40E0-8D78-44A094625D25}.Debug|x86.ActiveCfg = Debug|Win32
{3F8E0DF3-F402-40E0-8D78-44A094625D25}.Debug|x86.Build.0 = Debug|Win32
{3F8E0DF3-F402-40E0-8D78-44A094625D25}.Release|x64.ActiveCfg = Release|x64
{3F8E0DF3-F402-40E0-8D78-44A094625D25}.Release|x64.Build.0 = Release|x64
{3F8E0DF3-F402-40E0-8D78-44A094625D25}.Release|x86.ActiveCfg = Release|Win32
{3F8E0DF3-F402-40E0-8D78-44A094625D25}.Release|x86.Build.0 = Release|Win32
{5DC38E2B-0512-4140-8A1B-59952A5DC9CB}.Debug|x64.ActiveCfg = Debug|x64
{5DC38E2B-0512-4140-8A1B-59952A5DC9CB}.Debug|x64.Build.0 = Debug|x64
{5DC38E2B-0512-4140-8A1B-59952A5DC9CB}.Debug|x86.ActiveCfg = Debug|Win32
{5DC38E2B-0512-4140-8A1B-59952A5DC9CB}.Debug|x86.Build.0 = Debug|Win32
{5DC38E2B-0512-4140-8A1B-59952A5DC9CB}.Release|x64.ActiveCfg = Release|x64
{5DC38E2B-0512-4140-8A1B-59952A5DC9CB}.Release|x64.Build.0 = Release|x64
{5DC38E2B-0512-4140-8A1B-59952A5DC9CB}.Release|x86.ActiveCfg = Release|Win32
{5DC38E2B-0512-4140-8A1B-59952A5DC9CB}.Release|x86.Build.0 = Release|Win32
{B74812A1-C67D-4568-AF84-26CE2004D8BF}.Debug|x64.ActiveCfg = Debug|x64
{B74812A1-C67D-4568-AF84-26CE2004D8BF}.Debug|x64.Build.0 = Debug|x64
{B74812A1-C67D-4568-AF84-26CE2004D8BF}.Debug|x86.ActiveCfg = Debug|Win32
{B74812A1-C67D-4568-AF84-26CE2004D8BF}.Debug|x86.Build.0 = Debug|Win32
{B74812A1-C67D-4568-AF84-26CE2004D8BF}.Release|x64.ActiveCfg = Release|x64
{B74812A1-C67D-4568-AF84-26CE2004D8BF}.Release|x64.Build.0 = Release|x64
{B74812A1-C67D-4568-AF84-26CE2004D8BF}.Release|x86.ActiveCfg = Release|Win32
{B74812A1-C67D-4568-AF84-26CE2004D8BF}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -27,22 +27,26 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@ -72,7 +76,8 @@
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>true</LinkIncremental>
<LinkIncremental>
</LinkIncremental>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
@ -84,6 +89,8 @@
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<FunctionLevelLinking>true</FunctionLevelLinking>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
@ -98,6 +105,8 @@
<WarningLevel>EnableAllWarnings</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<FunctionLevelLinking>true</FunctionLevelLinking>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
@ -111,31 +120,49 @@
<ClCompile>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBKS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<WarningLevel>EnableAllWarnings</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>Debug</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBKS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>EnableAllWarnings</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src\ks.c" />
<ClCompile Include="src\ks_buffer.c" />
<ClCompile Include="src\ks_config.c" />
<ClCompile Include="src\ks_dso.c" />
<ClCompile Include="src\ks_hash.c" />
<ClCompile Include="src\ks_json.c" />
<ClCompile Include="src\ks_threadmutex.c" />
<ClCompile Include="src\mpool.c" />
<ClCompile Include="src\ks_log.c" />
<ClCompile Include="src\ks_pool.c" />
<ClCompile Include="src\ks_printf.c" />
<ClCompile Include="src\ks_q.c" />
<ClCompile Include="src\ks_rng.c" />
<ClCompile Include="src\ks_socket.c" />
<ClCompile Include="src\ks_string.c" />
<ClCompile Include="src\ks_thread.c" />
<ClCompile Include="src\ks_mutex.c" />
<ClCompile Include="src\ks_time.c" />
<ClCompile Include="src\simclist.c" />
<ClCompile Include="src\table.c" />
<ClCompile Include="src\table_util.c" />
<ClCompile Include="src\win\mman.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\include\cc.h" />
<ClInclude Include="src\include\ks.h" />
<ClInclude Include="src\include\ks_buffer.h" />
<ClInclude Include="src\include\ks_config.h" />
@ -143,14 +170,12 @@
<ClInclude Include="src\include\ks_platform.h" />
<ClInclude Include="src\include\ks_threadmutex.h" />
<ClInclude Include="src\include\ks_types.h" />
<ClInclude Include="src\include\mpool.h" />
<ClInclude Include="src\include\mpool_loc.h" />
<ClInclude Include="src\include\ks_pool.h" />
<ClInclude Include="src\include\ks_rng.h" />
<ClInclude Include="src\include\simclist.h" />
<ClInclude Include="src\include\table.h" />
<ClInclude Include="src\include\table_loc.h" />
<ClInclude Include="src\win\mman.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -18,6 +18,12 @@
<ClCompile Include="src\ks.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\ks_string.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\ks_socket.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\ks_buffer.c">
<Filter>Source Files</Filter>
</ClCompile>
@ -27,29 +33,44 @@
<ClCompile Include="src\ks_json.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\ks_threadmutex.c">
<ClCompile Include="src\ks_log.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\mpool.c">
<ClCompile Include="src\ks_mutex.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\simclist.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\table.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\table_util.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\win\mman.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\ks_pool.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\ks_rng.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\ks_thread.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\ks_dso.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\ks_hash.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\ks_printf.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\ks_q.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\ks_time.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\include\cc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\include\ks.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -65,10 +86,10 @@
<ClInclude Include="src\include\ks_threadmutex.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\include\mpool.h">
<ClInclude Include="src\include\ks_pool.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\include\mpool_loc.h">
<ClInclude Include="src\include\ks_rng.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\include\simclist.h">
@ -90,4 +111,4 @@
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
</Project>

2683
libs/libks/src/bencode.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -34,44 +34,54 @@
#ifndef _KS_H_
#define _KS_H_
#include <stdarg.h>
#ifdef __cplusplus
#define KS_BEGIN_EXTERN_C extern "C" {
#define KS_END_EXTERN_C }
#else
#define KS_BEGIN_EXTERN_C
#define KS_END_EXTERN_C
#endif
#include <ks_platform.h>
#include <ks_types.h>
#ifdef __cplusplus
extern "C" {
#endif /* defined(__cplusplus) */
#define ks_copy_string(_x, _y, _z) strncpy(_x, _y, _z - 1)
#define ks_set_string(_x, _y) ks_copy_string(_x, _y, sizeof(_x))
#if (_MSC_VER >= 1400) // VC8+
#define ks_assert(expr) assert(expr);__analysis_assume( expr )
#endif
#ifndef ks_assert
#define ks_assert(_x) assert(_x)
#endif
#define ks_safe_free(_x) if (_x) free(_x); _x = NULL
#define ks_strlen_zero(s) (!s || *(s) == '\0')
#define ks_strlen_zero_buf(s) (*(s) == '\0')
#define end_of(_s) *(*_s == '\0' ? _s : _s + strlen(_s) - 1)
#include "math.h"
#include "ks_json.h"
KS_BEGIN_EXTERN_C
#define BUF_CHUNK 65536 * 50
#define BUF_START 65536 * 100
#include <ks_threadmutex.h>
#include <ks_buffer.h>
/*!
\brief Test for NULL or zero length string
\param s the string to test
\return true value if the string is NULL or zero length
*/
_Check_return_ static __inline int _zstr(_In_opt_z_ const char *s)
{
return !s || *s == '\0';
}
#ifdef _PREFAST_
#define zstr(x) (_zstr(x) ? 1 : __analysis_assume(x),0)
#else
#define zstr(x) _zstr(x)
#endif
#define ks_strlen_zero(x) zstr(x)
#define ks_strlen_zero_buf(x) zstr_buf(x)
#define zstr_buf(s) (*(s) == '\0')
#define ks_set_string(_x, _y) ks_copy_string(_x, _y, sizeof(_x))
#define ks_safe_free(_x) if (_x) free(_x); _x = NULL
#define end_of(_s) *(*_s == '\0' ? _s : _s + strlen(_s) - 1)
#define ks_test_flag(obj, flag) ((obj)->flags & flag)
#define ks_set_flag(obj, flag) (obj)->flags |= (flag)
#define ks_clear_flag(obj, flag) (obj)->flags &= ~(flag)
#define ks_recv(_h) ks_recv_event(_h, 0, NULL)
#define ks_recv_timed(_h, _ms) ks_recv_event_timed(_h, _ms, 0, NULL)
KS_DECLARE(ks_status_t) ks_init(void);
KS_DECLARE(ks_status_t) ks_shutdown(void);
KS_DECLARE(ks_pool_t *) ks_global_pool(void);
KS_DECLARE(ks_status_t) ks_global_set_cleanup(ks_pool_cleanup_fn_t fn, void *arg);
KS_DECLARE(int) ks_vasprintf(char **ret, const char *fmt, va_list ap);
KS_DECLARE_DATA extern ks_logger_t ks_log;
@ -81,42 +91,46 @@ KS_DECLARE(void) ks_global_set_logger(ks_logger_t logger);
/*! Sets the default log level for libks */
KS_DECLARE(void) ks_global_set_default_logger(int level);
#include "ks_threadmutex.h"
#include "ks_config.h"
#include "ks_buffer.h"
#include "mpool.h"
#include "simclist.h"
#include "table.h"
KS_DECLARE(size_t) ks_url_encode(const char *url, char *buf, size_t len);
KS_DECLARE(char *)ks_url_decode(char *s);
KS_DECLARE(const char *)ks_stristr(const char *instr, const char *str);
KS_DECLARE(char *) ks_url_decode(char *s);
KS_DECLARE(const char *) ks_stristr(const char *instr, const char *str);
KS_DECLARE(int) ks_toupper(int c);
KS_DECLARE(int) ks_tolower(int c);
KS_DECLARE(char *) ks_copy_string(char *from_str, const char *to_str, ks_size_t from_str_len);
KS_DECLARE(int) ks_snprintf(char *buffer, size_t count, const char *fmt, ...);
KS_DECLARE(unsigned int) ks_separate_string(char *buf, const char *delim, char **array, unsigned int arraylen);
KS_DECLARE(int) ks_cpu_count(void);
static __inline__ int ks_safe_strcasecmp(const char *s1, const char *s2) {
if (!(s1 && s2)) {
return 1;
}
KS_DECLARE(int) ks_wait_sock(ks_socket_t sock, uint32_t ms, ks_poll_t flags);
KS_DECLARE(unsigned int) ks_separate_string_string(char *buf, const char *delim, char **array, unsigned int arraylen);
#define ks_recv(_h) ks_recv_event(_h, 0, NULL)
#define ks_recv_timed(_h, _ms) ks_recv_event_timed(_h, _ms, 0, NULL)
static __inline__ int ks_safe_strcasecmp(const char *s1, const char *s2)
{
if (!(s1 && s2)) {
return 1;
return strcasecmp(s1, s2);
}
return strcasecmp(s1, s2);
}
#ifdef __cplusplus
}
#endif /* defined(__cplusplus) */
KS_DECLARE(void) ks_random_string(char *buf, uint16_t len, char *set);
#include "ks_pool.h"
#include "ks_printf.h"
#include "ks_json.h"
#include "ks_threadmutex.h"
#include "ks_hash.h"
#include "ks_config.h"
#include "ks_q.h"
#include "ks_buffer.h"
#include "ks_time.h"
#include "ks_socket.h"
#include "ks_dso.h"
#include "ks_dht.h"
#include "ks_utp.h"
#include "simclist.h"
#include "ks_ssl.h"
#include "kws.h"
#include "ks_bencode.h"
#include "ks_rng.h"
KS_END_EXTERN_C
#endif /* defined(_KS_H_) */

View File

@ -0,0 +1,730 @@
/*
* libbencodetools
*
* Written by Heikki Orsila <heikki.orsila@iki.fi> and
* Janne Kulmala <janne.t.kulmala@tut.fi> in 2011.
*/
#ifndef TYPEVALIDATOR_BENCODE_H
#define TYPEVALIDATOR_BENCODE_H
#include <stdlib.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Used to verify format strings in compile time */
#ifdef __GNUC__
#define BEN_CHECK_FORMAT(...) __attribute__ ((format( __VA_ARGS__ )))
#else
#define BEN_CHECK_FORMAT(args)
#endif
enum {
BENCODE_BOOL = 1,
BENCODE_DICT,
BENCODE_INT,
BENCODE_LIST,
BENCODE_STR,
BENCODE_USER,
};
enum {
BEN_OK = 0, /* No errors. Set to zero. Non-zero implies an error. */
BEN_INVALID, /* Invalid data was given to decoder */
BEN_INSUFFICIENT, /* Insufficient amount of data for decoding */
BEN_NO_MEMORY, /* Memory allocation failed */
BEN_MISMATCH, /* A given structure did not match unpack format */
};
struct bencode {
char type;
};
struct bencode_bool {
char type;
char b;
};
struct bencode_dict_node {
long long hash;
struct bencode *key;
struct bencode *value;
size_t next;
};
struct bencode_dict {
char type;
char shared; /* non-zero means that the internal data is shared with
other instances and should not be freed */
size_t n;
size_t alloc;
size_t *buckets;
struct bencode_dict_node *nodes;
};
struct bencode_int {
char type;
long long ll;
};
struct bencode_list {
char type;
char shared; /* non-zero means that the internal data is shared with
other instances and should not be freed */
size_t n;
size_t alloc;
struct bencode **values;
};
struct bencode_str {
char type;
size_t len;
char *s;
};
struct ben_decode_ctx;
struct ben_encode_ctx;
struct bencode_type {
size_t size;
struct bencode *(*decode) (struct ben_decode_ctx *ctx);
int (*encode) (struct ben_encode_ctx *ctx, const struct bencode *b);
size_t (*get_size) (const struct bencode *b);
void (*free) (struct bencode *b);
int (*cmp) (const struct bencode *a, const struct bencode *b);
};
struct bencode_user {
char type;
struct bencode_type *info;
};
struct bencode_error {
int error; /* 0 if no errors */
int line; /* Error line: 0 is the first line */
size_t off; /* Error offset in bytes from the start */
};
/* Allocate an instance of a user-defined type */
void *ben_alloc_user(struct bencode_type *type);
/*
* Try to set capacity of a list or a dict to 'n' objects.
* The function does nothing if 'n' is less than or equal to the number of
* objects in 'b'. That is, nothing happens if n <= ben_{dict|list}_len(b).
*
* This function is used only for advice. The implementation need not obey it.
*
* The function returns 0 if the new capacity is used, otherwise -1.
*
* Note: This can be used to make construction of lists and dicts
* more efficient when the number of inserted items is known in advance.
*/
int ben_allocate(struct bencode *b, size_t n);
/*
* Returns an identical but a separate copy of structure b. Returns NULL if
* there is no memory to make a copy. The copy is made recursively.
*/
struct bencode *ben_clone(const struct bencode *b);
/*
* Returns a weak reference copy of structure b. Only a minimum amount of
* data is copied because the returned structure references to the same
* internal data as the original structure. As a result, the original
* structure must remain valid until the copy is destroyed.
*
* This function is used for optimization for special cases.
*/
struct bencode *ben_shared_clone(const struct bencode *b);
/*
* ben_cmp() is similar to strcmp(). It compares integers, strings and lists
* similar to Python. User-defined types can be also compared.
* Note: an integer is always less than a string.
*
* ben_cmp(a, b) returns a negative value if "a < b", 0 if "a == b",
* or a positive value if "a > b".
*
* Algorithm for comparing dictionaries is:
* If 'a' and 'b' have different number of keys or keys have different values,
* a non-zero value is returned. Otherwise, they have the exact same keys
* and comparison is done in ben_cmp() order of keys. The value for each key
* is compared, and the first inequal value (ben_cmp() != 0) defines the
* return value of the comparison.
*
* Note: recursive dictionaries in depth have the same issues.
*/
int ben_cmp(const struct bencode *a, const struct bencode *b);
/* Same as ben_cmp(), but the second argument is a C string */
int ben_cmp_with_str(const struct bencode *a, const char *s);
/*
* Comparison function suitable for qsort(). Uses ben_cmp(), so this can be
* used to order both integer and string arrays.
*/
int ben_cmp_qsort(const void *a, const void *b);
/*
* Decode 'data' with 'len' bytes of data. Returns NULL on error.
* The encoded data must be exactly 'len' bytes (not less), otherwise NULL
* is returned. ben_decode2() function supports partial decoding ('len' is
* larger than actual decoded message) and gives more accurate error reports.
*/
struct bencode *ben_decode(const void *data, size_t len);
/*
* Same as ben_decode(), but allows one to set start offset for decoding with
* 'off' and reports errors more accurately.
*
* '*off' must point to decoding start offset inside 'data'.
* If decoding is successful, '*off' is updated to point to the next byte
* after the decoded message.
*
* If 'error != NULL', it is updated according to the success and error of
* the decoding. BEN_OK is success, BEN_INVALID means invalid data.
* BEN_INSUFFICIENT means data is invalid but could be valid if more data
* was given for decoding. BEN_NO_MEMORY means decoding ran out of memory.
*/
struct bencode *ben_decode2(const void *data, size_t len, size_t *off, int *error);
/*
* Same as ben_decode2(), but allows one to define user types.
*/
struct bencode *ben_decode3(const void *data, size_t len, size_t *off, int *error, struct bencode_type *types[128]);
/*
* Same as ben_decode(), but decodes data encoded with ben_print(). This is
* whitespace tolerant, so intended Python syntax can also be read.
* The decoder skips comments that begin with a '#' character.
* The comment starts from '#' character and ends at the end of the same line.
*
* For example, this can be used to read in config files written as a Python
* dictionary.
*
* ben_decode_printed2() fills information about the error in
* struct bencode_error.
* error->error is 0 on success, otherwise it is an error code
* (see ben_decode2()).
* error->line is the line number where error occured.
* error->off is the byte offset of error (approximation).
*/
struct bencode *ben_decode_printed(const void *data, size_t len);
struct bencode *ben_decode_printed2(const void *data, size_t len, size_t *off, struct bencode_error *error);
/* Get the serialization size of bencode structure 'b' */
size_t ben_encoded_size(const struct bencode *b);
/* encode 'b'. Return encoded data with a pointer, and length in '*len' */
void *ben_encode(size_t *len, const struct bencode *b);
/*
* encode 'b' into 'data' buffer with at most 'maxlen' bytes.
* Returns the size of encoded data.
*/
size_t ben_encode2(char *data, size_t maxlen, const struct bencode *b);
/*
* You must use ben_free() for all allocated bencode structures after use.
* If b == NULL, ben_free does nothing.
*
* ben_free() frees all the objects contained within the bencoded structure.
* It recursively iterates over lists and dictionaries and frees objects.
*/
void ben_free(struct bencode *b);
long long ben_str_hash(const struct bencode *b);
long long ben_int_hash(const struct bencode *b);
long long ben_hash(const struct bencode *b);
/* Create a string from binary data with len bytes */
struct bencode *ben_blob(const void *data, size_t len);
/* Create a boolean from integer */
struct bencode *ben_bool(int b);
/* Create an empty dictionary */
struct bencode *ben_dict(void);
/*
* Try to locate 'key' in dictionary. Returns the associated value, if found.
* Returns NULL if the key does not exist.
*/
struct bencode *ben_dict_get(const struct bencode *d, const struct bencode *key);
struct bencode *ben_dict_get_by_str(const struct bencode *d, const char *key);
struct bencode *ben_dict_get_by_int(const struct bencode *d, long long key);
struct bencode_keyvalue {
struct bencode *key;
struct bencode *value;
};
/*
* Returns an array of key-value pairs in key order as defined by ben_cmp().
* Array elements are struct bencode_keyvalue members. Returns NULL if
* the array can not be allocated or the bencode object is not a dictionary.
* The returned array must be freed by using free(). The length of the
* array can be determined with ben_dict_len(d).
*
* Warning: key and value pointers in the array are pointers to exact same
* objects in the dictionary. Therefore, the dictionary and its key-values
* must exist while the same keys and values are accessed from the array.
*/
struct bencode_keyvalue *ben_dict_ordered_items(const struct bencode *d);
/*
* Try to locate 'key' in dictionary. Returns the associated value, if found.
* The value must be later freed with ben_free(). Returns NULL if the key
* does not exist.
*/
struct bencode *ben_dict_pop(struct bencode *d, const struct bencode *key);
struct bencode *ben_dict_pop_by_str(struct bencode *d, const char *key);
struct bencode *ben_dict_pop_by_int(struct bencode *d, long long key);
/*
* Set 'key' in dictionary to be 'value'. An old value exists for the key
* is freed if it exists. 'key' and 'value' are owned by the dictionary
* after a successful call (one may not call ben_free() for 'key' or
* 'value'). One may free 'key' and 'value' if the call is unsuccessful.
*
* Returns 0 on success, -1 on failure (no memory).
*/
int ben_dict_set(struct bencode *d, struct bencode *key, struct bencode *value);
/* Same as ben_dict_set(), but the key is a C string */
int ben_dict_set_by_str(struct bencode *d, const char *key, struct bencode *value);
/* Same as ben_dict_set(), but the key and value are C strings */
int ben_dict_set_str_by_str(struct bencode *d, const char *key, const char *value);
struct bencode *ben_int(long long ll);
/* Create an empty list */
struct bencode *ben_list(void);
/*
* Append 'b' to 'list'. Returns 0 on success, -1 on failure (no memory).
* One may not call ben_free(b) after a successful call, because the list owns
* the object 'b'.
*/
int ben_list_append(struct bencode *list, struct bencode *b);
int ben_list_append_str(struct bencode *list, const char *s);
int ben_list_append_int(struct bencode *list, long long ll);
/* Remove and return value at position 'pos' in list */
struct bencode *ben_list_pop(struct bencode *list, size_t pos);
/*
* Returns a Python formatted C string representation of 'b' on success,
* NULL on failure. The returned string should be freed with free().
*
* Note: The string is terminated with '\0'. All instances of '\0' bytes in
* the bencoded data are escaped so that there is only one '\0' byte
* in the generated string at the end.
*/
char *ben_print(const struct bencode *b);
/* Create a string from C string (note bencode string may contain '\0'. */
struct bencode *ben_str(const char *s);
/* Return a human readable explanation of error returned with ben_decode2() */
const char *ben_strerror(int error);
/*
* Unpack a Bencoded structure similar to scanf(). Takes a format string and
* a list of pointers as variable arguments. The given b structure is checked
* against the format and values are unpacked using the given specifiers.
* A specifier begins with a percent (%) that follows a string of specifier
* characters documented below.
* The syntax is similar to Python format for recursive data structures, and
* consists of tokens {, }, [, ] with any number of spaces between them.
* The keys of a dictionary are given as literal strings or integers and
* matched against the keys of the Bencoded structure.
*
* Unpack modifiers:
* l The integer is of type long or unsigned long, and the type of the
* argument is expected to be long * or unsigned long *.
* ll The integer is a long long or an unsigned long long, and the
* argument is long long * or unsigned long long *.
* L Same as ll.
* q Same as ll.
*
* Unpack specifiers:
* %ps The Bencode value must be a string and a pointer to a string
* (char **) is expected to be given as arguments. Note, returns a
* reference to the internal string buffer. The returned memory should
* not be freed and it has the same life time as the Bencode string.
*
* %pb Takes any structure and writes a pointer given as an argument.
* The argument is expected to be "struct bencode **". Note, returns a
* reference to the value inside the structure passed to ben_unpack().
* The returned memory should not be freed and it has the same life
* time as the original structure.
*
* %d The bencode value is expected to be a (signed) integer. The
* preceeding conversion modifiers define the type of the given
* pointer.
* %u The bencode value is expected to be an unsigned integer. The
* preceeding conversion modifiers define the type of the given
* pointer.
*/
int ben_unpack(const struct bencode *b, const char *fmt, ...)
BEN_CHECK_FORMAT(scanf, 2, 3);
int ben_unpack2(const struct bencode *b, size_t *off, struct bencode_error *error, const char *fmt, ...)
BEN_CHECK_FORMAT(scanf, 4, 5);
/*
* Pack a Bencoded structure similar to printf(). Takes a format string and
* a list of values as variable arguments.
* Works similarly to ben_decode_printed(), but allows the string to values
* specifiers which are replaced with values given as arguments.
* A specifier begins with a percent (%) that follows a string of specifier
* characters documented below.
*
* Value modifiers:
* l The integer is of type long or unsigned long.
* ll The integer is a long long or an unsigned long long.
* L Same as ll.
* q Same as ll.
*
* Value specifiers:
* %s A string pointer (char *) expected to be given as argument. A new
* Bencode string is constructed from the given string.
*
* %pb A Bencode structure (struct bencode *) is expected to be given as
* argument. Note, takes ownership of the structure, even when an
* error is returned.
*
* %d Constructs a new integer from the given (signed) integer. The
* preceeding conversion modifiers define the type of the value.
*
* %u Constructs a new integer from the given unsigned integer. The
* preceeding conversion modifiers define the type of the value.
*/
struct bencode *ben_pack(const char *fmt, ...)
BEN_CHECK_FORMAT(printf, 1, 2);
/* ben_is_bool() returns 1 iff b is a boolean, 0 otherwise */
static inline int ben_is_bool(const struct bencode *b)
{
return b->type == BENCODE_BOOL;
}
static inline int ben_is_dict(const struct bencode *b)
{
return b->type == BENCODE_DICT;
}
static inline int ben_is_int(const struct bencode *b)
{
return b->type == BENCODE_INT;
}
static inline int ben_is_list(const struct bencode *b)
{
return b->type == BENCODE_LIST;
}
static inline int ben_is_str(const struct bencode *b)
{
return b->type == BENCODE_STR;
}
static inline int ben_is_user(const struct bencode *b)
{
return b->type == BENCODE_USER;
}
/*
* ben_bool_const_cast(b) returns "(const struct bencode_bool *) b" if the
* underlying object is a boolean, NULL otherwise.
*/
static inline const struct bencode_bool *ben_bool_const_cast(const struct bencode *b)
{
return b->type == BENCODE_BOOL ? ((const struct bencode_bool *) b) : NULL;
}
/*
* ben_bool_cast(b) returns "(struct bencode_bool *) b" if the
* underlying object is a boolean, NULL otherwise.
*/
static inline struct bencode_bool *ben_bool_cast(struct bencode *b)
{
return b->type == BENCODE_BOOL ? ((struct bencode_bool *) b) : NULL;
}
static inline const struct bencode_dict *ben_dict_const_cast(const struct bencode *b)
{
return b->type == BENCODE_DICT ? ((const struct bencode_dict *) b) : NULL;
}
static inline struct bencode_dict *ben_dict_cast(struct bencode *b)
{
return b->type == BENCODE_DICT ? ((struct bencode_dict *) b) : NULL;
}
static inline const struct bencode_int *ben_int_const_cast(const struct bencode *i)
{
return i->type == BENCODE_INT ? ((const struct bencode_int *) i) : NULL;
}
static inline struct bencode_int *ben_int_cast(struct bencode *i)
{
return i->type == BENCODE_INT ? ((struct bencode_int *) i) : NULL;
}
static inline const struct bencode_list *ben_list_const_cast(const struct bencode *list)
{
return list->type == BENCODE_LIST ? ((const struct bencode_list *) list) : NULL;
}
static inline struct bencode_list *ben_list_cast(struct bencode *list)
{
return list->type == BENCODE_LIST ? ((struct bencode_list *) list) : NULL;
}
static inline const struct bencode_str *ben_str_const_cast(const struct bencode *str)
{
return str->type == BENCODE_STR ? ((const struct bencode_str *) str) : NULL;
}
static inline struct bencode_str *ben_str_cast(struct bencode *str)
{
return str->type == BENCODE_STR ? ((struct bencode_str *) str) : NULL;
}
static inline const struct bencode_user *ben_user_const_cast(const struct bencode *user)
{
return user->type == BENCODE_USER ? ((const struct bencode_user *) user) : NULL;
}
static inline struct bencode_user *ben_user_cast(struct bencode *user)
{
return user->type == BENCODE_USER ? ((struct bencode_user *) user) : NULL;
}
static inline int ben_is_user_type(const struct bencode *b, struct bencode_type *type)
{
return b->type == BENCODE_USER ? ((const struct bencode_user *) b)->info == type : 0;
}
static inline const void *ben_user_type_const_cast(const struct bencode *b, struct bencode_type *type)
{
return (b->type == BENCODE_USER && ((const struct bencode_user *) b)->info == type) ? b : NULL;
}
static inline void *ben_user_type_cast(struct bencode *b, struct bencode_type *type)
{
return (b->type == BENCODE_USER && ((const struct bencode_user *) b)->info == type) ? b : NULL;
}
/* Return the number of keys in a dictionary 'b' */
static inline size_t ben_dict_len(const struct bencode *b)
{
return ben_dict_const_cast(b)->n;
}
/* Return the number of items in a list 'b' */
static inline size_t ben_list_len(const struct bencode *b)
{
return ben_list_const_cast(b)->n;
}
/* ben_list_get(list, i) returns object at position i in list */
static inline struct bencode *ben_list_get(const struct bencode *list, size_t i)
{
const struct bencode_list *l = ben_list_const_cast(list);
if (i >= l->n) {
fprintf(stderr, "bencode: List index out of bounds\n");
abort();
}
return l->values[i];
}
/*
* ben_list_set(list, i, b) sets object b to list at position i.
* The old value at position i is freed.
* The program aborts if position i is out of bounds.
*/
void ben_list_set(struct bencode *list, size_t i, struct bencode *b);
/* Return the number of bytes in a string 'b' */
static inline size_t ben_str_len(const struct bencode *b)
{
return ben_str_const_cast(b)->len;
}
/* Return boolean value (0 or 1) of 'b' */
static inline int ben_bool_val(const struct bencode *b)
{
return ben_bool_const_cast(b)->b ? 1 : 0;
}
/* Return integer value of 'b' */
static inline long long ben_int_val(const struct bencode *b)
{
return ben_int_const_cast(b)->ll;
}
/*
* Note: the string is always zero terminated. Also, the string may
* contain more than one zero.
* bencode strings are not compatible with C strings.
*/
static inline const char *ben_str_val(const struct bencode *b)
{
return ben_str_const_cast(b)->s;
}
/*
* ben_list_for_each() is an iterator macro for bencoded lists.
*
* Note, it is not allowed to change the list while iterating except by
* using ben_list_pop_current().
*
* pos is a size_t.
*
* Example:
*
* size_t pos;
* struct bencode *list = xxx;
* struct bencode *value;
* ben_list_for_each(value, pos, list) {
* inspect(value);
* }
*/
#define ben_list_for_each(value, pos, l) \
for ((pos) = (size_t) 0; \
(pos) < (ben_list_const_cast(l))->n && \
((value) = ((const struct bencode_list *) (l))->values[(pos)]) != NULL ; \
(pos)++)
/*
* ben_list_pop_current() returns and removes the current item at 'pos'
* while iterating the list with ben_list_for_each().
* It can be used more than once per walk, but only once per item.
* Example below:
*
* Filter out all items from list whose string value does not begin with "foo".
*
* ben_list_for_each(value, pos, list) {
* if (strncmp(ben_str_val(value), "foo", 3) != 0)
* ben_free(ben_list_pop_current(&pos, list));
* }
*/
static inline struct bencode *ben_list_pop_current(struct bencode *list,
size_t *pos)
{
struct bencode *value = ben_list_pop(list, *pos);
(*pos)--;
return value;
}
/*
* ben_dict_for_each() is an iterator macro for bencoded dictionaries.
*
* Note, it is not allowed to change the dictionary while iterating except
* by using ben_dict_pop_current().
*
* struct bencode *dict = ben_dict();
* size_t pos;
* struct bencode *key;
* struct bencode *value;
* ben_dict_set_str_by_str(dict, "foo", "bar");
*
* ben_dict_for_each(key, value, pos, dict) {
* use(key, value);
* }
*
* pos is a size_t.
*/
#define ben_dict_for_each(bkey, bvalue, pos, d) \
for ((pos) = 0; \
(pos) < (ben_dict_const_cast(d))->n && \
((bkey) = ((const struct bencode_dict *) (d))->nodes[(pos)].key) != NULL && \
((bvalue) = ((const struct bencode_dict *) (d))->nodes[(pos)].value) != NULL; \
(pos)++)
/*
* ben_dict_pop_current() deletes the current item at 'pos' while iterating
* the dictionary with ben_dict_for_each(). It can be used more than once
* per walk, but only once per item. Example below:
*
* Filter out all items from dictionary whose key does not begin with "foo".
*
* ben_dict_for_each(key, value, pos, dict) {
* if (strncmp(ben_str_val(key), "foo", 3) != 0)
* ben_free(ben_dict_pop_current(dict, &pos));
* }
*/
struct bencode *ben_dict_pop_current(struct bencode *dict, size_t *pos);
/* Report an error while decoding. Returns NULL. */
void *ben_insufficient_ptr(struct ben_decode_ctx *ctx);
void *ben_invalid_ptr(struct ben_decode_ctx *ctx);
void *ben_oom_ptr(struct ben_decode_ctx *ctx);
/*
* Decode from the current position of 'ctx'.
*
* This function is used to implement decoders for user-defined types.
*/
struct bencode *ben_ctx_decode(struct ben_decode_ctx *ctx);
/*
* Test whether the input of 'ctx' has at least n bytes left.
* Returns 0 when there is enough bytes left and -1 when there isn't.
*
* This function is used to implement decoders for user-defined types.
*/
int ben_need_bytes(const struct ben_decode_ctx *ctx, size_t n);
/*
* Returns the character in current position of 'ctx'.
*
* This function is used to implement decoders for user-defined types.
*/
char ben_current_char(const struct ben_decode_ctx *ctx);
/*
* Get the next n bytes from input.
* Returns pointer to the data or NULL when there aren't enough bytes left.
*
* This function is used to implement decoders for user-defined types.
*/
const char *ben_current_buf(const struct ben_decode_ctx *ctx, size_t n);
/*
* Increments current position by n.
*
* This function is used to implement decoders for user-defined types.
*/
void ben_skip(struct ben_decode_ctx *ctx, size_t n);
/*
* Encode to the output of 'ctx'. The size of the encoded data can be obtained
* with ben_encoded_size().
*
* This function is used to implement encoders for user-defined types.
*/
int ben_ctx_encode(struct ben_encode_ctx *ctx, const struct bencode *b);
/*
* Append one character to output of 'ctx'. The amount of bytes written to the
* output must be the same as returned by get_size().
*
* This function is used to implement encoders for user-defined types.
*/
int ben_put_char(struct ben_encode_ctx *ctx, char c);
/*
* Append data to output of 'ctx'. The amount of bytes written to the output
* must be the same as returned by get_size().
*
* This function is used to implement encoders for user-defined types.
*/
int ben_put_buffer(struct ben_encode_ctx *ctx, const void *buf, size_t len);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2012, Anthony Minessale II
* Copyright (c) 2010-2015, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -30,9 +30,14 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ks.h"
#ifndef KS_BUFFER_H
#define KS_BUFFER_H
#include "ks.h"
KS_BEGIN_EXTERN_C
/**
* @defgroup ks_buffer Buffer Routines
* @ingroup buffer
@ -133,6 +138,7 @@ KS_DECLARE(ks_size_t) ks_buffer_seek(ks_buffer_t *buffer, ks_size_t datalen);
KS_DECLARE(ks_size_t) ks_buffer_zwrite(ks_buffer_t *buffer, const void *data, ks_size_t datalen);
KS_END_EXTERN_C
#endif
/* For Emacs:
* Local Variables:

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007-2014, Anthony Minessale II
* Copyright (c) 2007-2015, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -52,16 +52,12 @@
#ifndef KS_CONFIG_H
#define KS_CONFIG_H
KS_BEGIN_EXTERN_C
#include "ks.h"
#ifdef __cplusplus
extern "C" {
#endif /* defined(__cplusplus) */
#define KS_URL_SEPARATOR "://"
#ifdef WIN32
#define KS_PATH_SEPARATOR "\\"
#ifndef KS_CONFIG_DIR
@ -107,26 +103,26 @@ atoi(expr))) ? 1 : 0
typedef struct ks_config ks_config_t;
/*! \brief A simple file handle representing an open configuration file **/
struct ks_config {
/*! FILE stream buffer to the opened file */
FILE *file;
/*! path to the file */
char path[512];
/*! current category */
char category[256];
/*! current section */
char section[256];
/*! buffer of current line being read */
char buf[1024];
/*! current line number in file */
int lineno;
/*! current category number in file */
int catno;
/*! current section number in file */
int sectno;
struct ks_config {
/*! FILE stream buffer to the opened file */
FILE *file;
/*! path to the file */
char path[512];
/*! current category */
char category[256];
/*! current section */
char section[256];
/*! buffer of current line being read */
char buf[1024];
/*! current line number in file */
int lineno;
/*! current category number in file */
int catno;
/*! current section number in file */
int sectno;
int lockto;
};
int lockto;
};
/*!
\brief Open a configuration file
@ -134,13 +130,13 @@ struct ks_config {
\param file_path path to the file
\return 1 (true) on success 0 (false) on failure
*/
KS_DECLARE(int) ks_config_open_file(ks_config_t * cfg, const char *file_path);
KS_DECLARE(int) ks_config_open_file(ks_config_t *cfg, const char *file_path);
/*!
\brief Close a previously opened configuration file
\param cfg (ks_config_t *) config handle to use
*/
KS_DECLARE(void) ks_config_close_file(ks_config_t * cfg);
KS_DECLARE(void) ks_config_close_file(ks_config_t *cfg);
/*!
\brief Retrieve next name/value pair from configuration file
@ -148,24 +144,20 @@ KS_DECLARE(void) ks_config_close_file(ks_config_t * cfg);
\param var pointer to aim at the new variable name
\param val pointer to aim at the new value
*/
KS_DECLARE(int) ks_config_next_pair(ks_config_t * cfg, char **var, char **val);
KS_DECLARE(int) ks_config_next_pair(ks_config_t *cfg, char **var, char **val);
/*!
\brief Retrieve the CAS bits from a configuration string value
\param strvalue pointer to the configuration string value (expected to be in format whatever:xxxx)
\param outbits pointer to aim at the CAS bits
*/
KS_DECLARE(int) ks_config_get_cas_bits(char *strvalue, unsigned char *outbits);
KS_DECLARE(int) ks_config_get_cas_bits(char *strvalue, unsigned char *outbits);
/** @} */
#ifdef __cplusplus
}
#endif /* defined(__cplusplus) */
#endif /* defined(KS_CONFIG_H) */
KS_END_EXTERN_C
#endif /* defined(KS_CONFIG_H) */
/* For Emacs:
* Local Variables:
* mode:c

View File

@ -0,0 +1,109 @@
/*
Copyright (c) 2009-2011 by Juliusz Chroboczek
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef _KS_DHT_H
#define _KS_DHT_H
#include "ks.h"
#include "ks_bencode.h"
KS_BEGIN_EXTERN_C
typedef enum {
KS_DHT_EVENT_NONE = 0,
KS_DHT_EVENT_VALUES = 1,
KS_DHT_EVENT_VALUES6 = 2,
KS_DHT_EVENT_SEARCH_DONE = 3,
KS_DHT_EVENT_SEARCH_DONE6 = 4
} ks_dht_event_t;
typedef enum {
DHT_PARAM_AUTOROUTE = 1
} ks_dht_param_t;
typedef enum {
KS_DHT_AF_INET4 = (1 << 0),
KS_DHT_AF_INET6 = (1 << 1)
} ks_dht_af_flag_t;
typedef void (*dht_callback_t)(void *closure, ks_dht_event_t event, const unsigned char *info_hash, const void *data, size_t data_len);
typedef struct dht_handle_s dht_handle_t;
KS_DECLARE(int) dht_periodic(dht_handle_t *h, const void *buf, size_t buflen, ks_sockaddr_t *from);
KS_DECLARE(ks_status_t) ks_dht_init(dht_handle_t **handle, ks_dht_af_flag_t af_flags, const unsigned char *id, unsigned int port);
KS_DECLARE(void) ks_dht_set_param(dht_handle_t *h, ks_dht_param_t param, ks_bool_t val);
KS_DECLARE(ks_status_t) ks_dht_add_ip(dht_handle_t *h, char *ip, int port);
KS_DECLARE(void) ks_dht_start(dht_handle_t *h);
KS_DECLARE(int) dht_insert_node(dht_handle_t *h, const unsigned char *id, ks_sockaddr_t *sa);
KS_DECLARE(int) dht_ping_node(dht_handle_t *h, ks_sockaddr_t *sa);
KS_DECLARE(int) dht_search(dht_handle_t *h, const unsigned char *id, int port, int af, dht_callback_t callback, void *closure);
KS_DECLARE(int) dht_nodes(dht_handle_t *h, int af, int *good_return, int *dubious_return, int *cached_return, int *incoming_return);
KS_DECLARE(ks_status_t) ks_dht_one_loop(dht_handle_t *h, int timeout);
KS_DECLARE(ks_status_t) ks_dht_get_bind_addrs(dht_handle_t *h, const ks_sockaddr_t ***addrs, ks_size_t *addrlen);
KS_DECLARE(void) ks_dht_set_callback(dht_handle_t *h, dht_callback_t callback, void *closure);
KS_DECLARE(void) ks_dht_set_port(dht_handle_t *h, unsigned int port);
KS_DECLARE(void) dht_dump_tables(dht_handle_t *h, FILE *f);
KS_DECLARE(int) dht_get_nodes(dht_handle_t *h, struct sockaddr_in *sin, int *num, struct sockaddr_in6 *sin6, int *num6);
KS_DECLARE(int) dht_uninit(dht_handle_t **h);
KS_DECLARE(void) ks_dht_set_v(dht_handle_t *h, const unsigned char *v);
KS_DECLARE(int) ks_dht_calculate_mutable_storage_target(unsigned char *pk, unsigned char *salt, int salt_length, unsigned char *target, int target_length);
KS_DECLARE(int) ks_dht_generate_mutable_storage_args(struct bencode *data, int64_t sequence, int cas,
unsigned char *id, int id_len, /* querying nodes id */
const unsigned char *sk, const unsigned char *pk,
unsigned char *salt, unsigned long long salt_length,
unsigned char *token, unsigned long long token_length,
unsigned char *signature, unsigned long long *signature_length,
struct bencode **arguments);
/* This must be provided by the user. */
KS_DECLARE(int) dht_blacklisted(const ks_sockaddr_t *sa);
KS_DECLARE(void) dht_hash(void *hash_return, int hash_size, const void *v1, int len1, const void *v2, int len2, const void *v3, int len3);
KS_DECLARE(int) dht_random_bytes(void *buf, size_t size);
KS_DECLARE(int) ks_dht_send_message_mutable(dht_handle_t *h, unsigned char *sk, unsigned char *pk, char **node_id,
char *message_id, int sequence, char *message, ks_time_t life);
KS_DECLARE(int) ks_dht_send_message_mutable_cjson(dht_handle_t *h, unsigned char *sk, unsigned char *pk, char **node_id,
char *message_id, int sequence, cJSON *message, ks_time_t life);
typedef void (ks_dht_store_entry_json_cb)(struct dht_handle_s *h, const cJSON *msg, void *obj);
KS_DECLARE(void) ks_dht_store_entry_json_cb_set(struct dht_handle_s *h, ks_dht_store_entry_json_cb *store_json_cb, void *arg);
KS_DECLARE(int) ks_dht_api_find_node(dht_handle_t *h, char *node_id_hex, char *target_hex, ks_bool_t ipv6);
KS_END_EXTERN_C
#endif /* _KS_DHT_H */
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

49
libs/libks/src/include/ks_dso.h Executable file
View File

@ -0,0 +1,49 @@
/*
* Cross Platform dso/dll load abstraction
* Copyright(C) 2008 Michael Jerris
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so.
*
* This work is provided under this license on an "as is" basis, without warranty of any kind,
* either expressed or implied, including, without limitation, warranties that the covered code
* is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire
* risk as to the quality and performance of the covered code is with you. Should any covered
* code prove defective in any respect, you (not the initial developer or any other contributor)
* assume the cost of any necessary servicing, repair or correction. This disclaimer of warranty
* constitutes an essential part of this license. No use of any covered code is authorized hereunder
* except under this disclaimer.
*
*/
#include "ks.h"
#ifndef _KS_DSO_H
#define _KS_DSO_H
KS_BEGIN_EXTERN_C
typedef void (*ks_func_ptr_t) (void);
typedef void * ks_dso_lib_t;
KS_DECLARE(ks_status_t) ks_dso_destroy(ks_dso_lib_t *lib);
KS_DECLARE(ks_dso_lib_t) ks_dso_open(const char *path, char **err);
KS_DECLARE(void *) ks_dso_func_sym(ks_dso_lib_t lib, const char *sym, char **err);
KS_DECLARE(char *) ks_build_dso_path(const char *name, char *path, ks_size_t len);
KS_END_EXTERN_C
#endif
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

View File

@ -0,0 +1,372 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* ks_hash.h -- Ks_Hash
*
*/
/* ks_hash.h Copyright (C) 2002 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
#ifndef __KS_HASH_CWC22_H__
#define __KS_HASH_CWC22_H__
#ifdef _MSC_VER
#ifndef __inline__
#define __inline__ __inline
#endif
#endif
#include "ks.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct ks_hash ks_hash_t;
typedef struct ks_hash_iterator ks_hash_iterator_t;
typedef enum {
KS_UNLOCKED,
KS_READLOCKED
} ks_locked_t;
/* Example of use:
*
* ks_hash_t *h;
* struct some_key *k;
* struct some_value *v;
*
* static unsigned int hash_from_key_fn( void *k );
* static int keys_equal_fn ( void *key1, void *key2 );
*
* h = ks_hash_create(16, hash_from_key_fn, keys_equal_fn);
* k = (struct some_key *) malloc(sizeof(struct some_key));
* v = (struct some_value *) malloc(sizeof(struct some_value));
*
* (initialise k and v to suitable values)
*
* if (! ks_hash_insert(h,k,v) )
* { exit(-1); }
*
* if (NULL == (found = ks_hash_search(h,k) ))
* { printf("not found!"); }
*
* if (NULL == (found = ks_hash_remove(h,k) ))
* { printf("Not found\n"); }
*
*/
/* Macros may be used to define type-safe(r) ks_hash access functions, with
* methods specialized to take known key and value types as parameters.
*
* Example:
*
* Insert this at the start of your file:
*
* DEFINE_KS_HASH_INSERT(insert_some, struct some_key, struct some_value);
* DEFINE_KS_HASH_SEARCH(search_some, struct some_key, struct some_value);
* DEFINE_KS_HASH_REMOVE(remove_some, struct some_key, struct some_value);
*
* This defines the functions 'insert_some', 'search_some' and 'remove_some'.
* These operate just like ks_hash_insert etc., with the same parameters,
* but their function signatures have 'struct some_key *' rather than
* 'void *', and hence can generate compile time errors if your program is
* supplying incorrect data as a key (and similarly for value).
*
* Note that the hash and key equality functions passed to ks_hash_create
* still take 'void *' parameters instead of 'some key *'. This shouldn't be
* a difficult issue as they're only defined and passed once, and the other
* functions will ensure that only valid keys are supplied to them.
*
* The cost for this checking is increased code size and runtime overhead
* - if performance is important, it may be worth switching back to the
* unsafe methods once your program has been debugged with the safe methods.
* This just requires switching to some simple alternative defines - eg:
* #define insert_some ks_hash_insert
*
*/
typedef enum {
KS_HASH_FLAG_NONE = 0,
KS_HASH_FLAG_DEFAULT = (1 << 0),
KS_HASH_FLAG_FREE_KEY = (1 << 1),
KS_HASH_FLAG_FREE_VALUE = (1 << 2),
KS_HASH_FLAG_RWLOCK = (1 << 3),
KS_HASH_FLAG_DUP_CHECK = (1 << 4)
} ks_hash_flag_t;
#define KS_HASH_FREE_BOTH KS_HASH_FLAG_FREE_KEY | KS_HASH_FLAG_FREE_VALUE
typedef enum {
KS_HASH_MODE_DEFAULT = 0,
KS_HASH_MODE_CASE_SENSITIVE,
KS_HASH_MODE_CASE_INSENSITIVE,
KS_HASH_MODE_INT,
KS_HASH_MODE_INT64,
KS_HASH_MODE_PTR
} ks_hash_mode_t;
/*****************************************************************************
* ks_hash_create
* @name ks_hash_create
* @param minsize minimum initial size of ks_hash
* @param hashfunction function for hashing keys
* @param key_eq_fn function for determining key equality
* @return newly created ks_hash or NULL on failure
*/
KS_DECLARE(ks_status_t)
ks_hash_create_ex(ks_hash_t **hp, unsigned int minsize,
unsigned int (*hashfunction) (void*),
int (*key_eq_fn) (void*,void*), ks_hash_mode_t mode, ks_hash_flag_t flags, ks_hash_destructor_t destructor, ks_pool_t *pool);
/*****************************************************************************
* ks_hash_insert
* @name ks_hash_insert
* @param h the ks_hash to insert into
* @param k the key - ks_hash claims ownership and will free on removal
* @param v the value - does not claim ownership
* @return non-zero for successful insertion
*
* This function will cause the table to expand if the insertion would take
* the ratio of entries to table size over the maximum load factor.
*
* This function does not check for repeated insertions with a duplicate key.
* The value returned when using a duplicate key is undefined -- when
* the ks_hash changes size, the order of retrieval of duplicate key
* entries is reversed.
* If in doubt, remove before insert.
*/
KS_DECLARE(int) ks_hash_insert_ex(ks_hash_t *h, void *k, void *v, ks_hash_flag_t flags, ks_hash_destructor_t destructor);
#define ks_hash_insert(_h, _k, _v) ks_hash_insert_ex(_h, _k, _v, 0, NULL)
#define DEFINE_KS_HASH_INSERT(fnname, keytype, valuetype) \
int fnname (ks_hash_t *h, keytype *k, valuetype *v) \
{ \
return ks_hash_insert(h,k,v); \
}
KS_DECLARE(void) ks_hash_set_flags(ks_hash_t *h, ks_hash_flag_t flags);
KS_DECLARE(void) ks_hash_set_destructor(ks_hash_t *h, ks_hash_destructor_t destructor);
/*****************************************************************************
* ks_hash_search
* @name ks_hash_search
* @param h the ks_hash to search
* @param k the key to search for - does not claim ownership
* @return the value associated with the key, or NULL if none found
*/
KS_DECLARE(void *)
ks_hash_search(ks_hash_t *h, void *k, ks_locked_t locked);
#define DEFINE_KS_HASH_SEARCH(fnname, keytype, valuetype) \
valuetype * fnname (ks_hash_t *h, keytype *k) \
{ \
return (valuetype *) (ks_hash_search(h,k)); \
}
/*****************************************************************************
* ks_hash_remove
* @name ks_hash_remove
* @param h the ks_hash to remove the item from
* @param k the key to search for - does not claim ownership
* @return the value associated with the key, or NULL if none found
*/
KS_DECLARE(void *) /* returns value */
ks_hash_remove(ks_hash_t *h, void *k);
#define DEFINE_KS_HASH_REMOVE(fnname, keytype, valuetype) \
valuetype * fnname (ks_hash_t *h, keytype *k) \
{ \
return (valuetype *) (ks_hash_remove(h,k)); \
}
/*****************************************************************************
* ks_hash_count
* @name ks_hash_count
* @param h the ks_hash
* @return the number of items stored in the ks_hash
*/
KS_DECLARE(unsigned int)
ks_hash_count(ks_hash_t *h);
/*****************************************************************************
* ks_hash_destroy
* @name ks_hash_destroy
* @param h the ks_hash
* @param free_values whether to call 'free' on the remaining values
*/
KS_DECLARE(void)
ks_hash_destroy(ks_hash_t **h);
KS_DECLARE(ks_hash_iterator_t*) ks_hash_first(ks_hash_t *h, ks_locked_t locked);
KS_DECLARE(void) ks_hash_last(ks_hash_iterator_t **iP);
KS_DECLARE(ks_hash_iterator_t*) ks_hash_next(ks_hash_iterator_t **iP);
KS_DECLARE(void) ks_hash_this(ks_hash_iterator_t *i, const void **key, ks_ssize_t *klen, void **val);
KS_DECLARE(void) ks_hash_this_val(ks_hash_iterator_t *i, void *val);
KS_DECLARE(ks_status_t) ks_hash_create(ks_hash_t **hp, ks_hash_mode_t mode, ks_hash_flag_t flags, ks_pool_t *pool);
KS_DECLARE(void) ks_hash_write_lock(ks_hash_t *h);
KS_DECLARE(void) ks_hash_write_unlock(ks_hash_t *h);
KS_DECLARE(ks_status_t) ks_hash_read_lock(ks_hash_t *h);
KS_DECLARE(ks_status_t) ks_hash_read_unlock(ks_hash_t *h);
static __inline uint32_t ks_hash_default_int64(void *ky)
{
int64_t key = *((int64_t *)ky);
key = (~key) + (key << 18);
key = key ^ (key >> 31);
key = key * 21;
key = key ^ (key >> 11);
key = key + (key << 6);
key = key ^ (key >> 22);
return (uint32_t) key;
}
static __inline int ks_hash_equalkeys_int64(void *k1, void *k2)
{
return *(uint64_t *)k1 == *(uint64_t *)k2;
}
static __inline uint32_t ks_hash_default_int(void *ky) {
uint32_t x = *((uint32_t *)ky);
x = ((x >> 16) ^ x) * 0x45d9f3b;
x = ((x >> 16) ^ x) * 0x45d9f3b;
x = ((x >> 16) ^ x);
return x;
}
static __inline int ks_hash_equalkeys_int(void *k1, void *k2)
{
return *(uint32_t *)k1 == *(uint32_t *)k2;
}
#if 0
}
#endif
static __inline uint32_t ks_hash_default_ptr(void *ky)
{
#ifdef KS_64BIT
return ks_hash_default_int64(ky);
#endif
return ks_hash_default_int(ky);
}
static __inline int ks_hash_equalkeys_ptr(void *k1, void *k2)
{
#ifdef KS_64BIT
return ks_hash_equalkeys_int64(k1, k2);
#endif
return ks_hash_equalkeys_int(k1, k2);
}
static __inline int ks_hash_equalkeys(void *k1, void *k2)
{
return strcmp((char *) k1, (char *) k2) ? 0 : 1;
}
static __inline int ks_hash_equalkeys_ci(void *k1, void *k2)
{
return strcasecmp((char *) k1, (char *) k2) ? 0 : 1;
}
static __inline uint32_t ks_hash_default(void *ky)
{
unsigned char *str = (unsigned char *) ky;
uint32_t hash = 0;
int c;
while ((c = *str)) {
str++;
hash = c + (hash << 6) + (hash << 16) - hash;
}
return hash;
}
static __inline uint32_t ks_hash_default_ci(void *ky)
{
unsigned char *str = (unsigned char *) ky;
uint32_t hash = 0;
int c;
while ((c = ks_tolower(*str))) {
str++;
hash = c + (hash << 6) + (hash << 16) - hash;
}
return hash;
}
#ifdef __cplusplus
} /* extern C */
#endif
#endif /* __KS_HASH_CWC22_H__ */
/*
* Copyright (c) 2002, Christopher Clark
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

71
libs/libks/src/include/ks_json.h Executable file → Normal file
View File

@ -76,20 +76,21 @@ KS_DECLARE(int) cJSON_GetArraySize(cJSON *array);
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
KS_DECLARE(cJSON *)cJSON_GetArrayItem(cJSON *array,int item);
/* Get item "string" from object. Case insensitive. */
KS_DECLARE(cJSON *)cJSON_GetObjectItem(cJSON *object,const char *string);
KS_DECLARE(cJSON *)cJSON_GetObjectItem(const cJSON *object,const char *string);
KS_DECLARE(const char *)cJSON_GetObjectCstr(const cJSON *object, const char *string);
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
KS_DECLARE(const char *)cJSON_GetErrorPtr();
KS_DECLARE(const char *)cJSON_GetErrorPtr(void);
/* These calls create a cJSON item of the appropriate type. */
KS_DECLARE(cJSON *)cJSON_CreateNull();
KS_DECLARE(cJSON *)cJSON_CreateTrue();
KS_DECLARE(cJSON *)cJSON_CreateFalse();
KS_DECLARE(cJSON *)cJSON_CreateNull(void);
KS_DECLARE(cJSON *)cJSON_CreateTrue(void);
KS_DECLARE(cJSON *)cJSON_CreateFalse(void);
KS_DECLARE(cJSON *)cJSON_CreateBool(int b);
KS_DECLARE(cJSON *)cJSON_CreateNumber(double num);
KS_DECLARE(cJSON *)cJSON_CreateString(const char *string);
KS_DECLARE(cJSON *)cJSON_CreateArray();
KS_DECLARE(cJSON *)cJSON_CreateObject();
KS_DECLARE(cJSON *)cJSON_CreateArray(void);
KS_DECLARE(cJSON *)cJSON_CreateObject(void);
/* These utilities create an Array of count items. */
KS_DECLARE(cJSON *)cJSON_CreateIntArray(int *numbers,int count);
@ -114,12 +115,68 @@ KS_DECLARE(void) cJSON_DeleteItemFromObject(cJSON *object,const char *string);
KS_DECLARE(void) cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
KS_DECLARE(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
/* Duplicate a cJSON item */
KS_DECLARE(cJSON *) cJSON_Duplicate(cJSON *item,int recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
need to be released. With recurse!=0, it will duplicate any children connected to the item.
The item->next and ->prev pointers are always zero on return from Duplicate. */
#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
KS_DECLARE(cJSON *) cJSON_CreateStringPrintf(const char *fmt, ...);
static inline cJSON *json_add_child_obj(cJSON *json, const char *name, cJSON *obj)
{
cJSON *new_json = NULL;
ks_assert(json);
if (obj) {
new_json = obj;
} else {
new_json = cJSON_CreateObject();
}
ks_assert(new_json);
cJSON_AddItemToObject(json, name, new_json);
return new_json;
}
static inline cJSON *json_add_child_array(cJSON *json, const char *name)
{
cJSON *new_json = NULL;
ks_assert(json);
new_json = cJSON_CreateArray();
ks_assert(new_json);
cJSON_AddItemToObject(json, name, new_json);
return new_json;
}
static inline cJSON *json_add_child_string(cJSON *json, const char *name, const char *val)
{
cJSON *new_json = NULL;
ks_assert(json);
new_json = cJSON_CreateString(val);
ks_assert(new_json);
cJSON_AddItemToObject(json, name, new_json);
return new_json;
}
#ifdef __cplusplus
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007-2014, Anthony Minessale II
* Copyright (c) 2007-2015, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -34,33 +34,94 @@
#ifndef _KS_PLATFORM_H_
#define _KS_PLATFORM_H_
#include <stdarg.h>
KS_BEGIN_EXTERN_C
#ifdef __cplusplus
extern "C" {
#endif /* defined(__cplusplus) */
#if !defined(_XOPEN_SOURCE) && !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__)
#if !defined(_XOPEN_SOURCE) && !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__APPLE__)
#define _XOPEN_SOURCE 600
#endif
#ifndef HAVE_STRINGS_H
#define HAVE_STRINGS_H 1
#endif
#ifndef HAVE_SYS_SOCKET_H
#define HAVE_SYS_SOCKET_H 1
#if defined(__linux__) && !defined(_DEFAULT_SOURCE)
#define _DEFAULT_SOURCE 1
#endif
#ifndef __WINDOWS__
#if defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
#define __WINDOWS__
#endif
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#if UINTPTR_MAX == 0xffffffffffffffff
#define KS_64BIT 1
#endif
#include <stdarg.h>
#include <time.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <ctype.h>
#include <float.h>
#include <limits.h>
#include <sys/types.h>
#ifdef __WINDOWS__
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#else
#include <sys/time.h>
#include <sys/select.h>
#include <netinet/tcp.h>
#include <sys/signal.h>
#include <unistd.h>
#include <strings.h>
#include <stdint.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#endif
#ifdef _MSC_VER
#pragma comment(lib, "Ws2_32.lib")
#include <io.h>
/*#include <winsock2.h>
#include <ws2tcpip.h>
#include <Synchapi.h>
*/
#ifndef open
#define open _open
#endif
#ifndef close
#define close _close
#endif
#ifndef read
#define read _read
#endif
#ifndef write
#define write _write
#endif
#ifndef __inline__
#define __inline__ __inline
#endif
#ifndef strdup
#define strdup _strdup
#endif
#if (_MSC_VER >= 1400) /* VC8+ */
#ifndef _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE
@ -69,67 +130,62 @@ extern "C" {
#define _CRT_NONSTDC_NO_DEPRECATE
#endif
#endif
#ifndef strcasecmp
#define strcasecmp(s1, s2) _stricmp(s1, s2)
#endif
#ifndef strncasecmp
#define strncasecmp(s1, s2, n) _strnicmp(s1, s2, n)
#endif
#if (_MSC_VER < 1900) /* VC 2015 */
#ifndef snprintf
#define snprintf _snprintf
#endif
#endif
#ifndef S_IRUSR
#define S_IRUSR _S_IREAD
#endif
#ifndef S_IWUSR
#define S_IWUSR _S_IWRITE
#endif
#undef HAVE_STRINGS_H
#undef HAVE_SYS_SOCKET_H
#endif /* _MSC_VER */
#if (_MSC_VER >= 1400) // VC8+
#define ks_assert(expr) assert(expr);__analysis_assume( expr )
#endif
#include <time.h>
#ifndef WIN32
#include <sys/time.h>
#ifndef ks_assert
#define ks_assert(_x) assert(_x)
#endif
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/types.h>
#include <sys/select.h>
#include <netinet/tcp.h>
#include <sys/signal.h>
#include <unistd.h>
#include <ctype.h>
#endif
#ifdef __WINDOWS__
typedef SOCKET ks_socket_t;
typedef unsigned __int64 uint64_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int8 uint8_t;
typedef __int64 int64_t;
typedef __int32 int32_t;
typedef __int16 int16_t;
typedef __int8 int8_t;
typedef intptr_t ks_ssize_t;
typedef int ks_filehandle_t;
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#include <assert.h>
#ifdef WIN32
#include <winsock2.h>
#include <windows.h>
typedef SOCKET ks_socket_t;
typedef unsigned __int64 uint64_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int8 uint8_t;
typedef __int64 int64_t;
typedef __int32 int32_t;
typedef __int16 int16_t;
typedef __int8 int8_t;
typedef intptr_t ks_ssize_t;
typedef int ks_filehandle_t;
#define KS_SOCK_INVALID INVALID_SOCKET
#define strerror_r(num, buf, size) strerror_s(buf, size, num)
#else
#define KS_SOCK_INVALID -1
typedef int ks_socket_t;
typedef ssize_t ks_ssize_t;
typedef int ks_filehandle_t;
#endif
#ifdef __WINDOWS__
#if defined(KS_DECLARE_STATIC)
#define KS_DECLARE(type) type __stdcall
#define KS_DECLARE_NONSTD(type) type __cdecl
@ -143,30 +199,68 @@ typedef int ks_filehandle_t;
#define KS_DECLARE_NONSTD(type) __declspec(dllimport) type __cdecl
#define KS_DECLARE_DATA __declspec(dllimport)
#endif
#else // !WIN32
#else // !WIN32
#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(KS_API_VISIBILITY)
#define KS_DECLARE(type) __attribute__((visibility("default"))) type
#define KS_DECLARE_NONSTD(type) __attribute__((visibility("default"))) type
#define KS_DECLARE_DATA __attribute__((visibility("default")))
#else
#define KS_DECLARE(type) type
#define KS_DECLARE_NONSTD(type) type
#define KS_DECLARE_DATA
#include <stdint.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <stdarg.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define KS_SOCK_INVALID -1
typedef int ks_socket_t;
typedef ssize_t ks_ssize_t;
typedef int ks_filehandle_t;
#endif
#endif
/* malloc or DIE macros */
#ifdef NDEBUG
#define ks_malloc(ptr, len) (void)( (!!(ptr = malloc(len))) || (fprintf(stderr,"ABORT! Malloc failure at: %s:%d", __FILE__, __LINE__),abort(), 0), ptr )
#define ks_zmalloc(ptr, len) (void)( (!!(ptr = calloc(1, (len)))) || (fprintf(stderr,"ABORT! Malloc failure at: %s:%d", __FILE__, __LINE__),abort(), 0), ptr)
#if (_MSC_VER >= 1500) // VC9+
#define ks_strdup(ptr, s) (void)( (!!(ptr = _strdup(s))) || (fprintf(stderr,"ABORT! Malloc failure at: %s:%d", __FILE__, __LINE__),abort(), 0), ptr)
#else
#define ks_strdup(ptr, s) (void)( (!!(ptr = strdup(s))) || (fprintf(stderr,"ABORT! Malloc failure at: %s:%d", __FILE__, __LINE__),abort(), 0), ptr)
#endif
#else
#if (_MSC_VER >= 1500) // VC9+
#define ks_malloc(ptr, len) (void)(assert(((ptr) = malloc((len)))),ptr);__analysis_assume( ptr )
#define ks_zmalloc(ptr, len) (void)(assert((ptr = calloc(1, (len)))),ptr);__analysis_assume( ptr )
#define ks_strdup(ptr, s) (void)(assert(((ptr) = _strdup(s))),ptr);__analysis_assume( ptr )
#else
#define ks_malloc(ptr, len) (void)(assert(((ptr) = malloc((len)))),ptr)
#define ks_zmalloc(ptr, len) (void)(assert((ptr = calloc(1, (len)))),ptr)
#define ks_strdup(ptr, s) (void)(assert(((ptr) = strdup((s)))),ptr)
#endif
#endif
#ifndef __ATTR_SAL
/* used for msvc code analysis */
/* http://msdn2.microsoft.com/en-us/library/ms235402.aspx */
#define _In_
#define _In_z_
#define _In_opt_z_
#define _In_opt_
#define _Printf_format_string_
#define _Ret_opt_z_
#define _Ret_z_
#define _Out_opt_
#define _Out_
#define _Check_return_
#define _Inout_
#define _Inout_opt_
#define _In_bytecount_(x)
#define _Out_opt_bytecapcount_(x)
#define _Out_bytecapcount_(x)
#define _Ret_
#define _Post_z_
#define _Out_cap_(x)
#define _Out_z_cap_(x)
#define _Out_ptrdiff_cap_(x)
#define _Out_opt_ptrdiff_cap_(x)
#define _Post_count_(x)
#endif
#ifdef __cplusplus
}
#endif /* defined(__cplusplus) */
#endif /* defined(_KS_PLATFORM_H_) */
KS_END_EXTERN_C
#endif /* defined(_KS_PLATFORM_H_) */
/* For Emacs:
* Local Variables:
* mode:c

View File

@ -0,0 +1,478 @@
/*
* Memory pool defines.
*
* Copyright 1996 by Gray Watson.
*
* This file is part of the ks_mpool package.
*
* Permission to use, copy, modify, and distribute this software for
* any purpose and without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies, and that the name of Gray Watson not be used in advertising
* or publicity pertaining to distribution of the document or software
* without specific, written prior permission.
*
* Gray Watson makes no representations about the suitability of the
* software described herein for any purpose. It is provided "as is"
* without express or implied warranty.
*
* The author may be reached via http://256.com/gray/
*
* $Id: ks_mpool.h,v 1.4 2006/05/31 20:26:11 gray Exp $
*/
#ifndef __KS_POOL_H__
#define __KS_POOL_H__
#include "ks.h"
KS_BEGIN_EXTERN_C
/*
* ks_pool flags to ks_pool_alloc or ks_pool_set_attr
*/
typedef enum {
KS_POOL_FLAG_DEFAULT = 0,
KS_POOL_FLAG_BEST_FIT = (1 << 0),
/*
* Choose a best fit algorithm not first fit. This takes more CPU
* time but will result in a tighter heap.
*/
KS_POOL_FLAG_HEAVY_PACKING = (1 << 1)
/*
* This enables very heavy packing at the possible expense of CPU.
* This affects a number of parts of the library.
*
* By default the 1st page of memory is reserved for the main ks_pool
* structure. This flag will cause the rest of the 1st block to be
* available for use as user memory.
*
* By default the library looks through the memory when freed looking
* for a magic value. There is an internal max size that it will look
* and then it will give up. This flag forces it to look until it
* finds it.
*/
} ks_pool_flag_t;
/*
* Ks_Pool function IDs for the ks_pool_log_func callback function.
*/
#define KS_POOL_FUNC_CLOSE 1 /* ks_pool_close function called */
#define KS_POOL_FUNC_CLEAR 2 /* ks_pool_clear function called */
#define KS_POOL_FUNC_ALLOC 3 /* ks_pool_alloc function called */
#define KS_POOL_FUNC_CALLOC 4 /* ks_pool_calloc function called */
#define KS_POOL_FUNC_FREE 5 /* ks_pool_free function called */
#define KS_POOL_FUNC_RESIZE 6 /* ks_pool_resize function called */
/*
* void ks_pool_log_func_t
*
* DESCRIPTION:
*
* Ks_Pool transaction log function.
*
* RETURNS:
*
* None.
*
* ARGUMENT:
*
* mp_p -> Associated ks_pool address.
*
* func_id -> Integer function ID which identifies which ks_pool
* function is being called.
*
* byte_size -> Optionally specified byte size.
*
* ele_n -> Optionally specified element number. For ks_pool_calloc
* only.
*
* new_addr -> Optionally specified new address. For ks_pool_alloc,
* ks_pool_calloc, and ks_pool_resize only.
*
* old_addr -> Optionally specified old address. For ks_pool_resize and
* ks_pool_free only.
*
* old_byte_size -> Optionally specified old byte size. For
* ks_pool_resize only.
*/
typedef void (*ks_pool_log_func_t) (const void *mp_p,
const int func_id,
const unsigned long byte_size,
const unsigned long ele_n, const void *old_addr, const void *new_addr, const unsigned long old_byte_size);
/*
* ks_pool_t *ks_pool_open
*
* DESCRIPTION:
*
* Open/allocate a new memory pool.
*
* RETURNS:
*
* Success - KS_STATUS_SUCCESS
*
* Failure - ks_status_t error code
*
* ARGUMENTS:
*
* poolP <- pointer to new pool that will be set on success
*
*/
KS_DECLARE(ks_status_t) ks_pool_open(ks_pool_t **poolP);
/*
* ks_status_t ks_pool_close
*
* DESCRIPTION:
*
* Close/free a memory allocation pool previously opened with
* ks_pool_open.
*
* RETURNS:
*
* Success - KS_STATUS_SUCCESS
*
* Failure - ks_status_t error code
*
* ARGUMENTS:
*
* mp_pp <-> Pointer to pointer of our memory pool.
*/
KS_DECLARE(ks_status_t) ks_pool_close(ks_pool_t **mp_pP);
/*
* int ks_pool_clear
*
* DESCRIPTION:
*
* Wipe an opened memory pool clean so we can start again.
*
* RETURNS:
*
* Success - KS_STATUS_SUCCESS
*
* Failure - ks_status_t error code
*
* ARGUMENTS:
*
* mp_p <-> Pointer to our memory pool.
*/
KS_DECLARE(ks_status_t) ks_pool_clear(ks_pool_t *mp_p);
/*
* void *ks_pool_alloc
*
* DESCRIPTION:
*
* Allocate space for bytes inside of an already open memory pool.
*
* RETURNS:
*
* Success - Pointer to the address to use.
*
* Failure - NULL
*
* ARGUMENTS:
*
* mp_p <-> Pointer to the memory pool. If NULL then it will do a
* normal malloc.
*
* byte_size -> Number of bytes to allocate in the pool. Must be >0.
*
*/
KS_DECLARE(void *) ks_pool_alloc(ks_pool_t *mp_p, const unsigned long byte_size);
/*
* void *ks_pool_alloc_ex
*
* DESCRIPTION:
*
* Allocate space for bytes inside of an already open memory pool.
*
* RETURNS:
*
* Success - Pointer to the address to use.
*
* Failure - NULL
*
* ARGUMENTS:
*
* mp_p <-> Pointer to the memory pool. If NULL then it will do a
* normal malloc.
*
* byte_size -> Number of bytes to allocate in the pool. Must be >0.
*
* error_p <- Pointer to integer which, if not NULL, will be set with
* a ks_pool error code.
*/
KS_DECLARE(void *) ks_pool_alloc_ex(ks_pool_t *mp_p, const unsigned long byte_size, ks_status_t *error_p);
/*
* void *ks_pool_calloc
*
* DESCRIPTION:
*
* Allocate space for elements of bytes in the memory pool and zero
* the space afterwards.
*
* RETURNS:
*
* Success - Pointer to the address to use.
*
* Failure - NULL
*
* ARGUMENTS:
*
* mp_p <-> Pointer to the memory pool. If NULL then it will do a
* normal calloc.
*
* ele_n -> Number of elements to allocate.
*
* ele_size -> Number of bytes per element being allocated.
*
*/
KS_DECLARE(void *) ks_pool_calloc(ks_pool_t *mp_p, const unsigned long ele_n, const unsigned long ele_size);
/*
* void *ks_pool_calloc_ex
*
* DESCRIPTION:
*
* Allocate space for elements of bytes in the memory pool and zero
* the space afterwards.
*
* RETURNS:
*
* Success - Pointer to the address to use.
*
* Failure - NULL
*
* ARGUMENTS:
*
* mp_p <-> Pointer to the memory pool. If NULL then it will do a
* normal calloc.
*
* ele_n -> Number of elements to allocate.
*
* ele_size -> Number of bytes per element being allocated.
*
* error_p <- Pointer to integer which, if not NULL, will be set with
* a ks_pool error code.
*/
KS_DECLARE(void *) ks_pool_calloc_ex(ks_pool_t *mp_p, const unsigned long ele_n, const unsigned long ele_size, ks_status_t *error_p);
/*
* int ks_pool_free
*
* DESCRIPTION:
*
* Free an address from a memory pool.
*
* RETURNS:
*
* Success - KS_STATUS_SUCCESS
*
* Failure - ks_status_t error code
*
* ARGUMENTS:
*
* mp_p <-> Pointer to the memory pool. If NULL then it will do a
* normal free.
*
* addr <-> Address to free.
*
*/
KS_DECLARE(ks_status_t) ks_pool_free(ks_pool_t *mp_p, void *addr);
/*
* void *ks_pool_resize
*
* DESCRIPTION:
*
* Reallocate an address in a mmeory pool to a new size.
*
* RETURNS:
*
* Success - Pointer to the address to use.
*
* Failure - NULL
*
* ARGUMENTS:
*
* mp_p <-> Pointer to the memory pool. If NULL then it will do a
* normal realloc.
*
* old_addr -> Previously allocated address.
*
* new_byte_size -> New size of the allocation.
*
*/
KS_DECLARE(void *) ks_pool_resize(ks_pool_t *mp_p, void *old_addr, const unsigned long new_byte_size);
/*
* void *ks_pool_resize_ex
*
* DESCRIPTION:
*
* Reallocate an address in a mmeory pool to a new size.
*
* RETURNS:
*
* Success - Pointer to the address to use.
*
* Failure - NULL
*
* ARGUMENTS:
*
* mp_p <-> Pointer to the memory pool. If NULL then it will do a
* normal realloc.
*
* old_addr -> Previously allocated address.
*
* new_byte_size -> New size of the allocation.
*
* error_p <- Pointer to integer which, if not NULL, will be set with
* a ks_pool error code.
*/
KS_DECLARE(void *) ks_pool_resize_ex(ks_pool_t *mp_p, void *old_addr, const unsigned long new_byte_size, ks_status_t *error_p);
/*
* int ks_pool_stats
*
* DESCRIPTION:
*
* Return stats from the memory pool.
*
* RETURNS:
*
* Success - KS_STATUS_SUCCESS
*
* Failure - ks_status_t error code
*
* ARGUMENTS:
*
* mp_p -> Pointer to the memory pool.
*
* page_size_p <- Pointer to an unsigned integer which, if not NULL,
* will be set to the page-size of the pool.
*
* num_alloced_p <- Pointer to an unsigned long which, if not NULL,
* will be set to the number of pointers currently allocated in pool.
*
* user_alloced_p <- Pointer to an unsigned long which, if not NULL,
* will be set to the number of user bytes allocated in this pool.
*
* max_alloced_p <- Pointer to an unsigned long which, if not NULL,
* will be set to the maximum number of user bytes that have been
* allocated in this pool.
*
* tot_alloced_p <- Pointer to an unsigned long which, if not NULL,
* will be set to the total amount of space (including administrative
* overhead) used by the pool.
*/
KS_DECLARE(ks_status_t) ks_pool_stats(const ks_pool_t *mp_p, unsigned int *page_size_p,
unsigned long *num_alloced_p, unsigned long *user_alloced_p, unsigned long *max_alloced_p, unsigned long *tot_alloced_p);
/*
* int ks_pool_set_log_func
*
* DESCRIPTION:
*
* Set a logging callback function to be called whenever there was a
* memory transaction. See ks_pool_log_func_t.
*
* RETURNS:
*
* Success - KS_STATUS_SUCCESS
*
* Failure - ks_status_t error code
*
* ARGUMENTS:
*
* mp_p <-> Pointer to the memory pool.
*
* log_func -> Log function (defined in ks_pool.h) which will be called
* with each ks_pool transaction.
*/
KS_DECLARE(ks_status_t) ks_pool_set_log_func(ks_pool_t *mp_p, ks_pool_log_func_t log_func);
/*
* int ks_pool_set_max_pages
*
* DESCRIPTION:
*
* Set the maximum number of pages that the library will use. Once it
* hits the limit it will return KS_STATUS_NO_PAGES.
*
* NOTE: if the KS_POOL_FLAG_HEAVY_PACKING is set then this max-pages
* value will include the page with the ks_pool header structure in it.
* If the flag is _not_ set then the max-pages will not include this
* first page.
*
* RETURNS:
*
* Success - KS_STATUS_SUCCESS
*
* Failure - ks_status_t error code
*
* ARGUMENTS:
*
* mp_p <-> Pointer to the memory pool.
*
* max_pages -> Maximum number of pages used by the library.
*/
KS_DECLARE(ks_status_t) ks_pool_set_max_pages(ks_pool_t *mp_p, const unsigned int max_pages);
/*
* const char *ks_pool_strerror
*
* DESCRIPTION:
*
* Return the corresponding string for the error number.
*
* RETURNS:
*
* Success - String equivalient of the error.
*
* Failure - String "invalid error code"
*
* ARGUMENTS:
*
* error -> Error number that we are converting.
*/
KS_DECLARE(const char *) ks_pool_strerror(const ks_status_t error);
KS_DECLARE(ks_status_t) ks_pool_set_cleanup(ks_pool_t *mp_p, void *ptr, void *arg, int type, ks_pool_cleanup_fn_t fn);
#define ks_pool_safe_free(_p, _a) ks_pool_free(_p, _a); (_a) = NULL
/*<<<<<<<<<< This is end of the auto-generated output from fillproto. */
KS_DECLARE(char *) ks_pstrdup(ks_pool_t *pool, const char *str);
KS_DECLARE(char *) ks_pstrndup(ks_pool_t *pool, const char *str, size_t len);
KS_DECLARE(char *) ks_pstrmemdup(ks_pool_t *pool, const char *str, size_t len);
KS_DECLARE(void *) ks_pmemdup(ks_pool_t *pool, const void *buf, size_t len);
KS_DECLARE(char *) ks_pstrcat(ks_pool_t *pool, ...);
KS_END_EXTERN_C
#endif /* ! __KS_POOL_H__ */
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

View File

@ -0,0 +1,81 @@
/*
** 2001 September 22
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
*/
#ifndef KS_PRINTF_H
#define KS_PRINTF_H
#include "ks.h"
KS_BEGIN_EXTERN_C
/**
* This routine is a variant of the "sprintf()" from the
* standard C library. The resulting string is written into memory
* obtained from malloc() so that there is never a possiblity of buffer
* overflow. This routine also implement some additional formatting
* options that are useful for constructing SQL statements.
*
* The strings returned by this routine should be freed by calling
* free().
*
* All of the usual printf formatting options apply. In addition, there
* is a "%q" option. %q works like %s in that it substitutes a null-terminated
* string from the argument list. But %q also doubles every '\'' character.
* %q is designed for use inside a string literal. By doubling each '\''
* character it escapes that character and allows it to be inserted into
* the string.
*
* For example, so some string variable contains text as follows:
*
* char *zText = "It's a happy day!";
*
* We can use this text in an SQL statement as follows:
*
* char *z = ks_mprintf("INSERT INTO TABLES('%q')", zText);
* ks_core_db_exec(db, z, callback1, 0, 0);
* free(z);
*
* Because the %q format string is used, the '\'' character in zText
* is escaped and the SQL generated is as follows:
*
* INSERT INTO table1 VALUES('It''s a happy day!')
*
* This is correct. Had we used %s instead of %q, the generated SQL
* would have looked like this:
*
* INSERT INTO table1 VALUES('It's a happy day!');
*
* This second example is an SQL syntax error. As a general rule you
* should always use %q instead of %s when inserting text into a string
* literal.
*/
KS_DECLARE(char *) ks_mprintf(const char *zFormat, ...);
KS_DECLARE(char *) ks_vmprintf(const char *zFormat, va_list ap);
KS_DECLARE(char *) ks_snprintfv(char *zBuf, int n, const char *zFormat, ...);
KS_DECLARE(char *) ks_vsnprintf(char *zbuf, int n, const char *zFormat, va_list ap);
KS_DECLARE(char *) ks_vpprintf(ks_pool_t *pool, const char *zFormat, va_list ap);
KS_DECLARE(char *) ks_pprintf(ks_pool_t *pool, const char *zFormat, ...);
KS_END_EXTERN_C
#endif /* KS_PRINTF_H */
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2007-2015, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _KS_Q_H_
#define _KS_Q_H_
#include "ks.h"
KS_BEGIN_EXTERN_C
KS_DECLARE(ks_status_t) ks_q_pop_timeout(ks_q_t *q, void **ptr, uint32_t timeout);
KS_DECLARE(ks_status_t) ks_q_wake(ks_q_t *q);
KS_DECLARE(ks_status_t) ks_q_flush(ks_q_t *q);
KS_DECLARE(ks_status_t) ks_q_set_flush_fn(ks_q_t *q, ks_flush_fn_t fn, void *flush_data);
KS_DECLARE(ks_status_t) ks_q_wait(ks_q_t *q);
KS_DECLARE(ks_size_t) ks_q_term(ks_q_t *q);
KS_DECLARE(ks_size_t) ks_q_size(ks_q_t *q);
KS_DECLARE(ks_status_t) ks_q_destroy(ks_q_t **qP);
KS_DECLARE(ks_status_t) ks_q_create(ks_q_t **qP, ks_pool_t *pool, ks_size_t maxlen);
KS_DECLARE(ks_status_t) ks_q_push(ks_q_t *q, void *ptr);
KS_DECLARE(ks_status_t) ks_q_trypush(ks_q_t *q, void *ptr);
KS_DECLARE(ks_status_t) ks_q_pop(ks_q_t *q, void **ptr);
KS_DECLARE(ks_status_t) ks_q_trypop(ks_q_t *q, void **ptr);
KS_END_EXTERN_C
#endif /* defined(_KS_Q_H_) */
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

View File

@ -0,0 +1,56 @@
/*
* Cross Platform random/uuid abstraction
* Copyright(C) 2015 Michael Jerris
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so.
*
* This work is provided under this license on an "as is" basis, without warranty of any kind,
* either expressed or implied, including, without limitation, warranties that the covered code
* is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire
* risk as to the quality and performance of the covered code is with you. Should any covered
* code prove defective in any respect, you (not the initial developer or any other contributor)
* assume the cost of any necessary servicing, repair or correction. This disclaimer of warranty
* constitutes an essential part of this license. No use of any covered code is authorized hereunder
* except under this disclaimer.
*
*/
#include "ks.h"
#ifndef _KS_RNG_H
#define _KS_RNG_H
KS_BEGIN_EXTERN_C
#ifdef WIN32
#include <Rpc.h>
typedef UUID uuid_t;
#else
#include <uuid/uuid.h>
#endif
KS_DECLARE(uuid_t *) ks_uuid(uuid_t *uuid);
KS_DECLARE(char *) ks_uuid_str(ks_pool_t *pool, uuid_t *uuid);
KS_DECLARE(ks_status_t) ks_rng_init(void);
KS_DECLARE(ks_status_t) ks_rng_shutdown(void);
KS_DECLARE(size_t) ks_rng_get_data(uint8_t* buffer, size_t length);
KS_DECLARE(size_t) ks_rng_add_entropy(const uint8_t *buffer, size_t length);
KS_DECLARE(size_t) ks_rng_seed_data(uint8_t *seed, size_t length);
KS_END_EXTERN_C
#endif
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

View File

@ -0,0 +1,129 @@
/*
* Copyright (c) 2007-2014, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _KS_SOCKET_H_
#define _KS_SOCKET_H_
#include "ks.h"
#ifndef WIN32
#include <poll.h>
#endif
KS_BEGIN_EXTERN_C
#define KS_SO_NONBLOCK 2999
#ifdef WIN32
static __inline int ks_errno(void)
{
return WSAGetLastError();
}
static __inline int ks_errno_is_blocking(int errcode)
{
return errcode == WSAEWOULDBLOCK || errcode == WSAEINPROGRESS || errcode == 35 || errcode == 730035;
}
static __inline int ks_errno_is_interupt(int errcode)
{
return 0;
}
#else
static inline int ks_errno(void)
{
return errno;
}
static inline int ks_errno_is_blocking(int errcode)
{
return errcode == EAGAIN || errcode == EWOULDBLOCK || errcode == EINPROGRESS || errcode == EINTR || errcode == ETIMEDOUT || errcode == 35 || errcode == 730035;
}
static inline int ks_errno_is_interupt(int errcode)
{
return errcode == EINTR;
}
#endif
static __inline int ks_socket_valid(ks_socket_t s) {
return s != KS_SOCK_INVALID;
}
#define KS_SA_INIT {AF_INET};
KS_DECLARE(ks_status_t) ks_socket_send(ks_socket_t sock, void *data, ks_size_t *datalen);
KS_DECLARE(ks_status_t) ks_socket_recv(ks_socket_t sock, void *data, ks_size_t *datalen);
KS_DECLARE(ks_status_t) ks_socket_sendto(ks_socket_t sock, void *data, ks_size_t *datalen, ks_sockaddr_t *addr);
KS_DECLARE(ks_status_t) ks_socket_recvfrom(ks_socket_t sock, void *data, ks_size_t *datalen, ks_sockaddr_t *addr);
typedef struct pollfd *ks_ppollfd_t;
KS_DECLARE(int) ks_poll(ks_ppollfd_t fds, uint32_t nfds, int timeout);
KS_DECLARE(ks_status_t) ks_socket_option(ks_socket_t socket, int option_name, ks_bool_t enabled);
KS_DECLARE(ks_status_t) ks_socket_sndbuf(ks_socket_t socket, int bufsize);
KS_DECLARE(ks_status_t) ks_socket_rcvbuf(ks_socket_t socket, int bufsize);
KS_DECLARE(int) ks_wait_sock(ks_socket_t sock, uint32_t ms, ks_poll_t flags);
KS_DECLARE(ks_socket_t) ks_socket_connect(int type, int protocol, ks_sockaddr_t *addr);
KS_DECLARE(ks_status_t) ks_addr_bind(ks_socket_t server_sock, ks_sockaddr_t *addr);
KS_DECLARE(const char *) ks_addr_get_host(ks_sockaddr_t *addr);
KS_DECLARE(ks_port_t) ks_addr_get_port(ks_sockaddr_t *addr);
KS_DECLARE(int) ks_addr_cmp(const ks_sockaddr_t *sa1, const ks_sockaddr_t *sa2);
KS_DECLARE(ks_status_t) ks_addr_copy(ks_sockaddr_t *addr, const ks_sockaddr_t *src_addr);
KS_DECLARE(ks_status_t) ks_addr_set(ks_sockaddr_t *addr, const char *host, ks_port_t port, int family);
KS_DECLARE(ks_status_t) ks_addr_set_raw(ks_sockaddr_t *addr, void *data, ks_port_t port, int family);
KS_DECLARE(ks_status_t) ks_addr_raw_data(const ks_sockaddr_t *addr, void **data, ks_size_t *datalen);
KS_DECLARE(ks_status_t) ks_listen(const char *host, ks_port_t port, int family, int backlog, ks_listen_callback_t callback, void *user_data);
KS_DECLARE(ks_status_t) ks_socket_shutdown(ks_socket_t sock, int how);
KS_DECLARE(ks_status_t) ks_socket_close(ks_socket_t *sock);
KS_DECLARE(ks_status_t) ks_ip_route(char *buf, int len, const char *route_ip);
KS_DECLARE(ks_status_t) ks_find_local_ip(char *buf, int len, int *mask, int family, const char *route_ip);
KS_DECLARE(ks_status_t) ks_listen_sock(ks_socket_t server_sock, ks_sockaddr_t *addr, int backlog, ks_listen_callback_t callback, void *user_data);
KS_END_EXTERN_C
#endif /* defined(_KS_SOCKET_H_) */
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

View File

@ -0,0 +1,28 @@
#ifndef _KS_SSL_H
#define _KS_SSL_H
#include "ks.h"
#include <openssl/ssl.h>
#include <openssl/engine.h>
KS_BEGIN_EXTERN_C
KS_DECLARE(void) ks_ssl_init_ssl_locks(void);
KS_DECLARE(void) ks_ssl_destroy_ssl_locks(void);
KS_DECLARE(int) ks_gen_cert(const char *dir, const char *file);
KS_END_EXTERN_C
#endif /* defined(_KS_SSL_H) */
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

View File

@ -1,6 +1,6 @@
/*
/*
* Cross Platform Thread/Mutex abstraction
* Copyright(C) 2007 Michael Jerris
* Copyright(C) 2015 Michael Jerris
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
@ -13,38 +13,122 @@
* code prove defective in any respect, you (not the initial developer or any other contributor)
* assume the cost of any necessary servicing, repair or correction. This disclaimer of warranty
* constitutes an essential part of this license. No use of any covered code is authorized hereunder
* except under this disclaimer.
* except under this disclaimer.
*
*/
#ifndef _KS_THREADMUTEX_H
#define _KS_THREADMUTEX_H
#include "ks.h"
#ifdef __cplusplus
extern "C" {
#endif /* defined(__cplusplus) */
KS_BEGIN_EXTERN_C
typedef struct ks_mutex ks_mutex_t;
typedef struct ks_thread ks_thread_t;
typedef void *(*ks_thread_function_t) (ks_thread_t *, void *);
#ifdef WIN32
#include <process.h>
#define KS_THREAD_CALLING_CONVENTION __stdcall
#else
#include <pthread.h>
#define KS_THREAD_CALLING_CONVENTION
#endif
KS_DECLARE(ks_status_t) ks_thread_create_detached(ks_thread_function_t func, void *data);
ks_status_t ks_thread_create_detached_ex(ks_thread_function_t func, void *data, size_t stack_size);
void ks_thread_override_default_stacksize(size_t size);
KS_DECLARE(ks_status_t) ks_mutex_create(ks_mutex_t **mutex);
KS_DECLARE(ks_status_t) ks_mutex_destroy(ks_mutex_t **mutex);
KS_DECLARE(ks_status_t) ks_mutex_lock(ks_mutex_t *mutex);
KS_DECLARE(ks_status_t) ks_mutex_trylock(ks_mutex_t *mutex);
KS_DECLARE(ks_status_t) ks_mutex_unlock(ks_mutex_t *mutex);
#define KS_THREAD_DEFAULT_STACK 240 * 1024
#ifdef __cplusplus
}
#endif /* defined(__cplusplus) */
typedef struct ks_thread ks_thread_t;
typedef void *(*ks_thread_function_t) (ks_thread_t *, void *);
#endif /* defined(_KS_THREADMUTEX_H) */
typedef
#ifdef WIN32
void *
#else
pthread_t
#endif
ks_thread_os_handle_t;
struct ks_thread {
ks_pool_t *pool;
#ifdef WIN32
void *handle;
#else
pthread_t handle;
pthread_attr_t attribute;
#endif
void *private_data;
ks_thread_function_t function;
size_t stack_size;
uint32_t flags;
uint8_t running;
uint8_t priority;
void *return_data;
};
typedef enum {
KS_PRI_LOW = 1,
KS_PRI_NORMAL = 10,
KS_PRI_IMPORTANT = 50,
KS_PRI_REALTIME = 99,
} ks_thread_priority_t;
typedef enum {
KS_THREAD_FLAG_DEFAULT = 0,
KS_THREAD_FLAG_DETATCHED = (1 << 0)
} ks_thread_flags_t;
KS_DECLARE(int) ks_thread_set_priority(int nice_val);
KS_DECLARE(ks_thread_os_handle_t) ks_thread_self(void);
KS_DECLARE(ks_thread_os_handle_t) ks_thread_os_handle(ks_thread_t *thread);
KS_DECLARE(ks_status_t) ks_thread_create_ex(ks_thread_t **thread, ks_thread_function_t func, void *data,
uint32_t flags, size_t stack_size, ks_thread_priority_t priority, ks_pool_t *pool);
KS_DECLARE(ks_status_t) ks_thread_join(ks_thread_t *thread);
KS_DECLARE(uint8_t) ks_thread_priority(ks_thread_t *thread);
#define ks_thread_create(thread, func, data, pool) \
ks_thread_create_ex(thread, func, data, KS_THREAD_FLAG_DEFAULT, KS_THREAD_DEFAULT_STACK, KS_PRI_NORMAL, pool)
typedef enum {
KS_MUTEX_FLAG_DEFAULT = 0,
KS_MUTEX_FLAG_NON_RECURSIVE = (1 << 0)
} ks_mutex_flags_t;
typedef struct ks_mutex ks_mutex_t;
KS_DECLARE(ks_status_t) ks_mutex_create(ks_mutex_t **mutex, unsigned int flags, ks_pool_t *pool);
KS_DECLARE(ks_status_t) ks_mutex_lock(ks_mutex_t *mutex);
KS_DECLARE(ks_status_t) ks_mutex_trylock(ks_mutex_t *mutex);
KS_DECLARE(ks_status_t) ks_mutex_unlock(ks_mutex_t *mutex);
KS_DECLARE(ks_status_t) ks_mutex_destroy(ks_mutex_t **mutex);
typedef struct ks_cond ks_cond_t;
KS_DECLARE(ks_status_t) ks_cond_create(ks_cond_t **cond, ks_pool_t *pool);
KS_DECLARE(ks_status_t) ks_cond_create_ex(ks_cond_t **cond, ks_pool_t *pool, ks_mutex_t *mutex);
KS_DECLARE(ks_status_t) ks_cond_lock(ks_cond_t *cond);
KS_DECLARE(ks_status_t) ks_cond_trylock(ks_cond_t *cond);
KS_DECLARE(ks_status_t) ks_cond_unlock(ks_cond_t *cond);
KS_DECLARE(ks_status_t) ks_cond_signal(ks_cond_t *cond);
KS_DECLARE(ks_status_t) ks_cond_broadcast(ks_cond_t *cond);
KS_DECLARE(ks_status_t) ks_cond_try_signal(ks_cond_t *cond);
KS_DECLARE(ks_status_t) ks_cond_try_broadcast(ks_cond_t *cond);
KS_DECLARE(ks_status_t) ks_cond_wait(ks_cond_t *cond);
KS_DECLARE(ks_status_t) ks_cond_timedwait(ks_cond_t *cond, ks_time_t ms);
KS_DECLARE(ks_status_t) ks_cond_destroy(ks_cond_t **cond);
KS_DECLARE(ks_mutex_t *) ks_cond_get_mutex(ks_cond_t *cond);
typedef struct ks_rwl ks_rwl_t;
KS_DECLARE(ks_status_t) ks_rwl_create(ks_rwl_t **rwlock, ks_pool_t *pool);
KS_DECLARE(ks_status_t) ks_rwl_read_lock(ks_rwl_t *rwlock);
KS_DECLARE(ks_status_t) ks_rwl_write_lock(ks_rwl_t *rwlock);
KS_DECLARE(ks_status_t) ks_rwl_try_read_lock(ks_rwl_t *rwlock);
KS_DECLARE(ks_status_t) ks_rwl_try_write_lock(ks_rwl_t *rwlock);
KS_DECLARE(ks_status_t) ks_rwl_read_unlock(ks_rwl_t *rwlock);
KS_DECLARE(ks_status_t) ks_rwl_write_unlock(ks_rwl_t *rwlock);
KS_DECLARE(ks_status_t) ks_rwl_destroy(ks_rwl_t **rwlock);
KS_END_EXTERN_C
#endif /* defined(_KS_THREADMUTEX_H) */
/* For Emacs:
* Local Variables:

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2007-2015, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _KS_TIME_H_
#define _KS_TIME_H_
#include "ks.h"
KS_BEGIN_EXTERN_C
#define KS_USEC_PER_SEC 1000000
#define ks_time_sec(time) ((time) / KS_USEC_PER_SEC)
#define ks_time_usec(time) ((time) % KS_USEC_PER_SEC)
#define ks_time_nsec(time) (((time) % KS_USEC_PER_SEC) * 1000)
#define ks_sleep_ms(_t) ks_sleep(_t * 1000)
KS_DECLARE(ks_time_t) ks_time_now(void);
KS_DECLARE(ks_time_t) ks_time_now_sec(void);
KS_DECLARE(void) ks_sleep(ks_time_t microsec);
KS_END_EXTERN_C
#endif /* defined(_KS_TIME_H_) */
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007-2014, Anthony Minessale II
* Copyright (c) 2007-2015, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -34,113 +34,119 @@
#ifndef _KS_TYPES_H_
#define _KS_TYPES_H_
#include <stdarg.h>
#include "ks.h"
#ifdef __cplusplus
extern "C" {
#endif /* defined(__cplusplus) */
KS_BEGIN_EXTERN_C
#include <ks_platform.h>
#define KS_STR2ENUM_P(_FUNC1, _FUNC2, _TYPE) KS_DECLARE(_TYPE) _FUNC1 (const char *name); KS_DECLARE(const char *) _FUNC2 (_TYPE type);
#define KS_STR2ENUM(_FUNC1, _FUNC2, _TYPE, _STRINGS, _MAX) \
KS_DECLARE(_TYPE) _FUNC1 (const char *name) \
{ \
int i; \
_TYPE t = _MAX ; \
\
for (i = 0; i < _MAX ; i++) { \
if (!strcasecmp(name, _STRINGS[i])) { \
t = (_TYPE) i; \
break; \
} \
} \
\
return t; \
} \
KS_DECLARE(const char *) _FUNC2 (_TYPE type) \
{ \
if (type > _MAX) { \
type = _MAX; \
} \
return _STRINGS[(int)type]; \
} \
#define KS_ENUM_NAMES(_NAME, _STRINGS) static const char * _NAME [] = { _STRINGS , NULL };
#define KS_VA_NONE "%s", ""
typedef enum {
KS_POLL_READ = (1 << 0),
KS_POLL_WRITE = (1 << 1),
KS_POLL_ERROR = (1 << 2)
} ks_poll_t;
typedef enum {
KS_POLL_READ = (1 << 0),
KS_POLL_WRITE = (1 << 1),
KS_POLL_ERROR = (1 << 2)
} ks_poll_t;
typedef uint16_t ks_port_t;
typedef size_t ks_size_t;
#ifdef WIN32
#define KS_SEQ_FWHITE FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY
#define KS_SEQ_BWHITE FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
#define KS_SEQ_FRED FOREGROUND_RED | FOREGROUND_INTENSITY
#define KS_SEQ_BRED FOREGROUND_RED
#define KS_SEQ_FMAGEN FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY
#define KS_SEQ_BMAGEN FOREGROUND_BLUE | FOREGROUND_RED
#define KS_SEQ_FCYAN FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY
#define KS_SEQ_BCYAN FOREGROUND_GREEN | FOREGROUND_BLUE
#define KS_SEQ_FGREEN FOREGROUND_GREEN | FOREGROUND_INTENSITY
#define KS_SEQ_BGREEN FOREGROUND_GREEN
#define KS_SEQ_FYELLOW FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY
#define KS_SEQ_BYELLOW FOREGROUND_RED | FOREGROUND_GREEN
#define KS_SEQ_DEFAULT_COLOR KS_SEQ_FWHITE
#define KS_SEQ_FBLUE FOREGROUND_BLUE | FOREGROUND_INTENSITY
#define KS_SEQ_BBLUE FOREGROUND_BLUE
#define KS_SEQ_FBLACK 0 | FOREGROUND_INTENSITY
#define KS_SEQ_BBLACK 0
#else
#define KS_SEQ_ESC "\033["
/* Ansi Control character suffixes */
#define KS_SEQ_HOME_CHAR 'H'
#define KS_SEQ_HOME_CHAR_STR "H"
#define KS_SEQ_CLEARLINE_CHAR '1'
#define KS_SEQ_CLEARLINE_CHAR_STR "1"
#define KS_SEQ_CLEARLINEEND_CHAR "K"
#define KS_SEQ_CLEARSCR_CHAR0 '2'
#define KS_SEQ_CLEARSCR_CHAR1 'J'
#define KS_SEQ_CLEARSCR_CHAR "2J"
#define KS_SEQ_DEFAULT_COLOR KS_SEQ_ESC KS_SEQ_END_COLOR /* Reset to Default fg/bg color */
#define KS_SEQ_AND_COLOR ";" /* To add multiple color definitions */
#define KS_SEQ_END_COLOR "m" /* To end color definitions */
/* Foreground colors values */
#define KS_SEQ_F_BLACK "30"
#define KS_SEQ_F_RED "31"
#define KS_SEQ_F_GREEN "32"
#define KS_SEQ_F_YELLOW "33"
#define KS_SEQ_F_BLUE "34"
#define KS_SEQ_F_MAGEN "35"
#define KS_SEQ_F_CYAN "36"
#define KS_SEQ_F_WHITE "37"
/* Background colors values */
#define KS_SEQ_B_BLACK "40"
#define KS_SEQ_B_RED "41"
#define KS_SEQ_B_GREEN "42"
#define KS_SEQ_B_YELLOW "43"
#define KS_SEQ_B_BLUE "44"
#define KS_SEQ_B_MAGEN "45"
#define KS_SEQ_B_CYAN "46"
#define KS_SEQ_B_WHITE "47"
/* Preset escape sequences - Change foreground colors only */
#define KS_SEQ_FBLACK KS_SEQ_ESC KS_SEQ_F_BLACK KS_SEQ_END_COLOR
#define KS_SEQ_FRED KS_SEQ_ESC KS_SEQ_F_RED KS_SEQ_END_COLOR
#define KS_SEQ_FGREEN KS_SEQ_ESC KS_SEQ_F_GREEN KS_SEQ_END_COLOR
#define KS_SEQ_FYELLOW KS_SEQ_ESC KS_SEQ_F_YELLOW KS_SEQ_END_COLOR
#define KS_SEQ_FBLUE KS_SEQ_ESC KS_SEQ_F_BLUE KS_SEQ_END_COLOR
#define KS_SEQ_FMAGEN KS_SEQ_ESC KS_SEQ_F_MAGEN KS_SEQ_END_COLOR
#define KS_SEQ_FCYAN KS_SEQ_ESC KS_SEQ_F_CYAN KS_SEQ_END_COLOR
#define KS_SEQ_FWHITE KS_SEQ_ESC KS_SEQ_F_WHITE KS_SEQ_END_COLOR
#define KS_SEQ_BBLACK KS_SEQ_ESC KS_SEQ_B_BLACK KS_SEQ_END_COLOR
#define KS_SEQ_BRED KS_SEQ_ESC KS_SEQ_B_RED KS_SEQ_END_COLOR
#define KS_SEQ_BGREEN KS_SEQ_ESC KS_SEQ_B_GREEN KS_SEQ_END_COLOR
#define KS_SEQ_BYELLOW KS_SEQ_ESC KS_SEQ_B_YELLOW KS_SEQ_END_COLOR
#define KS_SEQ_BBLUE KS_SEQ_ESC KS_SEQ_B_BLUE KS_SEQ_END_COLOR
#define KS_SEQ_BMAGEN KS_SEQ_ESC KS_SEQ_B_MAGEN KS_SEQ_END_COLOR
#define KS_SEQ_BCYAN KS_SEQ_ESC KS_SEQ_B_CYAN KS_SEQ_END_COLOR
#define KS_SEQ_BWHITE KS_SEQ_ESC KS_SEQ_B_WHITE KS_SEQ_END_COLOR
/* Preset escape sequences */
#define KS_SEQ_HOME KS_SEQ_ESC KS_SEQ_HOME_CHAR_STR
#define KS_SEQ_CLEARLINE KS_SEQ_ESC KS_SEQ_CLEARLINE_CHAR_STR
#define KS_SEQ_CLEARLINEEND KS_SEQ_ESC KS_SEQ_CLEARLINEEND_CHAR
#define KS_SEQ_CLEARSCR KS_SEQ_ESC KS_SEQ_CLEARSCR_CHAR KS_SEQ_HOME
#endif
typedef enum {
KS_STATUS_SUCCESS,
KS_STATUS_FAIL,
KS_STATUS_BREAK,
KS_STATUS_DISCONNECTED,
KS_STATUS_GENERR,
KS_STATUS_INACTIVE,
KS_STATUS_TIMEOUT,
/* Memory pool errors */
KS_STATUS_ARG_NULL, /* function argument is null */
KS_STATUS_ARG_INVALID, /* function argument is invalid */
KS_STATUS_PNT, /* invalid ks_pool pointer */
KS_STATUS_POOL_OVER, /* ks_pool structure was overwritten */
KS_STATUS_PAGE_SIZE, /* could not get system page-size */
KS_STATUS_OPEN_ZERO, /* could not open /dev/zero */
KS_STATUS_NO_MEM, /* no memory available */
KS_STATUS_MMAP, /* problems with mmap */
KS_STATUS_SIZE, /* error processing requested size */
KS_STATUS_TOO_BIG, /* allocation exceeded max size */
KS_STATUS_MEM, /* invalid memory address */
KS_STATUS_MEM_OVER, /* memory lower bounds overwritten */
KS_STATUS_NOT_FOUND, /* memory block not found in pool */
KS_STATUS_IS_FREE, /* memory block already free */
KS_STATUS_BLOCK_STAT, /* invalid internal block status */
KS_STATUS_FREE_ADDR, /* invalid internal free address */
KS_STATUS_NO_PAGES, /* ran out of pages in pool */
KS_STATUS_ALLOC, /* calloc,malloc,free,realloc failed */
KS_STATUS_PNT_OVER, /* pointer structure was overwritten */
KS_STATUS_INVALID_POINTER, /* address is not valid */
/* Always insert new entries above this line*/
KS_STATUS_COUNT
} ks_status_t;
typedef int16_t ks_port_t;
typedef size_t ks_size_t;
#define STATUS_STRINGS\
"SUCCESS",\
"FAIL",\
"BREAK",\
"DISCONNECTED",\
"GENERR",\
"INACTIVE",\
"TIMEOUT",\
"ARG_NULL",\
"ARG_INVALID",\
"PNT",\
"POOL_OVER",\
"PAGE_SIZE",\
"OPEN_ZERO",\
"NO_MEM",\
"MMAP",\
"SIZE",\
"TOO_BIG",\
"MEM",\
"MEM_OVER",\
"NOT_FOUN",\
"IS_FREE",\
"BLOCK_STAT",\
"FREE_ADDR",\
"NO_PAGES",\
"ALLOC",\
"PNT_OVER",\
"INVALID_POINTER",\
/* insert new entries before this */\
"COUNT"
typedef enum {
KS_SUCCESS,
KS_FAIL,
KS_BREAK,
KS_DISCONNECTED,
KS_GENERR
} ks_status_t;
KS_STR2ENUM_P(ks_str2ks_status, ks_status2str, ks_status_t)
/*! \brief Used internally for truth test */
typedef enum {
KS_TRUE = 1,
KS_FALSE = 0
} ks_bool_t;
typedef enum {
KS_TRUE = 1,
KS_FALSE = 0
} ks_bool_t;
#ifndef __FUNCTION__
#define __FUNCTION__ (const char *)__func__
@ -164,16 +170,49 @@ typedef enum {
#define KS_LOG_CRIT KS_PRE, KS_LOG_LEVEL_CRIT
#define KS_LOG_ALERT KS_PRE, KS_LOG_LEVEL_ALERT
#define KS_LOG_EMERG KS_PRE, KS_LOG_LEVEL_EMERG
typedef void (*ks_logger_t)(const char *file, const char *func, int line, int level, const char *fmt, ...);
typedef void (*ks_listen_callback_t)(ks_socket_t server_sock, ks_socket_t client_sock, struct sockaddr_in *addr);
struct ks_pool_s;
#ifdef __cplusplus
}
#endif /* defined(__cplusplus) */
typedef struct ks_pool_s ks_pool_t;
typedef void (*ks_hash_destructor_t)(void *ptr);
typedef enum {
KS_MPCL_ANNOUNCE,
KS_MPCL_TEARDOWN,
KS_MPCL_DESTROY
} ks_pool_cleanup_action_t;
#endif /* defined(_KS_TYPES_H_) */
typedef enum {
KS_MPCL_FREE,
KS_MPCL_GLOBAL_FREE,
} ks_pool_cleanup_type_t;
typedef union {
struct sockaddr_in v4;
struct sockaddr_in6 v6;
} ks_sockaddr_in_t;
typedef struct {
int family;
ks_sockaddr_in_t v;
ks_port_t port;
char host[48];
} ks_sockaddr_t;
typedef void (*ks_pool_cleanup_fn_t) (ks_pool_t *mpool, void *ptr, void *arg, int type, ks_pool_cleanup_action_t action, ks_pool_cleanup_type_t ctype);
typedef void (*ks_logger_t) (const char *file, const char *func, int line, int level, const char *fmt, ...);
typedef void (*ks_listen_callback_t) (ks_socket_t server_sock, ks_socket_t client_sock, ks_sockaddr_t *addr, void *user_data);
typedef int64_t ks_time_t;
struct ks_q_s;
typedef struct ks_q_s ks_q_t;
typedef void (*ks_flush_fn_t)(ks_q_t *q, void *ptr, void *flush_data);
KS_END_EXTERN_C
#endif /* defined(_KS_TYPES_H_) */
/* For Emacs:
* Local Variables:
@ -185,4 +224,3 @@ typedef void (*ks_listen_callback_t)(ks_socket_t server_sock, ks_socket_t client
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

View File

@ -0,0 +1,192 @@
/*
* Copyright (c) 2007-2015, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _KS_UTP_H_
#define _KS_UTP_H_
#include "ks.h"
KS_BEGIN_EXTERN_C
typedef struct utp_socket utp_socket_t;
typedef struct utp_context utp_context_t;
enum {
UTP_UDP_DONTFRAG = 2, // Used to be a #define as UDP_IP_DONTFRAG
};
enum {
/* socket has reveived syn-ack (notification only for outgoing connection completion) this implies writability */
UTP_STATE_CONNECT = 1,
/* socket is able to send more data */
UTP_STATE_WRITABLE = 2,
/* connection closed */
UTP_STATE_EOF = 3,
/* socket is being destroyed, meaning all data has been sent if possible. it is not valid to refer to the socket after this state change occurs */
UTP_STATE_DESTROYING = 4,
};
/* Errors codes that can be passed to UTP_ON_ERROR callback */
enum {
UTP_ECONNREFUSED = 0,
UTP_ECONNRESET,
UTP_ETIMEDOUT,
};
enum {
/* callback names */
UTP_ON_FIREWALL = 0,
UTP_ON_ACCEPT,
UTP_ON_CONNECT,
UTP_ON_ERROR,
UTP_ON_READ,
UTP_ON_OVERHEAD_STATISTICS,
UTP_ON_STATE_CHANGE,
UTP_GET_READ_BUFFER_SIZE,
UTP_ON_DELAY_SAMPLE,
UTP_GET_UDP_MTU,
UTP_GET_UDP_OVERHEAD,
UTP_GET_MILLISECONDS,
UTP_GET_MICROSECONDS,
UTP_GET_RANDOM,
UTP_LOG,
UTP_SENDTO,
/* context and socket options that may be set/queried */
UTP_LOG_NORMAL,
UTP_LOG_MTU,
UTP_LOG_DEBUG,
UTP_SNDBUF,
UTP_RCVBUF,
UTP_TARGET_DELAY,
/* must be last */
UTP_ARRAY_SIZE,
};
typedef struct {
utp_context_t *context;
utp_socket_t *socket;
size_t len;
uint32_t flags;
int callback_type;
const uint8_t *buf;
union {
const struct sockaddr *address;
int send;
int sample_ms;
int error_code;
int state;
} d1;
union {
socklen_t address_len;
int type;
} d2;
} utp_callback_arguments;
typedef uint64_t utp_callback_t (utp_callback_arguments *);
/* Returned by utp_get_context_stats() */
typedef struct {
uint32_t _nraw_recv[5]; // total packets recieved less than 300/600/1200/MTU bytes fpr all connections (context-wide)
uint32_t _nraw_send[5]; // total packets sent less than 300/600/1200/MTU bytes for all connections (context-wide)
} utp_context_stats;
// Returned by utp_get_stats()
typedef struct {
uint64_t nbytes_recv; // total bytes received
uint64_t nbytes_xmit; // total bytes transmitted
uint32_t rexmit; // retransmit counter
uint32_t fastrexmit; // fast retransmit counter
uint32_t nxmit; // transmit counter
uint32_t nrecv; // receive counter (total)
uint32_t nduprecv; // duplicate receive counter
uint32_t mtu_guess; // Best guess at MTU
} utp_socket_stats;
#define UTP_IOV_MAX 1024
/* For utp_writev, to writes data from multiple buffers */
struct utp_iovec {
void *iov_base;
size_t iov_len;
};
// Public Functions
utp_context_t* utp_init (int version);
void utp_destroy (utp_context_t *ctx);
void utp_set_callback (utp_context_t *ctx, int callback_name, utp_callback_t *proc);
void* utp_context_set_userdata (utp_context_t *ctx, void *userdata);
void* utp_context_get_userdata (utp_context_t *ctx);
int utp_context_set_option (utp_context_t *ctx, int opt, int val);
int utp_context_get_option (utp_context_t *ctx, int opt);
int utp_process_udp (utp_context_t *ctx, const uint8_t *buf, size_t len, const struct sockaddr *to, socklen_t tolen);
int utp_process_icmp_error (utp_context_t *ctx, const uint8_t *buffer, size_t len, const struct sockaddr *to, socklen_t tolen);
int utp_process_icmp_fragmentation (utp_context_t *ctx, const uint8_t *buffer, size_t len, const struct sockaddr *to, socklen_t tolen, uint16_t next_hop_mtu);
void utp_check_timeouts (utp_context_t *ctx);
void utp_issue_deferred_acks (utp_context_t *ctx);
utp_context_stats* utp_get_context_stats (utp_context_t *ctx);
utp_socket_t* utp_create_socket (utp_context_t *ctx);
void* utp_set_userdata (utp_socket_t *s, void *userdata);
void* utp_get_userdata (utp_socket_t *s);
int utp_setsockopt (utp_socket_t *s, int opt, int val);
int utp_getsockopt (utp_socket_t *s, int opt);
int utp_connect (utp_socket_t *s, const struct sockaddr *to, socklen_t tolen);
ssize_t utp_write (utp_socket_t *s, void *buf, size_t count);
ssize_t utp_writev (utp_socket_t *s, struct utp_iovec *iovec, size_t num_iovecs);
int utp_getpeername (utp_socket_t *s, struct sockaddr *addr, socklen_t *addrlen);
void utp_read_drained (utp_socket_t *s);
int utp_get_delays (utp_socket_t *s, uint32_t *ours, uint32_t *theirs, uint32_t *age);
utp_socket_stats* utp_get_stats (utp_socket_t *s);
utp_context_t* utp_get_context (utp_socket_t *s);
void utp_close (utp_socket_t *s);
KS_END_EXTERN_C
#endif /* defined(_KS_UTP_H_) */
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 2007-2014, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _KWS_H
#define _KWS_H
#define WEBSOCKET_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
#define B64BUFFLEN 1024
#include "ks.h"
KS_BEGIN_EXTERN_C
typedef enum {
WS_NONE = 0,
WS_NORMAL = 1000,
WS_PROTO_ERR = 1002,
WS_DATA_TOO_BIG = 1009
} kws_cause_t;
typedef enum {
WSOC_CONTINUATION = 0x0,
WSOC_TEXT = 0x1,
WSOC_BINARY = 0x2,
WSOC_CLOSE = 0x8,
WSOC_PING = 0x9,
WSOC_PONG = 0xA
} kws_opcode_t;
typedef enum {
KWS_CLIENT,
KWS_SERVER
} kws_type_t;
typedef enum {
KWS_CLOSE_SOCK,
KWS_BLOCK,
KWS_STAY_OPEN
} kws_flag_t;
struct kws_s;
typedef struct kws_s kws_t;
KS_DECLARE(ks_ssize_t) kws_read_frame(kws_t *kws, kws_opcode_t *oc, uint8_t **data);
KS_DECLARE(ks_ssize_t) kws_write_frame(kws_t *kws, kws_opcode_t oc, void *data, ks_size_t bytes);
KS_DECLARE(ks_ssize_t) kws_raw_read(kws_t *kws, void *data, ks_size_t bytes, int block);
KS_DECLARE(ks_ssize_t) kws_raw_write(kws_t *kws, void *data, ks_size_t bytes);
KS_DECLARE(ks_status_t) kws_init(kws_t **kwsP, ks_socket_t sock, SSL_CTX *ssl_ctx, const char *client_data, kws_flag_t flags, ks_pool_t *pool);
KS_DECLARE(ks_ssize_t) kws_close(kws_t *kws, int16_t reason);
KS_DECLARE(void) kws_destroy(kws_t **kwsP);
KS_DECLARE(ks_status_t) kws_get_buffer(kws_t *kws, char **bufP, ks_size_t *buflen);
#if 0
static inline uint64_t get_unaligned_uint64(const void *p)
{
const struct { uint64_t d; } __attribute__((packed)) *pp = p;
return pp->d;
}
#endif
KS_END_EXTERN_C
#endif /* defined(_KWS_H_) */
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

View File

@ -32,20 +32,20 @@ extern "C" {
#include <sys/types.h>
#ifndef SIMCLIST_NO_DUMPRESTORE
# ifndef _WIN32
# include <sys/time.h> /* list_dump_info_t's struct timeval */
# else
# include <time.h>
# endif
#ifndef _WIN32
#include <sys/time.h> /* list_dump_info_t's struct timeval */
#else
#include <time.h>
#endif
#endif
/* Be friend of both C90 and C99 compilers */
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
/* "inline" and "restrict" are keywords */
/* "inline" and "restrict" are keywords */
#else
# define inline /* inline */
# define restrict /* restrict */
#define inline /* inline */
#define restrict /* restrict */
#endif
@ -58,13 +58,13 @@ extern "C" {
#ifndef SIMCLIST_NO_DUMPRESTORE
typedef struct {
uint16_t version; /* dump version */
struct timeval timestamp; /* when the list has been dumped, seconds since UNIX epoch */
uint16_t version; /* dump version */
struct timeval timestamp; /* when the list has been dumped, seconds since UNIX epoch */
uint32_t list_size;
uint32_t list_numels;
list_hash_t list_hash; /* hash of the list when dumped, or 0 if invalid */
list_hash_t list_hash; /* hash of the list when dumped, or 0 if invalid */
uint32_t dumpsize;
int consistent; /* 1 if the dump is verified complete/consistent; 0 otherwise */
int consistent; /* 1 if the dump is verified complete/consistent; 0 otherwise */
} list_dump_info_t;
#endif
@ -77,7 +77,7 @@ extern "C" {
*
* It is responsability of the function to handle possible NULL values.
*/
typedef int (*element_comparator)(const void *a, const void *b);
typedef int (*element_comparator) (const void *a, const void *b);
/**
* a seeker of elements.
@ -90,7 +90,7 @@ extern "C" {
* It is responsability of the function to handle possible NULL values in any
* argument.
*/
typedef int (*element_seeker)(const void *el, const void *indicator);
typedef int (*element_seeker) (const void *el, const void *indicator);
/**
* an element lenght meter.
@ -101,7 +101,7 @@ extern "C" {
*
* It is responsability of the function to handle possible NULL values.
*/
typedef size_t (*element_meter)(const void *el);
typedef size_t (*element_meter) (const void *el);
/**
* a function computing the hash of elements.
@ -112,7 +112,7 @@ extern "C" {
*
* It is responsability of the function to handle possible NULL values.
*/
typedef list_hash_t (*element_hash_computer)(const void *el);
typedef list_hash_t (*element_hash_computer) (const void *el);
/**
* a function for serializing an element.
@ -132,7 +132,7 @@ extern "C" {
* @param serialize_buffer reference to fill with the length of the buffer
* @return reference to the buffer with the serialized data
*/
typedef void *(*element_serializer)(const void *restrict el, uint32_t *restrict serializ_len);
typedef void *(*element_serializer) (const void *restrict el, uint32_t *restrict serializ_len);
/**
* a function for un-serializing an element.
@ -149,7 +149,7 @@ extern "C" {
* @param data_len reference to the location where to store the length of the data in the buffer returned
* @return reference to a buffer with the original, unserialized representation of the element
*/
typedef void *(*element_unserializer)(const void *restrict data, uint32_t *restrict data_len);
typedef void *(*element_unserializer) (const void *restrict data, uint32_t *restrict data_len);
/* [private-use] list entry -- olds actual user datum */
struct list_entry_s {
@ -776,49 +776,49 @@ extern "C" {
* ready-made comparator for int8_t elements.
* @see list_attributes_comparator()
*/
int list_comparator_int8_t(const void *a, const void *b);
int list_comparator_int8_t (const void *a, const void *b);
/**
* ready-made comparator for int16_t elements.
* @see list_attributes_comparator()
*/
int list_comparator_int16_t(const void *a, const void *b);
int list_comparator_int16_t (const void *a, const void *b);
/**
* ready-made comparator for int32_t elements.
* @see list_attributes_comparator()
*/
int list_comparator_int32_t(const void *a, const void *b);
int list_comparator_int32_t (const void *a, const void *b);
/**
* ready-made comparator for int64_t elements.
* @see list_attributes_comparator()
*/
int list_comparator_int64_t(const void *a, const void *b);
int list_comparator_int64_t (const void *a, const void *b);
/**
* ready-made comparator for uint8_t elements.
* @see list_attributes_comparator()
*/
int list_comparator_uint8_t(const void *a, const void *b);
int list_comparator_uint8_t (const void *a, const void *b);
/**
* ready-made comparator for uint16_t elements.
* @see list_attributes_comparator()
*/
int list_comparator_uint16_t(const void *a, const void *b);
int list_comparator_uint16_t (const void *a, const void *b);
/**
* ready-made comparator for uint32_t elements.
* @see list_attributes_comparator()
*/
int list_comparator_uint32_t(const void *a, const void *b);
int list_comparator_uint32_t (const void *a, const void *b);
/**
* ready-made comparator for uint64_t elements.
* @see list_attributes_comparator()
*/
int list_comparator_uint64_t(const void *a, const void *b);
int list_comparator_uint64_t (const void *a, const void *b);
/**
* ready-made comparator for float elements.
@ -843,49 +843,49 @@ extern "C" {
* ready-made metric function for int8_t elements.
* @see list_attributes_copy()
*/
size_t list_meter_int8_t(const void *el);
size_t list_meter_int8_t (const void *el);
/**
* ready-made metric function for int16_t elements.
* @see list_attributes_copy()
*/
size_t list_meter_int16_t(const void *el);
size_t list_meter_int16_t (const void *el);
/**
* ready-made metric function for int32_t elements.
* @see list_attributes_copy()
*/
size_t list_meter_int32_t(const void *el);
size_t list_meter_int32_t (const void *el);
/**
* ready-made metric function for int64_t elements.
* @see list_attributes_copy()
*/
size_t list_meter_int64_t(const void *el);
size_t list_meter_int64_t (const void *el);
/**
* ready-made metric function for uint8_t elements.
* @see list_attributes_copy()
*/
size_t list_meter_uint8_t(const void *el);
size_t list_meter_uint8_t (const void *el);
/**
* ready-made metric function for uint16_t elements.
* @see list_attributes_copy()
*/
size_t list_meter_uint16_t(const void *el);
size_t list_meter_uint16_t (const void *el);
/**
* ready-made metric function for uint32_t elements.
* @see list_attributes_copy()
*/
size_t list_meter_uint32_t(const void *el);
size_t list_meter_uint32_t (const void *el);
/**
* ready-made metric function for uint64_t elements.
* @see list_attributes_copy()
*/
size_t list_meter_uint64_t(const void *el);
size_t list_meter_uint64_t (const void *el);
/**
* ready-made metric function for float elements.
@ -975,9 +975,7 @@ extern "C" {
#ifdef __cplusplus
}
#endif
#endif
/* For Emacs:
* Local Variables:
* mode:c

View File

@ -31,346 +31,78 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Use select on windows and poll everywhere else.
Select is the devil. Especially if you are doing a lot of small socket connections.
If your FD number is bigger than 1024 you will silently create memory corruption.
If you have build errors on your platform because you don't have poll find a way to detect it and #define KS_USE_SELECT and #undef KS_USE_POLL
All of this will be upgraded to autoheadache eventually.
*/
/* TBD for win32 figure out how to tell if you have WSAPoll (vista or higher) and use it when available by #defining KS_USE_WSAPOLL (see below) */
#ifdef _MSC_VER
#define FD_SETSIZE 8192
#define KS_USE_SELECT
#else
#define KS_USE_POLL
#endif
#include <ks.h>
#ifndef WIN32
#define closesocket(x) shutdown(x, 2); close(x)
#include <fcntl.h>
#include <errno.h>
#else
#pragma warning (disable:6386)
/* These warnings need to be ignored warning in sdk header */
#include <Ws2tcpip.h>
#include <windows.h>
#pragma comment(lib, "Ws2_32.lib")
#ifndef errno
#define errno WSAGetLastError()
#endif
#ifndef EINTR
#define EINTR WSAEINTR
#endif
#pragma warning (default:6386)
#endif
#ifdef KS_USE_POLL
#include <poll.h>
#endif
#ifndef KS_MIN
#define KS_MIN(x,y) ((x) < (y) ? (x) : (y))
#endif
#ifndef KS_MAX
#define KS_MAX(x,y) ((x) > (y) ? (x) : (y))
#endif
#ifndef KS_CLAMP
#define KS_CLAMP(min,max,val) (KS_MIN(max,KS_MAX(val,min)))
#endif
static ks_pool_t *pool = NULL;
/* Written by Marc Espie, public domain */
#define KS_CTYPE_NUM_CHARS 256
const short _ks_C_toupper_[1 + KS_CTYPE_NUM_CHARS] = {
EOF,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
const short *_ks_toupper_tab_ = _ks_C_toupper_;
KS_DECLARE(int) ks_toupper(int c)
KS_DECLARE(void) ks_random_string(char *buf, uint16_t len, char *set)
{
if ((unsigned int)c > 255)
return(c);
if (c < -1)
return EOF;
return((_ks_toupper_tab_ + 1)[c]);
}
char chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
int max;
uint16_t x;
const short _ks_C_tolower_[1 + KS_CTYPE_NUM_CHARS] = {
EOF,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
const short *_ks_tolower_tab_ = _ks_C_tolower_;
KS_DECLARE(int) ks_tolower(int c)
{
if ((unsigned int)c > 255)
return(c);
if (c < -1)
return EOF;
return((_ks_tolower_tab_ + 1)[c]);
}
KS_DECLARE(const char *)ks_stristr(const char *instr, const char *str)
{
/*
** Rev History: 16/07/97 Greg Thayer Optimized
** 07/04/95 Bob Stout ANSI-fy
** 02/03/94 Fred Cole Original
** 09/01/03 Bob Stout Bug fix (lines 40-41) per Fred Bulback
**
** Hereby donated to public domain.
*/
const char *pptr, *sptr, *start;
if (!str || !instr)
return NULL;
for (start = str; *start; start++) {
/* find start of pattern in string */
for (; ((*start) && (ks_toupper(*start) != ks_toupper(*instr))); start++);
if (!*start)
return NULL;
pptr = instr;
sptr = start;
while (ks_toupper(*sptr) == ks_toupper(*pptr)) {
sptr++;
pptr++;
/* if end of pattern then pattern was found */
if (!*pptr)
return (start);
if (!*sptr)
return NULL;
}
}
return NULL;
}
#ifdef WIN32
#ifndef vsnprintf
#define vsnprintf _vsnprintf
#endif
#endif
int vasprintf(char **ret, const char *format, va_list ap);
KS_DECLARE(int) ks_vasprintf(char **ret, const char *fmt, va_list ap)
{
#if !defined(WIN32) && !defined(__sun)
return vasprintf(ret, fmt, ap);
#else
char *buf;
int len;
size_t buflen;
va_list ap2;
char *tmp = NULL;
#ifdef _MSC_VER
#if _MSC_VER >= 1500
/* hack for incorrect assumption in msvc header files for code analysis */
__analysis_assume(tmp);
#endif
ap2 = ap;
#else
va_copy(ap2, ap);
#endif
len = vsnprintf(tmp, 0, fmt, ap2);
if (len > 0 && (buf = malloc((buflen = (size_t) (len + 1)))) != NULL) {
len = vsnprintf(buf, buflen, fmt, ap);
*ret = buf;
} else {
*ret = NULL;
len = -1;
if (!set) {
set = chars;
}
va_end(ap2);
return len;
#endif
}
max = (int) strlen(set);
KS_DECLARE(int) ks_snprintf(char *buffer, size_t count, const char *fmt, ...)
{
va_list ap;
int ret;
va_start(ap, fmt);
ret = vsnprintf(buffer, count-1, fmt, ap);
if (ret < 0)
buffer[count-1] = '\0';
va_end(ap);
return ret;
}
static void null_logger(const char *file, const char *func, int line, int level, const char *fmt, ...)
{
if (file && func && line && level && fmt) {
return;
for (x = 0; x < len; x++) {
int j = (int) (max * 1.0 * rand() / (RAND_MAX + 1.0));
buf[x] = set[j];
}
return;
}
static const char *LEVEL_NAMES[] = {
"EMERG",
"ALERT",
"CRIT",
"ERROR",
"WARNING",
"NOTICE",
"INFO",
"DEBUG",
NULL
};
static int ks_log_level = 7;
static const char *cut_path(const char *in)
KS_DECLARE(ks_status_t) ks_global_set_cleanup(ks_pool_cleanup_fn_t fn, void *arg)
{
const char *p, *ret = in;
char delims[] = "/\\";
char *i;
for (i = delims; *i; i++) {
p = in;
while ((p = strchr(p, *i)) != 0) {
ret = ++p;
}
}
return ret;
return ks_pool_set_cleanup(ks_global_pool(), NULL, arg, 0, fn);
}
static void default_logger(const char *file, const char *func, int line, int level, const char *fmt, ...)
{
const char *fp;
char *data;
va_list ap;
int ret;
if (level < 0 || level > 7) {
level = 7;
}
if (level > ks_log_level) {
return;
KS_DECLARE(ks_status_t) ks_init(void)
{
srand(getpid() * (intptr_t)&pool + time(NULL));
ks_ssl_init_ssl_locks();
ks_global_pool();
ks_rng_init();
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) ks_shutdown(void)
{
ks_status_t status = KS_STATUS_SUCCESS;
ks_ssl_destroy_ssl_locks();
//ks_rng_shutdown();
if (pool) {
status = ks_pool_close(&pool);
}
fp = cut_path(file);
va_start(ap, fmt);
ret = ks_vasprintf(&data, fmt, ap);
if (ret != -1) {
fprintf(stderr, "[%s] %s:%d %s() %s", LEVEL_NAMES[level], fp, line, func, data);
free(data);
}
va_end(ap);
return status;
}
ks_logger_t ks_log = null_logger;
KS_DECLARE(void) ks_global_set_logger(ks_logger_t logger)
KS_DECLARE(ks_pool_t *) ks_global_pool(void)
{
if (logger) {
ks_log = logger;
} else {
ks_log = null_logger;
}
}
KS_DECLARE(void) ks_global_set_default_logger(int level)
{
if (level < 0 || level > 7) {
level = 7;
ks_status_t status;
if (!pool) {
if ((status = ks_pool_open(&pool)) != KS_STATUS_SUCCESS) {
abort();
}
}
ks_log = default_logger;
ks_log_level = level;
return pool;
}
KS_ENUM_NAMES(STATUS_NAMES, STATUS_STRINGS)
KS_STR2ENUM(ks_str2ks_status, ks_status2str, ks_status_t, STATUS_NAMES, KS_STATUS_COUNT)
KS_DECLARE(size_t) ks_url_encode(const char *url, char *buf, size_t len)
{
const char *p;
@ -408,7 +140,7 @@ KS_DECLARE(size_t) ks_url_encode(const char *url, char *buf, size_t len)
return x;
}
KS_DECLARE(char *)ks_url_decode(char *s)
KS_DECLARE(char *) ks_url_decode(char *s)
{
char *o;
unsigned int tmp;
@ -425,316 +157,30 @@ KS_DECLARE(char *)ks_url_decode(char *s)
return s;
}
static int ks_socket_reuseaddr(ks_socket_t socket)
KS_DECLARE(int) ks_cpu_count(void)
{
#ifdef WIN32
BOOL reuse_addr = TRUE;
return setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse_addr, sizeof(reuse_addr));
#else
int reuse_addr = 1;
return setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr));
#endif
}
struct thread_handler {
ks_listen_callback_t callback;
ks_socket_t server_sock;
ks_socket_t client_sock;
struct sockaddr_in addr;
};
static void *client_thread(ks_thread_t *me, void *obj)
{
struct thread_handler *handler = (struct thread_handler *) obj;
handler->callback(handler->server_sock, handler->client_sock, &handler->addr);
free(handler);
return NULL;
}
KS_DECLARE(ks_status_t) ks_listen(const char *host, ks_port_t port, ks_listen_callback_t callback)
{
ks_socket_t server_sock = KS_SOCK_INVALID;
struct sockaddr_in addr;
ks_status_t status = KS_SUCCESS;
if ((server_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
return KS_FAIL;
}
ks_socket_reuseaddr(server_sock);
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(port);
if (bind(server_sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
status = KS_FAIL;
goto end;
}
if (listen(server_sock, 10000) < 0) {
status = KS_FAIL;
goto end;
}
for (;;) {
int client_sock;
struct sockaddr_in echoClntAddr;
#ifdef WIN32
int clntLen;
#else
unsigned int clntLen;
#endif
clntLen = sizeof(echoClntAddr);
if ((client_sock = accept(server_sock, (struct sockaddr *) &echoClntAddr, &clntLen)) == KS_SOCK_INVALID) {
status = KS_FAIL;
goto end;
}
callback(server_sock, client_sock, &echoClntAddr);
}
end:
if (server_sock != KS_SOCK_INVALID) {
closesocket(server_sock);
server_sock = KS_SOCK_INVALID;
}
return status;
}
KS_DECLARE(ks_status_t) ks_listen_threaded(const char *host, ks_port_t port, ks_listen_callback_t callback, int max)
{
ks_socket_t server_sock = KS_SOCK_INVALID;
struct sockaddr_in addr;
ks_status_t status = KS_SUCCESS;
struct thread_handler *handler = NULL;
if ((server_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
return KS_FAIL;
}
ks_socket_reuseaddr(server_sock);
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(port);
if (bind(server_sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
status = KS_FAIL;
goto end;
}
if (listen(server_sock, max) < 0) {
status = KS_FAIL;
goto end;
}
for (;;) {
int client_sock;
struct sockaddr_in echoClntAddr;
#ifdef WIN32
int clntLen;
#else
unsigned int clntLen;
#endif
clntLen = sizeof(echoClntAddr);
if ((client_sock = accept(server_sock, (struct sockaddr *) &echoClntAddr, &clntLen)) == KS_SOCK_INVALID) {
status = KS_FAIL;
goto end;
}
handler = malloc(sizeof(*handler));
ks_assert(handler);
memset(handler, 0, sizeof(*handler));
handler->callback = callback;
handler->server_sock = server_sock;
handler->client_sock = client_sock;
handler->addr = echoClntAddr;
ks_thread_create_detached(client_thread, handler);
}
end:
if (server_sock != KS_SOCK_INVALID) {
closesocket(server_sock);
server_sock = KS_SOCK_INVALID;
}
return status;
}
/* USE WSAPoll on vista or higher */
#ifdef KS_USE_WSAPOLL
KS_DECLARE(int) ks_wait_sock(ks_socket_t sock, uint32_t ms, ks_poll_t flags)
{
}
#endif
#ifdef KS_USE_SELECT
#ifdef WIN32
#pragma warning( push )
#pragma warning( disable : 6262 ) /* warning C6262: Function uses '98348' bytes of stack: exceeds /analyze:stacksize'16384'. Consider moving some data to heap */
#endif
KS_DECLARE(int) ks_wait_sock(ks_socket_t sock, uint32_t ms, ks_poll_t flags)
{
int s = 0, r = 0;
fd_set rfds;
fd_set wfds;
fd_set efds;
struct timeval tv;
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_ZERO(&efds);
int cpu_count;
#ifndef WIN32
/* Wouldn't you rather know?? */
assert(sock <= FD_SETSIZE);
#endif
if ((flags & KS_POLL_READ)) {
#ifdef WIN32
#pragma warning( push )
#pragma warning( disable : 4127 )
FD_SET(sock, &rfds);
#pragma warning( pop )
cpu_count = sysconf (_SC_NPROCESSORS_ONLN);
#else
FD_SET(sock, &rfds);
#endif
{
SYSTEM_INFO sysinfo;
GetSystemInfo( &sysinfo );
cpu_count = sysinfo.dwNumberOfProcessors;
}
if ((flags & KS_POLL_WRITE)) {
#ifdef WIN32
#pragma warning( push )
#pragma warning( disable : 4127 )
FD_SET(sock, &wfds);
#pragma warning( pop )
#else
FD_SET(sock, &wfds);
#endif
}
if ((flags & KS_POLL_ERROR)) {
#ifdef WIN32
#pragma warning( push )
#pragma warning( disable : 4127 )
FD_SET(sock, &efds);
#pragma warning( pop )
#else
FD_SET(sock, &efds);
#endif
}
tv.tv_sec = ms / 1000;
tv.tv_usec = (ms % 1000) * ms;
s = select(sock + 1, (flags & KS_POLL_READ) ? &rfds : NULL, (flags & KS_POLL_WRITE) ? &wfds : NULL, (flags & KS_POLL_ERROR) ? &efds : NULL, &tv);
if (s < 0) {
r = s;
} else if (s > 0) {
if ((flags & KS_POLL_READ) && FD_ISSET(sock, &rfds)) {
r |= KS_POLL_READ;
}
if ((flags & KS_POLL_WRITE) && FD_ISSET(sock, &wfds)) {
r |= KS_POLL_WRITE;
}
if ((flags & KS_POLL_ERROR) && FD_ISSET(sock, &efds)) {
r |= KS_POLL_ERROR;
}
}
return r;
}
#ifdef WIN32
#pragma warning( pop )
#endif
#endif
#ifdef KS_USE_POLL
KS_DECLARE(int) ks_wait_sock(ks_socket_t sock, uint32_t ms, ks_poll_t flags)
{
struct pollfd pfds[2] = { { 0 } };
int s = 0, r = 0;
pfds[0].fd = sock;
if ((flags & KS_POLL_READ)) {
pfds[0].events |= POLLIN;
}
if ((flags & KS_POLL_WRITE)) {
pfds[0].events |= POLLOUT;
}
if ((flags & KS_POLL_ERROR)) {
pfds[0].events |= POLLERR;
}
s = poll(pfds, 1, ms);
if (s < 0) {
r = s;
} else if (s > 0) {
if ((pfds[0].revents & POLLIN)) {
r |= KS_POLL_READ;
}
if ((pfds[0].revents & POLLOUT)) {
r |= KS_POLL_WRITE;
}
if ((pfds[0].revents & POLLERR)) {
r |= KS_POLL_ERROR;
}
}
return r;
}
#endif
KS_DECLARE(unsigned int) ks_separate_string_string(char *buf, const char *delim, char **array, unsigned int arraylen)
{
unsigned int count = 0;
char *d;
size_t dlen = strlen(delim);
array[count++] = buf;
while (count < arraylen && array[count - 1]) {
if ((d = strstr(array[count - 1], delim))) {
*d = '\0';
d += dlen;
array[count++] = d;
} else
break;
}
return count;
return cpu_count;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

2697
libs/libks/src/ks_bencode.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -32,7 +32,7 @@
*/
#include "ks_buffer.h"
#include "ks.h"
static unsigned buffer_id = 0;
@ -61,7 +61,7 @@ KS_DECLARE(ks_status_t) ks_buffer_create(ks_buffer_t **buffer, ks_size_t blocksi
new_buffer->data = malloc(start_len);
if (!new_buffer->data) {
free(new_buffer);
return KS_FAIL;
return KS_STATUS_FAIL;
}
memset(new_buffer->data, 0, start_len);
}
@ -73,10 +73,10 @@ KS_DECLARE(ks_status_t) ks_buffer_create(ks_buffer_t **buffer, ks_size_t blocksi
new_buffer->head = new_buffer->data;
*buffer = new_buffer;
return KS_SUCCESS;
return KS_STATUS_SUCCESS;
}
return KS_FAIL;
return KS_STATUS_FAIL;
}
KS_DECLARE(ks_size_t) ks_buffer_len(ks_buffer_t *buffer)
@ -163,7 +163,7 @@ KS_DECLARE(ks_size_t) ks_buffer_read_loop(ks_buffer_t *buffer, void *data, ks_si
}
buffer->head = buffer->data;
buffer->used = buffer->actually_used;
len = ks_buffer_read(buffer, (char*)data + len, datalen - len);
len = ks_buffer_read(buffer, (char *) data + len, datalen - len);
buffer->loops--;
}
return len;
@ -199,22 +199,23 @@ KS_DECLARE(ks_size_t) ks_buffer_packet_count(ks_buffer_t *buffer)
{
char *pe, *p, *e, *head = (char *) buffer->head;
ks_size_t x = 0;
ks_assert(buffer != NULL);
e = (head + buffer->used);
for (p = head; p && *p && p < e; p++) {
if (*p == '\n') {
pe = p+1;
if (*pe == '\r') pe++;
pe = p + 1;
if (*pe == '\r')
pe++;
if (pe <= e && *pe == '\n') {
p = pe++;
x++;
}
}
}
return x;
}
@ -230,8 +231,9 @@ KS_DECLARE(ks_size_t) ks_buffer_read_packet(ks_buffer_t *buffer, void *data, ks_
for (p = head; p && *p && p < e; p++) {
if (*p == '\n') {
pe = p+1;
if (*pe == '\r') pe++;
pe = p + 1;
if (*pe == '\r')
pe++;
if (pe <= e && *pe == '\n') {
pe++;
datalen = pe - head;
@ -242,7 +244,7 @@ KS_DECLARE(ks_size_t) ks_buffer_read_packet(ks_buffer_t *buffer, void *data, ks_
}
}
}
return ks_buffer_read(buffer, data, datalen);
}
@ -268,16 +270,16 @@ KS_DECLARE(ks_size_t) ks_buffer_write(ks_buffer_t *buffer, const void *data, ks_
freespace = buffer->datalen - buffer->used;
/*
if (buffer->data != buffer->head) {
memmove(buffer->data, buffer->head, buffer->used);
buffer->head = buffer->data;
}
*/
if (buffer->data != buffer->head) {
memmove(buffer->data, buffer->head, buffer->used);
buffer->head = buffer->data;
}
*/
if (freespace < datalen) {
ks_size_t new_size, new_block_size;
void *data1;
new_size = buffer->datalen + datalen;
new_block_size = buffer->datalen + buffer->blocksize;
@ -293,7 +295,7 @@ KS_DECLARE(ks_size_t) ks_buffer_write(ks_buffer_t *buffer, const void *data, ks_
buffer->head = buffer->data;
buffer->datalen = new_size;
}
freespace = buffer->datalen - buffer->used;
@ -322,7 +324,7 @@ KS_DECLARE(void) ks_buffer_zero(ks_buffer_t *buffer)
KS_DECLARE(ks_size_t) ks_buffer_zwrite(ks_buffer_t *buffer, const void *data, ks_size_t datalen)
{
ks_size_t w;
if (!(w = ks_buffer_write(buffer, data, datalen))) {
ks_buffer_zero(buffer);
return ks_buffer_write(buffer, data, datalen);

View File

@ -32,7 +32,6 @@
*/
#include "ks.h"
#include "ks_config.h"
KS_DECLARE(int) ks_config_open_file(ks_config_t *cfg, const char *file_path)
{
@ -157,7 +156,7 @@ KS_DECLARE(int) ks_config_next_pair(ks_config_t *cfg, char **var, char **val)
}
if ((end = strchr(*var, ';')) && *(end+1) == *end) {
if ((end = strchr(*var, ';')) && *(end + 1) == *end) {
*end = '\0';
end--;
} else if ((end = strchr(*var, '\n')) != 0) {

4137
libs/libks/src/ks_dht.c Normal file

File diff suppressed because it is too large Load Diff

132
libs/libks/src/ks_dso.c Executable file
View File

@ -0,0 +1,132 @@
/*
* Cross Platform dso/dll load abstraction
* Copyright(C) 2008 Michael Jerris
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so.
*
* This work is provided under this license on an "as is" basis, without warranty of any kind,
* either expressed or implied, including, without limitation, warranties that the covered code
* is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire
* risk as to the quality and performance of the covered code is with you. Should any covered
* code prove defective in any respect, you (not the initial developer or any other contributor)
* assume the cost of any necessary servicing, repair or correction. This disclaimer of warranty
* constitutes an essential part of this license. No use of any covered code is authorized hereunder
* except under this disclaimer.
*
*/
#include "ks.h"
#ifdef WIN32
#include <windows.h>
#include <stdio.h>
KS_DECLARE(ks_status_t) ks_dso_destroy(ks_dso_lib_t *lib) {
if (lib && *lib) {
FreeLibrary(*lib);
*lib = NULL;
}
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_dso_lib_t) ks_dso_open(const char *path, char **err) {
HINSTANCE lib;
#ifdef UNICODE
size_t len = strlen(path) + 1;
wchar_t *wpath = malloc(len);
size_t converted;
mbstowcs_s(&converted, wpath, len, path, _TRUNCATE);
#else
char * wpath = path;
#endif
lib = LoadLibraryEx(wpath, NULL, 0);
if (!lib) {
LoadLibraryEx(wpath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
}
if (!lib) {
DWORD error = GetLastError();
char tmp[80];
sprintf(tmp, "dll open error [%lu]\n", error);
*err = strdup(tmp);
}
#ifdef UNICODE
free(wpath);
#endif
return lib;
}
KS_DECLARE(void*) ks_dso_func_sym(ks_dso_lib_t lib, const char *sym, char **err) {
FARPROC func = GetProcAddress(lib, sym);
if (!func) {
DWORD error = GetLastError();
char tmp[80];
sprintf(tmp, "dll sym error [%lu]\n", error);
*err = strdup(tmp);
}
return (void *)(intptr_t)func; // this should really be addr - ks_dso_func_data
}
#else
/*
** {========================================================================
** This is an implementation of loadlib based on the dlfcn interface.
** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,
** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least
** as an emulation layer on top of native functions.
** =========================================================================
*/
#include <dlfcn.h>
KS_DECLARE(ks_status_t) ks_dso_destroy(ks_dso_lib_t *lib) {
int rc;
if (lib && *lib) {
rc = dlclose(*lib);
if (rc) {
//ks_log(KS_LOG_ERROR, "Failed to close lib %p: %s\n", *lib, dlerror());
return KS_STATUS_FAIL;
}
//ks_log(KS_LOG_DEBUG, "lib %p was closed with success\n", *lib);
*lib = NULL;
return KS_STATUS_SUCCESS;
}
//ks_log(KS_LOG_ERROR, "Invalid pointer provided to ks_dso_destroy\n");
return KS_STATUS_FAIL;
}
KS_DECLARE(ks_dso_lib_t) ks_dso_open(const char *path, char **err) {
void *lib = dlopen(path, RTLD_NOW | RTLD_LOCAL);
if (lib == NULL) {
*err = strdup(dlerror());
}
return lib;
}
KS_DECLARE(void *) ks_dso_func_sym(ks_dso_lib_t lib, const char *sym, char **err) {
void *func = dlsym(lib, sym);
if (!func) {
*err = strdup(dlerror());
}
return func;
}
#endif
/* }====================================================== */
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

648
libs/libks/src/ks_hash.c Normal file
View File

@ -0,0 +1,648 @@
/*
* Copyright (c) 2002, Christopher Clark
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ks.h"
#include "ks_hash.h"
struct entry
{
void *k, *v;
unsigned int h;
ks_hash_flag_t flags;
ks_hash_destructor_t destructor;
struct entry *next;
};
struct ks_hash_iterator {
unsigned int pos;
ks_locked_t locked;
struct entry *e;
struct ks_hash *h;
};
struct ks_hash {
ks_pool_t *pool;
unsigned int tablelength;
struct entry **table;
unsigned int entrycount;
unsigned int loadlimit;
unsigned int primeindex;
unsigned int (*hashfn) (void *k);
int (*eqfn) (void *k1, void *k2);
ks_hash_flag_t flags;
ks_hash_destructor_t destructor;
ks_rwl_t *rwl;
ks_mutex_t *mutex;
uint32_t readers;
};
/*****************************************************************************/
/*****************************************************************************/
static inline unsigned int
hash(ks_hash_t *h, void *k)
{
/* Aim to protect against poor hash functions by adding logic here
* - logic taken from java 1.4 ks_hash source */
unsigned int i = h->hashfn(k);
i += ~(i << 9);
i ^= ((i >> 14) | (i << 18)); /* >>> */
i += (i << 4);
i ^= ((i >> 10) | (i << 22)); /* >>> */
return i;
}
/*****************************************************************************/
/* indexFor */
static __inline__ unsigned int
indexFor(unsigned int tablelength, unsigned int hashvalue) {
return (hashvalue % tablelength);
}
/* Only works if tablelength == 2^N */
/*static inline unsigned int
indexFor(unsigned int tablelength, unsigned int hashvalue)
{
return (hashvalue & (tablelength - 1u));
}
*/
/*****************************************************************************/
//#define freekey(X) free(X)
/*
Credit for primes table: Aaron Krowne
http://br.endernet.org/~akrowne/
http://planetmath.org/encyclopedia/GoodKs_HashPrimes.html
*/
static const unsigned int primes[] = {
53, 97, 193, 389,
769, 1543, 3079, 6151,
12289, 24593, 49157, 98317,
196613, 393241, 786433, 1572869,
3145739, 6291469, 12582917, 25165843,
50331653, 100663319, 201326611, 402653189,
805306457, 1610612741
};
const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0]);
const float max_load_factor = 0.65f;
/*****************************************************************************/
static void ks_hash_cleanup(ks_pool_t *mpool, void *ptr, void *arg, int type, ks_pool_cleanup_action_t action, ks_pool_cleanup_type_t ctype)
{
//ks_hash_t *hash = (ks_hash_t *) ptr;
switch(action) {
case KS_MPCL_ANNOUNCE:
break;
case KS_MPCL_TEARDOWN:
break;
case KS_MPCL_DESTROY:
//ks_hash_destroy(&hash);
break;
}
}
KS_DECLARE(ks_status_t) ks_hash_create(ks_hash_t **hp, ks_hash_mode_t mode, ks_hash_flag_t flags, ks_pool_t *pool)
{
return ks_hash_create_ex(hp, 16, NULL, NULL, mode, flags, NULL, pool);
}
KS_DECLARE(void) ks_hash_set_flags(ks_hash_t *h, ks_hash_flag_t flags)
{
h->flags = flags;
}
KS_DECLARE(void) ks_hash_set_destructor(ks_hash_t *h, ks_hash_destructor_t destructor)
{
h->destructor = destructor;
}
KS_DECLARE(ks_status_t)
ks_hash_create_ex(ks_hash_t **hp, unsigned int minsize,
unsigned int (*hashf) (void*),
int (*eqf) (void*,void*), ks_hash_mode_t mode, ks_hash_flag_t flags, ks_hash_destructor_t destructor, ks_pool_t *pool)
{
ks_hash_t *h;
unsigned int pindex, size = primes[0];
switch(mode) {
case KS_HASH_MODE_CASE_INSENSITIVE:
ks_assert(hashf == NULL);
hashf = ks_hash_default_ci;
break;
case KS_HASH_MODE_INT:
ks_assert(hashf == NULL);
ks_assert(eqf == NULL);
hashf = ks_hash_default_int;
eqf = ks_hash_equalkeys_int;
break;
case KS_HASH_MODE_INT64:
ks_assert(hashf == NULL);
ks_assert(eqf == NULL);
hashf = ks_hash_default_int64;
eqf = ks_hash_equalkeys_int64;
break;
case KS_HASH_MODE_PTR:
ks_assert(hashf == NULL);
ks_assert(eqf == NULL);
hashf = ks_hash_default_ptr;
eqf = ks_hash_equalkeys_ptr;
break;
default:
break;
}
if (flags == KS_HASH_FLAG_DEFAULT) {
flags = KS_HASH_FLAG_FREE_KEY | KS_HASH_FLAG_DUP_CHECK | KS_HASH_FLAG_RWLOCK;
}
ks_assert(pool);
if (!hashf) hashf = ks_hash_default;
if (!eqf) eqf = ks_hash_equalkeys;
if (!minsize) minsize = 16;
/* Check requested ks_hash isn't too large */
if (minsize > (1u << 30)) {*hp = NULL; return KS_STATUS_FAIL;}
/* Enforce size as prime */
for (pindex=0; pindex < prime_table_length; pindex++) {
if (primes[pindex] > minsize) {
size = primes[pindex];
break;
}
}
h = (ks_hash_t *) ks_pool_alloc(pool, sizeof(ks_hash_t));
h->pool = pool;
h->flags = flags;
h->destructor = destructor;
if ((flags & KS_HASH_FLAG_RWLOCK)) {
ks_rwl_create(&h->rwl, h->pool);
}
ks_mutex_create(&h->mutex, KS_MUTEX_FLAG_DEFAULT, h->pool);
if (NULL == h) abort(); /*oom*/
h->table = (struct entry **)ks_pool_alloc(h->pool, sizeof(struct entry*) * size);
if (NULL == h->table) abort(); /*oom*/
//memset(h->table, 0, size * sizeof(struct entry *));
h->tablelength = size;
h->primeindex = pindex;
h->entrycount = 0;
h->hashfn = hashf;
h->eqfn = eqf;
h->loadlimit = (unsigned int) ceil(size * max_load_factor);
*hp = h;
ks_pool_set_cleanup(pool, h, NULL, 0, ks_hash_cleanup);
return KS_STATUS_SUCCESS;
}
/*****************************************************************************/
static int
ks_hash_expand(ks_hash_t *h)
{
/* Double the size of the table to accomodate more entries */
struct entry **newtable;
struct entry *e;
struct entry **pE;
unsigned int newsize, i, index;
/* Check we're not hitting max capacity */
if (h->primeindex == (prime_table_length - 1)) return 0;
newsize = primes[++(h->primeindex)];
newtable = (struct entry **)ks_pool_alloc(h->pool, sizeof(struct entry*) * newsize);
if (NULL != newtable)
{
memset(newtable, 0, newsize * sizeof(struct entry *));
/* This algorithm is not 'stable'. ie. it reverses the list
* when it transfers entries between the tables */
for (i = 0; i < h->tablelength; i++) {
while (NULL != (e = h->table[i])) {
h->table[i] = e->next;
index = indexFor(newsize,e->h);
e->next = newtable[index];
newtable[index] = e;
}
}
ks_pool_safe_free(h->pool, h->table);
h->table = newtable;
}
/* Plan B: realloc instead */
else
{
newtable = (struct entry **)
ks_pool_resize(h->pool, h->table, newsize * sizeof(struct entry *));
if (NULL == newtable) { (h->primeindex)--; return 0; }
h->table = newtable;
memset(newtable[h->tablelength], 0, newsize - h->tablelength);
for (i = 0; i < h->tablelength; i++) {
for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) {
index = indexFor(newsize,e->h);
if (index == i) {
pE = &(e->next);
} else {
*pE = e->next;
e->next = newtable[index];
newtable[index] = e;
}
}
}
}
h->tablelength = newsize;
h->loadlimit = (unsigned int) ceil(newsize * max_load_factor);
return -1;
}
/*****************************************************************************/
KS_DECLARE(unsigned int)
ks_hash_count(ks_hash_t *h)
{
return h->entrycount;
}
static void * _ks_hash_remove(ks_hash_t *h, void *k, unsigned int hashvalue, unsigned int index) {
/* TODO: consider compacting the table when the load factor drops enough,
* or provide a 'compact' method. */
struct entry *e;
struct entry **pE;
void *v;
pE = &(h->table[index]);
e = *pE;
while (NULL != e) {
/* Check hash value to short circuit heavier comparison */
if ((hashvalue == e->h) && (h->eqfn(k, e->k))) {
*pE = e->next;
h->entrycount--;
v = e->v;
if (e->flags & KS_HASH_FLAG_FREE_KEY) {
ks_pool_free(h->pool, e->k);
}
if (e->flags & KS_HASH_FLAG_FREE_VALUE) {
ks_pool_safe_free(h->pool, e->v);
v = NULL;
} else if (e->destructor) {
e->destructor(e->v);
v = e->v = NULL;
} else if (h->destructor) {
h->destructor(e->v);
v = e->v = NULL;
}
ks_pool_safe_free(h->pool, e);
return v;
}
pE = &(e->next);
e = e->next;
}
return NULL;
}
/*****************************************************************************/
KS_DECLARE(int)
ks_hash_insert_ex(ks_hash_t *h, void *k, void *v, ks_hash_flag_t flags, ks_hash_destructor_t destructor)
{
struct entry *e;
unsigned int hashvalue = hash(h, k);
unsigned index = indexFor(h->tablelength, hashvalue);
ks_hash_write_lock(h);
if (!flags) {
flags = h->flags;
}
if (flags & KS_HASH_FLAG_DUP_CHECK) {
_ks_hash_remove(h, k, hashvalue, index);
}
if (++(h->entrycount) > h->loadlimit)
{
/* Ignore the return value. If expand fails, we should
* still try cramming just this value into the existing table
* -- we may not have memory for a larger table, but one more
* element may be ok. Next time we insert, we'll try expanding again.*/
ks_hash_expand(h);
index = indexFor(h->tablelength, hashvalue);
}
e = (struct entry *)ks_pool_alloc(h->pool, sizeof(struct entry));
if (NULL == e) { --(h->entrycount); return 0; } /*oom*/
e->h = hashvalue;
e->k = k;
e->v = v;
e->flags = flags;
e->destructor = destructor;
e->next = h->table[index];
h->table[index] = e;
ks_hash_write_unlock(h);
return -1;
}
KS_DECLARE(void) ks_hash_write_lock(ks_hash_t *h)
{
if ((h->flags & KS_HASH_FLAG_RWLOCK)) {
ks_rwl_write_lock(h->rwl);
} else {
ks_mutex_lock(h->mutex);
}
}
KS_DECLARE(void) ks_hash_write_unlock(ks_hash_t *h)
{
if ((h->flags & KS_HASH_FLAG_RWLOCK)) {
ks_rwl_write_unlock(h->rwl);
} else {
ks_mutex_unlock(h->mutex);
}
}
KS_DECLARE(ks_status_t) ks_hash_read_lock(ks_hash_t *h)
{
if (!(h->flags & KS_HASH_FLAG_RWLOCK)) {
return KS_STATUS_INACTIVE;
}
ks_rwl_read_lock(h->rwl);
ks_mutex_lock(h->mutex);
h->readers++;
ks_mutex_unlock(h->mutex);
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) ks_hash_read_unlock(ks_hash_t *h)
{
if (!(h->flags & KS_HASH_FLAG_RWLOCK)) {
return KS_STATUS_INACTIVE;
}
ks_mutex_lock(h->mutex);
h->readers--;
ks_mutex_unlock(h->mutex);
ks_rwl_read_unlock(h->rwl);
return KS_STATUS_SUCCESS;
}
/*****************************************************************************/
KS_DECLARE(void *) /* returns value associated with key */
ks_hash_search(ks_hash_t *h, void *k, ks_locked_t locked)
{
struct entry *e;
unsigned int hashvalue, index;
void *v = NULL;
ks_assert(locked != KS_READLOCKED || (h->flags & KS_HASH_FLAG_RWLOCK));
hashvalue = hash(h,k);
index = indexFor(h->tablelength,hashvalue);
if (locked == KS_READLOCKED) {
ks_rwl_read_lock(h->rwl);
ks_mutex_lock(h->mutex);
h->readers++;
ks_mutex_unlock(h->mutex);
}
e = h->table[index];
while (NULL != e) {
/* Check hash value to short circuit heavier comparison */
if ((hashvalue == e->h) && (h->eqfn(k, e->k))) {
v = e->v;
break;
}
e = e->next;
}
return v;
}
/*****************************************************************************/
KS_DECLARE(void *) /* returns value associated with key */
ks_hash_remove(ks_hash_t *h, void *k)
{
void *v;
unsigned int hashvalue = hash(h,k);
ks_hash_write_lock(h);
v = _ks_hash_remove(h, k, hashvalue, indexFor(h->tablelength,hashvalue));
ks_hash_write_unlock(h);
return v;
}
/*****************************************************************************/
/* destroy */
KS_DECLARE(void)
ks_hash_destroy(ks_hash_t **h)
{
unsigned int i;
struct entry *e, *f;
struct entry **table = (*h)->table;
ks_pool_t *pool;
ks_hash_write_lock(*h);
for (i = 0; i < (*h)->tablelength; i++) {
e = table[i];
while (NULL != e) {
f = e; e = e->next;
if (f->flags & KS_HASH_FLAG_FREE_KEY) {
ks_pool_free((*h)->pool, f->k);
}
if (f->flags & KS_HASH_FLAG_FREE_VALUE) {
ks_pool_safe_free((*h)->pool, f->v);
} else if (f->destructor) {
f->destructor(f->v);
f->v = NULL;
} else if ((*h)->destructor) {
(*h)->destructor(f->v);
f->v = NULL;
}
ks_pool_safe_free((*h)->pool, f);
}
}
pool = (*h)->pool;
ks_pool_safe_free(pool, (*h)->table);
ks_hash_write_unlock(*h);
if ((*h)->rwl) ks_pool_free(pool, (*h)->rwl);
ks_pool_free(pool, (*h)->mutex);
ks_pool_free(pool, *h);
pool = NULL;
*h = NULL;
}
KS_DECLARE(void) ks_hash_last(ks_hash_iterator_t **iP)
{
ks_hash_iterator_t *i = *iP;
//ks_assert(i->locked != KS_READLOCKED || (i->h->flags & KS_HASH_FLAG_RWLOCK));
if (i->locked == KS_READLOCKED) {
ks_mutex_lock(i->h->mutex);
i->h->readers--;
ks_mutex_unlock(i->h->mutex);
ks_rwl_read_unlock(i->h->rwl);
}
ks_pool_free(i->h->pool, i);
*iP = NULL;
}
KS_DECLARE(ks_hash_iterator_t *) ks_hash_next(ks_hash_iterator_t **iP)
{
ks_hash_iterator_t *i = *iP;
if (i->e) {
if ((i->e = i->e->next) != 0) {
return i;
} else {
i->pos++;
}
}
while(i->pos < i->h->tablelength && !i->h->table[i->pos]) {
i->pos++;
}
if (i->pos >= i->h->tablelength) {
goto end;
}
if ((i->e = i->h->table[i->pos]) != 0) {
return i;
}
end:
ks_hash_last(iP);
return NULL;
}
KS_DECLARE(ks_hash_iterator_t *) ks_hash_first(ks_hash_t *h, ks_locked_t locked)
{
ks_hash_iterator_t *iterator;
ks_assert(locked != KS_READLOCKED || (h->flags & KS_HASH_FLAG_RWLOCK));
iterator = ks_pool_alloc(h->pool, sizeof(*iterator));
ks_assert(iterator);
iterator->pos = 0;
iterator->e = NULL;
iterator->h = h;
if (locked == KS_READLOCKED) {
ks_rwl_read_lock(h->rwl);
iterator->locked = locked;
ks_mutex_lock(h->mutex);
h->readers++;
ks_mutex_unlock(h->mutex);
}
return ks_hash_next(&iterator);
}
KS_DECLARE(void) ks_hash_this_val(ks_hash_iterator_t *i, void *val)
{
if (i->e) {
i->e->v = val;
}
}
KS_DECLARE(void) ks_hash_this(ks_hash_iterator_t *i, const void **key, ks_ssize_t *klen, void **val)
{
if (i->e) {
if (key) {
*key = i->e->k;
}
if (klen) {
*klen = (int)strlen(i->e->k);
}
if (val) {
*val = i->e->v;
}
} else {
if (key) {
*key = NULL;
}
if (klen) {
*klen = 0;
}
if (val) {
*val = NULL;
}
}
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

View File

@ -27,11 +27,11 @@
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <float.h>
#include <limits.h>
#include <ctype.h>
#include "ks_json.h"
#include "ks.h"
#include "ks_json.h"
#include <float.h>
static const char *ep;
@ -40,7 +40,7 @@ KS_DECLARE(const char *)cJSON_GetErrorPtr() {return ep;}
static int cJSON_strcasecmp(const char *s1,const char *s2)
{
if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0;
for(; tolower(*(const unsigned char *)s1) == tolower(*(const unsigned char *)s2); ++s1, ++s2) if(*s1 == 0) return 0;
return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
}
@ -59,23 +59,23 @@ static void (*cJSON_free)(void *ptr) = glue_free;
static char* cJSON_strdup(const char* str)
{
size_t len;
char* copy;
const char *s = str ? str : "";
size_t len;
char* copy;
const char *s = str ? str : "";
len = strlen(s) + 1;
if (!(copy = (char*)cJSON_malloc(len))) return 0;
memcpy(copy,s,len);
return copy;
len = strlen(s) + 1;
if (!(copy = (char*)cJSON_malloc(len))) return 0;
memcpy(copy,s,len);
return copy;
}
KS_DECLARE(void)cJSON_InitHooks(cJSON_Hooks* hooks)
{
if (!hooks) { /* Reset hooks */
cJSON_malloc = malloc;
cJSON_free = free;
return;
}
if (!hooks) { /* Reset hooks */
cJSON_malloc = malloc;
cJSON_free = free;
return;
}
cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
cJSON_free = (hooks->free_fn)?hooks->free_fn:free;
@ -281,8 +281,8 @@ KS_DECLARE(cJSON *)cJSON_Parse(const char *value)
}
/* Render a cJSON item/entity/structure to text. */
KS_DECLARE(char *) cJSON_Print(cJSON *item) {return print_value(item,0,1);}
KS_DECLARE(char *) cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);}
KS_DECLARE(char *)cJSON_Print(cJSON *item) {return print_value(item,0,1);}
KS_DECLARE(char *)cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);}
/* Parser core - when encountering text, process appropriately. */
static const char *parse_value(cJSON *item,const char *value)
@ -349,7 +349,8 @@ static const char *parse_array(cJSON *item,const char *value)
static char *print_array(cJSON *item,int depth,int fmt)
{
char **entries;
char *out=0,*ptr,*ret;int len=5;
char *out=0,*ptr,*ret;
size_t len=5;
cJSON *child=item->child;
int numentries=0,i=0,fail=0;
@ -436,7 +437,8 @@ static const char *parse_object(cJSON *item,const char *value)
static char *print_object(cJSON *item,int depth,int fmt)
{
char **entries=0,**names=0;
char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
char *out=0,*ptr,*ret,*str;int i=0,j;
size_t len=7;
cJSON *child=item->child;
int numentries=0,fail=0;
/* Count the number of entries. */
@ -493,7 +495,20 @@ static char *print_object(cJSON *item,int depth,int fmt)
/* Get Array size/item / object item. */
KS_DECLARE(int) cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
KS_DECLARE(cJSON *)cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;}
KS_DECLARE(cJSON *)cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
KS_DECLARE(cJSON *)cJSON_GetObjectItem(const cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
KS_DECLARE(const char *)cJSON_GetObjectCstr(const cJSON *object, const char *string)
{
cJSON *cj = cJSON_GetObjectItem(object, string);
if (!cj || cj->type != cJSON_String || !cj->valuestring) return NULL;
return cj->valuestring;
}
/* Utility for array list handling. */
static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
@ -529,7 +544,68 @@ KS_DECLARE(cJSON *)cJSON_CreateArray() {cJSON *item=cJSON_New_Item();if(ite
KS_DECLARE(cJSON *)cJSON_CreateObject() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
/* Create Arrays: */
KS_DECLARE(cJSON *)cJSON_CreateIntArray(int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a!=0 && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
KS_DECLARE(cJSON *)cJSON_CreateFloatArray(float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a!=0 && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
KS_DECLARE(cJSON *)cJSON_CreateDoubleArray(double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a!=0 && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
KS_DECLARE(cJSON *)cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a!=0 && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
KS_DECLARE(cJSON *)cJSON_CreateIntArray(int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
KS_DECLARE(cJSON *)cJSON_CreateFloatArray(float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
KS_DECLARE(cJSON *)cJSON_CreateDoubleArray(double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
KS_DECLARE(cJSON *)cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
/* Duplication */
KS_DECLARE(cJSON *) cJSON_Duplicate(cJSON *item,int recurse)
{
cJSON *newitem,*cptr,*nptr=0,*newchild;
/* Bail on bad ptr */
if (!item) return 0;
/* Create new item */
newitem=cJSON_New_Item();
if (!newitem) return 0;
/* Copy over all vars */
newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;
if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}}
if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}}
/* If non-recursive, then we're done! */
if (!recurse) return newitem;
/* Walk the ->next chain for the child. */
cptr=item->child;
while (cptr) {
newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */
if (!newchild) {cJSON_Delete(newitem);return 0;}
if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */
else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */
cptr=cptr->next;
}
return newitem;
}
KS_DECLARE(cJSON *) cJSON_CreateStringPrintf(const char *fmt, ...)
{
va_list ap;
char *str;
cJSON *item;
va_start(ap, fmt);
str = ks_vmprintf(fmt, ap);
va_end(ap);
if (!str) return NULL;
if ((item = cJSON_New_Item())) {
item->type=cJSON_String;
item->valuestring = str;
} else {
free(str);
}
return item;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

123
libs/libks/src/ks_log.c Normal file
View File

@ -0,0 +1,123 @@
/*
* Copyright (c) 2007-2014, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <ks.h>
static void null_logger(const char *file, const char *func, int line, int level, const char *fmt, ...)
{
if (file && func && line && level && fmt) {
return;
}
return;
}
static const char *LEVEL_NAMES[] = {
"EMERG",
"ALERT",
"CRIT",
"ERROR",
"WARNING",
"NOTICE",
"INFO",
"DEBUG",
NULL
};
static int ks_log_level = 7;
static const char *cut_path(const char *in)
{
const char *p, *ret = in;
char delims[] = "/\\";
char *i;
for (i = delims; *i; i++) {
p = in;
while ((p = strchr(p, *i)) != 0) {
ret = ++p;
}
}
return ret;
}
static void default_logger(const char *file, const char *func, int line, int level, const char *fmt, ...)
{
const char *fp;
char *data;
va_list ap;
int ret;
if (level < 0 || level > 7) {
level = 7;
}
if (level > ks_log_level) {
return;
}
fp = cut_path(file);
va_start(ap, fmt);
ret = ks_vasprintf(&data, fmt, ap);
if (ret != -1) {
fprintf(stderr, "[%s] %s:%d %s() %s", LEVEL_NAMES[level], fp, line, func, data);
free(data);
}
va_end(ap);
}
ks_logger_t ks_log = null_logger;
KS_DECLARE(void) ks_global_set_logger(ks_logger_t logger)
{
if (logger) {
ks_log = logger;
} else {
ks_log = null_logger;
}
}
KS_DECLARE(void) ks_global_set_default_logger(int level)
{
if (level < 0 || level > 7) {
level = 7;
}
ks_log = default_logger;
ks_log_level = level;
}

648
libs/libks/src/ks_mutex.c Normal file
View File

@ -0,0 +1,648 @@
/*
* Cross Platform Thread/Mutex abstraction
* Copyright(C) 2007 Michael Jerris
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so.
*
* This work is provided under this license on an "as is" basis, without warranty of any kind,
* either expressed or implied, including, without limitation, warranties that the covered code
* is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire
* risk as to the quality and performance of the covered code is with you. Should any covered
* code prove defective in any respect, you (not the initial developer or any other contributor)
* assume the cost of any necessary servicing, repair or correction. This disclaimer of warranty
* constitutes an essential part of this license. No use of any covered code is authorized hereunder
* except under this disclaimer.
*
*/
#ifdef WIN32
/* required for TryEnterCriticalSection definition. Must be defined before windows.h include */
#define _WIN32_WINNT 0x0400
#endif
#include "ks.h"
#ifdef WIN32
#include <process.h>
#else
#include <pthread.h>
#endif
typedef enum {
KS_MUTEX_TYPE_DEFAULT,
KS_MUTEX_TYPE_NON_RECURSIVE
} ks_mutex_type_t;
struct ks_mutex {
#ifdef WIN32
CRITICAL_SECTION mutex;
HANDLE handle;
#else
pthread_mutex_t mutex;
#endif
ks_pool_t * pool;
ks_mutex_type_t type;
uint8_t malloc;
};
static void ks_mutex_cleanup(ks_pool_t *mpool, void *ptr, void *arg, int type, ks_pool_cleanup_action_t action, ks_pool_cleanup_type_t ctype)
{
ks_mutex_t *mutex = (ks_mutex_t *) ptr;
switch(action) {
case KS_MPCL_ANNOUNCE:
break;
case KS_MPCL_TEARDOWN:
break;
case KS_MPCL_DESTROY:
#ifdef WIN32
if (mutex->type == KS_MUTEX_TYPE_NON_RECURSIVE) {
CloseHandle(mutex->handle);
} else {
DeleteCriticalSection(&mutex->mutex);
}
#else
pthread_mutex_destroy(&mutex->mutex);
#endif
break;
}
}
KS_DECLARE(ks_status_t) ks_mutex_destroy(ks_mutex_t **mutexP)
{
ks_mutex_t *mutex;
ks_assert(mutexP);
mutex = *mutexP;
*mutexP = NULL;
if (!mutex) return KS_STATUS_FAIL;
if (mutex->malloc) {
#ifdef WIN32
if (mutex->type == KS_MUTEX_TYPE_NON_RECURSIVE) {
CloseHandle(mutex->handle);
} else {
DeleteCriticalSection(&mutex->mutex);
}
#else
pthread_mutex_destroy(&mutex->mutex);
#endif
free(mutex);
} else {
ks_pool_free(mutex->pool, (void *)mutex);
}
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) ks_mutex_create(ks_mutex_t **mutex, unsigned int flags, ks_pool_t *pool)
{
ks_status_t status = KS_STATUS_FAIL;
#ifndef WIN32
pthread_mutexattr_t attr;
#endif
ks_mutex_t *check = NULL;
if (pool) {
if (!(check = (ks_mutex_t *) ks_pool_alloc(pool, sizeof(**mutex)))) {
goto done;
}
} else {
check = malloc(sizeof(**mutex));
memset(check, 0, sizeof(**mutex));
check->malloc = 1;
}
check->pool = pool;
check->type = KS_MUTEX_TYPE_DEFAULT;
#ifdef WIN32
if (flags & KS_MUTEX_FLAG_NON_RECURSIVE) {
check->type = KS_MUTEX_TYPE_NON_RECURSIVE;
check->handle = CreateEvent(NULL, FALSE, TRUE, NULL);
} else {
InitializeCriticalSection(&check->mutex);
}
#else
if (flags & KS_MUTEX_FLAG_NON_RECURSIVE) {
if (pthread_mutex_init(&check->mutex, NULL))
goto done;
} else {
if (pthread_mutexattr_init(&attr))
goto done;
if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE))
goto fail;
if (pthread_mutex_init(&check->mutex, &attr))
goto fail;
}
goto success;
fail:
pthread_mutexattr_destroy(&attr);
goto done;
success:
#endif
*mutex = check;
status = KS_STATUS_SUCCESS;
if (pool) {
ks_pool_set_cleanup(pool, check, NULL, 0, ks_mutex_cleanup);
}
done:
return status;
}
KS_DECLARE(ks_status_t) ks_mutex_lock(ks_mutex_t *mutex)
{
#ifdef WIN32
if (mutex->type == KS_MUTEX_TYPE_NON_RECURSIVE) {
DWORD ret = WaitForSingleObject(mutex->handle, INFINITE);
if ((ret != WAIT_OBJECT_0) && (ret != WAIT_ABANDONED)) {
return KS_STATUS_FAIL;
}
} else {
EnterCriticalSection(&mutex->mutex);
}
#else
if (pthread_mutex_lock(&mutex->mutex))
return KS_STATUS_FAIL;
#endif
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) ks_mutex_trylock(ks_mutex_t *mutex)
{
#ifdef WIN32
if (mutex->type == KS_MUTEX_TYPE_NON_RECURSIVE) {
DWORD ret = WaitForSingleObject(mutex->handle, 0);
if ((ret != WAIT_OBJECT_0) && (ret != WAIT_ABANDONED)) {
return KS_STATUS_FAIL;
}
} else {
if (!TryEnterCriticalSection(&mutex->mutex))
return KS_STATUS_FAIL;
}
#else
if (pthread_mutex_trylock(&mutex->mutex))
return KS_STATUS_FAIL;
#endif
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) ks_mutex_unlock(ks_mutex_t *mutex)
{
#ifdef WIN32
if (mutex->type == KS_MUTEX_TYPE_NON_RECURSIVE) {
if (!SetEvent(mutex->handle)) {
return KS_STATUS_FAIL;
}
} else {
LeaveCriticalSection(&mutex->mutex);
}
#else
if (pthread_mutex_unlock(&mutex->mutex))
return KS_STATUS_FAIL;
#endif
return KS_STATUS_SUCCESS;
}
struct ks_cond {
ks_pool_t * pool;
ks_mutex_t *mutex;
#ifdef WIN32
CONDITION_VARIABLE cond;
#else
pthread_cond_t cond;
#endif
uint8_t static_mutex;
};
static void ks_cond_cleanup(ks_pool_t *mpool, void *ptr, void *arg, int type, ks_pool_cleanup_action_t action, ks_pool_cleanup_type_t ctype)
{
ks_cond_t *cond = (ks_cond_t *) ptr;
switch(action) {
case KS_MPCL_ANNOUNCE:
break;
case KS_MPCL_TEARDOWN:
break;
case KS_MPCL_DESTROY:
if (!cond->static_mutex) {
ks_mutex_destroy(&cond->mutex);
}
#ifndef WIN32
pthread_cond_destroy(&cond->cond);
#endif
break;
}
}
KS_DECLARE(ks_status_t) ks_cond_create_ex(ks_cond_t **cond, ks_pool_t *pool, ks_mutex_t *mutex)
{
ks_status_t status = KS_STATUS_FAIL;
ks_cond_t *check = NULL;
*cond = NULL;
if (!pool)
goto done;
if (!(check = (ks_cond_t *) ks_pool_alloc(pool, sizeof(**cond)))) {
goto done;
}
check->pool = pool;
if (mutex) {
check->mutex = mutex;
check->static_mutex = 1;
} else {
if (ks_mutex_create(&check->mutex, KS_MUTEX_FLAG_DEFAULT, pool) != KS_STATUS_SUCCESS) {
goto done;
}
}
#ifdef WIN32
InitializeConditionVariable(&check->cond);
#else
if (pthread_cond_init(&check->cond, NULL)) {
if (!check->static_mutex) {
ks_mutex_destroy(&check->mutex);
}
goto done;
}
#endif
*cond = check;
status = KS_STATUS_SUCCESS;
ks_pool_set_cleanup(pool, check, NULL, 0, ks_cond_cleanup);
done:
return status;
}
KS_DECLARE(ks_mutex_t *) ks_cond_get_mutex(ks_cond_t *cond)
{
return cond->mutex;
}
KS_DECLARE(ks_status_t) ks_cond_create(ks_cond_t **cond, ks_pool_t *pool)
{
return ks_cond_create_ex(cond, pool, NULL);
}
KS_DECLARE(ks_status_t) ks_cond_lock(ks_cond_t *cond)
{
return ks_mutex_lock(cond->mutex);
}
KS_DECLARE(ks_status_t) ks_cond_trylock(ks_cond_t *cond)
{
return ks_mutex_trylock(cond->mutex);
}
KS_DECLARE(ks_status_t) ks_cond_unlock(ks_cond_t *cond)
{
return ks_mutex_unlock(cond->mutex);
}
KS_DECLARE(ks_status_t) ks_cond_signal(ks_cond_t *cond)
{
ks_cond_lock(cond);
#ifdef WIN32
WakeConditionVariable(&cond->cond);
#else
pthread_cond_signal(&cond->cond);
#endif
ks_cond_unlock(cond);
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) ks_cond_broadcast(ks_cond_t *cond)
{
ks_cond_lock(cond);
#ifdef WIN32
WakeAllConditionVariable(&cond->cond);
#else
pthread_cond_broadcast(&cond->cond);
#endif
ks_cond_unlock(cond);
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) ks_cond_try_signal(ks_cond_t *cond)
{
if (ks_cond_trylock(cond) != KS_STATUS_SUCCESS) {
return KS_STATUS_FAIL;
}
#ifdef WIN32
WakeConditionVariable(&cond->cond);
#else
pthread_cond_signal(&cond->cond);
#endif
ks_cond_unlock(cond);
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) ks_cond_try_broadcast(ks_cond_t *cond)
{
if (ks_cond_trylock(cond) != KS_STATUS_SUCCESS) {
return KS_STATUS_FAIL;
}
#ifdef WIN32
WakeAllConditionVariable(&cond->cond);
#else
pthread_cond_broadcast(&cond->cond);
#endif
ks_cond_unlock(cond);
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) ks_cond_wait(ks_cond_t *cond)
{
#ifdef WIN32
SleepConditionVariableCS(&cond->cond, &cond->mutex->mutex, INFINITE);
#else
pthread_cond_wait(&cond->cond, &cond->mutex->mutex);
#endif
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) ks_cond_timedwait(ks_cond_t *cond, ks_time_t ms)
{
#ifdef WIN32
if(!SleepConditionVariableCS(&cond->cond, &cond->mutex->mutex, (DWORD)ms)) {
if (GetLastError() == ERROR_TIMEOUT) {
return KS_STATUS_TIMEOUT;
} else {
return KS_STATUS_FAIL;
}
}
#else
struct timespec ts;
ks_time_t n = ks_time_now() + (ms * 1000);
ts.tv_sec = ks_time_sec(n);
ts.tv_nsec = ks_time_nsec(n);
if (pthread_cond_timedwait(&cond->cond, &cond->mutex->mutex, &ts)) {
switch(errno) {
case ETIMEDOUT:
return KS_STATUS_TIMEOUT;
default:
return KS_STATUS_FAIL;
}
}
#endif
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) ks_cond_destroy(ks_cond_t **cond)
{
ks_cond_t *condp = *cond;
if (!condp) {
return KS_STATUS_FAIL;
}
*cond = NULL;
return ks_pool_free(condp->pool, condp);
}
struct ks_rwl {
#ifdef WIN32
SRWLOCK rwlock;
ks_hash_t *read_lock_list;
#else
pthread_rwlock_t rwlock;
#endif
ks_pool_t *pool;
ks_thread_os_handle_t write_locker;
uint32_t wlc;
};
static void ks_rwl_cleanup(ks_pool_t *mpool, void *ptr, void *arg, int type, ks_pool_cleanup_action_t action, ks_pool_cleanup_type_t ctype)
{
#ifndef WIN32
ks_rwl_t *rwlock = (ks_rwl_t *) ptr;
#endif
switch(action) {
case KS_MPCL_ANNOUNCE:
break;
case KS_MPCL_TEARDOWN:
break;
case KS_MPCL_DESTROY:
#ifndef WIN32
pthread_rwlock_destroy(&rwlock->rwlock);
#endif
break;
}
}
KS_DECLARE(ks_status_t) ks_rwl_create(ks_rwl_t **rwlock, ks_pool_t *pool)
{
ks_status_t status = KS_STATUS_FAIL;
ks_rwl_t *check = NULL;
*rwlock = NULL;
if (!pool) {
goto done;
}
if (!(check = (ks_rwl_t *) ks_pool_alloc(pool, sizeof(**rwlock)))) {
goto done;
}
check->pool = pool;
#ifdef WIN32
if (ks_hash_create(&check->read_lock_list, KS_HASH_MODE_PTR, KS_HASH_FLAG_NONE, pool) != KS_STATUS_SUCCESS) {
goto done;
}
InitializeSRWLock(&check->rwlock);
#else
if ((pthread_rwlock_init(&check->rwlock, NULL))) {
goto done;
}
#endif
*rwlock = check;
status = KS_STATUS_SUCCESS;
ks_pool_set_cleanup(pool, check, NULL, 0, ks_rwl_cleanup);
done:
return status;
}
KS_DECLARE(ks_status_t) ks_rwl_read_lock(ks_rwl_t *rwlock)
{
#ifdef WIN32
int count = (int)(intptr_t)ks_hash_remove(rwlock->read_lock_list, (void *)(intptr_t)ks_thread_self());
if (count) {
ks_hash_insert(rwlock->read_lock_list, (void *)(intptr_t)ks_thread_self(), (void *)(intptr_t)++count);
return KS_STATUS_SUCCESS;
}
AcquireSRWLockShared(&rwlock->rwlock);
#else
pthread_rwlock_rdlock(&rwlock->rwlock);
#endif
#ifdef WIN32
ks_hash_insert(rwlock->read_lock_list, (void *)(intptr_t)ks_thread_self(), (void *)(intptr_t)(int)1);
#endif
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) ks_rwl_write_lock(ks_rwl_t *rwlock)
{
int me = (rwlock->write_locker == ks_thread_self());
if (me) {
rwlock->wlc++;
return KS_STATUS_SUCCESS;
}
#ifdef WIN32
AcquireSRWLockExclusive(&rwlock->rwlock);
#else
pthread_rwlock_wrlock(&rwlock->rwlock);
#endif
rwlock->write_locker = ks_thread_self();
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) ks_rwl_try_read_lock(ks_rwl_t *rwlock)
{
#ifdef WIN32
int count = (int)(intptr_t)ks_hash_remove(rwlock->read_lock_list, (void *)(intptr_t)ks_thread_self());
if (count) {
ks_hash_insert(rwlock->read_lock_list, (void *)(intptr_t)ks_thread_self(), (void *)(intptr_t)++count);
return KS_STATUS_SUCCESS;
}
if (!TryAcquireSRWLockShared(&rwlock->rwlock)) {
return KS_STATUS_FAIL;
}
#else
if (pthread_rwlock_tryrdlock(&rwlock->rwlock)) {
return KS_STATUS_FAIL;
}
#endif
#ifdef WIN32
ks_hash_insert(rwlock->read_lock_list, (void *)(intptr_t)ks_thread_self(), (void *)(intptr_t)(int)1);
#endif
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) ks_rwl_try_write_lock(ks_rwl_t *rwlock)
{
int me = (rwlock->write_locker == ks_thread_self());
if (me) {
rwlock->wlc++;
return KS_STATUS_SUCCESS;
}
#ifdef WIN32
if (!TryAcquireSRWLockExclusive(&rwlock->rwlock)) {
return KS_STATUS_FAIL;
}
#else
if (pthread_rwlock_trywrlock(&rwlock->rwlock)) {
return KS_STATUS_FAIL;
}
#endif
rwlock->write_locker = ks_thread_self();
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) ks_rwl_read_unlock(ks_rwl_t *rwlock)
{
#ifdef WIN32
int count = (int)(intptr_t)ks_hash_remove(rwlock->read_lock_list, (void *)(intptr_t)ks_thread_self());
if (count > 1) {
ks_hash_insert(rwlock->read_lock_list, (void *)(intptr_t)ks_thread_self(), (void *)(intptr_t)--count);
return KS_STATUS_SUCCESS;
}
ReleaseSRWLockShared(&rwlock->rwlock);
#else
pthread_rwlock_unlock(&rwlock->rwlock);
#endif
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) ks_rwl_write_unlock(ks_rwl_t *rwlock)
{
int me = (rwlock->write_locker == ks_thread_self());
if (me && rwlock->wlc > 0) {
rwlock->wlc--;
return KS_STATUS_SUCCESS;
}
rwlock->write_locker = 0;
#ifdef WIN32
ReleaseSRWLockExclusive(&rwlock->rwlock);
#else
pthread_rwlock_unlock(&rwlock->rwlock);
#endif
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) ks_rwl_destroy(ks_rwl_t **rwlock)
{
ks_rwl_t *rwlockp = *rwlock;
if (!rwlockp) {
return KS_STATUS_FAIL;
}
*rwlock = NULL;
return ks_pool_free(rwlockp->pool, rwlockp);
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

2171
libs/libks/src/ks_pool.c Normal file

File diff suppressed because it is too large Load Diff

980
libs/libks/src/ks_printf.c Normal file
View File

@ -0,0 +1,980 @@
/*
** The "printf" code that follows dates from the 1980's. It is in
** the public domain. The original comments are included here for
** completeness. They are very out-of-date but might be useful as
** an historical reference. Most of the "enhancements" have been backed
** out so that the functionality is now the same as standard printf().
**
**************************************************************************
**
** The following modules is an enhanced replacement for the "printf" subroutines
** found in the standard C library. The following enhancements are
** supported:
**
** + Additional functions. The standard set of "printf" functions
** includes printf, fprintf, sprintf, vprintf, vfprintf, and
** vsprintf. This module adds the following:
**
** * snprintf -- Works like sprintf, but has an extra argument
** which is the size of the buffer written to.
**
** * mprintf -- Similar to sprintf. Writes output to memory
** obtained from malloc.
**
** * xprintf -- Calls a function to dispose of output.
**
** * nprintf -- No output, but returns the number of characters
** that would have been output by printf.
**
** * A v- version (ex: vsnprintf) of every function is also
** supplied.
**
** + A few extensions to the formatting notation are supported:
**
** * The "=" flag (similar to "-") causes the output to be
** be centered in the appropriately sized field.
**
** * The %b field outputs an integer in binary notation.
**
** * The %c field now accepts a precision. The character output
** is repeated by the number of times the precision specifies.
**
** * The %' field works like %c, but takes as its character the
** next character of the format string, instead of the next
** argument. For example, printf("%.78'-") prints 78 minus
** signs, the same as printf("%.78c",'-').
**
** + When compiled using GCC on a SPARC, this version of printf is
** faster than the library printf for SUN OS 4.1.
**
** + All functions are fully reentrant.
**
*/
/*
* 20090210 (stkn):
* Taken from sqlite-3.3.x,
* renamed SQLITE_ -> KS_,
* renamed visible functions to ks_*
* disabled functions without extra conversion specifiers
*/
#include <ks.h>
#define LONGDOUBLE_TYPE long double
/*
** Conversion types fall into various categories as defined by the
** following enumeration.
*/
#define etRADIX 1 /* Integer types. %d, %x, %o, and so forth */
#define etFLOAT 2 /* Floating point. %f */
#define etEXP 3 /* Exponentional notation. %e and %E */
#define etGENERIC 4 /* Floating or exponential, depending on exponent. %g */
#define etSIZE 5 /* Return number of characters processed so far. %n */
#define etSTRING 6 /* Strings. %s */
#define etDYNSTRING 7 /* Dynamically allocated strings. %z */
#define etPERCENT 8 /* Percent symbol. %% */
#define etCHARX 9 /* Characters. %c */
/* The rest are extensions, not normally found in printf() */
#define etCHARLIT 10 /* Literal characters. %' */
#define etSQLESCAPE 11 /* Strings with '\'' doubled. %q */
#define etSQLESCAPE2 12 /* Strings with '\'' doubled and enclosed in '',
NULL pointers replaced by SQL NULL. %Q */
#ifdef __UNSUPPORTED__
#define etTOKEN 13 /* a pointer to a Token structure */
#define etSRCLIST 14 /* a pointer to a SrcList */
#endif
#define etPOINTER 15 /* The %p conversion */
#define etSQLESCAPE3 16
#define etSQLESCAPE4 17
/*
** An "etByte" is an 8-bit unsigned value.
*/
typedef unsigned char etByte;
/*
** Each builtin conversion character (ex: the 'd' in "%d") is described
** by an instance of the following structure
*/
typedef struct et_info { /* Information about each format field */
char fmttype; /* The format field code letter */
etByte base; /* The base for radix conversion */
etByte flags; /* One or more of FLAG_ constants below */
etByte type; /* Conversion paradigm */
etByte charset; /* Offset into aDigits[] of the digits string */
etByte prefix; /* Offset into aPrefix[] of the prefix string */
} et_info;
/*
** Allowed values for et_info.flags
*/
#define FLAG_SIGNED 1 /* True if the value to convert is signed */
#define FLAG_INTERN 2 /* True if for internal use only */
#define FLAG_STRING 4 /* Allow infinity precision */
/*
** The following table is searched linearly, so it is good to put the
** most frequently used conversion types first.
*/
static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";
static const char aPrefix[] = "-x0\000X0";
static const et_info fmtinfo[] = {
{'d', 10, 1, etRADIX, 0, 0},
{'s', 0, 4, etSTRING, 0, 0},
{'g', 0, 1, etGENERIC, 30, 0},
{'z', 0, 6, etDYNSTRING, 0, 0},
{'q', 0, 4, etSQLESCAPE, 0, 0},
{'Q', 0, 4, etSQLESCAPE2, 0, 0},
{'w', 0, 4, etSQLESCAPE3, 0, 0},
{'y', 0, 4, etSQLESCAPE4, 0, 0},
{'c', 0, 0, etCHARX, 0, 0},
{'o', 8, 0, etRADIX, 0, 2},
{'u', 10, 0, etRADIX, 0, 0},
{'x', 16, 0, etRADIX, 16, 1},
{'X', 16, 0, etRADIX, 0, 4},
#ifndef KS_OMIT_FLOATING_POINT
{'f', 0, 1, etFLOAT, 0, 0},
{'e', 0, 1, etEXP, 30, 0},
{'E', 0, 1, etEXP, 14, 0},
{'G', 0, 1, etGENERIC, 14, 0},
#endif
{'i', 10, 1, etRADIX, 0, 0},
{'n', 0, 0, etSIZE, 0, 0},
{'%', 0, 0, etPERCENT, 0, 0},
{'p', 16, 0, etPOINTER, 0, 1},
#ifdef __UNSUPPORTED__
{'T', 0, 2, etTOKEN, 0, 0},
{'S', 0, 2, etSRCLIST, 0, 0},
#endif
};
#define etNINFO (sizeof(fmtinfo)/sizeof(fmtinfo[0]))
/*
** If KS_OMIT_FLOATING_POINT is defined, then none of the floating point
** conversions will work.
*/
#ifndef KS_OMIT_FLOATING_POINT
/*
** "*val" is a double such that 0.1 <= *val < 10.0
** Return the ascii code for the leading digit of *val, then
** multiply "*val" by 10.0 to renormalize.
**
** Example:
** input: *val = 3.14159
** output: *val = 1.4159 function return = '3'
**
** The counter *cnt is incremented each time. After counter exceeds
** 16 (the number of significant digits in a 64-bit float) '0' is
** always returned.
*/
static int et_getdigit(LONGDOUBLE_TYPE * val, int *cnt)
{
int digit;
LONGDOUBLE_TYPE d;
if ((*cnt)++ >= 16)
return '0';
digit = (int) *val;
d = digit;
digit += '0';
*val = (*val - d) * 10.0;
return digit;
}
#endif /* KS_OMIT_FLOATING_POINT */
/*
** On machines with a small stack size, you can redefine the
** KS_PRINT_BUF_SIZE to be less than 350. But beware - for
** smaller values some %f conversions may go into an infinite loop.
*/
#ifndef KS_PRINT_BUF_SIZE
# define KS_PRINT_BUF_SIZE 350
#endif
#define etBUFSIZE KS_PRINT_BUF_SIZE /* Size of the output buffer */
/*
** The root program. All variations call this core.
**
** INPUTS:
** func This is a pointer to a function taking three arguments
** 1. A pointer to anything. Same as the "arg" parameter.
** 2. A pointer to the list of characters to be output
** (Note, this list is NOT null terminated.)
** 3. An integer number of characters to be output.
** (Note: This number might be zero.)
**
** arg This is the pointer to anything which will be passed as the
** first argument to "func". Use it for whatever you like.
**
** fmt This is the format string, as in the usual print.
**
** ap This is a pointer to a list of arguments. Same as in
** vfprint.
**
** OUTPUTS:
** The return value is the total number of characters sent to
** the function "func". Returns -1 on a error.
**
** Note that the order in which automatic variables are declared below
** seems to make a big difference in determining how fast this beast
** will run.
*/
static int vxprintf(void (*func) (void *, const char *, int), /* Consumer of text */
void *arg, /* First argument to the consumer */
int useExtended, /* Allow extended %-conversions */
const char *fmt, /* Format string */
va_list ap /* arguments */
)
{
int c; /* Next character in the format string */
char *bufpt; /* Pointer to the conversion buffer */
int precision; /* Precision of the current field */
int length; /* Length of the field */
int idx; /* A general purpose loop counter */
int count; /* Total number of characters output */
int width; /* Width of the current field */
etByte flag_leftjustify; /* True if "-" flag is present */
etByte flag_plussign; /* True if "+" flag is present */
etByte flag_blanksign; /* True if " " flag is present */
etByte flag_alternateform; /* True if "#" flag is present */
etByte flag_altform2; /* True if "!" flag is present */
etByte flag_zeropad; /* True if field width constant starts with zero */
etByte flag_long; /* True if "l" flag is present */
etByte flag_longlong; /* True if the "ll" flag is present */
etByte done; /* Loop termination flag */
uint64_t longvalue; /* Value for integer types */
LONGDOUBLE_TYPE realvalue; /* Value for real types */
const et_info *infop; /* Pointer to the appropriate info structure */
char buf[etBUFSIZE]; /* Conversion buffer */
char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
etByte errorflag = 0; /* True if an error is encountered */
etByte xtype = 0; /* Conversion paradigm */
char *zExtra; /* Extra memory used for etTCLESCAPE conversions */
static const char spaces[] = " ";
#define etSPACESIZE (sizeof(spaces)-1)
#ifndef KS_OMIT_FLOATING_POINT
int exp, e2; /* exponent of real numbers */
double rounder; /* Used for rounding floating point values */
etByte flag_dp; /* True if decimal point should be shown */
etByte flag_rtz; /* True if trailing zeros should be removed */
etByte flag_exp; /* True to force display of the exponent */
int nsd; /* Number of significant digits returned */
#endif
func(arg, "", 0);
count = length = 0;
bufpt = 0;
for (; (c = (*fmt)) != 0; ++fmt) {
if (c != '%') {
int amt;
bufpt = (char *) fmt;
amt = 1;
while ((c = (*++fmt)) != '%' && c != 0)
amt++;
(*func) (arg, bufpt, amt);
count += amt;
if (c == 0)
break;
}
if ((c = (*++fmt)) == 0) {
errorflag = 1;
(*func) (arg, "%", 1);
count++;
break;
}
/* Find out what flags are present */
flag_leftjustify = flag_plussign = flag_blanksign = flag_alternateform = flag_altform2 = flag_zeropad = 0;
done = 0;
do {
switch (c) {
case '-':
flag_leftjustify = 1;
break;
case '+':
flag_plussign = 1;
break;
case ' ':
flag_blanksign = 1;
break;
case '#':
flag_alternateform = 1;
break;
case '!':
flag_altform2 = 1;
break;
case '0':
flag_zeropad = 1;
break;
default:
done = 1;
break;
}
} while (!done && (c = (*++fmt)) != 0);
/* Get the field width */
width = 0;
if (c == '*') {
width = va_arg(ap, int);
if (width < 0) {
flag_leftjustify = 1;
width = -width;
}
c = *++fmt;
} else {
while (c >= '0' && c <= '9') {
width = width * 10 + c - '0';
c = *++fmt;
}
}
if (width > etBUFSIZE - 10) {
width = etBUFSIZE - 10;
}
/* Get the precision */
if (c == '.') {
precision = 0;
c = *++fmt;
if (c == '*') {
precision = va_arg(ap, int);
if (precision < 0)
precision = -precision;
c = *++fmt;
} else {
while (c >= '0' && c <= '9') {
precision = precision * 10 + c - '0';
c = *++fmt;
}
}
} else {
precision = -1;
}
/* Get the conversion type modifier */
if (c == 'l') {
flag_long = 1;
c = *++fmt;
if (c == 'l') {
flag_longlong = 1;
c = *++fmt;
} else {
flag_longlong = 0;
}
} else {
flag_long = flag_longlong = 0;
}
/* Fetch the info entry for the field */
infop = 0;
for (idx = 0; idx < etNINFO; idx++) {
if (c == fmtinfo[idx].fmttype) {
infop = &fmtinfo[idx];
if (useExtended || (infop->flags & FLAG_INTERN) == 0) {
xtype = infop->type;
} else {
return -1;
}
break;
}
}
zExtra = 0;
if (infop == 0) {
return -1;
}
/* Limit the precision to prevent overflowing buf[] during conversion */
if (precision > etBUFSIZE - 40 && (infop->flags & FLAG_STRING) == 0) {
precision = etBUFSIZE - 40;
}
/*
** At this point, variables are initialized as follows:
**
** flag_alternateform TRUE if a '#' is present.
** flag_altform2 TRUE if a '!' is present.
** flag_plussign TRUE if a '+' is present.
** flag_leftjustify TRUE if a '-' is present or if the
** field width was negative.
** flag_zeropad TRUE if the width began with 0.
** flag_long TRUE if the letter 'l' (ell) prefixed
** the conversion character.
** flag_longlong TRUE if the letter 'll' (ell ell) prefixed
** the conversion character.
** flag_blanksign TRUE if a ' ' is present.
** width The specified field width. This is
** always non-negative. Zero is the default.
** precision The specified precision. The default
** is -1.
** xtype The class of the conversion.
** infop Pointer to the appropriate info struct.
*/
switch (xtype) {
case etPOINTER:
flag_longlong = sizeof(char *) == sizeof(int64_t);
flag_long = sizeof(char *) == sizeof(long int);
/* Fall through into the next case */
case etRADIX:
if (infop->flags & FLAG_SIGNED) {
int64_t v;
if (flag_longlong)
v = va_arg(ap, int64_t);
else if (flag_long)
v = va_arg(ap, long int);
else
v = va_arg(ap, int);
if (v < 0) {
longvalue = -v;
prefix = '-';
} else {
longvalue = v;
if (flag_plussign)
prefix = '+';
else if (flag_blanksign)
prefix = ' ';
else
prefix = 0;
}
} else {
if (flag_longlong)
longvalue = va_arg(ap, uint64_t);
else if (flag_long)
longvalue = va_arg(ap, unsigned long int);
else
longvalue = va_arg(ap, unsigned int);
prefix = 0;
}
if (longvalue == 0)
flag_alternateform = 0;
if (flag_zeropad && precision < width - (prefix != 0)) {
precision = width - (prefix != 0);
}
bufpt = &buf[etBUFSIZE - 1];
{
register const char *cset; /* Use registers for speed */
register int base;
cset = &aDigits[infop->charset];
base = infop->base;
do { /* Convert to ascii */
*(--bufpt) = cset[longvalue % base];
longvalue = longvalue / base;
} while (longvalue > 0);
}
length = (int)(&buf[etBUFSIZE - 1] - bufpt);
for (idx = precision - length; idx > 0; idx--) {
*(--bufpt) = '0'; /* Zero pad */
}
if (prefix)
*(--bufpt) = prefix; /* Add sign */
if (flag_alternateform && infop->prefix) { /* Add "0" or "0x" */
const char *pre;
char x;
pre = &aPrefix[infop->prefix];
if (*bufpt != pre[0]) {
for (; (x = (*pre)) != 0; pre++)
*(--bufpt) = x;
}
}
length = (int)(&buf[etBUFSIZE - 1] - bufpt);
break;
case etFLOAT:
case etEXP:
case etGENERIC:
realvalue = va_arg(ap, double);
#ifndef KS_OMIT_FLOATING_POINT
if (precision < 0)
precision = 6; /* Set default precision */
if (precision > etBUFSIZE / 2 - 10)
precision = etBUFSIZE / 2 - 10;
if (realvalue < 0.0) {
realvalue = -realvalue;
prefix = '-';
} else {
if (flag_plussign)
prefix = '+';
else if (flag_blanksign)
prefix = ' ';
else
prefix = 0;
}
if (xtype == etGENERIC && precision > 0)
precision--;
#if 0
/* Rounding works like BSD when the constant 0.4999 is used. Wierd! */
for (idx = precision, rounder = 0.4999; idx > 0; idx--, rounder *= 0.1);
#else
/* It makes more sense to use 0.5 */
for (idx = precision, rounder = 0.5; idx > 0; idx--, rounder *= 0.1) {
}
#endif
if (xtype == etFLOAT)
realvalue += rounder;
/* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
exp = 0;
if (realvalue > 0.0) {
while (realvalue >= 1e32 && exp <= 350) {
realvalue *= 1e-32;
exp += 32;
}
while (realvalue >= 1e8 && exp <= 350) {
realvalue *= 1e-8;
exp += 8;
}
while (realvalue >= 10.0 && exp <= 350) {
realvalue *= 0.1;
exp++;
}
while (realvalue < 1e-8 && exp >= -350) {
realvalue *= 1e8;
exp -= 8;
}
while (realvalue < 1.0 && exp >= -350) {
realvalue *= 10.0;
exp--;
}
if (exp > 350 || exp < -350) {
bufpt = "NaN";
length = 3;
break;
}
}
bufpt = buf;
/*
** If the field type is etGENERIC, then convert to either etEXP
** or etFLOAT, as appropriate.
*/
flag_exp = xtype == etEXP;
if (xtype != etFLOAT) {
realvalue += rounder;
if (realvalue >= 10.0) {
realvalue *= 0.1;
exp++;
}
}
if (xtype == etGENERIC) {
flag_rtz = !flag_alternateform;
if (exp < -4 || exp > precision) {
xtype = etEXP;
} else {
precision = precision - exp;
xtype = etFLOAT;
}
} else {
flag_rtz = 0;
}
if (xtype == etEXP) {
e2 = 0;
} else {
e2 = exp;
}
nsd = 0;
flag_dp = (precision > 0) | flag_alternateform | flag_altform2;
/* The sign in front of the number */
if (prefix) {
*(bufpt++) = prefix;
}
/* Digits prior to the decimal point */
if (e2 < 0) {
*(bufpt++) = '0';
} else {
for (; e2 >= 0; e2--) {
*(bufpt++) = (char) et_getdigit(&realvalue, &nsd);
}
}
/* The decimal point */
if (flag_dp) {
*(bufpt++) = '.';
}
/* "0" digits after the decimal point but before the first
** significant digit of the number */
for (e2++; e2 < 0 && precision > 0; precision--, e2++) {
*(bufpt++) = '0';
}
/* Significant digits after the decimal point */
while ((precision--) > 0) {
*(bufpt++) = (char) et_getdigit(&realvalue, &nsd);
}
/* Remove trailing zeros and the "." if no digits follow the "." */
if (flag_rtz && flag_dp) {
while (bufpt[-1] == '0')
*(--bufpt) = 0;
assert(bufpt > buf);
if (bufpt[-1] == '.') {
if (flag_altform2) {
*(bufpt++) = '0';
} else {
*(--bufpt) = 0;
}
}
}
/* Add the "eNNN" suffix */
if (flag_exp || (xtype == etEXP && exp)) {
*(bufpt++) = aDigits[infop->charset];
if (exp < 0) {
*(bufpt++) = '-';
exp = -exp;
} else {
*(bufpt++) = '+';
}
if (exp >= 100) {
*(bufpt++) = (char) (exp / 100) + '0'; /* 100's digit */
exp %= 100;
}
*(bufpt++) = (char) exp / 10 + '0'; /* 10's digit */
*(bufpt++) = exp % 10 + '0'; /* 1's digit */
}
*bufpt = 0;
/* The converted number is in buf[] and zero terminated. Output it.
** Note that the number is in the usual order, not reversed as with
** integer conversions. */
length = (int)(bufpt - buf);
bufpt = buf;
/* Special case: Add leading zeros if the flag_zeropad flag is
** set and we are not left justified */
if (flag_zeropad && !flag_leftjustify && length < width) {
int i;
int nPad = width - length;
for (i = width; i >= nPad; i--) {
bufpt[i] = bufpt[i - nPad];
}
i = prefix != 0;
while (nPad--)
bufpt[i++] = '0';
length = width;
}
#endif
break;
case etSIZE:
*(va_arg(ap, int *)) = count;
length = width = 0;
break;
case etPERCENT:
buf[0] = '%';
bufpt = buf;
length = 1;
break;
case etCHARLIT:
case etCHARX:
c = buf[0] = (char) (xtype == etCHARX ? va_arg(ap, int) : *++fmt);
if (precision >= 0) {
for (idx = 1; idx < precision; idx++)
buf[idx] = (char) c;
length = precision;
} else {
length = 1;
}
bufpt = buf;
break;
case etSTRING:
case etDYNSTRING:
bufpt = va_arg(ap, char *);
if (bufpt == 0) {
bufpt = "";
} else if (xtype == etDYNSTRING) {
zExtra = bufpt;
}
length = (int)strlen(bufpt);
if (precision >= 0 && precision < length)
length = precision;
break;
case etSQLESCAPE:
case etSQLESCAPE2:
case etSQLESCAPE4:
case etSQLESCAPE3:{
int i, j, n, ch, isnull;
int needQuote;
char *escarg = va_arg(ap, char *);
isnull = escarg == 0;
if (isnull)
escarg = (xtype == etSQLESCAPE2 ? "NULL" : "(NULL)");
for (i = n = 0; (ch = escarg[i]) != 0; i++) {
if (ch == '\'' || (xtype == etSQLESCAPE3 && ch == '\\'))
n++;
}
needQuote = !isnull && xtype == etSQLESCAPE2;
n += i + 1 + needQuote * 2;
if (n > etBUFSIZE) {
bufpt = zExtra = malloc(n);
if (bufpt == 0)
return -1;
} else {
bufpt = buf;
}
j = 0;
if (needQuote)
bufpt[j++] = '\'';
for (i = 0; (ch = escarg[i]) != 0; i++) {
bufpt[j++] = (char) ch;
if (xtype == etSQLESCAPE4) {
if (ch == '\'' || (xtype == etSQLESCAPE3 && ch == '\\')) {
bufpt[j] = (char) ch;
bufpt[j-1] = (char) '\\';
j++;
}
} else {
if (ch == '\'' || (xtype == etSQLESCAPE3 && ch == '\\'))
bufpt[j++] = (char) ch;
}
}
if (needQuote)
bufpt[j++] = '\'';
bufpt[j] = 0;
length = j;
/* The precision is ignored on %q and %Q */
/* if ( precision>=0 && precision<length ) length = precision; */
break;
}
#ifdef __UNSUPPORTED__
case etTOKEN:{
Token *pToken = va_arg(ap, Token *);
if (pToken && pToken->z) {
(*func) (arg, (char *) pToken->z, pToken->n);
}
length = width = 0;
break;
}
case etSRCLIST:{
SrcList *pSrc = va_arg(ap, SrcList *);
int k = va_arg(ap, int);
struct SrcList_item *pItem = &pSrc->a[k];
assert(k >= 0 && k < pSrc->nSrc);
if (pItem->zDatabase && pItem->zDatabase[0]) {
(*func) (arg, pItem->zDatabase, strlen(pItem->zDatabase));
(*func) (arg, ".", 1);
}
(*func) (arg, pItem->zName, strlen(pItem->zName));
length = width = 0;
break;
}
#endif
} /* End switch over the format type */
/*
** The text of the conversion is pointed to by "bufpt" and is
** "length" characters long. The field width is "width". Do
** the output.
*/
if (!flag_leftjustify) {
register int nspace;
nspace = width - length;
if (nspace > 0) {
count += nspace;
while (nspace >= etSPACESIZE) {
(*func) (arg, spaces, etSPACESIZE);
nspace -= etSPACESIZE;
}
if (nspace > 0)
(*func) (arg, spaces, nspace);
}
}
if (length > 0) {
(*func) (arg, bufpt, length);
count += length;
}
if (flag_leftjustify) {
register int nspace;
nspace = width - length;
if (nspace > 0) {
count += nspace;
while (nspace >= etSPACESIZE) {
(*func) (arg, spaces, etSPACESIZE);
nspace -= etSPACESIZE;
}
if (nspace > 0)
(*func) (arg, spaces, nspace);
}
}
if (zExtra) {
free(zExtra);
}
} /* End for loop over the format string */
return errorflag ? -1 : count;
} /* End of function */
/* This structure is used to store state information about the
** write to memory that is currently in progress.
*/
struct sgMprintf {
char *zBase; /* A base allocation */
char *zText; /* The string collected so far */
int nChar; /* Length of the string so far */
int nTotal; /* Output size if unconstrained */
int nAlloc; /* Amount of space allocated in zText */
void *arg; /* Third arg to the realloc callback */
void *(*xRealloc) (void *, int, void *); /* Function used to realloc memory */
};
/*
** This function implements the callback from vxprintf.
**
** This routine add nNewChar characters of text in zNewText to
** the sgMprintf structure pointed to by "arg".
*/
static void mout(void *arg, const char *zNewText, int nNewChar)
{
struct sgMprintf *pM = (struct sgMprintf *) arg;
pM->nTotal += nNewChar;
if (pM->nChar + nNewChar + 1 > pM->nAlloc) {
if (pM->xRealloc == 0) {
nNewChar = pM->nAlloc - pM->nChar - 1;
} else {
pM->nAlloc = pM->nChar + nNewChar * 2 + 1;
if (pM->zText == pM->zBase) {
pM->zText = pM->xRealloc(0, pM->nAlloc, pM->arg);
if (pM->zText && pM->nChar) {
memcpy(pM->zText, pM->zBase, pM->nChar);
}
} else {
char *zNew;
zNew = pM->xRealloc(pM->zText, pM->nAlloc, pM->arg);
if (zNew) {
pM->zText = zNew;
}
}
}
}
if (pM->zText) {
if (nNewChar > 0) {
memcpy(&pM->zText[pM->nChar], zNewText, nNewChar);
pM->nChar += nNewChar;
}
pM->zText[pM->nChar] = 0;
}
}
/*
** This routine is a wrapper around xprintf() that invokes mout() as
** the consumer.
*/
static char *base_vprintf(void *(*xRealloc) (void *, int, void *), /* Routine to realloc memory. May be NULL */
int useInternal, /* Use internal %-conversions if true */
char *zInitBuf, /* Initially write here, before mallocing */
int nInitBuf, /* Size of zInitBuf[] */
const char *zFormat, /* format string */
va_list ap, /* arguments */
void *realloc_arg /*arg to pass to realloc function*/
)
{
struct sgMprintf sM;
sM.zBase = sM.zText = zInitBuf;
sM.nChar = sM.nTotal = 0;
sM.nAlloc = nInitBuf;
sM.xRealloc = xRealloc;
sM.arg = realloc_arg;
vxprintf(mout, &sM, useInternal, zFormat, ap);
if (xRealloc) {
if (sM.zText == sM.zBase) {
sM.zText = xRealloc(0, sM.nChar + 1, realloc_arg);
if (sM.zText) {
memcpy(sM.zText, sM.zBase, sM.nChar + 1);
}
} else if (sM.nAlloc > sM.nChar + 10) {
char *zNew = xRealloc(sM.zText, sM.nChar + 1, realloc_arg);
if (zNew) {
sM.zText = zNew;
}
}
}
return sM.zText;
}
/*
** Realloc that is a real function, not a macro.
*/
static void *printf_realloc(void *old, int size, void *arg)
{
return realloc(old, size);
}
/*
** Print into memory. Omit the internal %-conversion extensions.
*/
KS_DECLARE(char *) ks_vmprintf(const char *zFormat, va_list ap)
{
char zBase[KS_PRINT_BUF_SIZE];
return base_vprintf(printf_realloc, 0, zBase, sizeof(zBase), zFormat, ap, NULL);
}
/*
** Print into memory. Omit the internal %-conversion extensions.
*/
KS_DECLARE(char *) ks_mprintf(const char *zFormat, ...)
{
va_list ap;
char *z;
char zBase[KS_PRINT_BUF_SIZE];
va_start(ap, zFormat);
z = base_vprintf(printf_realloc, 0, zBase, sizeof(zBase), zFormat, ap, NULL);
va_end(ap);
return z;
}
/*
** pool_realloc function
*/
static void *pool_realloc(void *old, int size, void *arg)
{
return ks_pool_resize(arg, old, size);
}
/*
** Print into pool memory. Omit the internal %-conversion extensions.
*/
KS_DECLARE(char *) ks_vpprintf(ks_pool_t *pool, const char *zFormat, va_list ap)
{
char zBase[KS_PRINT_BUF_SIZE];
return base_vprintf(pool_realloc, 0, zBase, sizeof(zBase), zFormat, ap, pool);
}
/*
** Print into pool memory. Omit the internal %-conversion extensions.
*/
KS_DECLARE(char *) ks_pprintf(ks_pool_t *pool, const char *zFormat, ...)
{
va_list ap;
char *z;
char zBase[KS_PRINT_BUF_SIZE];
va_start(ap, zFormat);
z = base_vprintf(pool_realloc, 0, zBase, sizeof(zBase), zFormat, ap, pool);
va_end(ap);
return z;
}
/*
** ks_vsnprintf() works like vsnprintf() except that it ignores the
** current locale settings. This is important for SQLite because we
** are not able to use a "," as the decimal point in place of "." as
** specified by some locales.
*/
KS_DECLARE(char *) ks_vsnprintfv(char *zBuf, int n, const char *zFormat, va_list ap)
{
return base_vprintf(0, 0, zBuf, n, zFormat, ap, NULL);
}
/*
** ks_snprintf() works like snprintf() except that it ignores the
** current locale settings. This is important for SQLite because we
** are not able to use a "," as the decimal point in place of "." as
** specified by some locales.
*/
KS_DECLARE(char *) ks_snprintfv(char *zBuf, int n, const char *zFormat, ...)
{
char *z;
va_list ap;
va_start(ap, zFormat);
z = base_vprintf(0, 0, zBuf, n, zFormat, ap, NULL);
va_end(ap);
return z;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

473
libs/libks/src/ks_q.c Normal file
View File

@ -0,0 +1,473 @@
/*
* Copyright (c) 2007-2014, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <ks.h>
typedef struct ks_qnode_s {
void *ptr;
struct ks_qnode_s *next;
struct ks_qnode_s *prev;
} ks_qnode_t;
struct ks_q_s {
ks_pool_t *pool;
ks_flush_fn_t flush_fn;
void *flush_data;
ks_size_t len;
ks_size_t maxlen;
ks_cond_t *pop_cond;
ks_cond_t *push_cond;
ks_mutex_t *list_mutex;
uint32_t pushers;
uint32_t poppers;
struct ks_qnode_s *head;
struct ks_qnode_s *tail;
struct ks_qnode_s *empty;
uint8_t active;
};
static void ks_q_cleanup(ks_pool_t *mpool, void *ptr, void *arg, int type, ks_pool_cleanup_action_t action, ks_pool_cleanup_type_t ctype)
{
ks_q_t *q = (ks_q_t *) ptr;
ks_qnode_t *np, *fp;
if (ctype == KS_MPCL_GLOBAL_FREE) {
return;
}
switch(action) {
case KS_MPCL_ANNOUNCE:
break;
case KS_MPCL_TEARDOWN:
np = q->head;
while(np) {
fp = np;
np = np->next;
ks_pool_free(q->pool, fp);
}
np = q->empty;
while(np) {
fp = np;
np = np->next;
ks_pool_free(q->pool, fp);
}
break;
case KS_MPCL_DESTROY:
ks_cond_destroy(&q->pop_cond);
ks_cond_destroy(&q->push_cond);
ks_mutex_destroy(&q->list_mutex);
break;
}
}
KS_DECLARE(ks_status_t) ks_q_flush(ks_q_t *q)
{
void *ptr;
if (!q->active) return KS_STATUS_INACTIVE;
if (!q->flush_fn) return KS_STATUS_FAIL;
while(ks_q_trypop(q, &ptr) == KS_STATUS_SUCCESS) {
q->flush_fn(q, ptr, q->flush_data);
}
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) ks_q_set_flush_fn(ks_q_t *q, ks_flush_fn_t fn, void *flush_data)
{
if (!q->active) return KS_STATUS_INACTIVE;
q->flush_fn = fn;
q->flush_data = flush_data;
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) ks_q_wake(ks_q_t *q)
{
ks_mutex_lock(q->list_mutex);
ks_cond_broadcast(q->push_cond);
ks_cond_broadcast(q->pop_cond);
ks_mutex_unlock(q->list_mutex);
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_size_t) ks_q_term(ks_q_t *q)
{
int active;
ks_mutex_lock(q->list_mutex);
active = q->active;
q->active = 0;
ks_mutex_unlock(q->list_mutex);
if (active) {
ks_q_wake(q);
}
return active ? KS_STATUS_SUCCESS : KS_STATUS_INACTIVE;
}
KS_DECLARE(ks_size_t) ks_q_size(ks_q_t *q)
{
ks_size_t size;
ks_mutex_lock(q->list_mutex);
size = q->len;
ks_mutex_unlock(q->list_mutex);
return size;
}
KS_DECLARE(ks_status_t) ks_q_destroy(ks_q_t **qP)
{
ks_q_t *q;
ks_pool_t *pool;
ks_assert(qP);
q = *qP;
*qP = NULL;
if (q) {
ks_q_flush(q);
ks_q_term(q);
pool = q->pool;
ks_pool_free(pool, q);
pool = NULL;
return KS_STATUS_SUCCESS;
}
return KS_STATUS_FAIL;
}
KS_DECLARE(ks_status_t) ks_q_create(ks_q_t **qP, ks_pool_t *pool, ks_size_t maxlen)
{
ks_q_t *q = NULL;
q = ks_pool_alloc(pool, sizeof(*q));
ks_assert(q);
q->pool = pool;
ks_mutex_create(&q->list_mutex, KS_MUTEX_FLAG_DEFAULT, pool);
ks_assert(q->list_mutex);
ks_cond_create_ex(&q->pop_cond, pool, q->list_mutex);
ks_assert(q->pop_cond);
ks_cond_create_ex(&q->push_cond, pool, q->list_mutex);
ks_assert(q->push_cond);
q->maxlen = maxlen;
q->active = 1;
ks_pool_set_cleanup(pool, q, NULL, 0, ks_q_cleanup);
*qP = q;
return KS_STATUS_SUCCESS;
}
static ks_qnode_t *new_node(ks_q_t *q)
{
ks_qnode_t *np;
if (q->empty) {
np = q->empty;
q->empty = q->empty->next;
} else {
np = ks_pool_alloc(q->pool, sizeof(*np));
}
np->prev = np->next = NULL;
np->ptr = NULL;
return np;
}
static ks_status_t do_push(ks_q_t *q, void *ptr)
{
ks_qnode_t *node;
ks_mutex_lock(q->list_mutex);
if (!q->active) {
ks_mutex_unlock(q->list_mutex);
return KS_STATUS_INACTIVE;
}
node = new_node(q);
node->ptr = ptr;
if (!q->head) {
q->head = q->tail = node;
} else {
q->tail->next = node;
node->prev = q->tail;
q->tail = node;
}
q->len++;
ks_mutex_unlock(q->list_mutex);
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) ks_q_push(ks_q_t *q, void *ptr)
{
ks_status_t r;
ks_mutex_lock(q->list_mutex);
if (q->active == 0) {
r = KS_STATUS_INACTIVE;
goto end;
}
if (q->maxlen && q->len == q->maxlen) {
q->pushers++;
ks_cond_wait(q->push_cond);
q->pushers--;
if (q->maxlen && q->len == q->maxlen) {
if (!q->active) {
r = KS_STATUS_INACTIVE;
} else {
r = KS_STATUS_BREAK;
}
goto end;
}
}
r = do_push(q, ptr);
if (q->poppers) {
ks_cond_signal(q->pop_cond);
}
end:
ks_mutex_unlock(q->list_mutex);
return r;
}
KS_DECLARE(ks_status_t) ks_q_trypush(ks_q_t *q, void *ptr)
{
ks_status_t r;
ks_mutex_lock(q->list_mutex);
if (q->active == 0) {
r = KS_STATUS_INACTIVE;
goto end;
}
if (q->maxlen && q->len == q->maxlen) {
r = KS_STATUS_BREAK;
goto end;
}
r = do_push(q, ptr);
if (q->poppers) {
ks_cond_signal(q->pop_cond);
}
end:
ks_mutex_unlock(q->list_mutex);
return r;
}
static ks_status_t do_pop(ks_q_t *q, void **ptr)
{
ks_qnode_t *np;
ks_mutex_lock(q->list_mutex);
if (!q->active) {
ks_mutex_unlock(q->list_mutex);
return KS_STATUS_INACTIVE;
}
if (!q->head) {
*ptr = NULL;
} else {
np = q->head;
if ((q->head = q->head->next)) {
q->head->prev = NULL;
}
*ptr = np->ptr;
np->next = q->empty;
np->prev = NULL;
np->ptr = NULL;
q->empty = np;
}
q->len--;
ks_mutex_unlock(q->list_mutex);
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) ks_q_pop_timeout(ks_q_t *q, void **ptr, uint32_t timeout)
{
ks_status_t r;
ks_mutex_lock(q->list_mutex);
if (!q->active) {
r = KS_STATUS_INACTIVE;
goto end;
}
if (q->len == 0) {
if (q->active) {
q->poppers++;
if (timeout) {
r = ks_cond_timedwait(q->pop_cond, timeout);
} else {
r = ks_cond_wait(q->pop_cond);
}
q->poppers--;
if (timeout && r != KS_STATUS_SUCCESS) {
goto end;
}
}
if (q->len == 0) {
if (!q->active) {
r = KS_STATUS_INACTIVE;
} else {
r = KS_STATUS_BREAK;
}
goto end;
}
}
r = do_pop(q, ptr);
if (q->pushers) {
ks_cond_signal(q->push_cond);
}
end:
ks_mutex_unlock(q->list_mutex);
return r;
}
KS_DECLARE(ks_status_t) ks_q_pop(ks_q_t *q, void **ptr)
{
return ks_q_pop_timeout(q, ptr, 0);
}
KS_DECLARE(ks_status_t) ks_q_trypop(ks_q_t *q, void **ptr)
{
ks_status_t r;
ks_mutex_lock(q->list_mutex);
if (!q->active) {
r = KS_STATUS_INACTIVE;
goto end;
}
if (q->len == 0) {
r = KS_STATUS_BREAK;
goto end;
}
r = do_pop(q, ptr);
if (q->pushers) {
ks_cond_signal(q->push_cond);
}
end:
ks_mutex_unlock(q->list_mutex);
return r;
}
KS_DECLARE(ks_status_t) ks_q_wait(ks_q_t *q)
{
ks_status_t r = KS_STATUS_SUCCESS;
int done = 0;
do {
ks_mutex_lock(q->list_mutex);
if (!q->active) {
r = KS_STATUS_INACTIVE;
done = 1;
}
if (q->len == 0) {
done = 1;
}
ks_mutex_unlock(q->list_mutex);
} while (!done);
return r;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

251
libs/libks/src/ks_rng.c Normal file
View File

@ -0,0 +1,251 @@
/*
* Cross Platform random/uuid abstraction
* Copyright(C) 2015 Michael Jerris
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so.
*
* This work is provided under this license on an "as is" basis, without warranty of any kind,
* either expressed or implied, including, without limitation, warranties that the covered code
* is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire
* risk as to the quality and performance of the covered code is with you. Should any covered
* code prove defective in any respect, you (not the initial developer or any other contributor)
* assume the cost of any necessary servicing, repair or correction. This disclaimer of warranty
* constitutes an essential part of this license. No use of any covered code is authorized hereunder
* except under this disclaimer.
*
*/
#include "ks.h"
#include "sodium.h"
#include <aes.h>
#include <sha2.h>
static ks_bool_t initialized = KS_FALSE;
static ks_mutex_t *rng_mutex = NULL;
static sha512_ctx global_sha512;
#ifdef __WINDOWS__
#include <Wincrypt.h>
HCRYPTPROV crypt_provider;
#else
int fd = -1;
#endif
/*
* memset_volatile is a volatile pointer to the memset function.
* You can call (*memset_volatile)(buf, val, len) or even
* memset_volatile(buf, val, len) just as you would call
* memset(buf, val, len), but the use of a volatile pointer
* guarantees that the compiler will not optimise the call away.
*/
//static void * (*volatile memset_volatile)(void *, int, size_t) = memset;
KS_DECLARE(uuid_t *) ks_uuid(uuid_t *uuid)
{
#ifdef __WINDOWS__
UuidCreate ( uuid );
#else
uuid_generate_random ( *uuid );
#endif
return uuid;
}
KS_DECLARE(char *) ks_uuid_str(ks_pool_t *pool, uuid_t *uuid)
{
char *uuidstr = ks_pool_alloc(pool, 37);
#ifdef __WINDOWS__
unsigned char * str;
UuidToStringA ( uuid, &str );
uuidstr = ks_pstrdup(pool, str);
RpcStringFreeA ( &str );
#else
char str[37] = { 0 };
uuid_unparse ( *uuid, str );
uuidstr = ks_pstrdup(pool, str);
#endif
return uuidstr;
}
KS_DECLARE(ks_status_t) ks_rng_init(void)
{
if (!initialized) {
if (sodium_init() == -1) {
abort();
}
randombytes_random();
ks_aes_init();
ks_mutex_create(&rng_mutex, KS_MUTEX_FLAG_DEFAULT, ks_global_pool());
#ifdef __WINDOWS__
if (!crypt_provider) {
if (CryptAcquireContext(&crypt_provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) == TRUE) {
initialized = KS_TRUE;
} else {
initialized = KS_FALSE;
}
}
#else
if (fd < 0) {
fd = open("/dev/urandom", O_RDONLY);
if (fd < 0) {
fd = open("/dev/random", O_RDONLY);
}
}
initialized = KS_TRUE;
#endif
}
sha512_begin(&global_sha512);
if (initialized) {
return KS_STATUS_SUCCESS;
} else {
return KS_STATUS_FAIL;
}
}
KS_DECLARE(ks_status_t) ks_rng_shutdown(void)
{
initialized = KS_FALSE;
#ifdef __WINDOWS__
if (crypt_provider) {
CryptReleaseContext(crypt_provider, 0);
crypt_provider = 0;
}
#else
if (fd >= 0) {
close(fd);
fd = -1;
}
#endif
return KS_STATUS_SUCCESS;
}
KS_DECLARE(size_t) ks_rng_seed_data(uint8_t *seed, size_t length)
{
size_t bytes = 0;
if (!initialized && (ks_rng_init() != KS_STATUS_SUCCESS)) {
return bytes;
}
#ifdef __WINDOWS__
if (crypt_provider) {
if(!CryptGenRandom(crypt_provider, length, seed)) {
return 0;
}
bytes = length;
}
#else
if (fd >= 0) {
bytes = read(fd, seed, length);
} else {
}
#endif
return bytes;
}
KS_DECLARE(size_t) ks_rng_add_entropy(const uint8_t *buffer, size_t length)
{
uint8_t seed[64];
size_t len = ks_rng_seed_data(seed, sizeof(seed));
ks_mutex_lock(rng_mutex);
if (!initialized) {
ks_rng_init();
}
if (buffer && length) {
sha512_hash(buffer, length, &global_sha512);
}
if (len > 0) {
sha512_hash(seed, len, &global_sha512);
length += len;
}
ks_mutex_unlock(rng_mutex);
return length;
}
KS_DECLARE(size_t) ks_rng_get_data(uint8_t* buffer, size_t length) {
randombytes_buf(buffer, length);
return length;
}
#if 0
KS_DECLARE(size_t) ks_rng_get_data(uint8_t* buffer, size_t length) {
aes_encrypt_ctx cx[1];
sha512_ctx random_context;
uint8_t md[SHA512_DIGEST_SIZE];
uint8_t ctr[AES_BLOCK_SIZE];
uint8_t rdata[AES_BLOCK_SIZE];
size_t generated = length;
/* Add entropy from system state. We will include whatever happens to be in the buffer, it can't hurt */
ks_rng_add_entropy(buffer, length);
ks_mutex_lock(rng_mutex);
/* Copy the mainCtx and finalize it into the md buffer */
memcpy(&random_context, &global_sha512, sizeof(sha512_ctx));
sha512_end(md, &random_context);
ks_mutex_lock(rng_mutex);
/* Key an AES context from this buffer */
aes_encrypt_key256(md, cx);
/* Initialize counter, using excess from md if available */
memset (ctr, 0, sizeof(ctr));
uint32_t ctrbytes = AES_BLOCK_SIZE;
memcpy(ctr + sizeof(ctr) - ctrbytes, md + 32, ctrbytes);
/* Encrypt counter, copy to destination buffer, increment counter */
while (length) {
uint8_t *ctrptr;
size_t copied;
aes_encrypt(ctr, rdata, cx);
copied = (sizeof(rdata) < length) ? sizeof(rdata) : length;
memcpy (buffer, rdata, copied);
buffer += copied;
length -= copied;
/* Increment counter */
ctrptr = ctr + sizeof(ctr) - 1;
while (ctrptr >= ctr) {
if ((*ctrptr-- += 1) != 0) {
break;
}
}
}
memset_volatile(&random_context, 0, sizeof(random_context));
memset_volatile(md, 0, sizeof(md));
memset_volatile(&cx, 0, sizeof(cx));
memset_volatile(ctr, 0, sizeof(ctr));
memset_volatile(rdata, 0, sizeof(rdata));
return generated;
}
#endif
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

1042
libs/libks/src/ks_socket.c Normal file

File diff suppressed because it is too large Load Diff

250
libs/libks/src/ks_ssl.c Normal file
View File

@ -0,0 +1,250 @@
/*
* Copyright (c) 2007-2014, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <ks.h>
static ks_mutex_t **ssl_mutexes;
static ks_pool_t *ssl_pool = NULL;
static int ssl_count = 0;
static int is_init = 0;
static inline void ks_ssl_lock_callback(int mode, int type, char *file, int line)
{
if (mode & CRYPTO_LOCK) {
ks_mutex_lock(ssl_mutexes[type]);
}
else {
ks_mutex_unlock(ssl_mutexes[type]);
}
}
static inline unsigned long ks_ssl_thread_id(void)
{
return (unsigned long) ks_thread_self();
}
KS_DECLARE(void) ks_ssl_init_ssl_locks(void)
{
int i, num;
if (is_init) return;
is_init = 1;
SSL_library_init();
if (ssl_count == 0) {
num = CRYPTO_num_locks();
ssl_mutexes = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(ks_mutex_t*));
ks_assert(ssl_mutexes != NULL);
ks_pool_open(&ssl_pool);
for (i = 0; i < num; i++) {
ks_mutex_create(&(ssl_mutexes[i]), KS_MUTEX_FLAG_DEFAULT, ssl_pool);
ks_assert(ssl_mutexes[i] != NULL);
}
CRYPTO_set_id_callback(ks_ssl_thread_id);
CRYPTO_set_locking_callback((void (*)(int, int, const char*, int))ks_ssl_lock_callback);
}
ssl_count++;
}
KS_DECLARE(void) ks_ssl_destroy_ssl_locks(void)
{
int i;
if (!is_init) return;
is_init = 0;
if (ssl_count == 1) {
CRYPTO_set_locking_callback(NULL);
for (i = 0; i < CRYPTO_num_locks(); i++) {
if (ssl_mutexes[i]) {
ks_mutex_destroy(&ssl_mutexes[i]);
}
}
OPENSSL_free(ssl_mutexes);
ssl_count--;
}
}
static int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int days);
KS_DECLARE(int) ks_gen_cert(const char *dir, const char *file)
{
//BIO *bio_err;
X509 *x509 = NULL;
EVP_PKEY *pkey = NULL;
char *rsa = NULL, *pvt = NULL;
FILE *fp;
char *pem = NULL;
if (ks_stristr(".pem", file)) {
pem = ks_mprintf("%s%s%s", dir, KS_PATH_SEPARATOR, file);
} else {
pvt = ks_mprintf("%s%s%s.key", dir, KS_PATH_SEPARATOR, file);
rsa = ks_mprintf("%s%s%s.crt", dir, KS_PATH_SEPARATOR, file);
}
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
//bio_err=BIO_new_fp(stderr, BIO_NOCLOSE);
mkcert(&x509, &pkey, 1024, 0, 36500);
//RSA_print_fp(stdout, pkey->pkey.rsa, 0);
//X509_print_fp(stdout, x509);
if (pem) {
if ((fp = fopen(pem, "w"))) {
PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL);
PEM_write_X509(fp, x509);
fclose(fp);
}
} else {
if (pvt && (fp = fopen(pvt, "w"))) {
PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL);
fclose(fp);
}
if (rsa && (fp = fopen(rsa, "w"))) {
PEM_write_X509(fp, x509);
fclose(fp);
}
}
X509_free(x509);
EVP_PKEY_free(pkey);
#ifndef OPENSSL_NO_ENGINE
ENGINE_cleanup();
#endif
CRYPTO_cleanup_all_ex_data();
//CRYPTO_mem_leaks(bio_err);
//BIO_free(bio_err);
ks_safe_free(pvt);
ks_safe_free(rsa);
ks_safe_free(pem);
return(0);
}
static int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int days)
{
X509 *x;
EVP_PKEY *pk;
RSA *rsa;
X509_NAME *name=NULL;
ks_assert(pkeyp);
ks_assert(x509p);
if (*pkeyp == NULL) {
if ((pk = EVP_PKEY_new()) == NULL) {
abort();
}
} else {
pk = *pkeyp;
}
if (*x509p == NULL) {
if ((x = X509_new()) == NULL) {
goto err;
}
} else {
x = *x509p;
}
rsa = RSA_generate_key(bits, RSA_F4, NULL, NULL);
if (!EVP_PKEY_assign_RSA(pk, rsa)) {
abort();
goto err;
}
rsa = NULL;
X509_set_version(x, 0);
ASN1_INTEGER_set(X509_get_serialNumber(x), serial);
X509_gmtime_adj(X509_get_notBefore(x), -(long)60*60*24*7);
X509_gmtime_adj(X509_get_notAfter(x), (long)60*60*24*days);
X509_set_pubkey(x, pk);
name = X509_get_subject_name(x);
/* This function creates and adds the entry, working out the
* correct string type and performing checks on its length.
* Normally we'd check the return value for errors...
*/
X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char *)"US", -1, -1, 0);
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char *)"FreeSWITCH-libKS", -1, -1, 0);
/* Its self signed so set the issuer name to be the same as the
* subject.
*/
X509_set_issuer_name(x, name);
if (!X509_sign(x, pk, EVP_sha1()))
goto err;
*x509p = x;
*pkeyp = pk;
return(1);
err:
return(0);
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

275
libs/libks/src/ks_string.c Normal file
View File

@ -0,0 +1,275 @@
/*
* Copyright (c) 2007-2014, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <ks.h>
/* Written by Marc Espie, public domain */
#define KS_CTYPE_NUM_CHARS 256
const short _ks_C_toupper_[1 + KS_CTYPE_NUM_CHARS] = {
EOF,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
const short *_ks_toupper_tab_ = _ks_C_toupper_;
KS_DECLARE(int) ks_toupper(int c)
{
if ((unsigned int) c > 255)
return (c);
if (c < -1)
return EOF;
return ((_ks_toupper_tab_ + 1)[c]);
}
const short _ks_C_tolower_[1 + KS_CTYPE_NUM_CHARS] = {
EOF,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
const short *_ks_tolower_tab_ = _ks_C_tolower_;
KS_DECLARE(int) ks_tolower(int c)
{
if ((unsigned int) c > 255)
return (c);
if (c < -1)
return EOF;
return ((_ks_tolower_tab_ + 1)[c]);
}
KS_DECLARE(const char *) ks_stristr(const char *instr, const char *str)
{
/*
** Rev History: 16/07/97 Greg Thayer Optimized
** 07/04/95 Bob Stout ANSI-fy
** 02/03/94 Fred Cole Original
** 09/01/03 Bob Stout Bug fix (lines 40-41) per Fred Bulback
**
** Hereby donated to public domain.
*/
const char *pptr, *sptr, *start;
if (!str || !instr)
return NULL;
for (start = str; *start; start++) {
/* find start of pattern in string */
for (; ((*start) && (ks_toupper(*start) != ks_toupper(*instr))); start++);
if (!*start)
return NULL;
pptr = instr;
sptr = start;
while (ks_toupper(*sptr) == ks_toupper(*pptr)) {
sptr++;
pptr++;
/* if end of pattern then pattern was found */
if (!*pptr)
return (start);
if (!*sptr)
return NULL;
}
}
return NULL;
}
#ifdef WIN32
#ifndef vsnprintf
#define vsnprintf _vsnprintf
#endif
#endif
int vasprintf(char **ret, const char *format, va_list ap);
KS_DECLARE(int) ks_vasprintf(char **ret, const char *fmt, va_list ap)
{
#if !defined(WIN32) && !defined(__sun)
return vasprintf(ret, fmt, ap);
#else
char *buf;
int len;
size_t buflen;
va_list ap2;
char *tmp = NULL;
#ifdef _MSC_VER
#if _MSC_VER >= 1500
/* hack for incorrect assumption in msvc header files for code analysis */
__analysis_assume(tmp);
#endif
ap2 = ap;
#else
va_copy(ap2, ap);
#endif
len = vsnprintf(tmp, 0, fmt, ap2);
if (len > 0 && (buf = malloc((buflen = (size_t) (len + 1)))) != NULL) {
len = vsnprintf(buf, buflen, fmt, ap);
*ret = buf;
} else {
*ret = NULL;
len = -1;
}
va_end(ap2);
return len;
#endif
}
KS_DECLARE(int) ks_snprintf(char *buffer, size_t count, const char *fmt, ...)
{
va_list ap;
int ret;
va_start(ap, fmt);
ret = vsnprintf(buffer, count - 1, fmt, ap);
if (ret < 0)
buffer[count - 1] = '\0';
va_end(ap);
return ret;
}
KS_DECLARE(unsigned int) ks_separate_string(char *buf, const char *delim, char **array, unsigned int arraylen)
{
unsigned int count = 0;
char *d;
size_t dlen = strlen(delim);
array[count++] = buf;
while (count < arraylen && array[count - 1]) {
if ((d = strstr(array[count - 1], delim))) {
*d = '\0';
d += dlen;
array[count++] = d;
} else
break;
}
return count;
}
KS_DECLARE(char *) ks_copy_string(char *from_str, const char *to_str, ks_size_t from_str_len)
{
char *p, *e;
if (!from_str)
return NULL;
if (!to_str) {
*from_str = '\0';
return from_str;
}
e = from_str + from_str_len - 1;
for (p = from_str; p < e; ++p, ++to_str) {
if (!(*p = *to_str)) {
return p;
}
}
*p = '\0';
return p;
}

285
libs/libks/src/ks_thread.c Normal file
View File

@ -0,0 +1,285 @@
/*
* Cross Platform Thread/Mutex abstraction
* Copyright(C) 2007 Michael Jerris
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so.
*
* This work is provided under this license on an "as is" basis, without warranty of any kind,
* either expressed or implied, including, without limitation, warranties that the covered code
* is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire
* risk as to the quality and performance of the covered code is with you. Should any covered
* code prove defective in any respect, you (not the initial developer or any other contributor)
* assume the cost of any necessary servicing, repair or correction. This disclaimer of warranty
* constitutes an essential part of this license. No use of any covered code is authorized hereunder
* except under this disclaimer.
*
*/
#include "ks.h"
size_t thread_default_stacksize = 240 * 1024;
#ifndef WIN32
pthread_once_t init_priority = PTHREAD_ONCE_INIT;
#endif
KS_DECLARE(ks_thread_os_handle_t) ks_thread_os_handle(ks_thread_t *thread)
{
return thread->handle;
}
KS_DECLARE(ks_thread_os_handle_t) ks_thread_self(void)
{
#ifdef WIN32
return GetCurrentThread();
#else
return pthread_self();
#endif
}
static void ks_thread_init_priority(void)
{
#ifdef WIN32
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
#else
#ifdef USE_SCHED_SETSCHEDULER
/*
* Try to use a round-robin scheduler
* with a fallback if that does not work
*/
struct sched_param sched = { 0 };
sched.sched_priority = KS_PRI_LOW;
if (sched_setscheduler(0, SCHED_FIFO, &sched)) {
sched.sched_priority = 0;
if (sched_setscheduler(0, SCHED_OTHER, &sched)) {
return;
}
}
#endif
#endif
return;
}
void ks_thread_override_default_stacksize(size_t size)
{
thread_default_stacksize = size;
}
static void ks_thread_cleanup(ks_pool_t *mpool, void *ptr, void *arg, int type, ks_pool_cleanup_action_t action, ks_pool_cleanup_type_t ctype)
{
ks_thread_t *thread = (ks_thread_t *) ptr;
switch(action) {
case KS_MPCL_ANNOUNCE:
thread->running = 0;
break;
case KS_MPCL_TEARDOWN:
if (!(thread->flags & KS_THREAD_FLAG_DETATCHED)) {
ks_thread_join(thread);
}
break;
case KS_MPCL_DESTROY:
#ifdef WIN32
if (!(thread->flags & KS_THREAD_FLAG_DETATCHED)) {
CloseHandle(thread->handle);
}
#endif
break;
}
}
static void *KS_THREAD_CALLING_CONVENTION thread_launch(void *args)
{
ks_thread_t *thread = (ks_thread_t *) args;
#ifdef HAVE_PTHREAD_SETSCHEDPARAM
if (thread->priority) {
int policy = SCHED_FIFO;
struct sched_param param = { 0 };
pthread_t tt = pthread_self();
pthread_once(&init_priority, ks_thread_init_priority);
pthread_getschedparam(tt, &policy, &param);
param.sched_priority = thread->priority;
pthread_setschedparam(tt, policy, &param);
}
#endif
thread->return_data = thread->function(thread, thread->private_data);
#ifndef WIN32
pthread_attr_destroy(&thread->attribute);
#endif
return thread->return_data;
}
KS_DECLARE(int) ks_thread_set_priority(int nice_val)
{
#ifdef WIN32
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
#else
#ifdef USE_SCHED_SETSCHEDULER
/*
* Try to use a round-robin scheduler
* with a fallback if that does not work
*/
struct sched_param sched = { 0 };
sched.sched_priority = KS_PRI_LOW;
if (sched_setscheduler(0, SCHED_FIFO, &sched)) {
sched.sched_priority = 0;
if (sched_setscheduler(0, SCHED_OTHER, &sched)) {
return -1;
}
}
#endif
if (nice_val) {
#ifdef HAVE_SETPRIORITY
/*
* setpriority() works on FreeBSD (6.2), nice() doesn't
*/
if (setpriority(PRIO_PROCESS, getpid(), nice_val) < 0) {
ks_log(KS_LOG_CRIT, "Could not set nice level\n");
return -1;
}
#else
if (nice(nice_val) != nice_val) {
ks_log(KS_LOG_CRIT, "Could not set nice level\n");
return -1;
}
#endif
}
#endif
return 0;
}
KS_DECLARE(uint8_t) ks_thread_priority(ks_thread_t *thread) {
uint8_t priority = 0;
#ifdef WIN32
DWORD pri = GetThreadPriority(thread->handle);
if (pri >= THREAD_PRIORITY_TIME_CRITICAL) {
priority = 99;
} else if (pri >= THREAD_PRIORITY_ABOVE_NORMAL) {
priority = 50;
} else {
priority = 10;
}
#else
int policy;
struct sched_param param = { 0 };
pthread_getschedparam(thread->handle, &policy, &param);
priority = param.sched_priority;
#endif
return priority;
}
KS_DECLARE(ks_status_t) ks_thread_join(ks_thread_t *thread) {
#ifdef WIN32
WaitForSingleObject(thread->handle, INFINITE);
#else
void *ret;
pthread_join(thread->handle, &ret);
#endif
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) ks_thread_create_ex(ks_thread_t **rthread, ks_thread_function_t func, void *data,
uint32_t flags, size_t stack_size, ks_thread_priority_t priority, ks_pool_t *pool)
{
ks_thread_t *thread = NULL;
ks_status_t status = KS_STATUS_FAIL;
if (!rthread) goto done;
*rthread = NULL;
if (!func || !pool) goto done;
thread = (ks_thread_t *) ks_pool_alloc(pool, sizeof(ks_thread_t));
if (!thread) goto done;
thread->private_data = data;
thread->function = func;
thread->stack_size = stack_size;
thread->running = 1;
thread->flags = flags;
thread->priority = priority;
thread->pool = pool;
#if defined(WIN32)
thread->handle = (void *) _beginthreadex(NULL, (unsigned) thread->stack_size, (unsigned int (__stdcall *) (void *)) thread_launch, thread, 0, NULL);
if (!thread->handle) {
goto fail;
}
if (priority >= 99) {
SetThreadPriority(thread->handle, THREAD_PRIORITY_TIME_CRITICAL);
} else if (priority >= 50) {
SetThreadPriority(thread->handle, THREAD_PRIORITY_ABOVE_NORMAL);
} else if (priority >= 10) {
SetThreadPriority(thread->handle, THREAD_PRIORITY_NORMAL);
} else if (priority >= 1) {
SetThreadPriority(thread->handle, THREAD_PRIORITY_LOWEST);
}
if (flags & KS_THREAD_FLAG_DETATCHED) {
CloseHandle(thread->handle);
}
status = KS_STATUS_SUCCESS;
goto done;
#else
if (pthread_attr_init(&thread->attribute) != 0)
goto fail;
if ((flags & KS_THREAD_FLAG_DETATCHED) && pthread_attr_setdetachstate(&thread->attribute, PTHREAD_CREATE_DETACHED) != 0)
goto failpthread;
if (thread->stack_size && pthread_attr_setstacksize(&thread->attribute, thread->stack_size) != 0)
goto failpthread;
if (pthread_create(&thread->handle, &thread->attribute, thread_launch, thread) != 0)
goto failpthread;
status = KS_STATUS_SUCCESS;
goto done;
failpthread:
pthread_attr_destroy(&thread->attribute);
#endif
fail:
if (thread) {
thread->running = 0;
if (pool) {
ks_pool_safe_free(pool, thread);
}
}
done:
if (status == KS_STATUS_SUCCESS) {
*rthread = thread;
ks_pool_set_cleanup(pool, thread, NULL, 0, ks_thread_cleanup);
}
return status;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

270
libs/libks/src/ks_time.c Normal file
View File

@ -0,0 +1,270 @@
/*
* Copyright (c) 2007-2014, Anthony Minessale II
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <ks.h>
#ifdef WIN32
static CRITICAL_SECTION timer_section;
static ks_time_t win32_tick_time_since_start = -1;
static DWORD win32_last_get_time_tick = 0;
static uint8_t win32_use_qpc = 0;
static uint64_t win32_qpc_freq = 0;
static int timer_init;
static inline void win32_init_timers(void)
{
OSVERSIONINFOEX version_info; /* Used to fetch current OS version from Windows */
InitializeCriticalSection(&timer_section);
EnterCriticalSection(&timer_section);
ZeroMemory(&version_info, sizeof(OSVERSIONINFOEX));
version_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
/* Check if we should use timeGetTime() (pre-Vista) or QueryPerformanceCounter() (Vista and later) */
if (GetVersionEx((OSVERSIONINFO*) &version_info)) {
if (version_info.dwPlatformId == VER_PLATFORM_WIN32_NT && version_info.dwMajorVersion >= 6) {
if (QueryPerformanceFrequency((LARGE_INTEGER*)&win32_qpc_freq) && win32_qpc_freq > 0) {
/* At least Vista, and QueryPerformanceFrequency() suceeded, enable qpc */
win32_use_qpc = 1;
} else {
/* At least Vista, but QueryPerformanceFrequency() failed, disable qpc */
win32_use_qpc = 0;
}
} else {
/* Older then Vista, disable qpc */
win32_use_qpc = 0;
}
} else {
/* Unknown version - we want at least Vista, disable qpc */
win32_use_qpc = 0;
}
if (win32_use_qpc) {
uint64_t count = 0;
if (!QueryPerformanceCounter((LARGE_INTEGER*)&count) || count == 0) {
/* Call to QueryPerformanceCounter() failed, disable qpc again */
win32_use_qpc = 0;
}
}
if (!win32_use_qpc) {
/* This will enable timeGetTime() instead, qpc init failed */
win32_last_get_time_tick = timeGetTime();
win32_tick_time_since_start = win32_last_get_time_tick;
}
LeaveCriticalSection(&timer_section);
timer_init = 1;
}
KS_DECLARE(ks_time_t) ks_time_now(void)
{
ks_time_t now;
if (!timer_init) {
win32_init_timers();
}
if (win32_use_qpc) {
/* Use QueryPerformanceCounter */
uint64_t count = 0;
QueryPerformanceCounter((LARGE_INTEGER*)&count);
now = ((count * 1000000) / win32_qpc_freq);
} else {
/* Use good old timeGetTime() */
DWORD tick_now;
DWORD tick_diff;
tick_now = timeGetTime();
if (win32_tick_time_since_start != -1) {
EnterCriticalSection(&timer_section);
/* just add diff (to make it work more than 50 days). */
tick_diff = tick_now - win32_last_get_time_tick;
win32_tick_time_since_start += tick_diff;
win32_last_get_time_tick = tick_now;
now = (win32_tick_time_since_start * 1000);
LeaveCriticalSection(&timer_section);
} else {
/* If someone is calling us before timer is initialized,
* return the current tick
*/
now = (tick_now * 1000);
}
}
return now;
}
KS_DECLARE(ks_time_t) ks_time_now_sec(void)
{
ks_time_t now;
if (!timer_init) {
win32_init_timers();
}
if (win32_use_qpc) {
/* Use QueryPerformanceCounter */
uint64_t count = 0;
QueryPerformanceCounter((LARGE_INTEGER*)&count);
now = (count / win32_qpc_freq);
} else {
/* Use good old timeGetTime() */
DWORD tick_now;
DWORD tick_diff;
tick_now = timeGetTime();
if (win32_tick_time_since_start != -1) {
EnterCriticalSection(&timer_section);
/* just add diff (to make it work more than 50 days). */
tick_diff = tick_now - win32_last_get_time_tick;
win32_tick_time_since_start += tick_diff;
win32_last_get_time_tick = tick_now;
now = (win32_tick_time_since_start / 1000);
LeaveCriticalSection(&timer_section);
} else {
/* If someone is calling us before timer is initialized,
* return the current tick
*/
now = (tick_now / 1000);
}
}
return now;
}
KS_DECLARE(void) ks_sleep(ks_time_t microsec)
{
LARGE_INTEGER perfCnt, start, now;
QueryPerformanceFrequency(&perfCnt);
QueryPerformanceCounter(&start);
do {
QueryPerformanceCounter((LARGE_INTEGER*) &now);
} while ((now.QuadPart - start.QuadPart) / (float)(perfCnt.QuadPart) * 1000 * 1000 < (DWORD)microsec);
}
#else //!WINDOWS, UNIX ETC
KS_DECLARE(ks_time_t) ks_time_now(void)
{
ks_time_t now;
#if (defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME))
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
now = (int64_t)ts.tv_sec * 1000000 + ((int64_t)ts.tv_nsec / 1000);
#else
struct timeval tv;
gettimeofday(&tv, NULL);
now = tv.tv_sec * 1000000 + tv.tv_usec;
#endif
return now;
}
KS_DECLARE(ks_time_t) ks_time_now_sec(void)
{
ks_time_t now;
#if (defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME))
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
now = (int64_t)ts.tv_sec;
#else
struct timeval tv;
gettimeofday(&tv, NULL);
now = tv.tv_sec;
#endif
return now;
}
#if !defined(HAVE_CLOCK_NANOSLEEP) && !defined(__APPLE__)
static void generic_sleep(ks_time_t microsec)
{
#ifdef HAVE_USLEEP
usleep(microsec);
#else
struct timeval tv;
tv.tv_usec = ks_time_usec(microsec);
tv.tv_sec = ks_time_sec(microsec);
select(0, NULL, NULL, NULL, &tv);
#endif
}
#endif
KS_DECLARE(void) ks_sleep(ks_time_t microsec)
{
#if defined(HAVE_CLOCK_NANOSLEEP) || defined(__APPLE__)
struct timespec ts;
#endif
#if defined(HAVE_CLOCK_NANOSLEEP)
ts.tv_sec = ks_time_sec(microsec);
ts.tv_nsec = ks_time_nsec(microsec);
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
#elif defined(__APPLE__)
ts.tv_sec = ks_time_sec(microsec);
ts.tv_nsec = ks_time_usec(microsec) * 850;
nanosleep(&ts, NULL);
#else
generic_sleep(microsec);
#endif
#if defined(__APPLE__)
sched_yield();
#endif
}
#endif
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

1146
libs/libks/src/kws.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

182
libs/libks/src/utp/utp.h Normal file
View File

@ -0,0 +1,182 @@
/*
* Copyright (c) 2010-2013 BitTorrent, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef __UTP_H__
#define __UTP_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdarg.h>
#include "utp_types.h"
typedef struct UTPSocket utp_socket;
typedef struct struct_utp_context utp_context;
enum {
UTP_UDP_DONTFRAG = 2, // Used to be a #define as UDP_IP_DONTFRAG
};
enum {
// socket has reveived syn-ack (notification only for outgoing connection completion)
// this implies writability
UTP_STATE_CONNECT = 1,
// socket is able to send more data
UTP_STATE_WRITABLE = 2,
// connection closed
UTP_STATE_EOF = 3,
// socket is being destroyed, meaning all data has been sent if possible.
// it is not valid to refer to the socket after this state change occurs
UTP_STATE_DESTROYING = 4,
};
extern const char *utp_state_names[];
// Errors codes that can be passed to UTP_ON_ERROR callback
enum {
UTP_ECONNREFUSED = 0,
UTP_ECONNRESET,
UTP_ETIMEDOUT,
};
extern const char *utp_error_code_names[];
enum {
// callback names
UTP_ON_FIREWALL = 0,
UTP_ON_ACCEPT,
UTP_ON_CONNECT,
UTP_ON_ERROR,
UTP_ON_READ,
UTP_ON_OVERHEAD_STATISTICS,
UTP_ON_STATE_CHANGE,
UTP_GET_READ_BUFFER_SIZE,
UTP_ON_DELAY_SAMPLE,
UTP_GET_UDP_MTU,
UTP_GET_UDP_OVERHEAD,
UTP_GET_MILLISECONDS,
UTP_GET_MICROSECONDS,
UTP_GET_RANDOM,
UTP_LOG,
UTP_SENDTO,
// context and socket options that may be set/queried
UTP_LOG_NORMAL,
UTP_LOG_MTU,
UTP_LOG_DEBUG,
UTP_SNDBUF,
UTP_RCVBUF,
UTP_TARGET_DELAY,
UTP_ARRAY_SIZE, // must be last
};
extern const char *utp_callback_names[];
typedef struct {
utp_context *context;
utp_socket *socket;
size_t len;
uint32 flags;
int callback_type;
const byte *buf;
union {
const struct sockaddr *address;
int send;
int sample_ms;
int error_code;
int state;
};
union {
socklen_t address_len;
int type;
};
} utp_callback_arguments;
typedef uint64 utp_callback_t(utp_callback_arguments *);
// Returned by utp_get_context_stats()
typedef struct {
uint32 _nraw_recv[5]; // total packets recieved less than 300/600/1200/MTU bytes fpr all connections (context-wide)
uint32 _nraw_send[5]; // total packets sent less than 300/600/1200/MTU bytes for all connections (context-wide)
} utp_context_stats;
// Returned by utp_get_stats()
typedef struct {
uint64 nbytes_recv; // total bytes received
uint64 nbytes_xmit; // total bytes transmitted
uint32 rexmit; // retransmit counter
uint32 fastrexmit; // fast retransmit counter
uint32 nxmit; // transmit counter
uint32 nrecv; // receive counter (total)
uint32 nduprecv; // duplicate receive counter
uint32 mtu_guess; // Best guess at MTU
} utp_socket_stats;
#define UTP_IOV_MAX 1024
// For utp_writev, to writes data from multiple buffers
struct utp_iovec {
void *iov_base;
size_t iov_len;
};
// Public Functions
utp_context* utp_init (int version);
void utp_destroy (utp_context *ctx);
void utp_set_callback (utp_context *ctx, int callback_name, utp_callback_t *proc);
void* utp_context_set_userdata (utp_context *ctx, void *userdata);
void* utp_context_get_userdata (utp_context *ctx);
int utp_context_set_option (utp_context *ctx, int opt, int val);
int utp_context_get_option (utp_context *ctx, int opt);
int utp_process_udp (utp_context *ctx, const byte *buf, size_t len, const struct sockaddr *to, socklen_t tolen);
int utp_process_icmp_error (utp_context *ctx, const byte *buffer, size_t len, const struct sockaddr *to, socklen_t tolen);
int utp_process_icmp_fragmentation (utp_context *ctx, const byte *buffer, size_t len, const struct sockaddr *to, socklen_t tolen, uint16 next_hop_mtu);
void utp_check_timeouts (utp_context *ctx);
void utp_issue_deferred_acks (utp_context *ctx);
utp_context_stats* utp_get_context_stats (utp_context *ctx);
utp_socket* utp_create_socket (utp_context *ctx);
void* utp_set_userdata (utp_socket *s, void *userdata);
void* utp_get_userdata (utp_socket *s);
int utp_setsockopt (utp_socket *s, int opt, int val);
int utp_getsockopt (utp_socket *s, int opt);
int utp_connect (utp_socket *s, const struct sockaddr *to, socklen_t tolen);
ssize_t utp_write (utp_socket *s, void *buf, size_t count);
ssize_t utp_writev (utp_socket *s, struct utp_iovec *iovec, size_t num_iovecs);
int utp_getpeername (utp_socket *s, struct sockaddr *addr, socklen_t *addrlen);
void utp_read_drained (utp_socket *s);
int utp_get_delays (utp_socket *s, uint32 *ours, uint32 *theirs, uint32 *age);
utp_socket_stats* utp_get_stats (utp_socket *s);
utp_context* utp_get_context (utp_socket *s);
void utp_close (utp_socket *s);
#ifdef __cplusplus
}
#endif
#endif //__UTP_H__

View File

@ -0,0 +1,139 @@
// vim:set ts=4 sw=4 ai:
/*
* Copyright (c) 2010-2013 BitTorrent, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdio.h>
#include "utp_internal.h"
#include "utp_utils.h"
extern "C" {
const char * utp_callback_names[] = {
"UTP_ON_FIREWALL",
"UTP_ON_ACCEPT",
"UTP_ON_CONNECT",
"UTP_ON_ERROR",
"UTP_ON_READ",
"UTP_ON_OVERHEAD_STATISTICS",
"UTP_ON_STATE_CHANGE",
"UTP_GET_READ_BUFFER_SIZE",
"UTP_ON_DELAY_SAMPLE",
"UTP_GET_UDP_MTU",
"UTP_GET_UDP_OVERHEAD",
"UTP_GET_MILLISECONDS",
"UTP_GET_MICROSECONDS",
"UTP_GET_RANDOM",
"UTP_LOG",
"UTP_SENDTO",
};
const char * utp_error_code_names[] = {
"UTP_ECONNREFUSED",
"UTP_ECONNRESET",
"UTP_ETIMEDOUT",
};
const char *utp_state_names[] = {
NULL,
"UTP_STATE_CONNECT",
"UTP_STATE_WRITABLE",
"UTP_STATE_EOF",
"UTP_STATE_DESTROYING",
};
struct_utp_context::struct_utp_context()
: userdata(NULL)
, current_ms(0)
, last_utp_socket(NULL)
, log_normal(false)
, log_mtu(false)
, log_debug(false)
{
memset(&context_stats, 0, sizeof(context_stats));
memset(callbacks, 0, sizeof(callbacks));
target_delay = CCONTROL_TARGET;
utp_sockets = new UTPSocketHT;
callbacks[UTP_GET_UDP_MTU] = &utp_default_get_udp_mtu;
callbacks[UTP_GET_UDP_OVERHEAD] = &utp_default_get_udp_overhead;
callbacks[UTP_GET_MILLISECONDS] = &utp_default_get_milliseconds;
callbacks[UTP_GET_MICROSECONDS] = &utp_default_get_microseconds;
callbacks[UTP_GET_RANDOM] = &utp_default_get_random;
// 1 MB of receive buffer (i.e. max bandwidth delay product)
// means that from a peer with 200 ms RTT, we cannot receive
// faster than 5 MB/s
// from a peer with 10 ms RTT, we cannot receive faster than
// 100 MB/s. This is assumed to be good enough, since bandwidth
// often is proportional to RTT anyway
// when setting a download rate limit, all sockets should have
// their receive buffer set much lower, to say 60 kiB or so
opt_rcvbuf = opt_sndbuf = 1024 * 1024;
last_check = 0;
}
struct_utp_context::~struct_utp_context() {
delete this->utp_sockets;
}
utp_context* utp_init (int version)
{
assert(version == 2);
if (version != 2)
return NULL;
utp_context *ctx = new utp_context;
return ctx;
}
void utp_destroy(utp_context *ctx) {
assert(ctx);
if (ctx) delete ctx;
}
void utp_set_callback(utp_context *ctx, int callback_name, utp_callback_t *proc) {
assert(ctx);
if (ctx) ctx->callbacks[callback_name] = proc;
}
void* utp_context_set_userdata(utp_context *ctx, void *userdata) {
assert(ctx);
if (ctx) ctx->userdata = userdata;
return ctx ? ctx->userdata : NULL;
}
void* utp_context_get_userdata(utp_context *ctx) {
assert(ctx);
return ctx ? ctx->userdata : NULL;
}
utp_context_stats* utp_get_context_stats(utp_context *ctx) {
assert(ctx);
return ctx ? &ctx->context_stats : NULL;
}
ssize_t utp_write(utp_socket *socket, void *buf, size_t len) {
struct utp_iovec iovec = { buf, len };
return utp_writev(socket, &iovec, 1);
}
}

View File

@ -0,0 +1,208 @@
// vim:set ts=4 sw=4 ai:
/*
* Copyright (c) 2010-2013 BitTorrent, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "utp_callbacks.h"
int utp_call_on_firewall(utp_context *ctx, const struct sockaddr *address, socklen_t address_len)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_ON_FIREWALL]) return 0;
args.callback_type = UTP_ON_FIREWALL;
args.context = ctx;
args.socket = NULL;
args.address = address;
args.address_len = address_len;
return (int)ctx->callbacks[UTP_ON_FIREWALL](&args);
}
void utp_call_on_accept(utp_context *ctx, utp_socket *socket, const struct sockaddr *address, socklen_t address_len)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_ON_ACCEPT]) return;
args.callback_type = UTP_ON_ACCEPT;
args.context = ctx;
args.socket = socket;
args.address = address;
args.address_len = address_len;
ctx->callbacks[UTP_ON_ACCEPT](&args);
}
void utp_call_on_connect(utp_context *ctx, utp_socket *socket)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_ON_CONNECT]) return;
args.callback_type = UTP_ON_CONNECT;
args.context = ctx;
args.socket = socket;
ctx->callbacks[UTP_ON_CONNECT](&args);
}
void utp_call_on_error(utp_context *ctx, utp_socket *socket, int error_code)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_ON_ERROR]) return;
args.callback_type = UTP_ON_ERROR;
args.context = ctx;
args.socket = socket;
args.error_code = error_code;
ctx->callbacks[UTP_ON_ERROR](&args);
}
void utp_call_on_read(utp_context *ctx, utp_socket *socket, const byte *buf, size_t len)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_ON_READ]) return;
args.callback_type = UTP_ON_READ;
args.context = ctx;
args.socket = socket;
args.buf = buf;
args.len = len;
ctx->callbacks[UTP_ON_READ](&args);
}
void utp_call_on_overhead_statistics(utp_context *ctx, utp_socket *socket, int send, size_t len, int type)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_ON_OVERHEAD_STATISTICS]) return;
args.callback_type = UTP_ON_OVERHEAD_STATISTICS;
args.context = ctx;
args.socket = socket;
args.send = send;
args.len = len;
args.type = type;
ctx->callbacks[UTP_ON_OVERHEAD_STATISTICS](&args);
}
void utp_call_on_delay_sample(utp_context *ctx, utp_socket *socket, int sample_ms)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_ON_DELAY_SAMPLE]) return;
args.callback_type = UTP_ON_DELAY_SAMPLE;
args.context = ctx;
args.socket = socket;
args.sample_ms = sample_ms;
ctx->callbacks[UTP_ON_DELAY_SAMPLE](&args);
}
void utp_call_on_state_change(utp_context *ctx, utp_socket *socket, int state)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_ON_STATE_CHANGE]) return;
args.callback_type = UTP_ON_STATE_CHANGE;
args.context = ctx;
args.socket = socket;
args.state = state;
ctx->callbacks[UTP_ON_STATE_CHANGE](&args);
}
uint16 utp_call_get_udp_mtu(utp_context *ctx, utp_socket *socket, const struct sockaddr *address, socklen_t address_len)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_GET_UDP_MTU]) return 0;
args.callback_type = UTP_GET_UDP_MTU;
args.context = ctx;
args.socket = socket;
args.address = address;
args.address_len = address_len;
return (uint16)ctx->callbacks[UTP_GET_UDP_MTU](&args);
}
uint16 utp_call_get_udp_overhead(utp_context *ctx, utp_socket *socket, const struct sockaddr *address, socklen_t address_len)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_GET_UDP_OVERHEAD]) return 0;
args.callback_type = UTP_GET_UDP_OVERHEAD;
args.context = ctx;
args.socket = socket;
args.address = address;
args.address_len = address_len;
return (uint16)ctx->callbacks[UTP_GET_UDP_OVERHEAD](&args);
}
uint64 utp_call_get_milliseconds(utp_context *ctx, utp_socket *socket)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_GET_MILLISECONDS]) return 0;
args.callback_type = UTP_GET_MILLISECONDS;
args.context = ctx;
args.socket = socket;
return ctx->callbacks[UTP_GET_MILLISECONDS](&args);
}
uint64 utp_call_get_microseconds(utp_context *ctx, utp_socket *socket)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_GET_MICROSECONDS]) return 0;
args.callback_type = UTP_GET_MICROSECONDS;
args.context = ctx;
args.socket = socket;
return ctx->callbacks[UTP_GET_MICROSECONDS](&args);
}
uint32 utp_call_get_random(utp_context *ctx, utp_socket *socket)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_GET_RANDOM]) return 0;
args.callback_type = UTP_GET_RANDOM;
args.context = ctx;
args.socket = socket;
return (uint32)ctx->callbacks[UTP_GET_RANDOM](&args);
}
size_t utp_call_get_read_buffer_size(utp_context *ctx, utp_socket *socket)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_GET_READ_BUFFER_SIZE]) return 0;
args.callback_type = UTP_GET_READ_BUFFER_SIZE;
args.context = ctx;
args.socket = socket;
return (size_t)ctx->callbacks[UTP_GET_READ_BUFFER_SIZE](&args);
}
void utp_call_log(utp_context *ctx, utp_socket *socket, const byte *buf)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_LOG]) return;
args.callback_type = UTP_LOG;
args.context = ctx;
args.socket = socket;
args.buf = buf;
ctx->callbacks[UTP_LOG](&args);
}
void utp_call_sendto(utp_context *ctx, utp_socket *socket, const byte *buf, size_t len, const struct sockaddr *address, socklen_t address_len, uint32 flags)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_SENDTO]) return;
args.callback_type = UTP_SENDTO;
args.context = ctx;
args.socket = socket;
args.buf = buf;
args.len = len;
args.address = address;
args.address_len = address_len;
args.flags = flags;
ctx->callbacks[UTP_SENDTO](&args);
}

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2010-2013 BitTorrent, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef __UTP_CALLBACKS_H__
#define __UTP_CALLBACKS_H__
#include "utp.h"
#include "utp_internal.h"
// Generated by running: grep ^[a-z] utp_callbacks.cpp | sed 's/$/;/'
int utp_call_on_firewall(utp_context *ctx, const struct sockaddr *address, socklen_t address_len);
void utp_call_on_accept(utp_context *ctx, utp_socket *s, const struct sockaddr *address, socklen_t address_len);
void utp_call_on_connect(utp_context *ctx, utp_socket *s);
void utp_call_on_error(utp_context *ctx, utp_socket *s, int error_code);
void utp_call_on_read(utp_context *ctx, utp_socket *s, const byte *buf, size_t len);
void utp_call_on_overhead_statistics(utp_context *ctx, utp_socket *s, int send, size_t len, int type);
void utp_call_on_delay_sample(utp_context *ctx, utp_socket *s, int sample_ms);
void utp_call_on_state_change(utp_context *ctx, utp_socket *s, int state);
uint16 utp_call_get_udp_mtu(utp_context *ctx, utp_socket *s, const struct sockaddr *address, socklen_t address_len);
uint16 utp_call_get_udp_overhead(utp_context *ctx, utp_socket *s, const struct sockaddr *address, socklen_t address_len);
uint64 utp_call_get_milliseconds(utp_context *ctx, utp_socket *s);
uint64 utp_call_get_microseconds(utp_context *ctx, utp_socket *s);
uint32 utp_call_get_random(utp_context *ctx, utp_socket *s);
size_t utp_call_get_read_buffer_size(utp_context *ctx, utp_socket *s);
void utp_call_log(utp_context *ctx, utp_socket *s, const byte *buf);
void utp_call_sendto(utp_context *ctx, utp_socket *s, const byte *buf, size_t len, const struct sockaddr *address, socklen_t address_len, uint32 flags);
#endif // __UTP_CALLBACKS_H__

View File

@ -0,0 +1,246 @@
/*
* Copyright (c) 2010-2013 BitTorrent, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "utp_hash.h"
#include "utp_types.h"
#define LIBUTP_HASH_UNUSED ((utp_link_t)-1)
#ifdef STRICT_ALIGN
inline uint32 Read32(const void *p)
{
uint32 tmp;
memcpy(&tmp, p, sizeof tmp);
return tmp;
}
#else
inline uint32 Read32(const void *p) { return *(uint32*)p; }
#endif
// Get the amount of memory required for the hash parameters and the bucket set
// Waste a space for an unused bucket in order to ensure the following managed memory have 32-bit aligned addresses
// TODO: make this 64-bit clean
#define BASE_SIZE(bc) (sizeof(utp_hash_t) + sizeof(utp_link_t) * ((bc) + 1))
// Get a pointer to the base of the structure array managed by the hash table
#define get_bep(h) ((byte*)(h)) + BASE_SIZE((h)->N)
// Get the address of the information associated with a specific structure in the array,
// given the address of the base of the structure.
// This assumes a utp_link_t link member is at the end of the structure.
// Given compilers filling out the memory to a 32-bit clean value, this may mean that
// the location named in the structure may not be the location actually used by the hash table,
// since the compiler may have padded the end of the structure with 2 bytes after the utp_link_t member.
// TODO: this macro should not require that the variable pointing at the hash table be named 'hash'
#define ptr_to_link(p) (utp_link_t *) (((byte *) (p)) + hash->E - sizeof(utp_link_t))
// Calculate how much to allocate for a hash table with bucket count, total size, and structure count
// TODO: make this 64-bit clean
#define ALLOCATION_SIZE(bc, ts, sc) (BASE_SIZE((bc)) + (ts) * (sc))
utp_hash_t *utp_hash_create(int N, int key_size, int total_size, int initial, utp_hash_compute_t hashfun, utp_hash_equal_t compfun)
{
// Must have odd number of hash buckets (prime number is best)
assert(N % 2);
// Ensure structures will be at aligned memory addresses
// TODO: make this 64-bit clean
assert(0 == (total_size % 4));
int size = ALLOCATION_SIZE(N, total_size, initial);
utp_hash_t *hash = (utp_hash_t *) malloc( size );
memset( hash, 0, size );
for (int i = 0; i < N + 1; ++i)
hash->inits[i] = LIBUTP_HASH_UNUSED;
hash->N = N;
hash->K = key_size;
hash->E = total_size;
hash->hash_compute = hashfun;
hash->hash_equal = compfun;
hash->allocated = initial;
hash->count = 0;
hash->used = 0;
hash->free = LIBUTP_HASH_UNUSED;
return hash;
}
uint utp_hash_mem(const void *keyp, size_t keysize)
{
uint hash = 0;
uint n = keysize;
while (n >= 4) {
hash ^= Read32(keyp);
keyp = (byte*)keyp + sizeof(uint32);
hash = (hash << 13) | (hash >> 19);
n -= 4;
}
while (n != 0) {
hash ^= *(byte*)keyp;
keyp = (byte*)keyp + sizeof(byte);
hash = (hash << 8) | (hash >> 24);
n--;
}
return hash;
}
uint utp_hash_mkidx(utp_hash_t *hash, const void *keyp)
{
// Generate a key from the hash
return hash->hash_compute(keyp, hash->K) % hash->N;
}
static inline bool compare(byte *a, byte *b,int n)
{
assert(n >= 4);
if (Read32(a) != Read32(b)) return false;
return memcmp(a+4, b+4, n-4) == 0;
}
#define COMPARE(h,k1,k2,ks) (((h)->hash_equal) ? (h)->hash_equal((void*)k1,(void*)k2,ks) : compare(k1,k2,ks))
// Look-up a key in the hash table.
// Returns NULL if not found
void *utp_hash_lookup(utp_hash_t *hash, const void *key)
{
utp_link_t idx = utp_hash_mkidx(hash, key);
// base pointer
byte *bep = get_bep(hash);
utp_link_t cur = hash->inits[idx];
while (cur != LIBUTP_HASH_UNUSED) {
byte *key2 = bep + (cur * hash->E);
if (COMPARE(hash, (byte*)key, key2, hash->K))
return key2;
cur = *ptr_to_link(key2);
}
return NULL;
}
// Add a new element to the hash table.
// Returns a pointer to the new element.
// This assumes the element is not already present!
void *utp_hash_add(utp_hash_t **hashp, const void *key)
{
//Allocate a new entry
byte *elemp;
utp_link_t elem;
utp_hash_t *hash = *hashp;
utp_link_t idx = utp_hash_mkidx(hash, key);
if ((elem=hash->free) == LIBUTP_HASH_UNUSED) {
utp_link_t all = hash->allocated;
if (hash->used == all) {
utp_hash_t *nhash;
if (all <= (LIBUTP_HASH_UNUSED/2)) {
all *= 2;
} else if (all != LIBUTP_HASH_UNUSED) {
all = LIBUTP_HASH_UNUSED;
} else {
// too many items! can't grow!
assert(0);
return NULL;
}
// otherwise need to allocate.
nhash = (utp_hash_t*)realloc(hash, ALLOCATION_SIZE(hash->N, hash->E, all));
if (!nhash) {
// out of memory (or too big to allocate)
assert(nhash);
return NULL;
}
hash = *hashp = nhash;
hash->allocated = all;
}
elem = hash->used++;
elemp = get_bep(hash) + elem * hash->E;
} else {
elemp = get_bep(hash) + elem * hash->E;
hash->free = *ptr_to_link(elemp);
}
*ptr_to_link(elemp) = hash->inits[idx];
hash->inits[idx] = elem;
hash->count++;
// copy key into it
memcpy(elemp, key, hash->K);
return elemp;
}
// Delete an element from the utp_hash_t
// Returns a pointer to the already deleted element.
void *utp_hash_del(utp_hash_t *hash, const void *key)
{
utp_link_t idx = utp_hash_mkidx(hash, key);
// base pointer
byte *bep = get_bep(hash);
utp_link_t *curp = &hash->inits[idx];
utp_link_t cur;
while ((cur=*curp) != LIBUTP_HASH_UNUSED) {
byte *key2 = bep + (cur * hash->E);
if (COMPARE(hash,(byte*)key,(byte*)key2, hash->K )) {
// found an item that matched. unlink it
*curp = *ptr_to_link(key2);
// Insert into freelist
*ptr_to_link(key2) = hash->free;
hash->free = cur;
hash->count--;
return key2;
}
curp = ptr_to_link(key2);
}
return NULL;
}
void *utp_hash_iterate(utp_hash_t *hash, utp_hash_iterator_t *iter)
{
utp_link_t elem;
if ((elem=iter->elem) == LIBUTP_HASH_UNUSED) {
// Find a bucket with an element
utp_link_t buck = iter->bucket + 1;
for(;;) {
if (buck >= hash->N)
return NULL;
if ((elem = hash->inits[buck]) != LIBUTP_HASH_UNUSED)
break;
buck++;
}
iter->bucket = buck;
}
byte *elemp = get_bep(hash) + (elem * hash->E);
iter->elem = *ptr_to_link(elemp);
return elemp;
}
void utp_hash_free_mem(utp_hash_t* hash)
{
free(hash);
}

View File

@ -0,0 +1,146 @@
/*
* Copyright (c) 2010-2013 BitTorrent, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef __UTP_HASH_H__
#define __UTP_HASH_H__
#include <string.h> // memset
#include <stdlib.h> // malloc
#include "utp_types.h"
#include "utp_templates.h"
// TODO: make utp_link_t a template parameter to HashTable
typedef uint32 utp_link_t;
#ifdef _MSC_VER
// Silence the warning about the C99-compliant zero-length array at the end of the structure
#pragma warning (disable: 4200)
#endif
typedef uint32 (*utp_hash_compute_t)(const void *keyp, size_t keysize);
typedef uint (*utp_hash_equal_t)(const void *key_a, const void *key_b, size_t keysize);
// In memory the HashTable is laid out as follows:
// ---------------------------- low
// | hash table data members |
// ---------------------------- _
// | indices | ^
// | . | | utp_link_t indices into the key-values.
// | . | .
// ---------------------------- - <----- bep
// | keys and values | each key-value pair has size total_size
// | . |
// | . |
// ---------------------------- high
//
// The code depends on the ability of the compiler to pad the length
// of the hash table data members structure to
// a length divisible by 32-bits with no remainder.
//
// Since the number of hash buckets (indices) should be odd, the code
// asserts this and adds one to the hash bucket count to ensure that the
// following key-value pairs array starts on a 32-bit boundary.
//
// The key-value pairs array should start on a 32-bit boundary, otherwise
// processors like the ARM will silently mangle 32-bit data in these structures
// (e.g., turning 0xABCD into 0XCDAB when moving a value from memory to register
// when the memory address is 16 bits offset from a 32-bit boundary),
// also, the value will be stored at an address two bytes lower than the address
// value would ordinarily indicate.
//
// The key-value pair is of type T. The first field in T must
// be the key, i.e., the first K bytes of T contains the key.
// total_size = sizeof(T) and thus sizeof(T) >= sizeof(K)
//
// N is the number of buckets.
//
struct utp_hash_t {
utp_link_t N;
byte K;
byte E;
size_t count;
utp_hash_compute_t hash_compute;
utp_hash_equal_t hash_equal;
utp_link_t allocated;
utp_link_t used;
utp_link_t free;
utp_link_t inits[0];
};
#ifdef _MSC_VER
#pragma warning (default: 4200)
#endif
struct utp_hash_iterator_t {
utp_link_t bucket;
utp_link_t elem;
utp_hash_iterator_t() : bucket(0xffffffff), elem(0xffffffff) {}
};
uint utp_hash_mem(const void *keyp, size_t keysize);
uint utp_hash_comp(const void *key_a, const void *key_b, size_t keysize);
utp_hash_t *utp_hash_create(int N, int key_size, int total_size, int initial, utp_hash_compute_t hashfun = utp_hash_mem, utp_hash_equal_t eqfun = NULL);
void *utp_hash_lookup(utp_hash_t *hash, const void *key);
void *utp_hash_add(utp_hash_t **hashp, const void *key);
void *utp_hash_del(utp_hash_t *hash, const void *key);
void *utp_hash_iterate(utp_hash_t *hash, utp_hash_iterator_t *iter);
void utp_hash_free_mem(utp_hash_t *hash);
/*
This HashTable requires that T have at least sizeof(K)+sizeof(utp_link_t) bytes.
Usually done like this:
struct K {
int whatever;
};
struct T {
K wtf;
utp_link_t link; // also wtf
};
*/
template<typename K, typename T> class utpHashTable {
utp_hash_t *hash;
public:
static uint compare(const void *k1, const void *k2, size_t ks) {
return *((K*)k1) == *((K*)k2);
}
static uint32 compute_hash(const void *k, size_t ks) {
return ((K*)k)->compute_hash();
}
void Init() { hash = NULL; }
bool Allocated() { return (hash != NULL); }
void Free() { utp_hash_free_mem(hash); hash = NULL; }
void Create(int N, int initial) { hash = utp_hash_create(N, sizeof(K), sizeof(T), initial, &compute_hash, &compare); }
T *Lookup(const K &key) { return (T*)utp_hash_lookup(hash, &key); }
T *Add(const K &key) { return (T*)utp_hash_add(&hash, &key); }
T *Delete(const K &key) { return (T*)utp_hash_del(hash, &key); }
T *Iterate(utp_hash_iterator_t &iterator) { return (T*)utp_hash_iterate(hash, &iterator); }
size_t GetCount() { return hash->count; }
};
#endif //__UTP_HASH_H__

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,139 @@
/*
* Copyright (c) 2010-2013 BitTorrent, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef __UTP_INTERNAL_H__
#define __UTP_INTERNAL_H__
#include <stdarg.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include "utp.h"
#include "utp_callbacks.h"
#include "utp_templates.h"
#include "utp_hash.h"
#include "utp_hash.h"
#include "utp_packedsockaddr.h"
/* These originally lived in utp_config.h */
#define CCONTROL_TARGET (100 * 1000) // us
enum bandwidth_type_t {
payload_bandwidth, connect_overhead,
close_overhead, ack_overhead,
header_overhead, retransmit_overhead
};
#ifdef WIN32
#ifdef _MSC_VER
#include "libutp_inet_ntop.h"
#endif
// newer versions of MSVC define these in errno.h
#ifndef ECONNRESET
#define ECONNRESET WSAECONNRESET
#define EMSGSIZE WSAEMSGSIZE
#define ECONNREFUSED WSAECONNREFUSED
#define ETIMEDOUT WSAETIMEDOUT
#endif
#endif
struct PACKED_ATTRIBUTE RST_Info {
PackedSockAddr addr;
uint32 connid;
uint16 ack_nr;
uint64 timestamp;
};
// It's really important that we don't have duplicate keys in the hash table.
// If we do, we'll eventually crash. if we try to remove the second instance
// of the key, we'll accidentally remove the first instead. then later,
// checkTimeouts will try to access the second one's already freed memory.
void UTP_FreeAll(struct UTPSocketHT *utp_sockets);
struct UTPSocketKey {
PackedSockAddr addr;
uint32 recv_id; // "conn_seed", "conn_id"
UTPSocketKey(const PackedSockAddr& _addr, uint32 _recv_id) {
memset(this, 0, sizeof(*this));
addr = _addr;
recv_id = _recv_id;
}
bool operator == (const UTPSocketKey &other) const {
return recv_id == other.recv_id && addr == other.addr;
}
uint32 compute_hash() const {
return recv_id ^ addr.compute_hash();
}
};
struct UTPSocketKeyData {
UTPSocketKey key;
UTPSocket *socket;
utp_link_t link;
};
#define UTP_SOCKET_BUCKETS 79
#define UTP_SOCKET_INIT 15
struct UTPSocketHT : utpHashTable<UTPSocketKey, UTPSocketKeyData> {
UTPSocketHT() {
const int buckets = UTP_SOCKET_BUCKETS;
const int initial = UTP_SOCKET_INIT;
this->Create(buckets, initial);
}
~UTPSocketHT() {
UTP_FreeAll(this);
this->Free();
}
};
struct struct_utp_context {
void *userdata;
utp_callback_t* callbacks[UTP_ARRAY_SIZE];
uint64 current_ms;
utp_context_stats context_stats;
UTPSocket *last_utp_socket;
Array<UTPSocket*> ack_sockets;
Array<RST_Info> rst_info;
UTPSocketHT *utp_sockets;
size_t target_delay;
size_t opt_sndbuf;
size_t opt_rcvbuf;
uint64 last_check;
struct_utp_context();
~struct_utp_context();
void log(int level, utp_socket *socket, char const *fmt, ...);
bool log_normal:1; // log normal events?
bool log_mtu:1; // log MTU related events?
bool log_debug:1; // log debugging events? (Must also compile with UTP_DEBUG_LOGGING defined)
};
#endif //__UTP_INTERNAL_H__

View File

@ -0,0 +1,139 @@
// vim:set ts=4 sw=4 ai:
/*
* Copyright (c) 2010-2013 BitTorrent, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include "utp_types.h"
#include "utp_hash.h"
#include "utp_packedsockaddr.h"
//#include "libutp_inet_ntop.h"
byte PackedSockAddr::get_family() const
{
#if defined(__sh__)
return ((_sin6d[0] == 0) && (_sin6d[1] == 0) && (_sin6d[2] == htonl(0xffff)) != 0) ?
AF_INET : AF_INET6;
#else
return (IN6_IS_ADDR_V4MAPPED(&_in._in6addr) != 0) ? AF_INET : AF_INET6;
#endif // defined(__sh__)
}
bool PackedSockAddr::operator==(const PackedSockAddr& rhs) const
{
if (&rhs == this)
return true;
if (_port != rhs._port)
return false;
return memcmp(_sin6, rhs._sin6, sizeof(_sin6)) == 0;
}
bool PackedSockAddr::operator!=(const PackedSockAddr& rhs) const
{
return !(*this == rhs);
}
uint32 PackedSockAddr::compute_hash() const {
return utp_hash_mem(&_in, sizeof(_in)) ^ _port;
}
void PackedSockAddr::set(const SOCKADDR_STORAGE* sa, socklen_t len)
{
if (sa->ss_family == AF_INET) {
assert(len >= sizeof(sockaddr_in));
const sockaddr_in *sin = (sockaddr_in*)sa;
_sin6w[0] = 0;
_sin6w[1] = 0;
_sin6w[2] = 0;
_sin6w[3] = 0;
_sin6w[4] = 0;
_sin6w[5] = 0xffff;
_sin4 = sin->sin_addr.s_addr;
_port = ntohs(sin->sin_port);
} else {
assert(len >= sizeof(sockaddr_in6));
const sockaddr_in6 *sin6 = (sockaddr_in6*)sa;
_in._in6addr = sin6->sin6_addr;
_port = ntohs(sin6->sin6_port);
}
}
PackedSockAddr::PackedSockAddr(const SOCKADDR_STORAGE* sa, socklen_t len)
{
set(sa, len);
}
PackedSockAddr::PackedSockAddr(void)
{
SOCKADDR_STORAGE sa;
socklen_t len = sizeof(SOCKADDR_STORAGE);
memset(&sa, 0, len);
sa.ss_family = AF_INET;
set(&sa, len);
}
SOCKADDR_STORAGE PackedSockAddr::get_sockaddr_storage(socklen_t *len = NULL) const
{
SOCKADDR_STORAGE sa;
const byte family = get_family();
if (family == AF_INET) {
sockaddr_in *sin = (sockaddr_in*)&sa;
if (len) *len = sizeof(sockaddr_in);
memset(sin, 0, sizeof(sockaddr_in));
sin->sin_family = family;
sin->sin_port = htons(_port);
sin->sin_addr.s_addr = _sin4;
} else {
sockaddr_in6 *sin6 = (sockaddr_in6*)&sa;
memset(sin6, 0, sizeof(sockaddr_in6));
if (len) *len = sizeof(sockaddr_in6);
sin6->sin6_family = family;
sin6->sin6_addr = _in._in6addr;
sin6->sin6_port = htons(_port);
}
return sa;
}
// #define addrfmt(x, s) x.fmt(s, sizeof(s))
cstr PackedSockAddr::fmt(str s, size_t len) const
{
memset(s, 0, len);
const byte family = get_family();
str i;
if (family == AF_INET) {
inet_ntop(family, (uint32*)&_sin4, s, len);
i = s;
while (*++i) {}
} else {
i = s;
*i++ = '[';
inet_ntop(family, (in6_addr*)&_in._in6addr, i, len-1);
while (*++i) {}
*i++ = ']';
}
snprintf(i, len - (i-s), ":%u", _port);
return s;
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2010-2013 BitTorrent, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef __UTP_PACKEDSOCKADDR_H__
#define __UTP_PACKEDSOCKADDR_H__
#include "utp_types.h"
struct PACKED_ATTRIBUTE PackedSockAddr {
// The values are always stored here in network byte order
union {
byte _in6[16]; // IPv6
uint16 _in6w[8]; // IPv6, word based (for convenience)
uint32 _in6d[4]; // Dword access
in6_addr _in6addr; // For convenience
} _in;
// Host byte order
uint16 _port;
#define _sin4 _in._in6d[3] // IPv4 is stored where it goes if mapped
#define _sin6 _in._in6
#define _sin6w _in._in6w
#define _sin6d _in._in6d
byte get_family() const;
bool operator==(const PackedSockAddr& rhs) const;
bool operator!=(const PackedSockAddr& rhs) const;
void set(const SOCKADDR_STORAGE* sa, socklen_t len);
PackedSockAddr(const SOCKADDR_STORAGE* sa, socklen_t len);
PackedSockAddr(void);
SOCKADDR_STORAGE get_sockaddr_storage(socklen_t *len) const;
cstr fmt(str s, size_t len) const;
uint32 compute_hash() const;
} ALIGNED_ATTRIBUTE(4);
#endif //__UTP_PACKEDSOCKADDR_H__

View File

@ -0,0 +1,195 @@
/*
* Copyright (c) 2010-2013 BitTorrent, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef __TEMPLATES_H__
#define __TEMPLATES_H__
#include "utp_types.h"
#include <assert.h>
#if defined(POSIX)
/* Allow over-writing FORCEINLINE from makefile because gcc 3.4.4 for buffalo
doesn't seem to support __attribute__((always_inline)) in -O0 build
(strangely, it works in -Os build) */
#ifndef FORCEINLINE
// The always_inline attribute asks gcc to inline the function even if no optimization is being requested.
// This macro should be used exclusive-or with the inline directive (use one or the other but not both)
// since Microsoft uses __forceinline to also mean inline,
// and this code is following a Microsoft compatibility model.
// Just setting the attribute without also specifying the inline directive apparently won't inline the function,
// as evidenced by multiply-defined symbols found at link time.
#define FORCEINLINE inline __attribute__((always_inline))
#endif
#endif
// Utility templates
#undef min
#undef max
template <typename T> static inline T min(T a, T b) { if (a < b) return a; return b; }
template <typename T> static inline T max(T a, T b) { if (a > b) return a; return b; }
template <typename T> static inline T min(T a, T b, T c) { return min(min(a,b),c); }
template <typename T> static inline T max(T a, T b, T c) { return max(max(a,b),c); }
template <typename T> static inline T clamp(T v, T mi, T ma)
{
if (v > ma) v = ma;
if (v < mi) v = mi;
return v;
}
#if (defined(__SVR4) && defined(__sun))
#pragma pack(1)
#else
#pragma pack(push,1)
#endif
namespace aux
{
FORCEINLINE uint16 host_to_network(uint16 i) { return htons(i); }
FORCEINLINE uint32 host_to_network(uint32 i) { return htonl(i); }
FORCEINLINE int32 host_to_network(int32 i) { return htonl(i); }
FORCEINLINE uint16 network_to_host(uint16 i) { return ntohs(i); }
FORCEINLINE uint32 network_to_host(uint32 i) { return ntohl(i); }
FORCEINLINE int32 network_to_host(int32 i) { return ntohl(i); }
}
template <class T>
struct PACKED_ATTRIBUTE big_endian
{
T operator=(T i) { m_integer = aux::host_to_network(i); return i; }
operator T() const { return aux::network_to_host(m_integer); }
private:
T m_integer;
};
typedef big_endian<int32> int32_big;
typedef big_endian<uint32> uint32_big;
typedef big_endian<uint16> uint16_big;
#if (defined(__SVR4) && defined(__sun))
#pragma pack(0)
#else
#pragma pack(pop)
#endif
template<typename T> static inline void zeromem(T *a, size_t count = 1) { memset(a, 0, count * sizeof(T)); }
typedef int SortCompareProc(const void *, const void *);
template<typename T> static FORCEINLINE void QuickSortT(T *base, size_t num, int (*comp)(const T *, const T *)) { qsort(base, num, sizeof(T), (SortCompareProc*)comp); }
// WARNING: The template parameter MUST be a POD type!
template <typename T, size_t minsize = 16> class Array {
protected:
T *mem;
size_t alloc,count;
public:
Array(size_t init) { Init(init); }
Array() { Init(); }
~Array() { Free(); }
void inline Init() { mem = NULL; alloc = count = 0; }
void inline Init(size_t init) { Init(); if (init) Resize(init); }
size_t inline GetCount() const { return count; }
size_t inline GetAlloc() const { return alloc; }
void inline SetCount(size_t c) { count = c; }
inline T& operator[](size_t offset) { assert(offset ==0 || offset<alloc); return mem[offset]; }
inline const T& operator[](size_t offset) const { assert(offset ==0 || offset<alloc); return mem[offset]; }
void inline Resize(size_t a) {
if (a == 0) { free(mem); Init(); }
else { mem = (T*)realloc(mem, (alloc=a) * sizeof(T)); }
}
void Grow() { Resize(::max<size_t>(minsize, alloc * 2)); }
inline size_t Append(const T &t) {
if (count >= alloc) Grow();
size_t r=count++;
mem[r] = t;
return r;
}
T inline &Append() {
if (count >= alloc) Grow();
return mem[count++];
}
void inline Compact() {
Resize(count);
}
void inline Free() {
free(mem);
Init();
}
void inline Clear() {
count = 0;
}
bool inline MoveUpLast(size_t index) {
assert(index < count);
size_t c = --count;
if (index != c) {
mem[index] = mem[c];
return true;
}
return false;
}
bool inline MoveUpLastExist(const T &v) {
return MoveUpLast(LookupElementExist(v));
}
size_t inline LookupElement(const T &v) const {
for(size_t i = 0; i != count; i++)
if (mem[i] == v)
return i;
return (size_t) -1;
}
bool inline HasElement(const T &v) const {
return LookupElement(v) != -1;
}
typedef int SortCompareProc(const T *a, const T *b);
void Sort(SortCompareProc* proc, size_t start, size_t end) {
QuickSortT(&mem[start], end - start, proc);
}
void Sort(SortCompareProc* proc, size_t start) {
Sort(proc, start, count);
}
void Sort(SortCompareProc* proc) {
Sort(proc, 0, count);
}
};
#endif //__TEMPLATES_H__

View File

@ -0,0 +1,121 @@
/*
* Copyright (c) 2010-2013 BitTorrent, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef __UTP_TYPES_H__
#define __UTP_TYPES_H__
#ifdef __GNUC__
// Used for gcc tool chains accepting but not supporting pragma pack
// See http://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html
#define PACKED_ATTRIBUTE __attribute__((__packed__))
#else
#define PACKED_ATTRIBUTE
#endif
#ifdef __GNUC__
#define ALIGNED_ATTRIBUTE(x) __attribute__((aligned (x)))
#else
#define ALIGNED_ATTRIBUTE(x)
#endif
// hash.cpp needs socket definitions, which is why this networking specific
// code is inclued in utypes.h
#ifdef WIN32
#define _CRT_SECURE_NO_DEPRECATE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#define IP_OPT_DONTFRAG IP_DONTFRAGMENT
#else
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/socket.h>
#ifdef IP_DONTFRAG
#define IP_OPT_DONTFRAG IP_DONTFRAG
#elif defined IP_DONTFRAGMENT
#define IP_OPT_DONTFRAG IP_DONTFRAGMENT
#else
//#warning "I don't know how to set DF bit on this system"
#endif
#endif
#ifdef _MSC_VER
#include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#endif
#ifdef POSIX
typedef struct sockaddr_storage SOCKADDR_STORAGE;
#endif
#ifdef WIN32
#define I64u "%I64u"
#else
#define I64u "%Lu"
#endif
#ifdef WIN32
#define snprintf _snprintf
#endif
// standard types
typedef unsigned char byte;
typedef unsigned char uint8;
typedef signed char int8;
typedef unsigned short uint16;
typedef signed short int16;
typedef unsigned int uint;
typedef unsigned int uint32;
typedef signed int int32;
#ifdef _MSC_VER
typedef unsigned __int64 uint64;
typedef signed __int64 int64;
#else
typedef unsigned long long uint64;
typedef long long int64;
#endif
/* compile-time assert */
#ifndef CASSERT
#define CASSERT( exp, name ) typedef int is_not_##name [ (exp ) ? 1 : -1 ];
#endif
CASSERT(8 == sizeof(uint64), sizeof_uint64_is_8)
CASSERT(8 == sizeof(int64), sizeof_int64_is_8)
#ifndef INT64_MAX
#define INT64_MAX 0x7fffffffffffffffLL
#endif
// always ANSI
typedef const char * cstr;
typedef char * str;
#ifndef __cplusplus
typedef uint8 bool;
#endif
#endif //__UTP_TYPES_H__

View File

@ -0,0 +1,254 @@
/*
* Copyright (c) 2010-2013 BitTorrent, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdlib.h>
#include <assert.h>
#include "utp.h"
#include "utp_types.h"
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#else //!WIN32
#include <time.h>
#include <sys/time.h> // Linux needs both time.h and sys/time.h
#endif
#if defined(__APPLE__)
#include <mach/mach_time.h>
#endif
#include "utp_utils.h"
#ifdef WIN32
typedef ULONGLONG (WINAPI GetTickCount64Proc)(void);
static GetTickCount64Proc *pt2GetTickCount64;
static GetTickCount64Proc *pt2RealGetTickCount;
static uint64 startPerformanceCounter;
static uint64 startGetTickCount;
// MSVC 6 standard doesn't like division with uint64s
static double counterPerMicrosecond;
static uint64 UTGetTickCount64()
{
if (pt2GetTickCount64) {
return pt2GetTickCount64();
}
if (pt2RealGetTickCount) {
uint64 v = pt2RealGetTickCount();
// fix return value from GetTickCount
return (DWORD)v | ((v >> 0x18) & 0xFFFFFFFF00000000);
}
return (uint64)GetTickCount();
}
static void Time_Initialize()
{
HMODULE kernel32 = GetModuleHandleA("kernel32.dll");
pt2GetTickCount64 = (GetTickCount64Proc*)GetProcAddress(kernel32, "GetTickCount64");
// not a typo. GetTickCount actually returns 64 bits
pt2RealGetTickCount = (GetTickCount64Proc*)GetProcAddress(kernel32, "GetTickCount");
uint64 frequency;
QueryPerformanceCounter((LARGE_INTEGER*)&startPerformanceCounter);
QueryPerformanceFrequency((LARGE_INTEGER*)&frequency);
counterPerMicrosecond = (double)frequency / 1000000.0f;
startGetTickCount = UTGetTickCount64();
}
static int64 abs64(int64 x) { return x < 0 ? -x : x; }
static uint64 __GetMicroseconds()
{
static bool time_init = false;
if (!time_init) {
time_init = true;
Time_Initialize();
}
uint64 counter;
uint64 tick;
QueryPerformanceCounter((LARGE_INTEGER*) &counter);
tick = UTGetTickCount64();
// unfortunately, QueryPerformanceCounter is not guaranteed
// to be monotonic. Make it so.
int64 ret = (int64)(((int64)counter - (int64)startPerformanceCounter) / counterPerMicrosecond);
// if the QPC clock leaps more than one second off GetTickCount64()
// something is seriously fishy. Adjust QPC to stay monotonic
int64 tick_diff = tick - startGetTickCount;
if (abs64(ret / 100000 - tick_diff / 100) > 10) {
startPerformanceCounter -= (uint64)((int64)(tick_diff * 1000 - ret) * counterPerMicrosecond);
ret = (int64)((counter - startPerformanceCounter) / counterPerMicrosecond);
}
return ret;
}
static inline uint64 UTP_GetMilliseconds()
{
return GetTickCount();
}
#else //!WIN32
static inline uint64 UTP_GetMicroseconds(void);
static inline uint64 UTP_GetMilliseconds()
{
return UTP_GetMicroseconds() / 1000;
}
#if defined(__APPLE__)
static uint64 __GetMicroseconds()
{
// http://developer.apple.com/mac/library/qa/qa2004/qa1398.html
// http://www.macresearch.org/tutorial_performance_and_time
static mach_timebase_info_data_t sTimebaseInfo;
static uint64_t start_tick = 0;
uint64_t tick;
// Returns a counter in some fraction of a nanoseconds
tick = mach_absolute_time();
if (sTimebaseInfo.denom == 0) {
// Get the timer ratio to convert mach_absolute_time to nanoseconds
mach_timebase_info(&sTimebaseInfo);
start_tick = tick;
}
// Calculate the elapsed time, convert it to microseconds and return it.
return ((tick - start_tick) * sTimebaseInfo.numer) / (sTimebaseInfo.denom * 1000);
}
#else // !__APPLE__
#if ! (defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 && defined(CLOCK_MONOTONIC))
#warning "Using non-monotonic function gettimeofday() in UTP_GetMicroseconds()"
#endif
/* Unfortunately, #ifdef CLOCK_MONOTONIC is not enough to make sure that
POSIX clocks work -- we could be running a recent libc with an ancient
kernel (think OpenWRT). -- jch */
static uint64_t __GetMicroseconds()
{
struct timeval tv;
#if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 && defined(CLOCK_MONOTONIC)
static int have_posix_clocks = -1;
int rc;
if (have_posix_clocks < 0) {
struct timespec ts;
rc = clock_gettime(CLOCK_MONOTONIC, &ts);
if (rc < 0) {
have_posix_clocks = 0;
} else {
have_posix_clocks = 1;
}
}
if (have_posix_clocks) {
struct timespec ts;
rc = clock_gettime(CLOCK_MONOTONIC, &ts);
return uint64(ts.tv_sec) * 1000000 + uint64(ts.tv_nsec) / 1000;
}
#endif
gettimeofday(&tv, NULL);
return uint64(tv.tv_sec) * 1000000 + tv.tv_usec;
}
#endif //!__APPLE__
#endif //!WIN32
/*
* Whew. Okay. After that #ifdef maze above, we now know we have a working
* __GetMicroseconds() implementation on all platforms.
*
* Because there are a number of assertions in libutp that will cause a crash
* if monotonic time isn't monotonic, now apply some safety checks. While in
* principle we're already protecting ourselves in cases where non-monotonic
* time is likely to happen, this protects all versions.
*/
static inline uint64 UTP_GetMicroseconds()
{
static uint64 offset = 0, previous = 0;
uint64 now = __GetMicroseconds() + offset;
if (previous > now) {
/* Eek! */
offset += previous - now;
now = previous;
}
previous = now;
return now;
}
#define ETHERNET_MTU 1500
#define IPV4_HEADER_SIZE 20
#define IPV6_HEADER_SIZE 40
#define UDP_HEADER_SIZE 8
#define GRE_HEADER_SIZE 24
#define PPPOE_HEADER_SIZE 8
#define MPPE_HEADER_SIZE 2
// packets have been observed in the wild that were fragmented
// with a payload of 1416 for the first fragment
// There are reports of routers that have MTU sizes as small as 1392
#define FUDGE_HEADER_SIZE 36
#define TEREDO_MTU 1280
#define UDP_IPV4_OVERHEAD (IPV4_HEADER_SIZE + UDP_HEADER_SIZE)
#define UDP_IPV6_OVERHEAD (IPV6_HEADER_SIZE + UDP_HEADER_SIZE)
#define UDP_TEREDO_OVERHEAD (UDP_IPV4_OVERHEAD + UDP_IPV6_OVERHEAD)
#define UDP_IPV4_MTU (ETHERNET_MTU - IPV4_HEADER_SIZE - UDP_HEADER_SIZE - GRE_HEADER_SIZE - PPPOE_HEADER_SIZE - MPPE_HEADER_SIZE - FUDGE_HEADER_SIZE)
#define UDP_IPV6_MTU (ETHERNET_MTU - IPV6_HEADER_SIZE - UDP_HEADER_SIZE - GRE_HEADER_SIZE - PPPOE_HEADER_SIZE - MPPE_HEADER_SIZE - FUDGE_HEADER_SIZE)
#define UDP_TEREDO_MTU (TEREDO_MTU - IPV6_HEADER_SIZE - UDP_HEADER_SIZE)
uint64 utp_default_get_udp_mtu(utp_callback_arguments *args) {
// Since we don't know the local address of the interface,
// be conservative and assume all IPv6 connections are Teredo.
return (args->address->sa_family == AF_INET6) ? UDP_TEREDO_MTU : UDP_IPV4_MTU;
}
uint64 utp_default_get_udp_overhead(utp_callback_arguments *args) {
// Since we don't know the local address of the interface,
// be conservative and assume all IPv6 connections are Teredo.
return (args->address->sa_family == AF_INET6) ? UDP_TEREDO_OVERHEAD : UDP_IPV4_OVERHEAD;
}
uint64 utp_default_get_random(utp_callback_arguments *args) {
return rand();
}
uint64 utp_default_get_milliseconds(utp_callback_arguments *args) {
return UTP_GetMilliseconds();
}
uint64 utp_default_get_microseconds(utp_callback_arguments *args) {
return UTP_GetMicroseconds();
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2010-2013 BitTorrent, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
uint64 utp_default_get_udp_mtu(utp_callback_arguments *args);
uint64 utp_default_get_udp_overhead(utp_callback_arguments *args);
uint64 utp_default_get_random(utp_callback_arguments *args);
uint64 utp_default_get_milliseconds(utp_callback_arguments *args);
uint64 utp_default_get_microseconds(utp_callback_arguments *args);

Some files were not shown because too many files have changed in this diff Show More