nginx-0.0.1-2002-08-20-18:48:28 import
diff --git a/src/core/nginx.c b/src/core/nginx.c
index a90b21e..bf73782 100644
--- a/src/core/nginx.c
+++ b/src/core/nginx.c
@@ -3,6 +3,8 @@
 
 #include <ngx_config.h>
 #include <ngx_string.h>
+#include <ngx_errno.h>
+#include <ngx_time.h>
 #include <ngx_log.h>
 #include <ngx_alloc.h>
 #include <ngx_array.h>
@@ -16,80 +18,134 @@
 /* */
 
 
+static void ngx_open_listening_sockets(ngx_log_t *log);
 
+
+/* STUB */
 int ngx_max_conn = 512;
 
-ngx_pool_t   ngx_pool;
-ngx_log_t    ngx_log;
-ngx_server_t ngx_server;
+ngx_server_t  ngx_server;
+/* */
+
+ngx_log_t     ngx_log;
+ngx_pool_t   *ngx_pool;
 
 
-ngx_array_t ngx_listening_sockets;
+ngx_array_t  *ngx_listening_sockets;
 
 
 int main(int argc, char *const *argv)
 {
     int  i;
-    ngx_socket_t  s;
-    ngx_listen_t *ls;
 
-    int  reuseaddr = 1;
-
+    /* STUB */
     ngx_log.log_level = NGX_LOG_DEBUG;
-    ngx_pool.log = &ngx_log;
+
+    ngx_pool = ngx_create_pool(16 * 1024, &ngx_log);
+    /* */
 
     ngx_init_sockets(&ngx_log);
 
     /* TODO: read config */
 
+    ngx_test_null(ngx_listening_sockets,
+                  ngx_create_array(ngx_pool, 10, sizeof(ngx_listen_t)), 1);
+
     /* STUB */
     /* TODO: init chain of global modules (like ngx_http.c),
        they would init its modules and ngx_listening_sockets */
-    ngx_http_init();
+    ngx_http_init(ngx_pool, &ngx_log);
 
-    /* for each listening socket */
-    ls = (ngx_listen_t *) ngx_listening_sockets.elts;
-    for (i = 0; i < ngx_listening_sockets.nelts; i++) {
-        s = socket(ls->family, ls->type, ls->protocol);
-        if (s == -1)
-            ngx_log_error(NGX_LOG_EMERG, &(ngx_log), ngx_socket_errno,
-                          "nginx: socket %s falied", ls->addr_text);
-
-        if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
-                       (const void *) &reuseaddr, sizeof(int)) == -1)
-            ngx_log_error(NGX_LOG_EMERG, &(ngx_log), ngx_socket_errno,
-                         "nginx: setsockopt (SO_REUSEADDR) %s failed",
-                         ls->addr_text);
-
-        /* TODO: close on exit */
-
-        if (ngx_nonblocking(s) == -1)
-            ngx_log_error(NGX_LOG_EMERG, &(ngx_log), ngx_socket_errno,
-                          ngx_nonblocking_n " %s failed", ls->addr_text);
-
-        if (bind(s, (struct sockaddr *) ls->addr, ls->addr_len) == -1)
-            ngx_log_error(NGX_LOG_EMERG, &(ngx_log), ngx_socket_errno,
-                         "bind to %s failed", ls->addr_text);
-
-        if (listen(s, ls->backlog) == -1)
-            ngx_log_error(NGX_LOG_EMERG, &(ngx_log), ngx_socket_errno,
-                         "listen to %s failed", ls->addr_text);
-
-        /* TODO: deferred accept */
-
-        ls->fd = s;
-        ls->server = &ngx_http_server;
-        ls->log = &ngx_log;
-    }
+    ngx_open_listening_sockets(&ngx_log);
 
     /* TODO: daemon */
 
     /* TODO: fork */
 
-    /* TODO: events: init ngx_connections and listen slots */
+    ngx_pre_thread(ngx_listening_sockets, ngx_pool, &ngx_log);
 
     /* TODO: threads */
 
     /* STUB */
