]> git.pld-linux.org Git - packages/lighttpd.git/commitdiff
- svn 1199
authorElan Ruusamäe <glen@pld-linux.org>
Tue, 18 Jul 2006 10:05:14 +0000 (10:05 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    lighttpd-branch.diff -> 1.7

lighttpd-branch.diff

index 97bdee3712b73aceab9dde38d6da92c915c735c1..9d33e7f58115c780b2a6b799923061ede0d9180d 100644 (file)
@@ -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.
  
  $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\r
 -------------------------------------------\r
 +Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>
 +
 --- ../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\r
 -------------------------------------------\r
 +Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>
 +
 --- ../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 @@
  ----------------
  
  :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 @@
  ===========
  
  ===========================
  
 --- ../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 @@
  ------------
  
 +  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
    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"
  
  ### 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
  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/";
    
    # 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
  Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-%version.tar.gz
  Packager: Jan Kneschke <jan@kneschke.de>
 --- ../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
  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
  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
  
  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 \
  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 <type>
++ * */
++
++#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) {
  }
  #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; \
        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_
  
  #ifdef HAVE_FAM_H
        int    dir_version;
        int    dir_ndx;
-@@ -215,8 +198,8 @@
+@@ -215,20 +198,20 @@
  } stat_cache_entry;
  
  typedef struct {
        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;
  } 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;
                                      * 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] */
 -      
 +
 +
        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;
  
        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;
 +                      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;
  #ifdef USE_OPENSSL
        SSL_CTX *ssl_ctx;
  #endif
-@@ -495,37 +488,37 @@
+@@ -495,37 +482,32 @@
  
  typedef struct {
        server_socket **ptr;
  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;
        size_t max_conns;
  
        /* buffers */
-@@ -533,13 +526,13 @@
+@@ -533,13 +515,13 @@
        buffer *response_header;
        buffer *response_range;
        buffer *tmp_buf;
        /* 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;
        stat_cache  *stat_cache;
  
        /**
-@@ -588,18 +581,20 @@
+@@ -588,18 +570,20 @@
         *   fastcgi.backend.<key>.disconnects = ...
         */
        array *status;
  
 -      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
  } 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 @@
  
  
   * 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;
        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;
 +
        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:
        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 ++;
                }
        }
        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 @@
                }
        }
  
   * replaces non-printable characters with '_'
   */
  
-@@ -854,10 +923,10 @@
+@@ -854,10 +922,10 @@
                                low = hex2int(*(src + 2));
                                if (low != 0xFF) {
                                        high = (high << 4) | low;
                                        *dst = high;
                                        src += 2;
                                }
-@@ -891,7 +960,7 @@
+@@ -891,7 +959,7 @@
   * /abc/./xyz       gets  /abc/xyz
   * /abc//xyz        gets  /abc/xyz
   *
   *       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;
        c |= 32;
        return (c >= 'a' && c <= 'f');
  }
-@@ -993,31 +1062,56 @@
+@@ -993,31 +1061,56 @@
        return light_isdigit(c) || light_isalpha(c);
  }
  
        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;
        size_t size;
  } buffer;
  
-+
 +typedef void (*buffer_ptr_free_t)(void *p);
 +
 +typedef struct {
  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);
  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,
        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);
  
 +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)
  
 -      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
        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:
                        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 {
        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 <string.h>
 +#include <ctype.h>
 +}
 +
 --- ../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 <stdlib.h>
                        break;
  
                case '+':
-@@ -637,96 +644,88 @@
+@@ -637,115 +644,107 @@
  
                case '{':
                        t->offset++;
                                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;
                                        }
        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;
        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);
        ** 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);
    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";
  }
  
 --- ../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 <stdlib.h>
        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);
  
        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;
 -      
 +
        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;
  }
  
 -#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);
  
 -      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);
 -                      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);
 -      }
 -              return -1;
 -      }
 -      buffer_prepare_copy(b, toread);
--
++      oldlen = chunkqueue_length(con->read_queue);
 -      len = read(con->fd, b->ptr, b->size - 1);
 -#endif
 -      
  }
  
  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:
                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:
                         * */
                        if (con->uri.path->used &&
                            con->uri.path->ptr[0] != '*') {
-@@ -381,55 +271,58 @@
+@@ -381,55 +248,60 @@
                        break;
                }
        }
        case 423:
        case 500:
        case 501:
++      case 502:
        case 503:
 -      case 505: 
