Skip to content

Commit a5a99cb

Browse files
marten-seemannianlancetaylor
authored andcommitted
internal/socket: use interface not type assertions to infer a wrapped net.Conn's kind
When passing a wrapped connection to ipv{4,6}.NewPacketConn, calls to ReadBatch will fail with an invalid connection error. This is because NewConn performs a type assertion to determine the type (TCP, UDP, IP) of the net.Conn. In order to allow for wrapped connections to be passed to NewConn, we can use an interface assertion that checks for methods on the net.Conn that are unique to TCP, UDP and IP. Fixes golang/go#42444. Change-Id: I07cdb037829643f5cf4cd77105a772fcff8c4b2a Reviewed-on: https://go-review.googlesource.com/c/net/+/271927 Reviewed-by: Emmanuel Odeke <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Run-TryBot: Emmanuel Odeke <[email protected]> TryBot-Result: Go Bot <[email protected]> Trust: Daniel Martí <[email protected]>
1 parent 0fccb6f commit a5a99cb

File tree

2 files changed

+33
-4
lines changed

2 files changed

+33
-4
lines changed

internal/socket/rawconn.go

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,45 @@ type Conn struct {
1717
c syscall.RawConn
1818
}
1919

20+
// tcpConn is an interface implemented by net.TCPConn.
21+
// It can be used for interface assertions to check if a net.Conn is a TCP connection.
22+
type tcpConn interface {
23+
SyscallConn() (syscall.RawConn, error)
24+
SetLinger(int) error
25+
}
26+
27+
var _ tcpConn = (*net.TCPConn)(nil)
28+
29+
// udpConn is an interface implemented by net.UDPConn.
30+
// It can be used for interface assertions to check if a net.Conn is a UDP connection.
31+
type udpConn interface {
32+
SyscallConn() (syscall.RawConn, error)
33+
ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *net.UDPAddr, err error)
34+
}
35+
36+
var _ udpConn = (*net.UDPConn)(nil)
37+
38+
// ipConn is an interface implemented by net.IPConn.
39+
// It can be used for interface assertions to check if a net.Conn is an IP connection.
40+
type ipConn interface {
41+
SyscallConn() (syscall.RawConn, error)
42+
ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *net.IPAddr, err error)
43+
}
44+
45+
var _ ipConn = (*net.IPConn)(nil)
46+
2047
// NewConn returns a new raw connection.
2148
func NewConn(c net.Conn) (*Conn, error) {
2249
var err error
2350
var cc Conn
2451
switch c := c.(type) {
25-
case *net.TCPConn:
52+
case tcpConn:
2653
cc.network = "tcp"
2754
cc.c, err = c.SyscallConn()
28-
case *net.UDPConn:
55+
case udpConn:
2956
cc.network = "udp"
3057
cc.c, err = c.SyscallConn()
31-
case *net.IPConn:
58+
case ipConn:
3259
cc.network = "ip"
3360
cc.c, err = c.SyscallConn()
3461
default:

internal/socket/socket_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,9 @@ func TestUDP(t *testing.T) {
164164
t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
165165
}
166166
defer c.Close()
167-
cc, err := socket.NewConn(c.(net.Conn))
167+
// test that wrapped connections work with NewConn too
168+
type wrappedConn struct{ *net.UDPConn }
169+
cc, err := socket.NewConn(&wrappedConn{c.(*net.UDPConn)})
168170
if err != nil {
169171
t.Fatal(err)
170172
}

0 commit comments

Comments
 (0)