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