~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Nginx/http/ngx_http.c

Version: ~ [ nginx-0.8.20 ] ~ [ nginx-0.7.62 ] ~ [ nginx-0.6.39 ] ~

  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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.