diff --git a/common/buf/readv_reader.go b/common/buf/readv_reader.go index d4c6617a3..b624b1b71 100644 --- a/common/buf/readv_reader.go +++ b/common/buf/readv_reader.go @@ -142,7 +142,7 @@ func init() { value := platform.NewEnvFlag("v2ray.buf.readv").GetValue(func() string { return defaultFlagValue }) switch value { case defaultFlagValue, "auto": - if (runtime.GOARCH == "386" || runtime.GOARCH == "amd64" || runtime.GOARCH == "s390x") && (runtime.GOOS == "linux" || runtime.GOOS == "darwin") { + if (runtime.GOARCH == "386" || runtime.GOARCH == "amd64" || runtime.GOARCH == "s390x") && (runtime.GOOS == "linux" || runtime.GOOS == "darwin" || runtime.GOOS == "windows") { useReadv = true } case "enable": diff --git a/common/buf/readv_test.go b/common/buf/readv_test.go new file mode 100644 index 000000000..4a6575a06 --- /dev/null +++ b/common/buf/readv_test.go @@ -0,0 +1,64 @@ +package buf_test + +import ( + "crypto/rand" + "net" + "testing" + + "v2ray.com/core/common" + . "v2ray.com/core/common/buf" + "v2ray.com/core/common/compare" + "v2ray.com/core/testing/servers/tcp" +) + +func TestReadvReader(t *testing.T) { + tcpServer := &tcp.Server{ + MsgProcessor: func(b []byte) []byte { + return b + }, + } + dest, err := tcpServer.Start() + common.Must(err) + defer tcpServer.Close() // nolint: errcheck + + conn, err := net.Dial("tcp", dest.NetAddr()) + common.Must(err) + defer conn.Close() // nolint: errcheck + + const size = 8192 + data := make([]byte, 8192) + common.Must2(rand.Read(data)) + + go func() { + writer := NewWriter(conn) + var mb MultiBuffer + common.Must2(mb.Write(data)) + + if err := writer.WriteMultiBuffer(mb); err != nil { + t.Fatal("failed to write data: ", err) + } + }() + + rawConn, err := conn.(*net.TCPConn).SyscallConn() + common.Must(err) + + reader := NewReadVReader(conn, rawConn) + var rmb MultiBuffer + for { + mb, err := reader.ReadMultiBuffer() + if err != nil { + t.Fatal("unexpected error: ", err) + } + rmb.AppendMulti(mb) + if rmb.Len() == size { + break + } + } + + rdata := make([]byte, size) + common.Must2(rmb.Read(rdata)) + + if err := compare.BytesEqualWithDetail(data, rdata); err != nil { + t.Fatal(err) + } +} diff --git a/common/buf/readv_windows.go b/common/buf/readv_windows.go index 04f5047bd..f58c6536a 100644 --- a/common/buf/readv_windows.go +++ b/common/buf/readv_windows.go @@ -5,10 +5,7 @@ package buf import "syscall" type windowsReader struct { - o syscall.Overlapped - bufs []syscall.WSABuf - flags uint32 - qty uint32 + bufs []syscall.WSABuf } func (r *windowsReader) Init(bs []*Buffer) { @@ -29,7 +26,9 @@ func (r *windowsReader) Clear() { func (r *windowsReader) Read(fd uintptr) int32 { var nBytes uint32 - err := syscall.WSARecv(syscall.Handle(fd), &r.bufs[0], uint32(len(r.bufs)), &nBytes, &r.flags, &r.o, nil) + var flags uint32 + var o syscall.Overlapped + err := syscall.WSARecv(syscall.Handle(fd), &r.bufs[0], uint32(len(r.bufs)), &nBytes, &flags, &o, nil) if err != nil { return -1 }