changeset 19:d7908993fdeb

nginx-0.0.1-2002-12-02-19:09:40 import; resume after 2 months stall
author Igor Sysoev <igor@sysoev.ru>
date Mon, 02 Dec 2002 16:09:40 +0000
parents 72ad26c77d2d
children a649c0a0adb3
files src/core/ngx_config_command.c src/core/ngx_string.h src/core/ngx_table.h src/http/modules/ngx_http_event_proxy_handler.c src/http/modules/ngx_http_event_proxy_handler.h src/http/modules/ngx_http_static_handler.c src/http/ngx_http.c src/http/ngx_http.h src/http/ngx_http_core.c src/http/ngx_http_core.h src/http/ngx_http_event.c src/http/ngx_http_get_time.c src/http/ngx_http_header_filter.c src/http/ngx_http_output_filter.c src/os/unix/ngx_errno.h src/os/win32/ngx_errno.h
diffstat 16 files changed, 656 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- a/src/core/ngx_config_command.c
+++ b/src/core/ngx_config_command.c
@@ -1,6 +1,260 @@
 
 #include <ngx_config.h>
 
+
+#if 0
+
+typedef struct ngx_conf_file_t {
+    ngx_fd_t  fd;
+    char     *name;
+    int       line;
+    char     *pos;
+};
+
+typedef struct ngx_conf_t {
+    char             *name;
+    ngx_array_t      *args;
+
+    ngx_conf_file_t  *file;
+    ngx_log_t        *log;
+
+    void *context;             # ngx_http_conf_t
+};
+
+static int argument_number[] = {
+    NGX_CONF_NOARGS,
+    NGX_CONF_TAKE1,
+    NGX_CONF_TAKE2,
+    NGX_CONF_TAKE3
+};
+
+
+ngx_conf_parse(cf, container, filename)
+{
+    create cf;
+
+    *conatiner(cf);
+
+    if (filename) {
+        open;
+    }
+
+    for ( ;; ) {
+        rc = ngx_conf_read_token(cf);
+
+NGX_OK, NGX_ERROR, NGX_CONF_FILE_DONE, NGX_CONF_BLOCK_DONE
+
+        if (rc != NGX_OK)
+            return rc;
+
+"listen address:port;"
+"location /images/ {"
+
+        cmd = ngx_conf_find_token(cf);
+        if (cmd == NULL) {
+            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                          "unknown directive \"%s\" in %s:%d",
+                          cf->name, cf->file->name, cf->file->line);
+            return NGX_ERROR;
+        }
+
+        if (cmd->type == NGX_CONF_CONTAINER) {
+            ngx_conf_parse(cf, cmd->container, NULL);
+
+        } else if (cmd->type == NGX_CONF_FLAG) {
+
+            if (cf->args->nelts != 1) {
+                ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                              "invalid number of arguments "
+                              "in directive \"%s\" in %s:%d",
+                              cf->name, cf->file->name, cf->file->line);
+                return NGX_ERROR;
+            }
+
+            if (ngx_strcasecmp(cf->args->elts[0], "on") == 0) {
+                flag = 1;
+
+            } else if (ngx_strcasecmp(cf->args->elts[0], "off") == 0) {
+                flag = 0;
+
+            } else {
+                ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                              "invalid flag in directive \"%s\" in %s:%d",
+                              cf->name, cf->file->name, cf->file->line);
+                return NGX_ERROR;
+            }
+
+            rv = cmd->set(cf, cmd->offset, flag);
+            if (rv) {
+                 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                               "%s in directive \"%s\" in %s:%d",
+                               rv, cf->name, cf->file->name, cf->file->line);
+                return NGX_ERROR;
+            }
+
+        } else if (cmd->type & argument_number[args->nelts]) {
+            rv = cmd->set(cf, cmd->offset, cf->args);
+            if (rv) {
+                 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                               "%s in directive \"%s\" in %s:%d",
+                               rv, cf->name, cf->file->name, cf->file->line);
+                return NGX_ERROR;
+            }
+
+        } else {
+            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                          "invalid number of arguments "
+                          "in directive \"%s\" in %s:%d",
+                          cf->name, cf->file->name, cf->file->line);
+            return NGX_ERROR;
+        }
+    }
+
+    if (filename) {
+        close;
+    }
+}    
+
+int ngx_conf_read_token(ngx_conf_t *cf)
+{
+
+    need_space = 0;
+    last_space = 1;
+    len = 0;
+    quoted = s_quoted = d_quoted = 0;
+
+    cf->args->nelts = 0;
+
+    for (/* void */ ; cf->pos < cf->end; cf->pos++) {
+
+        ch = *cf->pos;
+
+        if (ch == LF)
+            cf->line++;
+
+        if (quoted) {
+            quoted = 0;
+            continue;
+        }
+
+        len++;
+
+        if (ch = '\\') {
+            quoted = 1;
+            continue;
+        }
+
+        if (d_quoted) {
+
+            if (ch == '"') {
+                d_qouted = 0;
+                need_space = 1;
+                last_space = 1;
+                continue;
+            }
+
+        } else if (s_quoted) {
+
+            if (ch == '\'') {
+                s_qouted = 0;
+                need_space = 1;
+                last_space = 1;
+                continue;
+            }
+
+        } else {
+
+            if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {
+                ngx_test_null(word, ngx_push_array(cf->args), NGX_ERRROR);
+                ngx_test_null(*word, ngx_palloc(cf->temp_pool, len + 1),
+                              NGX_ERROR);
+
+                for (dst = *word, src = cf->start; src < cf->pos; /* void */) {
+                    if (*src == '\\')
+                        src++;
+                    *dst++ = *src++;
+                }
+                *dst = '\0';
+
+                need_space = 0;
+                last_space = 1;
+                continue;
+            }
+
+            if (need_space) {
+                return NGX_ERROR;
+            }
+
+            if (ch == ';')
+                return NGX_OK;
+
+            if (ch == '{')
+                return NGX_OK;
+
+            if (ch == '}')
+                return NGX_BLOCK_DONE;
+
+            if (last_space) {
+                if (ch == '"') {
+                    d_qouted = 1;
+                    continue;
+                }
+
+                if (ch == '\'') {
+                    s_qouted = 1;
+                    continue;
+                }
+            }
+
+            last_space = 0;
+        }
+    }
+}
+
+container
+    server
+    location
+    module
+    if
+
+http_conf current server
+          current location
+
+
+ngx_conf_t *ngx_conf_open(char *filename, ngx_log_t *log)
+{
+    ngx_cf->fd = ngx_open_file(config, NGX_FILE_RDONLY);
+    if (ngx_conf->fd == -1) {
+        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
+                      "ngx_conf_open: "
+                      ngx_open_file_n " %s failed", filename);
+
+        return NULL;
+    }
+
+    ngx_conf->name = filename;
+    ngx_conf->log = log;
+    return ngx_conf;
+}
+
+void ngx_conf_close(ngx_conf_t *cf)
+{
+    if (ngx_close_file(cf->fd) == -1) {
+        ngx_log_error(NGX_LOG_ERR, cf->log, ngx_errno,
+                      ngx_close_file_n " %s failed", cf->name);
+    }
+
+    cf->fd = -1;
+}
+
+
+
+
+
+
+#endif
+
+
 char *ngx_conf_set_size_slot(char *conf, int offset, char *value)
 {
     int size;
--- a/src/core/ngx_string.h
+++ b/src/core/ngx_string.h
@@ -5,6 +5,11 @@
 #include <ngx_config.h>
 
 
+typedef struct {
+    int   len;
+    char *data;
+} ngx_str_t;
+
 #if (WIN32)
 
 #define ngx_snprintf              _snprintf
new file mode 100644
--- /dev/null
+++ b/src/core/ngx_table.h
@@ -0,0 +1,21 @@
+#ifndef _NGX_TABLE_H_INCLUDED_
+#define _NGX_TABLE_H_INCLUDED_
+
+
+#include <ngx_config.h>
+#include <ngx_string.h>
+#include <ngx_alloc.h>
+#include <ngx_array.h>
+
+typedef ngx_array_t  ngx_table_t;
+
+typedef struct {
+    ngx_str_t  key;
+    ngx_str_t  value;
+} ngx_table_elt_t;
+
+#define ngx_create_table(p, n)  ngx_create_array(p, n, 2 * sizeof(ngx_str_t))
+#define ngx_push_table(t)       ngx_push_array(t)
+
+
+#endif /* _NGX_TABLE_H_INCLUDED_ */
new file mode 100644
--- /dev/null
+++ b/src/http/modules/ngx_http_event_proxy_handler.c
@@ -0,0 +1,206 @@
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_string.h>
+#include <ngx_file.h>
+#include <ngx_hunk.h>
+#include <ngx_http.h>
+#include <ngx_http_event_proxy_handler.h>
+
+ngx_http_module_t  ngx_http_proxy_module;
+
+
+static int ngx_http_proxy_connect(ngx_http_request_t *r,
+                                  struct sockaddr_in *addr,
+                                  char *addr_text);
+static int ngx_http_proxy_send_request(ngx_event_t *ev);
+
+
+int ngx_http_proxy_handler(ngx_http_request_t *r)
+{
+    struct sockaddr_in addr;
+    ngx_http_proxy_ctx_t  *p;
+
+    p = (ngx_http_proxy_ctx_t *) ngx_get_module_ctx(r, ngx_http_proxy_module);
+
+    if (p == NULL)
+        ngx_http_create_ctx(r, p, ngx_http_proxy_module,
+                            sizeof(ngx_http_proxy_ctx_t));
+
+    ngx_memzero(&addr, sizeof(struct sockaddr_in));
+    addr.sin_family = AF_INET;
+    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
+    addr.sin_port = htons(9000);
+
+    ngx_http_proxy_connect(r, &addr, "connecting to 127.0.0.1:9000");
+}
+
+static int ngx_http_proxy_connect(ngx_http_request_t *r,
+                                  struct sockaddr_in *addr,
+                                  char *addr_text)
+{
+    int                  rc;
+    ngx_err_t            err;
+    ngx_socket_t         s;
+    ngx_event_t         *ev;
+    ngx_connection_t    *c;
+    ngx_http_log_ctx_t  *ctx;
+
+    c = r->connection;
+    ctx = c->log->data;
+    ctx->action = addr_text;
+
+    s = ngx_socket(AF_INET, SOCK_STREAM, IPPROTO_IP, 0);
+    if (s == -1) {
+        ngx_log_error(NGX_LOG_ERR, c->log, ngx_socket_errno,
+                      ngx_socket_n " failed");
+        return NGX_ERROR;
+    }
+
+#if 0
+    if (rcvbuf) {
+        if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
+                       (const void *) &rcvbuf, sizeof(int)) == -1) {
+            ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno,
+                          "setsockopt(SO_RCVBUF) failed");
+
+            if (ngx_close_socket(s) == -1)
+                ngx_log_error(NGX_LOG_ERR, c->log, ngx_socket_errno,
+                              ngx_close_socket_n " failed");
+
+            return NGX_ERROR;
+        }
+    }
+#endif
+
+    if (ngx_nonblocking(s) == -1) {
+        ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno,
+                      ngx_nonblocking_n " failed");
+
+        if (ngx_close_socket(s) == -1)
+            ngx_log_error(NGX_LOG_ERR, c->log, ngx_socket_errno,
+                          ngx_close_socket_n " failed");
+
+        return NGX_ERROR;
+    }
+
+    rc = connect(s, (struct sockaddr *) addr, sizeof(struct sockaddr_in));
+
+    if (rc == -1) {
+        err = ngx_socket_errno;
+        if (err != NGX_EINPROGRESS) {
+            ngx_log_error(NGX_LOG_ERR, c->log, err, "connect() failed");
+
+            if (ngx_close_socket(s) == -1)
+                ngx_log_error(NGX_LOG_ERR, c->log, ngx_socket_errno,
+                              ngx_close_socket_n " failed");
+
+            return NGX_ERROR;
+        }
+    }
+
+    ngx_memzero(&ngx_read_events[s], sizeof(ngx_event_t));
+    ngx_memzero(&ngx_write_events[s], sizeof(ngx_event_t));
+    ngx_memzero(&ngx_connections[s], sizeof(ngx_connection_t));
+
+    ngx_read_events[s].data = ngx_write_events[s].data = &ngx_connections[s];
+    ngx_connections[s].read = &ngx_read_events[s];
+    ngx_connections[s].write = &ngx_write_events[s];
+
+    ngx_connections[s].fd = s;
+    ngx_connections[s].server = c->server;
+    ngx_connections[s].servers = c->servers;
+
+    ngx_connections[s].log =
+        ngx_read_events[s].log = ngx_write_events[s].log = c->log;
+
+    if (rc == -1) {
+        ngx_write_events[s].event_handler = ngx_http_proxy_send_request;
+
+        return ngx_add_event(&ngx_write_events[s],
+                             NGX_WRITE_EVENT, NGX_ONESHOT_EVENT);
+    }
+
+    ngx_write_events[s].write = 1;
+    ngx_write_events[s].ready = 1;
+
+    return ngx_http_proxy_send_request(ev);
+}
+
+static int ngx_http_proxy_send_request(ngx_event_t *ev)
+{
+    return NGX_ERROR;
+}
+
+#if 0
+
+static int ngx_http_proxy_send_request(ngx_event_t *ev)
+{
+    ngx_connection_t      *c;
+    ngx_http_request_t    *r;
+    ngx_http_proxy_ctx_t  *p;
+
+    c = (ngx_connection_t *) ev->data;
+    r = (ngx_http_request_t *) c->data;
+    p = (ngx_http_proxy_ctx_t *) ngx_get_module_ctx(r, ngx_http_proxy_module);
+
+    n = ngx_send(p->fd, p->header_out->pos.mem,
+                 p->header_out->end.mem - p->header_out->pos.mem);
+
+    if (n == NGX_ERROR) {
+        ngx_log_error(NGX_LOG_ERR, r->log, ngx_socket_errno,
+                      ngx_send_n " %s falied", p->addr_text);
+        return NGX_ERROR;
+    }
+
+    p->header_out->pos.mem += n;
+
+    if (p->header_out->end.mem - p->header_out->pos.mem > 0)
+        return NGX_AGAIN;
+
+    /* TODO: body */
+
+    return NGX_OK;
+}
+
+static int ngx_http_proxy_read_response_header(ngx_event_t *ev)
+{
+    ngx_connection_t      *c;
+    ngx_http_request_t    *r;
+    ngx_http_proxy_ctx_t  *p;
+
+    if (ev->timedout)
+        return NGX_ERROR;
+
+    c = (ngx_connection_t *) ev->data;
+    r = (ngx_http_request_t *) c->data;
+    p = (ngx_http_proxy_ctx_t *) ngx_get_module_ctx(r, ngx_http_proxy_module);
+
+    n = ngx_event_recv(c, p->header_in->last.mem,
+                       p->header_in->end - p->header_in->last.mem);
+
+}
+
+static int ngx_http_proxy_read_response_body(ngx_event_t *ev)
+{
+    ngx_connection_t      *c;
+    ngx_http_request_t    *r;
+    ngx_http_proxy_ctx_t  *p;
+
+    if (ev->timedout)
+        return NGX_ERROR;
+
+    c = (ngx_connection_t *) ev->data;
+    r = (ngx_http_request_t *) c->data;
+    p = (ngx_http_proxy_ctx_t *) ngx_get_module_ctx(r, ngx_http_proxy_module);
+
+}
+
+static int ngx_http_proxy_write_to_client(ngx_event_t *ev)
+{
+    /* если бэкенд быстрее, то CLEAR, иначе - ONESHOT */
+
+    rc = ngx_http_output_filter(r, h);
+}
+
+#endif
new file mode 100644
--- /dev/null
+++ b/src/http/modules/ngx_http_event_proxy_handler.h
@@ -0,0 +1,18 @@
+#ifndef _NGX_HTTP_PROXY_HANDLER_H_INCLUDED_
+#define _NGX_HTTP_PROXY_HANDLER_H_INCLUDED_
+
+
+#include <ngx_config.h>
+#include <ngx_array.h>
+#include <ngx_http.h>
+
+
+typedef struct {
+    int dummy;
+} ngx_http_proxy_ctx_t;
+
+
+extern ngx_http_module_t  ngx_http_proxy_module;
+
+
+#endif /* _NGX_HTTP_PROXY_HANDLER_H_INCLUDED_ */
--- a/src/http/modules/ngx_http_static_handler.c
+++ b/src/http/modules/ngx_http_static_handler.c
@@ -58,25 +58,25 @@ int ngx_http_static_handler(ngx_http_req
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    r->headers_out->status = NGX_HTTP_OK;
-    r->headers_out->content_length = ngx_file_size(r->fileinfo);
+    r->headers_out.status = NGX_HTTP_OK;
+    r->headers_out.content_length = ngx_file_size(r->fileinfo);
 /*
-    r->headers_out->last_modified = ngx_file_mtime(r->fileinfo);
+    r->headers_out.last_modified = ngx_file_mtime(r->fileinfo);
 */
 
     /* STUB */
     if (r->exten) {
         if (strcasecmp(r->exten, "html") == 0)
-            r->headers_out->content_type = "text/html; charset=koi8-r";
+            r->headers_out.content_type = "text/html; charset=koi8-r";
         else if (strcasecmp(r->exten, "gif") == 0)
-            r->headers_out->content_type = "image/gif";
+            r->headers_out.content_type = "image/gif";
         else if (strcasecmp(r->exten, "jpg") == 0)
-            r->headers_out->content_type = "image/jpeg";
+            r->headers_out.content_type = "image/jpeg";
         else if (strcasecmp(r->exten, "pdf") == 0)
-            r->headers_out->content_type = "application/pdf";
+            r->headers_out.content_type = "application/pdf";
 
     } else {
-        r->headers_out->content_type = "text/html; charset=koi8-r";
+        r->headers_out.content_type = "text/html; charset=koi8-r";
     }
 
     /* STUB */
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -31,8 +31,8 @@ int ngx_http_init(ngx_pool_t *pool, ngx_
 #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 = "/home/is/dox/";
 #endif
     ngx_http_server.doc_root_len = strlen(ngx_http_server.doc_root) + 1;
 
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -4,6 +4,8 @@
 
 #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>
@@ -56,6 +58,21 @@ typedef struct {
 } ngx_http_server_t;
 
 typedef struct {
+    int    len;
+    char  *data;
+    int    offset;
+} ngx_http_header_t;
+
+typedef struct {
+    ngx_table_elt_t  *host;
+    ngx_table_elt_t  *connection;
+    ngx_table_elt_t  *user_agent;
+    ngx_table_elt_t  *accept_encoding;
+
+    ngx_table_t      *headers;
+} ngx_http_headers_in_t;
+
+typedef struct {
     int     status;
     int     connection;
     off_t   content_length;
@@ -82,10 +99,8 @@ struct ngx_http_request_s {
     ngx_pool_t  *pool;
     ngx_hunk_t  *header_in;
 
-/*
-    ngx_http_headers_in_t *headers_in;
-*/
-    ngx_http_headers_out_t *headers_out;
+    ngx_http_headers_in_t   headers_in;
+    ngx_http_headers_out_t  headers_out;
 
     int    filename_len;
     int  (*handler)(ngx_http_request_t *r);
@@ -162,10 +177,10 @@ typedef struct {
 #define ngx_get_module_loc_conf(r, module)  r->loc_conf[module.index]
 #define ngx_get_module_ctx(r, module)  r->ctx[module.index]
 
-#define ngx_http_create_ctx(r, ctx, module, size)                             \
+#define ngx_http_create_ctx(r, cx, module, size)                              \
             do {                                                              \
-               ngx_test_null(ctx, ngx_pcalloc(r->pool, size), NGX_ERROR);     \
-               r->ctx[module.index] = ctx;                                    \
+               ngx_test_null(cx, ngx_pcalloc(r->pool, size), NGX_ERROR);      \
+               r->ctx[module.index] = cx;                                     \
             } while (0)
 
 
--- a/src/http/ngx_http_core.c
+++ b/src/http/ngx_http_core.c
@@ -6,7 +6,8 @@
 #include <ngx_http_config.h>
 
 
-static void *ngx_http_core_create_conf(ngx_pool_t *pool);
+static void *ngx_http_core_create_srv_conf(ngx_pool_t *pool);
+static void *ngx_http_core_create_loc_conf(ngx_pool_t *pool);
 
 
 static ngx_command_t ngx_http_core_commands[];
@@ -14,8 +15,8 @@ static ngx_command_t ngx_http_core_comma
 
 ngx_http_module_t  ngx_http_core_module = {
     NGX_HTTP_MODULE,
-    NULL,                                  /* create server config */
-    ngx_http_core_create_conf,             /* create location config */
+    ngx_http_core_create_srv_conf,         /* create server config */
+    ngx_http_core_create_loc_conf,         /* create location config */
     ngx_http_core_commands,                /* module directives */
     NULL,                                  /* init module */
     NULL                                   /* init output body filter */
@@ -25,7 +26,7 @@ ngx_http_module_t  ngx_http_core_module 
 static ngx_command_t ngx_http_core_commands[] = {
 
     {"send_timeout", ngx_conf_set_time_slot,
-     offsetof(ngx_http_core_conf_t, send_timeout),
+     offsetof(ngx_http_core_loc_conf_t, send_timeout),
      NGX_HTTP_LOC_CONF, NGX_CONF_TAKE1,
      "set timeout for sending response"},
 
@@ -34,12 +35,23 @@ static ngx_command_t ngx_http_core_comma
 };
 
 
-static void *ngx_http_core_create_conf(ngx_pool_t *pool)
+static void *ngx_http_core_create_srv_conf(ngx_pool_t *pool)
 {
-    ngx_http_core_conf_t *conf;
+    ngx_http_core_srv_conf_t *conf;
 
     ngx_test_null(conf,
-                  ngx_pcalloc(pool, sizeof(ngx_http_core_conf_t)),
+                  ngx_pcalloc(pool, sizeof(ngx_http_core_srv_conf_t)),
+                  NULL);
+
+    return conf;
+}
+
+static void *ngx_http_core_create_loc_conf(ngx_pool_t *pool)
+{
+    ngx_http_core_loc_conf_t *conf;
+
+    ngx_test_null(conf,
+                  ngx_pcalloc(pool, sizeof(ngx_http_core_loc_conf_t)),
                   NULL);
 
     conf->send_timeout = NGX_CONF_UNSET;
@@ -47,3 +59,15 @@ static void *ngx_http_core_create_conf(n
     return conf;
 }
 
+#if 0
+static void *ngx_http_core_create_conf(ngx_pool_t *pool)
+{
+
+    ngx_test_null(conf, ngx_palloc(pool, sizeof(ngx_http_core_conf_t)), NULL);
+
+    ngx_test_null(conf->srv, ngx_http_core_create_srv_conf_t(pool), NULL);
+    ngx_test_null(conf->loc, ngx_http_core_create_loc_conf_t(pool), NULL);
+    conf->parent = 
+    conf->next = NULL;
+}
+#endif
--- a/src/http/ngx_http_core.h
+++ b/src/http/ngx_http_core.h
@@ -6,8 +6,16 @@
 
 
 typedef struct {
+    int dummy;
+} ngx_http_core_conf_t;
+
+typedef struct {
+    int dummy;
+} ngx_http_core_srv_conf_t;
+
+typedef struct {
     time_t  send_timeout;
-} ngx_http_core_conf_t;
+} ngx_http_core_loc_conf_t;
 
 
 extern ngx_http_module_t  ngx_http_core_module;
--- a/src/http/ngx_http_event.c
+++ b/src/http/ngx_http_event.c
@@ -9,6 +9,8 @@
 #include <ngx_files.h>
 #include <ngx_log.h>
 #include <ngx_alloc.h>
+#include <ngx_array.h>
+#include <ngx_table.h>
 #include <ngx_hunk.h>
 #include <ngx_connection.h>
 #include <ngx_http.h>
@@ -19,6 +21,7 @@
 #include <ngx_http_output_filter.h>
 int ngx_http_static_handler(ngx_http_request_t *r);
 int ngx_http_index_handler(ngx_http_request_t *r);
+int ngx_http_proxy_handler(ngx_http_request_t *r);
 /* */
 
 int ngx_http_init_connection(ngx_connection_t *c);
@@ -60,6 +63,15 @@ static char *header_errors[] = {
 };
 
 
+static ngx_http_header_t headers_in[] = {
+    { 4, "Host", offsetof(ngx_http_headers_in_t, host) },
+    { 10, "Connection", offsetof(ngx_http_headers_in_t, connection) },
+
+    { 10, "User-Agent", offsetof(ngx_http_headers_in_t, user_agent) },
+
+    { 0, NULL, 0 }
+};
+
 
 int ngx_http_init_connection(ngx_connection_t *c)
 {
@@ -292,6 +304,8 @@ static int ngx_http_process_request_line
 
         /* TODO: check too long URI - no space for header, compact buffer */
 
+        r->headers_in.headers = ngx_create_table(r->pool, 10);
+
         r->state_handler = ngx_http_process_request_header;
         ctx = r->connection->log->data;
         ctx->action = "reading client request headers";
@@ -355,11 +369,31 @@ static int ngx_http_process_request_head
 
 static int ngx_http_process_request_header_line(ngx_http_request_t *r)
 {
-    /* STUB */
-    *r->header_name_end = '\0';
-    *r->header_end = '\0';
+    int  i;
+    ngx_table_elt_t *h;
+
+    ngx_test_null(h, ngx_push_array(r->headers_in.headers), NGX_ERROR);
+
+    h->key.len = r->header_name_end - r->header_name_start;
+    ngx_test_null(h->key.data, ngx_palloc(r->pool, h->key.len + 1), NGX_ERROR);
+    ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1);
+
+    h->value.len = r->header_end - r->header_start;
+    ngx_test_null(h->value.data, ngx_palloc(r->pool, h->value.len + 1),
+                  NGX_ERROR);
+    ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1);
+
+    for (i = 0; headers_in[i].len != 0; i++) {
+        if (headers_in[i].len == h->key.len) {
+            if (strcasecmp(headers_in[i].data, h->key.data) == 0) {
+                *((ngx_table_elt_t **)
+                    ((char *) &r->headers_in + headers_in[i].offset)) = h;
+            }
+        }
+    }
+
     ngx_log_debug(r->connection->log, "HTTP header: '%s: %s'" _
-                  r->header_name_start _ r->header_start);
+                  h->key.data _ h->value.data);
 
     return NGX_OK;
 }
@@ -446,6 +480,10 @@ static int ngx_http_event_handler(ngx_ht
     int rc;
     ngx_msec_t  timeout;
 
+    ngx_log_debug(r->connection->log, "UA: '%s: %s'" _
+                  r->headers_in.user_agent->key.data _
+                  r->headers_in.user_agent->value.data);
+
     rc = ngx_http_handler(r);
 
     /* transfer not completed */
@@ -545,9 +583,17 @@ static int ngx_http_set_default_handler(
     int   err, rc;
     char *name, *loc, *file;
 
+#if 0
+    /* STUB */
+    r->handler = ngx_http_proxy_handler;
+    return NGX_OK;
+#endif
+
+/*  NO NEEDED
     ngx_test_null(r->headers_out,
                   ngx_pcalloc(r->pool, sizeof(ngx_http_headers_out_t)),
                   NGX_HTTP_INTERNAL_SERVER_ERROR);
+*/
 
     if (*(r->uri_end - 1) == '/') {
         r->handler = ngx_http_index_handler;
@@ -583,7 +629,7 @@ static int ngx_http_set_default_handler(
         ngx_log_debug(r->connection->log, "HTTP DIR: '%s'" _ r->filename);
         *file++ = '/';
         *file = '\0';
-        r->headers_out->location = r->location;
+        r->headers_out.location = r->location;
         return NGX_HTTP_MOVED_PERMANENTLY;
     }
 
@@ -605,10 +651,10 @@ static int ngx_http_block_read(ngx_event
 static int ngx_http_writer(ngx_event_t *ev)
 {
     int rc;
-    ngx_msec_t             timeout;
-    ngx_connection_t      *c;
-    ngx_http_request_t    *r;
-    ngx_http_core_conf_t  *conf;
+    ngx_msec_t                 timeout;
+    ngx_connection_t          *c;
+    ngx_http_request_t        *r;
+    ngx_http_core_loc_conf_t  *conf;
 
     c = (ngx_connection_t *) ev->data;
     r = (ngx_http_request_t *) c->data;
@@ -622,7 +668,7 @@ static int ngx_http_writer(ngx_event_t *
     if (rc == NGX_AGAIN) {
 
         if (c->sent > 0) {
-            conf = (ngx_http_core_conf_t *)
+            conf = (ngx_http_core_loc_conf_t *)
                         ngx_get_module_loc_conf(r->main ? r->main : r,
                                                 ngx_http_core_module);
 
new file mode 100644
--- /dev/null
+++ b/src/http/ngx_http_get_time.c
@@ -0,0 +1,13 @@
+
+#include <nginx.h>
+
+#include <ngx_config.h>
+
+
+ngx_http_get_time(char *buf, time_t t)
+{
+    struct tm *tp;
+
+    tp = gmtime(&t);
+    return strftime(buf, 31, "%a, %d %b %Y %H:%M:%S GMT", tp);
+}
--- a/src/http/ngx_http_header_filter.c
+++ b/src/http/ngx_http_header_filter.c
@@ -29,7 +29,7 @@ int ngx_http_header_filter(ngx_http_requ
     ngx_test_null(h, ngx_create_temp_hunk(r->pool, 1024, 0, 64),
                   NGX_ERROR);
 
-    status = r->headers_out->status - NGX_HTTP_OK;
+    status = r->headers_out.status - NGX_HTTP_OK;
 
     ngx_memcpy(h->last.mem, "HTTP/1.1 ", 9);
     h->last.mem += 9;
@@ -43,28 +43,26 @@ int ngx_http_header_filter(ngx_http_requ
     h->last.mem += 24;
 #endif
 
-/*
     ngx_memcpy(h->last.mem, "Date: ", 6);
     h->last.mem += 6;
     h->last.mem += ngx_http_get_time(h->last.mem, time(NULL));
     *(h->last.mem++) = CR; *(h->last.mem++) = LF;
-*/
 
     /* 2^64 is 20 characters  */
-    if (r->headers_out->content_length)
+    if (r->headers_out.content_length)
         h->last.mem += ngx_snprintf(h->last.mem, 49, "Content-Length: %d" CRLF,
-                                    r->headers_out->content_length);
+                                    r->headers_out.content_length);
 
     /* check */
 
-    if (r->headers_out->content_type)
+    if (r->headers_out.content_type)
         h->last.mem += ngx_snprintf(h->last.mem, 100, "Content-Type: %s" CRLF,
-                                    r->headers_out->content_type);
+                                    r->headers_out.content_type);
 
     ngx_memcpy(h->last.mem, "Server: ", 8);
     h->last.mem += 8;
-    if (r->headers_out->server) {
-        h->last.mem = ngx_cpystrn(h->last.mem, r->headers_out->server,
+    if (r->headers_out.server) {
+        h->last.mem = ngx_cpystrn(h->last.mem, r->headers_out.server,
                                   h->end - h->last.mem);
         /* check space */
 
--- a/src/http/ngx_http_output_filter.c
+++ b/src/http/ngx_http_output_filter.c
@@ -90,7 +90,7 @@ int ngx_http_output_filter(ngx_http_requ
                 ctx->out.hunk = ctx->hunk;
 
                 rc = ngx_http_output_filter_copy_hunk(ctx->hunk, ctx->in->hunk);
-#if (NGX_FILE_AIO)
+#if (NGX_FILE_AIO_READ)
                 if (rc == NGX_AGAIN)
                     return rc;
 #endif
@@ -178,7 +178,7 @@ int ngx_http_output_filter(ngx_http_requ
 
                             rc = ngx_http_output_filter_copy_hunk(ctx->hunk,
                                                                   hunk);
-#if (NGX_FILE_AIO)
+#if (NGX_FILE_AIO_READ)
                             if (rc == NGX_AGAIN) {
                                 /* add hunk to input chain */
                                 ngx_add_hunk_to_chain(ctx->in, hunk, r->pool,
@@ -243,7 +243,7 @@ static int ngx_http_output_filter_copy_h
         if (n == NGX_ERROR) {
             return n;
 
-#if (NGX_FILE_AIO)
+#if (NGX_FILE_AIO_READ)
         } else if (n == NGX_AGAIN) {
             return n;
 #endif
--- a/src/os/unix/ngx_errno.h
+++ b/src/os/unix/ngx_errno.h
@@ -10,6 +10,7 @@ typedef int               ngx_err_t;
 #define NGX_ENOENT        ENOENT
 #define NGX_EINTR         EINTR
 #define NGX_EAGAIN        EWOULDBLOCK
+#define NGX_EINPROGRESS   EINPROGRESS
 #define NGX_EADDRINUSE    EADDRINUSE
 #define NGX_ETIMEDOUT     ETIMEDOUT
 
--- a/src/os/win32/ngx_errno.h
+++ b/src/os/win32/ngx_errno.h
@@ -12,6 +12,7 @@ typedef DWORD             ngx_err_t;
 
 #define NGX_ENOENT        ERROR_FILE_NOT_FOUND
 #define NGX_EAGAIN        WSAEWOULDBLOCK
+#define NGX_EINPROGRESS   WSAEINPROGRESS
 #define NGX_EADDRINUSE    WSAEADDRINUSE
 #define NGX_ETIMEDOUT     WSAETIMEDOUT