summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArno Töll <arno@debian.org>2012-11-21 23:03:36 +0100
committerArno Töll <arno@debian.org>2012-11-21 23:03:36 +0100
commit0e7d1e864fb7bc92f3bbab4a9a0f154ad00fd76e (patch)
treee0098274febb4c76579f70e9f6a7bd35ba189a7d
parenteb45c46b906e492f063f1469486190e93ff340ff (diff)
downloadlighttpd-0e7d1e864fb7bc92f3bbab4a9a0f154ad00fd76e.tar.gz
Imported Upstream version 1.4.11upstream/1.4.11
-rw-r--r--NEWS19
-rwxr-xr-xconfigure22
-rw-r--r--configure.in5
-rw-r--r--cygwin/lighttpd.README10
-rw-r--r--doc/Makefile.am8
-rw-r--r--doc/Makefile.in8
-rw-r--r--doc/cml.txt2
-rw-r--r--doc/configuration.txt71
-rw-r--r--doc/dirlisting.txt82
-rw-r--r--doc/evhost.txt45
-rw-r--r--doc/fastcgi.txt2
-rw-r--r--doc/lighttpd.conf1
-rwxr-xr-xdoc/rc.lighttpd3
-rw-r--r--lighttpd.spec2
-rw-r--r--openwrt/control4
-rw-r--r--openwrt/lighttpd.mk2
-rw-r--r--src/Makefile.am12
-rw-r--r--src/Makefile.in70
-rw-r--r--src/configfile-glue.c2
-rw-r--r--src/connections.c2
-rw-r--r--src/keyvalue.c4
-rw-r--r--src/keyvalue.h4
-rw-r--r--src/mod_alias.c4
-rw-r--r--src/mod_auth.c36
-rw-r--r--src/mod_cgi.c24
-rw-r--r--src/mod_fastcgi.c685
-rw-r--r--src/mod_flv_streaming.c278
-rw-r--r--src/mod_scgi.c4
-rw-r--r--src/mod_ssi.c14
-rw-r--r--src/mod_webdav.c4
-rw-r--r--src/network.c16
-rw-r--r--src/network_linux_sendfile.c39
-rw-r--r--src/network_writev.c4
-rw-r--r--src/request.c53
-rw-r--r--src/response.c36
-rw-r--r--src/server.c4
-rw-r--r--src/spawn-fcgi.c17
-rwxr-xr-xtests/core.t32
-rw-r--r--tests/lighttpd.conf3
-rwxr-xr-xtests/mod-fastcgi.t11
-rwxr-xr-xtests/request.t2
-rwxr-xr-xtests/wrapper.sh6
42 files changed, 1128 insertions, 524 deletions
diff --git a/NEWS b/NEWS
index 6141e31..5c03cf9 100644
--- a/NEWS
+++ b/NEWS
@@ -3,7 +3,24 @@
NEWS
====
-- 1.4.10 - 2005-02-08
+- 1.4.11 - 2006-03-09
+
+ * added ability to specify which ip address spawn-fci listens on
+ (agkr@pobox.com)
+ * added mod_flv_streaming to streaming Flash Movies efficiently
+ * fixed handling of error codes returned by mod_dav_svn behing a
+ mod_proxy
+ * fixed error-messages in mod_auth and mod_fastcgi
+ * fixed re-enabling overloaded local fastcgi backends
+ * fixed handling of deleted files in linux-sendfile
+ * fixed compilation on BSD and MacOSX
+ * fixed $SERVER["socket"] on a already bound socket
+ * fixed local source retrieval on windows
+ (secunia)
+ * fixed hanging cgi if remote side is dieing while reading
+ from the pipe (sandy@meebo.com)
+
+- 1.4.10 - 2006-02-08
* added docs for mod_dirlisting
* added fastcgi.map-extensions to mod_fastcgi
diff --git a/configure b/configure
index 96969dd..002d2c7 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.59 for lighttpd 1.4.10.
+# Generated by GNU Autoconf 2.59 for lighttpd 1.4.11.
#
# Report bugs to <jan@kneschke.de>.
#
@@ -423,8 +423,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='lighttpd'
PACKAGE_TARNAME='lighttpd'
-PACKAGE_VERSION='1.4.10'
-PACKAGE_STRING='lighttpd 1.4.10'
+PACKAGE_VERSION='1.4.11'
+PACKAGE_STRING='lighttpd 1.4.11'
PACKAGE_BUGREPORT='jan@kneschke.de'
ac_unique_file="src/server.c"
@@ -954,7 +954,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures lighttpd 1.4.10 to adapt to many kinds of systems.
+\`configure' configures lighttpd 1.4.11 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1021,7 +1021,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of lighttpd 1.4.10:";;
+ short | recursive ) echo "Configuration of lighttpd 1.4.11:";;
esac
cat <<\_ACEOF
@@ -1183,7 +1183,7 @@ fi
test -n "$ac_init_help" && exit 0
if $ac_init_version; then
cat <<\_ACEOF
-lighttpd configure 1.4.10
+lighttpd configure 1.4.11
generated by GNU Autoconf 2.59
Copyright (C) 2003 Free Software Foundation, Inc.
@@ -1197,7 +1197,7 @@ cat >&5 <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by lighttpd $as_me 1.4.10, which was
+It was created by lighttpd $as_me 1.4.11, which was
generated by GNU Autoconf 2.59. Invocation command line was
$ $0 $@
@@ -1925,7 +1925,7 @@ fi
# Define the identity of the package.
PACKAGE='lighttpd'
- VERSION='1.4.10'
+ VERSION='1.4.11'
cat >>confdefs.h <<_ACEOF
@@ -27390,8 +27390,6 @@ case $host_os in
* ) ;;
esac
-CFLAGS="${CFLAGS} -D_XOPEN_SOURCE=600 -D_BSD_SOURCE"
-
@@ -29203,7 +29201,7 @@ _ASBOX
} >&5
cat >&5 <<_CSEOF
-This file was extended by lighttpd $as_me 1.4.10, which was
+This file was extended by lighttpd $as_me 1.4.11, which was
generated by GNU Autoconf 2.59. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -29266,7 +29264,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
-lighttpd config.status 1.4.10
+lighttpd config.status 1.4.11
configured by $0, generated by GNU Autoconf 2.59,
with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
diff --git a/configure.in b/configure.in
index 128d84d..96391f5 100644
--- a/configure.in
+++ b/configure.in
@@ -1,7 +1,7 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.57)
-AC_INIT(lighttpd, 1.4.10, jan@kneschke.de)
+AC_INIT(lighttpd, 1.4.11, jan@kneschke.de)
AC_CONFIG_SRCDIR([src/server.c])
AC_CANONICAL_TARGET
@@ -439,9 +439,6 @@ case $host_os in
* ) ;;
esac
-dnl posix_* needs _XOPEN_SOURCE=600
-CFLAGS="${CFLAGS} -D_XOPEN_SOURCE=600 -D_BSD_SOURCE"
-
AC_CHECK_FUNCS([dup2 getcwd inet_ntoa inet_ntop memset mmap munmap strchr \
strdup strerror strstr strtol sendfile getopt socket \
gethostbyname poll sigtimedwait epoll_ctl getrlimit chroot \
diff --git a/cygwin/lighttpd.README b/cygwin/lighttpd.README
index b1af4f9..21a6b5f 100644
--- a/cygwin/lighttpd.README
+++ b/cygwin/lighttpd.README
@@ -31,17 +31,17 @@ Canonical download:
------------------------------------
Build instructions:
- unpack lighttpd-1.4.10-<REL>-src.tar.bz2
+ unpack lighttpd-1.4.11-<REL>-src.tar.bz2
if you use setup to install this src package, it will be
unpacked under /usr/src automatically
cd /usr/src
- ./lighttpd-1.4.10-<REL>.sh all
+ ./lighttpd-1.4.11-<REL>.sh all
This will create:
- /usr/src/lighttpd-1.4.10-<REL>.tar.bz2
- /usr/src/lighttpd-1.4.10-<REL>-src.tar.bz2
+ /usr/src/lighttpd-1.4.11-<REL>.tar.bz2
+ /usr/src/lighttpd-1.4.11-<REL>-src.tar.bz2
-Or use './lighttpd-1.4.10-<REL>.sh prep' to get a patched source directory
+Or use './lighttpd-1.4.11-<REL>.sh prep' to get a patched source directory
-------------------------------------------
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 043e570..47ca576 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -33,7 +33,9 @@ scgi.txt \
cml.txt \
trigger_b4_dl.txt \
webdav.txt \
-expire.txt
+expire.txt \
+dirlisting.txt \
+evhost.txt
HTMLDOCS=accesslog.html \
authentication.html \
@@ -67,7 +69,9 @@ HTMLDOCS=accesslog.html \
cml.html \
trigger_b4_dl.html \
webdav.html \
- expire.html
+ expire.html \
+ dirlisting.html \
+ evhost.html
EXTRA_DIST=lighttpd.conf lighttpd.user \
rc.lighttpd rc.lighttpd.redhat sysconfig.lighttpd \
diff --git a/doc/Makefile.in b/doc/Makefile.in
index 219b2f2..b12f424 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -222,7 +222,9 @@ scgi.txt \
cml.txt \
trigger_b4_dl.txt \
webdav.txt \
-expire.txt
+expire.txt \
+dirlisting.txt \
+evhost.txt
HTMLDOCS = accesslog.html \
authentication.html \
@@ -256,7 +258,9 @@ HTMLDOCS = accesslog.html \
cml.html \
trigger_b4_dl.html \
webdav.html \
- expire.html
+ expire.html \
+ dirlisting.html \
+ evhost.html
EXTRA_DIST = lighttpd.conf lighttpd.user \
rc.lighttpd rc.lighttpd.redhat sysconfig.lighttpd \
diff --git a/doc/cml.txt b/doc/cml.txt
index ddae340..ae69067 100644
--- a/doc/cml.txt
+++ b/doc/cml.txt
@@ -140,7 +140,7 @@ Don't forget: Webserver are built to send out static content, that is what they
The index.cml for this looks like: ::
- output_content_type = "text/html"
+ output_contenttype = "text/html"
cwd = request["CWD"]
diff --git a/doc/configuration.txt b/doc/configuration.txt
index c984a3f..2b60e58 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -7,8 +7,8 @@ Module: core
------------
:Author: Jan Kneschke
-:Date: $Date: 2006-02-01 13:05:01 +0100 (Wed, 01 Feb 2006) $
-:Revision: $Revision: 979 $
+:Date: $Date: 2006-03-09 01:10:40 +0100 (Thu, 09 Mar 2006) $
+:Revision: $Revision: 1034 $
:abstract:
the layout of the configuration file
@@ -162,8 +162,46 @@ Example
}
}
+Using variables
+===============
+
+You can set your own variables in the configuration to simplify your config.
+::
+
+ var.basedir = "/home/www/servers/"
+ $HTTP["host"] == "www.example.org" {
+ server.name = "www.example.org"
+ include "incl-base.conf"
+ }
+
+ in incl-base.conf:
+ server.document-root = basedir + server.name + "/pages/"
+ accesslog.filename = basedir + server.name + "/logs/access.log"
+
+You can also use environement variables or the default variables var.PID and
+var.CWD: ::
+
+ var.basedir = env.LIGHTTPDBASE
+
+ $HTTP["host"] == "www.example.org" {
+ server.name = "www.example.org"
+ include "incl-base.conf"
+ include "incl-fastcgi.conf"
+ }
+
+ in incl-fastcgi.conf:
+ fastcgi.server = ( ... => ((
+ "socket" => basedir + server.name + "/tmp/fastcgi-" + PID + ".sock"
+ )) )
+
+Or like the lighttpd script for rails does:
+
+ var.basedir = var.CWD
+
+ server.document-root = basedir + "/public/"
+
Global context
-=========================
+==============
::
@@ -281,10 +319,21 @@ index-file.names
server.modules
modules to load
-.. note:: the order of the modules is somewhat important as the modules are
- handled in the way they are specified. mod_rewrite should always be
- the first module, mod_accesslog always the last.
-
+.. note:: the order of the modules is important.
+
+ The modules are executed in the order as they are specified. Loading
+ mod_auth AFTER mod_fastcgi might disable authentication for fastcgi
+ backends (if check-local is disabled).
+
+ As auth should be done first, move it before all executing modules (like
+ proxy, fastcgi, scgi and cgi).
+
+ rewrites, redirects and access should be first, followed by auth and
+ the docroot plugins.
+
+ Afterwards the external handlers like fastcgi, cgi, scgi and proxy and
+ at the bottom the post-processing plugins like mod_accesslog.
+
e.g.: ::
server.modules = ( "mod_rewrite",
@@ -293,17 +342,17 @@ server.modules
"mod_access",
"mod_auth",
"mod_status",
- "mod_fastcgi",
- "mod_proxy",
"mod_simple_vhost",
"mod_evhost",
"mod_userdir",
+ "mod_secdownload",
+ "mod_fastcgi",
+ "mod_proxy",
"mod_cgi",
- "mod_compress",
"mod_ssi",
+ "mod_compress",
"mod_usertrack",
"mod_expire",
- "mod_secdownload",
"mod_rrdtool",
"mod_accesslog" )
diff --git a/doc/dirlisting.txt b/doc/dirlisting.txt
new file mode 100644
index 0000000..ea65ba6
--- /dev/null
+++ b/doc/dirlisting.txt
@@ -0,0 +1,82 @@
+==================
+Directory Listings
+==================
+
+----------------------
+Module: mod_dirlisting
+----------------------
+
+:Author: Jan Kneschke
+:Date: $Date: 2004/11/03 22:26:05 $
+:Revision: $Revision: 1.2 $
+
+:abstract:
+ mod_dirlisting generates HTML based directory listings with full CSS
+ control
+
+.. meta::
+ :keywords: lighttpd, directory listings, dirlisting
+
+.. contents:: Table of Contents
+
+Description
+===========
+
+mod_dirlisting is one of the modules which is loaded by default and don't have to
+be specified on server.modules to work.
+
+A directory listing is generated if a directory is requested and no index-file
+was found in that directory.
+
+To enable directory listings globally: ::
+
+ dir-listing.activate = "enable"
+
+If you need it only for a directory, use conditionals: ::
+
+ $HTTP["url"] =~ "^/download($|/)" {
+ dir-listing.activate = "enable"
+ }
+
+You can also use a external generator for directory listings if you use
+mod_indexfile. ::
+
+ index-file.names = ( "/dir-generator.php" )
+
+If a directory is requested the dir-generator.php is called instead which can
+take the REQUEST_URI to see which directory was requested.
+
+For large folders this is highly recommend.
+
+Options
+=======
+
+dir-listing.activate
+ enables virtual directory listings if a directory is requested no
+ index-file was found
+
+ Default: disabled
+
+dir-listing.hide-dotfiles
+ if enabled, does not list hidden files in directory listings generated
+ by the dir-listing option.
+
+ Default: enabled
+
+dir-listing.external-css
+ path to an external css stylesheet for the directory listing
+
+dir-listing.exclude
+ list of regular expressions. Files that match any of the specified regular
+ expressions will be excluded from directory listings.
+
+dir-listing.encoding
+ set a encoding for the generated directory listing
+
+ If you file-system is not using ASCII you have to set the encoding of
+ the filenames as they are put into the HTML listing AS IS (with XML
+ encoding)
+
+ Example: ::
+
+ dir-listing.encoding = "utf-8"
diff --git a/doc/evhost.txt b/doc/evhost.txt
new file mode 100644
index 0000000..9e79b03
--- /dev/null
+++ b/doc/evhost.txt
@@ -0,0 +1,45 @@
+========================
+Enhanced Virtual-Hosting
+========================
+
+------------------
+Module: mod_evhost
+------------------
+
+:Author: Jan Kneschke
+:Date: $Date: 2004/08/29 09:43:49 $
+:Revision: $Revision: 1.1 $
+
+:abstract:
+ virtual hosting
+
+.. meta::
+ :keywords: lighttpd, virtual hosting
+
+.. contents:: Table of Contents
+
+Description
+===========
+
+mod_evhost builds the document-root based on a pattern which contains
+wildcards. Those wildcards can represent parts if the submitted hostname
+
+
+::
+
+ %% => % sign
+ %0 => domain name + tld
+ %1 => tld
+ %2 => domain name without tld
+ %3 => subdomain 1 name
+ %4 => subdomain 2 name
+
+ evhost.path-pattern = "/home/www/servers/%3/pages/"
+
+Options
+=======
+
+evhost.path-pattern
+ pattern with wildcards to be replace to build a documentroot
+
+
diff --git a/doc/fastcgi.txt b/doc/fastcgi.txt
index 01a8666..a29cf48 100644
--- a/doc/fastcgi.txt
+++ b/doc/fastcgi.txt
@@ -77,7 +77,7 @@ fastcgi.debug
FastCGI module. Currently only 0 and 1 are used. Use 1 to
enable some debug output, 0 to disable it.
-fastcgi.max-extensions
+fastcgi.map-extensions
map multiple extensions to the same fastcgi server
Example: ::
diff --git a/doc/lighttpd.conf b/doc/lighttpd.conf
index 28402ea..6a273cf 100644
--- a/doc/lighttpd.conf
+++ b/doc/lighttpd.conf
@@ -205,6 +205,7 @@ static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )
#### fastcgi module
## read fastcgi.txt for more info
+## for PHP don't forget to set cgi.fix_pathinfo = 1 in the php.ini
#fastcgi.server = ( ".php" =>
# ( "localhost" =>
# (
diff --git a/doc/rc.lighttpd b/doc/rc.lighttpd
index 91accdd..4dd2a1e 100755
--- a/doc/rc.lighttpd
+++ b/doc/rc.lighttpd
@@ -111,8 +111,7 @@ case "$1" in
# Remember status and be quiet
rc_status
;;
- force-reload)
- reload)
+ force-reload|reload)
## Like force-reload, but if daemon does not support
## signalling, do nothing (!)
diff --git a/lighttpd.spec b/lighttpd.spec
index 69c08fa..170ebbf 100644
--- a/lighttpd.spec
+++ b/lighttpd.spec
@@ -1,6 +1,6 @@
Summary: A fast webserver with minimal memory-footprint (lighttpd)
Name: lighttpd
-Version: 1.4.10
+Version: 1.4.11
Release: 1
Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-%version.tar.gz
Packager: Jan Kneschke <jan@kneschke.de>
diff --git a/openwrt/control b/openwrt/control
index f1fdd46..d2bec04 100644
--- a/openwrt/control
+++ b/openwrt/control
@@ -1,8 +1,8 @@
Package: lighttpd
-Version: 1.4.10
+Version: 1.4.11
Architecture: mipsel
Maintainer: Jan Kneschke <jan@kneschke.de>
-Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-1.4.10.tar.gz
+Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-1.4.11.tar.gz
Section: net
Priority: optional
Depends:
diff --git a/openwrt/lighttpd.mk b/openwrt/lighttpd.mk
index bece136..adcc8d2 100644
--- a/openwrt/lighttpd.mk
+++ b/openwrt/lighttpd.mk
@@ -10,7 +10,7 @@
# For this example we'll use a fairly simple package that compiles easily
# and has sources available for download at sourceforge
-LIGHTTPD=lighttpd-1.4.10
+LIGHTTPD=lighttpd-1.4.11
LIGHTTPD_TARGET=.built
LIGHTTPD_DIR=$(BUILD_DIR)/$(LIGHTTPD)
LIGHTTPD_IPK=$(BUILD_DIR)/$(LIGHTTPD)_mipsel.ipk
diff --git a/src/Makefile.am b/src/Makefile.am
index 7e9fc9e..ffec47e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,3 +1,5 @@
+AM_CFLAGS = $(FAM_CFLAGS)
+
noinst_PROGRAMS=proc_open lemon # simple-fcgi #graphic evalo bench ajp ssl error_test adserver gen-license
sbin_PROGRAMS=lighttpd
bin_PROGRAMS=spawn-fcgi
@@ -59,7 +61,7 @@ if NO_RDYNAMIC
# everything
lib_LTLIBRARIES += liblightcomp.la
liblightcomp_la_SOURCES=$(common_src)
-liblightcomp_la_CFLAGS=$(AM_CFLAGS) $(FAM_CFLAGS)
+liblightcomp_la_CFLAGS=$(AM_CFLAGS)
liblightcomp_la_LDFLAGS = -avoid-version -no-undefined
liblightcomp_la_LIBADD = $(PCRE_LIB) $(SSL_LIB) $(FAM_LIBS)
common_libadd = liblightcomp.la
@@ -68,15 +70,19 @@ src += $(common_src)
common_libadd =
endif
+lib_LTLIBRARIES += mod_flv_streaming.la
+mod_flv_streaming_la_SOURCES = mod_flv_streaming.c
+mod_flv_streaming_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
+mod_flv_streaming_la_LIBADD = $(common_libadd)
+
lib_LTLIBRARIES += mod_evasive.la
mod_evasive_la_SOURCES = mod_evasive.c
mod_evasive_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
mod_evasive_la_LIBADD = $(common_libadd)
-
lib_LTLIBRARIES += mod_webdav.la
mod_webdav_la_SOURCES = mod_webdav.c
-mod_webdav_la_CFLAGS = $(XML_CFLAGS)
+mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS)
mod_webdav_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS)
diff --git a/src/Makefile.in b/src/Makefile.in
index cc6fab9..5b7e8c2 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -16,7 +16,7 @@
-SOURCES = $(liblightcomp_la_SOURCES) $(mod_access_la_SOURCES) $(mod_accesslog_la_SOURCES) $(mod_alias_la_SOURCES) $(mod_auth_la_SOURCES) $(mod_cgi_la_SOURCES) $(mod_cml_la_SOURCES) $(mod_compress_la_SOURCES) $(mod_dirlisting_la_SOURCES) $(mod_evasive_la_SOURCES) $(mod_evhost_la_SOURCES) $(mod_expire_la_SOURCES) $(mod_fastcgi_la_SOURCES) $(mod_indexfile_la_SOURCES) $(mod_mysql_vhost_la_SOURCES) $(mod_proxy_la_SOURCES) $(mod_redirect_la_SOURCES) $(mod_rewrite_la_SOURCES) $(mod_rrdtool_la_SOURCES) $(mod_scgi_la_SOURCES) $(mod_secdownload_la_SOURCES) $(mod_setenv_la_SOURCES) $(mod_simple_vhost_la_SOURCES) $(mod_ssi_la_SOURCES) $(mod_staticfile_la_SOURCES) $(mod_status_la_SOURCES) $(mod_trigger_b4_dl_la_SOURCES) $(mod_userdir_la_SOURCES) $(mod_usertrack_la_SOURCES) $(mod_webdav_la_SOURCES) $(lemon_SOURCES) $(lighttpd_SOURCES) $(proc_open_SOURCES) $(spawn_fcgi_SOURCES)
+SOURCES = $(liblightcomp_la_SOURCES) $(mod_access_la_SOURCES) $(mod_accesslog_la_SOURCES) $(mod_alias_la_SOURCES) $(mod_auth_la_SOURCES) $(mod_cgi_la_SOURCES) $(mod_cml_la_SOURCES) $(mod_compress_la_SOURCES) $(mod_dirlisting_la_SOURCES) $(mod_evasive_la_SOURCES) $(mod_evhost_la_SOURCES) $(mod_expire_la_SOURCES) $(mod_fastcgi_la_SOURCES) $(mod_flv_streaming_la_SOURCES) $(mod_indexfile_la_SOURCES) $(mod_mysql_vhost_la_SOURCES) $(mod_proxy_la_SOURCES) $(mod_redirect_la_SOURCES) $(mod_rewrite_la_SOURCES) $(mod_rrdtool_la_SOURCES) $(mod_scgi_la_SOURCES) $(mod_secdownload_la_SOURCES) $(mod_setenv_la_SOURCES) $(mod_simple_vhost_la_SOURCES) $(mod_ssi_la_SOURCES) $(mod_staticfile_la_SOURCES) $(mod_status_la_SOURCES) $(mod_trigger_b4_dl_la_SOURCES) $(mod_userdir_la_SOURCES) $(mod_usertrack_la_SOURCES) $(mod_webdav_la_SOURCES) $(lemon_SOURCES) $(lighttpd_SOURCES) $(proc_open_SOURCES) $(spawn_fcgi_SOURCES)
srcdir = @srcdir@
top_srcdir = @top_srcdir@
@@ -157,6 +157,9 @@ mod_expire_la_OBJECTS = $(am_mod_expire_la_OBJECTS)
mod_fastcgi_la_DEPENDENCIES = $(am__DEPENDENCIES_2)
am_mod_fastcgi_la_OBJECTS = mod_fastcgi.lo
mod_fastcgi_la_OBJECTS = $(am_mod_fastcgi_la_OBJECTS)
+mod_flv_streaming_la_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_mod_flv_streaming_la_OBJECTS = mod_flv_streaming.lo
+mod_flv_streaming_la_OBJECTS = $(am_mod_flv_streaming_la_OBJECTS)
mod_indexfile_la_DEPENDENCIES = $(am__DEPENDENCIES_2)
am_mod_indexfile_la_OBJECTS = mod_indexfile.lo
mod_indexfile_la_OBJECTS = $(am_mod_indexfile_la_OBJECTS)
@@ -287,24 +290,7 @@ SOURCES = $(liblightcomp_la_SOURCES) $(mod_access_la_SOURCES) \
$(mod_cml_la_SOURCES) $(mod_compress_la_SOURCES) \
$(mod_dirlisting_la_SOURCES) $(mod_evasive_la_SOURCES) \
$(mod_evhost_la_SOURCES) $(mod_expire_la_SOURCES) \
- $(mod_fastcgi_la_SOURCES) $(mod_indexfile_la_SOURCES) \
- $(mod_mysql_vhost_la_SOURCES) $(mod_proxy_la_SOURCES) \
- $(mod_redirect_la_SOURCES) $(mod_rewrite_la_SOURCES) \
- $(mod_rrdtool_la_SOURCES) $(mod_scgi_la_SOURCES) \
- $(mod_secdownload_la_SOURCES) $(mod_setenv_la_SOURCES) \
- $(mod_simple_vhost_la_SOURCES) $(mod_ssi_la_SOURCES) \
- $(mod_staticfile_la_SOURCES) $(mod_status_la_SOURCES) \
- $(mod_trigger_b4_dl_la_SOURCES) $(mod_userdir_la_SOURCES) \
- $(mod_usertrack_la_SOURCES) $(mod_webdav_la_SOURCES) \
- $(lemon_SOURCES) $(lighttpd_SOURCES) $(proc_open_SOURCES) \
- $(spawn_fcgi_SOURCES)
-DIST_SOURCES = $(am__liblightcomp_la_SOURCES_DIST) \
- $(mod_access_la_SOURCES) $(mod_accesslog_la_SOURCES) \
- $(mod_alias_la_SOURCES) $(mod_auth_la_SOURCES) \
- $(mod_cgi_la_SOURCES) $(mod_cml_la_SOURCES) \
- $(mod_compress_la_SOURCES) $(mod_dirlisting_la_SOURCES) \
- $(mod_evasive_la_SOURCES) $(mod_evhost_la_SOURCES) \
- $(mod_expire_la_SOURCES) $(mod_fastcgi_la_SOURCES) \
+ $(mod_fastcgi_la_SOURCES) $(mod_flv_streaming_la_SOURCES) \
$(mod_indexfile_la_SOURCES) $(mod_mysql_vhost_la_SOURCES) \
$(mod_proxy_la_SOURCES) $(mod_redirect_la_SOURCES) \
$(mod_rewrite_la_SOURCES) $(mod_rrdtool_la_SOURCES) \
@@ -313,9 +299,26 @@ DIST_SOURCES = $(am__liblightcomp_la_SOURCES_DIST) \
$(mod_ssi_la_SOURCES) $(mod_staticfile_la_SOURCES) \
$(mod_status_la_SOURCES) $(mod_trigger_b4_dl_la_SOURCES) \
$(mod_userdir_la_SOURCES) $(mod_usertrack_la_SOURCES) \
- $(mod_webdav_la_SOURCES) $(lemon_SOURCES) \
- $(am__lighttpd_SOURCES_DIST) $(proc_open_SOURCES) \
- $(spawn_fcgi_SOURCES)
+ $(mod_webdav_la_SOURCES) $(lemon_SOURCES) $(lighttpd_SOURCES) \
+ $(proc_open_SOURCES) $(spawn_fcgi_SOURCES)
+DIST_SOURCES = $(am__liblightcomp_la_SOURCES_DIST) \
+ $(mod_access_la_SOURCES) $(mod_accesslog_la_SOURCES) \
+ $(mod_alias_la_SOURCES) $(mod_auth_la_SOURCES) \
+ $(mod_cgi_la_SOURCES) $(mod_cml_la_SOURCES) \
+ $(mod_compress_la_SOURCES) $(mod_dirlisting_la_SOURCES) \
+ $(mod_evasive_la_SOURCES) $(mod_evhost_la_SOURCES) \
+ $(mod_expire_la_SOURCES) $(mod_fastcgi_la_SOURCES) \
+ $(mod_flv_streaming_la_SOURCES) $(mod_indexfile_la_SOURCES) \
+ $(mod_mysql_vhost_la_SOURCES) $(mod_proxy_la_SOURCES) \
+ $(mod_redirect_la_SOURCES) $(mod_rewrite_la_SOURCES) \
+ $(mod_rrdtool_la_SOURCES) $(mod_scgi_la_SOURCES) \
+ $(mod_secdownload_la_SOURCES) $(mod_setenv_la_SOURCES) \
+ $(mod_simple_vhost_la_SOURCES) $(mod_ssi_la_SOURCES) \
+ $(mod_staticfile_la_SOURCES) $(mod_status_la_SOURCES) \
+ $(mod_trigger_b4_dl_la_SOURCES) $(mod_userdir_la_SOURCES) \
+ $(mod_usertrack_la_SOURCES) $(mod_webdav_la_SOURCES) \
+ $(lemon_SOURCES) $(am__lighttpd_SOURCES_DIST) \
+ $(proc_open_SOURCES) $(spawn_fcgi_SOURCES)
HEADERS = $(noinst_HEADERS)
ETAGS = etags
CTAGS = ctags
@@ -456,6 +459,7 @@ target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
+AM_CFLAGS = $(FAM_CFLAGS)
LEMON = $(top_builddir)/src/lemon
lemon_SOURCES = lemon.c
common_src = buffer.c log.c \
@@ -485,26 +489,29 @@ spawn_fcgi_SOURCES = spawn-fcgi.c
#mod_httptls_la_SOURCES = mod_httptls.c
#mod_httptls_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
#mod_httptls_la_LIBADD = $(common_libadd)
-lib_LTLIBRARIES = $(am__append_1) mod_evasive.la mod_webdav.la \
- mod_cml.la mod_trigger_b4_dl.la mod_mysql_vhost.la mod_cgi.la \
- mod_scgi.la mod_staticfile.la mod_dirlisting.la \
- mod_indexfile.la mod_setenv.la mod_alias.la mod_userdir.la \
- mod_rrdtool.la mod_usertrack.la mod_proxy.la mod_ssi.la \
- mod_secdownload.la mod_expire.la mod_evhost.la \
+lib_LTLIBRARIES = $(am__append_1) mod_flv_streaming.la mod_evasive.la \
+ mod_webdav.la mod_cml.la mod_trigger_b4_dl.la \
+ mod_mysql_vhost.la mod_cgi.la mod_scgi.la mod_staticfile.la \
+ mod_dirlisting.la mod_indexfile.la mod_setenv.la mod_alias.la \
+ mod_userdir.la mod_rrdtool.la mod_usertrack.la mod_proxy.la \
+ mod_ssi.la mod_secdownload.la mod_expire.la mod_evhost.la \
mod_simple_vhost.la mod_fastcgi.la mod_access.la \
mod_compress.la mod_auth.la mod_rewrite.la mod_redirect.la \
mod_status.la mod_accesslog.la
@NO_RDYNAMIC_TRUE@liblightcomp_la_SOURCES = $(common_src)
-@NO_RDYNAMIC_TRUE@liblightcomp_la_CFLAGS = $(AM_CFLAGS) $(FAM_CFLAGS)
+@NO_RDYNAMIC_TRUE@liblightcomp_la_CFLAGS = $(AM_CFLAGS)
@NO_RDYNAMIC_TRUE@liblightcomp_la_LDFLAGS = -avoid-version -no-undefined
@NO_RDYNAMIC_TRUE@liblightcomp_la_LIBADD = $(PCRE_LIB) $(SSL_LIB) $(FAM_LIBS)
@NO_RDYNAMIC_FALSE@common_libadd =
@NO_RDYNAMIC_TRUE@common_libadd = liblightcomp.la
+mod_flv_streaming_la_SOURCES = mod_flv_streaming.c
+mod_flv_streaming_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
+mod_flv_streaming_la_LIBADD = $(common_libadd)
mod_evasive_la_SOURCES = mod_evasive.c
mod_evasive_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
mod_evasive_la_LIBADD = $(common_libadd)
mod_webdav_la_SOURCES = mod_webdav.c
-mod_webdav_la_CFLAGS = $(XML_CFLAGS)
+mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS)
mod_webdav_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS)
mod_cml_la_SOURCES = mod_cml.c mod_cml_lua.c mod_cml_funcs.c
@@ -710,6 +717,8 @@ mod_expire.la: $(mod_expire_la_OBJECTS) $(mod_expire_la_DEPENDENCIES)
$(LINK) -rpath $(libdir) $(mod_expire_la_LDFLAGS) $(mod_expire_la_OBJECTS) $(mod_expire_la_LIBADD) $(LIBS)
mod_fastcgi.la: $(mod_fastcgi_la_OBJECTS) $(mod_fastcgi_la_DEPENDENCIES)
$(LINK) -rpath $(libdir) $(mod_fastcgi_la_LDFLAGS) $(mod_fastcgi_la_OBJECTS) $(mod_fastcgi_la_LIBADD) $(LIBS)
+mod_flv_streaming.la: $(mod_flv_streaming_la_OBJECTS) $(mod_flv_streaming_la_DEPENDENCIES)
+ $(LINK) -rpath $(libdir) $(mod_flv_streaming_la_LDFLAGS) $(mod_flv_streaming_la_OBJECTS) $(mod_flv_streaming_la_LIBADD) $(LIBS)
mod_indexfile.la: $(mod_indexfile_la_OBJECTS) $(mod_indexfile_la_DEPENDENCIES)
$(LINK) -rpath $(libdir) $(mod_indexfile_la_LDFLAGS) $(mod_indexfile_la_OBJECTS) $(mod_indexfile_la_LIBADD) $(LIBS)
mod_mysql_vhost.la: $(mod_mysql_vhost_la_OBJECTS) $(mod_mysql_vhost_la_DEPENDENCIES)
@@ -912,6 +921,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_evhost.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_expire.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_fastcgi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_flv_streaming.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_indexfile.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_mysql_vhost_la-mod_mysql_vhost.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_proxy.Plo@am__quote@
diff --git a/src/configfile-glue.c b/src/configfile-glue.c
index 5c3c68b..6401854 100644
--- a/src/configfile-glue.c
+++ b/src/configfile-glue.c
@@ -372,8 +372,8 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat
n = pcre_exec(dc->regex, dc->regex_study, l->ptr, l->used - 1, 0, 0,
cache->matches, elementsof(cache->matches));
+ cache->patterncount = n;
if (n > 0) {
- cache->patterncount = n;
cache->comp_value = l;
return (dc->cond == CONFIG_COND_MATCH) ? COND_RESULT_TRUE : COND_RESULT_FALSE;
} else {
diff --git a/src/connections.c b/src/connections.c
index e4db410..3690448 100644
--- a/src/connections.c
+++ b/src/connections.c
@@ -394,6 +394,7 @@ static int connection_handle_write_prepare(server *srv, connection *con) {
case 408:
case 411:
case 416:
+ case 423:
case 500:
case 501:
case 503:
@@ -458,6 +459,7 @@ static int connection_handle_write_prepare(server *srv, connection *con) {
/* fall through */
case 207:
case 200: /* class: header + body */
+ case 201:
case 301:
case 302:
break;
diff --git a/src/keyvalue.c b/src/keyvalue.c
index b26588f..2b21d55 100644
--- a/src/keyvalue.c
+++ b/src/keyvalue.c
@@ -27,6 +27,10 @@ static keyvalue http_methods[] = {
{ HTTP_METHOD_LABEL, "LABEL" },
{ HTTP_METHOD_CHECKOUT, "CHECKOUT" },
{ HTTP_METHOD_CHECKIN, "CHECKIN" },
+ { HTTP_METHOD_MERGE, "MERGE" },
+ { HTTP_METHOD_LOCK, "LOCK" },
+ { HTTP_METHOD_UNLOCK, "UNLOCK" },
+ { HTTP_METHOD_MKACTIVITY, "MKACTIVITY" },
{ HTTP_METHOD_UNCHECKOUT, "UNCHECKOUT" },
{ HTTP_METHOD_VERSION_CONTROL, "VERSION-CONTROL" },
{ HTTP_METHOD_CONNECT, "CONNECT" },
diff --git a/src/keyvalue.h b/src/keyvalue.h
index e1c940f..5caca63 100644
--- a/src/keyvalue.h
+++ b/src/keyvalue.h
@@ -27,6 +27,10 @@ typedef enum {
HTTP_METHOD_CHECKIN,
HTTP_METHOD_VERSION_CONTROL,
HTTP_METHOD_UNCHECKOUT,
+ HTTP_METHOD_MKACTIVITY,
+ HTTP_METHOD_MERGE,
+ HTTP_METHOD_LOCK,
+ HTTP_METHOD_UNLOCK,
HTTP_METHOD_LABEL,
HTTP_METHOD_CONNECT
} http_method_t;
diff --git a/src/mod_alias.c b/src/mod_alias.c
index 23570e4..f56afeb 100644
--- a/src/mod_alias.c
+++ b/src/mod_alias.c
@@ -166,7 +166,9 @@ PHYSICALPATH_FUNC(mod_alias_physical_handler) {
if (alias_len > uri_len) continue;
if (ds->key->used == 0) continue;
- if (0 == strncmp(uri_ptr, ds->key->ptr, alias_len)) {
+ if (0 == (con->conf.force_lowercase_filenames ?
+ strncasecmp(uri_ptr, ds->key->ptr, alias_len) :
+ strncmp(uri_ptr, ds->key->ptr, alias_len))) {
/* matched */
buffer_copy_string_buffer(con->physical.basedir, ds->value);
diff --git a/src/mod_auth.c b/src/mod_auth.c
index 9b791d4..7810437 100644
--- a/src/mod_auth.c
+++ b/src/mod_auth.c
@@ -399,9 +399,10 @@ SETDEFAULTS_FUNC(mod_auth_set_defaults) {
const char *method, *realm, *require;
if (da->value->data[n]->type != TYPE_ARRAY) {
- log_error_write(srv, __FILE__, __LINE__, "sssbs",
- "unexpected type for key: ", "auth.require", "[", da->value->data[n]->key, "](string)");
-
+ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "auth.require should contain an array as in:",
+ "auth.require = ( \"...\" => ( ..., ...) )");
+
return HANDLER_ERROR;
}
@@ -416,34 +417,51 @@ SETDEFAULTS_FUNC(mod_auth_set_defaults) {
} else if (0 == strcmp(da_file->value->data[m]->key->ptr, "require")) {
require = ((data_string *)(da_file->value->data[m]))->value->ptr;
} else {
- log_error_write(srv, __FILE__, __LINE__, "sssbs", "unexpected type for key: ", "auth.require", "[", da_file->value->data[m]->key, "](string)");
+ log_error_write(srv, __FILE__, __LINE__, "ssbs",
+ "the field is unknown in:",
+ "auth.require = ( \"...\" => ( ..., -> \"",
+ da_file->value->data[m]->key,
+ "\" <- => \"...\" ) )");
+
return HANDLER_ERROR;
}
} else {
- log_error_write(srv, __FILE__, __LINE__, "sssbs", "unexpected type for key: ", "auth.require", "[", da_file->value->data[m]->key, "](string)");
+ log_error_write(srv, __FILE__, __LINE__, "ssbs",
+ "a string was expected for:",
+ "auth.require = ( \"...\" => ( ..., -> \"",
+ da_file->value->data[m]->key,
+ "\" <- => \"...\" ) )");
return HANDLER_ERROR;
}
}
if (method == NULL) {
- log_error_write(srv, __FILE__, __LINE__, "sssss", "missing entry for key: ", "auth.require", "[", "method", "](string)");
+ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "the require field is missing in:",
+ "auth.require = ( \"...\" => ( ..., \"method\" => \"...\" ) )");
return HANDLER_ERROR;
} else {
if (0 != strcmp(method, "basic") &&
0 != strcmp(method, "digest")) {
- log_error_write(srv, __FILE__, __LINE__, "s", "auth.require->method has to be either 'basic' or 'digest'");
+ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "method has to be either \"basic\" or \"digest\" in",
+ "auth.require = ( \"...\" => ( ..., \"method\" => \"...\") )");
return HANDLER_ERROR;
}
}
if (realm == NULL) {
- log_error_write(srv, __FILE__, __LINE__, "sssss", "missing entry for key: ", "auth.require", "[", "realm", "](string)");
+ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "the require field is missing in:",
+ "auth.require = ( \"...\" => ( ..., \"realm\" => \"...\" ) )");
return HANDLER_ERROR;
}
if (require == NULL) {
- log_error_write(srv, __FILE__, __LINE__, "sssss", "missing entry for key: ", "auth.require", "[", "require", "](string)");
+ log_error_write(srv, __FILE__, __LINE__, "ss",
+ "the require field is missing in:",
+ "auth.require = ( \"...\" => ( ..., \"require\" => \"...\" ) )");
return HANDLER_ERROR;
}
diff --git a/src/mod_cgi.c b/src/mod_cgi.c
index 883bf98..15aca3c 100644
--- a/src/mod_cgi.c
+++ b/src/mod_cgi.c
@@ -809,8 +809,12 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer *
cgi_env_add(&env, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
}
cgi_env_add(&env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200"));
- cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_BUF_LEN(con->uri.query));
- cgi_env_add(&env, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
+ if (!buffer_is_empty(con->uri.query)) {
+ cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_BUF_LEN(con->uri.query));
+ }
+ if (!buffer_is_empty(con->request.orig_uri)) {
+ cgi_env_add(&env, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
+ }
#ifdef HAVE_IPV6
@@ -967,6 +971,9 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer *
default: {
handler_ctx *hctx;
/* father */
+
+ close(from_cgi_fds[1]);
+ close(to_cgi_fds[0]);
if (con->request.content_length) {
chunkqueue *cq = con->request_content_queue;
@@ -987,6 +994,8 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer *
-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
+ close(from_cgi_fds[0]);
+ close(to_cgi_fds[1]);
return -1;
}
@@ -996,6 +1005,8 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer *
log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
strerror(errno), c->file.name, c->file.fd);
+ close(from_cgi_fds[0]);
+ close(to_cgi_fds[1]);
return -1;
}
@@ -1043,12 +1054,9 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer *
chunkqueue_remove_finished_chunks(cq);
}
}
-
- close(from_cgi_fds[1]);
-
- close(to_cgi_fds[0]);
+
close(to_cgi_fds[1]);
-
+
/* register PID and wait for them asyncronously */
con->mode = p->id;
buffer_reset(con->physical.path);
@@ -1128,7 +1136,7 @@ URIHANDLER_FUNC(cgi_is_handled) {
plugin_data *p = p_d;
buffer *fn = con->physical.path;
- if (fn->used == 0) return HANDLER_ERROR;
+ if (fn->used == 0) return HANDLER_GO_ON;
mod_cgi_patch_connection(srv, con, p);
diff --git a/src/mod_fastcgi.c b/src/mod_fastcgi.c
index da20c76..e64351a 100644
--- a/src/mod_fastcgi.c
+++ b/src/mod_fastcgi.c
@@ -57,8 +57,10 @@
typedef struct fcgi_proc {
size_t id; /* id will be between 1 and max_procs */
- buffer *socket; /* config.socket + "-" + id */
+ buffer *unixsocket; /* config.socket + "-" + id */
unsigned port; /* config.port + pno */
+
+ buffer *connection_name; /* either tcp:<host>:<port> or unix:<socket> for debuggin purposes */
pid_t pid; /* PID of the spawned process (0 if not spawned locally) */
@@ -74,12 +76,13 @@ typedef struct fcgi_proc {
int is_local;
enum {
- PROC_STATE_UNSET, /* init-phase */
- PROC_STATE_RUNNING, /* alive */
- PROC_STATE_DIED_WAIT_FOR_PID,
- PROC_STATE_KILLED, /* was killed as we don't have the load anymore */
- PROC_STATE_DIED, /* marked as dead, should be restarted */
- PROC_STATE_DISABLED /* proc disabled as it resulted in an error */
+ PROC_STATE_UNSET, /* init-phase */
+ PROC_STATE_RUNNING, /* alive */
+ PROC_STATE_OVERLOADED, /* listen-queue is full,
+ don't send something to this proc for the next 2 seconds */
+ PROC_STATE_DIED_WAIT_FOR_PID, /* */
+ PROC_STATE_DIED, /* marked as dead, should be restarted */
+ PROC_STATE_KILLED /* was killed as we don't have the load anymore */
} state;
} fcgi_proc;
@@ -262,6 +265,8 @@ typedef struct {
typedef struct {
buffer *key; /* like .php */
+ int note_is_sent;
+
fcgi_extension_host **hosts;
size_t used;
@@ -358,8 +363,6 @@ typedef struct {
/* ok, we need a prototype */
static handler_t fcgi_handle_fdevent(void *s, void *ctx, int revents);
-int fcgi_proclist_sort_down(server *srv, fcgi_extension_host *host, fcgi_proc *proc);
-
data_integer *status_counter_get_counter(server *srv, const char *s, size_t len) {
data_integer *di;
@@ -406,8 +409,10 @@ int status_counter_set(server *srv, const char *s, size_t len, int val) {
int fastcgi_status_copy_procname(buffer *b, fcgi_extension_host *host, fcgi_proc *proc) {
buffer_copy_string(b, "fastcgi.backend.");
buffer_append_string_buffer(b, host->id);
- buffer_append_string(b, ".");
- buffer_append_long(b, proc->id);
+ if (proc) {
+ buffer_append_string(b, ".");
+ buffer_append_long(b, proc->id);
+ }
return 0;
}
@@ -426,6 +431,15 @@ int fastcgi_status_init(server *srv, buffer *b, fcgi_extension_host *host, fcgi_
#undef CLEAN
+#define CLEAN(x) \
+ fastcgi_status_copy_procname(b, host, NULL); \
+ buffer_append_string(b, x); \
+ status_counter_set(srv, CONST_BUF_LEN(b), 0);
+
+ CLEAN(".load");
+
+#undef CLEAN
+
return 0;
}
@@ -472,7 +486,8 @@ fcgi_proc *fastcgi_process_init() {
fcgi_proc *f;
f = calloc(1, sizeof(*f));
- f->socket = buffer_init();
+ f->unixsocket = buffer_init();
+ f->connection_name = buffer_init();
f->prev = NULL;
f->next = NULL;
@@ -485,7 +500,8 @@ void fastcgi_process_free(fcgi_proc *f) {
fastcgi_process_free(f->next);
- buffer_free(f->socket);
+ buffer_free(f->unixsocket);
+ buffer_free(f->connection_name);
free(f);
}
@@ -669,8 +685,8 @@ FREE_FUNC(mod_fastcgi_free) {
if (proc->pid != 0) kill(proc->pid, SIGTERM);
if (proc->is_local &&
- !buffer_is_empty(proc->socket)) {
- unlink(proc->socket->ptr);
+ !buffer_is_empty(proc->unixsocket)) {
+ unlink(proc->unixsocket->ptr);
}
}
@@ -678,8 +694,8 @@ FREE_FUNC(mod_fastcgi_free) {
if (proc->pid != 0) kill(proc->pid, SIGTERM);
if (proc->is_local &&
- !buffer_is_empty(proc->socket)) {
- unlink(proc->socket->ptr);
+ !buffer_is_empty(proc->unixsocket)) {
+ unlink(proc->unixsocket->ptr);
}
}
}
@@ -799,24 +815,28 @@ static int fcgi_spawn_connection(server *srv,
if (p->conf.debug) {
log_error_write(srv, __FILE__, __LINE__, "sdb",
- "new proc, socket:", proc->port, proc->socket);
+ "new proc, socket:", proc->port, proc->unixsocket);
}
- if (!buffer_is_empty(proc->socket)) {
+ if (!buffer_is_empty(proc->unixsocket)) {
memset(&fcgi_addr, 0, sizeof(fcgi_addr));
#ifdef HAVE_SYS_UN_H
fcgi_addr_un.sun_family = AF_UNIX;
- strcpy(fcgi_addr_un.sun_path, proc->socket->ptr);
+ strcpy(fcgi_addr_un.sun_path, proc->unixsocket->ptr);
#ifdef SUN_LEN
servlen = SUN_LEN(&fcgi_addr_un);
#else
/* stevens says: */
- servlen = proc->socket->used - 1 + sizeof(fcgi_addr_un.sun_family);
+ servlen = proc->unixsocket->used + sizeof(fcgi_addr_un.sun_family);
#endif
socket_type = AF_UNIX;
fcgi_addr = (struct sockaddr *) &fcgi_addr_un;
+
+ buffer_copy_string(proc->connection_name, "unix:");
+ buffer_append_string_buffer(proc->connection_name, proc->unixsocket);
+
#else
log_error_write(srv, __FILE__, __LINE__, "s",
"ERROR: Unix Domain sockets are not supported.");
@@ -859,6 +879,11 @@ static int fcgi_spawn_connection(server *srv,
socket_type = AF_INET;
fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
+
+ buffer_copy_string(proc->connection_name, "tcp:");
+ buffer_append_string_buffer(proc->connection_name, host->host);
+ buffer_append_string(proc->connection_name, ":");
+ buffer_append_long(proc->connection_name, proc->port);
}
if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
@@ -872,8 +897,9 @@ static int fcgi_spawn_connection(server *srv,
pid_t child;
int val;
- if (!buffer_is_empty(proc->socket)) {
- unlink(proc->socket->ptr);
+ if (errno != ENOENT &&
+ !buffer_is_empty(proc->unixsocket)) {
+ unlink(proc->unixsocket->ptr);
}
close(fcgi_fd);
@@ -894,10 +920,9 @@ static int fcgi_spawn_connection(server *srv,
/* create socket */
if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) {
- log_error_write(srv, __FILE__, __LINE__, "sbds",
+ log_error_write(srv, __FILE__, __LINE__, "sbs",
"bind failed for:",
- proc->socket,
- proc->port,
+ proc->connection_name,
strerror(errno));
return -1;
}
@@ -1040,7 +1065,7 @@ static int fcgi_spawn_connection(server *srv,
WTERMSIG(status));
if (WTERMSIG(status) == 11) {
- log_error_write(srv, __FILE__, __LINE__, "ss",
+ log_error_write(srv, __FILE__, __LINE__, "s",
"to be exact: it seg-fault, crashed, died, ... you get the idea." );
log_error_write(srv, __FILE__, __LINE__, "s",
"If this is PHP try to remove the byte-code caches for now and try again.");
@@ -1068,7 +1093,7 @@ static int fcgi_spawn_connection(server *srv,
if (p->conf.debug) {
log_error_write(srv, __FILE__, __LINE__, "sb",
"(debug) socket is already used, won't spawn:",
- proc->socket);
+ proc->connection_name);
}
}
@@ -1240,9 +1265,12 @@ SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) {
if ((!buffer_is_empty(host->host) || host->port) &&
!buffer_is_empty(host->unixsocket)) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "either host+port or socket");
-
+ log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
+ "either host/port or socket have to be set in:",
+ da->key, "= (",
+ da_ext->key, " => (",
+ da_host->key, " ( ...");
+
return HANDLER_ERROR;
}
@@ -1250,8 +1278,12 @@ SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) {
/* unix domain socket */
if (host->unixsocket->used > UNIX_PATH_MAX - 2) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "path of the unixdomain socket is too large");
+ log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
+ "unixsocket is too long in:",
+ da->key, "= (",
+ da_ext->key, " => (",
+ da_host->key, " ( ...");
+
return HANDLER_ERROR;
}
} else {
@@ -1259,21 +1291,20 @@ SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) {
if (buffer_is_empty(host->host) &&
buffer_is_empty(host->bin_path)) {
- log_error_write(srv, __FILE__, __LINE__, "sbbbs",
- "missing key (string):",
- da->key,
- da_ext->key,
- da_host->key,
- "host");
+ log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
+ "host or binpath have to be set in:",
+ da->key, "= (",
+ da_ext->key, " => (",
+ da_host->key, " ( ...");
return HANDLER_ERROR;
} else if (host->port == 0) {
- log_error_write(srv, __FILE__, __LINE__, "sbbbs",
- "missing key (short):",
- da->key,
- da_ext->key,
- da_host->key,
- "port");
+ log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
+ "port has to be set in:",
+ da->key, "= (",
+ da_ext->key, " => (",
+ da_host->key, " ( ...");
+
return HANDLER_ERROR;
}
}
@@ -1308,9 +1339,9 @@ SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) {
if (buffer_is_empty(host->unixsocket)) {
proc->port = host->port + pno;
} else {
- buffer_copy_string_buffer(proc->socket, host->unixsocket);
- buffer_append_string(proc->socket, "-");
- buffer_append_long(proc->socket, pno);
+ buffer_copy_string_buffer(proc->unixsocket, host->unixsocket);
+ buffer_append_string(proc->unixsocket, "-");
+ buffer_append_long(proc->unixsocket, pno);
}
if (s->debug) {
@@ -1346,7 +1377,7 @@ SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) {
if (buffer_is_empty(host->unixsocket)) {
proc->port = host->port;
} else {
- buffer_copy_string_buffer(proc->socket, host->unixsocket);
+ buffer_copy_string_buffer(proc->unixsocket, host->unixsocket);
}
fastcgi_status_init(srv, p->statuskey, host, proc);
@@ -1477,14 +1508,13 @@ void fcgi_connection_close(server *srv, handler_ctx *hctx) {
status_counter_set(srv, CONST_BUF_LEN(p->statuskey), hctx->proc->load);
if (p->conf.debug) {
- log_error_write(srv, __FILE__, __LINE__, "sddb",
- "release proc:",
- hctx->fd,
- hctx->proc->pid, hctx->proc->socket);
+ log_error_write(srv, __FILE__, __LINE__, "ssdsbsd",
+ "released proc:",
+ "pid:", hctx->proc->pid,
+ "socket:", hctx->proc->connection_name,
+ "load:", hctx->proc->load);
}
}
-
- fcgi_proclist_sort_down(srv, hctx->host, hctx->proc);
}
@@ -1519,6 +1549,7 @@ static int fcgi_reconnect(server *srv, handler_ctx *hctx) {
fdevent_unregister(srv->ev, hctx->fd);
close(hctx->fd);
srv->cur_fds--;
+ hctx->fd = -1;
}
fcgi_requestid_del(srv, p, hctx->request_id);
@@ -1528,16 +1559,20 @@ static int fcgi_reconnect(server *srv, handler_ctx *hctx) {
hctx->request_id = 0;
hctx->reconnects++;
- if (p->conf.debug) {
- log_error_write(srv, __FILE__, __LINE__, "sddb",
- "release proc:",
- hctx->fd,
- hctx->proc->pid, hctx->proc->socket);
+ if (p->conf.debug > 2) {
+ if (hctx->proc) {
+ log_error_write(srv, __FILE__, __LINE__, "sdb",
+ "release proc for reconnect:",
+ hctx->proc->pid, hctx->proc->connection_name);
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "release proc for reconnect:",
+ hctx->host->unixsocket);
+ }
}
- if (hctx->proc) {
+ if (hctx->proc && hctx->got_proc) {
hctx->proc->load--;
- fcgi_proclist_sort_down(srv, hctx->host, hctx->proc);
}
/* perhaps another host gives us more luck */
@@ -1637,18 +1672,24 @@ static connection_result_t fcgi_establish_connection(server *srv, handler_ctx *h
memset(&fcgi_addr, 0, sizeof(fcgi_addr));
- if (!buffer_is_empty(proc->socket)) {
+ if (!buffer_is_empty(proc->unixsocket)) {
#ifdef HAVE_SYS_UN_H
/* use the unix domain socket */
fcgi_addr_un.sun_family = AF_UNIX;
- strcpy(fcgi_addr_un.sun_path, proc->socket->ptr);
+ strcpy(fcgi_addr_un.sun_path, proc->unixsocket->ptr);
#ifdef SUN_LEN
servlen = SUN_LEN(&fcgi_addr_un);
#else
/* stevens says: */
- servlen = proc->socket->used - 1 + sizeof(fcgi_addr_un.sun_family);
+ servlen = proc->unixsocket->used + sizeof(fcgi_addr_un.sun_family);
#endif
fcgi_addr = (struct sockaddr *) &fcgi_addr_un;
+
+ if (buffer_is_empty(proc->connection_name)) {
+ /* on remote spawing we have to set the connection-name now */
+ buffer_copy_string(proc->connection_name, "unix:");
+ buffer_append_string_buffer(proc->connection_name, proc->unixsocket);
+ }
#else
return -1;
#endif
@@ -1665,32 +1706,40 @@ static connection_result_t fcgi_establish_connection(server *srv, handler_ctx *h
servlen = sizeof(fcgi_addr_in);
fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
+
+ if (buffer_is_empty(proc->connection_name)) {
+ /* on remote spawing we have to set the connection-name now */
+ buffer_copy_string(proc->connection_name, "tcp:");
+ buffer_append_string_buffer(proc->connection_name, host->host);
+ buffer_append_string(proc->connection_name, ":");
+ buffer_append_long(proc->connection_name, proc->port);
+ }
}
if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
if (errno == EINPROGRESS ||
errno == EALREADY ||
errno == EINTR) {
- if (hctx->conf.debug) {
+ if (hctx->conf.debug > 2) {
log_error_write(srv, __FILE__, __LINE__, "sb",
- "connect delayed, will continue later:", host->host);
+ "connect delayed, will continue later:", proc->connection_name);
}
return CONNECTION_DELAYED;
} else if (errno == EAGAIN) {
if (hctx->conf.debug) {
- log_error_write(srv, __FILE__, __LINE__, "sd",
+ log_error_write(srv, __FILE__, __LINE__, "sbsd",
"This means that the you have more incoming requests than your fastcgi-backend can handle in parallel. "
"Perhaps it helps to spawn more fastcgi backend or php-children, if not decrease server.max-connections."
- "The load for this fastcgi backend is:", proc->load);
+ "The load for this fastcgi backend", proc->connection_name, "is", proc->load);
}
return CONNECTION_OVERLOADED;
} else {
- log_error_write(srv, __FILE__, __LINE__, "ssdb",
+ log_error_write(srv, __FILE__, __LINE__, "sssb",
"connect failed:",
- strerror(errno),
- proc->port, proc->socket);
+ strerror(errno), "on",
+ proc->connection_name);
return CONNECTION_DEAD;
}
@@ -2378,12 +2427,10 @@ static int fcgi_demux_response(server *srv, handler_ctx *hctx) {
b->used = r + 1; /* one extra for the fake \0 */
b->ptr[b->used - 1] = '\0';
} else {
- log_error_write(srv, __FILE__, __LINE__, "ssdsbsbsd",
+ log_error_write(srv, __FILE__, __LINE__, "ssdsb",
"unexpected end-of-file (perhaps the fastcgi process died):",
"pid:", proc->pid,
- "socket:", proc->socket,
- "host:", host->host,
- "port:", proc->port);
+ "socket:", proc->connection_name);
return -1;
}
@@ -2514,222 +2561,97 @@ static int fcgi_demux_response(server *srv, handler_ctx *hctx) {
return fin;
}
-int fcgi_proclist_sort_up(server *srv, fcgi_extension_host *host, fcgi_proc *proc) {
- fcgi_proc *p;
-
- UNUSED(srv);
-
- /* we have been the smallest of the current list
- * and we want to insert the node sorted as soon
- * possible
- *
- * 1 0 0 0 1 1 1
- * | ^
- * | |
- * +------+
- *
- */
-
- /* nothing to sort, only one element */
- if (host->first == proc && proc->next == NULL) return 0;
-
- for (p = proc; p->next && p->next->load < proc->load; p = p->next);
-
- /* no need to move something
- *
- * 1 2 2 2 3 3 3
- * ^
- * |
- * +
- *
- */
- if (p == proc) return 0;
-
- if (host->first == proc) {
- /* we have been the first elememt */
-
- host->first = proc->next;
- host->first->prev = NULL;
- }
-
- /* disconnect proc */
-
- if (proc->prev) proc->prev->next = proc->next;
- if (proc->next) proc->next->prev = proc->prev;
-
- /* proc should be right of p */
-
- proc->next = p->next;
- proc->prev = p;
- if (p->next) p->next->prev = proc;
- p->next = proc;
-#if 0
- for(p = host->first; p; p = p->next) {
- log_error_write(srv, __FILE__, __LINE__, "dd",
- p->pid, p->load);
- }
-#else
- UNUSED(srv);
-#endif
-
- return 0;
-}
-
-int fcgi_proclist_sort_down(server *srv, fcgi_extension_host *host, fcgi_proc *proc) {
- fcgi_proc *p;
-
- UNUSED(srv);
-
- /* we have been the smallest of the current list
- * and we want to insert the node sorted as soon
- * possible
- *
- * 0 0 0 0 1 0 1
- * ^ |
- * | |
- * +----------+
- *
- *
- * the basic is idea is:
- * - the last active fastcgi process should be still
- * in ram and is not swapped out yet
- * - processes that are not reused will be killed
- * after some time by the trigger-handler
- * - remember it as:
- * everything > 0 is hot
- * all unused procs are colder the more right they are
- * ice-cold processes are propably unused since more
- * than 'unused-timeout', are swaped out and won't be
- * reused in the next seconds anyway.
- *
- */
-
- /* nothing to sort, only one element */
- if (host->first == proc && proc->next == NULL) return 0;
-
- for (p = host->first; p != proc && p->load < proc->load; p = p->next);
-
-
- /* no need to move something
- *
- * 1 2 2 2 3 3 3
- * ^
- * |
- * +
- *
- */
- if (p == proc) return 0;
-
- /* we have to move left. If we are already the first element
- * we are done */
- if (host->first == proc) return 0;
-
- /* release proc */
- if (proc->prev) proc->prev->next = proc->next;
- if (proc->next) proc->next->prev = proc->prev;
-
- /* proc should be left of p */
- proc->next = p;
- proc->prev = p->prev;
- if (p->prev) p->prev->next = proc;
- p->prev = proc;
-
- if (proc->prev == NULL) host->first = proc;
-#if 0
- for(p = host->first; p; p = p->next) {
- log_error_write(srv, __FILE__, __LINE__, "dd",
- p->pid, p->load);
- }
-#else
- UNUSED(srv);
-#endif
-
- return 0;
-}
-
static int fcgi_restart_dead_procs(server *srv, plugin_data *p, fcgi_extension_host *host) {
fcgi_proc *proc;
for (proc = host->first; proc; proc = proc->next) {
- if (p->conf.debug) {
- log_error_write(srv, __FILE__, __LINE__, "sbdbdddd",
+ int status;
+
+ if (p->conf.debug > 2) {
+ log_error_write(srv, __FILE__, __LINE__, "sbdddd",
"proc:",
- host->host, proc->port,
- proc->socket,
+ proc->connection_name,
proc->state,
proc->is_local,
proc->load,
proc->pid);
}
- if (!proc->is_local) {
- /*
- * external servers might get disabled
- *
- * enable the server again, perhaps it is back again
- */
-
- if ((proc->state == PROC_STATE_DISABLED) &&
- (srv->cur_ts > proc->disabled_until)) {
- proc->state = PROC_STATE_RUNNING;
- host->active_procs++;
-
- fastcgi_status_copy_procname(p->statuskey, host, proc);
- buffer_append_string(p->statuskey, ".disabled");
+ /*
+ * if the remote side is overloaded, we check back after <n> seconds
+ *
+ */
+ switch (proc->state) {
+ case PROC_STATE_KILLED:
+ case PROC_STATE_UNSET:
+ /* this should never happen as long as adaptive spawing is disabled */
+ assert(0);
- status_counter_set(srv, CONST_BUF_LEN(p->statuskey), 0);
+ break;
+ case PROC_STATE_RUNNING:
+ break;
+ case PROC_STATE_OVERLOADED:
+ if (srv->cur_ts <= proc->disabled_until) break;
+
+ proc->state = PROC_STATE_RUNNING;
+ host->active_procs++;
+
+ log_error_write(srv, __FILE__, __LINE__, "sbdb",
+ "fcgi-server re-enabled:",
+ host->host, host->port,
+ host->unixsocket);
+ break;
+ case PROC_STATE_DIED_WAIT_FOR_PID:
+ /* non-local procs don't have PIDs to wait for */
+ if (!proc->is_local) break;
- log_error_write(srv, __FILE__, __LINE__, "sbdb",
- "fcgi-server re-enabled:",
- host->host, host->port,
- host->unixsocket);
- }
- } else {
/* the child should not terminate at all */
- int status;
- if (proc->state == PROC_STATE_DIED_WAIT_FOR_PID) {
- switch(waitpid(proc->pid, &status, WNOHANG)) {
- case 0:
- /* child is still alive */
- break;
- case -1:
- break;
- default:
- if (WIFEXITED(status)) {
+ switch(waitpid(proc->pid, &status, WNOHANG)) {
+ case 0:
+ /* child is still alive */
+ break;
+ case -1:
+ break;
+ default:
+ if (WIFEXITED(status)) {
#if 0
- log_error_write(srv, __FILE__, __LINE__, "sdsd",
- "child exited, pid:", proc->pid,
- "status:", WEXITSTATUS(status));
+ log_error_write(srv, __FILE__, __LINE__, "sdsd",
+ "child exited, pid:", proc->pid,
+ "status:", WEXITSTATUS(status));
#endif
- } else if (WIFSIGNALED(status)) {
- log_error_write(srv, __FILE__, __LINE__, "sd",
- "child signaled:",
- WTERMSIG(status));
- } else {
- log_error_write(srv, __FILE__, __LINE__, "sd",
- "child died somehow:",
- status);
- }
-
- proc->state = PROC_STATE_DIED;
- break;
+ } else if (WIFSIGNALED(status)) {
+ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "child signaled:",
+ WTERMSIG(status));
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "sd",
+ "child died somehow:",
+ status);
}
+
+ proc->state = PROC_STATE_DIED;
+ break;
}
+
+ /* fall through if we have a dead proc now */
+ if (proc->state != PROC_STATE_DIED) break;
+
+ case PROC_STATE_DIED:
+ /* local proc get restarted by us,
+ * remote ones hopefully by the admin */
+
+ if (proc->is_local) {
+ /* we still have connections bound to this proc,
+ * let them terminate first */
+ if (proc->load != 0) break;
- /*
- * local servers might died, but we restart them
- *
- */
- if (proc->state == PROC_STATE_DIED &&
- proc->load == 0) {
/* restart the child */
if (p->conf.debug) {
- log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
+ log_error_write(srv, __FILE__, __LINE__, "ssbsdsd",
"--- fastcgi spawning",
- "\n\tport:", host->port,
- "\n\tsocket", host->unixsocket,
+ "\n\tsocket", proc->connection_name,
"\n\tcurrent:", 1, "/", host->min_procs);
}
@@ -2738,9 +2660,17 @@ static int fcgi_restart_dead_procs(server *srv, plugin_data *p, fcgi_extension_h
"ERROR: spawning fcgi failed.");
return HANDLER_ERROR;
}
-
- fcgi_proclist_sort_down(srv, host, proc);
+ } else {
+ if (srv->cur_ts <= proc->disabled_until) break;
+
+ proc->state = PROC_STATE_RUNNING;
+ host->active_procs++;
+
+ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "fcgi-server re-enabled:",
+ proc->connection_name);
}
+ break;
}
}
@@ -2751,6 +2681,7 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) {
plugin_data *p = hctx->plugin_data;
fcgi_extension_host *host= hctx->host;
connection *con = hctx->remote_conn;
+ fcgi_proc *proc;
int ret;
@@ -2763,6 +2694,10 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) {
host->host->used,
host->port,
host->unixsocket->used);
+
+ hctx->proc->disabled_until = srv->cur_ts + 10;
+ hctx->proc->state = PROC_STATE_DIED;
+
return HANDLER_ERROR;
}
@@ -2776,18 +2711,29 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) {
log_error_write(srv, __FILE__, __LINE__, "ss",
"getsockopt failed:", strerror(errno));
+ hctx->proc->disabled_until = srv->cur_ts + 10;
+ hctx->proc->state = PROC_STATE_DIED;
+
return HANDLER_ERROR;
}
if (socket_error != 0) {
if (!hctx->proc->is_local || p->conf.debug) {
/* local procs get restarted */
- log_error_write(srv, __FILE__, __LINE__, "sssd",
+ log_error_write(srv, __FILE__, __LINE__, "sssb",
"establishing connection failed:", strerror(socket_error),
- "port:", hctx->proc->port);
+ "socket:", hctx->proc->connection_name);
}
- hctx->proc->disabled_until = srv->cur_ts + 10;
+ hctx->proc->disabled_until = srv->cur_ts + 5;
+
+ if (hctx->proc->is_local) {
+ hctx->proc->state = PROC_STATE_DIED_WAIT_FOR_PID;
+ } else {
+ hctx->proc->state = PROC_STATE_DIED;
+ }
+
+ hctx->proc->state = PROC_STATE_DIED;
fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
buffer_append_string(p->statuskey, ".died");
@@ -2807,18 +2753,27 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) {
break;
case FCGI_STATE_INIT:
/* do we have a running process for this host (max-procs) ? */
+ hctx->proc = NULL;
- for (hctx->proc = hctx->host->first;
- hctx->proc && hctx->proc->state != PROC_STATE_RUNNING;
- hctx->proc = hctx->proc->next);
+ for (proc = hctx->host->first;
+ proc && proc->state != PROC_STATE_RUNNING;
+ proc = proc->next);
/* all childs are dead */
- if (hctx->proc == NULL) {
+ if (proc == NULL) {
hctx->fde_ndx = -1;
return HANDLER_ERROR;
}
+ hctx->proc = proc;
+
+ /* check the other procs if they have a lower load */
+ for (proc = proc->next; proc; proc = proc->next) {
+ if (proc->state != PROC_STATE_RUNNING) continue;
+ if (proc->load < hctx->proc->load) hctx->proc = proc;
+ }
+
ret = host->unixsocket->used ? AF_UNIX : AF_INET;
if (-1 == (hctx->fd = socket(ret, SOCK_STREAM, 0))) {
@@ -2863,14 +2818,14 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) {
/* cool down the backend, it is overloaded
* -> EAGAIN */
- log_error_write(srv, __FILE__, __LINE__, "ssdsdb",
+ log_error_write(srv, __FILE__, __LINE__, "ssdsd",
"backend is overloaded, we disable it for a 2 seconds and send the request to another backend instead:",
"reconnects:", hctx->reconnects,
- "load:", host->load,
- host->unixsocket);
+ "load:", host->load);
hctx->proc->disabled_until = srv->cur_ts + 2;
+ hctx->proc->state = PROC_STATE_OVERLOADED;
fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
buffer_append_string(p->statuskey, ".overloaded");
@@ -2883,11 +2838,21 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) {
* - ECONNREFUSED for tcp-ip sockets
* - ENOENT for unix-domain-sockets
*
- * for check if the host is back in 10 seconds
+ * for check if the host is back in 5 seconds
* */
- hctx->proc->disabled_until = srv->cur_ts + 10;
-
+ hctx->proc->disabled_until = srv->cur_ts + 5;
+ if (hctx->proc->is_local) {
+ hctx->proc->state = PROC_STATE_DIED_WAIT_FOR_PID;
+ } else {
+ hctx->proc->state = PROC_STATE_DIED;
+ }
+
+ log_error_write(srv, __FILE__, __LINE__, "ssdsd",
+ "backend died, we disable it for a 5 seconds and send the request to another backend instead:",
+ "reconnects:", hctx->reconnects,
+ "load:", host->load);
+
fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
buffer_append_string(p->statuskey, ".died");
@@ -2919,24 +2884,27 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) {
status_counter_inc(srv, CONST_BUF_LEN(p->statuskey));
+ /* the proc-load */
fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
buffer_append_string(p->statuskey, ".load");
status_counter_set(srv, CONST_BUF_LEN(p->statuskey), hctx->proc->load);
+ /* the host-load */
+ fastcgi_status_copy_procname(p->statuskey, hctx->host, NULL);
+ buffer_append_string(p->statuskey, ".load");
+
+ status_counter_set(srv, CONST_BUF_LEN(p->statuskey), hctx->host->load);
+
if (p->conf.debug) {
- log_error_write(srv, __FILE__, __LINE__, "sddbdd",
+ log_error_write(srv, __FILE__, __LINE__, "ssdsbsd",
"got proc:",
- hctx->fd,
- hctx->proc->pid,
- hctx->proc->socket,
- hctx->proc->port,
- hctx->proc->load);
+ "pid:", hctx->proc->pid,
+ "socket:", hctx->proc->connection_name,
+ "load:", hctx->proc->load);
}
/* move the proc-list entry down the list */
- fcgi_proclist_sort_up(srv, hctx->host, hctx->proc);
-
if (hctx->request_id == 0) {
hctx->request_id = fcgi_requestid_new(srv, p);
} else {
@@ -3098,43 +3066,7 @@ SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) {
if (hctx->state == FCGI_STATE_INIT ||
hctx->state == FCGI_STATE_CONNECT_DELAYED) {
- /* connect() or getsockopt() failed,
- * restart the request-handling
- */
- if (proc) {
- if (proc->is_local) {
-
- if (p->conf.debug) {
- log_error_write(srv, __FILE__, __LINE__, "sbdb",
- "connect() to fastcgi failed, restarting the request-handling:",
- host->host,
- proc->port,
- proc->socket);
- }
-
- /*
- * several hctx might reference the same proc
- *
- * Only one of them should mark the proc as dead all the other
- * ones should just take a new one.
- *
- * If a new proc was started with the old struct this might lead
- * the mark a perfect proc as dead otherwise
- *
- */
- if (proc->state == PROC_STATE_RUNNING &&
- hctx->pid == proc->pid) {
- proc->state = PROC_STATE_DIED_WAIT_FOR_PID;
- }
- } else {
- proc->state = PROC_STATE_DISABLED;
- }
- host->active_procs--;
- fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
- buffer_append_string(p->statuskey, ".disabled");
-
- status_counter_set(srv, CONST_BUF_LEN(p->statuskey), 1);
- }
+ if (proc) host->active_procs--;
fcgi_restart_dead_procs(srv, p, host);
@@ -3247,18 +3179,18 @@ static handler_t fcgi_handle_fdevent(void *s, void *ctx, int revents) {
}
if (p->conf.debug) {
- log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
+ log_error_write(srv, __FILE__, __LINE__, "ssbsdsd",
"--- fastcgi spawning",
- "\n\tport:", host->port,
- "\n\tsocket", host->unixsocket,
+ "\n\tsocket", proc->connection_name,
"\n\tcurrent:", 1, "/", host->min_procs);
}
if (fcgi_spawn_connection(srv, p, host, proc)) {
- /* child died */
+ /* respawning failed, retry later */
proc->state = PROC_STATE_DIED;
- } else {
- fcgi_proclist_sort_down(srv, host, proc);
+
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "respawning failed, will retry later");
}
break;
@@ -3272,18 +3204,18 @@ static handler_t fcgi_handle_fdevent(void *s, void *ctx, int revents) {
hctx->reconnects < 5) {
fcgi_reconnect(srv, hctx);
- log_error_write(srv, __FILE__, __LINE__, "ssdsd",
- "response not received, request not sent, reconnecting.",
- "connection-fd:", con->fd,
- "fcgi-fd:", hctx->fd);
+ log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
+ "response not received, request not sent",
+ "on socket:", proc->connection_name,
+ "for", con->uri.path, ", reconnecting");
return HANDLER_WAIT_FOR_FD;
}
-
- log_error_write(srv, __FILE__, __LINE__, "sosdsd",
+
+ log_error_write(srv, __FILE__, __LINE__, "sosbsbs",
"response not received, request sent:", hctx->wb->bytes_out,
- "connection-fd:", con->fd,
- "fcgi-fd:", hctx->fd);
+ "on socket:", proc->connection_name,
+ "for", con->uri.path, ", closing connection");
fcgi_connection_close(srv, hctx);
@@ -3295,10 +3227,10 @@ static handler_t fcgi_handle_fdevent(void *s, void *ctx, int revents) {
/* response might have been already started, kill the connection */
fcgi_connection_close(srv, hctx);
- log_error_write(srv, __FILE__, __LINE__, "ssdsd",
- "response already sent out, termination connection",
- "connection-fd:", con->fd,
- "fcgi-fd:", hctx->fd);
+ log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
+ "response already sent out, but backend returned error",
+ "on socket:", proc->connection_name,
+ "for", con->uri.path, ", terminating connection");
connection_set_state(srv, con, CON_STATE_ERROR);
}
@@ -3351,7 +3283,7 @@ static handler_t fcgi_handle_fdevent(void *s, void *ctx, int revents) {
log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
"error: unexpected close of fastcgi connection for",
con->uri.path,
- "(no fastcgi process on host: ",
+ "(no fastcgi process on host:",
host->host,
", port: ",
host->port,
@@ -3425,9 +3357,7 @@ static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, i
fn = uri_path_handler ? con->uri.path : con->physical.path;
- if (fn->used == 0) {
- return HANDLER_ERROR;
- }
+ if (buffer_is_empty(fn)) return HANDLER_GO_ON;
s_len = fn->used - 1;
@@ -3519,14 +3449,23 @@ static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, i
/* sorry, we don't have a server alive for this ext */
buffer_reset(con->physical.path);
con->http_status = 500;
-
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "no fcgi-handler found for:",
- fn);
+
+ /* only send the 'no handler' once */
+ if (!extension->note_is_sent) {
+ extension->note_is_sent = 1;
+
+ log_error_write(srv, __FILE__, __LINE__, "sbsbs",
+ "all handlers for ", con->uri.path,
+ "on", extension->key,
+ "are down.");
+ }
return HANDLER_FINISHED;
}
+ /* a note about no handler is not sent yey */
+ extension->note_is_sent = 0;
+
/*
* if check-local is disabled, use the uri.path handler
*
@@ -3708,48 +3647,46 @@ TRIGGER_FUNC(mod_fastcgi_handle_trigger) {
host->num_procs < host->max_procs &&
(sum_load / host->num_procs) > host->max_load_per_proc) {
/* overload, spawn new child */
- fcgi_proc *fp = NULL;
-
if (p->conf.debug) {
log_error_write(srv, __FILE__, __LINE__, "s",
"overload detected, spawning a new child");
}
- for (fp = host->unused_procs; fp && fp->pid != 0; fp = fp->next);
+ for (proc = host->unused_procs; proc && proc->pid != 0; proc = proc->next);
- if (fp) {
- if (fp == host->unused_procs) host->unused_procs = fp->next;
+ if (proc) {
+ if (proc == host->unused_procs) host->unused_procs = proc->next;
- if (fp->next) fp->next->prev = NULL;
+ if (proc->next) proc->next->prev = NULL;
host->max_id++;
} else {
- fp = fastcgi_process_init();
- fp->id = host->max_id++;
+ proc = fastcgi_process_init();
+ proc->id = host->max_id++;
}
host->num_procs++;
if (buffer_is_empty(host->unixsocket)) {
- fp->port = host->port + fp->id;
+ proc->port = host->port + proc->id;
} else {
- buffer_copy_string_buffer(fp->socket, host->unixsocket);
- buffer_append_string(fp->socket, "-");
- buffer_append_long(fp->socket, fp->id);
+ buffer_copy_string_buffer(proc->unixsocket, host->unixsocket);
+ buffer_append_string(proc->unixsocket, "-");
+ buffer_append_long(proc->unixsocket, proc->id);
}
- if (fcgi_spawn_connection(srv, p, host, fp)) {
+ if (fcgi_spawn_connection(srv, p, host, proc)) {
log_error_write(srv, __FILE__, __LINE__, "s",
"ERROR: spawning fcgi failed.");
return HANDLER_ERROR;
}
- fp->prev = NULL;
- fp->next = host->first;
+ proc->prev = NULL;
+ proc->next = host->first;
if (host->first) {
- host->first->prev = fp;
+ host->first->prev = proc;
}
- host->first = fp;
+ host->first = proc;
}
for (proc = host->first; proc; proc = proc->next) {
@@ -3764,7 +3701,7 @@ TRIGGER_FUNC(mod_fastcgi_handle_trigger) {
if (p->conf.debug) {
log_error_write(srv, __FILE__, __LINE__, "ssbsd",
"idle-timeout reached, terminating child:",
- "socket:", proc->socket,
+ "socket:", proc->connection_name,
"pid", proc->pid);
}
@@ -3786,7 +3723,7 @@ TRIGGER_FUNC(mod_fastcgi_handle_trigger) {
log_error_write(srv, __FILE__, __LINE__, "ssbsd",
"killed:",
- "socket:", proc->socket,
+ "socket:", proc->connection_name,
"pid", proc->pid);
host->num_procs--;
@@ -3827,7 +3764,7 @@ TRIGGER_FUNC(mod_fastcgi_handle_trigger) {
if (proc->state != PROC_STATE_KILLED) {
log_error_write(srv, __FILE__, __LINE__, "sdb",
"child exited:",
- WEXITSTATUS(status), proc->socket);
+ WEXITSTATUS(status), proc->connection_name);
}
} else if (WIFSIGNALED(status)) {
if (WTERMSIG(status) != SIGTERM) {
diff --git a/src/mod_flv_streaming.c b/src/mod_flv_streaming.c
new file mode 100644
index 0000000..c557bd4
--- /dev/null
+++ b/src/mod_flv_streaming.c
@@ -0,0 +1,278 @@
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "base.h"
+#include "log.h"
+#include "buffer.h"
+#include "response.h"
+#include "http_chunk.h"
+#include "stat_cache.h"
+
+#include "plugin.h"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* plugin config for all request/connections */
+
+typedef struct {
+ array *extensions;
+} plugin_config;
+
+typedef struct {
+ PLUGIN_DATA;
+
+ buffer *query_str;
+ array *get_params;
+
+ plugin_config **config_storage;
+
+ plugin_config conf;
+} plugin_data;
+
+/* init the plugin data */
+INIT_FUNC(mod_flv_streaming_init) {
+ plugin_data *p;
+
+ p = calloc(1, sizeof(*p));
+
+ p->query_str = buffer_init();
+ p->get_params = array_init();
+
+ return p;
+}
+
+/* detroy the plugin data */
+FREE_FUNC(mod_flv_streaming_free) {
+ plugin_data *p = p_d;
+
+ UNUSED(srv);
+
+ if (!p) return HANDLER_GO_ON;
+
+ if (p->config_storage) {
+ size_t i;
+
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+
+ if (!s) continue;
+
+ array_free(s->extensions);
+
+ free(s);
+ }
+ free(p->config_storage);
+ }
+
+ buffer_free(p->query_str);
+ array_free(p->get_params);
+
+ free(p);
+
+ return HANDLER_GO_ON;
+}
+
+/* handle plugin config and check values */
+
+SETDEFAULTS_FUNC(mod_flv_streaming_set_defaults) {
+ plugin_data *p = p_d;
+ size_t i = 0;
+
+ config_values_t cv[] = {
+ { "flv-streaming.extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+
+ if (!p) return HANDLER_ERROR;
+
+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+
+ s = calloc(1, sizeof(plugin_config));
+ s->extensions = array_init();
+
+ cv[0].destination = s->extensions;
+
+ p->config_storage[i] = s;
+
+ if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+ return HANDLER_ERROR;
+ }
+ }
+
+ return HANDLER_GO_ON;
+}
+
+#define PATCH(x) \
+ p->conf.x = s->x;
+static int mod_flv_streaming_patch_connection(server *srv, connection *con, plugin_data *p) {
+ size_t i, j;
+ plugin_config *s = p->config_storage[0];
+
+ PATCH(extensions);
+
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ s = p->config_storage[i];
+
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("flv-streaming.extensions"))) {
+ PATCH(extensions);
+ }
+ }
+ }
+
+ return 0;
+}
+#undef PATCH
+
+static int split_get_params(server *srv, connection *con, array *get_params, buffer *qrystr) {
+ size_t is_key = 1;
+ size_t i;
+ char *key = NULL, *val = NULL;
+
+ key = qrystr->ptr;
+
+ /* we need the \0 */
+ for (i = 0; i < qrystr->used; i++) {
+ switch(qrystr->ptr[i]) {
+ case '=':
+ if (is_key) {
+ val = qrystr->ptr + i + 1;
+
+ qrystr->ptr[i] = '\0';
+
+ is_key = 0;
+ }
+
+ break;
+ case '&':
+ case '\0': /* fin symbol */
+ if (!is_key) {
+ data_string *ds;
+ /* we need at least a = since the last & */
+
+ /* terminate the value */
+ qrystr->ptr[i] = '\0';
+
+ if (NULL == (ds = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
+ ds = data_string_init();
+ }
+ buffer_copy_string_len(ds->key, key, strlen(key));
+ buffer_copy_string_len(ds->value, val, strlen(val));
+
+ array_insert_unique(get_params, (data_unset *)ds);
+ }
+
+ key = qrystr->ptr + i + 1;
+ val = NULL;
+ is_key = 1;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+URIHANDLER_FUNC(mod_flv_streaming_path_handler) {
+ plugin_data *p = p_d;
+ int s_len;
+ size_t k;
+
+ UNUSED(srv);
+
+ if (buffer_is_empty(con->physical.path)) return HANDLER_GO_ON;
+
+ mod_flv_streaming_patch_connection(srv, con, p);
+
+ s_len = con->physical.path->used - 1;
+
+ for (k = 0; k < p->conf.extensions->used; k++) {
+ data_string *ds = (data_string *)p->conf.extensions->data[k];
+ int ct_len = ds->value->used - 1;
+
+ if (ct_len > s_len) continue;
+ if (ds->value->used == 0) continue;
+
+ if (0 == strncmp(con->physical.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
+ data_string *get_param;
+ stat_cache_entry *sce = NULL;
+ buffer *b;
+ int start;
+ char *err = NULL;
+ /* if there is a start=[0-9]+ in the header use it as start,
+ * otherwise send the full file */
+
+ array_reset(p->get_params);
+ buffer_copy_string_buffer(p->query_str, con->uri.query);
+ split_get_params(srv, con, p->get_params, p->query_str);
+
+ if (NULL == (get_param = (data_string *)array_get_element(p->get_params, "start"))) {
+ return HANDLER_GO_ON;
+ }
+
+ /* too short */
+ if (get_param->value->used < 2) return HANDLER_GO_ON;
+
+ /* check if it is a number */
+ start = strtol(get_param->value->ptr, &err, 10);
+ if (*err != '\0') {
+ return HANDLER_GO_ON;
+ }
+
+ if (start <= 0) return HANDLER_GO_ON;
+
+ /* check if start is > filesize */
+ if (HANDLER_GO_ON != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
+ return HANDLER_GO_ON;
+ }
+
+ if (start > sce->st.st_size) {
+ return HANDLER_GO_ON;
+ }
+
+ /* we are safe now, let's build a flv header */
+ b = chunkqueue_get_append_buffer(con->write_queue);
+ BUFFER_COPY_STRING_CONST(b, "FLV\x1\x1\0\0\0\x9\0\0\0\x9");
+
+ http_chunk_append_file(srv, con, con->physical.path, start, sce->st.st_size - start);
+
+ response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("video/x-flv"));
+
+ con->file_finished = 1;
+
+ return HANDLER_FINISHED;
+ }
+ }
+
+ /* not found */
+ return HANDLER_GO_ON;
+}
+
+/* this function is called at dlopen() time and inits the callbacks */
+
+int mod_flv_streaming_plugin_init(plugin *p) {
+ p->version = LIGHTTPD_VERSION_ID;
+ p->name = buffer_init_string("flv_streaming");
+
+ p->init = mod_flv_streaming_init;
+ p->handle_physical = mod_flv_streaming_path_handler;
+ p->set_defaults = mod_flv_streaming_set_defaults;
+ p->cleanup = mod_flv_streaming_free;
+
+ p->data = NULL;
+
+ return 0;
+}
diff --git a/src/mod_scgi.c b/src/mod_scgi.c
index 2c1df2f..88c80eb 100644
--- a/src/mod_scgi.c
+++ b/src/mod_scgi.c
@@ -645,7 +645,7 @@ static int scgi_spawn_connection(server *srv,
servlen = SUN_LEN(&scgi_addr_un);
#else
/* stevens says: */
- servlen = proc->socket->used - 1 + sizeof(scgi_addr_un.sun_family);
+ servlen = proc->socket->used + sizeof(scgi_addr_un.sun_family);
#endif
socket_type = AF_UNIX;
scgi_addr = (struct sockaddr *) &scgi_addr_un;
@@ -1296,7 +1296,7 @@ static int scgi_establish_connection(server *srv, handler_ctx *hctx) {
servlen = SUN_LEN(&scgi_addr_un);
#else
/* stevens says: */
- servlen = proc->socket->used - 1 + sizeof(scgi_addr_un.sun_family);
+ servlen = proc->socket->used + sizeof(scgi_addr_un.sun_family);
#endif
scgi_addr = (struct sockaddr *) &scgi_addr_un;
#else
diff --git a/src/mod_ssi.c b/src/mod_ssi.c
index b6a19d7..d1e1b25 100644
--- a/src/mod_ssi.c
+++ b/src/mod_ssi.c
@@ -518,13 +518,11 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p,
} else {
buffer_copy_string_len(p->stat_fn, con->physical.path->ptr, sl - con->physical.path->ptr + 1);
}
-
- /* fn */
- if (NULL == (sl = strrchr(file_path, '/'))) {
- buffer_append_string(p->stat_fn, file_path);
- } else {
- buffer_append_string(p->stat_fn, sl + 1);
- }
+
+ buffer_copy_string(srv->tmp_buf, file_path);
+ buffer_urldecode_path(srv->tmp_buf);
+ buffer_path_simplify(srv->tmp_buf, srv->tmp_buf);
+ buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
} else {
/* virtual */
@@ -974,7 +972,7 @@ static int mod_ssi_handle_request(server *srv, connection *con, plugin_data *p)
#ifdef HAVE_PCRE_H
for (i = 0; (n = pcre_exec(p->ssi_regex, NULL, s.start, s.size, i, 0, ovec, N * 3)) > 0; i = ovec[1]) {
const char **l;
- /* take every think from last offset to current match pos */
+ /* take everything from last offset to current match pos */
if (!p->if_is_false) chunkqueue_append_file(con->write_queue, con->physical.path, i, ovec[0] - i);
diff --git a/src/mod_webdav.c b/src/mod_webdav.c
index 3306c73..c78e609 100644
--- a/src/mod_webdav.c
+++ b/src/mod_webdav.c
@@ -1294,6 +1294,7 @@ URIHANDLER_FUNC(mod_webdav_subrequest_handler) {
}
} else {
con->http_status = 201;
+ con->file_finished = 1;
}
return HANDLER_FINISHED;
@@ -1390,6 +1391,7 @@ URIHANDLER_FUNC(mod_webdav_subrequest_handler) {
chunk *c;
con->http_status = 201; /* created */
+ con->file_finished = 1;
for (c = cq->first; c; c = cq->first) {
int r = 0;
@@ -1606,6 +1608,7 @@ URIHANDLER_FUNC(mod_webdav_subrequest_handler) {
rmdir(con->physical.path->ptr);
}
con->http_status = 201;
+ con->file_finished = 1;
} else {
/* it is just a file, good */
int r;
@@ -1625,6 +1628,7 @@ URIHANDLER_FUNC(mod_webdav_subrequest_handler) {
if (-1 == r) {
con->http_status = 201; /* we will create a new one */
+ con->file_finished = 1;
switch(errno) {
case ENOTDIR:
diff --git a/src/network.c b/src/network.c
index 922009f..fe52bc2 100644
--- a/src/network.c
+++ b/src/network.c
@@ -252,7 +252,7 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) {
addr_len = SUN_LEN(&srv_socket->addr.un);
#else
/* stevens says: */
- addr_len = strlen(host) + sizeof(srv_socket->addr.un.sun_family);
+ addr_len = strlen(host) + 1 + sizeof(srv_socket->addr.un.sun_family);
#endif
/* check if the socket exists and try to connect to it. */
@@ -540,6 +540,7 @@ int network_init(server *srv) {
for (i = 1; i < srv->config_context->used; i++) {
data_config *dc = (data_config *)srv->config_context->data[i];
specific_config *s = srv->config_storage[i];
+ size_t j;
/* not our stage */
if (COMP_SERVER_SOCKET != dc->comp) continue;
@@ -549,13 +550,20 @@ int network_init(server *srv) {
return -1;
}
+
+ /* check if we already know this socket,
+ * if yes, don't init it */
+ for (j = 0; j < srv->srv_sockets.used; j++) {
+ if (buffer_is_equal(srv->srv_sockets.ptr[j]->srv_token, dc->string)) {
+ break;
+ }
+ }
- if (0 != network_server_init(srv, dc->string, s)) {
- return -1;
+ if (j == srv->srv_sockets.used) {
+ if (0 != network_server_init(srv, dc->string, s)) return -1;
}
}
-
return 0;
}
diff --git a/src/network_linux_sendfile.c b/src/network_linux_sendfile.c
index 6426568..580ba87 100644
--- a/src/network_linux_sendfile.c
+++ b/src/network_linux_sendfile.c
@@ -23,6 +23,9 @@
#include "log.h"
#include "stat_cache.h"
+/* on linux 2.4.29 + debian/ubuntu we have crashes if this is enabled */
+#undef HAVE_POSIX_FADVISE
+
int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, chunkqueue *cq) {
chunk *c;
size_t chunks_written = 0;
@@ -129,23 +132,11 @@ int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd,
size_t toSend;
stat_cache_entry *sce = NULL;
- if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- strerror(errno), c->file.name);
- return -1;
- }
-
offset = c->file.start + c->offset;
/* limit the toSend to 2^31-1 bytes in a chunk */
toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
((1 << 30) - 1) : c->file.length - c->offset;
- if (offset > sce->st.st_size) {
- log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
-
- return -1;
- }
-
/* open file if not already opened */
if (-1 == c->file.fd) {
if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
@@ -159,14 +150,14 @@ int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd,
#ifdef HAVE_POSIX_FADVISE
/* tell the kernel that we want to stream the file */
if (-1 == posix_fadvise(c->file.fd, 0, 0, POSIX_FADV_SEQUENTIAL)) {
- log_error_write(srv, __FILE__, __LINE__, "ssd",
- "posix_fadvise failed:", strerror(errno), c->file.fd);
+ if (ENOSYS != errno) {
+ log_error_write(srv, __FILE__, __LINE__, "ssd",
+ "posix_fadvise failed:", strerror(errno), c->file.fd);
+ }
}
#endif
}
-
- /* Linux sendfile() */
if (-1 == (r = sendfile(fd, c->file.fd, &offset, toSend))) {
switch (errno) {
case EAGAIN:
@@ -184,7 +175,21 @@ int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd,
}
if (r == 0) {
- /* we got a event to write put we couldn't. remote side closed ? */
+ /* We got an event to write but we wrote nothing
+ *
+ * - the file shrinked -> error
+ * - the remote side closed inbetween -> remote-close */
+
+ if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
+ /* file is gone ? */
+ return -1;
+ }
+
+ if (offset > sce->st.st_size) {
+ /* file shrinked, close the connection */
+ return -1;
+ }
+
return -2;
}
diff --git a/src/network_writev.c b/src/network_writev.c
index 578048e..96a2a4a 100644
--- a/src/network_writev.c
+++ b/src/network_writev.c
@@ -255,14 +255,14 @@ int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkq
#ifdef LOCAL_BUFFERING
buffer_copy_string_len(c->mem, c->file.mmap.start, c->file.mmap.length);
#else
-#ifdef HAVE_POSIX_MADVISE
+#ifdef HAVE_MADVISE
/* don't advise files < 64Kb */
if (c->file.mmap.length > (64 KByte)) {
/* darwin 7 is returning EINVAL all the time and I don't know how to
* detect this at runtime.i
*
* ignore the return value for now */
- posix_madvise(c->file.mmap.start, c->file.mmap.length, POSIX_MADV_WILLNEED);
+ madvise(c->file.mmap.start, c->file.mmap.length, MADV_WILLNEED);
}
#endif
#endif
diff --git a/src/request.c b/src/request.c
index 020333e..f539c80 100644
--- a/src/request.c
+++ b/src/request.c
@@ -368,11 +368,53 @@ int http_request_parse(server *srv, connection *con) {
}
con->request.http_method = r;
-
- if (0 == strncmp(proto, "HTTP/1.", sizeof("HTTP/1.") - 1)) {
- if (proto[7] == '1') {
+
+ /*
+ * RFC2616 says:
+ *
+ * HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT
+ *
+ * */
+ if (0 == strncmp(proto, "HTTP/", sizeof("HTTP/") - 1)) {
+ char * major = proto + sizeof("HTTP/") - 1;
+ char * minor = strchr(major, '.');
+ char *err = NULL;
+ int major_num = 0, minor_num = 0;
+
+ int invalid_version = 0;
+
+ if (NULL == minor || /* no dot */
+ minor == major || /* no major */
+ *(minor + 1) == '\0' /* no minor */) {
+ invalid_version = 1;
+ } else {
+ *minor = '\0';
+ major_num = strtol(major, &err, 10);
+
+ if (*err != '\0') invalid_version = 1;
+
+ *minor++ = '.';
+ minor_num = strtol(minor, &err, 10);
+
+ if (*err != '\0') invalid_version = 1;
+ }
+
+ if (invalid_version) {
+ con->http_status = 400;
+ con->keep_alive = 0;
+
+ if (srv->srvconf.log_request_header_on_error) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "unknown protocol -> 400");
+ log_error_write(srv, __FILE__, __LINE__, "Sb",
+ "request-header:\n",
+ con->request.request);
+ }
+ return 0;
+ }
+
+ if (major_num == 1 && minor_num == 1) {
con->request.http_version = con->conf.allow_http11 ? HTTP_VERSION_1_1 : HTTP_VERSION_1_0;
- } else if (proto[7] == '0') {
+ } else if (major_num == 1 && minor_num == 0) {
con->request.http_version = HTTP_VERSION_1_0;
} else {
con->http_status = 505;
@@ -1003,12 +1045,11 @@ int http_request_parse(server *srv, connection *con) {
switch(con->request.http_method) {
case HTTP_METHOD_GET:
case HTTP_METHOD_HEAD:
- case HTTP_METHOD_OPTIONS:
/* content-length is forbidden for those */
if (con_length_set && con->request.content_length != 0) {
/* content-length is missing */
log_error_write(srv, __FILE__, __LINE__, "s",
- "GET/HEAD/OPTIONS with content-length -> 400");
+ "GET/HEAD with content-length -> 400");
con->keep_alive = 0;
con->http_status = 400;
diff --git a/src/response.c b/src/response.c
index d955cec..4f23ea9 100644
--- a/src/response.c
+++ b/src/response.c
@@ -320,6 +320,42 @@ handler_t http_response_prepare(server *srv, connection *con) {
buffer_copy_string_buffer(con->physical.doc_root, con->conf.document_root);
buffer_copy_string_buffer(con->physical.rel_path, con->uri.path);
+#if defined(__WIN32) || defined(__CYGWIN__)
+ /* strip dots from the end and spaces
+ *
+ * windows/dos handle those filenames as the same file
+ *
+ * foo == foo. == foo..... == "foo... " == "foo.. ./"
+ *
+ * This will affect in some cases PATHINFO
+ *
+ * on native windows we could prepend the filename with \\?\ to circumvent
+ * this behaviour. I have no idea how to push this through cygwin
+ *
+ * */
+
+ if (con->physical.rel_path->used > 1) {
+ buffer *b = con->physical.rel_path;
+ size_t i;
+
+ if (b->used > 2 &&
+ b->ptr[b->used-2] == '/' &&
+ (b->ptr[b->used-3] == ' ' ||
+ b->ptr[b->used-3] == '.')) {
+ b->ptr[b->used--] = '\0';
+ }
+
+ for (i = b->used - 2; b->used > 1; i--) {
+ if (b->ptr[i] == ' ' ||
+ b->ptr[i] == '.') {
+ b->ptr[b->used--] = '\0';
+ } else {
+ break;
+ }
+ }
+ }
+#endif
+
if (con->conf.log_request_handling) {
log_error_write(srv, __FILE__, __LINE__, "s", "-- before doc_root");
log_error_write(srv, __FILE__, __LINE__, "sb", "Doc-Root :", con->physical.doc_root);
diff --git a/src/server.c b/src/server.c
index f33100c..d4f9eba 100644
--- a/src/server.c
+++ b/src/server.c
@@ -118,8 +118,6 @@ static void daemonize(void) {
if (0 != fork()) exit(0);
if (0 != chdir("/")) exit(0);
-
- umask(0);
}
#endif
@@ -218,6 +216,7 @@ static void server_free(server *srv) {
CLEAN(srvconf.event_handler);
CLEAN(srvconf.pid_file);
CLEAN(srvconf.modules_dir);
+ CLEAN(srvconf.network_backend);
CLEAN(tmp_chunk_len);
#undef CLEAN
@@ -256,6 +255,7 @@ static void server_free(server *srv) {
CLEAN(config_context);
CLEAN(config_touched);
CLEAN(status);
+ CLEAN(srvconf.upload_tempdirs);
#undef CLEAN
joblist_free(srv, srv->joblist);
diff --git a/src/spawn-fcgi.c b/src/spawn-fcgi.c
index 99fc31a..fd869a2 100644
--- a/src/spawn-fcgi.c
+++ b/src/spawn-fcgi.c
@@ -41,7 +41,7 @@ typedef int socklen_t;
#endif
#ifdef HAVE_SYS_UN_H
-int fcgi_spawn_connection(char *appPath, unsigned short port, const char *unixsocket, int child_count, int pid_fd, int nofork) {
+int fcgi_spawn_connection(char *appPath, char *addr, unsigned short port, const char *unixsocket, int child_count, int pid_fd, int nofork) {
int fcgi_fd;
int socket_type, status;
struct timeval tv = { 0, 100 * 1000 };
@@ -77,7 +77,11 @@ int fcgi_spawn_connection(char *appPath, unsigned short port, const char *unixso
fcgi_addr = (struct sockaddr *) &fcgi_addr_un;
} else {
fcgi_addr_in.sin_family = AF_INET;
- fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
+ if (addr != NULL) {
+ fcgi_addr_in.sin_addr.s_addr = inet_addr(addr);
+ } else {
+ fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
+ }
fcgi_addr_in.sin_port = htons(port);
servlen = sizeof(fcgi_addr_in);
@@ -243,6 +247,7 @@ void show_help () {
" - spawns fastcgi processes\n" \
"usage:\n" \
" -f <fcgiapp> filename of the fcgi-application\n" \
+" -a <addr> bind to ip address\n" \
" -p <port> bind to tcp-port\n" \
" -s <path> bind to unix-domain socket\n" \
" -C <childs> (PHP only) numbers of childs to spawn (default 5)\n" \
@@ -261,7 +266,8 @@ void show_help () {
int main(int argc, char **argv) {
char *fcgi_app = NULL, *changeroot = NULL, *username = NULL,
- *groupname = NULL, *unixsocket = NULL, *pid_file = NULL;
+ *groupname = NULL, *unixsocket = NULL, *pid_file = NULL,
+ *addr = NULL;
unsigned short port = 0;
int child_count = 5;
int i_am_root, o;
@@ -270,9 +276,10 @@ int main(int argc, char **argv) {
i_am_root = (getuid() == 0);
- while(-1 != (o = getopt(argc, argv, "c:f:g:hnp:u:vC:s:P:"))) {
+ while(-1 != (o = getopt(argc, argv, "c:f:g:hna:p:u:vC:s:P:"))) {
switch(o) {
case 'f': fcgi_app = optarg; break;
+ case 'a': addr = optarg;/* ip addr */ break;
case 'p': port = strtol(optarg, NULL, 10);/* port */ break;
case 'C': child_count = strtol(optarg, NULL, 10);/* */ break;
case 's': unixsocket = optarg; /* unix-domain socket */ break;
@@ -422,7 +429,7 @@ int main(int argc, char **argv) {
if (username) setuid(pwd->pw_uid);
}
- return fcgi_spawn_connection(fcgi_app, port, unixsocket, child_count, pid_fd, nofork);
+ return fcgi_spawn_connection(fcgi_app, addr, port, unixsocket, child_count, pid_fd, nofork);
}
#else
int main() {
diff --git a/tests/core.t b/tests/core.t
index 6d11cc6..d8187dd 100755
--- a/tests/core.t
+++ b/tests/core.t
@@ -9,7 +9,7 @@ BEGIN {
use strict;
use IO::Socket;
-use Test::More tests => 17;
+use Test::More tests => 21;
use LightyTest;
my $tf = LightyTest->new();
@@ -32,6 +32,36 @@ $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
ok($tf->handle_http($t) == 0, 'missing Protocol');
$t->{REQUEST} = ( <<EOF
+GET / HTTP/01.01
+Host: foo
+Connection: close
+EOF
+ );
+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200 } ];
+ok($tf->handle_http($t) == 0, 'zeros in protocol version');
+
+$t->{REQUEST} = ( <<EOF
+GET / HTTP/.01
+EOF
+ );
+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
+ok($tf->handle_http($t) == 0, 'missing major version');
+
+$t->{REQUEST} = ( <<EOF
+GET / HTTP/01.
+EOF
+ );
+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
+ok($tf->handle_http($t) == 0, 'missing minor version');
+
+$t->{REQUEST} = ( <<EOF
+GET / HTTP/a.b
+EOF
+ );
+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
+ok($tf->handle_http($t) == 0, 'strings as version');
+
+$t->{REQUEST} = ( <<EOF
BC /
EOF
);
diff --git a/tests/lighttpd.conf b/tests/lighttpd.conf
index 8d38c09..79e48c9 100644
--- a/tests/lighttpd.conf
+++ b/tests/lighttpd.conf
@@ -3,6 +3,9 @@ debug.log-condition-handling = "enable"
server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
+## 64 Mbyte ... nice limit
+server.max-request-size = 65000
+
## bind to port (default: 80)
server.port = 2048
diff --git a/tests/mod-fastcgi.t b/tests/mod-fastcgi.t
index d3ea4a8..291bf69 100755
--- a/tests/mod-fastcgi.t
+++ b/tests/mod-fastcgi.t
@@ -7,7 +7,7 @@ BEGIN {
}
use strict;
-use Test::More tests => 45;
+use Test::More tests => 47;
use LightyTest;
my $tf = LightyTest->new();
@@ -15,7 +15,7 @@ my $tf = LightyTest->new();
my $t;
SKIP: {
- skip "no PHP running on port 1026", 28 unless $tf->listening_on(1026);
+ skip "no PHP running on port 1026", 30 unless $tf->listening_on(1026);
ok($tf->start_proc == 0, "Starting lighttpd") or die();
@@ -115,6 +115,13 @@ EOF
ok($tf->handle_http($t) == 0, 'PATHINFO');
$t->{REQUEST} = ( <<EOF
+GET /cgi.php%20%20%20 HTTP/1.0
+EOF
+ );
+ $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
+ ok($tf->handle_http($t) == 0, 'No source retrieval');
+
+ $t->{REQUEST} = ( <<EOF
GET /www/abc/def HTTP/1.0
EOF
);
diff --git a/tests/request.t b/tests/request.t
index e581879..7dd4cc6 100755
--- a/tests/request.t
+++ b/tests/request.t
@@ -317,7 +317,7 @@ Content-Length: 4
1234
EOF
);
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
ok($tf->handle_http($t) == 0, 'OPTIONS with Content-Length');
$t->{REQUEST} = ( <<EOF
diff --git a/tests/wrapper.sh b/tests/wrapper.sh
index 5ba80ed..07cc784 100755
--- a/tests/wrapper.sh
+++ b/tests/wrapper.sh
@@ -2,8 +2,8 @@
## get some parameters from the makefile
-export srcdir=$1
-export top_builddir=$2
-export SHELL
+srcdir=$1
+top_builddir=$2
+export SHELL srcdir top_builddir
$3