blob: 7efa5c80dc8a1220d2c1dc719426bff5c4e71467 [file] [log] [blame]
Igor Sysoev73009772003-02-06 17:21:13 +00001
2#include <ngx_config.h>
Igor Sysoev73009772003-02-06 17:21:13 +00003#include <ngx_core.h>
Igor Sysoev73009772003-02-06 17:21:13 +00004#include <ngx_event.h>
Igor Sysoev239baac2003-06-11 15:28:34 +00005#include <nginx.h>
Igor Sysoev73009772003-02-06 17:21:13 +00006
7
Igor Sysoeve4a25262003-06-06 14:59:20 +00008void ngx_event_acceptex(ngx_event_t *rev)
Igor Sysoev73009772003-02-06 17:21:13 +00009{
10 ngx_connection_t *c;
11
Igor Sysoeve4a25262003-06-06 14:59:20 +000012 c = (ngx_connection_t *) rev->data;
Igor Sysoev73009772003-02-06 17:21:13 +000013
Igor Sysoeve4a25262003-06-06 14:59:20 +000014 if (rev->ovlp.error) {
Igor Sysoev239baac2003-06-11 15:28:34 +000015 ngx_log_error(NGX_LOG_CRIT, c->log, rev->ovlp.error,
16 "AcceptEx() %s failed", c->listening->addr_text.data);
Igor Sysoev1c104622003-06-03 15:42:58 +000017 return;
Igor Sysoev73009772003-02-06 17:21:13 +000018 }
19
Igor Sysoeve4a25262003-06-06 14:59:20 +000020 /* SO_UPDATE_ACCEPT_CONTEXT is required for shutdown() to work */
Igor Sysoevfa73aac2003-05-21 13:28:21 +000021
Igor Sysoev1c104622003-06-03 15:42:58 +000022 if (setsockopt(c->fd, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
23 (char *)&c->listening->fd, sizeof(ngx_socket_t)) == -1)
24 {
Igor Sysoev239baac2003-06-11 15:28:34 +000025 ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno,
Igor Sysoev1c104622003-06-03 15:42:58 +000026 "setsockopt(SO_UPDATE_ACCEPT_CONTEXT) failed for %s",
27 c->addr_text.data);
Igor Sysoeve4a25262003-06-06 14:59:20 +000028 } else {
Igor Sysoev239baac2003-06-11 15:28:34 +000029 c->accept_context_updated = 1;
Igor Sysoev1c104622003-06-03 15:42:58 +000030 }
Igor Sysoevfa73aac2003-05-21 13:28:21 +000031
Igor Sysoev239baac2003-06-11 15:28:34 +000032 getacceptexsockaddrs(c->buffer->pos, c->listening->post_accept_buffer_size,
33 c->listening->socklen + 16,
34 c->listening->socklen + 16,
Igor Sysoev73009772003-02-06 17:21:13 +000035 &c->local_sockaddr, &c->local_socklen,
36 &c->sockaddr, &c->socklen);
37
Igor Sysoev239baac2003-06-11 15:28:34 +000038 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 Sysoev73009772003-02-06 17:21:13 +000047 ngx_event_post_acceptex(c->listening, 1);
48
Igor Sysoev076498e2004-04-12 06:10:53 +000049 c->number = ngx_atomic_inc(ngx_connection_counter);
Igor Sysoev73009772003-02-06 17:21:13 +000050
Igor Sysoev239baac2003-06-11 15:28:34 +000051 c->listening->handler(c);
Igor Sysoev73009772003-02-06 17:21:13 +000052
Igor Sysoev1c104622003-06-03 15:42:58 +000053 return;
Igor Sysoev73009772003-02-06 17:21:13 +000054
55}
56
57
Igor Sysoev239baac2003-06-11 15:28:34 +000058int ngx_event_post_acceptex(ngx_listening_t *ls, int n)
Igor Sysoev73009772003-02-06 17:21:13 +000059{
Igor Sysoevab9d5fd2004-03-05 08:34:24 +000060 u_long rcvd;
61 ngx_int_t i;
Igor Sysoev73009772003-02-06 17:21:13 +000062 ngx_err_t err;
Igor Sysoev73009772003-02-06 17:21:13 +000063 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 Sysoev73009772003-02-06 17:21:13 +000071 s = ngx_socket(ls->family, ls->type, ls->protocol, ls->flags);
Igor Sysoeva5362982004-03-04 07:04:55 +000072
73 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ls->log, 0,
74 ngx_socket_n " s:%d fl:%d", s, ls->flags);
Igor Sysoev73009772003-02-06 17:21:13 +000075
76 if (s == -1) {
77 ngx_log_error(NGX_LOG_ALERT, ls->log, ngx_socket_errno,
Igor Sysoev239baac2003-06-11 15:28:34 +000078 ngx_socket_n " for AcceptEx() %s post failed",
79 ls->addr_text.data);
Igor Sysoev73009772003-02-06 17:21:13 +000080
81 return NGX_ERROR;
82 }
83
Igor Sysoev239baac2003-06-11 15:28:34 +000084 /*
85 * Winsock assignes a socket number divisible by 4
86 * so to find a connection we divide a socket number by 4.
87 */
Igor Sysoev73009772003-02-06 17:21:13 +000088
Igor Sysoev239baac2003-06-11 15:28:34 +000089 if (s % 4) {
90 ngx_log_error(NGX_LOG_EMERG, ls->log, 0,
Igor Sysoev9d639522003-07-07 06:11:50 +000091 ngx_socket_n
92 " created socket %d, not divisible by 4", s);
93
Igor Sysoev239baac2003-06-11 15:28:34 +000094 exit(1);
95 }
96
Igor Sysoev9d639522003-07-07 06:11:50 +000097 c = &ngx_cycle->connections[s / 4];
98 rev = &ngx_cycle->read_events[s / 4];
99 wev = &ngx_cycle->write_events[s / 4];
Igor Sysoev73009772003-02-06 17:21:13 +0000100
Igor Sysoev9d639522003-07-07 06:11:50 +0000101 ngx_memzero(c, sizeof(ngx_connection_t));
Igor Sysoev73009772003-02-06 17:21:13 +0000102 ngx_memzero(rev, sizeof(ngx_event_t));
103 ngx_memzero(wev, sizeof(ngx_event_t));
Igor Sysoev73009772003-02-06 17:21:13 +0000104
Igor Sysoev73009772003-02-06 17:21:13 +0000105 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 Sysoev73009772003-02-06 17:21:13 +0000114 c->listening = ls;
115 c->fd = s;
116
Igor Sysoev73009772003-02-06 17:21:13 +0000117 c->ctx = ls->ctx;
118 c->servers = ls->servers;
119
Igor Sysoev239baac2003-06-11 15:28:34 +0000120 c->unexpected_eof = 1;
121 wev->write = 1;
122 rev->event_handler = ngx_event_acceptex;
123
Igor Sysoev68ee8f12003-10-30 08:51:06 +0000124 rev->ready = 1;
125 wev->ready = 1;
126
Igor Sysoev239baac2003-06-11 15:28:34 +0000127 ngx_test_null(c->pool,
128 ngx_create_pool(ls->pool_size, ls->log),
Igor Sysoev73009772003-02-06 17:21:13 +0000129 NGX_ERROR);
Igor Sysoev239baac2003-06-11 15:28:34 +0000130
131 ngx_test_null(c->buffer,
132 ngx_create_temp_hunk(c->pool,
133 ls->post_accept_buffer_size
Igor Sysoev68ee8f12003-10-30 08:51:06 +0000134 + 2 * (c->listening->socklen + 16)),
Igor Sysoev73009772003-02-06 17:21:13 +0000135 NGX_ERROR);
Igor Sysoev239baac2003-06-11 15:28:34 +0000136
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 Sysoev73009772003-02-06 17:21:13 +0000141 NGX_ERROR);
142
143 ngx_test_null(c->log, ngx_palloc(c->pool, sizeof(ngx_log_t)),
144 NGX_ERROR);
Igor Sysoev239baac2003-06-11 15:28:34 +0000145
Igor Sysoev73009772003-02-06 17:21:13 +0000146 ngx_memcpy(c->log, ls->log, sizeof(ngx_log_t));
Igor Sysoev239baac2003-06-11 15:28:34 +0000147 c->read->log = c->write->log = c->log;
Igor Sysoev73009772003-02-06 17:21:13 +0000148
Igor Sysoeve4a25262003-06-06 14:59:20 +0000149 if (ngx_add_event(rev, 0, NGX_IOCP_IO) == NGX_ERROR) {
Igor Sysoev73009772003-02-06 17:21:13 +0000150 return NGX_ERROR;
151 }
152
Igor Sysoev239baac2003-06-11 15:28:34 +0000153 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 Sysoev73009772003-02-06 17:21:13 +0000157
158 err = ngx_socket_errno;
Igor Sysoev239baac2003-06-11 15:28:34 +0000159 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 Sysoev73009772003-02-06 17:21:13 +0000164 }
Igor Sysoev73009772003-02-06 17:21:13 +0000165 }
166 }
167
168 return NGX_OK;
169}