changeset 91:637625a2acdb

nginx-0.0.1-2003-05-19-20:39:14 import
author Igor Sysoev <igor@sysoev.ru>
date Mon, 19 May 2003 16:39:14 +0000
parents 37530da31268
children 19cc647ecd91
files src/core/nginx.c src/core/ngx_alloc.h src/core/ngx_array.h src/core/ngx_conf_file.c src/core/ngx_conf_file.h src/core/ngx_config.h src/core/ngx_connection.h src/core/ngx_core.h src/core/ngx_modules.c src/core/ngx_string.h src/event/modules/ngx_aio_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/event/ngx_event_timer.h src/http/modules/ngx_http_index_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_parse.c src/http/ngx_http_request.h src/http/ngx_http_write_filter.c src/os/unix/ngx_freebsd_init.c src/os/unix/ngx_freebsd_init.h src/os/unix/ngx_init.c src/os/unix/ngx_os_init.h src/os/unix/ngx_recv.c src/os/unix/ngx_recv.h src/os/unix/ngx_unix_init.c src/os/win32/ngx_init.c src/os/win32/ngx_os_init.h
diffstat 40 files changed, 1498 insertions(+), 929 deletions(-) [+]
line wrap: on
line diff
--- a/src/core/nginx.c
+++ b/src/core/nginx.c
@@ -4,6 +4,7 @@
 #include <ngx_config.h>
 
 #include <ngx_core.h>
+#include <ngx_connection.h>
 #include <ngx_os_init.h>
 #include <ngx_string.h>
 #include <ngx_errno.h>
@@ -13,7 +14,6 @@
 #include <ngx_array.h>
 #include <ngx_socket.h>
 #include <ngx_server.h>
-#include <ngx_connection.h>
 #include <ngx_listen.h>
 #include <ngx_conf_file.h>
 
@@ -33,8 +33,12 @@ u_int  ngx_sendfile_flags;
 ngx_server_t  ngx_server;
 /* */
 
-ngx_log_t     ngx_log;
-ngx_pool_t   *ngx_pool;
+ngx_log_t       ngx_log;
+ngx_pool_t     *ngx_pool;
+void        ****ngx_conf_ctx;
+
+
+ngx_os_io_t  ngx_io;
 
 
 int ngx_max_module;
@@ -55,94 +59,76 @@ int main(int argc, char *const *argv)
     ngx_log.log_level = NGX_LOG_DEBUG;
 
     if (ngx_os_init(&ngx_log) == NGX_ERROR) {
-        exit(1);
+        return 1;
     }
 
     ngx_pool = ngx_create_pool(16 * 1024, &ngx_log);
     /* */
 
-#if (WIN32)
-
-    if (ngx_init_sockets(&ngx_log) == NGX_ERROR) {
-        exit(1);
-    }
-
-#else
-
-    ngx_set_signals(&ngx_log);
-
-#endif
-
-    ngx_init_array(ngx_listening_sockets, ngx_pool, 10, sizeof(ngx_listen_t),
-                   1);
-
     ngx_max_module = 0;
     for (i = 0; ngx_modules[i]; i++) {
         ngx_modules[i]->index = ngx_max_module++;
     }
 
-    ngx_memzero(&conf, sizeof(ngx_conf_t));
+    /* life cycle */
 
