Merged with the default branch.

This commit is contained in:
Sergey Kandaurov 2022-12-15 19:40:44 +04:00
commit 68afb2f973
19 changed files with 215 additions and 63 deletions

View File

@ -5,6 +5,61 @@
<change_log title="nginx">
<changes ver="1.23.3" date="2022-12-13">
<change type="bugfix">
<para lang="ru">
при чтении заголовка протокола PROXY версии 2, содержащего
большое количество TLV, могла возникать ошибка.
</para>
<para lang="en">
an error might occur when reading PROXY protocol version 2 header
with large number of TLVs.
</para>
</change>
<change type="bugfix">
<para lang="ru">
при использовании SSI для обработки подзапросов, созданных другими модулями,
в рабочем процессе мог произойти segmentation fault.<br/>
Спасибо Ciel Zhao.
</para>
<para lang="en">
a segmentation fault might occur in a worker process
if SSI was used to process subrequests created by other modules.<br/>
Thanks to Ciel Zhao.
</para>
</change>
<change type="workaround">
<para lang="ru">
теперь, если при преобразовании в адреса имени хоста,
указанного в директиве listen, возвращается несколько адресов,
nginx игнорирует дубликаты среди этих адресов.
</para>
<para lang="en">
when a hostname used in the "listen" directive
resolves to multiple addresses,
nginx now ignores duplicates within these addresses.
</para>
</change>
<change type="bugfix">
<para lang="ru">
nginx мог нагружать процессор
при небуферизированном проксировании,
если использовались SSL-соединения с бэкендами.
</para>
<para lang="en">
nginx might hog CPU
during unbuffered proxying
if SSL connections to backends were used.
</para>
</change>
</changes>
<changes ver="1.23.2" date="2022-10-19">
<change type="security">

View File

@ -6,8 +6,8 @@ TEMP = tmp
CC = cl
OBJS = objs.msvc8
OPENSSL = openssl-1.1.1q
ZLIB = zlib-1.2.12
OPENSSL = openssl-1.1.1s
ZLIB = zlib-1.2.13
PCRE = pcre2-10.39

View File

@ -9,8 +9,8 @@
#define _NGINX_H_INCLUDED_
#define nginx_version 1023002
#define NGINX_VERSION "1.23.2"
#define nginx_version 1023003
#define NGINX_VERSION "1.23.3"
#define NGINX_VER "nginx/" NGINX_VERSION
#ifdef NGX_BUILD

View File

@ -109,7 +109,7 @@ ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
len = last - buf;
if (len >= sizeof(ngx_proxy_protocol_header_t)
&& memcmp(p, signature, sizeof(signature) - 1) == 0)
&& ngx_memcmp(p, signature, sizeof(signature) - 1) == 0)
{
return ngx_proxy_protocol_v2_read(c, buf, last);
}
@ -281,7 +281,9 @@ ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, u_char *last)
{
ngx_uint_t port, lport;
if (last - buf < NGX_PROXY_PROTOCOL_MAX_HEADER) {
if (last - buf < NGX_PROXY_PROTOCOL_V1_MAX_HEADER) {
ngx_log_error(NGX_LOG_ALERT, c->log, 0,
"too small buffer for PROXY protocol");
return NULL;
}
@ -394,11 +396,11 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)
src_sockaddr.sockaddr_in.sin_family = AF_INET;
src_sockaddr.sockaddr_in.sin_port = 0;
memcpy(&src_sockaddr.sockaddr_in.sin_addr, in->src_addr, 4);
ngx_memcpy(&src_sockaddr.sockaddr_in.sin_addr, in->src_addr, 4);
dst_sockaddr.sockaddr_in.sin_family = AF_INET;
dst_sockaddr.sockaddr_in.sin_port = 0;
memcpy(&dst_sockaddr.sockaddr_in.sin_addr, in->dst_addr, 4);
ngx_memcpy(&dst_sockaddr.sockaddr_in.sin_addr, in->dst_addr, 4);
pp->src_port = ngx_proxy_protocol_parse_uint16(in->src_port);
pp->dst_port = ngx_proxy_protocol_parse_uint16(in->dst_port);
@ -421,11 +423,11 @@ ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)
src_sockaddr.sockaddr_in6.sin6_family = AF_INET6;
src_sockaddr.sockaddr_in6.sin6_port = 0;
memcpy(&src_sockaddr.sockaddr_in6.sin6_addr, in6->src_addr, 16);
ngx_memcpy(&src_sockaddr.sockaddr_in6.sin6_addr, in6->src_addr, 16);
dst_sockaddr.sockaddr_in6.sin6_family = AF_INET6;
dst_sockaddr.sockaddr_in6.sin6_port = 0;
memcpy(&dst_sockaddr.sockaddr_in6.sin6_addr, in6->dst_addr, 16);
ngx_memcpy(&dst_sockaddr.sockaddr_in6.sin6_addr, in6->dst_addr, 16);
pp->src_port = ngx_proxy_protocol_parse_uint16(in6->src_port);
pp->dst_port = ngx_proxy_protocol_parse_uint16(in6->dst_port);

