// 解析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); }
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; 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; } *(ngx_stream_conf_ctx_t **) conf = ctx; /* count the number of the stream modules and set up their indices */ ngx_stream_max_module = ngx_count_modules(cf->cycle, NGX_STREAM_MODULE); /* the stream main_conf context, it's the same in the all stream contexts */ 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 */ 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 */ for (m = 0; cf->cycle->modules[m]; m++) { if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) { continue; } module = cf->cycle->modules[m]->ctx; mi = cf->cycle->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; } } } pcf = *cf; cf->ctx = ctx; for (m = 0; cf->cycle->modules[m]; m++) { if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) { continue; } module = cf->cycle->modules[m]->ctx; if (module->preconfiguration) { if (module->preconfiguration(cf) != NGX_OK) { return NGX_CONF_ERROR; } } } /* parse inside the stream{} block */ cf->module_type = NGX_STREAM_MODULE; cf->cmd_type = NGX_STREAM_MAIN_CONF; 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 */ cmcf = ctx->main_conf[ngx_stream_core_module.ctx_index]; cscfp = cmcf->servers.elts; for (m = 0; cf->cycle->modules[m]; m++) { if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) { continue; } module = cf->cycle->modules[m]->ctx; mi = cf->cycle->modules[m]->ctx_index; /* init stream{} 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; } } } } if (ngx_stream_init_phases(cf, cmcf) != NGX_OK) { return NGX_CONF_ERROR; } for (m = 0; cf->cycle->modules[m]; m++) { if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) { continue; } module = cf->cycle->modules[m]->ctx; if (module->postconfiguration) { if (module->postconfiguration(cf) != NGX_OK) { return NGX_CONF_ERROR; } } } if (ngx_stream_variables_init_vars(cf) != NGX_OK) { return NGX_CONF_ERROR; } *cf = pcf; if (ngx_stream_init_phase_handlers(cf, cmcf) != NGX_OK) { return NGX_CONF_ERROR; } if (ngx_array_init(&ports, cf->temp_pool, 4, sizeof(ngx_stream_conf_port_t)) != NGX_OK) { return NGX_CONF_ERROR; } listen = cmcf->listen.elts; for (i = 0; i < cmcf->listen.nelts; i++) { if (ngx_stream_add_ports(cf, &ports, &listen[i]) != NGX_OK) { return NGX_CONF_ERROR; } } return ngx_stream_optimize_servers(cf, &ports); }