forked from acouzens/open5gs
add build system using Core Library
This commit is contained in:
parent
ea7950b2ea
commit
fdf97f47bb
|
@ -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.
|
|
@ -0,0 +1,46 @@
|
|||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
SUBDIRS = lib src
|
||||
|
||||
bin_PROGRAMS = cellwired
|
||||
|
||||
dist_cellwired_SOURCES = main.c symtbl.h
|
||||
nodist_cellwired_SOURCES = symtbl.c
|
||||
|
||||
cellwired_LDADD = \
|
||||
$(top_srcdir)/src/libcellwire.la \
|
||||
$(top_srcdir)/lib/core/src/libcore.la \
|
||||
$(top_srcdir)/lib/logger/liblogger.la \
|
||||
-lpthread -lm -lsctp @OSLIBS@
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/lib/core/include \
|
||||
-I$(top_srcdir)/lib/logger \
|
||||
-I$(top_srcdir)/src
|
||||
|
||||
CLEANFILES = symtbl.c
|
||||
DISTCLEANFILES = $(DIST_ARCHIVES)
|
||||
MAINTAINERCLEANFILES = \
|
||||
configure config.in \
|
||||
aclocal.m4 m4/ltsugar.m4 m4/libtool.m4 m4/ltversion.m4 \
|
||||
m4/lt~obsolete.m4 m4/ltoptions.m4 \
|
||||
build-aux/depcomp build-aux/missing build-aux/config.guess \
|
||||
build-aux/config.sub build-aux/ltmain.sh build-aux/install-sh \
|
||||
.cscope.out .cscope.out.in .cscope.files .cscope.out.po \
|
||||
Makefile.in
|
||||
MOSTLYCLEANFILES = core *.stackdump
|
||||
|
||||
EXTRA_DIST = symtbl.sh
|
||||
|
||||
NM_TMP_FILE = nm.tmp
|
||||
.INTERMEDIATE: symtbl.c
|
||||
symtbl.c: $(bsd_DEPENDENCIES)
|
||||
@for las in $<; do \
|
||||
lib=`echo $$las | sed -e "s|\(.*\)/lib\([^/].*\)\.la|\1/.libs/lib\2.a|g"`; \
|
||||
echo $$lib; \
|
||||
nm $$lib >> $(NM_TMP_FILE); \
|
||||
done; \
|
||||
$(top_srcdir)/symtbl.sh $(NM_TMP_FILE) $@; \
|
||||
rm -f $(NM_TMP_FILE)
|
|
@ -0,0 +1,64 @@
|
|||
* Git Config
|
||||
user@host:~/git/cellwire$ sudo apt-get install git
|
||||
user@host:~/git/cellwire$ git config --global user.name "Sukchan Lee"
|
||||
user@host:~/git/cellwire$ git config --global user.email acetcom@gmail.com
|
||||
user@host:~/git/cellwire$ git config --global core.editor vi
|
||||
user@host:~/git/cellwire$ git clone https://github.com/acetcom/cellwire.git
|
||||
|
||||
* Initial Setup
|
||||
user@host:~/git/cellwire$ sudo apt-get install autoconf libtool m4 libsctp-dev
|
||||
cscope gdb
|
||||
user@host:~/git/cellwire$ autoreconf -iv
|
||||
user@host:~/git/cellwire$ \
|
||||
CFLAGS='-g3' ./configure --prefix=$HOME/Documents/git/cellwire/install
|
||||
user@host:~/git/cellwire$ make OR make install
|
||||
|
||||
* Install SCTP for Mac OS X 10.11(El Captian)
|
||||
- Reference : https://github.com/sctplab/SCTP_NKE_ElCapitan
|
||||
- Start up in OS X Recovery by holding down Command-R while the Mac is starting up
|
||||
Choose Terminal from the Utilities menu.
|
||||
Type 'csrutil disable' in Terminal and Reboot
|
||||
- Download SCTP_NKE_ElCapitan_Install_01.dmg
|
||||
xcode-select --install
|
||||
sudo cp -R /Volumes/SCTP_NKE_ElCapitan_01/SCTPSupport.kext /Library/Extensions
|
||||
sudo cp -R /Volumes/SCTP_NKE_ElCapitan_01/SCTP.kext /Library/Extensions
|
||||
sudo cp /Volumes/SCTP_NKE_ElCapitan_01/socket.h /usr/include/sys/
|
||||
sudo cp /Volumes/SCTP_NKE_ElCapitan_01/sctp.h /usr/include/netinet/
|
||||
sudo cp /Volumes/SCTP_NKE_ElCapitan_01/sctp_uio.h /usr/include/netinet/
|
||||
sudo cp /Volumes/SCTP_NKE_ElCapitan_01/libsctp.dylib /usr/lib/
|
||||
sudo kextload /Library/Extensions/SCTP.kext
|
||||
|
||||
* Git in Development
|
||||
user@host:~/git/cellwire$ git status -uno
|
||||
user@host:~/git/cellwire$ git add README
|
||||
user@host:~/git/cellwire$ git commit
|
||||
user@host:~/git/cellwire$ git push -u orgin master
|
||||
user@host:~/git/cellwire$ git pull
|
||||
user@host:~/git/cellwire$ git reset --hard HEAD
|
||||
user@host:~/git/cellwire$ git checkout README
|
||||
|
||||
* CSCOPE
|
||||
Download ViM plugin to user@host:~/.vim/plugin/cscope_maps.vim
|
||||
CSCOPE_DB="/home/acetcom/git/cellwire/.cscope.out"
|
||||
export CSCOPE_DB
|
||||
user@host:~/git/cellwire$ ./mkcscope.sh
|
||||
|
||||
* Reconfigure Build
|
||||
user@host:~/git/cellwire$ ./config.nice
|
||||
## config.nice sample script
|
||||
CFLAGS='-g3' \
|
||||
'./configure' \
|
||||
'--prefix=/home/acetcom/Documents/git/install' \
|
||||
"$@"
|
||||
|
||||
* Testing
|
||||
user@host:~/git/cellwire$ ./lib/core/test/testcore
|
||||
|
||||
* Running
|
||||
user@host:~/git/cellwire$ sudo ./cellwired
|
||||
|
||||
* Cleaning
|
||||
user@host:~/git/cellwire$ make clean
|
||||
user@host:~/git/cellwire$ make distclean
|
||||
user@host:~/git/cellwire$ make maintainer-clean
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
dnl
|
||||
dnl CORE_SUBST(varname)
|
||||
dnl
|
||||
dnl Adds variable with it's value into Makefile, e.g.:
|
||||
dnl CC = gcc
|
||||
dnl
|
||||
AC_DEFUN([CORE_SUBST],[
|
||||
CORE_VAR_SUBST="$CORE_VAR_SUBST $1"
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl CORE_SUBST_OLD(varname)
|
||||
dnl
|
||||
dnl Same as CORE_SUBST() but also substitutes all @VARNAME@
|
||||
dnl instances in every file passed to AC_OUTPUT()
|
||||
dnl
|
||||
AC_DEFUN([CORE_SUBST_OLD],[
|
||||
CORE_SUBST($1)
|
||||
AC_SUBST($1)
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl CORE_CONFIG_NICE(filename)
|
||||
dnl
|
||||
dnl Generates the config.nice file
|
||||
dnl
|
||||
AC_DEFUN([CORE_CONFIG_NICE],[
|
||||
AC_REQUIRE([AC_PROG_EGREP])
|
||||
AC_REQUIRE([LT_AC_PROG_SED])
|
||||
CORE_SUBST_OLD(EGREP)
|
||||
CORE_SUBST_OLD(SED)
|
||||
test -f $1 && mv $1 $1.old
|
||||
rm -f $1.old
|
||||
cat >$1<<EOF
|
||||
#! /bin/sh
|
||||
#
|
||||
# Created by configure
|
||||
|
||||
EOF
|
||||
|
||||
for var in CFLAGS CXXFLAGS CPPFLAGS LDFLAGS EXTRA_LDFLAGS_PROGRAM LIBS CC CXX; do
|
||||
eval val=\$$var
|
||||
if test -n "$val"; then
|
||||
echo "$var='$val' \\" >> $1
|
||||
fi
|
||||
done
|
||||
|
||||
echo "'[$]0' \\" >> $1
|
||||
if test `expr -- [$]0 : "'.*"` = 0; then
|
||||
CONFIGURE_COMMAND="$CONFIGURE_COMMAND '[$]0'"
|
||||
else
|
||||
CONFIGURE_COMMAND="$CONFIGURE_COMMAND [$]0"
|
||||
fi
|
||||
for arg in $ac_configure_args; do
|
||||
if test `expr -- $arg : "'.*"` = 0; then
|
||||
if test `expr -- $arg : "--.*"` = 0; then
|
||||
break;
|
||||
fi
|
||||
echo "'[$]arg' \\" >> $1
|
||||
CONFIGURE_OPTIONS="$CONFIGURE_OPTIONS '[$]arg'"
|
||||
else
|
||||
if test `expr -- $arg : "'--.*"` = 0; then
|
||||
break;
|
||||
fi
|
||||
echo "[$]arg \\" >> $1
|
||||
CONFIGURE_OPTIONS="$CONFIGURE_OPTIONS [$]arg"
|
||||
fi
|
||||
done
|
||||
echo '"[$]@"' >> $1
|
||||
chmod +x $1
|
||||
CONFIGURE_COMMAND="$CONFIGURE_COMMAND $CONFIGURE_OPTIONS"
|
||||
CORE_SUBST_OLD(CONFIGURE_COMMAND)
|
||||
CORE_SUBST_OLD(CONFIGURE_OPTIONS)
|
||||
])
|
|
@ -0,0 +1,272 @@
|
|||
dnl Process this file with autoconf to produce a configure script.
|
||||
dnl
|
||||
dnl This file is free software; as a special exception the author gives
|
||||
dnl unlimited permission to copy and/or distribute it, with or without
|
||||
dnl modifications, as long as this notice is preserved.
|
||||
dnl
|
||||
dnl This program is distributed in the hope that it will be useful, but
|
||||
dnl WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
|
||||
dnl implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
AC_INIT([CELLWIRE], [0.1.0], [acetcom@gmail.com])
|
||||
|
||||
CORE_CONFIG_NICE(config.nice)
|
||||
|
||||
dnl Must come before AM_INIT_AUTOMAKE.
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AM_INIT_AUTOMAKE([1.10 -Wall -Werror])
|
||||
|
||||
# Minimum Autoconf version required.
|
||||
AC_PREREQ(2.63)
|
||||
|
||||
# Where to generate output; srcdir location.
|
||||
AC_CONFIG_HEADERS([config.h:config.in])dnl Keep filename to 8.3 for MS-DOS.
|
||||
AC_CONFIG_SRCDIR([main.c])
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
case $host in
|
||||
*linux*)
|
||||
OSDIR="unix"
|
||||
OSCFLAGS="-DLINUX=1"
|
||||
;;
|
||||
*)
|
||||
OSDIR="unix"
|
||||
;;
|
||||
esac
|
||||
AC_SUBST(OSCFLAGS)
|
||||
AC_SUBST(OSDIR)
|
||||
|
||||
AH_TOP([
|
||||
#ifndef __CELLWIRE_CONFIG_H__
|
||||
#define __CELLWIRE_CONFIG_H__
|
||||
/* need this, because some autoconf tests rely on this (e.g. stpcpy)
|
||||
* and it should be used for new programs */
|
||||
#define _GNU_SOURCE 1
|
||||
])
|
||||
|
||||
AH_BOTTOM([
|
||||
#endif /* __CELLWIRE_CONFIG_H__ */
|
||||
])
|
||||
|
||||
AH_VERBATIM([_REENTRANT],
|
||||
[/* To allow the use of core in multithreaded programs we have to use
|
||||
special features from the library. */
|
||||
#ifndef _REENTRANT
|
||||
# define _REENTRANT 1
|
||||
#endif
|
||||
])
|
||||
|
||||
dnl Checks for programs.
|
||||
# We need a C compiler.
|
||||
AC_PROG_CC
|
||||
AC_PROG_CPP
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_AWK
|
||||
AM_PROG_AR
|
||||
AM_PROG_LIBTOOL
|
||||
|
||||
dnl Checks for pointer size
|
||||
AC_CHECK_SIZEOF(void*, 4)
|
||||
|
||||
if test "x$ac_cv_sizeof_voidp" != "x"; then
|
||||
voidp_size=$ac_cv_sizeof_voidp
|
||||
else
|
||||
AC_ERROR([Cannot determine size of void*])
|
||||
fi
|
||||
|
||||
dnl Checks for integer size
|
||||
AC_CHECK_SIZEOF(char, 1)
|
||||
AC_CHECK_SIZEOF(int, 4)
|
||||
AC_CHECK_SIZEOF(long, 4)
|
||||
AC_CHECK_SIZEOF(short, 2)
|
||||
AC_CHECK_SIZEOF(long long, 8)
|
||||
|
||||
if test "$ac_cv_sizeof_short" = "2"; then
|
||||
short_value=short
|
||||
fi
|
||||
if test "$ac_cv_sizeof_int" = "4"; then
|
||||
int_value=int
|
||||
fi
|
||||
# Now we need to find what c_int64_t (sizeof == 8) will be.
|
||||
# The first match is our preference.
|
||||
if test "$ac_cv_sizeof_int" = "8"; then
|
||||
int64_literal='#define C_INT64_C(val) (val)'
|
||||
uint64_literal='#define C_UINT64_C(val) (val##U)'
|
||||
int64_t_fmt='#define C_INT64_T_FMT "d"'
|
||||
uint64_t_fmt='#define C_UINT64_T_FMT "u"'
|
||||
uint64_t_hex_fmt='#define C_UINT64_T_HEX_FMT "x"'
|
||||
int64_value="int"
|
||||
long_value=int
|
||||
int64_strfn="strtoi"
|
||||
elif test "$ac_cv_sizeof_long" = "8"; then
|
||||
int64_literal='#define C_INT64_C(val) (val##L)'
|
||||
uint64_literal='#define C_UINT64_C(val) (val##UL)'
|
||||
int64_t_fmt='#define C_INT64_T_FMT "ld"'
|
||||
uint64_t_fmt='#define C_UINT64_T_FMT "lu"'
|
||||
uint64_t_hex_fmt='#define C_UINT64_T_HEX_FMT "lx"'
|
||||
int64_value="long"
|
||||
long_value=long
|
||||
int64_strfn="strtol"
|
||||
elif test "$ac_cv_sizeof_long_long" = "8"; then
|
||||
int64_literal='#define C_INT64_C(val) (val##LL)'
|
||||
uint64_literal='#define C_UINT64_C(val) (val##ULL)'
|
||||
# Linux, Solaris, FreeBSD all support ll with printf.
|
||||
# BSD 4.4 originated 'q'. Solaris is more popular and
|
||||
# doesn't support 'q'. Solaris wins. Exceptions can
|
||||
# go to the OS-dependent section.
|
||||
int64_t_fmt='#define C_INT64_T_FMT "lld"'
|
||||
uint64_t_fmt='#define C_UINT64_T_FMT "llu"'
|
||||
uint64_t_hex_fmt='#define C_UINT64_T_HEX_FMT "llx"'
|
||||
int64_value="long long"
|
||||
long_value="long long"
|
||||
int64_strfn="strtoll"
|
||||
elif test "$ac_cv_sizeof_longlong" = "8"; then
|
||||
int64_literal='#define C_INT64_C(val) (val##LL)'
|
||||
uint64_literal='#define C_UINT64_C(val) (val##ULL)'
|
||||
int64_t_fmt='#define C_INT64_T_FMT "qd"'
|
||||
uint64_t_fmt='#define C_UINT64_T_FMT "qu"'
|
||||
uint64_t_hex_fmt='#define C_UINT64_T_HEX_FMT "qx"'
|
||||
int64_value="__int64"
|
||||
long_value="__int64"
|
||||
int64_strfn="strtoll"
|
||||
else
|
||||
# int64_literal may be overriden if your compiler thinks you have
|
||||
# a 64-bit value but CORE does not agree.
|
||||
AC_ERROR([could not detect a 64-bit integer type])
|
||||
fi
|
||||
|
||||
AC_SUBST(voidp_size)
|
||||
AC_SUBST(short_value)
|
||||
AC_SUBST(int_value)
|
||||
AC_SUBST(long_value)
|
||||
AC_SUBST(int64_value)
|
||||
AC_SUBST(int64_t_fmt)
|
||||
AC_SUBST(uint64_t_fmt)
|
||||
AC_SUBST(uint64_t_hex_fmt)
|
||||
AC_SUBST(int64_literal)
|
||||
AC_SUBST(uint64_literal)
|
||||
|
||||
AC_DEFINE_UNQUOTED([PACKAGE_VERSION_MAJOR],
|
||||
[`echo $PACKAGE_VERSION | sed 's/^\([[^\.]]\+\)\.\([[^\.]]\+\)\.\([[^\.]]\+\).*/\1/'`],
|
||||
[Major version of this package])
|
||||
AC_DEFINE_UNQUOTED([PACKAGE_VERSION_MINOR],
|
||||
[`echo $PACKAGE_VERSION | sed 's/^\([[^\.]]\+\)\.\([[^\.]]\+\)\.\([[^\.]]\+\).*/\2/'`],
|
||||
[Minor version of this package])
|
||||
AC_DEFINE_UNQUOTED([PACKAGE_VERSION_PATCHLEVEL],
|
||||
[`echo $PACKAGE_VERSION | sed 's/^\([[^\.]]\+\)\.\([[^\.]]\+\)\.\([[^\.]]\+\).*/\3/'`],
|
||||
[Patch version of this package])
|
||||
|
||||
##################################
|
||||
#### Checks for header files. ####
|
||||
##################################
|
||||
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS( \
|
||||
arpa/inet.h \
|
||||
ctype.h \
|
||||
errno.h \
|
||||
fcntl.h \
|
||||
ifaddrs.h \
|
||||
limits.h \
|
||||
netdb.h \
|
||||
pthread.h \
|
||||
regex.h \
|
||||
semaphore.h \
|
||||
signal.h \
|
||||
stdarg.h \
|
||||
stdio.h \
|
||||
stdint.h \
|
||||
stdlib.h \
|
||||
string.h \
|
||||
strings.h \
|
||||
time.h \
|
||||
unistd.h \
|
||||
net/if_dl.h \
|
||||
netinet/ether.h \
|
||||
netinet/in.h \
|
||||
netinet/sctp.h \
|
||||
sys/ioctl.h \
|
||||
sys/param.h \
|
||||
sys/socket.h \
|
||||
sys/stat.h \
|
||||
sys/syslimits.h \
|
||||
sys/types.h \
|
||||
sys/time.h \
|
||||
sys/wait.h \
|
||||
sys/uio.h \
|
||||
)
|
||||
|
||||
##########################################
|
||||
#### Checks for typedefs, structures, ####
|
||||
#### and compiler characteristics. ####
|
||||
##########################################
|
||||
|
||||
AC_C_BIGENDIAN
|
||||
|
||||
AC_CHECK_MEMBERS([struct tm.tm_gmtoff, struct tm.__tm_gmtoff],,,[
|
||||
#include <sys/types.h>
|
||||
#include <time.h>])
|
||||
|
||||
AC_CHECK_FILE(/dev/random,
|
||||
AC_DEFINE([HAVE_DEV_RANDOM], [1],
|
||||
[Define to 1 if you have the /dev/random file.]))
|
||||
|
||||
#######################################
|
||||
#### Checks for library functions. ####
|
||||
#######################################
|
||||
|
||||
AC_FUNC_VPRINTF
|
||||
AC_CHECK_FUNCS(\
|
||||
atexit \
|
||||
gettimeofday \
|
||||
inet_ntop \
|
||||
inet_pton \
|
||||
inet_aton \
|
||||
memmove \
|
||||
sigaction \
|
||||
sigwait \
|
||||
sigsuspend \
|
||||
stpcpy \
|
||||
strcasecmp \
|
||||
strtoul \
|
||||
stricmp \
|
||||
strerror \
|
||||
writev \
|
||||
utime \
|
||||
utimes \
|
||||
sem_timedwait \
|
||||
)
|
||||
|
||||
AC_CHECK_LIB([crypt], [crypt], [OSLIBS="-lcrypt"])
|
||||
AC_SUBST(OSLIBS)
|
||||
|
||||
#####################
|
||||
#### Conclusion. ####
|
||||
#####################
|
||||
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_CONFIG_FILES([src/Makefile])
|
||||
AC_CONFIG_FILES([lib/Makefile])
|
||||
AC_CONFIG_FILES([lib/core/include/core.h])
|
||||
AC_CONFIG_FILES([lib/core/Makefile])
|
||||
AC_CONFIG_FILES([lib/core/src/Makefile])
|
||||
case $host in
|
||||
*)
|
||||
AC_CONFIG_FILES([lib/core/src/unix/Makefile])
|
||||
;;
|
||||
esac
|
||||
AC_CONFIG_FILES([lib/core/test/Makefile])
|
||||
AC_CONFIG_FILES([lib/logger/Makefile])
|
||||
AC_OUTPUT
|
||||
|
||||
echo "
|
||||
CellWire configuration
|
||||
--------------------
|
||||
version : ${PACKAGE_VERSION}
|
||||
host : ${host}
|
||||
source code location : ${srcdir}
|
||||
compiler : ${CC}
|
||||
compiler flags : ${CFLAGS}
|
||||
linker flags : ${LDFLAGS} ${LIBS}
|
||||
config file directory : `eval echo \`echo ${sysconfdir}\``
|
||||
"
|
|
@ -0,0 +1,6 @@
|
|||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
SUBDIRS = core logger
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
MOSTLYCLEANFILES = *.stackdump
|
|
@ -0,0 +1,6 @@
|
|||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
SUBDIRS = src test
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
MOSTLYCLEANFILES = core *.stackdump
|
|
@ -0,0 +1,4 @@
|
|||
#ifndef CORE_PRIVATE_COMMON_H
|
||||
#define CORE_PRIVATE_COMMON_H
|
||||
|
||||
#endif /*CORE_PRIVATE_COMMON_H*/
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef __CORE_ARCH_FILE_H__
|
||||
#define __CORE_ARCH_FILE_H__
|
||||
|
||||
#include "core.h"
|
||||
#include "core_time.h"
|
||||
#include "core_file.h"
|
||||
|
||||
#define FILE_DEFAULT_BUFSIZE 4096
|
||||
/* For backwards-compat */
|
||||
#define FILE_BUFSIZE FILE_DEFAULT_BUFSIZE
|
||||
|
||||
typedef int os_file_t; /**< native file */
|
||||
|
||||
struct file_t {
|
||||
os_file_t filedes;
|
||||
char fname[MAX_FILENAME_SIZE];
|
||||
c_int32_t flags;
|
||||
int eof_hit;
|
||||
c_time_t timeout;
|
||||
off_t filePtr; /* position in file of handle */
|
||||
};
|
||||
|
||||
typedef struct stat struct_stat;
|
||||
|
||||
mode_t unix_perms2mode(file_perms_t perms);
|
||||
file_perms_t unix_mode2perms(mode_t mode);
|
||||
|
||||
#endif /* ! __CORE_ARCH_FILE_H__ */
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef __CORE_ARCH_MUTEX_H__
|
||||
#define __CORE_ARCH_MUTEX_H__
|
||||
|
||||
#include "core.h"
|
||||
#include "core_mutex.h"
|
||||
|
||||
typedef struct _mutex_t {
|
||||
pthread_mutex_t mutex;
|
||||
} mutex_t;
|
||||
|
||||
#endif /* __CORE_ARCH_MUTEX_H__ */
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef __CORE_ARCH_SEMAPHORE_H__
|
||||
#define __CORE_ARCH_SEMAPHORE_H__
|
||||
|
||||
#include "core.h"
|
||||
#include "core_semaphore.h"
|
||||
|
||||
typedef struct _semaphore_t {
|
||||
sem_t *semaphore;
|
||||
} semaphore_t;
|
||||
|
||||
#endif /* __CORE_ARCH_SEMAPHORE_H__ */
|
||||
|
|
@ -0,0 +1,366 @@
|
|||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __CORE_H__
|
||||
#define __CORE_H__
|
||||
|
||||
/* GENERATED FILE WARNING! DO NOT EDIT core.h
|
||||
*
|
||||
* You must modify core.h.in instead.
|
||||
*
|
||||
* And please, make an effort to stub core.hw and core.hnw in the process.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file core.h
|
||||
* @brief CORE Platform Definitions
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup CORE Core Runtime library
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus) && !defined(__STDC_CONSTANT_MACROS)
|
||||
/* C99 7.18.4 requires that stdint.h only exposes INT64_C
|
||||
* and UINT64_C for C++ implementations if this is defined: */
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#endif
|
||||
|
||||
#if HAVE_CTYPE_H
|
||||
#include <ctype.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_NET_IF_H_
|
||||
#include <net/if.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_PTHREAD_H
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_SEMAPHORE_H
|
||||
#include <semaphore.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_STDARG_H
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_STDIO_H
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_STRINGS_H
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_TIME_H
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_NET_IF_DL_H
|
||||
#include <net/if_dl.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_NETINET_ETHER_H
|
||||
#include <netinet/ether.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_NETINET_SCTP_H
|
||||
#include <netinet/sctp.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_SYS_IOCTL_H
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_SYS_WAIT_H
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
/* header files for PATH_MAX, _POSIX_PATH_MAX */
|
||||
#if HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#else
|
||||
#if HAVE_SYS_SYSLIMITS_H
|
||||
#include <sys/syslimits.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAVE_SYS_UIO_H
|
||||
#include <sys/uio.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Typedefs that CORE needs. */
|
||||
|
||||
typedef char c_int8_t;
|
||||
typedef unsigned char c_uint8_t;
|
||||
|
||||
typedef @short_value@ c_int16_t;
|
||||
typedef unsigned @short_value@ c_uint16_t;
|
||||
|
||||
typedef @int_value@ c_int32_t;
|
||||
typedef unsigned @int_value@ c_uint32_t;
|
||||
|
||||
#define C_SIZEOF_VOIDP @voidp_size@
|
||||
|
||||
typedef @long_value@ c_int64_t;
|
||||
typedef unsigned @long_value@ c_uint64_t;
|
||||
|
||||
#if C_SIZEOF_VOIDP == 8
|
||||
typedef c_uint64_t c_uintptr_t;
|
||||
typedef c_int64_t c_intptr_t;
|
||||
#else
|
||||
typedef c_uint32_t c_uintptr_t;
|
||||
typedef c_int32_t c_intptr_t;
|
||||
#endif
|
||||
|
||||
/* Mechanisms to properly type numeric literals */
|
||||
@int64_literal@
|
||||
@uint64_literal@
|
||||
|
||||
@int64_t_fmt@
|
||||
@uint64_t_fmt@
|
||||
@uint64_t_hex_fmt@
|
||||
|
||||
#ifdef INT16_MIN
|
||||
#define C_INT16_MIN INT16_MIN
|
||||
#else
|
||||
#define C_INT16_MIN (-0x7fff - 1)
|
||||
#endif
|
||||
|
||||
#ifdef INT16_MAX
|
||||
#define C_INT16_MAX INT16_MAX
|
||||
#else
|
||||
#define C_INT16_MAX (0x7fff)
|
||||
#endif
|
||||
|
||||
#ifdef UINT16_MAX
|
||||
#define C_UINT16_MAX UINT16_MAX
|
||||
#else
|
||||
#define C_UINT16_MAX (0xffff)
|
||||
#endif
|
||||
|
||||
#ifdef INT32_MIN
|
||||
#define C_INT32_MIN INT32_MIN
|
||||
#else
|
||||
#define C_INT32_MIN (-0x7fffffff - 1)
|
||||
#endif
|
||||
|
||||
#ifdef INT32_MAX
|
||||
#define C_INT32_MAX INT32_MAX
|
||||
#else
|
||||
#define C_INT32_MAX 0x7fffffff
|
||||
#endif
|
||||
|
||||
#ifdef UINT32_MAX
|
||||
#define C_UINT32_MAX UINT32_MAX
|
||||
#else
|
||||
#define C_UINT32_MAX (0xffffffffU)
|
||||
#endif
|
||||
|
||||
#ifdef INT64_MIN
|
||||
#define C_INT64_MIN INT64_MIN
|
||||
#else
|
||||
#define C_INT64_MIN (C_INT64_C(-0x7fffffffffffffff) - 1)
|
||||
#endif
|
||||
|
||||
#ifdef INT64_MAX
|
||||
#define C_INT64_MAX INT64_MAX
|
||||
#else
|
||||
#define C_INT64_MAX C_INT64_C(0x7fffffffffffffff)
|
||||
#endif
|
||||
|
||||
#ifdef UINT64_MAX
|
||||
#define C_UINT64_MAX UINT64_MAX
|
||||
#else
|
||||
#define C_UINT64_MAX C_UINT64_C(0xffffffffffffffff)
|
||||
#endif
|
||||
|
||||
/* Definitions that CORE programs need to work properly. */
|
||||
|
||||
/**
|
||||
* Thread callbacks from CORE functions must be declared with THREAD_FUNC,
|
||||
* so that they follow the platform's calling convention.
|
||||
* <PRE>
|
||||
*
|
||||
* void* THREAD_FUNC my_thread_entry_fn(core_thread_t *thd, void *data);
|
||||
*
|
||||
* </PRE>
|
||||
*/
|
||||
#define THREAD_FUNC
|
||||
|
||||
/**
|
||||
* The public CORE functions are declared with CORE_DECLARE(), so they may
|
||||
* use the most appropriate calling convention. Public CORE functions with
|
||||
* variable arguments must use CORE_DECLARE_NONSTD().
|
||||
*
|
||||
* @remark Both the declaration and implementations must use the same macro.
|
||||
*
|
||||
* <PRE>
|
||||
* CORE_DECLARE(rettype) core_func(args)
|
||||
* </PRE>
|
||||
* @see CORE_DECLARE_NONSTD @see CORE_DECLARE_DATA
|
||||
* @remark Note that when CORE compiles the library itself, it passes the
|
||||
* symbol -DCORE_DECLARE_EXPORT to the compiler on some platforms (e.g. Win32)
|
||||
* to export public symbols from the dynamic library build.\n
|
||||
* The user must define the CORE_DECLARE_STATIC when compiling to target
|
||||
* the static CORE library on some platforms (e.g. Win32.) The public symbols
|
||||
* are neither exported nor imported when CORE_DECLARE_STATIC is defined.\n
|
||||
* By default, compiling an application and including the CORE public
|
||||
* headers, without defining CORE_DECLARE_STATIC, will prepare the code to be
|
||||
* linked to the dynamic library.
|
||||
*/
|
||||
#define CORE_DECLARE(type) type
|
||||
|
||||
/**
|
||||
* The public CORE functions using variable arguments are declared with
|
||||
* CORE_DECLARE_NONSTD(), as they must follow the C language calling convention.
|
||||
* @see CORE_DECLARE @see CORE_DECLARE_DATA
|
||||
* @remark Both the declaration and implementations must use the same macro.
|
||||
* <PRE>
|
||||
*
|
||||
* CORE_DECLARE_NONSTD(rettype) core_func(args, ...);
|
||||
*
|
||||
* </PRE>
|
||||
*/
|
||||
#define CORE_DECLARE_NONSTD(type) type
|
||||
|
||||
/**
|
||||
* The public CORE variables are declared with CORE_DECLARE_DATA.
|
||||
* This assures the appropriate indirection is invoked at compile time.
|
||||
* @see CORE_DECLARE @see CORE_DECLARE_NONSTD
|
||||
* @remark Note that the declaration and implementations use different forms,
|
||||
* but both must include the macro.
|
||||
*
|
||||
* <PRE>
|
||||
*
|
||||
* extern CORE_DECLARE_DATA type core_variable;\n
|
||||
* CORE_DECLARE_DATA type core_variable = value;
|
||||
*
|
||||
* </PRE>
|
||||
*/
|
||||
#define CORE_DECLARE_DATA
|
||||
|
||||
#if defined(PATH_MAX)
|
||||
#define C_PATH_MAX PATH_MAX
|
||||
#elif defined(_POSIX_PATH_MAX)
|
||||
#define C_PATH_MAX _POSIX_PATH_MAX
|
||||
#else
|
||||
#error no decision has been made on C_PATH_MAX for your platform
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
/* Definitions that only Win32 programs need to compile properly. */
|
||||
|
||||
#if WORDS_BIGENDIAN
|
||||
#define ED2(x1, x2) x1 x2
|
||||
#define ED3(x1, x2, x3) x1 x2 x3
|
||||
#define ED4(x1, x2, x3, x4) x1 x2 x3 x4
|
||||
#define ED5(x1, x2, x3, x4, x5) x1 x2 x3 x4 x5
|
||||
#define ED6(x1, x2, x3, x4, x5, x6) x1 x2 x3 x4 x5 x6
|
||||
#define ED7(x1, x2, x3, x4, x5, x6, x7) x1 x2 x3 x4 x5 x6 x7
|
||||
#define ED8(x1, x2, x3, x4, x5, x6, x7, x8) x1 x2 x3 x4 x5 x6 x7 x8
|
||||
#else
|
||||
#define ED2(x1, x2) x2 x1
|
||||
#define ED3(x1, x2, x3) x3 x2 x1
|
||||
#define ED4(x1, x2, x3, x4) x4 x3 x2 x1
|
||||
#define ED5(x1, x2, x3, x4, x5) x5 x4 x3 x2 x1
|
||||
#define ED6(x1, x2, x3, x4, x5, x6) x6 x5 x4 x3 x2 x1
|
||||
#define ED7(x1, x2, x3, x4, x5, x6, x7) x7 x6 x5 x4 x3 x2 x1
|
||||
#define ED8(x1, x2, x3, x4, x5, x6, x7, x8) x8 x7 x6 x5 x4 x3 x2 x1
|
||||
#endif
|
||||
|
||||
/** FALSE */
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
/** TRUE */
|
||||
#ifndef TRUE
|
||||
#define TRUE (!FALSE)
|
||||
#endif
|
||||
|
||||
/* CORE_ALIGN() is only to be used to align on a power of 2 boundary */
|
||||
#define CORE_ALIGN(size, boundary) \
|
||||
(((size) + ((boundary) - 1)) & ~((boundary) - 1))
|
||||
|
||||
/** Default alignment */
|
||||
#define CORE_ALIGN_DEFAULT(size) CORE_ALIGN(size, 4)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CORE_H */
|
|
@ -0,0 +1,42 @@
|
|||
#ifndef _CORE_AES_H__
|
||||
#define _CORE_AES_H__
|
||||
|
||||
#include "core.h"
|
||||
#include "core_errno.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#define AES_BLOCK_SIZE 16
|
||||
#define MAX_KEY_BITS 256
|
||||
|
||||
#define KEYLENGTH(keybits) ((keybits)/8)
|
||||
#define RKLENGTH(keybits) ((keybits)/8+28)
|
||||
#define NROUNDS(keybits) ((keybits)/32+6)
|
||||
|
||||
CORE_DECLARE(int) aes_setup_enc(c_uint32_t *rk, const c_uint8_t *key,
|
||||
int keybits);
|
||||
CORE_DECLARE(int) aes_setup_dec(c_uint32_t *rk, const c_uint8_t *key,
|
||||
int keybits);
|
||||
|
||||
CORE_DECLARE(void) aes_encrypt(const c_uint32_t *rk, int nrounds,
|
||||
const c_uint8_t plaintext[16], c_uint8_t ciphertext[16]);
|
||||
CORE_DECLARE(void) aes_decrypt(const c_uint32_t *rk, int nrounds,
|
||||
const c_uint8_t ciphertext[16], c_uint8_t plaintext[16]);
|
||||
|
||||
CORE_DECLARE(status_t) aes_cbc_encrypt(const c_uint8_t *key,
|
||||
const c_uint32_t keybits, c_uint8_t *ivec,
|
||||
const c_uint8_t *in, const c_uint32_t inlen,
|
||||
c_uint8_t *out, c_uint32_t *outlen);
|
||||
CORE_DECLARE(status_t) aes_cbc_decrypt(const c_uint8_t *key,
|
||||
const c_uint32_t keybits, c_uint8_t *ivec,
|
||||
const c_uint8_t *in, const c_uint32_t inlen,
|
||||
c_uint8_t *out, c_uint32_t *outlen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
#ifndef _CORE_AES_CMAC_H
|
||||
#define _CORE_AES_CMAC_H
|
||||
|
||||
#include "core_aes.h"
|
||||
|
||||
#define AES_CMAC_DIGEST_LEN 16
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Caculate CMAC value
|
||||
*
|
||||
* @param cmac
|
||||
* @param key
|
||||
* @param msg
|
||||
* @param len
|
||||
*
|
||||
* @return CORE_OK
|
||||
* CORE_ERROR
|
||||
*/
|
||||
CORE_DECLARE(status_t) aes_cmac_calculate(c_uint8_t *cmac, const c_uint8_t *key,
|
||||
const c_uint8_t *msg, const c_uint32_t len);
|
||||
|
||||
/**
|
||||
* Verify CMAC value
|
||||
*
|
||||
* @param cmac
|
||||
* @param key
|
||||
* @param msg
|
||||
* @param len
|
||||
*
|
||||
* @return CORE_OK
|
||||
* CORE_ERROR
|
||||
* ERR_INVALID_CMAC
|
||||
*/
|
||||
#define ERR_INVALID_CMAC -2
|
||||
CORE_DECLARE(status_t) aes_cmac_verify(c_uint8_t *cmac, const c_uint8_t *key,
|
||||
const c_uint8_t *msg, const c_uint32_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ! _CORE_AES_CMAC_H */
|
|
@ -0,0 +1,118 @@
|
|||
#ifndef __CORE_COND_H__
|
||||
#define __CORE_COND_H__
|
||||
|
||||
/**
|
||||
* @file cond.h
|
||||
* @brief CORE Condition Variable Routines
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "core_errno.h"
|
||||
#include "core_time.h"
|
||||
#include "core_mutex.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @defgroup cond Condition Variable Routines
|
||||
* @ingroup CORE
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Opaque structure for thread condition variables */
|
||||
typedef c_uintptr_t cond_id;
|
||||
|
||||
/**
|
||||
* Initialize Conditional Pool
|
||||
*/
|
||||
CORE_DECLARE(status_t) cond_init(void);
|
||||
|
||||
/**
|
||||
* Finalize Conditional Pool
|
||||
*/
|
||||
CORE_DECLARE(status_t) cond_final(void);
|
||||
|
||||
/**
|
||||
* Note: destroying a condition variable (or likewise, destroying or
|
||||
* clearing the pool from which a condition variable was allocated) if
|
||||
* any threads are blocked waiting on it gives undefined results.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create and initialize a condition variable that can be used to signal
|
||||
* and schedule threads in a single process.
|
||||
* @param id the memory address where the newly created condition variable
|
||||
* will be stored.
|
||||
*/
|
||||
CORE_DECLARE(status_t) cond_create(cond_id *id);
|
||||
|
||||
/**
|
||||
* Put the active calling thread to sleep until signaled to wake up. Each
|
||||
* condition variable must be associated with a mutex, and that mutex must
|
||||
* be locked before calling this function, or the behavior will be
|
||||
* undefined. As the calling thread is put to sleep, the given mutex
|
||||
* will be simultaneously released; and as this thread wakes up the lock
|
||||
* is again simultaneously acquired.
|
||||
* @param id the condition variable on which to block.
|
||||
* @param mid the mutex that must be locked upon entering this function,
|
||||
* is released while the thread is asleep, and is again acquired before
|
||||
* returning from this function.
|
||||
* @remark Spurious wakeups may occur. Before and after every call to wait on
|
||||
* a condition variable, the caller should test whether the condition is already
|
||||
* met.
|
||||
*/
|
||||
CORE_DECLARE(status_t) cond_wait(cond_id id, mutex_id mid);
|
||||
|
||||
/**
|
||||
* Put the active calling thread to sleep until signaled to wake up or
|
||||
* the timeout is reached. Each condition variable must be associated
|
||||
* with a mutex, and that mutex must be locked before calling this
|
||||
* function, or the behavior will be undefined. As the calling thread
|
||||
* is put to sleep, the given mutex will be simultaneously released;
|
||||
* and as this thread wakes up the lock is again simultaneously acquired.
|
||||
* @param id the condition variable on which to block.
|
||||
* @param mid the mutex that must be locked upon entering this function,
|
||||
* is released while the thread is asleep, and is again acquired before
|
||||
* returning from this function.
|
||||
* @param timeout The amount of time in microseconds to wait. This is
|
||||
* a maximum, not a minimum. If the condition is signaled, we
|
||||
* will wake up before this time, otherwise the error CORE_TIMEUP
|
||||
* is returned.
|
||||
*/
|
||||
CORE_DECLARE(status_t) cond_timedwait(
|
||||
cond_id id, mutex_id mid, c_time_t timeout);
|
||||
|
||||
/**
|
||||
* Signals a single thread, if one exists, that is blocking on the given
|
||||
* condition variable. That thread is then scheduled to wake up and acquire
|
||||
* the associated mutex. Although it is not required, if predictable scheduling
|
||||
* is desired, that mutex must be locked while calling this function.
|
||||
* @param id the condition variable on which to produce the signal.
|
||||
* @remark If no threads are waiting on the condition variable, nothing happens.
|
||||
*/
|
||||
CORE_DECLARE(status_t) cond_signal(cond_id id);
|
||||
|
||||
/**
|
||||
* Signals all threads blocking on the given condition variable.
|
||||
* Each thread that was signaled is then scheduled to wake up and acquire
|
||||
* the associated mutex. This will happen in a serialized manner.
|
||||
* @param id the condition variable on which to produce the broadcast.
|
||||
* @remark If no threads are waiting on the condition variable, nothing happens.
|
||||
*/
|
||||
CORE_DECLARE(status_t) cond_broadcast(cond_id id);
|
||||
|
||||
/**
|
||||
* Destroy the condition variable and free the associated memory.
|
||||
* @param id the condition variable to destroy.
|
||||
*/
|
||||
CORE_DECLARE(status_t) cond_delete(cond_id id);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* ! __CORE_COND_H__ */
|
|
@ -0,0 +1,226 @@
|
|||
#ifndef __CORE_DEBUG_H__
|
||||
#define __CORE_DEBUG_H__
|
||||
|
||||
#include "core.h"
|
||||
#include "core_time.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifdef TRACE_MODULE
|
||||
int TRACE_MODULE;
|
||||
#endif
|
||||
|
||||
extern int g_trace_mask;
|
||||
|
||||
#define trace_level_set(__level) (TRACE_MODULE = __level);
|
||||
|
||||
#define D_MSG_TYPE_NONE 0
|
||||
#define D_MSG_TYPE_RAW 1
|
||||
#define D_MSG_TYPE_TRACE 2
|
||||
#define D_MSG_TYPE_LOG 3
|
||||
#define D_MSG_TYPE_ASSERT 4
|
||||
|
||||
#define D_MSG_TO_CONSOLE 0x00000001
|
||||
#define D_MSG_TO_STDOUT 0x00000002
|
||||
#define D_MSG_TO_SYSLOG 0x00000004
|
||||
#define D_MSG_TO_LOGD 0x00000008
|
||||
#define D_MSG_TO_ALL (D_MSG_TO_CONSOLE | D_MSG_TO_STDOUT | \
|
||||
D_MSG_TO_SYSLOG | D_MSG_TO_LOGD)
|
||||
|
||||
#define D_LOG_LEVEL_NONE 0
|
||||
#define D_LOG_LEVEL_FATAL 1
|
||||
#define D_LOG_LEVEL_ERROR 2
|
||||
#define D_LOG_LEVEL_WARN 3
|
||||
#define D_LOG_LEVEL_INFO 4
|
||||
#define D_LOG_LEVEL_FULL D_LOG_LEVEL_INFO
|
||||
|
||||
CORE_DECLARE(int) d_msg(int tp, int lv, c_time_t t, char *fn, int ln,
|
||||
char *fmt, ...);
|
||||
|
||||
/* if C99 supported */
|
||||
#if (defined _ISOC99_SOURCE || defined _ISOC9X_SOURCE \
|
||||
|| (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L))
|
||||
|
||||
/**
|
||||
* Use for printing message. This always print out the message.
|
||||
*/
|
||||
#define d_print(fmt, ...) \
|
||||
d_msg(D_MSG_TYPE_RAW, 0, 0, NULL, 0, fmt, ## __VA_ARGS__)
|
||||
|
||||
#define __MAX_HEX_BUF 128
|
||||
|
||||
/**
|
||||
* Use for printing binary buffer as printable hex string. This always
|
||||
* print out the message.
|
||||
*/
|
||||
#define d_print_hex(__buf, __buflen) do { \
|
||||
int __i = 0, __l, __off = 0; \
|
||||
char __hex[__MAX_HEX_BUF*2+__MAX_HEX_BUF/4+__MAX_HEX_BUF/32+4], *__p; \
|
||||
d_print("%d bytes hex:\r\n", __buflen); \
|
||||
while (__off < (__buflen)) { \
|
||||
__p = __hex; __p[0] = 0; \
|
||||
__l = ((__buflen) - __off) > __MAX_HEX_BUF ? \
|
||||
__MAX_HEX_BUF : (__buflen) - __off; \
|
||||
for (__i = 0; __i < __l; __i++) { \
|
||||
__p += sprintf(__p, "%02x", ((char*)(__buf))[__off+__i] & 0xff); \
|
||||
if ((__i & 0x1f) == 31) \
|
||||
__p += sprintf(__p, "\r\n"); \
|
||||
else if ((__i & 0x3) == 3) \
|
||||
__p += sprintf(__p, " "); \
|
||||
} \
|
||||
__off += __l; \
|
||||
d_print(__hex); \
|
||||
} \
|
||||
if (__i & 0x1f) d_print("\r\n"); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Use for trace.
|
||||
* Trace message shall be shown only if trace level is set equal or higher
|
||||
* than __level.
|
||||
*/
|
||||
#define d_trace(__level, fmt, ...) \
|
||||
(!g_trace_mask || TRACE_MODULE < __level ? 0 : \
|
||||
d_msg(D_MSG_TYPE_TRACE, 0, time_now(), NULL, 0, fmt, ## __VA_ARGS__))
|
||||
|
||||
/**
|
||||
* Use for trace binary buffer as printable hex string .
|
||||
* Trace message shall be shown only if trace level is set equal or higher
|
||||
* than __level.
|
||||
*/
|
||||
#define d_trace_hex(__level, __buf, __buflen) do { \
|
||||
if (g_trace_mask && TRACE_MODULE >= __level) \
|
||||
d_print_hex(__buf, __buflen); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Informative log.
|
||||
* If log level is larger than 4,
|
||||
* this message is logged with informative format.
|
||||
*/
|
||||
#define d_info(fmt, ...) \
|
||||
d_msg(D_MSG_TYPE_LOG, D_LOG_LEVEL_INFO, time_now(), \
|
||||
__FILE__, __LINE__, fmt, ## __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Informative log.
|
||||
* If log level is larger than 3,
|
||||
* this message is logged with warning format.
|
||||
*/
|
||||
#define d_warn(fmt, ...) \
|
||||
d_msg(D_MSG_TYPE_LOG, D_LOG_LEVEL_WARN, time_now(), \
|
||||
__FILE__, __LINE__, fmt, ## __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Error log.
|
||||
* If log level is larger than 2,
|
||||
* this message is logged with error format.
|
||||
*/
|
||||
#define d_error(fmt, ...) \
|
||||
d_msg(D_MSG_TYPE_LOG, D_LOG_LEVEL_ERROR, time_now(), \
|
||||
__FILE__, __LINE__, fmt, ## __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Fatal error log.
|
||||
* If log level is larger than 1,
|
||||
* this message is logged with fatal error format.
|
||||
*/
|
||||
#define d_fatal(fmt, ...) \
|
||||
d_msg(D_MSG_TYPE_LOG, D_LOG_LEVEL_FATAL, time_now(), \
|
||||
__FILE__, __LINE__, fmt, ## __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Assertion
|
||||
* this message is logged with assertion format.
|
||||
*/
|
||||
#define d_assert(cond, expr, fmt, ...) \
|
||||
if (!(cond)) { \
|
||||
d_msg(D_MSG_TYPE_ASSERT, 0, time_now(), __FILE__, __LINE__, \
|
||||
"!("#cond"). "fmt, ## __VA_ARGS__); \
|
||||
expr; \
|
||||
}
|
||||
|
||||
#else /* C99 */
|
||||
|
||||
#define d_print
|
||||
|
||||
#define d_trace
|
||||
|
||||
#define d_info
|
||||
#define d_warn
|
||||
#define d_error
|
||||
#define d_fatal
|
||||
|
||||
#define d_assert
|
||||
|
||||
#endif /* C99 */
|
||||
|
||||
void d_msg_init();
|
||||
|
||||
void d_msg_final();
|
||||
|
||||
void d_msg_register_console(int console_fd);
|
||||
|
||||
void d_msg_deregister_console();
|
||||
|
||||
void d_msg_to(int to, int on_off);
|
||||
|
||||
int d_msg_get_to();
|
||||
|
||||
/**
|
||||
* Turn on log partially.
|
||||
* level 4: d_fatal, d_error, d_warn, d_info
|
||||
* level 3: d_fatal, d_error, d_warn
|
||||
* level 2: d_fatal, d_error
|
||||
* level 1: d_fatal
|
||||
* level 0: none
|
||||
*/
|
||||
void d_log_set_level(int to, int level);
|
||||
|
||||
int d_log_get_level(int to);
|
||||
|
||||
/**
|
||||
* Turn on log fully.
|
||||
* All of d_info, d_warn, d_error and d_fatal will be shown.
|
||||
* Equivalent to log_level(4).
|
||||
*/
|
||||
void d_log_full(int to);
|
||||
|
||||
/**
|
||||
* Turn off log fully.
|
||||
* All log will not be shown.
|
||||
* Equivalent to log_level(0).
|
||||
*/
|
||||
void d_log_off(int to);
|
||||
|
||||
/**
|
||||
* Turn on trace mask globally.
|
||||
*/
|
||||
void d_trace_global_on();
|
||||
|
||||
/**
|
||||
* Turn off trace mask globally.
|
||||
* Any trace of any module will not be shown although some trace module is
|
||||
* turned on.
|
||||
*/
|
||||
void d_trace_global_off();
|
||||
|
||||
/**
|
||||
* Turn on trace of specifed module with level. */
|
||||
void d_trace_level(int *mod_name, int level);
|
||||
|
||||
/**
|
||||
* Turn off trace of specifed module.
|
||||
* Equivalent to trace_level(0).
|
||||
*/
|
||||
void d_trace_off(int *mod_name);
|
||||
|
||||
#define D_LOGD_IPC_PATH "/tmp/dlogmesg"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* ! __CORE_DEBUG_H__ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,652 @@
|
|||
#ifndef __CORE_FILE_H__
|
||||
#define __CORE_FILE_H__
|
||||
|
||||
/**
|
||||
* @file core_file.h
|
||||
* @brief CORE File I/O Handling
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "core_time.h"
|
||||
#include "core_errno.h"
|
||||
#include "core_param.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @defgroup file_io File I/O Handling Functions
|
||||
* @ingroup CORE
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** filetype_e values for the filetype member of the
|
||||
* file_info_t structure
|
||||
* @warning: Not all of the filetypes below can be determined.
|
||||
* For example, a given platform might not correctly report
|
||||
* a socket descriptor as CORE_SOCK if that type isn't
|
||||
* well-identified on that platform. In such cases where
|
||||
* a filetype exists but cannot be described by the recognized
|
||||
* flags below, the filetype will be CORE_UNKFILE. If the
|
||||
* filetype member is not determined, the type will be CORE_NOFILE.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
FILE_NOFILE = 0, /**< no file type determined */
|
||||
FILE_REG, /**< a regular file */
|
||||
FILE_DIR, /**< a directory */
|
||||
FILE_CHR, /**< a character device */
|
||||
FILE_BLK, /**< a block device */
|
||||
FILE_PIPE, /**< a FIFO / pipe */
|
||||
FILE_LNK, /**< a symbolic link */
|
||||
FILE_SOCK, /**< a [unix domain] socket */
|
||||
FILE_UNKFILE = 127 /**< a file of some other unknown type */
|
||||
} filetype_e;
|
||||
|
||||
/**
|
||||
* @defgroup file_permissions File Permissions flags
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define FILE_USETID 0x8000 /**< Set user id */
|
||||
#define FILE_UREAD 0x0400 /**< Read by user */
|
||||
#define FILE_UWRITE 0x0200 /**< Write by user */
|
||||
#define FILE_UEXECUTE 0x0100 /**< Execute by user */
|
||||
|
||||
#define FILE_GSETID 0x4000 /**< Set group id */
|
||||
#define FILE_GREAD 0x0040 /**< Read by group */
|
||||
#define FILE_GWRITE 0x0020 /**< Write by group */
|
||||
#define FILE_GEXECUTE 0x0010 /**< Execute by group */
|
||||
|
||||
#define FILE_WSTICKY 0x2000 /**< Sticky bit */
|
||||
#define FILE_WREAD 0x0004 /**< Read by others */
|
||||
#define FILE_WWRITE 0x0002 /**< Write by others */
|
||||
#define FILE_WEXECUTE 0x0001 /**< Execute by others */
|
||||
|
||||
#define FILE_OS_DEFAULT 0x0FFF /**< use OS's default permissions */
|
||||
|
||||
/* additional permission flags for file_copy and file_append */
|
||||
#define FILE_SOURCE_PERMS 0x1000 /**< Copy source file's permissions */
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @defgroup file_open_flags File Open Flags/Routines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Note to implementors: Values in the range 0x00100000--0x80000000
|
||||
are reserved for platform-specific values. */
|
||||
|
||||
#define FILE_READ 0x00001 /**< Open the file for reading */
|
||||
#define FILE_WRITE 0x00002 /**< Open the file for writing */
|
||||
#define FILE_CREATE 0x00004 /**< Create the file if not there */
|
||||
#define FILE_APPEND 0x00008 /**< Append to the end of the file */
|
||||
#define FILE_TRUNCATE 0x00010 /**< Open the file and truncate
|
||||
to 0 length */
|
||||
#define FILE_BINARY 0x00020 /**< Open the file in binary mode */
|
||||
#define FILE_EXCL 0x00040 /**< Open should fail if FILE_CREATE
|
||||
and file exists. */
|
||||
#define FILE_DELONCLOSE 0x00100 /**< Delete the file after close */
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @defgroup file_seek_flags File Seek Flags
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* flags for file_seek */
|
||||
/** Set the file position */
|
||||
#define FILE_SET SEEK_SET
|
||||
/** Current */
|
||||
#define FILE_CUR SEEK_CUR
|
||||
/** Go to end of file */
|
||||
#define FILE_END SEEK_END
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @defgroup file_attrs_set_flags File Attribute Flags
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* flags for file_attrs_set */
|
||||
#define ATTR_READONLY 0x01 /**< File is read-only */
|
||||
#define ATTR_EXECUTABLE 0x02 /**< File is executable */
|
||||
#define ATTR_HIDDEN 0x04 /**< File is hidden */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @defgroup file_writev{_full} max iovec size
|
||||
* @{
|
||||
*/
|
||||
#if defined(DOXYGEN)
|
||||
#define MAX_IOVEC_SIZE 1024 /**< System dependent maximum
|
||||
size of an iovec array */
|
||||
#elif defined(IOV_MAX)
|
||||
#define MAX_IOVEC_SIZE IOV_MAX
|
||||
#elif defined(MAX_IOVEC)
|
||||
#define MAX_IOVEC_SIZE MAX_IOVEC
|
||||
#else
|
||||
#define MAX_IOVEC_SIZE 1024
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/** File attributes */
|
||||
typedef c_uint32_t file_attrs_t;
|
||||
|
||||
/** Type to pass as whence argument to file_seek. */
|
||||
typedef int seek_where_t;
|
||||
|
||||
/**
|
||||
* Structure for referencing files.
|
||||
*/
|
||||
typedef struct file_t file_t;
|
||||
|
||||
/**
|
||||
* Structure for referencing directories.
|
||||
*/
|
||||
typedef struct dir_t dir_t;
|
||||
/**
|
||||
* Structure for determining file permissions.
|
||||
*/
|
||||
typedef c_int32_t file_perms_t;
|
||||
#if (defined WIN32) || (defined NETWARE)
|
||||
/**
|
||||
* Structure for determining the device the file is on.
|
||||
*/
|
||||
typedef c_uint32_t dev_t;
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @defgroup file_stat Stat Functions
|
||||
* @{
|
||||
*/
|
||||
/** file info structure */
|
||||
typedef struct file_info_t file_info_t;
|
||||
|
||||
#define FILE_INFO_LINK 0x00000001 /**< Stat the link not the file itself
|
||||
if it is a link */
|
||||
#define FILE_INFO_MTIME 0x00000010 /**< Modification Time */
|
||||
#define FILE_INFO_CTIME 0x00000020 /**< Creation or inode-changed time */
|
||||
#define FILE_INFO_ATIME 0x00000040 /**< Access Time */
|
||||
#define FILE_INFO_SIZE 0x00000100 /**< Size of the file */
|
||||
#define FILE_INFO_CSIZE 0x00000200 /**< Storage size consumed by the file */
|
||||
#define FILE_INFO_DEV 0x00001000 /**< Device */
|
||||
#define FILE_INFO_INODE 0x00002000 /**< Inode */
|
||||
#define FILE_INFO_NLINK 0x00004000 /**< Number of links */
|
||||
#define FILE_INFO_TYPE 0x00008000 /**< Type */
|
||||
#define FILE_INFO_USER 0x00010000 /**< User */
|
||||
#define FILE_INFO_GROUP 0x00020000 /**< Group */
|
||||
#define FILE_INFO_UPROT 0x00100000 /**< User protection bits */
|
||||
#define FILE_INFO_GPROT 0x00200000 /**< Group protection bits */
|
||||
#define FILE_INFO_WPROT 0x00400000 /**< World protection bits */
|
||||
#define FILE_INFO_ICASE 0x01000000 /**< if dev is case insensitive */
|
||||
#define FILE_INFO_NAME 0x02000000 /**< ->name in proper case */
|
||||
|
||||
#define FILE_INFO_MIN 0x00008170 /**< type, mtime, ctime, atime, size */
|
||||
#define FILE_INFO_IDENT 0x00003000 /**< dev and inode */
|
||||
#define FILE_INFO_OWNER 0x00030000 /**< user and group */
|
||||
#define FILE_INFO_PROT 0x00700000 /**< all protections */
|
||||
#define FILE_INFO_NORM 0x0073b170 /**< an atomic unix file_stat() */
|
||||
#define FILE_INFO_DIRENT 0x02000000 /**< an atomic unix dir_read() */
|
||||
|
||||
/**
|
||||
* The file information structure. This is analogous to the POSIX
|
||||
* stat structure.
|
||||
*/
|
||||
struct file_info_t {
|
||||
/** The bitmask describing valid fields of this c_file_info_t structure
|
||||
* including all available 'wanted' fields and potentially more */
|
||||
c_int32_t valid;
|
||||
/** The access permissions of the file. Mimics Unix access rights. */
|
||||
file_perms_t protection;
|
||||
/** The type of file. One of CORE_REG, CORE_DIR, CORE_CHR, CORE_BLK,
|
||||
CORE_PIPE, CORE_LNK or CORE_SOCK. If the type is undetermined,
|
||||
the value is CORE_NOFILE.
|
||||
* If the type cannot be determined, the value is CORE_UNKFILE.
|
||||
*/
|
||||
filetype_e filetype;
|
||||
/** The user id that owns the file */
|
||||
uid_t user;
|
||||
/** The group id that owns the file */
|
||||
gid_t group;
|
||||
/** The inode of the file. */
|
||||
ino_t inode;
|
||||
/** The id of the device the file is on. */
|
||||
dev_t device;
|
||||
/** The number of hard links to the file. */
|
||||
c_int32_t nlink;
|
||||
/** The size of the file */
|
||||
off_t size;
|
||||
/** The storage size consumed by the file */
|
||||
off_t csize;
|
||||
/** The time the file was last accessed */
|
||||
c_time_t atime;
|
||||
/** The time the file was last modified */
|
||||
c_time_t mtime;
|
||||
/** The time the file was created, or the inode was last changed */
|
||||
c_time_t ctime;
|
||||
/** The pathname of the file (possibly unrooted) */
|
||||
char fname[MAX_FILENAME_SIZE];
|
||||
/** The file's name (no path) in filesystem case */
|
||||
char name[MAX_FILENAME_SIZE];
|
||||
/** The file's handle, if accessed (can be submitted to c_duphandle) */
|
||||
struct c_file_t *filehand;
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* Initialize the file utility.
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_init(void);
|
||||
|
||||
/**
|
||||
* Finalize the file utility.
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_final(void);
|
||||
|
||||
/**
|
||||
* Open the specified file.
|
||||
* @param newf The opened file descriptor.
|
||||
* @param fname The full path to the file (using / on all systems)
|
||||
* @param flag Or'ed value of:
|
||||
* <PRE>
|
||||
* FILE_READ open for reading
|
||||
* FILE_WRITE open for writing
|
||||
* FILE_CREATE create the file if not there
|
||||
* FILE_APPEND file ptr is set to end prior to all writes
|
||||
* FILE_TRUNCATE set length to zero if file exists
|
||||
* FILE_BINARY not a text file (This flag is ignored on
|
||||
* UNIX because it has no meaning)
|
||||
* FILE_EXCL return error if FILE_CREATE and file exists
|
||||
* FILE_DELONCLOSE delete the file after closing.
|
||||
* </PRE>
|
||||
* @param perm Access permissions for file.
|
||||
* @remark If perm is FILE_OS_DEFAULT and the file is being created,
|
||||
* appropriate default permissions will be used.
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_open(file_t **newf,
|
||||
const char *fname, c_int32_t flag, file_perms_t perm);
|
||||
|
||||
/**
|
||||
* Close the specified file.
|
||||
* @param file The file descriptor to close.
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_close(file_t *file);
|
||||
|
||||
/**
|
||||
* Delete the specified file.
|
||||
* @param path The full path to the file (using / on all systems)
|
||||
* @remark If the file is open, it won't be removed until all
|
||||
* instances are closed.
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_remove(const char *path);
|
||||
|
||||
/**
|
||||
* Rename the specified file.
|
||||
* @param from_path The full path to the original file (using / on all systems)
|
||||
* @param to_path The full path to the new file (using / on all systems)
|
||||
* @warning If a file exists at the new location, then it will be
|
||||
* overwritten. Moving files or directories across devices may not be
|
||||
* possible.
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_rename(const char *from_path, const char *to_path);
|
||||
|
||||
/**
|
||||
* Create a hard link to the specified file.
|
||||
* @param from_path The full path to the original file (using / on all systems)
|
||||
* @param to_path The full path to the new file (using / on all systems)
|
||||
* @remark Both files must reside on the same device.
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_link(const char *from_path, const char *to_path);
|
||||
|
||||
/**
|
||||
* Copy the specified file to another file.
|
||||
* @param from_path The full path to the original file (using / on all systems)
|
||||
* @param to_path The full path to the new file (using / on all systems)
|
||||
* @param perms Access permissions for the new file if it is created.
|
||||
* In place of the usual or'd combination of file permissions, the
|
||||
* value CORE_SOURCE_PERMS may be given, in which case the source
|
||||
* file's permissions are copied.
|
||||
* @remark The new file does not need to exist, it will be created if required.
|
||||
* @warning If the new file already exists, its contents will be overwritten.
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_copy(
|
||||
const char *from_path, const char *to_path, file_perms_t perms);
|
||||
|
||||
/**
|
||||
* Append the specified file to another file.
|
||||
* @param from_path The full path to the source file (use / on all systems)
|
||||
* @param to_path The full path to the destination file (use / on all systems)
|
||||
* @param perms Access permissions for the destination file if it is created.
|
||||
* In place of the usual or'd combination of file permissions, the
|
||||
* value CORE_SOURCE_PERMS may be given, in which case the source
|
||||
* file's permissions are copied.
|
||||
* @remark The new file does not need to exist, it will be created if required.
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_append(
|
||||
const char *from_path, const char *to_path, file_perms_t perms);
|
||||
|
||||
/**
|
||||
* Are we at the end of the file
|
||||
* @param fptr The core file we are testing.
|
||||
* @remark Returns CORE_EOF if we are at the end of file,
|
||||
* CORE_OK otherwise.
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_eof(file_t *fptr);
|
||||
|
||||
/**
|
||||
* Read data from the specified file.
|
||||
* @param thefile The file descriptor to read from.
|
||||
* @param buf The buffer to store the data to.
|
||||
* @param nbytes On entry, the number of bytes to read; on exit, the number
|
||||
* of bytes read.
|
||||
*
|
||||
* @remark file_read will read up to the specified number of
|
||||
* bytes, but never more. If there isn't enough data to fill that
|
||||
* number of bytes, all of the available data is read. The third
|
||||
* argument is modified to reflect the number of bytes read. If a
|
||||
* char was put back into the stream via ungetc, it will be the first
|
||||
* character returned.
|
||||
*
|
||||
* @remark It is not possible for both bytes to be read and an CORE_EOF
|
||||
* or other error to be returned. CORE_EINTR is never returned.
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_read(file_t *thefile, void *buf, size_t *nbytes);
|
||||
|
||||
/**
|
||||
* Write data to the specified file.
|
||||
* @param thefile The file descriptor to write to.
|
||||
* @param buf The buffer which contains the data.
|
||||
* @param nbytes On entry, the number of bytes to write; on exit, the number
|
||||
* of bytes written.
|
||||
*
|
||||
* @remark file_write will write up to the specified number of
|
||||
* bytes, but never more. If the OS cannot write that many bytes, it
|
||||
* will write as many as it can. The third argument is modified to
|
||||
* reflect the * number of bytes written.
|
||||
*
|
||||
* @remark It is possible for both bytes to be written and an error to
|
||||
* be returned. CORE_EINTR is never returned.
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_write(
|
||||
file_t *thefile, const void *buf, size_t *nbytes);
|
||||
|
||||
/**
|
||||
* Write data from iovec array to the specified file.
|
||||
* @param thefile The file descriptor to write to.
|
||||
* @param vec The array from which to get the data to write to the file.
|
||||
* @param nvec The number of elements in the struct iovec array. This must
|
||||
* be smaller than MAX_IOVEC_SIZE. If it isn't, the function
|
||||
* will fail with CORE_EINVAL.
|
||||
* @param nbytes The number of bytes written.
|
||||
*
|
||||
* @remark It is possible for both bytes to be written and an error to
|
||||
* be returned. CORE_EINTR is never returned.
|
||||
*
|
||||
* @remark file_writev is available even if the underlying
|
||||
* operating system doesn't provide writev().
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_writev(file_t *thefile,
|
||||
const struct iovec *vec, size_t nvec, size_t *nbytes);
|
||||
|
||||
/**
|
||||
* Read data from the specified file, ensuring that the buffer is filled
|
||||
* before returning.
|
||||
* @param thefile The file descriptor to read from.
|
||||
* @param buf The buffer to store the data to.
|
||||
* @param nbytes The number of bytes to read.
|
||||
* @param bytes_read If non-NULL, this will contain the number of bytes read.
|
||||
*
|
||||
* @remark file_read will read up to the specified number of
|
||||
* bytes, but never more. If there isn't enough data to fill that
|
||||
* number of bytes, then the process/thread will block until it is
|
||||
* available or EOF is reached. If a char was put back into the
|
||||
* stream via ungetc, it will be the first character returned.
|
||||
*
|
||||
* @remark It is possible for both bytes to be read and an error to be
|
||||
* returned. And if *bytes_read is less than nbytes, an accompanying
|
||||
* error is _always_ returned.
|
||||
*
|
||||
* @remark CORE_EINTR is never returned.
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_read_full(file_t *thefile, void *buf,
|
||||
size_t nbytes, size_t *bytes_read);
|
||||
|
||||
/**
|
||||
* Write data to the specified file, ensuring that all of the data is
|
||||
* written before returning.
|
||||
* @param thefile The file descriptor to write to.
|
||||
* @param buf The buffer which contains the data.
|
||||
* @param nbytes The number of bytes to write.
|
||||
* @param bytes_written If non-NULL, set to the number of bytes written.
|
||||
*
|
||||
* @remark file_write will write up to the specified number of
|
||||
* bytes, but never more. If the OS cannot write that many bytes, the
|
||||
* process/thread will block until they can be written. Exceptional
|
||||
* error such as "out of space" or "pipe closed" will terminate with
|
||||
* an error.
|
||||
*
|
||||
* @remark It is possible for both bytes to be written and an error to
|
||||
* be returned. And if *bytes_written is less than nbytes, an
|
||||
* accompanying error is _always_ returned.
|
||||
*
|
||||
* @remark CORE_EINTR is never returned.
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_write_full(file_t *thefile,
|
||||
const void *buf, size_t nbytes, size_t *bytes_written);
|
||||
|
||||
|
||||
/**
|
||||
* Write data from iovec array to the specified file, ensuring that all of the
|
||||
* data is written before returning.
|
||||
* @param thefile The file descriptor to write to.
|
||||
* @param vec The array from which to get the data to write to the file.
|
||||
* @param nvec The number of elements in the struct iovec array. This must
|
||||
* be smaller than MAX_IOVEC_SIZE. If it isn't, the function
|
||||
* will fail with CORE_EINVAL.
|
||||
* @param nbytes The number of bytes written.
|
||||
*
|
||||
* @remark file_writev_full is available even if the underlying
|
||||
* operating system doesn't provide writev().
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_writev_full(file_t *thefile,
|
||||
const struct iovec *vec, size_t nvec, size_t *nbytes);
|
||||
/**
|
||||
* Write a character into the specified file.
|
||||
* @param ch The character to write.
|
||||
* @param thefile The file descriptor to write to
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_putc(char ch, file_t *thefile);
|
||||
|
||||
/**
|
||||
* Read a character from the specified file.
|
||||
* @param ch The character to read into
|
||||
* @param thefile The file descriptor to read from
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_getc(char *ch, file_t *thefile);
|
||||
|
||||
/**
|
||||
* Put a character back onto a specified stream.
|
||||
* @param ch The character to write.
|
||||
* @param thefile The file descriptor to write to
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_ungetc(char ch, file_t *thefile);
|
||||
|
||||
/**
|
||||
* Read a string from the specified file.
|
||||
* @param str The buffer to store the string in.
|
||||
* @param len The length of the string
|
||||
* @param thefile The file descriptor to read from
|
||||
* @remark The buffer will be NUL-terminated if any characters are stored.
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_gets(char *str, int len, file_t *thefile);
|
||||
|
||||
/**
|
||||
* Write the string into the specified file.
|
||||
* @param str The string to write.
|
||||
* @param thefile The file descriptor to write to
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_puts(const char *str, file_t *thefile);
|
||||
|
||||
/**
|
||||
* Transfer all file modified data and metadata to disk.
|
||||
* @param thefile The file descriptor to sync
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_sync(file_t *thefile);
|
||||
|
||||
/**
|
||||
* Move the read/write file offset to a specified byte within a file.
|
||||
* @param thefile The file descriptor
|
||||
* @param where How to move the pointer, one of:
|
||||
* <PRE>
|
||||
* CORE_SET -- set the offset to offset
|
||||
* CORE_CUR -- add the offset to the current position
|
||||
* CORE_END -- add the offset to the current file size
|
||||
* </PRE>
|
||||
* @param offset The offset to move the pointer to.
|
||||
* @remark The third argument is modified to be the offset the pointer
|
||||
was actually moved to.
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_seek(file_t *thefile,
|
||||
seek_where_t where, off_t *offset);
|
||||
|
||||
/**accessor and general file_io functions. */
|
||||
|
||||
/**
|
||||
* return the file name of the current file.
|
||||
* @param new_path The path of the file.
|
||||
* @param thefile The currently open file.
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_name_get(const char **fname, file_t *thefile);
|
||||
|
||||
/**
|
||||
* set the specified file's permission bits.
|
||||
* @param fname The file (name) to apply the permissions to.
|
||||
* @param perms The permission bits to apply to the file.
|
||||
*
|
||||
* @warning Some platforms may not be able to apply all of the
|
||||
* available permission bits; CORE_INCOMPLETE will be returned if some
|
||||
* permissions are specified which could not be set.
|
||||
*
|
||||
* @warning Platforms which do not implement this feature will return
|
||||
* CORE_ENOTIMPL.
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_perms_set(const char *fname, file_perms_t perms);
|
||||
|
||||
/**
|
||||
* Set attributes of the specified file.
|
||||
* @param fname The full path to the file (using / on all systems)
|
||||
* @param attributes Or'd combination of
|
||||
* <PRE>
|
||||
* ATTR_READONLY - make the file readonly
|
||||
* ATTR_EXECUTABLE - make the file executable
|
||||
* ATTR_HIDDEN - make the file hidden
|
||||
* </PRE>
|
||||
* @param attr_mask Mask of valid bits in attributes.
|
||||
* @remark This function should be used in preference to explict manipulation
|
||||
* of the file permissions, because the operations to provide these
|
||||
* attributes are platform specific and may involve more than simply
|
||||
* setting permission bits.
|
||||
* @warning Platforms which do not implement this feature will return
|
||||
* CORE_ENOTIMPL.
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_attrs_set(const char *fname,
|
||||
file_attrs_t attributes, file_attrs_t attr_mask);
|
||||
|
||||
/**
|
||||
* Set the mtime of the specified file.
|
||||
* @param fname The full path to the file (using / on all systems)
|
||||
* @param mtime The mtime to apply to the file.
|
||||
* @warning Platforms which do not implement this feature will return
|
||||
* CORE_ENOTIMPL.
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_mtime_set(const char *fname, c_time_t mtime);
|
||||
|
||||
/**
|
||||
* Create a new directory on the file system.
|
||||
* @param path the path for the directory to be created. (use / on all systems)
|
||||
* @param perm Permissions for the new direcoty.
|
||||
*/
|
||||
CORE_DECLARE(status_t) dir_make(const char *path, file_perms_t perm);
|
||||
|
||||
/** Creates a new directory on the file system, but behaves like
|
||||
* 'mkdir -p'. Creates intermediate directories as required. No error
|
||||
* will be reported if PATH already exists.
|
||||
* @param path the path for the directory to be created. (use / on all systems)
|
||||
* @param perm Permissions for the new direcoty.
|
||||
*/
|
||||
CORE_DECLARE(status_t) dir_make_recursive(const char *path, file_perms_t perm);
|
||||
|
||||
/**
|
||||
* Remove directory from the file system.
|
||||
* @param path the path for the directory to be removed. (use / on all systems)
|
||||
* @remark Removing a directory which is in-use (e.g., the current working
|
||||
* directory, or during core_dir_read, or with an open file) is not portable.
|
||||
*/
|
||||
CORE_DECLARE(status_t) dir_remove(const char *path);
|
||||
|
||||
/**
|
||||
* get the specified file's stats.
|
||||
* @param finfo Where to store the information about the file.
|
||||
* @param wanted The desired file_info_t fields, as a bit flag of
|
||||
* CORE_FINFO_ values
|
||||
* @param thefile The file to get information about.
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_info_get(file_info_t *finfo,
|
||||
c_int32_t wanted, file_t *thefile);
|
||||
|
||||
|
||||
/**
|
||||
* Truncate the file's length to the specified offset
|
||||
* @param fp The file to truncate
|
||||
* @param offset The offset to truncate to.
|
||||
* @remark The read/write file offset is repositioned to offset.
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_trunc(file_t *fp, off_t offset);
|
||||
|
||||
/**
|
||||
* Retrieve the flags that were passed into file_open()
|
||||
* when the file was opened.
|
||||
* @return c_int32_t the flags
|
||||
*/
|
||||
CORE_DECLARE(c_int32_t) file_flags_get(file_t *f);
|
||||
|
||||
/**
|
||||
* get the specified file's stats. The file is specified by filename,
|
||||
* instead of using a pre-opened file.
|
||||
* @param finfo Where to store the information about the file, which is
|
||||
* never touched if the call fails.
|
||||
* @param fname The name of the file to stat.
|
||||
* @param wanted The desired file_info_t fields, as a bit flag of FILE_INFO_
|
||||
values
|
||||
*
|
||||
* @note If @c CORE_INCOMPLETE is returned all the fields in @a finfo may
|
||||
* not be filled in, and you need to check the @c finfo->valid bitmask
|
||||
* to verify that what you're looking for is there.
|
||||
*/
|
||||
CORE_DECLARE(status_t) file_stat(file_info_t *finfo,
|
||||
const char *fname, c_int32_t wanted);
|
||||
|
||||
/**
|
||||
* Find an existing directory suitable as a temporary storage location.
|
||||
* @param temp_dir The temp directory.
|
||||
* @remark
|
||||
* This function uses an algorithm to search for a directory that an
|
||||
* an application can use for temporary storage.
|
||||
*
|
||||
*/
|
||||
CORE_DECLARE(status_t) temp_dir_get(char *temp_dir);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* ! __CORE_FILE_H__ */
|
|
@ -0,0 +1,48 @@
|
|||
#ifndef __CORE_FSM_H__
|
||||
#define __CORE_FSM_H__
|
||||
|
||||
#include "core.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef enum _fsm_signal_t {
|
||||
FSM_ENTRY_SIG,
|
||||
FSM_EXIT_SIG,
|
||||
FSM_USER_SIG
|
||||
} fsm_signal_t;
|
||||
|
||||
typedef c_uint32_t fsm_event_t;
|
||||
typedef c_uint32_t fsm_state_t;
|
||||
typedef void (*fsm_handler_t)(void *s, void *e);
|
||||
|
||||
typedef struct _fsm_t {
|
||||
fsm_handler_t initial;
|
||||
fsm_handler_t final;
|
||||
fsm_handler_t state;
|
||||
} fsm_t;
|
||||
|
||||
#define fsm_create(__s, __i, __f) \
|
||||
(((__s)->initial = (__s)->state = (fsm_handler_t)(__i)), \
|
||||
(__s)->final = (fsm_handler_t)(__f))
|
||||
|
||||
#define fsm_clear(__s) \
|
||||
((__s)->initial = (__s)->state = (__s)->final = NULL)
|
||||
|
||||
|
||||
CORE_DECLARE(void) fsm_init(fsm_t *s, fsm_event_t *e);
|
||||
CORE_DECLARE(void) fsm_dispatch(fsm_t *s, fsm_event_t *e);
|
||||
CORE_DECLARE(void) fsm_final(fsm_t *s, fsm_event_t *e);
|
||||
|
||||
#define FSM_TRAN(__s, __target) \
|
||||
((fsm_t *)__s)->state = (fsm_handler_t)(__target)
|
||||
|
||||
#define FSM_STATE(__s) \
|
||||
(((fsm_t *)__s)->state)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ! __CORE_FSM_H__ */
|
|
@ -0,0 +1,122 @@
|
|||
#ifndef __CORE_GENERAL_H__
|
||||
#define __CORE_GENERAL_H__
|
||||
|
||||
/**
|
||||
* @file core_general.h
|
||||
* This is collection of oddballs that didn't fit anywhere else,
|
||||
* and might move to more appropriate headers with the release
|
||||
* of CORE 1.0.
|
||||
* @brief CORE Miscellaneous library routines
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "core_errno.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @defgroup core_general Miscellaneous library routines
|
||||
* @ingroup CORE
|
||||
* This is collection of oddballs that didn't fit anywhere else,
|
||||
* and might move to more appropriate headers with the release
|
||||
* of CORE 1.0.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** a space */
|
||||
#define ASCII_BLANK '\040'
|
||||
/** a carrige return */
|
||||
#define ASCII_CR '\015'
|
||||
/** a line feed */
|
||||
#define ASCII_LF '\012'
|
||||
/** a tab */
|
||||
#define ASCII_TAB '\011'
|
||||
|
||||
/**
|
||||
* Alignment macros
|
||||
*/
|
||||
|
||||
/* C_ALIGN() is only to be used to align on a power of 2 boundary */
|
||||
#define C_ALIGN(size, boundary) \
|
||||
(((size) + ((boundary) - 1)) & ~((boundary) - 1))
|
||||
|
||||
/** Default alignment */
|
||||
#define C_ALIGN_DEFAULT(size) C_ALIGN(size, 8)
|
||||
|
||||
|
||||
/**
|
||||
* String and memory functions
|
||||
*/
|
||||
|
||||
/* STRINGIFY is defined here, and also in core_release.h, so wrap it */
|
||||
#ifndef STRINGIFY
|
||||
/** Properly quote a value as a string in the C preprocessor */
|
||||
#define STRINGIFY(n) STRINGIFY_HELPER(n)
|
||||
/** Helper macro for STRINGIFY */
|
||||
#define STRINGIFY_HELPER(n) #n
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @defgroup core_library Library initialization and termination
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Setup any CORE internal data structures. This MUST be the first function
|
||||
* called for any CORE library.
|
||||
* @remark See core_app_initialize if this is an application, rather than
|
||||
* a library consumer of core.
|
||||
*/
|
||||
CORE_DECLARE(status_t) core_initialize(void);
|
||||
|
||||
/**
|
||||
* Set up an application with normalized argc, argv (and optionally env) in
|
||||
* order to deal with platform-specific oddities, such as Win32 services,
|
||||
* code pages and signals. This must be the first function called for any
|
||||
* CORE program.
|
||||
* @param argc Pointer to the argc that may be corrected
|
||||
* @param argv Pointer to the argv that may be corrected
|
||||
* @param env Pointer to the env that may be corrected, may be NULL
|
||||
* @remark See core_initialize if this is a library consumer of core.
|
||||
* Otherwise, this call is identical to core_initialize, and must be closed
|
||||
* with a call to core_terminate at the end of program execution.
|
||||
*/
|
||||
CORE_DECLARE(status_t) core_app_initialize(int *argc,
|
||||
char const * const * *argv,
|
||||
char const * const * *env);
|
||||
|
||||
/**
|
||||
* Tear down any CORE internal data structures which aren't torn down
|
||||
* automatically.
|
||||
* @remark An CORE program must call this function at termination once it
|
||||
* has stopped using CORE services. The CORE developers suggest using
|
||||
* atexit to ensure this is called. When using CORE from a language
|
||||
* other than C that has problems with the calling convention, use
|
||||
* core_terminate2() instead.
|
||||
*/
|
||||
CORE_DECLARE_NONSTD(void) core_terminate(void);
|
||||
|
||||
/**
|
||||
* Tear down any CORE internal data structures which aren't torn down
|
||||
* automatically, same as core_terminate
|
||||
* @remark An CORE program must call either the core_terminate or
|
||||
* core_terminate2 function once it it has finished using CORE
|
||||
* services. The CORE developers suggest using atexit(core_terminate)
|
||||
* to ensure this is done. core_terminate2 exists to allow non-c
|
||||
* language apps to tear down core, while core_terminate is
|
||||
* recommended from c language applications.
|
||||
*/
|
||||
CORE_DECLARE(void) core_terminate2(void);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* ! CORE_GENERAL_H */
|
|
@ -0,0 +1,67 @@
|
|||
#ifndef __CORE_INDEX_H__
|
||||
#define __CORE_INDEX_H__
|
||||
|
||||
#include "core.h"
|
||||
#include "core_mutex.h"
|
||||
|
||||
#define INVALID_INDEX 0
|
||||
|
||||
#define index_declare(__name, __size) \
|
||||
typedef struct { \
|
||||
int head, tail; \
|
||||
int size, avail; \
|
||||
c_uint32_t free_index[__size]; \
|
||||
mutex_id mut; \
|
||||
} index_##__name##_t; \
|
||||
index_##__name##_t __name
|
||||
|
||||
#define index_init(__pname, __size) do { \
|
||||
int __i; \
|
||||
mutex_create(&(__pname)->mut, MUTEX_DEFAULT); \
|
||||
(__pname)->size = (__pname)->avail = __size; \
|
||||
(__pname)->head = (__pname)->tail = 0; \
|
||||
for (__i = 0; __i < __size; __i++) \
|
||||
(__pname)->free_index[__i] = (__i + 1); \
|
||||
} while (0)
|
||||
|
||||
#define index_final(__pname) \
|
||||
((__pname)->mut ? mutex_delete((__pname)->mut) : CORE_OK)
|
||||
|
||||
#define index_init_wo_lock(__pname, __size) do { \
|
||||
int __i; \
|
||||
(__pname)->mut = 0; \
|
||||
(__pname)->size = (__pname)->avail = __size; \
|
||||
(__pname)->head = (__pname)->tail = 0; \
|
||||
for (__i = 0; __i < __size; __i++) \
|
||||
(__pname)->free_index[__i] = (__i + 1); \
|
||||
} while (0)
|
||||
|
||||
#define index_alloc(__pname, __index) do { \
|
||||
(__index) = INVALID_INDEX; \
|
||||
if ((__pname)->mut) mutex_lock((__pname)->mut); \
|
||||
if ((__pname)->avail > 0) { \
|
||||
(__pname)->avail--; \
|
||||
(__index) = (__pname)->free_index[(__pname)->head]; \
|
||||
(__pname)->free_index[(__pname)->head] = INVALID_INDEX; \
|
||||
(__pname)->head = ((__pname)->head + 1) % ((__pname)->size); \
|
||||
} \
|
||||
if ((__pname)->mut) mutex_unlock((__pname)->mut); \
|
||||
} while (0)
|
||||
|
||||
#define index_free(__pname, __index) do { \
|
||||
if ((__pname)->mut) mutex_lock((__pname)->mut); \
|
||||
if ((__pname)->avail < (__pname)->size) { \
|
||||
(__pname)->avail++; \
|
||||
(__pname)->free_index[(__pname)->tail] = (__index); \
|
||||
(__pname)->tail = ((__pname)->tail + 1) % ((__pname)->size); \
|
||||
} \
|
||||
if ((__pname)->mut) mutex_unlock((__pname)->mut); \
|
||||
} while (0)
|
||||
|
||||
#define index_size(__pname) ((__pname)->size)
|
||||
|
||||
#define index_avail(__pname) ((__pname)->avail)
|
||||
|
||||
#define index_used(__pname) (index_size(__pname) - index_avail(__pname))
|
||||
|
||||
#endif /* ! __CORE_INDEX_H__ */
|
|
@ -0,0 +1,87 @@
|
|||
#ifndef __CORE_LIB_H__
|
||||
#define __CORE_LIB_H__
|
||||
|
||||
/**
|
||||
* @file c_lib.h
|
||||
* This is collection of oddballs that didn't fit anywhere else,
|
||||
* and might move to more appropriate headers with the release
|
||||
* of CORE 1.0.
|
||||
* @brief CORE general purpose library routines
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "core_errno.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @defgroup c_lib General Purpose Library Routines
|
||||
* @ingroup CORE
|
||||
* This is collection of oddballs that didn't fit anywhere else,
|
||||
* and might move to more appropriate headers with the release
|
||||
* of CORE 1.0.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** A constant representing a 'large' string. */
|
||||
#define HUGE_STRING_LEN 8192
|
||||
|
||||
/*
|
||||
* Define the structures used by the CORE general-purpose library.
|
||||
*/
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @defgroup c_ctype ctype functions
|
||||
* These macros allow correct support of 8-bit characters on systems which
|
||||
* support 8-bit characters. Pretty dumb how the cast is required, but
|
||||
* that's legacy libc for ya. These new macros do not support EOF like
|
||||
* the standard macros do. Tough.
|
||||
* @{
|
||||
*/
|
||||
/** @see isalnum */
|
||||
#define c_isalnum(c) (isalnum(((unsigned char)(c))))
|
||||
/** @see isalpha */
|
||||
#define c_isalpha(c) (isalpha(((unsigned char)(c))))
|
||||
/** @see iscntrl */
|
||||
#define c_iscntrl(c) (iscntrl(((unsigned char)(c))))
|
||||
/** @see isdigit */
|
||||
#define c_isdigit(c) (isdigit(((unsigned char)(c))))
|
||||
/** @see isgraph */
|
||||
#define c_isgraph(c) (isgraph(((unsigned char)(c))))
|
||||
/** @see islower*/
|
||||
#define c_islower(c) (islower(((unsigned char)(c))))
|
||||
/** @see isascii */
|
||||
#ifdef isascii
|
||||
#define c_isascii(c) (isascii(((unsigned char)(c))))
|
||||
#else
|
||||
#define c_isascii(c) (((c) & ~0x7f)==0)
|
||||
#endif
|
||||
/** @see isprint */
|
||||
#define c_isprint(c) (isprint(((unsigned char)(c))))
|
||||
/** @see ispunct */
|
||||
#define c_ispunct(c) (ispunct(((unsigned char)(c))))
|
||||
/** @see isspace */
|
||||
#define c_isspace(c) (isspace(((unsigned char)(c))))
|
||||
/** @see isupper */
|
||||
#define c_isupper(c) (isupper(((unsigned char)(c))))
|
||||
/** @see isxdigit */
|
||||
#define c_isxdigit(c) (isxdigit(((unsigned char)(c))))
|
||||
/** @see tolower */
|
||||
#define c_tolower(c) (tolower(((unsigned char)(c))))
|
||||
/** @see toupper */
|
||||
#define c_toupper(c) (toupper(((unsigned char)(c))))
|
||||
|
||||
#define c_max(x , y) (((x) > (y)) ? (x) : (y))
|
||||
#define c_min(x , y) (((x) < (y)) ? (x) : (y))
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* ! __CORE_LIB_H__ */
|
|
@ -0,0 +1,112 @@
|
|||
#ifndef __CORE_LIST_H__
|
||||
#define __CORE_LIST_H__
|
||||
|
||||
#include "core.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
struct _ln_t {
|
||||
struct _ln_t *prev;
|
||||
struct _ln_t *next;
|
||||
};
|
||||
|
||||
typedef struct _ln_t ln_t;
|
||||
typedef struct _ln_t list_t;
|
||||
typedef struct _ln_t lnode_t;
|
||||
|
||||
#define list_init(__pname) do {\
|
||||
(__pname)->prev = NULL; \
|
||||
(__pname)->next = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define list_first(__pname) ((void*)((__pname)->next))
|
||||
|
||||
#define list_last(__pname) ((void*)((__pname)->prev))
|
||||
|
||||
#define list_prev(__ptr_node) ((void*)(((ln_t *)(__ptr_node))->prev))
|
||||
|
||||
#define list_next(__ptr_node) ((void*)(((ln_t *)(__ptr_node))->next))
|
||||
|
||||
#define list_is_empty(__pname) ((__pname)->next == NULL)
|
||||
|
||||
#define list_prepend(__pname, __ptr_new) do { \
|
||||
((ln_t*)(__ptr_new))->prev = NULL; \
|
||||
((ln_t*)(__ptr_new))->next = (__pname)->next; \
|
||||
if ((__pname)->next) \
|
||||
((__pname)->next)->prev = (ln_t*)(__ptr_new); \
|
||||
else \
|
||||
(__pname)->prev = (ln_t*)(__ptr_new); \
|
||||
(__pname)->next = (ln_t*)(__ptr_new); \
|
||||
} while (0)
|
||||
|
||||
#define list_append(__pname, __ptr_new) do { \
|
||||
((ln_t*)(__ptr_new))->prev = (__pname)->prev; \
|
||||
((ln_t*)(__ptr_new))->next = NULL; \
|
||||
if ((__pname)->prev) \
|
||||
((__pname)->prev)->next = (ln_t*)(__ptr_new); \
|
||||
else \
|
||||
(__pname)->next = (ln_t*)(__ptr_new); \
|
||||
((__pname)->prev) = (ln_t*)(__ptr_new); \
|
||||
} while (0)
|
||||
|
||||
#define list_insert_prev(__pname, __ptr_node, __ptr_new) do { \
|
||||
((ln_t*)(__ptr_new))->prev = ((ln_t*)(__ptr_node))->prev; \
|
||||
((ln_t*)(__ptr_new))->next = (ln_t*)(__ptr_node); \
|
||||
if (((ln_t*)(__ptr_node))->prev) \
|
||||
((ln_t*)(__ptr_node))->prev->next = (ln_t*)(__ptr_new); \
|
||||
else \
|
||||
(__pname)->next = (ln_t*)(__ptr_new); \
|
||||
((ln_t*)(__ptr_node))->prev = ((ln_t*)(__ptr_new)); \
|
||||
} while (0)
|
||||
|
||||
#define list_insert_next(__pname, __ptr_node, __ptr_new) do { \
|
||||
((ln_t*)(__ptr_new))->prev = (ln_t*)(__ptr_node); \
|
||||
((ln_t*)(__ptr_new))->next = ((ln_t*)(__ptr_node))->next; \
|
||||
if (((ln_t*)(__ptr_node))->next) \
|
||||
((ln_t*)(__ptr_node))->next->prev = (ln_t*)(__ptr_new); \
|
||||
else \
|
||||
(__pname)->prev = (ln_t*)(__ptr_new); \
|
||||
((ln_t*)(__ptr_node))->next = ((ln_t*)(__ptr_new)); \
|
||||
} while (0)
|
||||
|
||||
#define list_remove(__pname, __ptr_node) do { \
|
||||
ln_t *_iter = (__pname)->next; \
|
||||
while (_iter) { \
|
||||
if (_iter == (ln_t*)(__ptr_node)) { \
|
||||
if (_iter->prev) \
|
||||
_iter->prev->next = _iter->next; \
|
||||
else \
|
||||
(__pname)->next = _iter->next; \
|
||||
if (_iter->next) \
|
||||
_iter->next->prev = _iter->prev; \
|
||||
else \
|
||||
(__pname)->prev = _iter->prev; \
|
||||
break; \
|
||||
} \
|
||||
_iter = _iter->next; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
typedef int (*ln_cmp_cb)(lnode_t *pnode1, lnode_t *pnode2);
|
||||
|
||||
#define list_insert_sorted(__pname, __ptr_new, __cmp_callback) do { \
|
||||
ln_cmp_cb __pcb = (ln_cmp_cb)__cmp_callback; \
|
||||
ln_t *_iter = list_first(__pname); \
|
||||
while (_iter) { \
|
||||
if ((*__pcb)((ln_t*)(__ptr_new), _iter) < 0) { \
|
||||
list_insert_prev(__pname, _iter, __ptr_new); \
|
||||
break; \
|
||||
} \
|
||||
_iter = list_next(_iter); \
|
||||
} \
|
||||
if (_iter == NULL) \
|
||||
list_append(__pname, __ptr_new); \
|
||||
} while (0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* ! __CORE_LIST_H__ */
|
|
@ -0,0 +1,86 @@
|
|||
#ifndef __CORE_MSGQ_H__
|
||||
#define __CORE_MSGQ_H__
|
||||
|
||||
/**
|
||||
* @file core_msgq.h
|
||||
* @brief Message queue header
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "core_time.h"
|
||||
#include "core_errno.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef c_uintptr_t msgq_id;
|
||||
|
||||
#define MAX_MSG_LEN 0xffff
|
||||
|
||||
/**
|
||||
* @return CORE_OK or CORE_ERROR.
|
||||
*/
|
||||
CORE_DECLARE(status_t) msgq_init(void);
|
||||
|
||||
/**
|
||||
* @return CORE_OK or CORE_ERROR.
|
||||
*/
|
||||
CORE_DECLARE(status_t) msgq_final(void);
|
||||
|
||||
#define MSGQ_O_BLOCK 0x0
|
||||
#define MSGQ_O_NONBLOCK 0x1
|
||||
|
||||
/**
|
||||
* @param id
|
||||
* @param msgsize
|
||||
* @param opt
|
||||
*
|
||||
* @return If succeed, handler value. If fail, zero
|
||||
*/
|
||||
CORE_DECLARE(msgq_id) msgq_create(int qsize, int msgsize, int opt);
|
||||
|
||||
/**
|
||||
* @param id
|
||||
*
|
||||
* @return If succeed, CORE_OK. If fail, CORE_ERROR.
|
||||
*/
|
||||
CORE_DECLARE(status_t) msgq_delete(msgq_id id);
|
||||
|
||||
/**
|
||||
* @param id
|
||||
* @param msg
|
||||
* @param msglen
|
||||
*
|
||||
* @return the number of bytes to be sent. If there is insufficient room in
|
||||
* ring buffer, return CORE_EAGAIN. If any error, CORE_ERROR.
|
||||
*/
|
||||
CORE_DECLARE(int) msgq_send(msgq_id id, const char *msg, int msglen);
|
||||
|
||||
/**
|
||||
* @param id
|
||||
* @param msg
|
||||
* @param msglen
|
||||
*
|
||||
* @return the number of bytes to be read. If any error, CORE_ERROR.
|
||||
* If ring buffer is empty and MSGQ_O_NONBLOCK set, CORE_EAGAIN.
|
||||
*/
|
||||
CORE_DECLARE(int) msgq_recv(msgq_id id, char *msg, int msglen);
|
||||
|
||||
/**
|
||||
* @param id
|
||||
* @param msg
|
||||
* @param msglen
|
||||
*
|
||||
* @return the number of bytes to be read. If any error, CORE_ERROR.
|
||||
* If ring buffer is empty and MSGQ_O_NONBLOCK set, CORE_EAGAIN.
|
||||
* If time out with empty buffer, CORE_TIMEUP.
|
||||
*/
|
||||
CORE_DECLARE(int) msgq_timedrecv(msgq_id id, char *msg, int msglen,
|
||||
c_time_t timeout);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* !__CORE_MSGQ_H__ */
|
|
@ -0,0 +1,89 @@
|
|||
#ifndef __MUTEX_H__
|
||||
#define __MUTEX_H__
|
||||
|
||||
/**
|
||||
* @file mutex.h
|
||||
* @brief Core Mutex Routines
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "core_errno.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @defgroup mutex Thread Mutex Routines
|
||||
* @ingroup CORE
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Opaque thread-local mutex structure */
|
||||
typedef c_uintptr_t mutex_id;
|
||||
|
||||
#define MUTEX_DEFAULT 0x0 /**< platform-optimal lock behavior */
|
||||
#define MUTEX_NESTED 0x1 /**< enable nested (recursive) locks */
|
||||
#define MUTEX_UNNESTED 0x2 /**< disable nested locks */
|
||||
|
||||
/**
|
||||
* Initialize Mutex Pool
|
||||
*/
|
||||
CORE_DECLARE(status_t) mutex_init(void);
|
||||
|
||||
/**
|
||||
* Finalize Mutex Pool
|
||||
*/
|
||||
CORE_DECLARE(status_t) mutex_final(void);
|
||||
|
||||
/**
|
||||
* Create and initialize a mutex that can be used to synchronize threads.
|
||||
* @param id the memory address where the newly created mutex will be
|
||||
* stored.
|
||||
* @param flags Or'ed value of:
|
||||
* <PRE>
|
||||
* MUTEX_DEFAULT platform-optimal lock behavior.
|
||||
* MUTEX_NESTED enable nested (recursive) locks.
|
||||
* MUTEX_UNNESTED disable nested locks (non-recursive).
|
||||
* </PRE>
|
||||
* @param pool the pool from which to allocate the mutex.
|
||||
* @warning Be cautious in using MUTEX_DEFAULT. While this is the
|
||||
* most optimial mutex based on a given platform's performance charateristics,
|
||||
* it will behave as either a nested or an unnested lock.
|
||||
*/
|
||||
CORE_DECLARE(status_t) mutex_create(mutex_id *id, unsigned int flags);
|
||||
/**
|
||||
* Acquire the lock for the given mutex. If the mutex is already locked,
|
||||
* the current thread will be put to sleep until the lock becomes available.
|
||||
* @param id the mutex on which to acquire the lock.
|
||||
*/
|
||||
CORE_DECLARE(status_t) mutex_lock(mutex_id id);
|
||||
|
||||
/**
|
||||
* Attempt to acquire the lock for the given mutex. If the mutex has already
|
||||
* been acquired, the call returns immediately with CORE_EBUSY. Note: it
|
||||
* is important that the CORE_STATUS_IS_EBUSY(s) macro be used to determine
|
||||
* if the return value was CORE_EBUSY, for portability reasons.
|
||||
* @param id the mutex on which to attempt the lock acquiring.
|
||||
*/
|
||||
CORE_DECLARE(status_t) mutex_trylock(mutex_id id);
|
||||
|
||||
/**
|
||||
* Release the lock for the given mutex.
|
||||
* @param id the mutex from which to release the lock.
|
||||
*/
|
||||
CORE_DECLARE(status_t) mutex_unlock(mutex_id id);
|
||||
|
||||
/**
|
||||
* Destroy the mutex and free the memory associated with the lock.
|
||||
* @param id the mutex to destroy.
|
||||
*/
|
||||
CORE_DECLARE(status_t) mutex_delete(mutex_id id);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* ! __MUTEX_H__ */
|
|
@ -0,0 +1,266 @@
|
|||
#ifndef __CORE_NET_H__
|
||||
#define __CORE_NET_H__
|
||||
|
||||
#include "core.h"
|
||||
#include "core_errno.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#if HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#define MAX_NET_POOL_SIZE 100
|
||||
|
||||
/* Max length of interface name, ex: eth0, ath0 .. */
|
||||
#define MAX_IFNAME_LEN 16
|
||||
|
||||
#define INET_NTOP(src, dst) inet_ntop(AF_INET,(void *)(src),(dst),INET_ADDRSTRLEN)
|
||||
#define INET6_NTOP(src, dst) inet_ntop(AF_INET6,(void *)(src),(dst),INET6_ADDRSTRLEN)
|
||||
|
||||
/** Network handler */
|
||||
typedef int (*net_handler)(void *net_sl, void *data);
|
||||
|
||||
/** Network socket descriptor */
|
||||
typedef struct {
|
||||
int type;
|
||||
int proto;
|
||||
int sock_id;
|
||||
#if 0 /* deprecated */
|
||||
struct sockaddr_in local;
|
||||
#endif
|
||||
struct sockaddr_in remote;
|
||||
int opt;
|
||||
int sndrcv_errno;
|
||||
} net_sock_t;
|
||||
|
||||
/** Network socket handler */
|
||||
typedef int (*net_sock_handler)(net_sock_t *net_sock, void *data);
|
||||
|
||||
/** Basic socket library */
|
||||
|
||||
/** Initialize network library */
|
||||
CORE_DECLARE(status_t) net_init(void);
|
||||
|
||||
/** Finalize network library */
|
||||
CORE_DECLARE(status_t) net_final(void);
|
||||
|
||||
/**
|
||||
* Create network session.
|
||||
* @param net_sock Connected network session.
|
||||
* @param host Host IP address to be connected.
|
||||
* @param lport Local Port number(only for UDP)
|
||||
* @param rport Remote Port number
|
||||
* @param proto Protocol proto
|
||||
* @param type Protocol type
|
||||
* @param flag Option flags to be set for this connection
|
||||
*/
|
||||
CORE_DECLARE(int) net_open(net_sock_t **net_sock,const char *host,
|
||||
const int lport,
|
||||
const int rport,
|
||||
int type, int proto, const int flag);
|
||||
|
||||
/**
|
||||
* Create network session.
|
||||
* @param net_sock Connected network session.
|
||||
* @param local_addr Local Host IP address to bind(Network order)
|
||||
* @param remote_host Remote Host IP address to be connected.
|
||||
* @param lport Local Port number(only for UDP)
|
||||
* @param rport Remote Port number
|
||||
* @param proto Protocol proto
|
||||
* @param type Protocol type
|
||||
* @param flag Option flags to be set for this connection
|
||||
*/
|
||||
CORE_DECLARE(int) net_open_with_addr(net_sock_t **net_sock,
|
||||
const c_uint32_t local_addr,
|
||||
const char *remote_host,
|
||||
const int lport,
|
||||
const int rport,
|
||||
int type, int proto, const int flag);
|
||||
/**
|
||||
* Read the data from the socket
|
||||
* @param net_sock Socket which created before
|
||||
* @param buffer Buffer which data be saved
|
||||
* @param size Total length of buffer
|
||||
* @param timeout Wait timeout. If 0 , it will block until data ready
|
||||
*/
|
||||
CORE_DECLARE(int) net_read(net_sock_t *net_sock, char *buffer, size_t size,int timeout);
|
||||
|
||||
/** Write the data into the socket
|
||||
* @param net_sock Socket which created before
|
||||
* @param buffer Buffer which data be saved
|
||||
* @param size Total length of buffer
|
||||
*/
|
||||
CORE_DECLARE(int) net_write(net_sock_t *net_sock, char *buffer, size_t size,
|
||||
struct sockaddr_in *dest_addr, int addrlen);
|
||||
|
||||
CORE_DECLARE(int) net_send(net_sock_t *net_sock, char *buffer, size_t size);
|
||||
|
||||
CORE_DECLARE(int) net_sendto(net_sock_t *net_sock, char *buffer, size_t size,
|
||||
c_uint32_t ip_addr, c_uint16_t port);
|
||||
|
||||
|
||||
/** Close the socket
|
||||
* @param net_sock Socket to be closed
|
||||
*/
|
||||
CORE_DECLARE(int) net_close(net_sock_t *net_sock);
|
||||
|
||||
/** Wait the new socket session until given timeout
|
||||
* @param new_accept_sock Newly created socket for new connection
|
||||
* @param net_sock Listend socket before created
|
||||
* @param timeout Wait timeout. If 0, it will be blocked until new connection
|
||||
* received
|
||||
*/
|
||||
CORE_DECLARE(int) net_accept(net_sock_t **new_accept_sock,
|
||||
net_sock_t *net_sock, int timeout);
|
||||
|
||||
/** Create socket and listen to the specified port
|
||||
* @param net_sock Returned socket
|
||||
* @param type Protocol type
|
||||
* @param proto Protocol proto
|
||||
* @param port Port number
|
||||
* @param addr Specific address
|
||||
*/
|
||||
CORE_DECLARE(int) net_listen_with_addr(
|
||||
net_sock_t **net_sock, const int type, const int proto,
|
||||
const int port, const c_uint32_t addr);
|
||||
/** Create socket and listen to the specified port
|
||||
* @param net_sock Returned socket
|
||||
* @param type Protocol type
|
||||
* @param proto Protocol proto
|
||||
* @param port Port number
|
||||
*/
|
||||
CORE_DECLARE(int) net_listen(
|
||||
net_sock_t **net_sock, const int type, const int proto,
|
||||
const int port);
|
||||
|
||||
/** Network application protocol */
|
||||
#define MAX_FTP_SESSION_SIZE 10
|
||||
typedef struct {
|
||||
net_sock_t *ctrl_sock; /* Control channel */
|
||||
net_sock_t *data_sock; /* Data channel */
|
||||
int flag;
|
||||
char cmd_buf[256];
|
||||
char resp_buf[256];
|
||||
} net_ftp_t;
|
||||
|
||||
/** Open ftp session.
|
||||
* @param host host name or IP address to connect
|
||||
* @param username User ID or NULL if username is anonymous
|
||||
* @param passwd Password or NULL if no passwd
|
||||
* @param flag Option flags
|
||||
* @param ftp_session Ftp session structure. If connection failed , it will be NULL
|
||||
*/
|
||||
CORE_DECLARE(int) net_ftp_open(const char *host,
|
||||
const char *username,
|
||||
const char *passwd,
|
||||
int flag,
|
||||
net_ftp_t **ftp_session);
|
||||
|
||||
/** Retrieve file using FTP
|
||||
* @param ftp_session Ftp session which created from net_ftp_open
|
||||
* @param remote_filename Remote filename to retrieve
|
||||
* @param local_filename Local filename. If null, the same name as remote will
|
||||
* be used.
|
||||
*/
|
||||
CORE_DECLARE(int) net_ftp_get(net_ftp_t *ftp_session,
|
||||
const char *remote_filename,
|
||||
const char *local_filename);
|
||||
|
||||
/** Upload file using FTP
|
||||
* @param ftp_session Ftp session which created from net_ftp_open
|
||||
* @param local_filename Local filename to upload.
|
||||
* @param remote_filename Remote filename.If null, the same name as local will
|
||||
* be used.
|
||||
*/
|
||||
CORE_DECLARE(int) net_ftp_put(net_ftp_t *ftp_session,
|
||||
const char *local_filename,
|
||||
const char *remote_filename);
|
||||
/** Quit from ftp
|
||||
* @param ftp_session Ftp session which created from net_ftp_open
|
||||
*/
|
||||
CORE_DECLARE(int) net_ftp_quit(net_ftp_t *ftp_session);
|
||||
|
||||
/** Close ftp session
|
||||
* @param ftp_session Ftp session which created from net_ftp_open
|
||||
*/
|
||||
CORE_DECLARE(int) net_ftp_close(net_ftp_t *ftp_session);
|
||||
|
||||
/** Network session pool */
|
||||
CORE_DECLARE(int) net_pool_avail();
|
||||
|
||||
/** Network link interface */
|
||||
typedef struct {
|
||||
int fd;
|
||||
int ioctl_sock;
|
||||
char ifname[MAX_IFNAME_LEN];
|
||||
struct sockaddr hwaddr;
|
||||
} net_link_t;
|
||||
|
||||
/** Network link handler */
|
||||
typedef int (*net_link_handler)(net_link_t *net_sock, void *data);
|
||||
|
||||
|
||||
/** Open network interface */
|
||||
CORE_DECLARE(int) net_link_open(net_link_t **net_link, char *device, int proto);
|
||||
/** Close network interface */
|
||||
CORE_DECLARE(int) net_link_close(net_link_t *net_link);
|
||||
|
||||
/** Enable or disable promisc mode of network interface */
|
||||
CORE_DECLARE(int) net_link_promisc(net_link_t *net_link, int enable);
|
||||
|
||||
/** Write the data into the link */
|
||||
CORE_DECLARE(int) net_link_write(net_link_t *net_link, char *buf, int len);
|
||||
|
||||
/** Reate the data from the link */
|
||||
CORE_DECLARE(int) net_link_read(net_link_t *net_link, char *buffer, int size,
|
||||
int timeout);
|
||||
|
||||
/** Open the specified protocol raw socket */
|
||||
CORE_DECLARE(int) net_raw_open(net_link_t **net_link, int proto);
|
||||
|
||||
/** Clse the specified protocol raw socket */
|
||||
CORE_DECLARE(int) net_raw_close(net_link_t *net_link);
|
||||
|
||||
CORE_DECLARE(int) net_link_sendto(net_link_t *net_link, char *buf, int len,
|
||||
struct sockaddr *dest_addr, int addrlen);
|
||||
|
||||
/** Register net_sock */
|
||||
CORE_DECLARE(int) net_register_sock(net_sock_t *net_sock,
|
||||
net_sock_handler handler, void *data);
|
||||
|
||||
/** Register net_link */
|
||||
CORE_DECLARE(int) net_register_link(net_link_t *net_link,
|
||||
net_link_handler handler, void *data);
|
||||
|
||||
/** Unregister net_sock */
|
||||
CORE_DECLARE(int) net_unregister_sock(net_sock_t *net_sock);
|
||||
|
||||
/** Unregister net_link */
|
||||
CORE_DECLARE(int) net_unregister_link(net_link_t *net_link);
|
||||
|
||||
/** Read the multiple fds and run the registered handler
|
||||
* @param timeout timeout(milliseconds)
|
||||
*/
|
||||
CORE_DECLARE(int) net_fds_read_run(long timeout);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* ! __CORE_NET_H__ */
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef __CORE_PARAM_H__
|
||||
#define __CORE_PARAM_H__
|
||||
|
||||
#define MAX_NUM_OF_THREAD 128
|
||||
#define MAX_NUM_OF_THREADATTR MAX_NUM_OF_THREAD
|
||||
#define MAX_NUM_OF_MUTEX 512
|
||||
#define MAX_NUM_OF_COND 512
|
||||
#define MAX_NUM_OF_RWLOCK 512
|
||||
#define MAX_NUM_OF_SEMAPHORE 512
|
||||
|
||||
#define MAX_NUM_OF_FILE 256
|
||||
#define MAX_FILENAME_SIZE 256
|
||||
#define MAX_DIRNAME_SIZE 256
|
||||
|
||||
#define MAX_NUM_OF_TIMER 1024
|
||||
|
||||
#define MAX_SIG_DESC_SIZE 256
|
||||
|
||||
#endif /* ! __CORE_PARAM_H__ */
|
|
@ -0,0 +1,192 @@
|
|||
#ifndef __CORE_PKBUF_H__
|
||||
#define __CORE_PKBUF_H__
|
||||
|
||||
/**
|
||||
* @file core_pkbuf.h
|
||||
* @brief Packet Buffer Routines
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "core_errno.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* Cluster buffer structre */
|
||||
typedef struct _clbuf_t {
|
||||
|
||||
/**
|
||||
* reference count */
|
||||
c_uint16_t ref;
|
||||
|
||||
/**
|
||||
* pointer to cluster */
|
||||
void *cluster;
|
||||
|
||||
/**
|
||||
* the size of cluster */
|
||||
c_uint16_t size;
|
||||
|
||||
} clbuf_t;
|
||||
|
||||
/**
|
||||
* Packet buffer structure */
|
||||
typedef struct _pkbuf_t {
|
||||
|
||||
/** next pkbuf in singly linked pkbuf chain */
|
||||
struct _pkbuf_t *next;
|
||||
|
||||
/** pointer to cluster */
|
||||
clbuf_t *clbuf;
|
||||
|
||||
/** this buffer */
|
||||
void *payload;
|
||||
|
||||
/**
|
||||
* total length of this buffer and all next buffers in chain
|
||||
* belonging to the same packet.
|
||||
*
|
||||
* For non-queue packet chains this is the invariant:
|
||||
* p->tot_len == p->len + (p->next? p->next->tot_len: 0)
|
||||
*/
|
||||
c_uint16_t tot_len;
|
||||
|
||||
/** length of this buffer */
|
||||
c_uint16_t len;
|
||||
|
||||
/** misc flags */
|
||||
c_uint8_t flags;
|
||||
|
||||
} pkbuf_t;
|
||||
|
||||
/**
|
||||
* Initializes the packet buffer library */
|
||||
CORE_DECLARE(status_t) pkbuf_init(void);
|
||||
|
||||
/**
|
||||
* Finalizes the packet buffer library */
|
||||
CORE_DECLARE(status_t) pkbuf_final(void);
|
||||
|
||||
/**
|
||||
* Show the pkbuf/clbuf/cluster count */
|
||||
CORE_DECLARE(void) pkbuf_show(void);
|
||||
|
||||
/**
|
||||
* Allocates a pkbuf of the given type (possibly a chain).
|
||||
*
|
||||
* The actual memory allocated for the pkbuf is determined by the
|
||||
* headroom at which the pkbuf is allocated and the requested size
|
||||
* (from the headroom parameter).
|
||||
*
|
||||
* @param headroom define header size
|
||||
* @param type define header size
|
||||
* should be allocated as follows:
|
||||
*
|
||||
* @return the allocated pkbuf. If multiple pkbufs where allocated, this
|
||||
* is the first pkbuf of a pkbuf chain.
|
||||
*/
|
||||
#define MAX_SIZEOF_HEADROOM 128
|
||||
CORE_DECLARE(pkbuf_t *) pkbuf_alloc(c_uint16_t headroom, c_uint16_t length);
|
||||
|
||||
/**
|
||||
* Dereference a pkbuf chain and deallocate any no-longer-used
|
||||
* pkbufs at the head of this chain.
|
||||
*
|
||||
* Decrements the reference count of the pkbuf's cluster buffer.
|
||||
* If it reaches zero, the pkbuf is deallocated.
|
||||
*
|
||||
* For a pkbuf chain, this is repeated for each pkbuf in the chain,
|
||||
* up to the first pkbuf which has a non-zero reference count after
|
||||
* decrementing. So, when all reference counts are one, the whole
|
||||
* chain is free'd.
|
||||
*
|
||||
* @param pkbuf The pkbuf (chain) to be dereferenced.
|
||||
*
|
||||
* @return the number of pkbufs that were de-allocated
|
||||
* from the head of the chain.
|
||||
*/
|
||||
CORE_DECLARE(void) pkbuf_free(pkbuf_t *pkbuf);
|
||||
|
||||
/**
|
||||
* Adjusts the payload pointer to hide or reveal headers in the payload.
|
||||
*
|
||||
* Adjusts the ->payload pointer so that space for a header
|
||||
* (dis)appears in the pkbuf payload.
|
||||
*
|
||||
* The ->payload, ->tot_len and ->len fields are adjusted.
|
||||
*
|
||||
* @param pkbuf pkbuf to change the header size.
|
||||
* @param size Number of bytes to increment header size which
|
||||
* increases the size of the pkbuf. New space is on the front.
|
||||
* (Using a negative value decreases the header size.)
|
||||
* If hdr_size_inc is 0, this function does nothing and returns succesful.
|
||||
*
|
||||
* @return non-zero on failure, zero on success.
|
||||
*/
|
||||
CORE_DECLARE(status_t) pkbuf_header(pkbuf_t *pkbuf, c_int16_t size);
|
||||
|
||||
/**
|
||||
* Concatenate two pkbufs (each may be a pkbuf chain) and take over
|
||||
* the caller's reference of the tail pkbuf.
|
||||
*
|
||||
* @note The caller MAY NOT reference the tail pkbuf afterwards.
|
||||
* Use pkbuf_chain() for that purpose.
|
||||
*
|
||||
* @see pkbuf_chain()
|
||||
*/
|
||||
CORE_DECLARE(void) pkbuf_join(pkbuf_t *h, pkbuf_t *t);
|
||||
|
||||
/**
|
||||
* Create copies of pkbufs.
|
||||
*
|
||||
* @param pkbuf pkbuf source of the copy
|
||||
*/
|
||||
CORE_DECLARE(pkbuf_t*) pkbuf_copy(pkbuf_t *pkbuf);
|
||||
|
||||
/**
|
||||
* Create copies of some part of pkbufs.
|
||||
*
|
||||
* @param pkbuf pkbuf source of the copy
|
||||
* @param offset offset into the packet buffer from where to begin copying
|
||||
* len bytes
|
||||
* @param len length of data to copy
|
||||
*/
|
||||
CORE_DECLARE(pkbuf_t*) pkbuf_copy_partial(pkbuf_t *pkbuf,
|
||||
c_uint16_t offset, c_uint16_t len);
|
||||
|
||||
/**
|
||||
* Copy the whole contents of a packet buffer to an application supplied
|
||||
* buffer.
|
||||
*
|
||||
* @param pkbuf pkbuf from which to copy data
|
||||
* @param buf buffer to copy to
|
||||
* @param buflen
|
||||
*/
|
||||
CORE_DECLARE(status_t) pkbuf_tobuf(pkbuf_t *pkbuf,
|
||||
void *buf, c_uint16_t *buflen);
|
||||
|
||||
/**
|
||||
* Copy part of the contents of a packet buffer to an application supplied
|
||||
* buffer.
|
||||
*
|
||||
* @param pkbuf pkbuf from which to copy data
|
||||
* @param buf buffer to copy to
|
||||
* @param buflen
|
||||
* @param offset offset into the packet buffer from where
|
||||
* to begin copying len bytes
|
||||
* @param len length of data to copy
|
||||
*/
|
||||
CORE_DECLARE(status_t) pkbuf_tobuf_partial(pkbuf_t *pkbuf,
|
||||
void *buf, c_uint16_t *buflen, c_uint16_t offset, c_uint16_t len);
|
||||
|
||||
/**
|
||||
* Get the total length of packet buffer */
|
||||
#define pkbuf_length(__pkbuf) (__pkbuf) ? ((__pkbuf)->tot_len : -1)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* ! __PKBUF_H__ */
|
|
@ -0,0 +1,65 @@
|
|||
#ifndef __CORE_POOL_H__
|
||||
#define __CORE_POOL_H__
|
||||
|
||||
#include "core.h"
|
||||
#include "core_mutex.h"
|
||||
|
||||
#define pool_declare(__name, __type, __size) \
|
||||
typedef struct { \
|
||||
int head, tail; \
|
||||
int size, avail; \
|
||||
__type *free[__size], pool[__size]; \
|
||||
mutex_id mut; \
|
||||
} pool_##__name##_t; \
|
||||
pool_##__name##_t __name
|
||||
|
||||
#define pool_init(__pname, __size) do { \
|
||||
int __i; \
|
||||
mutex_create(&(__pname)->mut, MUTEX_DEFAULT); \
|
||||
(__pname)->size = (__pname)->avail = __size; \
|
||||
(__pname)->head = (__pname)->tail = 0; \
|
||||
for (__i = 0; __i < __size; __i++) \
|
||||
(__pname)->free[__i] = &((__pname)->pool[__i]); \
|
||||
} while (0)
|
||||
|
||||
#define pool_final(__pname) \
|
||||
((__pname)->mut ? mutex_delete((__pname)->mut) : CORE_OK)
|
||||
|
||||
#define pool_init_wo_lock(__pname, __size) do { \
|
||||
int __i; \
|
||||
(__pname)->mut = 0; \
|
||||
(__pname)->size = (__pname)->avail = __size; \
|
||||
(__pname)->head = (__pname)->tail = 0; \
|
||||
for (__i = 0; __i < __size; __i++) \
|
||||
(__pname)->free[__i] = &((__pname)->pool[__i]); \
|
||||
} while (0)
|
||||
|
||||
#define pool_alloc_node(__pname, __pptr_node) do { \
|
||||
*(__pptr_node) = NULL; \
|
||||
if ((__pname)->mut) mutex_lock((__pname)->mut); \
|
||||
if ((__pname)->avail > 0) { \
|
||||
(__pname)->avail--; \
|
||||
*(__pptr_node) = (void*)(__pname)->free[(__pname)->head]; \
|
||||
(__pname)->free[(__pname)->head] = NULL; \
|
||||
(__pname)->head = ((__pname)->head + 1) % ((__pname)->size); \
|
||||
} \
|
||||
if ((__pname)->mut) mutex_unlock((__pname)->mut); \
|
||||
} while (0)
|
||||
|
||||
#define pool_free_node(__pname, __ptr_node) do { \
|
||||
if ((__pname)->mut) mutex_lock((__pname)->mut); \
|
||||
if ((__pname)->avail < (__pname)->size) { \
|
||||
(__pname)->avail++; \
|
||||
(__pname)->free[(__pname)->tail] = (void*)(__ptr_node); \
|
||||
(__pname)->tail = ((__pname)->tail + 1) % ((__pname)->size); \
|
||||
} \
|
||||
if ((__pname)->mut) mutex_unlock((__pname)->mut); \
|
||||
} while (0)
|
||||
|
||||
#define pool_size(__pname) ((__pname)->size)
|
||||
|
||||
#define pool_avail(__pname) ((__pname)->avail)
|
||||
|
||||
#define pool_used(__pname) (pool_size(__pname) - pool_avail(__pname))
|
||||
|
||||
#endif /* ! __CORE_POOL_H__ */
|
|
@ -0,0 +1,40 @@
|
|||
#ifndef __CORE_QUEUE_H__
|
||||
#define __CORE_QUEUE_H__
|
||||
|
||||
#include "core.h"
|
||||
|
||||
#define que_declare(__name, __type, __size) \
|
||||
struct { \
|
||||
int head, tail, size, used; \
|
||||
__type pool[(__size)]; \
|
||||
} __name
|
||||
|
||||
#define que_init(__pname, __size) \
|
||||
((__pname)->head = (__pname)->tail = 0, \
|
||||
(__pname)->used = 0, \
|
||||
(__pname)->size = __size)
|
||||
|
||||
#define que_push(__pname, __ptr_node) \
|
||||
((__pname)->used == ((__pname)->size) ? -1 : \
|
||||
(((__pname)->pool[(__pname)->head] = *(__ptr_node), \
|
||||
(__pname)->head = ((__pname)->head + 1) % ((__pname)->size), \
|
||||
++(__pname)->used)))
|
||||
|
||||
|
||||
#define que_pop(__pname, __ptr_node) \
|
||||
((__pname)->used == 0 ? -1 : \
|
||||
((*(__ptr_node) = (__pname)->pool[(__pname)->tail], \
|
||||
(__pname)->tail = ((__pname)->tail + 1) % ((__pname)->size), \
|
||||
--(__pname)->used)))
|
||||
|
||||
#define que_is_empty(__pname) ((__pname)->used == 0)
|
||||
|
||||
#define que_is_full(__pname) ((__pname)->used == (__pname)->size)
|
||||
|
||||
#define que_size(__pname) ((__pname)->size)
|
||||
|
||||
#define que_used(__pname) ((__pname)->used)
|
||||
|
||||
#define que_avail(__pname) (que_size(__pname) - que_used(__pname))
|
||||
|
||||
#endif /* ! __CORE_QUEUE_H__ */
|
|
@ -0,0 +1,57 @@
|
|||
#ifndef __CORE_RINGBUF_H__
|
||||
#define __CORE_RINGBUF_H__
|
||||
|
||||
#include "core.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
struct _rbuf_header_t {
|
||||
int head, tail, size;
|
||||
char *pool;
|
||||
};
|
||||
|
||||
#define rbuf_declare(__name, __size) \
|
||||
struct { \
|
||||
struct _rbuf_header_t h; \
|
||||
char int_pool[(__size) + 1]; \
|
||||
} __name
|
||||
|
||||
#define rbuf_declare_ext(__name) \
|
||||
struct { \
|
||||
struct _rbuf_header_t h; \
|
||||
} __name
|
||||
|
||||
#define rbuf_init(__pname, __size) \
|
||||
((__pname)->h.head = (__pname)->h.tail = 0, \
|
||||
(__pname)->h.size = __size, \
|
||||
(__pname)->h.pool = (__pname)->int_pool)
|
||||
|
||||
#define rbuf_init_ext(__pname, __size, __ext_pool) \
|
||||
((__pname)->h.head = (__pname)->h.tail = 0, \
|
||||
(__pname)->h.size = __size, \
|
||||
(__pname)->h.pool = (char *)(__ext_pool))
|
||||
|
||||
#define rbuf_size(__pname) ((__pname)->h.size)
|
||||
|
||||
#define rbuf_is_empty(__pname) ((__pname)->h.head == (__pname)->h.tail)
|
||||
#define rbuf_is_full(__pname) (rbuf_free_bytes(__pname) == 0)
|
||||
|
||||
CORE_DECLARE(int) rbuf_bytes(void *__pname);
|
||||
|
||||
CORE_DECLARE(int) rbuf_free_bytes(void *__pname);
|
||||
|
||||
CORE_DECLARE(int) rbuf_skip_write_pos(void *__pname, int __len);
|
||||
|
||||
CORE_DECLARE(int) rbuf_write(void *__pname, const char *__buf, int __buf_len);
|
||||
|
||||
CORE_DECLARE(int) rbuf_skip_read_pos(void *__pname, int __len);
|
||||
|
||||
CORE_DECLARE(int) rbuf_read(void *__pname, char *__buf, int __buf_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* ! __CORE_RINGBUF_H__ */
|
|
@ -0,0 +1,110 @@
|
|||
#ifndef __CORE_RWLOCK_H__
|
||||
#define __CORE_RWLOCK_H__
|
||||
|
||||
/**
|
||||
* @file rwlock.h
|
||||
* @brief CORE Reader/Writer Lock Routines
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "core_errno.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @defgroup rwlock Reader/Writer Lock Routines
|
||||
* @ingroup CORE
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Opaque read-write thread-safe lock. */
|
||||
typedef c_uintptr_t rwlock_id;
|
||||
|
||||
/**
|
||||
* Initialize Read-Write Lock Pool
|
||||
*/
|
||||
CORE_DECLARE(status_t) rwlock_init(void);
|
||||
|
||||
/**
|
||||
* Finalize Read-Write Lock Pool
|
||||
*/
|
||||
CORE_DECLARE(status_t) rwlock_final(void);
|
||||
|
||||
/**
|
||||
* Note: The following operations have undefined results: unlocking a
|
||||
* read-write lock which is not locked in the calling thread; write
|
||||
* locking a read-write lock which is already locked by the calling
|
||||
* thread; destroying a read-write lock more than once; clearing or
|
||||
* destroying the pool from which a <b>locked</b> read-write lock is
|
||||
* allocated.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create and initialize a read-write lock that can be used to synchronize
|
||||
* threads.
|
||||
* @param id the memory address where the newly created readwrite lock
|
||||
* will be stored.
|
||||
*/
|
||||
CORE_DECLARE(status_t) rwlock_create(rwlock_id *id);
|
||||
/**
|
||||
* Acquire a shared-read lock on the given read-write lock. This will allow
|
||||
* multiple threads to enter the same critical section while they have acquired
|
||||
* the read lock.
|
||||
* @param id the read-write lock on which to acquire the shared read.
|
||||
*/
|
||||
CORE_DECLARE(status_t) rwlock_rdlock(rwlock_id id);
|
||||
|
||||
/**
|
||||
* Attempt to acquire the shared-read lock on the given read-write lock. This
|
||||
* is the same as rwlock_rdlock(), only that the function fails
|
||||
* if there is another thread holding the write lock, or if there are any
|
||||
* write threads blocking on the lock. If the function fails for this case,
|
||||
* CORE_EBUSY will be returned. Note: it is important that the
|
||||
* CORE_STATUS_IS_EBUSY(s) macro be used to determine if the return value was
|
||||
* CORE_EBUSY, for portability reasons.
|
||||
* @param id the rwlock on which to attempt the shared read.
|
||||
*/
|
||||
CORE_DECLARE(status_t) rwlock_tryrdlock(rwlock_id id);
|
||||
|
||||
/**
|
||||
* Acquire an exclusive-write lock on the given read-write lock. This will
|
||||
* allow only one single thread to enter the critical sections. If there
|
||||
* are any threads currently holding the read-lock, this thread is put to
|
||||
* sleep until it can have exclusive access to the lock.
|
||||
* @param id the read-write lock on which to acquire the exclusive write.
|
||||
*/
|
||||
CORE_DECLARE(status_t) rwlock_wrlock(rwlock_id id);
|
||||
|
||||
/**
|
||||
* Attempt to acquire the exclusive-write lock on the given read-write lock.
|
||||
* This is the same as rwlock_wrlock(), only that the function fails
|
||||
* if there is any other thread holding the lock (for reading or writing),
|
||||
* in which case the function will return CORE_EBUSY. Note: it is important
|
||||
* that the CORE_STATUS_IS_EBUSY(s) macro be used to determine if the return
|
||||
* value was CORE_EBUSY, for portability reasons.
|
||||
* @param id the rwlock on which to attempt the exclusive write.
|
||||
*/
|
||||
CORE_DECLARE(status_t) rwlock_trywrlock(rwlock_id id);
|
||||
|
||||
/**
|
||||
* Release either the read or write lock currently held by the calling thread
|
||||
* associated with the given read-write lock.
|
||||
* @param id the read-write lock to be released (unlocked).
|
||||
*/
|
||||
CORE_DECLARE(status_t) rwlock_unlock(rwlock_id id);
|
||||
|
||||
/**
|
||||
* Destroy the read-write lock and free the associated memory.
|
||||
* @param id the rwlock to destroy.
|
||||
*/
|
||||
CORE_DECLARE(status_t) rwlock_delete(rwlock_id id);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* ! __CORE_RWLOCK_H__ */
|
|
@ -0,0 +1,81 @@
|
|||
#ifndef __SEMAPHORE_H__
|
||||
#define __SEMAPHORE_H__
|
||||
|
||||
/**
|
||||
* @file semaphore.h
|
||||
* @brief Core Mutex Routines
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "core_errno.h"
|
||||
#include "core_time.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @defgroup semaphore Routines
|
||||
* @ingroup CORE
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Opaque semaphore structure */
|
||||
typedef c_uintptr_t semaphore_id;
|
||||
|
||||
/**
|
||||
* Initialize Mutex Pool
|
||||
*/
|
||||
CORE_DECLARE(status_t) semaphore_init(void);
|
||||
|
||||
/**
|
||||
* Finalize Mutex Pool
|
||||
*/
|
||||
CORE_DECLARE(status_t) semaphore_final(void);
|
||||
|
||||
/**
|
||||
* Create and initialize a semaphore that can be used to synchronize processes.
|
||||
* @param id the memory address where the newly created semaphore will be
|
||||
* stored.
|
||||
* @value initial value for semaphore
|
||||
*/
|
||||
CORE_DECLARE(status_t) semaphore_create(semaphore_id *id, c_uint32_t value);
|
||||
/**
|
||||
* Put the active calling thread to sleep until signaled to wake up.
|
||||
* @param id the semaphore variable on which to block.
|
||||
*/
|
||||
CORE_DECLARE(status_t) semaphore_wait(semaphore_id id);
|
||||
|
||||
#if HAVE_SEM_TIMEDWAIT
|
||||
/**
|
||||
* Put the active calling thread to sleep until signaled to wake up or
|
||||
* the timeout is reached.
|
||||
* @param id the semaphore variable on which to block.
|
||||
* @param timeout The amount of time in microsesemaphores to wait. This is
|
||||
* a maximum, not a minimum. If the semaphoreition is signaled, we
|
||||
* will wake up before this time, otherwise the error CORE_TIMEUP
|
||||
* is returned.
|
||||
*/
|
||||
CORE_DECLARE(status_t) semaphore_timedwait(semaphore_id id, c_time_t timeout);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Posts a single thread, if one exists, that is blocking on the given
|
||||
* semaphore variable.
|
||||
* @param id the semaphore variable on which to produce the signal.
|
||||
*/
|
||||
CORE_DECLARE(status_t) semaphore_post(semaphore_id id);
|
||||
|
||||
/**
|
||||
* Destroy the semaphore and free the memory associated with the lock.
|
||||
* @param semaphore the semaphore to destroy.
|
||||
*/
|
||||
CORE_DECLARE(status_t) semaphore_delete(semaphore_id id);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* ! __SEMAPHORE_H__ */
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* sha1.h
|
||||
*
|
||||
* Copyright (C) 1998, 2009
|
||||
* Paul E. Jones <paulej@packetizer.com>
|
||||
* All Rights Reserved
|
||||
*
|
||||
*****************************************************************************
|
||||
* $Id: sha1.h 12 2009-06-22 19:34:25Z paulej $
|
||||
*****************************************************************************
|
||||
*
|
||||
* Description:
|
||||
* This class implements the Secure Hashing Standard as defined
|
||||
* in FIPS PUB 180-1 published April 17, 1995.
|
||||
*
|
||||
* Many of the variable names in the sha1_ctx, especially the
|
||||
* single character names, were used because those were the names
|
||||
* used in the publication.
|
||||
*
|
||||
* Please read the file sha1.c for more information.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _CORE_SHA1_H_
|
||||
#define _CORE_SHA1_H_
|
||||
|
||||
#include "core.h"
|
||||
|
||||
#define SHA1_DIGEST_SIZE (160 / 8)
|
||||
#define SHA1_BLOCK_SIZE (512 / 8)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct sha1_ctx
|
||||
{
|
||||
unsigned Message_Digest[5]; /* Message Digest (output) */
|
||||
|
||||
unsigned Length_Low; /* Message length in bits */
|
||||
unsigned Length_High; /* Message length in bits */
|
||||
|
||||
unsigned char Message_Block[64]; /* 512-bit message blocks */
|
||||
int Message_Block_Index; /* Index into message block array */
|
||||
|
||||
int Computed; /* Is the digest computed? */
|
||||
int Corrupted; /* Is the message digest corruped? */
|
||||
} sha1_ctx;
|
||||
|
||||
CORE_DECLARE(void) sha1_init(sha1_ctx *ctx);
|
||||
CORE_DECLARE(void) sha1_update(sha1_ctx *ctx, const c_uint8_t *message,
|
||||
c_uint32_t len);
|
||||
CORE_DECLARE(void) sha1_final(sha1_ctx *ctx, c_uint8_t *digest);
|
||||
CORE_DECLARE(void) sha1(const c_uint8_t *message, c_uint32_t len,
|
||||
c_uint8_t *digest);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* _CORE_SHA1_H_ */
|
|
@ -0,0 +1,71 @@
|
|||
/*-
|
||||
* HMAC-SHA-224/256/384/512 implementation
|
||||
* Last update: 06/15/2005
|
||||
* Issue date: 06/15/2005
|
||||
*
|
||||
* Copyright (C) 2005 Olivier Gay <olivier.gay@a3.epfl.ch>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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 _CORE_HMAC_SHA1_H
|
||||
#define _CORE_HMAC_SHA1_H
|
||||
|
||||
#include "core_sha1.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
sha1_ctx ctx_inside;
|
||||
sha1_ctx ctx_outside;
|
||||
|
||||
/* for hmac_reinit */
|
||||
sha1_ctx ctx_inside_reinit;
|
||||
sha1_ctx ctx_outside_reinit;
|
||||
|
||||
c_uint8_t block_ipad[SHA1_BLOCK_SIZE];
|
||||
c_uint8_t block_opad[SHA1_BLOCK_SIZE];
|
||||
} hmac_sha1_ctx;
|
||||
|
||||
CORE_DECLARE(void) hmac_sha1_init(hmac_sha1_ctx *ctx, c_uint8_t *key,
|
||||
c_uint32_t key_size);
|
||||
CORE_DECLARE(void) hmac_sha1_reinit(hmac_sha1_ctx *ctx);
|
||||
CORE_DECLARE(void) hmac_sha1_update(hmac_sha1_ctx *ctx, c_uint8_t *message,
|
||||
c_uint32_t message_len);
|
||||
CORE_DECLARE(void) hmac_sha1_final(hmac_sha1_ctx *ctx, c_uint8_t *mac,
|
||||
c_uint32_t mac_size);
|
||||
CORE_DECLARE(void) hmac_sha1(c_uint8_t *key, c_uint32_t key_size,
|
||||
c_uint8_t *message, c_uint32_t message_len,
|
||||
c_uint8_t *mac, c_uint32_t mac_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ! _CORE_HMAC_SHA1_H */
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* FIPS 180-2 SHA-224/256/384/512 implementation
|
||||
* Last update: 02/02/2007
|
||||
* Issue date: 04/30/2005
|
||||
*
|
||||
* Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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 _CORE_SHA2_H_
|
||||
#define _CORE_SHA2_H_
|
||||
|
||||
#include "core.h"
|
||||
|
||||
#define SHA224_DIGEST_SIZE ( 224 / 8)
|
||||
#define SHA256_DIGEST_SIZE ( 256 / 8)
|
||||
#define SHA384_DIGEST_SIZE ( 384 / 8)
|
||||
#define SHA512_DIGEST_SIZE ( 512 / 8)
|
||||
|
||||
#define SHA256_BLOCK_SIZE ( 512 / 8)
|
||||
#define SHA512_BLOCK_SIZE (1024 / 8)
|
||||
#define SHA384_BLOCK_SIZE SHA512_BLOCK_SIZE
|
||||
#define SHA224_BLOCK_SIZE SHA256_BLOCK_SIZE
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct {
|
||||
c_uint32_t tot_len;
|
||||
c_uint32_t len;
|
||||
c_uint8_t block[2 * SHA256_BLOCK_SIZE];
|
||||
c_uint32_t h[8];
|
||||
} sha256_ctx;
|
||||
|
||||
typedef struct {
|
||||
c_uint32_t tot_len;
|
||||
c_uint32_t len;
|
||||
c_uint8_t block[2 * SHA512_BLOCK_SIZE];
|
||||
c_uint64_t h[8];
|
||||
} sha512_ctx;
|
||||
|
||||
typedef sha512_ctx sha384_ctx;
|
||||
typedef sha256_ctx sha224_ctx;
|
||||
|
||||
CORE_DECLARE(void) sha224_init(sha224_ctx *ctx);
|
||||
CORE_DECLARE(void) sha224_update(sha224_ctx *ctx, const c_uint8_t *message,
|
||||
c_uint32_t len);
|
||||
CORE_DECLARE(void) sha224_final(sha224_ctx *ctx, c_uint8_t *digest);
|
||||
CORE_DECLARE(void) sha224(const c_uint8_t *message, c_uint32_t len,
|
||||
c_uint8_t *digest);
|
||||
|
||||
CORE_DECLARE(void) sha256_init(sha256_ctx * ctx);
|
||||
CORE_DECLARE(void) sha256_update(sha256_ctx *ctx, const c_uint8_t *message,
|
||||
c_uint32_t len);
|
||||
CORE_DECLARE(void) sha256_final(sha256_ctx *ctx, c_uint8_t *digest);
|
||||
CORE_DECLARE(void) sha256(const c_uint8_t *message, c_uint32_t len,
|
||||
c_uint8_t *digest);
|
||||
|
||||
CORE_DECLARE(void) sha384_init(sha384_ctx *ctx);
|
||||
CORE_DECLARE(void) sha384_update(sha384_ctx *ctx, const c_uint8_t *message,
|
||||
c_uint32_t len);
|
||||
CORE_DECLARE(void) sha384_final(sha384_ctx *ctx, c_uint8_t *digest);
|
||||
CORE_DECLARE(void) sha384(const c_uint8_t *message, c_uint32_t len,
|
||||
c_uint8_t *digest);
|
||||
|
||||
CORE_DECLARE(void) sha512_init(sha512_ctx *ctx);
|
||||
CORE_DECLARE(void) sha512_update(sha512_ctx *ctx, const c_uint8_t *message,
|
||||
c_uint32_t len);
|
||||
CORE_DECLARE(void) sha512_final(sha512_ctx *ctx, c_uint8_t *digest);
|
||||
CORE_DECLARE(void) sha512(const c_uint8_t *message, c_uint32_t len,
|
||||
c_uint8_t *digest);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* !_CORE_SHA2_H_ */
|
|
@ -0,0 +1,140 @@
|
|||
/*-
|
||||
* HMAC-SHA-224/256/384/512 implementation
|
||||
* Last update: 06/15/2005
|
||||
* Issue date: 06/15/2005
|
||||
*
|
||||
* Copyright (C) 2005 Olivier Gay <olivier.gay@a3.epfl.ch>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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 _CORE_HMAC_SHA2_H
|
||||
#define _CORE_HMAC_SHA2_H
|
||||
|
||||
#include "core_sha2.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
sha224_ctx ctx_inside;
|
||||
sha224_ctx ctx_outside;
|
||||
|
||||
/* for hmac_reinit */
|
||||
sha224_ctx ctx_inside_reinit;
|
||||
sha224_ctx ctx_outside_reinit;
|
||||
|
||||
c_uint8_t block_ipad[SHA224_BLOCK_SIZE];
|
||||
c_uint8_t block_opad[SHA224_BLOCK_SIZE];
|
||||
} hmac_sha224_ctx;
|
||||
|
||||
typedef struct {
|
||||
sha256_ctx ctx_inside;
|
||||
sha256_ctx ctx_outside;
|
||||
|
||||
/* for hmac_reinit */
|
||||
sha256_ctx ctx_inside_reinit;
|
||||
sha256_ctx ctx_outside_reinit;
|
||||
|
||||
c_uint8_t block_ipad[SHA256_BLOCK_SIZE];
|
||||
c_uint8_t block_opad[SHA256_BLOCK_SIZE];
|
||||
} hmac_sha256_ctx;
|
||||
|
||||
typedef struct {
|
||||
sha384_ctx ctx_inside;
|
||||
sha384_ctx ctx_outside;
|
||||
|
||||
/* for hmac_reinit */
|
||||
sha384_ctx ctx_inside_reinit;
|
||||
sha384_ctx ctx_outside_reinit;
|
||||
|
||||
c_uint8_t block_ipad[SHA384_BLOCK_SIZE];
|
||||
c_uint8_t block_opad[SHA384_BLOCK_SIZE];
|
||||
} hmac_sha384_ctx;
|
||||
|
||||
typedef struct {
|
||||
sha512_ctx ctx_inside;
|
||||
sha512_ctx ctx_outside;
|
||||
|
||||
/* for hmac_reinit */
|
||||
sha512_ctx ctx_inside_reinit;
|
||||
sha512_ctx ctx_outside_reinit;
|
||||
|
||||
c_uint8_t block_ipad[SHA512_BLOCK_SIZE];
|
||||
c_uint8_t block_opad[SHA512_BLOCK_SIZE];
|
||||
} hmac_sha512_ctx;
|
||||
|
||||
CORE_DECLARE(void) hmac_sha224_init(hmac_sha224_ctx *ctx, c_uint8_t *key,
|
||||
c_uint32_t key_size);
|
||||
CORE_DECLARE(void) hmac_sha224_reinit(hmac_sha224_ctx *ctx);
|
||||
CORE_DECLARE(void) hmac_sha224_update(hmac_sha224_ctx *ctx, c_uint8_t *message,
|
||||
c_uint32_t message_len);
|
||||
CORE_DECLARE(void) hmac_sha224_final(hmac_sha224_ctx *ctx, c_uint8_t *mac,
|
||||
c_uint32_t mac_size);
|
||||
CORE_DECLARE(void) hmac_sha224(c_uint8_t *key, c_uint32_t key_size,
|
||||
c_uint8_t *message, c_uint32_t message_len,
|
||||
c_uint8_t *mac, c_uint32_t mac_size);
|
||||
|
||||
CORE_DECLARE(void) hmac_sha256_init(hmac_sha256_ctx *ctx, c_uint8_t *key,
|
||||
c_uint32_t key_size);
|
||||
CORE_DECLARE(void) hmac_sha256_reinit(hmac_sha256_ctx *ctx);
|
||||
CORE_DECLARE(void) hmac_sha256_update(hmac_sha256_ctx *ctx, c_uint8_t *message,
|
||||
c_uint32_t message_len);
|
||||
CORE_DECLARE(void) hmac_sha256_final(hmac_sha256_ctx *ctx, c_uint8_t *mac,
|
||||
c_uint32_t mac_size);
|
||||
CORE_DECLARE(void) hmac_sha256(c_uint8_t *key, c_uint32_t key_size,
|
||||
c_uint8_t *message, c_uint32_t message_len,
|
||||
c_uint8_t *mac, c_uint32_t mac_size);
|
||||
|
||||
CORE_DECLARE(void) hmac_sha384_init(hmac_sha384_ctx *ctx, c_uint8_t *key,
|
||||
c_uint32_t key_size);
|
||||
CORE_DECLARE(void) hmac_sha384_reinit(hmac_sha384_ctx *ctx);
|
||||
CORE_DECLARE(void) hmac_sha384_update(hmac_sha384_ctx *ctx, c_uint8_t *message,
|
||||
c_uint32_t message_len);
|
||||
CORE_DECLARE(void) hmac_sha384_final(hmac_sha384_ctx *ctx, c_uint8_t *mac,
|
||||
c_uint32_t mac_size);
|
||||
CORE_DECLARE(void) hmac_sha384(c_uint8_t *key, c_uint32_t key_size,
|
||||
c_uint8_t *message, c_uint32_t message_len,
|
||||
c_uint8_t *mac, c_uint32_t mac_size);
|
||||
|
||||
CORE_DECLARE(void) hmac_sha512_init(hmac_sha512_ctx *ctx, c_uint8_t *key,
|
||||
c_uint32_t key_size);
|
||||
CORE_DECLARE(void) hmac_sha512_reinit(hmac_sha512_ctx *ctx);
|
||||
CORE_DECLARE(void) hmac_sha512_update(hmac_sha512_ctx *ctx, c_uint8_t *message,
|
||||
c_uint32_t message_len);
|
||||
CORE_DECLARE(void) hmac_sha512_final(hmac_sha512_ctx *ctx, c_uint8_t *mac,
|
||||
c_uint32_t mac_size);
|
||||
CORE_DECLARE(void) hmac_sha512(c_uint8_t *key, c_uint32_t key_size,
|
||||
c_uint8_t *message, c_uint32_t message_len,
|
||||
c_uint8_t *mac, c_uint32_t mac_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ! _CORE_HMAC_SHA2_H */
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
#ifndef CORE_SIGNAL_H
|
||||
#define CORE_SIGNAL_H
|
||||
|
||||
/**
|
||||
* @file core_signal.h
|
||||
* @brief CORE Signal Handling
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "core_errno.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @defgroup core_signal Signal Handling
|
||||
* @ingroup CORE
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if HAVE_SIGACTION
|
||||
|
||||
#if defined(DARWIN) && !defined(__cplusplus) && !defined(_ANSI_SOURCE)
|
||||
/* work around Darwin header file bugs
|
||||
* http://www.opensource.apple.com/bugs/X/BSD%20Kernel/2657228.html
|
||||
*/
|
||||
#undef SIG_DFL
|
||||
#undef SIG_IGN
|
||||
#undef SIG_ERR
|
||||
#define SIG_DFL (void (*)(int))0
|
||||
#define SIG_IGN (void (*)(int))1
|
||||
#define SIG_ERR (void (*)(int))-1
|
||||
#endif
|
||||
|
||||
/** Function prototype for signal handlers */
|
||||
typedef void core_sigfunc_t(int);
|
||||
|
||||
/**
|
||||
* Set the signal handler function for a given signal
|
||||
* @param signo The signal (eg... SIGWINCH)
|
||||
* @param func the function to get called
|
||||
*/
|
||||
CORE_DECLARE(core_sigfunc_t *) core_signal(int signo, core_sigfunc_t * func);
|
||||
|
||||
#if defined(SIG_IGN) && !defined(SIG_ERR)
|
||||
#define SIG_ERR ((core_sigfunc_t *) -1)
|
||||
#endif
|
||||
|
||||
#else /* !HAVE_SIGACTION */
|
||||
#define core_signal(a, b) signal(a, b)
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Setup the process for a single thread to be used for all signal handling.
|
||||
* @warning This must be called before any threads are created
|
||||
*/
|
||||
CORE_DECLARE(status_t) signal_init(void);
|
||||
|
||||
/**
|
||||
* Make the current thread listen for signals. This thread will loop
|
||||
* forever, calling a provided function whenever it receives a signal. That
|
||||
* functions should return 1 if the signal has been handled, 0 otherwise.
|
||||
* @param signal_handler The function to call when a signal is received
|
||||
* apr_status_t apr_signal_thread((int)(*signal_handler)(int signum))
|
||||
*/
|
||||
CORE_DECLARE(status_t) signal_thread(int(*signal_handler)(int signum));
|
||||
|
||||
/**
|
||||
* Block the delivery of a particular signal
|
||||
* @param signum The signal number
|
||||
* @return status
|
||||
*/
|
||||
CORE_DECLARE(status_t) signal_block(int signum);
|
||||
|
||||
/**
|
||||
* Enable the delivery of a particular signal
|
||||
* @param signum The signal number
|
||||
* @return status
|
||||
*/
|
||||
CORE_DECLARE(status_t) signal_unblock(int signum);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* CORE_SIGNAL_H */
|
|
@ -0,0 +1,79 @@
|
|||
#ifndef __CORE_THREAD_H__
|
||||
#define __CORE_THREAD_H__
|
||||
|
||||
#include "core.h"
|
||||
#include "core_errno.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/** Opaque Thread structure. */
|
||||
typedef c_uintptr_t thread_id;
|
||||
|
||||
/** Opaque Thread attributes structure. */
|
||||
typedef struct threadattr_t threadattr_t;
|
||||
|
||||
typedef void *(THREAD_FUNC *thread_start_t)(void*);
|
||||
|
||||
/**
|
||||
* Check if Thread Should Stop
|
||||
*/
|
||||
CORE_DECLARE(int) thread_should_stop(void);
|
||||
|
||||
/**
|
||||
* Initialize Thread
|
||||
*/
|
||||
CORE_DECLARE(status_t) thread_init(void);
|
||||
|
||||
/**
|
||||
* Finalize Thread
|
||||
*/
|
||||
CORE_DECLARE(status_t) thread_final(void);
|
||||
|
||||
/**
|
||||
* Create and initialize a new threadattr variable
|
||||
* @param new_attr The newly created threadattr.
|
||||
*/
|
||||
CORE_DECLARE(status_t) threadattr_create(threadattr_t **new_attr);
|
||||
|
||||
/**
|
||||
* Set the stack size of newly created threads.
|
||||
* @param attr The threadattr to affect
|
||||
* @param stacksize The stack size in bytes
|
||||
*/
|
||||
CORE_DECLARE(status_t) threadattr_stacksize_set(
|
||||
threadattr_t *attr, size_t stacksize);
|
||||
|
||||
/**
|
||||
* Delete and initialize a new threadattr variable
|
||||
* @param new_attr The newly created threadattr.
|
||||
*/
|
||||
CORE_DECLARE(status_t) threadattr_delete(threadattr_t *attr);
|
||||
|
||||
/**
|
||||
* Create a new thread of execution
|
||||
* @param id The newly created thread handle.
|
||||
* @param attr The threadattr to use to determine how to create the thread
|
||||
* @param func The function to start the new thread in
|
||||
* @param data Any data to be passed to the starting function
|
||||
*/
|
||||
CORE_DECLARE(status_t) thread_create(thread_id *id,
|
||||
threadattr_t *attr, thread_start_t func, void *data);
|
||||
|
||||
/**
|
||||
* Delete a new thread of execution
|
||||
* @param id The thread to delete
|
||||
*/
|
||||
CORE_DECLARE(status_t) thread_delete(thread_id id);
|
||||
|
||||
/**
|
||||
* force the current thread to yield the processor
|
||||
*/
|
||||
CORE_DECLARE(void) thread_yield(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* ! __CORE_THREAD_H__ */
|
|
@ -0,0 +1,196 @@
|
|||
#ifndef __CORE_TIME_H__
|
||||
#define __CORE_TIME_H__
|
||||
|
||||
/**
|
||||
* @file core_time.h
|
||||
* @brief CORE Time Library
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "core_errno.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @defgroup core_time Time Routines
|
||||
* @ingroup CORE
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** month names */
|
||||
CORE_DECLARE_DATA extern const char month_snames[12][4];
|
||||
/** day names */
|
||||
CORE_DECLARE_DATA extern const char day_snames[7][4];
|
||||
|
||||
/** number of microseconds since 00:00:00 january 1, 1970 UTC */
|
||||
typedef c_int64_t c_time_t;
|
||||
|
||||
/** mechanism to properly type c_time_t literals */
|
||||
#define TIME_C(val) INT64_C(val)
|
||||
|
||||
/** mechanism to properly print c_time_t values */
|
||||
#define TIME_T_FMT INT64_T_FMT
|
||||
|
||||
/** number of microseconds per second */
|
||||
#define USEC_PER_SEC TIME_C(1000000)
|
||||
|
||||
/** @return c_time_t as a second */
|
||||
#define time_sec(time) ((time) / USEC_PER_SEC)
|
||||
|
||||
/** @return c_time_t as a usec */
|
||||
#define time_usec(time) ((time) % USEC_PER_SEC)
|
||||
|
||||
/** @return c_time_t as a msec */
|
||||
#define time_msec(time) (((time) / 1000) % 1000)
|
||||
|
||||
/** @return c_time_t as a msec */
|
||||
#define time_as_msec(time) ((time) / 1000)
|
||||
|
||||
/** @return milliseconds as an c_time_t */
|
||||
#define time_from_msec(msec) ((c_time_t)(msec) * 1000)
|
||||
|
||||
/** @return seconds as an c_time_t */
|
||||
#define time_from_sec(sec) ((c_time_t)(sec) * USEC_PER_SEC)
|
||||
|
||||
/** @return a second and usec combination as an c_time_t */
|
||||
#define time_make(sec, usec) ((c_time_t)(sec) * USEC_PER_SEC \
|
||||
+ (c_time_t)(usec))
|
||||
/** @see time_exp_t */
|
||||
typedef struct time_exp_t time_exp_t;
|
||||
|
||||
/**
|
||||
* a structure similar to ANSI struct tm with the following differences:
|
||||
* - tm_usec isn't an ANSI field
|
||||
* - tm_gmtoff isn't an ANSI field (it's a bsdism)
|
||||
*/
|
||||
struct time_exp_t {
|
||||
/** microseconds past tm_sec */
|
||||
int32_t tm_usec;
|
||||
/** (0-61) seconds past tm_min */
|
||||
int32_t tm_sec;
|
||||
/** (0-59) minutes past tm_hour */
|
||||
int32_t tm_min;
|
||||
/** (0-23) hours past midnight */
|
||||
int32_t tm_hour;
|
||||
/** (1-31) day of the month */
|
||||
int32_t tm_mday;
|
||||
/** (0-11) month of the year */
|
||||
int32_t tm_mon;
|
||||
/** year since 1900 */
|
||||
int32_t tm_year;
|
||||
/** (0-6) days since sunday */
|
||||
int32_t tm_wday;
|
||||
/** (0-365) days since jan 1 */
|
||||
int32_t tm_yday;
|
||||
/** daylight saving time */
|
||||
int32_t tm_isdst;
|
||||
/** seconds east of UTC */
|
||||
int32_t tm_gmtoff;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return the current time
|
||||
*/
|
||||
CORE_DECLARE(c_time_t) time_now(void);
|
||||
|
||||
/**
|
||||
* Sleep for the specified number of micro-seconds.
|
||||
* @param t desired amount of time to sleep.
|
||||
* @warning May sleep for longer than the specified time.
|
||||
*/
|
||||
CORE_DECLARE(void) core_sleep(c_time_t t);
|
||||
|
||||
/**
|
||||
* convert an ansi time_t to an c_time_t
|
||||
* @param result the resulting c_time_t
|
||||
* @param input the time_t to convert
|
||||
*/
|
||||
CORE_DECLARE(status_t) time_ansi_put(c_time_t *result, time_t input);
|
||||
|
||||
/**
|
||||
* convert a time to its human readable components using an offset
|
||||
* from GMT
|
||||
* @param result the exploded time
|
||||
* @param input the time to explode
|
||||
* @param offs the number of seconds offset to apply
|
||||
*/
|
||||
CORE_DECLARE(status_t) time_exp_tz(time_exp_t *result,
|
||||
c_time_t input, int32_t offs);
|
||||
|
||||
/**
|
||||
* convert a time to its human readable components in GMT timezone
|
||||
* @param result the exploded time
|
||||
* @param input the time to explode
|
||||
*/
|
||||
CORE_DECLARE(status_t) time_exp_gmt(time_exp_t *result, c_time_t input);
|
||||
|
||||
/**
|
||||
* convert a time to its human readable components in local timezone
|
||||
* @param result the exploded time
|
||||
* @param input the time to explode
|
||||
*/
|
||||
CORE_DECLARE(status_t) time_exp_lt(time_exp_t *result, c_time_t input);
|
||||
|
||||
/**
|
||||
* Convert time value from human readable format to a numeric c_time_t
|
||||
* e.g. elapsed usec since epoch
|
||||
* @param result the resulting imploded time
|
||||
* @param input the input exploded time
|
||||
*/
|
||||
CORE_DECLARE(status_t) time_exp_get(c_time_t *result, time_exp_t *input);
|
||||
|
||||
/**
|
||||
* Convert time value from human readable format to a numeric c_time_t that
|
||||
* always represents GMT
|
||||
* @param result the resulting imploded time
|
||||
* @param input the input exploded time
|
||||
*/
|
||||
CORE_DECLARE(status_t) time_exp_gmt_get(c_time_t *result, time_exp_t *input);
|
||||
|
||||
/** length of a RFC822 Date */
|
||||
#define APR_RFC822_DATE_LEN (30)
|
||||
/**
|
||||
* rfc822_date formats dates in the RFC822
|
||||
* format in an efficient manner. It is a fixed length
|
||||
* format which requires the indicated amount of storage,
|
||||
* including the trailing NUL terminator.
|
||||
* @param date_str String to write to.
|
||||
* @param t the time to convert
|
||||
*/
|
||||
CORE_DECLARE(status_t) rfc822_date(char *date_str, c_time_t t);
|
||||
|
||||
/** length of a CTIME date */
|
||||
#define CTIME_LEN (25)
|
||||
/**
|
||||
* ctime formats dates in the ctime() format
|
||||
* in an efficient manner. it is a fixed length format
|
||||
* and requires the indicated amount of storage including
|
||||
* the trailing NUL terminator.
|
||||
* Unlike ANSI/ISO C ctime(), ctime() does not include
|
||||
* a \n at the end of the string.
|
||||
* @param date_str String to write to.
|
||||
* @param t the time to convert
|
||||
*/
|
||||
CORE_DECLARE(status_t) core_ctime(char *date_str, c_time_t t);
|
||||
|
||||
/**
|
||||
* formats the exploded time according to the format specified
|
||||
* @param s string to write to
|
||||
* @param retsize The length of the returned string
|
||||
* @param max The maximum length of the string
|
||||
* @param format The format for the time string
|
||||
* @param tm The time to convert
|
||||
*/
|
||||
CORE_DECLARE(status_t) core_strftime(char *s, size_t *retsize,
|
||||
size_t max, const char *format,
|
||||
time_exp_t *tm);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* ! __CORE_TIME_H__ */
|
|
@ -0,0 +1,59 @@
|
|||
#ifndef __CORE_TIMER_H__
|
||||
#define __CORE_TIMER_H__
|
||||
|
||||
#include "core.h"
|
||||
#include "core_errno.h"
|
||||
#include "core_list.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef enum _tm_type {
|
||||
TIMER_TYPE_ONE_SHOT,
|
||||
TIMER_TYPE_PERIODIC
|
||||
} tm_type_e;
|
||||
|
||||
typedef struct _tm_service_t {
|
||||
list_t active_list;
|
||||
list_t idle_list;
|
||||
/* timer basic element */
|
||||
} tm_service_t;
|
||||
|
||||
typedef c_uintptr_t tm_block_id;
|
||||
|
||||
typedef void (*expire_func_t)(
|
||||
c_uintptr_t arg1, c_uintptr_t arg2, c_uintptr_t arg3);
|
||||
|
||||
typedef struct _tm_desc_t {
|
||||
tm_type_e type;
|
||||
c_uint32_t duration;
|
||||
expire_func_t expire_func;
|
||||
c_uintptr_t arg1;
|
||||
c_uintptr_t arg2;
|
||||
c_uintptr_t arg3;
|
||||
} tm_desc_t;
|
||||
|
||||
CORE_DECLARE(status_t) tm_init(void);
|
||||
CORE_DECLARE(status_t) tm_final(void);
|
||||
|
||||
CORE_DECLARE(c_uint32_t) tm_pool_avail(void);
|
||||
|
||||
CORE_DECLARE(void) tm_service_init(tm_service_t *tm_service);
|
||||
CORE_DECLARE(status_t) tm_execute_tm_service(tm_service_t *p_tm_s);
|
||||
|
||||
CORE_DECLARE(tm_block_id) tm_create(tm_service_t *tm_service);
|
||||
CORE_DECLARE(void) tm_delete(tm_block_id id);
|
||||
CORE_DECLARE(status_t) tm_set(tm_block_id id, tm_type_e type,
|
||||
c_uint32_t duration, expire_func_t expire_func,
|
||||
c_uintptr_t arg1, c_uintptr_t arg2, c_uintptr_t arg3);
|
||||
CORE_DECLARE(status_t) tm_set_duration(tm_block_id id, c_uint32_t duration);
|
||||
CORE_DECLARE(status_t) tm_set_by_desc(tm_block_id id, tm_desc_t *desc);
|
||||
CORE_DECLARE(status_t) tm_start(tm_block_id id);
|
||||
CORE_DECLARE(status_t) tm_stop(tm_block_id id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
|
@ -0,0 +1,108 @@
|
|||
#ifndef __CORE_TLV_H__
|
||||
#define __CORE_TLV_H__
|
||||
|
||||
#include "core.h"
|
||||
#include "core_pool.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
/* UTIS project specific parameters */
|
||||
#define UPDU_IE_TYPE_1_CODE 0x01
|
||||
#define UPDU_IE_TYPE_2_CODE 0x02
|
||||
#define UPDU_IE_TYPE_3_CODE 0x00
|
||||
|
||||
#define UPDU_IE_TYPE_1_MAX_SIZE 0x40
|
||||
#define UPDU_IE_TYPE_2_MAX_SIZE 0x4000
|
||||
#define UPDU_IE_TYPE_3_MAX_SIZE 0x40000000
|
||||
|
||||
|
||||
#define TLV_MODE_UTIS 2
|
||||
#define TLV_MODE_WIFI 3
|
||||
#define TLV_MODE_WMX_R4_R6 4
|
||||
#define TLV_MODE_WMX_R1 5
|
||||
|
||||
|
||||
#define NUM_OF_TLV_NODE 100
|
||||
|
||||
/* tlv_t struncture */
|
||||
|
||||
typedef struct _tlv_t
|
||||
{
|
||||
/* for tlv management */
|
||||
struct _tlv_t* head;
|
||||
struct _tlv_t* tail; /* this is used only for head tlv_t */
|
||||
struct _tlv_t* next;
|
||||
|
||||
struct _tlv_t* parent;
|
||||
struct _tlv_t* embedded;
|
||||
|
||||
|
||||
/* tlv basic element */
|
||||
c_uint32_t type;
|
||||
c_uint32_t length;
|
||||
void* value;
|
||||
|
||||
/* can be needed in encoding tlv_t*/
|
||||
c_uint8_t buff_allocated;
|
||||
c_uint32_t buff_len;
|
||||
c_uint8_t* buff_ptr;
|
||||
c_uint8_t* buff;
|
||||
} tlv_t;
|
||||
|
||||
#define tlv_type(pTlv) pTlv->type
|
||||
#define tlv_length(pTlv) pTlv->length
|
||||
#define tlv_value(pTlv) pTlv->value
|
||||
|
||||
#define tlv_wmx_r4_r6_type(pTlv) (pTlv->type & 0x7FFF)
|
||||
#define tlv_wmx_r4_r6_tc(pTlv) (pTlv->type & 0x8000)
|
||||
#define tlv_wmx_r4_r6_set_tc(pTlv) (pTlv->type | 0x8000)
|
||||
#define tlv_wmx_r4_r6_clr_tc(pTlv) (pTlv->type & 0x7FFF)
|
||||
|
||||
|
||||
/* tlv_t pool related functions */
|
||||
CORE_DECLARE(tlv_t*) tlv_get(void);
|
||||
CORE_DECLARE(void) tlv_free(tlv_t *pTlv);
|
||||
CORE_DECLARE(void) tlv_free_all(tlv_t *rootTlv);
|
||||
|
||||
CORE_DECLARE(status_t) tlv_init(void);
|
||||
CORE_DECLARE(status_t) tlv_final(void);
|
||||
|
||||
/* tlv_t encoding functions */
|
||||
CORE_DECLARE(c_uint8_t*) tlv_write_to_buff(
|
||||
c_uint8_t *blk, c_uint32_t type, c_uint32_t length,
|
||||
c_uint8_t *value, c_uint8_t mode);
|
||||
CORE_DECLARE(tlv_t*) tlv_add(
|
||||
tlv_t *headTlv, c_uint32_t type, c_uint32_t length, c_uint8_t *value);
|
||||
CORE_DECLARE(tlv_t*) tlv_create_buff_enabled_tlv(
|
||||
c_uint8_t *buff, c_uint32_t buff_len,
|
||||
c_uint32_t type, c_uint32_t length, c_uint8_t *value);
|
||||
CORE_DECLARE(tlv_t*) tlv_embed(
|
||||
tlv_t *parent_tlv, c_uint32_t type, c_uint32_t length, c_uint8_t *value);
|
||||
CORE_DECLARE(c_uint32_t) tlv_render(
|
||||
tlv_t *rootTlv, c_uint8_t *blk, c_uint32_t length, c_uint8_t mode);
|
||||
|
||||
|
||||
/* tlv_t parsing functions */
|
||||
CORE_DECLARE(tlv_t*) tlv_parse_tlv_block(c_uint32_t length,
|
||||
c_uint8_t *blk, c_uint8_t mode);
|
||||
CORE_DECLARE(tlv_t*) tlv_parse_embedded_tlv_block(tlv_t* pTlv, c_uint8_t mode);
|
||||
|
||||
|
||||
/* tlv operation-related function */
|
||||
CORE_DECLARE(tlv_t*) tlv_find(tlv_t* pTlv, c_uint32_t type);
|
||||
CORE_DECLARE(tlv_t*) tlv_find_root(tlv_t* pTlv);
|
||||
CORE_DECLARE(c_uint32_t) tlv_pool_avail(void);
|
||||
CORE_DECLARE(c_uint32_t) tlv_calc_length(tlv_t *p_tlv, c_uint8_t mode);
|
||||
CORE_DECLARE(c_uint32_t) tlv_calc_count(tlv_t *p_tlv);
|
||||
CORE_DECLARE(c_uint8_t) tlv_value_8(tlv_t *tlv);
|
||||
CORE_DECLARE(c_uint16_t) tlv_value_16(tlv_t *tlv);
|
||||
CORE_DECLARE(c_uint32_t) tlv_value_32(tlv_t *tlv);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* !__CORE_TLV_H__ */
|
|
@ -0,0 +1,141 @@
|
|||
#ifndef __CORE_VERSION_H__
|
||||
#define __CORE_VERSION_H__
|
||||
|
||||
/**
|
||||
* @file version.h
|
||||
* @brief CORE Versioning Interface
|
||||
*
|
||||
* CORE's Version
|
||||
*
|
||||
* There are several different mechanisms for accessing the version. There
|
||||
* is a string form, and a set of numbers; in addition, there are constants
|
||||
* which can be compiled into your application, and you can query the library
|
||||
* being used for its actual version.
|
||||
*
|
||||
* Note that it is possible for an application to detect that it has been
|
||||
* compiled against a different version of CORE by use of the compile-time
|
||||
* constants and the use of the run-time query function.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* The numeric compile-time version constants. These constants are the
|
||||
* authoritative version numbers for CORE.
|
||||
*/
|
||||
|
||||
/** major version
|
||||
* Major API changes that could cause compatibility problems for older
|
||||
* programs such as structure size changes. No binary compatibility is
|
||||
* possible across a change in the major version.
|
||||
*/
|
||||
#define CORE_MAJOR_VERSION 1
|
||||
|
||||
/** minor version
|
||||
* Minor API changes that do not cause binary compatibility problems.
|
||||
* Reset to 0 when upgrading CORE_MAJOR_VERSION
|
||||
*/
|
||||
#define CORE_MINOR_VERSION 0
|
||||
|
||||
/** patch level
|
||||
* The Patch Level never includes API changes, simply bug fixes.
|
||||
* Reset to 0 when upgrading CORE_MINOR_VERSION
|
||||
*/
|
||||
#define CORE_PATCH_VERSION 0
|
||||
|
||||
/**
|
||||
* The symbol CORE_IS_DEV_VERSION is only defined for internal,
|
||||
* "development" copies of CORE. It is undefined for released versions
|
||||
* of CORE.
|
||||
*/
|
||||
#define CORE_IS_DEV_VERSION
|
||||
|
||||
/**
|
||||
* Check at compile time if the CORE version is at least a certain
|
||||
* level.
|
||||
* @param major The major version component of the version checked
|
||||
* for (e.g., the "1" of "1.3.0").
|
||||
* @param minor The minor version component of the version checked
|
||||
* for (e.g., the "3" of "1.3.0").
|
||||
* @param patch The patch level component of the version checked
|
||||
* for (e.g., the "0" of "1.3.0").
|
||||
* @remark This macro is available with CORE versions starting with
|
||||
* 1.3.0.
|
||||
*/
|
||||
#define CORE_VERSION_AT_LEAST(major,minor,patch) \
|
||||
(((major) < CORE_MAJOR_VERSION) \
|
||||
|| ((major) == CORE_MAJOR_VERSION && (minor) < CORE_MINOR_VERSION) \
|
||||
|| ((major) == CORE_MAJOR_VERSION && (minor) == CORE_MINOR_VERSION && (patch) <= CORE_PATCH_VERSION))
|
||||
|
||||
#if defined(CORE_IS_DEV_VERSION) || defined(DOXYGEN)
|
||||
/** Internal: string form of the "is dev" flag */
|
||||
#define CORE_IS_DEV_STRING "-dev"
|
||||
#else
|
||||
#define CORE_IS_DEV_STRING ""
|
||||
#endif
|
||||
|
||||
/* STRINGIFY is defined here, and also in general.h, so wrap it */
|
||||
#ifndef STRINGIFY
|
||||
/** Properly quote a value as a string in the C preprocessor */
|
||||
#define STRINGIFY(n) STRINGIFY_HELPER(n)
|
||||
/** Helper macro for STRINGIFY */
|
||||
#define STRINGIFY_HELPER(n) #n
|
||||
#endif
|
||||
|
||||
/** The formatted string of CORE's version */
|
||||
#define CORE_VERSION_STRING \
|
||||
STRINGIFY(CORE_MAJOR_VERSION) "." \
|
||||
STRINGIFY(CORE_MINOR_VERSION) "." \
|
||||
STRINGIFY(CORE_PATCH_VERSION) \
|
||||
CORE_IS_DEV_STRING
|
||||
|
||||
/** An alternative formatted string of CORE's version */
|
||||
/* macro for Win32 .rc files using numeric csv representation */
|
||||
#define CORE_VERSION_STRING_CSV CORE_MAJOR_VERSION ##, \
|
||||
##CORE_MINOR_VERSION ##, \
|
||||
##CORE_PATCH_VERSION
|
||||
|
||||
|
||||
#ifndef __CORE_VERSION_ONLY__
|
||||
|
||||
/* The C language API to access the version at run time,
|
||||
* as opposed to compile time. CORE_VERSION_ONLY may be defined
|
||||
* externally when preprocessing version.h to obtain strictly
|
||||
* the C Preprocessor macro declarations.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* The numeric version information is broken out into fields within this
|
||||
* structure.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int major; /**< major number */
|
||||
int minor; /**< minor number */
|
||||
int patch; /**< patch number */
|
||||
int is_dev; /**< is development (1 or 0) */
|
||||
} core_version_t;
|
||||
|
||||
/**
|
||||
* Return CORE's version information information in a numeric form.
|
||||
*
|
||||
* @param pvsn Pointer to a version structure for returning the version
|
||||
* information.
|
||||
*/
|
||||
CORE_DECLARE(void) core_version(core_version_t *pvsn);
|
||||
|
||||
/** Return CORE's version information as a string. */
|
||||
CORE_DECLARE(const char *) core_version_string(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* ndef CORE_VERSION_ONLY */
|
||||
|
||||
#endif /* ndef CORE_VERSION_H */
|
|
@ -0,0 +1,41 @@
|
|||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
SUBDIRS = @OSDIR@
|
||||
|
||||
noinst_LTLIBRARIES = libcore.la
|
||||
|
||||
libcore_la_SOURCES = \
|
||||
version.c \
|
||||
../include/core_aes_cmac.h ../include/core_aes.h ../include/core_cond.h \
|
||||
../include/core_debug.h ../include/core_errno.h ../include/core_file.h \
|
||||
../include/core_fsm.h ../include/core_general.h ../include/core.h \
|
||||
../include/core.h.in ../include/core_index.h ../include/core_lib.h \
|
||||
../include/core_list.h ../include/core_msgq.h ../include/core_mutex.h \
|
||||
../include/core_net.h ../include/core_param.h ../include/core_pkbuf.h \
|
||||
../include/core_pool.h ../include/core_queue.h ../include/core_ringbuf.h \
|
||||
../include/core_rwlock.h ../include/core_semaphore.h ../include/core_sha1.h \
|
||||
../include/core_sha1_hmac.h ../include/core_sha2.h ../include/core_sha2_hmac.h \
|
||||
../include/core_signal.h ../include/core_thread.h ../include/core_time.h \
|
||||
../include/core_timer.h ../include/core_tlv.h ../include/core_version.h
|
||||
|
||||
nodist_libcore_la_SOURCES = \
|
||||
debug.c fsm.c msgq.c ringbuf.c timer.c tlv.c \
|
||||
aes.c aes_cmac.c sha1.c sha1_hmac.c sha2.c sha2_hmac.c
|
||||
|
||||
libcore_la_DEPENDENCIES = \
|
||||
$(top_srcdir)/lib/core/src/@OSDIR@/libcore@OSDIR@.la
|
||||
|
||||
libcore_la_LIBADD = \
|
||||
$(top_srcdir)/lib/core/src/@OSDIR@/libcore@OSDIR@.la
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/lib/core/include/arch/@OSDIR@ \
|
||||
-I$(top_srcdir)/lib/core/include
|
||||
|
||||
AM_CFLAGS = \
|
||||
-Wall -Werror
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
MOSTLYCLEANFILES = core *.stackdump
|
||||
|
||||
EXTRA_DIST = .libs $(noinst_LTLIBRARIES)
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,272 @@
|
|||
#define TRACE_MODULE _cmac
|
||||
#include "core.h"
|
||||
#include "core_debug.h"
|
||||
#include "core_aes_cmac.h"
|
||||
|
||||
#if (AES_BLOCK_SIZE != 16)
|
||||
#error "Wrong AES block size"
|
||||
#endif
|
||||
|
||||
/* From RFC 4493
|
||||
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+ Algorithm Generate_Subkey +
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+ +
|
||||
+ Input : K (128-bit key) +
|
||||
+ Output : K1 (128-bit first subkey) +
|
||||
+ K2 (128-bit second subkey) +
|
||||
+-------------------------------------------------------------------+
|
||||
+ +
|
||||
+ Constants: const_Zero is 0x00000000000000000000000000000000 +
|
||||
+ const_Rb is 0x00000000000000000000000000000087 +
|
||||
+ Variables: L for output of AES-128 applied to 0^128 +
|
||||
+ +
|
||||
+ Step 1. L := AES-128(K, const_Zero); +
|
||||
+ Step 2. if MSB(L) is equal to 0 +
|
||||
+ then K1 := L << 1; +
|
||||
+ else K1 := (L << 1) XOR const_Rb; +
|
||||
+ Step 3. if MSB(K1) is equal to 0 +
|
||||
+ then K2 := K1 << 1; +
|
||||
+ else K2 := (K1 << 1) XOR const_Rb; +
|
||||
+ Step 4. return K1, K2; +
|
||||
+ +
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
|
||||
|
||||
static status_t _generate_subkey(c_uint8_t *k1, c_uint8_t *k2,
|
||||
const c_uint8_t *key)
|
||||
{
|
||||
c_uint8_t zero[16] = {
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
||||
};
|
||||
c_uint8_t rb[16] = {
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x87
|
||||
};
|
||||
c_uint8_t L[16];
|
||||
|
||||
c_uint32_t rk[RKLENGTH(MAX_KEY_BITS)];
|
||||
int i, nrounds;
|
||||
|
||||
/* Step 1. L := AES-128(K, const_Zero) */
|
||||
nrounds = aes_setup_enc(rk, key, 128);
|
||||
aes_encrypt(rk, nrounds, zero, L);
|
||||
|
||||
/* Step 2. if MSB(L) is equal to 0 */
|
||||
if ((L[0] & 0x80) == 0)
|
||||
{
|
||||
/* then k1 := L << 1; */
|
||||
for (i = 0; i < 15; i++)
|
||||
k1[i] = ((L[i] << 1) & 0xfe) | ((L[i + 1] & 0x80) ? 1 : 0);
|
||||
k1[15] = ((L[15] << 1) & 0xfe);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* else k1 := (L << 1) XOR const_Rb; */
|
||||
for (i = 0; i < 15; i++)
|
||||
k1[i] = (((L[i] << 1) & 0xfe) | ((L[i + 1] & 0x80) ? 1 : 0))
|
||||
^ rb[i];
|
||||
k1[15] = ((L[15] << 1) & 0xfe) ^ rb[15];
|
||||
}
|
||||
|
||||
/* Step 3. if MSB(k1) is equal to 0 */
|
||||
if ((k1[0] & 0x80) == 0)
|
||||
{
|
||||
/* then k2 := k2 << 1; */
|
||||
for (i = 0; i < 15; i++)
|
||||
k2[i] = ((k1[i] << 1) & 0xfe) | ((k1[i + 1] & 0x80) ? 1 : 0);
|
||||
k2[15] = ((k1[15] << 1) & 0xfe);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* else k2 := (k2 << 1) XOR const_Rb; */
|
||||
for (i = 0; i < 15; i++)
|
||||
k2[i] = (((k1[i] << 1) & 0xfe) | ((k1[i + 1] & 0x80) ? 1 : 0))
|
||||
^ rb[i];
|
||||
k2[15] = ((k1[15] << 1) & 0xfe) ^ rb[15];
|
||||
}
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
/* From RFC 4493
|
||||
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+ Algorithm AES-CMAC +
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+ +
|
||||
+ Input : K ( 128-bit key ) +
|
||||
+ : M ( message to be authenticated ) +
|
||||
+ : len ( length of the message in octets ) +
|
||||
+ Output : T ( message authentication code ) +
|
||||
+ +
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+ Constants: const_Zero is 0x00000000000000000000000000000000 +
|
||||
+ const_Bsize is 16 +
|
||||
+ +
|
||||
+ Variables: K1, K2 for 128-bit subkeys +
|
||||
+ M_i is the i-th block (i=1..ceil(len/const_Bsize)) +
|
||||
+ M_last is the last block xor-ed with K1 or K2 +
|
||||
+ n for number of blocks to be processed +
|
||||
+ r for number of octets of last block +
|
||||
+ flag for denoting if last block is complete or not +
|
||||
+ +
|
||||
+ Step 1. (K1,K2) := Generate_Subkey(K); +
|
||||
+ Step 2. n := ceil(len/const_Bsize); +
|
||||
+ Step 3. if n = 0 +
|
||||
+ then +
|
||||
+ n := 1; +
|
||||
+ flag := false; +
|
||||
+ else +
|
||||
+ if len mod const_Bsize is 0 +
|
||||
+ then flag := true; +
|
||||
+ else flag := false; +
|
||||
+ +
|
||||
+ Step 4. if flag is true +
|
||||
+ then M_last := M_n XOR K1; +
|
||||
+ else M_last := padding(M_n) XOR K2; +
|
||||
+ Step 5. X := const_Zero; +
|
||||
+ Step 6. for i := 1 to n-1 do +
|
||||
+ begin +
|
||||
+ Y := X XOR M_i; +
|
||||
+ X := AES-128(K,Y); +
|
||||
+ end +
|
||||
+ Y := M_last XOR X; +
|
||||
+ T := AES-128(K,Y); +
|
||||
+ Step 7. return T; +
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
|
||||
|
||||
status_t aes_cmac_calculate(c_uint8_t *cmac, const c_uint8_t *key,
|
||||
const c_uint8_t *msg, const c_uint32_t len)
|
||||
{
|
||||
c_uint8_t x[16] = {
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
||||
};
|
||||
c_uint8_t y[16], m_last[16];
|
||||
c_uint8_t k1[16], k2[16];
|
||||
int i, j, n, bs, flag;
|
||||
c_uint32_t rk[RKLENGTH(MAX_KEY_BITS)];
|
||||
int nrounds;
|
||||
|
||||
d_assert(cmac, return CORE_ERROR, "Null param");
|
||||
d_assert(key, return CORE_ERROR, "Null param");
|
||||
d_assert(msg, return CORE_ERROR, "Null param");
|
||||
|
||||
/* Step 1. (K1,K2) := Generate_Subkey(K); */
|
||||
_generate_subkey(k1, k2, key);
|
||||
|
||||
/* Step 2. n := ceil(len/const_Bsize); */
|
||||
n = (len + 15) / AES_BLOCK_SIZE;
|
||||
|
||||
/* Step 3. if n = 0
|
||||
then
|
||||
n := 1;
|
||||
flag := false;
|
||||
else
|
||||
if len mod const_Bsize is 0
|
||||
then flag := true;
|
||||
else flag := false;
|
||||
*/
|
||||
if (n == 0)
|
||||
{
|
||||
n = 1;
|
||||
flag = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (len % AES_BLOCK_SIZE == 0)
|
||||
flag = 1;
|
||||
else
|
||||
flag = 0;
|
||||
}
|
||||
|
||||
/* Step 4. if flag is true
|
||||
then M_last := M_n XOR K1;
|
||||
else M_last := padding(M_n) XOR K2;
|
||||
*/
|
||||
bs = (n - 1) * AES_BLOCK_SIZE;
|
||||
|
||||
if (flag)
|
||||
{
|
||||
for (i = 0; i < 16; i++)
|
||||
m_last[i] = msg[bs + i] ^ k1[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < len % AES_BLOCK_SIZE; i++)
|
||||
m_last[i] = msg[bs + i] ^ k2[i];
|
||||
|
||||
m_last[i] = 0x80 ^ k2[i];
|
||||
|
||||
for (i = i + 1; i < AES_BLOCK_SIZE; i++)
|
||||
m_last[i] = 0x00 ^ k2[i];
|
||||
}
|
||||
|
||||
|
||||
/* Step 5. X := const_Zero; */
|
||||
/* Step 6. for i := 1 to n-1 do
|
||||
begin
|
||||
Y := X XOR M_i;
|
||||
X := AES-128(K,Y);
|
||||
end
|
||||
Y := M_last XOR X;
|
||||
T := AES-128(K,Y);
|
||||
*/
|
||||
|
||||
nrounds = aes_setup_enc(rk, key, 128);
|
||||
|
||||
for (i = 0; i <= n - 2; i++)
|
||||
{
|
||||
bs = i * AES_BLOCK_SIZE;
|
||||
for (j = 0; j < 16; j++)
|
||||
y[j] = x[j] ^ msg[bs + j];
|
||||
aes_encrypt(rk, nrounds, y, x);
|
||||
}
|
||||
|
||||
bs = (n - 1) * AES_BLOCK_SIZE;
|
||||
for (j = 0; j < 16; j++)
|
||||
y[j] = m_last[j] ^ x[j];
|
||||
aes_encrypt(rk, nrounds, y, cmac);
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
/* From RFC 4493
|
||||
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+ Algorithm Verify_MAC +
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+ +
|
||||
+ Input : K ( 128-bit Key ) +
|
||||
+ : M ( message to be verified ) +
|
||||
+ : len ( length of the message in octets ) +
|
||||
+ : T' ( the received MAC to be verified ) +
|
||||
+ Output : INVALID or VALID +
|
||||
+ +
|
||||
+-------------------------------------------------------------------+
|
||||
+ +
|
||||
+ Step 1. T* := AES-CMAC(K,M,len); +
|
||||
+ Step 2. if T* is equal to T' +
|
||||
+ then +
|
||||
+ return VALID; +
|
||||
+ else +
|
||||
+ return INVALID; +
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
|
||||
|
||||
status_t aes_cmac_verify(c_uint8_t *cmac, const c_uint8_t *key,
|
||||
const c_uint8_t *msg, const c_uint32_t len)
|
||||
{
|
||||
status_t rv;
|
||||
c_uint8_t cmac_calc[16];
|
||||
|
||||
rv = aes_cmac_calculate(cmac_calc, key, msg, len);
|
||||
if (rv != CORE_OK)
|
||||
return rv;
|
||||
|
||||
if (memcmp(cmac_calc, cmac, 16) != 0)
|
||||
return ERR_INVALID_CMAC;
|
||||
|
||||
return CORE_OK;
|
||||
}
|
|
@ -0,0 +1,405 @@
|
|||
#include "core_debug.h"
|
||||
#include "core_param.h"
|
||||
#include "core_file.h"
|
||||
|
||||
#include <syslog.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <errno.h>
|
||||
|
||||
int g_trace_mask = 1;
|
||||
|
||||
int g_msg_to = D_MSG_TO_LOGD | D_MSG_TO_STDOUT;
|
||||
|
||||
int g_console_connected = 0;
|
||||
int g_syslog_connected = 0;
|
||||
int g_logd_connected = 0;
|
||||
|
||||
int g_log_level_console = D_LOG_LEVEL_FULL;
|
||||
int g_log_level_stdout = D_LOG_LEVEL_FULL;
|
||||
int g_log_level_syslog = D_LOG_LEVEL_FULL;
|
||||
int g_log_level_logd = D_LOG_LEVEL_FULL;
|
||||
|
||||
int g_console_fd = -1;
|
||||
int g_logd_fd = -1;
|
||||
struct sockaddr_un g_logd_addr;
|
||||
|
||||
void d_msg_init()
|
||||
{
|
||||
openlog("wmcore", 0, LOG_DAEMON);
|
||||
|
||||
g_syslog_connected = 1;
|
||||
|
||||
g_logd_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
d_assert(g_logd_fd >= 0, return,
|
||||
"socket() failed. (%d:%s)\n", errno, strerror(errno));
|
||||
|
||||
g_logd_addr.sun_family = AF_UNIX;
|
||||
strcpy(g_logd_addr.sun_path, D_LOGD_IPC_PATH);
|
||||
|
||||
g_logd_connected = 1;
|
||||
}
|
||||
|
||||
void d_msg_final()
|
||||
{
|
||||
g_syslog_connected = 0;
|
||||
closelog();
|
||||
|
||||
g_logd_connected = 0;
|
||||
close(g_logd_fd);
|
||||
g_logd_fd = -1;
|
||||
}
|
||||
|
||||
void d_msg_register_console(int console_fd)
|
||||
{
|
||||
d_assert(console_fd >= 0, return, "param 'console_fd' is invalid");
|
||||
|
||||
g_console_fd = console_fd;
|
||||
g_console_connected = 1;
|
||||
}
|
||||
|
||||
void d_msg_deregister_console()
|
||||
{
|
||||
g_console_connected = 0;
|
||||
g_console_fd = -1;
|
||||
}
|
||||
|
||||
void d_msg_to(int to, int on_off)
|
||||
{
|
||||
switch (to)
|
||||
{
|
||||
case D_MSG_TO_CONSOLE:
|
||||
g_msg_to = on_off ?
|
||||
g_msg_to | D_MSG_TO_CONSOLE :
|
||||
g_msg_to & ~D_MSG_TO_CONSOLE;
|
||||
break;
|
||||
case D_MSG_TO_STDOUT:
|
||||
g_msg_to = on_off ?
|
||||
g_msg_to | D_MSG_TO_STDOUT :
|
||||
g_msg_to & ~D_MSG_TO_STDOUT;
|
||||
break;
|
||||
case D_MSG_TO_SYSLOG:
|
||||
g_msg_to = on_off ?
|
||||
g_msg_to | D_MSG_TO_SYSLOG :
|
||||
g_msg_to & ~D_MSG_TO_SYSLOG;
|
||||
break;
|
||||
case D_MSG_TO_LOGD:
|
||||
g_msg_to = on_off ?
|
||||
g_msg_to | D_MSG_TO_LOGD :
|
||||
g_msg_to & ~D_MSG_TO_LOGD;
|
||||
break;
|
||||
case D_MSG_TO_ALL:
|
||||
g_msg_to = on_off ? D_MSG_TO_ALL : 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int d_msg_get_to()
|
||||
{
|
||||
return g_msg_to;
|
||||
}
|
||||
|
||||
void d_log_set_level(int to, int level)
|
||||
{
|
||||
switch (to)
|
||||
{
|
||||
case D_MSG_TO_CONSOLE:
|
||||
g_log_level_console = level;
|
||||
break;
|
||||
case D_MSG_TO_STDOUT:
|
||||
g_log_level_stdout = level;
|
||||
break;
|
||||
case D_MSG_TO_SYSLOG:
|
||||
g_log_level_syslog = level;
|
||||
break;
|
||||
case D_MSG_TO_LOGD:
|
||||
g_log_level_logd = level;
|
||||
break;
|
||||
case D_MSG_TO_ALL:
|
||||
g_log_level_console = level;
|
||||
g_log_level_stdout = level;
|
||||
g_log_level_syslog = level;
|
||||
g_log_level_logd = level;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int d_log_get_level(int to)
|
||||
{
|
||||
switch (to)
|
||||
{
|
||||
case D_MSG_TO_CONSOLE:
|
||||
return g_log_level_console;
|
||||
case D_MSG_TO_STDOUT:
|
||||
return g_log_level_stdout;
|
||||
case D_MSG_TO_SYSLOG:
|
||||
return g_log_level_syslog;
|
||||
case D_MSG_TO_LOGD:
|
||||
return g_log_level_logd;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void d_log_full(int to)
|
||||
{
|
||||
switch (to)
|
||||
{
|
||||
case D_MSG_TO_CONSOLE:
|
||||
g_log_level_console = D_LOG_LEVEL_FULL;
|
||||
break;
|
||||
case D_MSG_TO_STDOUT:
|
||||
g_log_level_stdout = D_LOG_LEVEL_FULL;
|
||||
break;
|
||||
case D_MSG_TO_SYSLOG:
|
||||
g_log_level_syslog = D_LOG_LEVEL_FULL;
|
||||
break;
|
||||
case D_MSG_TO_LOGD:
|
||||
g_log_level_logd = D_LOG_LEVEL_FULL;
|
||||
break;
|
||||
case D_MSG_TO_ALL:
|
||||
g_log_level_console = D_LOG_LEVEL_FULL;
|
||||
g_log_level_stdout = D_LOG_LEVEL_FULL;
|
||||
g_log_level_syslog = D_LOG_LEVEL_FULL;
|
||||
g_log_level_logd = D_LOG_LEVEL_FULL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void d_log_off(int to)
|
||||
{
|
||||
switch (to)
|
||||
{
|
||||
case D_MSG_TO_CONSOLE:
|
||||
g_log_level_console = D_LOG_LEVEL_NONE;
|
||||
break;
|
||||
case D_MSG_TO_STDOUT:
|
||||
g_log_level_stdout = D_LOG_LEVEL_NONE;
|
||||
break;
|
||||
case D_MSG_TO_SYSLOG:
|
||||
g_log_level_syslog = D_LOG_LEVEL_NONE;
|
||||
break;
|
||||
case D_MSG_TO_LOGD:
|
||||
g_log_level_logd = D_LOG_LEVEL_NONE;
|
||||
break;
|
||||
case D_MSG_TO_ALL:
|
||||
g_log_level_console = D_LOG_LEVEL_NONE;
|
||||
g_log_level_stdout = D_LOG_LEVEL_NONE;
|
||||
g_log_level_syslog = D_LOG_LEVEL_NONE;
|
||||
g_log_level_logd = D_LOG_LEVEL_NONE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void d_trace_global_on()
|
||||
{
|
||||
g_trace_mask = 1;
|
||||
}
|
||||
|
||||
void d_trace_global_off()
|
||||
{
|
||||
g_trace_mask = 0;
|
||||
}
|
||||
|
||||
void d_trace_level(int *mod_name, int level)
|
||||
{
|
||||
*mod_name = level;
|
||||
}
|
||||
|
||||
void d_trace_off(int *mod_name)
|
||||
{
|
||||
*mod_name = 0;
|
||||
}
|
||||
|
||||
#define TA_NOR "\033[0m" /* all off */
|
||||
#define TA_BOLD "\033[1m" /* bold */
|
||||
#define TA_UNDER "\033[4m" /* underscore */
|
||||
#define TA_BLINK "\033[5m" /* blink */
|
||||
#define TA_REVERSE "\033[7m" /* reverse video */
|
||||
#define TA_CONCEALED "\033[8m" /* concealed */
|
||||
|
||||
#define TA_FGC_BLACK "\033[30m" /* Black */
|
||||
#define TA_FGC_RED "\033[31m" /* Red */
|
||||
#define TA_FGC_GREEN "\033[32m" /* Green */
|
||||
#define TA_FGC_YELLOW "\033[33m" /* Yellow */
|
||||
#define TA_FGC_BLUE "\033[34m" /* Blue */
|
||||
#define TA_FGC_MAGENTA "\033[35m" /* Magenta */
|
||||
#define TA_FGC_CYAN "\033[36m" /* Cyan */
|
||||
#define TA_FGC_WHITE "\033[37m" /* White */
|
||||
#define TA_FGC_DEFAULT "\033[39m" /* default */
|
||||
|
||||
#define TA_BGC_BLACK "\033[40m" /* Black */
|
||||
#define TA_BGC_RED "\033[41m" /* Red */
|
||||
#define TA_BGC_GREEN "\033[42m" /* Green */
|
||||
#define TA_BGC_YELLOW "\033[43m" /* Yellow */
|
||||
#define TA_BGC_BLUE "\033[44m" /* Blue */
|
||||
#define TA_BGC_MAGENTA "\033[45m" /* Magenta */
|
||||
#define TA_BGC_CYAN "\033[46m" /* Cyan */
|
||||
#define TA_BGC_WHITE "\033[47m" /* White */
|
||||
#define TA_BGC_DEFAULT "\033[49m" /* default */
|
||||
|
||||
#define TIME_FMT_STR "%02d/%02d %02d:%02d:%02d.%03d"
|
||||
#define TIME_FMT_STR2 "%02d.%06d"
|
||||
#define TIME_FMT_STR3 "%04d/%02d/%02d %02d:%02d:%02d.%03d"
|
||||
|
||||
int d_msg(int tp, int lv, c_time_t t, char *fn, int ln, char *fmt, ...)
|
||||
{
|
||||
char str[384] = {0}, fstr[512] = {0}, *ac_str;
|
||||
time_exp_t te;
|
||||
size_t n;
|
||||
char *lv_str[5] = {"NONE", "FATL", "ERRR", "WARN", "INFO"};
|
||||
|
||||
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
|
||||
if (t)
|
||||
{
|
||||
time_exp_lt(&te, t);
|
||||
}
|
||||
|
||||
switch (tp)
|
||||
{
|
||||
case D_MSG_TYPE_RAW:
|
||||
{
|
||||
n = vsprintf(fstr, fmt, args);
|
||||
|
||||
if (g_msg_to & D_MSG_TO_STDOUT)
|
||||
{
|
||||
printf("%s", fstr);
|
||||
}
|
||||
if (g_syslog_connected && (g_msg_to & D_MSG_TO_SYSLOG))
|
||||
{
|
||||
syslog(LOG_DEBUG, "%s", fstr);
|
||||
}
|
||||
if (g_logd_connected && (g_msg_to & D_MSG_TO_LOGD))
|
||||
{
|
||||
sendto(g_logd_fd, fstr, n, 0,
|
||||
(struct sockaddr *)&g_logd_addr, sizeof(g_logd_addr));
|
||||
}
|
||||
if (g_console_connected && (g_msg_to & D_MSG_TO_CONSOLE))
|
||||
{
|
||||
if (fstr[n-1] == '\n')
|
||||
{
|
||||
fstr[n-1] = '\r'; fstr[n++] = '\n';
|
||||
}
|
||||
write(g_console_fd, fstr, n);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case D_MSG_TYPE_TRACE:
|
||||
{
|
||||
n = vsprintf(fstr, fmt, args);
|
||||
|
||||
if (g_msg_to & D_MSG_TO_STDOUT)
|
||||
{
|
||||
printf("%s", fstr);
|
||||
}
|
||||
if (g_syslog_connected && (g_msg_to & D_MSG_TO_SYSLOG))
|
||||
{
|
||||
syslog(LOG_DEBUG, "%s", fstr);
|
||||
}
|
||||
if (g_logd_connected && (g_msg_to & D_MSG_TO_LOGD))
|
||||
{
|
||||
sendto(g_logd_fd, fstr, n, 0,
|
||||
(struct sockaddr *)&g_logd_addr, sizeof(g_logd_addr));
|
||||
}
|
||||
if (g_console_connected && (g_msg_to & D_MSG_TO_CONSOLE))
|
||||
{
|
||||
if (fstr[n-1] == '\n')
|
||||
{
|
||||
fstr[n-1] = '\r'; fstr[n++] = '\n';
|
||||
}
|
||||
write(g_console_fd, fstr, n);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case D_MSG_TYPE_LOG:
|
||||
{
|
||||
switch(lv)
|
||||
{
|
||||
case D_LOG_LEVEL_INFO: ac_str = TA_FGC_WHITE; break;
|
||||
case D_LOG_LEVEL_WARN: ac_str = TA_FGC_CYAN; break;
|
||||
case D_LOG_LEVEL_ERROR: ac_str = TA_FGC_YELLOW; break;
|
||||
case D_LOG_LEVEL_FATAL: ac_str = TA_FGC_RED; break;
|
||||
default: ac_str = NULL; break;
|
||||
}
|
||||
|
||||
vsprintf(str, fmt, args);
|
||||
|
||||
n = sprintf(fstr, "["TIME_FMT_STR"] %s: %s (%s:%d)",
|
||||
te.tm_mon + 1, te.tm_mday, te.tm_hour,
|
||||
te.tm_min, te.tm_sec, te.tm_usec/1000,
|
||||
lv_str[lv], str, fn, ln);
|
||||
|
||||
if ((g_msg_to & D_MSG_TO_STDOUT) &&
|
||||
lv <= g_log_level_stdout)
|
||||
{
|
||||
printf("%s%s" TA_NOR "\n", ac_str, fstr);
|
||||
}
|
||||
if (g_syslog_connected && (g_msg_to & D_MSG_TO_SYSLOG) &&
|
||||
lv <= g_log_level_syslog)
|
||||
{
|
||||
syslog(LOG_INFO, "[%s\n", fstr + 13);
|
||||
}
|
||||
if (g_logd_connected && (g_msg_to & D_MSG_TO_LOGD) &&
|
||||
lv <= g_log_level_logd)
|
||||
{
|
||||
fstr[n++] = '\n';
|
||||
sendto(g_logd_fd, fstr, n, 0,
|
||||
(struct sockaddr *)&g_logd_addr, sizeof(g_logd_addr));
|
||||
}
|
||||
if (g_console_connected && (g_msg_to & D_MSG_TO_CONSOLE) &&
|
||||
lv <= g_log_level_console)
|
||||
{
|
||||
fstr[n++] = '\r'; /* fstr[n++] = '\n'; FIXME: */
|
||||
write(g_console_fd, fstr, n);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case D_MSG_TYPE_ASSERT:
|
||||
{
|
||||
vsprintf(str, fmt, args);
|
||||
|
||||
n = sprintf(fstr, "[" TIME_FMT_STR "] ASSERT: %s (%s:%d)",
|
||||
te.tm_mon + 1, te.tm_mday, te.tm_hour,
|
||||
te.tm_min, te.tm_sec, te.tm_usec/1000, str, fn, ln);
|
||||
|
||||
if (g_msg_to & D_MSG_TO_STDOUT)
|
||||
{
|
||||
printf(TA_BOLD TA_FGC_RED "%s" TA_NOR "\n", fstr);
|
||||
}
|
||||
if (g_syslog_connected && (g_msg_to & D_MSG_TO_SYSLOG))
|
||||
{
|
||||
syslog(LOG_CRIT, "[%s\n", fstr + 13);
|
||||
}
|
||||
if (g_logd_connected && (g_msg_to & D_MSG_TO_LOGD))
|
||||
{
|
||||
fstr[n++] = '\n';
|
||||
sendto(g_logd_fd, fstr, n, 0,
|
||||
(struct sockaddr *)&g_logd_addr, sizeof(g_logd_addr));
|
||||
}
|
||||
if (g_console_connected && (g_msg_to & D_MSG_TO_CONSOLE))
|
||||
{
|
||||
fstr[n++] = '\r'; /* fstr[n++] = '\n'; FIXME: */
|
||||
write(g_console_fd, fstr, n);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return CORE_OK;
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
#include "core_fsm.h"
|
||||
|
||||
static fsm_event_t fsm_event[] = {
|
||||
FSM_ENTRY_SIG,
|
||||
FSM_EXIT_SIG
|
||||
};
|
||||
|
||||
void fsm_init(fsm_t *s, fsm_event_t *e)
|
||||
{
|
||||
if (s->initial != (fsm_state_t)0)
|
||||
{
|
||||
(*s->initial)(s, e);
|
||||
if (s->initial != s->state)
|
||||
{
|
||||
(*s->state)(s, &fsm_event[FSM_ENTRY_SIG]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fsm_dispatch(fsm_t *s, fsm_event_t *e)
|
||||
{
|
||||
fsm_handler_t tmp = s->state;
|
||||
s->state = (fsm_handler_t)0;
|
||||
|
||||
(*tmp)(s, e);
|
||||
if (s->state != (fsm_state_t)0)
|
||||
{
|
||||
(*tmp)(s, &fsm_event[FSM_EXIT_SIG]);
|
||||
(*s->state)(s, &fsm_event[FSM_ENTRY_SIG]);
|
||||
}
|
||||
else
|
||||
{
|
||||
s->state = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
void fsm_final(fsm_t *s, fsm_event_t *e)
|
||||
{
|
||||
if (s->final != s->state)
|
||||
{
|
||||
(*s->state)(s, &fsm_event[FSM_EXIT_SIG]);
|
||||
}
|
||||
|
||||
if (s->final != (fsm_state_t)0)
|
||||
{
|
||||
(*s->final)(s, 0);
|
||||
}
|
||||
|
||||
s->state = s->initial;
|
||||
}
|
|
@ -0,0 +1,310 @@
|
|||
#define TRACE_MODULE _msgq
|
||||
#include "core_debug.h"
|
||||
#include "core_pool.h"
|
||||
#include "core_ringbuf.h"
|
||||
#include "core_cond.h"
|
||||
#include "core_mutex.h"
|
||||
#include "core_msgq.h"
|
||||
|
||||
typedef struct _msq_desc_t {
|
||||
mutex_id mut_c, mut_r, mut_w;
|
||||
cond_id cond;
|
||||
int opt;
|
||||
int qdepth, msgsize, used;
|
||||
rbuf_declare_ext(rbuf);
|
||||
unsigned char *pool;
|
||||
} msg_desc_t;
|
||||
|
||||
pool_declare(msgqpool, msg_desc_t, 3);
|
||||
|
||||
status_t msgq_init(void)
|
||||
{
|
||||
pool_init(&msgqpool, 3);
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t msgq_final(void)
|
||||
{
|
||||
pool_final(&msgqpool);
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
msgq_id msgq_create(int qdepth, int msgsize, int opt)
|
||||
{
|
||||
msg_desc_t *md;
|
||||
int s;
|
||||
status_t rv;
|
||||
|
||||
if (qdepth == 0 || msgsize == 0)
|
||||
return 0;
|
||||
|
||||
pool_alloc_node(&msgqpool, &md);
|
||||
d_assert(md != NULL, return 0, "empty msgq pool");
|
||||
|
||||
memset((void*)md, 0, sizeof(msg_desc_t));
|
||||
|
||||
rv = mutex_create(&md->mut_c, MUTEX_DEFAULT);
|
||||
d_assert(rv == CORE_OK,
|
||||
goto error_final, "mutex creation failed");
|
||||
|
||||
rv = mutex_create(&md->mut_r, MUTEX_DEFAULT);
|
||||
d_assert(rv == CORE_OK,
|
||||
goto error_final, "mutex creation failed");
|
||||
|
||||
rv = mutex_create(&md->mut_w, MUTEX_DEFAULT);
|
||||
d_assert(rv == CORE_OK,
|
||||
goto error_final, "mutex creation failed");
|
||||
|
||||
rv = cond_create(&md->cond);
|
||||
d_assert(rv == CORE_OK,
|
||||
goto error_final, "mutex creation failed");
|
||||
|
||||
s = qdepth * (msgsize + 2);
|
||||
md->pool = malloc(s);
|
||||
d_assert(md->pool != NULL,
|
||||
goto error_final, "can't allocate msg q buffer %d bytes", s);
|
||||
|
||||
rbuf_init_ext(&(md->rbuf), s, md->pool);
|
||||
|
||||
md->opt = opt;
|
||||
md->qdepth = qdepth;
|
||||
md->msgsize = msgsize;
|
||||
md->used = 0;
|
||||
|
||||
return (msgq_id)md;
|
||||
|
||||
error_final:
|
||||
if (md->pool) free(md->pool);
|
||||
if (md->mut_c) mutex_delete(md->mut_c);
|
||||
if (md->mut_r) mutex_delete(md->mut_r);
|
||||
if (md->mut_w) mutex_delete(md->mut_w);
|
||||
if (md->cond) cond_delete(md->cond);
|
||||
|
||||
pool_free_node(&msgqpool, md);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
status_t msgq_delete(msgq_id id)
|
||||
{
|
||||
msg_desc_t *md = (msg_desc_t*)id;
|
||||
|
||||
d_assert(md != NULL, return CORE_ERROR, "param 'id' is null");
|
||||
|
||||
if (md->pool) free(md->pool);
|
||||
if (md->mut_c) mutex_delete(md->mut_c);
|
||||
if (md->cond) cond_delete(md->cond);
|
||||
|
||||
pool_free_node(&msgqpool, md);
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
int msgq_send(msgq_id id, const char *msg, int msglen)
|
||||
{
|
||||
msg_desc_t *md = (msg_desc_t*)id;
|
||||
int n;
|
||||
unsigned short len = msglen;
|
||||
|
||||
d_assert(md != NULL, return CORE_ERROR, "param 'id' is null");
|
||||
d_assert(msg != NULL, return CORE_ERROR, "param 'msg' is null");
|
||||
d_assert(msglen <= md->msgsize, return CORE_ERROR,
|
||||
"'msglen' is bigger than the msg size of queue");
|
||||
|
||||
d_assert(md->pool != NULL, return CORE_ERROR, "msgq has no ring buffer");
|
||||
|
||||
mutex_lock(md->mut_w);
|
||||
|
||||
n = rbuf_free_bytes(&md->rbuf);
|
||||
if (n == 0)
|
||||
{
|
||||
mutex_unlock(md->mut_w);
|
||||
return CORE_EAGAIN;
|
||||
}
|
||||
|
||||
d_assert(n >= md->msgsize + 2,
|
||||
mutex_unlock(md->mut_w); return CORE_ERROR,
|
||||
"msgq integrity broken");
|
||||
|
||||
n = rbuf_write(&md->rbuf, (const char*)&len, 2);
|
||||
d_trace(2, "ring write. head:%d tail:%d size:%d len:%d\n",
|
||||
md->rbuf.h.head, md->rbuf.h.tail, md->rbuf.h.size, 2);
|
||||
d_assert(n == 2,
|
||||
mutex_unlock(md->mut_w); return CORE_ERROR,
|
||||
"msgq integrity broken n:%d", n);
|
||||
|
||||
n += rbuf_write(&md->rbuf, msg, msglen);
|
||||
d_trace(2, "ring write. head:%d tail:%d size:%d len:%d\n",
|
||||
md->rbuf.h.head, md->rbuf.h.tail, md->rbuf.h.size, msglen);
|
||||
d_assert(n == 2 + msglen,
|
||||
mutex_unlock(md->mut_w); return CORE_ERROR,
|
||||
"msgq integrity broken n:%d len:%d", n, 2 + msglen);
|
||||
|
||||
if (md->msgsize > msglen)
|
||||
{
|
||||
n += rbuf_skip_write_pos(&md->rbuf, md->msgsize - msglen);
|
||||
d_trace(2, "ring write skip. head:%d tail:%d size:%d len:%d\n",
|
||||
md->rbuf.h.head, md->rbuf.h.tail, md->rbuf.h.size,
|
||||
md->msgsize - msglen);
|
||||
}
|
||||
|
||||
d_assert(n == 2 + md->msgsize,
|
||||
mutex_unlock(md->mut_w); return CORE_ERROR,
|
||||
"msgq integrity broken n:%d", n);
|
||||
|
||||
d_trace(1, "msg (%d bytes) pushed.\n", msglen);
|
||||
|
||||
mutex_unlock(md->mut_w);
|
||||
|
||||
mutex_lock(md->mut_c);
|
||||
cond_signal(md->cond);
|
||||
mutex_unlock(md->mut_c);
|
||||
|
||||
return msglen;
|
||||
}
|
||||
|
||||
int msgq_recv(msgq_id id, char *msg, int msglen)
|
||||
{
|
||||
msg_desc_t *md = (msg_desc_t*)id;
|
||||
unsigned short len;
|
||||
int n;
|
||||
|
||||
d_assert(md != NULL, return CORE_ERROR, "param 'id' is null");
|
||||
d_assert(msg != NULL, return CORE_ERROR, "param 'msg' is null");
|
||||
d_assert(msglen >= md->msgsize, return CORE_ERROR,
|
||||
"'msglen' is smaller than msgsize");
|
||||
|
||||
d_assert(md->pool != NULL, return CORE_ERROR, "msgq has no ring buffer");
|
||||
|
||||
mutex_lock(md->mut_r);
|
||||
|
||||
n = rbuf_bytes(&md->rbuf);
|
||||
|
||||
if (!(md->opt & MSGQ_O_NONBLOCK) && (n < md->msgsize + 2))
|
||||
{
|
||||
mutex_lock(md->mut_c);
|
||||
cond_wait(md->cond, md->mut_c);
|
||||
mutex_unlock(md->mut_c);
|
||||
|
||||
n = rbuf_bytes(&md->rbuf);
|
||||
|
||||
d_assert(n >= md->msgsize + 2,
|
||||
mutex_unlock(md->mut_r); return CORE_ERROR,
|
||||
"msgq integrity broken");
|
||||
}
|
||||
else if (n < md->msgsize + 2)
|
||||
{
|
||||
mutex_unlock(md->mut_r);
|
||||
return CORE_EAGAIN;
|
||||
}
|
||||
|
||||
n = rbuf_read(&md->rbuf, (char*)&len, 2);
|
||||
d_trace(2, "ring read. head:%d tail:%d size:%d len:%d\n",
|
||||
md->rbuf.h.head, md->rbuf.h.tail, md->rbuf.h.size, 2);
|
||||
d_assert(n == 2,
|
||||
mutex_unlock(md->mut_r); return CORE_ERROR,
|
||||
"msgq integrity broken n:%d", len);
|
||||
|
||||
n += rbuf_read(&md->rbuf, msg, len);
|
||||
d_trace(2, "ring read. head:%d tail:%d size:%d len:%d\n",
|
||||
md->rbuf.h.head, md->rbuf.h.tail, md->rbuf.h.size, len);
|
||||
|
||||
d_assert(n == 2 + len,
|
||||
mutex_unlock(md->mut_r); return CORE_ERROR,
|
||||
"msgq integrity broken n:%d len:%d", n, 2 + len);
|
||||
|
||||
if (md->msgsize > len)
|
||||
{
|
||||
n += rbuf_skip_read_pos(&md->rbuf, md->msgsize - len);
|
||||
d_trace(2, "ring read skip. head:%d tail:%d size:%d len:%d\n",
|
||||
md->rbuf.h.head, md->rbuf.h.tail, md->rbuf.h.size,
|
||||
md->msgsize - len);
|
||||
}
|
||||
|
||||
d_assert(n == 2 + md->msgsize,
|
||||
mutex_unlock(md->mut_r); return CORE_ERROR,
|
||||
"msgq integrity broken n:%d s:%d r:%d",
|
||||
n, md->msgsize, len);
|
||||
|
||||
d_trace(1, "msg (%d bytes) pop.\n", len);
|
||||
|
||||
mutex_unlock(md->mut_r);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int msgq_timedrecv(msgq_id id, char *msg, int msglen, c_time_t timeout)
|
||||
{
|
||||
msg_desc_t *md = (msg_desc_t*)id;
|
||||
unsigned short len;
|
||||
int n;
|
||||
status_t rv;
|
||||
|
||||
d_assert(md != NULL, return CORE_ERROR, "param 'id' is null");
|
||||
d_assert(msg != NULL, return CORE_ERROR, "param 'msg' is null");
|
||||
d_assert(msglen >= md->msgsize, return CORE_ERROR,
|
||||
"'msglen' is smaller than msgsize");
|
||||
|
||||
d_assert(md->pool != NULL, return CORE_ERROR, "msgq has no ring buffer");
|
||||
|
||||
mutex_lock(md->mut_r);
|
||||
|
||||
n = rbuf_bytes(&md->rbuf);
|
||||
|
||||
if (!(md->opt & MSGQ_O_NONBLOCK) && (n < md->msgsize + 2))
|
||||
{
|
||||
mutex_lock(md->mut_c);
|
||||
rv = cond_timedwait(md->cond, md->mut_c, timeout);
|
||||
mutex_unlock(md->mut_c);
|
||||
|
||||
if (rv == CORE_TIMEUP)
|
||||
{
|
||||
mutex_unlock(md->mut_r);
|
||||
return CORE_TIMEUP;
|
||||
}
|
||||
|
||||
n = rbuf_bytes(&md->rbuf);
|
||||
d_assert(n >= md->msgsize + 2,
|
||||
mutex_unlock(md->mut_r); return CORE_ERROR,
|
||||
"msgq integrity broken");
|
||||
}
|
||||
else if (n < md->msgsize + 2)
|
||||
{
|
||||
mutex_unlock(md->mut_r);
|
||||
return CORE_EAGAIN;
|
||||
}
|
||||
|
||||
n = rbuf_read(&md->rbuf, (char*)&len, 2);
|
||||
d_trace(2, "ring read. head:%d tail:%d size:%d len:%d\n",
|
||||
md->rbuf.h.head, md->rbuf.h.tail, md->rbuf.h.size, 2);
|
||||
d_assert(n == 2,
|
||||
mutex_unlock(md->mut_r); return CORE_ERROR,
|
||||
"msgq integrity broken n:%d", len);
|
||||
|
||||
n += rbuf_read(&md->rbuf, msg, len);
|
||||
d_trace(2, "ring read. head:%d tail:%d size:%d len:%d\n",
|
||||
md->rbuf.h.head, md->rbuf.h.tail, md->rbuf.h.size, len);
|
||||
|
||||
d_assert(n == 2 + len,
|
||||
mutex_unlock(md->mut_r); return CORE_ERROR,
|
||||
"msgq integrity broken n:%d len:%d", n, 2 + len);
|
||||
|
||||
if (md->msgsize > len)
|
||||
{
|
||||
n += rbuf_skip_read_pos(&md->rbuf, md->msgsize - len);
|
||||
d_trace(2, "ring read skip. head:%d tail:%d size:%d len:%d\n",
|
||||
md->rbuf.h.head, md->rbuf.h.tail, md->rbuf.h.size,
|
||||
md->msgsize - len);
|
||||
}
|
||||
|
||||
d_assert(n == 2 + md->msgsize,
|
||||
mutex_unlock(md->mut_r); return CORE_ERROR,
|
||||
"msgq integrity broken n:%d s:%d r:%d",
|
||||
n, md->msgsize, len);
|
||||
|
||||
d_trace(1, "msg (%d bytes) pop.\n", len);
|
||||
|
||||
mutex_unlock(md->mut_r);
|
||||
|
||||
return len;
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
#define TRACE_MODULE _ringbuf
|
||||
#include "core_debug.h"
|
||||
#include "core_ringbuf.h"
|
||||
|
||||
#define _rbuf_bytes(__h, __t, __s) \
|
||||
(((__h) < (__t)) ? (__h) + (__s) - (__t) + 1 : (__h) - (__t))
|
||||
|
||||
#define _rbuf_free_bytes(__h, __t, __s) \
|
||||
(((__h) < (__t)) ? (__t) - (__h) - 1 : (__t) + (__s) - (__h))
|
||||
|
||||
int rbuf_bytes(void *__pname)
|
||||
{
|
||||
int h, t;
|
||||
|
||||
struct _rbuf_header_t *ptr_h = (struct _rbuf_header_t*)__pname;
|
||||
|
||||
/* Store for thread safety */
|
||||
h = ptr_h->head; t = ptr_h->tail;
|
||||
|
||||
return _rbuf_bytes(h, t, ptr_h->size);
|
||||
}
|
||||
|
||||
int rbuf_free_bytes(void *__pname)
|
||||
{
|
||||
int h, t;
|
||||
|
||||
struct _rbuf_header_t *ptr_h = (struct _rbuf_header_t*)__pname;
|
||||
|
||||
/* Store for thread safety */
|
||||
h = ptr_h->head; t = ptr_h->tail;
|
||||
|
||||
return _rbuf_free_bytes(h, t, ptr_h->size);
|
||||
}
|
||||
|
||||
#define rbuf_is_empty(__pname) ((__pname)->h.head == (__pname)->h.tail)
|
||||
|
||||
#define rbuf_is_full(__pname) (rbuf_free_bytes(__pname) == 0)
|
||||
|
||||
int rbuf_skip_write_pos(void *__pname, int __len)
|
||||
{
|
||||
/* Write operation must handle only head pointer */
|
||||
|
||||
int n, h, t;
|
||||
|
||||
struct _rbuf_header_t *ptr_h = (struct _rbuf_header_t*)__pname;
|
||||
|
||||
if (ptr_h == NULL)
|
||||
return -1;
|
||||
|
||||
t = ptr_h->tail; /* Store for thread safety with read thread */
|
||||
h = ptr_h->head;
|
||||
|
||||
/* Check available buffer size */
|
||||
n = _rbuf_free_bytes(h, t, ptr_h->size);
|
||||
/* If no space, return */
|
||||
if (n == 0)
|
||||
return -1;
|
||||
/* Determin the number of bytes to be skipped */
|
||||
n = n < __len ? n : __len;
|
||||
|
||||
/* In this function, only ptr_h->head should be updated */
|
||||
ptr_h->head = (h + n) % (ptr_h->size + 1);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int rbuf_write(void *__pname, const char *__buf, int __buf_len)
|
||||
{
|
||||
/* Write operation must handle only head pointer */
|
||||
|
||||
int n, h, t;
|
||||
|
||||
struct _rbuf_header_t *ptr_h = (struct _rbuf_header_t*)__pname;
|
||||
|
||||
if (ptr_h == NULL)
|
||||
return -1;
|
||||
|
||||
t = ptr_h->tail; /* Store for thread safety with read thread */
|
||||
h = ptr_h->head;
|
||||
|
||||
/* Check available buffer size */
|
||||
n = _rbuf_free_bytes(h, t, ptr_h->size);
|
||||
/* If no space, return */
|
||||
if (n == 0)
|
||||
return -1;
|
||||
/* Determin the number of bytes to be written */
|
||||
n = n < __buf_len ? n : __buf_len;
|
||||
|
||||
if ((t > h) || (n < ptr_h->size - h + 1))
|
||||
{
|
||||
memcpy(ptr_h->pool + h, __buf, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(ptr_h->pool + h, __buf, ptr_h->size - h + 1);
|
||||
memcpy(ptr_h->pool, __buf + (ptr_h->size - h + 1),
|
||||
n - (ptr_h->size - h + 1));
|
||||
}
|
||||
|
||||
/* In this function, only ptr_h->head should be updated */
|
||||
ptr_h->head = (h + n) % (ptr_h->size + 1);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int rbuf_skip_read_pos(void *__pname, int __len)
|
||||
{
|
||||
/* Read operation must handle only tail pointer */
|
||||
int n, h, t;
|
||||
|
||||
struct _rbuf_header_t *ptr_h = (struct _rbuf_header_t*)__pname;
|
||||
|
||||
if (ptr_h == NULL)
|
||||
return -1;
|
||||
|
||||
h = ptr_h->head; /* Store for thread safety with write thread */
|
||||
t = ptr_h->tail;
|
||||
|
||||
/* Check filled buffer size */
|
||||
n = _rbuf_bytes(h, t, ptr_h->size);
|
||||
/* If empty, return */
|
||||
if (n == 0)
|
||||
return -1;
|
||||
/* Determine the number of bytes to be skipped */
|
||||
n = n < __len ? n : __len;
|
||||
|
||||
/* In this function, only ptr_h->tail should be updated */
|
||||
ptr_h->tail = (t + n) % (ptr_h->size + 1);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int rbuf_read(void *__pname, char *__buf, int __buf_len)
|
||||
{
|
||||
/* Read operation must handle only tail pointer */
|
||||
|
||||
int n, h, t;
|
||||
|
||||
struct _rbuf_header_t *ptr_h = (struct _rbuf_header_t*)__pname;
|
||||
|
||||
if (ptr_h == NULL)
|
||||
return -1;
|
||||
|
||||
h = ptr_h->head; /* Store for thread safety with write thread */
|
||||
t = ptr_h->tail;
|
||||
|
||||
/* Check filled buffer size */
|
||||
n = _rbuf_bytes(h, t, ptr_h->size);
|
||||
/* If empty, return */
|
||||
if (n == 0)
|
||||
return -1;
|
||||
/* Determine the number of bytes to be read */
|
||||
n = n < __buf_len ? n : __buf_len;
|
||||
|
||||
if (t < h || (n < ptr_h->size - t + 1))
|
||||
{
|
||||
memcpy(__buf, ptr_h->pool + t, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(__buf, ptr_h->pool + t, ptr_h->size - t + 1);
|
||||
memcpy(__buf + (ptr_h->size - t + 1), ptr_h->pool,
|
||||
n - (ptr_h->size - t + 1));
|
||||
}
|
||||
|
||||
/* In this function, only ptr_h->tail should be updated */
|
||||
ptr_h->tail = (t + n) % (ptr_h->size + 1);
|
||||
|
||||
return n;
|
||||
}
|
|
@ -0,0 +1,404 @@
|
|||
/*
|
||||
* sha1.c
|
||||
*
|
||||
* Copyright (C) 1998, 2009
|
||||
* Paul E. Jones <paulej@packetizer.com>
|
||||
* All Rights Reserved
|
||||
*
|
||||
*****************************************************************************
|
||||
* $Id: sha1.c 12 2009-06-22 19:34:25Z paulej $
|
||||
*****************************************************************************
|
||||
*
|
||||
* Description:
|
||||
* This file implements the Secure Hashing Standard as defined
|
||||
* in FIPS PUB 180-1 published April 17, 1995.
|
||||
*
|
||||
* The Secure Hashing Standard, which uses the Secure Hashing
|
||||
* Algorithm (SHA), produces a 160-bit message digest for a
|
||||
* given data stream. In theory, it is highly improbable that
|
||||
* two messages will produce the same message digest. Therefore,
|
||||
* this algorithm can serve as a means of providing a "fingerprint"
|
||||
* for a message.
|
||||
*
|
||||
* Portability Issues:
|
||||
* SHA-1 is defined in terms of 32-bit "words". This code was
|
||||
* written with the expectation that the processor has at least
|
||||
* a 32-bit machine word size. If the machine word size is larger,
|
||||
* the code should still function properly. One caveat to that
|
||||
* is that the input functions taking characters and character
|
||||
* arrays assume that only 8 bits of information are stored in each
|
||||
* character.
|
||||
*
|
||||
* Caveats:
|
||||
* SHA-1 is designed to work with messages less than 2^64 bits
|
||||
* long. Although SHA-1 allows a message digest to be generated for
|
||||
* messages of any number of bits less than 2^64, this
|
||||
* implementation only works with messages with a length that is a
|
||||
* multiple of the size of an 8-bit character.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core_sha1.h"
|
||||
|
||||
/*
|
||||
* Define the circular shift macro
|
||||
*/
|
||||
#define SHA1CircularShift(bits,word) \
|
||||
((((word) << (bits)) & 0xFFFFFFFF) | \
|
||||
((word) >> (32-(bits))))
|
||||
|
||||
/* Function prototypes */
|
||||
static void SHA1ProcessMessageBlock(sha1_ctx *);
|
||||
static void SHA1PadMessage(sha1_ctx *);
|
||||
|
||||
/*
|
||||
* sha1_init
|
||||
*
|
||||
* Description:
|
||||
* This function will initialize the sha1_ctx in preparation
|
||||
* for computing a new message digest.
|
||||
*
|
||||
* Parameters:
|
||||
* context: [in/out]
|
||||
* The context to reset.
|
||||
*
|
||||
* Returns:
|
||||
* Nothing.
|
||||
*
|
||||
* Comments:
|
||||
*
|
||||
*/
|
||||
void sha1_init(sha1_ctx *ctx)
|
||||
{
|
||||
ctx->Length_Low = 0;
|
||||
ctx->Length_High = 0;
|
||||
ctx->Message_Block_Index = 0;
|
||||
|
||||
ctx->Message_Digest[0] = 0x67452301;
|
||||
ctx->Message_Digest[1] = 0xEFCDAB89;
|
||||
ctx->Message_Digest[2] = 0x98BADCFE;
|
||||
ctx->Message_Digest[3] = 0x10325476;
|
||||
ctx->Message_Digest[4] = 0xC3D2E1F0;
|
||||
|
||||
ctx->Computed = 0;
|
||||
ctx->Corrupted = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* sha1_final
|
||||
*
|
||||
* Description:
|
||||
* This function will return the 160-bit message digest into the
|
||||
* Message_Digest array within the sha1_ctx provided
|
||||
*
|
||||
* Parameters:
|
||||
* context: [in/out]
|
||||
* The context to use to calculate the SHA-1 hash.
|
||||
*
|
||||
* Returns:
|
||||
* 1 if successful, 0 if it failed.
|
||||
*
|
||||
* Comments:
|
||||
*
|
||||
*/
|
||||
#if 0 /* modifed by anoveth */
|
||||
void sha1_final(sha1_ctx *ctx)
|
||||
#else
|
||||
void sha1_final(sha1_ctx *ctx, c_uint8_t *digest)
|
||||
#endif
|
||||
{
|
||||
#if 0 /* blocked by anoveth */
|
||||
if (ctx->Corrupted)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!ctx->Computed)
|
||||
{
|
||||
SHA1PadMessage(ctx);
|
||||
ctx->Computed = 1;
|
||||
}
|
||||
|
||||
#if 0 /* modified by anoveth */
|
||||
return 1;
|
||||
#else
|
||||
{
|
||||
#if WORDS_BIGENDIAN
|
||||
memcpy(digest, ctx->Message_Digest, SHA1_DIGEST_SIZE);
|
||||
#else
|
||||
#define ROTR(a) ((((unsigned)(a))>>8)|((a)<<24))
|
||||
#define ROTL(a) (((a)<<8)|(((unsigned)(a))>>24))
|
||||
#define SWAP32(a) (ROTL((a)&0xff00ff00)|ROTR((a)&0x00ff00ff))
|
||||
c_uint32_t n[5];
|
||||
n[0] = SWAP32(ctx->Message_Digest[0]);
|
||||
n[1] = SWAP32(ctx->Message_Digest[1]);
|
||||
n[2] = SWAP32(ctx->Message_Digest[2]);
|
||||
n[3] = SWAP32(ctx->Message_Digest[3]);
|
||||
n[4] = SWAP32(ctx->Message_Digest[4]);
|
||||
|
||||
memcpy(digest, n, SHA1_DIGEST_SIZE);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* sha1_update
|
||||
*
|
||||
* Description:
|
||||
* This function accepts an array of octets as the next portion of
|
||||
* the message.
|
||||
*
|
||||
* Parameters:
|
||||
* context: [in/out]
|
||||
* The SHA-1 context to update
|
||||
* message_array: [in]
|
||||
* An array of characters representing the next portion of the
|
||||
* message.
|
||||
* length: [in]
|
||||
* The length of the message in message_array
|
||||
*
|
||||
* Returns:
|
||||
* Nothing.
|
||||
*
|
||||
* Comments:
|
||||
*
|
||||
*/
|
||||
void sha1_update(sha1_ctx *ctx, const c_uint8_t *message_array,
|
||||
c_uint32_t length)
|
||||
{
|
||||
if (!length)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx->Computed || ctx->Corrupted)
|
||||
{
|
||||
ctx->Corrupted = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
while(length-- && !ctx->Corrupted)
|
||||
{
|
||||
ctx->Message_Block[ctx->Message_Block_Index++] =
|
||||
(*message_array & 0xFF);
|
||||
|
||||
ctx->Length_Low += 8;
|
||||
/* Force it to 32 bits */
|
||||
ctx->Length_Low &= 0xFFFFFFFF;
|
||||
if (ctx->Length_Low == 0)
|
||||
{
|
||||
ctx->Length_High++;
|
||||
/* Force it to 32 bits */
|
||||
ctx->Length_High &= 0xFFFFFFFF;
|
||||
if (ctx->Length_High == 0)
|
||||
{
|
||||
/* Message is too long */
|
||||
ctx->Corrupted = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->Message_Block_Index == 64)
|
||||
{
|
||||
SHA1ProcessMessageBlock(ctx);
|
||||
}
|
||||
|
||||
message_array++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA1ProcessMessageBlock
|
||||
*
|
||||
* Description:
|
||||
* This function will process the next 512 bits of the message
|
||||
* stored in the Message_Block array.
|
||||
*
|
||||
* Parameters:
|
||||
* None.
|
||||
*
|
||||
* Returns:
|
||||
* Nothing.
|
||||
*
|
||||
* Comments:
|
||||
* Many of the variable names in the SHAContext, especially the
|
||||
* single character names, were used because those were the names
|
||||
* used in the publication.
|
||||
*
|
||||
*
|
||||
*/
|
||||
static void SHA1ProcessMessageBlock(sha1_ctx *ctx)
|
||||
{
|
||||
const unsigned K[] = /* Constants defined in SHA-1 */
|
||||
{
|
||||
0x5A827999,
|
||||
0x6ED9EBA1,
|
||||
0x8F1BBCDC,
|
||||
0xCA62C1D6
|
||||
};
|
||||
int t; /* Loop counter */
|
||||
unsigned temp; /* Temporary word value */
|
||||
unsigned W[80]; /* Word sequence */
|
||||
unsigned A, B, C, D, E; /* Word buffers */
|
||||
|
||||
/*
|
||||
* Initialize the first 16 words in the array W
|
||||
*/
|
||||
for(t = 0; t < 16; t++)
|
||||
{
|
||||
W[t] = ((unsigned) ctx->Message_Block[t * 4]) << 24;
|
||||
W[t] |= ((unsigned) ctx->Message_Block[t * 4 + 1]) << 16;
|
||||
W[t] |= ((unsigned) ctx->Message_Block[t * 4 + 2]) << 8;
|
||||
W[t] |= ((unsigned) ctx->Message_Block[t * 4 + 3]);
|
||||
}
|
||||
|
||||
for(t = 16; t < 80; t++)
|
||||
{
|
||||
W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
|
||||
}
|
||||
|
||||
A = ctx->Message_Digest[0];
|
||||
B = ctx->Message_Digest[1];
|
||||
C = ctx->Message_Digest[2];
|
||||
D = ctx->Message_Digest[3];
|
||||
E = ctx->Message_Digest[4];
|
||||
|
||||
for(t = 0; t < 20; t++)
|
||||
{
|
||||
temp = SHA1CircularShift(5,A) +
|
||||
((B & C) | ((~B) & D)) + E + W[t] + K[0];
|
||||
temp &= 0xFFFFFFFF;
|
||||
E = D;
|
||||
D = C;
|
||||
C = SHA1CircularShift(30,B);
|
||||
B = A;
|
||||
A = temp;
|
||||
}
|
||||
|
||||
for(t = 20; t < 40; t++)
|
||||
{
|
||||
temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
|
||||
temp &= 0xFFFFFFFF;
|
||||
E = D;
|
||||
D = C;
|
||||
C = SHA1CircularShift(30,B);
|
||||
B = A;
|
||||
A = temp;
|
||||
}
|
||||
|
||||
for(t = 40; t < 60; t++)
|
||||
{
|
||||
temp = SHA1CircularShift(5,A) +
|
||||
((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
|
||||
temp &= 0xFFFFFFFF;
|
||||
E = D;
|
||||
D = C;
|
||||
C = SHA1CircularShift(30,B);
|
||||
B = A;
|
||||
A = temp;
|
||||
}
|
||||
|
||||
for(t = 60; t < 80; t++)
|
||||
{
|
||||
temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
|
||||
temp &= 0xFFFFFFFF;
|
||||
E = D;
|
||||
D = C;
|
||||
C = SHA1CircularShift(30,B);
|
||||
B = A;
|
||||
A = temp;
|
||||
}
|
||||
|
||||
ctx->Message_Digest[0] =
|
||||
(ctx->Message_Digest[0] + A) & 0xFFFFFFFF;
|
||||
ctx->Message_Digest[1] =
|
||||
(ctx->Message_Digest[1] + B) & 0xFFFFFFFF;
|
||||
ctx->Message_Digest[2] =
|
||||
(ctx->Message_Digest[2] + C) & 0xFFFFFFFF;
|
||||
ctx->Message_Digest[3] =
|
||||
(ctx->Message_Digest[3] + D) & 0xFFFFFFFF;
|
||||
ctx->Message_Digest[4] =
|
||||
(ctx->Message_Digest[4] + E) & 0xFFFFFFFF;
|
||||
|
||||
ctx->Message_Block_Index = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA1PadMessage
|
||||
*
|
||||
* Description:
|
||||
* According to the standard, the message must be padded to an even
|
||||
* 512 bits. The first padding bit must be a '1'. The last 64
|
||||
* bits represent the length of the original message. All bits in
|
||||
* between should be 0. This function will pad the message
|
||||
* according to those rules by filling the Message_Block array
|
||||
* accordingly. It will also call SHA1ProcessMessageBlock()
|
||||
* appropriately. When it returns, it can be assumed that the
|
||||
* message digest has been computed.
|
||||
*
|
||||
* Parameters:
|
||||
* context: [in/out]
|
||||
* The context to pad
|
||||
*
|
||||
* Returns:
|
||||
* Nothing.
|
||||
*
|
||||
* Comments:
|
||||
*
|
||||
*/
|
||||
static void SHA1PadMessage(sha1_ctx *ctx)
|
||||
{
|
||||
/*
|
||||
* Check to see if the current message block is too small to hold
|
||||
* the initial padding bits and length. If so, we will pad the
|
||||
* block, process it, and then continue padding into a second
|
||||
* block.
|
||||
*/
|
||||
if (ctx->Message_Block_Index > 55)
|
||||
{
|
||||
ctx->Message_Block[ctx->Message_Block_Index++] = 0x80;
|
||||
while(ctx->Message_Block_Index < 64)
|
||||
{
|
||||
ctx->Message_Block[ctx->Message_Block_Index++] = 0;
|
||||
}
|
||||
|
||||
SHA1ProcessMessageBlock(ctx);
|
||||
|
||||
while(ctx->Message_Block_Index < 56)
|
||||
{
|
||||
ctx->Message_Block[ctx->Message_Block_Index++] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx->Message_Block[ctx->Message_Block_Index++] = 0x80;
|
||||
while(ctx->Message_Block_Index < 56)
|
||||
{
|
||||
ctx->Message_Block[ctx->Message_Block_Index++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Store the message length as the last 8 octets
|
||||
*/
|
||||
ctx->Message_Block[56] = (ctx->Length_High >> 24) & 0xFF;
|
||||
ctx->Message_Block[57] = (ctx->Length_High >> 16) & 0xFF;
|
||||
ctx->Message_Block[58] = (ctx->Length_High >> 8) & 0xFF;
|
||||
ctx->Message_Block[59] = (ctx->Length_High) & 0xFF;
|
||||
ctx->Message_Block[60] = (ctx->Length_Low >> 24) & 0xFF;
|
||||
ctx->Message_Block[61] = (ctx->Length_Low >> 16) & 0xFF;
|
||||
ctx->Message_Block[62] = (ctx->Length_Low >> 8) & 0xFF;
|
||||
ctx->Message_Block[63] = (ctx->Length_Low) & 0xFF;
|
||||
|
||||
SHA1ProcessMessageBlock(ctx);
|
||||
}
|
||||
|
||||
void sha1(const c_uint8_t *message, c_uint32_t len, c_uint8_t *digest)
|
||||
{
|
||||
sha1_ctx ctx;
|
||||
|
||||
sha1_init(&ctx);
|
||||
sha1_update(&ctx, message, len);
|
||||
sha1_final(&ctx, digest);
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
/*-
|
||||
* HMAC-SHA-224/256/384/512 implementation
|
||||
* Last update: 06/15/2005
|
||||
* Issue date: 06/15/2005
|
||||
*
|
||||
* Copyright (C) 2005 Olivier Gay <olivier.gay@a3.epfl.ch>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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 <string.h>
|
||||
|
||||
#include "core_sha1_hmac.h"
|
||||
|
||||
void hmac_sha1_init(hmac_sha1_ctx *ctx, c_uint8_t *key,
|
||||
c_uint32_t key_size)
|
||||
{
|
||||
c_uint32_t fill;
|
||||
c_uint32_t num;
|
||||
|
||||
c_uint8_t *key_used;
|
||||
c_uint8_t key_temp[SHA1_DIGEST_SIZE];
|
||||
int i;
|
||||
|
||||
if (key_size == SHA1_BLOCK_SIZE) {
|
||||
key_used = key;
|
||||
num = SHA1_BLOCK_SIZE;
|
||||
} else {
|
||||
if (key_size > SHA1_BLOCK_SIZE){
|
||||
key_used = key_temp;
|
||||
num = SHA1_DIGEST_SIZE;
|
||||
sha1(key, key_size, key_used);
|
||||
} else { /* key_size > SHA1_BLOCK_SIZE */
|
||||
key_used = key;
|
||||
num = key_size;
|
||||
}
|
||||
fill = SHA1_BLOCK_SIZE - num;
|
||||
|
||||
memset(ctx->block_ipad + num, 0x36, fill);
|
||||
memset(ctx->block_opad + num, 0x5c, fill);
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
ctx->block_ipad[i] = key_used[i] ^ 0x36;
|
||||
ctx->block_opad[i] = key_used[i] ^ 0x5c;
|
||||
}
|
||||
|
||||
sha1_init(&ctx->ctx_inside);
|
||||
sha1_update(&ctx->ctx_inside, ctx->block_ipad, SHA1_BLOCK_SIZE);
|
||||
|
||||
sha1_init(&ctx->ctx_outside);
|
||||
sha1_update(&ctx->ctx_outside, ctx->block_opad,
|
||||
SHA1_BLOCK_SIZE);
|
||||
|
||||
/* for hmac_reinit */
|
||||
memcpy(&ctx->ctx_inside_reinit, &ctx->ctx_inside,
|
||||
sizeof(sha1_ctx));
|
||||
memcpy(&ctx->ctx_outside_reinit, &ctx->ctx_outside,
|
||||
sizeof(sha1_ctx));
|
||||
}
|
||||
|
||||
void hmac_sha1_reinit(hmac_sha1_ctx *ctx)
|
||||
{
|
||||
memcpy(&ctx->ctx_inside, &ctx->ctx_inside_reinit,
|
||||
sizeof(sha1_ctx));
|
||||
memcpy(&ctx->ctx_outside, &ctx->ctx_outside_reinit,
|
||||
sizeof(sha1_ctx));
|
||||
}
|
||||
|
||||
void hmac_sha1_update(hmac_sha1_ctx *ctx, c_uint8_t *message,
|
||||
c_uint32_t message_len)
|
||||
{
|
||||
sha1_update(&ctx->ctx_inside, message, message_len);
|
||||
}
|
||||
|
||||
void hmac_sha1_final(hmac_sha1_ctx *ctx, c_uint8_t *mac,
|
||||
c_uint32_t mac_size)
|
||||
{
|
||||
c_uint8_t digest_inside[SHA1_DIGEST_SIZE];
|
||||
c_uint8_t mac_temp[SHA1_DIGEST_SIZE];
|
||||
|
||||
sha1_final(&ctx->ctx_inside, digest_inside);
|
||||
sha1_update(&ctx->ctx_outside, digest_inside, SHA1_DIGEST_SIZE);
|
||||
sha1_final(&ctx->ctx_outside, mac_temp);
|
||||
memcpy(mac, mac_temp, mac_size);
|
||||
}
|
||||
|
||||
void hmac_sha1(c_uint8_t *key, c_uint32_t key_size,
|
||||
c_uint8_t *message, c_uint32_t message_len,
|
||||
c_uint8_t *mac, c_uint32_t mac_size)
|
||||
{
|
||||
hmac_sha1_ctx ctx;
|
||||
|
||||
hmac_sha1_init(&ctx, key, key_size);
|
||||
hmac_sha1_update(&ctx, message, message_len);
|
||||
hmac_sha1_final(&ctx, mac, mac_size);
|
||||
}
|
|
@ -0,0 +1,822 @@
|
|||
/*
|
||||
* FIPS 180-2 SHA-224/256/384/512 implementation
|
||||
* Last update: 02/02/2007
|
||||
* Issue date: 04/30/2005
|
||||
*
|
||||
* Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#define UNROLL_LOOPS /* Enable loops unrolling */
|
||||
#endif
|
||||
|
||||
#define TRACE_MODULE _sha2
|
||||
#include "core_debug.h"
|
||||
#include "core_sha2.h"
|
||||
|
||||
#define SHFR(x, n) (x >> n)
|
||||
#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
|
||||
#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
|
||||
#define CH(x, y, z) ((x & y) ^ (~x & z))
|
||||
#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
|
||||
|
||||
#define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
|
||||
#define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
|
||||
#define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3))
|
||||
#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
|
||||
|
||||
#define SHA512_F1(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
|
||||
#define SHA512_F2(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
|
||||
#define SHA512_F3(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHFR(x, 7))
|
||||
#define SHA512_F4(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHFR(x, 6))
|
||||
|
||||
#define UNPACK32(x, str) \
|
||||
{ \
|
||||
*((str) + 3) = (c_uint8_t) ((x) ); \
|
||||
*((str) + 2) = (c_uint8_t) ((x) >> 8); \
|
||||
*((str) + 1) = (c_uint8_t) ((x) >> 16); \
|
||||
*((str) + 0) = (c_uint8_t) ((x) >> 24); \
|
||||
}
|
||||
|
||||
#define PACK32(str, x) \
|
||||
{ \
|
||||
*(x) = ((c_uint32_t) *((str) + 3) ) \
|
||||
| ((c_uint32_t) *((str) + 2) << 8) \
|
||||
| ((c_uint32_t) *((str) + 1) << 16) \
|
||||
| ((c_uint32_t) *((str) + 0) << 24); \
|
||||
}
|
||||
|
||||
#define UNPACK64(x, str) \
|
||||
{ \
|
||||
*((str) + 7) = (c_uint8_t) ((x) ); \
|
||||
*((str) + 6) = (c_uint8_t) ((x) >> 8); \
|
||||
*((str) + 5) = (c_uint8_t) ((x) >> 16); \
|
||||
*((str) + 4) = (c_uint8_t) ((x) >> 24); \
|
||||
*((str) + 3) = (c_uint8_t) ((x) >> 32); \
|
||||
*((str) + 2) = (c_uint8_t) ((x) >> 40); \
|
||||
*((str) + 1) = (c_uint8_t) ((x) >> 48); \
|
||||
*((str) + 0) = (c_uint8_t) ((x) >> 56); \
|
||||
}
|
||||
|
||||
#define PACK64(str, x) \
|
||||
{ \
|
||||
*(x) = ((c_uint64_t) *((str) + 7) ) \
|
||||
| ((c_uint64_t) *((str) + 6) << 8) \
|
||||
| ((c_uint64_t) *((str) + 5) << 16) \
|
||||
| ((c_uint64_t) *((str) + 4) << 24) \
|
||||
| ((c_uint64_t) *((str) + 3) << 32) \
|
||||
| ((c_uint64_t) *((str) + 2) << 40) \
|
||||
| ((c_uint64_t) *((str) + 1) << 48) \
|
||||
| ((c_uint64_t) *((str) + 0) << 56); \
|
||||
}
|
||||
|
||||
/* Macros used for loops unrolling */
|
||||
|
||||
#define SHA256_SCR(i) \
|
||||
{ \
|
||||
w[i] = SHA256_F4(w[i - 2]) + w[i - 7] \
|
||||
+ SHA256_F3(w[i - 15]) + w[i - 16]; \
|
||||
}
|
||||
|
||||
#define SHA512_SCR(i) \
|
||||
{ \
|
||||
w[i] = SHA512_F4(w[i - 2]) + w[i - 7] \
|
||||
+ SHA512_F3(w[i - 15]) + w[i - 16]; \
|
||||
}
|
||||
|
||||
#define SHA256_EXP(a, b, c, d, e, f, g, h, j) \
|
||||
{ \
|
||||
t1 = wv[h] + SHA256_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \
|
||||
+ sha256_k[j] + w[j]; \
|
||||
t2 = SHA256_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
|
||||
wv[d] += t1; \
|
||||
wv[h] = t1 + t2; \
|
||||
}
|
||||
|
||||
#define SHA512_EXP(a, b, c, d, e, f, g ,h, j) \
|
||||
{ \
|
||||
t1 = wv[h] + SHA512_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \
|
||||
+ sha512_k[j] + w[j]; \
|
||||
t2 = SHA512_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
|
||||
wv[d] += t1; \
|
||||
wv[h] = t1 + t2; \
|
||||
}
|
||||
|
||||
c_uint32_t sha224_h0[8] =
|
||||
{0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
|
||||
0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4};
|
||||
|
||||
c_uint32_t sha256_h0[8] =
|
||||
{0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
|
||||
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
|
||||
|
||||
c_uint64_t sha384_h0[8] =
|
||||
{0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL,
|
||||
0x9159015a3070dd17ULL, 0x152fecd8f70e5939ULL,
|
||||
0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL,
|
||||
0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL};
|
||||
|
||||
c_uint64_t sha512_h0[8] =
|
||||
{0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
|
||||
0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
|
||||
0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
|
||||
0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL};
|
||||
|
||||
c_uint32_t sha256_k[64] =
|
||||
{0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
||||
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
||||
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
||||
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
||||
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
||||
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
|
||||
|
||||
c_uint64_t sha512_k[80] =
|
||||
{0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
|
||||
0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
|
||||
0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
|
||||
0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
|
||||
0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
|
||||
0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
|
||||
0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
|
||||
0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
|
||||
0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
|
||||
0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
|
||||
0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
|
||||
0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
|
||||
0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
|
||||
0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
|
||||
0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
|
||||
0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
|
||||
0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
|
||||
0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
|
||||
0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
|
||||
0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
|
||||
0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
|
||||
0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
|
||||
0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
|
||||
0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
|
||||
0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
|
||||
0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
|
||||
0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
|
||||
0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
|
||||
0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
|
||||
0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
|
||||
0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
|
||||
0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
|
||||
0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
|
||||
0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
|
||||
0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
|
||||
0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
|
||||
0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
|
||||
0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
|
||||
0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
|
||||
0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL};
|
||||
|
||||
/* SHA-256 functions */
|
||||
|
||||
void sha256_transf(sha256_ctx *ctx, const c_uint8_t *message,
|
||||
c_uint32_t block_nb)
|
||||
{
|
||||
c_uint32_t w[64];
|
||||
c_uint32_t wv[8];
|
||||
c_uint32_t t1, t2;
|
||||
const c_uint8_t *sub_block;
|
||||
int i;
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
int j;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < (int) block_nb; i++) {
|
||||
sub_block = message + (i << 6);
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
for (j = 0; j < 16; j++) {
|
||||
PACK32(&sub_block[j << 2], &w[j]);
|
||||
}
|
||||
|
||||
for (j = 16; j < 64; j++) {
|
||||
SHA256_SCR(j);
|
||||
}
|
||||
|
||||
for (j = 0; j < 8; j++) {
|
||||
wv[j] = ctx->h[j];
|
||||
}
|
||||
|
||||
for (j = 0; j < 64; j++) {
|
||||
t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
|
||||
+ sha256_k[j] + w[j];
|
||||
t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
|
||||
wv[7] = wv[6];
|
||||
wv[6] = wv[5];
|
||||
wv[5] = wv[4];
|
||||
wv[4] = wv[3] + t1;
|
||||
wv[3] = wv[2];
|
||||
wv[2] = wv[1];
|
||||
wv[1] = wv[0];
|
||||
wv[0] = t1 + t2;
|
||||
}
|
||||
|
||||
for (j = 0; j < 8; j++) {
|
||||
ctx->h[j] += wv[j];
|
||||
}
|
||||
#else
|
||||
PACK32(&sub_block[ 0], &w[ 0]); PACK32(&sub_block[ 4], &w[ 1]);
|
||||
PACK32(&sub_block[ 8], &w[ 2]); PACK32(&sub_block[12], &w[ 3]);
|
||||
PACK32(&sub_block[16], &w[ 4]); PACK32(&sub_block[20], &w[ 5]);
|
||||
PACK32(&sub_block[24], &w[ 6]); PACK32(&sub_block[28], &w[ 7]);
|
||||
PACK32(&sub_block[32], &w[ 8]); PACK32(&sub_block[36], &w[ 9]);
|
||||
PACK32(&sub_block[40], &w[10]); PACK32(&sub_block[44], &w[11]);
|
||||
PACK32(&sub_block[48], &w[12]); PACK32(&sub_block[52], &w[13]);
|
||||
PACK32(&sub_block[56], &w[14]); PACK32(&sub_block[60], &w[15]);
|
||||
|
||||
SHA256_SCR(16); SHA256_SCR(17); SHA256_SCR(18); SHA256_SCR(19);
|
||||
SHA256_SCR(20); SHA256_SCR(21); SHA256_SCR(22); SHA256_SCR(23);
|
||||
SHA256_SCR(24); SHA256_SCR(25); SHA256_SCR(26); SHA256_SCR(27);
|
||||
SHA256_SCR(28); SHA256_SCR(29); SHA256_SCR(30); SHA256_SCR(31);
|
||||
SHA256_SCR(32); SHA256_SCR(33); SHA256_SCR(34); SHA256_SCR(35);
|
||||
SHA256_SCR(36); SHA256_SCR(37); SHA256_SCR(38); SHA256_SCR(39);
|
||||
SHA256_SCR(40); SHA256_SCR(41); SHA256_SCR(42); SHA256_SCR(43);
|
||||
SHA256_SCR(44); SHA256_SCR(45); SHA256_SCR(46); SHA256_SCR(47);
|
||||
SHA256_SCR(48); SHA256_SCR(49); SHA256_SCR(50); SHA256_SCR(51);
|
||||
SHA256_SCR(52); SHA256_SCR(53); SHA256_SCR(54); SHA256_SCR(55);
|
||||
SHA256_SCR(56); SHA256_SCR(57); SHA256_SCR(58); SHA256_SCR(59);
|
||||
SHA256_SCR(60); SHA256_SCR(61); SHA256_SCR(62); SHA256_SCR(63);
|
||||
|
||||
wv[0] = ctx->h[0]; wv[1] = ctx->h[1];
|
||||
wv[2] = ctx->h[2]; wv[3] = ctx->h[3];
|
||||
wv[4] = ctx->h[4]; wv[5] = ctx->h[5];
|
||||
wv[6] = ctx->h[6]; wv[7] = ctx->h[7];
|
||||
|
||||
SHA256_EXP(0,1,2,3,4,5,6,7, 0); SHA256_EXP(7,0,1,2,3,4,5,6, 1);
|
||||
SHA256_EXP(6,7,0,1,2,3,4,5, 2); SHA256_EXP(5,6,7,0,1,2,3,4, 3);
|
||||
SHA256_EXP(4,5,6,7,0,1,2,3, 4); SHA256_EXP(3,4,5,6,7,0,1,2, 5);
|
||||
SHA256_EXP(2,3,4,5,6,7,0,1, 6); SHA256_EXP(1,2,3,4,5,6,7,0, 7);
|
||||
SHA256_EXP(0,1,2,3,4,5,6,7, 8); SHA256_EXP(7,0,1,2,3,4,5,6, 9);
|
||||
SHA256_EXP(6,7,0,1,2,3,4,5,10); SHA256_EXP(5,6,7,0,1,2,3,4,11);
|
||||
SHA256_EXP(4,5,6,7,0,1,2,3,12); SHA256_EXP(3,4,5,6,7,0,1,2,13);
|
||||
SHA256_EXP(2,3,4,5,6,7,0,1,14); SHA256_EXP(1,2,3,4,5,6,7,0,15);
|
||||
SHA256_EXP(0,1,2,3,4,5,6,7,16); SHA256_EXP(7,0,1,2,3,4,5,6,17);
|
||||
SHA256_EXP(6,7,0,1,2,3,4,5,18); SHA256_EXP(5,6,7,0,1,2,3,4,19);
|
||||
SHA256_EXP(4,5,6,7,0,1,2,3,20); SHA256_EXP(3,4,5,6,7,0,1,2,21);
|
||||
SHA256_EXP(2,3,4,5,6,7,0,1,22); SHA256_EXP(1,2,3,4,5,6,7,0,23);
|
||||
SHA256_EXP(0,1,2,3,4,5,6,7,24); SHA256_EXP(7,0,1,2,3,4,5,6,25);
|
||||
SHA256_EXP(6,7,0,1,2,3,4,5,26); SHA256_EXP(5,6,7,0,1,2,3,4,27);
|
||||
SHA256_EXP(4,5,6,7,0,1,2,3,28); SHA256_EXP(3,4,5,6,7,0,1,2,29);
|
||||
SHA256_EXP(2,3,4,5,6,7,0,1,30); SHA256_EXP(1,2,3,4,5,6,7,0,31);
|
||||
SHA256_EXP(0,1,2,3,4,5,6,7,32); SHA256_EXP(7,0,1,2,3,4,5,6,33);
|
||||
SHA256_EXP(6,7,0,1,2,3,4,5,34); SHA256_EXP(5,6,7,0,1,2,3,4,35);
|
||||
SHA256_EXP(4,5,6,7,0,1,2,3,36); SHA256_EXP(3,4,5,6,7,0,1,2,37);
|
||||
SHA256_EXP(2,3,4,5,6,7,0,1,38); SHA256_EXP(1,2,3,4,5,6,7,0,39);
|
||||
SHA256_EXP(0,1,2,3,4,5,6,7,40); SHA256_EXP(7,0,1,2,3,4,5,6,41);
|
||||
SHA256_EXP(6,7,0,1,2,3,4,5,42); SHA256_EXP(5,6,7,0,1,2,3,4,43);
|
||||
SHA256_EXP(4,5,6,7,0,1,2,3,44); SHA256_EXP(3,4,5,6,7,0,1,2,45);
|
||||
SHA256_EXP(2,3,4,5,6,7,0,1,46); SHA256_EXP(1,2,3,4,5,6,7,0,47);
|
||||
SHA256_EXP(0,1,2,3,4,5,6,7,48); SHA256_EXP(7,0,1,2,3,4,5,6,49);
|
||||
SHA256_EXP(6,7,0,1,2,3,4,5,50); SHA256_EXP(5,6,7,0,1,2,3,4,51);
|
||||
SHA256_EXP(4,5,6,7,0,1,2,3,52); SHA256_EXP(3,4,5,6,7,0,1,2,53);
|
||||
SHA256_EXP(2,3,4,5,6,7,0,1,54); SHA256_EXP(1,2,3,4,5,6,7,0,55);
|
||||
SHA256_EXP(0,1,2,3,4,5,6,7,56); SHA256_EXP(7,0,1,2,3,4,5,6,57);
|
||||
SHA256_EXP(6,7,0,1,2,3,4,5,58); SHA256_EXP(5,6,7,0,1,2,3,4,59);
|
||||
SHA256_EXP(4,5,6,7,0,1,2,3,60); SHA256_EXP(3,4,5,6,7,0,1,2,61);
|
||||
SHA256_EXP(2,3,4,5,6,7,0,1,62); SHA256_EXP(1,2,3,4,5,6,7,0,63);
|
||||
|
||||
ctx->h[0] += wv[0]; ctx->h[1] += wv[1];
|
||||
ctx->h[2] += wv[2]; ctx->h[3] += wv[3];
|
||||
ctx->h[4] += wv[4]; ctx->h[5] += wv[5];
|
||||
ctx->h[6] += wv[6]; ctx->h[7] += wv[7];
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
}
|
||||
}
|
||||
|
||||
void sha256(const c_uint8_t *message, c_uint32_t len, c_uint8_t *digest)
|
||||
{
|
||||
sha256_ctx ctx;
|
||||
|
||||
sha256_init(&ctx);
|
||||
sha256_update(&ctx, message, len);
|
||||
sha256_final(&ctx, digest);
|
||||
}
|
||||
|
||||
void sha256_init(sha256_ctx *ctx)
|
||||
{
|
||||
#ifndef UNROLL_LOOPS
|
||||
int i;
|
||||
for (i = 0; i < 8; i++) {
|
||||
ctx->h[i] = sha256_h0[i];
|
||||
}
|
||||
#else
|
||||
ctx->h[0] = sha256_h0[0]; ctx->h[1] = sha256_h0[1];
|
||||
ctx->h[2] = sha256_h0[2]; ctx->h[3] = sha256_h0[3];
|
||||
ctx->h[4] = sha256_h0[4]; ctx->h[5] = sha256_h0[5];
|
||||
ctx->h[6] = sha256_h0[6]; ctx->h[7] = sha256_h0[7];
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
|
||||
ctx->len = 0;
|
||||
ctx->tot_len = 0;
|
||||
}
|
||||
|
||||
void sha256_update(sha256_ctx *ctx, const c_uint8_t *message,
|
||||
c_uint32_t len)
|
||||
{
|
||||
c_uint32_t block_nb;
|
||||
c_uint32_t new_len, rem_len, tmp_len;
|
||||
const c_uint8_t *shifted_message;
|
||||
|
||||
tmp_len = SHA256_BLOCK_SIZE - ctx->len;
|
||||
rem_len = len < tmp_len ? len : tmp_len;
|
||||
|
||||
memcpy(&ctx->block[ctx->len], message, rem_len);
|
||||
|
||||
if (ctx->len + len < SHA256_BLOCK_SIZE) {
|
||||
ctx->len += len;
|
||||
return;
|
||||
}
|
||||
|
||||
new_len = len - rem_len;
|
||||
block_nb = new_len / SHA256_BLOCK_SIZE;
|
||||
|
||||
shifted_message = message + rem_len;
|
||||
|
||||
sha256_transf(ctx, ctx->block, 1);
|
||||
sha256_transf(ctx, shifted_message, block_nb);
|
||||
|
||||
rem_len = new_len % SHA256_BLOCK_SIZE;
|
||||
|
||||
memcpy(ctx->block, &shifted_message[block_nb << 6],
|
||||
rem_len);
|
||||
|
||||
ctx->len = rem_len;
|
||||
ctx->tot_len += (block_nb + 1) << 6;
|
||||
}
|
||||
|
||||
void sha256_final(sha256_ctx *ctx, c_uint8_t *digest)
|
||||
{
|
||||
c_uint32_t block_nb;
|
||||
c_uint32_t pm_len;
|
||||
c_uint32_t len_b;
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
int i;
|
||||
#endif
|
||||
|
||||
block_nb = (1 + ((SHA256_BLOCK_SIZE - 9)
|
||||
< (ctx->len % SHA256_BLOCK_SIZE)));
|
||||
|
||||
len_b = (ctx->tot_len + ctx->len) << 3;
|
||||
pm_len = block_nb << 6;
|
||||
|
||||
memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
|
||||
ctx->block[ctx->len] = 0x80;
|
||||
UNPACK32(len_b, ctx->block + pm_len - 4);
|
||||
|
||||
sha256_transf(ctx, ctx->block, block_nb);
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
for (i = 0 ; i < 8; i++) {
|
||||
UNPACK32(ctx->h[i], &digest[i << 2]);
|
||||
}
|
||||
#else
|
||||
UNPACK32(ctx->h[0], &digest[ 0]);
|
||||
UNPACK32(ctx->h[1], &digest[ 4]);
|
||||
UNPACK32(ctx->h[2], &digest[ 8]);
|
||||
UNPACK32(ctx->h[3], &digest[12]);
|
||||
UNPACK32(ctx->h[4], &digest[16]);
|
||||
UNPACK32(ctx->h[5], &digest[20]);
|
||||
UNPACK32(ctx->h[6], &digest[24]);
|
||||
UNPACK32(ctx->h[7], &digest[28]);
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
}
|
||||
|
||||
/* SHA-512 functions */
|
||||
|
||||
void sha512_transf(sha512_ctx *ctx, const c_uint8_t *message,
|
||||
c_uint32_t block_nb)
|
||||
{
|
||||
c_uint64_t w[80];
|
||||
c_uint64_t wv[8];
|
||||
c_uint64_t t1, t2;
|
||||
const c_uint8_t *sub_block;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < (int) block_nb; i++) {
|
||||
sub_block = message + (i << 7);
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
for (j = 0; j < 16; j++) {
|
||||
PACK64(&sub_block[j << 3], &w[j]);
|
||||
}
|
||||
|
||||
for (j = 16; j < 80; j++) {
|
||||
SHA512_SCR(j);
|
||||
}
|
||||
|
||||
for (j = 0; j < 8; j++) {
|
||||
wv[j] = ctx->h[j];
|
||||
}
|
||||
|
||||
for (j = 0; j < 80; j++) {
|
||||
t1 = wv[7] + SHA512_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
|
||||
+ sha512_k[j] + w[j];
|
||||
t2 = SHA512_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
|
||||
wv[7] = wv[6];
|
||||
wv[6] = wv[5];
|
||||
wv[5] = wv[4];
|
||||
wv[4] = wv[3] + t1;
|
||||
wv[3] = wv[2];
|
||||
wv[2] = wv[1];
|
||||
wv[1] = wv[0];
|
||||
wv[0] = t1 + t2;
|
||||
}
|
||||
|
||||
for (j = 0; j < 8; j++) {
|
||||
ctx->h[j] += wv[j];
|
||||
}
|
||||
#else
|
||||
PACK64(&sub_block[ 0], &w[ 0]); PACK64(&sub_block[ 8], &w[ 1]);
|
||||
PACK64(&sub_block[ 16], &w[ 2]); PACK64(&sub_block[ 24], &w[ 3]);
|
||||
PACK64(&sub_block[ 32], &w[ 4]); PACK64(&sub_block[ 40], &w[ 5]);
|
||||
PACK64(&sub_block[ 48], &w[ 6]); PACK64(&sub_block[ 56], &w[ 7]);
|
||||
PACK64(&sub_block[ 64], &w[ 8]); PACK64(&sub_block[ 72], &w[ 9]);
|
||||
PACK64(&sub_block[ 80], &w[10]); PACK64(&sub_block[ 88], &w[11]);
|
||||
PACK64(&sub_block[ 96], &w[12]); PACK64(&sub_block[104], &w[13]);
|
||||
PACK64(&sub_block[112], &w[14]); PACK64(&sub_block[120], &w[15]);
|
||||
|
||||
SHA512_SCR(16); SHA512_SCR(17); SHA512_SCR(18); SHA512_SCR(19);
|
||||
SHA512_SCR(20); SHA512_SCR(21); SHA512_SCR(22); SHA512_SCR(23);
|
||||
SHA512_SCR(24); SHA512_SCR(25); SHA512_SCR(26); SHA512_SCR(27);
|
||||
SHA512_SCR(28); SHA512_SCR(29); SHA512_SCR(30); SHA512_SCR(31);
|
||||
SHA512_SCR(32); SHA512_SCR(33); SHA512_SCR(34); SHA512_SCR(35);
|
||||
SHA512_SCR(36); SHA512_SCR(37); SHA512_SCR(38); SHA512_SCR(39);
|
||||
SHA512_SCR(40); SHA512_SCR(41); SHA512_SCR(42); SHA512_SCR(43);
|
||||
SHA512_SCR(44); SHA512_SCR(45); SHA512_SCR(46); SHA512_SCR(47);
|
||||
SHA512_SCR(48); SHA512_SCR(49); SHA512_SCR(50); SHA512_SCR(51);
|
||||
SHA512_SCR(52); SHA512_SCR(53); SHA512_SCR(54); SHA512_SCR(55);
|
||||
SHA512_SCR(56); SHA512_SCR(57); SHA512_SCR(58); SHA512_SCR(59);
|
||||
SHA512_SCR(60); SHA512_SCR(61); SHA512_SCR(62); SHA512_SCR(63);
|
||||
SHA512_SCR(64); SHA512_SCR(65); SHA512_SCR(66); SHA512_SCR(67);
|
||||
SHA512_SCR(68); SHA512_SCR(69); SHA512_SCR(70); SHA512_SCR(71);
|
||||
SHA512_SCR(72); SHA512_SCR(73); SHA512_SCR(74); SHA512_SCR(75);
|
||||
SHA512_SCR(76); SHA512_SCR(77); SHA512_SCR(78); SHA512_SCR(79);
|
||||
|
||||
wv[0] = ctx->h[0]; wv[1] = ctx->h[1];
|
||||
wv[2] = ctx->h[2]; wv[3] = ctx->h[3];
|
||||
wv[4] = ctx->h[4]; wv[5] = ctx->h[5];
|
||||
wv[6] = ctx->h[6]; wv[7] = ctx->h[7];
|
||||
|
||||
j = 0;
|
||||
|
||||
do {
|
||||
SHA512_EXP(0,1,2,3,4,5,6,7,j); j++;
|
||||
SHA512_EXP(7,0,1,2,3,4,5,6,j); j++;
|
||||
SHA512_EXP(6,7,0,1,2,3,4,5,j); j++;
|
||||
SHA512_EXP(5,6,7,0,1,2,3,4,j); j++;
|
||||
SHA512_EXP(4,5,6,7,0,1,2,3,j); j++;
|
||||
SHA512_EXP(3,4,5,6,7,0,1,2,j); j++;
|
||||
SHA512_EXP(2,3,4,5,6,7,0,1,j); j++;
|
||||
SHA512_EXP(1,2,3,4,5,6,7,0,j); j++;
|
||||
} while (j < 80);
|
||||
|
||||
ctx->h[0] += wv[0]; ctx->h[1] += wv[1];
|
||||
ctx->h[2] += wv[2]; ctx->h[3] += wv[3];
|
||||
ctx->h[4] += wv[4]; ctx->h[5] += wv[5];
|
||||
ctx->h[6] += wv[6]; ctx->h[7] += wv[7];
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
}
|
||||
}
|
||||
|
||||
void sha512(const c_uint8_t *message, c_uint32_t len,
|
||||
c_uint8_t *digest)
|
||||
{
|
||||
sha512_ctx ctx;
|
||||
|
||||
sha512_init(&ctx);
|
||||
sha512_update(&ctx, message, len);
|
||||
sha512_final(&ctx, digest);
|
||||
}
|
||||
|
||||
void sha512_init(sha512_ctx *ctx)
|
||||
{
|
||||
#ifndef UNROLL_LOOPS
|
||||
int i;
|
||||
for (i = 0; i < 8; i++) {
|
||||
ctx->h[i] = sha512_h0[i];
|
||||
}
|
||||
#else
|
||||
ctx->h[0] = sha512_h0[0]; ctx->h[1] = sha512_h0[1];
|
||||
ctx->h[2] = sha512_h0[2]; ctx->h[3] = sha512_h0[3];
|
||||
ctx->h[4] = sha512_h0[4]; ctx->h[5] = sha512_h0[5];
|
||||
ctx->h[6] = sha512_h0[6]; ctx->h[7] = sha512_h0[7];
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
|
||||
ctx->len = 0;
|
||||
ctx->tot_len = 0;
|
||||
}
|
||||
|
||||
void sha512_update(sha512_ctx *ctx, const c_uint8_t *message,
|
||||
c_uint32_t len)
|
||||
{
|
||||
c_uint32_t block_nb;
|
||||
c_uint32_t new_len, rem_len, tmp_len;
|
||||
const c_uint8_t *shifted_message;
|
||||
|
||||
tmp_len = SHA512_BLOCK_SIZE - ctx->len;
|
||||
rem_len = len < tmp_len ? len : tmp_len;
|
||||
|
||||
memcpy(&ctx->block[ctx->len], message, rem_len);
|
||||
|
||||
if (ctx->len + len < SHA512_BLOCK_SIZE) {
|
||||
ctx->len += len;
|
||||
return;
|
||||
}
|
||||
|
||||
new_len = len - rem_len;
|
||||
block_nb = new_len / SHA512_BLOCK_SIZE;
|
||||
|
||||
shifted_message = message + rem_len;
|
||||
|
||||
sha512_transf(ctx, ctx->block, 1);
|
||||
sha512_transf(ctx, shifted_message, block_nb);
|
||||
|
||||
rem_len = new_len % SHA512_BLOCK_SIZE;
|
||||
|
||||
memcpy(ctx->block, &shifted_message[block_nb << 7],
|
||||
rem_len);
|
||||
|
||||
ctx->len = rem_len;
|
||||
ctx->tot_len += (block_nb + 1) << 7;
|
||||
}
|
||||
|
||||
void sha512_final(sha512_ctx *ctx, c_uint8_t *digest)
|
||||
{
|
||||
c_uint32_t block_nb;
|
||||
c_uint32_t pm_len;
|
||||
c_uint32_t len_b;
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
int i;
|
||||
#endif
|
||||
|
||||
block_nb = 1 + ((SHA512_BLOCK_SIZE - 17)
|
||||
< (ctx->len % SHA512_BLOCK_SIZE));
|
||||
|
||||
len_b = (ctx->tot_len + ctx->len) << 3;
|
||||
pm_len = block_nb << 7;
|
||||
|
||||
memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
|
||||
ctx->block[ctx->len] = 0x80;
|
||||
UNPACK32(len_b, ctx->block + pm_len - 4);
|
||||
|
||||
sha512_transf(ctx, ctx->block, block_nb);
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
for (i = 0 ; i < 8; i++) {
|
||||
UNPACK64(ctx->h[i], &digest[i << 3]);
|
||||
}
|
||||
#else
|
||||
UNPACK64(ctx->h[0], &digest[ 0]);
|
||||
UNPACK64(ctx->h[1], &digest[ 8]);
|
||||
UNPACK64(ctx->h[2], &digest[16]);
|
||||
UNPACK64(ctx->h[3], &digest[24]);
|
||||
UNPACK64(ctx->h[4], &digest[32]);
|
||||
UNPACK64(ctx->h[5], &digest[40]);
|
||||
UNPACK64(ctx->h[6], &digest[48]);
|
||||
UNPACK64(ctx->h[7], &digest[56]);
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
}
|
||||
|
||||
/* SHA-384 functions */
|
||||
|
||||
void sha384(const c_uint8_t *message, c_uint32_t len,
|
||||
c_uint8_t *digest)
|
||||
{
|
||||
sha384_ctx ctx;
|
||||
|
||||
sha384_init(&ctx);
|
||||
sha384_update(&ctx, message, len);
|
||||
sha384_final(&ctx, digest);
|
||||
}
|
||||
|
||||
void sha384_init(sha384_ctx *ctx)
|
||||
{
|
||||
#ifndef UNROLL_LOOPS
|
||||
int i;
|
||||
for (i = 0; i < 8; i++) {
|
||||
ctx->h[i] = sha384_h0[i];
|
||||
}
|
||||
#else
|
||||
ctx->h[0] = sha384_h0[0]; ctx->h[1] = sha384_h0[1];
|
||||
ctx->h[2] = sha384_h0[2]; ctx->h[3] = sha384_h0[3];
|
||||
ctx->h[4] = sha384_h0[4]; ctx->h[5] = sha384_h0[5];
|
||||
ctx->h[6] = sha384_h0[6]; ctx->h[7] = sha384_h0[7];
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
|
||||
ctx->len = 0;
|
||||
ctx->tot_len = 0;
|
||||
}
|
||||
|
||||
void sha384_update(sha384_ctx *ctx, const c_uint8_t *message,
|
||||
c_uint32_t len)
|
||||
{
|
||||
c_uint32_t block_nb;
|
||||
c_uint32_t new_len, rem_len, tmp_len;
|
||||
const c_uint8_t *shifted_message;
|
||||
|
||||
tmp_len = SHA384_BLOCK_SIZE - ctx->len;
|
||||
rem_len = len < tmp_len ? len : tmp_len;
|
||||
|
||||
memcpy(&ctx->block[ctx->len], message, rem_len);
|
||||
|
||||
if (ctx->len + len < SHA384_BLOCK_SIZE) {
|
||||
ctx->len += len;
|
||||
return;
|
||||
}
|
||||
|
||||
new_len = len - rem_len;
|
||||
block_nb = new_len / SHA384_BLOCK_SIZE;
|
||||
|
||||
shifted_message = message + rem_len;
|
||||
|
||||
sha512_transf(ctx, ctx->block, 1);
|
||||
sha512_transf(ctx, shifted_message, block_nb);
|
||||
|
||||
rem_len = new_len % SHA384_BLOCK_SIZE;
|
||||
|
||||
memcpy(ctx->block, &shifted_message[block_nb << 7],
|
||||
rem_len);
|
||||
|
||||
ctx->len = rem_len;
|
||||
ctx->tot_len += (block_nb + 1) << 7;
|
||||
}
|
||||
|
||||
void sha384_final(sha384_ctx *ctx, c_uint8_t *digest)
|
||||
{
|
||||
c_uint32_t block_nb;
|
||||
c_uint32_t pm_len;
|
||||
c_uint32_t len_b;
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
int i;
|
||||
#endif
|
||||
|
||||
block_nb = (1 + ((SHA384_BLOCK_SIZE - 17)
|
||||
< (ctx->len % SHA384_BLOCK_SIZE)));
|
||||
|
||||
len_b = (ctx->tot_len + ctx->len) << 3;
|
||||
pm_len = block_nb << 7;
|
||||
|
||||
memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
|
||||
ctx->block[ctx->len] = 0x80;
|
||||
UNPACK32(len_b, ctx->block + pm_len - 4);
|
||||
|
||||
sha512_transf(ctx, ctx->block, block_nb);
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
for (i = 0 ; i < 6; i++) {
|
||||
UNPACK64(ctx->h[i], &digest[i << 3]);
|
||||
}
|
||||
#else
|
||||
UNPACK64(ctx->h[0], &digest[ 0]);
|
||||
UNPACK64(ctx->h[1], &digest[ 8]);
|
||||
UNPACK64(ctx->h[2], &digest[16]);
|
||||
UNPACK64(ctx->h[3], &digest[24]);
|
||||
UNPACK64(ctx->h[4], &digest[32]);
|
||||
UNPACK64(ctx->h[5], &digest[40]);
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
}
|
||||
|
||||
/* SHA-224 functions */
|
||||
|
||||
void sha224(const c_uint8_t *message, c_uint32_t len,
|
||||
c_uint8_t *digest)
|
||||
{
|
||||
sha224_ctx ctx;
|
||||
|
||||
sha224_init(&ctx);
|
||||
sha224_update(&ctx, message, len);
|
||||
sha224_final(&ctx, digest);
|
||||
}
|
||||
|
||||
void sha224_init(sha224_ctx *ctx)
|
||||
{
|
||||
#ifndef UNROLL_LOOPS
|
||||
int i;
|
||||
for (i = 0; i < 8; i++) {
|
||||
ctx->h[i] = sha224_h0[i];
|
||||
}
|
||||
#else
|
||||
ctx->h[0] = sha224_h0[0]; ctx->h[1] = sha224_h0[1];
|
||||
ctx->h[2] = sha224_h0[2]; ctx->h[3] = sha224_h0[3];
|
||||
ctx->h[4] = sha224_h0[4]; ctx->h[5] = sha224_h0[5];
|
||||
ctx->h[6] = sha224_h0[6]; ctx->h[7] = sha224_h0[7];
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
|
||||
ctx->len = 0;
|
||||
ctx->tot_len = 0;
|
||||
}
|
||||
|
||||
void sha224_update(sha224_ctx *ctx, const c_uint8_t *message,
|
||||
c_uint32_t len)
|
||||
{
|
||||
c_uint32_t block_nb;
|
||||
c_uint32_t new_len, rem_len, tmp_len;
|
||||
const c_uint8_t *shifted_message;
|
||||
|
||||
tmp_len = SHA224_BLOCK_SIZE - ctx->len;
|
||||
rem_len = len < tmp_len ? len : tmp_len;
|
||||
|
||||
memcpy(&ctx->block[ctx->len], message, rem_len);
|
||||
|
||||
if (ctx->len + len < SHA224_BLOCK_SIZE) {
|
||||
ctx->len += len;
|
||||
return;
|
||||
}
|
||||
|
||||
new_len = len - rem_len;
|
||||
block_nb = new_len / SHA224_BLOCK_SIZE;
|
||||
|
||||
shifted_message = message + rem_len;
|
||||
|
||||
sha256_transf(ctx, ctx->block, 1);
|
||||
sha256_transf(ctx, shifted_message, block_nb);
|
||||
|
||||
rem_len = new_len % SHA224_BLOCK_SIZE;
|
||||
|
||||
memcpy(ctx->block, &shifted_message[block_nb << 6],
|
||||
rem_len);
|
||||
|
||||
ctx->len = rem_len;
|
||||
ctx->tot_len += (block_nb + 1) << 6;
|
||||
}
|
||||
|
||||
void sha224_final(sha224_ctx *ctx, c_uint8_t *digest)
|
||||
{
|
||||
c_uint32_t block_nb;
|
||||
c_uint32_t pm_len;
|
||||
c_uint32_t len_b;
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
int i;
|
||||
#endif
|
||||
|
||||
block_nb = (1 + ((SHA224_BLOCK_SIZE - 9)
|
||||
< (ctx->len % SHA224_BLOCK_SIZE)));
|
||||
|
||||
len_b = (ctx->tot_len + ctx->len) << 3;
|
||||
pm_len = block_nb << 6;
|
||||
|
||||
memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
|
||||
ctx->block[ctx->len] = 0x80;
|
||||
UNPACK32(len_b, ctx->block + pm_len - 4);
|
||||
|
||||
sha256_transf(ctx, ctx->block, block_nb);
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
for (i = 0 ; i < 7; i++) {
|
||||
UNPACK32(ctx->h[i], &digest[i << 2]);
|
||||
}
|
||||
#else
|
||||
UNPACK32(ctx->h[0], &digest[ 0]);
|
||||
UNPACK32(ctx->h[1], &digest[ 4]);
|
||||
UNPACK32(ctx->h[2], &digest[ 8]);
|
||||
UNPACK32(ctx->h[3], &digest[12]);
|
||||
UNPACK32(ctx->h[4], &digest[16]);
|
||||
UNPACK32(ctx->h[5], &digest[20]);
|
||||
UNPACK32(ctx->h[6], &digest[24]);
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
}
|
|
@ -0,0 +1,380 @@
|
|||
/*-
|
||||
* HMAC-SHA-224/256/384/512 implementation
|
||||
* Last update: 06/15/2005
|
||||
* Issue date: 06/15/2005
|
||||
*
|
||||
* Copyright (C) 2005 Olivier Gay <olivier.gay@a3.epfl.ch>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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 <string.h>
|
||||
|
||||
#include "core_sha2_hmac.h"
|
||||
|
||||
/* HMAC-SHA-224 functions */
|
||||
|
||||
void hmac_sha224_init(hmac_sha224_ctx *ctx, c_uint8_t *key,
|
||||
c_uint32_t key_size)
|
||||
{
|
||||
c_uint32_t fill;
|
||||
c_uint32_t num;
|
||||
|
||||
c_uint8_t *key_used;
|
||||
c_uint8_t key_temp[SHA224_DIGEST_SIZE];
|
||||
int i;
|
||||
|
||||
if (key_size == SHA224_BLOCK_SIZE) {
|
||||
key_used = key;
|
||||
num = SHA224_BLOCK_SIZE;
|
||||
} else {
|
||||
if (key_size > SHA224_BLOCK_SIZE){
|
||||
key_used = key_temp;
|
||||
num = SHA224_DIGEST_SIZE;
|
||||
sha224(key, key_size, key_used);
|
||||
} else { /* key_size > SHA224_BLOCK_SIZE */
|
||||
key_used = key;
|
||||
num = key_size;
|
||||
}
|
||||
fill = SHA224_BLOCK_SIZE - num;
|
||||
|
||||
memset(ctx->block_ipad + num, 0x36, fill);
|
||||
memset(ctx->block_opad + num, 0x5c, fill);
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
ctx->block_ipad[i] = key_used[i] ^ 0x36;
|
||||
ctx->block_opad[i] = key_used[i] ^ 0x5c;
|
||||
}
|
||||
|
||||
sha224_init(&ctx->ctx_inside);
|
||||
sha224_update(&ctx->ctx_inside, ctx->block_ipad, SHA224_BLOCK_SIZE);
|
||||
|
||||
sha224_init(&ctx->ctx_outside);
|
||||
sha224_update(&ctx->ctx_outside, ctx->block_opad,
|
||||
SHA224_BLOCK_SIZE);
|
||||
|
||||
/* for hmac_reinit */
|
||||
memcpy(&ctx->ctx_inside_reinit, &ctx->ctx_inside,
|
||||
sizeof(sha224_ctx));
|
||||
memcpy(&ctx->ctx_outside_reinit, &ctx->ctx_outside,
|
||||
sizeof(sha224_ctx));
|
||||
}
|
||||
|
||||
void hmac_sha224_reinit(hmac_sha224_ctx *ctx)
|
||||
{
|
||||
memcpy(&ctx->ctx_inside, &ctx->ctx_inside_reinit,
|
||||
sizeof(sha224_ctx));
|
||||
memcpy(&ctx->ctx_outside, &ctx->ctx_outside_reinit,
|
||||
sizeof(sha224_ctx));
|
||||
}
|
||||
|
||||
void hmac_sha224_update(hmac_sha224_ctx *ctx, c_uint8_t *message,
|
||||
c_uint32_t message_len)
|
||||
{
|
||||
sha224_update(&ctx->ctx_inside, message, message_len);
|
||||
}
|
||||
|
||||
void hmac_sha224_final(hmac_sha224_ctx *ctx, c_uint8_t *mac,
|
||||
c_uint32_t mac_size)
|
||||
{
|
||||
c_uint8_t digest_inside[SHA224_DIGEST_SIZE];
|
||||
c_uint8_t mac_temp[SHA224_DIGEST_SIZE];
|
||||
|
||||
sha224_final(&ctx->ctx_inside, digest_inside);
|
||||
sha224_update(&ctx->ctx_outside, digest_inside, SHA224_DIGEST_SIZE);
|
||||
sha224_final(&ctx->ctx_outside, mac_temp);
|
||||
memcpy(mac, mac_temp, mac_size);
|
||||
}
|
||||
|
||||
void hmac_sha224(c_uint8_t *key, c_uint32_t key_size,
|
||||
c_uint8_t *message, c_uint32_t message_len,
|
||||
c_uint8_t *mac, c_uint32_t mac_size)
|
||||
{
|
||||
hmac_sha224_ctx ctx;
|
||||
|
||||
hmac_sha224_init(&ctx, key, key_size);
|
||||
hmac_sha224_update(&ctx, message, message_len);
|
||||
hmac_sha224_final(&ctx, mac, mac_size);
|
||||
}
|
||||
|
||||
/* HMAC-SHA-256 functions */
|
||||
|
||||
void hmac_sha256_init(hmac_sha256_ctx *ctx, c_uint8_t *key,
|
||||
c_uint32_t key_size)
|
||||
{
|
||||
c_uint32_t fill;
|
||||
c_uint32_t num;
|
||||
|
||||
c_uint8_t *key_used;
|
||||
c_uint8_t key_temp[SHA256_DIGEST_SIZE];
|
||||
int i;
|
||||
|
||||
if (key_size == SHA256_BLOCK_SIZE) {
|
||||
key_used = key;
|
||||
num = SHA256_BLOCK_SIZE;
|
||||
} else {
|
||||
if (key_size > SHA256_BLOCK_SIZE){
|
||||
key_used = key_temp;
|
||||
num = SHA256_DIGEST_SIZE;
|
||||
sha256(key, key_size, key_used);
|
||||
} else { /* key_size > SHA256_BLOCK_SIZE */
|
||||
key_used = key;
|
||||
num = key_size;
|
||||
}
|
||||
fill = SHA256_BLOCK_SIZE - num;
|
||||
|
||||
memset(ctx->block_ipad + num, 0x36, fill);
|
||||
memset(ctx->block_opad + num, 0x5c, fill);
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
ctx->block_ipad[i] = key_used[i] ^ 0x36;
|
||||
ctx->block_opad[i] = key_used[i] ^ 0x5c;
|
||||
}
|
||||
|
||||
sha256_init(&ctx->ctx_inside);
|
||||
sha256_update(&ctx->ctx_inside, ctx->block_ipad, SHA256_BLOCK_SIZE);
|
||||
|
||||
sha256_init(&ctx->ctx_outside);
|
||||
sha256_update(&ctx->ctx_outside, ctx->block_opad,
|
||||
SHA256_BLOCK_SIZE);
|
||||
|
||||
/* for hmac_reinit */
|
||||
memcpy(&ctx->ctx_inside_reinit, &ctx->ctx_inside,
|
||||
sizeof(sha256_ctx));
|
||||
memcpy(&ctx->ctx_outside_reinit, &ctx->ctx_outside,
|
||||
sizeof(sha256_ctx));
|
||||
}
|
||||
|
||||
void hmac_sha256_reinit(hmac_sha256_ctx *ctx)
|
||||
{
|
||||
memcpy(&ctx->ctx_inside, &ctx->ctx_inside_reinit,
|
||||
sizeof(sha256_ctx));
|
||||
memcpy(&ctx->ctx_outside, &ctx->ctx_outside_reinit,
|
||||
sizeof(sha256_ctx));
|
||||
}
|
||||
|
||||
void hmac_sha256_update(hmac_sha256_ctx *ctx, c_uint8_t *message,
|
||||
c_uint32_t message_len)
|
||||
{
|
||||
sha256_update(&ctx->ctx_inside, message, message_len);
|
||||
}
|
||||
|
||||
void hmac_sha256_final(hmac_sha256_ctx *ctx, c_uint8_t *mac,
|
||||
c_uint32_t mac_size)
|
||||
{
|
||||
c_uint8_t digest_inside[SHA256_DIGEST_SIZE];
|
||||
c_uint8_t mac_temp[SHA256_DIGEST_SIZE];
|
||||
|
||||
sha256_final(&ctx->ctx_inside, digest_inside);
|
||||
sha256_update(&ctx->ctx_outside, digest_inside, SHA256_DIGEST_SIZE);
|
||||
sha256_final(&ctx->ctx_outside, mac_temp);
|
||||
memcpy(mac, mac_temp, mac_size);
|
||||
}
|
||||
|
||||
void hmac_sha256(c_uint8_t *key, c_uint32_t key_size,
|
||||
c_uint8_t *message, c_uint32_t message_len,
|
||||
c_uint8_t *mac, c_uint32_t mac_size)
|
||||
{
|
||||
hmac_sha256_ctx ctx;
|
||||
|
||||
hmac_sha256_init(&ctx, key, key_size);
|
||||
hmac_sha256_update(&ctx, message, message_len);
|
||||
hmac_sha256_final(&ctx, mac, mac_size);
|
||||
}
|
||||
|
||||
/* HMAC-SHA-384 functions */
|
||||
|
||||
void hmac_sha384_init(hmac_sha384_ctx *ctx, c_uint8_t *key,
|
||||
c_uint32_t key_size)
|
||||
{
|
||||
c_uint32_t fill;
|
||||
c_uint32_t num;
|
||||
|
||||
c_uint8_t *key_used;
|
||||
c_uint8_t key_temp[SHA384_DIGEST_SIZE];
|
||||
int i;
|
||||
|
||||
if (key_size == SHA384_BLOCK_SIZE) {
|
||||
key_used = key;
|
||||
num = SHA384_BLOCK_SIZE;
|
||||
} else {
|
||||
if (key_size > SHA384_BLOCK_SIZE){
|
||||
key_used = key_temp;
|
||||
num = SHA384_DIGEST_SIZE;
|
||||
sha384(key, key_size, key_used);
|
||||
} else { /* key_size > SHA384_BLOCK_SIZE */
|
||||
key_used = key;
|
||||
num = key_size;
|
||||
}
|
||||
fill = SHA384_BLOCK_SIZE - num;
|
||||
|
||||
memset(ctx->block_ipad + num, 0x36, fill);
|
||||
memset(ctx->block_opad + num, 0x5c, fill);
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
ctx->block_ipad[i] = key_used[i] ^ 0x36;
|
||||
ctx->block_opad[i] = key_used[i] ^ 0x5c;
|
||||
}
|
||||
|
||||
sha384_init(&ctx->ctx_inside);
|
||||
sha384_update(&ctx->ctx_inside, ctx->block_ipad, SHA384_BLOCK_SIZE);
|
||||
|
||||
sha384_init(&ctx->ctx_outside);
|
||||
sha384_update(&ctx->ctx_outside, ctx->block_opad,
|
||||
SHA384_BLOCK_SIZE);
|
||||
|
||||
/* for hmac_reinit */
|
||||
memcpy(&ctx->ctx_inside_reinit, &ctx->ctx_inside,
|
||||
sizeof(sha384_ctx));
|
||||
memcpy(&ctx->ctx_outside_reinit, &ctx->ctx_outside,
|
||||
sizeof(sha384_ctx));
|
||||
}
|
||||
|
||||
void hmac_sha384_reinit(hmac_sha384_ctx *ctx)
|
||||
{
|
||||
memcpy(&ctx->ctx_inside, &ctx->ctx_inside_reinit,
|
||||
sizeof(sha384_ctx));
|
||||
memcpy(&ctx->ctx_outside, &ctx->ctx_outside_reinit,
|
||||
sizeof(sha384_ctx));
|
||||
}
|
||||
|
||||
void hmac_sha384_update(hmac_sha384_ctx *ctx, c_uint8_t *message,
|
||||
c_uint32_t message_len)
|
||||
{
|
||||
sha384_update(&ctx->ctx_inside, message, message_len);
|
||||
}
|
||||
|
||||
void hmac_sha384_final(hmac_sha384_ctx *ctx, c_uint8_t *mac,
|
||||
c_uint32_t mac_size)
|
||||
{
|
||||
c_uint8_t digest_inside[SHA384_DIGEST_SIZE];
|
||||
c_uint8_t mac_temp[SHA384_DIGEST_SIZE];
|
||||
|
||||
sha384_final(&ctx->ctx_inside, digest_inside);
|
||||
sha384_update(&ctx->ctx_outside, digest_inside, SHA384_DIGEST_SIZE);
|
||||
sha384_final(&ctx->ctx_outside, mac_temp);
|
||||
memcpy(mac, mac_temp, mac_size);
|
||||
}
|
||||
|
||||
void hmac_sha384(c_uint8_t *key, c_uint32_t key_size,
|
||||
c_uint8_t *message, c_uint32_t message_len,
|
||||
c_uint8_t *mac, c_uint32_t mac_size)
|
||||
{
|
||||
hmac_sha384_ctx ctx;
|
||||
|
||||
hmac_sha384_init(&ctx, key, key_size);
|
||||
hmac_sha384_update(&ctx, message, message_len);
|
||||
hmac_sha384_final(&ctx, mac, mac_size);
|
||||
}
|
||||
|
||||
/* HMAC-SHA-512 functions */
|
||||
|
||||
void hmac_sha512_init(hmac_sha512_ctx *ctx, c_uint8_t *key,
|
||||
c_uint32_t key_size)
|
||||
{
|
||||
c_uint32_t fill;
|
||||
c_uint32_t num;
|
||||
|
||||
c_uint8_t *key_used;
|
||||
c_uint8_t key_temp[SHA512_DIGEST_SIZE];
|
||||
int i;
|
||||
|
||||
if (key_size == SHA512_BLOCK_SIZE) {
|
||||
key_used = key;
|
||||
num = SHA512_BLOCK_SIZE;
|
||||
} else {
|
||||
if (key_size > SHA512_BLOCK_SIZE){
|
||||
key_used = key_temp;
|
||||
num = SHA512_DIGEST_SIZE;
|
||||
sha512(key, key_size, key_used);
|
||||
} else { /* key_size > SHA512_BLOCK_SIZE */
|
||||
key_used = key;
|
||||
num = key_size;
|
||||
}
|
||||
fill = SHA512_BLOCK_SIZE - num;
|
||||
|
||||
memset(ctx->block_ipad + num, 0x36, fill);
|
||||
memset(ctx->block_opad + num, 0x5c, fill);
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
ctx->block_ipad[i] = key_used[i] ^ 0x36;
|
||||
ctx->block_opad[i] = key_used[i] ^ 0x5c;
|
||||
}
|
||||
|
||||
sha512_init(&ctx->ctx_inside);
|
||||
sha512_update(&ctx->ctx_inside, ctx->block_ipad, SHA512_BLOCK_SIZE);
|
||||
|
||||
sha512_init(&ctx->ctx_outside);
|
||||
sha512_update(&ctx->ctx_outside, ctx->block_opad,
|
||||
SHA512_BLOCK_SIZE);
|
||||
|
||||
/* for hmac_reinit */
|
||||
memcpy(&ctx->ctx_inside_reinit, &ctx->ctx_inside,
|
||||
sizeof(sha512_ctx));
|
||||
memcpy(&ctx->ctx_outside_reinit, &ctx->ctx_outside,
|
||||
sizeof(sha512_ctx));
|
||||
}
|
||||
|
||||
void hmac_sha512_reinit(hmac_sha512_ctx *ctx)
|
||||
{
|
||||
memcpy(&ctx->ctx_inside, &ctx->ctx_inside_reinit,
|
||||
sizeof(sha512_ctx));
|
||||
memcpy(&ctx->ctx_outside, &ctx->ctx_outside_reinit,
|
||||
sizeof(sha512_ctx));
|
||||
}
|
||||
|
||||
void hmac_sha512_update(hmac_sha512_ctx *ctx, c_uint8_t *message,
|
||||
c_uint32_t message_len)
|
||||
{
|
||||
sha512_update(&ctx->ctx_inside, message, message_len);
|
||||
}
|
||||
|
||||
void hmac_sha512_final(hmac_sha512_ctx *ctx, c_uint8_t *mac,
|
||||
c_uint32_t mac_size)
|
||||
{
|
||||
c_uint8_t digest_inside[SHA512_DIGEST_SIZE];
|
||||
c_uint8_t mac_temp[SHA512_DIGEST_SIZE];
|
||||
|
||||
sha512_final(&ctx->ctx_inside, digest_inside);
|
||||
sha512_update(&ctx->ctx_outside, digest_inside, SHA512_DIGEST_SIZE);
|
||||
sha512_final(&ctx->ctx_outside, mac_temp);
|
||||
memcpy(mac, mac_temp, mac_size);
|
||||
}
|
||||
|
||||
void hmac_sha512(c_uint8_t *key, c_uint32_t key_size,
|
||||
c_uint8_t *message, c_uint32_t message_len,
|
||||
c_uint8_t *mac, c_uint32_t mac_size)
|
||||
{
|
||||
hmac_sha512_ctx ctx;
|
||||
|
||||
hmac_sha512_init(&ctx, key, key_size);
|
||||
hmac_sha512_update(&ctx, message, message_len);
|
||||
hmac_sha512_final(&ctx, mac, mac_size);
|
||||
}
|
|
@ -0,0 +1,244 @@
|
|||
#define TRACE_MODULE _timer
|
||||
#include "core_debug.h"
|
||||
#include "core_timer.h"
|
||||
#include "core_time.h"
|
||||
#include "core_param.h"
|
||||
#include "core_pool.h"
|
||||
|
||||
typedef struct _tm_block_t {
|
||||
lnode_t node;
|
||||
|
||||
tm_service_t *tm_s;
|
||||
c_uint32_t expire_time;
|
||||
|
||||
expire_func_t expire_func;
|
||||
c_uintptr_t arg1;
|
||||
c_uintptr_t arg2;
|
||||
c_uintptr_t arg3;
|
||||
|
||||
tm_type_e type;
|
||||
c_uint8_t running;
|
||||
c_uint32_t duration;
|
||||
} tm_block_t;
|
||||
|
||||
pool_declare(timer_pool, tm_block_t, MAX_NUM_OF_TIMER);
|
||||
|
||||
static int _tm_cmp_func(lnode_t *pnode1, lnode_t *pnode2);
|
||||
static tm_block_t *_tm_get(void);
|
||||
static void _tm_free(tm_block_t *tm);
|
||||
|
||||
#define _tm_add(__l, __tm) \
|
||||
list_insert_sorted(__l, __tm, _tm_cmp_func)
|
||||
|
||||
#define _tm_remove(__l, __tm) \
|
||||
list_remove(__l, __tm)
|
||||
|
||||
status_t tm_init(void)
|
||||
{
|
||||
pool_init(&timer_pool, MAX_NUM_OF_TIMER);
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t tm_final(void)
|
||||
{
|
||||
pool_final(&timer_pool);
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
c_uint32_t tm_pool_avail(void)
|
||||
{
|
||||
return pool_avail(&timer_pool);
|
||||
}
|
||||
|
||||
void tm_service_init(tm_service_t *tm_service)
|
||||
{
|
||||
memset(tm_service, 0x00, sizeof(tm_service_t));
|
||||
list_init(&tm_service->active_list);
|
||||
list_init(&tm_service->idle_list);
|
||||
return;
|
||||
}
|
||||
|
||||
status_t tm_execute_tm_service(tm_service_t *p_tm_s)
|
||||
{
|
||||
c_uint32_t cur_time;
|
||||
tm_block_t *tm;
|
||||
|
||||
cur_time = time_as_msec(time_now());
|
||||
tm = list_first(&(p_tm_s->active_list));
|
||||
|
||||
while(tm)
|
||||
{
|
||||
if(tm->expire_time < cur_time)
|
||||
{
|
||||
/* execute expiry function */
|
||||
tm->expire_func(tm->arg1, tm->arg2, tm->arg3);
|
||||
|
||||
/* remove this tm_block from the active list */
|
||||
_tm_remove(&(p_tm_s->active_list), tm);
|
||||
|
||||
if(tm->type == TIMER_TYPE_PERIODIC)
|
||||
{
|
||||
tm->expire_time = cur_time + tm->duration;
|
||||
|
||||
/* add this tm_block to the active list */
|
||||
_tm_add(&(p_tm_s->active_list), tm);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* add this tm_block to the idle list */
|
||||
_tm_add(&(p_tm_s->idle_list), tm);
|
||||
tm->running = 0;
|
||||
}
|
||||
|
||||
tm = list_first(&(p_tm_s->active_list));
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
static int _tm_cmp_func(lnode_t *pnode1, lnode_t *pnode2)
|
||||
{
|
||||
tm_block_t *tm1 = (tm_block_t*)pnode1;
|
||||
tm_block_t *tm2 = (tm_block_t*)pnode2;
|
||||
|
||||
if(tm1->expire_time < tm2->expire_time)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static tm_block_t *_tm_get(void)
|
||||
{
|
||||
tm_block_t *tm_b = NULL;
|
||||
|
||||
/* get timer node from node pool */
|
||||
pool_alloc_node(&timer_pool, &tm_b);
|
||||
|
||||
/* check for error */
|
||||
d_assert(tm_b != NULL, return NULL, "fail to get timer pool\n");
|
||||
|
||||
/* intialize timer node */
|
||||
memset((char*)tm_b, 0x00, sizeof(tm_block_t));
|
||||
return tm_b;
|
||||
|
||||
}
|
||||
|
||||
static void _tm_free(tm_block_t *tm)
|
||||
{
|
||||
/* free tlv node to the node pool */
|
||||
pool_free_node(&timer_pool, tm);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
tm_block_id tm_create(tm_service_t *tm_service)
|
||||
{
|
||||
tm_block_t *tm = NULL;
|
||||
tm = _tm_get();
|
||||
|
||||
d_assert(tm, return 0, "tm_create failed\n");
|
||||
tm->tm_s = tm_service;
|
||||
|
||||
_tm_add(&(tm->tm_s->idle_list), tm);
|
||||
|
||||
return (tm_block_id)tm;
|
||||
}
|
||||
|
||||
void tm_delete(tm_block_id id)
|
||||
{
|
||||
tm_block_t *tm = (tm_block_t *)id;
|
||||
|
||||
/* If running timer, pop it from active list */
|
||||
if (tm->running == 1)
|
||||
_tm_remove(&(tm->tm_s->active_list), tm);
|
||||
/* If not running timer, pop it from idle list */
|
||||
else
|
||||
_tm_remove(&(tm->tm_s->idle_list), tm);
|
||||
|
||||
_tm_free(tm);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
status_t tm_set(
|
||||
tm_block_id id, tm_type_e type, c_uint32_t duration,
|
||||
expire_func_t expire_func,
|
||||
c_uintptr_t arg1, c_uintptr_t arg2, c_uintptr_t arg3)
|
||||
{
|
||||
tm_block_t *tm = (tm_block_t *)id;
|
||||
|
||||
tm->type = type;
|
||||
tm->duration = duration;
|
||||
tm->expire_func = expire_func;
|
||||
tm->arg1 = arg1;
|
||||
tm->arg2 = arg2;
|
||||
tm->arg3 = arg3;
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t tm_set_duration(tm_block_id id, c_uint32_t duration)
|
||||
{
|
||||
tm_block_t *tm = (tm_block_t *)id;
|
||||
|
||||
tm->duration = duration;
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t tm_set_by_desc(tm_block_id id, tm_desc_t *desc)
|
||||
{
|
||||
tm_block_t *tm = (tm_block_t *)id;
|
||||
|
||||
tm->type = desc->type;
|
||||
tm->duration = desc->duration;
|
||||
tm->expire_func = desc->expire_func;
|
||||
tm->arg1 = desc->arg1;
|
||||
tm->arg2 = desc->arg2;
|
||||
tm->arg3 = desc->arg3;
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t tm_start(tm_block_id id)
|
||||
{
|
||||
c_uint32_t cur_time = time_as_msec(time_now());
|
||||
tm_block_t *tm = (tm_block_t *)id;
|
||||
|
||||
/* If already running timer, pop it from active list for put again */
|
||||
if (tm->running == 1)
|
||||
_tm_remove(&(tm->tm_s->active_list), tm);
|
||||
/* If not running, tm is in idle list. pop it */
|
||||
else
|
||||
_tm_remove(&(tm->tm_s->idle_list), tm);
|
||||
|
||||
/* Calculate expiration */
|
||||
tm->expire_time = cur_time + tm->duration;
|
||||
|
||||
/* Push tm to active list */
|
||||
_tm_add(&(tm->tm_s->active_list), tm);
|
||||
|
||||
tm->running = 1;
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t tm_stop(tm_block_id id)
|
||||
{
|
||||
tm_block_t *tm = (tm_block_t *)id;
|
||||
|
||||
/* If already stopped timer, no operations needed */
|
||||
if (tm->running == 0)
|
||||
return CORE_OK;
|
||||
|
||||
_tm_remove(&(tm->tm_s->active_list), tm);
|
||||
_tm_add(&(tm->tm_s->idle_list), tm);
|
||||
|
||||
tm->running = 0;
|
||||
|
||||
return CORE_OK;
|
||||
}
|
|
@ -0,0 +1,729 @@
|
|||
#define TRACE_MODULE _tlv
|
||||
#include "core_debug.h"
|
||||
#include "core_tlv.h"
|
||||
#include "core_lib.h"
|
||||
|
||||
pool_declare(tlv_pool, tlv_t, NUM_OF_TLV_NODE);
|
||||
|
||||
/* tlv_t common functions */
|
||||
tlv_t* tlv_get(void)
|
||||
{
|
||||
tlv_t *tlv = NULL;
|
||||
|
||||
/* get tlv node from node pool */
|
||||
pool_alloc_node(&tlv_pool, &tlv);
|
||||
|
||||
/* check for error */
|
||||
d_assert(tlv != NULL, return NULL, "fail to get tlv pool\n");
|
||||
|
||||
/* intialize tlv node */
|
||||
memset((char*)tlv, 0x00, sizeof(tlv_t));
|
||||
return tlv;
|
||||
}
|
||||
|
||||
void tlv_free(tlv_t *p_tlv)
|
||||
{
|
||||
/* free tlv node to the node pool */
|
||||
pool_free_node(&tlv_pool, p_tlv);
|
||||
return;
|
||||
}
|
||||
|
||||
status_t tlv_init(void)
|
||||
{
|
||||
pool_init(&tlv_pool, NUM_OF_TLV_NODE);
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t tlv_final(void)
|
||||
{
|
||||
pool_final(&tlv_pool);
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
c_uint32_t tlv_pool_avail(void)
|
||||
{
|
||||
return pool_avail(&tlv_pool);
|
||||
}
|
||||
|
||||
void tlv_free_all(tlv_t *root_tlv)
|
||||
{
|
||||
/* free all tlv node to the node pool */
|
||||
tlv_t *p_tlv = root_tlv;
|
||||
tlv_t *next = NULL;
|
||||
while(p_tlv)
|
||||
{
|
||||
if(p_tlv->embedded != NULL)
|
||||
{
|
||||
tlv_free_all(p_tlv->embedded);
|
||||
}
|
||||
next = p_tlv->next;
|
||||
tlv_free(p_tlv);
|
||||
p_tlv = next;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
c_uint8_t tlv_value_8(tlv_t *tlv)
|
||||
{
|
||||
return (*((c_uint8_t*)(tlv->value)));
|
||||
}
|
||||
|
||||
c_uint16_t tlv_value_16(tlv_t *tlv)
|
||||
{
|
||||
c_uint16_t c_16;
|
||||
c_uint8_t *v = tlv->value;
|
||||
|
||||
c_16 = ((v[0] << 8) & 0xff00) |
|
||||
((v[1] ) & 0x00ff);
|
||||
|
||||
return c_16;
|
||||
}
|
||||
|
||||
c_uint32_t tlv_value_32(tlv_t *tlv)
|
||||
{
|
||||
c_uint32_t c_32;
|
||||
c_uint8_t *v = tlv->value;
|
||||
|
||||
c_32 = ((v[0] << 24) & 0xff000000) |
|
||||
((v[1] << 16) & 0x00ff0000) |
|
||||
((v[2] << 8) & 0x0000ff00) |
|
||||
((v[3] ) & 0x000000ff);
|
||||
|
||||
return c_32;
|
||||
}
|
||||
|
||||
c_uint32_t tlv_calc_length(tlv_t *p_tlv, c_uint8_t mode)
|
||||
{
|
||||
tlv_t *tmp_tlv = p_tlv;
|
||||
c_uint32_t length = 0;
|
||||
|
||||
while(tmp_tlv)
|
||||
{
|
||||
/* this is length for type field */
|
||||
if(mode == TLV_MODE_WMX_R4_R6)
|
||||
{
|
||||
length += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
length += 1;
|
||||
}
|
||||
|
||||
|
||||
/* this is length for type field */
|
||||
if(tmp_tlv->embedded != NULL)
|
||||
{
|
||||
tmp_tlv->length = tlv_calc_length(tmp_tlv->embedded, mode);
|
||||
}
|
||||
|
||||
if(mode == TLV_MODE_WMX_R4_R6)
|
||||
{
|
||||
length += 2;
|
||||
}
|
||||
else if(mode == TLV_MODE_UTIS)
|
||||
{
|
||||
if(tmp_tlv->length < UPDU_IE_TYPE_1_MAX_SIZE)
|
||||
length += 1;
|
||||
else if(tmp_tlv->length < UPDU_IE_TYPE_2_MAX_SIZE)
|
||||
length += 2;
|
||||
else if(tmp_tlv->length < UPDU_IE_TYPE_3_MAX_SIZE)
|
||||
length += 4;
|
||||
else
|
||||
{
|
||||
/* Error : Invalid IE length field */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
length += 1;
|
||||
}
|
||||
|
||||
|
||||
/* this is length for value field */
|
||||
length += tmp_tlv->length;
|
||||
|
||||
tmp_tlv = tmp_tlv->next;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
c_uint32_t tlv_calc_count(tlv_t *p_tlv)
|
||||
{
|
||||
tlv_t *tmp_tlv = p_tlv;
|
||||
c_uint32_t count = 0;
|
||||
|
||||
while(tmp_tlv)
|
||||
{
|
||||
if(tmp_tlv->embedded != NULL)
|
||||
{
|
||||
count += tlv_calc_count(tmp_tlv->embedded);
|
||||
}
|
||||
else
|
||||
{
|
||||
count++;
|
||||
}
|
||||
tmp_tlv = tmp_tlv->next;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
c_uint32_t _tlv_get_length_utis(c_uint8_t **pos)
|
||||
{
|
||||
c_uint8_t *blk = *pos;
|
||||
c_uint32_t length = 0;
|
||||
|
||||
switch(*blk >> 6)
|
||||
{
|
||||
case UPDU_IE_TYPE_1_CODE:
|
||||
length = *blk & 0x3F;
|
||||
*pos += 1;
|
||||
break;
|
||||
|
||||
case UPDU_IE_TYPE_2_CODE:
|
||||
length = ((*blk & 0x3F) << 8) + *(blk + 1);
|
||||
*pos += 2;
|
||||
break;
|
||||
|
||||
case UPDU_IE_TYPE_3_CODE:
|
||||
length = ((*blk & 0x3F) << 24) +
|
||||
(*(blk + 1) << 16) + (*(blk + 2) << 8) + *(blk + 3);
|
||||
*pos += 4;
|
||||
break;
|
||||
default:
|
||||
/* Error : Invalid IE length field */
|
||||
return CORE_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
c_uint8_t* _tlv_put_length_utis(c_uint32_t length, c_uint8_t *pos)
|
||||
{
|
||||
if(length < UPDU_IE_TYPE_1_MAX_SIZE)
|
||||
{
|
||||
*(pos++) = (UPDU_IE_TYPE_1_CODE << 6) | length;
|
||||
}
|
||||
else if(length < UPDU_IE_TYPE_2_MAX_SIZE)
|
||||
{
|
||||
*(pos++) = (UPDU_IE_TYPE_2_CODE << 6) | (length >> 8);
|
||||
*(pos++) = length & 0xFF;
|
||||
}
|
||||
else if(length < UPDU_IE_TYPE_3_MAX_SIZE)
|
||||
{
|
||||
*(pos++) = (length >> 24) & 0xFF;
|
||||
*(pos++) = (length >> 16) & 0xFF;
|
||||
*(pos++) = (length >> 8) & 0xFF;
|
||||
*(pos++) = length & 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
d_assert(FALSE, return NULL, "invalid tlv length\n");
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
c_uint32_t _tlv_get_length_wifi(c_uint8_t **pos)
|
||||
{
|
||||
c_uint8_t *blk = *pos;
|
||||
c_uint32_t length = 0;
|
||||
|
||||
if(*blk & 0x80)
|
||||
{
|
||||
d_error("TLV for wifi is not implemented in case of (length > 127)");
|
||||
}
|
||||
else
|
||||
{
|
||||
length = *blk;
|
||||
*pos += 1;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
c_uint8_t* _tlv_put_length_wifi(c_uint32_t length, c_uint8_t *pos)
|
||||
{
|
||||
if(length < 128)
|
||||
{
|
||||
*(pos++) = length;
|
||||
}
|
||||
else
|
||||
{
|
||||
d_error("TLV for wifi is not implemented in case of (length > 127)");
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
c_uint32_t _tlv_get_length_wmx_r4_r6(c_uint8_t **pos)
|
||||
{
|
||||
c_uint8_t *blk = *pos;
|
||||
c_uint32_t length = 0;
|
||||
|
||||
length = ((*blk) << 8) + *(blk+1);
|
||||
*pos += 2;
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
c_uint8_t* _tlv_put_length_wmx_r4_r6(c_uint32_t length, c_uint8_t *pos)
|
||||
{
|
||||
*(pos++) = (length >> 8) & 0xFF;
|
||||
*(pos++) = length & 0xFF;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
/* Not Implemented for WMX_R1*/
|
||||
c_uint32_t _tlv_get_length_wmx_r1(c_uint8_t **pos)
|
||||
{
|
||||
c_uint8_t *blk = *pos;
|
||||
c_uint32_t length = 0;
|
||||
|
||||
if(*blk & 0x80)
|
||||
{
|
||||
d_error("TLV is not implemented in case of (length > 127)");
|
||||
}
|
||||
else
|
||||
{
|
||||
length = *blk;
|
||||
*pos += 1;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
c_uint8_t* _tlv_put_length_wmx_r1(c_uint32_t length, c_uint8_t *pos)
|
||||
{
|
||||
if(length < 128)
|
||||
{
|
||||
*(pos++) = length;
|
||||
}
|
||||
else
|
||||
{
|
||||
d_error("TLV is not implemented in case of (length > 127)");
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
c_uint32_t _tlv_get_length_common(c_uint8_t **pos)
|
||||
{
|
||||
c_uint8_t *blk = *pos;
|
||||
c_uint32_t length = 0;
|
||||
|
||||
if(*blk & 0x80)
|
||||
{
|
||||
d_error("TLV is not implemented in case of (length > 127)");
|
||||
}
|
||||
else
|
||||
{
|
||||
length = *blk;
|
||||
*pos += 1;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
c_uint8_t* _tlv_put_length_common(c_uint32_t length, c_uint8_t *pos)
|
||||
{
|
||||
if(length < 128)
|
||||
{
|
||||
*(pos++) = length;
|
||||
}
|
||||
else
|
||||
{
|
||||
d_error("TLV is not implemented in case of (length > 127)");
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
c_uint8_t* _tlv_put_length(c_uint32_t length, c_uint8_t *pos, c_uint8_t mode)
|
||||
{
|
||||
if(mode == TLV_MODE_UTIS)
|
||||
{
|
||||
pos = _tlv_put_length_utis(length, pos);
|
||||
|
||||
}
|
||||
else if(mode == TLV_MODE_WIFI)
|
||||
{
|
||||
pos = _tlv_put_length_wifi(length, pos);
|
||||
}
|
||||
else if(mode == TLV_MODE_WMX_R4_R6)
|
||||
{
|
||||
pos = _tlv_put_length_wmx_r4_r6(length, pos);
|
||||
}
|
||||
else if(mode == TLV_MODE_WMX_R1)
|
||||
{
|
||||
pos = _tlv_put_length_wmx_r1(length, pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
pos = _tlv_put_length_common(length, pos);
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
c_uint8_t* _tlv_get_element(tlv_t *p_tlv, c_uint8_t *tlvBlock, c_uint8_t mode)
|
||||
{
|
||||
c_uint8_t *pos = tlvBlock;
|
||||
|
||||
if(mode == TLV_MODE_WMX_R4_R6)
|
||||
{
|
||||
p_tlv->type = *(pos++) << 8;
|
||||
p_tlv->type += *(pos++);
|
||||
}
|
||||
else
|
||||
{
|
||||
p_tlv->type = *(pos++);
|
||||
}
|
||||
|
||||
|
||||
if(mode == TLV_MODE_UTIS)
|
||||
{
|
||||
p_tlv->length = _tlv_get_length_utis(&pos);
|
||||
}
|
||||
else if(mode == TLV_MODE_WIFI)
|
||||
{
|
||||
p_tlv->length = _tlv_get_length_wifi(&pos);
|
||||
}
|
||||
else if(mode == TLV_MODE_WMX_R4_R6)
|
||||
{
|
||||
p_tlv->length = _tlv_get_length_wmx_r4_r6(&pos);
|
||||
}
|
||||
else if(mode == TLV_MODE_WMX_R1)
|
||||
{
|
||||
p_tlv->length = _tlv_get_length_wmx_r1(&pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
p_tlv->length = _tlv_get_length_common(&pos);
|
||||
}
|
||||
p_tlv->value = pos;
|
||||
|
||||
return (pos + tlv_length(p_tlv));
|
||||
}
|
||||
|
||||
|
||||
c_uint8_t* _tlv_put_type(c_uint32_t type, c_uint8_t *pos, c_uint8_t mode)
|
||||
{
|
||||
if(mode == TLV_MODE_WMX_R4_R6)
|
||||
{
|
||||
*(pos++) = (type >> 8) & 0xFF;
|
||||
*(pos++) = type & 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
*(pos++) = type & 0xFF;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
c_uint8_t* _tlv_get_type(tlv_t *p_tlv, c_uint8_t *tlvBlock, c_uint8_t mode)
|
||||
{
|
||||
c_uint8_t *pos = tlvBlock;
|
||||
|
||||
p_tlv->type = *(pos++);
|
||||
if(mode == TLV_MODE_UTIS)
|
||||
{
|
||||
p_tlv->length = _tlv_get_length_utis(&pos);
|
||||
}
|
||||
else if(mode == TLV_MODE_WIFI)
|
||||
{
|
||||
p_tlv->length = _tlv_get_length_wifi(&pos);
|
||||
}
|
||||
else if(mode == TLV_MODE_WMX_R4_R6)
|
||||
{
|
||||
p_tlv->length = _tlv_get_length_wmx_r4_r6(&pos);
|
||||
}
|
||||
else if(mode == TLV_MODE_WMX_R1)
|
||||
{
|
||||
p_tlv->length = _tlv_get_length_wmx_r1(&pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
p_tlv->length = _tlv_get_length_common(&pos);
|
||||
}
|
||||
p_tlv->value = pos;
|
||||
|
||||
return (pos + tlv_length(p_tlv));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* tlv_t encoding functions */
|
||||
|
||||
c_uint8_t *tlv_write_to_buff(
|
||||
c_uint8_t *blk, c_uint32_t type, c_uint32_t length,
|
||||
c_uint8_t *value, c_uint8_t mode)
|
||||
{
|
||||
c_uint8_t *pos = blk;
|
||||
*(pos++) = type;
|
||||
pos = _tlv_put_length(length, pos, mode);
|
||||
|
||||
memcpy((c_uint8_t*)pos, (c_uint8_t*)value, length);
|
||||
|
||||
pos += length;
|
||||
return pos;
|
||||
}
|
||||
|
||||
void _tlv_alloc_buff_to_tlv(
|
||||
tlv_t* head_tlv, c_uint8_t* buff, c_uint32_t buff_len)
|
||||
{
|
||||
head_tlv->buff_allocated = TRUE;
|
||||
head_tlv->buff_len = buff_len;
|
||||
head_tlv->buff_ptr = buff;
|
||||
head_tlv->buff = buff;
|
||||
}
|
||||
|
||||
tlv_t * tlv_find_root(tlv_t* p_tlv)
|
||||
{
|
||||
tlv_t *head_tlv = p_tlv->head;
|
||||
tlv_t *parentTlv;
|
||||
|
||||
parentTlv = head_tlv->parent;
|
||||
while(parentTlv)
|
||||
{
|
||||
head_tlv = parentTlv->head;
|
||||
parentTlv = head_tlv->parent;
|
||||
}
|
||||
|
||||
return head_tlv;
|
||||
}
|
||||
|
||||
|
||||
tlv_t * tlv_add(
|
||||
tlv_t *head_tlv, c_uint32_t type, c_uint32_t length, c_uint8_t *value)
|
||||
{
|
||||
tlv_t* curr_tlv = head_tlv;
|
||||
tlv_t* new_tlv = NULL;
|
||||
|
||||
new_tlv = tlv_get();
|
||||
d_assert(new_tlv, return NULL, "can't get tlv node\n");
|
||||
if(length != 0)
|
||||
{
|
||||
d_assert(value, return NULL, "tlv value is NULL\n");
|
||||
}
|
||||
|
||||
new_tlv->type = type;
|
||||
new_tlv->length = length;
|
||||
new_tlv->value = value;
|
||||
|
||||
if(head_tlv != NULL && head_tlv->buff_allocated == TRUE)
|
||||
{
|
||||
d_assert((head_tlv->buff_ptr - head_tlv->buff + length)<
|
||||
head_tlv->buff_len, tlv_free(new_tlv); return NULL,
|
||||
"overflow in tlv buffer\n");
|
||||
|
||||
memcpy(head_tlv->buff_ptr, value, length);
|
||||
new_tlv->value = head_tlv->buff_ptr;
|
||||
head_tlv->buff_ptr += length;
|
||||
}
|
||||
|
||||
if(curr_tlv == NULL)
|
||||
{
|
||||
new_tlv->head = new_tlv;
|
||||
new_tlv->tail = new_tlv;
|
||||
}
|
||||
else
|
||||
{
|
||||
head_tlv = head_tlv->head; /* in case head_tlv is not head */
|
||||
new_tlv->head = head_tlv;
|
||||
head_tlv->tail->next = new_tlv;
|
||||
head_tlv->tail = new_tlv;
|
||||
}
|
||||
return new_tlv;
|
||||
}
|
||||
|
||||
tlv_t * tlv_create_buff_enabled_tlv(
|
||||
c_uint8_t *buff, c_uint32_t buff_len,
|
||||
c_uint32_t type, c_uint32_t length, c_uint8_t *value)
|
||||
{
|
||||
tlv_t* new_tlv = NULL;
|
||||
|
||||
new_tlv = tlv_get();
|
||||
d_assert(new_tlv, return NULL, "can't get tlv node\n");
|
||||
|
||||
new_tlv->type = type;
|
||||
new_tlv->length = length;
|
||||
new_tlv->value = value;
|
||||
new_tlv->head = new_tlv->tail = new_tlv;
|
||||
|
||||
_tlv_alloc_buff_to_tlv(new_tlv,buff, buff_len);
|
||||
|
||||
memcpy(new_tlv->buff_ptr, value, length);
|
||||
new_tlv->value = new_tlv->buff_ptr;
|
||||
new_tlv->buff_ptr += length;
|
||||
|
||||
return new_tlv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
tlv_t * tlv_embed(
|
||||
tlv_t *parent_tlv, c_uint32_t type, c_uint32_t length, c_uint8_t *value)
|
||||
{
|
||||
tlv_t* new_tlv = NULL, *root_tlv = NULL;
|
||||
|
||||
d_assert(parent_tlv, return NULL, "parent tlv is NULL\n");
|
||||
|
||||
new_tlv = tlv_get();
|
||||
d_assert(new_tlv, return NULL, "can't get tlv node\n");
|
||||
|
||||
new_tlv->type = type;
|
||||
new_tlv->length = length;
|
||||
new_tlv->value = value;
|
||||
|
||||
root_tlv = tlv_find_root(parent_tlv);
|
||||
|
||||
if(root_tlv->buff_allocated == TRUE)
|
||||
{
|
||||
d_assert((root_tlv->buff_ptr - root_tlv->buff + length)<root_tlv->buff_len,
|
||||
tlv_free(new_tlv); return NULL, "overflow in tlv buffer\n");
|
||||
|
||||
memcpy(root_tlv->buff_ptr, value, length);
|
||||
new_tlv->value = root_tlv->buff_ptr;
|
||||
root_tlv->buff_ptr += length;
|
||||
}
|
||||
|
||||
if(parent_tlv->embedded == NULL)
|
||||
{
|
||||
parent_tlv->embedded = new_tlv->head = new_tlv->tail = new_tlv;
|
||||
new_tlv->parent = parent_tlv;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_tlv->head = parent_tlv->embedded;
|
||||
parent_tlv->embedded->tail->next = new_tlv;
|
||||
parent_tlv->embedded->tail = new_tlv;
|
||||
}
|
||||
|
||||
return new_tlv;
|
||||
}
|
||||
|
||||
|
||||
c_uint32_t tlv_render(
|
||||
tlv_t *root_tlv, c_uint8_t *blk, c_uint32_t length, c_uint8_t mode)
|
||||
{
|
||||
tlv_t* curr_tlv = root_tlv;
|
||||
c_uint8_t* pos = blk;
|
||||
c_uint32_t embedded_len = 0;
|
||||
|
||||
while(curr_tlv)
|
||||
{
|
||||
pos = _tlv_put_type(curr_tlv->type, pos, mode);
|
||||
|
||||
if(curr_tlv->embedded == NULL)
|
||||
{
|
||||
pos = _tlv_put_length(curr_tlv->length, pos, mode);
|
||||
|
||||
if((pos - blk) + tlv_length(curr_tlv) > length)
|
||||
{
|
||||
d_assert(FALSE, ;,
|
||||
"tlv_t encoding error:overflow for given buff length\n");
|
||||
memcpy((char*)pos, (char*)curr_tlv->value, length - (pos-blk));
|
||||
pos += length - (pos-blk);
|
||||
|
||||
return (pos - blk);
|
||||
}
|
||||
|
||||
memcpy((char*)pos, (char*)curr_tlv->value, curr_tlv->length);
|
||||
pos += curr_tlv->length;
|
||||
}
|
||||
else
|
||||
{
|
||||
embedded_len = tlv_calc_length(curr_tlv->embedded, mode);
|
||||
pos = _tlv_put_length(embedded_len, pos, mode);
|
||||
tlv_render(curr_tlv->embedded,
|
||||
pos, length - (c_uint32_t)(pos-blk), mode);
|
||||
pos += embedded_len;
|
||||
}
|
||||
curr_tlv = curr_tlv->next;
|
||||
}
|
||||
|
||||
return (pos - blk);
|
||||
}
|
||||
|
||||
|
||||
/* tlv_t parsing functions */
|
||||
|
||||
tlv_t * tlv_parse_tlv_block(c_uint32_t length, c_uint8_t *blk, c_uint8_t mode)
|
||||
{
|
||||
c_uint8_t* pos = blk;
|
||||
|
||||
tlv_t* root_tlv = NULL;
|
||||
tlv_t* prev_tlv = NULL;
|
||||
tlv_t* curr_tlv = NULL;
|
||||
|
||||
root_tlv = curr_tlv = tlv_get();
|
||||
|
||||
d_assert(curr_tlv, return NULL, "can't get tlv node\n");
|
||||
|
||||
pos = _tlv_get_element(curr_tlv, pos, mode);
|
||||
|
||||
d_assert(pos != NULL, tlv_free_all(root_tlv); return NULL,
|
||||
"tlvGetElement Failed\n");
|
||||
|
||||
while(pos - blk < length)
|
||||
{
|
||||
prev_tlv = curr_tlv;
|
||||
|
||||
curr_tlv = tlv_get();
|
||||
d_assert(curr_tlv, tlv_free_all(root_tlv); return NULL,
|
||||
"can't get tlv node\n");
|
||||
prev_tlv->next = curr_tlv;
|
||||
|
||||
pos = _tlv_get_element(curr_tlv, pos, mode);
|
||||
d_assert(pos != NULL, tlv_free_all(root_tlv); return NULL,
|
||||
"tlvGetElement Failed\n");
|
||||
}
|
||||
|
||||
d_assert(length == (pos - blk),
|
||||
tlv_free_all(root_tlv); return NULL,
|
||||
"total size is not equal to sum of each tlv. %d %d",
|
||||
length, pos - blk);
|
||||
|
||||
return root_tlv;
|
||||
}
|
||||
|
||||
tlv_t * tlv_parse_embedded_tlv_block(tlv_t* p_tlv, c_uint8_t mode)
|
||||
{
|
||||
p_tlv->embedded = tlv_parse_tlv_block(p_tlv->length, p_tlv->value, mode);
|
||||
|
||||
return p_tlv->embedded;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* tlv operation-related function */
|
||||
|
||||
tlv_t * tlv_find(tlv_t* p_tlv, c_uint32_t type)
|
||||
{
|
||||
tlv_t *tmp_tlv = p_tlv, *embed_tlv = NULL;
|
||||
while(tmp_tlv)
|
||||
{
|
||||
if(tmp_tlv->type == type)
|
||||
{
|
||||
return tmp_tlv;
|
||||
}
|
||||
|
||||
if(tmp_tlv->embedded != NULL)
|
||||
{
|
||||
embed_tlv = tlv_find(tmp_tlv->embedded, type);
|
||||
if(embed_tlv != NULL)
|
||||
{
|
||||
return embed_tlv;
|
||||
}
|
||||
}
|
||||
tmp_tlv = tmp_tlv->next;
|
||||
}
|
||||
|
||||
/* tlv for the designated type doesn't exist */
|
||||
return NULL;
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
noinst_LTLIBRARIES = libcoreunix.la
|
||||
|
||||
libcoreunix_la_SOURCES = \
|
||||
../../include/arch/core_private_common.h \
|
||||
../../include/arch/unix/core_arch_file.h \
|
||||
../../include/arch/unix/core_arch_mutex.h \
|
||||
../../include/arch/unix/core_arch_semaphore.h
|
||||
|
||||
nodist_libcoreunix_la_SOURCES = \
|
||||
cond.c file.c net_lib.c thread.c errorcodes.c mutex.c rwlock.c \
|
||||
start.c time.c semaphore.c signal.c pkbuf.c
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir) \
|
||||
-I$(top_srcdir)/lib/core/include/arch/@OSDIR@ \
|
||||
-I$(top_srcdir)/lib/core/include
|
||||
|
||||
AM_CFLAGS = \
|
||||
-Wall -Werror @OSCFLAGS@
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
MOSTLYCLEANFILES = core *.stackdump
|
||||
|
||||
EXTRA_DIST = .libs $(noinst_LTLIBRARIES)
|
|
@ -0,0 +1,103 @@
|
|||
#include "core.h"
|
||||
#include "core_cond.h"
|
||||
#include "core_arch_mutex.h"
|
||||
#include "core_pool.h"
|
||||
#include "core_param.h"
|
||||
#include "core_general.h"
|
||||
#include "core_debug.h"
|
||||
|
||||
typedef struct _cond_t {
|
||||
pthread_cond_t cond;
|
||||
} cond_t;
|
||||
|
||||
pool_declare(cond_pool, cond_t, MAX_NUM_OF_COND);
|
||||
|
||||
status_t cond_init(void)
|
||||
{
|
||||
pool_init(&cond_pool, MAX_NUM_OF_COND);
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t cond_final(void)
|
||||
{
|
||||
pool_final(&cond_pool);
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t cond_create(cond_id *id)
|
||||
{
|
||||
cond_t *new_cond = NULL;
|
||||
status_t rv;
|
||||
|
||||
pool_alloc_node(&cond_pool, &new_cond);
|
||||
d_assert(new_cond, return CORE_ENOMEM, "cond_pool(%d) is not enough\n",
|
||||
MAX_NUM_OF_COND);
|
||||
|
||||
if ((rv = pthread_cond_init(&new_cond->cond, NULL)))
|
||||
{
|
||||
return rv;
|
||||
}
|
||||
|
||||
*id = (cond_id)new_cond;
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t cond_wait(cond_id id, mutex_id mid)
|
||||
{
|
||||
status_t rv;
|
||||
cond_t *cond = (cond_t *)id;
|
||||
mutex_t *mutex = (mutex_t *)mid;
|
||||
|
||||
rv = pthread_cond_wait(&cond->cond, &mutex->mutex);
|
||||
return rv;
|
||||
}
|
||||
|
||||
status_t cond_timedwait(cond_id id,
|
||||
mutex_id mid, c_time_t timeout)
|
||||
{
|
||||
status_t rv;
|
||||
c_time_t then;
|
||||
struct timespec abstime;
|
||||
cond_t *cond = (cond_t *)id;
|
||||
mutex_t *mutex = (mutex_t *)mid;
|
||||
|
||||
then = time_now() + timeout;
|
||||
abstime.tv_sec = time_sec(then);
|
||||
abstime.tv_nsec = time_usec(then) * 1000; /* nanoseconds */
|
||||
|
||||
rv = pthread_cond_timedwait(&cond->cond, &mutex->mutex, &abstime);
|
||||
if (ETIMEDOUT == rv)
|
||||
{
|
||||
return CORE_TIMEUP;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
status_t cond_signal(cond_id id)
|
||||
{
|
||||
status_t rv;
|
||||
cond_t *cond = (cond_t *)id;
|
||||
|
||||
rv = pthread_cond_signal(&cond->cond);
|
||||
return rv;
|
||||
}
|
||||
|
||||
status_t cond_broadcast(cond_id id)
|
||||
{
|
||||
status_t rv;
|
||||
cond_t *cond = (cond_t *)id;
|
||||
|
||||
rv = pthread_cond_broadcast(&cond->cond);
|
||||
return rv;
|
||||
}
|
||||
|
||||
status_t cond_delete(cond_id id)
|
||||
{
|
||||
status_t rv;
|
||||
cond_t *cond = (cond_t *)id;
|
||||
|
||||
rv = pthread_cond_destroy(&cond->cond);
|
||||
pool_free_node(&cond_pool, cond);
|
||||
return rv;
|
||||
}
|
|
@ -0,0 +1,420 @@
|
|||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "core_lib.h"
|
||||
#include "core_net.h"
|
||||
|
||||
static char *stuffbuffer(char *buf, size_t bufsize, const char *s)
|
||||
{
|
||||
strncpy(buf,s,bufsize);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static char *core_error_string(status_t statcode)
|
||||
{
|
||||
switch (statcode) {
|
||||
case CORE_ENOPOOL:
|
||||
return "A new pool could not be created.";
|
||||
case CORE_EBADDATE:
|
||||
return "An invalid date has been provided";
|
||||
case CORE_EINVALSOCK:
|
||||
return "An invalid socket was returned";
|
||||
case CORE_ENOPROC:
|
||||
return "No process was provided and one was required.";
|
||||
case CORE_ENOTIME:
|
||||
return "No time was provided and one was required.";
|
||||
case CORE_ENODIR:
|
||||
return "No directory was provided and one was required.";
|
||||
case CORE_ENOLOCK:
|
||||
return "No lock was provided and one was required.";
|
||||
case CORE_ENOPOLL:
|
||||
return "No poll structure was provided and one was required.";
|
||||
case CORE_ENOSOCKET:
|
||||
return "No socket was provided and one was required.";
|
||||
case CORE_ENOTHREAD:
|
||||
return "No thread was provided and one was required.";
|
||||
case CORE_ENOTHDKEY:
|
||||
return "No thread key structure was provided and one was required.";
|
||||
case CORE_ENOSHMAVAIL:
|
||||
return "No shared memory is currently available";
|
||||
case CORE_EDSOOPEN:
|
||||
return "DSO load failed";
|
||||
case CORE_EBADIP:
|
||||
return "The specified IP address is invalid.";
|
||||
case CORE_EBADMASK:
|
||||
return "The specified network mask is invalid.";
|
||||
|
||||
case CORE_INCHILD:
|
||||
return
|
||||
"Your code just forked, and you are currently executing in the "
|
||||
"child process";
|
||||
case CORE_INPARENT:
|
||||
return
|
||||
"Your code just forked, and you are currently executing in the "
|
||||
"parent process";
|
||||
case CORE_DETACH:
|
||||
return "The specified thread is detached";
|
||||
case CORE_NOTDETACH:
|
||||
return "The specified thread is not detached";
|
||||
case CORE_CHILD_DONE:
|
||||
return "The specified child process is done executing";
|
||||
case CORE_CHILD_NOTDONE:
|
||||
return "The specified child process is not done executing";
|
||||
case CORE_TIMEUP:
|
||||
return "The timeout specified has expired";
|
||||
case CORE_INCOMPLETE:
|
||||
return "Partial results are valid but processing is incomplete";
|
||||
case CORE_BADCH:
|
||||
return "Bad character specified on command line";
|
||||
case CORE_BADARG:
|
||||
return "Missing parameter for the specified command line option";
|
||||
case CORE_EOF:
|
||||
return "End of file found";
|
||||
case CORE_NOTFOUND:
|
||||
return "Could not find specified socket in poll list.";
|
||||
case CORE_ANONYMOUS:
|
||||
return "Shared memory is implemented anonymously";
|
||||
case CORE_FILEBASED:
|
||||
return "Shared memory is implemented using files";
|
||||
case CORE_KEYBASED:
|
||||
return "Shared memory is implemented using a key system";
|
||||
case CORE_EINIT:
|
||||
return
|
||||
"There is no error, this value signifies an initialized "
|
||||
"error code";
|
||||
case CORE_ENOTIMPL:
|
||||
return "This function has not been implemented on this platform";
|
||||
case CORE_EMISMATCH:
|
||||
return "passwords do not match";
|
||||
case CORE_EABSOLUTE:
|
||||
return "The given path is absolute";
|
||||
case CORE_ERELATIVE:
|
||||
return "The given path is relative";
|
||||
case CORE_EINCOMPLETE:
|
||||
return "The given path is incomplete";
|
||||
case CORE_EABOVEROOT:
|
||||
return "The given path was above the root path";
|
||||
case CORE_EBADPATH:
|
||||
return "The given path is misformatted or contained invalid characters";
|
||||
case CORE_EPATHWILD:
|
||||
return "The given path contained wildcard characters";
|
||||
case CORE_EPROC_UNKNOWN:
|
||||
return "The process is not recognized.";
|
||||
case CORE_EGENERAL:
|
||||
return "Internal error";
|
||||
default:
|
||||
return "Error string not specified yet";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef OS2
|
||||
#include <ctype.h>
|
||||
|
||||
int core_canonical_error(status_t err);
|
||||
|
||||
static char *core_os_strerror(char* buf, size_t bufsize, int err)
|
||||
{
|
||||
char result[200];
|
||||
unsigned char message[HUGE_STRING_LEN];
|
||||
ULONG len;
|
||||
char *pos;
|
||||
int c;
|
||||
|
||||
if (err >= 10000 && err < 12000) { /* socket error codes */
|
||||
return stuffbuffer(buf, bufsize,
|
||||
strerror(core_canonical_error(err+OS_START_SYSERR)));
|
||||
}
|
||||
else if (DosGetMessage(NULL, 0, message, HUGE_STRING_LEN, err,
|
||||
"OSO001.MSG", &len) == 0) {
|
||||
len--;
|
||||
message[len] = 0;
|
||||
pos = result;
|
||||
|
||||
if (len >= sizeof(result))
|
||||
len = sizeof(result) - 1;
|
||||
|
||||
for (c=0; c<len; c++) {
|
||||
/* skip multiple whitespace */
|
||||
while (core_isspace(message[c]) && core_isspace(message[c+1]))
|
||||
c++;
|
||||
*(pos++) = core_isspace(message[c]) ? ' ' : message[c];
|
||||
}
|
||||
|
||||
*pos = 0;
|
||||
}
|
||||
else {
|
||||
sprintf(result, "OS/2 error %d", err);
|
||||
}
|
||||
|
||||
/* Stuff the string into the caller supplied buffer, then return
|
||||
* a pointer to it.
|
||||
*/
|
||||
return stuffbuffer(buf, bufsize, result);
|
||||
}
|
||||
|
||||
#elif defined(WIN32) || (defined(NETWARE) && defined(USE_WINSOCK))
|
||||
|
||||
static const struct {
|
||||
status_t code;
|
||||
const char *msg;
|
||||
} gaErrorList[] = {
|
||||
WSAEINTR, "Interrupted system call",
|
||||
WSAEBADF, "Bad file number",
|
||||
WSAEACCES, "Permission denied",
|
||||
WSAEFAULT, "Bad address",
|
||||
WSAEINVAL, "Invalid argument",
|
||||
WSAEMFILE, "Too many open sockets",
|
||||
WSAEWOULDBLOCK, "Operation would block",
|
||||
WSAEINPROGRESS, "Operation now in progress",
|
||||
WSAEALREADY, "Operation already in progress",
|
||||
WSAENOTSOCK, "Socket operation on non-socket",
|
||||
WSAEDESTADDRREQ, "Destination address required",
|
||||
WSAEMSGSIZE, "Message too long",
|
||||
WSAEPROTOTYPE, "Protocol wrong type for socket",
|
||||
WSAENOPROTOOPT, "Bad protocol option",
|
||||
WSAEPROTONOSUPPORT, "Protocol not supported",
|
||||
WSAESOCKTNOSUPPORT, "Socket type not supported",
|
||||
WSAEOPNOTSUPP, "Operation not supported on socket",
|
||||
WSAEPFNOSUPPORT, "Protocol family not supported",
|
||||
WSAEAFNOSUPPORT, "Address family not supported",
|
||||
WSAEADDRINUSE, "Address already in use",
|
||||
WSAEADDRNOTAVAIL, "Can't assign requested address",
|
||||
WSAENETDOWN, "Network is down",
|
||||
WSAENETUNREACH, "Network is unreachable",
|
||||
WSAENETRESET, "Net connection reset",
|
||||
WSAECONNABORTED, "Software caused connection abort",
|
||||
WSAECONNRESET, "Connection reset by peer",
|
||||
WSAENOBUFS, "No buffer space available",
|
||||
WSAEISCONN, "Socket is already connected",
|
||||
WSAENOTCONN, "Socket is not connected",
|
||||
WSAESHUTDOWN, "Can't send after socket shutdown",
|
||||
WSAETOOMANYREFS, "Too many references, can't splice",
|
||||
WSAETIMEDOUT, "Connection timed out",
|
||||
WSAECONNREFUSED, "Connection refused",
|
||||
WSAELOOP, "Too many levels of symbolic links",
|
||||
WSAENAMETOOLONG, "File name too long",
|
||||
WSAEHOSTDOWN, "Host is down",
|
||||
WSAEHOSTUNREACH, "No route to host",
|
||||
WSAENOTEMPTY, "Directory not empty",
|
||||
WSAEPROCLIM, "Too many processes",
|
||||
WSAEUSERS, "Too many users",
|
||||
WSAEDQUOT, "Disc quota exceeded",
|
||||
WSAESTALE, "Stale NFS file handle",
|
||||
WSAEREMOTE, "Too many levels of remote in path",
|
||||
WSASYSNOTREADY, "Network system is unavailable",
|
||||
WSAVERNOTSUPPORTED, "Winsock version out of range",
|
||||
WSANOTINITIALISED, "WSAStartup not yet called",
|
||||
WSAEDISCON, "Graceful shutdown in progress",
|
||||
WSAHOST_NOT_FOUND, "Host not found",
|
||||
WSANO_DATA, "No host data of that type was found",
|
||||
0, NULL
|
||||
};
|
||||
|
||||
|
||||
static char *core_os_strerror(char *buf, size_t bufsize, status_t errcode)
|
||||
{
|
||||
size_t len=0, i;
|
||||
|
||||
#ifndef NETWARE
|
||||
#ifndef _WIN32_WCE
|
||||
len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM
|
||||
| FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
errcode,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
|
||||
buf,
|
||||
(DWORD)bufsize,
|
||||
NULL);
|
||||
#else /* _WIN32_WCE speaks unicode */
|
||||
LPTSTR msg = (LPTSTR) buf;
|
||||
len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
|
||||
| FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
errcode,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
|
||||
msg,
|
||||
(DWORD) (bufsize/sizeof(TCHAR)),
|
||||
NULL);
|
||||
/* in-place convert to US-ASCII, substituting '?' for non ASCII */
|
||||
for(i = 0; i <= len; i++) {
|
||||
if (msg[i] < 0x80 && msg[i] >= 0) {
|
||||
buf[i] = (char) msg[i];
|
||||
} else {
|
||||
buf[i] = '?';
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (!len) {
|
||||
for (i = 0; gaErrorList[i].msg; ++i) {
|
||||
if (gaErrorList[i].code == errcode) {
|
||||
core_cpystrn(buf, gaErrorList[i].msg, bufsize);
|
||||
len = strlen(buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (len) {
|
||||
/* FormatMessage put the message in the buffer, but it may
|
||||
* have embedded a newline (\r\n), and possible more than one.
|
||||
* Remove the newlines replacing them with a space. This is not
|
||||
* as visually perfect as moving all the remaining message over,
|
||||
* but more efficient.
|
||||
*/
|
||||
i = len;
|
||||
while (i) {
|
||||
i--;
|
||||
if ((buf[i] == '\r') || (buf[i] == '\n'))
|
||||
buf[i] = ' ';
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Windows didn't provide us with a message. Even stuff like * WSAECONNREFUSED won't get a message.
|
||||
*/
|
||||
core_snprintf(buf, bufsize, "Unrecognized Win32 error code %d", errcode);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
#else
|
||||
/* On Unix, core_os_strerror() handles error codes from the resolver
|
||||
* (h_errno).
|
||||
*/
|
||||
static char *core_os_strerror(char* buf, size_t bufsize, int err)
|
||||
{
|
||||
#ifdef HAVE_HSTRERROR
|
||||
return stuffbuffer(buf, bufsize, hstrerror(err));
|
||||
#else /* HAVE_HSTRERROR */
|
||||
const char *msg;
|
||||
|
||||
switch(err) {
|
||||
case HOST_NOT_FOUND:
|
||||
msg = "Unknown host";
|
||||
break;
|
||||
#if defined(NO_DATA)
|
||||
case NO_DATA:
|
||||
#if defined(NO_ADDRESS) && (NO_DATA != NO_ADDRESS)
|
||||
case NO_ADDRESS:
|
||||
#endif
|
||||
msg = "No address for host";
|
||||
break;
|
||||
#elif defined(NO_ADDRESS)
|
||||
case NO_ADDRESS:
|
||||
msg = "No address for host";
|
||||
break;
|
||||
#endif /* NO_DATA */
|
||||
default:
|
||||
msg = "Unrecognized resolver error";
|
||||
}
|
||||
return stuffbuffer(buf, bufsize, msg);
|
||||
#endif /* HAVE_STRERROR */
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_STRERROR_R) && defined(STRERROR_R_RC_INT) && !defined(BEOS)
|
||||
/* AIX and Tru64 style */
|
||||
static char *native_strerror(status_t statcode, char *buf,
|
||||
size_t bufsize)
|
||||
{
|
||||
if (strerror_r(statcode, buf, bufsize) < 0) {
|
||||
return stuffbuffer(buf, bufsize,
|
||||
"CORE does not understand this error code");
|
||||
}
|
||||
else {
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
#elif defined(HAVE_STRERROR_R)
|
||||
/* glibc style */
|
||||
|
||||
/* BeOS has the function available, but it doesn't provide
|
||||
* the prototype publically (doh!), so to avoid a build warning
|
||||
* we add a suitable prototype here.
|
||||
*/
|
||||
#if defined(BEOS)
|
||||
const char *strerror_r(status_t, char *, size_t);
|
||||
#endif
|
||||
|
||||
static char *native_strerror(status_t statcode, char *buf,
|
||||
size_t bufsize)
|
||||
{
|
||||
const char *msg;
|
||||
|
||||
buf[0] = '\0';
|
||||
msg = strerror_r(statcode, buf, bufsize);
|
||||
if (buf[0] == '\0') { /* libc didn't use our buffer */
|
||||
return stuffbuffer(buf, bufsize, msg);
|
||||
}
|
||||
else {
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* plain old strerror();
|
||||
* thread-safe on some platforms (e.g., Solaris, OS/390)
|
||||
*/
|
||||
static char *native_strerror(status_t statcode, char *buf,
|
||||
size_t bufsize)
|
||||
{
|
||||
#ifdef _WIN32_WCE
|
||||
static char err[32];
|
||||
sprintf(err, "Native Error #%d", statcode);
|
||||
return stuffbuffer(buf, bufsize, err);
|
||||
#else
|
||||
const char *err = strerror(statcode);
|
||||
if (err) {
|
||||
return stuffbuffer(buf, bufsize, err);
|
||||
} else {
|
||||
return stuffbuffer(buf, bufsize,
|
||||
"CORE does not understand this error code");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
char * core_strerror(status_t statcode, char *buf,
|
||||
size_t bufsize)
|
||||
{
|
||||
if (statcode < OS_START_ERROR) {
|
||||
return native_strerror(statcode, buf, bufsize);
|
||||
}
|
||||
else if (statcode < OS_START_USERERR) {
|
||||
return stuffbuffer(buf, bufsize, core_error_string(statcode));
|
||||
}
|
||||
else if (statcode < OS_START_EAIERR) {
|
||||
return stuffbuffer(buf, bufsize, "CORE does not understand this error code");
|
||||
}
|
||||
else if (statcode < OS_START_SYSERR) {
|
||||
#if defined(HAVE_GAI_STRERROR)
|
||||
statcode -= OS_START_EAIERR;
|
||||
#if defined(NEGATIVE_EAI)
|
||||
statcode = -statcode;
|
||||
#endif
|
||||
return stuffbuffer(buf, bufsize, gai_strerror(statcode));
|
||||
#else
|
||||
return stuffbuffer(buf, bufsize, "CORE does not understand this error code");
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
return core_os_strerror(buf, bufsize, statcode - OS_START_SYSERR);
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,108 @@
|
|||
#include "core.h"
|
||||
#include "core_arch_mutex.h"
|
||||
#include "core_errno.h"
|
||||
#include "core_param.h"
|
||||
#include "core_general.h"
|
||||
#include "core_debug.h"
|
||||
#include "core_pool.h"
|
||||
|
||||
pool_declare(mutex_pool, mutex_t, MAX_NUM_OF_MUTEX);
|
||||
|
||||
status_t mutex_init(void)
|
||||
{
|
||||
pool_init_wo_lock(&mutex_pool, MAX_NUM_OF_MUTEX);
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t mutex_final(void)
|
||||
{
|
||||
pool_final(&mutex_pool);
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t mutex_create(mutex_id *id, unsigned int flags)
|
||||
{
|
||||
mutex_t *new_mutex;
|
||||
status_t rv;
|
||||
|
||||
pool_alloc_node(&mutex_pool, &new_mutex);
|
||||
d_assert(new_mutex, return CORE_ENOMEM, "mutex_pool(%d) is not enough\n",
|
||||
MAX_NUM_OF_MUTEX);
|
||||
|
||||
if (flags & MUTEX_NESTED)
|
||||
{
|
||||
return CORE_ENOTIMPL;
|
||||
}
|
||||
|
||||
if (flags & MUTEX_NESTED)
|
||||
{
|
||||
pthread_mutexattr_t mattr;
|
||||
|
||||
rv = pthread_mutexattr_init(&mattr);
|
||||
if (rv) return rv;
|
||||
|
||||
rv = pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE);
|
||||
if (rv)
|
||||
{
|
||||
pthread_mutexattr_destroy(&mattr);
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = pthread_mutex_init(&new_mutex->mutex, &mattr);
|
||||
|
||||
pthread_mutexattr_destroy(&mattr);
|
||||
} else
|
||||
rv = pthread_mutex_init(&new_mutex->mutex, NULL);
|
||||
|
||||
if (rv)
|
||||
{
|
||||
return rv;
|
||||
}
|
||||
|
||||
*id = (mutex_id)new_mutex;
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t mutex_lock(mutex_id id)
|
||||
{
|
||||
status_t rv;
|
||||
mutex_t *mutex = (mutex_t *)id;
|
||||
|
||||
rv = pthread_mutex_lock(&mutex->mutex);
|
||||
return rv;
|
||||
}
|
||||
|
||||
status_t mutex_trylock(mutex_id id)
|
||||
{
|
||||
status_t rv;
|
||||
mutex_t *mutex = (mutex_t *)id;
|
||||
|
||||
rv = pthread_mutex_trylock(&mutex->mutex);
|
||||
if (rv)
|
||||
{
|
||||
return (rv == EBUSY) ? CORE_EBUSY : rv;
|
||||
}
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t mutex_unlock(mutex_id id)
|
||||
{
|
||||
status_t rv;
|
||||
mutex_t *mutex = (mutex_t *)id;
|
||||
|
||||
rv = pthread_mutex_unlock(&mutex->mutex);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
status_t mutex_delete(mutex_id id)
|
||||
{
|
||||
status_t rv;
|
||||
mutex_t *mutex = (mutex_t *)id;
|
||||
|
||||
rv = pthread_mutex_destroy(&mutex->mutex);
|
||||
pool_free_node(&mutex_pool, mutex);
|
||||
|
||||
return rv;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,498 @@
|
|||
#include "core.h"
|
||||
#define TRACE_MODULE _pkbuf
|
||||
#include "core_pkbuf.h"
|
||||
#include "core_errno.h"
|
||||
#include "core_lib.h"
|
||||
#include "core_debug.h"
|
||||
#include "core_pool.h"
|
||||
|
||||
#define MAX_NUM_OF_CLBUF 32
|
||||
#define MAX_NUM_OF_PKBUF 32
|
||||
|
||||
pool_declare(clbuf_pool, clbuf_t, MAX_NUM_OF_CLBUF);
|
||||
pool_declare(pkbuf_pool, pkbuf_t, MAX_NUM_OF_PKBUF);
|
||||
|
||||
#undef BOUNDARY
|
||||
#define BOUNDARY 4
|
||||
|
||||
#define SIZEOF_CLUSTER_128 CORE_ALIGN(128+MAX_SIZEOF_HEADROOM, BOUNDARY)
|
||||
#define SIZEOF_CLUSTER_256 CORE_ALIGN(256+MAX_SIZEOF_HEADROOM, BOUNDARY)
|
||||
#define SIZEOF_CLUSTER_512 CORE_ALIGN(512+MAX_SIZEOF_HEADROOM, BOUNDARY)
|
||||
#define SIZEOF_CLUSTER_1024 CORE_ALIGN(1024+MAX_SIZEOF_HEADROOM, BOUNDARY)
|
||||
#define SIZEOF_CLUSTER_2048 CORE_ALIGN(2048+MAX_SIZEOF_HEADROOM, BOUNDARY)
|
||||
#define SIZEOF_CLUSTER_8192 CORE_ALIGN(8192+MAX_SIZEOF_HEADROOM, BOUNDARY)
|
||||
|
||||
#define MAX_NUM_OF_CLUSTER_128 32
|
||||
#define MAX_NUM_OF_CLUSTER_256 32
|
||||
#define MAX_NUM_OF_CLUSTER_512 32
|
||||
#define MAX_NUM_OF_CLUSTER_1024 32
|
||||
#define MAX_NUM_OF_CLUSTER_2048 32
|
||||
#define MAX_NUM_OF_CLUSTER_8192 32
|
||||
|
||||
typedef c_uint8_t cluster_128_t[SIZEOF_CLUSTER_128];
|
||||
typedef c_uint8_t cluster_256_t[SIZEOF_CLUSTER_256];
|
||||
typedef c_uint8_t cluster_512_t[SIZEOF_CLUSTER_512];
|
||||
typedef c_uint8_t cluster_1024_t[SIZEOF_CLUSTER_1024];
|
||||
typedef c_uint8_t cluster_2048_t[SIZEOF_CLUSTER_2048];
|
||||
typedef c_uint8_t cluster_8192_t[SIZEOF_CLUSTER_2048];
|
||||
|
||||
pool_declare(cluster_128_pool, cluster_128_t, MAX_NUM_OF_CLUSTER_128);
|
||||
pool_declare(cluster_256_pool, cluster_256_t, MAX_NUM_OF_CLUSTER_256);
|
||||
pool_declare(cluster_512_pool, cluster_512_t, MAX_NUM_OF_CLUSTER_512);
|
||||
pool_declare(cluster_1024_pool, cluster_1024_t, MAX_NUM_OF_CLUSTER_1024);
|
||||
pool_declare(cluster_2048_pool, cluster_2048_t, MAX_NUM_OF_CLUSTER_2048);
|
||||
pool_declare(cluster_8192_pool, cluster_8192_t, MAX_NUM_OF_CLUSTER_8192);
|
||||
|
||||
static mutex_id mutex;
|
||||
|
||||
status_t pkbuf_init(void)
|
||||
{
|
||||
mutex_create(&mutex, MUTEX_DEFAULT);
|
||||
|
||||
pool_init(&clbuf_pool, MAX_NUM_OF_CLBUF);
|
||||
pool_init(&pkbuf_pool, MAX_NUM_OF_PKBUF);
|
||||
|
||||
pool_init(&cluster_128_pool, MAX_NUM_OF_CLUSTER_128);
|
||||
pool_init(&cluster_256_pool, MAX_NUM_OF_CLUSTER_256);
|
||||
pool_init(&cluster_512_pool, MAX_NUM_OF_CLUSTER_512);
|
||||
pool_init(&cluster_1024_pool, MAX_NUM_OF_CLUSTER_1024);
|
||||
pool_init(&cluster_2048_pool, MAX_NUM_OF_CLUSTER_2048);
|
||||
pool_init(&cluster_8192_pool, MAX_NUM_OF_CLUSTER_8192);
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
status_t pkbuf_final(void)
|
||||
{
|
||||
pool_final(&clbuf_pool);
|
||||
pool_final(&pkbuf_pool);
|
||||
|
||||
pool_final(&cluster_128_pool);
|
||||
pool_final(&cluster_256_pool);
|
||||
pool_final(&cluster_512_pool);
|
||||
pool_final(&cluster_1024_pool);
|
||||
pool_final(&cluster_2048_pool);
|
||||
pool_final(&cluster_8192_pool);
|
||||
|
||||
mutex_delete(mutex);
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
void pkbuf_show(void)
|
||||
{
|
||||
d_print("Pkbuf : Size = %d, Avail = %d\n",pool_size(&pkbuf_pool),
|
||||
pool_avail(&pkbuf_pool));
|
||||
d_print("clfbuf : Size = %d, Avail = %d\n\n",pool_size(&clbuf_pool),
|
||||
pool_avail(&clbuf_pool));
|
||||
|
||||
d_print("cluster128 : Size = %d, Avail = %d\n",pool_size(&cluster_128_pool),
|
||||
pool_avail(&cluster_128_pool));
|
||||
d_print("cluster256 : Size = %d, Avail = %d\n",pool_size(&cluster_256_pool),
|
||||
pool_avail(&cluster_256_pool));
|
||||
d_print("cluster512 : Size = %d, Avail = %d\n",pool_size(&cluster_512_pool),
|
||||
pool_avail(&cluster_512_pool));
|
||||
d_print("cluster1024 : Size = %d, Avail = %d\n",
|
||||
pool_size(&cluster_1024_pool),
|
||||
pool_avail(&cluster_128_pool));
|
||||
d_print("cluster2048 : Size = %d, Avail = %d\n",
|
||||
pool_size(&cluster_2048_pool),
|
||||
pool_avail(&cluster_2048_pool));
|
||||
|
||||
}
|
||||
|
||||
static clbuf_t* clbuf_alloc(c_uint16_t length);
|
||||
static void clbuf_free(clbuf_t *clbuf);
|
||||
|
||||
static clbuf_t* clbuf_alloc(c_uint16_t length)
|
||||
{
|
||||
clbuf_t *clbuf = NULL;
|
||||
c_uint8_t *cluster = NULL;
|
||||
|
||||
pool_alloc_node(&clbuf_pool, &clbuf);
|
||||
d_assert(clbuf, return NULL, "No more free clbuf. ");
|
||||
|
||||
if (length <= 128)
|
||||
{
|
||||
pool_alloc_node(&cluster_128_pool, &cluster);
|
||||
clbuf->size = SIZEOF_CLUSTER_128;
|
||||
}
|
||||
else if (length <= 256)
|
||||
{
|
||||
pool_alloc_node(&cluster_256_pool, &cluster);
|
||||
clbuf->size = SIZEOF_CLUSTER_256;
|
||||
}
|
||||
else if (length <= 512)
|
||||
{
|
||||
pool_alloc_node(&cluster_512_pool, &cluster);
|
||||
clbuf->size = SIZEOF_CLUSTER_512;
|
||||
}
|
||||
else if (length <= 1024)
|
||||
{
|
||||
pool_alloc_node(&cluster_1024_pool, &cluster);
|
||||
clbuf->size = SIZEOF_CLUSTER_1024;
|
||||
}
|
||||
else if (length <= 2048)
|
||||
{
|
||||
pool_alloc_node(&cluster_2048_pool, &cluster);
|
||||
clbuf->size = SIZEOF_CLUSTER_2048;
|
||||
}
|
||||
else
|
||||
{
|
||||
pool_alloc_node(&cluster_8192_pool, &cluster);
|
||||
clbuf->size = SIZEOF_CLUSTER_8192;
|
||||
}
|
||||
|
||||
d_assert(cluster, pool_free_node(&clbuf_pool, clbuf); return NULL,
|
||||
"No more free cluster. length:%d requested", length);
|
||||
|
||||
clbuf->ref = 0;
|
||||
clbuf->cluster = cluster;
|
||||
|
||||
return clbuf;
|
||||
}
|
||||
|
||||
static void clbuf_free(clbuf_t *clbuf)
|
||||
{
|
||||
d_assert(clbuf, return, "Null param");
|
||||
d_assert(clbuf->cluster, return, "clbuf has no cluster");
|
||||
|
||||
switch (clbuf->size)
|
||||
{
|
||||
case SIZEOF_CLUSTER_128:
|
||||
pool_free_node(&cluster_128_pool, clbuf->cluster);
|
||||
break;
|
||||
case SIZEOF_CLUSTER_256:
|
||||
pool_free_node(&cluster_256_pool, clbuf->cluster);
|
||||
break;
|
||||
case SIZEOF_CLUSTER_512:
|
||||
pool_free_node(&cluster_512_pool, clbuf->cluster);
|
||||
break;
|
||||
case SIZEOF_CLUSTER_1024:
|
||||
pool_free_node(&cluster_1024_pool, clbuf->cluster);
|
||||
break;
|
||||
case SIZEOF_CLUSTER_2048:
|
||||
pool_free_node(&cluster_2048_pool, clbuf->cluster);
|
||||
break;
|
||||
case SIZEOF_CLUSTER_8192:
|
||||
pool_free_node(&cluster_8192_pool, clbuf->cluster);
|
||||
break;
|
||||
default:
|
||||
d_assert(0, return, "clbuf has invalid size %d", clbuf->size);
|
||||
break;
|
||||
}
|
||||
|
||||
pool_free_node(&clbuf_pool, clbuf);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
pkbuf_t* pkbuf_alloc(c_uint16_t headroom, c_uint16_t length)
|
||||
{
|
||||
pkbuf_t *np = NULL, *pnp, *ret;
|
||||
clbuf_t *clbuf = NULL;
|
||||
c_uint16_t rem_length;
|
||||
|
||||
d_assert(headroom <= MAX_SIZEOF_HEADROOM, return NULL,
|
||||
"Max size of headroom is %d, but %d requested",
|
||||
MAX_SIZEOF_HEADROOM, headroom);
|
||||
|
||||
clbuf = clbuf_alloc(length);
|
||||
d_assert(clbuf, return NULL, "Can't allocate clbuf");
|
||||
|
||||
pool_alloc_node(&pkbuf_pool, &np);
|
||||
d_assert(np, clbuf_free(clbuf); return NULL, "No more free pkbuf");
|
||||
ret = np;
|
||||
|
||||
np->next = NULL;
|
||||
np->clbuf = clbuf;
|
||||
np->payload = (void*)CORE_ALIGN((c_uintptr_t)(clbuf->cluster + headroom), BOUNDARY);
|
||||
np->tot_len = length;
|
||||
np->len = c_min(length, clbuf->size - (np->payload - clbuf->cluster));
|
||||
np->flags = 0;
|
||||
clbuf->ref = 1;
|
||||
|
||||
pnp = np;
|
||||
rem_length = length - np->len;
|
||||
|
||||
while (rem_length > 0)
|
||||
{
|
||||
clbuf = clbuf_alloc(rem_length);
|
||||
d_assert(clbuf, break, "Can't allocate clbuf");
|
||||
|
||||
pool_alloc_node(&pkbuf_pool, &np);
|
||||
d_assert(np, clbuf_free(clbuf); break, "No more free pkbuf");
|
||||
|
||||
/* Chaining */
|
||||
pnp->next = np;
|
||||
|
||||
np->next = NULL;
|
||||
np->clbuf = clbuf;
|
||||
np->payload = clbuf->cluster;
|
||||
np->tot_len = rem_length;
|
||||
np->len = c_min(rem_length, clbuf->size);
|
||||
np->flags = 0;
|
||||
clbuf->ref = 1;
|
||||
|
||||
pnp = np;
|
||||
rem_length -= np->len;
|
||||
}
|
||||
|
||||
/* Abnormal break */
|
||||
if (rem_length > 0)
|
||||
{
|
||||
if (ret)
|
||||
pkbuf_free(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
status_t pkbuf_header(pkbuf_t *pkbuf, c_int16_t increment)
|
||||
{
|
||||
clbuf_t *clbuf;
|
||||
|
||||
d_assert(pkbuf, return CORE_ERROR, "Null param");
|
||||
d_assert(pkbuf->clbuf, return CORE_ERROR, "pkbuf has no clbuf");
|
||||
d_assert(pkbuf->clbuf->cluster, return CORE_ERROR, "clbuf has no cluster");
|
||||
|
||||
clbuf = pkbuf->clbuf;
|
||||
|
||||
/* No change */
|
||||
if (increment == 0)
|
||||
return CORE_OK;
|
||||
|
||||
if (increment > 0)
|
||||
{
|
||||
if (pkbuf->payload - clbuf->cluster < increment)
|
||||
return CORE_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pkbuf->len < -increment)
|
||||
return CORE_ERROR;
|
||||
}
|
||||
|
||||
pkbuf->payload -= increment;
|
||||
pkbuf->tot_len += increment;
|
||||
pkbuf->len += increment;
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
void pkbuf_free(pkbuf_t *pkbuf)
|
||||
{
|
||||
pkbuf_t *p, *q;
|
||||
|
||||
d_assert(pkbuf, return, "Null param");
|
||||
|
||||
p = pkbuf;
|
||||
while (p)
|
||||
{
|
||||
d_assert(p->clbuf, return, "param 'pkbuf' has no clbuf");
|
||||
|
||||
q = p->next;
|
||||
|
||||
mutex_lock(mutex);
|
||||
p->clbuf->ref--;
|
||||
mutex_unlock(mutex);
|
||||
|
||||
if (p->clbuf->ref == 0)
|
||||
clbuf_free(p->clbuf);
|
||||
|
||||
pool_free_node(&pkbuf_pool, p);
|
||||
|
||||
p = q;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void pkbuf_join(pkbuf_t *h, pkbuf_t *t)
|
||||
{
|
||||
pkbuf_t *p;
|
||||
|
||||
d_assert(h, return, "Null param");
|
||||
d_assert(t, return, "Null param");
|
||||
|
||||
/* proceed to last pbuf of chain */
|
||||
for (p = h; p->next != NULL; p = p->next)
|
||||
{
|
||||
/* add total length of second chain to all totals of first chain */
|
||||
p->tot_len += t->tot_len;
|
||||
}
|
||||
|
||||
d_assert(p->tot_len == p->len, return,
|
||||
"p->tot_len(%d) == p->len(%d) (of last pbuf in chain)",
|
||||
p->tot_len, p->len);
|
||||
|
||||
d_assert(p->next == NULL, return, "p->next == NULL");
|
||||
|
||||
/* add total length of second chain to last pbuf total of first chain */
|
||||
p->tot_len += t->tot_len;
|
||||
|
||||
/* chain last pbuf of head (p) with first of tail (t) */
|
||||
p->next = t;
|
||||
|
||||
/* p->next now references t, but the caller will drop its reference to t,
|
||||
* so netto there is no change to the reference count of t. */
|
||||
}
|
||||
|
||||
pkbuf_t* pkbuf_copy(pkbuf_t *pkbuf)
|
||||
{
|
||||
pkbuf_t *p, *np, *pnp = NULL, *ret = NULL;
|
||||
|
||||
d_assert(pkbuf, return NULL, "Null param");
|
||||
|
||||
p = pkbuf;
|
||||
|
||||
while (p)
|
||||
{
|
||||
pool_alloc_node(&pkbuf_pool, &np);
|
||||
d_assert(np, break, "No more free pkbuf. ");
|
||||
if (ret == NULL) ret = np;
|
||||
|
||||
if (pnp)
|
||||
pnp->next = np;
|
||||
|
||||
np->next = NULL;
|
||||
np->clbuf = p->clbuf;
|
||||
np->payload = p->payload;
|
||||
np->tot_len = p->tot_len;
|
||||
np->len = p->len;
|
||||
np->flags = p->flags;
|
||||
|
||||
mutex_lock(mutex);
|
||||
p->clbuf->ref++;
|
||||
mutex_unlock(mutex);
|
||||
|
||||
pnp = np;
|
||||
p = p->next;
|
||||
}
|
||||
|
||||
/* Abnormal break */
|
||||
if (p)
|
||||
{
|
||||
if (ret)
|
||||
pkbuf_free(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
pkbuf_t* pkbuf_copy_partial(pkbuf_t *pkbuf, c_uint16_t offset, c_uint16_t len)
|
||||
{
|
||||
pkbuf_t *p, *np, *pnp = NULL, *ret = NULL;
|
||||
c_uint16_t copied = 0, bytes = 0, skipped = 0;
|
||||
|
||||
d_assert(pkbuf, return NULL, "Null param");
|
||||
|
||||
if (pkbuf->tot_len < offset + len)
|
||||
return NULL;
|
||||
|
||||
p = pkbuf;
|
||||
|
||||
while (p)
|
||||
{
|
||||
bytes += p->len;
|
||||
|
||||
if (bytes > offset)
|
||||
{
|
||||
pool_alloc_node(&pkbuf_pool, &np);
|
||||
d_assert(np, break, "No more free pkbuf. ");
|
||||
|
||||
/* First block */
|
||||
if (ret == NULL)
|
||||
{
|
||||
ret = np;
|
||||
np->payload = p->payload + (offset - skipped);
|
||||
np->tot_len = len;
|
||||
np->len = p->len - (offset - skipped);
|
||||
}
|
||||
else
|
||||
{
|
||||
np->payload = p->payload;
|
||||
np->tot_len = pnp->tot_len - pnp->len;
|
||||
np->len = p->len;
|
||||
}
|
||||
|
||||
np->next = NULL;
|
||||
np->flags = p->flags;
|
||||
np->clbuf = p->clbuf;
|
||||
|
||||
mutex_lock(mutex);
|
||||
p->clbuf->ref++;
|
||||
mutex_unlock(mutex);
|
||||
|
||||
if (pnp)
|
||||
pnp->next = np;
|
||||
pnp = np;
|
||||
|
||||
copied += np->len;
|
||||
|
||||
/* Check the last block */
|
||||
if (copied >= len)
|
||||
{
|
||||
np->len -= copied - len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
skipped += p->len;
|
||||
|
||||
p = p->next;
|
||||
}
|
||||
|
||||
/* Abnormal break */
|
||||
if (copied < len)
|
||||
{
|
||||
if (ret)
|
||||
pkbuf_free(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
status_t pkbuf_tobuf(pkbuf_t *pkbuf, void *buf, c_uint16_t *buflen)
|
||||
{
|
||||
pkbuf_t *p;
|
||||
c_uint16_t copied = 0;
|
||||
|
||||
d_assert(pkbuf, return CORE_ERROR, "Null param");
|
||||
d_assert(buf, return CORE_ERROR, "Null param");
|
||||
d_assert(buflen, return CORE_ERROR, "Null param");
|
||||
|
||||
if (pkbuf->tot_len > *buflen)
|
||||
return CORE_ERROR;
|
||||
|
||||
*buflen = 0;
|
||||
|
||||
p = pkbuf;
|
||||
|
||||
while (p)
|
||||
{
|
||||
d_assert(p->clbuf, return CORE_ERROR, "pkbuf has no clbuf");
|
||||
d_assert(p->clbuf->cluster, return CORE_ERROR, "clbuf has no cluster");
|
||||
|
||||
memcpy(buf + copied, p->payload, p->len);
|
||||
copied += p->len;
|
||||
|
||||
p = p->next;
|
||||
}
|
||||
|
||||
d_assert(copied == pkbuf->tot_len, return CORE_ERROR,
|
||||
"Copy length isn't same with total length");
|
||||
|
||||
*buflen = copied;
|
||||
|
||||
return CORE_OK;;
|
||||
}
|
||||
|
||||
status_t pkbuf_tobuf_partial(pkbuf_t *pkbuf, void *buf, c_uint16_t *buflen,
|
||||
c_uint16_t offset, c_uint16_t len)
|
||||
{
|
||||
|
||||
return CORE_OK;
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
#include "core.h"
|
||||
#include "core_rwlock.h"
|
||||
#include "core_pool.h"
|
||||
#include "core_debug.h"
|
||||
#include "core_general.h"
|
||||
#include "core_param.h"
|
||||
|
||||
typedef struct _rwlock_t {
|
||||
pthread_rwlock_t rwlock;
|
||||
} rwlock_t;
|
||||
|
||||
pool_declare(rwlock_pool, rwlock_t, MAX_NUM_OF_RWLOCK);
|
||||
|
||||
status_t rwlock_init(void)
|
||||
{
|
||||
pool_init(&rwlock_pool, MAX_NUM_OF_RWLOCK);
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t rwlock_final(void)
|
||||
{
|
||||
pool_final(&rwlock_pool);
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t rwlock_create(rwlock_id *id)
|
||||
{
|
||||
rwlock_t *new_rwlock;
|
||||
status_t stat;
|
||||
|
||||
pool_alloc_node(&rwlock_pool, &new_rwlock);
|
||||
d_assert(new_rwlock, return CORE_ENOMEM, "rwlock_pool(%d) is not enough\n",
|
||||
MAX_NUM_OF_RWLOCK);
|
||||
|
||||
if ((stat = pthread_rwlock_init(&new_rwlock->rwlock, NULL)))
|
||||
{
|
||||
return stat;
|
||||
}
|
||||
|
||||
*id = (rwlock_id)new_rwlock;
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t rwlock_rdlock(rwlock_id id)
|
||||
{
|
||||
status_t stat;
|
||||
rwlock_t *rwlock = (rwlock_t *)id;
|
||||
|
||||
stat = pthread_rwlock_rdlock(&rwlock->rwlock);
|
||||
return stat;
|
||||
}
|
||||
|
||||
status_t rwlock_tryrdlock(rwlock_id id)
|
||||
{
|
||||
status_t stat;
|
||||
rwlock_t *rwlock = (rwlock_t *)id;
|
||||
|
||||
stat = pthread_rwlock_tryrdlock(&rwlock->rwlock);
|
||||
/* Normalize the return code. */
|
||||
if (stat == EBUSY)
|
||||
stat = CORE_EBUSY;
|
||||
return stat;
|
||||
}
|
||||
|
||||
status_t rwlock_wrlock(rwlock_id id)
|
||||
{
|
||||
status_t stat;
|
||||
rwlock_t *rwlock = (rwlock_t *)id;
|
||||
|
||||
stat = pthread_rwlock_wrlock(&rwlock->rwlock);
|
||||
return stat;
|
||||
}
|
||||
|
||||
status_t rwlock_trywrlock(rwlock_id id)
|
||||
{
|
||||
status_t stat;
|
||||
rwlock_t *rwlock = (rwlock_t *)id;
|
||||
|
||||
stat = pthread_rwlock_trywrlock(&rwlock->rwlock);
|
||||
/* Normalize the return code. */
|
||||
if (stat == EBUSY)
|
||||
stat = CORE_EBUSY;
|
||||
return stat;
|
||||
}
|
||||
|
||||
status_t rwlock_unlock(rwlock_id id)
|
||||
{
|
||||
status_t stat;
|
||||
rwlock_t *rwlock = (rwlock_t *)id;
|
||||
|
||||
stat = pthread_rwlock_unlock(&rwlock->rwlock);
|
||||
return stat;
|
||||
}
|
||||
|
||||
status_t rwlock_delete(rwlock_id id)
|
||||
{
|
||||
status_t stat;
|
||||
rwlock_t *rwlock = (rwlock_t *)id;
|
||||
|
||||
stat = pthread_rwlock_destroy(&rwlock->rwlock);
|
||||
return stat;
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
#include "core.h"
|
||||
#include "core_arch_semaphore.h"
|
||||
#include "core_errno.h"
|
||||
#include "core_param.h"
|
||||
#include "core_general.h"
|
||||
#include "core_debug.h"
|
||||
#include "core_pool.h"
|
||||
|
||||
pool_declare(semaphore_pool, semaphore_t, MAX_NUM_OF_SEMAPHORE);
|
||||
|
||||
status_t semaphore_init(void)
|
||||
{
|
||||
pool_init(&semaphore_pool, MAX_NUM_OF_SEMAPHORE);
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t semaphore_final(void)
|
||||
{
|
||||
pool_final(&semaphore_pool);
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t semaphore_create(semaphore_id *id, c_uint32_t value)
|
||||
{
|
||||
semaphore_t *new_semaphore;
|
||||
c_time_t now = time_now();
|
||||
char semname[64];
|
||||
|
||||
pool_alloc_node(&semaphore_pool, &new_semaphore);
|
||||
d_assert(new_semaphore, return CORE_ENOMEM,
|
||||
"semaphore_pool(%d) is not enough\n",
|
||||
MAX_NUM_OF_SEMAPHORE);
|
||||
|
||||
sprintf(semname, "/CoRe%" C_UINT64_T_HEX_FMT, now);
|
||||
|
||||
new_semaphore->semaphore = sem_open(semname, O_CREAT | O_EXCL, 0644, value);
|
||||
if (new_semaphore->semaphore == (sem_t *)SEM_FAILED)
|
||||
{
|
||||
return CORE_ERROR;
|
||||
}
|
||||
|
||||
sem_unlink(semname);
|
||||
|
||||
*id = (semaphore_id)new_semaphore;
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t semaphore_wait(semaphore_id id)
|
||||
{
|
||||
status_t rv;
|
||||
semaphore_t *semaphore = (semaphore_t *)id;
|
||||
|
||||
rv = sem_wait(semaphore->semaphore);
|
||||
return rv;
|
||||
}
|
||||
|
||||
#if HAVE_SEM_TIMEDWAIT
|
||||
status_t semaphore_timedwait(semaphore_id id, c_time_t timeout)
|
||||
{
|
||||
status_t rv;
|
||||
c_time_t then;
|
||||
struct timespec abstime;
|
||||
semaphore_t *semaphore = (semaphore_t *)id;
|
||||
|
||||
then = time_now() + timeout;
|
||||
abstime.tv_sec = time_sec(then);
|
||||
abstime.tv_nsec = time_usec(then) * 1000; /* nanosesemaphores */
|
||||
|
||||
rv = sem_timedwait(semaphore->semaphore, &abstime);
|
||||
if (rv == -1 && ETIMEDOUT == errno)
|
||||
{
|
||||
return CORE_TIMEUP;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
|
||||
status_t semaphore_post(semaphore_id id)
|
||||
{
|
||||
status_t rv;
|
||||
semaphore_t *semaphore = (semaphore_t *)id;
|
||||
|
||||
rv = sem_post(semaphore->semaphore);
|
||||
return rv;
|
||||
}
|
||||
|
||||
status_t semaphore_delete(semaphore_id id)
|
||||
{
|
||||
status_t rv;
|
||||
semaphore_t *semaphore = (semaphore_t *)id;
|
||||
|
||||
rv = sem_close(semaphore->semaphore);
|
||||
pool_free_node(&semaphore_pool, semaphore);
|
||||
|
||||
return rv;
|
||||
}
|
|
@ -0,0 +1,239 @@
|
|||
#include "core.h"
|
||||
#include "core_signal.h"
|
||||
|
||||
/*
|
||||
* Replace standard signal() with the more reliable sigaction equivalent
|
||||
* from W. Richard Stevens' "Advanced Programming in the UNIX Environment"
|
||||
* (the version that does not automatically restart system calls).
|
||||
*/
|
||||
core_sigfunc_t *core_signal(int signo, core_sigfunc_t *func)
|
||||
{
|
||||
struct sigaction act, oact;
|
||||
|
||||
act.sa_handler = func;
|
||||
sigemptyset(&act.sa_mask);
|
||||
act.sa_flags = 0;
|
||||
#ifdef SA_INTERRUPT /* SunOS */
|
||||
act.sa_flags |= SA_INTERRUPT;
|
||||
#endif
|
||||
#if defined(__osf__) && defined(__alpha)
|
||||
/* XXX jeff thinks this should be enabled whenever SA_NOCLDWAIT is defined */
|
||||
|
||||
/* this is required on Tru64 to cause child processes to
|
||||
* disappear gracefully - XPG4 compatible
|
||||
*/
|
||||
if ((signo == SIGCHLD) && (func == SIG_IGN))
|
||||
{
|
||||
act.sa_flags |= SA_NOCLDWAIT;
|
||||
}
|
||||
#endif
|
||||
#if defined(__NetBSD__) || defined(DARWIN)
|
||||
/* ignoring SIGCHLD or leaving the default disposition doesn't avoid zombies,
|
||||
* and there is no SA_NOCLDWAIT flag, so catch the signal and reap status in
|
||||
* the handler to avoid zombies
|
||||
*/
|
||||
if ((signo == SIGCHLD) && (func == SIG_IGN))
|
||||
{
|
||||
act.sa_handler = avoid_zombies;
|
||||
}
|
||||
#endif
|
||||
if (sigaction(signo, &act, &oact) < 0)
|
||||
return SIG_ERR;
|
||||
return oact.sa_handler;
|
||||
}
|
||||
|
||||
static void remove_sync_sigs(sigset_t *sig_mask)
|
||||
{
|
||||
#ifdef SIGABRT
|
||||
sigdelset(sig_mask, SIGABRT);
|
||||
#endif
|
||||
#ifdef SIGBUS
|
||||
sigdelset(sig_mask, SIGBUS);
|
||||
#endif
|
||||
#ifdef SIGEMT
|
||||
sigdelset(sig_mask, SIGEMT);
|
||||
#endif
|
||||
#ifdef SIGFPE
|
||||
sigdelset(sig_mask, SIGFPE);
|
||||
#endif
|
||||
#ifdef SIGILL
|
||||
sigdelset(sig_mask, SIGILL);
|
||||
#endif
|
||||
#ifdef SIGIOT
|
||||
sigdelset(sig_mask, SIGIOT);
|
||||
#endif
|
||||
#ifdef SIGPIPE
|
||||
sigdelset(sig_mask, SIGPIPE);
|
||||
#endif
|
||||
#ifdef SIGSEGV
|
||||
sigdelset(sig_mask, SIGSEGV);
|
||||
#endif
|
||||
#ifdef SIGSYS
|
||||
sigdelset(sig_mask, SIGSYS);
|
||||
#endif
|
||||
#ifdef SIGTRAP
|
||||
sigdelset(sig_mask, SIGTRAP);
|
||||
#endif
|
||||
#ifdef SIGCHLD
|
||||
sigdelset(sig_mask, SIGCHLD);
|
||||
#endif
|
||||
#ifdef SIGWINCH
|
||||
sigdelset(sig_mask, SIGWINCH);
|
||||
#endif
|
||||
|
||||
/* the rest of the signals removed from the mask in this function
|
||||
* absolutely must be removed; you cannot block synchronous signals
|
||||
* (requirement of pthreads API)
|
||||
*
|
||||
* SIGUSR2 is being removed from the mask for the convenience of
|
||||
* Purify users (Solaris, HP-UX, SGI) since Purify uses SIGUSR2
|
||||
*/
|
||||
#ifdef SIGUSR2
|
||||
sigdelset(sig_mask, SIGUSR2);
|
||||
#endif
|
||||
}
|
||||
|
||||
status_t signal_thread(int (*signal_handler)(int signum))
|
||||
{
|
||||
sigset_t sig_mask;
|
||||
int (*sig_func)(int signum) = (int (*)(int))signal_handler;
|
||||
|
||||
/* This thread will be the one responsible for handling signals */
|
||||
sigfillset(&sig_mask);
|
||||
|
||||
/* On certain platforms, sigwait() returns EINVAL if any of various
|
||||
* unblockable signals are included in the mask. This was first
|
||||
* observed on AIX and Tru64.
|
||||
*/
|
||||
#ifdef SIGKILL
|
||||
sigdelset(&sig_mask, SIGKILL);
|
||||
#endif
|
||||
#ifdef SIGSTOP
|
||||
sigdelset(&sig_mask, SIGSTOP);
|
||||
#endif
|
||||
#ifdef SIGCONT
|
||||
sigdelset(&sig_mask, SIGCONT);
|
||||
#endif
|
||||
#ifdef SIGWAITING
|
||||
sigdelset(&sig_mask, SIGWAITING);
|
||||
#endif
|
||||
|
||||
/* no synchronous signals should be in the mask passed to sigwait() */
|
||||
remove_sync_sigs(&sig_mask);
|
||||
|
||||
/* On AIX (4.3.3, at least), sigwait() won't wake up if the high-
|
||||
* order bit of the second word of flags is turned on. sigdelset()
|
||||
* returns an error when trying to turn this off, so we'll turn it
|
||||
* off manually.
|
||||
*
|
||||
* Note that the private fields differ between 32-bit and 64-bit
|
||||
* and even between _ALL_SOURCE and !_ALL_SOURCE. Except that on
|
||||
* AIX 4.3 32-bit builds and 64-bit builds use the same definition.
|
||||
*
|
||||
* Applicable AIX fixes such that this is no longer needed:
|
||||
*
|
||||
* APAR IY23096 for AIX 51B, fix included in AIX 51C, and
|
||||
* APAR IY24162 for 43X.
|
||||
*/
|
||||
#if defined(_AIX)
|
||||
#if defined(__64BIT__) && defined(_AIXVERSION_510)
|
||||
#ifdef _ALL_SOURCE
|
||||
sig_mask.ss_set[3] &= 0x7FFFFFFF;
|
||||
#else /* not _ALL_SOURCE */
|
||||
sig_mask.__ss_set[3] &= 0x7FFFFFFF;
|
||||
#endif
|
||||
#else /* not 64-bit build, or 64-bit build on 4.3 */
|
||||
#ifdef _ALL_SOURCE
|
||||
sig_mask.hisigs &= 0x7FFFFFFF;
|
||||
#else /* not _ALL_SOURCE */
|
||||
sig_mask.__hisigs &= 0x7FFFFFFF;
|
||||
#endif
|
||||
#endif
|
||||
#endif /* _AIX */
|
||||
|
||||
while (1) {
|
||||
#if HAVE_SIGWAIT
|
||||
int signal_received;
|
||||
|
||||
if (sigwait(&sig_mask, &signal_received) != 0)
|
||||
{
|
||||
/* handle sigwait() error here */
|
||||
}
|
||||
|
||||
if (sig_func(signal_received) == 1)
|
||||
{
|
||||
return CORE_OK;
|
||||
}
|
||||
#elif HAVE_SIGSUSPEND
|
||||
sigsuspend(&sig_mask);
|
||||
#else
|
||||
#error No sigwait() and no sigsuspend()
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
status_t signal_init(void)
|
||||
{
|
||||
sigset_t sig_mask;
|
||||
int rv;
|
||||
|
||||
/* All threads should mask out signals to be handled by
|
||||
* the thread doing sigwait().
|
||||
*
|
||||
* No thread should ever block synchronous signals.
|
||||
* See the Solaris man page for pthread_sigmask() for
|
||||
* some information. Solaris chooses to knock out such
|
||||
* processes when a blocked synchronous signal is
|
||||
* delivered, skipping any registered signal handler.
|
||||
* AIX doesn't call a signal handler either. At least
|
||||
* one level of linux+glibc does call the handler even
|
||||
* when the synchronous signal is blocked.
|
||||
*/
|
||||
sigfillset(&sig_mask);
|
||||
remove_sync_sigs(&sig_mask);
|
||||
|
||||
if ((rv = pthread_sigmask(SIG_SETMASK, &sig_mask, NULL)) != 0)
|
||||
{
|
||||
rv = errno;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
status_t signal_block(int signum)
|
||||
{
|
||||
#if HAVE_SIGACTION
|
||||
sigset_t sig_mask;
|
||||
int rv;
|
||||
|
||||
sigemptyset(&sig_mask);
|
||||
|
||||
sigaddset(&sig_mask, signum);
|
||||
|
||||
if ((rv = pthread_sigmask(SIG_BLOCK, &sig_mask, NULL)) != 0)
|
||||
{
|
||||
rv = errno;
|
||||
}
|
||||
return rv;
|
||||
#else
|
||||
return ENOTIMPL;
|
||||
#endif
|
||||
}
|
||||
|
||||
status_t signal_unblock(int signum)
|
||||
{
|
||||
#if HAVE_SIGACTION
|
||||
sigset_t sig_mask;
|
||||
int rv;
|
||||
|
||||
sigemptyset(&sig_mask);
|
||||
|
||||
sigaddset(&sig_mask, signum);
|
||||
|
||||
if ((rv = pthread_sigmask(SIG_UNBLOCK, &sig_mask, NULL)) != 0) {
|
||||
rv = errno;
|
||||
}
|
||||
return rv;
|
||||
#else
|
||||
return ENOTIMPL;
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
#include "core.h"
|
||||
#include "core_general.h"
|
||||
#include "core_debug.h"
|
||||
#include "core_pool.h"
|
||||
#include "core_msgq.h"
|
||||
#include "core_tlv.h"
|
||||
#include "core_timer.h"
|
||||
#include "core_mutex.h"
|
||||
#include "core_cond.h"
|
||||
#include "core_rwlock.h"
|
||||
#include "core_semaphore.h"
|
||||
#include "core_thread.h"
|
||||
#include "core_net.h"
|
||||
#include "core_file.h"
|
||||
#include "core_pkbuf.h"
|
||||
|
||||
status_t core_app_initialize(int *argc,
|
||||
const char * const * *argv,
|
||||
const char * const * *env)
|
||||
{
|
||||
/* An absolute noop. At present, only Win32 requires this stub, but it's
|
||||
* required in order to move command arguments passed through the service
|
||||
* control manager into the process, and it's required to fix the char*
|
||||
* data passed in from win32 unicode into utf-8, win32's core internal fmt.
|
||||
*/
|
||||
return core_initialize();
|
||||
}
|
||||
|
||||
static int initialized = 0;
|
||||
|
||||
status_t core_initialize(void)
|
||||
{
|
||||
if (initialized++)
|
||||
{
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
/* IMPORTANT: Mutex should be initialized firtly because node-pool
|
||||
* framework uses mutex and it will be used by other xxx_init() */
|
||||
mutex_init();
|
||||
semaphore_init();
|
||||
cond_init();
|
||||
rwlock_init();
|
||||
thread_init();
|
||||
net_init();
|
||||
file_init();
|
||||
pkbuf_init();
|
||||
tlv_init();
|
||||
tm_init();
|
||||
msgq_init();
|
||||
d_msg_init();
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
void core_terminate(void)
|
||||
{
|
||||
initialized--;
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reverse ordered finalization */
|
||||
d_msg_final();
|
||||
msgq_final();
|
||||
tm_final();
|
||||
tlv_final();
|
||||
pkbuf_final();
|
||||
tlv_init();
|
||||
file_final();
|
||||
net_final();
|
||||
thread_final();
|
||||
rwlock_final();
|
||||
cond_final();
|
||||
semaphore_final();
|
||||
mutex_final();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void core_terminate2(void)
|
||||
{
|
||||
core_terminate();
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
#include "core.h"
|
||||
#include "core_thread.h"
|
||||
#include "core_errno.h"
|
||||
#include "core_param.h"
|
||||
#include "core_general.h"
|
||||
#define TRACE_MODULE _thread
|
||||
#include "core_debug.h"
|
||||
#include "core_pool.h"
|
||||
#include "core_semaphore.h"
|
||||
|
||||
typedef struct _thread_t {
|
||||
pthread_t thread;
|
||||
void *data;
|
||||
thread_start_t func;
|
||||
|
||||
semaphore_id semaphore;
|
||||
} thread_t;
|
||||
|
||||
struct thread_stop_info {
|
||||
pthread_t thread;
|
||||
semaphore_id semaphore;
|
||||
};
|
||||
|
||||
struct threadattr_t {
|
||||
pthread_attr_t attr;
|
||||
};
|
||||
|
||||
pool_declare(thread_pool, thread_t, MAX_NUM_OF_THREAD);
|
||||
pool_declare(threadattr_pool, threadattr_t, MAX_NUM_OF_THREADATTR);
|
||||
|
||||
static struct thread_stop_info thread_stop_info;
|
||||
|
||||
int thread_should_stop(void)
|
||||
{
|
||||
return (thread_stop_info.thread == pthread_self());
|
||||
}
|
||||
|
||||
status_t thread_init(void)
|
||||
{
|
||||
pool_init(&thread_pool, MAX_NUM_OF_THREAD);
|
||||
pool_init(&threadattr_pool, MAX_NUM_OF_THREADATTR);
|
||||
|
||||
memset(&thread_stop_info, 0, sizeof(thread_stop_info));
|
||||
|
||||
semaphore_create(&thread_stop_info.semaphore, 0);
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t thread_final(void)
|
||||
{
|
||||
pool_final(&thread_pool);
|
||||
pool_final(&threadattr_pool);
|
||||
|
||||
semaphore_delete(thread_stop_info.semaphore);
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t threadattr_create(threadattr_t **new)
|
||||
{
|
||||
status_t stat;
|
||||
|
||||
pool_alloc_node(&threadattr_pool, &(*new));
|
||||
d_assert((*new), return CORE_ENOMEM, "threadattr_pool(%d) is not enough\n",
|
||||
MAX_NUM_OF_THREADATTR);
|
||||
stat = pthread_attr_init(&(*new)->attr);
|
||||
|
||||
if (stat == 0)
|
||||
{
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
return stat;
|
||||
}
|
||||
|
||||
status_t threadattr_stacksize_set(
|
||||
threadattr_t *attr, size_t stacksize)
|
||||
{
|
||||
int stat;
|
||||
|
||||
stat = pthread_attr_setstacksize(&attr->attr, stacksize);
|
||||
if (stat == 0)
|
||||
{
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
return stat;
|
||||
}
|
||||
|
||||
status_t threadattr_delete(threadattr_t *attr)
|
||||
{
|
||||
status_t stat;
|
||||
|
||||
stat = pthread_attr_destroy(&attr->attr);
|
||||
pool_free_node(&threadattr_pool, attr);
|
||||
|
||||
if (stat == 0)
|
||||
{
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
return stat;
|
||||
}
|
||||
|
||||
static void *dummy_worker(void *opaque)
|
||||
{
|
||||
void *func = NULL;
|
||||
thread_t *thread = (thread_t *)opaque;
|
||||
|
||||
thread->thread = pthread_self();
|
||||
semaphore_post(thread->semaphore);
|
||||
d_trace(3, "[%d] dummy_worker post semaphore\n", thread->thread);
|
||||
|
||||
if (!thread_should_stop())
|
||||
func = thread->func(thread->data);
|
||||
|
||||
d_trace(3, "[%d] thread stopped = %d\n",
|
||||
thread->thread, thread_should_stop());
|
||||
semaphore_post(thread_stop_info.semaphore);
|
||||
d_trace(3, "[%d] post semaphore for therad_stop_info.semaphore\n",
|
||||
thread->thread);
|
||||
|
||||
return func;
|
||||
}
|
||||
|
||||
status_t thread_create(thread_id *id,
|
||||
threadattr_t *attr, thread_start_t func, void *data)
|
||||
{
|
||||
status_t stat;
|
||||
pthread_attr_t *temp;
|
||||
thread_t *new = NULL;
|
||||
|
||||
pool_alloc_node(&thread_pool, &new);
|
||||
d_assert(new, return CORE_ENOMEM, "thread_pool(%d) is not enough\n",
|
||||
MAX_NUM_OF_THREAD);
|
||||
memset(new, 0, sizeof(thread_id));
|
||||
|
||||
new->data = data;
|
||||
new->func = func;
|
||||
|
||||
semaphore_create(&new->semaphore, 0);
|
||||
|
||||
if (attr)
|
||||
temp = &attr->attr;
|
||||
else
|
||||
temp = NULL;
|
||||
|
||||
if ((stat = pthread_create(&new->thread, temp, dummy_worker, new)) != 0)
|
||||
{
|
||||
return stat;
|
||||
}
|
||||
|
||||
d_trace(3, "thread_create wait\n");
|
||||
semaphore_wait(new->semaphore);
|
||||
d_trace(3, "thread_create done\n");
|
||||
|
||||
*id = (thread_id)new;
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t thread_delete(thread_id id)
|
||||
{
|
||||
thread_t *thread = (thread_t *)id;
|
||||
|
||||
thread_stop_info.thread = thread->thread;
|
||||
d_trace(3, "thread_stop_info.thread for %d\n", thread_stop_info.thread);
|
||||
semaphore_wait(thread_stop_info.semaphore);
|
||||
d_trace(3, "semaphore_wait done\n");
|
||||
thread_stop_info.thread = 0;
|
||||
|
||||
pthread_join(thread->thread, 0);
|
||||
|
||||
semaphore_delete(thread->semaphore);
|
||||
pool_free_node(&thread_pool, thread);
|
||||
d_trace(3, "delete thread-related memory\n");
|
||||
|
||||
return CORE_OK;
|
||||
}
|
|
@ -0,0 +1,255 @@
|
|||
#include "core.h"
|
||||
#include "core_time.h"
|
||||
|
||||
static c_int32_t get_offset(struct tm *tm)
|
||||
{
|
||||
#if defined(HAVE_STRUCT_TM_TM_GMTOFF)
|
||||
return tm->tm_gmtoff;
|
||||
#elif defined(HAVE_STRUCT_TM___TM_GMTOFF)
|
||||
return tm->__tm_gmtoff;
|
||||
#else
|
||||
#error cannot support tm->tm_gmtoff
|
||||
#endif
|
||||
}
|
||||
|
||||
status_t time_ansi_put(c_time_t *result, time_t input)
|
||||
{
|
||||
*result = (c_time_t)input * USEC_PER_SEC;
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
/* NB NB NB NB This returns GMT!!!!!!!!!! */
|
||||
c_time_t time_now(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return tv.tv_sec * USEC_PER_SEC + tv.tv_usec;
|
||||
}
|
||||
|
||||
void core_sleep(c_time_t t)
|
||||
{
|
||||
#ifdef OS2
|
||||
DosSleep(t/1000);
|
||||
#elif defined(BEOS)
|
||||
snooze(t);
|
||||
#elif defined(NETWARE)
|
||||
delay(t/1000);
|
||||
#else
|
||||
struct timeval tv;
|
||||
tv.tv_usec = t % USEC_PER_SEC;
|
||||
tv.tv_sec = t / USEC_PER_SEC;
|
||||
select(0, NULL, NULL, NULL, &tv);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void explode_time(time_exp_t *xt, c_time_t t,
|
||||
c_int32_t offset, int use_localtime)
|
||||
{
|
||||
struct tm tm;
|
||||
time_t tt = (t / USEC_PER_SEC) + offset;
|
||||
xt->tm_usec = t % USEC_PER_SEC;
|
||||
|
||||
#if defined (_POSIX_THREAD_SAFE_FUNCTIONS)
|
||||
if (use_localtime)
|
||||
localtime_r(&tt, &tm);
|
||||
else
|
||||
gmtime_r(&tt, &tm);
|
||||
#else
|
||||
if (use_localtime)
|
||||
tm = *localtime(&tt);
|
||||
else
|
||||
tm = *gmtime(&tt);
|
||||
#endif
|
||||
|
||||
xt->tm_sec = tm.tm_sec;
|
||||
xt->tm_min = tm.tm_min;
|
||||
xt->tm_hour = tm.tm_hour;
|
||||
xt->tm_mday = tm.tm_mday;
|
||||
xt->tm_mon = tm.tm_mon;
|
||||
xt->tm_year = tm.tm_year;
|
||||
xt->tm_wday = tm.tm_wday;
|
||||
xt->tm_yday = tm.tm_yday;
|
||||
xt->tm_isdst = tm.tm_isdst;
|
||||
xt->tm_gmtoff = get_offset(&tm);
|
||||
}
|
||||
|
||||
status_t time_exp_tz(time_exp_t *result,
|
||||
c_time_t input, c_int32_t offs)
|
||||
{
|
||||
explode_time(result, input, offs, 0);
|
||||
result->tm_gmtoff = offs;
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t time_exp_gmt(time_exp_t *result, c_time_t input)
|
||||
{
|
||||
return time_exp_tz(result, input, 0);
|
||||
}
|
||||
|
||||
status_t time_exp_lt(time_exp_t *result, c_time_t input)
|
||||
{
|
||||
#if defined(__EMX__)
|
||||
/* EMX gcc (OS/2) has a timezone global we can use */
|
||||
return time_exp_tz(result, input, -timezone);
|
||||
#else
|
||||
explode_time(result, input, 0, 1);
|
||||
return CORE_OK;
|
||||
#endif /* __EMX__ */
|
||||
}
|
||||
|
||||
status_t time_exp_get(c_time_t *t, time_exp_t *xt)
|
||||
{
|
||||
time_t year = xt->tm_year;
|
||||
time_t days;
|
||||
static const int dayoffset[12] =
|
||||
{306, 337, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275};
|
||||
|
||||
/* shift new year to 1st March in order to make leap year calc easy */
|
||||
|
||||
if (xt->tm_mon < 2)
|
||||
year--;
|
||||
|
||||
/* Find number of days since 1st March 1900 (in the Gregorian calendar). */
|
||||
|
||||
days = year * 365 + year / 4 - year / 100 + (year / 100 + 3) / 4;
|
||||
days += dayoffset[xt->tm_mon] + xt->tm_mday - 1;
|
||||
days -= 25508; /* 1 jan 1970 is 25508 days since 1 mar 1900 */
|
||||
days = ((days * 24 + xt->tm_hour) * 60 + xt->tm_min) * 60 + xt->tm_sec;
|
||||
|
||||
if (days < 0) {
|
||||
return CORE_EBADDATE;
|
||||
}
|
||||
*t = days * USEC_PER_SEC + xt->tm_usec;
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t time_exp_gmt_get(c_time_t *t,
|
||||
time_exp_t *xt)
|
||||
{
|
||||
status_t status = time_exp_get(t, xt);
|
||||
if (status == CORE_OK)
|
||||
*t -= (time_t) xt->tm_gmtoff * USEC_PER_SEC;
|
||||
return status;
|
||||
}
|
||||
|
||||
const char month_snames[12][4] =
|
||||
{
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
const char day_snames[7][4] =
|
||||
{
|
||||
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
|
||||
};
|
||||
|
||||
status_t rfc822_date(char *date_str, c_time_t t)
|
||||
{
|
||||
time_exp_t xt;
|
||||
const char *s;
|
||||
int real_year;
|
||||
|
||||
time_exp_gmt(&xt, t);
|
||||
|
||||
/* example: "Sat, 08 Jan 2000 18:31:41 GMT" */
|
||||
/* 12345678901234567890123456789 */
|
||||
|
||||
s = &day_snames[xt.tm_wday][0];
|
||||
*date_str++ = *s++;
|
||||
*date_str++ = *s++;
|
||||
*date_str++ = *s++;
|
||||
*date_str++ = ',';
|
||||
*date_str++ = ' ';
|
||||
*date_str++ = xt.tm_mday / 10 + '0';
|
||||
*date_str++ = xt.tm_mday % 10 + '0';
|
||||
*date_str++ = ' ';
|
||||
s = &month_snames[xt.tm_mon][0];
|
||||
*date_str++ = *s++;
|
||||
*date_str++ = *s++;
|
||||
*date_str++ = *s++;
|
||||
*date_str++ = ' ';
|
||||
real_year = 1900 + xt.tm_year;
|
||||
/* This routine isn't y10k ready. */
|
||||
*date_str++ = real_year / 1000 + '0';
|
||||
*date_str++ = real_year % 1000 / 100 + '0';
|
||||
*date_str++ = real_year % 100 / 10 + '0';
|
||||
*date_str++ = real_year % 10 + '0';
|
||||
*date_str++ = ' ';
|
||||
*date_str++ = xt.tm_hour / 10 + '0';
|
||||
*date_str++ = xt.tm_hour % 10 + '0';
|
||||
*date_str++ = ':';
|
||||
*date_str++ = xt.tm_min / 10 + '0';
|
||||
*date_str++ = xt.tm_min % 10 + '0';
|
||||
*date_str++ = ':';
|
||||
*date_str++ = xt.tm_sec / 10 + '0';
|
||||
*date_str++ = xt.tm_sec % 10 + '0';
|
||||
*date_str++ = ' ';
|
||||
*date_str++ = 'G';
|
||||
*date_str++ = 'M';
|
||||
*date_str++ = 'T';
|
||||
*date_str++ = 0;
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t core_ctime(char *date_str, c_time_t t)
|
||||
{
|
||||
time_exp_t xt;
|
||||
const char *s;
|
||||
int real_year;
|
||||
|
||||
/* example: "Wed Jun 30 21:49:08 1993" */
|
||||
/* 123456789012345678901234 */
|
||||
|
||||
time_exp_lt(&xt, t);
|
||||
s = &day_snames[xt.tm_wday][0];
|
||||
*date_str++ = *s++;
|
||||
*date_str++ = *s++;
|
||||
*date_str++ = *s++;
|
||||
*date_str++ = ' ';
|
||||
s = &month_snames[xt.tm_mon][0];
|
||||
*date_str++ = *s++;
|
||||
*date_str++ = *s++;
|
||||
*date_str++ = *s++;
|
||||
*date_str++ = ' ';
|
||||
*date_str++ = xt.tm_mday / 10 + '0';
|
||||
*date_str++ = xt.tm_mday % 10 + '0';
|
||||
*date_str++ = ' ';
|
||||
*date_str++ = xt.tm_hour / 10 + '0';
|
||||
*date_str++ = xt.tm_hour % 10 + '0';
|
||||
*date_str++ = ':';
|
||||
*date_str++ = xt.tm_min / 10 + '0';
|
||||
*date_str++ = xt.tm_min % 10 + '0';
|
||||
*date_str++ = ':';
|
||||
*date_str++ = xt.tm_sec / 10 + '0';
|
||||
*date_str++ = xt.tm_sec % 10 + '0';
|
||||
*date_str++ = ' ';
|
||||
real_year = 1900 + xt.tm_year;
|
||||
*date_str++ = real_year / 1000 + '0';
|
||||
*date_str++ = real_year % 1000 / 100 + '0';
|
||||
*date_str++ = real_year % 100 / 10 + '0';
|
||||
*date_str++ = real_year % 10 + '0';
|
||||
*date_str++ = 0;
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t core_strftime(char *s, size_t *retsize, size_t max,
|
||||
const char *format, time_exp_t *xt)
|
||||
{
|
||||
struct tm tm;
|
||||
memset(&tm, 0, sizeof tm);
|
||||
tm.tm_sec = xt->tm_sec;
|
||||
tm.tm_min = xt->tm_min;
|
||||
tm.tm_hour = xt->tm_hour;
|
||||
tm.tm_mday = xt->tm_mday;
|
||||
tm.tm_mon = xt->tm_mon;
|
||||
tm.tm_year = xt->tm_year;
|
||||
tm.tm_wday = xt->tm_wday;
|
||||
tm.tm_yday = xt->tm_yday;
|
||||
tm.tm_isdst = xt->tm_isdst;
|
||||
#if defined(HAVE_STRUCT_TM_TM_GMTOFF)
|
||||
tm.tm_gmtoff = xt->tm_gmtoff;
|
||||
#elif defined(HAVE_STRUCT_TM___TM_GMTOFF)
|
||||
tm.__tm_gmtoff = xt->tm_gmtoff;
|
||||
#endif
|
||||
(*retsize) = strftime(s, max, format, &tm);
|
||||
return CORE_OK;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#include "core_version.h"
|
||||
#include "core_general.h" /* for CORE_STRINGIFY */
|
||||
|
||||
CORE_DECLARE(void) core_version(core_version_t *pvsn)
|
||||
{
|
||||
pvsn->major = CORE_MAJOR_VERSION;
|
||||
pvsn->minor = CORE_MINOR_VERSION;
|
||||
pvsn->patch = CORE_PATCH_VERSION;
|
||||
#ifdef CORE_IS_DEV_VERSION
|
||||
pvsn->is_dev = 1;
|
||||
#else
|
||||
pvsn->is_dev = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
CORE_DECLARE(const char *) core_version_string(void)
|
||||
{
|
||||
return CORE_VERSION_STRING;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
## Process this file with automake to produce Makefile.in.
|
||||
|
||||
bin_PROGRAMS = testcore
|
||||
|
||||
nodist_testcore_SOURCES = \
|
||||
abts.c testds.c testfsm.c testnetlib.c testthread.c testtlv.c \
|
||||
testaes.c testfile.c testlock.c testsha.c testtime.c testutil.c \
|
||||
testdir.c testfilecopy.c testmsgq.c testsleep.c testtimer.c \
|
||||
abts.h abts_tests.h testutil.h
|
||||
|
||||
testcore_LDADD = \
|
||||
$(top_srcdir)/lib/core/src/libcore.la \
|
||||
-lpthread -lsctp
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/lib/core/include/arch/@OSDIR@ \
|
||||
-I$(top_srcdir)/lib/core/include
|
||||
|
||||
AM_CFLAGS = \
|
||||
-Wall -Werror @OSCFLAGS@ \
|
||||
-Wno-unused-function
|
||||
|
||||
TESTS = testcore
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
CLEANFILES = -R data
|
||||
MOSTLYCLEANFILES = core *.stackdump
|
|
@ -0,0 +1,458 @@
|
|||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "abts.h"
|
||||
#include "abts_tests.h"
|
||||
#include "testutil.h"
|
||||
|
||||
#define ABTS_STAT_SIZE 6
|
||||
static char status[ABTS_STAT_SIZE] = {'|', '/', '-', '|', '\\', '-'};
|
||||
static int curr_char;
|
||||
static int verbose = 1;
|
||||
static int exclude = 0;
|
||||
static int quiet = 0;
|
||||
static int list_tests = 0;
|
||||
|
||||
const char **testlist = NULL;
|
||||
|
||||
static int find_test_name(const char *testname) {
|
||||
int i;
|
||||
for (i = 0; testlist[i] != NULL; i++) {
|
||||
if (!strcmp(testlist[i], testname)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Determine if the test should be run at all */
|
||||
static int should_test_run(const char *testname) {
|
||||
int found = 0;
|
||||
if (list_tests == 1) {
|
||||
return 0;
|
||||
}
|
||||
if (testlist == NULL) {
|
||||
return 1;
|
||||
}
|
||||
found = find_test_name(testname);
|
||||
if ((found && !exclude) || (!found && exclude)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void reset_status(void)
|
||||
{
|
||||
curr_char = 0;
|
||||
}
|
||||
|
||||
static void update_status(void)
|
||||
{
|
||||
if (!quiet) {
|
||||
curr_char = (curr_char + 1) % ABTS_STAT_SIZE;
|
||||
fprintf(stdout, "\b%c", status[curr_char]);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
static void end_suite(abts_suite *suite)
|
||||
{
|
||||
if (suite != NULL) {
|
||||
sub_suite *last = suite->tail;
|
||||
if (!quiet) {
|
||||
fprintf(stdout, "\b");
|
||||
fflush(stdout);
|
||||
}
|
||||
if (last->failed == 0) {
|
||||
fprintf(stdout, "SUCCESS\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
else {
|
||||
fprintf(stdout, "FAILED %d of %d\n", last->failed, last->num_test);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abts_suite *abts_add_suite(abts_suite *suite, const char *suite_name_full)
|
||||
{
|
||||
sub_suite *subsuite;
|
||||
char *p;
|
||||
const char *suite_name;
|
||||
curr_char = 0;
|
||||
|
||||
/* Only end the suite if we actually ran it */
|
||||
if (suite && suite->tail &&!suite->tail->not_run) {
|
||||
end_suite(suite);
|
||||
}
|
||||
|
||||
subsuite = malloc(sizeof(*subsuite));
|
||||
subsuite->num_test = 0;
|
||||
subsuite->failed = 0;
|
||||
subsuite->next = NULL;
|
||||
/* suite_name_full may be an absolute path depending on __FILE__
|
||||
* expansion */
|
||||
suite_name = strrchr(suite_name_full, '/');
|
||||
if (suite_name) {
|
||||
suite_name++;
|
||||
} else {
|
||||
suite_name = suite_name_full;
|
||||
}
|
||||
p = strrchr(suite_name, '.');
|
||||
if (p) {
|
||||
subsuite->name = memcpy(calloc(p - suite_name + 1, 1),
|
||||
suite_name, p - suite_name);
|
||||
}
|
||||
else {
|
||||
subsuite->name = suite_name;
|
||||
}
|
||||
|
||||
if (list_tests) {
|
||||
fprintf(stdout, "%s\n", subsuite->name);
|
||||
}
|
||||
|
||||
subsuite->not_run = 0;
|
||||
|
||||
if (suite == NULL) {
|
||||
suite = malloc(sizeof(*suite));
|
||||
suite->head = subsuite;
|
||||
suite->tail = subsuite;
|
||||
}
|
||||
else {
|
||||
suite->tail->next = subsuite;
|
||||
suite->tail = subsuite;
|
||||
}
|
||||
|
||||
if (!should_test_run(subsuite->name)) {
|
||||
subsuite->not_run = 1;
|
||||
return suite;
|
||||
}
|
||||
|
||||
reset_status();
|
||||
fprintf(stdout, "%-20s: ", subsuite->name);
|
||||
update_status();
|
||||
fflush(stdout);
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
||||
void abts_run_test(abts_suite *ts, test_func f, void *value)
|
||||
{
|
||||
abts_case tc;
|
||||
sub_suite *ss;
|
||||
|
||||
if (!should_test_run(ts->tail->name)) {
|
||||
return;
|
||||
}
|
||||
ss = ts->tail;
|
||||
|
||||
tc.failed = 0;
|
||||
tc.suite = ss;
|
||||
|
||||
ss->num_test++;
|
||||
update_status();
|
||||
|
||||
f(&tc, value);
|
||||
|
||||
if (tc.failed) {
|
||||
ss->failed++;
|
||||
}
|
||||
}
|
||||
|
||||
static int report(abts_suite *suite)
|
||||
{
|
||||
int count = 0;
|
||||
sub_suite *dptr;
|
||||
|
||||
if (suite && suite->tail &&!suite->tail->not_run) {
|
||||
end_suite(suite);
|
||||
}
|
||||
|
||||
for (dptr = suite->head; dptr; dptr = dptr->next) {
|
||||
count += dptr->failed;
|
||||
}
|
||||
|
||||
if (list_tests) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
printf("All tests passed.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dptr = suite->head;
|
||||
fprintf(stdout, "%-15s\t\tTotal\tFail\tFailed %%\n", "Failed Tests");
|
||||
fprintf(stdout, "===================================================\n");
|
||||
while (dptr != NULL) {
|
||||
if (dptr->failed != 0) {
|
||||
float percent = ((float)dptr->failed / (float)dptr->num_test);
|
||||
fprintf(stdout, "%-15s\t\t%5d\t%4d\t%6.2f%%\n", dptr->name,
|
||||
dptr->num_test, dptr->failed, percent * 100);
|
||||
}
|
||||
dptr = dptr->next;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void abts_log_message(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
update_status();
|
||||
|
||||
if (verbose) {
|
||||
va_start(args, fmt);
|
||||
vfprintf(stderr, fmt, args);
|
||||
va_end(args);
|
||||
fprintf(stderr, "\n");
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
|
||||
void abts_int_equal(abts_case *tc, const int expected, const int actual, int lineno)
|
||||
{
|
||||
update_status();
|
||||
if (tc->failed) return;
|
||||
|
||||
if (expected == actual) return;
|
||||
|
||||
tc->failed = TRUE;
|
||||
if (verbose) {
|
||||
fprintf(stderr, "Line %d: expected <%d>, but saw <%d>\n", lineno, expected, actual);
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
|
||||
void abts_int_nequal(abts_case *tc, const int expected, const int actual, int lineno)
|
||||
{
|
||||
update_status();
|
||||
if (tc->failed) return;
|
||||
|
||||
if (expected != actual) return;
|
||||
|
||||
tc->failed = TRUE;
|
||||
if (verbose) {
|
||||
fprintf(stderr, "Line %d: expected <%d>, but saw <%d>\n", lineno, expected, actual);
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
|
||||
void abts_size_equal(abts_case *tc, size_t expected, size_t actual, int lineno)
|
||||
{
|
||||
update_status();
|
||||
if (tc->failed) return;
|
||||
|
||||
if (expected == actual) return;
|
||||
|
||||
tc->failed = TRUE;
|
||||
if (verbose) {
|
||||
/* Note that the comparison is type-exact, reporting must be a best-fit */
|
||||
fprintf(stderr, "Line %d: expected %lu, but saw %lu\n", lineno,
|
||||
(unsigned long)expected, (unsigned long)actual);
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
|
||||
void abts_str_equal(abts_case *tc, const char *expected, const char *actual, int lineno)
|
||||
{
|
||||
update_status();
|
||||
if (tc->failed) return;
|
||||
|
||||
if (!expected && !actual) return;
|
||||
if (expected && actual)
|
||||
if (!strcmp(expected, actual)) return;
|
||||
|
||||
tc->failed = TRUE;
|
||||
if (verbose) {
|
||||
fprintf(stderr, "Line %d: expected <%s>, but saw <%s>\n", lineno, expected, actual);
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
|
||||
void abts_str_nequal(abts_case *tc, const char *expected, const char *actual,
|
||||
size_t n, int lineno)
|
||||
{
|
||||
update_status();
|
||||
if (tc->failed) return;
|
||||
|
||||
if (!strncmp(expected, actual, n)) return;
|
||||
|
||||
tc->failed = TRUE;
|
||||
if (verbose) {
|
||||
fprintf(stderr, "Line %d: expected <%s>, but saw <%s>\n", lineno, expected, actual);
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
|
||||
void abts_ptr_null(abts_case *tc, const void *ptr, int lineno)
|
||||
{
|
||||
update_status();
|
||||
if (tc->failed) return;
|
||||
|
||||
if (ptr == NULL) return;
|
||||
|
||||
tc->failed = TRUE;
|
||||
if (verbose) {
|
||||
fprintf(stderr, "Line %d: Expected NULL, but saw <%p>\n", lineno, ptr);
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
|
||||
void abts_ptr_notnull(abts_case *tc, const void *ptr, int lineno)
|
||||
{
|
||||
update_status();
|
||||
if (tc->failed) return;
|
||||
|
||||
if (ptr != NULL) return;
|
||||
|
||||
tc->failed = TRUE;
|
||||
if (verbose) {
|
||||
fprintf(stderr, "Line %d: Expected not NULL, but saw <%p>\n", lineno, ptr);
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
|
||||
void abts_ptr_equal(abts_case *tc, const void *expected, const void *actual, int lineno)
|
||||
{
|
||||
update_status();
|
||||
if (tc->failed) return;
|
||||
|
||||
if (expected == actual) return;
|
||||
|
||||
tc->failed = TRUE;
|
||||
if (verbose) {
|
||||
fprintf(stderr, "Line %d: expected <%p>, but saw <%p>\n", lineno, expected, actual);
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
|
||||
void abts_fail(abts_case *tc, const char *message, int lineno)
|
||||
{
|
||||
update_status();
|
||||
if (tc->failed) return;
|
||||
|
||||
tc->failed = TRUE;
|
||||
if (verbose) {
|
||||
fprintf(stderr, "Line %d: %s\n", lineno, message);
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
|
||||
void abts_assert(abts_case *tc, const char *message, int condition, int lineno)
|
||||
{
|
||||
update_status();
|
||||
if (tc->failed) return;
|
||||
|
||||
if (condition) return;
|
||||
|
||||
tc->failed = TRUE;
|
||||
if (verbose) {
|
||||
fprintf(stderr, "Line %d: %s\n", lineno, message);
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
|
||||
void abts_true(abts_case *tc, int condition, int lineno)
|
||||
{
|
||||
update_status();
|
||||
if (tc->failed) return;
|
||||
|
||||
if (condition) return;
|
||||
|
||||
tc->failed = TRUE;
|
||||
if (verbose) {
|
||||
fprintf(stderr, "Line %d: Condition is false, but expected true\n", lineno);
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
|
||||
void abts_false(abts_case *tc, int condition, int lineno)
|
||||
{
|
||||
update_status();
|
||||
if (tc->failed) return;
|
||||
|
||||
if (!condition) return;
|
||||
|
||||
tc->failed = TRUE;
|
||||
if (verbose) {
|
||||
fprintf(stderr, "Line %d: Condition is true, but expected false\n", lineno);
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
|
||||
void abts_not_impl(abts_case *tc, const char *message, int lineno)
|
||||
{
|
||||
update_status();
|
||||
|
||||
tc->suite->not_impl++;
|
||||
if (verbose) {
|
||||
fprintf(stderr, "Line %d: %s\n", lineno, message);
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, const char *const argv[]) {
|
||||
int i;
|
||||
int rv;
|
||||
int list_provided = 0;
|
||||
abts_suite *suite = NULL;
|
||||
|
||||
test_initialize();
|
||||
|
||||
quiet = !isatty(STDOUT_FILENO);
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (!strcmp(argv[i], "-v")) {
|
||||
verbose = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(argv[i], "-x")) {
|
||||
exclude = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(argv[i], "-l")) {
|
||||
list_tests = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(argv[i], "-q")) {
|
||||
quiet = 1;
|
||||
continue;
|
||||
}
|
||||
if (argv[i][0] == '-') {
|
||||
fprintf(stderr, "Invalid option: `%s'\n", argv[i]);
|
||||
exit(1);
|
||||
}
|
||||
list_provided = 1;
|
||||
}
|
||||
|
||||
if (list_provided) {
|
||||
/* Waste a little space here, because it is easier than counting the
|
||||
* number of tests listed. Besides it is at most three char *.
|
||||
*/
|
||||
testlist = calloc(argc + 1, sizeof(char *));
|
||||
for (i = 1; i < argc; i++) {
|
||||
testlist[i - 1] = argv[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < (sizeof(alltests) / sizeof(struct testlist *)); i++) {
|
||||
suite = alltests[i].func(suite);
|
||||
}
|
||||
|
||||
rv = report(suite);
|
||||
return rv;
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef WIN32
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifndef ABTS_H
|
||||
#define ABTS_H
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
struct sub_suite {
|
||||
const char *name;
|
||||
int num_test;
|
||||
int failed;
|
||||
int not_run;
|
||||
int not_impl;
|
||||
struct sub_suite *next;
|
||||
};
|
||||
typedef struct sub_suite sub_suite;
|
||||
|
||||
struct abts_suite {
|
||||
sub_suite *head;
|
||||
sub_suite *tail;
|
||||
};
|
||||
typedef struct abts_suite abts_suite;
|
||||
|
||||
struct abts_case {
|
||||
int failed;
|
||||
sub_suite *suite;
|
||||
};
|
||||
typedef struct abts_case abts_case;
|
||||
|
||||
typedef void (*test_func)(abts_case *tc, void *data);
|
||||
|
||||
#define ADD_SUITE(suite) abts_add_suite(suite, __FILE__);
|
||||
|
||||
abts_suite *abts_add_suite(abts_suite *suite, const char *suite_name);
|
||||
void abts_run_test(abts_suite *ts, test_func f, void *value);
|
||||
void abts_log_message(const char *fmt, ...);
|
||||
|
||||
void abts_int_equal(abts_case *tc, const int expected, const int actual, int lineno);
|
||||
void abts_int_nequal(abts_case *tc, const int expected, const int actual, int lineno);
|
||||
void abts_str_equal(abts_case *tc, const char *expected, const char *actual, int lineno);
|
||||
void abts_str_nequal(abts_case *tc, const char *expected, const char *actual,
|
||||
size_t n, int lineno);
|
||||
void abts_ptr_null(abts_case *tc, const void *ptr, int lineno);
|
||||
void abts_ptr_notnull(abts_case *tc, const void *ptr, int lineno);
|
||||
void abts_ptr_equal(abts_case *tc, const void *expected, const void *actual, int lineno);
|
||||
void abts_true(abts_case *tc, int condition, int lineno);
|
||||
void abts_false(abts_case *tc, int condition, int lineno);
|
||||
void abts_fail(abts_case *tc, const char *message, int lineno);
|
||||
void abts_not_impl(abts_case *tc, const char *message, int lineno);
|
||||
void abts_assert(abts_case *tc, const char *message, int condition, int lineno);
|
||||
void abts_size_equal(abts_case *tc, size_t expected, size_t actual, int lineno);
|
||||
|
||||
/* Convenience macros. Ryan hates these! */
|
||||
#define ABTS_INT_EQUAL(a, b, c) abts_int_equal(a, b, c, __LINE__)
|
||||
#define ABTS_INT_NEQUAL(a, b, c) abts_int_nequal(a, b, c, __LINE__)
|
||||
#define ABTS_STR_EQUAL(a, b, c) abts_str_equal(a, b, c, __LINE__)
|
||||
#define ABTS_STR_NEQUAL(a, b, c, d) abts_str_nequal(a, b, c, d, __LINE__)
|
||||
#define ABTS_PTR_NULL(a, b) abts_ptr_null(a, b, __LINE__)
|
||||
#define ABTS_PTR_NOTNULL(a, b) abts_ptr_notnull(a, b, __LINE__)
|
||||
#define ABTS_PTR_EQUAL(a, b, c) abts_ptr_equal(a, b, c, __LINE__)
|
||||
#define ABTS_TRUE(a, b) abts_true(a, b, __LINE__);
|
||||
#define ABTS_FALSE(a, b) abts_false(a, b, __LINE__);
|
||||
#define ABTS_FAIL(a, b) abts_fail(a, b, __LINE__);
|
||||
#define ABTS_NOT_IMPL(a, b) abts_not_impl(a, b, __LINE__);
|
||||
#define ABTS_ASSERT(a, b, c) abts_assert(a, b, c, __LINE__);
|
||||
|
||||
#define ABTS_SIZE_EQUAL(a, b, c) abts_size_equal(a, b, c, __LINE__)
|
||||
|
||||
|
||||
abts_suite *run_tests(abts_suite *suite);
|
||||
abts_suite *run_tests1(abts_suite *suite);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef APR_TEST_INCLUDES
|
||||
#define APR_TEST_INCLUDES
|
||||
|
||||
#include "abts.h"
|
||||
#include "testutil.h"
|
||||
|
||||
const struct testlist {
|
||||
abts_suite *(*func)(abts_suite *suite);
|
||||
} alltests[] = {
|
||||
{testds},
|
||||
{testfsm},
|
||||
{testtlv},
|
||||
{testaes},
|
||||
{testsha2},
|
||||
{testnetlib},
|
||||
{testtime},
|
||||
{testtimer},
|
||||
{testthread},
|
||||
{testlock},
|
||||
{testfile},
|
||||
{testfilecopy},
|
||||
{testdir},
|
||||
{testmsgq},
|
||||
{testsleep},
|
||||
};
|
||||
|
||||
#endif /* APR_TEST_INCLUDES */
|
|
@ -0,0 +1,391 @@
|
|||
#include "core_aes.h"
|
||||
#include "core_aes_cmac.h"
|
||||
#include "testutil.h"
|
||||
|
||||
typedef struct {
|
||||
unsigned char *key;
|
||||
unsigned int *rk;
|
||||
int key_bits;
|
||||
unsigned char input[16];
|
||||
unsigned char cipher_output[16];
|
||||
unsigned char decipher_output[16];
|
||||
} aes_test_vector_t;
|
||||
|
||||
static void aes_test1(abts_case *tc, void *data)
|
||||
{
|
||||
const int key_bits = 128;
|
||||
unsigned int rk[RKLENGTH(128)];
|
||||
unsigned char key[16] =
|
||||
"\x00\x01\x02\x03\x05\x06\x07\x08\x0A\x0B\x0C\x0D\x0F\x10\x11\x12";
|
||||
unsigned char pt[16] = "\x50\x68\x12\xA4\x5F\x08\xC8\x89\xB9\x7F\x59\x80\x03\x8B\x83\x59";
|
||||
unsigned char ct[16];
|
||||
unsigned char expected[16] =
|
||||
"\xD8\xF5\x32\x53\x82\x89\xEF\x7D\x06\xB5\x06\xA4\xFD\x5B\xE9\xC9";
|
||||
int nrounds;
|
||||
int rc;
|
||||
|
||||
nrounds = aes_setup_enc(rk, key, key_bits);
|
||||
aes_encrypt(rk ,nrounds, pt, ct);
|
||||
|
||||
rc = memcmp(ct, expected, 16);
|
||||
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
}
|
||||
|
||||
static void aes_test2(abts_case *tc, void *data)
|
||||
{
|
||||
unsigned char tmp[16];
|
||||
int nrounds;
|
||||
int rc;
|
||||
aes_test_vector_t test_vector[3];
|
||||
int i;
|
||||
|
||||
|
||||
test_vector[0].key_bits = 128;
|
||||
test_vector[0].key =
|
||||
malloc(sizeof(char)*KEYLENGTH(test_vector[0].key_bits));
|
||||
test_vector[0].rk =
|
||||
malloc(sizeof(unsigned int)*RKLENGTH(test_vector[0].key_bits));
|
||||
memcpy(test_vector[0].key,
|
||||
"\x95\xA8\xEE\x8E\x89\x97\x9B\x9E"
|
||||
"\xFD\xCB\xC6\xEB\x97\x97\x52\x8D",
|
||||
KEYLENGTH(test_vector[0].key_bits));
|
||||
memcpy(test_vector[0].input,
|
||||
"\x4E\xC1\x37\xA4\x26\xDA\xBF\x8A"
|
||||
"\xA0\xBE\xB8\xBC\x0C\x2B\x89\xD6",
|
||||
16);
|
||||
memcpy(test_vector[0].cipher_output,
|
||||
"\xD9\xB6\x5D\x12\x32\xBA\x01\x99"
|
||||
"\xCD\xBD\x48\x7B\x2A\x1F\xD6\x46",
|
||||
16);
|
||||
memcpy(test_vector[0].decipher_output,
|
||||
"\x95\x70\xC3\x43\x63\x56\x5B\x39"
|
||||
"\x35\x03\xA0\x01\xC0\xE2\x3B\x65",
|
||||
16);
|
||||
|
||||
test_vector[1].key_bits = 192;
|
||||
test_vector[1].key =
|
||||
malloc(sizeof(char)*KEYLENGTH(test_vector[1].key_bits));
|
||||
test_vector[1].rk =
|
||||
malloc(sizeof(unsigned int)*RKLENGTH(test_vector[1].key_bits));
|
||||
memcpy(test_vector[1].key,
|
||||
"\x95\xA8\xEE\x8E\x89\x97\x9B\x9E"
|
||||
"\xFD\xCB\xC6\xEB\x97\x97\x52\x8D"
|
||||
"\x43\x2D\xC2\x60\x61\x55\x38\x18",
|
||||
KEYLENGTH(test_vector[1].key_bits));
|
||||
memcpy(test_vector[1].input ,
|
||||
"\x4E\xC1\x37\xA4\x26\xDA\xBF\x8A"
|
||||
"\xA0\xBE\xB8\xBC\x0C\x2B\x89\xD6",
|
||||
16);
|
||||
memcpy(test_vector[1].cipher_output,
|
||||
"\xB1\x8B\xB3\xE7\xE1\x07\x32\xBE"
|
||||
"\x13\x58\x44\x3A\x50\x4D\xBB\x49",
|
||||
16);
|
||||
memcpy(test_vector[1].decipher_output,
|
||||
"\x29\xDF\xD7\x5B\x85\xCE\xE4\xDE"
|
||||
"\x6E\x26\xA8\x08\xCD\xC2\xC9\xC3",
|
||||
16);
|
||||
|
||||
test_vector[2].key_bits = 256;
|
||||
test_vector[2].key =
|
||||
malloc(sizeof(char)*KEYLENGTH(test_vector[2].key_bits));
|
||||
test_vector[2].rk =
|
||||
malloc(sizeof(unsigned int)*RKLENGTH(test_vector[2].key_bits));
|
||||
memcpy(test_vector[2].key,
|
||||
"\x95\xA8\xEE\x8E\x89\x97\x9B\x9E"
|
||||
"\xFD\xCB\xC6\xEB\x97\x97\x52\x8D"
|
||||
"\x43\x2D\xC2\x60\x61\x55\x38\x18"
|
||||
"\xEA\x63\x5E\xC5\xD5\xA7\x72\x7E",
|
||||
KEYLENGTH(test_vector[2].key_bits));
|
||||
memcpy(test_vector[2].input ,
|
||||
"\x4E\xC1\x37\xA4\x26\xDA\xBF\x8A"
|
||||
"\xA0\xBE\xB8\xBC\x0C\x2B\x89\xD6",
|
||||
16);
|
||||
memcpy(test_vector[2].cipher_output,
|
||||
"\x2F\x9C\xFD\xDB\xFF\xCD\xE6\xB9"
|
||||
"\xF3\x7E\xF8\xE4\x0D\x51\x2C\xF4",
|
||||
16);
|
||||
memcpy(test_vector[2].decipher_output,
|
||||
"\x11\x0A\x35\x45\xCE\x49\xB8\x4B"
|
||||
"\xBB\x7B\x35\x23\x61\x08\xFA\x6E",
|
||||
16);
|
||||
|
||||
for (i=0; i<3; i++)
|
||||
{
|
||||
nrounds = aes_setup_enc(test_vector[i].rk, test_vector[i].key,
|
||||
test_vector[i].key_bits);
|
||||
aes_encrypt(test_vector[i].rk ,nrounds, test_vector[i].input, tmp);
|
||||
|
||||
rc = memcmp(tmp, test_vector[i].cipher_output, 16);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
|
||||
nrounds = aes_setup_dec(test_vector[i].rk, test_vector[i].key,
|
||||
test_vector[i].key_bits);
|
||||
aes_decrypt(test_vector[i].rk ,nrounds, test_vector[i].input, tmp);
|
||||
rc = memcmp(tmp, test_vector[i].decipher_output, 16);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
|
||||
free(test_vector[i].key);
|
||||
free(test_vector[i].rk);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
Case #1: Encrypting 16 bytes (1 block) using AES-CBC with 128-bit key
|
||||
Key : 0x06a9214036b8a15b512e03d534120006
|
||||
IV : 0x3dafba429d9eb430b422da802c9fac41
|
||||
Plaintext : "Single block msg"
|
||||
Ciphertext: 0xe353779c1079aeb82708942dbe77181a
|
||||
|
||||
Case #2: Encrypting 32 bytes (2 blocks) using AES-CBC with 128-bit key
|
||||
Key : 0xc286696d887c9aa0611bbb3e2025a45a
|
||||
IV : 0x562e17996d093d28ddb3ba695a2e6f58
|
||||
Plaintext : 0x000102030405060708090a0b0c0d0e0f
|
||||
101112131415161718191a1b1c1d1e1f
|
||||
Ciphertext: 0xd296cd94c2cccf8a3a863028b5e1dc0a
|
||||
7586602d253cfff91b8266bea6d61ab1
|
||||
|
||||
Case #3: Encrypting 48 bytes (3 blocks) using AES-CBC with 128-bit key
|
||||
Key : 0x6c3ea0477630ce21a2ce334aa746c2cd
|
||||
IV : 0xc782dc4c098c66cbd9cd27d825682c81
|
||||
Plaintext : "This is a 48-byte message (exactly 3 AES blocks)"
|
||||
Ciphertext: 0xd0a02b3836451753d493665d33f0e886
|
||||
2dea54cdb293abc7506939276772f8d5
|
||||
021c19216bad525c8579695d83ba2684
|
||||
|
||||
Case #4: Encrypting 64 bytes (4 blocks) using AES-CBC with 128-bit key
|
||||
Key : 0x56e47a38c5598974bc46903dba290349
|
||||
IV : 0x8ce82eefbea0da3c44699ed7db51b7d9
|
||||
Plaintext : 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf
|
||||
b0b1b2b3b4b5b6b7b8b9babbbcbdbebf
|
||||
c0c1c2c3c4c5c6c7c8c9cacbcccdcecf
|
||||
d0d1d2d3d4d5d6d7d8d9dadbdcdddedf
|
||||
Ciphertext: 0xc30e32ffedc0774e6aff6af0869f71aa
|
||||
0f3af07a9a31a9c684db207eb0ef8e4e
|
||||
35907aa632c3ffdf868bb7b29d3d46ad
|
||||
83ce9f9a102ee99d49a53e87f4c3da55
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
unsigned char key[33];
|
||||
int key_bits;
|
||||
unsigned char ivec[33];
|
||||
unsigned char plain[65];
|
||||
unsigned int plainlen;
|
||||
unsigned char cipher[65];
|
||||
unsigned int cipherlen;
|
||||
} aes_cbc_test_vector_t;
|
||||
|
||||
static void aes_test3(abts_case *tc, void *data)
|
||||
{
|
||||
aes_cbc_test_vector_t tv[5] = {
|
||||
{
|
||||
"\x06\xa9\x21\x40\x36\xb8\xa1\x5b\x51\x2e\x03\xd5\x34\x12\x00\x06",
|
||||
128,
|
||||
"\x3d\xaf\xba\x42\x9d\x9e\xb4\x30\xb4\x22\xda\x80\x2c\x9f\xac\x41",
|
||||
"Single block msg",
|
||||
16,
|
||||
"\xe3\x53\x77\x9c\x10\x79\xae\xb8\x27\x08\x94\x2d\xbe\x77\x18\x1a",
|
||||
16
|
||||
}, {
|
||||
"\xc2\x86\x69\x6d\x88\x7c\x9a\xa0\x61\x1b\xbb\x3e\x20\x25\xa4\x5a",
|
||||
128,
|
||||
"\x56\x2e\x17\x99\x6d\x09\x3d\x28\xdd\xb3\xba\x69\x5a\x2e\x6f\x58",
|
||||
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
|
||||
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
|
||||
32,
|
||||
"\xd2\x96\xcd\x94\xc2\xcc\xcf\x8a\x3a\x86\x30\x28\xb5\xe1\xdc\x0a"
|
||||
"\x75\x86\x60\x2d\x25\x3c\xff\xf9\x1b\x82\x66\xbe\xa6\xd6\x1a\xb1",
|
||||
32
|
||||
}, {
|
||||
|
||||
"\x6c\x3e\xa0\x47\x76\x30\xce\x21\xa2\xce\x33\x4a\xa7\x46\xc2\xcd",
|
||||
128,
|
||||
"\xc7\x82\xdc\x4c\x09\x8c\x66\xcb\xd9\xcd\x27\xd8\x25\x68\x2c\x81",
|
||||
"This is a 48-byte message (exactly 3 AES blocks)",
|
||||
48,
|
||||
"\xd0\xa0\x2b\x38\x36\x45\x17\x53\xd4\x93\x66\x5d\x33\xf0\xe8\x86"
|
||||
"\x2d\xea\x54\xcd\xb2\x93\xab\xc7\x50\x69\x39\x27\x67\x72\xf8\xd5"
|
||||
"\x02\x1c\x19\x21\x6b\xad\x52\x5c\x85\x79\x69\x5d\x83\xba\x26\x84",
|
||||
48
|
||||
}, {
|
||||
"\x56\xe4\x7a\x38\xc5\x59\x89\x74\xbc\x46\x90\x3d\xba\x29\x03\x49",
|
||||
128,
|
||||
"\x8c\xe8\x2e\xef\xbe\xa0\xda\x3c\x44\x69\x9e\xd7\xdb\x51\xb7\xd9",
|
||||
"\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
|
||||
"\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
|
||||
"\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
|
||||
"\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf",
|
||||
64,
|
||||
"\xc3\x0e\x32\xff\xed\xc0\x77\x4e\x6a\xff\x6a\xf0\x86\x9f\x71\xaa"
|
||||
"\x0f\x3a\xf0\x7a\x9a\x31\xa9\xc6\x84\xdb\x20\x7e\xb0\xef\x8e\x4e"
|
||||
"\x35\x90\x7a\xa6\x32\xc3\xff\xdf\x86\x8b\xb7\xb2\x9d\x3d\x46\xad"
|
||||
"\x83\xce\x9f\x9a\x10\x2e\xe9\x9d\x49\xa5\x3e\x87\xf4\xc3\xda\x55",
|
||||
64
|
||||
}, {
|
||||
"\x56\xe4\x7a\x38\xc5\x59\x89\x74\xbc\x46\x90\x3d\xba\x29\x03\x49",
|
||||
128,
|
||||
"\x8c\xe8\x2e\xef\xbe\xa0\xda\x3c\x44\x69\x9e\xd7\xdb\x51\xb7\xd9",
|
||||
"\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
|
||||
"\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
|
||||
"\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
|
||||
"\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd",
|
||||
62,
|
||||
"\xc3\x0e\x32\xff\xed\xc0\x77\x4e\x6a\xff\x6a\xf0\x86\x9f\x71\xaa"
|
||||
"\x0f\x3a\xf0\x7a\x9a\x31\xa9\xc6\x84\xdb\x20\x7e\xb0\xef\x8e\x4e"
|
||||
"\x35\x90\x7a\xa6\x32\xc3\xff\xdf\x86\x8b\xb7\xb2\x9d\x3d\x46\xad"
|
||||
"\x5d\x96\x74\x07\xe9\x86\x0c\x0b\x50\x80\x4a\xfb\x69\xc1\x13\xaa",
|
||||
64
|
||||
}
|
||||
};
|
||||
|
||||
unsigned char out[128];
|
||||
unsigned int i, rc, outlen;
|
||||
c_uint8_t ivec[32];
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
outlen = sizeof(out);
|
||||
memcpy(ivec, tv[i].ivec, 16);
|
||||
aes_cbc_encrypt(tv[i].key, tv[i].key_bits, ivec,
|
||||
tv[i].plain, tv[i].plainlen, out, &outlen);
|
||||
ABTS_INT_EQUAL(tc, tv[i].cipherlen, outlen);
|
||||
rc = memcmp(tv[i].cipher, out, tv[i].cipherlen);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
|
||||
outlen = sizeof(out);
|
||||
memcpy(ivec, tv[i].ivec, 16);
|
||||
aes_cbc_decrypt(tv[i].key, tv[i].key_bits, ivec,
|
||||
tv[i].cipher, tv[i].cipherlen, out, &outlen);
|
||||
ABTS_INT_EQUAL(tc, tv[i].cipherlen, outlen);
|
||||
rc = memcmp(tv[i].plain, out, tv[i].plainlen);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
}
|
||||
}
|
||||
|
||||
/* RFC 4493
|
||||
|
||||
--------------------------------------------------
|
||||
Subkey Generation
|
||||
K 2b7e1516 28aed2a6 abf71588 09cf4f3c
|
||||
AES-128(key,0) 7df76b0c 1ab899b3 3e42f047 b91b546f
|
||||
K1 fbeed618 35713366 7c85e08f 7236a8de
|
||||
K2 f7ddac30 6ae266cc f90bc11e e46d513b
|
||||
--------------------------------------------------
|
||||
|
||||
--------------------------------------------------
|
||||
Example 1: len = 0
|
||||
M <empty string>
|
||||
AES-CMAC bb1d6929 e9593728 7fa37d12 9b756746
|
||||
--------------------------------------------------
|
||||
|
||||
Example 2: len = 16
|
||||
M 6bc1bee2 2e409f96 e93d7e11 7393172a
|
||||
AES-CMAC 070a16b4 6b4d4144 f79bdd9d d04a287c
|
||||
--------------------------------------------------
|
||||
|
||||
Example 3: len = 40
|
||||
M 6bc1bee2 2e409f96 e93d7e11 7393172a
|
||||
ae2d8a57 1e03ac9c 9eb76fac 45af8e51
|
||||
30c81c46 a35ce411
|
||||
AES-CMAC dfa66747 de9ae630 30ca3261 1497c827
|
||||
--------------------------------------------------
|
||||
|
||||
Example 4: len = 64
|
||||
M 6bc1bee2 2e409f96 e93d7e11 7393172a
|
||||
ae2d8a57 1e03ac9c 9eb76fac 45af8e51
|
||||
30c81c46 a35ce411 e5fbc119 1a0a52ef
|
||||
f69f2445 df4f9b17 ad2b417b e66c3710
|
||||
AES-CMAC 51f0bebf 7e3b9d92 fc497417 79363cfe
|
||||
--------------------------------------------------
|
||||
*/
|
||||
|
||||
static void cmac_test(abts_case *tc, void *data)
|
||||
{
|
||||
c_uint8_t key[16] = {
|
||||
0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6,
|
||||
0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c
|
||||
};
|
||||
|
||||
c_uint8_t msg[4][64] = {
|
||||
{
|
||||
/* Empty string */
|
||||
},
|
||||
{
|
||||
0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,
|
||||
0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a
|
||||
}, {
|
||||
0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,
|
||||
0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a,
|
||||
0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c,
|
||||
0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51,
|
||||
0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11
|
||||
}, {
|
||||
0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,
|
||||
0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a,
|
||||
0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c,
|
||||
0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51,
|
||||
0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11,
|
||||
0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef,
|
||||
0xf6,0x9f,0x24,0x45,0xdf,0x4f,0x9b,0x17,
|
||||
0xad,0x2b,0x41,0x7b,0xe6,0x6c,0x37,0x10
|
||||
}
|
||||
};
|
||||
|
||||
c_uint32_t msglen[4] = {0, 16, 40, 64};
|
||||
|
||||
c_uint8_t cmac_answer[4][16] = {
|
||||
{
|
||||
0xbb,0x1d,0x69,0x29,0xe9,0x59,0x37,0x28,
|
||||
0x7f,0xa3,0x7d,0x12,0x9b,0x75,0x67,0x46
|
||||
}, {
|
||||
0x07,0x0a,0x16,0xb4,0x6b,0x4d,0x41,0x44,
|
||||
0xf7,0x9b,0xdd,0x9d,0xd0,0x4a,0x28,0x7c
|
||||
}, {
|
||||
0xdf,0xa6,0x67,0x47,0xde,0x9a,0xe6,0x30,
|
||||
0x30,0xca,0x32,0x61,0x14,0x97,0xc8,0x27
|
||||
}, {
|
||||
0x51,0xf0,0xbe,0xbf,0x7e,0x3b,0x9d,0x92,
|
||||
0xfc,0x49,0x74,0x17,0x79,0x36,0x3c,0xfe
|
||||
}
|
||||
};
|
||||
|
||||
c_uint8_t cmac[16];
|
||||
|
||||
int i, rc;
|
||||
status_t rv;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
rv = aes_cmac_calculate(cmac, key, msg[i], msglen[i]);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
rc = memcmp(cmac, cmac_answer[i], 16);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
rv = aes_cmac_verify(cmac_answer[i], key, msg[i], msglen[i]);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
}
|
||||
|
||||
key[0] = 0;
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
rv = aes_cmac_verify(cmac_answer[i], key, msg[i], msglen[i]);
|
||||
ABTS_INT_EQUAL(tc, ERR_INVALID_CMAC, rv);
|
||||
}
|
||||
}
|
||||
|
||||
abts_suite *testaes(abts_suite *suite)
|
||||
{
|
||||
suite = ADD_SUITE(suite);
|
||||
|
||||
abts_run_test(suite, aes_test1, NULL);
|
||||
abts_run_test(suite, aes_test2, NULL);
|
||||
abts_run_test(suite, aes_test3, NULL);
|
||||
abts_run_test(suite, cmac_test, NULL);
|
||||
|
||||
return suite;
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "core_file.h"
|
||||
#include "testutil.h"
|
||||
|
||||
static void test_mkdir(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
file_info_t finfo;
|
||||
|
||||
rv = dir_make("data/testdir", FILE_UREAD | FILE_UWRITE | FILE_UEXECUTE);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
rv = file_stat(&finfo, "data/testdir", FILE_INFO_TYPE);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_INT_EQUAL(tc, FILE_DIR, finfo.filetype);
|
||||
}
|
||||
|
||||
static void test_mkdir_recurs(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
file_info_t finfo;
|
||||
|
||||
rv = dir_make_recursive("data/one/two/three",
|
||||
FILE_UREAD | FILE_UWRITE | FILE_UEXECUTE);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
rv = file_stat(&finfo, "data/one", FILE_INFO_TYPE);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_INT_EQUAL(tc, FILE_DIR, finfo.filetype);
|
||||
|
||||
rv = file_stat(&finfo, "data/one/two", FILE_INFO_TYPE);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_INT_EQUAL(tc, FILE_DIR, finfo.filetype);
|
||||
|
||||
rv = file_stat(&finfo, "data/one/two/three", FILE_INFO_TYPE);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_INT_EQUAL(tc, FILE_DIR, finfo.filetype);
|
||||
}
|
||||
|
||||
static void test_remove(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
file_info_t finfo;
|
||||
|
||||
rv = dir_remove("data/testdir");
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
rv = file_stat(&finfo, "data/testdir", FILE_INFO_TYPE);
|
||||
ABTS_INT_EQUAL(tc, 1, STATUS_IS_ENOENT(rv));
|
||||
}
|
||||
|
||||
static void test_removeall_fail(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
|
||||
rv = dir_remove("data/one");
|
||||
ABTS_INT_EQUAL(tc, 1, STATUS_IS_ENOTEMPTY(rv));
|
||||
}
|
||||
|
||||
static void test_removeall(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
|
||||
rv = dir_remove("data/one/two/three");
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
rv = dir_remove("data/one/two");
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
rv = dir_remove("data/one");
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
}
|
||||
|
||||
static void test_remove_notthere(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
|
||||
rv = dir_remove("data/notthere");
|
||||
ABTS_INT_EQUAL(tc, 1, STATUS_IS_ENOENT(rv));
|
||||
}
|
||||
|
||||
static void test_mkdir_twice(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
|
||||
rv = dir_make("data/testdir", FILE_UREAD | FILE_UWRITE | FILE_UEXECUTE);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
rv = dir_make("data/testdir", FILE_UREAD | FILE_UWRITE | FILE_UEXECUTE);
|
||||
ABTS_INT_EQUAL(tc, 1, STATUS_IS_EEXIST(rv));
|
||||
|
||||
rv = dir_remove("data/testdir");
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
}
|
||||
|
||||
abts_suite *testdir(abts_suite *suite)
|
||||
{
|
||||
suite = ADD_SUITE(suite)
|
||||
|
||||
abts_run_test(suite, test_mkdir, NULL);
|
||||
abts_run_test(suite, test_mkdir_recurs, NULL);
|
||||
abts_run_test(suite, test_remove, NULL);
|
||||
abts_run_test(suite, test_removeall_fail, NULL);
|
||||
abts_run_test(suite, test_removeall, NULL);
|
||||
abts_run_test(suite, test_remove_notthere, NULL);
|
||||
abts_run_test(suite, test_mkdir_twice, NULL);
|
||||
|
||||
return suite;
|
||||
}
|
|
@ -0,0 +1,814 @@
|
|||
#include "core_pool.h"
|
||||
#include "core_list.h"
|
||||
#include "core_queue.h"
|
||||
#include "core_ringbuf.h"
|
||||
#include "testutil.h"
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* test for core_pool.h
|
||||
*/
|
||||
typedef struct {
|
||||
char m1;
|
||||
int m2;
|
||||
} pt_type1;
|
||||
|
||||
#define SIZE_OF_TPOOL1 5
|
||||
#define SIZE_OF_TPOOL2 5
|
||||
|
||||
typedef char type_of_tpool1;
|
||||
typedef pt_type1 type_of_tpool2;
|
||||
|
||||
pool_declare(tpool1, type_of_tpool1, SIZE_OF_TPOOL1);
|
||||
pool_declare(tpool2, type_of_tpool2, SIZE_OF_TPOOL2);
|
||||
|
||||
static void pool_test_core1(abts_case *tc, void *data, int start)
|
||||
{
|
||||
int i, j, n;
|
||||
|
||||
type_of_tpool1 *org[SIZE_OF_TPOOL1+1];
|
||||
type_of_tpool1 *node[SIZE_OF_TPOOL1+1];
|
||||
|
||||
pool_init(&tpool1, SIZE_OF_TPOOL1);
|
||||
|
||||
/* Check basic members */
|
||||
n = pool_size(&tpool1);
|
||||
ABTS_INT_EQUAL(tc, SIZE_OF_TPOOL1, n);
|
||||
n = pool_avail(&tpool1);
|
||||
ABTS_INT_EQUAL(tc, SIZE_OF_TPOOL1, n);
|
||||
n = pool_used(&tpool1);
|
||||
ABTS_INT_EQUAL(tc, 0, n);
|
||||
|
||||
/* Allocation up to start index */
|
||||
for (i = 0; i < start; i++)
|
||||
{
|
||||
pool_alloc_node(&tpool1, &node[i]);
|
||||
/* Check not null */
|
||||
ABTS_PTR_NOTNULL(tc, node[i]);
|
||||
/* Check the number of available nodes */
|
||||
n = pool_avail(&tpool1);
|
||||
ABTS_INT_EQUAL(tc, SIZE_OF_TPOOL1 - (i + 1), n);
|
||||
}
|
||||
|
||||
/* Free all allocated nodes */
|
||||
for (i = 0; i < start; i++)
|
||||
{
|
||||
pool_free_node(&tpool1, node[i]);
|
||||
/* Check the number of available nodes */
|
||||
n = pool_avail(&tpool1);
|
||||
ABTS_INT_EQUAL(tc, SIZE_OF_TPOOL1 - start + (i + 1), n);
|
||||
}
|
||||
|
||||
/* Allocation up to maximum pool size */
|
||||
for (i = 0; i < SIZE_OF_TPOOL1; i++)
|
||||
{
|
||||
pool_alloc_node(&tpool1, &node[i]);
|
||||
org[i] = node[i];
|
||||
/* Check not null */
|
||||
ABTS_PTR_NOTNULL(tc, node[i]);
|
||||
/* Check the number of available nodes */
|
||||
n = pool_avail(&tpool1);
|
||||
ABTS_INT_EQUAL(tc, SIZE_OF_TPOOL1 - (i + 1), n);
|
||||
}
|
||||
|
||||
/* Free all allocated */
|
||||
for (i = 0; i < SIZE_OF_TPOOL1; i++)
|
||||
{
|
||||
pool_free_node(&tpool1, node[i]);
|
||||
/* Check the number of available nodes */
|
||||
n = pool_avail(&tpool1);
|
||||
ABTS_INT_EQUAL(tc, i + 1, n);
|
||||
}
|
||||
|
||||
/* Check that addresses of nodes are same with original ones */
|
||||
n = 0;
|
||||
for (i = 0; i < SIZE_OF_TPOOL1; i++)
|
||||
{
|
||||
pool_alloc_node(&tpool1, &node[i]);
|
||||
for (j = 0; j < SIZE_OF_TPOOL1; j++)
|
||||
{
|
||||
if (node[i] == org[j])
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free all allocated */
|
||||
for (i = 0; i < SIZE_OF_TPOOL1; i++)
|
||||
{
|
||||
pool_free_node(&tpool1, node[i]);
|
||||
/* Check the number of available nodes */
|
||||
n = pool_avail(&tpool1);
|
||||
ABTS_INT_EQUAL(tc, i + 1, n);
|
||||
}
|
||||
|
||||
pool_final(&tpool1);
|
||||
}
|
||||
|
||||
static void pool_test_core2(abts_case *tc, void *data, int start)
|
||||
{
|
||||
int i, j, n;
|
||||
|
||||
type_of_tpool2 *org[SIZE_OF_TPOOL2+1];
|
||||
type_of_tpool2 *node[SIZE_OF_TPOOL2+1];
|
||||
|
||||
pool_init(&tpool1, SIZE_OF_TPOOL2);
|
||||
|
||||
/* Check basic members */
|
||||
n = pool_size(&tpool1);
|
||||
ABTS_INT_EQUAL(tc, SIZE_OF_TPOOL2, n);
|
||||
n = pool_avail(&tpool1);
|
||||
ABTS_INT_EQUAL(tc, SIZE_OF_TPOOL2, n);
|
||||
n = pool_used(&tpool1);
|
||||
ABTS_INT_EQUAL(tc, 0, n);
|
||||
|
||||
/* Allocation up to start index */
|
||||
for (i = 0; i < start; i++)
|
||||
{
|
||||
pool_alloc_node(&tpool1, &node[i]);
|
||||
/* Check not null */
|
||||
ABTS_PTR_NOTNULL(tc, node[i]);
|
||||
/* Check the number of available nodes */
|
||||
n = pool_avail(&tpool1);
|
||||
ABTS_INT_EQUAL(tc, SIZE_OF_TPOOL2 - (i + 1), n);
|
||||
}
|
||||
|
||||
/* Free all allocated nodes */
|
||||
for (i = 0; i < start; i++)
|
||||
{
|
||||
pool_free_node(&tpool1, node[i]);
|
||||
/* Check the number of available nodes */
|
||||
n = pool_avail(&tpool1);
|
||||
ABTS_INT_EQUAL(tc, SIZE_OF_TPOOL2 - start + (i + 1), n);
|
||||
}
|
||||
|
||||
/* Allocation up to maximum pool size */
|
||||
for (i = 0; i < SIZE_OF_TPOOL2; i++)
|
||||
{
|
||||
pool_alloc_node(&tpool1, &node[i]);
|
||||
org[i] = node[i];
|
||||
/* Check not null */
|
||||
ABTS_PTR_NOTNULL(tc, node[i]);
|
||||
/* Check the number of available nodes */
|
||||
n = pool_avail(&tpool1);
|
||||
ABTS_INT_EQUAL(tc, SIZE_OF_TPOOL2 - (i + 1), n);
|
||||
}
|
||||
|
||||
/* Free all allocated */
|
||||
for (i = 0; i < SIZE_OF_TPOOL2; i++)
|
||||
{
|
||||
pool_free_node(&tpool1, node[i]);
|
||||
/* Check the number of available nodes */
|
||||
n = pool_avail(&tpool1);
|
||||
ABTS_INT_EQUAL(tc, i + 1, n);
|
||||
}
|
||||
|
||||
/* Check that addresses of nodes are same with original ones */
|
||||
n = 0;
|
||||
for (i = 0; i < SIZE_OF_TPOOL2; i++)
|
||||
{
|
||||
pool_alloc_node(&tpool1, &node[i]);
|
||||
for (j = 0; j < SIZE_OF_TPOOL2; j++)
|
||||
{
|
||||
if (node[i] == org[j])
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free all allocated */
|
||||
for (i = 0; i < SIZE_OF_TPOOL2; i++)
|
||||
{
|
||||
pool_free_node(&tpool1, node[i]);
|
||||
/* Check the number of available nodes */
|
||||
n = pool_avail(&tpool1);
|
||||
ABTS_INT_EQUAL(tc, i + 1, n);
|
||||
}
|
||||
|
||||
pool_final(&tpool1);
|
||||
}
|
||||
|
||||
static void pool_test1(abts_case *tc, void *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SIZE_OF_TPOOL1; i++)
|
||||
pool_test_core1(tc, data, i);
|
||||
}
|
||||
|
||||
static void pool_test2(abts_case *tc, void *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SIZE_OF_TPOOL2; i++)
|
||||
pool_test_core2(tc, data, i);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* test for core_list.h
|
||||
*/
|
||||
typedef struct {
|
||||
lnode_t node;
|
||||
int m1;
|
||||
} lt_type1;
|
||||
|
||||
list_t tlist1;
|
||||
|
||||
int lttype1_compare(lt_type1 *pnode1, lt_type1 *pnode2)
|
||||
{
|
||||
if (pnode1->m1 == pnode2->m1)
|
||||
return 0;
|
||||
else if (pnode1->m1 < pnode2->m1)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define SIZE_OF_lt_type1 16
|
||||
|
||||
static void list_test1(abts_case *tc, void *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
lt_type1 *iter, node[SIZE_OF_lt_type1];
|
||||
|
||||
for (i = 0; i < SIZE_OF_lt_type1; i++)
|
||||
node[i].m1 = i;
|
||||
|
||||
/* Initialize head of list */
|
||||
list_init(&tlist1);
|
||||
|
||||
/* Check list is empty */
|
||||
ABTS_TRUE(tc, list_is_empty(&tlist1));
|
||||
|
||||
/* Confirm that any node can't be get */
|
||||
iter = list_first(&tlist1);
|
||||
ABTS_PTR_NULL(tc, iter);
|
||||
|
||||
/* Add a node */
|
||||
list_append(&tlist1, &node[0]);
|
||||
|
||||
/* Iterate from the first. And check the pointers */
|
||||
iter = list_first(&tlist1);
|
||||
ABTS_PTR_EQUAL(tc, &node[0], iter);
|
||||
iter = list_next(iter);
|
||||
ABTS_PTR_NULL(tc, iter);
|
||||
|
||||
/* Iterate from the last. And check the pointers */
|
||||
iter = list_last(&tlist1);
|
||||
ABTS_PTR_EQUAL(tc, &node[0], iter);
|
||||
iter = list_prev(iter);
|
||||
ABTS_PTR_NULL(tc, iter);
|
||||
|
||||
/* Add two nodes */
|
||||
list_append(&tlist1, &node[1]);
|
||||
list_append(&tlist1, &node[2]);
|
||||
|
||||
/* Iterate from the first. And check the pointers */
|
||||
iter = list_first(&tlist1);
|
||||
ABTS_PTR_EQUAL(tc, &node[0], iter);
|
||||
iter = list_next(iter);
|
||||
ABTS_PTR_EQUAL(tc, &node[1], iter);
|
||||
iter = list_next(iter);
|
||||
ABTS_PTR_EQUAL(tc, &node[2], iter);
|
||||
iter = list_next(iter);
|
||||
ABTS_PTR_NULL(tc, iter);
|
||||
|
||||
/* Iterate from the last. And check the pointers */
|
||||
iter = list_last(&tlist1);
|
||||
ABTS_PTR_EQUAL(tc, &node[2], iter);
|
||||
iter = list_prev(iter);
|
||||
ABTS_PTR_EQUAL(tc, &node[1], iter);
|
||||
iter = list_prev(iter);
|
||||
ABTS_PTR_EQUAL(tc, &node[0], iter);
|
||||
iter = list_prev(iter);
|
||||
ABTS_PTR_NULL(tc, iter);
|
||||
|
||||
/* Remove all nodes */
|
||||
list_remove(&tlist1, &node[0]);
|
||||
list_remove(&tlist1, &node[1]);
|
||||
list_remove(&tlist1, &node[2]);
|
||||
|
||||
/* Check list is empty */
|
||||
ABTS_TRUE(tc, list_is_empty(&tlist1));
|
||||
}
|
||||
|
||||
static void list_test2(abts_case *tc, void *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
lt_type1 *iter, node[SIZE_OF_lt_type1];
|
||||
|
||||
for (i = 0; i < SIZE_OF_lt_type1; i++)
|
||||
node[i].m1 = i;
|
||||
|
||||
/* Initialize head of list */
|
||||
list_init(&tlist1);
|
||||
|
||||
/* Check list is empty */
|
||||
ABTS_TRUE(tc, list_is_empty(&tlist1));
|
||||
|
||||
/* Confirm that any node can't be get */
|
||||
iter = list_first(&tlist1);
|
||||
ABTS_PTR_NULL(tc, iter);
|
||||
|
||||
/* Add a node */
|
||||
list_prepend(&tlist1, &node[0]);
|
||||
|
||||
/* Iterate from the first. And check the pointers */
|
||||
iter = list_first(&tlist1);
|
||||
ABTS_PTR_EQUAL(tc, &node[0], iter);
|
||||
iter = list_next(iter);
|
||||
ABTS_PTR_NULL(tc, iter);
|
||||
|
||||
/* Iterate from the last. And check the pointers */
|
||||
iter = list_last(&tlist1);
|
||||
ABTS_PTR_EQUAL(tc, &node[0], iter);
|
||||
iter = list_prev(iter);
|
||||
ABTS_PTR_NULL(tc, iter);
|
||||
|
||||
/* Add two nodes */
|
||||
list_prepend(&tlist1, &node[1]);
|
||||
list_prepend(&tlist1, &node[2]);
|
||||
|
||||
/* Iterate from the first. And check the pointers */
|
||||
iter = list_first(&tlist1);
|
||||
ABTS_PTR_EQUAL(tc, &node[2], iter);
|
||||
iter = list_next(iter);
|
||||
ABTS_PTR_EQUAL(tc, &node[1], iter);
|
||||
iter = list_next(iter);
|
||||
ABTS_PTR_EQUAL(tc, &node[0], iter);
|
||||
iter = list_next(iter);
|
||||
ABTS_PTR_NULL(tc, iter);
|
||||
|
||||
/* Iterate from the last. And check the pointers */
|
||||
iter = list_last(&tlist1);
|
||||
ABTS_PTR_EQUAL(tc, &node[0], iter);
|
||||
iter = list_prev(iter);
|
||||
ABTS_PTR_EQUAL(tc, &node[1], iter);
|
||||
iter = list_prev(iter);
|
||||
ABTS_PTR_EQUAL(tc, &node[2], iter);
|
||||
iter = list_prev(iter);
|
||||
ABTS_PTR_NULL(tc, iter);
|
||||
|
||||
/* Remove all nodes */
|
||||
list_remove(&tlist1, &node[2]);
|
||||
list_remove(&tlist1, &node[1]);
|
||||
list_remove(&tlist1, &node[0]);
|
||||
|
||||
/* Check list is empty */
|
||||
ABTS_TRUE(tc, list_is_empty(&tlist1));
|
||||
}
|
||||
|
||||
static void list_test3(abts_case *tc, void *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
lt_type1 *iter, node[SIZE_OF_lt_type1];
|
||||
|
||||
for (i = 0; i < SIZE_OF_lt_type1; i++)
|
||||
node[i].m1 = i;
|
||||
|
||||
/* Initialize head of list */
|
||||
list_init(&tlist1);
|
||||
|
||||
/* Add three nodes */
|
||||
for (i = 0; i < 3; i++)
|
||||
list_append(&tlist1, &node[i]);
|
||||
|
||||
/* Iterate from the first. And check the pointers */
|
||||
i = 0; iter = list_first(&tlist1);
|
||||
while (iter)
|
||||
{
|
||||
ABTS_PTR_EQUAL(tc, &node[i++], iter);
|
||||
iter = list_next(iter);
|
||||
}
|
||||
ABTS_INT_EQUAL(tc, 3, i);
|
||||
|
||||
/* Iterate from the last. And check the pointers */
|
||||
i = 0; iter = list_last(&tlist1);
|
||||
while (iter)
|
||||
{
|
||||
ABTS_PTR_EQUAL(tc, &node[3 - (++i)], iter);
|
||||
iter = list_prev(iter);
|
||||
}
|
||||
ABTS_INT_EQUAL(tc, 3, i);
|
||||
|
||||
/* Insert three nodes by list_insert_prev() */
|
||||
list_insert_prev(&tlist1, &node[0], &node[3]);
|
||||
list_insert_prev(&tlist1, &node[1], &node[4]);
|
||||
list_insert_prev(&tlist1, &node[2], &node[5]);
|
||||
|
||||
/* Iterate from the first. And check the pointers */
|
||||
iter = list_first(&tlist1);
|
||||
ABTS_PTR_EQUAL(tc, &node[3], iter);
|
||||
iter = list_next(iter);
|
||||
ABTS_PTR_EQUAL(tc, &node[0], iter);
|
||||
iter = list_next(iter);
|
||||
ABTS_PTR_EQUAL(tc, &node[4], iter);
|
||||
iter = list_next(iter);
|
||||
ABTS_PTR_EQUAL(tc, &node[1], iter);
|
||||
iter = list_next(iter);
|
||||
ABTS_PTR_EQUAL(tc, &node[5], iter);
|
||||
iter = list_next(iter);
|
||||
ABTS_PTR_EQUAL(tc, &node[2], iter);
|
||||
iter = list_next(iter);
|
||||
ABTS_PTR_NULL(tc, iter);
|
||||
|
||||
/* Remove three nodes inserted by list_insert_prev() */
|
||||
list_remove(&tlist1, &node[3]);
|
||||
list_remove(&tlist1, &node[4]);
|
||||
list_remove(&tlist1, &node[5]);
|
||||
|
||||
/* Iterate from the first. And check the pointers */
|
||||
iter = list_first(&tlist1);
|
||||
ABTS_PTR_EQUAL(tc, &node[0], iter);
|
||||
iter = list_next(iter);
|
||||
ABTS_PTR_EQUAL(tc, &node[1], iter);
|
||||
iter = list_next(iter);
|
||||
ABTS_PTR_EQUAL(tc, &node[2], iter);
|
||||
iter = list_next(iter);
|
||||
ABTS_PTR_NULL(tc, iter);
|
||||
}
|
||||
|
||||
static void list_test4(abts_case *tc, void *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
lt_type1 *iter, node[SIZE_OF_lt_type1];
|
||||
|
||||
for (i = 0; i < SIZE_OF_lt_type1; i++)
|
||||
node[i].m1 = i;
|
||||
|
||||
/* Initialize head of list */
|
||||
list_init(&tlist1);
|
||||
|
||||
/* Add three nodes */
|
||||
for (i = 0; i < 3; i++)
|
||||
list_append(&tlist1, &node[i]);
|
||||
|
||||
/* Iterate from the first. And check the pointers */
|
||||
i = 0; iter = list_first(&tlist1);
|
||||
while (iter)
|
||||
{
|
||||
ABTS_PTR_EQUAL(tc, &node[i++], iter);
|
||||
iter = list_next(iter);
|
||||
}
|
||||
ABTS_INT_EQUAL(tc, 3, i);
|
||||
|
||||
/* Iterate from the last. And check the pointers */
|
||||
i = 0; iter = list_last(&tlist1);
|
||||
while (iter)
|
||||
{
|
||||
ABTS_PTR_EQUAL(tc, &node[3 - (++i)], iter);
|
||||
iter = list_prev(iter);
|
||||
}
|
||||
ABTS_INT_EQUAL(tc, 3, i);
|
||||
|
||||
/* Insert three nodes by list_insert_next() */
|
||||
list_insert_next(&tlist1, &node[0], &node[3]);
|
||||
list_insert_next(&tlist1, &node[1], &node[4]);
|
||||
list_insert_next(&tlist1, &node[2], &node[5]);
|
||||
|
||||
/* Iterate from the first. And check the pointers */
|
||||
iter = list_first(&tlist1);
|
||||
ABTS_PTR_EQUAL(tc, &node[0], iter);
|
||||
iter = list_next(iter);
|
||||
ABTS_PTR_EQUAL(tc, &node[3], iter);
|
||||
iter = list_next(iter);
|
||||
ABTS_PTR_EQUAL(tc, &node[1], iter);
|
||||
iter = list_next(iter);
|
||||
ABTS_PTR_EQUAL(tc, &node[4], iter);
|
||||
iter = list_next(iter);
|
||||
ABTS_PTR_EQUAL(tc, &node[2], iter);
|
||||
iter = list_next(iter);
|
||||
ABTS_PTR_EQUAL(tc, &node[5], iter);
|
||||
iter = list_next(iter);
|
||||
ABTS_PTR_NULL(tc, iter);
|
||||
|
||||
/* Remove three nodes inserted by list_insert_next() */
|
||||
list_remove(&tlist1, &node[3]);
|
||||
list_remove(&tlist1, &node[4]);
|
||||
list_remove(&tlist1, &node[5]);
|
||||
|
||||
/* Iterate from the first. And check the pointers */
|
||||
iter = list_first(&tlist1);
|
||||
ABTS_PTR_EQUAL(tc, &node[0], iter);
|
||||
iter = list_next(iter);
|
||||
ABTS_PTR_EQUAL(tc, &node[1], iter);
|
||||
iter = list_next(iter);
|
||||
ABTS_PTR_EQUAL(tc, &node[2], iter);
|
||||
iter = list_next(iter);
|
||||
ABTS_PTR_NULL(tc, iter);
|
||||
}
|
||||
|
||||
static void list_test5(abts_case *tc, void *data)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
/* List up posssible oders with four nodes */
|
||||
int od[24][4] = {
|
||||
{0,1,2,3}, {0,1,3,2}, {0,2,1,3}, {0,2,3,1}, {0,3,1,2}, {0,3,2,1},
|
||||
{1,0,2,3}, {1,0,3,2}, {1,2,0,3}, {1,2,3,0}, {1,3,0,2}, {1,3,2,0},
|
||||
{2,1,0,3}, {2,1,3,0}, {2,0,1,3}, {2,0,3,1}, {2,3,1,0}, {2,3,0,1},
|
||||
{3,1,2,0}, {3,1,0,2}, {3,2,1,0}, {3,2,0,1}, {3,0,1,2}, {3,0,2,1}
|
||||
};
|
||||
|
||||
lt_type1 *iter, node[SIZE_OF_lt_type1];
|
||||
|
||||
for (i = 0; i < SIZE_OF_lt_type1; i++)
|
||||
node[i].m1 = i;
|
||||
|
||||
for (i = 0; i < 24; i++)
|
||||
{
|
||||
/* Initialize head of list */
|
||||
list_init(&tlist1);
|
||||
|
||||
/* Add four nodes using predefined orders */
|
||||
for (j = 0; j < 4; j++)
|
||||
list_insert_sorted(&tlist1, &node[od[i][j]], <type1_compare);
|
||||
|
||||
/* Iterate from the first. And check the SORTED */
|
||||
j = 0; iter = list_first(&tlist1);
|
||||
while (iter)
|
||||
{
|
||||
ABTS_INT_EQUAL(tc, iter->m1, j++);
|
||||
iter = list_next(iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* test for core_queue.h
|
||||
*/
|
||||
typedef struct {
|
||||
int m1;
|
||||
} qt_type1;
|
||||
|
||||
#define SIZE_OF_TQUE1 4
|
||||
#define SIZE_OF_TQUE2 3
|
||||
|
||||
typedef int type_of_tque1;
|
||||
typedef qt_type1 type_of_tque2;
|
||||
|
||||
que_declare(tque1, type_of_tque1, SIZE_OF_TQUE1);
|
||||
que_declare(tque2, type_of_tque2, SIZE_OF_TQUE2);
|
||||
que_declare(tque3, type_of_tque2 *, SIZE_OF_TQUE2);
|
||||
|
||||
static void que_test1(abts_case *tc, void *data)
|
||||
{
|
||||
int i, r;
|
||||
|
||||
type_of_tque1 n, node[SIZE_OF_TQUE1+1];
|
||||
|
||||
n = 0;
|
||||
for (i = 0; i < SIZE_OF_TQUE1; i++)
|
||||
node[i] = i;
|
||||
|
||||
/* Initialize queue */
|
||||
que_init(&tque1, SIZE_OF_TQUE1);
|
||||
|
||||
/* Check basic members */
|
||||
ABTS_TRUE(tc, que_is_empty(&tque1));
|
||||
ABTS_FALSE(tc, que_is_full(&tque1));
|
||||
ABTS_INT_EQUAL(tc, SIZE_OF_TQUE1, que_avail(&tque1));
|
||||
ABTS_INT_EQUAL(tc, 0, que_used(&tque1));
|
||||
|
||||
/* Push a node */
|
||||
r = que_push(&tque1, &node[0]);
|
||||
ABTS_INT_EQUAL(tc, 1, r);
|
||||
|
||||
/* Check queue status */
|
||||
ABTS_FALSE(tc, que_is_empty(&tque1));
|
||||
ABTS_FALSE(tc, que_is_full(&tque1));
|
||||
ABTS_INT_EQUAL(tc, SIZE_OF_TQUE1 - 1, que_avail(&tque1));
|
||||
ABTS_INT_EQUAL(tc, 1, que_used(&tque1));
|
||||
|
||||
/* Pop a node */
|
||||
r = que_pop(&tque1, &n);
|
||||
ABTS_INT_EQUAL(tc, 0, r);
|
||||
|
||||
/* Check queue status */
|
||||
ABTS_TRUE(tc, que_is_empty(&tque1));
|
||||
ABTS_FALSE(tc, que_is_full(&tque1));
|
||||
ABTS_INT_EQUAL(tc, SIZE_OF_TQUE1, que_avail(&tque1));
|
||||
ABTS_INT_EQUAL(tc, 0, que_used(&tque1));
|
||||
|
||||
/* Push nodes up to queue size */
|
||||
for (i = 0; i < SIZE_OF_TQUE1; i++)
|
||||
{
|
||||
r = que_push(&tque1, &node[i]);
|
||||
ABTS_INT_EQUAL(tc, i + 1, r);
|
||||
}
|
||||
|
||||
/* Check queue status */
|
||||
ABTS_FALSE(tc, que_is_empty(&tque1));
|
||||
ABTS_TRUE(tc, que_is_full(&tque1));
|
||||
ABTS_INT_EQUAL(tc, 0, que_avail(&tque1));
|
||||
ABTS_INT_EQUAL(tc, SIZE_OF_TQUE1, que_used(&tque1));
|
||||
|
||||
/* Push a node to full queue */
|
||||
r = que_push(&tque1, &node[0]);
|
||||
ABTS_INT_EQUAL(tc, -1, r);
|
||||
|
||||
/* Pop all pushed nodes and check pop order */
|
||||
for (i = 0; i < SIZE_OF_TQUE1; i++)
|
||||
{
|
||||
r = que_pop(&tque1, &n);
|
||||
ABTS_INT_EQUAL(tc, node[i], n);
|
||||
ABTS_INT_EQUAL(tc, SIZE_OF_TQUE1 - (i + 1), r);
|
||||
}
|
||||
|
||||
/* Check queue status */
|
||||
ABTS_TRUE(tc, que_is_empty(&tque1));
|
||||
ABTS_FALSE(tc, que_is_full(&tque1));
|
||||
ABTS_INT_EQUAL(tc, SIZE_OF_TQUE1, que_avail(&tque1));
|
||||
ABTS_INT_EQUAL(tc, 0, que_used(&tque1));
|
||||
|
||||
/* Pop a node from empty queue */
|
||||
r = que_pop(&tque1, &n);
|
||||
ABTS_INT_EQUAL(tc, -1, r);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* test for core_ringbuf.h
|
||||
*/
|
||||
|
||||
#define SIZE_OF_TRBUF1 7
|
||||
rbuf_declare(trbuf1, SIZE_OF_TRBUF1);
|
||||
|
||||
#define SIZE_OF_TRBUF2 7
|
||||
rbuf_declare_ext(trbuf2);
|
||||
char trbuf2_ext_buf[SIZE_OF_TRBUF2];
|
||||
|
||||
static void rbuf_test1(abts_case *tc, void *data)
|
||||
{
|
||||
int i, n;
|
||||
char wbuf[32];
|
||||
char rbuf[32];
|
||||
|
||||
for (i = 0; i < 26; i++)
|
||||
wbuf[i] = 'a' + i;
|
||||
|
||||
rbuf_init(&trbuf1, SIZE_OF_TRBUF1);
|
||||
|
||||
/* Check basic members */
|
||||
ABTS_TRUE(tc, rbuf_is_empty(&trbuf1));
|
||||
ABTS_FALSE(tc, rbuf_is_full(&trbuf1));
|
||||
ABTS_INT_EQUAL(tc, SIZE_OF_TRBUF1, rbuf_free_bytes(&trbuf1));
|
||||
ABTS_INT_EQUAL(tc, 0, rbuf_bytes(&trbuf1));
|
||||
|
||||
/* Write 3 bytes */
|
||||
n = rbuf_write(&trbuf1, wbuf, 3);
|
||||
ABTS_INT_EQUAL(tc, 3, n);
|
||||
|
||||
/* Check basic members */
|
||||
ABTS_FALSE(tc, rbuf_is_empty(&trbuf1));
|
||||
ABTS_FALSE(tc, rbuf_is_full(&trbuf1));
|
||||
ABTS_INT_EQUAL(tc, SIZE_OF_TRBUF1 - 3, rbuf_free_bytes(&trbuf1));
|
||||
ABTS_INT_EQUAL(tc, 3, rbuf_bytes(&trbuf1));
|
||||
|
||||
/* Read 3 bytes */
|
||||
n = rbuf_read(&trbuf1, rbuf, 3); rbuf[3] = 0;
|
||||
ABTS_INT_EQUAL(tc, 3, n);
|
||||
ABTS_STR_EQUAL(tc, "abc", rbuf);
|
||||
|
||||
/* Check basic members */
|
||||
ABTS_TRUE(tc, rbuf_is_empty(&trbuf1));
|
||||
ABTS_FALSE(tc, rbuf_is_full(&trbuf1));
|
||||
ABTS_INT_EQUAL(tc, SIZE_OF_TRBUF1, rbuf_free_bytes(&trbuf1));
|
||||
ABTS_INT_EQUAL(tc, 0, rbuf_bytes(&trbuf1));
|
||||
|
||||
/* Write 3 bytes */
|
||||
n = rbuf_write(&trbuf1, wbuf, 3);
|
||||
ABTS_INT_EQUAL(tc, 3, n);
|
||||
|
||||
/* Write 5 bytes, but only 4 bytes shall be written */
|
||||
n = rbuf_write(&trbuf1, wbuf + 3, 5);
|
||||
ABTS_INT_EQUAL(tc, 4, n);
|
||||
|
||||
/* Write 1 bytes to full buffer */
|
||||
n = rbuf_write(&trbuf1, wbuf, 1);
|
||||
ABTS_INT_EQUAL(tc, -1, n);
|
||||
|
||||
/* Read 2 bytes */
|
||||
n = rbuf_read(&trbuf1, rbuf, 2); rbuf[2] = 0;
|
||||
ABTS_INT_EQUAL(tc, 2, n);
|
||||
ABTS_STR_EQUAL(tc, "ab", rbuf);
|
||||
|
||||
/* Read 5 bytes */
|
||||
n = rbuf_read(&trbuf1, rbuf, 5); rbuf[5] = 0;
|
||||
ABTS_INT_EQUAL(tc, 5, n);
|
||||
ABTS_STR_EQUAL(tc, "cdefg", rbuf);
|
||||
|
||||
/* Check basic members */
|
||||
ABTS_TRUE(tc, rbuf_is_empty(&trbuf1));
|
||||
ABTS_FALSE(tc, rbuf_is_full(&trbuf1));
|
||||
ABTS_INT_EQUAL(tc, SIZE_OF_TRBUF1, rbuf_free_bytes(&trbuf1));
|
||||
ABTS_INT_EQUAL(tc, 0, rbuf_bytes(&trbuf1));
|
||||
|
||||
/* Read 1 bytes from empty buffer */
|
||||
n = rbuf_read(&trbuf1, rbuf, 1);
|
||||
ABTS_INT_EQUAL(tc, -1, n);
|
||||
}
|
||||
|
||||
static void rbuf_test2(abts_case *tc, void *data)
|
||||
{
|
||||
int i, n;
|
||||
char wbuf[32];
|
||||
char rbuf[32];
|
||||
|
||||
for (i = 0; i < 26; i++)
|
||||
wbuf[i] = 'a' + i;
|
||||
|
||||
rbuf_init_ext(&trbuf2, SIZE_OF_TRBUF1, trbuf2_ext_buf);
|
||||
|
||||
/* Check basic members */
|
||||
ABTS_TRUE(tc, rbuf_is_empty(&trbuf2));
|
||||
ABTS_FALSE(tc, rbuf_is_full(&trbuf2));
|
||||
ABTS_INT_EQUAL(tc, SIZE_OF_TRBUF2, rbuf_free_bytes(&trbuf2));
|
||||
ABTS_INT_EQUAL(tc, 0, rbuf_bytes(&trbuf2));
|
||||
|
||||
/* Write 3 bytes */
|
||||
n = rbuf_write(&trbuf2, wbuf, 3);
|
||||
ABTS_INT_EQUAL(tc, 3, n);
|
||||
|
||||
/* Check basic members */
|
||||
ABTS_FALSE(tc, rbuf_is_empty(&trbuf2));
|
||||
ABTS_FALSE(tc, rbuf_is_full(&trbuf2));
|
||||
ABTS_INT_EQUAL(tc, SIZE_OF_TRBUF2 - 3, rbuf_free_bytes(&trbuf2));
|
||||
ABTS_INT_EQUAL(tc, 3, rbuf_bytes(&trbuf2));
|
||||
|
||||
/* Read 3 bytes */
|
||||
n = rbuf_read(&trbuf2, rbuf, 3); rbuf[3] = 0;
|
||||
ABTS_INT_EQUAL(tc, 3, n);
|
||||
ABTS_STR_EQUAL(tc, "abc", rbuf);
|
||||
|
||||
/* Check basic members */
|
||||
ABTS_TRUE(tc, rbuf_is_empty(&trbuf2));
|
||||
ABTS_FALSE(tc, rbuf_is_full(&trbuf2));
|
||||
ABTS_INT_EQUAL(tc, SIZE_OF_TRBUF2, rbuf_free_bytes(&trbuf2));
|
||||
ABTS_INT_EQUAL(tc, 0, rbuf_bytes(&trbuf2));
|
||||
|
||||
/* Write 3 bytes */
|
||||
n = rbuf_write(&trbuf2, wbuf, 3);
|
||||
ABTS_INT_EQUAL(tc, 3, n);
|
||||
|
||||
/* Write 5 bytes, but only 4 bytes shall be written */
|
||||
n = rbuf_write(&trbuf2, wbuf + 3, 5);
|
||||
ABTS_INT_EQUAL(tc, 4, n);
|
||||
|
||||
/* Write 1 bytes to full buffer */
|
||||
n = rbuf_write(&trbuf2, wbuf, 1);
|
||||
ABTS_INT_EQUAL(tc, -1, n);
|
||||
|
||||
/* Read 2 bytes */
|
||||
n = rbuf_read(&trbuf2, rbuf, 2); rbuf[2] = 0;
|
||||
ABTS_INT_EQUAL(tc, 2, n);
|
||||
ABTS_STR_EQUAL(tc, "ab", rbuf);
|
||||
|
||||
/* Read 5 bytes */
|
||||
n = rbuf_read(&trbuf2, rbuf, 5); rbuf[5] = 0;
|
||||
ABTS_INT_EQUAL(tc, 5, n);
|
||||
ABTS_STR_EQUAL(tc, "cdefg", rbuf);
|
||||
|
||||
/* Check basic members */
|
||||
ABTS_TRUE(tc, rbuf_is_empty(&trbuf2));
|
||||
ABTS_FALSE(tc, rbuf_is_full(&trbuf2));
|
||||
ABTS_INT_EQUAL(tc, SIZE_OF_TRBUF2, rbuf_free_bytes(&trbuf2));
|
||||
ABTS_INT_EQUAL(tc, 0, rbuf_bytes(&trbuf2));
|
||||
|
||||
/* Read 1 bytes from empty buffer */
|
||||
n = rbuf_read(&trbuf2, rbuf, 1);
|
||||
ABTS_INT_EQUAL(tc, -1, n);
|
||||
|
||||
n = rbuf_skip_write_pos(&trbuf2, 5);
|
||||
ABTS_INT_EQUAL(tc, 5, n);
|
||||
n = rbuf_skip_read_pos(&trbuf2, 5);
|
||||
ABTS_INT_EQUAL(tc, 5, n);
|
||||
}
|
||||
|
||||
abts_suite *testds(abts_suite *suite)
|
||||
{
|
||||
suite = ADD_SUITE(suite)
|
||||
|
||||
abts_run_test(suite, pool_test1, NULL);
|
||||
abts_run_test(suite, pool_test2, NULL);
|
||||
|
||||
abts_run_test(suite, list_test1, NULL);
|
||||
abts_run_test(suite, list_test2, NULL);
|
||||
abts_run_test(suite, list_test3, NULL);
|
||||
abts_run_test(suite, list_test4, NULL);
|
||||
abts_run_test(suite, list_test5, NULL);
|
||||
|
||||
abts_run_test(suite, que_test1, NULL);
|
||||
|
||||
abts_run_test(suite, rbuf_test1, NULL);
|
||||
abts_run_test(suite, rbuf_test2, NULL);
|
||||
|
||||
return suite;
|
||||
}
|
|
@ -0,0 +1,684 @@
|
|||
#include "core_file.h"
|
||||
#include "testutil.h"
|
||||
|
||||
#define DIRNAME "data"
|
||||
#define FILENAME DIRNAME "/file_datafile.txt"
|
||||
#define TESTSTR "This is the file data file."
|
||||
|
||||
#define TESTREAD_BLKSIZE 1024
|
||||
#define FILE_BUFFERSIZE 4096 /* This should match FILE's buffer size. */
|
||||
|
||||
|
||||
static void test_file_init(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
file_info_t finfo;
|
||||
size_t bytes;
|
||||
file_t *filetest = NULL;
|
||||
|
||||
rv = dir_make("data", FILE_UREAD | FILE_UWRITE | FILE_UEXECUTE);
|
||||
|
||||
rv = file_stat(&finfo, "data", FILE_INFO_TYPE);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_INT_EQUAL(tc, FILE_DIR, finfo.filetype);
|
||||
|
||||
rv = file_open(&filetest, FILENAME,
|
||||
FILE_WRITE | FILE_CREATE,
|
||||
FILE_UREAD | FILE_UWRITE | FILE_GREAD);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
bytes = strlen(TESTSTR);
|
||||
rv = file_write(filetest, TESTSTR, &bytes);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
file_close(filetest);
|
||||
|
||||
}
|
||||
|
||||
static void test_open_noreadwrite(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
file_t *thefile = NULL;
|
||||
|
||||
rv = file_open(&thefile, FILENAME,
|
||||
FILE_CREATE | FILE_EXCL,
|
||||
FILE_UREAD | FILE_UWRITE | FILE_GREAD);
|
||||
ABTS_TRUE(tc, rv != CORE_OK);
|
||||
ABTS_INT_EQUAL(tc, 1, STATUS_IS_EACCES(rv));
|
||||
ABTS_PTR_EQUAL(tc, NULL, thefile);
|
||||
}
|
||||
|
||||
static void test_open_excl(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
file_t *thefile = NULL;
|
||||
|
||||
rv = file_open(&thefile, FILENAME,
|
||||
FILE_CREATE | FILE_EXCL | FILE_WRITE,
|
||||
FILE_UREAD | FILE_UWRITE | FILE_GREAD);
|
||||
ABTS_TRUE(tc, rv != CORE_OK);
|
||||
ABTS_INT_EQUAL(tc, 1, STATUS_IS_EEXIST(rv));
|
||||
ABTS_PTR_EQUAL(tc, NULL, thefile);
|
||||
}
|
||||
|
||||
static void test_open_read(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
file_t *filetest = NULL;
|
||||
|
||||
rv = file_open(&filetest, FILENAME,
|
||||
FILE_READ,
|
||||
FILE_UREAD | FILE_UWRITE | FILE_GREAD);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_PTR_NOTNULL(tc, filetest);
|
||||
file_close(filetest);
|
||||
}
|
||||
|
||||
static void link_existing(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
|
||||
rv = file_link("data/file_datafile.txt", "data/file_datafile2.txt");
|
||||
file_remove("data/file_datafile2.txt");
|
||||
ABTS_ASSERT(tc, "Couldn't create hardlink to file", rv == CORE_OK);
|
||||
}
|
||||
|
||||
static void link_nonexisting(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
|
||||
rv = file_link("data/does_not_exist.txt", "data/fake.txt");
|
||||
ABTS_ASSERT(tc, "", rv != CORE_OK);
|
||||
}
|
||||
|
||||
static void test_read(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
size_t nbytes = 256;
|
||||
char *str = malloc(nbytes + 1);
|
||||
file_t *filetest = NULL;
|
||||
|
||||
rv = file_open(&filetest, FILENAME,
|
||||
FILE_READ,
|
||||
FILE_UREAD | FILE_UWRITE | FILE_GREAD);
|
||||
|
||||
CORE_ASSERT_OK(tc, "Opening test file " FILENAME, rv);
|
||||
rv = file_read(filetest, str, &nbytes);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_SIZE_EQUAL(tc, strlen(TESTSTR), nbytes);
|
||||
ABTS_STR_EQUAL(tc, TESTSTR, str);
|
||||
|
||||
free(str);
|
||||
|
||||
file_close(filetest);
|
||||
}
|
||||
|
||||
static void test_readzero(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
size_t nbytes = 0;
|
||||
char *str = NULL;
|
||||
file_t *filetest;
|
||||
|
||||
rv = file_open(&filetest, FILENAME, FILE_READ, FILE_OS_DEFAULT);
|
||||
CORE_ASSERT_OK(tc, "Opening test file " FILENAME, rv);
|
||||
|
||||
rv = file_read(filetest, str, &nbytes);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_SIZE_EQUAL(tc, 0, nbytes);
|
||||
|
||||
file_close(filetest);
|
||||
}
|
||||
|
||||
static void test_filename(abts_case *tc, void *data)
|
||||
{
|
||||
const char *str;
|
||||
status_t rv;
|
||||
file_t *filetest = NULL;
|
||||
|
||||
rv = file_open(&filetest, FILENAME,
|
||||
FILE_READ,
|
||||
FILE_UREAD | FILE_UWRITE | FILE_GREAD);
|
||||
CORE_ASSERT_OK(tc, "Opening test file " FILENAME, rv);
|
||||
|
||||
rv = file_name_get(&str, filetest);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_STR_EQUAL(tc, FILENAME, str);
|
||||
|
||||
file_close(filetest);
|
||||
}
|
||||
|
||||
static void test_fileclose(abts_case *tc, void *data)
|
||||
{
|
||||
char str;
|
||||
status_t rv;
|
||||
size_t one = 1;
|
||||
file_t *filetest = NULL;
|
||||
|
||||
rv = file_open(&filetest, FILENAME,
|
||||
FILE_READ,
|
||||
FILE_UREAD | FILE_UWRITE | FILE_GREAD);
|
||||
CORE_ASSERT_OK(tc, "Opening test file " FILENAME, rv);
|
||||
|
||||
rv = file_close(filetest);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
/* We just closed the file, so this should fail */
|
||||
rv = file_read(filetest, &str, &one);
|
||||
ABTS_INT_EQUAL(tc, 1, STATUS_IS_EBADF(rv));
|
||||
}
|
||||
|
||||
static void test_file_remove(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
file_t *filetest = NULL;
|
||||
|
||||
rv = file_remove(FILENAME);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
rv = file_open(&filetest, FILENAME, FILE_READ,
|
||||
FILE_UREAD | FILE_UWRITE | FILE_GREAD);
|
||||
ABTS_INT_EQUAL(tc, 1, STATUS_IS_ENOENT(rv));
|
||||
}
|
||||
|
||||
static void test_open_write(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
file_t *filetest = NULL;
|
||||
|
||||
filetest = NULL;
|
||||
rv = file_open(&filetest, FILENAME,
|
||||
FILE_WRITE,
|
||||
FILE_UREAD | FILE_UWRITE | FILE_GREAD);
|
||||
ABTS_INT_EQUAL(tc, 1, STATUS_IS_ENOENT(rv));
|
||||
ABTS_PTR_EQUAL(tc, NULL, filetest);
|
||||
}
|
||||
|
||||
static void test_open_writecreate(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
file_t *filetest = NULL;
|
||||
|
||||
filetest = NULL;
|
||||
rv = file_open(&filetest, FILENAME,
|
||||
FILE_WRITE | FILE_CREATE,
|
||||
FILE_UREAD | FILE_UWRITE | FILE_GREAD);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
file_close(filetest);
|
||||
}
|
||||
|
||||
static void test_write(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
size_t bytes = strlen(TESTSTR);
|
||||
file_t *filetest = NULL;
|
||||
|
||||
rv = file_open(&filetest, FILENAME,
|
||||
FILE_WRITE | FILE_CREATE,
|
||||
FILE_UREAD | FILE_UWRITE | FILE_GREAD);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
rv = file_write(filetest, TESTSTR, &bytes);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
file_close(filetest);
|
||||
}
|
||||
|
||||
static void test_open_readwrite(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
file_t *filetest = NULL;
|
||||
|
||||
filetest = NULL;
|
||||
rv = file_open(&filetest, FILENAME,
|
||||
FILE_READ | FILE_WRITE,
|
||||
FILE_UREAD | FILE_UWRITE | FILE_GREAD);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_PTR_NOTNULL(tc, filetest);
|
||||
|
||||
file_close(filetest);
|
||||
}
|
||||
|
||||
static void test_seek(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
off_t offset = 5;
|
||||
size_t nbytes = 256;
|
||||
char *str = malloc(nbytes + 1);
|
||||
file_t *filetest = NULL;
|
||||
|
||||
rv = file_open(&filetest, FILENAME,
|
||||
FILE_READ,
|
||||
FILE_UREAD | FILE_UWRITE | FILE_GREAD);
|
||||
CORE_ASSERT_OK(tc, "Open test file " FILENAME, rv);
|
||||
|
||||
rv = file_read(filetest, str, &nbytes);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_SIZE_EQUAL(tc, strlen(TESTSTR), nbytes);
|
||||
ABTS_STR_EQUAL(tc, TESTSTR, str);
|
||||
|
||||
memset(str, 0, nbytes + 1);
|
||||
|
||||
rv = file_seek(filetest, SEEK_SET, &offset);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
rv = file_read(filetest, str, &nbytes);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_SIZE_EQUAL(tc, strlen(TESTSTR) - 5, nbytes);
|
||||
ABTS_STR_EQUAL(tc, TESTSTR + 5, str);
|
||||
|
||||
file_close(filetest);
|
||||
|
||||
/* Test for regression of sign error bug with SEEK_END and
|
||||
buffered files. */
|
||||
rv = file_open(&filetest, FILENAME,
|
||||
FILE_READ,
|
||||
FILE_UREAD | FILE_UWRITE | FILE_GREAD);
|
||||
CORE_ASSERT_OK(tc, "Open test file " FILENAME, rv);
|
||||
|
||||
offset = -5;
|
||||
rv = file_seek(filetest, SEEK_END, &offset);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_SIZE_EQUAL(tc, strlen(TESTSTR) - 5, nbytes);
|
||||
|
||||
memset(str, 0, nbytes + 1);
|
||||
nbytes = 256;
|
||||
rv = file_read(filetest, str, &nbytes);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_SIZE_EQUAL(tc, 5, nbytes);
|
||||
ABTS_STR_EQUAL(tc, TESTSTR + strlen(TESTSTR) - 5, str);
|
||||
|
||||
free(str);
|
||||
|
||||
file_close(filetest);
|
||||
}
|
||||
|
||||
static void test_getc(abts_case *tc, void *data)
|
||||
{
|
||||
file_t *f = NULL;
|
||||
status_t rv;
|
||||
char ch;
|
||||
|
||||
rv = file_open(&f, FILENAME, FILE_READ, 0);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
file_getc(&ch, f);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_INT_EQUAL(tc, (int)TESTSTR[0], (int)ch);
|
||||
file_close(f);
|
||||
}
|
||||
|
||||
static void test_gets(abts_case *tc, void *data)
|
||||
{
|
||||
file_t *f = NULL;
|
||||
status_t rv;
|
||||
char *str = malloc(256);
|
||||
|
||||
rv = file_open(&f, FILENAME, FILE_READ, 0);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
rv = file_gets(str, 256, f);
|
||||
/* Only one line in the test file, so FILE will encounter EOF on the first
|
||||
* call to gets, but we should get CORE_OK on this call and
|
||||
* CORE_EOF on the next.
|
||||
*/
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_STR_EQUAL(tc, TESTSTR, str);
|
||||
rv = file_gets(str, 256, f);
|
||||
ABTS_INT_EQUAL(tc, CORE_EOF, rv);
|
||||
ABTS_STR_EQUAL(tc, "", str);
|
||||
|
||||
free(str);
|
||||
file_close(f);
|
||||
}
|
||||
|
||||
static void test_bigread(abts_case *tc, void *data)
|
||||
{
|
||||
file_t *f = NULL;
|
||||
status_t rv;
|
||||
char buf[FILE_BUFFERSIZE * 2];
|
||||
size_t nbytes;
|
||||
|
||||
/* Create a test file with known content.
|
||||
*/
|
||||
rv = file_open(&f, "data/created_file",
|
||||
FILE_CREATE | FILE_WRITE | FILE_TRUNCATE,
|
||||
FILE_UREAD | FILE_UWRITE);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
nbytes = FILE_BUFFERSIZE;
|
||||
memset(buf, 0xFE, nbytes);
|
||||
|
||||
rv = file_write(f, buf, &nbytes);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_SIZE_EQUAL(tc, FILE_BUFFERSIZE, nbytes);
|
||||
|
||||
rv = file_close(f);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
f = NULL;
|
||||
rv = file_open(&f, "data/created_file", FILE_READ, 0);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
nbytes = sizeof buf;
|
||||
rv = file_read(f, buf, &nbytes);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_SIZE_EQUAL(tc, FILE_BUFFERSIZE, nbytes);
|
||||
|
||||
rv = file_close(f);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
rv = file_remove("data/created_file");
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
}
|
||||
|
||||
/* This is a horrible name for this function. We are testing FILE, not how
|
||||
* Apache uses FILE. And, this function tests _way_ too much stuff.
|
||||
*/
|
||||
static void test_mod_neg(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
file_t *f;
|
||||
const char *s;
|
||||
int i;
|
||||
size_t nbytes;
|
||||
char buf[8192];
|
||||
off_t cur;
|
||||
const char *fname = "data/modneg.dat";
|
||||
|
||||
rv = file_open(&f, fname,
|
||||
FILE_CREATE | FILE_WRITE, FILE_UREAD | FILE_UWRITE);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
s = "body56789\n";
|
||||
nbytes = strlen(s);
|
||||
rv = file_write(f, s, &nbytes);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_SIZE_EQUAL(tc, strlen(s), nbytes);
|
||||
|
||||
for (i = 0; i < 7980; i++) {
|
||||
s = "0";
|
||||
nbytes = strlen(s);
|
||||
rv = file_write(f, s, &nbytes);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_SIZE_EQUAL(tc, strlen(s), nbytes);
|
||||
}
|
||||
|
||||
s = "end456789\n";
|
||||
nbytes = strlen(s);
|
||||
rv = file_write(f, s, &nbytes);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_SIZE_EQUAL(tc, strlen(s), nbytes);
|
||||
|
||||
for (i = 0; i < 10000; i++) {
|
||||
s = "1";
|
||||
nbytes = strlen(s);
|
||||
rv = file_write(f, s, &nbytes);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_SIZE_EQUAL(tc, strlen(s), nbytes);
|
||||
}
|
||||
|
||||
rv = file_close(f);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
rv = file_open(&f, fname, FILE_READ, 0);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
rv = file_gets(buf, 11, f);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_STR_EQUAL(tc, "body56789\n", buf);
|
||||
|
||||
cur = 0;
|
||||
rv = file_seek(f, FILE_CUR, &cur);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_ASSERT(tc, "File Pointer Mismatch, expected 10", cur == 10);
|
||||
|
||||
nbytes = sizeof(buf);
|
||||
rv = file_read(f, buf, &nbytes);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_SIZE_EQUAL(tc, nbytes, sizeof(buf));
|
||||
|
||||
cur = -((off_t)nbytes - 7980);
|
||||
rv = file_seek(f, FILE_CUR, &cur);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_ASSERT(tc, "File Pointer Mismatch, expected 7990", cur == 7990);
|
||||
|
||||
rv = file_gets(buf, 11, f);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_STR_EQUAL(tc, "end456789\n", buf);
|
||||
|
||||
rv = file_close(f);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
rv = file_remove(fname);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
}
|
||||
|
||||
/* Test that the contents of file FNAME are equal to data EXPECT of
|
||||
* length EXPECTLEN. */
|
||||
static void file_contents_equal(abts_case *tc,
|
||||
const char *fname,
|
||||
const void *expect,
|
||||
size_t expectlen)
|
||||
{
|
||||
void *actual = malloc(expectlen);
|
||||
file_t *f;
|
||||
|
||||
CORE_ASSERT_OK(tc, "open file",
|
||||
file_open(&f, fname, FILE_READ,
|
||||
0));
|
||||
CORE_ASSERT_OK(tc, "read from file",
|
||||
file_read_full(f, actual, expectlen, NULL));
|
||||
|
||||
ABTS_ASSERT(tc, "matched expected file contents",
|
||||
memcmp(expect, actual, expectlen) == 0);
|
||||
|
||||
CORE_ASSERT_OK(tc, "close file", file_close(f));
|
||||
|
||||
free(actual);
|
||||
}
|
||||
|
||||
#define LINE1 "this is a line of text\n"
|
||||
#define LINE2 "this is a second line of text\n"
|
||||
|
||||
static void test_puts(abts_case *tc, void *data)
|
||||
{
|
||||
file_t *f;
|
||||
const char *fname = "data/testputs.txt";
|
||||
|
||||
CORE_ASSERT_OK(tc, "open file for writing",
|
||||
file_open(&f, fname,
|
||||
FILE_WRITE|FILE_CREATE|FILE_TRUNCATE,
|
||||
FILE_OS_DEFAULT));
|
||||
CORE_ASSERT_OK(tc, "write line to file",
|
||||
file_puts(LINE1, f));
|
||||
CORE_ASSERT_OK(tc, "write second line to file",
|
||||
file_puts(LINE2, f));
|
||||
|
||||
CORE_ASSERT_OK(tc, "close for writing",
|
||||
file_close(f));
|
||||
|
||||
file_contents_equal(tc, fname, LINE1 LINE2, strlen(LINE1 LINE2));
|
||||
}
|
||||
|
||||
static void test_writev(abts_case *tc, void *data)
|
||||
{
|
||||
file_t *f;
|
||||
size_t nbytes;
|
||||
struct iovec vec[5];
|
||||
const char *fname = "data/testwritev.txt";
|
||||
|
||||
CORE_ASSERT_OK(tc, "open file for writing",
|
||||
file_open(&f, fname,
|
||||
FILE_WRITE|FILE_CREATE|FILE_TRUNCATE,
|
||||
FILE_OS_DEFAULT));
|
||||
|
||||
vec[0].iov_base = LINE1;
|
||||
vec[0].iov_len = strlen(LINE1);
|
||||
|
||||
CORE_ASSERT_OK(tc, "writev of size 1 to file",
|
||||
file_writev(f, vec, 1, &nbytes));
|
||||
|
||||
file_contents_equal(tc, fname, LINE1, strlen(LINE1));
|
||||
|
||||
vec[0].iov_base = LINE1;
|
||||
vec[0].iov_len = strlen(LINE1);
|
||||
vec[1].iov_base = LINE2;
|
||||
vec[1].iov_len = strlen(LINE2);
|
||||
vec[2].iov_base = LINE1;
|
||||
vec[2].iov_len = strlen(LINE1);
|
||||
vec[3].iov_base = LINE1;
|
||||
vec[3].iov_len = strlen(LINE1);
|
||||
vec[4].iov_base = LINE2;
|
||||
vec[4].iov_len = strlen(LINE2);
|
||||
|
||||
CORE_ASSERT_OK(tc, "writev of size 5 to file",
|
||||
file_writev(f, vec, 5, &nbytes));
|
||||
|
||||
CORE_ASSERT_OK(tc, "close for writing",
|
||||
file_close(f));
|
||||
|
||||
file_contents_equal(tc, fname, LINE1 LINE1 LINE2 LINE1 LINE1 LINE2,
|
||||
strlen(LINE1)*4 + strlen(LINE2)*2);
|
||||
|
||||
}
|
||||
|
||||
static void test_writev_full(abts_case *tc, void *data)
|
||||
{
|
||||
file_t *f;
|
||||
size_t nbytes;
|
||||
struct iovec vec[5];
|
||||
const char *fname = "data/testwritev_full.txt";
|
||||
|
||||
CORE_ASSERT_OK(tc, "open file for writing",
|
||||
file_open(&f, fname,
|
||||
FILE_WRITE|FILE_CREATE|FILE_TRUNCATE,
|
||||
FILE_OS_DEFAULT));
|
||||
|
||||
vec[0].iov_base = LINE1;
|
||||
vec[0].iov_len = strlen(LINE1);
|
||||
vec[1].iov_base = LINE2;
|
||||
vec[1].iov_len = strlen(LINE2);
|
||||
vec[2].iov_base = LINE1;
|
||||
vec[2].iov_len = strlen(LINE1);
|
||||
vec[3].iov_base = LINE1;
|
||||
vec[3].iov_len = strlen(LINE1);
|
||||
vec[4].iov_base = LINE2;
|
||||
vec[4].iov_len = strlen(LINE2);
|
||||
|
||||
CORE_ASSERT_OK(tc, "writev_full of size 5 to file",
|
||||
file_writev_full(f, vec, 5, &nbytes));
|
||||
|
||||
ABTS_SIZE_EQUAL(tc, strlen(LINE1)*3 + strlen(LINE2)*2, nbytes);
|
||||
|
||||
CORE_ASSERT_OK(tc, "close for writing",
|
||||
file_close(f));
|
||||
|
||||
file_contents_equal(tc, fname, LINE1 LINE2 LINE1 LINE1 LINE2,
|
||||
strlen(LINE1)*3 + strlen(LINE2)*2);
|
||||
|
||||
}
|
||||
|
||||
static void test_truncate(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
file_t *f;
|
||||
const char *fname = "data/testtruncate.dat";
|
||||
const char *s;
|
||||
size_t nbytes;
|
||||
file_info_t finfo;
|
||||
|
||||
file_remove(fname);
|
||||
|
||||
rv = file_open(&f, fname,
|
||||
FILE_CREATE | FILE_WRITE, FILE_UREAD | FILE_UWRITE);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
s = "some data";
|
||||
nbytes = strlen(s);
|
||||
rv = file_write(f, s, &nbytes);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_SIZE_EQUAL(tc, strlen(s), nbytes);
|
||||
|
||||
rv = file_close(f);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
rv = file_open(&f, fname,
|
||||
FILE_TRUNCATE | FILE_WRITE, FILE_UREAD | FILE_UWRITE);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
rv = file_close(f);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
rv = file_stat(&finfo, fname, FILE_INFO_SIZE);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_ASSERT(tc, "File size mismatch, expected 0 (empty)", finfo.size == 0);
|
||||
|
||||
rv = file_remove(fname);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
}
|
||||
|
||||
static void test_fail_write_flush(abts_case *tc, void *data)
|
||||
{
|
||||
file_t *f;
|
||||
const char *fname = "data/testflush.dat";
|
||||
status_t rv;
|
||||
char buf[FILE_BUFFERSIZE];
|
||||
int n;
|
||||
|
||||
file_remove(fname);
|
||||
|
||||
CORE_ASSERT_OK(tc, "open test file",
|
||||
file_open(&f, fname,
|
||||
FILE_CREATE|FILE_READ,
|
||||
FILE_UREAD|FILE_UWRITE));
|
||||
|
||||
memset(buf, 'A', sizeof buf);
|
||||
|
||||
/* Try three writes. One of these should fail when it exceeds the
|
||||
* internal buffer and actually tries to write to the file, which
|
||||
* was opened read-only and hence should be unwritable. */
|
||||
for (n = 0, rv = CORE_OK; n < 4 && rv == CORE_OK; n++) {
|
||||
size_t bytes = sizeof buf;
|
||||
rv = file_write(f, buf, &bytes);
|
||||
}
|
||||
|
||||
ABTS_ASSERT(tc, "failed to write to read-only buffered fd",
|
||||
rv != CORE_OK);
|
||||
|
||||
file_close(f);
|
||||
}
|
||||
|
||||
abts_suite *testfile(abts_suite *suite)
|
||||
{
|
||||
suite = ADD_SUITE(suite)
|
||||
|
||||
abts_run_test(suite, test_file_init, NULL);
|
||||
abts_run_test(suite, test_open_noreadwrite, NULL);
|
||||
abts_run_test(suite, test_open_excl, NULL);
|
||||
abts_run_test(suite, test_open_read, NULL);
|
||||
abts_run_test(suite, test_open_readwrite, NULL);
|
||||
abts_run_test(suite, link_existing, NULL);
|
||||
abts_run_test(suite, link_nonexisting, NULL);
|
||||
abts_run_test(suite, test_read, NULL);
|
||||
abts_run_test(suite, test_readzero, NULL);
|
||||
abts_run_test(suite, test_seek, NULL);
|
||||
abts_run_test(suite, test_filename, NULL);
|
||||
abts_run_test(suite, test_fileclose, NULL);
|
||||
abts_run_test(suite, test_file_remove, NULL);
|
||||
abts_run_test(suite, test_open_write, NULL);
|
||||
abts_run_test(suite, test_open_writecreate, NULL);
|
||||
abts_run_test(suite, test_write, NULL);
|
||||
abts_run_test(suite, test_getc, NULL);
|
||||
abts_run_test(suite, test_gets, NULL);
|
||||
abts_run_test(suite, test_puts, NULL);
|
||||
abts_run_test(suite, test_writev, NULL);
|
||||
abts_run_test(suite, test_writev_full, NULL);
|
||||
abts_run_test(suite, test_bigread, NULL);
|
||||
abts_run_test(suite, test_mod_neg, NULL);
|
||||
abts_run_test(suite, test_truncate, NULL);
|
||||
abts_run_test(suite, test_fail_write_flush, NULL);
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
#include "core_file.h"
|
||||
#include "testutil.h"
|
||||
|
||||
#define DIRNAME "data"
|
||||
#define FILENAME1 DIRNAME "/file_datafile.txt"
|
||||
#define TESTSTR1 "This is the file data file."
|
||||
#define FILENAME2 DIRNAME "/mmap_datafile.txt"
|
||||
#define TESTSTR2 "This is the MMAP data file."
|
||||
|
||||
static void test_filecopy_init(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
file_info_t finfo;
|
||||
size_t bytes;
|
||||
file_t *filetest = NULL;
|
||||
|
||||
rv = dir_make("data", FILE_UREAD | FILE_UWRITE | FILE_UEXECUTE);
|
||||
|
||||
rv = file_stat(&finfo, "data", FILE_INFO_TYPE);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
ABTS_INT_EQUAL(tc, FILE_DIR, finfo.filetype);
|
||||
|
||||
rv = file_open(&filetest, FILENAME1,
|
||||
FILE_WRITE | FILE_CREATE,
|
||||
FILE_UREAD | FILE_UWRITE | FILE_GREAD);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
bytes = strlen(TESTSTR1);
|
||||
rv = file_write(filetest, TESTSTR1, &bytes);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
file_close(filetest);
|
||||
|
||||
rv = file_open(&filetest, FILENAME2,
|
||||
FILE_WRITE | FILE_CREATE,
|
||||
FILE_UREAD | FILE_UWRITE | FILE_GREAD);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
bytes = strlen(TESTSTR2);
|
||||
rv = file_write(filetest, TESTSTR2, &bytes);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
file_close(filetest);
|
||||
}
|
||||
|
||||
static void copy_helper(abts_case *tc, const char *from, const char * to,
|
||||
file_perms_t perms, int append)
|
||||
{
|
||||
status_t rv;
|
||||
status_t dest_rv;
|
||||
file_info_t copy;
|
||||
file_info_t orig;
|
||||
file_info_t dest;
|
||||
|
||||
dest_rv = file_stat(&dest, to, FILE_INFO_SIZE);
|
||||
|
||||
if (!append) {
|
||||
rv = file_copy(from, to, perms);
|
||||
}
|
||||
else {
|
||||
rv = file_append(from, to, perms);
|
||||
}
|
||||
CORE_ASSERT_OK(tc, "Error copying file", rv);
|
||||
|
||||
rv = file_stat(&orig, from, FILE_INFO_SIZE);
|
||||
CORE_ASSERT_OK(tc, "Couldn't stat original file", rv);
|
||||
|
||||
rv = file_stat(©, to, FILE_INFO_SIZE);
|
||||
CORE_ASSERT_OK(tc, "Couldn't stat copy file", rv);
|
||||
|
||||
if (!append) {
|
||||
ABTS_ASSERT(tc, "File size differs", orig.size == copy.size);
|
||||
}
|
||||
else {
|
||||
ABTS_ASSERT(tc, "File size differs",
|
||||
((dest_rv == CORE_OK)
|
||||
? dest.size : 0) + orig.size == copy.size);
|
||||
}
|
||||
}
|
||||
|
||||
static void copy_short_file(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
|
||||
/* make absolutely sure that the dest file doesn't exist. */
|
||||
file_remove("data/file_copy.txt");
|
||||
|
||||
copy_helper(tc, "data/file_datafile.txt", "data/file_copy.txt",
|
||||
FILE_SOURCE_PERMS, 0);
|
||||
rv = file_remove("data/file_copy.txt");
|
||||
CORE_ASSERT_OK(tc, "Couldn't remove copy file", rv);
|
||||
}
|
||||
|
||||
static void copy_over_existing(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
|
||||
/* make absolutely sure that the dest file doesn't exist. */
|
||||
file_remove("data/file_copy.txt");
|
||||
|
||||
/* This is a cheat. I don't want to create a new file, so I just copy
|
||||
* one file, then I copy another. If the second copy succeeds, then
|
||||
* this works.
|
||||
*/
|
||||
copy_helper(tc, "data/file_datafile.txt", "data/file_copy.txt",
|
||||
FILE_SOURCE_PERMS, 0);
|
||||
|
||||
copy_helper(tc, "data/mmap_datafile.txt", "data/file_copy.txt",
|
||||
FILE_SOURCE_PERMS, 0);
|
||||
|
||||
rv = file_remove("data/file_copy.txt");
|
||||
CORE_ASSERT_OK(tc, "Couldn't remove copy file", rv);
|
||||
}
|
||||
|
||||
static void append_nonexist(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
|
||||
/* make absolutely sure that the dest file doesn't exist. */
|
||||
file_remove("data/file_copy.txt");
|
||||
|
||||
copy_helper(tc, "data/file_datafile.txt", "data/file_copy.txt",
|
||||
FILE_SOURCE_PERMS, 0);
|
||||
rv = file_remove("data/file_copy.txt");
|
||||
CORE_ASSERT_OK(tc, "Couldn't remove copy file", rv);
|
||||
}
|
||||
|
||||
static void append_exist(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
|
||||
/* make absolutely sure that the dest file doesn't exist. */
|
||||
file_remove("data/file_copy.txt");
|
||||
|
||||
/* This is a cheat. I don't want to create a new file, so I just copy
|
||||
* one file, then I copy another. If the second copy succeeds, then
|
||||
* this works.
|
||||
*/
|
||||
copy_helper(tc, "data/file_datafile.txt", "data/file_copy.txt",
|
||||
FILE_SOURCE_PERMS, 0);
|
||||
|
||||
copy_helper(tc, "data/mmap_datafile.txt", "data/file_copy.txt",
|
||||
FILE_SOURCE_PERMS, 1);
|
||||
|
||||
rv = file_remove("data/file_copy.txt");
|
||||
CORE_ASSERT_OK(tc, "Couldn't remove copy file", rv);
|
||||
}
|
||||
|
||||
abts_suite *testfilecopy(abts_suite *suite)
|
||||
{
|
||||
suite = ADD_SUITE(suite)
|
||||
|
||||
abts_run_test(suite, test_filecopy_init, NULL);
|
||||
|
||||
abts_run_test(suite, copy_short_file, NULL);
|
||||
abts_run_test(suite, copy_over_existing, NULL);
|
||||
|
||||
abts_run_test(suite, append_nonexist, NULL);
|
||||
abts_run_test(suite, append_exist, NULL);
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
|
@ -0,0 +1,298 @@
|
|||
#include "core_fsm.h"
|
||||
#include "testutil.h"
|
||||
|
||||
enum bomb_signal_t {
|
||||
UP_SIG = FSM_USER_SIG,
|
||||
DOWN_SIG,
|
||||
ARM_SIG
|
||||
};
|
||||
|
||||
typedef struct _tick_event_t {
|
||||
fsm_event_t event;
|
||||
} tick_event_t;
|
||||
|
||||
typedef struct _bomb_t {
|
||||
fsm_t fsm;
|
||||
c_uint8_t timeout;
|
||||
c_uint8_t code;
|
||||
c_uint8_t defuse;
|
||||
} bomb_t;
|
||||
|
||||
void bomb_initial(bomb_t *s, fsm_event_t *e);
|
||||
void bomb_setting(bomb_t *s, fsm_event_t *e);
|
||||
void bomb_timing(bomb_t *s, fsm_event_t *e);
|
||||
|
||||
void bomb_create(bomb_t *s, uint8_t defuse)
|
||||
{
|
||||
fsm_create(&s->fsm, (fsm_handler_t)&bomb_initial, (fsm_handler_t)0);
|
||||
s->defuse = defuse;
|
||||
}
|
||||
|
||||
void bomb_initial(bomb_t *s, fsm_event_t *e)
|
||||
{
|
||||
s->timeout = 10;
|
||||
FSM_TRAN(s, &bomb_setting);
|
||||
}
|
||||
|
||||
void bomb_setting(bomb_t *s, fsm_event_t *e)
|
||||
{
|
||||
tick_event_t *te = (tick_event_t*)e;
|
||||
switch (te->event)
|
||||
{
|
||||
case UP_SIG:
|
||||
{
|
||||
if (s->timeout < 12)
|
||||
{
|
||||
++s->timeout;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DOWN_SIG: {
|
||||
if (s->timeout > 8)
|
||||
{
|
||||
--s->timeout;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ARM_SIG:
|
||||
{
|
||||
FSM_TRAN(s, &bomb_timing);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bomb_timing(bomb_t *s, fsm_event_t *e)
|
||||
{
|
||||
tick_event_t *te = (tick_event_t*)e;
|
||||
switch (te->event)
|
||||
{
|
||||
case FSM_ENTRY_SIG:
|
||||
{
|
||||
s->code = 0;
|
||||
break;
|
||||
}
|
||||
case UP_SIG:
|
||||
{
|
||||
s->code <<= 1;
|
||||
s->code |= 1;
|
||||
break;
|
||||
}
|
||||
case DOWN_SIG:
|
||||
{
|
||||
s->code <<= 1;
|
||||
break;
|
||||
}
|
||||
case ARM_SIG:
|
||||
{
|
||||
if (s->code == s->defuse)
|
||||
{
|
||||
FSM_TRAN(s, &bomb_setting);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fsm_test1(abts_case *tc, void *data)
|
||||
{
|
||||
bomb_t bomb;
|
||||
tick_event_t tick_event;
|
||||
|
||||
bomb_create(&bomb, 14);
|
||||
|
||||
fsm_init((fsm_t *)&bomb, (fsm_event_t*)0);
|
||||
ABTS_PTR_EQUAL(tc, &bomb_setting, ((fsm_t*)&bomb)->state);
|
||||
ABTS_INT_EQUAL(tc, 10, bomb.timeout);
|
||||
|
||||
tick_event.event = UP_SIG;
|
||||
fsm_dispatch((fsm_t *)&bomb, (fsm_event_t*)&tick_event);
|
||||
ABTS_PTR_EQUAL(tc, &bomb_setting, ((fsm_t*)&bomb)->state);
|
||||
ABTS_INT_EQUAL(tc, 11, bomb.timeout);
|
||||
fsm_dispatch((fsm_t *)&bomb, (fsm_event_t*)&tick_event);
|
||||
ABTS_PTR_EQUAL(tc, &bomb_setting, ((fsm_t*)&bomb)->state);
|
||||
ABTS_INT_EQUAL(tc, 12, bomb.timeout);
|
||||
fsm_dispatch((fsm_t *)&bomb, (fsm_event_t*)&tick_event);
|
||||
ABTS_PTR_EQUAL(tc, &bomb_setting, ((fsm_t*)&bomb)->state);
|
||||
ABTS_INT_EQUAL(tc, 12, bomb.timeout);
|
||||
|
||||
tick_event.event = DOWN_SIG;
|
||||
fsm_dispatch((fsm_t *)&bomb, (fsm_event_t*)&tick_event);
|
||||
ABTS_PTR_EQUAL(tc, &bomb_setting, ((fsm_t*)&bomb)->state);
|
||||
ABTS_INT_EQUAL(tc, 11, bomb.timeout);
|
||||
fsm_dispatch((fsm_t *)&bomb, (fsm_event_t*)&tick_event);
|
||||
ABTS_PTR_EQUAL(tc, &bomb_setting, ((fsm_t*)&bomb)->state);
|
||||
ABTS_INT_EQUAL(tc, 10, bomb.timeout);
|
||||
fsm_dispatch((fsm_t *)&bomb, (fsm_event_t*)&tick_event);
|
||||
ABTS_PTR_EQUAL(tc, &bomb_setting, ((fsm_t*)&bomb)->state);
|
||||
ABTS_INT_EQUAL(tc, 9, bomb.timeout);
|
||||
fsm_dispatch((fsm_t *)&bomb, (fsm_event_t*)&tick_event);
|
||||
ABTS_PTR_EQUAL(tc, &bomb_setting, ((fsm_t*)&bomb)->state);
|
||||
ABTS_INT_EQUAL(tc, 8, bomb.timeout);
|
||||
fsm_dispatch((fsm_t *)&bomb, (fsm_event_t*)&tick_event);
|
||||
ABTS_PTR_EQUAL(tc, &bomb_setting, ((fsm_t*)&bomb)->state);
|
||||
ABTS_INT_EQUAL(tc, 8, bomb.timeout);
|
||||
|
||||
tick_event.event = ARM_SIG;
|
||||
fsm_dispatch((fsm_t *)&bomb, (fsm_event_t*)&tick_event);
|
||||
ABTS_PTR_EQUAL(tc, &bomb_timing, ((fsm_t*)&bomb)->state);
|
||||
ABTS_INT_EQUAL(tc, 0, bomb.code);
|
||||
|
||||
tick_event.event = UP_SIG;
|
||||
fsm_dispatch((fsm_t *)&bomb, (fsm_event_t*)&tick_event);
|
||||
ABTS_PTR_EQUAL(tc, &bomb_timing, ((fsm_t*)&bomb)->state);
|
||||
ABTS_INT_EQUAL(tc, 1, bomb.code);
|
||||
|
||||
tick_event.event = UP_SIG;
|
||||
fsm_dispatch((fsm_t *)&bomb, (fsm_event_t*)&tick_event);
|
||||
ABTS_PTR_EQUAL(tc, &bomb_timing, ((fsm_t*)&bomb)->state);
|
||||
ABTS_INT_EQUAL(tc, 3, bomb.code);
|
||||
|
||||
tick_event.event = UP_SIG;
|
||||
fsm_dispatch((fsm_t *)&bomb, (fsm_event_t*)&tick_event);
|
||||
ABTS_PTR_EQUAL(tc, &bomb_timing, ((fsm_t*)&bomb)->state);
|
||||
ABTS_INT_EQUAL(tc, 7, bomb.code);
|
||||
|
||||
tick_event.event = DOWN_SIG;
|
||||
fsm_dispatch((fsm_t *)&bomb, (fsm_event_t*)&tick_event);
|
||||
ABTS_PTR_EQUAL(tc, &bomb_timing, ((fsm_t*)&bomb)->state);
|
||||
ABTS_INT_EQUAL(tc, 14, bomb.code);
|
||||
|
||||
tick_event.event = ARM_SIG;
|
||||
fsm_dispatch((fsm_t *)&bomb, (fsm_event_t*)&tick_event);
|
||||
ABTS_PTR_EQUAL(tc, &bomb_setting, ((fsm_t*)&bomb)->state);
|
||||
}
|
||||
|
||||
enum alarm_signal_t {
|
||||
TICK_SIG = FSM_USER_SIG,
|
||||
ALARM_SET_SIG,
|
||||
ALARM_ON_SIG,
|
||||
ALARM_OFF_SIG,
|
||||
ALARM_SIG,
|
||||
CLOCK_12H_SIG,
|
||||
CLOCK_24H_SIG,
|
||||
TIME_SIG,
|
||||
TERMINATE_SIG
|
||||
};
|
||||
|
||||
typedef struct _alarm_t {
|
||||
fsm_t fsm;
|
||||
c_uint32_t time;
|
||||
} alarm_t;
|
||||
|
||||
typedef struct _set_event_t {
|
||||
fsm_event_t event;
|
||||
c_uint8_t digit;
|
||||
} set_event_t;
|
||||
|
||||
typedef struct _time_event_t {
|
||||
fsm_event_t event;
|
||||
c_uint8_t current_time;
|
||||
} time_event_t;
|
||||
|
||||
void alarm_initial(alarm_t *s, fsm_event_t *e);
|
||||
void alarm_off(alarm_t *s, fsm_event_t *e);
|
||||
void alarm_on(alarm_t *s, fsm_event_t *e);
|
||||
|
||||
void alarm_initial(alarm_t *s, fsm_event_t *e)
|
||||
{
|
||||
s->time = 12*60;
|
||||
FSM_TRAN(s, &alarm_off);
|
||||
}
|
||||
|
||||
void alarm_off(alarm_t *s, fsm_event_t *e)
|
||||
{
|
||||
set_event_t *ae = (set_event_t*)e;
|
||||
switch (ae->event)
|
||||
{
|
||||
case FSM_ENTRY_SIG:
|
||||
{
|
||||
s->time = (s->time/60)*100 + s->time%60;
|
||||
break;
|
||||
}
|
||||
case FSM_EXIT_SIG:
|
||||
{
|
||||
s->time = (s->time/100)*60 + s->time%100;
|
||||
break;
|
||||
}
|
||||
case ALARM_ON_SIG:
|
||||
{
|
||||
FSM_TRAN(s, &alarm_on);
|
||||
break;
|
||||
}
|
||||
case ALARM_SET_SIG:
|
||||
{
|
||||
c_uint32_t alarm = (10 * s->time
|
||||
+ ae->digit) % 10000;
|
||||
if ((alarm / 100 < 24) && (alarm % 100 < 60))
|
||||
{
|
||||
s->time = alarm;
|
||||
}
|
||||
else
|
||||
{
|
||||
s->time = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void alarm_on(alarm_t *s, fsm_event_t *e)
|
||||
{
|
||||
time_event_t *ae = (time_event_t*)e;
|
||||
switch (ae->event)
|
||||
{
|
||||
case FSM_ENTRY_SIG:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case ALARM_SET_SIG:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case ALARM_OFF_SIG:
|
||||
{
|
||||
FSM_TRAN(s, &alarm_off);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fsm_test2(abts_case *tc, void *data)
|
||||
{
|
||||
alarm_t alarm;
|
||||
set_event_t set_event;
|
||||
time_event_t time_event;
|
||||
|
||||
fsm_create((fsm_t *)&alarm, (fsm_handler_t)&alarm_initial, (fsm_handler_t)0);
|
||||
|
||||
fsm_init((fsm_t *)&alarm, (fsm_event_t*)0);
|
||||
ABTS_PTR_EQUAL(tc, &alarm_off, ((fsm_t*)&alarm)->state);
|
||||
ABTS_INT_EQUAL(tc, 1200, alarm.time);
|
||||
|
||||
set_event.event = ALARM_ON_SIG;
|
||||
fsm_dispatch((fsm_t *)&alarm, (fsm_event_t*)&set_event);
|
||||
ABTS_PTR_EQUAL(tc, &alarm_on, ((fsm_t*)&alarm)->state);
|
||||
ABTS_INT_EQUAL(tc, 720, alarm.time);
|
||||
|
||||
time_event.event = ALARM_OFF_SIG;
|
||||
fsm_dispatch((fsm_t *)&alarm, (fsm_event_t*)&time_event);
|
||||
ABTS_PTR_EQUAL(tc, &alarm_off, ((fsm_t*)&alarm)->state);
|
||||
ABTS_INT_EQUAL(tc, 1200, alarm.time);
|
||||
|
||||
set_event.event = ALARM_SET_SIG;
|
||||
set_event.digit = 0;
|
||||
fsm_dispatch((fsm_t *)&alarm, (fsm_event_t*)&set_event);
|
||||
ABTS_PTR_EQUAL(tc, &alarm_off, ((fsm_t*)&alarm)->state);
|
||||
ABTS_INT_EQUAL(tc, 2000, alarm.time);
|
||||
}
|
||||
|
||||
abts_suite *testfsm(abts_suite *suite)
|
||||
{
|
||||
suite = ADD_SUITE(suite)
|
||||
|
||||
abts_run_test(suite, fsm_test1, NULL);
|
||||
abts_run_test(suite, fsm_test2, NULL);
|
||||
|
||||
return suite;
|
||||
}
|
|
@ -0,0 +1,393 @@
|
|||
#include "core_thread.h"
|
||||
#include "core_mutex.h"
|
||||
#include "core_cond.h"
|
||||
#include "core_rwlock.h"
|
||||
#include "core_semaphore.h"
|
||||
#include "core_time.h"
|
||||
#include "testutil.h"
|
||||
|
||||
#define MAX_ITER 40000
|
||||
#define MAX_COUNTER 10000
|
||||
#define MAX_RETRY 3
|
||||
|
||||
static void *THREAD_FUNC thread_rwlock_func(void *data);
|
||||
static void *THREAD_FUNC thread_mutex_function(void *data);
|
||||
static void *THREAD_FUNC thread_cond_producer(void *data);
|
||||
static void *THREAD_FUNC thread_cond_consumer(void *data);
|
||||
|
||||
static mutex_id mutex;
|
||||
static rwlock_id rwlock;
|
||||
static semaphore_id semaphore;
|
||||
static int i = 0, x = 0;
|
||||
|
||||
static int buff[MAX_COUNTER];
|
||||
|
||||
struct {
|
||||
mutex_id mutex;
|
||||
int nput;
|
||||
int nval;
|
||||
} put;
|
||||
|
||||
struct {
|
||||
mutex_id mutex;
|
||||
cond_id cond;
|
||||
int nready;
|
||||
} nready;
|
||||
|
||||
static mutex_id timeout_mutex;
|
||||
static cond_id timeout_cond;
|
||||
|
||||
static void *THREAD_FUNC thread_rwlock_func(void *data)
|
||||
{
|
||||
int exitLoop = 1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
rwlock_rdlock(rwlock);
|
||||
if (i == MAX_ITER)
|
||||
exitLoop = 0;
|
||||
rwlock_unlock(rwlock);
|
||||
|
||||
if (!exitLoop)
|
||||
break;
|
||||
|
||||
rwlock_wrlock(rwlock);
|
||||
if (i != MAX_ITER)
|
||||
{
|
||||
i++;
|
||||
x++;
|
||||
}
|
||||
rwlock_unlock(rwlock);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *THREAD_FUNC thread_mutex_function(void *data)
|
||||
{
|
||||
int exitLoop = 1;
|
||||
|
||||
/* slight delay to allow things to settle */
|
||||
core_sleep (1);
|
||||
|
||||
while (1)
|
||||
{
|
||||
mutex_lock(mutex);
|
||||
if (i == MAX_ITER)
|
||||
exitLoop = 0;
|
||||
else
|
||||
{
|
||||
i++;
|
||||
x++;
|
||||
}
|
||||
mutex_unlock(mutex);
|
||||
|
||||
if (!exitLoop)
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *THREAD_FUNC thread_cond_producer(void *data)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
mutex_lock(put.mutex);
|
||||
if (put.nput >= MAX_COUNTER)
|
||||
{
|
||||
mutex_unlock(put.mutex);
|
||||
return NULL;
|
||||
}
|
||||
buff[put.nput] = put.nval;
|
||||
put.nput++;
|
||||
put.nval++;
|
||||
mutex_unlock(put.mutex);
|
||||
|
||||
mutex_lock(nready.mutex);
|
||||
if (nready.nready == 0)
|
||||
cond_signal(nready.cond);
|
||||
nready.nready++;
|
||||
mutex_unlock(nready.mutex);
|
||||
|
||||
*((int *) data) += 1;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *THREAD_FUNC thread_cond_consumer(void *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_COUNTER; i++)
|
||||
{
|
||||
mutex_lock(nready.mutex);
|
||||
while (nready.nready == 0)
|
||||
cond_wait(nready.cond, nready.mutex);
|
||||
nready.nready--;
|
||||
mutex_unlock(nready.mutex);
|
||||
|
||||
if (buff[i] != i)
|
||||
printf("buff[%d] = %d\n", i, buff[i]);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *THREAD_FUNC thread_semaphore_function(void *data)
|
||||
{
|
||||
int exitLoop = 1;
|
||||
|
||||
/* slight delay to allow things to settle */
|
||||
core_sleep (1);
|
||||
|
||||
while (1)
|
||||
{
|
||||
semaphore_wait(semaphore);
|
||||
if (i == MAX_ITER)
|
||||
exitLoop = 0;
|
||||
else
|
||||
{
|
||||
i++;
|
||||
x++;
|
||||
}
|
||||
semaphore_post(semaphore);
|
||||
|
||||
if (!exitLoop)
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void test_mutex(abts_case *tc, void *data)
|
||||
{
|
||||
thread_id t1, t2, t3, t4;
|
||||
status_t s1, s2, s3, s4;
|
||||
|
||||
s1 = mutex_create(&mutex, MUTEX_DEFAULT);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, s1);
|
||||
|
||||
i = 0;
|
||||
x = 0;
|
||||
|
||||
s1 = thread_create(&t1, NULL, thread_mutex_function, NULL);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, s1);
|
||||
s2 = thread_create(&t2, NULL, thread_mutex_function, NULL);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, s2);
|
||||
s3 = thread_create(&t3, NULL, thread_mutex_function, NULL);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, s3);
|
||||
s4 = thread_create(&t4, NULL, thread_mutex_function, NULL);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, s4);
|
||||
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, thread_delete(t1));
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, thread_delete(t2));
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, thread_delete(t3));
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, thread_delete(t4));
|
||||
|
||||
ABTS_INT_EQUAL(tc, MAX_ITER, x);
|
||||
|
||||
CORE_ASSERT_OK(tc, "delete mutex", mutex_delete(mutex));
|
||||
}
|
||||
|
||||
static void test_thread_rwlock(abts_case *tc, void *data)
|
||||
{
|
||||
thread_id t1, t2, t3, t4;
|
||||
status_t s1, s2, s3, s4;
|
||||
|
||||
s1 = rwlock_create(&rwlock);
|
||||
if (s1 == CORE_ENOTIMPL)
|
||||
{
|
||||
ABTS_NOT_IMPL(tc, "rwlocks not implemented");
|
||||
return;
|
||||
}
|
||||
CORE_ASSERT_OK(tc, "rwlock_create", s1);
|
||||
|
||||
i = 0;
|
||||
x = 0;
|
||||
|
||||
s1 = thread_create(&t1, NULL, thread_rwlock_func, NULL);
|
||||
CORE_ASSERT_OK(tc, "create thread 1", s1);
|
||||
s2 = thread_create(&t2, NULL, thread_rwlock_func, NULL);
|
||||
CORE_ASSERT_OK(tc, "create thread 2", s2);
|
||||
s3 = thread_create(&t3, NULL, thread_rwlock_func, NULL);
|
||||
CORE_ASSERT_OK(tc, "create thread 3", s3);
|
||||
s4 = thread_create(&t4, NULL, thread_rwlock_func, NULL);
|
||||
CORE_ASSERT_OK(tc, "create thread 4", s4);
|
||||
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, thread_delete(t1));
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, thread_delete(t2));
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, thread_delete(t3));
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, thread_delete(t4));
|
||||
|
||||
ABTS_INT_EQUAL(tc, MAX_ITER, x);
|
||||
|
||||
CORE_ASSERT_OK(tc, "delete rwlock", rwlock_delete(rwlock));
|
||||
}
|
||||
|
||||
static void test_cond(abts_case *tc, void *data)
|
||||
{
|
||||
thread_id p1, p2, p3, p4, c1;
|
||||
status_t s0, s1, s2, s3, s4;
|
||||
int count1, count2, count3, count4;
|
||||
int sum;
|
||||
|
||||
CORE_ASSERT_OK(tc, "create put mutex",
|
||||
mutex_create(&put.mutex, MUTEX_DEFAULT));
|
||||
|
||||
CORE_ASSERT_OK(tc, "create nready mutex",
|
||||
mutex_create(&nready.mutex, MUTEX_DEFAULT));
|
||||
|
||||
CORE_ASSERT_OK(tc, "create condvar",
|
||||
cond_create(&nready.cond));
|
||||
|
||||
count1 = count2 = count3 = count4 = 0;
|
||||
put.nput = put.nval = 0;
|
||||
nready.nready = 0;
|
||||
i = 0;
|
||||
x = 0;
|
||||
|
||||
s0 = thread_create(&p1, NULL, thread_cond_producer, &count1);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, s0);
|
||||
s1 = thread_create(&p2, NULL, thread_cond_producer, &count2);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, s1);
|
||||
s2 = thread_create(&p3, NULL, thread_cond_producer, &count3);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, s2);
|
||||
s3 = thread_create(&p4, NULL, thread_cond_producer, &count4);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, s3);
|
||||
s4 = thread_create(&c1, NULL, thread_cond_consumer, NULL);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, s4);
|
||||
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, thread_delete(p1));
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, thread_delete(p2));
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, thread_delete(p3));
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, thread_delete(p4));
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, thread_delete(c1));
|
||||
|
||||
CORE_ASSERT_OK(tc, "delete condvar",
|
||||
cond_delete(nready.cond));
|
||||
CORE_ASSERT_OK(tc, "delete ready mutex", mutex_delete(nready.mutex));
|
||||
CORE_ASSERT_OK(tc, "delete put mutex", mutex_delete(put.mutex));
|
||||
|
||||
sum = count1 + count2 + count3 + count4;
|
||||
ABTS_INT_EQUAL(tc, MAX_COUNTER, sum);
|
||||
}
|
||||
|
||||
static void test_timeoutcond(abts_case *tc, void *data)
|
||||
{
|
||||
status_t s;
|
||||
c_time_t timeout;
|
||||
c_time_t begin, end;
|
||||
int i;
|
||||
|
||||
s = mutex_create(&timeout_mutex, MUTEX_DEFAULT);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, s);
|
||||
|
||||
s = cond_create(&timeout_cond);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, s);
|
||||
|
||||
timeout = time_from_sec(1);
|
||||
|
||||
for (i = 0; i < MAX_RETRY; i++)
|
||||
{
|
||||
mutex_lock(timeout_mutex);
|
||||
|
||||
begin = time_now();
|
||||
s = cond_timedwait(timeout_cond, timeout_mutex, timeout);
|
||||
end = time_now();
|
||||
mutex_unlock(timeout_mutex);
|
||||
|
||||
if (s != CORE_OK && !STATUS_IS_TIMEUP(s))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ABTS_INT_EQUAL(tc, 1, STATUS_IS_TIMEUP(s));
|
||||
ABTS_ASSERT(tc,
|
||||
"Timer returned too late", end - begin - timeout < 100000);
|
||||
break;
|
||||
}
|
||||
ABTS_ASSERT(tc, "Too many retries", i < MAX_RETRY);
|
||||
CORE_ASSERT_OK(tc, "Unable to delete the conditional",
|
||||
cond_delete(timeout_cond));
|
||||
CORE_ASSERT_OK(tc, "Unable to delete the mutex",
|
||||
mutex_delete(timeout_mutex));
|
||||
}
|
||||
|
||||
static void test_semaphore(abts_case *tc, void *data)
|
||||
{
|
||||
thread_id t1, t2, t3, t4;
|
||||
status_t s1, s2, s3, s4;
|
||||
|
||||
s1 = semaphore_create(&semaphore, 1);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, s1);
|
||||
|
||||
i = 0;
|
||||
x = 0;
|
||||
|
||||
s1 = thread_create(&t1, NULL, thread_semaphore_function, NULL);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, s1);
|
||||
s2 = thread_create(&t2, NULL, thread_semaphore_function, NULL);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, s2);
|
||||
s3 = thread_create(&t3, NULL, thread_semaphore_function, NULL);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, s3);
|
||||
s4 = thread_create(&t4, NULL, thread_semaphore_function, NULL);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, s4);
|
||||
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, thread_delete(t1));
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, thread_delete(t2));
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, thread_delete(t3));
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, thread_delete(t4));
|
||||
|
||||
ABTS_INT_EQUAL(tc, MAX_ITER, x);
|
||||
|
||||
CORE_ASSERT_OK(tc, "delete semaphore", semaphore_delete(semaphore));
|
||||
}
|
||||
|
||||
#if HAVE_SEM_TIMEDWAIT
|
||||
static semaphore_id timeout_semaphore;
|
||||
static void test_timeoutsemaphore(abts_case *tc, void *data)
|
||||
{
|
||||
status_t s;
|
||||
c_time_t timeout;
|
||||
c_time_t begin, end;
|
||||
int i;
|
||||
|
||||
s = semaphore_create(&timeout_semaphore, 0);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, s);
|
||||
|
||||
timeout = time_from_sec(1);
|
||||
|
||||
for (i = 0; i < MAX_RETRY; i++)
|
||||
{
|
||||
begin = time_now();
|
||||
s = semaphore_timedwait(timeout_semaphore, timeout);
|
||||
end = time_now();
|
||||
|
||||
if (s != CORE_OK && !STATUS_IS_TIMEUP(s))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ABTS_INT_EQUAL(tc, 1, STATUS_IS_TIMEUP(s));
|
||||
ABTS_ASSERT(tc,
|
||||
"Timer returned too late", end - begin - timeout < 100000);
|
||||
break;
|
||||
}
|
||||
ABTS_ASSERT(tc, "Too many retries", i < MAX_RETRY);
|
||||
CORE_ASSERT_OK(tc, "Unable to delete the semaphore",
|
||||
semaphore_delete(timeout_semaphore));
|
||||
}
|
||||
#endif
|
||||
|
||||
abts_suite *testlock(abts_suite *suite)
|
||||
{
|
||||
suite = ADD_SUITE(suite)
|
||||
|
||||
abts_run_test(suite, test_mutex, NULL);
|
||||
abts_run_test(suite, test_thread_rwlock, NULL);
|
||||
abts_run_test(suite, test_cond, NULL);
|
||||
abts_run_test(suite, test_timeoutcond, NULL);
|
||||
abts_run_test(suite, test_semaphore, NULL);
|
||||
#if HAVE_SEM_TIMEDWAIT
|
||||
abts_run_test(suite, test_timeoutsemaphore, NULL);
|
||||
#endif
|
||||
|
||||
return suite;
|
||||
}
|
|
@ -0,0 +1,188 @@
|
|||
#include "core_msgq.h"
|
||||
#include "testutil.h"
|
||||
|
||||
#if 0
|
||||
static thread_id *s1;
|
||||
static thread_id *r1;
|
||||
|
||||
static void *THREAD_FUNC thread_send(void *data);
|
||||
static void *THREAD_FUNC thread_recv(void *data);
|
||||
|
||||
static void *THREAD_FUNC thread_send(void *data)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void *THREAD_FUNC thread_recv(void *data)
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
char msg[16][24] = {
|
||||
{0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18},
|
||||
{0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28},
|
||||
{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38},
|
||||
{0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48},
|
||||
{0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58},
|
||||
{0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68},
|
||||
{0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78},
|
||||
{0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88},
|
||||
{0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98},
|
||||
{0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8},
|
||||
{0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8},
|
||||
{0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8},
|
||||
{0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8},
|
||||
{0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8},
|
||||
{0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8},
|
||||
{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}
|
||||
};
|
||||
|
||||
char rmsg[16][24];
|
||||
|
||||
int msglen[16] = {3, 4, 5, 6, 7, 8, 1, 2, 11, 12, 13, 14, 15, 16, 17, 18};
|
||||
|
||||
msgq_id md;
|
||||
|
||||
static void msgq_test1(abts_case *tc, void *data)
|
||||
{
|
||||
int i, n;
|
||||
|
||||
msgq_init();
|
||||
|
||||
/* Basic test */
|
||||
md = msgq_create(5, 8, 0);
|
||||
ABTS_INT_NEQUAL(tc, 0, md);
|
||||
|
||||
n = msgq_send(md, msg[0], msglen[0]);
|
||||
ABTS_INT_EQUAL(tc, msglen[0], n);
|
||||
|
||||
n = msgq_recv(md, rmsg[0], 8);
|
||||
ABTS_INT_EQUAL(tc, msglen[0], n);
|
||||
|
||||
n = memcmp(msg[0], rmsg[0], msglen[0]);
|
||||
ABTS_INT_EQUAL(tc, 0, n);
|
||||
|
||||
msgq_delete(md);
|
||||
|
||||
/* Test with send() and recv() function up to queue size */
|
||||
md = msgq_create(5, 8, 0);
|
||||
ABTS_INT_NEQUAL(tc, 0, md);
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
n = msgq_send(md, msg[i], msglen[i]);
|
||||
ABTS_INT_EQUAL(tc, msglen[i], n);
|
||||
}
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
n = msgq_recv(md, rmsg[i], 8);
|
||||
ABTS_INT_EQUAL(tc, msglen[i], n);
|
||||
|
||||
n = memcmp(msg[i], rmsg[i], msglen[i]);
|
||||
ABTS_INT_EQUAL(tc, 0, n);
|
||||
}
|
||||
|
||||
msgq_delete(md);
|
||||
|
||||
/* Test with send() and timedrecv() function up to queue size */
|
||||
md = msgq_create(5, 8, 0);
|
||||
ABTS_INT_NEQUAL(tc, 0, md);
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
n = msgq_send(md, msg[i], msglen[i]);
|
||||
ABTS_INT_EQUAL(tc, msglen[i], n);
|
||||
}
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
n = msgq_timedrecv(md, rmsg[i], 8, 0);
|
||||
ABTS_INT_EQUAL(tc, msglen[i], n);
|
||||
|
||||
n = memcmp(msg[i], rmsg[i], msglen[i]);
|
||||
ABTS_INT_EQUAL(tc, 0, n);
|
||||
}
|
||||
|
||||
msgq_delete(md);
|
||||
}
|
||||
|
||||
static void msgq_test2(abts_case *tc, void *data)
|
||||
{
|
||||
int i, n;
|
||||
|
||||
msgq_init();
|
||||
|
||||
md = msgq_create(5, 8, MSGQ_O_NONBLOCK);
|
||||
ABTS_INT_NEQUAL(tc, 0, md);
|
||||
|
||||
/* fill up the queue */
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
n = msgq_send(md, msg[i], msglen[i]);
|
||||
ABTS_INT_EQUAL(tc, msglen[i], n);
|
||||
}
|
||||
|
||||
/* Now, there is no room to send.
|
||||
* Confirm that send() returns CORE_EGAIN */
|
||||
n = msgq_send(md, msg[0], msglen[0]);
|
||||
ABTS_INT_EQUAL(tc, CORE_EAGAIN, n);
|
||||
|
||||
/* empty queue */
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
n = msgq_recv(md, rmsg[i], 8);
|
||||
ABTS_INT_EQUAL(tc, msglen[i], n);
|
||||
|
||||
n = memcmp(msg[i], rmsg[i], msglen[i]);
|
||||
ABTS_INT_EQUAL(tc, 0, n);
|
||||
}
|
||||
|
||||
/* Now, there is no sent buffer to be read.
|
||||
* Confirm that recv() return CORE_EGAIN */
|
||||
n = msgq_recv(md, rmsg[i], 8);
|
||||
ABTS_INT_EQUAL(tc, CORE_EAGAIN, n);
|
||||
|
||||
msgq_delete(md);
|
||||
}
|
||||
|
||||
static void msgq_test3(abts_case *tc, void *data)
|
||||
{
|
||||
int i, j, n;
|
||||
|
||||
msgq_init();
|
||||
|
||||
md = msgq_create(16, 24, MSGQ_O_BLOCK);
|
||||
ABTS_INT_NEQUAL(tc, 0, md);
|
||||
|
||||
/* Repeat 10 times */
|
||||
for (j = 0; j < 10; j++)
|
||||
{
|
||||
/* Cycle repeatedly by queue depth */
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
n = msgq_send(md, msg[i], 24);
|
||||
ABTS_INT_EQUAL(tc, 24, n);
|
||||
|
||||
n = msgq_recv(md, rmsg[i], 24);
|
||||
ABTS_INT_EQUAL(tc, 24, n);
|
||||
|
||||
n = memcmp(msg[i], rmsg[i], 24);
|
||||
ABTS_INT_EQUAL(tc, 0, n);
|
||||
}
|
||||
}
|
||||
|
||||
msgq_delete(md);
|
||||
}
|
||||
|
||||
abts_suite *testmsgq(abts_suite *suite)
|
||||
{
|
||||
suite = ADD_SUITE(suite)
|
||||
|
||||
abts_run_test(suite, msgq_test1, NULL);
|
||||
abts_run_test(suite, msgq_test2, NULL);
|
||||
abts_run_test(suite, msgq_test3, NULL);
|
||||
|
||||
return suite;
|
||||
}
|
|
@ -0,0 +1,835 @@
|
|||
#define TRACE_MODULE _testnetlib
|
||||
#include "core_debug.h"
|
||||
#include "core_net.h"
|
||||
#include "testutil.h"
|
||||
|
||||
#define TEST_SERVER_PORT 5121
|
||||
#define TEST_BUFFER_SIZE 1024
|
||||
|
||||
#define TEST_MAX_NUM 4
|
||||
|
||||
#define DISABLE_FTPTEST 1
|
||||
#define DISABLE_LINKTEST 1
|
||||
|
||||
static char buffer[TEST_BUFFER_SIZE];
|
||||
static int tcp_server_started = 0;
|
||||
static int udp_server_started = 0;
|
||||
static int sctp_stream_server_started = 0;
|
||||
static int sctp_seq_server_started = 0;
|
||||
|
||||
pthread_t tserver_tid,userver_tid,streamserver_tid, seqserver_tid;
|
||||
net_sock_t *tserver_sock,*userver_sock,*streamserver_sock,*seqserver_sock;
|
||||
|
||||
static void *tcp_session_main(void *param)
|
||||
{
|
||||
int rc;
|
||||
|
||||
net_sock_t *net_sock = (net_sock_t *)param;
|
||||
while (1)
|
||||
{
|
||||
rc = net_read(net_sock, buffer, TEST_BUFFER_SIZE, 1);
|
||||
if (rc > 0)
|
||||
{
|
||||
if (!strncmp(buffer, "QUIT",4))
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Send received data */
|
||||
rc = net_send(net_sock, buffer, rc);
|
||||
}
|
||||
}
|
||||
else if (rc == 0)
|
||||
{
|
||||
/* Timeout */
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("error = %d\n", net_sock->sndrcv_errno);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
net_close(net_sock);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void start_tcp_session(net_sock_t *net_sock)
|
||||
{
|
||||
pthread_t tid;
|
||||
|
||||
pthread_create(&tid, NULL, tcp_session_main, (void *)net_sock);
|
||||
pthread_detach(tid);
|
||||
return;
|
||||
}
|
||||
|
||||
static void *tcp_server_main(void *param)
|
||||
{
|
||||
int rc;
|
||||
net_sock_t *new_sock;
|
||||
|
||||
rc = net_listen(&tserver_sock, SOCK_STREAM, IPPROTO_TCP, TEST_SERVER_PORT);
|
||||
if (rc != 0)
|
||||
{
|
||||
d_error("net_tcp_listen Error(rc = %d)\n",rc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tcp_server_started = 1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
rc = net_accept(&new_sock, tserver_sock, 1);
|
||||
if (rc >0)
|
||||
{
|
||||
/* New connection arrived. Start session */
|
||||
start_tcp_session(new_sock);
|
||||
}
|
||||
else if (rc == 0)
|
||||
{
|
||||
/* Timeout */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Error occured */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void start_tcp_server()
|
||||
{
|
||||
pthread_create(&tserver_tid, NULL, tcp_server_main, NULL);
|
||||
while (tcp_server_started == 0)
|
||||
{
|
||||
sleep(1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void stop_tcp_server()
|
||||
{
|
||||
net_close(tserver_sock);
|
||||
pthread_join(tserver_tid, NULL);
|
||||
}
|
||||
|
||||
static void *udp_server_main(void *param)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = net_listen(&userver_sock,
|
||||
SOCK_DGRAM, IPPROTO_UDP, TEST_SERVER_PORT);
|
||||
if (rc != 0)
|
||||
{
|
||||
d_error("net_udp Error(rc = %d)\n",rc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
udp_server_started = 1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
d_trace(1,"Wait for data....\n");
|
||||
rc = net_read(userver_sock, buffer, TEST_BUFFER_SIZE, 2);
|
||||
if (rc >0)
|
||||
{
|
||||
d_trace(1,"RECV %d bytes\n", rc);
|
||||
if (!strncmp(buffer, "QUIT",4))
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Send received data */
|
||||
rc = net_send(userver_sock, buffer, rc);
|
||||
d_trace(1,"SEND %d bytes\n", rc);
|
||||
if (rc == -1)
|
||||
{
|
||||
printf("error = %d\n", userver_sock->sndrcv_errno);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (rc == 0)
|
||||
{
|
||||
/* Timeout */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Error occured */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void start_udp_server()
|
||||
{
|
||||
pthread_create(&userver_tid, NULL, udp_server_main, NULL);
|
||||
while (udp_server_started == 0)
|
||||
{
|
||||
sleep(1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void stop_udp_server()
|
||||
{
|
||||
net_close(userver_sock);
|
||||
pthread_join(userver_tid, NULL);
|
||||
}
|
||||
|
||||
static void *sctp_stream_session_main(void *param)
|
||||
{
|
||||
int rc;
|
||||
|
||||
net_sock_t *net_sock = (net_sock_t *)param;
|
||||
while (1)
|
||||
{
|
||||
rc = net_read(net_sock, buffer, TEST_BUFFER_SIZE, 1);
|
||||
if (rc > 0)
|
||||
{
|
||||
if (!strncmp(buffer, "QUIT",4))
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Send received data */
|
||||
rc = net_send(net_sock, buffer, rc);
|
||||
}
|
||||
}
|
||||
else if (rc == 0)
|
||||
{
|
||||
/* Timeout */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rc != -2 && net_sock->sndrcv_errno != EAGAIN)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
net_close(net_sock);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void start_stream_sctp_session(net_sock_t *net_sock)
|
||||
{
|
||||
pthread_t tid;
|
||||
|
||||
pthread_create(&tid, NULL, sctp_stream_session_main, (void *)net_sock);
|
||||
pthread_detach(tid);
|
||||
return;
|
||||
}
|
||||
|
||||
static void *sctp_stream_server_main(void *param)
|
||||
{
|
||||
int rc;
|
||||
net_sock_t *new_sock;
|
||||
|
||||
rc = net_listen(&streamserver_sock,
|
||||
SOCK_STREAM, IPPROTO_SCTP, TEST_SERVER_PORT);
|
||||
if (rc != 0)
|
||||
{
|
||||
d_error("net_sctp_listen Error(rc = %d)\n",rc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sctp_stream_server_started = 1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
rc = net_accept(&new_sock, streamserver_sock, 1);
|
||||
if (rc >0)
|
||||
{
|
||||
/* New connection arrived. Start session */
|
||||
start_stream_sctp_session(new_sock);
|
||||
}
|
||||
else if (rc == 0)
|
||||
{
|
||||
/* Timeout */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Error occured */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void start_stream_sctp_server()
|
||||
{
|
||||
pthread_create(&streamserver_tid, NULL, sctp_stream_server_main, NULL);
|
||||
while (sctp_stream_server_started == 0)
|
||||
{
|
||||
sleep(1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void stop_stream_sctp_server()
|
||||
{
|
||||
net_close(streamserver_sock);
|
||||
pthread_join(streamserver_tid, NULL);
|
||||
}
|
||||
|
||||
static void *sctp_seq_server_main(void *param)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = net_listen(&seqserver_sock,
|
||||
SOCK_SEQPACKET, IPPROTO_SCTP, TEST_SERVER_PORT);
|
||||
if (rc != 0)
|
||||
{
|
||||
d_error("net_sctp Error(rc = %d)\n",rc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sctp_seq_server_started = 1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
d_trace(1,"Wait for data....\n");
|
||||
rc = net_read(seqserver_sock, buffer, TEST_BUFFER_SIZE, 2);
|
||||
if (rc >0)
|
||||
{
|
||||
d_trace(1,"RECV %d bytes\n", rc);
|
||||
if (!strncmp(buffer, "QUIT",4))
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Send received data */
|
||||
rc = net_send(seqserver_sock, buffer, rc);
|
||||
d_trace(1,"SEND %d bytes\n", rc);
|
||||
if (rc == -1)
|
||||
{
|
||||
printf("error = %d\n", seqserver_sock->sndrcv_errno);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (rc == 0)
|
||||
{
|
||||
/* Timeout */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Error occured */
|
||||
if (rc != -2 && seqserver_sock->sndrcv_errno != EAGAIN)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void start_seq_sctp_server()
|
||||
{
|
||||
pthread_create(&seqserver_tid, NULL, sctp_seq_server_main, NULL);
|
||||
while (sctp_seq_server_started == 0)
|
||||
{
|
||||
sleep(1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void stop_seq_sctp_server()
|
||||
{
|
||||
net_close(seqserver_sock);
|
||||
pthread_join(seqserver_tid, NULL);
|
||||
}
|
||||
|
||||
static void netlib1(abts_case *tc, void *data)
|
||||
{
|
||||
int rc = 0;
|
||||
net_sock_t *net_sock;
|
||||
char inputbuf[TEST_MAX_NUM][20];
|
||||
char outputbuf[TEST_MAX_NUM][20];
|
||||
int i;
|
||||
|
||||
/* Start TCP server */
|
||||
start_tcp_server();
|
||||
|
||||
rc = net_open(&net_sock, "127.0.0.1", 0,
|
||||
TEST_SERVER_PORT, SOCK_STREAM, IPPROTO_TCP, 0);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
for (i=0; i< TEST_MAX_NUM; i++)
|
||||
{
|
||||
sprintf(inputbuf[i],"asdf%d",i);
|
||||
rc = net_send(net_sock, inputbuf[i], strlen(inputbuf[i])+1);
|
||||
ABTS_INT_EQUAL(tc, strlen(inputbuf[i])+1, rc);
|
||||
}
|
||||
|
||||
for (i=0; i< TEST_MAX_NUM; i++)
|
||||
{
|
||||
memset(outputbuf[i], 0, sizeof(outputbuf[i]));
|
||||
rc = 0;
|
||||
while (1)
|
||||
{
|
||||
int n;
|
||||
n = net_read(net_sock, outputbuf[i], 6, 1);
|
||||
rc += n;
|
||||
if (n == 0 || n == 6)
|
||||
break;
|
||||
}
|
||||
ABTS_INT_EQUAL(tc, 6, rc);
|
||||
ABTS_INT_EQUAL(tc, 6, strlen(outputbuf[i])+1);
|
||||
ABTS_STR_EQUAL(tc, inputbuf[i], outputbuf[i]);
|
||||
}
|
||||
/* Send QUIT */
|
||||
rc = net_send(net_sock, "QUIT", 4);
|
||||
ABTS_INT_EQUAL(tc, 4, rc);
|
||||
|
||||
/* Close */
|
||||
rc = net_close(net_sock);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
|
||||
/* Stop TCP server */
|
||||
stop_tcp_server();
|
||||
}
|
||||
|
||||
static void netlib2(abts_case *tc, void *data)
|
||||
{
|
||||
int rc = 0;
|
||||
net_sock_t *net_sock[TEST_MAX_NUM];
|
||||
char inputbuf[TEST_MAX_NUM][20];
|
||||
char outputbuf[TEST_MAX_NUM][20];
|
||||
int i;
|
||||
|
||||
/* Start TCP server */
|
||||
start_tcp_server();
|
||||
|
||||
/* Connect to invalid port */
|
||||
for (i =0 ; i<TEST_MAX_NUM; i++)
|
||||
{
|
||||
net_sock[i] = NULL;
|
||||
rc = net_open(&net_sock[i], "127.0.0.1", 0,TEST_SERVER_PORT + 1,
|
||||
SOCK_STREAM, IPPROTO_TCP, 0);
|
||||
ABTS_INT_EQUAL(tc, -1, rc);
|
||||
ABTS_PTR_NULL(tc, net_sock[i]);
|
||||
}
|
||||
|
||||
/* Connect to valid port */
|
||||
for (i =0 ; i<TEST_MAX_NUM; i++)
|
||||
{
|
||||
net_sock[i] = NULL;
|
||||
rc = net_open(&net_sock[i], "127.0.0.1", 0,TEST_SERVER_PORT,
|
||||
SOCK_STREAM, IPPROTO_TCP, 0);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
ABTS_PTR_NOTNULL(tc, net_sock[i]);
|
||||
}
|
||||
|
||||
for (i=0; i< TEST_MAX_NUM; i++)
|
||||
{
|
||||
sprintf(inputbuf[i],"asdf%d",i);
|
||||
memset(outputbuf[i], 0, sizeof(outputbuf[i]));
|
||||
rc = net_send(net_sock[i], inputbuf[i], strlen(inputbuf[i])+1);
|
||||
ABTS_INT_EQUAL(tc, strlen(inputbuf[i])+1, rc);
|
||||
rc = 0;
|
||||
while (1)
|
||||
{
|
||||
int n;
|
||||
n = net_read(net_sock[i], outputbuf[i], 6, 1);
|
||||
rc += n;
|
||||
if (n == 0 || n == 6)
|
||||
break;
|
||||
}
|
||||
ABTS_INT_EQUAL(tc, 6, rc);
|
||||
ABTS_INT_EQUAL(tc, 6, strlen(outputbuf[i])+1);
|
||||
ABTS_STR_EQUAL(tc, inputbuf[i], outputbuf[i]);
|
||||
}
|
||||
|
||||
for (i = 0 ; i< TEST_MAX_NUM; i++)
|
||||
{
|
||||
rc = net_close(net_sock[i]);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
}
|
||||
|
||||
/* Stop TCP server */
|
||||
stop_tcp_server();
|
||||
}
|
||||
|
||||
static void netlib3(abts_case *tc, void *data)
|
||||
{
|
||||
int rc = 0;
|
||||
net_sock_t *net_sock[TEST_MAX_NUM];
|
||||
char inputbuf[TEST_MAX_NUM][20];
|
||||
char outputbuf[TEST_MAX_NUM][20];
|
||||
int i;
|
||||
|
||||
/* Connect to invalid port.
|
||||
* In UDP cases, net_open should be success always
|
||||
*/
|
||||
for (i =0 ; i<TEST_MAX_NUM; i++)
|
||||
{
|
||||
net_sock[i] = NULL;
|
||||
rc = net_open(&net_sock[i], "127.0.0.1", 0,TEST_SERVER_PORT + 1,
|
||||
SOCK_DGRAM, IPPROTO_UDP, 0);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
ABTS_PTR_NOTNULL(tc, net_sock[i]);
|
||||
}
|
||||
|
||||
for (i = 0 ; i< TEST_MAX_NUM; i++)
|
||||
{
|
||||
rc = net_close(net_sock[i]);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
}
|
||||
|
||||
/* Start UDP Server */
|
||||
start_udp_server();
|
||||
|
||||
for (i =0 ; i<TEST_MAX_NUM; i++)
|
||||
{
|
||||
net_sock[i] = NULL;
|
||||
rc = net_open(&net_sock[i], "127.0.0.1", 0,TEST_SERVER_PORT,
|
||||
SOCK_DGRAM, IPPROTO_UDP, 0);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
ABTS_PTR_NOTNULL(tc, net_sock[i]);
|
||||
}
|
||||
|
||||
for (i=0; i< TEST_MAX_NUM; i++)
|
||||
{
|
||||
sprintf(inputbuf[i],"asdf%d",i);
|
||||
memset(outputbuf[i], 0, sizeof(outputbuf[i]));
|
||||
rc = net_send(net_sock[i], inputbuf[i], strlen(inputbuf[i])+1);
|
||||
ABTS_INT_EQUAL(tc, strlen(inputbuf[i])+1, rc);
|
||||
rc = 0;
|
||||
while (1)
|
||||
{
|
||||
int n;
|
||||
n = net_read(net_sock[i], outputbuf[i], 6, 1);
|
||||
rc += n;
|
||||
if (n == 0 || n == 6)
|
||||
break;
|
||||
}
|
||||
ABTS_INT_EQUAL(tc, 6, rc);
|
||||
ABTS_INT_EQUAL(tc, 6, strlen(outputbuf[i])+1);
|
||||
ABTS_STR_EQUAL(tc, inputbuf[i], outputbuf[i]);
|
||||
}
|
||||
|
||||
for (i = 0 ; i< TEST_MAX_NUM; i++)
|
||||
{
|
||||
rc = net_close(net_sock[i]);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
}
|
||||
|
||||
stop_udp_server();
|
||||
}
|
||||
|
||||
static void netlib4(abts_case *tc, void *data)
|
||||
{
|
||||
int rc = 0;
|
||||
net_sock_t *net_sock[TEST_MAX_NUM];
|
||||
char inputbuf[TEST_MAX_NUM][25];
|
||||
char outputbuf[TEST_MAX_NUM][25];
|
||||
int i;
|
||||
|
||||
/* Start SCTP Server */
|
||||
start_stream_sctp_server();
|
||||
|
||||
/* Connect to invalid port */
|
||||
for (i =0 ; i<TEST_MAX_NUM; i++)
|
||||
{
|
||||
net_sock[i] = NULL;
|
||||
rc = net_open(&net_sock[i], "127.0.0.1", 0,TEST_SERVER_PORT + 1,
|
||||
SOCK_STREAM, IPPROTO_SCTP, 0);
|
||||
ABTS_INT_EQUAL(tc, -1, rc);
|
||||
ABTS_PTR_NULL(tc, net_sock[i]);
|
||||
}
|
||||
|
||||
for (i =0 ; i<TEST_MAX_NUM; i++)
|
||||
{
|
||||
net_sock[i] = NULL;
|
||||
rc = net_open(&net_sock[i], "127.0.0.1", 0, TEST_SERVER_PORT,
|
||||
SOCK_STREAM, IPPROTO_SCTP, 0);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
ABTS_PTR_NOTNULL(tc, net_sock[i]);
|
||||
}
|
||||
|
||||
for (i=0; i< TEST_MAX_NUM; i++)
|
||||
{
|
||||
sprintf(inputbuf[i],"asdf%d",i);
|
||||
memset(outputbuf[i], 0, sizeof(outputbuf[i]));
|
||||
rc = net_send(net_sock[i], inputbuf[i], strlen(inputbuf[i])+1);
|
||||
ABTS_INT_EQUAL(tc, strlen(inputbuf[i])+1, rc);
|
||||
rc = 0;
|
||||
while (1)
|
||||
{
|
||||
int n;
|
||||
n = net_read(net_sock[i], outputbuf[i], sizeof(outputbuf[1]), 1);
|
||||
if (n < 0 && net_sock[i]->sndrcv_errno == EAGAIN)
|
||||
continue;
|
||||
rc += n;
|
||||
if (n == 0 || n == 6)
|
||||
break;
|
||||
}
|
||||
ABTS_INT_EQUAL(tc, 6, rc);
|
||||
ABTS_INT_EQUAL(tc, 6, strlen(outputbuf[i])+1);
|
||||
ABTS_STR_EQUAL(tc, inputbuf[i], outputbuf[i]);
|
||||
}
|
||||
|
||||
for (i = 0 ; i< TEST_MAX_NUM; i++)
|
||||
{
|
||||
rc = net_close(net_sock[i]);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
}
|
||||
|
||||
stop_stream_sctp_server();
|
||||
}
|
||||
|
||||
static void netlib5(abts_case *tc, void *data)
|
||||
{
|
||||
int rc = 0;
|
||||
net_sock_t *net_sock[TEST_MAX_NUM];
|
||||
char inputbuf[TEST_MAX_NUM][25];
|
||||
char outputbuf[TEST_MAX_NUM][25];
|
||||
int i;
|
||||
|
||||
/* Connect to invalid port.
|
||||
* In SCTP cases, net_open should be success always
|
||||
*/
|
||||
for (i =0 ; i<TEST_MAX_NUM; i++)
|
||||
{
|
||||
net_sock[i] = NULL;
|
||||
rc = net_open(&net_sock[i], "127.0.0.1", 0, TEST_SERVER_PORT + 1,
|
||||
SOCK_SEQPACKET, IPPROTO_SCTP, 0);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
ABTS_PTR_NOTNULL(tc, net_sock[i]);
|
||||
}
|
||||
|
||||
for (i = 0 ; i< TEST_MAX_NUM; i++)
|
||||
{
|
||||
rc = net_close(net_sock[i]);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
}
|
||||
|
||||
/* Start SCTP Server */
|
||||
start_seq_sctp_server();
|
||||
|
||||
for (i =0 ; i<TEST_MAX_NUM; i++)
|
||||
{
|
||||
net_sock[i] = NULL;
|
||||
rc = net_open(&net_sock[i], "127.0.0.1", 0, TEST_SERVER_PORT,
|
||||
SOCK_SEQPACKET, IPPROTO_SCTP, 0);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
ABTS_PTR_NOTNULL(tc, net_sock[i]);
|
||||
}
|
||||
|
||||
for (i=0; i< TEST_MAX_NUM; i++)
|
||||
{
|
||||
sprintf(inputbuf[i],"asdf%d",i);
|
||||
memset(outputbuf[i], 0, sizeof(outputbuf[i]));
|
||||
rc = net_send(net_sock[i], inputbuf[i], strlen(inputbuf[i])+1);
|
||||
ABTS_INT_EQUAL(tc, strlen(inputbuf[i])+1, rc);
|
||||
rc = 0;
|
||||
while (1)
|
||||
{
|
||||
int n;
|
||||
n = net_read(net_sock[i], outputbuf[i], sizeof(outputbuf[i]), 1);
|
||||
if (n < 0 && net_sock[i]->sndrcv_errno == EAGAIN)
|
||||
continue;
|
||||
rc += n;
|
||||
if (n == 0 || n == 6)
|
||||
break;
|
||||
}
|
||||
ABTS_INT_EQUAL(tc, 6, rc);
|
||||
ABTS_INT_EQUAL(tc, 6, strlen(outputbuf[i])+1);
|
||||
ABTS_STR_EQUAL(tc, inputbuf[i], outputbuf[i]);
|
||||
}
|
||||
|
||||
for (i = 0 ; i< TEST_MAX_NUM; i++)
|
||||
{
|
||||
rc = net_close(net_sock[i]);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
}
|
||||
|
||||
stop_seq_sctp_server();
|
||||
}
|
||||
|
||||
static void netlib6(abts_case *tc, void *data)
|
||||
{
|
||||
int rc;
|
||||
net_ftp_t *ftp_session = NULL;
|
||||
char *homedir = NULL;
|
||||
int remote_size = 0;
|
||||
int local_size = 0;
|
||||
char host[] = "127.0.0.1:21";
|
||||
int i;
|
||||
|
||||
#if DISABLE_FTPTEST
|
||||
return;
|
||||
#endif
|
||||
rc = net_ftp_open(host,
|
||||
"susia",
|
||||
"ich3lie",
|
||||
0,&ftp_session);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
ABTS_PTR_NOTNULL(tc, ftp_session);
|
||||
|
||||
homedir = getenv("HOME");
|
||||
if (homedir)
|
||||
{
|
||||
char filename[100];
|
||||
struct stat statbuff;
|
||||
sprintf(filename,"%s/.bashrc",homedir);
|
||||
|
||||
if (stat(filename, &statbuff) == 0)
|
||||
{
|
||||
remote_size= statbuff.st_size;
|
||||
}
|
||||
}
|
||||
rc = net_ftp_get(ftp_session,".bashrc",NULL);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
{
|
||||
struct stat statbuff;
|
||||
|
||||
rc = stat(".bashrc", &statbuff);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
local_size= statbuff.st_size;
|
||||
ABTS_INT_EQUAL(tc, local_size, remote_size);
|
||||
}
|
||||
|
||||
for (i=0; i < 20; i++)
|
||||
{
|
||||
rc = net_ftp_get(ftp_session,".bashrc","bashrc");
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
{
|
||||
struct stat statbuff;
|
||||
rc = stat("bashrc", &statbuff);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
local_size= statbuff.st_size;
|
||||
ABTS_INT_EQUAL(tc, local_size, remote_size);
|
||||
}
|
||||
rc = net_ftp_put(ftp_session,"bashrc", NULL);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
|
||||
unlink("bashrc");
|
||||
}
|
||||
|
||||
rc = net_ftp_quit(ftp_session);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
|
||||
rc = net_ftp_close(ftp_session);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
}
|
||||
|
||||
#if LINUX == 1
|
||||
static void filter_updu(char *buf, int len)
|
||||
{
|
||||
unsigned short proto = 0x88B6;
|
||||
struct ethhdr *eth_hdr = NULL;
|
||||
|
||||
eth_hdr = (struct ethhdr *)buf;
|
||||
if (ntohs(eth_hdr->h_proto) == proto)
|
||||
{
|
||||
d_print_hex(buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
static void netlib7(abts_case *tc, void *data)
|
||||
{
|
||||
net_link_t *net_link = NULL;
|
||||
int promisc = 1;
|
||||
int rc;
|
||||
int max_count = 10;
|
||||
char buf[1024];
|
||||
|
||||
#if DISABLE_LINKTEST
|
||||
return;
|
||||
#endif
|
||||
rc = net_link_open(&net_link, "eth0", ETH_P_ALL);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
ABTS_PTR_NOTNULL(tc, net_link);
|
||||
rc = net_link_promisc(net_link, promisc);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
#if 0
|
||||
d_print("HW addr of %s : ",net_link->ifname);
|
||||
d_print_hex(net_link->hwaddr.sa_data, 6);
|
||||
#endif
|
||||
while (max_count-- > 0)
|
||||
{
|
||||
rc = net_link_read(net_link, buf, 1024, 1);
|
||||
ABTS_TRUE(tc, rc > 0);
|
||||
filter_updu(buf, rc);
|
||||
}
|
||||
rc = net_link_close(net_link);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
}
|
||||
|
||||
static int make_test_updu(char *src_addr, char *dst_addr, char *buf, int len)
|
||||
{
|
||||
unsigned short proto = 0x88B6;
|
||||
struct ethhdr *eth_hdr = NULL;
|
||||
int rc = sizeof(struct ethhdr);
|
||||
char *ptr = buf;
|
||||
|
||||
eth_hdr = (struct ethhdr *)buf;
|
||||
memcpy(eth_hdr->h_source, src_addr, 6);
|
||||
memcpy(eth_hdr->h_dest, dst_addr, 6);
|
||||
eth_hdr->h_proto = htons(proto);
|
||||
/* Fill the data */
|
||||
rc += sprintf(ptr+rc,"Hellow World");
|
||||
d_print_hex(buf, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void netlib8(abts_case *tc, void *data)
|
||||
{
|
||||
net_link_t *net_link = NULL;
|
||||
int promisc = 1;
|
||||
int rc;
|
||||
int max_count = 1;
|
||||
char buf[1024];
|
||||
#if 0
|
||||
char dst_addr[6] = {'\x00','\x00','\x00','\x11','\x22','\x33'};
|
||||
#else
|
||||
char dst_addr[6] = {'\xff','\xff','\xff','\xff','\xff','\xff'};
|
||||
#endif
|
||||
|
||||
#if DISABLE_LINKTEST
|
||||
return;
|
||||
#endif
|
||||
|
||||
rc = net_link_open(&net_link, "eth0", ETH_P_ALL);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
ABTS_PTR_NOTNULL(tc, net_link);
|
||||
rc = net_link_promisc(net_link, promisc);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
while (max_count-- > 0)
|
||||
{
|
||||
rc = make_test_updu(net_link->hwaddr.sa_data, dst_addr,buf,1024);
|
||||
|
||||
rc = net_link_write(net_link, buf, rc);
|
||||
ABTS_TRUE(tc, rc > 0);
|
||||
}
|
||||
rc = net_link_close(net_link);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
}
|
||||
#endif
|
||||
|
||||
abts_suite *testnetlib(abts_suite *suite)
|
||||
{
|
||||
suite = ADD_SUITE(suite);
|
||||
|
||||
abts_run_test(suite, netlib1, NULL);
|
||||
abts_run_test(suite, netlib2, NULL);
|
||||
abts_run_test(suite, netlib3, NULL);
|
||||
abts_run_test(suite, netlib4, NULL);
|
||||
abts_run_test(suite, netlib5, NULL);
|
||||
abts_run_test(suite, netlib6, NULL);
|
||||
#if LINUX == 1
|
||||
abts_run_test(suite, netlib7, NULL);
|
||||
abts_run_test(suite, netlib8, NULL);
|
||||
#endif
|
||||
|
||||
return suite;
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
#include "core_debug.h"
|
||||
#include "core_sha1.h"
|
||||
#include "core_sha2.h"
|
||||
#include "testutil.h"
|
||||
|
||||
static void sha1_test1(abts_case *tc, void *data)
|
||||
{
|
||||
c_uint8_t msg1[] = "abc";
|
||||
c_uint8_t msg2[] = "abcdbcdecdefdefgefghfghighij"
|
||||
"hijkijkljklmklmnlmnomnopnopq";
|
||||
|
||||
c_uint8_t digest1[] = {
|
||||
0xa9,0x99,0x3e,0x36,0x47,0x06,0x81,0x6a,
|
||||
0xba,0x3e,0x25,0x71,0x78,0x50,0xc2,0x6c,
|
||||
0x9c,0xd0,0xd8,0x9d
|
||||
};
|
||||
c_uint8_t digest2[] = {
|
||||
0x84,0x98,0x3e,0x44,0x1c,0x3b,0xd2,0x6e,
|
||||
0xba,0xae,0x4a,0xa1,0xf9,0x51,0x29,0xe5,
|
||||
0xe5,0x46,0x70,0xf1
|
||||
};
|
||||
c_uint8_t digest3[] = {
|
||||
0x34,0xaa,0x97,0x3c,0xd4,0xc4,0xda,0xa4,
|
||||
0xf6,0x1e,0xeb,0x2b,0xdb,0xad,0x27,0x31,
|
||||
0x65,0x34,0x01,0x6f,
|
||||
};
|
||||
|
||||
c_uint8_t digest[20];
|
||||
int i;
|
||||
|
||||
sha1_ctx ctx;
|
||||
|
||||
sha1_init(&ctx);
|
||||
sha1_update(&ctx, msg1, sizeof(msg1) - 1);
|
||||
sha1_final(&ctx, digest);
|
||||
ABTS_INT_EQUAL(tc, 0, memcmp(digest1, digest, 20));
|
||||
|
||||
sha1_init(&ctx);
|
||||
sha1_update(&ctx, msg2, sizeof(msg2) - 1);
|
||||
sha1_final(&ctx, digest);
|
||||
ABTS_INT_EQUAL(tc, 0, memcmp(digest2, digest, 20));
|
||||
|
||||
sha1_init(&ctx);
|
||||
for (i = 0; i < 1000000; i++)
|
||||
sha1_update(&ctx, (c_uint8_t*)"a", 1);
|
||||
sha1_final(&ctx, digest);
|
||||
ABTS_INT_EQUAL(tc, 0, memcmp(digest3, digest, 20));
|
||||
|
||||
}
|
||||
|
||||
static void sha2_test1(abts_case *tc, void *data)
|
||||
{
|
||||
char *vectors[4][3] =
|
||||
{ /* SHA-224 */
|
||||
{
|
||||
"\x23\x09\x7d\x22\x34\x05\xd8\x22\x86\x42\xa4\x77\xbd\xa2\x55\xb3\x2a\xad\xbc\xe4\xbd\xa0\xb3\xf7\xe3\x6c\x9d\xa7",
|
||||
"\x75\x38\x8b\x16\x51\x27\x76\xcc\x5d\xba\x5d\xa1\xfd\x89\x01\x50\xb0\xc6\x45\x5c\xb4\xf5\x8b\x19\x52\x52\x25\x25",
|
||||
"\x20\x79\x46\x55\x98\x0c\x91\xd8\xbb\xb4\xc1\xea\x97\x61\x8a\x4b\xf0\x3f\x42\x58\x19\x48\xb2\xee\x4e\xe7\xad\x67",
|
||||
},
|
||||
/* SHA-\x25\x6 */
|
||||
{
|
||||
"\xba\x78\x16\xbf\x8f\x01\xcf\xea\x41\x41\x40\xde\x5d\xae\x22\x23\xb0\x03\x61\xa3\x96\x17\x7a\x9c\xb4\x10\xff\x61\xf2\x00\x15\xad",
|
||||
"\x24\x8d\x6a\x61\xd2\x06\x38\xb8\xe5\xc0\x26\x93\x0c\x3e\x60\x39\xa3\x3c\xe4\x59\x64\xff\x21\x67\xf6\xec\xed\xd4\x19\xdb\x06\xc1",
|
||||
"\xcd\xc7\x6e\x5c\x99\x14\xfb\x92\x81\xa1\xc7\xe2\x84\xd7\x3e\x67\xf1\x80\x9a\x48\xa4\x97\x20\x0e\x04\x6d\x39\xcc\xc7\x11\x2c\xd0",
|
||||
},
|
||||
/* SHA-\x38\x4 */
|
||||
{
|
||||
"\xcb\x00\x75\x3f\x45\xa3\x5e\x8b\xb5\xa0\x3d\x69\x9a\xc6\x50\x07\x27\x2c\x32\xab\x0e\xde\xd1\x63\x1a\x8b\x60\x5a\x43\xff\x5b\xed"
|
||||
"\x80\x86\x07\x2b\xa1\xe7\xcc\x23\x58\xba\xec\xa1\x34\xc8\x25\xa7",
|
||||
"\x09\x33\x0c\x33\xf7\x11\x47\xe8\x3d\x19\x2f\xc7\x82\xcd\x1b\x47\x53\x11\x1b\x17\x3b\x3b\x05\xd2\x2f\xa0\x80\x86\xe3\xb0\xf7\x12"
|
||||
"\xfc\xc7\xc7\x1a\x55\x7e\x2d\xb9\x66\xc3\xe9\xfa\x91\x74\x60\x39",
|
||||
"\x9d\x0e\x18\x09\x71\x64\x74\xcb\x08\x6e\x83\x4e\x31\x0a\x4a\x1c\xed\x14\x9e\x9c\x00\xf2\x48\x52\x79\x72\xce\xc5\x70\x4c\x2a\x5b"
|
||||
"\x07\xb8\xb3\xdc\x38\xec\xc4\xeb\xae\x97\xdd\xd8\x7f\x3d\x89\x85",
|
||||
},
|
||||
/* SHA-\x51\x2 */
|
||||
{
|
||||
"\xdd\xaf\x35\xa1\x93\x61\x7a\xba\xcc\x41\x73\x49\xae\x20\x41\x31\x12\xe6\xfa\x4e\x89\xa9\x7e\xa2\x0a\x9e\xee\xe6\x4b\x55\xd3\x9a"
|
||||
"\x21\x92\x99\x2a\x27\x4f\xc1\xa8\x36\xba\x3c\x23\xa3\xfe\xeb\xbd\x45\x4d\x44\x23\x64\x3c\xe8\x0e\x2a\x9a\xc9\x4f\xa5\x4c\xa4\x9f",
|
||||
"\x8e\x95\x9b\x75\xda\xe3\x13\xda\x8c\xf4\xf7\x28\x14\xfc\x14\x3f\x8f\x77\x79\xc6\xeb\x9f\x7f\xa1\x72\x99\xae\xad\xb6\x88\x90\x18"
|
||||
"\x50\x1d\x28\x9e\x49\x00\xf7\xe4\x33\x1b\x99\xde\xc4\xb5\x43\x3a\xc7\xd3\x29\xee\xb6\xdd\x26\x54\x5e\x96\xe5\x5b\x87\x4b\xe9\x09",
|
||||
"\xe7\x18\x48\x3d\x0c\xe7\x69\x64\x4e\x2e\x42\xc7\xbc\x15\xb4\x63\x8e\x1f\x98\xb1\x3b\x20\x44\x28\x56\x32\xa8\x03\xaf\xa9\x73\xeb"
|
||||
"\xde\x0f\xf2\x44\x87\x7e\xa6\x0a\x4c\xb0\x43\x2c\xe5\x77\xc3\x1b\xeb\x00\x9c\x5c\x2c\x49\xaa\x2e\x4e\xad\xb2\x17\xad\x8c\xc0\x9b"
|
||||
}
|
||||
};
|
||||
|
||||
char message1[] = "abc";
|
||||
char message2a[] = "abcdbcdecdefdefgefghfghighijhi"
|
||||
"jkijkljklmklmnlmnomnopnopq";
|
||||
char message2b[] = "abcdefghbcdefghicdefghijdefghijkefghij"
|
||||
"klfghijklmghijklmnhijklmnoijklmnopjklm"
|
||||
"nopqklmnopqrlmnopqrsmnopqrstnopqrstu";
|
||||
unsigned char *message3;
|
||||
unsigned int message3_len = 1000000;
|
||||
unsigned char digest[SHA512_DIGEST_SIZE];
|
||||
int rc;
|
||||
|
||||
message3 = malloc(message3_len);
|
||||
if (message3 == NULL) {
|
||||
fprintf(stderr, "Can't allocate memory\n");
|
||||
return;
|
||||
}
|
||||
memset(message3, 'a', message3_len);
|
||||
|
||||
/* SHA-2 FIPS 180-2 Validation tests.
|
||||
* SHA-224 Test vector */
|
||||
|
||||
sha224((c_uint8_t *)message1, strlen((char *) message1), digest);
|
||||
rc = memcmp(vectors[0][0], digest, SHA224_DIGEST_SIZE);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
sha224((c_uint8_t *)message2a, strlen((char *) message2a), digest);
|
||||
rc = memcmp(vectors[0][1], digest, SHA224_DIGEST_SIZE);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
sha224((c_uint8_t *)message3, message3_len, digest);
|
||||
rc = memcmp(vectors[0][2], digest, SHA224_DIGEST_SIZE);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
|
||||
/* SHA-256 Test vector */
|
||||
|
||||
sha256((c_uint8_t *)message1, strlen((char *) message1), digest);
|
||||
rc = memcmp(vectors[1][0], digest, SHA256_DIGEST_SIZE);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
sha256((c_uint8_t *)message2a, strlen((char *) message2a), digest);
|
||||
rc = memcmp(vectors[1][1], digest, SHA256_DIGEST_SIZE);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
sha256((c_uint8_t *)message3, message3_len, digest);
|
||||
rc = memcmp(vectors[1][2], digest, SHA256_DIGEST_SIZE);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
|
||||
/* SHA-384 Test vector */
|
||||
|
||||
sha384((c_uint8_t *)message1, strlen((char *) message1), digest);
|
||||
rc = memcmp(vectors[2][0], digest, SHA384_DIGEST_SIZE);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
sha384((c_uint8_t *)message2b, strlen((char *) message2b), digest);
|
||||
rc = memcmp(vectors[2][1], digest, SHA384_DIGEST_SIZE);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
sha384((c_uint8_t *)message3, message3_len, digest);
|
||||
rc = memcmp(vectors[2][2], digest, SHA384_DIGEST_SIZE);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
|
||||
/* SHA-512 Test vector */
|
||||
sha512((c_uint8_t *)message1, strlen((char *) message1), digest);
|
||||
rc = memcmp(vectors[3][0], digest, SHA512_DIGEST_SIZE);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
sha512((c_uint8_t *)message2b, strlen((char *) message2b), digest);
|
||||
rc = memcmp(vectors[3][1], digest, SHA512_DIGEST_SIZE);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
sha512((c_uint8_t *)message3, message3_len, digest);
|
||||
rc = memcmp(vectors[3][2], digest, SHA512_DIGEST_SIZE);
|
||||
ABTS_INT_EQUAL(tc, 0, rc);
|
||||
|
||||
free(message3);
|
||||
}
|
||||
|
||||
abts_suite *testsha2(abts_suite *suite)
|
||||
{
|
||||
suite = ADD_SUITE(suite);
|
||||
|
||||
abts_run_test(suite, sha1_test1, NULL);
|
||||
abts_run_test(suite, sha2_test1, NULL);
|
||||
|
||||
return suite;
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "core_time.h"
|
||||
#include "testutil.h"
|
||||
|
||||
#define SLEEP_INTERVAL 3
|
||||
|
||||
static void sleep_one(abts_case *tc, void *data)
|
||||
{
|
||||
time_t pretime = time(NULL);
|
||||
time_t posttime;
|
||||
time_t timediff;
|
||||
|
||||
core_sleep(time_from_sec(SLEEP_INTERVAL));
|
||||
posttime = time(NULL);
|
||||
|
||||
/* normalize the timediff. We should have slept for SLEEP_INTERVAL, so
|
||||
* we should just subtract that out.
|
||||
*/
|
||||
timediff = posttime - pretime - SLEEP_INTERVAL;
|
||||
ABTS_TRUE(tc, timediff >= 0);
|
||||
ABTS_TRUE(tc, timediff <= 1);
|
||||
}
|
||||
|
||||
abts_suite *testsleep(abts_suite *suite)
|
||||
{
|
||||
suite = ADD_SUITE(suite)
|
||||
|
||||
abts_run_test(suite, sleep_one, NULL);
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
#include "core_mutex.h"
|
||||
#include "core_thread.h"
|
||||
#include "testutil.h"
|
||||
|
||||
static mutex_id lock;
|
||||
static int x = 0;
|
||||
|
||||
static thread_id t1;
|
||||
static thread_id t2;
|
||||
static thread_id t3;
|
||||
static thread_id t4;
|
||||
|
||||
static void *THREAD_FUNC thread_func1(void *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 10000; i++)
|
||||
{
|
||||
mutex_lock(lock);
|
||||
x++;
|
||||
mutex_unlock(lock);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void init_thread(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
|
||||
rv = mutex_create(&lock, MUTEX_DEFAULT);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
}
|
||||
|
||||
static void create_threads(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
|
||||
rv = thread_create(&t1, NULL, thread_func1, NULL);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
rv = thread_create(&t2, NULL, thread_func1, NULL);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
rv = thread_create(&t3, NULL, thread_func1, NULL);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
rv = thread_create(&t4, NULL, thread_func1, NULL);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
}
|
||||
|
||||
static void delete_threads(abts_case *tc, void *data)
|
||||
{
|
||||
status_t s;
|
||||
|
||||
s = thread_delete(t1);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, s);
|
||||
s = thread_delete(t2);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, s);
|
||||
s = thread_delete(t3);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, s);
|
||||
s = thread_delete(t4);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, s);
|
||||
}
|
||||
|
||||
static void check_locks(abts_case *tc, void *data)
|
||||
{
|
||||
ABTS_INT_EQUAL(tc, 40000, x);
|
||||
}
|
||||
|
||||
abts_suite *testthread(abts_suite *suite)
|
||||
{
|
||||
suite = ADD_SUITE(suite)
|
||||
|
||||
abts_run_test(suite, init_thread, NULL);
|
||||
abts_run_test(suite, create_threads, NULL);
|
||||
abts_run_test(suite, delete_threads, NULL);
|
||||
abts_run_test(suite, check_locks, NULL);
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
|
@ -0,0 +1,289 @@
|
|||
#include "core_time.h"
|
||||
#include "testutil.h"
|
||||
|
||||
#define STR_SIZE 45
|
||||
|
||||
/* The time value is used throughout the tests, so just make this a global.
|
||||
* Also, we need a single value that we can test for the positive tests, so
|
||||
* I chose the number below, it corresponds to:
|
||||
* 2002-08-14 12:05:36.186711 -25200 [257 Sat].
|
||||
* Which happens to be when I wrote the new tests.
|
||||
*/
|
||||
static c_time_t now = C_INT64_C(1032030336186711);
|
||||
|
||||
static void test_now(abts_case *tc, void *data)
|
||||
{
|
||||
c_time_t timediff;
|
||||
c_time_t current;
|
||||
time_t os_now;
|
||||
|
||||
current = time_now();
|
||||
time(&os_now);
|
||||
|
||||
timediff = os_now - (current / USEC_PER_SEC);
|
||||
/* Even though these are called so close together, there is the chance
|
||||
* that the time will be slightly off, so accept anything between -1 and
|
||||
* 1 second.
|
||||
*/
|
||||
ABTS_ASSERT(tc, "core_time and OS time do not agree",
|
||||
(timediff > -2) && (timediff < 2));
|
||||
}
|
||||
|
||||
static void test_gmtstr(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
time_exp_t xt;
|
||||
char str[STR_SIZE+1];
|
||||
|
||||
rv = time_exp_gmt(&xt, now);
|
||||
if (rv == CORE_ENOTIMPL)
|
||||
{
|
||||
ABTS_NOT_IMPL(tc, "time_exp_gmt");
|
||||
}
|
||||
ABTS_TRUE(tc, rv == CORE_OK);
|
||||
sprintf(str, "%04d-%02d-%02d %02d:%02d:%02d.%06d %+05d [%d %s]%s",
|
||||
xt.tm_year + 1900,
|
||||
xt.tm_mon,
|
||||
xt.tm_mday,
|
||||
xt.tm_hour,
|
||||
xt.tm_min,
|
||||
xt.tm_sec,
|
||||
xt.tm_usec,
|
||||
xt.tm_gmtoff,
|
||||
xt.tm_yday + 1,
|
||||
day_snames[xt.tm_wday],
|
||||
(xt.tm_isdst ? " DST" : ""));
|
||||
ABTS_STR_EQUAL(tc, "2002-08-14 19:05:36.186711 +0000 [257 Sat]", str);
|
||||
}
|
||||
|
||||
static void test_exp_lt(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
time_exp_t xt;
|
||||
time_t posix_secs = (time_t)time_sec(now);
|
||||
struct tm *posix_exp = localtime(&posix_secs);
|
||||
|
||||
rv = time_exp_lt(&xt, now);
|
||||
if (rv == CORE_ENOTIMPL)
|
||||
{
|
||||
ABTS_NOT_IMPL(tc, "time_exp_lt");
|
||||
}
|
||||
ABTS_TRUE(tc, rv == CORE_OK);
|
||||
|
||||
#define CHK_FIELD(f) \
|
||||
ABTS_ASSERT(tc, "Mismatch in " #f, posix_exp->f == xt.f)
|
||||
|
||||
CHK_FIELD(tm_sec);
|
||||
CHK_FIELD(tm_min);
|
||||
CHK_FIELD(tm_hour);
|
||||
CHK_FIELD(tm_mday);
|
||||
CHK_FIELD(tm_mon);
|
||||
CHK_FIELD(tm_year);
|
||||
CHK_FIELD(tm_wday);
|
||||
CHK_FIELD(tm_yday);
|
||||
CHK_FIELD(tm_isdst);
|
||||
#undef CHK_FIELD
|
||||
}
|
||||
|
||||
static void test_exp_get_gmt(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
time_exp_t xt;
|
||||
c_time_t imp;
|
||||
c_int64_t hr_off_64;
|
||||
|
||||
rv = time_exp_gmt(&xt, now);
|
||||
ABTS_TRUE(tc, rv == CORE_OK);
|
||||
rv = time_exp_get(&imp, &xt);
|
||||
if (rv == CORE_ENOTIMPL)
|
||||
{
|
||||
ABTS_NOT_IMPL(tc, "time_exp_get");
|
||||
}
|
||||
ABTS_TRUE(tc, rv == CORE_OK);
|
||||
hr_off_64 = (c_int64_t) xt.tm_gmtoff * USEC_PER_SEC;
|
||||
ABTS_TRUE(tc, now + hr_off_64 == imp);
|
||||
}
|
||||
|
||||
static void test_exp_get_lt(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
time_exp_t xt;
|
||||
c_time_t imp;
|
||||
c_int64_t hr_off_64;
|
||||
|
||||
rv = time_exp_lt(&xt, now);
|
||||
ABTS_TRUE(tc, rv == CORE_OK);
|
||||
rv = time_exp_get(&imp, &xt);
|
||||
if (rv == CORE_ENOTIMPL)
|
||||
{
|
||||
ABTS_NOT_IMPL(tc, "time_exp_get");
|
||||
}
|
||||
ABTS_TRUE(tc, rv == CORE_OK);
|
||||
hr_off_64 = (c_int64_t) xt.tm_gmtoff * USEC_PER_SEC;
|
||||
ABTS_TRUE(tc, now + hr_off_64 == imp);
|
||||
}
|
||||
|
||||
static void test_imp_gmt(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
time_exp_t xt;
|
||||
c_time_t imp;
|
||||
|
||||
rv = time_exp_gmt(&xt, now);
|
||||
ABTS_TRUE(tc, rv == CORE_OK);
|
||||
rv = time_exp_gmt_get(&imp, &xt);
|
||||
if (rv == CORE_ENOTIMPL)
|
||||
{
|
||||
ABTS_NOT_IMPL(tc, "time_exp_gmt_get");
|
||||
}
|
||||
ABTS_TRUE(tc, rv == CORE_OK);
|
||||
ABTS_TRUE(tc, now == imp);
|
||||
}
|
||||
|
||||
static void test_rfcstr(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
char str[STR_SIZE];
|
||||
|
||||
rv = rfc822_date(str, now);
|
||||
if (rv == CORE_ENOTIMPL)
|
||||
{
|
||||
ABTS_NOT_IMPL(tc, "rfc822_date");
|
||||
}
|
||||
ABTS_TRUE(tc, rv == CORE_OK);
|
||||
ABTS_STR_EQUAL(tc, "Sat, 14 Sep 2002 19:05:36 GMT", str);
|
||||
}
|
||||
|
||||
static void test_ctime(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
char core_str[STR_SIZE];
|
||||
char libc_str[STR_SIZE];
|
||||
c_time_t now_sec = time_sec(now);
|
||||
time_t posix_sec = (time_t) now_sec;
|
||||
|
||||
rv = core_ctime(core_str, now);
|
||||
if (rv == CORE_ENOTIMPL)
|
||||
{
|
||||
ABTS_NOT_IMPL(tc, "core_ctime");
|
||||
}
|
||||
ABTS_TRUE(tc, rv == CORE_OK);
|
||||
strcpy(libc_str, ctime(&posix_sec));
|
||||
*strchr(libc_str, '\n') = '\0';
|
||||
|
||||
ABTS_STR_EQUAL(tc, libc_str, core_str);
|
||||
}
|
||||
|
||||
static void test_strftime(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
time_exp_t xt;
|
||||
char str[STR_SIZE+1];
|
||||
size_t sz;
|
||||
|
||||
rv = time_exp_gmt(&xt, now);
|
||||
rv = core_strftime(str, &sz, STR_SIZE, "%R %A %d %B %Y", &xt);
|
||||
if (rv == CORE_ENOTIMPL)
|
||||
{
|
||||
ABTS_NOT_IMPL(tc, "core_strftime");
|
||||
}
|
||||
ABTS_TRUE(tc, rv == CORE_OK);
|
||||
ABTS_STR_EQUAL(tc, "19:05 Saturday 14 September 2002", str);
|
||||
}
|
||||
|
||||
static void test_strftimesmall(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
time_exp_t xt;
|
||||
char str[STR_SIZE];
|
||||
size_t sz;
|
||||
|
||||
rv = time_exp_gmt(&xt, now);
|
||||
rv = core_strftime(str, &sz, STR_SIZE, "%T", &xt);
|
||||
if (rv == CORE_ENOTIMPL)
|
||||
{
|
||||
ABTS_NOT_IMPL(tc, "core_strftime");
|
||||
}
|
||||
ABTS_TRUE(tc, rv == CORE_OK);
|
||||
ABTS_STR_EQUAL(tc, "19:05:36", str);
|
||||
}
|
||||
|
||||
static void test_exp_tz(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
time_exp_t xt;
|
||||
c_int32_t hr_off = -5 * 3600; /* 5 hours in seconds */
|
||||
|
||||
rv = time_exp_tz(&xt, now, hr_off);
|
||||
if (rv == CORE_ENOTIMPL)
|
||||
{
|
||||
ABTS_NOT_IMPL(tc, "time_exp_tz");
|
||||
}
|
||||
ABTS_TRUE(tc, rv == CORE_OK);
|
||||
ABTS_TRUE(tc, (xt.tm_usec == 186711) &&
|
||||
(xt.tm_sec == 36) &&
|
||||
(xt.tm_min == 5) &&
|
||||
(xt.tm_hour == 14) &&
|
||||
(xt.tm_mday == 14) &&
|
||||
(xt.tm_mon == 8) &&
|
||||
(xt.tm_year == 102) &&
|
||||
(xt.tm_wday == 6) &&
|
||||
(xt.tm_yday == 256));
|
||||
}
|
||||
|
||||
static void test_strftimeoffset(abts_case *tc, void *data)
|
||||
{
|
||||
status_t rv;
|
||||
time_exp_t xt;
|
||||
char str[STR_SIZE];
|
||||
size_t sz;
|
||||
c_int32_t hr_off = -5 * 3600; /* 5 hours in seconds */
|
||||
|
||||
time_exp_tz(&xt, now, hr_off);
|
||||
rv = core_strftime(str, &sz, STR_SIZE, "%T", &xt);
|
||||
if (rv == CORE_ENOTIMPL)
|
||||
{
|
||||
ABTS_NOT_IMPL(tc, "core_strftime");
|
||||
}
|
||||
ABTS_TRUE(tc, rv == CORE_OK);
|
||||
}
|
||||
|
||||
/* 0.9.4 and earlier rejected valid dates in 2038 */
|
||||
static void test_2038(abts_case *tc, void *data)
|
||||
{
|
||||
time_exp_t xt;
|
||||
c_time_t t;
|
||||
|
||||
/* 2038-01-19T03:14:07.000000Z */
|
||||
xt.tm_year = 138;
|
||||
xt.tm_mon = 0;
|
||||
xt.tm_mday = 19;
|
||||
xt.tm_hour = 3;
|
||||
xt.tm_min = 14;
|
||||
xt.tm_sec = 7;
|
||||
|
||||
CORE_ASSERT_OK(tc, "explode January 19th, 2038",
|
||||
time_exp_get(&t, &xt));
|
||||
}
|
||||
|
||||
abts_suite *testtime(abts_suite *suite)
|
||||
{
|
||||
suite = ADD_SUITE(suite)
|
||||
|
||||
abts_run_test(suite, test_now, NULL);
|
||||
abts_run_test(suite, test_gmtstr, NULL);
|
||||
abts_run_test(suite, test_exp_lt, NULL);
|
||||
abts_run_test(suite, test_exp_get_gmt, NULL);
|
||||
abts_run_test(suite, test_exp_get_lt, NULL);
|
||||
abts_run_test(suite, test_imp_gmt, NULL);
|
||||
abts_run_test(suite, test_rfcstr, NULL);
|
||||
abts_run_test(suite, test_ctime, NULL);
|
||||
abts_run_test(suite, test_strftime, NULL);
|
||||
abts_run_test(suite, test_strftimesmall, NULL);
|
||||
abts_run_test(suite, test_exp_tz, NULL);
|
||||
abts_run_test(suite, test_strftimeoffset, NULL);
|
||||
abts_run_test(suite, test_2038, NULL);
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
|
@ -0,0 +1,381 @@
|
|||
#include "core_time.h"
|
||||
#include "core_timer.h"
|
||||
#include "core_param.h"
|
||||
#include "testutil.h"
|
||||
|
||||
#define TEST_TIMER_NUM 200
|
||||
#define TEST_TIMER_PRECISION 20 /* 2ms precision */
|
||||
#define TEST_DURATION 400
|
||||
|
||||
c_uint8_t expire_check[TEST_DURATION/TEST_TIMER_PRECISION];
|
||||
|
||||
typedef struct _test_timer_eliment
|
||||
{
|
||||
c_uint8_t type;
|
||||
c_uint32_t duration;
|
||||
} test_timer_eliment;
|
||||
|
||||
|
||||
test_timer_eliment timer_eliment[] ={
|
||||
{TIMER_TYPE_ONE_SHOT, 500},
|
||||
{TIMER_TYPE_ONE_SHOT, 50},
|
||||
{TIMER_TYPE_ONE_SHOT, 200},
|
||||
{TIMER_TYPE_ONE_SHOT, 90},
|
||||
{TIMER_TYPE_ONE_SHOT, 800}
|
||||
};
|
||||
|
||||
|
||||
void test_expire_func_1(c_uintptr_t arg1, c_uintptr_t arg2, c_uintptr_t arg3)
|
||||
{
|
||||
c_uint32_t index = arg2;
|
||||
|
||||
expire_check[index] = TRUE;
|
||||
}
|
||||
|
||||
void test_expire_func_2(c_uintptr_t arg1, c_uintptr_t arg2, c_uintptr_t arg3)
|
||||
{
|
||||
c_uint32_t index = arg2;
|
||||
|
||||
expire_check[index]++;
|
||||
}
|
||||
|
||||
static void test_now(abts_case *tc, void *data)
|
||||
{
|
||||
c_time_t timediff;
|
||||
c_time_t current;
|
||||
time_t os_now;
|
||||
|
||||
current = time_now();
|
||||
time(&os_now);
|
||||
|
||||
timediff = os_now - (current / USEC_PER_SEC);
|
||||
/* Even though these are called so close together, there is the chance
|
||||
* that the time will be slightly off, so accept anything between -1 and
|
||||
* 1 second.
|
||||
*/
|
||||
ABTS_ASSERT(tc, "core_time and OS time do not agree",
|
||||
(timediff > -2) && (timediff < 2));
|
||||
}
|
||||
|
||||
|
||||
/* basic timer Test */
|
||||
static void timer_test_1(abts_case *tc, void *data)
|
||||
{
|
||||
|
||||
int n = 0;
|
||||
tm_block_id id_array[100];
|
||||
tm_block_id id;
|
||||
tm_service_t tm_service;
|
||||
|
||||
memset((char*)id_array, 0x00, sizeof(tm_service));
|
||||
memset(expire_check, 0x00, sizeof(expire_check));
|
||||
|
||||
/* init tm_service */
|
||||
tm_service_init(&tm_service);
|
||||
|
||||
for(n = 0; n < sizeof(timer_eliment) / sizeof(test_timer_eliment); n++)
|
||||
{
|
||||
id_array[n] = tm_create(&tm_service);
|
||||
tm_set(id_array[n], TIMER_TYPE_ONE_SHOT, timer_eliment[n].duration,
|
||||
test_expire_func_1, (c_uintptr_t)id_array[n], n, 0);
|
||||
}
|
||||
|
||||
|
||||
for(n = 0; n < sizeof(timer_eliment) / sizeof(test_timer_eliment); n++)
|
||||
{
|
||||
tm_start(id_array[n]);
|
||||
}
|
||||
|
||||
id = (tm_block_id)list_first(&tm_service.idle_list);
|
||||
ABTS_INT_EQUAL(tc, id, 0);
|
||||
|
||||
id = (tm_block_id)list_first(&tm_service.active_list);
|
||||
ABTS_INT_NEQUAL(tc, id, 0);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[1]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[3]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[2]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[0]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[4]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, 0);
|
||||
|
||||
core_sleep(70000);
|
||||
tm_execute_tm_service(&tm_service);
|
||||
|
||||
id = (tm_block_id)list_first(&tm_service.idle_list);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[1]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, 0);
|
||||
|
||||
id = (tm_block_id)list_first(&tm_service.active_list);
|
||||
ABTS_INT_NEQUAL(tc, id, 0);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[3]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[2]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[0]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[4]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, 0);
|
||||
|
||||
ABTS_INT_EQUAL(tc, expire_check[0], 0);
|
||||
ABTS_INT_EQUAL(tc, expire_check[1], 1);
|
||||
ABTS_INT_EQUAL(tc, expire_check[2], 0);
|
||||
ABTS_INT_EQUAL(tc, expire_check[3], 0);
|
||||
ABTS_INT_EQUAL(tc, expire_check[4], 0);
|
||||
|
||||
|
||||
core_sleep(40000);
|
||||
tm_execute_tm_service(&tm_service);
|
||||
|
||||
id = (tm_block_id)list_first(&tm_service.idle_list);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[1]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[3]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, 0);
|
||||
|
||||
id = (tm_block_id)list_first(&tm_service.active_list);
|
||||
ABTS_INT_NEQUAL(tc, id, 0);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[2]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[0]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[4]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, 0);
|
||||
|
||||
ABTS_INT_EQUAL(tc, expire_check[0], 0);
|
||||
ABTS_INT_EQUAL(tc, expire_check[1], 1);
|
||||
ABTS_INT_EQUAL(tc, expire_check[2], 0);
|
||||
ABTS_INT_EQUAL(tc, expire_check[3], 1);
|
||||
ABTS_INT_EQUAL(tc, expire_check[4], 0);
|
||||
|
||||
|
||||
core_sleep(140000);
|
||||
tm_execute_tm_service(&tm_service);
|
||||
|
||||
id = (tm_block_id)list_first(&tm_service.idle_list);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[1]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[3]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[2]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, 0);
|
||||
|
||||
id = (tm_block_id)list_first(&tm_service.active_list);
|
||||
ABTS_INT_NEQUAL(tc, id, 0);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[0]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[4]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, 0);
|
||||
|
||||
ABTS_INT_EQUAL(tc, expire_check[0], 0);
|
||||
ABTS_INT_EQUAL(tc, expire_check[1], 1);
|
||||
ABTS_INT_EQUAL(tc, expire_check[2], 1);
|
||||
ABTS_INT_EQUAL(tc, expire_check[3], 1);
|
||||
ABTS_INT_EQUAL(tc, expire_check[4], 0);
|
||||
|
||||
|
||||
core_sleep(300000);
|
||||
tm_execute_tm_service(&tm_service);
|
||||
|
||||
id = (tm_block_id)list_first(&tm_service.idle_list);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[1]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[3]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[2]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[0]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, 0);
|
||||
|
||||
id = (tm_block_id)list_first(&tm_service.active_list);
|
||||
ABTS_INT_NEQUAL(tc, id, 0);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[4]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, 0);
|
||||
|
||||
ABTS_INT_EQUAL(tc, expire_check[0], 1);
|
||||
ABTS_INT_EQUAL(tc, expire_check[1], 1);
|
||||
ABTS_INT_EQUAL(tc, expire_check[2], 1);
|
||||
ABTS_INT_EQUAL(tc, expire_check[3], 1);
|
||||
ABTS_INT_EQUAL(tc, expire_check[4], 0);
|
||||
|
||||
|
||||
core_sleep(300000);
|
||||
tm_execute_tm_service(&tm_service);
|
||||
|
||||
id = (tm_block_id)list_first(&tm_service.idle_list);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[1]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[3]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[2]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[0]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, id_array[4]); if(tc->failed) return;
|
||||
id = (tm_block_id)list_next(id);
|
||||
ABTS_INT_EQUAL(tc, id, 0);
|
||||
|
||||
id = (tm_block_id)list_first(&tm_service.active_list);
|
||||
ABTS_INT_EQUAL(tc, id, 0);
|
||||
|
||||
ABTS_INT_EQUAL(tc, expire_check[0], 1);
|
||||
ABTS_INT_EQUAL(tc, expire_check[1], 1);
|
||||
ABTS_INT_EQUAL(tc, expire_check[2], 1);
|
||||
ABTS_INT_EQUAL(tc, expire_check[3], 1);
|
||||
ABTS_INT_EQUAL(tc, expire_check[4], 1);
|
||||
|
||||
for( n = 0; n < sizeof(timer_eliment) / sizeof(test_timer_eliment); n++)
|
||||
{
|
||||
tm_delete(id_array[n]);
|
||||
}
|
||||
|
||||
ABTS_INT_EQUAL(tc, tm_pool_avail(), MAX_NUM_OF_TIMER);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void timer_test_2(abts_case *tc, void *data)
|
||||
{
|
||||
|
||||
int n = 0;
|
||||
tm_block_id id_array[TEST_TIMER_NUM];
|
||||
tm_service_t tm_service;
|
||||
int duration;
|
||||
int tm_num[TEST_DURATION/TEST_TIMER_PRECISION];
|
||||
int tm_idx;
|
||||
|
||||
memset((char*)id_array, 0x00, sizeof(tm_service));
|
||||
memset(expire_check, 0x00, sizeof(expire_check));
|
||||
memset(tm_num, 0x00, sizeof(tm_num));
|
||||
|
||||
/* init tm_service */
|
||||
tm_service_init(&tm_service);
|
||||
|
||||
for(n = 0; n < TEST_TIMER_NUM; n++)
|
||||
{
|
||||
duration = (rand() % (TEST_DURATION/TEST_TIMER_PRECISION))
|
||||
* TEST_TIMER_PRECISION;
|
||||
|
||||
tm_idx = duration/TEST_TIMER_PRECISION;
|
||||
tm_num[tm_idx]++;
|
||||
duration += (TEST_TIMER_PRECISION >> 1);
|
||||
|
||||
id_array[n] = tm_create(&tm_service);
|
||||
tm_set(id_array[n], TIMER_TYPE_ONE_SHOT, duration,
|
||||
test_expire_func_2, (c_uintptr_t)id_array[n], tm_idx, 0);
|
||||
}
|
||||
|
||||
for(n = 0; n < TEST_TIMER_NUM; n++)
|
||||
{
|
||||
tm_start(id_array[n]);
|
||||
}
|
||||
|
||||
for(n = 0; n < TEST_DURATION/TEST_TIMER_PRECISION; n++)
|
||||
{
|
||||
core_sleep(TEST_TIMER_PRECISION * 1000);
|
||||
tm_execute_tm_service(&tm_service);
|
||||
ABTS_INT_EQUAL(tc, tm_num[n], expire_check[n]);
|
||||
}
|
||||
|
||||
for(n = 0; n < TEST_TIMER_NUM; n++)
|
||||
{
|
||||
tm_delete(id_array[n]);
|
||||
}
|
||||
|
||||
ABTS_INT_EQUAL(tc, tm_pool_avail(), MAX_NUM_OF_TIMER);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void timer_test_3(abts_case *tc, void *data)
|
||||
{
|
||||
c_uint32_t n = 0;
|
||||
tm_block_id id_array[TEST_TIMER_NUM];
|
||||
tm_service_t tm_service;
|
||||
int id_duration[TEST_TIMER_NUM];
|
||||
int duration;
|
||||
int tm_num[TEST_DURATION/TEST_TIMER_PRECISION];
|
||||
int tm_idx, tm_check_id;
|
||||
|
||||
memset((char*)id_array, 0x00, sizeof(tm_service));
|
||||
memset(expire_check, 0x00, sizeof(expire_check));
|
||||
memset(tm_num, 0x00, sizeof(tm_num));
|
||||
|
||||
/* init tm_service */
|
||||
tm_service_init(&tm_service);
|
||||
|
||||
for(n = 0; n < TEST_TIMER_NUM; n++)
|
||||
{
|
||||
duration = (rand() % (TEST_DURATION/TEST_TIMER_PRECISION))
|
||||
* TEST_TIMER_PRECISION;
|
||||
tm_idx = duration/TEST_TIMER_PRECISION;
|
||||
tm_num[tm_idx]++;
|
||||
id_duration[n] = duration;
|
||||
duration += (TEST_TIMER_PRECISION >> 1);
|
||||
|
||||
|
||||
id_array[n] = tm_create(&tm_service);
|
||||
tm_set(id_array[n], TIMER_TYPE_ONE_SHOT, duration,
|
||||
test_expire_func_2, (c_uint32_t)id_array[n], tm_idx, 0);
|
||||
}
|
||||
|
||||
for(n = 0; n < TEST_TIMER_NUM; n++)
|
||||
{
|
||||
tm_start(id_array[n]);
|
||||
}
|
||||
|
||||
for(n = 0; n < TEST_TIMER_NUM / 10; n++)
|
||||
{
|
||||
tm_idx = n*10 + rand()%10;
|
||||
tm_check_id = id_duration[tm_idx]/TEST_TIMER_PRECISION;
|
||||
tm_num[tm_check_id]--;
|
||||
tm_delete(id_array[tm_idx]);
|
||||
id_array[tm_idx] = 0;
|
||||
}
|
||||
|
||||
for(n = 0; n < TEST_DURATION/TEST_TIMER_PRECISION; n++)
|
||||
{
|
||||
core_sleep(TEST_TIMER_PRECISION * 1000);
|
||||
tm_execute_tm_service(&tm_service);
|
||||
ABTS_INT_EQUAL(tc, tm_num[n], expire_check[n]);
|
||||
}
|
||||
|
||||
for(n = 0; n < TEST_TIMER_NUM; n++)
|
||||
{
|
||||
if(id_array[n] != 0)
|
||||
{
|
||||
tm_delete(id_array[n]);
|
||||
}
|
||||
}
|
||||
|
||||
ABTS_INT_EQUAL(tc, tm_pool_avail(), MAX_NUM_OF_TIMER);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
abts_suite *testtimer(abts_suite *suite)
|
||||
{
|
||||
suite = ADD_SUITE(suite)
|
||||
|
||||
abts_run_test(suite, test_now, NULL);
|
||||
abts_run_test(suite, timer_test_1, NULL);
|
||||
abts_run_test(suite, timer_test_2, NULL);
|
||||
abts_run_test(suite, timer_test_3, NULL);
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
|
@ -0,0 +1,446 @@
|
|||
#include "core_tlv.h"
|
||||
#include "core_net.h"
|
||||
#include "testutil.h"
|
||||
|
||||
#define TLV_0_LEN 10
|
||||
#define TLV_1_LEN 20
|
||||
#define TLV_2_LEN 100
|
||||
#define TLV_3_LEN 200
|
||||
#define TLV_4_LEN 2
|
||||
#define TLV_5_LEN 2000
|
||||
#define TLV_VALUE_ARRAY_SIZE 3000
|
||||
|
||||
#define EMBED_TLV_TYPE 20
|
||||
|
||||
typedef struct _test_tlv_eliment
|
||||
{
|
||||
c_uint8_t type;
|
||||
c_uint32_t length;
|
||||
c_uint8_t *value;
|
||||
c_uint8_t val_char;
|
||||
} test_tlv_eliment;
|
||||
|
||||
c_uint8_t test_tlv_value[TLV_VALUE_ARRAY_SIZE];
|
||||
|
||||
test_tlv_eliment tlv_eliment[] ={
|
||||
{1, TLV_0_LEN, 0, 0x0a},
|
||||
{100, TLV_1_LEN, 0, 0x0b},
|
||||
{255, TLV_2_LEN, 0, 0x0c},
|
||||
{254, TLV_3_LEN, 0, 0x0d},
|
||||
{5, TLV_4_LEN, 0, 0x0e},
|
||||
{30, TLV_5_LEN, 0, 0x0f}
|
||||
};
|
||||
|
||||
void tlv_test_set_tlv_value(void)
|
||||
{
|
||||
c_uint32_t inc = 0;
|
||||
|
||||
/* set test tlv value */
|
||||
tlv_eliment[0].value = test_tlv_value;
|
||||
memset(tlv_eliment[0].value, tlv_eliment[0].val_char, tlv_eliment[0].length);
|
||||
inc += tlv_eliment[0].length;
|
||||
|
||||
tlv_eliment[1].value = test_tlv_value + inc;
|
||||
memset(tlv_eliment[1].value, tlv_eliment[1].val_char, tlv_eliment[1].length);
|
||||
inc += tlv_eliment[1].length;
|
||||
|
||||
tlv_eliment[2].value = test_tlv_value + inc;
|
||||
memset(tlv_eliment[2].value, tlv_eliment[2].val_char, tlv_eliment[2].length);
|
||||
inc += tlv_eliment[2].length;
|
||||
|
||||
tlv_eliment[3].value = test_tlv_value + inc;
|
||||
memset(tlv_eliment[3].value, tlv_eliment[3].val_char, tlv_eliment[3].length);
|
||||
inc += tlv_eliment[3].length;
|
||||
|
||||
tlv_eliment[4].value = test_tlv_value + inc;
|
||||
memset(tlv_eliment[4].value, tlv_eliment[4].val_char, tlv_eliment[4].length);
|
||||
inc += tlv_eliment[4].length;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void tlv_test_check_embed_tlv_test(abts_case *tc, tlv_t *root_tlv)
|
||||
{
|
||||
c_uint32_t m;
|
||||
c_uint32_t parent_block_len;
|
||||
tlv_t *pTlv;
|
||||
tlv_t *embed_tlv = NULL, *parent_tlv = NULL, *parsed_tlv = NULL;
|
||||
c_uint8_t parent_block[4000];
|
||||
c_uint8_t *pos = NULL;
|
||||
int result;
|
||||
|
||||
memset(parent_block, 0x00, sizeof(parent_block));
|
||||
|
||||
parent_block_len = tlv_render(root_tlv, parent_block,
|
||||
sizeof(parent_block), TLV_MODE_WMX_R4_R6);
|
||||
|
||||
ABTS_INT_EQUAL(tc, parent_block_len, 332);
|
||||
|
||||
tlv_free_all(root_tlv);
|
||||
ABTS_INT_EQUAL(tc, tlv_pool_avail(), NUM_OF_TLV_NODE);
|
||||
|
||||
|
||||
|
||||
pos = parent_block;
|
||||
|
||||
ABTS_INT_EQUAL(tc, *(pos++), tlv_eliment[0].type >> 8);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), tlv_eliment[0].type & 0xFF);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), tlv_eliment[0].length >> 8);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), tlv_eliment[0].length & 0xFF);
|
||||
|
||||
for(m = 0; m < tlv_eliment[0].length; m++)
|
||||
{
|
||||
ABTS_INT_EQUAL(tc, *(pos++), tlv_eliment[0].val_char);
|
||||
}
|
||||
|
||||
ABTS_INT_EQUAL(tc, *(pos++), EMBED_TLV_TYPE >> 8);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), EMBED_TLV_TYPE & 0xFF);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), (308 >> 8));
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 308 & 0xFF);
|
||||
|
||||
/* embedded tlv_t */
|
||||
ABTS_INT_EQUAL(tc, *(pos++), tlv_eliment[2].type >> 8);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), tlv_eliment[2].type & 0xFF);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), tlv_eliment[2].length >> 8);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), tlv_eliment[2].length & 0xFF);
|
||||
for(m = 0; m < tlv_eliment[2].length; m++)
|
||||
{
|
||||
ABTS_INT_EQUAL(tc, *(pos++), tlv_eliment[2].val_char);
|
||||
}
|
||||
|
||||
|
||||
ABTS_INT_EQUAL(tc, *(pos++), tlv_eliment[3].type >> 8);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), tlv_eliment[3].type & 0xFF);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), tlv_eliment[3].length >> 8);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), tlv_eliment[3].length & 0xFF);
|
||||
for(m = 0; m < tlv_eliment[3].length; m++)
|
||||
{
|
||||
ABTS_INT_EQUAL(tc, *(pos++), tlv_eliment[3].val_char);
|
||||
}
|
||||
|
||||
|
||||
ABTS_INT_EQUAL(tc, *(pos++), tlv_eliment[4].type >> 8);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), tlv_eliment[4].type & 0xFF);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), tlv_eliment[4].length >> 8);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), tlv_eliment[4].length & 0xFF);
|
||||
|
||||
for(m = 0; m < tlv_eliment[4].length; m++)
|
||||
{
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0x0e);
|
||||
}
|
||||
|
||||
|
||||
|
||||
parsed_tlv = tlv_parse_tlv_block(parent_block_len,
|
||||
parent_block, TLV_MODE_WMX_R4_R6);
|
||||
ABTS_PTR_NOTNULL(tc, parsed_tlv);
|
||||
|
||||
|
||||
pTlv = parsed_tlv;
|
||||
|
||||
ABTS_INT_EQUAL(tc, pTlv->type, tlv_eliment[0].type);
|
||||
|
||||
ABTS_INT_EQUAL(tc, pTlv->length, tlv_eliment[0].length);
|
||||
result = memcmp(pTlv->value, tlv_eliment[0].value, tlv_eliment[0].length);
|
||||
ABTS_INT_EQUAL(tc, result, 0);
|
||||
pTlv = pTlv->next;
|
||||
|
||||
ABTS_INT_EQUAL(tc, pTlv->type, 20);
|
||||
ABTS_INT_EQUAL(tc, pTlv->length, 308);
|
||||
pTlv = pTlv->next;
|
||||
|
||||
ABTS_INT_EQUAL(tc, pTlv->type, tlv_eliment[4].type);
|
||||
ABTS_INT_EQUAL(tc, pTlv->length, tlv_eliment[4].length);
|
||||
result = memcmp(pTlv->value, tlv_eliment[4].value, tlv_eliment[4].length);
|
||||
ABTS_INT_EQUAL(tc, result, 0);
|
||||
pTlv = pTlv->next;
|
||||
|
||||
|
||||
ABTS_PTR_NULL(tc, pTlv);
|
||||
|
||||
parent_tlv = tlv_find(parsed_tlv,20);
|
||||
ABTS_PTR_NOTNULL(tc, parent_tlv);
|
||||
|
||||
tlv_parse_embedded_tlv_block(parent_tlv, TLV_MODE_WMX_R4_R6);
|
||||
embed_tlv = parent_tlv->embedded;
|
||||
ABTS_PTR_NOTNULL(tc, embed_tlv);
|
||||
|
||||
|
||||
ABTS_INT_EQUAL(tc, embed_tlv->type, tlv_eliment[2].type);
|
||||
ABTS_INT_EQUAL(tc, embed_tlv->length, tlv_eliment[2].length);
|
||||
for(m = 0; m < tlv_eliment[2].length; m++)
|
||||
{
|
||||
ABTS_INT_EQUAL(tc, *((c_uint8_t*)(embed_tlv->value+m)),
|
||||
tlv_eliment[2].val_char);
|
||||
}
|
||||
embed_tlv = embed_tlv->next;
|
||||
|
||||
ABTS_INT_EQUAL(tc, embed_tlv->type, tlv_eliment[3].type);
|
||||
ABTS_INT_EQUAL(tc, embed_tlv->length, tlv_eliment[3].length);
|
||||
for(m = 0; m < tlv_eliment[3].length; m++)
|
||||
{
|
||||
ABTS_INT_EQUAL(tc, *((c_uint8_t*)(embed_tlv->value+m)),
|
||||
tlv_eliment[3].val_char);
|
||||
}
|
||||
embed_tlv = embed_tlv->next;
|
||||
|
||||
ABTS_PTR_NULL(tc, embed_tlv);
|
||||
|
||||
embed_tlv = tlv_find(parsed_tlv,254);
|
||||
ABTS_PTR_NOTNULL(tc, embed_tlv);
|
||||
|
||||
embed_tlv = tlv_find(parsed_tlv,253);
|
||||
ABTS_PTR_NULL(tc, embed_tlv);
|
||||
|
||||
tlv_free_all(parsed_tlv);
|
||||
ABTS_INT_EQUAL(tc, tlv_pool_avail(), NUM_OF_TLV_NODE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* basic encoding/decoding/finding Test */
|
||||
static void tlv_test_1(abts_case *tc, void *data)
|
||||
{
|
||||
c_uint32_t idx, m, parent_block_len;
|
||||
tlv_t *root_tlv = NULL, *parsed_tlv = NULL, *pTlv;
|
||||
c_uint8_t parent_block[4000];
|
||||
c_uint8_t *pos = NULL;
|
||||
|
||||
tlv_test_set_tlv_value();
|
||||
|
||||
/* tlv encoding for test */
|
||||
root_tlv = tlv_add(NULL,tlv_eliment[0].type,
|
||||
tlv_eliment[0].length, tlv_eliment[0].value);
|
||||
|
||||
for(idx = 1; idx < 4; idx++)
|
||||
{
|
||||
tlv_add(root_tlv,tlv_eliment[idx].type,
|
||||
tlv_eliment[idx].length, tlv_eliment[idx].value);
|
||||
}
|
||||
|
||||
memset(parent_block, 0x00, sizeof(parent_block));
|
||||
parent_block_len = tlv_render(root_tlv, parent_block,
|
||||
sizeof(parent_block), TLV_MODE_WMX_R4_R6);
|
||||
|
||||
ABTS_INT_EQUAL(tc, parent_block_len, 346);
|
||||
|
||||
tlv_free_all(root_tlv);
|
||||
ABTS_INT_EQUAL(tc, tlv_pool_avail(), NUM_OF_TLV_NODE);
|
||||
|
||||
pos = parent_block;
|
||||
|
||||
for(idx = 0; idx < 4; idx++)
|
||||
{
|
||||
|
||||
ABTS_INT_EQUAL(tc, *(pos++), (tlv_eliment[idx].type >> 8));
|
||||
ABTS_INT_EQUAL(tc, *(pos++), tlv_eliment[idx].type & 0xFF);
|
||||
|
||||
|
||||
ABTS_INT_EQUAL(tc, *(pos++), (tlv_eliment[idx].length >> 8));
|
||||
ABTS_INT_EQUAL(tc, *(pos++), tlv_eliment[idx].length & 0xFF);
|
||||
|
||||
for(m = 0; m < tlv_eliment[idx].length; m++)
|
||||
{
|
||||
ABTS_INT_EQUAL(tc, *(pos++), tlv_eliment[idx].val_char);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
parsed_tlv = tlv_parse_tlv_block(parent_block_len,parent_block,
|
||||
TLV_MODE_WMX_R4_R6);
|
||||
ABTS_PTR_NOTNULL(tc, parsed_tlv);
|
||||
|
||||
pTlv = parsed_tlv;
|
||||
|
||||
idx = 0;
|
||||
while(pTlv)
|
||||
{
|
||||
int result;
|
||||
ABTS_INT_EQUAL(tc, pTlv->type, tlv_eliment[idx].type);
|
||||
ABTS_INT_EQUAL(tc, pTlv->length, tlv_eliment[idx].length);
|
||||
|
||||
result = memcmp(pTlv->value, tlv_eliment[idx].value, tlv_eliment[idx].length);
|
||||
ABTS_INT_EQUAL(tc, result, 0);
|
||||
|
||||
pTlv = pTlv->next;
|
||||
idx++;
|
||||
}
|
||||
|
||||
ABTS_INT_EQUAL(tc, idx, 4);
|
||||
|
||||
pTlv = tlv_find(parsed_tlv, 255);
|
||||
ABTS_PTR_NOTNULL(tc, pTlv);
|
||||
|
||||
pTlv = tlv_find(parsed_tlv, 253);
|
||||
ABTS_PTR_NULL(tc, pTlv);
|
||||
|
||||
tlv_free_all(parsed_tlv);
|
||||
ABTS_INT_EQUAL(tc, tlv_pool_avail(), NUM_OF_TLV_NODE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* embedded tlv_t test : first, make embedded tlv block for embeded tlv
|
||||
and then make whole tlv block using embedded tlv block previously made*/
|
||||
static void tlv_test_2(abts_case *tc, void *data)
|
||||
{
|
||||
c_uint32_t embed_block_len;
|
||||
tlv_t *root_tlv = NULL;
|
||||
tlv_t *embed_tlv = NULL;
|
||||
c_uint8_t embed_block[1000];;
|
||||
|
||||
tlv_test_set_tlv_value();
|
||||
|
||||
/* Tlv Encoding for embeded tlv_t */
|
||||
embed_tlv = tlv_add(NULL, tlv_eliment[2].type,
|
||||
tlv_eliment[2].length, tlv_eliment[2].value);
|
||||
tlv_add(embed_tlv,tlv_eliment[3].type,
|
||||
tlv_eliment[3].length, tlv_eliment[3].value);
|
||||
|
||||
embed_block_len = tlv_render(embed_tlv, embed_block,
|
||||
sizeof(embed_block), TLV_MODE_WMX_R4_R6);
|
||||
ABTS_INT_EQUAL(tc, embed_block_len, 308);
|
||||
|
||||
tlv_free_all(embed_tlv);
|
||||
ABTS_INT_EQUAL(tc, tlv_pool_avail(), NUM_OF_TLV_NODE);
|
||||
|
||||
root_tlv = tlv_add(NULL,tlv_eliment[0].type,
|
||||
tlv_eliment[0].length, tlv_eliment[0].value);
|
||||
|
||||
tlv_add(root_tlv, EMBED_TLV_TYPE, embed_block_len, embed_block);
|
||||
tlv_add(root_tlv,tlv_eliment[4].type,
|
||||
tlv_eliment[4].length, tlv_eliment[4].value);
|
||||
|
||||
tlv_test_check_embed_tlv_test(tc, root_tlv);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* embedded tlv_t test : make parent and embedded tlv and then tlv_render
|
||||
functions makes whole tlv block. the value member of each tlv must
|
||||
point to vaild address at the time using tlv_rendering function */
|
||||
static void tlv_test_3(abts_case *tc, void *data)
|
||||
{
|
||||
tlv_t *root_tlv = NULL, *parent_tlv = NULL;
|
||||
|
||||
tlv_test_set_tlv_value();
|
||||
|
||||
/* Tlv Encoding for embeded tlv_t */
|
||||
root_tlv = tlv_add(NULL,tlv_eliment[0].type,
|
||||
tlv_eliment[0].length, tlv_eliment[0].value);
|
||||
parent_tlv= tlv_add(root_tlv, EMBED_TLV_TYPE, 0, NULL);
|
||||
tlv_add(root_tlv,tlv_eliment[4].type,
|
||||
tlv_eliment[4].length, tlv_eliment[4].value);
|
||||
|
||||
tlv_embed(parent_tlv,tlv_eliment[2].type,
|
||||
tlv_eliment[2].length, tlv_eliment[2].value);
|
||||
tlv_embed(parent_tlv,tlv_eliment[3].type,
|
||||
tlv_eliment[3].length, tlv_eliment[3].value);
|
||||
|
||||
tlv_test_check_embed_tlv_test(tc, root_tlv);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* embedded tlv_t test : make parent and embedded tlv and then tlv_render
|
||||
functions makes whole tlv block. The value member of each tlv is copied
|
||||
to the buff of the root tlv_t, so the allocated resource for the value
|
||||
member of each tlv can be deallocated after executing tlv_add or tlv embed
|
||||
function*/
|
||||
static void tlv_test_4(abts_case *tc, void *data)
|
||||
{
|
||||
tlv_t *root_tlv = NULL, *parent_tlv = NULL;
|
||||
c_uint8_t tlv_buff[2000];
|
||||
|
||||
tlv_test_set_tlv_value();
|
||||
|
||||
root_tlv = tlv_create_buff_enabled_tlv(tlv_buff, sizeof(tlv_buff),
|
||||
tlv_eliment[0].type,tlv_eliment[0].length, tlv_eliment[0].value);
|
||||
parent_tlv = tlv_add(root_tlv, 20, 0, NULL);
|
||||
tlv_add(root_tlv,tlv_eliment[4].type,
|
||||
tlv_eliment[4].length, tlv_eliment[4].value);
|
||||
|
||||
tlv_embed(parent_tlv,tlv_eliment[2].type,
|
||||
tlv_eliment[2].length, tlv_eliment[2].value);
|
||||
tlv_embed(parent_tlv,tlv_eliment[3].type,
|
||||
tlv_eliment[3].length, tlv_eliment[3].value);
|
||||
|
||||
memset(tlv_eliment[2].value, 0x00, tlv_eliment[2].length);
|
||||
memset(tlv_eliment[3].value, 0xf0, tlv_eliment[3].length);
|
||||
|
||||
tlv_test_check_embed_tlv_test(tc, root_tlv);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* endian check test */
|
||||
static void tlv_test_5(abts_case *tc, void *data)
|
||||
{
|
||||
c_uint32_t parent_block_len;
|
||||
tlv_t *root_tlv = NULL, *parsed_tlv = NULL, *p_tlv;
|
||||
c_uint8_t parent_block[4000];
|
||||
c_uint8_t *pos = NULL;
|
||||
c_uint16_t c_16 = 0x1122;
|
||||
c_uint32_t c_32 = 0x11223344;
|
||||
|
||||
/* tlv encoding for test */
|
||||
c_16 = htons(c_16);
|
||||
root_tlv = tlv_add(NULL,10, 2, (c_uint8_t*)&c_16);
|
||||
c_32 = htonl(c_32);
|
||||
tlv_add(root_tlv, 20, 4, (c_uint8_t*)&c_32);
|
||||
|
||||
memset(parent_block, 0x00, sizeof(parent_block));
|
||||
parent_block_len = tlv_render(root_tlv, parent_block,
|
||||
sizeof(parent_block), TLV_MODE_WMX_R4_R6);
|
||||
|
||||
tlv_free_all(root_tlv);
|
||||
ABTS_INT_EQUAL(tc, tlv_pool_avail(), NUM_OF_TLV_NODE);
|
||||
|
||||
pos = parent_block;
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0);
|
||||
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 10);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 2);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0x11);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0x22);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 20);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 4);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0x11);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0x22);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0x33);
|
||||
ABTS_INT_EQUAL(tc, *(pos++), 0x44);
|
||||
|
||||
p_tlv = parsed_tlv = tlv_parse_tlv_block(parent_block_len,parent_block,
|
||||
TLV_MODE_WMX_R4_R6);
|
||||
ABTS_INT_EQUAL(tc, tlv_value_16(p_tlv), 0x1122);
|
||||
p_tlv = parsed_tlv->next;
|
||||
ABTS_INT_EQUAL(tc, tlv_value_32(p_tlv), 0x11223344);
|
||||
|
||||
tlv_free_all(parsed_tlv);
|
||||
ABTS_INT_EQUAL(tc, tlv_pool_avail(), NUM_OF_TLV_NODE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
abts_suite *testtlv(abts_suite *suite)
|
||||
{
|
||||
suite = ADD_SUITE(suite)
|
||||
|
||||
abts_run_test(suite, tlv_test_1, NULL);
|
||||
abts_run_test(suite, tlv_test_2, NULL);
|
||||
abts_run_test(suite, tlv_test_3, NULL);
|
||||
abts_run_test(suite, tlv_test_4, NULL);
|
||||
abts_run_test(suite, tlv_test_5, NULL);
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "abts.h"
|
||||
#include "testutil.h"
|
||||
|
||||
void core_assert_ok(abts_case* tc, const char* context, status_t rv,
|
||||
int lineno)
|
||||
{
|
||||
if (rv == CORE_ENOTIMPL)
|
||||
{
|
||||
abts_not_impl(tc, context, lineno);
|
||||
} else if (rv != CORE_OK)
|
||||
{
|
||||
char buf[STRING_MAX], ebuf[128];
|
||||
sprintf(buf, "%s (%d): %s\n", context, rv,
|
||||
core_strerror(rv, ebuf, sizeof ebuf));
|
||||
abts_fail(tc, buf, lineno);
|
||||
}
|
||||
}
|
||||
|
||||
void test_initialize(void)
|
||||
{
|
||||
core_initialize();
|
||||
atexit(core_terminate);
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "core_general.h"
|
||||
#include "abts.h"
|
||||
|
||||
#ifndef __APR_TEST_UTIL__
|
||||
#define __APR_TEST_UTIL__
|
||||
|
||||
/* XXX: FIXME - these all should become much more utilitarian
|
||||
* and part of core, itself
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef BINPATH
|
||||
#define TESTBINPATH APR_STRINGIFY(BINPATH) "/"
|
||||
#else
|
||||
#define TESTBINPATH ""
|
||||
#endif
|
||||
#else
|
||||
#define TESTBINPATH "./"
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#define EXTENSION ".exe"
|
||||
#elif NETWARE
|
||||
#define EXTENSION ".nlm"
|
||||
#else
|
||||
#define EXTENSION
|
||||
#endif
|
||||
|
||||
#define STRING_MAX 8096
|
||||
|
||||
/* Some simple functions to make the test apps easier to write and
|
||||
* a bit more consistent...
|
||||
*/
|
||||
|
||||
/* Assert that RV is an CORE_OK value; else fail giving strerror
|
||||
* for RV and CONTEXT message. */
|
||||
void core_assert_ok(abts_case* tc, const char *context,
|
||||
status_t rv, int lineno);
|
||||
#define CORE_ASSERT_OK(tc, ctxt, rv) \
|
||||
core_assert_ok(tc, ctxt, rv, __LINE__)
|
||||
|
||||
void test_initialize(void);
|
||||
|
||||
abts_suite *testds(abts_suite *suite);
|
||||
abts_suite *testfsm(abts_suite *suite);
|
||||
abts_suite *testtlv(abts_suite *suite);
|
||||
abts_suite *testaes(abts_suite *suite);
|
||||
abts_suite *testsha2(abts_suite *suite);
|
||||
abts_suite *testnetlib(abts_suite *suite);
|
||||
abts_suite *testtime(abts_suite *suite);
|
||||
abts_suite *testtimer(abts_suite *suite);
|
||||
abts_suite *testthread(abts_suite *suite);
|
||||
abts_suite *testlock(abts_suite *suite);
|
||||
abts_suite *testfile(abts_suite *suite);
|
||||
abts_suite *testfilecopy(abts_suite *suite);
|
||||
abts_suite *testdir(abts_suite *suite);
|
||||
abts_suite *testmsgq(abts_suite *suite);
|
||||
abts_suite *testsleep(abts_suite *suite);
|
||||
|
||||
#endif /* CORE_TEST_INCLUDES */
|
|
@ -0,0 +1,18 @@
|
|||
## Process this file with automake to produce Makefile.in.
|
||||
|
||||
noinst_LTLIBRARIES = liblogger.la
|
||||
|
||||
liblogger_la_SOURCES = logger.h
|
||||
|
||||
nodist_liblogger_la_SOURCES = logger.c
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/lib/core/include
|
||||
|
||||
AM_CFLAGS = \
|
||||
-Wall -Werror
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
MOSTLYCLEANFILES = core *.stackdump
|
||||
|
||||
EXTRA_DIST = .libs $(noinst_LTLIBRARIES)
|
|
@ -0,0 +1,223 @@
|
|||
#include "logger.h"
|
||||
|
||||
#include "core_general.h"
|
||||
#include "core_debug.h"
|
||||
#include "core_param.h"
|
||||
#include "core_file.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define MAX_LOG_FILE_SIZE (6*16*1024) /* 96 KB */
|
||||
#define MAX_BACKUP_LOG_FILE_NUM 19 /* 96 KB x 19 */
|
||||
#define FILE_CHECK_CYCLE 15
|
||||
|
||||
static char g_buffer[1024];
|
||||
static char g_path[MAX_FILENAME_SIZE] = "wemania.log";
|
||||
static file_t *g_file = NULL;
|
||||
|
||||
static int request_stop = 0;
|
||||
|
||||
status_t log_file_backup()
|
||||
{
|
||||
status_t rv;
|
||||
char fn[MAX_FILENAME_SIZE], nfn[MAX_FILENAME_SIZE];
|
||||
file_t *tmpf = NULL;
|
||||
int i, j;
|
||||
|
||||
file_close(g_file);
|
||||
|
||||
for (i = 0; ; i++)
|
||||
{
|
||||
sprintf(fn, "%s.%d", g_path, i);
|
||||
|
||||
rv = file_open(&tmpf, fn, FILE_READ, 0);
|
||||
if (rv != CORE_OK)
|
||||
break;
|
||||
|
||||
file_close(tmpf);
|
||||
}
|
||||
|
||||
for (j = i - 1; j >= 0; j--)
|
||||
{
|
||||
sprintf(fn, "%s.%d", g_path, j);
|
||||
sprintf(nfn, "%s.%d", g_path, j + 1);
|
||||
|
||||
if (j + 1 > MAX_BACKUP_LOG_FILE_NUM)
|
||||
{
|
||||
rv = file_remove(fn);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
fprintf(stderr, "Can't remove '%s'\n", fn);
|
||||
return CORE_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = file_rename(fn, nfn);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
fprintf(stderr, "Can't rename '%s' to '%s'\n", fn, nfn);
|
||||
return CORE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sprintf(fn, "%s", g_path);
|
||||
sprintf(nfn, "%s.0", g_path);
|
||||
|
||||
rv = file_rename(fn, nfn);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
fprintf(stderr, "Can't rename '%s' to '%s'\n", fn, nfn);
|
||||
return CORE_ERROR;
|
||||
}
|
||||
|
||||
rv = file_open(&g_file, g_path,
|
||||
FILE_CREATE | FILE_WRITE| FILE_APPEND,
|
||||
FILE_UREAD | FILE_UWRITE | FILE_GREAD);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
fprintf(stderr, "Cannot open log file '%s'", g_path);
|
||||
return CORE_ERROR;
|
||||
}
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
int logger_start(const char *path)
|
||||
{
|
||||
status_t rv;
|
||||
int ret, count = 0;
|
||||
size_t nbytes;
|
||||
ssize_t r;
|
||||
file_info_t finfo;
|
||||
int us;
|
||||
fd_set readfd;
|
||||
struct timeval timer_val;
|
||||
struct sockaddr_un svaddr;
|
||||
|
||||
/* If path is given, use it */
|
||||
if (path)
|
||||
strcpy(g_path, path);
|
||||
|
||||
us = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
if (us < 0)
|
||||
{
|
||||
fprintf(stderr, "socket() failed. (%d:%s)\n",
|
||||
errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
svaddr.sun_family = AF_UNIX;
|
||||
strcpy(svaddr.sun_path, D_LOGD_IPC_PATH);
|
||||
|
||||
ret = bind(us, (struct sockaddr *)&svaddr, sizeof(svaddr));
|
||||
if (ret != 0)
|
||||
{
|
||||
if (errno == EADDRINUSE)
|
||||
{
|
||||
ret = unlink(D_LOGD_IPC_PATH);
|
||||
if (ret != 0)
|
||||
{
|
||||
fprintf(stderr, "unlink() failed. (%d:%s)\n",
|
||||
errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
ret = bind(us, (struct sockaddr *)&svaddr, sizeof(svaddr));
|
||||
if (ret != 0)
|
||||
{
|
||||
fprintf(stderr, "bind() failed 2. (%d:%s)\n",
|
||||
errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "bind() failed. (%d:%s)\n",
|
||||
errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
rv = file_open(&g_file, g_path,
|
||||
FILE_CREATE | FILE_WRITE| FILE_APPEND,
|
||||
FILE_UREAD | FILE_UWRITE | FILE_GREAD);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
fprintf(stderr, "Cannot open log file '%s'\n", g_path);
|
||||
close(us);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
while (!request_stop)
|
||||
{
|
||||
timer_val.tv_sec = 0;
|
||||
timer_val.tv_usec = 50000;
|
||||
FD_ZERO(&readfd);
|
||||
FD_SET(us, &readfd);
|
||||
|
||||
r = select (us+1, &readfd, NULL, NULL, &timer_val);
|
||||
if (r == -1)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
break;
|
||||
fprintf(stderr, "select() error(%d: %s)",
|
||||
errno, strerror(errno));
|
||||
}
|
||||
|
||||
if (r == 0)
|
||||
continue;
|
||||
|
||||
if (FD_ISSET(us, &readfd))
|
||||
{
|
||||
r = read(us, g_buffer, sizeof(g_buffer));
|
||||
|
||||
if (r < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
break;
|
||||
fprintf(stderr, "read() failed. (%d:%s)\n",
|
||||
errno, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (r == 0)
|
||||
continue;
|
||||
|
||||
nbytes = r;
|
||||
rv = file_write(g_file, g_buffer, &nbytes);
|
||||
if (rv != CORE_OK || r != nbytes)
|
||||
{
|
||||
fprintf(stderr, "Cannot write %ld bytes to log file (%ld written)\n",
|
||||
(long)r, (long)nbytes);
|
||||
}
|
||||
|
||||
if (count % FILE_CHECK_CYCLE == 0)
|
||||
{
|
||||
file_info_get(&finfo, FILE_INFO_SIZE, g_file);
|
||||
if (finfo.size > MAX_LOG_FILE_SIZE)
|
||||
{
|
||||
log_file_backup();
|
||||
}
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
file_close(g_file);
|
||||
|
||||
close(us);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void logger_stop()
|
||||
{
|
||||
request_stop = 1;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef __LOGGER_H__
|
||||
#define __LOGGER_H__
|
||||
|
||||
#include "core.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
CORE_DECLARE(int) logger_start(const char *path);
|
||||
CORE_DECLARE(void) logger_stop();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* !__cplusplus */
|
||||
|
||||
#endif /* !__LOGGER_H__ */
|
|
@ -0,0 +1,250 @@
|
|||
/**
|
||||
* @file main.c
|
||||
*/
|
||||
|
||||
/* Core library */
|
||||
#include "core.h"
|
||||
#include "core_general.h"
|
||||
#define TRACE_MODULE _main_
|
||||
#include "core_debug.h"
|
||||
#include "core_cond.h"
|
||||
#include "core_thread.h"
|
||||
#include "core_signal.h"
|
||||
#include "core_net.h"
|
||||
|
||||
#include "logger.h"
|
||||
#include "symtbl.h"
|
||||
|
||||
/* Server */
|
||||
#include "cellwire.h"
|
||||
|
||||
thread_id thr_sm;
|
||||
#define THREAD_SM_STACK_SIZE
|
||||
#define THREAD_SM_PRIORITY
|
||||
extern void *THREAD_FUNC sm_main(void *data);
|
||||
|
||||
thread_id thr_dp;
|
||||
#define THREAD_DP_STACK_SIZE
|
||||
#define THREAD_DP_PRIORITY
|
||||
extern void *THREAD_FUNC dp_main(void *data);
|
||||
|
||||
thread_id thr_test;
|
||||
|
||||
char *config_path = NULL;
|
||||
extern char g_compile_time[];
|
||||
|
||||
static void show_version()
|
||||
{
|
||||
printf("CellWire daemon v%s - %s\n",
|
||||
PACKAGE_VERSION, g_compile_time);
|
||||
}
|
||||
|
||||
static void show_help()
|
||||
{
|
||||
show_version();
|
||||
|
||||
printf("\n"
|
||||
"Usage: cellwired [arguments]\n"
|
||||
"\n"
|
||||
"Arguments:\n"
|
||||
" -v Show version\n"
|
||||
" -h Show help\n"
|
||||
" -d Start as daemon\n"
|
||||
" -f Set configuration file name\n"
|
||||
" -l log_path Fork log daemon with file path to be logged to\n"
|
||||
"\n"
|
||||
);
|
||||
}
|
||||
|
||||
static void threads_start()
|
||||
{
|
||||
status_t rv;
|
||||
|
||||
#if 0
|
||||
rv = thread_create(&thr_sm, NULL, sm_main, NULL);
|
||||
d_assert(rv == CORE_OK, return,
|
||||
"State machine thread creation failed");
|
||||
|
||||
rv = thread_create(&thr_dp, NULL, dp_main, NULL);
|
||||
d_assert(rv == CORE_OK, return,
|
||||
"Control path thread creation failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void threads_stop()
|
||||
{
|
||||
#if 0
|
||||
thread_delete(thr_sm);
|
||||
thread_delete(thr_dp);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int check_signal(int signum)
|
||||
{
|
||||
switch (signum)
|
||||
{
|
||||
case SIGTERM:
|
||||
case SIGINT:
|
||||
{
|
||||
d_info("%s received",
|
||||
signum == SIGTERM ? "SIGTERM" : "SIGINT");
|
||||
|
||||
threads_stop();
|
||||
|
||||
return 1;
|
||||
}
|
||||
case SIGHUP:
|
||||
{
|
||||
|
||||
d_info("SIGHUP received");
|
||||
|
||||
threads_stop();
|
||||
|
||||
cellwire_terminate();
|
||||
|
||||
core_terminate();
|
||||
|
||||
core_initialize();
|
||||
|
||||
cellwire_initialize();
|
||||
|
||||
threads_start();
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
d_error("Unknown Signal Number = %d\n", signum);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void logger_signal(int signum)
|
||||
{
|
||||
switch (signum)
|
||||
{
|
||||
case SIGTERM:
|
||||
case SIGINT:
|
||||
logger_stop();
|
||||
break;
|
||||
case SIGHUP:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int opt;
|
||||
int opt_daemon = 0;
|
||||
int opt_logger = 0;
|
||||
|
||||
char *log_path = NULL;
|
||||
|
||||
/**************************************************************************
|
||||
* Starting up process.
|
||||
*
|
||||
* Keep the order of starting-up
|
||||
*/
|
||||
|
||||
while (1)
|
||||
{
|
||||
opt = getopt (argc, argv, "vhdf:l:");
|
||||
if (opt == -1)
|
||||
break;
|
||||
|
||||
switch (opt)
|
||||
{
|
||||
case 'v':
|
||||
show_version();
|
||||
return EXIT_SUCCESS;
|
||||
case 'h':
|
||||
show_help();
|
||||
return EXIT_SUCCESS;
|
||||
case 'd':
|
||||
opt_daemon = 1;
|
||||
break;
|
||||
case 'f':
|
||||
config_path = optarg;
|
||||
break;
|
||||
case 'l':
|
||||
opt_logger = 1;
|
||||
log_path = optarg;
|
||||
break;
|
||||
default:
|
||||
show_help();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (opt_daemon)
|
||||
{
|
||||
pid_t pid;
|
||||
pid = fork();
|
||||
|
||||
d_assert(pid != -1, return EXIT_FAILURE, "fork() failed");
|
||||
|
||||
if (pid != 0)
|
||||
{
|
||||
/* Parent */
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
/* Child */
|
||||
|
||||
setsid();
|
||||
umask(027);
|
||||
}
|
||||
|
||||
core_initialize();
|
||||
|
||||
if (opt_logger)
|
||||
{
|
||||
pid_t pid;
|
||||
pid = fork();
|
||||
|
||||
d_assert(pid != -1, return EXIT_FAILURE, "fork() failed");
|
||||
|
||||
if (pid == 0)
|
||||
{
|
||||
/* Child */
|
||||
setsid();
|
||||
umask(027);
|
||||
|
||||
core_signal(SIGINT, logger_signal);
|
||||
core_signal(SIGTERM, logger_signal);
|
||||
core_signal(SIGHUP, logger_signal);
|
||||
|
||||
logger_start(log_path);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
/* Parent */
|
||||
}
|
||||
|
||||
signal_init();
|
||||
|
||||
if (cellwire_initialize() != CORE_OK)
|
||||
{
|
||||
d_fatal("CellWire initialization failed. Aborted");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
d_info("CellWire daemon start");
|
||||
|
||||
threads_start();
|
||||
|
||||
signal_thread(check_signal);
|
||||
|
||||
d_info("CellWire daemon terminating...");
|
||||
|
||||
cellwire_terminate();
|
||||
|
||||
core_terminate();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
## Process this file with automake to produce Makefile.in.
|
||||
|
||||
noinst_LTLIBRARIES = libcellwire.la
|
||||
|
||||
libcellwire_la_SOURCES = \
|
||||
../include/cellwire.h
|
||||
|
||||
nodist_libcellwire_la_SOURCES = \
|
||||
init.c
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/lib/core \
|
||||
-I$(top_srcdir)/lib/core/include
|
||||
|
||||
AM_CFLAGS = \
|
||||
-Wall -Werror
|
||||
|
||||
DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
MOSTLYCLEANFILES = core *.stackdump
|
||||
|
||||
EXTRA_DIST = .libs $(noinst_LTLIBRARIES)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue