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 | 076498e | 2004-04-12 06:10:53 +0000 | [diff] [blame] | 49 | c->number = ngx_atomic_inc(ngx_connection_counter); |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 50 | |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 51 | c->listening->handler(c); |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 52 | |
Igor Sysoev | 1c10462 | 2003-06-03 15:42:58 +0000 | [diff] [blame] | 53 | return; |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 54 | |
| 55 | } |
| 56 | |
| 57 | |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 58 | int ngx_event_post_acceptex(ngx_listening_t *ls, int n) |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 59 | { |
Igor Sysoev | ab9d5fd | 2004-03-05 08:34:24 +0000 | [diff] [blame] | 60 | u_long rcvd; |
| 61 | ngx_int_t i; |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 62 | ngx_err_t err; |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 63 | ngx_event_t *rev, *wev; |
| 64 | ngx_socket_t s; |
| 65 | ngx_connection_t *c; |
| 66 | |
| 67 | for (i = 0; i < n; i++) { |
| 68 | |
| 69 | /* TODO: look up reused sockets */ |
| 70 | |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 71 | s = ngx_socket(ls->family, ls->type, ls->protocol, ls->flags); |
Igor Sysoev | a536298 | 2004-03-04 07:04:55 +0000 | [diff] [blame] | 72 | |
| 73 | ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ls->log, 0, |
| 74 | ngx_socket_n " s:%d fl:%d", s, ls->flags); |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 75 | |
| 76 | if (s == -1) { |
| 77 | ngx_log_error(NGX_LOG_ALERT, ls->log, ngx_socket_errno, |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 78 | ngx_socket_n " for AcceptEx() %s post failed", |
| 79 | ls->addr_text.data); |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 80 | |
| 81 | return NGX_ERROR; |
| 82 | } |
| 83 | |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 84 | /* |
| 85 | * Winsock assignes a socket number divisible by 4 |
| 86 | * so to find a connection we divide a socket number by 4. |
| 87 | */ |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 88 | |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 89 | if (s % 4) { |
| 90 | ngx_log_error(NGX_LOG_EMERG, ls->log, 0, |
Igor Sysoev | 9d63952 | 2003-07-07 06:11:50 +0000 | [diff] [blame] | 91 | ngx_socket_n |
| 92 | " created socket %d, not divisible by 4", s); |
| 93 | |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 94 | exit(1); |
| 95 | } |
| 96 | |
Igor Sysoev | 9d63952 | 2003-07-07 06:11:50 +0000 | [diff] [blame] | 97 | c = &ngx_cycle->connections[s / 4]; |
| 98 | rev = &ngx_cycle->read_events[s / 4]; |
| 99 | wev = &ngx_cycle->write_events[s / 4]; |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 100 | |
Igor Sysoev | 9d63952 | 2003-07-07 06:11:50 +0000 | [diff] [blame] | 101 | ngx_memzero(c, sizeof(ngx_connection_t)); |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 102 | ngx_memzero(rev, sizeof(ngx_event_t)); |
| 103 | ngx_memzero(wev, sizeof(ngx_event_t)); |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 104 | |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 105 | rev->index = wev->index = NGX_INVALID_INDEX; |
| 106 | |
| 107 | rev->ovlp.event = rev; |
| 108 | wev->ovlp.event = wev; |
| 109 | |
| 110 | rev->data = wev->data = c; |
| 111 | c->read = rev; |
| 112 | c->write = wev; |
| 113 | |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 114 | c->listening = ls; |
| 115 | c->fd = s; |
| 116 | |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 117 | c->ctx = ls->ctx; |
| 118 | c->servers = ls->servers; |
| 119 | |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 120 | c->unexpected_eof = 1; |
| 121 | wev->write = 1; |
| 122 | rev->event_handler = ngx_event_acceptex; |
| 123 | |
Igor Sysoev | 68ee8f1 | 2003-10-30 08:51:06 +0000 | [diff] [blame] | 124 | rev->ready = 1; |
| 125 | wev->ready = 1; |
| 126 | |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 127 | ngx_test_null(c->pool, |
| 128 | ngx_create_pool(ls->pool_size, ls->log), |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 129 | NGX_ERROR); |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 130 | |
| 131 | ngx_test_null(c->buffer, |
| 132 | ngx_create_temp_hunk(c->pool, |
| 133 | ls->post_accept_buffer_size |
Igor Sysoev | 68ee8f1 | 2003-10-30 08:51:06 +0000 | [diff] [blame] | 134 | + 2 * (c->listening->socklen + 16)), |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 135 | NGX_ERROR); |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 136 | |
| 137 | ngx_test_null(c->local_sockaddr, ngx_palloc(c->pool, ls->socklen), |
| 138 | NGX_ERROR); |
| 139 | |
| 140 | ngx_test_null(c->sockaddr, ngx_palloc(c->pool, ls->socklen), |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 141 | NGX_ERROR); |
| 142 | |
| 143 | ngx_test_null(c->log, ngx_palloc(c->pool, sizeof(ngx_log_t)), |
| 144 | NGX_ERROR); |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 145 | |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 146 | ngx_memcpy(c->log, ls->log, sizeof(ngx_log_t)); |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 147 | c->read->log = c->write->log = c->log; |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 148 | |
Igor Sysoev | e4a2526 | 2003-06-06 14:59:20 +0000 | [diff] [blame] | 149 | if (ngx_add_event(rev, 0, NGX_IOCP_IO) == NGX_ERROR) { |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 150 | return NGX_ERROR; |
| 151 | } |
| 152 | |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 153 | if (acceptex(ls->fd, s, c->buffer->pos, ls->post_accept_buffer_size, |
| 154 | ls->socklen + 16, ls->socklen + 16, |
| 155 | &rcvd, (LPOVERLAPPED) &rev->ovlp) == 0) |
| 156 | { |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 157 | |
| 158 | err = ngx_socket_errno; |
Igor Sysoev | 239baac | 2003-06-11 15:28:34 +0000 | [diff] [blame] | 159 | if (err != WSA_IO_PENDING) { |
| 160 | ngx_log_error(NGX_LOG_ALERT, ls->log, err, |
| 161 | "AcceptEx() %s falied", ls->addr_text.data); |
| 162 | |
| 163 | return NGX_ERROR; |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 164 | } |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 165 | } |
| 166 | } |
| 167 | |
| 168 | return NGX_OK; |
| 169 | } |