github.com/roboticscm/goman@v0.0.0-20210203095141-87c07b4a0a55/src/net/lookup.go (about) 1 // Copyright 2012 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package net 6 7 import "time" 8 9 // protocols contains minimal mappings between internet protocol 10 // names and numbers for platforms that don't have a complete list of 11 // protocol numbers. 12 // 13 // See http://www.iana.org/assignments/protocol-numbers 14 var protocols = map[string]int{ 15 "icmp": 1, "ICMP": 1, 16 "igmp": 2, "IGMP": 2, 17 "tcp": 6, "TCP": 6, 18 "udp": 17, "UDP": 17, 19 "ipv6-icmp": 58, "IPV6-ICMP": 58, "IPv6-ICMP": 58, 20 } 21 22 // LookupHost looks up the given host using the local resolver. 23 // It returns an array of that host's addresses. 24 func LookupHost(host string) (addrs []string, err error) { 25 return lookupHost(host) 26 } 27 28 // LookupIP looks up host using the local resolver. 29 // It returns an array of that host's IPv4 and IPv6 addresses. 30 func LookupIP(host string) (addrs []IP, err error) { 31 return lookupIPMerge(host) 32 } 33 34 var lookupGroup singleflight 35 36 // lookupIPMerge wraps lookupIP, but makes sure that for any given 37 // host, only one lookup is in-flight at a time. The returned memory 38 // is always owned by the caller. 39 func lookupIPMerge(host string) (addrs []IP, err error) { 40 addrsi, err, shared := lookupGroup.Do(host, func() (interface{}, error) { 41 return lookupIP(host) 42 }) 43 return lookupIPReturn(addrsi, err, shared) 44 } 45 46 // lookupIPReturn turns the return values from singleflight.Do into 47 // the return values from LookupIP. 48 func lookupIPReturn(addrsi interface{}, err error, shared bool) ([]IP, error) { 49 if err != nil { 50 return nil, err 51 } 52 addrs := addrsi.([]IP) 53 if shared { 54 clone := make([]IP, len(addrs)) 55 copy(clone, addrs) 56 addrs = clone 57 } 58 return addrs, nil 59 } 60 61 // lookupIPDeadline looks up a hostname with a deadline. 62 func lookupIPDeadline(host string, deadline time.Time) (addrs []IP, err error) { 63 if deadline.IsZero() { 64 return lookupIPMerge(host) 65 } 66 67 // We could push the deadline down into the name resolution 68 // functions. However, the most commonly used implementation 69 // calls getaddrinfo, which has no timeout. 70 71 timeout := deadline.Sub(time.Now()) 72 if timeout <= 0 { 73 return nil, errTimeout 74 } 75 t := time.NewTimer(timeout) 76 defer t.Stop() 77 78 ch := lookupGroup.DoChan(host, func() (interface{}, error) { 79 return lookupIP(host) 80 }) 81 82 select { 83 case <-t.C: 84 // The DNS lookup timed out for some reason. Force 85 // future requests to start the DNS lookup again 86 // rather than waiting for the current lookup to 87 // complete. See issue 8602. 88 lookupGroup.Forget(host) 89 90 return nil, errTimeout 91 92 case r := <-ch: 93 return lookupIPReturn(r.v, r.err, r.shared) 94 } 95 } 96 97 // LookupPort looks up the port for the given network and service. 98 func LookupPort(network, service string) (port int, err error) { 99 return lookupPort(network, service) 100 } 101 102 // LookupCNAME returns the canonical DNS host for the given name. 103 // Callers that do not care about the canonical name can call 104 // LookupHost or LookupIP directly; both take care of resolving 105 // the canonical name as part of the lookup. 106 func LookupCNAME(name string) (cname string, err error) { 107 return lookupCNAME(name) 108 } 109 110 // LookupSRV tries to resolve an SRV query of the given service, 111 // protocol, and domain name. The proto is "tcp" or "udp". 112 // The returned records are sorted by priority and randomized 113 // by weight within a priority. 114 // 115 // LookupSRV constructs the DNS name to look up following RFC 2782. 116 // That is, it looks up _service._proto.name. To accommodate services 117 // publishing SRV records under non-standard names, if both service 118 // and proto are empty strings, LookupSRV looks up name directly. 119 func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) { 120 return lookupSRV(service, proto, name) 121 } 122 123 // LookupMX returns the DNS MX records for the given domain name sorted by preference. 124 func LookupMX(name string) (mx []*MX, err error) { 125 return lookupMX(name) 126 } 127 128 // LookupNS returns the DNS NS records for the given domain name. 129 func LookupNS(name string) (ns []*NS, err error) { 130 return lookupNS(name) 131 } 132 133 // LookupTXT returns the DNS TXT records for the given domain name. 134 func LookupTXT(name string) (txt []string, err error) { 135 return lookupTXT(name) 136 } 137 138 // LookupAddr performs a reverse lookup for the given address, returning a list 139 // of names mapping to that address. 140 func LookupAddr(addr string) (name []string, err error) { 141 return lookupAddr(addr) 142 }