Mercurial > hg > nginx-quic
diff src/os/win32/ngx_wsasend_chain.c @ 461:a88a3e4e158f release-0.1.5
nginx-0.1.5-RELEASE import
*) Bugfix: on Solaris and Linux there may be too many "recvmsg()
returned not enough data" alerts.
*) Bugfix: there were the "writev() failed (22: Invalid argument)"
errors on Solaris in proxy mode without sendfile. On other platforms
that do not support sendfile at all the process got caught in an
endless loop.
*) Bugfix: segmentation fault on Solaris in proxy mode and using
sendfile.
*) Bugfix: segmentation fault on Solaris.
*) Bugfix: on-line upgrade did not work on Linux.
*) Bugfix: the ngx_http_autoindex_module module did not escape the
spaces, the quotes, and the percent signs in the directory listing.
*) Change: the decrease of the copy operations.
*) Feature: the userid_p3p directive.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Thu, 11 Nov 2004 14:07:14 +0000 |
parents | 42d11f017717 |
children | 8e8f3af115b5 |
line wrap: on
line diff
--- a/src/os/win32/ngx_wsasend_chain.c +++ b/src/os/win32/ngx_wsasend_chain.c @@ -9,17 +9,21 @@ #include <ngx_event.h> +#define NGX_WSABUFS 8 + + ngx_chain_t *ngx_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) { int rc; u_char *prev; - size_t size; - u_long sent; - LPWSABUF wsabuf; + u_long size, sent, send, sprev; + ngx_uint_t complete; ngx_err_t err; ngx_event_t *wev; - ngx_array_t wsabufs; + ngx_array_t vec; + LPWSABUF wsabuf; + WSABUF wsabufs[NGX_WSABUFS]; ngx_chain_t *cl; wev = c->write; @@ -28,80 +32,119 @@ ngx_chain_t *ngx_wsasend_chain(ngx_conne return in; } + send = 0; + complete = 0; + /* * WSABUFs must be 4-byte aligned otherwise * WSASend() will return undocumented WSAEINVAL error. */ - ngx_init_array(wsabufs, c->pool, 10, sizeof(WSABUF), NGX_CHAIN_ERROR); - - prev = NULL; - wsabuf = NULL; - - /* create the WSABUF and coalesce the neighbouring bufs */ - - for (cl = in; cl; cl = cl->next) { - - if (prev == cl->buf->pos) { - wsabuf->len += cl->buf->last - cl->buf->pos; - prev = cl->buf->last; + vec.elts = wsabufs; + vec.size = sizeof(WSABUF); + vec.nalloc = NGX_WSABUFS; + vec.pool = c->pool; - } else { - ngx_test_null(wsabuf, ngx_push_array(&wsabufs), NGX_CHAIN_ERROR); - wsabuf->buf = (char *) cl->buf->pos; - wsabuf->len = cl->buf->last - cl->buf->pos; - prev = cl->buf->last; - } - } + for ( ;; ) { + prev = NULL; + wsabuf = NULL; + sprev = send; - rc = WSASend(c->fd, wsabufs.elts, wsabufs.nelts, &sent, 0, NULL, NULL); + vec.nelts = 0; - if (rc == -1) { - err = ngx_errno; + /* create the WSABUF and coalesce the neighbouring bufs */ - if (err == WSAEWOULDBLOCK) { - ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, - "WSASend() not ready"); - wev->ready = 0; - return in; + for (cl = in; + cl && vec.nelts < ngx_max_wsabufs && send < limit; + cl = cl->next) + { + if (ngx_buf_special(cl->buf)) { + continue; + } - } else { - wev->error = 1; - ngx_connection_error(c, err, "WSASend() failed"); - return NGX_CHAIN_ERROR; - } - } + size = cl->buf->last - cl->buf->pos; - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "WSASend: %d", sent); + if (send + size > limit) { + size = (u_long) (limit - send); + } - c->sent += sent; - - for (cl = in; cl && sent > 0; cl = cl->next) { + if (prev == cl->buf->pos) { + wsabuf->len += cl->buf->last - cl->buf->pos; - size = cl->buf->last - cl->buf->pos; + } else { + if (!(wsabuf = ngx_array_push(&vec))) { + return NGX_CHAIN_ERROR; + } - if (sent >= size) { - sent -= size; - - if (ngx_buf_in_memory(cl->buf)) { - cl->buf->pos = cl->buf->last; + wsabuf->buf = (char *) cl->buf->pos; + wsabuf->len = cl->buf->last - cl->buf->pos; } - continue; + prev = cl->buf->last; + send += size; } - if (ngx_buf_in_memory(cl->buf)) { - cl->buf->pos += sent; + sent = 0; + + rc = WSASend(c->fd, vec.elts, vec.nelts, &sent, 0, NULL, NULL); + + if (rc == -1) { + err = ngx_errno; + + if (err == WSAEWOULDBLOCK) { + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, + "WSASend() not ready"); + + } else { + wev->error = 1; + ngx_connection_error(c, err, "WSASend() failed"); + return NGX_CHAIN_ERROR; + } + } + + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "WSASend: fd:%d, s:%ul", c->fd, sent); + + if (send - sprev == sent) { + complete = 1; } - break; - } + c->sent += sent; + + for (cl = in; cl && sent > 0; cl = cl->next) { + if (ngx_buf_special(cl->buf)) { + continue; + } + + if (sent == 0) { + break; + } + + size = cl->buf->last - cl->buf->pos; + + if (sent >= size) { + sent -= size; + cl->buf->pos = cl->buf->last; - if (cl) { - wev->ready = 0; + continue; + } + + cl->buf->pos += sent; + + break; + } + + if (!complete) { + wev->ready = 0; + return cl; + } + + if (send >= limit || cl == NULL) { + return cl; + } + + in = cl; } - - return cl; } @@ -111,13 +154,14 @@ ngx_chain_t *ngx_overlapped_wsasend_chai int rc; u_char *prev; size_t size; - u_long sent; + u_long send, sent; LPWSABUF wsabuf; ngx_err_t err; ngx_event_t *wev; - ngx_array_t wsabufs; + ngx_array_t vec; ngx_chain_t *cl; LPWSAOVERLAPPED ovlp; + WSABUF wsabufs[NGX_WSABUFS]; wev = c->write; @@ -125,6 +169,9 @@ ngx_chain_t *ngx_overlapped_wsasend_chai return in; } + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, + "wev->complete: %d", wev->complete); + if (!wev->complete) { /* post the overlapped WSASend() */ @@ -134,32 +181,52 @@ ngx_chain_t *ngx_overlapped_wsasend_chai * WSASend() will return undocumented WSAEINVAL error. */ - ngx_init_array(wsabufs, c->pool, 10, sizeof(WSABUF), NGX_CHAIN_ERROR); + vec.elts = wsabufs; + vec.nelts = 0; + vec.size = sizeof(WSABUF); + vec.nalloc = NGX_WSABUFS; + vec.pool = c->pool; + send = 0; prev = NULL; wsabuf = NULL; /* create the WSABUF and coalesce the neighbouring bufs */ - for (cl = in; cl; cl = cl->next) { + for (cl = in; + cl && vec.nelts < ngx_max_wsabufs && send < limit; + cl = cl->next) + { + if (ngx_buf_special(cl->buf)) { + continue; + } + + size = cl->buf->last - cl->buf->pos; + + if (send + size > limit) { + size = (u_long) (limit - send); + } if (prev == cl->buf->pos) { wsabuf->len += cl->buf->last - cl->buf->pos; - prev = cl->buf->last; - + } else { - ngx_test_null(wsabuf, ngx_push_array(&wsabufs), - NGX_CHAIN_ERROR); + if (!(wsabuf = ngx_array_push(&vec))) { + return NGX_CHAIN_ERROR; + } + wsabuf->buf = (char *) cl->buf->pos; wsabuf->len = cl->buf->last - cl->buf->pos; - prev = cl->buf->last; } + + prev = cl->buf->last; + send += size; } ovlp = (LPWSAOVERLAPPED) &c->write->ovlp; ngx_memzero(ovlp, sizeof(WSAOVERLAPPED)); - rc = WSASend(c->fd, wsabufs.elts, wsabufs.nelts, &sent, 0, ovlp, NULL); + rc = WSASend(c->fd, vec.elts, vec.nelts, &sent, 0, ovlp, NULL); wev->complete = 0; @@ -167,6 +234,8 @@ ngx_chain_t *ngx_overlapped_wsasend_chai err = ngx_errno; if (err == WSA_IO_PENDING) { + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, + "WSASend() posted"); wev->active = 1; return in; @@ -188,6 +257,9 @@ ngx_chain_t *ngx_overlapped_wsasend_chai return in; } + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "WSASend: fd:%d, s:%ul", c->fd, sent); + } else { /* the overlapped WSASend() complete */ @@ -214,27 +286,30 @@ ngx_chain_t *ngx_overlapped_wsasend_chai } } - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "WSASend: %d", sent); + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "WSASend ovlp: fd:%d, s:%ul", c->fd, sent); c->sent += sent; for (cl = in; cl && sent > 0; cl = cl->next) { + if (ngx_buf_special(cl->buf)) { + continue; + } + + if (sent == 0) { + break; + } size = cl->buf->last - cl->buf->pos; if (sent >= size) { sent -= size; - - if (ngx_buf_in_memory(cl->buf)) { - cl->buf->pos = cl->buf->last; - } + cl->buf->pos = cl->buf->last; continue; } - if (ngx_buf_in_memory(cl->buf)) { - cl->buf->pos += sent; - } + cl->buf->pos += sent; break; }