summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/pkg/net/dial.go6
-rw-r--r--src/pkg/net/dial_gen.go6
-rw-r--r--src/pkg/net/fd_unix.go2
-rw-r--r--src/pkg/net/fd_windows.go2
-rw-r--r--src/pkg/net/iprawsock.go9
-rw-r--r--src/pkg/net/iprawsock_posix.go7
-rw-r--r--src/pkg/net/ipsock.go73
-rw-r--r--src/pkg/net/sock_posix.go7
-rw-r--r--src/pkg/net/tcpsock.go9
-rw-r--r--src/pkg/net/tcpsock_posix.go7
-rw-r--r--src/pkg/net/udpsock.go9
-rw-r--r--src/pkg/net/udpsock_posix.go7
-rw-r--r--src/pkg/net/unixsock.go7
-rw-r--r--src/pkg/net/unixsock_posix.go7
14 files changed, 85 insertions, 73 deletions
diff --git a/src/pkg/net/dial.go b/src/pkg/net/dial.go
index 8df4f7784..f0f47b215 100644
--- a/src/pkg/net/dial.go
+++ b/src/pkg/net/dial.go
@@ -82,7 +82,7 @@ func parseNetwork(net string) (afnet string, proto int, err error) {
return "", 0, UnknownNetworkError(net)
}
-func resolveAddr(op, net, addr string, deadline time.Time) (Addr, error) {
+func resolveAddr(op, net, addr string, deadline time.Time) (netaddr, error) {
afnet, _, err := parseNetwork(net)
if err != nil {
return nil, err
@@ -184,7 +184,7 @@ func Listen(net, laddr string) (Listener, error) {
if err != nil {
return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: err}
}
- switch la := la.(type) {
+ switch la := la.toAddr().(type) {
case *TCPAddr:
return ListenTCP(net, la)
case *UnixAddr:
@@ -203,7 +203,7 @@ func ListenPacket(net, laddr string) (PacketConn, error) {
if err != nil {
return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: err}
}
- switch la := la.(type) {
+ switch la := la.toAddr().(type) {
case *UDPAddr:
return ListenUDP(net, la)
case *IPAddr:
diff --git a/src/pkg/net/dial_gen.go b/src/pkg/net/dial_gen.go
index 4fb1c7ad9..f051cdaa8 100644
--- a/src/pkg/net/dial_gen.go
+++ b/src/pkg/net/dial_gen.go
@@ -26,7 +26,7 @@ func resolveAndDialChannel(net, addr string, localAddr Addr, deadline time.Time)
if err != nil {
return nil, &OpError{Op: "dial", Net: net, Addr: nil, Err: err}
}
- return dial(net, addr, localAddr, ra, noDeadline)
+ return dial(net, addr, localAddr, ra.toAddr(), noDeadline)
}
t := time.NewTimer(timeout)
defer t.Stop()
@@ -45,8 +45,8 @@ func resolveAndDialChannel(net, addr string, localAddr Addr, deadline time.Time)
ch <- pair{nil, &OpError{Op: "dial", Net: net, Addr: nil, Err: err}}
return
}
- resolvedAddr <- ra // in case we need it for OpError
- c, err := dial(net, addr, localAddr, ra, noDeadline)
+ resolvedAddr <- ra.toAddr() // in case we need it for OpError
+ c, err := dial(net, addr, localAddr, ra.toAddr(), noDeadline)
ch <- pair{c, err}
}()
select {
diff --git a/src/pkg/net/fd_unix.go b/src/pkg/net/fd_unix.go
index bdc2861d5..457c1d18e 100644
--- a/src/pkg/net/fd_unix.go
+++ b/src/pkg/net/fd_unix.go
@@ -41,7 +41,7 @@ func resolveAndDial(net, addr string, localAddr Addr, deadline time.Time) (Conn,
if err != nil {
return nil, &OpError{Op: "dial", Net: net, Addr: nil, Err: err}
}
- return dial(net, addr, localAddr, ra, deadline)
+ return dial(net, addr, localAddr, ra.toAddr(), deadline)
}
func newFD(sysfd, family, sotype int, net string) (*netFD, error) {
diff --git a/src/pkg/net/fd_windows.go b/src/pkg/net/fd_windows.go
index 75f7a63ca..6f344057c 100644
--- a/src/pkg/net/fd_windows.go
+++ b/src/pkg/net/fd_windows.go
@@ -93,7 +93,7 @@ func resolveAndDial(net, addr string, localAddr Addr, deadline time.Time) (Conn,
if err != nil {
return nil, &OpError{Op: "dial", Net: net, Addr: nil, Err: err}
}
- return dial(net, addr, localAddr, ra, deadline)
+ return dial(net, addr, localAddr, ra.toAddr(), deadline)
}
// operation contains superset of data necessary to perform all async IO.
diff --git a/src/pkg/net/iprawsock.go b/src/pkg/net/iprawsock.go
index 0be94eb70..5cc361390 100644
--- a/src/pkg/net/iprawsock.go
+++ b/src/pkg/net/iprawsock.go
@@ -23,6 +23,13 @@ func (a *IPAddr) String() string {
return a.IP.String()
}
+func (a *IPAddr) toAddr() Addr {
+ if a == nil {
+ return nil
+ }
+ return a
+}
+
// ResolveIPAddr parses addr as an IP address of the form "host" or
// "ipv6-host%zone" and resolves the domain name on the network net,
// which must be "ip", "ip4" or "ip6".
@@ -43,5 +50,5 @@ func ResolveIPAddr(net, addr string) (*IPAddr, error) {
if err != nil {
return nil, err
}
- return a.(*IPAddr), nil
+ return a.toAddr().(*IPAddr), nil
}
diff --git a/src/pkg/net/iprawsock_posix.go b/src/pkg/net/iprawsock_posix.go
index d74068b39..722853257 100644
--- a/src/pkg/net/iprawsock_posix.go
+++ b/src/pkg/net/iprawsock_posix.go
@@ -57,13 +57,6 @@ func (a *IPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
return ipToSockaddr(family, a.IP, 0, a.Zone)
}
-func (a *IPAddr) toAddr() sockaddr {
- if a == nil {
- return nil
- }
- return a
-}
-
// IPConn is the implementation of the Conn and PacketConn interfaces
// for IP network connections.
type IPConn struct {
diff --git a/src/pkg/net/ipsock.go b/src/pkg/net/ipsock.go
index 33b584db5..10a51f490 100644
--- a/src/pkg/net/ipsock.go
+++ b/src/pkg/net/ipsock.go
@@ -6,7 +6,10 @@
package net
-import "time"
+import (
+ "errors"
+ "time"
+)
var (
// supportsIPv4 reports whether the platform supports IPv4
@@ -29,30 +32,42 @@ func init() {
supportsIPv6, supportsIPv4map = probeIPv6Stack()
}
-func firstFavoriteAddr(filter func(IP) IP, addrs []string) (addr IP) {
+// A netaddr represents a network endpoint address or a list of
+// network endpoint addresses.
+type netaddr interface {
+ // toAddr returns the address represented in Addr interface.
+ // It returns a nil interface when the address is nil.
+ toAddr() Addr
+}
+
+var errNoSuitableAddress = errors.New("no suitable address found")
+
+// firstFavoriteAddr returns an address that implemets netaddr
+// interface.
+func firstFavoriteAddr(filter func(IP) IP, addrs []string, inetaddr func(IP) netaddr) (netaddr, error) {
if filter == nil {
// We'll take any IP address, but since the dialing code
// does not yet try multiple addresses, prefer to use
// an IPv4 address if possible. This is especially relevant
// if localhost resolves to [ipv6-localhost, ipv4-localhost].
// Too much code assumes localhost == ipv4-localhost.
- addr = firstSupportedAddr(ipv4only, addrs)
- if addr == nil {
- addr = firstSupportedAddr(anyaddr, addrs)
+ addr, err := firstSupportedAddr(ipv4only, addrs, inetaddr)
+ if err != nil {
+ addr, err = firstSupportedAddr(anyaddr, addrs, inetaddr)
}
+ return addr, err
} else {
- addr = firstSupportedAddr(filter, addrs)
+ return firstSupportedAddr(filter, addrs, inetaddr)
}
- return
}
-func firstSupportedAddr(filter func(IP) IP, addrs []string) IP {
+func firstSupportedAddr(filter func(IP) IP, addrs []string, inetaddr func(IP) netaddr) (netaddr, error) {
for _, s := range addrs {
- if addr := filter(ParseIP(s)); addr != nil {
- return addr
+ if ip := filter(ParseIP(s)); ip != nil {
+ return inetaddr(ip), nil
}
}
- return nil
+ return nil, errNoSuitableAddress
}
// anyaddr returns IP addresses that we can use with the current
@@ -178,7 +193,10 @@ func JoinHostPort(host, port string) string {
return host + ":" + port
}
-func resolveInternetAddr(net, addr string, deadline time.Time) (Addr, error) {
+// resolveInternetAddr resolves addr that is either a literal IP
+// address or a DNS registered name and returns an internet protocol
+// family address.
+func resolveInternetAddr(net, addr string, deadline time.Time) (netaddr, error) {
var (
err error
host, port, zone string
@@ -201,28 +219,30 @@ func resolveInternetAddr(net, addr string, deadline time.Time) (Addr, error) {
default:
return nil, UnknownNetworkError(net)
}
- inetaddr := func(net string, ip IP, port int, zone string) Addr {
+ inetaddr := func(ip IP) netaddr {
switch net {
case "tcp", "tcp4", "tcp6":
- return &TCPAddr{IP: ip, Port: port, Zone: zone}
+ return &TCPAddr{IP: ip, Port: portnum, Zone: zone}
case "udp", "udp4", "udp6":
- return &UDPAddr{IP: ip, Port: port, Zone: zone}
+ return &UDPAddr{IP: ip, Port: portnum, Zone: zone}
case "ip", "ip4", "ip6":
return &IPAddr{IP: ip, Zone: zone}
+ default:
+ panic("unexpected network: " + net)
}
- return nil
}
if host == "" {
- return inetaddr(net, nil, portnum, zone), nil
+ return inetaddr(nil), nil
}
- // Try as an IP address.
- if ip := parseIPv4(host); ip != nil {
- return inetaddr(net, ip, portnum, zone), nil
+ // Try as a literal IP address.
+ var ip IP
+ if ip = parseIPv4(host); ip != nil {
+ return inetaddr(ip), nil
}
- if ip, zone := parseIPv6(host, true); ip != nil {
- return inetaddr(net, ip, portnum, zone), nil
+ if ip, zone = parseIPv6(host, true); ip != nil {
+ return inetaddr(ip), nil
}
- // Try as a domain name.
+ // Try as a DNS registered name.
host, zone = splitHostZone(host)
addrs, err := lookupHostDeadline(host, deadline)
if err != nil {
@@ -235,12 +255,7 @@ func resolveInternetAddr(net, addr string, deadline time.Time) (Addr, error) {
if net != "" && net[len(net)-1] == '6' || zone != "" {
filter = ipv6only
}
- ip := firstFavoriteAddr(filter, addrs)
- if ip == nil {
- // should not happen
- return nil, &AddrError{"LookupHost returned no suitable address", addrs[0]}
- }
- return inetaddr(net, ip, portnum, zone), nil
+ return firstFavoriteAddr(filter, addrs, inetaddr)
}
func zoneToString(zone int) string {
diff --git a/src/pkg/net/sock_posix.go b/src/pkg/net/sock_posix.go
index a6a6b4e91..c2d343c58 100644
--- a/src/pkg/net/sock_posix.go
+++ b/src/pkg/net/sock_posix.go
@@ -17,6 +17,8 @@ import (
type sockaddr interface {
Addr
+ netaddr
+
// family returns the platform-dependent address family
// identifier.
family() int
@@ -30,11 +32,6 @@ type sockaddr interface {
// interface. It returns a nil interface when the address is
// nil.
sockaddr(family int) (syscall.Sockaddr, error)
-
- // toAddr returns the address represented in sockaddr
- // interface. It returns a nil interface when the address is
- // nil.
- toAddr() sockaddr
}
// socket returns a network file descriptor that is ready for
diff --git a/src/pkg/net/tcpsock.go b/src/pkg/net/tcpsock.go
index 4d9ebd214..8614c7459 100644
--- a/src/pkg/net/tcpsock.go
+++ b/src/pkg/net/tcpsock.go
@@ -24,6 +24,13 @@ func (a *TCPAddr) String() string {
return JoinHostPort(a.IP.String(), itoa(a.Port))
}
+func (a *TCPAddr) toAddr() Addr {
+ if a == nil {
+ return nil
+ }
+ return a
+}
+
// ResolveTCPAddr parses addr as a TCP address of the form "host:port"
// or "[ipv6-host%zone]:port" and resolves a pair of domain name and
// port name on the network net, which must be "tcp", "tcp4" or
@@ -42,5 +49,5 @@ func ResolveTCPAddr(net, addr string) (*TCPAddr, error) {
if err != nil {
return nil, err
}
- return a.(*TCPAddr), nil
+ return a.toAddr().(*TCPAddr), nil
}
diff --git a/src/pkg/net/tcpsock_posix.go b/src/pkg/net/tcpsock_posix.go
index 512b74c3f..d9e25e26e 100644
--- a/src/pkg/net/tcpsock_posix.go
+++ b/src/pkg/net/tcpsock_posix.go
@@ -52,13 +52,6 @@ func (a *TCPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
return ipToSockaddr(family, a.IP, a.Port, a.Zone)
}
-func (a *TCPAddr) toAddr() sockaddr {
- if a == nil {
- return nil
- }
- return a
-}
-
// TCPConn is an implementation of the Conn interface for TCP network
// connections.
type TCPConn struct {
diff --git a/src/pkg/net/udpsock.go b/src/pkg/net/udpsock.go
index 5ce7d6bea..edbb93be3 100644
--- a/src/pkg/net/udpsock.go
+++ b/src/pkg/net/udpsock.go
@@ -28,6 +28,13 @@ func (a *UDPAddr) String() string {
return JoinHostPort(a.IP.String(), itoa(a.Port))
}
+func (a *UDPAddr) toAddr() Addr {
+ if a == nil {
+ return nil
+ }
+ return a
+}
+
// ResolveUDPAddr parses addr as a UDP address of the form "host:port"
// or "[ipv6-host%zone]:port" and resolves a pair of domain name and
// port name on the network net, which must be "udp", "udp4" or
@@ -46,5 +53,5 @@ func ResolveUDPAddr(net, addr string) (*UDPAddr, error) {
if err != nil {
return nil, err
}
- return a.(*UDPAddr), nil
+ return a.toAddr().(*UDPAddr), nil
}
diff --git a/src/pkg/net/udpsock_posix.go b/src/pkg/net/udpsock_posix.go
index 67af4de18..142da8186 100644
--- a/src/pkg/net/udpsock_posix.go
+++ b/src/pkg/net/udpsock_posix.go
@@ -45,13 +45,6 @@ func (a *UDPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
return ipToSockaddr(family, a.IP, a.Port, a.Zone)
}
-func (a *UDPAddr) toAddr() sockaddr {
- if a == nil {
- return nil
- }
- return a
-}
-
// UDPConn is the implementation of the Conn and PacketConn interfaces
// for UDP network connections.
type UDPConn struct {
diff --git a/src/pkg/net/unixsock.go b/src/pkg/net/unixsock.go
index 94c4c39dd..85955845b 100644
--- a/src/pkg/net/unixsock.go
+++ b/src/pkg/net/unixsock.go
@@ -23,6 +23,13 @@ func (a *UnixAddr) String() string {
return a.Name
}
+func (a *UnixAddr) toAddr() Addr {
+ if a == nil {
+ return nil
+ }
+ return a
+}
+
// ResolveUnixAddr parses addr as a Unix domain socket address.
// The string net gives the network name, "unix", "unixgram" or
// "unixpacket".
diff --git a/src/pkg/net/unixsock_posix.go b/src/pkg/net/unixsock_posix.go
index c71ee957e..fc061804c 100644
--- a/src/pkg/net/unixsock_posix.go
+++ b/src/pkg/net/unixsock_posix.go
@@ -105,13 +105,6 @@ func (a *UnixAddr) sockaddr(family int) (syscall.Sockaddr, error) {
return &syscall.SockaddrUnix{Name: a.Name}, nil
}
-func (a *UnixAddr) toAddr() sockaddr {
- if a == nil {
- return nil
- }
- return a
-}
-
// UnixConn is an implementation of the Conn interface for connections
// to Unix domain sockets.
type UnixConn struct {