github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/pkg/util/unresolved_addr.go (about)

     1  // Copyright 2015 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package util
    12  
    13  import (
    14  	"fmt"
    15  	"net"
    16  	"os"
    17  
    18  	addrutil "github.com/cockroachdb/cockroachdb-parser/pkg/util/netutil/addr"
    19  )
    20  
    21  // TestAddr is an address to use for test servers. Listening on port 0
    22  // causes the kernel to allocate an unused port.
    23  var TestAddr = NewUnresolvedAddr("tcp", "127.0.0.1:0")
    24  
    25  // IsolatedTestAddr is initialized in testaddr_*.go
    26  
    27  // IsolatedTestAddr is an address to use for tests that need extra
    28  // isolation by using more addresses than 127.0.0.1 (support for this
    29  // is platform-specific and only enabled on Linux). Both TestAddr and
    30  // IsolatedTestAddr guarantee that the chosen port is not in use when
    31  // allocated, but IsolatedTestAddr draws from a larger pool of
    32  // addresses so that when tests are run in a tight loop the system is
    33  // less likely to run out of available ports or give a port to one
    34  // test immediately after it was closed by another.
    35  //
    36  // IsolatedTestAddr should be used for tests that open and close a
    37  // large number of sockets, or tests which stop a server and rely on
    38  // seeing a "connection refused" error afterwards. It cannot be used
    39  // with tests that operate in secure mode since our test certificates
    40  // are only valid for 127.0.0.1.
    41  var IsolatedTestAddr *UnresolvedAddr
    42  
    43  // MakeUnresolvedAddr populates an UnresolvedAddr from a network and raw
    44  // address string.
    45  func MakeUnresolvedAddr(network, addr string) UnresolvedAddr {
    46  	return UnresolvedAddr{
    47  		NetworkField: network,
    48  		AddressField: addr,
    49  	}
    50  }
    51  
    52  // NewUnresolvedAddr creates a new UnresolvedAddr from a network and raw
    53  // address string.
    54  func NewUnresolvedAddr(network, addr string) *UnresolvedAddr {
    55  	return &UnresolvedAddr{
    56  		NetworkField: network,
    57  		AddressField: addr,
    58  	}
    59  }
    60  
    61  // MakeUnresolvedAddrWithDefaults creates a new UnresolvedAddr from a network and
    62  // raw address string, using the following defaults if not given:
    63  //
    64  // - Network: tcp
    65  // - Host: local hostname or 127.0.0.1
    66  // - Port: given default port
    67  func MakeUnresolvedAddrWithDefaults(network, addr, defaultPort string) UnresolvedAddr {
    68  	if network == "" {
    69  		network = "tcp"
    70  	}
    71  	if host, port, err := addrutil.SplitHostPort(addr, defaultPort); err != nil {
    72  		addr = net.JoinHostPort(addr, defaultPort)
    73  	} else {
    74  		if host == "" {
    75  			host, err = os.Hostname()
    76  			if err != nil {
    77  				host = "127.0.0.1"
    78  			}
    79  		}
    80  		addr = net.JoinHostPort(host, port)
    81  	}
    82  	return UnresolvedAddr{
    83  		NetworkField: network,
    84  		AddressField: addr,
    85  	}
    86  }
    87  
    88  // Note that we make *UnresolvedAddr implement the net.Addr interface, not
    89  // UnresolvedAddr. This is done because assigning a non-empty struct to an
    90  // interface requires an allocation, while assigning a pointer to an interface
    91  // is allocation free. Using an *UnresolvedAddr makes it both clear that an
    92  // allocation is occurring and allows us to avoid an allocation when an
    93  // UnresolvedAddr is a field of a struct (e.g. NodeDescriptor.Address).
    94  var _ net.Addr = &UnresolvedAddr{}
    95  
    96  // Network returns the address's network name.
    97  func (a *UnresolvedAddr) Network() string {
    98  	return a.NetworkField
    99  }
   100  
   101  // IsEmpty returns true if the address has no network or address specified.
   102  func (a UnresolvedAddr) IsEmpty() bool {
   103  	return a == (UnresolvedAddr{})
   104  }
   105  
   106  // String returns the address's string form.
   107  func (a UnresolvedAddr) String() string {
   108  	return a.AddressField
   109  }
   110  
   111  // Resolve attempts to resolve a into a net.Addr.
   112  func (a UnresolvedAddr) Resolve() (net.Addr, error) {
   113  	switch a.NetworkField {
   114  	case "tcp", "tcp4", "tcp6":
   115  		return net.ResolveTCPAddr(a.NetworkField, a.AddressField)
   116  	case "udp", "udp4", "udp6":
   117  		return net.ResolveUDPAddr(a.NetworkField, a.AddressField)
   118  	case "unix", "unixgram", "unixpacket":
   119  		return net.ResolveUnixAddr(a.NetworkField, a.AddressField)
   120  	}
   121  	return nil, fmt.Errorf("network %s not supported", a.NetworkField)
   122  }