++      case 504:
 +      case 505:
 +      case 509:
                if (con->mode != DIRECT) break;
                                           "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
                                           "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
                                           "         \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\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));
                        buffer_append_string(b,
                                             "</title>\n"
                                             " </head>\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));
                        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;
                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);
                        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;
                }
 -      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;
  
        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();
  #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();
 +
                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);
                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);
        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;
        }
  #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
        return NULL;
  }
  /**
-@@ -840,22 +736,25 @@
+@@ -840,22 +715,25 @@
        chunk *c;
        chunkqueue *cq = con->read_queue;
        chunkqueue *dst_cq = con->request_content_queue;
                        }
                default:
                        break;
-@@ -891,14 +790,14 @@
+@@ -891,14 +769,14 @@
                        /* the last node was empty */
                        if (c->next == NULL) {
                                cq->last = c;
        /* 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;
                        } 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 */
                        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;
                                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;
                                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;
                                /* 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;
                        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 */
  
                                /*
                                 * */
  
                                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) {
                                                        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)) {
                                        close(dst_c->file.fd);
                                        dst_c->file.fd = -1;
  
-@@ -1090,7 +990,7 @@
+@@ -1090,7 +969,7 @@
                                }
  
                                dst_c->file.length += toRead;
                                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);
                        }
                        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);
                }
                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;
 +
        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 */
        }
                                 */
  #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
                } 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 {
 -                      
 +
                        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;
                }
        }
                /* 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));
                }
                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 */
 -                      
        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 */
 +
        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
 +                  (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 {
 +
                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);
 -              
                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;
  #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));
 -                              
                                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
        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;
                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));
                        }
 -                      
 +
                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));
                        }
 -                      
 +
 +
                        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 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 */
                                }
                                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;
                        }
 -                      
 +
                        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 (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));
                        }
 -                      
 +
                                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;
                                }
 +
  #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:
                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));
                        }
 -                      
 +
                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 */
 -                                      
 +
                                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);
                                }
                        }
 -                      
                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));
                        }
 -                      
 +
                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;
                                }
                        }
                        /* 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;
                                }
  #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;
                        }
 +
                        /* 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);
                        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;
                }
                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));
        }
 -      
        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 
 +              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
  
  
  #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) {
        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) {
        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) {
        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) {
        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) {
        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) {
        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("-"));
        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 <sys/types.h>
  
  #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 @@
 -/* 
 +/*
  } 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"
  #include <stdlib.h>
  #include <string.h>
  #include <errno.h>
-@@ -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;
 -      
                        __FILE__, __LINE__);
                return NULL;
        }
-@@ -75,26 +76,26 @@
+@@ -75,28 +130,29 @@
  void fdevent_free(fdevents *ev) {
        size_t i;
        if (!ev) return;
 +
        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 <sys/epoll.h>
  #endif
  
  #  include <sys/poll.h>
  # endif
  # if defined HAVE_SIGTIMEDWAIT && defined(__linux__)
-@@ -31,9 +31,11 @@
+@@ -31,9 +34,11 @@
  #  include <signal.h>
  # endif
  #endif
  #  include <winsock2.h>
  # endif
  # define USE_SELECT
-@@ -67,14 +69,14 @@
+@@ -67,14 +72,14 @@
  #define FDEVENT_HUP    BV(4)
  #define FDEVENT_NVAL   BV(5)
  
                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
   */
  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
   */
  
  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;
  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;
        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);
 -      
        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 <sys/types.h>
  
        }
  
 --- ../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 <sys/types.h>
  
  #include <stdlib.h>
  #include <stdio.h>
  #include <string.h>
-@@ -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);
                }
 +
                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
        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();
        }
 -      
        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;
        } 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);
                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;
        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;
        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;
 -      
  }
  #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 <sys/types.h>
  
  #include <stdlib.h>
  #include <stdio.h>
  #include <string.h>
-@@ -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));
 -              
 +
        }
 -      
 -      
+-      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));
 -      
        if (events & FDEVENT_IN)  ep.events |= EPOLLIN;
        if (events & FDEVENT_OUT) ep.events |= EPOLLOUT;
  
-@@ -60,20 +61,20 @@
+@@ -60,73 +64,61 @@
         * sent.
         *
         */
 -      
 +
        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));
 -              
 +
                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;
        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__);
  }
  #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 <sys/types.h>
  
  #include <stdlib.h>
  #include <stdio.h>
  #include <string.h>
-@@ -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; */
                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);
                }
                SEGFAULT();
        }
 -      
+-      return -1;
 +
-       return -1;
++      sock->fde_ndx = -1;
++
++      return 0;
  }
  
  #if 0
  }
  #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();
        }
 -      
        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;
        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 <sys/time.h>
  #include <sys/types.h>
  #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) {
        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;
        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 <sys/types.h>
  
  }
  #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) {
 +
                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;
 -                      
 +
        }
  
 --- ../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 <string.h>
  #include <time.h>
 -      
 +
        /* 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;
        }
 -      
 +
                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) { 
                        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';
 +
                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;
 -              
 -              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) {
        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 <ldap.h>
  #endif
  } 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
  #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
        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 <string.h>
 +#include <stdlib.h>
 +#include <stdio.h>
 +#include <assert.h>
 +
++#include "log.h"
 +#include "http_resp.h"
 +#include "http_resp_parser.h"
 +
 +      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) {
 +}
 +
 --- ../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_
 +
 +#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.
 +*/
 +#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.
 +*/
 +    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 */
 +  }
 +  **     break;
 +  */
 +      case 0:
-+#line 26 "./http_resp_parser.y"
++#line 28 "./http_resp_parser.y"
 +{
 +    http_resp *resp = ctx->resp;
 +    data_string *ds;
 +
 +    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;
 +        
 +        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"
 +
 +    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"
 +    
 +    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;
 +  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 */
 +}
 +
 +  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}
 +#include "http_resp.h"
 +#include "keyvalue.h"
 +#include "array.h"
++#include "log.h"
 +}
 +
 +%parse_failure {
 +%type number { int }
 +%type headers { array * }
 +%type header { data_string * }
++%destructor reason { buffer_free($$); }
 +%token_destructor { buffer_free($$); }
 +
 +/* just headers + Status: ... */
 +    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). {
 +        
 +        ctx->ok = 0;
 +    }
++    buffer_free(B);
 +}
 +
 +number(A) ::= STRING(B). {
 +    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). {
 +    
 +    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). {
 +    
 +    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"
  
        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 <stdlib.h>
++
++#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 <openssl/ssl.h>
++#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) {
  }
  
 --- ../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" },
        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 <pcre.h>
  #endif
        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 @@
  */
  
      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.
        ** 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 <errno.h>
  #include <fcntl.h>
  #ifdef HAVE_VALGRIND_VALGRIND_H
  #include <valgrind/valgrind.h>
  #endif
