stack.go 3.8 KB

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