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