Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 1 | |
| 2 | #include <ngx_config.h> |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 3 | #include <ngx_core.h> |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 4 | #include <ngx_event.h> |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 5 | #include <nginx.h> |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 6 | |
| 7 | |
Igor Sysoev | e4a2526 | 2003-06-06 14:59:20 +0000 | [diff] [blame] | 8 | void ngx_event_acceptex(ngx_event_t *rev) |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 9 | { |
| 10 | ngx_connection_t *c; |
| 11 | |
Igor Sysoev | e4a2526 | 2003-06-06 14:59:20 +0000 | [diff] [blame] | 12 | c = (ngx_connection_t *) rev->data; |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 13 | |
Igor Sysoev | e4a2526 | 2003-06-06 14:59:20 +0000 | [diff] [blame] | 14 | if (rev->ovlp.error) { |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 15 | ngx_log_error(NGX_LOG_CRIT, c->log, rev->ovlp.error, |
| 16 | "AcceptEx() %s failed", c->listening->addr_text.data); |
Igor Sysoev | 1c10462 | 2003-06-03 15:42:58 +0000 | [diff] [blame] | 17 | return; |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 18 | } |
| 19 | |
Igor Sysoev | e4a2526 | 2003-06-06 14:59:20 +0000 | [diff] [blame] | 20 | /* SO_UPDATE_ACCEPT_CONTEXT is required for shutdown() to work */ |
Igor Sysoev | fa73aac | 2003-05-21 13:28:21 +0000 | [diff] [blame] | 21 | |
Igor Sysoev | 1c10462 | 2003-06-03 15:42:58 +0000 | [diff] [blame] | 22 | if (setsockopt(c->fd, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, |
| 23 | (char *)&c->listening->fd, sizeof(ngx_socket_t)) == -1) |
| 24 | { |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 25 | ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno, |
Igor Sysoev | 1c10462 | 2003-06-03 15:42:58 +0000 | [diff] [blame] | 26 | "setsockopt(SO_UPDATE_ACCEPT_CONTEXT) failed for %s", |
| 27 | c->addr_text.data); |
Igor Sysoev | e4a2526 | 2003-06-06 14:59:20 +0000 | [diff] [blame] | 28 | } else { |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 29 | c->accept_context_updated = 1; |
Igor Sysoev | 1c10462 | 2003-06-03 15:42:58 +0000 | [diff] [blame] | 30 | } |
Igor Sysoev | fa73aac | 2003-05-21 13:28:21 +0000 | [diff] [blame] | 31 | |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 32 | getacceptexsockaddrs(c->buffer->pos, c->listening->post_accept_buffer_size, |
| 33 | c->listening->socklen + 16, |
| 34 | c->listening->socklen + 16, |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 35 | &c->local_sockaddr, &c->local_socklen, |
| 36 | &c->sockaddr, &c->socklen); |
| 37 | |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 38 | if (c->listening->post_accept_buffer_size) { |
| 39 | c->buffer->last += rev->available; |
| 40 | c->buffer->end = c->buffer->start |
| 41 | + c->listening->post_accept_buffer_size; |
| 42 | |
| 43 | } else { |
| 44 | c->buffer = NULL; |
| 45 | } |
| 46 | |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 47 | ngx_event_post_acceptex(c->listening, 1); |
| 48 | |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 49 | /* TODO: MT */ |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 50 | c->number = ngx_connection_counter++; |
| 51 | |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 52 | c->listening->handler(c); |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 53 | |
Igor Sysoev | 1c10462 | 2003-06-03 15:42:58 +0000 | [diff] [blame] | 54 | return; |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 55 | |
| 56 | } |
| 57 | |
| 58 | |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 59 | int ngx_event_post_acceptex(ngx_listening_t *ls, int n) |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 60 | { |
| 61 | int i; |
| 62 | u_int rcvd; |
| 63 | ngx_err_t err; |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 64 | ngx_event_t *rev, *wev; |
| 65 | ngx_socket_t s; |
| 66 | ngx_connection_t *c; |
| 67 | |
| 68 | for (i = 0; i < n; i++) { |
| 69 | |
| 70 | /* TODO: look up reused sockets */ |
| 71 | |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 72 | s = ngx_socket(ls->family, ls->type, ls->protocol, ls->flags); |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 73 | ngx_log_debug(ls->log, ngx_socket_n ": %d:%d" _ s _ ls->flags); |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 74 | |
| 75 | if (s == -1) { |
| 76 | ngx_log_error(NGX_LOG_ALERT, ls->log, ngx_socket_errno, |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 77 | ngx_socket_n " for AcceptEx() %s post failed", |
| 78 | ls->addr_text.data); |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 79 | |
| 80 | return NGX_ERROR; |
| 81 | } |
| 82 | |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 83 | /* |
| 84 | * Winsock assignes a socket number divisible by 4 |
| 85 | * so to find a connection we divide a socket number by 4. |
| 86 | */ |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 87 | |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 88 | if (s % 4) { |
| 89 | ngx_log_error(NGX_LOG_EMERG, ls->log, 0, |
Igor Sysoev | 9d63952 | 2003-07-07 06:11:50 +0000 | [diff] [blame] | 90 | ngx_socket_n |
| 91 | " created socket %d, not divisible by 4", s); |
| 92 | |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 93 | exit(1); |
| 94 | } |
| 95 | |
Igor Sysoev | 9d63952 | 2003-07-07 06:11:50 +0000 | [diff] [blame] | 96 | c = &ngx_cycle->connections[s / 4]; |
| 97 | rev = &ngx_cycle->read_events[s / 4]; |
| 98 | wev = &ngx_cycle->write_events[s / 4]; |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 99 | |
Igor Sysoev | 9d63952 | 2003-07-07 06:11:50 +0000 | [diff] [blame] | 100 | ngx_memzero(c, sizeof(ngx_connection_t)); |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 101 | ngx_memzero(rev, sizeof(ngx_event_t)); |
| 102 | ngx_memzero(wev, sizeof(ngx_event_t)); |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 103 | |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 104 | rev->index = wev->index = NGX_INVALID_INDEX; |
| 105 | |
| 106 | rev->ovlp.event = rev; |
| 107 | wev->ovlp.event = wev; |
| 108 | |
| 109 | rev->data = wev->data = c; |
| 110 | c->read = rev; |
| 111 | c->write = wev; |
| 112 | |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 113 | c->listening = ls; |
| 114 | c->fd = s; |
| 115 | |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 116 | c->ctx = ls->ctx; |
| 117 | c->servers = ls->servers; |
| 118 | |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 119 | c->unexpected_eof = 1; |
| 120 | wev->write = 1; |
| 121 | rev->event_handler = ngx_event_acceptex; |
| 122 | |
Igor Sysoev | 68ee8f1 | 2003-10-30 08:51:06 +0000 | [diff] [blame^] | 123 | rev->ready = 1; |
| 124 | wev->ready = 1; |
| 125 | |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 126 | ngx_test_null(c->pool, |
| 127 | ngx_create_pool(ls->pool_size, ls->log), |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 128 | NGX_ERROR); |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 129 | |
| 130 | ngx_test_null(c->buffer, |
| 131 | ngx_create_temp_hunk(c->pool, |
| 132 | ls->post_accept_buffer_size |
Igor Sysoev | 68ee8f1 | 2003-10-30 08:51:06 +0000 | [diff] [blame^] | 133 | + 2 * (c->listening->socklen + 16)), |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 134 | NGX_ERROR); |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 135 | |
| 136 | ngx_test_null(c->local_sockaddr, ngx_palloc(c->pool, ls->socklen), |
| 137 | NGX_ERROR); |
| 138 | |
| 139 | ngx_test_null(c->sockaddr, ngx_palloc(c->pool, ls->socklen), |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 140 | NGX_ERROR); |
| 141 | |
| 142 | ngx_test_null(c->log, ngx_palloc(c->pool, sizeof(ngx_log_t)), |
| 143 | NGX_ERROR); |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 144 | |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 145 | ngx_memcpy(c->log, ls->log, sizeof(ngx_log_t)); |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 146 | c->read->log = c->write->log = c->log; |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 147 | |
Igor Sysoev | e4a2526 | 2003-06-06 14:59:20 +0000 | [diff] [blame] | 148 | if (ngx_add_event(rev, 0, NGX_IOCP_IO) == NGX_ERROR) { |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 149 | return NGX_ERROR; |
| 150 | } |
| 151 | |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 152 | if (acceptex(ls->fd, s, c->buffer->pos, ls->post_accept_buffer_size, |
| 153 | ls->socklen + 16, ls->socklen + 16, |
| 154 | &rcvd, (LPOVERLAPPED) &rev->ovlp) == 0) |
| 155 | { |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 156 | |
| 157 | err = ngx_socket_errno; |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 158 | if (err != WSA_IO_PENDING) { |
| 159 | ngx_log_error(NGX_LOG_ALERT, ls->log, err, |
| 160 | "AcceptEx() %s falied", ls->addr_text.data); |
| 161 | |
| 162 | return NGX_ERROR; |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 163 | } |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 164 | } |
| 165 | } |
| 166 | |
| 167 | return NGX_OK; |
| 168 | } |