Merge branch 'nginx' (nginx-1.15.7).
Change-Id: Ic090f74a5d7bbf5a44c0151eafd89656f61b9525
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
diff --git a/.hgtags b/.hgtags
index 04a512b..8e059a3 100644
--- a/.hgtags
+++ b/.hgtags
@@ -432,3 +432,4 @@
49d49835653857daa418e68d6cbfed4958c78fca release-1.15.4
f062e43d74fc2578bb100a9e82a953efa1eb9e4e release-1.15.5
2351853ce6867b6166823bdf94333c0a76633c0a release-1.15.6
+051a039ce1c7e09144de4a4846669ec7116cecea release-1.15.7
diff --git a/BUILD b/BUILD
index a08d335..e572e13 100644
--- a/BUILD
+++ b/BUILD
@@ -1535,5 +1535,5 @@
preinst = "@nginx_pkgoss//:debian_preinst",
prerm = "@nginx_pkgoss//:debian_prerm",
section = "httpd",
- version = "1.15.6",
+ version = "1.15.7",
)
diff --git a/build.bzl b/build.bzl
index 78409de..bcf3238 100644
--- a/build.bzl
+++ b/build.bzl
@@ -663,7 +663,7 @@
name = "nginx_pkgoss",
build_file_content = _PKGOSS_BUILD_FILE.format(nginx = nginx) +
_PKGOSS_BUILD_FILE_TAIL,
- commit = "8cd9073e08734f32b52157e2495ad8804dbf8d51", # nginx-1.15.6
+ commit = "a0a043cd5bc6ce17124507e4a6241be72c7eaeaa", # nginx-1.15.7
remote = "https://nginx.googlesource.com/nginx-pkgoss",
)
diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml
index 43a21e5..0738e6f 100644
--- a/docs/xml/nginx/changes.xml
+++ b/docs/xml/nginx/changes.xml
@@ -5,6 +5,62 @@
<change_log title="nginx">
+<changes ver="1.15.7" date="2018-11-27">
+
+<change type="feature">
+<para lang="ru">
+директива proxy_requests в модуле stream.
+</para>
+<para lang="en">
+the "proxy_requests" directive in the stream module.
+</para>
+</change>
+
+<change type="feature">
+<para lang="ru">
+параметр "delay" директивы "limit_req".<br/>
+Спасибо Владиславу Шабанову и Петру Щучкину.
+</para>
+<para lang="en">
+the "delay" parameter of the "limit_req" directive.<br/>
+Thanks to Vladislav Shabanov and Peter Shchuchkin.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+утечки памяти в случае ошибок при переконфигурации.
+</para>
+<para lang="en">
+memory leak on errors during reconfiguration.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+в переменных $upstream_response_time, $upstream_connect_time и
+$upstream_header_time.
+</para>
+<para lang="en">
+in the $upstream_response_time, $upstream_connect_time, and
+$upstream_header_time variables.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+в рабочем процессе мог произойти segmentation fault,
+если использовался модуль ngx_http_mp4_module на 32-битных платформах.
+</para>
+<para lang="en">
+a segmentation fault might occur in a worker process
+if the ngx_http_mp4_module was used on 32-bit platforms.
+</para>
+</change>
+
+</changes>
+
+
<changes ver="1.15.6" date="2018-11-06">
<change type="security">
diff --git a/misc/GNUmakefile b/misc/GNUmakefile
index 73d8bd9..d68ceca 100644
--- a/misc/GNUmakefile
+++ b/misc/GNUmakefile
@@ -6,7 +6,7 @@
CC = cl
OBJS = objs.msvc8
-OPENSSL = openssl-1.0.2p
+OPENSSL = openssl-1.0.2q
ZLIB = zlib-1.2.11
PCRE = pcre-8.42
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 2ddd19d..14dc7c9 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -13,8 +13,8 @@
#define NGINX_NAME "nginx"
#endif
-#define nginx_version 1015006
-#define NGINX_VERSION "1.15.6"
+#define nginx_version 1015007
+#define NGINX_VERSION "1.15.7"
#define NGINX_VER NGINX_NAME "/" NGINX_VERSION
#ifdef NGX_BUILD
diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c
index 083c764..95f4bdf 100644
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -843,6 +843,69 @@
}
}
+ /* free the newly created shared memory */
+
+ part = &cycle->shared_memory.part;
+ shm_zone = part->elts;
+
+ for (i = 0; /* void */ ; i++) {
+
+ if (i >= part->nelts) {
+ if (part->next == NULL) {
+ break;
+ }
+ part = part->next;
+ shm_zone = part->elts;
+ i = 0;
+ }
+
+ if (shm_zone[i].shm.addr == NULL) {
+ continue;
+ }
+
+ opart = &old_cycle->shared_memory.part;
+ oshm_zone = opart->elts;
+
+ for (n = 0; /* void */ ; n++) {
+
+ if (n >= opart->nelts) {
+ if (opart->next == NULL) {
+ break;
+ }
+ opart = opart->next;
+ oshm_zone = opart->elts;
+ n = 0;
+ }
+
+ if (shm_zone[i].shm.name.len != oshm_zone[n].shm.name.len) {
+ continue;
+ }
+
+ if (ngx_strncmp(shm_zone[i].shm.name.data,
+ oshm_zone[n].shm.name.data,
+ shm_zone[i].shm.name.len)
+ != 0)
+ {
+ continue;
+ }
+
+ if (shm_zone[i].tag == oshm_zone[n].tag
+ && shm_zone[i].shm.size == oshm_zone[n].shm.size
+ && !shm_zone[i].noreuse)
+ {
+ goto old_shm_zone_found;
+ }
+
+ break;
+ }
+
+ ngx_shm_free(&shm_zone[i].shm);
+
+ old_shm_zone_found:
+
+ continue;
+ }
+
if (ngx_test_config) {
ngx_destroy_cycle_pools(&conf);
return NULL;
@@ -1274,6 +1337,7 @@
shm_zone->data = NULL;
shm_zone->shm.log = cf->cycle->log;
+ shm_zone->shm.addr = NULL;
shm_zone->shm.size = size;
shm_zone->shm.name = *name;
shm_zone->shm.exists = 0;
diff --git a/src/core/ngx_output_chain.c b/src/core/ngx_output_chain.c
index 7f5dc78..5c3dbe8 100644
--- a/src/core/ngx_output_chain.c
+++ b/src/core/ngx_output_chain.c
@@ -126,6 +126,26 @@
continue;
}
+ if (bsize < 0) {
+
+ ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0,
+ "negative size buf in output "
+ "t:%d r:%d f:%d %p %p-%p %p %O-%O",
+ ctx->in->buf->temporary,
+ ctx->in->buf->recycled,
+ ctx->in->buf->in_file,
+ ctx->in->buf->start,
+ ctx->in->buf->pos,
+ ctx->in->buf->last,
+ ctx->in->buf->file,
+ ctx->in->buf->file_pos,
+ ctx->in->buf->file_last);
+
+ ngx_debug_point();
+
+ return NGX_ERROR;
+ }
+
if (ngx_output_chain_as_is(ctx, ctx->in->buf)) {
/* move the chain link to the output chain */
@@ -665,7 +685,6 @@
for (size = 0; in; in = in->next) {
-#if 1
if (ngx_buf_size(in->buf) == 0 && !ngx_buf_special(in->buf)) {
ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0,
@@ -685,7 +704,26 @@
continue;
}
-#endif
+
+ if (ngx_buf_size(in->buf) < 0) {
+
+ ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0,
+ "negative size buf in chain writer "
+ "t:%d r:%d f:%d %p %p-%p %p %O-%O",
+ in->buf->temporary,
+ in->buf->recycled,
+ in->buf->in_file,
+ in->buf->start,
+ in->buf->pos,
+ in->buf->last,
+ in->buf->file,
+ in->buf->file_pos,
+ in->buf->file_last);
+
+ ngx_debug_point();
+
+ return NGX_ERROR;
+ }
size += ngx_buf_size(in->buf);
@@ -709,7 +747,6 @@
for (cl = ctx->out; cl; cl = cl->next) {
-#if 1
if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0,
@@ -729,7 +766,26 @@
continue;
}
-#endif
+
+ if (ngx_buf_size(cl->buf) < 0) {
+
+ ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0,
+ "negative size buf in chain writer "
+ "t:%d r:%d f:%d %p %p-%p %p %O-%O",
+ cl->buf->temporary,
+ cl->buf->recycled,
+ cl->buf->in_file,
+ cl->buf->start,
+ cl->buf->pos,
+ cl->buf->last,
+ cl->buf->file,
+ cl->buf->file_pos,
+ cl->buf->file_last);
+
+ ngx_debug_point();
+
+ return NGX_ERROR;
+ }
size += ngx_buf_size(cl->buf);
}
diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c
index 2ee07bf..04980f8 100644
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -2013,6 +2013,14 @@
}
+void
+ngx_explicit_memzero(void *buf, size_t n)
+{
+ ngx_memzero(buf, n);
+ ngx_memory_barrier();
+}
+
+
#if (NGX_MEMCPY_LIMIT)
void *
diff --git a/src/core/ngx_string.h b/src/core/ngx_string.h
index 882ae7c..0fb9be7 100644
--- a/src/core/ngx_string.h
+++ b/src/core/ngx_string.h
@@ -88,6 +88,8 @@
#define ngx_memzero(buf, n) (void) memset(buf, 0, n)
#define ngx_memset(buf, c, n) (void) memset(buf, c, n)
+void ngx_explicit_memzero(void *buf, size_t n);
+
#if (NGX_MEMCPY_LIMIT)
diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h
index 0c03b56..f6eaf8c 100644
--- a/src/event/ngx_event.h
+++ b/src/event/ngx_event.h
@@ -514,6 +514,7 @@
void ngx_udp_rbtree_insert_value(ngx_rbtree_node_t *temp,
ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
#endif
+void ngx_delete_udp_connection(void *data);
ngx_int_t ngx_trylock_accept_mutex(ngx_cycle_t *cycle);
ngx_int_t ngx_enable_accept_events(ngx_cycle_t *cycle);
u_char *ngx_accept_log_error(ngx_log_t *log, u_char *buf, size_t len);
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
index 88571a9..d31f3b7 100644
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -1074,7 +1074,7 @@
ngx_close_file_n " \"%s\" failed", file->data);
}
- ngx_memzero(buf, NGX_SSL_PASSWORD_BUFFER_SIZE);
+ ngx_explicit_memzero(buf, NGX_SSL_PASSWORD_BUFFER_SIZE);
return passwords;
}
@@ -1091,7 +1091,7 @@
pwd = passwords->elts;
for (i = 0; i < passwords->nelts; i++) {
- ngx_memzero(pwd[i].data, pwd[i].len);
+ ngx_explicit_memzero(pwd[i].data, pwd[i].len);
}
}
diff --git a/src/event/ngx_event_udp.c b/src/event/ngx_event_udp.c
index 8b0ae55..65eb22f 100644
--- a/src/event/ngx_event_udp.c
+++ b/src/event/ngx_event_udp.c
@@ -23,7 +23,6 @@
static ssize_t ngx_udp_shared_recv(ngx_connection_t *c, u_char *buf,
size_t size);
static ngx_int_t ngx_insert_udp_connection(ngx_connection_t *c);
-static void ngx_delete_udp_connection(void *data);
static ngx_connection_t *ngx_lookup_udp_connection(ngx_listening_t *ls,
struct sockaddr *sockaddr, socklen_t socklen,
struct sockaddr *local_sockaddr, socklen_t local_socklen);
@@ -261,7 +260,10 @@
rev->handler(rev);
- c->udp->buffer = NULL;
+ if (c->udp) {
+ c->udp->buffer = NULL;
+ }
+
rev->ready = 0;
goto next;
@@ -555,12 +557,18 @@
}
-static void
+void
ngx_delete_udp_connection(void *data)
{
ngx_connection_t *c = data;
+ if (c->udp == NULL) {
+ return;
+ }
+
ngx_rbtree_delete(&c->listening->rbtree, &c->udp->node);
+
+ c->udp = NULL;
}
@@ -638,4 +646,12 @@
return NULL;
}
+#else
+
+void
+ngx_delete_udp_connection(void *data)
+{
+ return;
+}
+
#endif
diff --git a/src/http/modules/ngx_http_limit_req_module.c b/src/http/modules/ngx_http_limit_req_module.c
index 63ec2de..e81d57f 100644
--- a/src/http/modules/ngx_http_limit_req_module.c
+++ b/src/http/modules/ngx_http_limit_req_module.c
@@ -44,7 +44,7 @@
ngx_shm_zone_t *shm_zone;
/* integer value, 1 corresponds to 0.001 r/s */
ngx_uint_t burst;
- ngx_uint_t nodelay; /* unsigned nodelay:1 */
+ ngx_uint_t delay;
} ngx_http_limit_req_limit_t;
@@ -499,12 +499,12 @@
excess = *ep;
- if (excess == 0 || (*limit)->nodelay) {
+ if ((ngx_uint_t) excess <= (*limit)->delay) {
max_delay = 0;
} else {
ctx = (*limit)->shm_zone->data;
- max_delay = excess * 1000 / ctx->rate;
+ max_delay = (excess - (*limit)->delay) * 1000 / ctx->rate;
}
while (n--) {
@@ -544,11 +544,11 @@
ctx->node = NULL;
- if (limits[n].nodelay) {
+ if ((ngx_uint_t) excess <= limits[n].delay) {
continue;
}
- delay = excess * 1000 / ctx->rate;
+ delay = (excess - limits[n].delay) * 1000 / ctx->rate;
if (delay > max_delay) {
max_delay = delay;
@@ -875,9 +875,9 @@
{
ngx_http_limit_req_conf_t *lrcf = conf;
- ngx_int_t burst;
+ ngx_int_t burst, delay;
ngx_str_t *value, s;
- ngx_uint_t i, nodelay;
+ ngx_uint_t i;
ngx_shm_zone_t *shm_zone;
ngx_http_limit_req_limit_t *limit, *limits;
@@ -885,7 +885,7 @@
shm_zone = NULL;
burst = 0;
- nodelay = 0;
+ delay = 0;
for (i = 1; i < cf->args->nelts; i++) {
@@ -908,7 +908,19 @@
burst = ngx_atoi(value[i].data + 6, value[i].len - 6);
if (burst <= 0) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid burst rate \"%V\"", &value[i]);
+ "invalid burst value \"%V\"", &value[i]);
+ return NGX_CONF_ERROR;
+ }
+
+ continue;
+ }
+
+ if (ngx_strncmp(value[i].data, "delay=", 6) == 0) {
+
+ delay = ngx_atoi(value[i].data + 6, value[i].len - 6);
+ if (delay <= 0) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid delay value \"%V\"", &value[i]);
return NGX_CONF_ERROR;
}
@@ -916,7 +928,7 @@
}
if (ngx_strcmp(value[i].data, "nodelay") == 0) {
- nodelay = 1;
+ delay = NGX_MAX_INT_T_VALUE / 1000;
continue;
}
@@ -956,7 +968,7 @@
limit->shm_zone = shm_zone;
limit->burst = burst * 1000;
- limit->nodelay = nodelay;
+ limit->delay = delay * 1000;
return NGX_CONF_OK;
}
diff --git a/src/http/modules/ngx_http_mp4_module.c b/src/http/modules/ngx_http_mp4_module.c
index 2a6fafa..618bf78 100644
--- a/src/http/modules/ngx_http_mp4_module.c
+++ b/src/http/modules/ngx_http_mp4_module.c
@@ -169,7 +169,14 @@
#define ngx_mp4_atom_next(mp4, n) \
- mp4->buffer_pos += (size_t) n; \
+ \
+ if (n > (size_t) (mp4->buffer_end - mp4->buffer_pos)) { \
+ mp4->buffer_pos = mp4->buffer_end; \
+ \
+ } else { \
+ mp4->buffer_pos += (size_t) n; \
+ } \
+ \
mp4->offset += n
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 1127b71..fdfd3c6 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -1509,8 +1509,8 @@
r->connection->log->action = "connecting to upstream";
- if (u->state && u->state->response_time) {
- u->state->response_time = ngx_current_msec - u->state->response_time;
+ if (u->state && u->state->response_time == (ngx_msec_t) -1) {
+ u->state->response_time = ngx_current_msec - u->start_time;
}
u->state = ngx_array_push(r->upstream_states);
@@ -1522,7 +1522,9 @@
ngx_memzero(u->state, sizeof(ngx_http_upstream_state_t));
- u->state->response_time = ngx_current_msec;
+ u->start_time = ngx_current_msec;
+
+ u->state->response_time = (ngx_msec_t) -1;
u->state->connect_time = (ngx_msec_t) -1;
u->state->header_time = (ngx_msec_t) -1;
@@ -2006,7 +2008,7 @@
"http upstream send request");
if (u->state->connect_time == (ngx_msec_t) -1) {
- u->state->connect_time = ngx_current_msec - u->state->response_time;
+ u->state->connect_time = ngx_current_msec - u->start_time;
}
if (!u->request_sent && ngx_http_upstream_test_connect(c) != NGX_OK) {
@@ -2421,7 +2423,7 @@
/* rc == NGX_OK */
- u->state->header_time = ngx_current_msec - u->state->response_time;
+ u->state->header_time = ngx_current_msec - u->start_time;
if (u->headers_in.status_n >= NGX_HTTP_SPECIAL_RESPONSE) {
@@ -4321,8 +4323,8 @@
u->resolved->ctx = NULL;
}
- if (u->state && u->state->response_time) {
- u->state->response_time = ngx_current_msec - u->state->response_time;
+ if (u->state && u->state->response_time == (ngx_msec_t) -1) {
+ u->state->response_time = ngx_current_msec - u->start_time;
if (u->pipe && u->pipe->read_length) {
u->state->bytes_received += u->pipe->read_length
@@ -5435,18 +5437,18 @@
state = r->upstream_states->elts;
for ( ;; ) {
- if (state[i].status) {
- if (data == 1 && state[i].header_time != (ngx_msec_t) -1) {
- ms = state[i].header_time;
+ if (data == 1) {
+ ms = state[i].header_time;
- } else if (data == 2 && state[i].connect_time != (ngx_msec_t) -1) {
- ms = state[i].connect_time;
+ } else if (data == 2) {
+ ms = state[i].connect_time;
- } else {
- ms = state[i].response_time;
- }
+ } else {
+ ms = state[i].response_time;
+ }
+ if (ms != -1) {
ms = ngx_max(ms, 0);
p = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000);
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
index 26a0cc5..6a3b302 100644
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -367,7 +367,7 @@
ngx_int_t (*rewrite_cookie)(ngx_http_request_t *r,
ngx_table_elt_t *h);
- ngx_msec_t timeout;
+ ngx_msec_t start_time;
ngx_http_upstream_state_t *state;
diff --git a/src/http/ngx_http_write_filter_module.c b/src/http/ngx_http_write_filter_module.c
index 0036231..3f18d76 100644
--- a/src/http/ngx_http_write_filter_module.c
+++ b/src/http/ngx_http_write_filter_module.c
@@ -80,7 +80,6 @@
cl->buf->file_pos,
cl->buf->file_last - cl->buf->file_pos);
-#if 1
if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
ngx_log_error(NGX_LOG_ALERT, c->log, 0,
"zero size buf in writer "
@@ -98,7 +97,24 @@
ngx_debug_point();
return NGX_ERROR;
}
-#endif
+
+ if (ngx_buf_size(cl->buf) < 0) {
+ ngx_log_error(NGX_LOG_ALERT, c->log, 0,
+ "negative size buf in writer "
+ "t:%d r:%d f:%d %p %p-%p %p %O-%O",
+ cl->buf->temporary,
+ cl->buf->recycled,
+ cl->buf->in_file,
+ cl->buf->start,
+ cl->buf->pos,
+ cl->buf->last,
+ cl->buf->file,
+ cl->buf->file_pos,
+ cl->buf->file_last);
+
+ ngx_debug_point();
+ return NGX_ERROR;
+ }
size += ngx_buf_size(cl->buf);
@@ -136,7 +152,6 @@
cl->buf->file_pos,
cl->buf->file_last - cl->buf->file_pos);
-#if 1
if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
ngx_log_error(NGX_LOG_ALERT, c->log, 0,
"zero size buf in writer "
@@ -154,7 +169,24 @@
ngx_debug_point();
return NGX_ERROR;
}
-#endif
+
+ if (ngx_buf_size(cl->buf) < 0) {
+ ngx_log_error(NGX_LOG_ALERT, c->log, 0,
+ "negative size buf in writer "
+ "t:%d r:%d f:%d %p %p-%p %p %O-%O",
+ cl->buf->temporary,
+ cl->buf->recycled,
+ cl->buf->in_file,
+ cl->buf->start,
+ cl->buf->pos,
+ cl->buf->last,
+ cl->buf->file,
+ cl->buf->file_pos,
+ cl->buf->file_last);
+
+ ngx_debug_point();
+ return NGX_ERROR;
+ }
size += ngx_buf_size(cl->buf);
diff --git a/src/stream/ngx_stream_proxy_module.c b/src/stream/ngx_stream_proxy_module.c
index c8465a7..0949313 100644
--- a/src/stream/ngx_stream_proxy_module.c
+++ b/src/stream/ngx_stream_proxy_module.c
@@ -26,6 +26,7 @@
size_t buffer_size;
size_t upload_rate;
size_t download_rate;
+ ngx_uint_t requests;
ngx_uint_t responses;
ngx_uint_t next_upstream_tries;
ngx_flag_t next_upstream;
@@ -73,6 +74,8 @@
static ngx_int_t ngx_stream_proxy_test_connect(ngx_connection_t *c);
static void ngx_stream_proxy_process(ngx_stream_session_t *s,
ngx_uint_t from_upstream, ngx_uint_t do_write);
+static ngx_int_t ngx_stream_proxy_test_finalize(ngx_stream_session_t *s,
+ ngx_uint_t from_upstream);
static void ngx_stream_proxy_next_upstream(ngx_stream_session_t *s);
static void ngx_stream_proxy_finalize(ngx_stream_session_t *s, ngx_uint_t rc);
static u_char *ngx_stream_proxy_log_error(ngx_log_t *log, u_char *buf,
@@ -193,6 +196,13 @@
offsetof(ngx_stream_proxy_srv_conf_t, download_rate),
NULL },
+ { ngx_string("proxy_requests"),
+ NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_num_slot,
+ NGX_STREAM_SRV_CONF_OFFSET,
+ offsetof(ngx_stream_proxy_srv_conf_t, requests),
+ NULL },
+
{ ngx_string("proxy_responses"),
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
@@ -680,7 +690,7 @@
u->proxy_protocol = pscf->proxy_protocol;
if (u->state) {
- u->state->response_time = ngx_current_msec - u->state->response_time;
+ u->state->response_time = ngx_current_msec - u->start_time;
}
u->state = ngx_array_push(s->upstream_states);
@@ -691,9 +701,11 @@
ngx_memzero(u->state, sizeof(ngx_stream_upstream_state_t));
+ u->start_time = ngx_current_msec;
+
u->state->connect_time = (ngx_msec_t) -1;
u->state->first_byte_time = (ngx_msec_t) -1;
- u->state->response_time = ngx_current_msec;
+ u->state->response_time = (ngx_msec_t) -1;
rc = ngx_event_connect_peer(&u->peer);
@@ -807,7 +819,7 @@
}
}
- u->state->connect_time = ngx_current_msec - u->state->response_time;
+ u->state->connect_time = ngx_current_msec - u->start_time;
if (u->peer.notify) {
u->peer.notify(&u->peer, u->peer.data,
@@ -1339,11 +1351,14 @@
} else {
if (s->connection->type == SOCK_DGRAM) {
- if (pscf->responses == NGX_MAX_INT32_VALUE) {
+
+ if (pscf->responses == NGX_MAX_INT32_VALUE
+ || (u->responses >= pscf->responses * u->requests))
+ {
/*
* successfully terminate timed out UDP session
- * with unspecified number of responses
+ * if expected number of responses was received
*/
handler = c->log->handler;
@@ -1609,7 +1624,7 @@
if (from_upstream) {
if (u->state->first_byte_time == (ngx_msec_t) -1) {
u->state->first_byte_time = ngx_current_msec
- - u->state->response_time;
+ - u->start_time;
}
}
@@ -1646,44 +1661,7 @@
c->log->action = "proxying connection";
- if (c->type == SOCK_DGRAM
- && pscf->responses != NGX_MAX_INT32_VALUE
- && u->responses >= pscf->responses * u->requests
- && !src->buffered && dst && !dst->buffered)
- {
- handler = c->log->handler;
- c->log->handler = NULL;
-
- ngx_log_error(NGX_LOG_INFO, c->log, 0,
- "udp done"
- ", packets from/to client:%ui/%ui"
- ", bytes from/to client:%O/%O"
- ", bytes from/to upstream:%O/%O",
- u->requests, u->responses,
- s->received, c->sent, u->received, pc ? pc->sent : 0);
-
- c->log->handler = handler;
-
- ngx_stream_proxy_finalize(s, NGX_STREAM_OK);
- return;
- }
-
- if (c->type == SOCK_STREAM
- && src->read->eof && dst && (dst->read->eof || !dst->buffered))
- {
- handler = c->log->handler;
- c->log->handler = NULL;
-
- ngx_log_error(NGX_LOG_INFO, c->log, 0,
- "%s disconnected"
- ", bytes from/to client:%O/%O"
- ", bytes from/to upstream:%O/%O",
- from_upstream ? "upstream" : "client",
- s->received, c->sent, u->received, pc ? pc->sent : 0);
-
- c->log->handler = handler;
-
- ngx_stream_proxy_finalize(s, NGX_STREAM_OK);
+ if (ngx_stream_proxy_test_finalize(s, from_upstream) == NGX_OK) {
return;
}
@@ -1710,6 +1688,87 @@
}
+static ngx_int_t
+ngx_stream_proxy_test_finalize(ngx_stream_session_t *s,
+ ngx_uint_t from_upstream)
+{
+ ngx_connection_t *c, *pc;
+ ngx_log_handler_pt handler;
+ ngx_stream_upstream_t *u;
+ ngx_stream_proxy_srv_conf_t *pscf;
+
+ pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
+
+ c = s->connection;
+ u = s->upstream;
+ pc = u->connected ? u->peer.connection : NULL;
+
+ if (c->type == SOCK_DGRAM) {
+
+ if (pscf->requests && u->requests < pscf->requests) {
+ return NGX_DECLINED;
+ }
+
+ if (pscf->requests) {
+ ngx_delete_udp_connection(c);
+ }
+
+ if (pscf->responses == NGX_MAX_INT32_VALUE
+ || u->responses < pscf->responses * u->requests)
+ {
+ return NGX_DECLINED;
+ }
+
+ if (pc == NULL || c->buffered || pc->buffered) {
+ return NGX_DECLINED;
+ }
+
+ handler = c->log->handler;
+ c->log->handler = NULL;
+
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,
+ "udp done"
+ ", packets from/to client:%ui/%ui"
+ ", bytes from/to client:%O/%O"
+ ", bytes from/to upstream:%O/%O",
+ u->requests, u->responses,
+ s->received, c->sent, u->received, pc ? pc->sent : 0);
+
+ c->log->handler = handler;
+
+ ngx_stream_proxy_finalize(s, NGX_STREAM_OK);
+
+ return NGX_OK;
+ }
+
+ /* c->type == SOCK_STREAM */
+
+ if (pc == NULL
+ || (!c->read->eof && !pc->read->eof)
+ || (!c->read->eof && c->buffered)
+ || (!pc->read->eof && pc->buffered))
+ {
+ return NGX_DECLINED;
+ }
+
+ handler = c->log->handler;
+ c->log->handler = NULL;
+
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,
+ "%s disconnected"
+ ", bytes from/to client:%O/%O"
+ ", bytes from/to upstream:%O/%O",
+ from_upstream ? "upstream" : "client",
+ s->received, c->sent, u->received, pc ? pc->sent : 0);
+
+ c->log->handler = handler;
+
+ ngx_stream_proxy_finalize(s, NGX_STREAM_OK);
+
+ return NGX_OK;
+}
+
+
static void
ngx_stream_proxy_next_upstream(ngx_stream_session_t *s)
{
@@ -1800,7 +1859,9 @@
pc = u->peer.connection;
if (u->state) {
- u->state->response_time = ngx_current_msec - u->state->response_time;
+ if (u->state->response_time == (ngx_msec_t) -1) {
+ u->state->response_time = ngx_current_msec - u->start_time;
+ }
if (pc) {
u->state->bytes_received = u->received;
@@ -1905,6 +1966,7 @@
conf->buffer_size = NGX_CONF_UNSET_SIZE;
conf->upload_rate = NGX_CONF_UNSET_SIZE;
conf->download_rate = NGX_CONF_UNSET_SIZE;
+ conf->requests = NGX_CONF_UNSET_UINT;
conf->responses = NGX_CONF_UNSET_UINT;
conf->next_upstream_tries = NGX_CONF_UNSET_UINT;
conf->next_upstream = NGX_CONF_UNSET;
@@ -1949,6 +2011,9 @@
ngx_conf_merge_size_value(conf->download_rate,
prev->download_rate, 0);
+ ngx_conf_merge_uint_value(conf->requests,
+ prev->requests, 0);
+
ngx_conf_merge_uint_value(conf->responses,
prev->responses, NGX_MAX_INT32_VALUE);
diff --git a/src/stream/ngx_stream_upstream.c b/src/stream/ngx_stream_upstream.c
index 7feac43..eadcf9f 100644
--- a/src/stream/ngx_stream_upstream.c
+++ b/src/stream/ngx_stream_upstream.c
@@ -267,24 +267,22 @@
for ( ;; ) {
if (data == 1) {
- if (state[i].first_byte_time == (ngx_msec_t) -1) {
- *p++ = '-';
- goto next;
- }
-
ms = state[i].first_byte_time;
- } else if (data == 2 && state[i].connect_time != (ngx_msec_t) -1) {
+ } else if (data == 2) {
ms = state[i].connect_time;
} else {
ms = state[i].response_time;
}
- ms = ngx_max(ms, 0);
- p = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000);
+ if (ms != -1) {
+ ms = ngx_max(ms, 0);
+ p = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000);
- next:
+ } else {
+ *p++ = '-';
+ }
if (++i == s->upstream_states->nelts) {
break;
diff --git a/src/stream/ngx_stream_upstream.h b/src/stream/ngx_stream_upstream.h
index 8931522..bf893f8 100644
--- a/src/stream/ngx_stream_upstream.h
+++ b/src/stream/ngx_stream_upstream.h
@@ -130,6 +130,7 @@
time_t start_sec;
ngx_uint_t requests;
ngx_uint_t responses;
+ ngx_msec_t start_time;
ngx_str_t ssl_name;
diff --git a/src/stream/ngx_stream_write_filter_module.c b/src/stream/ngx_stream_write_filter_module.c
index 8fdcd37..24326c6 100644
--- a/src/stream/ngx_stream_write_filter_module.c
+++ b/src/stream/ngx_stream_write_filter_module.c
@@ -104,7 +104,6 @@
cl->buf->file_pos,
cl->buf->file_last - cl->buf->file_pos);
-#if 1
if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
ngx_log_error(NGX_LOG_ALERT, c->log, 0,
"zero size buf in writer "
@@ -122,7 +121,24 @@
ngx_debug_point();
return NGX_ERROR;
}
-#endif
+
+ if (ngx_buf_size(cl->buf) < 0) {
+ ngx_log_error(NGX_LOG_ALERT, c->log, 0,
+ "negative size buf in writer "
+ "t:%d r:%d f:%d %p %p-%p %p %O-%O",
+ cl->buf->temporary,
+ cl->buf->recycled,
+ cl->buf->in_file,
+ cl->buf->start,
+ cl->buf->pos,
+ cl->buf->last,
+ cl->buf->file,
+ cl->buf->file_pos,
+ cl->buf->file_last);
+
+ ngx_debug_point();
+ return NGX_ERROR;
+ }
size += ngx_buf_size(cl->buf);
@@ -160,7 +176,6 @@
cl->buf->file_pos,
cl->buf->file_last - cl->buf->file_pos);
-#if 1
if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
ngx_log_error(NGX_LOG_ALERT, c->log, 0,
"zero size buf in writer "
@@ -178,7 +193,24 @@
ngx_debug_point();
return NGX_ERROR;
}
-#endif
+
+ if (ngx_buf_size(cl->buf) < 0) {
+ ngx_log_error(NGX_LOG_ALERT, c->log, 0,
+ "negative size buf in writer "
+ "t:%d r:%d f:%d %p %p-%p %p %O-%O",
+ cl->buf->temporary,
+ cl->buf->recycled,
+ cl->buf->in_file,
+ cl->buf->start,
+ cl->buf->pos,
+ cl->buf->last,
+ cl->buf->file,
+ cl->buf->file_pos,
+ cl->buf->file_last);
+
+ ngx_debug_point();
+ return NGX_ERROR;
+ }
size += ngx_buf_size(cl->buf);