ngx_http_add_addrs6

张开发
2026/4/8 0:05:27 15 分钟阅读

分享文章

ngx_http_add_addrs6
1 定义ngx_http_add_addrs6 函数 定义在 ./nginx-1.24.0/src/http/ngx_http.cstaticngx_int_tngx_http_add_addrs6(ngx_conf_t*cf,ngx_http_port_t*hport,ngx_http_conf_addr_t*addr){ngx_uint_ti;ngx_http_in6_addr_t*addrs6;structsockaddr_in6*sin6;ngx_http_virtual_names_t*vn;hport-addrsngx_pcalloc(cf-pool,hport-naddrs*sizeof(ngx_http_in6_addr_t));if(hport-addrsNULL){returnNGX_ERROR;}addrs6hport-addrs;for(i0;ihport-naddrs;i){sin6(structsockaddr_in6*)addr[i].opt.sockaddr;addrs6[i].addr6sin6-sin6_addr;addrs6[i].conf.default_serveraddr[i].default_server;#if(NGX_HTTP_SSL)addrs6[i].conf.ssladdr[i].opt.ssl;#endif#if(NGX_HTTP_V2)addrs6[i].conf.http2addr[i].opt.http2;#endifaddrs6[i].conf.proxy_protocoladdr[i].opt.proxy_protocol;if(addr[i].hash.bucketsNULL(addr[i].wc_headNULL||addr[i].wc_head-hash.bucketsNULL)(addr[i].wc_tailNULL||addr[i].wc_tail-hash.bucketsNULL)#if(NGX_PCRE)addr[i].nregex0#endif){continue;}vnngx_palloc(cf-pool,sizeof(ngx_http_virtual_names_t));if(vnNULL){returnNGX_ERROR;}addrs6[i].conf.virtual_namesvn;vn-names.hashaddr[i].hash;vn-names.wc_headaddr[i].wc_head;vn-names.wc_tailaddr[i].wc_tail;#if(NGX_PCRE)vn-nregexaddr[i].nregex;vn-regexaddr[i].regex;#endif}returnNGX_OK;}ngx_http_add_addrs6 函数的作用是 将解析得到的 IPv6 地址配置转换为端口结构内部使用的地址数组 以便 Nginx 在运行时能够根据每个 IPv6 地址独立处理连接和虚拟主机匹配。2 详解函数签名staticngx_int_tngx_http_add_addrs6(ngx_conf_t*cf,ngx_http_port_t*hport,ngx_http_conf_addr_t*addr)返回值 NGX_OK (0)成功。 NGX_ERROR (-1)失败参数 ngx_conf_t *cf 指向配置解析上下文 ngx_http_port_t *hport 代表一个 监听端口 的抽象结构 该结构包含了该端口上所有地址的配置信息、监听套接字、连接处理函数等 该参数是函数的 输出目标即函数将转换后的地址配置存储到 hport 中 ngx_http_conf_addr_t *addr 指向一个 配置地址数组 的起始位置。 每个元素代表一个具体的 IPv6 地址 是本次要处理的输入数据2 逻辑流程1 局部变量 2 分配内存 3 循环遍历处理每个输入的地址配置 4 返回成功1 局部变量{ngx_uint_ti;ngx_http_in6_addr_t*addrs6;structsockaddr_in6*sin6;ngx_http_virtual_names_t*vn;2 分配内存hport-addrsngx_pcalloc(cf-pool,hport-naddrs*sizeof(ngx_http_in6_addr_t));if(hport-addrsNULL){returnNGX_ERROR;}为 hport 分配一块连续的内存 用于存放该端口上所有 IPv6 地址的配置信息。 清零初始化 使用 ngx_pcalloc 分配的同时将内存全部清零 确保未显式赋值的字段具有安全的初始值0 或 NULL。 错误处理 若分配失败函数立即返回 NGX_ERROR终止当前配置处理流程。3 循环遍历处理每个输入的地址配置addrs6hport-addrs;for(i0;ihport-naddrs;i){sin6(structsockaddr_in6*)addr[i].opt.sockaddr;addrs6[i].addr6sin6-sin6_addr;addrs6[i].conf.default_serveraddr[i].default_server;#if(NGX_HTTP_SSL)addrs6[i].conf.ssladdr[i].opt.ssl;#endif#if(NGX_HTTP_V2)addrs6[i].conf.http2addr[i].opt.http2;#endifaddrs6[i].conf.proxy_protocoladdr[i].opt.proxy_protocol;if(addr[i].hash.bucketsNULL(addr[i].wc_headNULL||addr[i].wc_head-hash.bucketsNULL)(addr[i].wc_tailNULL||addr[i].wc_tail-hash.bucketsNULL)#if(NGX_PCRE)addr[i].nregex0#endif){continue;}vnngx_palloc(cf-pool,sizeof(ngx_http_virtual_names_t));if(vnNULL){returnNGX_ERROR;}addrs6[i].conf.virtual_namesvn;vn-names.hashaddr[i].hash;vn-names.wc_headaddr[i].wc_head;vn-names.wc_tailaddr[i].wc_tail;#if(NGX_PCRE)vn-nregexaddr[i].nregex;vn-regexaddr[i].regex;#endif}#1 将局部指针 addrs6 指向刚刚分配好的 hport-addrs 内存区域#2 循环遍历每个地址配置 循环次数 hport-naddrs 是该端口上需要绑定的 IPv6 地址总数 每次循环处理一个地址addr[i] 是输入配置 addrs6[i] 是输出结果#3 获取 IPv6 套接字地址并复制 IP#4 复制基础配置标志#5 如果该地址没有任何虚拟主机名配置包括精确匹配、通配符前缀、通配符后缀、正则表达式 则不需要分配 virtual_names 结构直接跳过后续代码continue 此时 addrs6[i].conf.virtual_names 保持为 NULL。 条件拆解 addr[i].hash.buckets NULL 精确匹配的哈希表ngx_hash_t未初始化没有 server_name 精确匹配项。 addr[i].wc_head NULL 或者没有前缀通配符结构如 *.example.com。 如果 wc_head 非空还需要检查其内部的 hash.buckets 是否为 NULL即虽然创建了结构但实际没有条目。 addr[i].wc_tail NULL 同理后缀通配符如 www.*为空或没有实际条目。 #if (NGX_PCRE) 如果支持正则表达式则要求 addr[i].nregex 0即没有正则匹配的 server_name。 逻辑意义 性能优化 大多数简单的 server 块可能只监听一个 IP 端口 没有复杂的虚拟主机名或者只有默认服务器。 此时不需要分配额外的 virtual_names 结构节省内存。 当客户端连接到达时如果 virtual_names 为 NULL Nginx 会直接使用该地址的默认服务器或仅有的服务器配置。 只有真正需要基于域名包括通配符和正则分发请求的地址才会携带 virtual_names。#6 分配 virtual_names 结构体 将指针绑定到当前地址的 conf.virtual_names。 浅拷贝Shallow Copy 直接将配置期已构建好的 哈希表指针、通配符结构指针、正则数组指针赋值给运行态结构。4 返回成功returnNGX_OK;}

更多文章