]> git.kaiwu.me - nginx.git/commitdiff
Added the "so_keepalive=" parameter to the "listen" directive.
authorValentin Bartenev <vbart@nginx.com>
Mon, 5 Dec 2011 08:06:15 +0000 (08:06 +0000)
committerValentin Bartenev <vbart@nginx.com>
Mon, 5 Dec 2011 08:06:15 +0000 (08:06 +0000)
The "so_keepalive" directive in mail module was deprecated.

Thanks to Vsevolod Stakhov for initial work.

auto/unix
src/core/ngx_connection.c
src/core/ngx_connection.h
src/http/ngx_http.c
src/http/ngx_http_core_module.c
src/http/ngx_http_core_module.h
src/mail/ngx_mail.c
src/mail/ngx_mail.h
src/mail/ngx_mail_core_module.c

index 7621e8fa23266e7d4f7f0e5ba87d60804a779ca2..67b7a90837d5fe1cd20c8fbf433790395ed5f1b5 100755 (executable)
--- a/auto/unix
+++ b/auto/unix
@@ -328,6 +328,20 @@ ngx_feature_test="setsockopt(0, IPPROTO_TCP, TCP_DEFER_ACCEPT, NULL, 0)"
 . auto/feature
 
 
+ngx_feature="TCP_KEEPIDLE, TCP_KEEPINTVL, TCP_KEEPCNT"
+ngx_feature_name="NGX_HAVE_KEEPALIVE_TUNABLE"
+ngx_feature_run=no
+ngx_feature_incs="#include <sys/socket.h>
+                  #include <netinet/in.h>
+                  #include <netinet/tcp.h>"
+ngx_feature_path=
+ngx_feature_libs=
+ngx_feature_test="setsockopt(0, IPPROTO_TCP, TCP_KEEPIDLE, NULL, 0);
+                  setsockopt(0, IPPROTO_TCP, TCP_KEEPINTVL, NULL, 0);
+                  setsockopt(0, IPPROTO_TCP, TCP_KEEPCNT, NULL, 0)"
+. auto/feature
+
+
 ngx_feature="accept4()"
 ngx_feature_name="NGX_HAVE_ACCEPT4"
 ngx_feature_run=no
index 3674b9a740807e477054770f33d096f6cf8cccf6..9dc5510908825bd3a629f1ad1a605f31451827fe 100644 (file)
@@ -462,6 +462,7 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle)
 void
 ngx_configure_listening_sockets(ngx_cycle_t *cycle)
 {
+    int                        keepalive;
     ngx_uint_t                 i;
     ngx_listening_t           *ls;
 
@@ -499,6 +500,56 @@ ngx_configure_listening_sockets(ngx_cycle_t *cycle)
             }
         }
 
