blob: 5e487e75cbffbfa6d5ab26621c8c43cc587383c1 [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
20static ngx_int_t ngx_http_init_server_lists(ngx_conf_t *cf,
21 ngx_array_t *servers, ngx_array_t *in_ports);
Igor Sysoeva8833612009-02-18 16:17:12 +000022static ngx_int_t ngx_http_add_ports(ngx_conf_t *cf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +000023 ngx_http_core_srv_conf_t *cscf, ngx_array_t *ports,
Igor Sysoeva8833612009-02-18 16:17:12 +000024 ngx_http_listen_t *listen);
25static ngx_int_t ngx_http_add_addresses(ngx_conf_t *cf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +000026 ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port,
Igor Sysoeva8833612009-02-18 16:17:12 +000027 ngx_http_listen_t *listen);
Igor Sysoevc0edbcc2004-10-21 15:34:38 +000028static ngx_int_t ngx_http_add_address(ngx_conf_t *cf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +000029 ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port,
Igor Sysoev6d14e652008-05-22 11:07:08 +000030 ngx_http_listen_t *listen);
Igor Sysoevc0edbcc2004-10-21 15:34:38 +000031static ngx_int_t ngx_http_add_names(ngx_conf_t *cf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +000032 ngx_http_core_srv_conf_t *cscf, ngx_http_conf_addr_t *addr);
Igor Sysoev6d14e652008-05-22 11:07:08 +000033
Igor Sysoev74a5ddb2004-07-18 19:11:20 +000034static char *ngx_http_merge_locations(ngx_conf_t *cf,
Igor Sysoeve55988c2008-05-24 14:14:13 +000035 ngx_queue_t *locations, void **loc_conf, ngx_http_module_t *module,
Igor Sysoev8184d1b2005-03-04 14:06:57 +000036 ngx_uint_t ctx_index);
Igor Sysoeve55988c2008-05-24 14:14:13 +000037static ngx_int_t ngx_http_init_locations(ngx_conf_t *cf,
38 ngx_http_core_srv_conf_t *cscf, ngx_http_core_loc_conf_t *pclcf);
39static ngx_int_t ngx_http_init_static_location_trees(ngx_conf_t *cf,
40 ngx_http_core_loc_conf_t *pclcf);
41static ngx_int_t ngx_http_cmp_locations(const ngx_queue_t *one,
42 const ngx_queue_t *two);
43static ngx_int_t ngx_http_join_exact_locations(ngx_conf_t *cf,
44 ngx_queue_t *locations);
45static void ngx_http_create_locations_list(ngx_queue_t *locations,
46 ngx_queue_t *q);
47static ngx_http_location_tree_node_t *
48 ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations,
49 size_t prefix);
Igor Sysoev6d14e652008-05-22 11:07:08 +000050
51static ngx_int_t ngx_http_optimize_servers(ngx_conf_t *cf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +000052 ngx_http_core_main_conf_t *cmcf, ngx_array_t *ports);
Igor Sysoeva8833612009-02-18 16:17:12 +000053static ngx_int_t ngx_http_server_names(ngx_conf_t *cf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +000054 ngx_http_core_main_conf_t *cmcf, ngx_http_conf_addr_t *addr);
55static ngx_int_t ngx_http_cmp_conf_addrs(const void *one, const void *two);
Igor Sysoev305a9d82005-12-26 17:07:48 +000056static int ngx_libc_cdecl ngx_http_cmp_dns_wildcards(const void *one,
57 const void *two);
Igor Sysoev4e9393a2003-01-09 05:36:00 +000058
Igor Sysoev6d14e652008-05-22 11:07:08 +000059static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +000060 ngx_http_conf_port_t *port);
61static ngx_listening_t *ngx_http_add_listening(ngx_conf_t *cf,
62 ngx_http_conf_addr_t *addr);
63static ngx_int_t ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport,
64 ngx_http_conf_addr_t *addr);
65#if (NGX_HAVE_INET6)
66static ngx_int_t ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport,
67 ngx_http_conf_addr_t *addr);
68#endif
Igor Sysoev6d14e652008-05-22 11:07:08 +000069
Igor Sysoev305a9d82005-12-26 17:07:48 +000070ngx_uint_t ngx_http_max_module;
Igor Sysoeve89c4582003-12-19 08:15:11 +000071
Igor Sysoevb2620632003-01-10 06:09:20 +000072
Igor Sysoev2f657222004-06-16 15:32:11 +000073ngx_int_t (*ngx_http_top_header_filter) (ngx_http_request_t *r);
74ngx_int_t (*ngx_http_top_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
Igor Sysoev4e9393a2003-01-09 05:36:00 +000075
76
Igor Sysoev390abe02008-08-12 13:11:36 +000077ngx_str_t ngx_http_html_default_types[] = {
78 ngx_string("text/html"),
79 ngx_null_string
80};
81
82
Igor Sysoev4e9393a2003-01-09 05:36:00 +000083static ngx_command_t ngx_http_commands[] = {
84
Igor Sysoev8184d1b2005-03-04 14:06:57 +000085 { ngx_string("http"),
86 NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
87 ngx_http_block,
88 0,
89 0,
90 NULL },
Igor Sysoev4e9393a2003-01-09 05:36:00 +000091
Igor Sysoev8184d1b2005-03-04 14:06:57 +000092 ngx_null_command
Igor Sysoev4e9393a2003-01-09 05:36:00 +000093};
94
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +000095
Igor Sysoev43f13192004-04-12 16:38:09 +000096static ngx_core_module_t ngx_http_module_ctx = {
97 ngx_string("http"),
98 NULL,
99 NULL
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +0000100};
Igor Sysoev43f13192004-04-12 16:38:09 +0000101
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000102
103ngx_module_t ngx_http_module = {
Igor Sysoev899b44e2005-05-12 14:58:06 +0000104 NGX_MODULE_V1,
Igor Sysoev43f13192004-04-12 16:38:09 +0000105 &ngx_http_module_ctx, /* module context */
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000106 ngx_http_commands, /* module directives */
Igor Sysoev6253ca12003-05-27 12:18:54 +0000107 NGX_CORE_MODULE, /* module type */
Igor Sysoeve5733802005-09-08 14:36:09 +0000108 NULL, /* init master */
Igor Sysoeva7f7fa82003-07-11 04:50:59 +0000109 NULL, /* init module */
Igor Sysoeve5733802005-09-08 14:36:09 +0000110 NULL, /* init process */
111 NULL, /* init thread */
112 NULL, /* exit thread */
113 NULL, /* exit process */
114 NULL, /* exit master */
115 NGX_MODULE_V1_PADDING
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000116};
117
118
Igor Sysoev8184d1b2005-03-04 14:06:57 +0000119static char *
120ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000121{
Igor Sysoev2e6ba932004-09-09 15:40:48 +0000122 char *rv;
Igor Sysoev6d14e652008-05-22 11:07:08 +0000123 ngx_uint_t mi, m, s;
Igor Sysoev3b30a902003-12-25 20:26:58 +0000124 ngx_conf_t pcf;
Igor Sysoev87ac67f2008-05-22 09:57:47 +0000125 ngx_array_t in_ports;
Igor Sysoeva9830112003-05-19 16:39:14 +0000126 ngx_http_module_t *module;
Igor Sysoeva9830112003-05-19 16:39:14 +0000127 ngx_http_conf_ctx_t *ctx;
Igor Sysoeve55988c2008-05-24 14:14:13 +0000128 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev6d14e652008-05-22 11:07:08 +0000129 ngx_http_core_srv_conf_t **cscfp;
Igor Sysoev3b30a902003-12-25 20:26:58 +0000130 ngx_http_core_main_conf_t *cmcf;
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000131
Igor Sysoeva9830112003-05-19 16:39:14 +0000132 /* the main http context */
Igor Sysoevb1dfe472004-12-21 12:30:30 +0000133
Igor Sysoevc1571722005-03-19 12:38:37 +0000134 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
135 if (ctx == NULL) {
Igor Sysoev805d9db2005-02-03 19:33:37 +0000136 return NGX_CONF_ERROR;
137 }
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000138
Igor Sysoevbb4ec5c2003-05-16 15:27:48 +0000139 *(ngx_http_conf_ctx_t **) conf = ctx;
140
Igor Sysoev805d9db2005-02-03 19:33:37 +0000141
Igor Sysoeva9830112003-05-19 16:39:14 +0000142 /* count the number of the http modules and set up their indices */
143
Igor Sysoeve2a31542003-04-08 15:40:10 +0000144 ngx_http_max_module = 0;
Igor Sysoeva9830112003-05-19 16:39:14 +0000145 for (m = 0; ngx_modules[m]; m++) {
Igor Sysoev6253ca12003-05-27 12:18:54 +0000146 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000147 continue;
148 }
149
Igor Sysoev6253ca12003-05-27 12:18:54 +0000150 ngx_modules[m]->ctx_index = ngx_http_max_module++;
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000151 }
152
Igor Sysoevb1dfe472004-12-21 12:30:30 +0000153
Igor Sysoev805d9db2005-02-03 19:33:37 +0000154 /* the http main_conf context, it is the same in the all http contexts */
Igor Sysoevbb4ec5c2003-05-16 15:27:48 +0000155
Igor Sysoev805d9db2005-02-03 19:33:37 +0000156 ctx->main_conf = ngx_pcalloc(cf->pool,
157 sizeof(void *) * ngx_http_max_module);
158 if (ctx->main_conf == NULL) {
159 return NGX_CONF_ERROR;
160 }
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000161
Igor Sysoeva9830112003-05-19 16:39:14 +0000162
Igor Sysoev805d9db2005-02-03 19:33:37 +0000163 /*
164 * the http null srv_conf context, it is used to merge
165 * the server{}s' srv_conf's
166 */
167
168 ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
169 if (ctx->srv_conf == NULL) {
170 return NGX_CONF_ERROR;
171 }
172
173
174 /*
175 * the http null loc_conf context, it is used to merge
176 * the server{}s' loc_conf's
177 */
178
179 ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
180 if (ctx->loc_conf == NULL) {
181 return NGX_CONF_ERROR;
182 }
183
184
185 /*
186 * create the main_conf's, the null srv_conf's, and the null loc_conf's
187 * of the all http modules
188 */
Igor Sysoeva9830112003-05-19 16:39:14 +0000189
190 for (m = 0; ngx_modules[m]; m++) {
Igor Sysoev6253ca12003-05-27 12:18:54 +0000191 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000192 continue;
193 }
194
Igor Sysoev6253ca12003-05-27 12:18:54 +0000195 module = ngx_modules[m]->ctx;
196 mi = ngx_modules[m]->ctx_index;
Igor Sysoeva9830112003-05-19 16:39:14 +0000197
198 if (module->create_main_conf) {
Igor Sysoevc1571722005-03-19 12:38:37 +0000199 ctx->main_conf[mi] = module->create_main_conf(cf);
200 if (ctx->main_conf[mi] == NULL) {
Igor Sysoev805d9db2005-02-03 19:33:37 +0000201 return NGX_CONF_ERROR;
202 }
Igor Sysoeva9830112003-05-19 16:39:14 +0000203 }
204
205 if (module->create_srv_conf) {
Igor Sysoevc1571722005-03-19 12:38:37 +0000206 ctx->srv_conf[mi] = module->create_srv_conf(cf);
207 if (ctx->srv_conf[mi] == NULL) {
Igor Sysoev805d9db2005-02-03 19:33:37 +0000208 return NGX_CONF_ERROR;
209 }
Igor Sysoeva9830112003-05-19 16:39:14 +0000210 }
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000211
212 if (module->create_loc_conf) {
Igor Sysoevc1571722005-03-19 12:38:37 +0000213 ctx->loc_conf[mi] = module->create_loc_conf(cf);
214 if (ctx->loc_conf[mi] == NULL) {
Igor Sysoev805d9db2005-02-03 19:33:37 +0000215 return NGX_CONF_ERROR;
216 }
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000217 }
218 }
219
Igor Sysoev899b44e2005-05-12 14:58:06 +0000220 pcf = *cf;
221 cf->ctx = ctx;
222
223 for (m = 0; ngx_modules[m]; m++) {
224 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
225 continue;
226 }
227
228 module = ngx_modules[m]->ctx;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000229
230 if (module->preconfiguration) {
231 if (module->preconfiguration(cf) != NGX_OK) {
232 return NGX_CONF_ERROR;
233 }
234 }
235 }
Igor Sysoev805d9db2005-02-03 19:33:37 +0000236
Igor Sysoeva9830112003-05-19 16:39:14 +0000237 /* parse inside the http{} block */
238
Igor Sysoev6253ca12003-05-27 12:18:54 +0000239 cf->module_type = NGX_HTTP_MODULE;
Igor Sysoev79a80482003-05-14 17:13:13 +0000240 cf->cmd_type = NGX_HTTP_MAIN_CONF;
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000241 rv = ngx_conf_parse(cf, NULL);
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000242
Igor Sysoev74e95c22003-11-09 20:03:38 +0000243 if (rv != NGX_CONF_OK) {
Igor Sysoeve55988c2008-05-24 14:14:13 +0000244 goto failed;
Igor Sysoev74e95c22003-11-09 20:03:38 +0000245 }
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000246
Igor Sysoev74e95c22003-11-09 20:03:38 +0000247 /*
248 * init http{} main_conf's, merge the server{}s' srv_conf's
249 * and its location{}s' loc_conf's
250 */
Igor Sysoeva19a85e2003-01-28 15:56:37 +0000251
Igor Sysoev6253ca12003-05-27 12:18:54 +0000252 cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
Igor Sysoevaa3436c2003-05-30 14:27:59 +0000253 cscfp = cmcf->servers.elts;
Igor Sysoeva9830112003-05-19 16:39:14 +0000254
255 for (m = 0; ngx_modules[m]; m++) {
Igor Sysoev6253ca12003-05-27 12:18:54 +0000256 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
Igor Sysoeva9830112003-05-19 16:39:14 +0000257 continue;
258 }
259
Igor Sysoevaa3436c2003-05-30 14:27:59 +0000260 module = ngx_modules[m]->ctx;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000261 mi = ngx_modules[m]->ctx_index;
Igor Sysoeva9830112003-05-19 16:39:14 +0000262
263 /* init http{} main_conf's */
264
265 if (module->init_main_conf) {
Igor Sysoev890fc962003-07-20 21:15:59 +0000266 rv = module->init_main_conf(cf, ctx->main_conf[mi]);
Igor Sysoeva9830112003-05-19 16:39:14 +0000267 if (rv != NGX_CONF_OK) {
Igor Sysoeve55988c2008-05-24 14:14:13 +0000268 goto failed;
Igor Sysoeva9830112003-05-19 16:39:14 +0000269 }
270 }
271
272 for (s = 0; s < cmcf->servers.nelts; s++) {
273
274 /* merge the server{}s' srv_conf's */
275
276 if (module->merge_srv_conf) {
Igor Sysoeve55988c2008-05-24 14:14:13 +0000277 rv = module->merge_srv_conf(cf, ctx->srv_conf[mi],
Igor Sysoeva9830112003-05-19 16:39:14 +0000278 cscfp[s]->ctx->srv_conf[mi]);
279 if (rv != NGX_CONF_OK) {
Igor Sysoeve55988c2008-05-24 14:14:13 +0000280 goto failed;
Igor Sysoeva9830112003-05-19 16:39:14 +0000281 }
282 }
283
284 if (module->merge_loc_conf) {
285
286 /* merge the server{}'s loc_conf */
287
Igor Sysoeve55988c2008-05-24 14:14:13 +0000288 rv = module->merge_loc_conf(cf, ctx->loc_conf[mi],
Igor Sysoeva9830112003-05-19 16:39:14 +0000289 cscfp[s]->ctx->loc_conf[mi]);
290 if (rv != NGX_CONF_OK) {
Igor Sysoeve55988c2008-05-24 14:14:13 +0000291 goto failed;
Igor Sysoeva9830112003-05-19 16:39:14 +0000292 }
293
294 /* merge the locations{}' loc_conf's */
295
Igor Sysoeve55988c2008-05-24 14:14:13 +0000296 clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
297
298 rv = ngx_http_merge_locations(cf, clcf->locations,
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000299 cscfp[s]->ctx->loc_conf,
300 module, mi);
301 if (rv != NGX_CONF_OK) {
Igor Sysoeve55988c2008-05-24 14:14:13 +0000302 goto failed;
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000303 }
Igor Sysoeva9830112003-05-19 16:39:14 +0000304 }
Igor Sysoeva19a85e2003-01-28 15:56:37 +0000305 }
306 }
Igor Sysoeva9830112003-05-19 16:39:14 +0000307
Igor Sysoev805d9db2005-02-03 19:33:37 +0000308
Igor Sysoeve55988c2008-05-24 14:14:13 +0000309 /* create location trees */
310
311 for (s = 0; s < cmcf->servers.nelts; s++) {
312
313 clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
314
315 if (ngx_http_init_locations(cf, cscfp[s], clcf) != NGX_OK) {
316 return NGX_CONF_ERROR;
317 }
318
319 if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
320 return NGX_CONF_ERROR;
321 }
322 }
323
324
Igor Sysoev87ac67f2008-05-22 09:57:47 +0000325 if (ngx_http_init_phases(cf, cmcf) != NGX_OK) {
Igor Sysoev805d9db2005-02-03 19:33:37 +0000326 return NGX_CONF_ERROR;
327 }
328
Igor Sysoev87ac67f2008-05-22 09:57:47 +0000329 if (ngx_http_init_headers_in_hash(cf, cmcf) != NGX_OK) {
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000330 return NGX_CONF_ERROR;
331 }
332
Igor Sysoev899b44e2005-05-12 14:58:06 +0000333
334 for (m = 0; ngx_modules[m]; m++) {
335 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
336 continue;
337 }
338
339 module = ngx_modules[m]->ctx;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000340
341 if (module->postconfiguration) {
342 if (module->postconfiguration(cf) != NGX_OK) {
343 return NGX_CONF_ERROR;
344 }
345 }
346 }
347
Igor Sysoev09c684b2005-11-09 17:25:55 +0000348 if (ngx_http_variables_init_vars(cf) != NGX_OK) {
349 return NGX_CONF_ERROR;
350 }
Igor Sysoev899b44e2005-05-12 14:58:06 +0000351
352 /*
353 * http{}'s cf->ctx was needed while the configuration merging
354 * and in postconfiguration process
355 */
356
357 *cf = pcf;
358
Igor Sysoev02f742b2005-04-08 15:18:55 +0000359
Igor Sysoev87ac67f2008-05-22 09:57:47 +0000360 if (ngx_http_init_phase_handlers(cf, cmcf) != NGX_OK) {
Igor Sysoevda173ab2006-08-30 10:39:17 +0000361 return NGX_CONF_ERROR;
362 }
363
Igor Sysoevda173ab2006-08-30 10:39:17 +0000364
Igor Sysoev5c8c52f2004-01-23 09:26:18 +0000365 /*
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000366 * create the lists of ports, addresses and server names
Igor Sysoev6d14e652008-05-22 11:07:08 +0000367 * to find quickly the server core module configuration at run-time
Igor Sysoev5c8c52f2004-01-23 09:26:18 +0000368 */
Igor Sysoeva19a85e2003-01-28 15:56:37 +0000369
Igor Sysoev6d14e652008-05-22 11:07:08 +0000370 if (ngx_http_init_server_lists(cf, &cmcf->servers, &in_ports) != NGX_OK) {
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000371 return NGX_CONF_ERROR;
372 }
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000373
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000374
375 /* optimize the lists of ports, addresses and server names */
Igor Sysoeva19a85e2003-01-28 15:56:37 +0000376
Igor Sysoev6d14e652008-05-22 11:07:08 +0000377 if (ngx_http_optimize_servers(cf, cmcf, &in_ports) != NGX_OK) {
378 return NGX_CONF_ERROR;
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000379 }
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000380
381 return NGX_CONF_OK;
Igor Sysoeve55988c2008-05-24 14:14:13 +0000382
383failed:
384
385 *cf = pcf;
386
387 return rv;
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000388}
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000389
390
Igor Sysoev87ac67f2008-05-22 09:57:47 +0000391static ngx_int_t
392ngx_http_init_phases(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
393{
394 if (ngx_array_init(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers,
395 cf->pool, 1, sizeof(ngx_http_handler_pt))
396 != NGX_OK)
397 {
398 return NGX_ERROR;
399 }
400
401 if (ngx_array_init(&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers,
402 cf->pool, 1, sizeof(ngx_http_handler_pt))
403 != NGX_OK)
404 {
405 return NGX_ERROR;
406 }
407
408 if (ngx_array_init(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers,
409 cf->pool, 1, sizeof(ngx_http_handler_pt))
410 != NGX_OK)
411 {
412 return NGX_ERROR;
413 }
414
415 if (ngx_array_init(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers,
416 cf->pool, 1, sizeof(ngx_http_handler_pt))
417 != NGX_OK)
418 {
419 return NGX_ERROR;
420 }
421
422 if (ngx_array_init(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers,
423 cf->pool, 2, sizeof(ngx_http_handler_pt))
424 != NGX_OK)
425 {
426 return NGX_ERROR;
427 }
428
429 if (ngx_array_init(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers,
430 cf->pool, 4, sizeof(ngx_http_handler_pt))
431 != NGX_OK)
432 {
433 return NGX_ERROR;
434 }
435
436 if (ngx_array_init(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers,
437 cf->pool, 1, sizeof(ngx_http_handler_pt))
438 != NGX_OK)
439 {
440 return NGX_ERROR;
441 }
442
443 return NGX_OK;
444}
445
446
447static ngx_int_t
448ngx_http_init_headers_in_hash(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
449{
450 ngx_array_t headers_in;
451 ngx_hash_key_t *hk;
452 ngx_hash_init_t hash;
453 ngx_http_header_t *header;
454
455 if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t))
456 != NGX_OK)
457 {
458 return NGX_ERROR;
459 }
460
461 for (header = ngx_http_headers_in; header->name.len; header++) {
462 hk = ngx_array_push(&headers_in);
463 if (hk == NULL) {
464 return NGX_ERROR;
465 }
466
467 hk->key = header->name;
468 hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len);
469 hk->value = header;
470 }
471
472 hash.hash = &cmcf->headers_in_hash;
473 hash.key = ngx_hash_key_lc;
474 hash.max_size = 512;
475 hash.bucket_size = ngx_align(64, ngx_cacheline_size);
476 hash.name = "headers_in_hash";
477 hash.pool = cf->pool;
478 hash.temp_pool = NULL;
479
480 if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) {
481 return NGX_ERROR;
482 }
483
484 return NGX_OK;
485}
486
487
488static ngx_int_t
489ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
490{
491 ngx_int_t j;
492 ngx_uint_t i, n;
493 ngx_uint_t find_config_index, use_rewrite, use_access;
494 ngx_http_handler_pt *h;
495 ngx_http_phase_handler_t *ph;
496 ngx_http_phase_handler_pt checker;
497
498 cmcf->phase_engine.server_rewrite_index = (ngx_uint_t) -1;
499 cmcf->phase_engine.location_rewrite_index = (ngx_uint_t) -1;
500 find_config_index = 0;
501 use_rewrite = cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers.nelts ? 1 : 0;
502 use_access = cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers.nelts ? 1 : 0;
503
Igor Sysoevd8e3d0b2008-12-15 10:56:48 +0000504 n = use_rewrite + use_access + cmcf->try_files + 1 /* find config phase */;
Igor Sysoev87ac67f2008-05-22 09:57:47 +0000505
506 for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) {
507 n += cmcf->phases[i].handlers.nelts;
508 }
509
510 ph = ngx_pcalloc(cf->pool,
511 n * sizeof(ngx_http_phase_handler_t) + sizeof(void *));
512 if (ph == NULL) {
513 return NGX_ERROR;
514 }
515
516 cmcf->phase_engine.handlers = ph;
517 n = 0;
518
519 for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) {
520 h = cmcf->phases[i].handlers.elts;
521
522 switch (i) {
523
524 case NGX_HTTP_SERVER_REWRITE_PHASE:
525 if (cmcf->phase_engine.server_rewrite_index == (ngx_uint_t) -1) {
526 cmcf->phase_engine.server_rewrite_index = n;
527 }
528 checker = ngx_http_core_generic_phase;
529
530 break;
531
532 case NGX_HTTP_FIND_CONFIG_PHASE:
533 find_config_index = n;
534
535 ph->checker = ngx_http_core_find_config_phase;
536 n++;
537 ph++;
538
539 continue;
540
541 case NGX_HTTP_REWRITE_PHASE:
542 if (cmcf->phase_engine.location_rewrite_index == (ngx_uint_t) -1) {
543 cmcf->phase_engine.location_rewrite_index = n;
544 }
545 checker = ngx_http_core_generic_phase;
546
547 break;
548
549 case NGX_HTTP_POST_REWRITE_PHASE:
550 if (use_rewrite) {
551 ph->checker = ngx_http_core_post_rewrite_phase;
552 ph->next = find_config_index;
553 n++;
554 ph++;
555 }
556
557 continue;
558
559 case NGX_HTTP_ACCESS_PHASE:
560 checker = ngx_http_core_access_phase;
561 n++;
562 break;
563
564 case NGX_HTTP_POST_ACCESS_PHASE:
565 if (use_access) {
566 ph->checker = ngx_http_core_post_access_phase;
567 ph->next = n;
568 ph++;
569 }
570
571 continue;
572
Igor Sysoevd8e3d0b2008-12-15 10:56:48 +0000573 case NGX_HTTP_TRY_FILES_PHASE:
574 if (cmcf->try_files) {
575 ph->checker = ngx_http_core_try_files_phase;
576 n++;
577 ph++;
578 }
579
580 continue;
581
Igor Sysoev87ac67f2008-05-22 09:57:47 +0000582 case NGX_HTTP_CONTENT_PHASE:
583 checker = ngx_http_core_content_phase;
584 break;
585
586 default:
587 checker = ngx_http_core_generic_phase;
588 }
589
590 n += cmcf->phases[i].handlers.nelts;
591
592 for (j = cmcf->phases[i].handlers.nelts - 1; j >=0; j--) {
593 ph->checker = checker;
594 ph->handler = h[j];
595 ph->next = n;
596 ph++;
597 }
598 }
599
600 return NGX_OK;
601}
602
603
Igor Sysoeve55988c2008-05-24 14:14:13 +0000604static char *
605ngx_http_merge_locations(ngx_conf_t *cf, ngx_queue_t *locations,
606 void **loc_conf, ngx_http_module_t *module, ngx_uint_t ctx_index)
607{
608 char *rv;
609 ngx_queue_t *q;
610 ngx_http_core_loc_conf_t *clcf;
611 ngx_http_location_queue_t *lq;
612
613 if (locations == NULL) {
614 return NGX_CONF_OK;
615 }
616
617 for (q = ngx_queue_head(locations);
618 q != ngx_queue_sentinel(locations);
619 q = ngx_queue_next(q))
620 {
621 lq = (ngx_http_location_queue_t *) q;
622
623 clcf = lq->exact ? lq->exact : lq->inclusive;
624
625 rv = module->merge_loc_conf(cf, loc_conf[ctx_index],
626 clcf->loc_conf[ctx_index]);
627 if (rv != NGX_CONF_OK) {
628 return rv;
629 }
630
631 rv = ngx_http_merge_locations(cf, clcf->locations, clcf->loc_conf,
632 module, ctx_index);
633 if (rv != NGX_CONF_OK) {
634 return rv;
635 }
636 }
637
638 return NGX_CONF_OK;
639}
640
641
642static ngx_int_t
643ngx_http_init_locations(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
644 ngx_http_core_loc_conf_t *pclcf)
645{
646 ngx_uint_t n;
647 ngx_queue_t *q, *locations, *named, tail;
648 ngx_http_core_loc_conf_t *clcf;
649 ngx_http_location_queue_t *lq;
650 ngx_http_core_loc_conf_t **clcfp;
651#if (NGX_PCRE)
652 ngx_uint_t r;
653 ngx_queue_t *regex;
654#endif
655
656 locations = pclcf->locations;
657
658 if (locations == NULL) {
659 return NGX_OK;
660 }
661
662 ngx_queue_sort(locations, ngx_http_cmp_locations);
663
664 named = NULL;
665 n = 0;
666#if (NGX_PCRE)
667 regex = NULL;
668 r = 0;
669#endif
670
671 for (q = ngx_queue_head(locations);
672 q != ngx_queue_sentinel(locations);
673 q = ngx_queue_next(q))
674 {
675 lq = (ngx_http_location_queue_t *) q;
676
677 clcf = lq->exact ? lq->exact : lq->inclusive;
678
679 if (ngx_http_init_locations(cf, NULL, clcf) != NGX_OK) {
680 return NGX_ERROR;
681 }
682
683#if (NGX_PCRE)
684
685 if (clcf->regex) {
686 r++;
687
688 if (regex == NULL) {
689 regex = q;
690 }
691
692 continue;
693 }
694
695#endif
696
697 if (clcf->named) {
698 n++;
699
700 if (named == NULL) {
701 named = q;
702 }
703
704 continue;
705 }
706
707 if (clcf->noname) {
708 break;
709 }
710 }
711
712 if (q != ngx_queue_sentinel(locations)) {
713 ngx_queue_split(locations, q, &tail);
714 }
715
716 if (named) {
717 clcfp = ngx_palloc(cf->pool,
718 (n + 1) * sizeof(ngx_http_core_loc_conf_t **));
719 if (clcfp == NULL) {
720 return NGX_ERROR;
721 }
722
723 cscf->named_locations = clcfp;
724
725 for (q = named;
726 q != ngx_queue_sentinel(locations);
727 q = ngx_queue_next(q))
728 {
729 lq = (ngx_http_location_queue_t *) q;
730
731 *(clcfp++) = lq->exact;
732 }
733
734 *clcfp = NULL;
735
736 ngx_queue_split(locations, named, &tail);
737 }
738
739#if (NGX_PCRE)
740
741 if (regex) {
742
743 clcfp = ngx_palloc(cf->pool,
744 (r + 1) * sizeof(ngx_http_core_loc_conf_t **));
745 if (clcfp == NULL) {
746 return NGX_ERROR;
747 }
748
749 pclcf->regex_locations = clcfp;
750
751 for (q = regex;
752 q != ngx_queue_sentinel(locations);
753 q = ngx_queue_next(q))
754 {
755 lq = (ngx_http_location_queue_t *) q;
756
757 *(clcfp++) = lq->exact;
758 }
759
760 *clcfp = NULL;
761
762 ngx_queue_split(locations, regex, &tail);
763 }
764
765#endif
766
767 return NGX_OK;
768}
769
770
771static ngx_int_t
772ngx_http_init_static_location_trees(ngx_conf_t *cf,
773 ngx_http_core_loc_conf_t *pclcf)
774{
775 ngx_queue_t *q, *locations;
776 ngx_http_core_loc_conf_t *clcf;
777 ngx_http_location_queue_t *lq;
778
779 locations = pclcf->locations;
780
781 if (locations == NULL) {
782 return NGX_OK;
783 }
784
785 if (ngx_queue_empty(locations)) {
786 return NGX_OK;
787 }
788
789 for (q = ngx_queue_head(locations);
790 q != ngx_queue_sentinel(locations);
791 q = ngx_queue_next(q))
792 {
793 lq = (ngx_http_location_queue_t *) q;
794
795 clcf = lq->exact ? lq->exact : lq->inclusive;
796
797 if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
798 return NGX_ERROR;
799 }
800 }
801
802 if (ngx_http_join_exact_locations(cf, locations) != NGX_OK) {
803 return NGX_ERROR;
804 }
805
806 ngx_http_create_locations_list(locations, ngx_queue_head(locations));
807
808 pclcf->static_locations = ngx_http_create_locations_tree(cf, locations, 0);
809 if (pclcf->static_locations == NULL) {
810 return NGX_ERROR;
811 }
812
813 return NGX_OK;
814}
815
816
817ngx_int_t
818ngx_http_add_location(ngx_conf_t *cf, ngx_queue_t **locations,
819 ngx_http_core_loc_conf_t *clcf)
820{
821 ngx_http_location_queue_t *lq;
822
823 if (*locations == NULL) {
824 *locations = ngx_palloc(cf->temp_pool,
825 sizeof(ngx_http_location_queue_t));
826 if (*locations == NULL) {
827 return NGX_ERROR;
828 }
829
830 ngx_queue_init(*locations);
831 }
832
833 lq = ngx_palloc(cf->temp_pool, sizeof(ngx_http_location_queue_t));
834 if (lq == NULL) {
835 return NGX_ERROR;
836 }
837
838 if (clcf->exact_match
839#if (NGX_PCRE)
840 || clcf->regex
841#endif
842 || clcf->named || clcf->noname)
843 {
844 lq->exact = clcf;
845 lq->inclusive = NULL;
846
847 } else {
848 lq->exact = NULL;
849 lq->inclusive = clcf;
850 }
851
852 lq->name = &clcf->name;
853 lq->file_name = cf->conf_file->file.name.data;
854 lq->line = cf->conf_file->line;
855
856 ngx_queue_init(&lq->list);
857
858 ngx_queue_insert_tail(*locations, &lq->queue);
859
860 return NGX_OK;
861}
862
863
864static ngx_int_t
865ngx_http_cmp_locations(const ngx_queue_t *one, const ngx_queue_t *two)
866{
867 ngx_int_t rc;
868 ngx_http_core_loc_conf_t *first, *second;
869 ngx_http_location_queue_t *lq1, *lq2;
870
871 lq1 = (ngx_http_location_queue_t *) one;
872 lq2 = (ngx_http_location_queue_t *) two;
873
874 first = lq1->exact ? lq1->exact : lq1->inclusive;
875 second = lq2->exact ? lq2->exact : lq2->inclusive;
876
877 if (first->noname && !second->noname) {
878 /* shift no named locations to the end */
879 return 1;
880 }
881
882 if (!first->noname && second->noname) {
883 /* shift no named locations to the end */
884 return -1;
885 }
886
887 if (first->noname || second->noname) {
888 /* do not sort no named locations */
889 return 0;
890 }
891
892 if (first->named && !second->named) {
893 /* shift named locations to the end */
894 return 1;
895 }
896
897 if (!first->named && second->named) {
898 /* shift named locations to the end */
899 return -1;
900 }
901
902 if (first->named && second->named) {
903 return ngx_strcmp(first->name.data, second->name.data);
904 }
905
906#if (NGX_PCRE)
907
908 if (first->regex && !second->regex) {
909 /* shift the regex matches to the end */
910 return 1;
911 }
912
913 if (!first->regex && second->regex) {
914 /* shift the regex matches to the end */
915 return -1;
916 }
917
918 if (first->regex || second->regex) {
919 /* do not sort the regex matches */
920 return 0;
921 }
922
923#endif
924
925 rc = ngx_strcmp(first->name.data, second->name.data);
926
927 if (rc == 0 && !first->exact_match && second->exact_match) {
928 /* an exact match must be before the same inclusive one */
929 return 1;
930 }
931
932 return rc;
933}
934
935
936static ngx_int_t
937ngx_http_join_exact_locations(ngx_conf_t *cf, ngx_queue_t *locations)
938{
939 ngx_queue_t *q, *x;
940 ngx_http_location_queue_t *lq, *lx;
941
942 q = ngx_queue_head(locations);
943
944 while (q != ngx_queue_last(locations)) {
945
946 x = ngx_queue_next(q);
947
948 lq = (ngx_http_location_queue_t *) q;
949 lx = (ngx_http_location_queue_t *) x;
950
951 if (ngx_strcmp(lq->name->data, lx->name->data) == 0) {
952
953 if ((lq->exact && lx->exact) || (lq->inclusive && lx->inclusive)) {
954 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
955 "duplicate location \"%V\" in %s:%ui",
956 lx->name, lx->file_name, lx->line);
957
958 return NGX_ERROR;
959 }
960
961 lq->inclusive = lx->inclusive;
962
963 ngx_queue_remove(x);
964
965 continue;
966 }
967
968 q = ngx_queue_next(q);
969 }
970
971 return NGX_OK;
972}
973
974
975static void
976ngx_http_create_locations_list(ngx_queue_t *locations, ngx_queue_t *q)
977{
978 u_char *name;
979 size_t len;
980 ngx_queue_t *x, tail;
981 ngx_http_location_queue_t *lq, *lx;
982
983 if (q == ngx_queue_last(locations)) {
984 return;
985 }
986
987 lq = (ngx_http_location_queue_t *) q;
988
989 if (lq->inclusive == NULL) {
990 ngx_http_create_locations_list(locations, ngx_queue_next(q));
991 return;
992 }
993
994 len = lq->name->len;
995 name = lq->name->data;
996
997 for (x = ngx_queue_next(q);
998 x != ngx_queue_sentinel(locations);
999 x = ngx_queue_next(x))
1000 {
1001 lx = (ngx_http_location_queue_t *) x;
1002
1003 if (len > lx->name->len
1004 || (ngx_strncmp(name, lx->name->data, len) != 0))
1005 {
1006 break;
1007 }
1008 }
1009
1010 q = ngx_queue_next(q);
1011
1012 if (q == x) {
1013 ngx_http_create_locations_list(locations, x);
1014 return;
1015 }
1016
1017 ngx_queue_split(locations, q, &tail);
1018 ngx_queue_add(&lq->list, &tail);
1019
1020 if (x == ngx_queue_sentinel(locations)) {
1021 ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list));
1022 return;
1023 }
1024
1025 ngx_queue_split(&lq->list, x, &tail);
1026 ngx_queue_add(locations, &tail);
1027
1028 ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list));
1029
1030 ngx_http_create_locations_list(locations, x);
1031}
1032
1033
1034/*
1035 * to keep cache locality for left leaf nodes, allocate nodes in following
1036 * order: node, left subtree, right subtree, inclusive subtree
1037 */
1038
1039static ngx_http_location_tree_node_t *
1040ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations,
1041 size_t prefix)
1042{
1043 size_t len;
1044 ngx_queue_t *q, tail;
1045 ngx_http_location_queue_t *lq;
1046 ngx_http_location_tree_node_t *node;
1047
1048 q = ngx_queue_middle(locations);
1049
1050 lq = (ngx_http_location_queue_t *) q;
1051 len = lq->name->len - prefix;
1052
Igor Sysoev7f6b2ff2008-06-17 15:00:30 +00001053 node = ngx_palloc(cf->pool,
1054 offsetof(ngx_http_location_tree_node_t, name) + len);
Igor Sysoeve55988c2008-05-24 14:14:13 +00001055 if (node == NULL) {
1056 return NULL;
1057 }
1058
Igor Sysoev2d951bf2008-05-27 09:37:40 +00001059 node->left = NULL;
1060 node->right = NULL;
1061 node->tree = NULL;
Igor Sysoeve55988c2008-05-24 14:14:13 +00001062 node->exact = lq->exact;
1063 node->inclusive = lq->inclusive;
1064
1065 node->auto_redirect = (u_char) ((lq->exact && lq->exact->auto_redirect)
1066 || (lq->inclusive && lq->inclusive->auto_redirect));
1067
1068 node->len = (u_char) len;
1069 ngx_memcpy(node->name, &lq->name->data[prefix], len);
1070
1071 ngx_queue_split(locations, q, &tail);
1072
1073 if (ngx_queue_empty(locations)) {
1074 /*
1075 * ngx_queue_split() insures that if left part is empty,
1076 * then right one is empty too
1077 */
1078 goto inclusive;
1079 }
1080
1081 node->left = ngx_http_create_locations_tree(cf, locations, prefix);
1082 if (node->left == NULL) {
1083 return NULL;
1084 }
1085
1086 ngx_queue_remove(q);
1087
1088 if (ngx_queue_empty(&tail)) {
1089 goto inclusive;
1090 }
1091
1092 node->right = ngx_http_create_locations_tree(cf, &tail, prefix);
1093 if (node->right == NULL) {
1094 return NULL;
1095 }
1096
1097inclusive:
1098
1099 if (ngx_queue_empty(&lq->list)) {
1100 return node;
1101 }
1102
1103 node->tree = ngx_http_create_locations_tree(cf, &lq->list, prefix + len);
1104 if (node->tree == NULL) {
1105 return NULL;
1106 }
1107
1108 return node;
1109}
1110
1111
Igor Sysoev6d14e652008-05-22 11:07:08 +00001112static ngx_int_t
1113ngx_http_init_server_lists(ngx_conf_t *cf, ngx_array_t *servers,
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001114 ngx_array_t *ports)
Igor Sysoev6d14e652008-05-22 11:07:08 +00001115{
Igor Sysoeva8833612009-02-18 16:17:12 +00001116 ngx_uint_t s, i;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001117 ngx_http_listen_t *listen;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001118 ngx_http_core_srv_conf_t **cscfp;
1119
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001120 if (ngx_array_init(ports, cf->temp_pool, 2, sizeof(ngx_http_conf_port_t))
Igor Sysoev6d14e652008-05-22 11:07:08 +00001121 != NGX_OK)
1122 {
1123 return NGX_ERROR;
1124 }
1125
1126 /* "server" directives */
1127
1128 cscfp = servers->elts;
1129 for (s = 0; s < servers->nelts; s++) {
1130
1131 /* "listen" directives */
1132
1133 listen = cscfp[s]->listen.elts;
Igor Sysoeva8833612009-02-18 16:17:12 +00001134 for (i = 0; i < cscfp[s]->listen.nelts; i++) {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001135
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001136 if (ngx_http_add_ports(cf, cscfp[s], ports, &listen[i]) != NGX_OK) {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001137 return NGX_ERROR;
1138 }
Igor Sysoev6d14e652008-05-22 11:07:08 +00001139 }
1140 }
1141
1142 return NGX_OK;
1143}
1144
1145
Igor Sysoeva8833612009-02-18 16:17:12 +00001146static ngx_int_t
1147ngx_http_add_ports(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001148 ngx_array_t *ports, ngx_http_listen_t *listen)
Igor Sysoeva8833612009-02-18 16:17:12 +00001149{
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001150 in_port_t p;
Igor Sysoeva8833612009-02-18 16:17:12 +00001151 ngx_uint_t i;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001152 struct sockaddr *sa;
1153 struct sockaddr_in *sin;
1154 ngx_http_conf_port_t *port;
1155#if (NGX_HAVE_INET6)
1156 struct sockaddr_in6 *sin6;
1157#endif
Igor Sysoeva8833612009-02-18 16:17:12 +00001158
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001159 sa = (struct sockaddr *) &listen->sockaddr;
Igor Sysoeva8833612009-02-18 16:17:12 +00001160
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001161 switch (sa->sa_family) {
1162
1163#if (NGX_HAVE_INET6)
1164 case AF_INET6:
1165 sin6 = (struct sockaddr_in6 *) sa;
1166 p = sin6->sin6_port;
1167 break;
1168#endif
1169
1170 default: /* AF_INET */
1171 sin = (struct sockaddr_in *) sa;
1172 p = sin->sin_port;
1173 break;
1174 }
1175
1176 port = ports->elts;
1177 for (i = 0; i < ports->nelts; i++) {
1178
1179 if (p != port[i].port || sa->sa_family != port[i].family) {
Igor Sysoeva8833612009-02-18 16:17:12 +00001180 continue;
1181 }
1182
1183 /* a port is already in the in_port list */
1184
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001185 return ngx_http_add_addresses(cf, cscf, &port[i], listen);
Igor Sysoeva8833612009-02-18 16:17:12 +00001186 }
1187
1188 /* add a port to the in_port list */
1189
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001190 port = ngx_array_push(ports);
1191 if (port == NULL) {
Igor Sysoeva8833612009-02-18 16:17:12 +00001192 return NGX_ERROR;
1193 }
1194
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001195 port->family = sa->sa_family;
1196 port->port = p;
1197 port->addrs.elts = NULL;
Igor Sysoeva8833612009-02-18 16:17:12 +00001198
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001199 return ngx_http_add_address(cf, cscf, port, listen);
Igor Sysoeva8833612009-02-18 16:17:12 +00001200}
1201
1202
1203static ngx_int_t
1204ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001205 ngx_http_conf_port_t *port, ngx_http_listen_t *listen)
Igor Sysoeva8833612009-02-18 16:17:12 +00001206{
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001207 u_char *p;
1208 size_t len, off;
1209 ngx_uint_t i;
1210 struct sockaddr *sa;
1211 ngx_http_conf_addr_t *addr;
Igor Sysoeva8833612009-02-18 16:17:12 +00001212
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001213 /*
1214 * we can not compare whole sockaddr struct's as kernel
1215 * may fill some fields in inherited sockaddr struct's
1216 */
Igor Sysoeva8833612009-02-18 16:17:12 +00001217
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001218 sa = (struct sockaddr *) &listen->sockaddr;
Igor Sysoeva8833612009-02-18 16:17:12 +00001219
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001220 switch (sa->sa_family) {
1221
1222#if (NGX_HAVE_INET6)
1223 case AF_INET6:
1224 off = offsetof(struct sockaddr_in6, sin6_addr);
1225 len = 16;
1226 break;
1227#endif
1228
1229 default: /* AF_INET */
1230 off = offsetof(struct sockaddr_in, sin_addr);
1231 len = 4;
1232 break;
1233 }
1234
1235 p = listen->sockaddr + off;
1236
1237 addr = port->addrs.elts;
1238
1239 for (i = 0; i < port->addrs.nelts; i++) {
1240
1241 if (ngx_memcmp(p, (u_char *) addr[i].sockaddr + off, len) != 0) {
Igor Sysoeva8833612009-02-18 16:17:12 +00001242 continue;
1243 }
1244
1245 /* the address is already in the address list */
1246
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001247 if (ngx_http_add_names(cf, cscf, &addr[i]) != NGX_OK) {
Igor Sysoeva8833612009-02-18 16:17:12 +00001248 return NGX_ERROR;
1249 }
1250
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001251 /* check the duplicate "default" server for this address:port */
Igor Sysoeva8833612009-02-18 16:17:12 +00001252
1253 if (listen->conf.default_server) {
1254
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001255 if (addr[i].default_server) {
Igor Sysoeva8833612009-02-18 16:17:12 +00001256 ngx_log_error(NGX_LOG_ERR, cf->log, 0,
1257 "the duplicate default server in %s:%ui",
1258 listen->file_name, listen->line);
1259
1260 return NGX_ERROR;
1261 }
1262
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001263 addr[i].core_srv_conf = cscf;
1264 addr[i].default_server = 1;
Igor Sysoeva8833612009-02-18 16:17:12 +00001265#if (NGX_HTTP_SSL)
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001266 addr[i].ssl = listen->conf.ssl;
Igor Sysoeva8833612009-02-18 16:17:12 +00001267#endif
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001268 addr[i].listen_conf = &listen->conf;
Igor Sysoeva8833612009-02-18 16:17:12 +00001269 }
1270
1271 return NGX_OK;
1272 }
1273
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001274 /* add the address to the addresses list that bound to this port */
Igor Sysoeva8833612009-02-18 16:17:12 +00001275
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001276 return ngx_http_add_address(cf, cscf, port, listen);
Igor Sysoeva8833612009-02-18 16:17:12 +00001277}
1278
1279
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001280/*
1281 * add the server address, the server names and the server core module
1282 * configurations to the port (in_port)
1283 */
1284
Igor Sysoev8184d1b2005-03-04 14:06:57 +00001285static ngx_int_t
Igor Sysoev6d14e652008-05-22 11:07:08 +00001286ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001287 ngx_http_conf_port_t *port, ngx_http_listen_t *listen)
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001288{
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001289 ngx_http_conf_addr_t *addr;
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001290
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001291 if (port->addrs.elts == NULL) {
1292 if (ngx_array_init(&port->addrs, cf->temp_pool, 4,
1293 sizeof(ngx_http_conf_addr_t))
Igor Sysoev242d1de2007-08-12 09:00:56 +00001294 != NGX_OK)
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001295 {
1296 return NGX_ERROR;
1297 }
1298 }
1299
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001300 addr = ngx_array_push(&port->addrs);
1301 if (addr == NULL) {
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001302 return NGX_ERROR;
1303 }
1304
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001305 addr->sockaddr = (struct sockaddr *) &listen->sockaddr;
1306 addr->socklen = listen->socklen;
1307 addr->hash.buckets = NULL;
1308 addr->hash.size = 0;
1309 addr->wc_head = NULL;
1310 addr->wc_tail = NULL;
1311 addr->names.elts = NULL;
Igor Sysoev43c3bf42007-08-12 19:48:12 +00001312#if (NGX_PCRE)
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001313 addr->nregex = 0;
1314 addr->regex = NULL;
Igor Sysoev43c3bf42007-08-12 19:48:12 +00001315#endif
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001316 addr->core_srv_conf = cscf;
1317 addr->default_server = listen->conf.default_server;
1318 addr->bind = listen->conf.bind;
1319 addr->wildcard = listen->conf.wildcard;
Igor Sysoevf100c782008-09-01 14:19:01 +00001320#if (NGX_HTTP_SSL)
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001321 addr->ssl = listen->conf.ssl;
Igor Sysoevf100c782008-09-01 14:19:01 +00001322#endif
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001323 addr->listen_conf = &listen->conf;
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001324
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001325 return ngx_http_add_names(cf, cscf, addr);
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001326}
1327
1328
1329/*
1330 * add the server names and the server core module
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001331 * configurations to the address:port
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001332 */
1333
Igor Sysoev8184d1b2005-03-04 14:06:57 +00001334static ngx_int_t
Igor Sysoev6d14e652008-05-22 11:07:08 +00001335ngx_http_add_names(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001336 ngx_http_conf_addr_t *addr)
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001337{
Igor Sysoev777b0192008-08-04 10:07:00 +00001338 ngx_uint_t i;
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001339 ngx_http_server_name_t *server_names, *name;
1340
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001341 if (addr->names.elts == NULL) {
1342 if (ngx_array_init(&addr->names, cf->temp_pool, 4,
Igor Sysoev242d1de2007-08-12 09:00:56 +00001343 sizeof(ngx_http_server_name_t))
1344 != NGX_OK)
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001345 {
1346 return NGX_ERROR;
1347 }
1348 }
1349
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001350 server_names = cscf->server_names.elts;
Igor Sysoev43c3bf42007-08-12 19:48:12 +00001351
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001352 for (i = 0; i < cscf->server_names.nelts; i++) {
1353
Igor Sysoev777b0192008-08-04 10:07:00 +00001354 ngx_strlow(server_names[i].name.data, server_names[i].name.data,
1355 server_names[i].name.len);
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001356
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001357 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +00001358 "name: %V", &server_names[i].name);
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001359
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001360 name = ngx_array_push(&addr->names);
Igor Sysoevc1571722005-03-19 12:38:37 +00001361 if (name == NULL) {
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001362 return NGX_ERROR;
1363 }
1364
1365 *name = server_names[i];
1366 }
1367
1368 return NGX_OK;
1369}
1370
1371
Igor Sysoevde8ec1e2008-03-24 13:04:02 +00001372static ngx_int_t
Igor Sysoev6d14e652008-05-22 11:07:08 +00001373ngx_http_optimize_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001374 ngx_array_t *ports)
Igor Sysoev6d14e652008-05-22 11:07:08 +00001375{
Igor Sysoevb37316d2009-04-08 19:51:30 +00001376 ngx_uint_t s, p, a;
1377 ngx_http_conf_port_t *port;
1378 ngx_http_conf_addr_t *addr;
1379 ngx_http_server_name_t *name;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001380
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001381 port = ports->elts;
1382 for (p = 0; p < ports->nelts; p++) {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001383
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001384 ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts,
1385 sizeof(ngx_http_conf_addr_t), ngx_http_cmp_conf_addrs);
Igor Sysoev6d14e652008-05-22 11:07:08 +00001386
1387 /*
Igor Sysoeva8833612009-02-18 16:17:12 +00001388 * check whether all name-based servers have the same
1389 * configuraiton as a default server for given address:port
Igor Sysoev6d14e652008-05-22 11:07:08 +00001390 */
1391
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001392 addr = port[p].addrs.elts;
1393 for (a = 0; a < port[p].addrs.nelts; a++) {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001394
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001395 name = addr[a].names.elts;
1396 for (s = 0; s < addr[a].names.nelts; s++) {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001397
Igor Sysoev7b5edd82009-03-19 16:07:40 +00001398 if (addr[a].core_srv_conf == name[s].core_srv_conf
1399#if (NGX_PCRE)
1400 && name[s].captures == 0
1401#endif
1402 )
1403 {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001404 continue;
1405 }
Igor Sysoev6d14e652008-05-22 11:07:08 +00001406
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001407 if (ngx_http_server_names(cf, cmcf, &addr[a]) != NGX_OK) {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001408 return NGX_ERROR;
1409 }
1410
Igor Sysoeva8833612009-02-18 16:17:12 +00001411 break;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001412 }
Igor Sysoev6d14e652008-05-22 11:07:08 +00001413 }
1414
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001415 if (ngx_http_init_listening(cf, &port[p]) != NGX_OK) {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001416 return NGX_ERROR;
1417 }
1418 }
1419
1420 return NGX_OK;
Igor Sysoeva8833612009-02-18 16:17:12 +00001421}
1422
1423
1424static ngx_int_t
1425ngx_http_server_names(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001426 ngx_http_conf_addr_t *addr)
Igor Sysoeva8833612009-02-18 16:17:12 +00001427{
Igor Sysoevb37316d2009-04-08 19:51:30 +00001428 ngx_int_t rc;
1429 ngx_uint_t s;
1430 ngx_hash_init_t hash;
1431 ngx_hash_keys_arrays_t ha;
1432 ngx_http_server_name_t *name;
Igor Sysoeva8833612009-02-18 16:17:12 +00001433#if (NGX_PCRE)
Igor Sysoevb37316d2009-04-08 19:51:30 +00001434 ngx_uint_t regex, i;
Igor Sysoeva8833612009-02-18 16:17:12 +00001435
1436 regex = 0;
1437#endif
1438
1439 ngx_memzero(&ha, sizeof(ngx_hash_keys_arrays_t));
1440
1441 ha.temp_pool = ngx_create_pool(16384, cf->log);
1442 if (ha.temp_pool == NULL) {
1443 return NGX_ERROR;
1444 }
1445
1446 ha.pool = cf->pool;
1447
1448 if (ngx_hash_keys_array_init(&ha, NGX_HASH_LARGE) != NGX_OK) {
1449 goto failed;
1450 }
1451
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001452 name = addr->names.elts;
Igor Sysoeva8833612009-02-18 16:17:12 +00001453
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001454 for (s = 0; s < addr->names.nelts; s++) {
Igor Sysoeva8833612009-02-18 16:17:12 +00001455
1456#if (NGX_PCRE)
1457 if (name[s].regex) {
1458 regex++;
1459 continue;
1460 }
1461#endif
1462
1463 rc = ngx_hash_add_key(&ha, &name[s].name, name[s].core_srv_conf,
1464 NGX_HASH_WILDCARD_KEY);
1465
1466 if (rc == NGX_ERROR) {
1467 return NGX_ERROR;
1468 }
1469
1470 if (rc == NGX_DECLINED) {
1471 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
1472 "invalid server name or wildcard \"%V\" on %s",
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001473 &name[s].name, addr->listen_conf->addr);
Igor Sysoeva8833612009-02-18 16:17:12 +00001474 return NGX_ERROR;
1475 }
1476
1477 if (rc == NGX_BUSY) {
1478 ngx_log_error(NGX_LOG_WARN, cf->log, 0,
1479 "conflicting server name \"%V\" on %s, ignored",
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001480 &name[s].name, addr->listen_conf->addr);
Igor Sysoeva8833612009-02-18 16:17:12 +00001481 }
1482 }
1483
1484 hash.key = ngx_hash_key_lc;
1485 hash.max_size = cmcf->server_names_hash_max_size;
1486 hash.bucket_size = cmcf->server_names_hash_bucket_size;
1487 hash.name = "server_names_hash";
1488 hash.pool = cf->pool;
1489
1490 if (ha.keys.nelts) {
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001491 hash.hash = &addr->hash;
Igor Sysoeva8833612009-02-18 16:17:12 +00001492 hash.temp_pool = NULL;
1493
1494 if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK) {
1495 goto failed;
1496 }
1497 }
1498
1499 if (ha.dns_wc_head.nelts) {
1500
1501 ngx_qsort(ha.dns_wc_head.elts, (size_t) ha.dns_wc_head.nelts,
1502 sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);
1503
1504 hash.hash = NULL;
1505 hash.temp_pool = ha.temp_pool;
1506
1507 if (ngx_hash_wildcard_init(&hash, ha.dns_wc_head.elts,
1508 ha.dns_wc_head.nelts)
1509 != NGX_OK)
1510 {
1511 goto failed;
1512 }
1513
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001514 addr->wc_head = (ngx_hash_wildcard_t *) hash.hash;
Igor Sysoeva8833612009-02-18 16:17:12 +00001515 }
1516
1517 if (ha.dns_wc_tail.nelts) {
1518
1519 ngx_qsort(ha.dns_wc_tail.elts, (size_t) ha.dns_wc_tail.nelts,
1520 sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);
1521
1522 hash.hash = NULL;
1523 hash.temp_pool = ha.temp_pool;
1524
1525 if (ngx_hash_wildcard_init(&hash, ha.dns_wc_tail.elts,
1526 ha.dns_wc_tail.nelts)
1527 != NGX_OK)
1528 {
1529 goto failed;
1530 }
1531
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001532 addr->wc_tail = (ngx_hash_wildcard_t *) hash.hash;
Igor Sysoeva8833612009-02-18 16:17:12 +00001533 }
1534
1535 ngx_destroy_pool(ha.temp_pool);
1536
1537#if (NGX_PCRE)
1538
1539 if (regex == 0) {
1540 return NGX_OK;
1541 }
1542
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001543 addr->nregex = regex;
1544 addr->regex = ngx_palloc(cf->pool, regex * sizeof(ngx_http_server_name_t));
1545 if (addr->regex == NULL) {
Igor Sysoeva8833612009-02-18 16:17:12 +00001546 return NGX_ERROR;
1547 }
1548
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001549 for (i = 0, s = 0; s < addr->names.nelts; s++) {
Igor Sysoeva8833612009-02-18 16:17:12 +00001550 if (name[s].regex) {
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001551 addr->regex[i++] = name[s];
Igor Sysoeva8833612009-02-18 16:17:12 +00001552 }
1553 }
1554
1555#endif
1556
1557 return NGX_OK;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001558
1559failed:
1560
1561 ngx_destroy_pool(ha.temp_pool);
1562
1563 return NGX_ERROR;
1564}
1565
1566
1567static ngx_int_t
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001568ngx_http_cmp_conf_addrs(const void *one, const void *two)
Igor Sysoev305a9d82005-12-26 17:07:48 +00001569{
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001570 ngx_http_conf_addr_t *first, *second;
Igor Sysoev305a9d82005-12-26 17:07:48 +00001571
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001572 first = (ngx_http_conf_addr_t *) one;
1573 second = (ngx_http_conf_addr_t *) two;
Igor Sysoev305a9d82005-12-26 17:07:48 +00001574
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001575 if (first->wildcard) {
1576 /* a wildcard address must be the last resort, shift it to the end */
Igor Sysoev305a9d82005-12-26 17:07:48 +00001577 return 1;
1578 }
1579
1580 if (first->bind && !second->bind) {
1581 /* shift explicit bind()ed addresses to the start */
1582 return -1;
1583 }
1584
1585 if (!first->bind && second->bind) {
1586 /* shift explicit bind()ed addresses to the start */
1587 return 1;
1588 }
1589
1590 /* do not sort by default */
1591
1592 return 0;
1593}
1594
1595
1596static int ngx_libc_cdecl
1597ngx_http_cmp_dns_wildcards(const void *one, const void *two)
1598{
1599 ngx_hash_key_t *first, *second;
1600
1601 first = (ngx_hash_key_t *) one;
1602 second = (ngx_hash_key_t *) two;
1603
1604 return ngx_strcmp(first->key.data, second->key.data);
1605}
Igor Sysoev6d14e652008-05-22 11:07:08 +00001606
1607
1608static ngx_int_t
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001609ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port)
Igor Sysoev6d14e652008-05-22 11:07:08 +00001610{
Igor Sysoev1966aed2009-02-24 07:29:55 +00001611 ngx_uint_t i, last, bind_wildcard;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001612 ngx_listening_t *ls;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001613 ngx_http_port_t *hport;
1614 ngx_http_conf_addr_t *addr;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001615
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001616 addr = port->addrs.elts;
1617 last = port->addrs.nelts;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001618
1619 /*
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001620 * If there is a binding to an "*:port" then we need to bind() to
1621 * the "*:port" only and ignore other implicit bindings. The bindings
1622 * have been already sorted: explicit bindings are on the start, then
1623 * implicit bindings go, and wildcard binding is in the end.
Igor Sysoev6d14e652008-05-22 11:07:08 +00001624 */
1625
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001626 if (addr[last - 1].wildcard) {
1627 addr[last - 1].bind = 1;
1628 bind_wildcard = 1;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001629
1630 } else {
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001631 bind_wildcard = 0;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001632 }
1633
Igor Sysoev1966aed2009-02-24 07:29:55 +00001634 i = 0;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001635
Igor Sysoev1966aed2009-02-24 07:29:55 +00001636 while (i < last) {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001637
Igor Sysoev1966aed2009-02-24 07:29:55 +00001638 if (bind_wildcard && !addr[i].bind) {
1639 i++;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001640 continue;
1641 }
1642
Igor Sysoev1966aed2009-02-24 07:29:55 +00001643 ls = ngx_http_add_listening(cf, &addr[i]);
Igor Sysoev6d14e652008-05-22 11:07:08 +00001644 if (ls == NULL) {
1645 return NGX_ERROR;
1646 }
1647
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001648 hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t));
1649 if (hport == NULL) {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001650 return NGX_ERROR;
1651 }
1652
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001653 ls->servers = hport;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001654
Igor Sysoev1966aed2009-02-24 07:29:55 +00001655 if (i == last - 1) {
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001656 hport->naddrs = last;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001657
1658 } else {
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001659 hport->naddrs = 1;
Igor Sysoev1966aed2009-02-24 07:29:55 +00001660 i = 0;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001661 }
1662
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001663 switch (ls->sockaddr->sa_family) {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001664
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001665#if (NGX_HAVE_INET6)
1666 case AF_INET6:
1667 if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001668 return NGX_ERROR;
1669 }
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001670 break;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001671#endif
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001672 default: /* AF_INET */
1673 if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) {
1674 return NGX_ERROR;
1675 }
1676 break;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001677 }
1678
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001679 addr++;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001680 last--;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001681 }
1682
1683 return NGX_OK;
1684}
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00001685
1686
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001687static ngx_listening_t *
1688ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)
1689{
1690 ngx_listening_t *ls;
1691 struct sockaddr *sa;
1692 ngx_http_core_loc_conf_t *clcf;
1693 ngx_http_core_srv_conf_t *cscf;
1694 u_char text[NGX_SOCKADDR_STRLEN];
1695
1696 ls = ngx_array_push(&cf->cycle->listening);
1697 if (ls == NULL) {
1698 return NULL;
1699 }
1700
1701 ngx_memzero(ls, sizeof(ngx_listening_t));
1702
1703 sa = ngx_palloc(cf->pool, addr->socklen);
1704 if (sa == NULL) {
1705 return NULL;
1706 }
1707
1708 ngx_memcpy(sa, addr->sockaddr, addr->socklen);
1709
1710 ls->sockaddr = sa;
1711 ls->socklen = addr->socklen;
1712
1713 ls->addr_text.len = ngx_sock_ntop(sa, text, NGX_SOCKADDR_STRLEN, 1);
1714
1715 ls->addr_text.data = ngx_pnalloc(cf->pool, ls->addr_text.len);
1716 if (ls->addr_text.data == NULL) {
1717 return NULL;
1718 }
1719
1720 ngx_memcpy(ls->addr_text.data, text, ls->addr_text.len);
1721
1722 ls->fd = (ngx_socket_t) -1;
1723 ls->type = SOCK_STREAM;
1724
1725 switch (ls->sockaddr->sa_family) {
1726#if (NGX_HAVE_INET6)
1727 case AF_INET6:
1728 ls->addr_text_max_len = NGX_INET6_ADDRSTRLEN;
1729 break;
1730#endif
1731 case AF_INET:
1732 ls->addr_text_max_len = NGX_INET_ADDRSTRLEN;
1733 break;
1734 default:
1735 ls->addr_text_max_len = NGX_SOCKADDR_STRLEN;
1736 break;
1737 }
1738
1739 ls->addr_ntop = 1;
1740
1741 ls->handler = ngx_http_init_connection;
1742
1743 cscf = addr->core_srv_conf;
1744 ls->pool_size = cscf->connection_pool_size;
1745 ls->post_accept_timeout = cscf->client_header_timeout;
1746
1747 clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];
1748
Igor Sysoev0cd76ea2009-04-30 13:53:42 +00001749 ls->logp = clcf->error_log;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001750 ls->log.data = &ls->addr_text;
1751 ls->log.handler = ngx_accept_log_error;
1752
1753#if (NGX_WIN32)
1754 {
1755 ngx_iocp_conf_t *iocpcf;
1756
1757 iocpcf = ngx_event_get_conf(cf->cycle->conf_ctx, ngx_iocp_module);
1758 if (iocpcf->acceptex_read) {
1759 ls->post_accept_buffer_size = cscf->client_header_buffer_size;
1760 }
1761 }
1762#endif
1763
1764 ls->backlog = addr->listen_conf->backlog;
1765 ls->rcvbuf = addr->listen_conf->rcvbuf;
1766 ls->sndbuf = addr->listen_conf->sndbuf;
1767
1768#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
1769 ls->accept_filter = addr->listen_conf->accept_filter;
1770#endif
1771
1772#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
1773 ls->deferred_accept = addr->listen_conf->deferred_accept;
1774#endif
1775
Igor Sysoev6d94b512009-03-13 14:20:34 +00001776#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
1777 ls->ipv6only = addr->listen_conf->ipv6only;
1778#endif
1779
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001780 return ls;
1781}
1782
1783
1784static ngx_int_t
1785ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport,
1786 ngx_http_conf_addr_t *addr)
1787{
1788 ngx_uint_t i;
1789 ngx_http_in_addr_t *addrs;
1790 struct sockaddr_in *sin;
1791 ngx_http_virtual_names_t *vn;
1792
1793 hport->addrs = ngx_pcalloc(cf->pool,
1794 hport->naddrs * sizeof(ngx_http_in_addr_t));
1795 if (hport->addrs == NULL) {
1796 return NGX_ERROR;
1797 }
1798
1799 addrs = hport->addrs;
1800
1801 for (i = 0; i < hport->naddrs; i++) {
1802
1803 sin = (struct sockaddr_in *) addr[i].sockaddr;
1804 addrs[i].addr = sin->sin_addr.s_addr;
1805 addrs[i].conf.core_srv_conf = addr[i].core_srv_conf;
1806#if (NGX_HTTP_SSL)
1807 addrs[i].conf.ssl = addr[i].ssl;
1808#endif
1809
1810 if (addr[i].hash.buckets == NULL
1811 && (addr[i].wc_head == NULL
1812 || addr[i].wc_head->hash.buckets == NULL)
Igor Sysoevfb3be732009-03-19 15:46:27 +00001813 && (addr[i].wc_tail == NULL
Igor Sysoev7b5edd82009-03-19 16:07:40 +00001814 || addr[i].wc_tail->hash.buckets == NULL)
1815#if (NGX_PCRE)
1816 && addr[i].nregex == 0
1817#endif
1818 )
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001819 {
1820 continue;
1821 }
1822
1823 vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
1824 if (vn == NULL) {
1825 return NGX_ERROR;
1826 }
1827
Igor Sysoeve4694392009-04-09 13:56:16 +00001828 addrs[i].conf.virtual_names = vn;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001829
1830 vn->names.hash = addr[i].hash;
1831 vn->names.wc_head = addr[i].wc_head;
1832 vn->names.wc_tail = addr[i].wc_tail;
1833#if (NGX_PCRE)
1834 vn->nregex = addr[i].nregex;
1835 vn->regex = addr[i].regex;
1836#endif
1837 }
1838
1839 return NGX_OK;
1840}
1841
1842
1843#if (NGX_HAVE_INET6)
1844
1845static ngx_int_t
1846ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport,
1847 ngx_http_conf_addr_t *addr)
1848{
1849 ngx_uint_t i;
1850 ngx_http_in6_addr_t *addrs6;
1851 struct sockaddr_in6 *sin6;
1852 ngx_http_virtual_names_t *vn;
1853
1854 hport->addrs = ngx_pcalloc(cf->pool,
1855 hport->naddrs * sizeof(ngx_http_in6_addr_t));
1856 if (hport->addrs == NULL) {
1857 return NGX_ERROR;
1858 }
1859
1860 addrs6 = hport->addrs;
1861
1862 for (i = 0; i < hport->naddrs; i++) {
1863
1864 sin6 = (struct sockaddr_in6 *) addr[i].sockaddr;
1865 addrs6[i].addr6 = sin6->sin6_addr;
1866 addrs6[i].conf.core_srv_conf = addr[i].core_srv_conf;
1867#if (NGX_HTTP_SSL)
1868 addrs6[i].conf.ssl = addr[i].ssl;
1869#endif
1870
1871 if (addr[i].hash.buckets == NULL
1872 && (addr[i].wc_head == NULL
1873 || addr[i].wc_head->hash.buckets == NULL)
1874 && (addr[i].wc_head == NULL
1875 || addr[i].wc_head->hash.buckets == NULL))
1876 {
1877 continue;
1878 }
1879
1880 vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
1881 if (vn == NULL) {
1882 return NGX_ERROR;
1883 }
1884
Igor Sysoeve4694392009-04-09 13:56:16 +00001885 addrs6[i].conf.virtual_names = vn;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001886
1887 vn->names.hash = addr[i].hash;
1888 vn->names.wc_head = addr[i].wc_head;
1889 vn->names.wc_tail = addr[i].wc_tail;
1890#if (NGX_PCRE)
1891 vn->nregex = addr[i].nregex;
1892 vn->regex = addr[i].regex;
1893#endif
1894 }
1895
1896 return NGX_OK;
1897}
1898
1899#endif
1900
1901
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00001902char *
1903ngx_http_types_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1904{
1905 char *p = conf;
1906
1907 ngx_array_t **types;
1908 ngx_str_t *value, *default_type;
1909 ngx_uint_t i, n, hash;
1910 ngx_hash_key_t *type;
1911
1912 types = (ngx_array_t **) (p + cmd->offset);
1913
1914 default_type = cmd->post;
1915
1916 if (*types == NULL) {
1917 *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t));
1918 if (*types == NULL) {
1919 return NGX_CONF_ERROR;
1920 }
1921
1922 if (default_type) {
1923 type = ngx_array_push(*types);
1924 if (type == NULL) {
1925 return NGX_CONF_ERROR;
1926 }
1927
1928 type->key = *default_type;
1929 type->key_hash = ngx_hash_key(default_type->data,
1930 default_type->len);
1931 type->value = (void *) 4;
1932 }
1933 }
1934
1935 value = cf->args->elts;
1936
1937 for (i = 1; i < cf->args->nelts; i++) {
1938
1939 hash = ngx_hash_strlow(value[i].data, value[i].data, value[i].len);
1940 value[i].data[value[i].len] = '\0';
1941
1942 type = (*types)->elts;
1943 for (n = 0; n < (*types)->nelts; n++) {
1944
1945 if (ngx_strcmp(value[i].data, type[n].key.data) == 0) {
1946 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1947 "duplicate MIME type \"%V\"", &value[i]);
1948 continue;
1949 }
1950 }
1951
1952 type = ngx_array_push(*types);
1953 if (type == NULL) {
1954 return NGX_CONF_ERROR;
1955 }
1956
1957 type->key = value[i];
1958 type->key_hash = hash;
1959 type->value = (void *) 4;
1960 }
1961
1962 return NGX_CONF_OK;
1963}
1964
1965
1966char *
1967ngx_http_merge_types(ngx_conf_t *cf, ngx_array_t *keys, ngx_hash_t *types_hash,
Igor Sysoevc71e3d82008-08-13 16:25:48 +00001968 ngx_array_t *prev_keys, ngx_hash_t *prev_types_hash,
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00001969 ngx_str_t *default_types)
1970{
1971 ngx_hash_init_t hash;
1972
Igor Sysoevc71e3d82008-08-13 16:25:48 +00001973 if (keys) {
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00001974
Igor Sysoevc71e3d82008-08-13 16:25:48 +00001975 hash.hash = types_hash;
1976 hash.key = NULL;
1977 hash.max_size = 2048;
1978 hash.bucket_size = 64;
1979 hash.name = "test_types_hash";
1980 hash.pool = cf->pool;
1981 hash.temp_pool = NULL;
1982
1983 if (ngx_hash_init(&hash, keys->elts, keys->nelts) != NGX_OK) {
1984 return NGX_CONF_ERROR;
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00001985 }
1986
Igor Sysoevc71e3d82008-08-13 16:25:48 +00001987 return NGX_CONF_OK;
1988 }
1989
1990 if (prev_types_hash->buckets == NULL) {
1991
1992 if (prev_keys == NULL) {
1993
Igor Sysoev0c16f732008-09-01 14:05:20 +00001994 if (ngx_http_set_default_types(cf, &prev_keys, default_types)
Igor Sysoevc71e3d82008-08-13 16:25:48 +00001995 != NGX_OK)
1996 {
Igor Sysoev0c16f732008-09-01 14:05:20 +00001997 return NGX_CONF_ERROR;
1998 }
Igor Sysoevc71e3d82008-08-13 16:25:48 +00001999 }
2000
2001 hash.hash = prev_types_hash;
2002 hash.key = NULL;
2003 hash.max_size = 2048;
2004 hash.bucket_size = 64;
2005 hash.name = "test_types_hash";
2006 hash.pool = cf->pool;
2007 hash.temp_pool = NULL;
2008
2009 if (ngx_hash_init(&hash, prev_keys->elts, prev_keys->nelts) != NGX_OK) {
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00002010 return NGX_CONF_ERROR;
2011 }
2012 }
2013
Igor Sysoevc71e3d82008-08-13 16:25:48 +00002014 *types_hash = *prev_types_hash;
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00002015
2016 return NGX_CONF_OK;
2017
2018}
2019
2020
Igor Sysoevc71e3d82008-08-13 16:25:48 +00002021ngx_int_t
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00002022ngx_http_set_default_types(ngx_conf_t *cf, ngx_array_t **types,
2023 ngx_str_t *default_type)
2024{
2025 ngx_hash_key_t *type;
2026
2027 *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t));
2028 if (*types == NULL) {
Igor Sysoevc71e3d82008-08-13 16:25:48 +00002029 return NGX_ERROR;
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00002030 }
2031
2032 while (default_type->len) {
2033
2034 type = ngx_array_push(*types);
2035 if (type == NULL) {
Igor Sysoevc71e3d82008-08-13 16:25:48 +00002036 return NGX_ERROR;
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00002037 }
2038
2039 type->key = *default_type;
2040 type->key_hash = ngx_hash_key(default_type->data,
2041 default_type->len);
2042 type->value = (void *) 4;
2043
2044 default_type++;
2045 }
2046
Igor Sysoevc71e3d82008-08-13 16:25:48 +00002047 return NGX_OK;
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00002048}