src/os/unix/ngx_recv.c - nginx-1.7.10

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. #if (NGX_HAVE_KQUEUE)

  9. ssize_t
  10. ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
  11. {
  12.     ssize_t       n;
  13.     ngx_err_t     err;
  14.     ngx_event_t  *rev;

  15.     rev = c->read;

  16.     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
  17.         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
  18.                        "recv: eof:%d, avail:%d, err:%d",
  19.                        rev->pending_eof, rev->available, rev->kq_errno);

  20.         if (rev->available == 0) {
  21.             if (rev->pending_eof) {
  22.                 rev->ready = 0;
  23.                 rev->eof = 1;

  24.                 if (rev->kq_errno) {
  25.                     rev->error = 1;
  26.                     ngx_set_socket_errno(rev->kq_errno);

  27.                     return ngx_connection_error(c, rev->kq_errno,
  28.                                "kevent() reported about an closed connection");
  29.                 }

  30.                 return 0;

  31.             } else {
  32.                 rev->ready = 0;
  33.                 return NGX_AGAIN;
  34.             }
  35.         }
  36.     }

  37.     do {
  38.         n = recv(c->fd, buf, size, 0);

  39.         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
  40.                        "recv: fd:%d %d of %d", c->fd, n, size);

  41.         if (n >= 0) {
  42.             if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
  43.                 rev->available -= n;

  44.                 /*
  45.                  * rev->available may be negative here because some additional
  46.                  * bytes may be received between kevent() and recv()
  47.                  */

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

  52.                     if (rev->available < 0) {
  53.                         rev->available = 0;
  54.                     }
  55.                 }

  56.                 if (n == 0) {

  57.                     /*
  58.                      * on FreeBSD recv() may return 0 on closed socket
  59.                      * even if kqueue reported about available data
  60.                      */

  61.                     rev->ready = 0;
  62.                     rev->eof = 1;
  63.                     rev->available = 0;
  64.                 }

  65.                 return n;
  66.             }

  67.             if ((size_t) n < size
  68.                 && !(ngx_event_flags & NGX_USE_GREEDY_EVENT))
  69.             {
  70.                 rev->ready = 0;
  71.             }

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

  75.             return n;
  76.         }

  77.         err = ngx_socket_errno;

  78.         if (err == NGX_EAGAIN || err == NGX_EINTR) {
  79.             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
  80.                            "recv() not ready");
  81.             n = NGX_AGAIN;

  82.         } else {
  83.             n = ngx_connection_error(c, err, "recv() failed");
  84.             break;
  85.         }

  86.     } while (err == NGX_EINTR);

  87.     rev->ready = 0;

  88.     if (n == NGX_ERROR) {
  89.         rev->error = 1;
  90.     }

  91.     return n;
  92. }

  93. #else /* ! NGX_HAVE_KQUEUE */

  94. ssize_t
  95. ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
  96. {
  97.     ssize_t       n;
  98.     ngx_err_t     err;
  99.     ngx_event_t  *rev;

  100.     rev = c->read;

  101.     do {
  102.         n = recv(c->fd, buf, size, 0);

  103.         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
  104.                        "recv: fd:%d %d of %d", c->fd, n, size);

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

  109.         } else if (n > 0) {

  110.             if ((size_t) n < size
  111.                 && !(ngx_event_flags & NGX_USE_GREEDY_EVENT))
  112.             {
  113.                 rev->ready = 0;
  114.             }

  115.             return n;
  116.         }

  117.         err = ngx_socket_errno;

  118.         if (err == NGX_EAGAIN || err == NGX_EINTR) {
  119.             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
  120.                            "recv() not ready");
  121.             n = NGX_AGAIN;

  122.         } else {
  123.             n = ngx_connection_error(c, err, "recv() failed");
  124.             break;
  125.         }

  126.     } while (err == NGX_EINTR);

  127.     rev->ready = 0;

  128.     if (n == NGX_ERROR) {
  129.         rev->error = 1;
  130.     }

  131.     return n;
  132. }

  133. #endif /* NGX_HAVE_KQUEUE */