blob: f4d6a2bccd4717c108e5c371442ddd9a135a537e [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 {
Igor Sysoevc463ece2008-01-31 15:36:33 +000044 rev->ready = 0;
Igor Sysoevcdc46302005-12-07 14:51:31 +000045 return NGX_AGAIN;
Igor Sysoev6253ca12003-05-27 12:18:54 +000046 }
Igor Sysoeva9830112003-05-19 16:39:14 +000047 }
Igor Sysoev6253ca12003-05-27 12:18:54 +000048 }
Igor Sysoeva9830112003-05-19 16:39:14 +000049
Igor Sysoev6253ca12003-05-27 12:18:54 +000050 do {
Igor Sysoeva9830112003-05-19 16:39:14 +000051 n = recv(c->fd, buf, size, 0);
52
Igor Sysoev7af6b162004-02-09 07:46:43 +000053 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
54 "recv: fd:%d %d of %d", c->fd, n, size);
Igor Sysoeva9830112003-05-19 16:39:14 +000055
Igor Sysoev6253ca12003-05-27 12:18:54 +000056 if (n >= 0) {
Igor Sysoevc0edbcc2004-10-21 15:34:38 +000057 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
Igor Sysoev6253ca12003-05-27 12:18:54 +000058 rev->available -= n;
Igor Sysoevab0c4f52003-10-28 15:45:41 +000059
60 /*
Igor Sysoevd3283ff2005-12-05 13:18:09 +000061 * rev->available may be negative here because some additional
Igor Sysoevcdc46302005-12-07 14:51:31 +000062 * bytes may be received between kevent() and recv()
Igor Sysoevab0c4f52003-10-28 15:45:41 +000063 */
64
Igor Sysoev0a280a32003-10-12 16:49:16 +000065 if (rev->available <= 0) {
Igor Sysoev98c1cf12004-07-02 15:54:34 +000066 if (!rev->pending_eof) {
Igor Sysoevd404c972003-10-16 20:19:16 +000067 rev->ready = 0;
68 }
69
Igor Sysoev0a280a32003-10-12 16:49:16 +000070 if (rev->available < 0) {
71 rev->available = 0;
72 }
Igor Sysoev6253ca12003-05-27 12:18:54 +000073 }
Igor Sysoeva9830112003-05-19 16:39:14 +000074
Igor Sysoev9e580192006-02-01 18:22:15 +000075 if (n == 0) {
76
77 /*
78 * on FreeBSD recv() may return 0 on closed socket
79 * even if kqueue reported about available data
80 */
81
Igor Sysoev9e580192006-02-01 18:22:15 +000082 rev->eof = 1;
83 rev->available = 0;
84 }
85
Igor Sysoev6253ca12003-05-27 12:18:54 +000086 return n;
87 }
Igor Sysoeva9830112003-05-19 16:39:14 +000088
Igor Sysoev6253ca12003-05-27 12:18:54 +000089 if ((size_t) n < size) {
90 rev->ready = 0;
91 }
Igor Sysoeva9830112003-05-19 16:39:14 +000092
Igor Sysoevab0c4f52003-10-28 15:45:41 +000093 if (n == 0) {
94 rev->eof = 1;
95 }
96
Igor Sysoev6253ca12003-05-27 12:18:54 +000097 return n;
Igor Sysoeva9830112003-05-19 16:39:14 +000098 }
99
Igor Sysoev7af6b162004-02-09 07:46:43 +0000100 err = ngx_socket_errno;
Igor Sysoeva9830112003-05-19 16:39:14 +0000101
Igor Sysoev7af6b162004-02-09 07:46:43 +0000102 if (err == NGX_EAGAIN || err == NGX_EINTR) {
Igor Sysoev54498db2004-02-11 17:08:49 +0000103 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
Igor Sysoev7af6b162004-02-09 07:46:43 +0000104 "recv() not ready");
105 n = NGX_AGAIN;
Igor Sysoeva9830112003-05-19 16:39:14 +0000106
Igor Sysoev7af6b162004-02-09 07:46:43 +0000107 } else {
108 n = ngx_connection_error(c, err, "recv() failed");
109 break;
110 }
111
112 } while (err == NGX_EINTR);
Igor Sysoev0b2b4cc2003-11-18 08:04:34 +0000113
114 rev->ready = 0;
115
Igor Sysoev7f9d8942003-11-14 07:20:34 +0000116 if (n == NGX_ERROR){
117 rev->error = 1;
118 }
119
Igor Sysoeva9830112003-05-19 16:39:14 +0000120 return n;
121}
Igor Sysoev6253ca12003-05-27 12:18:54 +0000122
Igor Sysoevf6906042004-11-25 16:17:31 +0000123#else /* ! NGX_HAVE_KQUEUE */
Igor Sysoev6253ca12003-05-27 12:18:54 +0000124
Igor Sysoev06187ce2007-12-01 20:25:32 +0000125ssize_t
126ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
Igor Sysoev6253ca12003-05-27 12:18:54 +0000127{
128 ssize_t n;
Igor Sysoev7af6b162004-02-09 07:46:43 +0000129 ngx_err_t err;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000130 ngx_event_t *rev;
131
132 rev = c->read;
133
134 do {
135 n = recv(c->fd, buf, size, 0);
136
Igor Sysoev7af6b162004-02-09 07:46:43 +0000137 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
138 "recv: fd:%d %d of %d", c->fd, n, size);
Igor Sysoev6253ca12003-05-27 12:18:54 +0000139
Igor Sysoev4cec79f2004-04-28 06:14:50 +0000140 if (n == 0) {
141 rev->ready = 0;
142 rev->eof = 1;
143 return n;
Igor Sysoevab0c4f52003-10-28 15:45:41 +0000144
Igor Sysoev4cec79f2004-04-28 06:14:50 +0000145 } else if (n > 0) {
146
147 if ((size_t) n < size
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000148 && !(ngx_event_flags & NGX_USE_GREEDY_EVENT))
Igor Sysoev4cec79f2004-04-28 06:14:50 +0000149 {
150 rev->ready = 0;
Igor Sysoevab0c4f52003-10-28 15:45:41 +0000151 }
152
Igor Sysoev6253ca12003-05-27 12:18:54 +0000153 return n;
154 }
155
Igor Sysoev7af6b162004-02-09 07:46:43 +0000156 err = ngx_socket_errno;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000157
Igor Sysoev7af6b162004-02-09 07:46:43 +0000158 if (err == NGX_EAGAIN || err == NGX_EINTR) {
Igor Sysoev54498db2004-02-11 17:08:49 +0000159 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
Igor Sysoev7af6b162004-02-09 07:46:43 +0000160 "recv() not ready");
161 n = NGX_AGAIN;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000162
Igor Sysoev7af6b162004-02-09 07:46:43 +0000163 } else {
164 n = ngx_connection_error(c, err, "recv() failed");
165 break;
166 }
167
168 } while (err == NGX_EINTR);
Igor Sysoev0b2b4cc2003-11-18 08:04:34 +0000169
170 rev->ready = 0;
171
Igor Sysoev7f9d8942003-11-14 07:20:34 +0000172 if (n == NGX_ERROR){
173 rev->error = 1;
174 }
175
Igor Sysoev6253ca12003-05-27 12:18:54 +0000176 return n;
177}
178
Igor Sysoevf6906042004-11-25 16:17:31 +0000179#endif /* NGX_HAVE_KQUEUE */