blob: 369be661aaa0a4d97364ac26d6afbf2e99b859bb [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 Sysoev10a543a2004-03-16 07:10:12 +000014ssize_t ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
Igor Sysoeva9830112003-05-19 16:39:14 +000015{
16 ssize_t n;
Igor Sysoev7af6b162004-02-09 07:46:43 +000017 ngx_err_t err;
Igor Sysoev6253ca12003-05-27 12:18:54 +000018 ngx_event_t *rev;
Igor Sysoeva9830112003-05-19 16:39:14 +000019
Igor Sysoev6253ca12003-05-27 12:18:54 +000020 rev = c->read;
Igor Sysoeva9830112003-05-19 16:39:14 +000021
Igor Sysoevc0edbcc2004-10-21 15:34:38 +000022 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
Igor Sysoev3c3ca172004-01-05 20:55:48 +000023 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
24 "recv: eof:%d, avail:%d, err:%d",
Igor Sysoev98c1cf12004-07-02 15:54:34 +000025 rev->pending_eof, rev->available, rev->kq_errno);
Igor Sysoeva9830112003-05-19 16:39:14 +000026
Igor Sysoev6253ca12003-05-27 12:18:54 +000027 if (rev->available == 0) {
Igor Sysoev98c1cf12004-07-02 15:54:34 +000028 if (rev->pending_eof) {
Igor Sysoevd404c972003-10-16 20:19:16 +000029 rev->ready = 0;
Igor Sysoevab0c4f52003-10-28 15:45:41 +000030 rev->eof = 1;
31
Igor Sysoev7af6b162004-02-09 07:46:43 +000032 ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,
33 "kevent() reported about an closed connection");
34
Igor Sysoevab0c4f52003-10-28 15:45:41 +000035 if (rev->kq_errno) {
36 rev->error = 1;
37 ngx_set_socket_errno(rev->kq_errno);
Igor Sysoev3c3ca172004-01-05 20:55:48 +000038
39 if (rev->kq_errno == NGX_ECONNRESET
Igor Sysoevc7a2f682004-02-10 16:23:38 +000040 && c->log_error == NGX_ERROR_IGNORE_ECONNRESET)
Igor Sysoev3c3ca172004-01-05 20:55:48 +000041 {
42 return 0;
43 }
44
45 return NGX_ERROR;
Igor Sysoev6253ca12003-05-27 12:18:54 +000046 }
Igor Sysoevab0c4f52003-10-28 15:45:41 +000047
Igor Sysoev6253ca12003-05-27 12:18:54 +000048 return 0;
Igor Sysoeva9830112003-05-19 16:39:14 +000049
Igor Sysoev6253ca12003-05-27 12:18:54 +000050 } else {
51 return NGX_AGAIN;
52 }
Igor Sysoeva9830112003-05-19 16:39:14 +000053 }
Igor Sysoev6253ca12003-05-27 12:18:54 +000054 }
Igor Sysoeva9830112003-05-19 16:39:14 +000055
Igor Sysoev6253ca12003-05-27 12:18:54 +000056 do {
Igor Sysoeva9830112003-05-19 16:39:14 +000057 n = recv(c->fd, buf, size, 0);
58
Igor Sysoev7af6b162004-02-09 07:46:43 +000059 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
60 "recv: fd:%d %d of %d", c->fd, n, size);
Igor Sysoeva9830112003-05-19 16:39:14 +000061
Igor Sysoev6253ca12003-05-27 12:18:54 +000062 if (n >= 0) {
Igor Sysoevc0edbcc2004-10-21 15:34:38 +000063 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
Igor Sysoev6253ca12003-05-27 12:18:54 +000064 rev->available -= n;
Igor Sysoevab0c4f52003-10-28 15:45:41 +000065
66 /*
67 * rev->available can be negative here because some additional
68 * bytes can be received between kevent() and recv()
69 */
70
Igor Sysoev0a280a32003-10-12 16:49:16 +000071 if (rev->available <= 0) {
Igor Sysoev98c1cf12004-07-02 15:54:34 +000072 if (!rev->pending_eof) {
Igor Sysoevd404c972003-10-16 20:19:16 +000073 rev->ready = 0;
74 }
75
Igor Sysoev0a280a32003-10-12 16:49:16 +000076 if (rev->available < 0) {
77 rev->available = 0;
78 }
Igor Sysoev6253ca12003-05-27 12:18:54 +000079 }
Igor Sysoeva9830112003-05-19 16:39:14 +000080
Igor Sysoev6253ca12003-05-27 12:18:54 +000081 return n;
82 }
Igor Sysoeva9830112003-05-19 16:39:14 +000083
Igor Sysoev6253ca12003-05-27 12:18:54 +000084 if ((size_t) n < size) {
85 rev->ready = 0;
86 }
Igor Sysoeva9830112003-05-19 16:39:14 +000087
Igor Sysoevab0c4f52003-10-28 15:45:41 +000088 if (n == 0) {
89 rev->eof = 1;
90 }
91
Igor Sysoev6253ca12003-05-27 12:18:54 +000092 return n;
Igor Sysoeva9830112003-05-19 16:39:14 +000093 }
94
Igor Sysoev7af6b162004-02-09 07:46:43 +000095 err = ngx_socket_errno;
Igor Sysoeva9830112003-05-19 16:39:14 +000096
Igor Sysoev7af6b162004-02-09 07:46:43 +000097 if (err == NGX_EAGAIN || err == NGX_EINTR) {
Igor Sysoev54498db2004-02-11 17:08:49 +000098 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
Igor Sysoev7af6b162004-02-09 07:46:43 +000099 "recv() not ready");
100 n = NGX_AGAIN;
Igor Sysoeva9830112003-05-19 16:39:14 +0000101
Igor Sysoev7af6b162004-02-09 07:46:43 +0000102 } else {
103 n = ngx_connection_error(c, err, "recv() failed");
104 break;
105 }
106
107 } while (err == NGX_EINTR);
Igor Sysoev0b2b4cc2003-11-18 08:04:34 +0000108
109 rev->ready = 0;
110
Igor Sysoev7f9d8942003-11-14 07:20:34 +0000111 if (n == NGX_ERROR){
112 rev->error = 1;
113 }
114
Igor Sysoeva9830112003-05-19 16:39:14 +0000115 return n;
116}
Igor Sysoev6253ca12003-05-27 12:18:54 +0000117
Igor Sysoevf6906042004-11-25 16:17:31 +0000118#else /* ! NGX_HAVE_KQUEUE */
Igor Sysoev6253ca12003-05-27 12:18:54 +0000119
Igor Sysoevc972a3f2004-04-02 15:13:20 +0000120ssize_t ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
Igor Sysoev6253ca12003-05-27 12:18:54 +0000121{
122 ssize_t n;
Igor Sysoev7af6b162004-02-09 07:46:43 +0000123 ngx_err_t err;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000124 ngx_event_t *rev;
125
126 rev = c->read;
127
128 do {
129 n = recv(c->fd, buf, size, 0);
130
Igor Sysoev7af6b162004-02-09 07:46:43 +0000131 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
132 "recv: fd:%d %d of %d", c->fd, n, size);
Igor Sysoev6253ca12003-05-27 12:18:54 +0000133
Igor Sysoev4cec79f2004-04-28 06:14:50 +0000134 if (n == 0) {
135 rev->ready = 0;
136 rev->eof = 1;
137 return n;
Igor Sysoevab0c4f52003-10-28 15:45:41 +0000138
Igor Sysoev4cec79f2004-04-28 06:14:50 +0000139 } else if (n > 0) {
140
141 if ((size_t) n < size
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000142 && !(ngx_event_flags & NGX_USE_GREEDY_EVENT))
Igor Sysoev4cec79f2004-04-28 06:14:50 +0000143 {
144 rev->ready = 0;
Igor Sysoevab0c4f52003-10-28 15:45:41 +0000145 }
146
Igor Sysoev6253ca12003-05-27 12:18:54 +0000147 return n;
148 }
149
Igor Sysoev7af6b162004-02-09 07:46:43 +0000150 err = ngx_socket_errno;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000151
Igor Sysoev7af6b162004-02-09 07:46:43 +0000152 if (err == NGX_EAGAIN || err == NGX_EINTR) {
Igor Sysoev54498db2004-02-11 17:08:49 +0000153 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
Igor Sysoev7af6b162004-02-09 07:46:43 +0000154 "recv() not ready");
155 n = NGX_AGAIN;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000156
Igor Sysoev7af6b162004-02-09 07:46:43 +0000157 } else {
158 n = ngx_connection_error(c, err, "recv() failed");
159 break;
160 }
161
162 } while (err == NGX_EINTR);
Igor Sysoev0b2b4cc2003-11-18 08:04:34 +0000163
164 rev->ready = 0;
165
Igor Sysoev7f9d8942003-11-14 07:20:34 +0000166 if (n == NGX_ERROR){
167 rev->error = 1;
168 }
169
Igor Sysoev6253ca12003-05-27 12:18:54 +0000170 return n;
171}
172
Igor Sysoevf6906042004-11-25 16:17:31 +0000173#endif /* NGX_HAVE_KQUEUE */