src/os/unix/ngx_recv.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_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
  10. {
  11.     ssize_t       n;
  12.     ngx_err_t     err;
  13.     ngx_event_t  *rev;

  14.     rev = c->read;

  15. #if (NGX_HAVE_KQUEUE)

  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. #endif

  38. #if (NGX_HAVE_EPOLLRDHUP)

  39.     if ((ngx_event_flags & NGX_USE_EPOLL_EVENT)
  40.         && ngx_use_epoll_rdhup)
  41.     {
  42.         ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
  43.                        "recv: eof:%d, avail:%d",
  44.                        rev->pending_eof, rev->available);

  45.         if (rev->available == 0 && !rev->pending_eof) {
  46.             rev->ready = 0;
  47.             return NGX_AGAIN;
  48.         }
  49.     }

  50. #endif

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

  53.         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
  54.                        "recv: fd:%d %z of %uz", c->fd, n, size);

  55.         if (n == 0) {
  56.             rev->ready = 0;
  57.             rev->eof = 1;

  58. #if (NGX_HAVE_KQUEUE)

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

  63.             if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
  64.                 rev->available = 0;
  65.             }

  66. #endif

  67.             return 0;
  68.         }

  69.         if (n > 0) {

  70. #if (NGX_HAVE_KQUEUE)

  71.             if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
  72.                 rev->available -= n;

  73.                 /*
  74.                  * rev->available may be negative here because some additional
  75.                  * bytes may be received between kevent() and recv()
  76.                  */

  77.                 if (rev->available <= 0) {
  78.                     if (!rev->pending_eof) {
  79.                         rev->ready = 0;
  80.                     }

  81.                     rev->available = 0;
  82.                 }

  83.                 return n;
  84.             }

  85. #endif

  86. #if (NGX_HAVE_FIONREAD)

  87.             if (rev->available >= 0) {
  88.                 rev->available -= n;

  89.                 /*
  90.                  * negative rev->available means some additional bytes
  91.                  * were received between kernel notification and recv(),
  92.                  * and therefore ev->ready can be safely reset even for
  93.                  * edge-triggered event methods
  94.                  */

  95.                 if (rev->available < 0) {
  96.                     rev->available = 0;
  97.                     rev->ready = 0;
  98.                 }

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

  101.             } else if ((size_t) n == size) {

  102.                 if (ngx_socket_nread(c->fd, &rev->available) == -1) {
  103.                     n = ngx_connection_error(c, ngx_socket_errno,
  104.                                              ngx_socket_nread_n " failed");
  105.                     break;
  106.                 }

  107.                 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
  108.                                "recv: avail:%d", rev->available);
  109.             }

  110. #endif

  111. #if (NGX_HAVE_EPOLLRDHUP)

  112.             if ((ngx_event_flags & NGX_USE_EPOLL_EVENT)
  113.                 && ngx_use_epoll_rdhup)
  114.             {
  115.                 if ((size_t) n < size) {
  116.                     if (!rev->pending_eof) {
  117.                         rev->ready = 0;
  118.                     }

  119.                     rev->available = 0;
  120.                 }

  121.                 return n;
  122.             }

  123. #endif

  124.             if ((size_t) n < size
  125.                 && !(ngx_event_flags & NGX_USE_GREEDY_EVENT))
  126.             {
  127.                 rev->ready = 0;
  128.             }

  129.             return n;
  130.         }

  131.         err = ngx_socket_errno;

  132.         if (err == NGX_EAGAIN || err == NGX_EINTR) {
  133.             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
  134.                            "recv() not ready");
  135.             n = NGX_AGAIN;

  136.         } else {
  137.             n = ngx_connection_error(c, err, "recv() failed");
  138.             break;
  139.         }

  140.     } while (err == NGX_EINTR);

  141.     rev->ready = 0;

  142.     if (n == NGX_ERROR) {
  143.         rev->error = 1;
  144.     }

  145.     return n;
  146. }