-    ngx_worker(&ls, 1, &ngx_pool, &ngx_log);
+    ngx_worker(&ngx_log);
+}
+
+static void ngx_open_listening_sockets(ngx_log_t *log)
+{
+    int           times, failed, reuseaddr, i;
+    ngx_err_t     err;
+    ngx_socket_t  s;
+    ngx_listen_t *ls;
+
+    reuseaddr = 1;
+
+    for (times = 10; times; times--) {
+         failed = 0;
+
+        /* for each listening socket */
+        ls = (ngx_listen_t *) ngx_listening_sockets->elts;
+        for (i = 0; i < ngx_listening_sockets->nelts; i++) {
+            if (ls[i].done)
+                continue;
+
+#if (WIN32)
+            s = WSASocket(ls[i].family, ls[i].type, ls[i].protocol, NULL, 0, 0);
+#else
+            s = socket(ls[i].family, ls[i].type, ls[i].protocol);
+#endif
+            if (s == -1)
+                ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
+                              "nginx: socket %s falied", ls[i].addr_text);
+
+            if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
+                           (const void *) &reuseaddr, sizeof(int)) == -1)
+                ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
+                              "nginx: setsockopt (SO_REUSEADDR) %s failed",
+                              ls[i].addr_text);
+
+            /* TODO: close on exit */
+
+            if (ls[i].nonblocking) {
+                if (ngx_nonblocking(s) == -1)
+                    ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
+                                  ngx_nonblocking_n " %s failed",
+                                  ls[i].addr_text);
+            }
+
+            if (bind(s, (struct sockaddr *) ls[i].addr, ls[i].addr_len) == -1) {
+                err = ngx_socket_errno;
+                ngx_log_error(NGX_LOG_ALERT, log, err,
+                              "bind to %s failed", ls[i].addr_text);
+
+                if (err != NGX_EADDRINUSE)
+                    exit(1);
+
+                if (ngx_close_socket(s) == -1)
+                    ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
+                                  ngx_close_socket_n " %s failed",
+                                  ls[i].addr_text);
+
+                failed = 1;
+                continue;
+            }
+
+            if (listen(s, ls[i].backlog) == -1)
+                ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
+                              "listen to %s failed", ls[i].addr_text);
+
+            /* TODO: deferred accept */
+
+            ls[i].fd = s;
+            ls[i].done = 1;
+        }
+
+        if (!failed)
+            break;
+
+        ngx_log_error(NGX_LOG_NOTICE, log, 0, "try to bind again after 500ms");
+        ngx_msleep(500);
+    }
+
+    if (failed)
+        ngx_log_error(NGX_LOG_EMERG, log, 0, "can't bind");
 }
diff --git a/src/core/ngx_config.h b/src/core/ngx_config.h
index 2350dee..16ea3a6 100644
--- a/src/core/ngx_config.h
+++ b/src/core/ngx_config.h
@@ -28,6 +28,10 @@
 
 #define ngx_close_socket closesocket
 
+#ifndef HAVE_INHERITED_NONBLOCK
+#define HAVE_INHERITED_NONBLOCK  1
+#endif
+
 #ifndef HAVE_WIN32_TRANSMITPACKETS
 #define HAVE_WIN32_TRANSMITPACKETS  1
 #define HAVE_WIN32_TRANSMITFILE     0
@@ -88,6 +92,10 @@
 
 #include <osreldate.h>
 
+#ifndef HAVE_INHERITED_NONBLOCK
+#define HAVE_INHERITED_NONBLOCK  1
+#endif
+
 #if __FreeBSD_version >= 300007
 
 #ifndef HAVE_FREEBSD_SENDFILE
@@ -129,4 +137,13 @@
 #endif /* __FreeBSD__ */
 
 
+#ifdef __SOME_OS_TEMPLATE__
+
+#ifndef HAVE_INHERITED_NONBLOCK
+#define HAVE_INHERITED_NONBLOCK  1
+#endif
+
+#endif
+
+
 #endif /* _NGX_CONFIG_H_INCLUDED_ */
diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h
index 17bd58a..84cbd24 100644
--- a/src/core/ngx_connection.h
+++ b/src/core/ngx_connection.h
@@ -1,6 +1,7 @@
 #ifndef _NGX_CONNECTION_H_INCLUDED_
 #define _NGX_CONNECTION_H_INCLUDED_
 
+#include <ngx_socket.h>
 #include <ngx_log.h>
 #include <ngx_alloc.h>
 #include <ngx_server.h>
@@ -21,14 +22,14 @@
 #endif
 
     ngx_log_t        *log;
+    int             (*handler)(ngx_connection_t *c);
     ngx_server_t     *server;
     ngx_server_t     *servers;
     ngx_pool_t       *pool;
 };
 
 
