static ngx_int_t
ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt)
{
ngx_http_conf_addr_t *addr;
if (port->addrs.elts == NULL) {
if (ngx_array_init(&port->addrs, cf->temp_pool, 4,
sizeof(ngx_http_conf_addr_t))
!= NGX_OK)
{
return NGX_ERROR;
}
}
#if (NGX_HTTP_V2 && NGX_HTTP_SSL \
&& !defined TLSEXT_TYPE_application_layer_protocol_negotiation)
if (lsopt->http2 && lsopt->ssl) {
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"nginx was built with OpenSSL that lacks ALPN "
"support, HTTP/2 is not enabled for %V",
&lsopt->addr_text);
}
#endif
addr = ngx_array_push(&port->addrs);
if (addr == NULL) {
return NGX_ERROR;
}
addr->opt = *lsopt;
addr->protocols = 0;
addr->protocols_set = 0;
addr->protocols_changed = 0;
addr->hash.buckets = NULL;
addr->hash.size = 0;
addr->wc_head = NULL;
addr->wc_tail = NULL;
#if (NGX_PCRE)
addr->nregex = 0;
addr->regex = NULL;
#endif
addr->default_server = cscf;
addr->servers.elts = NULL;
return ngx_http_add_server(cf, cscf, addr);
}
if (port->addrs.elts == NULL) {
if (ngx_array_init(&port->addrs, cf->temp_pool, 4,
sizeof(ngx_http_conf_addr_t))
!= NGX_OK)
{
return NGX_ERROR;
}
}
检查数组是否已初始化
port->addrs.elts == NULL
:通过判断ngx_array_t
类型的addrs
结构中的elts
指针是否为空,确定该数组是否已被初始化。elts
是 Nginx 动态数组(ngx_array_t
)的实际数据存储指针。如果为NULL
,说明数组尚未分配内存。
此时 port->addrs.elts=NULL
初始化动态数组
ngx_array_init(&port->addrs, cf->temp_pool, 4, sizeof(ngx_http_conf_addr_t))
:参数说明 :
&port->addrs
:指向要初始化的动态数组结构。
cf->temp_pool
:使用 Nginx 的临时内存池(ngx_pool_t
)分配内存,确保配置阶段的内存管理高效且无泄漏。
4
:初始预分配的数组元素数量(即初始容量为 4 个ngx_http_conf_addr_t
对象)。
sizeof(ngx_http_conf_addr_t)
:每个数组元素的大小。功能 :为数组分配初始内存,并设置内部状态(如
nelts=0
,size=4
等)。错误处理 :
如果
ngx_array_init
返回NGX_ERROR
(内存分配失败或初始化错误),函数直接返回NGX_ERROR
,终止当前配置流程,确保程序在资源不足时不会继续执行错误配置。
addr = ngx_array_push(&port->addrs);
if (addr == NULL) {
return NGX_ERROR;
}
addr->opt = *lsopt;
addr->protocols = 0;
addr->protocols_set = 0;
addr->protocols_changed = 0;
addr->hash.buckets = NULL;
addr->hash.size = 0;
addr->wc_head = NULL;
addr->wc_tail = NULL;
#if (NGX_PCRE)
addr->nregex = 0;
addr->regex = NULL;
#endif
addr->default_server = cscf;
addr->servers.elts = NULL;
return ngx_http_add_server(cf, cscf, addr);
将新的监听地址配置添加到端口的地址列表中
ngx_http_conf_addr_t-CSDN博客
addr->opt = *lsopt;
将用户配置的监听选项(如 IP、端口、SSL、HTTP/2 等)复制到新地址结构中
addr->protocols = 0; addr->protocols_set = 0; addr->protocols_changed = 0;
重置协议标志位,用于后续标记该地址支持的协议
字段含义 :
protocols
:位掩码,记录实际启用的协议。protocols_set
:记录用户显式配置的协议(如listen 443 ssl http2
)。protocols_changed
:标记协议配置是否被修改(用于配置阶段的兼容性检查)addr->hash.buckets = NULL; addr->hash.size = 0;
- 功能 :初始化哈希表结构(
ngx_hash_t
),用于快速匹配虚拟主机名。- 意义 :在请求到达时,通过哈希表快速定位到对应的服务器配置(如
server_name
匹配)addr->wc_head = NULL; addr->wc_tail = NULL;
- 功能 :初始化通配符匹配链表指针。
- 意义 :支持
server_name
中的通配符(如*.example.com
),通过链表管理这些规则。#if (NGX_PCRE) addr->nregex = 0; addr->regex = NULL; #endif
初始化正则表达式匹配相关字段
addr->default_server = cscf;
- 功能 :将当前解析的服务器块(
server
配置)设置为该地址的默认服务器。- 意义 :当请求的
Host
头无法匹配任何虚拟主机时,使用此默认服务器处理请求addr->servers.elts = NULL;
初始化服务器列表(
ngx_array_t
),用于存储所有绑定到该地址的服务器配置return ngx_http_add_server(cf, cscf, addr);
将当前服务器配置(
cscf
)与监听地址(addr
)关联ngx_http_add_server-CSDN博客