src/os/win32/ngx_wsarecv_chain.c - nginx source code

Functions defined

Macros defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_event.h>


  8. #define NGX_WSABUFS  64


  9. ssize_t
  10. ngx_wsarecv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit)
  11. {
  12.     int           rc;
  13.     u_char       *prev;
  14.     u_long        bytes, flags;
  15.     size_t        n, size;
  16.     ngx_err_t     err;
  17.     ngx_array_t   vec;
  18.     ngx_event_t  *rev;
  19.     LPWSABUF      wsabuf;
  20.     WSABUF        wsabufs[NGX_WSABUFS];

  21.     prev = NULL;
  22.     wsabuf = NULL;
  23.     flags = 0;
  24.     size = 0;
  25.     bytes = 0;

  26.     vec.elts = wsabufs;
  27.     vec.nelts = 0;
  28.     vec.size = sizeof(WSABUF);
  29.     vec.nalloc = NGX_WSABUFS;
  30.     vec.pool = c->pool;

  31.     /* coalesce the neighbouring bufs */

  32.     while (chain) {
  33.         n = chain->buf->end - chain->buf->last;

  34.         if (limit) {
  35.             if (size >= (size_t) limit) {
  36.                 break;
  37.             }

  38.             if (size + n > (size_t) limit) {
  39.                 n = (size_t) limit - size;
  40.             }
  41.         }

  42.         if (prev == chain->buf->last) {
  43.             wsabuf->len += n;

  44.         } else {
  45.             if (vec.nelts == vec.nalloc) {
  46.                 break;
  47.             }

  48.             wsabuf = ngx_array_push(&vec);
  49.             if (wsabuf == NULL) {
  50.                 return NGX_ERROR;
  51.             }

  52.             wsabuf->buf = (char *) chain->buf->last;
  53.             wsabuf->len = n;
  54.         }

  55.         size += n;
  56.         prev = chain->buf->end;
  57.         chain = chain->next;
  58.     }

  59.     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
  60.                    "WSARecv: %d:%d", vec.nelts, wsabuf->len);


  61.     rc = WSARecv(c->fd, vec.elts, vec.nelts, &bytes, &flags, NULL, NULL);

  62.     rev = c->read;

  63.     if (rc == -1) {
  64.         rev->ready = 0;
  65.         err = ngx_socket_errno;

  66.         if (err == WSAEWOULDBLOCK) {
  67.             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
  68.                            "WSARecv() not ready");
  69.             return NGX_AGAIN;
  70.         }

  71.         rev->error = 1;
  72.         ngx_connection_error(c, err, "WSARecv() failed");
  73.         return NGX_ERROR;
  74.     }

  75. #if (NGX_HAVE_FIONREAD)

  76.     if (rev->available >= 0 && bytes > 0) {
  77.         rev->available -= bytes;

  78.         /*
  79.          * negative rev->available means some additional bytes
  80.          * were received between kernel notification and WSARecv(),
  81.          * and therefore ev->ready can be safely reset even for
  82.          * edge-triggered event methods
  83.          */

  84.         if (rev->available < 0) {
  85.             rev->available = 0;
  86.             rev->ready = 0;
  87.         }

  88.         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
  89.                        "WSARecv: avail:%d", rev->available);

  90.     } else if (bytes == size) {

  91.         if (ngx_socket_nread(c->fd, &rev->available) == -1) {
  92.             rev->ready = 0;
  93.             rev->error = 1;
  94.             ngx_connection_error(c, ngx_socket_errno,
  95.                                  ngx_socket_nread_n " failed");
  96.             return NGX_ERROR;
  97.         }

  98.         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
  99.                        "WSARecv: avail:%d", rev->available);
  100.     }

  101. #endif

  102.     if (bytes < size) {
  103.         rev->ready = 0;
  104.     }

  105.     if (bytes == 0) {
  106.         rev->ready = 0;
  107.         rev->eof = 1;
  108.     }

  109.     return bytes;
  110. }