ngx_http_add_address

发布于:2025-03-23 ⋅ 阅读:(24) ⋅ 点赞:(0)
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博客