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