diff --git a/src/pkg/net/fd.go b/src/pkg/net/fd.go index e1592eb269..733f957e51 100644 --- a/src/pkg/net/fd.go +++ b/src/pkg/net/fd.go @@ -386,6 +386,10 @@ func (fd *netFD) Read(p []byte) (n int, err os.Error) { } break; } + if fd.proto == syscall.SOCK_DGRAM && err == os.EOF { + // 0 in datagram protocol just means 0-length packet + err = nil + } return; } @@ -433,7 +437,9 @@ func (fd *netFD) Write(p []byte) (n int, err os.Error) { } err = nil; nn := 0; - for nn < len(p) { + first := true; // force at least one Write, to send 0-length datagram packets + for nn < len(p) || first { + first = false; n, err = fd.sysfile.Write(p[nn:]); if n > 0 { nn += n diff --git a/src/pkg/net/server_test.go b/src/pkg/net/server_test.go index d5c2f182cb..454f1d7119 100644 --- a/src/pkg/net/server_test.go +++ b/src/pkg/net/server_test.go @@ -45,7 +45,7 @@ func runServe(t *testing.T, network, addr string, listening chan<- string, done done <- 1; } -func connect(t *testing.T, network, addr string) { +func connect(t *testing.T, network, addr string, isEmpty bool) { var laddr string; if network == "unixgram" { laddr = addr + ".local" @@ -54,18 +54,22 @@ func connect(t *testing.T, network, addr string) { if err != nil { t.Fatalf("net.Dial(%q, %q, %q) = _, %v", network, laddr, addr, err) } + fd.SetReadTimeout(10e6); // 10ms - b := strings.Bytes("hello, world\n"); + var b []byte; + if !isEmpty { + b = strings.Bytes("hello, world\n") + } var b1 [100]byte; - n, errno := fd.Write(b); + n, err := fd.Write(b); if n != len(b) { - t.Fatalf("fd.Write(%q) = %d, %v", b, n, errno) + t.Fatalf("fd.Write(%q) = %d, %v", b, n, err) } - n, errno = fd.Read(&b1); - if n != len(b) { - t.Fatalf("fd.Read() = %d, %v", n, errno) + n, err = fd.Read(&b1); + if n != len(b) || err != nil { + t.Fatalf("fd.Read() = %d, %v (want %d, nil)", n, err, len(b)) } fd.Close(); } @@ -82,7 +86,7 @@ func doTest(t *testing.T, network, listenaddr, dialaddr string) { if network == "tcp" { dialaddr += addr[strings.LastIndex(addr, ":"):] } - connect(t, network, dialaddr); + connect(t, network, dialaddr, false); <-done; // make sure server stopped } @@ -133,7 +137,7 @@ func runPacket(t *testing.T, network, addr string, listening chan<- string, done done <- 1; } -func doTestPacket(t *testing.T, network, listenaddr, dialaddr string) { +func doTestPacket(t *testing.T, network, listenaddr, dialaddr string, isEmpty bool) { t.Logf("TestPacket %s %s %s\n", network, listenaddr, dialaddr); listening := make(chan string); done := make(chan int); @@ -145,29 +149,33 @@ func doTestPacket(t *testing.T, network, listenaddr, dialaddr string) { if network == "udp" { dialaddr += addr[strings.LastIndex(addr, ":"):] } - connect(t, network, dialaddr); + connect(t, network, dialaddr, isEmpty); <-done; // tell server to stop <-done; // wait for stop } func TestUDPServer(t *testing.T) { - doTestPacket(t, "udp", "0.0.0.0", "127.0.0.1"); - doTestPacket(t, "udp", "", "127.0.0.1"); - if kernelSupportsIPv6() { - doTestPacket(t, "udp", "[::]", "[::ffff:127.0.0.1]"); - doTestPacket(t, "udp", "[::]", "127.0.0.1"); - doTestPacket(t, "udp", "0.0.0.0", "[::ffff:127.0.0.1]"); + for _, isEmpty := range []bool{false, true} { + doTestPacket(t, "udp", "0.0.0.0", "127.0.0.1", isEmpty); + doTestPacket(t, "udp", "", "127.0.0.1", isEmpty); + if kernelSupportsIPv6() { + doTestPacket(t, "udp", "[::]", "[::ffff:127.0.0.1]", isEmpty); + doTestPacket(t, "udp", "[::]", "127.0.0.1", isEmpty); + doTestPacket(t, "udp", "0.0.0.0", "[::ffff:127.0.0.1]", isEmpty); + } } } func TestUnixDatagramServer(t *testing.T) { - os.Remove("/tmp/gotest1.net"); - os.Remove("/tmp/gotest1.net.local"); - doTestPacket(t, "unixgram", "/tmp/gotest1.net", "/tmp/gotest1.net"); - os.Remove("/tmp/gotest1.net"); - os.Remove("/tmp/gotest1.net.local"); - if syscall.OS == "linux" { - // Test abstract unix domain socket, a Linux-ism - doTestPacket(t, "unixgram", "@gotest1/net", "@gotest1/net") + for _, isEmpty := range []bool{false, true} { + os.Remove("/tmp/gotest1.net"); + os.Remove("/tmp/gotest1.net.local"); + doTestPacket(t, "unixgram", "/tmp/gotest1.net", "/tmp/gotest1.net", isEmpty); + os.Remove("/tmp/gotest1.net"); + os.Remove("/tmp/gotest1.net.local"); + if syscall.OS == "linux" { + // Test abstract unix domain socket, a Linux-ism + doTestPacket(t, "unixgram", "@gotest1/net", "@gotest1/net", isEmpty) + } } }