File: | http/ngx_http.c |
Location: | line 748, column 31 |
Description: | Access to field 'named_locations' results in a dereference of a null pointer (loaded from variable 'cscf') |
1 | ||||
2 | /* | |||
3 | * Copyright (C) Igor Sysoev | |||
4 | * Copyright (C) Nginx, Inc. | |||
5 | */ | |||
6 | ||||
7 | ||||
8 | #include <ngx_config.h> | |||
9 | #include <ngx_core.h> | |||
10 | #include <ngx_http.h> | |||
11 | ||||
12 | ||||
13 | static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); | |||
14 | static ngx_int_t ngx_http_init_phases(ngx_conf_t *cf, | |||
15 | ngx_http_core_main_conf_t *cmcf); | |||
16 | static ngx_int_t ngx_http_init_headers_in_hash(ngx_conf_t *cf, | |||
17 | ngx_http_core_main_conf_t *cmcf); | |||
18 | static ngx_int_t ngx_http_init_phase_handlers(ngx_conf_t *cf, | |||
19 | ngx_http_core_main_conf_t *cmcf); | |||
20 | ||||
21 | static ngx_int_t ngx_http_add_addresses(ngx_conf_t *cf, | |||
22 | ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port, | |||
23 | ngx_http_listen_opt_t *lsopt); | |||
24 | static ngx_int_t ngx_http_add_address(ngx_conf_t *cf, | |||
25 | ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port, | |||
26 | ngx_http_listen_opt_t *lsopt); | |||
27 | static ngx_int_t ngx_http_add_server(ngx_conf_t *cf, | |||
28 | ngx_http_core_srv_conf_t *cscf, ngx_http_conf_addr_t *addr); | |||
29 | ||||
30 | static char *ngx_http_merge_servers(ngx_conf_t *cf, | |||
31 | ngx_http_core_main_conf_t *cmcf, ngx_http_module_t *module, | |||
32 | ngx_uint_t ctx_index); | |||
33 | static char *ngx_http_merge_locations(ngx_conf_t *cf, | |||
34 | ngx_queue_t *locations, void **loc_conf, ngx_http_module_t *module, | |||
35 | ngx_uint_t ctx_index); | |||
36 | static ngx_int_t ngx_http_init_locations(ngx_conf_t *cf, | |||
37 | ngx_http_core_srv_conf_t *cscf, ngx_http_core_loc_conf_t *pclcf); | |||
38 | static ngx_int_t ngx_http_init_static_location_trees(ngx_conf_t *cf, | |||
39 | ngx_http_core_loc_conf_t *pclcf); | |||
40 | static ngx_int_t ngx_http_cmp_locations(const ngx_queue_t *one, | |||
41 | const ngx_queue_t *two); | |||
42 | static ngx_int_t ngx_http_join_exact_locations(ngx_conf_t *cf, | |||
43 | ngx_queue_t *locations); | |||
44 | static void ngx_http_create_locations_list(ngx_queue_t *locations, | |||
45 | ngx_queue_t *q); | |||
46 | static ngx_http_location_tree_node_t * | |||
47 | ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations, | |||
48 | size_t prefix); | |||
49 | ||||
50 | static ngx_int_t ngx_http_optimize_servers(ngx_conf_t *cf, | |||
51 | ngx_http_core_main_conf_t *cmcf, ngx_array_t *ports); | |||
52 | static ngx_int_t ngx_http_server_names(ngx_conf_t *cf, | |||
53 | ngx_http_core_main_conf_t *cmcf, ngx_http_conf_addr_t *addr); | |||
54 | static ngx_int_t ngx_http_cmp_conf_addrs(const void *one, const void *two); | |||
55 | static int ngx_libc_cdecl ngx_http_cmp_dns_wildcards(const void *one, | |||
56 | const void *two); | |||
57 | ||||
58 | static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf, | |||
59 | ngx_http_conf_port_t *port); | |||
60 | static ngx_listening_t *ngx_http_add_listening(ngx_conf_t *cf, | |||
61 | ngx_http_conf_addr_t *addr); | |||
62 | static ngx_int_t ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport, | |||
63 | ngx_http_conf_addr_t *addr); | |||
64 | #if (NGX_HAVE_INET6) | |||
65 | static ngx_int_t ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport, | |||
66 | ngx_http_conf_addr_t *addr); | |||
67 | #endif | |||
68 | ||||
69 | ngx_uint_t ngx_http_max_module; | |||
70 | ||||
71 | ||||
72 | ngx_http_output_header_filter_pt ngx_http_top_header_filter; | |||
73 | ngx_http_output_body_filter_pt ngx_http_top_body_filter; | |||
74 | ngx_http_request_body_filter_pt ngx_http_top_request_body_filter; | |||
75 | ||||
76 | ||||
77 | ngx_str_t ngx_http_html_default_types[] = { | |||
78 | ngx_string("text/html"){ sizeof("text/html") - 1, (u_char *) "text/html" }, | |||
79 | ngx_null_string{ 0, ((void*)0) } | |||
80 | }; | |||
81 | ||||
82 | ||||
83 | static ngx_command_t ngx_http_commands[] = { | |||
84 | ||||
85 | { ngx_string("http"){ sizeof("http") - 1, (u_char *) "http" }, | |||
86 | NGX_MAIN_CONF0x01000000|NGX_CONF_BLOCK0x00000100|NGX_CONF_NOARGS0x00000001, | |||
87 | ngx_http_block, | |||
88 | 0, | |||
89 | 0, | |||
90 | NULL((void*)0) }, | |||
91 | ||||
92 | ngx_null_command{ { 0, ((void*)0) }, 0, ((void*)0), 0, 0, ((void*)0) } | |||
93 | }; | |||
94 | ||||
95 | ||||
96 | static ngx_core_module_t ngx_http_module_ctx = { | |||
97 | ngx_string("http"){ sizeof("http") - 1, (u_char *) "http" }, | |||
98 | NULL((void*)0), | |||
99 | NULL((void*)0) | |||
100 | }; | |||
101 | ||||
102 | ||||
103 | ngx_module_t ngx_http_module = { | |||
104 | NGX_MODULE_V1(ngx_uint_t) -1, (ngx_uint_t) -1, ((void*)0), 0, 0, 1011001, "8" "," "4" "," "8" "," "0" "0" "0" "0" "1" "1" "1" "0" "0" "1" "0" "1" "0" "1" "1" "1" "1" "1" "1" "1" "1" "0" "1" "0" "0" "1" "0" "1" "0" "0" "0" "1" "1", | |||
105 | &ngx_http_module_ctx, /* module context */ | |||
106 | ngx_http_commands, /* module directives */ | |||
107 | NGX_CORE_MODULE0x45524F43, /* module type */ | |||
108 | NULL((void*)0), /* init master */ | |||
109 | NULL((void*)0), /* init module */ | |||
110 | NULL((void*)0), /* init process */ | |||
111 | NULL((void*)0), /* init thread */ | |||
112 | NULL((void*)0), /* exit thread */ | |||
113 | NULL((void*)0), /* exit process */ | |||
114 | NULL((void*)0), /* exit master */ | |||
115 | NGX_MODULE_V1_PADDING0, 0, 0, 0, 0, 0, 0, 0 | |||
116 | }; | |||
117 | ||||
118 | ||||
119 | static char * | |||
120 | ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |||
121 | { | |||
122 | char *rv; | |||
123 | ngx_uint_t mi, m, s; | |||
124 | ngx_conf_t pcf; | |||
125 | ngx_http_module_t *module; | |||
126 | ngx_http_conf_ctx_t *ctx; | |||
127 | ngx_http_core_loc_conf_t *clcf; | |||
128 | ngx_http_core_srv_conf_t **cscfp; | |||
129 | ngx_http_core_main_conf_t *cmcf; | |||
130 | ||||
131 | if (*(ngx_http_conf_ctx_t **) conf) { | |||
132 | return "is duplicate"; | |||
133 | } | |||
134 | ||||
135 | /* the main http context */ | |||
136 | ||||
137 | ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); | |||
138 | if (ctx == NULL((void*)0)) { | |||
139 | return NGX_CONF_ERROR(void *) -1; | |||
140 | } | |||
141 | ||||
142 | *(ngx_http_conf_ctx_t **) conf = ctx; | |||
143 | ||||
144 | ||||
145 | /* count the number of the http modules and set up their indices */ | |||
146 | ||||
147 | ngx_http_max_module = ngx_count_modules(cf->cycle, NGX_HTTP_MODULE0x50545448); | |||
148 | ||||
149 | ||||
150 | /* the http main_conf context, it is the same in the all http contexts */ | |||
151 | ||||
152 | ctx->main_conf = ngx_pcalloc(cf->pool, | |||
153 | sizeof(void *) * ngx_http_max_module); | |||
154 | if (ctx->main_conf == NULL((void*)0)) { | |||
155 | return NGX_CONF_ERROR(void *) -1; | |||
156 | } | |||
157 | ||||
158 | ||||
159 | /* | |||
160 | * the http null srv_conf context, it is used to merge | |||
161 | * the server{}s' srv_conf's | |||
162 | */ | |||
163 | ||||
164 | ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); | |||
165 | if (ctx->srv_conf == NULL((void*)0)) { | |||
166 | return NGX_CONF_ERROR(void *) -1; | |||
167 | } | |||
168 | ||||
169 | ||||
170 | /* | |||
171 | * the http null loc_conf context, it is used to merge | |||
172 | * the server{}s' loc_conf's | |||
173 | */ | |||
174 | ||||
175 | ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); | |||
176 | if (ctx->loc_conf == NULL((void*)0)) { | |||
177 | return NGX_CONF_ERROR(void *) -1; | |||
178 | } | |||
179 | ||||
180 | ||||
181 | /* | |||
182 | * create the main_conf's, the null srv_conf's, and the null loc_conf's | |||
183 | * of the all http modules | |||
184 | */ | |||
185 | ||||
186 | for (m = 0; cf->cycle->modules[m]; m++) { | |||
187 | if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE0x50545448) { | |||
188 | continue; | |||
189 | } | |||
190 | ||||
191 | module = cf->cycle->modules[m]->ctx; | |||
192 | mi = cf->cycle->modules[m]->ctx_index; | |||
193 | ||||
194 | if (module->create_main_conf) { | |||
195 | ctx->main_conf[mi] = module->create_main_conf(cf); | |||
196 | if (ctx->main_conf[mi] == NULL((void*)0)) { | |||
197 | return NGX_CONF_ERROR(void *) -1; | |||
198 | } | |||
199 | } | |||
200 | ||||
201 | if (module->create_srv_conf) { | |||
202 | ctx->srv_conf[mi] = module->create_srv_conf(cf); | |||
203 | if (ctx->srv_conf[mi] == NULL((void*)0)) { | |||
204 | return NGX_CONF_ERROR(void *) -1; | |||
205 | } | |||
206 | } | |||
207 | ||||
208 | if (module->create_loc_conf) { | |||
209 | ctx->loc_conf[mi] = module->create_loc_conf(cf); | |||
210 | if (ctx->loc_conf[mi] == NULL((void*)0)) { | |||
211 | return NGX_CONF_ERROR(void *) -1; | |||
212 | } | |||
213 | } | |||
214 | } | |||
215 | ||||
216 | pcf = *cf; | |||
217 | cf->ctx = ctx; | |||
218 | ||||
219 | for (m = 0; cf->cycle->modules[m]; m++) { | |||
220 | if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE0x50545448) { | |||
221 | continue; | |||
222 | } | |||
223 | ||||
224 | module = cf->cycle->modules[m]->ctx; | |||
225 | ||||
226 | if (module->preconfiguration) { | |||
227 | if (module->preconfiguration(cf) != NGX_OK0) { | |||
228 | return NGX_CONF_ERROR(void *) -1; | |||
229 | } | |||
230 | } | |||
231 | } | |||
232 | ||||
233 | /* parse inside the http{} block */ | |||
234 | ||||
235 | cf->module_type = NGX_HTTP_MODULE0x50545448; | |||
236 | cf->cmd_type = NGX_HTTP_MAIN_CONF0x02000000; | |||
237 | rv = ngx_conf_parse(cf, NULL((void*)0)); | |||
238 | ||||
239 | if (rv != NGX_CONF_OK((void*)0)) { | |||
240 | goto failed; | |||
241 | } | |||
242 | ||||
243 | /* | |||
244 | * init http{} main_conf's, merge the server{}s' srv_conf's | |||
245 | * and its location{}s' loc_conf's | |||
246 | */ | |||
247 | ||||
248 | cmcf = ctx->main_conf[ngx_http_core_module.ctx_index]; | |||
249 | cscfp = cmcf->servers.elts; | |||
250 | ||||
251 | for (m = 0; cf->cycle->modules[m]; m++) { | |||
252 | if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE0x50545448) { | |||
253 | continue; | |||
254 | } | |||
255 | ||||
256 | module = cf->cycle->modules[m]->ctx; | |||
257 | mi = cf->cycle->modules[m]->ctx_index; | |||
258 | ||||
259 | /* init http{} main_conf's */ | |||
260 | ||||
261 | if (module->init_main_conf) { | |||
262 | rv = module->init_main_conf(cf, ctx->main_conf[mi]); | |||
263 | if (rv != NGX_CONF_OK((void*)0)) { | |||
264 | goto failed; | |||
265 | } | |||
266 | } | |||
267 | ||||
268 | rv = ngx_http_merge_servers(cf, cmcf, module, mi); | |||
269 | if (rv != NGX_CONF_OK((void*)0)) { | |||
270 | goto failed; | |||
271 | } | |||
272 | } | |||
273 | ||||
274 | ||||
275 | /* create location trees */ | |||
276 | ||||
277 | for (s = 0; s < cmcf->servers.nelts; s++) { | |||
278 | ||||
279 | clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index]; | |||
280 | ||||
281 | if (ngx_http_init_locations(cf, cscfp[s], clcf) != NGX_OK0) { | |||
282 | return NGX_CONF_ERROR(void *) -1; | |||
283 | } | |||
284 | ||||
285 | if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK0) { | |||
286 | return NGX_CONF_ERROR(void *) -1; | |||
287 | } | |||
288 | } | |||
289 | ||||
290 | ||||
291 | if (ngx_http_init_phases(cf, cmcf) != NGX_OK0) { | |||
292 | return NGX_CONF_ERROR(void *) -1; | |||
293 | } | |||
294 | ||||
295 | if (ngx_http_init_headers_in_hash(cf, cmcf) != NGX_OK0) { | |||
296 | return NGX_CONF_ERROR(void *) -1; | |||
297 | } | |||
298 | ||||
299 | ||||
300 | for (m = 0; cf->cycle->modules[m]; m++) { | |||
301 | if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE0x50545448) { | |||
302 | continue; | |||
303 | } | |||
304 | ||||
305 | module = cf->cycle->modules[m]->ctx; | |||
306 | ||||
307 | if (module->postconfiguration) { | |||
308 | if (module->postconfiguration(cf) != NGX_OK0) { | |||
309 | return NGX_CONF_ERROR(void *) -1; | |||
310 | } | |||
311 | } | |||
312 | } | |||
313 | ||||
314 | if (ngx_http_variables_init_vars(cf) != NGX_OK0) { | |||
315 | return NGX_CONF_ERROR(void *) -1; | |||
316 | } | |||
317 | ||||
318 | /* | |||
319 | * http{}'s cf->ctx was needed while the configuration merging | |||
320 | * and in postconfiguration process | |||
321 | */ | |||
322 | ||||
323 | *cf = pcf; | |||
324 | ||||
325 | ||||
326 | if (ngx_http_init_phase_handlers(cf, cmcf) != NGX_OK0) { | |||
327 | return NGX_CONF_ERROR(void *) -1; | |||
328 | } | |||
329 | ||||
330 | ||||
331 | /* optimize the lists of ports, addresses and server names */ | |||
332 | ||||
333 | if (ngx_http_optimize_servers(cf, cmcf, cmcf->ports) != NGX_OK0) { | |||
334 | return NGX_CONF_ERROR(void *) -1; | |||
335 | } | |||
336 | ||||
337 | return NGX_CONF_OK((void*)0); | |||
338 | ||||
339 | failed: | |||
340 | ||||
341 | *cf = pcf; | |||
342 | ||||
343 | return rv; | |||
344 | } | |||
345 | ||||
346 | ||||
347 | static ngx_int_t | |||
348 | ngx_http_init_phases(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf) | |||
349 | { | |||
350 | if (ngx_array_init(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers, | |||
351 | cf->pool, 1, sizeof(ngx_http_handler_pt)) | |||
352 | != NGX_OK0) | |||
353 | { | |||
354 | return NGX_ERROR-1; | |||
355 | } | |||
356 | ||||
357 | if (ngx_array_init(&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers, | |||
358 | cf->pool, 1, sizeof(ngx_http_handler_pt)) | |||
359 | != NGX_OK0) | |||
360 | { | |||
361 | return NGX_ERROR-1; | |||
362 | } | |||
363 | ||||
364 | if (ngx_array_init(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers, | |||
365 | cf->pool, 1, sizeof(ngx_http_handler_pt)) | |||
366 | != NGX_OK0) | |||
367 | { | |||
368 | return NGX_ERROR-1; | |||
369 | } | |||
370 | ||||
371 | if (ngx_array_init(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers, | |||
372 | cf->pool, 1, sizeof(ngx_http_handler_pt)) | |||
373 | != NGX_OK0) | |||
374 | { | |||
375 | return NGX_ERROR-1; | |||
376 | } | |||
377 | ||||
378 | if (ngx_array_init(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers, | |||
379 | cf->pool, 2, sizeof(ngx_http_handler_pt)) | |||
380 | != NGX_OK0) | |||
381 | { | |||
382 | return NGX_ERROR-1; | |||
383 | } | |||
384 | ||||
385 | if (ngx_array_init(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers, | |||
386 | cf->pool, 4, sizeof(ngx_http_handler_pt)) | |||
387 | != NGX_OK0) | |||
388 | { | |||
389 | return NGX_ERROR-1; | |||
390 | } | |||
391 | ||||
392 | if (ngx_array_init(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers, | |||
393 | cf->pool, 1, sizeof(ngx_http_handler_pt)) | |||
394 | != NGX_OK0) | |||
395 | { | |||
396 | return NGX_ERROR-1; | |||
397 | } | |||
398 | ||||
399 | return NGX_OK0; | |||
400 | } | |||
401 | ||||
402 | ||||
403 | static ngx_int_t | |||
404 | ngx_http_init_headers_in_hash(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf) | |||
405 | { | |||
406 | ngx_array_t headers_in; | |||
407 | ngx_hash_key_t *hk; | |||
408 | ngx_hash_init_t hash; | |||
409 | ngx_http_header_t *header; | |||
410 | ||||
411 | if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t)) | |||
412 | != NGX_OK0) | |||
413 | { | |||
414 | return NGX_ERROR-1; | |||
415 | } | |||
416 | ||||
417 | for (header = ngx_http_headers_in; header->name.len; header++) { | |||
418 | hk = ngx_array_push(&headers_in); | |||
419 | if (hk == NULL((void*)0)) { | |||
420 | return NGX_ERROR-1; | |||
421 | } | |||
422 | ||||
423 | hk->key = header->name; | |||
424 | hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len); | |||
425 | hk->value = header; | |||
426 | } | |||
427 | ||||
428 | hash.hash = &cmcf->headers_in_hash; | |||
429 | hash.key = ngx_hash_key_lc; | |||
430 | hash.max_size = 512; | |||
431 | hash.bucket_size = ngx_align(64, ngx_cacheline_size)(((64) + (ngx_cacheline_size - 1)) & ~(ngx_cacheline_size - 1)); | |||
432 | hash.name = "headers_in_hash"; | |||
433 | hash.pool = cf->pool; | |||
434 | hash.temp_pool = NULL((void*)0); | |||
435 | ||||
436 | if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK0) { | |||
437 | return NGX_ERROR-1; | |||
438 | } | |||
439 | ||||
440 | return NGX_OK0; | |||
441 | } | |||
442 | ||||
443 | ||||
444 | static ngx_int_t | |||
445 | ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf) | |||
446 | { | |||
447 | ngx_int_t j; | |||
448 | ngx_uint_t i, n; | |||
449 | ngx_uint_t find_config_index, use_rewrite, use_access; | |||
450 | ngx_http_handler_pt *h; | |||
451 | ngx_http_phase_handler_t *ph; | |||
452 | ngx_http_phase_handler_pt checker; | |||
453 | ||||
454 | cmcf->phase_engine.server_rewrite_index = (ngx_uint_t) -1; | |||
455 | cmcf->phase_engine.location_rewrite_index = (ngx_uint_t) -1; | |||
456 | find_config_index = 0; | |||
457 | use_rewrite = cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers.nelts ? 1 : 0; | |||
458 | use_access = cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers.nelts ? 1 : 0; | |||
459 | ||||
460 | n = use_rewrite + use_access + cmcf->try_files + 1 /* find config phase */; | |||
461 | ||||
462 | for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) { | |||
463 | n += cmcf->phases[i].handlers.nelts; | |||
464 | } | |||
465 | ||||
466 | ph = ngx_pcalloc(cf->pool, | |||
467 | n * sizeof(ngx_http_phase_handler_t) + sizeof(void *)); | |||
468 | if (ph == NULL((void*)0)) { | |||
469 | return NGX_ERROR-1; | |||
470 | } | |||
471 | ||||
472 | cmcf->phase_engine.handlers = ph; | |||
473 | n = 0; | |||
474 | ||||
475 | for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) { | |||
476 | h = cmcf->phases[i].handlers.elts; | |||
477 | ||||
478 | switch (i) { | |||
479 | ||||
480 | case NGX_HTTP_SERVER_REWRITE_PHASE: | |||
481 | if (cmcf->phase_engine.server_rewrite_index == (ngx_uint_t) -1) { | |||
482 | cmcf->phase_engine.server_rewrite_index = n; | |||
483 | } | |||
484 | checker = ngx_http_core_rewrite_phase; | |||
485 | ||||
486 | break; | |||
487 | ||||
488 | case NGX_HTTP_FIND_CONFIG_PHASE: | |||
489 | find_config_index = n; | |||
490 | ||||
491 | ph->checker = ngx_http_core_find_config_phase; | |||
492 | n++; | |||
493 | ph++; | |||
494 | ||||
495 | continue; | |||
496 | ||||
497 | case NGX_HTTP_REWRITE_PHASE: | |||
498 | if (cmcf->phase_engine.location_rewrite_index == (ngx_uint_t) -1) { | |||
499 | cmcf->phase_engine.location_rewrite_index = n; | |||
500 | } | |||
501 | checker = ngx_http_core_rewrite_phase; | |||
502 | ||||
503 | break; | |||
504 | ||||
505 | case NGX_HTTP_POST_REWRITE_PHASE: | |||
506 | if (use_rewrite) { | |||
507 | ph->checker = ngx_http_core_post_rewrite_phase; | |||
508 | ph->next = find_config_index; | |||
509 | n++; | |||
510 | ph++; | |||
511 | } | |||
512 | ||||
513 | continue; | |||
514 | ||||
515 | case NGX_HTTP_ACCESS_PHASE: | |||
516 | checker = ngx_http_core_access_phase; | |||
517 | n++; | |||
518 | break; | |||
519 | ||||
520 | case NGX_HTTP_POST_ACCESS_PHASE: | |||
521 | if (use_access) { | |||
522 | ph->checker = ngx_http_core_post_access_phase; | |||
523 | ph->next = n; | |||
524 | ph++; | |||
525 | } | |||
526 | ||||
527 | continue; | |||
528 | ||||
529 | case NGX_HTTP_TRY_FILES_PHASE: | |||
530 | if (cmcf->try_files) { | |||
531 | ph->checker = ngx_http_core_try_files_phase; | |||
532 | n++; | |||
533 | ph++; | |||
534 | } | |||
535 | ||||
536 | continue; | |||
537 | ||||
538 | case NGX_HTTP_CONTENT_PHASE: | |||
539 | checker = ngx_http_core_content_phase; | |||
540 | break; | |||
541 | ||||
542 | default: | |||
543 | checker = ngx_http_core_generic_phase; | |||
544 | } | |||
545 | ||||
546 | n += cmcf->phases[i].handlers.nelts; | |||
547 | ||||
548 | for (j = cmcf->phases[i].handlers.nelts - 1; j >=0; j--) { | |||
549 | ph->checker = checker; | |||
550 | ph->handler = h[j]; | |||
551 | ph->next = n; | |||
552 | ph++; | |||
553 | } | |||
554 | } | |||
555 | ||||
556 | return NGX_OK0; | |||
557 | } | |||
558 | ||||
559 | ||||
560 | static char * | |||
561 | ngx_http_merge_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf, | |||
562 | ngx_http_module_t *module, ngx_uint_t ctx_index) | |||
563 | { | |||
564 | char *rv; | |||
565 | ngx_uint_t s; | |||
566 | ngx_http_conf_ctx_t *ctx, saved; | |||
567 | ngx_http_core_loc_conf_t *clcf; | |||
568 | ngx_http_core_srv_conf_t **cscfp; | |||
569 | ||||
570 | cscfp = cmcf->servers.elts; | |||
571 | ctx = (ngx_http_conf_ctx_t *) cf->ctx; | |||
572 | saved = *ctx; | |||
573 | rv = NGX_CONF_OK((void*)0); | |||
574 | ||||
575 | for (s = 0; s < cmcf->servers.nelts; s++) { | |||
576 | ||||
577 | /* merge the server{}s' srv_conf's */ | |||
578 | ||||
579 | ctx->srv_conf = cscfp[s]->ctx->srv_conf; | |||
580 | ||||
581 | if (module->merge_srv_conf) { | |||
582 | rv = module->merge_srv_conf(cf, saved.srv_conf[ctx_index], | |||
583 | cscfp[s]->ctx->srv_conf[ctx_index]); | |||
584 | if (rv != NGX_CONF_OK((void*)0)) { | |||
585 | goto failed; | |||
586 | } | |||
587 | } | |||
588 | ||||
589 | if (module->merge_loc_conf) { | |||
590 | ||||
591 | /* merge the server{}'s loc_conf */ | |||
592 | ||||
593 | ctx->loc_conf = cscfp[s]->ctx->loc_conf; | |||
594 | ||||
595 | rv = module->merge_loc_conf(cf, saved.loc_conf[ctx_index], | |||
596 | cscfp[s]->ctx->loc_conf[ctx_index]); | |||
597 | if (rv != NGX_CONF_OK((void*)0)) { | |||
598 | goto failed; | |||
599 | } | |||
600 | ||||
601 | /* merge the locations{}' loc_conf's */ | |||
602 | ||||
603 | clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index]; | |||
604 | ||||
605 | rv = ngx_http_merge_locations(cf, clcf->locations, | |||
606 | cscfp[s]->ctx->loc_conf, | |||
607 | module, ctx_index); | |||
608 | if (rv != NGX_CONF_OK((void*)0)) { | |||
609 | goto failed; | |||
610 | } | |||
611 | } | |||
612 | } | |||
613 | ||||
614 | failed: | |||
615 | ||||
616 | *ctx = saved; | |||
617 | ||||
618 | return rv; | |||
619 | } | |||
620 | ||||
621 | ||||
622 | static char * | |||
623 | ngx_http_merge_locations(ngx_conf_t *cf, ngx_queue_t *locations, | |||
624 | void **loc_conf, ngx_http_module_t *module, ngx_uint_t ctx_index) | |||
625 | { | |||
626 | char *rv; | |||
627 | ngx_queue_t *q; | |||
628 | ngx_http_conf_ctx_t *ctx, saved; | |||
629 | ngx_http_core_loc_conf_t *clcf; | |||
630 | ngx_http_location_queue_t *lq; | |||
631 | ||||
632 | if (locations == NULL((void*)0)) { | |||
633 | return NGX_CONF_OK((void*)0); | |||
634 | } | |||
635 | ||||
636 | ctx = (ngx_http_conf_ctx_t *) cf->ctx; | |||
637 | saved = *ctx; | |||
638 | ||||
639 | for (q = ngx_queue_head(locations)(locations)->next; | |||
640 | q != ngx_queue_sentinel(locations)(locations); | |||
641 | q = ngx_queue_next(q)(q)->next) | |||
642 | { | |||
643 | lq = (ngx_http_location_queue_t *) q; | |||
644 | ||||
645 | clcf = lq->exact ? lq->exact : lq->inclusive; | |||
646 | ctx->loc_conf = clcf->loc_conf; | |||
647 | ||||
648 | rv = module->merge_loc_conf(cf, loc_conf[ctx_index], | |||
649 | clcf->loc_conf[ctx_index]); | |||
650 | if (rv != NGX_CONF_OK((void*)0)) { | |||
651 | return rv; | |||
652 | } | |||
653 | ||||
654 | rv = ngx_http_merge_locations(cf, clcf->locations, clcf->loc_conf, | |||
655 | module, ctx_index); | |||
656 | if (rv != NGX_CONF_OK((void*)0)) { | |||
657 | return rv; | |||
658 | } | |||
659 | } | |||
660 | ||||
661 | *ctx = saved; | |||
662 | ||||
663 | return NGX_CONF_OK((void*)0); | |||
664 | } | |||
665 | ||||
666 | ||||
667 | static ngx_int_t | |||
668 | ngx_http_init_locations(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, | |||
669 | ngx_http_core_loc_conf_t *pclcf) | |||
670 | { | |||
671 | ngx_uint_t n; | |||
672 | ngx_queue_t *q, *locations, *named, tail; | |||
673 | ngx_http_core_loc_conf_t *clcf; | |||
674 | ngx_http_location_queue_t *lq; | |||
675 | ngx_http_core_loc_conf_t **clcfp; | |||
676 | #if (NGX_PCRE1) | |||
677 | ngx_uint_t r; | |||
678 | ngx_queue_t *regex; | |||
679 | #endif | |||
680 | ||||
681 | locations = pclcf->locations; | |||
682 | ||||
683 | if (locations == NULL((void*)0)) { | |||
| ||||
684 | return NGX_OK0; | |||
685 | } | |||
686 | ||||
687 | ngx_queue_sort(locations, ngx_http_cmp_locations); | |||
688 | ||||
689 | named = NULL((void*)0); | |||
690 | n = 0; | |||
691 | #if (NGX_PCRE1) | |||
692 | regex = NULL((void*)0); | |||
693 | r = 0; | |||
694 | #endif | |||
695 | ||||
696 | for (q = ngx_queue_head(locations)(locations)->next; | |||
697 | q != ngx_queue_sentinel(locations)(locations); | |||
698 | q = ngx_queue_next(q)(q)->next) | |||
699 | { | |||
700 | lq = (ngx_http_location_queue_t *) q; | |||
701 | ||||
702 | clcf = lq->exact ? lq->exact : lq->inclusive; | |||
703 | ||||
704 | if (ngx_http_init_locations(cf, NULL((void*)0), clcf) != NGX_OK0) { | |||
705 | return NGX_ERROR-1; | |||
706 | } | |||
707 | ||||
708 | #if (NGX_PCRE1) | |||
709 | ||||
710 | if (clcf->regex) { | |||
711 | r++; | |||
712 | ||||
713 | if (regex == NULL((void*)0)) { | |||
714 | regex = q; | |||
715 | } | |||
716 | ||||
717 | continue; | |||
718 | } | |||
719 | ||||
720 | #endif | |||
721 | ||||
722 | if (clcf->named) { | |||
723 | n++; | |||
724 | ||||
725 | if (named == NULL((void*)0)) { | |||
726 | named = q; | |||
727 | } | |||
728 | ||||
729 | continue; | |||
730 | } | |||
731 | ||||
732 | if (clcf->noname) { | |||
733 | break; | |||
734 | } | |||
735 | } | |||
736 | ||||
737 | if (q != ngx_queue_sentinel(locations)(locations)) { | |||
738 | ngx_queue_split(locations, q, &tail)(&tail)->prev = (locations)->prev; (&tail)-> prev->next = &tail; (&tail)->next = q; (locations )->prev = (q)->prev; (locations)->prev->next = locations ; (q)->prev = &tail;; | |||
739 | } | |||
740 | ||||
741 | if (named) { | |||
742 | clcfp = ngx_palloc(cf->pool, | |||
743 | (n + 1) * sizeof(ngx_http_core_loc_conf_t *)); | |||
744 | if (clcfp == NULL((void*)0)) { | |||
745 | return NGX_ERROR-1; | |||
746 | } | |||
747 | ||||
748 | cscf->named_locations = clcfp; | |||
| ||||
749 | ||||
750 | for (q = named; | |||
751 | q != ngx_queue_sentinel(locations)(locations); | |||
752 | q = ngx_queue_next(q)(q)->next) | |||
753 | { | |||
754 | lq = (ngx_http_location_queue_t *) q; | |||
755 | ||||
756 | *(clcfp++) = lq->exact; | |||
757 | } | |||
758 | ||||
759 | *clcfp = NULL((void*)0); | |||
760 | ||||
761 | ngx_queue_split(locations, named, &tail)(&tail)->prev = (locations)->prev; (&tail)-> prev->next = &tail; (&tail)->next = named; (locations )->prev = (named)->prev; (locations)->prev->next = locations; (named)->prev = &tail;; | |||
762 | } | |||
763 | ||||
764 | #if (NGX_PCRE1) | |||
765 | ||||
766 | if (regex) { | |||
767 | ||||
768 | clcfp = ngx_palloc(cf->pool, | |||
769 | (r + 1) * sizeof(ngx_http_core_loc_conf_t *)); | |||
770 | if (clcfp == NULL((void*)0)) { | |||
771 | return NGX_ERROR-1; | |||
772 | } | |||
773 | ||||
774 | pclcf->regex_locations = clcfp; | |||
775 | ||||
776 | for (q = regex; | |||
777 | q != ngx_queue_sentinel(locations)(locations); | |||
778 | q = ngx_queue_next(q)(q)->next) | |||
779 | { | |||
780 | lq = (ngx_http_location_queue_t *) q; | |||
781 | ||||
782 | *(clcfp++) = lq->exact; | |||
783 | } | |||
784 | ||||
785 | *clcfp = NULL((void*)0); | |||
786 | ||||
787 | ngx_queue_split(locations, regex, &tail)(&tail)->prev = (locations)->prev; (&tail)-> prev->next = &tail; (&tail)->next = regex; (locations )->prev = (regex)->prev; (locations)->prev->next = locations; (regex)->prev = &tail;; | |||
788 | } | |||
789 | ||||
790 | #endif | |||
791 | ||||
792 | return NGX_OK0; | |||
793 | } | |||
794 | ||||
795 | ||||
796 | static ngx_int_t | |||
797 | ngx_http_init_static_location_trees(ngx_conf_t *cf, | |||
798 | ngx_http_core_loc_conf_t *pclcf) | |||
799 | { | |||
800 | ngx_queue_t *q, *locations; | |||
801 | ngx_http_core_loc_conf_t *clcf; | |||
802 | ngx_http_location_queue_t *lq; | |||
803 | ||||
804 | locations = pclcf->locations; | |||
805 | ||||
806 | if (locations == NULL((void*)0)) { | |||
807 | return NGX_OK0; | |||
808 | } | |||
809 | ||||
810 | if (ngx_queue_empty(locations)(locations == (locations)->prev)) { | |||
811 | return NGX_OK0; | |||
812 | } | |||
813 | ||||
814 | for (q = ngx_queue_head(locations)(locations)->next; | |||
815 | q != ngx_queue_sentinel(locations)(locations); | |||
816 | q = ngx_queue_next(q)(q)->next) | |||
817 | { | |||
818 | lq = (ngx_http_location_queue_t *) q; | |||
819 | ||||
820 | clcf = lq->exact ? lq->exact : lq->inclusive; | |||
821 | ||||
822 | if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK0) { | |||
823 | return NGX_ERROR-1; | |||
824 | } | |||
825 | } | |||
826 | ||||
827 | if (ngx_http_join_exact_locations(cf, locations) != NGX_OK0) { | |||
828 | return NGX_ERROR-1; | |||
829 | } | |||
830 | ||||
831 | ngx_http_create_locations_list(locations, ngx_queue_head(locations)(locations)->next); | |||
832 | ||||
833 | pclcf->static_locations = ngx_http_create_locations_tree(cf, locations, 0); | |||
834 | if (pclcf->static_locations == NULL((void*)0)) { | |||
835 | return NGX_ERROR-1; | |||
836 | } | |||
837 | ||||
838 | return NGX_OK0; | |||
839 | } | |||
840 | ||||
841 | ||||
842 | ngx_int_t | |||
843 | ngx_http_add_location(ngx_conf_t *cf, ngx_queue_t **locations, | |||
844 | ngx_http_core_loc_conf_t *clcf) | |||
845 | { | |||
846 | ngx_http_location_queue_t *lq; | |||
847 | ||||
848 | if (*locations == NULL((void*)0)) { | |||
849 | *locations = ngx_palloc(cf->temp_pool, | |||
850 | sizeof(ngx_http_location_queue_t)); | |||
851 | if (*locations == NULL((void*)0)) { | |||
852 | return NGX_ERROR-1; | |||
853 | } | |||
854 | ||||
855 | ngx_queue_init(*locations)(*locations)->prev = *locations; (*locations)->next = * locations; | |||
856 | } | |||
857 | ||||
858 | lq = ngx_palloc(cf->temp_pool, sizeof(ngx_http_location_queue_t)); | |||
859 | if (lq == NULL((void*)0)) { | |||
860 | return NGX_ERROR-1; | |||
861 | } | |||
862 | ||||
863 | if (clcf->exact_match | |||
864 | #if (NGX_PCRE1) | |||
865 | || clcf->regex | |||
866 | #endif | |||
867 | || clcf->named || clcf->noname) | |||
868 | { | |||
869 | lq->exact = clcf; | |||
870 | lq->inclusive = NULL((void*)0); | |||
871 | ||||
872 | } else { | |||
873 | lq->exact = NULL((void*)0); | |||
874 | lq->inclusive = clcf; | |||
875 | } | |||
876 | ||||
877 | lq->name = &clcf->name; | |||
878 | lq->file_name = cf->conf_file->file.name.data; | |||
879 | lq->line = cf->conf_file->line; | |||
880 | ||||
881 | ngx_queue_init(&lq->list)(&lq->list)->prev = &lq->list; (&lq-> list)->next = &lq->list; | |||
882 | ||||
883 | ngx_queue_insert_tail(*locations, &lq->queue)(&lq->queue)->prev = (*locations)->prev; (&lq ->queue)->prev->next = &lq->queue; (&lq-> queue)->next = *locations; (*locations)->prev = &lq ->queue; | |||
884 | ||||
885 | return NGX_OK0; | |||
886 | } | |||
887 | ||||
888 | ||||
889 | static ngx_int_t | |||
890 | ngx_http_cmp_locations(const ngx_queue_t *one, const ngx_queue_t *two) | |||
891 | { | |||
892 | ngx_int_t rc; | |||
893 | ngx_http_core_loc_conf_t *first, *second; | |||
894 | ngx_http_location_queue_t *lq1, *lq2; | |||
895 | ||||
896 | lq1 = (ngx_http_location_queue_t *) one; | |||
897 | lq2 = (ngx_http_location_queue_t *) two; | |||
898 | ||||
899 | first = lq1->exact ? lq1->exact : lq1->inclusive; | |||
900 | second = lq2->exact ? lq2->exact : lq2->inclusive; | |||
901 | ||||
902 | if (first->noname && !second->noname) { | |||
903 | /* shift no named locations to the end */ | |||
904 | return 1; | |||
905 | } | |||
906 | ||||
907 | if (!first->noname && second->noname) { | |||
908 | /* shift no named locations to the end */ | |||
909 | return -1; | |||
910 | } | |||
911 | ||||
912 | if (first->noname || second->noname) { | |||
913 | /* do not sort no named locations */ | |||
914 | return 0; | |||
915 | } | |||
916 | ||||
917 | if (first->named && !second->named) { | |||
918 | /* shift named locations to the end */ | |||
919 | return 1; | |||
920 | } | |||
921 | ||||
922 | if (!first->named && second->named) { | |||
923 | /* shift named locations to the end */ | |||
924 | return -1; | |||
925 | } | |||
926 | ||||
927 | if (first->named && second->named) { | |||
928 | return ngx_strcmp(first->name.data, second->name.data)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p ((const char *) first->name.data) && __builtin_constant_p ((const char *) second->name.data) && (__s1_len = strlen ((const char *) first->name.data), __s2_len = strlen ((const char *) second->name.data), (!((size_t)(const void *)(((const char *) first->name.data) + 1) - (size_t)(const void *)((const char *) first->name.data) == 1) || __s1_len >= 4) && (!((size_t)(const void *)(((const char * ) second->name.data) + 1) - (size_t)(const void *)((const char *) second->name.data) == 1) || __s2_len >= 4)) ? __builtin_strcmp ((const char *) first->name.data, (const char *) second-> name.data) : (__builtin_constant_p ((const char *) first-> name.data) && ((size_t)(const void *)(((const char *) first->name.data) + 1) - (size_t)(const void *)((const char *) first->name.data) == 1) && (__s1_len = strlen ( (const char *) first->name.data), __s1_len < 4) ? (__builtin_constant_p ((const char *) second->name.data) && ((size_t)(const void *)(((const char *) second->name.data) + 1) - (size_t )(const void *)((const char *) second->name.data) == 1) ? __builtin_strcmp ((const char *) first->name.data, (const char *) second-> name.data) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ((const char *) second->name .data); int __result = (((const unsigned char *) (const char * ) ((const char *) first->name.data))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ((const char *) first->name.data)) [1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ((const char *) first->name.data))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ((const char *) first->name.data))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p ((const char *) second->name.data) && ((size_t)(const void *)(((const char *) second->name.data) + 1) - (size_t)(const void *)((const char *) second->name.data) == 1) && (__s2_len = strlen ((const char *) second->name.data), __s2_len < 4) ? (__builtin_constant_p ((const char *) first->name .data) && ((size_t)(const void *)(((const char *) first ->name.data) + 1) - (size_t)(const void *)((const char *) first ->name.data) == 1) ? __builtin_strcmp ((const char *) first ->name.data, (const char *) second->name.data) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ((const char *) first->name.data); int __result = (((const unsigned char *) (const char *) ((const char *) second ->name.data))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ((const char *) second->name.data))[1] - __s2[1]) ; if (__s2_len > 1 && __result == 0) { __result = ( ((const unsigned char *) (const char *) ((const char *) second ->name.data))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ((const char *) second->name.data))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp ((const char *) first-> name.data, (const char *) second->name.data)))); }); | |||
929 | } | |||
930 | ||||
931 | #if (NGX_PCRE1) | |||
932 | ||||
933 | if (first->regex && !second->regex) { | |||
934 | /* shift the regex matches to the end */ | |||
935 | return 1; | |||
936 | } | |||
937 | ||||
938 | if (!first->regex && second->regex) { | |||
939 | /* shift the regex matches to the end */ | |||
940 | return -1; | |||
941 | } | |||
942 | ||||
943 | if (first->regex || second->regex) { | |||
944 | /* do not sort the regex matches */ | |||
945 | return 0; | |||
946 | } | |||
947 | ||||
948 | #endif | |||
949 | ||||
950 | rc = ngx_filename_cmp(first->name.data, second->name.data, | |||
951 | ngx_min(first->name.len, second->name.len)((first->name.len > second->name.len) ? (second-> name.len) : (first->name.len)) + 1); | |||
952 | ||||
953 | if (rc == 0 && !first->exact_match && second->exact_match) { | |||
954 | /* an exact match must be before the same inclusive one */ | |||
955 | return 1; | |||
956 | } | |||
957 | ||||
958 | return rc; | |||
959 | } | |||
960 | ||||
961 | ||||
962 | static ngx_int_t | |||
963 | ngx_http_join_exact_locations(ngx_conf_t *cf, ngx_queue_t *locations) | |||
964 | { | |||
965 | ngx_queue_t *q, *x; | |||
966 | ngx_http_location_queue_t *lq, *lx; | |||
967 | ||||
968 | q = ngx_queue_head(locations)(locations)->next; | |||
969 | ||||
970 | while (q != ngx_queue_last(locations)(locations)->prev) { | |||
971 | ||||
972 | x = ngx_queue_next(q)(q)->next; | |||
973 | ||||
974 | lq = (ngx_http_location_queue_t *) q; | |||
975 | lx = (ngx_http_location_queue_t *) x; | |||
976 | ||||
977 | if (lq->name->len == lx->name->len | |||
978 | && ngx_filename_cmp(lq->name->data, lx->name->data, lx->name->len) | |||
979 | == 0) | |||
980 | { | |||
981 | if ((lq->exact && lx->exact) || (lq->inclusive && lx->inclusive)) { | |||
982 | ngx_log_error(NGX_LOG_EMERG, cf->log, 0,if ((cf->log)->log_level >= 1) ngx_log_error_core(1, cf->log, 0, "duplicate location \"%V\" in %s:%ui", lx-> name, lx->file_name, lx->line) | |||
983 | "duplicate location \"%V\" in %s:%ui",if ((cf->log)->log_level >= 1) ngx_log_error_core(1, cf->log, 0, "duplicate location \"%V\" in %s:%ui", lx-> name, lx->file_name, lx->line) | |||
984 | lx->name, lx->file_name, lx->line)if ((cf->log)->log_level >= 1) ngx_log_error_core(1, cf->log, 0, "duplicate location \"%V\" in %s:%ui", lx-> name, lx->file_name, lx->line); | |||
985 | ||||
986 | return NGX_ERROR-1; | |||
987 | } | |||
988 | ||||
989 | lq->inclusive = lx->inclusive; | |||
990 | ||||
991 | ngx_queue_remove(x)(x)->next->prev = (x)->prev; (x)->prev->next = (x)->next; | |||
992 | ||||
993 | continue; | |||
994 | } | |||
995 | ||||
996 | q = ngx_queue_next(q)(q)->next; | |||
997 | } | |||
998 | ||||
999 | return NGX_OK0; | |||
1000 | } | |||
1001 | ||||
1002 | ||||
1003 | static void | |||
1004 | ngx_http_create_locations_list(ngx_queue_t *locations, ngx_queue_t *q) | |||
1005 | { | |||
1006 | u_char *name; | |||
1007 | size_t len; | |||
1008 | ngx_queue_t *x, tail; | |||
1009 | ngx_http_location_queue_t *lq, *lx; | |||
1010 | ||||
1011 | if (q == ngx_queue_last(locations)(locations)->prev) { | |||
1012 | return; | |||
1013 | } | |||
1014 | ||||
1015 | lq = (ngx_http_location_queue_t *) q; | |||
1016 | ||||
1017 | if (lq->inclusive == NULL((void*)0)) { | |||
1018 | ngx_http_create_locations_list(locations, ngx_queue_next(q)(q)->next); | |||
1019 | return; | |||
1020 | } | |||
1021 | ||||
1022 | len = lq->name->len; | |||
1023 | name = lq->name->data; | |||
1024 | ||||
1025 | for (x = ngx_queue_next(q)(q)->next; | |||
1026 | x != ngx_queue_sentinel(locations)(locations); | |||
1027 | x = ngx_queue_next(x)(x)->next) | |||
1028 | { | |||
1029 | lx = (ngx_http_location_queue_t *) x; | |||
1030 | ||||
1031 | if (len > lx->name->len | |||
1032 | || ngx_filename_cmp(name, lx->name->data, len) != 0) | |||
1033 | { | |||
1034 | break; | |||
1035 | } | |||
1036 | } | |||
1037 | ||||
1038 | q = ngx_queue_next(q)(q)->next; | |||
1039 | ||||
1040 | if (q == x) { | |||
1041 | ngx_http_create_locations_list(locations, x); | |||
1042 | return; | |||
1043 | } | |||
1044 | ||||
1045 | ngx_queue_split(locations, q, &tail)(&tail)->prev = (locations)->prev; (&tail)-> prev->next = &tail; (&tail)->next = q; (locations )->prev = (q)->prev; (locations)->prev->next = locations ; (q)->prev = &tail;; | |||
1046 | ngx_queue_add(&lq->list, &tail)(&lq->list)->prev->next = (&tail)->next; ( &tail)->next->prev = (&lq->list)->prev; ( &lq->list)->prev = (&tail)->prev; (&lq-> list)->prev->next = &lq->list;; | |||
1047 | ||||
1048 | if (x == ngx_queue_sentinel(locations)(locations)) { | |||
1049 | ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list)(&lq->list)->next); | |||
1050 | return; | |||
1051 | } | |||
1052 | ||||
1053 | ngx_queue_split(&lq->list, x, &tail)(&tail)->prev = (&lq->list)->prev; (&tail )->prev->next = &tail; (&tail)->next = x; (& lq->list)->prev = (x)->prev; (&lq->list)-> prev->next = &lq->list; (x)->prev = &tail;; | |||
1054 | ngx_queue_add(locations, &tail)(locations)->prev->next = (&tail)->next; (&tail )->next->prev = (locations)->prev; (locations)->prev = (&tail)->prev; (locations)->prev->next = locations ;; | |||
1055 | ||||
1056 | ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list)(&lq->list)->next); | |||
1057 | ||||
1058 | ngx_http_create_locations_list(locations, x); | |||
1059 | } | |||
1060 | ||||
1061 | ||||
1062 | /* | |||
1063 | * to keep cache locality for left leaf nodes, allocate nodes in following | |||
1064 | * order: node, left subtree, right subtree, inclusive subtree | |||
1065 | */ | |||
1066 | ||||
1067 | static ngx_http_location_tree_node_t * | |||
1068 | ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations, | |||
1069 | size_t prefix) | |||
1070 | { | |||
1071 | size_t len; | |||
1072 | ngx_queue_t *q, tail; | |||
1073 | ngx_http_location_queue_t *lq; | |||
1074 | ngx_http_location_tree_node_t *node; | |||
1075 | ||||
1076 | q = ngx_queue_middle(locations); | |||
1077 | ||||
1078 | lq = (ngx_http_location_queue_t *) q; | |||
1079 | len = lq->name->len - prefix; | |||
1080 | ||||
1081 | node = ngx_palloc(cf->pool, | |||
1082 | offsetof(ngx_http_location_tree_node_t, name)__builtin_offsetof(ngx_http_location_tree_node_t, name) + len); | |||
1083 | if (node == NULL((void*)0)) { | |||
1084 | return NULL((void*)0); | |||
1085 | } | |||
1086 | ||||
1087 | node->left = NULL((void*)0); | |||
1088 | node->right = NULL((void*)0); | |||
1089 | node->tree = NULL((void*)0); | |||
1090 | node->exact = lq->exact; | |||
1091 | node->inclusive = lq->inclusive; | |||
1092 | ||||
1093 | node->auto_redirect = (u_char) ((lq->exact && lq->exact->auto_redirect) | |||
1094 | || (lq->inclusive && lq->inclusive->auto_redirect)); | |||
1095 | ||||
1096 | node->len = (u_char) len; | |||
1097 | ngx_memcpy(node->name, &lq->name->data[prefix], len)(void) memcpy(node->name, &lq->name->data[prefix ], len); | |||
1098 | ||||
1099 | ngx_queue_split(locations, q, &tail)(&tail)->prev = (locations)->prev; (&tail)-> prev->next = &tail; (&tail)->next = q; (locations )->prev = (q)->prev; (locations)->prev->next = locations ; (q)->prev = &tail;; | |||
1100 | ||||
1101 | if (ngx_queue_empty(locations)(locations == (locations)->prev)) { | |||
1102 | /* | |||
1103 | * ngx_queue_split() insures that if left part is empty, | |||
1104 | * then right one is empty too | |||
1105 | */ | |||
1106 | goto inclusive; | |||
1107 | } | |||
1108 | ||||
1109 | node->left = ngx_http_create_locations_tree(cf, locations, prefix); | |||
1110 | if (node->left == NULL((void*)0)) { | |||
1111 | return NULL((void*)0); | |||
1112 | } | |||
1113 | ||||
1114 | ngx_queue_remove(q)(q)->next->prev = (q)->prev; (q)->prev->next = (q)->next; | |||
1115 | ||||
1116 | if (ngx_queue_empty(&tail)(&tail == (&tail)->prev)) { | |||
1117 | goto inclusive; | |||
1118 | } | |||
1119 | ||||
1120 | node->right = ngx_http_create_locations_tree(cf, &tail, prefix); | |||
1121 | if (node->right == NULL((void*)0)) { | |||
1122 | return NULL((void*)0); | |||
1123 | } | |||
1124 | ||||
1125 | inclusive: | |||
1126 | ||||
1127 | if (ngx_queue_empty(&lq->list)(&lq->list == (&lq->list)->prev)) { | |||
1128 | return node; | |||
1129 | } | |||
1130 | ||||
1131 | node->tree = ngx_http_create_locations_tree(cf, &lq->list, prefix + len); | |||
1132 | if (node->tree == NULL((void*)0)) { | |||
1133 | return NULL((void*)0); | |||
1134 | } | |||
1135 | ||||
1136 | return node; | |||
1137 | } | |||
1138 | ||||
1139 | ||||
1140 | ngx_int_t | |||
1141 | ngx_http_add_listen(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, | |||
1142 | ngx_http_listen_opt_t *lsopt) | |||
1143 | { | |||
1144 | in_port_t p; | |||
1145 | ngx_uint_t i; | |||
1146 | struct sockaddr *sa; | |||
1147 | struct sockaddr_in *sin; | |||
1148 | ngx_http_conf_port_t *port; | |||
1149 | ngx_http_core_main_conf_t *cmcf; | |||
1150 | #if (NGX_HAVE_INET6) | |||
1151 | struct sockaddr_in6 *sin6; | |||
1152 | #endif | |||
1153 | ||||
1154 | cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module)((ngx_http_conf_ctx_t *) cf->ctx)->main_conf[ngx_http_core_module .ctx_index]; | |||
1155 | ||||
1156 | if (cmcf->ports == NULL((void*)0)) { | |||
1157 | cmcf->ports = ngx_array_create(cf->temp_pool, 2, | |||
1158 | sizeof(ngx_http_conf_port_t)); | |||
1159 | if (cmcf->ports == NULL((void*)0)) { | |||
1160 | return NGX_ERROR-1; | |||
1161 | } | |||
1162 | } | |||
1163 | ||||
1164 | sa = &lsopt->sockaddr.sockaddr; | |||
1165 | ||||
1166 | switch (sa->sa_family) { | |||
1167 | ||||
1168 | #if (NGX_HAVE_INET6) | |||
1169 | case AF_INET610: | |||
1170 | sin6 = &lsopt->sockaddr.sockaddr_in6; | |||
1171 | p = sin6->sin6_port; | |||
1172 | break; | |||
1173 | #endif | |||
1174 | ||||
1175 | #if (NGX_HAVE_UNIX_DOMAIN1) | |||
1176 | case AF_UNIX1: | |||
1177 | p = 0; | |||
1178 | break; | |||
1179 | #endif | |||
1180 | ||||
1181 | default: /* AF_INET */ | |||
1182 | sin = &lsopt->sockaddr.sockaddr_in; | |||
1183 | p = sin->sin_port; | |||
1184 | break; | |||
1185 | } | |||
1186 | ||||
1187 | port = cmcf->ports->elts; | |||
1188 | for (i = 0; i < cmcf->ports->nelts; i++) { | |||
1189 | ||||
1190 | if (p != port[i].port || sa->sa_family != port[i].family) { | |||
1191 | continue; | |||
1192 | } | |||
1193 | ||||
1194 | /* a port is already in the port list */ | |||
1195 | ||||
1196 | return ngx_http_add_addresses(cf, cscf, &port[i], lsopt); | |||
1197 | } | |||
1198 | ||||
1199 | /* add a port to the port list */ | |||
1200 | ||||
1201 | port = ngx_array_push(cmcf->ports); | |||
1202 | if (port == NULL((void*)0)) { | |||
1203 | return NGX_ERROR-1; | |||
1204 | } | |||
1205 | ||||
1206 | port->family = sa->sa_family; | |||
1207 | port->port = p; | |||
1208 | port->addrs.elts = NULL((void*)0); | |||
1209 | ||||
1210 | return ngx_http_add_address(cf, cscf, port, lsopt); | |||
1211 | } | |||
1212 | ||||
1213 | ||||
1214 | static ngx_int_t | |||
1215 | ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, | |||
1216 | ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt) | |||
1217 | { | |||
1218 | ngx_uint_t i, default_server, proxy_protocol; | |||
1219 | ngx_http_conf_addr_t *addr; | |||
1220 | #if (NGX_HTTP_SSL) | |||
1221 | ngx_uint_t ssl; | |||
1222 | #endif | |||
1223 | #if (NGX_HTTP_V2) | |||
1224 | ngx_uint_t http2; | |||
1225 | #endif | |||
1226 | ||||
1227 | /* | |||
1228 | * we cannot compare whole sockaddr struct's as kernel | |||
1229 | * may fill some fields in inherited sockaddr struct's | |||
1230 | */ | |||
1231 | ||||
1232 | addr = port->addrs.elts; | |||
1233 | ||||
1234 | for (i = 0; i < port->addrs.nelts; i++) { | |||
1235 | ||||
1236 | if (ngx_cmp_sockaddr(&lsopt->sockaddr.sockaddr, lsopt->socklen, | |||
1237 | &addr[i].opt.sockaddr.sockaddr, | |||
1238 | addr[i].opt.socklen, 0) | |||
1239 | != NGX_OK0) | |||
1240 | { | |||
1241 | continue; | |||
1242 | } | |||
1243 | ||||
1244 | /* the address is already in the address list */ | |||
1245 | ||||
1246 | if (ngx_http_add_server(cf, cscf, &addr[i]) != NGX_OK0) { | |||
1247 | return NGX_ERROR-1; | |||
1248 | } | |||
1249 | ||||
1250 | /* preserve default_server bit during listen options overwriting */ | |||
1251 | default_server = addr[i].opt.default_server; | |||
1252 | ||||
1253 | proxy_protocol = lsopt->proxy_protocol || addr[i].opt.proxy_protocol; | |||
1254 | ||||
1255 | #if (NGX_HTTP_SSL) | |||
1256 | ssl = lsopt->ssl || addr[i].opt.ssl; | |||
1257 | #endif | |||
1258 | #if (NGX_HTTP_V2) | |||
1259 | http2 = lsopt->http2 || addr[i].opt.http2; | |||
1260 | #endif | |||
1261 | ||||
1262 | if (lsopt->set) { | |||
1263 | ||||
1264 | if (addr[i].opt.set) { | |||
1265 | ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0, | |||
1266 | "duplicate listen options for %s", addr[i].opt.addr); | |||
1267 | return NGX_ERROR-1; | |||
1268 | } | |||
1269 | ||||
1270 | addr[i].opt = *lsopt; | |||
1271 | } | |||
1272 | ||||
1273 | /* check the duplicate "default" server for this address:port */ | |||
1274 | ||||
1275 | if (lsopt->default_server) { | |||
1276 | ||||
1277 | if (default_server) { | |||
1278 | ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0, | |||
1279 | "a duplicate default server for %s", addr[i].opt.addr); | |||
1280 | return NGX_ERROR-1; | |||
1281 | } | |||
1282 | ||||
1283 | default_server = 1; | |||
1284 | addr[i].default_server = cscf; | |||
1285 | } | |||
1286 | ||||
1287 | addr[i].opt.default_server = default_server; | |||
1288 | addr[i].opt.proxy_protocol = proxy_protocol; | |||
1289 | #if (NGX_HTTP_SSL) | |||
1290 | addr[i].opt.ssl = ssl; | |||
1291 | #endif | |||
1292 | #if (NGX_HTTP_V2) | |||
1293 | addr[i].opt.http2 = http2; | |||
1294 | #endif | |||
1295 | ||||
1296 | return NGX_OK0; | |||
1297 | } | |||
1298 | ||||
1299 | /* add the address to the addresses list that bound to this port */ | |||
1300 | ||||
1301 | return ngx_http_add_address(cf, cscf, port, lsopt); | |||
1302 | } | |||
1303 | ||||
1304 | ||||
1305 | /* | |||
1306 | * add the server address, the server names and the server core module | |||
1307 | * configurations to the port list | |||
1308 | */ | |||
1309 | ||||
1310 | static ngx_int_t | |||
1311 | ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, | |||
1312 | ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt) | |||
1313 | { | |||
1314 | ngx_http_conf_addr_t *addr; | |||
1315 | ||||
1316 | if (port->addrs.elts == NULL((void*)0)) { | |||
1317 | if (ngx_array_init(&port->addrs, cf->temp_pool, 4, | |||
1318 | sizeof(ngx_http_conf_addr_t)) | |||
1319 | != NGX_OK0) | |||
1320 | { | |||
1321 | return NGX_ERROR-1; | |||
1322 | } | |||
1323 | } | |||
1324 | ||||
1325 | #if (NGX_HTTP_V2 && NGX_HTTP_SSL \ | |||
1326 | && !defined TLSEXT_TYPE_application_layer_protocol_negotiation \ | |||
1327 | && !defined TLSEXT_TYPE_next_proto_neg) | |||
1328 | ||||
1329 | if (lsopt->http2 && lsopt->ssl) { | |||
1330 | ngx_conf_log_error(NGX_LOG_WARN5, cf, 0, | |||
1331 | "nginx was built with OpenSSL that lacks ALPN " | |||
1332 | "and NPN support, HTTP/2 is not enabled for %s", | |||
1333 | lsopt->addr); | |||
1334 | } | |||
1335 | ||||
1336 | #endif | |||
1337 | ||||
1338 | addr = ngx_array_push(&port->addrs); | |||
1339 | if (addr == NULL((void*)0)) { | |||
1340 | return NGX_ERROR-1; | |||
1341 | } | |||
1342 | ||||
1343 | addr->opt = *lsopt; | |||
1344 | addr->hash.buckets = NULL((void*)0); | |||
1345 | addr->hash.size = 0; | |||
1346 | addr->wc_head = NULL((void*)0); | |||
1347 | addr->wc_tail = NULL((void*)0); | |||
1348 | #if (NGX_PCRE1) | |||
1349 | addr->nregex = 0; | |||
1350 | addr->regex = NULL((void*)0); | |||
1351 | #endif | |||
1352 | addr->default_server = cscf; | |||
1353 | addr->servers.elts = NULL((void*)0); | |||
1354 | ||||
1355 | return ngx_http_add_server(cf, cscf, addr); | |||
1356 | } | |||
1357 | ||||
1358 | ||||
1359 | /* add the server core module configuration to the address:port */ | |||
1360 | ||||
1361 | static ngx_int_t | |||
1362 | ngx_http_add_server(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, | |||
1363 | ngx_http_conf_addr_t *addr) | |||
1364 | { | |||
1365 | ngx_uint_t i; | |||
1366 | ngx_http_core_srv_conf_t **server; | |||
1367 | ||||
1368 | if (addr->servers.elts == NULL((void*)0)) { | |||
1369 | if (ngx_array_init(&addr->servers, cf->temp_pool, 4, | |||
1370 | sizeof(ngx_http_core_srv_conf_t *)) | |||
1371 | != NGX_OK0) | |||
1372 | { | |||
1373 | return NGX_ERROR-1; | |||
1374 | } | |||
1375 | ||||
1376 | } else { | |||
1377 | server = addr->servers.elts; | |||
1378 | for (i = 0; i < addr->servers.nelts; i++) { | |||
1379 | if (server[i] == cscf) { | |||
1380 | ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0, | |||
1381 | "a duplicate listen %s", addr->opt.addr); | |||
1382 | return NGX_ERROR-1; | |||
1383 | } | |||
1384 | } | |||
1385 | } | |||
1386 | ||||
1387 | server = ngx_array_push(&addr->servers); | |||
1388 | if (server == NULL((void*)0)) { | |||
1389 | return NGX_ERROR-1; | |||
1390 | } | |||
1391 | ||||
1392 | *server = cscf; | |||
1393 | ||||
1394 | return NGX_OK0; | |||
1395 | } | |||
1396 | ||||
1397 | ||||
1398 | static ngx_int_t | |||
1399 | ngx_http_optimize_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf, | |||
1400 | ngx_array_t *ports) | |||
1401 | { | |||
1402 | ngx_uint_t p, a; | |||
1403 | ngx_http_conf_port_t *port; | |||
1404 | ngx_http_conf_addr_t *addr; | |||
1405 | ||||
1406 | if (ports == NULL((void*)0)) { | |||
1407 | return NGX_OK0; | |||
1408 | } | |||
1409 | ||||
1410 | port = ports->elts; | |||
1411 | for (p = 0; p < ports->nelts; p++) { | |||
1412 | ||||
1413 | ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts, | |||
1414 | sizeof(ngx_http_conf_addr_t), ngx_http_cmp_conf_addrs); | |||
1415 | ||||
1416 | /* | |||
1417 | * check whether all name-based servers have the same | |||
1418 | * configuration as a default server for given address:port | |||
1419 | */ | |||
1420 | ||||
1421 | addr = port[p].addrs.elts; | |||
1422 | for (a = 0; a < port[p].addrs.nelts; a++) { | |||
1423 | ||||
1424 | if (addr[a].servers.nelts > 1 | |||
1425 | #if (NGX_PCRE1) | |||
1426 | || addr[a].default_server->captures | |||
1427 | #endif | |||
1428 | ) | |||
1429 | { | |||
1430 | if (ngx_http_server_names(cf, cmcf, &addr[a]) != NGX_OK0) { | |||
1431 | return NGX_ERROR-1; | |||
1432 | } | |||
1433 | } | |||
1434 | } | |||
1435 | ||||
1436 | if (ngx_http_init_listening(cf, &port[p]) != NGX_OK0) { | |||
1437 | return NGX_ERROR-1; | |||
1438 | } | |||
1439 | } | |||
1440 | ||||
1441 | return NGX_OK0; | |||
1442 | } | |||
1443 | ||||
1444 | ||||
1445 | static ngx_int_t | |||
1446 | ngx_http_server_names(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf, | |||
1447 | ngx_http_conf_addr_t *addr) | |||
1448 | { | |||
1449 | ngx_int_t rc; | |||
1450 | ngx_uint_t n, s; | |||
1451 | ngx_hash_init_t hash; | |||
1452 | ngx_hash_keys_arrays_t ha; | |||
1453 | ngx_http_server_name_t *name; | |||
1454 | ngx_http_core_srv_conf_t **cscfp; | |||
1455 | #if (NGX_PCRE1) | |||
1456 | ngx_uint_t regex, i; | |||
1457 | ||||
1458 | regex = 0; | |||
1459 | #endif | |||
1460 | ||||
1461 | ngx_memzero(&ha, sizeof(ngx_hash_keys_arrays_t))(void) memset(&ha, 0, sizeof(ngx_hash_keys_arrays_t)); | |||
1462 | ||||
1463 | ha.temp_pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE(16 * 1024), cf->log); | |||
1464 | if (ha.temp_pool == NULL((void*)0)) { | |||
1465 | return NGX_ERROR-1; | |||
1466 | } | |||
1467 | ||||
1468 | ha.pool = cf->pool; | |||
1469 | ||||
1470 | if (ngx_hash_keys_array_init(&ha, NGX_HASH_LARGE2) != NGX_OK0) { | |||
1471 | goto failed; | |||
1472 | } | |||
1473 | ||||
1474 | cscfp = addr->servers.elts; | |||
1475 | ||||
1476 | for (s = 0; s < addr->servers.nelts; s++) { | |||
1477 | ||||
1478 | name = cscfp[s]->server_names.elts; | |||
1479 | ||||
1480 | for (n = 0; n < cscfp[s]->server_names.nelts; n++) { | |||
1481 | ||||
1482 | #if (NGX_PCRE1) | |||
1483 | if (name[n].regex) { | |||
1484 | regex++; | |||
1485 | continue; | |||
1486 | } | |||
1487 | #endif | |||
1488 | ||||
1489 | rc = ngx_hash_add_key(&ha, &name[n].name, name[n].server, | |||
1490 | NGX_HASH_WILDCARD_KEY1); | |||
1491 | ||||
1492 | if (rc == NGX_ERROR-1) { | |||
1493 | return NGX_ERROR-1; | |||
1494 | } | |||
1495 | ||||
1496 | if (rc == NGX_DECLINED-5) { | |||
1497 | ngx_log_error(NGX_LOG_EMERG, cf->log, 0,if ((cf->log)->log_level >= 1) ngx_log_error_core(1, cf->log, 0, "invalid server name or wildcard \"%V\" on %s" , &name[n].name, addr->opt.addr) | |||
1498 | "invalid server name or wildcard \"%V\" on %s",if ((cf->log)->log_level >= 1) ngx_log_error_core(1, cf->log, 0, "invalid server name or wildcard \"%V\" on %s" , &name[n].name, addr->opt.addr) | |||
1499 | &name[n].name, addr->opt.addr)if ((cf->log)->log_level >= 1) ngx_log_error_core(1, cf->log, 0, "invalid server name or wildcard \"%V\" on %s" , &name[n].name, addr->opt.addr); | |||
1500 | return NGX_ERROR-1; | |||
1501 | } | |||
1502 | ||||
1503 | if (rc == NGX_BUSY-3) { | |||
1504 | ngx_log_error(NGX_LOG_WARN, cf->log, 0,if ((cf->log)->log_level >= 5) ngx_log_error_core(5, cf->log, 0, "conflicting server name \"%V\" on %s, ignored" , &name[n].name, addr->opt.addr) | |||
1505 | "conflicting server name \"%V\" on %s, ignored",if ((cf->log)->log_level >= 5) ngx_log_error_core(5, cf->log, 0, "conflicting server name \"%V\" on %s, ignored" , &name[n].name, addr->opt.addr) | |||
1506 | &name[n].name, addr->opt.addr)if ((cf->log)->log_level >= 5) ngx_log_error_core(5, cf->log, 0, "conflicting server name \"%V\" on %s, ignored" , &name[n].name, addr->opt.addr); | |||
1507 | } | |||
1508 | } | |||
1509 | } | |||
1510 | ||||
1511 | hash.key = ngx_hash_key_lc; | |||
1512 | hash.max_size = cmcf->server_names_hash_max_size; | |||
1513 | hash.bucket_size = cmcf->server_names_hash_bucket_size; | |||
1514 | hash.name = "server_names_hash"; | |||
1515 | hash.pool = cf->pool; | |||
1516 | ||||
1517 | if (ha.keys.nelts) { | |||
1518 | hash.hash = &addr->hash; | |||
1519 | hash.temp_pool = NULL((void*)0); | |||
1520 | ||||
1521 | if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK0) { | |||
1522 | goto failed; | |||
1523 | } | |||
1524 | } | |||
1525 | ||||
1526 | if (ha.dns_wc_head.nelts) { | |||
1527 | ||||
1528 | ngx_qsortqsort(ha.dns_wc_head.elts, (size_t) ha.dns_wc_head.nelts, | |||
1529 | sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards); | |||
1530 | ||||
1531 | hash.hash = NULL((void*)0); | |||
1532 | hash.temp_pool = ha.temp_pool; | |||
1533 | ||||
1534 | if (ngx_hash_wildcard_init(&hash, ha.dns_wc_head.elts, | |||
1535 | ha.dns_wc_head.nelts) | |||
1536 | != NGX_OK0) | |||
1537 | { | |||
1538 | goto failed; | |||
1539 | } | |||
1540 | ||||
1541 | addr->wc_head = (ngx_hash_wildcard_t *) hash.hash; | |||
1542 | } | |||
1543 | ||||
1544 | if (ha.dns_wc_tail.nelts) { | |||
1545 | ||||
1546 | ngx_qsortqsort(ha.dns_wc_tail.elts, (size_t) ha.dns_wc_tail.nelts, | |||
1547 | sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards); | |||
1548 | ||||
1549 | hash.hash = NULL((void*)0); | |||
1550 | hash.temp_pool = ha.temp_pool; | |||
1551 | ||||
1552 | if (ngx_hash_wildcard_init(&hash, ha.dns_wc_tail.elts, | |||
1553 | ha.dns_wc_tail.nelts) | |||
1554 | != NGX_OK0) | |||
1555 | { | |||
1556 | goto failed; | |||
1557 | } | |||
1558 | ||||
1559 | addr->wc_tail = (ngx_hash_wildcard_t *) hash.hash; | |||
1560 | } | |||
1561 | ||||
1562 | ngx_destroy_pool(ha.temp_pool); | |||
1563 | ||||
1564 | #if (NGX_PCRE1) | |||
1565 | ||||
1566 | if (regex == 0) { | |||
1567 | return NGX_OK0; | |||
1568 | } | |||
1569 | ||||
1570 | addr->nregex = regex; | |||
1571 | addr->regex = ngx_palloc(cf->pool, regex * sizeof(ngx_http_server_name_t)); | |||
1572 | if (addr->regex == NULL((void*)0)) { | |||
1573 | return NGX_ERROR-1; | |||
1574 | } | |||
1575 | ||||
1576 | i = 0; | |||
1577 | ||||
1578 | for (s = 0; s < addr->servers.nelts; s++) { | |||
1579 | ||||
1580 | name = cscfp[s]->server_names.elts; | |||
1581 | ||||
1582 | for (n = 0; n < cscfp[s]->server_names.nelts; n++) { | |||
1583 | if (name[n].regex) { | |||
1584 | addr->regex[i++] = name[n]; | |||
1585 | } | |||
1586 | } | |||
1587 | } | |||
1588 | ||||
1589 | #endif | |||
1590 | ||||
1591 | return NGX_OK0; | |||
1592 | ||||
1593 | failed: | |||
1594 | ||||
1595 | ngx_destroy_pool(ha.temp_pool); | |||
1596 | ||||
1597 | return NGX_ERROR-1; | |||
1598 | } | |||
1599 | ||||
1600 | ||||
1601 | static ngx_int_t | |||
1602 | ngx_http_cmp_conf_addrs(const void *one, const void *two) | |||
1603 | { | |||
1604 | ngx_http_conf_addr_t *first, *second; | |||
1605 | ||||
1606 | first = (ngx_http_conf_addr_t *) one; | |||
1607 | second = (ngx_http_conf_addr_t *) two; | |||
1608 | ||||
1609 | if (first->opt.wildcard) { | |||
1610 | /* a wildcard address must be the last resort, shift it to the end */ | |||
1611 | return 1; | |||
1612 | } | |||
1613 | ||||
1614 | if (second->opt.wildcard) { | |||
1615 | /* a wildcard address must be the last resort, shift it to the end */ | |||
1616 | return -1; | |||
1617 | } | |||
1618 | ||||
1619 | if (first->opt.bind && !second->opt.bind) { | |||
1620 | /* shift explicit bind()ed addresses to the start */ | |||
1621 | return -1; | |||
1622 | } | |||
1623 | ||||
1624 | if (!first->opt.bind && second->opt.bind) { | |||
1625 | /* shift explicit bind()ed addresses to the start */ | |||
1626 | return 1; | |||
1627 | } | |||
1628 | ||||
1629 | /* do not sort by default */ | |||
1630 | ||||
1631 | return 0; | |||
1632 | } | |||
1633 | ||||
1634 | ||||
1635 | static int ngx_libc_cdecl | |||
1636 | ngx_http_cmp_dns_wildcards(const void *one, const void *two) | |||
1637 | { | |||
1638 | ngx_hash_key_t *first, *second; | |||
1639 | ||||
1640 | first = (ngx_hash_key_t *) one; | |||
1641 | second = (ngx_hash_key_t *) two; | |||
1642 | ||||
1643 | return ngx_dns_strcmp(first->key.data, second->key.data); | |||
1644 | } | |||
1645 | ||||
1646 | ||||
1647 | static ngx_int_t | |||
1648 | ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port) | |||
1649 | { | |||
1650 | ngx_uint_t i, last, bind_wildcard; | |||
1651 | ngx_listening_t *ls; | |||
1652 | ngx_http_port_t *hport; | |||
1653 | ngx_http_conf_addr_t *addr; | |||
1654 | ||||
1655 | addr = port->addrs.elts; | |||
1656 | last = port->addrs.nelts; | |||
1657 | ||||
1658 | /* | |||
1659 | * If there is a binding to an "*:port" then we need to bind() to | |||
1660 | * the "*:port" only and ignore other implicit bindings. The bindings | |||
1661 | * have been already sorted: explicit bindings are on the start, then | |||
1662 | * implicit bindings go, and wildcard binding is in the end. | |||
1663 | */ | |||
1664 | ||||
1665 | if (addr[last - 1].opt.wildcard) { | |||
1666 | addr[last - 1].opt.bind = 1; | |||
1667 | bind_wildcard = 1; | |||
1668 | ||||
1669 | } else { | |||
1670 | bind_wildcard = 0; | |||
1671 | } | |||
1672 | ||||
1673 | i = 0; | |||
1674 | ||||
1675 | while (i < last) { | |||
1676 | ||||
1677 | if (bind_wildcard && !addr[i].opt.bind) { | |||
1678 | i++; | |||
1679 | continue; | |||
1680 | } | |||
1681 | ||||
1682 | ls = ngx_http_add_listening(cf, &addr[i]); | |||
1683 | if (ls == NULL((void*)0)) { | |||
1684 | return NGX_ERROR-1; | |||
1685 | } | |||
1686 | ||||
1687 | hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t)); | |||
1688 | if (hport == NULL((void*)0)) { | |||
1689 | return NGX_ERROR-1; | |||
1690 | } | |||
1691 | ||||
1692 | ls->servers = hport; | |||
1693 | ||||
1694 | hport->naddrs = i + 1; | |||
1695 | ||||
1696 | switch (ls->sockaddr->sa_family) { | |||
1697 | ||||
1698 | #if (NGX_HAVE_INET6) | |||
1699 | case AF_INET610: | |||
1700 | if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK0) { | |||
1701 | return NGX_ERROR-1; | |||
1702 | } | |||
1703 | break; | |||
1704 | #endif | |||
1705 | default: /* AF_INET */ | |||
1706 | if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK0) { | |||
1707 | return NGX_ERROR-1; | |||
1708 | } | |||
1709 | break; | |||
1710 | } | |||
1711 | ||||
1712 | if (ngx_clone_listening(cf, ls) != NGX_OK0) { | |||
1713 | return NGX_ERROR-1; | |||
1714 | } | |||
1715 | ||||
1716 | addr++; | |||
1717 | last--; | |||
1718 | } | |||
1719 | ||||
1720 | return NGX_OK0; | |||
1721 | } | |||
1722 | ||||
1723 | ||||
1724 | static ngx_listening_t * | |||
1725 | ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr) | |||
1726 | { | |||
1727 | ngx_listening_t *ls; | |||
1728 | ngx_http_core_loc_conf_t *clcf; | |||
1729 | ngx_http_core_srv_conf_t *cscf; | |||
1730 | ||||
1731 | ls = ngx_create_listening(cf, &addr->opt.sockaddr.sockaddr, | |||
1732 | addr->opt.socklen); | |||
1733 | if (ls == NULL((void*)0)) { | |||
1734 | return NULL((void*)0); | |||
1735 | } | |||
1736 | ||||
1737 | ls->addr_ntop = 1; | |||
1738 | ||||
1739 | ls->handler = ngx_http_init_connection; | |||
1740 | ||||
1741 | cscf = addr->default_server; | |||
1742 | ls->pool_size = cscf->connection_pool_size; | |||
1743 | ls->post_accept_timeout = cscf->client_header_timeout; | |||
1744 | ||||
1745 | clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index]; | |||
1746 | ||||
1747 | ls->logp = clcf->error_log; | |||
1748 | ls->log.data = &ls->addr_text; | |||
1749 | ls->log.handler = ngx_accept_log_error; | |||
1750 | ||||
1751 | #if (NGX_WIN32) | |||
1752 | { | |||
1753 | ngx_iocp_conf_t *iocpcf = NULL((void*)0); | |||
1754 | ||||
1755 | if (ngx_get_conf(cf->cycle->conf_ctx, ngx_events_module)cf->cycle->conf_ctx[ngx_events_module.index]) { | |||
1756 | iocpcf = ngx_event_get_conf(cf->cycle->conf_ctx, ngx_iocp_module)(*(cf->cycle->conf_ctx[ngx_events_module.index])) [ngx_iocp_module .ctx_index];; | |||
1757 | } | |||
1758 | if (iocpcf && iocpcf->acceptex_read) { | |||
1759 | ls->post_accept_buffer_size = cscf->client_header_buffer_size; | |||
1760 | } | |||
1761 | } | |||
1762 | #endif | |||
1763 | ||||
1764 | ls->backlog = addr->opt.backlog; | |||
1765 | ls->rcvbuf = addr->opt.rcvbuf; | |||
1766 | ls->sndbuf = addr->opt.sndbuf; | |||
1767 | ||||
1768 | ls->keepalive = addr->opt.so_keepalive; | |||
1769 | #if (NGX_HAVE_KEEPALIVE_TUNABLE1) | |||
1770 | ls->keepidle = addr->opt.tcp_keepidle; | |||
1771 | ls->keepintvl = addr->opt.tcp_keepintvl; | |||
1772 | ls->keepcnt = addr->opt.tcp_keepcnt; | |||
1773 | #endif | |||
1774 | ||||
1775 | #if (NGX_HAVE_DEFERRED_ACCEPT1 && defined SO_ACCEPTFILTER) | |||
1776 | ls->accept_filter = addr->opt.accept_filter; | |||
1777 | #endif | |||
1778 | ||||
1779 | #if (NGX_HAVE_DEFERRED_ACCEPT1 && defined TCP_DEFER_ACCEPT9) | |||
1780 | ls->deferred_accept = addr->opt.deferred_accept; | |||
1781 | #endif | |||
1782 | ||||
1783 | #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY26) | |||
1784 | ls->ipv6only = addr->opt.ipv6only; | |||
1785 | #endif | |||
1786 | ||||
1787 | #if (NGX_HAVE_SETFIB) | |||
1788 | ls->setfib = addr->opt.setfib; | |||
1789 | #endif | |||
1790 | ||||
1791 | #if (NGX_HAVE_TCP_FASTOPEN1) | |||
1792 | ls->fastopen = addr->opt.fastopen; | |||
1793 | #endif | |||
1794 | ||||
1795 | #if (NGX_HAVE_REUSEPORT1) | |||
1796 | ls->reuseport = addr->opt.reuseport; | |||
1797 | #endif | |||
1798 | ||||
1799 | return ls; | |||
1800 | } | |||
1801 | ||||
1802 | ||||
1803 | static ngx_int_t | |||
1804 | ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport, | |||
1805 | ngx_http_conf_addr_t *addr) | |||
1806 | { | |||
1807 | ngx_uint_t i; | |||
1808 | ngx_http_in_addr_t *addrs; | |||
1809 | struct sockaddr_in *sin; | |||
1810 | ngx_http_virtual_names_t *vn; | |||
1811 | ||||
1812 | hport->addrs = ngx_pcalloc(cf->pool, | |||
1813 | hport->naddrs * sizeof(ngx_http_in_addr_t)); | |||
1814 | if (hport->addrs == NULL((void*)0)) { | |||
1815 | return NGX_ERROR-1; | |||
1816 | } | |||
1817 | ||||
1818 | addrs = hport->addrs; | |||
1819 | ||||
1820 | for (i = 0; i < hport->naddrs; i++) { | |||
1821 | ||||
1822 | sin = &addr[i].opt.sockaddr.sockaddr_in; | |||
1823 | addrs[i].addr = sin->sin_addr.s_addr; | |||
1824 | addrs[i].conf.default_server = addr[i].default_server; | |||
1825 | #if (NGX_HTTP_SSL) | |||
1826 | addrs[i].conf.ssl = addr[i].opt.ssl; | |||
1827 | #endif | |||
1828 | #if (NGX_HTTP_V2) | |||
1829 | addrs[i].conf.http2 = addr[i].opt.http2; | |||
1830 | #endif | |||
1831 | addrs[i].conf.proxy_protocol = addr[i].opt.proxy_protocol; | |||
1832 | ||||
1833 | if (addr[i].hash.buckets == NULL((void*)0) | |||
1834 | && (addr[i].wc_head == NULL((void*)0) | |||
1835 | || addr[i].wc_head->hash.buckets == NULL((void*)0)) | |||
1836 | && (addr[i].wc_tail == NULL((void*)0) | |||
1837 | || addr[i].wc_tail->hash.buckets == NULL((void*)0)) | |||
1838 | #if (NGX_PCRE1) | |||
1839 | && addr[i].nregex == 0 | |||
1840 | #endif | |||
1841 | ) | |||
1842 | { | |||
1843 | continue; | |||
1844 | } | |||
1845 | ||||
1846 | vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t)); | |||
1847 | if (vn == NULL((void*)0)) { | |||
1848 | return NGX_ERROR-1; | |||
1849 | } | |||
1850 | ||||
1851 | addrs[i].conf.virtual_names = vn; | |||
1852 | ||||
1853 | vn->names.hash = addr[i].hash; | |||
1854 | vn->names.wc_head = addr[i].wc_head; | |||
1855 | vn->names.wc_tail = addr[i].wc_tail; | |||
1856 | #if (NGX_PCRE1) | |||
1857 | vn->nregex = addr[i].nregex; | |||
1858 | vn->regex = addr[i].regex; | |||
1859 | #endif | |||
1860 | } | |||
1861 | ||||
1862 | return NGX_OK0; | |||
1863 | } | |||
1864 | ||||
1865 | ||||
1866 | #if (NGX_HAVE_INET6) | |||
1867 | ||||
1868 | static ngx_int_t | |||
1869 | ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport, | |||
1870 | ngx_http_conf_addr_t *addr) | |||
1871 | { | |||
1872 | ngx_uint_t i; | |||
1873 | ngx_http_in6_addr_t *addrs6; | |||
1874 | struct sockaddr_in6 *sin6; | |||
1875 | ngx_http_virtual_names_t *vn; | |||
1876 | ||||
1877 | hport->addrs = ngx_pcalloc(cf->pool, | |||
1878 | hport->naddrs * sizeof(ngx_http_in6_addr_t)); | |||
1879 | if (hport->addrs == NULL((void*)0)) { | |||
1880 | return NGX_ERROR-1; | |||
1881 | } | |||
1882 | ||||
1883 | addrs6 = hport->addrs; | |||
1884 | ||||
1885 | for (i = 0; i < hport->naddrs; i++) { | |||
1886 | ||||
1887 | sin6 = &addr[i].opt.sockaddr.sockaddr_in6; | |||
1888 | addrs6[i].addr6 = sin6->sin6_addr; | |||
1889 | addrs6[i].conf.default_server = addr[i].default_server; | |||
1890 | #if (NGX_HTTP_SSL) | |||
1891 | addrs6[i].conf.ssl = addr[i].opt.ssl; | |||
1892 | #endif | |||
1893 | #if (NGX_HTTP_V2) | |||
1894 | addrs6[i].conf.http2 = addr[i].opt.http2; | |||
1895 | #endif | |||
1896 | addrs6[i].conf.proxy_protocol = addr[i].opt.proxy_protocol; | |||
1897 | ||||
1898 | if (addr[i].hash.buckets == NULL((void*)0) | |||
1899 | && (addr[i].wc_head == NULL((void*)0) | |||
1900 | || addr[i].wc_head->hash.buckets == NULL((void*)0)) | |||
1901 | && (addr[i].wc_tail == NULL((void*)0) | |||
1902 | || addr[i].wc_tail->hash.buckets == NULL((void*)0)) | |||
1903 | #if (NGX_PCRE1) | |||
1904 | && addr[i].nregex == 0 | |||
1905 | #endif | |||
1906 | ) | |||
1907 | { | |||
1908 | continue; | |||
1909 | } | |||
1910 | ||||
1911 | vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t)); | |||
1912 | if (vn == NULL((void*)0)) { | |||
1913 | return NGX_ERROR-1; | |||
1914 | } | |||
1915 | ||||
1916 | addrs6[i].conf.virtual_names = vn; | |||
1917 | ||||
1918 | vn->names.hash = addr[i].hash; | |||
1919 | vn->names.wc_head = addr[i].wc_head; | |||
1920 | vn->names.wc_tail = addr[i].wc_tail; | |||
1921 | #if (NGX_PCRE1) | |||
1922 | vn->nregex = addr[i].nregex; | |||
1923 | vn->regex = addr[i].regex; | |||
1924 | #endif | |||
1925 | } | |||
1926 | ||||
1927 | return NGX_OK0; | |||
1928 | } | |||
1929 | ||||
1930 | #endif | |||
1931 | ||||
1932 | ||||
1933 | char * | |||
1934 | ngx_http_types_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |||
1935 | { | |||
1936 | char *p = conf; | |||
1937 | ||||
1938 | ngx_array_t **types; | |||
1939 | ngx_str_t *value, *default_type; | |||
1940 | ngx_uint_t i, n, hash; | |||
1941 | ngx_hash_key_t *type; | |||
1942 | ||||
1943 | types = (ngx_array_t **) (p + cmd->offset); | |||
1944 | ||||
1945 | if (*types == (void *) -1) { | |||
1946 | return NGX_CONF_OK((void*)0); | |||
1947 | } | |||
1948 | ||||
1949 | default_type = cmd->post; | |||
1950 | ||||
1951 | if (*types == NULL((void*)0)) { | |||
1952 | *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t)); | |||
1953 | if (*types == NULL((void*)0)) { | |||
1954 | return NGX_CONF_ERROR(void *) -1; | |||
1955 | } | |||
1956 | ||||
1957 | if (default_type) { | |||
1958 | type = ngx_array_push(*types); | |||
1959 | if (type == NULL((void*)0)) { | |||
1960 | return NGX_CONF_ERROR(void *) -1; | |||
1961 | } | |||
1962 | ||||
1963 | type->key = *default_type; | |||
1964 | type->key_hash = ngx_hash_key(default_type->data, | |||
1965 | default_type->len); | |||
1966 | type->value = (void *) 4; | |||
1967 | } | |||
1968 | } | |||
1969 | ||||
1970 | value = cf->args->elts; | |||
1971 | ||||
1972 | for (i = 1; i < cf->args->nelts; i++) { | |||
1973 | ||||
1974 | if (value[i].len == 1 && value[i].data[0] == '*') { | |||
1975 | *types = (void *) -1; | |||
1976 | return NGX_CONF_OK((void*)0); | |||
1977 | } | |||
1978 | ||||
1979 | hash = ngx_hash_strlow(value[i].data, value[i].data, value[i].len); | |||
1980 | value[i].data[value[i].len] = '\0'; | |||
1981 | ||||
1982 | type = (*types)->elts; | |||
1983 | for (n = 0; n < (*types)->nelts; n++) { | |||
1984 | ||||
1985 | if (ngx_strcmp(value[i].data, type[n].key.data)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p ((const char *) value[i].data) && __builtin_constant_p ((const char *) type[n].key.data) && (__s1_len = strlen ((const char *) value[i].data), __s2_len = strlen ((const char *) type[n].key.data), (!((size_t)(const void *)(((const char *) value[i].data) + 1) - (size_t)(const void *)((const char * ) value[i].data) == 1) || __s1_len >= 4) && (!((size_t )(const void *)(((const char *) type[n].key.data) + 1) - (size_t )(const void *)((const char *) type[n].key.data) == 1) || __s2_len >= 4)) ? __builtin_strcmp ((const char *) value[i].data, ( const char *) type[n].key.data) : (__builtin_constant_p ((const char *) value[i].data) && ((size_t)(const void *)((( const char *) value[i].data) + 1) - (size_t)(const void *)((const char *) value[i].data) == 1) && (__s1_len = strlen ( (const char *) value[i].data), __s1_len < 4) ? (__builtin_constant_p ((const char *) type[n].key.data) && ((size_t)(const void *)(((const char *) type[n].key.data) + 1) - (size_t)(const void *)((const char *) type[n].key.data) == 1) ? __builtin_strcmp ((const char *) value[i].data, (const char *) type[n].key.data ) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ((const char *) type[n].key.data); int __result = (((const unsigned char *) (const char *) ((const char *) value[i].data))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ((const char *) value[i].data))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ((const char *) value[i].data))[2] - __s2 [2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ((const char *) value [i].data))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p ((const char *) type[n].key.data) && ((size_t)(const void *)(((const char *) type[n].key.data) + 1) - (size_t)(const void *)((const char *) type[n].key.data) == 1) && (__s2_len = strlen ((const char *) type[n].key.data), __s2_len < 4) ? (__builtin_constant_p ((const char *) value[i].data) && ((size_t)(const void *)(((const char *) value[i].data) + 1) - (size_t)(const void *)((const char *) value[i].data) == 1) ? __builtin_strcmp ((const char *) value[i].data, (const char * ) type[n].key.data) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ((const char * ) value[i].data); int __result = (((const unsigned char *) (const char *) ((const char *) type[n].key.data))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ((const char *) type[n].key. data))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ( (const char *) type[n].key.data))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ((const char *) type[n].key.data))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp ((const char *) value[i].data, (const char *) type[n].key.data)))); }) == 0) { | |||
1986 | ngx_conf_log_error(NGX_LOG_WARN5, cf, 0, | |||
1987 | "duplicate MIME type \"%V\"", &value[i]); | |||
1988 | goto next; | |||
1989 | } | |||
1990 | } | |||
1991 | ||||
1992 | type = ngx_array_push(*types); | |||
1993 | if (type == NULL((void*)0)) { | |||
1994 | return NGX_CONF_ERROR(void *) -1; | |||
1995 | } | |||
1996 | ||||
1997 | type->key = value[i]; | |||
1998 | type->key_hash = hash; | |||
1999 | type->value = (void *) 4; | |||
2000 | ||||
2001 | next: | |||
2002 | ||||
2003 | continue; | |||
2004 | } | |||
2005 | ||||
2006 | return NGX_CONF_OK((void*)0); | |||
2007 | } | |||
2008 | ||||
2009 | ||||
2010 | char * | |||
2011 | ngx_http_merge_types(ngx_conf_t *cf, ngx_array_t **keys, ngx_hash_t *types_hash, | |||
2012 | ngx_array_t **prev_keys, ngx_hash_t *prev_types_hash, | |||
2013 | ngx_str_t *default_types) | |||
2014 | { | |||
2015 | ngx_hash_init_t hash; | |||
2016 | ||||
2017 | if (*keys) { | |||
2018 | ||||
2019 | if (*keys == (void *) -1) { | |||
2020 | return NGX_CONF_OK((void*)0); | |||
2021 | } | |||
2022 | ||||
2023 | hash.hash = types_hash; | |||
2024 | hash.key = NULL((void*)0); | |||
2025 | hash.max_size = 2048; | |||
2026 | hash.bucket_size = 64; | |||
2027 | hash.name = "test_types_hash"; | |||
2028 | hash.pool = cf->pool; | |||
2029 | hash.temp_pool = NULL((void*)0); | |||
2030 | ||||
2031 | if (ngx_hash_init(&hash, (*keys)->elts, (*keys)->nelts) != NGX_OK0) { | |||
2032 | return NGX_CONF_ERROR(void *) -1; | |||
2033 | } | |||
2034 | ||||
2035 | return NGX_CONF_OK((void*)0); | |||
2036 | } | |||
2037 | ||||
2038 | if (prev_types_hash->buckets == NULL((void*)0)) { | |||
2039 | ||||
2040 | if (*prev_keys == NULL((void*)0)) { | |||
2041 | ||||
2042 | if (ngx_http_set_default_types(cf, prev_keys, default_types) | |||
2043 | != NGX_OK0) | |||
2044 | { | |||
2045 | return NGX_CONF_ERROR(void *) -1; | |||
2046 | } | |||
2047 | ||||
2048 | } else if (*prev_keys == (void *) -1) { | |||
2049 | *keys = *prev_keys; | |||
2050 | return NGX_CONF_OK((void*)0); | |||
2051 | } | |||
2052 | ||||
2053 | hash.hash = prev_types_hash; | |||
2054 | hash.key = NULL((void*)0); | |||
2055 | hash.max_size = 2048; | |||
2056 | hash.bucket_size = 64; | |||
2057 | hash.name = "test_types_hash"; | |||
2058 | hash.pool = cf->pool; | |||
2059 | hash.temp_pool = NULL((void*)0); | |||
2060 | ||||
2061 | if (ngx_hash_init(&hash, (*prev_keys)->elts, (*prev_keys)->nelts) | |||
2062 | != NGX_OK0) | |||
2063 | { | |||
2064 | return NGX_CONF_ERROR(void *) -1; | |||
2065 | } | |||
2066 | } | |||
2067 | ||||
2068 | *types_hash = *prev_types_hash; | |||
2069 | ||||
2070 | return NGX_CONF_OK((void*)0); | |||
2071 | ||||
2072 | } | |||
2073 | ||||
2074 | ||||
2075 | ngx_int_t | |||
2076 | ngx_http_set_default_types(ngx_conf_t *cf, ngx_array_t **types, | |||
2077 | ngx_str_t *default_type) | |||
2078 | { | |||
2079 | ngx_hash_key_t *type; | |||
2080 | ||||
2081 | *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t)); | |||
2082 | if (*types == NULL((void*)0)) { | |||
2083 | return NGX_ERROR-1; | |||
2084 | } | |||
2085 | ||||
2086 | while (default_type->len) { | |||
2087 | ||||
2088 | type = ngx_array_push(*types); | |||
2089 | if (type == NULL((void*)0)) { | |||
2090 | return NGX_ERROR-1; | |||
2091 | } | |||
2092 | ||||
2093 | type->key = *default_type; | |||
2094 | type->key_hash = ngx_hash_key(default_type->data, | |||
2095 | default_type->len); | |||
2096 | type->value = (void *) 4; | |||
2097 | ||||
2098 | default_type++; | |||
2099 | } | |||
2100 | ||||
2101 | return NGX_OK0; | |||
2102 | } |