upstream nginx-0.7.41
[nginx.git] / nginx / src / http / ngx_http.c
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 *in_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                  in_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, &in_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, &in_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 in_port list */
1184
1185         return ngx_http_add_addresses(cf, cscf, &port[i], listen);
1186     }
1187
1188     /* add a port to the in_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 (in_port)
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                     continue;
1400                 }
1401
1402                 if (ngx_http_server_names(cf, cmcf, &addr[a]) != NGX_OK) {
1403                     return NGX_ERROR;
1404                 }
1405
1406                 break;
1407             }
1408         }
1409
1410         if (ngx_http_init_listening(cf, &port[p]) != NGX_OK) {
1411             return NGX_ERROR;
1412         }
1413     }
1414
1415     return NGX_OK;
1416 }
1417
1418
1419 static ngx_int_t
1420 ngx_http_server_names(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
1421     ngx_http_conf_addr_t *addr)
1422 {
1423     ngx_int_t                  rc;
1424     ngx_uint_t                 s;
1425     ngx_hash_init_t            hash;
1426     ngx_http_server_name_t    *name;
1427     ngx_hash_keys_arrays_t     ha;
1428 #if (NGX_PCRE)
1429     ngx_uint_t                 regex, i;
1430
1431     regex = 0;
1432 #endif
1433
1434     ngx_memzero(&ha, sizeof(ngx_hash_keys_arrays_t));
1435
1436     ha.temp_pool = ngx_create_pool(16384, cf->log);
1437     if (ha.temp_pool == NULL) {
1438         return NGX_ERROR;
1439     }
1440
1441     ha.pool = cf->pool;
1442
1443     if (ngx_hash_keys_array_init(&ha, NGX_HASH_LARGE) != NGX_OK) {
1444         goto failed;
1445     }
1446
1447     name = addr->names.elts;
1448
1449     for (s = 0; s < addr->names.nelts; s++) {
1450
1451 #if (NGX_PCRE)
1452         if (name[s].regex) {
1453             regex++;
1454             continue;
1455         }
1456 #endif
1457
1458         rc = ngx_hash_add_key(&ha, &name[s].name, name[s].core_srv_conf,
1459                               NGX_HASH_WILDCARD_KEY);
1460
1461         if (rc == NGX_ERROR) {
1462             return NGX_ERROR;
1463         }
1464
1465         if (rc == NGX_DECLINED) {
1466             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
1467                           "invalid server name or wildcard \"%V\" on %s",
1468                           &name[s].name, addr->listen_conf->addr);
1469             return NGX_ERROR;
1470         }
1471
1472         if (rc == NGX_BUSY) {
1473             ngx_log_error(NGX_LOG_WARN, cf->log, 0,
1474                           "conflicting server name \"%V\" on %s, ignored",
1475                           &name[s].name, addr->listen_conf->addr);
1476         }
1477     }
1478
1479     hash.key = ngx_hash_key_lc;
1480     hash.max_size = cmcf->server_names_hash_max_size;
1481     hash.bucket_size = cmcf->server_names_hash_bucket_size;
1482     hash.name = "server_names_hash";
1483     hash.pool = cf->pool;
1484
1485     if (ha.keys.nelts) {
1486         hash.hash = &addr->hash;
1487         hash.temp_pool = NULL;
1488
1489         if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK) {
1490             goto failed;
1491         }
1492     }
1493
1494     if (ha.dns_wc_head.nelts) {
1495
1496         ngx_qsort(ha.dns_wc_head.elts, (size_t) ha.dns_wc_head.nelts,
1497                   sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);
1498
1499         hash.hash = NULL;
1500         hash.temp_pool = ha.temp_pool;
1501
1502         if (ngx_hash_wildcard_init(&hash, ha.dns_wc_head.elts,
1503                                    ha.dns_wc_head.nelts)
1504             != NGX_OK)
1505         {
1506             goto failed;
1507         }
1508
1509         addr->wc_head = (ngx_hash_wildcard_t *) hash.hash;
1510     }
1511
1512     if (ha.dns_wc_tail.nelts) {
1513
1514         ngx_qsort(ha.dns_wc_tail.elts, (size_t) ha.dns_wc_tail.nelts,
1515                   sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);
1516
1517         hash.hash = NULL;
1518         hash.temp_pool = ha.temp_pool;
1519
1520         if (ngx_hash_wildcard_init(&hash, ha.dns_wc_tail.elts,
1521                                    ha.dns_wc_tail.nelts)
1522             != NGX_OK)
1523         {
1524             goto failed;
1525         }
1526
1527         addr->wc_tail = (ngx_hash_wildcard_t *) hash.hash;
1528     }
1529
1530     ngx_destroy_pool(ha.temp_pool);
1531
1532 #if (NGX_PCRE)
1533
1534     if (regex == 0) {
1535         return NGX_OK;
1536     }
1537
1538     addr->nregex = regex;
1539     addr->regex = ngx_palloc(cf->pool, regex * sizeof(ngx_http_server_name_t));
1540     if (addr->regex == NULL) {
1541         return NGX_ERROR;
1542     }
1543
1544     for (i = 0, s = 0; s < addr->names.nelts; s++) {
1545         if (name[s].regex) {
1546             addr->regex[i++] = name[s];
1547         }
1548     }
1549
1550 #endif
1551
1552     return NGX_OK;
1553
1554 failed:
1555
1556     ngx_destroy_pool(ha.temp_pool);
1557
1558     return NGX_ERROR;
1559 }
1560
1561
1562 static ngx_int_t
1563 ngx_http_cmp_conf_addrs(const void *one, const void *two)
1564 {
1565     ngx_http_conf_addr_t  *first, *second;
1566
1567     first = (ngx_http_conf_addr_t *) one;
1568     second = (ngx_http_conf_addr_t *) two;
1569
1570     if (first->wildcard) {
1571         /* a wildcard address must be the last resort, shift it to the end */
1572         return 1;
1573     }
1574
1575     if (first->bind && !second->bind) {
1576         /* shift explicit bind()ed addresses to the start */
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     /* do not sort by default */
1586
1587     return 0;
1588 }
1589
1590
1591 static int ngx_libc_cdecl
1592 ngx_http_cmp_dns_wildcards(const void *one, const void *two)
1593 {
1594     ngx_hash_key_t  *first, *second;
1595
1596     first = (ngx_hash_key_t *) one;
1597     second = (ngx_hash_key_t *) two;
1598
1599     return ngx_strcmp(first->key.data, second->key.data);
1600 }
1601
1602
1603 static ngx_int_t
1604 ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port)
1605 {
1606     ngx_uint_t                 i, last, bind_wildcard;
1607     ngx_listening_t           *ls;
1608     ngx_http_port_t           *hport;
1609     ngx_http_conf_addr_t      *addr;
1610
1611     addr = port->addrs.elts;
1612     last = port->addrs.nelts;
1613
1614     /*
1615      * If there is a binding to an "*:port" then we need to bind() to
1616      * the "*:port" only and ignore other implicit bindings.  The bindings
1617      * have been already sorted: explicit bindings are on the start, then
1618      * implicit bindings go, and wildcard binding is in the end.
1619      */
1620
1621     if (addr[last - 1].wildcard) {
1622         addr[last - 1].bind = 1;
1623         bind_wildcard = 1;
1624
1625     } else {
1626         bind_wildcard = 0;
1627     }
1628
1629     i = 0;
1630
1631     while (i < last) {
1632
1633         if (bind_wildcard && !addr[i].bind) {
1634             i++;
1635             continue;
1636         }
1637
1638         ls = ngx_http_add_listening(cf, &addr[i]);
1639         if (ls == NULL) {
1640             return NGX_ERROR;
1641         }
1642
1643         hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t));
1644         if (hport == NULL) {
1645             return NGX_ERROR;
1646         }
1647
1648         ls->servers = hport;
1649
1650         if (i == last - 1) {
1651             hport->naddrs = last;
1652
1653         } else {
1654             hport->naddrs = 1;
1655             i = 0;
1656         }
1657
1658         switch (ls->sockaddr->sa_family) {
1659
1660 #if (NGX_HAVE_INET6)
1661         case AF_INET6:
1662             if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) {
1663                 return NGX_ERROR;
1664             }
1665             break;
1666 #endif
1667         default: /* AF_INET */
1668             if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) {
1669                 return NGX_ERROR;
1670             }
1671             break;
1672         }
1673
1674         addr++;
1675         last--;
1676     }
1677
1678     return NGX_OK;
1679 }
1680
1681
1682 static ngx_listening_t *
1683 ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)
1684 {
1685     ngx_listening_t           *ls;
1686     struct sockaddr           *sa;
1687     ngx_http_core_loc_conf_t  *clcf;
1688     ngx_http_core_srv_conf_t  *cscf;
1689     u_char                     text[NGX_SOCKADDR_STRLEN];
1690
1691     ls = ngx_array_push(&cf->cycle->listening);
1692     if (ls == NULL) {
1693         return NULL;
1694     }
1695
1696     ngx_memzero(ls, sizeof(ngx_listening_t));
1697
1698     sa = ngx_palloc(cf->pool, addr->socklen);
1699     if (sa == NULL) {
1700         return NULL;
1701     }
1702
1703     ngx_memcpy(sa, addr->sockaddr, addr->socklen);
1704
1705     ls->sockaddr = sa;
1706     ls->socklen = addr->socklen;
1707
1708     ls->addr_text.len = ngx_sock_ntop(sa, text, NGX_SOCKADDR_STRLEN, 1);
1709
1710     ls->addr_text.data = ngx_pnalloc(cf->pool, ls->addr_text.len);
1711     if (ls->addr_text.data == NULL) {
1712         return NULL;
1713     }
1714
1715     ngx_memcpy(ls->addr_text.data, text, ls->addr_text.len);
1716
1717     ls->fd = (ngx_socket_t) -1;
1718     ls->type = SOCK_STREAM;
1719
1720     switch (ls->sockaddr->sa_family) {
1721 #if (NGX_HAVE_INET6)
1722     case AF_INET6:
1723          ls->addr_text_max_len = NGX_INET6_ADDRSTRLEN;
1724          break;
1725 #endif
1726     case AF_INET:
1727          ls->addr_text_max_len = NGX_INET_ADDRSTRLEN;
1728          break;
1729     default:
1730          ls->addr_text_max_len = NGX_SOCKADDR_STRLEN;
1731          break;
1732     }
1733
1734     ls->addr_ntop = 1;
1735
1736     ls->handler = ngx_http_init_connection;
1737
1738     cscf = addr->core_srv_conf;
1739     ls->pool_size = cscf->connection_pool_size;
1740     ls->post_accept_timeout = cscf->client_header_timeout;
1741
1742     clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];
1743
1744     ls->log = *clcf->err_log;
1745     ls->log.data = &ls->addr_text;
1746     ls->log.handler = ngx_accept_log_error;
1747
1748 #if (NGX_WIN32)
1749     {
1750     ngx_iocp_conf_t  *iocpcf;
1751
1752     iocpcf = ngx_event_get_conf(cf->cycle->conf_ctx, ngx_iocp_module);
1753     if (iocpcf->acceptex_read) {
1754         ls->post_accept_buffer_size = cscf->client_header_buffer_size;
1755     }
1756     }
1757 #endif
1758
1759     ls->backlog = addr->listen_conf->backlog;
1760     ls->rcvbuf = addr->listen_conf->rcvbuf;
1761     ls->sndbuf = addr->listen_conf->sndbuf;
1762
1763 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
1764     ls->accept_filter = addr->listen_conf->accept_filter;
1765 #endif
1766
1767 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
1768     ls->deferred_accept = addr->listen_conf->deferred_accept;
1769 #endif
1770
1771     return ls;
1772 }
1773
1774
1775 static ngx_int_t
1776 ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport,
1777     ngx_http_conf_addr_t *addr)
1778 {
1779     ngx_uint_t                 i;
1780     ngx_http_in_addr_t        *addrs;
1781     struct sockaddr_in        *sin;
1782     ngx_http_virtual_names_t  *vn;
1783
1784     hport->addrs = ngx_pcalloc(cf->pool,
1785                                hport->naddrs * sizeof(ngx_http_in_addr_t));
1786     if (hport->addrs == NULL) {
1787         return NGX_ERROR;
1788     }
1789
1790     addrs = hport->addrs;
1791
1792     for (i = 0; i < hport->naddrs; i++) {
1793
1794         sin = (struct sockaddr_in *) addr[i].sockaddr;
1795         addrs[i].addr = sin->sin_addr.s_addr;
1796         addrs[i].conf.core_srv_conf = addr[i].core_srv_conf;
1797 #if (NGX_HTTP_SSL)
1798         addrs[i].conf.ssl = addr[i].ssl;
1799 #endif
1800
1801         if (addr[i].hash.buckets == NULL
1802             && (addr[i].wc_head == NULL
1803                 || addr[i].wc_head->hash.buckets == NULL)
1804             && (addr[i].wc_head == NULL
1805                 || addr[i].wc_head->hash.buckets == NULL))
1806         {
1807             continue;
1808         }
1809
1810         vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
1811         if (vn == NULL) {
1812             return NGX_ERROR;
1813         }
1814
1815         addrs[i].conf.core_srv_conf->virtual_names = vn;
1816
1817         vn->names.hash = addr[i].hash;
1818         vn->names.wc_head = addr[i].wc_head;
1819         vn->names.wc_tail = addr[i].wc_tail;
1820 #if (NGX_PCRE)
1821         vn->nregex = addr[i].nregex;
1822         vn->regex = addr[i].regex;
1823 #endif
1824     }
1825
1826     return NGX_OK;
1827 }
1828
1829
1830 #if (NGX_HAVE_INET6)
1831
1832 static ngx_int_t
1833 ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport,
1834     ngx_http_conf_addr_t *addr)
1835 {
1836     ngx_uint_t                 i;
1837     ngx_http_in6_addr_t       *addrs6;
1838     struct sockaddr_in6       *sin6;
1839     ngx_http_virtual_names_t  *vn;
1840
1841     hport->addrs = ngx_pcalloc(cf->pool,
1842                                hport->naddrs * sizeof(ngx_http_in6_addr_t));
1843     if (hport->addrs == NULL) {
1844         return NGX_ERROR;
1845     }
1846
1847     addrs6 = hport->addrs;
1848
1849     for (i = 0; i < hport->naddrs; i++) {
1850
1851         sin6 = (struct sockaddr_in6 *) addr[i].sockaddr;
1852         addrs6[i].addr6 = sin6->sin6_addr;
1853         addrs6[i].conf.core_srv_conf = addr[i].core_srv_conf;
1854 #if (NGX_HTTP_SSL)
1855         addrs6[i].conf.ssl = addr[i].ssl;
1856 #endif
1857
1858         if (addr[i].hash.buckets == NULL
1859             && (addr[i].wc_head == NULL
1860                 || addr[i].wc_head->hash.buckets == NULL)
1861             && (addr[i].wc_head == NULL
1862                 || addr[i].wc_head->hash.buckets == NULL))
1863         {
1864             continue;
1865         }
1866
1867         vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
1868         if (vn == NULL) {
1869             return NGX_ERROR;
1870         }
1871
1872         addrs6[i].conf.core_srv_conf->virtual_names = vn;
1873
1874         vn->names.hash = addr[i].hash;
1875         vn->names.wc_head = addr[i].wc_head;
1876         vn->names.wc_tail = addr[i].wc_tail;
1877 #if (NGX_PCRE)
1878         vn->nregex = addr[i].nregex;
1879         vn->regex = addr[i].regex;
1880 #endif
1881     }
1882
1883     return NGX_OK;
1884 }
1885
1886 #endif
1887
1888
1889 char *
1890 ngx_http_types_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1891 {
1892     char  *p = conf;
1893
1894     ngx_array_t     **types;
1895     ngx_str_t        *value, *default_type;
1896     ngx_uint_t        i, n, hash;
1897     ngx_hash_key_t   *type;
1898
1899     types = (ngx_array_t **) (p + cmd->offset);
1900
1901     default_type = cmd->post;
1902
1903     if (*types == NULL) {
1904         *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t));
1905         if (*types == NULL) {
1906             return NGX_CONF_ERROR;
1907         }
1908
1909         if (default_type) {
1910             type = ngx_array_push(*types);
1911             if (type == NULL) {
1912                 return NGX_CONF_ERROR;
1913             }
1914
1915             type->key = *default_type;
1916             type->key_hash = ngx_hash_key(default_type->data,
1917                                           default_type->len);
1918             type->value = (void *) 4;
1919         }
1920     }
1921
1922     value = cf->args->elts;
1923
1924     for (i = 1; i < cf->args->nelts; i++) {
1925
1926         hash = ngx_hash_strlow(value[i].data, value[i].data, value[i].len);
1927         value[i].data[value[i].len] = '\0';
1928
1929         type = (*types)->elts;
1930         for (n = 0; n < (*types)->nelts; n++) {
1931
1932             if (ngx_strcmp(value[i].data, type[n].key.data) == 0) {
1933                 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1934                                    "duplicate MIME type \"%V\"", &value[i]);
1935                 continue;
1936             }
1937         }
1938
1939         type = ngx_array_push(*types);
1940         if (type == NULL) {
1941             return NGX_CONF_ERROR;
1942         }
1943
1944         type->key = value[i];
1945         type->key_hash = hash;
1946         type->value = (void *) 4;
1947     }
1948
1949     return NGX_CONF_OK;
1950 }
1951
1952
1953 char *
1954 ngx_http_merge_types(ngx_conf_t *cf, ngx_array_t *keys, ngx_hash_t *types_hash,
1955     ngx_array_t *prev_keys, ngx_hash_t *prev_types_hash,
1956     ngx_str_t *default_types)
1957 {
1958     ngx_hash_init_t  hash;
1959
1960     if (keys) {
1961
1962         hash.hash = types_hash;
1963         hash.key = NULL;
1964         hash.max_size = 2048;
1965         hash.bucket_size = 64;
1966         hash.name = "test_types_hash";
1967         hash.pool = cf->pool;
1968         hash.temp_pool = NULL;
1969
1970         if (ngx_hash_init(&hash, keys->elts, keys->nelts) != NGX_OK) {
1971             return NGX_CONF_ERROR;
1972         }
1973
1974         return NGX_CONF_OK;
1975     }
1976
1977     if (prev_types_hash->buckets == NULL) {
1978
1979         if (prev_keys == NULL) {
1980
1981             if (ngx_http_set_default_types(cf, &prev_keys, default_types)
1982                 != NGX_OK)
1983             {
1984                 return NGX_CONF_ERROR;
1985             }
1986         }
1987
1988         hash.hash = prev_types_hash;
1989         hash.key = NULL;
1990         hash.max_size = 2048;
1991         hash.bucket_size = 64;
1992         hash.name = "test_types_hash";
1993         hash.pool = cf->pool;
1994         hash.temp_pool = NULL;
1995
1996         if (ngx_hash_init(&hash, prev_keys->elts, prev_keys->nelts) != NGX_OK) {
1997             return NGX_CONF_ERROR;
1998         }
1999     }
2000
2001     *types_hash = *prev_types_hash;
2002
2003     return NGX_CONF_OK;
2004
2005 }
2006
2007
2008 ngx_int_t
2009 ngx_http_set_default_types(ngx_conf_t *cf, ngx_array_t **types,
2010     ngx_str_t *default_type)
2011 {
2012     ngx_hash_key_t  *type;
2013
2014     *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t));
2015     if (*types == NULL) {
2016         return NGX_ERROR;
2017     }
2018
2019     while (default_type->len) {
2020
2021         type = ngx_array_push(*types);
2022         if (type == NULL) {
2023             return NGX_ERROR;
2024         }
2025
2026         type->key = *default_type;
2027         type->key_hash = ngx_hash_key(default_type->data,
2028                                       default_type->len);
2029         type->value = (void *) 4;
2030
2031         default_type++;
2032     }
2033
2034     return NGX_OK;
2035 }