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