internal/socket: drop support for go1.8 or below

Change-Id: I3dcc786d4e9196bfba7e139948ccf459d28675af
Reviewed-on: https://go-review.googlesource.com/c/net/+/162597
Run-TryBot: Mikio Hara <mikioh.public.networking@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Dave Cheney <dave@cheney.net>
diff --git a/internal/socket/rawconn.go b/internal/socket/rawconn.go
index d6871d5..b07b890 100644
--- a/internal/socket/rawconn.go
+++ b/internal/socket/rawconn.go
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build go1.9
-
 package socket
 
 import (
diff --git a/internal/socket/rawconn_mmsg.go b/internal/socket/rawconn_mmsg.go
index 499164a..1f4cb3b 100644
--- a/internal/socket/rawconn_mmsg.go
+++ b/internal/socket/rawconn_mmsg.go
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build go1.9
 // +build linux
 
 package socket
diff --git a/internal/socket/rawconn_msg.go b/internal/socket/rawconn_msg.go
index b21d2e6..76fea30 100644
--- a/internal/socket/rawconn_msg.go
+++ b/internal/socket/rawconn_msg.go
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build go1.9
 // +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
 
 package socket
diff --git a/internal/socket/rawconn_nommsg.go b/internal/socket/rawconn_nommsg.go
index 6ce6fd8..fe5bb94 100644
--- a/internal/socket/rawconn_nommsg.go
+++ b/internal/socket/rawconn_nommsg.go
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build go1.9
 // +build !linux
 
 package socket
diff --git a/internal/socket/rawconn_nomsg.go b/internal/socket/rawconn_nomsg.go
index 681e251..404b469 100644
--- a/internal/socket/rawconn_nomsg.go
+++ b/internal/socket/rawconn_nomsg.go
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build go1.9
 // +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
 
 package socket
diff --git a/internal/socket/rawconn_stub.go b/internal/socket/rawconn_stub.go
deleted file mode 100644
index 4c14e23..0000000
--- a/internal/socket/rawconn_stub.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2017 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.
-
-// +build !go1.9
-
-package socket
-
-func (c *Conn) recvMsg(m *Message, flags int) error {
-	return errNotImplemented
-}
-
-func (c *Conn) sendMsg(m *Message, flags int) error {
-	return errNotImplemented
-}
-
-func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) {
-	return 0, errNotImplemented
-}
-
-func (c *Conn) sendMsgs(ms []Message, flags int) (int, error) {
-	return 0, errNotImplemented
-}
diff --git a/internal/socket/reflect.go b/internal/socket/reflect.go
deleted file mode 100644
index bb179f1..0000000
--- a/internal/socket/reflect.go
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2017 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.
-
-// +build !go1.9
-
-package socket
-
-import (
-	"errors"
-	"net"
-	"os"
-	"reflect"
-	"runtime"
-)
-
-// A Conn represents a raw connection.
-type Conn struct {
-	c net.Conn
-}
-
-// NewConn returns a new raw connection.
-func NewConn(c net.Conn) (*Conn, error) {
-	return &Conn{c: c}, nil
-}
-
-func (o *Option) get(c *Conn, b []byte) (int, error) {
-	s, err := socketOf(c.c)
-	if err != nil {
-		return 0, err
-	}
-	n, err := getsockopt(s, o.Level, o.Name, b)
-	return n, os.NewSyscallError("getsockopt", err)
-}
-
-func (o *Option) set(c *Conn, b []byte) error {
-	s, err := socketOf(c.c)
-	if err != nil {
-		return err
-	}
-	return os.NewSyscallError("setsockopt", setsockopt(s, o.Level, o.Name, b))
-}
-
-func socketOf(c net.Conn) (uintptr, error) {
-	switch c.(type) {
-	case *net.TCPConn, *net.UDPConn, *net.IPConn:
-		v := reflect.ValueOf(c)
-		switch e := v.Elem(); e.Kind() {
-		case reflect.Struct:
-			fd := e.FieldByName("conn").FieldByName("fd")
-			switch e := fd.Elem(); e.Kind() {
-			case reflect.Struct:
-				sysfd := e.FieldByName("sysfd")
-				if runtime.GOOS == "windows" {
-					return uintptr(sysfd.Uint()), nil
-				}
-				return uintptr(sysfd.Int()), nil
-			}
-		}
-	}
-	return 0, errors.New("invalid type")
-}
diff --git a/internal/socket/socket_go1_9_test.go b/internal/socket/socket_go1_9_test.go
deleted file mode 100644
index c4edd4a..0000000
--- a/internal/socket/socket_go1_9_test.go
+++ /dev/null
@@ -1,259 +0,0 @@
-// Copyright 2017 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.
-
-// +build go1.9
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
-
-package socket_test
-
-import (
-	"bytes"
-	"fmt"
-	"net"
-	"runtime"
-	"testing"
-
-	"golang.org/x/net/internal/nettest"
-	"golang.org/x/net/internal/socket"
-)
-
-type mockControl struct {
-	Level int
-	Type  int
-	Data  []byte
-}
-
-func TestControlMessage(t *testing.T) {
-	for _, tt := range []struct {
-		cs []mockControl
-	}{
-		{
-			[]mockControl{
-				{Level: 1, Type: 1},
-			},
-		},
-		{
-			[]mockControl{
-				{Level: 2, Type: 2, Data: []byte{0xfe}},
-			},
-		},
-		{
-			[]mockControl{
-				{Level: 3, Type: 3, Data: []byte{0xfe, 0xff, 0xff, 0xfe}},
-			},
-		},
-		{
-			[]mockControl{
-				{Level: 4, Type: 4, Data: []byte{0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xfe}},
-			},
-		},
-		{
-			[]mockControl{
-				{Level: 4, Type: 4, Data: []byte{0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xfe}},
-				{Level: 2, Type: 2, Data: []byte{0xfe}},
-			},
-		},
-	} {
-		var w []byte
-		var tailPadLen int
-		mm := socket.NewControlMessage([]int{0})
-		for i, c := range tt.cs {
-			m := socket.NewControlMessage([]int{len(c.Data)})
-			l := len(m) - len(mm)
-			if i == len(tt.cs)-1 && l > len(c.Data) {
-				tailPadLen = l - len(c.Data)
-			}
-			w = append(w, m...)
-		}
-
-		var err error
-		ww := make([]byte, len(w))
-		copy(ww, w)
-		m := socket.ControlMessage(ww)
-		for _, c := range tt.cs {
-			if err = m.MarshalHeader(c.Level, c.Type, len(c.Data)); err != nil {
-				t.Fatalf("(%v).MarshalHeader() = %v", tt.cs, err)
-			}
-			copy(m.Data(len(c.Data)), c.Data)
-			m = m.Next(len(c.Data))
-		}
-		m = socket.ControlMessage(w)
-		for _, c := range tt.cs {
-			m, err = m.Marshal(c.Level, c.Type, c.Data)
-			if err != nil {
-				t.Fatalf("(%v).Marshal() = %v", tt.cs, err)
-			}
-		}
-		if !bytes.Equal(ww, w) {
-			t.Fatalf("got %#v; want %#v", ww, w)
-		}
-
-		ws := [][]byte{w}
-		if tailPadLen > 0 {
-			// Test a message with no tail padding.
-			nopad := w[:len(w)-tailPadLen]
-			ws = append(ws, [][]byte{nopad}...)
-		}
-		for _, w := range ws {
-			ms, err := socket.ControlMessage(w).Parse()
-			if err != nil {
-				t.Fatalf("(%v).Parse() = %v", tt.cs, err)
-			}
-			for i, m := range ms {
-				lvl, typ, dataLen, err := m.ParseHeader()
-				if err != nil {
-					t.Fatalf("(%v).ParseHeader() = %v", tt.cs, err)
-				}
-				if lvl != tt.cs[i].Level || typ != tt.cs[i].Type || dataLen != len(tt.cs[i].Data) {
-					t.Fatalf("%v: got %d, %d, %d; want %d, %d, %d", tt.cs[i], lvl, typ, dataLen, tt.cs[i].Level, tt.cs[i].Type, len(tt.cs[i].Data))
-				}
-			}
-		}
-	}
-}
-
-func TestUDP(t *testing.T) {
-	c, err := nettest.NewLocalPacketListener("udp")
-	if err != nil {
-		t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
-	}
-	defer c.Close()
-	cc, err := socket.NewConn(c.(net.Conn))
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	t.Run("Message", func(t *testing.T) {
-		data := []byte("HELLO-R-U-THERE")
-		wm := socket.Message{
-			Buffers: bytes.SplitAfter(data, []byte("-")),
-			Addr:    c.LocalAddr(),
-		}
-		if err := cc.SendMsg(&wm, 0); err != nil {
-			t.Fatal(err)
-		}
-		b := make([]byte, 32)
-		rm := socket.Message{
-			Buffers: [][]byte{b[:1], b[1:3], b[3:7], b[7:11], b[11:]},
-		}
-		if err := cc.RecvMsg(&rm, 0); err != nil {
-			t.Fatal(err)
-		}
-		if !bytes.Equal(b[:rm.N], data) {
-			t.Fatalf("got %#v; want %#v", b[:rm.N], data)
-		}
-	})
-	switch runtime.GOOS {
-	case "android", "linux":
-		t.Run("Messages", func(t *testing.T) {
-			data := []byte("HELLO-R-U-THERE")
-			wmbs := bytes.SplitAfter(data, []byte("-"))
-			wms := []socket.Message{
-				{Buffers: wmbs[:1], Addr: c.LocalAddr()},
-				{Buffers: wmbs[1:], Addr: c.LocalAddr()},
-			}
-			n, err := cc.SendMsgs(wms, 0)
-			if err != nil {
-				t.Fatal(err)
-			}
-			if n != len(wms) {
-				t.Fatalf("got %d; want %d", n, len(wms))
-			}
-			b := make([]byte, 32)
-			rmbs := [][][]byte{{b[:len(wmbs[0])]}, {b[len(wmbs[0]):]}}
-			rms := []socket.Message{
-				{Buffers: rmbs[0]},
-				{Buffers: rmbs[1]},
-			}
-			n, err = cc.RecvMsgs(rms, 0)
-			if err != nil {
-				t.Fatal(err)
-			}
-			if n != len(rms) {
-				t.Fatalf("got %d; want %d", n, len(rms))
-			}
-			nn := 0
-			for i := 0; i < n; i++ {
-				nn += rms[i].N
-			}
-			if !bytes.Equal(b[:nn], data) {
-				t.Fatalf("got %#v; want %#v", b[:nn], data)
-			}
-		})
-	}
-
-	// The behavior of transmission for zero byte paylaod depends
-	// on each platform implementation. Some may transmit only
-	// protocol header and options, other may transmit nothing.
-	// We test only that SendMsg and SendMsgs will not crash with
-	// empty buffers.
-	wm := socket.Message{
-		Buffers: [][]byte{{}},
-		Addr:    c.LocalAddr(),
-	}
-	cc.SendMsg(&wm, 0)
-	wms := []socket.Message{
-		{Buffers: [][]byte{{}}, Addr: c.LocalAddr()},
-	}
-	cc.SendMsgs(wms, 0)
-}
-
-func BenchmarkUDP(b *testing.B) {
-	c, err := nettest.NewLocalPacketListener("udp")
-	if err != nil {
-		b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
-	}
-	defer c.Close()
-	cc, err := socket.NewConn(c.(net.Conn))
-	if err != nil {
-		b.Fatal(err)
-	}
-	data := []byte("HELLO-R-U-THERE")
-	wm := socket.Message{
-		Buffers: [][]byte{data},
-		Addr:    c.LocalAddr(),
-	}
-	rm := socket.Message{
-		Buffers: [][]byte{make([]byte, 128)},
-		OOB:     make([]byte, 128),
-	}
-
-	for M := 1; M <= 1<<9; M = M << 1 {
-		b.Run(fmt.Sprintf("Iter-%d", M), func(b *testing.B) {
-			for i := 0; i < b.N; i++ {
-				for j := 0; j < M; j++ {
-					if err := cc.SendMsg(&wm, 0); err != nil {
-						b.Fatal(err)
-					}
-					if err := cc.RecvMsg(&rm, 0); err != nil {
-						b.Fatal(err)
-					}
-				}
-			}
-		})
-		switch runtime.GOOS {
-		case "android", "linux":
-			wms := make([]socket.Message, M)
-			for i := range wms {
-				wms[i].Buffers = [][]byte{data}
-				wms[i].Addr = c.LocalAddr()
-			}
-			rms := make([]socket.Message, M)
-			for i := range rms {
-				rms[i].Buffers = [][]byte{make([]byte, 128)}
-				rms[i].OOB = make([]byte, 128)
-			}
-			b.Run(fmt.Sprintf("Batch-%d", M), func(b *testing.B) {
-				for i := 0; i < b.N; i++ {
-					if _, err := cc.SendMsgs(wms, 0); err != nil {
-						b.Fatal(err)
-					}
-					if _, err := cc.RecvMsgs(rms, 0); err != nil {
-						b.Fatal(err)
-					}
-				}
-			})
-		}
-	}
-}
diff --git a/internal/socket/socket_test.go b/internal/socket/socket_test.go
index bf3751b..5de1b9f 100644
--- a/internal/socket/socket_test.go
+++ b/internal/socket/socket_test.go
@@ -7,6 +7,8 @@
 package socket_test
 
 import (
+	"bytes"
+	"fmt"
 	"net"
 	"runtime"
 	"syscall"
@@ -44,3 +46,253 @@
 		t.Fatalf("got %d; want greater than or equal to %d", n, N)
 	}
 }
