static ngx_int_t ngx_tcp_init_listening(ngx_conf_t *cf, ngx_tcp_conf_port_t *tport) { ngx_uint_t i, last, bind_wildcard; ngx_listening_t *ls; ngx_tcp_port_t *port; ngx_tcp_conf_addr_t *addr; addr = tport->addrs.elts; last = tport->addrs.nelts; /* * If there is a binding to an "*:port" then we need to bind() to * the "*:port" only and ignore other implicit bindings. The bindings * have been already sorted: explicit bindings are on the start, then * implicit bindings go, and wildcard binding is in the end. */ if (addr[last - 1].wildcard) { addr[last - 1].bind = 1; bind_wildcard = 1; } else { bind_wildcard = 0; } i = 0; while (i < last) { if (bind_wildcard && !addr[i].bind) { i++; continue; } ls = ngx_tcp_add_listening(cf, &addr[i]); if (ls == NULL) { return NGX_ERROR; } port = ngx_pcalloc(cf->pool, sizeof(ngx_tcp_port_t)); if (port == NULL) { return NGX_ERROR; } ls->servers = port; if (i == last - 1) { port->naddrs = last; } else { port->naddrs = 1; i = 0; } switch (ls->sockaddr->sa_family) { #if (NGX_HAVE_INET6) case AF_INET6: if (ngx_tcp_add_addrs6(cf, port, addr) != NGX_OK) { return NGX_ERROR; } break; #endif default: /* AF_INET */ if (ngx_tcp_add_addrs(cf, port, addr) != NGX_OK) { return NGX_ERROR; } break; } addr++; last--; } return NGX_OK; }
static char * ngx_tcp_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports) { ngx_uint_t i, p, last, bind_wildcard; ngx_listening_t *ls; ngx_tcp_port_t *mport; ngx_tcp_conf_port_t *port; ngx_tcp_conf_addr_t *addr; port = ports->elts; for (p = 0; p < ports->nelts; p++) { ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts, sizeof(ngx_tcp_conf_addr_t), ngx_tcp_cmp_conf_addrs); addr = port[p].addrs.elts; last = 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 (addr[last - 1].wildcard) { addr[last - 1].bind = 1; bind_wildcard = 1; } else { bind_wildcard = 0; } i = 0; while (i < last) { ngx_tcp_core_main_conf_t *cmcf; ngx_tcp_core_srv_conf_t *cscf; if (bind_wildcard && !addr[i].bind) { i++; continue; } cmcf = addr[i].ctx->main_conf[ngx_tcp_core_module.ctx_index]; cscf = addr[i].ctx->srv_conf[ngx_tcp_core_module.ctx_index]; ls = ngx_create_listening(cf, addr[i].sockaddr, addr[i].socklen); if (ls == NULL) { return NGX_CONF_ERROR; } ls->addr_ntop = 1; ls->handler = ngx_tcp_init_connection; ls->pool_size = cscf->connection_pool_size; if (cmcf->error_log == NULL) { ls->logp = &cf->cycle->new_log; } else { ls->logp = cmcf->error_log; } ls->log.data = &ls->addr_text; ls->log.handler = ngx_accept_log_error; ls->keepalive = addr[i].so_keepalive; #if (NGX_HAVE_KEEPALIVE_TUNABLE) ls->keepidle = addr[i].tcp_keepidle; ls->keepintvl = addr[i].tcp_keepintvl; ls->keepcnt = addr[i].tcp_keepcnt; #endif #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) ls->ipv6only = addr[i].ipv6only; #endif mport = ngx_palloc(cf->pool, sizeof(ngx_tcp_port_t)); if (mport == NULL) { return NGX_CONF_ERROR; } ls->servers = mport; if (i == last - 1) { mport->naddrs = last; } else { mport->naddrs = 1; i = 0; } switch (ls->sockaddr->sa_family) { #if (NGX_HAVE_INET6) case AF_INET6: if (ngx_tcp_add_addrs6(cf, mport, addr) != NGX_OK) { return NGX_CONF_ERROR; } break; #endif default: /* AF_INET */ if (ngx_tcp_add_addrs(cf, mport, addr) != NGX_OK) { return NGX_CONF_ERROR; } break; } addr++; last--; } } return NGX_CONF_OK; }