static char * ngx_tcp_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_tcp_core_srv_conf_t *cscf = conf; char *rv; ngx_str_t *value; ngx_conf_t save; ngx_tcp_core_loc_t *clcf; clcf = ngx_array_push(&cscf->locations); if (clcf == NULL) { return NGX_CONF_ERROR; } value = cf->args->elts; clcf->name = value[1]; save = *cf; cf->cmd_type = NGX_TCP_LOC_CONF; rv = ngx_conf_parse(cf, NULL); *cf = save; return rv; }
static char * ngx_dso_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; ngx_conf_t pcf; ngx_dso_conf_ctx_t *ctx; ctx = (ngx_dso_conf_ctx_t *) ngx_get_conf(cf->cycle->conf_ctx, ngx_dso_module); if (ctx->modules != NULL) { return "is duplicate"; } ctx->modules = ngx_array_create(cf->pool, 50, sizeof(ngx_dso_module_t)); if (ctx->modules == NULL) { return NGX_CONF_ERROR; } ctx->stubs = ngx_array_create(cf->pool, 50, sizeof(ngx_str_t)); if (ctx->stubs == NULL) { return NGX_CONF_ERROR; } ctx->flag_postion = ngx_dso_get_position(&module_flagpole[0].entry); if (ctx->flag_postion == NGX_ERROR) { return NGX_CONF_ERROR; } *(ngx_dso_conf_ctx_t **) conf = ctx; ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "dso flag postion (%i)", ctx->flag_postion); pcf = *cf; cf->ctx = ctx; cf->module_type = NGX_CORE_MODULE; cf->handler = ngx_dso_parse; cf->handler_conf = conf; rv = ngx_conf_parse(cf, NULL); if (rv != NGX_CONF_OK) { goto failed; } rv = ngx_dso_load(cf); if (rv == NGX_CONF_ERROR) { goto failed; } *cf = pcf; return NGX_CONF_OK; failed: *cf = pcf; return rv; }
static char * ngx_stream_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; void *mconf; ngx_uint_t m; ngx_conf_t pcf; ngx_stream_module_t *module; ngx_stream_conf_ctx_t *ctx, *stream_ctx; ngx_stream_core_srv_conf_t *cscf, **cscfp; ngx_stream_core_main_conf_t *cmcf; ctx = ngx_pcalloc(cf->pool, sizeof(ngx_stream_conf_ctx_t)); if (ctx == NULL) { return NGX_CONF_ERROR; } stream_ctx = cf->ctx; ctx->main_conf = stream_ctx->main_conf; /* the server{}'s srv_conf */ ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_stream_max_module); if (ctx->srv_conf == NULL) { return NGX_CONF_ERROR; } for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_STREAM_MODULE) { continue; } module = ngx_modules[m]->ctx; if (module->create_srv_conf) { mconf = module->create_srv_conf(cf); if (mconf == NULL) { return NGX_CONF_ERROR; } ctx->srv_conf[ngx_modules[m]->ctx_index] = mconf; } } /* the server configuration context */ cscf = ctx->srv_conf[ngx_stream_core_module.ctx_index]; cscf->ctx = ctx; cmcf = ctx->main_conf[ngx_stream_core_module.ctx_index]; cscfp = ngx_array_push(&cmcf->servers); if (cscfp == NULL) { return NGX_CONF_ERROR; } *cscfp = cscf; /* parse inside server{} */ pcf = *cf; cf->ctx = ctx; cf->cmd_type = NGX_STREAM_SRV_CONF; rv = ngx_conf_parse(cf, NULL); *cf = pcf; return rv; }
static char * ngx_dso_include(ngx_conf_t *cf, ngx_dso_conf_ctx_t *ctx, ngx_str_t *name) { char *rv; ngx_str_t file; ngx_conf_t pcf; file.len = name->len; file.data = ngx_pnalloc(cf->temp_pool, name->len + 1); if (file.data == NULL) { return NGX_CONF_ERROR; } ngx_sprintf(file.data, "%V%Z", name); if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) { return NGX_CONF_ERROR; } pcf = *cf; cf->ctx = ctx; cf->module_type = NGX_CORE_MODULE; rv = ngx_conf_parse(cf, &file); *cf = pcf; return rv; }
static char * ngx_http_geoip2(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_geoip2_conf_t *gcf = conf; ngx_str_t *value; int status, nelts, i; ngx_http_geoip2_db_t *database; char *rv; ngx_conf_t save; value = cf->args->elts; if (gcf->databases == NULL) { gcf->databases = ngx_array_create(cf->pool, 2, sizeof(ngx_http_geoip2_db_t)); if (gcf->databases == NULL) { return NGX_CONF_ERROR; } } else { nelts = (int) gcf->databases->nelts; database = gcf->databases->elts; for (i = 0; i < nelts; i++) { if (ngx_strcmp(value[1].data, database[i].mmdb.filename) == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "Duplicate GeoIP2 mmdb - %V", &value[1]); return NGX_CONF_ERROR; } } } database = ngx_array_push(gcf->databases); if (database == NULL) { return NGX_CONF_ERROR; } status = MMDB_open((char *) value[1].data, MMDB_MODE_MMAP, &database->mmdb); if (status != MMDB_SUCCESS) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "MMDB_open(\"%V\") failed - %s", &value[1], MMDB_strerror(status)); return NGX_CONF_ERROR; } #if (NGX_HAVE_INET6) ngx_memset(&database->address, 0, sizeof(database->address)); #else database->address = 0; #endif save = *cf; cf->handler = ngx_http_geoip2_add_variable; cf->handler_conf = (void *) database; rv = ngx_conf_parse(cf, NULL); *cf = save; return rv; }
static char * ngx_http_user_agent_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; ngx_str_t *value, name; ngx_conf_t save; ngx_http_variable_t *var; ngx_http_user_agent_ctx_t *ctx; value = cf->args->elts; name = value[1]; name.data++; name.len--; var = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE); if (var == NULL) { return NGX_CONF_ERROR; } ctx = ngx_palloc(cf->pool, sizeof(ngx_http_user_agent_ctx_t)); if (ctx == NULL) { return NGX_CONF_ERROR; } ctx->pool = cf->pool; ctx->trie = ngx_trie_create(ctx->pool); if (ctx->trie == NULL) { return NGX_CONF_ERROR; } ctx->default_value = NULL; var->get_handler = ngx_http_user_agent_variable; var->data = (uintptr_t) ctx; save = *cf; cf->ctx = ctx; cf->handler = ngx_http_user_agent; cf->handler_conf = conf; rv = ngx_conf_parse(cf, NULL); if (NGX_OK != ctx->trie->build_clue(ctx->trie)) { return NGX_CONF_ERROR; } *cf = save; if (ctx->default_value == NULL) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "no default value"); rv = NGX_CONF_ERROR; } return rv; }
static char * ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; ngx_int_t n; ngx_str_t *value, file; ngx_glob_t gl; value = cf->args->elts; file = value[1]; ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); if (ngx_conf_full_name(cf->cycle, &file) == NGX_ERROR) { return NGX_CONF_ERROR; } ngx_memzero(&gl, sizeof(ngx_glob_t)); gl.pattern = file.data; gl.log = cf->log; if (ngx_open_glob(&gl) != NGX_OK) { ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, ngx_open_glob_n " \"%s\" failed", file.data); return NGX_CONF_ERROR; } rv = NGX_CONF_OK; for ( ;; ) { n = ngx_read_glob(&gl, &file); if (n != NGX_OK) { break; } ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); rv = ngx_conf_parse(cf, &file); if (rv != NGX_CONF_OK) { break; } } ngx_close_glob(&gl); return rv; }
/** * Reads token_server block and sets ngx_http_gettoken_server as a handler of each conf value */ static char * ngx_http_gettoken_server_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; ngx_str_t *value, name; ngx_conf_t save; ngx_http_gettoken_server_t *server; ngx_http_gettoken_main_conf_t *cnf = conf; value = cf->args->elts; name = value[1]; if (ngx_strlen(name.data) == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "http_gettoken: Missing server name in server"); return NGX_CONF_ERROR; } if (cnf->servers == NULL) { cnf->servers = ngx_array_create(cf->pool, 6, sizeof(ngx_http_gettoken_server_t)); if (cnf->servers == NULL) { return NGX_CONF_ERROR; } } server = ngx_array_push(cnf->servers); if (server == NULL) { return NGX_CONF_ERROR; } ngx_memzero(server, sizeof(*server)); server->connect_timeout = 10000; server->reconnect_timeout = 10000; server->request_im_token_timeout = 5000; server->request_timeout = 10000; server->alias = name; save = *cf; cf->handler = ngx_http_gettoken_server; cf->handler_conf = conf; rv = ngx_conf_parse(cf, NULL); *cf = save; if (rv != NGX_CONF_OK) { return rv; } return NGX_CONF_OK; }
static char *ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_str_t *value, file; value = cf->args->elts; file = value[1]; if (ngx_conf_full_name(cf->cycle, &file) == NGX_ERROR){ return NGX_CONF_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); return ngx_conf_parse(cf, &file); }
static char * ngx_http_store_plusplus_path_group_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; ngx_http_store_plusplus_path_t **a; ngx_http_store_plusplus_path_t *store_path; char *rv; ngx_conf_t save; a = (ngx_http_store_plusplus_path_t **) (p + cmd->offset); if (*a != NGX_CONF_UNSET_PTR) { return "is duplicate"; } // TODO: parse parameter level store_path = ngx_pcalloc(cf->pool, sizeof(ngx_http_store_plusplus_path_t)); if (store_path == NULL) { return NGX_CONF_ERROR; } save = *cf; cf->handler = ngx_http_store_plusplus_path_conf; cf->handler_conf = (void *) store_path; rv = ngx_conf_parse(cf, NULL); *cf = save; if (rv != NGX_CONF_OK) { return rv; } if (!store_path->paths->nelts) { // TODO: check whether block is empty } *a = store_path; return rv; }
/*内部解析Nginx配置文件*/ char * ngx_conf_param(ngx_conf_t *cf) { char *rv; ngx_str_t *param; ngx_buf_t b; ngx_conf_file_t conf_file; param = &cf->cycle->conf_param; if (param->len == 0) { return NGX_CONF_OK; } /*以下为初始化解析配置文件时要用到的保存配置信息的结构体和指示解析位置的"游标"*/ ngx_memzero(&conf_file, sizeof(ngx_conf_file_t)); ngx_memzero(&b, sizeof(ngx_buf_t)); /*以下为初始化解析配置文件时用到的位置标识*/ b.start = param->data; b.pos = param->data; b.last = param->data + param->len; b.end = b.last; b.temporary = 1; conf_file.file.fd = NGX_INVALID_FILE; conf_file.file.name.data = NULL; conf_file.line = 0; cf->conf_file = &conf_file; cf->conf_file->buffer = &b; /*执行具体的配置文件解析工作,第二个参数为NULL,说明此次解析的内容为补充配置*/ rv = ngx_conf_parse(cf, NULL); cf->conf_file = NULL; return rv; }
char * ngx_conf_param(ngx_conf_t *cf) { char *rv; ngx_str_t *param; ngx_buf_t b; ngx_conf_file_t conf_file; param = &cf->cycle->conf_param; if (param->len == 0) { return NGX_CONF_OK; } ngx_memzero(&conf_file, sizeof(ngx_conf_file_t)); ngx_memzero(&b, sizeof(ngx_buf_t)); b.start = param->data; b.pos = param->data; b.last = param->data + param->len; b.end = b.last; b.temporary = 1; // ngx_conf_parse() 函数根据NGX_INVALID_FILE 这个值来判断解释的block中的内容还是param conf_file.file.fd = NGX_INVALID_FILE; conf_file.file.name.data = NULL; conf_file.line = 0; cf->conf_file = &conf_file; cf->conf_file->buffer = &b; // 以上信息为填充cf结构体,用于ngx_conf_parse函数解析 rv = ngx_conf_parse(cf, NULL); // 恢复cf原值,用于下一次ngx_conf_parse() 参考:main函数中的调用 cf->conf_file = NULL; return rv; }
/*解析-g携带的参数中需要特殊处理的配置项及其参数值*/ char * ngx_conf_param(ngx_conf_t *cf) { char *rv; ngx_str_t *param; ngx_buf_t b; ngx_conf_file_t conf_file; /*nginx处理配置文件时需要特殊处理的在命令行携带的参数,一般是-g 选项携带的参数*/ param = &cf->cycle->conf_param; if (param->len == 0) { return NGX_CONF_OK; } ngx_memzero(&conf_file, sizeof(ngx_conf_file_t)); ngx_memzero(&b, sizeof(ngx_buf_t)); b.start = param->data; b.pos = param->data; b.last = param->data + param->len; b.end = b.last; b.temporary = 1; conf_file.file.fd = NGX_INVALID_FILE; conf_file.file.name.data = NULL; conf_file.line = 0; cf->conf_file = &conf_file; cf->conf_file->buffer = &b; /*解析-g携带的参数中需要特殊处理的配置项及其参数值*/ rv = ngx_conf_parse(cf, NULL); cf->conf_file = NULL; return rv; }
static char * ngx_http_advertise_list(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_advertise_conf_t *accf = conf; char *rv; ngx_conf_t save; if (accf->advertise_array == NGX_CONF_UNSET_PTR) { accf->advertise_array = ngx_array_create(cf->pool, 16, sizeof(ngx_http_advertise_format)); if (accf->advertise_array == NULL) { return NGX_CONF_ERROR; } } save = *cf; cf->handler = ngx_http_advertise_item; cf->handler_conf = conf; rv = ngx_conf_parse(cf, NULL); *cf = save; return rv; }
//解析Nginx启动时命令行携带的参数 char * ngx_conf_param(ngx_conf_t *cf) { char *rv; ngx_str_t *param; ngx_buf_t b; ngx_conf_file_t conf_file; param = &cf->cycle->conf_param; if (param->len == 0) { return NGX_CONF_OK; } ngx_memzero(&conf_file, sizeof(ngx_conf_file_t)); ngx_memzero(&b, sizeof(ngx_buf_t)); b.start = param->data; b.pos = param->data; b.last = param->data + param->len; b.end = b.last; b.temporary = 1; conf_file.file.fd = NGX_INVALID_FILE; conf_file.file.name.data = NULL; conf_file.line = 0; cf->conf_file = &conf_file; cf->conf_file->buffer = &b; //我们直接总buffer中解析配置项,不需要传递文件名 rv = ngx_conf_parse(cf, NULL); cf->conf_file = NULL; return rv; }
static char * ngx_http_advertise_blackhosts(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_advertise_conf_t *accf = conf; char *rv; ngx_conf_t save; if (accf->black_hosts== NGX_CONF_UNSET_PTR) { accf->black_hosts = ngx_array_create(cf->pool, 16, sizeof(ngx_regex_elt_t)); if (accf->black_hosts == NULL) { return NGX_CONF_ERROR; } } save = *cf; cf->handler = ngx_http_advertise_blackhost; cf->handler_conf = conf; rv = ngx_conf_parse(cf, NULL); *cf = save; return rv; }
ngx_cycle_t * ngx_init_cycle(ngx_cycle_t *old_cycle) { void *rv; char **senv, **env; ngx_uint_t i, n; ngx_log_t *log; ngx_time_t *tp; ngx_conf_t conf; ngx_pool_t *pool; ngx_cycle_t *cycle, **old; ngx_shm_zone_t *shm_zone, *oshm_zone; ngx_list_part_t *part, *opart; ngx_open_file_t *file; ngx_listening_t *ls, *nls; ngx_core_conf_t *ccf, *old_ccf; ngx_core_module_t *module; char hostname[NGX_MAXHOSTNAMELEN]; ngx_timezone_update(); /* force localtime update with a new timezone */ tp = ngx_timeofday(); tp->sec = 0; ngx_time_update(); log = old_cycle->log; pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log); if (pool == NULL) { return NULL; } pool->log = log; cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t)); if (cycle == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->pool = pool; cycle->log = log; cycle->old_cycle = old_cycle; cycle->conf_prefix.len = old_cycle->conf_prefix.len; cycle->conf_prefix.data = ngx_pstrdup(pool, &old_cycle->conf_prefix); if (cycle->conf_prefix.data == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->prefix.len = old_cycle->prefix.len; cycle->prefix.data = ngx_pstrdup(pool, &old_cycle->prefix); if (cycle->prefix.data == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->conf_file.len = old_cycle->conf_file.len; cycle->conf_file.data = ngx_pnalloc(pool, old_cycle->conf_file.len + 1); if (cycle->conf_file.data == NULL) { ngx_destroy_pool(pool); return NULL; } ngx_cpystrn(cycle->conf_file.data, old_cycle->conf_file.data, old_cycle->conf_file.len + 1); cycle->conf_param.len = old_cycle->conf_param.len; cycle->conf_param.data = ngx_pstrdup(pool, &old_cycle->conf_param); if (cycle->conf_param.data == NULL) { ngx_destroy_pool(pool); return NULL; } n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10; cycle->paths.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)); if (cycle->paths.elts == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->paths.nelts = 0; cycle->paths.size = sizeof(ngx_path_t *); cycle->paths.nalloc = n; cycle->paths.pool = pool; if (old_cycle->open_files.part.nelts) { n = old_cycle->open_files.part.nelts; for (part = old_cycle->open_files.part.next; part; part = part->next) { n += part->nelts; } } else { n = 20; } if (ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t)) != NGX_OK) { ngx_destroy_pool(pool); return NULL; } if (old_cycle->shared_memory.part.nelts) { n = old_cycle->shared_memory.part.nelts; for (part = old_cycle->shared_memory.part.next; part; part = part->next) { n += part->nelts; } } else { n = 1; } if (ngx_list_init(&cycle->shared_memory, pool, n, sizeof(ngx_shm_zone_t)) != NGX_OK) { ngx_destroy_pool(pool); return NULL; } n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10; cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t)); if (cycle->listening.elts == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->listening.nelts = 0; cycle->listening.size = sizeof(ngx_listening_t); cycle->listening.nalloc = n; cycle->listening.pool = pool; ngx_queue_init(&cycle->reusable_connections_queue); cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *)); if (cycle->conf_ctx == NULL) { ngx_destroy_pool(pool); return NULL; } if (gethostname(hostname, NGX_MAXHOSTNAMELEN) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "gethostname() failed"); ngx_destroy_pool(pool); return NULL; } /* on Linux gethostname() silently truncates name that does not fit */ hostname[NGX_MAXHOSTNAMELEN - 1] = '\0'; cycle->hostname.len = ngx_strlen(hostname); cycle->hostname.data = ngx_pnalloc(pool, cycle->hostname.len); if (cycle->hostname.data == NULL) { ngx_destroy_pool(pool); return NULL; } ngx_strlow(cycle->hostname.data, (u_char *) hostname, cycle->hostname.len); for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_CORE_MODULE) { continue; } module = ngx_modules[i]->ctx; if (module->create_conf) { rv = module->create_conf(cycle); if (rv == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->conf_ctx[ngx_modules[i]->index] = rv; } } senv = environ; ngx_memzero(&conf, sizeof(ngx_conf_t)); /* STUB: init array ? */ conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t)); if (conf.args == NULL) { ngx_destroy_pool(pool); return NULL; } conf.temp_pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log); if (conf.temp_pool == NULL) { ngx_destroy_pool(pool); return NULL; } conf.ctx = cycle->conf_ctx; conf.cycle = cycle; conf.pool = pool; conf.log = log; conf.module_type = NGX_CORE_MODULE; conf.cmd_type = NGX_MAIN_CONF; #if 0 log->log_level = NGX_LOG_DEBUG_ALL; #endif if (ngx_conf_param(&conf) != NGX_CONF_OK) { environ = senv; ngx_destroy_cycle_pools(&conf); return NULL; } if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) { environ = senv; ngx_destroy_cycle_pools(&conf); return NULL; } if (ngx_test_config && !ngx_quiet_mode) { ngx_log_stderr(0, "the configuration file %s syntax is ok", cycle->conf_file.data); } for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_CORE_MODULE) { continue; } module = ngx_modules[i]->ctx; if (module->init_conf) { if (module->init_conf(cycle, cycle->conf_ctx[ngx_modules[i]->index]) == NGX_CONF_ERROR) { environ = senv; ngx_destroy_cycle_pools(&conf); return NULL; } } } if (ngx_process == NGX_PROCESS_SIGNALLER) { return cycle; } ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if (ngx_test_config) { if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) { goto failed; } } else if (!ngx_is_init_cycle(old_cycle)) { /* * we do not create the pid file in the first ngx_init_cycle() call * because we need to write the demonized process pid */ old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx, ngx_core_module); if (ccf->pid.len != old_ccf->pid.len || ngx_strcmp(ccf->pid.data, old_ccf->pid.data) != 0) { /* new pid file name */ if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) { goto failed; } ngx_delete_pidfile(old_cycle); } } if (ngx_test_lockfile(cycle->lock_file.data, log) != NGX_OK) { goto failed; } if (ngx_create_paths(cycle, ccf->user) != NGX_OK) { goto failed; } if (ngx_log_open_default(cycle) != NGX_OK) { goto failed; } /* open the new files */ part = &cycle->open_files.part; file = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; file = part->elts; i = 0; } if (file[i].name.len == 0) { continue; } file[i].fd = ngx_open_file(file[i].name.data, NGX_FILE_APPEND, NGX_FILE_CREATE_OR_OPEN, NGX_FILE_DEFAULT_ACCESS); ngx_log_debug3(NGX_LOG_DEBUG_CORE, log, 0, "log: %p %d \"%s\"", &file[i], file[i].fd, file[i].name.data); if (file[i].fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, ngx_open_file_n " \"%s\" failed", file[i].name.data); goto failed; } #if !(NGX_WIN32) if (fcntl(file[i].fd, F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "fcntl(FD_CLOEXEC) \"%s\" failed", file[i].name.data); goto failed; } #endif } cycle->log = &cycle->new_log; pool->log = &cycle->new_log; /* create shared memory */ part = &cycle->shared_memory.part; shm_zone = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; shm_zone = part->elts; i = 0; } if (shm_zone[i].shm.size == 0) { ngx_log_error(NGX_LOG_EMERG, log, 0, "zero size shared memory zone \"%V\"", &shm_zone[i].shm.name); goto failed; } shm_zone[i].shm.log = cycle->log; opart = &old_cycle->shared_memory.part; oshm_zone = opart->elts; for (n = 0; /* void */ ; n++) { if (n >= opart->nelts) { if (opart->next == NULL) { break; } opart = opart->next; oshm_zone = opart->elts; n = 0; } if (shm_zone[i].shm.name.len != oshm_zone[n].shm.name.len) { continue; } if (ngx_strncmp(shm_zone[i].shm.name.data, oshm_zone[n].shm.name.data, shm_zone[i].shm.name.len) != 0) { continue; } if (shm_zone[i].tag == oshm_zone[n].tag && shm_zone[i].shm.size == oshm_zone[n].shm.size) { shm_zone[i].shm.addr = oshm_zone[n].shm.addr; if (shm_zone[i].init(&shm_zone[i], oshm_zone[n].data) != NGX_OK) { goto failed; } goto shm_zone_found; } ngx_shm_free(&oshm_zone[n].shm); break; } if (ngx_shm_alloc(&shm_zone[i].shm) != NGX_OK) { goto failed; } if (ngx_init_zone_pool(cycle, &shm_zone[i]) != NGX_OK) { goto failed; } if (shm_zone[i].init(&shm_zone[i], NULL) != NGX_OK) { goto failed; } shm_zone_found: continue; } /* handle the listening sockets */ if (old_cycle->listening.nelts) { ls = old_cycle->listening.elts; for (i = 0; i < old_cycle->listening.nelts; i++) { ls[i].remain = 0; } nls = cycle->listening.elts; for (n = 0; n < cycle->listening.nelts; n++) { for (i = 0; i < old_cycle->listening.nelts; i++) { if (ls[i].ignore) { continue; } if (ngx_cmp_sockaddr(nls[n].sockaddr, ls[i].sockaddr) == NGX_OK) { nls[n].fd = ls[i].fd; nls[n].previous = &ls[i]; ls[i].remain = 1; if (ls[n].backlog != nls[i].backlog) { nls[n].listen = 1; } #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) /* * FreeBSD, except the most recent versions, * could not remove accept filter */ nls[n].deferred_accept = ls[i].deferred_accept; if (ls[i].accept_filter && nls[n].accept_filter) { if (ngx_strcmp(ls[i].accept_filter, nls[n].accept_filter) != 0) { nls[n].delete_deferred = 1; nls[n].add_deferred = 1; } } else if (ls[i].accept_filter) { nls[n].delete_deferred = 1; } else if (nls[n].accept_filter) { nls[n].add_deferred = 1; } #endif #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) if (ls[n].deferred_accept && !nls[n].deferred_accept) { nls[n].delete_deferred = 1; } else if (ls[i].deferred_accept != nls[n].deferred_accept) { nls[n].add_deferred = 1; } #endif break; } } if (nls[n].fd == (ngx_socket_t) -1) { nls[n].open = 1; #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) if (nls[n].accept_filter) { nls[n].add_deferred = 1; } #endif #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) if (nls[n].deferred_accept) { nls[n].add_deferred = 1; } #endif } } } else { ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { ls[i].open = 1; #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) if (ls[i].accept_filter) { ls[i].add_deferred = 1; } #endif #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) if (ls[i].deferred_accept) { ls[i].add_deferred = 1; } #endif } } if (ngx_open_listening_sockets(cycle) != NGX_OK) { goto failed; } if (!ngx_test_config) { ngx_configure_listening_sockets(cycle); } /* commit the new cycle configuration */ if (!ngx_use_stderr) { (void) ngx_log_redirect_stderr(cycle); } pool->log = cycle->log; for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->init_module) { if (ngx_modules[i]->init_module(cycle) != NGX_OK) { /* fatal */ exit(1); } } } /* close and delete stuff that lefts from an old cycle */ /* free the unnecessary shared memory */ opart = &old_cycle->shared_memory.part; oshm_zone = opart->elts; for (i = 0; /* void */ ; i++) { if (i >= opart->nelts) { if (opart->next == NULL) { goto old_shm_zone_done; } opart = opart->next; oshm_zone = opart->elts; i = 0; } part = &cycle->shared_memory.part; shm_zone = part->elts; for (n = 0; /* void */ ; n++) { if (n >= part->nelts) { if (part->next == NULL) { break; } part = part->next; shm_zone = part->elts; n = 0; } if (oshm_zone[i].shm.name.len == shm_zone[n].shm.name.len && ngx_strncmp(oshm_zone[i].shm.name.data, shm_zone[n].shm.name.data, oshm_zone[i].shm.name.len) == 0) { goto live_shm_zone; } } ngx_shm_free(&oshm_zone[i].shm); live_shm_zone: continue; } old_shm_zone_done: /* close the unnecessary listening sockets */ ls = old_cycle->listening.elts; for (i = 0; i < old_cycle->listening.nelts; i++) { if (ls[i].remain || ls[i].fd == (ngx_socket_t) -1) { continue; } if (ngx_close_socket(ls[i].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, ngx_close_socket_n " listening socket on %V failed", &ls[i].addr_text); } #if (NGX_HAVE_UNIX_DOMAIN) if (ls[i].sockaddr->sa_family == AF_UNIX) { u_char *name; name = ls[i].addr_text.data + sizeof("unix:") - 1; ngx_log_error(NGX_LOG_WARN, cycle->log, 0, "deleting socket %s", name); if (ngx_delete_file(name) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_delete_file_n " %s failed", name); } } #endif } /* close the unnecessary open files */ part = &old_cycle->open_files.part; file = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; file = part->elts; i = 0; } if (file[i].fd == NGX_INVALID_FILE || file[i].fd == ngx_stderr) { continue; } if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } ngx_destroy_pool(conf.temp_pool); if (ngx_process == NGX_PROCESS_MASTER || ngx_is_init_cycle(old_cycle)) { /* * perl_destruct() frees environ, if it is not the same as it was at * perl_construct() time, therefore we save the previous cycle * environment before ngx_conf_parse() where it will be changed. */ env = environ; environ = senv; ngx_destroy_pool(old_cycle->pool); cycle->old_cycle = NULL; environ = env; return cycle; } if (ngx_temp_pool == NULL) { ngx_temp_pool = ngx_create_pool(128, cycle->log); if (ngx_temp_pool == NULL) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "could not create ngx_temp_pool"); exit(1); } n = 10; ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool, n * sizeof(ngx_cycle_t *)); if (ngx_old_cycles.elts == NULL) { exit(1); } ngx_old_cycles.nelts = 0; ngx_old_cycles.size = sizeof(ngx_cycle_t *); ngx_old_cycles.nalloc = n; ngx_old_cycles.pool = ngx_temp_pool; ngx_cleaner_event.handler = ngx_clean_old_cycles; ngx_cleaner_event.log = cycle->log; ngx_cleaner_event.data = &dumb; dumb.fd = (ngx_socket_t) -1; } ngx_temp_pool->log = cycle->log; old = ngx_array_push(&ngx_old_cycles); if (old == NULL) { exit(1); } *old = old_cycle; if (!ngx_cleaner_event.timer_set) { ngx_add_timer(&ngx_cleaner_event, 30000); ngx_cleaner_event.timer_set = 1; } return cycle; failed: if (!ngx_is_init_cycle(old_cycle)) { old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx, ngx_core_module); if (old_ccf->environment) { environ = old_ccf->environment; } } /* rollback the new cycle configuration */ part = &cycle->open_files.part; file = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; file = part->elts; i = 0; } if (file[i].fd == NGX_INVALID_FILE || file[i].fd == ngx_stderr) { continue; } if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } if (ngx_test_config) { ngx_destroy_cycle_pools(&conf); return NULL; } ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { if (ls[i].fd == (ngx_socket_t) -1 || !ls[i].open) { continue; } if (ngx_close_socket(ls[i].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, ngx_close_socket_n " %V failed", &ls[i].addr_text); } } ngx_destroy_cycle_pools(&conf); return NULL; }
static char * ngx_rtmp_record_recorder(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; ngx_int_t i; ngx_str_t *value; ngx_conf_t save; ngx_rtmp_module_t *module; ngx_rtmp_core_app_conf_t *cacf, **pcacf, *rcacf; ngx_rtmp_record_app_conf_t *racf, **pracf, *rracf; ngx_rtmp_conf_ctx_t *ctx, *pctx; value = cf->args->elts; cacf = ngx_rtmp_conf_get_module_app_conf(cf, ngx_rtmp_core_module); racf = ngx_rtmp_conf_get_module_app_conf(cf, ngx_rtmp_record_module); ctx = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_conf_ctx_t)); if (ctx == NULL) { return NGX_CONF_ERROR; } pctx = cf->ctx; ctx->main_conf = pctx->main_conf; ctx->srv_conf = pctx->srv_conf; ctx->app_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_rtmp_max_module); if (ctx->app_conf == NULL) { return NGX_CONF_ERROR; } for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_RTMP_MODULE) { continue; } module = ngx_modules[i]->ctx; if (module->create_app_conf) { ctx->app_conf[ngx_modules[i]->ctx_index] = module->create_app_conf(cf); if (ctx->app_conf[ngx_modules[i]->ctx_index] == NULL) { return NGX_CONF_ERROR; } } } /* add to sub-applications */ rcacf = ctx->app_conf[ngx_rtmp_core_module.ctx_index]; rcacf->app_conf = ctx->app_conf; pcacf = ngx_array_push(&cacf->applications); if (pcacf == NULL) { return NGX_CONF_ERROR; } *pcacf = rcacf; /* add to recorders */ rracf = ctx->app_conf[ngx_rtmp_record_module.ctx_index]; rracf->rec_conf = ctx->app_conf; pracf = ngx_array_push(&racf->rec); if (pracf == NULL) { return NGX_CONF_ERROR; } *pracf = rracf; rracf->id = value[1]; save = *cf; cf->ctx = ctx; cf->cmd_type = NGX_RTMP_REC_CONF; rv = ngx_conf_parse(cf, NULL); *cf= save; return rv; }
static char * ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) { ngx_int_t rc; ngx_str_t *value, file; ngx_uint_t i, key; ngx_http_map_conf_ctx_t *ctx; ngx_http_variable_value_t *var, **vp; ctx = cf->ctx; value = cf->args->elts; if (cf->args->nelts == 1 && ngx_strcmp(value[0].data, "hostnames") == 0) { ctx->hostnames = 1; return NGX_CONF_OK; } else if (cf->args->nelts != 2) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid number of the map parameters"); return NGX_CONF_ERROR; } else if (value[0].len == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid first parameter"); return NGX_CONF_ERROR; } if (ngx_strcmp(value[0].data, "include") == 0) { file = value[1]; if (ngx_conf_full_name(cf->cycle, &file) == NGX_ERROR){ return NGX_CONF_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); return ngx_conf_parse(cf, &file); } key = 0; for (i = 0; i < value[1].len; i++) { key = ngx_hash(key, value[1].data[i]); } key %= ctx->keys.hsize; vp = ctx->values_hash[key].elts; if (vp) { for (i = 0; i < ctx->values_hash[key].nelts; i++) { if (value[1].len != (size_t) vp[i]->len) { continue; } if (ngx_strncmp(value[1].data, vp[i]->data, value[1].len) == 0) { var = vp[i]; goto found; } } } else { if (ngx_array_init(&ctx->values_hash[key], cf->pool, 4, sizeof(ngx_http_variable_value_t *)) != NGX_OK) { return NGX_CONF_ERROR; } } var = ngx_palloc(ctx->keys.pool, sizeof(ngx_http_variable_value_t)); if (var == NULL) { return NGX_CONF_ERROR; } var->len = value[1].len; var->data = ngx_pstrdup(ctx->keys.pool, &value[1]); if (var->data == NULL) { return NGX_CONF_ERROR; } var->valid = 1; var->no_cacheable = 0; var->not_found = 0; vp = ngx_array_push(&ctx->values_hash[key]); if (vp == NULL) { return NGX_CONF_ERROR; } *vp = var; found: if (ngx_strcmp(value[0].data, "default") == 0) { if (ctx->default_value) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "duplicate default map parameter"); return NGX_CONF_ERROR; } ctx->default_value = var; return NGX_CONF_OK; } if (value[0].len && value[0].data[0] == '!') { value[0].len--; value[0].data++; } rc = ngx_hash_add_key(&ctx->keys, &value[0], var, (ctx->hostnames) ? NGX_HASH_WILDCARD_KEY : 0); if (rc == NGX_OK) { return NGX_CONF_OK; } if (rc == NGX_DECLINED) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid hostname or wildcard \"%V\"", &value[0]); } if (rc == NGX_BUSY) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "conflicting parameter \"%V\"", &value[0]); } return NGX_CONF_ERROR; }
static char * ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_map_conf_t *mcf = conf; char *rv; ngx_str_t *value, name; ngx_conf_t save; ngx_pool_t *pool; ngx_hash_init_t hash; ngx_http_map_ctx_t *map; ngx_http_variable_t *var; ngx_http_map_conf_ctx_t ctx; if (mcf->hash_max_size == NGX_CONF_UNSET_UINT) { mcf->hash_max_size = 2048; } if (mcf->hash_bucket_size == NGX_CONF_UNSET_UINT) { mcf->hash_bucket_size = ngx_cacheline_size; } else { mcf->hash_bucket_size = ngx_align(mcf->hash_bucket_size, ngx_cacheline_size); } map = ngx_pcalloc(cf->pool, sizeof(ngx_http_map_ctx_t)); if (map == NULL) { return NGX_CONF_ERROR; } value = cf->args->elts; name = value[1]; name.len--; name.data++; map->index = ngx_http_get_variable_index(cf, &name); if (map->index == NGX_ERROR) { return NGX_CONF_ERROR; } name = value[2]; name.len--; name.data++; var = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE); if (var == NULL) { return NGX_CONF_ERROR; } var->get_handler = ngx_http_map_variable; var->data = (uintptr_t) map; pool = ngx_create_pool(16384, cf->log); if (pool == NULL) { return NGX_CONF_ERROR; } ctx.keys.pool = cf->pool; ctx.keys.temp_pool = pool; if (ngx_hash_keys_array_init(&ctx.keys, NGX_HASH_LARGE) != NGX_OK) { ngx_destroy_pool(pool); return NGX_CONF_ERROR; } ctx.values_hash = ngx_pcalloc(pool, sizeof(ngx_array_t) * ctx.keys.hsize); if (ctx.values_hash == NULL) { ngx_destroy_pool(pool); return NGX_CONF_ERROR; } ctx.default_value = NULL; ctx.hostnames = 0; save = *cf; cf->pool = pool; cf->ctx = &ctx; cf->handler = ngx_http_map; cf->handler_conf = conf; rv = ngx_conf_parse(cf, NULL); *cf = save; if (rv != NGX_CONF_OK) { ngx_destroy_pool(pool); return rv; } map->default_value = ctx.default_value ? ctx.default_value: &ngx_http_variable_null_value; hash.key = ngx_hash_key_lc; hash.max_size = mcf->hash_max_size; hash.bucket_size = mcf->hash_bucket_size; hash.name = "map_hash"; hash.pool = cf->pool; if (ctx.keys.keys.nelts) { hash.hash = &map->hash.hash; hash.temp_pool = NULL; if (ngx_hash_init(&hash, ctx.keys.keys.elts, ctx.keys.keys.nelts) != NGX_OK) { ngx_destroy_pool(pool); return NGX_CONF_ERROR; } } if (ctx.keys.dns_wc_head.nelts) { ngx_qsort(ctx.keys.dns_wc_head.elts, (size_t) ctx.keys.dns_wc_head.nelts, sizeof(ngx_hash_key_t), ngx_http_map_cmp_dns_wildcards); hash.hash = NULL; hash.temp_pool = pool; if (ngx_hash_wildcard_init(&hash, ctx.keys.dns_wc_head.elts, ctx.keys.dns_wc_head.nelts) != NGX_OK) { ngx_destroy_pool(pool); return NGX_CONF_ERROR; } map->hash.wc_head = (ngx_hash_wildcard_t *) hash.hash; } if (ctx.keys.dns_wc_tail.nelts) { ngx_qsort(ctx.keys.dns_wc_tail.elts, (size_t) ctx.keys.dns_wc_tail.nelts, sizeof(ngx_hash_key_t), ngx_http_map_cmp_dns_wildcards); hash.hash = NULL; hash.temp_pool = pool; if (ngx_hash_wildcard_init(&hash, ctx.keys.dns_wc_tail.elts, ctx.keys.dns_wc_tail.nelts) != NGX_OK) { ngx_destroy_pool(pool); return NGX_CONF_ERROR; } map->hash.wc_tail = (ngx_hash_wildcard_t *) hash.hash; } ngx_destroy_pool(pool); return rv; }
static char * ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; ngx_uint_t mi, m, s; ngx_conf_t pcf; ngx_http_module_t *module; ngx_http_conf_ctx_t *ctx; ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t **cscfp; ngx_http_core_main_conf_t *cmcf; /* the main http context */ ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); if (ctx == NULL) { return NGX_CONF_ERROR; } *(ngx_http_conf_ctx_t **) conf = ctx; /* count the number of the http modules and set up their indices */ ngx_http_max_module = 0; for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_HTTP_MODULE) { continue; } ngx_modules[m]->ctx_index = ngx_http_max_module++; } /* the http main_conf context, it is the same in the all http contexts */ ctx->main_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); if (ctx->main_conf == NULL) { return NGX_CONF_ERROR; } /* * the http null srv_conf context, it is used to merge * the server{}s' srv_conf's */ ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); if (ctx->srv_conf == NULL) { return NGX_CONF_ERROR; } /* * the http null loc_conf context, it is used to merge * the server{}s' loc_conf's */ ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); if (ctx->loc_conf == NULL) { return NGX_CONF_ERROR; } /* * create the main_conf's, the null srv_conf's, and the null loc_conf's * of the all http modules */ for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_HTTP_MODULE) { continue; } module = ngx_modules[m]->ctx; mi = ngx_modules[m]->ctx_index; if (module->create_main_conf) { ctx->main_conf[mi] = module->create_main_conf(cf); if (ctx->main_conf[mi] == NULL) { return NGX_CONF_ERROR; } } if (module->create_srv_conf) { ctx->srv_conf[mi] = module->create_srv_conf(cf); if (ctx->srv_conf[mi] == NULL) { return NGX_CONF_ERROR; } } if (module->create_loc_conf) { ctx->loc_conf[mi] = module->create_loc_conf(cf); if (ctx->loc_conf[mi] == NULL) { return NGX_CONF_ERROR; } } } pcf = *cf; cf->ctx = ctx; for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_HTTP_MODULE) { continue; } module = ngx_modules[m]->ctx; if (module->preconfiguration) { if (module->preconfiguration(cf) != NGX_OK) { return NGX_CONF_ERROR; } } } /* parse inside the http{} block */ cf->module_type = NGX_HTTP_MODULE; cf->cmd_type = NGX_HTTP_MAIN_CONF; rv = ngx_conf_parse(cf, NULL); if (rv != NGX_CONF_OK) { goto failed; } /* * init http{} main_conf's, merge the server{}s' srv_conf's * and its location{}s' loc_conf's */ cmcf = ctx->main_conf[ngx_http_core_module.ctx_index]; cscfp = cmcf->servers.elts; for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_HTTP_MODULE) { continue; } module = ngx_modules[m]->ctx; mi = ngx_modules[m]->ctx_index; /* init http{} main_conf's */ if (module->init_main_conf) { rv = module->init_main_conf(cf, ctx->main_conf[mi]); if (rv != NGX_CONF_OK) { goto failed; } } for (s = 0; s < cmcf->servers.nelts; s++) { /* merge the server{}s' srv_conf's */ if (module->merge_srv_conf) { rv = module->merge_srv_conf(cf, ctx->srv_conf[mi], cscfp[s]->ctx->srv_conf[mi]); if (rv != NGX_CONF_OK) { goto failed; } } if (module->merge_loc_conf) { /* merge the server{}'s loc_conf */ rv = module->merge_loc_conf(cf, ctx->loc_conf[mi], cscfp[s]->ctx->loc_conf[mi]); if (rv != NGX_CONF_OK) { goto failed; } /* merge the locations{}' loc_conf's */ clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index]; rv = ngx_http_merge_locations(cf, clcf->locations, cscfp[s]->ctx->loc_conf, module, mi); if (rv != NGX_CONF_OK) { goto failed; } } } } /* create location trees */ for (s = 0; s < cmcf->servers.nelts; s++) { clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index]; if (ngx_http_init_locations(cf, cscfp[s], clcf) != NGX_OK) { return NGX_CONF_ERROR; } if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) { return NGX_CONF_ERROR; } } if (ngx_http_init_phases(cf, cmcf) != NGX_OK) { return NGX_CONF_ERROR; } if (ngx_http_init_headers_in_hash(cf, cmcf) != NGX_OK) { return NGX_CONF_ERROR; } for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_HTTP_MODULE) { continue; } module = ngx_modules[m]->ctx; if (module->postconfiguration) { if (module->postconfiguration(cf) != NGX_OK) { return NGX_CONF_ERROR; } } } if (ngx_http_variables_init_vars(cf) != NGX_OK) { return NGX_CONF_ERROR; } /* * http{}'s cf->ctx was needed while the configuration merging * and in postconfiguration process */ *cf = pcf; if (ngx_http_init_phase_handlers(cf, cmcf) != NGX_OK) { return NGX_CONF_ERROR; } /* optimize the lists of ports, addresses and server names */ if (ngx_http_optimize_servers(cf, cmcf, cmcf->ports) != NGX_OK) { return NGX_CONF_ERROR; } return NGX_CONF_OK; failed: *cf = pcf; return rv; }
static char * ngx_http_eval_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_eval_loc_conf_t *ecf, *pecf = conf; char *rv; void *mconf; ngx_str_t name; ngx_uint_t i; ngx_conf_t save; ngx_http_module_t *module; ngx_http_conf_ctx_t *ctx, *pctx; ngx_http_core_loc_conf_t *clcf, *pclcf, *rclcf; ngx_http_core_srv_conf_t *cscf; if(ngx_http_eval_add_variables(cf, cmd, conf) != NGX_CONF_OK) { return NGX_CONF_ERROR; } ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); if (ctx == NULL) { return NGX_CONF_ERROR; } pctx = cf->ctx; ctx->main_conf = pctx->main_conf; ctx->srv_conf = pctx->srv_conf; ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); if (ctx->loc_conf == NULL) { return NGX_CONF_ERROR; } for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_HTTP_MODULE) { continue; } module = ngx_modules[i]->ctx; if (module->create_loc_conf) { mconf = module->create_loc_conf(cf); if (mconf == NULL) { return NGX_CONF_ERROR; } ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf; } } ecf = ctx->loc_conf[ngx_http_eval_module.ctx_index]; pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index]; clcf = ctx->loc_conf[ngx_http_core_module.ctx_index]; name.len = sizeof("/eval_") - 1 + NGX_OFF_T_LEN; name.data = ngx_palloc(cf->pool, name.len); if(name.data == NULL) { return NGX_CONF_ERROR; } name.len = ngx_sprintf(name.data, "/eval_%O", (off_t)(uintptr_t)clcf) - name.data; clcf->loc_conf = ctx->loc_conf; clcf->name = name; clcf->exact_match = 0; clcf->noname = 0; clcf->internal = 1; clcf->noregex = 1; cscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module); rclcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index]; if (ngx_http_add_location(cf, &rclcf->locations, clcf) != NGX_OK) { return NGX_CONF_ERROR; } pecf->eval_location = clcf->name; save = *cf; cf->ctx = ctx; cf->cmd_type = NGX_HTTP_LOC_CONF; rv = ngx_conf_parse(cf, NULL); *cf = save; return rv; }
static char * ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_rewrite_loc_conf_t *lcf = conf; void *mconf; char *rv; u_char *elts; ngx_uint_t i; ngx_conf_t save; ngx_http_module_t *module; ngx_http_conf_ctx_t *ctx, *pctx; ngx_http_core_loc_conf_t *clcf, *pclcf; ngx_http_script_if_code_t *if_code; ngx_http_rewrite_loc_conf_t *nlcf; ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); if (ctx == NULL) { return NGX_CONF_ERROR; } pctx = cf->ctx; ctx->main_conf = pctx->main_conf; ctx->srv_conf = pctx->srv_conf; ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); if (ctx->loc_conf == NULL) { return NGX_CONF_ERROR; } for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_HTTP_MODULE) { continue; } module = ngx_modules[i]->ctx; if (module->create_loc_conf) { mconf = module->create_loc_conf(cf); if (mconf == NULL) { return NGX_CONF_ERROR; } ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf; } } pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index]; clcf = ctx->loc_conf[ngx_http_core_module.ctx_index]; clcf->loc_conf = ctx->loc_conf; clcf->name = pclcf->name; clcf->noname = 1; if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) { return NGX_CONF_ERROR; } if (ngx_http_rewrite_if_condition(cf, lcf) != NGX_CONF_OK) { return NGX_CONF_ERROR; } if_code = ngx_array_push_n(lcf->codes, sizeof(ngx_http_script_if_code_t)); if (if_code == NULL) { return NGX_CONF_ERROR; } if_code->code = ngx_http_script_if_code; elts = lcf->codes->elts; /* the inner directives must be compiled to the same code array */ nlcf = ctx->loc_conf[ngx_http_rewrite_module.ctx_index]; nlcf->codes = lcf->codes; save = *cf; cf->ctx = ctx; if (pclcf->name.len == 0) { if_code->loc_conf = NULL; cf->cmd_type = NGX_HTTP_SIF_CONF; } else { if_code->loc_conf = ctx->loc_conf; cf->cmd_type = NGX_HTTP_LIF_CONF; } rv = ngx_conf_parse(cf, NULL); *cf = save; if (rv != NGX_CONF_OK) { return rv; } if (elts != lcf->codes->elts) { if_code = (ngx_http_script_if_code_t *) ((u_char *) if_code + ((u_char *) lcf->codes->elts - elts)); } if_code->next = (u_char *) lcf->codes->elts + lcf->codes->nelts - (u_char *) if_code; /* the code array belong to parent block */ nlcf->codes = NULL; return NGX_CONF_OK; }
static char * ngx_mail_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; void *mconf; ngx_uint_t m; ngx_conf_t pcf; ngx_mail_module_t *module; ngx_mail_conf_ctx_t *ctx, *mail_ctx; ngx_mail_core_srv_conf_t *cscf, **cscfp; ngx_mail_core_main_conf_t *cmcf; ctx = ngx_pcalloc(cf->pool, sizeof(ngx_mail_conf_ctx_t)); if (ctx == NULL) { return NGX_CONF_ERROR; } mail_ctx = cf->ctx; ctx->main_conf = mail_ctx->main_conf; /* the server{}'s srv_conf */ ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_mail_max_module); if (ctx->srv_conf == NULL) { return NGX_CONF_ERROR; } for (m = 0; cf->cycle->modules[m]; m++) { if (cf->cycle->modules[m]->type != NGX_MAIL_MODULE) { continue; } module = cf->cycle->modules[m]->ctx; if (module->create_srv_conf) { mconf = module->create_srv_conf(cf); if (mconf == NULL) { return NGX_CONF_ERROR; } ctx->srv_conf[cf->cycle->modules[m]->ctx_index] = mconf; } } /* the server configuration context */ cscf = ctx->srv_conf[ngx_mail_core_module.ctx_index]; cscf->ctx = ctx; cmcf = ctx->main_conf[ngx_mail_core_module.ctx_index]; cscfp = ngx_array_push(&cmcf->servers); if (cscfp == NULL) { return NGX_CONF_ERROR; } *cscfp = cscf; /* parse inside server{} */ pcf = *cf; cf->ctx = ctx; cf->cmd_type = NGX_MAIL_SRV_CONF; rv = ngx_conf_parse(cf, NULL); *cf = pcf; if (rv == NGX_CONF_OK && !cscf->listen) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"listen\" is defined for server in %s:%ui", cscf->file_name, cscf->line); return NGX_CONF_ERROR; } return rv; }
static char * ngx_rtmp_core_application(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; ngx_int_t i; ngx_str_t *value; ngx_conf_t save; ngx_rtmp_module_t *module; ngx_rtmp_conf_ctx_t *ctx, *pctx; ngx_rtmp_core_srv_conf_t *cscf; ngx_rtmp_core_app_conf_t *cacf, **cacfp; ctx = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_conf_ctx_t)); if (ctx == NULL) { return NGX_CONF_ERROR; } pctx = cf->ctx; ctx->main_conf = pctx->main_conf; ctx->srv_conf = pctx->srv_conf; ctx->app_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_rtmp_max_module); if (ctx->app_conf == NULL) { return NGX_CONF_ERROR; } for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_RTMP_MODULE) { continue; } module = ngx_modules[i]->ctx; if (module->create_app_conf) { ctx->app_conf[ngx_modules[i]->ctx_index] = module->create_app_conf(cf); if (ctx->app_conf[ngx_modules[i]->ctx_index] == NULL) { return NGX_CONF_ERROR; } } } cacf = ctx->app_conf[ngx_rtmp_core_module.ctx_index]; cacf->app_conf = ctx->app_conf; value = cf->args->elts; cacf->name = value[1]; cscf = pctx->srv_conf[ngx_rtmp_core_module.ctx_index]; cacfp = ngx_array_push(&cscf->applications); if (cacfp == NULL) { return NGX_CONF_ERROR; } *cacfp = cacf; save = *cf; cf->ctx = ctx; cf->cmd_type = NGX_RTMP_APP_CONF; rv = ngx_conf_parse(cf, NULL); *cf= save; return rv; }
/* * 包含一个配置文件,并读取解析配置文件 */ char * ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; ngx_int_t n; ngx_str_t *value, file, name; ngx_glob_t gl; value = cf->args->elts; file = value[1]; //配置文件名 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) { return NGX_CONF_ERROR; } /*是否包含正则表达式*/ if (strpbrk((char *) file.data, "*?[") == NULL) { ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); return ngx_conf_parse(cf, &file); } ngx_memzero(&gl, sizeof(ngx_glob_t)); gl.pattern = file.data; gl.log = cf->log; gl.test = 1; if (ngx_open_glob(&gl) != NGX_OK) { ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, ngx_open_glob_n " \"%s\" failed", file.data); return NGX_CONF_ERROR; } rv = NGX_CONF_OK; /*解析配置文件, 所有满足正则表达式的文件 */ for ( ;; ) { n = ngx_read_glob(&gl, &name); if (n != NGX_OK) { break; } file.len = name.len++; file.data = ngx_pstrdup(cf->pool, &name); if (file.data == NULL) { return NGX_CONF_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); rv = ngx_conf_parse(cf, &file); if (rv != NGX_CONF_OK) { break; } } ngx_close_glob(&gl); return rv; }
static char * ngx_stream_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) { char *rv; void *mconf; ngx_str_t *value; ngx_url_t u; ngx_uint_t m; ngx_conf_t pcf; ngx_stream_module_t *module; ngx_stream_conf_ctx_t *ctx, *stream_ctx; ngx_stream_upstream_srv_conf_t *uscf; ngx_memzero(&u, sizeof(ngx_url_t)); value = cf->args->elts; u.host = value[1]; u.no_resolve = 1; u.no_port = 1; uscf = ngx_stream_upstream_add(cf, &u, NGX_STREAM_UPSTREAM_CREATE |NGX_STREAM_UPSTREAM_WEIGHT |NGX_STREAM_UPSTREAM_MAX_FAILS |NGX_STREAM_UPSTREAM_FAIL_TIMEOUT |NGX_STREAM_UPSTREAM_DOWN |NGX_STREAM_UPSTREAM_BACKUP); if (uscf == NULL) { return NGX_CONF_ERROR; } ctx = ngx_pcalloc(cf->pool, sizeof(ngx_stream_conf_ctx_t)); if (ctx == NULL) { return NGX_CONF_ERROR; } stream_ctx = cf->ctx; ctx->main_conf = stream_ctx->main_conf; /* the upstream{}'s srv_conf */ ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_stream_max_module); if (ctx->srv_conf == NULL) { return NGX_CONF_ERROR; } ctx->srv_conf[ngx_stream_upstream_module.ctx_index] = uscf; uscf->srv_conf = ctx->srv_conf; for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_STREAM_MODULE) { continue; } module = ngx_modules[m]->ctx; if (module->create_srv_conf) { mconf = module->create_srv_conf(cf); if (mconf == NULL) { return NGX_CONF_ERROR; } ctx->srv_conf[ngx_modules[m]->ctx_index] = mconf; } } uscf->servers = ngx_array_create(cf->pool, 4, sizeof(ngx_stream_upstream_server_t)); if (uscf->servers == NULL) { return NGX_CONF_ERROR; } /* parse inside upstream{} */ pcf = *cf; cf->ctx = ctx; cf->cmd_type = NGX_STREAM_UPS_CONF; rv = ngx_conf_parse(cf, NULL); *cf = pcf; if (rv != NGX_CONF_OK) { return rv; } if (uscf->servers->nelts == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "no servers are inside upstream"); return NGX_CONF_ERROR; } return rv; }
static char * ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; void ***ctx; ngx_uint_t i; ngx_conf_t pcf; ngx_event_module_t *m; if (*(void **) conf) { return "is duplicate"; } /* count the number of the event modules and set up their indices */ ngx_event_max_module = 0; for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_EVENT_MODULE) { continue; } ngx_modules[i]->ctx_index = ngx_event_max_module++; } ctx = ngx_pcalloc(cf->pool, sizeof(void *)); if (ctx == NULL) { return NGX_CONF_ERROR; } *ctx = ngx_pcalloc(cf->pool, ngx_event_max_module * sizeof(void *)); if (*ctx == NULL) { return NGX_CONF_ERROR; } *(void **) conf = ctx; for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_EVENT_MODULE) { continue; } m = ngx_modules[i]->ctx; if (m->create_conf) { (*ctx)[ngx_modules[i]->ctx_index] = m->create_conf(cf->cycle); if ((*ctx)[ngx_modules[i]->ctx_index] == NULL) { return NGX_CONF_ERROR; } } } pcf = *cf; cf->ctx = ctx; cf->module_type = NGX_EVENT_MODULE; cf->cmd_type = NGX_EVENT_CONF; rv = ngx_conf_parse(cf, NULL); *cf = pcf; if (rv != NGX_CONF_OK) return rv; for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_EVENT_MODULE) { continue; } m = ngx_modules[i]->ctx; if (m->init_conf) { rv = m->init_conf(cf->cycle, (*ctx)[ngx_modules[i]->ctx_index]); if (rv != NGX_CONF_OK) { return rv; } } } return NGX_CONF_OK; }
static char * ngx_handoff_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; ngx_uint_t i, m, mi, s; ngx_conf_t pcf; ngx_array_t ports; ngx_handoff_listen_t *listen; ngx_handoff_module_t *module; ngx_handoff_conf_ctx_t *ctx; ngx_handoff_core_srv_conf_t **cscfp; ngx_handoff_core_main_conf_t *cmcf; /* the main tcp context */ ctx = ngx_pcalloc(cf->pool, sizeof(ngx_handoff_conf_ctx_t)); if (ctx == NULL) { return NGX_CONF_ERROR; } *(ngx_handoff_conf_ctx_t **) conf = ctx; /* count the number of the tcp modules and set up their indices */ ngx_handoff_max_module = 0; for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_HANDOFF_MODULE) { continue; } ngx_modules[m]->ctx_index = ngx_handoff_max_module++; } /* the tcp main_conf context, it is the same in the all tcp contexts */ ctx->main_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_handoff_max_module); if (ctx->main_conf == NULL) { return NGX_CONF_ERROR; } /* * the tcp null srv_conf context, it is used to merge * the server{}s' srv_conf's */ ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_handoff_max_module); if (ctx->srv_conf == NULL) { return NGX_CONF_ERROR; } /* * create the main_conf's, the null srv_conf's, and the null loc_conf's * of the all handoff modules */ for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_HANDOFF_MODULE) { continue; } module = ngx_modules[m]->ctx; mi = ngx_modules[m]->ctx_index; if (module->create_main_conf) { ctx->main_conf[mi] = module->create_main_conf(cf); if (ctx->main_conf[mi] == NULL) { return NGX_CONF_ERROR; } } if (module->create_srv_conf) { ctx->srv_conf[mi] = module->create_srv_conf(cf); if (ctx->srv_conf[mi] == NULL) { return NGX_CONF_ERROR; } } } /* parse inside the handoff{} block */ pcf = *cf; cf->ctx = ctx; cf->module_type = NGX_HANDOFF_MODULE; cf->cmd_type = NGX_HANDOFF_MAIN_CONF; rv = ngx_conf_parse(cf, NULL); if (rv != NGX_CONF_OK) { *cf = pcf; return rv; } /* init tcp{} main_conf's, merge the server{}s' srv_conf's */ cmcf = ctx->main_conf[ngx_handoff_core_module.ctx_index]; cscfp = cmcf->servers.elts; for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_HANDOFF_MODULE) { continue; } module = ngx_modules[m]->ctx; mi = ngx_modules[m]->ctx_index; /* init tcp{} main_conf's */ cf->ctx = ctx; if (module->init_main_conf) { rv = module->init_main_conf(cf, ctx->main_conf[mi]); if (rv != NGX_CONF_OK) { *cf = pcf; return rv; } } for (s = 0; s < cmcf->servers.nelts; s++) { /* merge the server{}s' srv_conf's */ cf->ctx = cscfp[s]->ctx; if (module->merge_srv_conf) { rv = module->merge_srv_conf(cf, ctx->srv_conf[mi], cscfp[s]->ctx->srv_conf[mi]); if (rv != NGX_CONF_OK) { *cf = pcf; return rv; } } } } *cf = pcf; if (ngx_array_init(&ports, cf->temp_pool, 4, sizeof(ngx_handoff_conf_port_t)) != NGX_OK) { return NGX_CONF_ERROR; } listen = cmcf->listen.elts; for (i = 0; i < cmcf->listen.nelts; i++) { if (ngx_handoff_add_ports(cf, &ports, &listen[i]) != NGX_OK) { return NGX_CONF_ERROR; } } return ngx_handoff_optimize_servers(cf, cmcf, &ports); }
// 解析stream{}配置块,与events类似 // tcp流处理的配置结构体,里面有main_conf/srv_conf两个数组 // 在cycle里存储配置指针 // 设置stream模块的ctx_index // 分配存储main_conf/srv_conf的数组,数量是ngx_stream_max_module // 遍历模块数组,调用每个stream模块create_xxx_conf,创建配置结构体 // 之后解析配置,解析完成后初始化main_conf,合并srv_conf,调用postconfiguration // 得到stream_core里的监听端口 // 调用ngx_create_listening添加到cycle的监听端口数组,只是添加,没有其他动作 // 设置有连接发生时的回调函数ngx_stream_init_connection static char * ngx_stream_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; ngx_uint_t i, m, mi, s; ngx_conf_t pcf; ngx_array_t ports; ngx_stream_listen_t *listen; ngx_stream_module_t *module; ngx_stream_conf_ctx_t *ctx; ngx_stream_core_srv_conf_t **cscfp; ngx_stream_core_main_conf_t *cmcf; // tcp流处理的配置结构体,里面有main_conf/srv_conf两个数组 // 不允许重复配置 // // conf里存储的是ngx_stream_conf_ctx_t * // 注意指针的转型,可以理解为(ngx_stream_conf_ctx_t*)* if (*(ngx_stream_conf_ctx_t **) conf) { return "is duplicate"; } /* the main stream context */ // 创建配置结构体 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_stream_conf_ctx_t)); if (ctx == NULL) { return NGX_CONF_ERROR; } // 在cycle里存储这个指针 // conf里存储的是ngx_stream_conf_ctx_t * // 注意指针的转型,可以理解为(ngx_stream_conf_ctx_t*)* *(ngx_stream_conf_ctx_t **) conf = ctx; /* count the number of the stream modules and set up their indices */ // 得到所有的stream模块数量 // 设置stream模块的ctx_index ngx_stream_max_module = 0; for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_STREAM_MODULE) { continue; } // 设置stream模块的ctx_index ngx_modules[m]->ctx_index = ngx_stream_max_module++; } /* the stream main_conf context, it's the same in the all stream contexts */ // 分配存储main_conf的数组,数量是ngx_stream_max_module ctx->main_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_stream_max_module); if (ctx->main_conf == NULL) { return NGX_CONF_ERROR; } /* * the stream null srv_conf context, it is used to merge * the server{}s' srv_conf's */ // 分配存储srv_conf的数组,数量是ngx_stream_max_module ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_stream_max_module); if (ctx->srv_conf == NULL) { return NGX_CONF_ERROR; } /* * create the main_conf's and the null srv_conf's of the all stream modules */ // 遍历模块数组,调用每个stream模块create_xxx_conf,创建配置结构体 // 这些配置结构体存储在最顶层,也就是stream_main for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_STREAM_MODULE) { continue; } module = ngx_modules[m]->ctx; mi = ngx_modules[m]->ctx_index; // 创建每个模块的main_conf if (module->create_main_conf) { ctx->main_conf[mi] = module->create_main_conf(cf); if (ctx->main_conf[mi] == NULL) { return NGX_CONF_ERROR; } } // 创建每个模块的srv_conf if (module->create_srv_conf) { ctx->srv_conf[mi] = module->create_srv_conf(cf); if (ctx->srv_conf[mi] == NULL) { return NGX_CONF_ERROR; } } } /* parse inside the stream{} block */ // 初始的解析环境已经准备好,下面开始解析stream{}配置 // 暂存当前的解析上下文 pcf = *cf; // 设置事件模块的新解析上下文 // 之前的ctx是cycle->conf_ctx // 此时ctx是ngx_stream_conf_ctx_t指针,里面存储了配置数组 cf->ctx = ctx; // 设定之后解析的模块类型必须是stream cf->module_type = NGX_STREAM_MODULE; // 指令的作用域是stream main cf->cmd_type = NGX_STREAM_MAIN_CONF; // 递归解析stream模块 rv = ngx_conf_parse(cf, NULL); if (rv != NGX_CONF_OK) { // 恢复之前保存的解析上下文 *cf = pcf; return rv; } /* init stream{} main_conf's, merge the server{}s' srv_conf's */ // 检查stream_core的main配置结构体 cmcf = ctx->main_conf[ngx_stream_core_module.ctx_index]; // 得到配置的server数量 cscfp = cmcf->servers.elts; // 初始化main_conf,合并srv_conf // 注意cf->ctx会不断变化 for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_STREAM_MODULE) { continue; } // module是流模块的函数表,用于解析配置时调用 module = ngx_modules[m]->ctx; mi = ngx_modules[m]->ctx_index; /* init stream{} main_conf's */ // 当前的ctx回到stream{}的数组 // 这样下面的操作才能获得正确的配置结构体 cf->ctx = ctx; if (module->init_main_conf) { rv = module->init_main_conf(cf, ctx->main_conf[mi]); if (rv != NGX_CONF_OK) { *cf = pcf; return rv; } } // 遍历每一个server{}配置块 for (s = 0; s < cmcf->servers.nelts; s++) { /* merge the server{}s' srv_conf's */ // 从server的ctx里得到server的配置数组,修改ctx // 这样才能获得server正确的配置 cf->ctx = cscfp[s]->ctx; if (module->merge_srv_conf) { rv = module->merge_srv_conf(cf, ctx->srv_conf[mi], cscfp[s]->ctx->srv_conf[mi]); if (rv != NGX_CONF_OK) { *cf = pcf; return rv; } } } } // 配置解析完毕,调用模块的postconfiguration for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_STREAM_MODULE) { continue; } // module是stream模块的函数表,用于解析配置时调用 module = ngx_modules[m]->ctx; if (module->postconfiguration) { if (module->postconfiguration(cf) != NGX_OK) { return NGX_CONF_ERROR; } } } // 最后恢复之前保存的解析上下文 *cf = pcf; // 初始化一个动态数组,准备存储监听端口 if (ngx_array_init(&ports, cf->temp_pool, 4, sizeof(ngx_stream_conf_port_t)) != NGX_OK) { return NGX_CONF_ERROR; } // 得到stream_core里的监听端口 // ngx_stream_core_listen添加,可能多个server都监听相同的端口 // 故listen数组里可能会有端口相同的元素 listen = cmcf->listen.elts; for (i = 0; i < cmcf->listen.nelts; i++) { // 把监听结构体添加进ports数组 // 多个相同的监听端口用一个数组元素,在addrs.opt里保存 if (ngx_stream_add_ports(cf, &ports, &listen[i]) != NGX_OK) { return NGX_CONF_ERROR; } } // 对已经整理好的监听端口数组排序 // 调用ngx_create_listening添加到cycle的监听端口数组,只是添加,没有其他动作 // 设置有连接发生时的回调函数ngx_stream_init_connection return ngx_stream_optimize_servers(cf, &ports); }