-@@ -31,38 +36,38 @@
+@@ -31,55 +36,114 @@
  # define O_LARGEFILE 0
  #endif
  
 + *
   */
  
- 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;
  }
  
 + *
   */
  
- 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;
                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 ')':
                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 <inttypes.h>
  #endif
  /* 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"
        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 <ctype.h>
  #include <stdlib.h>
        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"
  
        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 <string.h>
  #include <errno.h>
        /* 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 @@
                        }
                }
        }
                        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;
 -                                              
 +
                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);
 -                      
                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);
                        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);
                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", 
 -                                      
 +
                        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;
++
                                }
                        }
 -                                      
 +                                              "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;
                        }
 -                      
 +
 -                              
 +
                                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);
 -                              
 -                              
 +
                                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);
 -                              
 -                              
 +
                                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);
 -                              
                                                        "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))) {
                                                        "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))) {
                                                        "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;
                                                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;
        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 <sys/types.h>
 -#ifdef __WIN32
  #include <signal.h>
  #include <ctype.h>
  #include <assert.h>
-@@ -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 <sys/filio.h>
- #endif
-@@ -40,11 +34,12 @@
+@@ -40,11 +35,12 @@
  
  typedef struct {
        char **ptr;
  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;
 -      
 +      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;
 -      
 +
        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);
 -      
 +
        buffer_free(p->tmp_buf);
-       buffer_free(p->parse_response);
+-      buffer_free(p->parse_response);
 -      
++      http_response_free(p->resp);
 +
        free(p);
 -      
        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);
        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);
        }
        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: "<key>: <value>\r\n" */
-                               continue;
-                       }
+-                      key = s;
+-                      if (NULL == (value = strchr(s, ':'))) {
+-                              /* we expect: "<key>: <value>\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
         * 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) {
                switch(waitpid(pid, &status, WNOHANG)) {
                case 0:
                        /* not finished yet */
-@@ -519,19 +515,19 @@
+@@ -519,35 +383,35 @@
                case -1:
                        /* */
                        if (errno == EINTR) break;
                        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;
                        }
 -                              
                                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;
                        }
                }
  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;
                }
        }
 +
        /* 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);
        }
 -      
 +
        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));
        }
        /* 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;
                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;
                                      (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));
 -              
  #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));
                              (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));
                              (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));
  
  #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));
                /* 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
                                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';
                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';
                        /* 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);
                }
 -              
 +
                /* */
                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]);
                        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));
                                                                        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;
                                                /* 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;
                                                        break;
                                                default:
                                                        con->http_status = 403;
-@@ -1033,7 +1032,7 @@
+@@ -1033,7 +902,7 @@
                                                switch(errno) {
                                                case ENOSPC:
                                                        con->http_status = 507;
                                                        break;
                                                default:
                                                        con->http_status = 403;
-@@ -1056,103 +1055,100 @@
+@@ -1056,103 +925,95 @@
                }
  
                close(to_cgi_fds[1]);
                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;
        }
 +
        if (fn->used == 0) return HANDLER_GO_ON;
 -      
++
++      TRACE("http-version: (%d)", con->request.http_version);
 +
        mod_cgi_patch_connection(srv, con, p);
 -      
                                buffer_reset(con->physical.path);
                                return HANDLER_FINISHED;
                        }
-@@ -1160,7 +1156,7 @@
+@@ -1160,7 +1021,7 @@
                        break;
                }
        }
        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 */
                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));
                        return HANDLER_ERROR;
                default:
  
-@@ -1193,16 +1189,16 @@
+@@ -1193,96 +1054,103 @@
                        } else {
                                log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?");
                        }
        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;
 -              
                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;
 -              
 -              /* 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 */
 +
                }
 -              
-+
-               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;
        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 <stdlib.h>
  #include <string.h>
        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 {
  
  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 <stdlib.h>
  #include <string.h>
  }
  #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
  }
  #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 <sys/stat.h>
  
        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 <ctype.h>
  #include <stdlib.h>
        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 {
        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"
  }
  
 --- ../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"
  
        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 <sys/types.h>
 -#include <unistd.h>
        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;
 -      
 +
        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;
        connection *remote_conn;  /* dumb pointer */
        plugin_data *plugin_data; /* dumb pointer */
  } handler_ctx;
-@@ -380,7 +382,7 @@
+@@ -380,7 +381,7 @@
        return di;
  }
  
   * 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");
  
  
  #define CLEAN(x) \
        fastcgi_status_copy_procname(b, host, NULL); \
-@@ -438,33 +440,32 @@
+@@ -438,33 +439,30 @@
  
        CLEAN(".load");
  
        hctx = calloc(1, sizeof(*hctx));
        assert(hctx);
 -      
-+
-       hctx->fde_ndx = -1;
+-      hctx->fde_ndx = -1;
 -      
 -      hctx->response_header = buffer_init();
 -      
        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;
        return hctx;
  }
  
-@@ -473,10 +474,9 @@
+@@ -473,12 +471,13 @@
                hctx->host->load--;
                hctx->host = NULL;
        }
 +      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();
        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();
        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);
        free(f);
  }
  
-@@ -625,24 +625,25 @@
+@@ -625,24 +624,25 @@
                assert(fe->hosts);
        }
  
        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);
        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));
        }
        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));
                        start = b->ptr + i + 1;
                        break;
                default:
-@@ -794,7 +796,7 @@
+@@ -794,7 +795,7 @@
        return 0;
  }
  
                                 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;
                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;
                        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);
                        }
                                        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;
                                /* 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);
                        break;
                }
                case -1:
-@@ -1031,17 +1029,17 @@
+@@ -1031,17 +1028,17 @@
                        break;
                default:
                        /* father */
                                                "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)) {
                                                        "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)) {
                                                        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 {
                                                        status);
                                }
                                return -1;
