nginx-0.0.11-2004-09-17-20:07:35 import
diff --git a/src/core/ngx_palloc.c b/src/core/ngx_palloc.c
index fe469ec..37a0868 100644
--- a/src/core/ngx_palloc.c
+++ b/src/core/ngx_palloc.c
@@ -70,8 +70,9 @@
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);
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index be2e7fc..b345b2a 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -37,6 +37,7 @@
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 @@
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 @@
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 @@
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_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;
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index 3a70f29..8385f48 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -160,6 +160,7 @@
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 */
diff --git a/src/http/ngx_http_header_filter.c b/src/http/ngx_http_header_filter.c
index 5e9a115..74e36ba 100644
--- a/src/http/ngx_http_header_filter.c
+++ b/src/http/ngx_http_header_filter.c
@@ -114,13 +114,14 @@
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 @@
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 @@
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 @@
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 @@
i = 0;
}
-#if 0
- for (i = 0; i < r->headers_out.headers.nelts; i++) {
-#endif
-
if (header[i].key.len == 0) {
continue;
}
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index a930d1d..70f9955 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1023,7 +1023,7 @@
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 @@
* 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 @@
#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;
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index 4a579ce..aafabbe 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -149,6 +149,8 @@
unsigned msie:1;
unsigned msie4:1;
unsigned opera:1;
+ unsigned gecko:1;
+ unsigned konqueror:1;
} ngx_http_headers_in_t;
diff --git a/src/os/unix/ngx_writev_chain.c b/src/os/unix/ngx_writev_chain.c
index aba218d..afe49a9 100644
--- 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 @@
#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 @@
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;
}