comparison src/stream/ngx_stream_handler.c @ 6115:61d7ae76647d

Stream: port from NGINX+.
author Ruslan Ermilov <ru@nginx.com>
date Mon, 20 Apr 2015 13:05:11 +0300
parents
children 187aa751ad62
comparison
equal deleted inserted replaced
6114:4a640716f4e2 6115:61d7ae76647d
1
2 /*
3 * Copyright (C) Roman Arutyunyan
4 * Copyright (C) Nginx, Inc.
5 */
6
7
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_event.h>
11 #include <ngx_stream.h>
12
13
14 static u_char *ngx_stream_log_error(ngx_log_t *log, u_char *buf, size_t len);
15 static void ngx_stream_init_session(ngx_connection_t *c);
16
17 #if (NGX_STREAM_SSL)
18 static void ngx_stream_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c);
19 static void ngx_stream_ssl_handshake_handler(ngx_connection_t *c);
20 #endif
21
22
23 void
24 ngx_stream_init_connection(ngx_connection_t *c)
25 {
26 u_char text[NGX_SOCKADDR_STRLEN];
27 size_t len;
28 ngx_uint_t i;
29 struct sockaddr *sa;
30 ngx_stream_port_t *port;
31 struct sockaddr_in *sin;
32 ngx_stream_in_addr_t *addr;
33 ngx_stream_session_t *s;
34 ngx_stream_addr_conf_t *addr_conf;
35 #if (NGX_HAVE_INET6)
36 struct sockaddr_in6 *sin6;
37 ngx_stream_in6_addr_t *addr6;
38 #endif
39 ngx_stream_core_srv_conf_t *cscf;
40
41 /* find the server configuration for the address:port */
42
43 port = c->listening->servers;
44
45 if (port->naddrs > 1) {
46
47 /*
48 * There are several addresses on this port and one of them
49 * is the "*:port" wildcard so getsockname() is needed to determine
50 * the server address.
51 *
52 * AcceptEx() already gave this address.
53 */
54
55 if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
56 ngx_stream_close_connection(c);
57 return;
58 }
59
60 sa = c->local_sockaddr;
61
62 switch (sa->sa_family) {
63
64 #if (NGX_HAVE_INET6)
65 case AF_INET6:
66 sin6 = (struct sockaddr_in6 *) sa;
67
68 addr6 = port->addrs;
69
70 /* the last address is "*" */
71
72 for (i = 0; i < port->naddrs - 1; i++) {
73 if (ngx_memcmp(&addr6[i].addr6, &sin6->sin6_addr, 16) == 0) {
74 break;
75 }
76 }
77
78 addr_conf = &addr6[i].conf;
79
80 break;
81 #endif
82
83 default: /* AF_INET */
84 sin = (struct sockaddr_in *) sa;
85
86 addr = port->addrs;
87
88 /* the last address is "*" */
89
90 for (i = 0; i < port->naddrs - 1; i++) {
91 if (addr[i].addr == sin->sin_addr.s_addr) {
92 break;
93 }
94 }
95
96 addr_conf = &addr[i].conf;
97
98 break;
99 }
100
101 } else {
102 switch (c->local_sockaddr->sa_family) {
103
104 #if (NGX_HAVE_INET6)
105 case AF_INET6:
106 addr6 = port->addrs;
107 addr_conf = &addr6[0].conf;
108 break;
109 #endif
110
111 default: /* AF_INET */
112 addr = port->addrs;
113 addr_conf = &addr[0].conf;
114 break;
115 }
116 }
117
118 s = ngx_pcalloc(c->pool, sizeof(ngx_stream_session_t));
119 if (s == NULL) {
120 ngx_stream_close_connection(c);
121 return;
122 }
123
124 s->signature = NGX_STREAM_MODULE;
125 s->main_conf = addr_conf->ctx->main_conf;
126 s->srv_conf = addr_conf->ctx->srv_conf;
127
128 s->connection = c;
129 c->data = s;
130
131 cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module);
132
133 ngx_stream_set_connection_log(c, cscf->error_log);
134
135 len = ngx_sock_ntop(c->sockaddr, c->socklen, text, NGX_SOCKADDR_STRLEN, 1);
136
137 ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%uA client %*s connected to %V",
138 c->number, len, text, &addr_conf->addr_text);
139
140 c->log->connection = c->number;
141 c->log->handler = ngx_stream_log_error;
142 c->log->data = s;
143 c->log->action = "initializing connection";
144 c->log_error = NGX_ERROR_INFO;
145
146 #if (NGX_STREAM_SSL)
147 {
148 ngx_stream_ssl_conf_t *sslcf;
149
150 sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module);
151
152 if (addr_conf->ssl) {
153 c->log->action = "SSL handshaking";
154
155 if (sslcf->ssl.ctx == NULL) {
156 ngx_log_error(NGX_LOG_ERR, c->log, 0,
157 "no \"ssl_certificate\" is defined "
158 "in server listening on SSL port");
159 ngx_stream_close_connection(c);
160 return;
161 }
162
163 ngx_stream_ssl_init_connection(&sslcf->ssl, c);
164 return;
165 }
166 }
167 #endif
168
169 ngx_stream_init_session(c);
170 }
171
172
173 static void
174 ngx_stream_init_session(ngx_connection_t *c)
175 {
176 ngx_stream_session_t *s;
177 ngx_stream_core_srv_conf_t *cscf;
178
179 s = c->data;
180 c->log->action = "handling client connection";
181
182 cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module);
183
184 s->ctx = ngx_pcalloc(c->pool, sizeof(void *) * ngx_stream_max_module);
185 if (s->ctx == NULL) {
186 ngx_stream_close_connection(c);
187 return;
188 }
189
190 cscf->handler(s);
191 }
192
193
194 #if (NGX_STREAM_SSL)
195
196 static void
197 ngx_stream_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c)
198 {
199 ngx_stream_session_t *s;
200 ngx_stream_ssl_conf_t *sslcf;
201
202 if (ngx_ssl_create_connection(ssl, c, 0) == NGX_ERROR) {
203 ngx_stream_close_connection(c);
204 return;
205 }
206
207 if (ngx_ssl_handshake(c) == NGX_AGAIN) {
208
209 s = c->data;
210
211 sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module);
212
213 ngx_add_timer(c->read, sslcf->handshake_timeout);
214
215 c->ssl->handler = ngx_stream_ssl_handshake_handler;
216
217 return;
218 }
219
220 ngx_stream_ssl_handshake_handler(c);
221 }
222
223
224 static void
225 ngx_stream_ssl_handshake_handler(ngx_connection_t *c)
226 {
227 if (!c->ssl->handshaked) {
228 ngx_stream_close_connection(c);
229 return;
230 }
231
232 if (c->read->timer_set) {
233 ngx_del_timer(c->read);
234 }
235
236 ngx_stream_init_session(c);
237 }
238
239 #endif
240
241
242 void
243 ngx_stream_close_connection(ngx_connection_t *c)
244 {
245 ngx_pool_t *pool;
246
247 ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
248 "close stream connection: %d", c->fd);
249
250 #if (NGX_STREAM_SSL)
251
252 if (c->ssl) {
253 if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
254 c->ssl->handler = ngx_stream_close_connection;
255 return;
256 }
257 }
258
259 #endif
260
261 #if (NGX_STAT_STUB)
262 (void) ngx_atomic_fetch_add(ngx_stat_active, -1);
263 #endif
264
265 pool = c->pool;
266
267 ngx_close_connection(c);
268
269 ngx_destroy_pool(pool);
270 }
271
272
273 static u_char *
274 ngx_stream_log_error(ngx_log_t *log, u_char *buf, size_t len)
275 {
276 u_char *p;
277 ngx_stream_session_t *s;
278
279 if (log->action) {
280 p = ngx_snprintf(buf, len, " while %s", log->action);
281 len -= p - buf;
282 buf = p;
283 }
284
285 s = log->data;
286
287 p = ngx_snprintf(buf, len, ", client: %V, server: %V",
288 &s->connection->addr_text,
289 &s->connection->listening->addr_text);
290
291 if (s->log_handler) {
292 return s->log_handler(log, p, len);
293 }
294
295 return p;
296 }