mirror of
https://github.com/golang/go
synced 2024-09-30 22:18:32 -06:00
net: permit WriteMsgUDP to connected UDP sockets
The sanity checks at the beginning of WriteMsgUDP were too strict, and did not allow a case sendmsg(2) suppports: sending to a connected UDP socket. This fixes the sanity checks. Either the socket is unconnected, and a destination addresses is required (what all existing callers must have been doing), or the socket is connected and an explicit destination address must not be used. Fixes #9807 Change-Id: I08d4ec3c2bf830335c402acfc0680c841cfcec71 Reviewed-on: https://go-review.googlesource.com/3951 Reviewed-by: Mikio Hara <mikioh.mikioh@gmail.com>
This commit is contained in:
parent
e810a079eb
commit
263405ea4a
@ -81,26 +81,26 @@ func TestWriteToUDP(t *testing.T) {
|
||||
t.Skipf("skipping test on %q", runtime.GOOS)
|
||||
}
|
||||
|
||||
l, err := ListenPacket("udp", "127.0.0.1:0")
|
||||
c, err := ListenPacket("udp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatalf("Listen failed: %v", err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer l.Close()
|
||||
defer c.Close()
|
||||
|
||||
testWriteToConn(t, l.LocalAddr().String())
|
||||
testWriteToPacketConn(t, l.LocalAddr().String())
|
||||
testWriteToConn(t, c.LocalAddr().String())
|
||||
testWriteToPacketConn(t, c.LocalAddr().String())
|
||||
}
|
||||
|
||||
func testWriteToConn(t *testing.T, raddr string) {
|
||||
c, err := Dial("udp", raddr)
|
||||
if err != nil {
|
||||
t.Fatalf("Dial failed: %v", err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
ra, err := ResolveUDPAddr("udp", raddr)
|
||||
if err != nil {
|
||||
t.Fatalf("ResolveUDPAddr failed: %v", err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = c.(*UDPConn).WriteToUDP([]byte("Connection-oriented mode socket"), ra)
|
||||
@ -121,36 +121,60 @@ func testWriteToConn(t *testing.T, raddr string) {
|
||||
|
||||
_, err = c.Write([]byte("Connection-oriented mode socket"))
|
||||
if err != nil {
|
||||
t.Fatalf("Write failed: %v", err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, _, err = c.(*UDPConn).WriteMsgUDP([]byte("Connection-oriented mode socket"), nil, ra)
|
||||
if err == nil {
|
||||
t.Fatal("WriteMsgUDP should fail")
|
||||
}
|
||||
if err != nil && err.(*OpError).Err != ErrWriteToConnected {
|
||||
t.Fatalf("WriteMsgUDP should fail as ErrWriteToConnected: %v", err)
|
||||
}
|
||||
_, _, err = c.(*UDPConn).WriteMsgUDP([]byte("Connection-oriented mode socket"), nil, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func testWriteToPacketConn(t *testing.T, raddr string) {
|
||||
c, err := ListenPacket("udp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatalf("ListenPacket failed: %v", err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
ra, err := ResolveUDPAddr("udp", raddr)
|
||||
if err != nil {
|
||||
t.Fatalf("ResolveUDPAddr failed: %v", err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = c.(*UDPConn).WriteToUDP([]byte("Connection-less mode socket"), ra)
|
||||
if err != nil {
|
||||
t.Fatalf("WriteToUDP failed: %v", err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = c.WriteTo([]byte("Connection-less mode socket"), ra)
|
||||
if err != nil {
|
||||
t.Fatalf("WriteTo failed: %v", err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = c.(*UDPConn).Write([]byte("Connection-less mode socket"))
|
||||
if err == nil {
|
||||
t.Fatal("Write should fail")
|
||||
}
|
||||
|
||||
_, _, err = c.(*UDPConn).WriteMsgUDP([]byte("Connection-less mode socket"), nil, nil)
|
||||
if err == nil {
|
||||
t.Fatal("WriteMsgUDP should fail")
|
||||
}
|
||||
if err != nil && err.(*OpError).Err != errMissingAddress {
|
||||
t.Fatalf("WriteMsgUDP should fail as errMissingAddress: %v", err)
|
||||
}
|
||||
_, _, err = c.(*UDPConn).WriteMsgUDP([]byte("Connection-less mode socket"), nil, ra)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
var udpConnLocalNameTests = []struct {
|
||||
|
@ -139,17 +139,19 @@ func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) {
|
||||
return c.WriteToUDP(b, a)
|
||||
}
|
||||
|
||||
// WriteMsgUDP writes a packet to addr via c, copying the payload from
|
||||
// b and the associated out-of-band data from oob. It returns the
|
||||
// number of payload and out-of-band bytes written.
|
||||
// WriteMsgUDP writes a packet to addr via c if c isn't connected, or
|
||||
// to c's remote destination address if c is connected (in which case
|
||||
// addr must be nil). The payload is copied from b and the associated
|
||||
// out-of-band data is copied from oob. It returns the number of
|
||||
// payload and out-of-band bytes written.
|
||||
func (c *UDPConn) WriteMsgUDP(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) {
|
||||
if !c.ok() {
|
||||
return 0, 0, syscall.EINVAL
|
||||
}
|
||||
if c.fd.isConnected {
|
||||
if c.fd.isConnected && addr != nil {
|
||||
return 0, 0, &OpError{"write", c.fd.net, addr, ErrWriteToConnected}
|
||||
}
|
||||
if addr == nil {
|
||||
if !c.fd.isConnected && addr == nil {
|
||||
return 0, 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress}
|
||||
}
|
||||
sa, err := addr.sockaddr(c.fd.family)
|
||||
|
Loading…
Reference in New Issue
Block a user