1
2 /*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
6
7
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_event.h>
11
12
13 ssize_t
ngx_unix_recv(ngx_connection_t * c,u_char * buf,size_t size)14 ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
15 {
16 ssize_t n;
17 ngx_err_t err;
18 ngx_event_t *rev;
19
20 rev = c->read;
21
22 #if (NGX_HAVE_KQUEUE) || (NGX_HAVE_FSTACK)
23
24 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
25 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
26 "recv: eof:%d, avail:%d, err:%d",
27 rev->pending_eof, rev->available, rev->kq_errno);
28
29 if (rev->available == 0) {
30 if (rev->pending_eof) {
31 rev->ready = 0;
32 rev->eof = 1;
33
34 if (rev->kq_errno) {
35 rev->error = 1;
36 ngx_set_socket_errno(rev->kq_errno);
37
38 return ngx_connection_error(c, rev->kq_errno,
39 "kevent() reported about an closed connection");
40 }
41
42 return 0;
43
44 } else {
45 rev->ready = 0;
46 return NGX_AGAIN;
47 }
48 }
49 }
50
51 #endif
52
53 #if (NGX_HAVE_EPOLLRDHUP)
54
55 if (ngx_event_flags & NGX_USE_EPOLL_EVENT) {
56 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
57 "recv: eof:%d, avail:%d",
58 rev->pending_eof, rev->available);
59
60 if (!rev->available && !rev->pending_eof) {
61 rev->ready = 0;
62 return NGX_AGAIN;
63 }
64 }
65
66 #endif
67
68 do {
69 n = recv(c->fd, buf, size, 0);
70
71 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
72 "recv: fd:%d %z of %uz", c->fd, n, size);
73
74 if (n == 0) {
75 rev->ready = 0;
76 rev->eof = 1;
77
78 #if (NGX_HAVE_KQUEUE) || (NGX_HAVE_FSTACK)
79
80 /*
81 * on FreeBSD recv() may return 0 on closed socket
82 * even if kqueue reported about available data
83 */
84
85 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
86 rev->available = 0;
87 }
88
89 #endif
90
91 return 0;
92 }
93
94 if (n > 0) {
95
96 #if (NGX_HAVE_KQUEUE) || (NGX_HAVE_FSTACK)
97
98 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
99 rev->available -= n;
100
101 /*
102 * rev->available may be negative here because some additional
103 * bytes may be received between kevent() and recv()
104 */
105
106 if (rev->available <= 0) {
107 if (!rev->pending_eof) {
108 rev->ready = 0;
109 }
110
111 rev->available = 0;
112 }
113
114 return n;
115 }
116
117 #endif
118
119 #if (NGX_HAVE_EPOLLRDHUP)
120
121 if ((ngx_event_flags & NGX_USE_EPOLL_EVENT)
122 && ngx_use_epoll_rdhup)
123 {
124 if ((size_t) n < size) {
125 if (!rev->pending_eof) {
126 rev->ready = 0;
127 }
128
129 rev->available = 0;
130 }
131
132 return n;
133 }
134
135 #endif
136
137 if ((size_t) n < size
138 && !(ngx_event_flags & NGX_USE_GREEDY_EVENT))
139 {
140 rev->ready = 0;
141 }
142
143 return n;
144 }
145
146 err = ngx_socket_errno;
147
148 if (err == NGX_EAGAIN || err == NGX_EINTR) {
149 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
150 "recv() not ready");
151 n = NGX_AGAIN;
152
153 } else {
154 n = ngx_connection_error(c, err, "recv() failed");
155 break;
156 }
157
158 } while (err == NGX_EINTR);
159
160 rev->ready = 0;
161
162 if (n == NGX_ERROR) {
163 rev->error = 1;
164 }
165
166 return n;
167 }
168