blob: 86675dfdd8fe194c9aadfab7c180d895916305bb [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
Maxim Konovalovf8d59e32012-01-18 15:07:43 +00004 * Copyright (C) Nginx, Inc.
Igor Sysoevd90282d2004-09-28 08:34:51 +00005 */
6
7
Igor Sysoeva9830112003-05-19 16:39:14 +00008#include <ngx_config.h>
9#include <ngx_core.h>
Igor Sysoev239baac2003-06-11 15:28:34 +000010#include <ngx_event.h>
Igor Sysoeva9830112003-05-19 16:39:14 +000011
12
Igor Sysoevf6906042004-11-25 16:17:31 +000013#if (NGX_HAVE_KQUEUE)
Igor Sysoev6253ca12003-05-27 12:18:54 +000014
Igor Sysoev06187ce2007-12-01 20:25:32 +000015ssize_t
16ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
Igor Sysoeva9830112003-05-19 16:39:14 +000017{
18 ssize_t n;
Igor Sysoev7af6b162004-02-09 07:46:43 +000019 ngx_err_t err;
Igor Sysoev6253ca12003-05-27 12:18:54 +000020 ngx_event_t *rev;
Igor Sysoeva9830112003-05-19 16:39:14 +000021
Igor Sysoev6253ca12003-05-27 12:18:54 +000022 rev = c->read;
Igor Sysoeva9830112003-05-19 16:39:14 +000023
Igor Sysoevc0edbcc2004-10-21 15:34:38 +000024 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
Igor Sysoev3c3ca172004-01-05 20:55:48 +000025 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
26 "recv: eof:%d, avail:%d, err:%d",
Igor Sysoev98c1cf12004-07-02 15:54:34 +000027 rev->pending_eof, rev->available, rev->kq_errno);
Igor Sysoeva9830112003-05-19 16:39:14 +000028
Igor Sysoev6253ca12003-05-27 12:18:54 +000029 if (rev->available == 0) {
Igor Sysoevcdc46302005-12-07 14:51:31 +000030 if (rev->pending_eof) {
Igor Sysoevd404c972003-10-16 20:19:16 +000031 rev->ready = 0;
Igor Sysoevab0c4f52003-10-28 15:45:41 +000032 rev->eof = 1;
33
34 if (rev->kq_errno) {
35 rev->error = 1;
36 ngx_set_socket_errno(rev->kq_errno);
Igor Sysoev3c3ca172004-01-05 20:55:48 +000037
Igor Sysoeve5035392005-08-30 10:55:07 +000038 return ngx_connection_error(c, rev->kq_errno,
39 "kevent() reported about an closed connection");
Igor Sysoev6253ca12003-05-27 12:18:54 +000040 }
Igor Sysoevab0c4f52003-10-28 15:45:41 +000041
Igor Sysoev6253ca12003-05-27 12:18:54 +000042 return 0;
Igor Sysoevcdc46302005-12-07 14:51:31 +000043
44 } else {
Igor Sysoevc463ece2008-01-31 15:36:33 +000045 rev->ready = 0;
Igor Sysoevcdc46302005-12-07 14:51:31 +000046 return NGX_AGAIN;
Igor Sysoev6253ca12003-05-27 12:18:54 +000047 }
Igor Sysoeva9830112003-05-19 16:39:14 +000048 }
Igor Sysoev6253ca12003-05-27 12:18:54 +000049 }
Igor Sysoeva9830112003-05-19 16:39:14 +000050
Igor Sysoev6253ca12003-05-27 12:18:54 +000051 do {
Igor Sysoeva9830112003-05-19 16:39:14 +000052 n = recv(c->fd, buf, size, 0);
53
Igor Sysoev7af6b162004-02-09 07:46:43 +000054 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
55 "recv: fd:%d %d of %d", c->fd, n, size);
Igor Sysoeva9830112003-05-19 16:39:14 +000056
Igor Sysoev6253ca12003-05-27 12:18:54 +000057 if (n >= 0) {
Igor Sysoevc0edbcc2004-10-21 15:34:38 +000058 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
Igor Sysoev6253ca12003-05-27 12:18:54 +000059 rev->available -= n;
Igor Sysoevab0c4f52003-10-28 15:45:41 +000060
61 /*
Igor Sysoevd3283ff2005-12-05 13:18:09 +000062 * rev->available may be negative here because some additional
Igor Sysoevcdc46302005-12-07 14:51:31 +000063 * bytes may be received between kevent() and recv()
Igor Sysoevab0c4f52003-10-28 15:45:41 +000064 */
65
Igor Sysoev0a280a32003-10-12 16:49:16 +000066 if (rev->available <= 0) {
Igor Sysoev98c1cf12004-07-02 15:54:34 +000067 if (!rev->pending_eof) {
Igor Sysoevd404c972003-10-16 20:19:16 +000068 rev->ready = 0;
69 }
70
Igor Sysoev0a280a32003-10-12 16:49:16 +000071 if (rev->available < 0) {
72 rev->available = 0;
73 }
Igor Sysoev6253ca12003-05-27 12:18:54 +000074 }
Igor Sysoeva9830112003-05-19 16:39:14 +000075
Igor Sysoev9e580192006-02-01 18:22:15 +000076 if (n == 0) {
77
78 /*
79 * on FreeBSD recv() may return 0 on closed socket
80 * even if kqueue reported about available data
81 */
82
Valentin Bartenevcf08ba72013-09-05 16:53:02 +040083 rev->ready = 0;
Igor Sysoev9e580192006-02-01 18:22:15 +000084 rev->eof = 1;
85 rev->available = 0;
86 }
87
Igor Sysoev6253ca12003-05-27 12:18:54 +000088 return n;
89 }
Igor Sysoeva9830112003-05-19 16:39:14 +000090
Valentin Bartenev615d5582013-07-13 03:24:30 +040091 if ((size_t) n < size
92 && !(ngx_event_flags & NGX_USE_GREEDY_EVENT))
93 {
Igor Sysoev6253ca12003-05-27 12:18:54 +000094 rev->ready = 0;
95 }
Igor Sysoeva9830112003-05-19 16:39:14 +000096
Igor Sysoevab0c4f52003-10-28 15:45:41 +000097 if (n == 0) {
98 rev->eof = 1;
99 }
100
Igor Sysoev6253ca12003-05-27 12:18:54 +0000101 return n;
Igor Sysoeva9830112003-05-19 16:39:14 +0000102 }
103
Igor Sysoev7af6b162004-02-09 07:46:43 +0000104 err = ngx_socket_errno;
Igor Sysoeva9830112003-05-19 16:39:14 +0000105
Igor Sysoev7af6b162004-02-09 07:46:43 +0000106 if (err == NGX_EAGAIN || err == NGX_EINTR) {
Igor Sysoev54498db2004-02-11 17:08:49 +0000107 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
Igor Sysoev7af6b162004-02-09 07:46:43 +0000108 "recv() not ready");
109 n = NGX_AGAIN;
Igor Sysoeva9830112003-05-19 16:39:14 +0000110
Igor Sysoev7af6b162004-02-09 07:46:43 +0000111 } else {
112 n = ngx_connection_error(c, err, "recv() failed");
113 break;
114 }
115
116 } while (err == NGX_EINTR);
Igor Sysoev0b2b4cc2003-11-18 08:04:34 +0000117
118 rev->ready = 0;
119
Igor Sysoevaa6936e2010-06-23 16:34:54 +0000120 if (n == NGX_ERROR) {
Igor Sysoev7f9d8942003-11-14 07:20:34 +0000121 rev->error = 1;
122 }
123
Igor Sysoeva9830112003-05-19 16:39:14 +0000124 return n;
125}
Igor Sysoev6253ca12003-05-27 12:18:54 +0000126
Igor Sysoevf6906042004-11-25 16:17:31 +0000127#else /* ! NGX_HAVE_KQUEUE */
Igor Sysoev6253ca12003-05-27 12:18:54 +0000128
Igor Sysoev06187ce2007-12-01 20:25:32 +0000129ssize_t
130ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
Igor Sysoev6253ca12003-05-27 12:18:54 +0000131{
132 ssize_t n;
Igor Sysoev7af6b162004-02-09 07:46:43 +0000133 ngx_err_t err;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000134 ngx_event_t *rev;
135
136 rev = c->read;
137
138 do {
139 n = recv(c->fd, buf, size, 0);
140
Igor Sysoev7af6b162004-02-09 07:46:43 +0000141 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
142 "recv: fd:%d %d of %d", c->fd, n, size);
Igor Sysoev6253ca12003-05-27 12:18:54 +0000143
Igor Sysoev4cec79f2004-04-28 06:14:50 +0000144 if (n == 0) {
145 rev->ready = 0;
146 rev->eof = 1;
147 return n;
Igor Sysoevab0c4f52003-10-28 15:45:41 +0000148
Igor Sysoev4cec79f2004-04-28 06:14:50 +0000149 } else if (n > 0) {
150
151 if ((size_t) n < size
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000152 && !(ngx_event_flags & NGX_USE_GREEDY_EVENT))
Igor Sysoev4cec79f2004-04-28 06:14:50 +0000153 {
154 rev->ready = 0;
Igor Sysoevab0c4f52003-10-28 15:45:41 +0000155 }
156
Igor Sysoev6253ca12003-05-27 12:18:54 +0000157 return n;
158 }
159
Igor Sysoev7af6b162004-02-09 07:46:43 +0000160 err = ngx_socket_errno;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000161
Igor Sysoev7af6b162004-02-09 07:46:43 +0000162 if (err == NGX_EAGAIN || err == NGX_EINTR) {
Igor Sysoev54498db2004-02-11 17:08:49 +0000163 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
Igor Sysoev7af6b162004-02-09 07:46:43 +0000164 "recv() not ready");
165 n = NGX_AGAIN;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000166
Igor Sysoev7af6b162004-02-09 07:46:43 +0000167 } else {
168 n = ngx_connection_error(c, err, "recv() failed");
169 break;
170 }
171
172 } while (err == NGX_EINTR);
Igor Sysoev0b2b4cc2003-11-18 08:04:34 +0000173
174 rev->ready = 0;
175
Igor Sysoevaa6936e2010-06-23 16:34:54 +0000176 if (n == NGX_ERROR) {
Igor Sysoev7f9d8942003-11-14 07:20:34 +0000177 rev->error = 1;
178 }
179
Igor Sysoev6253ca12003-05-27 12:18:54 +0000180 return n;
181}
182
Igor Sysoevf6906042004-11-25 16:17:31 +0000183#endif /* NGX_HAVE_KQUEUE */