diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c index 975a8e001..f34565277 100644 --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -1185,10 +1185,10 @@ ngx_ssl_handshake_handler(ngx_event_t *ev) ssize_t -ngx_ssl_recv_chain(ngx_connection_t *c, ngx_chain_t *cl) +ngx_ssl_recv_chain(ngx_connection_t *c, ngx_chain_t *cl, off_t limit) { u_char *last; - ssize_t n, bytes; + ssize_t n, bytes, size; ngx_buf_t *b; bytes = 0; @@ -1197,8 +1197,19 @@ ngx_ssl_recv_chain(ngx_connection_t *c, ngx_chain_t *cl) last = b->last; for ( ;; ) { + size = b->end - last; - n = ngx_ssl_recv(c, last, b->end - last); + if (limit) { + if (bytes >= limit) { + return bytes; + } + + if (bytes + size > limit) { + size = (ssize_t) (limit - bytes); + } + } + + n = ngx_ssl_recv(c, last, size); if (n > 0) { last += n; diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h index 408694035..08eff6445 100644 --- a/src/event/ngx_event_openssl.h +++ b/src/event/ngx_event_openssl.h @@ -194,7 +194,7 @@ ngx_int_t ngx_ssl_get_client_verify(ngx_connection_t *c, ngx_pool_t *pool, ngx_int_t ngx_ssl_handshake(ngx_connection_t *c); ssize_t ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size); ssize_t ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size); -ssize_t ngx_ssl_recv_chain(ngx_connection_t *c, ngx_chain_t *cl); +ssize_t ngx_ssl_recv_chain(ngx_connection_t *c, ngx_chain_t *cl, off_t limit); ngx_chain_t *ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit); void ngx_ssl_free_buffer(ngx_connection_t *c); diff --git a/src/event/ngx_event_pipe.c b/src/event/ngx_event_pipe.c index 64fb07bde..21f084417 100644 --- a/src/event/ngx_event_pipe.c +++ b/src/event/ngx_event_pipe.c @@ -270,7 +270,7 @@ ngx_event_pipe_read_upstream(ngx_event_pipe_t *p) break; } - n = p->upstream->recv_chain(p->upstream, chain); + n = p->upstream->recv_chain(p->upstream, chain, 0); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, "pipe recv chain: %z", n); diff --git a/src/os/unix/ngx_aio_read_chain.c b/src/os/unix/ngx_aio_read_chain.c index 8c831b951..d8722b2c1 100644 --- a/src/os/unix/ngx_aio_read_chain.c +++ b/src/os/unix/ngx_aio_read_chain.c @@ -11,7 +11,7 @@ ssize_t -ngx_aio_read_chain(ngx_connection_t *c, ngx_chain_t *cl) +ngx_aio_read_chain(ngx_connection_t *c, ngx_chain_t *cl, off_t limit) { int n; u_char *buf, *prev; diff --git a/src/os/unix/ngx_os.h b/src/os/unix/ngx_os.h index 1033d8825..a1586426c 100644 --- a/src/os/unix/ngx_os.h +++ b/src/os/unix/ngx_os.h @@ -17,7 +17,8 @@ typedef ssize_t (*ngx_recv_pt)(ngx_connection_t *c, u_char *buf, size_t size); -typedef ssize_t (*ngx_recv_chain_pt)(ngx_connection_t *c, ngx_chain_t *in); +typedef ssize_t (*ngx_recv_chain_pt)(ngx_connection_t *c, ngx_chain_t *in, + off_t limit); typedef ssize_t (*ngx_send_pt)(ngx_connection_t *c, u_char *buf, size_t size); typedef ngx_chain_t *(*ngx_send_chain_pt)(ngx_connection_t *c, ngx_chain_t *in, off_t limit); @@ -41,7 +42,7 @@ ngx_int_t ngx_os_signal_process(ngx_cycle_t *cycle, char *sig, ngx_int_t pid); ssize_t ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size); -ssize_t ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *entry); +ssize_t ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *entry, off_t limit); ssize_t ngx_udp_unix_recv(ngx_connection_t *c, u_char *buf, size_t size); ssize_t ngx_unix_send(ngx_connection_t *c, u_char *buf, size_t size); ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, @@ -49,7 +50,7 @@ ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, #if (NGX_HAVE_AIO) ssize_t ngx_aio_read(ngx_connection_t *c, u_char *buf, size_t size); -ssize_t ngx_aio_read_chain(ngx_connection_t *c, ngx_chain_t *cl); +ssize_t ngx_aio_read_chain(ngx_connection_t *c, ngx_chain_t *cl, off_t limit); ssize_t ngx_aio_write(ngx_connection_t *c, u_char *buf, size_t size); ngx_chain_t *ngx_aio_write_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit); diff --git a/src/os/unix/ngx_readv_chain.c b/src/os/unix/ngx_readv_chain.c index 3cba80ccc..3544b4b17 100644 --- a/src/os/unix/ngx_readv_chain.c +++ b/src/os/unix/ngx_readv_chain.c @@ -11,7 +11,7 @@ ssize_t -ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain) +ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit) { u_char *prev; ssize_t n, size; @@ -66,8 +66,20 @@ ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain) /* coalesce the neighbouring bufs */ while (chain) { + n = chain->buf->end - chain->buf->last; + + if (limit) { + if (size >= limit) { + break; + } + + if (size + n > limit) { + n = (ssize_t) (limit - size); + } + } + if (prev == chain->buf->last) { - iov->iov_len += chain->buf->end - chain->buf->last; + iov->iov_len += n; } else { if (vec.nelts >= IOV_MAX) { @@ -80,10 +92,10 @@ ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain) } iov->iov_base = (void *) chain->buf->last; - iov->iov_len = chain->buf->end - chain->buf->last; + iov->iov_len = n; } - size += chain->buf->end - chain->buf->last; + size += n; prev = chain->buf->end; chain = chain->next; } diff --git a/src/os/win32/ngx_os.h b/src/os/win32/ngx_os.h index 6f828fe69..8bce9a289 100644 --- a/src/os/win32/ngx_os.h +++ b/src/os/win32/ngx_os.h @@ -17,7 +17,8 @@ typedef ssize_t (*ngx_recv_pt)(ngx_connection_t *c, u_char *buf, size_t size); -typedef ssize_t (*ngx_recv_chain_pt)(ngx_connection_t *c, ngx_chain_t *in); +typedef ssize_t (*ngx_recv_chain_pt)(ngx_connection_t *c, ngx_chain_t *in, + off_t limit); typedef ssize_t (*ngx_send_pt)(ngx_connection_t *c, u_char *buf, size_t size); typedef ngx_chain_t *(*ngx_send_chain_pt)(ngx_connection_t *c, ngx_chain_t *in, off_t limit); @@ -41,7 +42,7 @@ ssize_t ngx_overlapped_wsarecv(ngx_connection_t *c, u_char *buf, size_t size); ssize_t ngx_udp_wsarecv(ngx_connection_t *c, u_char *buf, size_t size); ssize_t ngx_udp_overlapped_wsarecv(ngx_connection_t *c, u_char *buf, size_t size); -ssize_t ngx_wsarecv_chain(ngx_connection_t *c, ngx_chain_t *chain); +ssize_t ngx_wsarecv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit); ssize_t ngx_wsasend(ngx_connection_t *c, u_char *buf, size_t size); ssize_t ngx_overlapped_wsasend(ngx_connection_t *c, u_char *buf, size_t size); ngx_chain_t *ngx_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in, diff --git a/src/os/win32/ngx_wsarecv_chain.c b/src/os/win32/ngx_wsarecv_chain.c index 7a85d8151..2598e091c 100644 --- a/src/os/win32/ngx_wsarecv_chain.c +++ b/src/os/win32/ngx_wsarecv_chain.c @@ -14,12 +14,12 @@ ssize_t -ngx_wsarecv_chain(ngx_connection_t *c, ngx_chain_t *chain) +ngx_wsarecv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit) { int rc; u_char *prev; u_long bytes, flags; - size_t size; + size_t n, size; ngx_err_t err; ngx_array_t vec; ngx_event_t *rev; @@ -41,8 +41,20 @@ ngx_wsarecv_chain(ngx_connection_t *c, ngx_chain_t *chain) /* coalesce the neighbouring bufs */ while (chain) { + n = chain->buf->end - chain->buf->last; + + if (limit) { + if (size >= (size_t) limit) { + break; + } + + if (size + n > (size_t) limit) { + n = (size_t) limit - size; + } + } + if (prev == chain->buf->last) { - wsabuf->len += chain->buf->end - chain->buf->last; + wsabuf->len += n; } else { wsabuf = ngx_array_push(&vec); @@ -51,10 +63,10 @@ ngx_wsarecv_chain(ngx_connection_t *c, ngx_chain_t *chain) } wsabuf->buf = (char *) chain->buf->last; - wsabuf->len = chain->buf->end - chain->buf->last; + wsabuf->len = n; } - size += chain->buf->end - chain->buf->last; + size += n; prev = chain->buf->end; chain = chain->next; }