changeset 89:29bf798b583f

nginx-0.0.1-2003-05-15-19:42:53 import
author Igor Sysoev <igor@sysoev.ru>
date Thu, 15 May 2003 15:42:53 +0000
parents 674d333f4296
children 37530da31268
files src/core/ngx_conf_file.c src/core/ngx_conf_file.h src/event/ngx_event_proxy.c src/event/ngx_event_timer.h src/http/modules/ngx_http_index_handler.c src/http/modules/ngx_http_static_handler.c src/http/ngx_http.c src/http/ngx_http.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_parse.c src/os/unix/ngx_freebsd_write_chain.c src/os/unix/ngx_recv_chain.c
diffstat 14 files changed, 427 insertions(+), 217 deletions(-) [+]
line wrap: on
line diff
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -85,8 +85,8 @@ ngx_log_debug(cf->log, "token %d" _ rc);
 
             } else {
                 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                             "%s %s in %s:%d",
-                             name->data, rv,
+                             "%s in %s:%d",
+                             rv,
                              cf->conf_file->file.name.data,
                              cf->conf_file->line);
                 return NGX_CONF_ERROR;
@@ -493,8 +493,8 @@ char *ngx_conf_set_size_slot(ngx_conf_t 
 
 char *ngx_conf_set_msec_slot(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
 {
-    int         size, total, len, scale, i;
-    u_int       max;
+    int         size, total, len, scale;
+    u_int       max, i;
     char        last, *start;
     ngx_str_t  *value;
 
@@ -584,8 +584,8 @@ char *ngx_conf_set_msec_slot(ngx_conf_t 
 
 char *ngx_conf_set_sec_slot(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
 {
-    int         size, total, len, scale, i;
-    u_int       max;
+    int         size, total, len, scale;
+    u_int       max, i;
     char        last, *start;
     ngx_str_t  *value;
 
--- a/src/core/ngx_conf_file.h
+++ b/src/core/ngx_conf_file.h
@@ -6,6 +6,7 @@
 #include <ngx_files.h>
 #include <ngx_log.h>
 #include <ngx_file.h>
+#include <ngx_time.h>
 #include <ngx_string.h>
 #include <ngx_alloc.h>
 #include <ngx_hunk.h>
@@ -13,20 +14,21 @@
 
 
 /*
- *      AAAA  number of agruments
- *    TT      command flags
- *  LL        command location
+ *        AAAA  number of agruments
+ *      FF      command flags
+ *    TT        command type, i.e. HTTP "location" or "server" command
+ *  00
  */
 
-#define NGX_CONF_NOARGS      1
-#define NGX_CONF_TAKE1       2
-#define NGX_CONF_TAKE2       4
-#define NGX_CONF_ARGS_NUMBER 0x00ffff
-#define NGX_CONF_ANY         0x010000
-#define NGX_CONF_BLOCK       0x020000
-#define NGX_CONF_FLAG        0x040000
+#define NGX_CONF_NOARGS      0x0000000001
+#define NGX_CONF_TAKE1       0x0000000002
+#define NGX_CONF_TAKE2       0x0000000004
+#define NGX_CONF_ARGS_NUMBER 0x000000ffff
+#define NGX_CONF_ANY         0x0000010000
+#define NGX_CONF_BLOCK       0x0000020000
+#define NGX_CONF_FLAG        0x0000040000
 
-#define NGX_MAIN_CONF        0x1000000
+#define NGX_MAIN_CONF        0x0001000000
 
 
 
@@ -101,8 +103,8 @@ struct ngx_conf_s {
     }
 
 #define ngx_conf_msec_merge(conf, prev, default)                             \
-    if (conf == NGX_CONF_UNSET) {                                            \
-        conf = (prev == NGX_CONF_UNSET) ? default : prev;                    \
+    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)                             \
--- a/src/event/ngx_event_proxy.c
+++ b/src/event/ngx_event_proxy.c
@@ -17,6 +17,10 @@ int ngx_event_proxy_read_upstream(ngx_ev
     ngx_hunk_t   *h, *nh;
     ngx_chain_t  *chain, *temp, *entry, *next;
 
+#if (NGX_SUPPRESS_WARN)
+    entry = NULL;
+#endif
+
 #if (NGX_EVENT_COPY_FILTER)
 
     if (p->input_filter == NULL) {
--- a/src/event/ngx_event_timer.h
+++ b/src/event/ngx_event_timer.h
@@ -23,6 +23,11 @@ ngx_inline static void ngx_event_del_tim
     ngx_log_debug(ev->log, "del timer: %d" _ *(int *)(ev->data));
 #endif
 
+    if (!ev->timer_next || !ev->timer_prev) {
+        ngx_log_error(NGX_LOG_ALERT, ev->log, 0, "timer already deleted");
+        return;
+    }
+
     if (ev->timer_prev) {
         ev->timer_prev->timer_next = ev->timer_next;
     }
--- a/src/http/modules/ngx_http_index_handler.c
+++ b/src/http/modules/ngx_http_index_handler.c
@@ -28,9 +28,10 @@ static ngx_command_t ngx_http_index_comm
      NGX_HTTP_LOC_CONF|NGX_CONF_ANY,
      ngx_http_index_set_index,
      NGX_HTTP_LOC_CONF_OFFSET,
-     0},
+     0,
+     NULL},
 
-    {ngx_string(""), 0, NULL, 0, 0}
+    {ngx_string(""), 0, NULL, 0, 0, NULL}
 };
 
 
--- a/src/http/modules/ngx_http_static_handler.c
+++ b/src/http/modules/ngx_http_static_handler.c
@@ -34,7 +34,12 @@ int ngx_http_static_handler(ngx_http_req
 
 #endif
 
-    ngx_http_discard_body(r);
+    rc = ngx_http_discard_body(r);
+
+    if (rc != NGX_OK) {
+        return rc;
+    }
+
     ctx = r->connection->log->data;
     ctx->action = "sending response";
 
@@ -74,7 +79,7 @@ int ngx_http_static_handler(ngx_http_req
         r->file.info_valid = 1;
     }
 
-#if !(WIN32) /* not regular files is probably Unix specific */
+#if !(WIN32) /* the not regular files are probably Unix specific */
 
     if (!ngx_is_file(r->file.info)) {
         ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -45,9 +45,10 @@ static ngx_command_t  ngx_http_commands[
      NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
      ngx_http_block,
      0,
-     0},
+     0,
+     NULL},
 
-    {ngx_string(""), 0, NULL, 0, 0}
+    {ngx_string(""), 0, NULL, 0, 0, NULL}
 };
 
 
@@ -71,11 +72,11 @@ static char *ngx_http_block(ngx_conf_t *
     ngx_http_module_t          *module;
     ngx_conf_t                  prev;
     ngx_http_conf_ctx_t        *ctx;
-    ngx_http_in_port_t         *in_port;
+    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;;
+    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);
@@ -148,14 +149,18 @@ static char *ngx_http_block(ngx_conf_t *
     ngx_init_array(ngx_http_index_handlers,
                    cf->pool, 3, sizeof(ngx_http_handler_pt), NGX_CONF_ERROR);
 
-    /* create lists of the ports, the addresses and the server names */
+
+    /* create the lists of the ports, the addresses and the server names
+       to allow quickly find the server core module configuration at run-time */
 
     ngx_init_array(in_ports, cf->pool, 10, sizeof(ngx_http_in_port_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++) {
 
+        /* "listen" directives */
         lscf = (ngx_http_listen_t *) cscf[s]->listen.elts;
         for (l = 0; l < cscf[s]->listen.nelts; l++) {
 
@@ -168,16 +173,28 @@ static char *ngx_http_block(ngx_conf_t *
 
                 if (lscf[l].port == in_port[p].port) {
 
+                    /* the port is already in the port list */
+
                     port_found = 1;
                     addr_found = 0;
 
-                    in_addr = (ngx_http_in_addr_t *) in_port[p].addr.elts;
-                    for (a = 0; a < in_port[p].addr.nelts; a++) {
+                    in_addr = (ngx_http_in_addr_t *) in_port[p].addrs.elts;
+                    for (a = 0; a < in_port[p].addrs.nelts; a++) {
 
                         if (lscf[l].addr == in_addr[a].addr) {
+
+                            /* the address is already bound to this port */
+
+                            /* "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++) {
+
+                                /* add the server name and server core module
+                                   configuration to the address:port */
+
+                                /* TODO: duplicate names can be checked here */
+
                                 ngx_test_null(name,
                                               ngx_push_array(&in_addr[a].names),
                                               NGX_CONF_ERROR);
@@ -186,6 +203,9 @@ static char *ngx_http_block(ngx_conf_t *
                                 name->core_srv_conf = s_name[n].core_srv_conf;
                             }
 
+                            /* check duplicate "default" server that
+                               serves this address:port */
+
                             if (lscf[l].flags & NGX_HTTP_DEFAULT_SERVER) {
                                 if (in_addr[a].flags
                                                    & NGX_HTTP_DEFAULT_SERVER) {
@@ -206,18 +226,25 @@ static char *ngx_http_block(ngx_conf_t *
 
                             break;
 
-                        /* "*:XX" is the last resort */
-                        } else if (in_addr[p].addr == INADDR_ANY) {
+                        } else if (in_addr[a].addr == INADDR_ANY) {
+
+                            /* "*:port" must be the last resort so move it
+                               to the end of the address list and add
+                               the new address at its place */
+
                             ngx_test_null(inaddr,
-                                          ngx_push_array(&in_port[p].addr),
+                                          ngx_push_array(&in_port[p].addrs),
                                           NGX_CONF_ERROR);
 
                             ngx_memcpy(inaddr, &in_addr[a],
                                        sizeof(ngx_http_in_addr_t));
 
-                            inaddr->addr = lscf[l].addr;
-                            inaddr->flags = lscf[l].flags;   
-                            inaddr->core_srv_conf = cscf[s];
+                            in_addr[a].addr = lscf[l].addr;
+                            in_addr[a].flags = lscf[l].flags;   
+                            in_addr[a].core_srv_conf = cscf[s];
+
+                            /* create the empty list of the server names that
+                               can be served on this address:port */
 
                             ngx_init_array(inaddr->names, cf->pool, 10,
                                            sizeof(ngx_http_server_name_t),
@@ -230,14 +257,21 @@ static char *ngx_http_block(ngx_conf_t *
                     }
 
                     if (!addr_found) {
+
+                        /* add the address to the addresses list that
+                           bound to this port */
+
                         ngx_test_null(inaddr,
-                                      ngx_push_array(&in_port[p].addr),
+                                      ngx_push_array(&in_port[p].addrs),
                                       NGX_CONF_ERROR);
 
                         inaddr->addr = lscf[l].addr;
                         inaddr->flags = lscf[l].flags;   
                         inaddr->core_srv_conf = cscf[s];
 
+                        /* create the empty list of the server names that
+                           can be served on this address:port */
+
                         ngx_init_array(inaddr->names, cf->pool, 10,
                                        sizeof(ngx_http_server_name_t),
                                        NGX_CONF_ERROR);
@@ -246,23 +280,33 @@ static char *ngx_http_block(ngx_conf_t *
             }
 
             if (!port_found) {
+
+                /* add the port to the in_port list */
+
                 ngx_test_null(in_port,
                               ngx_push_array(&in_ports),
                               NGX_CONF_ERROR);
 
                 in_port->port = lscf[l].port;
 
-                ngx_init_array(in_port->addr, cf->pool, 10,
+                /* create list of the addresses that bound to this port ... */
+
+                ngx_init_array(in_port->addrs, cf->pool, 10,
                                sizeof(ngx_http_in_addr_t),
                                NGX_CONF_ERROR);
 
-                ngx_test_null(inaddr, ngx_push_array(&in_port->addr),
+                ngx_test_null(inaddr, ngx_push_array(&in_port->addrs),
                               NGX_CONF_ERROR);
 
+                /* ... and add the address to this list */
+
                 inaddr->addr = lscf[l].addr;
                 inaddr->flags = lscf[l].flags;   
                 inaddr->core_srv_conf = cscf[s];
 
+                /* create the empty list of the server names that
+                   can be served on this address:port */
+
                 ngx_init_array(inaddr->names, cf->pool, 10,
                                sizeof(ngx_http_server_name_t),
                                NGX_CONF_ERROR);
@@ -270,15 +314,17 @@ static char *ngx_http_block(ngx_conf_t *
         }
     }
 
-    /* optimzie lists of ports, addresses and server names */
+    /* optimize the lists of the ports, the addresses and the server names */
 
     /* AF_INET only */
 
     in_port = (ngx_http_in_port_t *) in_ports.elts;
     for (p = 0; p < in_ports.nelts; p++) {
 
-        in_addr = (ngx_http_in_addr_t *) in_port[p].addr.elts;
-        for (a = 0; a < in_port[p].addr.nelts; a++) {
+        /* check whether the all server names point to the same server */
+
+        in_addr = (ngx_http_in_addr_t *) in_port[p].addrs.elts;
+        for (a = 0; a < in_port[p].addrs.nelts; a++) {
 
             virtual_names = 0;
 
@@ -290,24 +336,26 @@ static char *ngx_http_block(ngx_conf_t *
                 }
             }
 
-            /* if all server names point to the same server
-               then we do not need to check them at run time */
+            /* if the all server names point to the same server
+               then we do not need to check them at run-time */
+
             if (!virtual_names) {
                 in_addr[a].names.nelts = 0;
             }
         }
 
-        /* if there is binding to "*:XX" then we need to bind to "*:XX" only
-           and ignore other binding */
+        /* if there's the binding to "*:port" then we need to bind()
+           to "*:port" only and ignore the other bindings */
+
         if (in_addr[a - 1].addr == INADDR_ANY) {
-            start = a - 1;
+            a--;
 
         } else {
-            start = 0;
+            a = 0;
         }
 
-        in_addr = (ngx_http_in_addr_t *) in_port[p].addr.elts;
-        for (a = start; a < in_port[p].addr.nelts; a++) {
+        in_addr = (ngx_http_in_addr_t *) in_port[p].addrs.elts;
+        while (a < in_port[p].addrs.nelts) {
 
             ngx_test_null(ls, ngx_push_array(&ngx_listening_sockets),
                           NGX_CONF_ERROR);
@@ -326,12 +374,12 @@ static char *ngx_http_block(ngx_conf_t *
                           NGX_CONF_ERROR);
 
             ls->addr_text.len =
-                ngx_snprintf(ls->addr_text.data
-                             + ngx_inet_ntop(AF_INET,
-                                             (char *) &in_addr[a].addr,
-                                             ls->addr_text.data,
-                                             INET_ADDRSTRLEN),
-                             6, ":%d", in_port[p].port);
+                        ngx_snprintf(ls->addr_text.data
+                                     + ngx_inet_ntop(AF_INET,
+                                                     (char *) &in_addr[a].addr,
+                                                     ls->addr_text.data,
+                                                     INET_ADDRSTRLEN),
+                                     6, ":%d", in_port[p].port);
 
             ls->family = AF_INET;
             ls->type = SOCK_STREAM;
@@ -351,22 +399,49 @@ static char *ngx_http_block(ngx_conf_t *
             ls->log = cf->log;
             ls->pool_size = ngx_http_connection_pool_size;
             ls->ctx = ctx;
-            ls->servers = &in_port[p];
+
+            if (in_port[p].addrs.nelts > 1) {
+
+                in_addr = (ngx_http_in_addr_t *) in_port[p].addrs.elts;
+                if (in_addr[in_port[p].addrs.nelts - 1].addr != INADDR_ANY) {
+
+                    /* if this port has not the "*:port" binding then create
+                       the separate ngx_http_in_port_t for the all bindings */
 
-#if 0
-            if (in_port[p].addr.nelts == 1) {
-                in_addr = (ngx_http_in_addr_t *) in_port[p].addr.elts;
+                    ngx_test_null(inport,
+                                  ngx_palloc(cf->pool,
+                                                   sizeof(ngx_http_in_port_t)),
+                                  NGX_CONF_ERROR);
+
+                    inport->port = in_port[p].port;
+
+                    /* init list of the addresses ... */
 
-                /* if there is the single address for this port and no virtual
-                   name servers so we do not need to check addresses
-                   at run time */
-                if (in_addr[a].names.nelts == 0) {
-                    ls->ctx = in_addr->core_srv_conf->ctx;
-                    ls->servers = NULL;
+                    ngx_init_array(inport->addrs, cf->pool, 1,
+                                   sizeof(ngx_http_in_addr_t),
+                                   NGX_CONF_ERROR);
+
+                    /* ... and set up it with the first address */
+
+                    inport->addrs.nelts = 1;
+                    inport->addrs.elts = in_port[p].addrs.elts;
+
+                    ls->servers = inport;
+
+                    /* prepare for the next cycle */
+
+                    in_port[p].addrs.elts += in_port[p].addrs.size;
+                    in_port[p].addrs.nelts--;
+
+                    in_addr = (ngx_http_in_addr_t *) in_port[p].addrs.elts;
+                    a = 0;
+
+                    continue;
                 }
             }
-#endif
-ngx_log_debug(cf->log, "ls ctx: %d:%08x" _ in_port[p].port _ ls->ctx);
+
+            ls->servers = &in_port[p];
+            a++;
         }
     }
 
@@ -374,8 +449,8 @@ ngx_log_debug(cf->log, "ls ctx: %d:%08x"
     in_port = (ngx_http_in_port_t *) in_ports.elts;
     for (p = 0; p < in_ports.nelts; p++) {
 ngx_log_debug(cf->log, "port: %d" _ in_port[p].port);
-        in_addr = (ngx_http_in_addr_t *) in_port[p].addr.elts;
-        for (a = 0; a < in_port[p].addr.nelts; a++) {
+        in_addr = (ngx_http_in_addr_t *) in_port[p].addrs.elts;
+        for (a = 0; a < in_port[p].addrs.nelts; a++) {
             char ip[20];
             ngx_inet_ntop(AF_INET, (char *) &in_addr[a].addr, ip, 20);
 ngx_log_debug(cf->log, "%s %08x" _ ip _ in_addr[a].core_srv_conf);
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -31,7 +31,7 @@
 #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_HEAD       13
+#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
@@ -234,6 +234,7 @@ int ngx_http_init(ngx_pool_t *pool, ngx_
 void ngx_http_init_connection(ngx_connection_t *c);
 int ngx_parse_http_request_line(ngx_http_request_t *r);
 int ngx_parse_http_header_line(ngx_http_request_t *r, ngx_hunk_t *h);
+int ngx_http_find_server_conf(ngx_http_request_t *r);
 void ngx_http_handler(ngx_http_request_t *r);
 void ngx_http_finalize_request(ngx_http_request_t *r, int error);
 void ngx_http_set_write_handler(ngx_http_request_t *r);
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -40,93 +40,108 @@ static ngx_command_t  ngx_http_core_comm
      NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
      ngx_server_block,
      0,
-     0},
+     0,
+     NULL,},
 
     {ngx_string("post_accept_timeout"),
      NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_msec_slot,
      0,
-     addressof(ngx_http_post_accept_timeout)},
+     addressof(ngx_http_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)},
+     addressof(ngx_http_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)},
+     addressof(ngx_http_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)},
+     addressof(ngx_http_client_header_timeout),
+     NULL},
 
     {ngx_string("client_header_buffer_size"),
      NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_size_slot,
      0,
-     addressof(ngx_http_client_header_buffer_size)},
+     addressof(ngx_http_client_header_buffer_size),
+     NULL},
 
     {ngx_string("large_client_header"),
      NGX_HTTP_MAIN_CONF|NGX_CONF_FLAG,
      ngx_conf_set_flag_slot,
      0,
-     addressof(ngx_http_large_client_header)},
+     addressof(ngx_http_large_client_header),
+     NULL},
 
     {ngx_string("location"),
      NGX_HTTP_SRV_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE1,
      ngx_location_block,
      NGX_HTTP_SRV_CONF_OFFSET,
-     0},
+     0,
+     NULL},
 
     {ngx_string("listen"),
      NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
      ngx_set_listen,
      NGX_HTTP_SRV_CONF_OFFSET,
-     0},
+     0,
+     NULL},
 
     {ngx_string("types"),
      NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
      ngx_types_block,
      NGX_HTTP_LOC_CONF_OFFSET,
-     0},
+     0,
+     NULL},
 
     {ngx_string("root"),
      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)},
+     offsetof(ngx_http_core_loc_conf_t, doc_root),
+     NULL},
 
     {ngx_string("sendfile"),
      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)},
+     offsetof(ngx_http_core_loc_conf_t, sendfile),
+     NULL},
 
     {ngx_string("send_timeout"),
      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)},
+     offsetof(ngx_http_core_loc_conf_t, send_timeout),
+     NULL},
 
     {ngx_string("lingering_time"),
      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)},
+     offsetof(ngx_http_core_loc_conf_t, lingering_time),
+     NULL},
 
     {ngx_string("lingering_timeout"),
      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)},
+     offsetof(ngx_http_core_loc_conf_t, lingering_timeout),
+     NULL},
 
-    {ngx_null_string, 0, NULL, 0, 0}
+    {ngx_null_string, 0, NULL, 0, 0, NULL}
 };
 
 
@@ -150,72 +165,76 @@ ngx_module_t  ngx_http_core_module = {
 };
 
 
-void ngx_http_handler(ngx_http_request_t *r)
+int ngx_http_find_server_conf(ngx_http_request_t *r)
 {
-    int                         rc, a, n, i;
-    ngx_http_handler_pt        *h;
-    ngx_http_module_t          *module;
-    ngx_http_conf_ctx_t        *ctx;
-    ngx_http_in_port_t         *in_port;
-    ngx_http_in_addr_t         *in_addr;
-    ngx_http_server_name_t     *name;
-    ngx_http_core_srv_conf_t   *scf;
-    ngx_http_core_loc_conf_t   *lcf, **plcf;
+    int                      a, n;
+    socklen_t                len;
+    struct sockaddr_in       addr_in;
+    ngx_http_in_port_t      *in_port;
+    ngx_http_in_addr_t      *in_addr;
+    ngx_http_conf_ctx_t     *ctx;
+    ngx_http_server_name_t  *name;
 
-    r->connection->unexpected_eof = 0;
-
-    r->keepalive = 0;
-    r->lingering_close = 1;
+    /* AF_INET only */
 
-#if 0
-ngx_log_debug(r->connection->log, "servers: %0x" _ r->connection->servers);
-#endif
+    in_port = (ngx_http_in_port_t *) r->connection->servers;
+    in_addr = (ngx_http_in_addr_t *) in_port->addrs.elts;
 
-    /* find server config */
+    r->port = in_port->port;
+
+    a = 0;
 
-    if (r->connection->servers == NULL) {
-        ctx = (ngx_http_conf_ctx_t *) r->connection->ctx;
-
-    } else {
+    if (in_port->addrs.nelts > 1) {
 
-         /* AF_INET only */
-
-        in_port = (ngx_http_in_port_t *) r->connection->servers;
-        in_addr = (ngx_http_in_addr_t *) in_port->addr.elts;
-
-        a = 0;
+        /* there're the several addresses on this port and one of them
+           is "*:port" so getsockname() is needed to determine
+           the server address */
 
-        if (in_port->addr.nelts > 1) {
-            /* find r->in_addr, getsockname() */ 
-
-            for ( /* void */ ; a < in_port->addr.nelts; a++) {
+        len = sizeof(struct sockaddr_in);
+        if (getsockname(r->connection->fd, (struct sockaddr *) &addr_in, &len)
+                                                                       == -1) {
+            ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_socket_errno,
+                          "getsockname() failed");
+            return NGX_ERROR;
+        }
 
-                if (in_addr[a].addr == INADDR_ANY) {
-                    break;
-                }
+        r->in_addr = addr_in.sin_addr.s_addr;
 
-                if (in_addr[a].addr == r->in_addr) {
-                    break;
-                }
+        for ( /* void */ ; a < in_port->addrs.nelts; a++) {
+            if (in_addr[a].addr == r->in_addr) {
+ngx_log_debug(r->connection->log, "FOUND");
+                break;
             }
         }
 
-        ctx = in_addr[a].core_srv_conf->ctx;
+if (a == in_port->addrs.nelts) {
+    ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                  "addr not found");
+    exit(1);
+}
 
-        if (r->headers_in.host_name_len > 0) {
+    } else {
+        r->in_addr = in_addr[0].addr;
+    }
+
+    /* the default server configuration for this address:port */
+    ctx = in_addr[a].core_srv_conf->ctx;
 
-            name = (ngx_http_server_name_t *) in_addr[a].names.elts;
-            for (n = 0; n < in_addr[a].names.nelts; n++) {
-                if (r->headers_in.host_name_len != name[n].name.len) {
-                    continue;
-                }
+    if (r->headers_in.host_name_len > 0) {
+
+        /* find the name based server configuration */
 
-                if (ngx_strncasecmp(r->headers_in.host->value.data,
-                                    name[n].name.data,
-                                    r->headers_in.host_name_len) == 0) {
-                    ctx = name->core_srv_conf->ctx;
-                    break;
-                }
+        name = (ngx_http_server_name_t *) in_addr[a].names.elts;
+        for (n = 0; n < in_addr[a].names.nelts; n++) {
+            if (r->headers_in.host_name_len != name[n].name.len) {
+                continue;
+            }
+
+            if (ngx_strncasecmp(r->headers_in.host->value.data,
+                                name[n].name.data,
+                                r->headers_in.host_name_len) == 0) {
+                ctx = name->core_srv_conf->ctx;
+                break;
             }
         }
     }
@@ -229,7 +248,30 @@ ngx_log_debug(r->connection->log, "srv_c
 ngx_log_debug(r->connection->log, "loc_conf: %0x" _ r->loc_conf);
 #endif
 
-    /* run rewrite url phase */
+    return NGX_OK;
+}
+
+
+void ngx_http_handler(ngx_http_request_t *r)
+{
+    int                        rc, i;
+    ngx_http_handler_pt       *h;
+    ngx_http_module_t         *module;
+    ngx_http_core_loc_conf_t  *lcf, **plcf;
+    ngx_http_core_srv_conf_t  *scf;
+
+    r->connection->unexpected_eof = 0;
+
+    r->keepalive = 0;
+
+    if (r->headers_in.content_length_n > 0) {
+        r->lingering_close = 1;
+    }
+
+    /* TEST STUB */ r->lingering_close = 1;
+
+
+    /* TODO: run rewrite url phase */
 
 
     /* find location config */
@@ -383,7 +425,6 @@ ngx_log_debug(r->connection->log, "HTTP 
     if (r->file.info.dwFileAttributes == INVALID_FILE_ATTRIBUTES) {
         err = ngx_errno;
         ngx_log_error(NGX_LOG_ERR, r->connection->log, err,
-                      "ngx_http_core_translate_handler: "
                       ngx_file_type_n " \"%s\" failed", r->file.name.data);
 
         if (err == NGX_ENOENT || err == NGX_ENOTDIR) {
@@ -406,7 +447,6 @@ ngx_log_debug(r->connection->log, "HTTP 
     if (r->file.fd == NGX_INVALID_FILE) {
         err = ngx_errno;
         ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno,
-                      "ngx_http_core_handler: "
                       ngx_open_file_n " \"%s\" failed", r->file.name.data);
 
         if (err == NGX_ENOENT || err == NGX_ENOTDIR) {
@@ -423,12 +463,10 @@ ngx_log_debug(r->connection->log, "HTTP 
     if (!r->file.info_valid) {
         if (ngx_stat_fd(r->file.fd, &r->file.info) == NGX_FILE_ERROR) {
             ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
-                          "ngx_http_core_handler: "
                           ngx_stat_fd_n " \"%s\" failed", r->file.name.data);
 
             if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) {
                 ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
-                              "ngx_http_core_handler: "
                               ngx_close_file_n " \"%s\" failed",
                               r->file.name.data);
             }
@@ -446,7 +484,6 @@ ngx_log_debug(r->connection->log, "HTTP 
 #if !(WIN9X)
         if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) {
             ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
-                          "ngx_http_core_handler: "
                           ngx_close_file_n " \"%s\" failed", r->file.name.data);
         }
 #endif
@@ -842,13 +879,13 @@ static void *ngx_http_core_create_loc_co
                   ngx_pcalloc(pool, sizeof(ngx_http_core_loc_conf_t)), 
                   NGX_CONF_ERROR);
 
-/*
-    ngx_pcalloc():
+    /* set by ngx_pcalloc():
 
     lcf->doc_root.len = 0;
     lcf->doc_root.data = NULL;
     lcf->types = NULL;
-*/
+
+    */
 
     lcf->sendfile = NGX_CONF_UNSET;
 
@@ -933,23 +970,45 @@ static char *ngx_http_core_merge_loc_con
 
 static char *ngx_set_listen(ngx_conf_t *cf, ngx_command_t *cmd, char *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 */
+
     ngx_test_null(ls, ngx_push_array(&scf->listen), NGX_CONF_ERROR);
 
     /* AF_INET only */
 
     ls->family = AF_INET;
-    ls->addr = INADDR_ANY;
     ls->flags = 0;
     ls->file_name = cf->conf_file->file.name;
     ls->line = cf->conf_file->line;
 
     args = (ngx_str_t *) cf->args->elts;
+    addr = args[1].data;
 
-    ls->port = ngx_atoi(args[1].data, args[1].len);
+    for (p = 0; p < args[1].len; p++) {
+        if (addr[p] == ':') {
+            addr[p++] = '\0';
+
+            ls->addr = inet_addr(addr);
+            if (ls->addr == INADDR_NONE) {
+                return "bad addr";
+            }
+
+            break;
+        }
+    }
+
+    if (p == args[1].len) {
+        ls->addr = INADDR_ANY;
+        p = 0;
+    }
+
+    ls->port = ngx_atoi(&addr[p], args[1].len - p);
     if (ls->port < 1 || ls->port > 65536) {
         return "port must be between 1 and 65535";
     }
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -31,9 +31,10 @@ typedef struct {
 
 typedef struct {
     int           port;
-    ngx_array_t   addr;        /* array of ngx_http_in_addr_t */
+    ngx_array_t   addrs;       /* array of ngx_http_in_addr_t */
 } ngx_http_in_port_t;
 
+
 typedef struct {
     u_int32_t                  addr;
     ngx_array_t                names;     /* array of ngx_http_server_name_t */
@@ -42,8 +43,10 @@ typedef struct {
     int                        flags;    
 } ngx_http_in_addr_t;
 
+/* ngx_http_in_addr_t's flags */
 #define NGX_HTTP_DEFAULT_SERVER  1
 
+
 typedef struct {
     ngx_str_t                  name;
     ngx_http_core_srv_conf_t  *core_srv_conf; /* virtual name server conf */
@@ -54,7 +57,7 @@ typedef struct {
 
 #define ngx_http_types_hash_key(key, ext)                                   \
         {                                                                   \
-            int n;                                                          \
+            uint n;                                                         \
             for (key = 0, n = 0; n < ext.len; n++) {                        \
                 key += ext.data[n];                                         \
             }                                                               \
@@ -79,10 +82,10 @@ typedef struct {
     ngx_array_t  *types;
 
     int         sendfile;                /* sendfile */
-    time_t      send_timeout;            /* send_timeout */
+    ngx_msec_t  send_timeout;            /* send_timeout */
     size_t      send_lowat;              /* send_lowa */
     size_t      discarded_buffer_size;   /* discarded_buffer_size */
-    time_t      lingering_time;          /* lingering_time */
+    ngx_msec_t  lingering_time;          /* lingering_time */
     ngx_msec_t  lingering_timeout;       /* lingering_timeout */
 
 } ngx_http_core_loc_conf_t;
--- a/src/http/ngx_http_event.c
+++ b/src/http/ngx_http_event.c
@@ -25,8 +25,9 @@ static ssize_t ngx_http_read_request_hea
 
 static void ngx_http_writer(ngx_event_t *ev);
 
-static int ngx_http_block_read(ngx_event_t *ev);
-static int ngx_http_read_discarded_body(ngx_event_t *ev);
+static void ngx_http_block_read(ngx_event_t *ev);
+static void ngx_http_read_discarded_body_event(ngx_event_t *rev);
+static int ngx_http_read_discarded_body(ngx_http_request_t *r);
 
 static void ngx_http_set_keepalive(ngx_http_request_t *r);
 static void ngx_http_keepalive_handler(ngx_event_t *ev);
@@ -43,7 +44,7 @@ static char *header_errors[] = {
     "client %s sent invalid method",
     "client %s sent invalid request",
     "client %s sent too long URI",
-    "client %s sent HEAD method in HTTP/0.9 request",
+    "client %s sent invalid method in HTTP/0.9 request",
 
     "client %s sent invalid header, URL: %s",
     "client %s sent too long header line, URL: %s",
@@ -338,6 +339,13 @@ static void ngx_http_process_request_lin
         }
 
         if (r->http_version == NGX_HTTP_VERSION_9) {
+            if (ngx_http_find_server_conf(r) == NGX_ERROR) {
+                ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+                ngx_http_close_connection(c);
+                return;
+            }
+
+            rev->event_handler = ngx_http_block_read;
             ngx_http_handler(r);
             return;
         }
@@ -539,6 +547,13 @@ static void ngx_http_process_request_hea
                 }
             }
 
+            if (ngx_http_find_server_conf(r) == NGX_ERROR) {
+                ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+                ngx_http_close_connection(c);
+                return;
+            }
+
+            rev->event_handler = ngx_http_block_read;
             ngx_http_handler(r);
             return;
 
@@ -605,9 +620,9 @@ static ssize_t ngx_http_read_request_hea
                        r->header_in->end - r->header_in->last);
 
     if (n == NGX_AGAIN) {
+        rev = r->connection->read;
+
         if (!r->header_timeout_set) {
-            rev = r->connection->read;
-
             if (rev->timer_set) {
                 ngx_del_timer(rev);
             } else {
@@ -666,11 +681,15 @@ void ngx_http_finalize_request(ngx_http_
     if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
 
         rev = r->connection->read;
-
         if (rev->timer_set) {
             ngx_del_timer(rev);
-        } else {
-            rev->timer_set = 1;
+            rev->timer_set = 0;
+        }
+
+        wev = r->connection->write;
+        if (wev->timer_set) {
+            ngx_del_timer(wev);
+            wev->timer_set = 0;
         }
 
         rc = ngx_http_special_response_handler(r, rc);
@@ -811,90 +830,122 @@ static void ngx_http_writer(ngx_event_t 
 
     } else {
         ngx_http_close_request(r, 0);
+        ngx_http_close_connection(r->connection);
     }
 }
 
 
-static int ngx_http_block_read(ngx_event_t *ev)
+static void ngx_http_block_read(ngx_event_t *rev)
 {
-    ngx_log_debug(ev->log, "http read blocked");
+    ngx_connection_t          *c;
+    ngx_http_request_t        *r;
+
+    ngx_log_debug(rev->log, "http read blocked");
 
     /* aio does not call this handler */
 
-#if (USE_KQUEUE)
+    if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
 
-    return NGX_OK;
+        /* select, poll, /dev/poll */
 
-#else
+        rev->blocked = 1;
 
-    if (ngx_event_flags & NGX_USE_LEVEL_EVENT) { /* select, poll, /dev/poll */
-        ev->blocked = 1;
-        return ngx_del_event(ev, NGX_READ_EVENT, 0);
-
-    } else {                                     /* kqueue, epoll */
-        return NGX_OK;
+        if (ngx_del_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
+            c = (ngx_connection_t *) rev->data;
+            r = (ngx_http_request_t *) c->data;
+            ngx_http_close_request(r, 0);
+            ngx_http_close_connection(c);
+        }
     }
 
-#endif /* USE_KQUEUE */
+    /* kqueue, epoll */
+
+    return;
 }
 
 
-/* STUB */
-int ngx_http_discard_body(ngx_http_request_t *r)
-{
-    return NGX_OK;
-}
-
-#if 0
-/* TODO */
 int ngx_http_discard_body(ngx_http_request_t *r)
 {
-    ngx_event_t  *ev;
+    ssize_t       size;
+    ngx_event_t  *rev;
 
-    ev = r->connection->read;
+    rev = r->connection->read;
 
-    ngx_log_debug(r->connection->log, "set discard body");
+    ngx_log_debug(rev->log, "set discard body");
 
-    if (ev->timer_set) {
-        ngx_del_timer(ev);
-        ev->timer_set = 0;
+    if (rev->timer_set) {
+        ngx_del_timer(rev);
+        rev->timer_set = 0;
     }
 
-    if (r->headers_in.content_length_n) {
-        ev->event_handler = ngx_http_read_discarded_body;
-        /* if blocked - read */
-        /* else add timer */
+    if (r->headers_in.content_length_n > 0) {
+
+        size = r->header_in->last - r->header_in->pos;
+
+        if (size) {
+            if (r->headers_in.content_length_n > size) {
+                r->headers_in.content_length_n -= size;
+
+            } else {
+                r->header_in->pos += r->headers_in.content_length_n;
+                r->headers_in.content_length_n = 0;
+                return NGX_OK;
+            }
+        }
+ 
+        rev->event_handler = ngx_http_read_discarded_body_event;
+
+        if (rev->blocked) {
+            if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
+                if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT)
+                                                                == NGX_ERROR) {
+                    return NGX_HTTP_INTERNAL_SERVER_ERROR;
+                }
+            }
+
+            rev->blocked = 0;
+            return ngx_http_read_discarded_body(r);
+        }
     }
 
     return NGX_OK;
 }
 
 
-/* TODO */
-static int ngx_http_read_discarded_body(ngx_event_t *ev)
+static void ngx_http_read_discarded_body_event(ngx_event_t *rev)
 {
-    size_t   size;
-    ssize_t  n;
-    ngx_connection_t          *c;
-    ngx_http_request_t        *r;
+    int                  rc;
+    ngx_connection_t    *c;
+    ngx_http_request_t  *r;
+
+    c = (ngx_connection_t *) rev->data;
+    r = (ngx_http_request_t *) c->data;
+
+    rc = ngx_http_read_discarded_body(r);
+
+    if (rc != NGX_OK) {
+        ngx_http_close_request(r, rc);
+        ngx_http_close_connection(c);
+    }
+}
+
+
+static int ngx_http_read_discarded_body(ngx_http_request_t *r)
+{
+    size_t                     size;
+    ssize_t                    n;
     ngx_http_core_loc_conf_t  *lcf;
 
-    ngx_log_debug(ev->log, "http read discarded body");
-
-    if (ev->timedout) {
-        return NGX_ERROR;
-    }
-
-    c = (ngx_connection_t *) ev->data;
-    r = (ngx_http_request_t *) c->data;
+    ngx_log_debug(r->connection->log, "http read discarded body");
 
     lcf = (ngx_http_core_loc_conf_t *)
                      ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx);
 
     if (r->discarded_buffer == NULL) {
-        ngx_test_null(r->discarded_buffer,
-                      ngx_palloc(r->pool, lcf->discarded_buffer_size),
-                      NGX_ERROR);
+        r->discarded_buffer = ngx_palloc(r->pool, lcf->discarded_buffer_size);
+        if (r->discarded_buffer == NULL) {
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
     }
 
     size = r->headers_in.content_length_n;
@@ -902,9 +953,9 @@ static int ngx_http_read_discarded_body(
         size = lcf->discarded_buffer_size;
     }
 
-    n = ngx_event_recv(c, r->discarded_buffer, size);
+    n = ngx_event_recv(r->connection, r->discarded_buffer, size);
     if (n == NGX_ERROR) {
-        return NGX_ERROR;
+        return NGX_HTTP_BAD_REQUEST;
     }
 
     if (n == NGX_AGAIN) {
@@ -912,10 +963,9 @@ static int ngx_http_read_discarded_body(
     }
 
     r->headers_in.content_length_n -= n;
-    /* XXX: what if r->client_content_length == 0 ? */
+
     return NGX_OK;
 }
-#endif
 
 
 static void ngx_http_set_keepalive(ngx_http_request_t *r)
@@ -1182,7 +1232,7 @@ void ngx_http_close_request(ngx_http_req
 
     if (r->pool == NULL) {
         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                      "http already closed");
+                      "http request already closed");
         return;
     }
 
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -314,12 +314,12 @@ int ngx_parse_http_request_line(ngx_http
         r->http_version = r->http_major * 1000 + r->http_minor;
         r->state = sw_start;
 
-        if (r->http_version == 9 && r->method == NGX_HTTP_HEAD) {
-            return NGX_HTTP_PARSE_INVALID_HEAD;
-        } else {
-            return NGX_OK;
+        if (r->http_version == 9 && r->method != NGX_HTTP_GET) {
+            return NGX_HTTP_PARSE_INVALID_09_METHOD;
         }
 
+        return NGX_OK;
+
     } else {
         r->state = state;
         return NGX_AGAIN;
--- a/src/os/unix/ngx_freebsd_write_chain.c
+++ b/src/os/unix/ngx_freebsd_write_chain.c
@@ -54,6 +54,7 @@ ngx_chain_t *ngx_freebsd_write_chain(ngx
             if (ngx_freebsd_sendfile_nbytes_bug) {
                 hsize += ce->hunk->last - ce->hunk->pos;
             }
+
             ce = ce->next;
         }
     }
--- a/src/os/unix/ngx_recv_chain.c
+++ b/src/os/unix/ngx_recv_chain.c
@@ -13,6 +13,10 @@ ssize_t ngx_recv_chain(ngx_connection_t 
     ngx_err_t      err;
     ngx_array_t    io;
 
+#if (NGX_SUPPRESS_WARN)
+    iov = NULL;
+#endif
+
     ngx_init_array(io, c->pool, 10, sizeof(struct iovec), NGX_ERROR);
 
     while (entry) {