blob: 15b53feab2ca9b28a8920a3a761d41dbd03ce3c7 [file] [log] [blame]
Igor Sysoeve0af1b82002-08-16 15:27:03 +00001
Igor Sysoevd90282d2004-09-28 08:34:51 +00002/*
Igor Sysoevff8da912004-09-29 16:00:49 +00003 * Copyright (C) Igor Sysoev
Igor Sysoevd90282d2004-09-28 08:34:51 +00004 */
5
6
Igor Sysoev2b542382002-08-20 14:48:28 +00007#include <ngx_config.h>
Igor Sysoev1c104622003-06-03 15:42:58 +00008#include <ngx_core.h>
Igor Sysoeve0af1b82002-08-16 15:27:03 +00009#include <ngx_http.h>
10
11
Igor Sysoev6253ca12003-05-27 12:18:54 +000012static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
Igor Sysoev87ac67f2008-05-22 09:57:47 +000013static ngx_int_t ngx_http_init_phases(ngx_conf_t *cf,
14 ngx_http_core_main_conf_t *cmcf);
15static ngx_int_t ngx_http_init_headers_in_hash(ngx_conf_t *cf,
16 ngx_http_core_main_conf_t *cmcf);
17static ngx_int_t ngx_http_init_phase_handlers(ngx_conf_t *cf,
18 ngx_http_core_main_conf_t *cmcf);
Igor Sysoev6d14e652008-05-22 11:07:08 +000019
Igor Sysoeva8833612009-02-18 16:17:12 +000020static ngx_int_t ngx_http_add_addresses(ngx_conf_t *cf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +000021 ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port,
Igor Sysoevf2694cb2009-10-21 16:47:44 +000022 ngx_http_listen_opt_t *lsopt);
Igor Sysoevc0edbcc2004-10-21 15:34:38 +000023static ngx_int_t ngx_http_add_address(ngx_conf_t *cf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +000024 ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port,
Igor Sysoevf2694cb2009-10-21 16:47:44 +000025 ngx_http_listen_opt_t *lsopt);
Igor Sysoev2a634f52009-10-21 16:27:48 +000026static ngx_int_t ngx_http_add_server(ngx_conf_t *cf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +000027 ngx_http_core_srv_conf_t *cscf, ngx_http_conf_addr_t *addr);
Igor Sysoev6d14e652008-05-22 11:07:08 +000028
Igor Sysoev74a5ddb2004-07-18 19:11:20 +000029static char *ngx_http_merge_locations(ngx_conf_t *cf,
Igor Sysoeve55988c2008-05-24 14:14:13 +000030 ngx_queue_t *locations, void **loc_conf, ngx_http_module_t *module,
Igor Sysoev8184d1b2005-03-04 14:06:57 +000031 ngx_uint_t ctx_index);
Igor Sysoeve55988c2008-05-24 14:14:13 +000032static ngx_int_t ngx_http_init_locations(ngx_conf_t *cf,
33 ngx_http_core_srv_conf_t *cscf, ngx_http_core_loc_conf_t *pclcf);
34static ngx_int_t ngx_http_init_static_location_trees(ngx_conf_t *cf,
35 ngx_http_core_loc_conf_t *pclcf);
36static ngx_int_t ngx_http_cmp_locations(const ngx_queue_t *one,
37 const ngx_queue_t *two);
38static ngx_int_t ngx_http_join_exact_locations(ngx_conf_t *cf,
39 ngx_queue_t *locations);
40static void ngx_http_create_locations_list(ngx_queue_t *locations,
41 ngx_queue_t *q);
42static ngx_http_location_tree_node_t *
43 ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations,
44 size_t prefix);
Igor Sysoev6d14e652008-05-22 11:07:08 +000045
46static ngx_int_t ngx_http_optimize_servers(ngx_conf_t *cf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +000047 ngx_http_core_main_conf_t *cmcf, ngx_array_t *ports);
Igor Sysoeva8833612009-02-18 16:17:12 +000048static ngx_int_t ngx_http_server_names(ngx_conf_t *cf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +000049 ngx_http_core_main_conf_t *cmcf, ngx_http_conf_addr_t *addr);
50static ngx_int_t ngx_http_cmp_conf_addrs(const void *one, const void *two);
Igor Sysoev305a9d82005-12-26 17:07:48 +000051static int ngx_libc_cdecl ngx_http_cmp_dns_wildcards(const void *one,
52 const void *two);
Igor Sysoev4e9393a2003-01-09 05:36:00 +000053
Igor Sysoev6d14e652008-05-22 11:07:08 +000054static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +000055 ngx_http_conf_port_t *port);
56static ngx_listening_t *ngx_http_add_listening(ngx_conf_t *cf,
57 ngx_http_conf_addr_t *addr);
58static ngx_int_t ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport,
59 ngx_http_conf_addr_t *addr);
60#if (NGX_HAVE_INET6)
61static ngx_int_t ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport,
62 ngx_http_conf_addr_t *addr);
63#endif
Igor Sysoev6d14e652008-05-22 11:07:08 +000064
Igor Sysoev305a9d82005-12-26 17:07:48 +000065ngx_uint_t ngx_http_max_module;
Igor Sysoeve89c4582003-12-19 08:15:11 +000066
Igor Sysoevb2620632003-01-10 06:09:20 +000067
Igor Sysoev2f657222004-06-16 15:32:11 +000068ngx_int_t (*ngx_http_top_header_filter) (ngx_http_request_t *r);
69ngx_int_t (*ngx_http_top_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
Igor Sysoev4e9393a2003-01-09 05:36:00 +000070
71
Igor Sysoev390abe02008-08-12 13:11:36 +000072ngx_str_t ngx_http_html_default_types[] = {
73 ngx_string("text/html"),
74 ngx_null_string
75};
76
77
Igor Sysoev4e9393a2003-01-09 05:36:00 +000078static ngx_command_t ngx_http_commands[] = {
79
Igor Sysoev8184d1b2005-03-04 14:06:57 +000080 { ngx_string("http"),
81 NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
82 ngx_http_block,
83 0,
84 0,
85 NULL },
Igor Sysoev4e9393a2003-01-09 05:36:00 +000086
Igor Sysoev8184d1b2005-03-04 14:06:57 +000087 ngx_null_command
Igor Sysoev4e9393a2003-01-09 05:36:00 +000088};
89
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +000090
Igor Sysoev43f13192004-04-12 16:38:09 +000091static ngx_core_module_t ngx_http_module_ctx = {
92 ngx_string("http"),
93 NULL,
94 NULL
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +000095};
Igor Sysoev43f13192004-04-12 16:38:09 +000096
Igor Sysoev4e9393a2003-01-09 05:36:00 +000097
98ngx_module_t ngx_http_module = {
Igor Sysoev899b44e2005-05-12 14:58:06 +000099 NGX_MODULE_V1,
Igor Sysoev43f13192004-04-12 16:38:09 +0000100 &ngx_http_module_ctx, /* module context */
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000101 ngx_http_commands, /* module directives */
Igor Sysoev6253ca12003-05-27 12:18:54 +0000102 NGX_CORE_MODULE, /* module type */
Igor Sysoeve5733802005-09-08 14:36:09 +0000103 NULL, /* init master */
Igor Sysoeva7f7fa82003-07-11 04:50:59 +0000104 NULL, /* init module */
Igor Sysoeve5733802005-09-08 14:36:09 +0000105 NULL, /* init process */
106 NULL, /* init thread */
107 NULL, /* exit thread */
108 NULL, /* exit process */
109 NULL, /* exit master */
110 NGX_MODULE_V1_PADDING
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000111};
112
113
Igor Sysoev8184d1b2005-03-04 14:06:57 +0000114static char *
115ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000116{
Igor Sysoev2e6ba932004-09-09 15:40:48 +0000117 char *rv;
Igor Sysoev6d14e652008-05-22 11:07:08 +0000118 ngx_uint_t mi, m, s;
Igor Sysoev3b30a902003-12-25 20:26:58 +0000119 ngx_conf_t pcf;
Igor Sysoeva9830112003-05-19 16:39:14 +0000120 ngx_http_module_t *module;
Igor Sysoeva9830112003-05-19 16:39:14 +0000121 ngx_http_conf_ctx_t *ctx;
Igor Sysoeve55988c2008-05-24 14:14:13 +0000122 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev6d14e652008-05-22 11:07:08 +0000123 ngx_http_core_srv_conf_t **cscfp;
Igor Sysoev3b30a902003-12-25 20:26:58 +0000124 ngx_http_core_main_conf_t *cmcf;
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000125
Igor Sysoeva9830112003-05-19 16:39:14 +0000126 /* the main http context */
Igor Sysoevb1dfe472004-12-21 12:30:30 +0000127
Igor Sysoevc1571722005-03-19 12:38:37 +0000128 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
129 if (ctx == NULL) {
Igor Sysoev805d9db2005-02-03 19:33:37 +0000130 return NGX_CONF_ERROR;
131 }
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000132
Igor Sysoevbb4ec5c2003-05-16 15:27:48 +0000133 *(ngx_http_conf_ctx_t **) conf = ctx;
134
Igor Sysoev805d9db2005-02-03 19:33:37 +0000135
Igor Sysoeva9830112003-05-19 16:39:14 +0000136 /* count the number of the http modules and set up their indices */
137
Igor Sysoeve2a31542003-04-08 15:40:10 +0000138 ngx_http_max_module = 0;
Igor Sysoeva9830112003-05-19 16:39:14 +0000139 for (m = 0; ngx_modules[m]; m++) {
Igor Sysoev6253ca12003-05-27 12:18:54 +0000140 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000141 continue;
142 }
143
Igor Sysoev6253ca12003-05-27 12:18:54 +0000144 ngx_modules[m]->ctx_index = ngx_http_max_module++;
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000145 }
146
Igor Sysoevb1dfe472004-12-21 12:30:30 +0000147
Igor Sysoev805d9db2005-02-03 19:33:37 +0000148 /* the http main_conf context, it is the same in the all http contexts */
Igor Sysoevbb4ec5c2003-05-16 15:27:48 +0000149
Igor Sysoev805d9db2005-02-03 19:33:37 +0000150 ctx->main_conf = ngx_pcalloc(cf->pool,
151 sizeof(void *) * ngx_http_max_module);
152 if (ctx->main_conf == NULL) {
153 return NGX_CONF_ERROR;
154 }
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000155
Igor Sysoeva9830112003-05-19 16:39:14 +0000156
Igor Sysoev805d9db2005-02-03 19:33:37 +0000157 /*
158 * the http null srv_conf context, it is used to merge
159 * the server{}s' srv_conf's
160 */
161
162 ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
163 if (ctx->srv_conf == NULL) {
164 return NGX_CONF_ERROR;
165 }
166
167
168 /*
169 * the http null loc_conf context, it is used to merge
170 * the server{}s' loc_conf's
171 */
172
173 ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
174 if (ctx->loc_conf == NULL) {
175 return NGX_CONF_ERROR;
176 }
177
178
179 /*
180 * create the main_conf's, the null srv_conf's, and the null loc_conf's
181 * of the all http modules
182 */
Igor Sysoeva9830112003-05-19 16:39:14 +0000183
184 for (m = 0; ngx_modules[m]; m++) {
Igor Sysoev6253ca12003-05-27 12:18:54 +0000185 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000186 continue;
187 }
188
Igor Sysoev6253ca12003-05-27 12:18:54 +0000189 module = ngx_modules[m]->ctx;
190 mi = ngx_modules[m]->ctx_index;
Igor Sysoeva9830112003-05-19 16:39:14 +0000191
192 if (module->create_main_conf) {
Igor Sysoevc1571722005-03-19 12:38:37 +0000193 ctx->main_conf[mi] = module->create_main_conf(cf);
194 if (ctx->main_conf[mi] == NULL) {
Igor Sysoev805d9db2005-02-03 19:33:37 +0000195 return NGX_CONF_ERROR;
196 }
Igor Sysoeva9830112003-05-19 16:39:14 +0000197 }
198
199 if (module->create_srv_conf) {
Igor Sysoevc1571722005-03-19 12:38:37 +0000200 ctx->srv_conf[mi] = module->create_srv_conf(cf);
201 if (ctx->srv_conf[mi] == NULL) {
Igor Sysoev805d9db2005-02-03 19:33:37 +0000202 return NGX_CONF_ERROR;
203 }
Igor Sysoeva9830112003-05-19 16:39:14 +0000204 }
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000205
206 if (module->create_loc_conf) {
Igor Sysoevc1571722005-03-19 12:38:37 +0000207 ctx->loc_conf[mi] = module->create_loc_conf(cf);
208 if (ctx->loc_conf[mi] == NULL) {
Igor Sysoev805d9db2005-02-03 19:33:37 +0000209 return NGX_CONF_ERROR;
210 }
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000211 }
212 }
213
Igor Sysoev899b44e2005-05-12 14:58:06 +0000214 pcf = *cf;
215 cf->ctx = ctx;
216
217 for (m = 0; ngx_modules[m]; m++) {
218 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
219 continue;
220 }
221
222 module = ngx_modules[m]->ctx;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000223
224 if (module->preconfiguration) {
225 if (module->preconfiguration(cf) != NGX_OK) {
226 return NGX_CONF_ERROR;
227 }
228 }
229 }
Igor Sysoev805d9db2005-02-03 19:33:37 +0000230
Igor Sysoeva9830112003-05-19 16:39:14 +0000231 /* parse inside the http{} block */
232
Igor Sysoev6253ca12003-05-27 12:18:54 +0000233 cf->module_type = NGX_HTTP_MODULE;
Igor Sysoev79a80482003-05-14 17:13:13 +0000234 cf->cmd_type = NGX_HTTP_MAIN_CONF;
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000235 rv = ngx_conf_parse(cf, NULL);
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000236
Igor Sysoev74e95c22003-11-09 20:03:38 +0000237 if (rv != NGX_CONF_OK) {
Igor Sysoeve55988c2008-05-24 14:14:13 +0000238 goto failed;
Igor Sysoev74e95c22003-11-09 20:03:38 +0000239 }
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000240
Igor Sysoev74e95c22003-11-09 20:03:38 +0000241 /*
242 * init http{} main_conf's, merge the server{}s' srv_conf's
243 * and its location{}s' loc_conf's
244 */
Igor Sysoeva19a85e2003-01-28 15:56:37 +0000245
Igor Sysoev6253ca12003-05-27 12:18:54 +0000246 cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
Igor Sysoevaa3436c2003-05-30 14:27:59 +0000247 cscfp = cmcf->servers.elts;
Igor Sysoeva9830112003-05-19 16:39:14 +0000248
249 for (m = 0; ngx_modules[m]; m++) {
Igor Sysoev6253ca12003-05-27 12:18:54 +0000250 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
Igor Sysoeva9830112003-05-19 16:39:14 +0000251 continue;
252 }
253
Igor Sysoevaa3436c2003-05-30 14:27:59 +0000254 module = ngx_modules[m]->ctx;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000255 mi = ngx_modules[m]->ctx_index;
Igor Sysoeva9830112003-05-19 16:39:14 +0000256
257 /* init http{} main_conf's */
258
259 if (module->init_main_conf) {
Igor Sysoev890fc962003-07-20 21:15:59 +0000260 rv = module->init_main_conf(cf, ctx->main_conf[mi]);
Igor Sysoeva9830112003-05-19 16:39:14 +0000261 if (rv != NGX_CONF_OK) {
Igor Sysoeve55988c2008-05-24 14:14:13 +0000262 goto failed;
Igor Sysoeva9830112003-05-19 16:39:14 +0000263 }
264 }
265
266 for (s = 0; s < cmcf->servers.nelts; s++) {
267
268 /* merge the server{}s' srv_conf's */
269
270 if (module->merge_srv_conf) {
Igor Sysoeve55988c2008-05-24 14:14:13 +0000271 rv = module->merge_srv_conf(cf, ctx->srv_conf[mi],
Igor Sysoeva9830112003-05-19 16:39:14 +0000272 cscfp[s]->ctx->srv_conf[mi]);
273 if (rv != NGX_CONF_OK) {
Igor Sysoeve55988c2008-05-24 14:14:13 +0000274 goto failed;
Igor Sysoeva9830112003-05-19 16:39:14 +0000275 }
276 }
277
278 if (module->merge_loc_conf) {
279
280 /* merge the server{}'s loc_conf */
281
Igor Sysoeve55988c2008-05-24 14:14:13 +0000282 rv = module->merge_loc_conf(cf, ctx->loc_conf[mi],
Igor Sysoeva9830112003-05-19 16:39:14 +0000283 cscfp[s]->ctx->loc_conf[mi]);
284 if (rv != NGX_CONF_OK) {
Igor Sysoeve55988c2008-05-24 14:14:13 +0000285 goto failed;
Igor Sysoeva9830112003-05-19 16:39:14 +0000286 }
287
288 /* merge the locations{}' loc_conf's */
289
Igor Sysoeve55988c2008-05-24 14:14:13 +0000290 clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
291
292 rv = ngx_http_merge_locations(cf, clcf->locations,
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000293 cscfp[s]->ctx->loc_conf,
294 module, mi);
295 if (rv != NGX_CONF_OK) {
Igor Sysoeve55988c2008-05-24 14:14:13 +0000296 goto failed;
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000297 }
Igor Sysoeva9830112003-05-19 16:39:14 +0000298 }
Igor Sysoeva19a85e2003-01-28 15:56:37 +0000299 }
300 }
Igor Sysoeva9830112003-05-19 16:39:14 +0000301
Igor Sysoev805d9db2005-02-03 19:33:37 +0000302
Igor Sysoeve55988c2008-05-24 14:14:13 +0000303 /* create location trees */
304
305 for (s = 0; s < cmcf->servers.nelts; s++) {
306
307 clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
308
309 if (ngx_http_init_locations(cf, cscfp[s], clcf) != NGX_OK) {
310 return NGX_CONF_ERROR;
311 }
312
313 if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
314 return NGX_CONF_ERROR;
315 }
316 }
317
318
Igor Sysoev87ac67f2008-05-22 09:57:47 +0000319 if (ngx_http_init_phases(cf, cmcf) != NGX_OK) {
Igor Sysoev805d9db2005-02-03 19:33:37 +0000320 return NGX_CONF_ERROR;
321 }
322
Igor Sysoev87ac67f2008-05-22 09:57:47 +0000323 if (ngx_http_init_headers_in_hash(cf, cmcf) != NGX_OK) {
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000324 return NGX_CONF_ERROR;
325 }
326
Igor Sysoev899b44e2005-05-12 14:58:06 +0000327
328 for (m = 0; ngx_modules[m]; m++) {
329 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
330 continue;
331 }
332
333 module = ngx_modules[m]->ctx;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000334
335 if (module->postconfiguration) {
336 if (module->postconfiguration(cf) != NGX_OK) {
337 return NGX_CONF_ERROR;
338 }
339 }
340 }
341
Igor Sysoev09c684b2005-11-09 17:25:55 +0000342 if (ngx_http_variables_init_vars(cf) != NGX_OK) {
343 return NGX_CONF_ERROR;
344 }
Igor Sysoev899b44e2005-05-12 14:58:06 +0000345
346 /*
347 * http{}'s cf->ctx was needed while the configuration merging
348 * and in postconfiguration process
349 */
350
351 *cf = pcf;
352
Igor Sysoev02f742b2005-04-08 15:18:55 +0000353
Igor Sysoev87ac67f2008-05-22 09:57:47 +0000354 if (ngx_http_init_phase_handlers(cf, cmcf) != NGX_OK) {
Igor Sysoevda173ab2006-08-30 10:39:17 +0000355 return NGX_CONF_ERROR;
356 }
357
Igor Sysoevda173ab2006-08-30 10:39:17 +0000358
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000359 /* optimize the lists of ports, addresses and server names */
Igor Sysoeva19a85e2003-01-28 15:56:37 +0000360
Igor Sysoev79d630a2009-10-21 08:19:46 +0000361 if (ngx_http_optimize_servers(cf, cmcf, cmcf->ports) != NGX_OK) {
Igor Sysoev6d14e652008-05-22 11:07:08 +0000362 return NGX_CONF_ERROR;
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000363 }
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000364
365 return NGX_CONF_OK;
Igor Sysoeve55988c2008-05-24 14:14:13 +0000366
367failed:
368
369 *cf = pcf;
370
371 return rv;
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000372}
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000373
374
Igor Sysoev87ac67f2008-05-22 09:57:47 +0000375static ngx_int_t
376ngx_http_init_phases(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
377{
378 if (ngx_array_init(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers,
379 cf->pool, 1, sizeof(ngx_http_handler_pt))
380 != NGX_OK)
381 {
382 return NGX_ERROR;
383 }
384
385 if (ngx_array_init(&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers,
386 cf->pool, 1, sizeof(ngx_http_handler_pt))
387 != NGX_OK)
388 {
389 return NGX_ERROR;
390 }
391
392 if (ngx_array_init(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers,
393 cf->pool, 1, sizeof(ngx_http_handler_pt))
394 != NGX_OK)
395 {
396 return NGX_ERROR;
397 }
398
399 if (ngx_array_init(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers,
400 cf->pool, 1, sizeof(ngx_http_handler_pt))
401 != NGX_OK)
402 {
403 return NGX_ERROR;
404 }
405
406 if (ngx_array_init(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers,
407 cf->pool, 2, sizeof(ngx_http_handler_pt))
408 != NGX_OK)
409 {
410 return NGX_ERROR;
411 }
412
413 if (ngx_array_init(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers,
414 cf->pool, 4, sizeof(ngx_http_handler_pt))
415 != NGX_OK)
416 {
417 return NGX_ERROR;
418 }
419
420 if (ngx_array_init(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers,
421 cf->pool, 1, sizeof(ngx_http_handler_pt))
422 != NGX_OK)
423 {
424 return NGX_ERROR;
425 }
426
427 return NGX_OK;
428}
429
430
431static ngx_int_t
432ngx_http_init_headers_in_hash(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
433{
434 ngx_array_t headers_in;
435 ngx_hash_key_t *hk;
436 ngx_hash_init_t hash;
437 ngx_http_header_t *header;
438
439 if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t))
440 != NGX_OK)
441 {
442 return NGX_ERROR;
443 }
444
445 for (header = ngx_http_headers_in; header->name.len; header++) {
446 hk = ngx_array_push(&headers_in);
447 if (hk == NULL) {
448 return NGX_ERROR;
449 }
450
451 hk->key = header->name;
452 hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len);
453 hk->value = header;
454 }
455
456 hash.hash = &cmcf->headers_in_hash;
457 hash.key = ngx_hash_key_lc;
458 hash.max_size = 512;
459 hash.bucket_size = ngx_align(64, ngx_cacheline_size);
460 hash.name = "headers_in_hash";
461 hash.pool = cf->pool;
462 hash.temp_pool = NULL;
463
464 if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) {
465 return NGX_ERROR;
466 }
467
468 return NGX_OK;
469}
470
471
472static ngx_int_t
473ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
474{
475 ngx_int_t j;
476 ngx_uint_t i, n;
477 ngx_uint_t find_config_index, use_rewrite, use_access;
478 ngx_http_handler_pt *h;
479 ngx_http_phase_handler_t *ph;
480 ngx_http_phase_handler_pt checker;
481
482 cmcf->phase_engine.server_rewrite_index = (ngx_uint_t) -1;
483 cmcf->phase_engine.location_rewrite_index = (ngx_uint_t) -1;
484 find_config_index = 0;
485 use_rewrite = cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers.nelts ? 1 : 0;
486 use_access = cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers.nelts ? 1 : 0;
487
Igor Sysoevd8e3d0b2008-12-15 10:56:48 +0000488 n = use_rewrite + use_access + cmcf->try_files + 1 /* find config phase */;
Igor Sysoev87ac67f2008-05-22 09:57:47 +0000489
490 for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) {
491 n += cmcf->phases[i].handlers.nelts;
492 }
493
494 ph = ngx_pcalloc(cf->pool,
495 n * sizeof(ngx_http_phase_handler_t) + sizeof(void *));
496 if (ph == NULL) {
497 return NGX_ERROR;
498 }
499
500 cmcf->phase_engine.handlers = ph;
501 n = 0;
502
503 for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) {
504 h = cmcf->phases[i].handlers.elts;
505
506 switch (i) {
507
508 case NGX_HTTP_SERVER_REWRITE_PHASE:
509 if (cmcf->phase_engine.server_rewrite_index == (ngx_uint_t) -1) {
510 cmcf->phase_engine.server_rewrite_index = n;
511 }
512 checker = ngx_http_core_generic_phase;
513
514 break;
515
516 case NGX_HTTP_FIND_CONFIG_PHASE:
517 find_config_index = n;
518
519 ph->checker = ngx_http_core_find_config_phase;
520 n++;
521 ph++;
522
523 continue;
524
525 case NGX_HTTP_REWRITE_PHASE:
526 if (cmcf->phase_engine.location_rewrite_index == (ngx_uint_t) -1) {
527 cmcf->phase_engine.location_rewrite_index = n;
528 }
529 checker = ngx_http_core_generic_phase;
530
531 break;
532
533 case NGX_HTTP_POST_REWRITE_PHASE:
534 if (use_rewrite) {
535 ph->checker = ngx_http_core_post_rewrite_phase;
536 ph->next = find_config_index;
537 n++;
538 ph++;
539 }
540
541 continue;
542
543 case NGX_HTTP_ACCESS_PHASE:
544 checker = ngx_http_core_access_phase;
545 n++;
546 break;
547
548 case NGX_HTTP_POST_ACCESS_PHASE:
549 if (use_access) {
550 ph->checker = ngx_http_core_post_access_phase;
551 ph->next = n;
552 ph++;
553 }
554
555 continue;
556
Igor Sysoevd8e3d0b2008-12-15 10:56:48 +0000557 case NGX_HTTP_TRY_FILES_PHASE:
558 if (cmcf->try_files) {
559 ph->checker = ngx_http_core_try_files_phase;
560 n++;
561 ph++;
562 }
563
564 continue;
565
Igor Sysoev87ac67f2008-05-22 09:57:47 +0000566 case NGX_HTTP_CONTENT_PHASE:
567 checker = ngx_http_core_content_phase;
568 break;
569
570 default:
571 checker = ngx_http_core_generic_phase;
572 }
573
574 n += cmcf->phases[i].handlers.nelts;
575
576 for (j = cmcf->phases[i].handlers.nelts - 1; j >=0; j--) {
577 ph->checker = checker;
578 ph->handler = h[j];
579 ph->next = n;
580 ph++;
581 }
582 }
583
584 return NGX_OK;
585}
586
587
Igor Sysoeve55988c2008-05-24 14:14:13 +0000588static char *
589ngx_http_merge_locations(ngx_conf_t *cf, ngx_queue_t *locations,
590 void **loc_conf, ngx_http_module_t *module, ngx_uint_t ctx_index)
591{
592 char *rv;
593 ngx_queue_t *q;
594 ngx_http_core_loc_conf_t *clcf;
595 ngx_http_location_queue_t *lq;
596
597 if (locations == NULL) {
598 return NGX_CONF_OK;
599 }
600
601 for (q = ngx_queue_head(locations);
602 q != ngx_queue_sentinel(locations);
603 q = ngx_queue_next(q))
604 {
605 lq = (ngx_http_location_queue_t *) q;
606
607 clcf = lq->exact ? lq->exact : lq->inclusive;
608
609 rv = module->merge_loc_conf(cf, loc_conf[ctx_index],
610 clcf->loc_conf[ctx_index]);
611 if (rv != NGX_CONF_OK) {
612 return rv;
613 }
614
615 rv = ngx_http_merge_locations(cf, clcf->locations, clcf->loc_conf,
616 module, ctx_index);
617 if (rv != NGX_CONF_OK) {
618 return rv;
619 }
620 }
621
622 return NGX_CONF_OK;
623}
624
625
626static ngx_int_t
627ngx_http_init_locations(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
628 ngx_http_core_loc_conf_t *pclcf)
629{
630 ngx_uint_t n;
631 ngx_queue_t *q, *locations, *named, tail;
632 ngx_http_core_loc_conf_t *clcf;
633 ngx_http_location_queue_t *lq;
634 ngx_http_core_loc_conf_t **clcfp;
635#if (NGX_PCRE)
636 ngx_uint_t r;
637 ngx_queue_t *regex;
638#endif
639
640 locations = pclcf->locations;
641
642 if (locations == NULL) {
643 return NGX_OK;
644 }
645
646 ngx_queue_sort(locations, ngx_http_cmp_locations);
647
648 named = NULL;
649 n = 0;
650#if (NGX_PCRE)
651 regex = NULL;
652 r = 0;
653#endif
654
655 for (q = ngx_queue_head(locations);
656 q != ngx_queue_sentinel(locations);
657 q = ngx_queue_next(q))
658 {
659 lq = (ngx_http_location_queue_t *) q;
660
661 clcf = lq->exact ? lq->exact : lq->inclusive;
662
663 if (ngx_http_init_locations(cf, NULL, clcf) != NGX_OK) {
664 return NGX_ERROR;
665 }
666
667#if (NGX_PCRE)
668
669 if (clcf->regex) {
670 r++;
671
672 if (regex == NULL) {
673 regex = q;
674 }
675
676 continue;
677 }
678
679#endif
680
681 if (clcf->named) {
682 n++;
683
684 if (named == NULL) {
685 named = q;
686 }
687
688 continue;
689 }
690
691 if (clcf->noname) {
692 break;
693 }
694 }
695
696 if (q != ngx_queue_sentinel(locations)) {
697 ngx_queue_split(locations, q, &tail);
698 }
699
700 if (named) {
701 clcfp = ngx_palloc(cf->pool,
702 (n + 1) * sizeof(ngx_http_core_loc_conf_t **));
703 if (clcfp == NULL) {
704 return NGX_ERROR;
705 }
706
707 cscf->named_locations = clcfp;
708
709 for (q = named;
710 q != ngx_queue_sentinel(locations);
711 q = ngx_queue_next(q))
712 {
713 lq = (ngx_http_location_queue_t *) q;
714
715 *(clcfp++) = lq->exact;
716 }
717
718 *clcfp = NULL;
719
720 ngx_queue_split(locations, named, &tail);
721 }
722
723#if (NGX_PCRE)
724
725 if (regex) {
726
727 clcfp = ngx_palloc(cf->pool,
728 (r + 1) * sizeof(ngx_http_core_loc_conf_t **));
729 if (clcfp == NULL) {
730 return NGX_ERROR;
731 }
732
733 pclcf->regex_locations = clcfp;
734
735 for (q = regex;
736 q != ngx_queue_sentinel(locations);
737 q = ngx_queue_next(q))
738 {
739 lq = (ngx_http_location_queue_t *) q;
740
741 *(clcfp++) = lq->exact;
742 }
743
744 *clcfp = NULL;
745
746 ngx_queue_split(locations, regex, &tail);
747 }
748
749#endif
750
751 return NGX_OK;
752}
753
754
755static ngx_int_t
756ngx_http_init_static_location_trees(ngx_conf_t *cf,
757 ngx_http_core_loc_conf_t *pclcf)
758{
759 ngx_queue_t *q, *locations;
760 ngx_http_core_loc_conf_t *clcf;
761 ngx_http_location_queue_t *lq;
762
763 locations = pclcf->locations;
764
765 if (locations == NULL) {
766 return NGX_OK;
767 }
768
769 if (ngx_queue_empty(locations)) {
770 return NGX_OK;
771 }
772
773 for (q = ngx_queue_head(locations);
774 q != ngx_queue_sentinel(locations);
775 q = ngx_queue_next(q))
776 {
777 lq = (ngx_http_location_queue_t *) q;
778
779 clcf = lq->exact ? lq->exact : lq->inclusive;
780
781 if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
782 return NGX_ERROR;
783 }
784 }
785
786 if (ngx_http_join_exact_locations(cf, locations) != NGX_OK) {
787 return NGX_ERROR;
788 }
789
790 ngx_http_create_locations_list(locations, ngx_queue_head(locations));
791
792 pclcf->static_locations = ngx_http_create_locations_tree(cf, locations, 0);
793 if (pclcf->static_locations == NULL) {
794 return NGX_ERROR;
795 }
796
797 return NGX_OK;
798}
799
800
801ngx_int_t
802ngx_http_add_location(ngx_conf_t *cf, ngx_queue_t **locations,
803 ngx_http_core_loc_conf_t *clcf)
804{
805 ngx_http_location_queue_t *lq;
806
807 if (*locations == NULL) {
808 *locations = ngx_palloc(cf->temp_pool,
809 sizeof(ngx_http_location_queue_t));
810 if (*locations == NULL) {
811 return NGX_ERROR;
812 }
813
814 ngx_queue_init(*locations);
815 }
816
817 lq = ngx_palloc(cf->temp_pool, sizeof(ngx_http_location_queue_t));
818 if (lq == NULL) {
819 return NGX_ERROR;
820 }
821
822 if (clcf->exact_match
823#if (NGX_PCRE)
824 || clcf->regex
825#endif
826 || clcf->named || clcf->noname)
827 {
828 lq->exact = clcf;
829 lq->inclusive = NULL;
830
831 } else {
832 lq->exact = NULL;
833 lq->inclusive = clcf;
834 }
835
836 lq->name = &clcf->name;
837 lq->file_name = cf->conf_file->file.name.data;
838 lq->line = cf->conf_file->line;
839
840 ngx_queue_init(&lq->list);
841
842 ngx_queue_insert_tail(*locations, &lq->queue);
843
844 return NGX_OK;
845}
846
847
848static ngx_int_t
849ngx_http_cmp_locations(const ngx_queue_t *one, const ngx_queue_t *two)
850{
851 ngx_int_t rc;
852 ngx_http_core_loc_conf_t *first, *second;
853 ngx_http_location_queue_t *lq1, *lq2;
854
855 lq1 = (ngx_http_location_queue_t *) one;
856 lq2 = (ngx_http_location_queue_t *) two;
857
858 first = lq1->exact ? lq1->exact : lq1->inclusive;
859 second = lq2->exact ? lq2->exact : lq2->inclusive;
860
861 if (first->noname && !second->noname) {
862 /* shift no named locations to the end */
863 return 1;
864 }
865
866 if (!first->noname && second->noname) {
867 /* shift no named locations to the end */
868 return -1;
869 }
870
871 if (first->noname || second->noname) {
872 /* do not sort no named locations */
873 return 0;
874 }
875
876 if (first->named && !second->named) {
877 /* shift named locations to the end */
878 return 1;
879 }
880
881 if (!first->named && second->named) {
882 /* shift named locations to the end */
883 return -1;
884 }
885
886 if (first->named && second->named) {
887 return ngx_strcmp(first->name.data, second->name.data);
888 }
889
890#if (NGX_PCRE)
891
892 if (first->regex && !second->regex) {
893 /* shift the regex matches to the end */
894 return 1;
895 }
896
897 if (!first->regex && second->regex) {
898 /* shift the regex matches to the end */
899 return -1;
900 }
901
902 if (first->regex || second->regex) {
903 /* do not sort the regex matches */
904 return 0;
905 }
906
907#endif
908
909 rc = ngx_strcmp(first->name.data, second->name.data);
910
911 if (rc == 0 && !first->exact_match && second->exact_match) {
912 /* an exact match must be before the same inclusive one */
913 return 1;
914 }
915
916 return rc;
917}
918
919
920static ngx_int_t
921ngx_http_join_exact_locations(ngx_conf_t *cf, ngx_queue_t *locations)
922{
923 ngx_queue_t *q, *x;
924 ngx_http_location_queue_t *lq, *lx;
925
926 q = ngx_queue_head(locations);
927
928 while (q != ngx_queue_last(locations)) {
929
930 x = ngx_queue_next(q);
931
932 lq = (ngx_http_location_queue_t *) q;
933 lx = (ngx_http_location_queue_t *) x;
934
935 if (ngx_strcmp(lq->name->data, lx->name->data) == 0) {
936
937 if ((lq->exact && lx->exact) || (lq->inclusive && lx->inclusive)) {
938 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
939 "duplicate location \"%V\" in %s:%ui",
940 lx->name, lx->file_name, lx->line);
941
942 return NGX_ERROR;
943 }
944
945 lq->inclusive = lx->inclusive;
946
947 ngx_queue_remove(x);
948
949 continue;
950 }
951
952 q = ngx_queue_next(q);
953 }
954
955 return NGX_OK;
956}
957
958
959static void
960ngx_http_create_locations_list(ngx_queue_t *locations, ngx_queue_t *q)
961{
962 u_char *name;
963 size_t len;
964 ngx_queue_t *x, tail;
965 ngx_http_location_queue_t *lq, *lx;
966
967 if (q == ngx_queue_last(locations)) {
968 return;
969 }
970
971 lq = (ngx_http_location_queue_t *) q;
972
973 if (lq->inclusive == NULL) {
974 ngx_http_create_locations_list(locations, ngx_queue_next(q));
975 return;
976 }
977
978 len = lq->name->len;
979 name = lq->name->data;
980
981 for (x = ngx_queue_next(q);
982 x != ngx_queue_sentinel(locations);
983 x = ngx_queue_next(x))
984 {
985 lx = (ngx_http_location_queue_t *) x;
986
987 if (len > lx->name->len
988 || (ngx_strncmp(name, lx->name->data, len) != 0))
989 {
990 break;
991 }
992 }
993
994 q = ngx_queue_next(q);
995
996 if (q == x) {
997 ngx_http_create_locations_list(locations, x);
998 return;
999 }
1000
1001 ngx_queue_split(locations, q, &tail);
1002 ngx_queue_add(&lq->list, &tail);
1003
1004 if (x == ngx_queue_sentinel(locations)) {
1005 ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list));
1006 return;
1007 }
1008
1009 ngx_queue_split(&lq->list, x, &tail);
1010 ngx_queue_add(locations, &tail);
1011
1012 ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list));
1013
1014 ngx_http_create_locations_list(locations, x);
1015}
1016
1017
1018/*
1019 * to keep cache locality for left leaf nodes, allocate nodes in following
1020 * order: node, left subtree, right subtree, inclusive subtree
1021 */
1022
1023static ngx_http_location_tree_node_t *
1024ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations,
1025 size_t prefix)
1026{
1027 size_t len;
1028 ngx_queue_t *q, tail;
1029 ngx_http_location_queue_t *lq;
1030 ngx_http_location_tree_node_t *node;
1031
1032 q = ngx_queue_middle(locations);
1033
1034 lq = (ngx_http_location_queue_t *) q;
1035 len = lq->name->len - prefix;
1036
Igor Sysoev7f6b2ff2008-06-17 15:00:30 +00001037 node = ngx_palloc(cf->pool,
1038 offsetof(ngx_http_location_tree_node_t, name) + len);
Igor Sysoeve55988c2008-05-24 14:14:13 +00001039 if (node == NULL) {
1040 return NULL;
1041 }
1042
Igor Sysoev2d951bf2008-05-27 09:37:40 +00001043 node->left = NULL;
1044 node->right = NULL;
1045 node->tree = NULL;
Igor Sysoeve55988c2008-05-24 14:14:13 +00001046 node->exact = lq->exact;
1047 node->inclusive = lq->inclusive;
1048
1049 node->auto_redirect = (u_char) ((lq->exact && lq->exact->auto_redirect)
1050 || (lq->inclusive && lq->inclusive->auto_redirect));
1051
1052 node->len = (u_char) len;
1053 ngx_memcpy(node->name, &lq->name->data[prefix], len);
1054
1055 ngx_queue_split(locations, q, &tail);
1056
1057 if (ngx_queue_empty(locations)) {
1058 /*
1059 * ngx_queue_split() insures that if left part is empty,
1060 * then right one is empty too
1061 */
1062 goto inclusive;
1063 }
1064
1065 node->left = ngx_http_create_locations_tree(cf, locations, prefix);
1066 if (node->left == NULL) {
1067 return NULL;
1068 }
1069
1070 ngx_queue_remove(q);
1071
1072 if (ngx_queue_empty(&tail)) {
1073 goto inclusive;
1074 }
1075
1076 node->right = ngx_http_create_locations_tree(cf, &tail, prefix);
1077 if (node->right == NULL) {
1078 return NULL;
1079 }
1080
1081inclusive:
1082
1083 if (ngx_queue_empty(&lq->list)) {
1084 return node;
1085 }
1086
1087 node->tree = ngx_http_create_locations_tree(cf, &lq->list, prefix + len);
1088 if (node->tree == NULL) {
1089 return NULL;
1090 }
1091
1092 return node;
1093}
1094
1095
Igor Sysoev79d630a2009-10-21 08:19:46 +00001096ngx_int_t
1097ngx_http_add_listen(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
Igor Sysoevf2694cb2009-10-21 16:47:44 +00001098 ngx_http_listen_opt_t *lsopt)
Igor Sysoev6d14e652008-05-22 11:07:08 +00001099{
Igor Sysoev79d630a2009-10-21 08:19:46 +00001100 in_port_t p;
1101 ngx_uint_t i;
1102 struct sockaddr *sa;
1103 struct sockaddr_in *sin;
1104 ngx_http_conf_port_t *port;
1105 ngx_http_core_main_conf_t *cmcf;
1106#if (NGX_HAVE_INET6)
1107 struct sockaddr_in6 *sin6;
1108#endif
Igor Sysoev6d14e652008-05-22 11:07:08 +00001109
Igor Sysoev79d630a2009-10-21 08:19:46 +00001110 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
Igor Sysoev6d14e652008-05-22 11:07:08 +00001111
Igor Sysoev79d630a2009-10-21 08:19:46 +00001112 if (cmcf->ports == NULL) {
1113 cmcf->ports = ngx_array_create(cf->temp_pool, 2,
1114 sizeof(ngx_http_conf_port_t));
1115 if (cmcf->ports == NULL) {
1116 return NGX_ERROR;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001117 }
1118 }
1119
Igor Sysoevf2694cb2009-10-21 16:47:44 +00001120 sa = (struct sockaddr *) &lsopt->sockaddr;
Igor Sysoeva8833612009-02-18 16:17:12 +00001121
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001122 switch (sa->sa_family) {
1123
1124#if (NGX_HAVE_INET6)
1125 case AF_INET6:
1126 sin6 = (struct sockaddr_in6 *) sa;
1127 p = sin6->sin6_port;
1128 break;
1129#endif
1130
1131 default: /* AF_INET */
1132 sin = (struct sockaddr_in *) sa;
1133 p = sin->sin_port;
1134 break;
1135 }
1136
Igor Sysoev79d630a2009-10-21 08:19:46 +00001137 port = cmcf->ports->elts;
1138 for (i = 0; i < cmcf->ports->nelts; i++) {
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001139
1140 if (p != port[i].port || sa->sa_family != port[i].family) {
Igor Sysoeva8833612009-02-18 16:17:12 +00001141 continue;
1142 }
1143
Igor Sysoev1daaa002009-05-17 20:13:29 +00001144 /* a port is already in the port list */
Igor Sysoeva8833612009-02-18 16:17:12 +00001145
Igor Sysoevf2694cb2009-10-21 16:47:44 +00001146 return ngx_http_add_addresses(cf, cscf, &port[i], lsopt);
Igor Sysoeva8833612009-02-18 16:17:12 +00001147 }
1148
Igor Sysoev1daaa002009-05-17 20:13:29 +00001149 /* add a port to the port list */
Igor Sysoeva8833612009-02-18 16:17:12 +00001150
Igor Sysoev79d630a2009-10-21 08:19:46 +00001151 port = ngx_array_push(cmcf->ports);
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001152 if (port == NULL) {
Igor Sysoeva8833612009-02-18 16:17:12 +00001153 return NGX_ERROR;
1154 }
1155
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001156 port->family = sa->sa_family;
1157 port->port = p;
1158 port->addrs.elts = NULL;
Igor Sysoeva8833612009-02-18 16:17:12 +00001159
Igor Sysoevf2694cb2009-10-21 16:47:44 +00001160 return ngx_http_add_address(cf, cscf, port, lsopt);
Igor Sysoeva8833612009-02-18 16:17:12 +00001161}
1162
1163
1164static ngx_int_t
1165ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
Igor Sysoevf2694cb2009-10-21 16:47:44 +00001166 ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt)
Igor Sysoeva8833612009-02-18 16:17:12 +00001167{
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001168 u_char *p;
1169 size_t len, off;
1170 ngx_uint_t i;
1171 struct sockaddr *sa;
1172 ngx_http_conf_addr_t *addr;
Igor Sysoeva8833612009-02-18 16:17:12 +00001173
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001174 /*
1175 * we can not compare whole sockaddr struct's as kernel
1176 * may fill some fields in inherited sockaddr struct's
1177 */
Igor Sysoeva8833612009-02-18 16:17:12 +00001178
Igor Sysoevf2694cb2009-10-21 16:47:44 +00001179 sa = (struct sockaddr *) &lsopt->sockaddr;
Igor Sysoeva8833612009-02-18 16:17:12 +00001180
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001181 switch (sa->sa_family) {
1182
1183#if (NGX_HAVE_INET6)
1184 case AF_INET6:
1185 off = offsetof(struct sockaddr_in6, sin6_addr);
1186 len = 16;
1187 break;
1188#endif
1189
1190 default: /* AF_INET */
1191 off = offsetof(struct sockaddr_in, sin_addr);
1192 len = 4;
1193 break;
1194 }
1195
Igor Sysoevf2694cb2009-10-21 16:47:44 +00001196 p = lsopt->sockaddr + off;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001197
1198 addr = port->addrs.elts;
1199
1200 for (i = 0; i < port->addrs.nelts; i++) {
1201
Igor Sysoevf2694cb2009-10-21 16:47:44 +00001202 if (ngx_memcmp(p, (u_char *) addr[i].opt.sockaddr + off, len) != 0) {
Igor Sysoeva8833612009-02-18 16:17:12 +00001203 continue;
1204 }
1205
1206 /* the address is already in the address list */
1207
Igor Sysoev2a634f52009-10-21 16:27:48 +00001208 if (ngx_http_add_server(cf, cscf, &addr[i]) != NGX_OK) {
Igor Sysoeva8833612009-02-18 16:17:12 +00001209 return NGX_ERROR;
1210 }
1211
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001212 /* check the duplicate "default" server for this address:port */
Igor Sysoeva8833612009-02-18 16:17:12 +00001213
Igor Sysoevf2694cb2009-10-21 16:47:44 +00001214 if (lsopt->default_server) {
Igor Sysoeva8833612009-02-18 16:17:12 +00001215
Igor Sysoevd2d09312009-10-21 08:48:04 +00001216 if (addr[i].opt.default_server) {
Igor Sysoev79d630a2009-10-21 08:19:46 +00001217 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
Igor Sysoevba3083b2009-10-21 19:13:27 +00001218 "a duplicate default server for %s", addr[i].opt.addr);
Igor Sysoeva8833612009-02-18 16:17:12 +00001219 return NGX_ERROR;
1220 }
1221
Igor Sysoevf2694cb2009-10-21 16:47:44 +00001222 addr[i].opt = *lsopt;
Igor Sysoevcd8b43c2009-10-21 16:52:10 +00001223 addr[i].default_server = cscf;
Igor Sysoeva8833612009-02-18 16:17:12 +00001224 }
1225
1226 return NGX_OK;
1227 }
1228
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001229 /* add the address to the addresses list that bound to this port */
Igor Sysoeva8833612009-02-18 16:17:12 +00001230
Igor Sysoevf2694cb2009-10-21 16:47:44 +00001231 return ngx_http_add_address(cf, cscf, port, lsopt);
Igor Sysoeva8833612009-02-18 16:17:12 +00001232}
1233
1234
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001235/*
1236 * add the server address, the server names and the server core module
Igor Sysoev1daaa002009-05-17 20:13:29 +00001237 * configurations to the port list
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001238 */
1239
Igor Sysoev8184d1b2005-03-04 14:06:57 +00001240static ngx_int_t
Igor Sysoev6d14e652008-05-22 11:07:08 +00001241ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
Igor Sysoevf2694cb2009-10-21 16:47:44 +00001242 ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt)
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001243{
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001244 ngx_http_conf_addr_t *addr;
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001245
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001246 if (port->addrs.elts == NULL) {
1247 if (ngx_array_init(&port->addrs, cf->temp_pool, 4,
1248 sizeof(ngx_http_conf_addr_t))
Igor Sysoev242d1de2007-08-12 09:00:56 +00001249 != NGX_OK)
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001250 {
1251 return NGX_ERROR;
1252 }
1253 }
1254
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001255 addr = ngx_array_push(&port->addrs);
1256 if (addr == NULL) {
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001257 return NGX_ERROR;
1258 }
1259
Igor Sysoevf2694cb2009-10-21 16:47:44 +00001260 addr->opt = *lsopt;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001261 addr->hash.buckets = NULL;
1262 addr->hash.size = 0;
1263 addr->wc_head = NULL;
1264 addr->wc_tail = NULL;
Igor Sysoev43c3bf42007-08-12 19:48:12 +00001265#if (NGX_PCRE)
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001266 addr->nregex = 0;
1267 addr->regex = NULL;
Igor Sysoev43c3bf42007-08-12 19:48:12 +00001268#endif
Igor Sysoevcd8b43c2009-10-21 16:52:10 +00001269 addr->default_server = cscf;
Igor Sysoev2a634f52009-10-21 16:27:48 +00001270 addr->servers.elts = NULL;
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001271
Igor Sysoev2a634f52009-10-21 16:27:48 +00001272 return ngx_http_add_server(cf, cscf, addr);
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001273}
1274
1275
Igor Sysoev2a634f52009-10-21 16:27:48 +00001276/* add the server core module configuration to the address:port */
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001277
Igor Sysoev8184d1b2005-03-04 14:06:57 +00001278static ngx_int_t
Igor Sysoev2a634f52009-10-21 16:27:48 +00001279ngx_http_add_server(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001280 ngx_http_conf_addr_t *addr)
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001281{
Igor Sysoev2a634f52009-10-21 16:27:48 +00001282 ngx_http_core_srv_conf_t **server;
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001283
Igor Sysoev2a634f52009-10-21 16:27:48 +00001284 if (addr->servers.elts == NULL) {
1285 if (ngx_array_init(&addr->servers, cf->temp_pool, 4,
1286 sizeof(ngx_http_core_srv_conf_t *))
Igor Sysoev242d1de2007-08-12 09:00:56 +00001287 != NGX_OK)
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001288 {
1289 return NGX_ERROR;
1290 }
1291 }
1292
Igor Sysoev2a634f52009-10-21 16:27:48 +00001293 server = ngx_array_push(&addr->servers);
1294 if (server == NULL) {
1295 return NGX_ERROR;
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001296 }
1297
Igor Sysoev2a634f52009-10-21 16:27:48 +00001298 *server = cscf;
1299
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001300 return NGX_OK;
1301}
1302
1303
Igor Sysoevde8ec1e2008-03-24 13:04:02 +00001304static ngx_int_t
Igor Sysoev6d14e652008-05-22 11:07:08 +00001305ngx_http_optimize_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001306 ngx_array_t *ports)
Igor Sysoev6d14e652008-05-22 11:07:08 +00001307{
Igor Sysoev2a634f52009-10-21 16:27:48 +00001308 ngx_uint_t p, a;
1309 ngx_http_conf_port_t *port;
1310 ngx_http_conf_addr_t *addr;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001311
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001312 port = ports->elts;
1313 for (p = 0; p < ports->nelts; p++) {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001314
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001315 ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts,
1316 sizeof(ngx_http_conf_addr_t), ngx_http_cmp_conf_addrs);
Igor Sysoev6d14e652008-05-22 11:07:08 +00001317
1318 /*
Igor Sysoeva8833612009-02-18 16:17:12 +00001319 * check whether all name-based servers have the same
1320 * configuraiton as a default server for given address:port
Igor Sysoev6d14e652008-05-22 11:07:08 +00001321 */
1322
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001323 addr = port[p].addrs.elts;
1324 for (a = 0; a < port[p].addrs.nelts; a++) {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001325
Igor Sysoev2a634f52009-10-21 16:27:48 +00001326 if (addr[a].servers.nelts > 1
Igor Sysoev7b5edd82009-03-19 16:07:40 +00001327#if (NGX_PCRE)
Igor Sysoevcd8b43c2009-10-21 16:52:10 +00001328 || addr[a].default_server->captures
Igor Sysoev7b5edd82009-03-19 16:07:40 +00001329#endif
Igor Sysoev2a634f52009-10-21 16:27:48 +00001330 )
1331 {
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001332 if (ngx_http_server_names(cf, cmcf, &addr[a]) != NGX_OK) {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001333 return NGX_ERROR;
1334 }
Igor Sysoev6d14e652008-05-22 11:07:08 +00001335 }
Igor Sysoev6d14e652008-05-22 11:07:08 +00001336 }
1337
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001338 if (ngx_http_init_listening(cf, &port[p]) != NGX_OK) {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001339 return NGX_ERROR;
1340 }
1341 }
1342
1343 return NGX_OK;
Igor Sysoeva8833612009-02-18 16:17:12 +00001344}
1345
1346
1347static ngx_int_t
1348ngx_http_server_names(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001349 ngx_http_conf_addr_t *addr)
Igor Sysoeva8833612009-02-18 16:17:12 +00001350{
Igor Sysoev2a634f52009-10-21 16:27:48 +00001351 ngx_int_t rc;
1352 ngx_uint_t n, s;
1353 ngx_hash_init_t hash;
1354 ngx_hash_keys_arrays_t ha;
1355 ngx_http_server_name_t *name;
1356 ngx_http_core_srv_conf_t **cscfp;
Igor Sysoeva8833612009-02-18 16:17:12 +00001357#if (NGX_PCRE)
Igor Sysoev2a634f52009-10-21 16:27:48 +00001358 ngx_uint_t regex, i;
Igor Sysoeva8833612009-02-18 16:17:12 +00001359
1360 regex = 0;
1361#endif
1362
1363 ngx_memzero(&ha, sizeof(ngx_hash_keys_arrays_t));
1364
1365 ha.temp_pool = ngx_create_pool(16384, cf->log);
1366 if (ha.temp_pool == NULL) {
1367 return NGX_ERROR;
1368 }
1369
1370 ha.pool = cf->pool;
1371
1372 if (ngx_hash_keys_array_init(&ha, NGX_HASH_LARGE) != NGX_OK) {
1373 goto failed;
1374 }
1375
Igor Sysoev2a634f52009-10-21 16:27:48 +00001376 cscfp = addr->servers.elts;
Igor Sysoeva8833612009-02-18 16:17:12 +00001377
Igor Sysoev2a634f52009-10-21 16:27:48 +00001378 for (s = 0; s < addr->servers.nelts; s++) {
1379
1380 name = cscfp[s]->server_names.elts;
1381
1382 for (n = 0; n < cscfp[s]->server_names.nelts; n++) {
Igor Sysoeva8833612009-02-18 16:17:12 +00001383
1384#if (NGX_PCRE)
Igor Sysoev2a634f52009-10-21 16:27:48 +00001385 if (name[n].regex) {
1386 regex++;
1387 continue;
1388 }
Igor Sysoeva8833612009-02-18 16:17:12 +00001389#endif
1390
Igor Sysoevcd8b43c2009-10-21 16:52:10 +00001391 rc = ngx_hash_add_key(&ha, &name[n].name, name[n].server,
Igor Sysoev2a634f52009-10-21 16:27:48 +00001392 NGX_HASH_WILDCARD_KEY);
Igor Sysoeva8833612009-02-18 16:17:12 +00001393
Igor Sysoev2a634f52009-10-21 16:27:48 +00001394 if (rc == NGX_ERROR) {
1395 return NGX_ERROR;
1396 }
Igor Sysoeva8833612009-02-18 16:17:12 +00001397
Igor Sysoev2a634f52009-10-21 16:27:48 +00001398 if (rc == NGX_DECLINED) {
1399 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
1400 "invalid server name or wildcard \"%V\" on %s",
1401 &name[n].name, addr->opt.addr);
1402 return NGX_ERROR;
1403 }
Igor Sysoeva8833612009-02-18 16:17:12 +00001404
Igor Sysoev2a634f52009-10-21 16:27:48 +00001405 if (rc == NGX_BUSY) {
Igor Sysoeva8833612009-02-18 16:17:12 +00001406 ngx_log_error(NGX_LOG_WARN, cf->log, 0,
Igor Sysoev2a634f52009-10-21 16:27:48 +00001407 "conflicting server name \"%V\" on %s, ignored",
1408 &name[n].name, addr->opt.addr);
1409 }
Igor Sysoeva8833612009-02-18 16:17:12 +00001410 }
1411 }
1412
1413 hash.key = ngx_hash_key_lc;
1414 hash.max_size = cmcf->server_names_hash_max_size;
1415 hash.bucket_size = cmcf->server_names_hash_bucket_size;
1416 hash.name = "server_names_hash";
1417 hash.pool = cf->pool;
1418
1419 if (ha.keys.nelts) {
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001420 hash.hash = &addr->hash;
Igor Sysoeva8833612009-02-18 16:17:12 +00001421 hash.temp_pool = NULL;
1422
1423 if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK) {
1424 goto failed;
1425 }
1426 }
1427
1428 if (ha.dns_wc_head.nelts) {
1429
1430 ngx_qsort(ha.dns_wc_head.elts, (size_t) ha.dns_wc_head.nelts,
1431 sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);
1432
1433 hash.hash = NULL;
1434 hash.temp_pool = ha.temp_pool;
1435
1436 if (ngx_hash_wildcard_init(&hash, ha.dns_wc_head.elts,
1437 ha.dns_wc_head.nelts)
1438 != NGX_OK)
1439 {
1440 goto failed;
1441 }
1442
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001443 addr->wc_head = (ngx_hash_wildcard_t *) hash.hash;
Igor Sysoeva8833612009-02-18 16:17:12 +00001444 }
1445
1446 if (ha.dns_wc_tail.nelts) {
1447
1448 ngx_qsort(ha.dns_wc_tail.elts, (size_t) ha.dns_wc_tail.nelts,
1449 sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);
1450
1451 hash.hash = NULL;
1452 hash.temp_pool = ha.temp_pool;
1453
1454 if (ngx_hash_wildcard_init(&hash, ha.dns_wc_tail.elts,
1455 ha.dns_wc_tail.nelts)
1456 != NGX_OK)
1457 {
1458 goto failed;
1459 }
1460
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001461 addr->wc_tail = (ngx_hash_wildcard_t *) hash.hash;
Igor Sysoeva8833612009-02-18 16:17:12 +00001462 }
1463
1464 ngx_destroy_pool(ha.temp_pool);
1465
1466#if (NGX_PCRE)
1467
1468 if (regex == 0) {
1469 return NGX_OK;
1470 }
1471
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001472 addr->nregex = regex;
1473 addr->regex = ngx_palloc(cf->pool, regex * sizeof(ngx_http_server_name_t));
1474 if (addr->regex == NULL) {
Igor Sysoeva8833612009-02-18 16:17:12 +00001475 return NGX_ERROR;
1476 }
1477
Igor Sysoev2a634f52009-10-21 16:27:48 +00001478 i = 0;
1479
1480 for (s = 0; s < addr->servers.nelts; s++) {
1481
1482 name = cscfp[s]->server_names.elts;
1483
1484 for (n = 0; n < cscfp[s]->server_names.nelts; n++) {
1485 if (name[n].regex) {
1486 addr->regex[i++] = name[n];
1487 }
Igor Sysoeva8833612009-02-18 16:17:12 +00001488 }
1489 }
1490
1491#endif
1492
1493 return NGX_OK;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001494
1495failed:
1496
1497 ngx_destroy_pool(ha.temp_pool);
1498
1499 return NGX_ERROR;
1500}
1501
1502
1503static ngx_int_t
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001504ngx_http_cmp_conf_addrs(const void *one, const void *two)
Igor Sysoev305a9d82005-12-26 17:07:48 +00001505{
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001506 ngx_http_conf_addr_t *first, *second;
Igor Sysoev305a9d82005-12-26 17:07:48 +00001507
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001508 first = (ngx_http_conf_addr_t *) one;
1509 second = (ngx_http_conf_addr_t *) two;
Igor Sysoev305a9d82005-12-26 17:07:48 +00001510
Igor Sysoevd2d09312009-10-21 08:48:04 +00001511 if (first->opt.wildcard) {
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001512 /* a wildcard address must be the last resort, shift it to the end */
Igor Sysoev305a9d82005-12-26 17:07:48 +00001513 return 1;
1514 }
1515
Igor Sysoevd2d09312009-10-21 08:48:04 +00001516 if (first->opt.bind && !second->opt.bind) {
Igor Sysoev305a9d82005-12-26 17:07:48 +00001517 /* shift explicit bind()ed addresses to the start */
1518 return -1;
1519 }
1520
Igor Sysoevd2d09312009-10-21 08:48:04 +00001521 if (!first->opt.bind && second->opt.bind) {
Igor Sysoev305a9d82005-12-26 17:07:48 +00001522 /* shift explicit bind()ed addresses to the start */
1523 return 1;
1524 }
1525
1526 /* do not sort by default */
1527
1528 return 0;
1529}
1530
1531
1532static int ngx_libc_cdecl
1533ngx_http_cmp_dns_wildcards(const void *one, const void *two)
1534{
1535 ngx_hash_key_t *first, *second;
1536
1537 first = (ngx_hash_key_t *) one;
1538 second = (ngx_hash_key_t *) two;
1539
Igor Sysoev96e36ef2009-09-12 09:28:37 +00001540 return ngx_dns_strcmp(first->key.data, second->key.data);
Igor Sysoev305a9d82005-12-26 17:07:48 +00001541}
Igor Sysoev6d14e652008-05-22 11:07:08 +00001542
1543
1544static ngx_int_t
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001545ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port)
Igor Sysoev6d14e652008-05-22 11:07:08 +00001546{
Igor Sysoev1966aed2009-02-24 07:29:55 +00001547 ngx_uint_t i, last, bind_wildcard;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001548 ngx_listening_t *ls;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001549 ngx_http_port_t *hport;
1550 ngx_http_conf_addr_t *addr;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001551
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001552 addr = port->addrs.elts;
1553 last = port->addrs.nelts;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001554
1555 /*
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001556 * If there is a binding to an "*:port" then we need to bind() to
1557 * the "*:port" only and ignore other implicit bindings. The bindings
1558 * have been already sorted: explicit bindings are on the start, then
1559 * implicit bindings go, and wildcard binding is in the end.
Igor Sysoev6d14e652008-05-22 11:07:08 +00001560 */
1561
Igor Sysoevd2d09312009-10-21 08:48:04 +00001562 if (addr[last - 1].opt.wildcard) {
1563 addr[last - 1].opt.bind = 1;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001564 bind_wildcard = 1;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001565
1566 } else {
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001567 bind_wildcard = 0;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001568 }
1569
Igor Sysoev1966aed2009-02-24 07:29:55 +00001570 i = 0;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001571
Igor Sysoev1966aed2009-02-24 07:29:55 +00001572 while (i < last) {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001573
Igor Sysoevd2d09312009-10-21 08:48:04 +00001574 if (bind_wildcard && !addr[i].opt.bind) {
Igor Sysoev1966aed2009-02-24 07:29:55 +00001575 i++;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001576 continue;
1577 }
1578
Igor Sysoev1966aed2009-02-24 07:29:55 +00001579 ls = ngx_http_add_listening(cf, &addr[i]);
Igor Sysoev6d14e652008-05-22 11:07:08 +00001580 if (ls == NULL) {
1581 return NGX_ERROR;
1582 }
1583
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001584 hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t));
1585 if (hport == NULL) {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001586 return NGX_ERROR;
1587 }
1588
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001589 ls->servers = hport;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001590
Igor Sysoev1966aed2009-02-24 07:29:55 +00001591 if (i == last - 1) {
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001592 hport->naddrs = last;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001593
1594 } else {
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001595 hport->naddrs = 1;
Igor Sysoev1966aed2009-02-24 07:29:55 +00001596 i = 0;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001597 }
1598
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001599 switch (ls->sockaddr->sa_family) {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001600
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001601#if (NGX_HAVE_INET6)
1602 case AF_INET6:
1603 if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001604 return NGX_ERROR;
1605 }
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001606 break;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001607#endif
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001608 default: /* AF_INET */
1609 if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) {
1610 return NGX_ERROR;
1611 }
1612 break;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001613 }
1614
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001615 addr++;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001616 last--;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001617 }
1618
1619 return NGX_OK;
1620}
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00001621
1622
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001623static ngx_listening_t *
1624ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)
1625{
1626 ngx_listening_t *ls;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001627 ngx_http_core_loc_conf_t *clcf;
1628 ngx_http_core_srv_conf_t *cscf;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001629
Igor Sysoevf2694cb2009-10-21 16:47:44 +00001630 ls = ngx_create_listening(cf, addr->opt.sockaddr, addr->opt.socklen);
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001631 if (ls == NULL) {
1632 return NULL;
1633 }
1634
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001635 ls->addr_ntop = 1;
1636
1637 ls->handler = ngx_http_init_connection;
1638
Igor Sysoevcd8b43c2009-10-21 16:52:10 +00001639 cscf = addr->default_server;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001640 ls->pool_size = cscf->connection_pool_size;
1641 ls->post_accept_timeout = cscf->client_header_timeout;
1642
1643 clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];
1644
Igor Sysoev0cd76ea2009-04-30 13:53:42 +00001645 ls->logp = clcf->error_log;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001646 ls->log.data = &ls->addr_text;
1647 ls->log.handler = ngx_accept_log_error;
1648
1649#if (NGX_WIN32)
1650 {
1651 ngx_iocp_conf_t *iocpcf;
1652
1653 iocpcf = ngx_event_get_conf(cf->cycle->conf_ctx, ngx_iocp_module);
1654 if (iocpcf->acceptex_read) {
1655 ls->post_accept_buffer_size = cscf->client_header_buffer_size;
1656 }
1657 }
1658#endif
1659
Igor Sysoev79d630a2009-10-21 08:19:46 +00001660 ls->backlog = addr->opt.backlog;
1661 ls->rcvbuf = addr->opt.rcvbuf;
1662 ls->sndbuf = addr->opt.sndbuf;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001663
1664#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
Igor Sysoev79d630a2009-10-21 08:19:46 +00001665 ls->accept_filter = addr->opt.accept_filter;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001666#endif
1667
1668#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
Igor Sysoev79d630a2009-10-21 08:19:46 +00001669 ls->deferred_accept = addr->opt.deferred_accept;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001670#endif
1671
Igor Sysoev6d94b512009-03-13 14:20:34 +00001672#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
Igor Sysoev79d630a2009-10-21 08:19:46 +00001673 ls->ipv6only = addr->opt.ipv6only;
Igor Sysoev6d94b512009-03-13 14:20:34 +00001674#endif
1675
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001676 return ls;
1677}
1678
1679
1680static ngx_int_t
1681ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport,
1682 ngx_http_conf_addr_t *addr)
1683{
1684 ngx_uint_t i;
1685 ngx_http_in_addr_t *addrs;
1686 struct sockaddr_in *sin;
1687 ngx_http_virtual_names_t *vn;
1688
1689 hport->addrs = ngx_pcalloc(cf->pool,
1690 hport->naddrs * sizeof(ngx_http_in_addr_t));
1691 if (hport->addrs == NULL) {
1692 return NGX_ERROR;
1693 }
1694
1695 addrs = hport->addrs;
1696
1697 for (i = 0; i < hport->naddrs; i++) {
1698
Igor Sysoevf2694cb2009-10-21 16:47:44 +00001699 sin = (struct sockaddr_in *) addr[i].opt.sockaddr;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001700 addrs[i].addr = sin->sin_addr.s_addr;
Igor Sysoevcd8b43c2009-10-21 16:52:10 +00001701 addrs[i].conf.default_server = addr[i].default_server;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001702#if (NGX_HTTP_SSL)
Igor Sysoevd2d09312009-10-21 08:48:04 +00001703 addrs[i].conf.ssl = addr[i].opt.ssl;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001704#endif
1705
1706 if (addr[i].hash.buckets == NULL
1707 && (addr[i].wc_head == NULL
1708 || addr[i].wc_head->hash.buckets == NULL)
Igor Sysoevfb3be732009-03-19 15:46:27 +00001709 && (addr[i].wc_tail == NULL
Igor Sysoev7b5edd82009-03-19 16:07:40 +00001710 || addr[i].wc_tail->hash.buckets == NULL)
1711#if (NGX_PCRE)
1712 && addr[i].nregex == 0
1713#endif
1714 )
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001715 {
1716 continue;
1717 }
1718
1719 vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
1720 if (vn == NULL) {
1721 return NGX_ERROR;
1722 }
1723
Igor Sysoeve4694392009-04-09 13:56:16 +00001724 addrs[i].conf.virtual_names = vn;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001725
1726 vn->names.hash = addr[i].hash;
1727 vn->names.wc_head = addr[i].wc_head;
1728 vn->names.wc_tail = addr[i].wc_tail;
1729#if (NGX_PCRE)
1730 vn->nregex = addr[i].nregex;
1731 vn->regex = addr[i].regex;
1732#endif
1733 }
1734
1735 return NGX_OK;
1736}
1737
1738
1739#if (NGX_HAVE_INET6)
1740
1741static ngx_int_t
1742ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport,
1743 ngx_http_conf_addr_t *addr)
1744{
1745 ngx_uint_t i;
1746 ngx_http_in6_addr_t *addrs6;
1747 struct sockaddr_in6 *sin6;
1748 ngx_http_virtual_names_t *vn;
1749
1750 hport->addrs = ngx_pcalloc(cf->pool,
1751 hport->naddrs * sizeof(ngx_http_in6_addr_t));
1752 if (hport->addrs == NULL) {
1753 return NGX_ERROR;
1754 }
1755
1756 addrs6 = hport->addrs;
1757
1758 for (i = 0; i < hport->naddrs; i++) {
1759
Igor Sysoevf2694cb2009-10-21 16:47:44 +00001760 sin6 = (struct sockaddr_in6 *) addr[i].opt.sockaddr;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001761 addrs6[i].addr6 = sin6->sin6_addr;
Igor Sysoevcd8b43c2009-10-21 16:52:10 +00001762 addrs6[i].conf.default_server = addr[i].default_server;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001763#if (NGX_HTTP_SSL)
Igor Sysoevd2d09312009-10-21 08:48:04 +00001764 addrs6[i].conf.ssl = addr[i].opt.ssl;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001765#endif
1766
1767 if (addr[i].hash.buckets == NULL
1768 && (addr[i].wc_head == NULL
1769 || addr[i].wc_head->hash.buckets == NULL)
1770 && (addr[i].wc_head == NULL
1771 || addr[i].wc_head->hash.buckets == NULL))
1772 {
1773 continue;
1774 }
1775
1776 vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
1777 if (vn == NULL) {
1778 return NGX_ERROR;
1779 }
1780
Igor Sysoeve4694392009-04-09 13:56:16 +00001781 addrs6[i].conf.virtual_names = vn;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001782
1783 vn->names.hash = addr[i].hash;
1784 vn->names.wc_head = addr[i].wc_head;
1785 vn->names.wc_tail = addr[i].wc_tail;
1786#if (NGX_PCRE)
1787 vn->nregex = addr[i].nregex;
1788 vn->regex = addr[i].regex;
1789#endif
1790 }
1791
1792 return NGX_OK;
1793}
1794
1795#endif
1796
1797
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00001798char *
1799ngx_http_types_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1800{
1801 char *p = conf;
1802
1803 ngx_array_t **types;
1804 ngx_str_t *value, *default_type;
1805 ngx_uint_t i, n, hash;
1806 ngx_hash_key_t *type;
1807
1808 types = (ngx_array_t **) (p + cmd->offset);
1809
1810 default_type = cmd->post;
1811
1812 if (*types == NULL) {
1813 *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t));
1814 if (*types == NULL) {
1815 return NGX_CONF_ERROR;
1816 }
1817
1818 if (default_type) {
1819 type = ngx_array_push(*types);
1820 if (type == NULL) {
1821 return NGX_CONF_ERROR;
1822 }
1823
1824 type->key = *default_type;
1825 type->key_hash = ngx_hash_key(default_type->data,
1826 default_type->len);
1827 type->value = (void *) 4;
1828 }
1829 }
1830
1831 value = cf->args->elts;
1832
1833 for (i = 1; i < cf->args->nelts; i++) {
1834
1835 hash = ngx_hash_strlow(value[i].data, value[i].data, value[i].len);
1836 value[i].data[value[i].len] = '\0';
1837
1838 type = (*types)->elts;
1839 for (n = 0; n < (*types)->nelts; n++) {
1840
1841 if (ngx_strcmp(value[i].data, type[n].key.data) == 0) {
1842 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1843 "duplicate MIME type \"%V\"", &value[i]);
1844 continue;
1845 }
1846 }
1847
1848 type = ngx_array_push(*types);
1849 if (type == NULL) {
1850 return NGX_CONF_ERROR;
1851 }
1852
1853 type->key = value[i];
1854 type->key_hash = hash;
1855 type->value = (void *) 4;
1856 }
1857
1858 return NGX_CONF_OK;
1859}
1860
1861
1862char *
1863ngx_http_merge_types(ngx_conf_t *cf, ngx_array_t *keys, ngx_hash_t *types_hash,
Igor Sysoevc71e3d82008-08-13 16:25:48 +00001864 ngx_array_t *prev_keys, ngx_hash_t *prev_types_hash,
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00001865 ngx_str_t *default_types)
1866{
1867 ngx_hash_init_t hash;
1868
Igor Sysoevc71e3d82008-08-13 16:25:48 +00001869 if (keys) {
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00001870
Igor Sysoevc71e3d82008-08-13 16:25:48 +00001871 hash.hash = types_hash;
1872 hash.key = NULL;
1873 hash.max_size = 2048;
1874 hash.bucket_size = 64;
1875 hash.name = "test_types_hash";
1876 hash.pool = cf->pool;
1877 hash.temp_pool = NULL;
1878
1879 if (ngx_hash_init(&hash, keys->elts, keys->nelts) != NGX_OK) {
1880 return NGX_CONF_ERROR;
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00001881 }
1882
Igor Sysoevc71e3d82008-08-13 16:25:48 +00001883 return NGX_CONF_OK;
1884 }
1885
1886 if (prev_types_hash->buckets == NULL) {
1887
1888 if (prev_keys == NULL) {
1889
Igor Sysoev0c16f732008-09-01 14:05:20 +00001890 if (ngx_http_set_default_types(cf, &prev_keys, default_types)
Igor Sysoevc71e3d82008-08-13 16:25:48 +00001891 != NGX_OK)
1892 {
Igor Sysoev0c16f732008-09-01 14:05:20 +00001893 return NGX_CONF_ERROR;
1894 }
Igor Sysoevc71e3d82008-08-13 16:25:48 +00001895 }
1896
1897 hash.hash = prev_types_hash;
1898 hash.key = NULL;
1899 hash.max_size = 2048;
1900 hash.bucket_size = 64;
1901 hash.name = "test_types_hash";
1902 hash.pool = cf->pool;
1903 hash.temp_pool = NULL;
1904
1905 if (ngx_hash_init(&hash, prev_keys->elts, prev_keys->nelts) != NGX_OK) {
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00001906 return NGX_CONF_ERROR;
1907 }
1908 }
1909
Igor Sysoevc71e3d82008-08-13 16:25:48 +00001910 *types_hash = *prev_types_hash;
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00001911
1912 return NGX_CONF_OK;
1913
1914}
1915
1916
Igor Sysoevc71e3d82008-08-13 16:25:48 +00001917ngx_int_t
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00001918ngx_http_set_default_types(ngx_conf_t *cf, ngx_array_t **types,
1919 ngx_str_t *default_type)
1920{
1921 ngx_hash_key_t *type;
1922
1923 *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t));
1924 if (*types == NULL) {
Igor Sysoevc71e3d82008-08-13 16:25:48 +00001925 return NGX_ERROR;
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00001926 }
1927
1928 while (default_type->len) {
1929
1930 type = ngx_array_push(*types);
1931 if (type == NULL) {
Igor Sysoevc71e3d82008-08-13 16:25:48 +00001932 return NGX_ERROR;
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00001933 }
1934
1935 type->key = *default_type;
1936 type->key_hash = ngx_hash_key(default_type->data,
1937 default_type->len);
1938 type->value = (void *) 4;
1939
1940 default_type++;
1941 }
1942
Igor Sysoevc71e3d82008-08-13 16:25:48 +00001943 return NGX_OK;
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00001944}