blob: 3e077fb95ab9ee4288e49fa4c42d4a7b07ab12e1 [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
Maxim Konovalovf8d59e32012-01-18 15:07:43 +00004 * Copyright (C) Nginx, Inc.
Igor Sysoevd90282d2004-09-28 08:34:51 +00005 */
6
7
Igor Sysoev2b542382002-08-20 14:48:28 +00008#include <ngx_config.h>
Igor Sysoev1c104622003-06-03 15:42:58 +00009#include <ngx_core.h>
Igor Sysoeve0af1b82002-08-16 15:27:03 +000010#include <ngx_http.h>
11
12
Igor Sysoev6253ca12003-05-27 12:18:54 +000013static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
Igor Sysoev87ac67f2008-05-22 09:57:47 +000014static ngx_int_t ngx_http_init_phases(ngx_conf_t *cf,
15 ngx_http_core_main_conf_t *cmcf);
16static ngx_int_t ngx_http_init_headers_in_hash(ngx_conf_t *cf,
17 ngx_http_core_main_conf_t *cmcf);
18static ngx_int_t ngx_http_init_phase_handlers(ngx_conf_t *cf,
19 ngx_http_core_main_conf_t *cmcf);
Igor Sysoev6d14e652008-05-22 11:07:08 +000020
Igor Sysoeva8833612009-02-18 16:17:12 +000021static ngx_int_t ngx_http_add_addresses(ngx_conf_t *cf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +000022 ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port,
Igor Sysoevf2694cb2009-10-21 16:47:44 +000023 ngx_http_listen_opt_t *lsopt);
Igor Sysoevc0edbcc2004-10-21 15:34:38 +000024static ngx_int_t ngx_http_add_address(ngx_conf_t *cf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +000025 ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port,
Igor Sysoevf2694cb2009-10-21 16:47:44 +000026 ngx_http_listen_opt_t *lsopt);
Igor Sysoev2a634f52009-10-21 16:27:48 +000027static ngx_int_t ngx_http_add_server(ngx_conf_t *cf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +000028 ngx_http_core_srv_conf_t *cscf, ngx_http_conf_addr_t *addr);
Igor Sysoev6d14e652008-05-22 11:07:08 +000029
Igor Sysoev0ec54922010-08-02 15:28:04 +000030static char *ngx_http_merge_servers(ngx_conf_t *cf,
31 ngx_http_core_main_conf_t *cmcf, ngx_http_module_t *module,
32 ngx_uint_t ctx_index);
Igor Sysoev74a5ddb2004-07-18 19:11:20 +000033static char *ngx_http_merge_locations(ngx_conf_t *cf,
Igor Sysoeve55988c2008-05-24 14:14:13 +000034 ngx_queue_t *locations, void **loc_conf, ngx_http_module_t *module,
Igor Sysoev8184d1b2005-03-04 14:06:57 +000035 ngx_uint_t ctx_index);
Igor Sysoeve55988c2008-05-24 14:14:13 +000036static ngx_int_t ngx_http_init_locations(ngx_conf_t *cf,
37 ngx_http_core_srv_conf_t *cscf, ngx_http_core_loc_conf_t *pclcf);
38static ngx_int_t ngx_http_init_static_location_trees(ngx_conf_t *cf,
39 ngx_http_core_loc_conf_t *pclcf);
40static ngx_int_t ngx_http_cmp_locations(const ngx_queue_t *one,
41 const ngx_queue_t *two);
42static ngx_int_t ngx_http_join_exact_locations(ngx_conf_t *cf,
43 ngx_queue_t *locations);
44static void ngx_http_create_locations_list(ngx_queue_t *locations,
45 ngx_queue_t *q);
46static ngx_http_location_tree_node_t *
47 ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations,
48 size_t prefix);
Igor Sysoev6d14e652008-05-22 11:07:08 +000049
50static ngx_int_t ngx_http_optimize_servers(ngx_conf_t *cf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +000051 ngx_http_core_main_conf_t *cmcf, ngx_array_t *ports);
Igor Sysoeva8833612009-02-18 16:17:12 +000052static ngx_int_t ngx_http_server_names(ngx_conf_t *cf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +000053 ngx_http_core_main_conf_t *cmcf, ngx_http_conf_addr_t *addr);
54static ngx_int_t ngx_http_cmp_conf_addrs(const void *one, const void *two);
Igor Sysoev305a9d82005-12-26 17:07:48 +000055static int ngx_libc_cdecl ngx_http_cmp_dns_wildcards(const void *one,
56 const void *two);
Igor Sysoev4e9393a2003-01-09 05:36:00 +000057
Igor Sysoev6d14e652008-05-22 11:07:08 +000058static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +000059 ngx_http_conf_port_t *port);
60static ngx_listening_t *ngx_http_add_listening(ngx_conf_t *cf,
61 ngx_http_conf_addr_t *addr);
62static ngx_int_t ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport,
63 ngx_http_conf_addr_t *addr);
64#if (NGX_HAVE_INET6)
65static ngx_int_t ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport,
66 ngx_http_conf_addr_t *addr);
67#endif
Igor Sysoev6d14e652008-05-22 11:07:08 +000068
Igor Sysoev305a9d82005-12-26 17:07:48 +000069ngx_uint_t ngx_http_max_module;
Igor Sysoeve89c4582003-12-19 08:15:11 +000070
Igor Sysoevb2620632003-01-10 06:09:20 +000071
Igor Sysoev2f657222004-06-16 15:32:11 +000072ngx_int_t (*ngx_http_top_header_filter) (ngx_http_request_t *r);
73ngx_int_t (*ngx_http_top_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
Igor Sysoev4e9393a2003-01-09 05:36:00 +000074
75
Igor Sysoev390abe02008-08-12 13:11:36 +000076ngx_str_t ngx_http_html_default_types[] = {
77 ngx_string("text/html"),
78 ngx_null_string
79};
80
81
Igor Sysoev4e9393a2003-01-09 05:36:00 +000082static ngx_command_t ngx_http_commands[] = {
83
Igor Sysoev8184d1b2005-03-04 14:06:57 +000084 { ngx_string("http"),
85 NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
86 ngx_http_block,
87 0,
88 0,
89 NULL },
Igor Sysoev4e9393a2003-01-09 05:36:00 +000090
Igor Sysoev8184d1b2005-03-04 14:06:57 +000091 ngx_null_command
Igor Sysoev4e9393a2003-01-09 05:36:00 +000092};
93
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +000094
Igor Sysoev43f13192004-04-12 16:38:09 +000095static ngx_core_module_t ngx_http_module_ctx = {
96 ngx_string("http"),
97 NULL,
98 NULL
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +000099};
Igor Sysoev43f13192004-04-12 16:38:09 +0000100
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000101
102ngx_module_t ngx_http_module = {
Igor Sysoev899b44e2005-05-12 14:58:06 +0000103 NGX_MODULE_V1,
Igor Sysoev43f13192004-04-12 16:38:09 +0000104 &ngx_http_module_ctx, /* module context */
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000105 ngx_http_commands, /* module directives */
Igor Sysoev6253ca12003-05-27 12:18:54 +0000106 NGX_CORE_MODULE, /* module type */
Igor Sysoeve5733802005-09-08 14:36:09 +0000107 NULL, /* init master */
Igor Sysoeva7f7fa82003-07-11 04:50:59 +0000108 NULL, /* init module */
Igor Sysoeve5733802005-09-08 14:36:09 +0000109 NULL, /* init process */
110 NULL, /* init thread */
111 NULL, /* exit thread */
112 NULL, /* exit process */
113 NULL, /* exit master */
114 NGX_MODULE_V1_PADDING
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000115};
116
117
Igor Sysoev8184d1b2005-03-04 14:06:57 +0000118static char *
119ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000120{
Igor Sysoev2e6ba932004-09-09 15:40:48 +0000121 char *rv;
Igor Sysoev6d14e652008-05-22 11:07:08 +0000122 ngx_uint_t mi, m, s;
Igor Sysoev3b30a902003-12-25 20:26:58 +0000123 ngx_conf_t pcf;
Igor Sysoeva9830112003-05-19 16:39:14 +0000124 ngx_http_module_t *module;
Igor Sysoeva9830112003-05-19 16:39:14 +0000125 ngx_http_conf_ctx_t *ctx;
Igor Sysoeve55988c2008-05-24 14:14:13 +0000126 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev6d14e652008-05-22 11:07:08 +0000127 ngx_http_core_srv_conf_t **cscfp;
Igor Sysoev3b30a902003-12-25 20:26:58 +0000128 ngx_http_core_main_conf_t *cmcf;
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000129
Igor Sysoeva9830112003-05-19 16:39:14 +0000130 /* the main http context */
Igor Sysoevb1dfe472004-12-21 12:30:30 +0000131
Igor Sysoevc1571722005-03-19 12:38:37 +0000132 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
133 if (ctx == NULL) {
Igor Sysoev805d9db2005-02-03 19:33:37 +0000134 return NGX_CONF_ERROR;
135 }
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000136
Igor Sysoevbb4ec5c2003-05-16 15:27:48 +0000137 *(ngx_http_conf_ctx_t **) conf = ctx;
138
Igor Sysoev805d9db2005-02-03 19:33:37 +0000139
Igor Sysoeva9830112003-05-19 16:39:14 +0000140 /* count the number of the http modules and set up their indices */
141
Igor Sysoeve2a31542003-04-08 15:40:10 +0000142 ngx_http_max_module = 0;
Igor Sysoeva9830112003-05-19 16:39:14 +0000143 for (m = 0; ngx_modules[m]; m++) {
Igor Sysoev6253ca12003-05-27 12:18:54 +0000144 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000145 continue;
146 }
147
Igor Sysoev6253ca12003-05-27 12:18:54 +0000148 ngx_modules[m]->ctx_index = ngx_http_max_module++;
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000149 }
150
Igor Sysoevb1dfe472004-12-21 12:30:30 +0000151
Igor Sysoev805d9db2005-02-03 19:33:37 +0000152 /* the http main_conf context, it is the same in the all http contexts */
Igor Sysoevbb4ec5c2003-05-16 15:27:48 +0000153
Igor Sysoev805d9db2005-02-03 19:33:37 +0000154 ctx->main_conf = ngx_pcalloc(cf->pool,
155 sizeof(void *) * ngx_http_max_module);
156 if (ctx->main_conf == NULL) {
157 return NGX_CONF_ERROR;
158 }
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000159
Igor Sysoeva9830112003-05-19 16:39:14 +0000160
Igor Sysoev805d9db2005-02-03 19:33:37 +0000161 /*
162 * the http null srv_conf context, it is used to merge
163 * the server{}s' srv_conf's
164 */
165
166 ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
167 if (ctx->srv_conf == NULL) {
168 return NGX_CONF_ERROR;
169 }
170
171
172 /*
173 * the http null loc_conf context, it is used to merge
174 * the server{}s' loc_conf's
175 */
176
177 ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
178 if (ctx->loc_conf == NULL) {
179 return NGX_CONF_ERROR;
180 }
181
182
183 /*
184 * create the main_conf's, the null srv_conf's, and the null loc_conf's
185 * of the all http modules
186 */
Igor Sysoeva9830112003-05-19 16:39:14 +0000187
188 for (m = 0; ngx_modules[m]; m++) {
Igor Sysoev6253ca12003-05-27 12:18:54 +0000189 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000190 continue;
191 }
192
Igor Sysoev6253ca12003-05-27 12:18:54 +0000193 module = ngx_modules[m]->ctx;
194 mi = ngx_modules[m]->ctx_index;
Igor Sysoeva9830112003-05-19 16:39:14 +0000195
196 if (module->create_main_conf) {
Igor Sysoevc1571722005-03-19 12:38:37 +0000197 ctx->main_conf[mi] = module->create_main_conf(cf);
198 if (ctx->main_conf[mi] == NULL) {
Igor Sysoev805d9db2005-02-03 19:33:37 +0000199 return NGX_CONF_ERROR;
200 }
Igor Sysoeva9830112003-05-19 16:39:14 +0000201 }
202
203 if (module->create_srv_conf) {
Igor Sysoevc1571722005-03-19 12:38:37 +0000204 ctx->srv_conf[mi] = module->create_srv_conf(cf);
205 if (ctx->srv_conf[mi] == NULL) {
Igor Sysoev805d9db2005-02-03 19:33:37 +0000206 return NGX_CONF_ERROR;
207 }
Igor Sysoeva9830112003-05-19 16:39:14 +0000208 }
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000209
210 if (module->create_loc_conf) {
Igor Sysoevc1571722005-03-19 12:38:37 +0000211 ctx->loc_conf[mi] = module->create_loc_conf(cf);
212 if (ctx->loc_conf[mi] == NULL) {
Igor Sysoev805d9db2005-02-03 19:33:37 +0000213 return NGX_CONF_ERROR;
214 }
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000215 }
216 }
217
Igor Sysoev899b44e2005-05-12 14:58:06 +0000218 pcf = *cf;
219 cf->ctx = ctx;
220
221 for (m = 0; ngx_modules[m]; m++) {
222 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
223 continue;
224 }
225
226 module = ngx_modules[m]->ctx;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000227
228 if (module->preconfiguration) {
229 if (module->preconfiguration(cf) != NGX_OK) {
230 return NGX_CONF_ERROR;
231 }
232 }
233 }
Igor Sysoev805d9db2005-02-03 19:33:37 +0000234
Igor Sysoeva9830112003-05-19 16:39:14 +0000235 /* parse inside the http{} block */
236
Igor Sysoev6253ca12003-05-27 12:18:54 +0000237 cf->module_type = NGX_HTTP_MODULE;
Igor Sysoev79a80482003-05-14 17:13:13 +0000238 cf->cmd_type = NGX_HTTP_MAIN_CONF;
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000239 rv = ngx_conf_parse(cf, NULL);
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000240
Igor Sysoev74e95c22003-11-09 20:03:38 +0000241 if (rv != NGX_CONF_OK) {
Igor Sysoeve55988c2008-05-24 14:14:13 +0000242 goto failed;
Igor Sysoev74e95c22003-11-09 20:03:38 +0000243 }
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000244
Igor Sysoev74e95c22003-11-09 20:03:38 +0000245 /*
246 * init http{} main_conf's, merge the server{}s' srv_conf's
247 * and its location{}s' loc_conf's
248 */
Igor Sysoeva19a85e2003-01-28 15:56:37 +0000249
Igor Sysoev6253ca12003-05-27 12:18:54 +0000250 cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
Igor Sysoevaa3436c2003-05-30 14:27:59 +0000251 cscfp = cmcf->servers.elts;
Igor Sysoeva9830112003-05-19 16:39:14 +0000252
253 for (m = 0; ngx_modules[m]; m++) {
Igor Sysoev6253ca12003-05-27 12:18:54 +0000254 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
Igor Sysoeva9830112003-05-19 16:39:14 +0000255 continue;
256 }
257
Igor Sysoevaa3436c2003-05-30 14:27:59 +0000258 module = ngx_modules[m]->ctx;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000259 mi = ngx_modules[m]->ctx_index;
Igor Sysoeva9830112003-05-19 16:39:14 +0000260
261 /* init http{} main_conf's */
262
263 if (module->init_main_conf) {
Igor Sysoev890fc962003-07-20 21:15:59 +0000264 rv = module->init_main_conf(cf, ctx->main_conf[mi]);
Igor Sysoeva9830112003-05-19 16:39:14 +0000265 if (rv != NGX_CONF_OK) {
Igor Sysoeve55988c2008-05-24 14:14:13 +0000266 goto failed;
Igor Sysoeva9830112003-05-19 16:39:14 +0000267 }
268 }
269
Igor Sysoev0ec54922010-08-02 15:28:04 +0000270 rv = ngx_http_merge_servers(cf, cmcf, module, mi);
271 if (rv != NGX_CONF_OK) {
272 goto failed;
Igor Sysoeva19a85e2003-01-28 15:56:37 +0000273 }
274 }
Igor Sysoeva9830112003-05-19 16:39:14 +0000275
Igor Sysoev805d9db2005-02-03 19:33:37 +0000276
Igor Sysoeve55988c2008-05-24 14:14:13 +0000277 /* create location trees */
278
279 for (s = 0; s < cmcf->servers.nelts; s++) {
280
281 clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
282
283 if (ngx_http_init_locations(cf, cscfp[s], clcf) != NGX_OK) {
284 return NGX_CONF_ERROR;
285 }
286
287 if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
288 return NGX_CONF_ERROR;
289 }
290 }
291
292
Igor Sysoev87ac67f2008-05-22 09:57:47 +0000293 if (ngx_http_init_phases(cf, cmcf) != NGX_OK) {
Igor Sysoev805d9db2005-02-03 19:33:37 +0000294 return NGX_CONF_ERROR;
295 }
296
Igor Sysoev87ac67f2008-05-22 09:57:47 +0000297 if (ngx_http_init_headers_in_hash(cf, cmcf) != NGX_OK) {
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000298 return NGX_CONF_ERROR;
299 }
300
Igor Sysoev899b44e2005-05-12 14:58:06 +0000301
302 for (m = 0; ngx_modules[m]; m++) {
303 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
304 continue;
305 }
306
307 module = ngx_modules[m]->ctx;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000308
309 if (module->postconfiguration) {
310 if (module->postconfiguration(cf) != NGX_OK) {
311 return NGX_CONF_ERROR;
312 }
313 }
314 }
315
Igor Sysoev09c684b2005-11-09 17:25:55 +0000316 if (ngx_http_variables_init_vars(cf) != NGX_OK) {
317 return NGX_CONF_ERROR;
318 }
Igor Sysoev899b44e2005-05-12 14:58:06 +0000319
320 /*
321 * http{}'s cf->ctx was needed while the configuration merging
322 * and in postconfiguration process
323 */
324
325 *cf = pcf;
326
Igor Sysoev02f742b2005-04-08 15:18:55 +0000327
Igor Sysoev87ac67f2008-05-22 09:57:47 +0000328 if (ngx_http_init_phase_handlers(cf, cmcf) != NGX_OK) {
Igor Sysoevda173ab2006-08-30 10:39:17 +0000329 return NGX_CONF_ERROR;
330 }
331
Igor Sysoevda173ab2006-08-30 10:39:17 +0000332
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000333 /* optimize the lists of ports, addresses and server names */
Igor Sysoeva19a85e2003-01-28 15:56:37 +0000334
Igor Sysoev79d630a2009-10-21 08:19:46 +0000335 if (ngx_http_optimize_servers(cf, cmcf, cmcf->ports) != NGX_OK) {
Igor Sysoev6d14e652008-05-22 11:07:08 +0000336 return NGX_CONF_ERROR;
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000337 }
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000338
339 return NGX_CONF_OK;
Igor Sysoeve55988c2008-05-24 14:14:13 +0000340
341failed:
342
343 *cf = pcf;
344
345 return rv;
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000346}
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000347
348
Igor Sysoev87ac67f2008-05-22 09:57:47 +0000349static ngx_int_t
350ngx_http_init_phases(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
351{
352 if (ngx_array_init(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers,
353 cf->pool, 1, sizeof(ngx_http_handler_pt))
354 != NGX_OK)
355 {
356 return NGX_ERROR;
357 }
358
359 if (ngx_array_init(&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers,
360 cf->pool, 1, sizeof(ngx_http_handler_pt))
361 != NGX_OK)
362 {
363 return NGX_ERROR;
364 }
365
366 if (ngx_array_init(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers,
367 cf->pool, 1, sizeof(ngx_http_handler_pt))
368 != NGX_OK)
369 {
370 return NGX_ERROR;
371 }
372
373 if (ngx_array_init(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers,
374 cf->pool, 1, sizeof(ngx_http_handler_pt))
375 != NGX_OK)
376 {
377 return NGX_ERROR;
378 }
379
380 if (ngx_array_init(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers,
381 cf->pool, 2, sizeof(ngx_http_handler_pt))
382 != NGX_OK)
383 {
384 return NGX_ERROR;
385 }
386
387 if (ngx_array_init(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers,
388 cf->pool, 4, sizeof(ngx_http_handler_pt))
389 != NGX_OK)
390 {
391 return NGX_ERROR;
392 }
393
394 if (ngx_array_init(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers,
395 cf->pool, 1, sizeof(ngx_http_handler_pt))
396 != NGX_OK)
397 {
398 return NGX_ERROR;
399 }
400
401 return NGX_OK;
402}
403
404
405static ngx_int_t
406ngx_http_init_headers_in_hash(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
407{
408 ngx_array_t headers_in;
409 ngx_hash_key_t *hk;
410 ngx_hash_init_t hash;
411 ngx_http_header_t *header;
412
413 if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t))
414 != NGX_OK)
415 {
416 return NGX_ERROR;
417 }
418
419 for (header = ngx_http_headers_in; header->name.len; header++) {
420 hk = ngx_array_push(&headers_in);
421 if (hk == NULL) {
422 return NGX_ERROR;
423 }
424
425 hk->key = header->name;
426 hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len);
427 hk->value = header;
428 }
429
430 hash.hash = &cmcf->headers_in_hash;
431 hash.key = ngx_hash_key_lc;
432 hash.max_size = 512;
433 hash.bucket_size = ngx_align(64, ngx_cacheline_size);
434 hash.name = "headers_in_hash";
435 hash.pool = cf->pool;
436 hash.temp_pool = NULL;
437
438 if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) {
439 return NGX_ERROR;
440 }
441
442 return NGX_OK;
443}
444
445
446static ngx_int_t
447ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
448{
449 ngx_int_t j;
450 ngx_uint_t i, n;
451 ngx_uint_t find_config_index, use_rewrite, use_access;
452 ngx_http_handler_pt *h;
453 ngx_http_phase_handler_t *ph;
454 ngx_http_phase_handler_pt checker;
455
456 cmcf->phase_engine.server_rewrite_index = (ngx_uint_t) -1;
457 cmcf->phase_engine.location_rewrite_index = (ngx_uint_t) -1;
458 find_config_index = 0;
459 use_rewrite = cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers.nelts ? 1 : 0;
460 use_access = cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers.nelts ? 1 : 0;
461
Igor Sysoevd8e3d0b2008-12-15 10:56:48 +0000462 n = use_rewrite + use_access + cmcf->try_files + 1 /* find config phase */;
Igor Sysoev87ac67f2008-05-22 09:57:47 +0000463
464 for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) {
465 n += cmcf->phases[i].handlers.nelts;
466 }
467
468 ph = ngx_pcalloc(cf->pool,
469 n * sizeof(ngx_http_phase_handler_t) + sizeof(void *));
470 if (ph == NULL) {
471 return NGX_ERROR;
472 }
473
474 cmcf->phase_engine.handlers = ph;
475 n = 0;
476
477 for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) {
478 h = cmcf->phases[i].handlers.elts;
479
480 switch (i) {
481
482 case NGX_HTTP_SERVER_REWRITE_PHASE:
483 if (cmcf->phase_engine.server_rewrite_index == (ngx_uint_t) -1) {
484 cmcf->phase_engine.server_rewrite_index = n;
485 }
Igor Sysoev4c1b0772010-06-18 15:15:20 +0000486 checker = ngx_http_core_rewrite_phase;
Igor Sysoev87ac67f2008-05-22 09:57:47 +0000487
488 break;
489
490 case NGX_HTTP_FIND_CONFIG_PHASE:
491 find_config_index = n;
492
493 ph->checker = ngx_http_core_find_config_phase;
494 n++;
495 ph++;
496
497 continue;
498
499 case NGX_HTTP_REWRITE_PHASE:
500 if (cmcf->phase_engine.location_rewrite_index == (ngx_uint_t) -1) {
501 cmcf->phase_engine.location_rewrite_index = n;
502 }
Igor Sysoev4c1b0772010-06-18 15:15:20 +0000503 checker = ngx_http_core_rewrite_phase;
Igor Sysoev87ac67f2008-05-22 09:57:47 +0000504
505 break;
506
507 case NGX_HTTP_POST_REWRITE_PHASE:
508 if (use_rewrite) {
509 ph->checker = ngx_http_core_post_rewrite_phase;
510 ph->next = find_config_index;
511 n++;
512 ph++;
513 }
514
515 continue;
516
517 case NGX_HTTP_ACCESS_PHASE:
518 checker = ngx_http_core_access_phase;
519 n++;
520 break;
521
522 case NGX_HTTP_POST_ACCESS_PHASE:
523 if (use_access) {
524 ph->checker = ngx_http_core_post_access_phase;
525 ph->next = n;
526 ph++;
527 }
528
529 continue;
530
Igor Sysoevd8e3d0b2008-12-15 10:56:48 +0000531 case NGX_HTTP_TRY_FILES_PHASE:
532 if (cmcf->try_files) {
533 ph->checker = ngx_http_core_try_files_phase;
534 n++;
535 ph++;
536 }
537
538 continue;
539
Igor Sysoev87ac67f2008-05-22 09:57:47 +0000540 case NGX_HTTP_CONTENT_PHASE:
541 checker = ngx_http_core_content_phase;
542 break;
543
544 default:
545 checker = ngx_http_core_generic_phase;
546 }
547
548 n += cmcf->phases[i].handlers.nelts;
549
550 for (j = cmcf->phases[i].handlers.nelts - 1; j >=0; j--) {
551 ph->checker = checker;
552 ph->handler = h[j];
553 ph->next = n;
554 ph++;
555 }
556 }
557
558 return NGX_OK;
559}
560
561
Igor Sysoeve55988c2008-05-24 14:14:13 +0000562static char *
Igor Sysoev0ec54922010-08-02 15:28:04 +0000563ngx_http_merge_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
564 ngx_http_module_t *module, ngx_uint_t ctx_index)
565{
566 char *rv;
567 ngx_uint_t s;
568 ngx_http_conf_ctx_t *ctx, saved;
569 ngx_http_core_loc_conf_t *clcf;
570 ngx_http_core_srv_conf_t **cscfp;
571
572 cscfp = cmcf->servers.elts;
573 ctx = (ngx_http_conf_ctx_t *) cf->ctx;
574 saved = *ctx;
575 rv = NGX_CONF_OK;
576
577 for (s = 0; s < cmcf->servers.nelts; s++) {
578
579 /* merge the server{}s' srv_conf's */
580
581 ctx->srv_conf = cscfp[s]->ctx->srv_conf;
582
583 if (module->merge_srv_conf) {
584 rv = module->merge_srv_conf(cf, saved.srv_conf[ctx_index],
585 cscfp[s]->ctx->srv_conf[ctx_index]);
586 if (rv != NGX_CONF_OK) {
587 goto failed;
588 }
589 }
590
591 if (module->merge_loc_conf) {
592
593 /* merge the server{}'s loc_conf */
594
595 ctx->loc_conf = cscfp[s]->ctx->loc_conf;
596
597 rv = module->merge_loc_conf(cf, saved.loc_conf[ctx_index],
598 cscfp[s]->ctx->loc_conf[ctx_index]);
599 if (rv != NGX_CONF_OK) {
600 goto failed;
601 }
602
603 /* merge the locations{}' loc_conf's */
604
605 clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
606
607 rv = ngx_http_merge_locations(cf, clcf->locations,
608 cscfp[s]->ctx->loc_conf,
609 module, ctx_index);
610 if (rv != NGX_CONF_OK) {
611 goto failed;
612 }
613 }
614 }
615
616failed:
617
618 *ctx = saved;
619
620 return rv;
621}
622
623
624static char *
Igor Sysoeve55988c2008-05-24 14:14:13 +0000625ngx_http_merge_locations(ngx_conf_t *cf, ngx_queue_t *locations,
626 void **loc_conf, ngx_http_module_t *module, ngx_uint_t ctx_index)
627{
628 char *rv;
629 ngx_queue_t *q;
Igor Sysoev0ec54922010-08-02 15:28:04 +0000630 ngx_http_conf_ctx_t *ctx, saved;
Igor Sysoeve55988c2008-05-24 14:14:13 +0000631 ngx_http_core_loc_conf_t *clcf;
632 ngx_http_location_queue_t *lq;
633
634 if (locations == NULL) {
635 return NGX_CONF_OK;
636 }
637
Igor Sysoev0ec54922010-08-02 15:28:04 +0000638 ctx = (ngx_http_conf_ctx_t *) cf->ctx;
639 saved = *ctx;
640
Igor Sysoeve55988c2008-05-24 14:14:13 +0000641 for (q = ngx_queue_head(locations);
642 q != ngx_queue_sentinel(locations);
643 q = ngx_queue_next(q))
644 {
645 lq = (ngx_http_location_queue_t *) q;
646
647 clcf = lq->exact ? lq->exact : lq->inclusive;
Igor Sysoev0ec54922010-08-02 15:28:04 +0000648 ctx->loc_conf = clcf->loc_conf;
Igor Sysoeve55988c2008-05-24 14:14:13 +0000649
650 rv = module->merge_loc_conf(cf, loc_conf[ctx_index],
651 clcf->loc_conf[ctx_index]);
652 if (rv != NGX_CONF_OK) {
653 return rv;
654 }
655
656 rv = ngx_http_merge_locations(cf, clcf->locations, clcf->loc_conf,
657 module, ctx_index);
658 if (rv != NGX_CONF_OK) {
659 return rv;
660 }
661 }
662
Igor Sysoev0ec54922010-08-02 15:28:04 +0000663 *ctx = saved;
664
Igor Sysoeve55988c2008-05-24 14:14:13 +0000665 return NGX_CONF_OK;
666}
667
668
669static ngx_int_t
670ngx_http_init_locations(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
671 ngx_http_core_loc_conf_t *pclcf)
672{
673 ngx_uint_t n;
674 ngx_queue_t *q, *locations, *named, tail;
675 ngx_http_core_loc_conf_t *clcf;
676 ngx_http_location_queue_t *lq;
677 ngx_http_core_loc_conf_t **clcfp;
678#if (NGX_PCRE)
679 ngx_uint_t r;
680 ngx_queue_t *regex;
681#endif
682
683 locations = pclcf->locations;
684
685 if (locations == NULL) {
686 return NGX_OK;
687 }
688
689 ngx_queue_sort(locations, ngx_http_cmp_locations);
690
691 named = NULL;
692 n = 0;
693#if (NGX_PCRE)
694 regex = NULL;
695 r = 0;
696#endif
697
698 for (q = ngx_queue_head(locations);
699 q != ngx_queue_sentinel(locations);
700 q = ngx_queue_next(q))
701 {
702 lq = (ngx_http_location_queue_t *) q;
703
704 clcf = lq->exact ? lq->exact : lq->inclusive;
705
706 if (ngx_http_init_locations(cf, NULL, clcf) != NGX_OK) {
707 return NGX_ERROR;
708 }
709
710#if (NGX_PCRE)
711
712 if (clcf->regex) {
713 r++;
714
715 if (regex == NULL) {
716 regex = q;
717 }
718
719 continue;
720 }
721
722#endif
723
724 if (clcf->named) {
725 n++;
726
727 if (named == NULL) {
728 named = q;
729 }
730
731 continue;
732 }
733
734 if (clcf->noname) {
735 break;
736 }
737 }
738
739 if (q != ngx_queue_sentinel(locations)) {
740 ngx_queue_split(locations, q, &tail);
741 }
742
743 if (named) {
744 clcfp = ngx_palloc(cf->pool,
745 (n + 1) * sizeof(ngx_http_core_loc_conf_t **));
746 if (clcfp == NULL) {
747 return NGX_ERROR;
748 }
749
750 cscf->named_locations = clcfp;
751
752 for (q = named;
753 q != ngx_queue_sentinel(locations);
754 q = ngx_queue_next(q))
755 {
756 lq = (ngx_http_location_queue_t *) q;
757
758 *(clcfp++) = lq->exact;
759 }
760
761 *clcfp = NULL;
762
763 ngx_queue_split(locations, named, &tail);
764 }
765
766#if (NGX_PCRE)
767
768 if (regex) {
769
770 clcfp = ngx_palloc(cf->pool,
771 (r + 1) * sizeof(ngx_http_core_loc_conf_t **));
772 if (clcfp == NULL) {
773 return NGX_ERROR;
774 }
775
776 pclcf->regex_locations = clcfp;
777
778 for (q = regex;
779 q != ngx_queue_sentinel(locations);
780 q = ngx_queue_next(q))
781 {
782 lq = (ngx_http_location_queue_t *) q;
783
784 *(clcfp++) = lq->exact;
785 }
786
787 *clcfp = NULL;
788
789 ngx_queue_split(locations, regex, &tail);
790 }
791
792#endif
793
794 return NGX_OK;
795}
796
797
798static ngx_int_t
799ngx_http_init_static_location_trees(ngx_conf_t *cf,
800 ngx_http_core_loc_conf_t *pclcf)
801{
802 ngx_queue_t *q, *locations;
803 ngx_http_core_loc_conf_t *clcf;
804 ngx_http_location_queue_t *lq;
805
806 locations = pclcf->locations;
807
808 if (locations == NULL) {
809 return NGX_OK;
810 }
811
812 if (ngx_queue_empty(locations)) {
813 return NGX_OK;
814 }
815
816 for (q = ngx_queue_head(locations);
817 q != ngx_queue_sentinel(locations);
818 q = ngx_queue_next(q))
819 {
820 lq = (ngx_http_location_queue_t *) q;
821
822 clcf = lq->exact ? lq->exact : lq->inclusive;
823
824 if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
825 return NGX_ERROR;
826 }
827 }
828
829 if (ngx_http_join_exact_locations(cf, locations) != NGX_OK) {
830 return NGX_ERROR;
831 }
832
833 ngx_http_create_locations_list(locations, ngx_queue_head(locations));
834
835 pclcf->static_locations = ngx_http_create_locations_tree(cf, locations, 0);
836 if (pclcf->static_locations == NULL) {
837 return NGX_ERROR;
838 }
839
840 return NGX_OK;
841}
842
843
844ngx_int_t
845ngx_http_add_location(ngx_conf_t *cf, ngx_queue_t **locations,
846 ngx_http_core_loc_conf_t *clcf)
847{
848 ngx_http_location_queue_t *lq;
849
850 if (*locations == NULL) {
851 *locations = ngx_palloc(cf->temp_pool,
852 sizeof(ngx_http_location_queue_t));
853 if (*locations == NULL) {
854 return NGX_ERROR;
855 }
856
857 ngx_queue_init(*locations);
858 }
859
860 lq = ngx_palloc(cf->temp_pool, sizeof(ngx_http_location_queue_t));
861 if (lq == NULL) {
862 return NGX_ERROR;
863 }
864
865 if (clcf->exact_match
866#if (NGX_PCRE)
867 || clcf->regex
868#endif
869 || clcf->named || clcf->noname)
870 {
871 lq->exact = clcf;
872 lq->inclusive = NULL;
873
874 } else {
875 lq->exact = NULL;
876 lq->inclusive = clcf;
877 }
878
879 lq->name = &clcf->name;
880 lq->file_name = cf->conf_file->file.name.data;
881 lq->line = cf->conf_file->line;
882
883 ngx_queue_init(&lq->list);
884
885 ngx_queue_insert_tail(*locations, &lq->queue);
886
887 return NGX_OK;
888}
889
890
891static ngx_int_t
892ngx_http_cmp_locations(const ngx_queue_t *one, const ngx_queue_t *two)
893{
894 ngx_int_t rc;
895 ngx_http_core_loc_conf_t *first, *second;
896 ngx_http_location_queue_t *lq1, *lq2;
897
898 lq1 = (ngx_http_location_queue_t *) one;
899 lq2 = (ngx_http_location_queue_t *) two;
900
901 first = lq1->exact ? lq1->exact : lq1->inclusive;
902 second = lq2->exact ? lq2->exact : lq2->inclusive;
903
904 if (first->noname && !second->noname) {
905 /* shift no named locations to the end */
906 return 1;
907 }
908
909 if (!first->noname && second->noname) {
910 /* shift no named locations to the end */
911 return -1;
912 }
913
914 if (first->noname || second->noname) {
915 /* do not sort no named locations */
916 return 0;
917 }
918
919 if (first->named && !second->named) {
920 /* shift named locations to the end */
921 return 1;
922 }
923
924 if (!first->named && second->named) {
925 /* shift named locations to the end */
926 return -1;
927 }
928
929 if (first->named && second->named) {
930 return ngx_strcmp(first->name.data, second->name.data);
931 }
932
933#if (NGX_PCRE)
934
935 if (first->regex && !second->regex) {
936 /* shift the regex matches to the end */
937 return 1;
938 }
939
940 if (!first->regex && second->regex) {
941 /* shift the regex matches to the end */
942 return -1;
943 }
944
945 if (first->regex || second->regex) {
946 /* do not sort the regex matches */
947 return 0;
948 }
949
950#endif
951
952 rc = ngx_strcmp(first->name.data, second->name.data);
953
954 if (rc == 0 && !first->exact_match && second->exact_match) {
955 /* an exact match must be before the same inclusive one */
956 return 1;
957 }
958
959 return rc;
960}
961
962
963static ngx_int_t
964ngx_http_join_exact_locations(ngx_conf_t *cf, ngx_queue_t *locations)
965{
966 ngx_queue_t *q, *x;
967 ngx_http_location_queue_t *lq, *lx;
968
969 q = ngx_queue_head(locations);
970
971 while (q != ngx_queue_last(locations)) {
972
973 x = ngx_queue_next(q);
974
975 lq = (ngx_http_location_queue_t *) q;
976 lx = (ngx_http_location_queue_t *) x;
977
978 if (ngx_strcmp(lq->name->data, lx->name->data) == 0) {
979
980 if ((lq->exact && lx->exact) || (lq->inclusive && lx->inclusive)) {
981 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
982 "duplicate location \"%V\" in %s:%ui",
983 lx->name, lx->file_name, lx->line);
984
985 return NGX_ERROR;
986 }
987
988 lq->inclusive = lx->inclusive;
989
990 ngx_queue_remove(x);
991
992 continue;
993 }
994
995 q = ngx_queue_next(q);
996 }
997
998 return NGX_OK;
999}
1000
1001
1002static void
1003ngx_http_create_locations_list(ngx_queue_t *locations, ngx_queue_t *q)
1004{
1005 u_char *name;
1006 size_t len;
1007 ngx_queue_t *x, tail;
1008 ngx_http_location_queue_t *lq, *lx;
1009
1010 if (q == ngx_queue_last(locations)) {
1011 return;
1012 }
1013
1014 lq = (ngx_http_location_queue_t *) q;
1015
1016 if (lq->inclusive == NULL) {
1017 ngx_http_create_locations_list(locations, ngx_queue_next(q));
1018 return;
1019 }
1020
1021 len = lq->name->len;
1022 name = lq->name->data;
1023
1024 for (x = ngx_queue_next(q);
1025 x != ngx_queue_sentinel(locations);
1026 x = ngx_queue_next(x))
1027 {
1028 lx = (ngx_http_location_queue_t *) x;
1029
1030 if (len > lx->name->len
1031 || (ngx_strncmp(name, lx->name->data, len) != 0))
1032 {
1033 break;
1034 }
1035 }
1036
1037 q = ngx_queue_next(q);
1038
1039 if (q == x) {
1040 ngx_http_create_locations_list(locations, x);
1041 return;
1042 }
1043
1044 ngx_queue_split(locations, q, &tail);
1045 ngx_queue_add(&lq->list, &tail);
1046
1047 if (x == ngx_queue_sentinel(locations)) {
1048 ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list));
1049 return;
1050 }
1051
1052 ngx_queue_split(&lq->list, x, &tail);
1053 ngx_queue_add(locations, &tail);
1054
1055 ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list));
1056
1057 ngx_http_create_locations_list(locations, x);
1058}
1059
1060
1061/*
1062 * to keep cache locality for left leaf nodes, allocate nodes in following
1063 * order: node, left subtree, right subtree, inclusive subtree
1064 */
1065
1066static ngx_http_location_tree_node_t *
1067ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations,
1068 size_t prefix)
1069{
1070 size_t len;
1071 ngx_queue_t *q, tail;
1072 ngx_http_location_queue_t *lq;
1073 ngx_http_location_tree_node_t *node;
1074
1075 q = ngx_queue_middle(locations);
1076
1077 lq = (ngx_http_location_queue_t *) q;
1078 len = lq->name->len - prefix;
1079
Igor Sysoev7f6b2ff2008-06-17 15:00:30 +00001080 node = ngx_palloc(cf->pool,
1081 offsetof(ngx_http_location_tree_node_t, name) + len);
Igor Sysoeve55988c2008-05-24 14:14:13 +00001082 if (node == NULL) {
1083 return NULL;
1084 }
1085
Igor Sysoev2d951bf2008-05-27 09:37:40 +00001086 node->left = NULL;
1087 node->right = NULL;
1088 node->tree = NULL;
Igor Sysoeve55988c2008-05-24 14:14:13 +00001089 node->exact = lq->exact;
1090 node->inclusive = lq->inclusive;
1091
1092 node->auto_redirect = (u_char) ((lq->exact && lq->exact->auto_redirect)
1093 || (lq->inclusive && lq->inclusive->auto_redirect));
1094
1095 node->len = (u_char) len;
1096 ngx_memcpy(node->name, &lq->name->data[prefix], len);
1097
1098 ngx_queue_split(locations, q, &tail);
1099
1100 if (ngx_queue_empty(locations)) {
1101 /*
1102 * ngx_queue_split() insures that if left part is empty,
1103 * then right one is empty too
1104 */
1105 goto inclusive;
1106 }
1107
1108 node->left = ngx_http_create_locations_tree(cf, locations, prefix);
1109 if (node->left == NULL) {
1110 return NULL;
1111 }
1112
1113 ngx_queue_remove(q);
1114
1115 if (ngx_queue_empty(&tail)) {
1116 goto inclusive;
1117 }
1118
1119 node->right = ngx_http_create_locations_tree(cf, &tail, prefix);
1120 if (node->right == NULL) {
1121 return NULL;
1122 }
1123
1124inclusive:
1125
1126 if (ngx_queue_empty(&lq->list)) {
1127 return node;
1128 }
1129
1130 node->tree = ngx_http_create_locations_tree(cf, &lq->list, prefix + len);
1131 if (node->tree == NULL) {
1132 return NULL;
1133 }
1134
1135 return node;
1136}
1137
1138
Igor Sysoev79d630a2009-10-21 08:19:46 +00001139ngx_int_t
1140ngx_http_add_listen(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
Igor Sysoevf2694cb2009-10-21 16:47:44 +00001141 ngx_http_listen_opt_t *lsopt)
Igor Sysoev6d14e652008-05-22 11:07:08 +00001142{
Igor Sysoev79d630a2009-10-21 08:19:46 +00001143 in_port_t p;
1144 ngx_uint_t i;
1145 struct sockaddr *sa;
1146 struct sockaddr_in *sin;
1147 ngx_http_conf_port_t *port;
1148 ngx_http_core_main_conf_t *cmcf;
1149#if (NGX_HAVE_INET6)
1150 struct sockaddr_in6 *sin6;
1151#endif
Igor Sysoev6d14e652008-05-22 11:07:08 +00001152
Igor Sysoev79d630a2009-10-21 08:19:46 +00001153 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
Igor Sysoev6d14e652008-05-22 11:07:08 +00001154
Igor Sysoev79d630a2009-10-21 08:19:46 +00001155 if (cmcf->ports == NULL) {
1156 cmcf->ports = ngx_array_create(cf->temp_pool, 2,
1157 sizeof(ngx_http_conf_port_t));
1158 if (cmcf->ports == NULL) {
1159 return NGX_ERROR;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001160 }
1161 }
1162
Igor Sysoev8c97fa92009-12-22 15:15:45 +00001163 sa = &lsopt->u.sockaddr;
Igor Sysoeva8833612009-02-18 16:17:12 +00001164
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001165 switch (sa->sa_family) {
1166
1167#if (NGX_HAVE_INET6)
1168 case AF_INET6:
Igor Sysoev8c97fa92009-12-22 15:15:45 +00001169 sin6 = &lsopt->u.sockaddr_in6;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001170 p = sin6->sin6_port;
1171 break;
1172#endif
1173
Igor Sysoevbaf8e402009-10-26 11:43:32 +00001174#if (NGX_HAVE_UNIX_DOMAIN)
1175 case AF_UNIX:
1176 p = 0;
1177 break;
1178#endif
1179
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001180 default: /* AF_INET */
Igor Sysoev8c97fa92009-12-22 15:15:45 +00001181 sin = &lsopt->u.sockaddr_in;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001182 p = sin->sin_port;
1183 break;
1184 }
1185
Igor Sysoev79d630a2009-10-21 08:19:46 +00001186 port = cmcf->ports->elts;
1187 for (i = 0; i < cmcf->ports->nelts; i++) {
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001188
1189 if (p != port[i].port || sa->sa_family != port[i].family) {
Igor Sysoeva8833612009-02-18 16:17:12 +00001190 continue;
1191 }
1192
Igor Sysoev1daaa002009-05-17 20:13:29 +00001193 /* a port is already in the port list */
Igor Sysoeva8833612009-02-18 16:17:12 +00001194
Igor Sysoevf2694cb2009-10-21 16:47:44 +00001195 return ngx_http_add_addresses(cf, cscf, &port[i], lsopt);
Igor Sysoeva8833612009-02-18 16:17:12 +00001196 }
1197
Igor Sysoev1daaa002009-05-17 20:13:29 +00001198 /* add a port to the port list */
Igor Sysoeva8833612009-02-18 16:17:12 +00001199
Igor Sysoev79d630a2009-10-21 08:19:46 +00001200 port = ngx_array_push(cmcf->ports);
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001201 if (port == NULL) {
Igor Sysoeva8833612009-02-18 16:17:12 +00001202 return NGX_ERROR;
1203 }
1204
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001205 port->family = sa->sa_family;
1206 port->port = p;
1207 port->addrs.elts = NULL;
Igor Sysoeva8833612009-02-18 16:17:12 +00001208
Igor Sysoevf2694cb2009-10-21 16:47:44 +00001209 return ngx_http_add_address(cf, cscf, port, lsopt);
Igor Sysoeva8833612009-02-18 16:17:12 +00001210}
1211
1212
1213static ngx_int_t
1214ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
Igor Sysoevf2694cb2009-10-21 16:47:44 +00001215 ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt)
Igor Sysoeva8833612009-02-18 16:17:12 +00001216{
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001217 u_char *p;
1218 size_t len, off;
Igor Sysoev657b3b72009-10-22 10:17:54 +00001219 ngx_uint_t i, default_server;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001220 struct sockaddr *sa;
1221 ngx_http_conf_addr_t *addr;
Igor Sysoevbaf8e402009-10-26 11:43:32 +00001222#if (NGX_HAVE_UNIX_DOMAIN)
1223 struct sockaddr_un *saun;
1224#endif
Igor Sysoevf79878e2010-09-27 11:48:12 +00001225#if (NGX_HTTP_SSL)
1226 ngx_uint_t ssl;
1227#endif
Igor Sysoeva8833612009-02-18 16:17:12 +00001228
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001229 /*
Ruslan Ermilova823c552011-09-19 14:48:29 +00001230 * we cannot compare whole sockaddr struct's as kernel
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001231 * may fill some fields in inherited sockaddr struct's
1232 */
Igor Sysoeva8833612009-02-18 16:17:12 +00001233
Igor Sysoev8c97fa92009-12-22 15:15:45 +00001234 sa = &lsopt->u.sockaddr;
Igor Sysoeva8833612009-02-18 16:17:12 +00001235
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001236 switch (sa->sa_family) {
1237
1238#if (NGX_HAVE_INET6)
1239 case AF_INET6:
1240 off = offsetof(struct sockaddr_in6, sin6_addr);
1241 len = 16;
1242 break;
1243#endif
1244
Igor Sysoevbaf8e402009-10-26 11:43:32 +00001245#if (NGX_HAVE_UNIX_DOMAIN)
1246 case AF_UNIX:
1247 off = offsetof(struct sockaddr_un, sun_path);
1248 len = sizeof(saun->sun_path);
1249 break;
1250#endif
1251
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001252 default: /* AF_INET */
1253 off = offsetof(struct sockaddr_in, sin_addr);
1254 len = 4;
1255 break;
1256 }
1257
Igor Sysoev8c97fa92009-12-22 15:15:45 +00001258 p = lsopt->u.sockaddr_data + off;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001259
1260 addr = port->addrs.elts;
1261
1262 for (i = 0; i < port->addrs.nelts; i++) {
1263
Igor Sysoev8c97fa92009-12-22 15:15:45 +00001264 if (ngx_memcmp(p, addr[i].opt.u.sockaddr_data + off, len) != 0) {
Igor Sysoeva8833612009-02-18 16:17:12 +00001265 continue;
1266 }
1267
1268 /* the address is already in the address list */
1269
Igor Sysoev2a634f52009-10-21 16:27:48 +00001270 if (ngx_http_add_server(cf, cscf, &addr[i]) != NGX_OK) {
Igor Sysoeva8833612009-02-18 16:17:12 +00001271 return NGX_ERROR;
1272 }
1273
Igor Sysoev657b3b72009-10-22 10:17:54 +00001274 /* preserve default_server bit during listen options overwriting */
1275 default_server = addr[i].opt.default_server;
1276
Igor Sysoevf79878e2010-09-27 11:48:12 +00001277#if (NGX_HTTP_SSL)
Igor Sysoevbfec9882010-09-28 06:50:52 +00001278 ssl = lsopt->ssl || addr[i].opt.ssl;
Igor Sysoevf79878e2010-09-27 11:48:12 +00001279#endif
1280
Igor Sysoevacb43232009-10-22 08:14:02 +00001281 if (lsopt->set) {
1282
1283 if (addr[i].opt.set) {
1284 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
Ruslan Ermilovb1565cf2011-09-23 20:15:27 +00001285 "duplicate listen options for %s", addr[i].opt.addr);
Igor Sysoevacb43232009-10-22 08:14:02 +00001286 return NGX_ERROR;
1287 }
1288
1289 addr[i].opt = *lsopt;
Igor Sysoev5a950802009-10-21 19:16:38 +00001290 }
1291
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001292 /* check the duplicate "default" server for this address:port */
Igor Sysoeva8833612009-02-18 16:17:12 +00001293
Igor Sysoevf2694cb2009-10-21 16:47:44 +00001294 if (lsopt->default_server) {
Igor Sysoeva8833612009-02-18 16:17:12 +00001295
Igor Sysoev657b3b72009-10-22 10:17:54 +00001296 if (default_server) {
Igor Sysoev79d630a2009-10-21 08:19:46 +00001297 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
Igor Sysoevba3083b2009-10-21 19:13:27 +00001298 "a duplicate default server for %s", addr[i].opt.addr);
Igor Sysoeva8833612009-02-18 16:17:12 +00001299 return NGX_ERROR;
1300 }
1301
Igor Sysoev657b3b72009-10-22 10:17:54 +00001302 default_server = 1;
Igor Sysoevcd8b43c2009-10-21 16:52:10 +00001303 addr[i].default_server = cscf;
Igor Sysoeva8833612009-02-18 16:17:12 +00001304 }
1305
Igor Sysoev657b3b72009-10-22 10:17:54 +00001306 addr[i].opt.default_server = default_server;
Igor Sysoevf79878e2010-09-27 11:48:12 +00001307#if (NGX_HTTP_SSL)
1308 addr[i].opt.ssl = ssl;
1309#endif
Igor Sysoev657b3b72009-10-22 10:17:54 +00001310
Igor Sysoeva8833612009-02-18 16:17:12 +00001311 return NGX_OK;
1312 }
1313
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001314 /* add the address to the addresses list that bound to this port */
Igor Sysoeva8833612009-02-18 16:17:12 +00001315
Igor Sysoevf2694cb2009-10-21 16:47:44 +00001316 return ngx_http_add_address(cf, cscf, port, lsopt);
Igor Sysoeva8833612009-02-18 16:17:12 +00001317}
1318
1319
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001320/*
1321 * add the server address, the server names and the server core module
Igor Sysoev1daaa002009-05-17 20:13:29 +00001322 * configurations to the port list
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001323 */
1324
Igor Sysoev8184d1b2005-03-04 14:06:57 +00001325static ngx_int_t
Igor Sysoev6d14e652008-05-22 11:07:08 +00001326ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
Igor Sysoevf2694cb2009-10-21 16:47:44 +00001327 ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt)
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001328{
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001329 ngx_http_conf_addr_t *addr;
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001330
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001331 if (port->addrs.elts == NULL) {
1332 if (ngx_array_init(&port->addrs, cf->temp_pool, 4,
1333 sizeof(ngx_http_conf_addr_t))
Igor Sysoev242d1de2007-08-12 09:00:56 +00001334 != NGX_OK)
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001335 {
1336 return NGX_ERROR;
1337 }
1338 }
1339
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001340 addr = ngx_array_push(&port->addrs);
1341 if (addr == NULL) {
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001342 return NGX_ERROR;
1343 }
1344
Igor Sysoevf2694cb2009-10-21 16:47:44 +00001345 addr->opt = *lsopt;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001346 addr->hash.buckets = NULL;
1347 addr->hash.size = 0;
1348 addr->wc_head = NULL;
1349 addr->wc_tail = NULL;
Igor Sysoev43c3bf42007-08-12 19:48:12 +00001350#if (NGX_PCRE)
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001351 addr->nregex = 0;
1352 addr->regex = NULL;
Igor Sysoev43c3bf42007-08-12 19:48:12 +00001353#endif
Igor Sysoevcd8b43c2009-10-21 16:52:10 +00001354 addr->default_server = cscf;
Igor Sysoev2a634f52009-10-21 16:27:48 +00001355 addr->servers.elts = NULL;
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001356
Igor Sysoev2a634f52009-10-21 16:27:48 +00001357 return ngx_http_add_server(cf, cscf, addr);
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001358}
1359
1360
Igor Sysoev2a634f52009-10-21 16:27:48 +00001361/* add the server core module configuration to the address:port */
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001362
Igor Sysoev8184d1b2005-03-04 14:06:57 +00001363static ngx_int_t
Igor Sysoev2a634f52009-10-21 16:27:48 +00001364ngx_http_add_server(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001365 ngx_http_conf_addr_t *addr)
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001366{
Igor Sysoev315cfa02009-10-22 08:15:16 +00001367 ngx_uint_t i;
Igor Sysoev2a634f52009-10-21 16:27:48 +00001368 ngx_http_core_srv_conf_t **server;
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001369
Igor Sysoev2a634f52009-10-21 16:27:48 +00001370 if (addr->servers.elts == NULL) {
1371 if (ngx_array_init(&addr->servers, cf->temp_pool, 4,
1372 sizeof(ngx_http_core_srv_conf_t *))
Igor Sysoev242d1de2007-08-12 09:00:56 +00001373 != NGX_OK)
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001374 {
1375 return NGX_ERROR;
1376 }
Igor Sysoev315cfa02009-10-22 08:15:16 +00001377
1378 } else {
1379 server = addr->servers.elts;
1380 for (i = 0; i < addr->servers.nelts; i++) {
1381 if (server[i] == cscf) {
1382 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1383 "a duplicate listen %s", addr->opt.addr);
1384 return NGX_ERROR;
1385 }
1386 }
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001387 }
1388
Igor Sysoev2a634f52009-10-21 16:27:48 +00001389 server = ngx_array_push(&addr->servers);
1390 if (server == NULL) {
1391 return NGX_ERROR;
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001392 }
1393
Igor Sysoev2a634f52009-10-21 16:27:48 +00001394 *server = cscf;
1395
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001396 return NGX_OK;
1397}
1398
1399
Igor Sysoevde8ec1e2008-03-24 13:04:02 +00001400static ngx_int_t
Igor Sysoev6d14e652008-05-22 11:07:08 +00001401ngx_http_optimize_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001402 ngx_array_t *ports)
Igor Sysoev6d14e652008-05-22 11:07:08 +00001403{
Igor Sysoeve8568072009-10-28 10:47:00 +00001404 ngx_uint_t p, a;
Igor Sysoev2a634f52009-10-21 16:27:48 +00001405 ngx_http_conf_port_t *port;
1406 ngx_http_conf_addr_t *addr;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001407
Igor Sysoevcadac4e2009-10-28 10:45:40 +00001408 if (ports == NULL) {
1409 return NGX_OK;
1410 }
1411
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001412 port = ports->elts;
1413 for (p = 0; p < ports->nelts; p++) {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001414
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001415 ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts,
1416 sizeof(ngx_http_conf_addr_t), ngx_http_cmp_conf_addrs);
Igor Sysoev6d14e652008-05-22 11:07:08 +00001417
1418 /*
Igor Sysoeva8833612009-02-18 16:17:12 +00001419 * check whether all name-based servers have the same
Ruslan Ermilov47a04aa2012-04-03 07:37:31 +00001420 * configuration as a default server for given address:port
Igor Sysoev6d14e652008-05-22 11:07:08 +00001421 */
1422
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001423 addr = port[p].addrs.elts;
1424 for (a = 0; a < port[p].addrs.nelts; a++) {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001425
Igor Sysoev2a634f52009-10-21 16:27:48 +00001426 if (addr[a].servers.nelts > 1
Igor Sysoev7b5edd82009-03-19 16:07:40 +00001427#if (NGX_PCRE)
Igor Sysoevcd8b43c2009-10-21 16:52:10 +00001428 || addr[a].default_server->captures
Igor Sysoev7b5edd82009-03-19 16:07:40 +00001429#endif
Igor Sysoev2a634f52009-10-21 16:27:48 +00001430 )
1431 {
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001432 if (ngx_http_server_names(cf, cmcf, &addr[a]) != NGX_OK) {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001433 return NGX_ERROR;
1434 }
Igor Sysoev6d14e652008-05-22 11:07:08 +00001435 }
Igor Sysoev6d14e652008-05-22 11:07:08 +00001436 }
1437
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001438 if (ngx_http_init_listening(cf, &port[p]) != NGX_OK) {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001439 return NGX_ERROR;
1440 }
1441 }
1442
1443 return NGX_OK;
Igor Sysoeva8833612009-02-18 16:17:12 +00001444}
1445
1446
1447static ngx_int_t
1448ngx_http_server_names(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001449 ngx_http_conf_addr_t *addr)
Igor Sysoeva8833612009-02-18 16:17:12 +00001450{
Igor Sysoev2a634f52009-10-21 16:27:48 +00001451 ngx_int_t rc;
1452 ngx_uint_t n, s;
1453 ngx_hash_init_t hash;
1454 ngx_hash_keys_arrays_t ha;
1455 ngx_http_server_name_t *name;
1456 ngx_http_core_srv_conf_t **cscfp;
Igor Sysoeva8833612009-02-18 16:17:12 +00001457#if (NGX_PCRE)
Igor Sysoev2a634f52009-10-21 16:27:48 +00001458 ngx_uint_t regex, i;
Igor Sysoeva8833612009-02-18 16:17:12 +00001459
1460 regex = 0;
1461#endif
1462
1463 ngx_memzero(&ha, sizeof(ngx_hash_keys_arrays_t));
1464
1465 ha.temp_pool = ngx_create_pool(16384, cf->log);
1466 if (ha.temp_pool == NULL) {
1467 return NGX_ERROR;
1468 }
1469
1470 ha.pool = cf->pool;
1471
1472 if (ngx_hash_keys_array_init(&ha, NGX_HASH_LARGE) != NGX_OK) {
1473 goto failed;
1474 }
1475
Igor Sysoev2a634f52009-10-21 16:27:48 +00001476 cscfp = addr->servers.elts;
Igor Sysoeva8833612009-02-18 16:17:12 +00001477
Igor Sysoev2a634f52009-10-21 16:27:48 +00001478 for (s = 0; s < addr->servers.nelts; s++) {
1479
1480 name = cscfp[s]->server_names.elts;
1481
1482 for (n = 0; n < cscfp[s]->server_names.nelts; n++) {
Igor Sysoeva8833612009-02-18 16:17:12 +00001483
1484#if (NGX_PCRE)
Igor Sysoev2a634f52009-10-21 16:27:48 +00001485 if (name[n].regex) {
1486 regex++;
1487 continue;
1488 }
Igor Sysoeva8833612009-02-18 16:17:12 +00001489#endif
1490
Igor Sysoevcd8b43c2009-10-21 16:52:10 +00001491 rc = ngx_hash_add_key(&ha, &name[n].name, name[n].server,
Igor Sysoev2a634f52009-10-21 16:27:48 +00001492 NGX_HASH_WILDCARD_KEY);
Igor Sysoeva8833612009-02-18 16:17:12 +00001493
Igor Sysoev2a634f52009-10-21 16:27:48 +00001494 if (rc == NGX_ERROR) {
1495 return NGX_ERROR;
1496 }
Igor Sysoeva8833612009-02-18 16:17:12 +00001497
Igor Sysoev2a634f52009-10-21 16:27:48 +00001498 if (rc == NGX_DECLINED) {
1499 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
1500 "invalid server name or wildcard \"%V\" on %s",
1501 &name[n].name, addr->opt.addr);
1502 return NGX_ERROR;
1503 }
Igor Sysoeva8833612009-02-18 16:17:12 +00001504
Igor Sysoev2a634f52009-10-21 16:27:48 +00001505 if (rc == NGX_BUSY) {
Igor Sysoev7c2611a2010-12-12 20:11:31 +00001506 ngx_log_error(NGX_LOG_WARN, cf->log, 0,
Igor Sysoev2a634f52009-10-21 16:27:48 +00001507 "conflicting server name \"%V\" on %s, ignored",
1508 &name[n].name, addr->opt.addr);
1509 }
Igor Sysoeva8833612009-02-18 16:17:12 +00001510 }
1511 }
1512
1513 hash.key = ngx_hash_key_lc;
1514 hash.max_size = cmcf->server_names_hash_max_size;
1515 hash.bucket_size = cmcf->server_names_hash_bucket_size;
1516 hash.name = "server_names_hash";
1517 hash.pool = cf->pool;
1518
1519 if (ha.keys.nelts) {
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001520 hash.hash = &addr->hash;
Igor Sysoeva8833612009-02-18 16:17:12 +00001521 hash.temp_pool = NULL;
1522
1523 if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK) {
1524 goto failed;
1525 }
1526 }
1527
1528 if (ha.dns_wc_head.nelts) {
1529
1530 ngx_qsort(ha.dns_wc_head.elts, (size_t) ha.dns_wc_head.nelts,
1531 sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);
1532
1533 hash.hash = NULL;
1534 hash.temp_pool = ha.temp_pool;
1535
1536 if (ngx_hash_wildcard_init(&hash, ha.dns_wc_head.elts,
1537 ha.dns_wc_head.nelts)
1538 != NGX_OK)
1539 {
1540 goto failed;
1541 }
1542
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001543 addr->wc_head = (ngx_hash_wildcard_t *) hash.hash;
Igor Sysoeva8833612009-02-18 16:17:12 +00001544 }
1545
1546 if (ha.dns_wc_tail.nelts) {
1547
1548 ngx_qsort(ha.dns_wc_tail.elts, (size_t) ha.dns_wc_tail.nelts,
1549 sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);
1550
1551 hash.hash = NULL;
1552 hash.temp_pool = ha.temp_pool;
1553
1554 if (ngx_hash_wildcard_init(&hash, ha.dns_wc_tail.elts,
1555 ha.dns_wc_tail.nelts)
1556 != NGX_OK)
1557 {
1558 goto failed;
1559 }
1560
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001561 addr->wc_tail = (ngx_hash_wildcard_t *) hash.hash;
Igor Sysoeva8833612009-02-18 16:17:12 +00001562 }
1563
1564 ngx_destroy_pool(ha.temp_pool);
1565
1566#if (NGX_PCRE)
1567
1568 if (regex == 0) {
1569 return NGX_OK;
1570 }
1571
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001572 addr->nregex = regex;
1573 addr->regex = ngx_palloc(cf->pool, regex * sizeof(ngx_http_server_name_t));
1574 if (addr->regex == NULL) {
Igor Sysoeva8833612009-02-18 16:17:12 +00001575 return NGX_ERROR;
1576 }
1577
Igor Sysoev2a634f52009-10-21 16:27:48 +00001578 i = 0;
1579
1580 for (s = 0; s < addr->servers.nelts; s++) {
1581
1582 name = cscfp[s]->server_names.elts;
1583
1584 for (n = 0; n < cscfp[s]->server_names.nelts; n++) {
1585 if (name[n].regex) {
1586 addr->regex[i++] = name[n];
1587 }
Igor Sysoeva8833612009-02-18 16:17:12 +00001588 }
1589 }
1590
1591#endif
1592
1593 return NGX_OK;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001594
1595failed:
1596
1597 ngx_destroy_pool(ha.temp_pool);
1598
1599 return NGX_ERROR;
1600}
1601
1602
1603static ngx_int_t
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001604ngx_http_cmp_conf_addrs(const void *one, const void *two)
Igor Sysoev305a9d82005-12-26 17:07:48 +00001605{
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001606 ngx_http_conf_addr_t *first, *second;
Igor Sysoev305a9d82005-12-26 17:07:48 +00001607
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001608 first = (ngx_http_conf_addr_t *) one;
1609 second = (ngx_http_conf_addr_t *) two;
Igor Sysoev305a9d82005-12-26 17:07:48 +00001610
Igor Sysoevd2d09312009-10-21 08:48:04 +00001611 if (first->opt.wildcard) {
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001612 /* a wildcard address must be the last resort, shift it to the end */
Igor Sysoev305a9d82005-12-26 17:07:48 +00001613 return 1;
1614 }
1615
Igor Sysoevd2d09312009-10-21 08:48:04 +00001616 if (first->opt.bind && !second->opt.bind) {
Igor Sysoev305a9d82005-12-26 17:07:48 +00001617 /* shift explicit bind()ed addresses to the start */
1618 return -1;
1619 }
1620
Igor Sysoevd2d09312009-10-21 08:48:04 +00001621 if (!first->opt.bind && second->opt.bind) {
Igor Sysoev305a9d82005-12-26 17:07:48 +00001622 /* shift explicit bind()ed addresses to the start */
1623 return 1;
1624 }
1625
1626 /* do not sort by default */
1627
1628 return 0;
1629}
1630
1631
1632static int ngx_libc_cdecl
1633ngx_http_cmp_dns_wildcards(const void *one, const void *two)
1634{
1635 ngx_hash_key_t *first, *second;
1636
1637 first = (ngx_hash_key_t *) one;
1638 second = (ngx_hash_key_t *) two;
1639
Igor Sysoev96e36ef2009-09-12 09:28:37 +00001640 return ngx_dns_strcmp(first->key.data, second->key.data);
Igor Sysoev305a9d82005-12-26 17:07:48 +00001641}
Igor Sysoev6d14e652008-05-22 11:07:08 +00001642
1643
1644static ngx_int_t
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001645ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port)
Igor Sysoev6d14e652008-05-22 11:07:08 +00001646{
Igor Sysoev1966aed2009-02-24 07:29:55 +00001647 ngx_uint_t i, last, bind_wildcard;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001648 ngx_listening_t *ls;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001649 ngx_http_port_t *hport;
1650 ngx_http_conf_addr_t *addr;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001651
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001652 addr = port->addrs.elts;
1653 last = port->addrs.nelts;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001654
1655 /*
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001656 * If there is a binding to an "*:port" then we need to bind() to
1657 * the "*:port" only and ignore other implicit bindings. The bindings
1658 * have been already sorted: explicit bindings are on the start, then
1659 * implicit bindings go, and wildcard binding is in the end.
Igor Sysoev6d14e652008-05-22 11:07:08 +00001660 */
1661
Igor Sysoevd2d09312009-10-21 08:48:04 +00001662 if (addr[last - 1].opt.wildcard) {
1663 addr[last - 1].opt.bind = 1;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001664 bind_wildcard = 1;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001665
1666 } else {
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001667 bind_wildcard = 0;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001668 }
1669
Igor Sysoev1966aed2009-02-24 07:29:55 +00001670 i = 0;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001671
Igor Sysoev1966aed2009-02-24 07:29:55 +00001672 while (i < last) {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001673
Igor Sysoevd2d09312009-10-21 08:48:04 +00001674 if (bind_wildcard && !addr[i].opt.bind) {
Igor Sysoev1966aed2009-02-24 07:29:55 +00001675 i++;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001676 continue;
1677 }
1678
Igor Sysoev1966aed2009-02-24 07:29:55 +00001679 ls = ngx_http_add_listening(cf, &addr[i]);
Igor Sysoev6d14e652008-05-22 11:07:08 +00001680 if (ls == NULL) {
1681 return NGX_ERROR;
1682 }
1683
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001684 hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t));
1685 if (hport == NULL) {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001686 return NGX_ERROR;
1687 }
1688
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001689 ls->servers = hport;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001690
Igor Sysoev1966aed2009-02-24 07:29:55 +00001691 if (i == last - 1) {
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001692 hport->naddrs = last;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001693
1694 } else {
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001695 hport->naddrs = 1;
Igor Sysoev1966aed2009-02-24 07:29:55 +00001696 i = 0;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001697 }
1698
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001699 switch (ls->sockaddr->sa_family) {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001700
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001701#if (NGX_HAVE_INET6)
1702 case AF_INET6:
1703 if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) {
Igor Sysoev6d14e652008-05-22 11:07:08 +00001704 return NGX_ERROR;
1705 }
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001706 break;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001707#endif
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001708 default: /* AF_INET */
1709 if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) {
1710 return NGX_ERROR;
1711 }
1712 break;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001713 }
1714
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001715 addr++;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001716 last--;
Igor Sysoev6d14e652008-05-22 11:07:08 +00001717 }
1718
1719 return NGX_OK;
1720}
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00001721
1722
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001723static ngx_listening_t *
1724ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)
1725{
1726 ngx_listening_t *ls;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001727 ngx_http_core_loc_conf_t *clcf;
1728 ngx_http_core_srv_conf_t *cscf;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001729
Igor Sysoev8c97fa92009-12-22 15:15:45 +00001730 ls = ngx_create_listening(cf, &addr->opt.u.sockaddr, addr->opt.socklen);
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001731 if (ls == NULL) {
1732 return NULL;
1733 }
1734
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001735 ls->addr_ntop = 1;
1736
1737 ls->handler = ngx_http_init_connection;
1738
Igor Sysoevcd8b43c2009-10-21 16:52:10 +00001739 cscf = addr->default_server;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001740 ls->pool_size = cscf->connection_pool_size;
1741 ls->post_accept_timeout = cscf->client_header_timeout;
1742
1743 clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];
1744
Igor Sysoev0cd76ea2009-04-30 13:53:42 +00001745 ls->logp = clcf->error_log;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001746 ls->log.data = &ls->addr_text;
1747 ls->log.handler = ngx_accept_log_error;
1748
1749#if (NGX_WIN32)
1750 {
Maxim Dounin5cc90f32011-09-27 12:07:09 +00001751 ngx_iocp_conf_t *iocpcf = NULL;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001752
Maxim Dounin5cc90f32011-09-27 12:07:09 +00001753 if (ngx_get_conf(cf->cycle->conf_ctx, ngx_events_module)) {
1754 iocpcf = ngx_event_get_conf(cf->cycle->conf_ctx, ngx_iocp_module);
1755 }
1756 if (iocpcf && iocpcf->acceptex_read) {
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001757 ls->post_accept_buffer_size = cscf->client_header_buffer_size;
1758 }
1759 }
1760#endif
1761
Igor Sysoev79d630a2009-10-21 08:19:46 +00001762 ls->backlog = addr->opt.backlog;
1763 ls->rcvbuf = addr->opt.rcvbuf;
1764 ls->sndbuf = addr->opt.sndbuf;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001765
Valentin Bartenev92edf472011-12-05 08:06:15 +00001766 ls->keepalive = addr->opt.so_keepalive;
1767#if (NGX_HAVE_KEEPALIVE_TUNABLE)
1768 ls->keepidle = addr->opt.tcp_keepidle;
1769 ls->keepintvl = addr->opt.tcp_keepintvl;
1770 ls->keepcnt = addr->opt.tcp_keepcnt;
1771#endif
1772
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001773#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
Igor Sysoev79d630a2009-10-21 08:19:46 +00001774 ls->accept_filter = addr->opt.accept_filter;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001775#endif
1776
1777#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
Igor Sysoev79d630a2009-10-21 08:19:46 +00001778 ls->deferred_accept = addr->opt.deferred_accept;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001779#endif
1780
Igor Sysoev6d94b512009-03-13 14:20:34 +00001781#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
Igor Sysoev79d630a2009-10-21 08:19:46 +00001782 ls->ipv6only = addr->opt.ipv6only;
Igor Sysoev6d94b512009-03-13 14:20:34 +00001783#endif
1784
Igor Sysoev0bd7a7d2010-07-05 13:49:16 +00001785#if (NGX_HAVE_SETFIB)
1786 ls->setfib = addr->opt.setfib;
1787#endif
1788
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001789 return ls;
1790}
1791
1792
1793static ngx_int_t
1794ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport,
1795 ngx_http_conf_addr_t *addr)
1796{
1797 ngx_uint_t i;
1798 ngx_http_in_addr_t *addrs;
1799 struct sockaddr_in *sin;
1800 ngx_http_virtual_names_t *vn;
1801
1802 hport->addrs = ngx_pcalloc(cf->pool,
1803 hport->naddrs * sizeof(ngx_http_in_addr_t));
1804 if (hport->addrs == NULL) {
1805 return NGX_ERROR;
1806 }
1807
1808 addrs = hport->addrs;
1809
1810 for (i = 0; i < hport->naddrs; i++) {
1811
Igor Sysoev8c97fa92009-12-22 15:15:45 +00001812 sin = &addr[i].opt.u.sockaddr_in;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001813 addrs[i].addr = sin->sin_addr.s_addr;
Igor Sysoevcd8b43c2009-10-21 16:52:10 +00001814 addrs[i].conf.default_server = addr[i].default_server;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001815#if (NGX_HTTP_SSL)
Igor Sysoevd2d09312009-10-21 08:48:04 +00001816 addrs[i].conf.ssl = addr[i].opt.ssl;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001817#endif
1818
1819 if (addr[i].hash.buckets == NULL
1820 && (addr[i].wc_head == NULL
1821 || addr[i].wc_head->hash.buckets == NULL)
Igor Sysoevfb3be732009-03-19 15:46:27 +00001822 && (addr[i].wc_tail == NULL
Igor Sysoev7b5edd82009-03-19 16:07:40 +00001823 || addr[i].wc_tail->hash.buckets == NULL)
1824#if (NGX_PCRE)
1825 && addr[i].nregex == 0
1826#endif
1827 )
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001828 {
1829 continue;
1830 }
1831
1832 vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
1833 if (vn == NULL) {
1834 return NGX_ERROR;
1835 }
1836
Igor Sysoeve4694392009-04-09 13:56:16 +00001837 addrs[i].conf.virtual_names = vn;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001838
1839 vn->names.hash = addr[i].hash;
1840 vn->names.wc_head = addr[i].wc_head;
1841 vn->names.wc_tail = addr[i].wc_tail;
1842#if (NGX_PCRE)
1843 vn->nregex = addr[i].nregex;
1844 vn->regex = addr[i].regex;
1845#endif
1846 }
1847
1848 return NGX_OK;
1849}
1850
1851
1852#if (NGX_HAVE_INET6)
1853
1854static ngx_int_t
1855ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport,
1856 ngx_http_conf_addr_t *addr)
1857{
1858 ngx_uint_t i;
1859 ngx_http_in6_addr_t *addrs6;
1860 struct sockaddr_in6 *sin6;
1861 ngx_http_virtual_names_t *vn;
1862
1863 hport->addrs = ngx_pcalloc(cf->pool,
1864 hport->naddrs * sizeof(ngx_http_in6_addr_t));
1865 if (hport->addrs == NULL) {
1866 return NGX_ERROR;
1867 }
1868
1869 addrs6 = hport->addrs;
1870
1871 for (i = 0; i < hport->naddrs; i++) {
1872
Igor Sysoev8c97fa92009-12-22 15:15:45 +00001873 sin6 = &addr[i].opt.u.sockaddr_in6;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001874 addrs6[i].addr6 = sin6->sin6_addr;
Igor Sysoevcd8b43c2009-10-21 16:52:10 +00001875 addrs6[i].conf.default_server = addr[i].default_server;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001876#if (NGX_HTTP_SSL)
Igor Sysoevd2d09312009-10-21 08:48:04 +00001877 addrs6[i].conf.ssl = addr[i].opt.ssl;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001878#endif
1879
1880 if (addr[i].hash.buckets == NULL
1881 && (addr[i].wc_head == NULL
1882 || addr[i].wc_head->hash.buckets == NULL)
Igor Sysoev1fdb0042010-12-12 21:10:59 +00001883 && (addr[i].wc_tail == NULL
Igor Sysoev5644c432010-12-12 21:13:27 +00001884 || addr[i].wc_tail->hash.buckets == NULL)
1885#if (NGX_PCRE)
1886 && addr[i].nregex == 0
1887#endif
1888 )
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001889 {
1890 continue;
1891 }
1892
1893 vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
1894 if (vn == NULL) {
1895 return NGX_ERROR;
1896 }
1897
Igor Sysoeve4694392009-04-09 13:56:16 +00001898 addrs6[i].conf.virtual_names = vn;
Igor Sysoeva35eacc2009-02-21 07:02:02 +00001899
1900 vn->names.hash = addr[i].hash;
1901 vn->names.wc_head = addr[i].wc_head;
1902 vn->names.wc_tail = addr[i].wc_tail;
1903#if (NGX_PCRE)
1904 vn->nregex = addr[i].nregex;
1905 vn->regex = addr[i].regex;
1906#endif
1907 }
1908
1909 return NGX_OK;
1910}
1911
1912#endif
1913
1914
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00001915char *
1916ngx_http_types_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1917{
1918 char *p = conf;
1919
1920 ngx_array_t **types;
1921 ngx_str_t *value, *default_type;
1922 ngx_uint_t i, n, hash;
1923 ngx_hash_key_t *type;
1924
1925 types = (ngx_array_t **) (p + cmd->offset);
1926
Igor Sysoev1cfb9722009-11-30 13:15:10 +00001927 if (*types == (void *) -1) {
1928 return NGX_CONF_OK;
1929 }
1930
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00001931 default_type = cmd->post;
1932
1933 if (*types == NULL) {
1934 *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t));
1935 if (*types == NULL) {
1936 return NGX_CONF_ERROR;
1937 }
1938
1939 if (default_type) {
1940 type = ngx_array_push(*types);
1941 if (type == NULL) {
1942 return NGX_CONF_ERROR;
1943 }
1944
1945 type->key = *default_type;
1946 type->key_hash = ngx_hash_key(default_type->data,
1947 default_type->len);
1948 type->value = (void *) 4;
1949 }
1950 }
1951
1952 value = cf->args->elts;
1953
1954 for (i = 1; i < cf->args->nelts; i++) {
1955
Igor Sysoev1cfb9722009-11-30 13:15:10 +00001956 if (value[i].len == 1 && value[i].data[0] == '*') {
1957 *types = (void *) -1;
1958 return NGX_CONF_OK;
1959 }
1960
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00001961 hash = ngx_hash_strlow(value[i].data, value[i].data, value[i].len);
1962 value[i].data[value[i].len] = '\0';
1963
1964 type = (*types)->elts;
1965 for (n = 0; n < (*types)->nelts; n++) {
1966
1967 if (ngx_strcmp(value[i].data, type[n].key.data) == 0) {
1968 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1969 "duplicate MIME type \"%V\"", &value[i]);
1970 continue;
1971 }
1972 }
1973
1974 type = ngx_array_push(*types);
1975 if (type == NULL) {
1976 return NGX_CONF_ERROR;
1977 }
1978
1979 type->key = value[i];
1980 type->key_hash = hash;
1981 type->value = (void *) 4;
1982 }
1983
1984 return NGX_CONF_OK;
1985}
1986
1987
1988char *
Igor Sysoev1cfb9722009-11-30 13:15:10 +00001989ngx_http_merge_types(ngx_conf_t *cf, ngx_array_t **keys, ngx_hash_t *types_hash,
1990 ngx_array_t **prev_keys, ngx_hash_t *prev_types_hash,
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00001991 ngx_str_t *default_types)
1992{
1993 ngx_hash_init_t hash;
1994
Igor Sysoev1cfb9722009-11-30 13:15:10 +00001995 if (*keys) {
1996
1997 if (*keys == (void *) -1) {
1998 return NGX_CONF_OK;
1999 }
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00002000
Igor Sysoevc71e3d82008-08-13 16:25:48 +00002001 hash.hash = 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
Igor Sysoev1cfb9722009-11-30 13:15:10 +00002009 if (ngx_hash_init(&hash, (*keys)->elts, (*keys)->nelts) != NGX_OK) {
Igor Sysoevc71e3d82008-08-13 16:25:48 +00002010 return NGX_CONF_ERROR;
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00002011 }
2012
Igor Sysoevc71e3d82008-08-13 16:25:48 +00002013 return NGX_CONF_OK;
2014 }
2015
2016 if (prev_types_hash->buckets == NULL) {
2017
Igor Sysoev1cfb9722009-11-30 13:15:10 +00002018 if (*prev_keys == NULL) {
Igor Sysoevc71e3d82008-08-13 16:25:48 +00002019
Igor Sysoev1cfb9722009-11-30 13:15:10 +00002020 if (ngx_http_set_default_types(cf, prev_keys, default_types)
Igor Sysoevc71e3d82008-08-13 16:25:48 +00002021 != NGX_OK)
2022 {
Igor Sysoev0c16f732008-09-01 14:05:20 +00002023 return NGX_CONF_ERROR;
2024 }
Igor Sysoev1cfb9722009-11-30 13:15:10 +00002025
2026 } else if (*prev_keys == (void *) -1) {
2027 *keys = *prev_keys;
2028 return NGX_CONF_OK;
Igor Sysoevc71e3d82008-08-13 16:25:48 +00002029 }
2030
2031 hash.hash = prev_types_hash;
2032 hash.key = NULL;
2033 hash.max_size = 2048;
2034 hash.bucket_size = 64;
2035 hash.name = "test_types_hash";
2036 hash.pool = cf->pool;
2037 hash.temp_pool = NULL;
2038
Igor Sysoev1cfb9722009-11-30 13:15:10 +00002039 if (ngx_hash_init(&hash, (*prev_keys)->elts, (*prev_keys)->nelts)
2040 != NGX_OK)
2041 {
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00002042 return NGX_CONF_ERROR;
2043 }
2044 }
2045
Igor Sysoevc71e3d82008-08-13 16:25:48 +00002046 *types_hash = *prev_types_hash;
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00002047
2048 return NGX_CONF_OK;
2049
2050}
2051
2052
Igor Sysoevc71e3d82008-08-13 16:25:48 +00002053ngx_int_t
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00002054ngx_http_set_default_types(ngx_conf_t *cf, ngx_array_t **types,
2055 ngx_str_t *default_type)
2056{
2057 ngx_hash_key_t *type;
2058
2059 *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t));
2060 if (*types == NULL) {
Igor Sysoevc71e3d82008-08-13 16:25:48 +00002061 return NGX_ERROR;
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00002062 }
2063
2064 while (default_type->len) {
2065
2066 type = ngx_array_push(*types);
2067 if (type == NULL) {
Igor Sysoevc71e3d82008-08-13 16:25:48 +00002068 return NGX_ERROR;
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00002069 }
2070
2071 type->key = *default_type;
2072 type->key_hash = ngx_hash_key(default_type->data,
2073 default_type->len);
2074 type->value = (void *) 4;
2075
2076 default_type++;
2077 }
2078
Igor Sysoevc71e3d82008-08-13 16:25:48 +00002079 return NGX_OK;
Igor Sysoevb5bc3f92008-08-04 11:29:09 +00002080}