add build system using Core Library

This commit is contained in:
Sukchan Lee 2017-02-02 20:34:37 +09:00
parent ea7950b2ea
commit fdf97f47bb
104 changed files with 22806 additions and 0 deletions

0
AUTHORS Normal file
View File

0
COPYING Normal file
View File

0
ChangeLog Normal file
View File

370
INSTALL Normal file
View File

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

46
Makefile.am Normal file
View File

@ -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
NEWS Normal file
View File

64
README Normal file
View 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

74
acinclude.m4 Normal file
View File

@ -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)
])

272
configure.ac Normal file
View File

@ -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}\``
"

6
lib/Makefile.am Normal file
View File

@ -0,0 +1,6 @@
## Process this file with automake to produce Makefile.in
SUBDIRS = core logger
MAINTAINERCLEANFILES = Makefile.in
MOSTLYCLEANFILES = *.stackdump

6
lib/core/Makefile.am Normal file
View File

@ -0,0 +1,6 @@
## Process this file with automake to produce Makefile.in
SUBDIRS = src test
MAINTAINERCLEANFILES = Makefile.in
MOSTLYCLEANFILES = core *.stackdump

View File

@ -0,0 +1,4 @@
#ifndef CORE_PRIVATE_COMMON_H
#define CORE_PRIVATE_COMMON_H
#endif /*CORE_PRIVATE_COMMON_H*/

View File

@ -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__ */

View File

@ -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__ */

View File

@ -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__ */

366
lib/core/include/core.h.in Normal file
View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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__ */

View File

@ -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

View File

@ -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__ */

View File

@ -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__ */

View File

@ -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 */

View File

@ -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__ */

View File

@ -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__ */

View File

@ -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__ */

View File

@ -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__ */

View File

@ -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__ */

266
lib/core/include/core_net.h Normal file
View File

@ -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__ */

View File

@ -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__ */

View File

@ -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__ */

View File

@ -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__ */

View File

@ -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__ */

View File

@ -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__ */

View File

@ -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__ */

View File

@ -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__ */

View File

@ -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_ */

View File

@ -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 */

View File

@ -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_ */

View File

@ -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 */

View File

@ -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 */

View File

@ -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__ */

View File

@ -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__ */

View File

@ -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

108
lib/core/include/core_tlv.h Normal file
View File

@ -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__ */

View File

@ -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 */

41
lib/core/src/Makefile.am Normal file
View File

@ -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)

1344
lib/core/src/aes.c Normal file

File diff suppressed because it is too large Load Diff

272
lib/core/src/aes_cmac.c Normal file
View File

@ -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;
}

405
lib/core/src/debug.c Normal file
View File

@ -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;
}

50
lib/core/src/fsm.c Normal file
View File

@ -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;
}

310
lib/core/src/msgq.c Normal file
View File

@ -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;
}

170
lib/core/src/ringbuf.c Normal file
View File

@ -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;
}

404
lib/core/src/sha1.c Normal file
View File

@ -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);
}

120
lib/core/src/sha1_hmac.c Normal file
View File

@ -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);
}

822
lib/core/src/sha2.c Normal file
View File

@ -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 */
}

380
lib/core/src/sha2_hmac.c Normal file
View File

@ -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);
}

244
lib/core/src/timer.c Normal file
View File

@ -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;
}

729
lib/core/src/tlv.c Normal file
View File

@ -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;
}

View File

@ -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)

103
lib/core/src/unix/cond.c Normal file
View File

@ -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;
}

View File

@ -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);
}
}

1012
lib/core/src/unix/file.c Normal file

File diff suppressed because it is too large Load Diff

108
lib/core/src/unix/mutex.c Normal file
View File

@ -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;
}

1571
lib/core/src/unix/net_lib.c Normal file

File diff suppressed because it is too large Load Diff

498
lib/core/src/unix/pkbuf.c Normal file
View File

@ -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;
}

102
lib/core/src/unix/rwlock.c Normal file
View File

@ -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;
}

View File

@ -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;
}

239
lib/core/src/unix/signal.c Normal file
View File

@ -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
}

84
lib/core/src/unix/start.c Normal file
View File

@ -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();
}

178
lib/core/src/unix/thread.c Normal file
View File

@ -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;
}

255
lib/core/src/unix/time.c Normal file
View File

@ -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;
}

19
lib/core/src/version.c Normal file
View File

@ -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;
}

27
lib/core/test/Makefile.am Normal file
View File

@ -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

458
lib/core/test/abts.c Normal file
View File

@ -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;
}

112
lib/core/test/abts.h Normal file
View File

@ -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

View File

@ -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 */

391
lib/core/test/testaes.c Normal file
View File

@ -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;
}

124
lib/core/test/testdir.c Normal file
View File

@ -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;
}

814
lib/core/test/testds.c Normal file
View File

@ -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]], &lttype1_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;
}

684
lib/core/test/testfile.c Normal file
View File

@ -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;
}

View File

@ -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(&copy, 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;
}

298
lib/core/test/testfsm.c Normal file
View File

@ -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;
}

393
lib/core/test/testlock.c Normal file
View File

@ -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;
}

188
lib/core/test/testmsgq.c Normal file
View File

@ -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;
}

835
lib/core/test/testnetlib.c Normal file
View File

@ -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;
}

163
lib/core/test/testsha.c Normal file
View File

@ -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;
}

47
lib/core/test/testsleep.c Normal file
View File

@ -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;
}

View File

@ -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;
}

289
lib/core/test/testtime.c Normal file
View File

@ -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;
}

381
lib/core/test/testtimer.c Normal file
View File

@ -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;
}

446
lib/core/test/testtlv.c Normal file
View File

@ -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;
}

41
lib/core/test/testutil.c Normal file
View File

@ -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);
}

76
lib/core/test/testutil.h Normal file
View File

@ -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 */

18
lib/logger/Makefile.am Normal file
View File

@ -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)

223
lib/logger/logger.c Normal file
View File

@ -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;
}

17
lib/logger/logger.h Normal file
View File

@ -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__ */

250
main.c Normal file
View File

@ -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;
}

24
src/Makefile.am Normal file
View File

@ -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