Mercurial > hg > nginx-quic
view src/os/win32/ngx_wsarecv_chain.c @ 6956:9b5f31fdb850
HTTP/2: fixed stream finalization.
In order to finalize stream the error flag is set on fake connection and
either "write" or "read" event handler is called. The read events of fake
connections are always ready, but it's not the case with the write events.
When the ready flag isn't set, the error flag can be not checked in some
cases and as a result stream isn't finalized. Now the ready flag is
explicilty set on write events for proper finalization in all cases.
author | Valentin Bartenev <vbart@nginx.com> |
---|---|
date | Wed, 29 Mar 2017 20:16:23 +0300 |
parents | ec81934727a1 |
children | efd71d49bde0 |
line wrap: on
line source
/* * Copyright (C) Igor Sysoev * Copyright (C) Nginx, Inc. */ #include <ngx_config.h> #include <ngx_core.h> #include <ngx_event.h> #define NGX_WSABUFS 8 ssize_t 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 n, size; ngx_err_t err; ngx_array_t vec; ngx_event_t *rev; LPWSABUF wsabuf; WSABUF wsabufs[NGX_WSABUFS]; prev = NULL; wsabuf = NULL; flags = 0; size = 0; bytes = 0; vec.elts = wsabufs; vec.nelts = 0; vec.size = sizeof(WSABUF); vec.nalloc = NGX_WSABUFS; vec.pool = c->pool; /* 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 += n; } else { wsabuf = ngx_array_push(&vec); if (wsabuf == NULL) { return NGX_ERROR; } wsabuf->buf = (char *) chain->buf->last; wsabuf->len = n; } size += n; prev = chain->buf->end; chain = chain->next; } ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "WSARecv: %d:%d", vec.nelts, wsabuf->len); rc = WSARecv(c->fd, vec.elts, vec.nelts, &bytes, &flags, NULL, NULL); rev = c->read; if (rc == -1) { rev->ready = 0; err = ngx_socket_errno; if (err == WSAEWOULDBLOCK) { ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, "WSARecv() not ready"); return NGX_AGAIN; } rev->error = 1; ngx_connection_error(c, err, "WSARecv() failed"); return NGX_ERROR; } if (bytes < size) { rev->ready = 0; } if (bytes == 0) { rev->eof = 1; } return bytes; }