changeset 96:a23d010f356d

nginx-0.0.1-2003-05-27-16:18:54 import
author Igor Sysoev <igor@sysoev.ru>
date Tue, 27 May 2003 12:18:54 +0000
parents b48066122884
children 70d2345a903f
files src/core/nginx.c src/core/ngx_conf_file.c src/core/ngx_conf_file.h src/core/ngx_connection.h src/core/ngx_modules.c src/event/modules/ngx_aio_module.c src/event/modules/ngx_devpoll_module.c src/event/modules/ngx_kqueue_module.c src/event/modules/ngx_kqueue_module.h src/event/modules/ngx_poll_module.c src/event/modules/ngx_select_module.c src/event/ngx_event.c src/event/ngx_event.h src/event/ngx_event_accept.c src/event/ngx_event_timer.c src/http/modules/ngx_http_index_handler.c src/http/modules/ngx_http_index_handler.h src/http/modules/ngx_http_static_handler.c src/http/ngx_http.c src/http/ngx_http.h src/http/ngx_http_config.h src/http/ngx_http_core_module.c src/http/ngx_http_core_module.h src/http/ngx_http_event.c src/http/ngx_http_header_filter.c src/http/ngx_http_output_filter.c src/http/ngx_http_request.h src/http/ngx_http_special_response.c src/http/ngx_http_write_filter.c src/os/unix/ngx_freebsd_config.h src/os/unix/ngx_freebsd_init.h src/os/unix/ngx_freebsd_sendfile_chain.c src/os/unix/ngx_recv.c
diffstat 33 files changed, 950 insertions(+), 901 deletions(-) [+]
line wrap: on
line diff
--- a/src/core/nginx.c
+++ b/src/core/nginx.c
@@ -87,7 +87,7 @@ int main(int argc, char *const *argv)
         conf.ctx = ngx_conf_ctx;
         conf.pool = ngx_pool;
         conf.log = &ngx_log;
-        conf.module_type = NGX_CORE_MODULE_TYPE;
+        conf.module_type = NGX_CORE_MODULE;
         conf.cmd_type = NGX_MAIN_CONF;
 
         conf_file.len = sizeof("nginx.conf") - 1;
@@ -121,7 +121,7 @@ int main(int argc, char *const *argv)
 
         /* STUB */
         ngx_worker(&ngx_log);
-    }     
+    }
 
     return 0;
 }
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -6,6 +6,9 @@
 #include <ngx_conf_file.h>
 
 