-@@ -1082,26 +1080,26 @@
+@@ -1082,26 +1079,26 @@
                        proc->pid = child;
                        proc->last_used = srv->cur_ts;
                        proc->is_local = 1;
        return 0;
  }
  
-@@ -1111,93 +1109,93 @@
+@@ -1111,93 +1108,93 @@
        data_unset *du;
        size_t i = 0;
        buffer *fcgi_mode = buffer_init();
                                                { "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 */
                                        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 */
                                        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);
                                                                        da_ext->key, " => (",
                                                                        da_host->key, " ( ...");
  
-@@ -1288,37 +1286,37 @@
+@@ -1288,37 +1285,37 @@
                                                }
                                        } else {
                                                /* tcp/ip */
                                                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);
                                                }
                                                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);
                                                        }
                                                        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);
                                                        }
                                                        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);
                                        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 @@
                        }
                }
        }
        return 0;
  }
  
-@@ -1429,13 +1427,13 @@
+@@ -1429,13 +1426,13 @@
        size_t m = 0;
        size_t i;
        buffer_uint *r = &(p->fcgi_request_id);
        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);
        }
 -      
 +
        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--;
        }
 -      
 +
                        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",
 +       *
         */
  
-       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;
        }
 -      
 +
 +
        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));
 -      
        /* 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));
                        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);
 -              
 -              /* 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;
        }
  
        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) {
  
 -                              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 ||
 -                                              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 */
                        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);
                        }
                 */
                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;
                                        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 */
                        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
                                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;
        return 0;
  }
  
-@@ -2682,19 +2595,19 @@
+@@ -2682,19 +2601,19 @@
        fcgi_extension_host *host= hctx->host;
        connection *con   = hctx->remote_conn;
        fcgi_proc  *proc;
                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));
 -                      
                        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 */
                        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;
                        }
                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;
  
 +
                /* 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;
                        }
                                        "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));
 -                      
                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;
                                "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));
                        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
                         *  */
                        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);
                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",
                                        "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 {
                /* 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);
 -              
                                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:
                                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;
        }
        return HANDLER_WAIT_FOR_EVENT;
  }
  
-@@ -2996,18 +2910,18 @@
+@@ -2996,18 +2916,18 @@
   * */
  SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) {
        plugin_data *p = p_d;
         *    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];
                        con->http_status = 500;
                        con->mode = DIRECT;
  
-@@ -3040,16 +2954,16 @@
+@@ -3040,16 +2960,16 @@
                }
  
                host = hctx->ext->hosts[ndx];
                 *
                 * 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;
                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);
                                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);
                        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;
        fcgi_proc *proc   = hctx->proc;
        fcgi_extension_host *host= hctx->host;
  
-@@ -3125,8 +3039,8 @@
+@@ -3125,8 +3045,8 @@
                case 0:
                        break;
                case 1:
                            (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);
                                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)) {
                                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);
                                "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);
        }
  
  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;
        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" => ... )
                        /* 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 */
                        /* 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;
                }
  
        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.");
                }
                                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();
                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];
 +
        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;
        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;
        /* 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];
                                        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);
                                        }
                                        proc->prev = NULL;
                                        proc->next = host->first;
                                        if (host->first) {
-@@ -3688,56 +3623,56 @@
+@@ -3688,56 +3629,56 @@
                                        }
                                        host->first = proc;
                                }
                                        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 */
  #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) {
                                }
                        }
                }
-@@ -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;
        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 {
        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"
        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 <unistd.h>
  #include <stdio.h>
  }
  #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 <sys/types.h>
  
  } 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;
  
        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 */
 -      
        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;
  
        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;
  }
  
        chunkqueue_free(hctx->wb);
 -      
 +      chunkqueue_free(hctx->rb);
++
++      iosocket_free(hctx->fd);
 +
        free(hctx);
  }
                                                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 @@
                        }
                }
        }
 -      
 +
        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--;
        }
 -      
 +
        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));
 -      
 +
 +              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, ": ");
  
                        switch (req_c->type) {
                        case FILE_CHUNK:
-@@ -507,223 +550,161 @@
+@@ -507,223 +550,150 @@
  
                                req_c->offset += weHave;
                                req_cq->bytes_out += weHave;
        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);
 -                      
 -                      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;
 -      
        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)) {
 +      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;
 +                              /* 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"))) {
 +                              } 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);
 +
  }
  
  
-@@ -731,12 +712,12 @@
+@@ -731,32 +701,32 @@
        data_proxy *host= hctx->host;
        plugin_data *p    = hctx->plugin_data;
        connection *con   = hctx->remote_conn;
 +
        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++;
 -              
        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);
 +
                                /* 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));
 -                              
 +                      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;
                }
 -                      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;
                }
 +              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;
                 */
  
                return HANDLER_WAIT_FOR_FD;
-@@ -938,7 +919,7 @@
+@@ -938,7 +908,7 @@
        default:
                break;
        }
        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;
                                        "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--;
 -                      
 +
                        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);
                        }
                        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 */
        return HANDLER_FINISHED;
  }
  
-@@ -1058,44 +1044,48 @@
+@@ -1058,44 +1033,48 @@
        buffer *fn;
        data_array *extension = NULL;
        size_t path_info_offset;
                                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;
                }
        }
                log_error_write(srv, __FILE__, __LINE__,  "s", "proxy - ext found");
        }
  
-@@ -1120,34 +1112,34 @@
+@@ -1120,34 +1101,34 @@
                /* hash balancing */
  
                if (p->conf.debug) {
                        }
                }
  
