Annotation of embedaddon/nginx/src/http/ngx_http.c, revision 1.1.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>