diff options
| author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2015-11-21 14:51:17 +0100 | 
|---|---|---|
| committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2015-11-21 14:51:17 +0100 | 
| commit | bb9bc9051629c3319c56785c2f4ae0e605d76329 (patch) | |
| tree | ec393eb145e5a7d43909bdfc43cdeaa28c4e434a | |
Initial import of bitz-server version 0.1.6-1
103 files changed, 11550 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a768d50 --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +# Some generics first +# Compiled Object files +*.slo +*.lo +*.o + +# Compiled Dynamic libraries +*.so +*.dylib + +# Compiled Static libraries +*.lai +*.la +*.a + +# autotools +autom4te.cache/* +aux-build/* +aclocal.m4 +config.h.in +configure +Makefile.in + +# eclipse +.project +.cproject +.settings/* +.pydevproject + +# swap files +*.swp + +# python +*.pyc + +# project specific +build/* + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..84af588 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,19 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in + +# amflags +ACLOCAL_AMFLAGS = -I aux-build/m4 + +# sub dirs +SUBDIRS = \ +	conf \ +	doc \ +	include \ +	lib \ +	modules \ +	src + +# extra dist files +EXTRA_DIST = \ +	changelog \ +	README.md + diff --git a/README.md b/README.md new file mode 100644 index 0000000..799c2ef --- /dev/null +++ b/README.md @@ -0,0 +1,168 @@ +bitz-server +=========== + +An ICAP server implementation in C++ + +### Copyright and License + +Copyright (C) 2012-2013 Uditha Atukorala. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +[GNU General Public License](http://gnu.org/licenses/gpl.html) +for more details. + + +### The concept + +The main goal of this project is to create an ICAP server +([RFC 3507](http://www.ietf.org/rfc/rfc3507.txt)) implementation in C++ +to use the power of object oriented programming. + +Starting from scratch, the server is developed with a modular architecture in mind. +The server core (written in C++) will handle the client requests, manage workers +(child processes) etc. and will provide basic handlers to serve ICAP requests. + +To extend this core functionality the idea is to have pluggable modules (like apache +server modules). These modules will provide features like content filtering, anti-virus +scanning etc. and to make it easier to write (and faster to implement) such modules +there is hope to exploit python programming language. + + +### Acknowledgements + +* Many thanks to Kenneth Oksanen for his support in finding and fixing bugs + + +### Downloads +You can download the source distributions from http://packages.geniusse.com/source/bitz-server/. + + +#### Debian/Ubuntu packages +First you should add the repository key to avoid warning. + +	$ wget -q -O - http://packages.geniusse.com/debian/packman.gpg.key | sudo apt-key add - + +Then add the following to your `/etc/apt/sources.list`; + +	$ deb http://packages.geniusse.com/debian/ [release] main + +where the `[release]` being wheezy, jessie, sid etc. + +Finally update your package list and install bitz-server; + +	$ sudo aptitude update +	$ sudo aptitude install bitz-server + + +### Dependencies + +* [libconfig++ >= 1.4](http://www.hyperrealm.com/libconfig/) +* log4cpp >= 1.0 +* python 2.7 (for modpy module) + + +### Bugs and Feature Requests + +Please report all bugs and feature requests [here](http://bugs.geniusse.com/) under the +[bitz-server](http://bugs.geniusse.com/enter_bug.cgi?product=bitz-server) project. +Known issues can be found [here](http://bugs.geniusse.com/buglist.cgi?query_format=specific&order=relevance%20desc&bug_status=__open__&product=bitz-server&list_id=36). + + +### Version history + +__0.1.6__ - _28th September 2013_ +*   Few tweaks and minor changes distribution files (no functional changes) + +__0.1.5__ - _11th August 2013_ +*   Fixing modpy interface module string copy bug + +__0.1.4__ - _01st August 2013_ +*   Code optimisations +*   Fixing bug [#34](http://bugs.geniusse.com/show_bug.cgi?id=34) + +__0.1.3__ - _29th July 2013_ +*   Fixing bugs +	[#31](http://bugs.geniusse.com/show_bug.cgi?id=31), +	[#32](http://bugs.geniusse.com/show_bug.cgi?id=32) + +__0.1.2__ - _07th July 2013_ +*   Added a RESPMOD handler ([bug #16](http://bugs.geniusse.com/show_bug.cgi?id=16)) +*   Added Message Preview features ([bug #17](http://bugs.geniusse.com/show_bug.cgi?id=17)) +*   Code cleanup and optimisations +*   Fixing bugs [#15](http://bugs.geniusse.com/show_bug.cgi?id=15), +	[#23](http://bugs.geniusse.com/show_bug.cgi?id=23), +	[#24](http://bugs.geniusse.com/show_bug.cgi?id=24), +	[#25](http://bugs.geniusse.com/show_bug.cgi?id=25) + +__0.1.1__ - _06th March 2013_ +*   Fixing bugs [#19](http://bugs.geniusse.com/show_bug.cgi?id=19) and [#22](http://bugs.geniusse.com/show_bug.cgi?id=22) + +__0.1.0__ - _03rd March 2013_ + +*   Daemonized version ([bug #18](http://bugs.geniusse.com/show_bug.cgi?id=18)), hence +	the minor version bump. Server core is re-organised with bitz::server namespace to +	be more cleaner and easier to read. +*   Make it possible to pass in command-line options +*   Closed a memory leak in modpy module +*   Fixing bugs [#20](http://bugs.geniusse.com/show_bug.cgi?id=20) and [#21](http://bugs.geniusse.com/show_bug.cgi?id=21) + + +__0.0.1__ - _24th February 2013_ + +*   Proof of concept. An ICAP server with only a REQMOD handler. Includes a template +	_echo_ module to demonstrate the pluggable module architecture and the _modpy_ module +	to demonstrate the python interface. + +--------------------------------------- + + +### Compiling from source + +First you need to initialise the autotools + +	$ libtoolize (glibtoolize in OS X) +	$ aclocal +	$ autoheader +	$ autoconf +	$ automake --add-missing --foreign + +Or you can grab the latest source distribution tar from [CI artifacts](http://jenkins.geniusse.com/job/bitz-server/). + +After that you can use the usual `./configure && make` + + +#### Notes +##### modpy +This is the (long awaited) python interface module. It provides a template for any +other python interface module implementations either as C++ module template or as +a C++ interface for python modules. + + +##### Debugging + +Use the following to create the binaries with debug symbols + +	$ ./configure CXXFLAGS="-g -O0" + + +##### config file + +The default config file location is `/etc/bitz/bitz-server.conf` but this can +changed using the `--with-config` option when you run `configure`. + +e.g. + +	$ ./configure --with-config=/[path to source code]/conf/bitz-server.conf + + +##### valgrind checks + +	$ valgrind --leak-check=full --read-var-info=yes --trace-children=yes --suppressions=test/valgrind.supp --log-file=valgrind.log ./src/bitz-server --debug + diff --git a/acinclude.m4 b/acinclude.m4 new file mode 100644 index 0000000..73d421f --- /dev/null +++ b/acinclude.m4 @@ -0,0 +1,134 @@ +## this one is commonly used with AM_PATH_PYTHONDIR ... +dnl AM_CHECK_PYMOD(MODNAME [,SYMBOL [,ACTION-IF-FOUND [,ACTION-IF-NOT-FOUND]]]) +dnl Check if a module containing a given symbol is visible to python. +AC_DEFUN([AM_CHECK_PYMOD], +[AC_REQUIRE([AM_PATH_PYTHON]) +py_mod_var=`echo $1['_']$2 | sed 'y%./+-%__p_%'` +AC_MSG_CHECKING(for ifelse([$2],[],,[$2 in ])python module $1) +AC_CACHE_VAL(py_cv_mod_$py_mod_var, [ +ifelse([$2],[], [prog=" +import sys +try: +        import $1 +except ImportError: +        sys.exit(1) +except: +        sys.exit(0) +sys.exit(0)"], [prog=" +import $1 +$1.$2"]) +if $PYTHON -c "$prog" 1>&AC_FD_CC 2>&AC_FD_CC +  then +    eval "py_cv_mod_$py_mod_var=yes" +  else +    eval "py_cv_mod_$py_mod_var=no" +  fi +]) +py_val=`eval "echo \`echo '$py_cv_mod_'$py_mod_var\`"` +if test "x$py_val" != xno; then +  AC_MSG_RESULT(yes) +  ifelse([$3], [],, [$3 +])dnl +else +  AC_MSG_RESULT(no) +  ifelse([$4], [],, [$4 +])dnl +fi +]) + +dnl a macro to check for ability to create python extensions +dnl  AM_CHECK_PYTHON_HEADERS([ACTION-IF-POSSIBLE], [ACTION-IF-NOT-POSSIBLE]) +dnl function also defines PYTHON_INCLUDES +AC_DEFUN([AM_CHECK_PYTHON_HEADERS], +[AC_REQUIRE([AM_PATH_PYTHON]) +AC_MSG_CHECKING(for headers required to compile python extensions) +dnl deduce PYTHON_INCLUDES +py_prefix=`$PYTHON -c "import sys; print sys.prefix"` +py_exec_prefix=`$PYTHON -c "import sys; print sys.exec_prefix"` +if $PYTHON-config --help 2>/dev/null; then +  PYTHON_INCLUDES=`$PYTHON-config --includes 2>/dev/null` +else +  PYTHON_INCLUDES="-I${py_prefix}/include/python${PYTHON_VERSION}" +  if test "$py_prefix" != "$py_exec_prefix"; then +    PYTHON_INCLUDES="$PYTHON_INCLUDES -I${py_exec_prefix}/include/python${PYTHON_VERSION}" +  fi +fi +AC_SUBST(PYTHON_INCLUDES) +dnl check if the headers exist: +save_CPPFLAGS="$CPPFLAGS" +CPPFLAGS="$CPPFLAGS $PYTHON_INCLUDES" +AC_TRY_CPP([#include <Python.h>],dnl +[AC_MSG_RESULT(found) +$1],dnl +[AC_MSG_RESULT(not found) +$2]) +CPPFLAGS="$save_CPPFLAGS" +]) + +dnl a macro to check for ability to embed python +dnl  AM_CHECK_PYTHON_LIBS([ACTION-IF-POSSIBLE], [ACTION-IF-NOT-POSSIBLE]) +dnl function also defines PYTHON_LIBS +AC_DEFUN([AM_CHECK_PYTHON_LIBS], +[AC_REQUIRE([AM_CHECK_PYTHON_HEADERS]) +AC_MSG_CHECKING(for libraries required to embed python) +dnl deduce PYTHON_LIBS +py_exec_prefix=`$PYTHON -c "import sys; print sys.exec_prefix"` +PYTHON_LIBS="-L${py_prefix}/lib -lpython${PYTHON_VERSION}" +PYTHON_LIB_LOC="${py_prefix}/lib"  +AC_SUBST(PYTHON_LIBS) +AC_SUBST(PYTHON_LIB_LOC) +dnl check if the headers exist: +save_LIBS="$LIBS" +LIBS="$LIBS $PYTHON_LIBS" +AC_TRY_LINK_FUNC(Py_Initialize, dnl +         [LIBS="$save_LIBS"; AC_MSG_RESULT(yes); $1], dnl +         [LIBS="$save_LIBS"; AC_MSG_RESULT(no); $2]) + +]) + + +dnl as-ac-expand.m4 0.2.0 +dnl autostars m4 macro for expanding directories using configure's prefix +dnl thomas@apestaart.org +dnl + +dnl AS_AC_EXPAND(VAR, CONFIGURE_VAR) +dnl example +dnl AS_AC_EXPAND(SYSCONFDIR, $sysconfdir) +dnl will set SYSCONFDIR to /usr/local/etc if prefix=/usr/local + +AC_DEFUN([AS_AC_EXPAND], +[ +    EXP_VAR=[$1] +    FROM_VAR=[$2] + +    dnl first expand prefix and exec_prefix if necessary +    prefix_save=$prefix +    exec_prefix_save=$exec_prefix + +    dnl if no prefix given, then use /usr/local, the default prefix +    if test "x$prefix" = "xNONE"; then +        prefix="$ac_default_prefix" +    fi +    dnl if no exec_prefix given, then use prefix +    if test "x$exec_prefix" = "xNONE"; then +        exec_prefix=$prefix +    fi + +    full_var="$FROM_VAR" +    dnl loop until it doesn't change anymore +    while true; do +        new_full_var="`eval echo $full_var`" +        if test "x$new_full_var" = "x$full_var"; then break; fi +        full_var=$new_full_var +    done + +    dnl clean up +    full_var=$new_full_var +    AC_SUBST([$1], "$full_var") + +    dnl restore prefix and exec_prefix +    prefix=$prefix_save +    exec_prefix=$exec_prefix_save +]) + diff --git a/changelog b/changelog new file mode 100644 index 0000000..520a174 --- /dev/null +++ b/changelog @@ -0,0 +1,36 @@ +0.1.6 - 28th September 2013 +	*   Few tweaks and minor changes distribution files (no functional changes) + +0.1.5 - 11th August 2013 +	*   Fixing modpy interface module string copy bug + +0.1.4 - 01st August 2013 +	*   Code optimisations +	*   Fixing bug #34 + +0.1.3 - 29th July 2013 +	*   Fixing bugs #31, #32 + +0.1.2 - 07th July 2013 +	*   Added a RESPMOD handler (bug #16) +	*   Added Message Preview features (bug #17) +	*   Code cleanup and optimisations +	*   Fixing bugs #15, #23, #24, #25 + +0.1.1 - 06th March 2013 +	*   Fixing bugs #19 and #22 + +0.1.0 - 03rd March 2013 +	*   Daemonized version (bug #18), hence the minor version bump. Server +		core is re-organised with bitz::server namespace to be more cleaner +		and easier to read. +	*   Make it possible to pass in command-line options +	*   Closed a memory leak in modpy module +	*   Fixing bugs #20, #21 + + +0.0.1 - 24th February 2013 +	*   Proof of concept. An ICAP server with only a REQMOD handler. Includes +		a template 'echo' module to demonstrate the pluggable module architecture +		and the 'modpy' module to demonstrate the python interface. + diff --git a/conf/Makefile.am b/conf/Makefile.am new file mode 100644 index 0000000..1dce407 --- /dev/null +++ b/conf/Makefile.am @@ -0,0 +1,26 @@ +## conf/ +configdir		= $(sysconfdir)/bitz +config_DATA		= bitz-server.conf + +# extra dist files +EXTRA_DIST = \ +	bitz-server.conf.in + + +edit = sed \ +	-e 's|@sysconfdir[@]|$(sysconfdir)|g' \ +	-e 's|@localstatedir[@]|$(localstatedir)|g' \ +	-e 's|@pkglibdir[@]|$(pkglibdir)|g' + +bitz-server.conf: bitz-server.conf.in +	rm -f $@ $@.tmp +	srcdir=''; \ +		test -f ./$@.in || srcdir=$(srcdir)/; \ +		$(edit) $${srcdir}$@.in >$@.tmp +	chmod +r $@.tmp +	chmod og-wx $@.tmp +	mv $@.tmp $@ + +clean-local: +	rm -f *.conf + diff --git a/conf/bitz-server.conf.in b/conf/bitz-server.conf.in new file mode 100644 index 0000000..95083c4 --- /dev/null +++ b/conf/bitz-server.conf.in @@ -0,0 +1,56 @@ +# +# @sysconfdir@/bitz/bitz-server.conf +# + +port = 1344; + +pid_file     = "@localstatedir@/run/bitz/bitz-server.pid"; +log_file     = "@localstatedir@/log/bitz/bitz-server.log"; +log_category = "bitz-server"; + +# maximum number of workers +max_workers         = 1; + +# maximum number of requests a worker will serve +max_worker_requests = 100; + + +# request handlers +req_handlers : +({ +	handler = "REQMOD"; +	class   = "ReqmodRequestHandler"; +	modules : +	( +		{ +			name   = "modpy"; +			module = "@pkglibdir@/modules/mod_py.so"; +		} +	) +}, +{ +	handler = "RESPMOD"; +	class   = "RespmodRequestHandler"; +	modules : +	( +		{ +			name   = "modpy"; +			module = "@pkglibdir@/modules/mod_py.so"; +		} +	) +}); + + +# module configurations +modules : +{ +	modpy : +	{ +		# search path for python modules +		module_path = "@pkglibdir@/modules/modpy"; + +		# python module containing the interface methods +		module_name = "modpy"; +	}; +}; + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..9f43dd1 --- /dev/null +++ b/configure.ac @@ -0,0 +1,147 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ([2.68]) +AC_INIT([bitz-server], [0.1.6], [http://bugs.geniusse.com/]) +AC_CONFIG_AUX_DIR([aux-build]) +AC_CONFIG_MACRO_DIR([aux-build/m4]) +AC_CONFIG_HEADERS([include/config.h]) + +# Versioning rules ( C:R:A ) +# +# 1. Start with version 0:0:0. +# 2. If any of the sources have changed, increment R. This is a new revision +#    of the current interface. +# 3. If the interface has changed, increment C and set R to 0. This is the +#    first revision of a new interface. +# 4. If the new interface is a superset of the previous interface +#    (that is, if the previous interface has not been broken by the +#    changes in this new release), increment A. This release is backwards +#    compatible with the previous release. +# 5. If the new interface has removed elements with respect to the +#    previous interface, then backward compatibility is broken; set A to 0. +#    This release has a new, but backwards incompatible interface. +# +# For more info see section 6.3 of the GNU Libtool Manual. +# +# In short; +# +1 : ? : +1  == new interface that does not break old one +# +1 : ? : 0   == new interface that breaks old one +#  ? : ? : 0   == no new interfaces, but breaks apps +#  ? :+1 : ?   == just some internal changes, nothing breaks but might work +#                 better +# CURRENT : REVISION : AGE + +# lib versions +ICAP_LT_VERSION=0:3:0 +AC_SUBST(ICAP_LT_VERSION) + +# Init +AM_INIT_AUTOMAKE([foreign]) +LT_INIT() + +# Check for programs +AC_PROG_CXX +AC_PROG_INSTALL +AC_PROG_AWK +AC_PROG_MKDIR_P +AC_PROG_LIBTOOL + +# Language +AC_LANG(C++) + +# Options +AC_ARG_WITH([config], +	[AS_HELP_STRING([--with-config], +		[specify the config file to be used])], +	[], [with_config=no]) + +AC_ARG_ENABLE([modpy], +	[AS_HELP_STRING([--enable-modpy],[Enable modpy module (default is yes)])], +	[case "${enableval}" in +		yes) modpy=true ;; +		no)  modpy=false ;; +		*) AC_MSG_ERROR([bad value ${enableval} for --enable-modpy]) ;; +	esac], +	[modpy=true] +) +AM_CONDITIONAL([MODPY], [test x$modpy = xtrue]) + + +# Checks for libraries +AM_PROG_LIBTOOL + +PKG_PROG_PKG_CONFIG +PKG_CHECK_MODULES([libconfig], [libconfig++ >= 1.4],, +	AC_MSG_ERROR([libconfig++ 1.4 or newer not found.]) +) +PKG_CHECK_MODULES([log4cpp], [log4cpp >= 1.0],, +	AC_MSG_ERROR([log4cpp 1.0 or newer not found.]) +) + + +# Checks for header files. +#AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stddef.h stdlib.h string.h sys/socket.h syslog.h unistd.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_HEADER_STDBOOL +AC_C_INLINE +AC_TYPE_SIZE_T +AC_CHECK_TYPES([ptrdiff_t]) + +# Checks for library functions. +AC_FUNC_ERROR_AT_LINE +AC_FUNC_FORK +AC_CHECK_FUNCS([gethostbyname inet_ntoa memmove memset select socket strchr strerror]) + +# conditional statements +AS_IF([test x$modpy = xtrue], +	[ +		AM_PATH_PYTHON([2.7]) +		AM_CHECK_PYTHON_HEADERS +		AM_CHECK_PYTHON_LIBS +	] +) + +# defines / substitutes +AS_IF([test "x$with_config" != xno], +	AC_DEFINE_UNQUOTED([BITZ_SERVER_CONFIG_FILE], +		["$with_config"], +		[server configuration file] +	), +	[ +		AS_AC_EXPAND(SYSCONFDIR, $sysconfdir) +		AC_DEFINE_UNQUOTED( +			[BITZ_SERVER_CONFIG_FILE], +			["${SYSCONFDIR}/bitz/bitz-server.conf"], +			[server configuration file] +		) +	] +) + +# doxygen +AC_CHECK_PROGS([DOXYGEN], [doxygen], [false]) +AM_CONDITIONAL([HAVE_DOXYGEN], [test "x$DOXYGEN" != xfalse]) +AM_COND_IF([HAVE_DOXYGEN],, +	AC_MSG_WARN([Doxygen not found - continuing without Doxygen support]) +) + + +AC_CONFIG_FILES([ \ +	Makefile \ +	conf/Makefile \ +	doc/doxygen.cfg \ +	doc/Makefile \ +	include/Makefile \ +	lib/Makefile \ +	lib/socket/Makefile \ +	lib/icap/Makefile \ +	src/Makefile \ +	modules/Makefile \ +	modules/echo/Makefile \ +	modules/modpy/Makefile \ +	modules/modpy/modules/Makefile \ +]) + +AC_OUTPUT + diff --git a/debian/README.debian b/debian/README.debian new file mode 100644 index 0000000..4e48c83 --- /dev/null +++ b/debian/README.debian @@ -0,0 +1,12 @@ +bitz-server systemd notes +------------------------- + +- bitz-server are not enabled on install.  + +  To enable bitz-server in the default configuration +  use systemctl to enable the service: +   # systemctl enable bitz-server.service +  To disable bitz-server, use systemctl to disable the service: +   # systemctl disable bitz-server.service + + -- Jörg Frings-Fürst <debian@jff-webhosting.net>  Sat, 03 Jan 2015 15:31:04 +0100 diff --git a/debian/README.lintian b/debian/README.lintian new file mode 100644 index 0000000..dd50e3b --- /dev/null +++ b/debian/README.lintian @@ -0,0 +1,7 @@ +bitz-server lintian notes +------------------------- + +- pedantic "duplicate-files" in directory usr/share/doc/bitz-server-doc/docs +  are based on doxygen build. I don't overrides them. + + -- Jörg Frings-Fürst <debian@jff-webhosting.net>  Tue, 11 Nov 2014 08:50:49 +0100 diff --git a/debian/bitz-server-doc.dirs b/debian/bitz-server-doc.dirs new file mode 100644 index 0000000..71bc8a1 --- /dev/null +++ b/debian/bitz-server-doc.dirs @@ -0,0 +1 @@ +/usr/share/doc/bitz-server-doc/docs/ diff --git a/debian/bitz-server-doc.doc-base b/debian/bitz-server-doc.doc-base new file mode 100644 index 0000000..8d078b5 --- /dev/null +++ b/debian/bitz-server-doc.doc-base @@ -0,0 +1,7 @@ +Document: bitz-server +Title: bitz-server Documentation +Section: Network/Communication + +Format: HTML +Index: /usr/share/doc/bitz-server-doc/docs/index.html +Files: /usr/share/doc/bitz-server-doc/docs/*.html diff --git a/debian/bitz-server-doc.docs b/debian/bitz-server-doc.docs new file mode 100644 index 0000000..42061c0 --- /dev/null +++ b/debian/bitz-server-doc.docs @@ -0,0 +1 @@ +README.md
\ No newline at end of file diff --git a/debian/bitz-server-doc.lintian-overrides b/debian/bitz-server-doc.lintian-overrides new file mode 100644 index 0000000..6e13e8a --- /dev/null +++ b/debian/bitz-server-doc.lintian-overrides @@ -0,0 +1,7 @@ +# The lintian warning "bitz-server-doc: embedded-javascript-library +# usr/share/doc/bitz-server-doc/docs/jquery.js please use libjs-jquery" +# was overridden. +# The file jquery.js comes from the with doxygen-generated documentation. +# The built-in jquery.js in doxygen is not going to be removed (see Debian bug #736432). +# +bitz-server-doc binary: embedded-javascript-library diff --git a/debian/bitz-server.docs b/debian/bitz-server.docs new file mode 100644 index 0000000..aeb0ee7 --- /dev/null +++ b/debian/bitz-server.docs @@ -0,0 +1,2 @@ +README.md +debian/doc/*.txt diff --git a/debian/bitz-server.init b/debian/bitz-server.init new file mode 100644 index 0000000..ade8b71 --- /dev/null +++ b/debian/bitz-server.init @@ -0,0 +1,132 @@ +#!/bin/sh + +### BEGIN INIT INFO +# Provides:          bitz-server +# Required-Start:    $remote_fs $syslog +# Required-Stop:     $local_fs $remote_fs +# Default-Start:     2 3 4 5 +# Default-Stop:      0 1 6 +# Short-Description: Bitz ICAP server +# Description:       ICAP server (RFC 3507) +### END INIT INFO +# +#  Written 2014 by Jörg Frings-Fürst <debian@jff-webhosting.net>. +#  Licensed under GPL-3+. +# +### + +DESC="bitz ICAP server" +NAME="bitz-server" + +DAEMON="/usr/sbin/$NAME" +PIDFILE=/var/run/$NAME.pid + +PATH=/sbin:/usr/sbin:/bin:/usr/bin +SCRIPT=/etc/init.d/$NAME + +BITZ-SERVER_OPTS="--config=/etc/bitz/bitz-server.conf" + +# Are we making sense? +[ -x "$DAEMON" ] || exit 0 + +# Read configuration variable file if it is present +[ -r /etc/default/$NAME ] && . /etc/default/$NAME + +# Define all LSB log_* functions. +. /lib/lsb/init-functions + +# Start downtimed. +do_start() +{ +	start-stop-daemon --start --quiet --pidfile $PIDFILE \ +			--exec $DAEMON --test > /dev/null \ +		|| return 1 +	start-stop-daemon --start --quiet --pidfile $PIDFILE \ +			--exec $DAEMON -- $DOWNTIMED_OPTS \ +		|| return 2 + +	# Return status: +	#   0    daemon has been started +	#   1    daemon was already running +	#   2    daemon could not be started +} + +# Halt downtimed. +do_stop() +{ +	start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 \ +			--pidfile $PIDFILE --exec $DAEMON +	RETVAL="$?" +	[ "$RETVAL" = 2 ] && return 2 + +	rm -f $PIDFILE +	return "$RETVAL" + +	# Return status: +	#   0      daemon has been stopped +	#   1      daemon was already stopped +	#   2      daemon could not be stopped +	#   other  daemon reported some other failure +} + +# Reloading is a no-do in the standard case, when logging is +# done via the syslog service. Only if $DOWNTIMED_OPTS states +# a separate logging file, then a SIGHUP will result in the +# daemon releasing the file for rotation, or a similar action. + +do_reload() { +	start-stop-daemon --stop --signal 1 --quiet \ +			--pidfile $PIDFILE --exec $DAEMON +	return 0 +} + +case "$1" in +  start) +	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" +	do_start +	case "$?" in +		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; +		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; +	esac +	;; +  stop) +	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" +	do_stop +	case "$?" in +		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; +		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; +	esac +	;; +  status) +	status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? +	;; +  reload|force-reload) +	log_daemon_msg "Reloading $DESC" "$NAME" +	do_reload +	log_end_msg $? +	;; +  restart) +	log_daemon_msg "Restarting $DESC" "$NAME" +	do_stop +	case "$?" in +	  0|1) +		do_start +		case "$?" in +			0) log_end_msg 0 ;; +			1) log_end_msg 1 ;; # Still running. +			*) log_end_msg 1 ;; # Failure in starting. +		esac +		;; +	  *) +	  	# Failure in ending service. +		log_end_msg 1 +		;; +	esac +	;; +  *) +	echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload|status}" >&2 +	exit 3 +	;; +esac + +: diff --git a/debian/bitz-server.install b/debian/bitz-server.install new file mode 100644 index 0000000..738bdb8 --- /dev/null +++ b/debian/bitz-server.install @@ -0,0 +1,2 @@ +etc/bitz/* +usr/sbin/* diff --git a/debian/bitz-server.manpages b/debian/bitz-server.manpages new file mode 100644 index 0000000..1b5587e --- /dev/null +++ b/debian/bitz-server.manpages @@ -0,0 +1,2 @@ +debian/tmp/usr/share/man/man1/*.1 +debian/tmp/usr/share/man/man5/*.5 diff --git a/debian/bitz-server.postrm b/debian/bitz-server.postrm new file mode 100644 index 0000000..f172740 --- /dev/null +++ b/debian/bitz-server.postrm @@ -0,0 +1,22 @@ +#!/bin/sh + +set -e + +if [ "$1" = purge ]; then +# +# purge systemd files +# see ../../doc/why.txt +# +    rm -f /etc/systemd/system/bitz-server.service +    rm -f /var/lib/systemd/deb-systemd-helper-enabled/bitz-server.service.dsh-also +    rm -f /var/lib/systemd/deb-systemd-helper-masked/bitz-server.service +    if [ -d /var/lib/systemd/deb-systemd-helper-enabled ]; then +	rmdir --ignore-fail-on-non-empty /var/lib/systemd/deb-systemd-helper-enabled +    fi +    if [ -d /var/lib/systemd/deb-systemd-helper-masked ]; then +	rmdir --ignore-fail-on-non-empty /var/lib/systemd/deb-systemd-helper-masked +    fi +    rm -f /etc/init/bitz-server.override +fi + +#DEBHELPER# diff --git a/debian/bitz-server.service b/debian/bitz-server.service new file mode 100644 index 0000000..c81ddbd --- /dev/null +++ b/debian/bitz-server.service @@ -0,0 +1,11 @@ +[Unit] +Description=bitz ICAP server +After=network.target + +[Service] +Type=simple +ExecStart=/usr/sbin/bitz-server /etc/bitz/bitz-server.conf +ExecReload=/bin/kill -HUP $MAINPID + +[Install] +WantedBy=multi-user.target diff --git a/debian/bitz-server.upstart b/debian/bitz-server.upstart new file mode 100644 index 0000000..f0a3360 --- /dev/null +++ b/debian/bitz-server.upstart @@ -0,0 +1,7 @@ +description "bitz ICAP server" +author "Cameron Norman <camerontnorman@gmail.com>" + +start on runlevel [2345] +stop on runlevel [016] + +exec /usr/sbin/bitz-server /etc/bitz/bitz-server.conf diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..c7c70cb --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +bitz-server (0.1.6-1) unstable; urgency=low + +  * Initial release (Closes: #715022) + + -- Jörg Frings-Fürst <debian@jff-webhosting.net>  Sun, 08 Nov 2015 09:20:29 +0100 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..ec63514 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +9 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..4aad9fd --- /dev/null +++ b/debian/control @@ -0,0 +1,162 @@ +Source: bitz-server +Section: net +Priority: optional +Maintainer: Jörg Frings-Fürst <debian@jff-webhosting.net> +Uploaders: Uditha Atukorala <ua@nuked.zone> +Build-Depends: + debhelper (>= 9), + dh-autoreconf, + dh-python, + dh-systemd (>= 1.5), + libconfig++-dev, + liblog4cpp5-dev, + libpsocksxx-dev, + python-dev, + libpython-dev +Build-Depends-Indep: + doxygen +Standards-Version: 3.9.6 +Homepage: https://github.com/uditha-atukorala/bitz-server +Vcs-Git: git://anonscm.debian.org/collab-maint/bitz-server.git +Vcs-Browser: http://anonscm.debian.org/cgit/collab-maint/bitzserver.git + +Package: bitz-server +Architecture: any +Depends: + ${shlibs:Depends}, + ${misc:Depends}, + libicap0 (= ${binary:Version}) +Description: ICAP server (RFC 3507) implementation in C++ + The main goal of this project is to create an ICAP server (RFC 3507) + implementation in C++ to use the power of object oriented programming. + . + Starting from scratch, the server is developed with a modular architecture + in mind. The server core (written in C++) will handle the client requests, + manage workers (child processes) etc. and will provide basic handlers to serve + ICAP requests. + . + To extend this core functionality the idea is to have pluggable modules + (like Apache server modules). These modules will provide features like + content filtering, anti-virus scanning etc. and to make it easier to write + (and faster to implement) such modules there is hope to exploit Python + programming language. + +Package: bitz-server-doc +Architecture: all +Section: doc +Depends: ${misc:Depends} +Description: ICAP server (RFC 3507) implementation in C++ (Documentation) + The main goal of this project is to create an ICAP server (RFC 3507) + implementation in C++ to use the power of object oriented programming. + . + Starting from scratch, the server is developed with a modular architecture + in mind. The server core (written in C++) will handle the client requests, + manage workers (child processes) etc. and will provide basic handlers to serve + ICAP requests. + . + To extend this core functionality the idea is to have pluggable modules + (like Apache server modules). These modules will provide features like + content filtering, anti-virus scanning etc. and to make it easier to write + (and faster to implement) such modules there is hope to exploit Python + programming language. + . + This package holds the documentation. + +Package: libicap-dev +Section: libdevel +Architecture: any +Multi-Arch: same +Depends: + libicap0 (= ${binary:Version}), + ${misc:Depends} +Suggests: bitz-server-doc +Description: ICAP server (RFC 3507) implementation in C++ (development files) + The main goal of this project is to create an ICAP server (RFC 3507) + implementation in C++ to use the power of object oriented programming. + . + Starting from scratch, the server is developed with a modular architecture + in mind. The server core (written in C++) will handle the client requests, + manage workers (child processes) etc. and will provide basic handlers to serve + ICAP requests. + . + To extend this core functionality the idea is to have pluggable modules + (like Apache server modules). These modules will provide features like + content filtering, anti-virus scanning etc. and to make it easier to write + (and faster to implement) such modules there is hope to exploit Python + programming language. + . + This package holds the development files. + +Package: libicap0 +Architecture: any +Multi-Arch: same +Depends: + ${shlibs:Depends}, + ${misc:Depends} +Pre-Depends: + ${misc:Pre-Depends} +Description: ICAP server (RFC 3507) implementation in C++ (library files) + The main goal of this project is to create an ICAP server (RFC 3507) + implementation in C++ to use the power of object oriented programming. + . + Starting from scratch, the server is developed with a modular architecture + in mind. The server core (written in C++) will handle the client requests, + manage workers (child processes) etc. and will provide basic handlers to serve + ICAP requests. + . + To extend this core functionality the idea is to have pluggable modules + (like Apache server modules). These modules will provide features like + content filtering, anti-virus scanning etc. and to make it easier to write + (and faster to implement) such modules there is hope to exploit Python + programming language. + . + This package holds the library files. + +Package: bitz-server-dbg +Architecture: any +Section: debug +Priority: extra +Depends:  + ${misc:Depends}, + bitz-server (= ${binary:Version}) +Description: ICAP server (RFC 3507) implementation in C++ (server debug symbols) + The main goal of this project is to create an ICAP server (RFC 3507) + implementation in C++ to use the power of object oriented programming. + . + Starting from scratch, the server is developed with a modular architecture + in mind. The server core (written in C++) will handle the client requests, + manage workers (child processes) etc. and will provide basic handlers to serve + ICAP requests. + . + To extend this core functionality the idea is to have pluggable modules + (like Apache server modules). These modules will provide features like + content filtering, anti-virus scanning etc. and to make it easier to write + (and faster to implement) such modules there is hope to exploit Python + programming language. + . + This package holds the debug symbols for bitz-server. + +Package: libicap0-dbg +Architecture: any +Multi-Arch: same +Section: debug +Priority: extra +Depends:  + ${misc:Depends}, + libicap0 (= ${binary:Version}) +Description: ICAP server (RFC 3507) implementation in C++ (library debug symbols) + The main goal of this project is to create an ICAP server (RFC 3507) + implementation in C++ to use the power of object oriented programming. + . + Starting from scratch, the server is developed with a modular architecture + in mind. The server core (written in C++) will handle the client requests, + manage workers (child processes) etc. and will provide basic handlers to serve + ICAP requests. + . + To extend this core functionality the idea is to have pluggable modules + (like Apache server modules). These modules will provide features like + content filtering, anti-virus scanning etc. and to make it easier to write + (and faster to implement) such modules there is hope to exploit Python + programming language. + . + This package holds the debug symbols for libicap0. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..7cf797c --- /dev/null +++ b/debian/copyright @@ -0,0 +1,33 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: bitz-server +Source: https://github.com/uditha-atukorala/bitz-server + +Files: * +Copyright: 2012-2014 Uditha Atukorala <ua@nuked.zone> +License: GPL-3+ + +Files: lib/socket/socket.* +Copyright: 2002      <unknown> +           2010      Uditha Atukorala <ua@nuked.zone> +License: GPL-3+ + +Files: debian/* +Copyright: 2014-2015 Jörg Frings-Fürst <debian@jff-webhosting.net> +License: GPL-3+ +  +License: GPL-3+ + This package is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + . + This package is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + GNU General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/> + . + On Debian systems, the complete text of the GNU General + Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". diff --git a/debian/doc/why_delete_systemd_file_via_postrm.txt b/debian/doc/why_delete_systemd_file_via_postrm.txt new file mode 100644 index 0000000..d76dddb --- /dev/null +++ b/debian/doc/why_delete_systemd_file_via_postrm.txt @@ -0,0 +1,807 @@ +# +# 2015-05-14 +# +# why remove systemd over postrm +# + +########## +$ apt-cache policy piuparts +piuparts: +  Installiert:           0.63 +  Installationskandidat: 0.63 +  Versionstabelle: + *** 0.63 0 +        900 http://mirror.1und1.de/debian/ stretch/main amd64 Packages +        800 http://mirror.1und1.de/debian/ sid/main amd64 Packages +        100 /var/lib/dpkg/status + +########## +$ apt-cache policy systemd +systemd: +  Installiert:           215-17 +  Installationskandidat: 215-17 +  Versionstabelle: +     219-9 0 +          1 http://mirror.1und1.de/debian/ experimental/main amd64 Packages + *** 215-17 0 +        900 http://mirror.1und1.de/debian/ stretch/main amd64 Packages +        800 http://mirror.1und1.de/debian/ sid/main amd64 Packages +        100 /var/lib/dpkg/status + +########## +log piuparts: + +0m0.0s INFO: ------------------------------------------------------------------------------ +0m0.0s INFO: To quickly glance what went wrong, scroll down to the bottom of this logfile. +0m0.0s INFO: FAQ available at https://wiki.debian.org/piuparts/FAQ +0m0.0s INFO: The FAQ also explains how to contact us in case you think piuparts is wrong. +0m0.0s INFO: ------------------------------------------------------------------------------ +0m0.0s INFO: piuparts version 0.63 starting up. +0m0.0s INFO: Command line arguments: /usr/sbin/piuparts --basetgz=../../sid-amd64-base.tgz bitz-server_0.1.6-1_amd64.changes +0m0.0s INFO: Running on: Linux merkur 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt9-3 (2015-04-23) x86_64 +0m0.0s DEBUG: Starting command: ['dpkg', '--info', 'bitz-server_0.1.6-1_amd64.deb'] +0m0.0s DUMP:  +   new debian package, version 2.0. +   size 51096 bytes: control archive=2115 bytes. +        78 bytes,     3 lines      conffiles             +      1144 bytes,    23 lines      control               +       643 bytes,     9 lines      md5sums               +       867 bytes,    23 lines   *  postinst             #!/bin/sh +      1373 bytes,    47 lines   *  postrm               #!/bin/sh +       177 bytes,     7 lines   *  prerm                #!/bin/sh +   Package: bitz-server +   Version: 0.1.6-1 +   Architecture: amd64 +   Maintainer: Jörg Frings-Fürst <debian@jff-webhosting.net> +   Installed-Size: 137 +   Depends: libc6 (>= 2.15), libconfig++9, libgcc1 (>= 1:4.1.1), libicap0 (= 0.1.6-1), liblog4cpp5, libstdc++6 (>= 4.9), init-system-helpers (>= 1.18~) +   Section: net +   Priority: extra +   Homepage: https://github.com/uditha-atukorala/bitz-server +   Description: ICAP server (RFC 3507) implementation in C++ +    The main goal of this project is to create an ICAP server (RFC 3507) +    implementation in C++ to use the power of object oriented programming. +    . +    Starting from scratch, the server is developed with a modular architecture +    in mind. The server core (written in C++) will handle the client requests, +    manage workers (child processes) etc. and will provide basic handlers to serve +    ICAP requests. +    . +    To extend this core functionality the idea is to have pluggable modules +    (like Apache server modules). These modules will provide features like +    content filtering, anti-virus scanning etc. and to make it easier to write +    (and faster to implement) such modules there is hope to exploit Python +    programming language. +0m0.0s DEBUG: Command ok: ['dpkg', '--info', 'bitz-server_0.1.6-1_amd64.deb'] +0m0.0s DEBUG: Starting command: ['dpkg', '--info', 'bitz-server-doc_0.1.6-1_all.deb'] +0m0.0s DUMP:  +   new debian package, version 2.0. +   size 150870 bytes: control archive=9598 bytes. +      1076 bytes,    25 lines      control               +     28315 bytes,   292 lines      md5sums               +   Package: bitz-server-doc +   Source: bitz-server +   Version: 0.1.6-1 +   Architecture: all +   Maintainer: Jörg Frings-Fürst <debian@jff-webhosting.net> +   Installed-Size: 1657 +   Section: doc +   Priority: extra +   Homepage: https://github.com/uditha-atukorala/bitz-server +   Description: ICAP server (RFC 3507) implementation in C++ (Documentation) +    The main goal of this project is to create an ICAP server (RFC 3507) +    implementation in C++ to use the power of object oriented programming. +    . +    Starting from scratch, the server is developed with a modular architecture +    in mind. The server core (written in C++) will handle the client requests, +    manage workers (child processes) etc. and will provide basic handlers to serve +    ICAP requests. +    . +    To extend this core functionality the idea is to have pluggable modules +    (like Apache server modules). These modules will provide features like +    content filtering, anti-virus scanning etc. and to make it easier to write +    (and faster to implement) such modules there is hope to exploit Python +    programming language. +    . +    This package holds the documentation. +0m0.0s DEBUG: Command ok: ['dpkg', '--info', 'bitz-server-doc_0.1.6-1_all.deb'] +0m0.0s DEBUG: Starting command: ['dpkg', '--info', 'libicap-dev_0.1.6-1_amd64.deb'] +0m0.0s DUMP:  +   new debian package, version 2.0. +   size 10410 bytes: control archive=1342 bytes. +      1158 bytes,    28 lines      control               +       937 bytes,    14 lines      md5sums               +   Package: libicap-dev +   Source: bitz-server +   Version: 0.1.6-1 +   Architecture: amd64 +   Maintainer: Jörg Frings-Fürst <debian@jff-webhosting.net> +   Installed-Size: 33 +   Depends: libicap0 (= 0.1.6-1) +   Suggests: bitz-server-doc +   Section: libdevel +   Priority: extra +   Multi-Arch: same +   Homepage: https://github.com/uditha-atukorala/bitz-server +   Description: ICAP server (RFC 3507) implementation in C++ (development files) +    The main goal of this project is to create an ICAP server (RFC 3507) +    implementation in C++ to use the power of object oriented programming. +    . +    Starting from scratch, the server is developed with a modular architecture +    in mind. The server core (written in C++) will handle the client requests, +    manage workers (child processes) etc. and will provide basic handlers to serve +    ICAP requests. +    . +    To extend this core functionality the idea is to have pluggable modules +    (like Apache server modules). These modules will provide features like +    content filtering, anti-virus scanning etc. and to make it easier to write +    (and faster to implement) such modules there is hope to exploit Python +    programming language. +    . +    This package holds the development files. +0m0.0s DEBUG: Command ok: ['dpkg', '--info', 'libicap-dev_0.1.6-1_amd64.deb'] +0m0.0s DEBUG: Starting command: ['dpkg', '--info', 'libicap0_0.1.6-1_amd64.deb'] +0m0.1s DUMP:  +   new debian package, version 2.0. +   size 46194 bytes: control archive=3642 bytes. +      1155 bytes,    27 lines      control               +       360 bytes,     5 lines      md5sums               +       135 bytes,     7 lines   *  postinst             #!/bin/sh +       132 bytes,     7 lines   *  postrm               #!/bin/sh +        19 bytes,     1 lines      shlibs                +     12433 bytes,   203 lines      symbols               +   Package: libicap0 +   Source: bitz-server +   Version: 0.1.6-1 +   Architecture: amd64 +   Maintainer: Jörg Frings-Fürst <debian@jff-webhosting.net> +   Installed-Size: 138 +   Depends: libc6 (>= 2.15), libgcc1 (>= 1:4.1.1), libstdc++6 (>= 4.9) +   Section: net +   Priority: extra +   Multi-Arch: same +   Homepage: https://github.com/uditha-atukorala/bitz-server +   Description: ICAP server (RFC 3507) implementation in C++ (library files) +    The main goal of this project is to create an ICAP server (RFC 3507) +    implementation in C++ to use the power of object oriented programming. +    . +    Starting from scratch, the server is developed with a modular architecture +    in mind. The server core (written in C++) will handle the client requests, +    manage workers (child processes) etc. and will provide basic handlers to serve +    ICAP requests. +    . +    To extend this core functionality the idea is to have pluggable modules +    (like Apache server modules). These modules will provide features like +    content filtering, anti-virus scanning etc. and to make it easier to write +    (and faster to implement) such modules there is hope to exploit Python +    programming language. +    . +    This package holds the library files. +0m0.1s DEBUG: Command ok: ['dpkg', '--info', 'libicap0_0.1.6-1_amd64.deb'] +0m0.1s DEBUG: Starting command: ['dpkg', '--info', 'bitz-server-dbg_0.1.6-1_amd64.deb'] +0m0.1s DUMP:  +   new debian package, version 2.0. +   size 299412 bytes: control archive=1047 bytes. +      1135 bytes,    26 lines      control               +       341 bytes,     4 lines      md5sums               +   Package: bitz-server-dbg +   Source: bitz-server +   Version: 0.1.6-1 +   Architecture: amd64 +   Maintainer: Jörg Frings-Fürst <debian@jff-webhosting.net> +   Installed-Size: 319 +   Depends: bitz-server (= 0.1.6-1) +   Section: debug +   Priority: extra +   Homepage: https://github.com/uditha-atukorala/bitz-server +   Description: ICAP server (RFC 3507) implementation in C++ (server debug symbols) +    The main goal of this project is to create an ICAP server (RFC 3507) +    implementation in C++ to use the power of object oriented programming. +    . +    Starting from scratch, the server is developed with a modular architecture +    in mind. The server core (written in C++) will handle the client requests, +    manage workers (child processes) etc. and will provide basic handlers to serve +    ICAP requests. +    . +    To extend this core functionality the idea is to have pluggable modules +    (like Apache server modules). These modules will provide features like +    content filtering, anti-virus scanning etc. and to make it easier to write +    (and faster to implement) such modules there is hope to exploit Python +    programming language. +    . +    This package holds the debug symbols for bitz-server. +0m0.1s DEBUG: Command ok: ['dpkg', '--info', 'bitz-server-dbg_0.1.6-1_amd64.deb'] +0m0.1s DEBUG: Starting command: ['dpkg', '--info', 'libicap0-dbg_0.1.6-1_amd64.deb'] +0m0.1s DUMP:  +   new debian package, version 2.0. +   size 334462 bytes: control archive=1066 bytes. +      1144 bytes,    27 lines      control               +       332 bytes,     4 lines      md5sums               +   Package: libicap0-dbg +   Source: bitz-server +   Version: 0.1.6-1 +   Architecture: amd64 +   Maintainer: Jörg Frings-Fürst <debian@jff-webhosting.net> +   Installed-Size: 349 +   Depends: libicap0 (= 0.1.6-1) +   Section: debug +   Priority: extra +   Multi-Arch: same +   Homepage: https://github.com/uditha-atukorala/bitz-server +   Description: ICAP server (RFC 3507) implementation in C++ (library debug symbols) +    The main goal of this project is to create an ICAP server (RFC 3507) +    implementation in C++ to use the power of object oriented programming. +    . +    Starting from scratch, the server is developed with a modular architecture +    in mind. The server core (written in C++) will handle the client requests, +    manage workers (child processes) etc. and will provide basic handlers to serve +    ICAP requests. +    . +    To extend this core functionality the idea is to have pluggable modules +    (like Apache server modules). These modules will provide features like +    content filtering, anti-virus scanning etc. and to make it easier to write +    (and faster to implement) such modules there is hope to exploit Python +    programming language. +    . +    This package holds the debug symbols for libicap0. +0m0.1s DEBUG: Command ok: ['dpkg', '--info', 'libicap0-dbg_0.1.6-1_amd64.deb'] +0m0.1s DEBUG: Created temporary directory /tmp/tmpDXAZc1 +0m0.1s DEBUG: Unpacking ../../sid-amd64-base.tgz into /tmp/tmpDXAZc1 +0m0.1s DEBUG: Starting command: ['tar', '-C', '/tmp/tmpDXAZc1', '-zxf', '../../sid-amd64-base.tgz'] +0m3.4s DEBUG: Command ok: ['tar', '-C', '/tmp/tmpDXAZc1', '-zxf', '../../sid-amd64-base.tgz'] +0m3.4s DEBUG: Starting command: ['chroot', '/tmp/tmpDXAZc1', 'mount', '-t', 'proc', 'proc', '/proc'] +0m3.4s DEBUG: Command ok: ['chroot', '/tmp/tmpDXAZc1', 'mount', '-t', 'proc', 'proc', '/proc'] +0m3.4s DEBUG: Starting command: ['chroot', '/tmp/tmpDXAZc1', 'mount', '-t', 'devpts', 'devpts', '/dev/pts'] +0m3.4s DEBUG: Command ok: ['chroot', '/tmp/tmpDXAZc1', 'mount', '-t', 'devpts', 'devpts', '/dev/pts'] +0m3.4s DEBUG: sources.list: +  deb http://mirror.1und1.de/debian/ sid main +  deb http://mirror.1und1.de/debian/ sid non-free +  deb http://mirror.1und1.de/debian/ sid contrib +0m3.4s DEBUG: Created policy-rc.d and chmodded it. +0m3.4s DEBUG: Created resolv.conf. +0m3.4s DEBUG: Starting command: ['chroot', '/tmp/tmpDXAZc1', 'apt-get', 'update'] +0m25.2s DUMP:  +  Get:1 http://mirror.1und1.de sid InRelease [204 kB] +  Get:2 http://mirror.1und1.de sid/main amd64 Packages [7197 kB] +  Get:3 http://mirror.1und1.de sid/non-free amd64 Packages [89.2 kB] +  Get:4 http://mirror.1und1.de sid/contrib amd64 Packages [54.6 kB] +  Get:5 http://mirror.1und1.de sid/contrib Translation-en [42.8 kB] +  Get:6 http://mirror.1und1.de sid/main Translation-en [4883 kB] +  Get:7 http://mirror.1und1.de sid/non-free Translation-en [77.2 kB] +  Fetched 12.5 MB in 19s (645 kB/s) +  Reading package lists... +0m25.2s DEBUG: Command ok: ['chroot', '/tmp/tmpDXAZc1', 'apt-get', 'update'] +0m25.2s DEBUG: Starting command: ['chroot', '/tmp/tmpDXAZc1', 'apt-get', '-yf', 'dist-upgrade'] +0m25.5s DUMP:  +  Reading package lists... +  Building dependency tree... +  Reading state information... +  0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded. +0m25.5s DEBUG: Command ok: ['chroot', '/tmp/tmpDXAZc1', 'apt-get', '-yf', 'dist-upgrade'] +0m25.5s DEBUG: Starting command: ['chroot', '/tmp/tmpDXAZc1', 'apt-get', 'clean'] +0m25.5s DEBUG: Command ok: ['chroot', '/tmp/tmpDXAZc1', 'apt-get', 'clean'] +0m27.5s DEBUG: Starting command: ['chroot', '/tmp/tmpDXAZc1', 'dpkg', '--get-selections', '*'] +0m27.5s DUMP:  +  acl						install +  adduser						install +  apt						install +  aptitude					install +  aptitude-common					install +  base-files					install +  base-passwd					install +  bash						install +  binutils					install +  bsdutils					install +  build-essential					install +  bzip2						install +  coreutils					install +  cpp						install +  cpp-4.9						install +  dash						install +  debconf						install +  debconf-i18n					install +  debian-archive-keyring				install +  debianutils					install +  diffutils					install +  dmsetup						install +  dpkg						install +  dpkg-dev					install +  e2fslibs:amd64					install +  e2fsprogs					install +  findutils					install +  g++						install +  g++-4.9						install +  gcc						install +  gcc-4.7-base:amd64				install +  gcc-4.8-base:amd64				install +  gcc-4.9						install +  gcc-4.9-base:amd64				install +  gcc-5-base:amd64				install +  gnupg						install +  gpgv						install +  grep						install +  gzip						install +  hostname					install +  init						install +  initscripts					install +  insserv						install +  libacl1:amd64					install +  libapt-pkg4.12:amd64				install +  libasan1:amd64					install +  libatomic1:amd64				install +  libattr1:amd64					install +  libaudit-common					install +  libaudit1:amd64					install +  libblkid1:amd64					install +  libboost-iostreams1.55.0:amd64			install +  libbz2-1.0:amd64				install +  libc-bin					install +  libc-dev-bin					install +  libc6:amd64					install +  libc6-dev:amd64					install +  libcap2:amd64					install +  libcap2-bin					install +  libcilkrts5:amd64				install +  libcloog-isl4:amd64				install +  libcomerr2:amd64				install +  libcryptsetup4:amd64				install +  libcwidget3:amd64				install +  libdb5.3:amd64					install +  libdebconfclient0:amd64				install +  libdevmapper1.02.1:amd64			install +  libdpkg-perl					install +  libfdisk1:amd64					install +  libffi6:amd64					install +  libgcc-4.9-dev:amd64				install +  libgcc1:amd64					install +  libgcrypt20:amd64				install +  libgdbm3:amd64					install +  libglib2.0-0:amd64				install +  libgmp10:amd64					install +  libgomp1:amd64					install +  libgpg-error0:amd64				install +  libgpm2:amd64					install +  libisl10:amd64					install +  libisl13:amd64					install +  libitm1:amd64					install +  libkmod2:amd64					install +  liblocale-gettext-perl				install +  liblsan0:amd64					install +  liblzma5:amd64					install +  libmount1:amd64					install +  libmpc3:amd64					install +  libmpfr4:amd64					install +  libncurses5:amd64				install +  libncursesw5:amd64				install +  libpam-modules:amd64				install +  libpam-modules-bin				install +  libpam-runtime					install +  libpam0g:amd64					install +  libpcre3:amd64					install +  libprocps3:amd64				install +  libquadmath0:amd64				install +  libreadline6:amd64				install +  libselinux1:amd64				install +  libsemanage-common				install +  libsemanage1:amd64				install +  libsepol1:amd64					install +  libsigc++-2.0-0c2a:amd64			install +  libslang2:amd64					install +  libsmartcols1:amd64				install +  libsqlite3-0:amd64				install +  libss2:amd64					install +  libssh2-1:amd64					install +  libstdc++-4.9-dev:amd64				install +  libstdc++6:amd64				install +  libsystemd0:amd64				install +  libtext-charwidth-perl				install +  libtext-iconv-perl				install +  libtext-wrapi18n-perl				install +  libtimedate-perl				install +  libtinfo5:amd64					install +  libtsan0:amd64					install +  libubsan0:amd64					install +  libudev1:amd64					install +  libusb-0.1-4:amd64				install +  libustr-1.0-1:amd64				install +  libuuid1:amd64					install +  libxapian22					install +  linux-libc-dev:amd64				install +  login						install +  lsb-base					install +  make						install +  mawk						install +  mc						install +  mc-data						install +  mount						install +  multiarch-support				install +  ncurses-base					install +  ncurses-bin					install +  passwd						install +  patch						install +  perl						install +  perl-base					install +  perl-modules					install +  procps						install +  readline-common					install +  sed						install +  sensible-utils					install +  startpar					install +  systemd						install +  systemd-sysv					install +  sysv-rc						install +  sysvinit-utils					install +  tar						install +  tzdata						install +  udev						install +  util-linux					install +  xz-utils					install +  zlib1g:amd64					install +0m27.5s DEBUG: Command ok: ['chroot', '/tmp/tmpDXAZc1', 'dpkg', '--get-selections', '*'] +0m27.5s DEBUG: Starting command: ['chroot', '/tmp/tmpDXAZc1', 'dpkg-divert', '--list'] +0m27.6s DUMP:  +  diversion of /usr/share/man/man1/sh.1.gz to /usr/share/man/man1/sh.distrib.1.gz by dash +  diversion of /bin/sh to /bin/sh.distrib by dash +0m27.6s DEBUG: Command ok: ['chroot', '/tmp/tmpDXAZc1', 'dpkg-divert', '--list'] +0m27.6s INFO: apt-cache does not know about any of the requested packages +0m27.6s DEBUG: Starting command: ['lsof', '-w', '+D', '/tmp/tmpDXAZc1'] +0m28.2s DEBUG: Command failed (status=1), but ignoring error: ['lsof', '-w', '+D', '/tmp/tmpDXAZc1'] +0m29.7s DEBUG: No broken symlinks as far as we can find. +0m29.7s DEBUG: Starting command: ['lsof', '-w', '+D', '/tmp/tmpDXAZc1'] +0m30.4s DEBUG: Command failed (status=1), but ignoring error: ['lsof', '-w', '+D', '/tmp/tmpDXAZc1'] +0m31.9s DEBUG: No broken symlinks as far as we can find. +0m31.9s DEBUG: Copying bitz-server_0.1.6-1_amd64.deb, bitz-server-doc_0.1.6-1_all.deb, libicap-dev_0.1.6-1_amd64.deb, libicap0_0.1.6-1_amd64.deb, bitz-server-dbg_0.1.6-1_amd64.deb, libicap0-dbg_0.1.6-1_amd64.deb to /tmp/tmpDXAZc1/tmp +0m31.9s DEBUG: Starting command: ['chroot', '/tmp/tmpDXAZc1', 'dpkg', '-i', 'tmp/bitz-server_0.1.6-1_amd64.deb', 'tmp/bitz-server-doc_0.1.6-1_all.deb', 'tmp/libicap-dev_0.1.6-1_amd64.deb', 'tmp/libicap0_0.1.6-1_amd64.deb', 'tmp/bitz-server-dbg_0.1.6-1_amd64.deb', 'tmp/libicap0-dbg_0.1.6-1_amd64.deb'] +0m39.5s DUMP:  +  Selecting previously unselected package bitz-server. +  (Reading database ... 12464 files and directories currently installed.) +  Preparing to unpack .../bitz-server_0.1.6-1_amd64.deb ... +  Unpacking bitz-server (0.1.6-1) ... +  Selecting previously unselected package bitz-server-doc. +  Preparing to unpack .../bitz-server-doc_0.1.6-1_all.deb ... +  Unpacking bitz-server-doc (0.1.6-1) ... +  Selecting previously unselected package libicap-dev:amd64. +  Preparing to unpack .../libicap-dev_0.1.6-1_amd64.deb ... +  Unpacking libicap-dev:amd64 (0.1.6-1) ... +  Selecting previously unselected package libicap0:amd64. +  Preparing to unpack tmp/libicap0_0.1.6-1_amd64.deb ... +  Unpacking libicap0:amd64 (0.1.6-1) ... +  Selecting previously unselected package bitz-server-dbg. +  Preparing to unpack .../bitz-server-dbg_0.1.6-1_amd64.deb ... +  Unpacking bitz-server-dbg (0.1.6-1) ... +  Selecting previously unselected package libicap0-dbg:amd64. +  Preparing to unpack .../libicap0-dbg_0.1.6-1_amd64.deb ... +  Unpacking libicap0-dbg:amd64 (0.1.6-1) ... +  dpkg: dependency problems prevent configuration of bitz-server: +   bitz-server depends on libconfig++9; however: +    Package libconfig++9 is not installed. +   bitz-server depends on liblog4cpp5; however: +    Package liblog4cpp5 is not installed. +   bitz-server depends on init-system-helpers (>= 1.18~); however: +    Package init-system-helpers is not installed. +   +  dpkg: error processing package bitz-server (--install): +   dependency problems - leaving unconfigured +  Setting up bitz-server-doc (0.1.6-1) ... +  Setting up libicap0:amd64 (0.1.6-1) ... +  dpkg: dependency problems prevent configuration of bitz-server-dbg: +   bitz-server-dbg depends on bitz-server (= 0.1.6-1); however: +    Package bitz-server is not configured yet. +   +  dpkg: error processing package bitz-server-dbg (--install): +   dependency problems - leaving unconfigured +  Setting up libicap0-dbg:amd64 (0.1.6-1) ... +  Setting up libicap-dev:amd64 (0.1.6-1) ... +  Processing triggers for systemd (215-17) ... +  Processing triggers for libc-bin (2.19-18) ... +  Errors were encountered while processing: +   bitz-server +   bitz-server-dbg +0m39.5s DEBUG: Command failed (status=1), but ignoring error: ['chroot', '/tmp/tmpDXAZc1', 'dpkg', '-i', 'tmp/bitz-server_0.1.6-1_amd64.deb', 'tmp/bitz-server-doc_0.1.6-1_all.deb', 'tmp/libicap-dev_0.1.6-1_amd64.deb', 'tmp/libicap0_0.1.6-1_amd64.deb', 'tmp/bitz-server-dbg_0.1.6-1_amd64.deb', 'tmp/libicap0-dbg_0.1.6-1_amd64.deb'] +0m39.5s DEBUG: Starting command: ['chroot', '/tmp/tmpDXAZc1', 'apt-get', '-yf', 'install'] +0m45.7s DUMP:  +  Reading package lists... +  Building dependency tree... +  Reading state information... +  Correcting dependencies... Done +  The following extra packages will be installed: +    init-system-helpers libconfig++9 liblog4cpp5 +  The following NEW packages will be installed: +    init-system-helpers libconfig++9 liblog4cpp5 +  0 upgraded, 3 newly installed, 0 to remove and 0 not upgraded. +  2 not fully installed or removed. +  Need to get 183 kB of archives. +  After this operation, 515 kB of additional disk space will be used. +  Get:1 http://mirror.1und1.de/debian/ sid/main libconfig++9 amd64 1.4.9-2 [38.5 kB] +  Get:2 http://mirror.1und1.de/debian/ sid/main liblog4cpp5 amd64 1.0-4 [129 kB] +  Get:3 http://mirror.1und1.de/debian/ sid/main init-system-helpers all 1.23 [15.2 kB] +  debconf: delaying package configuration, since apt-utils is not installed +  Fetched 183 kB in 0s (366 kB/s) +  Selecting previously unselected package libconfig++9:amd64.
 +  (Reading database ... 
(Reading database ... 5%
(Reading database ... 10%
(Reading database ... 15%
(Reading database ... 20%
(Reading database ... 25%
(Reading database ... 30%
(Reading database ... 35%
(Reading database ... 40%
(Reading database ... 45%
(Reading database ... 50%
(Reading database ... 55%
(Reading database ... 60%
(Reading database ... 65%
(Reading database ... 70%
(Reading database ... 75%
(Reading database ... 80%
(Reading database ... 85%
(Reading database ... 90%
(Reading database ... 95%
(Reading database ... 100%
(Reading database ... 12812 files and directories currently installed.)
 +  Preparing to unpack .../libconfig++9_1.4.9-2_amd64.deb ...
 +  Unpacking libconfig++9:amd64 (1.4.9-2) ...
 +  Selecting previously unselected package liblog4cpp5.
 +  Preparing to unpack .../liblog4cpp5_1.0-4_amd64.deb ...
 +  Unpacking liblog4cpp5 (1.0-4) ...
 +  Selecting previously unselected package init-system-helpers.
 +  Preparing to unpack .../init-system-helpers_1.23_all.deb ...
 +  Unpacking init-system-helpers (1.23) ...
 +  Setting up libconfig++9:amd64 (1.4.9-2) ...
 +  Setting up liblog4cpp5 (1.0-4) ...
 +  Setting up init-system-helpers (1.23) ...
 +  Setting up bitz-server (0.1.6-1) ...
 +  invoke-rc.d: policy-rc.d denied execution of start.
 +  Setting up bitz-server-dbg (0.1.6-1) ...
 +  Processing triggers for libc-bin (2.19-18) ...
 +  Processing triggers for systemd (215-17) ...
 +0m45.7s DEBUG: Command ok: ['chroot', '/tmp/tmpDXAZc1', 'apt-get', '-yf', 'install'] +0m45.7s DEBUG: Starting command: ['chroot', '/tmp/tmpDXAZc1', 'dpkg-query', '-f', '${Package} ${Status}\n', '-W', 'bitz-server', 'bitz-server-doc', 'libicap-dev', 'libicap0', 'bitz-server-dbg', 'libicap0-dbg'] +0m45.7s DUMP:  +  bitz-server install ok installed +  bitz-server-dbg install ok installed +  bitz-server-doc install ok installed +  libicap-dev install ok installed +  libicap0 install ok installed +  libicap0-dbg install ok installed +0m45.7s DEBUG: Command ok: ['chroot', '/tmp/tmpDXAZc1', 'dpkg-query', '-f', '${Package} ${Status}\n', '-W', 'bitz-server', 'bitz-server-doc', 'libicap-dev', 'libicap0', 'bitz-server-dbg', 'libicap0-dbg'] +0m45.7s INFO: Installation of ['tmp/bitz-server_0.1.6-1_amd64.deb', 'tmp/bitz-server-doc_0.1.6-1_all.deb', 'tmp/libicap-dev_0.1.6-1_amd64.deb', 'tmp/libicap0_0.1.6-1_amd64.deb', 'tmp/bitz-server-dbg_0.1.6-1_amd64.deb', 'tmp/libicap0-dbg_0.1.6-1_amd64.deb'] ok +0m45.7s DEBUG: Removing /tmp/tmpDXAZc1/tmp/bitz-server_0.1.6-1_amd64.deb +0m45.7s DEBUG: Removing /tmp/tmpDXAZc1/tmp/bitz-server-doc_0.1.6-1_all.deb +0m45.8s DEBUG: Removing /tmp/tmpDXAZc1/tmp/libicap-dev_0.1.6-1_amd64.deb +0m45.8s DEBUG: Removing /tmp/tmpDXAZc1/tmp/libicap0_0.1.6-1_amd64.deb +0m45.8s DEBUG: Removing /tmp/tmpDXAZc1/tmp/bitz-server-dbg_0.1.6-1_amd64.deb +0m45.8s DEBUG: Removing /tmp/tmpDXAZc1/tmp/libicap0-dbg_0.1.6-1_amd64.deb +0m45.8s DEBUG: Starting command: ['lsof', '-w', '+D', '/tmp/tmpDXAZc1'] +0m46.4s DEBUG: Command failed (status=1), but ignoring error: ['lsof', '-w', '+D', '/tmp/tmpDXAZc1'] +0m48.0s DEBUG: No broken symlinks as far as we can find. +0m48.0s DEBUG: Starting command: ['chroot', '/tmp/tmpDXAZc1', 'dpkg', '--get-selections', '*'] +0m48.1s DUMP:  +  acl						install +  adduser						install +  apt						install +  aptitude					install +  aptitude-common					install +  base-files					install +  base-passwd					install +  bash						install +  binutils					install +  bitz-server					install +  bitz-server-dbg					install +  bitz-server-doc					install +  bsdutils					install +  build-essential					install +  bzip2						install +  coreutils					install +  cpp						install +  cpp-4.9						install +  dash						install +  debconf						install +  debconf-i18n					install +  debian-archive-keyring				install +  debianutils					install +  diffutils					install +  dmsetup						install +  dpkg						install +  dpkg-dev					install +  e2fslibs:amd64					install +  e2fsprogs					install +  findutils					install +  g++						install +  g++-4.9						install +  gcc						install +  gcc-4.7-base:amd64				install +  gcc-4.8-base:amd64				install +  gcc-4.9						install +  gcc-4.9-base:amd64				install +  gcc-5-base:amd64				install +  gnupg						install +  gpgv						install +  grep						install +  gzip						install +  hostname					install +  init						install +  init-system-helpers				install +  initscripts					install +  insserv						install +  libacl1:amd64					install +  libapt-pkg4.12:amd64				install +  libasan1:amd64					install +  libatomic1:amd64				install +  libattr1:amd64					install +  libaudit-common					install +  libaudit1:amd64					install +  libblkid1:amd64					install +  libboost-iostreams1.55.0:amd64			install +  libbz2-1.0:amd64				install +  libc-bin					install +  libc-dev-bin					install +  libc6:amd64					install +  libc6-dev:amd64					install +  libcap2:amd64					install +  libcap2-bin					install +  libcilkrts5:amd64				install +  libcloog-isl4:amd64				install +  libcomerr2:amd64				install +  libconfig++9:amd64				install +  libcryptsetup4:amd64				install +  libcwidget3:amd64				install +  libdb5.3:amd64					install +  libdebconfclient0:amd64				install +  libdevmapper1.02.1:amd64			install +  libdpkg-perl					install +  libfdisk1:amd64					install +  libffi6:amd64					install +  libgcc-4.9-dev:amd64				install +  libgcc1:amd64					install +  libgcrypt20:amd64				install +  libgdbm3:amd64					install +  libglib2.0-0:amd64				install +  libgmp10:amd64					install +  libgomp1:amd64					install +  libgpg-error0:amd64				install +  libgpm2:amd64					install +  libicap-dev:amd64				install +  libicap0:amd64					install +  libicap0-dbg:amd64				install +  libisl10:amd64					install +  libisl13:amd64					install +  libitm1:amd64					install +  libkmod2:amd64					install +  liblocale-gettext-perl				install +  liblog4cpp5					install +  liblsan0:amd64					install +  liblzma5:amd64					install +  libmount1:amd64					install +  libmpc3:amd64					install +  libmpfr4:amd64					install +  libncurses5:amd64				install +  libncursesw5:amd64				install +  libpam-modules:amd64				install +  libpam-modules-bin				install +  libpam-runtime					install +  libpam0g:amd64					install +  libpcre3:amd64					install +  libprocps3:amd64				install +  libquadmath0:amd64				install +  libreadline6:amd64				install +  libselinux1:amd64				install +  libsemanage-common				install +  libsemanage1:amd64				install +  libsepol1:amd64					install +  libsigc++-2.0-0c2a:amd64			install +  libslang2:amd64					install +  libsmartcols1:amd64				install +  libsqlite3-0:amd64				install +  libss2:amd64					install +  libssh2-1:amd64					install +  libstdc++-4.9-dev:amd64				install +  libstdc++6:amd64				install +  libsystemd0:amd64				install +  libtext-charwidth-perl				install +  libtext-iconv-perl				install +  libtext-wrapi18n-perl				install +  libtimedate-perl				install +  libtinfo5:amd64					install +  libtsan0:amd64					install +  libubsan0:amd64					install +  libudev1:amd64					install +  libusb-0.1-4:amd64				install +  libustr-1.0-1:amd64				install +  libuuid1:amd64					install +  libxapian22					install +  linux-libc-dev:amd64				install +  login						install +  lsb-base					install +  make						install +  mawk						install +  mc						install +  mc-data						install +  mount						install +  multiarch-support				install +  ncurses-base					install +  ncurses-bin					install +  passwd						install +  patch						install +  perl						install +  perl-base					install +  perl-modules					install +  procps						install +  readline-common					install +  sed						install +  sensible-utils					install +  startpar					install +  systemd						install +  systemd-sysv					install +  sysv-rc						install +  sysvinit-utils					install +  tar						install +  tzdata						install +  udev						install +  util-linux					install +  xz-utils					install +  zlib1g:amd64					install +0m48.1s DEBUG: Command ok: ['chroot', '/tmp/tmpDXAZc1', 'dpkg', '--get-selections', '*'] +0m49.1s DEBUG: Starting command: ['debsums', '--root', '/tmp/tmpDXAZc1', '-ac'] +0m50.3s DEBUG: Command ok: ['debsums', '--root', '/tmp/tmpDXAZc1', '-ac'] +0m50.3s DEBUG: Starting command: ['dpkg-query', '-f', '${Version}\n', '-W', 'adequate'] +0m50.4s DUMP:  +  0.13 +0m50.4s DEBUG: Command ok: ['dpkg-query', '-f', '${Version}\n', '-W', 'adequate'] +0m50.4s INFO: Running adequate version 0.13 now. +0m50.4s DEBUG: Starting command: ['adequate', '--root', '/tmp/tmpDXAZc1', 'bitz-server', 'bitz-server-doc', 'libicap-dev', 'libicap0', 'bitz-server-dbg', 'libicap0-dbg'] +0m50.6s DEBUG: Command ok: ['adequate', '--root', '/tmp/tmpDXAZc1', 'bitz-server', 'bitz-server-doc', 'libicap-dev', 'libicap0', 'bitz-server-dbg', 'libicap0-dbg'] +0m50.6s DEBUG: Starting command: ['chroot', '/tmp/tmpDXAZc1', 'apt-get', 'remove', '--no-install-recommends', 'libconfig++9:amd64', 'libicap-dev:amd64', 'liblog4cpp5', 'libicap0-dbg:amd64', 'libicap0:amd64', 'init-system-helpers', 'bitz-server-dbg', 'bitz-server', 'bitz-server-doc'] +0m55.5s DUMP:  +  Reading package lists... +  Building dependency tree... +  Reading state information... +  The following packages will be REMOVED: +    bitz-server bitz-server-dbg bitz-server-doc init-system-helpers libconfig++9 +    libicap-dev libicap0 libicap0-dbg liblog4cpp5 +  0 upgraded, 0 newly installed, 9 to remove and 0 not upgraded. +  After this operation, 3211 kB disk space will be freed. +  (Reading database ... 
(Reading database ... 5%
(Reading database ... 10%
(Reading database ... 15%
(Reading database ... 20%
(Reading database ... 25%
(Reading database ... 30%
(Reading database ... 35%
(Reading database ... 40%
(Reading database ... 45%
(Reading database ... 50%
(Reading database ... 55%
(Reading database ... 60%
(Reading database ... 65%
(Reading database ... 70%
(Reading database ... 75%
(Reading database ... 80%
(Reading database ... 85%
(Reading database ... 90%
(Reading database ... 95%
(Reading database ... 100%
(Reading database ... 12837 files and directories currently installed.)
 +  Removing bitz-server-dbg (0.1.6-1) ...
 +  Removing bitz-server (0.1.6-1) ...
 +  invoke-rc.d: policy-rc.d denied execution of stop.
 +  Removing bitz-server-doc (0.1.6-1) ...
 +  Removing init-system-helpers (1.23) ...
 +  Removing libconfig++9:amd64 (1.4.9-2) ...
 +  Removing libicap-dev:amd64 (0.1.6-1) ...
 +  Removing libicap0-dbg:amd64 (0.1.6-1) ...
 +  Removing libicap0:amd64 (0.1.6-1) ...
 +  Removing liblog4cpp5 (1.0-4) ...
 +  Processing triggers for libc-bin (2.19-18) ...
 +0m55.5s DEBUG: Command ok: ['chroot', '/tmp/tmpDXAZc1', 'apt-get', 'remove', '--no-install-recommends', 'libconfig++9:amd64', 'libicap-dev:amd64', 'liblog4cpp5', 'libicap0-dbg:amd64', 'libicap0:amd64', 'init-system-helpers', 'bitz-server-dbg', 'bitz-server', 'bitz-server-doc'] +0m55.5s DEBUG: Starting command: ['chroot', '/tmp/tmpDXAZc1', 'dpkg', '--purge', 'libconfig++9:amd64', 'libicap-dev:amd64', 'liblog4cpp5', 'libicap0-dbg:amd64', 'libicap0:amd64', 'init-system-helpers'] +0m56.9s DUMP:  +  (Reading database ... 12468 files and directories currently installed.) +  Removing libconfig++9:amd64 (1.4.9-2) ... +  Purging configuration files for libconfig++9:amd64 (1.4.9-2) ... +  dpkg: warning: ignoring request to remove libicap-dev which isn't installed +  Removing liblog4cpp5 (1.0-4) ... +  Purging configuration files for liblog4cpp5 (1.0-4) ... +  dpkg: warning: ignoring request to remove libicap0-dbg which isn't installed +  Removing libicap0:amd64 (0.1.6-1) ... +  Purging configuration files for libicap0:amd64 (0.1.6-1) ... +  dpkg: warning: ignoring request to remove init-system-helpers which isn't installed +0m56.9s DEBUG: Command ok: ['chroot', '/tmp/tmpDXAZc1', 'dpkg', '--purge', 'libconfig++9:amd64', 'libicap-dev:amd64', 'liblog4cpp5', 'libicap0-dbg:amd64', 'libicap0:amd64', 'init-system-helpers'] +0m56.9s DEBUG: Starting command: ['chroot', '/tmp/tmpDXAZc1', 'dpkg', '--purge', 'bitz-server-dbg', 'bitz-server', 'bitz-server-doc'] +0m57.6s DUMP:  +  dpkg: warning: ignoring request to remove bitz-server-dbg which isn't installed +  (Reading database ... 12468 files and directories currently installed.) +  Removing bitz-server (0.1.6-1) ... +  Purging configuration files for bitz-server (0.1.6-1) ... +  dpkg: warning: ignoring request to remove bitz-server-doc which isn't installed +0m57.6s DEBUG: Command ok: ['chroot', '/tmp/tmpDXAZc1', 'dpkg', '--purge', 'bitz-server-dbg', 'bitz-server', 'bitz-server-doc'] +0m57.6s DEBUG: Starting command: ['chroot', '/tmp/tmpDXAZc1', 'dpkg', '--purge', '--pending'] +0m57.6s DEBUG: Command ok: ['chroot', '/tmp/tmpDXAZc1', 'dpkg', '--purge', '--pending'] +0m57.6s DEBUG: Starting command: ['chroot', '/tmp/tmpDXAZc1', 'dpkg', '--remove', '--pending'] +0m57.7s DEBUG: Command ok: ['chroot', '/tmp/tmpDXAZc1', 'dpkg', '--remove', '--pending'] +0m57.7s DEBUG: Starting command: ['lsof', '-w', '+D', '/tmp/tmpDXAZc1'] +0m58.3s DEBUG: Command failed (status=1), but ignoring error: ['lsof', '-w', '+D', '/tmp/tmpDXAZc1'] +0m59.9s DEBUG: No broken symlinks as far as we can find. +0m59.9s DEBUG: Starting command: ['chroot', '/tmp/tmpDXAZc1', 'dpkg-divert', '--list'] +0m59.9s DUMP:  +  diversion of /usr/share/man/man1/sh.1.gz to /usr/share/man/man1/sh.distrib.1.gz by dash +  diversion of /bin/sh to /bin/sh.distrib by dash +0m59.9s DEBUG: Command ok: ['chroot', '/tmp/tmpDXAZc1', 'dpkg-divert', '--list'] +0m59.9s DEBUG: Starting command: ['chroot', '/tmp/tmpDXAZc1', 'apt-get', 'clean'] +0m59.9s DEBUG: Command ok: ['chroot', '/tmp/tmpDXAZc1', 'apt-get', 'clean'] +1m2.2s ERROR: FAIL: Package purging left files on system: +  /etc/systemd/system/bitz-server.service -> /dev/null	 not owned +  /var/lib/systemd/deb-systemd-helper-enabled/	 not owned +  /var/lib/systemd/deb-systemd-helper-enabled/bitz-server.service.dsh-also	 not owned +  /var/lib/systemd/deb-systemd-helper-masked/	 not owned +  /var/lib/systemd/deb-systemd-helper-masked/bitz-server.service	 not owned + +1m2.3s ERROR: FAIL: Installation and purging test. +1m2.9s DEBUG: Starting command: ['chroot', '/tmp/tmpDXAZc1', 'umount', '/proc'] +1m2.9s DEBUG: Command ok: ['chroot', '/tmp/tmpDXAZc1', 'umount', '/proc'] +1m2.9s DEBUG: Starting command: ['chroot', '/tmp/tmpDXAZc1', 'umount', '/dev/pts'] +1m3.0s DEBUG: Command ok: ['chroot', '/tmp/tmpDXAZc1', 'umount', '/dev/pts'] +1m3.0s DEBUG: Starting command: ['rm', '-rf', '--one-file-system', '/tmp/tmpDXAZc1'] +1m3.4s DEBUG: Command ok: ['rm', '-rf', '--one-file-system', '/tmp/tmpDXAZc1'] +1m3.4s DEBUG: Removed directory tree at /tmp/tmpDXAZc1 +1m3.4s ERROR: piuparts run ends. diff --git a/debian/libicap-dev.docs b/debian/libicap-dev.docs new file mode 100644 index 0000000..42061c0 --- /dev/null +++ b/debian/libicap-dev.docs @@ -0,0 +1 @@ +README.md
\ No newline at end of file diff --git a/debian/libicap-dev.install b/debian/libicap-dev.install new file mode 100644 index 0000000..34bfc00 --- /dev/null +++ b/debian/libicap-dev.install @@ -0,0 +1,2 @@ +usr/include +usr/lib/*/lib*.so diff --git a/debian/libicap0.install b/debian/libicap0.install new file mode 100644 index 0000000..3ddde58 --- /dev/null +++ b/debian/libicap0.install @@ -0,0 +1 @@ +usr/lib/*/lib*.so.* diff --git a/debian/libicap0.symbols b/debian/libicap0.symbols new file mode 100644 index 0000000..4b8c174 --- /dev/null +++ b/debian/libicap0.symbols @@ -0,0 +1,193 @@ +libicap.so.0 libicap0 #MINVER# + (c++)"socketlibrary::SocketException::SocketException(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool)@Base" 0.1.6 + (c++)"socketlibrary::SocketException::SocketException(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool)@Base" 0.1.6 + (c++)"socketlibrary::SocketException::~SocketException()@Base" 0.1.6 + (c++)"socketlibrary::SocketException::~SocketException()@Base" 0.1.6 + (c++)"socketlibrary::SocketException::~SocketException()@Base" 0.1.6 + (c++)"socketlibrary::TCPServerSocket::accept()@Base" 0.1.6 + (c++)"socketlibrary::TCPServerSocket::setListen(int)@Base" 0.1.6 + (c++)"socketlibrary::TCPServerSocket::TCPServerSocket(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned short, int)@Base" 0.1.6 + (c++)"socketlibrary::TCPServerSocket::TCPServerSocket(unsigned short, int)@Base" 0.1.6 + (c++)"socketlibrary::TCPServerSocket::TCPServerSocket(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned short, int)@Base" 0.1.6 + (c++)"socketlibrary::TCPServerSocket::TCPServerSocket(unsigned short, int)@Base" 0.1.6 + (c++)"socketlibrary::TCPServerSocketM::getWaitingClients(std::vector<socketlibrary::TCPSocket*, std::allocator<socketlibrary::TCPSocket*> >&)@Base" 0.1.6 + (c++)"socketlibrary::TCPServerSocketM::pendingConnections()@Base" 0.1.6 + (c++)"socketlibrary::TCPServerSocketM::closeClientConnection(socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"socketlibrary::TCPServerSocketM::accept()@Base" 0.1.6 + (c++)"socketlibrary::TCPServerSocketM::TCPServerSocketM(unsigned short, int)@Base" 0.1.6 + (c++)"socketlibrary::TCPServerSocketM::TCPServerSocketM(unsigned short, int)@Base" 0.1.6 + (c++)"socketlibrary::CommunicatingSocket::getForeignPort()@Base" 0.1.6 + (c++)"socketlibrary::CommunicatingSocket::getForeignAddress[abi:cxx11]()@Base" 0.1.6 + (c++)"socketlibrary::CommunicatingSocket::peek(void*, int)@Base" 0.1.6 + (c++)"socketlibrary::CommunicatingSocket::recv(void*, int)@Base" 0.1.6 + (c++)"socketlibrary::CommunicatingSocket::send(void const*, int)@Base" 0.1.6 + (c++)"socketlibrary::CommunicatingSocket::connect(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned short)@Base" 0.1.6 + (c++)"socketlibrary::CommunicatingSocket::readLine(char*, int, char)@Base" 0.1.6 + (c++)"socketlibrary::CommunicatingSocket::CommunicatingSocket(int)@Base" 0.1.6 + (c++)"socketlibrary::CommunicatingSocket::CommunicatingSocket(int, int)@Base" 0.1.6 + (c++)"socketlibrary::CommunicatingSocket::CommunicatingSocket(int)@Base" 0.1.6 + (c++)"socketlibrary::CommunicatingSocket::CommunicatingSocket(int, int)@Base" 0.1.6 + (c++)"socketlibrary::Socket::getLocalPort()@Base" 0.1.6 + (c++)"socketlibrary::Socket::setLocalPort(unsigned short)@Base" 0.1.6 + (c++)"socketlibrary::Socket::resolveService(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"socketlibrary::Socket::getLocalAddress[abi:cxx11]()@Base" 0.1.6 + (c++)"socketlibrary::Socket::setLocalAddressAndPort(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned short)@Base" 0.1.6 + (c++)"socketlibrary::Socket::cleanUp()@Base" 0.1.6 + (c++)"socketlibrary::Socket::Socket(int)@Base" 0.1.6 + (c++)"socketlibrary::Socket::Socket(int, int)@Base" 0.1.6 + (c++)"socketlibrary::Socket::Socket(int)@Base" 0.1.6 + (c++)"socketlibrary::Socket::Socket(int, int)@Base" 0.1.6 + (c++)"socketlibrary::Socket::~Socket()@Base" 0.1.6 + (c++)"socketlibrary::Socket::~Socket()@Base" 0.1.6 + (c++)"socketlibrary::fillAddr(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned short, sockaddr_in&)@Base" 0.1.6 + (c++)"socketlibrary::TCPSocket::TCPSocket(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned short)@Base" 0.1.6 + (c++)"socketlibrary::TCPSocket::TCPSocket(int)@Base" 0.1.6 + (c++)"socketlibrary::TCPSocket::TCPSocket()@Base" 0.1.6 + (c++)"socketlibrary::TCPSocket::TCPSocket(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned short)@Base" 0.1.6 + (c++)"socketlibrary::TCPSocket::TCPSocket(int)@Base" 0.1.6 + (c++)"socketlibrary::TCPSocket::TCPSocket()@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::disconnect()@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::leaveGroup(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::setBroadcast()@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::setMulticastTTL(unsigned char)@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::sendTo(void const*, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned short)@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::recvFrom(void*, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, unsigned short&)@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::joinGroup(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::UDPSocket(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned short)@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::UDPSocket(unsigned short)@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::UDPSocket()@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::UDPSocket(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned short)@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::UDPSocket(unsigned short)@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::UDPSocket()@Base" 0.1.6 + (c++)"icap::RequestHeader::read_header(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"icap::RequestHeader::RequestHeader(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"icap::RequestHeader::RequestHeader(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"icap::RequestHeader::~RequestHeader()@Base" 0.1.6 + (c++)"icap::RequestHeader::~RequestHeader()@Base" 0.1.6 + (c++)"icap::RequestHeader::~RequestHeader()@Base" 0.1.6 + (c++)"icap::ResponseHeader::init_defaults()@Base" 0.1.6 + (c++)"icap::ResponseHeader::generate_istag()@Base" 0.1.6 + (c++)"icap::ResponseHeader::update_timestamp()@Base" 0.1.6 + (c++)"icap::ResponseHeader::ResponseHeader(icap::ResponseHeader::status_t)@Base" 0.1.6 + (c++)"icap::ResponseHeader::ResponseHeader(icap::ResponseHeader::status_t)@Base" 0.1.6 + (c++)"icap::ResponseHeader::~ResponseHeader()@Base" 0.1.6 + (c++)"icap::ResponseHeader::~ResponseHeader()@Base" 0.1.6 + (c++)"icap::ResponseHeader::~ResponseHeader()@Base" 0.1.6 + (c++)"icap::util::read_chunk(socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"icap::util::read_chunked[abi:cxx11](socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"icap::util::send_chunked(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"icap::util::send_headers(icap::Header*, socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"icap::util::read_req_data(icap::Request*, socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"icap::util::send_response(icap::Response*, socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"icap::util::read_chunk_size(socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"icap::util::read_req_header(socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"icap::util::response_status[abi:cxx11](icap::ResponseHeader::status_t const&)@Base" 0.1.6 + (c++)"icap::util::read_chunk_header(socketlibrary::TCPSocket*, icap::util::chunk_t&)@Base" 0.1.6 + (c++)"icap::util::read_chunked_payload(socketlibrary::TCPSocket*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)@Base" 0.1.6 + (c++)"icap::util::read_req_continue_data(icap::Request*, socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > icap::util::itoa<int>(int)@Base" 0.1.6 + (c++)"std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > icap::util::itoa<long>(long)@Base" 0.1.6 + (c++)"icap::util::trim(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)@Base" 0.1.6 + (c++)"icap::util::ltrim(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)@Base" 0.1.6 + (c++)"icap::util::rtrim(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)@Base" 0.1.6 + (c++)"icap::util::split(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"icap::util::chunk_t::~chunk_t()@Base" 0.1.6 + (c++)"icap::util::chunk_t::~chunk_t()@Base" 0.1.6 + (c++)"icap::util::dectohex[abi:cxx11](unsigned int const&)@Base" 0.1.6 + (c++)"icap::util::hextodec(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"icap::util::read_data[abi:cxx11](socketlibrary::TCPSocket*, int)@Base" 0.1.6 + (c++)"icap::util::read_line[abi:cxx11](socketlibrary::TCPSocket*, bool)@Base" 0.1.6 + (c++)"icap::util::read_line(socketlibrary::TCPSocket*, char*, int, bool)@Base" 0.1.6 + (c++)"icap::util::send_data(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"icap::util::send_line(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"icap::Header::attach_encapsulated(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)@Base" 0.1.6 + (c++)"icap::Header::encapsulated_header(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"icap::Header::update_encapsulated(icap::payload_t const&)@Base" 0.1.6 + (c++)"icap::Header::encapsulated_header_str[abi:cxx11]()@Base" 0.1.6 + (c++)"icap::Header::sort_encapsulated_header[abi:cxx11]()@Base" 0.1.6 + (c++)"icap::Header::value(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"icap::Header::attach(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)@Base" 0.1.6 + (c++)"icap::Header::remove(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)@Base" 0.1.6 + (c++)"icap::Header::Header()@Base" 0.1.6 + (c++)"icap::Header::Header()@Base" 0.1.6 + (c++)"icap::Header::~Header()@Base" 0.1.6 + (c++)"icap::Header::~Header()@Base" 0.1.6 + (c++)"icap::Header::~Header()@Base" 0.1.6 + (c++)"icap::Request::preview_size()@Base" 0.1.6 + (c++)"icap::Request::payload(icap::payload_t)@Base" 0.1.6 + (c++)"icap::Request::Request(icap::RequestHeader*)@Base" 0.1.6 + (c++)"icap::Request::Request(icap::RequestHeader*)@Base" 0.1.6 + (c++)"icap::Request::~Request()@Base" 0.1.6 + (c++)"icap::Request::~Request()@Base" 0.1.6 + (c++)"icap::Request::~Request()@Base" 0.1.6 + (c++)"icap::Response::payload(icap::payload_t)@Base" 0.1.6 + (c++)"icap::Response::Response(icap::ResponseHeader::status_t)@Base" 0.1.6 + (c++)"icap::Response::Response(icap::ResponseHeader*)@Base" 0.1.6 + (c++)"icap::Response::Response(icap::ResponseHeader::status_t)@Base" 0.1.6 + (c++)"icap::Response::Response(icap::ResponseHeader*)@Base" 0.1.6 + (c++)"icap::Response::~Response()@Base" 0.1.6 + (c++)"icap::Response::~Response()@Base" 0.1.6 + (c++)"icap::Response::~Response()@Base" 0.1.6 + (c++)"icap::payload_t::~payload_t()@Base" 0.1.6 + (c++)"icap::payload_t::~payload_t()@Base" 0.1.6 + (c++)"socketlibrary::SocketException::what() const@Base" 0.1.6 + (c++)"icap::RequestHeader::uri[abi:cxx11]() const@Base" 0.1.6 + (c++)"icap::RequestHeader::method[abi:cxx11]() const@Base" 0.1.6 + (c++)"icap::RequestHeader::request() const@Base" 0.1.6 + (c++)"icap::RequestHeader::protocol[abi:cxx11]() const@Base" 0.1.6 + (c++)"icap::RequestHeader::raw_data[abi:cxx11]() const@Base" 0.1.6 + (c++)"icap::ResponseHeader::status() const@Base" 0.1.6 + (c++)"icap::ResponseHeader::protocol[abi:cxx11]() const@Base" 0.1.6 + (c++)"icap::Header::headers[abi:cxx11]() const@Base" 0.1.6 + (c++)"icap::Request::header() const@Base" 0.1.6 + (c++)"icap::Request::payload() const@Base" 0.1.6 + (c++)"icap::Response::header() const@Base" 0.1.6 + (c++)"icap::Response::payload() const@Base" 0.1.6 + (c++)"std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::_M_insert_aux(__gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::~vector()@Base" 0.1.6 + (c++)"std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::~vector()@Base" 0.1.6 + (c++)"std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::operator=(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&)@Base" 0.1.6 + (c++)"std::vector<socketlibrary::TCPSocket*, std::allocator<socketlibrary::TCPSocket*> >::_M_insert_aux(__gnu_cxx::__normal_iterator<socketlibrary::TCPSocket**, std::vector<socketlibrary::TCPSocket*, std::allocator<socketlibrary::TCPSocket*> > >, socketlibrary::TCPSocket* const&)@Base" 0.1.6 + (c++)"std::vector<socketlibrary::TCPSocket*, std::allocator<socketlibrary::TCPSocket*> >::_M_fill_insert(__gnu_cxx::__normal_iterator<socketlibrary::TCPSocket**, std::vector<socketlibrary::TCPSocket*, std::allocator<socketlibrary::TCPSocket*> > >, unsigned long, socketlibrary::TCPSocket* const&)@Base" 0.1.6 + (c++)"std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > >::~vector()@Base" 0.1.6 + (c++)"std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > >::~vector()@Base" 0.1.6 + (c++)"std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > >::operator=(std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > const&)@Base" 0.1.6 + (c++)"std::__cxx11::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::~basic_stringbuf()@Base" 0.1.6 + (c++)"std::__cxx11::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::~basic_stringbuf()@Base" 0.1.6 + (c++)"std::__cxx11::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::~basic_stringbuf()@Base" 0.1.6 + (c++)"std::_Rb_tree<icap::ResponseHeader::status_t, std::pair<icap::ResponseHeader::status_t const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::_Select1st<std::pair<icap::ResponseHeader::status_t const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<icap::ResponseHeader::status_t>, std::allocator<std::pair<icap::ResponseHeader::status_t const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::_M_get_insert_unique_pos(icap::ResponseHeader::status_t const&)@Base" 0.1.6 + (c++)"std::_Rb_tree<icap::ResponseHeader::status_t, std::pair<icap::ResponseHeader::status_t const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::_Select1st<std::pair<icap::ResponseHeader::status_t const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<icap::ResponseHeader::status_t>, std::allocator<std::pair<icap::ResponseHeader::status_t const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::_M_get_insert_hint_unique_pos(std::_Rb_tree_const_iterator<std::pair<icap::ResponseHeader::status_t const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, icap::ResponseHeader::status_t const&)@Base" 0.1.6 + (c++)"std::_Rb_tree<icap::ResponseHeader::status_t, std::pair<icap::ResponseHeader::status_t const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::_Select1st<std::pair<icap::ResponseHeader::status_t const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<icap::ResponseHeader::status_t>, std::allocator<std::pair<icap::ResponseHeader::status_t const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::_M_erase(std::_Rb_tree_node<std::pair<icap::ResponseHeader::status_t const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >*)@Base" 0.1.6 + (c++)"std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::equal_range(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::_M_get_insert_unique_pos(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::_M_get_insert_hint_unique_pos(std::_Rb_tree_const_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >* std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::_M_copy<std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::_Reuse_or_alloc_node>(std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const*, std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >*, std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::_Reuse_or_alloc_node&)@Base" 0.1.6 + (c++)"std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::_M_erase(std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >*)@Base" 0.1.6 + (c++)"std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> > >::_M_get_insert_unique_pos(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> > >::_M_get_insert_hint_unique_pos(std::_Rb_tree_const_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> > >::find(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> > >::_M_erase(std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> >*)@Base" 0.1.6 + (c++)"void std::__make_heap<__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, __gnu_cxx::__ops::_Iter_comp_iter<icap::Header::encapsulated_header_compare> >(__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, __gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, __gnu_cxx::__ops::_Iter_comp_iter<icap::Header::encapsulated_header_compare>)@Base" 0.1.6 + (c++)"void std::__adjust_heap<__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, long, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, __gnu_cxx::__ops::_Iter_comp_iter<icap::Header::encapsulated_header_compare> >(__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, long, long, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, __gnu_cxx::__ops::_Iter_comp_iter<icap::Header::encapsulated_header_compare>)@Base" 0.1.6 + (c++)"void std::__insertion_sort<__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, __gnu_cxx::__ops::_Iter_comp_iter<icap::Header::encapsulated_header_compare> >(__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, __gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, __gnu_cxx::__ops::_Iter_comp_iter<icap::Header::encapsulated_header_compare>)@Base" 0.1.6 + (c++)"void std::__introsort_loop<__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, long, __gnu_cxx::__ops::_Iter_comp_iter<icap::Header::encapsulated_header_compare> >(__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, __gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, long, __gnu_cxx::__ops::_Iter_comp_iter<icap::Header::encapsulated_header_compare>)@Base" 0.1.6 + (c++)"void std::__unguarded_linear_insert<__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, __gnu_cxx::__ops::_Val_comp_iter<icap::Header::encapsulated_header_compare> >(__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, __gnu_cxx::__ops::_Val_comp_iter<icap::Header::encapsulated_header_compare>)@Base" 0.1.6 + (c++)"__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > std::__find_if<__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__ops::_Iter_pred<std::unary_negate<std::pointer_to_unary_function<int, int> > > >(__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__ops::_Iter_pred<std::unary_negate<std::pointer_to_unary_function<int, int> > >, std::random_access_iterator_tag)@Base" 0.1.6 + (c++)"typeinfo for socketlibrary::SocketException@Base" 0.1.6 + (c++)"typeinfo for icap::RequestHeader@Base" 0.1.6 + (c++)"typeinfo for icap::ResponseHeader@Base" 0.1.6 + (c++)"typeinfo for icap::Header@Base" 0.1.6 + (c++)"typeinfo for icap::Request@Base" 0.1.6 + (c++)"typeinfo for icap::Response@Base" 0.1.6 + (c++)"typeinfo name for socketlibrary::SocketException@Base" 0.1.6 + (c++)"typeinfo name for icap::RequestHeader@Base" 0.1.6 + (c++)"typeinfo name for icap::ResponseHeader@Base" 0.1.6 + (c++)"typeinfo name for icap::Header@Base" 0.1.6 + (c++)"typeinfo name for icap::Request@Base" 0.1.6 + (c++)"typeinfo name for icap::Response@Base" 0.1.6 + (c++)"vtable for socketlibrary::SocketException@Base" 0.1.6 + (c++)"vtable for icap::RequestHeader@Base" 0.1.6 + (c++)"vtable for icap::ResponseHeader@Base" 0.1.6 + (c++)"vtable for icap::Header@Base" 0.1.6 + (c++)"vtable for icap::Request@Base" 0.1.6 + (c++)"vtable for icap::Response@Base" 0.1.6 diff --git a/debian/libicap0.symbols.i386 b/debian/libicap0.symbols.i386 new file mode 100644 index 0000000..f827875 --- /dev/null +++ b/debian/libicap0.symbols.i386 @@ -0,0 +1,187 @@ +libicap.so.0 libicap0 #MINVER# + (c++)"socketlibrary::SocketException::SocketException(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool)@Base" 0.1.6 + (c++)"socketlibrary::SocketException::SocketException(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool)@Base" 0.1.6 + (c++)"socketlibrary::SocketException::~SocketException()@Base" 0.1.6 + (c++)"socketlibrary::SocketException::~SocketException()@Base" 0.1.6 + (c++)"socketlibrary::SocketException::~SocketException()@Base" 0.1.6 + (c++)"socketlibrary::TCPServerSocket::accept()@Base" 0.1.6 + (c++)"socketlibrary::TCPServerSocket::setListen(int)@Base" 0.1.6 + (c++)"socketlibrary::TCPServerSocket::TCPServerSocket(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned short, int)@Base" 0.1.6 + (c++)"socketlibrary::TCPServerSocket::TCPServerSocket(unsigned short, int)@Base" 0.1.6 + (c++)"socketlibrary::TCPServerSocket::TCPServerSocket(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned short, int)@Base" 0.1.6 + (c++)"socketlibrary::TCPServerSocket::TCPServerSocket(unsigned short, int)@Base" 0.1.6 + (c++)"socketlibrary::TCPServerSocketM::getWaitingClients(std::vector<socketlibrary::TCPSocket*, std::allocator<socketlibrary::TCPSocket*> >&)@Base" 0.1.6 + (c++)"socketlibrary::TCPServerSocketM::pendingConnections()@Base" 0.1.6 + (c++)"socketlibrary::TCPServerSocketM::closeClientConnection(socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"socketlibrary::TCPServerSocketM::accept()@Base" 0.1.6 + (c++)"socketlibrary::TCPServerSocketM::TCPServerSocketM(unsigned short, int)@Base" 0.1.6 + (c++)"socketlibrary::TCPServerSocketM::TCPServerSocketM(unsigned short, int)@Base" 0.1.6 + (c++)"socketlibrary::CommunicatingSocket::getForeignPort()@Base" 0.1.6 + (c++)"socketlibrary::CommunicatingSocket::getForeignAddress[abi:cxx11]()@Base" 0.1.6 + (c++)"socketlibrary::CommunicatingSocket::peek(void*, int)@Base" 0.1.6 + (c++)"socketlibrary::CommunicatingSocket::recv(void*, int)@Base" 0.1.6 + (c++)"socketlibrary::CommunicatingSocket::send(void const*, int)@Base" 0.1.6 + (c++)"socketlibrary::CommunicatingSocket::connect(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned short)@Base" 0.1.6 + (c++)"socketlibrary::CommunicatingSocket::readLine(char*, int, char)@Base" 0.1.6 + (c++)"socketlibrary::CommunicatingSocket::CommunicatingSocket(int)@Base" 0.1.6 + (c++)"socketlibrary::CommunicatingSocket::CommunicatingSocket(int, int)@Base" 0.1.6 + (c++)"socketlibrary::CommunicatingSocket::CommunicatingSocket(int)@Base" 0.1.6 + (c++)"socketlibrary::CommunicatingSocket::CommunicatingSocket(int, int)@Base" 0.1.6 + (c++)"socketlibrary::Socket::getLocalPort()@Base" 0.1.6 + (c++)"socketlibrary::Socket::setLocalPort(unsigned short)@Base" 0.1.6 + (c++)"socketlibrary::Socket::resolveService(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"socketlibrary::Socket::getLocalAddress[abi:cxx11]()@Base" 0.1.6 + (c++)"socketlibrary::Socket::setLocalAddressAndPort(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned short)@Base" 0.1.6 + (c++)"socketlibrary::Socket::cleanUp()@Base" 0.1.6 + (c++)"socketlibrary::Socket::Socket(int)@Base" 0.1.6 + (c++)"socketlibrary::Socket::Socket(int, int)@Base" 0.1.6 + (c++)"socketlibrary::Socket::Socket(int)@Base" 0.1.6 + (c++)"socketlibrary::Socket::Socket(int, int)@Base" 0.1.6 + (c++)"socketlibrary::Socket::~Socket()@Base" 0.1.6 + (c++)"socketlibrary::Socket::~Socket()@Base" 0.1.6 + (c++)"socketlibrary::fillAddr(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned short, sockaddr_in&)@Base" 0.1.6 + (c++)"socketlibrary::TCPSocket::TCPSocket(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned short)@Base" 0.1.6 + (c++)"socketlibrary::TCPSocket::TCPSocket(int)@Base" 0.1.6 + (c++)"socketlibrary::TCPSocket::TCPSocket()@Base" 0.1.6 + (c++)"socketlibrary::TCPSocket::TCPSocket(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned short)@Base" 0.1.6 + (c++)"socketlibrary::TCPSocket::TCPSocket(int)@Base" 0.1.6 + (c++)"socketlibrary::TCPSocket::TCPSocket()@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::disconnect()@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::leaveGroup(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::setBroadcast()@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::setMulticastTTL(unsigned char)@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::sendTo(void const*, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned short)@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::recvFrom(void*, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, unsigned short&)@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::joinGroup(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::UDPSocket(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned short)@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::UDPSocket(unsigned short)@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::UDPSocket()@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::UDPSocket(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned short)@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::UDPSocket(unsigned short)@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::UDPSocket()@Base" 0.1.6 + (c++)"icap::RequestHeader::read_header(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"icap::RequestHeader::RequestHeader(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"icap::RequestHeader::RequestHeader(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"icap::RequestHeader::~RequestHeader()@Base" 0.1.6 + (c++)"icap::RequestHeader::~RequestHeader()@Base" 0.1.6 + (c++)"icap::RequestHeader::~RequestHeader()@Base" 0.1.6 + (c++)"icap::ResponseHeader::init_defaults()@Base" 0.1.6 + (c++)"icap::ResponseHeader::generate_istag()@Base" 0.1.6 + (c++)"icap::ResponseHeader::update_timestamp()@Base" 0.1.6 + (c++)"icap::ResponseHeader::ResponseHeader(icap::ResponseHeader::status_t)@Base" 0.1.6 + (c++)"icap::ResponseHeader::ResponseHeader(icap::ResponseHeader::status_t)@Base" 0.1.6 + (c++)"icap::ResponseHeader::~ResponseHeader()@Base" 0.1.6 + (c++)"icap::ResponseHeader::~ResponseHeader()@Base" 0.1.6 + (c++)"icap::ResponseHeader::~ResponseHeader()@Base" 0.1.6 + (c++)"icap::util::read_chunk(socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"icap::util::read_chunked[abi:cxx11](socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"icap::util::send_chunked(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"icap::util::send_headers(icap::Header*, socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"icap::util::read_req_data(icap::Request*, socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"icap::util::send_response(icap::Response*, socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"icap::util::read_chunk_size(socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"icap::util::read_req_header(socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"icap::util::response_status[abi:cxx11](icap::ResponseHeader::status_t const&)@Base" 0.1.6 + (c++)"icap::util::read_chunk_header(socketlibrary::TCPSocket*, icap::util::chunk_t&)@Base" 0.1.6 + (c++)"icap::util::read_chunked_payload(socketlibrary::TCPSocket*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)@Base" 0.1.6 + (c++)"icap::util::read_req_continue_data(icap::Request*, socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > icap::util::itoa<long>(long)@Base" 0.1.6 + (c++)"icap::util::trim(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)@Base" 0.1.6 + (c++)"icap::util::ltrim(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)@Base" 0.1.6 + (c++)"icap::util::rtrim(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)@Base" 0.1.6 + (c++)"icap::util::split(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"icap::util::chunk_t::~chunk_t()@Base" 0.1.6 + (c++)"icap::util::chunk_t::~chunk_t()@Base" 0.1.6 + (c++)"icap::util::dectohex[abi:cxx11](unsigned int const&)@Base" 0.1.6 + (c++)"icap::util::hextodec(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"icap::util::read_data[abi:cxx11](socketlibrary::TCPSocket*, int)@Base" 0.1.6 + (c++)"icap::util::read_line[abi:cxx11](socketlibrary::TCPSocket*, bool)@Base" 0.1.6 + (c++)"icap::util::read_line(socketlibrary::TCPSocket*, char*, int, bool)@Base" 0.1.6 + (c++)"icap::util::send_data(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"icap::util::send_line(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"icap::Header::attach_encapsulated(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)@Base" 0.1.6 + (c++)"icap::Header::encapsulated_header(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"icap::Header::update_encapsulated(icap::payload_t const&)@Base" 0.1.6 + (c++)"icap::Header::encapsulated_header_str[abi:cxx11]()@Base" 0.1.6 + (c++)"icap::Header::sort_encapsulated_header[abi:cxx11]()@Base" 0.1.6 + (c++)"icap::Header::value(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"icap::Header::attach(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)@Base" 0.1.6 + (c++)"icap::Header::remove(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)@Base" 0.1.6 + (c++)"icap::Header::Header()@Base" 0.1.6 + (c++)"icap::Header::Header()@Base" 0.1.6 + (c++)"icap::Header::~Header()@Base" 0.1.6 + (c++)"icap::Header::~Header()@Base" 0.1.6 + (c++)"icap::Header::~Header()@Base" 0.1.6 + (c++)"icap::Request::preview_size()@Base" 0.1.6 + (c++)"icap::Request::payload(icap::payload_t)@Base" 0.1.6 + (c++)"icap::Request::Request(icap::RequestHeader*)@Base" 0.1.6 + (c++)"icap::Request::Request(icap::RequestHeader*)@Base" 0.1.6 + (c++)"icap::Request::~Request()@Base" 0.1.6 + (c++)"icap::Request::~Request()@Base" 0.1.6 + (c++)"icap::Request::~Request()@Base" 0.1.6 + (c++)"icap::Response::payload(icap::payload_t)@Base" 0.1.6 + (c++)"icap::Response::Response(icap::ResponseHeader::status_t)@Base" 0.1.6 + (c++)"icap::Response::Response(icap::ResponseHeader*)@Base" 0.1.6 + (c++)"icap::Response::Response(icap::ResponseHeader::status_t)@Base" 0.1.6 + (c++)"icap::Response::Response(icap::ResponseHeader*)@Base" 0.1.6 + (c++)"icap::Response::~Response()@Base" 0.1.6 + (c++)"icap::Response::~Response()@Base" 0.1.6 + (c++)"icap::Response::~Response()@Base" 0.1.6 + (c++)"icap::payload_t::~payload_t()@Base" 0.1.6 + (c++)"icap::payload_t::~payload_t()@Base" 0.1.6 + (c++)"socketlibrary::SocketException::what() const@Base" 0.1.6 + (c++)"icap::RequestHeader::uri[abi:cxx11]() const@Base" 0.1.6 + (c++)"icap::RequestHeader::method[abi:cxx11]() const@Base" 0.1.6 + (c++)"icap::RequestHeader::request() const@Base" 0.1.6 + (c++)"icap::RequestHeader::protocol[abi:cxx11]() const@Base" 0.1.6 + (c++)"icap::RequestHeader::raw_data[abi:cxx11]() const@Base" 0.1.6 + (c++)"icap::ResponseHeader::status() const@Base" 0.1.6 + (c++)"icap::ResponseHeader::protocol[abi:cxx11]() const@Base" 0.1.6 + (c++)"icap::Header::headers[abi:cxx11]() const@Base" 0.1.6 + (c++)"icap::Request::header() const@Base" 0.1.6 + (c++)"icap::Request::payload() const@Base" 0.1.6 + (c++)"icap::Response::header() const@Base" 0.1.6 + (c++)"icap::Response::payload() const@Base" 0.1.6 + (c++)"std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::_M_insert_aux(__gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::~vector()@Base" 0.1.6 + (c++)"std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::~vector()@Base" 0.1.6 + (c++)"std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::operator=(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&)@Base" 0.1.6 + (c++)"std::vector<socketlibrary::TCPSocket*, std::allocator<socketlibrary::TCPSocket*> >::_M_insert_aux(__gnu_cxx::__normal_iterator<socketlibrary::TCPSocket**, std::vector<socketlibrary::TCPSocket*, std::allocator<socketlibrary::TCPSocket*> > >, socketlibrary::TCPSocket* const&)@Base" 0.1.6 + (c++)"std::vector<socketlibrary::TCPSocket*, std::allocator<socketlibrary::TCPSocket*> >::_M_fill_insert(__gnu_cxx::__normal_iterator<socketlibrary::TCPSocket**, std::vector<socketlibrary::TCPSocket*, std::allocator<socketlibrary::TCPSocket*> > >, unsigned int, socketlibrary::TCPSocket* const&)@Base" 0.1.6 + (c++)"std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > >::~vector()@Base" 0.1.6 + (c++)"std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > >::~vector()@Base" 0.1.6 + (c++)"std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > >::operator=(std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > const&)@Base" 0.1.6 + (c++)"std::__cxx11::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::~basic_stringbuf()@Base" 0.1.6 + (c++)"std::__cxx11::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::~basic_stringbuf()@Base" 0.1.6 + (c++)"std::__cxx11::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::~basic_stringbuf()@Base" 0.1.6 + (c++)"std::_Rb_tree<icap::ResponseHeader::status_t, std::pair<icap::ResponseHeader::status_t const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::_Select1st<std::pair<icap::ResponseHeader::status_t const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<icap::ResponseHeader::status_t>, std::allocator<std::pair<icap::ResponseHeader::status_t const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::_M_get_insert_unique_pos(icap::ResponseHeader::status_t const&)@Base" 0.1.6 + (c++)"std::_Rb_tree<icap::ResponseHeader::status_t, std::pair<icap::ResponseHeader::status_t const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::_Select1st<std::pair<icap::ResponseHeader::status_t const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<icap::ResponseHeader::status_t>, std::allocator<std::pair<icap::ResponseHeader::status_t const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::_M_erase(std::_Rb_tree_node<std::pair<icap::ResponseHeader::status_t const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >*)@Base" 0.1.6 + (c++)"std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::_M_get_insert_unique_pos(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >* std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::_M_copy<std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::_Reuse_or_alloc_node>(std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const*, std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >*, std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::_Reuse_or_alloc_node&)@Base" 0.1.6 + (c++)"std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::_M_erase(std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >*)@Base" 0.1.6 + (c++)"std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> > >::_M_get_insert_unique_pos(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> > >::find(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.1.6 + (c++)"std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int>, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> > >::_M_erase(std::_Rb_tree_node<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> >*)@Base" 0.1.6 + (c++)"void std::__make_heap<__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, __gnu_cxx::__ops::_Iter_comp_iter<icap::Header::encapsulated_header_compare> >(__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, __gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, __gnu_cxx::__ops::_Iter_comp_iter<icap::Header::encapsulated_header_compare>)@Base" 0.1.6 + (c++)"void std::__adjust_heap<__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, int, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, __gnu_cxx::__ops::_Iter_comp_iter<icap::Header::encapsulated_header_compare> >(__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, int, int, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, __gnu_cxx::__ops::_Iter_comp_iter<icap::Header::encapsulated_header_compare>)@Base" 0.1.6 + (c++)"void std::__insertion_sort<__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, __gnu_cxx::__ops::_Iter_comp_iter<icap::Header::encapsulated_header_compare> >(__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, __gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, __gnu_cxx::__ops::_Iter_comp_iter<icap::Header::encapsulated_header_compare>)@Base" 0.1.6 + (c++)"void std::__introsort_loop<__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, int, __gnu_cxx::__ops::_Iter_comp_iter<icap::Header::encapsulated_header_compare> >(__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, __gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, int, __gnu_cxx::__ops::_Iter_comp_iter<icap::Header::encapsulated_header_compare>)@Base" 0.1.6 + (c++)"void std::__unguarded_linear_insert<__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, __gnu_cxx::__ops::_Val_comp_iter<icap::Header::encapsulated_header_compare> >(__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, __gnu_cxx::__ops::_Val_comp_iter<icap::Header::encapsulated_header_compare>)@Base" 0.1.6 + (c++)"typeinfo for socketlibrary::SocketException@Base" 0.1.6 + (c++)"typeinfo for icap::RequestHeader@Base" 0.1.6 + (c++)"typeinfo for icap::ResponseHeader@Base" 0.1.6 + (c++)"typeinfo for icap::Header@Base" 0.1.6 + (c++)"typeinfo for icap::Request@Base" 0.1.6 + (c++)"typeinfo for icap::Response@Base" 0.1.6 + (c++)"typeinfo name for socketlibrary::SocketException@Base" 0.1.6 + (c++)"typeinfo name for icap::RequestHeader@Base" 0.1.6 + (c++)"typeinfo name for icap::ResponseHeader@Base" 0.1.6 + (c++)"typeinfo name for icap::Header@Base" 0.1.6 + (c++)"typeinfo name for icap::Request@Base" 0.1.6 + (c++)"typeinfo name for icap::Response@Base" 0.1.6 + (c++)"vtable for socketlibrary::SocketException@Base" 0.1.6 + (c++)"vtable for icap::RequestHeader@Base" 0.1.6 + (c++)"vtable for icap::ResponseHeader@Base" 0.1.6 + (c++)"vtable for icap::Header@Base" 0.1.6 + (c++)"vtable for icap::Request@Base" 0.1.6 + (c++)"vtable for icap::Response@Base" 0.1.6 diff --git a/debian/patches/0001-disable_search_doc.patch b/debian/patches/0001-disable_search_doc.patch new file mode 100644 index 0000000..0dfcdfb --- /dev/null +++ b/debian/patches/0001-disable_search_doc.patch @@ -0,0 +1,18 @@ +Description: Disable search in documentation +Author: Jörg Frings-Fürst <debian@jff-webhosting.net> +Last-Update: 2015-05-14 +--- +This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ +Index: trunk/doc/doxygen.cfg.in +=================================================================== +--- trunk.orig/doc/doxygen.cfg.in ++++ trunk/doc/doxygen.cfg.in +@@ -1234,7 +1234,7 @@ MATHJAX_EXTENSIONS     = + # typically be disabled. For large projects the javascript based search engine + # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. +  +-SEARCHENGINE           = YES ++SEARCHENGINE           = NO +  + # When the SERVER_BASED_SEARCH tag is enabled the search engine will be + # implemented using a web server instead of a web client using Javascript. diff --git a/debian/patches/0100-python_print.patch b/debian/patches/0100-python_print.patch new file mode 100644 index 0000000..472dc63 --- /dev/null +++ b/debian/patches/0100-python_print.patch @@ -0,0 +1,171 @@ +Description: Change to python3 syntacs +Author: Jörg Frings-Fürst <debian@jff-webhosting.net> +Forwarded: mailto:Uditha Atukorala <ua@nuked.zone> +Last-Update: 2015-11-21 +--- +This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ +Index: trunk/modules/modpy/modules/modpy.py +=================================================================== +--- trunk.orig/modules/modpy/modules/modpy.py ++++ trunk/modules/modpy/modules/modpy.py +@@ -6,15 +6,15 @@ + import bitz +  + def init(): +-	print "init() called"; ++	print ("init() called"); +  + def cleanup(): +-	print "cleanup() called"; ++	print ("cleanup() called"); +  + def preview( request ): + 	request     = bitz.get_request( request ); + 	req_payload = request['payload']; +-	print "preview payload: \r\n", req_payload; ++	print ("preview payload: \r\n", req_payload); +  + 	# response + 	if req_payload['ieof']: +@@ -27,7 +27,7 @@ def preview( request ): + def modify( request ): + 	request     = bitz.get_request( request ); + 	req_payload = request['payload']; +-	print "modify payload: \r\n", req_payload; ++	print ("modify payload: \r\n", req_payload); +  + 	# response + 	resp_payload = {}; +Index: trunk/test/icap-client.py +=================================================================== +--- trunk.orig/test/icap-client.py ++++ trunk/test/icap-client.py +@@ -14,16 +14,16 @@ SERVICE = 'icap://icap.server.net/sample + PORT    = 1344 +  + # OPTIONS +-print "----- OPTIONS -----" ++print ("----- OPTIONS -----") + try: + 	sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +-except socket.error, msg: ++except socket.error as msg: + 	sys.stderr.write("[ERROR] %s\n" % msg[1]) + 	sys.exit(1) +  + try: + 	sock.connect((HOST, PORT)) +-except socket.error, msg: ++except socket.error as msg: + 	sys.stderr.write("[ERROR] %s\n" % msg[1]) + 	sys.exit(2) +  +@@ -40,20 +40,20 @@ while len(data): + 	data = sock.recv(1024) + sock.close() +  +-print string ++print (string) +  +  + # REQMOD, GET +-print "----- REQMOD - GET -----" ++print ("----- REQMOD - GET -----") + try: + 	sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +-except socket.error, msg: ++except socket.error as msg: + 	sys.stderr.write("[ERROR] %s\n" % msg[1]) + 	sys.exit(1) +  + try: + 	sock.connect((HOST, PORT)) +-except socket.error, msg: ++except socket.error as msg: + 	sys.stderr.write("[ERROR] %s\n" % msg[1]) + 	sys.exit(2) +  +@@ -78,20 +78,20 @@ while len(data): + 	data = sock.recv(1024) + sock.close() +  +-print string ++print (string) +  +  + # REQMOD, POST +-print "----- REQMOD - POST -----" ++print ("----- REQMOD - POST -----") + try: + 	sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +-except socket.error, msg: ++except socket.error as msg: + 	sys.stderr.write("[ERROR] %s\n" % msg[1]) + 	sys.exit(1) +  + try: + 	sock.connect((HOST, PORT)) +-except socket.error, msg: ++except socket.error as msg: + 	sys.stderr.write("[ERROR] %s\n" % msg[1]) + 	sys.exit(2) +  +@@ -118,20 +118,20 @@ while len(data): + 	data = sock.recv(1024) + sock.close() +  +-print string ++print (string) +  +  + # REQMOD - Message preview +-print "----- REQMOD - Message preview -----" ++print ("----- REQMOD - Message preview -----") + try: + 	sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +-except socket.error, msg: ++except socket.error as msg: + 	sys.stderr.write("[ERROR] %s\n" % msg[1]) + 	sys.exit(1) +  + try: + 	sock.connect((HOST, PORT)) +-except socket.error, msg: ++except socket.error as msg: + 	sys.stderr.write("[ERROR] %s\n" % msg[1]) + 	sys.exit(2) +  +@@ -158,20 +158,20 @@ while len(data): + 	data = sock.recv(1024) + sock.close() +  +-print string ++print (string) +  +  + # RESPMOD +-print "----- RESPMOD -----" ++print ("----- RESPMOD -----") + try: + 	sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +-except socket.error, msg: ++except socket.error as msg: + 	sys.stderr.write("[ERROR] %s\n" % msg[1]) + 	sys.exit(1) +  + try: + 	sock.connect((HOST, PORT)) +-except socket.error, msg: ++except socket.error as msg: + 	sys.stderr.write("[ERROR] %s\n" % msg[1]) + 	sys.exit(2) +  +@@ -204,7 +204,7 @@ while len(data): + 	data = sock.recv(1024) + sock.close() +  +-print string ++print (string) +  +  + sys.exit(0) diff --git a/debian/patches/series b/debian/patches/series new file mode 100644 index 0000000..4705ad2 --- /dev/null +++ b/debian/patches/series @@ -0,0 +1,2 @@ +0100-python_print.patch +0001-disable_search_doc.patch diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..cf9ec8b --- /dev/null +++ b/debian/rules @@ -0,0 +1,35 @@ +#!/usr/bin/make -f +# -*- makefile -*- + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +export DEB_BUILD_MAINT_OPTIONS = hardening=+all + +VERSION = $(shell head -n1 debian/changelog | sed -e 's/.*(//;s/-.*).*//;s/\+/\-/') + +%: +	dh $@  --with systemd,autoreconf + +override_dh_auto_build-indep: +	dh_auto_build +	make -C doc doxygen-doc + +override_dh_installdocs-indep: +	cp -r $(CURDIR)/doc/doxygen/html/* $(CURDIR)/debian/bitz-server-doc/usr/share/doc/bitz-server-doc/docs/ +	dh_installdocs + +override_dh_strip: +	dh_strip -pbitz-server --dbg-package=bitz-server-dbg +	dh_strip -plibicap0    --dbg-package=libicap0-dbg + +override_dh_makeshlibs: +	dh_makeshlibs +	dpkg-gensymbols -v$(VERSION) -plibicap0 + +override_dh_systemd_enable: +<<<<<<< HEAD +	dh_systemd_enable -pbitz-server --no-enable bitz-server.service +======= +	dh_systemd_enable --no-enable bitz-server.service +>>>>>>> 042c3255709d05a45bf08fdd0ff2f1eb4027637b diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/debian/watch b/debian/watch new file mode 100644 index 0000000..066e65d --- /dev/null +++ b/debian/watch @@ -0,0 +1,5 @@ +# Compulsory line, this is a version 3 file +version=3 + +opts=filenamemangle=s/.+\/v?(\d\S*)\.tar\.gz/bitz-server-$1\.tar\.gz/ \ +  https://github.com/uditha-atukorala/bitz-server/tags .*/v?(\d\S*)\.tar\.gz diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..190a30d --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,30 @@ +# doc/ + +# man +man1_MANS = bitz-server.man +man5_MANS = bitz-server.conf.man + +# extra dist files +EXTRA_DIST = \ +	bitz-server.man \ +	bitz-server.conf.man + + +# doxygen +if HAVE_DOXYGEN + +.PHONY: doxygen-doc + +doxygen.stamp: +	$(DOXYGEN) doxygen.cfg +	echo timestamp > doxygen.stamp + +CLEANFILES = doxygen.stamp + +doxygen-doc: doxygen.stamp + +clean-local: +	rm -rf $(top_builddir)/doc/doxygen + +endif + diff --git a/doc/bitz-server.conf.man b/doc/bitz-server.conf.man new file mode 100644 index 0000000..1c9b5b0 --- /dev/null +++ b/doc/bitz-server.conf.man @@ -0,0 +1,64 @@ +.TH bitz-server.conf 5 "March 2013" Linux "File Formats Manual" +.SH NAME +bitz-server.conf \- bitz-server configuration file +.SH SYNOPSIS +.B /etc/bitz/bitz-server.conf +.SH DESCRIPTION +.BR bitz-server (1) +obtains configuration data from a config file, the location of which is specified +at compile-time and can be overridden by command-line options during run-time. +.SS Grammer +Below is the BNF grammar for configuration files. Comments and include directives +are not part of the grammar, so they are not included here. See libconfig manual +at http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-File-Grammar +for more details. +.PP +.RS +.nf +configuration = setting-list | empty +setting-list = setting | setting-list setting +setting = name (":" | "=") value (";" | "," | empty) +value = scalar-value | array | list | group +value-list = value | value-list "," value +scalar-value = boolean | integer | integer64 | hex | hex64 | float | string +scalar-value-list = scalar-value | scalar-value-list "," scalar-value +array = "[" (scalar-value-list | empty) "]" +list = "(" (value-list | empty) ")" +group = "{" (setting-list | empty) "}" +empty = +.fi +.RE +.PP +Terminals are defined below as regular expressions: +.TP +.B boolean +([Tt][Rr][Uu][Ee])|([Ff][Aa][Ll][Ss][Ee]) +.TP +.B string +\\"([^\\"\\\\]|\\\\.)*\\" +.TP +.B name +[A-Za-z\\*][\-A-Za-z0-9_\\*]* +.TP +.B integer +[\-+]?[0-9]+ +.TP +.B integer64 +[\-+]?[0-9]+L(L)? +.TP +.B hex +0[Xx][0-9A-Fa-f]+ +.TP +.B hex64 +0[Xx][0-9A-Fa-f]+L(L)? +.TP +.B float +.nf +([\-+]?([0-9]*)?\\.[0-9]*([eE][-+]?[0-9]+)?)| +([\-+]([0-9]+)(\\.[0-9]*)?[eE][-+]?[0-9]+) +.fi +.SH AUTHOR +Uditha Atukorala <udi at geniusse dot com> +.SH "SEE ALSO" +.BR bitz-server (1) + diff --git a/doc/bitz-server.man b/doc/bitz-server.man new file mode 100644 index 0000000..d59ffc1 --- /dev/null +++ b/doc/bitz-server.man @@ -0,0 +1,47 @@ +.TH bitz-server 1 "March 2013" Linux "User Manuals" +.SH NAME +bitz-server \- An ICAP server +.SH SYNOPSIS +.B bitz-server +[\-\-version] [\-\-help] [\-\-usage] [\-\-debug] [\-\-config=<config file>] +.SH DESCRIPTION +.B bitz-server +is an ICAP server implementation in C++. Starting from scratch, +the server is developed with a modular architecture in mind. +The server core (written in C++) will handle the client requests, +manage workers (child processes) etc. and will provide basic handlers +to serve ICAP requests but won't do any actual content adaptation. +.P +To extend this core functionality and do some actual content adaptation +a pluggable modules architecture is used. These modules will provide +features like content filtering, anti-virus scanning etc. and to make it +easier to write (and faster to implement) such modules a python interface +module is included. +.SH OPTIONS +.TP +.B \-\-version, \-v +Prints version information +.TP +.B \-\-help, \-\-usage, \-h +Prints the synopsis +.TP +.B \-\-debug +Run the server in debug mode. This will force the server to run in the +terminal rather than in the background. +.TP +.B \-\-config=<config file> +Set the alternative config file to use instead of the compiled default. +.SH FILES +.I /etc/bitz/bitz-server.conf +.RS +Default configuration file. See +.BR bitz-server.conf (5) +for further details. +.RE +.SH BUGS +Please report all bugs and feature requests at <http://bugs.geniusse.com/> +.SH AUTHOR +Uditha Atukorala <udi at geniusse dot com> +.SH "SEE ALSO" +.BR bitz-server.conf (5) + diff --git a/doc/doxygen.cfg.in b/doc/doxygen.cfg.in new file mode 100644 index 0000000..c4bb0e3 --- /dev/null +++ b/doc/doxygen.cfg.in @@ -0,0 +1,1864 @@ +# Doxyfile 1.8.3 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a hash (#) is considered a comment and will be ignored. +# The format is: +#       TAG = value [value, ...] +# For lists items can also be appended using: +#       TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" "). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING      = UTF-8 + +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. + +PROJECT_NAME           = @PACKAGE_NAME@ + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER         = @PACKAGE_VERSION@ + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF          = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO           = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY       = @top_builddir@/doc/doxygen + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS         = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE        = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC      = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF           = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF       = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC    = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB  = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES        = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. Note that you specify absolute paths here, but also +# relative paths, which will be relative from the directory where doxygen is +# started. + +STRIP_FROM_PATH        = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH    = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES            = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF      = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF           = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS           = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES  = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE               = 4 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES                = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding +# "class=itcl::class" will allow you to use the command class in the +# itcl::class meaning. + +TCL_SUBST              = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C  = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA   = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN   = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL   = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, +# and language is one of the parsers supported by doxygen: IDL, Java, +# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, +# C++. For instance to make doxygen treat .inc files as Fortran files (default +# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note +# that for custom extensions you also need to set FILE_PATTERNS otherwise the +# files are not read by doxygen. + +EXTENSION_MAPPING      = + +# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all +# comments according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you +# can mix doxygen, HTML, and XML commands with Markdown formatting. +# Disable only in case of backward compatibilities issues. + +MARKDOWN_SUPPORT       = YES + +# When enabled doxygen tries to link words that correspond to documented classes, +# or namespaces to their corresponding documentation. Such a link can be +# prevented in individual cases by by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. + +AUTOLINK_SUPPORT       = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT    = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT        = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT            = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES (the +# default) will make doxygen replace the get and set methods by a property in +# the documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT   = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC   = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING            = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields will be shown inline in the documentation +# of the scope in which they are defined (i.e. file, namespace, or group +# documentation), provided this scope is documented. If set to NO (the default), +# structs, classes, and unions are shown on a separate page (for HTML and Man +# pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS  = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT   = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +SYMBOL_CACHE_SIZE      = 0 + +# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be +# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given +# their name and scope. Since this can be an expensive process and often the +# same symbol appear multiple times in the code, doxygen keeps a cache of +# pre-resolved symbols. If the cache is too small doxygen will become slower. +# If the cache is too large, memory is wasted. The cache size is given by this +# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +LOOKUP_CACHE_SIZE      = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL            = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE        = NO + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. + +EXTRACT_PACKAGE        = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC         = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES  = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS  = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES   = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS     = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES     = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS  = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS      = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS          = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES       = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES       = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES     = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES   = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO            = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS       = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS        = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES       = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME     = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING  = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST      = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST      = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST       = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if section-label ... \endif +# and \cond section-label ... \endcond blocks. + +ENABLED_SECTIONS       = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES  = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES        = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES             = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES        = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command <command> <input-file>, where <command> is the value of +# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER    = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE            = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this +# feature you need bibtex and perl available in the search path. Do not use +# file names with spaces, bibtex cannot handle them. + +CITE_BIB_FILES         = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET                  = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS               = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED   = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR      = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC       = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT            = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE           = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT                  = @top_srcdir@ + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING         = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS          = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE              = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE                = @top_srcdir@/doc + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS       = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS       = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS        = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH           = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS       = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE      = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH             = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command <filter> <input-file>, where <filter> +# is the value of the INPUT_FILTER tag, and <input-file> is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER           = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS        = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES    = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page (index.html). +# This can be useful if you have a project on for instance GitHub and want reuse +# the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER         = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES         = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C, C++ and Fortran comments will always remain visible. + +STRIP_CODE_COMMENTS    = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION    = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS              = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS       = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX     = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX    = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX          = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML          = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT            = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION    = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +#  for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is advised to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER            = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER            = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If left blank doxygen will +# generate a default style sheet. Note that it is recommended to use +# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this +# tag will in the future become obsolete. + +HTML_STYLESHEET        = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional +# user-defined cascading style sheet that is included after the standard +# style sheets created by doxygen. Using this option one can overrule +# certain style aspects. This is preferred over using HTML_STYLESHEET +# since it does not replace the standard style sheet and is therefor more +# robust against future updates. Doxygen will copy the style sheet file to +# the output directory. + +HTML_EXTRA_STYLESHEET  = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES       = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the style sheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE    = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT    = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA  = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP         = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. + +HTML_DYNAMIC_SECTIONS  = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of +# entries shown in the various tree structured indices initially; the user +# can expand and collapse entries dynamically later on. Doxygen will expand +# the tree to such a level that at most the specified number of entries are +# visible (unless a fully collapsed tree already exceeds this amount). +# So setting the number of entries 1 will produce a full collapsed tree by +# default. 0 is a special value representing an infinite number of entries +# and will result in a full expanded tree by default. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET        = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME        = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID       = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely +# identify the documentation publisher. This should be a reverse domain-name +# style string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID    = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME  = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP      = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE               = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION           = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI           = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING     = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC             = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND             = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP           = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE               = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE          = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER     = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME   = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters"> +# Qt Help Project / Custom Filters</a>. + +QHP_CUST_FILTER_ATTRS  = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes"> +# Qt Help Project / Filter Attributes</a>. + +QHP_SECT_FILTER_ATTRS  = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION           = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +#  will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP   = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID         = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) +# at top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. Since the tabs have the same information as the +# navigation tree you can set this option to NO if you already set +# GENERATE_TREEVIEW to YES. + +DISABLE_INDEX          = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. +# Since the tree basically has the same information as the tab index you +# could consider to set DISABLE_INDEX to NO when enabling this option. + +GENERATE_TREEVIEW      = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE   = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH         = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW    = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE       = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT    = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you may also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX            = NO + +# When MathJax is enabled you can set the default output format to be used for +# thA MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and +# SVG. The default value is HTML-CSS, which is slower, but has the best +# compatibility. + +MATHJAX_FORMAT         = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to +# the MathJax Content Delivery Network so you can quickly see the result without +# installing MathJax. +# However, it is strongly recommended to install a local +# copy of MathJax from http://www.mathjax.org before deployment. + +MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS     = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE           = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a web server instead of a web client using Javascript. +# There are two flavours of web server based search depending on the +# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for +# searching and an index file used by the script. When EXTERNAL_SEARCH is +# enabled the indexing and searching needs to be provided by external tools. +# See the manual for details. + +SERVER_BASED_SEARCH    = NO + +# When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP +# script for searching. Instead the search results are written to an XML file +# which needs to be processed by an external indexer. Doxygen will invoke an +# external search engine pointed to by the SEARCHENGINE_URL option to obtain +# the search results. Doxygen ships with an example indexer (doxyindexer) and +# search engine (doxysearch.cgi) which are based on the open source search engine +# library Xapian. See the manual for configuration details. + +EXTERNAL_SEARCH        = NO + +# The SEARCHENGINE_URL should point to a search engine hosted by a web server +# which will returned the search results when EXTERNAL_SEARCH is enabled. +# Doxygen ships with an example search engine (doxysearch) which is based on +# the open source search engine library Xapian. See the manual for configuration +# details. + +SEARCHENGINE_URL       = + +# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed +# search data is written to a file for indexing by an external tool. With the +# SEARCHDATA_FILE tag the name of this file can be specified. + +SEARCHDATA_FILE        = searchdata.xml + +# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through other +# doxygen projects that are not otherwise connected via tags files, but are +# all added to the same search index. Each project needs to have a tag file set +# via GENERATE_TAGFILE. The search mapping then maps the name of the tag file +# to a relative location where the documentation can be found, +# similar to the +# TAGFILES option but without actually processing the tag file. +# The format is: EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ... + +EXTRA_SEARCH_MAPPINGS  = + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX         = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT           = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME         = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME     = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX          = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE             = a4 + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES         = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER           = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER           = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS         = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX           = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE        = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES     = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE      = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE        = plain + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF           = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT             = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF            = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS         = NO + +# Load style sheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE    = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE    = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN           = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT             = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION          = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS              = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML           = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT             = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA             = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD                = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING     = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF   = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD       = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX          = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY         = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING   = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION        = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF     = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + +SEARCH_INCLUDES        = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH           = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS  = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED             = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + +EXPAND_AS_DEFINED      = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS   = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. For each +# tag file the location of the external documentation should be added. The +# format of a tag file without this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths +# or URLs. Note that each tag file must have a unique name (where the name does +# NOT include the path). If a tag file is not located in the directory in which +# doxygen is run, you must also specify the path to the tagfile here. + +TAGFILES               = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE       = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS           = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS        = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH              = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS         = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH            = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS   = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT               = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS        = 0 + +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. + +DOT_FONTNAME           = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE           = 10 + +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. + +DOT_FONTPATH           = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH            = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH    = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS           = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK               = NO + +# If the UML_LOOK tag is enabled, the fields and methods are shown inside +# the class node. If there are many fields or methods and many nodes the +# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS +# threshold limits the number of items for each type to make the size more +# managable. Set this to 0 for no limit. Note that the threshold may be +# exceeded by 50% before the limit is enforced. + +UML_LIMIT_NUM_FIELDS   = 10 + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS     = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH          = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH      = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH             = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH           = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY    = YES + +# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH        = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). + +DOT_IMAGE_FORMAT       = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. + +INTERACTIVE_SVG        = NO + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH               = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS           = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS           = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES    = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH    = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT        = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS      = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND        = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP            = YES diff --git a/include/Makefile.am b/include/Makefile.am new file mode 100644 index 0000000..acb92a3 --- /dev/null +++ b/include/Makefile.am @@ -0,0 +1 @@ +## include/ diff --git a/lib/Makefile.am b/lib/Makefile.am new file mode 100644 index 0000000..bcd3933 --- /dev/null +++ b/lib/Makefile.am @@ -0,0 +1,3 @@ +## [bitz-server] lib/ +SUBDIRS = socket icap + diff --git a/lib/icap/Makefile.am b/lib/icap/Makefile.am new file mode 100644 index 0000000..02d8bb4 --- /dev/null +++ b/lib/icap/Makefile.am @@ -0,0 +1,24 @@ +## [icap-library] lib/icap/ +AM_CPPFLAGS             = -I$(top_srcdir)/lib +libicapincludedir       = $(includedir)/icap + +lib_LTLIBRARIES         = libicap.la +libicap_la_LIBADD       = $(top_builddir)/lib/socket/libsocket.la +libicap_la_LDFLAGS      = -version-info @ICAP_LT_VERSION@ -no-undefined +libicap_la_SOURCES      = \ +	header.cpp \ +	request_header.cpp \ +	response_header.cpp \ +	request.cpp \ +	response.cpp \ +	util.cpp + +libicapinclude_HEADERS  = \ +	common.h \ +	header.h  \ +	request_header.h \ +	response_header.h \ +	request.h \ +	response.h \ +	util.h + diff --git a/lib/icap/common.h b/lib/icap/common.h new file mode 100644 index 0000000..65c3694 --- /dev/null +++ b/lib/icap/common.h @@ -0,0 +1,41 @@ +/* + *	C++ ICAP library + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifndef ICAP_COMMON_H +#define ICAP_COMMON_H + +#include <string> + + +namespace icap { + +	/** +	*   Payload structure common to both requests and responses. +	*/ +	struct payload_t { +		std::string req_header;    /**< request header  */ +		std::string req_body;      /**< request body    */ +		std::string res_header;    /**< response header */ +		std::string res_body;      /**< response body   */ +		bool ieof;                 /**< boolen flag to store the presence of "ieof" */ +	}; + +} /* end of namespace icap */ + +#endif /* !ICAP_COMMON_H */ diff --git a/lib/icap/header.cpp b/lib/icap/header.cpp new file mode 100644 index 0000000..493e659 --- /dev/null +++ b/lib/icap/header.cpp @@ -0,0 +1,223 @@ +/* + *	C++ ICAP library + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include "header.h" +#include "util.h" + +#include <algorithm> +#include <cstdlib> + + +namespace icap { + +	Header::Header() { + +		// initialise defaults +		_encapsulated["req-hdr"]   = -1; +		_encapsulated["req-body"]  = -1; +		_encapsulated["res-hdr"]   = -1; +		_encapsulated["res-body"]  = -1; +		_encapsulated["opt-body"]  = -1; +		_encapsulated["null-body"] = -1; + +	} + +	Header::~Header() {} + + +	const Header::headers_t &Header::headers() const throw() { +		return _headers; +	} + + +	const std::string Header::value( const std::string &key ) throw() { + +		std::string value           = ""; +		Header::headers_index_t idx = _headers.find( key ); + +		if ( idx != _headers.end() ) { +			value = idx->second; +		} + +		return value; + +	} + + +	const int Header::encapsulated_header( const std::string &entity ) throw() { + +		Header::encapsulated_header_index_t idx; + +		idx = _encapsulated.find( entity ); +		if ( idx == _encapsulated.end() ) { +			return -1; +		} + +		return idx->second; + +	} + + +	void Header::attach( std::string key, std::string value ) throw() { + +		// trim +		key   = util::trim( key ); +		value = util::trim( value ); + +		// check for 'Encapsulated' headers +		if ( key == "Encapsulated" ) { +			attach_encapsulated( value ); +		} else { +			_headers[key] = value; +		} + +	} + + +	bool Header::attach_encapsulated( std::string header_value ) throw() { + +		std::vector<std::string> list_data; +		std::vector<std::string> entity_data; + +		encapsulated_header_index_t idx; +		bool r_status = true; + +		// grab the entity list [ req-hdr=0, null-body=170 ] +		list_data = util::split( util::trim( header_value ), "," ); + +		for ( size_t i = 0; i < list_data.size(); i++ ) { + +			// get entity data [ req-hdr=0 ] +			entity_data = util::split( util::trim( list_data.at( i ) ), "=" ); + +			if ( entity_data.size() == 2 ) { + +				idx = _encapsulated.find( util::trim( entity_data.at( 0 ) ) ); +				if ( idx != _encapsulated.end() ) { +					idx->second = atoi( util::trim( entity_data.at( 1 ) ).c_str() ); +				} + +			} else { +				r_status = false; +			} +		} + +		return r_status; + +	} + + +	bool Header::remove( std::string key ) throw() { +		return ( (bool) _headers.erase( util::trim( key ) ) ); +	} + + +	const std::string Header::encapsulated_header_str() throw() { + +		/* +		*  Encapsulated request header grammer: +		*   REQMOD  request  encapsulated_list: [reqhdr] reqbody +		*   REQMOD  response encapsulated_list: {[reqhdr] reqbody} | +		*                                       {[reshdr] resbody} +		*   RESPMOD request  encapsulated_list: [reqhdr] [reshdr] resbody +		*   RESPMOD response encapsulated_list: [reshdr] resbody +		*   OPTIONS response encapsulated_list: optbody +		*/ + +		Header::encapsulated_header_index_t idx; +		std::string encaps_header = ""; + +		// FIXME: chances are that we will always get the correct order +		//        but should consider sorting +		for ( idx = _encapsulated.begin(); idx != _encapsulated.end(); idx++ ) { + +			if ( idx->second > 0 ) { + +				if ( encaps_header != "" ) { +					encaps_header.append( ", " ); +				} + +				encaps_header.append( idx->first ).append( "=" ).append( util::itoa( idx->second ) ); + +			} + +		} + +		// sanity check +		if ( encaps_header == "" ) { +			encaps_header = "null-body=0"; +		} + +		return encaps_header; + +	} + + +	void Header::update_encapsulated( const payload_t &payload ) throw() { + +		unsigned int data_length = 0; +		unsigned int data_offset = 0; + +		// request header +		if ( payload.req_header.size() > 0 ) { +			_encapsulated["req-hdr"] = data_length; +			data_offset = data_length; +			data_length += payload.req_header.size(); +		} + +		// request body (POST data) +		if ( payload.req_body.size() > 0 ) { +			_encapsulated["req-body"] = data_length; +			data_offset = data_length; +			data_length += payload.req_body.size(); +		} + +		// response header +		if ( payload.res_header.size() > 0 ) { +			_encapsulated["res-hdr"] = data_length; +			data_offset = data_length; +			data_length += payload.res_header.size(); +		} + +		// response body +		if ( payload.res_body.size() > 0 ) { +			_encapsulated["res-body"] = data_length; +			data_offset = data_length; +			data_length += payload.res_body.size(); +		} + +		// null-body +		if ( data_offset == 0 ) { +			_encapsulated["null-body"] = data_length; +		} + +	} + + +	std::vector<Header::encapsulated_header_data_t> Header::sort_encapsulated_header() { + +		std::vector<Header::encapsulated_header_data_t> data( _encapsulated.begin(), _encapsulated.end() ); +		std::sort(data.begin(), data.end(), encapsulated_header_compare()); + +		return data; + +	} + +} + diff --git a/lib/icap/header.h b/lib/icap/header.h new file mode 100644 index 0000000..52a8fef --- /dev/null +++ b/lib/icap/header.h @@ -0,0 +1,168 @@ +/* + *	C++ ICAP library + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifndef ICAP_HEADER_H +#define ICAP_HEADER_H + +#include "common.h" + +#include <string> +#include <map> +#include <vector> +#include <functional> + + +namespace icap { + +	class Header { +	public: + +		/* headers data type */ +		typedef std::map<std::string, std::string> headers_t; + +		/* headers iterator type */ +		typedef headers_t::iterator headers_index_t; + +		/* encapsulated header type */ +		typedef std::map<std::string, int> encapsulated_header_t; + +		/* encapsulated header iterator type */ +		typedef encapsulated_header_t::iterator encapsulated_header_index_t; + +		/* encapsulated header data type */ +		typedef std::pair<std::string, int> encapsulated_header_data_t; + +		/** +		*   Binary compare structure to compare two encapsulated header +		*   entity (data) values. Used for sorting. +		*/ +		struct encapsulated_header_compare +			: std::binary_function<icap::Header::encapsulated_header_data_t, icap::Header::encapsulated_header_data_t, bool> { +			inline bool operator()( const icap::Header::encapsulated_header_data_t &lhs, const icap::Header::encapsulated_header_data_t &rhs ) { +				return lhs.second < rhs.second; +			} +		}; + + +		Header(); +		virtual ~Header(); + +		/** +		*   Return headers +		*   @return headers +		*/ +		const headers_t &headers() const throw(); + +		/** +		*   Returns the header value for the given header key or an empty string +		*   if the header is not found. +		* +		*   @param key header key +		*   @return header value  +		*/ +		const std::string value( const std::string &key ) throw(); + +		/** +		*   Return Encapsulated header value for the given entity +		*   or -1 if the given entity is invalid. +		* +		*   @param entity encapsulated header entity +		*   @return -1 | encapsulated header value +		*/ +		const int encapsulated_header( const std::string &entity ) throw(); + +		/** +		*   Attach header data into the header +		* +		*   <pre> +		*   e.g. +		*   Host: icap-server.net +		*   Encapsulated: req-hdr=0, null-body=170 +		*   [key]: [value] +		*   </pre> +		* +		*   @param key header key +		*   @param value header value +		*/ +		virtual void attach( std::string key, std::string value ) throw(); + +		/** +		*   Attach Encapsulated header data. This method should only be used +		*   when reading a raw request / response. Consider using update_encapsulated() +		*   method for other scenarios. +		* +		*   <pre> +		*   e.g. +		*   Encapsulated: req-hdr=0, req-body=412 +		*   Encapsulated: req-hdr=0, res-hdr=822, res-body=1655 +		*   Encapsulated: [header_value] +		*   </pre> +		* +		*   @param header_value Encapsulated header value +		*   @return boolean to denote success or failure +		*/ +		virtual bool attach_encapsulated( std::string header_value ) throw(); + + +		/** +		*   Update Encapsulated header data using the passed in (icap::payload_t) payload. +		*   When the request / response has been populated with the payload, calling this +		*   method will update the encapsulated header entities with appropriate values. +		* +		*   This methos will always succeed. +		* +		*   @param payload request or response payload +		*/ +		virtual void update_encapsulated( const payload_t &payload ) throw(); + +		/** +		*   Remove header data from the header instance with the given key +		* +		*   @param key header key +		*   @return boolean to denote success or failure +		*/ +		virtual bool remove( std::string key ) throw(); + +		/** +		*   Return Encapsulated header as a std::string value. +		*   @return encapsulated header value (e.g. res-hdr=0, res-body=213) +		*/ +		virtual const std::string encapsulated_header_str() throw(); + +		/** +		*   Sort the encapsulated header data and return a std::vector of +		*   encapsulated_header_data_t. The actual header data won't be changed. +		* +		*   @return sorted encapsulated header +		*/ +		virtual std::vector<encapsulated_header_data_t> sort_encapsulated_header(); + + +	protected: +		headers_t _headers; +		encapsulated_header_t _encapsulated; + +	private: + +	}; + +} /* end of namespace icap */ + +#endif /* !ICAP_HEADER_H */ + diff --git a/lib/icap/request.cpp b/lib/icap/request.cpp new file mode 100644 index 0000000..bf80e13 --- /dev/null +++ b/lib/icap/request.cpp @@ -0,0 +1,84 @@ +/* + *	C++ ICAP library + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include "request.h" + +#include <cstdlib> + + +namespace icap { + +	Request::Request( RequestHeader * req_header ) { + +		_header  = req_header; + +		// initialise defaults +		_payload.req_header = ""; +		_payload.req_body   = ""; +		_payload.res_header = ""; +		_payload.res_body   = ""; +		_payload.ieof       = false; + +	} + + +	Request::~Request() { } + + +	RequestHeader * const Request::header() const throw() { +		return _header; +	} + + +	void Request::payload( payload_t payload ) throw() { + +		_payload = payload; + +		// update encapsulated data +		_header->update_encapsulated( _payload ); + +	} + + +	const payload_t &Request::payload() const throw() { +		return _payload; +	} + + +	const int Request::preview_size() throw() { + +		int size = -1; + +		// grab the size from request header +		std::string s_size = _header->value( "Preview" ); + +		// sanity check +		if (! s_size.empty() ) { + +			// convert string to integer +			size = atoi( s_size.c_str() ); + +		} + +		return size; + +	} + +} /* end of namespace icap */ + diff --git a/lib/icap/request.h b/lib/icap/request.h new file mode 100644 index 0000000..d5c4f69 --- /dev/null +++ b/lib/icap/request.h @@ -0,0 +1,72 @@ +/* + *	C++ ICAP library + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifndef ICAP_REQUEST_H +#define ICAP_REQUEST_H + +#include "common.h" +#include "request_header.h" + + +namespace icap { + +	class Request { +	public: +		Request( RequestHeader * req_header ); +		virtual ~Request(); + +		/** +		*   Return the request header +		*   @return request header +		*/ +		RequestHeader * const header() const throw(); + +		/** +		*   Set the payload data for this response instance from a +		*   icap::payload_t data structure +		* +		*   @param payload payload data structure +		*/ +		void payload( payload_t payload ) throw(); + +		/** +		*   Return the payload data for this response instance +		*   @return payload data +		*/ +		const payload_t &payload() const throw(); + +		/** +		*   Returns the number of preview bytes in the request. If the preview +		*   header is not present in the request then a minus (-1) value will be +		*   returned. +		*    +		*   @return preview bytes +		*/ +	   const int preview_size() throw();	 + +	private: +		RequestHeader * _header; +		payload_t _payload; + +	}; + +} /* end of namespace icap */ + +#endif /* !ICAP_REQUEST_H */ + diff --git a/lib/icap/request_header.cpp b/lib/icap/request_header.cpp new file mode 100644 index 0000000..a9b42dc --- /dev/null +++ b/lib/icap/request_header.cpp @@ -0,0 +1,113 @@ +/* + *	C++ ICAP library + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include "request_header.h" +#include "util.h" + + +namespace icap { + +	/* +	*  sample icap request header: +	*  REQMOD icap://icap-server.net/server?arg=87 ICAP/1.0 +	*  Host: icap-server.net +	*  Encapsulated: req-hdr=0, null-body=170 +	* +	*  [payload] +	*/ +	RequestHeader::RequestHeader( const std::string &raw_data ) : Header() { + +		// initialise defaults +		_request.method   = ""; +		_request.uri      = ""; +		_request.protocol = "ICAP/1.0"; + +		// read header +		read_header( raw_data ); + +	} + + +	RequestHeader::~RequestHeader() { } + + +	const std::string &RequestHeader::method() const throw() { +		return _request.method; +	} + + +	const std::string &RequestHeader::uri() const throw() { +		return _request.uri; +	} + + +	const std::string &RequestHeader::protocol() const throw() { +		return _request.protocol; +	} + + +	const RequestHeader::request_t &RequestHeader::request() const throw() { +		return _request; +	} + + +	const std::string &RequestHeader::raw_data() const throw() { +		return _raw_data; +	} + + +	void RequestHeader::read_header( const std::string &raw_data ) throw() { + +		std::vector<std::string> data; + +		_raw_data = raw_data; +		data = util::split( raw_data, "\r\n" ); + +		if ( data.size() > 0 ) { + +			std::vector<std::string> header_data; +			std::vector<std::string> request; + +			std::string request_data = data.at( 0 ); +			request = util::split( util::trim( request_data ) ); + +			if ( request.size() == 3 ) { +				_request.method   = request.at(0); +				_request.uri      = request.at(1); +				_request.protocol = request.at(2); +			} else { +				// TODO: error, invalid request format +			} + +			for ( int i = 1; i < data.size(); i++ ) { +				header_data = util::split( data.at( i ), ":" ); + +				if ( header_data.size() == 2 ) { +					this->attach( header_data.at( 0 ), header_data.at( 1 ) ); +				} else { +					// TODO: error parsing header data +				} +			} + +		} + +	} + +} /* end of namespace icap */ + diff --git a/lib/icap/request_header.h b/lib/icap/request_header.h new file mode 100644 index 0000000..47978c1 --- /dev/null +++ b/lib/icap/request_header.h @@ -0,0 +1,84 @@ +/* + *	C++ ICAP library + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifndef ICAP_REQUEST_HEADER_H +#define ICAP_REQUEST_HEADER_H + +#include "header.h" + +#include <string> +#include <vector> + + +namespace icap { + +	class RequestHeader : public Header { +	public: + +		struct request_t { +			std::string method; +			std::string uri; +			std::string protocol; +		}; + +		RequestHeader( const std::string &raw_data ); +		virtual ~RequestHeader(); + +		/** +		*   Return request method +		*   @return method +		*/ +		const std::string &method() const throw(); + +		/** +		*   Return request URI +		*   @return URI +		*/ +		const std::string &uri() const throw(); + +		/** +		*   Return request protocol +		*   @return protocol +		*/ +		const std::string &protocol() const throw(); + +		/** +		*   Return request +		*   @return request +		*/ +		const request_t &request() const throw(); + +		/** +		*   Return raw header data +		*   @return raw request header +		*/ +		const std::string &raw_data() const throw(); + +	private: +		request_t _request; +		std::string _raw_data; + +		void read_header( const std::string &raw_data ) throw(); + +	}; + +} /* end of namespace icap */ + +#endif /* !ICAP_REQUEST_HEADER_H */ + diff --git a/lib/icap/response.cpp b/lib/icap/response.cpp new file mode 100644 index 0000000..6bd730f --- /dev/null +++ b/lib/icap/response.cpp @@ -0,0 +1,81 @@ +/* + *	C++ ICAP library + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include "response.h" + + +namespace icap { + +	Response::Response( ResponseHeader * header ) { + +		if ( header != NULL ) { +			_header = header; +			_cleanup_header  = false; +		} else { +			_header = new ResponseHeader( ResponseHeader::SERVER_ERROR ); +			_cleanup_header  = true; +		} + +		// initialise defaults +		_payload.req_header = ""; +		_payload.req_body   = ""; +		_payload.res_header = ""; +		_payload.res_body   = ""; +		_payload.ieof       = false; + +	} + + +	Response::Response( ResponseHeader::status_t status ) { +		_header = new ResponseHeader( status ); +		_cleanup_header  = true; +	} + + +	Response::~Response() { + +		// cleanup +		if ( _cleanup_header ) { +			delete _header; +		} + +	} + + +	ResponseHeader * const Response::header() const throw() { +		return _header; +	} + + +	void Response::payload( payload_t payload ) throw() { + +		_payload = payload; + +		// update encapsulated data +		_header->update_encapsulated( _payload ); + +	} + + +	const payload_t &Response::payload() const throw() { +		return _payload; +	} + +} /* end of namespace icap */ + diff --git a/lib/icap/response.h b/lib/icap/response.h new file mode 100644 index 0000000..2977c07 --- /dev/null +++ b/lib/icap/response.h @@ -0,0 +1,65 @@ +/* + *	C++ ICAP library + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifndef ICAP_RESPONSE_H +#define ICAP_RESPONSE_H + +#include "common.h" +#include "response_header.h" + + +namespace icap { + +	class Response { +	public: +		Response( ResponseHeader * response_header = NULL ); +		Response( ResponseHeader::status_t status ); +		virtual ~Response(); + +		/** +		*   Return the response header +		*   @return response header +		*/ +		ResponseHeader * const header() const throw(); + +		/** +		*   Set the payload data for this response instance from a +		*   icap::payload_t data structure +		* +		*   @param payload payload data structure +		*/ +		void payload( payload_t payload ) throw(); + +		/** +		*   Return the payload data for this response instance +		*   @return payload data +		*/ +		const payload_t &payload() const throw(); + +	private: +		ResponseHeader * _header; +		payload_t _payload; +		bool _cleanup_header; + +	}; + +} /* end of namespace icap */ + +#endif /* !ICAP_RESPONSE_H */ + diff --git a/lib/icap/response_header.cpp b/lib/icap/response_header.cpp new file mode 100644 index 0000000..aa29e63 --- /dev/null +++ b/lib/icap/response_header.cpp @@ -0,0 +1,101 @@ +/* + *	C++ ICAP library + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include "response_header.h" +#include "util.h" +#include <config.h> + +#include <ctime> +#include <stdlib.h> + + +namespace icap { + +	ResponseHeader::ResponseHeader( status_t status ) : Header() { + +		// FIXME: protocol shouldn't be hard-coded +		_response.protocol = "ICAP/1.0"; +		_response.status   = status; + +		// initialise default headers +		init_defaults(); + +	} + +	ResponseHeader::~ResponseHeader() { } + + +	const std::string &ResponseHeader::protocol() const throw() { +		return _response.protocol; +	} + + +	const ResponseHeader::status_t &ResponseHeader::status() const throw() { +		return _response.status; +	} + + +	void ResponseHeader::init_defaults() throw() { + +		update_timestamp(); +		generate_istag(); +		attach( "Server", PACKAGE_STRING ); + +		// close connection header +		if ( _response.status != ResponseHeader::CONTINUE ) { +			attach( "Connection" , "close" ); +		} + +	} + + +	void ResponseHeader::update_timestamp() throw() { + +		time_t raw_time; +		struct tm * time_info; +		char buffer [80]; + +		time( &raw_time ); +		time_info = localtime( &raw_time ); + +		strftime ( buffer, 80, "%c %Z", time_info ); +		attach( "Date", buffer ); + +	} + + +	void ResponseHeader::generate_istag() throw() { + +		time_t raw_time; +		clock_t clock_time; +		std::string istag; + +		time( &raw_time ); +		clock_time = clock(); + +		istag = "BITZ-"; +		istag.append( util::itoa( raw_time ) ).append( "-" ); +		istag.append( util::itoa( clock_time) ); + +		attach( "ISTag", istag.substr( 0, 32 ) ); + +	} + +} /* end of namespace icap */ + diff --git a/lib/icap/response_header.h b/lib/icap/response_header.h new file mode 100644 index 0000000..48d9ddd --- /dev/null +++ b/lib/icap/response_header.h @@ -0,0 +1,78 @@ +/* + *	C++ ICAP library + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifndef ICAP_RESPONSE_HEADER_H +#define ICAP_RESPONSE_HEADER_H + +#include "header.h" + + +namespace icap { + +	class ResponseHeader : public Header { +	public: + +		enum status_t { +			CONTINUE            = 100, +			OK                  = 200, +			NO_CONTENT          = 204, +			BAD_REQUEST         = 400, +			NOT_FOUND           = 404, +			NOT_ALLOWED         = 405, +			REQ_TIMEOUT         = 408, +			SERVER_ERROR        = 500, +			NOT_IMPLEMENTED     = 501, +			BAD_GATEWAY         = 502, +			SERVICE_OVERLOADED  = 503, +			NOT_SUPPORTED       = 505 +		}; + +		struct response_t { +			std::string protocol; +			status_t status; +		}; + +		ResponseHeader( status_t status ); +		virtual ~ResponseHeader(); + +		/** +		*   Return the response protocol +		*   @return protocol +		*/ +		const std::string &protocol() const throw(); + +		/** +		*   Return the response status +		*   @return status +		*/ +		const status_t &status() const throw(); + +	private: +		response_t _response; + +		void update_timestamp() throw(); +		void generate_istag() throw(); +		void init_defaults() throw(); + +	}; + +} /* end of namespace icap */ + +#endif /* !ICAP_RESPONSE_HEADER_H */ + diff --git a/lib/icap/util.cpp b/lib/icap/util.cpp new file mode 100644 index 0000000..c383261 --- /dev/null +++ b/lib/icap/util.cpp @@ -0,0 +1,693 @@ +/* + *	C++ ICAP library + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include "util.h" + +#include <string> +#include <algorithm> +#include <locale> +#include <iostream> + + +namespace icap { + +	namespace util { + +		unsigned int hextodec( const std::string &hex ) throw() { + +			unsigned int dec; +			std::stringstream ss; + +			ss << std::hex << hex; +			ss >> dec; + +			return dec; + +		} + + +		const std::string dectohex( const unsigned int &dec ) throw() { + +			std::string hex; +			std::stringstream ss; + +			ss << std::hex << dec; +			ss >> hex; + +			return hex; + +		} + + +		int read_line( socketlibrary::TCPSocket * socket, char * buf, int buf_length, bool incl_endl ) throw() { + +			int i  = 0, n; +			char c = '\0'; + +			while ( i < ( buf_length - 1 ) ) { + +				n = socket->recv( &c, 1 ); + +				if ( n > 0 ) { +					if ( c == '\r' ) { + +						if ( incl_endl ) { +							buf[i] = c; +							i++; +						} + +						// peak for \n +						n = socket->peek( &c, 1 ); + +						if ( ( n > 0 ) && ( c == '\n' ) ) { + +							n = socket->recv( &c, 1 ); + +							if ( incl_endl ) { +								buf[i] = c; +								i++; +							} + +							break;    // end of line +						} +					} + +					buf[i] = c; +					i++; +				} else { +					break;    // nothing read from socket +				} + +			} + +			buf[i] = '\0'; +			return i; + +		} + + +		std::string read_line( socketlibrary::TCPSocket * socket, bool incl_endl ) throw() { + +			int n; +			std::string line; +			char c = '\0'; + +			try { + +				while ( ( n = socket->recv( &c, 1 ) ) > 0 ) { + +					if ( c == '\r' ) { + +						if ( incl_endl ) { +							line += c; +						} + +						// peak for \n +						n = socket->peek( &c, 1 ); + +						if ( ( n > 0 ) && ( c == '\n' ) ) { + +							n = socket->recv( &c, 1 ); + +							if ( incl_endl ) { +								line += c; +							} + +							break;    // end of line +						} +					} + +					line  += c; + +				} + +			} catch ( socketlibrary::SocketException &sex ) { +				// TODO: log error? +				line = ""; +			} + +			return line; + +		} + + +		std::string read_data( socketlibrary::TCPSocket * socket, int size ) throw() { + +			char buffer[ICAP_BUFFER_SIZE]; +			std::string data = ""; +			int n; + +			// loop until we have read all the bytes +			while ( size > 0 ) { + +				try { + +					// read from socket +					n = socket->recv( buffer, min( size, ICAP_BUFFER_SIZE ) ); + +					// sanity check +					if ( n == 0 ) { +						break; +					} + +					// append to data +					data.append( buffer, n ); + +					// update size with remaining bytes +					size -= n; + +				} catch ( socketlibrary::SocketException &sex ) { +					// TODO: log errors ?? +				} + +			} + +			return data; + +		} + + +		unsigned int read_chunk_size( socketlibrary::TCPSocket * socket ) throw() { + +			std::string line; +			std::vector<std::string> chunk_header; + +			line = read_line( socket ); +			chunk_header = split( line, ";" ); + +			return hextodec( chunk_header.at( 0 ) ); + +		} + + +		void read_chunk_header( socketlibrary::TCPSocket * socket, chunk_t &chunk ) throw() { + +			std::string line; +			std::vector<std::string> chunk_header; + +			line = read_line( socket ); +			chunk_header = split( line, ";" ); + +			// sanity check +			if ( chunk_header.size() > 0 ) { + +				// sanity check +				if ( chunk_header.at( 0 ).size() > 0 ) { +					chunk.size = hextodec( chunk_header.at( 0 ) ); +				} + +				// check for chunk-extension +				if ( chunk_header.size() == 2 ) { +					chunk.extention = trim( chunk_header.at( 1 ) ); +				} +			} + +			return; + +		} + + +		chunk_t read_chunk( socketlibrary::TCPSocket * socket ) throw() { + +			chunk_t chunk; +			std::string line; +			std::vector<std::string> chunk_header; + +			// initialise chunk +			chunk.size      = 0; +			chunk.extention = ""; +			chunk.data      = ""; + +			// read chunk header +			read_chunk_header( socket, chunk ); + +			// read chunk data +			if ( chunk.size > 0 ) { +				chunk.data = read_data( socket, chunk.size ); +			} + +			// read \r\n ending for the chunk +			read_data( socket, 2 ); + +			return chunk; + +		} + + +		std::string read_chunked( socketlibrary::TCPSocket * socket ) throw() { + +			unsigned int chunk_size  = 0; +			unsigned int offset      = 0; +			std::string chunked_data = ""; + +			while ( ( chunk_size = read_chunk_size( socket ) ) > 0 ) { + +				offset = chunked_data.size(); + +				// read chunk-data +				chunked_data.append( read_data( socket, chunk_size ) ); + +				// sanity check +				if ( ( chunked_data.size() - offset ) != chunk_size ) { +					// something went wrong +					break; +				} + +				// extra \r\n +				read_data( socket, 2 ); + +			} + +			// read until the end of chunked data +			while ( read_line( socket, true ).size() > 2 ) ; + +			return chunked_data; + +		} + + +		bool read_chunked_payload( socketlibrary::TCPSocket * socket, std::string &payload ) throw() { + +			chunk_t chunk; +			bool ieof = false; + +			do { + +				// read chunk +				chunk = read_chunk( socket ); + +				// append to payload +				payload.append( chunk.data ); + +				// sanity check +				if ( chunk.data.size() != chunk.size ) { +					// something went wrong +					break; +				} + +			} while( chunk.size > 0 ); + +			// check for ieof +			if ( chunk.extention == "ieof" ) { +				ieof = true; +			} + +			return ieof; + +		} + + +		bool send_line( const std::string &line, socketlibrary::TCPSocket * socket ) throw() { + +			try { +				socket->send( line.c_str(), line.length() ); +				socket->send( "\r\n", 2 ); +			} catch ( socketlibrary::SocketException &sex ) { +				// TODO: log errors +				return false; +			} + +			return true; + +		} + + +		bool send_data( const std::string &data, socketlibrary::TCPSocket * socket ) throw() { + +			try { +				socket->send( data.c_str(), data.size() ); +			} catch( socketlibrary::SocketException &sex ) { +				// TODO: log errors +				return false; +			} + +			return true; + +		} + + +		bool send_chunked( const std::string &data, socketlibrary::TCPSocket * socket ) throw() { + +			std::string chunked_data = ""; +			unsigned int offset      = 0; +			int chunks               = 0; + +			// calculate the number of chunks we need +			if ( data.size() > ICAP_BUFFER_SIZE ) { +				chunks = ( data.size() / ICAP_BUFFER_SIZE ); +			} + +			try { + +				do { + +					// prepare data for this chunk +					chunked_data = data.substr( offset, ICAP_BUFFER_SIZE ); + +					// sanity check +					if ( chunked_data.size() <= 0 ) { +						// we shouldn't get here +						break; +					} + +					// update offset +					offset += chunked_data.size(); + +					// send chunk size +					if (! send_line( dectohex( chunked_data.size() ), socket ) ) { +						return false; +					} + +					// send chunk +					if (! send_data( chunked_data, socket ) ) { +						return false; +					} + +					chunks--; + +				} while ( chunks > 0 ); + +				// end of chunk +				if (! send_data( "\r\n0\r\n\r\n", socket ) ) { +					return false; +				} + +			} catch ( socketlibrary::SocketException &sex ) { +				// TODO: log errors ?? +				return false; +			} + +			return true; + +		} + + +		std::vector<std::string> split( const std::string &str, const std::string &delimiter ) throw() { + +			std::vector<std::string> result; +			size_t current; +			size_t next = -1; + +			do { +				current = next + 1; +				next    = str.find_first_of( delimiter, current ); +				result.push_back( str.substr( current, ( next - current ) ) ); +			} while ( next != std::string::npos ); + +			return result; + +		} + + +		std::string <rim( std::string &str ) throw() { +			str.erase( str.begin(), std::find_if( str.begin(), str.end(), std::not1( std::ptr_fun<int, int>( std::isspace ) ) ) ); +			return str; +		} + + +		std::string &rtrim( std::string &str ) throw() { +			str.erase( std::find_if( str.rbegin(), str.rend(), std::not1( std::ptr_fun<int, int>( std::isspace ) ) ).base(), str.end() ); +			return str; +		} + + +		std::string &trim( std::string &str ) throw() { +			return ltrim( rtrim( str ) ); +		} + + +		icap::RequestHeader * read_req_header( socketlibrary::TCPSocket * socket ) throw() { + +			char buffer[ICAP_BUFFER_SIZE]; +			int  n = 0; +			std::string data = ""; + +			while ( ( n = read_line( socket, buffer, ICAP_BUFFER_SIZE, true ) ) > 2 ) { +				data.append( buffer ); +			} + +			icap::RequestHeader * req_header = new icap::RequestHeader( data ); +			return req_header; + +		} + + +		bool read_req_data( icap::Request * request, socketlibrary::TCPSocket * socket ) throw() { + +			int data_offset = 0; +			int data_length = 0; +			int data_read   = 0; +			std::vector<icap::Header::encapsulated_header_data_t> sorted_encaps_header; +			std::vector<icap::Header::encapsulated_header_data_t>::iterator sorted_idx; + +			// payload +			icap::payload_t payload; +			payload.req_header = ""; +			payload.req_body   = ""; +			payload.res_header = ""; +			payload.res_body   = ""; +			payload.ieof       = false; + +			// header +			icap::Header * header = request->header(); +			sorted_encaps_header  = header->sort_encapsulated_header(); + +			// loop through the sorted header +			for ( sorted_idx = sorted_encaps_header.begin(); sorted_idx != sorted_encaps_header.end(); sorted_idx++ ) { + +				// don't want to read negative headers +				if ( sorted_idx->second < 0 ) { +					continue; +				} + +				// if this is the last header entity then check for chunked content +				if ( sorted_idx == ( sorted_encaps_header.end() - 1 ) ) { + +					if ( sorted_idx->first == "req-body" ) { +						payload.ieof = read_chunked_payload( socket, payload.req_body ); +					} else if ( sorted_idx->first == "res-body" ) { +						payload.ieof = read_chunked_payload( socket, payload.res_body ); +					} else { +						/* +						*  null-body is the only other legal possibility here +						*  we take that into account in the previous iterations +						*/ +						break; +					} + +				} else { + +					data_offset = sorted_idx->second; +					data_length = ( ( sorted_idx + 1 )->second - data_offset ); + + +					/* read request data */ + +					// is there anything to read? +					if ( data_length > 0  ) { + +						// update payload +						if ( sorted_idx->first == "req-hdr" ) { +							payload.req_header = read_data( socket, data_length ); +						} else if (  sorted_idx->first == "req-body" ) { +							payload.req_body   = read_data( socket, data_length ); +						} else if (  sorted_idx->first == "res-hdr" ) { +							payload.res_header = read_data( socket, data_length ); +						} else if (  sorted_idx->first == "res-body" ) { +							payload.res_body   = read_data( socket, data_length ); +						} else { +							// TODO: error? +						} + +					} + +				} + +			} + +			// update request +			request->payload( payload ); + +			return true; + +		} + + +		bool read_req_continue_data( icap::Request * request, socketlibrary::TCPSocket * socket ) throw() { + +			std::vector<icap::Header::encapsulated_header_data_t> sorted_encaps_header; +			icap::Header::encapsulated_header_data_t header_idx; + +			// copy the payload from request so we can append to it +			icap::payload_t payload; +			payload.req_header = request->payload().req_header; +			payload.req_body   = request->payload().req_body; +			payload.res_header = request->payload().res_header; +			payload.res_body   = request->payload().res_body; +			payload.ieof       = request->payload().ieof; + +			// header +			icap::Header * header = request->header(); +			sorted_encaps_header  = header->sort_encapsulated_header(); + +			// sanity check +			if ( sorted_encaps_header.size() > 0 ) { + +				// we are only interested in the last header entity +				header_idx = sorted_encaps_header.back(); + +				// read payload data +				if ( header_idx.first == "req-body" ) { +					payload.ieof = read_chunked_payload( socket, payload.req_body ); +				} else if ( header_idx.first == "res-body" ) { +					payload.ieof = read_chunked_payload( socket, payload.res_body ); +				} + +			} else { + +				// something isn't quite right +				return false; + +			} + +			// update request +			request->payload( payload ); + +			return true; + +		} + + +		bool send_headers( icap::Header * header, socketlibrary::TCPSocket * socket ) throw() { + +			std::string line; +			icap::Header::headers_index_t i; +			icap::ResponseHeader::headers_t headers; + +			// headers +			headers = header->headers(); + +			for ( i = headers.begin(); i != headers.end(); i++ ) { + +				line = i->first; +				line.append( ": " ); +				line.append( i->second ); + +				if (! send_line( line, socket ) ) { +					return false; +				} + +			} + +			// send encapsulated header +			line = "Encapsulated: "; +			line.append( header->encapsulated_header_str() ); +			if (! send_line( line, socket ) ) { +				return false; +			} + +			// end of header +			if (! send_data( "\r\n", socket ) ) { +				return false; +			} + +			return true; + +		} + + +		bool send_response( icap::Response * response, socketlibrary::TCPSocket * socket ) throw() { + +			bool r_success = true; + +			icap::ResponseHeader * header; + +			// grab the response header +			header = response->header(); + +			// response status +			std::string line = header->protocol(); +			line.append( " " ); +			line.append( itoa( header->status() ) ); +			line.append( " " ); +			line.append( response_status( header->status() ) ); + +			r_success = send_line( line, socket ); + +			// response headers +			if ( r_success ) { +				r_success = send_headers( header, socket ); +			} + +			// response content (if there are any) +			if ( r_success ) { + +				// req-hdr +				if ( response->payload().req_header.size() > 0 ) { +					send_data( response->payload().req_header, socket ); +				} + +				// red-body +				if ( response->payload().req_body.size() > 0 ) { +					send_chunked( response->payload().req_body, socket ); +				} + +				// res-hdr +				if ( response->payload().res_header.size() > 0 ) { +					send_data( response->payload().res_header, socket ); +				} + +				// res-body +				if ( response->payload().res_body.size() > 0 ) { +					send_chunked( response->payload().res_body, socket ); +				} + +			} + +			return r_success; + +		} + + +		const std::string response_status( const ResponseHeader::status_t &status ) throw() { + +			// FIXME: probably there's a better way of mapping this +			std::map<ResponseHeader::status_t, std::string> status_text; + +			status_text[ResponseHeader::CONTINUE]           = "Continue"; +			status_text[ResponseHeader::OK]                 = "OK"; +			status_text[ResponseHeader::NO_CONTENT]         = "No modifications needed"; +			status_text[ResponseHeader::BAD_REQUEST]        = "Bad request"; +			status_text[ResponseHeader::NOT_FOUND]          = "ICAP Service not found"; +			status_text[ResponseHeader::NOT_ALLOWED]        = "Method not allowed for service"; +			status_text[ResponseHeader::REQ_TIMEOUT]        = "Request timeout"; +			status_text[ResponseHeader::SERVER_ERROR]       = "Server error"; +			status_text[ResponseHeader::NOT_IMPLEMENTED]    = "Method not implemented"; +			status_text[ResponseHeader::BAD_GATEWAY]        = "Bad gateway"; +			status_text[ResponseHeader::SERVICE_OVERLOADED] = "Service overloaded"; +			status_text[ResponseHeader::NOT_SUPPORTED]      = "ICAP version not supported by server"; + +			return status_text[status]; + +		} + +	} /* end of namespace util */ + +} /* end of namespace icap */ + diff --git a/lib/icap/util.h b/lib/icap/util.h new file mode 100644 index 0000000..366bb9c --- /dev/null +++ b/lib/icap/util.h @@ -0,0 +1,265 @@ +/* + *	C++ ICAP library + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifndef ICAP_UTIL_H +#define ICAP_UTIL_H + +#include <sstream> + +#include <socket/socket.h> +#include "request.h" +#include "response.h" + +#ifndef ICAP_BUFFER_SIZE +#define ICAP_BUFFER_SIZE 1024 +#endif + + +namespace icap { + +	namespace util { + +		struct chunk_t { +			unsigned int size; +			std::string  extention; +			std::string  data; +		}; + +		/** +		*   Convert a number into a string +		* +		*   @param number number to be converted +		*   @return converted string +		*/ +		template <typename T> std::string itoa( T number ) { +			std::ostringstream ss; +			ss << number; + +			return ss.str(); +		} + +		/** +		*   Convert a hexadecimal number to a decimal number. +		* +		*   @param hex hex to convert to +		*   @return converted decimal value +		*/ +		unsigned int hextodec( const std::string &hex ) throw(); + +		/** +		*   Convert a decimal number to its hexadecimal value +		* +		*   @param dec decimal number +		*   @return converted hex value +		*/ +		const std::string dectohex( const unsigned int &dec ) throw(); + +		/** +		*   Read a line (ending with \r\n) from the socket +		* +		*   @param socket socket to read from +		*   @param buf buffer to read the data into +		*   @param buf_length length / size of the buffer data is read into +		*   @param incl_endl (optional) switch to control whether to include \r\n in the read line, +		*          default is false. +		*   @return number of bytes read +		*/ +		int read_line( socketlibrary::TCPSocket * socket, char * buf, int buf_length, bool incl_endl = false ) throw(); + +		/** +		*   Read a line (ending with \r\n) from the socket +		* +		*   @param socket socket instance to read data from +		*   @param incl_endl (optional) switch to control whether to include \r\n in the read line, +		*          default is false. +		*   @return read data +		*/ +		std::string read_line( socketlibrary::TCPSocket * socket, bool incl_endl = false ) throw(); + +		/** +		*   Read data from the socket +		* +		*   @param socket socket instance to read data from +		*   @param size size / length of data to be read +		*   @return read data +		*/ +		std::string read_data( socketlibrary::TCPSocket * socket, int size ) throw(); + +		/** +		*   Read chunk size. This is a helper method used by read_chunked(). +		* +		*   @param socket socket instance to read from +		*   @return chunk size +		*/ +		unsigned int read_chunk_size( socketlibrary::TCPSocket * socket ) throw(); + +		/** +		*   Read chunk header from the given socket. +		* +		*   @param socket socket instance to read data from +		*   @param chunk chunk data structure to store header data +		*/ +		void read_chunk_header( socketlibrary::TCPSocket * socket, chunk_t &chunk ) throw(); + +		/** +		*   Read a data chunk from a HTTP chunked transfer encoded data stream. +		* +		*   @param socket socket instance to read data from +		*   @return chunk data structure +		*/ +		chunk_t read_chunk( socketlibrary::TCPSocket * socket ) throw(); + +		/** +		*   Read chunked data from the given socket +		* +		*   @param socket socket instance to read data from +		*   @return read data (without the control characters) +		*/ +		std::string read_chunked( socketlibrary::TCPSocket * socket ) throw(); + +		/** +		*   Read chunked payload data from the given socket +		* +		*   @param socket socket instance to read data from +		*   @param payload payload to read data into +		*   @return boolean flag to denote the presence of "ieof" +		*/ +		bool read_chunked_payload( socketlibrary::TCPSocket * socket, std::string &payload ) throw(); + +		/** +		*   Send / write a line (ending with \r\n) to the socket +		* +		*   @param line line to send through the socket without the line-ending chars +		*   @param socket socket object to write the data to +		*   @return boolean to denote success or failure +		*/ +		bool send_line( const std::string &line, socketlibrary::TCPSocket * socket ) throw(); + +		/** +		*   Send / write data to the socket. +		*   If chunked is set to true then data will be transferred using +		*   "chunked" transfer-encoding. +		* +		*   @param data data to be sent +		*   @param socket socket instance to write to +		*   @return boolean to denote success or failure +		*/ +		bool send_data( const std::string &data, socketlibrary::TCPSocket * socket ) throw(); + +		/** +		*   Send / write data to the socket using chunked transfer encoding +		* +		*   @param data data to be sent +		*   @param socket socket instance to write to +		*   @return boolean to denote success or failure +		*/ +		bool send_chunked( const std::string &data, socketlibrary::TCPSocket * socket ) throw(); + +		/** +		*   split a string into a vector by the given delimiter +		* +		*   @param str input string +		*   @param delimiter (optional) delimiter, defaults to " " +		*/ +		std::vector<std::string> split( const std::string &str, const std::string &delimiter = " " ) throw(); + +		/** +		*   Left trim (trim from start) a passed in string +		* +		*   @param str string to trim +		*   @return trimmed string +		*/ +		std::string <rim( std::string &str ) throw(); + +		/** +		*   Right trim (trim from end) a passed in string +		* +		*   @param str string to trim +		*   @return trimmed string +		*/ +		std::string &rtrim( std::string &str ) throw(); + +		/** +		*   Trim (trim from both ends) a passed in string +		* +		*   @param str string to trim +		*   @return trimmed string +		*/ +		std::string &trim( std::string &str ) throw(); + +		/** +		*   Read icap request header from the socket passes in +		* +		*   @param socket socket object to read data from +		*   @return icap request header object +		*/ +		icap::RequestHeader * read_req_header( socketlibrary::TCPSocket * socket ) throw(); + +		/** +		*   Read icap request into the icap::Request instance +		*   using the socket passed in +		* +		*   @param request request object to read data into +		*   @param socket socket object to read data from +		*   @return boolean to denote success or failure +		*/ +		bool read_req_data( icap::Request * request, socketlibrary::TCPSocket * socket ) throw(); + +		/** +		*   Read icap request data after a '100 Continue' response. This will not look for any +		*   additional headers and will treat any data coming through the socket as payload data. +		* +		*   @param request request object to read data into +		*   @param socket socket object to read data from +		*   @return boolean to denote success or failure +		*/ +		bool read_req_continue_data( icap::Request * request, socketlibrary::TCPSocket * socket ) throw(); + +		/** +		*   Send / write header data to a socket +		* +		*   @param headers headers to be sent +		*   @param socket socket object to write the data to +		*   @return boolean to denote success or failure +		*/ +		bool send_headers( icap::Header::headers_t headers, socketlibrary::TCPSocket * socket ) throw(); + +		/** +		*   Output a response using the passed in icap::Response class to the +		*   passed in socket +		* +		*   @param response response object to get the response data from +		*   @param socket socket object to send the data to +		*   @return boolean to denote success or failure +		*/ +		bool send_response( icap::Response * response, socketlibrary::TCPSocket * socket ) throw(); + +		/** +		*   Returns the response status text for the given status +		* +		*   @param status status to get the text for +		*/ +		const std::string response_status( const ResponseHeader::status_t &status ) throw(); + +	} /* end of namespace util */ + +} /* end of namespace icap */ + +#endif /* !ICAP_UTIL_H */ + diff --git a/lib/socket/Makefile.am b/lib/socket/Makefile.am new file mode 100644 index 0000000..93f98a5 --- /dev/null +++ b/lib/socket/Makefile.am @@ -0,0 +1,4 @@ +## [socket-library] lib/ +noinst_LTLIBRARIES      = libsocket.la +libsocket_la_SOURCES    = socket.h socket.cpp + diff --git a/lib/socket/socket.cpp b/lib/socket/socket.cpp new file mode 100644 index 0000000..a086d95 --- /dev/null +++ b/lib/socket/socket.cpp @@ -0,0 +1,472 @@ +/* + *	C++ sockets on Unix and Windows + *	Copyright (C) 2002	<unknown> + *	Copyright (C) 2010	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ +  +#include <socket.h> + +#ifndef WIN32 +	#include <sys/types.h>			// For data types +	#include <sys/socket.h>			// For socket(), connect(), send(), and recv() +	#include <netdb.h>				// For gethostbyname() +	#include <arpa/inet.h>			// For inet_addr() +	#include <unistd.h>				// For close() +#endif + +#include <cerrno>					// For errno +#include <cstring>					// For strerror +#include <cstdlib>					// For atoi() + +using namespace std; + +namespace socketlibrary { + +#ifdef WIN32 +	static bool initialized = false; +#endif + +// SocketException Code + +SocketException::SocketException(const string &message, bool inclSysMsg) throw() : userMessage(message) { +	if (inclSysMsg) { +		userMessage.append(": "); +		userMessage.append(strerror(errno)); +	} +} + +SocketException::~SocketException() throw() { +} + +const char *SocketException::what() const throw() { +	return userMessage.c_str(); +} + +// Function to fill in address structure given an address and port +void fillAddr(const string &address, unsigned short port, sockaddr_in &addr) { + +	memset(&addr, 0, sizeof(addr));  // Zero out address structure +	addr.sin_family = AF_INET;       // Internet address + +	hostent *host;  // Resolve name +	if ((host = gethostbyname(address.c_str())) == NULL) { +		// strerror() will not work for gethostbyname() and hstrerror()  +		// is supposedly obsolete +		throw SocketException("Failed to resolve name (gethostbyname())"); +	} +	 +	addr.sin_addr.s_addr = *((unsigned long *) host->h_addr_list[0]); +	addr.sin_port = htons(port);     // Assign port in network byte order +	 +} + +// Socket Code + +Socket::Socket(int type, int protocol) throw(SocketException) { +#ifdef WIN32 +	if (!initialized) { +		WORD wVersionRequested; +		WSADATA wsaData; + +		wVersionRequested = MAKEWORD(2, 0);							// Request WinSock v2.0 +		if (WSAStartup(wVersionRequested, &wsaData) != 0) {			// Load WinSock DLL +			throw SocketException("Unable to load WinSock DLL"); +		} +		initialized = true; +	} +#endif + +	// Make a new socket +	if ((sock = socket(PF_INET, type, protocol)) < 0) { +		throw SocketException("Socket creation failed (socket())", true); +	} +} + +Socket::Socket(int sock) { +	this->sock = sock; +} + +Socket::~Socket() { + +#ifdef WIN32 +	::closesocket(sock); +#else +	::close(sock); +#endif +	sock = -1; +} + +string Socket::getLocalAddress() throw(SocketException) { +	sockaddr_in addr; +	unsigned int addr_len = sizeof(addr); + +	if (getsockname(sock, (sockaddr *) &addr, (socklen_t *) &addr_len) < 0) { +		throw SocketException("Fetch of local address failed (getsockname())", true); +	} +	return inet_ntoa(addr.sin_addr); +} + +unsigned short Socket::getLocalPort() throw(SocketException) { +	sockaddr_in addr; +	unsigned int addr_len = sizeof(addr); + +	if (getsockname(sock, (sockaddr *) &addr, (socklen_t *) &addr_len) < 0) { +		throw SocketException("Fetch of local port failed (getsockname())", true); +	} +	return ntohs(addr.sin_port); +} + +void Socket::setLocalPort(unsigned short localPort) throw(SocketException) { +	// Bind the socket to its port +	sockaddr_in localAddr; +	memset(&localAddr, 0, sizeof(localAddr)); +	localAddr.sin_family = AF_INET; +	localAddr.sin_addr.s_addr = htonl(INADDR_ANY); +	localAddr.sin_port = htons(localPort); + +	if (bind(sock, (sockaddr *) &localAddr, sizeof(sockaddr_in)) < 0) { +		throw SocketException("Set of local port failed (bind())", true); +	} +} + +void Socket::setLocalAddressAndPort(const string &localAddress, unsigned short localPort) throw(SocketException) { +	// Get the address of the requested host +	sockaddr_in localAddr; +	fillAddr(localAddress, localPort, localAddr); + +	if (bind(sock, (sockaddr *) &localAddr, sizeof(sockaddr_in)) < 0) { +		throw SocketException("Set of local address and port failed (bind())", true); +	} +} + +void Socket::cleanUp() throw(SocketException) { +#ifdef WIN32 +	if (WSACleanup() != 0) { +		throw SocketException("WSACleanup() failed"); +	} +#endif +} + +unsigned short Socket::resolveService(const string &service, const string &protocol) { + +	struct servent *serv;        /* Structure containing service information */ + +	if ((serv = getservbyname(service.c_str(), protocol.c_str())) == NULL) +		return atoi(service.c_str());  /* Service is port number */ +	else  +		return ntohs(serv->s_port);    /* Found port (network byte order) by name */ +	 +} + +// CommunicatingSocket Code + +CommunicatingSocket::CommunicatingSocket(int type, int protocol) throw(SocketException) : Socket(type, protocol) { +} + +CommunicatingSocket::CommunicatingSocket(int newSD) : Socket(newSD) { +} + +void CommunicatingSocket::connect(const string &foreignAddress, unsigned short foreignPort) throw(SocketException) { +	// Get the address of the requested host +	sockaddr_in destAddr; +	fillAddr(foreignAddress, foreignPort, destAddr); + +	// Try to connect to the given port +	if (::connect(sock, (sockaddr *) &destAddr, sizeof(destAddr)) < 0) { +		throw SocketException("Connect failed (connect())", true); +	} +} + +void CommunicatingSocket::send(const void *buffer, int bufferLen) throw(SocketException) { +	if (::send(sock, (raw_type *) buffer, bufferLen, 0) < 0) { +		throw SocketException("Send failed (send())", true); +	} +} + +int CommunicatingSocket::recv(void *buffer, int bufferLen) throw(SocketException) { +	int rtn; +	if ((rtn = ::recv(sock, (raw_type *) buffer, bufferLen, 0)) < 0) { +		throw SocketException("Received failed (recv()) for socket ", true); +	} +	return rtn; +} + +int CommunicatingSocket::peek(void *buffer, int bufferLen) throw(SocketException) { +	int rtn; +	if ((rtn = ::recv(sock, (raw_type *) buffer, bufferLen, MSG_PEEK)) < 0) { +		throw SocketException("Received failed (recv()) for socket ", true); +	} +	return rtn; +} + +int CommunicatingSocket::readLine(char *buffer, int bufferLen, const char delimiter) throw(SocketException) { + +	int n, rc; +	char c; + +	for (n = 1; n < bufferLen; n++) { +		if ((rc = recv(&c, 1)) == 1) { +			*buffer++ = c; +			if (c == delimiter) { +				break; +			} +		} else if (rc == 0) { +			if (n == 1) { +				return 0; // EOF, no data read +			} else { +				break; // EOF, read some data +			} +		} else { +			throw SocketException("Failed to read data from socket ", true); +		} +	} + +	*buffer = '\0'; +	return n; + +} + +string CommunicatingSocket::getForeignAddress() throw(SocketException) { +	sockaddr_in addr; +	unsigned int addr_len = sizeof(addr); + +	if (getpeername(sock, (sockaddr *) &addr,(socklen_t *) &addr_len) < 0) { +		throw SocketException("Fetch of foreign address failed (getpeername())", true); +	} +	return inet_ntoa(addr.sin_addr); +} + +unsigned short CommunicatingSocket::getForeignPort() throw(SocketException) { +	sockaddr_in addr; +	unsigned int addr_len = sizeof(addr); + +	if (getpeername(sock, (sockaddr *) &addr, (socklen_t *) &addr_len) < 0) { +		throw SocketException("Fetch of foreign port failed (getpeername())", true); +	} +	return ntohs(addr.sin_port); +} + +// TCPSocket Code + +TCPSocket::TCPSocket() throw(SocketException) : CommunicatingSocket(SOCK_STREAM, IPPROTO_TCP) { +} + +TCPSocket::TCPSocket(const string &foreignAddress, unsigned short foreignPort) throw(SocketException) : CommunicatingSocket(SOCK_STREAM, IPPROTO_TCP) { +	connect(foreignAddress, foreignPort); +} + +TCPSocket::TCPSocket(int newSD) : CommunicatingSocket(newSD) { +} + +// TCPServerSocket Code + +TCPServerSocket::TCPServerSocket(unsigned short localPort, int queueLen) throw(SocketException) : Socket(SOCK_STREAM, IPPROTO_TCP) { +	setLocalPort(localPort); +	setListen(queueLen); +} + +TCPServerSocket::TCPServerSocket(const string &localAddress, unsigned short localPort, int queueLen) throw(SocketException) : Socket(SOCK_STREAM, IPPROTO_TCP) { +	setLocalAddressAndPort(localAddress, localPort); +	setListen(queueLen); +} + +TCPSocket *TCPServerSocket::accept() throw(SocketException) { +	int newSD;	 +	if ((newSD = ::accept(sock, NULL, 0)) < 0) { +		throw SocketException("Accept failed (accept())", true); +	} +	return new TCPSocket(newSD); +} + +void TCPServerSocket::setListen(int queueLen) throw(SocketException) { +	if (listen(sock, queueLen) < 0) { +		throw SocketException("Set listening socket failed (listen())", true); +	} +} + +// TCPServerSocketM Code  + +TCPServerSocketM::TCPServerSocketM(unsigned short localPort, int queueLen) throw(SocketException) : TCPServerSocket(localPort, queueLen) { +	 +	FD_ZERO(&fds_master);		// clear the master and temp sets + +	FD_SET(sock, &fds_master);	// Add ourself to the master set +	fdmax = sock;				// keep track of the biggest file descriptor, only ourself for the moment +	 +} + +TCPSocket *TCPServerSocketM::accept() throw(SocketException) { +	 +	TCPSocket *newClient = TCPServerSocket::accept(); +	int newSD = newClient->sock; + +	FD_SET(newSD, &fds_master); 	// add to master set +	if (newSD > fdmax) {    		// keep track of the max +		fdmax = newSD; +	} +	 +	v_clients.push_back(newClient);	 +	return newClient; +	 +} + +bool TCPServerSocketM::pendingConnections() throw (SocketException) { +	 +	fd_set read_fds; +	FD_ZERO(&read_fds); +	 +	read_fds = fds_master; +	if (select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1) { +		throw SocketException("Failed to select read fds (select())", true); +	} +	 +	if (FD_ISSET(sock, &read_fds)) { +		return true; +	} else { +		return false; +	} +	 +} + +int TCPServerSocketM::getWaitingClients(vector<TCPSocket *> &clients) throw (SocketException) { + +	fd_set read_fds; +	FD_ZERO(&read_fds); +	 +	int cl_count = 0; +	 +	read_fds = fds_master; +	if (select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1) { +		throw SocketException("Failed to select read fds (select())", true); +	} + +	// resize the vector so it doesn't contain any old information +	clients.resize(0); +	 +	for(unsigned int i=0; i<v_clients.size(); i++) { +		if (FD_ISSET(v_clients.at(i)->sock, &read_fds)) { // we got one!! +			clients.push_back(v_clients.at(i)); +			cl_count++; +		} +	} +	 +	return cl_count; +} + +void TCPServerSocketM::closeClientConnection(TCPSocket * client) { +	 +	for(unsigned int i=0; i<v_clients.size(); i++) { +		if (client->sock == v_clients.at(i)->sock) {			 +			FD_CLR(client->sock, &fds_master);  +			v_clients.erase(v_clients.begin() + i); +			delete client; +			break; +		} +	} +	 +} + + +// UDPSocket Code + +UDPSocket::UDPSocket() throw(SocketException) : CommunicatingSocket(SOCK_DGRAM, IPPROTO_UDP) { +	setBroadcast(); +} + +UDPSocket::UDPSocket(unsigned short localPort)  throw(SocketException) : CommunicatingSocket(SOCK_DGRAM, IPPROTO_UDP) { +	setLocalPort(localPort); +	setBroadcast(); +} + +UDPSocket::UDPSocket(const string &localAddress, unsigned short localPort) throw(SocketException) : CommunicatingSocket(SOCK_DGRAM, IPPROTO_UDP) { +	setLocalAddressAndPort(localAddress, localPort); +	setBroadcast(); +} + +void UDPSocket::setBroadcast() { +	// If this fails, we'll hear about it when we try to send.  This will allow  +	// system that cannot broadcast to continue if they don't plan to broadcast +	int broadcastPermission = 1; +	setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (raw_type *) &broadcastPermission, sizeof(broadcastPermission)); +} + +void UDPSocket::disconnect() throw(SocketException) { +	sockaddr_in nullAddr; +	memset(&nullAddr, 0, sizeof(nullAddr)); +	nullAddr.sin_family = AF_UNSPEC; + +	// Try to disconnect +	if (::connect(sock, (sockaddr *) &nullAddr, sizeof(nullAddr)) < 0) { +#ifdef WIN32 +		if (errno != WSAEAFNOSUPPORT) { +#else +		if (errno != EAFNOSUPPORT) { +#endif +			throw SocketException("Disconnect failed (connect())", true); +		} +	} +} + +void UDPSocket::sendTo(const void *buffer, int bufferLen, const string &foreignAddress, unsigned short foreignPort) throw(SocketException) { +	sockaddr_in destAddr; +	fillAddr(foreignAddress, foreignPort, destAddr); + +	// Write out the whole buffer as a single message. +	if (sendto(sock, (raw_type *) buffer, bufferLen, 0, (sockaddr *) &destAddr, sizeof(destAddr)) != bufferLen) { +		throw SocketException("Send failed (sendto())", true); +	} +} + +int UDPSocket::recvFrom(void *buffer, int bufferLen, string &sourceAddress, unsigned short &sourcePort) throw(SocketException) { +	sockaddr_in clntAddr; +	socklen_t addrLen = sizeof(clntAddr); +	int rtn; +	if ((rtn = recvfrom(sock, (raw_type *) buffer, bufferLen, 0, (sockaddr *) &clntAddr, (socklen_t *) &addrLen)) < 0) { +		throw SocketException("Receive failed (recvfrom())", true); +	} +	sourceAddress = inet_ntoa(clntAddr.sin_addr); +	sourcePort = ntohs(clntAddr.sin_port); +	return rtn; +} + +void UDPSocket::setMulticastTTL(unsigned char multicastTTL) throw(SocketException) { +	if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (raw_type *) &multicastTTL, sizeof(multicastTTL)) < 0) { +		throw SocketException("Multicast TTL set failed (setsockopt())", true); +	} +} + +void UDPSocket::joinGroup(const string &multicastGroup) throw(SocketException) { +	struct ip_mreq multicastRequest; + +	multicastRequest.imr_multiaddr.s_addr = inet_addr(multicastGroup.c_str()); +	multicastRequest.imr_interface.s_addr = htonl(INADDR_ANY); +	if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (raw_type *) &multicastRequest, sizeof(multicastRequest)) < 0) { +		throw SocketException("Multicast group join failed (setsockopt())", true); +	} +} + +void UDPSocket::leaveGroup(const string &multicastGroup) throw(SocketException) { +	struct ip_mreq multicastRequest; + +	multicastRequest.imr_multiaddr.s_addr = inet_addr(multicastGroup.c_str()); +	multicastRequest.imr_interface.s_addr = htonl(INADDR_ANY); +	if (setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, (raw_type *) &multicastRequest, sizeof(multicastRequest)) < 0) { +		throw SocketException("Multicast group leave failed (setsockopt())", true); +	} +} + +} // End of namespace SocketLibrary diff --git a/lib/socket/socket.h b/lib/socket/socket.h new file mode 100644 index 0000000..2c4d777 --- /dev/null +++ b/lib/socket/socket.h @@ -0,0 +1,427 @@ +/* + *	C++ sockets on Unix and Windows + *	Copyright (C) 2002	<unknown> + *	Copyright (C) 2010	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifndef SL_SOCKET_H +#define SL_SOCKET_H + +#include <string>			// For string +#include <exception>		// For exception class +#include <vector>			// For vectors + +#ifdef WIN32 +	#include <winsock.h>			// For socket(), connect(), send(), and recv() +	typedef int socklen_t; +	typedef char raw_type;			// Type used for raw data on this platform +#else +	#include <netinet/in.h>         // For sockaddr_in +	typedef void raw_type;			// Type used for raw data on this platform +#endif + +using namespace std; + +namespace socketlibrary { + +/** + * Function to fill in address structure given an address and port + */ +void fillAddr(const string &address, unsigned short port, sockaddr_in &addr); + +/** + *   Signals a problem with the execution of a socket call. + */ +class SocketException : public exception { +public: +	/** +	*   Construct a SocketException with a explanatory message. +	*   @param message explanatory message +	*   @param incSysMsg true if system message (from strerror(errno)) +	*   should be postfixed to the user provided message +	*/ +	SocketException(const string &message, bool inclSysMsg = false) throw(); + +	/** +	*   Provided just to guarantee that no exceptions are thrown. +	*/ +	~SocketException() throw(); + +	/** +	*   Get the exception message +	*   @return exception message +	*/ +	const char *what() const throw(); + +private: +	string userMessage;		// Exception message +}; + + +/** + *   Base class representing basic communication endpoint + */ +class Socket { +public: +	/** +	*   Close and deallocate this socket +	*/ +	~Socket(); + +	/** +	*   Get the local address +	*   @return local address of socket +	*   @exception SocketException thrown if fetch fails +	*/ +	string getLocalAddress() throw(SocketException); + +	/** +	*   Get the local port +	*   @return local port of socket +	*   @exception SocketException thrown if fetch fails +	*/ +	unsigned short getLocalPort() throw(SocketException); + +	/** +	*   Set the local port to the specified port and the local address +	*   to any interface +	*   @param localPort local port +	*   @exception SocketException thrown if setting local port fails +	*/ +	void setLocalPort(unsigned short localPort) throw(SocketException); + +	/** +	*   Set the local port to the specified port and the local address +	*   to the specified address.  If you omit the port, a random port  +	*   will be selected. +	*   @param localAddress local address +	*   @param localPort local port +	*   @exception SocketException thrown if setting local port or address fails +	*/ +	void setLocalAddressAndPort(const string &localAddress, unsigned short localPort = 0) throw(SocketException); + +	/** +	*   If WinSock, unload the WinSock DLLs; otherwise do nothing.  We ignore +	*   this in our sample client code but include it in the library for +	*   completeness.  If you are running on Windows and you are concerned +	*   about DLL resource consumption, call this after you are done with all +	*   Socket instances.  If you execute this on Windows while some instance of +	*   Socket exists, you are toast.  For portability of client code, this is  +	*   an empty function on non-Windows platforms so you can always include it. +	*   @param buffer buffer to receive the data +	*   @param bufferLen maximum number of bytes to read into buffer +	*   @return number of bytes read, 0 for EOF, and -1 for error +	*   @exception SocketException thrown WinSock clean up fails +	*/ +	static void cleanUp() throw(SocketException); + +	/** +	*   Resolve the specified service for the specified protocol to the +	*   corresponding port number in host byte order +	*   @param service service to resolve (e.g., "http") +	*   @param protocol protocol of service to resolve.  Default is "tcp". +	*/ +	static unsigned short resolveService(const string &service, const string &protocol = "tcp"); +	 +private: +	// Prevent the user from trying to use value semantics on this object +	Socket(const Socket &sock); +	void operator=(const Socket &sock); + +protected: +	int sock;				// Socket descriptor +	Socket(int type, int protocol) throw(SocketException); +	Socket(int sock); +}; + +/** + *   Socket which is able to connect, send, and receive + */ +class CommunicatingSocket : public Socket { +public: +	/** +	*   Establish a socket connection with the given foreign +	*   address and port +	*   @param foreignAddress foreign address (IP address or name) +	*   @param foreignPort foreign port +	*   @exception SocketException thrown if unable to establish connection +	*/ +	void connect(const string &foreignAddress, unsigned short foreignPort) throw(SocketException); + +	/** +	*   Write the given buffer to this socket.  Call connect() before +	*   calling send() +	*   @param buffer buffer to be written +	*   @param bufferLen number of bytes from buffer to be written +	*   @exception SocketException thrown if unable to send data +	*/ +	void send(const void *buffer, int bufferLen) throw(SocketException); + +	/** +	*   Read into the given buffer up to bufferLen bytes data from this +	*   socket.  Call connect() before calling recv() +	*   @param buffer buffer to receive the data +	*   @param bufferLen maximum number of bytes to read into buffer +	*   @return number of bytes read, 0 for EOF, and -1 for error +	*   @exception SocketException thrown if unable to receive data +	*/ +	int recv(void *buffer, int bufferLen) throw(SocketException); + +	/** +	*   Read into the given buffer up to bufferLen bytes data from this +	*   socket but don't remove the read bytes from the socket read buffer. +	*   Call connect() before calling peek() +	* +	*   @param buffer buffer to receive the data +	*   @param bufferLen maximum number of bytes to read into buffer +	*   @return number of bytes read, 0 for EOF, and -1 for error +	*   @exception SocketException thrown if unable to receive data +	*/ +	int peek(void *buffer, int bufferLen) throw(SocketException); + +	/** +	*   Read a line into the given buffer from this socket. +	*   Call connect() before calling recv() +	* +	*   @param buffer buffer to receive the data +	*   @param bufferLen maximum number of bytes to read into buffer +	*   @param delimiter (optional) end of line delimiter +	*   @return number of bytes read, 0 for EOF, and -1 for error +	*   @exception SocketException thrown if unable to receive data +	*/ +	int readLine(char *buffer, int bufferLen, const char delimiter = '\n') throw(SocketException); + +	/** +	*   Get the foreign address.  Call connect() before calling recv() +	*   @return foreign address +	*   @exception SocketException thrown if unable to fetch foreign address +	*/ +	string getForeignAddress() throw(SocketException); + +	/** +	*   Get the foreign port.  Call connect() before calling recv() +	*   @return foreign port +	*   @exception SocketException thrown if unable to fetch foreign port +	*/ +	unsigned short getForeignPort() throw(SocketException); + +protected: +	CommunicatingSocket(int type, int protocol) throw(SocketException); +	CommunicatingSocket(int newSD); +}; + +/** + *   TCP socket for communication with other TCP sockets + */ +class TCPSocket : public CommunicatingSocket { +public: +	/** +	*   Construct a TCP socket with no connection +	*   @exception SocketException thrown if unable to create TCP socket +	*/ +	TCPSocket() throw(SocketException); + +	/** +	*   Construct a TCP socket with a connection to the given foreign address +	*   and port +	*   @param foreignAddress foreign address (IP address or name) +	*   @param foreignPort foreign port +	*   @exception SocketException thrown if unable to create TCP socket +	*/ +	TCPSocket(const string &foreignAddress, unsigned short foreignPort) throw(SocketException); + +private: +	friend class TCPServerSocket;	// Access for TCPServerSocket::accept() connection creation +	friend class TCPServerSocketM;	// Access for TCPServerSocketM::accept() connection creation +	TCPSocket(int newSD); +}; + +/** + *   TCP socket class for servers + */ +class TCPServerSocket : public Socket { +public: +	/** +	*   Construct a TCP socket for use with a server, accepting connections +	*   on the specified port on any interface +	*   @param localPort local port of server socket, a value of zero will +	*                   give a system-assigned unused port +	*   @param queueLen maximum queue length for outstanding  +	*                   connection requests (default 5) +	*   @exception SocketException thrown if unable to create TCP server socket +	*/ +	TCPServerSocket(unsigned short localPort, int queueLen = 5) throw(SocketException); + +	/** +	*   Construct a TCP socket for use with a server, accepting connections +	*   on the specified port on the interface specified by the given address +	*   @param localAddress local interface (address) of server socket +	*   @param localPort local port of server socket +	*   @param queueLen maximum queue length for outstanding  +	*                   connection requests (default 5) +	*   @exception SocketException thrown if unable to create TCP server socket +	*/ +	TCPServerSocket(const string &localAddress, unsigned short localPort, int queueLen = 5) throw(SocketException); + +	/** +	*   Blocks until a new connection is established on this socket or error +	*   @return new connection socket +	*   @exception SocketException thrown if attempt to accept a new connection fails +	*/ +	TCPSocket *accept() throw(SocketException); + +private: +	void setListen(int queueLen) throw(SocketException); +}; + +/** + *   TCP socket class for multi-client servers + */ +class TCPServerSocketM : public TCPServerSocket { +public: + +	/** +	*   Construct a TCP socket for use with a server, accepting connections +	*   on the specified port on any interface +	*   @param localPort local port of server socket, a value of zero will +	*                   give a system-assigned unused port +	*   @param queueLen maximum queue length for outstanding  +	*                   connection requests (default 5) +	*   @exception SocketException thrown if unable to create TCP server socket +	*/ +	TCPServerSocketM(unsigned short localPort, int queueLen = 5) throw(SocketException); +	 +	/** +	*   Blocks until a new connection is established on this socket or error +	*   @return new connection socket +	*   @exception SocketException thrown if attempt to accept a new connection fails +	*/ +	TCPSocket *accept() throw(SocketException); +	 +	/** +	*   Checks for incoming connections or error +	*   @return boolean (true if incoming connections are present) +	*   @exception SocketException thrown if attempt to check for new connections fail +	*/ +	bool pendingConnections() throw(SocketException); +	 +	/** +	*   Checks for read waiting clients +	*   @param clients a vector of TCPSocket pointers to get the waiting clients +	*   @return number of clients waiting +	*   @exception SocketException thrown if attempt to check for waiting clients fail +	*/ +	int getWaitingClients(vector<TCPSocket *> &clients) throw (SocketException); +	 +	/** +	*   Closes the connection to a client +	*   @param client the client TCPSocket to close +	*/ +	void closeClientConnection(TCPSocket *client); +	 +private: +	fd_set fds_master;		// master file descriptor list +	int fdmax;				// maximum file descriptor number +	 +	vector<TCPSocket *> v_clients; +}; + +/** +  *   UDP socket class +  */ +class UDPSocket : public CommunicatingSocket { +public: +	/** +	*   Construct a UDP socket +	*   @exception SocketException thrown if unable to create UDP socket +	*/ +	UDPSocket() throw(SocketException); + +	/** +	*   Construct a UDP socket with the given local port +	*   @param localPort local port +	*   @exception SocketException thrown if unable to create UDP socket +	*/ +	UDPSocket(unsigned short localPort) throw(SocketException); + +	/** +	*   Construct a UDP socket with the given local port and address +	*   @param localAddress local address +	*   @param localPort local port +	*   @exception SocketException thrown if unable to create UDP socket +	*/ +	UDPSocket(const string &localAddress, unsigned short localPort) throw(SocketException); + +	/** +	*   Unset foreign address and port +	*   @return true if disassociation is successful +	*   @exception SocketException thrown if unable to disconnect UDP socket +	*/ +	void disconnect() throw(SocketException); + +	/** +	*   Send the given buffer as a UDP datagram to the +	*   specified address/port +	*   @param buffer buffer to be written +	*   @param bufferLen number of bytes to write +	*   @param foreignAddress address (IP address or name) to send to +	*   @param foreignPort port number to send to +	*   @return true if send is successful +	*   @exception SocketException thrown if unable to send datagram +	*/ +	void sendTo(const void *buffer, int bufferLen, const string &foreignAddress, unsigned short foreignPort) throw(SocketException); + +	/** +	*   Read read up to bufferLen bytes data from this socket.  The given buffer +	*   is where the data will be placed +	*   @param buffer buffer to receive data +	*   @param bufferLen maximum number of bytes to receive +	*   @param sourceAddress address of datagram source +	*   @param sourcePort port of data source +	*   @return number of bytes received and -1 for error +	*   @exception SocketException thrown if unable to receive datagram +	*/ +	int recvFrom(void *buffer, int bufferLen, string &sourceAddress, unsigned short &sourcePort) throw(SocketException); + +	/** +	*   Set the multicast TTL +	*   @param multicastTTL multicast TTL +	*   @exception SocketException thrown if unable to set TTL +	*/ +	void setMulticastTTL(unsigned char multicastTTL) throw(SocketException); + +	/** +	*   Join the specified multicast group +	*   @param multicastGroup multicast group address to join +	*   @exception SocketException thrown if unable to join group +	*/ +	void joinGroup(const string &multicastGroup) throw(SocketException); + +	/** +	*   Leave the specified multicast group +	*   @param multicastGroup multicast group address to leave +	*   @exception SocketException thrown if unable to leave group +	*/ +	void leaveGroup(const string &multicastGroup) throw(SocketException); + +private: +	void setBroadcast(); +}; + +} // End of namespace SocketLibrary + +#endif /* !SL_SOCKET_H */ diff --git a/modules/Makefile.am b/modules/Makefile.am new file mode 100644 index 0000000..c52d720 --- /dev/null +++ b/modules/Makefile.am @@ -0,0 +1,3 @@ +## modules/ +SUBDIRS = echo modpy + diff --git a/modules/echo/Makefile.am b/modules/echo/Makefile.am new file mode 100644 index 0000000..3236ad7 --- /dev/null +++ b/modules/echo/Makefile.am @@ -0,0 +1,9 @@ +# modules/echo +AM_CPPFLAGS             = -I$(top_srcdir)/lib -I$(top_srcdir)/src + +modlibdir               = $(pkglibdir)/modules +modlib_LTLIBRARIES      = mod_echo.la +mod_echo_la_LDFLAGS     = -module -avoid-version +mod_echo_la_SOURCES     = \ +	echo.h echo.cpp + diff --git a/modules/echo/echo.cpp b/modules/echo/echo.cpp new file mode 100644 index 0000000..a8496c5 --- /dev/null +++ b/modules/echo/echo.cpp @@ -0,0 +1,55 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include "echo.h" + + +namespace bitz { + +	Echo::Echo() : Modifier() { } +	Echo::~Echo() { } + + +	icap::Response * Echo::modify( icap::Request * request ) throw() { + +		icap::Response * response; +		icap::payload_t payload; + +		// copy payload from request +		payload.req_header = request->payload().req_header; +		payload.req_body   = request->payload().req_body; +		payload.res_header = request->payload().res_header; +		payload.res_body   = request->payload().res_body; + + +		response = new icap::Response( icap::ResponseHeader::OK ); +		response->payload( payload ); + +		return response; + +	} + + +	icap::Response * Echo::preview( icap::Request * request ) throw() { +		// 100 - continue always +		return new icap::Response( icap::ResponseHeader::CONTINUE ); +	} + +} /* end of namespace bitz */ + diff --git a/modules/echo/echo.h b/modules/echo/echo.h new file mode 100644 index 0000000..87df312 --- /dev/null +++ b/modules/echo/echo.h @@ -0,0 +1,54 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifndef BITZ_ECHO_H +#define BITZ_ECHO_H + +#include <bitz/modifier.h> + + +namespace bitz { + +	class Echo : public Modifier { +	public: +		Echo(); +		virtual ~Echo(); + +		icap::Response * modify( icap::Request * request ) throw(); +		icap::Response * preview( icap::Request * request ) throw(); + +	private: + +	}; + +} /* end of namespace bitz */ + + +/* class factories */ + +extern "C" bitz::Modifier * create() { +	return new bitz::Echo; +} + +extern "C" void destroy( bitz::Modifier * m ) { +	delete m; +} + +#endif /* !BITZ_ECHO_H */ + diff --git a/modules/modpy/Makefile.am b/modules/modpy/Makefile.am new file mode 100644 index 0000000..eccb2a2 --- /dev/null +++ b/modules/modpy/Makefile.am @@ -0,0 +1,18 @@ +# modules/modpy + +SUBDIRS = modules + +if MODPY +modlibdir               = $(pkglibdir)/modules +modlib_LTLIBRARIES      = mod_py.la +mod_py_la_LDFLAGS       = -module -avoid-version +mod_py_la_SOURCES       = \ +	py.h py.cpp \ +	interface.h interface.cpp + +AM_CPPFLAGS             = -I$(top_srcdir)/lib -I$(top_srcdir)/src \ +	${PYTHON_INCLUDES} ${libconfig_CFLAGS} ${log4cpp_CFLAGS} + +mod_py_la_LIBADD        = ${PYTHON_LIBS} +endif + diff --git a/modules/modpy/interface.cpp b/modules/modpy/interface.cpp new file mode 100644 index 0000000..948fa5c --- /dev/null +++ b/modules/modpy/interface.cpp @@ -0,0 +1,160 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include "interface.h" + +#include <bitz/logger.h> +#include <icap/request.h> +#include <icap/response.h> +#include <iostream> + + +PyObject * bitz_get_request( PyObject * self, PyObject * pyrequest ) { + +	PyObject * pyreturn; +	PyObject * pypayload; +	icap::Request * request; + +	// logger +	bitz::Logger &logger = bitz::Logger::instance(); +	logger.debug( "[modpy.interface] get_request()" ); + +	// initialise return dictionary +	pyreturn = PyDict_New(); + +	// grab the request object pointer from args +	void * p = PyCapsule_GetPointer( pyrequest, "request" ); + +	// sanity check +	if ( p != NULL ) { + +		// construct the request +		request = static_cast<icap::Request *>(p); + +		PyDict_SetItemString( pyreturn, "request", PyString_FromString( request->header()->method().c_str() ) ); +		PyDict_SetItemString( pyreturn, "uri", PyString_FromString( request->header()->uri().c_str() ) ); +		PyDict_SetItemString( pyreturn, "protocol", PyString_FromString( request->header()->protocol().c_str() ) ); + +		// payload dictionary +		pypayload = PyDict_New(); +		PyDict_SetItemString( pypayload, "req_header", PyString_FromStringAndSize( request->payload().req_header.c_str(), request->payload().req_header.size() ) ); +		PyDict_SetItemString( pypayload, "req_body", PyString_FromStringAndSize( request->payload().req_body.c_str(), request->payload().req_body.size() ) ); +		PyDict_SetItemString( pypayload, "res_header", PyString_FromStringAndSize( request->payload().res_header.c_str(), request->payload().res_header.size() ) ); +		PyDict_SetItemString( pypayload, "res_body", PyString_FromStringAndSize( request->payload().res_body.c_str(), request->payload().res_body.size() ) ); +		PyDict_SetItemString( pypayload, "ieof", PyBool_FromLong( request->payload().ieof ) ); + +		PyDict_SetItemString( pyreturn, "payload", pypayload ); + +		// cleanup +		Py_DECREF( pypayload ); + +	} else { +		logger.warn( "[modpy.interface] failed to get request object pointer" ); +	} + +	return pyreturn; + +} + + +PyObject * bitz_get_response_from_status( PyObject * self, PyObject * args ) { + +	PyObject * pyresponse; +	icap::Response * response; + +	unsigned int resp_status; + +	// logger +	bitz::Logger &logger = bitz::Logger::instance(); +	logger.debug( "[modpy.interface] get_response_from_status()" ); + +	// parse args +	if ( PyArg_ParseTuple( args, "I", &resp_status ) ) { +		response = new icap::Response( (icap::ResponseHeader::status_t) resp_status ); +	} else { +		logger.warn( "[modpy.interface] failed to parse arguments" ); +		response = new icap::Response( icap::ResponseHeader::SERVER_ERROR ); +	} + +	// convert the response into a capsule +	pyresponse = PyCapsule_New( (void *) response, "response", NULL ); + +	return pyresponse; + +} + + +PyObject * bitz_get_response( PyObject * self, PyObject * args ) { + +	PyObject * pyresponse; +	PyObject * pypayload; +	icap::Response * response = NULL; + +	unsigned int resp_status; +	icap::payload_t payload; + +	// vars to ferry across strings from python dictionary to c++ +	char * pybuffer; +	Py_ssize_t pybuflen; + + +	// logger +	bitz::Logger &logger = bitz::Logger::instance(); +	logger.debug( "[modpy.interface] get_response()" ); + +	// parse args +	if ( PyArg_ParseTuple( args, "IO!", &resp_status, &PyDict_Type, &pypayload ) ) { + +		// copy strings from python dictionary +		PyString_AsStringAndSize( PyDict_GetItemString( pypayload, "req_header" ), &pybuffer, &pybuflen ); +		payload.req_header.assign( pybuffer, pybuflen ); + +		PyString_AsStringAndSize( PyDict_GetItemString( pypayload, "req_body" ), &pybuffer, &pybuflen ); +		payload.req_body.assign( pybuffer, pybuflen ); + +		PyString_AsStringAndSize( PyDict_GetItemString( pypayload, "res_header" ), &pybuffer, &pybuflen ); +		payload.res_header.assign( pybuffer, pybuflen ); + +		PyString_AsStringAndSize( PyDict_GetItemString( pypayload, "res_body" ), &pybuffer, &pybuflen ); +		payload.res_body.assign( pybuffer, pybuflen ); + +		// copy other data types from python dictionary +		payload.ieof = PyBool_Check( PyDict_GetItemString( pypayload, "ieof" ) ); + +		// construct the response object +		response = new icap::Response( (icap::ResponseHeader::status_t) resp_status ); +		response->payload( payload ); + +	} else { +		logger.warn( "[modpy.interface] failed to parse arguments" ); +	} + +	// sanity check +	if ( response == NULL ) { +		response = new icap::Response( icap::ResponseHeader::SERVER_ERROR ); +	} + +	// convert the response into a capsule +	pyresponse = PyCapsule_New( (void *) response, "response", NULL ); + +	return pyresponse; + +} + + diff --git a/modules/modpy/interface.h b/modules/modpy/interface.h new file mode 100644 index 0000000..315a2f6 --- /dev/null +++ b/modules/modpy/interface.h @@ -0,0 +1,39 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifndef BITZ_MODPY_INTERFACE_H +#define BITZ_MODPY_INTERFACE_H + +#include <Python.h> +#include <stddef.h> + + +PyObject * bitz_get_request( PyObject * self, PyObject * pyrequest ); +PyObject * bitz_get_response( PyObject * self, PyObject * args ); +PyObject * bitz_get_response_from_status( PyObject * self, PyObject * args); + +static PyMethodDef bitz_methods[] = { +		{ "get_request", bitz_get_request, METH_O, "Convert a capsule request into a python dictionary" }, +		{ "get_response", bitz_get_response, METH_VARARGS, "Get a response capsule (takes in status and payload dictionary as args)" }, +		{ "get_response_from_status", bitz_get_response_from_status, METH_VARARGS, "Get a response capsule from a response status" }, +		{ NULL, NULL, 0, NULL } +}; + +#endif /* !BITZ_MODPY_INTERFACE_H */ + diff --git a/modules/modpy/modules/Makefile.am b/modules/modpy/modules/Makefile.am new file mode 100644 index 0000000..9292d1d --- /dev/null +++ b/modules/modpy/modules/Makefile.am @@ -0,0 +1,11 @@ +# modules/modpy/modules + +# extra dist files +EXTRA_DIST = \ +	modpy.py + +if MODPY +modpydir        = $(pkglibdir)/modules/modpy +modpy_DATA      = modpy.py +endif + diff --git a/modules/modpy/modules/modpy.py b/modules/modpy/modules/modpy.py new file mode 100644 index 0000000..9a5e578 --- /dev/null +++ b/modules/modpy/modules/modpy.py @@ -0,0 +1,42 @@ +# +# modpy.py +# Copyright (c) 2013 Uditha Atukorala +# + +import bitz + +def init(): +	print "init() called"; + +def cleanup(): +	print "cleanup() called"; + +def preview( request ): +	request     = bitz.get_request( request ); +	req_payload = request['payload']; +	print "preview payload: \r\n", req_payload; + +	# response +	if req_payload['ieof']: +		response = bitz.get_response_from_status( 204 ); +	else: +		response = bitz.get_response_from_status( 100 ); + +	return response; + +def modify( request ): +	request     = bitz.get_request( request ); +	req_payload = request['payload']; +	print "modify payload: \r\n", req_payload; + +	# response +	resp_payload = {}; +	resp_payload['req_header'] = req_payload['req_header']; +	resp_payload['req_body']   = req_payload['req_body']; +	resp_payload['res_header'] = req_payload['res_header']; +	resp_payload['res_body']   = req_payload['res_body']; +	resp_payload['ieof']       = True; + +	response = bitz.get_response( 200, resp_payload ); +	return response; + diff --git a/modules/modpy/py.cpp b/modules/modpy/py.cpp new file mode 100644 index 0000000..51cb38f --- /dev/null +++ b/modules/modpy/py.cpp @@ -0,0 +1,265 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include "py.h" +#include "interface.h" + +#include <bitz/config.h> +#include <bitz/logger.h> + + +namespace bitz { + +	Py::Py() : Modifier() { + +		// defaults +		_pymodule = NULL; + +		// initialise Py::config_t values +		_config.module_name = "modpy"; +		_config.module_path = ""; + +		// load configs +		load_configs(); + +		// initialise python +		init_python(); + +	} + + +	Py::~Py() { + +		// cleanup python +		cleanup_python(); + +	} + + +	icap::Response * Py::modify( icap::Request * request ) throw() { + +		// get the modify response +		return python_response( request, "modify" ); + +	} + + +	icap::Response * Py::preview( icap::Request * request ) throw() { + +		// get the preview response +		return python_response( request, "preview" ); + +	} + + +	void Py::load_configs() throw() { + +		std::string s; +		Config &server_config = Config::instance(); + +		// interface module name +		s = server_config.module_config( "modpy", "module_name" ); +		if ( s != "" ) { +			_config.module_name = s; +		} + +		// module lookup path +		_config.module_path = server_config.module_config( "modpy", "module_path" ); + +	} + + +	void Py::init_python() throw() { + +		PyObject * sys_path; +		PyObject * pymodule_path, * pymodule_name; +		PyObject * pymethod; +		PyObject * pyreturn; + +		// logger +		Logger &logger = Logger::instance(); + +		// python core +		Py_Initialize(); + +		// bitz python module +		if ( Py_InitModule( "bitz", bitz_methods ) == NULL ) { +			logger.warn( "[modpy] failed to init C interface module: bitz" ); +		} + +		// setup python environment +		if ( _config.module_path != "" ) { + +			logger.debug( std::string( "[modpy] appending to sys.path, module_path: " ).append( _config.module_path ) ); + +			sys_path      = PySys_GetObject( (char *) "path" ); +			pymodule_path = PyString_FromString( _config.module_path.c_str() ); +			PyList_Append( sys_path, pymodule_path ); + +		} + +		// load the interface module +		logger.debug( std::string( "[modpy] interface module: " ).append( _config.module_name ) ); + +		pymodule_name = PyString_FromString( _config.module_name.c_str() ); +		_pymodule     = PyImport_Import( pymodule_name ); + +		if ( _pymodule != NULL ) { + +			logger.debug( "[modpy] interface module loaded successfully" ); + +			// call init() in the interface module +			pymethod = PyObject_GetAttrString( _pymodule, "init" ); + +			if ( pymethod && PyCallable_Check( pymethod ) ) { +				pyreturn = PyObject_CallObject( pymethod, NULL ); +				Py_DECREF( pyreturn ); +			} else { +				logger.warn ( "[modpy] failed to call init() in interface module" ); +			} + +			Py_DECREF( pymethod ); + +		} else { +			logger.warn( "[modpy] failed to load interface module" ); +		} + + +		// cleanup +		Py_DECREF( pymodule_name ); +		Py_DECREF( pymodule_path ); +		Py_DECREF( sys_path ); + +	} + + +	void Py::cleanup_python() throw() { + +		PyObject * pymethod; +		PyObject * pyreturn; + +		// logger +		Logger &logger = Logger::instance(); + + +		// cleanup +		if ( _pymodule != NULL ) { + +			// call cleanup() in the interface module +			pymethod = PyObject_GetAttrString( _pymodule, "cleanup" ); + +			if ( pymethod && PyCallable_Check( pymethod ) ) { +				pyreturn = PyObject_CallObject( pymethod, NULL ); +				Py_DECREF( pyreturn ); +			} else { +				logger.warn ( "[modpy] failed to call cleanup() in interface module" ); +			} + +			Py_DECREF( pymethod ); +			Py_DECREF( _pymodule ); + +		} + +		// finalise python core +		Py_Finalize(); + +	} + + +	icap::Response * Py::python_response( icap::Request * request, const std::string &method ) throw() { + +		/* +		*  notes: +		*    + pass icap::Request to python module as a PyCapsule object +		*      so it can be used to grab the data needed using the C/C++ interface. +		*    + process data (within the python module) and use the C/C++ interface +		*      to create a icap::Response and pass it back to this method +		*      using a PyCapsule object +		*/ + +		icap::Response * response; + +		PyObject * pymethod; +		PyObject * pyargs; +		PyObject * pyrequest, * pyresponse; + +		// logger +		Logger &logger = Logger::instance(); + +		// initialise the response object +		response = NULL; + +		// check for the interface module +		if ( _pymodule != NULL ) { + +			/* call the [method]() in the interface module */ +			pymethod  = PyObject_GetAttrString( _pymodule, method.c_str() ); +			pyargs    = PyTuple_New( 1 ); +			pyrequest = PyCapsule_New( (void *) request, "request", NULL ); +			PyTuple_SetItem( pyargs, 0, pyrequest ); + +			if ( pymethod && PyCallable_Check( pymethod ) ) { + +				// get the response capsule +				pyresponse = PyObject_CallObject( pymethod, pyargs ); + +				// sanity check +				if ( pyresponse != NULL ) { + +					void * p = PyCapsule_GetPointer( pyresponse, "response" ); + +					// sanity check +					if ( p != NULL ) { + +						// construct the response +						response = static_cast<icap::Response *>(p); + +					} else { +						logger.warn( std::string( "[modpy] invalid capsule response, method: " ).append( method ) ); +					} + +					Py_DECREF( pyresponse ); + +				} else { +					logger.warn( std::string( "[modpy] response is NULL, method: " ).append( method ) ); +				} + + +			} else { +				logger.warn ( std::string( "[modpy] failed to call the method in interface module, method: " ).append( method ) ); +			} + +			// cleanup +			// pyrequest is created from the reference passed in +			Py_DECREF( pyargs ); +			Py_DECREF( pymethod ); + +		} + +		// sanity check +		if ( response == NULL ) { +			response = new icap::Response( icap::ResponseHeader::SERVER_ERROR ); +		} + +		return response; + +	} + +} /* end of namespace bitz */ + diff --git a/modules/modpy/py.h b/modules/modpy/py.h new file mode 100644 index 0000000..358c36f --- /dev/null +++ b/modules/modpy/py.h @@ -0,0 +1,70 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifndef BITZ_PY_H +#define BITZ_PY_H + +#include <Python.h> + +#include <bitz/modifier.h> + + +namespace bitz { + +	class Py : public Modifier { +	public: + +		struct config_t { +			std::string module_path; +			std::string module_name; +		}; + +		Py(); +		virtual ~Py(); + +		icap::Response * modify( icap::Request * request ) throw(); +		icap::Response * preview( icap::Request * request ) throw(); + +	private: +		config_t _config; +		PyObject * _pymodule; + +		void load_configs() throw(); +		void init_python() throw(); +		void cleanup_python() throw(); + +		icap::Response * python_response( icap::Request * request, const std::string &method ) throw(); + +	}; + +} /* end of namespace bitz */ + + +/* class factories */ + +extern "C" bitz::Modifier * create() { +	return new bitz::Py; +} + +extern "C" void destroy( bitz::Modifier * m ) { +	delete m; +} + +#endif /* !BITZ_PY_H */ + diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..201a051 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,32 @@ +## src/ +AUTOMAKE_OPTIONS        = subdir-objects +AM_CPPFLAGS             = -I$(top_srcdir)/lib ${libconfig_CFLAGS} ${log4cpp_CFLAGS} + +bitzincludedir          = $(pkgincludedir) +sbin_PROGRAMS           = bitz-server +bitz_server_LDFLAGS     = -ldl -export-dynamic +bitz_server_LDADD       = $(top_builddir)/lib/socket/libsocket.la \ +	$(top_builddir)/lib/icap/libicap.la \ +	${libconfig_LIBS} ${log4cpp_LIBS} + +bitz_server_SOURCES     = main.cpp \ +	bitz-server.h bitz-server.cpp \ +	bitz/exception.h bitz/exception.cpp \ +	bitz/manager_exception.h bitz/manager_exception.cpp \ +	bitz/config.h bitz/config.cpp \ +	bitz/logger.h bitz/logger.cpp \ +	bitz/common.h \ +	bitz/util.h bitz/util.cpp \ +	bitz/manager.h bitz/manager.cpp \ +	bitz/worker.h bitz/worker.cpp \ +	bitz/request_handler.h bitz/request_handler.cpp \ +	bitz/options_request_handler.h bitz/options_request_handler.cpp \ +	bitz/reqmod_request_handler.h bitz/reqmod_request_handler.cpp \ +	bitz/respmod_request_handler.h bitz/respmod_request_handler.cpp \ +	bitz/modifier.cpp + +bitzinclude_HEADERS     = \ +	bitz/config.h \ +	bitz/logger.h \ +	bitz/modifier.h + diff --git a/src/bitz-server.cpp b/src/bitz-server.cpp new file mode 100644 index 0000000..c444762 --- /dev/null +++ b/src/bitz-server.cpp @@ -0,0 +1,472 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include <iostream> +#include <string> +#include <cstdlib> +#include <cstdio> +#include <cstring> +#include <fcntl.h> +#include <unistd.h> +#include <getopt.h> +#include <syslog.h> +#include <sys/stat.h> +#include <sys/wait.h> + +#include <config.h> +#include "bitz-server.h" + +namespace bitz { + +	namespace server { + +		static server_t globals; + +		void init() { + +			// initialise defaults +			globals.pid_handle  = -1; +			globals.manager     = NULL; +			globals.terminating = 0; +			globals.daemon      = false; + +			// logger (syslog) +			setlogmask( LOG_UPTO( LOG_INFO ) ); +			openlog( PACKAGE_NAME, LOG_CONS, LOG_USER ); + +			// signal handlers +			init_signal_handlers(); + +		} + + +		void init_signal_handlers() { + +			sigset_t ignore_mask; + +			// set signal mask - signals we want to block +			sigemptyset(&ignore_mask); +			sigaddset(&ignore_mask, SIGTSTP);				// ignore Tty stop signals +			sigaddset(&ignore_mask, SIGTTOU);				// ignore Tty background writes +			sigaddset(&ignore_mask, SIGTTIN);				// ignore Tty background reads +			sigprocmask(SIG_BLOCK, &ignore_mask, NULL);		// block the above specified signals + +			init_sigchld_handler(); +			init_sigterm_handler(); +			init_sigquit_handler(); +			init_sigint_handler(); + +		} + + +		void init_sigchld_handler() { + +			struct sigaction sa; + +			// block all other signals +			sigfillset( &sa.sa_mask ); + +			// signal handler proc +			sa.sa_sigaction = &sigchld_handler; + +			// flags +			sa.sa_flags = SA_SIGINFO; + +			if ( sigaction( SIGCHLD, &sa, NULL ) < 0 ) { +				exit( EXIT_FAILURE ); +			} + +		} + + +		void sigchld_handler( int sig, siginfo_t *siginfo, void *context ) { + +			pid_t worker_pid; +			int status; + +			std::cout << "[" << getpid() << "] inside zombie deleter: "; +			while ( ( worker_pid = waitpid( WAIT_ANY, &status, WNOHANG ) ) > 0 ) { +				std::cout << "child " << worker_pid << " terminated with status " << status << std::endl; + +				if ( globals.manager != NULL ) { +					globals.manager->reap_worker( worker_pid ); +				} +			} + +		} + + +		void init_sigterm_handler() { + +			struct sigaction sa; + +			// block all other signals +			sigfillset( &sa.sa_mask ); + +			// signal handler proc +			sa.sa_sigaction = &sigterm_handler; + +			// flags +			sa.sa_flags = SA_SIGINFO; + +			if ( sigaction( SIGTERM, &sa, NULL ) < 0 ) { +				exit( EXIT_FAILURE ); +			} + +		} + + +		void sigterm_handler( int sig, siginfo_t *siginfo, void *context ) { + +			std::cout << "[" << getpid() << "] inside SIGTERM handler" << std::endl; +			termination_handler( sig, siginfo, context ); + +		} + + +		void init_sigquit_handler() { + +			struct sigaction sa; + +			// block all other signals +			sigfillset( &sa.sa_mask ); + +			// signal handler proc +			sa.sa_sigaction = &sigquit_handler; + +			// flags +			sa.sa_flags = SA_SIGINFO; + +			if ( sigaction( SIGQUIT, &sa, NULL ) < 0 ) { +				exit( EXIT_FAILURE ); +			} + +		} + + +		void sigquit_handler( int sig, siginfo_t *siginfo, void *context ) { + +			std::cout << "[" << getpid() << "] inside SIGQUIT handler" << std::endl; +			termination_handler( sig, siginfo, context ); + +		} + + +		void init_sigint_handler() { + +			struct sigaction sa; + +			// block all other signals +			sigfillset( &sa.sa_mask ); + +			// signal handler proc +			sa.sa_sigaction = &sigint_handler; + +			// flags +			sa.sa_flags = SA_SIGINFO; + +			if ( sigaction( SIGINT, &sa, NULL ) < 0 ) { +				exit( EXIT_FAILURE ); +			} + +		} + + +		void sigint_handler(  int sig, siginfo_t *siginfo, void *context ) { + +			std::cout << "[" << getpid() << "] inside SIGQINT handler" << std::endl; +			termination_handler( sig, siginfo, context ); + +		} + + +		void daemonize( const char *rundir, const char *pidfile ) { + +			pid_t pid, sid; +			long i; +			char str[10]; + +			// notify +			syslog( LOG_NOTICE, "starting daemon (version %s)", PACKAGE_VERSION ); + +			// check parent process id value +			if ( getppid() == 1 ) { +				// we are already a daemon +				return; +			} + +			/* fork daemon */ +			pid = fork(); +			if ( pid < 0 ) { +				exit( EXIT_FAILURE ); +			} + +			// exit the parent +			if ( pid > 0 ) { +				exit( EXIT_SUCCESS ); +			} + + +			/* child (a.k.a daemon) continues */ + +			// set file permissions (750) +			umask( 027 ); + +			// get a new process group +			sid = setsid(); +			if ( sid < 0 ) { +				exit(EXIT_FAILURE); +			} + +			// route I/O connections +			close( STDIN_FILENO ); +			close( STDOUT_FILENO ); +			close( STDERR_FILENO ); + +			// change running directory +			chdir( rundir ); + + +			/* lock pid file to ensure we have only one copy */ + +			globals.pid_handle = open( pidfile, O_RDWR | O_CREAT, 0600 ); +			if ( globals.pid_handle == -1 ) { +				syslog( LOG_ERR, "could not open pid lock file: %s", pidfile ); +				exit( EXIT_FAILURE ); +			} + +			if ( lockf( globals.pid_handle, F_TLOCK, 0 ) == -1 ) { +				syslog( LOG_ERR, "could not lock pid lock file: %s", pidfile); +				exit( EXIT_FAILURE ); +			} + +			// get and format pid +			sprintf( str, "%d\n", getpid() ); + +			// write pid to lockfile +			write( globals.pid_handle, str, strlen( str ) ); + +			// update status +			globals.daemon = true; + + +		} + + +		void shutdown() { + +			// notify +			if ( globals.daemon && ( getppid() == 1 ) ) { +				syslog( LOG_NOTICE, "shutting down daemon (version %s)", PACKAGE_VERSION ); +			} + +			// close pid file +			if ( globals.pid_handle != -1 ) { +				close( globals.pid_handle ); +			} + +			// close logger (syslog) +			closelog(); + +		} + + +		void termination_handler( int sig, siginfo_t * sig_info, void * context ) { + +			std::cout << "[" << getpid() << "] inside termination handler" << std::endl; + +			// exit by re-raising the signal if termination +			// already in progress +			if ( globals.terminating ) { +				std::cout << "[" << getpid() << "] already terminating" << std::endl; +				raise( sig ); +			} + +			// update termination status +			globals.terminating = 1; + + +			if ( globals.manager != NULL ) { + +				// shutdown the manager +				globals.manager->shutdown(); + +				// clean-up +				delete globals.manager; + +			} + +			// cleanup +			shutdown(); + +			// re-raise the signal after reactivating the signal's default action +			signal( sig, SIG_DFL ); +			raise( sig ); + +		} + + +		options_t read_options( int argc, char **argv ) { + +			int optidx, optchar; +			options_t options; + +			options.config_file = ""; + +			struct option lopts[] = { +				{ "config", required_argument, 0, 'c' }, +				{ "debug", no_argument, &options.debug_flag, 1 }, +				{ "help", no_argument, 0, 'h' }, +				{ "usage", no_argument, 0, 'h' }, +				{ "version", no_argument, 0, 'v' }, +				{ 0, 0, 0, 0 } +			}; + +			while ( true ) { + +				optidx  = 0; +				optchar = getopt_long( argc, argv, "c:hv", lopts, &optidx ); + +				// sanity check +				if ( optchar == -1 ) { +					break; +				} + +				switch ( optchar ) { +					case 0: +						// TODO: +						break; + +					case 'c': +						options.config_file = optarg; +						break; + +					case 'h': +						print_usage(); +						exit( EXIT_SUCCESS ); +						break; + +					case 'v': +						print_version(); +						exit( EXIT_SUCCESS ); + +					case '?': +						print_usage(); +						exit( EXIT_FAILURE ); +						break; + +					default: +						// TODO: +						break; +				} + +			} + +			return options; + +		} + + +		void print_version() { + +			std::cout << PACKAGE_STRING << std::endl; +			std::cout << "" << std::endl; +			std::cout << "Copyright (C) 2012-2013 Uditha Atukorala" << std::endl; +			std::cout << "" << std::endl; +			std::cout << "This program is free software; you can redistribute it and/or modify" << std::endl; +			std::cout << "it under the terms of the GNU General Public License as published by" << std::endl; +			std::cout << "the Free Software Foundation; either version 3 of the License, or" << std::endl; +			std::cout << "(at your option) any later version." << std::endl; +			std::cout << "" << std::endl; +			std::cout << "This program is distributed in the hope that it will be useful," << std::endl; +			std::cout << "but WITHOUT ANY WARRANTY; without even the implied warranty of" << std::endl; +			std::cout << "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the" << std::endl; +			std::cout << "GNU General Public License (http://gnu.org/licenses/gpl.html)" << std::endl; +			std::cout << "for more details." << std::endl; +			std::cout << "" << std::endl; + +		} + + +		void print_usage() { + +			std::cout << "usage: " << PACKAGE_NAME << " " +				<< "[--version] [--help] [--usage] [--debug] [--config=<config file>]" +				<< std::endl; + +			std::cout << "" << std::endl; +			std::cout << "See the man pages for more information" << std::endl; + +		} + + +		void start( int port, unsigned int children, int max_requests ) { + +			try { +				globals.manager = new bitz::Manager( port ); +				globals.manager->spawn( children, max_requests ); +			} catch ( bitz::ManagerException &mex ) { +				syslog( LOG_ERR, "failed to start, exception: %s", mex.what() ); +				exit( EXIT_FAILURE ); +			} + +		} + + +		void run() { + +			sigset_t mask, oldmask; + +			// sanity check +			if ( globals.manager == NULL ) { +				return; +			} + +			// block termination signals until we are ready +			sigemptyset( &mask ); +			sigaddset( &mask, SIGTERM ); +			sigaddset( &mask, SIGQUIT ); +			sigaddset( &mask, SIGINT ); +			sigprocmask ( SIG_BLOCK, &mask, &oldmask ); + +			// loop until a termination signal is received +			while (! globals.terminating ) { + +				// capture any signals +				sigsuspend( &oldmask ); + +				// unblock termination signals +				sigprocmask( SIG_UNBLOCK, &mask, NULL ); + +				// manage workers +				globals.manager->manager_workers(); + +				// block termination signals +				sigprocmask( SIG_BLOCK, &mask, &oldmask ); + +			} + +		} + +	} /* end of namespace server */ + +} /* end of namespace bitz */ + + + diff --git a/src/bitz-server.h b/src/bitz-server.h new file mode 100644 index 0000000..87129ad --- /dev/null +++ b/src/bitz-server.h @@ -0,0 +1,113 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifndef BITZ_SERVER_H +#define BITZ_SERVER_H + +#include "bitz/manager.h" + +#include <csignal> + + +namespace bitz { + +	namespace server { + +		/** +		*   Structure to hold server globals initialised +		*   by the init() method. +		*/ +		struct server_t { +			int pid_handle; +			volatile sig_atomic_t terminating; +			bool daemon; + +			bitz::Manager * manager; +		}; + +		/** +		*   Structure to hold command line options. +		*/ +		struct options_t { +			int          debug_flag; +			std::string  config_file; +		}; + +		void init(); +		void init_signal_handlers(); +		void init_sigchld_handler(); +		void init_sigterm_handler(); +		void init_sigquit_handler(); +		void init_sigint_handler(); +		void sigchld_handler( int sig, siginfo_t * sig_info, void * context ); +		void sigterm_handler( int sig, siginfo_t * sig_info, void * context ); +		void sigquit_handler( int sig, siginfo_t * sig_info, void * context ); +		void sigint_handler( int sig, siginfo_t * sig_info, void * context ); + +		void daemonize( const char * run_dir, const char * pid_file ); +		void shutdown(); +		void termination_handler( int sig, siginfo_t * sig_info, void * context ); + +		/** +		*   Read command line options and return a options_t structure. +		*   This method will terminate the program with an exit status +		*   of EXIT_FAILURE if any errors are found while reading options. +		*   If --version or --help options are found this will print the +		*   appropriate message to the standard output and terminate with +		*   EXIT_SUCCESS. +		* +		*   @param argc same as main() argc +		*   @param argv same as main() argv +		*   @return read options +		*/ +		options_t read_options( int argc, char **argv ); + +		/** +		*   Print version information to the standard output +		*/ +		void print_version(); + +		/** +		*   Print usage message to the standard output +		*/ +		void print_usage(); + +		/** +		*   Start the server by creating a bitz::Manager instance and spawn +		*   workers. +		* +		*   @param port port number to listen to +		*   @param children number of children to spawn +		*   @param max_request maximum number of requests that a child will serve +		*/ +		void start( int port, unsigned int children, int max_requests ); + +		/** +		*   Run the server managing workers until a termination signal is received. +		*   This process will never return, instead the termination signal will +		*   end the process. +		*/ +		void run(); + +	} /* end of namespace server */ + +} /* end of namespace bitz */ + +#endif /* !BITZ_SERVER_H */ + diff --git a/src/bitz/common.h b/src/bitz/common.h new file mode 100644 index 0000000..5b03948 --- /dev/null +++ b/src/bitz/common.h @@ -0,0 +1,40 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifndef BITZ_COMMON_H +#define BITZ_COMMON_H + +#include <string> +#include <map> + +#include "request_handler.h" + + +namespace bitz { + +	/* request handlers type */ +	typedef std::map<std::string, RequestHandler *> req_handlers_t; + +	/* iterator type */ +	typedef req_handlers_t::iterator req_handlers_index_t; + +} /* end of namespace bitz */ + +#endif /* !BITZ_COMMIN_H */ + diff --git a/src/bitz/config.cpp b/src/bitz/config.cpp new file mode 100644 index 0000000..a9ca856 --- /dev/null +++ b/src/bitz/config.cpp @@ -0,0 +1,190 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include "config.h" +#include "logger.h" + +#include <iostream> +#include <cstdlib> + + +namespace bitz { + +	Config::Config() { + +		// initialise config_t values +		_config.port            = 1344; +		_config.pid_file        = "/dev/null"; +		_config.log_file        = "/dev/null"; +		_config.log_category    = "bitz"; +		_config.req_handlers_count = 0; +		_config.req_handlers       = NULL; + +		_config.max_workers         = 0; +		_config.max_worker_requests = 0; + + +		// defaults +		_lconfig = NULL; + +	} + +	Config::~Config() { + +		// cleanup +		delete _lconfig; + +		for (int i = 0; i < _config.req_handlers_count ; i++ ) { +			if ( _config.req_handlers[i].modules_count > 0 ) { +				delete [] _config.req_handlers[i].modules; +			} +		} + +		if ( _config.req_handlers != NULL ) { +			delete [] _config.req_handlers; +		} + +	} + + +	const config_t &Config::initialise( const std::string &config_file ) { + +		libconfig::Config * config; +		config = new libconfig::Config; + +		try { +			config->readFile( config_file.c_str() ); +		} catch( const libconfig::FileIOException &ex ) { +			std::cerr << "[config] failed to read config file: " << config_file +					<< ", exception: " << ex.what() << std::endl; +			exit( EXIT_FAILURE ); +		} catch( const libconfig::ParseException &pex ) { +			std::cerr << "[config] parse error at " << pex.getFile() +					<< ":" << pex.getLine() << " - " << pex.getError() << std::endl; +			exit( EXIT_FAILURE ); +		} + +		try { + +			// read core configs +			config->lookupValue( "port", _config.port ); +			config->lookupValue( "pid_file", _config.pid_file ); +			config->lookupValue( "log_file", _config.log_file ); +			config->lookupValue( "log_category", _config.log_category ); + +			config->lookupValue( "max_workers", _config.max_workers ); +			config->lookupValue( "max_worker_requests", _config.max_worker_requests ); + +		} catch( const libconfig::SettingNotFoundException &e ) { +			std::cerr << "[config] failed to load core configs, " +					<< e.getPath() << " : " << e.what() << std::endl; +		} + +		// cache configs +		_lconfig = config; + +		// read other configs +		read_req_handler_configs(); + +		return _config; + +	} + + +	const config_t &Config::configs() { +		return _config; +	} + + +	const std::string Config::module_config( const std::string &module, const std::string &config ) throw() { + +		std::string config_value = ""; + +		if ( _lconfig->exists( "modules" ) ) { + +			try { +				libconfig::Setting &setting = _lconfig->lookup( std::string( "modules." ).append( module ) ); +				setting.lookupValue( config, config_value ); +			} catch( const libconfig::SettingNotFoundException &e ) { +				// TODO: log errors ?? +				std::cerr << "[config] " << e.getPath() << " : " << e.what() << std::endl; +			} + +		} else { +			std::cout << "[config] 'modules' configs not found" << std::endl; +		} + +		return config_value; + +	} + + +	void Config::read_req_handler_configs() throw() { + +		int i, j; +		std::string s; + +		std::cout << "[config] looking for req_handlers... "; +		if ( _lconfig->exists( "req_handlers" ) ) { + +			std::cout << "found "; + +			libconfig::Setting &req_handlers = _lconfig->lookup( "req_handlers" ); +			_config.req_handlers_count       = req_handlers.getLength(); +			_config.req_handlers             = new req_handlers_config_t[_config.req_handlers_count]; + +			std::cout << "(" << _config.req_handlers_count << ")" << std::endl; + +			try { + +				// read request handler configs +				for ( i = 0; i < _config.req_handlers_count ; i++ ) { +					_config.req_handlers[i].name       = (const char *) req_handlers[i]["handler"]; +					_config.req_handlers[i].class_name = (const char *) req_handlers[i]["class"]; + +					// read request handler modules config +					std::cout << "[config] looking for " << _config.req_handlers[i].name << " modules... "; +					if ( req_handlers[i].exists( "modules" ) ) { +						std::cout << "found "; + +						_config.req_handlers[i].modules_count   = req_handlers[i]["modules"].getLength(); +						_config.req_handlers[i].modules         = new modules_config_t[_config.req_handlers[i].modules_count]; + +						std::cout << "(" << _config.req_handlers[i].modules_count << ")" << std::endl; +						for ( j = 0; j < _config.req_handlers[i].modules_count; j++ ) { +							_config.req_handlers[i].modules[j].name   = (const char *) req_handlers[i]["modules"][j]["name"]; +							_config.req_handlers[i].modules[j].module = (const char *) req_handlers[i]["modules"][j]["module"]; +						} +					} else { +						std::cout << "not found" << std::endl; +					} +				} + +			} catch ( const libconfig::SettingNotFoundException &ex ) { +				std::cerr << "[config] Error: " << ex.getPath() << ex.what() << std::endl; +			} + +		} else { +			std::cout << "not found" << std::endl; +		} + +	} + +} /* end of namespace bitz */ + diff --git a/src/bitz/config.h b/src/bitz/config.h new file mode 100644 index 0000000..453d29d --- /dev/null +++ b/src/bitz/config.h @@ -0,0 +1,95 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifndef BITZ_CONFIG_H +#define BITZ_CONFIG_H + +#include <string> +#include <libconfig.h++> + + +#ifndef BITZ_SERVER_CONFIG_FILE +#define BITZ_SERVER_CONFIG_FILE "/etc/bitz/bitz-server.conf" +#endif + +namespace bitz { + +	struct modules_config_t { +		std::string name; +		std::string module; +	}; + +	struct req_handlers_config_t { +		std::string name; +		std::string class_name; +		unsigned int modules_count; + +		modules_config_t * modules; +	}; + +	struct config_t { +		int port; +		int max_workers; +		int max_worker_requests; +		std::string pid_file; +		std::string log_file; +		std::string log_category; +		unsigned int req_handlers_count; + +		req_handlers_config_t * req_handlers; +	}; + +	class Config { +	public: +		static Config &instance() { +			static Config config; +			return config; +		} + +		const config_t &initialise( const std::string &config_file = BITZ_SERVER_CONFIG_FILE ); +		const config_t &configs(); + +		/** +		*   Returns module specific config value (or NULL string if not found) +		*   Note: This method should be only used my the pluggable modules and not +		*         by the core code. +		* +		*   @param module module name +		*   @param config config name +		*   @return module config value +		*/ +		const std::string module_config( const std::string &module, const std::string &config ) throw(); + +	private: +		config_t _config; +		libconfig::Config * _lconfig; + +		Config(); +		~Config(); +		Config( Config const © ); +		Config &operator=( const Config © ); + +		void read_req_handler_configs() throw(); + +	}; + +} /* end of namespace bitz */ + +#endif /* !BITZ_CONFIG_H */ + diff --git a/src/bitz/exception.cpp b/src/bitz/exception.cpp new file mode 100644 index 0000000..bf8be9e --- /dev/null +++ b/src/bitz/exception.cpp @@ -0,0 +1,40 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include "exception.h" +#include <cerrno>          // For errno +#include <cstring>         // For strerror + +namespace bitz { + +	Exception::Exception( const std::string &message, bool inclSystemMessage ) throw() : _message( message ) { +		if ( inclSystemMessage ) { +			_message.append( " : " ); +			_message.append( strerror( errno ) ); +		} +	} + +	Exception::~Exception() throw() { } + +	const char * Exception::what() const throw() { +		return _message.c_str(); +	} + +} /* end of namespace bitz */ + diff --git a/src/bitz/exception.h b/src/bitz/exception.h new file mode 100644 index 0000000..54abdcd --- /dev/null +++ b/src/bitz/exception.h @@ -0,0 +1,43 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef BITZ_EXCEPTION_H +#define BITZ_EXCEPTION_H + +#include <exception>        // for exception class +#include <string>           // for std::string + +namespace bitz { + +	class Exception : public std::exception { +	public: +		Exception( const std::string &message, bool inclSystemMessage = false ) throw(); +		virtual ~Exception() throw(); + +		virtual const char * what() const throw(); + +	private: +		std::string _message; +	}; + +} /* end of namespace bitz */ + +#endif /* !BITZ_EXCEPTION_H */ + diff --git a/src/bitz/logger.cpp b/src/bitz/logger.cpp new file mode 100644 index 0000000..1d7d833 --- /dev/null +++ b/src/bitz/logger.cpp @@ -0,0 +1,98 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include "logger.h" + +#include <log4cpp/FileAppender.hh> +#include <log4cpp/PatternLayout.hh> + +namespace bitz { + +	Logger::Logger( std::string log_file, std::string category ) { +		this->LOGGER = NULL; +		this->initialise( log_file, category ); +	} + +	Logger::~Logger() { +		this->LOGGER->debug( "closing down logger" ); +	} + +	void Logger::initialise( std::string log_file, std::string category ) { + +		this->LOGGER = &log4cpp::Category::getInstance( category ); + +		// setting up appender, layout and category +		log4cpp::Appender * log_appender    = new log4cpp::FileAppender( "FileAppender", log_file ); +		log4cpp::PatternLayout * log_layout = new log4cpp::PatternLayout(); +		log_layout->setConversionPattern( "%d %p %c %x: %m%n" ); + +		log_appender->setLayout( log_layout ); +		this->LOGGER->setAppender( log_appender ); +		this->LOGGER->setPriority( this->getPriorityValue( "DEBUG" ) ); + +		this->LOGGER->debug( "logger initialised, log_file: " + log_file ); + +	} + +	int Logger::getPriorityValue( const std::string &priority ) { +		return ( log4cpp::Priority::getPriorityValue( priority ) ); +	} + +	void Logger::log( log4cpp::Priority::Value priority, const std::string &message ) { +		this->LOGGER->log( priority, message ); +	} + +	void Logger::fatal( const std::string& message ) { +		this->LOGGER->fatal( message ); +	} + +	void Logger::emerg( const std::string& message ) { +		this->LOGGER->emerg( message ); +	} + +	void Logger::alert( const std::string& message ) { +		this->LOGGER->alert( message ); +	} + +	void Logger::crit( const std::string& message ) { +		this->LOGGER->crit( message ); +	} + +	void Logger::error( const std::string& message ) { +		this->LOGGER->error( message ); +	} + +	void Logger::warn( const std::string& message ) { +		this->LOGGER->warn( message ); +	} + +	void Logger::notice( const std::string& message ) { +		this->LOGGER->notice( message ); +	} + +	void Logger::info( const std::string& message ) { +		this->LOGGER->info( message ); +	} + +	void Logger::debug( const std::string& message ) { +		this->LOGGER->debug( message ); +	} + +} /* end of namespace bitz */ + diff --git a/src/bitz/logger.h b/src/bitz/logger.h new file mode 100644 index 0000000..f1c9c6c --- /dev/null +++ b/src/bitz/logger.h @@ -0,0 +1,62 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifndef BITZ_LOGGER_H +#define BITZ_LOGGER_H + +#include <string> +#include <log4cpp/Category.hh> + +namespace bitz { + +	class Logger { +	public: +		static Logger &instance( std::string log_file = "/dev/null" , std::string category = "logger" ) { +			static Logger logger( log_file, category ); +			return logger; +		} + +		void initialise( std::string log_file, std::string category ); + +		static int getPriorityValue( const std::string& priority ); +		void log( int priority, const std::string &message ); + +		void fatal( const std::string& message ); +		void emerg( const std::string& message ); +		void alert( const std::string& message ); +		void crit( const std::string& message ); +		void error( const std::string& message ); +		void warn( const std::string& message ); +		void notice( const std::string& message ); +		void info( const std::string& message ); +		void debug( const std::string& message ); + +	private: +		log4cpp::Category * LOGGER; + +		Logger( std::string log_file, std::string category ); +		~Logger(); +		Logger( Logger const © ); +		Logger &operator=( const Logger © ); +	}; + +} /* end of namespace bitz */ + +#endif /* !BITZ_LOGGER_H */ + diff --git a/src/bitz/manager.cpp b/src/bitz/manager.cpp new file mode 100644 index 0000000..ffa2dae --- /dev/null +++ b/src/bitz/manager.cpp @@ -0,0 +1,223 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include "manager.h" +#include "logger.h" +#include "util.h" + +#include <cstdlib> +#include <sstream> +#include <csignal> + + +namespace bitz { + +	Manager::Manager( unsigned short port, const std::string &address, int backlog ) throw( ManagerException ) { + +		// initialise manager +		_manager.worker        = false; +		_manager.max_workers   = 0; +		_manager.workers_count = 0; +		_manager.worker_id     = 0; +		_manager.socket        = NULL; +		_manager.worker_pool   = NULL; + +		// initialise listening socket +		try { +			if ( address.empty() ) { +				_manager.socket = new socketlibrary::TCPServerSocket( port, backlog ); +			} else { +				_manager.socket = new socketlibrary::TCPServerSocket( address, port, backlog ); +			} +		} catch ( socketlibrary::SocketException &sex ) { +			throw ManagerException( "failed to initialise socket" ); +		} + +		Logger &logger = Logger::instance(); +		logger.debug( "manager initialised" ); + +	} + + +	Manager::~Manager() { + +		Logger &logger = Logger::instance(); + +		if ( _manager.worker ) { +			logger.debug( "[worker] cleaning up manager" ); +		} else { +			logger.debug( "[manager] shutting down manager" ); +		} + +		delete [] _manager.worker_pool; +		delete _manager.socket; + +	} + + +	void Manager::spawn( unsigned int max_workers, unsigned int max_worker_requests ) throw( ManagerException ) { + +		_manager.max_workers         = max_workers; +		_manager.max_worker_requests = max_worker_requests; +		_manager.worker_pool         = new worker_pool_t[max_workers]; + +		// pre-fork workers +		if (! _manager.worker ) { +			for ( unsigned int i = 0; i < max_workers; i++ ) { + +				try { +					spawn_worker( i ); +				} catch ( ManagerException &mex ) { +					throw mex; +				} + +			} +		} + +	} + + +	void Manager::spawn_worker( unsigned int worker_id ) throw( ManagerException ) { + +		Logger &logger = Logger::instance(); +		pid_t worker_pid; + +		// create a worker child +		worker_pid = fork(); +		if ( worker_pid == -1 ) { +			throw ManagerException( "failed to create worker", true ); +		} + +		if ( worker_pid == 0 ) { + +			/* worker */ + +			_manager.worker    = true; +			_manager.worker_id = worker_id; +			_manager.worker_pool[worker_id].worker     = new Worker(); +			_manager.worker_pool[worker_id].worker_id  = worker_id; +			_manager.worker_pool[worker_id].worker_pid = worker_pid; + +			_manager.worker_pool[worker_id].worker->run( _manager.socket, _manager.max_worker_requests ); +			logger.info( std::string( "end of cycle, worker[" ).append( util::itoa( worker_id ) ).append( "]" ) ); + +			delete _manager.worker_pool[worker_id].worker; +			_exit( EXIT_SUCCESS ); + +		} else { + +			/* manager */ +			logger.info( std::string( "[manager] worker spawned with pid: " ).append( util::itoa( worker_pid) ) ); + +			_manager.workers_count++; + +			_manager.worker = false; +			_manager.worker_pool[worker_id].worker     = NULL; +			_manager.worker_pool[worker_id].worker_id  = worker_id; +			_manager.worker_pool[worker_id].worker_pid = worker_pid; + +		} + +	} + + +	void Manager::shutdown( bool graceful ) throw() { + +		// logger +		Logger &logger = Logger::instance(); + +		if ( _manager.worker ) { + +			logger.info( "[worker] manager shutdown request received" ); + +			/* worker: cleanup */ +			delete _manager.worker_pool[_manager.worker_id].worker; + +		} else { + +			/* manager: stop all child processes */ +			logger.info( "[manager] shutdown request received" ); + +			for (unsigned int i = 0; i < _manager.max_workers; i++ ) { +				if ( _manager.worker_pool[i].worker_pid != 0 ) { +					if ( graceful ) { +						kill( _manager.worker_pool[i].worker_pid, SIGTERM ); +						logger.debug( std::string( "[manager] sending SIGTERM to worker[" ).append( util::itoa( i ) ) +								.append( "], pid: " ).append( util::itoa( _manager.worker_pool[i].worker_pid ) ) ); +					} else { +						kill( _manager.worker_pool[i].worker_pid, SIGKILL ); +						logger.debug( std::string( "[manager] sending SIGKILL to worker[" ).append( util::itoa( i ) ) +								.append( "], pid: " ).append( util::itoa( _manager.worker_pool[i].worker_pid ) ) ); +					} +				} else { +					logger.debug( std::string( "[manager] worker[" ).append( util::itoa( i ) ).append( "] already closed" ) ); +				} +			} +		} + +	} + + +	void Manager::reap_worker( pid_t worker_pid ) throw() { + +		// logger +		Logger &logger = Logger::instance(); +		logger.debug( std::string( "reaping worker, pid: " ).append( util::itoa( worker_pid ) ) ); + +		if (! _manager.worker ) { +			for (unsigned int i = 0; i < _manager.max_workers; i++ ) { +				if ( _manager.worker_pool[i].worker_pid == worker_pid ) { + +					// reap the dead worker +					_manager.worker_pool[i].worker_pid = 0; +					_manager.workers_count--; + +					// break out the loop +					break; + +				} +			} +		} + +	} + + +	void Manager::manager_workers() throw() { + +		if (! _manager.worker ) { + +			// check the worker count +			while ( _manager.workers_count != _manager.max_workers ) { + +				// we are missing workers, find out who +				for (unsigned int i = 0; i < _manager.max_workers; i++ ) { +					if ( _manager.worker_pool[i].worker_pid == 0 ) { +						// spawn a worker for the missing +						spawn_worker( i ); +					} +				} + +			} + +		} + +	} + +} /* end of namespace bitz */ + diff --git a/src/bitz/manager.h b/src/bitz/manager.h new file mode 100644 index 0000000..cc15f9c --- /dev/null +++ b/src/bitz/manager.h @@ -0,0 +1,87 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifndef BITZ_MANAGER_H +#define BITZ_MANAGER_H + +#include <unistd.h>            // pid_t, fork() etc. +#include <socket/socket.h>     // socket-library + +#include "manager_exception.h" +#include "worker.h" + +#ifndef BITZ_MAX_WORKERS +#define BITZ_MAX_WORKERS 2 +#endif + +#ifndef BITZ_MAX_WORKER_REQUESTS +#define BITZ_MAX_WORKER_REQUESTS 100 +#endif + + +namespace bitz { + +	class Manager { +	public: + +		struct worker_pool_t { +			pid_t worker_pid; +			unsigned int worker_id; +			Worker * worker; +		}; + +		struct manager_t { +			bool worker; +			unsigned int max_workers; +			unsigned int max_worker_requests; +			unsigned int workers_count; +			unsigned int worker_id; + +			socketlibrary::TCPServerSocket * socket; +			worker_pool_t * worker_pool; +		}; + + +		/** +		*   Note: backlog = SOMAXCONN (from sys/socket.h) +		*/ +		Manager( unsigned short port, const std::string &address = "", int backlog = 128 ) throw( ManagerException ); + +		/** +		*   deconstructor +		*/ +		virtual ~Manager(); + +		virtual void spawn( unsigned int max_workers = BITZ_MAX_WORKERS, unsigned int max_worker_requests = BITZ_MAX_WORKER_REQUESTS ) throw( ManagerException ); +		virtual void shutdown( bool graceful = true ) throw(); +		virtual void reap_worker( pid_t worker_pid ) throw(); +		virtual void manager_workers() throw(); + + +	private: +		manager_t         _manager; + +		virtual void spawn_worker( unsigned int worker_id ) throw( ManagerException ); + +	}; + +} /* end of namespace bitz */ + +#endif /* !BITZ_MANAGER_H */ + diff --git a/src/bitz/manager_exception.cpp b/src/bitz/manager_exception.cpp new file mode 100644 index 0000000..d49f58a --- /dev/null +++ b/src/bitz/manager_exception.cpp @@ -0,0 +1,32 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include "manager_exception.h" + +namespace bitz { + +	ManagerException::ManagerException( const std::string &message, bool inclSystemMessage ) throw() : +			Exception( message, inclSystemMessage ) { +		// constructor +	} + +	ManagerException::~ManagerException() throw() { } + +} /* end of namespace bitz */ + diff --git a/src/bitz/manager_exception.h b/src/bitz/manager_exception.h new file mode 100644 index 0000000..0729ef0 --- /dev/null +++ b/src/bitz/manager_exception.h @@ -0,0 +1,36 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifndef BITZ_MANAGER_EXCEPTION_H +#define BITZ_MANAGER_EXCEPTION_H + +#include "exception.h" + +namespace bitz { + +	class ManagerException: public Exception { +	public: +		ManagerException( const std::string &message, bool inclSystemMessage = false ) throw(); +		virtual ~ManagerException() throw(); +	}; + +} /* end of namespace bitz */ + +#endif /* BITZ_MANAGER_EXCEPTION_H */ + diff --git a/src/bitz/modifier.cpp b/src/bitz/modifier.cpp new file mode 100644 index 0000000..a0a416f --- /dev/null +++ b/src/bitz/modifier.cpp @@ -0,0 +1,29 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include "modifier.h" + + +namespace bitz { + +	Modifier::Modifier() { } +	Modifier::~Modifier() { } + +} /* end of namespace bitz */ + diff --git a/src/bitz/modifier.h b/src/bitz/modifier.h new file mode 100644 index 0000000..7f189aa --- /dev/null +++ b/src/bitz/modifier.h @@ -0,0 +1,70 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifndef BITZ_MODIFIER_H +#define BITZ_MODIFIER_H + +#include <icap/request.h> +#include <icap/response.h> + + +namespace bitz { + +	class Modifier { +	public: + +		/* types of the class factories */ +		typedef bitz::Modifier * create_t(); +		typedef void destroy_t( bitz::Modifier * ); + +		struct symbols_t { +			void * modifier; +			create_t  * create; +			destroy_t * destroy; +		}; + +		Modifier(); +		virtual ~Modifier(); + +		/** +		*   Modify the request as needed and return a response object. +		* +		*   @param request request object +		*   @return response object +		*/ +		virtual icap::Response * modify( icap::Request * request ) throw() =0; + +		/** +		*   Preview the request passed in and return a response object. The +		*   response status of 100 (continue) should be handled by the caller +		*   and pass the complete request to modify() method. +		* +		*   @param request request object +		*   @return response object +		*/ +		virtual icap::Response * preview( icap::Request * request ) throw() =0; + +	private: + +	}; + +} /* end of namespace bitz */ + +#endif /* !BITZ_MODIFIER_H */ + diff --git a/src/bitz/options_request_handler.cpp b/src/bitz/options_request_handler.cpp new file mode 100644 index 0000000..6872b5c --- /dev/null +++ b/src/bitz/options_request_handler.cpp @@ -0,0 +1,57 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include "options_request_handler.h" + + +namespace bitz { + +	OptionsRequestHandler::OptionsRequestHandler() : RequestHandler( "OPTIONS" ) { } +	OptionsRequestHandler::~OptionsRequestHandler() { } + + +	icap::Response * OptionsRequestHandler::process( icap::RequestHeader * req_header, socketlibrary::TCPSocket * socket ) throw() { + +		icap::ResponseHeader * header; +		icap::Response       * response; + +		// header +		header = new icap::ResponseHeader( icap::ResponseHeader::OK ); + +		// FIXME: Methods are tied to the URIs +		header->attach( "Methods", _methods.at( 0 ) ); +		header->attach( "Options-TTL", "3600" ); +		header->attach( "Allow", "204" ); + +		response = new icap::Response( header ); +		return response; + +	} + + +	void OptionsRequestHandler::register_handler( RequestHandler * req_handler ) throw() { + +		// FIXME: Methods are tied to the URIs +		_methods.push_back( req_handler->method() ); +		return; + +	} + +} /* end of namespace bitz */ + diff --git a/src/bitz/options_request_handler.h b/src/bitz/options_request_handler.h new file mode 100644 index 0000000..a81377f --- /dev/null +++ b/src/bitz/options_request_handler.h @@ -0,0 +1,51 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifndef BITZ_OPTIONS_REQUEST_HANDLER_H +#define BITZ_OPTIONS_REQUEST_HANDLER_H + +#include "request_handler.h" + + +namespace bitz { + +	class OptionsRequestHandler : public RequestHandler { +	public: +		OptionsRequestHandler(); +		virtual ~OptionsRequestHandler(); + +		icap::Response * process( icap::RequestHeader * req_header, socketlibrary::TCPSocket * socket ) throw(); + +		/** +		*   Register a request handler so it is known to the OPTIONS +		*   handler +		* +		*   @param req_handler request handler +		*/ +		void register_handler( RequestHandler * req_handler ) throw(); + +	private: +		std::vector<std::string> _methods; + +	}; + +} /* end of namespace bitz */ + +#endif /* !BITZ_OPTIONS_REQUEST_HANDLER_H */ + diff --git a/src/bitz/reqmod_request_handler.cpp b/src/bitz/reqmod_request_handler.cpp new file mode 100644 index 0000000..7b1f0a2 --- /dev/null +++ b/src/bitz/reqmod_request_handler.cpp @@ -0,0 +1,30 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include "reqmod_request_handler.h" + + +namespace bitz { + +	ReqmodRequestHandler::ReqmodRequestHandler() : RequestHandler( "REQMOD" ) { } + +	ReqmodRequestHandler::~ReqmodRequestHandler() { } + +} /* end of namespace bitz */ + diff --git a/src/bitz/reqmod_request_handler.h b/src/bitz/reqmod_request_handler.h new file mode 100644 index 0000000..b267c07 --- /dev/null +++ b/src/bitz/reqmod_request_handler.h @@ -0,0 +1,41 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifndef BITZ_REQMOD_REQUEST_HANDLER_H +#define BITZ_REQMOD_REQUEST_HANDLER_H + +#include "request_handler.h" + + +namespace bitz { + +	class ReqmodRequestHandler : public RequestHandler { +	public: + +		ReqmodRequestHandler(); +		virtual ~ReqmodRequestHandler(); + +	private: + +	}; + +} /* end of namespace bitz */ + +#endif /* !BITZ_REQMOD_REQUEST_HANDLER_H */ + diff --git a/src/bitz/request_handler.cpp b/src/bitz/request_handler.cpp new file mode 100644 index 0000000..3665cba --- /dev/null +++ b/src/bitz/request_handler.cpp @@ -0,0 +1,401 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include "request_handler.h" +#include "config.h" +#include "logger.h" +#include "util.h" + +#include <dlfcn.h> +#include <icap/util.h> + + +namespace bitz { + +	RequestHandler::RequestHandler( const std::string &method ) { + +		// initialise defaults +		_handlers_count = 0; +		_handlers       = NULL; + +		// update variables +		_req_handler.method = method; + +		// load modifier modules +		load_modules(); + +	} + + +	RequestHandler::~RequestHandler() { + +		// cleanup modifier modules +		cleanup_modules(); + +		if ( _handlers != NULL ) { +			delete [] _handlers; +		} + +		Logger &logger = Logger::instance(); +		logger.debug( std::string( "[req] exiting request handler [" ).append( _req_handler.method ).append( "]" ) ); + +	} + + +	const std::string &RequestHandler::method() const throw() { +		return _req_handler.method; +	} + + +	icap::Response * RequestHandler::process( icap::RequestHeader * req_header, socketlibrary::TCPSocket * socket ) throw() { + + +		icap::Request  * request; +		icap::Response * response = NULL; + +		// logger +		Logger &logger = Logger::instance(); + + +		// request +		request = new icap::Request( req_header ); + +		// read request data +		if (! icap::util::read_req_data( request, socket ) ) { + +			logger.warn( "[req] failed to read request data" ); +			response = new icap::Response( icap::ResponseHeader::SERVER_ERROR ); + +		} else { + +			logger.debug( std::string( "[req] payload.req-hdr:\r\n").append( request->payload().req_header ) ); +			logger.debug( std::string( "[req] payload.req-body:\r\n").append( request->payload().req_body ) ); +			logger.debug( std::string( "[req] payload.res-hdr:\r\n").append( request->payload().res_header ) ); +			logger.debug( std::string( "[req] payload.res-body:\r\n").append( request->payload().res_body ) ); + + +			// check for message preview +			if ( request->preview_size() >= 0 ) { + +				// process preview +				logger.debug( std::string( "[req] message preview request, preview: " ).append( util::itoa( request->preview_size() ) ) ); +				response = process_preview( request, socket ); + +			} + +			/* +			*  When we get here, if the response is NULL then either this is a +			*  pure REQMOD request without message preview or the preview was +			*  inconclusive (i.e. 100 Continue) and we have requested for the full +			*  request. +			*/ +			if ( response == NULL ) { + +				// process modify +				logger.debug( "[req] modify request" ); +				response = process_modify( request ); + +			} + +		} + +		// cleanup +		delete request; + +		// sanity check +		if ( response == NULL ) { +			logger.warn( "[req] no valid response from modifiers, creating a server error (500) response" ); +			response = new icap::Response( icap::ResponseHeader::SERVER_ERROR ); +		} + +		return response; + +	} + + +	bool RequestHandler::load_modifier( const std::string &file, Modifier::symbols_t &symbols ) throw() { + +		// logger +		Logger &logger = Logger::instance(); + +		// vars +		const char* dlsym_error; + +		// load the modifier module +		logger.debug( "[req] loading modifier: " + file ); +		symbols.modifier = dlopen( file.c_str(), RTLD_LAZY | RTLD_LOCAL ); + +		if (! symbols.modifier ) { +			logger.warn( std::string( "[req] failed to load modifier: " ).append( file ).append( dlerror() ) ); +			return false; +		} + +		// reset errors +		dlerror(); + +		// load the symbols +		symbols.create = ( Modifier::create_t * ) dlsym( symbols.modifier, "create" ); +		dlsym_error    = dlerror(); + +		if ( dlsym_error ) { +			logger.warn( std::string( "[req] failed to load create symbol: " ).append( dlsym_error ) ); +			return false; +		} + +		symbols.destroy = ( Modifier::destroy_t * ) dlsym( symbols.modifier, "destroy" ); +		dlsym_error     = dlerror(); + +		if ( dlsym_error ) { +			logger.warn( std::string( "[req] failed to load destroy symbol: " ).append( dlsym_error ) ); +			return false; +		} + +		return true; + +	} + + +	void RequestHandler::unload_modifier( void * modifier ) throw() { +		// unload the modifier module +		dlclose( modifier ); +	} + + +	void RequestHandler::load_modules() throw() { + +		int i = 0; +		int j = 0; +		const bitz::config_t &config = Config::instance().configs(); + +		// search for request handlers +		for ( i = 0; i < config.req_handlers_count; i++ ) { + +			// we are only interested in handlers for the current method (e.g. REQMOD, RESPMOD) +			if ( config.req_handlers[i].name == method() ) { + +				if ( config.req_handlers[i].modules_count > 0 ) { + +					_handlers_count = config.req_handlers[i].modules_count; +					_handlers       = new handler_t[_handlers_count]; + +					// search for request handler modules +					for (j = 0; j < _handlers_count; j++ ) { + +						// load module +						if ( load_modifier( config.req_handlers[i].modules[j].module, _handlers[j].symbols ) ) { +							_handlers[j].name = config.req_handlers[i].modules[j].name; +						} else { +							_handlers[j].name = ""; +							// FIXME: error handling +						} + +					} + +				} + +				// not interested in duplicate config entries +				break; +			} + +		} + + +	} + + +	void RequestHandler::cleanup_modules() throw() { + +		int i = 0; + +		// logger +		Logger &logger = Logger::instance(); + +		for ( i = 0; i < _handlers_count; i++ ) { + +			logger.debug( std::string( "[req] unloading module: " ).append( _handlers[i].name ) ); + +			// unload +			unload_modifier( _handlers[i].symbols.modifier ); + +		} + +	} + + +	icap::Response * RequestHandler::process_preview( icap::Request * request, socketlibrary::TCPSocket * socket ) throw() { + +		icap::Response * response = NULL; +		Modifier       * modifier; + +		int i = 0; +		bool continue_status = false; + +		// logger +		Logger &logger = Logger::instance(); + + +		/* +		*  Loop through loaded modifier modules and grab responses +		* +		*  We will only get a chance to get a response from the first +		*  module. But if the first module returns a '100 Continue' response +		*  then we read the rest of the request here before returning a NULL +		*  response. +		*/ +		for ( i = 0 ; i < _handlers_count; i++ ) { + +			// sanity check +			if ( _handlers[i].name == "" ) { +				logger.info( "[req] modifier not loaded, not trying to get a response" ); +				continue; +			} + +			// grab the response from modifier +			logger.debug( std::string( "[req] getting preview response from modifier: " ).append( _handlers[i].name ) ); +			modifier = _handlers[i].symbols.create(); +			response = modifier->preview( request ); + +			// cleanup +			logger.debug( std::string( "[req] cleaning up modifier: " ).append( _handlers[i].name ) ); +			_handlers[i].symbols.destroy( modifier ); + +			// check response status +			if ( ( response->header()->status() == icap::ResponseHeader::NO_CONTENT ) +					|| ( response->header()->status() == icap::ResponseHeader::OK ) ) { +				// no further action needed, break out of the loop +				break; +			} + +			if ( response->header()->status() == icap::ResponseHeader::CONTINUE ) { + +				// read the full response +				continue_status = preview_continue( response, request, socket ); + +				// cleanup +				delete response; + +				// sanity check +				if ( continue_status ) { + +					// success - set the response to NULL +					response = NULL; + +				} else { + +					// something went wrong, server error +					response = new icap::Response( icap::ResponseHeader::SERVER_ERROR ); + +				} + +				// exit the loop +				break; + +			} + +			// we shouldn't have got this far +			logger.info( std::string( "[req] unrecognised preview response from modifier: " ).append( _handlers[i].name ) ); + +		} + +		return response; + +	} + + +	icap::Response * RequestHandler::process_modify( icap::Request * request ) throw() { + +		icap::Response * response = NULL; +		Modifier       * modifier; + +		int i = 0; + +		// logger +		Logger &logger = Logger::instance(); + + +		/* +		*  Loop through loaded modifier modules and grab responses +		* +		*  We will only return the response from the last module +		*  unless a icap::ResponseHeader::OK is received +		*/ +		for ( i = 0 ; i < _handlers_count; i++ ) { + +			// sanity check +			if ( _handlers[i].name == "" ) { +				logger.info( "[req] modifier not loaded, not trying to get a response" ); +				continue; +			} + +			// grab the response from modifier +			logger.debug( std::string( "[req] getting modify response from modifier: " ).append( _handlers[i].name ) ); +			modifier = _handlers[i].symbols.create(); +			response = modifier->modify( request ); + +			// cleanup +			logger.debug( std::string( "[req] cleaning up modifier: " ).append( _handlers[i].name ) ); +			_handlers[i].symbols.destroy( modifier ); + +			// status 200 OK means content modified +			if ( response->header()->status() == icap::ResponseHeader::OK ) { +				logger.debug( "[req] OK response received, not getting responses from other modifiers" ); +				break; +			} + +		} + +		return response; + +	} + + +	bool RequestHandler::preview_continue( icap::Response * response, icap::Request * request, socketlibrary::TCPSocket * socket ) throw() { + +		bool status = false; + +		// logger +		Logger &logger = Logger::instance(); + + +		// sanity check +		if ( request->payload().ieof ) { + +			// we can process a '100 Continue' only if an 'ieof' is not received +			logger.warn( "[req] illegal '100 Continue' response" ); + +		} else { + +			/* read the full request */ + +			// send back the response first +			if ( icap::util::send_response( response, socket ) ) { + +				// read the rest of the request +				status = icap::util::read_req_continue_data( request, socket ); + +			} + +		} + +		return status; + +	} + +} /* end of namespace bitz */ + diff --git a/src/bitz/request_handler.h b/src/bitz/request_handler.h new file mode 100644 index 0000000..3fe99f1 --- /dev/null +++ b/src/bitz/request_handler.h @@ -0,0 +1,133 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifndef BITZ_REQUEST_HANDLER_H +#define BITZ_REQUEST_HANDLER_H + +#include "modifier.h" + +#include <icap/response.h> +#include <icap/request.h> +#include <socket/socket.h> + + +namespace bitz { + +	class RequestHandler { +	public: + +		struct req_handler_t { +			std::string method; +		}; + +		struct handler_t { +			std::string name; +			Modifier::symbols_t symbols; +		}; + +		RequestHandler( const std::string &method ); +		virtual ~RequestHandler(); + +		/** +		*   Returns the request method handled by this handler +		*   @return method +		*/ +		const std::string &method() const throw(); + +		/** +		*   Process the request and return a new response object. This will also +		*   read from the passed in socket if more data needs to be read. +		* +		*   @param req_header request header object +		*   @param socket socket object to read the data from +		*   @return response object +		*/ +		virtual icap::Response * process( icap::RequestHeader * req_header, socketlibrary::TCPSocket * socket ) throw(); + + +	protected: + +		unsigned int _handlers_count; +		handler_t * _handlers; + +		/** +		*   Load a modifier module +		* +		*   @param file file name / path of the module +		*   @param symbols structure to return the symbols +		*   @return boolean to denote success or failure +		*/ +		bool load_modifier( const std::string &file, Modifier::symbols_t &symbols ) throw(); + +		/** +		*   Unload a modifier module +		* +		*   @param modifier pointer to the modifier to unload +		*/ +		void unload_modifier( void * modifier ) throw(); + +		/** +		*   Load all the configured modifier modules for this request handler +		*/ +		void load_modules() throw(); + +		/** +		*  Cleanup all the loaded modifier modules +		*/ +		void cleanup_modules() throw(); + +		/** +		*   Given a request instance and a socket instance to communicate, this method will use the +		*   loaded handler modules to grab a preview response. This will return a icap::Response +		*   object or NULL after processing a '100 Continue' response. +		* +		*   @param request request object +		*   @param socket socket object to read data from +		*   @return preview response (response object) +		*/ +		icap::Response * process_preview( icap::Request * request, socketlibrary::TCPSocket * socket ) throw(); + +		/** +		*   This method will use the loaded handler modules to get a response to the request. +		* +		*   @param request request object +		*   @return response object +		*/ +		icap::Response * process_modify( icap::Request * request ) throw(); + +		/** +		*   Helper method to set a '100 Continue' response back to the client and read the full request. +		* +		*   @param response response object with status 100 +		*   @param request request object +		*   @param socket socket object to read / write data +		*   @return +		*/ +		bool preview_continue( icap::Response * response, icap::Request * request, socketlibrary::TCPSocket * socket ) throw(); + +	private: + +		req_handler_t _req_handler; + +	}; + +} /* end of namespace bitz */ + +#endif /* !BITZ_REQUEST_HANDLER_H */ + diff --git a/src/bitz/respmod_request_handler.cpp b/src/bitz/respmod_request_handler.cpp new file mode 100644 index 0000000..8f99695 --- /dev/null +++ b/src/bitz/respmod_request_handler.cpp @@ -0,0 +1,30 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include "respmod_request_handler.h" + + +namespace bitz { + +	RespmodRequestHandler::RespmodRequestHandler() : RequestHandler( "RESPMOD" ) { } + +	RespmodRequestHandler::~RespmodRequestHandler() { } + +} /* end of namespace bitz */ + diff --git a/src/bitz/respmod_request_handler.h b/src/bitz/respmod_request_handler.h new file mode 100644 index 0000000..dc1a18a --- /dev/null +++ b/src/bitz/respmod_request_handler.h @@ -0,0 +1,41 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifndef BITZ_RESPMOD_REQUEST_HANDLER_H +#define BITZ_RESPMOD_REQUEST_HANDLER_H + +#include "request_handler.h" + + +namespace bitz { + +	class RespmodRequestHandler : public RequestHandler { +	public: + +		RespmodRequestHandler(); +		virtual ~RespmodRequestHandler(); + +	private: + +	}; + +} /* end of namespace bitz */ + +#endif /* !BITZ_RESPMOD_REQUEST_HANDLER_H */ + diff --git a/src/bitz/util.cpp b/src/bitz/util.cpp new file mode 100644 index 0000000..8fedc85 --- /dev/null +++ b/src/bitz/util.cpp @@ -0,0 +1,122 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include "util.h" + +#include <cerrno> +#include <sys/stat.h> + + +namespace bitz { + +	namespace util { + +		RequestHandler * find_req_handler( req_handlers_t req_handlers, const std::string &req_method ) throw() { + +			RequestHandler * req_handler; +			req_handlers_index_t rh_i; +			rh_i = req_handlers.find( req_method ); + +			if ( rh_i != req_handlers.end() ) { +				req_handler = rh_i->second; +			} else { +				req_handler = NULL; +			} + +			return req_handler; + +		} + + +		void delete_req_handlers( req_handlers_t req_handlers ) throw() { + +			req_handlers_index_t rh_i; + +			for ( rh_i = req_handlers.begin(); rh_i != req_handlers.end(); rh_i++ ) { +				if ( rh_i->first != "OPTIONS" ) { +					delete rh_i->second; +				} +			} + +			return; + +		} + + +		std::string dirpath( const std::string &path ) throw() { +			return path.substr( 0, path.find_last_of( '/' ) ); +		} + + +		std::string filename( const std::string &path ) throw() { +			return path.substr( path.find_last_of( '/' ) ); +		} + + +		bool mkdirp( const std::string &path ) throw() { + +			bool r_success = false; + + +			if ( ::mkdir( path.c_str(), 0755 ) == -1 ) { + +				switch( errno ) { + +					case ENOENT: + +						// parent didn't exist, try to create it +						if ( mkdirp( path.substr( 0, path.find_last_of( '/' ) ) ) ) { + +							// try creating the dir again +							r_success = ( 0 == ::mkdir( path.c_str(), 0755 ) ); + +						} else { + +							// failed to create parent +							r_success = false; +						} + +						break; + +					case EEXIST: + +						// already exists +						r_success = true; +						break; + +					default: +						r_success = false; +						break; + +				} + +			} else { +				r_success = true; +			} + + +			return r_success; + +		} + + +	} /* end of namespace util */ + +} /* end of namespace bitz */ + diff --git a/src/bitz/util.h b/src/bitz/util.h new file mode 100644 index 0000000..da1b544 --- /dev/null +++ b/src/bitz/util.h @@ -0,0 +1,92 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifndef BITZ_UTIL_H +#define BITZ_UTIL_H + +#include "common.h" + +#include <string> +#include <sstream> + + +namespace bitz { + +	namespace util { + +		/** +		*   Convert a number into a string +		* +		*   @param number number to be converted +		*   @return converted string +		*/ +		template <typename T> std::string itoa( T number ) { +			std::ostringstream ss; +			ss << number; + +			return ss.str(); +		} + +		/** +		*   Find a matching request handler for the given method +		* +		*   @param req_handlers request handlers +		*   @param req_method request method +		*   @return request handler (or null pointer if not found) +		*/ +		RequestHandler * find_req_handler( req_handlers_t req_handlers, const std::string &req_method ) throw(); + +		/** +		*   Helper method to delete any loaded request handlers apart +		*   from the OPTIONS handler +		* +		*   @param req_handlers request handlers +		*/ +		void delete_req_handlers( req_handlers_t req_handlers ) throw(); + +		/** +		*   Extract directory path from a path +		* +		*   @param path path to extract the directory from +		*   @return directory path +		*/ +		std::string dirpath( const std::string &path ) throw(); + +		/** +		*   Extract the file name from a path +		* +		*   @param path path to extract the file name from +		*   @return file name +		*/ +		std::string filename( const std::string &path ) throw(); + +		/** +		*   Create a directory tree recursively +		* +		*   @param path full directory path +		*   @return boolean to denote success or failure +		*/ +		bool mkdirp( const std::string &path ) throw(); + +	} /* end of namespace util */ + +} /* end of namespace bitz */ + +#endif /* !BITZ_UTIL_H */ + diff --git a/src/bitz/worker.cpp b/src/bitz/worker.cpp new file mode 100644 index 0000000..efbeef3 --- /dev/null +++ b/src/bitz/worker.cpp @@ -0,0 +1,138 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include "worker.h" +#include "logger.h" +#include "util.h" +#include "options_request_handler.h" +#include "reqmod_request_handler.h" +#include "respmod_request_handler.h" + +#include <icap/util.h> +#include <icap/request_header.h> + + +namespace bitz { + +	Worker::Worker() { + +		// load request handlers +		load_req_handlers(); + +	} + + +	Worker::~Worker() { + +		// logger +		Logger &logger = Logger::instance(); +		logger.debug( "[worker] exiting" ); + +		// cleanup request handlers +		util::delete_req_handlers( _req_handlers ); +		delete _req_handlers["OPTIONS"]; + +	} + + +	void Worker::run( socketlibrary::TCPServerSocket * server_sock, unsigned int max_requests ) throw() { + +		Logger &logger = Logger::instance(); + +		socketlibrary::TCPSocket * client_sock; +		icap::RequestHeader * req_header; +		icap::Response * response; +		RequestHandler * req_handler; + + +		try { + +			while ( max_requests > 0 ) { + +				logger.debug( std::string( "[worker] waiting for a connection" ) ); + +				client_sock = server_sock->accept(); +				logger.debug( std::string( "[worker] new connection accepted on " ).append( client_sock->getForeignAddress() ) +						.append( ":" ).append( util::itoa( client_sock->getForeignPort() ) ) ); + +				// request header +				req_header  = icap::util::read_req_header( client_sock ); +				logger.debug( std::string( "[worker] request header:\r\n" ).append( req_header->raw_data() ) ); + +				// try to find a handler for the request +				req_handler = util::find_req_handler( _req_handlers, req_header->method() ); + +				if ( req_handler != NULL ) { + +					logger.debug( std::string( "[worker] handling request: " ).append( req_header->method() ) ); + +					// process the request and grab the response +					response = req_handler->process( req_header, client_sock ); + +				} else { + +					// unsupported request +					logger.info( std::string( "[worker] unsupported request: " ).append( req_header->method() ) ); +					response = new icap::Response( new icap::ResponseHeader( icap::ResponseHeader::NOT_ALLOWED ) ); + +				} + +				// send the response back to the client +				icap::util::send_response( response, client_sock ); + +				// cleanup +				delete response; +				delete req_header; + +				// destroy / close connection +				delete client_sock; + +				max_requests--; + +			} + +		} catch( socketlibrary::SocketException &sex ) { +			logger.error( std::string( "[worker] ERROR: " ).append( sex.what() ) ); +		} + +	} + + +	void Worker::load_req_handlers() throw() { + +		OptionsRequestHandler * options_handler; + +		// OPTIONS handler +		options_handler = new OptionsRequestHandler(); +		_req_handlers["OPTIONS"] = options_handler; + +		/* request handlers */ + +		// REQMOD +		_req_handlers["REQMOD"]  = new ReqmodRequestHandler(); +		options_handler->register_handler( _req_handlers["REQMOD"] ); + +		// RESPMOD +		_req_handlers["RESPMOD"] = new RespmodRequestHandler(); +		options_handler->register_handler( _req_handlers["RESPMOD"] ); + +	} + +} /* end of namespace bitz */ + diff --git a/src/bitz/worker.h b/src/bitz/worker.h new file mode 100644 index 0000000..69edbca --- /dev/null +++ b/src/bitz/worker.h @@ -0,0 +1,47 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifndef BITZ_WORKER_H +#define BITZ_WORKER_H + +#include <socket/socket.h> + +#include "common.h" + + +namespace bitz { + +	class Worker { +	public: +		Worker(); +		virtual ~Worker(); + +		virtual void run( socketlibrary::TCPServerSocket * server_sock, unsigned int max_requests ) throw(); + +	private: +		req_handlers_t    _req_handlers; + +		virtual void load_req_handlers() throw(); + +	}; + +} /* end of namespace bitz */ + +#endif /* !BITZ_WORKER_H */ + diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..e00c1c6 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,82 @@ +/* + *	bitz-server, An ICAP server implementation in C++ + *	Copyright (C) 2012	Uditha Atukorala + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License as published by + *	the Free Software Foundation; either version 3 of the License, or + *	(at your option) any later version. + * + *	This program is distributed in the hope that it will be useful, + *	but WITHOUT ANY WARRANTY; without even the implied warranty of + *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *	GNU General Public License for more details. + * + *	You should have received a copy of the GNU General Public License + *	along with this program; if not, write to the Free Software + *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include <cstdlib> + +#include <config.h> +#include "bitz-server.h" +#include "bitz/config.h" +#include "bitz/logger.h" +#include "bitz/util.h" + + +int main( int argc, char **argv ) { + +	// initialise the server +	bitz::server::init(); + +	// read command line options +	bitz::server::options_t opt = bitz::server::read_options( argc, argv ); + +	// initialise configurations +	bitz::Config &server_config = bitz::Config::instance(); + +	if ( opt.config_file != "" ) { +		server_config.initialise( opt.config_file ); +	} else { +		server_config.initialise(); +	} + +	// get a copy of the configs +	const bitz::config_t &config = server_config.configs(); + +	// create directories +	if ( ( opt.debug_flag != 1 ) && (! bitz::util::mkdirp( bitz::util::dirpath( config.pid_file ) ) ) ) { +		std::cerr << "[core] failed to create run dir" << std::endl; +		exit( EXIT_FAILURE ); +	} + +	if (! bitz::util::mkdirp( bitz::util::dirpath( config.log_file ) ) ) { +		std::cerr << "[core] failed to create log dir" << std::endl; +		exit( EXIT_FAILURE ); +	} + + +	// daemonize +	if ( opt.debug_flag != 1 ) { +		bitz::server::daemonize( bitz::util::dirpath( config.pid_file ).c_str(), config.pid_file.c_str() ); +	} + +	// initialise the logger +	bitz::Logger &logger = bitz::Logger::instance( config.log_file, config.log_category ); +	logger.info( std::string( PACKAGE_STRING ) + " initialised" ); + +	// start the server +	bitz::server::start( config.port, config.max_workers, config.max_worker_requests ); + +	// run the server +	bitz::server::run(); + +	// we should never get here +	bitz::server::shutdown(); + +	return( EXIT_SUCCESS ); + +} + diff --git a/test/icap-client.py b/test/icap-client.py new file mode 100644 index 0000000..622d9ca --- /dev/null +++ b/test/icap-client.py @@ -0,0 +1,211 @@ +#!/usr/bin/env python +# +# icap-client.py +# Copyright (c) 2013 Uditha Atukorala +# + +# simple icap client to test a server implementation + +import socket +import sys + +HOST    = 'localhost' +SERVICE = 'icap://icap.server.net/sample-service' +PORT    = 1344 + +# OPTIONS +print "----- OPTIONS -----" +try: +	sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +except socket.error, msg: +	sys.stderr.write("[ERROR] %s\n" % msg[1]) +	sys.exit(1) + +try: +	sock.connect((HOST, PORT)) +except socket.error, msg: +	sys.stderr.write("[ERROR] %s\n" % msg[1]) +	sys.exit(2) + +sock.send( "OPTIONS %s ICAP/1.0\r\n" % ( SERVICE ) ) +sock.send( "Host: %s\r\n" % ( HOST ) ) +sock.send( "User-Agent: Python ICAP tester\r\n" ) +sock.send( "\r\n" ) + + +data = sock.recv(1024) +string = "" +while len(data): +	string = string + data +	data = sock.recv(1024) +sock.close() + +print string + + +# REQMOD, GET +print "----- REQMOD - GET -----" +try: +	sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +except socket.error, msg: +	sys.stderr.write("[ERROR] %s\n" % msg[1]) +	sys.exit(1) + +try: +	sock.connect((HOST, PORT)) +except socket.error, msg: +	sys.stderr.write("[ERROR] %s\n" % msg[1]) +	sys.exit(2) + +sock.send( "REQMOD %s ICAP/1.0\r\n" % ( SERVICE ) ) +sock.send( "Host: %s\r\n" % ( HOST ) ) +sock.send( "Encapsulated: req-hdr=0, null-body=170\r\n" ) +sock.send( "\r\n" ) + +sock.send( "GET / HTTP/1.1\r\n" ) +sock.send( "Host: www.origin-server.com\r\n" ) +sock.send( "Accept: text/html, text/plain\r\n" ) +sock.send( "Accept-Encoding: compress\r\n" ) +sock.send( "Cookie: ff39fk3jur@4ii0e02i\r\n" ) +sock.send( "If-None-Match: \"xyzzy\", \"r2d2xxxe\"\r\n" ) +sock.send( "\r\n" ) + + +data = sock.recv(1024) +string = "" +while len(data): +	string = string + data +	data = sock.recv(1024) +sock.close() + +print string + + +# REQMOD, POST +print "----- REQMOD - POST -----" +try: +	sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +except socket.error, msg: +	sys.stderr.write("[ERROR] %s\n" % msg[1]) +	sys.exit(1) + +try: +	sock.connect((HOST, PORT)) +except socket.error, msg: +	sys.stderr.write("[ERROR] %s\n" % msg[1]) +	sys.exit(2) + +sock.send( "REQMOD %s ICAP/1.0\r\n" % ( SERVICE ) ) +sock.send( "Host: %s\r\n" % ( HOST ) ) +sock.send( "Encapsulated: req-hdr=0, req-body=147\r\n" ) +sock.send( "\r\n" ) + +sock.send( "POST /origin-resource/form.pl HTTP/1.1\r\n" ) +sock.send( "Host: www.origin-server.com\r\n" ) +sock.send( "Accept: text/html, text/plain\r\n" ) +sock.send( "Accept-Encoding: compress\r\n" ) +sock.send( "Pragma: no-cache\r\n" ) +sock.send( "\r\n" ) +sock.send( "1e\r\n" ) +sock.send( "I am posting this information.\r\n" ) +sock.send( "0\r\n" ) +sock.send( "\r\n" ) + +data = sock.recv(1024) +string = "" +while len(data): +	string = string + data +	data = sock.recv(1024) +sock.close() + +print string + + +# REQMOD - Message preview +print "----- REQMOD - Message preview -----" +try: +	sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +except socket.error, msg: +	sys.stderr.write("[ERROR] %s\n" % msg[1]) +	sys.exit(1) + +try: +	sock.connect((HOST, PORT)) +except socket.error, msg: +	sys.stderr.write("[ERROR] %s\n" % msg[1]) +	sys.exit(2) + +sock.send( "REQMOD %s ICAP/1.0\r\n" % ( SERVICE ) ) +sock.send( "Host: %s\r\n" % ( HOST ) ) +sock.send( "Preview: 1024\r\n" ) +sock.send( "Encapsulated: req-hdr=0, req-body=147\r\n" ) +sock.send( "\r\n" ) + +sock.send( "POST /origin-resource/form.pl HTTP/1.1\r\n" ) +sock.send( "Host: www.origin-server.com\r\n" ) +sock.send( "Accept: text/html, text/plain\r\n" ) +sock.send( "Accept-Encoding: compress\r\n" ) +sock.send( "Pragma: no-cache\r\n" ) +sock.send( "\r\n" ) +sock.send( "1e\r\n" ) +sock.send( "I am posting this information.\r\n" ) +sock.send( "0; ieof\r\n\r\n" ) + +data = sock.recv(1024) +string = "" +while len(data): +	string = string + data +	data = sock.recv(1024) +sock.close() + +print string + + +# RESPMOD +print "----- RESPMOD -----" +try: +	sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +except socket.error, msg: +	sys.stderr.write("[ERROR] %s\n" % msg[1]) +	sys.exit(1) + +try: +	sock.connect((HOST, PORT)) +except socket.error, msg: +	sys.stderr.write("[ERROR] %s\n" % msg[1]) +	sys.exit(2) + +sock.send( "RESPMOD %s ICAP/1.0\r\n" % ( SERVICE ) ) +sock.send( "Host: %s\r\n" % ( HOST ) ) +sock.send( "Encapsulated: req-hdr=0, res-hdr=137, res-body=296\r\n" ) +sock.send( "\r\n" ) + +sock.send( "GET /origin-resource HTTP/1.1\r\n" ) +sock.send( "Host: www.origin-server.com\r\n" ) +sock.send( "Accept: text/html, text/plain, image/gif\r\n" ) +sock.send( "Accept-Encoding: gzip, compress\r\n" ) +sock.send( "\r\n" ) +sock.send( "HTTP/1.1 200 OK\r\n" ) +sock.send( "Date: Mon, 10 Jan 2000 09:52:22 GMT\r\n" ) +sock.send( "Server: Apache/1.3.6 (Unix)\r\n" ) +sock.send( 'ETag: "63840-1ab7-378d415b"\r\n' ) +sock.send( "Content-Type: text/html\r\n" ) +sock.send( "Content-Length: 51\r\n" ) +sock.send( "\r\n" ) +sock.send( "33\r\n" ) +sock.send( "This is data that was returned by an origin server.\r\n" ) +sock.send( "0\r\n" ) +sock.send( "\r\n" ) + +data = sock.recv(1024) +string = "" +while len(data): +	string = string + data +	data = sock.recv(1024) +sock.close() + +print string + + +sys.exit(0) + diff --git a/test/sample.txt b/test/sample.txt new file mode 100644 index 0000000..a149049 --- /dev/null +++ b/test/sample.txt @@ -0,0 +1,192 @@ +REQMOD +====== + +ICAP Request Modification Example 1 - ICAP Request +---------------------------------------------------------------- +REQMOD icap://icap-server.net/server?arg=87 ICAP/1.0 +Host: icap-server.net +Encapsulated: req-hdr=0, null-body=170 + +GET / HTTP/1.1 +Host: www.origin-server.com +Accept: text/html, text/plain +Accept-Encoding: compress +Cookie: ff39fk3jur@4ii0e02i +If-None-Match: "xyzzy", "r2d2xxxx" + +---------------------------------------------------------------- +ICAP Request Modification Example 1 - ICAP Response +---------------------------------------------------------------- +ICAP/1.0 200 OK +Date: Mon, 10 Jan 2000  09:55:21 GMT +Server: ICAP-Server-Software/1.0 +Connection: close +ISTag: "W3E4R7U9-L2E4-2" +Encapsulated: req-hdr=0, null-body=231 + +GET /modified-path HTTP/1.1 +Host: www.origin-server.com +Via: 1.0 icap-server.net (ICAP Example ReqMod Service 1.1) +Accept: text/html, text/plain, image/gif +Accept-Encoding: gzip, compress +If-None-Match: "xyzzy", "r2d2xxxx" + +---------------------------------------------------------------- + + + +ICAP Request Modification Example 2 - ICAP Request +---------------------------------------------------------------- +REQMOD icap://icap-server.net/server?arg=87 ICAP/1.0 +Host: icap-server.net +Encapsulated: req-hdr=0, req-body=147 + +POST /origin-resource/form.pl HTTP/1.1 +Host: www.origin-server.com +Accept: text/html, text/plain +Accept-Encoding: compress +Pragma: no-cache + +1e +I am posting this information. +0 + +---------------------------------------------------------------- +ICAP Request Modification Example 2 - ICAP Response +---------------------------------------------------------------- +ICAP/1.0 200 OK +Date: Mon, 10 Jan 2000  09:55:21 GMT +Server: ICAP-Server-Software/1.0 +Connection: close +ISTag: "W3E4R7U9-L2E4-2" +Encapsulated: req-hdr=0, req-body=244 + +POST /origin-resource/form.pl HTTP/1.1 +Host: www.origin-server.com +Via: 1.0 icap-server.net (ICAP Example ReqMod Service 1.1) +Accept: text/html, text/plain, image/gif +Accept-Encoding: gzip, compress +Pragma: no-cache +Content-Length: 45 + +2d +I am posting this information.  ICAP powered! +0 + +---------------------------------------------------------------- + + +ICAP Request Modification Example 3 - ICAP Request +---------------------------------------------------------------- +REQMOD icap://icap-server.net/content-filter ICAP/1.0 +Host: icap-server.net +Encapsulated: req-hdr=0, null-body=119 + +GET /naughty-content HTTP/1.1 +Host: www.naughty-site.com +Accept: text/html, text/plain +Accept-Encoding: compress + +---------------------------------------------------------------- +ICAP Request Modification Example 3 - ICAP Response +---------------------------------------------------------------- +ICAP/1.0 200 OK +Date: Mon, 10 Jan 2000  09:55:21 GMT +Server: ICAP-Server-Software/1.0 +Connection: close +ISTag: "W3E4R7U9-L2E4-2" +Encapsulated: res-hdr=0, res-body=213 + +HTTP/1.1 403 Forbidden +Date: Wed, 08 Nov 2000 16:02:10 GMT +Server: Apache/1.3.12 (Unix) +Last-Modified: Thu, 02 Nov 2000 13:51:37 GMT +ETag: "63600-1989-3a017169" +Content-Length: 58 +Content-Type: text/html + +3a +Sorry, you are not allowed to access that naughty content. +0 + +---------------------------------------------------------------- + + +RESPMOD +======= + +ICAP Response Modification Example 4 - ICAP Request +---------------------------------------------------------------- +RESPMOD icap://icap.example.org/satisf ICAP/1.0 +Host: icap.example.org +Encapsulated: req-hdr=0, res-hdr=137, res-body=296 + +GET /origin-resource HTTP/1.1 +Host: www.origin-server.com +Accept: text/html, text/plain, image/gif +Accept-Encoding: gzip, compress + +HTTP/1.1 200 OK +Date: Mon, 10 Jan 2000 09:52:22 GMT +Server: Apache/1.3.6 (Unix) +ETag: "63840-1ab7-378d415b" +Content-Type: text/html +Content-Length: 51 + +33 +This is data that was returned by an origin server. +0 + +---------------------------------------------------------------- +ICAP Response Modification Example 4 - ICAP Response +---------------------------------------------------------------- +ICAP/1.0 200 OK +Date: Mon, 10 Jan 2000  09:55:21 GMT +Server: ICAP-Server-Software/1.0 +Connection: close +ISTag: "W3E4R7U9-L2E4-2" +Encapsulated: res-hdr=0, res-body=222 + +HTTP/1.1 200 OK +Date: Mon, 10 Jan 2000  09:55:21 GMT +Via: 1.0 icap.example.org (ICAP Example RespMod Service 1.1) +Server: Apache/1.3.6 (Unix) +ETag: "63840-1ab7-378d415b" +Content-Type: text/html +Content-Length: 92 + +5c +This is data that was returned by an origin server, but with +value added by an ICAP server. +0 + +---------------------------------------------------------------- + + +OPTIONS +======= + +ICAP OPTIONS Example 5 - ICAP OPTIONS Request +---------------------------------------------------------------- +OPTIONS icap://icap.server.net/sample-service ICAP/1.0 +Host: icap.server.net +User-Agent: BazookaDotCom-ICAP-Client-Library/2.3 + +---------------------------------------------------------------- +ICAP OPTIONS Example 5 - ICAP OPTIONS Response +---------------------------------------------------------------- +ICAP/1.0 200 OK +Date: Mon, 10 Jan 2000  09:55:21 GMT +Methods: RESPMOD +Service: FOO Tech Server 1.0 +ISTag: "W3E4R7U9-L2E4-2" +Encapsulated: null-body=0 +Max-Connections: 1000 +Options-TTL: 7200 +Allow: 204 +Preview: 2048 +Transfer-Complete: asp, bat, exe, com +Transfer-Ignore: html +Transfer-Preview: * + +----------------------------------------------------------------
\ No newline at end of file diff --git a/test/valgrind.supp b/test/valgrind.supp new file mode 100644 index 0000000..be525db --- /dev/null +++ b/test/valgrind.supp @@ -0,0 +1,29 @@ +# +# valgrind.supp +# + +# Python +{ +	Python 2.7 (libpython2.7.so.1.0) +	Memcheck:Value4 +	obj:/usr/lib/libpython2.7.so.1.0 +} + +{ +	Python 2.7 (libpython2.7.so.1.0) +	Memcheck:Addr4 +	obj:/usr/lib/libpython2.7.so.1.0 +} + +{ +	Python 2.7 (libpython2.7.so.1.0) +	Memcheck:Value8 +	obj:/usr/lib/libpython2.7.so.1.0 +} + +{ +	Python 2.7 (libpython2.7.so.1.0) +	Memcheck:Cond +	obj:/usr/lib/libpython2.7.so.1.0 +} +  | 