-@@ -1155,19 +1147,20 @@
+@@ -1155,19 +1136,20 @@
        case PROXY_BALANCE_FAIR:
                /* fair balancing */
                if (p->conf.debug) {
                        }
                }
  
-@@ -1175,89 +1168,100 @@
+@@ -1175,89 +1157,100 @@
        case PROXY_BALANCE_RR:
                /* round robin */
                if (p->conf.debug) {
        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];
                        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;
                                                        "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;
 +
        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 <string.h>
++#include <stdlib.h>
++#include <fcntl.h>
++#include <errno.h>
 +
-       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 <stdlib.h>
++#include <string.h>
++
++#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 <time.h>
++#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 <stdlib.h>
++
++#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 <stdlib.h>
++
++#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 <sys/types.h>
++#include <sys/time.h>
++
++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 <stdlib.h>
++
++#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 <sys/time.h>
++
++#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 {
        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
  
        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 <stdlib.h>
  #include <stdio.h>
        /* fork, execve */
        switch (pid = fork()) {
        case 0: {
-@@ -117,33 +120,33 @@
+@@ -117,33 +120,28 @@
                int argc;
                int i = 0;
                char *dash = "-";
 +
                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 */
                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);
                }
                /* */
                SEGFAULT();
                break;
-@@ -168,19 +171,19 @@
+@@ -168,19 +166,19 @@
                break;
        default: {
                /* father */
        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;
                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");
                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");
        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 <sys/types.h>
 -#include <unistd.h>
  #include <errno.h>
  #include <fcntl.h>
  #include <string.h>
-@@ -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"
  
  #ifndef UNIX_PATH_MAX
  # define UNIX_PATH_MAX 108
-@@ -46,30 +47,29 @@
+@@ -46,30 +48,29 @@
  enum {EOL_UNSET, EOL_N, EOL_RN};
  
  /*
        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 */
  } 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
         */
  
        unsigned short min_procs;
-@@ -111,44 +111,44 @@
+@@ -111,44 +112,44 @@
  
        /*
         * kick the process from the list if it was not
        unsigned short port;
  
        /*
-@@ -161,7 +161,7 @@
+@@ -161,7 +162,7 @@
         */
        buffer *unixsocket;
  
         * 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
         */
         * remote host
         *
         * reasons:
-@@ -192,7 +192,7 @@
+@@ -192,7 +193,7 @@
        buffer *docroot;
  
        /*
         * 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
   *
   * 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;
        size_t used;
        size_t size;
  } scgi_extension;
-@@ -253,14 +253,14 @@
+@@ -253,14 +254,14 @@
  
  
  typedef struct {
        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;
 -      
 +
        buffer *path;
-       buffer *parse_response;
+-      buffer *parse_response;
 -      
++
++      http_resp *resp;
 +
        plugin_config **config_storage;
 -      
  /* 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;
 -      
 +
        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;
 -      
        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;
        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();
        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();
        free(f);
  }
  
-@@ -504,99 +503,103 @@
+@@ -504,99 +492,103 @@
                assert(fe->hosts);
        }
  
 -      
 +
        p->path = buffer_init();
-       p->parse_response = buffer_init();
+-      p->parse_response = buffer_init();
 -      
++      p->resp = http_response_init();
 +
        return p;
  }
  
        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;
        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));
        }
                                 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;
                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;
                                        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;
                        break;
                }
                case -1:
-@@ -817,32 +816,32 @@
+@@ -817,32 +805,32 @@
                        break;
                default:
                        /* father */
                                                        status);
                                }
                                return -1;
-@@ -852,26 +851,26 @@
+@@ -852,26 +840,26 @@
                        proc->pid = child;
                        proc->last_used = srv->cur_ts;
                        proc->is_local = 1;
        return 0;
  }
  
-@@ -880,89 +879,89 @@
+@@ -880,89 +868,89 @@
        plugin_data *p = p_d;
        data_unset *du;
        size_t i = 0;
                                                { "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 */
                                        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);
                                                                        da->key,
                                                                        da_ext->key,
                                                                        da_host->key,
-@@ -1056,14 +1055,14 @@
+@@ -1056,14 +1044,14 @@
                                                        return HANDLER_ERROR;
                                                }
                                        }
                                                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);
                                                }
                                                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);
                                                        }
                                                        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);
                                                        }
        return 0;
  }
  
-@@ -1150,34 +1149,34 @@
+@@ -1150,35 +1138,35 @@
  void scgi_connection_cleanup(server *srv, handler_ctx *hctx) {
        plugin_data *p;
        connection  *con;
 -      
 +
        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--;
        }
 -      
                        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);
        }
  
 +       *
         */
 -      
+-      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++;
        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);
        }
 -      
   * returns
   *   -1 error
   *    0 connected
-@@ -1280,24 +1279,21 @@
+@@ -1280,24 +1268,21 @@
        struct sockaddr_un scgi_addr_un;
  #endif
        socklen_t servlen;
 +
        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));
 -      
                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))) {
        return 0;
  }
  
-@@ -1415,20 +1411,20 @@
+@@ -1415,20 +1400,20 @@
        char b2[INET6_ADDRSTRLEN + 1];
  #endif
        buffer *b;
        /* 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));
                              (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));
        }
        /* 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));
  
        /*
         * 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));
                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)) {
                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(""));
        }
        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
  
                        switch (req_c->type) {
                        case FILE_CHUNK:
-@@ -1615,32 +1611,32 @@
+@@ -1615,293 +1600,170 @@
  
                                req_c->offset += weHave;
                                req_cq->bytes_out += weHave;
        }
  #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: "<key>: <value>\r\n" */
