├── AUTHORS ├── COPYING ├── INSTALL ├── Makefile.am ├── NEWS ├── README.md ├── config ├── ac_cxx_gnucxx_hashmap.m4 ├── ac_cxx_have_ext_hash_map.m4 ├── ac_cxx_namespaces.m4 ├── ac_cxx_stlport_hashmap.m4 ├── ax_boost_base.m4 ├── ax_boost_header.m4 ├── ax_boost_lib.m4 ├── ax_boost_prefix.m4 ├── ax_boost_regex.m4 ├── ax_boost_thread.m4 ├── ax_check_compiler_flags.m4 ├── ax_check_cppunit.m4 ├── ax_check_dmalloc.m4 ├── ax_check_fastcgi.m4 ├── ax_check_log4cxx.m4 └── cppunit.m4 ├── configure.in ├── daemon-arc.png ├── debian ├── changelog ├── compat ├── control ├── fastcgi-daemon2-init.files ├── fastcgi-daemon2-init.postinst ├── fastcgi-daemon2-init.postrm ├── fastcgi-daemon2.files ├── libfastcgi-daemon2-dev.files ├── libfastcgi-daemon2.files ├── libfastcgi2-filelogger.files ├── libfastcgi2-statistics.files ├── libfastcgi2-syslog.files └── rules ├── doc ├── daemon-arc-en.png └── en │ ├── API. Application development.md │ ├── Class Component.md │ ├── Class ComponentContext.md │ ├── Class Config.md │ ├── Class Cookie.md │ ├── Class DataBuffer.md │ ├── Class Handler.md │ ├── Class HandlerContext.md │ ├── Class Logger.md │ ├── Class Request.md │ ├── Class SegmentIterator.md │ ├── Introduction.md │ ├── Overview.md │ ├── Quick start guide.md │ └── Setup.md ├── example ├── Makefile.am ├── example.cpp └── fastcgi.conf ├── extra ├── fastcgi-daemon2 └── fastcgistart2.sh ├── fastcgi-daemon2-bf.spec ├── file-logger ├── Makefile.am ├── file_logger.cpp └── file_logger.h ├── include ├── Makefile.am ├── details │ ├── Makefile.am │ ├── component_context.h │ ├── componentset.h │ ├── config.h │ ├── data_buffer_impl.h │ ├── functors.h │ ├── globals.h │ ├── handler_context.h │ ├── handlerset.h │ ├── loader.h │ ├── parser.h │ ├── range.h │ ├── request_cache.h │ ├── request_filter.h │ ├── request_thread_pool.h │ ├── requestimpl.h │ ├── response_time_statistics.h │ ├── server.h │ ├── string_buffer.h │ ├── thread_pool.h │ └── xml.h └── fastcgi2 │ ├── Makefile.am │ ├── component.h │ ├── component_factory.h │ ├── config.h │ ├── cookie.h │ ├── data_buffer.h │ ├── except.h │ ├── handler.h │ ├── helpers.h │ ├── logger.h │ ├── request.h │ ├── request_io_stream.h │ ├── stream.h │ └── util.h ├── library ├── Makefile.am ├── component.cpp ├── component_context.cpp ├── component_factory.cpp ├── componentset.cpp ├── config.cpp ├── cookie.cpp ├── data_buffer.cpp ├── except.cpp ├── globals.cpp ├── handler.cpp ├── handlerset.cpp ├── loader.cpp ├── logger.cpp ├── parser.cpp ├── request.cpp ├── request_filter.cpp ├── request_thread_pool.cpp ├── requestimpl.cpp ├── response_time_statistics.cpp ├── server.cpp ├── stream.cpp ├── string_buffer.cpp ├── util.cpp └── xml.cpp ├── logging ├── Makefile.am ├── logger.cpp └── logger.h ├── main ├── Makefile.am ├── endpoint.cpp ├── endpoint.h ├── fastcgi.conf.example ├── fcgi_request.cpp ├── fcgi_request.h ├── fcgi_server.cpp ├── fcgi_server.h └── main.cpp ├── statistics ├── Makefile.am ├── response_time_handler.cpp └── response_time_handler.h ├── syslog ├── Makefile.am ├── syslog-logger.cpp └── syslog-logger.h └── tests ├── Makefile.am ├── main.cpp ├── multipart-test-n.dat ├── multipart-test-rn.dat ├── multipart-test-rn2.dat ├── test.conf ├── test_config.cpp └── test_request.cpp /AUTHORS: -------------------------------------------------------------------------------- 1 | Ilya Golubtsov 2 | Vasily Kiritsev 3 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | ACLOCAL_AMFLAGS = -I config 2 | AUTOMAKE_OPTIONS = 1.9 foreign 3 | 4 | SUBDIRS = include library main example syslog statistics file-logger 5 | 6 | if HAVE_CPPUNIT 7 | SUBDIRS += tests 8 | endif 9 | 10 | EXTRA_DIST = autogen.sh config/settings.h.in config/ac_cxx_gnucxx_hashmap.m4 \ 11 | config/ac_cxx_have_ext_hash_map.m4 config/ac_cxx_namespaces.m4 \ 12 | config/ac_cxx_stlport_hashmap.m4 config/ax_check_cppunit.m4 \ 13 | config/ax_check_dmalloc.m4 config/ax_check_fastcgi.m4 \ 14 | ax_check_compiler_flags.m4 config/cppunit.m4 extra/fastcgi-daemon2 \ 15 | extra/fastcgistart2.sh 16 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmovsesjan/Fastcgi-Daemon/a6f2043403d07e6e1771a1bf2368d209b8868d81/NEWS -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Fastcgi Daemon - Yandex's opensource framework for highload FastCGI applications on C++ design. 2 | 3 | [Документация](https://github.com/lmovsesjan/Fastcgi-Daemon/wiki/Документация) 4 | 5 | [Documentation](https://github.com/lmovsesjan/Fastcgi-Daemon/blob/master/doc/en/Introduction.md) 6 | -------------------------------------------------------------------------------- /config/ac_cxx_gnucxx_hashmap.m4: -------------------------------------------------------------------------------- 1 | ##### http://autoconf-archive.cryp.to/ac_cxx_gnucxx_hashmap.html 2 | # 3 | # SYNOPSIS 4 | # 5 | # AC_CXX_GNUCXX_HASHMAP 6 | # 7 | # DESCRIPTION 8 | # 9 | # Test for the presence of GCC's hashmap STL extension. 10 | # 11 | # LAST MODIFICATION 12 | # 13 | # 2005-07-18 14 | # 15 | # COPYLEFT 16 | # 17 | # Copyright (c) 2005 Patrick Mauritz 18 | # 19 | # Copying and distribution of this file, with or without 20 | # modification, are permitted in any medium without royalty provided 21 | # the copyright notice and this notice are preserved. 22 | 23 | AC_DEFUN([AC_CXX_GNUCXX_HASHMAP],[ 24 | AC_CACHE_CHECK(whether the compiler supports __gnu_cxx::hash_map, 25 | ac_cv_cxx_gnucxx_hashmap, 26 | [AC_LANG_SAVE 27 | AC_LANG_CPLUSPLUS 28 | AC_TRY_COMPILE([#include 29 | using __gnu_cxx::hash_map;], 30 | [], 31 | ac_cv_cxx_gnucxx_hashmap=yes, ac_cv_cxx_gnucxx_hashmap=no) 32 | AC_LANG_RESTORE 33 | ]) 34 | if test "$ac_cv_cxx_gnucxx_hashmap" = yes; then 35 | AC_DEFINE(HAVE_GNUCXX_HASHMAP,,[define if the compiler supports __gnu_cxx::hash_map]) 36 | fi 37 | ]) 38 | -------------------------------------------------------------------------------- /config/ac_cxx_have_ext_hash_map.m4: -------------------------------------------------------------------------------- 1 | ##### http://autoconf-archive.cryp.to/ac_cxx_have_ext_hash_map.html 2 | # 3 | # SYNOPSIS 4 | # 5 | # AC_CXX_HAVE_EXT_HASH_MAP 6 | # 7 | # DESCRIPTION 8 | # 9 | # Check if the compiler has ext/hash_map Eg: 10 | # 11 | # #if defined(HAVE_EXT_HASH_MAP) 12 | # #include 13 | # #else 14 | # #if defined(HAVE_STL) 15 | # #include 16 | # #else 17 | # # Can't find hash_map header ! 18 | # #endif 19 | # #endif 20 | # 21 | # This file is Alain BARBET's AC_CXX_HAVE_EXT_HASH_SET 1.1 with 22 | # s/set/map/g :) 23 | # 24 | # LAST MODIFICATION 25 | # 26 | # 2002-09-25 27 | # 28 | # COPYLEFT 29 | # 30 | # Copyright (c) 2002 Perceval ANICHINI 31 | # 32 | # This program is free software; you can redistribute it and/or 33 | # modify it under the terms of the GNU General Public License as 34 | # published by the Free Software Foundation; either version 2 of the 35 | # License, or (at your option) any later version. 36 | # 37 | # This program is distributed in the hope that it will be useful, but 38 | # WITHOUT ANY WARRANTY; without even the implied warranty of 39 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 40 | # General Public License for more details. 41 | # 42 | # You should have received a copy of the GNU General Public License 43 | # along with this program; if not, write to the Free Software 44 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 45 | # 02111-1307, USA. 46 | # 47 | # As a special exception, the respective Autoconf Macro's copyright 48 | # owner gives unlimited permission to copy, distribute and modify the 49 | # configure scripts that are the output of Autoconf when processing 50 | # the Macro. You need not follow the terms of the GNU General Public 51 | # License when using or distributing such scripts, even though 52 | # portions of the text of the Macro appear in them. The GNU General 53 | # Public License (GPL) does govern all other use of the material that 54 | # constitutes the Autoconf Macro. 55 | # 56 | # This special exception to the GPL applies to versions of the 57 | # Autoconf Macro released by the Autoconf Macro Archive. When you 58 | # make and distribute a modified version of the Autoconf Macro, you 59 | # may extend this special exception to the GPL to apply to your 60 | # modified version as well. 61 | 62 | AC_DEFUN([AC_CXX_HAVE_EXT_HASH_MAP], 63 | [AC_CACHE_CHECK(whether the compiler has ext/hash_map, 64 | ac_cv_cxx_have_ext_hash_map, 65 | [AC_REQUIRE([AC_CXX_NAMESPACES]) 66 | AC_LANG_SAVE 67 | AC_LANG_CPLUSPLUS 68 | AC_TRY_COMPILE([#include 69 | #ifdef HAVE_NAMESPACES 70 | using namespace std; 71 | #endif],[hash_map t; return 0;], 72 | ac_cv_cxx_have_ext_hash_map=yes, ac_cv_cxx_have_ext_hash_map=no) 73 | AC_LANG_RESTORE 74 | ]) 75 | if test "$ac_cv_cxx_have_ext_hash_map" = yes; then 76 | AC_DEFINE(HAVE_EXT_HASH_MAP,,[define if the compiler has ext/hash_map]) 77 | fi 78 | ]) 79 | -------------------------------------------------------------------------------- /config/ac_cxx_namespaces.m4: -------------------------------------------------------------------------------- 1 | ##### http://autoconf-archive.cryp.to/ac_cxx_namespaces.html 2 | # 3 | # SYNOPSIS 4 | # 5 | # AC_CXX_NAMESPACES 6 | # 7 | # DESCRIPTION 8 | # 9 | # If the compiler can prevent names clashes using namespaces, define 10 | # HAVE_NAMESPACES. 11 | # 12 | # LAST MODIFICATION 13 | # 14 | # 2004-02-04 15 | # 16 | # COPYLEFT 17 | # 18 | # Copyright (c) 2004 Todd Veldhuizen 19 | # Copyright (c) 2004 Luc Maisonobe 20 | # 21 | # Copying and distribution of this file, with or without 22 | # modification, are permitted in any medium without royalty provided 23 | # the copyright notice and this notice are preserved. 24 | 25 | AC_DEFUN([AC_CXX_NAMESPACES], 26 | [AC_CACHE_CHECK(whether the compiler implements namespaces, 27 | ac_cv_cxx_namespaces, 28 | [AC_LANG_SAVE 29 | AC_LANG_CPLUSPLUS 30 | AC_TRY_COMPILE([namespace Outer { namespace Inner { int i = 0; }}], 31 | [using namespace Outer::Inner; return i;], 32 | ac_cv_cxx_namespaces=yes, ac_cv_cxx_namespaces=no) 33 | AC_LANG_RESTORE 34 | ]) 35 | if test "$ac_cv_cxx_namespaces" = yes; then 36 | AC_DEFINE(HAVE_NAMESPACES,,[define if the compiler implements namespaces]) 37 | fi 38 | ]) 39 | -------------------------------------------------------------------------------- /config/ac_cxx_stlport_hashmap.m4: -------------------------------------------------------------------------------- 1 | ##### http://autoconf-archive.cryp.to/ac_cxx_stlport_hashmap.html 2 | # 3 | # SYNOPSIS 4 | # 5 | # AC_CXX_STLPORT_HASHMAP 6 | # 7 | # DESCRIPTION 8 | # 9 | # Test for the presence of STLport's hashmap extension. 10 | # 11 | # LAST MODIFICATION 12 | # 13 | # 2005-07-18 14 | # 15 | # COPYLEFT 16 | # 17 | # Copyright (c) 2005 Patrick Mauritz 18 | # 19 | # Copying and distribution of this file, with or without 20 | # modification, are permitted in any medium without royalty provided 21 | # the copyright notice and this notice are preserved. 22 | 23 | AC_DEFUN([AC_CXX_STLPORT_HASHMAP],[ 24 | AC_CACHE_CHECK(whether the compiler supports std::hash_map, 25 | ac_cv_cxx_stlport_hashmap, 26 | [AC_LANG_SAVE 27 | AC_LANG_CPLUSPLUS 28 | AC_TRY_COMPILE([#include 29 | using std::hash_map;], 30 | [], 31 | ac_cv_cxx_stlport_hashmap=yes, ac_cv_cxx_stlport_hashmap=no) 32 | AC_LANG_RESTORE 33 | ]) 34 | if test "$ac_cv_cxx_stlport_hashmap" = yes; then 35 | AC_DEFINE(HAVE_STLPORT_HASHMAP,,[define if the compiler supports std::hash_map]) 36 | fi 37 | ]) 38 | -------------------------------------------------------------------------------- /config/ax_boost_header.m4: -------------------------------------------------------------------------------- 1 | AC_DEFUN([AX_BOOST_HEADER], 2 | [ 3 | ax_header_found="yes" 4 | AC_REQUIRE([AX_BOOST_PREFIX]) 5 | 6 | ax_boost_header_stored_cppflags="$CPPFLAGS" 7 | CPPFLAGS="$ax_boost_header_stored_cppflags $BOOST_CPPFLAGS" 8 | AC_CHECK_HEADER([boost/$1], [], [ax_header_found="no"]) 9 | CPPFLAGS="$ax_boost_header_stored_cppflags" 10 | if test "f$ax_header_found" = "fyes"; then 11 | ifelse([$2], , :, [$2]) 12 | else 13 | ifelse([$3], , :, [$3]) 14 | fi 15 | ]) 16 | 17 | -------------------------------------------------------------------------------- /config/ax_boost_lib.m4: -------------------------------------------------------------------------------- 1 | AC_DEFUN([AX_BOOST_LIB], 2 | [ 3 | AC_REQUIRE([AX_BOOST_PREFIX]) 4 | AC_MSG_CHECKING([for $2]) 5 | ax_check=$2 6 | ax_library="$ax_check" 7 | ax_value=`echo $CPPFLAGS $CXXFLAGS | grep -- -pthread` 8 | if test "f$ax_value" != "f"; then 9 | ax_check="$ax_check-mt" 10 | fi 11 | if test -f "$ax_boost_prefix/lib/lib$ax_check.so"; then 12 | ax_library="$ax_check" 13 | fi 14 | ax_value=`echo $CPPFLAGS $CXXFLAGS | grep -- -g` 15 | if test "f$ax_value" != "f"; then 16 | ax_check="$ax_check-d" 17 | fi 18 | if test -f "$ax_boost_prefix/lib/lib$ax_check.so"; then 19 | ax_library="$ax_check" 20 | fi 21 | if test -f "$ac_boost_lib_path/lib$ax_check.so"; then 22 | ax_library="$ax_check" 23 | fi 24 | $1="$ax_library" 25 | AC_MSG_RESULT([$ax_library]) 26 | ]) 27 | 28 | -------------------------------------------------------------------------------- /config/ax_boost_prefix.m4: -------------------------------------------------------------------------------- 1 | AC_DEFUN([_AX_CHECK_BOOST_IN], 2 | [ 3 | ax_prefix=$1 4 | AC_MSG_CHECKING([whether boost is installed in $1]) 5 | ax_have_boost_in="yes" 6 | if test ! -d "$ax_prefix/include/boost"; then 7 | ax_have_boost_in="no" 8 | fi 9 | if test ! -d "$ax_prefix/lib"; then 10 | ax_have_boost_in="no" 11 | fi 12 | AC_MSG_RESULT([$ax_have_boost_in]) 13 | if test "f$ax_have_boost_in" = "fyes"; then 14 | ifelse([$2], , :, [$2]) 15 | else 16 | ifelse([$3], , :, [$3]) 17 | fi 18 | ]) 19 | 20 | AC_DEFUN([AX_BOOST_PREFIX], 21 | [ 22 | ax_boost_prefix="" 23 | AC_ARG_WITH([boost-prefix], 24 | AS_HELP_STRING(--with-boost-prefix, specifies boost installation), 25 | [ 26 | if test "f$withval" != "f"; then 27 | ax_boost_prefix="$withval" 28 | fi 29 | ]) 30 | if test "f$ax_boost_prefix" != "f"; then 31 | _AX_CHECK_BOOST_IN([$ax_boost_prefix], [], [ax_boost_prefix=""]) 32 | else 33 | for i in /usr/local /usr; do 34 | _AX_CHECK_BOOST_IN([$i], [ax_boost_prefix="$i"], []) 35 | done; 36 | fi 37 | 38 | if test "f$ax_boost_prefix" != "f"; then 39 | AC_SUBST([BOOST_LDFLAGS], ["-I$ax_boost_prefix/lib"]) 40 | AC_SUBST([BOOST_CPPFLAGS], ["-I$ax_boost_prefix/include"]) 41 | ifelse([$1], , :, [$1]) 42 | else 43 | ifelse([$2], , :, [$2]) 44 | fi 45 | ]) 46 | 47 | -------------------------------------------------------------------------------- /config/ax_boost_regex.m4: -------------------------------------------------------------------------------- 1 | AC_DEFUN([AX_BOOST_REGEX], 2 | [ 3 | ax_boost_regex_stored_ldflags="$LDFLAGS" 4 | 5 | AC_REQUIRE([AX_BOOST_PREFIX]) 6 | AX_BOOST_LIB([ax_boost_regex_lib], [boost_regex]) 7 | 8 | LDFLAGS="$ax_boost_regex_stored_ldflags $BOOST_LDFLAGS -l$ax_boost_regex_lib" 9 | 10 | ax_have_boost_regex="yes" 11 | AX_BOOST_HEADER([regex.hpp], [], [ax_have_boost_regex="no"]) 12 | 13 | AC_MSG_CHECKING([trying to link with boost::regex]) 14 | AC_LINK_IFELSE( 15 | [ AC_LANG_PROGRAM([#include ], [ ;]) ], 16 | [ AC_MSG_RESULT(yes) ], 17 | [ AC_MSG_RESULT(no); ax_have_boost_regex="no" ]) 18 | 19 | LDFLAGS="$ax_boost_regex_stored_ldflags" 20 | 21 | if test "f$ax_have_boost_regex" = "fyes"; then 22 | ifelse([$1], , :, [$1]) 23 | AC_SUBST([BOOST_REGEX_LDFLAGS], ["-l$ax_boost_regex_lib"]) 24 | else 25 | ifelse([$2], , :, [$2]) 26 | fi 27 | ]) 28 | -------------------------------------------------------------------------------- /config/ax_boost_thread.m4: -------------------------------------------------------------------------------- 1 | AC_DEFUN([AX_BOOST_THREAD], 2 | [ 3 | ax_boost_thread_stored_ldflags="$LDFLAGS" 4 | 5 | AC_REQUIRE([AX_BOOST_PREFIX]) 6 | AX_BOOST_LIB([ax_boost_thread_lib], [boost_thread]) 7 | 8 | LDFLAGS="$ax_boost_thread_stored_ldflags $BOOST_LDFLAGS -l$ax_boost_thread_lib" 9 | 10 | ax_have_boost_thread="yes" 11 | AX_BOOST_HEADER([thread.hpp], [], [ax_have_boost_thread="no"]) 12 | AX_BOOST_HEADER([thread/mutex.hpp], [], [ax_have_boost_thread="no"]) 13 | AX_BOOST_HEADER([thread/condition.hpp], [], [ax_have_boost_thread="no"]) 14 | AX_BOOST_HEADER([thread/thread.hpp], [], [ax_have_boost_thread="no"]) 15 | 16 | LDFLAGS="$ax_boost_thread_stored_ldflags" 17 | 18 | if test "f$ax_have_boost_thread" = "fyes"; then 19 | ifelse([$1], , :, [$1]) 20 | AC_SUBST([BOOST_THREAD_LDFLAGS], ["-l$ax_boost_thread_lib"]) 21 | else 22 | ifelse([$2], , :, [$2]) 23 | fi 24 | ]) 25 | -------------------------------------------------------------------------------- /config/ax_check_compiler_flags.m4: -------------------------------------------------------------------------------- 1 | AC_DEFUN([AX_CHECK_COMPILER_FLAGS], 2 | [AC_PREREQ(2.59) dnl for _AC_LANG_PREFIX 3 | AC_MSG_CHECKING([whether _AC_LANG compiler accepts $1]) 4 | dnl Some hackery here since AC_CACHE_VAL can't handle a non-literal varname: 5 | AS_LITERAL_IF([$1], 6 | [AC_CACHE_VAL(AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1), [ 7 | ax_save_FLAGS=$[]_AC_LANG_PREFIX[]FLAGS 8 | _AC_LANG_PREFIX[]FLAGS="$1" 9 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], 10 | AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1)=yes, 11 | AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1)=no) 12 | _AC_LANG_PREFIX[]FLAGS=$ax_save_FLAGS])], 13 | [ax_save_FLAGS=$[]_AC_LANG_PREFIX[]FLAGS 14 | _AC_LANG_PREFIX[]FLAGS="$1" 15 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], 16 | eval AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1)=yes, 17 | eval AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1)=no) 18 | _AC_LANG_PREFIX[]FLAGS=$ax_save_FLAGS]) 19 | eval ax_check_compiler_flags=$AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1) 20 | AC_MSG_RESULT($ax_check_compiler_flags) 21 | if test "x$ax_check_compiler_flags" = xyes; then 22 | m4_default([$2], :) 23 | else 24 | m4_default([$3], :) 25 | fi 26 | ])dnl AX_CHECK_COMPILER_FLAGS 27 | -------------------------------------------------------------------------------- /config/ax_check_cppunit.m4: -------------------------------------------------------------------------------- 1 | AC_DEFUN([AX_CHECK_CPPUNIT], 2 | [ 3 | AC_REQUIRE([AM_PATH_CPPUNIT]) 4 | 5 | ac_have_cppunit="no" 6 | ac_cppunit_found="no" 7 | AC_ARG_ENABLE(cppunit, 8 | AS_HELP_STRING(--enable-cppunit,enables cppunit tests compilation), 9 | [ 10 | if test "f$enableval" = "fyes"; then 11 | ac_have_cppunit="yes" 12 | fi 13 | ]) 14 | 15 | if test "f$ac_have_cppunit" = "fyes"; then 16 | ac_cppunit_found="yes" 17 | 18 | AC_LANG_SAVE 19 | AC_LANG_CPLUSPLUS 20 | AM_PATH_CPPUNIT([$1], [], [ac_cppunit_found="no"]) 21 | 22 | ac_stored_libs=$LIBS 23 | ac_stored_cppflags=$CPPFLAGS 24 | LIBS="$ac_stored_libs $CPPUNIT_LIBS" 25 | CPPFLAGS="$ac_stored_cppflags $CPPUNIT_CFLAGS" 26 | 27 | AC_MSG_CHECKING([linkage with cppunit]) 28 | AC_LINK_IFELSE( 29 | [AC_LANG_PROGRAM([#include ], [CppUnit::TextUi::TestRunner r;])], 30 | [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]); ac_cppunit_found="no"]) 31 | 32 | CPPFLAGS=$ac_stored_cppflags 33 | LIBS=$ac_stored_libs 34 | 35 | AC_LANG_RESTORE 36 | if test "f$ac_cppunit_found" = "fyes"; then 37 | ifelse([$2], , :, [$2]) 38 | AC_DEFINE([HAVE_CPPUNIT], 1, [Define to 1 if you want to compile cppunit tests]) 39 | else 40 | ifelse([$3], , :, [$3]) 41 | fi 42 | fi 43 | AM_CONDITIONAL(HAVE_CPPUNIT, [test "f$ac_cppunit_found" = "fyes"]) 44 | ]) 45 | -------------------------------------------------------------------------------- /config/ax_check_dmalloc.m4: -------------------------------------------------------------------------------- 1 | AC_DEFUN([AX_CHECK_DMALLOC], 2 | [ 3 | ac_have_dmalloc="no" 4 | ac_dmalloc_found="no" 5 | 6 | AC_ARG_ENABLE(dmalloc, 7 | AS_HELP_STRING(--enable-dmalloc,enables dmalloc support), 8 | [ 9 | if test "f$enableval" = "fyes"; then 10 | ac_have_dmalloc="yes"; 11 | fi 12 | ]) 13 | 14 | if test "f$ac_have_dmalloc" = "fyes"; then 15 | 16 | AC_LANG_SAVE 17 | AC_LANG_CPLUSPLUS 18 | AC_CHECK_HEADER([dmalloc.h], [], [ac_dmalloc_found="no"]) 19 | AC_CHECK_LIB(dmallocthcxx, dmalloc_shutdown, [], [ac_dmalloc_found="no"]) 20 | AC_LANG_RESTORE 21 | 22 | if test "f$ac_dmalloc_found" = "fyes"; then 23 | ifelse([$1], , :, [$1]) 24 | AC_SUBST([dmalloc_LIBS], [-ldmallocthcxx]) 25 | AC_SUBST([dmalloc_CFLAGS], [-DDMALLOC_FUNC_CHECK]) 26 | AC_DEFINE(HAVE_DMALLOC_H, 1, [Define to 1 if you have the header file]) 27 | else 28 | ifelse([$2], , :, [$2]) 29 | fi 30 | fi 31 | AM_CONDITIONAL([HAVE_DMALLOC], [ test "f$ac_dmalloc_found" = "fyes" ]) 32 | ]) 33 | -------------------------------------------------------------------------------- /config/ax_check_fastcgi.m4: -------------------------------------------------------------------------------- 1 | AC_DEFUN([AX_CHECK_FASTCGI], 2 | [ 3 | ac_have_fcgi="yes" 4 | 5 | ac_stored_libs=$LIBS 6 | ac_stored_cppflags="$CPPFLAGS" 7 | 8 | AC_CHECK_LIB(fcgi, FCGX_Accept_r, [], [ac_have_fcgi="no"]) 9 | 10 | AC_LANG_SAVE 11 | AC_LANG_CPLUSPLUS 12 | LIBS="$ac_stored_libs -lfcgi -lfcgi++" 13 | 14 | AC_MSG_CHECKING([linkage with libfcgi++]) 15 | AC_LINK_IFELSE( 16 | [AC_LANG_PROGRAM([#include ], [[char buf[256]; fcgi_streambuf stbuf(buf, sizeof(buf));]])], 17 | [AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no); ac_have_fcgi="no"]) 18 | 19 | LIBS=$ac_stored_libs 20 | AC_LANG_RESTORE 21 | 22 | if test "f$ac_have_fcgi" = "fyes"; then 23 | ifelse([$1], , :, [$1]) 24 | else 25 | ifelse([$2], , :, [$2]) 26 | fi 27 | ]) 28 | -------------------------------------------------------------------------------- /config/ax_check_log4cxx.m4: -------------------------------------------------------------------------------- 1 | AC_DEFUN([AX_CHECK_LOG4CXX], 2 | [ 3 | ac_have_log4cxx="no" 4 | ac_log4cxx_found="no" 5 | AC_ARG_ENABLE(log4cxx, 6 | AS_HELP_STRING(--enable-cppunit,enables compilation of log4cxx logger), 7 | [ 8 | if test "f$enableval" = "fyes"; then 9 | ac_have_log4cxx="yes" 10 | fi 11 | ]) 12 | 13 | if test "f$ac_have_log4cxx" = "fyes"; then 14 | ac_log4cxx_found="yes" 15 | 16 | AC_LANG_SAVE 17 | AC_LANG_CPLUSPLUS 18 | AC_CHECK_HEADER([log4cxx/logger.h], [], [ac_log4cxx_found="no"]) 19 | 20 | ac_stored_libs=$LIBS 21 | LIBS="$ac_stored_libs -llog4cxx" 22 | 23 | AC_MSG_CHECKING([linkage with log4cxx]) 24 | AC_LINK_IFELSE( 25 | [AC_LANG_PROGRAM([#include ], [log4cxx::LoggerPtr l = log4cxx::Logger::getRootLogger();])], 26 | [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]); ac_log4cxx_found="no"]) 27 | 28 | LIBS=$ac_stored_libs 29 | AC_LANG_RESTORE 30 | 31 | if test "f$ac_log4cxx_found" = "fyes"; then 32 | ifelse([$1], , :, [$1]) 33 | AC_DEFINE([HAVE_LOG4CXX], 1, [Define to 1 if you want to use log4cxx logger]) 34 | else 35 | ifelse([$2], , :, [$2]) 36 | fi 37 | fi 38 | AM_CONDITIONAL(HAVE_LOG4CXX, [test "f$ac_log4cxx_found" = "fyes"]) 39 | ]) 40 | -------------------------------------------------------------------------------- /config/cppunit.m4: -------------------------------------------------------------------------------- 1 | dnl 2 | dnl AM_PATH_CPPUNIT(MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) 3 | dnl 4 | AC_DEFUN([AM_PATH_CPPUNIT], 5 | [ 6 | 7 | AC_ARG_WITH(cppunit-prefix,[ --with-cppunit-prefix=PFX Prefix where CppUnit is installed (optional)], 8 | cppunit_config_prefix="$withval", cppunit_config_prefix="") 9 | AC_ARG_WITH(cppunit-exec-prefix,[ --with-cppunit-exec-prefix=PFX Exec prefix where CppUnit is installed (optional)], 10 | cppunit_config_exec_prefix="$withval", cppunit_config_exec_prefix="") 11 | 12 | if test x$cppunit_config_exec_prefix != x ; then 13 | cppunit_config_args="$cppunit_config_args --exec-prefix=$cppunit_config_exec_prefix" 14 | if test x${CPPUNIT_CONFIG+set} != xset ; then 15 | CPPUNIT_CONFIG=$cppunit_config_exec_prefix/bin/cppunit-config 16 | fi 17 | fi 18 | if test x$cppunit_config_prefix != x ; then 19 | cppunit_config_args="$cppunit_config_args --prefix=$cppunit_config_prefix" 20 | if test x${CPPUNIT_CONFIG+set} != xset ; then 21 | CPPUNIT_CONFIG=$cppunit_config_prefix/bin/cppunit-config 22 | fi 23 | fi 24 | 25 | AC_PATH_PROG(CPPUNIT_CONFIG, cppunit-config, no) 26 | cppunit_version_min=$1 27 | 28 | AC_MSG_CHECKING(for Cppunit - version >= $cppunit_version_min) 29 | no_cppunit="" 30 | if test "$CPPUNIT_CONFIG" = "no" ; then 31 | AC_MSG_RESULT(no) 32 | no_cppunit=yes 33 | else 34 | CPPUNIT_CFLAGS=`$CPPUNIT_CONFIG --cflags` 35 | CPPUNIT_LIBS=`$CPPUNIT_CONFIG --libs` 36 | cppunit_version=`$CPPUNIT_CONFIG --version` 37 | 38 | cppunit_major_version=`echo $cppunit_version | \ 39 | sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` 40 | cppunit_minor_version=`echo $cppunit_version | \ 41 | sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` 42 | cppunit_micro_version=`echo $cppunit_version | \ 43 | sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` 44 | 45 | cppunit_major_min=`echo $cppunit_version_min | \ 46 | sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` 47 | if test "x${cppunit_major_min}" = "x" ; then 48 | cppunit_major_min=0 49 | fi 50 | 51 | cppunit_minor_min=`echo $cppunit_version_min | \ 52 | sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` 53 | if test "x${cppunit_minor_min}" = "x" ; then 54 | cppunit_minor_min=0 55 | fi 56 | 57 | cppunit_micro_min=`echo $cppunit_version_min | \ 58 | sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` 59 | if test "x${cppunit_micro_min}" = "x" ; then 60 | cppunit_micro_min=0 61 | fi 62 | 63 | cppunit_version_proper=`expr \ 64 | $cppunit_major_version \> $cppunit_major_min \| \ 65 | $cppunit_major_version \= $cppunit_major_min \& \ 66 | $cppunit_minor_version \> $cppunit_minor_min \| \ 67 | $cppunit_major_version \= $cppunit_major_min \& \ 68 | $cppunit_minor_version \= $cppunit_minor_min \& \ 69 | $cppunit_micro_version \>= $cppunit_micro_min ` 70 | 71 | if test "$cppunit_version_proper" = "1" ; then 72 | AC_MSG_RESULT([$cppunit_major_version.$cppunit_minor_version.$cppunit_micro_version]) 73 | else 74 | AC_MSG_RESULT(no) 75 | no_cppunit=yes 76 | fi 77 | fi 78 | 79 | if test "x$no_cppunit" = x ; then 80 | ifelse([$2], , :, [$2]) 81 | else 82 | CPPUNIT_CFLAGS="" 83 | CPPUNIT_LIBS="" 84 | ifelse([$3], , :, [$3]) 85 | fi 86 | 87 | AC_SUBST(CPPUNIT_CFLAGS) 88 | AC_SUBST(CPPUNIT_LIBS) 89 | ]) 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /configure.in: -------------------------------------------------------------------------------- 1 | AC_INIT([fastcgi2], [2.0-1], [toshik@yandex-team.ru]) 2 | AM_INIT_AUTOMAKE([foreign]) 3 | 4 | AC_CONFIG_MACRO_DIR([config]) 5 | 6 | AC_GNU_SOURCE 7 | AC_CONFIG_HEADERS(config/settings.h) 8 | 9 | AC_PROG_CXX 10 | AC_PROG_CXXCPP 11 | AC_PROG_LIBTOOL 12 | 13 | AC_LANG([C++]) 14 | AM_MAINTAINER_MODE 15 | 16 | PKG_CHECK_MODULES(yandex_platform, [yandex-platform], [], [echo yandex-platform not found]) 17 | 18 | LIBS="$yandex_platform_LIBS" 19 | CPPFLAGS="$yandex_platform_CFLAGS -pthread" 20 | 21 | AC_SYS_LARGEFILE 22 | AC_CXX_GNUCXX_HASHMAP 23 | AC_CXX_STLPORT_HASHMAP 24 | AC_CXX_HAVE_EXT_HASH_MAP 25 | 26 | PKG_CHECK_MODULES(xml, [libxml-2.0], [], 27 | AC_MSG_ERROR([libxml not found])) 28 | 29 | AX_CHECK_FASTCGI([], 30 | AC_MSG_ERROR([libfcgi not found])) 31 | 32 | AX_CHECK_DMALLOC([], 33 | AC_MSG_WARN([dmalloc library not found])) 34 | 35 | AX_CHECK_CPPUNIT([1.10.0], [], 36 | AC_MSG_WARN([cppunit library not found. compilation of tests disabled])) 37 | 38 | have_va_copy="yes" 39 | AC_MSG_CHECKING([trying fo find to find va_copy macro]) 40 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM( 41 | [[#include ]], 42 | [[ va_list args1; va_list args2; va_copy(args1, args2); ]])], 43 | [ have_va_copy="yes" ], 44 | [ have_va_copy="no" ]) 45 | AC_MSG_RESULT([$have_va_copy]) 46 | 47 | have_nonstandard_va_copy="yes" 48 | AC_MSG_CHECKING([trying fo find to find __va_copy macro]) 49 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM( 50 | [[#include ]], 51 | [[ va_list args1; va_list args2; __va_copy(args1, args2); ]])], 52 | [ have_nonstandard_va_copy="yes" ], 53 | [ have_nonstandard_va_copy="no" ]) 54 | AC_MSG_RESULT([$have_nonstandard_va_copy]) 55 | 56 | if test "f$have_va_copy" = "fyes"; then 57 | AC_DEFINE(HAVE_VA_COPY, 1, [define to 1 if you have va_copy macro definition]) 58 | elif test "f$have_nonstandard_va_copy" = "fyes"; then 59 | AC_DEFINE(HAVE_NONSTANDARD_VA_COPY, 1, [define to 1 if you have __va_copy macro definition]) 60 | else 61 | AC_MSG_ERROR([can not find va_copy or similar]) 62 | fi 63 | 64 | AX_BOOST_BASE([1.30]) 65 | AX_BOOST_THREAD 66 | 67 | if test "f$BOOST_THREAD_LDFLAGS" == "f" 68 | then 69 | AC_MSG_ERROR([boost thread lib not found, unable to compile]) 70 | fi 71 | 72 | AX_BOOST_REGEX 73 | if test "f$BOOST_REGEX_LDFLAGS" == "f" 74 | then 75 | AC_MSG_ERROR([boost regex lib not found, unable to compile]) 76 | fi 77 | 78 | for i in -W -Wall -Wextra -fexceptions -frtti -ftemplate-depth-128; do 79 | AX_CHECK_COMPILER_FLAGS([$i], [CXXFLAGS="$CXXFLAGS $i"], []) 80 | done 81 | 82 | LIBS=$stored_libs 83 | 84 | AC_CONFIG_FILES([Makefile include/Makefile include/fastcgi2/Makefile 85 | include/details/Makefile library/Makefile main/Makefile tests/Makefile 86 | example/Makefile syslog/Makefile statistics/Makefile 87 | file-logger/Makefile]) 88 | 89 | AC_OUTPUT 90 | -------------------------------------------------------------------------------- /daemon-arc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmovsesjan/Fastcgi-Daemon/a6f2043403d07e6e1771a1bf2368d209b8868d81/daemon-arc.png -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 4 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: fastcgi-daemon2 2 | Priority: optional 3 | Maintainer: Anton Kortunov 4 | Build-Depends: debhelper (>= 7), 5 | automake, 6 | autotools-dev, 7 | libboost-dev, 8 | libboost-system-dev, 9 | libboost-thread-dev, 10 | libfcgi-dev, 11 | libxml2-dev, 12 | libboost-regex-dev, 13 | libtool, 14 | pkg-config, 15 | autoconf-archive 16 | Standards-Version: 3.8.0 17 | Section: libs 18 | Vcs-Git: git@github.com:lmovsesjan/Fastcgi-Daemon.git 19 | 20 | Package: libfastcgi-daemon2 21 | Section: libs 22 | Architecture: any 23 | Depends: ${shlibs:Depends}, libfcgi0c2 | libfcgi0 | libfcgi0ldbl 24 | Description: fastcgi-daemon is an application server for FastCGI 25 | applications wtiteen in C++. This is the core package. 26 | 27 | Package: libfastcgi-daemon2-dev 28 | Section: libdevel 29 | Architecture: any 30 | Depends: libfastcgi-daemon2 (=${Source-Version}), libboost-regex-dev, libfcgi-dev 31 | Description: fastcgi-daemon is an application server for FastCGI 32 | applications wtiteen in C++. Headers and libraries to develop modules. 33 | 34 | Package: libfastcgi2-syslog 35 | Section: libs 36 | Architecture: any 37 | Depends: ${shlibs:Depends}, libfastcgi-daemon2 (=${Source-Version}) 38 | Description: fastcgi-daemon is an application server for FastCGI 39 | applications wtiteen in C++. Binary to execute server. 40 | 41 | Package: libfastcgi2-filelogger 42 | Section: libs 43 | Architecture: any 44 | Depends: ${shlibs:Depends}, libfastcgi-daemon2 (=${Source-Version}) 45 | Description: fastcgi-daemon is an application server for FastCGI 46 | applications wtiteen in C++. Binary to execute server. 47 | 48 | Package: libfastcgi2-statistics 49 | Section: libs 50 | Architecture: any 51 | Depends: ${shlibs:Depends}, libfastcgi-daemon2 (=${Source-Version}) 52 | Description: fastcgi-daemon is an application server for FastCGI 53 | applications wtiteen in C++. Binary to execute server. 54 | 55 | Package: fastcgi-daemon2 56 | Section: libs 57 | Architecture: any 58 | Depends: ${shlibs:Depends}, libfastcgi-daemon2 (=${Source-Version}) 59 | Description: fastcgi-daemon is an application server for FastCGI 60 | applications wtiteen in C++. Binary to execute server. 61 | 62 | Package: fastcgi-daemon2-init 63 | Section: libs 64 | Architecture: any 65 | Depends: ${shlibs:Depends}, fastcgi-daemon2 (=${Source-Version}) 66 | Description: fastcgi-daemon-init is init scripts packet for fastcgi-daemon 67 | 68 | -------------------------------------------------------------------------------- /debian/fastcgi-daemon2-init.files: -------------------------------------------------------------------------------- 1 | /usr/bin/fastcgistart2.sh 2 | /etc/init.d/fastcgi-daemon2 3 | 4 | -------------------------------------------------------------------------------- /debian/fastcgi-daemon2-init.postinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | AVAILABLE_DIR=/etc/fastcgi2/available 4 | LOG_DIR=/var/log/fastcgi2 5 | RUN_DIR=/var/run/fastcgi2 6 | POSTSTART_DIR=/etc/fastcgi2/poststart 7 | POSTSTOP_DIR=/etc/fastcgi2/poststop 8 | CHECK_DIR=/etc/fastcgi2/check 9 | 10 | USER=www-data 11 | 12 | mkdir -p $AVAILABLE_DIR $LOG_DIR $RUN_DIR $POSTSTART_DIR $POSTSTOP_DIR $CHECK_DIR 13 | 14 | chown $USER $LOG_DIR $RUN_DIR 15 | chgrp $USER $LOG_DIR $RUN_DIR 16 | 17 | /usr/sbin/update-rc.d fastcgi-daemon2 start 19 2 . stop 21 0 1 6 . 18 | 19 | true 20 | -------------------------------------------------------------------------------- /debian/fastcgi-daemon2-init.postrm: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | AVAILABLE_DIR=/etc/fastcgi2/available 4 | LOG_DIR=/var/log/fastcgi2 5 | RUN_DIR=/var/run/fastcgi2 6 | POSTSTART_DIR=/etc/fastcgi2/poststart 7 | POSTSTOP_DIR=/etc/fastcgi2/poststop 8 | CHECK_DIR=/etc/fastcgi2/check 9 | 10 | rmdir $AVAILABLE_DIR $LOG_DIR $RUN_DIR $POSTSTART_DIR $POSTSTOP_DIR $CHECK_DIR >/dev/null 2>&1 11 | 12 | /usr/sbin/update-rc.d -f fastcgi-daemon2 remove 13 | 14 | exit 0 15 | 16 | -------------------------------------------------------------------------------- /debian/fastcgi-daemon2.files: -------------------------------------------------------------------------------- 1 | usr/sbin/fastcgi-daemon2 2 | etc/fastcgi2/fastcgi.conf.example 3 | -------------------------------------------------------------------------------- /debian/libfastcgi-daemon2-dev.files: -------------------------------------------------------------------------------- 1 | usr/include/fastcgi2/* 2 | usr/lib/libfastcgi-daemon2.a 3 | usr/lib/libfastcgi-daemon2.la 4 | -------------------------------------------------------------------------------- /debian/libfastcgi-daemon2.files: -------------------------------------------------------------------------------- 1 | usr/lib/libfastcgi-daemon2.so* 2 | -------------------------------------------------------------------------------- /debian/libfastcgi2-filelogger.files: -------------------------------------------------------------------------------- 1 | usr/lib/fastcgi2/fastcgi2-filelogger.so* 2 | -------------------------------------------------------------------------------- /debian/libfastcgi2-statistics.files: -------------------------------------------------------------------------------- 1 | usr/lib/fastcgi2/fastcgi2-statistics.so* 2 | -------------------------------------------------------------------------------- /debian/libfastcgi2-syslog.files: -------------------------------------------------------------------------------- 1 | usr/lib/fastcgi2/fastcgi2-syslog.so* 2 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | #export DH_VERBOSE=1 4 | 5 | CXX = g++ 6 | ACLOCAL_OPTIONS = "-I /usr/share/autoconf-archive/ -I ./config/" 7 | 8 | ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) 9 | CXXFLAGS += -g -O0 -fPIC 10 | else 11 | CXXFLAGS += -g -O2 -fPIC -finline 12 | endif 13 | 14 | autogen: autogen-stamp 15 | 16 | autogen-stamp: configure.in 17 | dh_testdir 18 | autoreconf --install 19 | touch autogen-stamp 20 | 21 | configure: configure-stamp 22 | 23 | configure-stamp: 24 | dh_testdir 25 | CXX="$(CXX)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" ./configure --enable-maintainer-mode \ 26 | --prefix=/usr --sysconfdir=/etc/fastcgi2 --localstatedir=/var/log/fastcgi2 \ 27 | --enable-cppunit 28 | touch configure-stamp 29 | 30 | build: build-stamp 31 | 32 | build-stamp: autogen-stamp configure-stamp 33 | dh_testdir 34 | $(MAKE) release=1 35 | touch build-stamp 36 | 37 | clean: 38 | dh_testdir 39 | dh_testroot 40 | rm -f *-stamp 41 | -$(MAKE) distclean 42 | dh_clean 43 | 44 | tests: build 45 | dh_testdir 46 | $(MAKE) check 47 | 48 | install: build tests 49 | dh_testdir 50 | dh_testroot 51 | dh_clean -k 52 | dh_installdirs 53 | $(MAKE) install DESTDIR=$(CURDIR)/debian/tmp 54 | install -d $(CURDIR)/debian/tmp/usr/bin 55 | install -m 755 $(CURDIR)/extra/fastcgistart2.sh $(CURDIR)/debian/tmp/usr/bin 56 | install -d $(CURDIR)/debian/tmp/etc/init.d 57 | install -m 755 $(CURDIR)/extra/fastcgi-daemon2 $(CURDIR)/debian/tmp/etc/init.d 58 | 59 | binary-arch: build install 60 | dh_testdir 61 | dh_testroot 62 | dh_movefiles 63 | dh_installchangelogs 64 | dh_link 65 | dh_compress 66 | dh_fixperms 67 | dh_makeshlibs -v 68 | dh_installdeb 69 | dh_shlibdeps 70 | dh_gencontrol 71 | dh_md5sums 72 | dh_builddeb 73 | 74 | binary: binary-arch 75 | 76 | .PHONY: build clean binary-arch binary install configure 77 | -------------------------------------------------------------------------------- /doc/daemon-arc-en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmovsesjan/Fastcgi-Daemon/a6f2043403d07e6e1771a1bf2368d209b8868d81/doc/daemon-arc-en.png -------------------------------------------------------------------------------- /doc/en/API. Application development.md: -------------------------------------------------------------------------------- 1 | Applications (custom components) for FastCGI-Daemon are the shared objects (so). You should compile `libfastcgi-daemon2.so` and use headers in `include/fastcgi2` for development. 2 | 3 | API contains the namespace `fastcgi`, with the classes: 4 | 5 | |**Class**|**Description**| 6 | |---------|------------| 7 | |[Component](Class Component.md)|Abstract class, mandatory for inheritance by a custom component. It is the base of a custom component.| 8 | |[ComponentContext](Class ComponentContext.md)|Keeps the context of a custom component.| 9 | |[Config](Class Config.md)|Contains configuration settings of daemon.| 10 | |[Cookie](Class Cookie.md)|Operates with cookies.| 11 | |[DataBuffer](Class DataBuffer.md)|Operates with data.| 12 | |[SegmentIterator](Class SegmentIterator.md)|Iterator for the segmented `DataBuffer`.| 13 | |[Handler](Class Handler.md)|Abstract class, mandatory for inheritance by a custom component. It is the base of a custom request handler.| 14 | |[HandlerContext](Class HandlerContext.md)|Stores global parameters of a custom request handler.| 15 | |[Logger](Class Logger.md)|Operates with logging.| 16 | |[Request](Class Request.md)|Operates with a request. It used to parse and modify request and to create a response for it.| 17 | 18 | Custom component must inherit from `Component` and `Handler`. Methods `onLoad()`, `onUnload()` and `handleRequest(...)` should be defined. Component should use macros defined in `ComponentFactory.h` in order to provide its functionality to daemon. 19 | 20 | For example, user defines 2 components in its module (.so): 21 | 22 | ``` 23 | class ExampleComponent1 : virtual public fastcgi::Component, virtual public fastcgi::Handler{...} 24 | class ExampleComponent2 : virtual public fastcgi::Component, virtual public fastcgi::Handler{...} 25 | ``` 26 | 27 | They should be registered as follows: 28 | 29 | ``` 30 | FCGIDAEMON_REGISTER_FACTORIES_BEGIN() 31 | FCGIDAEMON_ADD_DEFAULT_FACTORY("factory1", ExampleComponent1) 32 | FCGIDAEMON_ADD_DEFAULT_FACTORY("factory2", ExampleComponent2) 33 | FCGIDAEMON_REGISTER_FACTORIES_END() 34 | ``` 35 | 36 | To use syslog, custom component should get `daemon-logger` using the `findComponent` method of [ComponentContext](Class ComponentContext.md) class. Then use methods of [Logger](Class Logger.md) class as follows: 37 | 38 | ``` 39 | fastcgi::ComponentContext *cntx = context(); 40 | fastcgi::Logger *log = cntx->findComponent("daemon-logger"); 41 | log->info("some useful info"); 42 | ``` 43 | -------------------------------------------------------------------------------- /doc/en/Class Component.md: -------------------------------------------------------------------------------- 1 | Abstract class, that should be inherited by a custom components. Header - `fastcgi2/component.h`. 2 | 3 | Member functions: 4 | 5 | |Function|Description| 6 | |--------|-----------| 7 | |[onLoad](#-onload)|Callback method, called at component load.| 8 | |[onUnload](#-onunload)|Callback method, called at component unload.| 9 | |[context](#-context)|Returns a component context.| 10 | 11 | ## onLoad 12 | Callback method, called at component load. 13 | 14 | ``` 15 | virtual void onLoad() = 0; 16 | ``` 17 | 18 | ## onUnload 19 | Callback method, called at component unload. 20 | 21 | ``` 22 | virtual void onUnload() = 0; 23 | ``` 24 | 25 | ## context 26 | Returns a component context. 27 | 28 | ``` 29 | ComponentContext* context(); 30 | const ComponentContext* context() const; 31 | ``` 32 | 33 | **Return value** 34 | 35 | A component context. 36 | -------------------------------------------------------------------------------- /doc/en/Class ComponentContext.md: -------------------------------------------------------------------------------- 1 | Provides context of a component. Header - `fastcgi2/component.h`. 2 | 3 | Member functions: 4 | 5 | |Function|Description| 6 | |--------|-----------| 7 | |[getConfig](#-getconfig)|Returns [Config](Class Config.md) which contains the configuration parameters of FastCGI-daemon.| 8 | |[getComponentXPath](#-getcomponentxpath)|Returns XPath to the component description in the configuration file.| 9 | |[findComponent](#-findcomponent)|Returns the pointer to the existing and loaded component.| 10 | 11 | ## getConfig 12 | Returns [Config](Class Config.md) which contains the configuration parameters of FastCGI-daemon. 13 | 14 | ``` 15 | virtual const Config* getConfig() const = 0; 16 | ``` 17 | 18 | **Return value** 19 | 20 | Pointer to [Config](Class Config.md). 21 | 22 | ## getComponentXPath 23 | Returns XPath to the component description in the configuration file. 24 | 25 | ``` 26 | virtual std::string getComponentXPath() const = 0; 27 | ``` 28 | 29 | **Return value** 30 | 31 | XPath. For example, `/fastcgi/components/component[1]`. 32 | 33 | ## findComponent 34 | Returns the pointer to the existing and loaded component. 35 | 36 | ``` 37 | template T* findComponent(const std::string &name) 38 | ``` 39 | 40 | **Parameters** 41 | 42 | |Parameter|Description| 43 | |--------|--------| 44 | |name|Name of the component.| 45 | 46 | **Return value** 47 | 48 | Pointer to the component class. 49 | -------------------------------------------------------------------------------- /doc/en/Class Config.md: -------------------------------------------------------------------------------- 1 | Contains the configuration settings of the daemon. Header - `fastcgi2/config.h`. 2 | 3 | Member functions: 4 | 5 | |Function|Desription| 6 | |--------|----------| 7 | |[asInt](#-asint)|Returns the configuration parameter as an integer.| 8 | |[asString](#-asstring)|Returns the configuration parameter as a string.| 9 | |[subKeys](#-subkeys)|Returns XPath to the tags with the same name.| 10 | |[filename](#-filename)|Returns a filename of configuration which daemon runs.| 11 | 12 | ## asInt 13 | Returns the configuration parameter as an integer. 14 | 15 | ``` 16 | virtual int asInt(const std::string &value) const = 0; 17 | virtual int asInt(const std::string &value, int defval) const = 0; 18 | ``` 19 | 20 | **Parameters** 21 | 22 | |Parameter|Description| 23 | |--------|--------| 24 | |value|XPath to the required parameter. For example, `/fastcgi/daemon/monitor_port`.| 25 | |defval|The default value, which is returned in case the requested value doesn't exist.| 26 | 27 | **Return value** 28 | 29 | The parameter as an interger. 30 | 31 | ## asString 32 | Returns the configuration parameter as a string. 33 | 34 | ``` 35 | virtual std::string asString(const std::string &value) const = 0; 36 | virtual std::string asString(const std::string &value, const std::string &defval) const = 0; 37 | ``` 38 | 39 | **Parameters** 40 | 41 | |Parameter|Description| 42 | |--------|--------| 43 | |value|XPath to the required parameter. For example, `/fastcgi/daemon/pidfile`.| 44 | |defval|The default value, which is returned in case the requested value doesn't exist.| 45 | 46 | **Return value** 47 | 48 | The parameter as a string. 49 | 50 | ## subKeys 51 | Returns XPath to tags with the same name. 52 | 53 | ``` 54 | virtual void subKeys(const std::string &value, std::vector &v) const = 0; 55 | ``` 56 | 57 | **Parameters** 58 | 59 | |Parameter|Description| 60 | |--------|--------| 61 | |value|XPath to the configuration file tag. For example, `/fastcgi/components/component`.| 62 | |v|Container for the result.| 63 | 64 | **Return value** 65 | 66 | A vector of the paths to the same named tags of the same branch of the configuration tree. 67 | 68 | For example, `value=/fastcgi/components/component`, and we have a 3 components described in the configuration file. In this case the result will be: 69 | 70 | ``` 71 | /fastcgi/components/component[1] 72 | /fastcgi/components/component[2] 73 | /fastcgi/components/component[3] 74 | ``` 75 | 76 | ## filename 77 | Returns a filename of the configuration which daemon runs. 78 | 79 | ``` 80 | const std::string& filename() const; 81 | ``` 82 | 83 | **Return value** 84 | 85 | A name of the configuration file. 86 | -------------------------------------------------------------------------------- /doc/en/Class Cookie.md: -------------------------------------------------------------------------------- 1 | Operates with cookies. Header - `fastcgi2/cookie.h`. 2 | 3 | Member functions: 4 | 5 | |Function|Description| 6 | |-----|--------| 7 | |[Cookie](#-konstruktorklassa)|Constructor.| 8 | |[name](#-name)|Returns the name of a cookie.| 9 | |[value](#-value)|Returns the value of a cookie.| 10 | |[secure](#-secure)|Sets/returns the property of HTTPS usage.| 11 | |[expires](#-expires)|Sets/returns a cookie expiration time.| 12 | |[permanent](#-permanent)|Sets/returns the property of permanency.| 13 | |[httpOnly](#-httponly)|Sets/returns the HTTP-only property.| 14 | |[path](#-path)|Sets/returns a cookie path.| 15 | |[domain](#-domain)|Sets a cookie domain.| 16 | |[toString](#-tostring)|Returns a cookie string.| 17 | |[urlEncode](#-urlencode)|Sets a property of urlencode. If `true`, then `toString` returns an urlencoded value.| 18 | 19 | A custom component can get a request cookie and create new cookies with this class. When creating a new cookie its properties must be set by `secure, expires, permanent, httpOnly` etc. methods. 20 | A cookie can be exported to the string with `toString` method. 21 | 22 | ## Constructor 23 | 24 | ``` 25 | Cookie(const std::string &name, const std::string &value); 26 | Cookie(const Cookie &cookie); 27 | ``` 28 | 29 | **Parameters** 30 | 31 | |Parameter|Description| 32 | |--------|--------| 33 | |name|A cookie name.| 34 | |value|A cookie value.| 35 | |cookie|A cookie.| 36 | 37 | ## name 38 | Returns a cookie name. 39 | 40 | ``` 41 | const std::string& name() const; 42 | ``` 43 | 44 | **Return value** 45 | 46 | A cookie name. 47 | 48 | ## value 49 | Returns a cookie value. 50 | 51 | ``` 52 | const std::string& value() const; 53 | ``` 54 | **Return value** 55 | 56 | A cookie value. 57 | 58 | ## secure 59 | Sets/returns the property of HTTPS usage. 60 | 61 | ``` 62 | bool secure() const; 63 | void secure(bool value); 64 | ``` 65 | 66 | **Parameters** 67 | 68 | |Parameter|Description| 69 | |--------|--------| 70 | |value|`true`, if HTTPS needed.| 71 | 72 | **Return value** 73 | 74 | The property of HTTPS usage. 75 | 76 | ## expires 77 | Sets/returns a cookie expiration time. 78 | 79 | ``` 80 | time_t expires() const; 81 | void expires(time_t value); 82 | ``` 83 | 84 | **Parameters** 85 | 86 | |Parameter|Description| 87 | |--------|--------| 88 | |value|A cookie expiration UNIX-time.| 89 | 90 | **Return value** 91 | 92 | A cookie expiration UNIX-time. 93 | 94 | ## permanent 95 | Sets/returns the property of permanency. 96 | 97 | ``` 98 | void permanent(bool value); 99 | bool permanent() const; 100 | ``` 101 | 102 | **Parameters** 103 | 104 | |Parameter|Description| 105 | |--------|--------| 106 | |value|`true`, if cookie should be permanent.| 107 | 108 | **Return value** 109 | 110 | `true`, if cookie is permanent. 111 | 112 | ## httpOnly 113 | Sets/returns the HTTP-only property. 114 | 115 | ``` 116 | void httpOnly(bool value); 117 | bool httpOnly() const; 118 | ``` 119 | 120 | **Parameters** 121 | 122 | |Parameter|Description| 123 | |--------|--------| 124 | |value|`true` if HTTP-only needed.| 125 | 126 | **Return value** 127 | 128 | The HTTP-only property. 129 | 130 | ## path 131 | Sets/returns a cookie path. 132 | 133 | ``` 134 | const std::string& path() const; 135 | void path(const std::string &value); 136 | ``` 137 | 138 | **Parameters** 139 | 140 | |Parameter|Description| 141 | |--------|--------| 142 | |value|A cookie path.| 143 | 144 | **Return value** 145 | 146 | A cookie path. 147 | 148 | ## domain 149 | Sets a cookie domain. 150 | 151 | ``` 152 | const std::string& domain() const; 153 | void domain(const std::string &value); 154 | ``` 155 | 156 | **Parameters** 157 | 158 | |Parameter|Description| 159 | |--------|--------| 160 | |value|A cookie domain.| 161 | 162 | **Return value** 163 | 164 | A cookie domain. 165 | 166 | ## toString 167 | Returns a cookie string. 168 | 169 | ``` 170 | std::string toString() const; 171 | ``` 172 | 173 | **Return value** 174 | 175 | A cookie. For example, `coname=coval; domain=yandex.ru; HttpOnly`. 176 | 177 | ## urlEncode 178 | Sets the property of urlencode. If `true`, then `toString` returns an urlencoded value. 179 | 180 | ``` 181 | void urlEncode(bool value); 182 | ``` 183 | 184 | **Parameters** 185 | 186 | |Parameter|Description| 187 | |--------|--------| 188 | |value|An urlendode property.| 189 | -------------------------------------------------------------------------------- /doc/en/Class Handler.md: -------------------------------------------------------------------------------- 1 | Abstract class, mandatory for inheritance by a custom component. It is the base of a custom request handler. Header - `fastcgi2/handler.h`. 2 | 3 | Member functions: 4 | 5 | |Function|Description| 6 | |--------|-----------| 7 | |[onThreadStart](#-onthreadstart)|Callback function.| 8 | |[handleRequest](#-handlerequest)|Start point of the request processing.| 9 | 10 | ## Метод onThreadStart 11 | Callback function. 12 | 13 | ``` 14 | virtual void onThreadStart() 15 | ``` 16 | 17 | ## Метод handleRequest 18 | Start point of the request processing. It called by daemon on incoming request. 19 | 20 | ``` 21 | virtual void handleRequest(Request *req, HandlerContext *context) = 0 22 | ``` 23 | 24 | **Parameters** 25 | 26 | |Parameter|Description| 27 | |---------|-----------| 28 | |req|A pointer to [Request](Class Request), which contains all the request info and provides functions to operate with it.| 29 | |context|Pointer to [HandlerContext](Class HandlerContext.md).| -------------------------------------------------------------------------------- /doc/en/Class HandlerContext.md: -------------------------------------------------------------------------------- 1 | Stores global parameters of custom request handler. Header `fastcgi2/handler.h`. 2 | 3 | This is a storage of custom parameters, there is no data until `setParam` is called. You can call `getParam` only after corresponding `setParam`. 4 | 5 | Member functions: 6 | 7 | |Function|Description| 8 | |--------|-----------| 9 | |[getParam](#-getparam)|Returns parameter by the name.| 10 | |[setParam](#-setparam)|Sets parameter by the name.| 11 | 12 | 13 | ## getParam 14 | Returns parameter by the name. 15 | 16 | ``` 17 | virtual boost::any getParam(const std::string &name) const = 0 18 | ``` 19 | 20 | **Parameters** 21 | 22 | |Parameter|Description| 23 | |---------|-----------| 24 | |name|The parameter name.| 25 | 26 | **Return value** 27 | 28 | The parameter value. 29 | 30 | ## setParam 31 | Sets parameter by the name. 32 | 33 | ``` 34 | virtual void setParam(const std::string &name, const boost::any &value) = 0 35 | ``` 36 | 37 | **Parameters** 38 | 39 | |Parameter|Decription| 40 | |---------|----------| 41 | |name|Parameter name.| 42 | |value|Parameter value.| 43 | -------------------------------------------------------------------------------- /doc/en/Class Logger.md: -------------------------------------------------------------------------------- 1 | Operates with logging. Header - `fastcgi2/logger.h`. 2 | 3 | Member functions: 4 | 5 | |Function|Description| 6 | |--------|-----------| 7 | |[exiting](#-exiting)|Sends the DEBUG-level log info on exit from the function.| 8 | |[entering](#-entering)|Sends the DEBUG-level log info on enter to the function.| 9 | |[getLevel](#-getlevel)|Returns logging level (DEBUG, INFO, ERROR,EMERGENCY) of an application.| 10 | |[setLevel](#-setlevel)|Sets the logging level for application.| 11 | |[stringToLevel](#-stringtolevel)|Converts name of logging level into the numeric identifier.| 12 | |[levelToString](#-leveltostring)|Converts numeric identifier of logging level into its name.| 13 | |[debug, info, error, emerg](#-ydebuginfoerroremerg)|Sends info of DEBUG, INFO, ERROR, EMERGENCY level respectively into the log.| 14 | |[log](#-log)|Sends info of specified level into the log.| 15 | 16 | 17 | ## exiting 18 | Sends DEBUG-level log info on exit from the function. 19 | 20 | ``` 21 | void exiting(const char *function) 22 | ``` 23 | 24 | **Parameters** 25 | 26 | |Parameter|Description| 27 | |--------|--------| 28 | |function|Function name.| 29 | 30 | ## entering 31 | Sends DEBUG-level log info on enter to the function. 32 | 33 | ``` 34 | void entering(const char *function) 35 | ``` 36 | 37 | **Parameters** 38 | 39 | |Parameter|Description| 40 | |--------|--------| 41 | |function|Function name.| 42 | 43 | ## getLevel 44 | Returns logging level (DEBUG, INFO, ERROR,EMERGENCY) of an application. 45 | 46 | ``` 47 | Level getLevel() const 48 | ``` 49 | 50 | **Return value** 51 | 52 | Numeric identifier of application log level. If this level is INFO then the messages of EMERGENCY, ERROR и INFO level will be logged, but DEBUG messages will not be logged. 53 | 54 | ## setLevel 55 | Sets logging level for an application. 56 | 57 | ``` 58 | void setLevel(const Level level) 59 | ``` 60 | 61 | **Parameters** 62 | 63 | |Parameter|Description| 64 | |--------|--------| 65 | |level|Numeric identifier of logging level.| 66 | 67 | ## stringToLevel 68 | Converts name of logging level into numeric identifier. 69 | 70 | ``` 71 | static Level stringToLevel(const std::string &name) 72 | ``` 73 | 74 | **Parameters** 75 | 76 | |Parameter|Description| 77 | |--------|--------| 78 | |name|The name of logging level.| 79 | 80 | **Return value** 81 | 82 | A numeric identifier of logging level. 83 | 84 | ## levelToString 85 | Converts numeric identifier of logging level into its name. 86 | 87 | ``` 88 | static std::string levelToString(const Level) 89 | ``` 90 | 91 | **Parameters** 92 | 93 | |Parameter|Description| 94 | |--------|--------| 95 | |level|A numeric identifier of logging level.| 96 | 97 | **Return value** 98 | 99 | The name of logging level. 100 | 101 | ## debug, info, error, emerg 102 | Sends info of DEBUG, INFO, ERROR, EMERGENCY level respectively into the log. 103 | 104 | ``` 105 | virtual void debug(const char *format, ...) 106 | virtual void info(const char *format, ...) 107 | virtual void error(const char *format, ...) 108 | virtual void emerg(const char *format, ...) 109 | ``` 110 | 111 | **Parameters** 112 | 113 | |Parameter|Description| 114 | |--------|--------| 115 | |format|String format.| 116 | |...|Format arguments.| 117 | 118 | ## log 119 | Sends info of specified level into the log. 120 | 121 | ``` 122 | virtual void log(const Level level, const char *format, va_list args) = 0 123 | ``` 124 | 125 | **Parameters** 126 | 127 | |Parameter|Description| 128 | |--------|--------| 129 | |level|A numeric identifier of logging level.| 130 | |format|A string format.| 131 | |args|Format arguments.| 132 | -------------------------------------------------------------------------------- /doc/en/Class SegmentIterator.md: -------------------------------------------------------------------------------- 1 | Iterator for [DataBuffer](Class DataBuffer.md) 2 | Header `fastcgi2/data_buffer.h`. 3 | 4 | Operators: 5 | ``` 6 | SegmentIterator& operator++(); 7 | SegmentIterator operator++(int); 8 | SegmentIterator& operator--(); 9 | SegmentIterator operator--(int); 10 | ``` 11 | 12 | Data can be accessed though the operators: 13 | 14 | ``` 15 | std::pair operator*() const; 16 | std::pair* operator->() const; 17 | ``` 18 | 19 | The `first` member is a segment data, the `second` is a size of segment. 20 | -------------------------------------------------------------------------------- /doc/en/Introduction.md: -------------------------------------------------------------------------------- 1 | This section provides documentation for FastCGI-Daemon, which will help you install and configure it. 2 | API for application development is also described in this paper. 3 | 4 | Documentation is intended for developers and system administrators. 5 | 6 | ## Contents: 7 | * [Overview](Overview.md) 8 | * [Quick start guide](Quick start guide.md) 9 | * [Setup](Setup.md) 10 | * [API. Application development](API. Application development.md) 11 | -------------------------------------------------------------------------------- /doc/en/Overview.md: -------------------------------------------------------------------------------- 1 | FastCGI-daemon is a multithreaded platform, designed to run FastCGI applications written in C++. Applications should be designed as a plug-ins using `libfastcgi-daemon2` which is a part of a project. 2 | 3 | ![FastCGI-daemon structure](../daemon-arc-en.png) 4 | 5 | Daemon consists of some thread pools. One of them is a socket-pool which is responsible for interaction with HTTP-server, others run custom FastCGI-applications. 6 | 7 | # Packages 8 | The project is supporter on Linux Ubuntu (Hardy, Lucid � Precise). 9 | 10 | 11 | |Package|Description| 12 | |-----|--------| 13 | |`fastcgi-daemon2`|Contains FastCGI-Daemon.| 14 | |`fastcgi-daemon2-init`|Init-scripts for daemon.| 15 | |`libfastcgi-daemon2`|Library needed to develop custom applications.| 16 | |`libfastcgi-daemon2-dev`|Header files and static library `libfastcgi-daemon2.a`.| 17 | |`libfastcgi2-syslog`|Application for daemon used to log into syslog.| 18 | -------------------------------------------------------------------------------- /doc/en/Quick start guide.md: -------------------------------------------------------------------------------- 1 | In this section, we consider the simple installation of FastCGI-daemon in conjunction with [nginx] (http://nginx.org). Custom application for daemon will also be developed and tested. 2 | 3 | 4 | ## nginx intallation 5 | Install nginx: 6 | 7 | ``` 8 | $ sudo apt-get install nginx 9 | ``` 10 | 11 | Configure nginx as a proxy for FastCGI-Daemon: 12 | 13 | ``` 14 | $ cat /etc/nginx/sites-enabled/fastcgi-daemon.conf 15 | 16 | server { 17 | listen 80; 18 | 19 | location / { 20 | include fastcgi_params; 21 | fastcgi_param SCRIPT_FILENAME $fastcgi_script_name; 22 | fastcgi_pass unix:/tmp/fastcgi_daemon.sock; 23 | } 24 | } 25 | ``` 26 | 27 | `fastcgi_pass` is the same socket, that FastCGI-daemon use. 28 | 29 | Restart nginx: 30 | 31 | ``` 32 | $ service nginx restart 33 | ``` 34 | 35 | ## FastCGI-daemon installation 36 | Install FastCGI-daemon: 37 | 38 | ``` 39 | $ sudo apt-get install fastcgi-daemon2-init libfastcgi-daemon2-dev libfastcgi2-syslog 40 | ``` 41 | 42 | Next, we will develop a component `csimple` (``) in `csimple_module` (``), which we will compile as `libcsimple.so`. This component will be a handler (``) of requests to `/csimple_res` resource. The component will be implemented by a class `SimpleClass` and registered as a `simple_factory`. 43 | 44 | Configuration file of FastCGI-daemon, which will handle this component looks as follows: 45 | 46 | ``` 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | INFO 61 | fastcgi-test 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 128 72 | /tmp/fastcgi_daemon.sock 73 | 1 74 | 75 | /tmp/fastcgi_daemon.pid 76 | 20011 77 | 78 | 79 | ``` 80 | 81 | `logger` module (`daemon-logger` component) is used for logging and should be included in all cases. 82 | Save this file as `csimple.conf`. 83 | 84 | 85 | ## Component development 86 | Our component will respond with header `Simple-Header` for all the requests. 87 | 88 | ``` 89 | #include 90 | #include 91 | #include 92 | #include 93 | 94 | #include 95 | 96 | class SimpleClass : virtual public fastcgi::Component, virtual public fastcgi::Handler { 97 | 98 | public: 99 | SimpleClass(fastcgi::ComponentContext *context) : 100 | fastcgi::Component(context) { 101 | } 102 | virtual ~SimpleClass() { 103 | } 104 | 105 | public: 106 | virtual void onLoad() { 107 | } 108 | virtual void onUnload() { 109 | } 110 | virtual void handleRequest(fastcgi::Request *request, fastcgi::HandlerContext *context) { 111 | 112 | //Request handler code. The start point of the request processing. 113 | 114 | request->setHeader("Simple-Header", "Reply from csimple"); 115 | } 116 | 117 | }; 118 | 119 | FCGIDAEMON_REGISTER_FACTORIES_BEGIN() 120 | FCGIDAEMON_ADD_DEFAULT_FACTORY("simple_factory", SimpleClass) 121 | FCGIDAEMON_REGISTER_FACTORIES_END() 122 | ``` 123 | 124 | Save this code to file `SimpleClass.cpp` and compile it: 125 | 126 | ``` 127 | $ g++ SimpleClass.cpp -fPIC -lfastcgi-daemon2 -shared -o libcsimple.so 128 | ``` 129 | 130 | Put `libcsimple.so` into `/fastcgi/csimple`. Start FastCGI-Daemon: 131 | 132 | ``` 133 | $ fastcgi-daemon2 --config=csimple.conf 134 | ``` 135 | 136 | Test application: 137 | 138 | ``` 139 | $ curl -v "http://localhost/simple_res" 140 | 141 | > GET /simple_res HTTP/1.1 142 | > User-Agent: curl/7.22.0 (i686-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3 143 | > Host: localhost 144 | > Accept: */* 145 | > 146 | < HTTP/1.1 200 OK 147 | < Server: nginx/1.2.1 148 | < Date: Wed, 28 Nov 2012 07:02:04 GMT 149 | < Transfer-Encoding: chunked 150 | < Connection: keep-alive 151 | < Simple-Header: Reply from csimple 152 | ``` 153 | 154 | We'll see "Simple-Header: Reply from csimple" in the server's response. That's all. 155 | -------------------------------------------------------------------------------- /doc/en/Setup.md: -------------------------------------------------------------------------------- 1 | ## Configuration objects 2 | Logically daemon consists of multiple thread pools, one of which is a pool of sockets, and the remaining pools are run the request handlers. 3 | 4 | Socket pool is responsible for receiving data from the HTTP-server and forwarding the request to the appropriate handler. Its configuration is set in the `` section of configuration file. 5 | 6 | Handlers are implemented as shared objects (``) and may contain several components (``). Each component can run in any worker pool (``). Socket pool pass requests into the handlers. 7 | 8 | Daemon can have many worker pools and they are separately configurable in `` section. Each pool has configurable maximum amount of threads and maximum size of an entrance queue. Administrator can manage pool priority using it. 9 | 10 | ## Configuration file 11 | The configuration is stored in XML-file like that: 12 | 13 | ``` 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | INFO 28 | fastcgi-test 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 128 39 | /tmp/fastcgi_daemon.sock 40 | 1 41 | 42 | /tmp/fastcgi_daemon.pid 43 | 20011 44 | 45 | 46 | ``` 47 | 48 | Tags: 49 | 50 | * pools - worker pools definition. Contains attributes: 51 | * `name` - pool name. Defined by administrator; 52 | * `threads` - maximum number of threads in pool; 53 | * `queue` - size of queue of incoming requests. 54 | * handlers - consists of `handler` tags. 55 | * handler - associate the user's request and a handler component. Handler can be configured for a specific port, domain/host or url. Contains attributes: 56 | * url - resource name. For example, `url="/some_resource"`; 57 | * host - `Host` header of the request; 58 | * port - nginx port; 59 | * address - nginx bind address from its configuration file (one from `listen`); 60 | * pool - pool name. The only required attribute, remaining attributes can be specified arbitrarily. 61 | 62 | Can contain `param` (there may be several) and `component` tags. 63 | * param - defines requred request parameter. Attribute `name` - name of the parameter. 64 | * component - component which will handle request. Attribute `name` - name of the component. 65 | * components - contains `component` tags. 66 | * component - component definition. Can contain any tags required by the developer of component. Contains attributes: 67 | * `name` - component name; 68 | * `type` - :. Component factory name provided by developer. 69 | * modules - contains `module` tags. 70 | * module - definition of module with FastCGI-application. Contains attributes: 71 | * name - module name. Defined by administrator; 72 | * path - path to the shared object with the custom application. 73 | * daemon - definition of common daemon parameters and parameters of a socket pool. Contains`logger`, `endpoint`, `pidfile`, `monitor_port` tags. 74 | * logger - logging component. Attribute `component` - a component name. 75 | * endpoint - a socket pool configuration. Contains tags: 76 | * backlog - size of queue of incoming connections from nginx. Extra connections will be dropped; 77 | * socket - path to the socket; 78 | * threads - maximum number of threads in a pool. 79 | * pidfile - path to a pid-file. 80 | * monitor_port - monitoring port of a daemon. If you want to check daemon state you should `netcat` to this port. 81 | 82 | Logging configuration. 83 | Component `daemon-logger` is used for logging into syslog. To use it, configure component with tags `level` and `ident`, setting log level and application id for syslog. 84 | 85 | ## Operability test 86 | To make sure that the daemon is running, use the command: 87 | 88 | ``` 89 | $ echo i | netcat localhost port 90 | ``` 91 | 92 | `port` should have the same value, that contained in `value` of configuration file. 93 | 94 | You will see the next XML as a response: 95 | 96 | ``` 97 | 98 | running 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | ``` -------------------------------------------------------------------------------- /example/Makefile.am: -------------------------------------------------------------------------------- 1 | pkglib_LTLIBRARIES = example.la 2 | 3 | example_la_SOURCES = example.cpp 4 | example_la_LDFLAGS = -module 5 | example_la_LIBADD = ../library/libfastcgi-daemon2.la 6 | 7 | AM_CPPFLAGS = -I../include -I../config 8 | AM_CXXFLAGS = -pthread 9 | AM_LDFLAGS = 10 | 11 | -------------------------------------------------------------------------------- /example/example.cpp: -------------------------------------------------------------------------------- 1 | #include "settings.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "fastcgi2/logger.h" 7 | #include "fastcgi2/config.h" 8 | #include "fastcgi2/stream.h" 9 | #include "fastcgi2/handler.h" 10 | #include "fastcgi2/request.h" 11 | #include "fastcgi2/component.h" 12 | #include "fastcgi2/component_factory.h" 13 | 14 | #ifdef HAVE_DMALLOC_H 15 | #include 16 | #endif 17 | 18 | namespace example 19 | { 20 | 21 | class ExampleHandler : virtual public fastcgi::Component, virtual public fastcgi::Handler 22 | { 23 | public: 24 | ExampleHandler(fastcgi::ComponentContext *context); 25 | virtual ~ExampleHandler(); 26 | 27 | virtual void onLoad(); 28 | virtual void onUnload(); 29 | 30 | virtual void handleRequest(fastcgi::Request *req, fastcgi::HandlerContext *handlerContext); 31 | 32 | private: 33 | fastcgi::Logger *logger_; 34 | }; 35 | 36 | class ExampleHandler2 : virtual public fastcgi::Component, virtual public fastcgi::Handler 37 | { 38 | public: 39 | ExampleHandler2(fastcgi::ComponentContext *context); 40 | virtual ~ExampleHandler2(); 41 | 42 | virtual void onLoad(); 43 | virtual void onUnload(); 44 | 45 | virtual void handleRequest(fastcgi::Request *req, fastcgi::HandlerContext *handlerContext); 46 | }; 47 | 48 | 49 | ExampleHandler::ExampleHandler(fastcgi::ComponentContext *context) : fastcgi::Component(context), logger_(NULL) { 50 | } 51 | 52 | ExampleHandler::~ExampleHandler() { 53 | } 54 | 55 | void 56 | ExampleHandler::onLoad() { 57 | std::cout << "onLoad handler1 executed" << std::endl; 58 | const std::string loggerComponentName = context()->getConfig()->asString(context()->getComponentXPath() + "/logger"); 59 | logger_ = context()->findComponent(loggerComponentName); 60 | if (!logger_) { 61 | throw std::runtime_error("cannot get component " + loggerComponentName); 62 | } 63 | } 64 | 65 | void 66 | ExampleHandler::onUnload() { 67 | std::cout << "onUnload handler1 executed" << std::endl; 68 | } 69 | 70 | void 71 | ExampleHandler::handleRequest(fastcgi::Request *req, fastcgi::HandlerContext *handlerContext) { 72 | 73 | // std::cout << req->countArgs() << ":" << req->getArg("a") << std::endl; 74 | // std::cout << "QUERY_STRING=" << req->getQueryString() << std::endl; 75 | 76 | // req->setContentType("text/plain"); 77 | fastcgi::RequestStream stream(req); 78 | 79 | /* std::vector names; 80 | req->argNames(names); 81 | for (std::vector::iterator i = names.begin(), end = names.end(); i != end; ++i) { 82 | stream << "arg " << (*i) << " has value " << req->getArg(*i) << "\n"; 83 | } 84 | req->headerNames(names); 85 | for (std::vector::iterator i = names.begin(), end = names.end(); i != end; ++i) { 86 | stream << "header " << (*i) << " has value " << req->getHeader(*i) << "\n"; 87 | } 88 | req->cookieNames(names); 89 | for (std::vector::iterator i = names.begin(), end = names.end(); i != end; ++i) { 90 | stream << "cookie " << (*i) << " has value " << req->getCookie(*i) << "\n"; 91 | }*/ 92 | 93 | stream << "test ok\n"; 94 | 95 | // logger_->info("request processed"); 96 | 97 | req->setStatus(200); 98 | 99 | // handlerContext->setParam("param1", std::string("hi!")); 100 | } 101 | 102 | ExampleHandler2::ExampleHandler2(fastcgi::ComponentContext *context) : fastcgi::Component(context) { 103 | } 104 | 105 | ExampleHandler2::~ExampleHandler2() { 106 | } 107 | 108 | void 109 | ExampleHandler2::onLoad() { 110 | std::cout << "onLoad handler2 executed" << std::endl; 111 | } 112 | 113 | void 114 | ExampleHandler2::onUnload() { 115 | std::cout << "onUnload handler2 executed" << std::endl; 116 | } 117 | 118 | void 119 | ExampleHandler2::handleRequest(fastcgi::Request *req, fastcgi::HandlerContext *handlerContext) { 120 | boost::any param1 = handlerContext->getParam("param1"); 121 | boost::any param2 = handlerContext->getParam("param2"); 122 | 123 | if (param1.empty()) { 124 | std::cout << "param1 not found" << std::endl; 125 | } else { 126 | try { 127 | //std::cout << "value of param1 = " << boost::any_cast(param1) << std::endl; 128 | } catch (const boost::bad_any_cast &) { 129 | //std::cout << "bad_any_cast: param1 is not string" << std::endl; 130 | } 131 | } 132 | 133 | if (param2.empty()) { 134 | //std::cout << "param2 not found" << std::endl; 135 | } else { 136 | //std::cout << "param1 found" << std::endl; 137 | } 138 | 139 | if (req->getScriptName() == "/upload" && req->getRequestMethod() == "POST") { 140 | fastcgi::DataBuffer f = req->remoteFile("file"); 141 | std::string file; 142 | f.toString(file); 143 | //std::cout << "file=\n" << file << std::endl; 144 | } 145 | } 146 | 147 | 148 | FCGIDAEMON_REGISTER_FACTORIES_BEGIN() 149 | FCGIDAEMON_ADD_DEFAULT_FACTORY("example", ExampleHandler) 150 | FCGIDAEMON_ADD_DEFAULT_FACTORY("example2", ExampleHandler2) 151 | FCGIDAEMON_REGISTER_FACTORIES_END() 152 | 153 | } // namespace example 154 | -------------------------------------------------------------------------------- /example/fastcgi.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /tmp/fastcgi2-example.sock 7 | 10 8 | 4096 9 | 10 | 11 | /tmp/fastcgi2-example1.sock 12 | 10 13 | 4096 14 | 15 | /var/run/fastcgi-example.pid 16 | 3333 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | daemon-logger 32 | 33 | 34 | daemon-logger 35 | 36 | 37 | DEBUG 38 | /var/log/fastcgi2/example-daemon.log 39 | example-daemon-logger 40 | %r [%d] %p %c %x - %m%n 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /extra/fastcgistart2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Starting script for FastCgi Daemon 3 | 4 | ETCDIR='/etc' 5 | THIS=`basename $0 | sed 's/^[SK][0123456789]*b/b/'` 6 | MAILHOST="yandex-team.ru" 7 | 8 | SUBJECT="$THIS on `hostname`" 9 | FASTCGI_CONFIG=/etc/fastcgi2/available/$1.conf 10 | FASTCGI_NICE=/etc/fastcgi2/available/$1.nice 11 | FASTCGI_ENV=/etc/fastcgi2/available/$1.env 12 | FASTCGI_START=/etc/fastcgi2/available/$1.start 13 | LOCKER=/var/run/fastcgi2/fastcgistart2.$1.pid 14 | RDELAY=1 15 | 16 | if [ -e $FASTCGI_CONFIG ]; then 17 | if [ ! -r $FASTCGI_START ]; then 18 | COREDIR=/var/tmp/core-files 19 | ulimit -c unlimited 20 | ulimit -s 1024 21 | 22 | if [ -d "$COREDIR" ]; then 23 | mkdir -p $COREDIR 2>/dev/null 24 | fi 25 | fi 26 | 27 | if [ -e $FASTCGI_NICE ]; then 28 | FASTCGI_NICE=`cat $FASTCGI_NICE` 29 | else 30 | FASTCGI_NICE=0 31 | fi 32 | 33 | if [ -e $FASTCGI_ENV ]; then 34 | export `cat $FASTCGI_ENV` 35 | fi 36 | 37 | if [ -z $LOGDIR ]; then 38 | LOGDIR=/var/log/fastcgi2 39 | fi 40 | 41 | [ -d "$LOGDIR" ] || mkdir -p $LOGDIR 2>/dev/null 42 | 43 | touch $LOCKER 44 | trap "rm $LOCKER 2>/dev/null" 0 45 | echo $$ > $LOCKER 46 | 47 | while [ -f $LOCKER ]; do 48 | echo " /usr/sbin/fastcgi-daemon2 --config=$FASTCGI_CONFIG" 49 | nice -n $FASTCGI_NICE /usr/sbin/fastcgi-daemon2 --config=$FASTCGI_CONFIG >> $LOGDIR/err.$1.log 2>&1 50 | echo "on `date` ::$THIS:: $THIS on `hostname` restarted" >>$LOGDIR/err.$1.log 51 | sleep $RDELAY 52 | done 53 | 54 | else 55 | echo "$FASTCGI_CONFIG don't found" 56 | exit 1 57 | fi 58 | -------------------------------------------------------------------------------- /file-logger/Makefile.am: -------------------------------------------------------------------------------- 1 | pkglib_LTLIBRARIES = fastcgi2-filelogger.la 2 | 3 | fastcgi2_filelogger_la_SOURCES = file_logger.cpp 4 | fastcgi2_filelogger_la_LIBADD = ../library/libfastcgi-daemon2.la 5 | fastcgi2_filelogger_la_LDFLAGS = -module -lpthread 6 | 7 | AM_CPPFLAGS = -I../include -I../config 8 | AM_CXXFLAGS = -pthread 9 | 10 | noinst_HEADERS = file_logger.h -------------------------------------------------------------------------------- /file-logger/file_logger.h: -------------------------------------------------------------------------------- 1 | #ifndef _FASTCGI_FILE_LOGGER_H_ 2 | #define _FASTCGI_FILE_LOGGER_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "fastcgi2/component.h" 10 | #include "fastcgi2/logger.h" 11 | 12 | namespace fastcgi 13 | { 14 | 15 | class FileLogger : virtual public Logger, virtual public Component { 16 | public: 17 | FileLogger(ComponentContext *context); 18 | ~FileLogger(); 19 | 20 | virtual void onLoad(); 21 | virtual void onUnload(); 22 | 23 | virtual void log(const Logger::Level level, const char *format, va_list args); 24 | private: 25 | virtual void rollOver(); 26 | 27 | private: 28 | // File name 29 | std::string filename_; 30 | 31 | // Open mode 32 | mode_t openMode_; 33 | 34 | // Time format specification 35 | std::string time_format_; 36 | 37 | bool print_level_; 38 | bool print_time_; 39 | 40 | // File descriptor 41 | int fd_; 42 | 43 | // Lock of file descriptor to avoid logrotate race-condition 44 | boost::mutex fdMutex_; 45 | 46 | 47 | // Writing queue. 48 | // All writes happens in separate thread. All someInternal methods just 49 | // push string into queue and signal conditional variable. 50 | 51 | // Logger is stopping. 52 | volatile bool stopping_; 53 | 54 | // Writing queue. 55 | std::vector queue_; 56 | 57 | // Condition and mutex for signalling. 58 | boost::condition queueCondition_; 59 | boost::mutex queueMutex_; 60 | 61 | // Writing thread. 62 | boost::thread writingThread_; 63 | 64 | 65 | void openFile(); 66 | void prepareFormat(char * buf, size_t size, const Logger::Level level, const char* format); 67 | 68 | void writingThread(); 69 | }; 70 | 71 | } 72 | 73 | #endif // _FASTCGI_FILE_LOGGER_H_ 74 | -------------------------------------------------------------------------------- /include/Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = fastcgi2 details 2 | 3 | -------------------------------------------------------------------------------- /include/details/Makefile.am: -------------------------------------------------------------------------------- 1 | noinst_HEADERS = component_context.h componentset.h config.h functors.h \ 2 | handler_context.h handlerset.h loader.h parser.h range.h requestimpl.h \ 3 | xml.h data_buffer_impl.h string_buffer.h server.h request_cache.h \ 4 | thread_pool.h request_thread_pool.h globals.h request_filter.h 5 | -------------------------------------------------------------------------------- /include/details/component_context.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_DETAILS_COMPONENT_CONTEXT_H_ 19 | #define _FASTCGI_DETAILS_COMPONENT_CONTEXT_H_ 20 | 21 | #include 22 | 23 | #include 24 | 25 | namespace fastcgi 26 | { 27 | 28 | class Config; 29 | class Globals; 30 | 31 | class ComponentContextImpl : public ComponentContext { 32 | public: 33 | ComponentContextImpl(const Globals *globals, const std::string &componentXPath); 34 | virtual ~ComponentContextImpl(); 35 | 36 | virtual const Config* getConfig() const; 37 | virtual std::string getComponentXPath() const; 38 | 39 | const Globals* globals() const; 40 | 41 | protected: 42 | virtual Component* findComponentInternal(const std::string &name) const; 43 | 44 | private: 45 | const Globals *globals_; 46 | std::string componentXPath_; 47 | }; 48 | 49 | } //namespace fastcgi 50 | 51 | #endif //_FASTCGI_DETAILS_COMPONENT_CONTEXT_H_ 52 | -------------------------------------------------------------------------------- /include/details/componentset.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_DETAILS_COMPONENTSET_H_ 19 | #define _FASTCGI_DETAILS_COMPONENTSET_H_ 20 | 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | namespace fastcgi 28 | { 29 | 30 | class Globals; 31 | class Loader; 32 | class Component; 33 | class ComponentContext; 34 | 35 | class ComponentSet : private boost::noncopyable 36 | { 37 | protected: 38 | struct ComponentContainer { 39 | ComponentContainer(); 40 | 41 | Component *component; 42 | ComponentContext *context; 43 | bool isLoadingStarted; 44 | }; 45 | typedef std::map ComponentMap; 46 | 47 | public: 48 | ComponentSet(); 49 | virtual ~ComponentSet(); 50 | 51 | void init(const Globals *globals); 52 | 53 | 54 | Component* find(const std::string &name) const; 55 | 56 | protected: 57 | void add(const std::string &name, const std::string &type, const std::string &componentXPath); 58 | 59 | void sendOnLoadToComponents(); 60 | void sendOnUnloadToComponents(); 61 | void sendOnLoad(const std::string &componentName, ComponentContainer &cont); 62 | bool isComponentLoaded(const std::string &componentName) const; 63 | 64 | private: 65 | ComponentMap components_; 66 | std::vector loadingStack_; 67 | const Globals *globals_; 68 | }; 69 | 70 | } // namespace fastcgi 71 | 72 | #endif // _FASTCGI_DETAILS_COMPONENTSET_H_ 73 | -------------------------------------------------------------------------------- /include/details/config.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_DETAILS_XML_CONFIG_H_ 19 | #define _FASTCGI_DETAILS_XML_CONFIG_H_ 20 | 21 | #include "details/xml.h" 22 | 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | #include 29 | 30 | #include 31 | 32 | namespace fastcgi 33 | { 34 | 35 | class XmlConfig : public Config 36 | { 37 | public: 38 | XmlConfig(const char *file); 39 | virtual ~XmlConfig(); 40 | 41 | virtual int asInt(const std::string &value) const; 42 | virtual int asInt(const std::string &value, int defval) const; 43 | 44 | virtual std::string asString(const std::string &value) const; 45 | virtual std::string asString(const std::string &value, const std::string &defval) const; 46 | 47 | virtual void subKeys(const std::string &value, std::vector &v) const; 48 | 49 | private: 50 | XmlConfig(const XmlConfig &); 51 | XmlConfig& operator = (const XmlConfig &); 52 | 53 | void findVariables(const XmlDocHelper &doc); 54 | void resolveVariables(std::string &val) const; 55 | const std::string& findVariable(const std::string &key) const; 56 | 57 | private: 58 | XmlDocHelper doc_; 59 | boost::regex regex_; 60 | std::map vars_; 61 | }; 62 | 63 | } // namespace fastcgi 64 | 65 | #endif // _FASTCGI_DETAILS_XML_CONFIG_H_ 66 | -------------------------------------------------------------------------------- /include/details/data_buffer_impl.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_DETAILS_DATA_BUFFER_IMPL_H_ 19 | #define _FASTCGI_DETAILS_DATA_BUFFER_IMPL_H_ 20 | 21 | #include 22 | #include 23 | 24 | namespace fastcgi 25 | { 26 | 27 | class DataBufferImpl { 28 | public: 29 | virtual ~DataBufferImpl() {}; 30 | virtual boost::uint64_t read(boost::uint64_t pos, char *data, boost::uint64_t len) = 0; 31 | virtual boost::uint64_t write(boost::uint64_t pos, const char *data, boost::uint64_t len) = 0; 32 | virtual char at(boost::uint64_t pos) = 0; 33 | virtual boost::uint64_t find(boost::uint64_t begin, boost::uint64_t end, const char* buf, boost::uint64_t len) = 0; 34 | virtual std::pair trim(boost::uint64_t begin, boost::uint64_t end) const = 0; 35 | virtual std::pair chunk(boost::uint64_t pos) const = 0; 36 | virtual std::pair segment(boost::uint64_t pos) const = 0; 37 | virtual boost::uint64_t size() const = 0; 38 | virtual void resize(boost::uint64_t size) = 0; 39 | virtual const std::string& filename() const = 0; 40 | virtual DataBufferImpl* getCopy() const = 0; 41 | }; 42 | 43 | } // namespace fastcgi 44 | 45 | #endif // _FASTCGI_DETAILS_DATA_BUFFER_IMPL_H_ 46 | -------------------------------------------------------------------------------- /include/details/functors.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_DETAILS_FUNCTORS_H_ 19 | #define _FASTCGI_DETAILS_FUNCTORS_H_ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "settings.h" 30 | #include "details/range.h" 31 | 32 | namespace fastcgi 33 | { 34 | 35 | struct CharCILess : public std::binary_function 36 | { 37 | bool operator () (char c, char target) const { 38 | return tolower(c) < tolower(target); 39 | } 40 | }; 41 | 42 | struct RangeCILess : public std::binary_function 43 | { 44 | bool operator() (const Range &range, const Range &target) const { 45 | return std::lexicographical_compare(range.begin(), range.end(), target.begin(), target.end(), CharCILess()); 46 | } 47 | }; 48 | 49 | #if defined(HAVE_GNUCXX_HASHMAP) || defined(HAVE_EXT_HASH_MAP) || defined(HAVE_STLPORT_HASHMAP) 50 | 51 | struct StringCIHash : public std::unary_function 52 | { 53 | boost::uint32_t operator () (const std::string &str) const { 54 | boost::uint32_t value = 0; 55 | for (std::string::const_iterator i = str.begin(), end = str.end(); i != end; ++i) { 56 | value += 5 * tolower(*i); 57 | } 58 | return value; 59 | } 60 | }; 61 | 62 | struct StringCIEqual : public std::binary_function 63 | { 64 | bool operator () (const std::string& str, const std::string& target) const { 65 | if (str.size() == target.size()) { 66 | return (strncasecmp(str.c_str(), target.c_str(), str.size()) == 0); 67 | } 68 | return false; 69 | } 70 | }; 71 | 72 | #else 73 | 74 | struct StringCILess : public std::binary_function 75 | { 76 | bool operator () (const std::string& str, const std::string& target) const { 77 | return std::lexicagraphical_compare(str.begin(), str.end(), target.begin(), target.end(), CharCILess()); 78 | } 79 | }; 80 | 81 | #endif 82 | 83 | } // namespace fastcgi 84 | 85 | #endif // _FASTCGI_DETAILS_FUNCTORS_H_ 86 | -------------------------------------------------------------------------------- /include/details/globals.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_DETAILS_GLOBALS_H_ 19 | #define _FASTCGI_DETAILS_GLOBALS_H_ 20 | 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | 27 | namespace fastcgi 28 | { 29 | 30 | class ComponentSet; 31 | class Config; 32 | class HandlerSet; 33 | class Loader; 34 | class Logger; 35 | class RequestsThreadPool; 36 | 37 | class Globals : private boost::noncopyable { 38 | public: 39 | Globals(const Config *config); 40 | virtual ~Globals(); 41 | 42 | const Config* config() const; 43 | 44 | typedef std::map > ThreadPoolMap; 45 | 46 | ComponentSet* components() const; 47 | HandlerSet* handlers() const; 48 | const ThreadPoolMap& pools() const; 49 | Loader* loader() const; 50 | Logger* logger() const; 51 | 52 | void stopThreadPools(); 53 | void joinThreadPools(); 54 | 55 | private: 56 | void initPools(); 57 | void initLogger(); 58 | void startThreadPools(); 59 | 60 | private: 61 | ThreadPoolMap pools_; 62 | const Config* config_; 63 | std::auto_ptr loader_; 64 | std::auto_ptr handlerSet_; 65 | std::auto_ptr componentSet_; 66 | Logger* logger_; 67 | }; 68 | 69 | } // namespace fastcgi 70 | 71 | #endif // _FASTCGI_DETAILS_GLOBALS_H_ 72 | -------------------------------------------------------------------------------- /include/details/handler_context.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_DETAILS_HANDLER_CONTEXT_H_ 19 | #define _FASTCGI_DETAILS_HANDLER_CONTEXT_H_ 20 | 21 | #include 22 | 23 | #include 24 | 25 | namespace fastcgi 26 | { 27 | 28 | class HandlerContextImpl : public HandlerContext { 29 | public: 30 | virtual boost::any getParam(const std::string &name) const; 31 | virtual void setParam(const std::string &name, const boost::any &value); 32 | 33 | private: 34 | typedef std::map ParamsMapType; 35 | ParamsMapType params_; 36 | }; 37 | 38 | } // namespace fastcgi 39 | 40 | #endif // _FASTCGI_DETAILS_HANDLER_CONTEXT_H_ 41 | -------------------------------------------------------------------------------- /include/details/handlerset.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_DETAILS_HANDLERSET_H_ 19 | #define _FASTCGI_DETAILS_HANDLERSET_H_ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | 29 | namespace fastcgi 30 | { 31 | 32 | class Config; 33 | class ComponentSet; 34 | class Handler; 35 | class Request; 36 | class RequestFilter; 37 | 38 | class HandlerSet : private boost::noncopyable 39 | { 40 | public: 41 | struct HandlerDescription { 42 | typedef std::vector > > FilterArray; 43 | FilterArray filters; 44 | std::vector handlers; 45 | std::string poolName; 46 | std::string id; 47 | }; 48 | typedef std::vector HandlerArray; 49 | 50 | public: 51 | HandlerSet(); 52 | virtual ~HandlerSet(); 53 | 54 | void init(const Config *config, const ComponentSet *componentSet); 55 | 56 | const HandlerSet::HandlerDescription* findURIHandler(const Request *request) const; 57 | void findPoolHandlers(const std::string &poolName, std::set &handlers) const; 58 | std::set getPoolsNeeded() const; 59 | 60 | private: 61 | HandlerArray handlers_; 62 | }; 63 | 64 | } // namespace fastcgi 65 | 66 | #endif // _FASTCGI_DETAILS_HANDLERSET_H_ 67 | -------------------------------------------------------------------------------- /include/details/loader.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_DETAILS_LOADER_H_ 19 | #define _FASTCGI_DETAILS_LOADER_H_ 20 | 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | 27 | #include 28 | 29 | namespace fastcgi 30 | { 31 | 32 | class Config; 33 | class ComponentFactory; 34 | 35 | class Loader : private boost::noncopyable 36 | { 37 | public: 38 | Loader(); 39 | virtual ~Loader(); 40 | 41 | virtual void init(const Config *config); 42 | virtual ComponentFactory *findComponentFactory(const std::string &type) const; 43 | 44 | protected: 45 | virtual void load(const char *name, const char *path); 46 | void checkLoad(const char *err); 47 | 48 | private: 49 | std::vector handles_; 50 | FactoryMap factories_; 51 | }; 52 | 53 | } // namespace fastcgi 54 | 55 | #endif // _FASTCGI_DETAILS_LOADER_H_ 56 | -------------------------------------------------------------------------------- /include/details/parser.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_DETAILS_PARSER_H_ 19 | #define _FASTCGI_DETAILS_PARSER_H_ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "settings.h" 28 | #include "fastcgi2/util.h" 29 | #include "details/range.h" 30 | #include "details/functors.h" 31 | 32 | namespace fastcgi 33 | { 34 | 35 | class File; 36 | class Logger; 37 | class RequestImpl; 38 | 39 | class Parser : private boost::noncopyable { 40 | public: 41 | static const char* statusToString(short status); 42 | static std::string getBoundary(const Range &range); 43 | 44 | static void addCookie(RequestImpl *req, const Range &range); 45 | static void addHeader(RequestImpl *req, const Range &key, const Range &value); 46 | 47 | static void parse(RequestImpl *req, char *env[], Logger* logger); 48 | static void parseCookies(RequestImpl *req, const Range &range); 49 | 50 | static void parsePart(RequestImpl *req, DataBuffer part); 51 | static void parseLine(DataBuffer line, DataBuffer &name, DataBuffer &filename, DataBuffer &type); 52 | static void parseMultipart(RequestImpl *req, DataBuffer data, const std::string &boundary); 53 | 54 | template static bool has(const Map &m, const std::string &key); 55 | template static void keys(const Map &m, std::vector &v); 56 | template static const std::string& get(const Map &m, const std::string &key); 57 | 58 | static std::string normalizeInputHeaderName(const Range &range); 59 | static std::string normalizeOutputHeaderName(const std::string &name); 60 | 61 | static const Range RETURN_N_RANGE; 62 | static const Range RETURN_RN_RANGE; 63 | 64 | static const Range EMPTY_LINE_NN_RANGE; 65 | static const Range EMPTY_LINE_RNRN_RANGE; 66 | 67 | static const Range NAME_RANGE; 68 | static const Range FILENAME_RANGE; 69 | 70 | static const Range HEADER_RANGE; 71 | static const Range COOKIE_RANGE; 72 | static const Range CONTENT_TYPE_RANGE; 73 | }; 74 | 75 | template inline bool 76 | Parser::has(const Map &m, const std::string &key) { 77 | return m.find(key) != m.end(); 78 | } 79 | 80 | template inline void 81 | Parser::keys(const Map &m, std::vector &v) { 82 | 83 | std::vector tmp; 84 | tmp.reserve(m.size()); 85 | 86 | for (typename Map::const_iterator i = m.begin(), end = m.end(); i != end; ++i) { 87 | tmp.push_back(i->first); 88 | } 89 | v.swap(tmp); 90 | } 91 | 92 | template inline const std::string& 93 | Parser::get(const Map &m, const std::string &key) { 94 | typename Map::const_iterator i = m.find(key); 95 | return (m.end() == i) ? StringUtils::EMPTY_STRING : i->second; 96 | } 97 | 98 | } // namespace fastcgi 99 | 100 | #endif //_FASTCGI_DETAILS_PARSER_H_ 101 | -------------------------------------------------------------------------------- /include/details/range.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_DETAILS_RANGE_H_ 19 | #define _FASTCGI_DETAILS_RANGE_H_ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | namespace fastcgi 30 | { 31 | 32 | class Range 33 | { 34 | public: 35 | typedef std::size_t size_type; 36 | 37 | Range() : begin_(NULL), end_(NULL) { 38 | } 39 | 40 | Range(const char* begin, const char* end) : begin_(begin), end_(end) { 41 | assert(begin <= end); 42 | } 43 | 44 | const char* end() const { 45 | return end_; 46 | } 47 | 48 | const char* begin() const { 49 | return begin_; 50 | } 51 | 52 | bool empty() const { 53 | return begin_ == end_; 54 | } 55 | 56 | Range::size_type size() const { 57 | return end_ - begin_; 58 | } 59 | 60 | char operator[] (Range::size_type i) const { 61 | assert(i < size()); 62 | return begin_[i]; 63 | } 64 | 65 | Range trim() const { 66 | const char* begin = begin_; 67 | const char* end = end_; 68 | while (begin != end && isspace(*begin)) { 69 | ++begin; 70 | } 71 | while (begin != end && isspace(*(end - 1))) { 72 | --end; 73 | } 74 | return Range(begin, end); 75 | } 76 | 77 | Range trimn(int b, int e) const { 78 | const char* begin = begin_; 79 | const char* end = end_; 80 | while (begin != end && b--) { 81 | ++begin; 82 | } 83 | while (begin != end && e--) { 84 | --end; 85 | } 86 | return Range(begin, end); 87 | } 88 | 89 | const char* find(const Range& substr) const { 90 | if (substr.size() == 1) { 91 | return find(*substr.begin()); 92 | } 93 | else { 94 | return std::search(begin(), end(), substr.begin(), substr.end()); 95 | } 96 | } 97 | 98 | const char* find(char ch) const { 99 | return std::find(begin(), end(), ch); 100 | } 101 | 102 | bool split(Range const& delim, Range& first, Range& second) const { 103 | return doSplit(find(delim), delim.size(), first, second); 104 | } 105 | 106 | bool split(const char delim, Range& first, Range& second) const { 107 | return doSplit(find(delim), 1, first, second); 108 | } 109 | 110 | bool endsWith(const Range &range) { 111 | if (range.size() <= size()) { 112 | return memcmp(end_ - range.size(), range.begin(), range.size()) == 0; 113 | } 114 | return false; 115 | } 116 | 117 | bool startsWith(const Range &range) const { 118 | if (range.size() <= size()) { 119 | return memcmp(begin_, range.begin_, range.size()) == 0; 120 | } 121 | return false; 122 | } 123 | 124 | bool operator < (const Range &range) const { 125 | return std::lexicographical_compare(begin_, end_, range.begin_, range.end_); 126 | } 127 | 128 | bool operator > (const Range &range) const { 129 | return range.operator < (*this); 130 | } 131 | 132 | bool operator == (const Range &range) const { 133 | if (size() == range.size()) { 134 | return memcmp(begin_, range.begin_, size()) == 0; 135 | } 136 | return false; 137 | } 138 | 139 | bool operator != (const Range &range) const { 140 | return !operator == (range); 141 | } 142 | 143 | static Range fromChars(const char* str) { 144 | return Range(str, str + strlen(str)); 145 | } 146 | 147 | static Range fromString(const std::string& str) { 148 | return Range(str.c_str(), str.c_str() + str.size()); 149 | } 150 | 151 | static Range fromVector(const std::vector& vec) { 152 | return Range(&vec[0], &vec[0] + vec.size()); 153 | } 154 | 155 | std::string toString() const { 156 | return (NULL == begin()) ? std::string() : std::string(begin_, end_); 157 | } 158 | 159 | private: 160 | 161 | bool doSplit(const char* e, size_type size, Range& first, Range& second) const { 162 | const char *begin = begin_; 163 | const char *end = end_; 164 | first = Range(begin, e); 165 | if (e != end) { 166 | second = Range(e + size, end); 167 | return true; 168 | } 169 | else { 170 | second = Range(end, end); 171 | return false; 172 | } 173 | } 174 | 175 | private: 176 | const char *begin_, *end_; 177 | }; 178 | 179 | } // namespace fastcgi 180 | 181 | #endif // _FASTCGI_DETAILS_RANGE_H_ 182 | -------------------------------------------------------------------------------- /include/details/request_cache.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_DETAILS_REQUEST_CACHE_H_ 19 | #define _FASTCGI_DETAILS_REQUEST_CACHE_H_ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | namespace fastcgi 26 | { 27 | 28 | class DataBuffer; 29 | class Request; 30 | 31 | class RequestCache : private boost::noncopyable { 32 | public: 33 | RequestCache() {}; 34 | virtual ~RequestCache() {}; 35 | 36 | virtual DataBuffer create() = 0; 37 | virtual void save(Request *request, time_t delay) = 0; 38 | virtual boost::uint32_t minPostSize() const = 0; 39 | }; 40 | 41 | } // namespace fastcgi 42 | 43 | #endif // _FASTCGI_DETAILS_REQUEST_CACHE_H_ 44 | -------------------------------------------------------------------------------- /include/details/request_filter.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_DETAILS_REQUEST_FILTER_H_ 19 | #define _FASTCGI_DETAILS_REQUEST_FILTER_H_ 20 | 21 | #include 22 | 23 | #include 24 | 25 | 26 | namespace fastcgi 27 | { 28 | 29 | class Request; 30 | 31 | class RequestFilter { 32 | public: 33 | virtual bool check(const Request *request) const = 0; 34 | }; 35 | 36 | class RegexFilter { 37 | public: 38 | RegexFilter(const std::string ®ex); 39 | ~RegexFilter(); 40 | 41 | bool check(const std::string &value) const; 42 | private: 43 | boost::regex regex_; 44 | }; 45 | 46 | class UrlFilter : public RequestFilter { 47 | public: 48 | UrlFilter(const std::string ®ex); 49 | ~UrlFilter(); 50 | 51 | virtual bool check(const Request *request) const; 52 | private: 53 | RegexFilter regex_; 54 | }; 55 | 56 | class HostFilter : public RequestFilter { 57 | public: 58 | HostFilter(const std::string ®ex); 59 | ~HostFilter(); 60 | 61 | virtual bool check(const Request *request) const; 62 | private: 63 | RegexFilter regex_; 64 | }; 65 | 66 | class PortFilter : public RequestFilter { 67 | public: 68 | PortFilter(const std::string ®ex); 69 | ~PortFilter(); 70 | 71 | virtual bool check(const Request *request) const; 72 | private: 73 | RegexFilter regex_; 74 | }; 75 | 76 | class AddressFilter : public RequestFilter { 77 | public: 78 | AddressFilter(const std::string ®ex); 79 | ~AddressFilter(); 80 | 81 | virtual bool check(const Request *request) const; 82 | private: 83 | RegexFilter regex_; 84 | }; 85 | 86 | class RefererFilter : public RequestFilter { 87 | public: 88 | RefererFilter(const std::string ®ex); 89 | ~RefererFilter(); 90 | 91 | virtual bool check(const Request *request) const; 92 | private: 93 | RegexFilter regex_; 94 | }; 95 | 96 | class ParamFilter : public RequestFilter { 97 | public: 98 | ParamFilter(const std::string &name, const std::string ®ex); 99 | ~ParamFilter(); 100 | 101 | virtual bool check(const Request *request) const; 102 | private: 103 | std::string name_; 104 | RegexFilter regex_; 105 | }; 106 | 107 | } // namespace fastcgi 108 | 109 | #endif // _FASTCGI_DETAILS_REQUEST_FILTER_H_ 110 | -------------------------------------------------------------------------------- /include/details/request_thread_pool.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_DETAILS_REQUEST_THREAD_POOL_H_ 19 | #define _FASTCGI_DETAILS_REQUEST_THREAD_POOL_H_ 20 | 21 | #include 22 | #include 23 | 24 | #include "details/response_time_statistics.h" 25 | #include "details/thread_pool.h" 26 | 27 | namespace fastcgi { 28 | 29 | class Handler; 30 | class Logger; 31 | 32 | struct RequestTask { 33 | boost::shared_ptr request; 34 | std::vector handlers; 35 | boost::shared_ptr request_stream; 36 | boost::uint64_t start; 37 | }; 38 | 39 | class RequestsThreadPool : public ThreadPool { 40 | public: 41 | RequestsThreadPool(const unsigned threadsNumber, const unsigned queueLength, fastcgi::Logger *logger); 42 | RequestsThreadPool(const unsigned threadsNumber, const unsigned queueLength, boost::uint64_t delay, 43 | fastcgi::Logger *logger); 44 | virtual ~RequestsThreadPool(); 45 | virtual void handleTask(RequestTask task); 46 | boost::uint64_t delay() const; 47 | private: 48 | fastcgi::Logger *logger_; 49 | boost::uint64_t delay_; 50 | }; 51 | 52 | } // namespace fastcgi 53 | 54 | #endif // _FASTCGI_DETAILS_REQUEST_THREAD_POOL_H_ 55 | -------------------------------------------------------------------------------- /include/details/response_time_statistics.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_DETAILS_RESPONSE_TIME_STATISTICS_H_ 19 | #define _FASTCGI_DETAILS_RESPONSE_TIME_STATISTICS_H_ 20 | 21 | #include 22 | 23 | #include 24 | 25 | namespace fastcgi 26 | { 27 | 28 | class ResponseTimeStatistics { 29 | public: 30 | ResponseTimeStatistics(); 31 | virtual ~ResponseTimeStatistics(); 32 | 33 | virtual void add(const std::string &handler, unsigned short status, boost::uint64_t time) = 0; 34 | }; 35 | 36 | } // namespace fastcgi 37 | 38 | #endif // _FASTCGI_DETAILS_RESPONSE_TIME_STATISTICS_H_ 39 | -------------------------------------------------------------------------------- /include/details/server.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_DETAILS_SERVER_H_ 19 | #define _FASTCGI_DETAILS_SERVER_H_ 20 | 21 | #include 22 | 23 | #include "details/handlerset.h" 24 | #include "details/request_thread_pool.h" 25 | 26 | namespace fastcgi 27 | { 28 | 29 | class Globals; 30 | 31 | class Server : private boost::noncopyable { 32 | public: 33 | Server(); 34 | virtual ~Server(); 35 | 36 | protected: 37 | virtual void handleRequest(RequestTask task); 38 | virtual const Globals* globals() const = 0; 39 | virtual Logger* logger() const = 0; 40 | 41 | void handleRequestInternal(const HandlerSet::HandlerDescription* handler, RequestTask task); 42 | const HandlerSet::HandlerDescription* getHandler(RequestTask task) const; 43 | }; 44 | 45 | } // namespace fastcgi 46 | 47 | #endif // _FASTCGI_DETAILS_SERVER_H_ 48 | -------------------------------------------------------------------------------- /include/details/string_buffer.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_DETAILS_STRING_BUFFER_H_ 19 | #define _FASTCGI_DETAILS_STRING_BUFFER_H_ 20 | 21 | #include 22 | #include 23 | 24 | #include 25 | 26 | #include "fastcgi2/data_buffer.h" 27 | #include "details/data_buffer_impl.h" 28 | 29 | namespace fastcgi 30 | { 31 | 32 | class StringBuffer : public DataBufferImpl { 33 | public: 34 | StringBuffer(const char *data, boost::uint64_t size); 35 | virtual ~StringBuffer(); 36 | virtual boost::uint64_t read(boost::uint64_t pos, char *data, boost::uint64_t len); 37 | virtual boost::uint64_t write(boost::uint64_t pos, const char *data, boost::uint64_t len); 38 | virtual char at(boost::uint64_t pos); 39 | virtual boost::uint64_t find(boost::uint64_t begin, boost::uint64_t end, const char* buf, boost::uint64_t len); 40 | virtual std::pair trim(boost::uint64_t begin, boost::uint64_t end) const; 41 | virtual std::pair chunk(boost::uint64_t pos) const; 42 | virtual std::pair segment(boost::uint64_t pos) const; 43 | virtual boost::uint64_t size() const; 44 | virtual void resize(boost::uint64_t size); 45 | virtual const std::string& filename() const; 46 | virtual DataBufferImpl* getCopy() const; 47 | private: 48 | boost::shared_ptr > data_; 49 | }; 50 | 51 | } // namespace fastcgi 52 | 53 | #endif // _FASTCGI_DETAILS_STRING_BUFFER_H_ 54 | -------------------------------------------------------------------------------- /include/details/xml.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_DETAILS_XML_H_ 19 | #define _FASTCGI_DETAILS_XML_H_ 20 | 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | 27 | namespace fastcgi 28 | { 29 | 30 | class XmlUtils : private boost::noncopyable 31 | { 32 | public: 33 | XmlUtils(); 34 | virtual ~XmlUtils(); 35 | 36 | static void throwUnless(bool value); 37 | static const char* value(xmlAttrPtr node); 38 | static const char* value(xmlNodePtr node); 39 | static const char* attrValue(xmlNodePtr node, const char *name); 40 | }; 41 | 42 | struct XmlDocCleaner 43 | { 44 | static void clean(xmlDocPtr doc); 45 | }; 46 | 47 | struct XmlNodeCleaner 48 | { 49 | static void clean(xmlNodePtr node); 50 | }; 51 | 52 | struct XmlXPathObjectCleaner 53 | { 54 | static void clean(xmlXPathObjectPtr obj); 55 | }; 56 | 57 | struct XmlXPathContextCleaner 58 | { 59 | static void clean(xmlXPathContextPtr ctx); 60 | }; 61 | 62 | typedef Helper XmlDocHelper; 63 | typedef Helper XmlNodeHelper; 64 | typedef Helper XmlXPathObjectHelper; 65 | typedef Helper XmlXPathContextHelper; 66 | 67 | } // namespace fastcgi 68 | 69 | #endif // _FASTCGI_DETAILS_XML_H_ 70 | -------------------------------------------------------------------------------- /include/fastcgi2/Makefile.am: -------------------------------------------------------------------------------- 1 | pkginclude_HEADERS = component.h component_factory.h config.h cookie.h except.h handler.h \ 2 | helpers.h logger.h request.h stream.h util.h data_buffer.h request_io_stream.h 3 | -------------------------------------------------------------------------------- /include/fastcgi2/component.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_COMPONENT_H_ 19 | #define _FASTCGI_COMPONENT_H_ 20 | 21 | #include 22 | #include 23 | 24 | namespace fastcgi 25 | { 26 | 27 | class Config; 28 | class Component; 29 | 30 | class ComponentContext : private boost::noncopyable 31 | { 32 | public: 33 | virtual ~ComponentContext(); 34 | 35 | virtual const Config* getConfig() const = 0; 36 | virtual std::string getComponentXPath() const = 0; 37 | 38 | template 39 | T* findComponent(const std::string &name) { 40 | return dynamic_cast(findComponentInternal(name)); 41 | } 42 | 43 | protected: 44 | virtual Component* findComponentInternal(const std::string &name) const = 0; 45 | }; 46 | 47 | class Component : private boost::noncopyable 48 | { 49 | public: 50 | Component(ComponentContext *context); 51 | virtual ~Component(); 52 | 53 | virtual void onLoad() = 0; 54 | virtual void onUnload() = 0; 55 | 56 | protected: 57 | ComponentContext* context(); 58 | const ComponentContext* context() const; 59 | 60 | private: 61 | ComponentContext *context_; 62 | }; 63 | 64 | } // namespace fastcgi 65 | 66 | #endif // _FASTCGI_COMPONENT_H_ 67 | -------------------------------------------------------------------------------- /include/fastcgi2/component_factory.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_COMPONENT_FACTORY_H_ 19 | #define _FASTCGI_COMPONENT_FACTORY_H_ 20 | 21 | #include 22 | #include 23 | 24 | #include 25 | 26 | namespace fastcgi 27 | { 28 | 29 | class Component; 30 | class ComponentFactory; 31 | class ComponentContext; 32 | 33 | typedef std::map FactoryMap; 34 | 35 | class ComponentFactory : private boost::noncopyable 36 | { 37 | public: 38 | ComponentFactory(); 39 | virtual ~ComponentFactory(); 40 | virtual Component* createComponent(ComponentContext *context) = 0; 41 | }; 42 | 43 | template 44 | class DefaultComponentFactory : public ComponentFactory { 45 | public: 46 | virtual Component* createComponent(ComponentContext *context) { 47 | return new T(context); 48 | } 49 | 50 | virtual ~DefaultComponentFactory() { 51 | } 52 | }; 53 | 54 | } // namespace fastcgi 55 | 56 | typedef fastcgi::FactoryMap* (*FastcgiGetFactoryMapFunction)(); 57 | 58 | #if __GNUC__ >= 4 59 | # define FCGIDAEMON_DSO_GLOBALLY_VISIBLE \ 60 | __attribute__ ((visibility ("default"))) 61 | #else 62 | # define FCGIDAEMON_DSO_GLOBALLY_VISIBLE 63 | #endif 64 | 65 | #define FCGIDAEMON_REGISTER_FACTORIES_BEGIN() \ 66 | extern "C" FCGIDAEMON_DSO_GLOBALLY_VISIBLE \ 67 | const fastcgi::FactoryMap* getFactoryMap() { \ 68 | static fastcgi::FactoryMap m; 69 | 70 | #define FCGIDAEMON_ADD_DEFAULT_FACTORY(name, Type) \ 71 | m.insert(std::make_pair((name), new fastcgi::DefaultComponentFactory)); 72 | 73 | #define FCGIDAEMON_ADD_FACTORY(name, factory) \ 74 | m.insert(std::make_pair((name), (factory))); 75 | 76 | #define FCGIDAEMON_REGISTER_FACTORIES_END() \ 77 | return &m; \ 78 | } 79 | 80 | #endif //_FASTCGI_COMPONENT_FACTORY_H_ 81 | 82 | -------------------------------------------------------------------------------- /include/fastcgi2/config.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_CONFIG_H_ 19 | #define _FASTCGI_CONFIG_H_ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | namespace fastcgi 31 | { 32 | 33 | typedef std::ostream& (*HelpFunc)(std::ostream &stream); 34 | 35 | class Config : private boost::noncopyable { 36 | public: 37 | Config(); 38 | virtual ~Config(); 39 | 40 | virtual int asInt(const std::string &value) const = 0; 41 | virtual int asInt(const std::string &value, int defval) const = 0; 42 | 43 | virtual std::string asString(const std::string &value) const = 0; 44 | virtual std::string asString(const std::string &value, const std::string &defval) const = 0; 45 | 46 | virtual void subKeys(const std::string &value, std::vector &v) const = 0; 47 | 48 | static std::auto_ptr create(const char *file); 49 | static std::auto_ptr create(int &argc, char *argv[], HelpFunc func = NULL); 50 | 51 | const std::string& filename() const; 52 | 53 | protected: 54 | void setFilename(const std::string &name); 55 | 56 | private: 57 | Config(const Config &); 58 | Config& operator = (const Config &); 59 | 60 | private: 61 | std::string filename_; 62 | }; 63 | 64 | } // namespace fastcgi 65 | 66 | #endif // _FASTCGI_CONFIG_H_ 67 | -------------------------------------------------------------------------------- /include/fastcgi2/cookie.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_COOKIE_H_ 19 | #define _FASTCGI_COOKIE_H_ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | namespace fastcgi 26 | { 27 | 28 | class Cookie { 29 | public: 30 | Cookie(const std::string &name, const std::string &value); 31 | Cookie(const Cookie &cookie); 32 | virtual ~Cookie(); 33 | Cookie& operator=(const Cookie &cookie); 34 | bool operator < (const Cookie &cookie) const; 35 | 36 | const std::string& name() const; 37 | const std::string& value() const; 38 | 39 | bool secure() const; 40 | void secure(bool value); 41 | 42 | time_t expires() const; 43 | void expires(time_t value); 44 | 45 | void permanent(bool value); 46 | bool permanent() const; 47 | 48 | void httpOnly(bool value); 49 | bool httpOnly() const; 50 | 51 | const std::string& path() const; 52 | void path(const std::string &value); 53 | 54 | const std::string& domain() const; 55 | void domain(const std::string &value); 56 | 57 | std::string toString() const; 58 | 59 | void urlEncode(bool value); 60 | 61 | private: 62 | class CookieData; 63 | std::auto_ptr data_; 64 | }; 65 | 66 | } // namespace fastcgi 67 | 68 | #endif // _FASTCGI_COOKIE_H_ 69 | -------------------------------------------------------------------------------- /include/fastcgi2/data_buffer.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_DATA_BUFFER_H_ 19 | #define _FASTCGI_DATA_BUFFER_H_ 20 | 21 | #include 22 | 23 | #include 24 | #include 25 | 26 | namespace fastcgi 27 | { 28 | 29 | /** 30 | * Chunked storage with shared internal buffer 31 | */ 32 | 33 | class DataBufferImpl; 34 | 35 | class DataBuffer { 36 | public: 37 | static DataBuffer create(const char *data, boost::uint64_t size); 38 | static DataBuffer create(DataBufferImpl *impl); 39 | 40 | DataBuffer(); 41 | DataBuffer(DataBuffer buffer, boost::uint64_t begin, boost::uint64_t end); 42 | 43 | char at(boost::uint64_t pos) const; 44 | bool isNil() const; 45 | bool empty() const; 46 | boost::uint64_t size() const; 47 | void resize(boost::uint64_t size); 48 | 49 | class SegmentIterator; 50 | friend class SegmentIterator; 51 | 52 | SegmentIterator begin() const; 53 | SegmentIterator end() const; 54 | 55 | DataBuffer trim() const; 56 | DataBuffer trimn(boost::uint64_t b, boost::uint64_t e) const; 57 | bool split(const std::string &delim, DataBuffer &first, DataBuffer &second) const; 58 | bool split(char delim, DataBuffer &first, DataBuffer &second) const; 59 | bool startsWith(const std::string &data) const; 60 | bool startsWithCI(const std::string &data) const; 61 | bool endsWith(const std::string &data) const; 62 | bool endsWithCI(const std::string &data) const; 63 | void toString(std::string &str) const; 64 | 65 | boost::uint64_t read(boost::uint64_t pos, char *data, boost::uint64_t len); 66 | boost::uint64_t write(boost::uint64_t pos, const char *data, boost::uint64_t len); 67 | 68 | boost::uint64_t beginIndex() const; 69 | boost::uint64_t endIndex() const; 70 | 71 | DataBufferImpl* impl() const; 72 | 73 | private: 74 | void checkIndex(boost::uint64_t index) const; 75 | boost::uint64_t find(boost::uint64_t pos, const char* buf, boost::uint64_t len) const; 76 | 77 | private: 78 | boost::shared_ptr data_; 79 | boost::uint64_t begin_; 80 | boost::uint64_t end_; 81 | }; 82 | 83 | class DataBuffer::SegmentIterator { 84 | public: 85 | SegmentIterator(); 86 | std::pair operator*() const; 87 | std::pair* operator->() const; 88 | SegmentIterator& operator++(); 89 | SegmentIterator operator++(int); 90 | SegmentIterator& operator--(); 91 | SegmentIterator operator--(int); 92 | private: 93 | friend class DataBuffer; 94 | friend bool operator==(const SegmentIterator &lhs, const SegmentIterator &rhs); 95 | friend bool operator!=(const SegmentIterator &lhs, const SegmentIterator &rhs); 96 | SegmentIterator(const DataBuffer &buffer); // begin iterator 97 | DataBufferImpl* impl() const; 98 | private: 99 | DataBuffer buffer_; 100 | boost::uint64_t pos_begin_; 101 | boost::uint64_t pos_end_; 102 | mutable std::pair data_; 103 | }; 104 | 105 | bool operator==(const DataBuffer::SegmentIterator &lhs, const DataBuffer::SegmentIterator &rhs); 106 | bool operator!=(const DataBuffer::SegmentIterator &lhs, const DataBuffer::SegmentIterator &rhs); 107 | 108 | } // namespace fastcgi 109 | 110 | #endif // _FASTCGI_DATA_BUFFER_H_ 111 | -------------------------------------------------------------------------------- /include/fastcgi2/except.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_EXCEPT_H_ 19 | #define _FASTCGI_EXCEPT_H_ 20 | 21 | #include 22 | 23 | namespace fastcgi 24 | { 25 | 26 | class HttpException : public std::exception 27 | { 28 | public: 29 | HttpException(unsigned short status); 30 | virtual ~HttpException() throw (); 31 | 32 | unsigned short status() const; 33 | virtual const char* what() const throw (); 34 | 35 | private: 36 | unsigned short status_; 37 | }; 38 | 39 | class NotFound : public HttpException 40 | { 41 | public: 42 | NotFound(); 43 | }; 44 | 45 | class BadMethod : public HttpException 46 | { 47 | public: 48 | BadMethod(const char *reason); 49 | virtual const char* reason() const; 50 | private: 51 | char reason_[256]; 52 | }; 53 | 54 | class InternalError : public HttpException 55 | { 56 | public: 57 | InternalError(); 58 | }; 59 | 60 | } // namespace fastcgi 61 | 62 | #endif // _FASTCGI_EXCEPT_H_ 63 | -------------------------------------------------------------------------------- /include/fastcgi2/handler.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_HANDLER_H_ 19 | #define _FASTCGI_HANDLER_H_ 20 | 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | namespace fastcgi 29 | { 30 | 31 | class Request; 32 | 33 | class HandlerContext { 34 | public: 35 | virtual ~HandlerContext(); 36 | 37 | virtual boost::any getParam(const std::string &name) const = 0; 38 | virtual void setParam(const std::string &name, const boost::any &value) = 0; 39 | }; 40 | 41 | class Handler : private boost::noncopyable 42 | { 43 | public: 44 | Handler(); 45 | virtual ~Handler(); 46 | 47 | virtual void onThreadStart(); 48 | virtual void handleRequest(Request *req, HandlerContext *context) = 0; 49 | }; 50 | 51 | } // namespace fastcgi 52 | 53 | #endif // _FASTCGI_HANDLER_H_ 54 | -------------------------------------------------------------------------------- /include/fastcgi2/helpers.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_HELPERS_H_ 19 | #define _FASTCGI_HELPERS_H_ 20 | 21 | #include 22 | #include 23 | 24 | namespace fastcgi 25 | { 26 | 27 | template 28 | class Helper 29 | { 30 | public: 31 | Helper() throw (); 32 | explicit Helper(Type tptr) throw (); 33 | 34 | Helper(const Helper &h) throw (); 35 | Helper& operator = (const Helper &h) throw (); 36 | 37 | ~Helper() throw (); 38 | 39 | Type get() const throw (); 40 | Type operator -> () const throw (); 41 | 42 | Type release() throw (); 43 | void reset(Type tptr) throw (); 44 | 45 | private: 46 | Type releaseInternal() const throw (); 47 | 48 | private: 49 | mutable Type tptr_; 50 | }; 51 | 52 | template 53 | Helper::Helper() throw () : 54 | tptr_(NULL) 55 | { 56 | } 57 | 58 | template 59 | Helper::Helper(Type tptr) throw () : 60 | tptr_(tptr) 61 | { 62 | } 63 | 64 | template 65 | Helper::Helper(const Helper &h) throw () : 66 | tptr_(NULL) 67 | { 68 | std::swap(tptr_, h.tptr_); 69 | assert(NULL == h.get()); 70 | } 71 | 72 | template Helper& 73 | Helper::operator = (const Helper &h) throw () { 74 | if (&h != this) { 75 | reset(h.releaseInternal()); 76 | assert(NULL == h.get()); 77 | } 78 | return *this; 79 | } 80 | 81 | template inline 82 | Helper::~Helper() throw () { 83 | reset(NULL); 84 | } 85 | 86 | template Type 87 | Helper::get() const throw () { 88 | return tptr_; 89 | } 90 | 91 | template Type 92 | Helper::operator -> () const throw () { 93 | assert(NULL != tptr_); 94 | return tptr_; 95 | } 96 | 97 | template Type 98 | Helper::release() throw () { 99 | return releaseInternal(); 100 | } 101 | 102 | template void 103 | Helper::reset(Type tptr) throw () { 104 | if (NULL != tptr_) { 105 | Clean::clean(tptr_); 106 | } 107 | tptr_ = tptr; 108 | } 109 | 110 | template Type 111 | Helper::releaseInternal() const throw () { 112 | Type ptr = NULL; 113 | std::swap(ptr, tptr_); 114 | return ptr; 115 | } 116 | 117 | } // namespace fastcgi 118 | 119 | #endif // _FASTCGI_HELPERS_H_ 120 | -------------------------------------------------------------------------------- /include/fastcgi2/logger.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_LOGGER_H_ 19 | #define _FASTCGI_LOGGER_H_ 20 | 21 | #include 22 | #include 23 | 24 | namespace fastcgi 25 | { 26 | 27 | class Logger : private boost::noncopyable 28 | { 29 | public: 30 | enum Level { 31 | DEBUG, INFO, ERROR, EMERGENCY 32 | }; 33 | 34 | public: 35 | Logger(); 36 | virtual ~Logger(); 37 | 38 | void exiting(const char *function); 39 | void entering(const char *function); 40 | 41 | Level getLevel() const; 42 | void setLevel(const Level level); 43 | 44 | static Level stringToLevel(const std::string &); 45 | static std::string levelToString(const Level); 46 | 47 | virtual void info(const char *format, ...); 48 | virtual void debug(const char *format, ...); 49 | virtual void error(const char *format, ...); 50 | virtual void emerg(const char *format, ...); 51 | 52 | virtual void log(const Level level, const char *format, va_list args) = 0; 53 | 54 | protected: 55 | virtual void setLevelInternal(const Level level); 56 | virtual void rollOver(); 57 | 58 | private: 59 | Level level_; 60 | }; 61 | 62 | class LoggerRequestId 63 | { 64 | public: 65 | LoggerRequestId(); 66 | virtual ~LoggerRequestId(); 67 | 68 | virtual void setRequestId(const std::string &id) = 0; 69 | virtual std::string getRequestId() = 0; 70 | }; 71 | 72 | 73 | class BulkLogger : public Logger { 74 | public: 75 | BulkLogger(); 76 | 77 | protected: 78 | virtual void log(const Level level, const char *format, va_list args); 79 | }; 80 | 81 | } // namespace fastcgi 82 | 83 | #endif // _FASTCGI_LOGGER_H_ 84 | -------------------------------------------------------------------------------- /include/fastcgi2/request.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_REQUEST_H_ 19 | #define _FASTCGI_REQUEST_H_ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | #include 28 | 29 | namespace fastcgi 30 | { 31 | 32 | class Cookie; 33 | class Logger; 34 | class RequestCache; 35 | class RequestIOStream; 36 | class RequestImpl; 37 | 38 | class Request : private boost::noncopyable { 39 | public: 40 | Request(Logger *logger, RequestCache *cache); 41 | ~Request(); 42 | 43 | unsigned short getServerPort() const; 44 | const std::string& getHost() const; 45 | const std::string& getServerAddr() const; 46 | 47 | const std::string& getPathInfo() const; 48 | const std::string& getPathTranslated() const; 49 | 50 | const std::string& getScriptName() const; 51 | const std::string& getScriptFilename() const; 52 | 53 | const std::string& getDocumentRoot() const; 54 | 55 | const std::string& getRemoteUser() const; 56 | const std::string& getRemoteAddr() const; 57 | const std::string& getQueryString() const; 58 | const std::string& getRequestMethod() const; 59 | const std::string& getRequestId() const; 60 | 61 | std::streamsize getContentLength() const; 62 | const std::string& getContentType() const; 63 | 64 | std::string getURI() const; 65 | std::string getUrl() const; 66 | 67 | unsigned int countArgs() const; 68 | bool hasArg(const std::string &name) const; 69 | const std::string& getArg(const std::string &name) const; 70 | void getArg(const std::string &name, std::vector &v) const; 71 | void argNames(std::vector &v) const; 72 | 73 | unsigned int countHeaders() const; 74 | bool hasHeader(const std::string &name) const; 75 | const std::string& getHeader(const std::string &name) const; 76 | void headerNames(std::vector &v) const; 77 | 78 | unsigned int countCookie() const; 79 | bool hasCookie(const std::string &name) const; 80 | const std::string& getCookie(const std::string &name) const; 81 | void cookieNames(std::vector &v) const; 82 | 83 | bool hasFile(const std::string &name) const; 84 | void remoteFiles(std::vector &v) const; 85 | 86 | const std::string& remoteFileName(const std::string &name) const; 87 | const std::string& remoteFileType(const std::string &name) const; 88 | DataBuffer remoteFile(const std::string &name) const; 89 | 90 | bool isSecure() const; 91 | DataBuffer requestBody() const; 92 | 93 | void setCookie(const Cookie &cookie); 94 | void setStatus(unsigned short status); 95 | void sendError(unsigned short status); 96 | void setHeader(const std::string &name, const std::string &value); 97 | 98 | void write(std::streambuf *buf); 99 | std::streamsize write(const char *buf, std::streamsize size); 100 | std::string outputHeader(const std::string &name) const; 101 | 102 | void reset(); 103 | void sendHeaders(); 104 | void attach(RequestIOStream *stream, char *env[]); 105 | 106 | bool isProcessed() const; 107 | void markAsProcessed(); 108 | 109 | void tryAgain(time_t delay); 110 | 111 | void redirectBack(); 112 | void redirectToPath(const std::string &path); 113 | 114 | void setContentType(const std::string &type); 115 | void setContentEncoding(const std::string &encoding); 116 | 117 | void parse(DataBuffer buffer); 118 | void serialize(DataBuffer &buffer); 119 | 120 | unsigned short status() const; 121 | 122 | void flush(); 123 | 124 | private: 125 | std::auto_ptr impl_; 126 | }; 127 | 128 | } // namespace fastcgi 129 | 130 | #endif // _FASTCGI_REQUEST_H_ 131 | 132 | -------------------------------------------------------------------------------- /include/fastcgi2/request_io_stream.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_REQUEST_IO_STREAM_H_ 19 | #define _FASTCGI_REQUEST_IO_STREAM_H_ 20 | 21 | namespace fastcgi 22 | { 23 | 24 | class RequestIOStream { 25 | public: 26 | virtual int read(char *buf, int size) = 0; 27 | virtual int write(const char *buf, int size) = 0; 28 | virtual void write(std::streambuf *buf) = 0; 29 | virtual void flush() = 0; 30 | }; 31 | 32 | } // namespace fastcgi 33 | 34 | #endif // _FASTCGI_REQUEST_IO_STREAM_H_ 35 | -------------------------------------------------------------------------------- /include/fastcgi2/stream.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_STREAM_H_ 19 | #define _FASTCGI_STREAM_H_ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | namespace fastcgi 26 | { 27 | 28 | class Request; 29 | 30 | class RequestStream : private boost::noncopyable 31 | { 32 | public: 33 | RequestStream(Request *req); 34 | virtual ~RequestStream(); 35 | 36 | RequestStream& operator << (std::ostream& (*f)(std::ostream &os)) { 37 | stream_ << f; 38 | return *this; 39 | } 40 | 41 | template RequestStream& operator << (const T &value) { 42 | stream_ << value; 43 | return *this; 44 | } 45 | 46 | private: 47 | Request *request_; 48 | std::stringstream stream_; 49 | }; 50 | 51 | } // namespace fastcgi 52 | 53 | #endif // _FASTCGI_STREAM_H_ 54 | -------------------------------------------------------------------------------- /include/fastcgi2/util.h: -------------------------------------------------------------------------------- 1 | // Fastcgi Daemon - framework for design highload FastCGI applications on C++ 2 | // Copyright (C) 2011 Ilya Golubtsov 3 | 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either version 2 7 | // of the License, or (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | 18 | #ifndef _FASTCGI_UTIL_H_ 19 | #define _FASTCGI_UTIL_H_ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | namespace fastcgi 28 | { 29 | 30 | class Range; 31 | 32 | class StringUtils : private boost::noncopyable 33 | { 34 | public: 35 | static std::string urlencode(const Range &val); 36 | static std::string urlencode(const std::string &val); 37 | 38 | static std::string urldecode(const Range &val); 39 | static std::string urldecode(DataBuffer data); 40 | static std::string urldecode(const std::string &val); 41 | 42 | typedef std::pair NamedValue; 43 | 44 | static void parse(const Range &range, std::vector &v); 45 | static void parse(const std::string &str, std::vector &v); 46 | static void parse(DataBuffer data, std::vector &v); 47 | 48 | static const std::string EMPTY_STRING; 49 | 50 | private: 51 | static void urldecode(const Range &range, std::string &result); 52 | 53 | StringUtils(); 54 | virtual ~StringUtils(); 55 | }; 56 | 57 | class HttpDateUtils : private boost::noncopyable 58 | { 59 | public: 60 | static time_t parse(const char *value); 61 | static std::string format(time_t value); 62 | 63 | private: 64 | HttpDateUtils(); 65 | virtual ~HttpDateUtils(); 66 | }; 67 | 68 | } // namespace fastcgi 69 | 70 | #endif // _FASTCGI_UTIL_H_ 71 | -------------------------------------------------------------------------------- /library/Makefile.am: -------------------------------------------------------------------------------- 1 | lib_LTLIBRARIES = libfastcgi-daemon2.la 2 | 3 | libfastcgi_daemon2_la_SOURCES = component.cpp config.cpp cookie.cpp except.cpp \ 4 | handler.cpp handlerset.cpp loader.cpp logger.cpp parser.cpp request.cpp \ 5 | requestimpl.cpp stream.cpp util.cpp xml.cpp componentset.cpp \ 6 | component_factory.cpp component_context.cpp data_buffer.cpp string_buffer.cpp \ 7 | server.cpp request_thread_pool.cpp globals.cpp response_time_statistics.cpp request_filter.cpp 8 | 9 | AM_CPPFLAGS = -I../include -I../config @xml_CFLAGS@ 10 | AM_CXXFLAGS = -pthread 11 | AM_LDFLAGS = -lpthread -ldl -lfcgi -lfcgi++ @BOOST_LDFLAGS@ @BOOST_THREAD_LDFLAGS@ @BOOST_REGEX_LDFLAGS@ @xml_LIBS@ 12 | -------------------------------------------------------------------------------- /library/component.cpp: -------------------------------------------------------------------------------- 1 | #include "settings.h" 2 | 3 | #include "fastcgi2/component.h" 4 | #include "details/componentset.h" 5 | #include "details/loader.h" 6 | 7 | #ifdef HAVE_DMALLOC_H 8 | #include 9 | #endif 10 | 11 | namespace fastcgi 12 | { 13 | 14 | ComponentContext::~ComponentContext() { 15 | } 16 | 17 | Component::Component(ComponentContext *context) : context_(context) { 18 | } 19 | 20 | Component::~Component() { 21 | } 22 | 23 | ComponentContext* Component::context() { 24 | return context_; 25 | } 26 | 27 | const ComponentContext* Component::context() const { 28 | return context_; 29 | } 30 | 31 | } // namespace fastcgi 32 | -------------------------------------------------------------------------------- /library/component_context.cpp: -------------------------------------------------------------------------------- 1 | #include "settings.h" 2 | 3 | #include "details/component_context.h" 4 | #include "details/componentset.h" 5 | #include "details/globals.h" 6 | 7 | #ifdef HAVE_DMALLOC_H 8 | #include 9 | #endif 10 | 11 | namespace fastcgi 12 | { 13 | 14 | ComponentContextImpl::ComponentContextImpl( 15 | const Globals *globals, const std::string &componentXPath) : 16 | globals_(globals), componentXPath_(componentXPath) 17 | {} 18 | 19 | ComponentContextImpl::~ComponentContextImpl() { 20 | } 21 | 22 | const Config* 23 | ComponentContextImpl::getConfig() const { 24 | return globals_->config(); 25 | } 26 | 27 | const Globals* 28 | ComponentContextImpl::globals() const { 29 | return globals_; 30 | } 31 | 32 | std::string 33 | ComponentContextImpl::getComponentXPath() const { 34 | return componentXPath_; 35 | } 36 | 37 | Component* 38 | ComponentContextImpl::findComponentInternal(const std::string &name) const { 39 | return globals_->components()->find(name); 40 | } 41 | 42 | } // namespace fastcgi 43 | -------------------------------------------------------------------------------- /library/component_factory.cpp: -------------------------------------------------------------------------------- 1 | #include "settings.h" 2 | #include "fastcgi2/component_factory.h" 3 | 4 | #ifdef HAVE_DMALLOC_H 5 | #include 6 | #endif 7 | 8 | namespace fastcgi 9 | { 10 | 11 | ComponentFactory::ComponentFactory() { 12 | } 13 | 14 | ComponentFactory::~ComponentFactory() { 15 | } 16 | 17 | } // namespace fastcgi 18 | -------------------------------------------------------------------------------- /library/componentset.cpp: -------------------------------------------------------------------------------- 1 | #include "settings.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "fastcgi2/config.h" 8 | #include "fastcgi2/component.h" 9 | #include "fastcgi2/component_factory.h" 10 | 11 | #include "details/loader.h" 12 | #include "details/componentset.h" 13 | #include "details/component_context.h" 14 | #include "details/globals.h" 15 | 16 | #ifdef HAVE_DMALLOC_H 17 | #include 18 | #endif 19 | 20 | namespace fastcgi 21 | { 22 | 23 | ComponentSet::ComponentContainer::ComponentContainer() 24 | : component(NULL), context(NULL), isLoadingStarted(false) 25 | {} 26 | 27 | ComponentSet::ComponentSet() : globals_(NULL) { 28 | } 29 | 30 | ComponentSet::~ComponentSet() { 31 | sendOnUnloadToComponents(); 32 | for (ComponentMap::reverse_iterator i = components_.rbegin(); i != components_.rend(); ++i) { 33 | delete i->second.component; 34 | delete i->second.context; 35 | } 36 | } 37 | 38 | void 39 | ComponentSet::init(const Globals *globals) { 40 | globals_ = globals; 41 | std::vector v; 42 | std::string key("/fastcgi/components/component"); 43 | globals->config()->subKeys(key, v); 44 | for (std::vector::iterator i = v.begin(), end = v.end(); i != end; ++i) { 45 | const std::string name = globals->config()->asString(*i + "/@name"); 46 | const std::string type = globals->config()->asString(*i + "/@type"); 47 | add(name, type, *i); 48 | } 49 | sendOnLoadToComponents(); 50 | } 51 | 52 | Component* 53 | ComponentSet::find(const std::string &name) const { 54 | ComponentSet *nonConstThis = const_cast(this); 55 | ComponentMap::iterator i = nonConstThis->components_.find(name); 56 | if (i != components_.end()) { 57 | ComponentContainer &cont = i->second; 58 | if (!isComponentLoaded(name)) { 59 | nonConstThis->sendOnLoad(name, cont); 60 | } 61 | return cont.component; 62 | } 63 | return NULL; 64 | } 65 | 66 | void 67 | ComponentSet::add(const std::string &name, const std::string &type, 68 | const std::string &componentXPath) { 69 | ComponentFactory *factory = globals_->loader()->findComponentFactory(type); 70 | if (!factory) { 71 | throw std::runtime_error("Cannot find component factory for type: " + type); 72 | } 73 | ComponentContainer c; 74 | std::auto_ptr ctx(new ComponentContextImpl(globals_, componentXPath)); 75 | try { 76 | c.component = factory->createComponent(ctx.get()); 77 | } 78 | catch (const std::exception &e) { 79 | throw std::runtime_error(e.what()); 80 | } 81 | catch (...) { 82 | throw std::runtime_error("Unknown exception caught"); 83 | } 84 | c.context = ctx.release(); 85 | components_.insert(make_pair(name, c)); 86 | } 87 | 88 | void 89 | ComponentSet::sendOnLoadToComponents() { 90 | for (ComponentMap::iterator i = components_.begin(); i != components_.end(); ++i) { 91 | sendOnLoad(i->first, i->second); 92 | } 93 | } 94 | 95 | void 96 | ComponentSet::sendOnLoad(const std::string &componentName, ComponentContainer &cont) { 97 | if (!isComponentLoaded(componentName)) { 98 | if (cont.isLoadingStarted) { 99 | throw std::runtime_error("Cyclic component dependence found"); 100 | } 101 | cont.isLoadingStarted = true; 102 | try { 103 | cont.component->onLoad(); 104 | } 105 | catch (const std::exception &e) { 106 | throw std::runtime_error(e.what()); 107 | } 108 | catch (...) { 109 | throw std::runtime_error("Unknown exception caught"); 110 | } 111 | loadingStack_.push_back(componentName); 112 | } 113 | } 114 | 115 | void 116 | ComponentSet::sendOnUnloadToComponents() { 117 | for (std::vector::reverse_iterator i = loadingStack_.rbegin(); i != loadingStack_.rend(); ++i) { 118 | ComponentContainer cont = components_.find(*i)->second; 119 | try { 120 | cont.component->onUnload(); 121 | } 122 | catch (const std::exception &e) { 123 | std::cerr << e.what() << std::endl; 124 | } 125 | catch (...) { 126 | std::cerr << "Unknown exception caught" << std::endl; 127 | } 128 | } 129 | } 130 | 131 | bool 132 | ComponentSet::isComponentLoaded(const std::string &componentName) const { 133 | return std::find(loadingStack_.begin(), loadingStack_.end(), componentName) != loadingStack_.end(); 134 | } 135 | 136 | } // namespace fastcgi 137 | -------------------------------------------------------------------------------- /library/except.cpp: -------------------------------------------------------------------------------- 1 | #include "settings.h" 2 | 3 | #include 4 | 5 | #include "fastcgi2/except.h" 6 | #include "details/parser.h" 7 | 8 | #ifdef HAVE_LDMALLOC_H 9 | #include 10 | #endif 11 | 12 | namespace fastcgi 13 | { 14 | 15 | HttpException::HttpException(unsigned short status) : 16 | status_(status) 17 | { 18 | } 19 | 20 | HttpException::~HttpException() throw () { 21 | } 22 | 23 | unsigned short 24 | HttpException::status() const { 25 | return status_; 26 | } 27 | 28 | const char* 29 | HttpException::what() const throw () { 30 | return Parser::statusToString(status_); 31 | } 32 | 33 | NotFound::NotFound() : HttpException(404) 34 | { 35 | } 36 | 37 | BadMethod::BadMethod(const char *reason) : HttpException(400) 38 | { 39 | snprintf(reason_, sizeof(reason_), "%s", reason); 40 | } 41 | 42 | const char* 43 | BadMethod::reason() const { 44 | return reason_; 45 | } 46 | 47 | InternalError::InternalError() : HttpException(500) 48 | { 49 | } 50 | 51 | } // namespace fastcgi 52 | -------------------------------------------------------------------------------- /library/globals.cpp: -------------------------------------------------------------------------------- 1 | #include "settings.h" 2 | 3 | #include "fastcgi2/component.h" 4 | #include "fastcgi2/config.h" 5 | #include "fastcgi2/handler.h" 6 | #include "fastcgi2/logger.h" 7 | 8 | #include "details/componentset.h" 9 | #include "details/globals.h" 10 | #include "details/handlerset.h" 11 | #include "details/loader.h" 12 | #include "details/request_thread_pool.h" 13 | 14 | #ifdef HAVE_DMALLOC_H 15 | #include 16 | #endif 17 | 18 | namespace fastcgi 19 | { 20 | 21 | Globals::Globals(const Config *config) : config_(config), loader_(new Loader()), 22 | handlerSet_(new HandlerSet()), componentSet_(new ComponentSet()), logger_(NULL) 23 | { 24 | loader_->init(config); 25 | componentSet_->init(this); 26 | handlerSet_->init(config, componentSet_.get()); 27 | 28 | initLogger(); 29 | initPools(); 30 | startThreadPools(); 31 | } 32 | 33 | Globals::~Globals() { 34 | } 35 | 36 | ComponentSet* 37 | Globals::components() const { 38 | return componentSet_.get(); 39 | } 40 | 41 | HandlerSet* 42 | Globals::handlers() const { 43 | return handlerSet_.get(); 44 | } 45 | 46 | const Globals::ThreadPoolMap& 47 | Globals::pools() const { 48 | return pools_; 49 | } 50 | 51 | Loader* 52 | Globals::loader() const { 53 | return loader_.get(); 54 | } 55 | 56 | Logger* 57 | Globals::logger() const { 58 | return logger_; 59 | } 60 | 61 | const Config* 62 | Globals::config() const { 63 | return config_; 64 | } 65 | 66 | static void 67 | startUpFunc(const std::set &handlers) { 68 | for (std::set::const_iterator it = handlers.begin(); 69 | it != handlers.end(); 70 | ++it) { 71 | (*it)->onThreadStart(); 72 | } 73 | } 74 | 75 | void 76 | Globals::startThreadPools() { 77 | for (ThreadPoolMap::iterator it = pools_.begin(); it != pools_.end(); ++it) { 78 | std::set handlers; 79 | handlerSet_->findPoolHandlers(it->first, handlers); 80 | it->second->start(boost::bind(&startUpFunc, handlers)); 81 | } 82 | } 83 | 84 | void 85 | Globals::stopThreadPools() { 86 | for (ThreadPoolMap::iterator it = pools_.begin(); it != pools_.end(); ++it) { 87 | it->second->stop(); 88 | } 89 | } 90 | 91 | void 92 | Globals::joinThreadPools() { 93 | for (ThreadPoolMap::iterator i = pools_.begin(); i != pools_.end(); ++i) { 94 | i->second->join(); 95 | } 96 | } 97 | 98 | void 99 | Globals::initPools() { 100 | std::set poolsNeeded = handlerSet_->getPoolsNeeded(); 101 | 102 | std::vector poolSubkeys; 103 | config_->subKeys("/fastcgi/pools/pool", poolSubkeys); 104 | unsigned maxTasksInProcessCounter = 0; 105 | for (std::vector::const_iterator p = poolSubkeys.begin(); p != poolSubkeys.end(); ++p) { 106 | const std::string poolName = config_->asString(*p + "/@name"); 107 | const int threadsNumber = config_->asInt(*p + "/@threads"); 108 | const int queueLength = config_->asInt(*p + "/@queue"); 109 | const int delay = config_->asInt(*p + "/@max-delay", 0); 110 | 111 | maxTasksInProcessCounter += (threadsNumber + queueLength); 112 | if (maxTasksInProcessCounter > 65535) { 113 | throw std::runtime_error("The sum of all threads and queue attributes must be not more than 65535"); 114 | } 115 | 116 | if (pools_.find(poolName) != pools_.end()) { 117 | throw std::runtime_error(poolName + ": pool names must be unique"); 118 | } 119 | 120 | if (poolsNeeded.find(poolName) == poolsNeeded.end()) { 121 | continue; 122 | } 123 | 124 | pools_.insert(make_pair(poolName, boost::shared_ptr(delay ? 125 | new RequestsThreadPool(threadsNumber, queueLength, delay, logger_) : 126 | new RequestsThreadPool(threadsNumber, queueLength, logger_)))); 127 | } 128 | 129 | for (std::set::const_iterator i = poolsNeeded.begin(); i != poolsNeeded.end(); ++i) { 130 | if (pools_.find(*i) == pools_.end()) { 131 | throw std::runtime_error("cannot find pool " + *i); 132 | } 133 | } 134 | } 135 | 136 | void 137 | Globals::initLogger() { 138 | const std::string loggerComponentName = config_->asString( 139 | "/fastcgi/daemon[count(logger)=1]/logger/@component"); 140 | Component *loggerComponent = componentSet_->find(loggerComponentName); 141 | if (!loggerComponent) { 142 | throw std::runtime_error("Daemon logger does not exist"); 143 | } 144 | logger_ = dynamic_cast(loggerComponent); 145 | if (!logger_) { 146 | throw std::runtime_error("Component " + loggerComponentName + " does not implement Logger interface"); 147 | } 148 | } 149 | 150 | } // namespace fastcgi 151 | -------------------------------------------------------------------------------- /library/handler.cpp: -------------------------------------------------------------------------------- 1 | #include "settings.h" 2 | 3 | #include "details/handler_context.h" 4 | #include "details/handlerset.h" 5 | 6 | #ifdef HAVE_DMALLOC_H 7 | #include 8 | #endif 9 | 10 | namespace fastcgi 11 | { 12 | 13 | HandlerContext::~HandlerContext() { 14 | } 15 | 16 | boost::any HandlerContextImpl::getParam(const std::string &name) const { 17 | ParamsMapType::const_iterator itr = params_.find(name); 18 | if (itr != params_.end()) { 19 | return itr->second; 20 | } 21 | return boost::any(); 22 | } 23 | 24 | void HandlerContextImpl::setParam(const std::string &name, const boost::any &value) { 25 | params_[name] = value; 26 | } 27 | 28 | Handler::Handler() { 29 | } 30 | 31 | Handler::~Handler() { 32 | } 33 | 34 | void 35 | Handler::onThreadStart() { 36 | } 37 | 38 | } // namespace fastcgi 39 | -------------------------------------------------------------------------------- /library/loader.cpp: -------------------------------------------------------------------------------- 1 | #include "settings.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include "details/loader.h" 13 | #include "fastcgi2/config.h" 14 | #include "fastcgi2/component_factory.h" 15 | 16 | #ifdef HAVE_DMALLOC_H 17 | #include 18 | #endif 19 | 20 | namespace fastcgi 21 | { 22 | 23 | Loader::Loader() 24 | { 25 | } 26 | 27 | Loader::~Loader() { 28 | std::for_each(handles_.rbegin(), handles_.rend(), boost::bind(&dlclose, _1)); 29 | } 30 | 31 | void 32 | Loader::init(const Config *config) { 33 | std::vector v; 34 | std::string key("/fastcgi/modules/module"); 35 | 36 | config->subKeys(key, v); 37 | for (std::vector::iterator i = v.begin(), end = v.end(); i != end; ++i) { 38 | const std::string name = config->asString(*i + "/@name"); 39 | const std::string path = config->asString(*i + "/@path"); 40 | load(name.c_str(), path.c_str()); 41 | } 42 | } 43 | 44 | ComponentFactory* 45 | Loader::findComponentFactory(const std::string &type) const { 46 | FactoryMap::const_iterator i = factories_.find(type); 47 | if (i != factories_.end()) { 48 | return i->second; 49 | } 50 | return NULL; 51 | } 52 | 53 | void 54 | Loader::load(const char *name, const char *path) { 55 | 56 | void *handle = NULL; 57 | try { 58 | handle = dlopen(path, RTLD_NOW | RTLD_GLOBAL); 59 | checkLoad(dlerror()); 60 | 61 | void *libraryEntry = dlsym(handle, "getFactoryMap"); 62 | checkLoad(dlerror()); 63 | FastcgiGetFactoryMapFunction getFactoryMap = NULL; 64 | memcpy(&getFactoryMap, &libraryEntry, sizeof(FastcgiGetFactoryMapFunction)); 65 | 66 | FactoryMap *factoryMap = getFactoryMap(); 67 | 68 | for (FactoryMap::const_iterator i = factoryMap->begin(); i != factoryMap->end(); ++i) { 69 | const std::string fullFactoryName = std::string(name) + ":" + i->first; 70 | factories_.insert(make_pair(fullFactoryName, i->second)); 71 | } 72 | 73 | handles_.push_back(handle); 74 | 75 | } catch (const std::exception &e) { 76 | if (NULL != handle) { 77 | dlclose(handle); 78 | } 79 | throw; 80 | } 81 | } 82 | 83 | void 84 | Loader::checkLoad(const char *err) { 85 | if (NULL != err) { 86 | throw std::runtime_error(err); 87 | } 88 | } 89 | 90 | } // namespace fastcgi 91 | -------------------------------------------------------------------------------- /library/logger.cpp: -------------------------------------------------------------------------------- 1 | #include "settings.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "fastcgi2/util.h" 9 | #include "fastcgi2/config.h" 10 | #include "fastcgi2/logger.h" 11 | #include "fastcgi2/request.h" 12 | #include "fastcgi2/stream.h" 13 | 14 | #include 15 | 16 | #ifdef HAVE_DMALLOC_H 17 | #include 18 | #endif 19 | 20 | namespace fastcgi 21 | { 22 | 23 | Logger::Logger() 24 | { 25 | level_ = DEBUG; 26 | } 27 | 28 | Logger::~Logger() { 29 | } 30 | 31 | /* 32 | void 33 | Logger::handleRequest(Request *request) { 34 | request->setContentType("text/plain"); 35 | const std::string &action = request->getArg("action"); 36 | if ("setlevel" == action) { 37 | const std::string &level = request->getArg("level"); 38 | setLevel(stringToLevel(level)); 39 | RequestStream(request) << "level " << level << "successfully set"; 40 | } else if ("rollover" == action) { 41 | rollOver(); 42 | RequestStream(request) << "rollover successful"; 43 | } else { 44 | RequestStream(request) << "bad action"; 45 | } 46 | } 47 | */ 48 | 49 | void 50 | Logger::exiting(const char *function) { 51 | debug("exiting %s\n", function); 52 | } 53 | 54 | void 55 | Logger::entering(const char *function) { 56 | debug("entering %s\n", function); 57 | } 58 | 59 | void 60 | Logger::info(const char *format, ...) { 61 | va_list args; 62 | va_start(args, format); 63 | log(INFO, format, args); 64 | va_end(args); 65 | } 66 | 67 | void 68 | Logger::debug(const char *format, ...) { 69 | va_list args; 70 | va_start(args, format); 71 | log(DEBUG, format, args); 72 | va_end(args); 73 | } 74 | 75 | void 76 | Logger::error(const char *format, ...) { 77 | va_list args; 78 | va_start(args, format); 79 | log(ERROR, format, args); 80 | va_end(args); 81 | } 82 | 83 | void 84 | Logger::emerg(const char *format, ...) { 85 | va_list args; 86 | va_start(args, format); 87 | log(EMERGENCY, format, args); 88 | va_end(args); 89 | } 90 | 91 | Logger::Level Logger::getLevel() const { 92 | return level_; 93 | } 94 | 95 | void Logger::setLevel(const Logger::Level level) { 96 | setLevelInternal(level); 97 | level_ = level; 98 | } 99 | 100 | Logger::Level Logger::stringToLevel(const std::string &name) { 101 | if (strncasecmp(name.c_str(), "INFO", sizeof("INFO")) == 0) { 102 | return INFO; 103 | } else if (strncasecmp(name.c_str(), "DEBUG", sizeof("DEBUG")) == 0) { 104 | return DEBUG; 105 | } else if (strncasecmp(name.c_str(), "ERROR", sizeof("ERROR")) == 0) { 106 | return ERROR; 107 | } else if (strncasecmp(name.c_str(), "EMERG", sizeof("EMERG")) == 0) { 108 | return EMERGENCY; 109 | } else { 110 | throw std::runtime_error("bad string to log level cast)"); 111 | } 112 | } 113 | 114 | std::string Logger::levelToString(const Level level) { 115 | switch (level) { 116 | case INFO: 117 | return "INFO"; 118 | case DEBUG: 119 | return "DEBUG"; 120 | case ERROR: 121 | return "ERROR"; 122 | case EMERGENCY: 123 | return "EMERG"; 124 | default: 125 | throw std::runtime_error("bad log level to string cast"); 126 | } 127 | } 128 | 129 | void Logger::setLevelInternal(const Level level) { 130 | } 131 | 132 | void Logger::rollOver() { 133 | } 134 | 135 | LoggerRequestId::LoggerRequestId() { 136 | } 137 | 138 | LoggerRequestId::~LoggerRequestId() { 139 | } 140 | 141 | /* 142 | const char* 143 | Logger::level() const { 144 | switch (setlogmask(0)) { 145 | case LOG_INFO: 146 | return "INFO"; 147 | case LOG_DEBUG: 148 | return "DEBUG"; 149 | case LOG_ERR: 150 | return "ERROR"; 151 | case LOG_EMERG: 152 | return "EMERG"; 153 | default: 154 | throw std::runtime_error("bad level"); 155 | } 156 | } 157 | 158 | void 159 | Logger::level(const char* value) { 160 | setlogmask(findLevel(value)); 161 | } 162 | 163 | Logger* 164 | Logger::instance() { 165 | assert(NULL != helper_.get()); 166 | return helper_.get(); 167 | } 168 | 169 | unsigned int 170 | Logger::findLevel(const char *name) const { 171 | if (strncasecmp(name, "INFO", sizeof("INFO")) == 0) { 172 | return LOG_INFO; 173 | } 174 | if (strncasecmp(name, "DEBUG", sizeof("DEBUG")) == 0) { 175 | return LOG_DEBUG; 176 | } 177 | if (strncasecmp(name, "ERROR", sizeof("ERROR")) == 0) { 178 | return LOG_ERR; 179 | } 180 | if (strncasecmp(name, "EMERG", sizeof("EMERG")) == 0) { 181 | return LOG_EMERG; 182 | } 183 | throw std::runtime_error("bad level"); 184 | } 185 | 186 | void 187 | Logger::log(int value, const char *format, va_list args) { 188 | vsyslog(value, format, args); 189 | } 190 | 191 | void 192 | Logger::attachImpl(LoggerHelper helper) { 193 | helper_ = helper; 194 | } 195 | 196 | LoggerRegisterer::LoggerRegisterer(LoggerHelper helper) { 197 | Logger::attachImpl(helper); 198 | } 199 | 200 | */ 201 | 202 | BulkLogger::BulkLogger() { 203 | } 204 | 205 | void BulkLogger::log(Level level, const char *format, va_list args) { 206 | } 207 | 208 | } // namespace fastcgi 209 | -------------------------------------------------------------------------------- /library/request_filter.cpp: -------------------------------------------------------------------------------- 1 | #include "settings.h" 2 | 3 | #include "details/request_filter.h" 4 | 5 | #include 6 | 7 | #include "fastcgi2/request.h" 8 | 9 | #ifdef HAVE_DMALLOC_H 10 | #include 11 | #endif 12 | 13 | namespace fastcgi 14 | { 15 | 16 | RegexFilter::RegexFilter(const std::string ®ex) : regex_(regex) 17 | {} 18 | 19 | RegexFilter::~RegexFilter() 20 | {} 21 | 22 | bool 23 | RegexFilter::check(const std::string &value) const { 24 | return boost::regex_match(value, regex_); 25 | } 26 | 27 | UrlFilter::UrlFilter(const std::string ®ex) : regex_(regex) 28 | {} 29 | 30 | UrlFilter::~UrlFilter() 31 | {} 32 | 33 | bool 34 | UrlFilter::check(const Request *request) const { 35 | return regex_.check(request->getScriptName()); 36 | } 37 | 38 | HostFilter::HostFilter(const std::string ®ex) : regex_(regex) 39 | {} 40 | 41 | HostFilter::~HostFilter() 42 | {} 43 | 44 | bool 45 | HostFilter::check(const Request *request) const { 46 | return regex_.check(request->getHost()); 47 | } 48 | 49 | 50 | PortFilter::PortFilter(const std::string ®ex) : regex_(regex) 51 | {} 52 | 53 | PortFilter::~PortFilter() 54 | {} 55 | 56 | bool 57 | PortFilter::check(const Request *request) const { 58 | std::string port = boost::lexical_cast(request->getServerPort()); 59 | return regex_.check(port); 60 | } 61 | 62 | 63 | AddressFilter::AddressFilter(const std::string ®ex) : regex_(regex) 64 | {} 65 | 66 | AddressFilter::~AddressFilter() 67 | {} 68 | 69 | bool 70 | AddressFilter::check(const Request *request) const { 71 | return regex_.check(request->getServerAddr()); 72 | } 73 | 74 | RefererFilter::RefererFilter(const std::string ®ex) : regex_(regex) 75 | {} 76 | 77 | RefererFilter::~RefererFilter() 78 | {} 79 | 80 | bool 81 | RefererFilter::check(const Request *request) const { 82 | if (!request->hasHeader("Referer")) { 83 | return false; 84 | } 85 | 86 | return regex_.check(request->getHeader("Referer")); 87 | } 88 | 89 | ParamFilter::ParamFilter(const std::string &name, const std::string ®ex) : 90 | name_(name), regex_(regex) 91 | {} 92 | 93 | ParamFilter::~ParamFilter() 94 | {} 95 | 96 | bool 97 | ParamFilter::check(const Request *request) const { 98 | if (!request->hasArg(name_)) { 99 | return false; 100 | } 101 | return regex_.check(request->getArg(name_)); 102 | } 103 | 104 | 105 | } // namespace fastcgi 106 | -------------------------------------------------------------------------------- /library/request_thread_pool.cpp: -------------------------------------------------------------------------------- 1 | #include "settings.h" 2 | 3 | #include "details/request_thread_pool.h" 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include "details/handler_context.h" 14 | 15 | #ifdef HAVE_DMALLOC_H 16 | #include 17 | #endif 18 | 19 | namespace fastcgi 20 | { 21 | 22 | RequestsThreadPool::RequestsThreadPool( 23 | const unsigned threadsNumber, const unsigned queueLength, fastcgi::Logger *logger) : 24 | ThreadPool(threadsNumber, queueLength), logger_(logger), delay_(0) 25 | {} 26 | 27 | RequestsThreadPool::RequestsThreadPool( 28 | const unsigned threadsNumber, const unsigned queueLength, boost::uint64_t delay, fastcgi::Logger *logger) : 29 | ThreadPool(threadsNumber, queueLength), logger_(logger), delay_(delay) 30 | {} 31 | 32 | RequestsThreadPool::~RequestsThreadPool() 33 | {} 34 | 35 | boost::uint64_t 36 | RequestsThreadPool::delay() const { 37 | return delay_; 38 | } 39 | 40 | void 41 | RequestsThreadPool::handleTask(RequestTask task) { 42 | try { 43 | if (delay_) { 44 | struct timeval t; 45 | gettimeofday(&t, 0); 46 | boost::uint64_t now = (t.tv_sec * 1000) + (t.tv_usec / 1000); 47 | if (now - task.start > delay_) { 48 | logger_->error("thread pool task is timed out"); 49 | task.request->sendError(503); 50 | return; 51 | } 52 | } 53 | try { 54 | LoggerRequestId *logger_req_id = dynamic_cast(logger_); 55 | if (logger_req_id) { 56 | logger_req_id->setRequestId(task.request->getRequestId()); 57 | } 58 | 59 | std::auto_ptr context(new HandlerContextImpl); 60 | for (std::vector::iterator i = task.handlers.begin(); 61 | i != task.handlers.end(); 62 | ++i) { 63 | if (task.request->isProcessed()) { 64 | break; 65 | } 66 | (*i)->handleRequest(task.request.get(), context.get()); 67 | } 68 | 69 | task.request->sendHeaders(); 70 | } 71 | catch (const HttpException &e) { 72 | bool headersAlreadySent = false; 73 | try { 74 | task.request->setStatus(500); 75 | } 76 | catch (...) { // this means that headers already send and we cannot change status/headers and so on 77 | headersAlreadySent = true; 78 | } 79 | if (headersAlreadySent) { 80 | throw; 81 | } 82 | else { 83 | task.request->sendError(e.status()); 84 | } 85 | } 86 | catch (const std::exception &e) { 87 | bool headersAlreadySent = false; 88 | try { 89 | task.request->setStatus(500); 90 | } 91 | catch (...) { // this means that headers already send and we cannot change status/headers and so on 92 | headersAlreadySent = true; 93 | } 94 | if (headersAlreadySent) { 95 | throw; 96 | } 97 | else { 98 | task.request->sendError(500); 99 | std::string err(e.what()); 100 | task.request->write(err.c_str(), err.size()); 101 | } 102 | } 103 | catch (...) { 104 | bool headersAlreadySent = false; 105 | try { 106 | task.request->setStatus(500); 107 | } 108 | catch (...) { // this means that headers already send and we cannot change status/headers and so on 109 | headersAlreadySent = true; 110 | } 111 | if (headersAlreadySent) { 112 | throw; 113 | } 114 | else { 115 | fastcgi::RequestStream stream(task.request.get()); 116 | stream << "fastcgi-daemon: got unknown exception from handler"; 117 | task.request->sendError(500); 118 | } 119 | } 120 | } 121 | catch (const std::exception &e) { 122 | logger_->error("%s", e.what()); 123 | throw; 124 | } 125 | catch (...) { 126 | logger_->error("RequestsThreadPool::handleTask: got unknown exception, it should't happen"); 127 | throw; 128 | } 129 | } 130 | 131 | } // namespace fastcgi 132 | -------------------------------------------------------------------------------- /library/response_time_statistics.cpp: -------------------------------------------------------------------------------- 1 | #include "settings.h" 2 | 3 | #include "details/response_time_statistics.h" 4 | 5 | #ifdef HAVE_DMALLOC_H 6 | #include 7 | #endif 8 | 9 | namespace fastcgi 10 | { 11 | 12 | ResponseTimeStatistics::ResponseTimeStatistics() 13 | {} 14 | 15 | ResponseTimeStatistics::~ResponseTimeStatistics() 16 | {} 17 | 18 | } // namespace fastcgi 19 | -------------------------------------------------------------------------------- /library/server.cpp: -------------------------------------------------------------------------------- 1 | #include "settings.h" 2 | 3 | #include "details/server.h" 4 | 5 | #include 6 | 7 | #include "details/globals.h" 8 | #include "details/handlerset.h" 9 | 10 | #include "fastcgi2/logger.h" 11 | 12 | #ifdef HAVE_DMALLOC_H 13 | #include 14 | #endif 15 | 16 | namespace fastcgi 17 | { 18 | 19 | Server::Server() 20 | {} 21 | 22 | Server::~Server() 23 | {} 24 | 25 | void 26 | Server::handleRequest(RequestTask task) { 27 | handleRequestInternal(getHandler(task), task); 28 | } 29 | 30 | void 31 | Server::handleRequestInternal(const HandlerSet::HandlerDescription* handler, RequestTask task) { 32 | if (NULL == handler || handler->handlers.empty()) { 33 | task.request->sendError(404); 34 | return; 35 | } 36 | 37 | try { 38 | task.handlers = handler->handlers; 39 | RequestsThreadPool* pool = globals()->pools().find(handler->poolName)->second.get(); 40 | if (pool->delay()) { 41 | struct timeval now; 42 | gettimeofday(&now, 0); 43 | task.start = (now.tv_sec * 1000) + (now.tv_usec / 1000); 44 | } 45 | else { 46 | task.start = 0; 47 | } 48 | pool->addTask(task); 49 | } 50 | catch (const std::exception &e) { 51 | task.request->sendError(503); 52 | logger()->error("cannot add request to pool: %s", e.what()); 53 | } 54 | } 55 | 56 | const HandlerSet::HandlerDescription* 57 | Server::getHandler(RequestTask task) const { 58 | return globals()->handlers()->findURIHandler(task.request.get()); 59 | } 60 | 61 | } // namespace fastcgi 62 | -------------------------------------------------------------------------------- /library/stream.cpp: -------------------------------------------------------------------------------- 1 | #include "settings.h" 2 | #include "fastcgi2/stream.h" 3 | #include "fastcgi2/request.h" 4 | 5 | #ifdef HAVE_DMALLOC_H 6 | #include 7 | #endif 8 | 9 | namespace fastcgi 10 | { 11 | 12 | RequestStream::RequestStream(Request *req) : 13 | request_(req) 14 | {} 15 | 16 | RequestStream::~RequestStream() { 17 | if (stream_.rdbuf()->in_avail()) { 18 | request_->write(stream_.rdbuf()); 19 | } 20 | } 21 | 22 | } // namespace fastcgi 23 | -------------------------------------------------------------------------------- /library/string_buffer.cpp: -------------------------------------------------------------------------------- 1 | #include "settings.h" 2 | 3 | #include 4 | 5 | #include "details/range.h" 6 | #include "details/string_buffer.h" 7 | 8 | #include "fastcgi2/util.h" 9 | 10 | #ifdef HAVE_DMALLOC_H 11 | #include 12 | #endif 13 | 14 | namespace fastcgi 15 | { 16 | 17 | StringBuffer::StringBuffer(const char *data, boost::uint64_t size) : 18 | data_(new std::vector(data, data + size)) 19 | {} 20 | 21 | StringBuffer::~StringBuffer() 22 | {} 23 | 24 | boost::uint64_t 25 | StringBuffer::read(boost::uint64_t pos, char *data, boost::uint64_t len) { 26 | memcpy(data, &((*data_)[pos]), len); 27 | return len; 28 | } 29 | 30 | boost::uint64_t 31 | StringBuffer::write(boost::uint64_t pos, const char *data, boost::uint64_t len) { 32 | memcpy(&((*data_)[pos]), data, len); 33 | return len; 34 | } 35 | 36 | char 37 | StringBuffer::at(boost::uint64_t pos) { 38 | return data_->at(pos); 39 | } 40 | 41 | boost::uint64_t 42 | StringBuffer::find(boost::uint64_t begin, boost::uint64_t end, const char* buf, boost::uint64_t len) { 43 | if (len > end - begin) { 44 | return end; 45 | } 46 | char* first = &((*data_)[0]); 47 | Range base(first + begin, first + end); 48 | Range substr(buf, buf + len); 49 | return base.find(substr) - first; 50 | } 51 | 52 | std::pair 53 | StringBuffer::trim(boost::uint64_t begin, boost::uint64_t end) const { 54 | char* first = &((*data_)[0]); 55 | Range base(first + begin, first + end); 56 | Range trimmed = base.trim(); 57 | return std::pair( 58 | trimmed.begin() - first, trimmed.end() - first); 59 | } 60 | 61 | std::pair 62 | StringBuffer::chunk(boost::uint64_t pos) const { 63 | return std::pair(&((*data_)[0]) + pos, data_->size() - pos); 64 | } 65 | 66 | std::pair 67 | StringBuffer::segment(boost::uint64_t pos) const { 68 | return std::pair(pos, size()); 69 | } 70 | 71 | boost::uint64_t 72 | StringBuffer::size() const { 73 | return data_->size(); 74 | } 75 | 76 | void 77 | StringBuffer::resize(boost::uint64_t size) { 78 | data_->resize(size); 79 | } 80 | 81 | const std::string& 82 | StringBuffer::filename() const { 83 | return StringUtils::EMPTY_STRING; 84 | } 85 | 86 | DataBufferImpl* 87 | StringBuffer::getCopy() const { 88 | return new StringBuffer(*this); 89 | } 90 | 91 | } // namespace fastcgi 92 | -------------------------------------------------------------------------------- /library/xml.cpp: -------------------------------------------------------------------------------- 1 | #include "settings.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "details/xml.h" 7 | 8 | #ifdef HAVE_DMALLOC_H 9 | #include 10 | #endif 11 | 12 | namespace fastcgi 13 | { 14 | 15 | XmlUtils::XmlUtils() { 16 | 17 | xmlInitParser(); 18 | 19 | xmlLoadExtDtdDefaultValue = 1; 20 | xmlSubstituteEntitiesDefault(0); 21 | } 22 | 23 | XmlUtils::~XmlUtils() { 24 | xmlCleanupParser(); 25 | } 26 | 27 | void 28 | XmlUtils::throwUnless(bool value) { 29 | if (!value) { 30 | const char *message = "unknown xml error"; 31 | xmlErrorPtr err =xmlGetLastError(); 32 | if (err && err->message) { 33 | message = err->message; 34 | } 35 | std::runtime_error exc(message); 36 | xmlResetLastError(); 37 | throw exc; 38 | } 39 | } 40 | 41 | const char* 42 | XmlUtils::value(xmlNodePtr node) { 43 | assert(node); 44 | xmlNodePtr child = node->children; 45 | if (child && xmlNodeIsText(child) && child->content) { 46 | return (const char*) child->content; 47 | } 48 | return NULL; 49 | } 50 | 51 | const char* 52 | XmlUtils::value(xmlAttrPtr attr) { 53 | assert(attr); 54 | xmlNodePtr child = attr->children; 55 | if (child && xmlNodeIsText(child) && child->content) { 56 | return (const char*) child->content; 57 | } 58 | return NULL; 59 | } 60 | 61 | const char* 62 | XmlUtils::attrValue(xmlNodePtr node, const char *name) { 63 | assert(node); 64 | xmlAttrPtr attr = xmlHasProp(node, (const xmlChar*) name); 65 | return attr ? value(attr) : NULL; 66 | } 67 | 68 | void 69 | XmlDocCleaner::clean(xmlDocPtr doc) { 70 | xmlFreeDoc(doc); 71 | } 72 | 73 | void 74 | XmlNodeCleaner::clean(xmlNodePtr node) { 75 | xmlFreeNode(node); 76 | } 77 | 78 | void 79 | XmlXPathObjectCleaner::clean(xmlXPathObjectPtr obj) { 80 | xmlXPathFreeObject(obj); 81 | } 82 | 83 | void 84 | XmlXPathContextCleaner::clean(xmlXPathContextPtr ctx) { 85 | xmlXPathFreeContext(ctx); 86 | } 87 | 88 | } // namespace fastcgi 89 | -------------------------------------------------------------------------------- /logging/Makefile.am: -------------------------------------------------------------------------------- 1 | pkglib_LTLIBRARIES = fastcgi2-logger.la 2 | 3 | fastcgi2_logger_la_SOURCES = logger.cpp 4 | fastcgi2_logger_la_LIBADD = ../library/libfastcgi-daemon2.la 5 | fastcgi2_logger_la_LDFLAGS = -module -lpthread -llog4cxx 6 | 7 | AM_CPPFLAGS = -I../include -I../config 8 | AM_CXXFLAGS = -pthread 9 | 10 | noinst_HEADERS = logger.h 11 | -------------------------------------------------------------------------------- /logging/logger.cpp: -------------------------------------------------------------------------------- 1 | #include "settings.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include "fastcgi2/config.h" 11 | #include "fastcgi2/logger.h" 12 | #include "fastcgi2/component_factory.h" 13 | #include "fastcgi2/request.h" 14 | #include "fastcgi2/stream.h" 15 | #include "logger.h" 16 | 17 | #ifdef HAVE_DMALLOC_H 18 | #include 19 | #endif 20 | 21 | #if defined(HAVE_VA_COPY) 22 | #define VA_COPY(a,b) va_copy((a), (b)) 23 | #elif defined(HAVE_NONSTANDARD_VA_COPY) 24 | #define VA_COPY(a,b) __va_copy((a), (b)) 25 | #endif 26 | 27 | FCGIDAEMON_REGISTER_FACTORIES_BEGIN() 28 | FCGIDAEMON_ADD_DEFAULT_FACTORY("logger", fastcgi::DefaultLogger) 29 | FCGIDAEMON_REGISTER_FACTORIES_END() 30 | 31 | namespace fastcgi 32 | { 33 | 34 | DefaultLogger::DefaultLogger(ComponentContext *context) 35 | : Component(context), logger_(log4cxx::Logger::getRootLogger()) 36 | { 37 | const Config *config = context->getConfig(); 38 | const std::string componentXPath = context->getComponentXPath(); 39 | 40 | std::string layoutPattern = config->asString(componentXPath + "/pattern", "DEFAULT"); 41 | 42 | log4cxx::LayoutPtr layout(new log4cxx::PatternLayout( 43 | "DEFAULT" == layoutPattern ? log4cxx::PatternLayout::TTCC_CONVERSION_PATTERN : layoutPattern)); 44 | 45 | logger_ = log4cxx::Logger::getLogger(config->asString(componentXPath + "/ident")); 46 | 47 | const std::string logFileName = config->asString(componentXPath + "/file"); 48 | appender_ = log4cxx::helpers::ObjectPtrT(new log4cxx::RollingFileAppender(layout, logFileName)); 49 | 50 | appender_->setMaxFileSize("2000MB"); 51 | 52 | logger_->addAppender(appender_); 53 | 54 | setLevel(stringToLevel(config->asString(componentXPath + "/level"))); 55 | } 56 | 57 | DefaultLogger::~DefaultLogger() { 58 | } 59 | 60 | void 61 | DefaultLogger::onLoad() { 62 | } 63 | 64 | void 65 | DefaultLogger::onUnload() { 66 | } 67 | 68 | void 69 | DefaultLogger::handleRequest(Request *request, HandlerContext *handlerContext) { 70 | request->setContentType("text/plain"); 71 | const std::string &action = request->getArg("action"); 72 | if ("setlevel" == action) { 73 | const std::string &l = request->getArg("level"); 74 | setLevel(stringToLevel(l)); 75 | RequestStream(request) << "level " << l << "successfully set" << std::endl; 76 | } 77 | else if ("rollover" == action) { 78 | rollOver(); 79 | RequestStream(request) << "rollover successful" << std::endl; 80 | } 81 | else { 82 | RequestStream(request) << "bad action" << std::endl; 83 | } 84 | } 85 | 86 | void 87 | DefaultLogger::rollOver() { 88 | appender_->rollOver(); 89 | } 90 | 91 | void 92 | DefaultLogger::setLevelInternal(const Level level) { 93 | logger_->setLevel(toLog4cxxLevel(level)); 94 | } 95 | 96 | void 97 | DefaultLogger::log(const Level level, const char *format, va_list args) { 98 | log4cxx::LevelPtr log4cxxLevel = toLog4cxxLevel(level); 99 | if (logger_->isEnabledFor(log4cxxLevel)) { 100 | va_list tmpargs; 101 | VA_COPY(tmpargs, args); 102 | size_t size = vsnprintf(NULL, 0, format, tmpargs); 103 | va_end(tmpargs); 104 | if (size > 0) { 105 | std::vector data(size + 1); 106 | vsnprintf(&data[0], size + 1, format, args); 107 | logger_->log(log4cxxLevel, std::string(data.begin(), data.begin() + size)); 108 | } 109 | } 110 | } 111 | 112 | log4cxx::LevelPtr 113 | DefaultLogger::toLog4cxxLevel(const Level level) { 114 | switch (level) { 115 | case INFO: 116 | return log4cxx::Level::INFO; 117 | case DEBUG: 118 | return log4cxx::Level::DEBUG; 119 | case ERROR: 120 | return log4cxx::Level::ERROR; 121 | case EMERGENCY: 122 | return log4cxx::Level::FATAL; 123 | default: 124 | throw std::logic_error("toLog4cxxLevel: unknown log level"); 125 | } 126 | } 127 | 128 | } // namespace fastcgi 129 | -------------------------------------------------------------------------------- /logging/logger.h: -------------------------------------------------------------------------------- 1 | #ifndef _FASTCGI_LOG4CXX_LOGGER_H_ 2 | #define _FASTCGI_LOG4CXX_LOGGER_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include "fastcgi2/logger.h" 8 | #include "fastcgi2/component.h" 9 | #include "fastcgi2/handler.h" 10 | 11 | namespace fastcgi 12 | { 13 | 14 | class DefaultLogger : virtual public Logger, virtual public Component, virtual public Handler 15 | { 16 | public: 17 | DefaultLogger(ComponentContext *context); 18 | virtual ~DefaultLogger(); 19 | 20 | virtual void onLoad(); 21 | virtual void onUnload(); 22 | 23 | virtual void handleRequest(Request *request, HandlerContext *handlerContext); 24 | 25 | protected: 26 | virtual void log(const Level level, const char *format, va_list args); 27 | virtual void setLevelInternal(const Level level); 28 | virtual void rollOver(); 29 | 30 | private: 31 | static log4cxx::LevelPtr toLog4cxxLevel(const Level level); 32 | 33 | private: 34 | log4cxx::LoggerPtr logger_; 35 | log4cxx::helpers::ObjectPtrT appender_; 36 | }; 37 | 38 | } // namespace fastcgi 39 | 40 | #endif // _FASTCGI_LOG4CXX_LOGGER_H_ 41 | -------------------------------------------------------------------------------- /main/Makefile.am: -------------------------------------------------------------------------------- 1 | sbin_PROGRAMS = fastcgi-daemon2 2 | 3 | fastcgi_daemon2_SOURCES = main.cpp fcgi_server.cpp endpoint.cpp fcgi_request.cpp 4 | fastcgi_daemon2_LDADD = ../library/libfastcgi-daemon2.la -lfcgi -lfcgi++ 5 | 6 | AM_CPPFLAGS = -I@top_srcdir@/include -I@top_srcdir@/config 7 | AM_LDFLAGS = @BOOST_THREAD_LDFLAGS@ -lboost_system 8 | 9 | noinst_HEADERS = fcgi_server.h endpoint.h fcgi_request.h 10 | dist_sysconf_DATA = fastcgi.conf.example 11 | -------------------------------------------------------------------------------- /main/endpoint.cpp: -------------------------------------------------------------------------------- 1 | #include "settings.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include "endpoint.h" 11 | 12 | #ifdef HAVE_DMALLOC_H 13 | #include 14 | #endif 15 | 16 | namespace fastcgi 17 | { 18 | 19 | Endpoint::ScopedBusyCounter::ScopedBusyCounter(Endpoint &endpoint) : 20 | incremented_(false), endpoint_(endpoint) { 21 | increment(); 22 | } 23 | 24 | Endpoint::ScopedBusyCounter::~ScopedBusyCounter() { 25 | decrement(); 26 | } 27 | 28 | void 29 | Endpoint::ScopedBusyCounter::increment() { 30 | if (!incremented_) { 31 | endpoint_.incrementBusyCounter(); 32 | incremented_ = true; 33 | } 34 | } 35 | 36 | void 37 | Endpoint::ScopedBusyCounter::decrement() { 38 | if (incremented_) { 39 | endpoint_.decrementBusyCounter(); 40 | incremented_ = false; 41 | } 42 | } 43 | 44 | Endpoint::Endpoint(const std::string &path, const std::string &port, unsigned short threads) : 45 | socket_(-1), busy_count_(0), threads_(threads), socket_path_(path), socket_port_(port) 46 | { 47 | if (socket_path_.empty() && socket_port_.empty()) { 48 | throw std::runtime_error("Both /socket and /port param for endpoint is empty"); 49 | } 50 | } 51 | 52 | Endpoint::~Endpoint() { 53 | } 54 | 55 | int 56 | Endpoint::socket() const { 57 | boost::mutex::scoped_lock sl(mutex_); 58 | return socket_; 59 | } 60 | 61 | unsigned short 62 | Endpoint::threads() const { 63 | return threads_; 64 | } 65 | 66 | std::string 67 | Endpoint::toString() const { 68 | return socket_path_.empty() ? (std::string(":") + socket_port_) : socket_path_; 69 | } 70 | 71 | unsigned short 72 | Endpoint::getBusyCounter() const { 73 | boost::mutex::scoped_lock sl(mutex_); 74 | return busy_count_; 75 | } 76 | 77 | void 78 | Endpoint::openSocket(const int backlog) { 79 | boost::mutex::scoped_lock sl(mutex_); 80 | socket_ = FCGX_OpenSocket(toString().c_str(), backlog); 81 | if (-1 == socket_) { 82 | std::stringstream stream; 83 | stream << "can not open fastcgi socket: " << toString() << "[" << errno << "]"; 84 | throw std::runtime_error(stream.str()); 85 | } 86 | if (!socket_path_.empty()) { 87 | chmod(socket_path_.c_str(), 0666); 88 | } 89 | } 90 | 91 | void 92 | Endpoint::incrementBusyCounter() { 93 | boost::mutex::scoped_lock sl(mutex_); 94 | busy_count_ += 1; 95 | } 96 | 97 | void 98 | Endpoint::decrementBusyCounter() { 99 | boost::mutex::scoped_lock sl(mutex_); 100 | assert(busy_count_ > 0); 101 | busy_count_ -= 1; 102 | } 103 | 104 | } // namespace fastcgi 105 | -------------------------------------------------------------------------------- /main/endpoint.h: -------------------------------------------------------------------------------- 1 | #ifndef _FASTCGI_FASTCGI_ENDPOINT_H_ 2 | #define _FASTCGI_FASTCGI_ENDPOINT_H_ 3 | 4 | #include 5 | 6 | namespace fastcgi 7 | { 8 | 9 | class Endpoint { 10 | public: 11 | class ScopedBusyCounter { 12 | public: 13 | ScopedBusyCounter(Endpoint &endpoint); 14 | ~ScopedBusyCounter(); 15 | void increment(); 16 | void decrement(); 17 | private: 18 | bool incremented_; 19 | Endpoint &endpoint_; 20 | }; 21 | 22 | public: 23 | Endpoint(const std::string &path, const std::string &port, unsigned short threads); 24 | virtual ~Endpoint(); 25 | 26 | int socket() const; 27 | 28 | unsigned short threads() const; 29 | 30 | std::string toString() const; 31 | unsigned short getBusyCounter() const; 32 | 33 | void openSocket(const int backlog); 34 | 35 | void incrementBusyCounter(); 36 | void decrementBusyCounter(); 37 | 38 | private: 39 | int socket_; 40 | int busy_count_; 41 | unsigned short threads_; 42 | mutable boost::mutex mutex_; 43 | std::string socket_path_, socket_port_; 44 | }; 45 | 46 | } // namespace fastcgi 47 | 48 | #endif // _FASTCGI_FASTCGI_ENDPOINT_H_ 49 | -------------------------------------------------------------------------------- /main/fastcgi.conf.example: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /main/fcgi_request.h: -------------------------------------------------------------------------------- 1 | #ifndef _FASTCGI_FASTCGI_REQUEST_H_ 2 | #define _FASTCGI_FASTCGI_REQUEST_H_ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #include "fastcgi2/request_io_stream.h" 15 | #include "details/handlerset.h" 16 | 17 | namespace fastcgi 18 | { 19 | 20 | class Endpoint; 21 | class Logger; 22 | class Request; 23 | class ResponseTimeStatistics; 24 | 25 | class FastcgiRequest : public RequestIOStream { 26 | public: 27 | FastcgiRequest(boost::shared_ptr request, Endpoint *endpoint, 28 | Logger *logger, ResponseTimeStatistics *statistics, const bool logTimes); 29 | virtual ~FastcgiRequest(); 30 | void attach(); 31 | int accept(); 32 | 33 | int read(char *buf, int size); 34 | int write(const char *buf, int size); 35 | void write(std::streambuf *buf); 36 | 37 | void setHandlerDesc(const HandlerSet::HandlerDescription *handler); 38 | void flush(); 39 | private: 40 | boost::shared_ptr request_; 41 | Logger *logger_; 42 | std::string url_; 43 | std::string request_id_; 44 | Endpoint *endpoint_; 45 | FCGX_Request fcgiRequest_; 46 | ResponseTimeStatistics *statistics_; 47 | const bool logTimes_; 48 | timeval accept_time_, finish_time_; 49 | const HandlerSet::HandlerDescription* handler_; 50 | }; 51 | 52 | } // namespace fastcgi 53 | 54 | #endif // _FASTCGI_FASTCGI_REQUEST_H_ 55 | -------------------------------------------------------------------------------- /main/fcgi_server.h: -------------------------------------------------------------------------------- 1 | #ifndef _FASTCGI_FASTCGI_SERVER_H_ 2 | #define _FASTCGI_FASTCGI_SERVER_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include "details/server.h" 13 | 14 | namespace fastcgi 15 | { 16 | 17 | class Config; 18 | class Request; 19 | class Logger; 20 | class Loader; 21 | class Endpoint; 22 | class ComponentSet; 23 | class HandlerSet; 24 | class RequestsThreadPool; 25 | 26 | class ServerStopper { 27 | public: 28 | ServerStopper() : stopped_(false) {} 29 | 30 | void stopped(bool flag) { 31 | boost::mutex::scoped_lock lock(mutex_); 32 | stopped_ = flag; 33 | } 34 | 35 | bool stopped() const { 36 | boost::mutex::scoped_lock lock(mutex_); 37 | return stopped_; 38 | } 39 | private: 40 | mutable boost::mutex mutex_; 41 | bool stopped_; 42 | }; 43 | 44 | class ActiveThreadCounter { 45 | public: 46 | ActiveThreadCounter() : count_(0) 47 | {} 48 | void increment() { 49 | boost::mutex::scoped_lock lock(mutex_); 50 | ++count_; 51 | } 52 | void decrement() { 53 | boost::mutex::scoped_lock lock(mutex_); 54 | --count_; 55 | } 56 | 57 | int count() const { 58 | boost::mutex mutex_; 59 | return count_; 60 | } 61 | 62 | private: 63 | boost::mutex mutex_; 64 | int count_; 65 | }; 66 | 67 | class FCGIServer : public Server { 68 | protected: 69 | enum Status {NOT_INITED, LOADING, RUNNING}; 70 | 71 | public: 72 | FCGIServer(boost::shared_ptr globals); 73 | virtual ~FCGIServer(); 74 | 75 | static void writePid(const Config& config); 76 | void start(); 77 | void stop(); 78 | void join(); 79 | 80 | private: 81 | virtual const Globals* globals() const; 82 | virtual Logger* logger() const; 83 | virtual void handleRequest(RequestTask task); 84 | void handle(Endpoint *endpoint); 85 | void monitor(); 86 | 87 | std::string getServerInfo() const; 88 | 89 | void initMonitorThread(); 90 | void initRequestCache(); 91 | void initTimeStatistics(); 92 | void initFastCGISubsystem(); 93 | void initPools(); 94 | void createWorkThreads(); 95 | 96 | void stopInternal(); 97 | 98 | void stopThreadFunction(); 99 | 100 | Status status() const; 101 | 102 | private: 103 | boost::shared_ptr globals_; 104 | boost::shared_ptr stopper_; 105 | 106 | typedef char ThreadHolder; 107 | boost::shared_ptr active_thread_holder_; 108 | 109 | std::vector > endpoints_; 110 | int monitorSocket_; 111 | 112 | RequestCache *request_cache_; 113 | ResponseTimeStatistics *time_statistics_; 114 | 115 | mutable boost::mutex statusInfoMutex_; 116 | Status status_; 117 | 118 | std::auto_ptr monitorThread_; 119 | std::auto_ptr stopThread_; 120 | int stopPipes_[2]; 121 | 122 | bool logTimes_; 123 | boost::thread_group globalPool_; 124 | }; 125 | 126 | } // namespace fastcgi 127 | 128 | #endif // _FASTCGI_FASTCGI_SERVER_H_ 129 | -------------------------------------------------------------------------------- /main/main.cpp: -------------------------------------------------------------------------------- 1 | #include "settings.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #include "fcgi_server.h" 14 | #include "fastcgi2/config.h" 15 | #include "details/globals.h" 16 | 17 | #ifdef HAVE_DMALLOC_H 18 | #include 19 | #endif 20 | 21 | fastcgi::FCGIServer *server; 22 | 23 | bool 24 | daemonize() { 25 | pid_t pid = fork(); 26 | if (pid == -1) { 27 | std::stringstream ss; 28 | ss << "Could not become a daemon: fork #1 failed: " << errno; 29 | throw std::logic_error(ss.str()); 30 | } 31 | if (pid != 0) { 32 | _exit(0); // exit parent 33 | } 34 | 35 | pid_t sid = setsid(); 36 | if (sid == -1) { 37 | std::stringstream ss; 38 | ss << "Could not become a daemon: setsid failed: " << errno;; 39 | throw std::logic_error(ss.str()); 40 | } 41 | 42 | // check fork for child 43 | pid = fork(); 44 | if (pid == -1) { 45 | std::stringstream ss; 46 | ss << "Could not become a daemon: fork #2 failed: " << errno; 47 | throw std::logic_error(ss.str()); 48 | } 49 | if (pid != 0) { 50 | _exit(0); // exit session leader 51 | } 52 | 53 | for (int i = getdtablesize(); i--; ) { 54 | close(i); 55 | } 56 | umask(0002); // disable: S_IWOTH 57 | chdir("/"); 58 | 59 | const char *devnull = "/dev/null"; 60 | stdin = fopen(devnull, "a+"); 61 | if (stdin == NULL) { 62 | return false; 63 | } 64 | stdout = fopen(devnull, "w"); 65 | if (stdout == NULL) { 66 | return false; 67 | } 68 | stderr = fopen(devnull, "w"); 69 | if (stderr == NULL) { 70 | return false; 71 | } 72 | return true; 73 | } 74 | 75 | void 76 | signalHandler(int signo) { 77 | if ((SIGINT == signo || SIGTERM == signo) && ::server != NULL) { 78 | server->stop(); 79 | } 80 | } 81 | 82 | void 83 | setUpSignalHandlers() { 84 | if (SIG_ERR == signal(SIGINT, signalHandler)) { 85 | throw std::runtime_error("Cannot set up SIGINT handler"); 86 | } 87 | if (SIG_ERR == signal(SIGTERM, signalHandler)) { 88 | throw std::runtime_error("Cannot set up SIGTERM handler"); 89 | } 90 | } 91 | 92 | int 93 | main(int argc, char *argv[]) { 94 | using namespace fastcgi; 95 | try { 96 | for (int i = 1; i < argc; ++i) { 97 | if (!strcmp(argv[i], "--daemon")) { 98 | if (!daemonize()) { 99 | return EXIT_FAILURE; 100 | } 101 | break; 102 | } 103 | } 104 | 105 | boost::scoped_ptr config(Config::create(argc, argv)); 106 | FCGIServer::writePid(*config); 107 | boost::shared_ptr globals(new Globals(config.get())); 108 | FCGIServer server(globals); 109 | ::server = &server; 110 | setUpSignalHandlers(); 111 | server.start(); 112 | server.join(); 113 | return EXIT_SUCCESS; 114 | } 115 | catch (const std::exception &e) { 116 | std::cerr << e.what() << std::endl; 117 | return EXIT_FAILURE; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /statistics/Makefile.am: -------------------------------------------------------------------------------- 1 | pkglib_LTLIBRARIES = fastcgi2-statistics.la 2 | 3 | fastcgi2_statistics_la_SOURCES = response_time_handler.cpp 4 | fastcgi2_statistics_la_LIBADD = ../library/libfastcgi-daemon2.la 5 | fastcgi2_statistics_la_LDFLAGS = -module -lpthread 6 | 7 | AM_CPPFLAGS = -I../include -I../config 8 | AM_CXXFLAGS = -pthread 9 | 10 | noinst_HEADERS = response_time_handler.h -------------------------------------------------------------------------------- /statistics/response_time_handler.cpp: -------------------------------------------------------------------------------- 1 | #include "settings.h" 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include "fastcgi2/component_factory.h" 8 | #include "fastcgi2/request.h" 9 | 10 | #include "response_time_handler.h" 11 | 12 | #ifdef HAVE_DMALLOC_H 13 | #include 14 | #endif 15 | 16 | namespace fastcgi 17 | { 18 | 19 | CounterData::CounterData() : min_(std::numeric_limits::max()), 20 | max_(0), total_(0), hits_(0) 21 | {} 22 | 23 | void 24 | CounterData::add(boost::uint64_t time) { 25 | total_ += time; 26 | ++hits_; 27 | min_ = std::min(min_, time); 28 | max_ = std::max(max_, time); 29 | } 30 | 31 | boost::uint64_t 32 | CounterData::min() const { 33 | return min_; 34 | } 35 | 36 | boost::uint64_t 37 | CounterData::max() const { 38 | return max_; 39 | } 40 | 41 | boost::uint64_t 42 | CounterData::avg() const { 43 | return hits_ ? total_/hits_ : 0; 44 | } 45 | 46 | boost::uint64_t 47 | CounterData::hits() const { 48 | return hits_; 49 | } 50 | 51 | ResponseTimeHandler::ResponseTimeHandler(ComponentContext *context) : Component(context) 52 | {} 53 | 54 | ResponseTimeHandler::~ResponseTimeHandler() 55 | {} 56 | 57 | void 58 | ResponseTimeHandler::onLoad() { 59 | } 60 | 61 | void 62 | ResponseTimeHandler::onUnload() { 63 | } 64 | 65 | void 66 | ResponseTimeHandler::handleRequest(Request *req, HandlerContext *handlerContext) { 67 | (void)handlerContext; 68 | std::stringstream str; 69 | str.precision(3); 70 | str << std::showpoint << std::fixed; 71 | str << ""; 72 | str << ""; 73 | { 74 | boost::mutex::scoped_lock lock(mutex_); 75 | for (std::map::iterator iter = data_.begin(); 76 | iter != data_.end(); 77 | ++iter) { 78 | str << "first << "\">"; 79 | for (CounterMapType::iterator it = iter->second.begin(); 80 | it != iter->second.end(); 81 | ++it) { 82 | str << "first << "\""; 84 | str << " avg=\"" << 0.001*it->second->avg() << "\""; 85 | str << " min=\"" << 0.001*it->second->min() << "\""; 86 | str << " max=\"" << 0.001*it->second->max() << "\""; 87 | str << " hits=\"" << it->second->hits() << "\""; 88 | str << "/>"; 89 | } 90 | str << ""; 91 | } 92 | } 93 | str << ""; 94 | req->setStatus(200); 95 | req->write(str.rdbuf()); 96 | } 97 | 98 | void 99 | ResponseTimeHandler::add(const std::string &handler, unsigned short status, boost::uint64_t time) { 100 | boost::mutex::scoped_lock lock(mutex_); 101 | CounterMapType& handle = data_[handler]; 102 | CounterMapType::iterator it = handle.find(status); 103 | if (handle.end() == it) { 104 | boost::shared_ptr counter(new CounterData); 105 | counter->add(time); 106 | handle.insert(std::make_pair(status, counter)); 107 | } 108 | else { 109 | it->second->add(time); 110 | } 111 | } 112 | 113 | } //namespace fastcgi 114 | 115 | FCGIDAEMON_REGISTER_FACTORIES_BEGIN() 116 | FCGIDAEMON_ADD_DEFAULT_FACTORY("statistics", fastcgi::ResponseTimeHandler) 117 | FCGIDAEMON_REGISTER_FACTORIES_END() 118 | -------------------------------------------------------------------------------- /statistics/response_time_handler.h: -------------------------------------------------------------------------------- 1 | #ifndef _FASTCGI_STATISTICS_RESPONSE_TIME_HANDLER_H_ 2 | #define _FASTCGI_STATISTICS_RESPONSE_TIME_HANDLER_H_ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include "fastcgi2/component.h" 10 | #include "fastcgi2/handler.h" 11 | 12 | #include "details/response_time_statistics.h" 13 | 14 | namespace fastcgi 15 | { 16 | 17 | class CounterData { 18 | public: 19 | CounterData(); 20 | void add(boost::uint64_t time); 21 | boost::uint64_t min() const; 22 | boost::uint64_t max() const; 23 | boost::uint64_t avg() const; 24 | boost::uint64_t hits() const; 25 | 26 | private: 27 | boost::uint64_t min_; 28 | boost::uint64_t max_; 29 | boost::uint64_t total_; 30 | boost::uint64_t hits_; 31 | }; 32 | 33 | class ResponseTimeHandler : virtual public Handler, virtual public Component, 34 | virtual public ResponseTimeStatistics { 35 | public: 36 | ResponseTimeHandler(ComponentContext *context); 37 | virtual ~ResponseTimeHandler(); 38 | 39 | virtual void onLoad(); 40 | virtual void onUnload(); 41 | 42 | virtual void handleRequest(Request *req, HandlerContext *handlerContext); 43 | virtual void add(const std::string &handler, unsigned short status, boost::uint64_t time); 44 | 45 | private: 46 | boost::mutex mutex_; 47 | typedef std::map > CounterMapType; 48 | std::map data_; 49 | }; 50 | 51 | } // namespace fastcgi 52 | 53 | #endif // _FASTCGI_STATISTICS_RESPONSE_TIME_HANDLER_H_ 54 | -------------------------------------------------------------------------------- /syslog/Makefile.am: -------------------------------------------------------------------------------- 1 | pkglib_LTLIBRARIES = fastcgi2-syslog.la 2 | 3 | fastcgi2_syslog_la_SOURCES = syslog-logger.cpp 4 | fastcgi2_syslog_la_LIBADD = ../library/libfastcgi-daemon2.la 5 | fastcgi2_syslog_la_LDFLAGS = -module -lpthread 6 | 7 | AM_CPPFLAGS = -I../include -I../config 8 | AM_CXXFLAGS = -pthread 9 | 10 | noinst_HEADERS = syslog-logger.h -------------------------------------------------------------------------------- /syslog/syslog-logger.cpp: -------------------------------------------------------------------------------- 1 | #include "settings.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "fastcgi2/logger.h" 7 | #include "fastcgi2/config.h" 8 | #include "fastcgi2/request.h" 9 | #include "fastcgi2/stream.h" 10 | #include "fastcgi2/component_factory.h" 11 | 12 | #include "syslog-logger.h" 13 | #include 14 | 15 | #ifdef HAVE_DMALLOC_H 16 | #include 17 | #endif 18 | #include 19 | #include 20 | 21 | 22 | namespace fastcgi 23 | { 24 | 25 | SyslogLogger::SyslogLogger(ComponentContext *context) : Component(context) { 26 | const Config *config = context->getConfig(); 27 | const std::string componentXPath = context->getComponentXPath(); 28 | /* 29 | std::string globalLogIdent = config->asString("/fastcgi/daemon/global-log-ident"); 30 | const int facility = config->asInt(componentXPath + "/facility", 0); 31 | if (facility < 0 || facility > 6) { 32 | throw std::runtime_error("SyslogLogger: facility must be in range 0..6"); 33 | } 34 | openlog(globalLogIdent.c_str(), 0, facility); 35 | */ 36 | ident_ = config->asString(componentXPath + "/ident"); 37 | 38 | setLevel(stringToLevel(config->asString(componentXPath + "/level"))); 39 | 40 | requestSpecificIdent_ = (config->asString(componentXPath + "/request-specific-ident", "off") == "on"); 41 | } 42 | 43 | SyslogLogger::~SyslogLogger() { 44 | } 45 | 46 | void SyslogLogger::onLoad() { 47 | } 48 | 49 | void SyslogLogger::onUnload() { 50 | } 51 | 52 | void SyslogLogger::handleRequest(Request *request, HandlerContext *handlerContext) { 53 | request->setContentType("text/plain"); 54 | const std::string &action = request->getArg("action"); 55 | if ("setlevel" == action) { 56 | const std::string &l = request->getArg("level"); 57 | setLevel(stringToLevel(l)); 58 | RequestStream(request) << "level " << l << "successfully set" << std::endl; 59 | } 60 | else if ("rollover" == action) { 61 | rollOver(); 62 | RequestStream(request) << "rollover successful" << std::endl; 63 | } 64 | else { 65 | RequestStream(request) << "bad action" << std::endl; 66 | } 67 | } 68 | 69 | void SyslogLogger::log(const Level level, const char *format, va_list args) { 70 | if (level >= getLevel()) { 71 | std::string format_ident; 72 | 73 | if (requestSpecificIdent_ && threadIdent_.get()) { 74 | format_ident = ident_ + ":" + *threadIdent_ + ": %s"; 75 | } else { 76 | format_ident = ident_ + ": %s"; 77 | } 78 | 79 | std::string formatted(1024*10, '\0'); 80 | 81 | vsnprintf(const_cast(formatted.data()), formatted.size(), format, args); 82 | 83 | std::string tmp; 84 | std::stringstream ss(formatted); 85 | 86 | while (ss.good()) { 87 | std::getline(ss, tmp, '\n'); 88 | syslog(toSyslogPriority(level), format_ident.c_str(), tmp.c_str()); 89 | } 90 | 91 | //vsyslog(toSyslogPriority(level), signedFormat.c_str(), args); 92 | } 93 | } 94 | 95 | void SyslogLogger::setLevelInternal(const Level level) { 96 | priority_ = toSyslogPriority(level); 97 | } 98 | 99 | void SyslogLogger::rollOver() { 100 | } 101 | 102 | void SyslogLogger::setRequestId(const std::string &id) { 103 | threadIdent_.reset(new std::string(id)); 104 | } 105 | 106 | std::string SyslogLogger::getRequestId() { 107 | if (requestSpecificIdent_ && threadIdent_.get()) { 108 | return *threadIdent_; 109 | } 110 | return std::string(); 111 | } 112 | 113 | int 114 | SyslogLogger::toSyslogPriority(const Level level) { 115 | switch (level) { 116 | case INFO: 117 | return LOG_INFO; 118 | case DEBUG: 119 | return LOG_DEBUG; 120 | case ERROR: 121 | return LOG_ERR; 122 | case EMERGENCY: 123 | return LOG_EMERG; 124 | default: 125 | throw std::logic_error("SyslogLogger: unknown log level"); 126 | } 127 | } 128 | 129 | } //namespace fastcgi 130 | 131 | FCGIDAEMON_REGISTER_FACTORIES_BEGIN() 132 | FCGIDAEMON_ADD_DEFAULT_FACTORY("logger", fastcgi::SyslogLogger) 133 | FCGIDAEMON_REGISTER_FACTORIES_END() 134 | -------------------------------------------------------------------------------- /syslog/syslog-logger.h: -------------------------------------------------------------------------------- 1 | #ifndef _FASTCGI_SYSLOG_LOGGER_H_ 2 | #define _FASTCGI_SYSLOG_LOGGER_H_ 3 | 4 | #include "fastcgi2/logger.h" 5 | #include "fastcgi2/component.h" 6 | #include "fastcgi2/handler.h" 7 | 8 | #include 9 | #include 10 | 11 | namespace fastcgi 12 | { 13 | 14 | class SyslogLogger : virtual public Logger, virtual public Component, virtual public Handler, virtual public LoggerRequestId 15 | { 16 | public: 17 | SyslogLogger(ComponentContext *context); 18 | virtual ~SyslogLogger(); 19 | 20 | virtual void onLoad(); 21 | virtual void onUnload(); 22 | 23 | virtual void handleRequest(Request *request, HandlerContext *handlerContext); 24 | 25 | virtual void setRequestId(const std::string &id); 26 | virtual std::string getRequestId(); 27 | 28 | protected: 29 | virtual void log(const Level level, const char *format, va_list args); 30 | virtual void setLevelInternal(const Level level); 31 | virtual void rollOver(); 32 | 33 | private: 34 | static int toSyslogPriority(const Level level); 35 | 36 | private: 37 | std::string ident_; 38 | int priority_; 39 | bool requestSpecificIdent_; 40 | boost::thread_specific_ptr threadIdent_; 41 | }; 42 | 43 | } // namespace fastcgi 44 | 45 | #endif // _FASTCGI_SYSLOG_LOGGER_H_ 46 | -------------------------------------------------------------------------------- /tests/Makefile.am: -------------------------------------------------------------------------------- 1 | check_PROGRAMS = test 2 | 3 | test_SOURCES = main.cpp test_request.cpp test_config.cpp 4 | 5 | test_CPPFLAGS = -I../include -I../config @CPPUNIT_CFLAGS@ 6 | test_CXXFLAGS = -pthread 7 | 8 | test_LDADD = ../library/libfastcgi-daemon2.la 9 | test_LDFLAGS = -lpthread @CPPUNIT_LIBS@ 10 | 11 | noinst_DATA = multipart-test-rn.dat multipart-test-n.dat test.conf 12 | 13 | TESTS = test 14 | -------------------------------------------------------------------------------- /tests/main.cpp: -------------------------------------------------------------------------------- 1 | #include "settings.h" 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #ifdef HAVE_DMALLOC_H 9 | #include 10 | #endif 11 | 12 | int 13 | main(int argc, char *argv[]) { 14 | 15 | CppUnit::TextUi::TestRunner r; 16 | r.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest()); 17 | return r.run("", false) ? EXIT_SUCCESS : EXIT_FAILURE; 18 | } 19 | -------------------------------------------------------------------------------- /tests/multipart-test-n.dat: -------------------------------------------------------------------------------- 1 | -----------------------------15403834263040891721303455736 2 | Content-Disposition: form-data; name="username" 3 | 4 | test 5 | -----------------------------15403834263040891721303455736 6 | Content-Disposition: form-data; name="filename" 7 | 8 | test 9 | -----------------------------15403834263040891721303455736 10 | Content-Disposition: form-data; 11 | name="some_long_long_long_long_long_long_filename.ext" 12 | 13 | file content 14 | -----------------------------15403834263040891721303455736 15 | Content-Disposition: form-data; name="uploaded"; filename="nopasswd.pem" 16 | Content-Type: application/octet-stream 17 | 18 | -----BEGIN RSA PRIVATE KEY----- 19 | MIICXQIBAAKBgQCxfqGk8LlB01g13KQLRvRgp9up2hHWfR3n5a+WwWuI1G7k/gaJ 20 | kdDOKpiv4NzYaoA4PjjKyhdnp8RvtqnXY7cHUkfC9fwkyrYOJdAbtU8zCpuHsmqp 21 | ZplKXhRi3FDOFtRwtP/dwwtT9pBBLicBHJ+YTufsUF6tLtnbI49d2t1XawIDAQAB 22 | AoGBAJ17oaha/cRt5IJFtjdbSVDJHplhpxoMARDUNisoimTpN0tuKBa/jeie2sKS 23 | XOCX/hPpATLMhF+v9xa3l5JIIwedfh06apLWOEEUI46UJ0p5B6rbmUxXU/BjDu6/ 24 | Lvg0rR5wyD5dnjT4afqbIwFWTp+lUZIvB+C7H799KGMk1v7hAkEA3Df7jWmMl3n+ 25 | m/4g91mlmn9Mjh3Y8F02ubs0CuezMTslZ5YfT9VQhTSPi1ZGrMlcn5Ac1jZtinSy 26 | rz2XmgGbzwJBAM5VielE5IT3vG8VyNX9KomVNr4Sa0VLap+UONi2FQRAnOZdHwQx 27 | i/Ig/FVtyrh2LaZbPyQawp0nvVhNVdeBJaUCQGXYSjEjQE8Jr3OrOsnKHultuBT9 28 | vsejBF0vM6lbcKbzCKB4cDC2oY+JOF2jX/onAfwVZRC4iT6AK+cZoBQsbEcCQQCS 29 | wsb4c/czGN8gCFe01YEnIUoxwfoo7K6nWQ9iHYkvYCH5vOyt1+wZyhqRTSmvMOfh 30 | du+fZ6VbkQOdxkwzn/m9AkBfrLTH30U2ZrfJEPA2yE4A34z8QSm4ze8b84L6HIqR 31 | 9ogJ3Sala0RGNbqpHWJFAQGE/hVURrXDlEHgX4Rsxa36 32 | -----END RSA PRIVATE KEY----- 33 | 34 | -----------------------------15403834263040891721303455736-- 35 | -------------------------------------------------------------------------------- /tests/multipart-test-rn.dat: -------------------------------------------------------------------------------- 1 | -----------------------------15403834263040891721303455736 2 | Content-Disposition: form-data; name="username" 3 | 4 | test 5 | -----------------------------15403834263040891721303455736 6 | Content-Disposition: form-data; name="filename" 7 | 8 | test 9 | -----------------------------15403834263040891721303455736 10 | Content-Disposition: form-data; name="uploaded"; filename="nopasswd.pem" 11 | Content-Type: application/octet-stream 12 | 13 | -----BEGIN RSA PRIVATE KEY----- 14 | MIICXQIBAAKBgQCxfqGk8LlB01g13KQLRvRgp9up2hHWfR3n5a+WwWuI1G7k/gaJ 15 | kdDOKpiv4NzYaoA4PjjKyhdnp8RvtqnXY7cHUkfC9fwkyrYOJdAbtU8zCpuHsmqp 16 | ZplKXhRi3FDOFtRwtP/dwwtT9pBBLicBHJ+YTufsUF6tLtnbI49d2t1XawIDAQAB 17 | AoGBAJ17oaha/cRt5IJFtjdbSVDJHplhpxoMARDUNisoimTpN0tuKBa/jeie2sKS 18 | XOCX/hPpATLMhF+v9xa3l5JIIwedfh06apLWOEEUI46UJ0p5B6rbmUxXU/BjDu6/ 19 | Lvg0rR5wyD5dnjT4afqbIwFWTp+lUZIvB+C7H799KGMk1v7hAkEA3Df7jWmMl3n+ 20 | m/4g91mlmn9Mjh3Y8F02ubs0CuezMTslZ5YfT9VQhTSPi1ZGrMlcn5Ac1jZtinSy 21 | rz2XmgGbzwJBAM5VielE5IT3vG8VyNX9KomVNr4Sa0VLap+UONi2FQRAnOZdHwQx 22 | i/Ig/FVtyrh2LaZbPyQawp0nvVhNVdeBJaUCQGXYSjEjQE8Jr3OrOsnKHultuBT9 23 | vsejBF0vM6lbcKbzCKB4cDC2oY+JOF2jX/onAfwVZRC4iT6AK+cZoBQsbEcCQQCS 24 | wsb4c/czGN8gCFe01YEnIUoxwfoo7K6nWQ9iHYkvYCH5vOyt1+wZyhqRTSmvMOfh 25 | du+fZ6VbkQOdxkwzn/m9AkBfrLTH30U2ZrfJEPA2yE4A34z8QSm4ze8b84L6HIqR 26 | 9ogJ3Sala0RGNbqpHWJFAQGE/hVURrXDlEHgX4Rsxa36 27 | -----END RSA PRIVATE KEY----- 28 | 29 | -----------------------------15403834263040891721303455736-- 30 | -------------------------------------------------------------------------------- /tests/multipart-test-rn2.dat: -------------------------------------------------------------------------------- 1 | --AaB03x 2 | content-disposition: form-data; name="field1" 3 | 4 | Joe Blow 5 | --AaB03x 6 | content-disposition: form-data; name="pics" 7 | Content-type: multipart/mixed, boundary=BbC04y 8 | 9 | --BbC04y 10 | Content-disposition: attachment; name="file1"; filename="file1.txt" 11 | Content-Type: text/plain 12 | 13 | ... contents of file1.txt ... 14 | --BbC04y 15 | Content-disposition: attachment; name="file2"; filename="file2.gif" 16 | Content-type: image/gif 17 | Content-Transfer-Encoding: binary 18 | 19 | ...contents of file2.gif... 20 | --BbC04y-- 21 | --AaB03x-- 22 | -------------------------------------------------------------------------------- /tests/test.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | example 5 | 6 | 7 | daemon-logger 8 | DEBUG 9 | ${id} 10 | 11 | 10 12 | /tmp/${id}.sock 13 | 14 | /var/run/fastcgi-${id}.pid 15 | 50 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /tests/test_config.cpp: -------------------------------------------------------------------------------- 1 | #include "settings.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "fastcgi2/config.h" 7 | 8 | #ifdef HAVE_DMALLOC_H 9 | #include 10 | #endif 11 | 12 | class ConfigTest : public CppUnit::TestFixture 13 | { 14 | public: 15 | void testConfig(); 16 | 17 | private: 18 | CPPUNIT_TEST_SUITE(ConfigTest); 19 | CPPUNIT_TEST(testConfig); 20 | CPPUNIT_TEST_SUITE_END(); 21 | }; 22 | 23 | CPPUNIT_TEST_SUITE_REGISTRATION(ConfigTest); 24 | 25 | void 26 | ConfigTest::testConfig() { 27 | 28 | using namespace fastcgi; 29 | 30 | std::vector v; 31 | std::auto_ptr config = Config::create("test.conf"); 32 | 33 | CPPUNIT_ASSERT_EQUAL(10, config->asInt("/fastcgi/daemon/endpoint/backlog")); 34 | CPPUNIT_ASSERT_EQUAL(std::string("/tmp/example.sock"), config->asString("/fastcgi/daemon/endpoint/socket")); 35 | 36 | config->subKeys("/fastcgi/modules/module", v); 37 | CPPUNIT_ASSERT_EQUAL(static_cast::size_type>(1), v.size()); 38 | } 39 | --------------------------------------------------------------------------------