+        if (ls[i].keepalive) {
+            keepalive = (ls[i].keepalive == 1) ? 1 : 0;
+
+            if (setsockopt(ls[i].fd, SOL_SOCKET, SO_KEEPALIVE,
+                           (const void *) &keepalive, sizeof(int))
+                == -1)
+            {
+                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+                              "setsockopt(SO_KEEPALIVE, %d) %V failed, ignored",
+                              keepalive, &ls[i].addr_text);
+            }
+        }
+
+#if (NGX_HAVE_KEEPALIVE_TUNABLE) 
+
+        if (ls[i].keepidle) {
+            if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPIDLE,
+                           (const void *) &ls[i].keepidle, sizeof(int))
+                == -1)
+            {
+                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+                              "setsockopt(TCP_KEEPIDLE, %d) %V failed, ignored",
+                              ls[i].keepidle, &ls[i].addr_text);
+            }
+        }
+
+        if (ls[i].keepintvl) {
+            if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPINTVL,
+                           (const void *) &ls[i].keepintvl, sizeof(int))
+                == -1)
+            {
+                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+                             "setsockopt(TCP_KEEPINTVL, %d) %V failed, ignored",
+                             ls[i].keepintvl, &ls[i].addr_text);
+            }
+        }
+
+        if (ls[i].keepcnt) {
+            if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPCNT,
+                           (const void *) &ls[i].keepcnt, sizeof(int))
+                == -1)
+            {
+                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+                              "setsockopt(TCP_KEEPCNT, %d) %V failed, ignored",
+                              ls[i].keepcnt, &ls[i].addr_text);
+            }
+        }
+
+#endif
+
 #if (NGX_HAVE_SETFIB)
         if (ls[i].setfib != -1) {
             if (setsockopt(ls[i].fd, SOL_SOCKET, SO_SETFIB,
index f9bf504010546e747fa3ec88d1cbda1d6b33d50c..9e3ca52fbad4dbcd51ae99bd8c0d1997b3130ea5 100644 (file)
@@ -27,6 +27,11 @@ struct ngx_listening_s {
     int                 backlog;
     int                 rcvbuf;
     int                 sndbuf;
+#if (NGX_HAVE_KEEPALIVE_TUNABLE)
+    int                 keepidle;
+    int                 keepintvl;
+    int                 keepcnt;
+#endif
 
     /* handler of accepted connection */
     ngx_connection_handler_pt   handler;
@@ -60,6 +65,7 @@ struct ngx_listening_s {
 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
     unsigned            ipv6only:2;
 #endif
+    unsigned            keepalive:2;
 
 #if (NGX_HAVE_DEFERRED_ACCEPT)
     unsigned            deferred_accept:1;
index 1eb22f81e1c066b4a53e79f25d3ff13b27902735..e10dbc88d7ded9fb1227ef56363105ac7473ef23 100644 (file)
@@ -1762,6 +1762,13 @@ ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)
     ls->rcvbuf = addr->opt.rcvbuf;
     ls->sndbuf = addr->opt.sndbuf;
 
+    ls->keepalive = addr->opt.so_keepalive;
+#if (NGX_HAVE_KEEPALIVE_TUNABLE)
+    ls->keepidle = addr->opt.tcp_keepidle;
+    ls->keepintvl = addr->opt.tcp_keepintvl;
+    ls->keepcnt = addr->opt.tcp_keepcnt;
+#endif
+
 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
     ls->accept_filter = addr->opt.accept_filter;
 #endif
index 96be4236927549fd5fe725554c71a4859160a6e4..e6668232791aa90c213cbd7e0a6217c0bf3aec0b 100644 (file)
@@ -3815,6 +3815,97 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 #endif
         }
 
+        if (ngx_strncmp(value[n].data, "so_keepalive=", 13) == 0) {
+
+            if (ngx_strcmp(&value[n].data[13], "on") == 0) {
+                lsopt.so_keepalive = 1;
+
+            } else if (ngx_strcmp(&value[n].data[13], "off") == 0) {
+                lsopt.so_keepalive = 2;
+
+            } else {
+
+#if (NGX_HAVE_KEEPALIVE_TUNABLE)
+                u_char     *p, *end;
+                ngx_str_t   s;
+
+                end = value[n].data + value[n].len;
+                s.data = value[n].data + 13;
+
+                p = ngx_strlchr(s.data, end, ':');
+                if (p == NULL) {
+                    p = end;
+                }
+
+                if (p > s.data) {
+                    s.len = p - s.data;
+
+                    lsopt.tcp_keepidle = ngx_parse_time(&s, 1);
+                    if (lsopt.tcp_keepidle == NGX_ERROR) {
+                        goto invalid_so_keepalive;
+                    }
+                }
+
+                s.data = (p < end) ? (p + 1) : end;
+
+                p = ngx_strlchr(s.data, end, ':');
+                if (p == NULL) {
+                    p = end;
+                }
+
+                if (p > s.data) {
+                    s.len = p - s.data;
+
+                    lsopt.tcp_keepintvl = ngx_parse_time(&s, 1);
+                    if (lsopt.tcp_keepintvl == NGX_ERROR) {
+                        goto invalid_so_keepalive;
+                    }
+                }
+
+                s.data = (p < end) ? (p + 1) : end;
+
+                if (s.data < end) {
+                    s.len = end - s.data;
+
+                    lsopt.tcp_keepcnt = ngx_atoi(s.data, s.len);
+                    if (lsopt.tcp_keepcnt == NGX_ERROR) {
+                        goto invalid_so_keepalive;
+                    }
+                }
+
+                if (lsopt.tcp_keepidle == 0 && lsopt.tcp_keepintvl == 0 
+                    && lsopt.tcp_keepcnt == 0)
+                {
+                    goto invalid_so_keepalive;
+                }
+
+                lsopt.so_keepalive = 1;
+
+#else
+
+                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                                   "the \"so_keepalive\" parameter accepts "
+                                   "only \"on\" or \"off\" on this platform");
+                return NGX_CONF_ERROR;
+
+#endif
+            }
+
+            lsopt.set = 1;
+            lsopt.bind = 1;
+
+            continue;
+
+#if (NGX_HAVE_KEEPALIVE_TUNABLE)
+        invalid_so_keepalive:
+
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "invalid so_keepalive value: \"%s\"",
+                               &value[n].data[13]);
+            return NGX_CONF_ERROR;
+#endif
+        }
+
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                            "invalid parameter \"%V\"", &value[n]);
         return NGX_CONF_ERROR;
