Source file
src/net/hosts.go
1
2
3
4
5 package net
6
7 import (
8 "internal/bytealg"
9 "sync"
10 "time"
11 )
12
13 const cacheMaxAge = 5 * time.Second
14
15 func parseLiteralIP(addr string) string {
16 var ip IP
17 var zone string
18 ip = parseIPv4(addr)
19 if ip == nil {
20 ip, zone = parseIPv6Zone(addr)
21 }
22 if ip == nil {
23 return ""
24 }
25 if zone == "" {
26 return ip.String()
27 }
28 return ip.String() + "%" + zone
29 }
30
31 type byName struct {
32 addrs []string
33 canonicalName string
34 }
35
36
37 var hosts struct {
38 sync.Mutex
39
40
41
42
43
44 byName map[string]byName
45
46
47
48
49 byAddr map[string][]string
50
51 expire time.Time
52 path string
53 mtime time.Time
54 size int64
55 }
56
57 func readHosts() {
58 now := time.Now()
59 hp := testHookHostsPath
60
61 if now.Before(hosts.expire) && hosts.path == hp && len(hosts.byName) > 0 {
62 return
63 }
64 mtime, size, err := stat(hp)
65 if err == nil && hosts.path == hp && hosts.mtime.Equal(mtime) && hosts.size == size {
66 hosts.expire = now.Add(cacheMaxAge)
67 return
68 }
69
70 hs := make(map[string]byName)
71 is := make(map[string][]string)
72
73 var file *file
74 if file, _ = open(hp); file == nil {
75 return
76 }
77 for line, ok := file.readLine(); ok; line, ok = file.readLine() {
78 if i := bytealg.IndexByteString(line, '#'); i >= 0 {
79
80 line = line[0:i]
81 }
82 f := getFields(line)
83 if len(f) < 2 {
84 continue
85 }
86 addr := parseLiteralIP(f[0])
87 if addr == "" {
88 continue
89 }
90
91 var canonical string
92 for i := 1; i < len(f); i++ {
93 name := absDomainName(f[i])
94 h := []byte(f[i])
95 lowerASCIIBytes(h)
96 key := absDomainName(string(h))
97
98 if i == 1 {
99 canonical = key
100 }
101
102 is[addr] = append(is[addr], name)
103
104 if v, ok := hs[key]; ok {
105 hs[key] = byName{
106 addrs: append(v.addrs, addr),
107 canonicalName: v.canonicalName,
108 }
109 continue
110 }
111
112 hs[key] = byName{
113 addrs: []string{addr},
114 canonicalName: canonical,
115 }
116 }
117 }
118
119 hosts.expire = now.Add(cacheMaxAge)
120 hosts.path = hp
121 hosts.byName = hs
122 hosts.byAddr = is
123 hosts.mtime = mtime
124 hosts.size = size
125 file.close()
126 }
127
128
129 func lookupStaticHost(host string) ([]string, string) {
130 hosts.Lock()
131 defer hosts.Unlock()
132 readHosts()
133 if len(hosts.byName) != 0 {
134 if hasUpperCase(host) {
135 lowerHost := []byte(host)
136 lowerASCIIBytes(lowerHost)
137 host = string(lowerHost)
138 }
139 if byName, ok := hosts.byName[absDomainName(host)]; ok {
140 ipsCp := make([]string, len(byName.addrs))
141 copy(ipsCp, byName.addrs)
142 return ipsCp, byName.canonicalName
143 }
144 }
145 return nil, ""
146 }
147
148
149 func lookupStaticAddr(addr string) []string {
150 hosts.Lock()
151 defer hosts.Unlock()
152 readHosts()
153 addr = parseLiteralIP(addr)
154 if addr == "" {
155 return nil
156 }
157 if len(hosts.byAddr) != 0 {
158 if hosts, ok := hosts.byAddr[addr]; ok {
159 hostsCp := make([]string, len(hosts))
160 copy(hostsCp, hosts)
161 return hostsCp
162 }
163 }
164 return nil
165 }
166
View as plain text