memoize iface addrs separately

This commit is contained in:
Aaron Paterson 2025-11-20 14:05:55 -07:00
parent 932f14d2ac
commit fded1547ec
3 changed files with 60 additions and 33 deletions

View file

@ -328,18 +328,18 @@ func (st *ServerType) listenersForServerBlockAddress(sblock serverBlock, addr Ad
}
// use a map to prevent duplication
interfaceAddresses := map[string][]string{}
listeners := map[string]map[string]struct{}{}
interfaces := map[string][]net.Addr{}
for _, lnCfgVal := range lnCfgVals {
addresses := make([]string, 0, len(lnCfgVal.addresses))
addresses = append(addresses, lnCfgVal.addresses...)
lnAddresses := make([]string, 0, len(lnCfgVal.addresses))
lnAddresses = append(lnAddresses, lnCfgVal.addresses...)
for _, lnIface := range lnCfgVal.interfaces {
lnNetw, lnDevice, _, err := caddy.SplitNetworkAddress(lnIface)
if err != nil {
return nil, fmt.Errorf("splitting listener interface: %v", err)
}
ifaceAddresses, ok := interfaceAddresses[lnDevice]
ifaceAddresses, ok := interfaces[lnDevice]
if !ok {
iface, err := net.InterfaceByName(lnDevice)
if err != nil {
@ -348,34 +348,61 @@ func (st *ServerType) listenersForServerBlockAddress(sblock serverBlock, addr Ad
if iface == nil {
return nil, fmt.Errorf("querying listener interface: %v", lnDevice)
}
ifaceAddrs, err := iface.Addrs()
ifaceAddresses, err := iface.Addrs()
if err != nil {
return nil, fmt.Errorf("querying listener interface addresses: %v: %v", lnDevice, err)
}
for _, ifaceAddr := range ifaceAddrs {
var ip string
switch ifaceAddrValue := ifaceAddr.(type) {
case *net.IPAddr:
ip = ifaceAddrValue.IP.String()
case *net.IPNet:
ip = ifaceAddrValue.IP.String()
default:
ip = ifaceAddrValue.String()
}
if len(ip) == net.IPv4len && caddy.IsIPv4Network(lnNetw) || len(ip) == net.IPv6len && caddy.IsIPv6Network(lnNetw) {
ifaceAddresses = append(ifaceAddresses, ip)
}
}
if len(ifaceAddresses) == 0 {
return nil, fmt.Errorf("querying listener interface addresses for network: %v: %v", lnDevice, lnNetw)
}
interfaceAddresses[lnDevice] = ifaceAddresses
interfaces[lnDevice] = ifaceAddresses
}
lnIfaceAddresses := []string{}
for _, ifaceAddress := range ifaceAddresses {
addresses = append(addresses, caddy.JoinNetworkAddress(lnNetw, ifaceAddress, ""))
var (
ip net.IP
ipok bool
)
switch ifaceAddressValue := ifaceAddress.(type) {
case *net.IPAddr:
ip, ipok = ifaceAddressValue.IP, true
case *net.IPNet:
ip, ipok = ifaceAddressValue.IP, true
case *net.TCPAddr:
ip, ipok = ifaceAddressValue.IP, true
case *net.UDPAddr:
ip, ipok = ifaceAddressValue.IP, true
}
if ipok {
if len(ip) == net.IPv4len && caddy.IsIPv4Network(lnNetw) || len(ip) == net.IPv6len && caddy.IsIPv6Network(lnNetw) {
lnIfaceAddresses = append(lnIfaceAddresses, ip.String())
}
continue
}
var (
name string
nameok bool
)
switch ifaceAddressValue := ifaceAddress.(type) {
case *net.UnixAddr:
name, nameok = ifaceAddressValue.Name, true
}
if nameok {
if caddy.IsUnixNetwork(lnNetw) {
lnIfaceAddresses = append(lnIfaceAddresses, name)
}
continue
}
lnIfaceAddresses = append(lnIfaceAddresses, ifaceAddress.String())
}
if len(lnIfaceAddresses) == 0 {
return nil, fmt.Errorf("no available listener interface addresses for network: %v: %v", lnDevice, lnNetw)
}
for _, lnIfaceAddress := range lnIfaceAddresses {
lnAddresses = append(lnAddresses, caddy.JoinNetworkAddress(lnNetw, lnIfaceAddress, ""))
}
}
for _, lnAddr := range addresses {
for _, lnAddr := range lnAddresses {
lnNetw, lnHost, _, err := caddy.SplitNetworkAddress(lnAddr)
if err != nil {
return nil, fmt.Errorf("splitting listener address: %v", err)

View file

@ -171,7 +171,7 @@ func (na NetworkAddress) Listen(ctx context.Context, portOffset uint, config net
address = na.JoinHostPort(portOffset)
}
if na.IsIPNetwork() {
if na.IsIPTransportNetwork() {
ln, err = config.ListenPacket(ctx, na.Network, address)
} else {
if na.IsUnixNetwork() {
@ -225,10 +225,10 @@ func (na NetworkAddress) IsUDPNetwork() bool {
return IsUDPNetwork(na.Network)
}
// IsIPNetwork returns true if na.Network starts with
// IsIPTransportNetwork returns true if na.Network starts with
// ip: ip4: or ip6:
func (na NetworkAddress) IsIPNetwork() bool {
return IsIPNetwork(na.Network)
func (na NetworkAddress) IsIPTransportNetwork() bool {
return IsIPTransportNetwork(na.Network)
}
// IsFDNetwork returns true if na.Network is

View file

@ -55,8 +55,8 @@ func IsUDPNetwork(netw string) bool {
return netw == UDP || netw == UDP4 || netw == UDP6
}
// IsIPNetwork returns true if the netw is an ip network.
func IsIPNetwork(netw string) bool {
// IsIPTransportNetwork returns true if the netw is an ip: network.
func IsIPTransportNetwork(netw string) bool {
return strings.HasPrefix(netw, IP_) || strings.HasPrefix(netw, IP4_) || strings.HasPrefix(netw, IP6_)
}
@ -69,7 +69,7 @@ func IsReservedNetwork(network string) bool {
return IsUnixNetwork(network) ||
IsTCPNetwork(network) ||
IsUDPNetwork(network) ||
IsIPNetwork(network) ||
IsIPTransportNetwork(network) ||
IsFDNetwork(network)
}
@ -86,7 +86,7 @@ func IsStreamNetwork(netw string) bool {
}
func IsPacketNetwork(netw string) bool {
return netw == UNIXGRAM || IsUDPNetwork(netw) || IsIPNetwork(netw) || netw == FDGRAM
return netw == UNIXGRAM || IsUDPNetwork(netw) || IsIPTransportNetwork(netw) || netw == FDGRAM
}
// ListenerFunc is a function that can return a listener given a network and address.