+char ngx_conf_errstr[MAX_CONF_ERRSTR];
+
+
 static int argument_number[] = {
     NGX_CONF_NOARGS,
     NGX_CONF_TAKE1,
@@ -17,7 +20,7 @@ static int ngx_conf_read_token(ngx_conf_
 
 char *ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
 {
-    int               i, rc, found;
+    int               m, rc, found;
     char             *rv;
     void             *conf, **confp;
     ngx_str_t        *name;
@@ -32,7 +35,6 @@ char *ngx_conf_parse(ngx_conf_t *cf, ngx
         fd = ngx_open_file(filename->data, NGX_FILE_RDONLY);
         if (fd == NGX_INVALID_FILE) {
             ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno,
-                          "ngx_conf_file: "
                           ngx_open_file_n " %s failed", filename->data);
             return NGX_CONF_ERROR;
         }
@@ -44,7 +46,6 @@ char *ngx_conf_parse(ngx_conf_t *cf, ngx
 
         if (ngx_stat_fd(fd, &cf->conf_file->file.info) == -1) {
             ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno,
-                          "ngx_conf_file: "
                           ngx_stat_fd_n " %s failed", filename->data);
         }
 
@@ -101,17 +102,17 @@ ngx_log_debug(cf->log, "token %d" _ rc);
         name = (ngx_str_t *) cf->args->elts;
         found = 0;
 
-        for (i = 0; !found && ngx_modules[i]; i++) {
+        for (m = 0; !found && ngx_modules[m]; m++) {
 
             /* look up the directive in the appropriate modules */
 
-            if (ngx_modules[i]->type != NGX_CONF_MODULE_TYPE
-                && ngx_modules[i]->type != cf->module_type)
+            if (ngx_modules[m]->type != NGX_CONF_MODULE
+                && ngx_modules[m]->type != cf->module_type)
             {
                 continue;
             }
 
-            cmd = ngx_modules[i]->commands;
+            cmd = ngx_modules[m]->commands;
             if (cmd == NULL) {
                 continue;
             }
@@ -160,14 +161,14 @@ ngx_log_debug(cf->log, "command '%s'" _ 
 
                     conf = NULL;
 
-                    if (cf->module_type == NGX_CORE_MODULE_TYPE) {
-                        conf = &(((void **) cf->ctx)[ngx_modules[i]->index]);
+                    if (cf->module_type == NGX_CORE_MODULE) {
+                        conf = &(((void **) cf->ctx)[ngx_modules[m]->index]);
 
                     } else if (cf->ctx) {
                         confp = *(void **) ((char *) cf->ctx + cmd->conf);
 
                         if (confp) {
-                            conf = confp[*(int *)(ngx_modules[i]->ctx)];
+                            conf = confp[ngx_modules[m]->ctx_index];
                         }
                     }
 
@@ -185,11 +186,19 @@ ngx_log_debug(cf->log, "rv: %d" _ rv);
                         return NGX_CONF_ERROR;
 
                     } else {
-                        ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                                     "%s %s in %s:%d",
-                                     name->data, rv,
-                                     cf->conf_file->file.name.data,
-                                     cf->conf_file->line);
+                        if (rv == ngx_conf_errstr) {
+                            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                                         "%s in %s:%d",
+                                         rv,
+                                         cf->conf_file->file.name.data,
+                                         cf->conf_file->line);
+                        } else {
+                            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                                         "%s %s in %s:%d",
+                                         name->data, rv,
+                                         cf->conf_file->file.name.data,
+                                         cf->conf_file->line);
+                        }
 
                         return NGX_CONF_ERROR;
                     }
@@ -430,7 +439,7 @@ ngx_log_debug(cf->log, "FOUND %d:'%s'" _
 }
 
 
-char *ngx_conf_set_flag_slot(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
+char *ngx_conf_set_flag_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     int         flag;
     ngx_str_t  *value;
@@ -457,13 +466,13 @@ char *ngx_conf_set_flag_slot(ngx_conf_t 
 }
 
 
-char *ngx_conf_set_str_slot(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
+char *ngx_conf_set_str_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     ngx_str_t  *field, *value;
 
     field = (ngx_str_t *) (conf + cmd->offset);
 
-    if (field->len > 0) {
+    if (field->data) {
         return "is duplicate";
     }
 
@@ -476,7 +485,7 @@ char *ngx_conf_set_str_slot(ngx_conf_t *
 }
 
 
-char *ngx_conf_set_num_slot(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
+char *ngx_conf_set_num_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     int         num, len;
     ngx_str_t  *value;
@@ -500,7 +509,7 @@ char *ngx_conf_set_num_slot(ngx_conf_t *
 }
 
 
-char *ngx_conf_set_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
+char *ngx_conf_set_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     int         size, len, scale;
     char        last;
@@ -545,7 +554,7 @@ char *ngx_conf_set_size_slot(ngx_conf_t 
 }
 
 
-char *ngx_conf_set_msec_slot(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
+char *ngx_conf_set_msec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     int         size, total, len, scale;
     u_int       max, i;
@@ -640,7 +649,7 @@ char *ngx_conf_set_msec_slot(ngx_conf_t 
 }
 
 
-char *ngx_conf_set_sec_slot(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
+char *ngx_conf_set_sec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     int         size, total, len, scale;
     u_int       max, i;
@@ -747,7 +756,7 @@ char *ngx_conf_set_sec_slot(ngx_conf_t *
 }
 
 
-char *ngx_conf_unsupported(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
+char *ngx_conf_unsupported(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     return "unsupported on this platform";
 }
--- a/src/core/ngx_conf_file.h
+++ b/src/core/ngx_conf_file.h
@@ -40,9 +40,14 @@
 #define NGX_CONF_BLOCK_DONE  1
 #define NGX_CONF_FILE_DONE   2
 
+#define NGX_MODULE           0, 0
 
-#define NGX_CORE_MODULE_TYPE 0x45524F43  /* "CORE" */
-#define NGX_CONF_MODULE_TYPE 0x464E4F43  /* "CONF" */
+#define NGX_CORE_MODULE      0x45524F43  /* "CORE" */
+#define NGX_CONF_MODULE      0x464E4F43  /* "CONF" */
+
+
+#define MAX_CONF_ERRSTR      256
+extern  char ngx_conf_errstr[MAX_CONF_ERRSTR];
 
 
 typedef struct ngx_conf_s  ngx_conf_t;
@@ -52,16 +57,18 @@ typedef struct ngx_command_s  ngx_comman
 struct ngx_command_s {
     ngx_str_t  name;
     int        type;
-    char    *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, char *conf);
+    char    *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
     int        conf;
     int        offset;
     void      *bounds;
 };
 
+#define ngx_null_command   {ngx_null_string, 0, NULL, 0, 0, NULL}
 
 typedef struct {
+    int             ctx_index;
+    int             index;
     void           *ctx;
-    int             index;
     ngx_command_t  *commands;
     int             type;
     int           (*init_module)(ngx_pool_t *p);
@@ -129,6 +136,17 @@ struct ngx_conf_s {
         conf = (prev == (size_t) NGX_CONF_UNSET) ? default : prev;           \
     }
 
+#define ngx_conf_merge_str_value(conf, prev, default)                        \
+    if (conf.len == 0) {                                                     \
+        if (prev.len) {                                                      \
+            conf.len = prev.len;                                             \
+            conf.data = prev.data;                                           \
+        } else {                                                             \
+            conf.len = sizeof(default) - 1;                                  \
+            conf.data = default;                                             \
+        }                                                                    \
+    }
+
 
 #define addressof(addr)  ((int) &addr)
 
@@ -136,12 +154,12 @@ struct ngx_conf_s {
 char *ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename);
 
 
-char *ngx_conf_set_flag_slot(ngx_conf_t *cf, ngx_command_t *cmd, char *conf);
-char *ngx_conf_set_str_slot(ngx_conf_t *cf, ngx_command_t *cmd, char *conf);
-char *ngx_conf_set_num_slot(ngx_conf_t *cf, ngx_command_t *cmd, char *conf);
-char *ngx_conf_set_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, char *conf);
-char *ngx_conf_set_msec_slot(ngx_conf_t *cf, ngx_command_t *cmd, char *conf);
-char *ngx_conf_set_time_slot(ngx_conf_t *cf, ngx_command_t *cmd, char *conf);
+char *ngx_conf_set_flag_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
+char *ngx_conf_set_str_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
+char *ngx_conf_set_num_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
+char *ngx_conf_set_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
+char *ngx_conf_set_msec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
+char *ngx_conf_set_time_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
 
 
 extern ngx_module_t     *ngx_modules[];
--- a/src/core/ngx_connection.h
+++ b/src/core/ngx_connection.h
@@ -10,9 +10,9 @@
 #include <ngx_hunk.h>
 #include <ngx_array.h>
 #include <ngx_string.h>
-#endif
 
 #include <ngx_server.h>
+#endif
 
 #if 0
 typedef struct ngx_connection_s  ngx_connection_t;
@@ -35,7 +35,7 @@ struct ngx_connection_s {
 
     void            (*handler)(ngx_connection_t *c);
     void             *ctx;
-    ngx_server_t     *servers;
+    void             *servers;
 
     ngx_log_t        *log;
 
@@ -114,7 +114,6 @@ ngx_chain_t *ngx_write_chain(ngx_connect
 
 /* TODO: move it to OS specific file */
 #if (__FreeBSD__)
-ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in);
 ngx_chain_t *ngx_aio_write_chain(ngx_connection_t *c, ngx_chain_t *in);
 #endif
 
--- a/src/core/ngx_modules.c
+++ b/src/core/ngx_modules.c
@@ -30,6 +30,7 @@ extern ngx_module_t  ngx_http_output_fil
 extern ngx_module_t  ngx_http_header_filter_module;
 
 extern ngx_module_t  ngx_http_index_module;
+extern ngx_module_t  ngx_http_static_module;
 extern ngx_module_t  ngx_http_proxy_module;
 
 
@@ -68,9 +69,8 @@ ngx_module_t *ngx_modules[] = {
     /* &ngx_http_ssi_filter_module, */
 
     &ngx_http_index_module,
-/*
-    &ngx_http_proxy_module,
-*/
+    /* &ngx_http_static_module, */
+    /* &ngx_http_proxy_module, */
 
     NULL
 };
--- a/src/event/modules/ngx_aio_module.c
+++ b/src/event/modules/ngx_aio_module.c
@@ -29,7 +29,6 @@ ngx_os_io_t ngx_os_aio = {
 static ngx_str_t      aio_name = ngx_string("aio");
 
 ngx_event_module_t  ngx_aio_module_ctx = {
-    NGX_EVENT_MODULE,
     &aio_name,
     NULL,                                  /* create configuration */
     NULL,                                  /* init configuration */
@@ -49,10 +48,10 @@ ngx_event_module_t  ngx_aio_module_ctx =
 };
 
 ngx_module_t  ngx_aio_module = {
+    NGX_MODULE,
     &ngx_aio_module_ctx,                   /* module context */
-    0,                                     /* module index */
     NULL,                                  /* module directives */
-    NGX_EVENT_MODULE_TYPE,                 /* module type */
+    NGX_EVENT_MODULE,                      /* module type */
     NULL                                   /* init module */
 };
 
--- a/src/event/modules/ngx_devpoll_module.c
+++ b/src/event/modules/ngx_devpoll_module.c
@@ -72,12 +72,11 @@ static ngx_command_t  ngx_devpoll_comman
      offsetof(ngx_devpoll_conf_t, events),
      NULL},
 
-    {ngx_string(""), 0, NULL, 0, 0, NULL}
+    ngx_null_command
 };
 
 
 ngx_event_module_t  ngx_devpoll_module_ctx = {
-    NGX_EVENT_MODULE,
     &devpoll_name,
     ngx_devpoll_create_conf,               /* create configuration */
     ngx_devpoll_init_conf,                 /* init configuration */
@@ -97,10 +96,10 @@ ngx_event_module_t  ngx_devpoll_module_c
 };
 
 ngx_module_t  ngx_devpoll_module = {
+    NGX_MODULE,
     &ngx_devpoll_module_ctx,               /* module context */
-    0,                                     /* module index */
     ngx_devpoll_commands,                  /* module directives */
-    NGX_EVENT_MODULE_TYPE,                 /* module type */
+    NGX_EVENT_MODULE,                      /* module type */
     NULL                                   /* init module */
 };
 
@@ -109,7 +108,7 @@ static int ngx_devpoll_init(ngx_log_t *l
 {
     ngx_devpoll_conf_t  *dpcf;
 
-    dpcf = ngx_event_get_conf(ngx_devpoll_module_ctx);
+    dpcf = ngx_event_get_conf(ngx_devpoll_module);
 
 ngx_log_debug(log, "CH: %d" _ dpcf->changes);
 ngx_log_debug(log, "EV: %d" _ dpcf->events);
@@ -194,7 +193,7 @@ static int ngx_devpoll_del_event(ngx_eve
     ngx_event_t  *e;
 
 #if (NGX_DEBUG_EVENT)
-    ngx_connection_t *c = (ngx_connection_t *) ev->data;
+    ngx_connection_t *c = ev->data;
     ngx_log_debug(c->log, "del event: %d, %d" _ c->fd _ event);
 #endif
 
@@ -229,7 +228,7 @@ static int ngx_devpoll_del_event(ngx_eve
 
 static int ngx_devpoll_set_event(ngx_event_t *ev, int event, u_int flags)
 {
-    int  n;
+    int                n;
     ngx_connection_t  *c;
 
     c = ev->data;
--- a/src/event/modules/ngx_kqueue_module.c
+++ b/src/event/modules/ngx_kqueue_module.c
@@ -47,12 +47,11 @@ static ngx_command_t  ngx_kqueue_command
      offsetof(ngx_kqueue_conf_t, events),
      NULL},
 
-    {ngx_string(""), 0, NULL, 0, 0, NULL}
+    ngx_null_command
 };
 
 
 ngx_event_module_t  ngx_kqueue_module_ctx = {
-    NGX_EVENT_MODULE,
     &kqueue_name,
     ngx_kqueue_create_conf,                /* create configuration */
     ngx_kqueue_init_conf,                  /* init configuration */
@@ -72,10 +71,10 @@ ngx_event_module_t  ngx_kqueue_module_ct
 };
 
 ngx_module_t  ngx_kqueue_module = {
+    NGX_MODULE,
     &ngx_kqueue_module_ctx,                /* module context */
-    0,                                     /* module index */
     ngx_kqueue_commands,                   /* module directives */
-    NGX_EVENT_MODULE_TYPE,                 /* module type */
+    NGX_EVENT_MODULE,                      /* module type */
     NULL                                   /* init module */
 };
 
@@ -84,7 +83,7 @@ static int ngx_kqueue_init(ngx_log_t *lo
 {
     ngx_kqueue_conf_t  *kcf;
 
-    kcf = ngx_event_get_conf(ngx_kqueue_module_ctx);
+    kcf = ngx_event_get_conf(ngx_kqueue_module);
 
 ngx_log_debug(log, "CH: %d" _ kcf->changes);
 ngx_log_debug(log, "EV: %d" _ kcf->events);
--- a/src/event/modules/ngx_kqueue_module.h
+++ b/src/event/modules/ngx_kqueue_module.h
@@ -8,8 +8,9 @@ typedef struct {
 } ngx_kqueue_conf_t;
 
 
-extern int  ngx_kqueue;
-/* STUB */ extern ngx_event_module_t  ngx_kqueue_module_ctx;
+extern int                 ngx_kqueue;
+extern ngx_module_t        ngx_kqueue_module;
+extern ngx_event_module_t  ngx_kqueue_module_ctx;
 
 
 
--- a/src/event/modules/ngx_poll_module.c
+++ b/src/event/modules/ngx_poll_module.c
@@ -27,7 +27,6 @@ static ngx_event_t   **ready_index;
 static ngx_str_t    poll_name = ngx_string("poll");
 
 ngx_event_module_t  ngx_poll_module_ctx = {
-    NGX_EVENT_MODULE,
     &poll_name,
     NULL,                                  /* create configuration */
     NULL,                                  /* init configuration */
@@ -47,10 +46,10 @@ ngx_event_module_t  ngx_poll_module_ctx 
 };
 
 ngx_module_t  ngx_poll_module = {
+    NGX_MODULE,
     &ngx_poll_module_ctx,                  /* module context */
-    0,                                     /* module index */
     NULL,                                  /* module directives */
-    NGX_EVENT_MODULE_TYPE,                 /* module type */
+    NGX_EVENT_MODULE,                      /* module type */
     NULL                                   /* init module */
 };
 
@@ -60,7 +59,7 @@ static int ngx_poll_init(ngx_log_t *log)
 {
     ngx_event_conf_t  *ecf;
 
-    ecf = ngx_event_get_conf(ngx_event_module_ctx);
+    ecf = ngx_event_get_conf(ngx_event_module);
 
     ngx_test_null(event_list,
                   ngx_alloc(sizeof(struct pollfd) * ecf->connections, log),
--- a/src/event/modules/ngx_select_module.c
+++ b/src/event/modules/ngx_select_module.c
@@ -40,7 +40,6 @@ static ngx_event_t  **ready_index;
 static ngx_str_t    select_name = ngx_string("select");
 
 ngx_event_module_t  ngx_select_module_ctx = {
-    NGX_EVENT_MODULE,
     &select_name,
     NULL,                                  /* create configuration */
     ngx_select_init_conf,                  /* init configuration */
@@ -60,10 +59,10 @@ ngx_event_module_t  ngx_select_module_ct
 };
 
 ngx_module_t  ngx_select_module = {
+    NGX_MODULE,
     &ngx_select_module_ctx,                /* module context */
-    0,                                     /* module index */
     NULL,                                  /* module directives */
-    NGX_EVENT_MODULE_TYPE,                 /* module type */
+    NGX_EVENT_MODULE,                      /* module type */
     NULL                                   /* init module */
 };
 
@@ -72,7 +71,7 @@ static int ngx_select_init(ngx_log_t *lo
 {
     ngx_event_conf_t  *ecf;
 
-    ecf = ngx_event_get_conf(ngx_event_module_ctx);
+    ecf = ngx_event_get_conf(ngx_event_module);
 
     FD_ZERO(&master_read_fd_set);
     FD_ZERO(&master_write_fd_set);
@@ -378,7 +377,7 @@ static char *ngx_select_init_conf(ngx_po
 {
     ngx_event_conf_t  *ecf;
 
-    ecf = ngx_event_get_conf(ngx_event_module_ctx);
+    ecf = ngx_event_get_conf(ngx_event_module);
 
     if (ecf->connections > FD_SETSIZE) {
         return "maximum number of connections "
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -12,12 +12,11 @@
 extern ngx_event_module_t ngx_select_module_ctx;
 
 #if (HAVE_KQUEUE)
-extern ngx_event_module_t ngx_kqueue_module_ctx;
 #include <ngx_kqueue_module.h>
 #endif
 
 #if (HAVE_DEVPOLL)
-extern ngx_event_module_t ngx_devpoll_module_ctx;
+extern ngx_module_t ngx_devpoll_module;
 #endif
 
 #if (HAVE_AIO)
@@ -30,8 +29,8 @@ extern ngx_event_module_t ngx_devpoll_mo
 #endif
 
 
-static char *ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy);
-static char *ngx_event_use(ngx_conf_t *cf, ngx_command_t *cmd, char *conf);
+static char *ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
+static char *ngx_event_use(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
 static void *ngx_event_create_conf(ngx_pool_t *pool);
 static char *ngx_event_init_conf(ngx_pool_t *pool, void *conf);
 
@@ -61,15 +60,15 @@ static ngx_command_t  ngx_events_command
      0,
      NULL},
 
-    {ngx_string(""), 0, NULL, 0, 0, NULL}
+    ngx_null_command
 };
 
 
 ngx_module_t  ngx_events_module = {
+    NGX_MODULE,
     &events_name,                          /* module context */
-    0,                                     /* module index */
     ngx_events_commands,                   /* module directives */
-    NGX_CORE_MODULE_TYPE,                  /* module type */
+    NGX_CORE_MODULE,                       /* module type */
     NULL                                   /* init module */
 };
 
@@ -98,12 +97,11 @@ static ngx_command_t  ngx_event_commands
      offsetof(ngx_event_conf_t, timer_queues),
      NULL},
 
-    {ngx_string(""), 0, NULL, 0, 0, NULL}
+    ngx_null_command
 };
 
 
 ngx_event_module_t  ngx_event_module_ctx = {
-    NGX_EVENT_MODULE,
     &event_name,
     ngx_event_create_conf,                 /* create configuration */
     ngx_event_init_conf,                   /* init configuration */
@@ -113,10 +111,10 @@ ngx_event_module_t  ngx_event_module_ctx
 
 
 ngx_module_t  ngx_event_module = {
+    NGX_MODULE,
     &ngx_event_module_ctx,                 /* module context */
-    0,                                     /* module index */
     ngx_event_commands,                    /* module directives */
-    NGX_EVENT_MODULE_TYPE,                 /* module type */
+    NGX_EVENT_MODULE,                      /* module type */
     NULL                                   /* init module */
 };
 
@@ -132,18 +130,18 @@ int ngx_pre_thread(ngx_array_t *ls, ngx_
     ngx_event_conf_t  *ecf;
     ngx_event_module_t  *module;
 
-    ecf = ngx_event_get_conf(ngx_event_module_ctx);
+    ecf = ngx_event_get_conf(ngx_event_module);
 
 ngx_log_debug(log, "CONN: %d" _ ecf->connections);
 ngx_log_debug(log, "TYPE: %d" _ ecf->use);
 
     for (m = 0; ngx_modules[m]; m++) {
-        if (ngx_modules[m]->type != NGX_EVENT_MODULE_TYPE) {
+        if (ngx_modules[m]->type != NGX_EVENT_MODULE) {
             continue;
         }
 
-        module = ngx_modules[m]->ctx;
-        if (module->index == ecf->use) {
+        if (ngx_modules[m]->ctx_index == ecf->use) {
+            module = ngx_modules[m]->ctx;
             if (module->actions.init(log) == NGX_ERROR) {
                 return NGX_ERROR;
             }
@@ -247,7 +245,7 @@ void ngx_worker(ngx_log_t *log)
 }
 
 
-static char *ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
+static char *ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     int                    m;
     char                  *rv;
@@ -259,12 +257,11 @@ static char *ngx_events_block(ngx_conf_t
 
     ngx_event_max_module = 0;
     for (m = 0; ngx_modules[m]; m++) {
-        if (ngx_modules[m]->type != NGX_EVENT_MODULE_TYPE) {
+        if (ngx_modules[m]->type != NGX_EVENT_MODULE) {
             continue;
         }
 
-        module = ngx_modules[m]->ctx;
-        module->index = ngx_event_max_module++;
+        ngx_modules[m]->ctx_index = ngx_event_max_module++;
     }
 
     ngx_test_null(ctx, ngx_pcalloc(cf->pool, sizeof(void *)), NGX_CONF_ERROR);
@@ -276,21 +273,22 @@ static char *ngx_events_block(ngx_conf_t
     *(void **) conf = ctx;
 
     for (m = 0; ngx_modules[m]; m++) {
-        if (ngx_modules[m]->type != NGX_EVENT_MODULE_TYPE) {
+        if (ngx_modules[m]->type != NGX_EVENT_MODULE) {
             continue;
         }
 
         module = ngx_modules[m]->ctx;
 
         if (module->create_conf) {
-            ngx_test_null((*ctx)[module->index], module->create_conf(cf->pool),
+            ngx_test_null((*ctx)[ngx_modules[m]->ctx_index],
+                          module->create_conf(cf->pool),
                           NGX_CONF_ERROR);
         }
     }
 
     pcf = *cf;
     cf->ctx = ctx;
-    cf->module_type = NGX_EVENT_MODULE_TYPE;
+    cf->module_type = NGX_EVENT_MODULE;
     cf->cmd_type = NGX_EVENT_CONF;
     rv = ngx_conf_parse(cf, NULL);
     *cf = pcf;
@@ -299,14 +297,14 @@ static char *ngx_events_block(ngx_conf_t
         return rv;
 
     for (m = 0; ngx_modules[m]; m++) {
-        if (ngx_modules[m]->type != NGX_EVENT_MODULE_TYPE) {
+        if (ngx_modules[m]->type != NGX_EVENT_MODULE) {
             continue;
         }
 
         module = ngx_modules[m]->ctx;
 
         if (module->init_conf) {
-            rv = module->init_conf(cf->pool, (*ctx)[module->index]);
+            rv = module->init_conf(cf->pool, (*ctx)[ngx_modules[m]->ctx_index]);
             if (rv != NGX_CONF_OK) {
                 return rv;
             }
@@ -317,9 +315,9 @@ static char *ngx_events_block(ngx_conf_t
 }
 
 
-static char *ngx_event_use(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
+static char *ngx_event_use(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
-    ngx_event_conf_t *ecf = (ngx_event_conf_t *) conf;
+    ngx_event_conf_t  *ecf = conf;
 
     int                   m;
     ngx_str_t            *args;
@@ -332,14 +330,14 @@ static char *ngx_event_use(ngx_conf_t *c
     args = cf->args->elts;
 
     for (m = 0; ngx_modules[m]; m++) {
-        if (ngx_modules[m]->type != NGX_EVENT_MODULE_TYPE) {
+        if (ngx_modules[m]->type != NGX_EVENT_MODULE) {
             continue;
         }
 
         module = ngx_modules[m]->ctx;
         if (module->name->len == args[1].len) {
             if (ngx_strcmp(module->name->data, args[1].data) == 0) {
-                ecf->use = module->index;
+                ecf->use = ngx_modules[m]->ctx_index;
                 return NGX_CONF_OK;
             }
         }
@@ -380,19 +378,19 @@ static char *ngx_event_init_conf(ngx_poo
 #endif
 
     ngx_conf_init_value(ecf->connections, DEF_CONNECTIONS);
-    ngx_conf_init_value(ecf->use, ngx_kqueue_module_ctx.index);
+    ngx_conf_init_value(ecf->use, ngx_kqueue_module.ctx_index);
 
 #elif (HAVE_DEVPOLL)
 
     ngx_conf_init_value(ecf->connections, DEF_CONNECTIONS);
-    ngx_conf_init_value(ecf->use, ngx_devpoll_module_ctx.index);
+    ngx_conf_init_value(ecf->use, ngx_devpoll_module.ctx_index);
 
 #else /* HAVE_SELECT */
 
     ngx_conf_init_value(ecf->connections,
                   FD_SETSIZE < DEF_CONNECTIONS ? FD_SETSIZE : DEF_CONNECTIONS);
 
-    ngx_conf_init_value(ecf->use, ngx_select_module_ctx.index);
+    ngx_conf_init_value(ecf->use, ngx_select_module.ctx_index);
 
 #endif
 
--- a/src/event/ngx_event.h
+++ b/src/event/ngx_event.h
@@ -17,9 +17,6 @@
 
 
 
-/* STUB */
-#define NGX_LOWAT   10000
-
 #define NGX_INVALID_INDEX  0x80000000
 
 
@@ -319,10 +316,9 @@ extern int                   ngx_event_f
 #endif
 
 
-#define NGX_EVENT_MODULE_TYPE 0x544E5645  /* "EVNT" */
+#define NGX_EVENT_MODULE      0x544E5645  /* "EVNT" */
 
 #define NGX_EVENT_CONF        0x00200000
-#define NGX_EVENT_MODULE      0
 
 
 typedef struct {
@@ -333,7 +329,6 @@ typedef struct {
 
 
 typedef struct {
-    int                     index;
     ngx_str_t              *name;
 
     void                 *(*create_conf)(ngx_pool_t *p);
@@ -344,11 +339,11 @@ typedef struct {
 
 
 extern ngx_module_t        ngx_events_module;
-extern ngx_event_module_t  ngx_event_module_ctx;
+extern ngx_module_t        ngx_event_module;
 
 
 #define ngx_event_get_conf(module)                                           \
-                          (*(ngx_get_conf(ngx_events_module))) [module.index];
+                     (*(ngx_get_conf(ngx_events_module))) [module.ctx_index];
 
 
 
--- a/src/event/ngx_event_accept.c
+++ b/src/event/ngx_event_accept.c
@@ -162,6 +162,6 @@ void ngx_event_accept(ngx_event_t *ev)
         }
 
     } while (ev->available);
-  
+
     return;
 }
--- a/src/event/ngx_event_timer.c
+++ b/src/event/ngx_event_timer.c
@@ -20,7 +20,7 @@ int ngx_event_timer_init(ngx_log_t *log)
     int                i;
     ngx_event_conf_t  *ecf;
 
-    ecf = ngx_event_get_conf(ngx_event_module_ctx);
+    ecf = ngx_event_get_conf(ngx_event_module);
 
     ngx_timer_queue_num = ecf->timer_queues;
     ngx_timer_cur_queue = 0;
--- a/src/http/modules/ngx_http_index_handler.c
+++ b/src/http/modules/ngx_http_index_handler.c
@@ -1,25 +1,14 @@
 
-#include <ngx_config.h>
-
-#include <ngx_core.h>
-#include <ngx_errno.h>
-#include <ngx_string.h>
-#include <ngx_files.h>
-#include <ngx_conf_file.h>
-
-#include <ngx_http.h>
-#include <ngx_http_config.h>
-#include <ngx_http_core_module.h>
 #include <ngx_http_index_handler.h>
 
 
 static int ngx_http_index_test_dir(ngx_http_request_t *r);
 static int ngx_http_index_init(ngx_pool_t *pool);
 static void *ngx_http_index_create_conf(ngx_pool_t *pool);
-static char *ngx_http_index_merge_conf(ngx_pool_t *p,
-                                       void *parent, void *child);
+static char *ngx_http_index_merge_conf(ngx_pool_t *p, void *parent,
+                                                                  void *child);
 static char *ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd,
-                                      char *conf);
+                                                                   void *conf);
 
 
 static ngx_command_t ngx_http_index_commands[] = {
@@ -31,13 +20,11 @@ static ngx_command_t ngx_http_index_comm
      0,
      NULL},
 
-    {ngx_string(""), 0, NULL, 0, 0, NULL}
+    ngx_null_command
 };
 
 
 ngx_http_module_t  ngx_http_index_module_ctx = {
-    NGX_HTTP_MODULE,
-
     NULL,                                  /* create main configuration */
     NULL,                                  /* init main configuration */
 
@@ -50,10 +37,10 @@ ngx_http_module_t  ngx_http_index_module
 
 
 ngx_module_t  ngx_http_index_module = {
+    NGX_MODULE,
     &ngx_http_index_module_ctx,            /* module context */
-    0,                                     /* module index */
     ngx_http_index_commands,               /* module directives */
-    NGX_HTTP_MODULE_TYPE,                  /* module type */
+    NGX_HTTP_MODULE,                       /* module type */
     ngx_http_index_init                    /* init module */
 };
 
@@ -63,42 +50,39 @@ ngx_module_t  ngx_http_index_module = {
    because the valid requests should be many more then invalid ones.
    If open() failed then stat() should be more quickly because some data
    is already cached in the kernel.
-   Besides Win32 has ERROR_PATH_NOT_FOUND (NGX_ENOTDIR) and
-   Unix has ENOTDIR error (although it less helpfull).
+   Besides Win32 has ERROR_PATH_NOT_FOUND (NGX_ENOTDIR).
+   Unix has ENOTDIR error, although it less helpfull - it shows only
+   that path contains the usual file in place of the directory.
 */
 
 int ngx_http_index_handler(ngx_http_request_t *r)
 {
-    int          i, rc, test_dir;
-    char        *name, *file;
-    ngx_str_t    loc, *index;
-    ngx_err_t    err;
-    ngx_fd_t     fd;
+    int                        i, rc, test_dir;
+    char                      *name, *file;
+    ngx_str_t                  loc, *index;
+    ngx_err_t                  err;
+    ngx_fd_t                   fd;
+    ngx_http_index_conf_t     *icf;
+    ngx_http_core_loc_conf_t  *clcf;
 
-    ngx_http_index_conf_t     *cf;
-    ngx_http_core_loc_conf_t  *core_cf;
-
-    cf = (ngx_http_index_conf_t *)
-                    ngx_http_get_module_loc_conf(r, ngx_http_index_module_ctx);
-
-    core_cf = (ngx_http_core_loc_conf_t *)
-                     ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx);
+    icf = ngx_http_get_module_loc_conf(r, ngx_http_index_module);
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
     ngx_test_null(r->path.data,
                   ngx_palloc(r->pool,
-                             core_cf->doc_root.len + r->uri.len
-                             + cf->max_index_len),
+                             clcf->doc_root.len + r->uri.len
+                             + icf->max_index_len),
                   NGX_HTTP_INTERNAL_SERVER_ERROR);
 
-    loc.data = ngx_cpystrn(r->path.data, core_cf->doc_root.data,
-                           core_cf->doc_root.len + 1);
+    loc.data = ngx_cpystrn(r->path.data, clcf->doc_root.data,
+                           clcf->doc_root.len + 1);
     file = ngx_cpystrn(loc.data, r->uri.data, r->uri.len + 1);
     r->path.len = file - r->path.data;
 
     test_dir = 1;
 
-    index = (ngx_str_t *) cf->indices->elts;
-    for (i = 0; i < cf->indices->nelts; i++) {
+    index = (ngx_str_t *) icf->indices.elts;
+    for (i = 0; i < icf->indices.nelts; i++) {
 
         if (index[i].data[0] != '/') {
             ngx_memcpy(file, index[i].data, index[i].len + 1);
@@ -147,8 +131,8 @@ ngx_log_error(NGX_LOG_DEBUG, r->connecti
             return NGX_HTTP_INTERNAL_SERVER_ERROR;
         }
 
-        r->file.name.data = name; 
-        r->file.fd = fd; 
+        r->file.name.data = name;
+        r->file.fd = fd;
 
         if (index[i].data[0] == '/') {
             r->file.name.len = index[i].len;
@@ -157,7 +141,7 @@ ngx_log_error(NGX_LOG_DEBUG, r->connecti
 
         } else {
             loc.len = r->uri.len + index[i].len;
-            r->file.name.len = core_cf->doc_root.len + r->uri.len
+            r->file.name.len = clcf->doc_root.len + r->uri.len
                                + index[i].len;
         }
 
@@ -178,9 +162,9 @@ static int ngx_http_index_test_dir(ngx_h
 ngx_log_debug(r->connection->log, "IS_DIR: %s" _ r->path.data);
 
 #if 0
-        if (r->path_err == NGX_EACCES) {
-            return NGX_HTTP_FORBIDDEN;
-        }
+    if (r->path_err == NGX_EACCES) {
+        return NGX_HTTP_FORBIDDEN;
+    }
 #endif
 
     if (ngx_file_type(r->path.data, &r->file.info) == -1) {
@@ -226,76 +210,88 @@ static void *ngx_http_index_create_conf(
 {
     ngx_http_index_conf_t  *conf;
 
-    ngx_test_null(conf, ngx_pcalloc(pool, sizeof(ngx_http_index_conf_t)),
+    ngx_test_null(conf, ngx_palloc(pool, sizeof(ngx_http_index_conf_t)),
                   NGX_CONF_ERROR);
 
-    ngx_test_null(conf->indices,
-                  ngx_create_array(pool, 3, sizeof(ngx_str_t)),
-                  NGX_CONF_ERROR);
+    ngx_init_array(conf->indices, pool, 3, sizeof(ngx_str_t), NGX_CONF_ERROR);
+    conf->max_index_len = 0;
 
     return conf;
 }
 
 
-/* STUB */
+/* TODO: remove duplicate indices */
+
 static char *ngx_http_index_merge_conf(ngx_pool_t *p, void *parent, void *child)
 {
-#if 0
-    ngx_http_index_conf_t *prev = (ngx_http_index_conf_t *) parent;
-#endif
-    ngx_http_index_conf_t *conf = (ngx_http_index_conf_t *) child;
-    ngx_str_t  *index;
+    ngx_http_index_conf_t *prev = parent;
+    ngx_http_index_conf_t *conf = child;
+
+    int         i;
+    ngx_str_t  *index, *prev_index;
 
     if (conf->max_index_len == 0) {
-        ngx_test_null(index, ngx_push_array(conf->indices), NGX_CONF_ERROR);
-        index->len = sizeof(NGX_HTTP_INDEX) - 1;
-        index->data = NGX_HTTP_INDEX;
-        conf->max_index_len = sizeof(NGX_HTTP_INDEX);
+        if (prev->max_index_len != 0) {
+            ngx_memcpy(conf, prev, sizeof(ngx_http_index_conf_t)); 
+            return NGX_CONF_OK;
+        }
+
+        ngx_test_null(index, ngx_push_array(&conf->indices), NGX_CONF_ERROR);
+        index->len = sizeof(NGX_HTTP_DEFAULT_INDEX) - 1;
+        index->data = NGX_HTTP_DEFAULT_INDEX;
+        conf->max_index_len = sizeof(NGX_HTTP_DEFAULT_INDEX);
+
+        return NGX_CONF_OK;
     }
 
-    /* FAIL: if first index is started with '/' */
+    if (prev->max_index_len != 0) {
 
-    return NULL;
+        prev_index = prev->indices.elts;
+        for (i = 0; i < prev->indices.nelts; i++) {
+            ngx_test_null(index, ngx_push_array(&conf->indices),
+                          NGX_CONF_ERROR);
+            index->len = prev_index[i].len;
+            index->data = prev_index[i].data;
+        }
+    }
+
+    if (conf->max_index_len < prev->max_index_len) {
+        conf->max_index_len = prev->max_index_len;
+    }
+
+    return NGX_CONF_OK;
 }
 
 
-#if 0
-static char *ngx_http_index_merge_conf(ngx_pool_t *p, void *parent, void *child)
+/* TODO: check duplicate indices */
+
+static char *ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd,
+                                      void *conf)
 {
-    ngx_http_index_conf_t *prev = (ngx_http_index_conf_t *) parent;
-    ngx_http_index_conf_t *conf = (ngx_http_index_conf_t *) child;
-    ngx_str_t  *index;
+    ngx_http_index_conf_t *icf = conf;
+
+    int         i;
+    ngx_str_t  *index, *value;
+
+    value = cf->args->elts;
 
-    if (conf->max_index_len == 0) {
-        if (prev->max_index_len != 0) {
-            return prev;
+    if (value[1].data[0] == '/' && icf->indices.nelts == 0) {
+        ngx_snprintf(ngx_conf_errstr, sizeof(ngx_conf_errstr) - 1,
+                     "first index \"%s\" must not be absolute", value[1].data);
+        return ngx_conf_errstr;
+    }
+
+    for (i = 1; i < cf->args->nelts; i++) {
+        if (value[i].len == 0) {
+            return "is invalid";
         }
 
-        ngx_test_null(index, ngx_push_array(conf->indices), NULL);
-        index->len = sizeof(NGX_HTTP_INDEX) - 1;
-        index->data = NGX_HTTP_INDEX;
-        conf->max_index_len = sizeof(NGX_HTTP_INDEX);
-    }
-
-    return conf;
-}
-#endif
-
-static char *ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd,
-                                      char *conf)
-{
-    ngx_http_index_conf_t *lcf = (ngx_http_index_conf_t *) conf;
-    int  i;
-    ngx_str_t  *index, *value;
-
-    value = (ngx_str_t *) cf->args->elts;
-    for (i = 1; i < cf->args->nelts; i++) {
-        ngx_test_null(index, ngx_push_array(lcf->indices), NGX_CONF_ERROR);
+        ngx_test_null(index, ngx_push_array(&icf->indices), NGX_CONF_ERROR);
         index->len = value[i].len;
         index->data = value[i].data;
 
-        if (lcf->max_index_len < index->len) {
-            lcf->max_index_len = index->len;
+        if (icf->max_index_len < index->len + 1) {
+            icf->max_index_len = index->len + 1;
         }
     }
 
--- a/src/http/modules/ngx_http_index_handler.h
+++ b/src/http/modules/ngx_http_index_handler.h
@@ -3,16 +3,16 @@
 
 
 #include <ngx_config.h>
-#include <ngx_array.h>
+#include <ngx_core.h>
 #include <ngx_http.h>
 
 
-#define NGX_HTTP_INDEX   "index.html"
+#define NGX_HTTP_DEFAULT_INDEX   "index.html"
 
 
 typedef struct {
-    ngx_array_t  *indices;
-    size_t        max_index_len;
+    ngx_array_t  indices;
+    size_t       max_index_len;
 } ngx_http_index_conf_t;
 
 
--- a/src/http/modules/ngx_http_static_handler.c
+++ b/src/http/modules/ngx_http_static_handler.c
@@ -1,38 +1,22 @@
 
 #include <ngx_config.h>
 #include <ngx_core.h>
-#include <ngx_string.h>
-#include <ngx_file.h>
-#include <ngx_hunk.h>
 #include <ngx_http.h>
 #include <ngx_http_config.h>
 #include <ngx_http_core_module.h>
 #include <ngx_http_output_filter.h>
 
 
-ngx_http_module_t  ngx_http_static_module;
-
 
 int ngx_http_static_handler(ngx_http_request_t *r)
 {
-    int                  rc, key, i;
-    ngx_log_e            level;
-    ngx_err_t            err;
-    ngx_hunk_t          *h;
-    ngx_http_type_t     *type;
-    ngx_http_log_ctx_t  *ctx;
-    ngx_http_core_loc_conf_t  *core_lcf; 
-
-    core_lcf = (ngx_http_core_loc_conf_t *)
-                     ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx);
-
-#if 0
-    ngx_http_event_static_handler_loc_conf_t  *lcf;
-
-    lcf = (ngx_http_event_static_handler_loc_conf_t *)
-         ngx_get_module_loc_conf(r, &ngx_http_event_static_handler_module_ctx);
-
-#endif
+    int                        rc, key, i;
+    ngx_log_e                  level;
+    ngx_err_t                  err;
+    ngx_hunk_t                *h;
+    ngx_http_type_t           *type;
+    ngx_http_log_ctx_t        *ctx;
+    ngx_http_core_loc_conf_t  *clcf;
 
     rc = ngx_http_discard_body(r);
 
@@ -40,6 +24,10 @@ int ngx_http_static_handler(ngx_http_req
         return rc;
     }
 
+    if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) {
+        return NGX_HTTP_NOT_ALLOWED;
+    }
+
     ctx = r->connection->log->data;
     ctx->action = "sending response";
 
@@ -102,14 +90,18 @@ int ngx_http_static_handler(ngx_http_req
                   ngx_push_table(r->headers_out.headers),
                   NGX_HTTP_INTERNAL_SERVER_ERROR);
 
-    r->headers_out.content_type->key.len = 12;
-    r->headers_out.content_type->key.data = "Content-Type";
+    r->headers_out.content_type->key.len = 0;
+    r->headers_out.content_type->key.data = NULL;
+    r->headers_out.content_type->value.len = 0;
+    r->headers_out.content_type->value.data = NULL;
+
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
     if (r->exten.len) {
         ngx_http_types_hash_key(key, r->exten);
 
-        type = (ngx_http_type_t *) core_lcf->types[key].elts;
-        for (i = 0; i < core_lcf->types[key].nelts; i++) {
+        type = (ngx_http_type_t *) clcf->types[key].elts;
+        for (i = 0; i < clcf->types[key].nelts; i++) {
             if (r->exten.len != type[i].exten.len) {
                 continue;
             }
@@ -117,14 +109,15 @@ int ngx_http_static_handler(ngx_http_req
             if (ngx_strcasecmp(r->exten.data, type[i].exten.data) == 0) {
                 r->headers_out.content_type->value.len = type[i].type.len;
                 r->headers_out.content_type->value.data = type[i].type.data;
+
+                break;
             }
         }
     }
 
     if (r->headers_out.content_type->value.len == 0) {
-        /* STUB: default type */
-        r->headers_out.content_type->value.len = 25;
-        r->headers_out.content_type->value.data = "text/html; charset=koi8-r";
+        r->headers_out.content_type->value.len = clcf->default_type.len;
+        r->headers_out.content_type->value.data = clcf->default_type.data;
     }
 
     /* we need to allocate all before the header would be sent */
@@ -134,9 +127,19 @@ int ngx_http_static_handler(ngx_http_req
     ngx_test_null(h->file, ngx_pcalloc(r->pool, sizeof(ngx_file_t)),
                   NGX_HTTP_INTERNAL_SERVER_ERROR);
 
-    ngx_http_send_header(r);
-    if (r->header_only)
+
+    rc = ngx_http_send_header(r);
+
+    if (r->header_only) {
+        if (rc == NGX_AGAIN) {
+            ngx_http_set_write_handler(r);
+
+        } else {
+            ngx_http_finalize_request(r, 0);
+        }
+
         return NGX_OK;
+    }
 
 
     h->type = NGX_HUNK_FILE|NGX_HUNK_LAST;
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -11,7 +11,7 @@
 
 
 static void ngx_http_init_filters(ngx_pool_t *pool, ngx_module_t **modules);
-static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy);
+static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
 
 
 int  ngx_http_max_module;
@@ -37,20 +37,20 @@ static ngx_command_t  ngx_http_commands[
      0,
      NULL},
 
-    {ngx_string(""), 0, NULL, 0, 0, NULL}
+    ngx_null_command
 };
 
 
 ngx_module_t  ngx_http_module = {
+    NGX_MODULE,
     &http_name,                            /* module context */
-    0,                                     /* module index */
     ngx_http_commands,                     /* module directives */
-    NGX_CORE_MODULE_TYPE,                  /* module type */
+    NGX_CORE_MODULE,                       /* module type */
     NULL                                   /* init module */
 };
 
 
-static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
+static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     int                          mi, m, s, l, p, a, n;
     int                          port_found, addr_found, virtual_names;
@@ -81,12 +81,11 @@ static char *ngx_http_block(ngx_conf_t *
 
     ngx_http_max_module = 0;
     for (m = 0; ngx_modules[m]; m++) {
-        if (ngx_modules[m]->type != NGX_HTTP_MODULE_TYPE) {
+        if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
             continue;
         }
 
-        module = (ngx_http_module_t *) ngx_modules[m]->ctx;
-        module->index = ngx_http_max_module++;
+        ngx_modules[m]->ctx_index = ngx_http_max_module++;
     }
 
     /* the main http main_conf, it's the same in the all http contexts */
@@ -108,26 +107,27 @@ static char *ngx_http_block(ngx_conf_t *
     /* create the main_conf, srv_conf and loc_conf in all http modules */
 
     for (m = 0; ngx_modules[m]; m++) {
-        if (ngx_modules[m]->type != NGX_HTTP_MODULE_TYPE) {
+        if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
             continue;
         }
 
-        module = (ngx_http_module_t *) ngx_modules[m]->ctx;
+        module = ngx_modules[m]->ctx;
+        mi = ngx_modules[m]->ctx_index;
 
         if (module->create_main_conf) {
-            ngx_test_null(ctx->main_conf[module->index],
+            ngx_test_null(ctx->main_conf[mi],
                           module->create_main_conf(cf->pool),
                           NGX_CONF_ERROR);
         }
 
         if (module->create_srv_conf) {
-            ngx_test_null(ctx->srv_conf[module->index],
+            ngx_test_null(ctx->srv_conf[mi],
                           module->create_srv_conf(cf->pool),
                           NGX_CONF_ERROR);
         }
 
         if (module->create_loc_conf) {
-            ngx_test_null(ctx->loc_conf[module->index],
+            ngx_test_null(ctx->loc_conf[mi],
                           module->create_loc_conf(cf->pool),
                           NGX_CONF_ERROR);
         }
@@ -138,7 +138,7 @@ static char *ngx_http_block(ngx_conf_t *
 
     pcf = *cf;
     cf->ctx = ctx;
-    cf->module_type = NGX_HTTP_MODULE_TYPE;
+    cf->module_type = NGX_HTTP_MODULE;
     cf->cmd_type = NGX_HTTP_MAIN_CONF;
     rv = ngx_conf_parse(cf, NULL);
     *cf = pcf;
@@ -150,16 +150,16 @@ static char *ngx_http_block(ngx_conf_t *
     /* init http{} main_conf's, merge the server{}s' srv_conf's
        and its location{}s' loc_conf's */
 
-    cmcf = ctx->main_conf[ngx_http_core_module_ctx.index];
+    cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
     cscfp = (ngx_http_core_srv_conf_t **)cmcf->servers.elts;
 
     for (m = 0; ngx_modules[m]; m++) {
-        if (ngx_modules[m]->type != NGX_HTTP_MODULE_TYPE) {
+        if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
             continue;
         }
 
         module = (ngx_http_module_t *) ngx_modules[m]->ctx;
-        mi = module->index;
+        mi = ngx_modules[m]->ctx_index;
 
         /* init http{} main_conf's */
 
@@ -310,7 +310,7 @@ static char *ngx_http_block(ngx_conf_t *
                                        sizeof(ngx_http_in_addr_t));
 
                             in_addr[a].addr = lscf[l].addr;
-                            in_addr[a].flags = lscf[l].flags;   
+                            in_addr[a].flags = lscf[l].flags;
                             in_addr[a].core_srv_conf = cscfp[s];
 
                             /* create the empty list of the server names that
@@ -336,7 +336,7 @@ static char *ngx_http_block(ngx_conf_t *
                                       NGX_CONF_ERROR);
 
                         inaddr->addr = lscf[l].addr;
-                        inaddr->flags = lscf[l].flags;   
+                        inaddr->flags = lscf[l].flags;
                         inaddr->core_srv_conf = cscfp[s];
 
                         /* create the empty list of the server names that
@@ -359,6 +359,12 @@ static char *ngx_http_block(ngx_conf_t *
 
                 in_port->port = lscf[l].port;
 
+                ngx_test_null(in_port->port_name.data, ngx_palloc(cf->pool, 7),
+                              NGX_CONF_ERROR);
+                in_port->port_name.len = ngx_snprintf(in_port->port_name.data,
+                                                      7, ":%d",
+                                                      in_port->port);
+
                 /* create list of the addresses that bound to this port ... */
 
                 ngx_init_array(in_port->addrs, cf->pool, 10,
@@ -371,7 +377,7 @@ static char *ngx_http_block(ngx_conf_t *
                 /* ... and add the address to this list */
 
                 inaddr->addr = lscf[l].addr;
-                inaddr->flags = lscf[l].flags;   
+                inaddr->flags = lscf[l].flags;
                 inaddr->core_srv_conf = cscfp[s];
 
                 /* create the empty list of the server names that
@@ -484,6 +490,7 @@ static char *ngx_http_block(ngx_conf_t *
                                   NGX_CONF_ERROR);
 
                     inport->port = in_port[p].port;
+                    inport->port_name = in_port[p].port_name;
 
                     /* init list of the addresses ... */
 
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -13,6 +13,8 @@
 #include <ngx_conf_file.h>
 
 #include <ngx_http_request.h>
+#include <ngx_http_config.h>
+#include <ngx_http_core_module.h>
 
 
 typedef struct {
@@ -30,12 +32,12 @@ typedef int (*ngx_http_output_body_filte
                                    (ngx_http_request_t *r, ngx_chain_t *chain);
 
 
-#define ngx_http_get_module_ctx(r, module)       r->ctx[module.index]
+#define ngx_http_get_module_ctx(r, module)       r->ctx[module.ctx_index]
 
 #define ngx_http_create_ctx(r, cx, module, size, error)                       \
             do {                                                              \
                 ngx_test_null(cx, ngx_pcalloc(r->pool, size), error);         \
-                r->ctx[module.index] = cx;                                    \
+                r->ctx[module.ctx_index] = cx;                                \
             } while (0)
 
 
--- a/src/http/ngx_http_config.h
+++ b/src/http/ngx_http_config.h
@@ -20,8 +20,6 @@ typedef struct {
 
 
 typedef struct {
-    int      index;
-
     void  *(*create_main_conf)(ngx_pool_t *p);
     char  *(*init_main_conf)(ngx_pool_t *p, void *conf);
 
@@ -33,9 +31,7 @@ typedef struct {
 } ngx_http_module_t;
 
 
-#define NGX_HTTP_MODULE_TYPE      0x50545448   /* "HTTP" */
-
-#define NGX_HTTP_MODULE           0
+#define NGX_HTTP_MODULE           0x50545448   /* "HTTP" */
 
 #define NGX_HTTP_MAIN_CONF        0x2000000
 #define NGX_HTTP_SRV_CONF         0x4000000
@@ -47,13 +43,11 @@ typedef struct {
 #define NGX_HTTP_LOC_CONF_OFFSET   offsetof(ngx_http_conf_ctx_t, loc_conf)
 
 
-#define ngx_http_get_module_main_conf(r, ctx)  r->main_conf[ctx.index]
-#define ngx_http_get_module_srv_conf(r, ctx)   r->srv_conf[ctx.index]
-#define ngx_http_get_module_loc_conf(r, ctx)   r->loc_conf[ctx.index]
+#define ngx_http_get_module_main_conf(r, module) r->main_conf[module.ctx_index]
+#define ngx_http_get_module_srv_conf(r, module)  r->srv_conf[module.ctx_index]
+#define ngx_http_get_module_loc_conf(r, module)  r->loc_conf[module.ctx_index]
 
 
-int ngx_http_config_modules(ngx_pool_t *pool, ngx_module_t **modules);
-
 
 extern int (*ngx_http_top_header_filter) (ngx_http_request_t *r);
 
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -1,29 +1,22 @@
 
 #include <ngx_config.h>
+#include <ngx_core.h>
 
+/* ???? */
 #include <ngx_listen.h>
-#include <ngx_core.h>
-#include <ngx_string.h>
-#include <ngx_conf_file.h>
+
+#include <ngx_http.h>
+#include <ngx_http_output_filter.h>
 
 #include <nginx.h>
 
-#include <ngx_http.h>
-#include <ngx_http_config.h>
-#include <ngx_http_core_module.h>
+
+/* STUB */
+int ngx_http_static_handler(ngx_http_request_t *r);
 
 
-/* STUB for r->filter = NGX_HTTP_FILTER_NEED_IN_MEMORY; */
-#include <ngx_http_output_filter.h>
-
-int ngx_http_static_handler(ngx_http_request_t *r);
-int ngx_http_proxy_handler(ngx_http_request_t *r);
-/**/
-
 static int ngx_http_core_index_handler(ngx_http_request_t *r);
 
-static int ngx_http_core_init(ngx_pool_t *pool);
-
 static void *ngx_http_core_create_main_conf(ngx_pool_t *pool);
 static char *ngx_http_core_init_main_conf(ngx_pool_t *pool, void *conf);
 static void *ngx_http_core_create_srv_conf(ngx_pool_t *pool);
@@ -33,11 +26,12 @@ static void *ngx_http_core_create_loc_co
 static char *ngx_http_core_merge_loc_conf(ngx_pool_t *pool,
                                           void *parent, void *child);
 
-static char *ngx_server_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy);
+static int ngx_http_core_init(ngx_pool_t *pool);
+static char *ngx_server_block(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy);
 static char *ngx_location_block(ngx_conf_t *cf, ngx_command_t *cmd,
-                                                                  char *dummy);
-static char *ngx_types_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy);
-static char *ngx_set_listen(ngx_conf_t *cf, ngx_command_t *cmd, char *conf);
+                                                                  void *dummy);
+static char *ngx_types_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
+static char *ngx_set_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
 
 
 static ngx_command_t  ngx_http_core_commands[] = {
@@ -113,6 +107,13 @@ static ngx_command_t  ngx_http_core_comm
      0,
      NULL},
 
+    {ngx_string("default_type"),
+     NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+     ngx_conf_set_str_slot,
+     NGX_HTTP_LOC_CONF_OFFSET,
+     offsetof(ngx_http_core_loc_conf_t, default_type),
+     NULL},
+
     {ngx_string("root"),
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_str_slot,
@@ -155,13 +156,11 @@ static ngx_command_t  ngx_http_core_comm
      offsetof(ngx_http_core_loc_conf_t, lingering_timeout),
      NULL},
 
-    {ngx_null_string, 0, NULL, 0, 0, NULL}
+    ngx_null_command
 };
 
 
 ngx_http_module_t  ngx_http_core_module_ctx = {
-    NGX_HTTP_MODULE,
-
     ngx_http_core_create_main_conf,        /* create main configuration */
     ngx_http_core_init_main_conf,          /* init main configuration */
 
@@ -174,108 +173,20 @@ ngx_http_module_t  ngx_http_core_module_
 
 
 ngx_module_t  ngx_http_core_module = {
+    NGX_MODULE,
     &ngx_http_core_module_ctx,             /* module context */
-    0,                                     /* module index */
     ngx_http_core_commands,                /* module directives */
-    NGX_HTTP_MODULE_TYPE,                  /* module type */
+    NGX_HTTP_MODULE,                       /* module type */
     ngx_http_core_init                     /* init module */
 };
 
 
-int ngx_http_find_server_conf(ngx_http_request_t *r)
-{
-    int                      a, n;
-    socklen_t                len;
-    struct sockaddr_in       addr_in;
-    ngx_http_in_port_t      *in_port;
-    ngx_http_in_addr_t      *in_addr;
-    ngx_http_conf_ctx_t     *ctx;
-    ngx_http_server_name_t  *name;
-
-    /* AF_INET only */
-
-    in_port = (ngx_http_in_port_t *) r->connection->servers;
-    in_addr = (ngx_http_in_addr_t *) in_port->addrs.elts;
-
-    r->port = in_port->port;
-
-    a = 0;
-
-    if (in_port->addrs.nelts > 1) {
-
-        /* there're the several addresses on this port and one of them
-           is "*:port" so getsockname() is needed to determine
-           the server address */
-
-        len = sizeof(struct sockaddr_in);
-        if (getsockname(r->connection->fd, (struct sockaddr *) &addr_in, &len)
-                                                                       == -1) {
-            ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_socket_errno,
-                          "getsockname() failed");
-            return NGX_ERROR;
-        }
-
-        r->in_addr = addr_in.sin_addr.s_addr;
-
-        for ( /* void */ ; a < in_port->addrs.nelts; a++) {
-            if (in_addr[a].addr == r->in_addr) {
-ngx_log_debug(r->connection->log, "FOUND");
-                break;
-            }
-        }
-
-/* DEBUG */
-if (a == in_port->addrs.nelts) {
-    ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                  "addr not found");
-    exit(1);
-}
-
-    } else {
-        r->in_addr = in_addr[0].addr;
-    }
-
-    /* the default server configuration for this address:port */
-    ctx = in_addr[a].core_srv_conf->ctx;
-
-    if (r->headers_in.host_name_len > 0) {
-
-        /* find the name based server configuration */
-
-        name = (ngx_http_server_name_t *) in_addr[a].names.elts;
-        for (n = 0; n < in_addr[a].names.nelts; n++) {
-            if (r->headers_in.host_name_len != name[n].name.len) {
-                continue;
-            }
-
-            if (ngx_strncasecmp(r->headers_in.host->value.data,
-                                name[n].name.data,
-                                r->headers_in.host_name_len) == 0) {
-                ctx = name->core_srv_conf->ctx;
-                break;
-            }
-        }
-    }
-
-    r->srv_conf = ctx->srv_conf;
-    r->loc_conf = ctx->loc_conf;
-
-#if 0
-ngx_log_debug(r->connection->log, "cxt: %08x" _ ctx);
-ngx_log_debug(r->connection->log, "srv_conf: %0x" _ r->srv_conf);
-ngx_log_debug(r->connection->log, "loc_conf: %0x" _ r->loc_conf);
-#endif
-
-    return NGX_OK;
-}
-
-
 void ngx_http_handler(ngx_http_request_t *r)
 {
     int                        rc, i;
     ngx_http_handler_pt       *h;
-    ngx_http_core_loc_conf_t  *lcf, **lcfp;
-    ngx_http_core_srv_conf_t  *scf;
+    ngx_http_core_loc_conf_t  *clcf, **clcfp;
+    ngx_http_core_srv_conf_t  *cscf;
 
     r->connection->unexpected_eof = 0;
 
@@ -293,33 +204,32 @@ void ngx_http_handler(ngx_http_request_t
 
     /* find location config */
 
-    scf = (ngx_http_core_srv_conf_t *)
-                     ngx_http_get_module_srv_conf(r, ngx_http_core_module_ctx);
+    cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
 
-    lcfp = (ngx_http_core_loc_conf_t **) scf->locations.elts;
-    for (i = 0; i < scf->locations.nelts; i++) {
+    clcfp = cscf->locations.elts;
+    for (i = 0; i < cscf->locations.nelts; i++) {
 #if 0
-ngx_log_debug(r->connection->log, "trans: %s" _ lcfp[i]->name.data);
+ngx_log_debug(r->connection->log, "trans: %s" _ clcfp[i]->name.data);
 #endif
-         if (r->uri.len < lcfp[i]->name.len) {
+         if (r->uri.len < clcfp[i]->name.len) {
              continue;
          }
 
-         rc = ngx_rstrncmp(r->uri.data, lcfp[i]->name.data, lcfp[i]->name.len);
+         rc = ngx_rstrncmp(r->uri.data, clcfp[i]->name.data,
+                           clcfp[i]->name.len);
 
          if (rc < 0) {
              break;
          }
 
          if (rc == 0) {
-             r->loc_conf = lcfp[i]->loc_conf;
+             r->loc_conf = clcfp[i]->loc_conf;
          }
     }
 
-    lcf = (ngx_http_core_loc_conf_t *)
-                     ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx);
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
-    if ((ngx_io.flags & NGX_IO_SENDFILE) == 0 || lcf->sendfile == 0) {
+    if ((ngx_io.flags & NGX_IO_SENDFILE) == 0 || clcf->sendfile == 0) {
         r->filter = NGX_HTTP_FILTER_NEED_IN_MEMORY;
     }
 
@@ -355,80 +265,37 @@ ngx_log_debug(r->connection->log, "trans
 
 int ngx_http_core_translate_handler(ngx_http_request_t *r)
 {
-    int                         len, port_len, f_offset, l_offset;
-    char                       *buf, *location, *last;
+    char                       *location, *last;
     ngx_err_t                   err;
     ngx_table_elt_t            *h;
+    ngx_http_in_port_t         *in_port;
     ngx_http_server_name_t     *s_name;
-    ngx_http_core_srv_conf_t   *scf;
-    ngx_http_core_loc_conf_t   *lcf;
+    ngx_http_core_srv_conf_t   *cscf;
+    ngx_http_core_loc_conf_t   *clcf;
 
-    lcf = (ngx_http_core_loc_conf_t *)
-                     ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx);
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
-    if (lcf->handler) {
-        r->handler = lcf->handler;
+    if (clcf->handler) {
+        r->handler = clcf->handler;
         return NGX_OK;
     }
 
-    scf = (ngx_http_core_srv_conf_t *)
-                     ngx_http_get_module_srv_conf(r, ngx_http_core_module_ctx);
+    cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
 
     if (r->uri.data[r->uri.len - 1] == '/') {
         r->handler = ngx_http_core_index_handler;
         return NGX_OK;
     }
 
-ngx_log_debug(r->connection->log, "doc_root: %08x" _ &lcf->doc_root);
-
-    s_name = (ngx_http_server_name_t *) scf->server_names.elts;
-
-    if (r->port == 0) {
-#if 0
-        struct sockaddr_in  *addr_in;
-        addr_in = (struct sockaddr_in *) r->connection->sockaddr;
-        r->port = ntohs(addr_in->sin_port);
-#else
-        ngx_http_in_port_t  *in_port;
-        in_port = (ngx_http_in_port_t *) r->connection->servers;
-        r->port = in_port->port;
-#endif
-        if (r->port != 80) {
-            ngx_test_null(r->port_name.data, ngx_palloc(r->pool, 7),
-                          NGX_HTTP_INTERNAL_SERVER_ERROR);
-            r->port_name.len = ngx_snprintf(r->port_name.data, 7, ":%d",
-                                            r->port);
-        }
-    }
-
-    port_len = (r->port != 80) ? r->port_name.len : 0;
-
-    /* "+ 7" is "http://" */
-    if (lcf->doc_root.len > 7 + s_name[0].name.len + port_len) {
-        len = lcf->doc_root.len;
-        f_offset = 0;
-        l_offset = len - (7 + s_name[0].name.len + port_len);
-
-    } else {
-        len = 7 + s_name[0].name.len + port_len;
-        f_offset = len - lcf->doc_root.len;
-        l_offset = 0;
-    }
-
     /* "+ 2" is for trailing '/' in redirect and '\0' */
-    len += r->uri.len + 2;
-
-    ngx_test_null(buf, ngx_palloc(r->pool, len),
+    ngx_test_null(r->file.name.data,
+                  ngx_palloc(r->pool, clcf->doc_root.len + r->uri.len + 2),
                   NGX_HTTP_INTERNAL_SERVER_ERROR);
 
-    r->file.name.data = buf + f_offset;
-    location = buf + l_offset;
+    location = ngx_cpymem(r->file.name.data, clcf->doc_root.data,
+                          clcf->doc_root.len),
 
-    last = ngx_cpystrn(ngx_cpystrn(r->file.name.data, lcf->doc_root.data,
-                                   lcf->doc_root.len + 1),
-                       r->uri.data, r->uri.len + 1);
-
-    r->file.name.len = last - r->file.name.data;
+    last = ngx_cpystrn(location, r->uri.data, r->uri.len + 1);
 
 ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ r->file.name.data);
 
@@ -510,13 +377,6 @@ ngx_log_debug(r->connection->log, "HTTP 
         ngx_test_null(h, ngx_push_table(r->headers_out.headers),
                       NGX_HTTP_INTERNAL_SERVER_ERROR);
 
-        ngx_memcpy(location, "http://", 7);
-        ngx_memcpy(location + 7, s_name[0].name.data, s_name[0].name.len);
-        if (port_len) {
-            ngx_memcpy(location + 7 + s_name[0].name.len, r->port_name.data,
-                       port_len);
-        }
-
         *last++ = '/';
         *last = '\0';
         h->key.len = 8;
@@ -584,7 +444,7 @@ int ngx_http_redirect(ngx_http_request_t
 }
 
 
-int ngx_http_error(ngx_http_request_t *r, int error) 
+int ngx_http_error(ngx_http_request_t *r, int error)
 {
     /* STUB */
     ngx_log_debug(r->connection->log, "http error: %d" _ error);
@@ -627,7 +487,7 @@ static int ngx_http_core_init(ngx_pool_t
 }
 
 
-static char *ngx_server_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy)
+static char *ngx_server_block(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
 {
     int                          m;
     char                        *rv;
@@ -657,20 +517,20 @@ static char *ngx_server_block(ngx_conf_t
                   NGX_CONF_ERROR);
 
     for (m = 0; ngx_modules[m]; m++) {
-        if (ngx_modules[m]->type != NGX_HTTP_MODULE_TYPE) {
+        if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
             continue;
         }
 
-        module = (ngx_http_module_t *) ngx_modules[m]->ctx;
+        module = ngx_modules[m]->ctx;
 
         if (module->create_srv_conf) {
-            ngx_test_null(ctx->srv_conf[module->index],
+            ngx_test_null(ctx->srv_conf[ngx_modules[m]->ctx_index],
                           module->create_srv_conf(cf->pool),
                           NGX_CONF_ERROR);
         }
 
         if (module->create_loc_conf) {
-            ngx_test_null(ctx->loc_conf[module->index],
+            ngx_test_null(ctx->loc_conf[ngx_modules[m]->ctx_index],
                           module->create_loc_conf(cf->pool),
                           NGX_CONF_ERROR);
         }
@@ -678,10 +538,10 @@ static char *ngx_server_block(ngx_conf_t
 
     /* create links of the srv_conf's */
 
-    cscf = ctx->srv_conf[ngx_http_core_module_ctx.index];
+    cscf = ctx->srv_conf[ngx_http_core_module.ctx_index];
     cscf->ctx = ctx;
 
-    cmcf = ctx->main_conf[ngx_http_core_module_ctx.index];
+    cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
     ngx_test_null(cscfp, ngx_push_array(&cmcf->servers), NGX_CONF_ERROR);
     *cscfp = cscf;
 
@@ -698,9 +558,9 @@ static char *ngx_server_block(ngx_conf_t
 }
 
 
-static char *ngx_location_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy)
+static char *ngx_location_block(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
 {
-    int                        i;
+    int                        m;
     char                      *rv;
     ngx_str_t                 *location;
     ngx_http_module_t         *module;
@@ -721,27 +581,27 @@ static char *ngx_location_block(ngx_conf
                   ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module),
                   NGX_CONF_ERROR);
 
-    for (i = 0; ngx_modules[i]; i++) {
-        if (ngx_modules[i]->type != NGX_HTTP_MODULE_TYPE) {
+    for (m = 0; ngx_modules[m]; m++) {
+        if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
             continue;
         }
 
-        module = (ngx_http_module_t *) ngx_modules[i]->ctx;
+        module = ngx_modules[m]->ctx;
 
         if (module->create_loc_conf) {
-            ngx_test_null(ctx->loc_conf[module->index],
+            ngx_test_null(ctx->loc_conf[ngx_modules[m]->ctx_index],
                           module->create_loc_conf(cf->pool),
                           NGX_CONF_ERROR);
         }
     }
 
-    clcf = ctx->loc_conf[ngx_http_core_module_ctx.index];
+    clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];
     location = (ngx_str_t *) cf->args->elts;
     clcf->name.len = location[1].len;
     clcf->name.data = location[1].data;
     clcf->loc_conf = ctx->loc_conf;
 
-    cscf = ctx->srv_conf[ngx_http_core_module_ctx.index];
+    cscf = ctx->srv_conf[ngx_http_core_module.ctx_index];
     ngx_test_null(clcfp, ngx_push_array(&cscf->locations), NGX_CONF_ERROR);
     *clcfp = clcf;
 
@@ -791,7 +651,7 @@ static char *ngx_set_type(ngx_conf_t *cf
 }
 
 
-static char *ngx_types_block(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
+static char *ngx_types_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     char        *rv;
     ngx_conf_t   pcf;
@@ -811,7 +671,7 @@ static void *ngx_http_core_create_main_c
     ngx_http_core_main_conf_t *cmcf;
 
     ngx_test_null(cmcf,
-                  ngx_palloc(pool, sizeof(ngx_http_core_main_conf_t)), 
+                  ngx_palloc(pool, sizeof(ngx_http_core_main_conf_t)),
                   NGX_CONF_ERROR);
 
     cmcf->connection_pool_size = NGX_CONF_UNSET;
@@ -826,7 +686,7 @@ static void *ngx_http_core_create_main_c
 
 static char *ngx_http_core_init_main_conf(ngx_pool_t *pool, void *conf)
 {
-    ngx_http_core_main_conf_t *cmcf = (ngx_http_core_main_conf_t *) conf;
+    ngx_http_core_main_conf_t *cmcf = conf;
 
     ngx_conf_init_size_value(cmcf->connection_pool_size, 16384);
     ngx_conf_init_msec_value(cmcf->post_accept_timeout, 30000);
@@ -840,7 +700,7 @@ static void *ngx_http_core_create_srv_co
     ngx_http_core_srv_conf_t  *cscf;
 
     ngx_test_null(cscf,
-                  ngx_pcalloc(pool, sizeof(ngx_http_core_srv_conf_t)), 
+                  ngx_pcalloc(pool, sizeof(ngx_http_core_srv_conf_t)),
                   NGX_CONF_ERROR);
 
     ngx_init_array(cscf->locations, pool, 5, sizeof(void *), NGX_CONF_ERROR);
@@ -881,12 +741,8 @@ static char *ngx_http_core_merge_srv_con
         ngx_test_null(n->name.data, ngx_palloc(pool, NGX_MAXHOSTNAMELEN),
                       NGX_CONF_ERROR);
         if (gethostname(n->name.data, NGX_MAXHOSTNAMELEN) == -1) {
-/* STUB: no log here */
-#if 0
-            ngx_log_error(NGX_LOG_EMERG, scf->log, ngx_errno,
-                          "gethostname() failed");
-#endif
-            return NGX_CONF_ERROR;
+            /* TODO: need ngx_errno here */
+            return "gethostname() failed";
         }
         n->name.len = ngx_strlen(n->name.data);
         n->core_srv_conf = conf;
@@ -910,7 +766,7 @@ static void *ngx_http_core_create_loc_co
     ngx_http_core_loc_conf_t *lcf;
 
     ngx_test_null(lcf,
-                  ngx_pcalloc(pool, sizeof(ngx_http_core_loc_conf_t)), 
+                  ngx_pcalloc(pool, sizeof(ngx_http_core_loc_conf_t)),
                   NGX_CONF_ERROR);
 
     /* set by ngx_pcalloc():
@@ -918,6 +774,8 @@ static void *ngx_http_core_create_loc_co
     lcf->doc_root.len = 0;
     lcf->doc_root.data = NULL;
     lcf->types = NULL;
+    lcf->default_type.len = 0;
+    lcf->default_type.data = NULL;
 
     */
 
@@ -950,16 +808,8 @@ static char *ngx_http_core_merge_loc_con
     int               i, key;
     ngx_http_type_t  *t;
 
-    if (conf->doc_root.len == 0) {
-        if (prev->doc_root.len) {
-           conf->doc_root.len = prev->doc_root.len;
-           conf->doc_root.data = prev->doc_root.data;
-
-        } else {
-           conf->doc_root.len = 4;
-           conf->doc_root.data = "html";
-        }
-    }
+    ngx_conf_merge_str_value(conf->doc_root,
+                             prev->doc_root, "html");
 
     if (conf->types == NULL) {
         if (prev->types) {
@@ -989,6 +839,9 @@ static char *ngx_http_core_merge_loc_con
         }
     }
 
+    ngx_conf_merge_str_value(conf->default_type,
+                             prev->default_type, "text/plain");
+
     ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0);
     ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 10000);
     ngx_conf_merge_size_value(conf->discarded_buffer_size,
@@ -1004,16 +857,18 @@ static char *ngx_http_core_merge_loc_con
 }
 
 
-static char *ngx_set_listen(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
+static char *ngx_set_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     ngx_http_core_srv_conf_t *scf = (ngx_http_core_srv_conf_t *) conf;
 
     char               *addr;
     u_int               p;
+    struct hostent     *h;
     ngx_str_t          *args;
     ngx_http_listen_t  *ls;
 
-    /* TODO: check duplicate 'listen' directives */
+    /* TODO: check duplicate 'listen' directives, 
+             add resolved name to server names */
 
     ngx_test_null(ls, ngx_push_array(&scf->listen), NGX_CONF_ERROR);
 
@@ -1033,8 +888,13 @@ static char *ngx_set_listen(ngx_conf_t *
 
             ls->addr = inet_addr(addr);
             if (ls->addr == INADDR_NONE) {
-                /* TODO: gethostbyname() */
-                return "can not resolve host name";
+                h = gethostbyname(addr);
+
+                if (h == NULL || h->h_addr_list[0] == NULL) {
+                    return "can not resolve host name";
+                }
+
+                ls->addr = *(u_int32_t *)(h->h_addr_list[0]);
             }
 
             break;
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -47,6 +47,7 @@ typedef struct {
 
 typedef struct {
     int           port;
+    ngx_str_t     port_name;
     ngx_array_t   addrs;       /* array of ngx_http_in_addr_t */
 } ngx_http_in_port_t;
 
@@ -56,7 +57,7 @@ typedef struct {
     ngx_array_t                names;     /* array of ngx_http_server_name_t */
     ngx_http_core_srv_conf_t  *core_srv_conf;  /* default server conf
                                                   for this address:port */
-    int                        flags;    
+    int                        flags;
 } ngx_http_in_addr_t;
 
 /* ngx_http_in_addr_t's flags */
@@ -87,22 +88,23 @@ typedef struct {
 
 
 typedef struct {
-    ngx_str_t   name;          /* location name */
-    void      **loc_conf ;     /* pointer to the modules' loc_conf */
+    ngx_str_t     name;          /* location name */
+    void        **loc_conf ;     /* pointer to the modules' loc_conf */
 
-    int       (*handler) (ngx_http_request_t *r);
+    int         (*handler) (ngx_http_request_t *r);
 
-    ngx_str_t   doc_root;                /* root */
+    ngx_str_t     doc_root;                /* root */
 
     ngx_array_t  *types;
+    ngx_str_t     default_type;
 
-    int         sendfile;                /* sendfile */
-    ngx_msec_t  send_timeout;            /* send_timeout */
-    size_t      send_lowat;              /* send_lowa */
-    size_t      discarded_buffer_size;   /* discarded_buffer_size */
-    ngx_msec_t  keepalive_timeout;       /* keepalive_timeout */
-    ngx_msec_t  lingering_time;          /* lingering_time */
-    ngx_msec_t  lingering_timeout;       /* lingering_timeout */
+    int           sendfile;                /* sendfile */
+    ngx_msec_t    send_timeout;            /* send_timeout */
+    size_t        send_lowat;              /* send_lowat */
+    size_t        discarded_buffer_size;   /* discarded_buffer_size */
+    ngx_msec_t    keepalive_timeout;       /* keepalive_timeout */
+    ngx_msec_t    lingering_time;          /* lingering_time */
+    ngx_msec_t    lingering_timeout;       /* lingering_timeout */
 
 } ngx_http_core_loc_conf_t;
 
--- a/src/http/ngx_http_event.c
+++ b/src/http/ngx_http_event.c
@@ -75,10 +75,9 @@ static ngx_http_header_t headers_in[] = 
 
 void ngx_http_init_connection(ngx_connection_t *c)
 {
-    int                   event;
-    ngx_event_t          *rev;
-    ngx_http_log_ctx_t   *lcx;
-    ngx_http_conf_ctx_t  *ctx;
+    int                  event;
+    ngx_event_t         *rev;
+    ngx_http_log_ctx_t  *lcx;
 
     c->addr_text.data = ngx_palloc(c->pool, c->addr_text_max_len);
     if (c->addr_text.data == NULL) {
@@ -139,16 +138,77 @@ void ngx_http_init_connection(ngx_connec
 
 static void ngx_http_init_request(ngx_event_t *rev)
 {
+    int                        i;
+    socklen_t                  len;
+    struct sockaddr_in         addr_in;
     ngx_connection_t          *c;
     ngx_http_request_t        *r;
-    ngx_http_conf_ctx_t       *ctx;
+    ngx_http_in_port_t        *in_port;
+    ngx_http_in_addr_t        *in_addr;
+    ngx_http_server_name_t    *server_name;
     ngx_http_core_srv_conf_t  *cscf;
 
     c = rev->data;
-    ctx = c->ctx;
+
+    r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t));
+    if (r == NULL) {
+        ngx_http_close_connection(c);
+        return;
+    }
+
+    /* find the server configuration for the address:port */
+
+    /* AF_INET only */
+
+    in_port = c->servers;
+    in_addr = in_port->addrs.elts;
+
+    r->port = in_port->port;
+    r->port_name = &in_port->port_name;
+
+    i = 0;
+
+    if (in_port->addrs.nelts > 1) {
+
+        /* there're the several addresses on this port and one of them
+           is "*:port" so getsockname() is needed to determine
+           the server address */
+
+        /* TODO: AcceptEx() already gave this sockaddr_in */
 
-    cscf = ngx_http_get_module_srv_conf(ctx, ngx_http_core_module_ctx);
-    cscf = ngx_http_get_module_srv_conf(cscf->ctx, ngx_http_core_module_ctx);
+        len = sizeof(struct sockaddr_in);
+        if (getsockname(c->fd, (struct sockaddr *) &addr_in, &len) == -1) {
+            ngx_log_error(NGX_LOG_CRIT, rev->log, ngx_socket_errno,
+                          "getsockname() failed");
+            ngx_http_close_connection(c);
+            return;
+        }
+
+        r->in_addr = addr_in.sin_addr.s_addr;
+
+        /* the last in_port->addrs address is "*" */
+
+        for ( /* void */ ; i < in_port->addrs.nelts - 1; i++) {
+            if (in_addr[i].addr == r->in_addr) {
+                break;
+            }
+        }
+
+    } else {
+        r->in_addr = in_addr[0].addr;
+    }
+
+    r->virtual_names = &in_addr[i].names;
+
+    /* the default server configuration for the address:port */
+    cscf = in_addr[i].core_srv_conf;
+
+    r->main_conf = cscf->ctx->main_conf;
+    r->srv_conf = cscf->ctx->srv_conf;
+    r->loc_conf = cscf->ctx->loc_conf;
+
+    server_name = cscf->server_names.elts;
+    r->server_name = &server_name->name;
 
     if (c->buffer == NULL) {
         c->buffer = ngx_create_temp_hunk(c->pool,
@@ -160,12 +220,6 @@ static void ngx_http_init_request(ngx_ev
         }
     }
 
-    r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t));
-    if (r == NULL) {
-        ngx_http_close_connection(c);
-        return;
-    }
-
     r->pool = ngx_create_pool(cscf->request_pool_size, c->log);
     if (r->pool == NULL) {
         ngx_http_close_connection(c);
@@ -186,10 +240,6 @@ static void ngx_http_init_request(ngx_ev
         return;
     }
 
-    r->main_conf = ctx->main_conf;
-    r->srv_conf = ctx->srv_conf;
-    r->loc_conf = ctx->loc_conf;
-
     c->sent = 0;
     c->data = r;
     r->connection = c;
@@ -239,7 +289,7 @@ static void ngx_http_process_request_lin
 
         /* the request line has been parsed successfully */
 
-        cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module_ctx);
+        cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
 
         if (r->http_version >= NGX_HTTP_VERSION_10
             && cscf->large_client_header == 0
@@ -269,7 +319,7 @@ static void ngx_http_process_request_lin
 
         ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1);
 
-#if 1 /* needed to log url on errors in proxy only ? */
+#if 1 /* THINK: needed to log url on errors in proxy only ? */
 
         /* copy unparsed URI */
 
@@ -353,12 +403,6 @@ static void ngx_http_process_request_lin
 #endif
 
         if (r->http_version == NGX_HTTP_VERSION_9) {
-            if (ngx_http_find_server_conf(r) == NGX_ERROR) {
-                ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
-                ngx_http_close_connection(c);
-                return;
-            }
-
             rev->event_handler = ngx_http_block_read;
             ngx_http_handler(r);
             return;
@@ -400,7 +444,7 @@ static void ngx_http_process_request_lin
            are enabled otherwise a request line had been already copied
            to the start of the r->header_in hunk in ngx_http_set_keepalive() */
 
-        cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module_ctx);
+        cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
 
         if (cscf->large_client_header) {
             offset = r->request_start - r->header_in->start;
@@ -446,7 +490,7 @@ static void ngx_http_process_request_hea
     ngx_table_elt_t           *h;
     ngx_connection_t          *c;
     ngx_http_request_t        *r;
-    ngx_http_log_ctx_t        *ctx;
+    ngx_http_server_name_t    *name;
     ngx_http_core_srv_conf_t  *cscf;
 
     c = rev->data;
@@ -460,6 +504,8 @@ static void ngx_http_process_request_hea
         return;
     }
 
+    cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
+
     rc = NGX_AGAIN;
 
     for ( ;; ) {
@@ -490,8 +536,6 @@ static void ngx_http_process_request_hea
             /* if the large client headers are enabled then
                we need to copy the header name and value */
 
-            cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module_ctx);
-
             if (cscf->large_client_header) {
                 h->key.data = ngx_palloc(r->pool,
                                          h->key.len + 1 + h->value.len + 1);
@@ -532,6 +576,8 @@ static void ngx_http_process_request_hea
                 r->header_in->pos = r->header_in->last = r->header_in->start;
             }
 
+            continue;
+
         } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
 
             /* a whole header has been parsed successfully */
@@ -546,6 +592,24 @@ static void ngx_http_process_request_hea
                 }
                 r->headers_in.host_name_len = len;
 
+                /* find the name based server configuration */
+
+                name = r->virtual_names->elts;
+                for (i = 0; i < r->virtual_names->nelts; i++) {
+                    if (r->headers_in.host_name_len != name[i].name.len) {
+                        continue;
+                    }
+
+                    if (ngx_strncasecmp(r->headers_in.host->value.data,
+                                        name[i].name.data,
+                                        r->headers_in.host_name_len) == 0)
+                    {
+                        r->srv_conf = name[i].core_srv_conf->ctx->srv_conf;
+                        r->loc_conf = name[i].core_srv_conf->ctx->loc_conf;
+                        break;
+                    }
+                }
+
             } else {
                 if (r->http_version > NGX_HTTP_VERSION_10) {
                     ngx_http_header_parse_error(r,
@@ -568,12 +632,6 @@ static void ngx_http_process_request_hea
                 }
             }
 
-            if (ngx_http_find_server_conf(r) == NGX_ERROR) {
-                ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
-                ngx_http_close_connection(c);
-                return;
-            }
-
             rev->event_handler = ngx_http_block_read;
             ngx_http_handler(r);
             return;
@@ -595,8 +653,6 @@ static void ngx_http_process_request_hea
             /* if the large client headers are enabled then
                 we need to compact r->header_in hunk */
 
-            cscf = ngx_http_get_module_main_conf(r, ngx_http_core_module_ctx);
-
             if (cscf->large_client_header) {
                 offset = r->header_name_start - r->header_in->start;
 
@@ -653,7 +709,7 @@ static ssize_t ngx_http_read_request_hea
                 rev->timer_set = 1;
             }
 
-            cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module_ctx);
+            cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
 
             ngx_add_timer(rev, cscf->client_header_timeout);
             r->header_timeout_set = 1;
@@ -758,9 +814,8 @@ void ngx_http_set_write_handler(ngx_http
         return;
     }
 
-    clcf = (ngx_http_core_loc_conf_t *)
-                        ngx_http_get_module_loc_conf(r->main ? r->main : r,
-                                                     ngx_http_core_module_ctx);
+    clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
+                                        ngx_http_core_module);
     ngx_add_timer(wev, clcf->send_timeout);
     wev->timer_set = 1;
 
@@ -799,10 +854,10 @@ static void ngx_http_writer(ngx_event_t 
     ngx_event_t               *rev;
     ngx_connection_t          *c;
     ngx_http_request_t        *r;
-    ngx_http_core_loc_conf_t  *lcf;
+    ngx_http_core_loc_conf_t  *clcf;
 
-    c = (ngx_connection_t *) wev->data;
-    r = (ngx_http_request_t *) c->data;
+    c = wev->data;
+    r = c->data;
 
     rc = ngx_http_output_filter(r, NULL);
 
@@ -810,16 +865,15 @@ static void ngx_http_writer(ngx_event_t 
 
     if (rc == NGX_AGAIN) {
 
-        lcf = (ngx_http_core_loc_conf_t *)
-                        ngx_http_get_module_loc_conf(r->main ? r->main : r,
-                                                     ngx_http_core_module_ctx);
+        clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
+                                           ngx_http_core_module);
         if (wev->timer_set) {
             ngx_del_timer(wev);
         } else {
             wev->timer_set = 1;
         }
 
-        ngx_add_timer(wev, lcf->send_timeout);
+        ngx_add_timer(wev, clcf->send_timeout);
 
         return;
     }
@@ -941,8 +995,8 @@ static void ngx_http_read_discarded_body
     ngx_connection_t    *c;
     ngx_http_request_t  *r;
 
-    c = (ngx_connection_t *) rev->data;
-    r = (ngx_http_request_t *) c->data;
+    c = rev->data;
+    r = c->data;
 
     rc = ngx_http_read_discarded_body(r);
 
@@ -957,23 +1011,22 @@ static int ngx_http_read_discarded_body(
 {
     size_t                     size;
     ssize_t                    n;
-    ngx_http_core_loc_conf_t  *lcf;
+    ngx_http_core_loc_conf_t  *clcf;
 
     ngx_log_debug(r->connection->log, "http read discarded body");
 
-    lcf = (ngx_http_core_loc_conf_t *)
-                     ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx);
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
     if (r->discarded_buffer == NULL) {
-        r->discarded_buffer = ngx_palloc(r->pool, lcf->discarded_buffer_size);
+        r->discarded_buffer = ngx_palloc(r->pool, clcf->discarded_buffer_size);
         if (r->discarded_buffer == NULL) {
             return NGX_HTTP_INTERNAL_SERVER_ERROR;
         }
     }
 
     size = r->headers_in.content_length_n;
-    if (size > lcf->discarded_buffer_size) {
-        size = lcf->discarded_buffer_size;
+    if (size > clcf->discarded_buffer_size) {
+        size = clcf->discarded_buffer_size;
     }
 
     n = ngx_event_recv(r->connection, r->discarded_buffer, size);
@@ -1001,7 +1054,7 @@ static void ngx_http_set_keepalive(ngx_h
     ngx_http_core_srv_conf_t  *cscf;
     ngx_http_core_loc_conf_t  *clcf;
 
-    c = (ngx_connection_t *) r->connection;
+    c = r->connection;
     rev = c->read;
 
     ngx_log_debug(c->log, "set http keepalive handler");
@@ -1016,8 +1069,7 @@ static void ngx_http_set_keepalive(ngx_h
         rev->timer_set = 1;
     }
 
-    clcf = (ngx_http_core_loc_conf_t *)
-                     ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx);
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
     ngx_add_timer(rev, clcf->keepalive_timeout);
 
@@ -1045,7 +1097,7 @@ static void ngx_http_set_keepalive(ngx_h
            This copy should be rare because clients that support
            pipelined requests (Mozilla 1.x, Opera 6.x) are still rare */
 
-        cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module_ctx);
+        cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
 
         if (!cscf->large_client_header) {
             len = h->last - h->pos;
@@ -1054,6 +1106,8 @@ static void ngx_http_set_keepalive(ngx_h
             h->last = h->start + len;
         }
 
+        ngx_log_debug(c->log, "pipelined request");
+
         c->pipeline = 1;
         ctx->action = "reading client pipelined request line";
         ngx_http_init_request(rev);
@@ -1140,15 +1194,14 @@ static void ngx_http_set_lingering_close
 {
     ngx_event_t               *rev;
     ngx_connection_t          *c;
-    ngx_http_core_loc_conf_t  *lcf;
+    ngx_http_core_loc_conf_t  *clcf;
 
     c = r->connection;
     rev = c->read;
 
-    lcf = (ngx_http_core_loc_conf_t *)
-                     ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx);
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
-    r->lingering_time = ngx_time() + lcf->lingering_time / 1000;
+    r->lingering_time = ngx_time() + clcf->lingering_time / 1000;
     rev->event_handler = ngx_http_lingering_close_handler;
 
     if (rev->timer_set) {
@@ -1157,7 +1210,7 @@ static void ngx_http_set_lingering_close
         rev->timer_set = 1;
     }
 
-    ngx_add_timer(rev, lcf->lingering_timeout);
+    ngx_add_timer(rev, clcf->lingering_timeout);
 
     if (rev->blocked && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
         if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) {
@@ -1201,10 +1254,10 @@ static void ngx_http_lingering_close_han
     ngx_msec_t                 timer;
     ngx_connection_t          *c;
     ngx_http_request_t        *r;
-    ngx_http_core_loc_conf_t  *lcf;
+    ngx_http_core_loc_conf_t  *clcf;
 
-    c = (ngx_connection_t *) rev->data;
-    r = (ngx_http_request_t *) c->data;
+    c = rev->data;
+    r = c->data;
 
     ngx_log_debug(c->log, "http lingering close handler");
 
@@ -1221,8 +1274,7 @@ static void ngx_http_lingering_close_han
         return;
     }
 
-    lcf = (ngx_http_core_loc_conf_t *)
-                     ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx);
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
     if (r->discarded_buffer == NULL) {
 
@@ -1231,12 +1283,12 @@ static void ngx_http_lingering_close_han
                  instead of r->header_in->last */
 
         if ((size_t)(r->header_in->end - r->header_in->last)
-                                               >= lcf->discarded_buffer_size) {
+                                              >= clcf->discarded_buffer_size) {
             r->discarded_buffer = r->header_in->last;
 
         } else {
             r->discarded_buffer = ngx_palloc(c->pool,
-                                             lcf->discarded_buffer_size);
+                                             clcf->discarded_buffer_size);
             if (r->discarded_buffer) {
                 ngx_http_close_request(r, 0);
                 ngx_http_close_connection(c);
@@ -1246,7 +1298,7 @@ static void ngx_http_lingering_close_han
     }
 
     do {
-        n = ngx_event_recv(c, r->discarded_buffer, lcf->discarded_buffer_size);
+        n = ngx_event_recv(c, r->discarded_buffer, clcf->discarded_buffer_size);
 
         ngx_log_debug(c->log, "lingering read: %d" _ n);
 
@@ -1259,8 +1311,8 @@ static void ngx_http_lingering_close_han
     } while (rev->ready);
 
     timer *= 1000;
-    if (timer > lcf->lingering_timeout) {
-        timer = lcf->lingering_timeout;
+    if (timer > clcf->lingering_timeout) {
+        timer = clcf->lingering_timeout;
     }
 
     if (rev->timer_set) {
@@ -1334,7 +1386,7 @@ void ngx_http_close_connection(ngx_conne
         c->write->timer_set = 0;
     }
 
-    if (1) {
+    if (ngx_del_conn) {
         ngx_del_conn(c);
 
     } else {
--- a/src/http/ngx_http_header_filter.c
+++ b/src/http/ngx_http_header_filter.c
@@ -19,8 +19,6 @@ static int ngx_http_header_filter(ngx_ht
 
 
 static ngx_http_module_t  ngx_http_header_filter_module_ctx = {
-    NGX_HTTP_MODULE,
-
     NULL,                                  /* create main configuration */
     NULL,                                  /* init main configuration */
 
@@ -33,10 +31,10 @@ static ngx_http_module_t  ngx_http_heade
 
 
 ngx_module_t  ngx_http_header_filter_module = {
+    NGX_MODULE,
     &ngx_http_header_filter_module_ctx,    /* module context */
-    0,                                     /* module index */
     NULL,                                  /* module directives */
-    NGX_HTTP_MODULE_TYPE,                  /* module type */
+    NGX_HTTP_MODULE,                       /* module type */
     ngx_http_header_filter_init            /* init module */
 };
 
@@ -47,30 +45,41 @@ static char server_string[] = "Server: "
 static ngx_str_t http_codes[] = {
 
     ngx_string("200 OK"),
+    ngx_null_string,  /* "201 Created" */
+    ngx_null_string,  /* "202 Accepted" */
+    ngx_null_string,  /* "203 Non-Authoritative Information" */
+    ngx_null_string,  /* "204 No Content" */
+    ngx_null_string,  /* "205 Reset Content" */
+    ngx_string("206 Partial Content"),
+    ngx_null_string,  /* "207 Multi-Status" */
+
+#if 0
+    ngx_null_string,  /* "300 Multiple Choices" */
+#endif
 
     ngx_string("301 Moved Permanently"),
     ngx_string("302 Moved Temporarily"),
-    ngx_null_string,  /* 303 */
+    ngx_null_string,  /* "303 See Other" */
     ngx_string("304 Not Modified"),
 
     ngx_string("400 Bad Request"),
-    ngx_null_string,  /* 401 */
-    ngx_null_string,  /* 402 */
+    ngx_string("401 Unauthorized"),
+    ngx_null_string,  /* "402 Payment Required" */
     ngx_string("403 Forbidden"),
     ngx_string("404 Not Found"),
-    ngx_null_string,  /* 405 */
-    ngx_null_string,  /* 406 */
-    ngx_null_string,  /* 407 */
+    ngx_string("405 Not Allowed"),
+    ngx_null_string,  /* "406 Not Acceptable" */
+    ngx_null_string,  /* "407 Proxy Authentication Required" */
     ngx_string("408 Request Time-out"),
-    ngx_null_string,  /* 409 */
-    ngx_null_string,  /* 410 */
+    ngx_null_string,  /* "409 Conflict" */
+    ngx_null_string,  /* "410 Gone" */
     ngx_string("411 Length Required"),
-    ngx_null_string,  /* 412 */
+    ngx_null_string,  /* "412 Precondition Failed" */
     ngx_string("413 Request Entity Too Large"),
     ngx_null_string,  /* "414 Request-URI Too Large" but we never send it
                          because we treat such requests as the HTTP/0.9 requests
                          and send only the body without the header */
-    ngx_null_string,  /* 415 */
+    ngx_null_string,  /* "415 Unsupported Media Type" */
     ngx_string("416 Requested Range Not Satisfiable"),
 
     ngx_string("500 Internal Server Error"),
@@ -84,7 +93,7 @@ static ngx_str_t http_codes[] = {
 
 static int ngx_http_header_filter(ngx_http_request_t *r)
 {
-    int               len, status, i;
+    int               len, status, text, i;
     time_t            ims;
     ngx_hunk_t       *h;
     ngx_chain_t      *ch;
@@ -94,6 +103,10 @@ static int ngx_http_header_filter(ngx_ht
         return NGX_OK;
     }
 
+    if (r->method == NGX_HTTP_HEAD) {
+        r->header_only = 1;
+    }
+
     /* 9 is for "HTTP/1.x ", 2 is for trailing "\r\n"
        and 2 is for end of header */
     len = 9 + 2 + 2;
@@ -132,17 +145,17 @@ static int ngx_http_header_filter(ngx_ht
 
         } else if (r->headers_out.status < NGX_HTTP_BAD_REQUEST) {
             /* 3XX */
-            status = r->headers_out.status - NGX_HTTP_MOVED_PERMANENTLY + 1;
+            status = r->headers_out.status - NGX_HTTP_MOVED_PERMANENTLY + 8;
             r->header_only = 1;
 
         } else if (r->headers_out.status < NGX_HTTP_INTERNAL_SERVER_ERROR) {
             /* 4XX */
-            status = r->headers_out.status - NGX_HTTP_BAD_REQUEST + 1 + 4;
+            status = r->headers_out.status - NGX_HTTP_BAD_REQUEST + 8 + 4;
 
         } else {
             /* 5XX */
             status = r->headers_out.status
-                                 - NGX_HTTP_INTERNAL_SERVER_ERROR + 1 + 4 + 17;
+                                 - NGX_HTTP_INTERNAL_SERVER_ERROR + 8 + 4 + 17;
         }
 
         len += http_codes[status].len;
@@ -159,31 +172,55 @@ static int ngx_http_header_filter(ngx_ht
         len += r->headers_out.date->key.len
                + r->headers_out.date->value.len + 2;
     } else {
-        /* "Date: ... \r\n"; */
+        /* "Date: ... \r\n" */
         len += 37;
     }
 
-    /* 2^64 is 20 characters */
     if (r->headers_out.content_length >= 0) {
+        /* "Content-Length: ... \r\n", 2^64 is 20 characters */
         len += 48;
     }
 
-#if 0
-    if (r->headers_out.content_type.len)
-        len += r->headers_out.content_type.len + 16;
-#endif
+    text = 0;
+    if (r->headers_out.content_type && r->headers_out.content_type->value.len) {
+        r->headers_out.content_type->key.len = 0;
+        len += 16 + r->headers_out.content_type->value.len;
+        if (ngx_strncasecmp(r->headers_out.content_type->value.data,
+                                                            "text/", 5) == 0) {
+            text = 1;
+            /* "; charset=koi8-r" */
+            len += 16;
+        }
+    }
+
+    if (r->headers_out.location
+        && r->headers_out.location->value.len
+        && r->headers_out.location->value.data[0] == '/')
+    {
+        r->headers_out.location->key.len = 0;
+        /* "Location: http:// ... \r\n" */
+        len += 17 + r->server_name->len
+               + r->headers_out.location->value.len + 2;
+
+        if (r->port != 80) {
+            len += r->port_name->len;
+        }
+    }
 
     if (r->headers_out.last_modified && r->headers_out.last_modified->key.len) {
         len += r->headers_out.last_modified->key.len
                + r->headers_out.last_modified->value.len + 2;
+
     } else if (r->headers_out.last_modified_time != -1) {
-        /* "Last-Modified: ... \r\n"; */
+        /* "Last-Modified: ... \r\n" */
         len += 46;
     }
 
     if (r->keepalive == 0) {
+        /* "Connection: close\r\n" */
         len += 19;
     } else {
+        /* "Connection: keep-alive\r\n" */
         len += 24;
     }
 
@@ -199,30 +236,25 @@ static int ngx_http_header_filter(ngx_ht
     ngx_test_null(h, ngx_create_temp_hunk(r->pool, len, 0, 64), NGX_ERROR);
 
     /* "HTTP/1.x " */
-    ngx_memcpy(h->last, "HTTP/1.1 ", 9);
-    h->last += 9;
+    h->last = ngx_cpymem(h->last, "HTTP/1.1 ", 9);
 
     /* status line */
     if (r->headers_out.status_line.len) {
-        ngx_memcpy(h->last, r->headers_out.status_line.data,
-                   r->headers_out.status_line.len);
-        h->last += r->headers_out.status_line.len;
+        h->last = ngx_cpymem(h->last, r->headers_out.status_line.data,
+                             r->headers_out.status_line.len);
 
     } else {
-        ngx_memcpy(h->last, http_codes[status].data,
-                   http_codes[status].len);
-        h->last += http_codes[status].len;
+        h->last = ngx_cpymem(h->last, http_codes[status].data,
+                             http_codes[status].len);
     }
     *(h->last++) = CR; *(h->last++) = LF;
 
     if (!(r->headers_out.server && r->headers_out.server->key.len)) {
-        ngx_memcpy(h->last, server_string, sizeof(server_string) - 1);
-        h->last += sizeof(server_string) - 1;
+        h->last = ngx_cpymem(h->last, server_string, sizeof(server_string) - 1);
     }
 
     if (!(r->headers_out.date && r->headers_out.date->key.len)) {
-        ngx_memcpy(h->last, "Date: ", 6);
-        h->last += 6;
+        h->last = ngx_cpymem(h->last, "Date: ", 6);
         h->last += ngx_http_get_time(h->last, time(NULL));
         *(h->last++) = CR; *(h->last++) = LF;
     }
@@ -230,39 +262,54 @@ static int ngx_http_header_filter(ngx_ht
     /* 2^64 is 20 characters  */
     if (r->headers_out.content_length >= 0) {
         h->last += ngx_snprintf(h->last, 49,
-                                    "Content-Length: " OFF_FMT CRLF,
-                                    r->headers_out.content_length);
+                                "Content-Length: " OFF_FMT CRLF,
+                                r->headers_out.content_length);
+    }
+
+    if (r->headers_out.content_type && r->headers_out.content_type->value.len) {
+        h->last = ngx_cpymem(h->last, "Content-Type: ", 14);
+        h->last = ngx_cpymem(h->last, r->headers_out.content_type->value.data,
+                   r->headers_out.content_type->value.len);
+
+        if (text) {
+            h->last = ngx_cpymem(h->last, "; charset=koi8-r", 16);
+        }
+
+        *(h->last++) = CR; *(h->last++) = LF;
     }
 
-#if 0
-    if (r->headers_out.content_type.len) {
-        ngx_memcpy(h->last, "Content-Type: ", 14);
-        h->last += 14;
-        ngx_memcpy(h->last, r->headers_out.content_type.data,
-                   r->headers_out.content_type.len);
-        h->last += r->headers_out.content_type.len;
+    if (r->headers_out.location
+        && r->headers_out.location->value.len
+        && r->headers_out.location->value.data[0] == '/')
+    {
+        h->last = ngx_cpymem(h->last, "Location: http://", 17);
+        h->last = ngx_cpymem(h->last, r->server_name->data,
+                             r->server_name->len);
+        if (r->port != 80) {
+            h->last = ngx_cpymem(h->last, r->port_name->data,
+                                 r->port_name->len);
+        }
+
+        h->last = ngx_cpymem(h->last, r->headers_out.location->value.data,
+                             r->headers_out.location->value.len);
+
         *(h->last++) = CR; *(h->last++) = LF;
     }
-#endif
 
-    if (!(r->headers_out.last_modified
-          && r->headers_out.last_modified->key.len)
+    if (!(r->headers_out.last_modified && r->headers_out.last_modified->key.len)
         && r->headers_out.last_modified_time != -1)
     {
-        ngx_memcpy(h->last, "Last-Modified: ", 15);
-        h->last += 15;
+        h->last = ngx_cpymem(h->last, "Last-Modified: ", 15);
         h->last += ngx_http_get_time(h->last,
                                          r->headers_out.last_modified_time);
         *(h->last++) = CR; *(h->last++) = LF;
     }
 
     if (r->keepalive == 0) {
-        ngx_memcpy(h->last, "Connection: close" CRLF, 19);
-        h->last += 19;
+        h->last = ngx_cpymem(h->last, "Connection: close" CRLF, 19);
 
     } else {
-        ngx_memcpy(h->last, "Connection: keep-alive" CRLF, 24);
-        h->last += 24;
+        h->last = ngx_cpymem(h->last, "Connection: keep-alive" CRLF, 24);
     }
 
     for (i = 0; i < r->headers_out.headers->nelts; i++) {
@@ -270,12 +317,11 @@ static int ngx_http_header_filter(ngx_ht
             continue;
         }
 
-        ngx_memcpy(h->last, header[i].key.data, header[i].key.len);
-        h->last += header[i].key.len;
+        h->last = ngx_cpymem(h->last, header[i].key.data, header[i].key.len);
         *(h->last++) = ':' ; *(h->last++) = ' ' ;
 
-        ngx_memcpy(h->last, header[i].value.data, header[i].value.len);
-        h->last += header[i].value.len;
+        h->last = ngx_cpymem(h->last, header[i].value.data,
+                             header[i].value.len);
         *(h->last++) = CR; *(h->last++) = LF;
     }
 
@@ -284,7 +330,7 @@ static int ngx_http_header_filter(ngx_ht
     ngx_log_debug(r->connection->log, "%s\n" _ h->pos);
     /**/
 
-    /* end of HTTP header */
+    /* the end of HTTP header */
     *(h->last++) = CR; *(h->last++) = LF;
 
     if (r->header_only) {
--- a/src/http/ngx_http_output_filter.c
+++ b/src/http/ngx_http_output_filter.c
@@ -16,8 +16,6 @@ static int ngx_http_output_filter_copy_h
 static void *ngx_http_output_filter_create_conf(ngx_pool_t *pool);
 static char *ngx_http_output_filter_merge_conf(ngx_pool_t *pool,
                                                void *parent, void *child);
-static void ngx_http_output_filter_init(ngx_pool_t *pool,
-                                        ngx_http_conf_filter_t *cf);
 
 
 static ngx_command_t  ngx_http_output_filter_commands[] = {
@@ -29,13 +27,11 @@ static ngx_command_t  ngx_http_output_fi
      offsetof(ngx_http_output_filter_conf_t, hunk_size),
      NULL},
 
-    {ngx_null_string, 0, NULL, 0, 0, NULL}
+    ngx_null_command
 };
 
 
 static ngx_http_module_t  ngx_http_output_filter_module_ctx = {
-    NGX_HTTP_MODULE,
-
     NULL,                                  /* create main configuration */
     NULL,                                  /* init main configuration */
 
@@ -48,10 +44,10 @@ static ngx_http_module_t  ngx_http_outpu
 
 
 ngx_module_t  ngx_http_output_filter_module = {
+    NGX_MODULE,
     &ngx_http_output_filter_module_ctx,    /* module context */
-    0,                                     /* module index */
     ngx_http_output_filter_commands,       /* module directives */
-    NGX_HTTP_MODULE_TYPE,                  /* module type */
+    NGX_HTTP_MODULE,                       /* module type */
     NULL                                   /* init module */
 };
 
@@ -73,12 +69,11 @@ int ngx_http_output_filter(ngx_http_requ
     ngx_http_output_filter_ctx_t   *ctx;
     ngx_http_output_filter_conf_t  *conf;
 
-    ctx = (ngx_http_output_filter_ctx_t *)
-                    ngx_http_get_module_ctx(r->main ? r->main : r,
-                                            ngx_http_output_filter_module_ctx);
+    ctx = ngx_http_get_module_ctx(r->main ? r->main : r,
+                                            ngx_http_output_filter_module);
 
     if (ctx == NULL) {
-        ngx_http_create_ctx(r, ctx, ngx_http_output_filter_module_ctx,
+        ngx_http_create_ctx(r, ctx, ngx_http_output_filter_module,
                             sizeof(ngx_http_output_filter_ctx_t), NGX_ERROR);
     }
 
@@ -117,9 +112,8 @@ int ngx_http_output_filter(ngx_http_requ
     /* allocate our hunk if it's needed */
     if (ctx->hunk == NULL) {
 
-        conf = (ngx_http_output_filter_conf_t *)
-               ngx_http_get_module_loc_conf(r->main ? r->main : r,
-                                            ngx_http_output_filter_module_ctx);
+        conf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
+                                            ngx_http_output_filter_module);
 
         if (hunk->type & NGX_HUNK_LAST) {
             if (hunk->type & NGX_HUNK_IN_MEMORY) {
@@ -307,22 +301,12 @@ ngx_log_debug(src->file->log, "READ: %qd
 }
 
 
-static void ngx_http_output_filter_init(ngx_pool_t *pool,
-                                        ngx_http_conf_filter_t *cf)
-{
-#if 0
-    next_filter = cf->output_body_filter;
-    cf->output_body_filter = NULL;
-#endif
-}
-
-
 static void *ngx_http_output_filter_create_conf(ngx_pool_t *pool)
 {
     ngx_http_output_filter_conf_t *conf;
 
     ngx_test_null(conf,
-                  ngx_pcalloc(pool, sizeof(ngx_http_output_filter_conf_t)),
+                  ngx_palloc(pool, sizeof(ngx_http_output_filter_conf_t)),
                   NULL);
 
     conf->hunk_size = NGX_CONF_UNSET;
@@ -334,10 +318,8 @@ static void *ngx_http_output_filter_crea
 static char *ngx_http_output_filter_merge_conf(ngx_pool_t *pool,
                                                void *parent, void *child)
 {
-    ngx_http_output_filter_conf_t *prev =
-                                      (ngx_http_output_filter_conf_t *) parent;
-    ngx_http_output_filter_conf_t *conf =
-                                       (ngx_http_output_filter_conf_t *) child;
+    ngx_http_output_filter_conf_t *prev = parent;
+    ngx_http_output_filter_conf_t *conf = child;
 
     ngx_conf_merge_size_value(conf->hunk_size, prev->hunk_size, 32768);
 
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -49,6 +49,7 @@
 #define NGX_HTTP_BAD_REQUEST            400
 #define NGX_HTTP_FORBIDDEN              403
 #define NGX_HTTP_NOT_FOUND              404
+#define NGX_HTTP_NOT_ALLOWED            405
 #define NGX_HTTP_REQUEST_TIME_OUT       408
 #define NGX_HTTP_REQUEST_URI_TOO_LARGE  414
 
@@ -154,10 +155,11 @@ struct ngx_http_request_s {
 
     ngx_http_request_t  *main;
 
-    u_int       in_addr;
-
-    int         port;
-    ngx_str_t   port_name;
+    u_int                in_addr;
+    int                  port;
+    ngx_str_t           *port_name;    /* ":80" */
+    ngx_str_t           *server_name;
+    ngx_array_t         *virtual_names;
 
     int         filter;
 
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -39,6 +39,14 @@ static char error_404_page[] =
 ;
 
 
+static char error_405_page[] =
+"<html>" CRLF
+"<head><title>405 Not Allowed</title></head>" CRLF
+"<body bgcolor=\"white\">" CRLF
+"<center><h1>405 Not Allowed</h1></center>" CRLF
+;
+
+
 static char error_408_page[] =
 "<html>" CRLF
 "<head><title>408 Request Time-out</title></head>" CRLF
@@ -89,7 +97,7 @@ static ngx_str_t error_pages[] = {
     ngx_null_string,             /* 402 */
     ngx_string(error_403_page),
     ngx_string(error_404_page),
-    ngx_null_string,             /* 405 */
+    ngx_string(error_405_page),
     ngx_null_string,             /* 406 */
     ngx_null_string,             /* 407 */
     ngx_string(error_408_page),
--- a/src/http/ngx_http_write_filter.c
+++ b/src/http/ngx_http_write_filter.c
@@ -28,13 +28,11 @@ static ngx_command_t ngx_http_write_filt
      offsetof(ngx_http_write_filter_conf_t, buffer_output),
      NULL},
 
-    {ngx_null_string, 0, NULL, 0, 0, NULL}
+    ngx_null_command
 };
 
 
 ngx_http_module_t  ngx_http_write_filter_module_ctx = {
-    NGX_HTTP_MODULE,
-
     NULL,                                  /* create main configuration */
     NULL,                                  /* init main configuration */
 
@@ -47,10 +45,10 @@ ngx_http_module_t  ngx_http_write_filter
 
 
 ngx_module_t  ngx_http_write_filter_module = {
+    NGX_MODULE,
     &ngx_http_write_filter_module_ctx,     /* module context */
-    0,                                     /* module index */
     ngx_http_write_filter_commands,        /* module directives */
-    NGX_HTTP_MODULE_TYPE,                  /* module type */
+    NGX_HTTP_MODULE,                       /* module type */
     ngx_http_write_filter_init             /* init module */
 };
 
@@ -63,12 +61,11 @@ int ngx_http_write_filter(ngx_http_reque
     ngx_http_write_filter_ctx_t   *ctx;
     ngx_http_write_filter_conf_t  *conf;
 
-
     ctx = ngx_http_get_module_ctx(r->main ? r->main : r,
-                                  ngx_http_write_filter_module_ctx);
+                                  ngx_http_write_filter_module);
 
     if (ctx == NULL) {
-        ngx_http_create_ctx(r, ctx, ngx_http_write_filter_module_ctx,
+        ngx_http_create_ctx(r, ctx, ngx_http_write_filter_module,
                             sizeof(ngx_http_write_filter_ctx_t), NGX_ERROR);
     }
 
@@ -122,7 +119,7 @@ int ngx_http_write_filter(ngx_http_reque
     }
 
     conf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
-                                        ngx_http_write_filter_module_ctx);
+                                        ngx_http_write_filter_module);
 
 #if (NGX_DEBUG_WRITE_FILTER)
     ngx_log_debug(r->connection->log,
--- a/src/os/unix/ngx_freebsd_config.h
+++ b/src/os/unix/ngx_freebsd_config.h
@@ -15,7 +15,9 @@
 #include <sys/resource.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
+#include <netinet/tcp.h>        /* TCP_NOPUSH */
 #include <arpa/inet.h>
+#include <netdb.h>
 #include <osreldate.h>
 
 
--- a/src/os/unix/ngx_freebsd_init.h
+++ b/src/os/unix/ngx_freebsd_init.h
@@ -13,6 +13,8 @@ ssize_t ngx_unix_recv(ngx_connection_t *
 ssize_t ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *entry);
 /* */
 
+ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in);
+
 
 extern int ngx_freebsd_kern_osreldate;
 extern int ngx_freebsd_hw_ncpu;
--- a/src/os/unix/ngx_freebsd_sendfile_chain.c
+++ b/src/os/unix/ngx_freebsd_sendfile_chain.c
@@ -1,20 +1,27 @@
 
 #include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_freebsd_init.h>
 
-#include <ngx_core.h>
-#include <ngx_types.h>
-#include <ngx_alloc.h>
-#include <ngx_array.h>
-#include <ngx_hunk.h>
-#include <ngx_connection.h>
-#include <ngx_sendv.h>
-#include <ngx_sendfile.h>
-#include <ngx_freebsd_init.h>
+
+/*
+   sendfile() often sends 4K pages over ethernet in 3 packets: 2x1460 and 1176
+   or in 6 packets: 5x1460 and 892.  Besides although sendfile() allows
+   to pass the header and the trailer it never sends the header or the trailer
+   with the part of the file in one packet.  So we use TCP_NOPUSH (similar
+   to Linux's TCP_CORK) to postpone the sending - it not only sends the header
+   and the first part of the file in one packet but also sends 4K pages
+   in the full packets.
+
+   The turning TCP_NOPUSH off flushes any pending data at least in FreeBSD 4.2,
+   although there's special fix in src/sys/netinet/tcp_usrreq.c just before
+   FreeBSD 4.5.
+*/
 
 
 ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
 {
-    int              rc;
+    int              rc, eintr, tcp_nopush;
     char            *prev;
     size_t           hsize, size;
     off_t            sent;
@@ -23,160 +30,208 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(
     ngx_err_t        err;
     ngx_array_t      header, trailer;
     ngx_hunk_t      *file;
-    ngx_chain_t     *ce;
+    ngx_chain_t     *ce, *tail;
+
+    tcp_nopush = 0;
+
+    do {
+        ce = in;
+        file = NULL;
+        hsize = 0;
+        eintr = 0;
+
+        ngx_init_array(header, c->pool, 10, sizeof(struct iovec),
+                       NGX_CHAIN_ERROR);
+        ngx_init_array(trailer, c->pool, 10, sizeof(struct iovec),
+                       NGX_CHAIN_ERROR);
+
+        /* create the header iovec */
+        if (ngx_hunk_in_memory_only(ce->hunk)) {
+            prev = NULL;
+            iov = NULL;
+
+            /* create the iovec and coalesce the neighbouring chain entries */
+            while (ce && ngx_hunk_in_memory_only(ce->hunk)) {
 
-    ce = in;
-    file = NULL;
-    hsize = 0;
+                if (prev == ce->hunk->pos) {
+                    iov->iov_len += ce->hunk->last - ce->hunk->pos;
+                    prev = ce->hunk->last;
+
+                } else {
+                    ngx_test_null(iov, ngx_push_array(&header),
+                                  NGX_CHAIN_ERROR);
+                    iov->iov_base = ce->hunk->pos;
+                    iov->iov_len = ce->hunk->last - ce->hunk->pos;
+                    prev = ce->hunk->last;
+                }
 
-    ngx_init_array(header, c->pool, 10, sizeof(struct iovec), NGX_CHAIN_ERROR);
-    ngx_init_array(trailer, c->pool, 10, sizeof(struct iovec), NGX_CHAIN_ERROR);
+                hsize += ce->hunk->last - ce->hunk->pos;
+
+                ce = ce->next;
+            }
+        }
+
+        /* TODO: coalesce the neighbouring file hunks */
+        if (ce && (ce->hunk->type & NGX_HUNK_FILE)) {
+            file = ce->hunk;
+            ce = ce->next;
+        }
 
-    /* create the header iovec */
-    if (ngx_hunk_in_memory_only(ce->hunk)) {
-        prev = NULL;
-        iov = NULL;
+        /* create the trailer iovec */
+        if (ce && ngx_hunk_in_memory_only(ce->hunk)) {
+            prev = NULL;
+            iov = NULL;
+
+            /* create the iovec and coalesce the neighbouring chain entries */
+            while (ce && ngx_hunk_in_memory_only(ce->hunk)) {
+
+                if (prev == ce->hunk->pos) {
+                    iov->iov_len += ce->hunk->last - ce->hunk->pos;
+                    prev = ce->hunk->last;
 
-        /* create the iovec and coalesce the neighbouring chain entries */
-        while (ce && ngx_hunk_in_memory_only(ce->hunk)) {
+                } else {
+                    ngx_test_null(iov, ngx_push_array(&trailer),
+                                  NGX_CHAIN_ERROR);
+                    iov->iov_base = ce->hunk->pos;
+                    iov->iov_len = ce->hunk->last - ce->hunk->pos;
+                    prev = ce->hunk->last;
+                }
+
+                ce = ce->next;
+            }
+        }
 
-            if (prev == ce->hunk->pos) {
-                iov->iov_len += ce->hunk->last - ce->hunk->pos;
-                prev = ce->hunk->last;
+        tail = ce;
+
+        if (file) {
 
-            } else {
-                ngx_test_null(iov, ngx_push_array(&header), NGX_CHAIN_ERROR);
-                iov->iov_base = ce->hunk->pos;
-                iov->iov_len = ce->hunk->last - ce->hunk->pos;
-                prev = ce->hunk->last;
+            if (tcp_nopush == 0) {
+                tcp_nopush = 1;
+                if (setsockopt(c->fd, IPPROTO_TCP, TCP_NOPUSH,
+                               (const void *) &tcp_nopush,
+                               sizeof(int)) == -1)
+                {
+                    ngx_log_error(NGX_LOG_CRIT, c->log, ngx_errno,
+                                  "setsockopt(TCP_NO_PUSH) failed");
+                    return NGX_CHAIN_ERROR;
+                }
+            }
+
+            hdtr.headers = (struct iovec *) header.elts;
+            hdtr.hdr_cnt = header.nelts;
+            hdtr.trailers = (struct iovec *) trailer.elts;
+            hdtr.trl_cnt = trailer.nelts;
+
+            if (ngx_freebsd_sendfile_nbytes_bug == 0) {
+                hsize = 0;
             }
 
-            if (ngx_freebsd_sendfile_nbytes_bug) {
-                hsize += ce->hunk->last - ce->hunk->pos;
+            rc = sendfile(file->file->fd, c->fd, file->file_pos,
+                          (size_t) (file->file_last - file->file_pos) + hsize,
+                          &hdtr, &sent, 0);
+
+            if (rc == -1) {
+                err = ngx_errno;
+
+                if (err == NGX_EINTR) {
+                    eintr = 1;
+                }
+
+                if (err == NGX_EAGAIN || err == NGX_EINTR) {
+                    ngx_log_error(NGX_LOG_INFO, c->log, err,
+                                  "sendfile() sent only %qd bytes", sent);
+
+                } else {
+                    ngx_log_error(NGX_LOG_CRIT, c->log, err,
+                                  "sendfile() failed");
+                    return NGX_CHAIN_ERROR;
+                }
+            }
+
+#if (NGX_DEBUG_WRITE_CHAIN)
+            ngx_log_debug(c->log, "sendfile: %d, @%qd %qd:%d" _
+                          rc _ file->file_pos _ sent _
+                          (size_t) (file->file_last - file->file_pos) + hsize);
+#endif
+
+        } else {
+            rc = writev(c->fd, (struct iovec *) header.elts, header.nelts);
+
+            if (rc == -1) {
+                err = ngx_errno;
+                if (err == NGX_EAGAIN) {
+                    ngx_log_error(NGX_LOG_INFO, c->log, err, "writev() EAGAIN");
+
+                } else if (err == NGX_EINTR) {
+                    eintr = 1;
+                    ngx_log_error(NGX_LOG_INFO, c->log, err, "writev() EINTR");
+
+                } else {
+                    ngx_log_error(NGX_LOG_CRIT, c->log, err, "writev() failed");
+                    return NGX_CHAIN_ERROR;
+                }
             }
 
-            ce = ce->next;
-        }
-    }
+            sent = rc > 0 ? rc : 0;
 
-    /* TODO: coalesce the neighbouring file hunks */
-    if (ce && (ce->hunk->type & NGX_HUNK_FILE)) {
-        file = ce->hunk;
-        ce = ce->next;
-    }
+#if (NGX_DEBUG_WRITE_CHAIN)
+            ngx_log_debug(c->log, "writev: %qd" _ sent);
+#endif
+        }
 
-    /* create the trailer iovec */
-    if (ce && ngx_hunk_in_memory_only(ce->hunk)) {
-        prev = NULL;
-        iov = NULL;
+        c->sent += sent;
 
-        /* create the iovec and coalesce the neighbouring chain entries */
-        while (ce && ngx_hunk_in_memory_only(ce->hunk)) {
+        for (ce = in; ce && sent > 0; ce = ce->next) {
 
-            if (prev == ce->hunk->pos) {
-                iov->iov_len += ce->hunk->last - ce->hunk->pos;
-                prev = ce->hunk->last;
-
+            if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
+                size = ce->hunk->last - ce->hunk->pos;
             } else {
-                ngx_test_null(iov, ngx_push_array(&trailer), NGX_CHAIN_ERROR);
-                iov->iov_base = ce->hunk->pos;
-                iov->iov_len = ce->hunk->last - ce->hunk->pos;
-                prev = ce->hunk->last;
+                size = ce->hunk->file_last - ce->hunk->file_pos;
             }
 
-            ce = ce->next;
+            if (sent >= size) {
+                sent -= size;
+
+                if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
+                    ce->hunk->pos = ce->hunk->last;
+                }
+
+                if (ce->hunk->type & NGX_HUNK_FILE) {
+                    ce->hunk->file_pos = ce->hunk->file_last;
+                }
+
+                continue;
+            }
+
+            if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
+                ce->hunk->pos += sent;
+            }
+
+            if (ce->hunk->type & NGX_HUNK_FILE) {
+                ce->hunk->file_pos += sent;
+            }
+
+            break;
+        }
+
+        ngx_destroy_array(&trailer);
+        ngx_destroy_array(&header);
+
+        in = ce;
+
+    } while ((tail && tail == ce) || eintr);
+
+    if (tcp_nopush == 1) {
+        tcp_nopush = 0;
+        if (setsockopt(c->fd, IPPROTO_TCP, TCP_NOPUSH,
+                       (const void *) &tcp_nopush,
+                       sizeof(int)) == -1)
+        {
+            ngx_log_error(NGX_LOG_CRIT, c->log, ngx_errno,
+                          "setsockopt(!TCP_NO_PUSH) failed");
+            return NGX_CHAIN_ERROR;
         }
     }
 
-    if (file) {
-        hdtr.headers = (struct iovec *) header.elts;
-        hdtr.hdr_cnt = header.nelts;
-        hdtr.trailers = (struct iovec *) trailer.elts;
-        hdtr.trl_cnt = trailer.nelts;
-
-        rc = sendfile(file->file->fd, c->fd, file->file_pos,
-                      (size_t) (file->file_last - file->file_pos) + hsize,
-                      &hdtr, &sent, 0);
-
-        if (rc == -1) {
-            err = ngx_errno;
-            if (err == NGX_EAGAIN || err == NGX_EINTR) {
-                ngx_log_error(NGX_LOG_INFO, c->log, err,
-                              "sendfile() sent only %qd bytes", sent);
-
-            } else {
-                ngx_log_error(NGX_LOG_CRIT, c->log, err, "sendfile() failed");
-                return NGX_CHAIN_ERROR;
-            }
-        }
-
-#if (NGX_DEBUG_WRITE_CHAIN)
-        ngx_log_debug(c->log, "sendfile: %d, @%qd %qd:%d" _
-                      rc _ file->file_pos _ sent _
-                      (size_t) (file->file_last - file->file_pos) + hsize);
-#endif
-
-    } else {
-        rc = writev(c->fd, (struct iovec *) header.elts, header.nelts);
-
-        if (rc == -1) {
-            err = ngx_errno;
-            if (err == NGX_EAGAIN) {
-                ngx_log_error(NGX_LOG_INFO, c->log, err, "writev() EAGAIN");
-
-            } else if (err == NGX_EINTR) {
-                ngx_log_error(NGX_LOG_INFO, c->log, err, "writev() EINTR");
-
-            } else {
-                ngx_log_error(NGX_LOG_CRIT, c->log, err, "writev() failed");
-                return NGX_CHAIN_ERROR;
-            }
-        }
-
-        sent = rc > 0 ? rc : 0;
-    }
-
-#if (NGX_DEBUG_WRITE_CHAIN)
-    ngx_log_debug(c->log, "sendv: %qd" _ sent);
-#endif
-
-    c->sent += sent;
-
-    for (ce = in; ce && sent > 0; ce = ce->next) {
-
-        if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
-            size = ce->hunk->last - ce->hunk->pos;
-        } else {
-            size = ce->hunk->file_last - ce->hunk->file_pos;
-        }
-
-        if (sent >= size) {
-            sent -= size;
-
-            if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
-                ce->hunk->pos = ce->hunk->last;
-            }
-
-            if (ce->hunk->type & NGX_HUNK_FILE) {
-                ce->hunk->file_pos = ce->hunk->file_last;
-            }
-
-            continue;
-        }
-
-        if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
-            ce->hunk->pos += sent;
-        }
-
-        if (ce->hunk->type & NGX_HUNK_FILE) {
-            ce->hunk->file_pos += sent;
-        }
-
-        break;
-    }
-
-    ngx_destroy_array(&trailer);
-    ngx_destroy_array(&header);
-
     return ce;
 }
--- a/src/os/unix/ngx_recv.c
+++ b/src/os/unix/ngx_recv.c
@@ -1,94 +1,118 @@
 
 #include <ngx_config.h>
 #include <ngx_core.h>
-#include <ngx_errno.h>
-#include <ngx_log.h>
-#include <ngx_recv.h>
-#include <ngx_connection.h>
+
 
+static int ngx_unix_recv_error(ngx_event_t *rev, ngx_err_t err);
+
+
+#if (HAVE_KQUEUE)
 
 ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size)
 {
     ssize_t       n;
-    ngx_err_t     err;
-    ngx_event_t  *ev;
+    ngx_event_t  *rev;
 
-    ev = c->read;
+    rev = c->read;
 
-#if (HAVE_KQUEUE) /* DEBUG */
     if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
         ngx_log_debug(c->log, "recv: eof:%d, avail:%d, err:%d" _
-                      ev->eof _ ev->available _ ev->error);
-    }
-#endif
-
-#if (HAVE_KQUEUE)
-
-    if ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT)
-        && ev->eof && ev->available == 0) {
+                      rev->eof _ rev->available _ rev->error);
 
-        if (ev->error == 0) {
-            return 0;
-        }
-
-        ngx_set_socket_errno(ev->error);
-        err = ev->error;
-        n = -1;
+        if (rev->available == 0) {
+            if (rev->eof) {
+                if (rev->error) {
+                    rev->ready = 0;
+                    ngx_set_socket_errno(rev->error);
+                    return ngx_unix_recv_error(rev, rev->error);
+                }
+                return 0;
 
-    } else {
-        n = recv(c->fd, buf, size, 0);
-
-ngx_log_debug(c->log, "recv: read:%d:%d" _ n _ size);
-
-        if (n == -1) {
-            err = ngx_socket_errno;
+            } else {
+                return NGX_AGAIN;
+            }
         }
     }
 
-#else /* not kqueue */
+    do {
+        n = recv(c->fd, buf, size, 0);
 
-    n = recv(c->fd, buf, size, 0);
-
-ngx_log_debug(c->log, "recv: read:%d:%d" _ n _ size);
+        ngx_log_debug(c->log, "recv: %d:%d" _ n _ size);
 
-    if (n == -1) {
-        err = ngx_socket_errno;
-    }
-
-#endif
+        if (n >= 0) {
+            if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
+                rev->available -= n;
+                if (rev->available == 0) {
+                    rev->ready = 0;
+                }
 
-    if (n == -1) {
-        ev->ready = 0;
+                return n;
+            }
 
-        if (err == NGX_ECONNRESET && ev->ignore_econnreset) {
-            return 0;
+            if ((size_t) n < size) {
+                rev->ready = 0;
+            }
+
+            return n;
         }
 
-        if (err == NGX_EAGAIN) {
-            ngx_log_error(NGX_LOG_INFO, c->log, err, "recv() returned EAGAIN");
-            return NGX_AGAIN;
-        }
-
-        ngx_log_error(NGX_LOG_ERR, c->log, err, "recv() failed");
-        return NGX_ERROR;
-    }
-
-#if (HAVE_KQUEUE)
+        rev->ready = 0;
+        n = ngx_unix_recv_error(rev, ngx_socket_errno);
 
-    if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
-        ev->available -= n;
-        if (ev->available == 0) {
-            ev->ready = 0;
-        }
-
-        return n;
-    }
-
-#endif
-
-    if ((size_t) n < size) {
-        ev->ready = 0;
-    }
+    } while (n == NGX_EINTR);
 
     return n;
 }
+
+#else /* ! NAVE_KQUEUE */
+
+ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size)
+{
+    ssize_t       n;
+    ngx_event_t  *rev;
+
+    rev = c->read;
+
+    do {
+        n = recv(c->fd, buf, size, 0);
+
+        ngx_log_debug(c->log, "recv: %d:%d" _ n _ size);
+
+        if (n >= 0) {
+            if ((size_t) n < size) {
+                rev->ready = 0;
+            }
+            return n;
+        }
+
+        rev->ready = 0;
+        n = ngx_unix_recv_error(rev, ngx_socket_errno);
+
+    } while (n == NGX_EINTR);
+
+    return n;
+}
+
+#endif /* NAVE_KQUEUE */
+
+
+static int ngx_unix_recv_error(ngx_event_t *rev, ngx_err_t err)
+{
+    if (err == NGX_ECONNRESET && rev->ignore_econnreset) {
+        return 0;
+    }
+
+    if (err == NGX_EAGAIN) {
+        ngx_log_error(NGX_LOG_INFO, rev->log, err, "recv() returned EAGAIN");
+        return NGX_AGAIN;
+    }
+
+    if (err == NGX_EINTR) {
+        ngx_log_error(NGX_LOG_INFO, rev->log, err, "recv() returned EINTR");
+        return NGX_EINTR;
+    }
+
+    ngx_log_error(NGX_LOG_ERR, rev->log, err, "recv() failed");
+
+    return NGX_ERROR;
+}