Mercurial > hg > nginx
annotate src/stream/ngx_stream.c @ 7315:e7b2b907c0f8
Events: moved sockets cloning to ngx_event_init_conf().
Previously, listenings sockets were not cloned if the worker_processes
directive was specified after "listen ... reuseport".
This also simplifies upcoming configuration check on the number
of worker connections, as it needs to know the number of listening
sockets before cloning.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 12 Jul 2018 19:50:02 +0300 |
parents | d7ce41bdf050 |
children | 4f9b72a229c1 |
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); | |
6693 | 15 static ngx_int_t ngx_stream_init_phases(ngx_conf_t *cf, |
16 ngx_stream_core_main_conf_t *cmcf); | |
17 static ngx_int_t ngx_stream_init_phase_handlers(ngx_conf_t *cf, | |
18 ngx_stream_core_main_conf_t *cmcf); | |
6115 | 19 static ngx_int_t ngx_stream_add_ports(ngx_conf_t *cf, ngx_array_t *ports, |
20 ngx_stream_listen_t *listen); | |
21 static char *ngx_stream_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports); | |
22 static ngx_int_t ngx_stream_add_addrs(ngx_conf_t *cf, ngx_stream_port_t *stport, | |
23 ngx_stream_conf_addr_t *addr); | |
24 #if (NGX_HAVE_INET6) | |
25 static ngx_int_t ngx_stream_add_addrs6(ngx_conf_t *cf, | |
26 ngx_stream_port_t *stport, ngx_stream_conf_addr_t *addr); | |
27 #endif | |
28 static ngx_int_t ngx_stream_cmp_conf_addrs(const void *one, const void *two); | |
29 | |
30 | |
31 ngx_uint_t ngx_stream_max_module; | |
32 | |
33 | |
6692 | 34 ngx_stream_filter_pt ngx_stream_top_filter; |
35 | |
36 | |
6115 | 37 static ngx_command_t ngx_stream_commands[] = { |
38 | |
39 { ngx_string("stream"), | |
40 NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, | |
41 ngx_stream_block, | |
42 0, | |
43 0, | |
44 NULL }, | |
45 | |
46 ngx_null_command | |
47 }; | |
48 | |
49 | |
50 static ngx_core_module_t ngx_stream_module_ctx = { | |
51 ngx_string("stream"), | |
52 NULL, | |
53 NULL | |
54 }; | |
55 | |
56 | |
57 ngx_module_t ngx_stream_module = { | |
58 NGX_MODULE_V1, | |
59 &ngx_stream_module_ctx, /* module context */ | |
60 ngx_stream_commands, /* module directives */ | |
61 NGX_CORE_MODULE, /* module type */ | |
62 NULL, /* init master */ | |
63 NULL, /* init module */ | |
64 NULL, /* init process */ | |
65 NULL, /* init thread */ | |
66 NULL, /* exit thread */ | |
67 NULL, /* exit process */ | |
68 NULL, /* exit master */ | |
69 NGX_MODULE_V1_PADDING | |
70 }; | |
71 | |
72 | |
73 static char * | |
74 ngx_stream_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
75 { | |
76 char *rv; | |
77 ngx_uint_t i, m, mi, s; | |
78 ngx_conf_t pcf; | |
79 ngx_array_t ports; | |
80 ngx_stream_listen_t *listen; | |
81 ngx_stream_module_t *module; | |
82 ngx_stream_conf_ctx_t *ctx; | |
83 ngx_stream_core_srv_conf_t **cscfp; | |
84 ngx_stream_core_main_conf_t *cmcf; | |
85 | |
6193
78c06e5e1d76
Disabled duplicate http, mail, and stream blocks.
Vladimir Homutov <vl@nginx.com>
parents:
6174
diff
changeset
|
86 if (*(ngx_stream_conf_ctx_t **) conf) { |
78c06e5e1d76
Disabled duplicate http, mail, and stream blocks.
Vladimir Homutov <vl@nginx.com>
parents:
6174
diff
changeset
|
87 return "is duplicate"; |
78c06e5e1d76
Disabled duplicate http, mail, and stream blocks.
Vladimir Homutov <vl@nginx.com>
parents:
6174
diff
changeset
|
88 } |
78c06e5e1d76
Disabled duplicate http, mail, and stream blocks.
Vladimir Homutov <vl@nginx.com>
parents:
6174
diff
changeset
|
89 |
6115 | 90 /* the main stream context */ |
91 | |
92 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_stream_conf_ctx_t)); | |
93 if (ctx == NULL) { | |
94 return NGX_CONF_ERROR; | |
95 } | |
96 | |
97 *(ngx_stream_conf_ctx_t **) conf = ctx; | |
98 | |
99 /* count the number of the stream modules and set up their indices */ | |
100 | |
6378
0f203a2af17c
Dynamic modules: moved module-related stuff to separate files.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6193
diff
changeset
|
101 ngx_stream_max_module = ngx_count_modules(cf->cycle, NGX_STREAM_MODULE); |
6115 | 102 |
103 | |
104 /* the stream main_conf context, it's the same in the all stream contexts */ | |
105 | |
106 ctx->main_conf = ngx_pcalloc(cf->pool, | |
107 sizeof(void *) * ngx_stream_max_module); | |
108 if (ctx->main_conf == NULL) { | |
109 return NGX_CONF_ERROR; | |
110 } | |
111 | |
112 | |
113 /* | |
114 * the stream null srv_conf context, it is used to merge | |
115 * the server{}s' srv_conf's | |
116 */ | |
117 | |
118 ctx->srv_conf = ngx_pcalloc(cf->pool, | |
119 sizeof(void *) * ngx_stream_max_module); | |
120 if (ctx->srv_conf == NULL) { | |
121 return NGX_CONF_ERROR; | |
122 } | |
123 | |
124 | |
125 /* | |
126 * create the main_conf's and the null srv_conf's of the all stream modules | |
127 */ | |
128 | |
6379
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6378
diff
changeset
|
129 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
|
130 if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) { |
6115 | 131 continue; |
132 } | |
133 | |
6379
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6378
diff
changeset
|
134 module = cf->cycle->modules[m]->ctx; |
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6378
diff
changeset
|
135 mi = cf->cycle->modules[m]->ctx_index; |
6115 | 136 |
137 if (module->create_main_conf) { | |
138 ctx->main_conf[mi] = module->create_main_conf(cf); | |
139 if (ctx->main_conf[mi] == NULL) { | |
140 return NGX_CONF_ERROR; | |
141 } | |
142 } | |
143 | |
144 if (module->create_srv_conf) { | |
145 ctx->srv_conf[mi] = module->create_srv_conf(cf); | |
146 if (ctx->srv_conf[mi] == NULL) { | |
147 return NGX_CONF_ERROR; | |
148 } | |
149 } | |
150 } | |
151 | |
152 | |
153 pcf = *cf; | |
154 cf->ctx = ctx; | |
155 | |
6606
2f41d383c9c7
Stream: added preconfiguration step.
Vladimir Homutov <vl@nginx.com>
parents:
6593
diff
changeset
|
156 for (m = 0; cf->cycle->modules[m]; m++) { |
2f41d383c9c7
Stream: added preconfiguration step.
Vladimir Homutov <vl@nginx.com>
parents:
6593
diff
changeset
|
157 if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) { |
2f41d383c9c7
Stream: added preconfiguration step.
Vladimir Homutov <vl@nginx.com>
parents:
6593
diff
changeset
|
158 continue; |
2f41d383c9c7
Stream: added preconfiguration step.
Vladimir Homutov <vl@nginx.com>
parents:
6593
diff
changeset
|
159 } |
2f41d383c9c7
Stream: added preconfiguration step.
Vladimir Homutov <vl@nginx.com>
parents:
6593
diff
changeset
|
160 |
2f41d383c9c7
Stream: added preconfiguration step.
Vladimir Homutov <vl@nginx.com>
parents:
6593
diff
changeset
|
161 module = cf->cycle->modules[m]->ctx; |
2f41d383c9c7
Stream: added preconfiguration step.
Vladimir Homutov <vl@nginx.com>
parents:
6593
diff
changeset
|
162 |
2f41d383c9c7
Stream: added preconfiguration step.
Vladimir Homutov <vl@nginx.com>
parents:
6593
diff
changeset
|
163 if (module->preconfiguration) { |
2f41d383c9c7
Stream: added preconfiguration step.
Vladimir Homutov <vl@nginx.com>
parents:
6593
diff
changeset
|
164 if (module->preconfiguration(cf) != NGX_OK) { |
2f41d383c9c7
Stream: added preconfiguration step.
Vladimir Homutov <vl@nginx.com>
parents:
6593
diff
changeset
|
165 return NGX_CONF_ERROR; |
2f41d383c9c7
Stream: added preconfiguration step.
Vladimir Homutov <vl@nginx.com>
parents:
6593
diff
changeset
|
166 } |
2f41d383c9c7
Stream: added preconfiguration step.
Vladimir Homutov <vl@nginx.com>
parents:
6593
diff
changeset
|
167 } |
2f41d383c9c7
Stream: added preconfiguration step.
Vladimir Homutov <vl@nginx.com>
parents:
6593
diff
changeset
|
168 } |
2f41d383c9c7
Stream: added preconfiguration step.
Vladimir Homutov <vl@nginx.com>
parents:
6593
diff
changeset
|
169 |
2f41d383c9c7
Stream: added preconfiguration step.
Vladimir Homutov <vl@nginx.com>
parents:
6593
diff
changeset
|
170 |
2f41d383c9c7
Stream: added preconfiguration step.
Vladimir Homutov <vl@nginx.com>
parents:
6593
diff
changeset
|
171 /* parse inside the stream{} block */ |
2f41d383c9c7
Stream: added preconfiguration step.
Vladimir Homutov <vl@nginx.com>
parents:
6593
diff
changeset
|
172 |
6115 | 173 cf->module_type = NGX_STREAM_MODULE; |
174 cf->cmd_type = NGX_STREAM_MAIN_CONF; | |
175 rv = ngx_conf_parse(cf, NULL); | |
176 | |
177 if (rv != NGX_CONF_OK) { | |
178 *cf = pcf; | |
179 return rv; | |
180 } | |
181 | |
182 | |
183 /* init stream{} main_conf's, merge the server{}s' srv_conf's */ | |
184 | |
185 cmcf = ctx->main_conf[ngx_stream_core_module.ctx_index]; | |
186 cscfp = cmcf->servers.elts; | |
187 | |
6379
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6378
diff
changeset
|
188 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
|
189 if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) { |
6115 | 190 continue; |
191 } | |
192 | |
6379
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6378
diff
changeset
|
193 module = cf->cycle->modules[m]->ctx; |
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6378
diff
changeset
|
194 mi = cf->cycle->modules[m]->ctx_index; |
6115 | 195 |
196 /* init stream{} main_conf's */ | |
197 | |
198 cf->ctx = ctx; | |
199 | |
200 if (module->init_main_conf) { | |
201 rv = module->init_main_conf(cf, ctx->main_conf[mi]); | |
202 if (rv != NGX_CONF_OK) { | |
203 *cf = pcf; | |
204 return rv; | |
205 } | |
206 } | |
207 | |
208 for (s = 0; s < cmcf->servers.nelts; s++) { | |
209 | |
210 /* merge the server{}s' srv_conf's */ | |
211 | |
212 cf->ctx = cscfp[s]->ctx; | |
213 | |
214 if (module->merge_srv_conf) { | |
215 rv = module->merge_srv_conf(cf, | |
216 ctx->srv_conf[mi], | |
217 cscfp[s]->ctx->srv_conf[mi]); | |
218 if (rv != NGX_CONF_OK) { | |
219 *cf = pcf; | |
220 return rv; | |
221 } | |
222 } | |
223 } | |
224 } | |
225 | |
6693 | 226 if (ngx_stream_init_phases(cf, cmcf) != NGX_OK) { |
227 return NGX_CONF_ERROR; | |
228 } | |
229 | |
6379
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6378
diff
changeset
|
230 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
|
231 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
|
232 continue; |
68c106e6fa0a
Stream: added postconfiguration method to stream modules.
Vladimir Homutov <vl@nginx.com>
parents:
6172
diff
changeset
|
233 } |
68c106e6fa0a
Stream: added postconfiguration method to stream modules.
Vladimir Homutov <vl@nginx.com>
parents:
6172
diff
changeset
|
234 |
6379
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6378
diff
changeset
|
235 module = cf->cycle->modules[m]->ctx; |
6174
68c106e6fa0a
Stream: added postconfiguration method to stream modules.
Vladimir Homutov <vl@nginx.com>
parents:
6172
diff
changeset
|
236 |
68c106e6fa0a
Stream: added postconfiguration method to stream modules.
Vladimir Homutov <vl@nginx.com>
parents:
6172
diff
changeset
|
237 if (module->postconfiguration) { |
68c106e6fa0a
Stream: added postconfiguration method to stream modules.
Vladimir Homutov <vl@nginx.com>
parents:
6172
diff
changeset
|
238 if (module->postconfiguration(cf) != NGX_OK) { |
68c106e6fa0a
Stream: added postconfiguration method to stream modules.
Vladimir Homutov <vl@nginx.com>
parents:
6172
diff
changeset
|
239 return NGX_CONF_ERROR; |
68c106e6fa0a
Stream: added postconfiguration method to stream modules.
Vladimir Homutov <vl@nginx.com>
parents:
6172
diff
changeset
|
240 } |
68c106e6fa0a
Stream: added postconfiguration method to stream modules.
Vladimir Homutov <vl@nginx.com>
parents:
6172
diff
changeset
|
241 } |
68c106e6fa0a
Stream: added postconfiguration method to stream modules.
Vladimir Homutov <vl@nginx.com>
parents:
6172
diff
changeset
|
242 } |
68c106e6fa0a
Stream: added postconfiguration method to stream modules.
Vladimir Homutov <vl@nginx.com>
parents:
6172
diff
changeset
|
243 |
6607
c70b7f4537e1
Stream: variables and script.
Vladimir Homutov <vl@nginx.com>
parents:
6606
diff
changeset
|
244 if (ngx_stream_variables_init_vars(cf) != NGX_OK) { |
c70b7f4537e1
Stream: variables and script.
Vladimir Homutov <vl@nginx.com>
parents:
6606
diff
changeset
|
245 return NGX_CONF_ERROR; |
c70b7f4537e1
Stream: variables and script.
Vladimir Homutov <vl@nginx.com>
parents:
6606
diff
changeset
|
246 } |
c70b7f4537e1
Stream: variables and script.
Vladimir Homutov <vl@nginx.com>
parents:
6606
diff
changeset
|
247 |
6115 | 248 *cf = pcf; |
249 | |
6693 | 250 if (ngx_stream_init_phase_handlers(cf, cmcf) != NGX_OK) { |
251 return NGX_CONF_ERROR; | |
252 } | |
6115 | 253 |
254 if (ngx_array_init(&ports, cf->temp_pool, 4, sizeof(ngx_stream_conf_port_t)) | |
255 != NGX_OK) | |
256 { | |
257 return NGX_CONF_ERROR; | |
258 } | |
259 | |
260 listen = cmcf->listen.elts; | |
261 | |
262 for (i = 0; i < cmcf->listen.nelts; i++) { | |
263 if (ngx_stream_add_ports(cf, &ports, &listen[i]) != NGX_OK) { | |
264 return NGX_CONF_ERROR; | |
265 } | |
266 } | |
267 | |
268 return ngx_stream_optimize_servers(cf, &ports); | |
269 } | |
270 | |
271 | |
272 static ngx_int_t | |
6693 | 273 ngx_stream_init_phases(ngx_conf_t *cf, ngx_stream_core_main_conf_t *cmcf) |
274 { | |
275 if (ngx_array_init(&cmcf->phases[NGX_STREAM_POST_ACCEPT_PHASE].handlers, | |
276 cf->pool, 1, sizeof(ngx_stream_handler_pt)) | |
277 != NGX_OK) | |
278 { | |
279 return NGX_ERROR; | |
280 } | |
281 | |
282 if (ngx_array_init(&cmcf->phases[NGX_STREAM_PREACCESS_PHASE].handlers, | |
283 cf->pool, 1, sizeof(ngx_stream_handler_pt)) | |
284 != NGX_OK) | |
285 { | |
286 return NGX_ERROR; | |
287 } | |
288 | |
289 if (ngx_array_init(&cmcf->phases[NGX_STREAM_ACCESS_PHASE].handlers, | |
290 cf->pool, 1, sizeof(ngx_stream_handler_pt)) | |
291 != NGX_OK) | |
292 { | |
293 return NGX_ERROR; | |
294 } | |
295 | |
296 if (ngx_array_init(&cmcf->phases[NGX_STREAM_SSL_PHASE].handlers, | |
297 cf->pool, 1, sizeof(ngx_stream_handler_pt)) | |
298 != NGX_OK) | |
299 { | |
300 return NGX_ERROR; | |
301 } | |
302 | |
6694 | 303 if (ngx_array_init(&cmcf->phases[NGX_STREAM_PREREAD_PHASE].handlers, |
304 cf->pool, 1, sizeof(ngx_stream_handler_pt)) | |
305 != NGX_OK) | |
306 { | |
307 return NGX_ERROR; | |
308 } | |
309 | |
6693 | 310 if (ngx_array_init(&cmcf->phases[NGX_STREAM_LOG_PHASE].handlers, |
311 cf->pool, 1, sizeof(ngx_stream_handler_pt)) | |
312 != NGX_OK) | |
313 { | |
314 return NGX_ERROR; | |
315 } | |
316 | |
317 return NGX_OK; | |
318 } | |
319 | |
320 | |
321 static ngx_int_t | |
322 ngx_stream_init_phase_handlers(ngx_conf_t *cf, | |
323 ngx_stream_core_main_conf_t *cmcf) | |
324 { | |
325 ngx_int_t j; | |
326 ngx_uint_t i, n; | |
327 ngx_stream_handler_pt *h; | |
328 ngx_stream_phase_handler_t *ph; | |
329 ngx_stream_phase_handler_pt checker; | |
330 | |
331 n = 1 /* content phase */; | |
332 | |
333 for (i = 0; i < NGX_STREAM_LOG_PHASE; i++) { | |
334 n += cmcf->phases[i].handlers.nelts; | |
335 } | |
336 | |
337 ph = ngx_pcalloc(cf->pool, | |
338 n * sizeof(ngx_stream_phase_handler_t) + sizeof(void *)); | |
339 if (ph == NULL) { | |
340 return NGX_ERROR; | |
341 } | |
342 | |
343 cmcf->phase_engine.handlers = ph; | |
344 n = 0; | |
345 | |
346 for (i = 0; i < NGX_STREAM_LOG_PHASE; i++) { | |
347 h = cmcf->phases[i].handlers.elts; | |
348 | |
349 switch (i) { | |
350 | |
6694 | 351 case NGX_STREAM_PREREAD_PHASE: |
352 checker = ngx_stream_core_preread_phase; | |
353 break; | |
354 | |
6693 | 355 case NGX_STREAM_CONTENT_PHASE: |
356 ph->checker = ngx_stream_core_content_phase; | |
357 n++; | |
358 ph++; | |
359 | |
360 continue; | |
361 | |
362 default: | |
363 checker = ngx_stream_core_generic_phase; | |
364 } | |
365 | |
366 n += cmcf->phases[i].handlers.nelts; | |
367 | |
368 for (j = cmcf->phases[i].handlers.nelts - 1; j >= 0; j--) { | |
369 ph->checker = checker; | |
370 ph->handler = h[j]; | |
371 ph->next = n; | |
372 ph++; | |
373 } | |
374 } | |
375 | |
376 return NGX_OK; | |
377 } | |
378 | |
379 | |
380 static ngx_int_t | |
6115 | 381 ngx_stream_add_ports(ngx_conf_t *cf, ngx_array_t *ports, |
382 ngx_stream_listen_t *listen) | |
383 { | |
384 in_port_t p; | |
385 ngx_uint_t i; | |
386 struct sockaddr *sa; | |
387 ngx_stream_conf_port_t *port; | |
388 ngx_stream_conf_addr_t *addr; | |
389 | |
6560
c90cf79d0e1d
Renamed "u" to "sockaddr" in listen options types.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6436
diff
changeset
|
390 sa = &listen->sockaddr.sockaddr; |
6593
b3b7e33083ac
Introduced ngx_inet_get_port() and ngx_inet_set_port() functions.
Roman Arutyunyan <arut@nginx.com>
parents:
6560
diff
changeset
|
391 p = ngx_inet_get_port(sa); |
6115 | 392 |
393 port = ports->elts; | |
394 for (i = 0; i < ports->nelts; i++) { | |
395 | |
6436 | 396 if (p == port[i].port |
397 && listen->type == port[i].type | |
398 && sa->sa_family == port[i].family) | |
399 { | |
6115 | 400 /* a port is already in the port list */ |
401 | |
402 port = &port[i]; | |
403 goto found; | |
404 } | |
405 } | |
406 | |
407 /* add a port to the port list */ | |
408 | |
409 port = ngx_array_push(ports); | |
410 if (port == NULL) { | |
411 return NGX_ERROR; | |
412 } | |
413 | |
414 port->family = sa->sa_family; | |
6436 | 415 port->type = listen->type; |
6115 | 416 port->port = p; |
417 | |
418 if (ngx_array_init(&port->addrs, cf->temp_pool, 2, | |
419 sizeof(ngx_stream_conf_addr_t)) | |
420 != NGX_OK) | |
421 { | |
422 return NGX_ERROR; | |
423 } | |
424 | |
425 found: | |
426 | |
427 addr = ngx_array_push(&port->addrs); | |
428 if (addr == NULL) { | |
429 return NGX_ERROR; | |
430 } | |
431 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
432 addr->opt = *listen; |
6115 | 433 |
434 return NGX_OK; | |
435 } | |
436 | |
437 | |
438 static char * | |
439 ngx_stream_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports) | |
440 { | |
441 ngx_uint_t i, p, last, bind_wildcard; | |
442 ngx_listening_t *ls; | |
443 ngx_stream_port_t *stport; | |
444 ngx_stream_conf_port_t *port; | |
445 ngx_stream_conf_addr_t *addr; | |
446 ngx_stream_core_srv_conf_t *cscf; | |
447 | |
448 port = ports->elts; | |
449 for (p = 0; p < ports->nelts; p++) { | |
450 | |
451 ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts, | |
452 sizeof(ngx_stream_conf_addr_t), ngx_stream_cmp_conf_addrs); | |
453 | |
454 addr = port[p].addrs.elts; | |
455 last = port[p].addrs.nelts; | |
456 | |
457 /* | |
458 * if there is the binding to the "*:port" then we need to bind() | |
459 * to the "*:port" only and ignore the other bindings | |
460 */ | |
461 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
462 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
|
463 addr[last - 1].opt.bind = 1; |
6115 | 464 bind_wildcard = 1; |
465 | |
466 } else { | |
467 bind_wildcard = 0; | |
468 } | |
469 | |
470 i = 0; | |
471 | |
472 while (i < last) { | |
473 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
474 if (bind_wildcard && !addr[i].opt.bind) { |
6115 | 475 i++; |
476 continue; | |
477 } | |
478 | |
6560
c90cf79d0e1d
Renamed "u" to "sockaddr" in listen options types.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6436
diff
changeset
|
479 ls = ngx_create_listening(cf, &addr[i].opt.sockaddr.sockaddr, |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
480 addr[i].opt.socklen); |
6115 | 481 if (ls == NULL) { |
482 return NGX_CONF_ERROR; | |
483 } | |
484 | |
485 ls->addr_ntop = 1; | |
486 ls->handler = ngx_stream_init_connection; | |
487 ls->pool_size = 256; | |
6436 | 488 ls->type = addr[i].opt.type; |
6115 | 489 |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
490 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
|
491 |
6115 | 492 ls->logp = cscf->error_log; |
493 ls->log.data = &ls->addr_text; | |
494 ls->log.handler = ngx_accept_log_error; | |
495 | |
6172 | 496 ls->backlog = addr[i].opt.backlog; |
6975
d7ce41bdf050
Stream: configurable socket buffer sizes.
Vladimir Homutov <vl@nginx.com>
parents:
6736
diff
changeset
|
497 ls->rcvbuf = addr[i].opt.rcvbuf; |
d7ce41bdf050
Stream: configurable socket buffer sizes.
Vladimir Homutov <vl@nginx.com>
parents:
6736
diff
changeset
|
498 ls->sndbuf = addr[i].opt.sndbuf; |
6172 | 499 |
6436 | 500 ls->wildcard = addr[i].opt.wildcard; |
501 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
502 ls->keepalive = addr[i].opt.so_keepalive; |
6115 | 503 #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
|
504 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
|
505 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
|
506 ls->keepcnt = addr[i].opt.tcp_keepcnt; |
6115 | 507 #endif |
508 | |
6719
cebf5fed00bf
Modules compatibility: removed unneeded IPV6_V6ONLY checks.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6694
diff
changeset
|
509 #if (NGX_HAVE_INET6) |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
510 ls->ipv6only = addr[i].opt.ipv6only; |
6115 | 511 #endif |
512 | |
6169
f654addf0eea
Stream: fixed "reuseport" to actually work.
Ruslan Ermilov <ru@nginx.com>
parents:
6153
diff
changeset
|
513 #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
|
514 ls->reuseport = addr[i].opt.reuseport; |
6169
f654addf0eea
Stream: fixed "reuseport" to actually work.
Ruslan Ermilov <ru@nginx.com>
parents:
6153
diff
changeset
|
515 #endif |
f654addf0eea
Stream: fixed "reuseport" to actually work.
Ruslan Ermilov <ru@nginx.com>
parents:
6153
diff
changeset
|
516 |
6115 | 517 stport = ngx_palloc(cf->pool, sizeof(ngx_stream_port_t)); |
518 if (stport == NULL) { | |
519 return NGX_CONF_ERROR; | |
520 } | |
521 | |
522 ls->servers = stport; | |
523 | |
6152
3c344ea7d88b
Simplified ngx_http_init_listening().
Maxim Dounin <mdounin@mdounin.ru>
parents:
6129
diff
changeset
|
524 stport->naddrs = i + 1; |
6115 | 525 |
526 switch (ls->sockaddr->sa_family) { | |
527 #if (NGX_HAVE_INET6) | |
528 case AF_INET6: | |
529 if (ngx_stream_add_addrs6(cf, stport, addr) != NGX_OK) { | |
530 return NGX_CONF_ERROR; | |
531 } | |
532 break; | |
533 #endif | |
534 default: /* AF_INET */ | |
535 if (ngx_stream_add_addrs(cf, stport, addr) != NGX_OK) { | |
536 return NGX_CONF_ERROR; | |
537 } | |
538 break; | |
539 } | |
540 | |
541 addr++; | |
542 last--; | |
543 } | |
544 } | |
545 | |
546 return NGX_CONF_OK; | |
547 } | |
548 | |
549 | |
550 static ngx_int_t | |
551 ngx_stream_add_addrs(ngx_conf_t *cf, ngx_stream_port_t *stport, | |
552 ngx_stream_conf_addr_t *addr) | |
553 { | |
554 u_char *p; | |
555 size_t len; | |
556 ngx_uint_t i; | |
557 struct sockaddr_in *sin; | |
558 ngx_stream_in_addr_t *addrs; | |
559 u_char buf[NGX_SOCKADDR_STRLEN]; | |
560 | |
561 stport->addrs = ngx_pcalloc(cf->pool, | |
562 stport->naddrs * sizeof(ngx_stream_in_addr_t)); | |
563 if (stport->addrs == NULL) { | |
564 return NGX_ERROR; | |
565 } | |
566 | |
567 addrs = stport->addrs; | |
568 | |
569 for (i = 0; i < stport->naddrs; i++) { | |
570 | |
6560
c90cf79d0e1d
Renamed "u" to "sockaddr" in listen options types.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6436
diff
changeset
|
571 sin = &addr[i].opt.sockaddr.sockaddr_in; |
6115 | 572 addrs[i].addr = sin->sin_addr.s_addr; |
573 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
574 addrs[i].conf.ctx = addr[i].opt.ctx; |
6115 | 575 #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
|
576 addrs[i].conf.ssl = addr[i].opt.ssl; |
6115 | 577 #endif |
6680
7357abd1fa8c
Stream: the "proxy_protocol" parameter of the "listen" directive.
Dmitry Volyntsev <xeioex@nginx.com>
parents:
6607
diff
changeset
|
578 addrs[i].conf.proxy_protocol = addr[i].opt.proxy_protocol; |
6115 | 579 |
6560
c90cf79d0e1d
Renamed "u" to "sockaddr" in listen options types.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6436
diff
changeset
|
580 len = ngx_sock_ntop(&addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen, |
c90cf79d0e1d
Renamed "u" to "sockaddr" in listen options types.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6436
diff
changeset
|
581 buf, NGX_SOCKADDR_STRLEN, 1); |
6115 | 582 |
583 p = ngx_pnalloc(cf->pool, len); | |
584 if (p == NULL) { | |
585 return NGX_ERROR; | |
586 } | |
587 | |
588 ngx_memcpy(p, buf, len); | |
589 | |
590 addrs[i].conf.addr_text.len = len; | |
591 addrs[i].conf.addr_text.data = p; | |
592 } | |
593 | |
594 return NGX_OK; | |
595 } | |
596 | |
597 | |
598 #if (NGX_HAVE_INET6) | |
599 | |
600 static ngx_int_t | |
601 ngx_stream_add_addrs6(ngx_conf_t *cf, ngx_stream_port_t *stport, | |
602 ngx_stream_conf_addr_t *addr) | |
603 { | |
604 u_char *p; | |
605 size_t len; | |
606 ngx_uint_t i; | |
607 struct sockaddr_in6 *sin6; | |
608 ngx_stream_in6_addr_t *addrs6; | |
609 u_char buf[NGX_SOCKADDR_STRLEN]; | |
610 | |
611 stport->addrs = ngx_pcalloc(cf->pool, | |
612 stport->naddrs * sizeof(ngx_stream_in6_addr_t)); | |
613 if (stport->addrs == NULL) { | |
614 return NGX_ERROR; | |
615 } | |
616 | |
617 addrs6 = stport->addrs; | |
618 | |
619 for (i = 0; i < stport->naddrs; i++) { | |
620 | |
6560
c90cf79d0e1d
Renamed "u" to "sockaddr" in listen options types.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6436
diff
changeset
|
621 sin6 = &addr[i].opt.sockaddr.sockaddr_in6; |
6115 | 622 addrs6[i].addr6 = sin6->sin6_addr; |
623 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
624 addrs6[i].conf.ctx = addr[i].opt.ctx; |
6115 | 625 #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
|
626 addrs6[i].conf.ssl = addr[i].opt.ssl; |
6115 | 627 #endif |
6680
7357abd1fa8c
Stream: the "proxy_protocol" parameter of the "listen" directive.
Dmitry Volyntsev <xeioex@nginx.com>
parents:
6607
diff
changeset
|
628 addrs6[i].conf.proxy_protocol = addr[i].opt.proxy_protocol; |
6115 | 629 |
6560
c90cf79d0e1d
Renamed "u" to "sockaddr" in listen options types.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6436
diff
changeset
|
630 len = ngx_sock_ntop(&addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen, |
c90cf79d0e1d
Renamed "u" to "sockaddr" in listen options types.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6436
diff
changeset
|
631 buf, NGX_SOCKADDR_STRLEN, 1); |
6115 | 632 |
633 p = ngx_pnalloc(cf->pool, len); | |
634 if (p == NULL) { | |
635 return NGX_ERROR; | |
636 } | |
637 | |
638 ngx_memcpy(p, buf, len); | |
639 | |
640 addrs6[i].conf.addr_text.len = len; | |
641 addrs6[i].conf.addr_text.data = p; | |
642 } | |
643 | |
644 return NGX_OK; | |
645 } | |
646 | |
647 #endif | |
648 | |
649 | |
650 static ngx_int_t | |
651 ngx_stream_cmp_conf_addrs(const void *one, const void *two) | |
652 { | |
653 ngx_stream_conf_addr_t *first, *second; | |
654 | |
655 first = (ngx_stream_conf_addr_t *) one; | |
656 second = (ngx_stream_conf_addr_t *) two; | |
657 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
658 if (first->opt.wildcard) { |
6115 | 659 /* a wildcard must be the last resort, shift it to the end */ |
660 return 1; | |
661 } | |
662 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
663 if (second->opt.wildcard) { |
6115 | 664 /* a wildcard must be the last resort, shift it to the end */ |
665 return -1; | |
666 } | |
667 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
668 if (first->opt.bind && !second->opt.bind) { |
6115 | 669 /* shift explicit bind()ed addresses to the start */ |
670 return -1; | |
671 } | |
672 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
673 if (!first->opt.bind && second->opt.bind) { |
6115 | 674 /* shift explicit bind()ed addresses to the start */ |
675 return 1; | |
676 } | |
677 | |
678 /* do not sort by default */ | |
679 | |
680 return 0; | |
681 } |