Igor Sysoev | a983011 | 2003-05-19 16:39:14 +0000 | [diff] [blame] | 1 | |
Igor Sysoev | d90282d | 2004-09-28 08:34:51 +0000 | [diff] [blame] | 2 | /* |
Igor Sysoev | ff8da91 | 2004-09-29 16:00:49 +0000 | [diff] [blame] | 3 | * Copyright (C) Igor Sysoev |
Igor Sysoev | d90282d | 2004-09-28 08:34:51 +0000 | [diff] [blame] | 4 | */ |
| 5 | |
| 6 | |
Igor Sysoev | a983011 | 2003-05-19 16:39:14 +0000 | [diff] [blame] | 7 | #include <ngx_config.h> |
| 8 | #include <ngx_core.h> |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 9 | #include <ngx_event.h> |
Igor Sysoev | a983011 | 2003-05-19 16:39:14 +0000 | [diff] [blame] | 10 | |
| 11 | |
Igor Sysoev | f690604 | 2004-11-25 16:17:31 +0000 | [diff] [blame^] | 12 | #if (NGX_HAVE_KQUEUE) |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 13 | |
Igor Sysoev | 10a543a | 2004-03-16 07:10:12 +0000 | [diff] [blame] | 14 | ssize_t ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size) |
Igor Sysoev | a983011 | 2003-05-19 16:39:14 +0000 | [diff] [blame] | 15 | { |
| 16 | ssize_t n; |
Igor Sysoev | 7af6b16 | 2004-02-09 07:46:43 +0000 | [diff] [blame] | 17 | ngx_err_t err; |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 18 | ngx_event_t *rev; |
Igor Sysoev | a983011 | 2003-05-19 16:39:14 +0000 | [diff] [blame] | 19 | |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 20 | rev = c->read; |
Igor Sysoev | a983011 | 2003-05-19 16:39:14 +0000 | [diff] [blame] | 21 | |
Igor Sysoev | c0edbcc | 2004-10-21 15:34:38 +0000 | [diff] [blame] | 22 | if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { |
Igor Sysoev | 3c3ca17 | 2004-01-05 20:55:48 +0000 | [diff] [blame] | 23 | ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, |
| 24 | "recv: eof:%d, avail:%d, err:%d", |
Igor Sysoev | 98c1cf1 | 2004-07-02 15:54:34 +0000 | [diff] [blame] | 25 | rev->pending_eof, rev->available, rev->kq_errno); |
Igor Sysoev | a983011 | 2003-05-19 16:39:14 +0000 | [diff] [blame] | 26 | |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 27 | if (rev->available == 0) { |
Igor Sysoev | 98c1cf1 | 2004-07-02 15:54:34 +0000 | [diff] [blame] | 28 | if (rev->pending_eof) { |
Igor Sysoev | d404c97 | 2003-10-16 20:19:16 +0000 | [diff] [blame] | 29 | rev->ready = 0; |
Igor Sysoev | ab0c4f5 | 2003-10-28 15:45:41 +0000 | [diff] [blame] | 30 | rev->eof = 1; |
| 31 | |
Igor Sysoev | 7af6b16 | 2004-02-09 07:46:43 +0000 | [diff] [blame] | 32 | ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno, |
| 33 | "kevent() reported about an closed connection"); |
| 34 | |
Igor Sysoev | ab0c4f5 | 2003-10-28 15:45:41 +0000 | [diff] [blame] | 35 | if (rev->kq_errno) { |
| 36 | rev->error = 1; |
| 37 | ngx_set_socket_errno(rev->kq_errno); |
Igor Sysoev | 3c3ca17 | 2004-01-05 20:55:48 +0000 | [diff] [blame] | 38 | |
| 39 | if (rev->kq_errno == NGX_ECONNRESET |
Igor Sysoev | c7a2f68 | 2004-02-10 16:23:38 +0000 | [diff] [blame] | 40 | && c->log_error == NGX_ERROR_IGNORE_ECONNRESET) |
Igor Sysoev | 3c3ca17 | 2004-01-05 20:55:48 +0000 | [diff] [blame] | 41 | { |
| 42 | return 0; |
| 43 | } |
| 44 | |
| 45 | return NGX_ERROR; |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 46 | } |
Igor Sysoev | ab0c4f5 | 2003-10-28 15:45:41 +0000 | [diff] [blame] | 47 | |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 48 | return 0; |
Igor Sysoev | a983011 | 2003-05-19 16:39:14 +0000 | [diff] [blame] | 49 | |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 50 | } else { |
| 51 | return NGX_AGAIN; |
| 52 | } |
Igor Sysoev | a983011 | 2003-05-19 16:39:14 +0000 | [diff] [blame] | 53 | } |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 54 | } |
Igor Sysoev | a983011 | 2003-05-19 16:39:14 +0000 | [diff] [blame] | 55 | |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 56 | do { |
Igor Sysoev | a983011 | 2003-05-19 16:39:14 +0000 | [diff] [blame] | 57 | n = recv(c->fd, buf, size, 0); |
| 58 | |
Igor Sysoev | 7af6b16 | 2004-02-09 07:46:43 +0000 | [diff] [blame] | 59 | ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, |
| 60 | "recv: fd:%d %d of %d", c->fd, n, size); |
Igor Sysoev | a983011 | 2003-05-19 16:39:14 +0000 | [diff] [blame] | 61 | |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 62 | if (n >= 0) { |
Igor Sysoev | c0edbcc | 2004-10-21 15:34:38 +0000 | [diff] [blame] | 63 | if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 64 | rev->available -= n; |
Igor Sysoev | ab0c4f5 | 2003-10-28 15:45:41 +0000 | [diff] [blame] | 65 | |
| 66 | /* |
| 67 | * rev->available can be negative here because some additional |
| 68 | * bytes can be received between kevent() and recv() |
| 69 | */ |
| 70 | |
Igor Sysoev | 0a280a3 | 2003-10-12 16:49:16 +0000 | [diff] [blame] | 71 | if (rev->available <= 0) { |
Igor Sysoev | 98c1cf1 | 2004-07-02 15:54:34 +0000 | [diff] [blame] | 72 | if (!rev->pending_eof) { |
Igor Sysoev | d404c97 | 2003-10-16 20:19:16 +0000 | [diff] [blame] | 73 | rev->ready = 0; |
| 74 | } |
| 75 | |
Igor Sysoev | 0a280a3 | 2003-10-12 16:49:16 +0000 | [diff] [blame] | 76 | if (rev->available < 0) { |
| 77 | rev->available = 0; |
| 78 | } |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 79 | } |
Igor Sysoev | a983011 | 2003-05-19 16:39:14 +0000 | [diff] [blame] | 80 | |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 81 | return n; |
| 82 | } |
Igor Sysoev | a983011 | 2003-05-19 16:39:14 +0000 | [diff] [blame] | 83 | |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 84 | if ((size_t) n < size) { |
| 85 | rev->ready = 0; |
| 86 | } |
Igor Sysoev | a983011 | 2003-05-19 16:39:14 +0000 | [diff] [blame] | 87 | |
Igor Sysoev | ab0c4f5 | 2003-10-28 15:45:41 +0000 | [diff] [blame] | 88 | if (n == 0) { |
| 89 | rev->eof = 1; |
| 90 | } |
| 91 | |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 92 | return n; |
Igor Sysoev | a983011 | 2003-05-19 16:39:14 +0000 | [diff] [blame] | 93 | } |
| 94 | |
Igor Sysoev | 7af6b16 | 2004-02-09 07:46:43 +0000 | [diff] [blame] | 95 | err = ngx_socket_errno; |
Igor Sysoev | a983011 | 2003-05-19 16:39:14 +0000 | [diff] [blame] | 96 | |
Igor Sysoev | 7af6b16 | 2004-02-09 07:46:43 +0000 | [diff] [blame] | 97 | if (err == NGX_EAGAIN || err == NGX_EINTR) { |
Igor Sysoev | 54498db | 2004-02-11 17:08:49 +0000 | [diff] [blame] | 98 | ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, |
Igor Sysoev | 7af6b16 | 2004-02-09 07:46:43 +0000 | [diff] [blame] | 99 | "recv() not ready"); |
| 100 | n = NGX_AGAIN; |
Igor Sysoev | a983011 | 2003-05-19 16:39:14 +0000 | [diff] [blame] | 101 | |
Igor Sysoev | 7af6b16 | 2004-02-09 07:46:43 +0000 | [diff] [blame] | 102 | } else { |
| 103 | n = ngx_connection_error(c, err, "recv() failed"); |
| 104 | break; |
| 105 | } |
| 106 | |
| 107 | } while (err == NGX_EINTR); |
Igor Sysoev | 0b2b4cc | 2003-11-18 08:04:34 +0000 | [diff] [blame] | 108 | |
| 109 | rev->ready = 0; |
| 110 | |
Igor Sysoev | 7f9d894 | 2003-11-14 07:20:34 +0000 | [diff] [blame] | 111 | if (n == NGX_ERROR){ |
| 112 | rev->error = 1; |
| 113 | } |
| 114 | |
Igor Sysoev | a983011 | 2003-05-19 16:39:14 +0000 | [diff] [blame] | 115 | return n; |
| 116 | } |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 117 | |
Igor Sysoev | f690604 | 2004-11-25 16:17:31 +0000 | [diff] [blame^] | 118 | #else /* ! NGX_HAVE_KQUEUE */ |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 119 | |
Igor Sysoev | c972a3f | 2004-04-02 15:13:20 +0000 | [diff] [blame] | 120 | ssize_t ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size) |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 121 | { |
| 122 | ssize_t n; |
Igor Sysoev | 7af6b16 | 2004-02-09 07:46:43 +0000 | [diff] [blame] | 123 | ngx_err_t err; |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 124 | ngx_event_t *rev; |
| 125 | |
| 126 | rev = c->read; |
| 127 | |
| 128 | do { |
| 129 | n = recv(c->fd, buf, size, 0); |
| 130 | |
Igor Sysoev | 7af6b16 | 2004-02-09 07:46:43 +0000 | [diff] [blame] | 131 | ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, |
| 132 | "recv: fd:%d %d of %d", c->fd, n, size); |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 133 | |
Igor Sysoev | 4cec79f | 2004-04-28 06:14:50 +0000 | [diff] [blame] | 134 | if (n == 0) { |
| 135 | rev->ready = 0; |
| 136 | rev->eof = 1; |
| 137 | return n; |
Igor Sysoev | ab0c4f5 | 2003-10-28 15:45:41 +0000 | [diff] [blame] | 138 | |
Igor Sysoev | 4cec79f | 2004-04-28 06:14:50 +0000 | [diff] [blame] | 139 | } else if (n > 0) { |
| 140 | |
| 141 | if ((size_t) n < size |
Igor Sysoev | c0edbcc | 2004-10-21 15:34:38 +0000 | [diff] [blame] | 142 | && !(ngx_event_flags & NGX_USE_GREEDY_EVENT)) |
Igor Sysoev | 4cec79f | 2004-04-28 06:14:50 +0000 | [diff] [blame] | 143 | { |
| 144 | rev->ready = 0; |
Igor Sysoev | ab0c4f5 | 2003-10-28 15:45:41 +0000 | [diff] [blame] | 145 | } |
| 146 | |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 147 | return n; |
| 148 | } |
| 149 | |
Igor Sysoev | 7af6b16 | 2004-02-09 07:46:43 +0000 | [diff] [blame] | 150 | err = ngx_socket_errno; |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 151 | |
Igor Sysoev | 7af6b16 | 2004-02-09 07:46:43 +0000 | [diff] [blame] | 152 | if (err == NGX_EAGAIN || err == NGX_EINTR) { |
Igor Sysoev | 54498db | 2004-02-11 17:08:49 +0000 | [diff] [blame] | 153 | ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, |
Igor Sysoev | 7af6b16 | 2004-02-09 07:46:43 +0000 | [diff] [blame] | 154 | "recv() not ready"); |
| 155 | n = NGX_AGAIN; |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 156 | |
Igor Sysoev | 7af6b16 | 2004-02-09 07:46:43 +0000 | [diff] [blame] | 157 | } else { |
| 158 | n = ngx_connection_error(c, err, "recv() failed"); |
| 159 | break; |
| 160 | } |
| 161 | |
| 162 | } while (err == NGX_EINTR); |
Igor Sysoev | 0b2b4cc | 2003-11-18 08:04:34 +0000 | [diff] [blame] | 163 | |
| 164 | rev->ready = 0; |
| 165 | |
Igor Sysoev | 7f9d894 | 2003-11-14 07:20:34 +0000 | [diff] [blame] | 166 | if (n == NGX_ERROR){ |
| 167 | rev->error = 1; |
| 168 | } |
| 169 | |
Igor Sysoev | 6253ca1 | 2003-05-27 12:18:54 +0000 | [diff] [blame] | 170 | return n; |
| 171 | } |
| 172 | |
Igor Sysoev | f690604 | 2004-11-25 16:17:31 +0000 | [diff] [blame^] | 173 | #endif /* NGX_HAVE_KQUEUE */ |