Mercurial > hg > nginx
annotate src/stream/ngx_stream.c @ 6719:cebf5fed00bf
Modules compatibility: removed unneeded IPV6_V6ONLY checks.
The IPV6_V6ONLY macro is now checked only while parsing appropriate flag
and when using the macro.
The ipv6only field in listen structures is always initialized to 1,
even if not supported on a given platform. This is expected to prevent
a module compiled without IPV6_V6ONLY from accidentally creating dual
sockets if loaded into main binary with proper IPV6_V6ONLY support.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 03 Oct 2016 15:58:25 +0300 |
parents | ea9dfe2f62e7 |
children | f41c2530dd17 |
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_STREAM_SSL) | |
297 if (ngx_array_init(&cmcf->phases[NGX_STREAM_SSL_PHASE].handlers, | |
298 cf->pool, 1, sizeof(ngx_stream_handler_pt)) | |
299 != NGX_OK) | |
300 { | |
301 return NGX_ERROR; | |
302 } | |
303 #endif | |
304 | |
6694 | 305 if (ngx_array_init(&cmcf->phases[NGX_STREAM_PREREAD_PHASE].handlers, |
306 cf->pool, 1, sizeof(ngx_stream_handler_pt)) | |
307 != NGX_OK) | |
308 { | |
309 return NGX_ERROR; | |
310 } | |
311 | |
6693 | 312 if (ngx_array_init(&cmcf->phases[NGX_STREAM_LOG_PHASE].handlers, |
313 cf->pool, 1, sizeof(ngx_stream_handler_pt)) | |
314 != NGX_OK) | |
315 { | |
316 return NGX_ERROR; | |
317 } | |
318 | |
319 return NGX_OK; | |
320 } | |
321 | |
322 | |
323 static ngx_int_t | |
324 ngx_stream_init_phase_handlers(ngx_conf_t *cf, | |
325 ngx_stream_core_main_conf_t *cmcf) | |
326 { | |
327 ngx_int_t j; | |
328 ngx_uint_t i, n; | |
329 ngx_stream_handler_pt *h; | |
330 ngx_stream_phase_handler_t *ph; | |
331 ngx_stream_phase_handler_pt checker; | |
332 | |
333 n = 1 /* content phase */; | |
334 | |
335 for (i = 0; i < NGX_STREAM_LOG_PHASE; i++) { | |
336 n += cmcf->phases[i].handlers.nelts; | |
337 } | |
338 | |
339 ph = ngx_pcalloc(cf->pool, | |
340 n * sizeof(ngx_stream_phase_handler_t) + sizeof(void *)); | |
341 if (ph == NULL) { | |
342 return NGX_ERROR; | |
343 } | |
344 | |
345 cmcf->phase_engine.handlers = ph; | |
346 n = 0; | |
347 | |
348 for (i = 0; i < NGX_STREAM_LOG_PHASE; i++) { | |
349 h = cmcf->phases[i].handlers.elts; | |
350 | |
351 switch (i) { | |
352 | |
6694 | 353 case NGX_STREAM_PREREAD_PHASE: |
354 checker = ngx_stream_core_preread_phase; | |
355 break; | |
356 | |
6693 | 357 case NGX_STREAM_CONTENT_PHASE: |
358 ph->checker = ngx_stream_core_content_phase; | |
359 n++; | |
360 ph++; | |
361 | |
362 continue; | |
363 | |
364 default: | |
365 checker = ngx_stream_core_generic_phase; | |
366 } | |
367 | |
368 n += cmcf->phases[i].handlers.nelts; | |
369 | |
370 for (j = cmcf->phases[i].handlers.nelts - 1; j >= 0; j--) { | |
371 ph->checker = checker; | |
372 ph->handler = h[j]; | |
373 ph->next = n; | |
374 ph++; | |
375 } | |
376 } | |
377 | |
378 return NGX_OK; | |
379 } | |
380 | |
381 | |
382 static ngx_int_t | |
6115 | 383 ngx_stream_add_ports(ngx_conf_t *cf, ngx_array_t *ports, |
384 ngx_stream_listen_t *listen) | |
385 { | |
386 in_port_t p; | |
387 ngx_uint_t i; | |
388 struct sockaddr *sa; | |
389 ngx_stream_conf_port_t *port; | |
390 ngx_stream_conf_addr_t *addr; | |
391 | |
6560
c90cf79d0e1d
Renamed "u" to "sockaddr" in listen options types.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6436
diff
changeset
|
392 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
|
393 p = ngx_inet_get_port(sa); |
6115 | 394 |
395 port = ports->elts; | |
396 for (i = 0; i < ports->nelts; i++) { | |
397 | |
6436 | 398 if (p == port[i].port |
399 && listen->type == port[i].type | |
400 && sa->sa_family == port[i].family) | |
401 { | |
6115 | 402 /* a port is already in the port list */ |
403 | |
404 port = &port[i]; | |
405 goto found; | |
406 } | |
407 } | |
408 | |
409 /* add a port to the port list */ | |
410 | |
411 port = ngx_array_push(ports); | |
412 if (port == NULL) { | |
413 return NGX_ERROR; | |
414 } | |
415 | |
416 port->family = sa->sa_family; | |
6436 | 417 port->type = listen->type; |
6115 | 418 port->port = p; |
419 | |
420 if (ngx_array_init(&port->addrs, cf->temp_pool, 2, | |
421 sizeof(ngx_stream_conf_addr_t)) | |
422 != NGX_OK) | |
423 { | |
424 return NGX_ERROR; | |
425 } | |
426 | |
427 found: | |
428 | |
429 addr = ngx_array_push(&port->addrs); | |
430 if (addr == NULL) { | |
431 return NGX_ERROR; | |
432 } | |
433 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
434 addr->opt = *listen; |
6115 | 435 |
436 return NGX_OK; | |
437 } | |
438 | |
439 | |
440 static char * | |
441 ngx_stream_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports) | |
442 { | |
443 ngx_uint_t i, p, last, bind_wildcard; | |
444 ngx_listening_t *ls; | |
445 ngx_stream_port_t *stport; | |
446 ngx_stream_conf_port_t *port; | |
447 ngx_stream_conf_addr_t *addr; | |
448 ngx_stream_core_srv_conf_t *cscf; | |
449 | |
450 port = ports->elts; | |
451 for (p = 0; p < ports->nelts; p++) { | |
452 | |
453 ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts, | |
454 sizeof(ngx_stream_conf_addr_t), ngx_stream_cmp_conf_addrs); | |
455 | |
456 addr = port[p].addrs.elts; | |
457 last = port[p].addrs.nelts; | |
458 | |
459 /* | |
460 * if there is the binding to the "*:port" then we need to bind() | |
461 * to the "*:port" only and ignore the other bindings | |
462 */ | |
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 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
|
465 addr[last - 1].opt.bind = 1; |
6115 | 466 bind_wildcard = 1; |
467 | |
468 } else { | |
469 bind_wildcard = 0; | |
470 } | |
471 | |
472 i = 0; | |
473 | |
474 while (i < last) { | |
475 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
476 if (bind_wildcard && !addr[i].opt.bind) { |
6115 | 477 i++; |
478 continue; | |
479 } | |
480 | |
6560
c90cf79d0e1d
Renamed "u" to "sockaddr" in listen options types.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6436
diff
changeset
|
481 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
|
482 addr[i].opt.socklen); |
6115 | 483 if (ls == NULL) { |
484 return NGX_CONF_ERROR; | |
485 } | |
486 | |
487 ls->addr_ntop = 1; | |
488 ls->handler = ngx_stream_init_connection; | |
489 ls->pool_size = 256; | |
6436 | 490 ls->type = addr[i].opt.type; |
6115 | 491 |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
492 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
|
493 |
6115 | 494 ls->logp = cscf->error_log; |
495 ls->log.data = &ls->addr_text; | |
496 ls->log.handler = ngx_accept_log_error; | |
497 | |
6172 | 498 ls->backlog = addr[i].opt.backlog; |
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 | |
6153
4f6efabcb09b
The "reuseport" option of the "listen" directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6152
diff
changeset
|
541 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
|
542 return NGX_CONF_ERROR; |
4f6efabcb09b
The "reuseport" option of the "listen" directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6152
diff
changeset
|
543 } |
4f6efabcb09b
The "reuseport" option of the "listen" directive.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6152
diff
changeset
|
544 |
6115 | 545 addr++; |
546 last--; | |
547 } | |
548 } | |
549 | |
550 return NGX_CONF_OK; | |
551 } | |
552 | |
553 | |
554 static ngx_int_t | |
555 ngx_stream_add_addrs(ngx_conf_t *cf, ngx_stream_port_t *stport, | |
556 ngx_stream_conf_addr_t *addr) | |
557 { | |
558 u_char *p; | |
559 size_t len; | |
560 ngx_uint_t i; | |
561 struct sockaddr_in *sin; | |
562 ngx_stream_in_addr_t *addrs; | |
563 u_char buf[NGX_SOCKADDR_STRLEN]; | |
564 | |
565 stport->addrs = ngx_pcalloc(cf->pool, | |
566 stport->naddrs * sizeof(ngx_stream_in_addr_t)); | |
567 if (stport->addrs == NULL) { | |
568 return NGX_ERROR; | |
569 } | |
570 | |
571 addrs = stport->addrs; | |
572 | |
573 for (i = 0; i < stport->naddrs; i++) { | |
574 | |
6560
c90cf79d0e1d
Renamed "u" to "sockaddr" in listen options types.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6436
diff
changeset
|
575 sin = &addr[i].opt.sockaddr.sockaddr_in; |
6115 | 576 addrs[i].addr = sin->sin_addr.s_addr; |
577 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
578 addrs[i].conf.ctx = addr[i].opt.ctx; |
6115 | 579 #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
|
580 addrs[i].conf.ssl = addr[i].opt.ssl; |
6115 | 581 #endif |
6680
7357abd1fa8c
Stream: the "proxy_protocol" parameter of the "listen" directive.
Dmitry Volyntsev <xeioex@nginx.com>
parents:
6607
diff
changeset
|
582 addrs[i].conf.proxy_protocol = addr[i].opt.proxy_protocol; |
6115 | 583 |
6560
c90cf79d0e1d
Renamed "u" to "sockaddr" in listen options types.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6436
diff
changeset
|
584 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
|
585 buf, NGX_SOCKADDR_STRLEN, 1); |
6115 | 586 |
587 p = ngx_pnalloc(cf->pool, len); | |
588 if (p == NULL) { | |
589 return NGX_ERROR; | |
590 } | |
591 | |
592 ngx_memcpy(p, buf, len); | |
593 | |
594 addrs[i].conf.addr_text.len = len; | |
595 addrs[i].conf.addr_text.data = p; | |
596 } | |
597 | |
598 return NGX_OK; | |
599 } | |
600 | |
601 | |
602 #if (NGX_HAVE_INET6) | |
603 | |
604 static ngx_int_t | |
605 ngx_stream_add_addrs6(ngx_conf_t *cf, ngx_stream_port_t *stport, | |
606 ngx_stream_conf_addr_t *addr) | |
607 { | |
608 u_char *p; | |
609 size_t len; | |
610 ngx_uint_t i; | |
611 struct sockaddr_in6 *sin6; | |
612 ngx_stream_in6_addr_t *addrs6; | |
613 u_char buf[NGX_SOCKADDR_STRLEN]; | |
614 | |
615 stport->addrs = ngx_pcalloc(cf->pool, | |
616 stport->naddrs * sizeof(ngx_stream_in6_addr_t)); | |
617 if (stport->addrs == NULL) { | |
618 return NGX_ERROR; | |
619 } | |
620 | |
621 addrs6 = stport->addrs; | |
622 | |
623 for (i = 0; i < stport->naddrs; i++) { | |
624 | |
6560
c90cf79d0e1d
Renamed "u" to "sockaddr" in listen options types.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6436
diff
changeset
|
625 sin6 = &addr[i].opt.sockaddr.sockaddr_in6; |
6115 | 626 addrs6[i].addr6 = sin6->sin6_addr; |
627 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
628 addrs6[i].conf.ctx = addr[i].opt.ctx; |
6115 | 629 #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
|
630 addrs6[i].conf.ssl = addr[i].opt.ssl; |
6115 | 631 #endif |
6680
7357abd1fa8c
Stream: the "proxy_protocol" parameter of the "listen" directive.
Dmitry Volyntsev <xeioex@nginx.com>
parents:
6607
diff
changeset
|
632 addrs6[i].conf.proxy_protocol = addr[i].opt.proxy_protocol; |
6115 | 633 |
6560
c90cf79d0e1d
Renamed "u" to "sockaddr" in listen options types.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6436
diff
changeset
|
634 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
|
635 buf, NGX_SOCKADDR_STRLEN, 1); |
6115 | 636 |
637 p = ngx_pnalloc(cf->pool, len); | |
638 if (p == NULL) { | |
639 return NGX_ERROR; | |
640 } | |
641 | |
642 ngx_memcpy(p, buf, len); | |
643 | |
644 addrs6[i].conf.addr_text.len = len; | |
645 addrs6[i].conf.addr_text.data = p; | |
646 } | |
647 | |
648 return NGX_OK; | |
649 } | |
650 | |
651 #endif | |
652 | |
653 | |
654 static ngx_int_t | |
655 ngx_stream_cmp_conf_addrs(const void *one, const void *two) | |
656 { | |
657 ngx_stream_conf_addr_t *first, *second; | |
658 | |
659 first = (ngx_stream_conf_addr_t *) one; | |
660 second = (ngx_stream_conf_addr_t *) two; | |
661 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
662 if (first->opt.wildcard) { |
6115 | 663 /* a wildcard must be the last resort, shift it to the end */ |
664 return 1; | |
665 } | |
666 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
667 if (second->opt.wildcard) { |
6115 | 668 /* a wildcard must be the last resort, shift it to the end */ |
669 return -1; | |
670 } | |
671 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
672 if (first->opt.bind && !second->opt.bind) { |
6115 | 673 /* shift explicit bind()ed addresses to the start */ |
674 return -1; | |
675 } | |
676 | |
6170
c13091e6292c
Stream: embed ngx_stream_listen_t into ngx_stream_conf_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
6169
diff
changeset
|
677 if (!first->opt.bind && second->opt.bind) { |
6115 | 678 /* shift explicit bind()ed addresses to the start */ |
679 return 1; | |
680 } | |
681 | |
682 /* do not sort by default */ | |
683 | |
684 return 0; | |
685 } |