From: Igor Sysoev Date: Thu, 22 May 2008 11:07:08 +0000 (+0000) Subject: split ngx_http_block() further X-Git-Tag: release-0.7.1~11 X-Git-Url: http://www.kaiwu.me/postgresql/commit/?a=commitdiff_plain;h=6d14e650563beb06544904340e0ca3d570ad550a;p=nginx.git split ngx_http_block() further --- diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c index 3d8a583cd..6be66715e 100644 --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -17,18 +17,28 @@ static ngx_int_t ngx_http_init_headers_in_hash(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf); static ngx_int_t ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf); + +static ngx_int_t ngx_http_init_server_lists(ngx_conf_t *cf, + ngx_array_t *servers, ngx_array_t *in_ports); static ngx_int_t ngx_http_add_address(ngx_conf_t *cf, - ngx_http_conf_in_port_t *in_port, ngx_http_listen_t *lscf, - ngx_http_core_srv_conf_t *cscf); + ngx_http_core_srv_conf_t *cscf, ngx_http_conf_in_port_t *in_port, + ngx_http_listen_t *listen); static ngx_int_t ngx_http_add_names(ngx_conf_t *cf, - ngx_http_conf_in_addr_t *in_addr, ngx_http_core_srv_conf_t *cscf); + ngx_http_core_srv_conf_t *cscf, ngx_http_conf_in_addr_t *in_addr); + static char *ngx_http_merge_locations(ngx_conf_t *cf, ngx_array_t *locations, void **loc_conf, ngx_http_module_t *module, ngx_uint_t ctx_index); + +static ngx_int_t ngx_http_optimize_servers(ngx_conf_t *cf, + ngx_http_core_main_conf_t *cmcf, ngx_array_t *in_ports); static ngx_int_t ngx_http_cmp_conf_in_addrs(const void *one, const void *two); static int ngx_libc_cdecl ngx_http_cmp_dns_wildcards(const void *one, const void *two); +static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf, + ngx_http_conf_in_port_t *in_port); + ngx_uint_t ngx_http_max_module; ngx_uint_t ngx_http_total_requests; @@ -79,28 +89,13 @@ static char * ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; - ngx_int_t rc; - ngx_uint_t mi, m, s, l, p, a, i; - ngx_uint_t last, bind_all, done; + ngx_uint_t mi, m, s; ngx_conf_t pcf; ngx_array_t in_ports; - ngx_hash_init_t hash; - ngx_listening_t *ls; - ngx_http_listen_t *lscf; ngx_http_module_t *module; - ngx_http_in_port_t *hip; ngx_http_conf_ctx_t *ctx; - ngx_http_conf_in_port_t *in_port; - ngx_http_conf_in_addr_t *in_addr; - ngx_hash_keys_arrays_t ha; - ngx_http_server_name_t *name; - ngx_http_virtual_names_t *vn; - ngx_http_core_srv_conf_t **cscfp, *cscf; - ngx_http_core_loc_conf_t *clcf; + ngx_http_core_srv_conf_t **cscfp; ngx_http_core_main_conf_t *cmcf; -#if (NGX_PCRE) - ngx_uint_t regex; -#endif /* the main http context */ @@ -328,32 +323,265 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) /* * create the lists of ports, addresses and server names - * to quickly find the server core module configuration at run-time + * to find quickly the server core module configuration at run-time */ - if (ngx_array_init(&in_ports, cf->temp_pool, 2, + /* AF_INET only */ + + if (ngx_http_init_server_lists(cf, &cmcf->servers, &in_ports) != NGX_OK) { + return NGX_CONF_ERROR; + } + + + /* optimize the lists of ports, addresses and server names */ + + /* AF_INET only */ + + if (ngx_http_optimize_servers(cf, cmcf, &in_ports) != NGX_OK) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + + +static ngx_int_t +ngx_http_init_phases(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf) +{ + if (ngx_array_init(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers, + cf->pool, 1, sizeof(ngx_http_handler_pt)) + != NGX_OK) + { + return NGX_ERROR; + } + + if (ngx_array_init(&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers, + cf->pool, 1, sizeof(ngx_http_handler_pt)) + != NGX_OK) + { + return NGX_ERROR; + } + + if (ngx_array_init(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers, + cf->pool, 1, sizeof(ngx_http_handler_pt)) + != NGX_OK) + { + return NGX_ERROR; + } + + if (ngx_array_init(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers, + cf->pool, 1, sizeof(ngx_http_handler_pt)) + != NGX_OK) + { + return NGX_ERROR; + } + + if (ngx_array_init(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers, + cf->pool, 2, sizeof(ngx_http_handler_pt)) + != NGX_OK) + { + return NGX_ERROR; + } + + if (ngx_array_init(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers, + cf->pool, 4, sizeof(ngx_http_handler_pt)) + != NGX_OK) + { + return NGX_ERROR; + } + + if (ngx_array_init(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers, + cf->pool, 1, sizeof(ngx_http_handler_pt)) + != NGX_OK) + { + return NGX_ERROR; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_init_headers_in_hash(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf) +{ + ngx_array_t headers_in; + ngx_hash_key_t *hk; + ngx_hash_init_t hash; + ngx_http_header_t *header; + + if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t)) + != NGX_OK) + { + return NGX_ERROR; + } + + for (header = ngx_http_headers_in; header->name.len; header++) { + hk = ngx_array_push(&headers_in); + if (hk == NULL) { + return NGX_ERROR; + } + + hk->key = header->name; + hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len); + hk->value = header; + } + + hash.hash = &cmcf->headers_in_hash; + hash.key = ngx_hash_key_lc; + hash.max_size = 512; + hash.bucket_size = ngx_align(64, ngx_cacheline_size); + hash.name = "headers_in_hash"; + hash.pool = cf->pool; + hash.temp_pool = NULL; + + if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) { + return NGX_ERROR; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf) +{ + ngx_int_t j; + ngx_uint_t i, n; + ngx_uint_t find_config_index, use_rewrite, use_access; + ngx_http_handler_pt *h; + ngx_http_phase_handler_t *ph; + ngx_http_phase_handler_pt checker; + + cmcf->phase_engine.server_rewrite_index = (ngx_uint_t) -1; + cmcf->phase_engine.location_rewrite_index = (ngx_uint_t) -1; + find_config_index = 0; + use_rewrite = cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers.nelts ? 1 : 0; + use_access = cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers.nelts ? 1 : 0; + + n = use_rewrite + use_access + 1; /* find config phase */ + + for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) { + n += cmcf->phases[i].handlers.nelts; + } + + ph = ngx_pcalloc(cf->pool, + n * sizeof(ngx_http_phase_handler_t) + sizeof(void *)); + if (ph == NULL) { + return NGX_ERROR; + } + + cmcf->phase_engine.handlers = ph; + n = 0; + + for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) { + h = cmcf->phases[i].handlers.elts; + + switch (i) { + + case NGX_HTTP_SERVER_REWRITE_PHASE: + if (cmcf->phase_engine.server_rewrite_index == (ngx_uint_t) -1) { + cmcf->phase_engine.server_rewrite_index = n; + } + checker = ngx_http_core_generic_phase; + + break; + + case NGX_HTTP_FIND_CONFIG_PHASE: + find_config_index = n; + + ph->checker = ngx_http_core_find_config_phase; + n++; + ph++; + + continue; + + case NGX_HTTP_REWRITE_PHASE: + if (cmcf->phase_engine.location_rewrite_index == (ngx_uint_t) -1) { + cmcf->phase_engine.location_rewrite_index = n; + } + checker = ngx_http_core_generic_phase; + + break; + + case NGX_HTTP_POST_REWRITE_PHASE: + if (use_rewrite) { + ph->checker = ngx_http_core_post_rewrite_phase; + ph->next = find_config_index; + n++; + ph++; + } + + continue; + + case NGX_HTTP_ACCESS_PHASE: + checker = ngx_http_core_access_phase; + n++; + break; + + case NGX_HTTP_POST_ACCESS_PHASE: + if (use_access) { + ph->checker = ngx_http_core_post_access_phase; + ph->next = n; + ph++; + } + + continue; + + case NGX_HTTP_CONTENT_PHASE: + checker = ngx_http_core_content_phase; + break; + + default: + checker = ngx_http_core_generic_phase; + } + + n += cmcf->phases[i].handlers.nelts; + + for (j = cmcf->phases[i].handlers.nelts - 1; j >=0; j--) { + ph->checker = checker; + ph->handler = h[j]; + ph->next = n; + ph++; + } + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_init_server_lists(ngx_conf_t *cf, ngx_array_t *servers, + ngx_array_t *in_ports) +{ + ngx_uint_t s, l, p, a; + ngx_http_listen_t *listen; + ngx_http_conf_in_port_t *in_port; + ngx_http_conf_in_addr_t *in_addr; + ngx_http_core_srv_conf_t **cscfp; + + if (ngx_array_init(in_ports, cf->temp_pool, 2, sizeof(ngx_http_conf_in_port_t)) != NGX_OK) { - return NGX_CONF_ERROR; + return NGX_ERROR; } /* "server" directives */ - cscfp = cmcf->servers.elts; - for (s = 0; s < cmcf->servers.nelts; s++) { + cscfp = servers->elts; + for (s = 0; s < servers->nelts; s++) { /* "listen" directives */ - lscf = cscfp[s]->listen.elts; + listen = cscfp[s]->listen.elts; for (l = 0; l < cscfp[s]->listen.nelts; l++) { /* AF_INET only */ - in_port = in_ports.elts; - for (p = 0; p < in_ports.nelts; p++) { + in_port = in_ports->elts; + for (p = 0; p < in_ports->nelts; p++) { - if (lscf[l].port != in_port[p].port) { + if (listen[l].port != in_port[p].port) { continue; } @@ -362,15 +590,15 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) in_addr = in_port[p].addrs.elts; for (a = 0; a < in_port[p].addrs.nelts; a++) { - if (lscf[l].addr != in_addr[a].addr) { + if (listen[l].addr != in_addr[a].addr) { continue; } /* the address is already in the address list */ - if (ngx_http_add_names(cf, &in_addr[a], cscfp[s]) != NGX_OK) + if (ngx_http_add_names(cf, cscfp[s], &in_addr[a]) != NGX_OK) { - return NGX_CONF_ERROR; + return NGX_ERROR; } /* @@ -378,14 +606,14 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) * for this address:port */ - if (lscf[l].conf.default_server) { + if (listen[l].conf.default_server) { if (in_addr[a].default_server) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "the duplicate default server in %s:%ui", - lscf[l].file_name, lscf[l].line); + listen[l].file_name, listen[l].line); - return NGX_CONF_ERROR; + return NGX_ERROR; } in_addr[a].core_srv_conf = cscfp[s]; @@ -400,10 +628,10 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) * bound to this port */ - if (ngx_http_add_address(cf, &in_port[p], &lscf[l], cscfp[s]) + if (ngx_http_add_address(cf, cscfp[s], &in_port[p], &listen[l]) != NGX_OK) { - return NGX_CONF_ERROR; + return NGX_ERROR; } goto found; @@ -411,17 +639,18 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) /* add the port to the in_port list */ - in_port = ngx_array_push(&in_ports); + in_port = ngx_array_push(in_ports); if (in_port == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } - in_port->port = lscf[l].port; + in_port->port = listen[l].port; in_port->addrs.elts = NULL; - if (ngx_http_add_address(cf, in_port, &lscf[l], cscfp[s]) != NGX_OK) + if (ngx_http_add_address(cf, cscfp[s], in_port, &listen[l]) + != NGX_OK) { - return NGX_CONF_ERROR; + return NGX_ERROR; } found: @@ -430,16 +659,160 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } } + return NGX_OK; +} - /* optimize the lists of ports, addresses and server names */ - /* AF_INET only */ +/* + * add the server address, the server names and the server core module + * configurations to the port (in_port) + */ - in_port = in_ports.elts; - for (p = 0; p < in_ports.nelts; p++) { +static ngx_int_t +ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, + ngx_http_conf_in_port_t *in_port, ngx_http_listen_t *listen) +{ + ngx_http_conf_in_addr_t *in_addr; - ngx_sort(in_port[p].addrs.elts, (size_t) in_port[p].addrs.nelts, - sizeof(ngx_http_conf_in_addr_t), ngx_http_cmp_conf_in_addrs); + if (in_port->addrs.elts == NULL) { + if (ngx_array_init(&in_port->addrs, cf->temp_pool, 4, + sizeof(ngx_http_conf_in_addr_t)) + != NGX_OK) + { + return NGX_ERROR; + } + } + + in_addr = ngx_array_push(&in_port->addrs); + if (in_addr == NULL) { + return NGX_ERROR; + } + + in_addr->addr = listen->addr; + in_addr->hash.buckets = NULL; + in_addr->hash.size = 0; + in_addr->wc_head = NULL; + in_addr->wc_tail = NULL; + in_addr->names.elts = NULL; +#if (NGX_PCRE) + in_addr->nregex = 0; + in_addr->regex = NULL; +#endif + in_addr->core_srv_conf = cscf; + in_addr->default_server = listen->conf.default_server; + in_addr->bind = listen->conf.bind; + in_addr->listen_conf = &listen->conf; + +#if (NGX_DEBUG) + { + u_char text[20]; + ngx_inet_ntop(AF_INET, &in_addr->addr, text, 20); + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0, "address: %s:%d", + text, in_port->port); + } +#endif + + return ngx_http_add_names(cf, cscf, in_addr); +} + + +/* + * add the server names and the server core module + * configurations to the address:port (in_addr) + */ + +static ngx_int_t +ngx_http_add_names(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, + ngx_http_conf_in_addr_t *in_addr) +{ + ngx_uint_t i, n; + ngx_http_server_name_t *server_names, *name; + + if (in_addr->names.elts == NULL) { + if (ngx_array_init(&in_addr->names, cf->temp_pool, 4, + sizeof(ngx_http_server_name_t)) + != NGX_OK) + { + return NGX_ERROR; + } + } + + server_names = cscf->server_names.elts; + + for (i = 0; i < cscf->server_names.nelts; i++) { + + for (n = 0; n < server_names[i].name.len; n++) { + server_names[i].name.data[n] = + ngx_tolower(server_names[i].name.data[n]); + } + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0, + "name: %V", &server_names[i].name); + + name = ngx_array_push(&in_addr->names); + if (name == NULL) { + return NGX_ERROR; + } + + *name = server_names[i]; + } + + return NGX_OK; +} + + +static char * +ngx_http_merge_locations(ngx_conf_t *cf, ngx_array_t *locations, + void **loc_conf, ngx_http_module_t *module, ngx_uint_t ctx_index) +{ + char *rv; + ngx_uint_t i; + ngx_http_core_loc_conf_t **clcfp; + + clcfp = locations->elts; + + for (i = 0; i < locations->nelts; i++) { + rv = module->merge_loc_conf(cf, loc_conf[ctx_index], + clcfp[i]->loc_conf[ctx_index]); + if (rv != NGX_CONF_OK) { + return rv; + } + + if (clcfp[i]->locations == NULL) { + continue; + } + + rv = ngx_http_merge_locations(cf, clcfp[i]->locations, + clcfp[i]->loc_conf, module, ctx_index); + if (rv != NGX_CONF_OK) { + return rv; + } + } + + return NGX_CONF_OK; +} + + +static ngx_int_t +ngx_http_optimize_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf, + ngx_array_t *in_ports) +{ + ngx_int_t rc; + ngx_uint_t s, p, a, i; + ngx_hash_init_t hash; + ngx_http_server_name_t *name; + ngx_hash_keys_arrays_t ha; + ngx_http_conf_in_port_t *in_port; + ngx_http_conf_in_addr_t *in_addr; +#if (NGX_PCRE) + ngx_uint_t regex; +#endif + + in_port = in_ports->elts; + for (p = 0; p < in_ports->nelts; p++) { + + ngx_sort(in_port[p].addrs.elts, (size_t) in_port[p].addrs.nelts, + sizeof(ngx_http_conf_in_addr_t), ngx_http_cmp_conf_in_addrs); /* * check whether all name-based servers have the same configuraiton @@ -477,14 +850,13 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ha.temp_pool = ngx_create_pool(16384, cf->log); if (ha.temp_pool == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } ha.pool = cf->pool; if (ngx_hash_keys_array_init(&ha, NGX_HASH_LARGE) != NGX_OK) { - ngx_destroy_pool(ha.temp_pool); - return NGX_CONF_ERROR; + goto failed; } #if (NGX_PCRE) @@ -506,14 +878,14 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) NGX_HASH_WILDCARD_KEY); if (rc == NGX_ERROR) { - return NGX_CONF_ERROR; + return NGX_ERROR; } if (rc == NGX_DECLINED) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "invalid server name or wildcard \"%V\" on %s", &name[s].name, in_addr[a].listen_conf->addr); - return NGX_CONF_ERROR; + return NGX_ERROR; } if (rc == NGX_BUSY) { @@ -535,8 +907,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK) { - ngx_destroy_pool(ha.temp_pool); - return NGX_CONF_ERROR; + goto failed; } } @@ -554,8 +925,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ha.dns_wc_head.nelts) != NGX_OK) { - ngx_destroy_pool(ha.temp_pool); - return NGX_CONF_ERROR; + goto failed; } in_addr[a].wc_head = (ngx_hash_wildcard_t *) hash.hash; @@ -575,8 +945,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ha.dns_wc_tail.nelts) != NGX_OK) { - ngx_destroy_pool(ha.temp_pool); - return NGX_CONF_ERROR; + goto failed; } in_addr[a].wc_tail = (ngx_hash_wildcard_t *) hash.hash; @@ -595,7 +964,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) regex * sizeof(ngx_http_server_name_t)); if (in_addr[a].regex == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } for (i = 0, s = 0; s < in_addr[a].names.nelts; s++) { @@ -606,534 +975,219 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) #endif } - in_addr = in_port[p].addrs.elts; - last = in_port[p].addrs.nelts; - - /* - * if there is the binding to the "*:port" then we need to bind() - * to the "*:port" only and ignore the other bindings - */ + if (ngx_http_init_listening(cf, &in_port[p]) != NGX_OK) { + return NGX_ERROR; + } + } - if (in_addr[last - 1].addr == INADDR_ANY) { - in_addr[last - 1].bind = 1; - bind_all = 0; + return NGX_OK; - } else { - bind_all = 1; - } +failed: - for (a = 0; a < last; /* void */ ) { + ngx_destroy_pool(ha.temp_pool); - if (!bind_all && !in_addr[a].bind) { - a++; - continue; - } + return NGX_ERROR; +} - ls = ngx_listening_inet_stream_socket(cf, in_addr[a].addr, - in_port[p].port); - if (ls == NULL) { - return NGX_CONF_ERROR; - } - ls->addr_ntop = 1; +static ngx_int_t +ngx_http_cmp_conf_in_addrs(const void *one, const void *two) +{ + ngx_http_conf_in_addr_t *first, *second; - ls->handler = ngx_http_init_connection; + first = (ngx_http_conf_in_addr_t *) one; + second = (ngx_http_conf_in_addr_t *) two; - cscf = in_addr[a].core_srv_conf; - ls->pool_size = cscf->connection_pool_size; - ls->post_accept_timeout = cscf->client_header_timeout; + if (first->addr == INADDR_ANY) { + /* the INADDR_ANY must be the last resort, shift it to the end */ + return 1; + } - clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index]; + if (first->bind && !second->bind) { + /* shift explicit bind()ed addresses to the start */ + return -1; + } - ls->log = *clcf->err_log; - ls->log.data = &ls->addr_text; - ls->log.handler = ngx_accept_log_error; + if (!first->bind && second->bind) { + /* shift explicit bind()ed addresses to the start */ + return 1; + } -#if (NGX_WIN32) - { - ngx_iocp_conf_t *iocpcf; + /* do not sort by default */ - iocpcf = ngx_event_get_conf(cf->cycle->conf_ctx, ngx_iocp_module); - if (iocpcf->acceptex_read) { - ls->post_accept_buffer_size = cscf->client_header_buffer_size; - } - } -#endif + return 0; +} - ls->backlog = in_addr[a].listen_conf->backlog; - ls->rcvbuf = in_addr[a].listen_conf->rcvbuf; - ls->sndbuf = in_addr[a].listen_conf->sndbuf; -#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) - ls->accept_filter = in_addr[a].listen_conf->accept_filter; -#endif +static int ngx_libc_cdecl +ngx_http_cmp_dns_wildcards(const void *one, const void *two) +{ + ngx_hash_key_t *first, *second; -#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) - ls->deferred_accept = in_addr[a].listen_conf->deferred_accept; -#endif + first = (ngx_hash_key_t *) one; + second = (ngx_hash_key_t *) two; - hip = ngx_palloc(cf->pool, sizeof(ngx_http_in_port_t)); - if (hip == NULL) { - return NGX_CONF_ERROR; - } + return ngx_strcmp(first->key.data, second->key.data); +} - hip->port = in_port[p].port; - hip->port_text.data = ngx_palloc(cf->pool, 7); - if (hip->port_text.data == NULL) { - return NGX_CONF_ERROR; - } +static ngx_int_t +ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_in_port_t *in_port) +{ + ngx_uint_t i, a, last, bind_all, done; + ngx_listening_t *ls; + ngx_http_in_port_t *hip; + ngx_http_conf_in_addr_t *in_addr; + ngx_http_virtual_names_t *vn; + ngx_http_core_loc_conf_t *clcf; + ngx_http_core_srv_conf_t *cscf; - ls->servers = hip; + in_addr = in_port->addrs.elts; + last = in_port->addrs.nelts; - hip->port_text.len = ngx_sprintf(hip->port_text.data, ":%d", - hip->port) - - hip->port_text.data; + /* + * if there is a binding to a "*:port" then we need to bind() + * to the "*:port" only and ignore other bindings + */ - in_addr = in_port[p].addrs.elts; + if (in_addr[last - 1].addr == INADDR_ANY) { + in_addr[last - 1].bind = 1; + bind_all = 0; - if (in_addr[a].bind && in_addr[a].addr != INADDR_ANY) { - hip->naddrs = 1; - done = 0; + } else { + bind_all = 1; + } - } else if (in_port[p].addrs.nelts > 1 - && in_addr[last - 1].addr == INADDR_ANY) - { - hip->naddrs = last; - done = 1; + a = 0; - } else { - hip->naddrs = 1; - done = 0; - } + while (a < last) { -#if 0 - ngx_log_error(NGX_LOG_ALERT, cf->log, 0, - "%ui: %V %d %ui %ui", - a, &ls->addr_text, in_addr[a].bind, - hip->naddrs, last); -#endif + if (!bind_all && !in_addr[a].bind) { + a++; + continue; + } - hip->addrs = ngx_pcalloc(cf->pool, - hip->naddrs * sizeof(ngx_http_in_addr_t)); - if (hip->addrs == NULL) { - return NGX_CONF_ERROR; - } + ls = ngx_listening_inet_stream_socket(cf, in_addr[a].addr, + in_port->port); + if (ls == NULL) { + return NGX_ERROR; + } - for (i = 0; i < hip->naddrs; i++) { - hip->addrs[i].addr = in_addr[i].addr; - hip->addrs[i].core_srv_conf = in_addr[i].core_srv_conf; + ls->addr_ntop = 1; - if (in_addr[i].hash.buckets == NULL - && (in_addr[i].wc_head == NULL - || in_addr[i].wc_head->hash.buckets == NULL) - && (in_addr[i].wc_head == NULL - || in_addr[i].wc_head->hash.buckets == NULL)) - { - continue; - } + ls->handler = ngx_http_init_connection; - vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t)); - if (vn == NULL) { - return NGX_CONF_ERROR; - } - hip->addrs[i].virtual_names = vn; + cscf = in_addr[a].core_srv_conf; + ls->pool_size = cscf->connection_pool_size; + ls->post_accept_timeout = cscf->client_header_timeout; - vn->names.hash = in_addr[i].hash; - vn->names.wc_head = in_addr[i].wc_head; - vn->names.wc_tail = in_addr[i].wc_tail; -#if (NGX_PCRE) - vn->nregex = in_addr[i].nregex; - vn->regex = in_addr[i].regex; -#endif - } + clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index]; - if (done) { - break; - } + ls->log = *clcf->err_log; + ls->log.data = &ls->addr_text; + ls->log.handler = ngx_accept_log_error; - in_addr++; - in_port[p].addrs.elts = in_addr; - last--; +#if (NGX_WIN32) + { + ngx_iocp_conf_t *iocpcf; - a = 0; + iocpcf = ngx_event_get_conf(cf->cycle->conf_ctx, ngx_iocp_module); + if (iocpcf->acceptex_read) { + ls->post_accept_buffer_size = cscf->client_header_buffer_size; } - } + } +#endif - return NGX_CONF_OK; -} + ls->backlog = in_addr[a].listen_conf->backlog; + ls->rcvbuf = in_addr[a].listen_conf->rcvbuf; + ls->sndbuf = in_addr[a].listen_conf->sndbuf; +#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) + ls->accept_filter = in_addr[a].listen_conf->accept_filter; +#endif -static ngx_int_t -ngx_http_init_phases(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf) -{ - if (ngx_array_init(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers, - cf->pool, 1, sizeof(ngx_http_handler_pt)) - != NGX_OK) - { - return NGX_ERROR; - } +#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) + ls->deferred_accept = in_addr[a].listen_conf->deferred_accept; +#endif - if (ngx_array_init(&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers, - cf->pool, 1, sizeof(ngx_http_handler_pt)) - != NGX_OK) - { - return NGX_ERROR; - } + hip = ngx_palloc(cf->pool, sizeof(ngx_http_in_port_t)); + if (hip == NULL) { + return NGX_ERROR; + } - if (ngx_array_init(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers, - cf->pool, 1, sizeof(ngx_http_handler_pt)) - != NGX_OK) - { - return NGX_ERROR; - } + hip->port = in_port->port; - if (ngx_array_init(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers, - cf->pool, 1, sizeof(ngx_http_handler_pt)) - != NGX_OK) - { - return NGX_ERROR; - } + hip->port_text.data = ngx_palloc(cf->pool, 7); + if (hip->port_text.data == NULL) { + return NGX_ERROR; + } - if (ngx_array_init(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers, - cf->pool, 2, sizeof(ngx_http_handler_pt)) - != NGX_OK) - { - return NGX_ERROR; - } + ls->servers = hip; - if (ngx_array_init(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers, - cf->pool, 4, sizeof(ngx_http_handler_pt)) - != NGX_OK) - { - return NGX_ERROR; - } + hip->port_text.len = ngx_sprintf(hip->port_text.data, ":%d", hip->port) + - hip->port_text.data; - if (ngx_array_init(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers, - cf->pool, 1, sizeof(ngx_http_handler_pt)) - != NGX_OK) - { - return NGX_ERROR; - } + in_addr = in_port->addrs.elts; - return NGX_OK; -} + if (in_addr[a].bind && in_addr[a].addr != INADDR_ANY) { + hip->naddrs = 1; + done = 0; + } else if (in_port->addrs.nelts > 1 + && in_addr[last - 1].addr == INADDR_ANY) + { + hip->naddrs = last; + done = 1; -static ngx_int_t -ngx_http_init_headers_in_hash(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf) -{ - ngx_array_t headers_in; - ngx_hash_key_t *hk; - ngx_hash_init_t hash; - ngx_http_header_t *header; - - if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t)) - != NGX_OK) - { - return NGX_ERROR; - } + } else { + hip->naddrs = 1; + done = 0; + } - for (header = ngx_http_headers_in; header->name.len; header++) { - hk = ngx_array_push(&headers_in); - if (hk == NULL) { + hip->addrs = ngx_pcalloc(cf->pool, + hip->naddrs * sizeof(ngx_http_in_addr_t)); + if (hip->addrs == NULL) { return NGX_ERROR; } - hk->key = header->name; - hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len); - hk->value = header; - } - - hash.hash = &cmcf->headers_in_hash; - hash.key = ngx_hash_key_lc; - hash.max_size = 512; - hash.bucket_size = ngx_align(64, ngx_cacheline_size); - hash.name = "headers_in_hash"; - hash.pool = cf->pool; - hash.temp_pool = NULL; - - if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) { - return NGX_ERROR; - } - - return NGX_OK; -} - + for (i = 0; i < hip->naddrs; i++) { + hip->addrs[i].addr = in_addr[i].addr; + hip->addrs[i].core_srv_conf = in_addr[i].core_srv_conf; -static ngx_int_t -ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf) -{ - ngx_int_t j; - ngx_uint_t i, n; - ngx_uint_t find_config_index, use_rewrite, use_access; - ngx_http_handler_pt *h; - ngx_http_phase_handler_t *ph; - ngx_http_phase_handler_pt checker; - - cmcf->phase_engine.server_rewrite_index = (ngx_uint_t) -1; - cmcf->phase_engine.location_rewrite_index = (ngx_uint_t) -1; - find_config_index = 0; - use_rewrite = cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers.nelts ? 1 : 0; - use_access = cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers.nelts ? 1 : 0; - - n = use_rewrite + use_access + 1; /* find config phase */ - - for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) { - n += cmcf->phases[i].handlers.nelts; - } - - ph = ngx_pcalloc(cf->pool, - n * sizeof(ngx_http_phase_handler_t) + sizeof(void *)); - if (ph == NULL) { - return NGX_ERROR; - } - - cmcf->phase_engine.handlers = ph; - n = 0; - - for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) { - h = cmcf->phases[i].handlers.elts; - - switch (i) { - - case NGX_HTTP_SERVER_REWRITE_PHASE: - if (cmcf->phase_engine.server_rewrite_index == (ngx_uint_t) -1) { - cmcf->phase_engine.server_rewrite_index = n; - } - checker = ngx_http_core_generic_phase; - - break; - - case NGX_HTTP_FIND_CONFIG_PHASE: - find_config_index = n; - - ph->checker = ngx_http_core_find_config_phase; - n++; - ph++; - - continue; - - case NGX_HTTP_REWRITE_PHASE: - if (cmcf->phase_engine.location_rewrite_index == (ngx_uint_t) -1) { - cmcf->phase_engine.location_rewrite_index = n; + if (in_addr[i].hash.buckets == NULL + && (in_addr[i].wc_head == NULL + || in_addr[i].wc_head->hash.buckets == NULL) + && (in_addr[i].wc_head == NULL + || in_addr[i].wc_head->hash.buckets == NULL)) + { + continue; } - checker = ngx_http_core_generic_phase; - break; - - case NGX_HTTP_POST_REWRITE_PHASE: - if (use_rewrite) { - ph->checker = ngx_http_core_post_rewrite_phase; - ph->next = find_config_index; - n++; - ph++; + vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t)); + if (vn == NULL) { + return NGX_ERROR; } + hip->addrs[i].virtual_names = vn; - continue; - - case NGX_HTTP_ACCESS_PHASE: - checker = ngx_http_core_access_phase; - n++; - break; - - case NGX_HTTP_POST_ACCESS_PHASE: - if (use_access) { - ph->checker = ngx_http_core_post_access_phase; - ph->next = n; - ph++; - } - - continue; - - case NGX_HTTP_CONTENT_PHASE: - checker = ngx_http_core_content_phase; - break; - - default: - checker = ngx_http_core_generic_phase; - } - - n += cmcf->phases[i].handlers.nelts; - - for (j = cmcf->phases[i].handlers.nelts - 1; j >=0; j--) { - ph->checker = checker; - ph->handler = h[j]; - ph->next = n; - ph++; - } - } - - return NGX_OK; -} - - -/* - * add the server address, the server names and the server core module - * configurations to the port (in_port) - */ - -static ngx_int_t -ngx_http_add_address(ngx_conf_t *cf, ngx_http_conf_in_port_t *in_port, - ngx_http_listen_t *lscf, ngx_http_core_srv_conf_t *cscf) -{ - ngx_http_conf_in_addr_t *in_addr; - - if (in_port->addrs.elts == NULL) { - if (ngx_array_init(&in_port->addrs, cf->temp_pool, 4, - sizeof(ngx_http_conf_in_addr_t)) - != NGX_OK) - { - return NGX_ERROR; - } - } - - in_addr = ngx_array_push(&in_port->addrs); - if (in_addr == NULL) { - return NGX_ERROR; - } - - in_addr->addr = lscf->addr; - in_addr->hash.buckets = NULL; - in_addr->hash.size = 0; - in_addr->wc_head = NULL; - in_addr->wc_tail = NULL; - in_addr->names.elts = NULL; + vn->names.hash = in_addr[i].hash; + vn->names.wc_head = in_addr[i].wc_head; + vn->names.wc_tail = in_addr[i].wc_tail; #if (NGX_PCRE) - in_addr->nregex = 0; - in_addr->regex = NULL; -#endif - in_addr->core_srv_conf = cscf; - in_addr->default_server = lscf->conf.default_server; - in_addr->bind = lscf->conf.bind; - in_addr->listen_conf = &lscf->conf; - -#if (NGX_DEBUG) - { - u_char text[20]; - ngx_inet_ntop(AF_INET, &in_addr->addr, text, 20); - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0, "address: %s:%d", - text, in_port->port); - } + vn->nregex = in_addr[i].nregex; + vn->regex = in_addr[i].regex; #endif - - return ngx_http_add_names(cf, in_addr, cscf); -} - - -/* - * add the server names and the server core module - * configurations to the address:port (in_addr) - */ - -static ngx_int_t -ngx_http_add_names(ngx_conf_t *cf, ngx_http_conf_in_addr_t *in_addr, - ngx_http_core_srv_conf_t *cscf) -{ - ngx_uint_t i, n; - ngx_http_server_name_t *server_names, *name; - - if (in_addr->names.elts == NULL) { - if (ngx_array_init(&in_addr->names, cf->temp_pool, 4, - sizeof(ngx_http_server_name_t)) - != NGX_OK) - { - return NGX_ERROR; } - } - - server_names = cscf->server_names.elts; - for (i = 0; i < cscf->server_names.nelts; i++) { - - for (n = 0; n < server_names[i].name.len; n++) { - server_names[i].name.data[n] = - ngx_tolower(server_names[i].name.data[n]); + if (done) { + return NGX_OK; } - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0, - "name: %V", &server_names[i].name); + in_addr++; + in_port->addrs.elts = in_addr; + last--; - name = ngx_array_push(&in_addr->names); - if (name == NULL) { - return NGX_ERROR; - } - - *name = server_names[i]; + a = 0; } return NGX_OK; } - - -static char * -ngx_http_merge_locations(ngx_conf_t *cf, ngx_array_t *locations, - void **loc_conf, ngx_http_module_t *module, ngx_uint_t ctx_index) -{ - char *rv; - ngx_uint_t i; - ngx_http_core_loc_conf_t **clcfp; - - clcfp = locations->elts; - - for (i = 0; i < locations->nelts; i++) { - rv = module->merge_loc_conf(cf, loc_conf[ctx_index], - clcfp[i]->loc_conf[ctx_index]); - if (rv != NGX_CONF_OK) { - return rv; - } - - if (clcfp[i]->locations == NULL) { - continue; - } - - rv = ngx_http_merge_locations(cf, clcfp[i]->locations, - clcfp[i]->loc_conf, module, ctx_index); - if (rv != NGX_CONF_OK) { - return rv; - } - } - - return NGX_CONF_OK; -} - - -static ngx_int_t -ngx_http_cmp_conf_in_addrs(const void *one, const void *two) -{ - ngx_http_conf_in_addr_t *first, *second; - - first = (ngx_http_conf_in_addr_t *) one; - second = (ngx_http_conf_in_addr_t *) two; - - if (first->addr == INADDR_ANY) { - /* the INADDR_ANY must be the last resort, shift it to the end */ - return 1; - } - - if (first->bind && !second->bind) { - /* shift explicit bind()ed addresses to the start */ - return -1; - } - - if (!first->bind && second->bind) { - /* shift explicit bind()ed addresses to the start */ - return 1; - } - - /* do not sort by default */ - - return 0; -} - - -static int ngx_libc_cdecl -ngx_http_cmp_dns_wildcards(const void *one, const void *two) -{ - ngx_hash_key_t *first, *second; - - first = (ngx_hash_key_t *) one; - second = (ngx_hash_key_t *) two; - - return ngx_strcmp(first->key.data, second->key.data); -}