blob: c737434b768a185f5ee547c028cf3e61a1918fe0 [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{
61 int i;
62 u_int rcvd;
63 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 Sysoev239baac2003-06-11 15:28:34 +000073 ngx_log_debug(ls->log, ngx_socket_n ": %d:%d" _ s _ ls->flags);
Igor Sysoev73009772003-02-06 17:21:13 +000074
75 if (s == -1) {
76 ngx_log_error(NGX_LOG_ALERT, ls->log, ngx_socket_errno,
Igor Sysoev239baac2003-06-11 15:28:34 +000077 ngx_socket_n " for AcceptEx() %s post failed",
78 ls->addr_text.data);
Igor Sysoev73009772003-02-06 17:21:13 +000079
80 return NGX_ERROR;
81 }
82
Igor Sysoev239baac2003-06-11 15:28:34 +000083 /*
84 * Winsock assignes a socket number divisible by 4
85 * so to find a connection we divide a socket number by 4.
86 */
Igor Sysoev73009772003-02-06 17:21:13 +000087
Igor Sysoev239baac2003-06-11 15:28:34 +000088 if (s % 4) {
89 ngx_log_error(NGX_LOG_EMERG, ls->log, 0,
Igor Sysoev9d639522003-07-07 06:11:50 +000090 ngx_socket_n
91 " created socket %d, not divisible by 4", s);
92
Igor Sysoev239baac2003-06-11 15:28:34 +000093 exit(1);
94 }
95
Igor Sysoev9d639522003-07-07 06:11:50 +000096 c = &ngx_cycle->connections[s / 4];
97 rev = &ngx_cycle->read_events[s / 4];
98 wev = &ngx_cycle->write_events[s / 4];
Igor Sysoev73009772003-02-06 17:21:13 +000099
Igor Sysoev9d639522003-07-07 06:11:50 +0000100 ngx_memzero(c, sizeof(ngx_connection_t));
Igor Sysoev73009772003-02-06 17:21:13 +0000101 ngx_memzero(rev, sizeof(ngx_event_t));
102 ngx_memzero(wev, sizeof(ngx_event_t));
Igor Sysoev73009772003-02-06 17:21:13 +0000103
Igor Sysoev73009772003-02-06 17:21:13 +0000104 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 Sysoev73009772003-02-06 17:21:13 +0000113 c->listening = ls;
114 c->fd = s;
115
Igor Sysoev73009772003-02-06 17:21:13 +0000116 c->ctx = ls->ctx;
117 c->servers = ls->servers;
118
Igor Sysoev239baac2003-06-11 15:28:34 +0000119 c->unexpected_eof = 1;
120 wev->write = 1;
121 rev->event_handler = ngx_event_acceptex;
122
Igor Sysoev68ee8f12003-10-30 08:51:06 +0000123 rev->ready = 1;
124 wev->ready = 1;
125
Igor Sysoev239baac2003-06-11 15:28:34 +0000126 ngx_test_null(c->pool,
127 ngx_create_pool(ls->pool_size, ls->log),
Igor Sysoev73009772003-02-06 17:21:13 +0000128 NGX_ERROR);
Igor Sysoev239baac2003-06-11 15:28:34 +0000129
130 ngx_test_null(c->buffer,
131 ngx_create_temp_hunk(c->pool,
132 ls->post_accept_buffer_size
Igor Sysoev68ee8f12003-10-30 08:51:06 +0000133 + 2 * (c->listening->socklen + 16)),
Igor Sysoev73009772003-02-06 17:21:13 +0000134 NGX_ERROR);
Igor Sysoev239baac2003-06-11 15:28:34 +0000135
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 Sysoev73009772003-02-06 17:21:13 +0000140 NGX_ERROR);
141
142 ngx_test_null(c->log, ngx_palloc(c->pool, sizeof(ngx_log_t)),
143 NGX_ERROR);
Igor Sysoev239baac2003-06-11 15:28:34 +0000144
Igor Sysoev73009772003-02-06 17:21:13 +0000145 ngx_memcpy(c->log, ls->log, sizeof(ngx_log_t));
Igor Sysoev239baac2003-06-11 15:28:34 +0000146 c->read->log = c->write->log = c->log;
Igor Sysoev73009772003-02-06 17:21:13 +0000147
Igor Sysoeve4a25262003-06-06 14:59:20 +0000148 if (ngx_add_event(rev, 0, NGX_IOCP_IO) == NGX_ERROR) {
Igor Sysoev73009772003-02-06 17:21:13 +0000149 return NGX_ERROR;
150 }
151
Igor Sysoev239baac2003-06-11 15:28:34 +0000152 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 Sysoev73009772003-02-06 17:21:13 +0000156
157 err = ngx_socket_errno;
Igor Sysoev239baac2003-06-11 15:28:34 +0000158 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 Sysoev73009772003-02-06 17:21:13 +0000163 }
Igor Sysoev73009772003-02-06 17:21:13 +0000164 }
165 }
166
167 return NGX_OK;
168}