Mercurial > hg > nginx-quic
annotate src/stream/ngx_stream.c @ 6765:85c3740b6745 stable-1.10
HTTP/2: flushing of the SSL buffer in transition to the idle state.
It fixes potential connection leak if some unsent data was left in the SSL
buffer. Particularly, that could happen when a client canceled the stream
after the HEADERS frame has already been created. In this case no other
frames might be produced and the HEADERS frame alone didn't flush the buffer.
author | Valentin Bartenev <vbart@nginx.com> |
---|---|
date | Tue, 19 Jul 2016 20:34:17 +0300 |
parents | 8f038068f4bc |
children | c90cf79d0e1d |
rev | line source |
---|---|
6115 | 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 char *ngx_stream_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); | |
15 static ngx_int_t ngx_stream_add_ports(ngx_conf_t *cf, ngx_array_t *ports, | |
16 ngx_stream_listen_t *listen); | |
17 static char *ngx_stream_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports); | |
18 static ngx_int_t ngx_stream_add_addrs(ngx_conf_t *cf, ngx_stream_port_t *stport, | |
19 ngx_stream_conf_addr_t *addr); | |
20 #if (NGX_HAVE_INET6) | |
21 static ngx_int_t ngx_stream_add_addrs6(ngx_conf_t *cf, | |
22 ngx_stream_port_t *stport, ngx_stream_conf_addr_t *addr); | |
23 #endif | |
24 static ngx_int_t ngx_stream_cmp_conf_addrs(const void *one, const void *two); | |
25 | |
26 | |
27 ngx_uint_t ngx_stream_max_module; | |
28 | |
29 | |
30 static ngx_command_t ngx_stream_commands[] = { | |
31 | |
32 { ngx_string("stream"), | |
33 NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, | |
34 ngx_stream_block, | |
35 0, | |
36 0, | |
37 NULL }, | |
38 | |
39 ngx_null_command | |
40 }; | |
41 | |
42 | |
43 static ngx_core_module_t ngx_stream_module_ctx = { | |
44 ngx_string("stream"), | |
45 NULL, | |
46 NULL | |
47 }; | |
48 | |
49 | |
50 ngx_module_t ngx_stream_module = { | |
51 NGX_MODULE_V1, | |
52 &ngx_stream_module_ctx, /* module context */ | |
53 ngx_stream_commands, /* module directives */ | |
54 NGX_CORE_MODULE, /* module type */ | |
55 NULL, /* init master */ | |
56 NULL, /* init module */ | |
57 NULL, /* init process */ | |
58 NULL, /* init thread */ | |
59 NULL, /* exit thread */ | |
60 NULL, /* exit process */ | |
61 NULL, /* exit master */ | |
62 NGX_MODULE_V1_PADDING | |
63 }; | |
64 | |
65 | |
66 static char * | |
67 ngx_stream_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
68 { | |
69 char *rv; | |
70 ngx_uint_t i, m, mi, s; | |
71 ngx_conf_t pcf; | |
72 ngx_array_t ports; | |
73 ngx_stream_listen_t *listen; | |
74 ngx_stream_module_t *module; | |
75 ngx_stream_conf_ctx_t *ctx; | |
76 ngx_stream_core_srv_conf_t **cscfp; | |
77 ngx_stream_core_main_conf_t *cmcf; | |
78 | |
6193
78c06e5e1d76
Disabled duplicate http, mail, and stream blocks.
Vladimir Homutov <vl@nginx.com>
parents:
6174
diff
changeset
|
79 if (*(ngx_stream_conf_ctx_t **) conf) { |
78c06e5e1d76
Disabled duplicate http, mail, and stream blocks.
Vladimir Homutov <vl@nginx.com>
parents:
6174
diff
changeset
|
80 return "is duplicate"; |
78c06e5e1d76
Disabled duplicate http, mail, and stream blocks.
Vladimir Homutov <vl@nginx.com>
parents:
6174
diff
changeset
|
81 } |
78c06e5e1d76
Disabled duplicate http, mail, and stream blocks.
Vladimir Homutov <vl@nginx.com>
parents:
6174
diff
changeset
|
82 |
6115 | 83 /* the main stream context */ |
84 | |
85 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_stream_conf_ctx_t)); | |
86 if (ctx == NULL) { | |
87 return NGX_CONF_ERROR; | |
88 } | |
89 | |
90 *(ngx_stream_conf_ctx_t **) conf = ctx; | |
91 | |
92 /* count the number of the stream modules and set up their indices */ | |
93 | |
6378
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6193
diff
changeset
|
94 ngx_stream_max_module = ngx_count_modules(cf->cycle, NGX_STREAM_MODULE); |
6115 | 95 |
96 | |
97 /* the stream main_conf context, it's the same in the all stream contexts */ | |
98 | |
99 ctx->main_conf = ngx_pcalloc(cf->pool, | |
100 sizeof(void *) * ngx_stream_max_module); | |
101 if (ctx->main_conf == NULL) { | |
102 return NGX_CONF_ERROR; | |
103 } | |
104 | |
105 | |
106 /* | |
107 * the stream null srv_conf context, it is used to merge | |
108 * the server{}s' srv_conf's | |
109 */ | |
110 | |
111 ctx->srv_conf = ngx_pcalloc(cf->pool, | |
112 sizeof(void *) * ngx_stream_max_module); | |
113 if (ctx->srv_conf == NULL) { | |
114 return NGX_CONF_ERROR; | |
115 } | |
116 | |
117 | |
118 /* | |
119 * create the main_conf's and the null srv_conf's of the all stream modules | |
120 */ | |
121 | |
6379
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6378
diff
changeset
|
122 for (m = 0; cf->cycle->modules[m]; m++) { |
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6378
diff
changeset
|
123 if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) { |
6115 | 124 continue; |
125 } | |
126 | |
6379
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6378
diff
changeset
|
127 module = cf->cycle->modules[m]->ctx; |
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6378
diff
changeset
|
128 mi = cf->cycle->modules[m]->ctx_index; |
6115 | 129 |
130 if (module->create_main_conf) { | |
131 ctx->main_conf[mi] = module->create_main_conf(cf); | |
132 if (ctx->main_conf[mi] == NULL) { | |
133 return NGX_CONF_ERROR; | |
134 } | |
135 } | |
136 | |
137 if (module->create_srv_conf) { | |
138 ctx->srv_conf[mi] = module->create_srv_conf(cf); | |
139 if (ctx->srv_conf[mi] == NULL) { | |
140 return NGX_CONF_ERROR; | |
141 } | |
142 } | |
143 } | |
144 | |
145 | |
146 /* parse inside the stream{} block */ | |
147 | |
148 pcf = *cf; | |
149 cf->ctx = ctx; | |
150 | |
151 cf->module_type = NGX_STREAM_MODULE; | |
152 cf->cmd_type = NGX_STREAM_MAIN_CONF; | |
153 rv = ngx_conf_parse(cf, NULL); | |
154 | |
155 if (rv != NGX_CONF_OK) { | |
156 *cf = pcf; | |
157 return rv; | |
158 } | |
159 | |
160 | |
161 /* init stream{} main_conf's, merge the server{}s' srv_conf's */ | |
162 | |
163 cmcf = ctx->main_conf[ngx_stream_core_module.ctx_index]; | |
164 cscfp = cmcf->servers.elts; | |
165 | |
6379
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6378
diff
changeset
|
166 for (m = 0; cf->cycle->modules[m]; m++) { |
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6378
diff
changeset
|
167 if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) { |
6115 | 168 continue; |
169 } | |
170 | |
6379
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6378
diff
changeset
|
171 module = cf->cycle->modules[m]->ctx; |
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6378
diff
changeset
|
172 mi = cf->cycle->modules[m]->ctx_index; |
6115 | 173 |
174 /* init stream{} main_conf's */ | |
175 | |
176 cf->ctx = ctx; | |
177 | |
178 if (module->init_main_conf) { | |
179 rv = module->init_main_conf(cf, ctx->main_conf[mi]); | |
180 if (rv != NGX_CONF_OK) { | |
181 *cf = pcf; | |
182 return rv; | |
183 } | |
184 } | |
185 | |
186 for (s = 0; s < cmcf->servers.nelts; s++) { | |
187 | |
188 /* merge the server{}s' srv_conf's */ | |
189 | |
190 cf->ctx = cscfp[s]->ctx; | |
191 | |
192 if (module->merge_srv_conf) { | |
193 rv = module->merge_srv_conf(cf, | |
194 ctx->srv_conf[mi], | |
195 cscfp[s]->ctx->srv_conf[mi]); | |
196 if (rv != NGX_CONF_OK) { | |
197 *cf = pcf; | |
198 return rv; | |
199 } | |
200 } | |
201 } | |
202 } | |
203 | |
6379
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6378
diff
changeset
|
204 for (m = 0; cf->cycle->modules[m]; m++) { |
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6378
diff
changeset
|
205 if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) { |
6174
68c106e6fa0a
Stream: added postconfiguration method to stream modules.
Vladimir Homutov <vl@nginx.com>
parents:
6172
diff
changeset
|
206 continue; |
68c106e6fa0a
Stream: added postconfiguration method to stream modules.
Vladimir Homutov <vl@nginx.com>
parents:
6172
diff
changeset
|
207 } |
68c106e6fa0a
Stream: added postconfiguration method to stream modules.
Vladimir Homutov <vl@nginx.com>
parents:
6172
diff
changeset
|
208 |
6379
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6378
diff
changeset
|
209 module = cf->cycle->modules[m]->ctx; |
6174
68c106e6fa0a
Stream: added postconfiguration method to stream modules.
Vladimir Homutov <vl@nginx.com>
parents:
6172
diff
changeset
|
210 |
68c106e6fa0a
Stream: added postconfiguration method to stream modules.
Vladimir Homutov <vl@nginx.com>
parents:
6172
diff
changeset
|
211 if (module->postconfiguration) { |
68c106e6fa0a
Stream: added postconfiguration method to stream modules.
Vladimir Homutov <vl@nginx.com>
parents:
6172
diff
changeset
|
212 if (module->postconfiguration(cf) != NGX_OK) { |
68c106e6fa0a
Stream: added postconfiguration method to stream modules.
Vladimir Homutov <vl@nginx.com>
parents:
6172
diff
changeset
|
213 return NGX_CONF_ERROR; |
68c106e6fa0a
Stream: added postconfiguration method to stream modules.
Vladimir Homutov <vl@nginx.com>
parents:
6172
diff
changeset
|
214 } |
68c106e6fa0a
Stream: added postconfiguration method to stream modules.
Vladimir Homutov <vl@nginx.com>
parents:
6172
diff
changeset
|
215 } |
68c106e6fa0a
Stream: added postconfiguration method to stream modules.
Vladimir Homutov <vl@nginx.com>
parents:
6172
diff
changeset
|
216 } |
68c106e6fa0a
Stream: added postconfiguration method to stream modules.
Vladimir Homutov <vl@nginx.com>
parents:
6172
diff
changeset
|
217 |
6115 | 218 *cf = pcf; |
219 | |
220 | |
221 if (ngx_array_init(&ports, cf->temp_pool, 4, sizeof(ngx_stream_conf_port_t)) | |
222 != NGX_OK) | |
223 { | |
224 return NGX_CONF_ERROR; | |
225 } | |
226 | |
227 listen = cmcf->listen.elts; | |
228 | |
229 for (i = 0; i < cmcf->listen.nelts; i++) { | |
230 if (ngx_stream_add_ports(cf, &ports, &listen[i]) != NGX_OK) { | |
231 return NGX_CONF_ERROR; | |
232 } | |
233 } | |
234 | |
235 return ngx_stream_optimize_servers(cf, &ports); | |
236 } | |
237 | |
238 | |
239 static ngx_int_t | |
240 ngx_stream_add_ports(ngx_conf_t *cf, ngx_array_t *ports, | |
241 ngx_stream_listen_t *listen) | |
242 { | |
243 in_port_t p; | |
244 ngx_uint_t i; | |
245 struct sockaddr *sa; | |
246 struct sockaddr_in *sin; | |
247 ngx_stream_conf_port_t *port; | |
248 ngx_stream_conf_addr_t *addr; | |
249 #if (NGX_HAVE_INET6) | |
250 struct sockaddr_in6 *sin6; | |
251 #endif | |
252 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
253 sa = &listen->u.sockaddr; |
6115 | 254 |
255 switch (sa->sa_family) { | |
256 | |
257 #if (NGX_HAVE_INET6) | |
258 case AF_INET6: | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
259 sin6 = &listen->u.sockaddr_in6; |
6115 | 260 p = sin6->sin6_port; |
261 break; | |
262 #endif | |
263 | |
264 #if (NGX_HAVE_UNIX_DOMAIN) | |
265 case AF_UNIX: | |
266 p = 0; | |
267 break; | |
268 #endif | |
269 | |
270 default: /* AF_INET */ | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
271 sin = &listen->u.sockaddr_in; |
6115 | 272 p = sin->sin_port; |
273 break; | |
274 } | |
275 | |
276 port = ports->elts; | |
277 for (i = 0; i < ports->nelts; i++) { | |
278 | |
6436 | 279 if (p == port[i].port |
280 && listen->type == port[i].type | |
281 && sa->sa_family == port[i].family) | |
282 { | |
6115 | 283 /* a port is already in the port list */ |
284 | |
285 port = &port[i]; | |
286 goto found; | |
287 } | |
288 } | |
289 | |
290 /* add a port to the port list */ | |
291 | |
292 port = ngx_array_push(ports); | |
293 if (port == NULL) { | |
294 return NGX_ERROR; | |
295 } | |
296 | |
297 port->family = sa->sa_family; | |
6436 | 298 port->type = listen->type; |
6115 | 299 port->port = p; |
300 | |
301 if (ngx_array_init(&port->addrs, cf->temp_pool, 2, | |
302 sizeof(ngx_stream_conf_addr_t)) | |
303 != NGX_OK) | |
304 { | |
305 return NGX_ERROR; | |
306 } | |
307 | |
308 found: | |
309 | |
310 addr = ngx_array_push(&port->addrs); | |
311 if (addr == NULL) { | |
312 return NGX_ERROR; | |
313 } | |
314 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
315 addr->opt = *listen; |
6115 | 316 |
317 return NGX_OK; | |
318 } | |
319 | |
320 | |
321 static char * | |
322 ngx_stream_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports) | |
323 { | |
324 ngx_uint_t i, p, last, bind_wildcard; | |
325 ngx_listening_t *ls; | |
326 ngx_stream_port_t *stport; | |
327 ngx_stream_conf_port_t *port; | |
328 ngx_stream_conf_addr_t *addr; | |
329 ngx_stream_core_srv_conf_t *cscf; | |
330 | |
331 port = ports->elts; | |
332 for (p = 0; p < ports->nelts; p++) { | |
333 | |
334 ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts, | |
335 sizeof(ngx_stream_conf_addr_t), ngx_stream_cmp_conf_addrs); | |
336 | |
337 addr = port[p].addrs.elts; | |
338 last = port[p].addrs.nelts; | |
339 | |
340 /* | |
341 * if there is the binding to the "*:port" then we need to bind() | |
342 * to the "*:port" only and ignore the other bindings | |
343 */ | |
344 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
345 if (addr[last - 1].opt.wildcard) { |
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
346 addr[last - 1].opt.bind = 1; |
6115 | 347 bind_wildcard = 1; |
348 | |
349 } else { | |
350 bind_wildcard = 0; | |
351 } | |
352 | |
353 i = 0; | |
354 | |
355 while (i < last) { | |
356 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
357 if (bind_wildcard && !addr[i].opt.bind) { |
6115 | 358 i++; |
359 continue; | |
360 } | |
361 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
362 ls = ngx_create_listening(cf, &addr[i].opt.u.sockaddr, |
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
363 addr[i].opt.socklen); |
6115 | 364 if (ls == NULL) { |
365 return NGX_CONF_ERROR; | |
366 } | |
367 | |
368 ls->addr_ntop = 1; | |
369 ls->handler = ngx_stream_init_connection; | |
370 ls->pool_size = 256; | |
6436 | 371 ls->type = addr[i].opt.type; |
6115 | 372 |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
373 cscf = addr->opt.ctx->srv_conf[ngx_stream_core_module.ctx_index]; |
6129
187aa751ad62
Core: the ngx_set_connection_log() macro.
Vladimir Homutov <vl@nginx.com>
parents:
6115
diff
changeset
|
374 |
6115 | 375 ls->logp = cscf->error_log; |
376 ls->log.data = &ls->addr_text; | |
377 ls->log.handler = ngx_accept_log_error; | |
378 | |
6172 | 379 ls->backlog = addr[i].opt.backlog; |
380 | |
6436 | 381 ls->wildcard = addr[i].opt.wildcard; |
382 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
383 ls->keepalive = addr[i].opt.so_keepalive; |
6115 | 384 #if (NGX_HAVE_KEEPALIVE_TUNABLE) |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
385 ls->keepidle = addr[i].opt.tcp_keepidle; |
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
386 ls->keepintvl = addr[i].opt.tcp_keepintvl; |
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
387 ls->keepcnt = addr[i].opt.tcp_keepcnt; |
6115 | 388 #endif |
389 | |
390 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
391 ls->ipv6only = addr[i].opt.ipv6only; |
6115 | 392 #endif |
393 | |
6169
f654addf0eea
Stream: fixed "reuseport" to actually work.
Ruslan Ermilov <ru@nginx.com>
parents:
6153
diff
changeset
|
394 #if (NGX_HAVE_REUSEPORT) |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
395 ls->reuseport = addr[i].opt.reuseport; |
6169
f654addf0eea
Stream: fixed "reuseport" to actually work.
Ruslan Ermilov <ru@nginx.com>
parents:
6153
diff
changeset
|
396 #endif |
f654addf0eea
Stream: fixed "reuseport" to actually work.
Ruslan Ermilov <ru@nginx.com>
parents:
6153
diff
changeset
|
397 |
6115 | 398 stport = ngx_palloc(cf->pool, sizeof(ngx_stream_port_t)); |
399 if (stport == NULL) { | |
400 return NGX_CONF_ERROR; | |
401 } | |
402 | |
403 ls->servers = stport; | |
404 | |
6152
3c344ea7d88b
Simplified ngx_http_init_listening().
Maxim Dounin <mdounin@mdounin.ru>
parents:
6129
diff
changeset
|
405 stport->naddrs = i + 1; |
6115 | 406 |
407 switch (ls->sockaddr->sa_family) { | |
408 #if (NGX_HAVE_INET6) | |
409 case AF_INET6: | |
410 if (ngx_stream_add_addrs6(cf, stport, addr) != NGX_OK) { | |
411 return NGX_CONF_ERROR; | |
412 } | |
413 break; | |
414 #endif | |
415 default: /* AF_INET */ | |
416 if (ngx_stream_add_addrs(cf, stport, addr) != NGX_OK) { | |
417 return NGX_CONF_ERROR; | |
418 } | |
419 break; | |
420 } | |
421 | |
6153
4f6efabcb09b
The "reuseport" option of the "listen" directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6152
diff
changeset
|
422 if (ngx_clone_listening(cf, ls) != NGX_OK) { |
4f6efabcb09b
The "reuseport" option of the "listen" directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6152
diff
changeset
|
423 return NGX_CONF_ERROR; |
4f6efabcb09b
The "reuseport" option of the "listen" directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6152
diff
changeset
|
424 } |
4f6efabcb09b
The "reuseport" option of the "listen" directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6152
diff
changeset
|
425 |
6115 | 426 addr++; |
427 last--; | |
428 } | |
429 } | |
430 | |
431 return NGX_CONF_OK; | |
432 } | |
433 | |
434 | |
435 static ngx_int_t | |
436 ngx_stream_add_addrs(ngx_conf_t *cf, ngx_stream_port_t *stport, | |
437 ngx_stream_conf_addr_t *addr) | |
438 { | |
439 u_char *p; | |
440 size_t len; | |
441 ngx_uint_t i; | |
442 struct sockaddr_in *sin; | |
443 ngx_stream_in_addr_t *addrs; | |
444 u_char buf[NGX_SOCKADDR_STRLEN]; | |
445 | |
446 stport->addrs = ngx_pcalloc(cf->pool, | |
447 stport->naddrs * sizeof(ngx_stream_in_addr_t)); | |
448 if (stport->addrs == NULL) { | |
449 return NGX_ERROR; | |
450 } | |
451 | |
452 addrs = stport->addrs; | |
453 | |
454 for (i = 0; i < stport->naddrs; i++) { | |
455 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
456 sin = &addr[i].opt.u.sockaddr_in; |
6115 | 457 addrs[i].addr = sin->sin_addr.s_addr; |
458 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
459 addrs[i].conf.ctx = addr[i].opt.ctx; |
6115 | 460 #if (NGX_STREAM_SSL) |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
461 addrs[i].conf.ssl = addr[i].opt.ssl; |
6115 | 462 #endif |
463 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
464 len = ngx_sock_ntop(&addr[i].opt.u.sockaddr, addr[i].opt.socklen, buf, |
6115 | 465 NGX_SOCKADDR_STRLEN, 1); |
466 | |
467 p = ngx_pnalloc(cf->pool, len); | |
468 if (p == NULL) { | |
469 return NGX_ERROR; | |
470 } | |
471 | |
472 ngx_memcpy(p, buf, len); | |
473 | |
474 addrs[i].conf.addr_text.len = len; | |
475 addrs[i].conf.addr_text.data = p; | |
476 } | |
477 | |
478 return NGX_OK; | |
479 } | |
480 | |
481 | |
482 #if (NGX_HAVE_INET6) | |
483 | |
484 static ngx_int_t | |
485 ngx_stream_add_addrs6(ngx_conf_t *cf, ngx_stream_port_t *stport, | |
486 ngx_stream_conf_addr_t *addr) | |
487 { | |
488 u_char *p; | |
489 size_t len; | |
490 ngx_uint_t i; | |
491 struct sockaddr_in6 *sin6; | |
492 ngx_stream_in6_addr_t *addrs6; | |
493 u_char buf[NGX_SOCKADDR_STRLEN]; | |
494 | |
495 stport->addrs = ngx_pcalloc(cf->pool, | |
496 stport->naddrs * sizeof(ngx_stream_in6_addr_t)); | |
497 if (stport->addrs == NULL) { | |
498 return NGX_ERROR; | |
499 } | |
500 | |
501 addrs6 = stport->addrs; | |
502 | |
503 for (i = 0; i < stport->naddrs; i++) { | |
504 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
505 sin6 = &addr[i].opt.u.sockaddr_in6; |
6115 | 506 addrs6[i].addr6 = sin6->sin6_addr; |
507 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
508 addrs6[i].conf.ctx = addr[i].opt.ctx; |
6115 | 509 #if (NGX_STREAM_SSL) |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
510 addrs6[i].conf.ssl = addr[i].opt.ssl; |
6115 | 511 #endif |
512 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
513 len = ngx_sock_ntop(&addr[i].opt.u.sockaddr, addr[i].opt.socklen, buf, |
6115 | 514 NGX_SOCKADDR_STRLEN, 1); |
515 | |
516 p = ngx_pnalloc(cf->pool, len); | |
517 if (p == NULL) { | |
518 return NGX_ERROR; | |
519 } | |
520 | |
521 ngx_memcpy(p, buf, len); | |
522 | |
523 addrs6[i].conf.addr_text.len = len; | |
524 addrs6[i].conf.addr_text.data = p; | |
525 } | |
526 | |
527 return NGX_OK; | |
528 } | |
529 | |
530 #endif | |
531 | |
532 | |
533 static ngx_int_t | |
534 ngx_stream_cmp_conf_addrs(const void *one, const void *two) | |
535 { | |
536 ngx_stream_conf_addr_t *first, *second; | |
537 | |
538 first = (ngx_stream_conf_addr_t *) one; | |
539 second = (ngx_stream_conf_addr_t *) two; | |
540 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
541 if (first->opt.wildcard) { |
6115 | 542 /* a wildcard must be the last resort, shift it to the end */ |
543 return 1; | |
544 } | |
545 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
546 if (second->opt.wildcard) { |
6115 | 547 /* a wildcard must be the last resort, shift it to the end */ |
548 return -1; | |
549 } | |
550 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
551 if (first->opt.bind && !second->opt.bind) { |
6115 | 552 /* shift explicit bind()ed addresses to the start */ |
553 return -1; | |
554 } | |
555 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
556 if (!first->opt.bind && second->opt.bind) { |
6115 | 557 /* shift explicit bind()ed addresses to the start */ |
558 return 1; | |
559 } | |
560 | |
561 /* do not sort by default */ | |
562 | |
563 return 0; | |
564 } |