github.com/hbdrawn/golang@v0.0.0-20141214014649-6b835209aba2/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  }