-                               continue;
-                       }
+-                      key = s;
+-                      if (NULL == (value = strchr(s, ':'))) {
+-                              /* we expect: "<key>: <value>\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;
  }
         */
  
        /* 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);
  
         * ^
         * |
         * +
-@@ -1930,16 +1926,16 @@
+@@ -1930,16 +1792,16 @@
  
        if (proc->prev) proc->prev->next = proc->next;
        if (proc->next) proc->next->prev = proc->prev;
                                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;
         *   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.
         */
  
        /* 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);
  
  
        /* 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;
                                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;
                                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
                                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);
                                }
        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;
                                "write-req: error",
                                host,
                                host->host->used,
-@@ -2135,179 +2133,180 @@
+@@ -2135,259 +1999,260 @@
                                host->unixsocket->used);
                return HANDLER_ERROR;
        }
 +
  
        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;
                        }
                                        "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));
 -                      
 -              
 +
                /* 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);
 +
                        /* all childs are dead */
                        if (hctx->proc == NULL) {
-                               hctx->fde_ndx = -1;
+-                              hctx->fde_ndx = -1;
 -                              
++                              hctx->sock->fde_ndx = -1;
 +
                                return HANDLER_ERROR;
                        }
 +
                        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:
 -                      
 +
                        /* 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));
 -                              
                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,
                /* 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);
 -      
 +
                                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;
                        }
 +
                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;
        }
                        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
                         */
                                 */
                                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);
                        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;
 -      
 -      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);
        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;
        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);
                                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)) {
                                        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);
                                        }
 +
 +                                      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;
                                }
 +
 +                              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);
 -                              
                                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);
 +
 +                              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);
                        }
 -      
 +
        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
 -                       * 
 +                       *
 +
        /* 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 
 +                       *
                         */
                        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:
 -                       * 
                                "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);
        }
  
  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;
                /* 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;
        }
                        ndx = k;
                }
        }
-@@ -2728,12 +2725,12 @@
+@@ -2728,12 +2593,12 @@
        /* found a server */
        if (ndx != -1) {
                scgi_extension_host *host = extension->hosts[ndx];
                /* 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();
                                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;
                                        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();
                        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;
                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];
 +
        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;
         */
  
        /* check all childs if they are still up */
-@@ -2904,47 +2901,47 @@
+@@ -2904,47 +2770,47 @@
                        scgi_extension *ex;
  
                        ex = exts->exts[j];
                                        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);
                                        }
                                        fp->prev = NULL;
                                        fp->next = host->first;
                                        if (host->first) {
-@@ -2966,56 +2963,57 @@
+@@ -2966,56 +2832,57 @@
                                        }
                                        host->first = fp;
                                }
                                        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 */
  #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) {
                                }
                        }
                }
-@@ -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;
        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
        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;
        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"
        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 @@
  
  /**
        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 <stdio.h>
 +#include <errno.h>
 +}
 +
 --- ../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_
 +
 +#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 <string.h>
  #include <errno.h>
        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 {
  
  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;
        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 {
  } 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.
        ** 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"
        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 <fcntl.h>
  #include <stdlib.h>
        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 @@
  
  /**
        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"
  
        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 {
        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 <ctype.h>
  #include <stdlib.h>
        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 */
  
 +
                        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 */
                        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);
                                /* 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 */
  
 +
                                                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;
        }
        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;
                }
        }
        stream_close(&s);
        close(ofd);
  
-@@ -614,16 +711,16 @@
+@@ -614,19 +709,18 @@
                        sqlite3_reset(stmt);
  
                        /* bind the values to the insert */
 +
                        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;
                        }
                        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 */
 +
                                                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);
                closedir(srcdir);
        }
  
-@@ -748,12 +845,12 @@
+@@ -748,12 +841,12 @@
                        if (S_ISDIR(sce->st.st_mode)) {
                                buffer_append_string(b, "<D:getcontenttype>httpd/unix-directory</D:getcontenttype>");
                                found = 1;
                                        if (buffer_is_equal_right_len(dst->path, ds->key, ds->key->used - 1)) {
                                                buffer_append_string(b,"<D:getcontenttype>");
                                                buffer_append_string_buffer(b, ds->value);
-@@ -807,23 +904,23 @@
+@@ -807,23 +900,23 @@
  
                        /* bind the values to the insert */
  
                                found = 1;
                        }
                }
-@@ -840,7 +937,7 @@
+@@ -840,7 +933,7 @@
        char *prop;
  } webdav_property;
  
        { "DAV:", "creationdate" },
        { "DAV:", "displayname" },
        { "DAV:", "getcontentlanguage" },
-@@ -871,8 +968,8 @@
+@@ -871,8 +964,8 @@
                        webdav_property *prop;
  
                        prop = props->ptr[i];
                                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));
                                                        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);
                        }
                        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);
                        }
                        c->offset += weHave;
                        cq->bytes_out += weHave;
  
-@@ -991,6 +1088,113 @@
+@@ -991,6 +1084,113 @@
  }
  #endif
  
  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;
        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 ? */
  #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 */
 -                                              
 +
                                                                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);
                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);
                        buffer_append_string(b,"<D:response>\n");
                        buffer_append_string(b,"<D:href>");
                        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,"</D:prop>\n");
                                buffer_append_string(b,"</D:propstat>\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,"</D:prop>\n");
                        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 */
                                        } 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);
                                        buffer_append_string(b,"<D:response>\n");
                                        buffer_append_string(b,"<D:href>");
                                        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,"</D:prop>\n");
                                                buffer_append_string(b,"</D:propstat>\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,"</D:prop>\n");
                                                buffer_append_string(b,"</D:propstat>\n");
                                        }
  
