changeset 429:694cd6cdb714

nginx-0.0.11-2004-09-17-20:07:35 import
author Igor Sysoev <igor@sysoev.ru>
date Fri, 17 Sep 2004 16:07:35 +0000
parents 5e73d0ea4dab
children 1fa5daf7558e
files src/core/ngx_palloc.c src/http/ngx_http_core_module.c src/http/ngx_http_core_module.h src/http/ngx_http_header_filter.c src/http/ngx_http_request.c src/http/ngx_http_request.h src/os/unix/ngx_writev_chain.c
diffstat 7 files changed, 128 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- a/src/core/ngx_palloc.c
+++ b/src/core/ngx_palloc.c
@@ -70,8 +70,9 @@ void *ngx_palloc(ngx_pool_t *pool, size_
     ngx_pool_t        *p, *n;
     ngx_pool_large_t  *large, *last;
 
-    if (size <= (size_t) NGX_MAX_ALLOC_FROM_POOL) {
-
+    if (size <= (size_t) NGX_MAX_ALLOC_FROM_POOL
+        && size <= (size_t) (pool->end - (char *) pool))
+    {
         for (p = pool, n = pool->next; /* void */; p = n, n = n->next) {
             m = ngx_align(p->last);
 
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -37,6 +37,7 @@ static char *ngx_set_server_name(ngx_con
 static char *ngx_set_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
 static char *ngx_set_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
 static char *ngx_set_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
+static char *ngx_set_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
 
 static char *ngx_http_lowat_check(ngx_conf_t *cf, void *post, void *data);
 
@@ -227,10 +228,10 @@ static ngx_command_t  ngx_http_core_comm
       NULL },
 
     { ngx_string("keepalive_timeout"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_msec_slot,
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
+      ngx_set_keepalive,
       NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_core_loc_conf_t, keepalive_timeout),
+      0,
       NULL },
 
     { ngx_string("lingering_time"),
@@ -1370,6 +1371,7 @@ static void *ngx_http_core_create_loc_co
     lcf->limit_rate = NGX_CONF_UNSET_SIZE;
     lcf->discarded_buffer_size = NGX_CONF_UNSET_SIZE;
     lcf->keepalive_timeout = NGX_CONF_UNSET_MSEC;
+    lcf->keepalive_header = NGX_CONF_UNSET;
     lcf->lingering_time = NGX_CONF_UNSET_MSEC;
     lcf->lingering_timeout = NGX_CONF_UNSET_MSEC;
     lcf->reset_timedout_connection = NGX_CONF_UNSET;
@@ -1457,7 +1459,9 @@ static char *ngx_http_core_merge_loc_con
     ngx_conf_merge_size_value(conf->discarded_buffer_size,
                               prev->discarded_buffer_size, 1500);
     ngx_conf_merge_msec_value(conf->keepalive_timeout,
-                              prev->keepalive_timeout, 70000);
+                              prev->keepalive_timeout, 75000);
+    ngx_conf_merge_sec_value(conf->keepalive_header,
+                              prev->keepalive_header, 0);
     ngx_conf_merge_msec_value(conf->lingering_time,
                               prev->lingering_time, 30000);
     ngx_conf_merge_msec_value(conf->lingering_timeout,
@@ -1711,6 +1715,44 @@ static char *ngx_set_error_page(ngx_conf
 }
 
 
+static char *ngx_set_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    ngx_http_core_loc_conf_t *lcf = conf;
+
+    ngx_str_t  *value;
+
+    if (lcf->keepalive_timeout != NGX_CONF_UNSET_MSEC) {
+        return "is duplicate";
+    }
+
+    value = cf->args->elts;
+
+    lcf->keepalive_timeout = ngx_parse_time(&value[1], 0);
+    if (lcf->keepalive_timeout == (ngx_msec_t) NGX_ERROR) {
+        return "invalid value";
+    }
+
+    if (lcf->keepalive_timeout == (ngx_msec_t) NGX_PARSE_LARGE_TIME) {
+        return "value must be less than 597 hours";
+    }
+
+    if (cf->args->nelts == 2) {
+        return NGX_CONF_OK;
+    }
+
+    lcf->keepalive_header = ngx_parse_time(&value[2], 1);
+    if (lcf->keepalive_header == NGX_ERROR) {
+        return "invalid value";
+    }
+
+    if (lcf->keepalive_header == NGX_PARSE_LARGE_TIME) {
+        return "value must be less than 68 years";
+    }
+
+    return NGX_CONF_OK;
+}
+
+
 static char *ngx_set_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     ngx_http_core_loc_conf_t *lcf = conf;
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -160,6 +160,7 @@ struct ngx_http_core_loc_conf_s {
     ngx_msec_t    client_body_timeout;     /* client_body_timeout */
     ngx_msec_t    send_timeout;            /* send_timeout */
     ngx_msec_t    keepalive_timeout;       /* keepalive_timeout */
+    time_t        keepalive_header;        /* keepalive_timeout */
     ngx_msec_t    lingering_time;          /* lingering_time */
     ngx_msec_t    lingering_timeout;       /* lingering_timeout */
 
--- a/src/http/ngx_http_header_filter.c
+++ b/src/http/ngx_http_header_filter.c
@@ -114,13 +114,14 @@ ngx_http_header_t  ngx_http_headers_out[
 
 static ngx_int_t ngx_http_header_filter(ngx_http_request_t *r)
 {
-    u_char           *p;
-    size_t            len;
-    ngx_uint_t        status, i;
-    ngx_buf_t        *b;
-    ngx_chain_t      *ln;
-    ngx_list_part_t  *part;
-    ngx_table_elt_t  *header;
+    u_char                    *p;
+    size_t                     len;
+    ngx_uint_t                 status, i;
+    ngx_buf_t                 *b;
+    ngx_chain_t               *ln;
+    ngx_list_part_t           *part;
+    ngx_table_elt_t           *header;
+    ngx_http_core_loc_conf_t  *clcf;
 
     if (r->http_version < NGX_HTTP_VERSION_10) {
         return NGX_OK;
@@ -222,8 +223,25 @@ static ngx_int_t ngx_http_header_filter(
         len += sizeof("Transfer-Encoding: chunked" CRLF) - 1;
     }
 
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
     if (r->keepalive) {
         len += sizeof("Connection: keep-alive" CRLF) - 1;
+
+        /*
+         * MSIE and Opera ignore the "Keep-Alive: timeout=<N>" header.
+         * MSIE keeps the connection alive for about 60-65 seconds.
+         * Opera keeps the connection alive very long.
+         * Mozilla keeps the connection alive for N plus about 1-10 seconds.
+         * Konqueror keeps the connection alive for about N seconds.
+         */
+
+        if (clcf->keepalive_header
+            && (r->headers_in.gecko || r->headers_in.konqueror))
+        {
+            len += sizeof("Keep-Alive: timeout=") - 1 + TIME_T_LEN + 2;
+        }
+
     } else {
         len += sizeof("Connection: closed" CRLF) - 1;
     }
@@ -243,11 +261,6 @@ static ngx_int_t ngx_http_header_filter(
             i = 0;
         }
 
-#if 0
-    header = r->headers_out.headers.elts;
-    for (i = 0; i < r->headers_out.headers.nelts; i++) {
-#endif
-
         if (header[i].key.len == 0) {
             continue;
         }
@@ -357,6 +370,15 @@ static ngx_int_t ngx_http_header_filter(
         b->last = ngx_cpymem(b->last, "Connection: keep-alive" CRLF,
                              sizeof("Connection: keep-alive" CRLF) - 1);
 
+        if (clcf->keepalive_header
+            && (r->headers_in.gecko || r->headers_in.konqueror))
+        {
+            b->last += ngx_snprintf((char *) b->last,
+                            sizeof("Keep-Alive: timeout=") + TIME_T_LEN + 2,
+                            "Keep-Alive: timeout=" TIME_T_FMT CRLF,
+                            clcf->keepalive_header);
+        }
+
     } else {
         b->last = ngx_cpymem(b->last, "Connection: close" CRLF,
                              sizeof("Connection: close" CRLF) - 1);
@@ -377,10 +399,6 @@ static ngx_int_t ngx_http_header_filter(
             i = 0;
         }
 
-#if 0
-    for (i = 0; i < r->headers_out.headers.nelts; i++) {
-#endif
-
         if (header[i].key.len == 0) {
             continue;
         }
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1023,7 +1023,7 @@ static ssize_t ngx_http_read_request_hea
 
 static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r)
 {
-    u_char                    *ua;
+    u_char                    *ua, *user_agent;
     size_t                     len;
     ngx_uint_t                 i;
     ngx_http_server_name_t    *name;
@@ -1126,13 +1126,14 @@ static ngx_int_t ngx_http_process_reques
          * in CPU cache
          */
 
-        ua = (u_char *) ngx_strstr(r->headers_in.user_agent->value.data,
-                                   "MSIE");
-        if (ua
-            && ua + 8 < r->headers_in.user_agent->value.data
-                                         + r->headers_in.user_agent->value.len)
-        {
+        user_agent = r->headers_in.user_agent->value.data;
+
+        ua = (u_char *) ngx_strstr(user_agent, "MSIE");
+
+        if (ua && ua + 8 < user_agent + r->headers_in.user_agent->value.len) {
+
             r->headers_in.msie = 1;
+
             if (ua[4] == ' ' && ua[5] == '4' && ua[6] == '.') {
                 r->headers_in.msie4 = 1;
             }
@@ -1144,11 +1145,21 @@ static ngx_int_t ngx_http_process_reques
 #endif
         }
 
-        if (ngx_strstr(r->headers_in.user_agent->value.data, "Opera")) {
+        if (ngx_strstr(user_agent, "Opera")) {
             r->headers_in.opera = 1;
             r->headers_in.msie = 0;
             r->headers_in.msie4 = 0;
         }
+
+        if (!r->headers_in.msie && !r->headers_in.opera) {
+
+            if (ngx_strstr(user_agent, "Gecko")) {
+                r->headers_in.gecko = 1;
+
+            } else if (ngx_strstr(user_agent, "Konqueror")) {
+                r->headers_in.konqueror = 1;
+            }
+        }
     }
 
     return NGX_OK;
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -149,6 +149,8 @@ typedef struct {
     unsigned          msie:1;
     unsigned          msie4:1;
     unsigned          opera:1;
+    unsigned          gecko:1;
+    unsigned          konqueror:1;
 } ngx_http_headers_in_t;
 
 
--- a/src/os/unix/ngx_writev_chain.c
+++ b/src/os/unix/ngx_writev_chain.c
@@ -4,17 +4,20 @@
 #include <ngx_event.h>
 
 
+#define NGX_IOVS  8
+
+
 ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
 {
-    u_char          *prev;
-    ssize_t          n, size;
-    off_t            send, sprev, sent;
-    struct iovec    *iov;
-    ngx_uint_t       eintr, complete;
-    ngx_err_t        err;
-    ngx_array_t      vec;
-    ngx_chain_t     *cl;
-    ngx_event_t     *wev;
+    u_char        *prev;
+    ssize_t        n, size;
+    off_t          send, sprev, sent;
+    ngx_uint_t     eintr, complete;
+    ngx_err_t      err;
+    ngx_array_t    vec;
+    ngx_chain_t   *cl;
+    ngx_event_t   *wev;
+    struct iovec  *iov, iovs[NGX_IOVS];
 
     wev = c->write;
 
@@ -34,17 +37,22 @@ ngx_chain_t *ngx_writev_chain(ngx_connec
 
 #endif
 
-    ngx_init_array(vec, c->pool, 10, sizeof(struct iovec), NGX_CHAIN_ERROR);
-
     send = 0;
     complete = 0;
 
+    vec.elts = iovs;
+    vec.size = sizeof(struct iovec);
+    vec.nalloc = NGX_IOVS;
+    vec.pool = c->pool;
+
     for ( ;; ) {
         prev = NULL;
         iov = NULL;
         eintr = 0;
         sprev = send;
 
+        vec.nelts = 0;
+
         /* create the iovec and coalesce the neighbouring bufs */
 
         for (cl = in; cl && vec.nelts < IOV_MAX && send < limit; cl = cl->next)
@@ -63,7 +71,10 @@ ngx_chain_t *ngx_writev_chain(ngx_connec
                 iov->iov_len += size;
 
             } else {
-                ngx_test_null(iov, ngx_push_array(&vec), NGX_CHAIN_ERROR);
+                if (!(iov = ngx_array_push(&vec))) {
+                    return NGX_CHAIN_ERROR;
+                }
+
                 iov->iov_base = (void *) cl->buf->pos;
                 iov->iov_len = size;
             }