+
+type mockControl struct {
+	Level int
+	Type  int
+	Data  []byte
+}
+
+func TestControlMessage(t *testing.T) {
+	switch runtime.GOOS {
+	case "windows":
+		t.Skipf("not supported on %s", runtime.GOOS)
+	}
+
+	for _, tt := range []struct {
+		cs []mockControl
+	}{
+		{
+			[]mockControl{
+				{Level: 1, Type: 1},
+			},
+		},
+		{
+			[]mockControl{
+				{Level: 2, Type: 2, Data: []byte{0xfe}},
+			},
+		},
+		{
+			[]mockControl{
+				{Level: 3, Type: 3, Data: []byte{0xfe, 0xff, 0xff, 0xfe}},
+			},
+		},
+		{
+			[]mockControl{
+				{Level: 4, Type: 4, Data: []byte{0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xfe}},
+			},
+		},
+		{
+			[]mockControl{
+				{Level: 4, Type: 4, Data: []byte{0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xfe}},
+				{Level: 2, Type: 2, Data: []byte{0xfe}},
+			},
+		},
+	} {
+		var w []byte
+		var tailPadLen int
+		mm := socket.NewControlMessage([]int{0})
+		for i, c := range tt.cs {
+			m := socket.NewControlMessage([]int{len(c.Data)})
+			l := len(m) - len(mm)
+			if i == len(tt.cs)-1 && l > len(c.Data) {
+				tailPadLen = l - len(c.Data)
+			}
+			w = append(w, m...)
+		}
+
+		var err error
+		ww := make([]byte, len(w))
+		copy(ww, w)
+		m := socket.ControlMessage(ww)
+		for _, c := range tt.cs {
+			if err = m.MarshalHeader(c.Level, c.Type, len(c.Data)); err != nil {
+				t.Fatalf("(%v).MarshalHeader() = %v", tt.cs, err)
+			}
+			copy(m.Data(len(c.Data)), c.Data)
+			m = m.Next(len(c.Data))
+		}
+		m = socket.ControlMessage(w)
+		for _, c := range tt.cs {
+			m, err = m.Marshal(c.Level, c.Type, c.Data)
+			if err != nil {
+				t.Fatalf("(%v).Marshal() = %v", tt.cs, err)
+			}
+		}
+		if !bytes.Equal(ww, w) {
+			t.Fatalf("got %#v; want %#v", ww, w)
+		}
+
+		ws := [][]byte{w}
+		if tailPadLen > 0 {
+			// Test a message with no tail padding.
+			nopad := w[:len(w)-tailPadLen]
+			ws = append(ws, [][]byte{nopad}...)
+		}
+		for _, w := range ws {
+			ms, err := socket.ControlMessage(w).Parse()
+			if err != nil {
+				t.Fatalf("(%v).Parse() = %v", tt.cs, err)
+			}
+			for i, m := range ms {
+				lvl, typ, dataLen, err := m.ParseHeader()
+				if err != nil {
+					t.Fatalf("(%v).ParseHeader() = %v", tt.cs, err)
+				}
+				if lvl != tt.cs[i].Level || typ != tt.cs[i].Type || dataLen != len(tt.cs[i].Data) {
+					t.Fatalf("%v: got %d, %d, %d; want %d, %d, %d", tt.cs[i], lvl, typ, dataLen, tt.cs[i].Level, tt.cs[i].Type, len(tt.cs[i].Data))
+				}
+			}
+		}
+	}
+}
+
+func TestUDP(t *testing.T) {
+	switch runtime.GOOS {
+	case "windows":
+		t.Skipf("not supported on %s", runtime.GOOS)
+	}
+
+	c, err := nettest.NewLocalPacketListener("udp")
+	if err != nil {
+		t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
+	}
+	defer c.Close()
+	cc, err := socket.NewConn(c.(net.Conn))
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	t.Run("Message", func(t *testing.T) {
+		data := []byte("HELLO-R-U-THERE")
+		wm := socket.Message{
+			Buffers: bytes.SplitAfter(data, []byte("-")),
+			Addr:    c.LocalAddr(),
+		}
+		if err := cc.SendMsg(&wm, 0); err != nil {
+			t.Fatal(err)
+		}
+		b := make([]byte, 32)
+		rm := socket.Message{
+			Buffers: [][]byte{b[:1], b[1:3], b[3:7], b[7:11], b[11:]},
+		}
+		if err := cc.RecvMsg(&rm, 0); err != nil {
+			t.Fatal(err)
+		}
+		if !bytes.Equal(b[:rm.N], data) {
+			t.Fatalf("got %#v; want %#v", b[:rm.N], data)
+		}
+	})
+	switch runtime.GOOS {
+	case "android", "linux":
+		t.Run("Messages", func(t *testing.T) {
+			data := []byte("HELLO-R-U-THERE")
+			wmbs := bytes.SplitAfter(data, []byte("-"))
+			wms := []socket.Message{
+				{Buffers: wmbs[:1], Addr: c.LocalAddr()},
+				{Buffers: wmbs[1:], Addr: c.LocalAddr()},
+			}
+			n, err := cc.SendMsgs(wms, 0)
+			if err != nil {
+				t.Fatal(err)
+			}
+			if n != len(wms) {
+				t.Fatalf("got %d; want %d", n, len(wms))
+			}
+			b := make([]byte, 32)
+			rmbs := [][][]byte{{b[:len(wmbs[0])]}, {b[len(wmbs[0]):]}}
+			rms := []socket.Message{
+				{Buffers: rmbs[0]},
+				{Buffers: rmbs[1]},
+			}
+			n, err = cc.RecvMsgs(rms, 0)
+			if err != nil {
+				t.Fatal(err)
+			}
+			if n != len(rms) {
+				t.Fatalf("got %d; want %d", n, len(rms))
+			}
+			nn := 0
+			for i := 0; i < n; i++ {
+				nn += rms[i].N
+			}
+			if !bytes.Equal(b[:nn], data) {
+				t.Fatalf("got %#v; want %#v", b[:nn], data)
+			}
+		})
+	}
+
+	// The behavior of transmission for zero byte paylaod depends
+	// on each platform implementation. Some may transmit only
+	// protocol header and options, other may transmit nothing.
+	// We test only that SendMsg and SendMsgs will not crash with
+	// empty buffers.
+	wm := socket.Message{
+		Buffers: [][]byte{{}},
+		Addr:    c.LocalAddr(),
+	}
+	cc.SendMsg(&wm, 0)
+	wms := []socket.Message{
+		{Buffers: [][]byte{{}}, Addr: c.LocalAddr()},
+	}
+	cc.SendMsgs(wms, 0)
+}
+
+func BenchmarkUDP(b *testing.B) {
+	c, err := nettest.NewLocalPacketListener("udp")
+	if err != nil {
+		b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
+	}
+	defer c.Close()
+	cc, err := socket.NewConn(c.(net.Conn))
+	if err != nil {
+		b.Fatal(err)
+	}
+	data := []byte("HELLO-R-U-THERE")
+	wm := socket.Message{
+		Buffers: [][]byte{data},
+		Addr:    c.LocalAddr(),
+	}
+	rm := socket.Message{
+		Buffers: [][]byte{make([]byte, 128)},
+		OOB:     make([]byte, 128),
+	}
+
+	for M := 1; M <= 1<<9; M = M << 1 {
+		b.Run(fmt.Sprintf("Iter-%d", M), func(b *testing.B) {
+			for i := 0; i < b.N; i++ {
+				for j := 0; j < M; j++ {
+					if err := cc.SendMsg(&wm, 0); err != nil {
+						b.Fatal(err)
+					}
+					if err := cc.RecvMsg(&rm, 0); err != nil {
+						b.Fatal(err)
+					}
+				}
+			}
+		})
+		switch runtime.GOOS {
+		case "android", "linux":
+			wms := make([]socket.Message, M)
+			for i := range wms {
+				wms[i].Buffers = [][]byte{data}
+				wms[i].Addr = c.LocalAddr()
+			}
+			rms := make([]socket.Message, M)
+			for i := range rms {
+				rms[i].Buffers = [][]byte{make([]byte, 128)}
+				rms[i].OOB = make([]byte, 128)
+			}
+			b.Run(fmt.Sprintf("Batch-%d", M), func(b *testing.B) {
+				for i := 0; i < b.N; i++ {
+					if _, err := cc.SendMsgs(wms, 0); err != nil {
+						b.Fatal(err)
+					}
+					if _, err := cc.RecvMsgs(rms, 0); err != nil {
+						b.Fatal(err)
+					}
+				}
+			})
+		}
+	}
+}
diff --git a/internal/socket/sys_posix.go b/internal/socket/sys_posix.go
index 9a9bc47..fbac72d 100644
--- a/internal/socket/sys_posix.go
+++ b/internal/socket/sys_posix.go
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build go1.9
 // +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
 
 package socket