From: Elan Ruusamäe Date: Tue, 18 Jul 2006 10:05:14 +0000 (+0000) Subject: - svn 1199 X-Git-Tag: DEVLE~4 X-Git-Url: http://git.pld-linux.org/?p=packages%2Flighttpd.git;a=commitdiff_plain;h=520831994447c2b1338b3c6c5a8aecaf28b43af5 - svn 1199 Changed files: lighttpd-branch.diff -> 1.7 --- diff --git a/lighttpd-branch.diff b/lighttpd-branch.diff index 97bdee3..9d33e7f 100644 --- a/lighttpd-branch.diff +++ b/lighttpd-branch.diff @@ -1,5 +1,5 @@ --- ../lighttpd-1.4.11/NEWS 2006-03-09 19:34:33.000000000 +0200 -+++ lighttpd-1.4.12/NEWS 2006-07-11 22:07:54.000000000 +0300 ++++ lighttpd-1.4.12/NEWS 2006-07-16 00:26:05.000000000 +0300 @@ -3,6 +3,23 @@ NEWS ==== @@ -25,7 +25,7 @@ * added ability to specify which ip address spawn-fci listens on --- ../lighttpd-1.4.11/configure.in 2006-03-04 16:32:38.000000000 +0200 -+++ lighttpd-1.4.12/configure.in 2006-07-15 22:43:22.000000000 +0300 ++++ lighttpd-1.4.12/configure.in 2006-07-16 00:26:05.000000000 +0300 @@ -1,7 +1,7 @@ # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. @@ -135,7 +135,7 @@ $ECHO --- ../lighttpd-1.4.11/cygwin/lighttpd.README 2006-03-07 14:22:19.000000000 +0200 -+++ lighttpd-1.4.12/cygwin/lighttpd.README 2006-07-11 22:08:04.000000000 +0300 ++++ lighttpd-1.4.12/cygwin/lighttpd.README 2006-07-17 22:02:18.000000000 +0300 @@ -1,114 +1,114 @@ -lighttpd ------------------------------------------- @@ -366,7 +366,7 @@ +Please address all questions to the Cygwin mailing list at + --- ../lighttpd-1.4.11/cygwin/lighttpd.README.in 2005-08-11 01:26:59.000000000 +0300 -+++ lighttpd-1.4.12/cygwin/lighttpd.README.in 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/cygwin/lighttpd.README.in 2006-07-16 00:26:04.000000000 +0300 @@ -1,114 +1,114 @@ -lighttpd ------------------------------------------- @@ -597,7 +597,7 @@ +Please address all questions to the Cygwin mailing list at + --- ../lighttpd-1.4.11/doc/authentication.txt 2006-01-12 20:34:26.000000000 +0200 -+++ lighttpd-1.4.12/doc/authentication.txt 2006-07-11 22:07:54.000000000 +0300 ++++ lighttpd-1.4.12/doc/authentication.txt 2006-07-16 00:26:05.000000000 +0300 @@ -7,8 +7,8 @@ ---------------- @@ -610,7 +610,7 @@ :abstract: The auth module provides ... --- ../lighttpd-1.4.11/doc/compress.txt 2005-08-11 01:26:16.000000000 +0300 -+++ lighttpd-1.4.12/doc/compress.txt 2006-07-11 22:07:54.000000000 +0300 ++++ lighttpd-1.4.12/doc/compress.txt 2006-07-16 00:26:05.000000000 +0300 @@ -22,12 +22,38 @@ =========== @@ -685,7 +685,7 @@ =========================== --- ../lighttpd-1.4.11/doc/configuration.txt 2006-03-09 02:10:40.000000000 +0200 -+++ lighttpd-1.4.12/doc/configuration.txt 2006-07-11 22:07:54.000000000 +0300 ++++ lighttpd-1.4.12/doc/configuration.txt 2006-07-16 00:26:05.000000000 +0300 @@ -7,8 +7,8 @@ ------------ @@ -709,7 +709,7 @@ + for developers only + default: disabled --- ../lighttpd-1.4.11/doc/fastcgi.txt 2006-02-16 17:03:52.000000000 +0200 -+++ lighttpd-1.4.12/doc/fastcgi.txt 2006-07-11 22:07:54.000000000 +0300 ++++ lighttpd-1.4.12/doc/fastcgi.txt 2006-07-16 00:26:05.000000000 +0300 @@ -144,8 +144,8 @@ PHP can extract PATH_INFO from it (default: disabled) :"disable-time": time to wait before a disabled backend is checked @@ -722,7 +722,7 @@ If bin-path is set: --- ../lighttpd-1.4.11/doc/lighttpd.conf 2006-03-04 14:41:12.000000000 +0200 -+++ lighttpd-1.4.12/doc/lighttpd.conf 2006-07-11 22:07:54.000000000 +0300 ++++ lighttpd-1.4.12/doc/lighttpd.conf 2006-07-16 00:26:05.000000000 +0300 @@ -172,10 +172,11 @@ #dir-listing.activate = "enable" @@ -740,7 +740,7 @@ ### only root can use these options # --- ../lighttpd-1.4.11/doc/performance.txt 2006-02-02 13:01:08.000000000 +0200 -+++ lighttpd-1.4.12/doc/performance.txt 2006-07-11 22:07:54.000000000 +0300 ++++ lighttpd-1.4.12/doc/performance.txt 2006-07-16 00:26:05.000000000 +0300 @@ -183,6 +183,8 @@ server.stat-cache-engine = "fam" # either fam, simple or disabled @@ -751,7 +751,7 @@ Platform-Specific Notes ======================= --- ../lighttpd-1.4.11/doc/secdownload.txt 2005-12-20 15:58:58.000000000 +0200 -+++ lighttpd-1.4.12/doc/secdownload.txt 2006-07-11 22:07:54.000000000 +0300 ++++ lighttpd-1.4.12/doc/secdownload.txt 2006-07-16 00:26:05.000000000 +0300 @@ -118,7 +118,7 @@ $secret = "verysecret"; $uri_prefix = "/dl/"; @@ -762,7 +762,7 @@ # current timestamp --- ../lighttpd-1.4.11/lighttpd.spec 2006-03-07 14:22:18.000000000 +0200 -+++ lighttpd-1.4.12/lighttpd.spec 2006-07-11 22:07:58.000000000 +0300 ++++ lighttpd-1.4.12/lighttpd.spec 2006-07-17 22:02:18.000000000 +0300 @@ -1,6 +1,6 @@ Summary: A fast webserver with minimal memory-footprint (lighttpd) Name: lighttpd @@ -772,7 +772,7 @@ Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-%version.tar.gz Packager: Jan Kneschke --- ../lighttpd-1.4.11/openwrt/control 2006-03-07 14:22:19.000000000 +0200 -+++ lighttpd-1.4.12/openwrt/control 2006-07-11 22:08:05.000000000 +0300 ++++ lighttpd-1.4.12/openwrt/control 2006-07-17 22:02:18.000000000 +0300 @@ -1,8 +1,8 @@ Package: lighttpd -Version: 1.4.11 @@ -785,7 +785,7 @@ Priority: optional Depends: --- ../lighttpd-1.4.11/openwrt/lighttpd.mk 2006-03-07 14:22:19.000000000 +0200 -+++ lighttpd-1.4.12/openwrt/lighttpd.mk 2006-07-11 22:08:05.000000000 +0300 ++++ lighttpd-1.4.12/openwrt/lighttpd.mk 2006-07-17 22:02:18.000000000 +0300 @@ -10,7 +10,7 @@ # For this example we'll use a fairly simple package that compiles easily @@ -796,7 +796,7 @@ LIGHTTPD_DIR=$(BUILD_DIR)/$(LIGHTTPD) LIGHTTPD_IPK=$(BUILD_DIR)/$(LIGHTTPD)_mipsel.ipk --- ../lighttpd-1.4.11/src/Makefile.am 2006-03-07 14:20:20.000000000 +0200 -+++ lighttpd-1.4.12/src/Makefile.am 2006-07-15 23:38:00.000000000 +0300 ++++ lighttpd-1.4.12/src/Makefile.am 2006-07-18 13:03:40.000000000 +0300 @@ -16,18 +16,24 @@ else configparser.y: lemon @@ -824,7 +824,14 @@ common_src=buffer.c log.c \ keyvalue.c chunk.c \ -@@ -46,7 +52,7 @@ +@@ -40,13 +46,13 @@ + fdevent_solaris_devpoll.c fdevent_freebsd_kqueue.c \ + data_config.c bitset.c \ + inet_ntop_cache.c crc32.c \ +- connections-glue.c \ ++ connections-glue.c iosocket.c \ + configfile-glue.c \ + http-header-glue.c \ network_write.c network_linux_sendfile.c \ network_freebsd_sendfile.c network_writev.c \ network_solaris_sendfilev.c network_openssl.c \ @@ -857,24 +864,78 @@ lib_LTLIBRARIES += mod_cgi.la mod_cgi_la_SOURCES = mod_cgi.c mod_cgi_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined -@@ -240,7 +251,8 @@ +@@ -158,6 +169,13 @@ + mod_proxy_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined + mod_proxy_la_LIBADD = $(common_libadd) + ++lib_LTLIBRARIES += mod_proxy_core.la ++mod_proxy_core_la_SOURCES = mod_proxy_core.c mod_proxy_core_pool.c \ ++ mod_proxy_core_backend.c mod_proxy_core_address.c mod_proxy_core_backlog.c ++mod_proxy_core_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined ++mod_proxy_core_la_LIBADD = $(common_libadd) ++ ++ + lib_LTLIBRARIES += mod_ssi.la + mod_ssi_la_SOURCES = mod_ssi_exprparser.c mod_ssi_expr.c mod_ssi.c + mod_ssi_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined +@@ -240,7 +258,12 @@ mod_ssi.h mod_ssi_expr.h inet_ntop_cache.h \ configparser.h mod_ssi_exprparser.h \ sys-mmap.h sys-socket.h mod_cml.h mod_cml_funcs.h \ - splaytree.h proc_open.h + splaytree.h proc_open.h http_resp.h mod_sql_vhost_core.h \ -+ sys-files.h sys-process.h sys-strings.h http_resp_parser.h ++ sys-files.h sys-process.h sys-strings.h http_resp_parser.h \ ++ iosocket.h array-static.h \ ++ mod_proxy_core_address.h mod_proxy_core_backend.h \ ++ mod_proxy_core_backlog.h mod_proxy_core.h \ ++ mod_proxy_core_pool.h DEFS= @DEFS@ -DLIBRARY_DIR="\"$(libdir)\"" -@@ -267,4 +279,4 @@ +@@ -267,4 +290,4 @@ #ajp_SOURCES = ajp.c noinst_HEADERS = $(hdr) -EXTRA_DIST = mod_skeleton.c configparser.y mod_ssi_exprparser.y lempar.c +EXTRA_DIST = mod_skeleton.c configparser.y mod_ssi_exprparser.y lempar.c http_resp_parser.y +--- ../lighttpd-1.4.11/src/array-static.h 1970-01-01 03:00:00.000000000 +0300 ++++ lighttpd-1.4.12/src/array-static.h 2006-07-18 13:03:40.000000000 +0300 +@@ -0,0 +1,33 @@ ++#ifndef _ARRAY_STATIC_H_ ++#define _ARRAY_STATIC_H_ ++ ++/* define a generic array of ++ * */ ++ ++#define ARRAY_STATIC_DEF(name, type, extra) \ ++typedef struct { \ ++ type **ptr; \ ++ size_t used; \ ++ size_t size; \ ++ extra\ ++} name ++ ++/* all append operations need a 'resize' for the +1 */ ++ ++#define ARRAY_STATIC_PREPARE_APPEND(a) \ ++ if (a->size == 0) { \ ++ a->size = 16; \ ++ a->ptr = malloc(a->size * sizeof(*(a->ptr))); \ ++ } else if (a->size == a->used) { \ ++ a->size += 16; \ ++ a->ptr = realloc(a->ptr, a->size * sizeof(*(a->ptr))); \ ++ } ++ ++#define FOREACH(array, element, func) \ ++do { size_t _i; for (_i = 0; _i < array->used; _i++) { void *element = array->ptr[_i]; func; } } while(0); ++ ++#define STRUCT_INIT(type, var) \ ++ type *var;\ ++ var = calloc(1, sizeof(*var)) ++ ++#endif --- ../lighttpd-1.4.11/src/array.c 2005-11-18 13:58:32.000000000 +0200 -+++ lighttpd-1.4.12/src/array.c 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/array.c 2006-07-16 00:26:03.000000000 +0300 @@ -11,12 +11,12 @@ array *array_init(void) { @@ -1164,7 +1225,7 @@ } #endif --- ../lighttpd-1.4.11/src/array.h 2005-09-23 21:24:18.000000000 +0300 -+++ lighttpd-1.4.12/src/array.h 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/array.h 2006-07-16 00:26:03.000000000 +0300 @@ -16,7 +16,7 @@ #define DATA_UNSET \ data_type_t type; \ @@ -1283,7 +1344,7 @@ int last_used_ndx; /* round robin */ } data_fastcgi; --- ../lighttpd-1.4.11/src/base.h 2006-01-11 16:51:04.000000000 +0200 -+++ lighttpd-1.4.12/src/base.h 2006-07-15 22:43:21.000000000 +0300 ++++ lighttpd-1.4.12/src/base.h 2006-07-18 13:03:40.000000000 +0300 @@ -2,7 +2,6 @@ #define _BASE_H_ @@ -1458,7 +1519,7 @@ #ifdef HAVE_FAM_H int dir_version; int dir_ndx; -@@ -215,8 +198,8 @@ +@@ -215,20 +198,20 @@ } stat_cache_entry; typedef struct { @@ -1469,7 +1530,12 @@ buffer *dir_name; /* for building the dirname from the filename */ #ifdef HAVE_FAM_H splay_tree *dirs; /* the nodes of the tree are fam_dir_entry */ -@@ -228,7 +211,7 @@ + + FAMConnection *fam; +- int fam_fcce_ndx; ++ iosocket *sock; + #endif + } stat_cache; typedef struct { array *mimetypes; @@ -1569,7 +1635,7 @@ } connection_state_t; typedef enum { COND_RESULT_UNSET, COND_RESULT_FALSE, COND_RESULT_TRUE } cond_result_t; -@@ -315,88 +299,88 @@ +@@ -315,91 +299,86 @@ typedef struct { connection_state_t state; @@ -1596,9 +1662,10 @@ * this is self-protection */ - +- int fd; /* the FD for this connection */ +- int fde_ndx; /* index for the fdevent-handler */ + - int fd; /* the FD for this connection */ - int fde_ndx; /* index for the fdevent-handler */ ++ iosocket *sock; int ndx; /* reverse mapping to server->connection[ndx] */ - + @@ -1682,11 +1749,13 @@ + void *srv_socket; /* reference to the server-socket (typecast to server_socket) */ - -+ - #ifdef USE_OPENSSL - SSL *ssl; - #endif -@@ -439,39 +423,48 @@ +-#ifdef USE_OPENSSL +- SSL *ssl; +-#endif + } connection; + + typedef struct { +@@ -439,55 +418,63 @@ size_t size; } buffer_plugin; @@ -1703,9 +1772,8 @@ unsigned short port; buffer *bindhost; - -+ - buffer *errorlog_file; - unsigned short errorlog_use_syslog; +- buffer *errorlog_file; +- unsigned short errorlog_use_syslog; - + unsigned short dont_daemonize; @@ -1746,12 +1814,17 @@ + STAT_CACHE_ENGINE_FAM } stat_cache_engine; unsigned short enable_cores; ++ ++ buffer *errorlog_file; ++ unsigned short errorlog_use_syslog; } server_config; -@@ -480,14 +473,14 @@ + + typedef struct { sock_addr addr; - int fd; - int fde_ndx; +- int fd; +- int fde_ndx; - ++ iosocket *sock; + buffer *ssl_pemfile; buffer *ssl_ca_file; @@ -1765,7 +1838,7 @@ #ifdef USE_OPENSSL SSL_CTX *ssl_ctx; #endif -@@ -495,37 +488,37 @@ +@@ -495,37 +482,32 @@ typedef struct { server_socket **ptr; @@ -1778,11 +1851,10 @@ typedef struct server { server_socket_array srv_sockets; - -+ - /* the errorlog */ - int errorlog_fd; - enum { ERRORLOG_STDERR, ERRORLOG_FILE, ERRORLOG_SYSLOG } errorlog_mode; - buffer *errorlog_buf; +- /* the errorlog */ +- int errorlog_fd; +- enum { ERRORLOG_STDERR, ERRORLOG_FILE, ERRORLOG_SYSLOG } errorlog_mode; +- buffer *errorlog_buf; - + fdevents *ev, *ev_ins; @@ -1811,7 +1883,7 @@ size_t max_conns; /* buffers */ -@@ -533,13 +526,13 @@ +@@ -533,13 +515,13 @@ buffer *response_header; buffer *response_range; buffer *tmp_buf; @@ -1828,7 +1900,7 @@ /* caches */ #ifdef HAVE_IPV6 inet_ntop_cache_type inet_ntop_cache[INET_NTOP_CACHE_MAX]; -@@ -547,31 +540,31 @@ +@@ -547,31 +529,31 @@ mtime_cache_type mtime_cache[FILE_CACHE_MAX]; array *split_vals; @@ -1868,7 +1940,7 @@ stat_cache *stat_cache; /** -@@ -588,18 +581,20 @@ +@@ -588,18 +570,20 @@ * fastcgi.backend..disconnects = ... */ array *status; @@ -1878,13 +1950,13 @@ - int (* network_backend_write)(struct server *srv, connection *con, int fd, chunkqueue *cq); - int (* network_backend_read)(struct server *srv, connection *con, int fd, chunkqueue *cq); -+ network_status_t (* network_backend_write)(struct server *srv, connection *con, int fd, chunkqueue *cq); -+ network_status_t (* network_backend_read)(struct server *srv, connection *con, int fd, chunkqueue *cq); ++ network_status_t (* network_backend_write)(struct server *srv, connection *con, iosocket *sock, chunkqueue *cq); ++ network_status_t (* network_backend_read)(struct server *srv, connection *con, iosocket *sock, chunkqueue *cq); #ifdef USE_OPENSSL - int (* network_ssl_backend_write)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq); - int (* network_ssl_backend_read)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq); -+ network_status_t (* network_ssl_backend_write)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq); -+ network_status_t (* network_ssl_backend_read)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq); ++ network_status_t (* network_ssl_backend_write)(struct server *srv, connection *con, iosocket *sock, chunkqueue *cq); ++ network_status_t (* network_ssl_backend_read)(struct server *srv, connection *con, iosocket *sock, chunkqueue *cq); #endif +#ifdef HAVE_PWD_H @@ -1894,8 +1966,18 @@ } server; +--- ../lighttpd-1.4.11/src/bitset.c 2005-08-22 01:54:12.000000000 +0300 ++++ lighttpd-1.4.12/src/bitset.c 2006-07-18 13:03:40.000000000 +0300 +@@ -6,6 +6,7 @@ + + #include "bitset.h" + #include "buffer.h" ++#include "log.h" + + #define BITSET_BITS \ + ( CHAR_BIT * sizeof(size_t) ) --- ../lighttpd-1.4.11/src/buffer.c 2006-01-13 00:00:45.000000000 +0200 -+++ lighttpd-1.4.12/src/buffer.c 2006-07-11 22:07:52.000000000 +0300 ++++ lighttpd-1.4.12/src/buffer.c 2006-07-18 13:03:40.000000000 +0300 @@ -12,20 +12,20 @@ @@ -2297,7 +2379,13 @@ * HISTORY: this function was pretty much optimized, but didn't handled * alignment properly. */ -@@ -522,100 +591,100 @@ +@@ -517,105 +586,105 @@ + if (a->used != b->used) return 0; + if (a->used == 0) return 1; + +- return (0 == strcmp(a->ptr, b->ptr)); ++ return (0 == strncmp(a->ptr, b->ptr, a->used - 1)); + } int buffer_is_equal_string(buffer *a, const char *s, size_t b_len) { buffer b; @@ -2483,7 +2571,7 @@ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 70 - 7F */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80 - 8F */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 90 - 9F */ -@@ -734,13 +803,13 @@ +@@ -734,13 +803,12 @@ unsigned char *ds, *d; size_t d_len, ndx; const char *map = NULL; @@ -2491,16 +2579,18 @@ + if (!s || !b) return -1; - -+ - if (b->ptr[b->used - 1] != '\0') { - SEGFAULT(); - } +- if (b->ptr[b->used - 1] != '\0') { +- SEGFAULT(); +- } - ++ if (b->used == 0) return -1; ++ ++ if (b->ptr[b->used - 1] != '\0') return -1; + if (s_len == 0) return 0; switch(encoding) { -@@ -760,12 +829,12 @@ +@@ -760,12 +828,12 @@ map = encoded_chars_hex; break; case ENCODING_UNSET: @@ -2516,7 +2606,7 @@ for (ds = (unsigned char *)s, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) { if (map[*ds]) { switch(encoding) { -@@ -787,9 +856,9 @@ +@@ -787,9 +855,9 @@ d_len ++; } } @@ -2528,7 +2618,7 @@ for (ds = (unsigned char *)s, d = (unsigned char *)b->ptr + b->used - 1, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) { if (map[*ds]) { switch(encoding) { -@@ -820,16 +889,16 @@ +@@ -820,16 +888,16 @@ } } @@ -2548,7 +2638,7 @@ * replaces non-printable characters with '_' */ -@@ -854,10 +923,10 @@ +@@ -854,10 +922,10 @@ low = hex2int(*(src + 2)); if (low != 0xFF) { high = (high << 4) | low; @@ -2562,7 +2652,7 @@ *dst = high; src += 2; } -@@ -891,7 +960,7 @@ +@@ -891,7 +959,7 @@ * /abc/./xyz gets /abc/xyz * /abc//xyz gets /abc/xyz * @@ -2571,7 +2661,7 @@ * the operation is performed in-place. */ -@@ -979,7 +1048,7 @@ +@@ -979,7 +1047,7 @@ int light_isxdigit(int c) { if (light_isdigit(c)) return 1; @@ -2580,7 +2670,7 @@ c |= 32; return (c >= 'a' && c <= 'f'); } -@@ -993,31 +1062,56 @@ +@@ -993,31 +1061,56 @@ return light_isdigit(c) || light_isalpha(c); } @@ -2644,8 +2734,8 @@ return 0; } --- ../lighttpd-1.4.11/src/buffer.h 2006-01-13 00:00:45.000000000 +0200 -+++ lighttpd-1.4.12/src/buffer.h 2006-07-11 22:07:52.000000000 +0300 -@@ -12,27 +12,44 @@ ++++ lighttpd-1.4.12/src/buffer.h 2006-07-18 13:03:40.000000000 +0300 +@@ -12,27 +12,43 @@ typedef struct { char *ptr; @@ -2655,7 +2745,6 @@ size_t size; } buffer; -+ +typedef void (*buffer_ptr_free_t)(void *p); + +typedef struct { @@ -2696,7 +2785,7 @@ buffer_array* buffer_array_init(void); void buffer_array_free(buffer_array *b); void buffer_array_reset(buffer_array *b); -@@ -43,7 +60,7 @@ +@@ -43,7 +59,7 @@ buffer* buffer_init_string(const char *str); void buffer_free(buffer *b); void buffer_reset(buffer *b); @@ -2705,7 +2794,7 @@ int buffer_prepare_copy(buffer *b, size_t size); int buffer_prepare_append(buffer *b, size_t size); -@@ -85,9 +102,9 @@ +@@ -85,9 +101,9 @@ typedef enum { ENCODING_UNSET, @@ -2718,7 +2807,7 @@ ENCODING_MINIMAL_XML, /* minimal encoding for xml */ ENCODING_HEX /* encode string as hex */ } buffer_encoding_t; -@@ -111,19 +128,21 @@ +@@ -111,20 +127,23 @@ int light_isalpha(int c); int light_isalnum(int c); @@ -2728,6 +2817,7 @@ +BUFFER_CTYPE_FUNC(alpha) +BUFFER_CTYPE_FUNC(alnum) + ++#define BUF_STR(x) x->ptr #define BUFFER_APPEND_STRING_CONST(x, y) \ buffer_append_string_len(x, y, sizeof(y) - 1) @@ -2738,14 +2828,17 @@ - if (x->used > 1 && x->ptr[x->used - 2] != '/') { BUFFER_APPEND_STRING_CONST(x, "/"); } - #define CONST_STR_LEN(x) x, x ? sizeof(x) - 1 : 0 - #define CONST_BUF_LEN(x) x->ptr, x->used ? x->used - 1 : 0 +-#define CONST_BUF_LEN(x) x->ptr, x->used ? x->used - 1 : 0 ++#define CONST_BUF_LEN(x) BUF_STR(x), x->used ? x->used - 1 : 0 - - #define SEGFAULT() do { fprintf(stderr, "%s.%d: aborted\n", __FILE__, __LINE__); abort(); } while(0) +-#define SEGFAULT() do { fprintf(stderr, "%s.%d: aborted\n", __FILE__, __LINE__); abort(); } while(0) ++ #define UNUSED(x) ( (void)(x) ) + #endif --- ../lighttpd-1.4.11/src/chunk.c 2005-11-18 15:18:19.000000000 +0200 -+++ lighttpd-1.4.12/src/chunk.c 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/chunk.c 2006-07-18 13:03:40.000000000 +0300 @@ -1,16 +1,14 @@ /** * the network chunk-API @@ -3107,7 +3200,11 @@ return len; } -@@ -358,9 +359,9 @@ +@@ -355,12 +356,13 @@ + + switch (c->type) { + case MEM_CHUNK: ++ if (c->mem->used == 0) is_finished = 1; if (c->offset == (off_t)c->mem->used - 1) is_finished = 1; break; case FILE_CHUNK: @@ -3119,8 +3216,59 @@ break; } +@@ -383,3 +385,50 @@ + + return 0; + } ++ ++void chunkqueue_print(chunkqueue *cq) { ++ chunk *c; ++ ++ for (c = cq->first; c; c = c->next) { ++ fprintf(stderr, "(mem) %s", c->mem->ptr + c->offset); ++ } ++ fprintf(stderr, "\r\n"); ++} ++ ++ ++/** ++ * remove the last chunk if it is empty ++ */ ++ ++void chunkqueue_remove_empty_last_chunk(chunkqueue *cq) { ++ chunk *c; ++ if (!cq->last) return; ++ if (!cq->first) return; ++ ++ if (cq->first == cq->last) { ++ c = cq->first; ++ ++ if (c->type != MEM_CHUNK) return; ++ if (c->mem->used == 0) { ++ chunk_free(c); ++ cq->first = cq->last = NULL; ++ } ++ return; ++ } ++ ++ for (c = cq->first; c->next; c = c->next) { ++ if (c->type != MEM_CHUNK) continue; ++ if (c->mem->used != 0) continue; ++ ++ if (c->next == cq->last) { ++ cq->last = c; ++ ++ chunk_free(c->next); ++ c->next = NULL; ++ ++ return; ++ } ++ } ++} ++ ++ --- ../lighttpd-1.4.11/src/chunk.h 2005-11-01 09:32:21.000000000 +0200 -+++ lighttpd-1.4.12/src/chunk.h 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/chunk.h 2006-07-18 13:03:40.000000000 +0300 @@ -6,7 +6,7 @@ typedef struct chunk { @@ -3167,8 +3315,23 @@ chunk *unused; size_t unused_chunks; +@@ -56,6 +56,7 @@ + buffer * chunkqueue_get_append_buffer(chunkqueue *c); + buffer * chunkqueue_get_prepend_buffer(chunkqueue *c); + chunk * chunkqueue_get_append_tempfile(chunkqueue *cq); ++void chunkqueue_remove_empty_last_chunk(chunkqueue *cq); + + int chunkqueue_remove_finished_chunks(chunkqueue *cq); + +@@ -66,4 +67,6 @@ + + int chunkqueue_is_empty(chunkqueue *c); + ++void chunkqueue_print(chunkqueue *cq); ++ + #endif --- ../lighttpd-1.4.11/src/configfile-glue.c 2006-03-03 20:14:56.000000000 +0200 -+++ lighttpd-1.4.12/src/configfile-glue.c 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/configfile-glue.c 2006-07-16 00:26:03.000000000 +0300 @@ -1,4 +1,5 @@ #include +#include @@ -3655,7 +3818,7 @@ +} + --- ../lighttpd-1.4.11/src/configfile.c 2006-02-15 14:26:42.000000000 +0200 -+++ lighttpd-1.4.12/src/configfile.c 2006-07-15 22:43:21.000000000 +0300 ++++ lighttpd-1.4.12/src/configfile.c 2006-07-18 13:03:40.000000000 +0300 @@ -2,7 +2,6 @@ #include @@ -4238,7 +4401,7 @@ break; case '+': -@@ -637,96 +644,88 @@ +@@ -637,115 +644,107 @@ case '{': t->offset++; @@ -4359,11 +4522,19 @@ if (i && t->input[t->offset + i]) { buffer_copy_string_len(token, t->input + t->offset, i); - +- if (strcmp(token->ptr, "include") == 0) { + - if (strcmp(token->ptr, "include") == 0) { ++ if (buffer_is_equal_string(token, CONST_STR_LEN("include"))) { tid = TK_INCLUDE; - } else if (strcmp(token->ptr, "include_shell") == 0) { -@@ -738,14 +737,14 @@ +- } else if (strcmp(token->ptr, "include_shell") == 0) { ++ } else if (buffer_is_equal_string(token, CONST_STR_LEN("include_shell"))) { + tid = TK_INCLUDE_SHELL; +- } else if (strcmp(token->ptr, "global") == 0) { ++ } else if (buffer_is_equal_string(token, CONST_STR_LEN("global"))) { + tid = TK_GLOBAL; +- } else if (strcmp(token->ptr, "else") == 0) { ++ } else if (buffer_is_equal_string(token, CONST_STR_LEN("else"))) { + tid = TK_ELSE; } else { tid = TK_LKEY; } @@ -4739,7 +4910,7 @@ return 0; } --- ../lighttpd-1.4.11/src/configfile.h 2005-08-23 17:36:12.000000000 +0300 -+++ lighttpd-1.4.12/src/configfile.h 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/configfile.h 2006-07-16 00:26:03.000000000 +0300 @@ -9,7 +9,7 @@ server *srv; int ok; @@ -4750,7 +4921,7 @@ buffer *basedir; } config_t; --- ../lighttpd-1.4.11/src/configparser.c 2006-02-01 19:51:15.000000000 +0200 -+++ lighttpd-1.4.12/src/configparser.c 2006-07-11 22:08:02.000000000 +0300 ++++ lighttpd-1.4.12/src/configparser.c 2006-07-17 22:02:23.000000000 +0300 @@ -24,52 +24,34 @@ dc->parent = ctx->current; array_insert_unique(dc->parent->childs, (data_unset *)dc); @@ -5681,7 +5852,7 @@ ** This is what we do if the grammar does define ERROR: ** --- ../lighttpd-1.4.11/src/configparser.y 2006-01-26 18:46:25.000000000 +0200 -+++ lighttpd-1.4.12/src/configparser.y 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/configparser.y 2006-07-16 00:26:04.000000000 +0300 @@ -21,52 +21,34 @@ dc->parent = ctx->current; array_insert_unique(dc->parent->childs, (data_unset *)dc); @@ -5846,7 +6017,7 @@ A = B; B = NULL; --- ../lighttpd-1.4.11/src/connections-glue.c 2005-09-12 10:04:23.000000000 +0300 -+++ lighttpd-1.4.12/src/connections-glue.c 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/connections-glue.c 2006-07-16 00:26:03.000000000 +0300 @@ -13,7 +13,7 @@ case CON_STATE_REQUEST_END: return "req-end"; case CON_STATE_RESPONSE_START: return "resp-start"; @@ -5876,7 +6047,7 @@ } --- ../lighttpd-1.4.11/src/connections.c 2006-03-05 22:14:53.000000000 +0200 -+++ lighttpd-1.4.12/src/connections.c 2006-07-15 22:43:21.000000000 +0300 ++++ lighttpd-1.4.12/src/connections.c 2006-07-18 13:03:40.000000000 +0300 @@ -2,7 +2,6 @@ #include @@ -5915,7 +6086,7 @@ if (conns->size == 0) { conns->size = 128; conns->ptr = NULL; -@@ -54,21 +54,21 @@ +@@ -54,21 +54,14 @@ } else if (conns->size == conns->used) { conns->size += 128; conns->ptr = realloc(conns->ptr, sizeof(*conns->ptr) * conns->size); @@ -5928,20 +6099,18 @@ connection_reset(srv, conns->ptr[conns->used]); -#if 0 -+#if 0 - fprintf(stderr, "%s.%d: add: ", __FILE__, __LINE__); - for (i = 0; i < conns->used + 1; i++) { - fprintf(stderr, "%d ", conns->ptr[i]->fd); - } - fprintf(stderr, "\n"); +- fprintf(stderr, "%s.%d: add: ", __FILE__, __LINE__); +- for (i = 0; i < conns->used + 1; i++) { +- fprintf(stderr, "%d ", conns->ptr[i]->fd); +- } +- fprintf(stderr, "\n"); -#endif - -+#endif + conns->ptr[conns->used]->ndx = conns->used; return conns->ptr[conns->used++]; } -@@ -77,26 +77,26 @@ +@@ -77,263 +70,134 @@ size_t i; connections *conns = srv->conns; connection *temp; @@ -5974,14 +6143,14 @@ - + con->ndx = -1; - #if 0 - fprintf(stderr, "%s.%d: del: (%d)", __FILE__, __LINE__, conns->used); -@@ -104,25 +104,23 @@ - fprintf(stderr, "%d ", conns->ptr[i]->fd); - } - fprintf(stderr, "\n"); +-#if 0 +- fprintf(stderr, "%s.%d: del: (%d)", __FILE__, __LINE__, conns->used); +- for (i = 0; i < conns->used; i++) { +- fprintf(stderr, "%d ", conns->ptr[i]->fd); +- } +- fprintf(stderr, "\n"); -#endif -+#endif ++ return 0; } @@ -5993,30 +6162,39 @@ -#ifdef USE_OPENSSL + if (srv_sock->is_ssl) { - if (con->ssl) SSL_free(con->ssl); - con->ssl = NULL; +- if (con->ssl) SSL_free(con->ssl); +- con->ssl = NULL; ++ if (con->sock->ssl) SSL_free(con->sock->ssl); ++ con->sock->ssl = NULL; } #endif - -+ - fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd); - fdevent_unregister(srv->ev, con->fd); +- fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd); +- fdevent_unregister(srv->ev, con->fd); -#ifdef __WIN32 -+#ifdef _WIN32 - if (closesocket(con->fd)) { +- if (closesocket(con->fd)) { +- log_error_write(srv, __FILE__, __LINE__, "sds", +- "(warning) close:", con->fd, strerror(errno)); +- } +-#else +- if (close(con->fd)) { ++ ++ fdevent_event_del(srv->ev, con->sock); ++ fdevent_unregister(srv->ev, con->sock); ++ ++ if (closesocket(con->sock->fd)) { log_error_write(srv, __FILE__, __LINE__, "sds", - "(warning) close:", con->fd, strerror(errno)); -@@ -133,207 +131,96 @@ - "(warning) close:", con->fd, strerror(errno)); +- "(warning) close:", con->fd, strerror(errno)); ++ "(warning) close:", con->sock->fd, strerror(errno)); } - #endif +-#endif - + srv->cur_fds--; - #if 0 - log_error_write(srv, __FILE__, __LINE__, "sd", - "closed()", con->fd); - #endif +-#if 0 +- log_error_write(srv, __FILE__, __LINE__, "sd", +- "closed()", con->fd); +-#endif - + connection_del(srv, con); @@ -6091,9 +6269,7 @@ - b = chunkqueue_get_append_buffer(con->read_queue); - buffer_prepare_copy(b, 4096); -+static network_status_t connection_handle_read(server *srv, connection *con) { -+ off_t oldlen, newlen; - +- -#ifdef USE_OPENSSL - if (srv_sock->is_ssl) { - len = SSL_read(con->ssl, b->ptr, b->size - 1); @@ -6105,7 +6281,8 @@ - return -1; - } - buffer_prepare_copy(b, toread); -+ oldlen = chunkqueue_length(con->read_queue); ++static network_status_t connection_handle_read(server *srv, connection *con) { ++ off_t oldlen, newlen; - len = read(con->fd, b->ptr, b->size - 1); - } @@ -6119,7 +6296,8 @@ - return -1; - } - buffer_prepare_copy(b, toread); -- ++ oldlen = chunkqueue_length(con->read_queue); + - len = read(con->fd, b->ptr, b->size - 1); -#endif - @@ -6254,7 +6432,7 @@ } static int connection_handle_write_prepare(server *srv, connection *con) { -@@ -343,6 +230,7 @@ +@@ -343,6 +207,7 @@ case HTTP_METHOD_GET: case HTTP_METHOD_POST: case HTTP_METHOD_HEAD: @@ -6262,7 +6440,7 @@ case HTTP_METHOD_PUT: case HTTP_METHOD_MKCOL: case HTTP_METHOD_DELETE: -@@ -350,12 +238,14 @@ +@@ -350,12 +215,14 @@ case HTTP_METHOD_MOVE: case HTTP_METHOD_PROPFIND: case HTTP_METHOD_PROPPATCH: @@ -6279,7 +6457,7 @@ * */ if (con->uri.path->used && con->uri.path->ptr[0] != '*') { -@@ -381,55 +271,58 @@ +@@ -381,55 +248,60 @@ break; } } @@ -6303,8 +6481,10 @@ case 423: case 500: case 501: ++ case 502: case 503: - case 505: ++ case 504: + case 505: + case 509: if (con->mode != DIRECT) break; @@ -6353,7 +6533,7 @@ "\n" "\n" -@@ -439,7 +332,7 @@ +@@ -439,7 +311,7 @@ buffer_append_long(b, con->http_status); buffer_append_string(b, " - "); buffer_append_string(b, get_http_status_name(con->http_status)); @@ -6362,7 +6542,7 @@ buffer_append_string(b, "\n" " \n" -@@ -448,12 +341,12 @@ +@@ -448,12 +320,12 @@ buffer_append_long(b, con->http_status); buffer_append_string(b, " - "); buffer_append_string(b, get_http_status_name(con->http_status)); @@ -6378,7 +6558,7 @@ response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html")); } /* fall through */ -@@ -463,10 +356,10 @@ +@@ -463,10 +335,10 @@ case 301: case 302: break; @@ -6391,7 +6571,7 @@ break; case 205: /* class: header only */ case 304: -@@ -474,19 +367,19 @@ +@@ -474,19 +346,19 @@ /* disable chunked encoding again as we have no body */ con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED; chunkqueue_reset(con->write_queue); @@ -6417,7 +6597,7 @@ response_header_overwrite(srv, con, CONST_STR_LEN("Content-Length"), CONST_BUF_LEN(srv->tmp_buf)); } } else { -@@ -495,74 +388,77 @@ +@@ -495,77 +367,79 @@ ((con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0)) { con->keep_alive = 0; } @@ -6470,7 +6650,8 @@ - case -1: /* error on our side */ + case NETWORK_STATUS_FATAL_ERROR: /* error on our side */ log_error_write(srv, __FILE__, __LINE__, "sd", - "connection closed: write failed on fd", con->fd); +- "connection closed: write failed on fd", con->fd); ++ "connection closed: write failed on fd", con->sock->fd); connection_set_state(srv, con, CON_STATE_ERROR); joblist_append(srv, con); break; @@ -6507,11 +6688,15 @@ con = calloc(1, sizeof(*con)); - +- con->fd = 0; + - con->fd = 0; ++ con->sock = iosocket_init(); con->ndx = -1; - con->fde_ndx = -1; -@@ -573,32 +469,32 @@ +- con->fde_ndx = -1; + con->bytes_written = 0; + con->bytes_read = 0; + con->bytes_header = 0; +@@ -573,32 +447,32 @@ #define CLEAN(x) \ con->x = buffer_init(); @@ -6550,7 +6735,7 @@ #undef CLEAN con->write_queue = chunkqueue_init(); con->read_queue = chunkqueue_init(); -@@ -608,26 +504,26 @@ +@@ -608,26 +482,27 @@ con->request.headers = array_init(); con->response.headers = array_init(); con->environment = array_init(); @@ -6581,11 +6766,12 @@ + connection_reset(srv, con); - ++ iosocket_free(con->sock); + chunkqueue_free(con->write_queue); chunkqueue_free(con->read_queue); chunkqueue_free(con->request_content_queue); -@@ -637,27 +533,27 @@ +@@ -637,27 +512,27 @@ #define CLEAN(x) \ buffer_free(con->x); @@ -6618,7 +6804,7 @@ CLEAN(authed_user); CLEAN(server_name); CLEAN(error_handler); -@@ -665,97 +561,97 @@ +@@ -665,97 +540,97 @@ #undef CLEAN free(con->plugin_ctx); free(con->cond_cache); @@ -6742,7 +6928,7 @@ for (i = 0; i < srv->plugins.used; i++) { plugin *p = ((plugin **)(srv->plugins.ptr))[i]; plugin_data *pd = p->data; -@@ -768,7 +664,7 @@ +@@ -768,7 +643,7 @@ con->plugin_ctx[pd->id] = NULL; } @@ -6751,7 +6937,7 @@ #if COND_RESULT_UNSET for (i = srv->config_context->used - 1; i >= 0; i --) { con->cond_cache[i].result = COND_RESULT_UNSET; -@@ -777,56 +673,56 @@ +@@ -777,56 +652,56 @@ #else memset(con->cond_cache, 0, sizeof(cond_cache_t) * srv->config_context->used); #endif @@ -6827,7 +7013,7 @@ return NULL; } /** -@@ -840,22 +736,25 @@ +@@ -840,22 +715,25 @@ chunk *c; chunkqueue *cq = con->read_queue; chunkqueue *dst_cq = con->request_content_queue; @@ -6858,7 +7044,7 @@ } default: break; -@@ -891,14 +790,14 @@ +@@ -891,14 +769,14 @@ /* the last node was empty */ if (c->next == NULL) { cq->last = c; @@ -6875,7 +7061,7 @@ /* nothing to handle */ if (cq->first == NULL) return 0; -@@ -906,25 +805,26 @@ +@@ -906,25 +784,26 @@ case CON_STATE_READ: /* prepare con->request.request */ c = cq->first; @@ -6909,7 +7095,7 @@ } else { /* not found, copy everything */ buffer_copy_string_len(con->request.request, c->mem->ptr + c->offset, c->mem->used - c->offset - 1); -@@ -932,14 +832,14 @@ +@@ -932,14 +811,14 @@ } } else { /* have to take care of overlapping header terminators */ @@ -6927,7 +7113,7 @@ if (con->request.request->used - 1 > 3 && c->mem->used > 1 && s[l-2] == '\r' && -@@ -948,7 +848,7 @@ +@@ -948,7 +827,7 @@ c->mem->ptr[0] == '\n') { buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 1); c->offset += 1; @@ -6936,7 +7122,7 @@ h_term = con->request.request->ptr; } else if (con->request.request->used - 1 > 2 && c->mem->used > 2 && -@@ -958,7 +858,7 @@ +@@ -958,7 +837,7 @@ c->mem->ptr[1] == '\n') { buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 2); c->offset += 2; @@ -6945,7 +7131,7 @@ h_term = con->request.request->ptr; } else if (con->request.request->used - 1 > 1 && c->mem->used > 3 && -@@ -968,17 +868,17 @@ +@@ -968,17 +847,17 @@ c->mem->ptr[2] == '\n') { buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 3); c->offset += 3; @@ -6968,7 +7154,7 @@ /* the buffer has been read up to the terminator */ c->offset += h_term - b.ptr + 4; } else { -@@ -999,16 +899,16 @@ +@@ -999,16 +878,16 @@ connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST); } break; @@ -6990,7 +7176,7 @@ toRead = weHave > weWant ? weWant : weHave; /* the new way, copy everything into a chunkqueue whcih might use tempfiles */ -@@ -1017,13 +917,13 @@ +@@ -1017,13 +896,13 @@ /* copy everything to max 1Mb sized tempfiles */ /* @@ -7007,7 +7193,7 @@ * */ if (dst_cq->last && -@@ -1056,14 +956,14 @@ +@@ -1056,14 +935,14 @@ /* we have a chunk, let's write to it */ if (dst_c->file.fd == -1) { @@ -7024,7 +7210,7 @@ dst_c->file.name, strerror(errno)); con->http_status = 413; /* Request-Entity too large */ -@@ -1074,15 +974,15 @@ +@@ -1074,15 +953,15 @@ } if (toRead != write(dst_c->file.fd, c->mem->ptr + c->offset, toRead)) { @@ -7044,7 +7230,7 @@ close(dst_c->file.fd); dst_c->file.fd = -1; -@@ -1090,7 +990,7 @@ +@@ -1090,7 +969,7 @@ } dst_c->file.length += toRead; @@ -7053,7 +7239,7 @@ if (dst_cq->bytes_in + toRead == (off_t)con->request.content_length) { /* we read everything, close the chunk */ close(dst_c->file.fd); -@@ -1102,7 +1002,7 @@ +@@ -1102,7 +981,7 @@ b = chunkqueue_get_append_buffer(dst_cq); buffer_copy_string_len(b, c->mem->ptr + c->offset, toRead); } @@ -7062,7 +7248,7 @@ c->offset += toRead; dst_cq->bytes_in += toRead; } -@@ -1111,7 +1011,7 @@ +@@ -1111,7 +990,7 @@ if (dst_cq->bytes_in == (off_t)con->request.content_length) { connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST); } @@ -7071,7 +7257,7 @@ break; } -@@ -1123,9 +1023,9 @@ +@@ -1123,100 +1002,104 @@ handler_t connection_handle_fdevent(void *s, void *context, int revents) { server *srv = (server *)s; connection *con = context; @@ -7082,8 +7268,11 @@ + if (revents & FDEVENT_IN) { con->is_readable = 1; - #if 0 -@@ -1136,19 +1036,19 @@ +-#if 0 +- log_error_write(srv, __FILE__, __LINE__, "sd", "read-wait - done", con->fd); +-#endif + } + if (revents & FDEVENT_OUT) { con->is_writable = 1; /* we don't need the event twice */ } @@ -7108,7 +7297,12 @@ */ #ifdef USE_LINUX_SIGIO if (srv->ev->in_sigio == 1) { -@@ -1160,32 +1060,39 @@ + log_error_write(srv, __FILE__, __LINE__, "sd", +- "connection closed: poll() -> HUP", con->fd); ++ "connection closed: poll() -> HUP", con->sock->fd); + } else { + connection_set_state(srv, con, CON_STATE_ERROR); + } #else connection_set_state(srv, con, CON_STATE_ERROR); #endif @@ -7118,8 +7312,9 @@ } else if (revents & FDEVENT_ERR) { #ifndef USE_LINUX_SIGIO log_error_write(srv, __FILE__, __LINE__, "sd", - "connection closed: poll() -> ERR", con->fd); +- "connection closed: poll() -> ERR", con->fd); -#endif ++ "connection closed: poll() -> ERR", con->sock->fd); +#endif connection_set_state(srv, con, CON_STATE_ERROR); } else { @@ -7153,9 +7348,10 @@ - + log_error_write(srv, __FILE__, __LINE__, "ds", - con->fd, +- con->fd, ++ con->sock->fd, "handle write failed."); -@@ -1193,30 +1100,30 @@ + } else if (con->state == CON_STATE_WRITE) { con->write_request_ts = srv->cur_ts; } } @@ -7165,8 +7361,9 @@ /* flush the read buffers */ int b; - +- if (ioctl(con->fd, FIONREAD, &b)) { + - if (ioctl(con->fd, FIONREAD, &b)) { ++ if (ioctl(con->sock->fd, FIONREAD, &b)) { log_error_write(srv, __FILE__, __LINE__, "ss", "ioctl() failed", strerror(errno)); } @@ -7175,11 +7372,13 @@ if (b > 0) { char buf[1024]; log_error_write(srv, __FILE__, __LINE__, "sdd", - "CLOSE-read()", con->fd, b); +- "CLOSE-read()", con->fd, b); - ++ "CLOSE-read()", con->sock->fd, b); + /* */ - read(con->fd, buf, sizeof(buf)); +- read(con->fd, buf, sizeof(buf)); ++ read(con->sock->fd, buf, sizeof(buf)); } else { /* nothing to read */ - @@ -7192,7 +7391,7 @@ return HANDLER_FINISHED; } -@@ -1229,63 +1136,68 @@ +@@ -1229,63 +1112,68 @@ sock_addr cnt_addr; socklen_t cnt_len; /* accept it and register the fd */ @@ -7200,7 +7399,8 @@ + cnt_len = sizeof(cnt_addr); - if (-1 == (cnt = accept(srv_socket->fd, (struct sockaddr *) &cnt_addr, &cnt_len))) { +- if (-1 == (cnt = accept(srv_socket->fd, (struct sockaddr *) &cnt_addr, &cnt_len))) { ++ if (-1 == (cnt = accept(srv_socket->sock->fd, (struct sockaddr *) &cnt_addr, &cnt_len))) { +#ifdef _WIN32 + errno = WSAGetLastError(); +#endif @@ -7208,7 +7408,7 @@ + (errno != EWOULDBLOCK) && (errno != EINTR)) { - log_error_write(srv, __FILE__, __LINE__, "ssd", "accept failed:", strerror(errno), errno); -+ log_error_write(srv, __FILE__, __LINE__, "ssd", "accept failed:", strerror(errno), srv_socket->fd); ++ log_error_write(srv, __FILE__, __LINE__, "ssd", "accept failed:", strerror(errno), srv_socket->sock->fd); } return NULL; } else { @@ -7228,15 +7428,18 @@ + con = connections_get_new_connection(srv); - - con->fd = cnt; - con->fde_ndx = -1; +- con->fd = cnt; +- con->fde_ndx = -1; -#if 0 ++ con->sock->fd = cnt; ++ con->sock->fde_ndx = -1; +#if 0 gettimeofday(&(con->start_tv), NULL); -#endif -+#endif - fdevent_register(srv->ev, con->fd, connection_handle_fdevent, con); +- fdevent_register(srv->ev, con->fd, connection_handle_fdevent, con); - ++#endif ++ fdevent_register(srv->ev, con->sock, connection_handle_fdevent, con); + connection_set_state(srv, con, CON_STATE_REQUEST_START); - @@ -7246,8 +7449,9 @@ buffer_copy_string(con->dst_addr_buf, inet_ntop_cache_get_ip(srv, &(con->dst_addr))); con->srv_socket = srv_socket; - +- if (-1 == (fdevent_fcntl_set(srv->ev, con->fd))) { + - if (-1 == (fdevent_fcntl_set(srv->ev, con->fd))) { ++ if (-1 == (fdevent_fcntl_set(srv->ev, con->sock))) { log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno)); + connection_close(srv, con); return NULL; @@ -7255,8 +7459,9 @@ #ifdef USE_OPENSSL /* connect FD to SSL */ if (srv_socket->is_ssl) { - if (NULL == (con->ssl = SSL_new(srv_socket->ssl_ctx))) { +- if (NULL == (con->ssl = SSL_new(srv_socket->ssl_ctx))) { - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", ++ if (NULL == (con->sock->ssl = SSL_new(srv_socket->ssl_ctx))) { + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", ERR_error_string(ERR_get_error(), NULL)); - @@ -7264,20 +7469,22 @@ return NULL; } - +- SSL_set_accept_state(con->ssl); + - SSL_set_accept_state(con->ssl); ++ SSL_set_accept_state(con->sock->ssl); con->conf.is_ssl=1; - -+ - if (1 != (SSL_set_fd(con->ssl, cnt))) { +- if (1 != (SSL_set_fd(con->ssl, cnt))) { - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", ++ ++ if (1 != (SSL_set_fd(con->sock->ssl, cnt))) { + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", ERR_error_string(ERR_get_error(), NULL)); + connection_close(srv, con); return NULL; } } -@@ -1300,10 +1212,10 @@ +@@ -1300,102 +1188,102 @@ #ifdef USE_OPENSSL server_socket *srv_sock = con->srv_socket; #endif @@ -7286,12 +7493,13 @@ if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sds", - "state at start", +- con->fd, + log_error_write(srv, __FILE__, __LINE__, "sds", + "state at start", - con->fd, ++ con->sock->fd, connection_get_state(con->state)); } -@@ -1311,91 +1223,91 @@ + while (done == 0) { size_t ostate = con->state; int b; @@ -7301,8 +7509,9 @@ case CON_STATE_REQUEST_START: /* transient */ if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sds", +- "state for fd", con->fd, connection_get_state(con->state)); + log_error_write(srv, __FILE__, __LINE__, "sds", - "state for fd", con->fd, connection_get_state(con->state)); ++ "state for fd", con->sock->fd, connection_get_state(con->state)); } - + @@ -7321,8 +7530,9 @@ case CON_STATE_REQUEST_END: /* transient */ if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sds", +- "state for fd", con->fd, connection_get_state(con->state)); + log_error_write(srv, __FILE__, __LINE__, "sds", - "state for fd", con->fd, connection_get_state(con->state)); ++ "state for fd", con->sock->fd, connection_get_state(con->state)); } - + @@ -7358,8 +7568,9 @@ + if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sds", +- "state for fd", con->fd, connection_get_state(con->state)); + log_error_write(srv, __FILE__, __LINE__, "sds", - "state for fd", con->fd, connection_get_state(con->state)); ++ "state for fd", con->sock->fd, connection_get_state(con->state)); } - + @@ -7413,7 +7624,7 @@ "If this is a rails app: check your production.log"); con->http_status = con->error_handler_saved_status; } -@@ -1403,26 +1315,26 @@ +@@ -1403,73 +1291,73 @@ /* error-handler is back and has generated content */ /* if Status: was set, take it otherwise use 200 */ } @@ -7446,8 +7657,11 @@ break; case HANDLER_ERROR: /* something went wrong */ -@@ -1432,44 +1344,44 @@ - log_error_write(srv, __FILE__, __LINE__, "sdd", "unknown ret-value: ", con->fd, r); + connection_set_state(srv, con, CON_STATE_ERROR); + break; + default: +- log_error_write(srv, __FILE__, __LINE__, "sdd", "unknown ret-value: ", con->fd, r); ++ log_error_write(srv, __FILE__, __LINE__, "sdd", "unknown ret-value: ", con->sock->fd, r); break; } - @@ -7465,8 +7679,9 @@ + if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sds", +- "state for fd", con->fd, connection_get_state(con->state)); + log_error_write(srv, __FILE__, __LINE__, "sds", - "state for fd", con->fd, connection_get_state(con->state)); ++ "state for fd", con->sock->fd, connection_get_state(con->state)); } - + @@ -7486,8 +7701,9 @@ + if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sds", +- "state for fd", con->fd, connection_get_state(con->state)); + log_error_write(srv, __FILE__, __LINE__, "sds", - "state for fd", con->fd, connection_get_state(con->state)); ++ "state for fd", con->sock->fd, connection_get_state(con->state)); } - + @@ -7506,7 +7722,7 @@ con->request_start = srv->cur_ts; con->read_idle_ts = srv->cur_ts; #endif -@@ -1482,7 +1394,7 @@ +@@ -1482,103 +1370,103 @@ log_error_write(srv, __FILE__, __LINE__, "sd", "unhandling return value", r); break; } @@ -7514,8 +7730,9 @@ + #ifdef USE_OPENSSL if (srv_sock->is_ssl) { - switch (SSL_shutdown(con->ssl)) { -@@ -1490,44 +1402,44 @@ +- switch (SSL_shutdown(con->ssl)) { ++ switch (SSL_shutdown(con->sock->ssl)) { + case 1: /* done */ break; case 0: @@ -7551,8 +7768,9 @@ case CON_STATE_CONNECT: if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sds", +- "state for fd", con->fd, connection_get_state(con->state)); + log_error_write(srv, __FILE__, __LINE__, "sds", - "state for fd", con->fd, connection_get_state(con->state)); ++ "state for fd", con->sock->fd, connection_get_state(con->state)); } - + @@ -7566,22 +7784,28 @@ case CON_STATE_CLOSE: if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sds", +- "state for fd", con->fd, connection_get_state(con->state)); + log_error_write(srv, __FILE__, __LINE__, "sds", - "state for fd", con->fd, connection_get_state(con->state)); ++ "state for fd", con->sock->fd, connection_get_state(con->state)); } - + if (con->keep_alive) { - if (ioctl(con->fd, FIONREAD, &b)) { +- if (ioctl(con->fd, FIONREAD, &b)) { ++ if (ioctl(con->sock->fd, FIONREAD, &b)) { log_error_write(srv, __FILE__, __LINE__, "ss", -@@ -1537,43 +1449,43 @@ + "ioctl() failed", strerror(errno)); + } + if (b > 0) { char buf[1024]; log_error_write(srv, __FILE__, __LINE__, "sdd", - "CLOSE-read()", con->fd, b); +- "CLOSE-read()", con->fd, b); - ++ "CLOSE-read()", con->sock->fd, b); + /* */ - read(con->fd, buf, sizeof(buf)); +- read(con->fd, buf, sizeof(buf)); ++ read(con->sock->fd, buf, sizeof(buf)); } else { /* nothing to read */ - @@ -7599,8 +7823,9 @@ + if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sd", +- "connection closed for fd", con->fd); + log_error_write(srv, __FILE__, __LINE__, "sd", - "connection closed for fd", con->fd); ++ "connection closed for fd", con->sock->fd); } } - @@ -7610,8 +7835,9 @@ case CON_STATE_READ: if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sds", +- "state for fd", con->fd, connection_get_state(con->state)); + log_error_write(srv, __FILE__, __LINE__, "sds", - "state for fd", con->fd, connection_get_state(con->state)); ++ "state for fd", con->sock->fd, connection_get_state(con->state)); } - + @@ -7620,15 +7846,30 @@ case CON_STATE_WRITE: if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sds", +- "state for fd", con->fd, connection_get_state(con->state)); + log_error_write(srv, __FILE__, __LINE__, "sds", - "state for fd", con->fd, connection_get_state(con->state)); ++ "state for fd", con->sock->fd, connection_get_state(con->state)); } - + /* only try to write if we have something in the queue */ if (!chunkqueue_is_empty(con->write_queue)) { #if 0 -@@ -1593,10 +1505,10 @@ + log_error_write(srv, __FILE__, __LINE__, "dsd", +- con->fd, ++ con->sock->fd, + "packets to write:", + con->write_queue->used); + #endif +@@ -1586,17 +1474,17 @@ + if (!chunkqueue_is_empty(con->write_queue) && con->is_writable) { + if (-1 == connection_handle_write(srv, con)) { + log_error_write(srv, __FILE__, __LINE__, "ds", +- con->fd, ++ con->sock->fd, + "handle write failed."); + connection_set_state(srv, con, CON_STATE_ERROR); + } else if (con->state == CON_STATE_WRITE) { con->write_request_ts = srv->cur_ts; } } @@ -7641,14 +7882,24 @@ /* even if the connection was drop we still have to write it to the access log */ if (con->http_status) { plugins_call_handle_request_done(srv, con); -@@ -1612,19 +1524,19 @@ - SSL_shutdown(con->ssl); +@@ -1604,28 +1492,28 @@ + #ifdef USE_OPENSSL + if (srv_sock->is_ssl) { + int ret; +- switch ((ret = SSL_shutdown(con->ssl))) { ++ switch ((ret = SSL_shutdown(con->sock->ssl))) { + case 1: + /* ok */ + break; + case 0: +- SSL_shutdown(con->ssl); ++ SSL_shutdown(con->sock->ssl); break; default: - log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:", - SSL_get_error(con->ssl, ret), + log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:", -+ SSL_get_error(con->ssl, ret), ++ SSL_get_error(con->sock->ssl, ret), ERR_error_string(ERR_get_error(), NULL)); return -1; } @@ -7661,12 +7912,14 @@ #if 0 - log_error_write(srv, __FILE__, __LINE__, "sd", - "emergency exit: direct", +- con->fd); + log_error_write(srv, __FILE__, __LINE__, "sd", + "emergency exit: direct", - con->fd); ++ con->sock->fd); #endif break; -@@ -1639,35 +1551,35 @@ + default: +@@ -1639,35 +1527,35 @@ } break; } @@ -7677,15 +7930,17 @@ + /* close the connection */ if ((con->keep_alive == 1) && - (0 == shutdown(con->fd, SHUT_WR))) { +- (0 == shutdown(con->fd, SHUT_WR))) { ++ (0 == shutdown(con->sock->fd, SHUT_WR))) { con->close_timeout_ts = srv->cur_ts; connection_set_state(srv, con, CON_STATE_CLOSE); - + if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sd", +- "shutdown for fd", con->fd); + log_error_write(srv, __FILE__, __LINE__, "sd", - "shutdown for fd", con->fd); ++ "shutdown for fd", con->sock->fd); } } else { connection_close(srv, con); @@ -7701,9 +7956,10 @@ break; default: - log_error_write(srv, __FILE__, __LINE__, "sdd", -+ log_error_write(srv, __FILE__, __LINE__, "sdd", - "unknown state:", con->fd, con->state); +- "unknown state:", con->fd, con->state); - ++ log_error_write(srv, __FILE__, __LINE__, "sdd", ++ "unknown state:", con->sock->fd, con->state); + break; } @@ -7712,15 +7968,16 @@ if (done == -1) { done = 0; } else if (ostate == con->state) { -@@ -1676,12 +1588,12 @@ +@@ -1676,33 +1564,33 @@ } if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sds", - "state at exit:", +- con->fd, + log_error_write(srv, __FILE__, __LINE__, "sds", + "state at exit:", - con->fd, ++ con->sock->fd, connection_get_state(con->state)); } - @@ -7728,8 +7985,9 @@ switch(con->state) { case CON_STATE_READ_POST: case CON_STATE_READ: -@@ -1689,11 +1601,11 @@ - fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_IN); + case CON_STATE_CLOSE: +- fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_IN); ++ fdevent_event_add(srv->ev, con->sock, FDEVENT_IN); break; case CON_STATE_WRITE: - /* request write-fdevent only if we really need it @@ -7742,9 +8000,21 @@ + if (!chunkqueue_is_empty(con->write_queue) && (con->is_writable == 0) && (con->traffic_limit_reached == 0)) { - fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_OUT); +- fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_OUT); ++ fdevent_event_add(srv->ev, con->sock, FDEVENT_OUT); + } else { +- fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd); ++ fdevent_event_del(srv->ev, con->sock); + } + break; + default: +- fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd); ++ fdevent_event_del(srv->ev, con->sock); + break; + } + --- ../lighttpd-1.4.11/src/crc32.h 2005-09-30 20:18:59.000000000 +0300 -+++ lighttpd-1.4.12/src/crc32.h 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/crc32.h 2006-07-16 00:26:04.000000000 +0300 @@ -6,6 +6,7 @@ #endif @@ -7765,7 +8035,7 @@ #endif --- ../lighttpd-1.4.11/src/data_array.c 2005-08-23 17:36:12.000000000 +0300 -+++ lighttpd-1.4.12/src/data_array.c 2006-07-11 22:07:52.000000000 +0300 ++++ lighttpd-1.4.12/src/data_array.c 2006-07-16 00:26:04.000000000 +0300 @@ -17,16 +17,16 @@ static void data_array_free(data_unset *d) { @@ -7819,7 +8089,7 @@ return ds; } --- ../lighttpd-1.4.11/src/data_config.c 2005-08-17 12:53:19.000000000 +0300 -+++ lighttpd-1.4.12/src/data_config.c 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/data_config.c 2006-07-16 00:26:03.000000000 +0300 @@ -17,26 +17,26 @@ static void data_config_free(data_unset *d) { @@ -7901,7 +8171,7 @@ return ds; } --- ../lighttpd-1.4.11/src/data_count.c 2005-08-23 17:36:12.000000000 +0300 -+++ lighttpd-1.4.12/src/data_count.c 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/data_count.c 2006-07-16 00:26:03.000000000 +0300 @@ -16,53 +16,53 @@ static void data_count_free(data_unset *d) { @@ -7969,7 +8239,7 @@ return ds; } --- ../lighttpd-1.4.11/src/data_fastcgi.c 2005-08-23 17:36:12.000000000 +0300 -+++ lighttpd-1.4.12/src/data_fastcgi.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/data_fastcgi.c 2006-07-16 00:26:04.000000000 +0300 @@ -17,53 +17,53 @@ static void data_fastcgi_free(data_unset *d) { @@ -8035,7 +8305,7 @@ return ds; } --- ../lighttpd-1.4.11/src/data_integer.c 2005-08-23 17:36:12.000000000 +0300 -+++ lighttpd-1.4.12/src/data_integer.c 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/data_integer.c 2006-07-16 00:26:03.000000000 +0300 @@ -16,15 +16,15 @@ static void data_integer_free(data_unset *d) { @@ -8091,7 +8361,7 @@ return ds; } --- ../lighttpd-1.4.11/src/data_string.c 2005-08-23 17:36:12.000000000 +0300 -+++ lighttpd-1.4.12/src/data_string.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/data_string.c 2006-07-16 00:26:04.000000000 +0300 @@ -17,16 +17,16 @@ static void data_string_free(data_unset *d) { @@ -8188,7 +8458,16 @@ return ds; } --- ../lighttpd-1.4.11/src/etag.c 2005-08-11 01:26:40.000000000 +0300 -+++ lighttpd-1.4.12/src/etag.c 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/etag.c 2006-07-18 13:03:40.000000000 +0300 +@@ -4,7 +4,7 @@ + #include "etag.h" + + int etag_is_equal(buffer *etag, const char *matches) { +- if (0 == strcmp(etag->ptr, matches)) return 1; ++ if (buffer_is_equal_string(etag, matches, strlen(matches))) return 1; + return 0; + } + @@ -14,19 +14,19 @@ buffer_append_off_t(etag, st->st_size); buffer_append_string_len(etag, CONST_STR_LEN("-")); @@ -8214,7 +8493,7 @@ return 0; } --- ../lighttpd-1.4.11/src/etag.h 2005-08-11 01:26:40.000000000 +0300 -+++ lighttpd-1.4.12/src/etag.h 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/etag.h 2006-07-16 00:26:03.000000000 +0300 @@ -3,13 +3,12 @@ #include @@ -8231,7 +8510,7 @@ #endif --- ../lighttpd-1.4.11/src/fastcgi.h 2005-08-11 01:26:40.000000000 +0300 -+++ lighttpd-1.4.12/src/fastcgi.h 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/fastcgi.h 2006-07-16 00:26:03.000000000 +0300 @@ -1,4 +1,4 @@ -/* +/* @@ -8248,7 +8527,7 @@ } FCGI_UnknownTypeBody; --- ../lighttpd-1.4.11/src/fdevent.c 2005-11-15 10:51:05.000000000 +0200 -+++ lighttpd-1.4.12/src/fdevent.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/fdevent.c 2006-07-18 13:03:40.000000000 +0300 @@ -2,7 +2,6 @@ #include "settings.h" @@ -8257,12 +8536,67 @@ #include #include #include -@@ -12,59 +11,61 @@ +@@ -11,60 +10,116 @@ + #include "fdevent.h" #include "buffer.h" - ++#include "log.h" ++ +#include "sys-socket.h" + ++fdevent_revent *fdevent_revent_init(void) { ++ STRUCT_INIT(fdevent_revent, revent); ++ ++ return revent; ++} ++ ++void fdevent_revent_free(fdevent_revent *revent) { ++ if (!revent) return; ++ ++ free(revent); ++} ++ ++fdevent_revents *fdevent_revents_init(void) { ++ STRUCT_INIT(fdevent_revents, revents); ++ ++ return revents; ++} ++ ++void fdevent_revents_reset(fdevent_revents *revents) { ++ if (!revents) return; ++ ++ revents->used = 0; ++} ++ ++void fdevent_revents_add(fdevent_revents *revents, int fd, int events) { ++ fdevent_revent *revent; ++ ++ if (revents->used == revents->size) { ++ /* resize the events-array */ ++ revents->ptr = realloc(revents->ptr, (revents->size + 1) * sizeof(*(revents->ptr))); ++ revents->ptr[revents->size++] = fdevent_revent_init(); ++ } ++ ++ revent = revents->ptr[revents->used++]; ++ revent->fd = fd; ++ revent->revents = events; ++} ++ ++void fdevent_revents_free(fdevent_revents *revents) { ++ size_t i; ++ ++ if (!revents) return; ++ ++ if (revents->size) { ++ for (i = 0; i < revents->size; i++) { ++ fdevent_revent_free(revents->ptr[i]); ++ } ++ ++ free(revents->ptr); ++ } ++ free(revents); ++} + fdevents *fdevent_init(size_t maxfds, fdevent_handler_t type) { fdevents *ev; - @@ -8329,7 +8663,7 @@ __FILE__, __LINE__); return NULL; } -@@ -75,26 +76,26 @@ +@@ -75,28 +130,29 @@ void fdevent_free(fdevents *ev) { size_t i; if (!ev) return; @@ -8360,124 +8694,164 @@ + fdn = calloc(1, sizeof(*fdn)); fdn->fd = -1; ++ return fdn; -@@ -106,12 +107,12 @@ + } - int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx) { +@@ -104,48 +160,40 @@ + free(fdn); + } + +-int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx) { ++int fdevent_register(fdevents *ev, iosocket *sock, fdevent_handler handler, void *ctx) { fdnode *fdn; - + fdn = fdnode_init(); fdn->handler = handler; - fdn->fd = fd; +- fdn->fd = fd; ++ fdn->fd = sock->fd; fdn->ctx = ctx; - +- ev->fdarray[fd] = fdn; + - ev->fdarray[fd] = fdn; ++ ev->fdarray[sock->fd] = fdn; return 0; -@@ -121,31 +122,31 @@ + } + +-int fdevent_unregister(fdevents *ev, int fd) { ++int fdevent_unregister(fdevents *ev, iosocket *sock) { fdnode *fdn; if (!ev) return 0; - fdn = ev->fdarray[fd]; +- fdn = ev->fdarray[fd]; - ++ fdn = ev->fdarray[sock->fd]; + fdnode_free(fdn); - -+ - ev->fdarray[fd] = NULL; +- ev->fdarray[fd] = NULL; - ++ ++ ev->fdarray[sock->fd] = NULL; + return 0; } - int fdevent_event_del(fdevents *ev, int *fde_ndx, int fd) { - int fde = fde_ndx ? *fde_ndx : -1; +-int fdevent_event_del(fdevents *ev, int *fde_ndx, int fd) { +- int fde = fde_ndx ? *fde_ndx : -1; - -+ - if (ev->event_del) fde = ev->event_del(ev, fde, fd); +- if (ev->event_del) fde = ev->event_del(ev, fde, fd); - -+ - if (fde_ndx) *fde_ndx = fde; +- if (fde_ndx) *fde_ndx = fde; - ++int fdevent_event_del(fdevents *ev, iosocket *sock) { ++ if (ev->event_del) ev->event_del(ev, sock); + return 0; } - int fdevent_event_add(fdevents *ev, int *fde_ndx, int fd, int events) { - int fde = fde_ndx ? *fde_ndx : -1; +-int fdevent_event_add(fdevents *ev, int *fde_ndx, int fd, int events) { +- int fde = fde_ndx ? *fde_ndx : -1; - -+ - if (ev->event_add) fde = ev->event_add(ev, fde, fd, events); +- if (ev->event_add) fde = ev->event_add(ev, fde, fd, events); - -+ - if (fde_ndx) *fde_ndx = fde; +- if (fde_ndx) *fde_ndx = fde; - ++int fdevent_event_add(fdevents *ev, iosocket *sock, int events) { ++ if (ev->event_add) ev->event_add(ev, sock, events); + return 0; } -@@ -156,38 +157,43 @@ +@@ -154,49 +202,41 @@ + return ev->poll(ev, timeout_ms); + } - int fdevent_event_get_revent(fdevents *ev, size_t ndx) { - if (ev->event_get_revent == NULL) SEGFAULT(); +-int fdevent_event_get_revent(fdevents *ev, size_t ndx) { +- if (ev->event_get_revent == NULL) SEGFAULT(); - -+ - return ev->event_get_revent(ev, ndx); - } +- return ev->event_get_revent(ev, ndx); +-} ++int fdevent_get_revents(fdevents *ev, size_t event_count, fdevent_revents *revents) { ++ size_t i; - int fdevent_event_get_fd(fdevents *ev, size_t ndx) { - if (ev->event_get_fd == NULL) SEGFAULT(); +-int fdevent_event_get_fd(fdevents *ev, size_t ndx) { +- if (ev->event_get_fd == NULL) SEGFAULT(); - -+ - return ev->event_get_fd(ev, ndx); - } +- return ev->event_get_fd(ev, ndx); +-} ++ if (ev->get_revents == NULL) SEGFAULT(); - fdevent_handler fdevent_get_handler(fdevents *ev, int fd) { - if (ev->fdarray[fd] == NULL) SEGFAULT(); - if (ev->fdarray[fd]->fd != fd) SEGFAULT(); +-fdevent_handler fdevent_get_handler(fdevents *ev, int fd) { +- if (ev->fdarray[fd] == NULL) SEGFAULT(); +- if (ev->fdarray[fd]->fd != fd) SEGFAULT(); - -+ - return ev->fdarray[fd]->handler; - } +- return ev->fdarray[fd]->handler; +-} ++ fdevent_revents_reset(revents); - void * fdevent_get_context(fdevents *ev, int fd) { - if (ev->fdarray[fd] == NULL) SEGFAULT(); - if (ev->fdarray[fd]->fd != fd) SEGFAULT(); +-void * fdevent_get_context(fdevents *ev, int fd) { +- if (ev->fdarray[fd] == NULL) SEGFAULT(); +- if (ev->fdarray[fd]->fd != fd) SEGFAULT(); - +- return ev->fdarray[fd]->ctx; ++ ev->get_revents(ev, event_count, revents); ++ ++ /* patch the event handlers */ ++ for (i = 0; i < event_count; i++) { ++ fdevent_revent *r = revents->ptr[i]; ++ ++ r->handler = ev->fdarray[r->fd]->handler; ++ r->context = ev->fdarray[r->fd]->ctx; ++ } + - return ev->fdarray[fd]->ctx; ++ return 0; } - int fdevent_fcntl_set(fdevents *ev, int fd) { +-int fdevent_fcntl_set(fdevents *ev, int fd) { ++int fdevent_fcntl_set(fdevents *ev, iosocket *sock) { +#ifdef _WIN32 -+ int i = 1; ++ int i = 1; +#endif #ifdef FD_CLOEXEC /* close fd on exec (cgi) */ - fcntl(fd, F_SETFD, FD_CLOEXEC); +- fcntl(fd, F_SETFD, FD_CLOEXEC); ++ fcntl(sock->fd, F_SETFD, FD_CLOEXEC); #endif - if ((ev) && (ev->fcntl_set)) return ev->fcntl_set(ev, fd); +- if ((ev) && (ev->fcntl_set)) return ev->fcntl_set(ev, fd); -#ifdef O_NONBLOCK +- return fcntl(fd, F_SETFL, O_NONBLOCK | O_RDWR); ++ if ((ev) && (ev->fcntl_set)) return ev->fcntl_set(ev, sock->fd); +#ifdef O_NONBLOCK - return fcntl(fd, F_SETFL, O_NONBLOCK | O_RDWR); ++ return fcntl(sock->fd, F_SETFL, O_NONBLOCK | O_RDWR); +#elif defined _WIN32 -+ return ioctlsocket(fd, FIONBIO, &i); ++ return ioctlsocket(sock->fd, FIONBIO, &i); #else return 0; #endif -@@ -196,7 +202,7 @@ + } - int fdevent_event_next_fdndx(fdevents *ev, int ndx) { - if (ev->event_next_fdndx) return ev->event_next_fdndx(ev, ndx); +- +-int fdevent_event_next_fdndx(fdevents *ev, int ndx) { +- if (ev->event_next_fdndx) return ev->event_next_fdndx(ev, ndx); - +- return -1; +-} +- +--- ../lighttpd-1.4.11/src/fdevent.h 2005-09-27 11:26:33.000000000 +0300 ++++ lighttpd-1.4.12/src/fdevent.h 2006-07-18 13:03:40.000000000 +0300 +@@ -7,6 +7,9 @@ + #include "settings.h" + #include "bitset.h" + ++#include "iosocket.h" ++#include "array-static.h" + - return -1; - } + /* select event-system */ ---- ../lighttpd-1.4.11/src/fdevent.h 2005-09-27 11:26:33.000000000 +0300 -+++ lighttpd-1.4.12/src/fdevent.h 2006-07-11 22:07:51.000000000 +0300 -@@ -17,13 +17,13 @@ + #if defined(HAVE_EPOLL_CTL) && defined(HAVE_SYS_EPOLL_H) +@@ -17,13 +20,13 @@ # include #endif @@ -8493,7 +8867,7 @@ # include # endif # if defined HAVE_SIGTIMEDWAIT && defined(__linux__) -@@ -31,9 +31,11 @@ +@@ -31,9 +34,11 @@ # include # endif #endif @@ -8507,7 +8881,7 @@ # include # endif # define USE_SELECT -@@ -67,14 +69,14 @@ +@@ -67,14 +72,14 @@ #define FDEVENT_HUP BV(4) #define FDEVENT_NVAL BV(5) @@ -8528,7 +8902,7 @@ FDEVENT_HANDLER_SELECT, FDEVENT_HANDLER_POLL, FDEVENT_HANDLER_LINUX_RTSIG, -@@ -86,7 +88,7 @@ +@@ -86,7 +91,7 @@ /** * a mapping from fd to connection structure @@ -8537,15 +8911,29 @@ */ typedef struct { int fd; /**< the fd */ -@@ -98,41 +100,41 @@ +@@ -96,43 +101,51 @@ + int revents; + } fd_conn; ++ARRAY_STATIC_DEF(fd_conn_buffer, fd_conn, ); ++ ++/** ++ * revents ++ */ typedef struct { - fd_conn *ptr; +- fd_conn *ptr; - +- size_t size; +- size_t used; +-} fd_conn_buffer; ++ int fd; ++ int revents; + - size_t size; - size_t used; - } fd_conn_buffer; ++ fdevent_handler handler; ++ void *context; ++} fdevent_revent; ++ ++ARRAY_STATIC_DEF(fdevent_revents, fdevent_revent, ); /** * array of unused fd's @@ -8554,10 +8942,13 @@ */ typedef struct _fdnode { - fdevent_handler handler; - void *ctx; - int fd; +- fdevent_handler handler; +- void *ctx; +- int fd; - ++ fdevent_handler handler; /* who handles the events for this fd */ ++ void *ctx; /* opaque pointer which is passed as 3rd parameter to the handler */ ++ int fd; /* fd */ + struct _fdnode *prev, *next; } fdnode; @@ -8578,15 +8969,16 @@ typedef struct fdevents { fdevent_handler_t type; - +- fdnode **fdarray; + - fdnode **fdarray; ++ fdnode **fdarray; /* a list of fdnodes */ size_t maxfds; - + #ifdef USE_LINUX_SIGIO int in_sigio; int signum; -@@ -146,21 +148,21 @@ +@@ -146,21 +159,21 @@ #endif #ifdef USE_POLL struct pollfd *pollfds; @@ -8612,20 +9004,22 @@ int select_max_fd; #endif #ifdef USE_SOLARIS_DEVPOLL -@@ -177,16 +179,16 @@ +@@ -177,16 +190,13 @@ #endif int (*reset)(struct fdevents *ev); void (*free)(struct fdevents *ev); - -+ - int (*event_add)(struct fdevents *ev, int fde_ndx, int fd, int events); - int (*event_del)(struct fdevents *ev, int fde_ndx, int fd); - int (*event_get_revent)(struct fdevents *ev, size_t ndx); - int (*event_get_fd)(struct fdevents *ev, size_t ndx); +- int (*event_add)(struct fdevents *ev, int fde_ndx, int fd, int events); +- int (*event_del)(struct fdevents *ev, int fde_ndx, int fd); +- int (*event_get_revent)(struct fdevents *ev, size_t ndx); +- int (*event_get_fd)(struct fdevents *ev, size_t ndx); - -+ - int (*event_next_fdndx)(struct fdevents *ev, int ndx); +- int (*event_next_fdndx)(struct fdevents *ev, int ndx); - ++ ++ int (*event_add)(struct fdevents *ev, iosocket *sock, int events); ++ int (*event_del)(struct fdevents *ev, iosocket *sock); ++ int (*get_revents)(struct fdevents *ev, size_t event_count, fdevent_revents *revents); + int (*poll)(struct fdevents *ev, int timeout_ms); - @@ -8633,8 +9027,64 @@ int (*fcntl_set)(struct fdevents *ev, int fd); } fdevents; +@@ -194,22 +204,44 @@ + int fdevent_reset(fdevents *ev); + void fdevent_free(fdevents *ev); + +-int fdevent_event_add(fdevents *ev, int *fde_ndx, int fd, int events); +-int fdevent_event_del(fdevents *ev, int *fde_ndx, int fd); +-int fdevent_event_get_revent(fdevents *ev, size_t ndx); +-int fdevent_event_get_fd(fdevents *ev, size_t ndx); +-fdevent_handler fdevent_get_handler(fdevents *ev, int fd); +-void * fdevent_get_context(fdevents *ev, int fd); ++/** ++ * call the plugin for the number of available events ++ */ ++int fdevent_poll(fdevents *ev, int timeout_ms); ++/** ++ * get all available events ++ */ ++int fdevent_get_revents(fdevents *ev, size_t event_count, fdevent_revents *revents); + +-int fdevent_event_next_fdndx(fdevents *ev, int ndx); ++/** ++ * add or remove a fd to the handled-pool ++ */ ++int fdevent_register(fdevents *ev, iosocket *sock, fdevent_handler handler, void *ctx); ++int fdevent_unregister(fdevents *ev, iosocket *sock); + +-int fdevent_poll(fdevents *ev, int timeout_ms); ++/** ++ * add a event to a registered fd ++ */ ++int fdevent_event_add(fdevents *ev, iosocket *sock, int events); ++int fdevent_event_del(fdevents *ev, iosocket *sock); ++ ++/** ++ * set non-blocking ++ */ ++int fdevent_fcntl_set(fdevents *ev, iosocket *sock); ++ ++fdevent_revents *fdevent_revents_init(void); ++void fdevent_revents_reset(fdevent_revents *revents); ++void fdevent_revents_add(fdevent_revents *revents, int fd, int events); ++void fdevent_revents_free(fdevent_revents *revents); + +-int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx); +-int fdevent_unregister(fdevents *ev, int fd); ++fdevent_revent *fdevent_revent_init(void); ++void fdevent_revent_free(fdevent_revent *revent); + +-int fdevent_fcntl_set(fdevents *ev, int fd); + ++/** ++ * plugin init ++ */ + int fdevent_select_init(fdevents *ev); + int fdevent_poll_init(fdevents *ev); + int fdevent_linux_rtsig_init(fdevents *ev); --- ../lighttpd-1.4.11/src/fdevent_freebsd_kqueue.c 2005-09-01 10:46:24.000000000 +0300 -+++ lighttpd-1.4.12/src/fdevent_freebsd_kqueue.c 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/fdevent_freebsd_kqueue.c 2006-07-16 00:26:03.000000000 +0300 @@ -1,6 +1,5 @@ #include @@ -8701,7 +9151,7 @@ } --- ../lighttpd-1.4.11/src/fdevent_linux_rtsig.c 2005-11-21 19:56:11.000000000 +0200 -+++ lighttpd-1.4.12/src/fdevent_linux_rtsig.c 2006-07-15 22:43:21.000000000 +0300 ++++ lighttpd-1.4.12/src/fdevent_linux_rtsig.c 2006-07-18 13:03:40.000000000 +0300 @@ -1,6 +1,5 @@ #include @@ -8709,39 +9159,49 @@ #include #include #include -@@ -14,6 +13,7 @@ +@@ -14,6 +13,8 @@ #include "fdevent.h" #include "settings.h" #include "buffer.h" +#include "sys-process.h" ++#include "log.h" #ifdef USE_LINUX_SIGIO static void fdevent_linux_rtsig_free(fdevents *ev) { -@@ -26,19 +26,19 @@ +@@ -24,21 +25,21 @@ + } - static int fdevent_linux_rtsig_event_del(fdevents *ev, int fde_ndx, int fd) { - if (fde_ndx < 0) return -1; + +-static int fdevent_linux_rtsig_event_del(fdevents *ev, int fde_ndx, int fd) { +- if (fde_ndx < 0) return -1; - +- if ((size_t)fde_ndx >= ev->used) { +- fprintf(stderr, "%s.%d: del! out of range %d %zu\n", __FILE__, __LINE__, fde_ndx, ev->used); ++static int fdevent_linux_rtsig_event_del(fdevents *ev, iosocket *sock) { ++ if (sock->fde_ndx < 0) return -1; + - if ((size_t)fde_ndx >= ev->used) { - fprintf(stderr, "%s.%d: del! out of range %d %zu\n", __FILE__, __LINE__, fde_ndx, ev->used); ++ if ((size_t)sock->fde_ndx >= ev->used) { ++ TRACE("del! out of range %d %zu\n", sock->fde_ndx, ev->used); SEGFAULT(); } - -+ - if (ev->pollfds[fde_ndx].fd == fd) { - size_t k = fde_ndx; +- if (ev->pollfds[fde_ndx].fd == fd) { +- size_t k = fde_ndx; - ++ ++ if (ev->pollfds[sock->fde_ndx].fd == sock->fd) { ++ size_t k = sock->fde_ndx; + ev->pollfds[k].fd = -1; - bitset_clear_bit(ev->sigbset, fd); +- bitset_clear_bit(ev->sigbset, fd); - ++ bitset_clear_bit(ev->sigbset, sock->fd); + if (ev->unused.size == 0) { ev->unused.size = 16; ev->unused.ptr = malloc(sizeof(*(ev->unused.ptr)) * ev->unused.size); -@@ -46,29 +46,29 @@ +@@ -46,53 +47,54 @@ ev->unused.size += 16; ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size); } @@ -8749,14 +9209,17 @@ + ev->unused.ptr[ev->unused.used++] = k; } else { - fprintf(stderr, "%s.%d: del! %d %d\n", __FILE__, __LINE__, ev->pollfds[fde_ndx].fd, fd); +- fprintf(stderr, "%s.%d: del! %d %d\n", __FILE__, __LINE__, ev->pollfds[fde_ndx].fd, fd); - ++ fprintf(stderr, "%s.%d: del! %d %d\n", __FILE__, __LINE__, ev->pollfds[sock->fde_ndx].fd, sock->fd); + SEGFAULT(); } - +- return -1; ++ sock->fde_ndx = -1; + - return -1; ++ return 0; } #if 0 @@ -8778,15 +9241,23 @@ return 0; } #endif -@@ -78,21 +78,21 @@ - if (fde_ndx != -1) { - if (ev->pollfds[fde_ndx].fd == fd) { - ev->pollfds[fde_ndx].events = events; + +-static int fdevent_linux_rtsig_event_add(fdevents *ev, int fde_ndx, int fd, int events) { ++static int fdevent_linux_rtsig_event_add(fdevents *ev, iosocket *sock, int events) { + /* known index */ +- if (fde_ndx != -1) { +- if (ev->pollfds[fde_ndx].fd == fd) { +- ev->pollfds[fde_ndx].events = events; - +- return fde_ndx; ++ if (sock->fde_ndx != -1) { ++ if (ev->pollfds[sock->fde_ndx].fd == sock->fd) { ++ ev->pollfds[sock->fde_ndx].events = events; + - return fde_ndx; ++ return sock->fde_ndx; } - fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, fde_ndx, ev->pollfds[fde_ndx].fd); +- fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, fde_ndx, ev->pollfds[fde_ndx].fd); ++ fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, sock->fde_ndx, ev->pollfds[sock->fde_ndx].fd); SEGFAULT(); } - @@ -8794,32 +9265,36 @@ if (ev->unused.used > 0) { int k = ev->unused.ptr[--ev->unused.used]; - +- ev->pollfds[k].fd = fd; + - ev->pollfds[k].fd = fd; ++ ev->pollfds[k].fd = sock->fd; ev->pollfds[k].events = events; - bitset_set_bit(ev->sigbset, fd); +- bitset_set_bit(ev->sigbset, fd); - ++ bitset_set_bit(ev->sigbset, sock->fd); + return k; } else { if (ev->size == 0) { -@@ -102,12 +102,12 @@ +@@ -102,12 +104,12 @@ ev->size += 16; ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size); } - +- ev->pollfds[ev->used].fd = fd; + - ev->pollfds[ev->used].fd = fd; ++ ev->pollfds[ev->used].fd = sock->fd; ev->pollfds[ev->used].events = events; - bitset_set_bit(ev->sigbset, fd); +- bitset_set_bit(ev->sigbset, fd); - ++ bitset_set_bit(ev->sigbset, sock->fd); + return ev->used++; } } -@@ -115,20 +115,20 @@ +@@ -115,20 +117,20 @@ static int fdevent_linux_rtsig_poll(fdevents *ev, int timeout_ms) { struct timespec ts; int r; @@ -8846,7 +9321,7 @@ } else if (r == SIGIO) { struct sigaction act; -@@ -140,7 +140,7 @@ +@@ -140,7 +142,7 @@ /* re-enable the signal queue */ act.sa_handler = SIG_DFL; sigaction(ev->signum, &act, NULL); @@ -8855,22 +9330,50 @@ ev->in_sigio = 0; r = poll(ev->pollfds, ev->used, timeout_ms); -@@ -162,12 +162,12 @@ - if (ev->siginfo.si_band == POLLERR) { - fprintf(stderr, "event: %d %02lx %02x %s\n", ev->siginfo.si_fd, ev->siginfo.si_band, errno, strerror(errno)); - } +@@ -156,97 +158,67 @@ + } + } + +-static int fdevent_linux_rtsig_event_get_revent(fdevents *ev, size_t ndx) { ++static int fdevent_linux_rtsig_get_revents(fdevents *ev, size_t event_count, fdevent_revents *revents) { + if (ev->in_sigio == 1) { +-# if 0 +- if (ev->siginfo.si_band == POLLERR) { +- fprintf(stderr, "event: %d %02lx %02x %s\n", ev->siginfo.si_fd, ev->siginfo.si_band, errno, strerror(errno)); +- } -# endif -+# endif - if (ndx != 0) { - fprintf(stderr, "+\n"); - return 0; - } +- if (ndx != 0) { +- fprintf(stderr, "+\n"); +- return 0; +- } - +- return ev->siginfo.si_band & 0x3f; ++ /* only one event */ + - return ev->siginfo.si_band & 0x3f; ++ fdevent_revents_add(revents, ev->siginfo.si_fd, ev->siginfo.si_band & 0x3f); } else { - if (ndx >= ev->used) { -@@ -188,13 +188,13 @@ +- if (ndx >= ev->used) { +- fprintf(stderr, "%s.%d: event: %zu %zu\n", __FILE__, __LINE__, ndx, ev->used); +- return 0; ++ size_t ndx; ++ ++ for (ndx = 0; ndx < ev->used; ndx++) { ++ if (ev->pollfds[ndx].revents) { ++ fdevent_revents_add(revents, ev->pollfds[ndx].fd, ev->pollfds[ndx].revents); ++ } + } +- return ev->pollfds[ndx].revents; + } +-} + +-static int fdevent_linux_rtsig_event_get_fd(fdevents *ev, size_t ndx) { +- if (ev->in_sigio == 1) { +- return ev->siginfo.si_fd; +- } else { +- return ev->pollfds[ndx].fd; +- } ++ return 0; + } static int fdevent_linux_rtsig_fcntl_set(fdevents *ev, int fd) { static pid_t pid = 0; @@ -8888,22 +9391,24 @@ return fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK | O_RDWR); } -@@ -205,12 +205,12 @@ - return -1; - } else { - size_t i; + +-static int fdevent_linux_rtsig_event_next_fdndx(fdevents *ev, int ndx) { +- if (ev->in_sigio == 1) { +- if (ndx < 0) return 0; +- return -1; +- } else { +- size_t i; - -+ - i = (ndx < 0) ? 0 : ndx + 1; - for (; i < ev->used; i++) { - if (ev->pollfds[i].revents) break; - } +- i = (ndx < 0) ? 0 : ndx + 1; +- for (; i < ev->used; i++) { +- if (ev->pollfds[i].revents) break; +- } - -+ - return i; - } - } -@@ -219,34 +219,34 @@ +- return i; +- } +-} +- + int fdevent_linux_rtsig_init(fdevents *ev) { ev->type = FDEVENT_HANDLER_LINUX_RTSIG; #define SET(x) \ ev->x = fdevent_linux_rtsig_##x; @@ -8916,12 +9421,13 @@ SET(event_del); SET(event_add); - +- SET(event_next_fdndx); + - SET(event_next_fdndx); SET(fcntl_set); - SET(event_get_fd); - SET(event_get_revent); +- SET(event_get_fd); +- SET(event_get_revent); - ++ SET(get_revents); + ev->signum = SIGRTMIN + 1; - @@ -8947,7 +9453,7 @@ } #else --- ../lighttpd-1.4.11/src/fdevent_linux_sysepoll.c 2005-09-30 20:29:27.000000000 +0300 -+++ lighttpd-1.4.12/src/fdevent_linux_sysepoll.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/fdevent_linux_sysepoll.c 2006-07-18 13:03:40.000000000 +0300 @@ -1,6 +1,5 @@ #include @@ -8955,32 +9461,39 @@ #include #include #include -@@ -12,6 +11,8 @@ +@@ -11,6 +10,9 @@ + #include "fdevent.h" #include "settings.h" #include "buffer.h" - -+#include "sys-files.h" ++#include "log.h" + ++#include "sys-files.h" + #ifdef USE_LINUX_EPOLL static void fdevent_linux_sysepoll_free(fdevents *ev) { - close(ev->epoll_fd); -@@ -20,36 +21,36 @@ +@@ -18,38 +20,40 @@ + free(ev->epoll_events); + } - static int fdevent_linux_sysepoll_event_del(fdevents *ev, int fde_ndx, int fd) { +-static int fdevent_linux_sysepoll_event_del(fdevents *ev, int fde_ndx, int fd) { ++static int fdevent_linux_sysepoll_event_del(fdevents *ev, iosocket *sock) { struct epoll_event ep; - -+ - if (fde_ndx < 0) return -1; +- if (fde_ndx < 0) return -1; - ++ ++ if (sock->fde_ndx < 0) return -1; + memset(&ep, 0, sizeof(ep)); - +- ep.data.fd = fd; + - ep.data.fd = fd; ++ ep.data.fd = sock->fd; ep.data.ptr = NULL; - +- if (0 != epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fd, &ep)) { + - if (0 != epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fd, &ep)) { ++ if (0 != epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, sock->fd, &ep)) { fprintf(stderr, "%s.%d: epoll_ctl failed: %s, dying\n", __FILE__, __LINE__, strerror(errno)); - + @@ -8991,18 +9504,23 @@ } - - +- return -1; + ++ sock->fde_ndx = -1; + - return -1; ++ return 0; } - static int fdevent_linux_sysepoll_event_add(fdevents *ev, int fde_ndx, int fd, int events) { +-static int fdevent_linux_sysepoll_event_add(fdevents *ev, int fde_ndx, int fd, int events) { ++static int fdevent_linux_sysepoll_event_add(fdevents *ev, iosocket *sock, int events) { struct epoll_event ep; int add = 0; - -+ - if (fde_ndx == -1) add = 1; +- if (fde_ndx == -1) add = 1; - ++ ++ /* a new fd */ ++ if (sock->fde_ndx == -1) add = 1; + memset(&ep, 0, sizeof(ep)); - @@ -9013,7 +9531,7 @@ if (events & FDEVENT_IN) ep.events |= EPOLLIN; if (events & FDEVENT_OUT) ep.events |= EPOLLOUT; -@@ -60,20 +61,20 @@ +@@ -60,73 +64,61 @@ * sent. * */ @@ -9023,10 +9541,12 @@ - + ep.data.ptr = NULL; - ep.data.fd = fd; +- ep.data.fd = fd; - +- if (0 != epoll_ctl(ev->epoll_fd, add ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd, &ep)) { ++ ep.data.fd = sock->fd; + - if (0 != epoll_ctl(ev->epoll_fd, add ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd, &ep)) { ++ if (0 != epoll_ctl(ev->epoll_fd, add ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, sock->fd, &ep)) { fprintf(stderr, "%s.%d: epoll_ctl failed: %s, dying\n", __FILE__, __LINE__, strerror(errno)); - + @@ -9036,49 +9556,65 @@ return 0; } - +- return fd; + - return fd; ++ sock->fde_ndx = sock->fd; ++ ++ return 0; } -@@ -83,14 +84,14 @@ + static int fdevent_linux_sysepoll_poll(fdevents *ev, int timeout_ms) { + return epoll_wait(ev->epoll_fd, ev->epoll_events, ev->maxfds, timeout_ms); + } - static int fdevent_linux_sysepoll_event_get_revent(fdevents *ev, size_t ndx) { - int events = 0, e; +-static int fdevent_linux_sysepoll_event_get_revent(fdevents *ev, size_t ndx) { +- int events = 0, e; - -+ - e = ev->epoll_events[ndx].events; - if (e & EPOLLIN) events |= FDEVENT_IN; - if (e & EPOLLOUT) events |= FDEVENT_OUT; - if (e & EPOLLERR) events |= FDEVENT_ERR; - if (e & EPOLLHUP) events |= FDEVENT_HUP; - if (e & EPOLLPRI) events |= FDEVENT_PRI; +- e = ev->epoll_events[ndx].events; +- if (e & EPOLLIN) events |= FDEVENT_IN; +- if (e & EPOLLOUT) events |= FDEVENT_OUT; +- if (e & EPOLLERR) events |= FDEVENT_ERR; +- if (e & EPOLLHUP) events |= FDEVENT_HUP; +- if (e & EPOLLPRI) events |= FDEVENT_PRI; - -+ - return e; - } - -@@ -98,17 +99,17 @@ - # if 0 - fprintf(stderr, "%s.%d: %d, %d\n", __FILE__, __LINE__, ndx, ev->epoll_events[ndx].data.fd); - # endif +- return e; +-} +- +-static int fdevent_linux_sysepoll_event_get_fd(fdevents *ev, size_t ndx) { +-# if 0 +- fprintf(stderr, "%s.%d: %d, %d\n", __FILE__, __LINE__, ndx, ev->epoll_events[ndx].data.fd); +-# endif - -+ - return ev->epoll_events[ndx].data.fd; - } - - static int fdevent_linux_sysepoll_event_next_fdndx(fdevents *ev, int ndx) { - size_t i; +- return ev->epoll_events[ndx].data.fd; +-} +- +-static int fdevent_linux_sysepoll_event_next_fdndx(fdevents *ev, int ndx) { +- size_t i; - +- UNUSED(ev); ++static int fdevent_linux_sysepoll_get_revents(fdevents *ev, size_t event_count, fdevent_revents *revents) { ++ size_t ndx; + - UNUSED(ev); ++ for (ndx = 0; ndx < event_count; ndx++) { ++ int events = 0, e; ++ ++ e = ev->epoll_events[ndx].events; ++ if (e & EPOLLIN) events |= FDEVENT_IN; ++ if (e & EPOLLOUT) events |= FDEVENT_OUT; ++ if (e & EPOLLERR) events |= FDEVENT_ERR; ++ if (e & EPOLLHUP) events |= FDEVENT_HUP; ++ if (e & EPOLLPRI) events |= FDEVENT_PRI; - i = (ndx < 0) ? 0 : ndx + 1; +- i = (ndx < 0) ? 0 : ndx + 1; - +- return i; ++ fdevent_revents_add(revents, ev->epoll_events[ndx].data.fd, e); ++ } + - return i; ++ return 0; } -@@ -116,17 +117,17 @@ + int fdevent_linux_sysepoll_init(fdevents *ev) { ev->type = FDEVENT_HANDLER_LINUX_SYSEPOLL; #define SET(x) \ ev->x = fdevent_linux_sysepoll_##x; @@ -9091,16 +9627,17 @@ SET(event_del); SET(event_add); - -+ - SET(event_next_fdndx); - SET(event_get_fd); - SET(event_get_revent); +- SET(event_next_fdndx); +- SET(event_get_fd); +- SET(event_get_revent); - ++ ++ SET(get_revents); + if (-1 == (ev->epoll_fd = epoll_create(ev->maxfds))) { fprintf(stderr, "%s.%d: epoll_create failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n", __FILE__, __LINE__, strerror(errno)); -@@ -154,7 +155,7 @@ +@@ -154,7 +146,7 @@ fprintf(stderr, "%s.%d: linux-sysepoll not supported, try to set server.event-handler = \"poll\" or \"select\"\n", __FILE__, __LINE__); @@ -9110,7 +9647,7 @@ } #endif --- ../lighttpd-1.4.11/src/fdevent_poll.c 2005-11-18 13:59:16.000000000 +0200 -+++ lighttpd-1.4.12/src/fdevent_poll.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/fdevent_poll.c 2006-07-18 13:03:40.000000000 +0300 @@ -1,6 +1,5 @@ #include @@ -9118,21 +9655,37 @@ #include #include #include -@@ -20,19 +19,19 @@ +@@ -11,6 +10,7 @@ + #include "fdevent.h" + #include "settings.h" + #include "buffer.h" ++#include "log.h" - static int fdevent_poll_event_del(fdevents *ev, int fde_ndx, int fd) { - if (fde_ndx < 0) return -1; + #ifdef USE_POLL + static void fdevent_poll_free(fdevents *ev) { +@@ -18,21 +18,21 @@ + if (ev->unused.ptr) free(ev->unused.ptr); + } + +-static int fdevent_poll_event_del(fdevents *ev, int fde_ndx, int fd) { +- if (fde_ndx < 0) return -1; - +- if ((size_t)fde_ndx >= ev->used) { +- fprintf(stderr, "%s.%d: del! out of range %d %zd\n", __FILE__, __LINE__, fde_ndx, ev->used); ++static int fdevent_poll_event_del(fdevents *ev, iosocket *sock) { ++ if (sock->fde_ndx < 0) return -1; + - if ((size_t)fde_ndx >= ev->used) { - fprintf(stderr, "%s.%d: del! out of range %d %zd\n", __FILE__, __LINE__, fde_ndx, ev->used); ++ if ((size_t)sock->fde_ndx >= ev->used) { ++ fprintf(stderr, "%s.%d: del! out of range %d %zd\n", __FILE__, __LINE__, sock->fde_ndx, ev->used); SEGFAULT(); } - -+ - if (ev->pollfds[fde_ndx].fd == fd) { - size_t k = fde_ndx; +- if (ev->pollfds[fde_ndx].fd == fd) { +- size_t k = fde_ndx; - ++ ++ if (ev->pollfds[sock->fde_ndx].fd == sock->fd) { ++ size_t k = sock->fde_ndx; + ev->pollfds[k].fd = -1; /* ev->pollfds[k].events = 0; */ @@ -9142,7 +9695,7 @@ if (ev->unused.size == 0) { ev->unused.size = 16; ev->unused.ptr = malloc(sizeof(*(ev->unused.ptr)) * ev->unused.size); -@@ -40,47 +39,47 @@ +@@ -40,48 +40,51 @@ ev->unused.size += 16; ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size); } @@ -9153,8 +9706,11 @@ SEGFAULT(); } - +- return -1; + - return -1; ++ sock->fde_ndx = -1; ++ ++ return 0; } #if 0 @@ -9173,18 +9729,25 @@ } #endif - static int fdevent_poll_event_add(fdevents *ev, int fde_ndx, int fd, int events) { - /* known index */ +-static int fdevent_poll_event_add(fdevents *ev, int fde_ndx, int fd, int events) { +- /* known index */ - -+ - if (fde_ndx != -1) { - if (ev->pollfds[fde_ndx].fd == fd) { - ev->pollfds[fde_ndx].events = events; +- if (fde_ndx != -1) { +- if (ev->pollfds[fde_ndx].fd == fd) { +- ev->pollfds[fde_ndx].events = events; - +- return fde_ndx; ++static int fdevent_poll_event_add(fdevents *ev, iosocket *sock, int events) { ++ if (sock->fde_ndx != -1) { ++ /* this fd was already added, just change the requested events */ ++ ++ if (ev->pollfds[sock->fde_ndx].fd == sock->fd) { ++ ev->pollfds[sock->fde_ndx].events = events; + - return fde_ndx; ++ return sock->fde_ndx; } - fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, fde_ndx, ev->pollfds[fde_ndx].fd); +- fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, fde_ndx, ev->pollfds[fde_ndx].fd); ++ fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, sock->fde_ndx, ev->pollfds[sock->fde_ndx].fd); SEGFAULT(); } - @@ -9192,68 +9755,98 @@ if (ev->unused.used > 0) { int k = ev->unused.ptr[--ev->unused.used]; - +- ev->pollfds[k].fd = fd; + - ev->pollfds[k].fd = fd; ++ ev->pollfds[k].fd = sock->fd; ev->pollfds[k].events = events; - +- return k; ++ ++ sock->fde_ndx = k; + - return k; } else { if (ev->size == 0) { -@@ -90,10 +89,10 @@ + ev->size = 16; +@@ -90,12 +93,13 @@ ev->size += 16; ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size); } - +- ev->pollfds[ev->used].fd = fd; + - ev->pollfds[ev->used].fd = fd; ++ ev->pollfds[ev->used].fd = sock->fd; ev->pollfds[ev->used].events = events; - +- return ev->used++; + - return ev->used++; ++ sock->fde_ndx = ev->used++; } ++ return 0; } -@@ -109,12 +108,12 @@ - int r, poll_r; - if (ndx >= ev->used) { - fprintf(stderr, "%s.%d: dying because: event: %zd >= %zd\n", __FILE__, __LINE__, ndx, ev->used); + + static int fdevent_poll_poll(fdevents *ev, int timeout_ms) { +@@ -105,71 +109,38 @@ + return poll(ev->pollfds, ev->used, timeout_ms); + } + +-static int fdevent_poll_event_get_revent(fdevents *ev, size_t ndx) { +- int r, poll_r; +- if (ndx >= ev->used) { +- fprintf(stderr, "%s.%d: dying because: event: %zd >= %zd\n", __FILE__, __LINE__, ndx, ev->used); - -+ - SEGFAULT(); +- SEGFAULT(); - -+ - return 0; - } -- -+ - if (ev->pollfds[ndx].revents & POLLNVAL) { - /* should never happen */ - SEGFAULT(); -@@ -131,7 +130,7 @@ - if (poll_r & POLLHUP) r |= FDEVENT_HUP; - if (poll_r & POLLNVAL) r |= FDEVENT_NVAL; - if (poll_r & POLLPRI) r |= FDEVENT_PRI; +- return 0; +- } - -+ - return ev->pollfds[ndx].revents; - } - -@@ -141,12 +140,12 @@ +- if (ev->pollfds[ndx].revents & POLLNVAL) { +- /* should never happen */ +- SEGFAULT(); +- } ++static int fdevent_poll_get_revents(fdevents *ev, size_t event_count, fdevent_revents *revents) { ++ size_t ndx; + +- r = 0; +- poll_r = ev->pollfds[ndx].revents; ++ for (ndx = 0; ndx < ev->used; ndx++) { ++ if (ev->pollfds[ndx].revents) { ++ if (ev->pollfds[ndx].revents & POLLNVAL) { ++ /* should never happen */ ++ SEGFAULT(); ++ } - static int fdevent_poll_event_next_fdndx(fdevents *ev, int ndx) { - size_t i; +- /* map POLL* to FDEVEN_* */ +- +- if (poll_r & POLLIN) r |= FDEVENT_IN; +- if (poll_r & POLLOUT) r |= FDEVENT_OUT; +- if (poll_r & POLLERR) r |= FDEVENT_ERR; +- if (poll_r & POLLHUP) r |= FDEVENT_HUP; +- if (poll_r & POLLNVAL) r |= FDEVENT_NVAL; +- if (poll_r & POLLPRI) r |= FDEVENT_PRI; +- +- return ev->pollfds[ndx].revents; +-} +- +-static int fdevent_poll_event_get_fd(fdevents *ev, size_t ndx) { +- return ev->pollfds[ndx].fd; +-} +- +-static int fdevent_poll_event_next_fdndx(fdevents *ev, int ndx) { +- size_t i; - -+ - i = (ndx < 0) ? 0 : ndx + 1; - for (; i < ev->used; i++) { - if (ev->pollfds[i].revents) break; +- i = (ndx < 0) ? 0 : ndx + 1; +- for (; i < ev->used; i++) { +- if (ev->pollfds[i].revents) break; ++ fdevent_revents_add(revents, ev->pollfds[ndx].fd, ev->pollfds[ndx].revents); ++ } } - +- return i; + - return i; ++ return 0; } -@@ -154,17 +153,17 @@ + int fdevent_poll_init(fdevents *ev) { ev->type = FDEVENT_HANDLER_POLL; #define SET(x) \ ev->x = fdevent_poll_##x; @@ -9266,17 +9859,23 @@ SET(event_del); SET(event_add); - -+ - SET(event_next_fdndx); - SET(event_get_fd); - SET(event_get_revent); +- SET(event_next_fdndx); +- SET(event_get_fd); +- SET(event_get_revent); - -+ - return 0; - } +- return 0; +-} +- ++ SET(get_revents); + ++ return 0; ++} + + #else + int fdevent_poll_init(fdevents *ev) { --- ../lighttpd-1.4.11/src/fdevent_select.c 2005-08-31 11:12:46.000000000 +0300 -+++ lighttpd-1.4.12/src/fdevent_select.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/fdevent_select.c 2006-07-18 13:03:40.000000000 +0300 @@ -1,18 +1,19 @@ -#include #include @@ -9299,26 +9898,65 @@ #ifdef USE_SELECT static int fdevent_select_reset(fdevents *ev) { -@@ -38,7 +39,9 @@ - UNUSED(fde_ndx); +@@ -24,101 +25,98 @@ + return 0; + } + +-static int fdevent_select_event_del(fdevents *ev, int fde_ndx, int fd) { +- if (fde_ndx < 0) return -1; ++static int fdevent_select_event_del(fdevents *ev, iosocket *sock) { ++ if (sock->fde_ndx < 0) return -1; +- FD_CLR(fd, &(ev->select_set_read)); +- FD_CLR(fd, &(ev->select_set_write)); +- FD_CLR(fd, &(ev->select_set_error)); ++ FD_CLR(sock->fd, &(ev->select_set_read)); ++ FD_CLR(sock->fd, &(ev->select_set_write)); ++ FD_CLR(sock->fd, &(ev->select_set_error)); + +- return -1; +-} ++ /* mark the fdevent as deleted */ ++ sock->fde_ndx = -1; + +-static int fdevent_select_event_add(fdevents *ev, int fde_ndx, int fd, int events) { +- UNUSED(fde_ndx); ++ return 0; ++} + ++static int fdevent_select_event_add(fdevents *ev, iosocket *sock, int events) { /* we should be protected by max-fds, but you never know */ +- assert(fd < FD_SETSIZE); +#ifndef _WIN32 - assert(fd < FD_SETSIZE); ++ assert(sock->fd < FD_SETSIZE); +#endif if (events & FDEVENT_IN) { - FD_SET(fd, &(ev->select_set_read)); -@@ -49,28 +52,28 @@ - FD_SET(fd, &(ev->select_set_write)); +- FD_SET(fd, &(ev->select_set_read)); +- FD_CLR(fd, &(ev->select_set_write)); ++ FD_SET(sock->fd, &(ev->select_set_read)); ++ FD_CLR(sock->fd, &(ev->select_set_write)); } - FD_SET(fd, &(ev->select_set_error)); + if (events & FDEVENT_OUT) { +- FD_CLR(fd, &(ev->select_set_read)); +- FD_SET(fd, &(ev->select_set_write)); ++ FD_CLR(sock->fd, &(ev->select_set_read)); ++ FD_SET(sock->fd, &(ev->select_set_write)); + } +- FD_SET(fd, &(ev->select_set_error)); - -+ - if (fd > ev->select_max_fd) ev->select_max_fd = fd; +- if (fd > ev->select_max_fd) ev->select_max_fd = fd; - +- return fd; ++ FD_SET(sock->fd, &(ev->select_set_error)); + - return fd; ++ /* we need this for the poll */ ++ if (sock->fd > ev->select_max_fd) ev->select_max_fd = sock->fd; ++ ++ /* mark fd as added */ ++ sock->fde_ndx = sock->fd; ++ ++ return 0; } static int fdevent_select_poll(fdevents *ev, int timeout_ms) { @@ -9337,42 +9975,67 @@ return select(ev->select_max_fd + 1, &(ev->select_read), &(ev->select_write), &(ev->select_error), &tv); } - static int fdevent_select_event_get_revent(fdevents *ev, size_t ndx) { - int revents = 0; +-static int fdevent_select_event_get_revent(fdevents *ev, size_t ndx) { +- int revents = 0; - +- if (FD_ISSET(ndx, &(ev->select_read))) { +- revents |= FDEVENT_IN; ++/** ++ * scan the fdset for events ++ */ ++static int fdevent_select_get_revents(fdevents *ev, size_t event_count, fdevent_revents *revents) { + - if (FD_ISSET(ndx, &(ev->select_read))) { - revents |= FDEVENT_IN; - } -@@ -80,7 +83,7 @@ - if (FD_ISSET(ndx, &(ev->select_error))) { - revents |= FDEVENT_ERR; ++ int ndx = 0; ++ ++ for (ndx = 0; ndx < ev->select_max_fd; ndx++) { ++ int events = 0; ++ ++ if (FD_ISSET(ndx, &(ev->select_read))) { ++ events |= FDEVENT_IN; ++ } ++ if (FD_ISSET(ndx, &(ev->select_write))) { ++ events |= FDEVENT_OUT; ++ } ++ if (FD_ISSET(ndx, &(ev->select_error))) { ++ events |= FDEVENT_ERR; ++ } ++ ++ if (events) { ++ fdevent_revents_add(revents, ndx, events); ++ } } +- if (FD_ISSET(ndx, &(ev->select_write))) { +- revents |= FDEVENT_OUT; +- } +- if (FD_ISSET(ndx, &(ev->select_error))) { +- revents |= FDEVENT_ERR; +- } - -+ - return revents; - } - -@@ -92,15 +95,15 @@ +- return revents; +-} +- +-static int fdevent_select_event_get_fd(fdevents *ev, size_t ndx) { +- UNUSED(ev); +- +- return ndx; +-} - static int fdevent_select_event_next_fdndx(fdevents *ev, int ndx) { - int i; +-static int fdevent_select_event_next_fdndx(fdevents *ev, int ndx) { +- int i; - -+ - i = (ndx < 0) ? 0 : ndx + 1; +- i = (ndx < 0) ? 0 : ndx + 1; - -+ - for (; i < ev->select_max_fd + 1; i++) { - if (FD_ISSET(i, &(ev->select_read))) break; - if (FD_ISSET(i, &(ev->select_write))) break; - if (FD_ISSET(i, &(ev->select_error))) break; - } +- for (; i < ev->select_max_fd + 1; i++) { +- if (FD_ISSET(i, &(ev->select_read))) break; +- if (FD_ISSET(i, &(ev->select_write))) break; +- if (FD_ISSET(i, &(ev->select_error))) break; +- } - -+ - return i; +- return i; ++ return 0; } -@@ -108,17 +111,17 @@ + int fdevent_select_init(fdevents *ev) { ev->type = FDEVENT_HANDLER_SELECT; #define SET(x) \ ev->x = fdevent_select_##x; @@ -9385,17 +10048,18 @@ SET(event_del); SET(event_add); - -+ - SET(event_next_fdndx); - SET(event_get_fd); - SET(event_get_revent); +- SET(event_next_fdndx); +- SET(event_get_fd); +- SET(event_get_revent); - ++ ++ SET(get_revents); + return 0; } --- ../lighttpd-1.4.11/src/fdevent_solaris_devpoll.c 2005-09-01 10:45:26.000000000 +0300 -+++ lighttpd-1.4.12/src/fdevent_solaris_devpoll.c 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/fdevent_solaris_devpoll.c 2006-07-16 00:26:03.000000000 +0300 @@ -1,6 +1,5 @@ #include @@ -9526,7 +10190,7 @@ } #endif --- ../lighttpd-1.4.11/src/http-header-glue.c 2006-02-08 15:31:36.000000000 +0200 -+++ lighttpd-1.4.12/src/http-header-glue.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/http-header-glue.c 2006-07-18 13:03:40.000000000 +0300 @@ -45,20 +45,20 @@ # ifdef HAVE_STRUCT_SOCKADDR_STORAGE static size_t get_sa_len(const struct sockaddr *addr) { @@ -9609,8 +10273,9 @@ + our_addr_len = sizeof(our_addr); - +- if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) { + - if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) { ++ if (-1 == getsockname(con->sock->fd, &(our_addr.plain), &our_addr_len)) { con->http_status = 500; - + @@ -9861,7 +10526,7 @@ } --- ../lighttpd-1.4.11/src/http_auth.c 2006-02-01 13:02:52.000000000 +0200 -+++ lighttpd-1.4.12/src/http_auth.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/http_auth.c 2006-07-18 13:03:40.000000000 +0300 @@ -22,7 +22,6 @@ #include #include @@ -10189,7 +10854,8 @@ - + /* if we get here, the user we got a authed user */ - if (0 == strcmp(require->value->ptr, "valid-user")) { +- if (0 == strcmp(require->value->ptr, "valid-user")) { ++ if (buffer_is_equal_string(require->value, CONST_STR_LEN("valid-user"))) { return 0; } - @@ -10332,8 +10998,9 @@ + CvtHex(HA1, a1); - +- if (0 == strcmp(password->ptr, a1)) { + - if (0 == strcmp(password->ptr, a1)) { ++ if (buffer_is_equal_string(password, a1, strlen(a1))) { return 0; } - } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) { @@ -10365,7 +11032,7 @@ if (NULL == (dollar = strchr(password->ptr + 3, '$'))) { fprintf(stderr, "%s.%d\n", __FILE__, __LINE__); return -1; -@@ -495,7 +485,7 @@ +@@ -495,48 +485,21 @@ strncpy(salt, password->ptr, salt_len); salt[salt_len] = '\0'; @@ -10373,20 +11040,18 @@ + crypted = crypt(pw, salt); - if (0 == strcmp(password->ptr, crypted)) { -@@ -503,40 +493,13 @@ +- if (0 == strcmp(password->ptr, crypted)) { ++ if (buffer_is_equal_string(password, crypted, strlen(crypted))) { + return 0; } else { fprintf(stderr, "%s.%d\n", __FILE__, __LINE__); } - -#endif - } else if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) { -+ -+#endif -+ } else if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) { - if (0 == strcmp(password->ptr, pw)) { - return 0; - } +- if (0 == strcmp(password->ptr, pw)) { +- return 0; +- } - } else if (p->conf.auth_backend == AUTH_BACKEND_PAM) { -#ifdef USE_PAM - pam_handle_t *pamh=NULL; @@ -10409,10 +11074,14 @@ - - if (retval == PAM_SUCCESS) { - log_error_write(srv, __FILE__, __LINE__, "s", "Authenticated"); -- return 0; ++ ++#endif ++ } else if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) { ++ if (buffer_is_equal_string(password, pw, strlen(pw))) { + return 0; - } else { - log_error_write(srv, __FILE__, __LINE__, "s", "Not Authenticated"); -- } + } -#endif - } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) { + } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) { @@ -10939,7 +11608,7 @@ return 0; } --- ../lighttpd-1.4.11/src/http_auth.h 2005-08-14 17:12:31.000000000 +0300 -+++ lighttpd-1.4.12/src/http_auth.h 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/http_auth.h 2006-07-16 00:26:04.000000000 +0300 @@ -9,22 +9,26 @@ # include #endif @@ -11014,7 +11683,7 @@ } mod_auth_plugin_data; --- ../lighttpd-1.4.11/src/http_auth_digest.h 2006-01-05 00:54:01.000000000 +0200 -+++ lighttpd-1.4.12/src/http_auth_digest.h 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/http_auth_digest.h 2006-07-16 00:26:04.000000000 +0300 @@ -12,7 +12,7 @@ #ifdef USE_OPENSSL #define IN const @@ -11025,7 +11694,7 @@ #define OUT --- ../lighttpd-1.4.11/src/http_chunk.c 2005-08-11 01:26:50.000000000 +0300 -+++ lighttpd-1.4.12/src/http_chunk.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/http_chunk.c 2006-07-16 00:26:04.000000000 +0300 @@ -1,7 +1,7 @@ /** * the HTTP chunk-API @@ -11182,13 +11851,14 @@ return chunkqueue_length(con->write_queue); } --- ../lighttpd-1.4.11/src/http_resp.c 1970-01-01 03:00:00.000000000 +0300 -+++ lighttpd-1.4.12/src/http_resp.c 2006-07-15 22:43:21.000000000 +0300 -@@ -0,0 +1,274 @@ ++++ lighttpd-1.4.12/src/http_resp.c 2006-07-18 13:03:40.000000000 +0300 +@@ -0,0 +1,277 @@ +#include +#include +#include +#include + ++#include "log.h" +#include "http_resp.h" +#include "http_resp_parser.h" + @@ -11422,19 +12092,21 @@ + if (context.ok == 0) { + ret = PARSE_ERROR; + -+ fprintf(stderr, "%s.%d: parsing failed at: ...%20s\r\n", -+ __FILE__, __LINE__, t.c->mem->ptr + t.offset); ++ if (!buffer_is_empty(context.errmsg)) { ++ TRACE("parsing failed: %s", BUF_STR(context.errmsg)); ++ } else { ++ TRACE("%s", "parsing failed ..."); ++ } + } + + http_resp_parser(pParser, 0, token, &context); -+ http_resp_parserFree(pParser, free ); ++ http_resp_parserFree(pParser, free); + + if (context.ok == 0) { + /* we are missing the some tokens */ + + if (!buffer_is_empty(context.errmsg)) { -+ fprintf(stderr, "%s.%d: hmm, %20s\r\n", -+ __FILE__, __LINE__, context.errmsg->ptr); ++ TRACE("parsing failed: %s", BUF_STR(context.errmsg)); + } + + if (ret == PARSE_UNSET) { @@ -11459,7 +12131,7 @@ +} + --- ../lighttpd-1.4.11/src/http_resp.h 1970-01-01 03:00:00.000000000 +0300 -+++ lighttpd-1.4.12/src/http_resp.h 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/http_resp.h 2006-07-16 00:26:04.000000000 +0300 @@ -0,0 +1,34 @@ +#ifndef _HTTP_RESP_H_ +#define _HTTP_RESP_H_ @@ -11496,8 +12168,8 @@ + +#endif --- ../lighttpd-1.4.11/src/http_resp_parser.c 1970-01-01 03:00:00.000000000 +0300 -+++ lighttpd-1.4.12/src/http_resp_parser.c 2006-07-15 22:44:07.000000000 +0300 -@@ -0,0 +1,895 @@ ++++ lighttpd-1.4.12/src/http_resp_parser.c 2006-07-18 13:03:52.000000000 +0300 +@@ -0,0 +1,901 @@ +/* Driver template for the LEMON parser generator. +** The author disclaims copyright to this source code. +*/ @@ -11511,8 +12183,9 @@ +#include "http_resp.h" +#include "keyvalue.h" +#include "array.h" ++#include "log.h" + -+#line 16 "http_resp_parser.c" ++#line 17 "http_resp_parser.c" +/* Next is all token values, in a form suitable for use by makeheaders. +** This section will be null unless lemon is run with the -m switch. +*/ @@ -11821,9 +12494,14 @@ + case 1: + case 2: + case 3: -+#line 23 "./http_resp_parser.y" ++#line 25 "./http_resp_parser.y" ++{ buffer_free((yypminor->yy0)); } ++#line 327 "http_resp_parser.c" ++ break; ++ case 10: ++#line 24 "./http_resp_parser.y" +{ buffer_free((yypminor->yy0)); } -+#line 326 "http_resp_parser.c" ++#line 332 "http_resp_parser.c" + break; + default: break; /* If no destructor action specified: do nothing */ + } @@ -12045,7 +12723,7 @@ + ** break; + */ + case 0: -+#line 26 "./http_resp_parser.y" ++#line 28 "./http_resp_parser.y" +{ + http_resp *resp = ctx->resp; + data_string *ds; @@ -12073,30 +12751,29 @@ + + yymsp[-1].minor.yy12 = NULL; +} -+#line 576 "http_resp_parser.c" ++#line 582 "http_resp_parser.c" + yy_destructor(1,&yymsp[0].minor); + break; + case 1: -+#line 54 "./http_resp_parser.y" ++#line 56 "./http_resp_parser.y" +{ + http_resp *resp = ctx->resp; + + resp->status = yymsp[-4].minor.yy20; + resp->protocol = yymsp[-5].minor.yy20; + buffer_copy_string_buffer(resp->reason, yymsp[-3].minor.yy0); -+ ++ buffer_free(yymsp[-3].minor.yy0); ++ + array_free(resp->headers); + + resp->headers = yymsp[-1].minor.yy12; -+ -+ yymsp[-1].minor.yy12 = NULL; +} -+#line 594 "http_resp_parser.c" ++#line 599 "http_resp_parser.c" + yy_destructor(1,&yymsp[-2].minor); + yy_destructor(1,&yymsp[0].minor); + break; + case 2: -+#line 68 "./http_resp_parser.y" ++#line 69 "./http_resp_parser.y" +{ + if (buffer_is_equal_string(yymsp[0].minor.yy0, CONST_STR_LEN("HTTP/1.0"))) { + yygotominor.yy20 = HTTP_VERSION_1_0; @@ -12108,54 +12785,53 @@ + + ctx->ok = 0; + } ++ buffer_free(yymsp[0].minor.yy0); +} -+#line 612 "http_resp_parser.c" ++#line 618 "http_resp_parser.c" + break; + case 3: -+#line 81 "./http_resp_parser.y" ++#line 83 "./http_resp_parser.y" +{ + char *err; + yygotominor.yy20 = strtol(yymsp[0].minor.yy0->ptr, &err, 10); + + if (*err != '\0') { -+ buffer_copy_string(ctx->errmsg, "expected a number: "); ++ buffer_copy_string(ctx->errmsg, "expected a number, got: "); + buffer_append_string_buffer(ctx->errmsg, yymsp[0].minor.yy0); + + ctx->ok = 0; + } ++ buffer_free(yymsp[0].minor.yy0); +} -+#line 627 "http_resp_parser.c" ++#line 634 "http_resp_parser.c" + break; + case 4: -+#line 93 "./http_resp_parser.y" ++#line 96 "./http_resp_parser.y" +{ + yygotominor.yy0 = yymsp[0].minor.yy0; -+ yymsp[0].minor.yy0 = NULL; +} -+#line 635 "http_resp_parser.c" ++#line 641 "http_resp_parser.c" + break; + case 5: -+#line 98 "./http_resp_parser.y" ++#line 100 "./http_resp_parser.y" +{ + yygotominor.yy0 = yymsp[-1].minor.yy0; + + buffer_append_string(yygotominor.yy0, " "); + buffer_append_string_buffer(yygotominor.yy0, yymsp[0].minor.yy0); -+ -+ yymsp[-1].minor.yy0 = NULL; ++ ++ buffer_free(yymsp[0].minor.yy0); +} -+#line 647 "http_resp_parser.c" ++#line 653 "http_resp_parser.c" + break; + case 6: -+#line 107 "./http_resp_parser.y" ++#line 109 "./http_resp_parser.y" +{ + yygotominor.yy12 = yymsp[-1].minor.yy12; + + array_insert_unique(yygotominor.yy12, (data_unset *)yymsp[0].minor.yy9); -+ -+ yymsp[-1].minor.yy12 = NULL; +} -+#line 658 "http_resp_parser.c" ++#line 662 "http_resp_parser.c" + break; + case 7: +#line 115 "./http_resp_parser.y" @@ -12164,7 +12840,7 @@ + + array_insert_unique(yygotominor.yy12, (data_unset *)yymsp[0].minor.yy9); +} -+#line 667 "http_resp_parser.c" ++#line 671 "http_resp_parser.c" + break; + case 8: +#line 120 "./http_resp_parser.y" @@ -12173,8 +12849,10 @@ + + buffer_copy_string_buffer(yygotominor.yy9->key, yymsp[-3].minor.yy0); + buffer_copy_string_buffer(yygotominor.yy9->value, yymsp[-1].minor.yy0); ++ buffer_free(yymsp[-3].minor.yy0); ++ buffer_free(yymsp[-1].minor.yy0); +} -+#line 677 "http_resp_parser.c" ++#line 683 "http_resp_parser.c" + yy_destructor(3,&yymsp[-2].minor); + yy_destructor(1,&yymsp[0].minor); + break; @@ -12205,11 +12883,11 @@ + while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); + /* Here code is inserted which will be executed whenever the + ** parser fails */ -+#line 14 "./http_resp_parser.y" ++#line 15 "./http_resp_parser.y" + + ctx->ok = 0; + -+#line 712 "http_resp_parser.c" ++#line 718 "http_resp_parser.c" + http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */ +} + @@ -12394,14 +13072,14 @@ + return; +} --- ../lighttpd-1.4.11/src/http_resp_parser.h 1970-01-01 03:00:00.000000000 +0300 -+++ lighttpd-1.4.12/src/http_resp_parser.h 2006-07-15 22:44:07.000000000 +0300 ++++ lighttpd-1.4.12/src/http_resp_parser.h 2006-07-18 13:03:52.000000000 +0300 @@ -0,0 +1,3 @@ +#define TK_CRLF 1 +#define TK_STRING 2 +#define TK_COLON 3 --- ../lighttpd-1.4.11/src/http_resp_parser.y 1970-01-01 03:00:00.000000000 +0300 -+++ lighttpd-1.4.12/src/http_resp_parser.y 2006-07-15 22:43:21.000000000 +0300 -@@ -0,0 +1,125 @@ ++++ lighttpd-1.4.12/src/http_resp_parser.y 2006-07-18 13:03:40.000000000 +0300 +@@ -0,0 +1,127 @@ +%token_prefix TK_ +%token_type {buffer *} +%extra_argument {http_resp_ctx_t *ctx} @@ -12413,6 +13091,7 @@ +#include "http_resp.h" +#include "keyvalue.h" +#include "array.h" ++#include "log.h" +} + +%parse_failure { @@ -12424,6 +13103,7 @@ +%type number { int } +%type headers { array * } +%type header { data_string * } ++%destructor reason { buffer_free($$); } +%token_destructor { buffer_free($$); } + +/* just headers + Status: ... */ @@ -12461,12 +13141,11 @@ + resp->status = C; + resp->protocol = B; + buffer_copy_string_buffer(resp->reason, D); -+ ++ buffer_free(D); ++ + array_free(resp->headers); + + resp->headers = HDR; -+ -+ HDR = NULL; +} + +protocol(A) ::= STRING(B). { @@ -12480,6 +13159,7 @@ + + ctx->ok = 0; + } ++ buffer_free(B); +} + +number(A) ::= STRING(B). { @@ -12487,16 +13167,16 @@ + A = strtol(B->ptr, &err, 10); + + if (*err != '\0') { -+ buffer_copy_string(ctx->errmsg, "expected a number: "); ++ buffer_copy_string(ctx->errmsg, "expected a number, got: "); + buffer_append_string_buffer(ctx->errmsg, B); + + ctx->ok = 0; + } ++ buffer_free(B); +} + +reason(A) ::= STRING(B). { + A = B; -+ B = NULL; +} + +reason(A) ::= reason(C) STRING(B). { @@ -12504,16 +13184,14 @@ + + buffer_append_string(A, " "); + buffer_append_string_buffer(A, B); -+ -+ C = NULL; ++ ++ buffer_free(B); +} + +headers(HDRS) ::= headers(SRC) header(HDR). { + HDRS = SRC; + + array_insert_unique(HDRS, (data_unset *)HDR); -+ -+ SRC = NULL; +} + +headers(HDRS) ::= header(HDR). { @@ -12526,9 +13204,11 @@ + + buffer_copy_string_buffer(HDR->key, A); + buffer_copy_string_buffer(HDR->value, B); ++ buffer_free(A); ++ buffer_free(B); +} --- ../lighttpd-1.4.11/src/inet_ntop_cache.c 2005-08-11 01:26:38.000000000 +0300 -+++ lighttpd-1.4.12/src/inet_ntop_cache.c 2006-07-11 22:07:52.000000000 +0300 ++++ lighttpd-1.4.12/src/inet_ntop_cache.c 2006-07-16 00:26:04.000000000 +0300 @@ -8,7 +8,7 @@ #include "sys-socket.h" @@ -12578,8 +13258,82 @@ return srv->inet_ntop_cache[i].b2; #else UNUSED(srv); +--- ../lighttpd-1.4.11/src/iosocket.c 1970-01-01 03:00:00.000000000 +0300 ++++ lighttpd-1.4.12/src/iosocket.c 2006-07-18 13:03:40.000000000 +0300 +@@ -0,0 +1,36 @@ ++#include ++ ++#include "iosocket.h" ++#include "sys-socket.h" ++#include "sys-files.h" ++#include "array-static.h" ++ ++iosocket *iosocket_init(void) { ++ STRUCT_INIT(iosocket, sock); ++ ++ sock->fde_ndx = -1; ++ sock->fd = -1; ++ ++ sock->type = IOSOCKET_TYPE_SOCKET; ++ ++ return sock; ++} ++ ++void iosocket_free(iosocket *sock) { ++ if (!sock) return; ++ ++ if (sock->fd != -1) { ++ switch (sock->type) { ++ case IOSOCKET_TYPE_SOCKET: ++ closesocket(sock->fd); ++ break; ++ case IOSOCKET_TYPE_PIPE: ++ close(sock->fd); ++ break; ++ default: ++ break; ++ } ++ } ++ ++ free(sock); ++} +--- ../lighttpd-1.4.11/src/iosocket.h 1970-01-01 03:00:00.000000000 +0300 ++++ lighttpd-1.4.12/src/iosocket.h 2006-07-18 13:03:40.000000000 +0300 +@@ -0,0 +1,32 @@ ++#ifndef _IOSOCKET_H_ ++#define _IOSOCKET_H_ ++ ++#if defined HAVE_LIBSSL && defined HAVE_OPENSSL_SSL_H ++# define USE_OPENSSL ++# include ++#endif ++ ++typedef enum { ++ IOSOCKET_TYPE_UNSET, ++ IOSOCKET_TYPE_SOCKET, ++ IOSOCKET_TYPE_PIPE ++} iosocket_t; ++ ++/** ++ * a non-blocking fd ++ */ ++typedef struct { ++ int fd; ++ int fde_ndx; ++ ++#ifdef USE_OPENSSL ++ SSL *ssl; ++#endif ++ ++ iosocket_t type; /**< sendfile on solaris doesn't work on pipes */ ++} iosocket; ++ ++iosocket *iosocket_init(void); ++void iosocket_free(iosocket *sock); ++ ++#endif --- ../lighttpd-1.4.11/src/joblist.c 2005-08-11 01:26:41.000000000 +0300 -+++ lighttpd-1.4.12/src/joblist.c 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/joblist.c 2006-07-16 00:26:03.000000000 +0300 @@ -7,7 +7,7 @@ int joblist_append(server *srv, connection *con) { @@ -12641,7 +13395,7 @@ } --- ../lighttpd-1.4.11/src/keyvalue.c 2006-03-02 16:08:06.000000000 +0200 -+++ lighttpd-1.4.12/src/keyvalue.c 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/keyvalue.c 2006-07-16 00:26:03.000000000 +0300 @@ -87,7 +87,8 @@ { 504, "Gateway Timeout" }, { 505, "HTTP Version Not Supported" }, @@ -12949,7 +13703,7 @@ free(kvb); } --- ../lighttpd-1.4.11/src/keyvalue.h 2006-03-02 16:08:06.000000000 +0200 -+++ lighttpd-1.4.12/src/keyvalue.h 2006-07-11 22:07:52.000000000 +0300 ++++ lighttpd-1.4.12/src/keyvalue.h 2006-07-16 00:26:04.000000000 +0300 @@ -9,19 +9,19 @@ # include #endif @@ -13017,7 +13771,7 @@ httpauth_type type; } httpauth_keyvalue; --- ../lighttpd-1.4.11/src/lemon.c 2005-09-01 00:21:34.000000000 +0300 -+++ lighttpd-1.4.12/src/lemon.c 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/lemon.c 2006-07-16 00:26:03.000000000 +0300 @@ -579,7 +579,7 @@ */ @@ -13190,7 +13944,7 @@ if( x4a->tbl==0 ){ free(x4a); --- ../lighttpd-1.4.11/src/lempar.c 2005-08-11 01:26:40.000000000 +0300 -+++ lighttpd-1.4.12/src/lempar.c 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/lempar.c 2006-07-16 00:26:03.000000000 +0300 @@ -8,10 +8,10 @@ /* Next is all token values, in a form suitable for use by makeheaders. ** This section will be null unless lemon is run with the -m switch. @@ -13335,7 +14089,7 @@ ** This is what we do if the grammar does define ERROR: ** --- ../lighttpd-1.4.11/src/log.c 2005-11-07 15:01:35.000000000 +0200 -+++ lighttpd-1.4.12/src/log.c 2006-07-15 22:43:21.000000000 +0300 ++++ lighttpd-1.4.12/src/log.c 2006-07-18 13:03:40.000000000 +0300 @@ -5,7 +5,6 @@ #include #include @@ -13364,7 +14118,7 @@ #ifdef HAVE_VALGRIND_VALGRIND_H #include #endif -@@ -31,38 +36,38 @@ +@@ -31,55 +36,114 @@ # define O_LARGEFILE 0 #endif @@ -13385,54 +14139,126 @@ + * */ - int log_error_open(server *srv) { +-int log_error_open(server *srv) { ++ ++typedef struct { ++ buffer *file; ++ unsigned short use_syslog; ++ ++ /* the errorlog */ int fd; - int close_stderr = 1; -- +- int close_stderr = 1; ++ enum { ERRORLOG_STDERR, ERRORLOG_FILE, ERRORLOG_SYSLOG } mode; ++ buffer *buf; ++ ++ time_t cached_ts; ++ buffer *cached_ts_str; ++} errorlog; ++ ++errorlog *myconfig = NULL; ++ ++void log_init(void) { ++ /* use syslog */ ++ errorlog *err; ++ ++ err = calloc(1, sizeof(*err)); + ++ err->fd = -1; ++ err->mode = ERRORLOG_STDERR; ++ err->buf = buffer_init(); ++ err->cached_ts_str = buffer_init(); ++ ++ myconfig = err; ++} ++ ++void log_free(void) { ++ errorlog *err = myconfig; ++ ++ if (!err) return; ++ ++ TRACE("%s", "server stopped"); ++ ++ switch(err->mode) { ++ case ERRORLOG_FILE: ++ close(err->fd); ++ break; ++ case ERRORLOG_SYSLOG: ++#ifdef HAVE_SYSLOG_H ++ closelog(); ++#endif ++ break; ++ case ERRORLOG_STDERR: ++ break; ++ } ++ ++ buffer_free(err->buf); ++ buffer_free(err->cached_ts_str); ++ if (err->file) buffer_free(err->file); ++ ++ free(err); ++ ++ myconfig = NULL; ++} ++ ++int log_error_open(buffer *file, int use_syslog) { ++ int fd; ++ int close_stderr = 1; ++ ++ errorlog *err = myconfig; + #ifdef HAVE_SYSLOG_H /* perhaps someone wants to use syslog() */ openlog("lighttpd", LOG_CONS | LOG_PID, LOG_DAEMON); #endif - srv->errorlog_mode = ERRORLOG_STDERR; +- srv->errorlog_mode = ERRORLOG_STDERR; - -+ - if (srv->srvconf.errorlog_use_syslog) { - srv->errorlog_mode = ERRORLOG_SYSLOG; - } else if (!buffer_is_empty(srv->srvconf.errorlog_file)) { - const char *logfile = srv->srvconf.errorlog_file->ptr; +- if (srv->srvconf.errorlog_use_syslog) { +- srv->errorlog_mode = ERRORLOG_SYSLOG; +- } else if (!buffer_is_empty(srv->srvconf.errorlog_file)) { +- const char *logfile = srv->srvconf.errorlog_file->ptr; - -+ - if (-1 == (srv->errorlog_fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) { +- if (-1 == (srv->errorlog_fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) { - log_error_write(srv, __FILE__, __LINE__, "SSSS", -+ log_error_write(srv, __FILE__, __LINE__, "SSSS", - "opening errorlog '", logfile, +- "opening errorlog '", logfile, ++ err->mode = ERRORLOG_STDERR; ++ ++ if (use_syslog) { ++ err->mode = ERRORLOG_SYSLOG; ++ } else if (!buffer_is_empty(file)) { ++ if (-1 == (err->fd = open(file->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) { ++ log_error_write(NULL, __FILE__, __LINE__, "SBSS", ++ "opening errorlog '", file, "' failed: ", strerror(errno)); - + return -1; } #ifdef FD_CLOEXEC -@@ -71,15 +76,15 @@ + /* close fd on exec (cgi) */ +- fcntl(srv->errorlog_fd, F_SETFD, FD_CLOEXEC); ++ fcntl(err->fd, F_SETFD, FD_CLOEXEC); #endif - srv->errorlog_mode = ERRORLOG_FILE; +- srv->errorlog_mode = ERRORLOG_FILE; ++ err->mode = ERRORLOG_FILE; } - -+ - log_error_write(srv, __FILE__, __LINE__, "s", "server started"); +- log_error_write(srv, __FILE__, __LINE__, "s", "server started"); - ++ ++ TRACE("%s", "server started"); + #ifdef HAVE_VALGRIND_VALGRIND_H /* don't close stderr for debugging purposes if run in valgrind */ if (RUNNING_ON_VALGRIND) close_stderr = 0; #endif - if (srv->errorlog_mode == ERRORLOG_STDERR) close_stderr = 0; +- if (srv->errorlog_mode == ERRORLOG_STDERR) close_stderr = 0; - ++ if (err->mode == ERRORLOG_STDERR) close_stderr = 0; + /* move stderr to /dev/null */ if (close_stderr && -1 != (fd = open("/dev/null", O_WRONLY))) { -@@ -90,33 +95,33 @@ +@@ -90,167 +154,202 @@ return 0; } @@ -13447,91 +14273,129 @@ + * */ - int log_error_cycle(server *srv) { +-int log_error_cycle(server *srv) { ++int log_error_cycle(void) { /* only cycle if we are not in syslog-mode */ - +- if (srv->errorlog_mode == ERRORLOG_FILE) { +- const char *logfile = srv->srvconf.errorlog_file->ptr; + - if (srv->errorlog_mode == ERRORLOG_FILE) { - const char *logfile = srv->srvconf.errorlog_file->ptr; ++ errorlog *err = myconfig; ++ ++ if (err->mode == ERRORLOG_FILE) { ++ buffer *file = err->file; /* already check of opening time */ - + int new_fd; - +- if (-1 == (new_fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) { + - if (-1 == (new_fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) { ++ if (-1 == (new_fd = open(file->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) { /* write to old log */ - log_error_write(srv, __FILE__, __LINE__, "SSSSS", -+ log_error_write(srv, __FILE__, __LINE__, "SSSSS", - "cycling errorlog '", logfile, +- "cycling errorlog '", logfile, ++ log_error_write(NULL, __FILE__, __LINE__, "SBSSS", ++ "cycling errorlog '", file, "' failed: ", strerror(errno), ", falling back to syslog()"); - -+ - close(srv->errorlog_fd); - srv->errorlog_fd = -1; +- close(srv->errorlog_fd); +- srv->errorlog_fd = -1; -#ifdef HAVE_SYSLOG_H +- srv->errorlog_mode = ERRORLOG_SYSLOG; ++ ++ close(err->fd); ++ err->fd = -1; +#ifdef HAVE_SYSLOG_H - srv->errorlog_mode = ERRORLOG_SYSLOG; ++ err->mode = ERRORLOG_SYSLOG; #endif } else { -@@ -125,15 +130,15 @@ - srv->errorlog_fd = new_fd; + /* ok, new log is open, close the old one */ +- close(srv->errorlog_fd); +- srv->errorlog_fd = new_fd; ++ close(err->fd); ++ err->fd = new_fd; } } - -+ - log_error_write(srv, __FILE__, __LINE__, "s", "logfiles cycled"); +- log_error_write(srv, __FILE__, __LINE__, "s", "logfiles cycled"); - -+ - return 0; - } +- return 0; +-} - int log_error_close(server *srv) { - log_error_write(srv, __FILE__, __LINE__, "s", "server stopped"); +-int log_error_close(server *srv) { +- log_error_write(srv, __FILE__, __LINE__, "s", "server stopped"); - -+ - switch(srv->errorlog_mode) { - case ERRORLOG_FILE: - close(srv->errorlog_fd); -@@ -146,13 +151,13 @@ - case ERRORLOG_STDERR: - break; - } +- switch(srv->errorlog_mode) { +- case ERRORLOG_FILE: +- close(srv->errorlog_fd); +- break; +- case ERRORLOG_SYSLOG: +-#ifdef HAVE_SYSLOG_H +- closelog(); +-#endif +- break; +- case ERRORLOG_STDERR: +- break; +- } - ++ TRACE("%s", "logfiles cycled"); + return 0; } - int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...) { +-int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...) { ++int log_error_write(void *srv, const char *filename, unsigned int line, const char *fmt, ...) { va_list ap; - +- switch(srv->errorlog_mode) { ++ time_t t; ++ ++ errorlog *err = myconfig; + - switch(srv->errorlog_mode) { ++ switch(err->mode) { case ERRORLOG_FILE: case ERRORLOG_STDERR: -@@ -161,7 +166,7 @@ - buffer_prepare_copy(srv->ts_debug_str, 255); - strftime(srv->ts_debug_str->ptr, srv->ts_debug_str->size - 1, "%Y-%m-%d %H:%M:%S", localtime(&(srv->cur_ts))); - srv->ts_debug_str->used = strlen(srv->ts_debug_str->ptr) + 1; + /* cache the generated timestamp */ +- if (srv->cur_ts != srv->last_generated_debug_ts) { +- buffer_prepare_copy(srv->ts_debug_str, 255); +- strftime(srv->ts_debug_str->ptr, srv->ts_debug_str->size - 1, "%Y-%m-%d %H:%M:%S", localtime(&(srv->cur_ts))); +- srv->ts_debug_str->used = strlen(srv->ts_debug_str->ptr) + 1; - -+ - srv->last_generated_debug_ts = srv->cur_ts; +- srv->last_generated_debug_ts = srv->cur_ts; ++ t = time(NULL); ++ ++ if (t != err->cached_ts) { ++ buffer_prepare_copy(err->cached_ts_str, 255); ++ strftime(err->cached_ts_str->ptr, err->cached_ts_str->size - 1, "%Y-%m-%d %H:%M:%S", localtime(&(t))); ++ err->cached_ts_str->used = strlen(err->cached_ts_str->ptr) + 1; ++ err->cached_ts = t; } -@@ -173,19 +178,19 @@ - BUFFER_COPY_STRING_CONST(srv->errorlog_buf, "("); +- buffer_copy_string_buffer(srv->errorlog_buf, srv->ts_debug_str); +- BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, ": ("); ++ buffer_copy_string_buffer(err->buf, err->cached_ts_str); ++ BUFFER_APPEND_STRING_CONST(err->buf, ": ("); + break; + case ERRORLOG_SYSLOG: + /* syslog is generating its own timestamps */ +- BUFFER_COPY_STRING_CONST(srv->errorlog_buf, "("); ++ BUFFER_COPY_STRING_CONST(err->buf, "("); break; } - -+ - buffer_append_string(srv->errorlog_buf, filename); - BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "."); - buffer_append_long(srv->errorlog_buf, line); - BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, ") "); +- buffer_append_string(srv->errorlog_buf, filename); +- BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "."); +- buffer_append_long(srv->errorlog_buf, line); +- BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, ") "); - - + ++ buffer_append_string(err->buf, filename); ++ BUFFER_APPEND_STRING_CONST(err->buf, "."); ++ buffer_append_long(err->buf, line); ++ BUFFER_APPEND_STRING_CONST(err->buf, ") "); + for(va_start(ap, fmt); *fmt; fmt++) { int d; @@ -13543,7 +14407,55 @@ switch(*fmt) { case 's': /* string */ s = va_arg(ap, char *); -@@ -227,7 +232,7 @@ +- buffer_append_string(srv->errorlog_buf, s); +- BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, " "); ++ buffer_append_string(err->buf, s); ++ BUFFER_APPEND_STRING_CONST(err->buf, " "); + break; + case 'b': /* buffer */ + b = va_arg(ap, buffer *); +- buffer_append_string_buffer(srv->errorlog_buf, b); +- BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, " "); ++ buffer_append_string_buffer(err->buf, b); ++ BUFFER_APPEND_STRING_CONST(err->buf, " "); + break; + case 'd': /* int */ + d = va_arg(ap, int); +- buffer_append_long(srv->errorlog_buf, d); +- BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, " "); ++ buffer_append_long(err->buf, d); ++ BUFFER_APPEND_STRING_CONST(err->buf, " "); + break; + case 'o': /* off_t */ + o = va_arg(ap, off_t); +- buffer_append_off_t(srv->errorlog_buf, o); +- BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, " "); ++ buffer_append_off_t(err->buf, o); ++ BUFFER_APPEND_STRING_CONST(err->buf, " "); + break; + case 'x': /* int (hex) */ + d = va_arg(ap, int); +- BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "0x"); +- buffer_append_long_hex(srv->errorlog_buf, d); +- BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, " "); ++ BUFFER_APPEND_STRING_CONST(err->buf, "0x"); ++ buffer_append_long_hex(err->buf, d); ++ BUFFER_APPEND_STRING_CONST(err->buf, " "); + break; + case 'S': /* string */ + s = va_arg(ap, char *); +- buffer_append_string(srv->errorlog_buf, s); ++ buffer_append_string(err->buf, s); + break; + case 'B': /* buffer */ + b = va_arg(ap, buffer *); +- buffer_append_string_buffer(srv->errorlog_buf, b); ++ buffer_append_string_buffer(err->buf, b); + break; + case 'D': /* int */ + d = va_arg(ap, int); +- buffer_append_long(srv->errorlog_buf, d); ++ buffer_append_long(err->buf, d); break; case '(': case ')': @@ -13552,41 +14464,120 @@ case '>': case ',': case ' ': -@@ -236,7 +241,7 @@ +- buffer_append_string_len(srv->errorlog_buf, fmt, 1); ++ buffer_append_string_len(err->buf, fmt, 1); + break; } } va_end(ap); - +- switch(srv->errorlog_mode) { + - switch(srv->errorlog_mode) { ++ switch(err->mode) { case ERRORLOG_FILE: - BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "\n"); -@@ -246,11 +251,13 @@ - BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "\n"); - write(STDERR_FILENO, srv->errorlog_buf->ptr, srv->errorlog_buf->used - 1); +- BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "\n"); +- write(srv->errorlog_fd, srv->errorlog_buf->ptr, srv->errorlog_buf->used - 1); ++ BUFFER_APPEND_STRING_CONST(err->buf, "\n"); ++ write(err->fd, err->buf->ptr, err->buf->used - 1); + break; + case ERRORLOG_STDERR: +- BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "\n"); +- write(STDERR_FILENO, srv->errorlog_buf->ptr, srv->errorlog_buf->used - 1); ++ BUFFER_APPEND_STRING_CONST(err->buf, "\n"); ++ write(STDERR_FILENO, err->buf->ptr, err->buf->used - 1); break; ++#ifdef HAVE_SYSLOG_H ++ case ERRORLOG_SYSLOG: ++ syslog(LOG_ERR, "%s", err->buf->ptr); ++ break; ++#endif ++ } ++ ++ return 0; ++} ++ ++static int log_trace_write(const char *fmt, va_list ap) { ++ buffer *b; ++ int l; ++ errorlog *err = myconfig; ++ ++ b = buffer_init(); ++ buffer_prepare_copy(b, 1024); ++ l = vsnprintf(b->ptr, b->size - 1, fmt, ap); ++ if (l > 0) { ++ b->used = (l > b->size - 1) ? b->size : l + 1; ++ } ++ ++ /* write b */ ++ switch(err->mode) { ++ case ERRORLOG_FILE: ++ buffer_append_string(b, "\r\n"); ++ write(err->fd, b->ptr, b->used - 1); ++ break; ++ case ERRORLOG_STDERR: ++ buffer_append_string(b, "\r\n"); ++ write(STDERR_FILENO, b->ptr, b->used - 1); ++ break; +#ifdef HAVE_SYSLOG_H case ERRORLOG_SYSLOG: - syslog(LOG_ERR, "%s", srv->errorlog_buf->ptr); +- syslog(LOG_ERR, "%s", srv->errorlog_buf->ptr); ++ syslog(LOG_ERR, "%s", b->ptr); break; +#endif } -- + ++ buffer_free(b); ++ ++ return 0; ++} ++ ++int log_trace(const char *fmt, ...) { ++ va_list ap; ++ ++ va_start(ap, fmt); ++ ++ log_trace_write(fmt, ap); ++ ++ va_end(ap); + return 0; } ++ --- ../lighttpd-1.4.11/src/log.h 2005-08-11 01:26:36.000000000 +0300 -+++ lighttpd-1.4.12/src/log.h 2006-07-11 22:07:53.000000000 +0300 -@@ -9,5 +9,5 @@ - int log_error_close(server *srv); - int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...); - int log_error_cycle(server *srv); ++++ lighttpd-1.4.12/src/log.h 2006-07-18 13:03:40.000000000 +0300 +@@ -1,13 +1,22 @@ + #ifndef _LOG_H_ + #define _LOG_H_ + +-#include "server.h" ++#include "buffer.h" + +-#define WP() log_error_write(srv, __FILE__, __LINE__, ""); ++void log_init(void); ++void log_free(void); + +-int log_error_open(server *srv); +-int log_error_close(server *srv); +-int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...); +-int log_error_cycle(server *srv); - ++int log_error_open(buffer *file, int use_syslog); ++int log_error_close(); ++int log_error_write(void *srv, const char *filename, unsigned int line, const char *fmt, ...); ++int log_error_cycle(); ++ ++#define ERROR(fmt, ...) \ ++ log_trace("%s.%d: (error) "fmt, __FILE__, __LINE__, __VA_ARGS__) ++ ++#define TRACE(fmt, ...) \ ++ log_trace("%s.%d: (trace) "fmt, __FILE__, __LINE__, __VA_ARGS__) + ++#define SEGFAULT() do { ERROR("%s", "Ooh, Ooh, Ooh. Something is not good ... going down"); abort(); } while(0) ++int log_trace(const char *fmt, ...); #endif --- ../lighttpd-1.4.11/src/md5.h 2005-11-17 16:20:40.000000000 +0200 -+++ lighttpd-1.4.12/src/md5.h 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/md5.h 2006-07-16 00:26:04.000000000 +0300 @@ -30,9 +30,15 @@ # include #endif @@ -13604,7 +14595,7 @@ /* MD5 context. */ typedef struct { --- ../lighttpd-1.4.11/src/mod_access.c 2006-01-14 19:44:54.000000000 +0200 -+++ lighttpd-1.4.12/src/mod_access.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_access.c 2006-07-16 00:26:04.000000000 +0300 @@ -8,126 +8,125 @@ #include "plugin.h" @@ -13807,7 +14798,7 @@ return 0; } --- ../lighttpd-1.4.11/src/mod_accesslog.c 2006-01-31 14:01:43.000000000 +0200 -+++ lighttpd-1.4.12/src/mod_accesslog.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_accesslog.c 2006-07-16 00:26:04.000000000 +0300 @@ -6,8 +6,7 @@ #include #include @@ -14662,7 +15653,7 @@ return 0; } --- ../lighttpd-1.4.11/src/mod_alias.c 2006-03-01 23:18:51.000000000 +0200 -+++ lighttpd-1.4.12/src/mod_alias.c 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_alias.c 2006-07-16 00:26:03.000000000 +0300 @@ -8,6 +8,7 @@ #include "buffer.h" @@ -14878,7 +15869,7 @@ return 0; } --- ../lighttpd-1.4.11/src/mod_auth.c 2006-02-15 20:01:31.000000000 +0200 -+++ lighttpd-1.4.12/src/mod_auth.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_auth.c 2006-07-18 13:03:40.000000000 +0300 @@ -5,168 +5,167 @@ #include #include @@ -15138,7 +16129,7 @@ /* search auth-directives for path */ for (k = 0; k < p->conf.auth_require->used; k++) { buffer *req = p->conf.auth_require->data[k]->key; -@@ -212,31 +211,31 @@ +@@ -212,76 +211,76 @@ } } } @@ -15175,12 +16166,15 @@ if ((auth_type_len == 5) && (0 == strncmp(http_authorization, "Basic", auth_type_len))) { - +- if (0 == strcmp(method->value->ptr, "basic")) { + - if (0 == strcmp(method->value->ptr, "basic")) { ++ if (buffer_is_equal_string(method->value, CONST_STR_LEN("basic"))) { auth_satisfied = http_auth_basic_check(srv, con, p, req, con->uri.path, auth_realm+1); } -@@ -245,43 +244,43 @@ - if (0 == strcmp(method->value->ptr, "digest")) { + } else if ((auth_type_len == 6) && + (0 == strncmp(http_authorization, "Digest", auth_type_len))) { +- if (0 == strcmp(method->value->ptr, "digest")) { ++ if (buffer_is_equal_string(method->value, CONST_STR_LEN("digest"))) { if (-1 == (auth_satisfied = http_auth_digest_check(srv, con, p, req, con->uri.path, auth_realm+1))) { con->http_status = 400; - @@ -15209,15 +16203,17 @@ + con->http_status = 401; - +- if (0 == strcmp(method->value->ptr, "basic")) { + - if (0 == strcmp(method->value->ptr, "basic")) { ++ if (buffer_is_equal_string(method->value, CONST_STR_LEN("basic"))) { buffer_copy_string(p->tmp_buf, "Basic realm=\""); buffer_append_string_buffer(p->tmp_buf, realm->value); buffer_append_string(p->tmp_buf, "\""); - + response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf)); - } else if (0 == strcmp(method->value->ptr, "digest")) { +- } else if (0 == strcmp(method->value->ptr, "digest")) { ++ } else if (buffer_is_equal_string(method->value, CONST_STR_LEN("digest"))) { char hh[33]; http_auth_digest_generate_nonce(srv, p, srv->tmp_buf, hh); - @@ -15300,7 +16296,7 @@ cv[0].destination = s->auth_backend_conf; cv[1].destination = s->auth_plain_groupfile; cv[2].destination = s->auth_plain_userfile; -@@ -364,14 +363,14 @@ +@@ -364,146 +363,148 @@ cv[11].destination = s->auth_htdigest_userfile; cv[12].destination = s->auth_htpasswd_userfile; cv[13].destination = &(s->auth_debug); @@ -15314,11 +16310,20 @@ return HANDLER_ERROR; } - +- if (s->auth_backend_conf->used) { +- if (0 == strcmp(s->auth_backend_conf->ptr, "htpasswd")) { + - if (s->auth_backend_conf->used) { - if (0 == strcmp(s->auth_backend_conf->ptr, "htpasswd")) { ++ if (!buffer_is_empty(s->auth_backend_conf)) { ++ if (buffer_is_equal_string(s->auth_backend_conf, CONST_STR_LEN("htpasswd"))) { s->auth_backend = AUTH_BACKEND_HTPASSWD; -@@ -383,31 +382,31 @@ +- } else if (0 == strcmp(s->auth_backend_conf->ptr, "htdigest")) { ++ } else if (buffer_is_equal_string(s->auth_backend_conf, CONST_STR_LEN("htdigest"))) { + s->auth_backend = AUTH_BACKEND_HTDIGEST; +- } else if (0 == strcmp(s->auth_backend_conf->ptr, "plain")) { ++ } else if (buffer_is_equal_string(s->auth_backend_conf, CONST_STR_LEN("plain"))) { + s->auth_backend = AUTH_BACKEND_PLAIN; +- } else if (0 == strcmp(s->auth_backend_conf->ptr, "ldap")) { ++ } else if (buffer_is_equal_string(s->auth_backend_conf, CONST_STR_LEN("ldap"))) { s->auth_backend = AUTH_BACKEND_LDAP; } else { log_error_write(srv, __FILE__, __LINE__, "sb", "auth.backend not supported:", s->auth_backend_conf); @@ -15338,8 +16343,9 @@ for (n = 0; n < da->value->used; n++) { size_t m; data_array *da_file = (data_array *)da->value->data[n]; - const char *method, *realm, *require; +- const char *method, *realm, *require; - ++ buffer *method, *realm, *require; + if (da->value->data[n]->type != TYPE_ARRAY) { - log_error_write(srv, __FILE__, __LINE__, "ss", @@ -15356,33 +16362,52 @@ - + for (m = 0; m < da_file->value->used; m++) { - if (da_file->value->data[m]->type == TYPE_STRING) { - if (0 == strcmp(da_file->value->data[m]->key->ptr, "method")) { -@@ -417,8 +416,8 @@ - } else if (0 == strcmp(da_file->value->data[m]->key->ptr, "require")) { - require = ((data_string *)(da_file->value->data[m]))->value->ptr; - } else { +- if (da_file->value->data[m]->type == TYPE_STRING) { +- if (0 == strcmp(da_file->value->data[m]->key->ptr, "method")) { +- method = ((data_string *)(da_file->value->data[m]))->value->ptr; +- } else if (0 == strcmp(da_file->value->data[m]->key->ptr, "realm")) { +- realm = ((data_string *)(da_file->value->data[m]))->value->ptr; +- } 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__, "ssbs", - "the field is unknown in:", -+ log_error_write(srv, __FILE__, __LINE__, "ssbs", ++ data_string *ds_auth_req = (data_string *)da_file->value->data[m]; ++ ++ if (ds_auth_req->type != TYPE_STRING) { ++ log_error_write(srv, __FILE__, __LINE__, "ssbs", ++ "a string was expected for:", ++ "auth.require = ( \"...\" => ( ..., -> \"", ++ ds_auth_req->key, ++ "\" <- => \"...\" ) )"); ++ ++ return HANDLER_ERROR; ++ } ++ ++ if (buffer_is_equal_string(ds_auth_req->key, CONST_STR_LEN("method"))) { ++ method = ds_auth_req->value; ++ } else if (buffer_is_equal_string(ds_auth_req->key, CONST_STR_LEN("realm"))) { ++ realm = ds_auth_req->value; ++ } else if (buffer_is_equal_string(ds_auth_req->key, CONST_STR_LEN("require"))) { ++ require = ds_auth_req->value; ++ } else { ++ log_error_write(srv, __FILE__, __LINE__, "ssbs", + "the field is unknown in:", "auth.require = ( \"...\" => ( ..., -> \"", da_file->value->data[m]->key, "\" <- => \"...\" ) )"); -@@ -426,19 +425,19 @@ - return HANDLER_ERROR; - } - } else { + +- return HANDLER_ERROR; +- } +- } else { - log_error_write(srv, __FILE__, __LINE__, "ssbs", - "a string was expected for:", -+ log_error_write(srv, __FILE__, __LINE__, "ssbs", -+ "a string was expected for:", - "auth.require = ( \"...\" => ( ..., -> \"", - da_file->value->data[m]->key, - "\" <- => \"...\" ) )"); +- "auth.require = ( \"...\" => ( ..., -> \"", +- da_file->value->data[m]->key, +- "\" <- => \"...\" ) )"); - -+ return HANDLER_ERROR; ++ } } - @@ -15394,10 +16419,21 @@ + "the require field is missing in:", "auth.require = ( \"...\" => ( ..., \"method\" => \"...\" ) )"); return HANDLER_ERROR; - } else { -@@ -450,60 +449,60 @@ - return HANDLER_ERROR; - } +- } else { +- if (0 != strcmp(method, "basic") && +- 0 != strcmp(method, "digest")) { +- log_error_write(srv, __FILE__, __LINE__, "ss", +- "method has to be either \"basic\" or \"digest\" in", +- "auth.require = ( \"...\" => ( ..., \"method\" => \"...\") )"); +- return HANDLER_ERROR; +- } ++ } ++ if (!buffer_is_equal_string(method, CONST_STR_LEN("basic")) && ++ !buffer_is_equal_string(method, CONST_STR_LEN("digest"))) { ++ log_error_write(srv, __FILE__, __LINE__, "ss", ++ "method has to be either \"basic\" or \"digest\" in", ++ "auth.require = ( \"...\" => ( ..., \"method\" => \"...\") )"); ++ return HANDLER_ERROR; } - + @@ -15434,8 +16470,9 @@ - + buffer_copy_string(ds->key, "method"); - buffer_copy_string(ds->value, method); +- buffer_copy_string(ds->value, method); - ++ buffer_copy_string_buffer(ds->value, method); + array_insert_unique(a->value, (data_unset *)ds); - @@ -15444,8 +16481,9 @@ - + buffer_copy_string(ds->key, "realm"); - buffer_copy_string(ds->value, realm); +- buffer_copy_string(ds->value, realm); - ++ buffer_copy_string_buffer(ds->value, realm); + array_insert_unique(a->value, (data_unset *)ds); - @@ -15454,8 +16492,9 @@ - + buffer_copy_string(ds->key, "require"); - buffer_copy_string(ds->value, require); +- buffer_copy_string(ds->value, require); - ++ buffer_copy_string_buffer(ds->value, require); + array_insert_unique(a->value, (data_unset *)ds); - @@ -15476,7 +16515,7 @@ "opening auth.backend.plain.userfile:", s->auth_plain_userfile, "failed:", strerror(errno)); return HANDLER_ERROR; -@@ -516,7 +515,7 @@ +@@ -516,7 +517,7 @@ int fd; /* try to read */ if (-1 == (fd = open(s->auth_htpasswd_userfile->ptr, O_RDONLY))) { @@ -15485,7 +16524,7 @@ "opening auth.backend.htpasswd.userfile:", s->auth_htpasswd_userfile, "failed:", strerror(errno)); return HANDLER_ERROR; -@@ -529,7 +528,7 @@ +@@ -529,7 +530,7 @@ int fd; /* try to read */ if (-1 == (fd = open(s->auth_htdigest_userfile->ptr, O_RDONLY))) { @@ -15494,7 +16533,7 @@ "opening auth.backend.htdigest.userfile:", s->auth_htdigest_userfile, "failed:", strerror(errno)); return HANDLER_ERROR; -@@ -554,75 +553,75 @@ +@@ -554,75 +555,75 @@ handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s) { #ifdef USE_LDAP int ret; @@ -15591,7 +16630,7 @@ return HANDLER_ERROR; } } -@@ -641,8 +640,8 @@ +@@ -641,8 +642,8 @@ p->set_defaults = mod_auth_set_defaults; p->handle_uri_clean = mod_auth_uri_handler; p->cleanup = mod_auth_free; @@ -15603,7 +16642,7 @@ return 0; } --- ../lighttpd-1.4.11/src/mod_cgi.c 2006-02-22 15:15:10.000000000 +0200 -+++ lighttpd-1.4.12/src/mod_cgi.c 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_cgi.c 2006-07-18 13:03:40.000000000 +0300 @@ -1,21 +1,8 @@ #include -#ifdef __WIN32 @@ -15626,24 +16665,24 @@ #include #include #include -@@ -29,9 +16,16 @@ +@@ -29,8 +16,16 @@ #include "connections.h" #include "joblist.h" #include "http_chunk.h" +#include "fdevent.h" #include "plugin.h" - ++#include "http_resp.h" ++ +#include "sys-files.h" +#include "sys-mmap.h" +#include "sys-socket.h" +#include "sys-strings.h" +#include "sys-process.h" -+ + #ifdef HAVE_SYS_FILIO_H # include - #endif -@@ -40,11 +34,12 @@ +@@ -40,11 +35,12 @@ typedef struct { char **ptr; @@ -15657,15 +16696,17 @@ typedef struct { pid_t *ptr; size_t used; -@@ -58,23 +53,23 @@ +@@ -58,57 +54,68 @@ typedef struct { PLUGIN_DATA; buffer_pid_t cgi_pid; - + buffer *tmp_buf; - buffer *parse_response; +- buffer *parse_response; - ++ ++ http_resp *resp; + plugin_config **config_storage; - @@ -15674,41 +16715,71 @@ + plugin_config conf; } plugin_data; ++typedef enum { ++ CGI_STATE_UNSET, ++ CGI_STATE_CONNECTING, ++ CGI_STATE_READ_RESPONSE_HEADER, ++ CGI_STATE_READ_RESPONSE_CONTENT ++} cgi_state_t; ++ typedef struct { pid_t pid; - int fd; - int fde_ndx; /* index into the fd-event buffer */ +- int fd; +- int fde_ndx; /* index into the fd-event buffer */ - -+ - connection *remote_conn; /* dumb pointer */ - plugin_data *plugin_data; /* dumb pointer */ +- connection *remote_conn; /* dumb pointer */ +- plugin_data *plugin_data; /* dumb pointer */ - -+ - buffer *response; - buffer *response_header; - } handler_ctx; -@@ -83,17 +78,17 @@ - handler_ctx *hctx = calloc(1, sizeof(*hctx)); +- buffer *response; +- buffer *response_header; +-} handler_ctx; - assert(hctx); +-static handler_ctx * cgi_handler_ctx_init() { +- handler_ctx *hctx = calloc(1, sizeof(*hctx)); ++ iosocket *sock; + +- assert(hctx); - -+ - hctx->response = buffer_init(); - hctx->response_header = buffer_init(); +- hctx->response = buffer_init(); +- hctx->response_header = buffer_init(); - -+ - return hctx; - } +- return hctx; +-} ++ chunkqueue *rb; ++ chunkqueue *wb; - static void cgi_handler_ctx_free(handler_ctx *hctx) { - buffer_free(hctx->response); - buffer_free(hctx->response_header); +-static void cgi_handler_ctx_free(handler_ctx *hctx) { +- buffer_free(hctx->response); +- buffer_free(hctx->response_header); - +- free(hctx); ++ cgi_state_t state; + - free(hctx); ++ connection *remote_con; /* dumb pointer */ ++} cgi_session; ++ ++static cgi_session * cgi_session_init() { ++ cgi_session *sess = calloc(1, sizeof(*sess)); ++ assert(sess); ++ ++ sess->sock = iosocket_init(); ++ sess->wb = chunkqueue_init(); ++ sess->rb = chunkqueue_init(); ++ ++ return sess; } -@@ -101,14 +96,14 @@ +-enum {FDEVENT_HANDLED_UNSET, FDEVENT_HANDLED_FINISHED, FDEVENT_HANDLED_NOT_FINISHED, FDEVENT_HANDLED_ERROR}; ++static void cgi_session_free(cgi_session *sess) { ++ if (!sess) return; ++ ++ iosocket_free(sess->sock); ++ ++ chunkqueue_free(sess->wb); ++ chunkqueue_free(sess->rb); ++ ++ free(sess); ++} INIT_FUNC(mod_cgi_init) { plugin_data *p; @@ -15720,13 +16791,14 @@ - + p->tmp_buf = buffer_init(); - p->parse_response = buffer_init(); +- p->parse_response = buffer_init(); - ++ p->resp = http_response_init(); + return p; } -@@ -116,62 +111,62 @@ +@@ -116,62 +123,62 @@ FREE_FUNC(mod_cgi_free) { plugin_data *p = p_d; buffer_pid_t *r = &(p->cgi_pid); @@ -15755,8 +16827,9 @@ - + buffer_free(p->tmp_buf); - buffer_free(p->parse_response); +- buffer_free(p->parse_response); - ++ http_response_free(p->resp); + free(p); - @@ -15807,7 +16880,7 @@ return HANDLER_GO_ON; } -@@ -180,13 +175,13 @@ +@@ -180,13 +187,13 @@ int m = -1; size_t i; buffer_pid_t *r = &(p->cgi_pid); @@ -15823,7 +16896,7 @@ if (r->size == 0) { r->size = 16; r->ptr = malloc(sizeof(*r->ptr) * r->size); -@@ -194,31 +189,31 @@ +@@ -194,321 +201,178 @@ r->size += 16; r->ptr = realloc(r->ptr, sizeof(*r->ptr) * r->size); } @@ -15861,282 +16934,364 @@ return 0; } -@@ -226,32 +221,32 @@ - char *ns; - const char *s; - int line = 0; +-static int cgi_response_parse(server *srv, connection *con, plugin_data *p, buffer *in, int eol) { +- char *ns; +- const char *s; +- int line = 0; - -+ - UNUSED(srv); +- UNUSED(srv); - -+ - buffer_copy_string_buffer(p->parse_response, in); +- buffer_copy_string_buffer(p->parse_response, in); - - for (s = p->parse_response->ptr; - NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n'))); -+ -+ for (s = p->parse_response->ptr; -+ NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n'))); - s = ns + (eol == EOL_RN ? 2 : 1), line++) { - const char *key, *value; - int key_len; - data_string *ds; +- s = ns + (eol == EOL_RN ? 2 : 1), line++) { +- const char *key, *value; +- int key_len; +- data_string *ds; - -+ - ns[0] = '\0'; +- ns[0] = '\0'; - - if (line == 0 && -+ -+ if (line == 0 && - 0 == strncmp(s, "HTTP/1.", 7)) { - /* non-parsed header ... we parse them anyway */ -- -+ - if ((s[7] == '1' || - s[7] == '0') && - s[8] == ' ') { - int status; - /* after the space should be a status code for us */ -- -+ - status = strtol(s+9, NULL, 10); -- -+ - if (con->http_status >= 100 && - con->http_status < 1000) { - /* we expected 3 digits and didn't got them */ -@@ -260,27 +255,27 @@ - } - } - } else { +- 0 == strncmp(s, "HTTP/1.", 7)) { +- /* non-parsed header ... we parse them anyway */ +- +- if ((s[7] == '1' || +- s[7] == '0') && +- s[8] == ' ') { +- int status; +- /* after the space should be a status code for us */ +- +- status = strtol(s+9, NULL, 10); +- +- if (con->http_status >= 100 && +- con->http_status < 1000) { +- /* we expected 3 digits and didn't got them */ +- con->parsed_response |= HTTP_STATUS; +- con->http_status = status; +- } +- } +- } else { - -+ - key = s; - if (NULL == (value = strchr(s, ':'))) { - /* we expect: ": \r\n" */ - continue; - } +- key = s; +- if (NULL == (value = strchr(s, ':'))) { +- /* we expect: ": \r\n" */ +- continue; +- } - -+ - key_len = value - key; - value += 1; +- key_len = value - key; +- value += 1; - -+ - /* skip LWS */ - while (*value == ' ' || *value == '\t') value++; +- /* skip LWS */ +- while (*value == ' ' || *value == '\t') value++; - -+ - if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) { - ds = data_response_init(); - } - buffer_copy_string_len(ds->key, key, key_len); - buffer_copy_string(ds->value, value); +- if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) { +- ds = data_response_init(); +- } +- buffer_copy_string_len(ds->key, key, key_len); +- buffer_copy_string(ds->value, value); - -+ - array_insert_unique(con->response.headers, (data_unset *)ds); +- array_insert_unique(con->response.headers, (data_unset *)ds); - -+ - switch(key_len) { - case 4: - if (0 == strncasecmp(key, "Date", key_len)) { -@@ -315,13 +310,13 @@ - } - } - } +- switch(key_len) { +- case 4: +- if (0 == strncasecmp(key, "Date", key_len)) { +- con->parsed_response |= HTTP_DATE; +- } +- break; +- case 6: +- if (0 == strncasecmp(key, "Status", key_len)) { +- con->http_status = strtol(value, NULL, 10); +- con->parsed_response |= HTTP_STATUS; +- } +- break; +- case 8: +- if (0 == strncasecmp(key, "Location", key_len)) { +- con->parsed_response |= HTTP_LOCATION; +- } +- break; +- case 10: +- if (0 == strncasecmp(key, "Connection", key_len)) { +- con->response.keep_alive = (0 == strcasecmp(value, "Keep-Alive")) ? 1 : 0; +- con->parsed_response |= HTTP_CONNECTION; +- } +- break; +- case 14: +- if (0 == strncasecmp(key, "Content-Length", key_len)) { +- con->response.content_length = strtol(value, NULL, 10); +- con->parsed_response |= HTTP_CONTENT_LENGTH; +- } +- break; +- default: +- break; +- } +- } +- } - +- /* CGI/1.1 rev 03 - 7.2.1.2 */ +- if ((con->parsed_response & HTTP_LOCATION) && +- !(con->parsed_response & HTTP_STATUS)) { +- con->http_status = 302; ++static int cgi_demux_response(server *srv, connection *con, plugin_data *p) { ++ cgi_session *sess = con->plugin_ctx[p->id]; ++ chunk *c = NULL; + - /* CGI/1.1 rev 03 - 7.2.1.2 */ - if ((con->parsed_response & HTTP_LOCATION) && - !(con->parsed_response & HTTP_STATUS)) { - con->http_status = 302; ++ switch(srv->network_backend_read(srv, con, sess->sock, sess->rb)) { ++ case NETWORK_STATUS_SUCCESS: ++ /* we got content */ ++ break; ++ case NETWORK_STATUS_WAIT_FOR_EVENT: ++ return 0; ++ case NETWORK_STATUS_CONNECTION_CLOSE: ++ /* this is a bit too early */ ++ ERROR("%s", "cgi-connection got closed before we read the response-header (CGI died ?)"); ++ return -1; ++ default: ++ /* oops */ ++ ERROR("%s", "oops, read-pipe-read failed and I don't know why"); ++ return -1; } - -+ - return 0; - } +- return 0; +-} -@@ -329,10 +324,10 @@ - static int cgi_demux_response(server *srv, handler_ctx *hctx) { - plugin_data *p = hctx->plugin_data; - connection *con = hctx->remote_conn; ++ /* looks like we got some content ++ * ++ * split off the header from the incoming stream ++ */ + +-static int cgi_demux_response(server *srv, handler_ctx *hctx) { +- plugin_data *p = hctx->plugin_data; +- connection *con = hctx->remote_conn; - -+ - while(1) { - int n; +- while(1) { +- int n; - -+ - buffer_prepare_copy(hctx->response, 1024); - if (-1 == (n = read(hctx->fd, hctx->response->ptr, hctx->response->size - 1))) { - if (errno == EAGAIN || errno == EINTR) { -@@ -343,125 +338,125 @@ - log_error_write(srv, __FILE__, __LINE__, "sdd", strerror(errno), con->fd, hctx->fd); - return FDEVENT_HANDLED_ERROR; - } +- buffer_prepare_copy(hctx->response, 1024); +- if (-1 == (n = read(hctx->fd, hctx->response->ptr, hctx->response->size - 1))) { +- if (errno == EAGAIN || errno == EINTR) { +- /* would block, wait for signal */ +- return FDEVENT_HANDLED_NOT_FINISHED; +- } +- /* error */ +- log_error_write(srv, __FILE__, __LINE__, "sdd", strerror(errno), con->fd, hctx->fd); +- return FDEVENT_HANDLED_ERROR; +- } - -+ - if (n == 0) { - /* read finished */ +- if (n == 0) { +- /* read finished */ - -+ - con->file_finished = 1; +- con->file_finished = 1; - -+ - /* send final chunk */ - http_chunk_append_mem(srv, con, NULL, 0); - joblist_append(srv, con); +- /* send final chunk */ +- http_chunk_append_mem(srv, con, NULL, 0); +- joblist_append(srv, con); - -+ - return FDEVENT_HANDLED_FINISHED; - } +- return FDEVENT_HANDLED_FINISHED; +- } - -+ - hctx->response->ptr[n] = '\0'; - hctx->response->used = n+1; +- hctx->response->ptr[n] = '\0'; +- hctx->response->used = n+1; - -+ - /* split header from body */ +- /* split header from body */ - -+ - if (con->file_started == 0) { - char *c; - int in_header = 0; - int header_end = 0; - int cp, eol = EOL_UNSET; - size_t used = 0; -- -+ - buffer_append_string_buffer(hctx->response_header, hctx->response); -- -+ - /* nph (non-parsed headers) */ - if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) in_header = 1; -- -+ - /* search for the \r\n\r\n or \n\n in the string */ - for (c = hctx->response_header->ptr, cp = 0, used = hctx->response_header->used - 1; used; c++, cp++, used--) { - if (*c == ':') in_header = 1; - else if (*c == '\n') { - if (in_header == 0) { - /* got a response without a response header */ +- if (con->file_started == 0) { +- char *c; +- int in_header = 0; +- int header_end = 0; +- int cp, eol = EOL_UNSET; +- size_t used = 0; +- +- buffer_append_string_buffer(hctx->response_header, hctx->response); +- +- /* nph (non-parsed headers) */ +- if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) in_header = 1; +- +- /* search for the \r\n\r\n or \n\n in the string */ +- for (c = hctx->response_header->ptr, cp = 0, used = hctx->response_header->used - 1; used; c++, cp++, used--) { +- if (*c == ':') in_header = 1; +- else if (*c == '\n') { +- if (in_header == 0) { +- /* got a response without a response header */ - -+ - c = NULL; - header_end = 1; - break; - } +- c = NULL; +- header_end = 1; +- break; +- } - -+ - if (eol == EOL_UNSET) eol = EOL_N; +- if (eol == EOL_UNSET) eol = EOL_N; - -+ - if (*(c+1) == '\n') { - header_end = 1; - break; - } +- if (*(c+1) == '\n') { +- header_end = 1; +- break; +- } - -+ - } else if (used > 1 && *c == '\r' && *(c+1) == '\n') { - if (in_header == 0) { - /* got a response without a response header */ +- } else if (used > 1 && *c == '\r' && *(c+1) == '\n') { +- if (in_header == 0) { +- /* got a response without a response header */ - -+ - c = NULL; - header_end = 1; - break; - } +- c = NULL; +- header_end = 1; +- break; +- } - -+ - if (eol == EOL_UNSET) eol = EOL_RN; +- if (eol == EOL_UNSET) eol = EOL_RN; - -+ - if (used > 3 && +- if (used > 3 && - *(c+2) == '\r' && -+ *(c+2) == '\r' && - *(c+3) == '\n') { - header_end = 1; - break; - } +- *(c+3) == '\n') { +- header_end = 1; +- break; +- } - +- /* skip the \n */ +- c++; +- cp++; +- used--; ++ if (con->file_started == 0) { ++ size_t i; ++ int have_content_length = 0; ++ ++ http_response_reset(p->resp); ++ ++ /* the response header is not fully received yet, ++ * ++ * extract the http-response header from the rb-cq ++ */ ++ switch (http_response_parse_cq(sess->rb, p->resp)) { ++ case PARSE_ERROR: ++ /* parsing failed */ ++ ++ TRACE("%s", "response parser failed"); ++ ++ con->http_status = 502; /* Bad Gateway */ ++ return -1; ++ case PARSE_NEED_MORE: ++ return 0; ++ case PARSE_SUCCESS: ++ con->http_status = p->resp->status; ++ ++ chunkqueue_remove_finished_chunks(sess->rb); + - /* skip the \n */ - c++; - cp++; - used--; ++ /* copy the http-headers */ ++ for (i = 0; i < p->resp->headers->used; i++) { ++ const char *ign[] = { "Status", "Connection", NULL }; ++ size_t j; ++ data_string *ds; ++ ++ data_string *header = (data_string *)p->resp->headers->data[i]; ++ ++ /* some headers are ignored by default */ ++ for (j = 0; ign[j]; j++) { ++ if (0 == strcasecmp(ign[j], header->key->ptr)) break; } - } +- } - -+ - if (header_end) { - if (c == NULL) { - /* no header, but a body */ +- if (header_end) { +- if (c == NULL) { +- /* no header, but a body */ - -+ - if (con->request.http_version == HTTP_VERSION_1_1) { - con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED; - } +- if (con->request.http_version == HTTP_VERSION_1_1) { +- con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED; +- } - -+ - http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used); - joblist_append(srv, con); - } else { - size_t hlen = c - hctx->response_header->ptr + (eol == EOL_RN ? 4 : 2); - size_t blen = hctx->response_header->used - hlen - 1; +- http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used); +- joblist_append(srv, con); +- } else { +- size_t hlen = c - hctx->response_header->ptr + (eol == EOL_RN ? 4 : 2); +- size_t blen = hctx->response_header->used - hlen - 1; - -+ - /* a small hack: terminate after at the second \r */ - hctx->response_header->used = hlen + 1 - (eol == EOL_RN ? 2 : 1); - hctx->response_header->ptr[hlen - (eol == EOL_RN ? 2 : 1)] = '\0'; +- /* a small hack: terminate after at the second \r */ +- hctx->response_header->used = hlen + 1 - (eol == EOL_RN ? 2 : 1); +- hctx->response_header->ptr[hlen - (eol == EOL_RN ? 2 : 1)] = '\0'; - -+ - /* parse the response header */ - cgi_response_parse(srv, con, p, hctx->response_header, eol); +- /* parse the response header */ +- cgi_response_parse(srv, con, p, hctx->response_header, eol); - -+ - /* enable chunked-transfer-encoding */ - if (con->request.http_version == HTTP_VERSION_1_1 && - !(con->parsed_response & HTTP_CONTENT_LENGTH)) { - con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED; - } +- /* enable chunked-transfer-encoding */ +- if (con->request.http_version == HTTP_VERSION_1_1 && +- !(con->parsed_response & HTTP_CONTENT_LENGTH)) { +- con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED; +- } - +- if ((hctx->response->used != hlen) && blen > 0) { +- http_chunk_append_mem(srv, con, c + (eol == EOL_RN ? 4: 2), blen + 1); +- joblist_append(srv, con); +- } ++ if (ign[j]) continue; + - if ((hctx->response->used != hlen) && blen > 0) { - http_chunk_append_mem(srv, con, c + (eol == EOL_RN ? 4: 2), blen + 1); - joblist_append(srv, con); - } ++ if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Location"))) { ++ /* CGI/1.1 rev 03 - 7.2.1.2 */ ++ if (con->http_status == 0) con->http_status = 302; ++ } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Content-Length"))) { ++ have_content_length = 1; } -- + +- con->file_started = 1; ++ if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) { ++ ds = data_response_init(); ++ } ++ buffer_copy_string_buffer(ds->key, header->key); ++ buffer_copy_string_buffer(ds->value, header->value); + - con->file_started = 1; ++ array_insert_unique(con->response.headers, (data_unset *)ds); } - } else { - http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used); - joblist_append(srv, con); +- } else { +- http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used); +- joblist_append(srv, con); ++ ++ con->file_started = 1; ++ sess->state = CGI_STATE_READ_RESPONSE_CONTENT; ++ ++ if (con->request.http_version == HTTP_VERSION_1_1 && ++ !have_content_length) { ++ con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED; ++ } ++ ++ break; } - -#if 0 -+ -+#if 0 - log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), b->ptr); - #endif +- log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), b->ptr); +-#endif } - +- return FDEVENT_HANDLED_NOT_FINISHED; + - return FDEVENT_HANDLED_NOT_FINISHED; ++ /* FIXME: pass the response-header to the other plugins to ++ * setup the filter-queue ++ * ++ * - use next-queue instead of con->write_queue ++ */ ++ ++ /* copy the content to the next cq */ ++ for (c = sess->rb->first; c; c = c->next) { ++ http_chunk_append_mem(srv, con, c->mem->ptr + c->offset, c->mem->used - c->offset); ++ ++ c->offset = c->mem->used - 1; ++ } ++ ++ chunkqueue_remove_finished_chunks(sess->rb); ++ joblist_append(srv, con); ++ ++ return 0; } -@@ -470,45 +465,46 @@ +-static handler_t cgi_connection_close(server *srv, handler_ctx *hctx) { ++static handler_t cgi_connection_close(server *srv, connection *con, plugin_data *p) { ++ cgi_session *sess = con->plugin_ctx[p->id]; + int status; pid_t pid; - plugin_data *p; - connection *con; +- plugin_data *p; +- connection *con; - -+ - if (NULL == hctx) return HANDLER_GO_ON; +- if (NULL == hctx) return HANDLER_GO_ON; - -+ - p = hctx->plugin_data; - con = hctx->remote_conn; +- p = hctx->plugin_data; +- con = hctx->remote_conn; - + ++ if (NULL == sess) return HANDLER_GO_ON; if (con->mode != p->id) return HANDLER_GO_ON; -#ifndef __WIN32 @@ -16150,32 +17305,35 @@ * close cgi-connection */ - +- if (hctx->fd != -1) { + - if (hctx->fd != -1) { ++ if (sess->sock->fd != -1) { /* close connection to the cgi-script */ - fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); - fdevent_unregister(srv->ev, hctx->fd); +- fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); +- fdevent_unregister(srv->ev, hctx->fd); - -+ - if (close(hctx->fd)) { - log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno)); - } +- if (close(hctx->fd)) { +- log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno)); +- } - -+ - hctx->fd = -1; - hctx->fde_ndx = -1; +- hctx->fd = -1; +- hctx->fde_ndx = -1; ++ fdevent_event_del(srv->ev, sess->sock); ++ fdevent_unregister(srv->ev, sess->sock); } - -+ - pid = hctx->pid; +- pid = hctx->pid; - ++ ++ pid = sess->pid; + con->plugin_ctx[p->id] = NULL; - + /* is this a good idea ? */ - cgi_handler_ctx_free(hctx); +- cgi_handler_ctx_free(hctx); - ++ cgi_session_free(sess); + /* if waitpid hasn't been called by response.c yet, do it here */ if (pid) { @@ -16184,7 +17342,7 @@ switch(waitpid(pid, &status, WNOHANG)) { case 0: /* not finished yet */ -@@ -519,19 +515,19 @@ +@@ -519,35 +383,35 @@ case -1: /* */ if (errno == EINTR) break; @@ -16210,8 +17368,11 @@ log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno)); return HANDLER_ERROR; default: -@@ -541,13 +537,13 @@ - con->http_status = 500; + /* Send an error if we haven't sent any data yet */ + if (0 == con->file_started) { + connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST); +- con->http_status = 500; ++ if (con->http_status == 0) con->http_status = 500; con->mode = DIRECT; } - @@ -16226,7 +17387,7 @@ return HANDLER_GO_ON; } else { log_error_write(srv, __FILE__, __LINE__, "sd", "cgi died, pid:", pid); -@@ -555,20 +551,20 @@ +@@ -555,122 +419,126 @@ return HANDLER_GO_ON; } } @@ -16248,51 +17409,102 @@ static handler_t cgi_connection_close_callback(server *srv, connection *con, void *p_d) { plugin_data *p = p_d; - +- return cgi_connection_close(srv, con->plugin_ctx[p->id]); + - return cgi_connection_close(srv, con->plugin_ctx[p->id]); ++ return cgi_connection_close(srv, con, p); } -@@ -577,43 +573,43 @@ + + static handler_t cgi_handle_fdevent(void *s, void *ctx, int revents) { server *srv = (server *)s; - handler_ctx *hctx = ctx; - connection *con = hctx->remote_conn; +- handler_ctx *hctx = ctx; +- connection *con = hctx->remote_conn; - -+ - joblist_append(srv, con); +- joblist_append(srv, con); - -+ - if (hctx->fd == -1) { - log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), "invalid cgi-fd"); +- if (hctx->fd == -1) { +- log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), "invalid cgi-fd"); - -+ - return HANDLER_ERROR; - } +- return HANDLER_ERROR; +- } - ++ cgi_session *sess = ctx; ++ connection *con = sess->remote_con; ++ chunk *c; + if (revents & FDEVENT_IN) { - switch (cgi_demux_response(srv, hctx)) { - case FDEVENT_HANDLED_NOT_FINISHED: +- switch (cgi_demux_response(srv, hctx)) { +- case FDEVENT_HANDLED_NOT_FINISHED: ++ switch (sess->state) { ++ case CGI_STATE_READ_RESPONSE_HEADER: ++ /* parse the header and set file-started, the demuxer will care about it */ ++ joblist_append(srv, con); ++ break; - case FDEVENT_HANDLED_FINISHED: - /* we are done */ +- case FDEVENT_HANDLED_FINISHED: +- /* we are done */ - ++ case CGI_STATE_READ_RESPONSE_CONTENT: ++ /* just forward the content to the out-going queue */ + ++ chunkqueue_remove_finished_chunks(sess->rb); ++ ++ switch (srv->network_backend_read(srv, sess->remote_con, sess->sock, sess->rb)) { ++ case NETWORK_STATUS_CONNECTION_CLOSE: ++ fdevent_event_del(srv->ev, sess->sock); ++ ++ /* the connection is gone ++ * make the connect */ ++ sess->remote_con->file_finished = 1; #if 0 - log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), "finished"); +- log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), "finished"); ++ fdevent_event_del(srv->ev, sess->sock); #endif - cgi_connection_close(srv, hctx); +- cgi_connection_close(srv, hctx); - - /* if we get a IN|HUP and have read everything don't exec the close twice */ -+ -+ /* if we get a IN|HUP and have read everything don't exec the close twice */ - return HANDLER_FINISHED; - case FDEVENT_HANDLED_ERROR: - connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST); - con->http_status = 500; - con->mode = DIRECT; +- return HANDLER_FINISHED; +- case FDEVENT_HANDLED_ERROR: +- connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST); +- con->http_status = 500; +- con->mode = DIRECT; - +- log_error_write(srv, __FILE__, __LINE__, "s", "demuxer failed: "); ++ case NETWORK_STATUS_SUCCESS: ++ /* read even more, do we have all the content */ ++ ++ /* how much do we want to read ? */ ++ ++ /* call stream-decoder (HTTP-chunked, FastCGI, ... ) */ ++ ++ chunkqueue_remove_finished_chunks(sess->rb); ++ ++ /* copy the content to the next cq */ ++ for (c = sess->rb->first; c; c = c->next) { ++ if (c->mem->used == 0) continue; ++ ++ http_chunk_append_mem(srv, sess->remote_con, c->mem->ptr + c->offset, c->mem->used - c->offset); ++ ++ c->offset = c->mem->used - 1; ++ ++ } ++ chunkqueue_remove_finished_chunks(sess->rb); + - log_error_write(srv, __FILE__, __LINE__, "s", "demuxer failed: "); ++ if (sess->remote_con->file_finished) { ++ /* send final HTTP-Chunk packet */ ++ http_chunk_append_mem(srv, sess->remote_con, NULL, 0); ++ } ++ ++ break; ++ default: ++ ERROR("%s", "oops, we failed to read"); ++ break; ++ } ++ ++ joblist_append(srv, sess->remote_con); ++ break; ++ default: ++ TRACE("unexpected state for a FDEVENT_IN: %d", sess->state); break; } } @@ -16305,50 +17517,52 @@ + /* perhaps this issue is already handled */ if (revents & FDEVENT_HUP) { - /* check if we still have a unfinished header package which is a body in reality */ -@@ -623,54 +619,54 @@ - http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used); - joblist_append(srv, con); - } +- /* check if we still have a unfinished header package which is a body in reality */ +- if (con->file_started == 0 && +- hctx->response_header->used) { +- con->file_started = 1; +- http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used); +- joblist_append(srv, con); +- } - -+ - if (con->file_finished == 0) { - http_chunk_append_mem(srv, con, NULL, 0); - joblist_append(srv, con); - } +- if (con->file_finished == 0) { +- http_chunk_append_mem(srv, con, NULL, 0); +- joblist_append(srv, con); +- } - -+ con->file_finished = 1; - -+ - if (chunkqueue_is_empty(con->write_queue)) { - /* there is nothing left to write */ - connection_set_state(srv, con, CON_STATE_RESPONSE_END); - } else { - /* used the write-handler to finish the request on demand */ +- if (chunkqueue_is_empty(con->write_queue)) { +- /* there is nothing left to write */ +- connection_set_state(srv, con, CON_STATE_RESPONSE_END); +- } else { +- /* used the write-handler to finish the request on demand */ - -+ - } +- } - -+ - # if 0 - log_error_write(srv, __FILE__, __LINE__, "sddd", "got HUP from cgi", con->fd, hctx->fd, revents); - # endif +-# if 0 +- log_error_write(srv, __FILE__, __LINE__, "sddd", "got HUP from cgi", con->fd, hctx->fd, revents); +-# endif - +- /* rtsigs didn't liked the close */ +- cgi_connection_close(srv, hctx); ++ ++ fdevent_event_del(srv->ev, sess->sock); + - /* rtsigs didn't liked the close */ - cgi_connection_close(srv, hctx); ++ /* someone has to close this socket now :) */ ++ http_chunk_append_mem(srv, sess->remote_con, NULL, 0); ++ joblist_append(srv, sess->remote_con); } else if (revents & FDEVENT_ERR) { con->file_finished = 1; - + /* kill all connections to the cgi process */ - cgi_connection_close(srv, hctx); - #if 1 - log_error_write(srv, __FILE__, __LINE__, "s", "cgi-FDEVENT_ERR"); +- cgi_connection_close(srv, hctx); +-#if 1 +- log_error_write(srv, __FILE__, __LINE__, "s", "cgi-FDEVENT_ERR"); -#endif -+#endif - return HANDLER_ERROR; +- return HANDLER_ERROR; ++ fdevent_event_del(srv->ev, sess->sock); } - + @@ -16373,7 +17587,7 @@ if (env->size == 0) { env->size = 16; env->ptr = malloc(env->size * sizeof(*env->ptr)); -@@ -678,45 +674,45 @@ +@@ -678,45 +546,45 @@ env->size += 16; env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr)); } @@ -16430,7 +17644,7 @@ /* fork, execve */ switch (pid = fork()) { case 0: { -@@ -730,22 +726,22 @@ +@@ -730,44 +598,40 @@ char *c; const char *s; server_socket *srv_sock = con->srv_socket; @@ -16452,16 +17666,20 @@ close(to_cgi_fds[1]); - - /* HACK: +- * this is not nice, but it works +- * +- * we feed the stderr of the CGI to our errorlog, if possible + -+ /* HACK: - * this is not nice, but it works - * - * we feed the stderr of the CGI to our errorlog, if possible -@@ -754,20 +750,20 @@ - close(STDERR_FILENO); - dup2(srv->errorlog_fd, STDERR_FILENO); - } ++ /** ++ * FIXME: add a event-handler for STDERR_FILENO and let it LOG() + */ +- if (srv->errorlog_mode == ERRORLOG_FILE) { +- close(STDERR_FILENO); +- dup2(srv->errorlog_fd, STDERR_FILENO); +- } - ++ ++ close(STDERR_FILENO); + /* create environment */ env.ptr = NULL; @@ -16482,11 +17700,13 @@ (const void *) &(srv_sock->addr.ipv6.sin6_addr) : (const void *) &(srv_sock->addr.ipv4.sin_addr), b2, sizeof(b2)-1); -@@ -779,10 +775,10 @@ +@@ -779,10 +643,12 @@ cgi_env_add(&env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1")); s = get_http_version_name(con->request.http_version); - ++ ++ TRACE("http-version: %s (%d)", s, con->request.http_version); + cgi_env_add(&env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s)); - @@ -16496,7 +17716,7 @@ #ifdef HAVE_IPV6 ntohs(srv_sock->addr.plain.sa_family == AF_INET6 ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port) #else -@@ -790,10 +786,10 @@ +@@ -790,10 +656,10 @@ #endif ); cgi_env_add(&env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf)); @@ -16510,7 +17730,7 @@ (const void *) &(srv_sock->addr.ipv6.sin6_addr) : (const void *) &(srv_sock->addr.ipv4.sin_addr), b2, sizeof(b2)-1); -@@ -811,15 +807,18 @@ +@@ -811,15 +677,18 @@ cgi_env_add(&env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")); if (!buffer_is_empty(con->uri.query)) { cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_BUF_LEN(con->uri.query)); @@ -16533,7 +17753,7 @@ (const void *) &(con->dst_addr.ipv6.sin6_addr) : (const void *) &(con->dst_addr.ipv4.sin_addr), b2, sizeof(b2)-1); -@@ -828,7 +827,7 @@ +@@ -828,7 +697,7 @@ #endif cgi_env_add(&env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s)); @@ -16542,7 +17762,7 @@ #ifdef HAVE_IPV6 ntohs(con->dst_addr.plain.sa_family == AF_INET6 ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port) #else -@@ -836,19 +835,19 @@ +@@ -836,19 +705,19 @@ #endif ); cgi_env_add(&env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf)); @@ -16565,7 +17785,7 @@ /* for valgrind */ if (NULL != (s = getenv("LD_PRELOAD"))) { cgi_env_add(&env, CONST_STR_LEN("LD_PRELOAD"), s, strlen(s)); -@@ -863,24 +862,24 @@ +@@ -863,24 +732,24 @@ cgi_env_add(&env, CONST_STR_LEN("SYSTEMROOT"), s, strlen(s)); } #endif @@ -16597,7 +17817,7 @@ for (j = 0; j < ds->key->used - 1; j++) { char cr = '_'; if (light_isalpha(ds->key->ptr[j])) { -@@ -893,46 +892,46 @@ +@@ -893,46 +762,46 @@ p->tmp_buf->ptr[p->tmp_buf->used++] = cr; } p->tmp_buf->ptr[p->tmp_buf->used++] = '\0'; @@ -16658,7 +17878,7 @@ if (cgi_handler->used > 1) { args[i++] = cgi_handler->ptr; } -@@ -942,7 +941,7 @@ +@@ -942,7 +811,7 @@ /* search for the last / */ if (NULL != (c = strrchr(con->physical.path->ptr, '/'))) { *c = '\0'; @@ -16667,9 +17887,12 @@ /* change to the physical directory */ if (-1 == chdir(con->physical.path->ptr)) { log_error_write(srv, __FILE__, __LINE__, "ssb", "chdir failed:", strerror(errno), con->physical.path); -@@ -954,12 +953,12 @@ +@@ -952,14 +821,14 @@ + + /* we don't need the client socket */ for (i = 3; i < 256; i++) { - if (i != srv->errorlog_fd) close(i); +- if (i != srv->errorlog_fd) close(i); ++ close(i); } - + @@ -16683,7 +17906,13 @@ /* */ SEGFAULT(); break; -@@ -974,11 +973,11 @@ +@@ -969,16 +838,16 @@ + log_error_write(srv, __FILE__, __LINE__, "ss", "fork failed:", strerror(errno)); + break; + default: { +- handler_ctx *hctx; ++ cgi_session *sess; + /* father */ close(from_cgi_fds[1]); close(to_cgi_fds[0]); @@ -16697,7 +17926,7 @@ assert(chunkqueue_length(cq) == (off_t)con->request.content_length); /* there is content to send */ -@@ -993,16 +992,16 @@ +@@ -993,16 +862,16 @@ if (-1 == c->file.fd && /* open the file if not already open */ -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) { log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno)); @@ -16717,7 +17946,7 @@ strerror(errno), c->file.name, c->file.fd); close(from_cgi_fds[0]); -@@ -1012,7 +1011,7 @@ +@@ -1012,7 +881,7 @@ close(c->file.fd); c->file.fd = -1; @@ -16726,7 +17955,7 @@ /* chunk_reset() or chunk_free() will cleanup for us */ } -@@ -1020,7 +1019,7 @@ +@@ -1020,7 +889,7 @@ switch(errno) { case ENOSPC: con->http_status = 507; @@ -16735,7 +17964,7 @@ break; default: con->http_status = 403; -@@ -1033,7 +1032,7 @@ +@@ -1033,7 +902,7 @@ switch(errno) { case ENOSPC: con->http_status = 507; @@ -16744,7 +17973,7 @@ break; default: con->http_status = 403; -@@ -1056,103 +1055,100 @@ +@@ -1056,103 +925,95 @@ } close(to_cgi_fds[1]); @@ -16754,47 +17983,56 @@ con->mode = p->id; buffer_reset(con->physical.path); - -+ - hctx = cgi_handler_ctx_init(); +- hctx = cgi_handler_ctx_init(); - -+ - hctx->remote_conn = con; - hctx->plugin_data = p; - hctx->pid = pid; - hctx->fd = from_cgi_fds[0]; - hctx->fde_ndx = -1; +- hctx->remote_conn = con; +- hctx->plugin_data = p; +- hctx->pid = pid; +- hctx->fd = from_cgi_fds[0]; +- hctx->fde_ndx = -1; - -+ - con->plugin_ctx[p->id] = hctx; +- con->plugin_ctx[p->id] = hctx; - -+ - fdevent_register(srv->ev, hctx->fd, cgi_handle_fdevent, hctx); - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); +- fdevent_register(srv->ev, hctx->fd, cgi_handle_fdevent, hctx); +- fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); - +- if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) { + - if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) { ++ sess = cgi_session_init(); ++ ++ sess->remote_con = con; ++ sess->pid = pid; ++ ++ sess->sock->fd = from_cgi_fds[0]; ++ sess->sock->type = IOSOCKET_TYPE_PIPE; ++ ++ if (-1 == fdevent_fcntl_set(srv->ev, sess->sock)) { log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno)); - -+ - fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); - fdevent_unregister(srv->ev, hctx->fd); +- fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); +- fdevent_unregister(srv->ev, hctx->fd); - -+ - log_error_write(srv, __FILE__, __LINE__, "sd", "cgi close:", hctx->fd); +- log_error_write(srv, __FILE__, __LINE__, "sd", "cgi close:", hctx->fd); - -+ - close(hctx->fd); +- close(hctx->fd); - -+ - cgi_handler_ctx_free(hctx); +- cgi_handler_ctx_free(hctx); - -+ - con->plugin_ctx[p->id] = NULL; +- con->plugin_ctx[p->id] = NULL; - ++ ++ cgi_session_free(sess); + return -1; } - ++ ++ con->plugin_ctx[p->id] = sess; ++ ++ fdevent_register(srv->ev, sess->sock, cgi_handle_fdevent, sess); ++ fdevent_event_add(srv->ev, sess->sock, FDEVENT_IN); ++ ++ sess->state = CGI_STATE_READ_RESPONSE_HEADER; + break; } @@ -16853,6 +18091,8 @@ + if (fn->used == 0) return HANDLER_GO_ON; - ++ ++ TRACE("http-version: (%d)", con->request.http_version); + mod_cgi_patch_connection(srv, con, p); - @@ -16877,7 +18117,7 @@ buffer_reset(con->physical.path); return HANDLER_FINISHED; } -@@ -1160,7 +1156,7 @@ +@@ -1160,7 +1021,7 @@ break; } } @@ -16886,7 +18126,7 @@ return HANDLER_GO_ON; } -@@ -1168,11 +1164,11 @@ +@@ -1168,11 +1029,11 @@ plugin_data *p = p_d; size_t ndx; /* the trigger handle only cares about lonely PID which we have to wait for */ @@ -16900,7 +18140,7 @@ switch(waitpid(p->cgi_pid.ptr[ndx], &status, WNOHANG)) { case 0: /* not finished yet */ -@@ -1182,7 +1178,7 @@ +@@ -1182,7 +1043,7 @@ break; case -1: log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno)); @@ -16909,7 +18149,7 @@ return HANDLER_ERROR; default: -@@ -1193,16 +1189,16 @@ +@@ -1193,96 +1054,103 @@ } else { log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?"); } @@ -16929,28 +18169,57 @@ return HANDLER_GO_ON; } -@@ -1210,15 +1206,15 @@ + SUBREQUEST_FUNC(mod_cgi_handle_subrequest) { int status; plugin_data *p = p_d; - handler_ctx *hctx = con->plugin_ctx[p->id]; +- handler_ctx *hctx = con->plugin_ctx[p->id]; - ++ cgi_session *sess = con->plugin_ctx[p->id]; + if (con->mode != p->id) return HANDLER_GO_ON; - if (NULL == hctx) return HANDLER_GO_ON; +- if (NULL == hctx) return HANDLER_GO_ON; - ++ if (NULL == sess) return HANDLER_GO_ON; ++ ++ switch (cgi_demux_response(srv, con, p)) { ++ case 0: ++ break; ++ case 1: ++ cgi_connection_close(srv, con, p); ++ ++ /* if we get a IN|HUP and have read everything don't exec the close twice */ ++ return HANDLER_FINISHED; ++ case -1: ++ cgi_connection_close(srv, con, p); ++ ++ if (0 == con->http_status) con->http_status = 500; ++ connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST); ++ con->mode = DIRECT; ++ ++ return HANDLER_FINISHED; ++ } + #if 0 - log_error_write(srv, __FILE__, __LINE__, "sdd", "subrequest, pid =", hctx, hctx->pid); +- log_error_write(srv, __FILE__, __LINE__, "sdd", "subrequest, pid =", hctx, hctx->pid); -#endif -+#endif - if (hctx->pid == 0) return HANDLER_FINISHED; +- if (hctx->pid == 0) return HANDLER_FINISHED; -#ifndef __WIN32 +- switch(waitpid(hctx->pid, &status, WNOHANG)) { ++ log_error_write(srv, __FILE__, __LINE__, "sdd", "subrequest, pid =", sess, sess->pid); ++#endif ++ if (sess->pid == 0) return HANDLER_FINISHED; +#ifndef _WIN32 - switch(waitpid(hctx->pid, &status, WNOHANG)) { ++ switch(waitpid(sess->pid, &status, WNOHANG)) { case 0: /* we only have for events here if we don't have the header yet, -@@ -1228,61 +1224,61 @@ - return HANDLER_WAIT_FOR_EVENT; + * otherwise the event-handler will send us the incoming data */ +- if (con->file_started) return HANDLER_FINISHED; + +- return HANDLER_WAIT_FOR_EVENT; ++ if (!con->file_started) return HANDLER_WAIT_FOR_EVENT; ++ if (con->file_finished) return HANDLER_FINISHED; ++ ++ return HANDLER_GO_ON; case -1: if (errno == EINTR) return HANDLER_WAIT_FOR_EVENT; - @@ -16969,21 +18238,24 @@ con->mode = DIRECT; con->http_status = 500; - -+ - hctx->pid = 0; +- hctx->pid = 0; - -+ - fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); - fdevent_unregister(srv->ev, hctx->fd); +- fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); +- fdevent_unregister(srv->ev, hctx->fd); - -+ - if (close(hctx->fd)) { - log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno)); - } +- if (close(hctx->fd)) { +- log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno)); +- } - -+ - cgi_handler_ctx_free(hctx); +- cgi_handler_ctx_free(hctx); - ++ ++ sess->pid = 0; ++ ++ fdevent_event_del(srv->ev, sess->sock); ++ fdevent_unregister(srv->ev, sess->sock); ++ ++ cgi_session_free(sess); + con->plugin_ctx[p->id] = NULL; - @@ -16993,14 +18265,11 @@ - /* cgi process exited cleanly - * - * check if we already got the response -+ /* cgi process exited cleanly -+ * -+ * check if we already got the response - */ +- */ - -+ - if (!con->file_started) return HANDLER_WAIT_FOR_EVENT; +- if (!con->file_started) return HANDLER_WAIT_FOR_EVENT; - ++ con->file_finished = 1; + if (WIFEXITED(status)) { /* nothing */ @@ -17014,26 +18283,29 @@ + } - -+ - hctx->pid = 0; +- hctx->pid = 0; - -+ - fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); - fdevent_unregister(srv->ev, hctx->fd); +- fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); +- fdevent_unregister(srv->ev, hctx->fd); - -+ - if (close(hctx->fd)) { - log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno)); - } +- if (close(hctx->fd)) { +- log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno)); +- } - -+ - cgi_handler_ctx_free(hctx); +- cgi_handler_ctx_free(hctx); - ++ ++ sess->pid = 0; ++ ++ fdevent_event_del(srv->ev, sess->sock); ++ fdevent_unregister(srv->ev, sess->sock); ++ ++ cgi_session_free(sess); + con->plugin_ctx[p->id] = NULL; return HANDLER_FINISHED; } -@@ -1306,8 +1302,8 @@ +@@ -1306,8 +1174,8 @@ p->init = mod_cgi_init; p->cleanup = mod_cgi_free; p->set_defaults = mod_fastcgi_set_defaults; @@ -17045,7 +18317,7 @@ return 0; } --- ../lighttpd-1.4.11/src/mod_cml.c 2006-01-30 13:51:48.000000000 +0200 -+++ lighttpd-1.4.12/src/mod_cml.c 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_cml.c 2006-07-16 00:26:03.000000000 +0300 @@ -4,7 +4,6 @@ #include #include @@ -17377,7 +18649,7 @@ return 0; } --- ../lighttpd-1.4.11/src/mod_cml.h 2006-01-30 13:51:35.000000000 +0200 -+++ lighttpd-1.4.12/src/mod_cml.h 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_cml.h 2006-07-16 00:26:03.000000000 +0300 @@ -16,10 +16,10 @@ typedef struct { @@ -17413,7 +18685,7 @@ int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn); --- ../lighttpd-1.4.11/src/mod_cml_funcs.c 2005-11-17 16:15:08.000000000 +0200 -+++ lighttpd-1.4.12/src/mod_cml_funcs.c 2006-07-11 22:07:52.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_cml_funcs.c 2006-07-16 00:26:04.000000000 +0300 @@ -4,8 +4,7 @@ #include #include @@ -17759,7 +19031,7 @@ } #endif --- ../lighttpd-1.4.11/src/mod_cml_lua.c 2006-01-30 13:56:40.000000000 +0200 -+++ lighttpd-1.4.12/src/mod_cml_lua.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_cml_lua.c 2006-07-16 00:26:04.000000000 +0300 @@ -23,7 +23,7 @@ #ifdef USE_OPENSSL #define IN const @@ -18237,7 +19509,7 @@ } #else --- ../lighttpd-1.4.11/src/mod_compress.c 2005-11-18 13:49:14.000000000 +0200 -+++ lighttpd-1.4.12/src/mod_compress.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_compress.c 2006-07-16 00:26:04.000000000 +0300 @@ -2,7 +2,6 @@ #include @@ -19126,7 +20398,7 @@ return 0; } --- ../lighttpd-1.4.11/src/mod_dirlisting.c 2006-01-13 00:00:45.000000000 +0200 -+++ lighttpd-1.4.12/src/mod_dirlisting.c 2006-07-15 22:43:21.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_dirlisting.c 2006-07-16 00:26:04.000000000 +0300 @@ -1,11 +1,9 @@ #include #include @@ -19692,7 +20964,7 @@ return 0; } --- ../lighttpd-1.4.11/src/mod_evasive.c 2006-01-04 15:24:51.000000000 +0200 -+++ lighttpd-1.4.12/src/mod_evasive.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_evasive.c 2006-07-16 00:26:04.000000000 +0300 @@ -31,100 +31,97 @@ typedef struct { @@ -19870,7 +21142,7 @@ return 0; } --- ../lighttpd-1.4.11/src/mod_evhost.c 2005-08-17 10:42:03.000000000 +0300 -+++ lighttpd-1.4.12/src/mod_evhost.c 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_evhost.c 2006-07-16 00:26:03.000000000 +0300 @@ -7,10 +7,12 @@ #include "response.h" #include "stat_cache.h" @@ -20244,7 +21516,7 @@ } --- ../lighttpd-1.4.11/src/mod_expire.c 2005-11-03 09:52:13.000000000 +0200 -+++ lighttpd-1.4.12/src/mod_expire.c 2006-07-11 22:07:52.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_expire.c 2006-07-16 00:26:04.000000000 +0300 @@ -12,8 +12,8 @@ #include "stat_cache.h" @@ -20653,7 +21925,7 @@ return 0; } --- ../lighttpd-1.4.11/src/mod_fastcgi.c 2006-03-09 13:18:39.000000000 +0200 -+++ lighttpd-1.4.12/src/mod_fastcgi.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_fastcgi.c 2006-07-18 13:03:40.000000000 +0300 @@ -1,5 +1,4 @@ #include -#include @@ -20949,7 +22221,7 @@ size_t size; size_t used; } char_array; -@@ -306,44 +308,44 @@ +@@ -306,55 +308,54 @@ typedef struct { PLUGIN_DATA; buffer_uint fcgi_request_id; @@ -21010,9 +22282,11 @@ - + size_t request_id; - int fd; /* fd to the fastcgi process */ - int fde_ndx; /* index into the fd-event buffer */ -@@ -352,9 +354,9 @@ +- int fd; /* fd to the fastcgi process */ +- int fde_ndx; /* index into the fd-event buffer */ ++ iosocket *sock; + + pid_t pid; int got_proc; int send_content_body; @@ -21024,7 +22298,7 @@ connection *remote_conn; /* dumb pointer */ plugin_data *plugin_data; /* dumb pointer */ } handler_ctx; -@@ -380,7 +382,7 @@ +@@ -380,7 +381,7 @@ return di; } @@ -21033,7 +22307,7 @@ * they will be moved to a statistics.c later */ int status_counter_inc(server *srv, const char *s, size_t len) { data_integer *di = status_counter_get_counter(srv, s, len); -@@ -429,7 +431,7 @@ +@@ -429,7 +430,7 @@ CLEAN(".connected"); CLEAN(".load"); @@ -21042,7 +22316,7 @@ #define CLEAN(x) \ fastcgi_status_copy_procname(b, host, NULL); \ -@@ -438,33 +440,32 @@ +@@ -438,33 +439,30 @@ CLEAN(".load"); @@ -21059,8 +22333,7 @@ hctx = calloc(1, sizeof(*hctx)); assert(hctx); - -+ - hctx->fde_ndx = -1; +- hctx->fde_ndx = -1; - - hctx->response_header = buffer_init(); - @@ -21069,9 +22342,10 @@ hctx->state = FCGI_STATE_INIT; hctx->proc = NULL; - -+ - hctx->fd = -1; +- hctx->fd = -1; - ++ ++ hctx->sock = iosocket_init(); + hctx->reconnects = 0; hctx->send_content_body = 1; @@ -21084,7 +22358,7 @@ return hctx; } -@@ -473,10 +474,9 @@ +@@ -473,12 +471,13 @@ hctx->host->load--; hctx->host = NULL; } @@ -21095,8 +22369,12 @@ + chunkqueue_free(hctx->http_rb); chunkqueue_free(hctx->wb); ++ iosocket_free(hctx->sock); ++ free(hctx); -@@ -488,21 +488,21 @@ + } + +@@ -488,21 +487,21 @@ f = calloc(1, sizeof(*f)); f->unixsocket = buffer_init(); f->connection_name = buffer_init(); @@ -21123,7 +22401,7 @@ free(f); } -@@ -519,13 +519,13 @@ +@@ -519,13 +518,13 @@ f->bin_env = array_init(); f->bin_env_copy = array_init(); f->strip_request_uri = buffer_init(); @@ -21139,7 +22417,7 @@ buffer_free(h->id); buffer_free(h->host); buffer_free(h->unixsocket); -@@ -534,49 +534,49 @@ +@@ -534,49 +533,49 @@ buffer_free(h->strip_request_uri); array_free(h->bin_env); array_free(h->bin_env_copy); @@ -21203,7 +22481,7 @@ free(f); } -@@ -625,24 +625,25 @@ +@@ -625,24 +624,25 @@ assert(fe->hosts); } @@ -21236,7 +22514,7 @@ return p; } -@@ -650,81 +651,82 @@ +@@ -650,81 +650,82 @@ FREE_FUNC(mod_fastcgi_free) { plugin_data *p = p_d; buffer_uint *r = &(p->fcgi_request_id); @@ -21341,7 +22619,7 @@ if (env->size == 0) { env->size = 16; env->ptr = malloc(env->size * sizeof(*env->ptr)); -@@ -732,9 +734,9 @@ +@@ -732,9 +733,9 @@ env->size += 16; env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr)); } @@ -21353,7 +22631,7 @@ return 0; } -@@ -753,15 +755,15 @@ +@@ -753,15 +754,15 @@ if (env->size == 0) { env->size = 16; env->ptr = malloc(env->size * sizeof(*env->ptr)); @@ -21372,7 +22650,7 @@ start = b->ptr + i + 1; break; default: -@@ -794,7 +796,7 @@ +@@ -794,7 +795,7 @@ return 0; } @@ -21381,7 +22659,7 @@ plugin_data *p, fcgi_extension_host *host, fcgi_proc *proc) { -@@ -806,31 +808,27 @@ +@@ -806,31 +807,27 @@ #endif struct sockaddr_in fcgi_addr_in; struct sockaddr *fcgi_addr; @@ -21420,7 +22698,7 @@ socket_type = AF_UNIX; fcgi_addr = (struct sockaddr *) &fcgi_addr_un; -@@ -844,108 +842,108 @@ +@@ -844,108 +841,108 @@ #endif } else { fcgi_addr_in.sin_family = AF_INET; @@ -21560,7 +22838,7 @@ arg.ptr = NULL; arg.size = 0; arg.used = 0; -@@ -955,18 +953,18 @@ +@@ -955,18 +952,18 @@ dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO); close(fcgi_fd); } @@ -21582,7 +22860,7 @@ if (NULL != (ge = getenv(ds->value->ptr))) { env_add(&env, CONST_BUF_LEN(ds->value), ge, strlen(ge)); } -@@ -974,39 +972,39 @@ +@@ -974,39 +971,39 @@ } else { for (i = 0; environ[i]; i++) { char *eq; @@ -21630,7 +22908,7 @@ /* change to the physical directory */ if (-1 == chdir(arg.ptr[0])) { *c = '/'; -@@ -1018,12 +1016,12 @@ +@@ -1018,12 +1015,12 @@ /* exec the cgi */ execve(arg.ptr[0], arg.ptr, env.ptr); @@ -21647,7 +22925,7 @@ break; } case -1: -@@ -1031,17 +1029,17 @@ +@@ -1031,17 +1028,17 @@ break; default: /* father */ @@ -21668,7 +22946,7 @@ "pid not found:", strerror(errno)); return -1; default: -@@ -1049,10 +1047,10 @@ +@@ -1049,10 +1046,10 @@ "the fastcgi-backend", host->bin_path, "failed to start:"); /* the child should not terminate at all */ if (WIFEXITED(status)) { @@ -21682,7 +22960,7 @@ "if you try do run PHP as FastCGI backend make sure you use the FastCGI enabled version.\n" "You can find out if it is the right one by executing 'php -v' and it should display '(cgi-fcgi)' " "in the output, NOT (cgi) NOR (cli)\n" -@@ -1060,8 +1058,8 @@ +@@ -1060,8 +1057,8 @@ log_error_write(srv, __FILE__, __LINE__, "s", "If this is PHP on Gentoo add fastcgi to the USE flags"); } else if (WIFSIGNALED(status)) { @@ -21693,7 +22971,7 @@ WTERMSIG(status)); if (WTERMSIG(status) == 11) { -@@ -1071,8 +1069,8 @@ +@@ -1071,8 +1068,8 @@ "If this is PHP try to remove the byte-code caches for now and try again."); } } else { @@ -21704,7 +22982,7 @@ status); } return -1; -@@ -1082,26 +1080,26 @@ +@@ -1082,26 +1079,26 @@ proc->pid = child; proc->last_used = srv->cur_ts; proc->is_local = 1; @@ -21736,7 +23014,7 @@ return 0; } -@@ -1111,93 +1109,93 @@ +@@ -1111,93 +1108,93 @@ data_unset *du; size_t i = 0; buffer *fcgi_mode = buffer_init(); @@ -21866,7 +23144,7 @@ { "check-local", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 5 */ { "port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 6 */ { "min-procs-not-working", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 7 this is broken for now */ -@@ -1205,28 +1203,28 @@ +@@ -1205,28 +1202,28 @@ { "max-load-per-proc", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 9 */ { "idle-timeout", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 10 */ { "disable-time", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 11 */ @@ -21905,7 +23183,7 @@ buffer_copy_string_buffer(host->id, da_host->key); host->check_local = 1; -@@ -1238,13 +1236,13 @@ +@@ -1238,13 +1235,13 @@ host->disable_time = 60; host->break_scriptfilename_for_php = 0; host->allow_xsendfile = 0; /* handle X-LIGHTTPD-send-file */ @@ -21921,7 +23199,7 @@ fcv[5].destination = &(host->check_local); fcv[6].destination = &(host->port); fcv[7].destination = &(host->min_procs); -@@ -1252,35 +1250,35 @@ +@@ -1252,35 +1249,35 @@ fcv[9].destination = &(host->max_load_per_proc); fcv[10].destination = &(host->idle_timeout); fcv[11].destination = &(host->disable_time); @@ -21967,7 +23245,7 @@ da_ext->key, " => (", da_host->key, " ( ..."); -@@ -1288,37 +1286,37 @@ +@@ -1288,37 +1285,37 @@ } } else { /* tcp/ip */ @@ -22016,7 +23294,7 @@ if (s->debug) { log_error_write(srv, __FILE__, __LINE__, "ssbsdsbsdsd", "--- fastcgi spawning local", -@@ -1328,7 +1326,7 @@ +@@ -1328,7 +1325,7 @@ "\n\tmin-procs:", host->min_procs, "\n\tmax-procs:", host->max_procs); } @@ -22025,7 +23303,7 @@ for (pno = 0; pno < host->min_procs; pno++) { fcgi_proc *proc; -@@ -1343,7 +1341,7 @@ +@@ -1343,7 +1340,7 @@ buffer_append_string(proc->unixsocket, "-"); buffer_append_long(proc->unixsocket, pno); } @@ -22034,7 +23312,7 @@ if (s->debug) { log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd", "--- fastcgi spawning", -@@ -1351,7 +1349,7 @@ +@@ -1351,7 +1348,7 @@ "\n\tsocket", host->unixsocket, "\n\tcurrent:", pno, "/", host->min_procs); } @@ -22043,7 +23321,7 @@ if (fcgi_spawn_connection(srv, p, host, proc)) { log_error_write(srv, __FILE__, __LINE__, "s", "[ERROR]: spawning fcgi failed."); -@@ -1359,35 +1357,35 @@ +@@ -1359,35 +1356,35 @@ } fastcgi_status_init(srv, p->statuskey, host, proc); @@ -22086,7 +23364,7 @@ if (!buffer_is_empty(fcgi_mode)) { if (strcmp(fcgi_mode->ptr, "responder") == 0) { host->mode = FCGI_RESPONDER; -@@ -1411,16 +1409,16 @@ +@@ -1411,16 +1408,16 @@ } } } @@ -22106,7 +23384,7 @@ return 0; } -@@ -1429,13 +1427,13 @@ +@@ -1429,13 +1426,13 @@ size_t m = 0; size_t i; buffer_uint *r = &(p->fcgi_request_id); @@ -22122,7 +23400,7 @@ if (r->size == 0) { r->size = 16; r->ptr = malloc(sizeof(*r->ptr) * r->size); -@@ -1443,54 +1441,54 @@ +@@ -1443,54 +1440,55 @@ r->size += 16; r->ptr = realloc(r->ptr, sizeof(*r->ptr) * r->size); } @@ -22172,16 +23450,23 @@ - + if (con->mode != p->id) { - WP(); +- WP(); return; } - +- if (hctx->fd != -1) { +- fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); +- fdevent_unregister(srv->ev, hctx->fd); +- close(hctx->fd); +- srv->cur_fds--; + - if (hctx->fd != -1) { - fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); - fdevent_unregister(srv->ev, hctx->fd); - close(hctx->fd); - srv->cur_fds--; ++ if (hctx->sock->fd != -1) { ++ fdevent_event_del(srv->ev, hctx->sock); ++ fdevent_unregister(srv->ev, hctx->sock); ++ closesocket(hctx->sock->fd); ++ hctx->sock->fd = -1; ++ ++ srv->cur_fds--; } - + @@ -22197,7 +23482,7 @@ status_counter_dec(srv, CONST_STR_LEN("fastcgi.active-requests")); fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc); -@@ -1509,39 +1507,39 @@ +@@ -1509,101 +1507,101 @@ if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "ssdsbsd", @@ -22254,10 +23539,17 @@ + * */ - if (hctx->fd != -1) { -@@ -1551,59 +1549,59 @@ +- if (hctx->fd != -1) { +- fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); +- fdevent_unregister(srv->ev, hctx->fd); +- close(hctx->fd); ++ if (hctx->sock->fd != -1) { ++ fdevent_event_del(srv->ev, hctx->sock); ++ fdevent_unregister(srv->ev, hctx->sock); ++ close(hctx->sock->fd); srv->cur_fds--; - hctx->fd = -1; +- hctx->fd = -1; ++ hctx->sock->fd = -1; } - + @@ -22376,8 +23668,9 @@ + fcgi_extension_host *host = hctx->host; fcgi_proc *proc = hctx->proc; - int fcgi_fd = hctx->fd; +- int fcgi_fd = hctx->fd; - ++ int fcgi_fd = hctx->sock->fd; + memset(&fcgi_addr, 0, sizeof(fcgi_addr)); - @@ -22619,8 +23912,9 @@ /* get the server-side of the connection to the client */ our_addr_len = sizeof(our_addr); - +- if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) { + - if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) { ++ if (-1 == getsockname(con->sock->fd, &(our_addr.plain), &our_addr_len)) { s = inet_ntop_cache_get_ip(srv, &(srv_sock->addr)); } else { s = inet_ntop_cache_get_ip(srv, &(our_addr)); @@ -22969,7 +24263,7 @@ buffer_append_string_len(packet->b, c->mem->ptr + c->offset + offset, weHave); /* we only skipped the first 8 bytes as they are the fcgi header */ -@@ -2380,65 +2278,37 @@ +@@ -2380,65 +2278,42 @@ } chunkqueue_remove_finished_chunks(hctx->rb); @@ -23018,24 +24312,32 @@ - - /* this should be catched by the b > 0 above */ - assert(r); ++ handler_t ret; - b->used = r + 1; /* one extra for the fake \0 */ - b->ptr[b->used - 1] = '\0'; - } else { - log_error_write(srv, __FILE__, __LINE__, "ssdsb", -+ switch(srv->network_backend_read(srv, con, hctx->fd, hctx->rb)) { -+ case NETWORK_STATUS_WAIT_FOR_EVENT: -+ /* we are only triggered when there is a event */ -+ log_error_write(srv, __FILE__, __LINE__, "ssdsb", - "unexpected end-of-file (perhaps the fastcgi process died):", - "pid:", proc->pid, - "socket:", proc->connection_name); +- "unexpected end-of-file (perhaps the fastcgi process died):", +- "pid:", proc->pid, +- "socket:", proc->connection_name); - ++ /* in case we read nothing, check the return code ++ * if we got something, be happy :) ++ * ++ * Ok, to be honest: ++ * - it is fine to receive a EAGAIN on a second read() call ++ * - it might be fine they we get a con-close on a second read() call */ ++ switch(srv->network_backend_read(srv, con, hctx->sock, hctx->rb)) { ++ case NETWORK_STATUS_WAIT_FOR_EVENT: ++ /* a EAGAIN after we read exactly the chunk-size */ ++ ++ ERROR("%s", "oops, got a EAGAIN even if we just got call for the event, wired"); + return -1; + case NETWORK_STATUS_SUCCESS: + break; + default: -+ log_error_write(srv, __FILE__, __LINE__, "s", "fastcgi-read failed"); ++ ERROR("reading from fastcgi socket failed (fd=%d)", hctx->sock->fd); return -1; } @@ -23047,7 +24349,7 @@ while (fin == 0) { fastcgi_response_packet packet; -@@ -2454,92 +2324,135 @@ +@@ -2454,92 +2329,136 @@ /* is the header already finished */ if (0 == con->file_started) { @@ -23110,6 +24412,9 @@ - con->file_started = 1; + chunkqueue_remove_finished_chunks(hctx->http_rb); ++ ++ con->http_status = p->resp->status; ++ hctx->send_content_body = 1; - if (host->mode == FCGI_AUTHORIZER && - (con->http_status == 0 || @@ -23128,8 +24433,6 @@ - http_chunk_append_file(srv, con, ds->value, 0, sce->st.st_size); - hctx->send_content_body = 0; /* ignore the content */ - joblist_append(srv, con); -+ con->http_status = p->resp->status; -+ + /* handle the header fields */ + if (host->mode == FCGI_AUTHORIZER) { + /* auth mode is a bit different */ @@ -23244,7 +24547,7 @@ if (host->mode != FCGI_AUTHORIZER || !(con->http_status == 0 || con->http_status == 200)) { -@@ -2547,39 +2460,39 @@ +@@ -2547,39 +2466,39 @@ http_chunk_append_mem(srv, con, NULL, 0); joblist_append(srv, con); } @@ -23293,7 +24596,7 @@ */ switch (proc->state) { case PROC_STATE_KILLED: -@@ -2592,13 +2505,13 @@ +@@ -2592,13 +2511,13 @@ break; case PROC_STATE_OVERLOADED: if (srv->cur_ts <= proc->disabled_until) break; @@ -23312,7 +24615,7 @@ host->unixsocket); break; case PROC_STATE_DIED_WAIT_FOR_PID: -@@ -2606,7 +2519,7 @@ +@@ -2606,7 +2525,7 @@ if (!proc->is_local) break; /* the child should not terminate at all */ @@ -23321,7 +24624,7 @@ switch(waitpid(proc->pid, &status, WNOHANG)) { case 0: /* child is still alive */ -@@ -2616,45 +2529,45 @@ +@@ -2616,45 +2535,45 @@ default: if (WIFEXITED(status)) { #if 0 @@ -23379,7 +24682,7 @@ if (fcgi_spawn_connection(srv, p, host, proc)) { log_error_write(srv, __FILE__, __LINE__, "s", "ERROR: spawning fcgi failed."); -@@ -2662,18 +2575,18 @@ +@@ -2662,18 +2581,18 @@ } } else { if (srv->cur_ts <= proc->disabled_until) break; @@ -23403,7 +24706,7 @@ return 0; } -@@ -2682,19 +2595,19 @@ +@@ -2682,19 +2601,19 @@ fcgi_extension_host *host= hctx->host; connection *con = hctx->remote_conn; fcgi_proc *proc; @@ -23427,15 +24730,16 @@ hctx->proc->disabled_until = srv->cur_ts + 10; hctx->proc->state = PROC_STATE_DIED; -@@ -2705,12 +2618,12 @@ +@@ -2705,12 +2624,12 @@ if (hctx->state == FCGI_STATE_CONNECT_DELAYED) { int socket_error; socklen_t socket_error_len = sizeof(socket_error); - + /* try to finish the connect() */ - if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) { +- if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) { - log_error_write(srv, __FILE__, __LINE__, "ss", ++ if (0 != getsockopt(hctx->sock->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) { + log_error_write(srv, __FILE__, __LINE__, "ss", "getsockopt failed:", strerror(errno)); - @@ -23443,7 +24747,7 @@ hctx->proc->disabled_until = srv->cur_ts + 10; hctx->proc->state = PROC_STATE_DIED; -@@ -2719,12 +2632,12 @@ +@@ -2719,12 +2638,12 @@ if (socket_error != 0) { if (!hctx->proc->is_local || p->conf.debug) { /* local procs get restarted */ @@ -23459,7 +24763,7 @@ hctx->proc->disabled_until = srv->cur_ts + 5; if (hctx->proc->is_local) { -@@ -2732,17 +2645,17 @@ +@@ -2732,17 +2651,17 @@ } else { hctx->proc->state = PROC_STATE_DIED; } @@ -23481,7 +24785,7 @@ hctx->state = FCGI_STATE_PREPARE_WRITE; } -@@ -2755,14 +2668,14 @@ +@@ -2755,14 +2674,14 @@ /* do we have a running process for this host (max-procs) ? */ hctx->proc = NULL; @@ -23494,25 +24798,28 @@ + /* all childs are dead */ if (proc == NULL) { - hctx->fde_ndx = -1; +- hctx->fde_ndx = -1; - ++ hctx->sock->fde_ndx = -1; + return HANDLER_ERROR; } -@@ -2775,50 +2688,50 @@ +@@ -2775,50 +2694,50 @@ } ret = host->unixsocket->used ? AF_UNIX : AF_INET; - +- if (-1 == (hctx->fd = socket(ret, SOCK_STREAM, 0))) { + - if (-1 == (hctx->fd = socket(ret, SOCK_STREAM, 0))) { ++ if (-1 == (hctx->sock->fd = socket(ret, SOCK_STREAM, 0))) { if (errno == EMFILE || errno == EINTR) { - log_error_write(srv, __FILE__, __LINE__, "sd", -+ log_error_write(srv, __FILE__, __LINE__, "sd", - "wait for fd at connection:", con->fd); +- "wait for fd at connection:", con->fd); - ++ log_error_write(srv, __FILE__, __LINE__, "sd", ++ "wait for fd at connection:", con->sock->fd); + return HANDLER_WAIT_FOR_FD; } @@ -23523,17 +24830,20 @@ "socket failed:", strerror(errno), srv->cur_fds, srv->max_fds); return HANDLER_ERROR; } - hctx->fde_ndx = -1; +- hctx->fde_ndx = -1; - ++ hctx->sock->fde_ndx = -1; + srv->cur_fds++; - -+ - fdevent_register(srv->ev, hctx->fd, fcgi_handle_fdevent, hctx); +- fdevent_register(srv->ev, hctx->fd, fcgi_handle_fdevent, hctx); - -+ - if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) { +- if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) { - log_error_write(srv, __FILE__, __LINE__, "ss", ++ ++ fdevent_register(srv->ev, hctx->sock, fcgi_handle_fdevent, hctx); ++ ++ if (-1 == fdevent_fcntl_set(srv->ev, hctx->sock)) { + log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed:", strerror(errno)); - @@ -23551,9 +24861,10 @@ case CONNECTION_DELAYED: /* connection is in progress, wait for an event and call getsockopt() below */ - -+ - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); +- fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); - ++ ++ fdevent_event_add(srv->ev, hctx->sock, FDEVENT_OUT); + fcgi_set_state(srv, hctx, FCGI_STATE_CONNECT_DELAYED); return HANDLER_WAIT_FOR_EVENT; @@ -23566,7 +24877,7 @@ "backend is overloaded, we disable it for a 2 seconds and send the request to another backend instead:", "reconnects:", hctx->reconnects, "load:", host->load); -@@ -2831,7 +2744,7 @@ +@@ -2831,7 +2750,7 @@ buffer_append_string(p->statuskey, ".overloaded"); status_counter_inc(srv, CONST_BUF_LEN(p->statuskey)); @@ -23575,7 +24886,7 @@ return HANDLER_ERROR; case CONNECTION_DEAD: /* we got a hard error from the backend like -@@ -2840,19 +2753,19 @@ +@@ -2840,19 +2759,19 @@ * * for check if the host is back in 5 seconds * */ @@ -23599,7 +24910,7 @@ fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc); buffer_append_string(p->statuskey, ".died"); -@@ -2863,19 +2776,19 @@ +@@ -2863,19 +2782,19 @@ /* everything is ok, go on */ fcgi_set_state(srv, hctx, FCGI_STATE_PREPARE_WRITE); @@ -23623,7 +24934,7 @@ status_counter_inc(srv, CONST_STR_LEN("fastcgi.requests")); status_counter_inc(srv, CONST_STR_LEN("fastcgi.active-requests")); -@@ -2898,9 +2811,9 @@ +@@ -2898,9 +2817,9 @@ if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "ssdsbsd", @@ -23636,7 +24947,7 @@ "load:", hctx->proc->load); } -@@ -2908,62 +2821,63 @@ +@@ -2908,74 +2827,75 @@ if (hctx->request_id == 0) { hctx->request_id = fcgi_requestid_new(srv, p); } else { @@ -23656,7 +24967,7 @@ /* fall through */ case FCGI_STATE_WRITE: - ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb); -+ ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb); ++ ret = srv->network_backend_write(srv, con, hctx->sock, hctx->wb); chunkqueue_remove_finished_chunks(hctx->wb); - @@ -23711,8 +25022,9 @@ return HANDLER_ERROR; case EAGAIN: case EINTR: - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); +- fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); - ++ fdevent_event_add(srv->ev, hctx->sock, FDEVENT_OUT); + return HANDLER_WAIT_FOR_EVENT; default: @@ -23724,16 +25036,23 @@ return HANDLER_ERROR; } } -@@ -2975,7 +2889,7 @@ + + if (hctx->wb->bytes_out == hctx->wb->bytes_in) { + /* we don't need the out event anymore */ +- fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); +- fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); ++ fdevent_event_del(srv->ev, hctx->sock); ++ fdevent_event_add(srv->ev, hctx->sock, FDEVENT_IN); fcgi_set_state(srv, hctx, FCGI_STATE_READ); } else { - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); +- fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); - ++ fdevent_event_add(srv->ev, hctx->sock, FDEVENT_OUT); + return HANDLER_WAIT_FOR_EVENT; } -@@ -2987,7 +2901,7 @@ +@@ -2987,7 +2907,7 @@ log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state"); return HANDLER_ERROR; } @@ -23742,7 +25061,7 @@ return HANDLER_WAIT_FOR_EVENT; } -@@ -2996,18 +2910,18 @@ +@@ -2996,18 +2916,18 @@ * */ SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) { plugin_data *p = p_d; @@ -23765,7 +25084,7 @@ * and when the host died and we have to select a new one */ if (hctx->host == NULL) { size_t k; -@@ -3016,23 +2930,23 @@ +@@ -3016,23 +2936,23 @@ /* get best server */ for (k = 0, ndx = -1; k < hctx->ext->used; k++) { host = hctx->ext->hosts[k]; @@ -23793,7 +25112,7 @@ con->http_status = 500; con->mode = DIRECT; -@@ -3040,16 +2954,16 @@ +@@ -3040,16 +2960,16 @@ } host = hctx->ext->hosts[ndx]; @@ -23816,7 +25135,7 @@ * * as soon as hctx->host is unassigned, decrease the load again */ hctx->host->load++; -@@ -3063,7 +2977,7 @@ +@@ -3063,7 +2983,7 @@ case HANDLER_ERROR: proc = hctx->proc; host = hctx->host; @@ -23825,7 +25144,7 @@ if (hctx->state == FCGI_STATE_INIT || hctx->state == FCGI_STATE_CONNECT_DELAYED) { if (proc) host->active_procs--; -@@ -3078,7 +2992,7 @@ +@@ -3078,7 +2998,7 @@ return HANDLER_WAIT_FOR_FD; } else { fcgi_connection_close(srv, hctx); @@ -23834,7 +25153,7 @@ buffer_reset(con->physical.path); con->mode = DIRECT; con->http_status = 500; -@@ -3088,12 +3002,12 @@ +@@ -3088,12 +3008,12 @@ } } else { fcgi_connection_close(srv, hctx); @@ -23849,7 +25168,7 @@ return HANDLER_FINISHED; } case HANDLER_WAIT_FOR_EVENT: -@@ -3115,7 +3029,7 @@ +@@ -3115,7 +3035,7 @@ handler_ctx *hctx = ctx; connection *con = hctx->remote_conn; plugin_data *p = hctx->plugin_data; @@ -23858,7 +25177,7 @@ fcgi_proc *proc = hctx->proc; fcgi_extension_host *host= hctx->host; -@@ -3125,8 +3039,8 @@ +@@ -3125,8 +3045,8 @@ case 0: break; case 1: @@ -23869,7 +25188,7 @@ (con->http_status == 200 || con->http_status == 0)) { /* -@@ -3136,26 +3050,26 @@ +@@ -3136,26 +3056,26 @@ */ buffer_copy_string_buffer(con->physical.doc_root, host->docroot); @@ -23901,7 +25220,7 @@ switch(waitpid(proc->pid, &status, WNOHANG)) { case 0: /* child is still alive */ -@@ -3165,60 +3079,61 @@ +@@ -3165,60 +3085,61 @@ default: /* the child should not terminate at all */ if (WIFEXITED(status)) { @@ -23982,7 +25301,7 @@ connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST); buffer_reset(con->physical.path); con->http_status = 500; -@@ -3226,76 +3141,76 @@ +@@ -3226,76 +3147,76 @@ } else { /* response might have been already started, kill the connection */ fcgi_connection_close(srv, hctx); @@ -24082,7 +25401,7 @@ "fcgi: got a FDEVENT_ERR. Don't know why."); /* kill all connections to the fastcgi process */ -@@ -3304,45 +3219,42 @@ +@@ -3304,45 +3225,42 @@ fcgi_connection_close(srv, hctx); joblist_append(srv, con); } @@ -24142,7 +25461,7 @@ static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, int uri_path_handler) { plugin_data *p = p_d; -@@ -3351,16 +3263,16 @@ +@@ -3351,16 +3269,16 @@ buffer *fn; fcgi_extension *extension = NULL; fcgi_extension_host *host = NULL; @@ -24162,7 +25481,7 @@ fcgi_patch_connection(srv, con, p); /* fastcgi.map-extensions maps extensions to existing fastcgi.server entries -@@ -3368,24 +3280,24 @@ +@@ -3368,24 +3286,24 @@ * fastcgi.map-extensions = ( ".php3" => ".php" ) * * fastcgi.server = ( ".php" => ... ) @@ -24193,7 +25512,7 @@ /* we can reuse k here */ for (k = 0; k < p->conf.exts->used; k++) { extension = p->conf.exts->exts[k]; -@@ -3407,15 +3319,15 @@ +@@ -3407,15 +3325,15 @@ /* check if extension matches */ for (k = 0; k < p->conf.exts->used; k++) { size_t ct_len; /* length of the config entry */ @@ -24214,7 +25533,7 @@ /* check extension in the form "/fcgi_pattern" */ if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) { break; -@@ -3441,10 +3353,10 @@ +@@ -3441,10 +3359,10 @@ continue; } @@ -24227,7 +25546,7 @@ if (!host) { /* sorry, we don't have a server alive for this ext */ buffer_reset(con->physical.path); -@@ -3459,72 +3371,72 @@ +@@ -3459,72 +3377,72 @@ "on", extension->key, "are down."); } @@ -24325,7 +25644,7 @@ con->uri.path->used -= con->request.pathinfo->used - 1; con->uri.path->ptr[con->uri.path->used - 1] = '\0'; } -@@ -3532,19 +3444,19 @@ +@@ -3532,19 +3450,19 @@ } else { handler_ctx *hctx; hctx = handler_ctx_init(); @@ -24350,7 +25669,7 @@ if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi"); } -@@ -3566,19 +3478,19 @@ +@@ -3566,19 +3484,19 @@ JOBLIST_FUNC(mod_fastcgi_handle_joblist) { plugin_data *p = p_d; handler_ctx *hctx = con->plugin_ctx[p->id]; @@ -24358,22 +25677,25 @@ + if (hctx == NULL) return HANDLER_GO_ON; - if (hctx->fd != -1) { +- if (hctx->fd != -1) { ++ if (hctx->sock->fd != -1) { switch (hctx->state) { case FCGI_STATE_READ: - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); +- fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); - ++ fdevent_event_add(srv->ev, hctx->sock, FDEVENT_IN); + break; case FCGI_STATE_CONNECT_DELAYED: case FCGI_STATE_WRITE: - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); +- fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); - ++ fdevent_event_add(srv->ev, hctx->sock, FDEVENT_OUT); + break; case FCGI_STATE_INIT: /* at reconnect */ -@@ -3595,7 +3507,7 @@ +@@ -3595,7 +3513,7 @@ static handler_t fcgi_connection_close_callback(server *srv, connection *con, void *p_d) { plugin_data *p = p_d; @@ -24382,7 +25704,7 @@ fcgi_connection_close(srv, con->plugin_ctx[p->id]); return HANDLER_GO_ON; -@@ -3604,16 +3516,39 @@ +@@ -3604,16 +3522,39 @@ TRIGGER_FUNC(mod_fastcgi_handle_trigger) { plugin_data *p = p_d; size_t i, j, n; @@ -24428,7 +25750,7 @@ /* check all childs if they are still up */ for (i = 0; i < srv->config_context->used; i++) { -@@ -3628,45 +3563,45 @@ +@@ -3628,45 +3569,45 @@ fcgi_extension *ex; ex = exts->exts[j]; @@ -24487,7 +25809,7 @@ if (buffer_is_empty(host->unixsocket)) { proc->port = host->port + proc->id; } else { -@@ -3674,13 +3609,13 @@ +@@ -3674,13 +3615,13 @@ buffer_append_string(proc->unixsocket, "-"); buffer_append_long(proc->unixsocket, proc->id); } @@ -24503,7 +25825,7 @@ proc->prev = NULL; proc->next = host->first; if (host->first) { -@@ -3688,56 +3623,56 @@ +@@ -3688,56 +3629,56 @@ } host->first = proc; } @@ -24583,7 +25905,7 @@ switch (waitpid(proc->pid, &status, WNOHANG)) { case 0: /* child still running after timeout, good */ -@@ -3745,10 +3680,10 @@ +@@ -3745,10 +3686,10 @@ case -1: if (errno != EINTR) { /* no PID found ? should never happen */ @@ -24596,7 +25918,7 @@ #if 0 if (errno == ECHILD) { /* someone else has cleaned up for us */ -@@ -3762,25 +3697,26 @@ +@@ -3762,25 +3703,26 @@ /* the child should not terminate at all */ if (WIFEXITED(status)) { if (proc->state != PROC_STATE_KILLED) { @@ -24629,7 +25951,7 @@ } } } -@@ -3804,8 +3740,8 @@ +@@ -3804,8 +3746,8 @@ p->handle_subrequest = mod_fastcgi_handle_subrequest; p->handle_joblist = mod_fastcgi_handle_joblist; p->handle_trigger = mod_fastcgi_handle_trigger; @@ -24641,7 +25963,7 @@ return 0; } --- ../lighttpd-1.4.11/src/mod_flv_streaming.c 2006-03-07 14:06:26.000000000 +0200 -+++ lighttpd-1.4.12/src/mod_flv_streaming.c 2006-07-11 22:07:52.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_flv_streaming.c 2006-07-16 00:26:04.000000000 +0300 @@ -23,35 +23,35 @@ typedef struct { @@ -24915,7 +26237,7 @@ return 0; } --- ../lighttpd-1.4.11/src/mod_indexfile.c 2005-09-30 01:08:53.000000000 +0300 -+++ lighttpd-1.4.12/src/mod_indexfile.c 2006-07-15 22:43:21.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_indexfile.c 2006-07-16 00:26:04.000000000 +0300 @@ -12,6 +12,8 @@ #include "stat_cache.h" @@ -25188,7 +26510,7 @@ return 0; } --- ../lighttpd-1.4.11/src/mod_mysql_vhost.c 2006-01-14 20:35:10.000000000 +0200 -+++ lighttpd-1.4.12/src/mod_mysql_vhost.c 2006-07-11 22:07:52.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_mysql_vhost.c 2006-07-16 00:26:04.000000000 +0300 @@ -1,13 +1,18 @@ -#include #include @@ -25702,7 +27024,7 @@ } #else --- ../lighttpd-1.4.11/src/mod_proxy.c 2006-01-31 13:01:22.000000000 +0200 -+++ lighttpd-1.4.12/src/mod_proxy.c 2006-07-15 22:43:21.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_proxy.c 2006-07-18 13:03:40.000000000 +0300 @@ -1,6 +1,5 @@ #include @@ -25803,7 +27125,7 @@ } proxy_connection_state_t; enum { PROXY_STDOUT, PROXY_END_REQUEST }; -@@ -93,19 +107,17 @@ +@@ -93,19 +107,16 @@ typedef struct { proxy_connection_state_t state; time_t state_timestamp; @@ -25816,10 +27138,11 @@ chunkqueue *wb; - +- int fd; /* fd to the proxy process */ +- int fde_ndx; /* index into the fd-event buffer */ + chunkqueue *rb; + - int fd; /* fd to the proxy process */ - int fde_ndx; /* index into the fd-event buffer */ ++ iosocket *fd; /* fd to the proxy process */ size_t path_info_offset; /* start of path_info in uri.path */ - @@ -25827,7 +27150,7 @@ connection *remote_conn; /* dump pointer */ plugin_data *plugin_data; /* dump pointer */ } handler_ctx; -@@ -116,69 +128,88 @@ +@@ -116,69 +127,89 @@ static handler_ctx * handler_ctx_init() { handler_ctx * hctx; @@ -25845,11 +27168,12 @@ hctx->wb = chunkqueue_init(); + hctx->rb = chunkqueue_init(); ++ ++ hctx->fd = iosocket_init(); - hctx->fd = -1; - hctx->fde_ndx = -1; +- hctx->fd = -1; +- hctx->fde_ndx = -1; - -+ return hctx; } @@ -25859,6 +27183,8 @@ chunkqueue_free(hctx->wb); - + chunkqueue_free(hctx->rb); ++ ++ iosocket_free(hctx->fd); + free(hctx); } @@ -26126,7 +27452,7 @@ array_insert_unique(dfa->value, (data_unset *)df); array_insert_unique(s->extensions, (data_unset *)dfa); } else { -@@ -328,19 +360,19 @@ +@@ -328,67 +360,76 @@ } } } @@ -26148,10 +27474,12 @@ - + if (hctx->fd != -1) { - fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); +- fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); ++ fdevent_event_del(srv->ev, hctx->fd); fdevent_unregister(srv->ev, hctx->fd); -@@ -348,47 +380,56 @@ - close(hctx->fd); + +- close(hctx->fd); ++ close(hctx->fd->fd); srv->cur_fds--; } - @@ -26169,8 +27497,9 @@ + plugin_data *p = hctx->plugin_data; data_proxy *host= hctx->host; - int proxy_fd = hctx->fd; +- int proxy_fd = hctx->fd; - ++ int proxy_fd = hctx->fd->fd; + memset(&proxy_addr, 0, sizeof(proxy_addr)); - @@ -26316,8 +27645,8 @@ + + if (buffer_is_empty(ds->value) || buffer_is_empty(ds->key)) continue; + -+ if (!buffer_is_equal_string(ds->key, CONST_STR_LEN("Connection"))) continue; -+ if (!buffer_is_equal_string(ds->key, CONST_STR_LEN("Keep-Alive"))) continue; ++ if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Connection"))) continue; ++ if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Keep-Alive"))) continue; + + buffer_append_string_buffer(b, ds->key); + BUFFER_APPEND_STRING_CONST(b, ": "); @@ -26345,7 +27674,7 @@ switch (req_c->type) { case FILE_CHUNK: -@@ -507,223 +550,161 @@ +@@ -507,223 +550,150 @@ req_c->offset += weHave; req_cq->bytes_out += weHave; @@ -26372,19 +27701,16 @@ hctx->state = state; hctx->state_timestamp = srv->cur_ts; - -+ - return 0; - } - +- return 0; +-} +- -static int proxy_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) { - char *s, *ns; - int http_response_status = -1; - - UNUSED(srv); -+static void chunkqueue_print(chunkqueue *cq) { -+ chunk *c; - +- - /* \r\n -> \0\0 */ - - buffer_copy_string_buffer(p->parse_response, in); @@ -26465,15 +27791,12 @@ - - array_insert_unique(con->response.headers, (data_unset *)ds); - } -+ for (c = cq->first; c; c = c->next) { -+ fprintf(stderr, "%s", c->mem->ptr + c->offset); - } +- } - -- return 0; -+ fprintf(stderr, "\r\n"); + return 0; } -- + static int proxy_demux_response(server *srv, handler_ctx *hctx) { - int fin = 0; - int b; @@ -26481,7 +27804,7 @@ - plugin_data *p = hctx->plugin_data; connection *con = hctx->remote_conn; - int proxy_fd = hctx->fd; +- int proxy_fd = hctx->fd; - - /* check how much we have to read */ - if (ioctl(hctx->fd, FIONREAD, &b)) { @@ -26491,13 +27814,12 @@ + chunkqueue *next_queue = NULL; + chunk *c = NULL; + -+ switch(srv->network_backend_read(srv, con, proxy_fd, hctx->rb)) { ++ switch(srv->network_backend_read(srv, con, hctx->fd, hctx->rb)) { + case NETWORK_STATUS_SUCCESS: + /* we got content */ + break; + case NETWORK_STATUS_WAIT_FOR_EVENT: -+ /* the ioctl will return WAIT_FOR_EVENT on a read */ -+ if (0 == con->file_started) return -1; ++ return 0; + case NETWORK_STATUS_CONNECTION_CLOSE: + /* we are done, get out of here */ + con->file_finished = 1; @@ -26604,12 +27926,7 @@ + /* some headers are ignored by default */ + for (j = 0; ign[j]; j++) { + if (0 == strcasecmp(ign[j], header->key->ptr)) break; - } -- -- con->file_started = 1; -- if (blen) { -- http_chunk_append_mem(srv, con, c + 4, blen + 1); -- joblist_append(srv, con); ++ } + if (ign[j]) continue; + + if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Location"))) { @@ -26618,11 +27935,16 @@ + } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Content-Length"))) { + have_content_length = 1; } -- hctx->response->used = 0; +- +- con->file_started = 1; +- if (blen) { +- http_chunk_append_mem(srv, con, c + 4, blen + 1); +- joblist_append(srv, con); + + if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) { + ds = data_response_init(); -+ } + } +- hctx->response->used = 0; + buffer_copy_string_buffer(ds->key, header->key); + buffer_copy_string_buffer(ds->value, header->value); + @@ -26685,7 +28007,7 @@ } -@@ -731,12 +712,12 @@ +@@ -731,32 +701,32 @@ data_proxy *host= hctx->host; plugin_data *p = hctx->plugin_data; connection *con = hctx->remote_conn; @@ -26702,12 +28024,14 @@ + switch(hctx->state) { case PROXY_STATE_INIT: - if (-1 == (hctx->fd = socket(AF_INET, SOCK_STREAM, 0))) { -@@ -744,19 +725,19 @@ +- if (-1 == (hctx->fd = socket(AF_INET, SOCK_STREAM, 0))) { ++ if (-1 == (hctx->fd->fd = socket(AF_INET, SOCK_STREAM, 0))) { + log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed: ", strerror(errno)); return HANDLER_ERROR; } - hctx->fde_ndx = -1; +- hctx->fde_ndx = -1; - ++ hctx->fd->fde_ndx = -1; + srv->cur_fds++; - @@ -26729,7 +28053,7 @@ case PROXY_STATE_CONNECT: /* try to finish the connect() */ if (hctx->state == PROXY_STATE_INIT) { -@@ -764,16 +745,16 @@ +@@ -764,16 +734,16 @@ switch (proxy_establish_connection(srv, hctx)) { case 1: proxy_set_state(srv, hctx, PROXY_STATE_CONNECT); @@ -26737,32 +28061,36 @@ + /* connection is in progress, wait for an event and call getsockopt() below */ - -+ - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); +- fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); - ++ ++ fdevent_event_add(srv->ev, hctx->fd, FDEVENT_OUT); + return HANDLER_WAIT_FOR_EVENT; case -1: /* if ECONNREFUSED choose another connection -> FIXME */ - hctx->fde_ndx = -1; +- hctx->fde_ndx = -1; - ++ hctx->fd->fde_ndx = -1; + return HANDLER_ERROR; default: /* everything is ok, go on */ -@@ -782,152 +763,152 @@ +@@ -782,152 +752,152 @@ } else { int socket_error; socklen_t socket_error_len = sizeof(socket_error); - - /* we don't need it anymore */ +- fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); + + /* we don't need it anymore */ - fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); ++ fdevent_event_del(srv->ev, hctx->fd); /* try to finish the connect() */ - if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) { +- if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) { - log_error_write(srv, __FILE__, __LINE__, "ss", ++ if (0 != getsockopt(hctx->fd->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) { + log_error_write(srv, __FILE__, __LINE__, "ss", "getsockopt failed:", strerror(errno)); - @@ -26818,7 +28146,7 @@ + return HANDLER_ERROR; + case NETWORK_STATUS_WAIT_FOR_EVENT: + -+ fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); ++ fdevent_event_add(srv->ev, hctx->fd, FDEVENT_OUT); + + return HANDLER_WAIT_FOR_EVENT; } @@ -26827,11 +28155,14 @@ - proxy_set_state(srv, hctx, PROXY_STATE_READ); + proxy_set_state(srv, hctx, PROXY_STATE_RESPONSE_HEADER); - fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); +- fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); +- fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); ++ fdevent_event_del(srv->ev, hctx->fd); ++ fdevent_event_add(srv->ev, hctx->fd, FDEVENT_IN); } else { - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); +- fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); - ++ fdevent_event_add(srv->ev, hctx->fd, FDEVENT_OUT); + return HANDLER_WAIT_FOR_EVENT; } @@ -26930,8 +28261,9 @@ + log_error_write(srv, __FILE__, __LINE__, "sbdd", "proxy-server disabled:", host->host, host->port, - hctx->fd); +- hctx->fd); - ++ hctx->fd->fd); + /* disable this server */ host->is_disabled = 1; @@ -26957,7 +28289,7 @@ */ return HANDLER_WAIT_FOR_FD; -@@ -938,7 +919,7 @@ +@@ -938,7 +908,7 @@ default: break; } @@ -26966,7 +28298,7 @@ if (con->file_started == 1) { return HANDLER_FINISHED; } else { -@@ -951,13 +932,14 @@ +@@ -951,13 +921,14 @@ handler_ctx *hctx = ctx; connection *con = hctx->remote_conn; plugin_data *p = hctx->plugin_data; @@ -26985,12 +28317,12 @@ "proxy: fdevent-in", hctx->state); } -@@ -965,11 +947,15 @@ +@@ -965,11 +936,15 @@ case 0: break; case 1: + log_error_write(srv, __FILE__, __LINE__, "sd", -+ "proxy: request done", hctx->fd); ++ "proxy: request done", hctx->fd->fd); hctx->host->usage--; - + @@ -27003,7 +28335,7 @@ joblist_append(srv, con); return HANDLER_FINISHED; case -1: -@@ -982,53 +968,53 @@ +@@ -982,53 +957,53 @@ /* response might have been already started, kill the connection */ connection_set_state(srv, con, CON_STATE_ERROR); } @@ -27071,7 +28403,7 @@ return HANDLER_FINISHED; } -@@ -1038,13 +1024,13 @@ +@@ -1038,13 +1013,13 @@ joblist_append(srv, con); } else if (revents & FDEVENT_ERR) { /* kill all connections to the proxy process */ @@ -27087,7 +28419,7 @@ return HANDLER_FINISHED; } -@@ -1058,44 +1044,48 @@ +@@ -1058,44 +1033,48 @@ buffer *fn; data_array *extension = NULL; size_t path_info_offset; @@ -27149,7 +28481,7 @@ if (0 != (pi_offset = strchr(fn->ptr + ct_len + 1, '/'))) { path_info_offset = pi_offset - fn->ptr; } -@@ -1106,12 +1096,14 @@ +@@ -1106,12 +1085,14 @@ break; } } @@ -27166,7 +28498,7 @@ log_error_write(srv, __FILE__, __LINE__, "s", "proxy - ext found"); } -@@ -1120,34 +1112,34 @@ +@@ -1120,34 +1101,34 @@ /* hash balancing */ if (p->conf.debug) { @@ -27214,7 +28546,7 @@ } } -@@ -1155,19 +1147,20 @@ +@@ -1155,19 +1136,20 @@ case PROXY_BALANCE_FAIR: /* fair balancing */ if (p->conf.debug) { @@ -27245,7 +28577,7 @@ } } -@@ -1175,89 +1168,100 @@ +@@ -1175,89 +1157,100 @@ case PROXY_BALANCE_RR: /* round robin */ if (p->conf.debug) { @@ -27406,7 +28738,7 @@ proxy_connection_close(srv, con->plugin_ctx[p->id]); return HANDLER_GO_ON; -@@ -1276,11 +1280,11 @@ +@@ -1276,11 +1269,11 @@ size_t i, n, k; for (i = 0; i < srv->config_context->used; i++) { plugin_config *s = p->config_storage[i]; @@ -27421,7 +28753,7 @@ for (k = 0; k < s->extensions->used; k++) { data_array *extension = (data_array *)s->extensions->data[k]; -@@ -1290,8 +1294,8 @@ +@@ -1290,8 +1283,8 @@ if (!host->is_disabled || srv->cur_ts - host->disable_ts < 5) continue; @@ -27432,7 +28764,7 @@ "proxy - re-enabled:", host->host, host->port); -@@ -1317,8 +1321,8 @@ +@@ -1317,8 +1310,8 @@ p->handle_uri_clean = mod_proxy_check_extension; p->handle_subrequest = mod_proxy_handle_subrequest; p->handle_trigger = mod_proxy_trigger; @@ -27443,234 +28775,2294 @@ + return 0; } ---- ../lighttpd-1.4.11/src/mod_redirect.c 2006-02-08 15:38:06.000000000 +0200 -+++ lighttpd-1.4.12/src/mod_redirect.c 2006-07-11 22:07:52.000000000 +0300 -@@ -22,35 +22,35 @@ - PLUGIN_DATA; - buffer *match_buf; - buffer *location; -- +--- ../lighttpd-1.4.11/src/mod_proxy_core.c 1970-01-01 03:00:00.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_proxy_core.c 2006-07-18 13:03:40.000000000 +0300 +@@ -0,0 +1,1451 @@ ++#include ++#include ++#include ++#include + - plugin_config **config_storage; -- -- plugin_config conf; ++#include "buffer.h" ++#include "array.h" ++#include "log.h" ++ ++#include "base.h" ++#include "plugin.h" ++#include "joblist.h" ++#include "sys-files.h" ++#include "inet_ntop_cache.h" ++#include "http_resp.h" ++#include "http_chunk.h" ++#include "crc32.h" ++ ++#include "mod_proxy_core_pool.h" ++#include "mod_proxy_core_backend.h" ++#include "mod_proxy_core_backlog.h" ++ ++typedef enum { ++ PROXY_PROTOCOL_UNSET, ++ PROXY_PROTOCOL_HTTP, ++ PROXY_PROTOCOL_HTTPS, ++ PROXY_PROTOCOL_FASTCGI, ++ PROXY_PROTOCOL_SCGI ++} proxy_protocol_t; ++ ++typedef struct { ++ proxy_backends *backends; ++ ++ proxy_backlog *backlog; ++ ++ int debug; ++ ++ proxy_balance_t balancer; ++ proxy_protocol_t protocol; ++} plugin_config; ++ ++typedef struct { ++ PLUGIN_DATA; ++ ++ http_resp *resp; ++ ++ array *possible_balancers; ++ array *possible_protocols; ++ ++ /* for parsing only */ ++ array *backends_arr; ++ buffer *protocol_buf; ++ buffer *balance_buf; ++ ++ plugin_config **config_storage; + + plugin_config conf; - } plugin_data; - - INIT_FUNC(mod_redirect_init) { - plugin_data *p; -- ++} plugin_data; + - p = calloc(1, sizeof(*p)); -- ++int array_insert_int(array *a, const char *key, int val) { ++ data_integer *di; + - p->match_buf = buffer_init(); - p->location = buffer_init(); -- ++ if (NULL == (di = (data_integer *)array_get_unused_element(a, TYPE_INTEGER))) { ++ di = data_integer_init(); ++ } + - return p; - } - - FREE_FUNC(mod_redirect_free) { - plugin_data *p = p_d; -- ++ buffer_copy_string(di->key, key); ++ di->value = val; ++ array_insert_unique(a, (data_unset *)di); + - 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]; -- ++ return 0; ++} + - pcre_keyvalue_buffer_free(s->redirect); -- ++INIT_FUNC(mod_proxy_core_init) { ++ plugin_data *p; + - free(s); - } - free(p->config_storage); -@@ -59,9 +59,9 @@ - - buffer_free(p->match_buf); - buffer_free(p->location); -- ++ p = calloc(1, sizeof(*p)); + - free(p); -- ++ /* create some backends as long as we don't have the config-parser */ + - return HANDLER_GO_ON; - } - -@@ -69,195 +69,137 @@ - plugin_data *p = p_d; - data_unset *du; - size_t i = 0; -- -- config_values_t cv[] = { ++ p->possible_balancers = array_init(); ++ array_insert_int(p->possible_balancers, "fair", PROXY_BALANCE_FAIR); ++ array_insert_int(p->possible_balancers, "hash", PROXY_BALANCE_RR); ++ array_insert_int(p->possible_balancers, "round-robin", PROXY_BALANCE_HASH); ++ ++ p->possible_protocols = array_init(); ++ array_insert_int(p->possible_protocols, "http", PROXY_PROTOCOL_HTTP); ++ array_insert_int(p->possible_protocols, "fastcgi", PROXY_PROTOCOL_FASTCGI); ++ array_insert_int(p->possible_protocols, "scgi", PROXY_PROTOCOL_SCGI); ++ array_insert_int(p->possible_protocols, "https", PROXY_PROTOCOL_HTTPS); ++ ++ p->balance_buf = buffer_init(); ++ p->protocol_buf = buffer_init(); ++ p->backends_arr = array_init(); ++ ++ p->resp = http_response_init(); ++ ++ return p; ++} ++ ++FREE_FUNC(mod_proxy_core_free) { ++ plugin_data *p = p_d; ++ ++ 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; ++ ++ proxy_backends_free(s->backends); ++ proxy_backlog_free(s->backlog); ++ ++ ++ free(s); ++ } ++ free(p->config_storage); ++ } ++ ++ array_free(p->possible_protocols); ++ array_free(p->possible_balancers); ++ array_free(p->backends_arr); ++ ++ buffer_free(p->balance_buf); ++ buffer_free(p->protocol_buf); ++ ++ http_response_free(p->resp); ++ ++ free(p); ++ ++ return HANDLER_GO_ON; ++} ++ ++SETDEFAULTS_FUNC(mod_proxy_core_set_defaults) { ++ plugin_data *p = p_d; ++ size_t i, j; + + config_values_t cv[] = { - { "url.redirect", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ - { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } - }; -- ++ { "proxy-core.backends", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ ++ { "proxy-core.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ ++ { "proxy-core.balancer", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */ ++ { "proxy-core.protocol", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */ ++ { 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 *)); + - /* 0 */ - p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *)); -- ++ for (i = 0; i < srv->config_context->used; i++) { ++ plugin_config *s; ++ array *ca; ++ proxy_backend *backend; + - for (i = 0; i < srv->config_context->used; i++) { - plugin_config *s; - size_t j; - array *ca; - data_array *da = (data_array *)du; -- ++ array_reset(p->backends_arr); ++ buffer_reset(p->balance_buf); ++ buffer_reset(p->protocol_buf); + - s = calloc(1, sizeof(plugin_config)); - s->redirect = pcre_keyvalue_buffer_init(); -- ++ s = malloc(sizeof(plugin_config)); ++ s->debug = 0; ++ s->balancer = PROXY_BALANCE_UNSET; ++ s->protocol = PROXY_PROTOCOL_UNSET; ++ s->backends = proxy_backends_init(); ++ s->backlog = proxy_backlog_init(); + - cv[0].destination = s->redirect; -- ++ cv[0].destination = p->backends_arr; ++ cv[1].destination = &(s->debug); ++ cv[2].destination = p->balance_buf; /* parse into a constant */ ++ cv[3].destination = p->protocol_buf; /* parse into a constant */ + - p->config_storage[i] = s; - ca = ((data_config *)srv->config_context->data[i])->value; -- ++ buffer_reset(p->balance_buf); + - if (0 != config_insert_values_global(srv, ca, cv)) { - return HANDLER_ERROR; - } -- ++ p->config_storage[i] = s; ++ ca = ((data_config *)srv->config_context->data[i])->value; + - if (NULL == (du = array_get_element(ca, "url.redirect"))) { - /* no url.redirect defined */ - continue; - } -- ++ if (0 != config_insert_values_global(srv, ca, cv)) { ++ return HANDLER_ERROR; ++ } + - if (du->type != TYPE_ARRAY) { -- log_error_write(srv, __FILE__, __LINE__, "sss", -+ log_error_write(srv, __FILE__, __LINE__, "sss", - "unexpected type for key: ", "url.redirect", "array of strings"); -- ++ if (!buffer_is_empty(p->balance_buf)) { ++ data_integer *di; ++ ++ if (NULL == (di = (data_integer *)array_get_element(p->possible_balancers, BUF_STR(p->balance_buf)))) { ++ ERROR("proxy.balance has to be on of 'fair', 'round-robin', 'hash', got %s", BUF_STR(p->balance_buf)); + - return HANDLER_ERROR; - } -- ++ return HANDLER_ERROR; ++ } + - da = (data_array *)du; -- ++ s->balancer = di->value; ++ } + - for (j = 0; j < da->value->used; j++) { - if (da->value->data[j]->type != TYPE_STRING) { -- log_error_write(srv, __FILE__, __LINE__, "sssbs", -- "unexpected type for key: ", -- "url.redirect", -+ log_error_write(srv, __FILE__, __LINE__, "sssbs", -+ "unexpected type for key: ", -+ "url.redirect", - "[", da->value->data[j]->key, "](string)"); -- ++ if (!buffer_is_empty(p->protocol_buf)) { ++ data_integer *di; ++ ++ if (NULL == (di = (data_integer *)array_get_element(p->possible_protocols, BUF_STR(p->protocol_buf)))) { ++ ERROR("proxy.balance has to be on of 'fair', 'round-robin', 'hash', got %s", BUF_STR(p->protocol_buf)); + - return HANDLER_ERROR; - } -- -- if (0 != pcre_keyvalue_buffer_append(s->redirect, ++ return HANDLER_ERROR; ++ } + -+ if (0 != pcre_keyvalue_buffer_append(s->redirect, - ((data_string *)(da->value->data[j]))->key->ptr, - ((data_string *)(da->value->data[j]))->value->ptr)) { -- -- log_error_write(srv, __FILE__, __LINE__, "sb", ++ s->protocol = di->value; ++ } + -+ log_error_write(srv, __FILE__, __LINE__, "sb", - "pcre-compile failed for", da->value->data[j]->key); - } - } - } -- ++ backend = proxy_backend_init(); + - return HANDLER_GO_ON; - } - #ifdef HAVE_PCRE_H - static int mod_redirect_patch_connection(server *srv, connection *con, plugin_data *p) { - size_t i, j; - plugin_config *s = p->config_storage[0]; -- ++ /* check if the backends have a valid host-name */ ++ for (j = 0; j < p->backends_arr->used; j++) { ++ data_string *ds = (data_string *)p->backends_arr->data[j]; + - p->conf.redirect = s->redirect; -- ++ /* the values should be ips or hostnames */ ++ if (0 != proxy_address_pool_add_string(backend->address_pool, ds->value)) { ++ return HANDLER_ERROR; ++ } ++ } + - /* 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]; -- ++ proxy_backends_add(s->backends, backend); ++ } + - /* condition didn't match */ - if (!config_check_cond(srv, con, dc)) continue; -- ++ return HANDLER_GO_ON; ++} + - /* merge config */ - for (j = 0; j < dc->value->used; j++) { - data_unset *du = dc->value->data[j]; -- + - if (0 == strcmp(du->key->ptr, "url.redirect")) { - p->conf.redirect = s->redirect; - p->conf.context = dc; - } - } - } -- ++typedef enum { ++ PROXY_STATE_UNSET, ++ PROXY_STATE_CONNECTING, ++ PROXY_STATE_CONNECTED, ++ PROXY_STATE_WRITE_REQUEST_HEADER, ++ PROXY_STATE_WRITE_REQUEST_BODY, ++ PROXY_STATE_READ_RESPONSE_HEADER, ++ PROXY_STATE_READ_RESPONSE_BODY ++} proxy_state_t; + - return 0; - } - #endif - static handler_t mod_redirect_uri_handler(server *srv, connection *con, void *p_data) { - #ifdef HAVE_PCRE_H - plugin_data *p = p_data; -- size_t i; -+ int i; - -- /* -+ /* - * REWRITE URL -- * -+ * - * e.g. redirect /base/ to /index.php?section=base -- * ++typedef struct { ++ proxy_connection *proxy_con; ++ proxy_backend *proxy_backend; ++ ++ connection *remote_con; ++ ++ array *request_headers; ++ ++ int is_chunked; ++ ++ /** ++ * chunkqueues ++ * - the encoded_rb is the raw network stuff ++ * - the rb is filtered through the stream decoder + * - */ -- ++ * - wb is the normal bytes stream ++ * - encoded_wb is encoded for the network by the stream encoder ++ */ ++ chunkqueue *recv; ++ chunkqueue *recv_raw; ++ chunkqueue *send_raw; ++ chunkqueue *send; ++ ++ off_t bytes_read; ++ off_t content_length; + - mod_redirect_patch_connection(srv, con, p); -- ++ proxy_state_t state; ++} proxy_session; + - buffer_copy_string_buffer(p->match_buf, con->request.uri); -- -- for (i = 0; i < p->conf.redirect->used; i++) { -- pcre *match; -- pcre_extra *extra; -- const char *pattern; -- size_t pattern_len; -- int n; -- pcre_keyvalue *kv = p->conf.redirect->kv[i]; --# define N 10 -- int ovec[N * 3]; -- -- match = kv->key; -- extra = kv->key_extra; -- pattern = kv->value->ptr; -- pattern_len = kv->value->used - 1; -- -- if ((n = pcre_exec(match, extra, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) { -- if (n != PCRE_ERROR_NOMATCH) { -- log_error_write(srv, __FILE__, __LINE__, "sd", -- "execution error while matching: ", n); ++proxy_session *proxy_session_init(void) { ++ proxy_session *sess; ++ ++ sess = calloc(1, sizeof(*sess)); ++ ++ sess->state = PROXY_STATE_UNSET; ++ sess->request_headers = array_init(); ++ ++ sess->recv = chunkqueue_init(); ++ sess->recv_raw = chunkqueue_init(); ++ sess->send_raw = chunkqueue_init(); ++ sess->send = chunkqueue_init(); ++ ++ sess->is_chunked = 0; ++ ++ return sess; ++} ++ ++void proxy_session_free(proxy_session *sess) { ++ if (!sess) return; ++ ++ array_free(sess->request_headers); ++ ++ chunkqueue_free(sess->recv); ++ chunkqueue_free(sess->recv_raw); ++ chunkqueue_free(sess->send_raw); ++ chunkqueue_free(sess->send); ++ ++ free(sess); ++} ++ ++handler_t proxy_connection_connect(proxy_connection *con) { ++ int fd; ++ ++ if (-1 == (fd = socket(con->address->addr.plain.sa_family, SOCK_STREAM, 0))) { ++ } ++ ++ fcntl(fd, F_SETFL, O_NONBLOCK | O_RDWR); ++ ++ con->sock->fd = fd; ++ con->sock->fde_ndx = -1; ++ con->sock->type = IOSOCKET_TYPE_SOCKET; ++ ++ if (-1 == connect(fd, &(con->address->addr.plain), sizeof(con->address->addr))) { ++ switch(errno) { ++ case EINPROGRESS: ++ case EALREADY: ++ case EINTR: ++ return HANDLER_WAIT_FOR_EVENT; ++ default: ++ close(fd); ++ con->sock->fd = -1; ++ ++ return HANDLER_ERROR; ++ } ++ } ++ ++ return HANDLER_GO_ON; ++} ++ ++/** ++ * event-handler for idling connections ++ * ++ * unused (idling) keep-alive connections are not bound to a session ++ * and need their own event-handler ++ * ++ * if the connection closes (we get a FDEVENT_IN), close our side too and ++ * let the trigger-func handle the cleanup ++ * ++ * @see proxy_trigger ++ */ ++ ++ ++static handler_t proxy_handle_fdevent_idle(void *s, void *ctx, int revents) { ++ server *srv = (server *)s; ++ proxy_connection *proxy_con = ctx; ++ ++ if (revents & FDEVENT_IN) { ++ switch (proxy_con->state) { ++ case PROXY_CONNECTION_STATE_IDLE: ++ proxy_con->state = PROXY_CONNECTION_STATE_CLOSED; ++ ++ /* close + unregister have to be in the same call, ++ * otherwise we get a events for a re-opened fd */ ++ ++ fdevent_event_del(srv->ev, proxy_con->sock); ++ ++ break; ++ case PROXY_CONNECTION_STATE_CLOSED: ++ /* poll() is state-driven, we will get events as long as it isn't disabled ++ * the close() above should disable the events too */ ++ ERROR("%s", "hurry up buddy, I got another event for a closed idle-connection"); ++ break; ++ default: ++ ERROR("invalid connection state: %d, should be idle", proxy_con->state); ++ break; ++ } ++ } ++ ++ return HANDLER_GO_ON; ++} ++ ++void chunkqueue_skip(chunkqueue *cq, off_t skip) { ++ chunk *c; ++ ++ for (c = cq->first; c && skip; c = c->next) { ++ if (skip > c->mem->used - c->offset - 1) { ++ skip -= c->mem->used - c->offset - 1; ++ } else { ++ c->offset += skip; ++ skip = 0; ++ } ++ } ++ ++ return; ++} ++ ++int proxy_http_stream_decoder(server *srv, proxy_session *sess, chunkqueue *raw, chunkqueue *decoded) { ++ chunk *c; ++ ++ if (sess->is_chunked) { ++ do { ++ /* the start should always be a chunk-length */ ++ off_t chunk_len = 0; ++ char *err = NULL; ++ int chunklen_strlen = 0; ++ char ch; ++ off_t we_have = 0, we_need = 0; ++ ++ c = raw->first; ++ ++ chunk_len = strtol(BUF_STR(c->mem) + c->offset, &err, 16); ++ if (!(*err == ' ' || *err == '\r' || *err == ';')) { ++ if (*err == '\0') { ++ /* we just need more data */ ++ return 0; ++ } ++ return -1; ++ } ++ ++ if (chunk_len < 0) { ++ ERROR("chunk_len is negative: %Ld", chunk_len); ++ return -1; ++ } ++ ++ chunklen_strlen = err - (BUF_STR(c->mem) + c->offset); ++ chunklen_strlen++; /* skip the err-char */ ++ ++ do { ++ ch = BUF_STR(c->mem)[c->offset + chunklen_strlen]; ++ ++ switch (ch) { ++ case '\n': ++ case '\0': ++ /* bingo, chunk-header is finished */ ++ break; ++ default: ++ break; ++ } ++ chunklen_strlen++; ++ } while (ch != '\n' && c != '\0'); ++ ++ if (ch != '\n') { ++ ERROR("%s", "missing the CRLF"); ++ return 0; ++ } ++ ++ we_need = chunk_len + chunklen_strlen + 2; ++ /* do we have the full chunk ? */ ++ for (c = raw->first; c; c = c->next) { ++ we_have += c->mem->used - 1 - c->offset; ++ ++ /* we have enough, jump out */ ++ if (we_have > we_need) break; ++ } ++ ++ /* get more data */ ++ if (we_have < we_need) { ++ return 0; ++ } ++ ++ /* skip the chunk-header */ ++ chunkqueue_skip(raw, chunklen_strlen); ++ ++ /* final chunk */ ++ if (chunk_len == 0) { ++ chunkqueue_skip(raw, 2); ++ ++ return 1; ++ } ++ ++ /* we have enough, copy the data */ ++ for (c = raw->first; c && chunk_len; c = c->next) { ++ off_t we_want = 0; ++ buffer *b = chunkqueue_get_append_buffer(decoded); ++ ++ we_want = chunk_len > (c->mem->used - c->offset - 1) ? c->mem->used - c->offset - 1: chunk_len; ++ ++ buffer_copy_string_len(b, c->mem->ptr + c->offset, we_want); ++ ++ c->offset += we_want; ++ chunk_len -= we_want; ++ } ++ ++ /* skip the \r\n */ ++ chunkqueue_skip(raw, 2); ++ ++ /* we are done, give the connection to someone else */ ++ chunkqueue_remove_finished_chunks(raw); ++ } while (1); ++ } else { ++ /* no chunked encoding, ok, perhaps a content-length ? */ ++ ++ TRACE("content-lenght: %d", sess->content_length); ++ ++ chunkqueue_remove_finished_chunks(raw); ++ for (c = raw->first; c; c = c->next) { ++ buffer *b; ++ ++ if (c->mem->used == 0) continue; ++ ++ b = chunkqueue_get_append_buffer(decoded); ++ ++ sess->bytes_read += c->mem->used - c->offset - 1; ++ ++ buffer_copy_string_len(b, c->mem->ptr + c->offset, c->mem->used - c->offset - 1); ++ ++ c->offset = c->mem->used - 1; ++ ++ if (sess->bytes_read == sess->content_length) { ++ break; ++ } ++ ++ } ++ if (sess->bytes_read == sess->content_length) { ++ return 1; /* finished */ ++ } ++ } ++ ++ return 0; ++} ++/* don't call any proxy functions directly */ ++static handler_t proxy_handle_fdevent(void *s, void *ctx, int revents) { ++ server *srv = (server *)s; ++ proxy_session *sess = ctx; ++ ++ if (revents & FDEVENT_OUT) { ++ switch (sess->state) { ++ case PROXY_STATE_CONNECTING: /* delayed connect */ ++ case PROXY_STATE_WRITE_REQUEST_HEADER: ++ case PROXY_STATE_WRITE_REQUEST_BODY: ++ /* we are still connection */ ++ ++ joblist_append(srv, sess->remote_con); ++ break; ++ default: ++ ERROR("oops, unexpected state for fdevent-out %d", sess->state); ++ break; ++ } ++ } else if (revents & FDEVENT_IN) { ++ chunk *c; ++ ++ switch (sess->state) { ++ case PROXY_STATE_READ_RESPONSE_HEADER: ++ /* call our header parser */ ++ joblist_append(srv, sess->remote_con); ++ break; ++ case PROXY_STATE_READ_RESPONSE_BODY: ++ /* we should be in the WRITE state now, ++ * just read in the content and forward it to the outgoing connection ++ * */ ++ ++ chunkqueue_remove_finished_chunks(sess->recv_raw); ++ switch (srv->network_backend_read(srv, sess->remote_con, sess->proxy_con->sock, sess->recv_raw)) { ++ case NETWORK_STATUS_CONNECTION_CLOSE: ++ fdevent_event_del(srv->ev,sess->proxy_con->sock); ++ ++ /* the connection is gone ++ * make the connect */ ++ sess->remote_con->file_finished = 1; ++ sess->proxy_con->state = PROXY_CONNECTION_STATE_CLOSED; ++ ++ case NETWORK_STATUS_SUCCESS: ++ /* read even more, do we have all the content */ ++ ++ /* how much do we want to read ? */ ++ ++ /* call stream-decoder (HTTP-chunked, FastCGI, ... ) */ ++ ++ switch (proxy_http_stream_decoder(srv, sess, sess->recv_raw, sess->recv)) { ++ case 0: ++ /* need more */ ++ break; ++ case -1: ++ /* error */ ++ break; ++ case 1: ++ /* we are done */ ++ sess->remote_con->file_finished = 1; ++ ++ break; ++ } ++ chunkqueue_remove_finished_chunks(sess->recv_raw); ++ ++ /* copy the content to the next cq */ ++ for (c = sess->recv->first; c; c = c->next) { ++ if (c->mem->used == 0) continue; ++ ++ http_chunk_append_mem(srv, sess->remote_con, c->mem->ptr + c->offset, c->mem->used - c->offset); ++ ++ c->offset = c->mem->used - 1; ++ ++ } ++ chunkqueue_remove_finished_chunks(sess->recv); ++ ++ if (sess->remote_con->file_finished) { ++ /* send final HTTP-Chunk packet */ ++ http_chunk_append_mem(srv, sess->remote_con, NULL, 0); ++ } ++ ++ break; ++ default: ++ ERROR("%s", "oops, we failed to read"); ++ break; ++ } ++ ++ joblist_append(srv, sess->remote_con); ++ break; ++ default: ++ ERROR("oops, unexpected state for fdevent-in %d", sess->state); ++ break; ++ } ++ } ++ ++ if (revents & FDEVENT_HUP) { ++ /* someone closed our connection */ ++ switch (sess->state) { ++ case PROXY_STATE_CONNECTING: ++ /* let the getsockopt() catch this */ ++ joblist_append(srv, sess->remote_con); ++ break; ++ default: ++ ERROR("oops, unexpected state for fdevent-hup %d", sess->state); ++ break; ++ } ++ } ++ ++ return HANDLER_GO_ON; ++} ++ ++/** ++ * generate a HTTP/1.1 proxy request from the set of request-headers ++ * ++ * TODO: this is HTTP-proxy specific and will be moved moved into a separate backed ++ * ++ */ ++int proxy_get_request_chunk(server *srv, connection *con, proxy_session *sess, chunkqueue *cq) { ++ buffer *b; ++ size_t i; ++ ++ b = chunkqueue_get_append_buffer(cq); ++ ++ /* request line */ ++ buffer_copy_string(b, get_http_method_name(con->request.http_method)); ++ BUFFER_APPEND_STRING_CONST(b, " "); ++ ++ buffer_append_string_buffer(b, con->request.uri); ++ BUFFER_APPEND_STRING_CONST(b, " HTTP/1.1\r\n"); ++ ++ for (i = 0; i < sess->request_headers->used; i++) { ++ data_string *ds; ++ ++ ds = (data_string *)sess->request_headers->data[i]; ++ ++ buffer_append_string_buffer(b, ds->key); ++ BUFFER_APPEND_STRING_CONST(b, ": "); ++ buffer_append_string_buffer(b, ds->value); ++ BUFFER_APPEND_STRING_CONST(b, "\r\n"); ++ } ++ ++ BUFFER_APPEND_STRING_CONST(b, "\r\n"); ++ ++ return 0; ++} ++ ++void proxy_set_header(array *hdrs, const char *key, size_t key_len, const char *value, size_t val_len) { ++ data_string *ds_dst; ++ ++ if (NULL == (ds_dst = (data_string *)array_get_unused_element(hdrs, TYPE_STRING))) { ++ ds_dst = data_string_init(); ++ } ++ ++ buffer_copy_string_len(ds_dst->key, key, key_len); ++ buffer_copy_string_len(ds_dst->value, value, val_len); ++ array_insert_unique(hdrs, (data_unset *)ds_dst); ++} ++ ++void proxy_append_header(array *hdrs, const char *key, size_t key_len, const char *value, size_t val_len) { ++ data_string *ds_dst; ++ ++ if (NULL == (ds_dst = (data_string *)array_get_unused_element(hdrs, TYPE_STRING))) { ++ ds_dst = data_string_init(); ++ } ++ ++ buffer_copy_string_len(ds_dst->key, key, key_len); ++ buffer_append_string_len(ds_dst->value, value, val_len); ++ array_insert_unique(hdrs, (data_unset *)ds_dst); ++} ++ ++ ++/** ++ * build the request-header array and call the backend specific request formater ++ * to fill the chunkqueue ++ */ ++int proxy_get_request_header(server *srv, connection *con, proxy_session *sess) { ++ /* request line */ ++ const char *remote_ip; ++ size_t i; ++ ++ remote_ip = inet_ntop_cache_get_ip(srv, &(con->dst_addr)); ++ proxy_append_header(sess->request_headers, CONST_STR_LEN("X-Forwarded-For"), remote_ip, strlen(remote_ip)); ++ ++ /* http_host is NOT is just a pointer to a buffer ++ * which is NULL if it is not set */ ++ if (con->request.http_host && ++ !buffer_is_empty(con->request.http_host)) { ++ proxy_set_header(sess->request_headers, CONST_STR_LEN("X-Host"), CONST_BUF_LEN(con->request.http_host)); ++ } ++ if (con->conf.is_ssl) { ++ proxy_set_header(sess->request_headers, CONST_STR_LEN("X-Forwarded-Proto"), CONST_STR_LEN("https")); ++ } else { ++ proxy_set_header(sess->request_headers, CONST_STR_LEN("X-Forwarded-Proto"), CONST_STR_LEN("http")); ++ } ++ ++ /* request header */ ++ for (i = 0; i < con->request.headers->used; i++) { ++ data_string *ds; ++ ++ ds = (data_string *)con->request.headers->data[i]; ++ ++ if (buffer_is_empty(ds->value) || buffer_is_empty(ds->key)) continue; ++ ++ if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Connection"))) continue; ++ if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Keep-Alive"))) continue; ++ ++ proxy_set_header(sess->request_headers, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value)); ++ } ++ ++ proxy_get_request_chunk(srv, con, sess, sess->send_raw); ++ ++ return 0; ++} ++ ++/** ++ * parse the response header ++ * ++ * NOTE: this can be used by all backends as they all send a HTTP-Response a clean block ++ * - fastcgi needs some decoding for the protocol ++ */ ++parse_status_t proxy_parse_response_header(server *srv, connection *con, plugin_data *p, proxy_session *sess, chunkqueue *cq) { ++ int have_content_length = 0; ++ size_t i; ++ ++ http_response_reset(p->resp); ++ ++ switch (http_response_parse_cq(cq, p->resp)) { ++ case PARSE_ERROR: ++ /* parsing failed */ ++ ++ return PARSE_ERROR; ++ case PARSE_NEED_MORE: ++ return PARSE_NEED_MORE; ++ case PARSE_SUCCESS: ++ con->http_status = p->resp->status; ++ ++ chunkqueue_remove_finished_chunks(cq); ++ ++ sess->content_length = -1; ++ ++ /* copy the http-headers */ ++ for (i = 0; i < p->resp->headers->used; i++) { ++ const char *ign[] = { "Status", "Connection", NULL }; ++ size_t j; ++ data_string *ds; ++ ++ data_string *header = (data_string *)p->resp->headers->data[i]; ++ ++ /* some headers are ignored by default */ ++ for (j = 0; ign[j]; j++) { ++ if (0 == strcasecmp(ign[j], header->key->ptr)) break; ++ } ++ if (ign[j]) continue; ++ ++ if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Location"))) { ++ /* CGI/1.1 rev 03 - 7.2.1.2 */ ++ if (con->http_status == 0) con->http_status = 302; ++ } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Content-Length"))) { ++ have_content_length = 1; ++ ++ sess->content_length = strtol(header->value->ptr, NULL, 10); ++ ++ if (sess->content_length < 0) { ++ return PARSE_ERROR; ++ } ++ } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Transfer-Encoding"))) { ++ if (strstr(header->value->ptr, "chunked")) { ++ sess->is_chunked = 1; ++ } ++ /* ignore the header */ ++ continue; ++ } ++ ++ if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) { ++ ds = data_response_init(); ++ } ++ buffer_copy_string_buffer(ds->key, header->key); ++ buffer_copy_string_buffer(ds->value, header->value); ++ ++ array_insert_unique(con->response.headers, (data_unset *)ds); ++ } ++ ++ /* does the client allow us to send chunked encoding ? */ ++ if (con->request.http_version == HTTP_VERSION_1_1 && ++ !have_content_length) { ++ con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED; ++ } ++ ++ break; ++ } ++ ++ return PARSE_SUCCESS; /* we have a full header */ ++} ++ ++/* we are event-driven ++ * ++ * the first entry is connect() call, if the doesn't need a event ++ * ++ * a bit boring ++ * - connect (+ delayed connect) ++ * - write header + content ++ * - read header + content ++ * ++ * as soon as have read the response header we switch con->file_started and return HANDLER_GO_ON to ++ * tell the core we are ready to stream out the content. ++ * */ ++handler_t proxy_state_engine(server *srv, connection *con, plugin_data *p, proxy_session *sess) { ++ /* do we have a connection ? */ ++ ++ if (sess->state == PROXY_STATE_UNSET) { ++ /* we are not started yet */ ++ switch(proxy_connection_connect(sess->proxy_con)) { ++ case HANDLER_WAIT_FOR_EVENT: ++ /* waiting on the connect call */ ++ ++ fdevent_register(srv->ev, sess->proxy_con->sock, proxy_handle_fdevent, sess); ++ fdevent_event_add(srv->ev, sess->proxy_con->sock, FDEVENT_OUT); ++ ++ sess->state = PROXY_STATE_CONNECTING; ++ sess->proxy_con->state = PROXY_CONNECTION_STATE_CONNECTING; ++ ++ return HANDLER_WAIT_FOR_EVENT; ++ case HANDLER_GO_ON: ++ /* we are connected */ ++ sess->state = PROXY_STATE_CONNECTED; ++ sess->proxy_con->state = PROXY_CONNECTION_STATE_CONNECTED; ++ fdevent_register(srv->ev, sess->proxy_con->sock, proxy_handle_fdevent, sess); ++ ++ break; ++ case HANDLER_ERROR: ++ default: ++ /* not good, something failed */ ++ return HANDLER_ERROR; ++ ++ } ++ } else if (sess->state == PROXY_STATE_CONNECTING) { ++ int socket_error; ++ socklen_t socket_error_len = sizeof(socket_error); ++ ++ fdevent_event_del(srv->ev, sess->proxy_con->sock); ++ ++ if (0 != getsockopt(sess->proxy_con->sock->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) { ++ ERROR("getsockopt failed:", strerror(errno)); ++ ++ return HANDLER_ERROR; ++ } ++ if (socket_error != 0) { ++ switch (socket_error) { ++ case ECONNREFUSED: ++ /* there is no-one on the other side */ ++ sess->proxy_con->address->disabled_until = srv->cur_ts + 2; ++ ++ TRACE("address %s refused us, disabling for 2 sec", sess->proxy_con->address->name->ptr); ++ break; ++ case EHOSTUNREACH: ++ /* there is no-one on the other side */ ++ sess->proxy_con->address->disabled_until = srv->cur_ts + 60; ++ ++ TRACE("host %s is unreachable, disabling for 60 sec", sess->proxy_con->address->name->ptr); ++ break; ++ default: ++ sess->proxy_con->address->disabled_until = srv->cur_ts + 60; ++ ++ TRACE("connected finally failed: %s (%d)", strerror(socket_error), socket_error); ++ ++ TRACE("connect to address %s failed and I don't know why, disabling for 10 sec", sess->proxy_con->address->name->ptr); ++ ++ break; ++ } ++ ++ sess->proxy_con->address->state = PROXY_ADDRESS_STATE_DISABLED; ++ ++ sess->proxy_con->state = PROXY_CONNECTION_STATE_CLOSED; ++ return HANDLER_COMEBACK; ++ } ++ ++ sess->state = PROXY_STATE_CONNECTED; ++ sess->proxy_con->state = PROXY_CONNECTION_STATE_CONNECTED; ++ } ++ ++ if (sess->state == PROXY_STATE_CONNECTED) { ++ /* build the header */ ++ proxy_get_request_header(srv, con, sess); ++ ++ sess->state = PROXY_STATE_WRITE_REQUEST_HEADER; ++ } ++ ++ switch (sess->state) { ++ case PROXY_STATE_WRITE_REQUEST_HEADER: ++ /* create the request-packet */ ++ fdevent_event_del(srv->ev, sess->proxy_con->sock); ++ ++ switch (srv->network_backend_write(srv, con, sess->proxy_con->sock, sess->send_raw)) { ++ case NETWORK_STATUS_SUCCESS: ++ sess->state = PROXY_STATE_WRITE_REQUEST_BODY; ++ break; ++ case NETWORK_STATUS_WAIT_FOR_EVENT: ++ fdevent_event_add(srv->ev, sess->proxy_con->sock, FDEVENT_OUT); ++ ++ return HANDLER_WAIT_FOR_EVENT; ++ case NETWORK_STATUS_CONNECTION_CLOSE: ++ sess->proxy_con->state = PROXY_CONNECTION_STATE_CLOSED; ++ ++ /* this connection is closed, restart the request with a new connection */ ++ ++ return HANDLER_COMEBACK; ++ default: ++ return HANDLER_ERROR; ++ } ++ /* fall through */ ++ case PROXY_STATE_WRITE_REQUEST_BODY: ++ fdevent_event_del(srv->ev, sess->proxy_con->sock); ++ sess->state = PROXY_STATE_READ_RESPONSE_HEADER; ++ ++ case PROXY_STATE_READ_RESPONSE_HEADER: ++ fdevent_event_del(srv->ev, sess->proxy_con->sock); ++ ++ chunkqueue_remove_finished_chunks(sess->recv_raw); ++ ++ switch (srv->network_backend_read(srv, con, sess->proxy_con->sock, sess->recv_raw)) { ++ case NETWORK_STATUS_SUCCESS: ++ /* we read everything from the socket, do we have a full header ? */ ++ ++ switch (proxy_parse_response_header(srv, con, p, sess, sess->recv_raw)) { ++ case PARSE_ERROR: ++ con->http_status = 502; /* bad gateway */ ++ ++ return HANDLER_FINISHED; ++ case PARSE_NEED_MORE: ++ /* we need more */ ++ fdevent_event_add(srv->ev, sess->proxy_con->sock, FDEVENT_IN); ++ ++ return HANDLER_WAIT_FOR_EVENT; ++ case PARSE_SUCCESS: ++ break; ++ default: ++ return HANDLER_ERROR; ++ } ++ ++ con->file_started = 1; ++ ++ sess->state = PROXY_STATE_READ_RESPONSE_BODY; ++ ++ /** ++ * set the event to pass the content through to the server ++ * ++ * this triggers the event-handler ++ * @see proxy_handle_fdevent ++ */ ++ fdevent_event_add(srv->ev, sess->proxy_con->sock, FDEVENT_IN); ++ ++ return HANDLER_GO_ON; /* tell http_response_prepare that we are done with the header */ ++ case NETWORK_STATUS_WAIT_FOR_EVENT: ++ fdevent_event_add(srv->ev, sess->proxy_con->sock, FDEVENT_IN); ++ return HANDLER_WAIT_FOR_EVENT; ++ case NETWORK_STATUS_CONNECTION_CLOSE: ++ if (chunkqueue_length(sess->recv_raw) == 0) { ++ /* the connection went away before we got something back */ ++ sess->proxy_con->state = PROXY_CONNECTION_STATE_CLOSED; ++ ++ /** ++ * we might run into a 'race-condition' ++ * ++ * 1. proxy-con is keep-alive, idling and just being closed (FDEVENT_IN) [fd=27] ++ * 2. new connection comes in, we use the idling connection [fd=14] ++ * 3. we write(), successful [to fd=27] ++ * 3. we read() ... and finally receive the close-event for the connection ++ */ ++ ++ con->http_status = 500; ++ ++ ERROR("++ %s", "oops, connection got closed while we were reading from it"); ++ return HANDLER_FINISHED; ++ } ++ ++ ERROR("%s", "conn-close after header-read"); ++ ++ break; ++ default: ++ ERROR("++ %s", "oops, something went wrong while reading"); ++ return HANDLER_ERROR; ++ } ++ case PROXY_STATE_READ_RESPONSE_BODY: ++ /* if we do everything right, we won't get call for this state-anymore */ ++ ++ ERROR("%s", "PROXY_STATE_READ_RESPONSE_BODY"); ++ ++ break; ++ } ++ ++ return HANDLER_GO_ON; ++} ++ ++proxy_backend *proxy_get_backend(server *srv, connection *con, plugin_data *p, buffer *uri) { ++ size_t i; ++ ++ for (i = 0; i < p->conf.backends->used; i++) { ++ proxy_backend *backend = p->conf.backends->ptr[i]; ++ ++ return backend; ++ } ++ ++ return NULL; ++} ++ ++/** ++ * choose a available address from the address-pool ++ * ++ * the backend has different balancers ++ */ ++proxy_address *proxy_backend_balance(server *srv, connection *con, proxy_backend *backend) { ++ size_t i; ++ proxy_address_pool *address_pool = backend->address_pool; ++ unsigned long last_max; /* for the HASH balancer */ ++ proxy_address *address = NULL, *cur_address = NULL; ++ int active_addresses = 0, rand_ndx; ++ ++ switch(backend->balancer) { ++ case PROXY_BALANCE_HASH: ++ /* hash balancing */ ++ ++ for (i = 0, last_max = ULONG_MAX; i < address_pool->used; i++) { ++ unsigned long cur_max; ++ ++ cur_address = address_pool->ptr[i]; ++ ++ if (cur_address->state != PROXY_ADDRESS_STATE_ACTIVE) continue; ++ ++ cur_max = generate_crc32c(CONST_BUF_LEN(con->uri.path)) + ++ generate_crc32c(CONST_BUF_LEN(cur_address->name)) + /* we can cache this */ ++ generate_crc32c(CONST_BUF_LEN(con->uri.authority)); ++ ++ TRACE("hash-election: %s - %s - %s: %ld", ++ con->uri.path->ptr, ++ cur_address->name->ptr, ++ con->uri.authority->ptr, ++ cur_max); ++ ++ if (address == NULL || (cur_max > last_max)) { ++ last_max = cur_max; ++ ++ address = cur_address; ++ } ++ } ++ ++ break; ++ case PROXY_BALANCE_FAIR: ++ /* fair balancing */ ++ ++ for (i = 0; i < address_pool->used; i++) { ++ cur_address = address_pool->ptr[i]; ++ ++ if (cur_address->state != PROXY_ADDRESS_STATE_ACTIVE) continue; ++ ++ /* the address is up, use it */ ++ ++ address = cur_address; ++ ++ break; ++ } ++ ++ break; ++ case PROXY_BALANCE_RR: ++ /* round robin */ ++ ++ /** ++ * instead of real RoundRobin we just do a RandomSelect ++ * ++ * it is state-less and has the same distribution ++ */ ++ ++ active_addresses = 0; ++ ++ for (i = 0; i < address_pool->used; i++) { ++ cur_address = address_pool->ptr[i]; ++ ++ if (cur_address->state != PROXY_ADDRESS_STATE_ACTIVE) continue; ++ ++ active_addresses++; ++ } ++ ++ rand_ndx = (int) (1.0 * active_addresses * rand()/(RAND_MAX)); ++ ++ active_addresses = 0; ++ for (i = 0; i < address_pool->used; i++) { ++ cur_address = address_pool->ptr[i]; ++ ++ if (cur_address->state != PROXY_ADDRESS_STATE_ACTIVE) continue; ++ ++ address = cur_address; ++ ++ if (rand_ndx == active_addresses++) break; ++ } ++ ++ break; ++ default: ++ break; ++ } ++ ++ return address; ++} ++ ++static int mod_proxy_core_patch_connection(server *srv, connection *con, plugin_data *p) { ++ size_t i, j; ++ plugin_config *s = p->config_storage[0]; ++ ++ /* global defaults */ ++ PATCH_OPTION(balancer); ++ PATCH_OPTION(debug); ++ PATCH_OPTION(backends); ++ PATCH_OPTION(backlog); ++ PATCH_OPTION(protocol); ++ ++ /* 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("proxy.backends"))) { ++ PATCH_OPTION(backends); ++ PATCH_OPTION(backlog); ++ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.debug"))) { ++ PATCH_OPTION(debug); ++ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.balancer"))) { ++ PATCH_OPTION(balancer); ++ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.protocol"))) { ++ PATCH_OPTION(protocol); ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++ ++SUBREQUEST_FUNC(mod_proxy_core_check_extension) { ++ plugin_data *p = p_d; ++ proxy_session *sess = con->plugin_ctx[p->id]; /* if this is the second round, sess is already prepared */ ++ ++ /* check if we have a matching conditional for this request */ ++ ++ if (buffer_is_empty(con->uri.path)) return HANDLER_GO_ON; ++ ++ mod_proxy_core_patch_connection(srv, con, p); ++ ++ /* ++ * 0. build session ++ * 1. get a proxy connection ++ * 2. create the http-request header ++ * 3. stream the content to the backend ++ * 4. wait for http-response header ++ * 5. decode the response + parse the response ++ * 6. stream the response-content to the client ++ * 7. kill session ++ * */ ++ ++ if (!sess) { ++ /* a session lives for a single request */ ++ sess = proxy_session_init(); ++ ++ con->plugin_ctx[p->id] = sess; ++ con->mode = p->id; ++ ++ sess->remote_con = con; ++ } ++ ++ switch (sess->state) { ++ case PROXY_STATE_CONNECTING: ++ /* this connections is waited 10 seconds to connect to the backend ++ * and didn't got a successful connection yet, sending timeout */ ++ if (srv->cur_ts - con->request_start > 10) { ++ con->http_status = 504; /* gateway timeout */ ++ ++ if (sess->proxy_con) { ++ /* if we are waiting for a proxy-connection right now, close it */ ++ proxy_connection_pool_remove_connection(sess->proxy_backend->pool, sess->proxy_con); ++ ++ fdevent_event_del(srv->ev, sess->proxy_con->sock); ++ fdevent_unregister(srv->ev, sess->proxy_con->sock); ++ ++ proxy_connection_free(sess->proxy_con); ++ ++ sess->proxy_con = NULL; ++ } ++ ++ return HANDLER_FINISHED; ++ } ++ default: ++ /* handle-request-timeout, */ ++ if (srv->cur_ts - con->request_start > 60) { ++ TRACE("request runs longer than 60sec: current state: %d", sess->state); ++ } ++ break; ++ } ++ ++ /* if the WRITE fails from the start, restart the connection */ ++ while (1) { ++ if (sess->proxy_con == NULL) { ++ proxy_address *address = NULL; ++ if (NULL == (sess->proxy_backend = proxy_get_backend(srv, con, p, con->uri.path))) { ++ /* no connection pool for this location */ ++ SEGFAULT(); ++ } ++ ++ /** ++ * ask the balancer for the next address and ++ * check the connection pool if we have a connection open ++ * for that address ++ */ ++ if (NULL == (address = proxy_backend_balance(srv, con, sess->proxy_backend))) { ++ /* we don't have any backends to connect to */ ++ proxy_request *req; ++ ++ /* connection pool is full, queue the request for now */ ++ req = proxy_request_init(); ++ req->added_ts = srv->cur_ts; ++ req->con = con; ++ ++ TRACE("backlog: all backends are down, putting %s (%d) into the backlog", BUF_STR(con->uri.path), con->sock->fd); ++ proxy_backlog_push(p->conf.backlog, req); ++ ++ /* no, not really a event, ++ * we just want to block the outer loop from stepping forward ++ * ++ * the trigger will bring this connection back into the game ++ * */ ++ return HANDLER_WAIT_FOR_EVENT; ++ } ++ ++ if (PROXY_CONNECTIONPOOL_FULL == proxy_connection_pool_get_connection( ++ sess->proxy_backend->pool, ++ address, ++ &(sess->proxy_con))) { ++ proxy_request *req; ++ ++ /* connection pool is full, queue the request for now */ ++ req = proxy_request_init(); ++ req->added_ts = srv->cur_ts; ++ req->con = con; ++ ++ TRACE("backlog: the con-pool is full, putting %s (%d) into the backlog", con->uri.path->ptr, con->sock->fd); ++ proxy_backlog_push(p->conf.backlog, req); ++ ++ /* no, not really a event, ++ * we just want to block the outer loop from stepping forward ++ * ++ * the trigger will bring this connection back into the game ++ * */ ++ return HANDLER_WAIT_FOR_EVENT; ++ } ++ ++ /* a fresh connection, we need address for it */ ++ if (sess->proxy_con->state == PROXY_CONNECTION_STATE_CONNECTING) { ++ sess->state = PROXY_STATE_UNSET; ++ sess->bytes_read = 0; ++ } else { ++ /* we are already connected */ ++ sess->state = PROXY_STATE_CONNECTED; ++ ++ /* the connection was idling and using the fdevent_idle-handler ++ * switch it back to the normal proxy-event-handler */ ++ fdevent_event_del(srv->ev, sess->proxy_con->sock); ++ fdevent_unregister(srv->ev, sess->proxy_con->sock); ++ ++ fdevent_register(srv->ev, sess->proxy_con->sock, proxy_handle_fdevent, sess); ++ fdevent_event_add(srv->ev, sess->proxy_con->sock, FDEVENT_IN); ++ } ++ } ++ ++ switch (proxy_state_engine(srv, con, p, sess)) { ++ case HANDLER_WAIT_FOR_EVENT: ++ return HANDLER_WAIT_FOR_EVENT; ++ case HANDLER_COMEBACK: ++ proxy_connection_pool_remove_connection(sess->proxy_backend->pool, sess->proxy_con); ++ ++ fdevent_event_del(srv->ev, sess->proxy_con->sock); ++ fdevent_unregister(srv->ev, sess->proxy_con->sock); ++ ++ proxy_connection_free(sess->proxy_con); ++ ++ sess->proxy_con = NULL; ++ /* restart the connection to the backend */ ++ TRACE("%s", "write failed, restarting request"); ++ break; ++ case HANDLER_GO_ON: ++ return HANDLER_GO_ON; ++ default: ++ return HANDLER_ERROR; ++ } ++ } ++ ++ /* should not be reached */ ++ return HANDLER_ERROR; ++} ++ ++/** ++ * end of the connection to the client ++ */ ++REQUESTDONE_FUNC(mod_proxy_connection_close_callback) { ++ plugin_data *p = p_d; ++ ++ if (con->mode != p->id) return HANDLER_GO_ON; ++ ++ return HANDLER_GO_ON; ++} ++ ++/** ++ * end of a request ++ */ ++CONNECTION_FUNC(mod_proxy_connection_reset) { ++ plugin_data *p = p_d; ++ proxy_session *sess = con->plugin_ctx[p->id]; ++ ++ if (con->mode != p->id) return HANDLER_GO_ON; ++ ++ if (sess->proxy_con) { ++ switch (sess->proxy_con->state) { ++ case PROXY_CONNECTION_STATE_CONNECTED: ++ sess->proxy_con->state = PROXY_CONNECTION_STATE_IDLE; ++ ++ /* ignore events as the FD is idle, we might get a HUP as the remote connection might close */ ++ fdevent_event_del(srv->ev, sess->proxy_con->sock); ++ fdevent_unregister(srv->ev, sess->proxy_con->sock); ++ ++ fdevent_register(srv->ev, sess->proxy_con->sock, proxy_handle_fdevent_idle, sess->proxy_con); ++ fdevent_event_add(srv->ev, sess->proxy_con->sock, FDEVENT_IN); ++ ++ break; ++ case PROXY_CONNECTION_STATE_CLOSED: ++ proxy_connection_pool_remove_connection(sess->proxy_backend->pool, sess->proxy_con); ++ ++ fdevent_event_del(srv->ev, sess->proxy_con->sock); ++ fdevent_unregister(srv->ev, sess->proxy_con->sock); ++ ++ proxy_connection_free(sess->proxy_con); ++ break; ++ case PROXY_CONNECTION_STATE_IDLE: ++ TRACE("%s", "... connection is already back in the pool"); ++ break; ++ default: ++ ERROR("connection is in a unexpected state at close-time: %d", sess->proxy_con->state); ++ break; ++ } ++ } else { ++ /* if we have the connection in the backlog, remove it */ ++ proxy_backlog_remove_connection(p->conf.backlog, con); ++ } ++ ++ ++ proxy_session_free(sess); ++ ++ con->plugin_ctx[p->id] = NULL; ++ ++ return HANDLER_GO_ON; ++} ++ ++ ++ ++/** ++ * cleanup dead connections once a second ++ * ++ * the idling event-handler can't cleanup connections itself and has to wait until the ++ * trigger cleans up ++ */ ++handler_t mod_proxy_trigger_context(server *srv, plugin_config *p) { ++ size_t i, j; ++ proxy_request *req; ++ ++ for (i = 0; i < p->backends->used; i++) { ++ proxy_backend *backend = p->backends->ptr[i]; ++ proxy_connection_pool *pool = backend->pool; ++ proxy_address_pool *address_pool = backend->address_pool; ++ ++ for (j = 0; j < pool->used; ) { ++ proxy_connection *proxy_con = pool->ptr[j]; ++ ++ /* remove-con is removing the current con and moves the good connections to the left ++ * no need to increment i */ ++ if (proxy_con->state == PROXY_CONNECTION_STATE_CLOSED) { ++ proxy_connection_pool_remove_connection(backend->pool, proxy_con); ++ ++ fdevent_event_del(srv->ev, proxy_con->sock); ++ fdevent_unregister(srv->ev, proxy_con->sock); ++ ++ proxy_connection_free(proxy_con); ++ } else { ++ j++; ++ } ++ } ++ ++ /* active the disabled addresses again */ ++ for (j = 0; j < address_pool->used; j++) { ++ proxy_address *address = address_pool->ptr[j]; ++ ++ if (address->state != PROXY_ADDRESS_STATE_DISABLED) continue; ++ ++ if (srv->cur_ts > address->disabled_until) { ++ address->disabled_until = 0; ++ address->state = PROXY_ADDRESS_STATE_ACTIVE; ++ } ++ } ++ } ++ ++ /* wake up the connections from the backlog */ ++ while ((req = proxy_backlog_shift(p->backlog))) { ++ connection *con = req->con; ++ ++ joblist_append(srv, con); ++ ++ proxy_request_free(req); ++ } ++ ++ return HANDLER_GO_ON; ++} ++ ++TRIGGER_FUNC(mod_proxy_trigger) { ++ plugin_data *p = p_d; ++ size_t i; ++ ++ for (i = 0; i < srv->config_context->used; i++) { ++ mod_proxy_trigger_context(srv, p->config_storage[i]); ++ } ++ ++ return HANDLER_GO_ON; ++} ++ ++int mod_proxy_core_plugin_init(plugin *p) { ++ p->version = LIGHTTPD_VERSION_ID; ++ p->name = buffer_init_string("mod_proxy_core"); ++ ++ p->init = mod_proxy_core_init; ++ p->cleanup = mod_proxy_core_free; ++ p->set_defaults = mod_proxy_core_set_defaults; ++ p->handle_uri_clean = mod_proxy_core_check_extension; ++ p->handle_subrequest_start = mod_proxy_core_check_extension; ++ p->handle_subrequest = mod_proxy_core_check_extension; ++ p->connection_reset = mod_proxy_connection_reset; ++ p->handle_connection_close = mod_proxy_connection_close_callback; ++ p->handle_trigger = mod_proxy_trigger; ++ ++ p->data = NULL; ++ ++ return 0; ++} +--- ../lighttpd-1.4.11/src/mod_proxy_core.h 1970-01-01 03:00:00.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_proxy_core.h 2006-07-18 13:03:40.000000000 +0300 +@@ -0,0 +1,18 @@ ++#ifndef _MOD_PROXY_CORE_H_ ++#define _MOD_PROXY_CORE_H_ ++ ++#include "buffer.h" ++#include "base.h" ++ ++#define PROXY_BACKEND_CONNECT_PARAMS \ ++ (server *srv, connection *con, void *p_d) ++ ++#define PROXY_BACKEND_CONNECT_RETVAL handler_t ++ ++#define PROXY_BACKEND_CONNECT(name) \ ++ PROXY_BACKEND_CONNECT_RETVAL name PROXY_BACKEND_CONNECT_PARAMS ++ ++#define PROXY_BACKEND_CONNECT_PTR(name) \ ++ PROXY_BACKEND_CONNECT_RETVAL (* name)PROXY_BACKEND_CONNECT_PARAMS ++ ++#endif +--- ../lighttpd-1.4.11/src/mod_proxy_core_address.c 1970-01-01 03:00:00.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_proxy_core_address.c 2006-07-18 13:03:40.000000000 +0300 +@@ -0,0 +1,85 @@ ++#include ++#include ++ ++#include "log.h" ++#include "sys-socket.h" ++#include "mod_proxy_core_address.h" ++ ++proxy_address *proxy_address_init(void) { ++ proxy_address *address; ++ ++ address = calloc(1, sizeof(*address)); ++ ++ address->name = buffer_init(); ++ ++ return address; ++} ++ ++void proxy_address_free(proxy_address *address) { ++ if (!address) return; ++ ++ buffer_free(address->name); ++ ++ free(address); ++} ++ ++ ++proxy_address_pool *proxy_address_pool_init(void) { ++ proxy_address_pool *address_pool; ++ ++ address_pool = calloc(1, sizeof(*address_pool)); ++ ++ return address_pool; ++} ++ ++void proxy_address_pool_free(proxy_address_pool *address_pool) { ++ if (!address_pool) return; ++ ++ FOREACH(address_pool, element, proxy_address_free(element)) ++ ++ free(address_pool); ++} ++ ++void proxy_address_pool_add(proxy_address_pool *address_pool, proxy_address *address) { ++ ARRAY_STATIC_PREPARE_APPEND(address_pool); ++ ++ address_pool->ptr[address_pool->used++] = address; ++} ++ ++int proxy_address_pool_add_string(proxy_address_pool *address_pool, buffer *name) { ++ struct addrinfo *res = NULL, pref, *cur; ++ int ret; ++ ++ pref.ai_flags = 0; ++ pref.ai_family = PF_UNSPEC; ++ pref.ai_socktype = SOCK_STREAM; ++ pref.ai_protocol = 0; ++ pref.ai_addrlen = 0; ++ pref.ai_addr = NULL; ++ pref.ai_canonname = NULL; ++ pref.ai_next = NULL; ++ ++ if (0 != (ret = getaddrinfo(name->ptr, "80", &pref, &res))) { ++ ERROR("getaddrinfo failed: %s", gai_strerror(ret)); ++ ++ return -1; ++ } ++ ++ for (cur = res; cur; cur = cur->ai_next) { ++ proxy_address *a = proxy_address_init(); ++ ++ memcpy(&(a->addr), cur->ai_addr, cur->ai_addrlen); ++ ++ a->state = PROXY_ADDRESS_STATE_ACTIVE; ++ ++ buffer_copy_string(a->name, inet_ntoa(a->addr.ipv4.sin_addr)); ++ ++ proxy_address_pool_add(address_pool, a); ++ } ++ ++ freeaddrinfo(res); ++ ++ return 0; ++} ++ ++ +--- ../lighttpd-1.4.11/src/mod_proxy_core_address.h 1970-01-01 03:00:00.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_proxy_core_address.h 2006-07-18 13:03:40.000000000 +0300 +@@ -0,0 +1,33 @@ ++#ifndef _MOD_PROXY_CORE_ADDRESS_H_ ++#define _MOD_PROXY_CORE_ADDRESS_H_ ++ ++#include ++#include "buffer.h" ++#include "sys-socket.h" ++#include "array-static.h" ++ ++typedef enum { ++ PROXY_ADDRESS_STATE_UNSET, ++ PROXY_ADDRESS_STATE_ACTIVE, ++ PROXY_ADDRESS_STATE_DISABLED, ++} proxy_address_state_t; ++ ++typedef struct { ++ sock_addr addr; ++ ++ buffer *name; /* a inet_ntoa() prepresentation of the address */ ++ ++ time_t last_used; ++ time_t disabled_until; ++ ++ proxy_address_state_t state; ++} proxy_address; ++ ++ARRAY_STATIC_DEF(proxy_address_pool, proxy_address, ); ++ ++proxy_address_pool *proxy_address_pool_init(void); ++void proxy_address_pool_free(proxy_address_pool *address_pool); ++void proxy_address_pool_add(proxy_address_pool *address_pool, proxy_address *address); ++int proxy_address_pool_add_string(proxy_address_pool *address_pool, buffer *address); ++ ++#endif +--- ../lighttpd-1.4.11/src/mod_proxy_core_backend.c 1970-01-01 03:00:00.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_proxy_core_backend.c 2006-07-18 13:03:40.000000000 +0300 +@@ -0,0 +1,45 @@ ++#include ++ ++#include "mod_proxy_core_backend.h" ++#include "mod_proxy_core_pool.h" ++#include "mod_proxy_core_address.h" ++ ++proxy_backend *proxy_backend_init(void) { ++ proxy_backend *backend; ++ ++ backend = calloc(1, sizeof(*backend)); ++ backend->pool = proxy_connection_pool_init(); ++ backend->address_pool = proxy_address_pool_init(); ++ backend->balancer = PROXY_BALANCE_RR; ++ ++ return backend; ++} ++ ++void proxy_backend_free(proxy_backend *backend) { ++ if (!backend) return; ++ ++ proxy_address_pool_free(backend->address_pool); ++ proxy_connection_pool_free(backend->pool); ++ ++ free(backend); ++} ++ ++proxy_backends *proxy_backends_init(void) { ++ proxy_backends *backends; ++ ++ backends = calloc(1, sizeof(*backends)); ++ ++ return backends; ++} ++ ++void proxy_backends_free(proxy_backends *backends) { ++ FOREACH(backends, element, proxy_backend_free(element)) ++ ++ free(backends); ++} ++ ++void proxy_backends_add(proxy_backends *backends, proxy_backend *backend) { ++ ARRAY_STATIC_PREPARE_APPEND(backends); ++ ++ backends->ptr[backends->used++] = backend; ++} +--- ../lighttpd-1.4.11/src/mod_proxy_core_backend.h 1970-01-01 03:00:00.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_proxy_core_backend.h 2006-07-18 13:03:40.000000000 +0300 +@@ -0,0 +1,54 @@ ++#ifndef _MOD_PROXY_CORE_BACKEND_H_ ++#define _MOD_PROXY_CORE_BACKEND_H_ ++ ++#include "array-static.h" ++#include "buffer.h" ++#include "mod_proxy_core_address.h" ++#include "mod_proxy_core_pool.h" ++#include "sys-socket.h" ++ ++/** ++ * a single DNS name might explode to several IP addresses ++ * ++ * url: ++ * - http://foo.bar/suburl/ ++ * - https://foo.bar/suburl/ ++ * - unix:/tmp/socket ++ * - tcp://foobar:1025/ ++ * ++ * backend: ++ * - scgi ++ * - http ++ * - fastcgi ++ * ++ * request-url-rewrite ++ * response-url-rewrite ++ */ ++typedef enum { ++ PROXY_BALANCE_UNSET, ++ PROXY_BALANCE_FAIR, ++ PROXY_BALANCE_HASH, ++ PROXY_BALANCE_RR ++} proxy_balance_t; ++ ++typedef struct { ++ buffer *url; ++ ++ proxy_connection_pool *pool; /* pool of active connections */ ++ int use_keepalive; ++ ++ proxy_address_pool *address_pool; /* possible destination-addresses, disabling is done here */ ++ proxy_balance_t balancer; /* how to choose a address from the address-pool */ ++} proxy_backend; ++ ++ARRAY_STATIC_DEF(proxy_backends, proxy_backend, ); ++ ++proxy_backend *proxy_backend_init(void); ++void proxy_backend_free(proxy_backend *backend); ++ ++proxy_backends *proxy_backends_init(void); ++void proxy_backends_free(proxy_backends *backends); ++void proxy_backends_add(proxy_backends *backends, proxy_backend *backend); ++ ++#endif ++ +--- ../lighttpd-1.4.11/src/mod_proxy_core_backlog.c 1970-01-01 03:00:00.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_proxy_core_backlog.c 2006-07-18 13:03:40.000000000 +0300 +@@ -0,0 +1,109 @@ ++#include ++ ++#include "mod_proxy_core_backlog.h" ++#include "array-static.h" ++ ++proxy_backlog *proxy_backlog_init(void) { ++ STRUCT_INIT(proxy_backlog, backlog); ++ ++ return backlog; ++} ++ ++void proxy_backlog_free(proxy_backlog *backlog) { ++ if (!backlog) return; ++ ++ free(backlog); ++} ++ ++int proxy_backlog_push(proxy_backlog *backlog, proxy_request *req) { ++ /* first entry */ ++ if (NULL == backlog->first) { ++ backlog->first = backlog->last = req; ++ } else { ++ backlog->last->next = req; ++ backlog->last = req; ++ } ++ backlog->length++; ++ ++ return 0; ++} ++ ++/** ++ * remove the first element from the backlog ++ */ ++proxy_request *proxy_backlog_shift(proxy_backlog *backlog) { ++ proxy_request *req = NULL; ++ ++ if (!backlog->first) return req; ++ ++ backlog->length--; ++ ++ req = backlog->first; ++ ++ backlog->first = req->next; ++ ++ /* the backlog is empty */ ++ if (backlog->first == NULL) backlog->last = NULL; ++ ++ return req; ++} ++ ++int proxy_backlog_remove_connection(proxy_backlog *backlog, void *con) { ++ proxy_request *req = NULL; ++ ++ if (!backlog->first) return -1; ++ if (!con) return -1; ++ ++ /* the first element is what we look for */ ++ if (backlog->first->con == con) { ++ req = backlog->first; ++ ++ backlog->first = req->next; ++ if (backlog->first == NULL) backlog->last = NULL; ++ ++ backlog->length--; ++ ++ proxy_request_free(req); ++ ++ return 0; ++ } ++ ++ ++ for (req = backlog->first; req && req->next; req = req->next) { ++ proxy_request *cur; ++ ++ if (req->next->con != con) continue; ++ ++ backlog->length--; ++ /* the next node is our searched connection */ ++ ++ cur = req->next; ++ req->next = cur->next; ++ ++ /* the next node is the last one, make the current the new last */ ++ if (cur == backlog->last) { ++ backlog->last = req; ++ } ++ cur->next = NULL; ++ ++ proxy_request_free(req); ++ ++ return 0; ++ } ++ ++ return -1; ++} ++ ++proxy_request *proxy_request_init(void) { ++ STRUCT_INIT(proxy_request, request); ++ ++ return request; ++} ++ ++void proxy_request_free(proxy_request *request) { ++ if (!request) return; ++ ++ free(request); ++} ++ ++ +--- ../lighttpd-1.4.11/src/mod_proxy_core_backlog.h 1970-01-01 03:00:00.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_proxy_core_backlog.h 2006-07-18 13:03:40.000000000 +0300 +@@ -0,0 +1,56 @@ ++#ifndef _MOD_PROXY_CORE_BACKLOG_H_ ++#define _MOD_PROXY_CORE_BACKLOG_H_ ++ ++#include ++#include ++ ++typedef struct _proxy_request { ++ void *con; /* a pointer to the client-connection, (type: connection) */ ++ ++ time_t added_ts; /* when was the entry added (for timeout handling) */ ++ ++ struct _proxy_request *next; ++} proxy_request; ++ ++/** ++ * a we can't get a connection from the pool, queue the request in the ++ * request queue (FIFO) ++ * ++ * - the queue is infinite ++ * - entries are removed after a timeout (status 504) ++ */ ++typedef struct { ++ proxy_request *first; /* pull() does q->first = q->first->next */ ++ proxy_request *last; /* push() does q->last = r */ ++ ++ size_t length; ++} proxy_backlog; ++ ++proxy_backlog *proxy_backlog_init(void); ++void proxy_backlog_free(proxy_backlog *backlog); ++ ++/** ++ * append a request to the end ++ * ++ * @return 0 in success, -1 if full ++ */ ++int proxy_backlog_push(proxy_backlog *backlog, proxy_request *req); ++ ++/** ++ * remove the first request from the backlog ++ * ++ * @return NULL if backlog is empty, the request otherwise ++ */ ++proxy_request *proxy_backlog_shift(proxy_backlog *backlog); ++/** ++ * remove the request with the connection 'con' from the backlog ++ * ++ * @return -1 if not found, 0 otherwise ++ */ ++int proxy_backlog_remove_connection(proxy_backlog *backlog, void *con); ++ ++proxy_request *proxy_request_init(void); ++void proxy_request_free(proxy_request *req); ++ ++#endif ++ +--- ../lighttpd-1.4.11/src/mod_proxy_core_pool.c 1970-01-01 03:00:00.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_proxy_core_pool.c 2006-07-18 13:03:40.000000000 +0300 +@@ -0,0 +1,127 @@ ++ ++#include ++ ++#include "array-static.h" ++#include "sys-files.h" ++#include "log.h" ++#include "mod_proxy_core_pool.h" ++ ++proxy_connection * proxy_connection_init(void) { ++ proxy_connection *con; ++ ++ con = calloc(1, sizeof(*con)); ++ ++ con->sock = iosocket_init(); ++ ++ return con; ++} ++ ++void proxy_connection_free(proxy_connection *con) { ++ if (!con) return; ++ ++ iosocket_free(con->sock); ++ ++ free(con); ++} ++ ++proxy_connection_pool *proxy_connection_pool_init(void) { ++ proxy_connection_pool *pool; ++ ++ pool = calloc(1, sizeof(*pool)); ++ ++ /* default: max parallel connections to the backend ++ * ++ * this should match max-procs if we manage the procs ourself ++ */ ++ ++ pool->max_size = 8; ++ ++ return pool; ++} ++ ++void proxy_connection_pool_free(proxy_connection_pool *pool) { ++ size_t i; ++ ++ if (!pool) return; ++ ++ for (i = 0; i < pool->used; i++) { ++ proxy_connection_free(pool->ptr[i]); ++ } ++ ++ if (pool->size) free(pool->ptr); ++ ++ free(pool); ++} ++ ++void proxy_connection_pool_add_connection(proxy_connection_pool *pool, proxy_connection *c) { ++ ARRAY_STATIC_PREPARE_APPEND(pool); ++ ++ pool->ptr[pool->used++] = c; ++} ++/** ++ * remove the connection from the pool ++ * ++ * usually called on conn-shutdown ++ */ ++int proxy_connection_pool_remove_connection(proxy_connection_pool *pool, proxy_connection *c) { ++ size_t i; ++ ++ if (pool->used == 0) return -1; /* empty */ ++ ++ for (i = 0; i < pool->used; i++) { ++ if (pool->ptr[i] == c) { ++ break; ++ } ++ } ++ ++ if (i == pool->used) return -1; /* not found */ ++ ++ /** ++ * move all elements one to the left ++ * ++ * if the last element is going to be removed, skip the loop ++ */ ++ for (; i < pool->used - 1; i++) { ++ pool->ptr[i] = pool->ptr[i + 1]; ++ } ++ ++ pool->used--; ++ ++ return 0; ++} ++ ++proxy_connection_pool_t proxy_connection_pool_get_connection(proxy_connection_pool *pool, proxy_address *address, proxy_connection **rcon) { ++ proxy_connection *proxy_con = NULL; ++ size_t i; ++ ++ /* search for a idling proxy connection with the given address */ ++ for (i = 0; i < pool->used; i++) { ++ proxy_con = pool->ptr[i]; ++ ++ if (proxy_con->address == address && ++ proxy_con->state == PROXY_CONNECTION_STATE_IDLE) { ++ break; ++ } ++ } ++ ++ if (i == pool->used) { ++ /* no idling connection found */ ++ ++ if (pool->used == pool->max_size) return PROXY_CONNECTIONPOOL_FULL; ++ ++ proxy_con = proxy_connection_init(); ++ ++ proxy_con->state = PROXY_CONNECTION_STATE_CONNECTING; ++ proxy_con->address = address; ++ ++ proxy_connection_pool_add_connection(pool, proxy_con); ++ } else { ++ proxy_con->state = PROXY_CONNECTION_STATE_CONNECTED; ++ } ++ ++ *rcon = proxy_con; ++ ++ return PROXY_CONNECTIONPOOL_GOT_CONNECTION; ++} ++ ++ +--- ../lighttpd-1.4.11/src/mod_proxy_core_pool.h 1970-01-01 03:00:00.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_proxy_core_pool.h 2006-07-18 13:03:40.000000000 +0300 +@@ -0,0 +1,52 @@ ++#ifndef _MOD_PROXY_CORE_POOL_H_ ++#define _MOD_PROXY_CORE_POOL_H_ ++ ++#include ++ ++#include "iosocket.h" ++#include "array-static.h" ++#include "mod_proxy_core_address.h" ++ ++typedef enum { ++ PROXY_CONNECTION_STATE_UNSET, ++ PROXY_CONNECTION_STATE_CONNECTING, ++ PROXY_CONNECTION_STATE_CONNECTED, ++ PROXY_CONNECTION_STATE_IDLE, ++ PROXY_CONNECTION_STATE_CLOSED, ++} proxy_connection_state_t; ++ ++/** ++ * a connection to a proxy backend ++ * ++ * the connection is independent of the incoming request to allow keep-alive ++ */ ++typedef struct { ++ iosocket *sock; ++ ++ time_t last_read; /* timeout handling for keep-alive connections */ ++ time_t last_write; ++ ++ proxy_address *address; /* the struct sock_addr for the sock */ ++ ++ proxy_connection_state_t state; ++} proxy_connection; ++ ++ARRAY_STATIC_DEF(proxy_connection_pool, proxy_connection, size_t max_size;); ++ ++typedef enum { ++ PROXY_CONNECTIONPOOL_UNSET, ++ PROXY_CONNECTIONPOOL_FULL, ++ PROXY_CONNECTIONPOOL_GOT_CONNECTION, ++} proxy_connection_pool_t; ++ ++proxy_connection_pool *proxy_connection_pool_init(void); ++void proxy_connection_pool_free(proxy_connection_pool *pool); ++ ++proxy_connection_pool_t proxy_connection_pool_get_connection(proxy_connection_pool *pool, proxy_address *address, proxy_connection **rcon); ++int proxy_connection_pool_remove_connection(proxy_connection_pool *pool, proxy_connection *c); ++ ++proxy_connection * proxy_connection_init(void); ++void proxy_connection_free(proxy_connection *pool); ++ ++#endif ++ +--- ../lighttpd-1.4.11/src/mod_redirect.c 2006-02-08 15:38:06.000000000 +0200 ++++ lighttpd-1.4.12/src/mod_redirect.c 2006-07-16 00:26:04.000000000 +0300 +@@ -22,35 +22,35 @@ + PLUGIN_DATA; + buffer *match_buf; + buffer *location; +- ++ + plugin_config **config_storage; +- +- plugin_config conf; ++ ++ plugin_config conf; + } plugin_data; + + INIT_FUNC(mod_redirect_init) { + plugin_data *p; +- ++ + p = calloc(1, sizeof(*p)); +- ++ + p->match_buf = buffer_init(); + p->location = buffer_init(); +- ++ + return p; + } + + FREE_FUNC(mod_redirect_free) { + plugin_data *p = p_d; +- ++ + 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]; +- ++ + pcre_keyvalue_buffer_free(s->redirect); +- ++ + free(s); + } + free(p->config_storage); +@@ -59,9 +59,9 @@ + + buffer_free(p->match_buf); + buffer_free(p->location); +- ++ + free(p); +- ++ + return HANDLER_GO_ON; + } + +@@ -69,195 +69,137 @@ + plugin_data *p = p_d; + data_unset *du; + size_t i = 0; +- +- config_values_t cv[] = { ++ ++ config_values_t cv[] = { + { "url.redirect", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ + { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } + }; +- ++ + if (!p) return HANDLER_ERROR; +- ++ + /* 0 */ + p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *)); +- ++ + for (i = 0; i < srv->config_context->used; i++) { + plugin_config *s; + size_t j; + array *ca; + data_array *da = (data_array *)du; +- ++ + s = calloc(1, sizeof(plugin_config)); + s->redirect = pcre_keyvalue_buffer_init(); +- ++ + cv[0].destination = s->redirect; +- ++ + p->config_storage[i] = s; + ca = ((data_config *)srv->config_context->data[i])->value; +- ++ + if (0 != config_insert_values_global(srv, ca, cv)) { + return HANDLER_ERROR; + } +- ++ + if (NULL == (du = array_get_element(ca, "url.redirect"))) { + /* no url.redirect defined */ + continue; + } +- ++ + if (du->type != TYPE_ARRAY) { +- log_error_write(srv, __FILE__, __LINE__, "sss", ++ log_error_write(srv, __FILE__, __LINE__, "sss", + "unexpected type for key: ", "url.redirect", "array of strings"); +- ++ + return HANDLER_ERROR; + } +- ++ + da = (data_array *)du; +- ++ + for (j = 0; j < da->value->used; j++) { + if (da->value->data[j]->type != TYPE_STRING) { +- log_error_write(srv, __FILE__, __LINE__, "sssbs", +- "unexpected type for key: ", +- "url.redirect", ++ log_error_write(srv, __FILE__, __LINE__, "sssbs", ++ "unexpected type for key: ", ++ "url.redirect", + "[", da->value->data[j]->key, "](string)"); +- ++ + return HANDLER_ERROR; + } +- +- if (0 != pcre_keyvalue_buffer_append(s->redirect, ++ ++ if (0 != pcre_keyvalue_buffer_append(s->redirect, + ((data_string *)(da->value->data[j]))->key->ptr, + ((data_string *)(da->value->data[j]))->value->ptr)) { +- +- log_error_write(srv, __FILE__, __LINE__, "sb", ++ ++ log_error_write(srv, __FILE__, __LINE__, "sb", + "pcre-compile failed for", da->value->data[j]->key); + } + } + } +- ++ + return HANDLER_GO_ON; + } + #ifdef HAVE_PCRE_H + static int mod_redirect_patch_connection(server *srv, connection *con, plugin_data *p) { + size_t i, j; + plugin_config *s = p->config_storage[0]; +- ++ + p->conf.redirect = s->redirect; +- ++ + /* 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 (0 == strcmp(du->key->ptr, "url.redirect")) { + p->conf.redirect = s->redirect; + p->conf.context = dc; + } + } + } +- ++ + return 0; + } + #endif + static handler_t mod_redirect_uri_handler(server *srv, connection *con, void *p_data) { + #ifdef HAVE_PCRE_H + plugin_data *p = p_data; +- size_t i; ++ int i; + +- /* ++ /* + * REWRITE URL +- * ++ * + * e.g. redirect /base/ to /index.php?section=base +- * ++ * + */ +- ++ + mod_redirect_patch_connection(srv, con, p); +- ++ + buffer_copy_string_buffer(p->match_buf, con->request.uri); +- +- for (i = 0; i < p->conf.redirect->used; i++) { +- pcre *match; +- pcre_extra *extra; +- const char *pattern; +- size_t pattern_len; +- int n; +- pcre_keyvalue *kv = p->conf.redirect->kv[i]; +-# define N 10 +- int ovec[N * 3]; +- +- match = kv->key; +- extra = kv->key_extra; +- pattern = kv->value->ptr; +- pattern_len = kv->value->used - 1; +- +- if ((n = pcre_exec(match, extra, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) { +- if (n != PCRE_ERROR_NOMATCH) { +- log_error_write(srv, __FILE__, __LINE__, "sd", +- "execution error while matching: ", n); - return HANDLER_ERROR; - } - } else { @@ -27767,7 +31159,7 @@ return 0; } --- ../lighttpd-1.4.11/src/mod_rewrite.c 2005-09-29 20:59:10.000000000 +0300 -+++ lighttpd-1.4.12/src/mod_rewrite.c 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_rewrite.c 2006-07-16 00:26:03.000000000 +0300 @@ -13,24 +13,8 @@ #endif @@ -28301,7 +31693,7 @@ return 0; } --- ../lighttpd-1.4.11/src/mod_rrdtool.c 2005-08-22 01:52:24.000000000 +0300 -+++ lighttpd-1.4.12/src/mod_rrdtool.c 2006-07-11 22:07:52.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_rrdtool.c 2006-07-18 13:03:40.000000000 +0300 @@ -5,7 +5,6 @@ #include #include @@ -28433,7 +31825,7 @@ /* fork, execve */ switch (pid = fork()) { case 0: { -@@ -117,33 +120,33 @@ +@@ -117,33 +120,28 @@ int argc; int i = 0; char *dash = "-"; @@ -28457,11 +31849,10 @@ + close(STDERR_FILENO); - -+ - if (srv->errorlog_mode == ERRORLOG_FILE) { - dup2(srv->errorlog_fd, STDERR_FILENO); - close(srv->errorlog_fd); - } +- if (srv->errorlog_mode == ERRORLOG_FILE) { +- dup2(srv->errorlog_fd, STDERR_FILENO); +- close(srv->errorlog_fd); +- } - + /* set up args */ @@ -28473,7 +31864,7 @@ args[i++] = p->conf.path_rrdtool_bin->ptr; args[i++] = dash; args[i++] = NULL; -@@ -152,12 +155,12 @@ +@@ -152,12 +150,12 @@ for (i = 3; i < 256; i++) { close(i); } @@ -28489,7 +31880,7 @@ /* */ SEGFAULT(); break; -@@ -168,19 +171,19 @@ +@@ -168,19 +166,19 @@ break; default: { /* father */ @@ -28513,7 +31904,7 @@ return 0; #else return -1; -@@ -189,19 +192,19 @@ +@@ -189,19 +187,19 @@ static int mod_rrdtool_create_rrd(server *srv, plugin_data *p, plugin_config *s) { struct stat st; @@ -28536,7 +31927,7 @@ BUFFER_COPY_STRING_CONST(p->cmd, "create "); buffer_append_string_buffer(p->cmd, s->path_rrd); buffer_append_string(p->cmd, " --step 60 "); -@@ -220,158 +223,155 @@ +@@ -220,158 +218,155 @@ buffer_append_string(p->cmd, "RRA:MIN:0.5:6:700 "); buffer_append_string(p->cmd, "RRA:MIN:0.5:24:775 "); buffer_append_string(p->cmd, "RRA:MIN:0.5:288:797\n"); @@ -28744,7 +32135,7 @@ BUFFER_COPY_STRING_CONST(p->cmd, "update "); buffer_append_string_buffer(p->cmd, s->path_rrd); BUFFER_APPEND_STRING_CONST(p->cmd, " N:"); -@@ -381,69 +381,69 @@ +@@ -381,69 +376,69 @@ BUFFER_APPEND_STRING_CONST(p->cmd, ":"); buffer_append_long(p->cmd, s->requests); BUFFER_APPEND_STRING_CONST(p->cmd, "\n"); @@ -28836,14 +32227,22 @@ return 0; } --- ../lighttpd-1.4.11/src/mod_scgi.c 2006-03-04 17:15:26.000000000 +0200 -+++ lighttpd-1.4.12/src/mod_scgi.c 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_scgi.c 2006-07-18 13:03:40.000000000 +0300 @@ -1,5 +1,4 @@ #include -#include #include #include #include -@@ -30,7 +29,9 @@ +@@ -18,6 +17,7 @@ + #include "connections.h" + #include "response.h" + #include "joblist.h" ++#include "http_resp.h" + + #include "plugin.h" + +@@ -30,7 +30,9 @@ #endif #include "sys-socket.h" @@ -28854,7 +32253,7 @@ #ifndef UNIX_PATH_MAX # define UNIX_PATH_MAX 108 -@@ -46,30 +47,29 @@ +@@ -46,30 +48,29 @@ enum {EOL_UNSET, EOL_N, EOL_RN}; /* @@ -28891,7 +32290,7 @@ int is_local; enum { PROC_STATE_UNSET, /* init-phase */ -@@ -78,7 +78,7 @@ +@@ -78,7 +79,7 @@ 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 */ @@ -28900,7 +32299,7 @@ } scgi_proc; typedef struct { -@@ -86,20 +86,20 @@ +@@ -86,20 +87,20 @@ * sorted by lowest load * * whenever a job is done move it up in the list @@ -28928,7 +32327,7 @@ */ unsigned short min_procs; -@@ -111,44 +111,44 @@ +@@ -111,44 +112,44 @@ /* * kick the process from the list if it was not @@ -28988,7 +32387,7 @@ unsigned short port; /* -@@ -161,7 +161,7 @@ +@@ -161,7 +162,7 @@ */ buffer *unixsocket; @@ -28997,7 +32396,7 @@ * process ourself * * bin-path is the path to the binary -@@ -169,19 +169,19 @@ +@@ -169,19 +170,19 @@ * check min_procs and max_procs for the number * of process to start-up */ @@ -29024,7 +32423,7 @@ * remote host * * reasons: -@@ -192,7 +192,7 @@ +@@ -192,7 +193,7 @@ buffer *docroot; /* @@ -29033,7 +32432,7 @@ * or not. FastCGI doesn't care if the service is * remote. If the web-server side doesn't contain * the scgi-files we should not stat() for them -@@ -202,33 +202,33 @@ +@@ -202,33 +203,33 @@ /* * append PATH_INFO to SCRIPT_FILENAME @@ -29074,7 +32473,7 @@ * * in case of PHP and FCGI_CHILDREN we have again a procs * but we don't control it directly. -@@ -239,7 +239,7 @@ +@@ -239,7 +240,7 @@ buffer *key; /* like .php */ scgi_extension_host **hosts; @@ -29083,7 +32482,7 @@ size_t used; size_t size; } scgi_extension; -@@ -253,14 +253,14 @@ +@@ -253,14 +254,14 @@ typedef struct { @@ -29101,7 +32500,7 @@ size_t size; size_t used; } char_array; -@@ -268,52 +268,51 @@ +@@ -268,52 +269,51 @@ /* generic plugin data, shared between all connections */ typedef struct { PLUGIN_DATA; @@ -29111,8 +32510,10 @@ - + buffer *path; - buffer *parse_response; +- buffer *parse_response; - ++ ++ http_resp *resp; + plugin_config **config_storage; - @@ -29123,18 +32524,22 @@ /* connection specific data */ -typedef enum { FCGI_STATE_INIT, FCGI_STATE_CONNECT, FCGI_STATE_PREPARE_WRITE, - FCGI_STATE_WRITE, FCGI_STATE_READ -+typedef enum { FCGI_STATE_INIT, FCGI_STATE_CONNECT, FCGI_STATE_PREPARE_WRITE, -+ FCGI_STATE_WRITE, FCGI_STATE_READ ++typedef enum { ++ SCGI_STATE_INIT, ++ SCGI_STATE_CONNECT, ++ SCGI_STATE_PREPARE_WRITE, ++ SCGI_STATE_WRITE, ++ SCGI_STATE_RESPONSE_HEADER, ++ SCGI_STATE_RESPONSE_CONTENT, ++ SCGI_STATE_ERROR } scgi_connection_state_t; typedef struct { - buffer *response; -+ buffer *response; - size_t response_len; - int response_type; - int response_padding; +- size_t response_len; +- int response_type; +- int response_padding; - -+ scgi_proc *proc; scgi_extension_host *host; - @@ -29145,21 +32550,22 @@ + int reconnects; /* number of reconnect attempts */ - +- read_buffer *rb; + - read_buffer *rb; ++ chunkqueue *rb; chunkqueue *wb; - -+ - buffer *response_header; +- buffer *response_header; - + int delayed; /* flag to mark that the connect() is delayed */ - + size_t request_id; - int fd; /* fd to the scgi process */ - int fde_ndx; /* index into the fd-event buffer */ -- +- int fd; /* fd to the scgi process */ +- int fde_ndx; /* index into the fd-event buffer */ ++ iosocket *sock; /* fd to the scgi process */ + pid_t pid; int got_proc; - @@ -29170,7 +32576,7 @@ connection *remote_conn; /* dumb pointer */ plugin_data *plugin_data; /* dumb pointer */ } handler_ctx; -@@ -328,28 +327,28 @@ +@@ -328,42 +328,30 @@ static handler_ctx * handler_ctx_init() { handler_ctx * hctx; @@ -29179,49 +32585,53 @@ hctx = calloc(1, sizeof(*hctx)); assert(hctx); - -+ - hctx->fde_ndx = -1; +- hctx->fde_ndx = -1; - -+ - hctx->response = buffer_init(); - hctx->response_header = buffer_init(); +- hctx->response = buffer_init(); +- hctx->response_header = buffer_init(); - ++ ++ hctx->sock = iosocket_init();; + hctx->request_id = 0; - hctx->state = FCGI_STATE_INIT; +- hctx->state = FCGI_STATE_INIT; ++ hctx->state = SCGI_STATE_INIT; hctx->proc = NULL; - -+ - hctx->response_len = 0; - hctx->response_type = 0; - hctx->response_padding = 0; - hctx->fd = -1; +- hctx->response_len = 0; +- hctx->response_type = 0; +- hctx->response_padding = 0; +- hctx->fd = -1; - + hctx->reconnects = 0; hctx->wb = chunkqueue_init(); - ++ hctx->rb = chunkqueue_init(); + return hctx; } -@@ -358,12 +357,12 @@ - buffer_free(hctx->response_header); - + static void handler_ctx_free(handler_ctx *hctx) { +- buffer_free(hctx->response); +- buffer_free(hctx->response_header); +- chunkqueue_free(hctx->wb); - -+ - if (hctx->rb) { - if (hctx->rb->ptr) free(hctx->rb->ptr); - free(hctx->rb); - } +- if (hctx->rb) { +- if (hctx->rb->ptr) free(hctx->rb->ptr); +- free(hctx->rb); +- } - ++ chunkqueue_free(hctx->rb); ++ ++ iosocket_free(hctx->sock); + free(hctx); } -@@ -372,20 +371,20 @@ +@@ -372,20 +360,20 @@ f = calloc(1, sizeof(*f)); f->socket = buffer_init(); @@ -29247,7 +32657,7 @@ free(f); } -@@ -400,62 +399,62 @@ +@@ -400,62 +388,62 @@ f->bin_path = buffer_init(); f->bin_env = array_init(); f->bin_env_copy = array_init(); @@ -29326,7 +32736,7 @@ free(f); } -@@ -504,99 +503,103 @@ +@@ -504,99 +492,103 @@ assert(fe->hosts); } @@ -29349,8 +32759,9 @@ - + p->path = buffer_init(); - p->parse_response = buffer_init(); +- p->parse_response = buffer_init(); - ++ p->resp = http_response_init(); + return p; } @@ -29364,8 +32775,9 @@ buffer_free(p->scgi_env); buffer_free(p->path); - buffer_free(p->parse_response); +- buffer_free(p->parse_response); - ++ http_response_free(p->resp); + if (p->config_storage) { size_t i, j, n; @@ -29456,7 +32868,7 @@ if (env->size == 0) { env->size = 16; env->ptr = malloc(env->size * sizeof(*env->ptr)); -@@ -604,13 +607,13 @@ +@@ -604,13 +596,13 @@ env->size += 16; env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr)); } @@ -29473,7 +32885,7 @@ plugin_data *p, scgi_extension_host *host, scgi_proc *proc) { -@@ -622,31 +625,27 @@ +@@ -622,31 +614,27 @@ #endif struct sockaddr_in scgi_addr_in; struct sockaddr *scgi_addr; @@ -29512,7 +32924,7 @@ socket_type = AF_UNIX; scgi_addr = (struct sockaddr *) &scgi_addr_un; #else -@@ -656,115 +655,115 @@ +@@ -656,115 +644,115 @@ #endif } else { scgi_addr_in.sin_family = AF_INET; @@ -29662,7 +33074,7 @@ if (NULL != (ge = getenv(ds->value->ptr))) { env_add(&env, CONST_BUF_LEN(ds->value), ge, strlen(ge)); } -@@ -772,44 +771,44 @@ +@@ -772,44 +760,44 @@ } else { for (i = 0; environ[i]; i++) { char *eq; @@ -29719,7 +33131,7 @@ break; } case -1: -@@ -817,32 +816,32 @@ +@@ -817,32 +805,32 @@ break; default: /* father */ @@ -29761,7 +33173,7 @@ status); } return -1; -@@ -852,26 +851,26 @@ +@@ -852,26 +840,26 @@ proc->pid = child; proc->last_used = srv->cur_ts; proc->is_local = 1; @@ -29793,7 +33205,7 @@ return 0; } -@@ -880,89 +879,89 @@ +@@ -880,89 +868,89 @@ plugin_data *p = p_d; data_unset *du; size_t i = 0; @@ -29919,7 +33331,7 @@ { "check-local", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 4 */ { "port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 5 */ { "min-procs-not-working", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 7 this is broken for now */ -@@ -970,37 +969,37 @@ +@@ -970,37 +958,37 @@ { "max-load-per-proc", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 8 */ { "idle-timeout", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 9 */ { "disable-time", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 10 */ @@ -29969,7 +33381,7 @@ fcv[4].destination = &(df->check_local); fcv[5].destination = &(df->port); fcv[6].destination = &(df->min_procs); -@@ -1008,47 +1007,47 @@ +@@ -1008,47 +996,47 @@ fcv[8].destination = &(df->max_load_per_proc); fcv[9].destination = &(df->idle_timeout); fcv[10].destination = &(df->disable_time); @@ -30034,7 +33446,7 @@ da->key, da_ext->key, da_host->key, -@@ -1056,14 +1055,14 @@ +@@ -1056,14 +1044,14 @@ return HANDLER_ERROR; } } @@ -30053,7 +33465,7 @@ if (s->debug) { log_error_write(srv, __FILE__, __LINE__, "ssbsdsbsdsd", "--- scgi spawning local", -@@ -1073,7 +1072,7 @@ +@@ -1073,7 +1061,7 @@ "\n\tmin-procs:", df->min_procs, "\n\tmax-procs:", df->max_procs); } @@ -30062,7 +33474,7 @@ for (pno = 0; pno < df->min_procs; pno++) { scgi_proc *proc; -@@ -1088,7 +1087,7 @@ +@@ -1088,7 +1076,7 @@ buffer_append_string(proc->socket, "-"); buffer_append_long(proc->socket, pno); } @@ -30071,7 +33483,7 @@ if (s->debug) { log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd", "--- scgi spawning", -@@ -1096,53 +1095,53 @@ +@@ -1096,53 +1084,53 @@ "\n\tsocket", df->unixsocket, "\n\tcurrent:", pno, "/", df->min_procs); } @@ -30135,7 +33547,7 @@ return 0; } -@@ -1150,34 +1149,34 @@ +@@ -1150,35 +1138,35 @@ void scgi_connection_cleanup(server *srv, handler_ctx *hctx) { plugin_data *p; connection *con; @@ -30149,15 +33561,20 @@ - + if (con->mode != p->id) { - WP(); +- WP(); return; } - +- if (hctx->fd != -1) { +- fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); +- fdevent_unregister(srv->ev, hctx->fd); +- close(hctx->fd); + - if (hctx->fd != -1) { - fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); - fdevent_unregister(srv->ev, hctx->fd); - close(hctx->fd); ++ if (hctx->sock->fd != -1) { ++ fdevent_event_del(srv->ev, hctx->sock); ++ fdevent_unregister(srv->ev, hctx->sock); ++ closesocket(hctx->sock->fd); ++ hctx->sock->fd = -1; srv->cur_fds--; } - @@ -30174,11 +33591,13 @@ if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "sddb", - "release proc:", +- hctx->fd, + "release proc:", - hctx->fd, ++ hctx->sock->fd, hctx->proc->pid, hctx->proc->socket); } -@@ -1186,87 +1185,87 @@ + } +@@ -1186,87 +1174,87 @@ scgi_proclist_sort_down(srv, hctx->host, hctx->proc); } @@ -30224,15 +33643,19 @@ + * */ - +- fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); +- fdevent_unregister(srv->ev, hctx->fd); +- close(hctx->fd); + - fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); - fdevent_unregister(srv->ev, hctx->fd); - close(hctx->fd); ++ fdevent_event_del(srv->ev, hctx->sock); ++ fdevent_unregister(srv->ev, hctx->sock); ++ closesocket(hctx->sock->fd); srv->cur_fds--; - -+ - scgi_set_state(srv, hctx, FCGI_STATE_INIT); +- scgi_set_state(srv, hctx, FCGI_STATE_INIT); - ++ ++ scgi_set_state(srv, hctx, SCGI_STATE_INIT); + hctx->request_id = 0; hctx->reconnects++; @@ -30241,8 +33664,9 @@ if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "sddb", - "release proc:", +- hctx->fd, + "release proc:", - hctx->fd, ++ hctx->sock->fd, hctx->proc->pid, hctx->proc->socket); } - @@ -30296,7 +33720,7 @@ * returns * -1 error * 0 connected -@@ -1280,24 +1279,21 @@ +@@ -1280,24 +1268,21 @@ struct sockaddr_un scgi_addr_un; #endif socklen_t servlen; @@ -30304,8 +33728,9 @@ + scgi_extension_host *host = hctx->host; scgi_proc *proc = hctx->proc; - int scgi_fd = hctx->fd; +- int scgi_fd = hctx->fd; - ++ int scgi_fd = hctx->sock->fd; + memset(&scgi_addr, 0, sizeof(scgi_addr)); - @@ -30326,7 +33751,7 @@ scgi_addr = (struct sockaddr *) &scgi_addr_un; #else return -1; -@@ -1305,105 +1301,105 @@ +@@ -1305,105 +1290,105 @@ } else { scgi_addr_in.sin_family = AF_INET; if (0 == inet_aton(host->host->ptr, &(scgi_addr_in.sin_addr))) { @@ -30464,7 +33889,7 @@ return 0; } -@@ -1415,20 +1411,20 @@ +@@ -1415,20 +1400,20 @@ char b2[INET6_ADDRSTRLEN + 1]; #endif buffer *b; @@ -30489,7 +33914,7 @@ /* request.content_length < SSIZE_MAX, see request.c */ ltostr(buf, con->request.content_length); scgi_env_add(p->scgi_env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf)); -@@ -1436,13 +1432,13 @@ +@@ -1436,13 +1421,13 @@ scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION)); @@ -30506,7 +33931,7 @@ (const void *) &(srv_sock->addr.ipv6.sin6_addr) : (const void *) &(srv_sock->addr.ipv4.sin_addr), b2, sizeof(b2)-1); -@@ -1451,47 +1447,47 @@ +@@ -1451,47 +1436,47 @@ #endif scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s)); } @@ -30531,8 +33956,9 @@ /* get the server-side of the connection to the client */ our_addr_len = sizeof(our_addr); - +- if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) { + - if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) { ++ if (-1 == getsockname(con->sock->fd, &(our_addr.plain), &our_addr_len)) { s = inet_ntop_cache_get_ip(srv, &(srv_sock->addr)); } else { s = inet_ntop_cache_get_ip(srv, &(our_addr)); @@ -30566,7 +33992,7 @@ /* * SCRIPT_NAME, PATH_INFO and PATH_TRANSLATED according to -@@ -1500,12 +1496,12 @@ +@@ -1500,12 +1485,12 @@ */ scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path)); @@ -30582,7 +34008,7 @@ if (!buffer_is_empty(host->docroot)) { buffer_copy_string_buffer(p->path, host->docroot); } else { -@@ -1526,19 +1522,19 @@ +@@ -1526,19 +1511,19 @@ */ if (!buffer_is_empty(host->docroot)) { @@ -30608,7 +34034,7 @@ scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path)); scgi_env_add(p->scgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root)); } -@@ -1551,30 +1547,30 @@ +@@ -1551,30 +1536,30 @@ } else { scgi_env_add(p->scgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN("")); } @@ -30644,7 +34070,7 @@ if (con->request.content_length) { chunkqueue *req_cq = con->request_content_queue; chunk *req_c; -@@ -1587,7 +1583,7 @@ +@@ -1587,7 +1572,7 @@ /* we announce toWrite octects * now take all the request_content chunk that we need to fill this request @@ -30653,7 +34079,7 @@ switch (req_c->type) { case FILE_CHUNK: -@@ -1615,32 +1611,32 @@ +@@ -1615,293 +1600,170 @@ req_c->offset += weHave; req_cq->bytes_out += weHave; @@ -30687,269 +34113,355 @@ } #endif - -+ - return 0; - } +- return 0; +-} -@@ -1648,32 +1644,32 @@ - char *ns; - const char *s; - int line = 0; +-static int scgi_response_parse(server *srv, connection *con, plugin_data *p, buffer *in, int eol) { +- char *ns; +- const char *s; +- int line = 0; - -+ - UNUSED(srv); +- UNUSED(srv); - -+ - buffer_copy_string_buffer(p->parse_response, in); +- buffer_copy_string_buffer(p->parse_response, in); - - for (s = p->parse_response->ptr; - NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n'))); -+ -+ for (s = p->parse_response->ptr; -+ NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n'))); - s = ns + (eol == EOL_RN ? 2 : 1), line++) { - const char *key, *value; - int key_len; - data_string *ds; +- s = ns + (eol == EOL_RN ? 2 : 1), line++) { +- const char *key, *value; +- int key_len; +- data_string *ds; - -+ - ns[0] = '\0'; +- ns[0] = '\0'; - - if (line == 0 && -+ -+ if (line == 0 && - 0 == strncmp(s, "HTTP/1.", 7)) { - /* non-parsed header ... we parse them anyway */ -- -+ - if ((s[7] == '1' || - s[7] == '0') && - s[8] == ' ') { - int status; - /* after the space should be a status code for us */ -- -+ - status = strtol(s+9, NULL, 10); -- -+ - if (con->http_status >= 100 && - con->http_status < 1000) { - /* we expected 3 digits and didn't got them */ -@@ -1682,27 +1678,27 @@ - } - } - } else { +- 0 == strncmp(s, "HTTP/1.", 7)) { +- /* non-parsed header ... we parse them anyway */ +- +- if ((s[7] == '1' || +- s[7] == '0') && +- s[8] == ' ') { +- int status; +- /* after the space should be a status code for us */ +- +- status = strtol(s+9, NULL, 10); +- +- if (con->http_status >= 100 && +- con->http_status < 1000) { +- /* we expected 3 digits and didn't got them */ +- con->parsed_response |= HTTP_STATUS; +- con->http_status = status; +- } +- } +- } else { - -+ - key = s; - if (NULL == (value = strchr(s, ':'))) { - /* we expect: ": \r\n" */ - continue; - } +- key = s; +- if (NULL == (value = strchr(s, ':'))) { +- /* we expect: ": \r\n" */ +- continue; +- } - -+ - key_len = value - key; - value += 1; +- key_len = value - key; +- value += 1; - -+ - /* skip LWS */ - while (*value == ' ' || *value == '\t') value++; +- /* skip LWS */ +- while (*value == ' ' || *value == '\t') value++; - -+ - if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) { - ds = data_response_init(); - } - buffer_copy_string_len(ds->key, key, key_len); - buffer_copy_string(ds->value, value); +- if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) { +- ds = data_response_init(); +- } +- buffer_copy_string_len(ds->key, key, key_len); +- buffer_copy_string(ds->value, value); - -+ - array_insert_unique(con->response.headers, (data_unset *)ds); +- array_insert_unique(con->response.headers, (data_unset *)ds); - -+ - switch(key_len) { - case 4: - if (0 == strncasecmp(key, "Date", key_len)) { -@@ -1737,13 +1733,13 @@ - } - } - } +- switch(key_len) { +- case 4: +- if (0 == strncasecmp(key, "Date", key_len)) { +- con->parsed_response |= HTTP_DATE; +- } +- break; +- case 6: +- if (0 == strncasecmp(key, "Status", key_len)) { +- con->http_status = strtol(value, NULL, 10); +- con->parsed_response |= HTTP_STATUS; +- } +- break; +- case 8: +- if (0 == strncasecmp(key, "Location", key_len)) { +- con->parsed_response |= HTTP_LOCATION; +- } +- break; +- case 10: +- if (0 == strncasecmp(key, "Connection", key_len)) { +- con->response.keep_alive = (0 == strcasecmp(value, "Keep-Alive")) ? 1 : 0; +- con->parsed_response |= HTTP_CONNECTION; +- } +- break; +- case 14: +- if (0 == strncasecmp(key, "Content-Length", key_len)) { +- con->response.content_length = strtol(value, NULL, 10); +- con->parsed_response |= HTTP_CONTENT_LENGTH; +- } +- break; +- default: +- break; +- } +- } +- } - -+ - /* CGI/1.1 rev 03 - 7.2.1.2 */ - if ((con->parsed_response & HTTP_LOCATION) && - !(con->parsed_response & HTTP_STATUS)) { - con->http_status = 302; - } +- /* CGI/1.1 rev 03 - 7.2.1.2 */ +- if ((con->parsed_response & HTTP_LOCATION) && +- !(con->parsed_response & HTTP_STATUS)) { +- con->http_status = 302; +- } - -+ return 0; } -@@ -1751,10 +1747,10 @@ +- static int scgi_demux_response(server *srv, handler_ctx *hctx) { plugin_data *p = hctx->plugin_data; connection *con = hctx->remote_conn; - -+ - while(1) { - int n; +- while(1) { +- int n; - -+ - buffer_prepare_copy(hctx->response, 1024); - if (-1 == (n = read(hctx->fd, hctx->response->ptr, hctx->response->size - 1))) { - if (errno == EAGAIN || errno == EINTR) { -@@ -1765,143 +1761,143 @@ - log_error_write(srv, __FILE__, __LINE__, "sdd", strerror(errno), con->fd, hctx->fd); - return -1; - } +- buffer_prepare_copy(hctx->response, 1024); +- if (-1 == (n = read(hctx->fd, hctx->response->ptr, hctx->response->size - 1))) { +- if (errno == EAGAIN || errno == EINTR) { +- /* would block, wait for signal */ +- return 0; +- } +- /* error */ +- log_error_write(srv, __FILE__, __LINE__, "sdd", strerror(errno), con->fd, hctx->fd); +- return -1; +- } - -+ - if (n == 0) { - /* read finished */ +- if (n == 0) { +- /* read finished */ - -+ - con->file_finished = 1; +- con->file_finished = 1; - -+ - /* send final chunk */ - http_chunk_append_mem(srv, con, NULL, 0); - joblist_append(srv, con); +- /* send final chunk */ +- http_chunk_append_mem(srv, con, NULL, 0); +- joblist_append(srv, con); - ++ chunk *c; + - return 1; - } -- ++ switch(srv->network_backend_read(srv, con, hctx->sock, hctx->rb)) { ++ case NETWORK_STATUS_SUCCESS: ++ /* we got content */ ++ break; ++ case NETWORK_STATUS_WAIT_FOR_EVENT: ++ /* the ioctl will return WAIT_FOR_EVENT on a read */ ++ if (0 == con->file_started) return -1; ++ case NETWORK_STATUS_CONNECTION_CLOSE: ++ /* we are done, get out of here */ ++ con->file_finished = 1; + - hctx->response->ptr[n] = '\0'; - hctx->response->used = n+1; -- ++ /* close the chunk-queue with a empty chunk */ + - /* split header from body */ -- ++ return 1; ++ default: ++ /* oops */ ++ return -1; ++ } + - if (con->file_started == 0) { - char *c; - int in_header = 0; - int header_end = 0; - int cp, eol = EOL_UNSET; - size_t used = 0; -- ++ /* looks like we got some content ++ * ++ * split off the header from the incoming stream ++ */ + - buffer_append_string_buffer(hctx->response_header, hctx->response); -- ++ if (hctx->state == SCGI_STATE_RESPONSE_HEADER) { ++ size_t i; ++ int have_content_length = 0; + - /* nph (non-parsed headers) */ - if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) in_header = 1; -- ++ http_response_reset(p->resp); + - /* search for the \r\n\r\n or \n\n in the string */ - for (c = hctx->response_header->ptr, cp = 0, used = hctx->response_header->used - 1; used; c++, cp++, used--) { - if (*c == ':') in_header = 1; - else if (*c == '\n') { - if (in_header == 0) { - /* got a response without a response header */ -- ++ /* the response header is not fully received yet, ++ * ++ * extract the http-response header from the rb-cq ++ */ ++ switch (http_response_parse_cq(hctx->rb, p->resp)) { ++ case PARSE_ERROR: ++ /* parsing failed */ + - c = NULL; - header_end = 1; - break; - } ++ con->http_status = 502; /* Bad Gateway */ + return 1; +- } +- +- hctx->response->ptr[n] = '\0'; +- hctx->response->used = n+1; +- +- /* split header from body */ +- +- if (con->file_started == 0) { +- char *c; +- int in_header = 0; +- int header_end = 0; +- int cp, eol = EOL_UNSET; +- size_t used = 0; +- +- buffer_append_string_buffer(hctx->response_header, hctx->response); +- +- /* nph (non-parsed headers) */ +- if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) in_header = 1; +- +- /* search for the \r\n\r\n or \n\n in the string */ +- for (c = hctx->response_header->ptr, cp = 0, used = hctx->response_header->used - 1; used; c++, cp++, used--) { +- if (*c == ':') in_header = 1; +- else if (*c == '\n') { +- if (in_header == 0) { +- /* got a response without a response header */ +- +- c = NULL; +- header_end = 1; +- break; +- } - -+ - if (eol == EOL_UNSET) eol = EOL_N; +- if (eol == EOL_UNSET) eol = EOL_N; - -+ - if (*(c+1) == '\n') { - header_end = 1; - break; - } +- if (*(c+1) == '\n') { +- header_end = 1; +- break; +- } - -+ - } else if (used > 1 && *c == '\r' && *(c+1) == '\n') { - if (in_header == 0) { - /* got a response without a response header */ +- } else if (used > 1 && *c == '\r' && *(c+1) == '\n') { +- if (in_header == 0) { +- /* got a response without a response header */ - -+ - c = NULL; - header_end = 1; - break; - } +- c = NULL; +- header_end = 1; +- break; +- } - -+ - if (eol == EOL_UNSET) eol = EOL_RN; +- if (eol == EOL_UNSET) eol = EOL_RN; - -+ - if (used > 3 && +- if (used > 3 && - *(c+2) == '\r' && -+ *(c+2) == '\r' && - *(c+3) == '\n') { - header_end = 1; - break; - } +- *(c+3) == '\n') { +- header_end = 1; +- break; +- } - +- /* skip the \n */ +- c++; +- cp++; +- used--; ++ case PARSE_NEED_MORE: ++ return 0; ++ case PARSE_SUCCESS: ++ con->http_status = p->resp->status; ++ ++ chunkqueue_remove_finished_chunks(hctx->rb); ++ ++ /* copy the http-headers */ ++ for (i = 0; i < p->resp->headers->used; i++) { ++ const char *ign[] = { "Status", "Connection", NULL }; ++ size_t j; ++ data_string *ds; + - /* skip the \n */ - c++; - cp++; - used--; ++ data_string *header = (data_string *)p->resp->headers->data[i]; ++ ++ /* some headers are ignored by default */ ++ for (j = 0; ign[j]; j++) { ++ if (0 == strcasecmp(ign[j], header->key->ptr)) break; } - } +- } - -+ - if (header_end) { - if (c == NULL) { - /* no header, but a body */ +- if (header_end) { +- if (c == NULL) { +- /* no header, but a body */ - -+ - if (con->request.http_version == HTTP_VERSION_1_1) { - con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED; - } +- if (con->request.http_version == HTTP_VERSION_1_1) { +- con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED; +- } - -+ - http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used); - joblist_append(srv, con); - } else { - size_t hlen = c - hctx->response_header->ptr + (eol == EOL_RN ? 4 : 2); - size_t blen = hctx->response_header->used - hlen - 1; +- http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used); +- joblist_append(srv, con); +- } else { +- size_t hlen = c - hctx->response_header->ptr + (eol == EOL_RN ? 4 : 2); +- size_t blen = hctx->response_header->used - hlen - 1; - -+ - /* a small hack: terminate after at the second \r */ - hctx->response_header->used = hlen + 1 - (eol == EOL_RN ? 2 : 1); - hctx->response_header->ptr[hlen - (eol == EOL_RN ? 2 : 1)] = '\0'; +- /* a small hack: terminate after at the second \r */ +- hctx->response_header->used = hlen + 1 - (eol == EOL_RN ? 2 : 1); +- hctx->response_header->ptr[hlen - (eol == EOL_RN ? 2 : 1)] = '\0'; - -+ - /* parse the response header */ - scgi_response_parse(srv, con, p, hctx->response_header, eol); +- /* parse the response header */ +- scgi_response_parse(srv, con, p, hctx->response_header, eol); - -+ - /* enable chunked-transfer-encoding */ - if (con->request.http_version == HTTP_VERSION_1_1 && - !(con->parsed_response & HTTP_CONTENT_LENGTH)) { - con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED; - } +- /* enable chunked-transfer-encoding */ +- if (con->request.http_version == HTTP_VERSION_1_1 && +- !(con->parsed_response & HTTP_CONTENT_LENGTH)) { +- con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED; +- } - +- if ((hctx->response->used != hlen) && blen > 0) { +- http_chunk_append_mem(srv, con, c + (eol == EOL_RN ? 4: 2), blen + 1); +- joblist_append(srv, con); +- } ++ if (ign[j]) continue; + - if ((hctx->response->used != hlen) && blen > 0) { - http_chunk_append_mem(srv, con, c + (eol == EOL_RN ? 4: 2), blen + 1); - joblist_append(srv, con); - } ++ if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Location"))) { ++ /* CGI/1.1 rev 03 - 7.2.1.2 */ ++ if (con->http_status == 0) con->http_status = 302; ++ } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Content-Length"))) { ++ have_content_length = 1; } -- + +- con->file_started = 1; ++ if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) { ++ ds = data_response_init(); ++ } ++ buffer_copy_string_buffer(ds->key, header->key); ++ buffer_copy_string_buffer(ds->value, header->value); + - con->file_started = 1; ++ array_insert_unique(con->response.headers, (data_unset *)ds); } - } else { - http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used); - joblist_append(srv, con); +- } else { +- http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used); +- joblist_append(srv, con); ++ ++ con->file_started = 1; ++ ++ if (con->request.http_version == HTTP_VERSION_1_1 && ++ !have_content_length) { ++ con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED; ++ } ++ ++ hctx->state = SCGI_STATE_RESPONSE_CONTENT; ++ break; } - -#if 0 -+ -+#if 0 - log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), b->ptr); - #endif +- log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), b->ptr); +-#endif } - ++ ++ /* FIXME: pass the response-header to the other plugins to ++ * setup the filter-queue ++ * ++ * - use next-queue instead of con->write_queue ++ */ ++ ++ assert(hctx->state == SCGI_STATE_RESPONSE_CONTENT); ++ ++ /* FIXME: if we have a content-length or chunked-encoding ++ * handle it. ++ * ++ * for now we wait for EOF on the socket */ ++ ++ /* copy the content to the next cq */ ++ for (c = hctx->rb->first; c; c = c->next) { ++ http_chunk_append_mem(srv, con, c->mem->ptr + c->offset, c->mem->used - c->offset); ++ ++ c->offset = c->mem->used - 1; ++ } ++ ++ chunkqueue_remove_finished_chunks(hctx->rb); ++ joblist_append(srv, con); + return 0; } @@ -30979,7 +34491,7 @@ */ /* nothing to sort, only one element */ -@@ -1909,9 +1905,9 @@ +@@ -1909,9 +1771,9 @@ for (p = proc; p->next && p->next->load < proc->load; p = p->next); @@ -30991,7 +34503,7 @@ * ^ * | * + -@@ -1930,16 +1926,16 @@ +@@ -1930,16 +1792,16 @@ if (proc->prev) proc->prev->next = proc->next; if (proc->next) proc->next->prev = proc->prev; @@ -31011,7 +34523,7 @@ p->pid, p->load); } #else -@@ -1951,21 +1947,21 @@ +@@ -1951,21 +1813,21 @@ int scgi_proclist_sort_down(server *srv, scgi_extension_host *host, scgi_proc *proc) { scgi_proc *p; @@ -31039,7 +34551,7 @@ * in ram and is not swapped out yet * - processes that are not reused will be killed * after some time by the trigger-handler -@@ -1975,7 +1971,7 @@ +@@ -1975,7 +1837,7 @@ * ice-cold processes are propably unused since more * than 'unused-timeout', are swaped out and won't be * reused in the next seconds anyway. @@ -31048,7 +34560,7 @@ */ /* nothing to sort, only one element */ -@@ -1984,16 +1980,16 @@ +@@ -1984,16 +1846,16 @@ for (p = host->first; p != proc && p->load < proc->load; p = p->next); @@ -31068,7 +34580,7 @@ /* we have to move left. If we are already the first element * we are done */ if (host->first == proc) return 0; -@@ -2009,9 +2005,9 @@ +@@ -2009,9 +1871,9 @@ p->prev = proc; if (proc->prev == NULL) host->first = proc; @@ -31080,7 +34592,7 @@ p->pid, p->load); } #else -@@ -2023,41 +2019,42 @@ +@@ -2023,41 +1885,42 @@ static int scgi_restart_dead_procs(server *srv, plugin_data *p, scgi_extension_host *host) { scgi_proc *proc; @@ -31138,7 +34650,7 @@ switch(waitpid(proc->pid, &status, WNOHANG)) { case 0: /* child is still alive */ -@@ -2067,33 +2064,34 @@ +@@ -2067,33 +1930,34 @@ default: if (WIFEXITED(status)) { #if 0 @@ -31183,7 +34695,7 @@ if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd", "--- scgi spawning", -@@ -2101,18 +2099,18 @@ +@@ -2101,18 +1965,18 @@ "\n\tsocket", host->unixsocket, "\n\tcurrent:", 1, "/", host->min_procs); } @@ -31205,7 +34717,7 @@ return 0; } -@@ -2121,13 +2119,13 @@ +@@ -2121,13 +1985,13 @@ plugin_data *p = hctx->plugin_data; scgi_extension_host *host= hctx->host; connection *con = hctx->remote_conn; @@ -31222,7 +34734,7 @@ "write-req: error", host, host->host->used, -@@ -2135,179 +2133,180 @@ +@@ -2135,259 +1999,260 @@ host->unixsocket->used); return HANDLER_ERROR; } @@ -31230,17 +34742,20 @@ + switch(hctx->state) { - case FCGI_STATE_INIT: +- case FCGI_STATE_INIT: ++ case SCGI_STATE_INIT: ret = host->unixsocket->used ? AF_UNIX : AF_INET; - +- if (-1 == (hctx->fd = socket(ret, SOCK_STREAM, 0))) { + - if (-1 == (hctx->fd = socket(ret, SOCK_STREAM, 0))) { ++ if (-1 == (hctx->sock->fd = socket(ret, SOCK_STREAM, 0))) { if (errno == EMFILE || errno == EINTR) { - log_error_write(srv, __FILE__, __LINE__, "sd", -+ log_error_write(srv, __FILE__, __LINE__, "sd", - "wait for fd at connection:", con->fd); +- "wait for fd at connection:", con->fd); - ++ log_error_write(srv, __FILE__, __LINE__, "sd", ++ "wait for fd at connection:", con->sock->fd); + return HANDLER_WAIT_FOR_FD; } @@ -31251,17 +34766,20 @@ "socket failed:", strerror(errno), srv->cur_fds, srv->max_fds); return HANDLER_ERROR; } - hctx->fde_ndx = -1; +- hctx->fde_ndx = -1; - ++ hctx->sock->fde_ndx = -1; + srv->cur_fds++; - -+ - fdevent_register(srv->ev, hctx->fd, scgi_handle_fdevent, hctx); +- fdevent_register(srv->ev, hctx->fd, scgi_handle_fdevent, hctx); - -+ - if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) { +- if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) { - log_error_write(srv, __FILE__, __LINE__, "ss", ++ ++ fdevent_register(srv->ev, hctx->sock, scgi_handle_fdevent, hctx); ++ ++ if (-1 == fdevent_fcntl_set(srv->ev, hctx->sock)) { + log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno)); - @@ -31271,10 +34789,12 @@ - + /* fall through */ - case FCGI_STATE_CONNECT: - if (hctx->state == FCGI_STATE_INIT) { +- case FCGI_STATE_CONNECT: +- if (hctx->state == FCGI_STATE_INIT) { - for (hctx->proc = hctx->host->first; - hctx->proc && hctx->proc->state != PROC_STATE_RUNNING; ++ case SCGI_STATE_CONNECT: ++ if (hctx->state == SCGI_STATE_INIT) { + for (hctx->proc = hctx->host->first; + hctx->proc && hctx->proc->state != PROC_STATE_RUNNING; hctx->proc = hctx->proc->next); @@ -31282,8 +34802,9 @@ + /* all childs are dead */ if (hctx->proc == NULL) { - hctx->fde_ndx = -1; +- hctx->fde_ndx = -1; - ++ hctx->sock->fde_ndx = -1; + return HANDLER_ERROR; } @@ -31296,20 +34817,23 @@ + switch (scgi_establish_connection(srv, hctx)) { case 1: - scgi_set_state(srv, hctx, FCGI_STATE_CONNECT); +- scgi_set_state(srv, hctx, FCGI_STATE_CONNECT); - ++ scgi_set_state(srv, hctx, SCGI_STATE_CONNECT); + /* connection is in progress, wait for an event and call getsockopt() below */ - -+ - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); +- fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); - ++ ++ fdevent_event_add(srv->ev, hctx->sock, FDEVENT_OUT); + return HANDLER_WAIT_FOR_EVENT; case -1: /* if ECONNREFUSED choose another connection -> FIXME */ - hctx->fde_ndx = -1; +- hctx->fde_ndx = -1; - ++ hctx->sock->fde_ndx = -1; + return HANDLER_ERROR; default: @@ -31325,8 +34849,9 @@ - + /* try to finish the connect() */ - if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) { +- if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) { - log_error_write(srv, __FILE__, __LINE__, "ss", ++ if (0 != getsockopt(hctx->sock->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) { + log_error_write(srv, __FILE__, __LINE__, "ss", "getsockopt failed:", strerror(errno)); - @@ -31361,10 +34886,11 @@ if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "sddbdd", - "got proc:", -+ "got proc:", - hctx->fd, +- hctx->fd, - hctx->proc->pid, - hctx->proc->socket, ++ "got proc:", ++ hctx->sock->fd, + hctx->proc->pid, + hctx->proc->socket, hctx->proc->port, @@ -31374,20 +34900,24 @@ /* move the proc-list entry down the list */ scgi_proclist_sort_up(srv, hctx->host, hctx->proc); - +- scgi_set_state(srv, hctx, FCGI_STATE_PREPARE_WRITE); + - scgi_set_state(srv, hctx, FCGI_STATE_PREPARE_WRITE); ++ scgi_set_state(srv, hctx, SCGI_STATE_PREPARE_WRITE); /* fall through */ - case FCGI_STATE_PREPARE_WRITE: +- case FCGI_STATE_PREPARE_WRITE: ++ case SCGI_STATE_PREPARE_WRITE: scgi_create_env(srv, hctx); - -+ - scgi_set_state(srv, hctx, FCGI_STATE_WRITE); +- scgi_set_state(srv, hctx, FCGI_STATE_WRITE); - ++ ++ scgi_set_state(srv, hctx, SCGI_STATE_WRITE); + /* fall through */ - case FCGI_STATE_WRITE: +- case FCGI_STATE_WRITE: - ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb); -+ ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb); ++ case SCGI_STATE_WRITE: ++ ret = srv->network_backend_write(srv, con, hctx->sock, hctx->wb); chunkqueue_remove_finished_chunks(hctx->wb); - @@ -31453,8 +34983,9 @@ + return HANDLER_ERROR; } else { - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); +- fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); - ++ fdevent_event_add(srv->ev, hctx->sock, FDEVENT_OUT); + return HANDLER_WAIT_FOR_EVENT; } @@ -31463,21 +34994,27 @@ + if (hctx->wb->bytes_out == hctx->wb->bytes_in) { /* we don't need the out event anymore */ - fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); -@@ -2315,10 +2314,10 @@ - scgi_set_state(srv, hctx, FCGI_STATE_READ); +- fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); +- fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); +- scgi_set_state(srv, hctx, FCGI_STATE_READ); ++ fdevent_event_del(srv->ev, hctx->sock); ++ fdevent_event_add(srv->ev, hctx->sock, FDEVENT_IN); ++ scgi_set_state(srv, hctx, SCGI_STATE_RESPONSE_HEADER); } else { - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); +- fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); - ++ fdevent_event_add(srv->ev, hctx->sock, FDEVENT_OUT); + return HANDLER_WAIT_FOR_EVENT; } - + break; - case FCGI_STATE_READ: +- case FCGI_STATE_READ: ++ case SCGI_STATE_RESPONSE_HEADER: /* waiting for a response */ -@@ -2327,67 +2326,67 @@ + break; + default: log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state"); return HANDLER_ERROR; } @@ -31529,11 +35066,13 @@ host->active_procs--; } - -+ - if (hctx->state == FCGI_STATE_INIT || - hctx->state == FCGI_STATE_CONNECT) { +- if (hctx->state == FCGI_STATE_INIT || +- hctx->state == FCGI_STATE_CONNECT) { - /* connect() or getsockopt() failed, - * restart the request-handling ++ ++ if (hctx->state == SCGI_STATE_INIT || ++ hctx->state == SCGI_STATE_CONNECT) { + /* connect() or getsockopt() failed, + * restart the request-handling */ @@ -31563,7 +35102,7 @@ */ if (proc->state == PROC_STATE_RUNNING && hctx->pid == proc->pid) { -@@ -2395,25 +2394,25 @@ +@@ -2395,25 +2260,25 @@ } } scgi_restart_dead_procs(srv, p, host); @@ -31597,7 +35136,7 @@ return HANDLER_FINISHED; } case HANDLER_WAIT_FOR_EVENT: -@@ -2433,23 +2432,23 @@ +@@ -2433,23 +2298,23 @@ static handler_t scgi_connection_close(server *srv, handler_ctx *hctx) { plugin_data *p; connection *con; @@ -31614,15 +35153,17 @@ - - log_error_write(srv, __FILE__, __LINE__, "ssdsd", - "emergency exit: scgi:", -+ -+ log_error_write(srv, __FILE__, __LINE__, "ssdsd", -+ "emergency exit: scgi:", - "connection-fd:", con->fd, - "fcgi-fd:", hctx->fd); +- "connection-fd:", con->fd, +- "fcgi-fd:", hctx->fd); - - - + ++ log_error_write(srv, __FILE__, __LINE__, "ssdsd", ++ "emergency exit: scgi:", ++ "connection-fd:", con->sock->fd, ++ "fcgi-fd:", hctx->sock->fd); ++ + + scgi_connection_cleanup(srv, hctx); @@ -31631,7 +35172,7 @@ return HANDLER_FINISHED; } -@@ -2459,7 +2458,7 @@ +@@ -2459,27 +2324,28 @@ handler_ctx *hctx = ctx; connection *con = hctx->remote_conn; plugin_data *p = hctx->plugin_data; @@ -31640,7 +35181,13 @@ scgi_proc *proc = hctx->proc; scgi_extension_host *host= hctx->host; -@@ -2471,15 +2470,15 @@ + if ((revents & FDEVENT_IN) && +- hctx->state == FCGI_STATE_READ) { ++ (hctx->state == SCGI_STATE_RESPONSE_HEADER || ++ hctx->state == SCGI_STATE_RESPONSE_CONTENT)) { + switch (scgi_demux_response(srv, hctx)) { + case 0: + break; case 1: /* we are done */ scgi_connection_cleanup(srv, hctx); @@ -31659,7 +35206,7 @@ switch(waitpid(proc->pid, &status, WNOHANG)) { case 0: /* child is still alive */ -@@ -2489,19 +2488,19 @@ +@@ -2489,19 +2355,19 @@ default: /* the child should not terminate at all */ if (WIFEXITED(status)) { @@ -31685,7 +35232,7 @@ if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd", "--- scgi spawning", -@@ -2509,40 +2508,41 @@ +@@ -2509,40 +2375,41 @@ "\n\tsocket", host->unixsocket, "\n\tcurrent:", 1, "/", host->min_procs); } @@ -31716,9 +35263,11 @@ + + log_error_write(srv, __FILE__, __LINE__, "sdsdsd", "response not sent, request not sent, reconnection.", - "connection-fd:", con->fd, - "fcgi-fd:", hctx->fd); +- "connection-fd:", con->fd, +- "fcgi-fd:", hctx->fd); - ++ "connection-fd:", con->sock->fd, ++ "fcgi-fd:", hctx->sock->fd); + return HANDLER_WAIT_FOR_FD; } @@ -31727,9 +35276,11 @@ + + log_error_write(srv, __FILE__, __LINE__, "sosdsd", "response not sent, request sent:", hctx->wb->bytes_out, - "connection-fd:", con->fd, - "fcgi-fd:", hctx->fd); +- "connection-fd:", con->fd, +- "fcgi-fd:", hctx->fd); - ++ "connection-fd:", con->sock->fd, ++ "fcgi-fd:", hctx->sock->fd); + scgi_connection_cleanup(srv, hctx); - @@ -31737,7 +35288,7 @@ connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST); buffer_reset(con->physical.path); con->http_status = 500; -@@ -2550,76 +2550,76 @@ +@@ -2550,76 +2417,77 @@ } else { /* response might have been already started, kill the connection */ scgi_connection_cleanup(srv, hctx); @@ -31746,9 +35297,11 @@ + + log_error_write(srv, __FILE__, __LINE__, "ssdsd", "response already sent out, termination connection", - "connection-fd:", con->fd, - "fcgi-fd:", hctx->fd); +- "connection-fd:", con->fd, +- "fcgi-fd:", hctx->fd); - ++ "connection-fd:", con->sock->fd, ++ "fcgi-fd:", hctx->sock->fd); + connection_set_state(srv, con, CON_STATE_ERROR); } @@ -31765,8 +35318,10 @@ - + if (revents & FDEVENT_OUT) { - if (hctx->state == FCGI_STATE_CONNECT || - hctx->state == FCGI_STATE_WRITE) { +- if (hctx->state == FCGI_STATE_CONNECT || +- hctx->state == FCGI_STATE_WRITE) { ++ if (hctx->state == SCGI_STATE_CONNECT || ++ hctx->state == SCGI_STATE_WRITE) { /* we are allowed to send something out - * + * @@ -31786,7 +35341,8 @@ + /* perhaps this issue is already handled */ if (revents & FDEVENT_HUP) { - if (hctx->state == FCGI_STATE_CONNECT) { +- if (hctx->state == FCGI_STATE_CONNECT) { ++ if (hctx->state == SCGI_STATE_CONNECT) { /* getoptsock will catch this one (right ?) - * - * if we are in connect we might get a EINPROGRESS @@ -31802,7 +35358,9 @@ + * */ return mod_scgi_handle_subrequest(srv, con, p); - } else if (hctx->state == FCGI_STATE_READ && +- } else if (hctx->state == FCGI_STATE_READ && ++ } else if ((hctx->state == SCGI_STATE_RESPONSE_HEADER || ++ hctx->state == SCGI_STATE_RESPONSE_CONTENT ) && hctx->proc->port == 0) { /* FIXME: - * @@ -31836,7 +35394,7 @@ "fcgi: got a FDEVENT_ERR. Don't know why."); /* kill all connections to the scgi process */ -@@ -2628,42 +2628,39 @@ +@@ -2628,42 +2496,39 @@ scgi_connection_close(srv, hctx); joblist_append(srv, con); } @@ -31891,7 +35449,7 @@ static handler_t scgi_check_extension(server *srv, connection *con, void *p_d, int uri_path_handler) { plugin_data *p = p_d; -@@ -2673,30 +2670,30 @@ +@@ -2673,30 +2538,30 @@ size_t k; buffer *fn; scgi_extension *extension = NULL; @@ -31930,7 +35488,7 @@ /* check extension in the form "/scgi_pattern" */ if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) { break; -@@ -2710,17 +2707,17 @@ +@@ -2710,17 +2575,17 @@ if (k == p->conf.exts->used) { return HANDLER_GO_ON; } @@ -31951,7 +35509,7 @@ ndx = k; } } -@@ -2728,12 +2725,12 @@ +@@ -2728,12 +2593,12 @@ /* found a server */ if (ndx != -1) { scgi_extension_host *host = extension->hosts[ndx]; @@ -31969,7 +35527,7 @@ /* init handler-context */ if (uri_path_handler) { if (host->check_local == 0) { -@@ -2741,7 +2738,7 @@ +@@ -2741,7 +2606,7 @@ char *pathinfo; hctx = handler_ctx_init(); @@ -31978,7 +35536,7 @@ hctx->remote_conn = con; hctx->plugin_data = p; hctx->host = host; -@@ -2749,45 +2746,45 @@ +@@ -2749,45 +2614,45 @@ hctx->conf.exts = p->conf.exts; hctx->conf.debug = p->conf.debug; @@ -32039,7 +35597,7 @@ con->uri.path->used -= con->request.pathinfo->used - 1; con->uri.path->ptr[con->uri.path->used - 1] = '\0'; } -@@ -2796,21 +2793,21 @@ +@@ -2796,21 +2661,21 @@ } else { handler_ctx *hctx; hctx = handler_ctx_init(); @@ -32067,7 +35625,7 @@ if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi"); } -@@ -2821,11 +2818,11 @@ +@@ -2821,11 +2686,11 @@ /* no handler found */ buffer_reset(con->physical.path); con->http_status = 500; @@ -32083,7 +35641,7 @@ return HANDLER_FINISHED; } return HANDLER_GO_ON; -@@ -2844,19 +2841,19 @@ +@@ -2844,21 +2709,22 @@ JOBLIST_FUNC(mod_scgi_handle_joblist) { plugin_data *p = p_d; handler_ctx *hctx = con->plugin_ctx[p->id]; @@ -32091,22 +35649,32 @@ + if (hctx == NULL) return HANDLER_GO_ON; - if (hctx->fd != -1) { +- if (hctx->fd != -1) { ++ if (hctx->sock->fd != -1) { switch (hctx->state) { - case FCGI_STATE_READ: - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); +- case FCGI_STATE_READ: +- fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); - ++ case SCGI_STATE_RESPONSE_HEADER: ++ case SCGI_STATE_RESPONSE_CONTENT: ++ fdevent_event_add(srv->ev, hctx->sock, FDEVENT_IN); + break; - case FCGI_STATE_CONNECT: - case FCGI_STATE_WRITE: - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); +- case FCGI_STATE_CONNECT: +- case FCGI_STATE_WRITE: +- fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); - ++ case SCGI_STATE_CONNECT: ++ case SCGI_STATE_WRITE: ++ fdevent_event_add(srv->ev, hctx->sock, FDEVENT_OUT); + break; - case FCGI_STATE_INIT: +- case FCGI_STATE_INIT: ++ case SCGI_STATE_INIT: /* at reconnect */ -@@ -2873,21 +2870,21 @@ + break; + default: +@@ -2873,21 +2739,21 @@ static handler_t scgi_connection_close_callback(server *srv, connection *con, void *p_d) { plugin_data *p = p_d; @@ -32135,7 +35703,7 @@ */ /* check all childs if they are still up */ -@@ -2904,47 +2901,47 @@ +@@ -2904,47 +2770,47 @@ scgi_extension *ex; ex = exts->exts[j]; @@ -32197,7 +35765,7 @@ if (buffer_is_empty(host->unixsocket)) { fp->port = host->port + fp->id; } else { -@@ -2952,13 +2949,13 @@ +@@ -2952,13 +2818,13 @@ buffer_append_string(fp->socket, "-"); buffer_append_long(fp->socket, fp->id); } @@ -32213,7 +35781,7 @@ fp->prev = NULL; fp->next = host->first; if (host->first) { -@@ -2966,56 +2963,57 @@ +@@ -2966,56 +2832,57 @@ } host->first = fp; } @@ -32294,7 +35862,7 @@ switch (waitpid(proc->pid, &status, WNOHANG)) { case 0: /* child still running after timeout, good */ -@@ -3023,10 +3021,10 @@ +@@ -3023,10 +2890,10 @@ case -1: if (errno != EINTR) { /* no PID found ? should never happen */ @@ -32307,7 +35875,7 @@ #if 0 if (errno == ECHILD) { /* someone else has cleaned up for us */ -@@ -3040,25 +3038,26 @@ +@@ -3040,25 +2907,26 @@ /* the child should not terminate at all */ if (WIFEXITED(status)) { if (proc->state != PROC_STATE_KILLED) { @@ -32340,7 +35908,7 @@ } } } -@@ -3082,8 +3081,8 @@ +@@ -3082,8 +2950,8 @@ p->handle_subrequest = mod_scgi_handle_subrequest; p->handle_joblist = mod_scgi_handle_joblist; p->handle_trigger = mod_scgi_handle_trigger; @@ -32352,7 +35920,7 @@ return 0; } --- ../lighttpd-1.4.11/src/mod_secure_download.c 2005-12-14 14:37:29.000000000 +0200 -+++ lighttpd-1.4.12/src/mod_secure_download.c 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_secure_download.c 2006-07-16 00:26:03.000000000 +0300 @@ -25,7 +25,7 @@ #ifdef USE_OPENSSL #define IN const @@ -32707,7 +36275,7 @@ return 0; } --- ../lighttpd-1.4.11/src/mod_setenv.c 2006-01-14 20:33:12.000000000 +0200 -+++ lighttpd-1.4.12/src/mod_setenv.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_setenv.c 2006-07-16 00:26:04.000000000 +0300 @@ -18,25 +18,25 @@ typedef struct { array *request_header; @@ -32983,7 +36551,7 @@ return 0; } --- ../lighttpd-1.4.11/src/mod_simple_vhost.c 2005-11-18 15:16:13.000000000 +0200 -+++ lighttpd-1.4.12/src/mod_simple_vhost.c 2006-07-11 22:07:52.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_simple_vhost.c 2006-07-16 00:26:04.000000000 +0300 @@ -10,6 +10,8 @@ #include "plugin.h" @@ -33324,7 +36892,7 @@ return 0; } --- ../lighttpd-1.4.11/src/mod_skeleton.c 2005-10-02 18:30:51.000000000 +0300 -+++ lighttpd-1.4.12/src/mod_skeleton.c 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_skeleton.c 2006-07-16 00:26:03.000000000 +0300 @@ -14,13 +14,13 @@ /** @@ -33564,7 +37132,7 @@ return 0; } --- ../lighttpd-1.4.11/src/mod_sql_vhost_core.c 1970-01-01 03:00:00.000000000 +0300 -+++ lighttpd-1.4.12/src/mod_sql_vhost_core.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_sql_vhost_core.c 2006-07-16 00:26:04.000000000 +0300 @@ -0,0 +1,209 @@ +#include +#include @@ -33776,7 +37344,7 @@ +} + --- ../lighttpd-1.4.11/src/mod_sql_vhost_core.h 1970-01-01 03:00:00.000000000 +0300 -+++ lighttpd-1.4.12/src/mod_sql_vhost_core.h 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_sql_vhost_core.h 2006-07-16 00:26:04.000000000 +0300 @@ -0,0 +1,49 @@ +#ifndef _MOD_SQL_VHOST_CORE_H_ +#define _MOD_SQL_VHOST_CORE_H_ @@ -33828,7 +37396,7 @@ + +#endif --- ../lighttpd-1.4.11/src/mod_ssi.c 2006-03-04 17:09:48.000000000 +0200 -+++ lighttpd-1.4.12/src/mod_ssi.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_ssi.c 2006-07-16 00:26:04.000000000 +0300 @@ -6,7 +6,6 @@ #include #include @@ -34998,7 +38566,7 @@ return 0; } --- ../lighttpd-1.4.11/src/mod_ssi.h 2005-08-11 01:26:39.000000000 +0300 -+++ lighttpd-1.4.12/src/mod_ssi.h 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_ssi.h 2006-07-16 00:26:04.000000000 +0300 @@ -19,23 +19,23 @@ typedef struct { @@ -35033,7 +38601,7 @@ int ssi_eval_expr(server *srv, connection *con, plugin_data *p, const char *expr); --- ../lighttpd-1.4.11/src/mod_ssi_expr.c 2005-08-11 01:26:48.000000000 +0300 -+++ lighttpd-1.4.12/src/mod_ssi_expr.c 2006-07-11 22:07:52.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_ssi_expr.c 2006-07-16 00:26:04.000000000 +0300 @@ -11,9 +11,9 @@ const char *input; size_t offset; @@ -35414,7 +38982,7 @@ return context.val.bo; } --- ../lighttpd-1.4.11/src/mod_ssi_expr.h 2005-08-11 01:26:48.000000000 +0300 -+++ lighttpd-1.4.12/src/mod_ssi_expr.h 2006-07-11 22:07:52.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_ssi_expr.h 2006-07-16 00:26:04.000000000 +0300 @@ -5,16 +5,16 @@ typedef struct { @@ -35436,7 +39004,7 @@ } ssi_ctx_t; --- ../lighttpd-1.4.11/src/mod_ssi_exprparser.c 2005-10-03 00:40:25.000000000 +0300 -+++ lighttpd-1.4.12/src/mod_ssi_exprparser.c 2006-07-11 22:08:02.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_ssi_exprparser.c 2006-07-17 22:02:23.000000000 +0300 @@ -18,10 +18,10 @@ /* Next is all token values, in a form suitable for use by makeheaders. ** This section will be null unless lemon is run with the -m switch. @@ -35581,7 +39149,7 @@ ** This is what we do if the grammar does define ERROR: ** --- ../lighttpd-1.4.11/src/mod_staticfile.c 2006-02-15 14:31:14.000000000 +0200 -+++ lighttpd-1.4.12/src/mod_staticfile.c 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_staticfile.c 2006-07-16 00:26:03.000000000 +0300 @@ -14,9 +14,11 @@ #include "http_chunk.h" #include "response.h" @@ -36143,7 +39711,7 @@ return 0; } --- ../lighttpd-1.4.11/src/mod_status.c 2006-01-10 21:45:32.000000000 +0200 -+++ lighttpd-1.4.12/src/mod_status.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_status.c 2006-07-16 00:26:04.000000000 +0300 @@ -4,7 +4,6 @@ #include #include @@ -37095,7 +40663,7 @@ return 0; } --- ../lighttpd-1.4.11/src/mod_trigger_b4_dl.c 2005-09-23 22:53:55.000000000 +0300 -+++ lighttpd-1.4.12/src/mod_trigger_b4_dl.c 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_trigger_b4_dl.c 2006-07-16 00:26:03.000000000 +0300 @@ -24,18 +24,18 @@ /** @@ -37771,7 +41339,7 @@ return 0; } --- ../lighttpd-1.4.11/src/mod_userdir.c 2005-10-28 16:48:28.000000000 +0300 -+++ lighttpd-1.4.12/src/mod_userdir.c 2006-07-11 22:07:52.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_userdir.c 2006-07-16 00:26:04.000000000 +0300 @@ -10,6 +10,7 @@ #include "response.h" @@ -38080,7 +41648,7 @@ return 0; } --- ../lighttpd-1.4.11/src/mod_usertrack.c 2006-01-31 15:01:20.000000000 +0200 -+++ lighttpd-1.4.12/src/mod_usertrack.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_usertrack.c 2006-07-16 00:26:04.000000000 +0300 @@ -24,44 +24,44 @@ typedef struct { @@ -38397,7 +41965,7 @@ return 0; } --- ../lighttpd-1.4.11/src/mod_webdav.c 2006-03-03 01:28:58.000000000 +0200 -+++ lighttpd-1.4.12/src/mod_webdav.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/mod_webdav.c 2006-07-18 13:03:40.000000000 +0300 @@ -3,13 +3,10 @@ #include #include @@ -38949,7 +42517,7 @@ if (con->request.http_version == HTTP_VERSION_1_1) { BUFFER_COPY_STRING_CONST(b, "HTTP/1.1 "); } else { -@@ -458,11 +555,11 @@ +@@ -458,14 +555,13 @@ /* bind the values to the insert */ @@ -38963,8 +42531,11 @@ + if (SQLITE_DONE != sqlite3_step(stmt)) { /* */ - WP(); -@@ -493,14 +590,14 @@ +- WP(); + } + } + #endif +@@ -493,14 +589,14 @@ (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) { continue; /* ignore the parent dir */ @@ -38983,7 +42554,7 @@ buffer_append_string(d.rel_path, de->d_name); /* stat and unlink afterwards */ -@@ -508,7 +605,7 @@ +@@ -508,7 +604,7 @@ /* don't about it yet, rmdir will fail too */ } else if (S_ISDIR(st.st_mode)) { have_multi_status = webdav_delete_dir(srv, con, p, &d, b); @@ -38992,7 +42563,7 @@ /* try to unlink it */ if (-1 == rmdir(d.path->ptr)) { switch(errno) { -@@ -535,11 +632,11 @@ +@@ -535,14 +631,13 @@ /* bind the values to the insert */ @@ -39006,8 +42577,11 @@ + if (SQLITE_DONE != sqlite3_step(stmt)) { /* */ - WP(); -@@ -569,7 +666,7 @@ +- WP(); + } + } + #endif +@@ -569,7 +664,7 @@ if (stream_open(&s, src->path)) { return 403; } @@ -39016,7 +42590,7 @@ if (-1 == (ofd = open(dst->path->ptr, O_WRONLY|O_TRUNC|O_CREAT|(overwrite ? 0 : O_EXCL), 0600))) { /* opening the destination failed for some reason */ switch(errno) { -@@ -601,7 +698,7 @@ +@@ -601,7 +696,7 @@ break; } } @@ -39025,7 +42599,7 @@ stream_close(&s); close(ofd); -@@ -614,16 +711,16 @@ +@@ -614,19 +709,18 @@ sqlite3_reset(stmt); /* bind the values to the insert */ @@ -39046,8 +42620,11 @@ + if (SQLITE_DONE != sqlite3_step(stmt)) { /* */ - WP(); -@@ -655,21 +752,21 @@ +- WP(); + } + } + } +@@ -655,21 +749,21 @@ (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) { continue; } @@ -39074,7 +42651,7 @@ buffer_append_string(d.rel_path, de->d_name); if (-1 == stat(s.path->ptr, &st)) { -@@ -692,16 +789,16 @@ +@@ -692,19 +786,18 @@ sqlite3_reset(stmt); /* bind the values to the insert */ @@ -39095,8 +42672,11 @@ + if (SQLITE_DONE != sqlite3_step(stmt)) { /* */ - WP(); -@@ -721,7 +818,7 @@ +- WP(); + } + } + #endif +@@ -721,7 +814,7 @@ buffer_free(s.rel_path); buffer_free(d.path); buffer_free(d.rel_path); @@ -39105,7 +42685,7 @@ closedir(srcdir); } -@@ -748,12 +845,12 @@ +@@ -748,12 +841,12 @@ if (S_ISDIR(sce->st.st_mode)) { buffer_append_string(b, "httpd/unix-directory"); found = 1; @@ -39121,7 +42701,7 @@ if (buffer_is_equal_right_len(dst->path, ds->key, ds->key->used - 1)) { buffer_append_string(b,""); buffer_append_string_buffer(b, ds->value); -@@ -807,23 +904,23 @@ +@@ -807,23 +900,23 @@ /* bind the values to the insert */ @@ -39151,7 +42731,7 @@ found = 1; } } -@@ -840,7 +937,7 @@ +@@ -840,7 +933,7 @@ char *prop; } webdav_property; @@ -39160,7 +42740,7 @@ { "DAV:", "creationdate" }, { "DAV:", "displayname" }, { "DAV:", "getcontentlanguage" }, -@@ -871,8 +968,8 @@ +@@ -871,8 +964,8 @@ webdav_property *prop; prop = props->ptr[i]; @@ -39171,7 +42751,7 @@ dst, prop->prop, prop->ns, b_200)) { webdav_gen_prop_tag(srv, con, prop->prop, prop->ns, NULL, b_404); } -@@ -916,12 +1013,12 @@ +@@ -916,12 +1009,12 @@ if (-1 == c->file.fd && /* open the file if not already open */ -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) { log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno)); @@ -39187,7 +42767,7 @@ strerror(errno), c->file.name, c->file.fd); return -1; -@@ -938,7 +1035,7 @@ +@@ -938,7 +1031,7 @@ if (XML_ERR_OK != (err = xmlParseChunk(ctxt, c->file.mmap.start + c->offset, weHave, 0))) { log_error_write(srv, __FILE__, __LINE__, "sddd", "xmlParseChunk failed at:", cq->bytes_out, weHave, err); } @@ -39196,7 +42776,7 @@ c->offset += weHave; cq->bytes_out += weHave; -@@ -956,7 +1053,7 @@ +@@ -956,7 +1049,7 @@ if (XML_ERR_OK != (err = xmlParseChunk(ctxt, c->mem->ptr + c->offset, weHave, 0))) { log_error_write(srv, __FILE__, __LINE__, "sddd", "xmlParseChunk failed at:", cq->bytes_out, weHave, err); } @@ -39205,7 +42785,7 @@ c->offset += weHave; cq->bytes_out += weHave; -@@ -991,6 +1088,113 @@ +@@ -991,6 +1084,113 @@ } #endif @@ -39319,7 +42899,7 @@ URIHANDLER_FUNC(mod_webdav_subrequest_handler) { plugin_data *p = p_d; buffer *b; -@@ -1001,7 +1205,8 @@ +@@ -1001,7 +1201,8 @@ buffer *prop_200; buffer *prop_404; webdav_properties *req_props; @@ -39329,7 +42909,7 @@ UNUSED(srv); if (!p->conf.enabled) return HANDLER_GO_ON; -@@ -1019,7 +1224,19 @@ +@@ -1019,7 +1220,19 @@ req_props = NULL; /* is there a content-body ? */ @@ -39350,7 +42930,7 @@ #ifdef USE_PROPPATCH /* any special requests or just allprop ? */ if (con->request.content_length) { -@@ -1087,12 +1304,12 @@ +@@ -1087,14 +1300,13 @@ /* get all property names (EMPTY) */ sqlite3_reset(stmt); /* bind the values to the insert */ @@ -39365,9 +42945,11 @@ - + if (SQLITE_DONE != sqlite3_step(stmt)) { - WP(); +- WP(); } -@@ -1115,13 +1332,13 @@ + } + } else if (0 == xmlStrcmp(cmd->name, BAD_CAST "allprop")) { +@@ -1115,13 +1327,13 @@ response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\"")); b = chunkqueue_get_append_buffer(con->write_queue); @@ -39383,7 +42965,7 @@ prop_200 = buffer_init(); prop_404 = buffer_init(); -@@ -1129,7 +1346,7 @@ +@@ -1129,7 +1341,7 @@ case 0: /* Depth: 0 */ webdav_get_props(srv, con, p, &(con->physical), req_props, prop_200, prop_404); @@ -39392,7 +42974,7 @@ buffer_append_string(b,"\n"); buffer_append_string(b,""); buffer_append_string_buffer(b, con->uri.scheme); -@@ -1145,9 +1362,9 @@ +@@ -1145,9 +1357,9 @@ buffer_append_string_buffer(b, prop_200); buffer_append_string(b,"\n"); @@ -39404,7 +42986,7 @@ buffer_append_string(b,"\n"); } if (!buffer_is_empty(prop_404)) { -@@ -1157,16 +1374,16 @@ +@@ -1157,16 +1369,16 @@ buffer_append_string_buffer(b, prop_404); buffer_append_string(b,"\n"); @@ -39424,7 +43006,7 @@ if (NULL != (dir = opendir(con->physical.path->ptr))) { struct dirent *de; physical d; -@@ -1179,16 +1396,16 @@ +@@ -1179,16 +1391,16 @@ if (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') { continue; /* ignore the parent dir */ @@ -39445,7 +43027,7 @@ } else { buffer_append_string(d.path, de->d_name); buffer_append_string(d.rel_path, de->d_name); -@@ -1198,7 +1415,7 @@ +@@ -1198,7 +1410,7 @@ buffer_reset(prop_404); webdav_get_props(srv, con, p, &d, req_props, prop_200, prop_404); @@ -39454,7 +43036,7 @@ buffer_append_string(b,"\n"); buffer_append_string(b,""); buffer_append_string_buffer(b, con->uri.scheme); -@@ -1214,9 +1431,9 @@ +@@ -1214,9 +1426,9 @@ buffer_append_string_buffer(b, prop_200); buffer_append_string(b,"\n"); @@ -39466,7 +43048,7 @@ buffer_append_string(b,"\n"); } if (!buffer_is_empty(prop_404)) { -@@ -1226,9 +1443,9 @@ +@@ -1226,9 +1438,9 @@ buffer_append_string_buffer(b, prop_404); buffer_append_string(b,"\n"); @@ -39478,7 +43060,7 @@ buffer_append_string(b,"\n"); } -@@ -1275,7 +1492,7 @@ +@@ -1275,7 +1487,7 @@ return HANDLER_FINISHED; } @@ -39487,7 +43069,7 @@ /* let's create the directory */ if (-1 == mkdir(con->physical.path->ptr, 0700)) { -@@ -1303,7 +1520,13 @@ +@@ -1303,7 +1515,13 @@ con->http_status = 403; return HANDLER_FINISHED; } @@ -39502,7 +43084,7 @@ /* stat and unlink afterwards */ if (-1 == stat(con->physical.path->ptr, &st)) { /* don't about it yet, unlink will fail too */ -@@ -1323,7 +1546,7 @@ +@@ -1323,7 +1541,7 @@ response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\"")); b = chunkqueue_get_append_buffer(con->write_queue); @@ -39511,7 +43093,7 @@ buffer_copy_string(b, "\n"); buffer_append_string(b,"\n"); -@@ -1331,7 +1554,7 @@ +@@ -1331,7 +1549,7 @@ buffer_append_string_buffer(b, multi_status_resp); buffer_append_string(b,"\n"); @@ -39520,7 +43102,7 @@ if (p->conf.log_xml) { log_error_write(srv, __FILE__, __LINE__, "sb", "XML-response-body:", b); } -@@ -1340,7 +1563,7 @@ +@@ -1340,7 +1558,7 @@ con->file_finished = 1; } else { /* everything went fine, remove the directory */ @@ -39529,7 +43111,7 @@ if (-1 == rmdir(con->physical.path->ptr)) { switch(errno) { case ENOENT: -@@ -1375,97 +1598,174 @@ +@@ -1375,97 +1593,174 @@ case HTTP_METHOD_PUT: { int fd; chunkqueue *cq = con->request_content_queue; @@ -39770,7 +43352,7 @@ case HTTP_METHOD_COPY: { buffer *destination = NULL; char *sep, *start; -@@ -1475,7 +1775,15 @@ +@@ -1475,7 +1770,15 @@ con->http_status = 403; return HANDLER_FINISHED; } @@ -39787,7 +43369,7 @@ if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Destination"))) { destination = ds->value; } else { -@@ -1549,10 +1857,10 @@ +@@ -1549,10 +1852,10 @@ } buffer_copy_string_buffer(p->physical.path, p->physical.doc_root); @@ -39800,7 +43382,7 @@ if (p->physical.rel_path->ptr[0] == '/') { buffer_append_string_len(p->physical.path, p->physical.rel_path->ptr + 1, p->physical.rel_path->used - 2); } else { -@@ -1613,6 +1921,12 @@ +@@ -1613,6 +1916,12 @@ /* it is just a file, good */ int r; @@ -39813,7 +43395,7 @@ /* destination exists */ if (0 == (r = stat(p->physical.path->ptr, &st))) { if (S_ISDIR(st.st_mode)) { -@@ -1636,7 +1950,7 @@ +@@ -1636,7 +1945,7 @@ return HANDLER_FINISHED; } } else if (overwrite == 0) { @@ -39822,7 +43404,7 @@ con->http_status = 412; return HANDLER_FINISHED; } else { -@@ -1655,16 +1969,16 @@ +@@ -1655,16 +1964,16 @@ sqlite3_reset(stmt); /* bind the values to the insert */ @@ -39844,7 +43426,7 @@ if (SQLITE_DONE != sqlite3_step(stmt)) { log_error_write(srv, __FILE__, __LINE__, "ss", "sql-move failed:", sqlite3_errmsg(p->conf.sql)); } -@@ -1691,12 +2005,17 @@ +@@ -1691,12 +2000,17 @@ return HANDLER_FINISHED; } @@ -39863,7 +43445,7 @@ /* check if destination exists */ if (-1 == stat(con->physical.path->ptr, &st)) { switch(errno) { -@@ -1737,7 +2056,7 @@ +@@ -1737,7 +2051,7 @@ sqlite3_stmt *stmt; @@ -39872,7 +43454,7 @@ p->conf.stmt_delete_prop : p->conf.stmt_update_prop; for (props = cmd->children; props; props = props->next) { -@@ -1762,34 +2081,35 @@ +@@ -1762,34 +2076,35 @@ /* bind the values to the insert */ @@ -39916,7 +43498,7 @@ } } } -@@ -1804,7 +2124,7 @@ +@@ -1804,7 +2119,7 @@ goto propmatch_cleanup; } @@ -39925,7 +43507,7 @@ con->http_status = 400; } else { if (SQLITE_OK != sqlite3_exec(p->conf.sql, "COMMIT", NULL, NULL, &err)) { -@@ -1821,6 +2141,7 @@ +@@ -1821,6 +2136,7 @@ } propmatch_cleanup: @@ -39933,7 +43515,7 @@ xmlFreeDoc(xml); } else { con->http_status = 400; -@@ -1830,11 +2151,307 @@ +@@ -1830,11 +2146,307 @@ #endif con->http_status = 501; return HANDLER_FINISHED; @@ -40243,7 +43825,7 @@ /* not found */ return HANDLER_GO_ON; } -@@ -1845,14 +2462,14 @@ +@@ -1845,14 +2457,14 @@ int mod_webdav_plugin_init(plugin *p) { p->version = LIGHTTPD_VERSION_ID; p->name = buffer_init_string("webdav"); @@ -40262,7 +43844,7 @@ return 0; } --- ../lighttpd-1.4.11/src/network.c 2006-03-04 16:45:46.000000000 +0200 -+++ lighttpd-1.4.12/src/network.c 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/network.c 2006-07-18 13:03:40.000000000 +0300 @@ -1,14 +1,14 @@ #include #include @@ -40296,7 +43878,7 @@ #endif handler_t network_server_handle_fdevent(void *s, void *context, int revents) { -@@ -31,11 +32,11 @@ +@@ -31,25 +32,25 @@ server_socket *srv_socket = (server_socket *)context; connection *con; int loops = 0; @@ -40309,9 +43891,11 @@ - log_error_write(srv, __FILE__, __LINE__, "sdd", + log_error_write(srv, __FILE__, __LINE__, "sdd", "strange event for server socket", - srv_socket->fd, +- srv_socket->fd, ++ srv_socket->sock->fd, revents); -@@ -44,12 +45,12 @@ + return HANDLER_ERROR; + } /* accept()s at most 100 connections directly * @@ -40357,8 +43941,9 @@ - + srv_socket = calloc(1, sizeof(*srv_socket)); - srv_socket->fd = -1; +- srv_socket->fd = -1; - ++ srv_socket->sock = iosocket_init(); + srv_socket->srv_token = buffer_init(); buffer_copy_string_buffer(srv_socket->srv_token, host_token); @@ -40399,7 +43984,7 @@ port = strtol(sp, NULL, 10); if (host[0] == '/') { -@@ -129,17 +130,17 @@ +@@ -129,18 +130,18 @@ is_unix_domain_socket = 1; } else if (port == 0 || port > 65535) { log_error_write(srv, __FILE__, __LINE__, "sd", "port out of range:", port); @@ -40416,40 +44001,47 @@ srv_socket->addr.plain.sa_family = AF_UNIX; - +- if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, 0))) { + - if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, 0))) { ++ if (-1 == (srv_socket->sock->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, 0))) { log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno)); return -1; -@@ -154,7 +155,7 @@ + } +@@ -154,32 +155,32 @@ #ifdef HAVE_IPV6 if (s->use_ipv6) { srv_socket->addr.plain.sa_family = AF_INET6; - +- if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) { + - if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) { ++ if (-1 == (srv_socket->sock->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) { log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno)); return -1; -@@ -162,7 +163,7 @@ + } srv_socket->use_ipv6 = 1; } #endif - +- if (srv_socket->fd == -1) { + - if (srv_socket->fd == -1) { ++ if (srv_socket->sock->fd == -1) { srv_socket->addr.plain.sa_family = AF_INET; - if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) { -@@ -170,16 +171,16 @@ +- if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) { ++ if (-1 == (srv_socket->sock->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) { + log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno)); return -1; } } - + /* */ - srv->cur_fds = srv_socket->fd; +- srv->cur_fds = srv_socket->fd; - ++ srv->cur_fds = srv_socket->sock->fd; + val = 1; - if (setsockopt(srv_socket->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) { +- if (setsockopt(srv_socket->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) { ++ if (setsockopt(srv_socket->sock->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) { log_error_write(srv, __FILE__, __LINE__, "ss", "socketsockopt failed:", strerror(errno)); return -1; } @@ -40533,8 +44125,12 @@ #ifdef SUN_LEN addr_len = SUN_LEN(&srv_socket->addr.un); #else -@@ -259,8 +261,8 @@ - if (-1 != (fd = connect(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len))) { +@@ -256,11 +258,11 @@ + #endif + + /* check if the socket exists and try to connect to it. */ +- if (-1 != (fd = connect(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len))) { ++ if (-1 != (fd = connect(srv_socket->sock->fd, (struct sockaddr *) &(srv_socket->addr), addr_len))) { close(fd); - log_error_write(srv, __FILE__, __LINE__, "ss", @@ -40566,8 +44162,9 @@ return -1; } - +- if (0 != bind(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len)) { + - if (0 != bind(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len)) { ++ if (0 != bind(srv_socket->sock->fd, (struct sockaddr *) &(srv_socket->addr), addr_len)) { switch(srv_socket->addr.plain.sa_family) { case AF_UNIX: - log_error_write(srv, __FILE__, __LINE__, "sds", @@ -40587,8 +44184,9 @@ return -1; } - +- if (-1 == listen(srv_socket->fd, 128 * 8)) { + - if (-1 == listen(srv_socket->fd, 128 * 8)) { ++ if (-1 == listen(srv_socket->sock->fd, 128 * 8)) { log_error_write(srv, __FILE__, __LINE__, "ss", "listen failed: ", strerror(errno)); return -1; } @@ -40678,20 +44276,28 @@ return -1; #endif } else { -@@ -390,10 +393,10 @@ +@@ -383,17 +386,16 @@ + */ + memset(&afa, 0, sizeof(afa)); + strcpy(afa.af_name, "httpready"); +- if (setsockopt(srv_socket->fd, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa)) < 0) { ++ if (setsockopt(srv_socket->sock->fd, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa)) < 0) { + if (errno != ENOENT) { + log_error_write(srv, __FILE__, __LINE__, "ss", "can't set accept-filter 'httpready': ", strerror(errno)); + } } #endif } - + srv_socket->is_ssl = s->is_ssl; - srv_socket->fde_ndx = -1; +- srv_socket->fde_ndx = -1; - + if (srv->srv_sockets.size == 0) { srv->srv_sockets.size = 4; srv->srv_sockets.used = 0; -@@ -402,11 +405,10 @@ +@@ -402,11 +404,10 @@ srv->srv_sockets.size += 4; srv->srv_sockets.ptr = realloc(srv->srv_sockets.ptr, srv->srv_sockets.size * sizeof(server_socket)); } @@ -40705,29 +44311,36 @@ return 0; } -@@ -414,45 +416,58 @@ +@@ -414,45 +415,60 @@ size_t i; for (i = 0; i < srv->srv_sockets.used; i++) { server_socket *srv_socket = srv->srv_sockets.ptr[i]; - +- if (srv_socket->fd != -1) { + - if (srv_socket->fd != -1) { ++ if (srv_socket->sock->fd != -1) { /* check if server fd are already registered */ - if (srv_socket->fde_ndx != -1) { - fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd); - fdevent_unregister(srv->ev, srv_socket->fd); +- if (srv_socket->fde_ndx != -1) { +- fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd); +- fdevent_unregister(srv->ev, srv_socket->fd); ++ if (srv_socket->sock->fde_ndx != -1) { ++ fdevent_event_del(srv->ev, srv_socket->sock); ++ fdevent_unregister(srv->ev, srv_socket->sock); } - +- close(srv_socket->fd); + - close(srv_socket->fd); - } -- ++ closesocket(srv_socket->sock->fd); ++ } + + if (srv_socket->is_ssl) { +#ifdef USE_OPENSSL + SSL_CTX_free(srv_socket->ssl_ctx); +#endif -+ } + } +- ++ ++ iosocket_free(srv_socket->sock); + buffer_free(srv_socket->srv_token); - @@ -40776,7 +44389,7 @@ /* lowest id wins */ #if defined USE_LINUX_SENDFILE { NETWORK_BACKEND_LINUX_SENDFILE, "linux-sendfile" }, -@@ -466,21 +481,30 @@ +@@ -466,21 +482,30 @@ #if defined USE_WRITEV { NETWORK_BACKEND_WRITEV, "writev" }, #endif @@ -40811,7 +44424,7 @@ #ifdef USE_OPENSSL srv->network_ssl_backend_write = network_write_chunkqueue_openssl; #endif -@@ -500,54 +524,80 @@ +@@ -500,54 +525,80 @@ if (NULL == network_backends[i].name) { /* we don't know it */ @@ -40902,7 +44515,7 @@ return -1; } -@@ -558,36 +608,47 @@ +@@ -558,36 +609,47 @@ break; } } @@ -40928,8 +44541,10 @@ for (i = 0; i < srv->srv_sockets.used; i++) { server_socket *srv_socket = srv->srv_sockets.ptr[i]; - - fdevent_register(srv->ev, srv_socket->fd, network_server_handle_fdevent, srv_socket); - fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN); +- fdevent_register(srv->ev, srv_socket->fd, network_server_handle_fdevent, srv_socket); +- fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN); ++ fdevent_register(srv->ev, srv_socket->sock, network_server_handle_fdevent, srv_socket); ++ fdevent_event_add(srv->ev, srv_socket->sock, FDEVENT_IN); } return 0; } @@ -40937,16 +44552,16 @@ -int network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) { - int ret = -1; +network_status_t network_read_chunkqueue(server *srv, connection *con, chunkqueue *cq) { -+ server_socket *srv_socket = con->srv_socket; ++ server_socket *srv_socket = con->srv_socket; + + if (srv_socket->is_ssl) { +#ifdef USE_OPENSSL -+ return srv->network_ssl_backend_read(srv, con, con->ssl, cq); ++ return srv->network_ssl_backend_read(srv, con, con->sock, cq); +#else + return NETWORK_STATUS_FATAL_ERROR; +#endif + } else { -+ return srv->network_backend_read(srv, con, con->fd, cq); ++ return srv->network_backend_read(srv, con, con->sock, cq); + } +} + @@ -40958,7 +44573,7 @@ int corked = 0; #endif server_socket *srv_socket = con->srv_socket; -@@ -600,11 +661,11 @@ +@@ -600,37 +662,42 @@ joblist_append(srv, con); return 1; @@ -40972,18 +44587,22 @@ /* Linux: put a cork into the socket as we want to combine the write() calls * but only if we really have multiple chunks */ -@@ -613,7 +674,7 @@ - setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked)); + if (cq->first && cq->first->next) { + corked = 1; +- setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked)); ++ setsockopt(con->sock->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked)); } #endif - + if (srv_socket->is_ssl) { #ifdef USE_OPENSSL - ret = srv->network_ssl_backend_write(srv, con, con->ssl, cq); -@@ -621,12 +682,17 @@ +- ret = srv->network_ssl_backend_write(srv, con, con->ssl, cq); ++ ret = srv->network_ssl_backend_write(srv, con, con->sock, cq); + #endif } else { - ret = srv->network_backend_write(srv, con, con->fd, cq); +- ret = srv->network_backend_write(srv, con, con->fd, cq); ++ ret = srv->network_backend_write(srv, con, con->sock, cq); } - - if (ret >= 0) { @@ -41003,7 +44622,12 @@ #ifdef TCP_CORK if (corked) { corked = 0; -@@ -639,13 +705,13 @@ +- setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked)); ++ setsockopt(con->sock->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked)); + } + #endif + +@@ -639,13 +706,13 @@ con->bytes_written_cur_second += written; *(con->conf.global_bytes_per_second_cnt_ptr) += written; @@ -41020,8 +44644,8 @@ return ret; } --- ../lighttpd-1.4.11/src/network.h 2005-08-11 01:26:42.000000000 +0300 -+++ lighttpd-1.4.12/src/network.h 2006-07-11 22:07:51.000000000 +0300 -@@ -3,7 +3,8 @@ ++++ lighttpd-1.4.12/src/network.h 2006-07-18 13:03:40.000000000 +0300 +@@ -3,11 +3,13 @@ #include "server.h" @@ -41031,9 +44655,14 @@ int network_init(server *srv); int network_close(server *srv); + + int network_register_fdevents(server *srv); ++handler_t network_server_handle_fdevent(void *s, void *context, int revents); + + #endif --- ../lighttpd-1.4.11/src/network_backends.h 2005-10-24 15:13:51.000000000 +0300 -+++ lighttpd-1.4.12/src/network_backends.h 2006-07-11 22:07:52.000000000 +0300 -@@ -43,16 +43,52 @@ ++++ lighttpd-1.4.12/src/network_backends.h 2006-07-18 13:03:40.000000000 +0300 +@@ -43,16 +43,47 @@ # define USE_AIX_SENDFILE #endif @@ -41054,13 +44683,13 @@ +#include "network.h" + +#define NETWORK_BACKEND_WRITE_CHUNK(x) \ -+ network_status_t network_write_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq, chunk *c) ++ network_status_t network_write_chunkqueue_##x(server *srv, connection *con, iosocket *sock, chunkqueue *cq, chunk *c) + +#define NETWORK_BACKEND_WRITE(x) \ -+ network_status_t network_write_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq) ++ network_status_t network_write_chunkqueue_##x(server *srv, connection *con, iosocket *sock, chunkqueue *cq) +#define NETWORK_BACKEND_READ(x) \ -+ network_status_t network_read_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq) - ++ network_status_t network_read_chunkqueue_##x(server *srv, connection *con, iosocket *sock, chunkqueue *cq) ++ +NETWORK_BACKEND_WRITE_CHUNK(writev_mem); + +NETWORK_BACKEND_WRITE(write); @@ -41071,7 +44700,7 @@ + +NETWORK_BACKEND_WRITE(win32transmitfile); +NETWORK_BACKEND_WRITE(win32send); -+ + +NETWORK_BACKEND_READ(read); +NETWORK_BACKEND_READ(win32recv); @@ -41082,18 +44711,13 @@ -int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int fd, chunkqueue *cq); #ifdef USE_OPENSSL -int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq); -+#define NETWORK_BACKEND_WRITE_SSL(x) \ -+ network_status_t network_write_chunkqueue_##x(server *srv, connection *con, SSL *ssl, chunkqueue *cq) -+#define NETWORK_BACKEND_READ_SSL(x) \ -+ network_status_t network_read_chunkqueue_##x(server *srv, connection *con, SSL *ssl, chunkqueue *cq) -+ -+NETWORK_BACKEND_WRITE_SSL(openssl); -+NETWORK_BACKEND_READ_SSL(openssl); ++NETWORK_BACKEND_WRITE(openssl); ++NETWORK_BACKEND_READ(openssl); #endif #endif --- ../lighttpd-1.4.11/src/network_freebsd_sendfile.c 2005-10-22 12:28:18.000000000 +0300 -+++ lighttpd-1.4.12/src/network_freebsd_sendfile.c 2006-07-11 22:07:52.000000000 +0300 ++++ lighttpd-1.4.12/src/network_freebsd_sendfile.c 2006-07-16 00:26:04.000000000 +0300 @@ -26,142 +26,61 @@ #ifndef UIO_MAXIOV @@ -41312,7 +44936,7 @@ #endif --- ../lighttpd-1.4.11/src/network_linux_sendfile.c 2006-02-15 20:02:36.000000000 +0200 -+++ lighttpd-1.4.12/src/network_linux_sendfile.c 2006-07-15 22:43:21.000000000 +0300 ++++ lighttpd-1.4.12/src/network_linux_sendfile.c 2006-07-18 13:03:40.000000000 +0300 @@ -26,122 +26,54 @@ /* on linux 2.4.29 + debian/ubuntu we have crashes if this is enabled */ #undef HAVE_POSIX_FADVISE @@ -41396,7 +45020,7 @@ - /* check which chunks have been written */ - cq->bytes_out += r; + case MEM_CHUNK: -+ ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, c); ++ ret = network_write_chunkqueue_writev_mem(srv, con, sock, cq, c); - for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) { - if (r >= (ssize_t)chunks[i].iov_len) { @@ -41459,7 +45083,7 @@ return -1; } #ifdef FD_CLOEXEC -@@ -151,7 +83,7 @@ +@@ -151,14 +83,14 @@ /* tell the kernel that we want to stream the file */ if (-1 == posix_fadvise(c->file.fd, 0, 0, POSIX_FADV_SEQUENTIAL)) { if (ENOSYS != errno) { @@ -41468,16 +45092,31 @@ "posix_fadvise failed:", strerror(errno), c->file.fd); } } -@@ -168,7 +100,7 @@ + #endif + } + +- if (-1 == (r = sendfile(fd, c->file.fd, &offset, toSend))) { ++ if (-1 == (r = sendfile(sock->fd, c->file.fd, &offset, toSend))) { + switch (errno) { + case EAGAIN: + case EINTR: +@@ -166,11 +98,11 @@ + break; + case EPIPE: case ECONNRESET: - return -2; +- return -2; ++ return NETWORK_STATUS_CONNECTION_CLOSE; default: - log_error_write(srv, __FILE__, __LINE__, "ssd", +- "sendfile failed:", strerror(errno), fd); +- return -1; + log_error_write(srv, __FILE__, __LINE__, "ssd", - "sendfile failed:", strerror(errno), fd); - return -1; ++ "sendfile failed:", strerror(errno), sock->fd); ++ return NETWORK_STATUS_FATAL_ERROR; } -@@ -179,7 +111,7 @@ + } + +@@ -179,39 +111,39 @@ * * - the file shrinked -> error * - the remote side closed inbetween -> remote-close */ @@ -41485,8 +45124,20 @@ + if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) { /* file is gone ? */ - return -1; -@@ -196,22 +128,22 @@ +- return -1; ++ return NETWORK_STATUS_FATAL_ERROR; + } + + if (offset > sce->st.st_size) { + /* file shrinked, close the connection */ +- return -1; ++ return NETWORK_STATUS_FATAL_ERROR; + } + +- return -2; ++ return NETWORK_STATUS_CONNECTION_CLOSE; + } + #ifdef HAVE_POSIX_FADVISE #if 0 #define K * 1024 @@ -41526,16 +45177,18 @@ + log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known"); - +- return -1; + - return -1; ++ return NETWORK_STATUS_FATAL_ERROR; } - + if (!chunk_finished) { /* not finished yet */ - +- break; + - break; ++ return NETWORK_STATUS_WAIT_FOR_EVENT; } } @@ -41545,7 +45198,7 @@ #endif --- ../lighttpd-1.4.11/src/network_openssl.c 2005-11-17 14:53:29.000000000 +0200 -+++ lighttpd-1.4.12/src/network_openssl.c 2006-07-11 22:07:52.000000000 +0300 ++++ lighttpd-1.4.12/src/network_openssl.c 2006-07-18 13:03:40.000000000 +0300 @@ -23,17 +23,87 @@ #include "log.h" #include "stat_cache.h" @@ -41556,20 +45209,20 @@ +# include -int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq) { -+NETWORK_BACKEND_READ_SSL(openssl) { ++NETWORK_BACKEND_READ(openssl) { + buffer *b; + off_t len; + + b = chunkqueue_get_append_buffer(cq); + buffer_prepare_copy(b, 8192); -+ len = SSL_read(ssl, b->ptr, b->size - 1); ++ len = SSL_read(sock->ssl, b->ptr, b->size - 1); + + log_error_write(srv, __FILE__, __LINE__, "so", "SSL:", len); + + if (len < 0) { + int r, ssl_err; + -+ switch ((r = SSL_get_error(con->ssl, len))) { ++ switch ((r = SSL_get_error(sock->ssl, len))) { + case SSL_ERROR_WANT_READ: + return NETWORK_STATUS_WAIT_FOR_EVENT; + case SSL_ERROR_SYSCALL: @@ -41626,7 +45279,7 @@ +} + + -+NETWORK_BACKEND_WRITE_SSL(openssl) { ++NETWORK_BACKEND_WRITE(openssl) { int ssl_r; chunk *c; size_t chunks_written = 0; @@ -41638,7 +45291,7 @@ * of SSL_write to pass the SAME parameter in case of a _WANT_WRITE * * the buffer is allocated once, is NOT realloced and is NOT freed at shutdown -@@ -43,14 +113,14 @@ +@@ -43,59 +113,61 @@ * In reality we would like to use mmap() but we don't have a guarantee that * we get the same mmap() address for each call. On openbsd the mmap() address * even randomized. @@ -41656,7 +45309,10 @@ * - wget * if keep-alive is disabled */ -@@ -60,32 +130,34 @@ + if (con->keep_alive == 0) { +- SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN); ++ SSL_set_shutdown(sock->ssl, SSL_RECEIVED_SHUTDOWN); + } for(c = cq->first; c; c = c->next) { int chunk_finished = 0; @@ -41696,11 +45352,14 @@ - - if ((r = SSL_write(ssl, offset, toSend)) <= 0) { + -+ if (toSend != 0 && (r = SSL_write(ssl, offset, toSend)) <= 0) { ++ if (toSend != 0 && (r = SSL_write(sock->ssl, offset, toSend)) <= 0) { unsigned long err; - switch ((ssl_r = SSL_get_error(ssl, r))) { -@@ -95,7 +167,7 @@ +- switch ((ssl_r = SSL_get_error(ssl, r))) { ++ switch ((ssl_r = SSL_get_error(sock->ssl, r))) { + case SSL_ERROR_WANT_WRITE: + break; + case SSL_ERROR_SYSCALL: /* perhaps we have error waiting in our error-queue */ if (0 != (err = ERR_get_error())) { do { @@ -41788,7 +45447,7 @@ return -1; } -@@ -183,9 +255,9 @@ +@@ -183,13 +255,13 @@ } s = local_send_buffer; @@ -41796,10 +45455,16 @@ + close(ifd); - +- if ((r = SSL_write(ssl, s, toSend)) <= 0) { + - if ((r = SSL_write(ssl, s, toSend)) <= 0) { ++ if ((r = SSL_write(sock->ssl, s, toSend)) <= 0) { unsigned long err; +- switch ((ssl_r = SSL_get_error(ssl, r))) { ++ switch ((ssl_r = SSL_get_error(sock->ssl, r))) { + case SSL_ERROR_WANT_WRITE: + write_wait = 1; + break; @@ -197,7 +269,7 @@ /* perhaps we have error waiting in our error-queue */ if (0 != (err = ERR_get_error())) { @@ -41809,7 +45474,7 @@ ssl_r, r, ERR_error_string(err, NULL)); } while((err = ERR_get_error())); -@@ -207,58 +279,58 @@ +@@ -207,62 +279,62 @@ case EPIPE: return -2; default: @@ -41881,8 +45546,13 @@ chunks_written++; } +- return chunks_written; ++ return NETWORK_STATUS_SUCCESS; + } + #endif + --- ../lighttpd-1.4.11/src/network_solaris_sendfilev.c 2005-10-22 12:28:27.000000000 +0300 -+++ lighttpd-1.4.12/src/network_solaris_sendfilev.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/network_solaris_sendfilev.c 2006-07-16 00:26:04.000000000 +0300 @@ -29,114 +29,34 @@ #endif @@ -42103,7 +45773,7 @@ #endif --- ../lighttpd-1.4.11/src/network_write.c 2005-10-22 12:27:56.000000000 +0300 -+++ lighttpd-1.4.12/src/network_write.c 2006-07-15 22:43:21.000000000 +0300 ++++ lighttpd-1.4.12/src/network_write.c 2006-07-18 13:03:40.000000000 +0300 @@ -1,11 +1,11 @@ #include #include @@ -42131,11 +45801,12 @@ #ifdef HAVE_SYS_FILIO_H # include #endif -@@ -24,47 +27,84 @@ +@@ -24,47 +27,92 @@ #include #endif -int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq) { ++ +/** +* fill the chunkqueue will all the data that we can get +* @@ -42147,6 +45818,11 @@ + buffer *b; + off_t r; + ++ /** ++ * a EAGAIN is a successful read if we already read something to the chunkqueue ++ */ ++ int read_something = 0; ++ + /* use a chunk-size of 8k */ + do { + toread = 8192; @@ -42155,27 +45831,29 @@ + + buffer_prepare_copy(b, toread); + -+ if (-1 == (r = read(fd, b->ptr, toread))) { ++ if (-1 == (r = read(sock->fd, b->ptr, toread))) { + switch (errno) { + case EAGAIN: -+ return NETWORK_STATUS_WAIT_FOR_EVENT; ++ /* remove the last chunk from the chunkqueue */ ++ chunkqueue_remove_empty_last_chunk(cq); ++ return read_something ? NETWORK_STATUS_SUCCESS : NETWORK_STATUS_WAIT_FOR_EVENT; + default: -+ log_error_write(srv, __FILE__, __LINE__, "sds", -+ "unexpected end-of-file (perhaps the proxy process died):", -+ fd, strerror(errno)); ++ ERROR("oops, read from fd=%d failed: %s (%d)", sock->fd, strerror(errno), errno ); ++ + return NETWORK_STATUS_FATAL_ERROR; + } + } + + if (r == 0) { -+ return NETWORK_STATUS_CONNECTION_CLOSE; ++ chunkqueue_remove_empty_last_chunk(cq); ++ return read_something ? NETWORK_STATUS_SUCCESS : NETWORK_STATUS_CONNECTION_CLOSE; + } + -+ /* this should be catched by the b > 0 above */ -+ assert(r); -+ b->used += r + 1; -+ b->ptr[b->used - 1] = '\0'; -+ } while (r == toread); ++ read_something = 1; ++ ++ b->used = r; ++ b->ptr[b->used++] = '\0'; ++ } while (r == toread); + + return NETWORK_STATUS_SUCCESS; +} @@ -42211,12 +45889,14 @@ - return -1; - } -#else -+ - if ((r = write(fd, offset, toSend)) < 0) { - log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd); +- if ((r = write(fd, offset, toSend)) < 0) { +- log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd); - - return -1; + ++ if ((r = write(sock->fd, offset, toSend)) < 0) { ++ log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), sock->fd); ++ + return NETWORK_STATUS_FATAL_ERROR; } -#endif @@ -42234,7 +45914,7 @@ break; } case FILE_CHUNK: { -@@ -76,93 +116,89 @@ +@@ -76,93 +124,89 @@ size_t toSend; stat_cache_entry *sce = NULL; int ifd; @@ -42281,7 +45961,8 @@ } close(ifd); - if ((r = write(fd, p + offset, toSend)) <= 0) { +- if ((r = write(fd, p + offset, toSend)) <= 0) { ++ if ((r = write(sock->fd, p + offset, toSend)) <= 0) { log_error_write(srv, __FILE__, __LINE__, "ss", "write failed: ", strerror(errno)); munmap(p, sce->st.st_size); - return -1; @@ -42305,7 +45986,8 @@ } close(ifd); - if (-1 == (r = send(fd, srv->tmp_buf->ptr, toSend, 0))) { +- if (-1 == (r = send(fd, srv->tmp_buf->ptr, toSend, 0))) { ++ if (-1 == (r = send(sock->fd, srv->tmp_buf->ptr, toSend, 0))) { log_error_write(srv, __FILE__, __LINE__, "ss", "write: ", strerror(errno)); - - return -1; @@ -42356,7 +46038,7 @@ -} #endif --- ../lighttpd-1.4.11/src/network_writev.c 2006-02-15 01:02:36.000000000 +0200 -+++ lighttpd-1.4.12/src/network_writev.c 2006-07-15 22:43:21.000000000 +0300 ++++ lighttpd-1.4.12/src/network_writev.c 2006-07-18 13:03:40.000000000 +0300 @@ -28,10 +28,10 @@ #ifndef UIO_MAXIOV @@ -42420,7 +46102,7 @@ + } + } + -+ if ((r = writev(fd, chunks, num_chunks)) < 0) { ++ if ((r = writev(sock->fd, chunks, num_chunks)) < 0) { + switch (errno) { + case EAGAIN: + return NETWORK_STATUS_WAIT_FOR_EVENT; @@ -42431,7 +46113,7 @@ + return NETWORK_STATUS_CONNECTION_CLOSE; + default: + log_error_write(srv, __FILE__, __LINE__, "ssd", -+ "writev failed:", strerror(errno), fd); ++ "writev failed:", strerror(errno), sock->fd); + + return NETWORK_STATUS_FATAL_ERROR; + } @@ -42533,7 +46215,7 @@ - - cq->bytes_out += r; + case MEM_CHUNK: -+ ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, c); ++ ret = network_write_chunkqueue_writev_mem(srv, con, sock, cq, c); - /* check which chunks have been written */ - @@ -42669,6 +46351,15 @@ assert(toSend < 0); } +@@ -289,7 +305,7 @@ + start = c->file.mmap.start; + #endif + +- if ((r = write(fd, start + (abs_offset - c->file.mmap.offset), toSend)) < 0) { ++ if ((r = write(sock->fd, start + (abs_offset - c->file.mmap.offset), toSend)) < 0) { + switch (errno) { + case EAGAIN: + case EINTR: @@ -297,18 +313,18 @@ break; case EPIPE: @@ -42677,10 +46368,11 @@ + return NETWORK_STATUS_CONNECTION_CLOSE; default: - log_error_write(srv, __FILE__, __LINE__, "ssd", -+ log_error_write(srv, __FILE__, __LINE__, "ssd", - "write failed:", strerror(errno), fd); +- "write failed:", strerror(errno), fd); - - return -1; ++ log_error_write(srv, __FILE__, __LINE__, "ssd", ++ "write failed:", strerror(errno), sock->fd); + + return NETWORK_STATUS_FATAL_ERROR; } @@ -42730,7 +46422,7 @@ #endif --- ../lighttpd-1.4.11/src/plugin.c 2006-02-08 14:00:54.000000000 +0200 -+++ lighttpd-1.4.12/src/plugin.c 2006-07-11 22:07:52.000000000 +0300 ++++ lighttpd-1.4.12/src/plugin.c 2006-07-16 00:26:04.000000000 +0300 @@ -13,27 +13,27 @@ #include #endif @@ -43178,7 +46870,7 @@ srv->plugins.ptr = NULL; srv->plugins.used = 0; --- ../lighttpd-1.4.11/src/plugin.h 2005-08-15 12:28:56.000000000 +0300 -+++ lighttpd-1.4.12/src/plugin.h 2006-07-11 22:07:52.000000000 +0300 ++++ lighttpd-1.4.12/src/plugin.h 2006-07-16 00:26:04.000000000 +0300 @@ -12,6 +12,12 @@ #define INIT_FUNC(x) \ @@ -43256,7 +46948,7 @@ #endif --- ../lighttpd-1.4.11/src/proc_open.c 2005-08-11 01:26:39.000000000 +0300 -+++ lighttpd-1.4.12/src/proc_open.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/proc_open.c 2006-07-16 00:26:04.000000000 +0300 @@ -13,13 +13,13 @@ #endif @@ -43343,7 +47035,7 @@ for (;;) { buffer_prepare_append(b, 512); --- ../lighttpd-1.4.11/src/proc_open.h 2005-08-11 01:26:39.000000000 +0300 -+++ lighttpd-1.4.12/src/proc_open.h 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/proc_open.h 2006-07-16 00:26:04.000000000 +0300 @@ -1,7 +1,7 @@ #include "buffer.h" @@ -43354,7 +47046,7 @@ typedef HANDLE descriptor_t; typedef HANDLE proc_pid_t; --- ../lighttpd-1.4.11/src/request.c 2006-03-05 11:58:09.000000000 +0200 -+++ lighttpd-1.4.12/src/request.c 2006-07-11 22:07:52.000000000 +0300 ++++ lighttpd-1.4.12/src/request.c 2006-07-18 13:03:40.000000000 +0300 @@ -10,15 +10,17 @@ #include "keyvalue.h" #include "log.h" @@ -43645,7 +47337,7 @@ - "fd:", con->fd, - "request-len:", con->request.request->used, + log_error_write(srv, __FILE__, __LINE__, "sdsdSb", -+ "fd:", con->fd, ++ "fd:", con->sock->fd, + "request-len:", con->request.request->used, "\n", con->request.request); } @@ -44465,7 +48157,7 @@ return 0; } --- ../lighttpd-1.4.11/src/response.c 2006-03-04 16:41:39.000000000 +0200 -+++ lighttpd-1.4.12/src/response.c 2006-07-11 22:07:52.000000000 +0300 ++++ lighttpd-1.4.12/src/response.c 2006-07-16 00:26:04.000000000 +0300 @@ -7,7 +7,6 @@ #include #include @@ -45131,7 +48823,7 @@ return HANDLER_COMEBACK; } --- ../lighttpd-1.4.11/src/server.c 2006-03-04 19:12:17.000000000 +0200 -+++ lighttpd-1.4.12/src/server.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/server.c 2006-07-18 13:03:40.000000000 +0300 @@ -1,11 +1,9 @@ #include -#include @@ -45160,7 +48852,7 @@ #endif #ifdef HAVE_VALGRIND_VALGRIND_H -@@ -60,8 +63,16 @@ +@@ -60,8 +63,17 @@ /* #define USE_ALARM */ #endif @@ -45170,6 +48862,7 @@ + +#include "sys-files.h" +#include "sys-process.h" ++#include "sys-socket.h" + static volatile sig_atomic_t srv_shutdown = 0; static volatile sig_atomic_t graceful_shutdown = 0; @@ -45177,7 +48870,7 @@ static volatile sig_atomic_t handle_sig_alarm = 1; static volatile sig_atomic_t handle_sig_hup = 0; -@@ -72,9 +83,9 @@ +@@ -72,9 +84,9 @@ switch (sig) { case SIGTERM: srv_shutdown = 1; break; @@ -45189,7 +48882,7 @@ break; case SIGALRM: handle_sig_alarm = 1; break; -@@ -86,9 +97,9 @@ +@@ -86,9 +98,9 @@ static void signal_handler(int sig) { switch (sig) { case SIGTERM: srv_shutdown = 1; break; @@ -45201,7 +48894,7 @@ break; case SIGALRM: handle_sig_alarm = 1; break; -@@ -110,25 +121,26 @@ +@@ -110,35 +122,35 @@ signal(SIGTSTP, SIG_IGN); #endif if (0 != fork()) exit(0); @@ -45232,7 +48925,9 @@ CLEAN(response_header); CLEAN(parse_full_path); CLEAN(ts_debug_str); -@@ -138,7 +150,7 @@ + CLEAN(ts_date_str); +- CLEAN(errorlog_buf); + CLEAN(response_range); CLEAN(tmp_buf); srv->empty_string = buffer_init_string(""); CLEAN(cond_check_buf); @@ -45241,7 +48936,7 @@ CLEAN(srvconf.errorlog_file); CLEAN(srvconf.groupname); CLEAN(srvconf.username); -@@ -146,58 +158,58 @@ +@@ -146,68 +158,63 @@ CLEAN(srvconf.bindhost); CLEAN(srvconf.event_handler); CLEAN(srvconf.pid_file); @@ -45287,10 +48982,9 @@ srv->srvconf.network_backend = buffer_init(); srv->srvconf.upload_tempdirs = array_init(); - -+ - /* use syslog */ - srv->errorlog_fd = -1; - srv->errorlog_mode = ERRORLOG_STDERR; +- /* use syslog */ +- srv->errorlog_fd = -1; +- srv->errorlog_mode = ERRORLOG_STDERR; srv->split_vals = array_init(); - @@ -45314,7 +49008,9 @@ CLEAN(response_header); CLEAN(parse_full_path); CLEAN(ts_debug_str); -@@ -207,7 +219,7 @@ + CLEAN(ts_date_str); +- CLEAN(errorlog_buf); + CLEAN(response_range); CLEAN(tmp_buf); CLEAN(empty_string); CLEAN(cond_check_buf); @@ -45323,7 +49019,7 @@ CLEAN(srvconf.errorlog_file); CLEAN(srvconf.groupname); CLEAN(srvconf.username); -@@ -217,7 +229,7 @@ +@@ -217,7 +224,7 @@ CLEAN(srvconf.pid_file); CLEAN(srvconf.modules_dir); CLEAN(srvconf.network_backend); @@ -45332,7 +49028,7 @@ CLEAN(tmp_chunk_len); #undef CLEAN -@@ -225,15 +237,15 @@ +@@ -225,15 +232,15 @@ fdevent_unregister(srv->ev, srv->fd); #endif fdevent_free(srv->ev); @@ -45351,7 +49047,7 @@ buffer_free(s->document_root); buffer_free(s->server_name); buffer_free(s->server_tag); -@@ -242,32 +254,32 @@ +@@ -242,32 +249,32 @@ buffer_free(s->error_handler); buffer_free(s->errorfile_prefix); array_free(s->mimetypes); @@ -45390,7 +49086,7 @@ free(srv); } -@@ -281,14 +293,12 @@ +@@ -281,14 +288,12 @@ " - a light and fast webserver\n" \ "Build-Date: " __DATE__ " " __TIME__ "\n"; ; @@ -45407,7 +49103,7 @@ #ifdef USE_SELECT "\t+ select (generic)\n" #else -@@ -355,11 +365,6 @@ +@@ -355,11 +360,6 @@ #else "\t- crypt support\n" #endif @@ -45419,7 +49115,7 @@ #ifdef USE_OPENSSL "\t+ SSL Support\n" #else -@@ -371,9 +376,9 @@ +@@ -371,9 +371,9 @@ "\t- PCRE support\n" #endif #ifdef HAVE_MYSQL @@ -45431,7 +49127,7 @@ #endif #if defined(HAVE_LDAP_H) && defined(HAVE_LBER_H) && defined(HAVE_LIBLDAP) && defined(HAVE_LIBLBER) "\t+ LDAP support\n" -@@ -410,8 +415,11 @@ +@@ -410,8 +410,11 @@ #else "\t- GDBM support\n" #endif @@ -45445,7 +49141,7 @@ } static void show_help (void) { -@@ -433,12 +441,12 @@ +@@ -433,277 +436,644 @@ " -h show this help\n" \ "\n" ; @@ -45456,262 +49152,829 @@ } -int main (int argc, char **argv) { +- server *srv = NULL; +- int print_config = 0; +- int test_config = 0; +- int i_am_root; +- int o; +- int num_childs = 0; +- int pid_fd = -1, fd; +- size_t i; +-#ifdef HAVE_SIGACTION +- struct sigaction act; +-#endif +-#ifdef HAVE_GETRLIMIT +- struct rlimit rlim; +-#endif +- +-#ifdef USE_ALARM +- struct itimerval interval; +- +- interval.it_interval.tv_sec = 1; +- interval.it_interval.tv_usec = 0; +- interval.it_value.tv_sec = 1; +- interval.it_value.tv_usec = 0; +-#endif +- +- +- /* for nice %b handling in strfime() */ +- setlocale(LC_TIME, "C"); +- +- if (NULL == (srv = server_init())) { +- fprintf(stderr, "did this really happen?\n"); +- return -1; +- } +- +- /* init structs done */ +- +- srv->srvconf.port = 0; +-#ifdef HAVE_GETUID +- i_am_root = (getuid() == 0); +-#else +- i_am_root = 0; +-#endif +- srv->srvconf.dont_daemonize = 0; +- +- while(-1 != (o = getopt(argc, argv, "f:m:hvVDpt"))) { +- switch(o) { +- case 'f': +- if (config_read(srv, optarg)) { +- server_free(srv); +- return -1; +- } +- break; +- case 'm': +- buffer_copy_string(srv->srvconf.modules_dir, optarg); +- break; +- case 'p': print_config = 1; break; +- case 't': test_config = 1; break; +- case 'D': srv->srvconf.dont_daemonize = 1; break; +- case 'v': show_version(); return 0; +- case 'V': show_features(); return 0; +- case 'h': show_help(); return 0; +- default: +- show_help(); +- server_free(srv); +- return -1; +- } +- } +- +- if (!srv->config_storage) { +- log_error_write(srv, __FILE__, __LINE__, "s", +- "No configuration available. Try using -f option."); +- +- server_free(srv); +- return -1; +- } +- +- if (print_config) { +- data_unset *dc = srv->config_context->data[0]; +- if (dc) { +- dc->print(dc, 0); +- fprintf(stderr, "\n"); +- } else { +- /* shouldn't happend */ +- fprintf(stderr, "global config not found\n"); +- } +- } ++int lighty_mainloop(server *srv) { ++ fdevent_revents *revents = fdevent_revents_init(); + +- if (test_config) { +- printf("Syntax OK\n"); +- } ++ /* main-loop */ ++ while (!srv_shutdown) { ++ int n; ++ size_t ndx; ++ time_t min_ts; + +- if (test_config || print_config) { +- server_free(srv); +- return 0; +- } +- +- /* close stdin and stdout, as they are not needed */ +- /* move stdin to /dev/null */ +- if (-1 != (fd = open("/dev/null", O_RDONLY))) { +- close(STDIN_FILENO); +- dup2(fd, STDIN_FILENO); +- close(fd); +- } +- +- /* move stdout to /dev/null */ +- if (-1 != (fd = open("/dev/null", O_WRONLY))) { +- close(STDOUT_FILENO); +- dup2(fd, STDOUT_FILENO); +- close(fd); +- } +- +- if (0 != config_set_defaults(srv)) { +- log_error_write(srv, __FILE__, __LINE__, "s", +- "setting default values failed"); +- server_free(srv); +- return -1; +- } +- +- /* UID handling */ +-#ifdef HAVE_GETUID +- if (!i_am_root && (geteuid() == 0 || getegid() == 0)) { +- /* we are setuid-root */ +- +- log_error_write(srv, __FILE__, __LINE__, "s", +- "Are you nuts ? Don't apply a SUID bit to this binary"); +- +- server_free(srv); +- return -1; +- } +-#endif +- +- /* check document-root */ +- if (srv->config_storage[0]->document_root->used <= 1) { +- log_error_write(srv, __FILE__, __LINE__, "s", +- "document-root is not set\n"); +- +- server_free(srv); +- +- return -1; +- } +- +- if (plugins_load(srv)) { +- log_error_write(srv, __FILE__, __LINE__, "s", +- "loading plugins finally failed"); +- +- plugins_free(srv); +- server_free(srv); +- +- return -1; +- } +- +- /* open pid file BEFORE chroot */ +- if (srv->srvconf.pid_file->used) { +- if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) { +- struct stat st; +- if (errno != EEXIST) { +- log_error_write(srv, __FILE__, __LINE__, "sbs", +- "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno)); +- return -1; +- } +- +- if (0 != stat(srv->srvconf.pid_file->ptr, &st)) { +- log_error_write(srv, __FILE__, __LINE__, "sbs", +- "stating existing pid-file failed:", srv->srvconf.pid_file, strerror(errno)); +- } +- +- if (!S_ISREG(st.st_mode)) { +- log_error_write(srv, __FILE__, __LINE__, "sb", +- "pid-file exists and isn't regular file:", srv->srvconf.pid_file); +- return -1; +- } +- +- if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) { +- log_error_write(srv, __FILE__, __LINE__, "sbs", +- "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno)); +- return -1; ++ if (handle_sig_hup) { ++ handler_t r; ++ ++ /* reset notification */ ++ handle_sig_hup = 0; ++ ++#if 0 ++ pid_t pid; ++ ++ /* send the old process into a graceful-shutdown and start a ++ * new process right away ++ * ++ * BUGS: ++ * - if webserver is running on port < 1024 (e.g. 80, 433) ++ * we don't have the permissions to bind to that port anymore ++ * ++ * ++ * */ ++ if (0 == (pid = fork())) { ++ execve(argv[0], argv, envp); ++ ++ exit(-1); ++ } else if (pid == -1) { ++ ++ } else { ++ /* parent */ ++ ++ graceful_shutdown = 1; /* shutdown without killing running connections */ ++ graceful_restart = 1; /* don't delete pid file */ + } +- } +- } ++#else ++ /* cycle logfiles */ + +- if (srv->event_handler == FDEVENT_HANDLER_SELECT) { +- /* select limits itself +- * +- * as it is a hard limit and will lead to a segfault we add some safety +- * */ +- srv->max_fds = FD_SETSIZE - 200; +- } else { +- srv->max_fds = 4096; +- } ++ switch(r = plugins_call_handle_sighup(srv)) { ++ case HANDLER_GO_ON: ++ break; ++ default: ++ log_error_write(srv, __FILE__, __LINE__, "sd", "sighup-handler return with an error", r); ++ break; ++ } + +- if (i_am_root) { +- struct group *grp = NULL; +- struct passwd *pwd = NULL; +- int use_rlimit = 1; ++ if (-1 == log_error_cycle()) { ++ log_error_write(srv, __FILE__, __LINE__, "s", "cycling errorlog failed, dying"); + +-#ifdef HAVE_VALGRIND_VALGRIND_H +- if (RUNNING_ON_VALGRIND) use_rlimit = 0; +-#endif +- +-#ifdef HAVE_GETRLIMIT +- if (0 != getrlimit(RLIMIT_NOFILE, &rlim)) { +- log_error_write(srv, __FILE__, __LINE__, +- "ss", "couldn't get 'max filedescriptors'", +- strerror(errno)); +- return -1; +- } +- +- if (use_rlimit && srv->srvconf.max_fds) { +- /* set rlimits */ +- +- rlim.rlim_cur = srv->srvconf.max_fds; +- rlim.rlim_max = srv->srvconf.max_fds; +- +- if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) { +- log_error_write(srv, __FILE__, __LINE__, +- "ss", "couldn't set 'max filedescriptors'", +- strerror(errno)); + return -1; + } ++#endif + } + +- /* #372: solaris need some fds extra for devpoll */ +- if (rlim.rlim_cur > 10) rlim.rlim_cur -= 10; ++ if (handle_sig_alarm) { ++ /* a new second */ + +- if (srv->event_handler == FDEVENT_HANDLER_SELECT) { +- srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 200 ? rlim.rlim_cur : FD_SETSIZE - 200; +- } else { +- srv->max_fds = rlim.rlim_cur; +- } ++#ifdef USE_ALARM ++ /* reset notification */ ++ handle_sig_alarm = 0; ++#endif + +- /* set core file rlimit, if enable_cores is set */ +- if (use_rlimit && srv->srvconf.enable_cores && getrlimit(RLIMIT_CORE, &rlim) == 0) { +- rlim.rlim_cur = rlim.rlim_max; ++ /* get current time */ ++ min_ts = time(NULL); ++ ++ if (min_ts != srv->cur_ts) { ++ int cs = 0; ++ connections *conns = srv->conns; ++ handler_t r; ++ ++ switch(r = plugins_call_handle_trigger(srv)) { ++ case HANDLER_GO_ON: ++ break; ++ case HANDLER_ERROR: ++ log_error_write(srv, __FILE__, __LINE__, "s", "one of the triggers failed"); ++ break; ++ default: ++ log_error_write(srv, __FILE__, __LINE__, "d", r); ++ break; ++ } ++ ++ /* trigger waitpid */ ++ srv->cur_ts = min_ts; ++ ++ /* cleanup stat-cache */ ++ stat_cache_trigger_cleanup(srv); ++ /** ++ * check all connections for timeouts ++ * ++ */ ++ for (ndx = 0; ndx < conns->used; ndx++) { ++ int changed = 0; ++ connection *con; ++ int t_diff; ++ ++ con = conns->ptr[ndx]; ++ ++ if (con->state == CON_STATE_READ || ++ con->state == CON_STATE_READ_POST) { ++ if (con->request_count == 1) { ++ if (srv->cur_ts - con->read_idle_ts > con->conf.max_read_idle) { ++ /* time - out */ ++#if 0 ++ log_error_write(srv, __FILE__, __LINE__, "sd", ++ "connection closed - read-timeout:", con->fd); ++#endif ++ connection_set_state(srv, con, CON_STATE_ERROR); ++ changed = 1; ++ } ++ } else { ++ if (srv->cur_ts - con->read_idle_ts > con->conf.max_keep_alive_idle) { ++ /* time - out */ ++#if 0 ++ log_error_write(srv, __FILE__, __LINE__, "sd", ++ "connection closed - read-timeout:", con->fd); ++#endif ++ connection_set_state(srv, con, CON_STATE_ERROR); ++ changed = 1; ++ } ++ } ++ } ++ ++ if ((con->state == CON_STATE_WRITE) && ++ (con->write_request_ts != 0)) { ++#if 0 ++ if (srv->cur_ts - con->write_request_ts > 60) { ++ log_error_write(srv, __FILE__, __LINE__, "sdd", ++ "connection closed - pre-write-request-timeout:", con->fd, srv->cur_ts - con->write_request_ts); ++ } ++#endif ++ ++ if (srv->cur_ts - con->write_request_ts > con->conf.max_write_idle) { ++ /* time - out */ ++#if 1 ++ log_error_write(srv, __FILE__, __LINE__, "sbsosds", ++ "NOTE: a request for", ++ con->request.uri, ++ "timed out after writing", ++ con->bytes_written, ++ "bytes. We waited", ++ (int)con->conf.max_write_idle, ++ "seconds. If this a problem increase server.max-write-idle"); ++#endif ++ connection_set_state(srv, con, CON_STATE_ERROR); ++ changed = 1; ++ } ++ } ++ /* we don't like div by zero */ ++ if (0 == (t_diff = srv->cur_ts - con->connection_start)) t_diff = 1; ++ ++ if (con->traffic_limit_reached && ++ (con->conf.kbytes_per_second == 0 || ++ ((con->bytes_written / t_diff) < con->conf.kbytes_per_second * 1024))) { ++ /* enable connection again */ ++ con->traffic_limit_reached = 0; ++ ++ changed = 1; ++ } ++ ++ if (changed) { ++ connection_state_machine(srv, con); ++ } ++ con->bytes_written_cur_second = 0; ++ *(con->conf.global_bytes_per_second_cnt_ptr) = 0; ++ ++#if 0 ++ if (cs == 0) { ++ fprintf(stderr, "connection-state: "); ++ cs = 1; ++ } ++ ++ fprintf(stderr, "c[%d,%d]: %s ", ++ con->fd, ++ con->fcgi.fd, ++ connection_get_state(con->state)); ++#endif ++ } ++ ++ if (cs == 1) fprintf(stderr, "\n"); ++ } ++ } ++ ++ if (srv->sockets_disabled) { ++ /* our server sockets are disabled, why ? */ ++ ++ if ((srv->cur_fds + srv->want_fds < srv->max_fds * 0.8) && /* we have enough unused fds */ ++ (srv->conns->used < srv->max_conns * 0.9) && ++ (0 == graceful_shutdown)) { ++ size_t i; ++ ++ for (i = 0; i < srv->srv_sockets.used; i++) { ++ server_socket *srv_socket = srv->srv_sockets.ptr[i]; ++ fdevent_event_add(srv->ev, srv_socket->sock, FDEVENT_IN); ++ } ++ ++ log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets enabled again"); ++ ++ srv->sockets_disabled = 0; ++ } ++ } else { ++ if ((srv->cur_fds + srv->want_fds > srv->max_fds * 0.9) || /* out of fds */ ++ (srv->conns->used > srv->max_conns) || /* out of connections */ ++ (graceful_shutdown)) { /* graceful_shutdown */ ++ size_t i; ++ ++ /* disable server-fds */ ++ ++ for (i = 0; i < srv->srv_sockets.used; i++) { ++ server_socket *srv_socket = srv->srv_sockets.ptr[i]; ++ fdevent_event_del(srv->ev, srv_socket->sock); ++ ++ if (graceful_shutdown) { ++ /* we don't want this socket anymore, ++ * ++ * closing it right away will make it possible for ++ * the next lighttpd to take over (graceful restart) ++ * */ ++ ++ fdevent_unregister(srv->ev, srv_socket->sock); ++ closesocket(srv_socket->sock->fd); ++ srv_socket->sock->fd = -1; ++ ++ /* network_close() will cleanup after us */ ++ } ++ } ++ ++ if (graceful_shutdown) { ++ log_error_write(srv, __FILE__, __LINE__, "s", "[note] graceful shutdown started"); ++ } else if (srv->conns->used > srv->max_conns) { ++ log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, connection limit reached"); ++ } else { ++ log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, out-of-fds"); ++ } ++ ++ srv->sockets_disabled = 1; ++ } ++ } ++ ++ if (graceful_shutdown && srv->conns->used == 0) { ++ /* we are in graceful shutdown phase and all connections are closed ++ * we are ready to terminate without harming anyone */ ++ srv_shutdown = 1; ++ } ++ ++ /* we still have some fds to share */ ++ if (srv->want_fds) { ++ /* check the fdwaitqueue for waiting fds */ ++ int free_fds = srv->max_fds - srv->cur_fds - 16; ++ connection *con; ++ ++ for (; free_fds > 0 && NULL != (con = fdwaitqueue_unshift(srv, srv->fdwaitqueue)); free_fds--) { ++ connection_state_machine(srv, con); ++ ++ srv->want_fds--; ++ } ++ } ++ ++ if ((n = fdevent_poll(srv->ev, 1000)) > 0) { ++ /* n is the number of events */ ++ size_t i; ++ fdevent_get_revents(srv->ev, n, revents); ++ ++ /* handle client connections first ++ * ++ * this is a bit of a hack, but we have to make sure than we handle ++ * close-events before the connection is reused for a keep-alive ++ * request ++ * ++ * this is mostly an issue for mod_proxy_core, but you never know ++ * ++ */ ++ ++ for (i = 0; i < revents->used; i++) { ++ fdevent_revent *revent = revents->ptr[i]; ++ handler_t r; ++ ++ /* skip server-fds */ ++ if (revent->handler == network_server_handle_fdevent) continue; ++ ++ switch (r = (*(revent->handler))(srv, revent->context, revent->revents)) { ++ case HANDLER_FINISHED: ++ case HANDLER_GO_ON: ++ case HANDLER_WAIT_FOR_EVENT: ++ case HANDLER_WAIT_FOR_FD: ++ break; ++ case HANDLER_ERROR: ++ /* should never happen */ ++ SEGFAULT(); ++ break; ++ default: ++ log_error_write(srv, __FILE__, __LINE__, "d", r); ++ break; ++ } ++ } ++ ++ for (i = 0; i < revents->used; i++) { ++ fdevent_revent *revent = revents->ptr[i]; ++ handler_t r; ++ ++ /* server fds only */ ++ if (revent->handler != network_server_handle_fdevent) continue; ++ ++ switch (r = (*(revent->handler))(srv, revent->context, revent->revents)) { ++ case HANDLER_FINISHED: ++ case HANDLER_GO_ON: ++ case HANDLER_WAIT_FOR_EVENT: ++ case HANDLER_WAIT_FOR_FD: ++ break; ++ case HANDLER_ERROR: ++ /* should never happen */ ++ SEGFAULT(); ++ break; ++ default: ++ log_error_write(srv, __FILE__, __LINE__, "d", r); ++ break; ++ } ++ } ++ ++ } else if (n < 0 && errno != EINTR) { ++ log_error_write(srv, __FILE__, __LINE__, "ss", ++ "fdevent_poll failed:", ++ strerror(errno)); ++ } ++ ++ for (ndx = 0; ndx < srv->joblist->used; ndx++) { ++ connection *con = srv->joblist->ptr[ndx]; ++ handler_t r; ++ ++ connection_state_machine(srv, con); ++ ++ switch(r = plugins_call_handle_joblist(srv, con)) { ++ case HANDLER_FINISHED: ++ case HANDLER_GO_ON: ++ break; ++ default: ++ log_error_write(srv, __FILE__, __LINE__, "d", r); ++ break; ++ } ++ ++ con->in_joblist = 0; ++ } ++ ++ srv->joblist->used = 0; ++ } ++ ++ fdevent_revents_free(revents); ++ ++ return 0; ++} ++ ++ +int main (int argc, char **argv, char **envp) { - server *srv = NULL; - int print_config = 0; - int test_config = 0; -@@ -447,33 +455,37 @@ - int num_childs = 0; - int pid_fd = -1, fd; - size_t i; ++ server *srv = NULL; ++ int print_config = 0; ++ int test_config = 0; ++ int i_am_root; ++ int o; ++ int num_childs = 0; ++ int pid_fd = -1, fd; ++ size_t i; +#ifdef _WIN32 + char *optarg = NULL; +#endif + - #ifdef HAVE_SIGACTION - struct sigaction act; - #endif - #ifdef HAVE_GETRLIMIT - struct rlimit rlim; - #endif -- ++#ifdef HAVE_SIGACTION ++ struct sigaction act; ++#endif ++#ifdef HAVE_GETRLIMIT ++ struct rlimit rlim; ++#endif + - #ifdef USE_ALARM - struct itimerval interval; -- ++#ifdef USE_ALARM ++ struct itimerval interval; + - interval.it_interval.tv_sec = 1; - interval.it_interval.tv_usec = 0; - interval.it_value.tv_sec = 1; - interval.it_value.tv_usec = 0; - #endif -- -- ++ interval.it_interval.tv_sec = 1; ++ interval.it_interval.tv_usec = 0; ++ interval.it_value.tv_sec = 1; ++ interval.it_value.tv_usec = 0; ++#endif + ++ log_init(); + - /* for nice %b handling in strfime() */ - setlocale(LC_TIME, "C"); -- ++ /* for nice %b handling in strfime() */ ++ setlocale(LC_TIME, "C"); + - if (NULL == (srv = server_init())) { - fprintf(stderr, "did this really happen?\n"); - return -1; - } -- ++ if (NULL == (srv = server_init())) { ++ fprintf(stderr, "did this really happen?\n"); ++ return -1; ++ } + - /* init structs done */ -- ++ /* init structs done */ + - srv->srvconf.port = 0; - #ifdef HAVE_GETUID - i_am_root = (getuid() == 0); -@@ -481,14 +493,19 @@ - i_am_root = 0; - #endif - srv->srvconf.dont_daemonize = 0; -- ++ srv->srvconf.port = 0; ++#ifdef HAVE_GETUID ++ i_am_root = (getuid() == 0); ++#else ++ i_am_root = 0; ++#endif ++ srv->srvconf.dont_daemonize = 0; + - while(-1 != (o = getopt(argc, argv, "f:m:hvVDpt"))) { - switch(o) { -- case 'f': -- if (config_read(srv, optarg)) { ++ while(-1 != (o = getopt(argc, argv, "f:m:hvVDpt"))) { ++ switch(o) { + case 'f': +#ifdef _WIN32 + /* evil HACK for windows, optarg is not set */ + optarg = argv[optind-1]; +#endif + if (config_read(srv, optarg)) { - server_free(srv); - return -1; - } ++ server_free(srv); ++ return -1; ++ } + - break; - case 'm': - buffer_copy_string(srv->srvconf.modules_dir, optarg); -@@ -497,23 +514,23 @@ - case 't': test_config = 1; break; - case 'D': srv->srvconf.dont_daemonize = 1; break; - case 'v': show_version(); return 0; -- case 'V': show_features(); return 0; ++ break; ++ case 'm': ++ buffer_copy_string(srv->srvconf.modules_dir, optarg); ++ break; ++ case 'p': print_config = 1; break; ++ case 't': test_config = 1; break; ++ case 'D': srv->srvconf.dont_daemonize = 1; break; ++ case 'v': show_version(); return 0; + case 'V': show_features(); return 0; - case 'h': show_help(); return 0; -- default: ++ case 'h': show_help(); return 0; + default: - show_help(); - server_free(srv); - return -1; - } - } -- ++ show_help(); ++ server_free(srv); ++ return -1; ++ } ++ } + - if (!srv->config_storage) { - log_error_write(srv, __FILE__, __LINE__, "s", - "No configuration available. Try using -f option."); -- ++ if (!srv->config_storage) { ++ log_error_write(srv, __FILE__, __LINE__, "s", ++ "No configuration available. Try using -f option."); + - server_free(srv); - return -1; - } -- ++ server_free(srv); ++ return -1; ++ } + - if (print_config) { - data_unset *dc = srv->config_context->data[0]; - if (dc) { -@@ -533,7 +550,7 @@ - server_free(srv); - return 0; - } -- ++ if (print_config) { ++ data_unset *dc = srv->config_context->data[0]; ++ if (dc) { ++ dc->print(dc, 0); ++ fprintf(stderr, "\n"); ++ } else { ++ /* shouldn't happend */ ++ fprintf(stderr, "global config not found\n"); ++ } ++ } + - /* close stdin and stdout, as they are not needed */ - /* move stdin to /dev/null */ - if (-1 != (fd = open("/dev/null", O_RDONLY))) { -@@ -541,54 +558,55 @@ - dup2(fd, STDIN_FILENO); - close(fd); - } -- ++ if (test_config) { ++ printf("Syntax OK\n"); ++ } + - /* move stdout to /dev/null */ - if (-1 != (fd = open("/dev/null", O_WRONLY))) { - close(STDOUT_FILENO); - dup2(fd, STDOUT_FILENO); - close(fd); - } -- ++ if (test_config || print_config) { ++ server_free(srv); ++ return 0; ++ } + - if (0 != config_set_defaults(srv)) { -- log_error_write(srv, __FILE__, __LINE__, "s", ++ /* close stdin and stdout, as they are not needed */ ++ /* move stdin to /dev/null */ ++ if (-1 != (fd = open("/dev/null", O_RDONLY))) { ++ close(STDIN_FILENO); ++ dup2(fd, STDIN_FILENO); ++ close(fd); ++ } ++ ++ /* move stdout to /dev/null */ ++ if (-1 != (fd = open("/dev/null", O_WRONLY))) { ++ close(STDOUT_FILENO); ++ dup2(fd, STDOUT_FILENO); ++ close(fd); ++ } ++ ++ if (0 != config_set_defaults(srv)) { + log_error_write(srv, __FILE__, __LINE__, "s", - "setting default values failed"); - server_free(srv); - return -1; - } -- ++ "setting default values failed"); ++ server_free(srv); ++ return -1; ++ } + - /* UID handling */ - #ifdef HAVE_GETUID - if (!i_am_root && (geteuid() == 0 || getegid() == 0)) { - /* we are setuid-root */ -- -- log_error_write(srv, __FILE__, __LINE__, "s", ++ /* UID handling */ ++#ifdef HAVE_GETUID ++ if (!i_am_root && (geteuid() == 0 || getegid() == 0)) { ++ /* we are setuid-root */ + + log_error_write(srv, __FILE__, __LINE__, "s", - "Are you nuts ? Don't apply a SUID bit to this binary"); -- ++ "Are you nuts ? Don't apply a SUID bit to this binary"); + - server_free(srv); - return -1; - } - #endif -- ++ server_free(srv); ++ return -1; ++ } ++#endif + - /* check document-root */ - if (srv->config_storage[0]->document_root->used <= 1) { -- log_error_write(srv, __FILE__, __LINE__, "s", ++ /* check document-root */ ++ if (srv->config_storage[0]->document_root->used <= 1) { + log_error_write(srv, __FILE__, __LINE__, "s", - "document-root is not set\n"); -- ++ "document-root is not set\n"); + - server_free(srv); -- ++ server_free(srv); + - return -1; - } -- ++ return -1; ++ } + - if (plugins_load(srv)) { - log_error_write(srv, __FILE__, __LINE__, "s", - "loading plugins finally failed"); -- ++ if (plugins_load(srv)) { ++ log_error_write(srv, __FILE__, __LINE__, "s", ++ "loading plugins finally failed"); + - plugins_free(srv); - server_free(srv); -- ++ plugins_free(srv); ++ server_free(srv); + - return -1; - } -- ++ return -1; ++ } + +#ifndef _WIN32 - /* open pid file BEFORE chroot */ - if (srv->srvconf.pid_file->used) { - if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) { -@@ -598,18 +616,18 @@ - "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno)); - return -1; - } -- ++ /* open pid file BEFORE chroot */ ++ if (srv->srvconf.pid_file->used) { ++ if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) { ++ struct stat st; ++ if (errno != EEXIST) { ++ log_error_write(srv, __FILE__, __LINE__, "sbs", ++ "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno)); ++ return -1; ++ } + - if (0 != stat(srv->srvconf.pid_file->ptr, &st)) { - log_error_write(srv, __FILE__, __LINE__, "sbs", - "stating existing pid-file failed:", srv->srvconf.pid_file, strerror(errno)); - } -- ++ if (0 != stat(srv->srvconf.pid_file->ptr, &st)) { ++ log_error_write(srv, __FILE__, __LINE__, "sbs", ++ "stating existing pid-file failed:", srv->srvconf.pid_file, strerror(errno)); ++ } + - if (!S_ISREG(st.st_mode)) { - log_error_write(srv, __FILE__, __LINE__, "sb", - "pid-file exists and isn't regular file:", srv->srvconf.pid_file); - return -1; - } -- ++ if (!S_ISREG(st.st_mode)) { ++ log_error_write(srv, __FILE__, __LINE__, "sb", ++ "pid-file exists and isn't regular file:", srv->srvconf.pid_file); ++ return -1; ++ } + - if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) { - log_error_write(srv, __FILE__, __LINE__, "sbs", - "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno)); -@@ -617,13 +635,14 @@ - } - } - } -- ++ if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) { ++ log_error_write(srv, __FILE__, __LINE__, "sbs", ++ "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno)); ++ return -1; ++ } ++ } ++ } +#endif - if (srv->event_handler == FDEVENT_HANDLER_SELECT) { - /* select limits itself - * - * as it is a hard limit and will lead to a segfault we add some safety - * */ -- srv->max_fds = FD_SETSIZE - 200; ++ if (srv->event_handler == FDEVENT_HANDLER_SELECT) { ++ /* select limits itself ++ * ++ * as it is a hard limit and will lead to a segfault we add some safety ++ * */ + fprintf(stderr, "%s.%d: max parallel connections: %d\r\n", __FILE__, __LINE__, FD_SETSIZE); + srv->max_fds = FD_SETSIZE - 4; - } else { - srv->max_fds = 4096; - } -@@ -636,7 +655,7 @@ - #ifdef HAVE_VALGRIND_VALGRIND_H - if (RUNNING_ON_VALGRIND) use_rlimit = 0; - #endif -- ++ } else { ++ srv->max_fds = 4096; ++ } + - #ifdef HAVE_GETRLIMIT - if (0 != getrlimit(RLIMIT_NOFILE, &rlim)) { - log_error_write(srv, __FILE__, __LINE__, -@@ -644,13 +663,13 @@ - strerror(errno)); - return -1; - } -- ++ if (i_am_root) { ++ struct group *grp = NULL; ++ struct passwd *pwd = NULL; ++ int use_rlimit = 1; + - if (use_rlimit && srv->srvconf.max_fds) { - /* set rlimits */ -- ++#ifdef HAVE_VALGRIND_VALGRIND_H ++ if (RUNNING_ON_VALGRIND) use_rlimit = 0; ++#endif + - rlim.rlim_cur = srv->srvconf.max_fds; - rlim.rlim_max = srv->srvconf.max_fds; -- ++#ifdef HAVE_GETRLIMIT ++ if (0 != getrlimit(RLIMIT_NOFILE, &rlim)) { ++ log_error_write(srv, __FILE__, __LINE__, ++ "ss", "couldn't get 'max filedescriptors'", ++ strerror(errno)); ++ return -1; ++ } ++ ++ if (use_rlimit && srv->srvconf.max_fds) { ++ /* set rlimits */ ++ ++ rlim.rlim_cur = srv->srvconf.max_fds; ++ rlim.rlim_max = srv->srvconf.max_fds; ++ ++ if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) { ++ log_error_write(srv, __FILE__, __LINE__, ++ "ss", "couldn't set 'max filedescriptors'", ++ strerror(errno)); ++ return -1; ++ } ++ } + - if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) { - log_error_write(srv, __FILE__, __LINE__, - "ss", "couldn't set 'max filedescriptors'", -@@ -659,7 +678,7 @@ - } - } - -- /* #372: solaris need some fds extra for devpoll */ + /* #372: solaris need some fds extra for devpoll */ - if (rlim.rlim_cur > 10) rlim.rlim_cur -= 10; - - if (srv->event_handler == FDEVENT_HANDLER_SELECT) { -@@ -677,33 +696,33 @@ ++ if (rlim.rlim_cur > 10) rlim.rlim_cur -= 10; ++ ++ if (srv->event_handler == FDEVENT_HANDLER_SELECT) { ++ srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 200 ? rlim.rlim_cur : FD_SETSIZE - 200; ++ } else { ++ srv->max_fds = rlim.rlim_cur; ++ } ++ ++ /* set core file rlimit, if enable_cores is set */ ++ if (use_rlimit && srv->srvconf.enable_cores && getrlimit(RLIMIT_CORE, &rlim) == 0) { ++ rlim.rlim_cur = rlim.rlim_max; + setrlimit(RLIMIT_CORE, &rlim); + } + #endif if (srv->event_handler == FDEVENT_HANDLER_SELECT) { /* don't raise the limit above FD_SET_SIZE */ if (srv->max_fds > FD_SETSIZE - 200) { @@ -45751,7 +50014,7 @@ "can't find groupname", srv->srvconf.groupname); return -1; } -@@ -713,15 +732,15 @@ +@@ -713,15 +1083,15 @@ return -1; } } @@ -45770,7 +50033,7 @@ if (srv->srvconf.changeroot->used) { tzset(); -@@ -761,7 +780,7 @@ +@@ -761,7 +1131,7 @@ } if (srv->event_handler == FDEVENT_HANDLER_SELECT) { @@ -45779,7 +50042,7 @@ } else { srv->max_fds = rlim.rlim_cur; } -@@ -775,18 +794,18 @@ +@@ -775,18 +1145,18 @@ #endif if (srv->event_handler == FDEVENT_HANDLER_SELECT) { /* don't raise the limit above FD_SET_SIZE */ @@ -45803,7 +50066,7 @@ return -1; } } -@@ -802,25 +821,27 @@ +@@ -802,25 +1172,27 @@ /* or use the default */ srv->max_conns = srv->max_fds; } @@ -45836,7 +50099,7 @@ /* write pid file */ if (pid_fd != -1) { buffer_copy_long(srv->tmp_buf, getpid()); -@@ -829,17 +850,17 @@ +@@ -829,17 +1201,17 @@ close(pid_fd); pid_fd = -1; } @@ -45858,7 +50121,7 @@ /* dump unused config-keys */ for (i = 0; i < srv->config_context->used; i++) { array *config = ((data_config *)srv->config_context->data[i])->value; -@@ -847,43 +868,42 @@ +@@ -847,43 +1219,42 @@ for (j = 0; config && j < config->used; j++) { data_unset *du = config->data[j]; @@ -45894,9 +50157,10 @@ return -1; } - -+ - if (-1 == log_error_open(srv)) { +- if (-1 == log_error_open(srv)) { - log_error_write(srv, __FILE__, __LINE__, "s", ++ ++ if (-1 == log_error_open(srv->srvconf.errorlog_file, srv->srvconf.errorlog_use_syslog)) { + log_error_write(srv, __FILE__, __LINE__, "s", "opening errorlog failed, dying"); - @@ -45912,7 +50176,7 @@ #ifdef HAVE_SIGACTION memset(&act, 0, sizeof(act)); act.sa_handler = SIG_IGN; -@@ -903,7 +923,7 @@ +@@ -903,7 +1274,7 @@ sigaction(SIGHUP, &act, NULL); sigaction(SIGALRM, &act, NULL); sigaction(SIGCHLD, &act, NULL); @@ -45921,7 +50185,7 @@ #elif defined(HAVE_SIGNAL) /* ignore the SIGPIPE from sendfile() */ signal(SIGPIPE, SIG_IGN); -@@ -914,20 +934,20 @@ +@@ -914,20 +1285,20 @@ signal(SIGCHLD, signal_handler); signal(SIGINT, signal_handler); #endif @@ -45946,7 +50210,7 @@ /* start watcher and workers */ num_childs = srv->srvconf.max_worker; if (num_childs > 0) { -@@ -957,13 +977,13 @@ +@@ -957,13 +1328,13 @@ } #endif @@ -45963,7 +50227,7 @@ * all server sockets get their handlers * * */ -@@ -971,7 +991,7 @@ +@@ -971,7 +1342,7 @@ plugins_free(srv); network_close(srv); server_free(srv); @@ -45972,7 +50236,7 @@ return -1; } -@@ -986,7 +1006,7 @@ +@@ -986,17 +1357,17 @@ /* setup FAM */ if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM) { if (0 != FAMOpen2(srv->stat_cache->fam, "lighttpd")) { @@ -45981,341 +50245,331 @@ "could not open a fam connection, dieing."); return -1; } -@@ -1018,16 +1038,40 @@ - int n; - size_t ndx; - time_t min_ts; + #ifdef HAVE_FAMNOEXISTS + FAMNoExists(srv->stat_cache->fam); + #endif ++ srv->stat_cache->sock->fd = FAMCONNECTION_GETFD(srv->stat_cache->fam); + +- srv->stat_cache->fam_fcce_ndx = -1; +- fdevent_register(srv->ev, FAMCONNECTION_GETFD(srv->stat_cache->fam), stat_cache_handle_fdevent, NULL); +- fdevent_event_add(srv->ev, &(srv->stat_cache->fam_fcce_ndx), FAMCONNECTION_GETFD(srv->stat_cache->fam), FDEVENT_IN); ++ fdevent_register(srv->ev, srv->stat_cache->sock, stat_cache_handle_fdevent, NULL); ++ fdevent_event_add(srv->ev, srv->stat_cache->sock, FDEVENT_IN); + } + #endif + +@@ -1007,330 +1378,34 @@ + + for (i = 0; i < srv->srv_sockets.used; i++) { + server_socket *srv_socket = srv->srv_sockets.ptr[i]; +- if (-1 == fdevent_fcntl_set(srv->ev, srv_socket->fd)) { ++ if (-1 == fdevent_fcntl_set(srv->ev, srv_socket->sock)) { + log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed:", strerror(errno)); + return -1; + } + } + +- /* main-loop */ +- while (!srv_shutdown) { +- int n; +- size_t ndx; +- time_t min_ts; - -+ - if (handle_sig_hup) { - handler_t r; +- if (handle_sig_hup) { +- handler_t r; - -+ - /* reset notification */ - handle_sig_hup = 0; +- /* reset notification */ +- handle_sig_hup = 0; - - -+ -+#if 0 -+ pid_t pid; -+ -+ /* send the old process into a graceful-shutdown and start a -+ * new process right away -+ * -+ * BUGS: -+ * - if webserver is running on port < 1024 (e.g. 80, 433) -+ * we don't have the permissions to bind to that port anymore -+ * -+ * -+ * */ -+ if (0 == (pid = fork())) { -+ execve(argv[0], argv, envp); -+ -+ exit(-1); -+ } else if (pid == -1) { -+ -+ } else { -+ /* parent */ -+ -+ graceful_shutdown = 1; /* shutdown without killing running connections */ -+ graceful_restart = 1; /* don't delete pid file */ -+ } -+#else - /* cycle logfiles */ +- /* cycle logfiles */ - -+ - switch(r = plugins_call_handle_sighup(srv)) { - case HANDLER_GO_ON: - break; -@@ -1035,30 +1079,31 @@ - log_error_write(srv, __FILE__, __LINE__, "sd", "sighup-handler return with an error", r); - break; - } +- switch(r = plugins_call_handle_sighup(srv)) { +- case HANDLER_GO_ON: +- break; +- default: +- log_error_write(srv, __FILE__, __LINE__, "sd", "sighup-handler return with an error", r); +- break; +- } - -+ - if (-1 == log_error_cycle(srv)) { - log_error_write(srv, __FILE__, __LINE__, "s", "cycling errorlog failed, dying"); +- if (-1 == log_error_cycle(srv)) { +- log_error_write(srv, __FILE__, __LINE__, "s", "cycling errorlog failed, dying"); - -+ - return -1; - } -+#endif - } +- return -1; +- } +- } - -+ - if (handle_sig_alarm) { - /* a new second */ +- if (handle_sig_alarm) { +- /* a new second */ - -+ - #ifdef USE_ALARM - /* reset notification */ - handle_sig_alarm = 0; - #endif +-#ifdef USE_ALARM +- /* reset notification */ +- handle_sig_alarm = 0; +-#endif - -+ - /* get current time */ - min_ts = time(NULL); +- /* get current time */ +- min_ts = time(NULL); - -+ - if (min_ts != srv->cur_ts) { - int cs = 0; - connections *conns = srv->conns; - handler_t r; +- if (min_ts != srv->cur_ts) { +- int cs = 0; +- connections *conns = srv->conns; +- handler_t r; - -+ - switch(r = plugins_call_handle_trigger(srv)) { - case HANDLER_GO_ON: - break; -@@ -1069,21 +1114,21 @@ - log_error_write(srv, __FILE__, __LINE__, "d", r); - break; - } +- switch(r = plugins_call_handle_trigger(srv)) { +- case HANDLER_GO_ON: +- break; +- case HANDLER_ERROR: +- log_error_write(srv, __FILE__, __LINE__, "s", "one of the triggers failed"); +- break; +- default: +- log_error_write(srv, __FILE__, __LINE__, "d", r); +- break; +- } - -+ - /* trigger waitpid */ - srv->cur_ts = min_ts; +- /* trigger waitpid */ +- srv->cur_ts = min_ts; - - /* cleanup stat-cache */ -+ -+ /* cleanup stat-cache */ - stat_cache_trigger_cleanup(srv); - /** +- stat_cache_trigger_cleanup(srv); +- /** - * check all connections for timeouts - * -+ * check all connections for timeouts -+ * - */ - for (ndx = 0; ndx < conns->used; ndx++) { - int changed = 0; - connection *con; - int t_diff; +- */ +- for (ndx = 0; ndx < conns->used; ndx++) { +- int changed = 0; +- connection *con; +- int t_diff; - -+ - con = conns->ptr[ndx]; - - if (con->state == CON_STATE_READ || -@@ -1092,7 +1137,7 @@ - if (srv->cur_ts - con->read_idle_ts > con->conf.max_read_idle) { - /* time - out */ - #if 0 +- con = conns->ptr[ndx]; +- +- if (con->state == CON_STATE_READ || +- con->state == CON_STATE_READ_POST) { +- if (con->request_count == 1) { +- if (srv->cur_ts - con->read_idle_ts > con->conf.max_read_idle) { +- /* time - out */ +-#if 0 - log_error_write(srv, __FILE__, __LINE__, "sd", -+ log_error_write(srv, __FILE__, __LINE__, "sd", - "connection closed - read-timeout:", con->fd); - #endif - connection_set_state(srv, con, CON_STATE_ERROR); -@@ -1102,7 +1147,7 @@ - if (srv->cur_ts - con->read_idle_ts > con->conf.max_keep_alive_idle) { - /* time - out */ - #if 0 +- "connection closed - read-timeout:", con->fd); +-#endif +- connection_set_state(srv, con, CON_STATE_ERROR); +- changed = 1; +- } +- } else { +- if (srv->cur_ts - con->read_idle_ts > con->conf.max_keep_alive_idle) { +- /* time - out */ +-#if 0 - log_error_write(srv, __FILE__, __LINE__, "sd", -+ log_error_write(srv, __FILE__, __LINE__, "sd", - "connection closed - read-timeout:", con->fd); - #endif - connection_set_state(srv, con, CON_STATE_ERROR); -@@ -1110,20 +1155,20 @@ - } - } - } +- "connection closed - read-timeout:", con->fd); +-#endif +- connection_set_state(srv, con, CON_STATE_ERROR); +- changed = 1; +- } +- } +- } - -+ - if ((con->state == CON_STATE_WRITE) && +- if ((con->state == CON_STATE_WRITE) && - (con->write_request_ts != 0)) { -+ (con->write_request_ts != 0)) { - #if 0 - if (srv->cur_ts - con->write_request_ts > 60) { +-#if 0 +- if (srv->cur_ts - con->write_request_ts > 60) { - log_error_write(srv, __FILE__, __LINE__, "sdd", -+ log_error_write(srv, __FILE__, __LINE__, "sdd", - "connection closed - pre-write-request-timeout:", con->fd, srv->cur_ts - con->write_request_ts); - } - #endif +- "connection closed - pre-write-request-timeout:", con->fd, srv->cur_ts - con->write_request_ts); +- } +-#endif - -+ - if (srv->cur_ts - con->write_request_ts > con->conf.max_write_idle) { - /* time - out */ - #if 1 +- if (srv->cur_ts - con->write_request_ts > con->conf.max_write_idle) { +- /* time - out */ +-#if 1 - log_error_write(srv, __FILE__, __LINE__, "sbsosds", -+ log_error_write(srv, __FILE__, __LINE__, "sbsosds", - "NOTE: a request for", - con->request.uri, - "timed out after writing", -@@ -1138,35 +1183,35 @@ - } - /* we don't like div by zero */ - if (0 == (t_diff = srv->cur_ts - con->connection_start)) t_diff = 1; +- "NOTE: a request for", +- con->request.uri, +- "timed out after writing", +- con->bytes_written, +- "bytes. We waited", +- (int)con->conf.max_write_idle, +- "seconds. If this a problem increase server.max-write-idle"); +-#endif +- connection_set_state(srv, con, CON_STATE_ERROR); +- changed = 1; +- } +- } +- /* we don't like div by zero */ +- if (0 == (t_diff = srv->cur_ts - con->connection_start)) t_diff = 1; - - if (con->traffic_limit_reached && - (con->conf.kbytes_per_second == 0 || -+ -+ if (con->traffic_limit_reached && -+ (con->conf.kbytes_per_second == 0 || - ((con->bytes_written / t_diff) < con->conf.kbytes_per_second * 1024))) { - /* enable connection again */ - con->traffic_limit_reached = 0; +- ((con->bytes_written / t_diff) < con->conf.kbytes_per_second * 1024))) { +- /* enable connection again */ +- con->traffic_limit_reached = 0; - -+ - changed = 1; - } +- changed = 1; +- } - -+ - if (changed) { - connection_state_machine(srv, con); - } - con->bytes_written_cur_second = 0; - *(con->conf.global_bytes_per_second_cnt_ptr) = 0; +- if (changed) { +- connection_state_machine(srv, con); +- } +- con->bytes_written_cur_second = 0; +- *(con->conf.global_bytes_per_second_cnt_ptr) = 0; - -+ - #if 0 - if (cs == 0) { - fprintf(stderr, "connection-state: "); - cs = 1; - } +-#if 0 +- if (cs == 0) { +- fprintf(stderr, "connection-state: "); +- cs = 1; +- } - -+ - fprintf(stderr, "c[%d,%d]: %s ", - con->fd, - con->fcgi.fd, - connection_get_state(con->state)); - #endif - } +- fprintf(stderr, "c[%d,%d]: %s ", +- con->fd, +- con->fcgi.fd, +- connection_get_state(con->state)); +-#endif +- } - -+ - if (cs == 1) fprintf(stderr, "\n"); - } - } -@@ -1181,18 +1226,18 @@ - server_socket *srv_socket = srv->srv_sockets.ptr[i]; - fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN); - } +- if (cs == 1) fprintf(stderr, "\n"); +- } +- } +- +- if (srv->sockets_disabled) { +- /* our server sockets are disabled, why ? */ +- +- if ((srv->cur_fds + srv->want_fds < srv->max_fds * 0.8) && /* we have enough unused fds */ +- (srv->conns->used < srv->max_conns * 0.9) && +- (0 == graceful_shutdown)) { +- for (i = 0; i < srv->srv_sockets.used; i++) { +- server_socket *srv_socket = srv->srv_sockets.ptr[i]; +- fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN); +- } - -+ - log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets enabled again"); +- log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets enabled again"); - -+ - srv->sockets_disabled = 0; - } - } else { - if ((srv->cur_fds + srv->want_fds > srv->max_fds * 0.9) || /* out of fds */ - (srv->conns->used > srv->max_conns) || /* out of connections */ +- srv->sockets_disabled = 0; +- } +- } else { +- if ((srv->cur_fds + srv->want_fds > srv->max_fds * 0.9) || /* out of fds */ +- (srv->conns->used > srv->max_conns) || /* out of connections */ - (graceful_shutdown)) { /* graceful_shutdown */ -+ (graceful_shutdown)) { /* graceful_shutdown */ - - /* disable server-fds */ +- +- /* disable server-fds */ - -+ - for (i = 0; i < srv->srv_sockets.used; i++) { - server_socket *srv_socket = srv->srv_sockets.ptr[i]; - fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd); -@@ -1211,7 +1256,7 @@ - /* network_close() will cleanup after us */ - } - } +- for (i = 0; i < srv->srv_sockets.used; i++) { +- server_socket *srv_socket = srv->srv_sockets.ptr[i]; +- fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd); +- +- if (graceful_shutdown) { +- /* we don't want this socket anymore, +- * +- * closing it right away will make it possible for +- * the next lighttpd to take over (graceful restart) +- * */ +- +- fdevent_unregister(srv->ev, srv_socket->fd); +- close(srv_socket->fd); +- srv_socket->fd = -1; +- +- /* network_close() will cleanup after us */ +- } +- } - -+ - if (graceful_shutdown) { - log_error_write(srv, __FILE__, __LINE__, "s", "[note] graceful shutdown started"); - } else if (srv->conns->used > srv->max_conns) { -@@ -1219,7 +1264,7 @@ - } else { - log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, out-of-fds"); - } +- if (graceful_shutdown) { +- log_error_write(srv, __FILE__, __LINE__, "s", "[note] graceful shutdown started"); +- } else if (srv->conns->used > srv->max_conns) { +- log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, connection limit reached"); +- } else { +- log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, out-of-fds"); +- } - -+ - srv->sockets_disabled = 1; - } - } -@@ -1229,16 +1274,16 @@ - * we are ready to terminate without harming anyone */ - srv_shutdown = 1; - } +- srv->sockets_disabled = 1; +- } +- } +- +- if (graceful_shutdown && srv->conns->used == 0) { +- /* we are in graceful shutdown phase and all connections are closed +- * we are ready to terminate without harming anyone */ +- srv_shutdown = 1; +- } - -+ - /* we still have some fds to share */ +- /* we still have some fds to share */ - if (srv->want_fds) { -+ if (srv->want_fds) { - /* check the fdwaitqueue for waiting fds */ - int free_fds = srv->max_fds - srv->cur_fds - 16; - connection *con; +- /* check the fdwaitqueue for waiting fds */ +- int free_fds = srv->max_fds - srv->cur_fds - 16; +- connection *con; - -+ - for (; free_fds > 0 && NULL != (con = fdwaitqueue_unshift(srv, srv->fdwaitqueue)); free_fds--) { - connection_state_machine(srv, con); +- for (; free_fds > 0 && NULL != (con = fdwaitqueue_unshift(srv, srv->fdwaitqueue)); free_fds--) { +- connection_state_machine(srv, con); - -+ - srv->want_fds--; - } - } -@@ -1249,27 +1294,27 @@ - int fd_ndx; - #if 0 - if (n > 0) { +- srv->want_fds--; +- } +- } ++ lighty_mainloop(srv); + +- if ((n = fdevent_poll(srv->ev, 1000)) > 0) { +- /* n is the number of events */ +- int revents; +- int fd_ndx; +-#if 0 +- if (n > 0) { - log_error_write(srv, __FILE__, __LINE__, "sd", -+ log_error_write(srv, __FILE__, __LINE__, "sd", - "polls:", n); - } +- "polls:", n); +- } -#endif -+#endif - fd_ndx = -1; - do { - fdevent_handler handler; - void *context; - handler_t r; -- -+ - fd_ndx = fdevent_event_next_fdndx (srv->ev, fd_ndx); - revents = fdevent_event_get_revent (srv->ev, fd_ndx); - fd = fdevent_event_get_fd (srv->ev, fd_ndx); - handler = fdevent_get_handler(srv->ev, fd); - context = fdevent_get_context(srv->ev, fd); -- -+ - /* connection_handle_fdevent needs a joblist_append */ - #if 0 +- fd_ndx = -1; +- do { +- fdevent_handler handler; +- void *context; +- handler_t r; +- +- fd_ndx = fdevent_event_next_fdndx (srv->ev, fd_ndx); +- revents = fdevent_event_get_revent (srv->ev, fd_ndx); +- fd = fdevent_event_get_fd (srv->ev, fd_ndx); +- handler = fdevent_get_handler(srv->ev, fd); +- context = fdevent_get_context(srv->ev, fd); +- +- /* connection_handle_fdevent needs a joblist_append */ +-#if 0 - log_error_write(srv, __FILE__, __LINE__, "sdd", -+ log_error_write(srv, __FILE__, __LINE__, "sdd", - "event for", fd, revents); +- "event for", fd, revents); -#endif -+#endif - switch (r = (*handler)(srv, context, revents)) { - case HANDLER_FINISHED: - case HANDLER_GO_ON: -@@ -1286,17 +1331,17 @@ - } - } while (--n > 0); - } else if (n < 0 && errno != EINTR) { +- switch (r = (*handler)(srv, context, revents)) { +- case HANDLER_FINISHED: +- case HANDLER_GO_ON: +- case HANDLER_WAIT_FOR_EVENT: +- case HANDLER_WAIT_FOR_FD: +- break; +- case HANDLER_ERROR: +- /* should never happen */ +- SEGFAULT(); +- break; +- default: +- log_error_write(srv, __FILE__, __LINE__, "d", r); +- break; +- } +- } while (--n > 0); +- } else if (n < 0 && errno != EINTR) { - log_error_write(srv, __FILE__, __LINE__, "ss", - "fdevent_poll failed:", -+ log_error_write(srv, __FILE__, __LINE__, "ss", -+ "fdevent_poll failed:", - strerror(errno)); - } +- strerror(errno)); +- } - -+ - for (ndx = 0; ndx < srv->joblist->used; ndx++) { - connection *con = srv->joblist->ptr[ndx]; - handler_t r; +- for (ndx = 0; ndx < srv->joblist->used; ndx++) { +- connection *con = srv->joblist->ptr[ndx]; +- handler_t r; - -+ - connection_state_machine(srv, con); +- connection_state_machine(srv, con); - -+ - switch(r = plugins_call_handle_joblist(srv, con)) { - case HANDLER_FINISHED: - case HANDLER_GO_ON: -@@ -1305,32 +1350,33 @@ - log_error_write(srv, __FILE__, __LINE__, "d", r); - break; - } +- switch(r = plugins_call_handle_joblist(srv, con)) { +- case HANDLER_FINISHED: +- case HANDLER_GO_ON: +- break; +- default: +- log_error_write(srv, __FILE__, __LINE__, "d", r); +- break; +- } - -+ - con->in_joblist = 0; - } +- con->in_joblist = 0; +- } - -+ - srv->joblist->used = 0; - } +- srv->joblist->used = 0; +- } - - if (srv->srvconf.pid_file->used && -+ + if (0 == graceful_restart && + srv->srvconf.pid_file->used && srv->srvconf.changeroot->used == 0) { @@ -46334,17 +50588,18 @@ - + /* clean-up */ - log_error_close(srv); +- log_error_close(srv); network_close(srv); connections_free(srv); plugins_free(srv); server_free(srv); - ++ log_free(); + return 0; } --- ../lighttpd-1.4.11/src/settings.h 2005-08-11 01:26:41.000000000 +0300 -+++ lighttpd-1.4.12/src/settings.h 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/settings.h 2006-07-16 00:26:04.000000000 +0300 @@ -9,24 +9,24 @@ /** * max size of a buffer which will just be reset @@ -46378,7 +50633,7 @@ HANDLER_WAIT_FOR_FD } handler_t; --- ../lighttpd-1.4.11/src/spawn-fcgi.c 2006-03-07 14:18:10.000000000 +0200 -+++ lighttpd-1.4.12/src/spawn-fcgi.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/spawn-fcgi.c 2006-07-16 00:26:04.000000000 +0300 @@ -1,19 +1,16 @@ #include -#include @@ -46853,7 +51108,7 @@ } #else --- ../lighttpd-1.4.11/src/splaytree.c 2005-09-12 21:51:28.000000000 +0300 -+++ lighttpd-1.4.12/src/splaytree.c 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/splaytree.c 2006-07-16 00:26:03.000000000 +0300 @@ -56,19 +56,19 @@ #define node_size splaytree_size @@ -46888,7 +51143,7 @@ r->left = t->right; t->left = N.right; --- ../lighttpd-1.4.11/src/splaytree.h 2005-09-12 21:51:13.000000000 +0300 -+++ lighttpd-1.4.12/src/splaytree.h 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/splaytree.h 2006-07-16 00:26:03.000000000 +0300 @@ -19,6 +19,6 @@ /* This macro returns the size of a node. Unlike "x->size", */ /* it works even if x=NULL. The test could be avoided by using */ @@ -46898,7 +51153,7 @@ #endif --- ../lighttpd-1.4.11/src/stat_cache.c 2005-11-22 15:23:51.000000000 +0200 -+++ lighttpd-1.4.12/src/stat_cache.c 2006-07-15 22:43:21.000000000 +0300 ++++ lighttpd-1.4.12/src/stat_cache.c 2006-07-18 13:03:40.000000000 +0300 @@ -6,7 +6,6 @@ #include #include @@ -46982,7 +51237,7 @@ typedef struct { int *ptr; -@@ -105,15 +93,15 @@ +@@ -105,15 +93,16 @@ stat_cache *stat_cache_init(void) { stat_cache *fc = NULL; @@ -46994,6 +51249,7 @@ fc->dir_name = buffer_init(); #ifdef HAVE_FAM_H fc->fam = calloc(1, sizeof(*fc->fam)); ++ fc->sock = iosocket_init(); #endif -#ifdef DEBUG_STAT_CACHE @@ -47001,7 +51257,7 @@ ctrl.size = 0; #endif -@@ -122,24 +110,24 @@ +@@ -122,24 +111,24 @@ static stat_cache_entry * stat_cache_entry_init(void) { stat_cache_entry *sce = NULL; @@ -47031,7 +51287,7 @@ free(sce); } -@@ -148,22 +136,22 @@ +@@ -148,22 +137,22 @@ fam_dir_entry *fam_dir = NULL; fam_dir = calloc(1, sizeof(*fam_dir)); @@ -47060,7 +51316,7 @@ free(fam_dir); } #endif -@@ -174,7 +162,7 @@ +@@ -174,7 +163,7 @@ splay_tree *node = sc->files; osize = sc->files->size; @@ -47069,7 +51325,7 @@ stat_cache_entry_free(node->data); sc->files = splaytree_delete(sc->files, node->key); -@@ -187,12 +175,12 @@ +@@ -187,12 +176,12 @@ while (sc->dirs) { int osize; splay_tree *node = sc->dirs; @@ -47084,7 +51340,15 @@ if (osize == 1) { assert(NULL == sc->dirs); } else { -@@ -212,7 +200,7 @@ +@@ -202,6 +191,7 @@ + + if (sc->fam) { + FAMClose(sc->fam); ++ iosocket_free(sc->sock); + free(sc->fam); + } + #endif +@@ -212,7 +202,7 @@ static int stat_cache_attr_get(buffer *buf, char *name) { int attrlen; int ret; @@ -47093,7 +51357,7 @@ attrlen = 1024; buffer_prepare_copy(buf, attrlen); attrlen--; -@@ -251,15 +239,15 @@ +@@ -251,15 +241,15 @@ sc->fam) { events = FAMPending(sc->fam); @@ -47112,7 +51376,7 @@ /* handle event */ switch(fe.code) { -@@ -280,7 +268,7 @@ +@@ -280,7 +270,7 @@ sc->dirs = splaytree_splay(sc->dirs, ndx); node = sc->dirs; @@ -47121,7 +51385,19 @@ if (node && (node->key == ndx)) { int osize = splaytree_size(sc->dirs); -@@ -308,7 +296,7 @@ +@@ -298,17 +288,15 @@ + + if (revent & FDEVENT_HUP) { + /* fam closed the connection */ +- srv->stat_cache->fam_fcce_ndx = -1; +- +- fdevent_event_del(srv->ev, &(sc->fam_fcce_ndx), FAMCONNECTION_GETFD(sc->fam)); +- fdevent_unregister(srv->ev, FAMCONNECTION_GETFD(sc->fam)); ++ fdevent_event_del(srv->ev, sc->sock); ++ fdevent_unregister(srv->ev, sc->sock); + + FAMClose(sc->fam); + free(sc->fam); sc->fam = NULL; } @@ -47412,7 +51688,7 @@ if (ctrl.ptr[j] == ndx) { ctrl.ptr[j] = ctrl.ptr[--ctrl.used]; --- ../lighttpd-1.4.11/src/stream.c 2005-09-23 21:50:15.000000000 +0300 -+++ lighttpd-1.4.12/src/stream.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/stream.c 2006-07-16 00:26:04.000000000 +0300 @@ -1,7 +1,6 @@ #include #include @@ -47513,7 +51789,7 @@ } --- ../lighttpd-1.4.11/src/sys-files.h 1970-01-01 03:00:00.000000000 +0300 -+++ lighttpd-1.4.12/src/sys-files.h 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/src/sys-files.h 2006-07-16 00:26:04.000000000 +0300 @@ -0,0 +1,67 @@ +#ifndef _SYS_FILES_H_ +#define _SYS_FILES_H_ @@ -47583,7 +51859,7 @@ +#endif + --- ../lighttpd-1.4.11/src/sys-mmap.h 2005-08-11 01:26:34.000000000 +0300 -+++ lighttpd-1.4.12/src/sys-mmap.h 2006-07-11 22:07:52.000000000 +0300 ++++ lighttpd-1.4.12/src/sys-mmap.h 2006-07-16 00:26:04.000000000 +0300 @@ -1,7 +1,7 @@ #ifndef WIN32_MMAP_H #define WIN32_MMAP_H @@ -47594,7 +51870,7 @@ #define MAP_FAILED -1 #define PROT_SHARED 0 --- ../lighttpd-1.4.11/src/sys-process.h 1970-01-01 03:00:00.000000000 +0300 -+++ lighttpd-1.4.12/src/sys-process.h 2006-07-15 22:43:21.000000000 +0300 ++++ lighttpd-1.4.12/src/sys-process.h 2006-07-16 00:26:04.000000000 +0300 @@ -0,0 +1,17 @@ +#ifndef _SYS_PROCESS_H_ +#define _SYS_PROCESS_H_ @@ -47614,7 +51890,7 @@ +#endif + --- ../lighttpd-1.4.11/src/sys-socket.h 2005-08-11 01:26:39.000000000 +0300 -+++ lighttpd-1.4.12/src/sys-socket.h 2006-07-15 22:43:21.000000000 +0300 ++++ lighttpd-1.4.12/src/sys-socket.h 2006-07-18 13:03:40.000000000 +0300 @@ -1,15 +1,26 @@ #ifndef WIN32_SOCKET_H #define WIN32_SOCKET_H @@ -47643,7 +51919,7 @@ #else #include #include -@@ -18,7 +29,23 @@ +@@ -18,7 +29,25 @@ #include #include @@ -47651,10 +51927,12 @@ +#define SUN_LEN(su) \ + (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path)) +#endif ++ ++#define closesocket(x) close(x) + #include - #endif - ++#endif /* !_WIN32 */ ++ +typedef union { +#ifdef HAVE_IPV6 + struct sockaddr_in6 ipv6; @@ -47662,13 +51940,13 @@ + struct sockaddr_in ipv4; +#ifdef HAVE_SYS_UN_H + struct sockaddr_un un; -+#endif + #endif + struct sockaddr plain; +} sock_addr; -+ + #endif --- ../lighttpd-1.4.11/src/sys-strings.h 1970-01-01 03:00:00.000000000 +0300 -+++ lighttpd-1.4.12/src/sys-strings.h 2006-07-11 22:07:51.000000000 +0300 ++++ lighttpd-1.4.12/src/sys-strings.h 2006-07-16 00:26:03.000000000 +0300 @@ -0,0 +1,11 @@ +#ifndef _SYS_STRINGS_H_ +#define _SYS_STRINGS_H_ @@ -47682,8 +51960,8 @@ +#endif + --- ../lighttpd-1.4.11/tests/LightyTest.pm 2006-01-14 20:32:31.000000000 +0200 -+++ lighttpd-1.4.12/tests/LightyTest.pm 2006-07-11 22:07:53.000000000 +0300 -@@ -87,14 +87,14 @@ ++++ lighttpd-1.4.12/tests/LightyTest.pm 2006-07-18 13:03:40.000000000 +0300 +@@ -87,14 +87,16 @@ # pre-process configfile if necessary # @@ -47693,16 +51971,19 @@ + $ENV{'PORT'} = $self->{PORT}; unlink($self->{LIGHTTPD_PIDFILE}); - if (1) { +- if (1) { - system($self->{LIGHTTPD_PATH}." -f ".$self->{TESTDIR}."/tmp/cfg.file -m ".$self->{MODULES_PATH}); -+ system($self->{LIGHTTPD_PATH}." -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH}); ++ if (defined $ENV{"TRACEME"} && $ENV{"TRACEME"} eq 'strace') { ++ system("strace -tt -s 512 -o strace ".$self->{LIGHTTPD_PATH}." -D -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH}." &"); ++ } elsif (defined $ENV{"TRACEME"} && $ENV{"TRACEME"} eq 'valgrind') { ++ system("valgrind --tool=memcheck --show-reachable=yes --leak-check=yes --logfile=valgrind ".$self->{LIGHTTPD_PATH}." -D -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH}." &"); } else { - system("valgrind --tool=memcheck --show-reachable=yes --leak-check=yes --logfile=foo ".$self->{LIGHTTPD_PATH}." -D -f ".$self->{TESTDIR}."/tmp/cfg.file -m ".$self->{MODULES_PATH}." &"); -+ system("valgrind --tool=memcheck --show-reachable=yes --leak-check=yes --logfile=foo ".$self->{LIGHTTPD_PATH}." -D -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH}." &"); ++ system($self->{LIGHTTPD_PATH}." -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH}); } select(undef, undef, undef, 0.1); -@@ -184,7 +184,7 @@ +@@ -184,7 +186,7 @@ (my $h = $1) =~ tr/[A-Z]/[a-z]/; if (defined $resp_hdr{$h}) { @@ -47711,7 +51992,7 @@ $h, $resp_hdr{$h}, $2)); } else { $resp_hdr{$h} = $2; -@@ -196,6 +196,9 @@ +@@ -196,6 +198,9 @@ } } @@ -47722,7 +52003,7 @@ if (defined $resp_hdr{"content-length"}) { $resp_body = substr($lines, 0, $resp_hdr{"content-length"}); --- ../lighttpd-1.4.11/tests/Makefile.am 2005-09-16 15:48:40.000000000 +0300 -+++ lighttpd-1.4.12/tests/Makefile.am 2006-07-15 22:43:22.000000000 +0300 ++++ lighttpd-1.4.12/tests/Makefile.am 2006-07-16 00:26:05.000000000 +0300 @@ -39,10 +39,18 @@ mod-redirect.t \ mod-userdir.t \ @@ -47744,7 +52025,7 @@ TESTS_ENVIRONMENT=$(srcdir)/wrapper.sh $(srcdir) $(top_builddir) --- ../lighttpd-1.4.11/tests/bug-06.conf 2005-08-27 17:44:19.000000000 +0300 -+++ lighttpd-1.4.12/tests/bug-06.conf 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/tests/bug-06.conf 2006-07-16 00:26:04.000000000 +0300 @@ -1,5 +1,5 @@ -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/" -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid" @@ -47818,7 +52099,7 @@ } --- ../lighttpd-1.4.11/tests/bug-12.conf 2005-08-27 17:44:19.000000000 +0300 -+++ lighttpd-1.4.12/tests/bug-12.conf 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/tests/bug-12.conf 2006-07-16 00:26:04.000000000 +0300 @@ -1,5 +1,5 @@ -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/" -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid" @@ -47892,7 +52173,7 @@ } --- ../lighttpd-1.4.11/tests/cachable.t 1970-01-01 03:00:00.000000000 +0300 -+++ lighttpd-1.4.12/tests/cachable.t 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/tests/cachable.t 2006-07-18 13:03:40.000000000 +0300 @@ -0,0 +1,112 @@ +#!/usr/bin/env perl +BEGIN { @@ -47929,7 +52210,7 @@ +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo +EOF + ); -+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ]; ++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+Last-Modified' => ''} ]; +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-Modified-Since, comment'); + +my $now = $t->{date}; @@ -47955,7 +52236,7 @@ +If-None-Match: foo +EOF + ); -+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ]; ++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+ETag' => ''} ]; +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-None-Match'); + +my $etag = $t->{etag}; @@ -48007,7 +52288,7 @@ +ok($tf->stop_proc == 0, "Stopping lighttpd"); + --- ../lighttpd-1.4.11/tests/condition.conf 2005-08-27 17:44:19.000000000 +0300 -+++ lighttpd-1.4.12/tests/condition.conf 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/tests/condition.conf 2006-07-16 00:26:05.000000000 +0300 @@ -2,15 +2,15 @@ debug.log-request-handling = "enable" debug.log-condition-handling = "enable" @@ -48067,7 +52348,7 @@ url.redirect = ("^" => "/match_4") --- ../lighttpd-1.4.11/tests/core-keepalive.t 2005-11-17 15:54:19.000000000 +0200 -+++ lighttpd-1.4.12/tests/core-keepalive.t 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/tests/core-keepalive.t 2006-07-16 00:26:05.000000000 +0300 @@ -40,7 +40,7 @@ GET /12345.txt HTTP/1.0 @@ -48077,18 +52358,132 @@ EOF ); $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } , { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ]; +--- ../lighttpd-1.4.11/tests/default.conf 1970-01-01 03:00:00.000000000 +0300 ++++ lighttpd-1.4.12/tests/default.conf 2006-07-16 00:26:05.000000000 +0300 +@@ -0,0 +1,111 @@ ++server.name = "www.example.org" ++ ++## bind to port (default: 80) ++server.port = env.PORT ++ ++ ++server.dir-listing = "enable" ++ ++#server.event-handler = "linux-sysepoll" ++#server.event-handler = "linux-rtsig" ++ ++server.modules = ( ++ "mod_rewrite", ++ "mod_setenv", ++ "mod_access", ++ "mod_auth", ++ "mod_status", ++ "mod_expire", ++ "mod_simple_vhost", ++ "mod_redirect", ++ "mod_secdownload", ++ "mod_ssi", ++ "mod_fastcgi", ++ "mod_proxy", ++ "mod_cgi", ++ "mod_compress", ++ "mod_userdir", ++ "mod_accesslog" ) ++ ++server.indexfiles = ( "index.php", "index.html", ++ "index.htm", "default.htm" ) ++ ++ssi.extension = ( ".shtml" ) ++ ++######################## MODULE CONFIG ############################ ++ ++ ++accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log" ++server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log" ++ ++mimetype.assign = ( ".png" => "image/png", ++ ".jpg" => "image/jpeg", ++ ".jpeg" => "image/jpeg", ++ ".gif" => "image/gif", ++ ".html" => "text/html", ++ ".htm" => "text/html", ++ ".pdf" => "application/pdf", ++ ".swf" => "application/x-shockwave-flash", ++ ".spl" => "application/futuresplash", ++ ".txt" => "text/plain", ++ ".tar.gz" => "application/x-tgz", ++ ".tgz" => "application/x-tgz", ++ ".gz" => "application/x-gzip", ++ ".c" => "text/plain", ++ ".conf" => "text/plain" ) ++ ++compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/" ++compress.filetype = ("text/plain", "text/html") ++ ++setenv.add-environment = ( "TRAC_ENV" => "tracenv", "SETENV" => "setenv") ++ ++cgi.assign = ( ".pl" => "/usr/bin/perl", ++ ".cgi" => "/usr/bin/perl", ++ ".py" => "/usr/bin/python" ) ++ ++userdir.include-user = ( "jan" ) ++userdir.path = "/" ++ ++ssl.engine = "disable" ++ssl.pemfile = "server.pem" ++ ++auth.backend = "plain" ++auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user" ++auth.backend.htpasswd.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.htpasswd" ++auth.backend.plain.groupfile = "lighttpd.group" ++ ++auth.backend.ldap.hostname = "localhost" ++auth.backend.ldap.base-dn = "dc=my-domain,dc=com" ++auth.backend.ldap.filter = "(uid=$)" ++ ++auth.require = ( "/server-status" => ++ ( ++ "method" => "digest", ++ "realm" => "download archiv", ++ "require" => "valid-user" ++ ), ++ "/auth.php" => ++ ( ++ "method" => "basic", ++ "realm" => "download archiv", ++ "require" => "user=jan" ++ ), ++ "/server-config" => ++ ( ++ "method" => "basic", ++ "realm" => "download archiv", ++ "require" => "valid-user" ++ ) ++ ) ++ ++url.access-deny = ( "~", ".inc") ++ ++url.redirect = ( "^/redirect/$" => "http://localhost:2048/" ) ++ ++url.rewrite = ( "^/rewrite/foo($|\?.+)" => "/indexfile/rewrite.php$1", ++ "^/rewrite/bar(?:$|\?(.+))" => "/indexfile/rewrite.php?bar&$1" ) ++ ++#### status module ++status.status-url = "/server-status" ++status.config-url = "/server-config" ++ --- ../lighttpd-1.4.11/tests/docroot/www/dummydir/.svn/entries 2006-03-09 19:21:49.000000000 +0200 -+++ lighttpd-1.4.12/tests/docroot/www/dummydir/.svn/entries 2006-07-15 22:43:22.000000000 +0300 ++++ lighttpd-1.4.12/tests/docroot/www/dummydir/.svn/entries 2006-07-18 13:03:40.000000000 +0300 @@ -9,5 +9,6 @@ last-author="jan" kind="dir" uuid="152afb58-edef-0310-8abb-c4023f1b3aa9" - revision="1040"/> + repos="svn://svn.lighttpd.net/lighttpd" -+ revision="1173"/> ++ revision="1199"/> --- ../lighttpd-1.4.11/tests/fastcgi-10.conf 2005-08-31 23:36:34.000000000 +0300 -+++ lighttpd-1.4.12/tests/fastcgi-10.conf 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/tests/fastcgi-10.conf 2006-07-16 00:26:04.000000000 +0300 @@ -1,12 +1,12 @@ -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/" -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid" @@ -48147,7 +52542,7 @@ } --- ../lighttpd-1.4.11/tests/fastcgi-13.conf 2006-01-03 12:38:17.000000000 +0200 -+++ lighttpd-1.4.12/tests/fastcgi-13.conf 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/tests/fastcgi-13.conf 2006-07-18 13:03:40.000000000 +0300 @@ -1,5 +1,5 @@ -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/" -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid" @@ -48183,6 +52578,15 @@ compress.filetype = ("text/plain", "text/html") fastcgi.debug = 0 +@@ -85,7 +85,7 @@ + "grisu" => ( + "host" => "127.0.0.1", + "port" => 1048, +- "bin-path" => "/home/jan/Documents/php-5.1.0/sapi/cgi/php -c /usr/local/lib/php.ini", ++ "bin-path" => "/home/jan/Documents/php-5.1.4/sapi/cgi/php -c /usr/local/lib/php.ini", + "bin-copy-environment" => ( "PATH", "SHELL", "USER" ), + ) + ) @@ -102,7 +102,7 @@ ssl.pemfile = "server.pem" @@ -48207,7 +52611,7 @@ } --- ../lighttpd-1.4.11/tests/fastcgi-auth.conf 2005-08-27 17:44:19.000000000 +0300 -+++ lighttpd-1.4.12/tests/fastcgi-auth.conf 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/tests/fastcgi-auth.conf 2006-07-16 00:26:05.000000000 +0300 @@ -1,5 +1,5 @@ -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/" -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid" @@ -48279,7 +52683,7 @@ } --- ../lighttpd-1.4.11/tests/fastcgi-responder.conf 2005-08-27 17:44:19.000000000 +0300 -+++ lighttpd-1.4.12/tests/fastcgi-responder.conf 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/tests/fastcgi-responder.conf 2006-07-16 00:26:05.000000000 +0300 @@ -1,5 +1,5 @@ -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/" -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid" @@ -48353,7 +52757,7 @@ } --- ../lighttpd-1.4.11/tests/fcgi-responder.c 2005-08-11 01:26:55.000000000 +0300 -+++ lighttpd-1.4.12/tests/fcgi-responder.c 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/tests/fcgi-responder.c 2006-07-16 00:26:05.000000000 +0300 @@ -6,11 +6,17 @@ int main () { int num_requests = 2; @@ -48397,7 +52801,7 @@ printf("Status: 200 OK\r\n\r\n"); num_requests--; --- ../lighttpd-1.4.11/tests/lighttpd.conf 2006-03-09 15:26:58.000000000 +0200 -+++ lighttpd-1.4.12/tests/lighttpd.conf 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/tests/lighttpd.conf 2006-07-16 00:26:05.000000000 +0300 @@ -1,80 +1,18 @@ -debug.log-request-handling = "enable" -debug.log-condition-handling = "enable" @@ -48569,7 +52973,7 @@ } --- ../lighttpd-1.4.11/tests/lowercase.conf 1970-01-01 03:00:00.000000000 +0300 -+++ lighttpd-1.4.12/tests/lowercase.conf 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/tests/lowercase.conf 2006-07-16 00:26:05.000000000 +0300 @@ -0,0 +1,80 @@ +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/" +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid" @@ -48652,7 +53056,7 @@ + static-file.exclude-extensions = ( ".jpg" ) +} --- ../lighttpd-1.4.11/tests/lowercase.t 1970-01-01 03:00:00.000000000 +0300 -+++ lighttpd-1.4.12/tests/lowercase.t 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/tests/lowercase.t 2006-07-16 00:26:05.000000000 +0300 @@ -0,0 +1,94 @@ +#!/usr/bin/env perl +BEGIN { @@ -48748,8 +53152,19 @@ + +ok($tf->stop_proc == 0, "Stopping lighttpd"); + +--- ../lighttpd-1.4.11/tests/mod-cgi.t 2005-09-01 14:43:05.000000000 +0300 ++++ lighttpd-1.4.12/tests/mod-cgi.t 2006-07-18 13:03:40.000000000 +0300 +@@ -43,7 +43,7 @@ + GET /nph-status.pl HTTP/1.0 + EOF + ); +-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ]; ++$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 502 } ]; + ok($tf->handle_http($t) == 0, 'NPH + perl, Bug #14'); + + $t->{REQUEST} = ( <{CONFIGFILE} = 'fastcgi-13.conf'; ok($tf->start_proc == 0, "Starting lighttpd with $tf->{CONFIGFILE}") or die(); $t->{REQUEST} = ( <{PORT} = 2048; +$tf_proxy->{CONFIGFILE} = 'proxy.conf'; +$tf_proxy->{LIGHTTPD_PIDFILE} = $tf_proxy->{SRCDIR}.'/tmp/lighttpd/lighttpd-proxy.pid'; @@ -48987,9 +53404,29 @@ +ok($tf_backend2->stop_proc == 0, "Stopping lighttpd"); + +ok($tf_proxy->stop_proc == 0, "Stopping lighttpd proxy"); ++} +--- ../lighttpd-1.4.11/tests/proxy-backend-1.conf 1970-01-01 03:00:00.000000000 +0300 ++++ lighttpd-1.4.12/tests/proxy-backend-1.conf 2006-07-16 00:26:05.000000000 +0300 +@@ -0,0 +1,7 @@ ++server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/" ++server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd-backend-1.pid" ++ ++include "default.conf" ++ ++ ++server.tag = "proxy-backend-1" +--- ../lighttpd-1.4.11/tests/proxy-backend-2.conf 1970-01-01 03:00:00.000000000 +0300 ++++ lighttpd-1.4.12/tests/proxy-backend-2.conf 2006-07-16 00:26:04.000000000 +0300 +@@ -0,0 +1,7 @@ ++server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/" ++server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd-backend-2.pid" ++ ++include "default.conf" ++ + ++server.tag = "proxy-backend-2" --- ../lighttpd-1.4.11/tests/proxy.conf 1970-01-01 03:00:00.000000000 +0300 -+++ lighttpd-1.4.12/tests/proxy.conf 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/tests/proxy.conf 2006-07-16 00:26:05.000000000 +0300 @@ -0,0 +1,26 @@ +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/" +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd-proxy.pid" @@ -49018,7 +53455,7 @@ +} + --- ../lighttpd-1.4.11/tests/var-include.conf 2005-08-27 17:44:19.000000000 +0300 -+++ lighttpd-1.4.12/tests/var-include.conf 2006-07-11 22:07:53.000000000 +0300 ++++ lighttpd-1.4.12/tests/var-include.conf 2006-07-16 00:26:05.000000000 +0300 @@ -2,15 +2,15 @@ debug.log-request-handling = "enable" debug.log-condition-handling = "enable"