From bb9bc9051629c3319c56785c2f4ae0e605d76329 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Sat, 21 Nov 2015 14:51:17 +0100 Subject: Initial import of bitz-server version 0.1.6-1 --- .gitignore | 38 + Makefile.am | 19 + README.md | 168 ++ acinclude.m4 | 134 ++ changelog | 36 + conf/Makefile.am | 26 + conf/bitz-server.conf.in | 56 + configure.ac | 147 ++ debian/README.debian | 12 + debian/README.lintian | 7 + debian/bitz-server-doc.dirs | 1 + debian/bitz-server-doc.doc-base | 7 + debian/bitz-server-doc.docs | 1 + debian/bitz-server-doc.lintian-overrides | 7 + debian/bitz-server.docs | 2 + debian/bitz-server.init | 132 ++ debian/bitz-server.install | 2 + debian/bitz-server.manpages | 2 + debian/bitz-server.postrm | 22 + debian/bitz-server.service | 11 + debian/bitz-server.upstart | 7 + debian/changelog | 5 + debian/compat | 1 + debian/control | 162 ++ debian/copyright | 33 + debian/doc/why_delete_systemd_file_via_postrm.txt | 807 +++++++++ debian/libicap-dev.docs | 1 + debian/libicap-dev.install | 2 + debian/libicap0.install | 1 + debian/libicap0.symbols | 193 +++ debian/libicap0.symbols.i386 | 187 +++ debian/patches/0001-disable_search_doc.patch | 18 + debian/patches/0100-python_print.patch | 171 ++ debian/patches/series | 2 + debian/rules | 35 + debian/source/format | 1 + debian/watch | 5 + doc/Makefile.am | 30 + doc/bitz-server.conf.man | 64 + doc/bitz-server.man | 47 + doc/doxygen.cfg.in | 1864 +++++++++++++++++++++ include/Makefile.am | 1 + lib/Makefile.am | 3 + lib/icap/Makefile.am | 24 + lib/icap/common.h | 41 + lib/icap/header.cpp | 223 +++ lib/icap/header.h | 168 ++ lib/icap/request.cpp | 84 + lib/icap/request.h | 72 + lib/icap/request_header.cpp | 113 ++ lib/icap/request_header.h | 84 + lib/icap/response.cpp | 81 + lib/icap/response.h | 65 + lib/icap/response_header.cpp | 101 ++ lib/icap/response_header.h | 78 + lib/icap/util.cpp | 693 ++++++++ lib/icap/util.h | 265 +++ lib/socket/Makefile.am | 4 + lib/socket/socket.cpp | 472 ++++++ lib/socket/socket.h | 427 +++++ modules/Makefile.am | 3 + modules/echo/Makefile.am | 9 + modules/echo/echo.cpp | 55 + modules/echo/echo.h | 54 + modules/modpy/Makefile.am | 18 + modules/modpy/interface.cpp | 160 ++ modules/modpy/interface.h | 39 + modules/modpy/modules/Makefile.am | 11 + modules/modpy/modules/modpy.py | 42 + modules/modpy/py.cpp | 265 +++ modules/modpy/py.h | 70 + src/Makefile.am | 32 + src/bitz-server.cpp | 472 ++++++ src/bitz-server.h | 113 ++ src/bitz/common.h | 40 + src/bitz/config.cpp | 190 +++ src/bitz/config.h | 95 ++ src/bitz/exception.cpp | 40 + src/bitz/exception.h | 43 + src/bitz/logger.cpp | 98 ++ src/bitz/logger.h | 62 + src/bitz/manager.cpp | 223 +++ src/bitz/manager.h | 87 + src/bitz/manager_exception.cpp | 32 + src/bitz/manager_exception.h | 36 + src/bitz/modifier.cpp | 29 + src/bitz/modifier.h | 70 + src/bitz/options_request_handler.cpp | 57 + src/bitz/options_request_handler.h | 51 + src/bitz/reqmod_request_handler.cpp | 30 + src/bitz/reqmod_request_handler.h | 41 + src/bitz/request_handler.cpp | 401 +++++ src/bitz/request_handler.h | 133 ++ src/bitz/respmod_request_handler.cpp | 30 + src/bitz/respmod_request_handler.h | 41 + src/bitz/util.cpp | 122 ++ src/bitz/util.h | 92 + src/bitz/worker.cpp | 138 ++ src/bitz/worker.h | 47 + src/main.cpp | 82 + test/icap-client.py | 211 +++ test/sample.txt | 192 +++ test/valgrind.supp | 29 + 103 files changed, 11550 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile.am create mode 100644 README.md create mode 100644 acinclude.m4 create mode 100644 changelog create mode 100644 conf/Makefile.am create mode 100644 conf/bitz-server.conf.in create mode 100644 configure.ac create mode 100644 debian/README.debian create mode 100644 debian/README.lintian create mode 100644 debian/bitz-server-doc.dirs create mode 100644 debian/bitz-server-doc.doc-base create mode 100644 debian/bitz-server-doc.docs create mode 100644 debian/bitz-server-doc.lintian-overrides create mode 100644 debian/bitz-server.docs create mode 100644 debian/bitz-server.init create mode 100644 debian/bitz-server.install create mode 100644 debian/bitz-server.manpages create mode 100644 debian/bitz-server.postrm create mode 100644 debian/bitz-server.service create mode 100644 debian/bitz-server.upstart create mode 100644 debian/changelog create mode 100644 debian/compat create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/doc/why_delete_systemd_file_via_postrm.txt create mode 100644 debian/libicap-dev.docs create mode 100644 debian/libicap-dev.install create mode 100644 debian/libicap0.install create mode 100644 debian/libicap0.symbols create mode 100644 debian/libicap0.symbols.i386 create mode 100644 debian/patches/0001-disable_search_doc.patch create mode 100644 debian/patches/0100-python_print.patch create mode 100644 debian/patches/series create mode 100755 debian/rules create mode 100644 debian/source/format create mode 100644 debian/watch create mode 100644 doc/Makefile.am create mode 100644 doc/bitz-server.conf.man create mode 100644 doc/bitz-server.man create mode 100644 doc/doxygen.cfg.in create mode 100644 include/Makefile.am create mode 100644 lib/Makefile.am create mode 100644 lib/icap/Makefile.am create mode 100644 lib/icap/common.h create mode 100644 lib/icap/header.cpp create mode 100644 lib/icap/header.h create mode 100644 lib/icap/request.cpp create mode 100644 lib/icap/request.h create mode 100644 lib/icap/request_header.cpp create mode 100644 lib/icap/request_header.h create mode 100644 lib/icap/response.cpp create mode 100644 lib/icap/response.h create mode 100644 lib/icap/response_header.cpp create mode 100644 lib/icap/response_header.h create mode 100644 lib/icap/util.cpp create mode 100644 lib/icap/util.h create mode 100644 lib/socket/Makefile.am create mode 100644 lib/socket/socket.cpp create mode 100644 lib/socket/socket.h create mode 100644 modules/Makefile.am create mode 100644 modules/echo/Makefile.am create mode 100644 modules/echo/echo.cpp create mode 100644 modules/echo/echo.h create mode 100644 modules/modpy/Makefile.am create mode 100644 modules/modpy/interface.cpp create mode 100644 modules/modpy/interface.h create mode 100644 modules/modpy/modules/Makefile.am create mode 100644 modules/modpy/modules/modpy.py create mode 100644 modules/modpy/py.cpp create mode 100644 modules/modpy/py.h create mode 100644 src/Makefile.am create mode 100644 src/bitz-server.cpp create mode 100644 src/bitz-server.h create mode 100644 src/bitz/common.h create mode 100644 src/bitz/config.cpp create mode 100644 src/bitz/config.h create mode 100644 src/bitz/exception.cpp create mode 100644 src/bitz/exception.h create mode 100644 src/bitz/logger.cpp create mode 100644 src/bitz/logger.h create mode 100644 src/bitz/manager.cpp create mode 100644 src/bitz/manager.h create mode 100644 src/bitz/manager_exception.cpp create mode 100644 src/bitz/manager_exception.h create mode 100644 src/bitz/modifier.cpp create mode 100644 src/bitz/modifier.h create mode 100644 src/bitz/options_request_handler.cpp create mode 100644 src/bitz/options_request_handler.h create mode 100644 src/bitz/reqmod_request_handler.cpp create mode 100644 src/bitz/reqmod_request_handler.h create mode 100644 src/bitz/request_handler.cpp create mode 100644 src/bitz/request_handler.h create mode 100644 src/bitz/respmod_request_handler.cpp create mode 100644 src/bitz/respmod_request_handler.h create mode 100644 src/bitz/util.cpp create mode 100644 src/bitz/util.h create mode 100644 src/bitz/worker.cpp create mode 100644 src/bitz/worker.h create mode 100644 src/main.cpp create mode 100644 test/icap-client.py create mode 100644 test/sample.txt create mode 100644 test/valgrind.supp 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 ],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 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 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 . +# 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 " + +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 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 +Uploaders: Uditha Atukorala +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 +License: GPL-3+ + +Files: lib/socket/socket.* +Copyright: 2002 + 2010 Uditha Atukorala +License: GPL-3+ + +Files: debian/* +Copyright: 2014-2015 Jörg Frings-Fürst +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 + . + 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 + 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 + 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 + 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 + 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 + 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 + 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, std::allocator > const&, bool)@Base" 0.1.6 + (c++)"socketlibrary::SocketException::SocketException(std::__cxx11::basic_string, std::allocator > 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, std::allocator > 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, std::allocator > 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 >&)@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, std::allocator > 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, std::allocator > const&, std::__cxx11::basic_string, std::allocator > const&)@Base" 0.1.6 + (c++)"socketlibrary::Socket::getLocalAddress[abi:cxx11]()@Base" 0.1.6 + (c++)"socketlibrary::Socket::setLocalAddressAndPort(std::__cxx11::basic_string, std::allocator > 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, std::allocator > const&, unsigned short, sockaddr_in&)@Base" 0.1.6 + (c++)"socketlibrary::TCPSocket::TCPSocket(std::__cxx11::basic_string, std::allocator > 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, std::allocator > 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, std::allocator > 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, std::allocator > const&, unsigned short)@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::recvFrom(void*, int, std::__cxx11::basic_string, std::allocator >&, unsigned short&)@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::joinGroup(std::__cxx11::basic_string, std::allocator > const&)@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::UDPSocket(std::__cxx11::basic_string, std::allocator > 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, std::allocator > 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, std::allocator > const&)@Base" 0.1.6 + (c++)"icap::RequestHeader::RequestHeader(std::__cxx11::basic_string, std::allocator > const&)@Base" 0.1.6 + (c++)"icap::RequestHeader::RequestHeader(std::__cxx11::basic_string, std::allocator > 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, std::allocator > 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, std::allocator >&)@Base" 0.1.6 + (c++)"icap::util::read_req_continue_data(icap::Request*, socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"std::__cxx11::basic_string, std::allocator > icap::util::itoa(int)@Base" 0.1.6 + (c++)"std::__cxx11::basic_string, std::allocator > icap::util::itoa(long)@Base" 0.1.6 + (c++)"icap::util::trim(std::__cxx11::basic_string, std::allocator >&)@Base" 0.1.6 + (c++)"icap::util::ltrim(std::__cxx11::basic_string, std::allocator >&)@Base" 0.1.6 + (c++)"icap::util::rtrim(std::__cxx11::basic_string, std::allocator >&)@Base" 0.1.6 + (c++)"icap::util::split(std::__cxx11::basic_string, std::allocator > const&, std::__cxx11::basic_string, std::allocator > 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, std::allocator > 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, std::allocator > const&, socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"icap::util::send_line(std::__cxx11::basic_string, std::allocator > const&, socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"icap::Header::attach_encapsulated(std::__cxx11::basic_string, std::allocator >)@Base" 0.1.6 + (c++)"icap::Header::encapsulated_header(std::__cxx11::basic_string, std::allocator > 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, std::allocator > const&)@Base" 0.1.6 + (c++)"icap::Header::attach(std::__cxx11::basic_string, std::allocator >, std::__cxx11::basic_string, std::allocator >)@Base" 0.1.6 + (c++)"icap::Header::remove(std::__cxx11::basic_string, std::allocator >)@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::allocator >, std::allocator, std::allocator > > >::_M_insert_aux(__gnu_cxx::__normal_iterator, std::allocator >*, std::vector, std::allocator >, std::allocator, std::allocator > > > >, std::__cxx11::basic_string, std::allocator > const&)@Base" 0.1.6 + (c++)"std::vector, std::allocator >, std::allocator, std::allocator > > >::~vector()@Base" 0.1.6 + (c++)"std::vector, std::allocator >, std::allocator, std::allocator > > >::~vector()@Base" 0.1.6 + (c++)"std::vector, std::allocator >, std::allocator, std::allocator > > >::operator=(std::vector, std::allocator >, std::allocator, std::allocator > > > const&)@Base" 0.1.6 + (c++)"std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, socketlibrary::TCPSocket* const&)@Base" 0.1.6 + (c++)"std::vector >::_M_fill_insert(__gnu_cxx::__normal_iterator > >, unsigned long, socketlibrary::TCPSocket* const&)@Base" 0.1.6 + (c++)"std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > >::~vector()@Base" 0.1.6 + (c++)"std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > >::~vector()@Base" 0.1.6 + (c++)"std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > >::operator=(std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > const&)@Base" 0.1.6 + (c++)"std::__cxx11::basic_stringbuf, std::allocator >::~basic_stringbuf()@Base" 0.1.6 + (c++)"std::__cxx11::basic_stringbuf, std::allocator >::~basic_stringbuf()@Base" 0.1.6 + (c++)"std::__cxx11::basic_stringbuf, std::allocator >::~basic_stringbuf()@Base" 0.1.6 + (c++)"std::_Rb_tree, std::allocator > >, std::_Select1st, std::allocator > > >, std::less, std::allocator, std::allocator > > > >::_M_get_insert_unique_pos(icap::ResponseHeader::status_t const&)@Base" 0.1.6 + (c++)"std::_Rb_tree, std::allocator > >, std::_Select1st, std::allocator > > >, std::less, std::allocator, std::allocator > > > >::_M_get_insert_hint_unique_pos(std::_Rb_tree_const_iterator, std::allocator > > >, icap::ResponseHeader::status_t const&)@Base" 0.1.6 + (c++)"std::_Rb_tree, std::allocator > >, std::_Select1st, std::allocator > > >, std::less, std::allocator, std::allocator > > > >::_M_erase(std::_Rb_tree_node, std::allocator > > >*)@Base" 0.1.6 + (c++)"std::_Rb_tree, std::allocator >, std::pair, std::allocator > const, std::__cxx11::basic_string, std::allocator > >, std::_Select1st, std::allocator > const, std::__cxx11::basic_string, std::allocator > > >, std::less, std::allocator > >, std::allocator, std::allocator > const, std::__cxx11::basic_string, std::allocator > > > >::equal_range(std::__cxx11::basic_string, std::allocator > const&)@Base" 0.1.6 + (c++)"std::_Rb_tree, std::allocator >, std::pair, std::allocator > const, std::__cxx11::basic_string, std::allocator > >, std::_Select1st, std::allocator > const, std::__cxx11::basic_string, std::allocator > > >, std::less, std::allocator > >, std::allocator, std::allocator > const, std::__cxx11::basic_string, std::allocator > > > >::_M_get_insert_unique_pos(std::__cxx11::basic_string, std::allocator > const&)@Base" 0.1.6 + (c++)"std::_Rb_tree, std::allocator >, std::pair, std::allocator > const, std::__cxx11::basic_string, std::allocator > >, std::_Select1st, std::allocator > const, std::__cxx11::basic_string, std::allocator > > >, std::less, std::allocator > >, std::allocator, std::allocator > const, std::__cxx11::basic_string, std::allocator > > > >::_M_get_insert_hint_unique_pos(std::_Rb_tree_const_iterator, std::allocator > const, std::__cxx11::basic_string, std::allocator > > >, std::__cxx11::basic_string, std::allocator > const&)@Base" 0.1.6 + (c++)"std::_Rb_tree_node, std::allocator > const, std::__cxx11::basic_string, std::allocator > > >* std::_Rb_tree, std::allocator >, std::pair, std::allocator > const, std::__cxx11::basic_string, std::allocator > >, std::_Select1st, std::allocator > const, std::__cxx11::basic_string, std::allocator > > >, std::less, std::allocator > >, std::allocator, std::allocator > const, std::__cxx11::basic_string, std::allocator > > > >::_M_copy, std::allocator >, std::pair, std::allocator > const, std::__cxx11::basic_string, std::allocator > >, std::_Select1st, std::allocator > const, std::__cxx11::basic_string, std::allocator > > >, std::less, std::allocator > >, std::allocator, std::allocator > const, std::__cxx11::basic_string, std::allocator > > > >::_Reuse_or_alloc_node>(std::_Rb_tree_node, std::allocator > const, std::__cxx11::basic_string, std::allocator > > > const*, std::_Rb_tree_node, std::allocator > const, std::__cxx11::basic_string, std::allocator > > >*, std::_Rb_tree, std::allocator >, std::pair, std::allocator > const, std::__cxx11::basic_string, std::allocator > >, std::_Select1st, std::allocator > const, std::__cxx11::basic_string, std::allocator > > >, std::less, std::allocator > >, std::allocator, std::allocator > const, std::__cxx11::basic_string, std::allocator > > > >::_Reuse_or_alloc_node&)@Base" 0.1.6 + (c++)"std::_Rb_tree, std::allocator >, std::pair, std::allocator > const, std::__cxx11::basic_string, std::allocator > >, std::_Select1st, std::allocator > const, std::__cxx11::basic_string, std::allocator > > >, std::less, std::allocator > >, std::allocator, std::allocator > const, std::__cxx11::basic_string, std::allocator > > > >::_M_erase(std::_Rb_tree_node, std::allocator > const, std::__cxx11::basic_string, std::allocator > > >*)@Base" 0.1.6 + (c++)"std::_Rb_tree, std::allocator >, std::pair, std::allocator > const, int>, std::_Select1st, std::allocator > const, int> >, std::less, std::allocator > >, std::allocator, std::allocator > const, int> > >::_M_get_insert_unique_pos(std::__cxx11::basic_string, std::allocator > const&)@Base" 0.1.6 + (c++)"std::_Rb_tree, std::allocator >, std::pair, std::allocator > const, int>, std::_Select1st, std::allocator > const, int> >, std::less, std::allocator > >, std::allocator, std::allocator > const, int> > >::_M_get_insert_hint_unique_pos(std::_Rb_tree_const_iterator, std::allocator > const, int> >, std::__cxx11::basic_string, std::allocator > const&)@Base" 0.1.6 + (c++)"std::_Rb_tree, std::allocator >, std::pair, std::allocator > const, int>, std::_Select1st, std::allocator > const, int> >, std::less, std::allocator > >, std::allocator, std::allocator > const, int> > >::find(std::__cxx11::basic_string, std::allocator > const&)@Base" 0.1.6 + (c++)"std::_Rb_tree, std::allocator >, std::pair, std::allocator > const, int>, std::_Select1st, std::allocator > const, int> >, std::less, std::allocator > >, std::allocator, std::allocator > const, int> > >::_M_erase(std::_Rb_tree_node, std::allocator > const, int> >*)@Base" 0.1.6 + (c++)"void std::__make_heap<__gnu_cxx::__normal_iterator, std::allocator >, int>*, std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > >, __gnu_cxx::__ops::_Iter_comp_iter >(__gnu_cxx::__normal_iterator, std::allocator >, int>*, std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > >, __gnu_cxx::__normal_iterator, std::allocator >, int>*, std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > >, __gnu_cxx::__ops::_Iter_comp_iter)@Base" 0.1.6 + (c++)"void std::__adjust_heap<__gnu_cxx::__normal_iterator, std::allocator >, int>*, std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > >, long, std::pair, std::allocator >, int>, __gnu_cxx::__ops::_Iter_comp_iter >(__gnu_cxx::__normal_iterator, std::allocator >, int>*, std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > >, long, long, std::pair, std::allocator >, int>, __gnu_cxx::__ops::_Iter_comp_iter)@Base" 0.1.6 + (c++)"void std::__insertion_sort<__gnu_cxx::__normal_iterator, std::allocator >, int>*, std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > >, __gnu_cxx::__ops::_Iter_comp_iter >(__gnu_cxx::__normal_iterator, std::allocator >, int>*, std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > >, __gnu_cxx::__normal_iterator, std::allocator >, int>*, std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > >, __gnu_cxx::__ops::_Iter_comp_iter)@Base" 0.1.6 + (c++)"void std::__introsort_loop<__gnu_cxx::__normal_iterator, std::allocator >, int>*, std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > >, long, __gnu_cxx::__ops::_Iter_comp_iter >(__gnu_cxx::__normal_iterator, std::allocator >, int>*, std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > >, __gnu_cxx::__normal_iterator, std::allocator >, int>*, std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > >, long, __gnu_cxx::__ops::_Iter_comp_iter)@Base" 0.1.6 + (c++)"void std::__unguarded_linear_insert<__gnu_cxx::__normal_iterator, std::allocator >, int>*, std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > >, __gnu_cxx::__ops::_Val_comp_iter >(__gnu_cxx::__normal_iterator, std::allocator >, int>*, std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > >, __gnu_cxx::__ops::_Val_comp_iter)@Base" 0.1.6 + (c++)"__gnu_cxx::__normal_iterator, std::allocator > > std::__find_if<__gnu_cxx::__normal_iterator, std::allocator > >, __gnu_cxx::__ops::_Iter_pred > > >(__gnu_cxx::__normal_iterator, std::allocator > >, __gnu_cxx::__normal_iterator, std::allocator > >, __gnu_cxx::__ops::_Iter_pred > >, 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, std::allocator > const&, bool)@Base" 0.1.6 + (c++)"socketlibrary::SocketException::SocketException(std::__cxx11::basic_string, std::allocator > 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, std::allocator > 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, std::allocator > 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 >&)@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, std::allocator > 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, std::allocator > const&, std::__cxx11::basic_string, std::allocator > const&)@Base" 0.1.6 + (c++)"socketlibrary::Socket::getLocalAddress[abi:cxx11]()@Base" 0.1.6 + (c++)"socketlibrary::Socket::setLocalAddressAndPort(std::__cxx11::basic_string, std::allocator > 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, std::allocator > const&, unsigned short, sockaddr_in&)@Base" 0.1.6 + (c++)"socketlibrary::TCPSocket::TCPSocket(std::__cxx11::basic_string, std::allocator > 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, std::allocator > 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, std::allocator > 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, std::allocator > const&, unsigned short)@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::recvFrom(void*, int, std::__cxx11::basic_string, std::allocator >&, unsigned short&)@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::joinGroup(std::__cxx11::basic_string, std::allocator > const&)@Base" 0.1.6 + (c++)"socketlibrary::UDPSocket::UDPSocket(std::__cxx11::basic_string, std::allocator > 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, std::allocator > 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, std::allocator > const&)@Base" 0.1.6 + (c++)"icap::RequestHeader::RequestHeader(std::__cxx11::basic_string, std::allocator > const&)@Base" 0.1.6 + (c++)"icap::RequestHeader::RequestHeader(std::__cxx11::basic_string, std::allocator > 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, std::allocator > 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, std::allocator >&)@Base" 0.1.6 + (c++)"icap::util::read_req_continue_data(icap::Request*, socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"std::__cxx11::basic_string, std::allocator > icap::util::itoa(long)@Base" 0.1.6 + (c++)"icap::util::trim(std::__cxx11::basic_string, std::allocator >&)@Base" 0.1.6 + (c++)"icap::util::ltrim(std::__cxx11::basic_string, std::allocator >&)@Base" 0.1.6 + (c++)"icap::util::rtrim(std::__cxx11::basic_string, std::allocator >&)@Base" 0.1.6 + (c++)"icap::util::split(std::__cxx11::basic_string, std::allocator > const&, std::__cxx11::basic_string, std::allocator > 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, std::allocator > 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, std::allocator > const&, socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"icap::util::send_line(std::__cxx11::basic_string, std::allocator > const&, socketlibrary::TCPSocket*)@Base" 0.1.6 + (c++)"icap::Header::attach_encapsulated(std::__cxx11::basic_string, std::allocator >)@Base" 0.1.6 + (c++)"icap::Header::encapsulated_header(std::__cxx11::basic_string, std::allocator > 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, std::allocator > const&)@Base" 0.1.6 + (c++)"icap::Header::attach(std::__cxx11::basic_string, std::allocator >, std::__cxx11::basic_string, std::allocator >)@Base" 0.1.6 + (c++)"icap::Header::remove(std::__cxx11::basic_string, std::allocator >)@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::allocator >, std::allocator, std::allocator > > >::_M_insert_aux(__gnu_cxx::__normal_iterator, std::allocator >*, std::vector, std::allocator >, std::allocator, std::allocator > > > >, std::__cxx11::basic_string, std::allocator > const&)@Base" 0.1.6 + (c++)"std::vector, std::allocator >, std::allocator, std::allocator > > >::~vector()@Base" 0.1.6 + (c++)"std::vector, std::allocator >, std::allocator, std::allocator > > >::~vector()@Base" 0.1.6 + (c++)"std::vector, std::allocator >, std::allocator, std::allocator > > >::operator=(std::vector, std::allocator >, std::allocator, std::allocator > > > const&)@Base" 0.1.6 + (c++)"std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, socketlibrary::TCPSocket* const&)@Base" 0.1.6 + (c++)"std::vector >::_M_fill_insert(__gnu_cxx::__normal_iterator > >, unsigned int, socketlibrary::TCPSocket* const&)@Base" 0.1.6 + (c++)"std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > >::~vector()@Base" 0.1.6 + (c++)"std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > >::~vector()@Base" 0.1.6 + (c++)"std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > >::operator=(std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > const&)@Base" 0.1.6 + (c++)"std::__cxx11::basic_stringbuf, std::allocator >::~basic_stringbuf()@Base" 0.1.6 + (c++)"std::__cxx11::basic_stringbuf, std::allocator >::~basic_stringbuf()@Base" 0.1.6 + (c++)"std::__cxx11::basic_stringbuf, std::allocator >::~basic_stringbuf()@Base" 0.1.6 + (c++)"std::_Rb_tree, std::allocator > >, std::_Select1st, std::allocator > > >, std::less, std::allocator, std::allocator > > > >::_M_get_insert_unique_pos(icap::ResponseHeader::status_t const&)@Base" 0.1.6 + (c++)"std::_Rb_tree, std::allocator > >, std::_Select1st, std::allocator > > >, std::less, std::allocator, std::allocator > > > >::_M_erase(std::_Rb_tree_node, std::allocator > > >*)@Base" 0.1.6 + (c++)"std::_Rb_tree, std::allocator >, std::pair, std::allocator > const, std::__cxx11::basic_string, std::allocator > >, std::_Select1st, std::allocator > const, std::__cxx11::basic_string, std::allocator > > >, std::less, std::allocator > >, std::allocator, std::allocator > const, std::__cxx11::basic_string, std::allocator > > > >::_M_get_insert_unique_pos(std::__cxx11::basic_string, std::allocator > const&)@Base" 0.1.6 + (c++)"std::_Rb_tree_node, std::allocator > const, std::__cxx11::basic_string, std::allocator > > >* std::_Rb_tree, std::allocator >, std::pair, std::allocator > const, std::__cxx11::basic_string, std::allocator > >, std::_Select1st, std::allocator > const, std::__cxx11::basic_string, std::allocator > > >, std::less, std::allocator > >, std::allocator, std::allocator > const, std::__cxx11::basic_string, std::allocator > > > >::_M_copy, std::allocator >, std::pair, std::allocator > const, std::__cxx11::basic_string, std::allocator > >, std::_Select1st, std::allocator > const, std::__cxx11::basic_string, std::allocator > > >, std::less, std::allocator > >, std::allocator, std::allocator > const, std::__cxx11::basic_string, std::allocator > > > >::_Reuse_or_alloc_node>(std::_Rb_tree_node, std::allocator > const, std::__cxx11::basic_string, std::allocator > > > const*, std::_Rb_tree_node, std::allocator > const, std::__cxx11::basic_string, std::allocator > > >*, std::_Rb_tree, std::allocator >, std::pair, std::allocator > const, std::__cxx11::basic_string, std::allocator > >, std::_Select1st, std::allocator > const, std::__cxx11::basic_string, std::allocator > > >, std::less, std::allocator > >, std::allocator, std::allocator > const, std::__cxx11::basic_string, std::allocator > > > >::_Reuse_or_alloc_node&)@Base" 0.1.6 + (c++)"std::_Rb_tree, std::allocator >, std::pair, std::allocator > const, std::__cxx11::basic_string, std::allocator > >, std::_Select1st, std::allocator > const, std::__cxx11::basic_string, std::allocator > > >, std::less, std::allocator > >, std::allocator, std::allocator > const, std::__cxx11::basic_string, std::allocator > > > >::_M_erase(std::_Rb_tree_node, std::allocator > const, std::__cxx11::basic_string, std::allocator > > >*)@Base" 0.1.6 + (c++)"std::_Rb_tree, std::allocator >, std::pair, std::allocator > const, int>, std::_Select1st, std::allocator > const, int> >, std::less, std::allocator > >, std::allocator, std::allocator > const, int> > >::_M_get_insert_unique_pos(std::__cxx11::basic_string, std::allocator > const&)@Base" 0.1.6 + (c++)"std::_Rb_tree, std::allocator >, std::pair, std::allocator > const, int>, std::_Select1st, std::allocator > const, int> >, std::less, std::allocator > >, std::allocator, std::allocator > const, int> > >::find(std::__cxx11::basic_string, std::allocator > const&)@Base" 0.1.6 + (c++)"std::_Rb_tree, std::allocator >, std::pair, std::allocator > const, int>, std::_Select1st, std::allocator > const, int> >, std::less, std::allocator > >, std::allocator, std::allocator > const, int> > >::_M_erase(std::_Rb_tree_node, std::allocator > const, int> >*)@Base" 0.1.6 + (c++)"void std::__make_heap<__gnu_cxx::__normal_iterator, std::allocator >, int>*, std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > >, __gnu_cxx::__ops::_Iter_comp_iter >(__gnu_cxx::__normal_iterator, std::allocator >, int>*, std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > >, __gnu_cxx::__normal_iterator, std::allocator >, int>*, std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > >, __gnu_cxx::__ops::_Iter_comp_iter)@Base" 0.1.6 + (c++)"void std::__adjust_heap<__gnu_cxx::__normal_iterator, std::allocator >, int>*, std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > >, int, std::pair, std::allocator >, int>, __gnu_cxx::__ops::_Iter_comp_iter >(__gnu_cxx::__normal_iterator, std::allocator >, int>*, std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > >, int, int, std::pair, std::allocator >, int>, __gnu_cxx::__ops::_Iter_comp_iter)@Base" 0.1.6 + (c++)"void std::__insertion_sort<__gnu_cxx::__normal_iterator, std::allocator >, int>*, std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > >, __gnu_cxx::__ops::_Iter_comp_iter >(__gnu_cxx::__normal_iterator, std::allocator >, int>*, std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > >, __gnu_cxx::__normal_iterator, std::allocator >, int>*, std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > >, __gnu_cxx::__ops::_Iter_comp_iter)@Base" 0.1.6 + (c++)"void std::__introsort_loop<__gnu_cxx::__normal_iterator, std::allocator >, int>*, std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > >, int, __gnu_cxx::__ops::_Iter_comp_iter >(__gnu_cxx::__normal_iterator, std::allocator >, int>*, std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > >, __gnu_cxx::__normal_iterator, std::allocator >, int>*, std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > >, int, __gnu_cxx::__ops::_Iter_comp_iter)@Base" 0.1.6 + (c++)"void std::__unguarded_linear_insert<__gnu_cxx::__normal_iterator, std::allocator >, int>*, std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > >, __gnu_cxx::__ops::_Val_comp_iter >(__gnu_cxx::__normal_iterator, std::allocator >, int>*, std::vector, std::allocator >, int>, std::allocator, std::allocator >, int> > > >, __gnu_cxx::__ops::_Val_comp_iter)@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 +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 +Forwarded: mailto:Uditha Atukorala +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 +.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=] +.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= +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 +.SH AUTHOR +Uditha Atukorala +.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 , where is the value of +# the FILE_VERSION_FILTER tag, and 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 , where +# is the value of the INPUT_FILTER tag, and 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 +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +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 + + +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 +#include + + +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 list_data; + std::vector 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::sort_encapsulated_header() { + + std::vector 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 +#include +#include +#include + + +namespace icap { + + class Header { + public: + + /* headers data type */ + typedef std::map headers_t; + + /* headers iterator type */ + typedef headers_t::iterator headers_index_t; + + /* encapsulated header type */ + typedef std::map encapsulated_header_t; + + /* encapsulated header iterator type */ + typedef encapsulated_header_t::iterator encapsulated_header_index_t; + + /* encapsulated header data type */ + typedef std::pair 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 { + 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 + * + *
+		*   e.g.
+		*   Host: icap-server.net
+		*   Encapsulated: req-hdr=0, null-body=170
+		*   [key]: [value]
+		*   
+ * + * @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. + * + *
+		*   e.g.
+		*   Encapsulated: req-hdr=0, req-body=412
+		*   Encapsulated: req-hdr=0, res-hdr=822, res-body=1655
+		*   Encapsulated: [header_value]
+		*   
+ * + * @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 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 + + +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 data; + + _raw_data = raw_data; + data = util::split( raw_data, "\r\n" ); + + if ( data.size() > 0 ) { + + std::vector header_data; + std::vector 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 +#include + + +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 + +#include +#include + + +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 +#include +#include +#include + + +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 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 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 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 split( const std::string &str, const std::string &delimiter ) throw() { + + std::vector 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( 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( 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 sorted_encaps_header; + std::vector::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 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 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 + +#include +#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 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 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 + * 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 + +#ifndef WIN32 + #include // For data types + #include // For socket(), connect(), send(), and recv() + #include // For gethostbyname() + #include // For inet_addr() + #include // For close() +#endif + +#include // For errno +#include // For strerror +#include // 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 &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; isock, &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; isock == 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 + * 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 // For string +#include // For exception class +#include // For vectors + +#ifdef WIN32 + #include // For socket(), connect(), send(), and recv() + typedef int socklen_t; + typedef char raw_type; // Type used for raw data on this platform +#else + #include // 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 &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 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 + + +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 +#include +#include +#include + + +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(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 +#include + + +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 +#include + + +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(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 + +#include + + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#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=]" + << 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 + + +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 +#include + +#include "request_handler.h" + + +namespace bitz { + + /* request handlers type */ + typedef std::map 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 +#include + + +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 +#include + + +#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 // For errno +#include // 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 // for exception class +#include // 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 +#include + +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 +#include + +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 +#include +#include + + +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 // pid_t, fork() etc. +#include // 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 +#include + + +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 _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 +#include + + +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 +#include +#include + + +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 +#include + + +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 +#include + + +namespace bitz { + + namespace util { + + /** + * Convert a number into a string + * + * @param number number to be converted + * @return converted string + */ + template 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 +#include + + +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 + +#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 + +#include +#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 +} + -- cgit v1.2.3