index d2764fe0d2612b891535beb87cec9561d41ec48c..73e39e3b9d6ab2d2353e487ddd8859dc619cf4d0 100644 (file)
@@ -77,6 +77,7 @@ typedef struct {
 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
     unsigned                   ipv6only:2;
 #endif
+    unsigned                   so_keepalive:2;
 
     int                        backlog;
     int                        rcvbuf;
@@ -84,6 +85,11 @@ typedef struct {
 #if (NGX_HAVE_SETFIB)
     int                        setfib;
 #endif
+#if (NGX_HAVE_KEEPALIVE_TUNABLE)
+    int                        tcp_keepidle;
+    int                        tcp_keepintvl;
+    int                        tcp_keepcnt;
+#endif
 
 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
     char                      *accept_filter;
index 3eeb97fe0d232dd83cde1ce973c1cfc350857452..0234d18ef9bc6688e1402efd048d3290d79b5fa2 100644 (file)
@@ -308,6 +308,12 @@ found:
     addr->ctx = listen->ctx;
     addr->bind = listen->bind;
     addr->wildcard = listen->wildcard;
+    addr->so_keepalive = listen->so_keepalive;
+#if (NGX_HAVE_KEEPALIVE_TUNABLE)
+    addr->tcp_keepidle = listen->tcp_keepidle;
+    addr->tcp_keepintvl = listen->tcp_keepintvl;
+    addr->tcp_keepcnt = listen->tcp_keepcnt;
+#endif
 #if (NGX_MAIL_SSL)
     addr->ssl = listen->ssl;
 #endif
@@ -373,6 +379,13 @@ ngx_mail_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports)
             ls->log.data = &ls->addr_text;
             ls->log.handler = ngx_accept_log_error;
 
+            ls->keepalive = addr[i].so_keepalive;
+#if (NGX_HAVE_KEEPALIVE_TUNABLE)
+            ls->keepidle = addr[i].tcp_keepidle;
+            ls->keepintvl = addr[i].tcp_keepintvl;
+            ls->keepcnt = addr[i].tcp_keepcnt;
+#endif
+
 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
             ls->ipv6only = addr[i].ipv6only;
 #endif
index fd6d318a5d49c0ac43a22a1afd7b2828e10b8c04..ca78d055361921d5b05a15f6cf2471516b34dd18 100644 (file)
@@ -39,6 +39,12 @@ typedef struct {
 #endif
 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
     unsigned                ipv6only:2;
+#endif
+    unsigned                so_keepalive:2;
+#if (NGX_HAVE_KEEPALIVE_TUNABLE)
+    int                     tcp_keepidle;
+    int                     tcp_keepintvl;
+    int                     tcp_keepcnt;
 #endif
 } ngx_mail_listen_t;
 
@@ -94,6 +100,12 @@ typedef struct {
 #endif
 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
     unsigned                ipv6only:2;
+#endif
+    unsigned                so_keepalive:2;
+#if (NGX_HAVE_KEEPALIVE_TUNABLE)
+    int                     tcp_keepidle;
+    int                     tcp_keepintvl;
+    int                     tcp_keepcnt;
 #endif
 } ngx_mail_conf_addr_t;
 
index 0088fbf26be68e159446f97a654400fdbecc6cf5..530bc5d4915d119607e564b39ba4eb51ff2f4487 100644 (file)
@@ -24,6 +24,12 @@ static char *ngx_mail_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
 
 
+static ngx_conf_deprecated_t  ngx_conf_deprecated_so_keepalive = {
+    ngx_conf_deprecated, "so_keepalive", 
+    "so_keepalive\" parameter of the \"listen"
+};
+
+
 static ngx_command_t  ngx_mail_core_commands[] = {
 
     { ngx_string("server"),
@@ -52,7 +58,7 @@ static ngx_command_t  ngx_mail_core_commands[] = {
       ngx_conf_set_flag_slot,
       NGX_MAIL_SRV_CONF_OFFSET,
       offsetof(ngx_mail_core_srv_conf_t, so_keepalive),
-      NULL },
+      &ngx_conf_deprecated_so_keepalive },
 
     { ngx_string("timeout"),
       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
@@ -446,6 +452,96 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 #endif
         }
 
+        if (ngx_strncmp(value[i].data, "so_keepalive=", 13) == 0) {
+
+            if (ngx_strcmp(&value[i].data[13], "on") == 0) {
+                ls->so_keepalive = 1;
+
+            } else if (ngx_strcmp(&value[i].data[13], "off") == 0) {
+                ls->so_keepalive = 2;
+
+            } else {
+
+#if (NGX_HAVE_KEEPALIVE_TUNABLE)
+                u_char     *p, *end;
+                ngx_str_t   s;
+
+                end = value[i].data + value[i].len;
+                s.data = value[i].data + 13;
+
+                p = ngx_strlchr(s.data, end, ':');
+                if (p == NULL) {
+                    p = end;
+                }
+
+                if (p > s.data) {
+                    s.len = p - s.data;
+
+                    ls->tcp_keepidle = ngx_parse_time(&s, 1);
+                    if (ls->tcp_keepidle == NGX_ERROR) {
+                        goto invalid_so_keepalive;
+                    }
+                }
+
+                s.data = (p < end) ? (p + 1) : end;
+
+                p = ngx_strlchr(s.data, end, ':');
+                if (p == NULL) {
+                    p = end;
+                }
+
+                if (p > s.data) {
+                    s.len = p - s.data;
+
+                    ls->tcp_keepintvl = ngx_parse_time(&s, 1);
+                    if (ls->tcp_keepintvl == NGX_ERROR) {
+                        goto invalid_so_keepalive;
+                    }
+                }
+
+                s.data = (p < end) ? (p + 1) : end;
+
+                if (s.data < end) {
+                    s.len = end - s.data;
+
+                    ls->tcp_keepcnt = ngx_atoi(s.data, s.len);
+                    if (ls->tcp_keepcnt == NGX_ERROR) {
+                        goto invalid_so_keepalive;
+                    }
+                }
+
+                if (ls->tcp_keepidle == 0 && ls->tcp_keepintvl == 0
+                    && ls->tcp_keepcnt == 0)
+                {
+                    goto invalid_so_keepalive;
+                }
+
+                ls->so_keepalive = 1;
+
+#else
+
+                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                                   "the \"so_keepalive\" parameter accepts "
+                                   "only \"on\" or \"off\" on this platform");
+                return NGX_CONF_ERROR;
+
+#endif
+            }
+
+            ls->bind = 1;
+
+            continue;
+
+#if (NGX_HAVE_KEEPALIVE_TUNABLE)
+        invalid_so_keepalive:
+
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "invalid so_keepalive value: \"%s\"",
+                               &value[i].data[13]);
+            return NGX_CONF_ERROR;
+#endif
+        }
+
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                            "the invalid \"%V\" parameter", &value[i]);
         return NGX_CONF_ERROR;