blob: 7923a022b23c3d6b512caa9b8c00d8fe3bf7cd5b [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 Sysoev239baac2003-06-11 15:28:34 +000049 /* TODO: MT */
Igor Sysoev73009772003-02-06 17:21:13 +000050 c->number = ngx_connection_counter++;
51
Igor Sysoev239baac2003-06-11 15:28:34 +000052 c->listening->handler(c);
Igor Sysoev73009772003-02-06 17:21:13 +000053
Igor Sysoev1c104622003-06-03 15:42:58 +000054 return;
Igor Sysoev73009772003-02-06 17:21:13 +000055
56}
57
58
Igor Sysoev239baac2003-06-11 15:28:34 +000059int ngx_event_post_acceptex(ngx_listening_t *ls, int n)
Igor Sysoev73009772003-02-06 17:21:13 +000060{
Igor Sysoevab9d5fd2004-03-05 08:34:24 +000061 u_long rcvd;
62 ngx_int_t i;
Igor Sysoev73009772003-02-06 17:21:13 +000063 ngx_err_t err;
Igor Sysoev73009772003-02-06 17:21:13 +000064 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 Sysoev73009772003-02-06 17:21:13 +000072 s = ngx_socket(ls->family, ls->type, ls->protocol, ls->flags);
Igor Sysoeva5362982004-03-04 07:04:55 +000073
74 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ls->log, 0,
75 ngx_socket_n " s:%d fl:%d", s, ls->flags);
Igor Sysoev73009772003-02-06 17:21:13 +000076
77 if (s == -1) {
78 ngx_log_error(NGX_LOG_ALERT, ls->log, ngx_socket_errno,
Igor Sysoev239baac2003-06-11 15:28:34 +000079 ngx_socket_n " for AcceptEx() %s post failed",
80 ls->addr_text.data);
Igor Sysoev73009772003-02-06 17:21:13 +000081
82 return NGX_ERROR;
83 }
84
Igor Sysoev239baac2003-06-11 15:28:34 +000085 /*
86 * Winsock assignes a socket number divisible by 4
87 * so to find a connection we divide a socket number by 4.
88 */
Igor Sysoev73009772003-02-06 17:21:13 +000089
Igor Sysoev239baac2003-06-11 15:28:34 +000090 if (s % 4) {
91 ngx_log_error(NGX_LOG_EMERG, ls->log, 0,
Igor Sysoev9d639522003-07-07 06:11:50 +000092 ngx_socket_n
93 " created socket %d, not divisible by 4", s);
94
Igor Sysoev239baac2003-06-11 15:28:34 +000095 exit(1);
96 }
97
Igor Sysoev9d639522003-07-07 06:11:50 +000098 c = &ngx_cycle->connections[s / 4];
99 rev = &ngx_cycle->read_events[s / 4];
100 wev = &ngx_cycle->write_events[s / 4];
Igor Sysoev73009772003-02-06 17:21:13 +0000101
Igor Sysoev9d639522003-07-07 06:11:50 +0000102 ngx_memzero(c, sizeof(ngx_connection_t));
Igor Sysoev73009772003-02-06 17:21:13 +0000103 ngx_memzero(rev, sizeof(ngx_event_t));
104 ngx_memzero(wev, sizeof(ngx_event_t));
Igor Sysoev73009772003-02-06 17:21:13 +0000105
Igor Sysoev73009772003-02-06 17:21:13 +0000106 rev->index = wev->index = NGX_INVALID_INDEX;
107
108 rev->ovlp.event = rev;
109 wev->ovlp.event = wev;
110
111 rev->data = wev->data = c;
112 c->read = rev;
113 c->write = wev;
114
Igor Sysoev73009772003-02-06 17:21:13 +0000115 c->listening = ls;
116 c->fd = s;
117
Igor Sysoev73009772003-02-06 17:21:13 +0000118 c->ctx = ls->ctx;
119 c->servers = ls->servers;
120
Igor Sysoev239baac2003-06-11 15:28:34 +0000121 c->unexpected_eof = 1;
122 wev->write = 1;
123 rev->event_handler = ngx_event_acceptex;
124
Igor Sysoev68ee8f12003-10-30 08:51:06 +0000125 rev->ready = 1;
126 wev->ready = 1;
127
Igor Sysoev239baac2003-06-11 15:28:34 +0000128 ngx_test_null(c->pool,
129 ngx_create_pool(ls->pool_size, ls->log),
Igor Sysoev73009772003-02-06 17:21:13 +0000130 NGX_ERROR);
Igor Sysoev239baac2003-06-11 15:28:34 +0000131
132 ngx_test_null(c->buffer,
133 ngx_create_temp_hunk(c->pool,
134 ls->post_accept_buffer_size
Igor Sysoev68ee8f12003-10-30 08:51:06 +0000135 + 2 * (c->listening->socklen + 16)),
Igor Sysoev73009772003-02-06 17:21:13 +0000136 NGX_ERROR);
Igor Sysoev239baac2003-06-11 15:28:34 +0000137
138 ngx_test_null(c->local_sockaddr, ngx_palloc(c->pool, ls->socklen),
139 NGX_ERROR);
140
141 ngx_test_null(c->sockaddr, ngx_palloc(c->pool, ls->socklen),
Igor Sysoev73009772003-02-06 17:21:13 +0000142 NGX_ERROR);
143
144 ngx_test_null(c->log, ngx_palloc(c->pool, sizeof(ngx_log_t)),
145 NGX_ERROR);
Igor Sysoev239baac2003-06-11 15:28:34 +0000146
Igor Sysoev73009772003-02-06 17:21:13 +0000147 ngx_memcpy(c->log, ls->log, sizeof(ngx_log_t));
Igor Sysoev239baac2003-06-11 15:28:34 +0000148 c->read->log = c->write->log = c->log;
Igor Sysoev73009772003-02-06 17:21:13 +0000149
Igor Sysoeve4a25262003-06-06 14:59:20 +0000150 if (ngx_add_event(rev, 0, NGX_IOCP_IO) == NGX_ERROR) {
Igor Sysoev73009772003-02-06 17:21:13 +0000151 return NGX_ERROR;
152 }
153
Igor Sysoev239baac2003-06-11 15:28:34 +0000154 if (acceptex(ls->fd, s, c->buffer->pos, ls->post_accept_buffer_size,
155 ls->socklen + 16, ls->socklen + 16,
156 &rcvd, (LPOVERLAPPED) &rev->ovlp) == 0)
157 {
Igor Sysoev73009772003-02-06 17:21:13 +0000158
159 err = ngx_socket_errno;
Igor Sysoev239baac2003-06-11 15:28:34 +0000160 if (err != WSA_IO_PENDING) {
161 ngx_log_error(NGX_LOG_ALERT, ls->log, err,
162 "AcceptEx() %s falied", ls->addr_text.data);
163
164 return NGX_ERROR;
Igor Sysoev73009772003-02-06 17:21:13 +0000165 }
Igor Sysoev73009772003-02-06 17:21:13 +0000166 }
167 }
168
169 return NGX_OK;
170}