package net
import (
)
const cacheMaxAge = 5 * time.Second
func ( string) string {
, := netip.ParseAddr()
if != nil {
return ""
}
return .String()
}
type byName struct {
addrs []string
canonicalName string
}
var hosts struct {
sync.Mutex
byName map[string]byName
byAddr map[string][]string
expire time.Time
path string
mtime time.Time
size int64
}
func () {
:= time.Now()
:= hostsFilePath
if .Before(hosts.expire) && hosts.path == && len(hosts.byName) > 0 {
return
}
, , := stat()
if == nil && hosts.path == && hosts.mtime.Equal() && hosts.size == {
hosts.expire = .Add(cacheMaxAge)
return
}
:= make(map[string]byName)
:= make(map[string][]string)
, := open()
if != nil {
if !errors.Is(, fs.ErrNotExist) && !errors.Is(, fs.ErrPermission) {
return
}
}
if != nil {
defer .close()
for , := .readLine(); ; , = .readLine() {
if := bytealg.IndexByteString(, '#'); >= 0 {
= [0:]
}
:= getFields()
if len() < 2 {
continue
}
:= parseLiteralIP([0])
if == "" {
continue
}
var string
for := 1; < len(); ++ {
:= absDomainName([])
:= []byte([])
lowerASCIIBytes()
:= absDomainName(string())
if == 1 {
=
}
[] = append([], )
if , := []; {
[] = byName{
addrs: append(.addrs, ),
canonicalName: .canonicalName,
}
continue
}
[] = byName{
addrs: []string{},
canonicalName: ,
}
}
}
}
hosts.expire = .Add(cacheMaxAge)
hosts.path =
hosts.byName =
hosts.byAddr =
hosts.mtime =
hosts.size =
}
func ( string) ([]string, string) {
hosts.Lock()
defer hosts.Unlock()
readHosts()
if len(hosts.byName) != 0 {
if hasUpperCase() {
:= []byte()
lowerASCIIBytes()
= string()
}
if , := hosts.byName[absDomainName()]; {
:= make([]string, len(.addrs))
copy(, .addrs)
return , .canonicalName
}
}
return nil, ""
}
func ( string) []string {
hosts.Lock()
defer hosts.Unlock()
readHosts()
= parseLiteralIP()
if == "" {
return nil
}
if len(hosts.byAddr) != 0 {
if , := hosts.byAddr[]; {
:= make([]string, len())
copy(, )
return
}
}
return nil
}