OLD | NEW |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package net | 5 package net |
6 | 6 |
7 import ( | 7 import ( |
8 "os" | 8 "os" |
9 "runtime" | 9 "runtime" |
10 "syscall" | 10 "syscall" |
(...skipping 16 matching lines...) Expand all Loading... |
27 // lookupProtocol looks up IP protocol name and returns correspondent protocol n
umber. | 27 // lookupProtocol looks up IP protocol name and returns correspondent protocol n
umber. |
28 func lookupProtocol(name string) (proto int, err error) { | 28 func lookupProtocol(name string) (proto int, err error) { |
29 // GetProtoByName return value is stored in thread local storage. | 29 // GetProtoByName return value is stored in thread local storage. |
30 // Start new os thread before the call to prevent races. | 30 // Start new os thread before the call to prevent races. |
31 type result struct { | 31 type result struct { |
32 proto int | 32 proto int |
33 err error | 33 err error |
34 } | 34 } |
35 ch := make(chan result) | 35 ch := make(chan result) |
36 go func() { | 36 go func() { |
| 37 acquireThread() |
| 38 defer releaseThread() |
37 runtime.LockOSThread() | 39 runtime.LockOSThread() |
38 defer runtime.UnlockOSThread() | 40 defer runtime.UnlockOSThread() |
39 proto, err := getprotobyname(name) | 41 proto, err := getprotobyname(name) |
40 ch <- result{proto: proto, err: err} | 42 ch <- result{proto: proto, err: err} |
41 }() | 43 }() |
42 r := <-ch | 44 r := <-ch |
43 return r.proto, r.err | 45 return r.proto, r.err |
44 } | 46 } |
45 | 47 |
46 func lookupHost(name string) (addrs []string, err error) { | 48 func lookupHost(name string) (addrs []string, err error) { |
47 ips, err := LookupIP(name) | 49 ips, err := LookupIP(name) |
48 if err != nil { | 50 if err != nil { |
49 return | 51 return |
50 } | 52 } |
51 addrs = make([]string, 0, len(ips)) | 53 addrs = make([]string, 0, len(ips)) |
52 for _, ip := range ips { | 54 for _, ip := range ips { |
53 addrs = append(addrs, ip.String()) | 55 addrs = append(addrs, ip.String()) |
54 } | 56 } |
55 return | 57 return |
56 } | 58 } |
57 | 59 |
58 func gethostbyname(name string) (addrs []IP, err error) { | 60 func gethostbyname(name string) (addrs []IP, err error) { |
| 61 // caller already acquired thread |
59 h, err := syscall.GetHostByName(name) | 62 h, err := syscall.GetHostByName(name) |
60 if err != nil { | 63 if err != nil { |
61 return nil, os.NewSyscallError("GetHostByName", err) | 64 return nil, os.NewSyscallError("GetHostByName", err) |
62 } | 65 } |
63 switch h.AddrType { | 66 switch h.AddrType { |
64 case syscall.AF_INET: | 67 case syscall.AF_INET: |
65 i := 0 | 68 i := 0 |
66 addrs = make([]IP, 100) // plenty of room to grow | 69 addrs = make([]IP, 100) // plenty of room to grow |
67 for p := (*[100](*[4]byte))(unsafe.Pointer(h.AddrList)); i < cap
(addrs) && p[i] != nil; i++ { | 70 for p := (*[100](*[4]byte))(unsafe.Pointer(h.AddrList)); i < cap
(addrs) && p[i] != nil; i++ { |
68 addrs[i] = IPv4(p[i][0], p[i][1], p[i][2], p[i][3]) | 71 addrs[i] = IPv4(p[i][0], p[i][1], p[i][2], p[i][3]) |
69 } | 72 } |
70 addrs = addrs[0:i] | 73 addrs = addrs[0:i] |
71 default: // TODO(vcc): Implement non IPv4 address lookups. | 74 default: // TODO(vcc): Implement non IPv4 address lookups. |
72 return nil, os.NewSyscallError("LookupIP", syscall.EWINDOWS) | 75 return nil, os.NewSyscallError("LookupIP", syscall.EWINDOWS) |
73 } | 76 } |
74 return addrs, nil | 77 return addrs, nil |
75 } | 78 } |
76 | 79 |
77 func oldLookupIP(name string) (addrs []IP, err error) { | 80 func oldLookupIP(name string) (addrs []IP, err error) { |
78 // GetHostByName return value is stored in thread local storage. | 81 // GetHostByName return value is stored in thread local storage. |
79 // Start new os thread before the call to prevent races. | 82 // Start new os thread before the call to prevent races. |
80 type result struct { | 83 type result struct { |
81 addrs []IP | 84 addrs []IP |
82 err error | 85 err error |
83 } | 86 } |
84 ch := make(chan result) | 87 ch := make(chan result) |
85 go func() { | 88 go func() { |
| 89 acquireThread() |
| 90 defer releaseThread() |
86 runtime.LockOSThread() | 91 runtime.LockOSThread() |
87 defer runtime.UnlockOSThread() | 92 defer runtime.UnlockOSThread() |
88 addrs, err := gethostbyname(name) | 93 addrs, err := gethostbyname(name) |
89 ch <- result{addrs: addrs, err: err} | 94 ch <- result{addrs: addrs, err: err} |
90 }() | 95 }() |
91 r := <-ch | 96 r := <-ch |
92 return r.addrs, r.err | 97 return r.addrs, r.err |
93 } | 98 } |
94 | 99 |
95 func newLookupIP(name string) (addrs []IP, err error) { | 100 func newLookupIP(name string) (addrs []IP, err error) { |
| 101 acquireThread() |
| 102 defer releaseThread() |
96 hints := syscall.AddrinfoW{ | 103 hints := syscall.AddrinfoW{ |
97 Family: syscall.AF_UNSPEC, | 104 Family: syscall.AF_UNSPEC, |
98 Socktype: syscall.SOCK_STREAM, | 105 Socktype: syscall.SOCK_STREAM, |
99 Protocol: syscall.IPPROTO_IP, | 106 Protocol: syscall.IPPROTO_IP, |
100 } | 107 } |
101 var result *syscall.AddrinfoW | 108 var result *syscall.AddrinfoW |
102 e := syscall.GetAddrInfoW(syscall.StringToUTF16Ptr(name), nil, &hints, &
result) | 109 e := syscall.GetAddrInfoW(syscall.StringToUTF16Ptr(name), nil, &hints, &
result) |
103 if e != nil { | 110 if e != nil { |
104 return nil, os.NewSyscallError("GetAddrInfoW", e) | 111 return nil, os.NewSyscallError("GetAddrInfoW", e) |
105 } | 112 } |
106 defer syscall.FreeAddrInfoW(result) | 113 defer syscall.FreeAddrInfoW(result) |
107 addrs = make([]IP, 0, 5) | 114 addrs = make([]IP, 0, 5) |
108 for ; result != nil; result = result.Next { | 115 for ; result != nil; result = result.Next { |
109 addr := unsafe.Pointer(result.Addr) | 116 addr := unsafe.Pointer(result.Addr) |
110 switch result.Family { | 117 switch result.Family { |
111 case syscall.AF_INET: | 118 case syscall.AF_INET: |
112 a := (*syscall.RawSockaddrInet4)(addr).Addr | 119 a := (*syscall.RawSockaddrInet4)(addr).Addr |
113 addrs = append(addrs, IPv4(a[0], a[1], a[2], a[3])) | 120 addrs = append(addrs, IPv4(a[0], a[1], a[2], a[3])) |
114 case syscall.AF_INET6: | 121 case syscall.AF_INET6: |
115 a := (*syscall.RawSockaddrInet6)(addr).Addr | 122 a := (*syscall.RawSockaddrInet6)(addr).Addr |
116 addrs = append(addrs, IP{a[0], a[1], a[2], a[3], a[4], a
[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]}) | 123 addrs = append(addrs, IP{a[0], a[1], a[2], a[3], a[4], a
[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]}) |
117 default: | 124 default: |
118 return nil, os.NewSyscallError("LookupIP", syscall.EWIND
OWS) | 125 return nil, os.NewSyscallError("LookupIP", syscall.EWIND
OWS) |
119 } | 126 } |
120 } | 127 } |
121 return addrs, nil | 128 return addrs, nil |
122 } | 129 } |
123 | 130 |
124 func getservbyname(network, service string) (port int, err error) { | 131 func getservbyname(network, service string) (port int, err error) { |
| 132 acquireThread() |
| 133 defer releaseThread() |
125 switch network { | 134 switch network { |
126 case "tcp4", "tcp6": | 135 case "tcp4", "tcp6": |
127 network = "tcp" | 136 network = "tcp" |
128 case "udp4", "udp6": | 137 case "udp4", "udp6": |
129 network = "udp" | 138 network = "udp" |
130 } | 139 } |
131 s, err := syscall.GetServByName(service, network) | 140 s, err := syscall.GetServByName(service, network) |
132 if err != nil { | 141 if err != nil { |
133 return 0, os.NewSyscallError("GetServByName", err) | 142 return 0, os.NewSyscallError("GetServByName", err) |
134 } | 143 } |
135 return int(syscall.Ntohs(s.Port)), nil | 144 return int(syscall.Ntohs(s.Port)), nil |
136 } | 145 } |
137 | 146 |
138 func oldLookupPort(network, service string) (port int, err error) { | 147 func oldLookupPort(network, service string) (port int, err error) { |
139 // GetServByName return value is stored in thread local storage. | 148 // GetServByName return value is stored in thread local storage. |
140 // Start new os thread before the call to prevent races. | 149 // Start new os thread before the call to prevent races. |
141 type result struct { | 150 type result struct { |
142 port int | 151 port int |
143 err error | 152 err error |
144 } | 153 } |
145 ch := make(chan result) | 154 ch := make(chan result) |
146 go func() { | 155 go func() { |
| 156 acquireThread() |
| 157 defer releaseThread() |
147 runtime.LockOSThread() | 158 runtime.LockOSThread() |
148 defer runtime.UnlockOSThread() | 159 defer runtime.UnlockOSThread() |
149 port, err := getservbyname(network, service) | 160 port, err := getservbyname(network, service) |
150 ch <- result{port: port, err: err} | 161 ch <- result{port: port, err: err} |
151 }() | 162 }() |
152 r := <-ch | 163 r := <-ch |
153 return r.port, r.err | 164 return r.port, r.err |
154 } | 165 } |
155 | 166 |
156 func newLookupPort(network, service string) (port int, err error) { | 167 func newLookupPort(network, service string) (port int, err error) { |
| 168 acquireThread() |
| 169 defer releaseThread() |
157 var stype int32 | 170 var stype int32 |
158 switch network { | 171 switch network { |
159 case "tcp4", "tcp6": | 172 case "tcp4", "tcp6": |
160 stype = syscall.SOCK_STREAM | 173 stype = syscall.SOCK_STREAM |
161 case "udp4", "udp6": | 174 case "udp4", "udp6": |
162 stype = syscall.SOCK_DGRAM | 175 stype = syscall.SOCK_DGRAM |
163 } | 176 } |
164 hints := syscall.AddrinfoW{ | 177 hints := syscall.AddrinfoW{ |
165 Family: syscall.AF_UNSPEC, | 178 Family: syscall.AF_UNSPEC, |
166 Socktype: stype, | 179 Socktype: stype, |
(...skipping 14 matching lines...) Expand all Loading... |
181 a := (*syscall.RawSockaddrInet4)(addr) | 194 a := (*syscall.RawSockaddrInet4)(addr) |
182 return int(syscall.Ntohs(a.Port)), nil | 195 return int(syscall.Ntohs(a.Port)), nil |
183 case syscall.AF_INET6: | 196 case syscall.AF_INET6: |
184 a := (*syscall.RawSockaddrInet6)(addr) | 197 a := (*syscall.RawSockaddrInet6)(addr) |
185 return int(syscall.Ntohs(a.Port)), nil | 198 return int(syscall.Ntohs(a.Port)), nil |
186 } | 199 } |
187 return 0, os.NewSyscallError("LookupPort", syscall.EINVAL) | 200 return 0, os.NewSyscallError("LookupPort", syscall.EINVAL) |
188 } | 201 } |
189 | 202 |
190 func lookupCNAME(name string) (cname string, err error) { | 203 func lookupCNAME(name string) (cname string, err error) { |
| 204 acquireThread() |
| 205 defer releaseThread() |
191 var r *syscall.DNSRecord | 206 var r *syscall.DNSRecord |
192 e := syscall.DnsQuery(name, syscall.DNS_TYPE_CNAME, 0, nil, &r, nil) | 207 e := syscall.DnsQuery(name, syscall.DNS_TYPE_CNAME, 0, nil, &r, nil) |
193 if e != nil { | 208 if e != nil { |
194 return "", os.NewSyscallError("LookupCNAME", e) | 209 return "", os.NewSyscallError("LookupCNAME", e) |
195 } | 210 } |
196 defer syscall.DnsRecordListFree(r, 1) | 211 defer syscall.DnsRecordListFree(r, 1) |
197 if r != nil && r.Type == syscall.DNS_TYPE_CNAME { | 212 if r != nil && r.Type == syscall.DNS_TYPE_CNAME { |
198 v := (*syscall.DNSPTRData)(unsafe.Pointer(&r.Data[0])) | 213 v := (*syscall.DNSPTRData)(unsafe.Pointer(&r.Data[0])) |
199 cname = syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Ho
st))[:]) + "." | 214 cname = syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Ho
st))[:]) + "." |
200 } | 215 } |
201 return | 216 return |
202 } | 217 } |
203 | 218 |
204 func lookupSRV(service, proto, name string) (cname string, addrs []*SRV, err err
or) { | 219 func lookupSRV(service, proto, name string) (cname string, addrs []*SRV, err err
or) { |
| 220 acquireThread() |
| 221 defer releaseThread() |
205 var target string | 222 var target string |
206 if service == "" && proto == "" { | 223 if service == "" && proto == "" { |
207 target = name | 224 target = name |
208 } else { | 225 } else { |
209 target = "_" + service + "._" + proto + "." + name | 226 target = "_" + service + "._" + proto + "." + name |
210 } | 227 } |
211 var r *syscall.DNSRecord | 228 var r *syscall.DNSRecord |
212 e := syscall.DnsQuery(target, syscall.DNS_TYPE_SRV, 0, nil, &r, nil) | 229 e := syscall.DnsQuery(target, syscall.DNS_TYPE_SRV, 0, nil, &r, nil) |
213 if e != nil { | 230 if e != nil { |
214 return "", nil, os.NewSyscallError("LookupSRV", e) | 231 return "", nil, os.NewSyscallError("LookupSRV", e) |
215 } | 232 } |
216 defer syscall.DnsRecordListFree(r, 1) | 233 defer syscall.DnsRecordListFree(r, 1) |
217 addrs = make([]*SRV, 0, 10) | 234 addrs = make([]*SRV, 0, 10) |
218 for p := r; p != nil && p.Type == syscall.DNS_TYPE_SRV; p = p.Next { | 235 for p := r; p != nil && p.Type == syscall.DNS_TYPE_SRV; p = p.Next { |
219 v := (*syscall.DNSSRVData)(unsafe.Pointer(&p.Data[0])) | 236 v := (*syscall.DNSSRVData)(unsafe.Pointer(&p.Data[0])) |
220 addrs = append(addrs, &SRV{syscall.UTF16ToString((*[256]uint16)(
unsafe.Pointer(v.Target))[:]), v.Port, v.Priority, v.Weight}) | 237 addrs = append(addrs, &SRV{syscall.UTF16ToString((*[256]uint16)(
unsafe.Pointer(v.Target))[:]), v.Port, v.Priority, v.Weight}) |
221 } | 238 } |
222 byPriorityWeight(addrs).sort() | 239 byPriorityWeight(addrs).sort() |
223 return name, addrs, nil | 240 return name, addrs, nil |
224 } | 241 } |
225 | 242 |
226 func lookupMX(name string) (mx []*MX, err error) { | 243 func lookupMX(name string) (mx []*MX, err error) { |
| 244 acquireThread() |
| 245 defer releaseThread() |
227 var r *syscall.DNSRecord | 246 var r *syscall.DNSRecord |
228 e := syscall.DnsQuery(name, syscall.DNS_TYPE_MX, 0, nil, &r, nil) | 247 e := syscall.DnsQuery(name, syscall.DNS_TYPE_MX, 0, nil, &r, nil) |
229 if e != nil { | 248 if e != nil { |
230 return nil, os.NewSyscallError("LookupMX", e) | 249 return nil, os.NewSyscallError("LookupMX", e) |
231 } | 250 } |
232 defer syscall.DnsRecordListFree(r, 1) | 251 defer syscall.DnsRecordListFree(r, 1) |
233 mx = make([]*MX, 0, 10) | 252 mx = make([]*MX, 0, 10) |
234 for p := r; p != nil && p.Type == syscall.DNS_TYPE_MX; p = p.Next { | 253 for p := r; p != nil && p.Type == syscall.DNS_TYPE_MX; p = p.Next { |
235 v := (*syscall.DNSMXData)(unsafe.Pointer(&p.Data[0])) | 254 v := (*syscall.DNSMXData)(unsafe.Pointer(&p.Data[0])) |
236 mx = append(mx, &MX{syscall.UTF16ToString((*[256]uint16)(unsafe.
Pointer(v.NameExchange))[:]) + ".", v.Preference}) | 255 mx = append(mx, &MX{syscall.UTF16ToString((*[256]uint16)(unsafe.
Pointer(v.NameExchange))[:]) + ".", v.Preference}) |
237 } | 256 } |
238 byPref(mx).sort() | 257 byPref(mx).sort() |
239 return mx, nil | 258 return mx, nil |
240 } | 259 } |
241 | 260 |
242 func lookupNS(name string) (ns []*NS, err error) { | 261 func lookupNS(name string) (ns []*NS, err error) { |
| 262 acquireThread() |
| 263 defer releaseThread() |
243 var r *syscall.DNSRecord | 264 var r *syscall.DNSRecord |
244 e := syscall.DnsQuery(name, syscall.DNS_TYPE_NS, 0, nil, &r, nil) | 265 e := syscall.DnsQuery(name, syscall.DNS_TYPE_NS, 0, nil, &r, nil) |
245 if e != nil { | 266 if e != nil { |
246 return nil, os.NewSyscallError("LookupNS", e) | 267 return nil, os.NewSyscallError("LookupNS", e) |
247 } | 268 } |
248 defer syscall.DnsRecordListFree(r, 1) | 269 defer syscall.DnsRecordListFree(r, 1) |
249 ns = make([]*NS, 0, 10) | 270 ns = make([]*NS, 0, 10) |
250 for p := r; p != nil && p.Type == syscall.DNS_TYPE_NS; p = p.Next { | 271 for p := r; p != nil && p.Type == syscall.DNS_TYPE_NS; p = p.Next { |
251 v := (*syscall.DNSPTRData)(unsafe.Pointer(&p.Data[0])) | 272 v := (*syscall.DNSPTRData)(unsafe.Pointer(&p.Data[0])) |
252 ns = append(ns, &NS{syscall.UTF16ToString((*[256]uint16)(unsafe.
Pointer(v.Host))[:]) + "."}) | 273 ns = append(ns, &NS{syscall.UTF16ToString((*[256]uint16)(unsafe.
Pointer(v.Host))[:]) + "."}) |
253 } | 274 } |
254 return ns, nil | 275 return ns, nil |
255 } | 276 } |
256 | 277 |
257 func lookupTXT(name string) (txt []string, err error) { | 278 func lookupTXT(name string) (txt []string, err error) { |
| 279 acquireThread() |
| 280 defer releaseThread() |
258 var r *syscall.DNSRecord | 281 var r *syscall.DNSRecord |
259 e := syscall.DnsQuery(name, syscall.DNS_TYPE_TEXT, 0, nil, &r, nil) | 282 e := syscall.DnsQuery(name, syscall.DNS_TYPE_TEXT, 0, nil, &r, nil) |
260 if e != nil { | 283 if e != nil { |
261 return nil, os.NewSyscallError("LookupTXT", e) | 284 return nil, os.NewSyscallError("LookupTXT", e) |
262 } | 285 } |
263 defer syscall.DnsRecordListFree(r, 1) | 286 defer syscall.DnsRecordListFree(r, 1) |
264 txt = make([]string, 0, 10) | 287 txt = make([]string, 0, 10) |
265 if r != nil && r.Type == syscall.DNS_TYPE_TEXT { | 288 if r != nil && r.Type == syscall.DNS_TYPE_TEXT { |
266 d := (*syscall.DNSTXTData)(unsafe.Pointer(&r.Data[0])) | 289 d := (*syscall.DNSTXTData)(unsafe.Pointer(&r.Data[0])) |
267 for _, v := range (*[1 << 10]*uint16)(unsafe.Pointer(&(d.StringA
rray[0])))[:d.StringCount] { | 290 for _, v := range (*[1 << 10]*uint16)(unsafe.Pointer(&(d.StringA
rray[0])))[:d.StringCount] { |
268 s := syscall.UTF16ToString((*[1 << 20]uint16)(unsafe.Poi
nter(v))[:]) | 291 s := syscall.UTF16ToString((*[1 << 20]uint16)(unsafe.Poi
nter(v))[:]) |
269 txt = append(txt, s) | 292 txt = append(txt, s) |
270 } | 293 } |
271 } | 294 } |
272 return | 295 return |
273 } | 296 } |
274 | 297 |
275 func lookupAddr(addr string) (name []string, err error) { | 298 func lookupAddr(addr string) (name []string, err error) { |
| 299 acquireThread() |
| 300 defer releaseThread() |
276 arpa, err := reverseaddr(addr) | 301 arpa, err := reverseaddr(addr) |
277 if err != nil { | 302 if err != nil { |
278 return nil, err | 303 return nil, err |
279 } | 304 } |
280 var r *syscall.DNSRecord | 305 var r *syscall.DNSRecord |
281 e := syscall.DnsQuery(arpa, syscall.DNS_TYPE_PTR, 0, nil, &r, nil) | 306 e := syscall.DnsQuery(arpa, syscall.DNS_TYPE_PTR, 0, nil, &r, nil) |
282 if e != nil { | 307 if e != nil { |
283 return nil, os.NewSyscallError("LookupAddr", e) | 308 return nil, os.NewSyscallError("LookupAddr", e) |
284 } | 309 } |
285 defer syscall.DnsRecordListFree(r, 1) | 310 defer syscall.DnsRecordListFree(r, 1) |
286 name = make([]string, 0, 10) | 311 name = make([]string, 0, 10) |
287 for p := r; p != nil && p.Type == syscall.DNS_TYPE_PTR; p = p.Next { | 312 for p := r; p != nil && p.Type == syscall.DNS_TYPE_PTR; p = p.Next { |
288 v := (*syscall.DNSPTRData)(unsafe.Pointer(&p.Data[0])) | 313 v := (*syscall.DNSPTRData)(unsafe.Pointer(&p.Data[0])) |
289 name = append(name, syscall.UTF16ToString((*[256]uint16)(unsafe.
Pointer(v.Host))[:])) | 314 name = append(name, syscall.UTF16ToString((*[256]uint16)(unsafe.
Pointer(v.Host))[:])) |
290 } | 315 } |
291 return name, nil | 316 return name, nil |
292 } | 317 } |
OLD | NEW |