blob: 6361b3ce02007fe9e1d9aefeee1e91011b56a7aa [file] [log] [blame]
Igor Sysoeva9830112003-05-19 16:39:14 +00001
Igor Sysoevd90282d2004-09-28 08:34:51 +00002/*
Igor Sysoevff8da912004-09-29 16:00:49 +00003 * Copyright (C) Igor Sysoev
Igor Sysoevd90282d2004-09-28 08:34:51 +00004 */
5
6
Igor Sysoeva9830112003-05-19 16:39:14 +00007#include <ngx_config.h>
8#include <ngx_core.h>
Igor Sysoev239baac2003-06-11 15:28:34 +00009#include <ngx_event.h>
Igor Sysoeva9830112003-05-19 16:39:14 +000010
11
Igor Sysoevf6906042004-11-25 16:17:31 +000012#if (NGX_HAVE_KQUEUE)
Igor Sysoev6253ca12003-05-27 12:18:54 +000013
Igor Sysoev06187ce2007-12-01 20:25:32 +000014ssize_t
15ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
Igor Sysoeva9830112003-05-19 16:39:14 +000016{
17 ssize_t n;
Igor Sysoev7af6b162004-02-09 07:46:43 +000018 ngx_err_t err;
Igor Sysoev6253ca12003-05-27 12:18:54 +000019 ngx_event_t *rev;
Igor Sysoeva9830112003-05-19 16:39:14 +000020
Igor Sysoev6253ca12003-05-27 12:18:54 +000021 rev = c->read;
Igor Sysoeva9830112003-05-19 16:39:14 +000022
Igor Sysoevc0edbcc2004-10-21 15:34:38 +000023 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
Igor Sysoev3c3ca172004-01-05 20:55:48 +000024 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
25 "recv: eof:%d, avail:%d, err:%d",
Igor Sysoev98c1cf12004-07-02 15:54:34 +000026 rev->pending_eof, rev->available, rev->kq_errno);
Igor Sysoeva9830112003-05-19 16:39:14 +000027
Igor Sysoev6253ca12003-05-27 12:18:54 +000028 if (rev->available == 0) {
Igor Sysoevcdc46302005-12-07 14:51:31 +000029 if (rev->pending_eof) {
Igor Sysoevd404c972003-10-16 20:19:16 +000030 rev->ready = 0;
Igor Sysoevab0c4f52003-10-28 15:45:41 +000031 rev->eof = 1;
32
33 if (rev->kq_errno) {
34 rev->error = 1;
35 ngx_set_socket_errno(rev->kq_errno);
Igor Sysoev3c3ca172004-01-05 20:55:48 +000036
Igor Sysoeve5035392005-08-30 10:55:07 +000037 return ngx_connection_error(c, rev->kq_errno,
38 "kevent() reported about an closed connection");
Igor Sysoev6253ca12003-05-27 12:18:54 +000039 }
Igor Sysoevab0c4f52003-10-28 15:45:41 +000040
Igor Sysoev6253ca12003-05-27 12:18:54 +000041 return 0;
Igor Sysoevcdc46302005-12-07 14:51:31 +000042
43 } else {
44 return NGX_AGAIN;
Igor Sysoev6253ca12003-05-27 12:18:54 +000045 }
Igor Sysoeva9830112003-05-19 16:39:14 +000046 }
Igor Sysoev6253ca12003-05-27 12:18:54 +000047 }
Igor Sysoeva9830112003-05-19 16:39:14 +000048
Igor Sysoev6253ca12003-05-27 12:18:54 +000049 do {
Igor Sysoeva9830112003-05-19 16:39:14 +000050 n = recv(c->fd, buf, size, 0);
51
Igor Sysoev7af6b162004-02-09 07:46:43 +000052 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
53 "recv: fd:%d %d of %d", c->fd, n, size);
Igor Sysoeva9830112003-05-19 16:39:14 +000054
Igor Sysoev6253ca12003-05-27 12:18:54 +000055 if (n >= 0) {
Igor Sysoevc0edbcc2004-10-21 15:34:38 +000056 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
Igor Sysoev6253ca12003-05-27 12:18:54 +000057 rev->available -= n;
Igor Sysoevab0c4f52003-10-28 15:45:41 +000058
59 /*
Igor Sysoevd3283ff2005-12-05 13:18:09 +000060 * rev->available may be negative here because some additional
Igor Sysoevcdc46302005-12-07 14:51:31 +000061 * bytes may be received between kevent() and recv()
Igor Sysoevab0c4f52003-10-28 15:45:41 +000062 */
63
Igor Sysoev0a280a32003-10-12 16:49:16 +000064 if (rev->available <= 0) {
Igor Sysoev98c1cf12004-07-02 15:54:34 +000065 if (!rev->pending_eof) {
Igor Sysoevd404c972003-10-16 20:19:16 +000066 rev->ready = 0;
67 }
68
Igor Sysoev0a280a32003-10-12 16:49:16 +000069 if (rev->available < 0) {
70 rev->available = 0;
71 }
Igor Sysoev6253ca12003-05-27 12:18:54 +000072 }
Igor Sysoeva9830112003-05-19 16:39:14 +000073
Igor Sysoev9e580192006-02-01 18:22:15 +000074 if (n == 0) {
75
76 /*
77 * on FreeBSD recv() may return 0 on closed socket
78 * even if kqueue reported about available data
79 */
80
Igor Sysoev9e580192006-02-01 18:22:15 +000081 rev->eof = 1;
82 rev->available = 0;
83 }
84
Igor Sysoev6253ca12003-05-27 12:18:54 +000085 return n;
86 }
Igor Sysoeva9830112003-05-19 16:39:14 +000087
Igor Sysoev6253ca12003-05-27 12:18:54 +000088 if ((size_t) n < size) {
89 rev->ready = 0;
90 }
Igor Sysoeva9830112003-05-19 16:39:14 +000091
Igor Sysoevab0c4f52003-10-28 15:45:41 +000092 if (n == 0) {
93 rev->eof = 1;
94 }
95
Igor Sysoev6253ca12003-05-27 12:18:54 +000096 return n;
Igor Sysoeva9830112003-05-19 16:39:14 +000097 }
98
Igor Sysoev7af6b162004-02-09 07:46:43 +000099 err = ngx_socket_errno;
Igor Sysoeva9830112003-05-19 16:39:14 +0000100
Igor Sysoev7af6b162004-02-09 07:46:43 +0000101 if (err == NGX_EAGAIN || err == NGX_EINTR) {
Igor Sysoev54498db2004-02-11 17:08:49 +0000102 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
Igor Sysoev7af6b162004-02-09 07:46:43 +0000103 "recv() not ready");
104 n = NGX_AGAIN;
Igor Sysoeva9830112003-05-19 16:39:14 +0000105
Igor Sysoev7af6b162004-02-09 07:46:43 +0000106 } else {
107 n = ngx_connection_error(c, err, "recv() failed");
108 break;
109 }
110
111 } while (err == NGX_EINTR);
Igor Sysoev0b2b4cc2003-11-18 08:04:34 +0000112
113 rev->ready = 0;
114
Igor Sysoev7f9d8942003-11-14 07:20:34 +0000115 if (n == NGX_ERROR){
116 rev->error = 1;
117 }
118
Igor Sysoeva9830112003-05-19 16:39:14 +0000119 return n;
120}
Igor Sysoev6253ca12003-05-27 12:18:54 +0000121
Igor Sysoevf6906042004-11-25 16:17:31 +0000122#else /* ! NGX_HAVE_KQUEUE */
Igor Sysoev6253ca12003-05-27 12:18:54 +0000123
Igor Sysoev06187ce2007-12-01 20:25:32 +0000124ssize_t
125ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
Igor Sysoev6253ca12003-05-27 12:18:54 +0000126{
127 ssize_t n;
Igor Sysoev7af6b162004-02-09 07:46:43 +0000128 ngx_err_t err;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000129 ngx_event_t *rev;
130
131 rev = c->read;
132
133 do {
134 n = recv(c->fd, buf, size, 0);
135
Igor Sysoev7af6b162004-02-09 07:46:43 +0000136 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
137 "recv: fd:%d %d of %d", c->fd, n, size);
Igor Sysoev6253ca12003-05-27 12:18:54 +0000138
Igor Sysoev4cec79f2004-04-28 06:14:50 +0000139 if (n == 0) {
140 rev->ready = 0;
141 rev->eof = 1;
142 return n;
Igor Sysoevab0c4f52003-10-28 15:45:41 +0000143
Igor Sysoev4cec79f2004-04-28 06:14:50 +0000144 } else if (n > 0) {
145
146 if ((size_t) n < size
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000147 && !(ngx_event_flags & NGX_USE_GREEDY_EVENT))
Igor Sysoev4cec79f2004-04-28 06:14:50 +0000148 {
149 rev->ready = 0;
Igor Sysoevab0c4f52003-10-28 15:45:41 +0000150 }
151
Igor Sysoev6253ca12003-05-27 12:18:54 +0000152 return n;
153 }
154
Igor Sysoev7af6b162004-02-09 07:46:43 +0000155 err = ngx_socket_errno;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000156
Igor Sysoev7af6b162004-02-09 07:46:43 +0000157 if (err == NGX_EAGAIN || err == NGX_EINTR) {
Igor Sysoev54498db2004-02-11 17:08:49 +0000158 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
Igor Sysoev7af6b162004-02-09 07:46:43 +0000159 "recv() not ready");
160 n = NGX_AGAIN;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000161
Igor Sysoev7af6b162004-02-09 07:46:43 +0000162 } else {
163 n = ngx_connection_error(c, err, "recv() failed");
164 break;
165 }
166
167 } while (err == NGX_EINTR);
Igor Sysoev0b2b4cc2003-11-18 08:04:34 +0000168
169 rev->ready = 0;
170
Igor Sysoev7f9d8942003-11-14 07:20:34 +0000171 if (n == NGX_ERROR){
172 rev->error = 1;
173 }
174
Igor Sysoev6253ca12003-05-27 12:18:54 +0000175 return n;
176}
177
Igor Sysoevf6906042004-11-25 16:17:31 +0000178#endif /* NGX_HAVE_KQUEUE */