|  | 
 | /* | 
 |  * 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) | 
 | { | 
 |     int           rc; | 
 |     u_char       *prev; | 
 |     u_long        bytes, flags; | 
 |     size_t        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) { | 
 |         if (prev == chain->buf->last) { | 
 |             wsabuf->len += chain->buf->end - chain->buf->last; | 
 |  | 
 |         } else { | 
 |             wsabuf = ngx_array_push(&vec); | 
 |             if (wsabuf == NULL) { | 
 |                 return NGX_ERROR; | 
 |             } | 
 |  | 
 |             wsabuf->buf = (char *) chain->buf->last; | 
 |             wsabuf->len = chain->buf->end - chain->buf->last; | 
 |         } | 
 |  | 
 |         size += chain->buf->end - chain->buf->last; | 
 |         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; | 
 | } |