View File

@ -13,7 +13,8 @@
#include <ngx_core.h>
#define NGX_PROXY_PROTOCOL_MAX_HEADER 107
#define NGX_PROXY_PROTOCOL_V1_MAX_HEADER 107
#define NGX_PROXY_PROTOCOL_MAX_HEADER 4096
struct ngx_proxy_protocol_s {

View File

@ -140,12 +140,12 @@ ngx_copy(u_char *dst, u_char *src, size_t len)
#endif
#define ngx_memmove(dst, src, n) (void) memmove(dst, src, n)
#define ngx_movemem(dst, src, n) (((u_char *) memmove(dst, src, n)) + (n))
#define ngx_memmove(dst, src, n) (void) memmove(dst, src, n)
#define ngx_movemem(dst, src, n) (((u_char *) memmove(dst, src, n)) + (n))
/* msvc and icc7 compile memcmp() to the inline loop */
#define ngx_memcmp(s1, s2, n) memcmp((const char *) s1, (const char *) s2, n)
#define ngx_memcmp(s1, s2, n) memcmp(s1, s2, n)
u_char *ngx_cpystrn(u_char *dst, u_char *src, size_t n);

View File

@ -434,6 +434,7 @@ ngx_event_init_conf(ngx_cycle_t *cycle, void *conf)
{
#if (NGX_HAVE_REUSEPORT)
ngx_uint_t i;
ngx_core_conf_t *ccf;
ngx_listening_t *ls;
#endif
@ -460,7 +461,9 @@ ngx_event_init_conf(ngx_cycle_t *cycle, void *conf)
#if (NGX_HAVE_REUSEPORT)
if (!ngx_test_config) {
ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
if (!ngx_test_config && ccf->master) {
ls = cycle->listening.elts;
for (i = 0; i < cycle->listening.nelts; i++) {
@ -828,7 +831,9 @@ ngx_event_process_init(ngx_cycle_t *cycle)
rev->deferred_accept = ls[i].deferred_accept;
#endif
if (!(ngx_event_flags & NGX_USE_IOCP_EVENT)) {
if (!(ngx_event_flags & NGX_USE_IOCP_EVENT)
&& cycle->old_cycle)
{
if (ls[i].previous) {
/*

View File

@ -2204,6 +2204,7 @@ ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size)
#endif
if (c->ssl->last == NGX_ERROR) {
c->read->ready = 0;
c->read->error = 1;
return NGX_ERROR;
}
@ -2270,6 +2271,7 @@ ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size)
#if (NGX_HAVE_FIONREAD)
if (ngx_socket_nread(c->fd, &c->read->available) == -1) {
c->read->ready = 0;
c->read->error = 1;
ngx_connection_error(c, ngx_socket_errno,
ngx_socket_nread_n " failed");
@ -2306,6 +2308,7 @@ ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size)
return 0;
case NGX_ERROR:
c->read->ready = 0;
c->read->error = 1;
/* fall through */
@ -2326,6 +2329,7 @@ ngx_ssl_recv_early(ngx_connection_t *c, u_char *buf, size_t size)
size_t readbytes;
if (c->ssl->last == NGX_ERROR) {
c->read->ready = 0;
c->read->error = 1;
return NGX_ERROR;
}
@ -2425,6 +2429,7 @@ ngx_ssl_recv_early(ngx_connection_t *c, u_char *buf, size_t size)
return 0;
case NGX_ERROR:
c->read->ready = 0;
c->read->error = 1;
/* fall through */
@ -3020,7 +3025,7 @@ ngx_ssl_sendfile(ngx_connection_t *c, ngx_buf_t *file, size_t size)
n = SSL_sendfile(c->ssl->connection, file->file->fd, file->file_pos,
size, flags);
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_sendfile: %d", n);
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_sendfile: %z", n);
if (n > 0) {

View File

@ -329,7 +329,7 @@ static ngx_http_variable_t ngx_http_ssi_vars[] = {
static ngx_int_t
ngx_http_ssi_header_filter(ngx_http_request_t *r)
{
ngx_http_ssi_ctx_t *ctx;
ngx_http_ssi_ctx_t *ctx, *mctx;
ngx_http_ssi_loc_conf_t *slcf;
slcf = ngx_http_get_module_loc_conf(r, ngx_http_ssi_filter_module);
@ -341,6 +341,8 @@ ngx_http_ssi_header_filter(ngx_http_request_t *r)
return ngx_http_next_header_filter(r);
}
mctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_ssi_ctx_t));
if (ctx == NULL) {
return NGX_ERROR;
@ -367,6 +369,26 @@ ngx_http_ssi_header_filter(ngx_http_request_t *r)
r->filter_need_in_memory = 1;
if (r == r->main) {
if (mctx) {
/*
* if there was a shared context previously used as main,
* copy variables and blocks
*/
ctx->variables = mctx->variables;
ctx->blocks = mctx->blocks;
#if (NGX_PCRE)
ctx->ncaptures = mctx->ncaptures;
ctx->captures = mctx->captures;
ctx->captures_data = mctx->captures_data;
#endif
mctx->shared = 0;
}
ngx_http_clear_content_length(r);
ngx_http_clear_accept_ranges(r);
@ -379,6 +401,10 @@ ngx_http_ssi_header_filter(ngx_http_request_t *r)
} else {
ngx_http_weak_etag(r);
}
} else if (mctx == NULL) {
ngx_http_set_ctx(r->main, ctx, ngx_http_ssi_filter_module);
ctx->shared = 1;
}
return ngx_http_next_header_filter(r);
@ -405,6 +431,7 @@ ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
ctx = ngx_http_get_module_ctx(r, ngx_http_ssi_filter_module);
if (ctx == NULL
|| (ctx->shared && r == r->main)
|| (in == NULL
&& ctx->buf == NULL
&& ctx->in == NULL

View File

@ -71,6 +71,7 @@ typedef struct {
u_char *captures_data;
#endif
unsigned shared:1;
unsigned conditional:2;
unsigned encoding:2;
unsigned block:1;

View File

@ -3964,7 +3964,7 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_str_t *value, size;
ngx_url_t u;
ngx_uint_t n;
ngx_uint_t n, i;
ngx_http_listen_opt_t lsopt;
cscf->listen = 1;
@ -4310,6 +4310,16 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
#endif
for (n = 0; n < u.naddrs; n++) {
for (i = 0; i < n; i++) {
if (ngx_cmp_sockaddr(u.addrs[n].sockaddr, u.addrs[n].socklen,
u.addrs[i].sockaddr, u.addrs[i].socklen, 0)
== NGX_OK)
{
goto next;
}
}
lsopt.sockaddr = u.addrs[n].sockaddr;
lsopt.socklen = u.addrs[n].socklen;
lsopt.addr_text = u.addrs[n].name;
@ -4318,6 +4328,9 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
if (ngx_http_add_listen(cf, cscf, &lsopt) != NGX_OK) {
return NGX_CONF_ERROR;
}
next:
continue;
}
return NGX_CONF_OK;

View File

@ -308,7 +308,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_str_t *value, size;
ngx_url_t u;
ngx_uint_t i, n, m;
ngx_mail_listen_t *ls, *als;
ngx_mail_listen_t *ls, *als, *nls;
ngx_mail_module_t *module;
ngx_mail_core_main_conf_t *cmcf;
@ -333,7 +333,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
cmcf = ngx_mail_conf_get_module_main_conf(cf, ngx_mail_core_module);
ls = ngx_array_push_n(&cmcf->listen, u.naddrs);
ls = ngx_array_push(&cmcf->listen);
if (ls == NULL) {
return NGX_CONF_ERROR;
}
@ -568,20 +568,40 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
als = cmcf->listen.elts;
for (n = 0; n < u.naddrs; n++) {
ls[n] = ls[0];
ls[n].sockaddr = u.addrs[n].sockaddr;
ls[n].socklen = u.addrs[n].socklen;
ls[n].addr_text = u.addrs[n].name;
ls[n].wildcard = ngx_inet_wildcard(ls[n].sockaddr);
for (i = 0; i < n; i++) {
if (ngx_cmp_sockaddr(u.addrs[n].sockaddr, u.addrs[n].socklen,
u.addrs[i].sockaddr, u.addrs[i].socklen, 0)
== NGX_OK)
{
goto next;
}
}
for (i = 0; i < cmcf->listen.nelts - u.naddrs + n; i++) {
if (n != 0) {
nls = ngx_array_push(&cmcf->listen);
if (nls == NULL) {
return NGX_CONF_ERROR;
}
*nls = *ls;
} else {
nls = ls;
}
nls->sockaddr = u.addrs[n].sockaddr;
nls->socklen = u.addrs[n].socklen;
nls->addr_text = u.addrs[n].name;
nls->wildcard = ngx_inet_wildcard(nls->sockaddr);
als = cmcf->listen.elts;
for (i = 0; i < cmcf->listen.nelts - 1; i++) {
if (ngx_cmp_sockaddr(als[i].sockaddr, als[i].socklen,
ls[n].sockaddr, ls[n].socklen, 1)
nls->sockaddr, nls->socklen, 1)
!= NGX_OK)
{
continue;
@ -589,9 +609,12 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"duplicate \"%V\" address and port pair",
&ls[n].addr_text);
&nls->addr_text);
return NGX_CONF_ERROR;
}
next:
continue;
}
return NGX_CONF_OK;

View File

@ -890,7 +890,7 @@ ngx_mail_proxy_send_proxy_protocol(ngx_mail_session_t *s)
u_char *p;
ssize_t n, size;
ngx_connection_t *c;
u_char buf[NGX_PROXY_PROTOCOL_MAX_HEADER];
u_char buf[NGX_PROXY_PROTOCOL_V1_MAX_HEADER];
s->connection->log->action = "sending PROXY protocol header to upstream";
@ -898,7 +898,7 @@ ngx_mail_proxy_send_proxy_protocol(ngx_mail_session_t *s)
"mail proxy send PROXY protocol header");
p = ngx_proxy_protocol_write(s->connection, buf,
buf + NGX_PROXY_PROTOCOL_MAX_HEADER);
buf + NGX_PROXY_PROTOCOL_V1_MAX_HEADER);
if (p == NULL) {
ngx_mail_proxy_internal_server_error(s);
return NGX_ERROR;

View File

@ -736,6 +736,7 @@ ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
ngx_set_shutdown_timer(cycle);
ngx_close_listening_sockets(cycle);
ngx_close_idle_connections(cycle);
ngx_event_process_posted(cycle, &ngx_posted_events);
}
}
@ -758,7 +759,6 @@ ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker)
ngx_cpuset_t *cpu_affinity;
struct rlimit rlmt;
ngx_core_conf_t *ccf;
ngx_listening_t *ls;
if (ngx_set_environment(cycle, NULL) == NULL) {
/* fatal */
@ -888,15 +888,6 @@ ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker)
tp = ngx_timeofday();
srandom(((unsigned) ngx_pid << 16) ^ tp->sec ^ tp->msec);
/*
* disable deleting previous events for the listening sockets because
* in the worker processes there are no events at all at this point
*/
ls = cycle->listening.elts;
for (i = 0; i < cycle->listening.nelts; i++) {
ls[i].previous = NULL;
}
for (i = 0; cycle->modules[i]; i++) {
if (cycle->modules[i]->init_process) {
if (cycle->modules[i]->init_process(cycle) == NGX_ERROR) {

View File

@ -804,6 +804,7 @@ ngx_worker_thread(void *data)
ngx_set_shutdown_timer(cycle);
ngx_close_listening_sockets(cycle);
ngx_close_idle_connections(cycle);
ngx_event_process_posted(cycle, &ngx_posted_events);
}
}

View File

@ -78,6 +78,7 @@ ngx_wsarecv(ngx_connection_t *c, u_char *buf, size_t size)
ngx_socket_nread_n " failed");
if (n == NGX_ERROR) {
rev->ready = 0;
rev->error = 1;
}
@ -95,6 +96,7 @@ ngx_wsarecv(ngx_connection_t *c, u_char *buf, size_t size)
}
if (bytes == 0) {
rev->ready = 0;
rev->eof = 1;
}

View File

@ -121,6 +121,7 @@ ngx_wsarecv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit)
} else if (bytes == size) {
if (ngx_socket_nread(c->fd, &rev->available) == -1) {
rev->ready = 0;
rev->error = 1;
ngx_connection_error(c, ngx_socket_errno,
ngx_socket_nread_n " failed");
@ -138,6 +139,7 @@ ngx_wsarecv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit)
}
if (bytes == 0) {
rev->ready = 0;
rev->eof = 1;
}

View File

@ -578,7 +578,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_str_t *value, size;
ngx_url_t u;
ngx_uint_t i, n, backlog;
ngx_stream_listen_t *ls, *als;
ngx_stream_listen_t *ls, *als, *nls;
ngx_stream_core_main_conf_t *cmcf;
cscf->listen = 1;
@ -602,7 +602,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
ls = ngx_array_push_n(&cmcf->listen, u.naddrs);
ls = ngx_array_push(&cmcf->listen);
if (ls == NULL) {
return NGX_CONF_ERROR;
}
@ -915,23 +915,43 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
#endif
}
als = cmcf->listen.elts;
for (n = 0; n < u.naddrs; n++) {
ls[n] = ls[0];
ls[n].sockaddr = u.addrs[n].sockaddr;
ls[n].socklen = u.addrs[n].socklen;
ls[n].addr_text = u.addrs[n].name;
ls[n].wildcard = ngx_inet_wildcard(ls[n].sockaddr);
for (i = 0; i < n; i++) {
if (ngx_cmp_sockaddr(u.addrs[n].sockaddr, u.addrs[n].socklen,
u.addrs[i].sockaddr, u.addrs[i].socklen, 0)
== NGX_OK)
{
goto next;
}
}
for (i = 0; i < cmcf->listen.nelts - u.naddrs + n; i++) {
if (ls[n].type != als[i].type) {
if (n != 0) {
nls = ngx_array_push(&cmcf->listen);
if (nls == NULL) {
return NGX_CONF_ERROR;
}
*nls = *ls;
} else {
nls = ls;
}
nls->sockaddr = u.addrs[n].sockaddr;
nls->socklen = u.addrs[n].socklen;
nls->addr_text = u.addrs[n].name;
nls->wildcard = ngx_inet_wildcard(nls->sockaddr);
als = cmcf->listen.elts;
for (i = 0; i < cmcf->listen.nelts - 1; i++) {
if (nls->type != als[i].type) {
continue;
}
if (ngx_cmp_sockaddr(als[i].sockaddr, als[i].socklen,
ls[n].sockaddr, ls[n].socklen, 1)
nls->sockaddr, nls->socklen, 1)
!= NGX_OK)
{
continue;
@ -939,9 +959,12 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"duplicate \"%V\" address and port pair",
&ls[n].addr_text);
&nls->addr_text);
return NGX_CONF_ERROR;
}
next:
continue;
}
return NGX_CONF_OK;

View File

@ -894,7 +894,7 @@ ngx_stream_proxy_init_upstream(ngx_stream_session_t *s)
return;
}
p = ngx_pnalloc(c->pool, NGX_PROXY_PROTOCOL_MAX_HEADER);
p = ngx_pnalloc(c->pool, NGX_PROXY_PROTOCOL_V1_MAX_HEADER);
if (p == NULL) {
ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
return;
@ -902,7 +902,8 @@ ngx_stream_proxy_init_upstream(ngx_stream_session_t *s)
cl->buf->pos = p;
p = ngx_proxy_protocol_write(c, p, p + NGX_PROXY_PROTOCOL_MAX_HEADER);
p = ngx_proxy_protocol_write(c, p,
p + NGX_PROXY_PROTOCOL_V1_MAX_HEADER);
if (p == NULL) {
ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
return;
@ -946,14 +947,15 @@ ngx_stream_proxy_send_proxy_protocol(ngx_stream_session_t *s)
ngx_connection_t *c, *pc;
ngx_stream_upstream_t *u;
ngx_stream_proxy_srv_conf_t *pscf;
u_char buf[NGX_PROXY_PROTOCOL_MAX_HEADER];
u_char buf[NGX_PROXY_PROTOCOL_V1_MAX_HEADER];
c = s->connection;
ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0,
"stream proxy send PROXY protocol header");
p = ngx_proxy_protocol_write(c, buf, buf + NGX_PROXY_PROTOCOL_MAX_HEADER);
p = ngx_proxy_protocol_write(c, buf,
buf + NGX_PROXY_PROTOCOL_V1_MAX_HEADER);
if (p == NULL) {
ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
return NGX_ERROR;
@ -1673,9 +1675,8 @@ ngx_stream_proxy_process(ngx_stream_session_t *s, ngx_uint_t from_upstream,
size = b->end - b->last;
if (size && src->read->ready && !src->read->delayed
&& !src->read->error)
{
if (size && src->read->ready && !src->read->delayed) {
if (limit_rate) {
limit = (off_t) limit_rate * (ngx_time() - u->start_sec + 1)
- *received;