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

Functions 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. ssize_t
  9. ngx_wsarecv(ngx_connection_t *c, u_char *buf, size_t size)
  10. {
  11.     int           rc;
  12.     u_long        bytes, flags;
  13.     WSABUF        wsabuf[1];
  14.     ngx_err_t     err;
  15.     ngx_int_t     n;
  16.     ngx_event_t  *rev;

  17.     wsabuf[0].buf = (char *) buf;
  18.     wsabuf[0].len = size;
  19.     flags = 0;
  20.     bytes = 0;

  21.     rc = WSARecv(c->fd, wsabuf, 1, &bytes, &flags, NULL, NULL);

  22.     ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
  23.                    "WSARecv: fd:%d rc:%d %ul of %z", c->fd, rc, bytes, size);

  24.     rev = c->read;

  25.     if (rc == -1) {
  26.         rev->ready = 0;
  27.         err = ngx_socket_errno;

  28.         if (err == WSAEWOULDBLOCK) {
  29.             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
  30.                            "WSARecv() not ready");
  31.             return NGX_AGAIN;
  32.         }

  33.         n = ngx_connection_error(c, err, "WSARecv() failed");

  34.         if (n == NGX_ERROR) {
  35.             rev->error = 1;
  36.         }

  37.         return n;
  38.     }

  39. #if (NGX_HAVE_FIONREAD)

  40.     if (rev->available >= 0 && bytes > 0) {
  41.         rev->available -= bytes;

  42.         /*
  43.          * negative rev->available means some additional bytes
  44.          * were received between kernel notification and WSARecv(),
  45.          * and therefore ev->ready can be safely reset even for
  46.          * edge-triggered event methods
  47.          */

  48.         if (rev->available < 0) {
  49.             rev->available = 0;
  50.             rev->ready = 0;
  51.         }

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

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

  55.         if (ngx_socket_nread(c->fd, &rev->available) == -1) {
  56.             n = ngx_connection_error(c, ngx_socket_errno,
  57.                                      ngx_socket_nread_n " failed");

  58.             if (n == NGX_ERROR) {
  59.                 rev->ready = 0;
  60.                 rev->error = 1;
  61.             }

  62.             return n;
  63.         }

  64.         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
  65.                        "WSARecv: avail:%d", rev->available);
  66.     }

  67. #endif

  68.     if (bytes < size) {
  69.         rev->ready = 0;
  70.     }

  71.     if (bytes == 0) {
  72.         rev->ready = 0;
  73.         rev->eof = 1;
  74.     }

  75.     return bytes;
  76. }


  77. ssize_t
  78. ngx_overlapped_wsarecv(ngx_connection_t *c, u_char *buf, size_t size)
  79. {
  80.     int               rc;
  81.     u_long            bytes, flags;
  82.     WSABUF            wsabuf[1];
  83.     ngx_err_t         err;
  84.     ngx_int_t         n;
  85.     ngx_event_t      *rev;
  86.     LPWSAOVERLAPPED   ovlp;

  87.     rev = c->read;

  88.     if (!rev->ready) {
  89.         ngx_log_error(NGX_LOG_ALERT, c->log, 0, "second wsa post");
  90.         return NGX_AGAIN;
  91.     }

  92.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
  93.                    "rev->complete: %d", rev->complete);

  94.     if (rev->complete) {
  95.         rev->complete = 0;

  96.         if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
  97.             if (rev->ovlp.error) {
  98.                 ngx_connection_error(c, rev->ovlp.error, "WSARecv() failed");
  99.                 return NGX_ERROR;
  100.             }

  101.             ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
  102.                            "WSARecv ovlp: fd:%d %ul of %z",
  103.                            c->fd, rev->available, size);

  104.             return rev->available;
  105.         }

  106.         if (WSAGetOverlappedResult(c->fd, (LPWSAOVERLAPPED) &rev->ovlp,
  107.                                    &bytes, 0, NULL)
  108.             == 0)
  109.         {
  110.             ngx_connection_error(c, ngx_socket_errno,
  111.                                "WSARecv() or WSAGetOverlappedResult() failed");
  112.             return NGX_ERROR;
  113.         }

  114.         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
  115.                        "WSARecv: fd:%d %ul of %z", c->fd, bytes, size);

  116.         return bytes;
  117.     }

  118.     ovlp = (LPWSAOVERLAPPED) &rev->ovlp;
  119.     ngx_memzero(ovlp, sizeof(WSAOVERLAPPED));
  120.     wsabuf[0].buf = (char *) buf;
  121.     wsabuf[0].len = size;
  122.     flags = 0;
  123.     bytes = 0;

  124.     rc = WSARecv(c->fd, wsabuf, 1, &bytes, &flags, ovlp, NULL);

  125.     rev->complete = 0;

  126.     ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
  127.                    "WSARecv ovlp: fd:%d rc:%d %ul of %z",
  128.                    c->fd, rc, bytes, size);

  129.     if (rc == -1) {
  130.         err = ngx_socket_errno;
  131.         if (err == WSA_IO_PENDING) {
  132.             rev->active = 1;
  133.             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
  134.                            "WSARecv() posted");
  135.             return NGX_AGAIN;
  136.         }

  137.         n = ngx_connection_error(c, err, "WSARecv() failed");

  138.         if (n == NGX_ERROR) {
  139.             rev->error = 1;
  140.         }

  141.         return n;
  142.     }

  143.     if (ngx_event_flags & NGX_USE_IOCP_EVENT) {

  144.         /*
  145.          * if a socket was bound with I/O completion port
  146.          * then GetQueuedCompletionStatus() would anyway return its status
  147.          * despite that WSARecv() was already complete
  148.          */

  149.         rev->active = 1;
  150.         return NGX_AGAIN;
  151.     }

  152.     if (bytes == 0) {
  153.         rev->eof = 1;
  154.         rev->ready = 0;

  155.     } else {
  156.         rev->ready = 1;
  157.     }

  158.     rev->active = 0;

  159.     return bytes;
  160. }