blob: 1a14fd963a8b3094fda7ee23fa0716c781a02714 [file] [log] [blame]
Igor Sysoeva9830112003-05-19 16:39:14 +00001
2#include <ngx_config.h>
3#include <ngx_core.h>
Igor Sysoev239baac2003-06-11 15:28:34 +00004#include <ngx_event.h>
Igor Sysoeva9830112003-05-19 16:39:14 +00005
6
Igor Sysoev6253ca12003-05-27 12:18:54 +00007static int ngx_unix_recv_error(ngx_event_t *rev, ngx_err_t err);
8
9
10#if (HAVE_KQUEUE)
11
Igor Sysoeva9830112003-05-19 16:39:14 +000012ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size)
13{
14 ssize_t n;
Igor Sysoev6253ca12003-05-27 12:18:54 +000015 ngx_event_t *rev;
Igor Sysoeva9830112003-05-19 16:39:14 +000016
Igor Sysoev6253ca12003-05-27 12:18:54 +000017 rev = c->read;
Igor Sysoeva9830112003-05-19 16:39:14 +000018
Igor Sysoeva9830112003-05-19 16:39:14 +000019 if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
Igor Sysoevfa73aac2003-05-21 13:28:21 +000020 ngx_log_debug(c->log, "recv: eof:%d, avail:%d, err:%d" _
Igor Sysoevab0c4f52003-10-28 15:45:41 +000021 rev->kq_eof _ rev->available _ rev->kq_errno);
Igor Sysoeva9830112003-05-19 16:39:14 +000022
Igor Sysoev6253ca12003-05-27 12:18:54 +000023 if (rev->available == 0) {
Igor Sysoevab0c4f52003-10-28 15:45:41 +000024 if (rev->kq_eof) {
Igor Sysoevd404c972003-10-16 20:19:16 +000025 rev->ready = 0;
Igor Sysoevab0c4f52003-10-28 15:45:41 +000026 rev->eof = 1;
27
28 if (rev->kq_errno) {
29 rev->error = 1;
30 ngx_set_socket_errno(rev->kq_errno);
31 return ngx_unix_recv_error(rev, rev->kq_errno);
Igor Sysoev6253ca12003-05-27 12:18:54 +000032 }
Igor Sysoevab0c4f52003-10-28 15:45:41 +000033
Igor Sysoev6253ca12003-05-27 12:18:54 +000034 return 0;
Igor Sysoeva9830112003-05-19 16:39:14 +000035
Igor Sysoev6253ca12003-05-27 12:18:54 +000036 } else {
37 return NGX_AGAIN;
38 }
Igor Sysoeva9830112003-05-19 16:39:14 +000039 }
Igor Sysoev6253ca12003-05-27 12:18:54 +000040 }
Igor Sysoeva9830112003-05-19 16:39:14 +000041
Igor Sysoev6253ca12003-05-27 12:18:54 +000042 do {
Igor Sysoeva9830112003-05-19 16:39:14 +000043 n = recv(c->fd, buf, size, 0);
44
Igor Sysoev6253ca12003-05-27 12:18:54 +000045 ngx_log_debug(c->log, "recv: %d:%d" _ n _ size);
Igor Sysoeva9830112003-05-19 16:39:14 +000046
Igor Sysoev6253ca12003-05-27 12:18:54 +000047 if (n >= 0) {
48 if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
49 rev->available -= n;
Igor Sysoevab0c4f52003-10-28 15:45:41 +000050
51 /*
52 * rev->available can be negative here because some additional
53 * bytes can be received between kevent() and recv()
54 */
55
Igor Sysoev0a280a32003-10-12 16:49:16 +000056 if (rev->available <= 0) {
Igor Sysoevab0c4f52003-10-28 15:45:41 +000057 if (!rev->kq_eof) {
Igor Sysoevd404c972003-10-16 20:19:16 +000058 rev->ready = 0;
59 }
60
Igor Sysoev0a280a32003-10-12 16:49:16 +000061 if (rev->available < 0) {
62 rev->available = 0;
63 }
Igor Sysoev6253ca12003-05-27 12:18:54 +000064 }
Igor Sysoeva9830112003-05-19 16:39:14 +000065
Igor Sysoev6253ca12003-05-27 12:18:54 +000066 return n;
67 }
Igor Sysoeva9830112003-05-19 16:39:14 +000068
Igor Sysoev6253ca12003-05-27 12:18:54 +000069 if ((size_t) n < size) {
70 rev->ready = 0;
71 }
Igor Sysoeva9830112003-05-19 16:39:14 +000072
Igor Sysoevab0c4f52003-10-28 15:45:41 +000073 if (n == 0) {
74 rev->eof = 1;
75 }
76
Igor Sysoev6253ca12003-05-27 12:18:54 +000077 return n;
Igor Sysoeva9830112003-05-19 16:39:14 +000078 }
79
Igor Sysoev6253ca12003-05-27 12:18:54 +000080 rev->ready = 0;
Igor Sysoevab0c4f52003-10-28 15:45:41 +000081 rev->error = 1;
Igor Sysoev6253ca12003-05-27 12:18:54 +000082 n = ngx_unix_recv_error(rev, ngx_socket_errno);
Igor Sysoeva9830112003-05-19 16:39:14 +000083
Igor Sysoev6253ca12003-05-27 12:18:54 +000084 } while (n == NGX_EINTR);
Igor Sysoeva9830112003-05-19 16:39:14 +000085
86 return n;
87}
Igor Sysoev6253ca12003-05-27 12:18:54 +000088
89#else /* ! NAVE_KQUEUE */
90
91ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size)
92{
93 ssize_t n;
94 ngx_event_t *rev;
95
96 rev = c->read;
97
98 do {
99 n = recv(c->fd, buf, size, 0);
100
101 ngx_log_debug(c->log, "recv: %d:%d" _ n _ size);
102
103 if (n >= 0) {
104 if ((size_t) n < size) {
105 rev->ready = 0;
106 }
Igor Sysoevab0c4f52003-10-28 15:45:41 +0000107
108 if (n == 0) {
109 rev->eof = 1;
110 }
111
Igor Sysoev6253ca12003-05-27 12:18:54 +0000112 return n;
113 }
114
115 rev->ready = 0;
Igor Sysoevab0c4f52003-10-28 15:45:41 +0000116 rev->error = 1;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000117 n = ngx_unix_recv_error(rev, ngx_socket_errno);
118
119 } while (n == NGX_EINTR);
120
121 return n;
122}
123
124#endif /* NAVE_KQUEUE */
125
126
127static int ngx_unix_recv_error(ngx_event_t *rev, ngx_err_t err)
128{
129 if (err == NGX_ECONNRESET && rev->ignore_econnreset) {
130 return 0;
131 }
132
133 if (err == NGX_EAGAIN) {
134 ngx_log_error(NGX_LOG_INFO, rev->log, err, "recv() returned EAGAIN");
135 return NGX_AGAIN;
136 }
137
138 if (err == NGX_EINTR) {
139 ngx_log_error(NGX_LOG_INFO, rev->log, err, "recv() returned EINTR");
140 return NGX_EINTR;
141 }
142
143 ngx_log_error(NGX_LOG_ERR, rev->log, err, "recv() failed");
144
145 return NGX_ERROR;
146}