-@@ -1275,7 +1492,7 @@
+@@ -1275,7 +1487,7 @@
  
                        return HANDLER_FINISHED;
                }
                /* 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;
                }
                /* 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);
                                buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
  
                                buffer_append_string(b,"<D:multistatus xmlns:D=\"DAV:\">\n");
-@@ -1331,7 +1554,7 @@
+@@ -1331,7 +1549,7 @@
                                buffer_append_string_buffer(b, multi_status_resp);
  
                                buffer_append_string(b,"</D:multistatus>\n");
                                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 */
                                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;
        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;
                }
                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);
                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;
  
                        /* 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) {
                                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 */
                                                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;
        }
                /* 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;
  
                                                                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 */
  
                                                                        }
                                                                }
                                                        }
-@@ -1804,7 +2124,7 @@
+@@ -1804,7 +2119,7 @@
  
                                                        goto propmatch_cleanup;
                                                }
                                                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:
                                xmlFreeDoc(xml);
                        } else {
                                con->http_status = 400;
-@@ -1830,11 +2151,307 @@
+@@ -1830,11 +2146,307 @@
  #endif
                con->http_status = 501;
                return HANDLER_FINISHED;
        /* 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");
        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 <sys/types.h>
  #include <sys/stat.h>
  #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;
 -              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
         *
 -      
 +
        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);
        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);
  
                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;
        }
  #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", 
                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", 
                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;
        }
                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));
        }
        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);
 -              
                /* 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
  #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 */
  
                        return -1;
                }
  
-@@ -558,36 +608,47 @@
+@@ -558,36 +609,47 @@
                                break;
                        }
                }
        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;
  }
 -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);
 +      }
 +}
 +
        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;
        /* 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) {
  #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;
        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"
  
  
  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
  
 +#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);
 +
 +NETWORK_BACKEND_WRITE(win32transmitfile);
 +NETWORK_BACKEND_WRITE(win32send);
-+
 +NETWORK_BACKEND_READ(read);
 +NETWORK_BACKEND_READ(win32recv);
  
 -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
  
  #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
 -                      /* 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) {
                                        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) {
                                                        "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 */
 +
                                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
 +
                        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;
                }
        }
  
  
  #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"
 +# include <openssl/err.h>
  
 -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:
 +}
 +
 +
-+NETWORK_BACKEND_WRITE_SSL(openssl) {
++NETWORK_BACKEND_WRITE(openssl) {
        int ssl_r;
        chunk *c;
        size_t chunks_written = 0;
         * 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.
         * - 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;
 -                      
 -                      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 {
                                        return -1;
                                }
  
-@@ -183,9 +255,9 @@
+@@ -183,13 +255,13 @@
                                }
  
                                s = local_send_buffer;
 +
                                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())) {
                                                                                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:
                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
  
  
  #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 <sys/types.h>
  #include <sys/stat.h>
  #ifdef HAVE_SYS_FILIO_H
  # include <sys/filio.h>
  #endif
-@@ -24,47 +27,84 @@
+@@ -24,47 +27,92 @@
  #include <sys/resource.h>
  #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
 +*
 +      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;
 +
 +              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;
 +}
 -                              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
                        break;
                }
                case FILE_CHUNK: {
-@@ -76,93 +116,89 @@
+@@ -76,93 +124,89 @@
                        size_t toSend;
                        stat_cache_entry *sce = NULL;
                        int ifd;
                        }
                        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;
                        }
                        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;
 -}
  #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
 +              }
 +      }
 +
-+      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;
 +                      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;
 +              }
 -                      
 -                      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 */
 -                      
                                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:
 +                                      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;
                                }
  
  #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 <valgrind/valgrind.h>
  #endif
        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) \
  
  #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
  
        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"
  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"
 -                              "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);
        }
        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 <stdlib.h>
  #include <string.h>
        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 <sys/types.h>
 -#include <sys/time.h>
  #endif
  
  #ifdef HAVE_VALGRIND_VALGRIND_H
-@@ -60,8 +63,16 @@
+@@ -60,8 +63,17 @@
  /* #define USE_ALARM */
  #endif
  
 +
 +#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;
  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;
  
             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;
  
             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);
        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);
        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);
        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();
 -      
        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);
        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);
        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);
                        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);
        free(srv);
  }
  
-@@ -281,14 +293,12 @@
+@@ -281,14 +288,12 @@
  " - a light and fast webserver\n" \
  "Build-Date: " __DATE__ " " __TIME__ "\n";
  ;
  #ifdef USE_SELECT
        "\t+ select (generic)\n"
  #else
-@@ -355,11 +365,6 @@
+@@ -355,11 +360,6 @@
  #else
        "\t- crypt support\n"
  #endif
  #ifdef USE_OPENSSL
        "\t+ SSL Support\n"
  #else
-@@ -371,9 +376,9 @@
+@@ -371,9 +371,9 @@
        "\t- PCRE support\n"
  #endif
  #ifdef HAVE_MYSQL
  #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
  }
  
  static void show_help (void) {
-@@ -433,12 +441,12 @@
+@@ -433,277 +436,644 @@
  " -h         show this help\n" \
  "\n"
  ;
  }
  
 -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) {
                                        "can't find groupname", srv->srvconf.groupname);
                                return -1;
                        }
-@@ -713,15 +732,15 @@
+@@ -713,15 +1083,15 @@
                                return -1;
                        }
                }
                if (srv->srvconf.changeroot->used) {
                        tzset();
  
-@@ -761,7 +780,7 @@
+@@ -761,7 +1131,7 @@
                }
  
                if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
                } 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 */
                        return -1;
                }
        }