-    ngx_test_null(conf.args, ngx_create_array(ngx_pool, 10, sizeof(ngx_str_t)),
-                  1);
+    {
+        ngx_init_array(ngx_listening_sockets,
+                       ngx_pool, 10, sizeof(ngx_listen_t),
+                       1);
 
-    ngx_test_null(conf.ctx,
-                  ngx_pcalloc(ngx_pool, ngx_max_module * sizeof(void *)),
-                  1);
+        ngx_memzero(&conf, sizeof(ngx_conf_t));
 
-    conf.pool = ngx_pool;
-    conf.log = &ngx_log;
-    conf.module_type = NGX_CORE_MODULE_TYPE;
-    conf.cmd_type = NGX_MAIN_CONF;
+        ngx_test_null(conf.args,
+                      ngx_create_array(ngx_pool, 10, sizeof(ngx_str_t)),
+                      1);
+
+        ngx_test_null(ngx_conf_ctx,
+                      ngx_pcalloc(ngx_pool, ngx_max_module * sizeof(void *)),
+                      1);
 
-    conf_file.len = sizeof("nginx.conf") - 1;
-    conf_file.data = "nginx.conf";
+        conf.ctx = ngx_conf_ctx;
+        conf.pool = ngx_pool;
+        conf.log = &ngx_log;
+        conf.module_type = NGX_CORE_MODULE_TYPE;
+        conf.cmd_type = NGX_MAIN_CONF;
 
-    if (ngx_conf_parse(&conf, &conf_file) != NGX_CONF_OK) {
-        return 1;
-    }
+        conf_file.len = sizeof("nginx.conf") - 1;
+        conf_file.data = "nginx.conf";
 
-    ngx_init_temp_number();
+        if (ngx_conf_parse(&conf, &conf_file) != NGX_CONF_OK) {
+            return 1;
+        }
+
+        ngx_init_temp_number();
 
-    for (i = 0; ngx_modules[i]; i++) {
-        if (ngx_modules[i]->init_module) {
-            if (ngx_modules[i]->init_module(ngx_pool) == NGX_ERROR) {
-                return 1;
+        ngx_io = ngx_os_io;
+
+        for (i = 0; ngx_modules[i]; i++) {
+            if (ngx_modules[i]->init_module) {
+                if (ngx_modules[i]->init_module(ngx_pool) == NGX_ERROR) {
+                    return 1;
+                }
             }
         }
-    }
+
+        ngx_open_listening_sockets(&ngx_log);
 
-    ngx_open_listening_sockets(&ngx_log);
+        /* TODO: daemon, once only */
 
-    /* TODO: daemon */
+        /* TODO: fork */
 
-    /* TODO: fork */
+        ngx_pre_thread(&ngx_listening_sockets, ngx_pool, &ngx_log);
 
-    ngx_pre_thread(&ngx_listening_sockets, ngx_pool, &ngx_log);
+        /* TODO: threads */
 
-    /* TODO: threads */
-
-    /* STUB */
-    ngx_worker(&ngx_log);
+        /* STUB */
+        ngx_worker(&ngx_log);
+    }     
 
     return 0;
 }
 
-#if !(WIN32)
-static void ngx_set_signals(ngx_log_t *log)
-{
-    struct sigaction sa;
-
-    ngx_memzero(&sa, sizeof(struct sigaction));
-    sa.sa_handler = SIG_IGN;
-    sigemptyset(&sa.sa_mask);
-    if (sigaction(SIGPIPE, &sa, NULL) == -1) {
-        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
-                      "sigaction(SIGPIPE, SIG_IGN) failed");
-        exit(1);
-    }
-}
-#endif
 
 static void ngx_open_listening_sockets(ngx_log_t *log)
 {
--- a/src/core/ngx_alloc.h
+++ b/src/core/ngx_alloc.h
@@ -42,5 +42,7 @@ void ngx_destroy_pool(ngx_pool_t *pool);
 void *ngx_palloc(ngx_pool_t *pool, size_t size);
 void *ngx_pcalloc(ngx_pool_t *pool, size_t size);
 
+#define ngx_free   free
+
 
 #endif /* _NGX_ALLOC_H_INCLUDED_ */
--- a/src/core/ngx_array.h
+++ b/src/core/ngx_array.h
@@ -7,7 +7,7 @@
 #include <ngx_alloc.h>
 
 typedef struct {
-    char       *elts;
+    void       *elts;
     int         nelts;
     size_t      size;
     int         nalloc;
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -19,7 +19,7 @@ char *ngx_conf_parse(ngx_conf_t *cf, ngx
 {
     int               i, rc, found;
     char             *rv;
-    void             *conf, **pconf;
+    void             *conf, **confp;
     ngx_str_t        *name;
     ngx_fd_t          fd;
     ngx_conf_file_t  *prev;
@@ -164,10 +164,10 @@ ngx_log_debug(cf->log, "command '%s'" _ 
                         conf = &(((void **) cf->ctx)[ngx_modules[i]->index]);
 
                     } else if (cf->ctx) {
-                        pconf = *(void **) ((char *) cf->ctx + cmd->conf);
+                        confp = *(void **) ((char *) cf->ctx + cmd->conf);
 
-                        if (pconf) {
-                            conf = pconf[*(int *)(ngx_modules[i]->ctx)];
+                        if (confp) {
+                            conf = confp[*(int *)(ngx_modules[i]->ctx)];
                         }
                     }
 
--- a/src/core/ngx_conf_file.h
+++ b/src/core/ngx_conf_file.h
@@ -96,17 +96,35 @@ struct ngx_conf_s {
 };
 
 
-#define ngx_conf_merge(conf, prev, default)                                  \
+#define ngx_get_conf(module)  ngx_conf_ctx[module.index]
+
+
+#define ngx_conf_init_value(conf, default)                                   \
+    if (conf == NGX_CONF_UNSET) {                                            \
+        conf = default;                                                      \
+    }
+
+#define ngx_conf_init_size_value(conf, default)                              \
+    if (conf == NGX_CONF_UNSET) {                                            \
+        conf = default;                                                      \
+    }
+
+#define ngx_conf_init_msec_value(conf, default)                              \
+    if (conf == NGX_CONF_UNSET) {                                            \
+        conf = default;                                                      \
+    }
+
+#define ngx_conf_merge_value(conf, prev, default)                            \
     if (conf == NGX_CONF_UNSET) {                                            \
         conf = (prev == NGX_CONF_UNSET) ? default : prev;                    \
     }
 
-#define ngx_conf_msec_merge(conf, prev, default)                             \
+#define ngx_conf_merge_msec_value(conf, prev, default)                       \
     if (conf == (ngx_msec_t) NGX_CONF_UNSET) {                               \
         conf = (prev == (ngx_msec_t) NGX_CONF_UNSET) ? default : prev;       \
     }
 
-#define ngx_conf_size_merge(conf, prev, default)                             \
+#define ngx_conf_merge_size_value(conf, prev, default)                       \
     if (conf == (size_t) NGX_CONF_UNSET) {                                   \
         conf = (prev == (size_t) NGX_CONF_UNSET) ? default : prev;           \
     }
@@ -126,7 +144,8 @@ char *ngx_conf_set_msec_slot(ngx_conf_t 
 char *ngx_conf_set_time_slot(ngx_conf_t *cf, ngx_command_t *cmd, char *conf);
 
 
-extern ngx_module_t *ngx_modules[];
+extern ngx_module_t     *ngx_modules[];
+extern void          ****ngx_conf_ctx;
 
 
 #endif /* _NGX_HTTP_CONF_FILE_H_INCLUDED_ */
--- a/src/core/ngx_config.h
+++ b/src/core/ngx_config.h
@@ -92,6 +92,7 @@
 #include <sys/time.h>
 #include <sys/socket.h>
 #include <sys/uio.h>
+#include <sys/resource.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <netdb.h>
--- a/src/core/ngx_connection.h
+++ b/src/core/ngx_connection.h
@@ -81,12 +81,26 @@ EV_VNODE        should notify by some si
 #endif
 
 
+typedef struct {
+    ssize_t       (*recv)(ngx_connection_t *c, char *buf, size_t size);
+    void           *dummy_recv_chain;
+    void           *dummy_send;
+    ngx_chain_t  *(*send_chain)(ngx_connection_t *c, ngx_chain_t *in);
+} ngx_os_io_t;
+
+
+extern ngx_os_io_t  ngx_io;
+
+
+
 extern ngx_chain_t *(*ngx_write_chain_proc)
                                         (ngx_connection_t *c, ngx_chain_t *in);
 
 
 ssize_t ngx_recv_chain(ngx_connection_t *c, ngx_chain_t *ce);
+#if 0
 ngx_chain_t *ngx_write_chain(ngx_connection_t *c, ngx_chain_t *in, off_t flush);
+#endif
 
 
 /* TODO: move it to OS specific file */
--- a/src/core/ngx_core.h
+++ b/src/core/ngx_core.h
@@ -2,6 +2,23 @@
 #define _NGX_CORE_H_INCLUDED_
 
 
+#include <ngx_types.h>
+#include <ngx_time.h>
+#include <ngx_socket.h>
+#include <ngx_files.h>
+
+#include <ngx_log.h>
+#include <ngx_alloc.h>
+#include <ngx_hunk.h>
+#include <ngx_array.h>
+#include <ngx_string.h>
+#include <ngx_file.h>
+#include <ngx_conf_file.h>
+#include <ngx_connection.h>
+#include <ngx_os_init.h>
+
+
+
 #define  NGX_OK          0
 #define  NGX_ERROR      -1
 #define  NGX_AGAIN      -2
--- a/src/core/ngx_modules.c
+++ b/src/core/ngx_modules.c
@@ -7,6 +7,11 @@
 extern ngx_module_t  ngx_events_module;
 extern ngx_module_t  ngx_event_module;
 
+extern ngx_module_t  ngx_select_module;
+#if (HAVE_KQUEUE)
+extern ngx_module_t  ngx_kqueue_module;
+#endif
+
 
 extern ngx_module_t  ngx_http_module;
 extern ngx_module_t  ngx_http_core_module;
@@ -26,6 +31,11 @@ ngx_module_t *ngx_modules[] = {
     &ngx_events_module,
     &ngx_event_module,
 
+    &ngx_select_module,
+#if (HAVE_KQUEUE)
+    &ngx_kqueue_module,
+#endif
+
     /* http */
 
     &ngx_http_module,
--- a/src/core/ngx_string.h
+++ b/src/core/ngx_string.h
@@ -53,4 +53,8 @@ int ngx_rstrncmp(char *s1, char *s2, siz
 int ngx_atoi(char *line, size_t n);
 
 
+#define  ngx_value_helper(n)   #n
+#define  ngx_value(n)          ngx_value_helper(n)
+
+
 #endif /* _NGX_STRING_H_INCLUDED_ */
--- a/src/event/modules/ngx_aio_module.c
+++ b/src/event/modules/ngx_aio_module.c
@@ -21,7 +21,7 @@ int ngx_aio_init(int max_connections, ng
 
     rc = ngx_kqueue_init(max_connections, log);
 
-    ngx_event_flags = NGX_HAVE_AIO_EVENT;
+    ngx_event_flags = NGX_HAVE_AIO_EVENT|NGX_USE_AIO_EVENT;
     ngx_write_chain_proc = ngx_aio_write_chain;
 
     return rc;
--- a/src/event/modules/ngx_kqueue_module.c
+++ b/src/event/modules/ngx_kqueue_module.c
@@ -1,3 +1,4 @@
+
 /*
  * Copyright (C) 2002-2003 Igor Sysoev, http://sysoev.ru
  */
@@ -5,39 +6,30 @@
 
 #include <ngx_config.h>
 #include <ngx_core.h>
-#include <ngx_types.h>
-#include <ngx_log.h>
 #include <ngx_connection.h>
 #include <ngx_event.h>
-#include <ngx_event_timer.h>
-#include <ngx_conf_file.h>
 #include <ngx_kqueue_module.h>
 
 
-/* STUB */
-#define KQUEUE_NCHANGES  512
-#define KQUEUE_NEVENTS   512
+static int ngx_kqueue_init(ngx_log_t *log);
+static void ngx_kqueue_done(ngx_log_t *log);
+static int ngx_kqueue_add_event(ngx_event_t *ev, int event, u_int flags);
+static int ngx_kqueue_del_event(ngx_event_t *ev, int event, u_int flags);
+static int ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags);
+static int ngx_kqueue_process_events(ngx_log_t *log);
 
-
-static int  ngx_kqueue_changes;
-static int  ngx_kqueue_events;
+static void *ngx_kqueue_create_conf(ngx_pool_t *pool);
+static char *ngx_kqueue_init_conf(ngx_pool_t *pool, void *conf);
 
 
-/* should be per-thread if threads are used without thread pool */
-#if 1
-int                     kq;
-#else
-static int              kq;
-#endif
-static struct kevent   *change_list, *event_list;
-static unsigned int     nchanges;
-static int              nevents;
+int                    ngx_kqueue;
 
-static ngx_event_t     *timer_queue;
-/* */
+static struct kevent  *change_list, *event_list;
+static u_int           max_changes, nchanges;
+static int             nevents;
 
 
-static ngx_str_t  kqueue_name = ngx_string("kqueue");
+static ngx_str_t      kqueue_name = ngx_string("kqueue");
 
 static ngx_command_t  ngx_kqueue_commands[] = {
 
@@ -45,21 +37,42 @@ static ngx_command_t  ngx_kqueue_command
      NGX_EVENT_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_num_slot,
      0,
-     addressof(ngx_kqueue_changes),
+     offsetof(ngx_kqueue_conf_t, changes),
      NULL},
 
     {ngx_string("kqueue_events"),
      NGX_EVENT_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_num_slot,
      0,
-     addressof(ngx_kqueue_events),
+     offsetof(ngx_kqueue_conf_t, events),
      NULL},
 
     {ngx_string(""), 0, NULL, 0, 0, NULL}
 };
 
+
+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 */
+
+    { 
+        ngx_kqueue_add_event,              /* add an event */
+        ngx_kqueue_del_event,              /* delete an event */
+        ngx_kqueue_add_event,              /* enable an event */
+        ngx_kqueue_del_event,              /* disable an event */
+        NULL,                              /* add an connection */
+        NULL,                              /* delete an connection */
+        ngx_kqueue_process_events,         /* process the events */
+        ngx_kqueue_init,                   /* init the events */
+        ngx_kqueue_done,                   /* done the events */
+    }
+
+};
+
 ngx_module_t  ngx_kqueue_module = {
-    &kqueue_name,                          /* module context */
+    &ngx_kqueue_module_ctx,                /* module context */
     0,                                     /* module index */
     ngx_kqueue_commands,                   /* module directives */
     NGX_EVENT_MODULE_TYPE,                 /* module type */
@@ -67,109 +80,91 @@ ngx_module_t  ngx_kqueue_module = {
 };
 
 
-
-int ngx_kqueue_init(int max_connections, ngx_log_t *log)
+static int ngx_kqueue_init(ngx_log_t *log)
 {
-    int  change_size, event_size;
+    ngx_kqueue_conf_t  *kcf;
+
+    kcf = ngx_event_get_conf(ngx_kqueue_module_ctx);
 
-    nevents = KQUEUE_NEVENTS;
+ngx_log_debug(log, "CH: %d" _ kcf->changes);
+ngx_log_debug(log, "EV: %d" _ kcf->events);
+
+    max_changes = kcf->changes;
+    nevents = kcf->events;
     nchanges = 0;
-    change_size = sizeof(struct kevent) * KQUEUE_NCHANGES;
-    event_size = sizeof(struct kevent) * KQUEUE_NEVENTS;
 
-    kq = kqueue();
+    ngx_kqueue = kqueue();
 
-    if (kq == -1) {
+    if (ngx_kqueue == -1) {
         ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "kqueue() failed");
         return NGX_ERROR;
     }
 
-    ngx_test_null(change_list, ngx_alloc(change_size, log), NGX_ERROR);
-    ngx_test_null(event_list, ngx_alloc(event_size, log), NGX_ERROR);
+    ngx_test_null(change_list,
+                  ngx_alloc(kcf->changes * sizeof(struct kevent), log),
+                  NGX_ERROR);
+    ngx_test_null(event_list,
+                  ngx_alloc(kcf->events * sizeof(struct kevent), log),
+                  NGX_ERROR);
 
-    timer_queue = ngx_event_init_timer(log);
-    if (timer_queue == NULL) {
+    if (ngx_event_timer_init(log) == NGX_ERROR) {
         return NGX_ERROR;
     }
 
-    ngx_event_actions.add = ngx_kqueue_add_event;
-    ngx_event_actions.del = ngx_kqueue_del_event;
-    ngx_event_actions.timer = ngx_event_add_timer;
-    ngx_event_actions.process = ngx_kqueue_process_events;
-
-#if (HAVE_AIO_EVENT)
-
-    ngx_event_flags = NGX_HAVE_AIO_EVENT;
-
-#else
+    ngx_event_actions = ngx_kqueue_module_ctx.actions;
 
     ngx_event_flags = NGX_HAVE_LEVEL_EVENT
                      |NGX_HAVE_ONESHOT_EVENT
-
 #if (HAVE_CLEAR_EVENT)
                      |NGX_HAVE_CLEAR_EVENT
 #else
                      |NGX_USE_LEVEL_EVENT
 #endif
-
 #if (HAVE_LOWAT_EVENT)
                      |NGX_HAVE_LOWAT_EVENT
 #endif
-
                      |NGX_HAVE_KQUEUE_EVENT;
 
-    ngx_write_chain_proc = ngx_freebsd_write_chain;
-
-#endif
-
     return NGX_OK;
 }
 
 
-void ngx_kqueue_done(ngx_log_t *log)
+static void ngx_kqueue_done(ngx_log_t *log)
 {
-    if (close(kq) == -1) {
+    if (close(ngx_kqueue) == -1) {
         ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "kqueue close() failed");
     }
+
+    ngx_event_timer_done(log);
+
+    ngx_free(change_list);
+    ngx_free(event_list);
 }
 
 
-int ngx_kqueue_add_event(ngx_event_t *ev, int event, u_int flags)
+static int ngx_kqueue_add_event(ngx_event_t *ev, int event, u_int flags)
 {
+    ngx_connection_t  *c;
+
     ev->active = 1;
     ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1: 0;
 
-    /* The event addition or change should be always passed to a kernel
-       because there can be case when event was passed to a kernel then
-       added again to the change_list and then deleted from the change_list
-       by ngx_kqueue_del_event() so the first event still remains in a kernel */
-
-#if 0
-
     if (nchanges > 0
         && ev->index < nchanges
-        && change_list[ev->index].udata == ev)
+        && (void *) ((uintptr_t) change_list[ev->index].udata & ~1) == ev)
     {
-#if (NGX_DEBUG_EVENT)
-        ngx_connection_t *c = (ngx_connection_t *) ev->data;
-        ngx_log_debug(ev->log, "kqueue add event: %d: ft:%d" _ c->fd _ event);
-#endif
+        c = ev->data;
+        ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
+                      "previous event were not passed in kernel", c->fd);
 
-        /* if the event is still not passed to a kernel we change it */
-
-        change_list[ev->index].filter = event;
-        change_list[ev->index].flags = flags;
-
-        return NGX_OK;
+        return NGX_ERROR;
     }
 
-#endif
-
     return ngx_kqueue_set_event(ev, event, EV_ADD | flags);
 }
 
 
-int ngx_kqueue_del_event(ngx_event_t *ev, int event, u_int flags)
+static int ngx_kqueue_del_event(ngx_event_t *ev, int event, u_int flags)
 {
     ngx_event_t  *e;
 
@@ -181,7 +176,8 @@ int ngx_kqueue_del_event(ngx_event_t *ev
     {
 #if (NGX_DEBUG_EVENT)
         ngx_connection_t *c = (ngx_connection_t *) ev->data;
-        ngx_log_debug(ev->log, "kqueue del event: %d: ft:%d" _ c->fd _ event);
+        ngx_log_debug(ev->log, "kqueue event deleted: %d: ft:%d" _
+                      c->fd _ event);
 #endif
 
         /* if the event is still not passed to a kernel we will not pass it */
@@ -207,26 +203,26 @@ int ngx_kqueue_del_event(ngx_event_t *ev
 }
 
 
-int ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags)
+static int ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags)
 {
-    struct timespec    ts;
-    ngx_connection_t  *c;
+    struct timespec     ts;
+    ngx_connection_t   *c;
 
-    c = (ngx_connection_t *) ev->data;
+    c = ev->data;
 
 #if (NGX_DEBUG_EVENT)
     ngx_log_debug(ev->log, "kqueue set event: %d: ft:%d f:%08x" _
                   c->fd _ filter _ flags);
 #endif
 
-    if (nchanges >= KQUEUE_NCHANGES) {
+    if (nchanges >= max_changes) {
         ngx_log_error(NGX_LOG_WARN, ev->log, 0,
                       "kqueue change list is filled up");
 
         ts.tv_sec = 0;
         ts.tv_nsec = 0;
 
-        if (kevent(kq, change_list, nchanges, NULL, 0, &ts) == -1) {
+        if (kevent(ngx_kqueue, change_list, nchanges, NULL, 0, &ts) == -1) {
             ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, "kevent failed");
             return NGX_ERROR;
         }
@@ -265,7 +261,7 @@ int ngx_kqueue_set_event(ngx_event_t *ev
 }
 
 
-int ngx_kqueue_process_events(ngx_log_t *log)
+static int ngx_kqueue_process_events(ngx_log_t *log)
 {
     int              events, instance, i;
     ngx_msec_t       timer, delta;
@@ -292,7 +288,7 @@ int ngx_kqueue_process_events(ngx_log_t 
     ngx_log_debug(log, "kevent timer: %d" _ timer);
 #endif
 
-    events = kevent(kq, change_list, nchanges, event_list, nevents, tp);
+    events = kevent(ngx_kqueue, change_list, nchanges, event_list, nevents, tp);
 
     if (events == -1) {
         ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "kevent failed");
@@ -305,8 +301,8 @@ int ngx_kqueue_process_events(ngx_log_t 
         gettimeofday(&tv, NULL);
         delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta;
 
-        /* Expired timers must be deleted before the events processing
-           because the new timers can be added during the processing */
+        /* The expired timers must be handled before a processing of the events
+           because the new timers can be added during a processing */
 
         ngx_event_expire_timers(delta);
 
@@ -370,8 +366,9 @@ int ngx_kqueue_process_events(ngx_log_t 
                 ev->error = event_list[i].fflags;
             }
 
-            if (ev->oneshot) {
+            if (ev->oneshot && ev->timer_set) {
                 ngx_del_timer(ev);
+                ev->timer_set = 0;
             }
 
             /* fall through */
@@ -392,3 +389,28 @@ int ngx_kqueue_process_events(ngx_log_t 
 
     return NGX_OK;
 }
+
+
+static void *ngx_kqueue_create_conf(ngx_pool_t *pool)
+{
+    ngx_kqueue_conf_t  *kcf;
+
+    ngx_test_null(kcf, ngx_palloc(pool, sizeof(ngx_kqueue_conf_t)),
+                  NGX_CONF_ERROR);
+
+    kcf->changes = NGX_CONF_UNSET;
+    kcf->events = NGX_CONF_UNSET;
+
+    return kcf;
+}
+
+
+static char *ngx_kqueue_init_conf(ngx_pool_t *pool, void *conf)
+{
+    ngx_kqueue_conf_t *kcf = conf;
+
+    ngx_conf_init_value(kcf->changes, 512);
+    ngx_conf_init_value(kcf->events, 512);
+
+    return NGX_CONF_OK;
+}
--- a/src/event/modules/ngx_kqueue_module.h
+++ b/src/event/modules/ngx_kqueue_module.h
@@ -2,22 +2,13 @@
 #define _NGX_KQUEUE_MODULE_H_INCLUDED_
 
 
-#include <ngx_types.h>
-#include <ngx_log.h>
-#include <ngx_event.h>
-
-int ngx_kqueue_init(int max_connections, ngx_log_t *log);
-int ngx_kqueue_add_event(ngx_event_t *ev, int event, u_int flags);
-int ngx_kqueue_del_event(ngx_event_t *ev, int event, u_int flags);
-int ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags);
-void ngx_kqueue_add_timer(ngx_event_t *ev, ngx_msec_t timer);
-int ngx_kqueue_process_events(ngx_log_t *log);
+typedef struct {
+    int   changes;
+    int   events;
+} ngx_kqueue_conf_t;
 
 
-#if 1
-extern int              kq;
-#endif
-
+extern int  ngx_kqueue;
 
 
 #endif /* _NGX_KQUEUE_MODULE_H_INCLUDED_ */
--- a/src/event/modules/ngx_poll_module.c
+++ b/src/event/modules/ngx_poll_module.c
@@ -242,7 +242,10 @@ int ngx_poll_process_events(ngx_log_t *l
         ev->ready = 1;
 
         if (ev->oneshot) {
-            ngx_del_timer(ev);
+            if (ev->timer_set) {
+                ngx_del_timer(ev);
+                ev->timer_set = 0;
+            }
 
             if (ev->write) {
                 ngx_poll_del_event(ev, NGX_WRITE_EVENT, 0);
--- a/src/event/modules/ngx_select_module.c
+++ b/src/event/modules/ngx_select_module.c
@@ -1,16 +1,24 @@
+
+/*
+ * Copyright (C) 2002-2003 Igor Sysoev, http://sysoev.ru
+ */
+
 
 #include <ngx_config.h>
 #include <ngx_core.h>
-#include <ngx_types.h>
-#include <ngx_log.h>
-#include <ngx_time.h>
 #include <ngx_connection.h>
 #include <ngx_event.h>
-#include <ngx_event_timer.h>
-#include <ngx_select_module.h>
 
 
-/* should be per-thread */
+static int ngx_select_init(ngx_log_t *log);
+static void ngx_select_done(ngx_log_t *log);
+static int ngx_select_add_event(ngx_event_t *ev, int event, u_int flags);
+static int ngx_select_del_event(ngx_event_t *ev, int event, u_int flags);
+static int ngx_select_process_events(ngx_log_t *log);
+
+static char *ngx_select_init_conf(ngx_pool_t *pool, void *conf);
+
+
 static fd_set         master_read_fd_set;
 static fd_set         master_write_fd_set;
 static fd_set         work_read_fd_set;
@@ -27,45 +35,67 @@ static u_int          nevents;
 
 static ngx_event_t  **event_index;
 static ngx_event_t  **ready_index;
-static ngx_event_t   *timer_queue;
-/* */
+
+
+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 */
 
-int ngx_select_init(int max_connections, ngx_log_t *log)
+    {
+        ngx_select_add_event,              /* add an event */
+        ngx_select_del_event,              /* delete an event */
+        ngx_select_add_event,              /* enable an event */
+        ngx_select_del_event,              /* disable an event */
+        NULL,                              /* add an connection */
+        NULL,                              /* delete an connection */
+        ngx_select_process_events,         /* process the events */
+        ngx_select_init,                   /* init the events */
+        ngx_select_done                    /* done the events */
+    }
+
+};
+
+ngx_module_t  ngx_select_module = {
+    &ngx_select_module_ctx,                /* module context */
+    0,                                     /* module index */
+    NULL,                                  /* module directives */
+    NGX_EVENT_MODULE_TYPE,                 /* module type */
+    NULL                                   /* init module */
+};
+
+
+static int ngx_select_init(ngx_log_t *log)
 {
-    if (max_connections > FD_SETSIZE) {
-        ngx_log_error(NGX_LOG_EMERG, log, 0,
-#if (WIN32)
-                      "maximum number of descriptors "
-                      "supported by select() is %d", FD_SETSIZE);
-#else
-                      "maximum descriptor number"
-                      "supported by select() is %d", FD_SETSIZE - 1);
-#endif
-        exit(1);
-    }
+    ngx_event_conf_t  *ecf;
+
+    ecf = ngx_event_get_conf(ngx_event_module_ctx);
 
     FD_ZERO(&master_read_fd_set);
     FD_ZERO(&master_write_fd_set);
 
     ngx_test_null(event_index,
-                  ngx_alloc(sizeof(ngx_event_t *) * 2 * max_connections, log),
+                  ngx_alloc(sizeof(ngx_event_t *) * 2 * ecf->connections, log),
                   NGX_ERROR);
 
     ngx_test_null(ready_index,
-                  ngx_alloc(sizeof(ngx_event_t *) * 2 * max_connections, log),
+                  ngx_alloc(sizeof(ngx_event_t *) * 2 * ecf->connections, log),
                   NGX_ERROR);
 
     nevents = 0;
 
-    timer_queue = ngx_event_init_timer(log);
-    if (timer_queue == NULL) {
+    if (ngx_event_timer_init(log) == NGX_ERROR) {
         return NGX_ERROR;
     }
 
-    ngx_event_actions.add = ngx_select_add_event;
-    ngx_event_actions.del = ngx_select_del_event;
-    ngx_event_actions.timer = ngx_event_add_timer;
-    ngx_event_actions.process = ngx_select_process_events;
+    ngx_event_actions = ngx_select_module_ctx.actions;
+
+    ngx_event_flags = NGX_HAVE_LEVEL_EVENT
+                      |NGX_HAVE_ONESHOT_EVENT
+                      |NGX_USE_LEVEL_EVENT;
 
 #if (WIN32)
     max_read = max_write = 0;
@@ -76,11 +106,19 @@ int ngx_select_init(int max_connections,
     return NGX_OK;
 }
 
-int ngx_select_add_event(ngx_event_t *ev, int event, u_int flags)
+
+static void ngx_select_done(ngx_log_t *log)
+{
+    ngx_free(event_index);
+    ngx_free(ready_index);
+}
+
+
+static int ngx_select_add_event(ngx_event_t *ev, int event, u_int flags)
 {
     ngx_connection_t  *c;
 
-    c = (ngx_connection_t *) ev->data;
+    c = ev->data;
 
 #if (NGX_DEBUG_EVENT)
     ngx_log_debug(ev->log, "select fd:%d event:%d" _ c->fd _ event);
@@ -132,10 +170,12 @@ int ngx_select_add_event(ngx_event_t *ev
     return NGX_OK;
 }
 
-int ngx_select_del_event(ngx_event_t *ev, int event, u_int flags)
+
+static int ngx_select_del_event(ngx_event_t *ev, int event, u_int flags)
 {
-    ngx_connection_t *c;
-    c = (ngx_connection_t *) ev->data;
+    ngx_connection_t  *c;
+
+    c = ev->data;
 
     if (ev->index == NGX_INVALID_INDEX)
         return NGX_OK;
@@ -175,7 +215,8 @@ int ngx_select_del_event(ngx_event_t *ev
     return NGX_OK;
 }
 
-int ngx_select_process_events(ngx_log_t *log)
+
+static int ngx_select_process_events(ngx_log_t *log)
 {
     int                ready, found;
     u_int              i, nready;
@@ -298,7 +339,10 @@ int ngx_select_process_events(ngx_log_t 
         ev->ready = 1;
 
         if (ev->oneshot) {
-            ngx_del_timer(ev);
+            if (ev->timer_set) {
+                ngx_del_timer(ev);
+                ev->timer_set = 0;
+            }
 
             if (ev->write)
                 ngx_select_del_event(ev, NGX_WRITE_EVENT, 0);
@@ -315,3 +359,18 @@ int ngx_select_process_events(ngx_log_t 
 
     return NGX_OK;
 }
+
+
+static char *ngx_select_init_conf(ngx_pool_t *pool, void *conf)
+{
+    ngx_event_conf_t  *ecf;
+
+    ecf = ngx_event_get_conf(ngx_event_module_ctx);
+
+    if (ecf->connections > FD_SETSIZE) {
+        return "maximum number of connections "
+               "supported by select() is " ngx_value(FD_SETSIZE);
+    }
+
+    return NGX_CONF_OK;
+}
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -11,7 +11,7 @@
 #include <ngx_event.h>
 #include <ngx_conf_file.h>
 
-#include <ngx_select_module.h>
+extern ngx_event_module_t ngx_select_module_ctx;
 
 #if (HAVE_POLL)
 #include <ngx_poll_module.h>
@@ -22,6 +22,7 @@
 #endif
 
 #if (HAVE_KQUEUE)
+extern ngx_event_module_t ngx_kqueue_module_ctx;
 #include <ngx_kqueue_module.h>
 #endif
 
@@ -36,46 +37,26 @@
 
 
 static char *ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy);
+static char *ngx_event_set_type(ngx_conf_t *cf, ngx_command_t *cmd, char *conf);
+static void *ngx_event_create_conf(ngx_pool_t *pool);
+static char *ngx_event_init_conf(ngx_pool_t *pool, void *conf);
 
 
+int                  ngx_event_flags;
+ngx_event_actions_t  ngx_event_actions;
+
 ngx_connection_t    *ngx_connections;
 ngx_event_t         *ngx_read_events, *ngx_write_events;
 
-#if !(USE_KQUEUE)
 
-ngx_event_type_e     ngx_event_type;
-
-int                  ngx_event_flags;
-
-ngx_event_actions_t  ngx_event_actions;
-
-/* ngx_event_type_e order */
-static int (*ngx_event_init[]) (int max_connections, ngx_log_t *log) = {
-    ngx_select_init,
-#if (HAVE_POLL)
-    ngx_poll_init,
-#endif
-#if (HAVE_DEVPOLL)
-    ngx_devpoll_init,
-#endif
-#if (HAVE_KQUEUE)
-    ngx_kqueue_init,
-#endif
-#if (HAVE_AIO)
-    ngx_aio_init,
-#endif
-#if (HAVE_IOCP)
-    ngx_iocp_init
-#endif
-};
-
-#endif /* USE_KQUEUE */
+static int  ngx_event_max_module;
 
 
 static int  ngx_event_connections;
 
 
 static ngx_str_t  events_name = ngx_string("events");
+static ngx_str_t  event_name = ngx_string("event");
 
 static ngx_command_t  ngx_events_commands[] = {
 
@@ -106,67 +87,87 @@ static ngx_command_t  ngx_event_commands
      NGX_EVENT_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_num_slot,
      0,
-     addressof(ngx_event_connections),
+     offsetof(ngx_event_conf_t, connections),
      NULL},
 
-#if 0
     {ngx_string("type"),
      NGX_EVENT_CONF|NGX_CONF_TAKE1,
      ngx_event_set_type,
      0,
      0,
      NULL},
-#endif
+
+    {ngx_string("timer_queues"),
+     NGX_EVENT_CONF|NGX_CONF_TAKE1,
+     ngx_conf_set_num_slot,
+     0,
+     offsetof(ngx_event_conf_t, timer_queues),
+     NULL},
 
     {ngx_string(""), 0, NULL, 0, 0, NULL}
 };
 
 
+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 */
+
+    { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
+};
+
+
 ngx_module_t  ngx_event_module = {
-    NULL,                                  /* module context */
+    &ngx_event_module_ctx,                 /* module context */
     0,                                     /* module index */
-    ngx_events_commands,                   /* module directives */
+    ngx_event_commands,                    /* module directives */
     NGX_EVENT_MODULE_TYPE,                 /* module type */
     NULL                                   /* init module */
 };
 
 
 
-void ngx_pre_thread(ngx_array_t *ls, ngx_pool_t *pool, ngx_log_t *log)
+int ngx_pre_thread(ngx_array_t *ls, ngx_pool_t *pool, ngx_log_t *log)
 {
-    int  i, fd;
+    int  m, i, fd;
 
     ngx_listen_t      *s;
     ngx_event_t       *ev;
     ngx_connection_t  *c;
+    ngx_event_conf_t  *ecf;
+    ngx_event_module_t  *module;
 
-    /* STUB */
-    int max_connections = 512;
+    ecf = ngx_event_get_conf(ngx_event_module_ctx);
+
+ngx_log_debug(log, "CONN: %d" _ ecf->connections);
+ngx_log_debug(log, "TYPE: %d" _ ecf->type);
 
-#if 0
-    ngx_event_type = NGX_POLL_EVENT_N;
-#endif
-#if 1
-    ngx_event_type = NGX_KQUEUE_EVENT_N;
-#endif
-#if 0
-    ngx_event_type = NGX_DEVPOLL_EVENT_N;
-#endif
-#if 0
-    ngx_event_type = NGX_AIO_EVENT_N;
-#endif
-#if 0
-    ngx_event_type = NGX_IOCP_EVENT_N;
-#endif
+    for (m = 0; ngx_modules[m]; m++) {
+        if (ngx_modules[m]->type != NGX_EVENT_MODULE_TYPE) {
+            continue;
+        }
 
-    if (ngx_init_events(max_connections, log) == NGX_ERROR) {
-        exit(1);
+        module = ngx_modules[m]->ctx;
+        if (module->index == ecf->type) {
+            if (module->actions.init(log) == NGX_ERROR) {
+                return NGX_ERROR;
+            }
+            break;
+        }
     }
 
-    ngx_connections = ngx_alloc(sizeof(ngx_connection_t)
-                                                       * max_connections, log);
-    ngx_read_events = ngx_alloc(sizeof(ngx_event_t) * max_connections, log);
-    ngx_write_events = ngx_alloc(sizeof(ngx_event_t) * max_connections, log);
+    ngx_test_null(ngx_connections,
+                  ngx_alloc(sizeof(ngx_connection_t) * ecf->connections, log),
+                  NGX_ERROR);
+
+    ngx_test_null(ngx_read_events,
+                  ngx_alloc(sizeof(ngx_event_t) * ecf->connections, log),
+                  NGX_ERROR);
+
+    ngx_test_null(ngx_write_events,
+                  ngx_alloc(sizeof(ngx_event_t) * ecf->connections, log),
+                  NGX_ERROR);
 
     /* for each listening socket */
     s = (ngx_listen_t *) ls->elts;
@@ -196,7 +197,9 @@ void ngx_pre_thread(ngx_array_t *ls, ngx
         c->pool_size = s[i].pool_size;
 
         ngx_test_null(ev->log,
-                      ngx_palloc(pool, sizeof(ngx_log_t)), /* void */ ; );
+                      ngx_palloc(pool, sizeof(ngx_log_t)),
+                      NGX_ERROR);
+
         ngx_memcpy(ev->log, c->log, sizeof(ngx_log_t));
         c->read = ev;
         ev->data = c;
@@ -235,6 +238,8 @@ void ngx_pre_thread(ngx_array_t *ls, ngx
 
 #endif
     }
+
+    return NGX_OK;
 }
 
 
@@ -248,35 +253,50 @@ void ngx_worker(ngx_log_t *log)
 }
 
 
-static char *ngx_events_init(ngx_pool_t *pool)
+static char *ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
 {
-    ngx_event_connections = -1;
-    ngx_event_type = -1;
+    int                    m;
+    char                  *rv;
+    void               ***ctx;
+    ngx_conf_t            pcf;
+    ngx_event_conf_t     *ecf;
+    ngx_event_module_t   *module;
 
-    return NGX_CONF_OK;
-}
-
+    /* count the number of the event modules and set up their indices */
 
-static char *ngx_events_postconf(ngx_pool_t *pool)
-{
-    if (ngx_event_connections == -1) {
-        ngx_event_connections = 512;
+    ngx_event_max_module = 0;
+    for (m = 0; ngx_modules[m]; m++) {
+        if (ngx_modules[m]->type != NGX_EVENT_MODULE_TYPE) {
+            continue;
+        }
+
+        module = ngx_modules[m]->ctx;
+        module->index = ngx_event_max_module++;
     }
 
-    return NGX_CONF_OK;
-}
+    ngx_test_null(ctx, ngx_pcalloc(cf->pool, sizeof(void *)), NGX_CONF_ERROR);
 
+    ngx_test_null(*ctx,
+                  ngx_pcalloc(cf->pool, ngx_event_max_module * sizeof(void *)),
+                  NGX_CONF_ERROR);
+
+    *(void **) conf = ctx;
 
-static char *ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
-{
-    char        *rv;
-    ngx_conf_t   pcf;
+    for (m = 0; ngx_modules[m]; m++) {
+        if (ngx_modules[m]->type != NGX_EVENT_MODULE_TYPE) {
+            continue;
+        }
 
-#if 0
-    *(ngx_events_conf_ctx_t **) conf = ctx;
-#endif
+        module = ngx_modules[m]->ctx;
+
+        if (module->create_conf) {
+            ngx_test_null((*ctx)[module->index], module->create_conf(cf->pool),
+                          NGX_CONF_ERROR);
+        }
+    }
 
     pcf = *cf;
+    cf->ctx = ctx;
     cf->module_type = NGX_EVENT_MODULE_TYPE;
     cf->cmd_type = NGX_EVENT_CONF;
     rv = ngx_conf_parse(cf, NULL);
@@ -285,5 +305,90 @@ static char *ngx_events_block(ngx_conf_t
     if (rv != NGX_CONF_OK)
         return rv;
 
+    for (m = 0; ngx_modules[m]; m++) {
+        if (ngx_modules[m]->type != NGX_EVENT_MODULE_TYPE) {
+            continue;
+        }
+
+        module = ngx_modules[m]->ctx;
+
+        if (module->init_conf) {
+            rv = module->init_conf(cf->pool, (*ctx)[module->index]);
+            if (rv != NGX_CONF_OK) {
+                return rv;
+            }
+        }
+    }
+
     return NGX_CONF_OK;
 }
+
+
+static char *ngx_event_set_type(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
+{
+    ngx_event_conf_t *ecf = (ngx_event_conf_t *) conf;
+
+    int                   m;
+    ngx_str_t            *args;
+    ngx_event_module_t   *module;
+
+    if (ecf->type != NGX_CONF_UNSET) {
+        return "duplicate event type" ;
+    }
+
+    args = cf->args->elts;
+
+    for (m = 0; ngx_modules[m]; m++) {
+        if (ngx_modules[m]->type != NGX_EVENT_MODULE_TYPE) {
+            continue;
+        }
+
+        module = ngx_modules[m]->ctx;
+        if (module->name->len == args[1].len) {
+            if (ngx_strcmp(module->name->data, args[1].data) == 0) {
+                ecf->type = module->index;
+                return NGX_CONF_OK;
+            }
+        }
+    }
+
+    return "invalid event type";
+}
+
+
+static void *ngx_event_create_conf(ngx_pool_t *pool)
+{
+    ngx_event_conf_t  *ecf;
+
+    ngx_test_null(ecf, ngx_palloc(pool, sizeof(ngx_event_conf_t)),
+                  NGX_CONF_ERROR);
+
+    ecf->connections = NGX_CONF_UNSET;
+    ecf->type = NGX_CONF_UNSET;
+
+    return ecf;
+}
+
+
+static char *ngx_event_init_conf(ngx_pool_t *pool, void *conf)
+{
+    ngx_event_conf_t *ecf = conf;
+
+#if (HAVE_KQUEUE)
+
+    ngx_conf_init_value(ecf->connections, 1024);
+    ngx_conf_init_value(ecf->type, ngx_kqueue_module_ctx.index);
+
+#else /* HAVE_SELECT */
+
+    ngx_conf_init_value(ecf->connections,
+                        FD_SETSIZE < 1024 ? FD_SETSIZE : 1024);
+
+    ngx_conf_init_value(ecf->type, ngx_select_module_ctx.index);
+
+#endif
+
+    ngx_conf_init_value(ecf->timer_queues, 10);
+
+    return NGX_CONF_OK;
+}
--- a/src/event/ngx_event.h
+++ b/src/event/ngx_event.h
@@ -9,12 +9,16 @@
 #include <ngx_log.h>
 #include <ngx_alloc.h>
 #include <ngx_array.h>
+#include <ngx_conf_file.h>
+
+
 
 /* STUB */
 #define NGX_LOWAT   10000
 
 #define NGX_INVALID_INDEX  0x80000000
 
+
 typedef struct ngx_event_s       ngx_event_t;
 
 #if (HAVE_IOCP)
@@ -141,15 +145,21 @@ typedef enum {
     NGX_DUMMY_EVENT_N    /* avoid comma at end of enumerator list */
 } ngx_event_type_e ;
 
+
+
 typedef struct {
-    int  (*add)(ngx_event_t *ev, int event, u_int flags);
-    int  (*del)(ngx_event_t *ev, int event, u_int flags);
-    void (*timer)(ngx_event_t *ev, ngx_msec_t timer);
-    int  (*process)(ngx_log_t *log);
-    int  (*read)(ngx_event_t *ev, char *buf, size_t size);
-/*
-    int  (*write)(ngx_event_t *ev, char *buf, size_t size);
-*/
+    int   (*add)(ngx_event_t *ev, int event, u_int flags);
+    int   (*del)(ngx_event_t *ev, int event, u_int flags);
+
+    int   (*enable)(ngx_event_t *ev, int event, u_int flags);
+    int   (*disable)(ngx_event_t *ev, int event, u_int flags);
+
+    int   (*add_conn)(ngx_connection_t *c);
+    int   (*del_conn)(ngx_connection_t *c);
+
+    int   (*process)(ngx_log_t *log);
+    int   (*init)(ngx_log_t *log);
+    void  (*done)(ngx_log_t *log);
 } ngx_event_actions_t;
 
 
@@ -273,7 +283,8 @@ typedef struct {
 #elif (HAVE_AIO_EVENT)
 #define ngx_event_recv       ngx_event_aio_read
 #else
-#define ngx_event_recv       ngx_event_recv_core
+#define ngx_event_recv       ngx_io.recv
+#define ngx_write_chain      ngx_io.send_chain
 #endif
 
 #endif
@@ -301,6 +312,33 @@ extern int                   ngx_event_f
 #define NGX_EVENT_MODULE_TYPE 0x544E5645  /* "EVNT" */
 
 #define NGX_EVENT_CONF        0x00200000
+#define NGX_EVENT_MODULE      0
+
+
+typedef struct {
+    int   connections;
+    int   type;
+    int   timer_queues;
+} ngx_event_conf_t;
+
+
+typedef struct {
+    int                     index;
+    ngx_str_t              *name;
+
+    void                 *(*create_conf)(ngx_pool_t *p);
+    char                 *(*init_conf)(ngx_pool_t *p, void *conf);
+
+    ngx_event_actions_t     actions;
+} ngx_event_module_t;
+
+
+extern ngx_module_t        ngx_events_module;
+extern ngx_event_module_t  ngx_event_module_ctx;
+
+
+#define ngx_event_get_conf(module)                                           \
+                          (*(ngx_get_conf(ngx_events_module))) [module.index];
 
 
 
@@ -311,8 +349,11 @@ ssize_t ngx_event_recv_core(ngx_connecti
 int ngx_event_close_connection(ngx_event_t *ev);
 
 
-void ngx_pre_thread(ngx_array_t *ls, ngx_pool_t *pool, ngx_log_t *log);
+int  ngx_pre_thread(ngx_array_t *ls, ngx_pool_t *pool, ngx_log_t *log);
 void ngx_worker(ngx_log_t *log);
 
 
+#include <ngx_event_timer.h>
+
+
 #endif /* _NGX_EVENT_H_INCLUDED_ */
--- a/src/event/ngx_event_accept.c
+++ b/src/event/ngx_event_accept.c
@@ -175,10 +175,7 @@ void ngx_event_accept(ngx_event_t *ev)
 
 #elif (HAVE_KQUEUE)
 
-/*
-        if (ngx_event_type == NGX_HAVE_AIO_EVENT  or NGX_HAVE_KQUEUE_EVENT) {
-*/
-        if (ngx_event_type == NGX_HAVE_KQUEUE_EVENT) {
+        if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
             ev->available--;
         }
 
--- a/src/event/ngx_event_timer.c
+++ b/src/event/ngx_event_timer.c
@@ -9,33 +9,38 @@
 
 #include <ngx_event_timer.h>
 
-/* STUB */
-#define NGX_TIMER_QUEUE_NUM  5
 
-/* should be per-thread */
 static ngx_event_t  *ngx_timer_queue;
 static int           ngx_timer_cur_queue;
-/* */
 static int           ngx_timer_queue_num;
 
 
-ngx_event_t *ngx_event_init_timer(ngx_log_t *log)
+int ngx_event_timer_init(ngx_log_t *log)
 {
-    int  i;
+    int                i;
+    ngx_event_conf_t  *ecf;
 
-    ngx_timer_queue_num = NGX_TIMER_QUEUE_NUM;
+    ecf = ngx_event_get_conf(ngx_event_module_ctx);
+
+    ngx_timer_queue_num = ecf->timer_queues;
     ngx_timer_cur_queue = 0;
 
     ngx_test_null(ngx_timer_queue,
                   ngx_alloc(ngx_timer_queue_num * sizeof(ngx_event_t), log),
-                  NULL);
+                  NGX_ERROR);
 
     for (i = 0; i < ngx_timer_queue_num; i++) {
         ngx_timer_queue[i].timer_prev = &ngx_timer_queue[i];
         ngx_timer_queue[i].timer_next = &ngx_timer_queue[i];
     }
 
-    return ngx_timer_queue;
+    return NGX_OK;;
+}
+
+
+void ngx_event_timer_done(ngx_log_t *log)
+{
+    ngx_free(ngx_timer_queue);
 }
 
 
@@ -126,6 +131,8 @@ void ngx_event_expire_timers(ngx_msec_t 
             delta -= ev->timer_delta;
 
             ngx_del_timer(ev);
+            ev->timer_set = 0;
+
             if (ev->delayed) {
                 ev->delayed = 0;
                 if (ev->ready == 0) {
--- a/src/event/ngx_event_timer.h
+++ b/src/event/ngx_event_timer.h
@@ -9,9 +9,10 @@
 #include <ngx_event.h>
 
 
-ngx_event_t *ngx_event_init_timer(ngx_log_t *log);
+int  ngx_event_timer_init(ngx_log_t *log);
+void ngx_event_timer_done(ngx_log_t *log);
 void ngx_event_add_timer(ngx_event_t *ev, ngx_msec_t timer);
-int ngx_event_find_timer(void);
+int  ngx_event_find_timer(void);
 void ngx_event_expire_timers(ngx_msec_t timer);
 
 
--- a/src/http/modules/ngx_http_index_handler.c
+++ b/src/http/modules/ngx_http_index_handler.c
@@ -38,11 +38,14 @@ static ngx_command_t ngx_http_index_comm
 ngx_http_module_t  ngx_http_index_module_ctx = {
     NGX_HTTP_MODULE,
 
-    NULL,                                  /* create server config */
-    NULL,                                  /* init server config */
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
 
-    ngx_http_index_create_conf,            /* create location config */
-    ngx_http_index_merge_conf              /* merge location config */
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    ngx_http_index_create_conf,            /* create location configration */
+    ngx_http_index_merge_conf              /* merge location configration */
 };
 
 
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -16,17 +16,6 @@ static char *ngx_http_block(ngx_conf_t *
 
 int  ngx_http_max_module;
 
-ngx_array_t  ngx_http_servers;   /* array of ngx_http_core_srv_conf_t */ 
-
-int  ngx_http_post_accept_timeout = 30000;
-int  ngx_http_connection_pool_size = 16384;
-int  ngx_http_request_pool_size = 16384;
-int  ngx_http_client_header_timeout = 60000;
-int  ngx_http_client_header_buffer_size = 1024;
-int  ngx_http_large_client_header = 1;
-
-int  ngx_http_url_in_error_log = 1;
-
 
 ngx_array_t  ngx_http_translate_handlers;
 ngx_array_t  ngx_http_index_handlers;
@@ -63,65 +52,79 @@ ngx_module_t  ngx_http_module = {
 
 static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
 {
-    int                         i, s, l, p, a, n, start;
-    int                         port_found, addr_found, virtual_names;
-    char                       *rv;
-    struct sockaddr_in         *addr_in;
-    ngx_array_t                 in_ports;
-    ngx_listen_t               *ls;
-    ngx_http_module_t          *module;
-    ngx_conf_t                  pcf;
-    ngx_http_conf_ctx_t        *ctx;
-    ngx_http_in_port_t         *in_port, *inport;
-    ngx_http_in_addr_t         *in_addr, *inaddr;
-    ngx_http_core_srv_conf_t  **cscf;
-    ngx_http_listen_t          *lscf;
-    ngx_http_server_name_t     *s_name, *name;
+    int                          mi, m, s, l, p, a, n;
+    int                          port_found, addr_found, virtual_names;
+    char                        *rv;
+    struct sockaddr_in          *addr_in;
+    ngx_array_t                  in_ports;
+    ngx_listen_t                *ls;
+    ngx_http_module_t           *module;
+    ngx_conf_t                   pcf;
+    ngx_http_conf_ctx_t         *ctx;
+    ngx_http_in_port_t          *in_port, *inport;
+    ngx_http_in_addr_t          *in_addr, *inaddr;
+    ngx_http_core_main_conf_t   *cmcf;
+    ngx_http_core_srv_conf_t   **cscfp;
+    ngx_http_core_loc_conf_t   **clcfp;
+    ngx_http_listen_t           *lscf;
+    ngx_http_server_name_t      *s_name, *name;
 
-    ngx_init_array(ngx_http_servers, cf->pool, 10,
-                   sizeof(ngx_http_core_srv_conf_t *), NGX_CONF_ERROR);
-
+    /* the main http context */
     ngx_test_null(ctx,
                   ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)),
                   NGX_CONF_ERROR);
 
     *(ngx_http_conf_ctx_t **) conf = ctx;
 
+
+    /* count the number of the http modules and set up their indices */
+
     ngx_http_max_module = 0;
-    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_TYPE) {
             continue;
         }
 
-        module = (ngx_http_module_t *) ngx_modules[i]->ctx;
-
+        module = (ngx_http_module_t *) ngx_modules[m]->ctx;
         module->index = ngx_http_max_module++;
     }
 
-    /* TODO: http main_conf */
-
+    /* the main http main_conf, it's the same in the all http contexts */
     ngx_test_null(ctx->main_conf,
                   ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module),
                   NGX_CONF_ERROR);
 
-    /* TODO: http srv_conf */
-
+    /* the http null srv_conf, it's used to merge the server{}s' srv_conf's */
     ngx_test_null(ctx->srv_conf,
                   ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module),
                   NGX_CONF_ERROR);
 
-    /* http null loc_conf */
-
+    /* the http null loc_conf, it's used to merge the server{}s' loc_conf's */
     ngx_test_null(ctx->loc_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) {
+
+    /* 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) {
             continue;
         }
 
-        module = (ngx_http_module_t *) ngx_modules[i]->ctx;
+        module = (ngx_http_module_t *) ngx_modules[m]->ctx;
+
+        if (module->create_main_conf) {
+            ngx_test_null(ctx->main_conf[module->index],
+                          module->create_main_conf(cf->pool),
+                          NGX_CONF_ERROR);
+        }
+
+        if (module->create_srv_conf) {
+            ngx_test_null(ctx->srv_conf[module->index],
+                          module->create_srv_conf(cf->pool),
+                          NGX_CONF_ERROR);
+        }
 
         if (module->create_loc_conf) {
             ngx_test_null(ctx->loc_conf[module->index],
@@ -130,6 +133,9 @@ static char *ngx_http_block(ngx_conf_t *
         }
     }
 
+
+    /* parse inside the http{} block */
+
     pcf = *cf;
     cf->ctx = ctx;
     cf->module_type = NGX_HTTP_MODULE_TYPE;
@@ -141,22 +147,71 @@ static char *ngx_http_block(ngx_conf_t *
         return rv;
 
 
-#if 0
-    /* DEBUG STUFF */
-    cscf = (ngx_http_core_srv_conf_t **) ngx_http_servers.elts;
-    for (s = 0; s < ngx_http_servers.nelts; s++) {
-        ngx_http_core_loc_conf_t **loc;
+    /* 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];
+    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) {
+            continue;
+        }
+
+        module = (ngx_http_module_t *) ngx_modules[m]->ctx;
+        mi = module->index;
+
+        /* init http{} main_conf's */
+
+        if (module->init_main_conf) {
+            rv = module->init_main_conf(cf->pool, ctx->main_conf[mi]);
+            if (rv != NGX_CONF_OK) {
+                return rv;
+            }
+        }
+
+        for (s = 0; s < cmcf->servers.nelts; s++) {
+
+            /* merge the server{}s' srv_conf's */
 
-        ngx_log_debug(cf->log, "srv: %08x" _ cscf[s]);
-        loc = (ngx_http_core_loc_conf_t **) cscf[s]->locations.elts;
-        for (l = 0; l < cscf[s]->locations.nelts; l++) {
-            ngx_log_debug(cf->log, "loc: %08x:%s, %08x:%s" _
-                          loc[l] _ loc[l]->name.data _
-                          &loc[l]->doc_root _ loc[l]->doc_root.data);
+            if (module->merge_srv_conf) {
+                rv = module->merge_srv_conf(cf->pool,
+                                            ctx->srv_conf[mi],
+                                            cscfp[s]->ctx->srv_conf[mi]);
+                if (rv != NGX_CONF_OK) {
+                    return rv;
+                }
+            }
+
+            if (module->merge_loc_conf) {
+
+                /* merge the server{}'s loc_conf */
+
+                rv = module->merge_loc_conf(cf->pool,
+                                            ctx->loc_conf[mi],
+                                            cscfp[s]->ctx->loc_conf[mi]);
+                if (rv != NGX_CONF_OK) {
+                    return rv;
+                }
+
+                /* merge the locations{}' loc_conf's */
+
+                clcfp = (ngx_http_core_loc_conf_t **)cscfp[s]->locations.elts;
+
+                for (l = 0; l < cscfp[s]->locations.nelts; l++) {
+                    rv = module->merge_loc_conf(cf->pool,
+                                                cscfp[s]->ctx->loc_conf[mi],
+                                                clcfp[l]->loc_conf[mi]);
+                    if (rv != NGX_CONF_OK) {
+                        return rv;
+                    }
+                }
+            }
         }
     }
-    /**/
-#endif
+
+
+    /* init list of the handlers */
 
     ngx_init_array(ngx_http_translate_handlers,
                    cf->pool, 10, sizeof(ngx_http_handler_pt), NGX_CONF_ERROR);
@@ -172,12 +227,12 @@ static char *ngx_http_block(ngx_conf_t *
                    NGX_CONF_ERROR);
 
     /* "server" directives */
-    cscf = (ngx_http_core_srv_conf_t **) ngx_http_servers.elts;
-    for (s = 0; s < ngx_http_servers.nelts; s++) {
+    cscfp = (ngx_http_core_srv_conf_t **) cmcf->servers.elts;
+    for (s = 0; s < cmcf->servers.nelts; s++) {
 
         /* "listen" directives */
-        lscf = (ngx_http_listen_t *) cscf[s]->listen.elts;
-        for (l = 0; l < cscf[s]->listen.nelts; l++) {
+        lscf = (ngx_http_listen_t *) cscfp[s]->listen.elts;
+        for (l = 0; l < cscfp[s]->listen.nelts; l++) {
 
             port_found = 0;
 
@@ -202,8 +257,8 @@ static char *ngx_http_block(ngx_conf_t *
 
                             /* "server_name" directives */
                             s_name = (ngx_http_server_name_t *)
-                                                    cscf[s]->server_names.elts;
-                            for (n = 0; n < cscf[s]->server_names.nelts; n++) {
+                                                    cscfp[s]->server_names.elts;
+                            for (n = 0; n < cscfp[s]->server_names.nelts; n++) {
 
                                 /* add the server name and server core module
                                    configuration to the address:port */
@@ -234,7 +289,7 @@ static char *ngx_http_block(ngx_conf_t *
                                 }
 
                                 in_addr[a].flags |= NGX_HTTP_DEFAULT_SERVER;
-                                in_addr[a].core_srv_conf = cscf[s];
+                                in_addr[a].core_srv_conf = cscfp[s];
                             }
 
                             addr_found = 1;
@@ -256,7 +311,7 @@ static char *ngx_http_block(ngx_conf_t *
 
                             in_addr[a].addr = lscf[l].addr;
                             in_addr[a].flags = lscf[l].flags;   
-                            in_addr[a].core_srv_conf = cscf[s];
+                            in_addr[a].core_srv_conf = cscfp[s];
 
                             /* create the empty list of the server names that
                                can be served on this address:port */
@@ -282,7 +337,7 @@ static char *ngx_http_block(ngx_conf_t *
 
                         inaddr->addr = lscf[l].addr;
                         inaddr->flags = lscf[l].flags;   
-                        inaddr->core_srv_conf = cscf[s];
+                        inaddr->core_srv_conf = cscfp[s];
 
                         /* create the empty list of the server names that
                            can be served on this address:port */
@@ -317,7 +372,7 @@ static char *ngx_http_block(ngx_conf_t *
 
                 inaddr->addr = lscf[l].addr;
                 inaddr->flags = lscf[l].flags;   
-                inaddr->core_srv_conf = cscf[s];
+                inaddr->core_srv_conf = cscfp[s];
 
                 /* create the empty list of the server names that
                    can be served on this address:port */
@@ -407,12 +462,12 @@ static char *ngx_http_block(ngx_conf_t *
             ls->addr = offsetof(struct sockaddr_in, sin_addr);
             ls->addr_text_max_len = INET_ADDRSTRLEN;
             ls->backlog = -1;
-            ls->post_accept_timeout = ngx_http_post_accept_timeout;
+            ls->post_accept_timeout = cmcf->post_accept_timeout;
             ls->nonblocking = 1;
 
             ls->handler = ngx_http_init_connection;
             ls->log = cf->log;
-            ls->pool_size = ngx_http_connection_pool_size;
+            ls->pool_size = cmcf->connection_pool_size;
             ls->ctx = ctx;
 
             if (in_port[p].addrs.nelts > 1) {
@@ -475,87 +530,3 @@ ngx_log_debug(cf->log, "%s %08x" _ ip _ 
 
     return NGX_CONF_OK;
 }
-
-
-#if 0
-/* STUB */
-
-static struct sockaddr_in  addr;
-static char addr_text[22];
-
-
-int ngx_http_init(ngx_pool_t *pool, ngx_log_t *log)
-{
-    ngx_listen_t  *ls;
-
-    ngx_http_server.connection_pool_size = 16384;
-    ngx_http_server.request_pool_size = 16384;
-    ngx_http_server.header_timeout = 20000;
-    ngx_http_server.header_buffer_size = 1024;
-    ngx_http_server.discarded_buffer_size = 1500;
-
-    ngx_http_server.lingering_timeout = 5000;
-    ngx_http_server.lingering_time = 30;
-
-#if (WIN32)
-    ngx_http_server.doc_root = "html";
-#else
-    ngx_http_server.doc_root = "/home/is/dox/";
-    ngx_http_server.doc_root = "/home/is/work/xml/site-1.0.0/html";
-    ngx_http_server.doc_root = "/spool/test/lperltk";
-    ngx_http_server.doc_root = "/home/is/dox/ora/lperltk";
-#endif
-    ngx_http_server.doc_root_len = strlen(ngx_http_server.doc_root) + 1;
-
-
-    ngx_http_config_modules(pool, ngx_modules);
-
-#if 0
-    /* STUB */
-    ngx_http_output_filter_set_stub(pool, ngx_http_modules);
-    ngx_http_write_filter_set_stub(pool, ngx_http_modules);
-    ngx_http_index_set_stub(pool, ngx_http_modules);
-
-    ngx_http_init_modules(pool, ngx_http_modules);
-#endif
-
-    ngx_http_init_filters(pool, ngx_modules);
-
-    ls = ngx_push_array(&ngx_listening_sockets);
-    ngx_memzero(ls, sizeof(ngx_listen_t));
-
-    addr.sin_family = AF_INET;
-    addr.sin_addr.s_addr = inet_addr("0.0.0.0");
-    addr.sin_port = htons(8000);
-
-    ngx_snprintf(ngx_cpystrn(addr_text, inet_ntoa(addr.sin_addr), 16),
-                 7, ":%d", ntohs(addr.sin_port));
-
-    ls->family = AF_INET;
-    ls->type = SOCK_STREAM;
-    ls->protocol = IPPROTO_IP;
-
-#if (NGX_OVERLAPPED)
-    ls->flags = WSA_FLAG_OVERLAPPED;
-#else
-    ls->nonblocking = 1;
-#endif
-
-    ls->sockaddr = (struct sockaddr *) &addr;
-    ls->socklen = sizeof(struct sockaddr_in);
-    ls->addr = offsetof(struct sockaddr_in, sin_addr);
-    ls->addr_text.len = INET_ADDRSTRLEN;
-    ls->addr_text.data = addr_text;
-    ls->backlog = -1;
-    ls->post_accept_timeout = 10000;
-
-    ls->handler = ngx_http_init_connection;
-    ls->server = &ngx_http_server;
-    ls->log = log;
-
-
-    return 1;
-}
-
-/**/
-#endif
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -12,190 +12,7 @@
 #include <ngx_connection.h>
 #include <ngx_conf_file.h>
 
-/* STUB */
-#include <ngx_event_timer.h>
-
-#define NGX_HTTP_VERSION_9           9
-#define NGX_HTTP_VERSION_10       1000
-#define NGX_HTTP_VERSION_11       1001
-
-#define NGX_HTTP_GET   1
-#define NGX_HTTP_HEAD  2
-#define NGX_HTTP_POST  3
-
-#define NGX_HTTP_CONN_CLOSE       0
-#define NGX_HTTP_CONN_KEEP_ALIVE  1
-
-
-#define NGX_HTTP_PARSE_HEADER_DONE        1
-#define NGX_HTTP_PARSE_INVALID_METHOD     10
-#define NGX_HTTP_PARSE_INVALID_REQUEST    11
-#define NGX_HTTP_PARSE_TOO_LONG_URI       12
-#define NGX_HTTP_PARSE_INVALID_09_METHOD  13
-#define NGX_HTTP_PARSE_INVALID_HEADER     14
-#define NGX_HTTP_PARSE_TOO_LONG_HEADER    15
-#define NGX_HTTP_PARSE_NO_HOST_HEADER     16
-#define NGX_HTTP_PARSE_INVALID_CL_HEADER  17
-
-
-#define NGX_HTTP_OK                     200
-
-#define NGX_HTTP_SPECIAL_RESPONSE       300
-#define NGX_HTTP_MOVED_PERMANENTLY      301
-#define NGX_HTTP_MOVED_TEMPORARILY      302
-#define NGX_HTTP_NOT_MODIFIED           304
-
-#define NGX_HTTP_BAD_REQUEST            400
-#define NGX_HTTP_FORBIDDEN              403
-#define NGX_HTTP_NOT_FOUND              404
-#define NGX_HTTP_REQUEST_TIME_OUT       408
-#define NGX_HTTP_REQUEST_URI_TOO_LARGE  414
-
-#define NGX_HTTP_INTERNAL_SERVER_ERROR  500
-#define NGX_HTTP_NOT_IMPLEMENTED        501
-#define NGX_HTTP_BAD_GATEWAY            502
-#define NGX_HTTP_SERVICE_UNAVAILABLE    503
-#define NGX_HTTP_GATEWAY_TIME_OUT       504
-
-
-
-#define NGX_HTTP_STATIC_HANDLER     0
-#define NGX_HTTP_DIRECTORY_HANDLER  1
-
-
-typedef struct {
-    ngx_str_t  name;
-    int        offset;
-} ngx_http_header_t;
-
-
-typedef struct {
-    size_t            host_name_len;
-    ssize_t           content_length_n;
-
-    ngx_table_elt_t  *host;
-    ngx_table_elt_t  *connection;
-    ngx_table_elt_t  *if_modified_since;
-    ngx_table_elt_t  *content_length;
-    ngx_table_elt_t  *accept_encoding;
-
-    ngx_table_elt_t  *user_agent;
-
-    ngx_table_t      *headers;
-} ngx_http_headers_in_t;
-
-
-typedef struct {
-    ngx_chain_t       chain[4];
-    ngx_hunk_t       *header_out;
-    ngx_hunk_t       *hunk;
-    ngx_hunk_t       *file_hunk;
-    ngx_file_t        temp_file;
-    ngx_path_t       *temp_path;
-    off_t             offset;
-    char             *header_in_pos;
-} ngx_http_request_body_t;
-
-
-typedef struct {
-    int               status;
-    ngx_str_t         status_line;
-
-    ngx_table_elt_t  *server;
-    ngx_table_elt_t  *date;
-    ngx_table_elt_t  *content_type;
-    ngx_table_elt_t  *location;
-    ngx_table_elt_t  *last_modified;
-
-    ngx_table_t      *headers;
-
-    off_t             content_length;
-    char             *charset;
-    char             *etag;
-    time_t            date_time;
-    time_t            last_modified_time;
-} ngx_http_headers_out_t;
-
-
-typedef struct ngx_http_request_s ngx_http_request_t;
-
-struct ngx_http_request_s {
-    ngx_connection_t    *connection;
-
-    void               **ctx;
-    void               **srv_conf;
-    void               **loc_conf;
-
-    ngx_file_t           file;
-
-    ngx_pool_t               *pool;
-    ngx_hunk_t               *header_in;
-    ngx_http_request_body_t  *request_body;
-
-    ngx_http_headers_in_t     headers_in;
-    ngx_http_headers_out_t    headers_out;
-
-    int  (*handler)(ngx_http_request_t *r);
-
-    time_t  lingering_time;
-
-    int                  method;
-    int                  http_version;
-    int                  http_major;
-    int                  http_minor;
-
-    ngx_str_t            request_line;
-    ngx_str_t            uri;
-    ngx_str_t            args;
-    ngx_str_t            exten;
-    ngx_http_request_t  *main;
-
-    u_int       in_addr;
-
-    int         port;
-    ngx_str_t   port_name;
-
-    int         filter;
-
-    char       *discarded_buffer;
-
-    ngx_str_t   path;
-    int         path_err;
-
-    unsigned  proxy:1;
-    unsigned  cachable:1;
-    unsigned  pipeline:1;
-    unsigned  keepalive:1;
-    unsigned  lingering_close:1;
-
-    unsigned  header_read:1;
-    unsigned  header_timeout_set:1;
-
-    unsigned  logging:1;
-
-    unsigned  header_only:1;
-    unsigned  unusual_uri:1;  /* URI is not started with '/' - "GET http://" */
-    unsigned  complex_uri:1;  /* URI with "/." or with "//" (WIN32) */
-    unsigned  path_not_found:1;
-#ifdef NGX_EVENT
-    unsigned  write_level_event:1;
-#endif
-
-    int    state;
-    char  *uri_start;
-    char  *uri_end;
-    char  *uri_ext;
-    char  *args_start;
-    char  *request_start;
-    char  *request_end;
-    char  *header_name_start;
-    char  *header_name_end;
-    char  *header_start;
-    char  *header_end;
-#ifdef NGX_EVENT
-    int  (*state_handler)(ngx_http_request_t *r);
-#endif
-};
+#include <ngx_http_request.h>
 
 
 typedef struct {
@@ -263,20 +80,11 @@ int ngx_http_discard_body(ngx_http_reque
 
 
 
-
-extern int  ngx_max_module;
-extern ngx_array_t  ngx_http_servers;
+extern ngx_module_t  ngx_http_module;
 
 
-extern int  ngx_http_post_accept_timeout;
-extern int  ngx_http_connection_pool_size;
-extern int  ngx_http_request_pool_size;
-extern int  ngx_http_client_header_timeout;
-extern int  ngx_http_client_header_buffer_size;
-extern int  ngx_http_large_client_header;
-extern int  ngx_http_discarded_buffer_size;
+extern int  ngx_max_module;
 
-extern int  ngx_http_url_in_error_log;
 
 extern ngx_array_t  ngx_http_translate_handlers;
 extern ngx_array_t  ngx_http_index_handlers;
--- a/src/http/ngx_http_config.h
+++ b/src/http/ngx_http_config.h
@@ -7,9 +7,9 @@
 
 
 typedef struct {
-    void        **main_conf;
-    void        **srv_conf;
-    void        **loc_conf;
+    void   **main_conf;
+    void   **srv_conf;
+    void   **loc_conf;
 } ngx_http_conf_ctx_t;
 
 
@@ -22,8 +22,11 @@ typedef struct {
 typedef struct {
     int      index;
 
+    void  *(*create_main_conf)(ngx_pool_t *p);
+    char  *(*init_main_conf)(ngx_pool_t *p, void *conf);
+
     void  *(*create_srv_conf)(ngx_pool_t *p);
-    char  *(*init_srv_conf)(ngx_pool_t *p, void *conf);
+    char  *(*merge_srv_conf)(ngx_pool_t *p, void *prev, void *conf);
 
     void  *(*create_loc_conf)(ngx_pool_t *p);
     char  *(*merge_loc_conf)(ngx_pool_t *p, void *prev, void *conf);
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -6,10 +6,13 @@
 #include <ngx_string.h>
 #include <ngx_conf_file.h>
 
+#include <nginx.h>
+
 #include <ngx_http.h>
 #include <ngx_http_config.h>
 #include <ngx_http_core_module.h>
 
+
 /* STUB for r->filter = NGX_HTTP_FILTER_NEED_IN_MEMORY; */
 #include <ngx_http_output_filter.h>
 
@@ -21,8 +24,11 @@ static int ngx_http_core_index_handler(n
 
 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);
-static char *ngx_http_core_init_srv_conf(ngx_pool_t *pool, void *conf);
+static char *ngx_http_core_merge_srv_conf(ngx_pool_t *pool,
+                                          void *parent, void *child);
 static void *ngx_http_core_create_loc_conf(ngx_pool_t *pool);
 static char *ngx_http_core_merge_loc_conf(ngx_pool_t *pool,
                                           void *parent, void *child);
@@ -46,29 +52,29 @@ static ngx_command_t  ngx_http_core_comm
     {ngx_string("post_accept_timeout"),
      NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_msec_slot,
-     0,
-     addressof(ngx_http_post_accept_timeout),
+     NGX_HTTP_MAIN_CONF_OFFSET,
+     offsetof(ngx_http_core_main_conf_t, post_accept_timeout),
      NULL},
 
     {ngx_string("connection_pool_size"),
      NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_size_slot,
-     0,
-     addressof(ngx_http_connection_pool_size),
+     NGX_HTTP_MAIN_CONF_OFFSET,
+     offsetof(ngx_http_core_main_conf_t, connection_pool_size),
      NULL},
 
     {ngx_string("request_pool_size"),
      NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_size_slot,
-     0,
-     addressof(ngx_http_request_pool_size),
+     NGX_HTTP_MAIN_CONF_OFFSET,
+     offsetof(ngx_http_core_main_conf_t, request_pool_size),
      NULL},
 
     {ngx_string("client_header_timeout"),
      NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_msec_slot,
-     0,
-     addressof(ngx_http_client_header_timeout),
+     NGX_HTTP_MAIN_CONF_OFFSET,
+     offsetof(ngx_http_core_main_conf_t, client_header_timeout),
      NULL},
 
     {ngx_string("client_header_buffer_size"),
@@ -81,8 +87,8 @@ static ngx_command_t  ngx_http_core_comm
     {ngx_string("large_client_header"),
      NGX_HTTP_MAIN_CONF|NGX_CONF_FLAG,
      ngx_conf_set_flag_slot,
-     0,
-     addressof(ngx_http_large_client_header),
+     NGX_HTTP_MAIN_CONF_OFFSET,
+     offsetof(ngx_http_core_main_conf_t, large_client_header),
      NULL},
 
     {ngx_string("location"),
@@ -93,49 +99,50 @@ static ngx_command_t  ngx_http_core_comm
      NULL},
 
     {ngx_string("listen"),
-     NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
+     NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
      ngx_set_listen,
      NGX_HTTP_SRV_CONF_OFFSET,
      0,
      NULL},
 
     {ngx_string("types"),
-     NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
+     NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF
+                                         |NGX_CONF_BLOCK|NGX_CONF_NOARGS,
      ngx_types_block,
      NGX_HTTP_LOC_CONF_OFFSET,
      0,
      NULL},
 
     {ngx_string("root"),
-     NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+     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, doc_root),
      NULL},
 
     {ngx_string("sendfile"),
-     NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+     NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_flag_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_core_loc_conf_t, sendfile),
      NULL},
 
     {ngx_string("send_timeout"),
-     NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+     NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_msec_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_core_loc_conf_t, send_timeout),
      NULL},
 
     {ngx_string("lingering_time"),
-     NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+     NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_msec_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_core_loc_conf_t, lingering_time),
      NULL},
 
     {ngx_string("lingering_timeout"),
-     NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+     NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_msec_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_core_loc_conf_t, lingering_timeout),
@@ -148,11 +155,14 @@ static ngx_command_t  ngx_http_core_comm
 ngx_http_module_t  ngx_http_core_module_ctx = {
     NGX_HTTP_MODULE,
 
-    ngx_http_core_create_srv_conf,         /* create server config */
-    ngx_http_core_init_srv_conf,           /* init server config */
+    ngx_http_core_create_main_conf,        /* create main configuration */
+    ngx_http_core_init_main_conf,          /* init main configuration */
 
-    ngx_http_core_create_loc_conf,         /* create location config */
-    ngx_http_core_merge_loc_conf           /* merge location config */
+    ngx_http_core_create_srv_conf,         /* create server configuration */
+    ngx_http_core_merge_srv_conf,          /* merge server configuration */
+
+    ngx_http_core_create_loc_conf,         /* create location configuration */
+    ngx_http_core_merge_loc_conf           /* merge location configuration */
 };
 
 
@@ -207,6 +217,7 @@ ngx_log_debug(r->connection->log, "FOUND
             }
         }
 
+/* DEBUG */
 if (a == in_port->addrs.nelts) {
     ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                   "addr not found");
@@ -257,12 +268,12 @@ void ngx_http_handler(ngx_http_request_t
     int                        rc, i;
     ngx_http_handler_pt       *h;
     ngx_http_module_t         *module;
-    ngx_http_core_loc_conf_t  *lcf, **plcf;
+    ngx_http_core_loc_conf_t  *lcf, **lcfp;
     ngx_http_core_srv_conf_t  *scf;
 
     r->connection->unexpected_eof = 0;
 
-    r->keepalive = 0;
+    r->keepalive = 1;
 
     if (r->headers_in.content_length_n > 0) {
         r->lingering_close = 1;
@@ -279,23 +290,23 @@ void ngx_http_handler(ngx_http_request_t
     scf = (ngx_http_core_srv_conf_t *)
                      ngx_http_get_module_srv_conf(r, ngx_http_core_module_ctx);
 
-    plcf = (ngx_http_core_loc_conf_t **) scf->locations.elts;
+    lcfp = (ngx_http_core_loc_conf_t **) scf->locations.elts;
     for (i = 0; i < scf->locations.nelts; i++) {
 #if 0
-ngx_log_debug(r->connection->log, "trans: %s" _ plcf[i]->name.data);
+ngx_log_debug(r->connection->log, "trans: %s" _ lcfp[i]->name.data);
 #endif
-         if (r->uri.len < plcf[i]->name.len) {
+         if (r->uri.len < lcfp[i]->name.len) {
              continue;
          }
 
-         rc = ngx_rstrncmp(r->uri.data, plcf[i]->name.data, plcf[i]->name.len);
+         rc = ngx_rstrncmp(r->uri.data, lcfp[i]->name.data, lcfp[i]->name.len);
 
          if (rc < 0) {
              break;
          }
 
          if (rc == 0) {
-             r->loc_conf = plcf[i]->loc_conf;
+             r->loc_conf = lcfp[i]->loc_conf;
          }
     }
 
@@ -587,7 +598,8 @@ int ngx_http_internal_redirect(ngx_http_
     r->uri.len = uri.len;
     r->uri.data = uri.data;
 
-    /* NEEDED ? */
+    /* BROKEN, NEEDED ? */
+    /* r->exten */
     r->uri_start = uri.data;
     r->uri_end = uri.data + uri.len;
     /**/
@@ -611,28 +623,28 @@ static int ngx_http_core_init(ngx_pool_t
 
 static char *ngx_server_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy)
 {
-    int                         i, j;
-    char                       *rv;
-    ngx_http_module_t          *module;
-    ngx_conf_t                  pcf;
-    ngx_http_conf_ctx_t        *ctx, *tctx, *pctx;
-    ngx_http_core_srv_conf_t   *scf;
-    ngx_http_core_loc_conf_t  **plcf;
+    int                          i, j;
+    char                        *rv;
+    ngx_http_module_t           *module;
+    ngx_conf_t                   pcf;
+    ngx_http_conf_ctx_t         *ctx, *hctx, *pctx;
+    ngx_http_core_main_conf_t   *cmcf;
+    ngx_http_core_srv_conf_t    *cscf, **cscfp;
 
     ngx_test_null(ctx,
                   ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)),
                   NGX_CONF_ERROR);
 
-    tctx = (ngx_http_conf_ctx_t *) cf->ctx;
-    ctx->main_conf = tctx->main_conf;
+    hctx = (ngx_http_conf_ctx_t *) cf->ctx;
+    ctx->main_conf = hctx->main_conf;
 
-    /* server configuration */
+    /* the server{}'s srv_conf */
 
     ngx_test_null(ctx->srv_conf,
                   ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module),
                   NGX_CONF_ERROR);
 
-    /* server location configuration */
+    /* the server{}'s loc_conf */
 
     ngx_test_null(ctx->loc_conf,
                   ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module),
@@ -658,6 +670,17 @@ 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 = ctx;
+
+    cmcf = ctx->main_conf[ngx_http_core_module_ctx.index];
+    ngx_test_null(cscfp, ngx_push_array(&cmcf->servers), NGX_CONF_ERROR);
+    *cscfp = cscf;
+
+    /* parse inside server{} */
+
     pcf = *cf;
     pctx = cf->ctx;
     cf->ctx = ctx;
@@ -665,50 +688,7 @@ static char *ngx_server_block(ngx_conf_t
     rv = ngx_conf_parse(cf, NULL);
     *cf = pcf;
 
-    if (rv != NGX_CONF_OK)
-        return rv;
-
-
-    scf = ctx->srv_conf[ngx_http_core_module_ctx.index];
-    scf->ctx = ctx;
-
-    plcf = (ngx_http_core_loc_conf_t **)scf->locations.elts;
-
-    for (i = 0; ngx_modules[i]; i++) {
-        if (ngx_modules[i]->type != NGX_HTTP_MODULE_TYPE) {
-            continue;
-        }
-
-        module = (ngx_http_module_t *) ngx_modules[i]->ctx;
-
-        if (module->init_srv_conf) {
-            if (module->init_srv_conf(cf->pool,
-                                      ctx->srv_conf[module->index])
-                                                           == NGX_CONF_ERROR) {
-                return NGX_CONF_ERROR;
-            }
-        }
-
-        if (module->merge_loc_conf) {
-            rv = module->merge_loc_conf(cf->pool,
-                                        pctx->loc_conf[module->index],
-                                        ctx->loc_conf[module->index]);
-            if (rv != NGX_CONF_OK) {
-                return rv;
-            }
-
-            for (j = 0; j < scf->locations.nelts; j++) {
-                rv = module->merge_loc_conf(cf->pool,
-                                            ctx->loc_conf[module->index],
-                                            plcf[j]->loc_conf[module->index]);
-                if (rv != NGX_CONF_OK) {
-                    return rv;
-                }
-            }
-        }
-    }
-
-    return NGX_CONF_OK;
+    return rv;
 }
 
 
@@ -720,14 +700,15 @@ static char *ngx_location_block(ngx_conf
     ngx_http_module_t         *module;
     ngx_conf_t                 pcf;
     ngx_http_conf_ctx_t       *ctx, *pctx;
-    ngx_http_core_srv_conf_t  *scf;
-    ngx_http_core_loc_conf_t  *lcf, **plcf;
+    ngx_http_core_srv_conf_t  *cscf;
+    ngx_http_core_loc_conf_t  *clcf, **clcfp;
 
     ngx_test_null(ctx,
                   ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)),
                   NGX_CONF_ERROR);
 
     pctx = (ngx_http_conf_ctx_t *) cf->ctx;
+    ctx->main_conf = pctx->main_conf;
     ctx->srv_conf = pctx->srv_conf;
 
     ngx_test_null(ctx->loc_conf,
@@ -748,17 +729,15 @@ static char *ngx_location_block(ngx_conf
         }
     }
 
-    lcf = (ngx_http_core_loc_conf_t *)
-                                 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;
-    lcf->name.len = location[1].len;
-    lcf->name.data = location[1].data;
-    lcf->loc_conf = ctx->loc_conf;
+    clcf->name.len = location[1].len;
+    clcf->name.data = location[1].data;
+    clcf->loc_conf = ctx->loc_conf;
 
-    scf = (ngx_http_core_srv_conf_t *)
-                                 ctx->srv_conf[ngx_http_core_module_ctx.index];
-    ngx_test_null(plcf, ngx_push_array(&scf->locations), NGX_CONF_ERROR);
-    *plcf = lcf;
+    cscf = ctx->srv_conf[ngx_http_core_module_ctx.index];
+    ngx_test_null(clcfp, ngx_push_array(&cscf->locations), NGX_CONF_ERROR);
+    *clcfp = clcf;
 
     pcf = *cf;
     cf->ctx = ctx;
@@ -821,43 +800,81 @@ static char *ngx_types_block(ngx_conf_t 
 }
 
 
+static void *ngx_http_core_create_main_conf(ngx_pool_t *pool)
+{
+    ngx_http_core_main_conf_t *cmcf;
+
+    ngx_test_null(cmcf,
+                  ngx_palloc(pool, sizeof(ngx_http_core_main_conf_t)), 
+                  NGX_CONF_ERROR);
+
+    cmcf->post_accept_timeout = NGX_CONF_UNSET;
+    cmcf->connection_pool_size = NGX_CONF_UNSET;
+    cmcf->request_pool_size = NGX_CONF_UNSET;
+    cmcf->client_header_timeout = NGX_CONF_UNSET;
+    cmcf->client_header_buffer_size = NGX_CONF_UNSET;
+    cmcf->large_client_header = NGX_CONF_UNSET;
+
+    ngx_init_array(cmcf->servers, pool, 5, sizeof(ngx_http_core_srv_conf_t *),
+                   NGX_CONF_ERROR);
+
+    return cmcf;
+}
+
+
+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_conf_init_msec_value(cmcf->post_accept_timeout, 30000);
+    ngx_conf_init_size_value(cmcf->connection_pool_size, 16384);
+    ngx_conf_init_size_value(cmcf->request_pool_size, 16384);
+    ngx_conf_init_msec_value(cmcf->client_header_timeout, 60000);
+    ngx_conf_init_size_value(cmcf->client_header_buffer_size, 1024);
+    ngx_conf_init_value(cmcf->large_client_header, 1);
+
+    return NGX_CONF_OK;
+}
+
+
 static void *ngx_http_core_create_srv_conf(ngx_pool_t *pool)
 {
-    ngx_http_core_srv_conf_t *scf, **cf;
+    ngx_http_core_srv_conf_t  *cscf;
 
-    ngx_test_null(scf,
+    ngx_test_null(cscf,
                   ngx_pcalloc(pool, sizeof(ngx_http_core_srv_conf_t)), 
                   NGX_CONF_ERROR);
 
-    ngx_init_array(scf->locations, pool, 5, sizeof(void *), NGX_CONF_ERROR);
-    ngx_init_array(scf->listen, pool, 5, sizeof(ngx_http_listen_t),
+    ngx_init_array(cscf->locations, pool, 5, sizeof(void *), NGX_CONF_ERROR);
+    ngx_init_array(cscf->listen, pool, 5, sizeof(ngx_http_listen_t),
                    NGX_CONF_ERROR);
-    ngx_init_array(scf->server_names, pool, 5, sizeof(ngx_http_server_name_t),
+    ngx_init_array(cscf->server_names, pool, 5, sizeof(ngx_http_server_name_t),
                    NGX_CONF_ERROR);
 
-    ngx_test_null(cf, ngx_push_array(&ngx_http_servers), NGX_CONF_ERROR);
-    *cf = scf;
-
-    return scf;
+    return cscf;
 }
 
 
-static char *ngx_http_core_init_srv_conf(ngx_pool_t *pool, void *conf)
+static char *ngx_http_core_merge_srv_conf(ngx_pool_t *pool,
+                                          void *parent, void *child)
 {
-    ngx_http_core_srv_conf_t *scf = (ngx_http_core_srv_conf_t *) conf;
+    ngx_http_core_srv_conf_t *prev = (ngx_http_core_srv_conf_t *) parent;
+    ngx_http_core_srv_conf_t *conf = (ngx_http_core_srv_conf_t *) child;
 
     ngx_http_listen_t        *l;
     ngx_http_server_name_t   *n;
 
-    if (scf->listen.nelts == 0) {
-        ngx_test_null(l, ngx_push_array(&scf->listen), NGX_CONF_ERROR);
+    /* TODO: it does not merge, it init only */
+
+    if (conf->listen.nelts == 0) {
+        ngx_test_null(l, ngx_push_array(&conf->listen), NGX_CONF_ERROR);
         l->addr = INADDR_ANY;
         l->port = 8000;
         l->family = AF_INET;
     }
 
-    if (scf->server_names.nelts == 0) {
-        ngx_test_null(n, ngx_push_array(&scf->server_names), NGX_CONF_ERROR);
+    if (conf->server_names.nelts == 0) {
+        ngx_test_null(n, ngx_push_array(&conf->server_names), NGX_CONF_ERROR);
         ngx_test_null(n->name.data, ngx_palloc(pool, NGX_MAXHOSTNAMELEN),
                       NGX_CONF_ERROR);
         if (gethostname(n->name.data, NGX_MAXHOSTNAMELEN) == -1) {
@@ -959,15 +976,16 @@ static char *ngx_http_core_merge_loc_con
         }
     }
 
-    ngx_conf_merge(conf->sendfile, prev->sendfile, 0);
+    ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0);
 
-    ngx_conf_msec_merge(conf->send_timeout, prev->send_timeout, 10000);
+    ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 10000);
 
-    ngx_conf_size_merge(conf->discarded_buffer_size,
-                        prev->discarded_buffer_size, 1500);
-
-    ngx_conf_msec_merge(conf->lingering_time, prev->lingering_time, 30000);
-    ngx_conf_msec_merge(conf->lingering_timeout, prev->lingering_timeout, 5000);
+    ngx_conf_merge_size_value(conf->discarded_buffer_size,
+                              prev->discarded_buffer_size, 1500);
+    ngx_conf_merge_msec_value(conf->lingering_time, prev->lingering_time,
+                              30000);
+    ngx_conf_merge_msec_value(conf->lingering_timeout, prev->lingering_timeout,
+                              5000);
 
     return NGX_CONF_OK;
 }
@@ -975,11 +993,12 @@ static char *ngx_http_core_merge_loc_con
 
 static char *ngx_set_listen(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
 {
+    ngx_http_core_srv_conf_t *scf = (ngx_http_core_srv_conf_t *) conf;
+
     uint                p;
     char               *addr;
     ngx_str_t          *args;
     ngx_http_listen_t  *ls;
-    ngx_http_core_srv_conf_t *scf = (ngx_http_core_srv_conf_t *) conf;
 
     /* TODO: check duplicate 'listen' directives */
 
@@ -1001,7 +1020,8 @@ static char *ngx_set_listen(ngx_conf_t *
 
             ls->addr = inet_addr(addr);
             if (ls->addr == INADDR_NONE) {
-                return "bad addr";
+                /* TODO: gethostbyname() */
+                return "can not resolve host name";
             }
 
             break;
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -18,17 +18,27 @@ typedef struct {
 
 
 typedef struct {
+    int          post_accept_timeout;
+    int          connection_pool_size;
     int          request_pool_size;
+    int          client_header_timeout;
     int          client_header_buffer_size;
+    int          large_client_header;
+    int          url_in_error_log;
+
+    ngx_array_t  servers;      /* array of ngx_http_core_srv_conf_t */
 } ngx_http_core_main_conf_t;
 
 
 typedef struct {
-    ngx_array_t  locations;    /* array of ngx_http_core_loc_conf_t */
+    ngx_array_t  locations;    /* array of ngx_http_core_loc_conf_t,
+                                  used in the translation handler
+                                  and in the merge phase */
 
     ngx_array_t  listen;       /* 'listen', array of ngx_http_listen_t */
     ngx_array_t  server_names; /* 'server_name',
                                   array of ngx_http_server_name_t */
+
     ngx_http_conf_ctx_t *ctx;  /* server ctx */
 } ngx_http_core_srv_conf_t;
 
@@ -78,8 +88,7 @@ typedef struct {
 
 typedef struct {
     ngx_str_t   name;          /* location name */
-    void      **loc_conf;      /* pointer to modules loc_conf,
-                                  used in translation handler */
+    void      **loc_conf ;     /* pointer to the modules' loc_conf */
 
     int       (*handler) (ngx_http_request_t *r);
 
--- a/src/http/ngx_http_event.c
+++ b/src/http/ngx_http_event.c
@@ -137,15 +137,19 @@ void ngx_http_init_connection(ngx_connec
 
 static void ngx_http_init_request(ngx_event_t *rev)
 {
-    ngx_connection_t     *c;
-    ngx_http_request_t   *r;
-    ngx_http_conf_ctx_t  *ctx;
+    ngx_connection_t           *c;
+    ngx_http_request_t         *r;
+    ngx_http_conf_ctx_t        *ctx;
+    ngx_http_core_main_conf_t  *cmcf;
 
-    c = (ngx_connection_t *) rev->data;
+    c = rev->data;
+    ctx = c->ctx;
+
+    cmcf = ngx_http_get_module_main_conf(ctx, ngx_http_core_module_ctx);
 
     if (c->buffer == NULL) {
         c->buffer = ngx_create_temp_hunk(c->pool,
-                                         ngx_http_client_header_buffer_size,
+                                         cmcf->client_header_buffer_size,
                                          0, 0);
         if (c->buffer == NULL) {
             ngx_http_close_connection(c);
@@ -159,7 +163,7 @@ static void ngx_http_init_request(ngx_ev
         return;
     }
 
-    r->pool = ngx_create_pool(ngx_http_request_pool_size, c->log);
+    r->pool = ngx_create_pool(cmcf->request_pool_size, c->log);
     if (r->pool == NULL) {
         ngx_http_close_connection(c);
         return;
@@ -179,7 +183,7 @@ static void ngx_http_init_request(ngx_ev
         return;
     }
 
-    ctx = (ngx_http_conf_ctx_t *) c->ctx;
+    r->main_conf = ctx->main_conf;
     r->srv_conf = ctx->srv_conf;
     r->loc_conf = ctx->loc_conf;
 
@@ -202,14 +206,15 @@ static void ngx_http_init_request(ngx_ev
 
 static void ngx_http_process_request_line(ngx_event_t *rev)
 {
-    int                  rc, offset;
-    ssize_t              n;
-    ngx_connection_t    *c;
-    ngx_http_request_t  *r;
-    ngx_http_log_ctx_t  *lcx;
+    int                         rc, offset;
+    ssize_t                     n;
+    ngx_connection_t           *c;
+    ngx_http_request_t         *r;
+    ngx_http_log_ctx_t         *lcx;
+    ngx_http_core_main_conf_t  *cmcf;
 
-    c = (ngx_connection_t *) rev->data;
-    r = (ngx_http_request_t *) c->data;
+    c = rev->data;
+    r = c->data;
 
     ngx_log_debug(rev->log, "http process request line");
 
@@ -231,8 +236,10 @@ static void ngx_http_process_request_lin
 
         /* the request line has been parsed successfully */
 
+        cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module_ctx);
+
         if (r->http_version >= NGX_HTTP_VERSION_10
-            && ngx_http_large_client_header == 0
+            && cmcf->large_client_header == 0
             && r->header_in->pos == r->header_in->end)
         {
             /* no space for "\r\n" at the end of the header */
@@ -259,12 +266,29 @@ 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 ? */
+
+        /* copy unparsed URI */
+
+        r->unparsed_uri.len = r->uri_end - r->uri_start;
+        r->unparsed_uri.data = ngx_palloc(r->pool, r->unparsed_uri.len + 1);
+        if (r->unparsed_uri.data == NULL) {
+            ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+            ngx_http_close_connection(c);
+            return;
+        }
+
+        ngx_cpystrn(r->unparsed_uri.data, r->uri_start,
+                    r->unparsed_uri.len + 1);
+
+#endif
+
         r->request_line.len = r->request_end - r->request_start;
 
         /* if the large client headers are enabled then
            we need to copy a request line */
 
-        if (ngx_http_large_client_header) {
+        if (cmcf->large_client_header) {
 
             r->request_line.data = ngx_palloc(r->pool, r->request_line.len + 1);
             if (r->request_line.data == NULL) {
@@ -325,19 +349,6 @@ static void ngx_http_process_request_lin
         if (r->args.data[0] == '\0') { r->args.data = NULL; }
 #endif
 
-        lcx = c->log->data;
-
-        if (ngx_http_url_in_error_log) {
-            lcx->url = ngx_palloc(r->pool, r->uri_end - r->uri_start + 1);
-            if (lcx->url == NULL) {
-                ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
-                ngx_http_close_connection(c);
-                return;
-            }
-
-            ngx_cpystrn(lcx->url, r->uri_start, r->uri_end - r->uri_start + 1);
-        }
-
         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);
@@ -350,10 +361,12 @@ static void ngx_http_process_request_lin
             return;
         }
 
+        lcx = c->log->data;
         lcx->action = "reading client request headers";
+        lcx->url = r->unparsed_uri.data;
         r->headers_in.headers = ngx_create_table(r->pool, 10);
 
-        if (ngx_http_large_client_header
+        if (cmcf->large_client_header
             && r->header_in->pos == r->header_in->last)
         {
             r->header_in->pos = r->header_in->last = r->header_in->start;
@@ -384,7 +397,9 @@ 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() */
 
-        if (ngx_http_large_client_header) {
+        cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module_ctx);
+
+        if (cmcf->large_client_header) {
             offset = r->request_start - r->header_in->start;
 
             if (offset == 0) {
@@ -422,16 +437,17 @@ static void ngx_http_process_request_lin
 
 static void ngx_http_process_request_headers(ngx_event_t *rev)
 {
-    int                  rc, i, offset;
-    size_t               len;
-    ssize_t              n;
-    ngx_table_elt_t     *h;
-    ngx_connection_t    *c;
-    ngx_http_request_t  *r;
-    ngx_http_log_ctx_t  *ctx;
+    int                         rc, i, offset;
+    size_t                      len;
+    ssize_t                     n;
+    ngx_table_elt_t            *h;
+    ngx_connection_t           *c;
+    ngx_http_request_t         *r;
+    ngx_http_log_ctx_t         *ctx;
+    ngx_http_core_main_conf_t  *cmcf;
 
-    c = (ngx_connection_t *) rev->data;
-    r = (ngx_http_request_t *) c->data;
+    c = rev->data;
+    r = c->data;
 
     ngx_log_debug(rev->log, "http process request header line");
 
@@ -471,7 +487,9 @@ static void ngx_http_process_request_hea
             /* if the large client headers are enabled then
                we need to copy the header name and value */
 
-            if (ngx_http_large_client_header) {
+            cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module_ctx);
+
+            if (cmcf->large_client_header) {
                 h->key.data = ngx_palloc(r->pool,
                                          h->key.len + 1 + h->value.len + 1);
                 if (h->key.data == NULL) {
@@ -505,7 +523,7 @@ static void ngx_http_process_request_hea
             ngx_log_debug(r->connection->log, "HTTP header: '%s: %s'" _
                           h->key.data _ h->value.data);
 
-            if (ngx_http_large_client_header
+            if (cmcf->large_client_header
                 && r->header_in->pos == r->header_in->last)
             {
                 r->header_in->pos = r->header_in->last = r->header_in->start;
@@ -574,7 +592,9 @@ static void ngx_http_process_request_hea
             /* if the large client headers are enabled then
                 we need to compact r->header_in hunk */
 
-            if (ngx_http_large_client_header) {
+            cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module_ctx);
+
+            if (cmcf->large_client_header) {
                 offset = r->header_name_start - r->header_in->start;
 
                 if (offset == 0) {
@@ -606,9 +626,10 @@ static void ngx_http_process_request_hea
 
 static ssize_t ngx_http_read_request_header(ngx_http_request_t *r)
 {
-    int           event;
-    ssize_t       n;
-    ngx_event_t  *rev;
+    int                         event;
+    ssize_t                     n;
+    ngx_event_t                *rev;
+    ngx_http_core_main_conf_t  *cmcf;
 
     n = r->header_in->last - r->header_in->pos;
 
@@ -629,7 +650,9 @@ static ssize_t ngx_http_read_request_hea
                 rev->timer_set = 1;
             }
 
-            ngx_add_timer(rev, ngx_http_client_header_timeout);
+            cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module_ctx);
+
+            ngx_add_timer(rev, cmcf->client_header_timeout);
             r->header_timeout_set = 1;
         }
 
@@ -724,7 +747,7 @@ void ngx_http_set_write_handler(ngx_http
 {
     int                        event;
     ngx_event_t               *wev;
-    ngx_http_core_loc_conf_t  *lcf;
+    ngx_http_core_loc_conf_t  *clcf;
 
     wev = r->connection->write;
     wev->event_handler = ngx_http_writer;
@@ -733,10 +756,10 @@ void ngx_http_set_write_handler(ngx_http
         return;
     }
 
-    lcf = (ngx_http_core_loc_conf_t *)
+    clcf = (ngx_http_core_loc_conf_t *)
                         ngx_http_get_module_loc_conf(r->main ? r->main : r,
                                                      ngx_http_core_module_ctx);
-    ngx_add_timer(wev, lcf->send_timeout);
+    ngx_add_timer(wev, clcf->send_timeout);
     wev->timer_set = 1;
 
     if (ngx_event_flags & (NGX_HAVE_AIO_EVENT|NGX_HAVE_EDGE_EVENT)) {
@@ -747,7 +770,7 @@ void ngx_http_set_write_handler(ngx_http
 #if (HAVE_LOWAT_EVENT) /* kqueue's NOTE_LOWAT */
 
     if (ngx_event_flags & NGX_HAVE_LOWAT_EVENT) {
-        wev->lowat = lcf->send_lowat;
+        wev->lowat = clcf->send_lowat;
     }
 
 #endif
@@ -823,9 +846,8 @@ static void ngx_http_writer(ngx_event_t 
 
     if (r->keepalive != 0) {
         ngx_http_set_keepalive(r);
-    }
 
-    if (r->lingering_close) {
+    } else if (r->lingering_close) {
         ngx_http_set_lingering_close(r);
 
     } else {
@@ -970,11 +992,12 @@ static int ngx_http_read_discarded_body(
 
 static void ngx_http_set_keepalive(ngx_http_request_t *r)
 {
-    int                  len, blocked;
-    ngx_hunk_t          *h;
-    ngx_event_t         *rev, *wev;
-    ngx_connection_t    *c;
-    ngx_http_log_ctx_t  *ctx;
+    int                         len, blocked;
+    ngx_hunk_t                 *h;
+    ngx_event_t                *rev, *wev;
+    ngx_connection_t           *c;
+    ngx_http_log_ctx_t         *ctx;
+    ngx_http_core_main_conf_t  *cmcf;
 
     c = (ngx_connection_t *) r->connection;
     rev = c->read;
@@ -1007,7 +1030,9 @@ 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 */
 
-        if (!ngx_http_large_client_header) {
+        cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module_ctx);
+
+        if (!cmcf->large_client_header) {
             len = h->last - h->pos; 
             ngx_memcpy(h->start, h->pos, len);
             h->pos = h->start;
--- a/src/http/ngx_http_header_filter.c
+++ b/src/http/ngx_http_header_filter.c
@@ -18,14 +18,17 @@ static int ngx_http_header_filter_init(n
 static int ngx_http_header_filter(ngx_http_request_t *r);
 
 
-ngx_http_module_t  ngx_http_header_filter_module_ctx = {
-    NULL,                                  /* create server config */
-    NULL,                                  /* init server config */
+static ngx_http_module_t  ngx_http_header_filter_module_ctx = {
+    NGX_HTTP_MODULE,
+
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
 
-    NULL,                                  /* create location config */
-    NULL,                                  /* merge location config */
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
 
-    NULL                                   /* init filters */
+    NULL,                                  /* create location configuration */
+    NULL,                                  /* merge location configuration */
 };
 
 
--- a/src/http/ngx_http_output_filter.c
+++ b/src/http/ngx_http_output_filter.c
@@ -23,7 +23,7 @@ static void ngx_http_output_filter_init(
 static ngx_command_t  ngx_http_output_filter_commands[] = {
 
     {ngx_string("output_buffer"),
-     NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+     NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_size_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_output_filter_conf_t, hunk_size),
@@ -36,11 +36,14 @@ static ngx_command_t  ngx_http_output_fi
 static ngx_http_module_t  ngx_http_output_filter_module_ctx = {
     NGX_HTTP_MODULE,
 
-    NULL,                                  /* create server config */
-    NULL,                                  /* init server config */
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
 
-    ngx_http_output_filter_create_conf,    /* create location config */
-    ngx_http_output_filter_merge_conf      /* merge location config */
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    ngx_http_output_filter_create_conf,    /* create location configuration */
+    ngx_http_output_filter_merge_conf      /* merge location configuration */
 };
 
 
@@ -336,7 +339,7 @@ static char *ngx_http_output_filter_merg
     ngx_http_output_filter_conf_t *conf =
                                        (ngx_http_output_filter_conf_t *) child;
 
-    ngx_conf_size_merge(conf->hunk_size, prev->hunk_size, 32768);
+    ngx_conf_merge_size_value(conf->hunk_size, prev->hunk_size, 32768);
 
     return NULL;
 }
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -9,13 +9,24 @@ int ngx_parse_http_request_line(ngx_http
     char  *p;
     enum {
         sw_start = 0,
+        sw_G,
+        sw_GE,
+        sw_H,
+        sw_HE,
+        sw_HEA,
+        sw_P,
+        sw_PO,
+        sw_POS,
         sw_space_after_method,
         sw_spaces_before_uri,
         sw_after_slash_in_uri,
         sw_check_uri,
         sw_uri,
         sw_http_09,
-        sw_http_version,
+        sw_http_H,
+        sw_http_HT,
+        sw_http_HTT,
+        sw_http_HTTP,
         sw_first_major_digit,
         sw_major_digit,
         sw_first_minor_digit,
@@ -30,7 +41,7 @@ int ngx_parse_http_request_line(ngx_http
     while (p < r->header_in->last && state < sw_done) {
         ch = *p++;
 
-        /* GCC 2.95.2 and VC 6.0 compile this switch as jump table */
+        /* gcc 2.95.2 and vc 6.0 compile this switch as an jump table */
 
         switch (state) {
 
@@ -40,49 +51,100 @@ int ngx_parse_http_request_line(ngx_http
 
             switch (ch) {
             case 'G':
-                if (p + 1 >= r->header_in->last) {
-                    return NGX_AGAIN;
-                }
-
-                if (*p != 'E' || *(p + 1) != 'T') {
-                    return NGX_HTTP_PARSE_INVALID_METHOD;
-                }
-
-                r->method = NGX_HTTP_GET;
-                p += 2;
+                state = sw_G;
+                break;
+            case 'H':
+                state = sw_H;
                 break;
-
-            case 'H':
-                if (p + 2 >= r->header_in->last) {
-                    return NGX_AGAIN;
-                }
+            case 'P':
+                state = sw_P;
+                break;
+            default:
+                return NGX_HTTP_PARSE_INVALID_METHOD;
+            }
+            break;
 
-                if (*p != 'E' || *(p + 1) != 'A' || *(p + 2) != 'D') {
-                    return NGX_HTTP_PARSE_INVALID_METHOD;
-                }
-
-                r->method = NGX_HTTP_HEAD;
-                p += 3;
+        case sw_G:
+            switch (ch) {
+            case 'E':
+                state = sw_GE;
                 break;
+            default:
+                return NGX_HTTP_PARSE_INVALID_METHOD;
+            }
+            break;
 
-            case 'P':
-                if (p + 2 >= r->header_in->last) {
-                    return NGX_AGAIN;
-                }
+        case sw_GE:
+            switch (ch) {
+            case 'T':
+                r->method = NGX_HTTP_GET;
+                state = sw_space_after_method;
+                break;
+            default:
+                return NGX_HTTP_PARSE_INVALID_METHOD;
+            }
+            break;
 
-                if (*p != 'O' || *(p + 1) != 'S' || *(p + 2) != 'T') {
-                    return NGX_HTTP_PARSE_INVALID_METHOD;
-                }
-
-                r->method = NGX_HTTP_POST;
-                p += 3;
+        case sw_H:
+            switch (ch) {
+            case 'E':
+                state = sw_HE;
                 break;
-
             default:
                 return NGX_HTTP_PARSE_INVALID_METHOD;
             }
+            break;
 
-            state = sw_space_after_method;
+        case sw_HE:
+            switch (ch) {
+            case 'A':
+                state = sw_HEA;
+                break;
+            default:
+                return NGX_HTTP_PARSE_INVALID_METHOD;
+            }
+            break;
+
+        case sw_HEA:
+            switch (ch) {
+            case 'D':
+                r->method = NGX_HTTP_HEAD;
+                state = sw_space_after_method;
+                break;
+            default:
+                return NGX_HTTP_PARSE_INVALID_METHOD;
+            }
+            break;
+
+        case sw_P:
+            switch (ch) {
+            case 'O':
+                state = sw_PO;
+                break;
+            default:
+                return NGX_HTTP_PARSE_INVALID_METHOD;
+            }
+            break;
+
+        case sw_PO:
+            switch (ch) {
+            case 'S':
+                state = sw_POS;
+                break;
+            default:
+                return NGX_HTTP_PARSE_INVALID_METHOD;
+            }
+            break;
+
+        case sw_POS:
+            switch (ch) {
+            case 'T':
+                r->method = NGX_HTTP_POST;
+                state = sw_space_after_method;
+                break;
+            default:
+                return NGX_HTTP_PARSE_INVALID_METHOD;
+            }
             break;
 
         /* single space after method */
@@ -214,27 +276,51 @@ int ngx_parse_http_request_line(ngx_http
                 state = sw_done;
                 break;
             case 'H':
-                state = sw_http_version;
+                state = sw_http_H;
+                break;
+            default:
+                return NGX_HTTP_PARSE_INVALID_REQUEST;
+            }
+            break;
+
+        case sw_http_H:
+            switch (ch) {
+            case 'T':
+                state = sw_http_HT;
                 break;
             default:
                 return NGX_HTTP_PARSE_INVALID_REQUEST;
             }
             break;
 
-        /* "TTP/" */
-        case sw_http_version:
-            if (p + 2 >= r->header_in->last) {
-                r->state = sw_http_version;
-                r->header_in->pos = p - 1;
-                return NGX_AGAIN;
-            }
-
-            if (ch != 'T' || *p != 'T' || *(p + 1) != 'P' || *(p + 2) != '/') {
+        case sw_http_HT:
+            switch (ch) {
+            case 'T':
+                state = sw_http_HTT;
+                break;
+            default:
                 return NGX_HTTP_PARSE_INVALID_REQUEST;
             }
+            break;
 
-            p += 3;
-            state = sw_first_major_digit;
+        case sw_http_HTT:
+            switch (ch) {
+            case 'P':
+                state = sw_http_HTTP;
+                break;
+            default:
+                return NGX_HTTP_PARSE_INVALID_REQUEST;
+            }
+            break;
+
+        case sw_http_HTTP:
+            switch (ch) {
+            case '/':
+                state = sw_first_major_digit;
+                break;
+            default:
+                return NGX_HTTP_PARSE_INVALID_REQUEST;
+            }
             break;
 
         /* first digit of major HTTP version */
new file mode 100644
--- /dev/null
+++ b/src/http/ngx_http_request.h
@@ -0,0 +1,205 @@
+#ifndef _NGX_HTTP_REQUEST_H_INCLUDED_
+#define _NGX_HTTP_REQUEST_H_INCLUDED_
+
+
+#if 0
+#include <ngx_config.h>
+
+#include <ngx_types.h>
+#include <ngx_string.h>
+#include <ngx_table.h>
+#include <ngx_hunk.h>
+#include <ngx_files.h>
+#include <ngx_connection.h>
+#include <ngx_conf_file.h>
+
+#endif
+
+
+#define NGX_HTTP_VERSION_9           9
+#define NGX_HTTP_VERSION_10       1000
+#define NGX_HTTP_VERSION_11       1001
+
+#define NGX_HTTP_GET   1
+#define NGX_HTTP_HEAD  2
+#define NGX_HTTP_POST  3
+
+#define NGX_HTTP_CONN_CLOSE       0
+#define NGX_HTTP_CONN_KEEP_ALIVE  1
+
+
+#define NGX_HTTP_PARSE_HEADER_DONE        1
+#define NGX_HTTP_PARSE_INVALID_METHOD     10
+#define NGX_HTTP_PARSE_INVALID_REQUEST    11
+#define NGX_HTTP_PARSE_TOO_LONG_URI       12
+#define NGX_HTTP_PARSE_INVALID_09_METHOD  13
+#define NGX_HTTP_PARSE_INVALID_HEADER     14
+#define NGX_HTTP_PARSE_TOO_LONG_HEADER    15
+#define NGX_HTTP_PARSE_NO_HOST_HEADER     16
+#define NGX_HTTP_PARSE_INVALID_CL_HEADER  17
+
+
+#define NGX_HTTP_OK                     200
+
+#define NGX_HTTP_SPECIAL_RESPONSE       300
+#define NGX_HTTP_MOVED_PERMANENTLY      301
+#define NGX_HTTP_MOVED_TEMPORARILY      302
+#define NGX_HTTP_NOT_MODIFIED           304
+
+#define NGX_HTTP_BAD_REQUEST            400
+#define NGX_HTTP_FORBIDDEN              403
+#define NGX_HTTP_NOT_FOUND              404
+#define NGX_HTTP_REQUEST_TIME_OUT       408
+#define NGX_HTTP_REQUEST_URI_TOO_LARGE  414
+
+#define NGX_HTTP_INTERNAL_SERVER_ERROR  500
+#define NGX_HTTP_NOT_IMPLEMENTED        501
+#define NGX_HTTP_BAD_GATEWAY            502
+#define NGX_HTTP_SERVICE_UNAVAILABLE    503
+#define NGX_HTTP_GATEWAY_TIME_OUT       504
+
+
+
+#define NGX_HTTP_STATIC_HANDLER     0
+#define NGX_HTTP_DIRECTORY_HANDLER  1
+
+
+typedef struct {
+    ngx_str_t  name;
+    int        offset;
+} ngx_http_header_t;
+
+
+typedef struct {
+    size_t            host_name_len;
+    ssize_t           content_length_n;
+
+    ngx_table_elt_t  *host;
+    ngx_table_elt_t  *connection;
+    ngx_table_elt_t  *if_modified_since;
+    ngx_table_elt_t  *content_length;
+    ngx_table_elt_t  *accept_encoding;
+
+    ngx_table_elt_t  *user_agent;
+
+    ngx_table_t      *headers;
+} ngx_http_headers_in_t;
+
+
+typedef struct {
+    ngx_chain_t       chain[4];
+    ngx_hunk_t       *header_out;
+    ngx_hunk_t       *hunk;
+    ngx_hunk_t       *file_hunk;
+    ngx_file_t        temp_file;
+    ngx_path_t       *temp_path;
+    off_t             offset;
+    char             *header_in_pos;
+} ngx_http_request_body_t;
+
+
+typedef struct {
+    int               status;
+    ngx_str_t         status_line;
+
+    ngx_table_elt_t  *server;
+    ngx_table_elt_t  *date;
+    ngx_table_elt_t  *content_type;
+    ngx_table_elt_t  *location;
+    ngx_table_elt_t  *last_modified;
+
+    ngx_table_t      *headers;
+
+    off_t             content_length;
+    char             *charset;
+    char             *etag;
+    time_t            date_time;
+    time_t            last_modified_time;
+} ngx_http_headers_out_t;
+
+
+typedef struct ngx_http_request_s ngx_http_request_t;
+
+struct ngx_http_request_s {
+    ngx_connection_t    *connection;
+
+    void               **ctx;
+    void               **main_conf;
+    void               **srv_conf;
+    void               **loc_conf;
+
+    ngx_file_t           file;
+
+    ngx_pool_t               *pool;
+    ngx_hunk_t               *header_in;
+    ngx_http_request_body_t  *request_body;
+
+    ngx_http_headers_in_t     headers_in;
+    ngx_http_headers_out_t    headers_out;
+
+    int  (*handler)(ngx_http_request_t *r);
+
+    time_t  lingering_time;
+
+    int                  method;
+    int                  http_version;
+    int                  http_major;
+    int                  http_minor;
+
+    ngx_str_t            request_line;
+    ngx_str_t            uri;
+    ngx_str_t            args;
+    ngx_str_t            exten;
+    ngx_str_t            unparsed_uri;
+
+    ngx_http_request_t  *main;
+
+    u_int       in_addr;
+
+    int         port;
+    ngx_str_t   port_name;
+
+    int         filter;
+
+    char       *discarded_buffer;
+
+    ngx_str_t   path;
+    int         path_err;
+
+    unsigned  proxy:1;
+    unsigned  cachable:1;
+    unsigned  pipeline:1;
+    unsigned  keepalive:1;
+    unsigned  lingering_close:1;
+
+    unsigned  header_read:1;
+    unsigned  header_timeout_set:1;
+
+    unsigned  logging:1;
+
+    unsigned  header_only:1;
+    unsigned  unusual_uri:1;  /* URI is not started with '/' - "GET http://" */
+    unsigned  complex_uri:1;  /* URI with "/." or with "//" (WIN32) */
+    unsigned  path_not_found:1;
+#ifdef NGX_EVENT
+    unsigned  write_level_event:1;
+#endif
+
+    int    state;
+    char  *uri_start;
+    char  *uri_end;
+    char  *uri_ext;
+    char  *args_start;
+    char  *request_start;
+    char  *request_end;
+    char  *header_name_start;
+    char  *header_name_end;
+    char  *header_start;
+    char  *header_end;
+#ifdef NGX_EVENT
+    int  (*state_handler)(ngx_http_request_t *r);
+#endif
+};
+
+
+#endif /* _NGX_HTTP_REQUEST_H_INCLUDED_ */
--- a/src/http/ngx_http_write_filter.c
+++ b/src/http/ngx_http_write_filter.c
@@ -35,11 +35,14 @@ static ngx_command_t ngx_http_write_filt
 ngx_http_module_t  ngx_http_write_filter_module_ctx = {
     NGX_HTTP_MODULE,
 
-    NULL,                                  /* create server config */
-    NULL,                                  /* init server config */
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
 
-    ngx_http_write_filter_create_conf,     /* create location config */
-    ngx_http_write_filter_merge_conf       /* merge location config */
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    ngx_http_write_filter_create_conf,     /* create location configuration */
+    ngx_http_write_filter_merge_conf       /* merge location configuration */
 };
 
 
@@ -61,9 +64,9 @@ int ngx_http_write_filter(ngx_http_reque
     ngx_http_write_filter_conf_t  *conf;
 
 
-    ctx = (ngx_http_write_filter_ctx_t *)
-                     ngx_http_get_module_ctx(r->main ? r->main : r,
-                                             ngx_http_write_filter_module_ctx);
+    ctx = ngx_http_get_module_ctx(r->main ? r->main : r,
+                                  ngx_http_write_filter_module_ctx);
+
     if (ctx == NULL) {
         ngx_http_create_ctx(r, ctx, ngx_http_write_filter_module_ctx,
                             sizeof(ngx_http_write_filter_ctx_t), NGX_ERROR);
@@ -118,9 +121,8 @@ int ngx_http_write_filter(ngx_http_reque
         }
     }
 
-    conf = (ngx_http_write_filter_conf_t *)
-                ngx_http_get_module_loc_conf(r->main ? r->main : r,
-                                             ngx_http_write_filter_module_ctx);
+    conf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
+                                        ngx_http_write_filter_module_ctx);
 
 #if (NGX_DEBUG_WRITE_FILTER)
     ngx_log_debug(r->connection->log,
@@ -139,7 +141,11 @@ int ngx_http_write_filter(ngx_http_reque
         return NGX_AGAIN;
     }
 
+#if 1
+    chain = ngx_write_chain(r->connection, ctx->out);
+#else
     chain = ngx_write_chain(r->connection, ctx->out, flush);
+#endif
 
 #if (NGX_DEBUG_WRITE_FILTER)
     ngx_log_debug(r->connection->log, "write filter %x" _ chain);
@@ -177,12 +183,10 @@ static void *ngx_http_write_filter_creat
 static char *ngx_http_write_filter_merge_conf(ngx_pool_t *pool,
                                               void *parent, void *child)
 {
-    ngx_http_write_filter_conf_t *prev =
-                                      (ngx_http_write_filter_conf_t *) parent;
-    ngx_http_write_filter_conf_t *conf =
-                                       (ngx_http_write_filter_conf_t *) child;
+    ngx_http_write_filter_conf_t *prev = parent;
+    ngx_http_write_filter_conf_t *conf = child;
 
-    ngx_conf_size_merge(conf->buffer_output, prev->buffer_output, 1460);
+    ngx_conf_merge_size_value(conf->buffer_output, prev->buffer_output, 1460);
 
     return NULL;
 }
--- a/src/os/unix/ngx_freebsd_init.c
+++ b/src/os/unix/ngx_freebsd_init.c
@@ -10,6 +10,14 @@ int ngx_freebsd_net_inet_tcp_sendspace;
 int ngx_freebsd_sendfile_nbytes_bug;
 
 
+ngx_os_io_t ngx_os_io = {
+    ngx_unix_recv,
+    NULL,
+    NULL,
+    ngx_freebsd_write_chain
+};
+
+
 int ngx_os_init(ngx_log_t *log)
 {
     size_t  size;
@@ -99,5 +107,5 @@ int ngx_os_init(ngx_log_t *log)
     ngx_log_error(NGX_LOG_INFO, log, 0, "net.inet.tcp.sendspace: %d",
                   ngx_freebsd_net_inet_tcp_sendspace);
 
-    return NGX_OK;
+    return ngx_unix_init(log);
 }
--- a/src/os/unix/ngx_freebsd_init.h
+++ b/src/os/unix/ngx_freebsd_init.h
@@ -5,10 +5,12 @@
 #include <ngx_config.h>
 #include <ngx_core.h>
 #include <ngx_log.h>
+#include <ngx_os_init.h>
 #include <sys/sysctl.h>
 
 
-int ngx_os_init(ngx_log_t *log);
+int ngx_unix_init(ngx_log_t *log);
+ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size);
 
 
 extern int ngx_freebsd_kern_osreldate;
--- a/src/os/unix/ngx_os_init.h
+++ b/src/os/unix/ngx_os_init.h
@@ -4,9 +4,13 @@
 
 #include <ngx_config.h>
 #include <ngx_log.h>
+#include <ngx_hunk.h>
+#include <ngx_connection.h>
 
 
 int ngx_os_init(ngx_log_t *log);
 
+extern ngx_os_io_t  ngx_os_io;
+
 
 #endif /* _NGX_OS_INIT_H_INCLUDED_ */
new file mode 100644
--- /dev/null
+++ b/src/os/unix/ngx_recv.c
@@ -0,0 +1,92 @@
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_errno.h>
+#include <ngx_log.h>
+#include <ngx_recv.h>
+#include <ngx_connection.h>
+
+
+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;
+
+    ev = c->read;
+
+#if (HAVE_KQUEUE) /* DEBUG */
+    if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
+        ngx_log_debug(c->log, "ngx_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) {
+
+        if (ev->error == 0) {
+            return 0;
+        }
+
+        ngx_set_socket_errno(ev->error);
+        err = ev->error;
+        n = -1;
+
+    } else {
+        n = recv(c->fd, buf, size, 0);
+
+ngx_log_debug(c->log, "ngx_recv: read:%d:%d" _ n _ size);
+
+        if (n == -1) {
+            err = ngx_socket_errno;
+        }
+    }
+
+#else /* not kqueue */
+
+    n = recv(c->fd, buf, size, 0);
+
+    if (n == -1) {
+        err = ngx_socket_errno;
+    }
+
+#endif
+
+    if (n == -1) {
+        ev->ready = 0;
+
+        if (err == NGX_ECONNRESET && ev->ignore_econnreset) {
+            return 0;
+        }
+
+        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)
+
+    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;
+    }
+
+    return n;
+}
--- a/src/os/unix/ngx_recv.h
+++ b/src/os/unix/ngx_recv.h
@@ -2,9 +2,11 @@
 #define _NGX_RECV_H_INCLUDED_
 
 
+#if 0
 #include <errno.h>
 
 #define ngx_recv(fd, buf, size, flags)  recv(fd, buf, size, flags)
+#endif
 
 
 #endif /* _NGX_RECV_H_INCLUDED_ */
rename from src/os/unix/ngx_init.c
rename to src/os/unix/ngx_unix_init.c
--- a/src/os/unix/ngx_init.c
+++ b/src/os/unix/ngx_unix_init.c
@@ -1,9 +1,24 @@
+
+#include <ngx_config.h>
+#include <ngx_core.h>
 
 
 int ngx_unix_init(ngx_log_t *log)
 {
+    struct sigaction sa;
     struct rlimit  rlmt;
 
+    ngx_memzero(&sa, sizeof(struct sigaction));
+    sa.sa_handler = SIG_IGN;
+    sigemptyset(&sa.sa_mask);
+
+    if (sigaction(SIGPIPE, &sa, NULL) == -1) {
+        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
+                      "sigaction(SIGPIPE, SIG_IGN) failed");
+        return NGX_ERROR;
+    }
+
+
     if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
         ngx_log_error(NGX_LOG_ALERT, log, errno,
                       "getrlimit(RLIMIT_NOFILE) failed)");
@@ -11,10 +26,14 @@ int ngx_unix_init(ngx_log_t *log)
     }
 
     ngx_log_error(NGX_LOG_INFO, log, 0,
-                  "getrlimit(RLIMIT_NOFILE): %d", rlmt.rlim_cur);
+                  "getrlimit(RLIMIT_NOFILE): %qd:%qd",
+                  rlmt.rlim_cur, rlmt.rlim_max);
 
+
+#if 0
     RLIM_INFINITY
     max_connections =< rlmt.rlim_cur;
+#endif
 
     return NGX_OK;
 }
new file mode 100644
--- /dev/null
+++ b/src/os/win32/ngx_init.c
@@ -0,0 +1,11 @@
+
+#include <ngx_os_init.h>
+
+int ngx_os_init(ngx_log_t *log)
+{
+    if (ngx_init_sockets(&ngx_log) == NGX_ERROR) {
+        return NGX_ERROR;
+    }
+
+    return NGX_OK;
+}
new file mode 100644
--- /dev/null
+++ b/src/os/win32/ngx_os_init.h
@@ -0,0 +1,12 @@
+#ifndef _NGX_OS_INIT_H_INCLUDED_
+#define _NGX_OS_INIT_H_INCLUDED_
+
+
+#include <ngx_config.h>
+#include <ngx_log.h>
+
+
+int ngx_os_init(ngx_log_t *log);
+
+
+#endif /* _NGX_OS_INIT_H_INCLUDED_ */