Annotation of embedaddon/nginx/src/http/ngx_http.c, revision 1.1

1.1     ! misho       1: 
        !             2: /*
        !             3:  * Copyright (C) Igor Sysoev
        !             4:  * Copyright (C) Nginx, Inc.
        !             5:  */
        !             6: 
        !             7: 
        !             8: #include <ngx_config.h>
        !             9: #include <ngx_core.h>
        !            10: #include <ngx_http.h>
        !            11: 
        !            12: 
        !            13: static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
        !            14: static ngx_int_t ngx_http_init_phases(ngx_conf_t *cf,
        !            15:     ngx_http_core_main_conf_t *cmcf);
        !            16: static ngx_int_t ngx_http_init_headers_in_hash(ngx_conf_t *cf,
        !            17:     ngx_http_core_main_conf_t *cmcf);
        !            18: static ngx_int_t ngx_http_init_phase_handlers(ngx_conf_t *cf,
        !            19:     ngx_http_core_main_conf_t *cmcf);
        !            20: 
        !            21: static ngx_int_t ngx_http_add_addresses(ngx_conf_t *cf,
        !            22:     ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port,
        !            23:     ngx_http_listen_opt_t *lsopt);
        !            24: static ngx_int_t ngx_http_add_address(ngx_conf_t *cf,
        !            25:     ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port,
        !            26:     ngx_http_listen_opt_t *lsopt);
        !            27: static ngx_int_t ngx_http_add_server(ngx_conf_t *cf,
        !            28:     ngx_http_core_srv_conf_t *cscf, ngx_http_conf_addr_t *addr);
        !            29: 
        !            30: static 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);
        !            33: static char *ngx_http_merge_locations(ngx_conf_t *cf,
        !            34:     ngx_queue_t *locations, void **loc_conf, ngx_http_module_t *module,
        !            35:     ngx_uint_t ctx_index);
        !            36: static 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);
        !            38: static ngx_int_t ngx_http_init_static_location_trees(ngx_conf_t *cf,
        !            39:     ngx_http_core_loc_conf_t *pclcf);
        !            40: static ngx_int_t ngx_http_cmp_locations(const ngx_queue_t *one,
        !            41:     const ngx_queue_t *two);
        !            42: static ngx_int_t ngx_http_join_exact_locations(ngx_conf_t *cf,
        !            43:     ngx_queue_t *locations);
        !            44: static void ngx_http_create_locations_list(ngx_queue_t *locations,
        !            45:     ngx_queue_t *q);
        !            46: static ngx_http_location_tree_node_t *
        !            47:     ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations,
        !            48:     size_t prefix);
        !            49: 
        !            50: static ngx_int_t ngx_http_optimize_servers(ngx_conf_t *cf,
        !            51:     ngx_http_core_main_conf_t *cmcf, ngx_array_t *ports);
        !            52: static ngx_int_t ngx_http_server_names(ngx_conf_t *cf,
        !            53:     ngx_http_core_main_conf_t *cmcf, ngx_http_conf_addr_t *addr);
        !            54: static ngx_int_t ngx_http_cmp_conf_addrs(const void *one, const void *two);
        !            55: static int ngx_libc_cdecl ngx_http_cmp_dns_wildcards(const void *one,
        !            56:     const void *two);
        !            57: 
        !            58: static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf,
        !            59:     ngx_http_conf_port_t *port);
        !            60: static ngx_listening_t *ngx_http_add_listening(ngx_conf_t *cf,
        !            61:     ngx_http_conf_addr_t *addr);
        !            62: static 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)
        !            65: static 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
        !            68: 
        !            69: ngx_uint_t   ngx_http_max_module;
        !            70: 
        !            71: 
        !            72: ngx_int_t  (*ngx_http_top_header_filter) (ngx_http_request_t *r);
        !            73: ngx_int_t  (*ngx_http_top_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
        !            74: 
        !            75: 
        !            76: ngx_str_t  ngx_http_html_default_types[] = {
        !            77:     ngx_string("text/html"),
        !            78:     ngx_null_string
        !            79: };
        !            80: 
        !            81: 
        !            82: static ngx_command_t  ngx_http_commands[] = {
        !            83: 
        !            84:     { ngx_string("http"),
        !            85:       NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
        !            86:       ngx_http_block,
        !            87:       0,
        !            88:       0,
        !            89:       NULL },
        !            90: 
        !            91:       ngx_null_command
        !            92: };
        !            93: 
        !            94: 
        !            95: static ngx_core_module_t  ngx_http_module_ctx = {
        !            96:     ngx_string("http"),
        !            97:     NULL,
        !            98:     NULL
        !            99: };
        !           100: 
        !           101: 
        !           102: ngx_module_t  ngx_http_module = {
        !           103:     NGX_MODULE_V1,
        !           104:     &ngx_http_module_ctx,                  /* module context */
        !           105:     ngx_http_commands,                     /* module directives */
        !           106:     NGX_CORE_MODULE,                       /* module type */
        !           107:     NULL,                                  /* init master */
        !           108:     NULL,                                  /* init module */
        !           109:     NULL,                                  /* init process */
        !           110:     NULL,                                  /* init thread */
        !           111:     NULL,                                  /* exit thread */
        !           112:     NULL,                                  /* exit process */
        !           113:     NULL,                                  /* exit master */
        !           114:     NGX_MODULE_V1_PADDING
        !           115: };
        !           116: 
        !           117: 
        !           118: static char *
        !           119: ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
        !           120: {
        !           121:     char                        *rv;
        !           122:     ngx_uint_t                   mi, m, s;
        !           123:     ngx_conf_t                   pcf;
        !           124:     ngx_http_module_t           *module;
        !           125:     ngx_http_conf_ctx_t         *ctx;
        !           126:     ngx_http_core_loc_conf_t    *clcf;
        !           127:     ngx_http_core_srv_conf_t   **cscfp;
        !           128:     ngx_http_core_main_conf_t   *cmcf;
        !           129: 
        !           130:     /* the main http context */
        !           131: 
        !           132:     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
        !           133:     if (ctx == NULL) {
        !           134:         return NGX_CONF_ERROR;
        !           135:     }
        !           136: 
        !           137:     *(ngx_http_conf_ctx_t **) conf = ctx;
        !           138: 
        !           139: 
        !           140:     /* count the number of the http modules and set up their indices */
        !           141: 
        !           142:     ngx_http_max_module = 0;
        !           143:     for (m = 0; ngx_modules[m]; m++) {
        !           144:         if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
        !           145:             continue;
        !           146:         }
        !           147: 
        !           148:         ngx_modules[m]->ctx_index = ngx_http_max_module++;
        !           149:     }
        !           150: 
        !           151: 
        !           152:     /* the http main_conf context, it is the same in the all http contexts */
        !           153: 
        !           154:     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:     }
        !           159: 
        !           160: 
        !           161:     /*
        !           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:      */
        !           187: 
        !           188:     for (m = 0; ngx_modules[m]; m++) {
        !           189:         if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
        !           190:             continue;
        !           191:         }
        !           192: 
        !           193:         module = ngx_modules[m]->ctx;
        !           194:         mi = ngx_modules[m]->ctx_index;
        !           195: 
        !           196:         if (module->create_main_conf) {
        !           197:             ctx->main_conf[mi] = module->create_main_conf(cf);
        !           198:             if (ctx->main_conf[mi] == NULL) {
        !           199:                 return NGX_CONF_ERROR;
        !           200:             }
        !           201:         }
        !           202: 
        !           203:         if (module->create_srv_conf) {
        !           204:             ctx->srv_conf[mi] = module->create_srv_conf(cf);
        !           205:             if (ctx->srv_conf[mi] == NULL) {
        !           206:                 return NGX_CONF_ERROR;
        !           207:             }
        !           208:         }
        !           209: 
        !           210:         if (module->create_loc_conf) {
        !           211:             ctx->loc_conf[mi] = module->create_loc_conf(cf);
        !           212:             if (ctx->loc_conf[mi] == NULL) {
        !           213:                 return NGX_CONF_ERROR;
        !           214:             }
        !           215:         }
        !           216:     }
        !           217: 
        !           218:     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;
        !           227: 
        !           228:         if (module->preconfiguration) {
        !           229:             if (module->preconfiguration(cf) != NGX_OK) {
        !           230:                 return NGX_CONF_ERROR;
        !           231:             }
        !           232:         }
        !           233:     }
        !           234: 
        !           235:     /* parse inside the http{} block */
        !           236: 
        !           237:     cf->module_type = NGX_HTTP_MODULE;
        !           238:     cf->cmd_type = NGX_HTTP_MAIN_CONF;
        !           239:     rv = ngx_conf_parse(cf, NULL);
        !           240: 
        !           241:     if (rv != NGX_CONF_OK) {
        !           242:         goto failed;
        !           243:     }
        !           244: 
        !           245:     /*
        !           246:      * init http{} main_conf's, merge the server{}s' srv_conf's
        !           247:      * and its location{}s' loc_conf's
        !           248:      */
        !           249: 
        !           250:     cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
        !           251:     cscfp = cmcf->servers.elts;
        !           252: 
        !           253:     for (m = 0; ngx_modules[m]; m++) {
        !           254:         if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
        !           255:             continue;
        !           256:         }
        !           257: 
        !           258:         module = ngx_modules[m]->ctx;
        !           259:         mi = ngx_modules[m]->ctx_index;
        !           260: 
        !           261:         /* init http{} main_conf's */
        !           262: 
        !           263:         if (module->init_main_conf) {
        !           264:             rv = module->init_main_conf(cf, ctx->main_conf[mi]);
        !           265:             if (rv != NGX_CONF_OK) {
        !           266:                 goto failed;
        !           267:             }
        !           268:         }
        !           269: 
        !           270:         rv = ngx_http_merge_servers(cf, cmcf, module, mi);
        !           271:         if (rv != NGX_CONF_OK) {
        !           272:             goto failed;
        !           273:         }
        !           274:     }
        !           275: 
        !           276: 
        !           277:     /* 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: 
        !           293:     if (ngx_http_init_phases(cf, cmcf) != NGX_OK) {
        !           294:         return NGX_CONF_ERROR;
        !           295:     }
        !           296: 
        !           297:     if (ngx_http_init_headers_in_hash(cf, cmcf) != NGX_OK) {
        !           298:         return NGX_CONF_ERROR;
        !           299:     }
        !           300: 
        !           301: 
        !           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;
        !           308: 
        !           309:         if (module->postconfiguration) {
        !           310:             if (module->postconfiguration(cf) != NGX_OK) {
        !           311:                 return NGX_CONF_ERROR;
        !           312:             }
        !           313:         }
        !           314:     }
        !           315: 
        !           316:     if (ngx_http_variables_init_vars(cf) != NGX_OK) {
        !           317:         return NGX_CONF_ERROR;
        !           318:     }
        !           319: 
        !           320:     /*
        !           321:      * http{}'s cf->ctx was needed while the configuration merging
        !           322:      * and in postconfiguration process
        !           323:      */
        !           324: 
        !           325:     *cf = pcf;
        !           326: 
        !           327: 
        !           328:     if (ngx_http_init_phase_handlers(cf, cmcf) != NGX_OK) {
        !           329:         return NGX_CONF_ERROR;
        !           330:     }
        !           331: 
        !           332: 
        !           333:     /* optimize the lists of ports, addresses and server names */
        !           334: 
        !           335:     if (ngx_http_optimize_servers(cf, cmcf, cmcf->ports) != NGX_OK) {
        !           336:         return NGX_CONF_ERROR;
        !           337:     }
        !           338: 
        !           339:     return NGX_CONF_OK;
        !           340: 
        !           341: failed:
        !           342: 
        !           343:     *cf = pcf;
        !           344: 
        !           345:     return rv;
        !           346: }
        !           347: 
        !           348: 
        !           349: static ngx_int_t
        !           350: ngx_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: 
        !           405: static ngx_int_t
        !           406: ngx_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: 
        !           446: static ngx_int_t
        !           447: ngx_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: 
        !           462:     n = use_rewrite + use_access + cmcf->try_files + 1 /* find config phase */;
        !           463: 
        !           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:             }
        !           486:             checker = ngx_http_core_rewrite_phase;
        !           487: 
        !           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:             }
        !           503:             checker = ngx_http_core_rewrite_phase;
        !           504: 
        !           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: 
        !           531:         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: 
        !           540:         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: 
        !           562: static char *
        !           563: ngx_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: 
        !           616: failed:
        !           617: 
        !           618:     *ctx = saved;
        !           619: 
        !           620:     return rv;
        !           621: }
        !           622: 
        !           623: 
        !           624: static char *
        !           625: ngx_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;
        !           630:     ngx_http_conf_ctx_t        *ctx, saved;
        !           631:     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: 
        !           638:     ctx = (ngx_http_conf_ctx_t *) cf->ctx;
        !           639:     saved = *ctx;
        !           640: 
        !           641:     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;
        !           648:         ctx->loc_conf = clcf->loc_conf;
        !           649: 
        !           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: 
        !           663:     *ctx = saved;
        !           664: 
        !           665:     return NGX_CONF_OK;
        !           666: }
        !           667: 
        !           668: 
        !           669: static ngx_int_t
        !           670: ngx_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: 
        !           798: static ngx_int_t
        !           799: ngx_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: 
        !           844: ngx_int_t
        !           845: ngx_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: 
        !           891: static ngx_int_t
        !           892: ngx_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: 
        !           963: static ngx_int_t
        !           964: ngx_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: 
        !          1002: static void
        !          1003: ngx_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: 
        !          1066: static ngx_http_location_tree_node_t *
        !          1067: ngx_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: 
        !          1080:     node = ngx_palloc(cf->pool,
        !          1081:                       offsetof(ngx_http_location_tree_node_t, name) + len);
        !          1082:     if (node == NULL) {
        !          1083:         return NULL;
        !          1084:     }
        !          1085: 
        !          1086:     node->left = NULL;
        !          1087:     node->right = NULL;
        !          1088:     node->tree = NULL;
        !          1089:     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: 
        !          1124: inclusive:
        !          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: 
        !          1139: ngx_int_t
        !          1140: ngx_http_add_listen(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
        !          1141:     ngx_http_listen_opt_t *lsopt)
        !          1142: {
        !          1143:     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
        !          1152: 
        !          1153:     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
        !          1154: 
        !          1155:     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;
        !          1160:         }
        !          1161:     }
        !          1162: 
        !          1163:     sa = &lsopt->u.sockaddr;
        !          1164: 
        !          1165:     switch (sa->sa_family) {
        !          1166: 
        !          1167: #if (NGX_HAVE_INET6)
        !          1168:     case AF_INET6:
        !          1169:         sin6 = &lsopt->u.sockaddr_in6;
        !          1170:         p = sin6->sin6_port;
        !          1171:         break;
        !          1172: #endif
        !          1173: 
        !          1174: #if (NGX_HAVE_UNIX_DOMAIN)
        !          1175:     case AF_UNIX:
        !          1176:         p = 0;
        !          1177:         break;
        !          1178: #endif
        !          1179: 
        !          1180:     default: /* AF_INET */
        !          1181:         sin = &lsopt->u.sockaddr_in;
        !          1182:         p = sin->sin_port;
        !          1183:         break;
        !          1184:     }
        !          1185: 
        !          1186:     port = cmcf->ports->elts;
        !          1187:     for (i = 0; i < cmcf->ports->nelts; i++) {
        !          1188: 
        !          1189:         if (p != port[i].port || sa->sa_family != port[i].family) {
        !          1190:             continue;
        !          1191:         }
        !          1192: 
        !          1193:         /* a port is already in the port list */
        !          1194: 
        !          1195:         return ngx_http_add_addresses(cf, cscf, &port[i], lsopt);
        !          1196:     }
        !          1197: 
        !          1198:     /* add a port to the port list */
        !          1199: 
        !          1200:     port = ngx_array_push(cmcf->ports);
        !          1201:     if (port == NULL) {
        !          1202:         return NGX_ERROR;
        !          1203:     }
        !          1204: 
        !          1205:     port->family = sa->sa_family;
        !          1206:     port->port = p;
        !          1207:     port->addrs.elts = NULL;
        !          1208: 
        !          1209:     return ngx_http_add_address(cf, cscf, port, lsopt);
        !          1210: }
        !          1211: 
        !          1212: 
        !          1213: static ngx_int_t
        !          1214: ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
        !          1215:     ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt)
        !          1216: {
        !          1217:     u_char                *p;
        !          1218:     size_t                 len, off;
        !          1219:     ngx_uint_t             i, default_server;
        !          1220:     struct sockaddr       *sa;
        !          1221:     ngx_http_conf_addr_t  *addr;
        !          1222: #if (NGX_HAVE_UNIX_DOMAIN)
        !          1223:     struct sockaddr_un    *saun;
        !          1224: #endif
        !          1225: #if (NGX_HTTP_SSL)
        !          1226:     ngx_uint_t             ssl;
        !          1227: #endif
        !          1228: #if (NGX_HTTP_SPDY)
        !          1229:     ngx_uint_t             spdy;
        !          1230: #endif
        !          1231: 
        !          1232:     /*
        !          1233:      * we cannot compare whole sockaddr struct's as kernel
        !          1234:      * may fill some fields in inherited sockaddr struct's
        !          1235:      */
        !          1236: 
        !          1237:     sa = &lsopt->u.sockaddr;
        !          1238: 
        !          1239:     switch (sa->sa_family) {
        !          1240: 
        !          1241: #if (NGX_HAVE_INET6)
        !          1242:     case AF_INET6:
        !          1243:         off = offsetof(struct sockaddr_in6, sin6_addr);
        !          1244:         len = 16;
        !          1245:         break;
        !          1246: #endif
        !          1247: 
        !          1248: #if (NGX_HAVE_UNIX_DOMAIN)
        !          1249:     case AF_UNIX:
        !          1250:         off = offsetof(struct sockaddr_un, sun_path);
        !          1251:         len = sizeof(saun->sun_path);
        !          1252:         break;
        !          1253: #endif
        !          1254: 
        !          1255:     default: /* AF_INET */
        !          1256:         off = offsetof(struct sockaddr_in, sin_addr);
        !          1257:         len = 4;
        !          1258:         break;
        !          1259:     }
        !          1260: 
        !          1261:     p = lsopt->u.sockaddr_data + off;
        !          1262: 
        !          1263:     addr = port->addrs.elts;
        !          1264: 
        !          1265:     for (i = 0; i < port->addrs.nelts; i++) {
        !          1266: 
        !          1267:         if (ngx_memcmp(p, addr[i].opt.u.sockaddr_data + off, len) != 0) {
        !          1268:             continue;
        !          1269:         }
        !          1270: 
        !          1271:         /* the address is already in the address list */
        !          1272: 
        !          1273:         if (ngx_http_add_server(cf, cscf, &addr[i]) != NGX_OK) {
        !          1274:             return NGX_ERROR;
        !          1275:         }
        !          1276: 
        !          1277:         /* preserve default_server bit during listen options overwriting */
        !          1278:         default_server = addr[i].opt.default_server;
        !          1279: 
        !          1280: #if (NGX_HTTP_SSL)
        !          1281:         ssl = lsopt->ssl || addr[i].opt.ssl;
        !          1282: #endif
        !          1283: #if (NGX_HTTP_SPDY)
        !          1284:         spdy = lsopt->spdy || addr[i].opt.spdy;
        !          1285: #endif
        !          1286: 
        !          1287:         if (lsopt->set) {
        !          1288: 
        !          1289:             if (addr[i].opt.set) {
        !          1290:                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
        !          1291:                         "duplicate listen options for %s", addr[i].opt.addr);
        !          1292:                 return NGX_ERROR;
        !          1293:             }
        !          1294: 
        !          1295:             addr[i].opt = *lsopt;
        !          1296:         }
        !          1297: 
        !          1298:         /* check the duplicate "default" server for this address:port */
        !          1299: 
        !          1300:         if (lsopt->default_server) {
        !          1301: 
        !          1302:             if (default_server) {
        !          1303:                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
        !          1304:                         "a duplicate default server for %s", addr[i].opt.addr);
        !          1305:                 return NGX_ERROR;
        !          1306:             }
        !          1307: 
        !          1308:             default_server = 1;
        !          1309:             addr[i].default_server = cscf;
        !          1310:         }
        !          1311: 
        !          1312:         addr[i].opt.default_server = default_server;
        !          1313: #if (NGX_HTTP_SSL)
        !          1314:         addr[i].opt.ssl = ssl;
        !          1315: #endif
        !          1316: #if (NGX_HTTP_SPDY)
        !          1317:         addr[i].opt.spdy = spdy;
        !          1318: #endif
        !          1319: 
        !          1320:         return NGX_OK;
        !          1321:     }
        !          1322: 
        !          1323:     /* add the address to the addresses list that bound to this port */
        !          1324: 
        !          1325:     return ngx_http_add_address(cf, cscf, port, lsopt);
        !          1326: }
        !          1327: 
        !          1328: 
        !          1329: /*
        !          1330:  * add the server address, the server names and the server core module
        !          1331:  * configurations to the port list
        !          1332:  */
        !          1333: 
        !          1334: static ngx_int_t
        !          1335: ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
        !          1336:     ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt)
        !          1337: {
        !          1338:     ngx_http_conf_addr_t  *addr;
        !          1339: 
        !          1340:     if (port->addrs.elts == NULL) {
        !          1341:         if (ngx_array_init(&port->addrs, cf->temp_pool, 4,
        !          1342:                            sizeof(ngx_http_conf_addr_t))
        !          1343:             != NGX_OK)
        !          1344:         {
        !          1345:             return NGX_ERROR;
        !          1346:         }
        !          1347:     }
        !          1348: 
        !          1349: #if (NGX_HTTP_SPDY && NGX_HTTP_SSL && !defined TLSEXT_TYPE_next_proto_neg)
        !          1350:     if (lsopt->spdy && lsopt->ssl) {
        !          1351:         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
        !          1352:                            "nginx was built without OpenSSL NPN support, "
        !          1353:                            "SPDY is not enabled for %s", lsopt->addr);
        !          1354:     }
        !          1355: #endif
        !          1356: 
        !          1357:     addr = ngx_array_push(&port->addrs);
        !          1358:     if (addr == NULL) {
        !          1359:         return NGX_ERROR;
        !          1360:     }
        !          1361: 
        !          1362:     addr->opt = *lsopt;
        !          1363:     addr->hash.buckets = NULL;
        !          1364:     addr->hash.size = 0;
        !          1365:     addr->wc_head = NULL;
        !          1366:     addr->wc_tail = NULL;
        !          1367: #if (NGX_PCRE)
        !          1368:     addr->nregex = 0;
        !          1369:     addr->regex = NULL;
        !          1370: #endif
        !          1371:     addr->default_server = cscf;
        !          1372:     addr->servers.elts = NULL;
        !          1373: 
        !          1374:     return ngx_http_add_server(cf, cscf, addr);
        !          1375: }
        !          1376: 
        !          1377: 
        !          1378: /* add the server core module configuration to the address:port */
        !          1379: 
        !          1380: static ngx_int_t
        !          1381: ngx_http_add_server(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
        !          1382:     ngx_http_conf_addr_t *addr)
        !          1383: {
        !          1384:     ngx_uint_t                  i;
        !          1385:     ngx_http_core_srv_conf_t  **server;
        !          1386: 
        !          1387:     if (addr->servers.elts == NULL) {
        !          1388:         if (ngx_array_init(&addr->servers, cf->temp_pool, 4,
        !          1389:                            sizeof(ngx_http_core_srv_conf_t *))
        !          1390:             != NGX_OK)
        !          1391:         {
        !          1392:             return NGX_ERROR;
        !          1393:         }
        !          1394: 
        !          1395:     } else {
        !          1396:         server = addr->servers.elts;
        !          1397:         for (i = 0; i < addr->servers.nelts; i++) {
        !          1398:             if (server[i] == cscf) {
        !          1399:                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
        !          1400:                                    "a duplicate listen %s", addr->opt.addr);
        !          1401:                 return NGX_ERROR;
        !          1402:             }
        !          1403:         }
        !          1404:     }
        !          1405: 
        !          1406:     server = ngx_array_push(&addr->servers);
        !          1407:     if (server == NULL) {
        !          1408:         return NGX_ERROR;
        !          1409:     }
        !          1410: 
        !          1411:     *server = cscf;
        !          1412: 
        !          1413:     return NGX_OK;
        !          1414: }
        !          1415: 
        !          1416: 
        !          1417: static ngx_int_t
        !          1418: ngx_http_optimize_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
        !          1419:     ngx_array_t *ports)
        !          1420: {
        !          1421:     ngx_uint_t             p, a;
        !          1422:     ngx_http_conf_port_t  *port;
        !          1423:     ngx_http_conf_addr_t  *addr;
        !          1424: 
        !          1425:     if (ports == NULL) {
        !          1426:         return NGX_OK;
        !          1427:     }
        !          1428: 
        !          1429:     port = ports->elts;
        !          1430:     for (p = 0; p < ports->nelts; p++) {
        !          1431: 
        !          1432:         ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts,
        !          1433:                  sizeof(ngx_http_conf_addr_t), ngx_http_cmp_conf_addrs);
        !          1434: 
        !          1435:         /*
        !          1436:          * check whether all name-based servers have the same
        !          1437:          * configuration as a default server for given address:port
        !          1438:          */
        !          1439: 
        !          1440:         addr = port[p].addrs.elts;
        !          1441:         for (a = 0; a < port[p].addrs.nelts; a++) {
        !          1442: 
        !          1443:             if (addr[a].servers.nelts > 1
        !          1444: #if (NGX_PCRE)
        !          1445:                 || addr[a].default_server->captures
        !          1446: #endif
        !          1447:                )
        !          1448:             {
        !          1449:                 if (ngx_http_server_names(cf, cmcf, &addr[a]) != NGX_OK) {
        !          1450:                     return NGX_ERROR;
        !          1451:                 }
        !          1452:             }
        !          1453:         }
        !          1454: 
        !          1455:         if (ngx_http_init_listening(cf, &port[p]) != NGX_OK) {
        !          1456:             return NGX_ERROR;
        !          1457:         }
        !          1458:     }
        !          1459: 
        !          1460:     return NGX_OK;
        !          1461: }
        !          1462: 
        !          1463: 
        !          1464: static ngx_int_t
        !          1465: ngx_http_server_names(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
        !          1466:     ngx_http_conf_addr_t *addr)
        !          1467: {
        !          1468:     ngx_int_t                   rc;
        !          1469:     ngx_uint_t                  n, s;
        !          1470:     ngx_hash_init_t             hash;
        !          1471:     ngx_hash_keys_arrays_t      ha;
        !          1472:     ngx_http_server_name_t     *name;
        !          1473:     ngx_http_core_srv_conf_t  **cscfp;
        !          1474: #if (NGX_PCRE)
        !          1475:     ngx_uint_t                  regex, i;
        !          1476: 
        !          1477:     regex = 0;
        !          1478: #endif
        !          1479: 
        !          1480:     ngx_memzero(&ha, sizeof(ngx_hash_keys_arrays_t));
        !          1481: 
        !          1482:     ha.temp_pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, cf->log);
        !          1483:     if (ha.temp_pool == NULL) {
        !          1484:         return NGX_ERROR;
        !          1485:     }
        !          1486: 
        !          1487:     ha.pool = cf->pool;
        !          1488: 
        !          1489:     if (ngx_hash_keys_array_init(&ha, NGX_HASH_LARGE) != NGX_OK) {
        !          1490:         goto failed;
        !          1491:     }
        !          1492: 
        !          1493:     cscfp = addr->servers.elts;
        !          1494: 
        !          1495:     for (s = 0; s < addr->servers.nelts; s++) {
        !          1496: 
        !          1497:         name = cscfp[s]->server_names.elts;
        !          1498: 
        !          1499:         for (n = 0; n < cscfp[s]->server_names.nelts; n++) {
        !          1500: 
        !          1501: #if (NGX_PCRE)
        !          1502:             if (name[n].regex) {
        !          1503:                 regex++;
        !          1504:                 continue;
        !          1505:             }
        !          1506: #endif
        !          1507: 
        !          1508:             rc = ngx_hash_add_key(&ha, &name[n].name, name[n].server,
        !          1509:                                   NGX_HASH_WILDCARD_KEY);
        !          1510: 
        !          1511:             if (rc == NGX_ERROR) {
        !          1512:                 return NGX_ERROR;
        !          1513:             }
        !          1514: 
        !          1515:             if (rc == NGX_DECLINED) {
        !          1516:                 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
        !          1517:                               "invalid server name or wildcard \"%V\" on %s",
        !          1518:                               &name[n].name, addr->opt.addr);
        !          1519:                 return NGX_ERROR;
        !          1520:             }
        !          1521: 
        !          1522:             if (rc == NGX_BUSY) {
        !          1523:                 ngx_log_error(NGX_LOG_WARN, cf->log, 0,
        !          1524:                               "conflicting server name \"%V\" on %s, ignored",
        !          1525:                               &name[n].name, addr->opt.addr);
        !          1526:             }
        !          1527:         }
        !          1528:     }
        !          1529: 
        !          1530:     hash.key = ngx_hash_key_lc;
        !          1531:     hash.max_size = cmcf->server_names_hash_max_size;
        !          1532:     hash.bucket_size = cmcf->server_names_hash_bucket_size;
        !          1533:     hash.name = "server_names_hash";
        !          1534:     hash.pool = cf->pool;
        !          1535: 
        !          1536:     if (ha.keys.nelts) {
        !          1537:         hash.hash = &addr->hash;
        !          1538:         hash.temp_pool = NULL;
        !          1539: 
        !          1540:         if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK) {
        !          1541:             goto failed;
        !          1542:         }
        !          1543:     }
        !          1544: 
        !          1545:     if (ha.dns_wc_head.nelts) {
        !          1546: 
        !          1547:         ngx_qsort(ha.dns_wc_head.elts, (size_t) ha.dns_wc_head.nelts,
        !          1548:                   sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);
        !          1549: 
        !          1550:         hash.hash = NULL;
        !          1551:         hash.temp_pool = ha.temp_pool;
        !          1552: 
        !          1553:         if (ngx_hash_wildcard_init(&hash, ha.dns_wc_head.elts,
        !          1554:                                    ha.dns_wc_head.nelts)
        !          1555:             != NGX_OK)
        !          1556:         {
        !          1557:             goto failed;
        !          1558:         }
        !          1559: 
        !          1560:         addr->wc_head = (ngx_hash_wildcard_t *) hash.hash;
        !          1561:     }
        !          1562: 
        !          1563:     if (ha.dns_wc_tail.nelts) {
        !          1564: 
        !          1565:         ngx_qsort(ha.dns_wc_tail.elts, (size_t) ha.dns_wc_tail.nelts,
        !          1566:                   sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);
        !          1567: 
        !          1568:         hash.hash = NULL;
        !          1569:         hash.temp_pool = ha.temp_pool;
        !          1570: 
        !          1571:         if (ngx_hash_wildcard_init(&hash, ha.dns_wc_tail.elts,
        !          1572:                                    ha.dns_wc_tail.nelts)
        !          1573:             != NGX_OK)
        !          1574:         {
        !          1575:             goto failed;
        !          1576:         }
        !          1577: 
        !          1578:         addr->wc_tail = (ngx_hash_wildcard_t *) hash.hash;
        !          1579:     }
        !          1580: 
        !          1581:     ngx_destroy_pool(ha.temp_pool);
        !          1582: 
        !          1583: #if (NGX_PCRE)
        !          1584: 
        !          1585:     if (regex == 0) {
        !          1586:         return NGX_OK;
        !          1587:     }
        !          1588: 
        !          1589:     addr->nregex = regex;
        !          1590:     addr->regex = ngx_palloc(cf->pool, regex * sizeof(ngx_http_server_name_t));
        !          1591:     if (addr->regex == NULL) {
        !          1592:         return NGX_ERROR;
        !          1593:     }
        !          1594: 
        !          1595:     i = 0;
        !          1596: 
        !          1597:     for (s = 0; s < addr->servers.nelts; s++) {
        !          1598: 
        !          1599:         name = cscfp[s]->server_names.elts;
        !          1600: 
        !          1601:         for (n = 0; n < cscfp[s]->server_names.nelts; n++) {
        !          1602:             if (name[n].regex) {
        !          1603:                 addr->regex[i++] = name[n];
        !          1604:             }
        !          1605:         }
        !          1606:     }
        !          1607: 
        !          1608: #endif
        !          1609: 
        !          1610:     return NGX_OK;
        !          1611: 
        !          1612: failed:
        !          1613: 
        !          1614:     ngx_destroy_pool(ha.temp_pool);
        !          1615: 
        !          1616:     return NGX_ERROR;
        !          1617: }
        !          1618: 
        !          1619: 
        !          1620: static ngx_int_t
        !          1621: ngx_http_cmp_conf_addrs(const void *one, const void *two)
        !          1622: {
        !          1623:     ngx_http_conf_addr_t  *first, *second;
        !          1624: 
        !          1625:     first = (ngx_http_conf_addr_t *) one;
        !          1626:     second = (ngx_http_conf_addr_t *) two;
        !          1627: 
        !          1628:     if (first->opt.wildcard) {
        !          1629:         /* a wildcard address must be the last resort, shift it to the end */
        !          1630:         return 1;
        !          1631:     }
        !          1632: 
        !          1633:     if (second->opt.wildcard) {
        !          1634:         /* a wildcard address must be the last resort, shift it to the end */
        !          1635:         return -1;
        !          1636:     }
        !          1637: 
        !          1638:     if (first->opt.bind && !second->opt.bind) {
        !          1639:         /* shift explicit bind()ed addresses to the start */
        !          1640:         return -1;
        !          1641:     }
        !          1642: 
        !          1643:     if (!first->opt.bind && second->opt.bind) {
        !          1644:         /* shift explicit bind()ed addresses to the start */
        !          1645:         return 1;
        !          1646:     }
        !          1647: 
        !          1648:     /* do not sort by default */
        !          1649: 
        !          1650:     return 0;
        !          1651: }
        !          1652: 
        !          1653: 
        !          1654: static int ngx_libc_cdecl
        !          1655: ngx_http_cmp_dns_wildcards(const void *one, const void *two)
        !          1656: {
        !          1657:     ngx_hash_key_t  *first, *second;
        !          1658: 
        !          1659:     first = (ngx_hash_key_t *) one;
        !          1660:     second = (ngx_hash_key_t *) two;
        !          1661: 
        !          1662:     return ngx_dns_strcmp(first->key.data, second->key.data);
        !          1663: }
        !          1664: 
        !          1665: 
        !          1666: static ngx_int_t
        !          1667: ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port)
        !          1668: {
        !          1669:     ngx_uint_t                 i, last, bind_wildcard;
        !          1670:     ngx_listening_t           *ls;
        !          1671:     ngx_http_port_t           *hport;
        !          1672:     ngx_http_conf_addr_t      *addr;
        !          1673: 
        !          1674:     addr = port->addrs.elts;
        !          1675:     last = port->addrs.nelts;
        !          1676: 
        !          1677:     /*
        !          1678:      * If there is a binding to an "*:port" then we need to bind() to
        !          1679:      * the "*:port" only and ignore other implicit bindings.  The bindings
        !          1680:      * have been already sorted: explicit bindings are on the start, then
        !          1681:      * implicit bindings go, and wildcard binding is in the end.
        !          1682:      */
        !          1683: 
        !          1684:     if (addr[last - 1].opt.wildcard) {
        !          1685:         addr[last - 1].opt.bind = 1;
        !          1686:         bind_wildcard = 1;
        !          1687: 
        !          1688:     } else {
        !          1689:         bind_wildcard = 0;
        !          1690:     }
        !          1691: 
        !          1692:     i = 0;
        !          1693: 
        !          1694:     while (i < last) {
        !          1695: 
        !          1696:         if (bind_wildcard && !addr[i].opt.bind) {
        !          1697:             i++;
        !          1698:             continue;
        !          1699:         }
        !          1700: 
        !          1701:         ls = ngx_http_add_listening(cf, &addr[i]);
        !          1702:         if (ls == NULL) {
        !          1703:             return NGX_ERROR;
        !          1704:         }
        !          1705: 
        !          1706:         hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t));
        !          1707:         if (hport == NULL) {
        !          1708:             return NGX_ERROR;
        !          1709:         }
        !          1710: 
        !          1711:         ls->servers = hport;
        !          1712: 
        !          1713:         if (i == last - 1) {
        !          1714:             hport->naddrs = last;
        !          1715: 
        !          1716:         } else {
        !          1717:             hport->naddrs = 1;
        !          1718:             i = 0;
        !          1719:         }
        !          1720: 
        !          1721:         switch (ls->sockaddr->sa_family) {
        !          1722: 
        !          1723: #if (NGX_HAVE_INET6)
        !          1724:         case AF_INET6:
        !          1725:             if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) {
        !          1726:                 return NGX_ERROR;
        !          1727:             }
        !          1728:             break;
        !          1729: #endif
        !          1730:         default: /* AF_INET */
        !          1731:             if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) {
        !          1732:                 return NGX_ERROR;
        !          1733:             }
        !          1734:             break;
        !          1735:         }
        !          1736: 
        !          1737:         addr++;
        !          1738:         last--;
        !          1739:     }
        !          1740: 
        !          1741:     return NGX_OK;
        !          1742: }
        !          1743: 
        !          1744: 
        !          1745: static ngx_listening_t *
        !          1746: ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)
        !          1747: {
        !          1748:     ngx_listening_t           *ls;
        !          1749:     ngx_http_core_loc_conf_t  *clcf;
        !          1750:     ngx_http_core_srv_conf_t  *cscf;
        !          1751: 
        !          1752:     ls = ngx_create_listening(cf, &addr->opt.u.sockaddr, addr->opt.socklen);
        !          1753:     if (ls == NULL) {
        !          1754:         return NULL;
        !          1755:     }
        !          1756: 
        !          1757:     ls->addr_ntop = 1;
        !          1758: 
        !          1759:     ls->handler = ngx_http_init_connection;
        !          1760: 
        !          1761:     cscf = addr->default_server;
        !          1762:     ls->pool_size = cscf->connection_pool_size;
        !          1763:     ls->post_accept_timeout = cscf->client_header_timeout;
        !          1764: 
        !          1765:     clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];
        !          1766: 
        !          1767:     ls->logp = clcf->error_log;
        !          1768:     ls->log.data = &ls->addr_text;
        !          1769:     ls->log.handler = ngx_accept_log_error;
        !          1770: 
        !          1771: #if (NGX_WIN32)
        !          1772:     {
        !          1773:     ngx_iocp_conf_t  *iocpcf = NULL;
        !          1774: 
        !          1775:     if (ngx_get_conf(cf->cycle->conf_ctx, ngx_events_module)) {
        !          1776:         iocpcf = ngx_event_get_conf(cf->cycle->conf_ctx, ngx_iocp_module);
        !          1777:     }
        !          1778:     if (iocpcf && iocpcf->acceptex_read) {
        !          1779:         ls->post_accept_buffer_size = cscf->client_header_buffer_size;
        !          1780:     }
        !          1781:     }
        !          1782: #endif
        !          1783: 
        !          1784:     ls->backlog = addr->opt.backlog;
        !          1785:     ls->rcvbuf = addr->opt.rcvbuf;
        !          1786:     ls->sndbuf = addr->opt.sndbuf;
        !          1787: 
        !          1788:     ls->keepalive = addr->opt.so_keepalive;
        !          1789: #if (NGX_HAVE_KEEPALIVE_TUNABLE)
        !          1790:     ls->keepidle = addr->opt.tcp_keepidle;
        !          1791:     ls->keepintvl = addr->opt.tcp_keepintvl;
        !          1792:     ls->keepcnt = addr->opt.tcp_keepcnt;
        !          1793: #endif
        !          1794: 
        !          1795: #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
        !          1796:     ls->accept_filter = addr->opt.accept_filter;
        !          1797: #endif
        !          1798: 
        !          1799: #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
        !          1800:     ls->deferred_accept = addr->opt.deferred_accept;
        !          1801: #endif
        !          1802: 
        !          1803: #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
        !          1804:     ls->ipv6only = addr->opt.ipv6only;
        !          1805: #endif
        !          1806: 
        !          1807: #if (NGX_HAVE_SETFIB)
        !          1808:     ls->setfib = addr->opt.setfib;
        !          1809: #endif
        !          1810: 
        !          1811:     return ls;
        !          1812: }
        !          1813: 
        !          1814: 
        !          1815: static ngx_int_t
        !          1816: ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport,
        !          1817:     ngx_http_conf_addr_t *addr)
        !          1818: {
        !          1819:     ngx_uint_t                 i;
        !          1820:     ngx_http_in_addr_t        *addrs;
        !          1821:     struct sockaddr_in        *sin;
        !          1822:     ngx_http_virtual_names_t  *vn;
        !          1823: 
        !          1824:     hport->addrs = ngx_pcalloc(cf->pool,
        !          1825:                                hport->naddrs * sizeof(ngx_http_in_addr_t));
        !          1826:     if (hport->addrs == NULL) {
        !          1827:         return NGX_ERROR;
        !          1828:     }
        !          1829: 
        !          1830:     addrs = hport->addrs;
        !          1831: 
        !          1832:     for (i = 0; i < hport->naddrs; i++) {
        !          1833: 
        !          1834:         sin = &addr[i].opt.u.sockaddr_in;
        !          1835:         addrs[i].addr = sin->sin_addr.s_addr;
        !          1836:         addrs[i].conf.default_server = addr[i].default_server;
        !          1837: #if (NGX_HTTP_SSL)
        !          1838:         addrs[i].conf.ssl = addr[i].opt.ssl;
        !          1839: #endif
        !          1840: #if (NGX_HTTP_SPDY)
        !          1841:         addrs[i].conf.spdy = addr[i].opt.spdy;
        !          1842: #endif
        !          1843: 
        !          1844:         if (addr[i].hash.buckets == NULL
        !          1845:             && (addr[i].wc_head == NULL
        !          1846:                 || addr[i].wc_head->hash.buckets == NULL)
        !          1847:             && (addr[i].wc_tail == NULL
        !          1848:                 || addr[i].wc_tail->hash.buckets == NULL)
        !          1849: #if (NGX_PCRE)
        !          1850:             && addr[i].nregex == 0
        !          1851: #endif
        !          1852:             )
        !          1853:         {
        !          1854:             continue;
        !          1855:         }
        !          1856: 
        !          1857:         vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
        !          1858:         if (vn == NULL) {
        !          1859:             return NGX_ERROR;
        !          1860:         }
        !          1861: 
        !          1862:         addrs[i].conf.virtual_names = vn;
        !          1863: 
        !          1864:         vn->names.hash = addr[i].hash;
        !          1865:         vn->names.wc_head = addr[i].wc_head;
        !          1866:         vn->names.wc_tail = addr[i].wc_tail;
        !          1867: #if (NGX_PCRE)
        !          1868:         vn->nregex = addr[i].nregex;
        !          1869:         vn->regex = addr[i].regex;
        !          1870: #endif
        !          1871:     }
        !          1872: 
        !          1873:     return NGX_OK;
        !          1874: }
        !          1875: 
        !          1876: 
        !          1877: #if (NGX_HAVE_INET6)
        !          1878: 
        !          1879: static ngx_int_t
        !          1880: ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport,
        !          1881:     ngx_http_conf_addr_t *addr)
        !          1882: {
        !          1883:     ngx_uint_t                 i;
        !          1884:     ngx_http_in6_addr_t       *addrs6;
        !          1885:     struct sockaddr_in6       *sin6;
        !          1886:     ngx_http_virtual_names_t  *vn;
        !          1887: 
        !          1888:     hport->addrs = ngx_pcalloc(cf->pool,
        !          1889:                                hport->naddrs * sizeof(ngx_http_in6_addr_t));
        !          1890:     if (hport->addrs == NULL) {
        !          1891:         return NGX_ERROR;
        !          1892:     }
        !          1893: 
        !          1894:     addrs6 = hport->addrs;
        !          1895: 
        !          1896:     for (i = 0; i < hport->naddrs; i++) {
        !          1897: 
        !          1898:         sin6 = &addr[i].opt.u.sockaddr_in6;
        !          1899:         addrs6[i].addr6 = sin6->sin6_addr;
        !          1900:         addrs6[i].conf.default_server = addr[i].default_server;
        !          1901: #if (NGX_HTTP_SSL)
        !          1902:         addrs6[i].conf.ssl = addr[i].opt.ssl;
        !          1903: #endif
        !          1904: #if (NGX_HTTP_SPDY)
        !          1905:         addrs6[i].conf.spdy = addr[i].opt.spdy;
        !          1906: #endif
        !          1907: 
        !          1908:         if (addr[i].hash.buckets == NULL
        !          1909:             && (addr[i].wc_head == NULL
        !          1910:                 || addr[i].wc_head->hash.buckets == NULL)
        !          1911:             && (addr[i].wc_tail == NULL
        !          1912:                 || addr[i].wc_tail->hash.buckets == NULL)
        !          1913: #if (NGX_PCRE)
        !          1914:             && addr[i].nregex == 0
        !          1915: #endif
        !          1916:             )
        !          1917:         {
        !          1918:             continue;
        !          1919:         }
        !          1920: 
        !          1921:         vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
        !          1922:         if (vn == NULL) {
        !          1923:             return NGX_ERROR;
        !          1924:         }
        !          1925: 
        !          1926:         addrs6[i].conf.virtual_names = vn;
        !          1927: 
        !          1928:         vn->names.hash = addr[i].hash;
        !          1929:         vn->names.wc_head = addr[i].wc_head;
        !          1930:         vn->names.wc_tail = addr[i].wc_tail;
        !          1931: #if (NGX_PCRE)
        !          1932:         vn->nregex = addr[i].nregex;
        !          1933:         vn->regex = addr[i].regex;
        !          1934: #endif
        !          1935:     }
        !          1936: 
        !          1937:     return NGX_OK;
        !          1938: }
        !          1939: 
        !          1940: #endif
        !          1941: 
        !          1942: 
        !          1943: char *
        !          1944: ngx_http_types_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
        !          1945: {
        !          1946:     char  *p = conf;
        !          1947: 
        !          1948:     ngx_array_t     **types;
        !          1949:     ngx_str_t        *value, *default_type;
        !          1950:     ngx_uint_t        i, n, hash;
        !          1951:     ngx_hash_key_t   *type;
        !          1952: 
        !          1953:     types = (ngx_array_t **) (p + cmd->offset);
        !          1954: 
        !          1955:     if (*types == (void *) -1) {
        !          1956:         return NGX_CONF_OK;
        !          1957:     }
        !          1958: 
        !          1959:     default_type = cmd->post;
        !          1960: 
        !          1961:     if (*types == NULL) {
        !          1962:         *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t));
        !          1963:         if (*types == NULL) {
        !          1964:             return NGX_CONF_ERROR;
        !          1965:         }
        !          1966: 
        !          1967:         if (default_type) {
        !          1968:             type = ngx_array_push(*types);
        !          1969:             if (type == NULL) {
        !          1970:                 return NGX_CONF_ERROR;
        !          1971:             }
        !          1972: 
        !          1973:             type->key = *default_type;
        !          1974:             type->key_hash = ngx_hash_key(default_type->data,
        !          1975:                                           default_type->len);
        !          1976:             type->value = (void *) 4;
        !          1977:         }
        !          1978:     }
        !          1979: 
        !          1980:     value = cf->args->elts;
        !          1981: 
        !          1982:     for (i = 1; i < cf->args->nelts; i++) {
        !          1983: 
        !          1984:         if (value[i].len == 1 && value[i].data[0] == '*') {
        !          1985:             *types = (void *) -1;
        !          1986:             return NGX_CONF_OK;
        !          1987:         }
        !          1988: 
        !          1989:         hash = ngx_hash_strlow(value[i].data, value[i].data, value[i].len);
        !          1990:         value[i].data[value[i].len] = '\0';
        !          1991: 
        !          1992:         type = (*types)->elts;
        !          1993:         for (n = 0; n < (*types)->nelts; n++) {
        !          1994: 
        !          1995:             if (ngx_strcmp(value[i].data, type[n].key.data) == 0) {
        !          1996:                 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
        !          1997:                                    "duplicate MIME type \"%V\"", &value[i]);
        !          1998:                 continue;
        !          1999:             }
        !          2000:         }
        !          2001: 
        !          2002:         type = ngx_array_push(*types);
        !          2003:         if (type == NULL) {
        !          2004:             return NGX_CONF_ERROR;
        !          2005:         }
        !          2006: 
        !          2007:         type->key = value[i];
        !          2008:         type->key_hash = hash;
        !          2009:         type->value = (void *) 4;
        !          2010:     }
        !          2011: 
        !          2012:     return NGX_CONF_OK;
        !          2013: }
        !          2014: 
        !          2015: 
        !          2016: char *
        !          2017: ngx_http_merge_types(ngx_conf_t *cf, ngx_array_t **keys, ngx_hash_t *types_hash,
        !          2018:     ngx_array_t **prev_keys, ngx_hash_t *prev_types_hash,
        !          2019:     ngx_str_t *default_types)
        !          2020: {
        !          2021:     ngx_hash_init_t  hash;
        !          2022: 
        !          2023:     if (*keys) {
        !          2024: 
        !          2025:         if (*keys == (void *) -1) {
        !          2026:             return NGX_CONF_OK;
        !          2027:         }
        !          2028: 
        !          2029:         hash.hash = types_hash;
        !          2030:         hash.key = NULL;
        !          2031:         hash.max_size = 2048;
        !          2032:         hash.bucket_size = 64;
        !          2033:         hash.name = "test_types_hash";
        !          2034:         hash.pool = cf->pool;
        !          2035:         hash.temp_pool = NULL;
        !          2036: 
        !          2037:         if (ngx_hash_init(&hash, (*keys)->elts, (*keys)->nelts) != NGX_OK) {
        !          2038:             return NGX_CONF_ERROR;
        !          2039:         }
        !          2040: 
        !          2041:         return NGX_CONF_OK;
        !          2042:     }
        !          2043: 
        !          2044:     if (prev_types_hash->buckets == NULL) {
        !          2045: 
        !          2046:         if (*prev_keys == NULL) {
        !          2047: 
        !          2048:             if (ngx_http_set_default_types(cf, prev_keys, default_types)
        !          2049:                 != NGX_OK)
        !          2050:             {
        !          2051:                 return NGX_CONF_ERROR;
        !          2052:             }
        !          2053: 
        !          2054:         } else if (*prev_keys == (void *) -1) {
        !          2055:             *keys = *prev_keys;
        !          2056:             return NGX_CONF_OK;
        !          2057:         }
        !          2058: 
        !          2059:         hash.hash = prev_types_hash;
        !          2060:         hash.key = NULL;
        !          2061:         hash.max_size = 2048;
        !          2062:         hash.bucket_size = 64;
        !          2063:         hash.name = "test_types_hash";
        !          2064:         hash.pool = cf->pool;
        !          2065:         hash.temp_pool = NULL;
        !          2066: 
        !          2067:         if (ngx_hash_init(&hash, (*prev_keys)->elts, (*prev_keys)->nelts)
        !          2068:             != NGX_OK)
        !          2069:         {
        !          2070:             return NGX_CONF_ERROR;
        !          2071:         }
        !          2072:     }
        !          2073: 
        !          2074:     *types_hash = *prev_types_hash;
        !          2075: 
        !          2076:     return NGX_CONF_OK;
        !          2077: 
        !          2078: }
        !          2079: 
        !          2080: 
        !          2081: ngx_int_t
        !          2082: ngx_http_set_default_types(ngx_conf_t *cf, ngx_array_t **types,
        !          2083:     ngx_str_t *default_type)
        !          2084: {
        !          2085:     ngx_hash_key_t  *type;
        !          2086: 
        !          2087:     *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t));
        !          2088:     if (*types == NULL) {
        !          2089:         return NGX_ERROR;
        !          2090:     }
        !          2091: 
        !          2092:     while (default_type->len) {
        !          2093: 
        !          2094:         type = ngx_array_push(*types);
        !          2095:         if (type == NULL) {
        !          2096:             return NGX_ERROR;
        !          2097:         }
        !          2098: 
        !          2099:         type->key = *default_type;
        !          2100:         type->key_hash = ngx_hash_key(default_type->data,
        !          2101:                                       default_type->len);
        !          2102:         type->value = (void *) 4;
        !          2103: 
        !          2104:         default_type++;
        !          2105:     }
        !          2106: 
        !          2107:     return NGX_OK;
        !          2108: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>