-@@ -802,25 +821,27 @@
+@@ -802,25 +1172,27 @@
                /* or use the default */
                srv->max_conns = srv->max_fds;
        }
        /* 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;
        }
        /* 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];
                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");
 -              
  #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);
  #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
        /* start watcher and workers */
        num_childs = srv->srvconf.max_worker;
        if (num_childs > 0) {
-@@ -957,13 +977,13 @@
+@@ -957,13 +1328,13 @@
        }
  #endif
  
         * all server sockets get their handlers
         *
         * */
-@@ -971,7 +991,7 @@
+@@ -971,7 +1342,7 @@
                plugins_free(srv);
                network_close(srv);
                server_free(srv);
                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")) {
                                         "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) {
 -      
 +
        /* 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
                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 <sys/types.h>
 -#include <sys/time.h>
  }
  #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
      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  */
  
  #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 <stdlib.h>
  #include <string.h>
  typedef struct {
        int *ptr;
  
-@@ -105,15 +93,15 @@
+@@ -105,15 +93,16 @@
  
  stat_cache *stat_cache_init(void) {
        stat_cache *fc = NULL;
        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       
        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;
        free(sce);
  }
  
-@@ -148,22 +136,22 @@
+@@ -148,22 +137,22 @@
        fam_dir_entry *fam_dir = NULL;
  
        fam_dir = calloc(1, sizeof(*fam_dir));
        free(fam_dir);
  }
  #endif
-@@ -174,7 +162,7 @@
+@@ -174,7 +163,7 @@
                splay_tree *node = sc->files;
  
                osize = sc->files->size;
                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;
                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;
        attrlen = 1024;
        buffer_prepare_copy(buf, attrlen);
        attrlen--;
-@@ -251,15 +239,15 @@
+@@ -251,15 +241,15 @@
            sc->fam) {
  
                events = FAMPending(sc->fam);
                        /* handle event */
  
                        switch(fe.code) {
-@@ -280,7 +268,7 @@
+@@ -280,7 +270,7 @@
  
                                sc->dirs = splaytree_splay(sc->dirs, ndx);
                                node = sc->dirs;
                                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;
        }
                                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 <sys/types.h>
  #include <sys/stat.h>
  }
  
 --- ../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_
 +#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
  #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_
 +#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
  #else
  #include <sys/socket.h>
  #include <sys/ioctl.h>
-@@ -18,7 +29,23 @@
+@@ -18,7 +29,25 @@
  #include <sys/un.h>
  #include <arpa/inet.h>
  
 +#define SUN_LEN(su) \
 +        (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
 +#endif
++
++#define closesocket(x) close(x)
 +
  #include <netdb.h>
- #endif
++#endif /* !_WIN32 */
++
 +typedef union {
 +#ifdef HAVE_IPV6
 +      struct sockaddr_in6 ipv6;
 +      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_
 +#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
        #
  
 +      $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}) {
                                                             $h, $resp_hdr{$h}, $2));
                                        } else {
                                                $resp_hdr{$h} = $2;
-@@ -196,6 +196,9 @@
+@@ -196,6 +198,9 @@
                        }
                }
  
                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 \
  
  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"
  }
  
 --- ../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"
  }
  
 --- ../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 {
 +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};
 +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};
 +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"
    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
  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"/>
  </wc-entries>
 --- ../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"
  }
  
 --- ../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"
  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"
  
  }
  
 --- ../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"
  }
  
 --- ../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"
  }
  
 --- ../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;
                                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"
  }
  
 --- ../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"
 +  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 {
 +
 +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} = ( <<EOF
 --- ../lighttpd-1.4.11/tests/mod-fastcgi.t     2006-03-09 15:30:45.000000000 +0200
-+++ lighttpd-1.4.12/tests/mod-fastcgi.t        2006-07-11 22:07:53.000000000 +0300
++++ lighttpd-1.4.12/tests/mod-fastcgi.t        2006-07-18 13:03:40.000000000 +0300
 @@ -7,7 +7,7 @@
  }
  
  
  SKIP: {
 -      skip "no php found", 4 unless -x "/home/jan/Documents/php-5.1.0/sapi/cgi/php"; 
-+      skip "no php found", 4 unless -x "/home/jan/Documents/php-5.1.0/sapi/cgi/php";
++      skip "no php found", 4 unless -x "/home/jan/Documents/php-5.1.4/sapi/cgi/php";
        $tf->{CONFIGFILE} = 'fastcgi-13.conf';
        ok($tf->start_proc == 0, "Starting lighttpd with $tf->{CONFIGFILE}") or die();
        $t->{REQUEST}  = ( <<EOF
  GET /index.fcgi?die-at-end HTTP/1.0
  Host: www.example.org
 --- ../lighttpd-1.4.11/tests/mod-proxy.t       1970-01-01 03:00:00.000000000 +0300
-+++ lighttpd-1.4.12/tests/mod-proxy.t  2006-07-11 22:07:53.000000000 +0300
-@@ -0,0 +1,173 @@
++++ lighttpd-1.4.12/tests/mod-proxy.t  2006-07-18 13:03:40.000000000 +0300
+@@ -0,0 +1,175 @@
 +#!/usr/bin/env perl
 +BEGIN {
 +    # add current source dir to the include-path
 +## 1. the real webserver
 +## 2. the proxy server
 +
++SKIP: {
++  skip "disabled for now", 21;
 +$tf_proxy->{PORT} = 2048;
 +$tf_proxy->{CONFIGFILE} = 'proxy.conf';
 +$tf_proxy->{LIGHTTPD_PIDFILE} = $tf_proxy->{SRCDIR}.'/tmp/lighttpd/lighttpd-proxy.pid';
 +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"
 +}
 +
 --- ../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"
This page took 1.080658 seconds and 4 git commands to generate.