blob: cc92c035bbbec37eaef7bd42aa395b61e6838247 [file] [log] [blame]
David K. Bainbridge215e0242017-09-05 23:18:24 -07001// Copyright 2014 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 nettest provides utilities for network testing.
6package nettest // import "golang.org/x/net/internal/nettest"
7
8import (
9 "fmt"
10 "io/ioutil"
11 "net"
12 "os"
13 "runtime"
14)
15
16var (
17 supportsIPv4 bool
18 supportsIPv6 bool
19)
20
21func init() {
22 if ln, err := net.Listen("tcp4", "127.0.0.1:0"); err == nil {
23 ln.Close()
24 supportsIPv4 = true
25 }
26 if ln, err := net.Listen("tcp6", "[::1]:0"); err == nil {
27 ln.Close()
28 supportsIPv6 = true
29 }
30}
31
32// SupportsIPv4 reports whether the platform supports IPv4 networking
33// functionality.
34func SupportsIPv4() bool { return supportsIPv4 }
35
36// SupportsIPv6 reports whether the platform supports IPv6 networking
37// functionality.
38func SupportsIPv6() bool { return supportsIPv6 }
39
40// SupportsRawIPSocket reports whether the platform supports raw IP
41// sockets.
42func SupportsRawIPSocket() (string, bool) {
43 return supportsRawIPSocket()
44}
45
46// SupportsIPv6MulticastDeliveryOnLoopback reports whether the
47// platform supports IPv6 multicast packet delivery on software
48// loopback interface.
49func SupportsIPv6MulticastDeliveryOnLoopback() bool {
50 return supportsIPv6MulticastDeliveryOnLoopback()
51}
52
53// ProtocolNotSupported reports whether err is a protocol not
54// supported error.
55func ProtocolNotSupported(err error) bool {
56 return protocolNotSupported(err)
57}
58
59// TestableNetwork reports whether network is testable on the current
60// platform configuration.
61func TestableNetwork(network string) bool {
62 // This is based on logic from standard library's
63 // net/platform_test.go.
64 switch network {
65 case "unix", "unixgram":
66 switch runtime.GOOS {
67 case "android", "nacl", "plan9", "windows":
68 return false
69 }
70 if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
71 return false
72 }
73 case "unixpacket":
74 switch runtime.GOOS {
75 case "android", "darwin", "freebsd", "nacl", "plan9", "windows":
76 return false
77 }
78 }
79 return true
80}
81
82// NewLocalListener returns a listener which listens to a loopback IP
83// address or local file system path.
84// Network must be "tcp", "tcp4", "tcp6", "unix" or "unixpacket".
85func NewLocalListener(network string) (net.Listener, error) {
86 switch network {
87 case "tcp":
88 if supportsIPv4 {
89 if ln, err := net.Listen("tcp4", "127.0.0.1:0"); err == nil {
90 return ln, nil
91 }
92 }
93 if supportsIPv6 {
94 return net.Listen("tcp6", "[::1]:0")
95 }
96 case "tcp4":
97 if supportsIPv4 {
98 return net.Listen("tcp4", "127.0.0.1:0")
99 }
100 case "tcp6":
101 if supportsIPv6 {
102 return net.Listen("tcp6", "[::1]:0")
103 }
104 case "unix", "unixpacket":
105 return net.Listen(network, localPath())
106 }
107 return nil, fmt.Errorf("%s is not supported", network)
108}
109
110// NewLocalPacketListener returns a packet listener which listens to a
111// loopback IP address or local file system path.
112// Network must be "udp", "udp4", "udp6" or "unixgram".
113func NewLocalPacketListener(network string) (net.PacketConn, error) {
114 switch network {
115 case "udp":
116 if supportsIPv4 {
117 if c, err := net.ListenPacket("udp4", "127.0.0.1:0"); err == nil {
118 return c, nil
119 }
120 }
121 if supportsIPv6 {
122 return net.ListenPacket("udp6", "[::1]:0")
123 }
124 case "udp4":
125 if supportsIPv4 {
126 return net.ListenPacket("udp4", "127.0.0.1:0")
127 }
128 case "udp6":
129 if supportsIPv6 {
130 return net.ListenPacket("udp6", "[::1]:0")
131 }
132 case "unixgram":
133 return net.ListenPacket(network, localPath())
134 }
135 return nil, fmt.Errorf("%s is not supported", network)
136}
137
138func localPath() string {
139 f, err := ioutil.TempFile("", "nettest")
140 if err != nil {
141 panic(err)
142 }
143 path := f.Name()
144 f.Close()
145 os.Remove(path)
146 return path
147}