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 }