Browse Source

go.net/internal/nettest: new package

This CL factors out testing utilities used by both ipv4 and ipv6 packages.

LGTM=iant
R=iant
CC=golang-codereviews
https://golang.org/cl/152070043
Mikio Hara 11 years ago
parent
commit
fb10a5fdb4
2 changed files with 121 additions and 0 deletions
  1. 91 0
      internal/nettest/interface.go
  2. 30 0
      internal/nettest/stack.go

+ 91 - 0
internal/nettest/interface.go

@@ -0,0 +1,91 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package nettest
+
+import "net"
+
+// IsMulticastCapable reports whether ifi is an IP multicast-capable
+// network interface. Network must be "ip", "ip4" or "ip6".
+func IsMulticastCapable(network string, ifi *net.Interface) (net.IP, bool) {
+	switch network {
+	case "ip", "ip4", "ip6":
+	default:
+		return nil, false
+	}
+	if ifi == nil || ifi.Flags&net.FlagUp == 0 || ifi.Flags&net.FlagMulticast == 0 {
+		return nil, false
+	}
+	return hasRoutableIP(network, ifi)
+}
+
+// RoutedInterface returns a network interface that can route IP
+// traffic and satisfies flags. It returns nil when an appropriate
+// network interface is not found. Network must be "ip", "ip4" or
+// "ip6".
+func RoutedInterface(network string, flags net.Flags) *net.Interface {
+	switch network {
+	case "ip", "ip4", "ip6":
+	default:
+		return nil
+	}
+	ift, err := net.Interfaces()
+	if err != nil {
+		return nil
+	}
+	for _, ifi := range ift {
+		if ifi.Flags&flags != flags {
+			continue
+		}
+		if _, ok := hasRoutableIP(network, &ifi); !ok {
+			continue
+		}
+		return &ifi
+	}
+	return nil
+}
+
+func hasRoutableIP(network string, ifi *net.Interface) (net.IP, bool) {
+	ifat, err := ifi.Addrs()
+	if err != nil {
+		return nil, false
+	}
+	for _, ifa := range ifat {
+		switch ifa := ifa.(type) {
+		case *net.IPAddr:
+			if ip := routableIP(network, ifa.IP); ip != nil {
+				return ip, true
+			}
+		case *net.IPNet:
+			if ip := routableIP(network, ifa.IP); ip != nil {
+				return ip, true
+			}
+		}
+	}
+	return nil, false
+}
+
+func routableIP(network string, ip net.IP) net.IP {
+	if !ip.IsLoopback() && !ip.IsLinkLocalUnicast() && !ip.IsGlobalUnicast() {
+		return nil
+	}
+	switch network {
+	case "ip4":
+		if ip := ip.To4(); ip != nil {
+			return ip
+		}
+	case "ip6":
+		if ip := ip.To16(); ip != nil && ip.To4() == nil {
+			return ip
+		}
+	default:
+		if ip := ip.To4(); ip != nil {
+			return ip
+		}
+		if ip := ip.To16(); ip != nil {
+			return ip
+		}
+	}
+	return nil
+}

+ 30 - 0
internal/nettest/stack.go

@@ -0,0 +1,30 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package nettest provides utilities for IP testing.
+package nettest
+
+import "net"
+
+// SupportsIPv4 reports whether the platform supports IPv4 networking
+// functionality.
+func SupportsIPv4() bool {
+	ln, err := net.Listen("tcp4", "127.0.0.1:0")
+	if err != nil {
+		return false
+	}
+	ln.Close()
+	return true
+}
+
+// SupportsIPv6 reports whether the platform supports IPv6 networking
+// functionality.
+func SupportsIPv6() bool {
+	ln, err := net.Listen("tcp6", "[::1]:0")
+	if err != nil {
+		return false
+	}
+	ln.Close()
+	return true
+}