Skip to content

Commit d199bc5

Browse files
committed
Fix writev
1 parent 9e4c902 commit d199bc5

File tree

3 files changed

+60
-32
lines changed

3 files changed

+60
-32
lines changed

common/bufio/vectorised.go

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package bufio
33
import (
44
"io"
55
"net"
6+
"runtime"
67
"syscall"
78

89
"github.com/sagernet/sing/common"
@@ -19,26 +20,36 @@ func NewVectorisedWriter(writer io.Writer) N.VectorisedWriter {
1920
}
2021

2122
func CreateVectorisedWriter(writer any) (N.VectorisedWriter, bool) {
23+
var rawConn syscall.RawConn
2224
switch w := writer.(type) {
2325
case N.VectorisedWriter:
2426
return w, true
25-
/*case *net.TCPConn:
26-
return &NetVectorisedWriterWrapper{w}, true
27-
case *net.UDPConn:
28-
return &NetVectorisedWriterWrapper{w}, true
29-
case *net.IPConn:
30-
return &NetVectorisedWriterWrapper{w}, true
31-
case *net.UnixConn:
32-
return &NetVectorisedWriterWrapper{w}, true*/
3327
case syscall.Conn:
34-
rawConn, err := w.SyscallConn()
35-
if err == nil {
36-
return &SyscallVectorisedWriter{upstream: writer, rawConn: rawConn}, true
28+
var err error
29+
rawConn, err = w.SyscallConn()
30+
if err != nil {
31+
return nil, false
3732
}
3833
case syscall.RawConn:
39-
return &SyscallVectorisedWriter{upstream: writer, rawConn: w}, true
34+
rawConn = w
35+
default:
36+
return nil, false
4037
}
41-
return nil, false
38+
if runtime.GOOS == "windows" {
39+
switch conn := writer.(type) {
40+
case *net.TCPConn:
41+
return &NetVectorisedWriterWrapper{conn}, true
42+
case *net.UDPConn:
43+
return &NetVectorisedWriterWrapper{conn}, true
44+
case *net.IPConn:
45+
return &NetVectorisedWriterWrapper{conn}, true
46+
case *net.UnixConn:
47+
return &NetVectorisedWriterWrapper{conn}, true
48+
default:
49+
return nil, false
50+
}
51+
}
52+
return &SyscallVectorisedWriter{upstream: writer, rawConn: rawConn}, false
4253
}
4354

4455
func CreateVectorisedPacketWriter(writer any) (N.VectorisedPacketWriter, bool) {

common/bufio/vectorised_unix.go

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"sync"
88
"unsafe"
99

10+
"github.com/sagernet/sing/common"
1011
"github.com/sagernet/sing/common/buf"
1112
M "github.com/sagernet/sing/common/metadata"
1213

@@ -28,13 +29,30 @@ func (w *SyscallVectorisedWriter) WriteVectorised(buffers []*buf.Buffer) error {
2829
}
2930
var innerErr unix.Errno
3031
err := w.rawConn.Write(func(fd uintptr) (done bool) {
31-
//nolint:staticcheck
32-
_, _, innerErr = unix.Syscall(unix.SYS_WRITEV, fd, uintptr(unsafe.Pointer(&iovecList[0])), uintptr(len(iovecList)))
33-
return innerErr != unix.EAGAIN && innerErr != unix.EWOULDBLOCK
32+
for {
33+
var r0 uintptr
34+
//nolint:staticcheck
35+
r0, _, innerErr = unix.RawSyscall(unix.SYS_WRITEV, fd, uintptr(unsafe.Pointer(&iovecList[0])), uintptr(len(iovecList)))
36+
writeN := int(r0)
37+
for writeN > 0 {
38+
if buffers[0].Len() > writeN {
39+
buffers[0].Advance(writeN)
40+
iovecList[0] = buffers[0].Iovec(buffers[0].Len())
41+
break
42+
} else {
43+
writeN -= buffers[0].Len()
44+
buffers[0].Release()
45+
buffers = buffers[1:]
46+
iovecList = iovecList[1:]
47+
}
48+
}
49+
if innerErr == unix.EINTR || (innerErr == 0 && len(iovecList) > 0) {
50+
continue
51+
}
52+
return innerErr != unix.EAGAIN
53+
}
3454
})
35-
for i := range iovecList {
36-
iovecList[i] = unix.Iovec{}
37-
}
55+
common.ClearArray(iovecList)
3856
if cap(iovecList) > cap(w.iovecList) {
3957
w.iovecList = iovecList[:0]
4058
}
@@ -62,12 +80,15 @@ func (w *SyscallVectorisedPacketWriter) WriteVectorisedPacket(buffers []*buf.Buf
6280
msg.Iov = &iovecList[0]
6381
msg.SetIovlen(len(iovecList))
6482
}
65-
_, innerErr = sendmsg(int(fd), &msg, 0)
66-
return innerErr != unix.EAGAIN && innerErr != unix.EWOULDBLOCK
83+
for {
84+
_, _, innerErr = unix.RawSyscall(unix.SYS_SENDMSG, fd, uintptr(unsafe.Pointer(&msg)), 0)
85+
if innerErr == unix.EINTR {
86+
continue
87+
}
88+
return innerErr != unix.EAGAIN
89+
}
6790
})
68-
for i := range iovecList {
69-
iovecList[i] = unix.Iovec{}
70-
}
91+
common.ClearArray(iovecList)
7192
if cap(iovecList) > cap(w.iovecList) {
7293
w.iovecList = iovecList[:0]
7394
}
@@ -76,6 +97,3 @@ func (w *SyscallVectorisedPacketWriter) WriteVectorisedPacket(buffers []*buf.Buf
7697
}
7798
return err
7899
}
79-
80-
//go:linkname sendmsg golang.org/x/sys/unix.sendmsg
81-
func sendmsg(s int, msg *unix.Msghdr, flags int) (n int, err error)

common/bufio/vectorised_windows.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ type syscallVectorisedWriterFields struct {
1515
}
1616

1717
func (w *SyscallVectorisedWriter) WriteVectorised(buffers []*buf.Buffer) error {
18-
w.access.Lock()
18+
/*w.access.Lock()
1919
defer w.access.Unlock()
2020
defer buf.ReleaseMulti(buffers)
2121
iovecList := w.iovecList
@@ -28,16 +28,15 @@ func (w *SyscallVectorisedWriter) WriteVectorised(buffers []*buf.Buffer) error {
2828
innerErr = windows.WSASend(windows.Handle(fd), &iovecList[0], uint32(len(iovecList)), &n, 0, nil, nil)
2929
return innerErr != windows.WSAEWOULDBLOCK
3030
})
31-
for i := range iovecList {
32-
iovecList[i] = windows.WSABuf{}
33-
}
31+
common.ClearArray(iovecList)
3432
if cap(iovecList) > cap(w.iovecList) {
3533
w.iovecList = w.iovecList[:0]
3634
}
3735
if innerErr != nil {
3836
err = innerErr
3937
}
40-
return err
38+
return err*/
39+
panic("not implemented")
4140
}
4241

4342
func (w *SyscallVectorisedPacketWriter) WriteVectorisedPacket(buffers []*buf.Buffer, destination M.Socksaddr) error {

0 commit comments

Comments
 (0)