diff src/core/ngx_connection.c @ 218:05592fd7a436

nginx-0.0.1-2004-01-05-23:55:48 import
author Igor Sysoev <igor@sysoev.ru>
date Mon, 05 Jan 2004 20:55:48 +0000
parents
children f57597ec5249
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/src/core/ngx_connection.c
@@ -0,0 +1,275 @@
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_event.h>
+/* STUB */
+#include <nginx.h>
+
+
+ngx_os_io_t            ngx_io;
+
+
+ngx_int_t ngx_set_inherited_sockets(ngx_cycle_t *cycle, char **envp)
+{
+    char                *p, *v;
+    ngx_socket_t         s;
+    ngx_listening_t     *ls;
+    struct sockaddr_in  *addr_in;
+
+    for ( /* void */ ; *envp; envp++) {
+        if (ngx_strncmp(*envp, NGINX_VAR, NGINX_VAR_LEN) != 0) {
+            continue;
+        }
+
+        ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
+                      "using inherited sockets from \"%s\"", *envp);
+
+        ngx_init_array(cycle->listening, cycle->pool,
+                       10, sizeof(ngx_listening_t), NGX_ERROR);
+
+        for (p = *envp + NGINX_VAR_LEN, v = p; *p; p++) {
+            if (*p == ':' || *p == ';') {
+                s = ngx_atoi(v, p - v);
+                if (s == NGX_ERROR) {
+                    ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
+                                  "invalid socket number \"%s\" "
+                                  "in NGINX enviroment variable, "
+                                  "ignoring the rest of the variable", v);
+                    break;
+                }
+                v = p + 1;
+
+                if (!(ls = ngx_push_array(&cycle->listening))) {
+                    return NGX_ERROR;
+                }
+
+                ls->fd = s;
+
+                /* AF_INET only */
+
+                ls->sockaddr = ngx_palloc(cycle->pool,
+                                          sizeof(struct sockaddr_in));
+                if (ls->sockaddr == NULL) {
+                    return NGX_ERROR;
+                }
+
+                ls->socklen = sizeof(struct sockaddr_in);
+                if (getsockname(s, ls->sockaddr, &ls->socklen) == -1) {
+                    ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
+                                  "getsockname() of the inherited "
+                                  "socket #%d failed", s);
+                    ls->ignore = 1;
+                    continue;
+                }
+
+                addr_in = (struct sockaddr_in *) ls->sockaddr;
+
+                if (addr_in->sin_family != AF_INET) {
+                    ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
+                                  "the inherited socket #%d has "
+                                  "unsupported family", s);
+                    ls->ignore = 1;
+                    continue;
+                }
+                ls->addr_text_max_len = INET_ADDRSTRLEN;
+
+                ls->addr_text.data = ngx_palloc(cycle->pool,
+                                                ls->addr_text_max_len);
+                if (ls->addr_text.data == NULL) {
+                    return NGX_ERROR;
+                }
+
+                addr_in->sin_len = 0;
+
+                ls->family = addr_in->sin_family;
+                ls->addr_text.len = ngx_sock_ntop(ls->family, ls->sockaddr,
+                                                  ls->addr_text.data,
+                                                  ls->addr_text_max_len);
+                if (ls->addr_text.len == 0) {
+                    return NGX_ERROR;
+                }
+            }
+        }
+
+        break;
+    }
+
+    return NGX_OK;
+}
+
+
+ngx_int_t ngx_open_listening_sockets(ngx_cycle_t *cycle)
+{
+    int              tries, failed, reuseaddr, i;
+    ngx_err_t        err;
+    ngx_log_t       *log;
+    ngx_socket_t     s;
+    ngx_listening_t *ls;
+
+    reuseaddr = 1;
+#if (NGX_SUPPRESS_WARN)
+    failed = 0;
+#endif
+
+    log = cycle->log;
+
+    /* TODO: tries configurable */
+
+    for (tries = 10; tries; tries--) {
+        failed = 0;
+
+        /* for each listening socket */
+
+        ls = cycle->listening.elts;
+        for (i = 0; i < cycle->listening.nelts; i++) {
+
+            if (ls[i].ignore) {
+                continue;
+            }
+
+            if (ls[i].fd != -1) {
+                continue;
+            }
+
+            if (ls[i].inherited) {
+
+                /* TODO: close on exit */
+                /* TODO: nonblocking */
+                /* TODO: deferred accept */
+
+                continue;
+            }
+
+            s = ngx_socket(ls[i].family, ls[i].type, ls[i].protocol,
+                           ls[i].flags);
+
+            if (s == -1) {
+                ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
+                              ngx_socket_n " %s failed", ls[i].addr_text.data);
+                return NGX_ERROR;
+            }
+
+#if (WIN32)
+            /*
+             * Winsock assignes a socket number divisible by 4
+             * so to find a connection we divide a socket number by 4.
+             */
+
+            if (s % 4) {
+                ngx_log_error(NGX_LOG_EMERG, ls->log, 0,
+                              ngx_socket_n " created socket %d", s);
+                return NGX_ERROR;
+            }
+#endif
+
+            if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
+                           (const void *) &reuseaddr, sizeof(int)) == -1) {
+                ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
+                              "setsockopt(SO_REUSEADDR) %s failed",
+                              ls[i].addr_text.data);
+                return NGX_ERROR;
+            }
+
+            /* TODO: close on exit */
+
+            if (!(ngx_event_flags & NGX_USE_AIO_EVENT)) {
+                if (ngx_nonblocking(s) == -1) {
+                    ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
+                                  ngx_nonblocking_n " %s failed",
+                                  ls[i].addr_text.data);
+                    return NGX_ERROR;
+                }
+            }
+
+#if 0
+            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.data);
+                    return NGX_ERROR;
+                }
+            }
+#endif
+
+            if (bind(s, ls[i].sockaddr, ls[i].socklen) == -1) {
+                err = ngx_socket_errno;
+                ngx_log_error(NGX_LOG_EMERG, log, err,
+                              "bind() to %s failed", ls[i].addr_text.data);
+
+                if (err != NGX_EADDRINUSE)
+                    return NGX_ERROR;
+
+                if (ngx_close_socket(s) == -1)
+                    ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
+                                  ngx_close_socket_n " %s failed",
+                                  ls[i].addr_text.data);
+
+                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.data);
+                return NGX_ERROR;
+            }
+
+            /* TODO: deferred accept */
+
+            ls[i].fd = s;
+        }
+
+        if (!failed)
+            break;
+
+        /* TODO: delay configurable */
+
+        ngx_log_error(NGX_LOG_NOTICE, log, 0,
+                      "try again to bind() after 500ms");
+        ngx_msleep(500);
+    }
+
+    if (failed) {
+        ngx_log_error(NGX_LOG_EMERG, log, 0, "still can not bind()");
+        return NGX_ERROR;
+    }
+
+    return NGX_OK;
+}
+
+
+void ngx_close_listening_sockets(ngx_cycle_t *cycle)
+{
+    ngx_int_t         i;
+    ngx_socket_t      fd;
+    ngx_listening_t  *ls;
+
+    if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
+        return;
+    }
+
+    ls = cycle->listening.elts;
+    for (i = 0; i < cycle->listening.nelts; i++) {
+        fd = ls[i].fd;
+
+#if (WIN32)
+        /*
+         * Winsock assignes a socket number divisible by 4
+         * so to find a connection we divide a socket number by 4.
+         */
+
+        fd /= 4;
+#endif
+
+        ngx_del_event(&cycle->read_events[fd], NGX_READ_EVENT, NGX_CLOSE_EVENT);
+
+        if (ngx_close_socket(ls[i].fd) == -1) {
+            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
+                          ngx_close_socket_n " %s failed",
+                          ls[i].addr_text.data);
+        }
+
+        cycle->connections[fd].fd = -1;
+    }
+}