-/*
-
+#if 0
 cached file
     int      fd;       -2 unused, -1 closed (but read or mmaped), >=0 open
     char    *name;
@@ -49,6 +50,6 @@
 
 EV_VNODE        should notify by some signal if diretory tree is changed
                 or stat if aged >= N seconds (big enough)
-*/
+#endif
 
 #endif /* _NGX_CONNECTION_H_INCLUDED_ */
diff --git a/src/core/ngx_hunk.c b/src/core/ngx_hunk.c
index 2bf1a53..29edfbc 100644
--- a/src/core/ngx_hunk.c
+++ b/src/core/ngx_hunk.c
@@ -1,5 +1,5 @@
 
-#include <ngx_types.h>
+#include <ngx_file.h>
 #include <ngx_hunk.h>
 
 
diff --git a/src/core/ngx_hunk.h b/src/core/ngx_hunk.h
index 8fbcf80..8352333 100644
--- a/src/core/ngx_hunk.h
+++ b/src/core/ngx_hunk.h
@@ -4,6 +4,7 @@
 
 #include <ngx_config.h>
 #include <ngx_types.h>
+#include <ngx_file.h>
 #include <ngx_alloc.h>
 
 
diff --git a/src/core/ngx_listen.h b/src/core/ngx_listen.h
index 3be7162..26980d4 100644
--- a/src/core/ngx_listen.h
+++ b/src/core/ngx_listen.h
@@ -2,8 +2,40 @@
 #define _NGX_LISTEN_H_INCLUDED_
 
 
-ngx_socket_t ngx_listen(struct sockaddr *addr, int backlog,
-                        ngx_log_t *log, char *addr_text);
+#include <ngx_config.h>
+#include <ngx_log.h>
+#include <ngx_types.h>
+#include <ngx_socket.h>
+#include <ngx_connection.h>
+
+typedef struct {
+    ngx_socket_t  fd;
+
+    void         *addr;
+    size_t        addr_len;
+    char         *addr_text;
+
+    int           family;
+    int           type;
+    int           protocol;
+
+    ngx_log_t    *log;
+    void         *server;
+    int         (*handler)(ngx_connection_t *c);
+
+    int           backlog;
+
+    unsigned      done:1;
+    unsigned      close:1;
+    unsigned      nonblocking:1;
+#if 0
+    unsigned      overlapped:1;
+#endif
+    unsigned      shared:1;          /* shared between threads or processes */
+#if (HAVE_DEFERRED_ACCEPT)
+    unsigned      deferred_accept:1;
+#endif
+} ngx_listen_t;
 
 
 #endif /* _NGX_LISTEN_H_INCLUDED_ */
diff --git a/src/core/ngx_log.h b/src/core/ngx_log.h
index 54c96d3..ad4fcee 100644
--- a/src/core/ngx_log.h
+++ b/src/core/ngx_log.h
@@ -16,6 +16,21 @@
 } ngx_log_e;
 
 /*
+    "[%time] [%level] %pid#%tid: %message:(%errno)%errstr, while %action"
+        " %peer and processing %context"
+
+    message = "recv() failed";
+    errno = 32;
+    action = "reading request headers from client";
+    peer = "192.168.1.1";
+    context = "URL /"
+
+    "[2002/08/20 12:00:00] [error] 412#3: recv() failed:(32)Broken pipe,"
+    " while reading request headers from client 192.168.1.1"
+    " and processing URL /"
+
+
+    OLD:
     "... while ", action = "reading client request headers"
     "... while reading client request headers"
     "... while ", action = "reading client request headers"
diff --git a/src/core/ngx_server.h b/src/core/ngx_server.h
index 21f6178..6372b9a 100644
--- a/src/core/ngx_server.h
+++ b/src/core/ngx_server.h
@@ -14,28 +14,4 @@
 } ngx_server_t;
 
 
-typedef struct {
-    ngx_socket_t  fd;
-
-    ngx_log_t    *log;
-    void         *server;
-
-    int           family;
-    int           type;
-    int           protocol;
-
-    void         *addr;
-    size_t        addr_len;
-    char         *addr_text;
-
-    int           backlog;
-
-    unsigned      non_blocking:1;
-    unsigned      shared:1;          /* shared between threads or processes */
-#if (HAVE_DEFERRED_ACCEPT)
-    unsigned      deferred_accept:1;
-#endif
-} ngx_listen_t;
-
-
 #endif /* _NGX_SERVER_H_INCLUDED_ */