From cdf5e0c73e36fbb01d71b08c88a6d8f4998ce228 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Fri, 22 Aug 2025 11:27:32 +0800 Subject: [PATCH] chore: rewrite vision client write --- common/buf/sing.go | 1 + common/net/sing.go | 4 ++ transport/vless/vision/conn.go | 72 ++++++++++++------------------- transport/vless/vision/padding.go | 14 +++--- 4 files changed, 40 insertions(+), 51 deletions(-) diff --git a/common/buf/sing.go b/common/buf/sing.go index 59c650ad..73f65f15 100644 --- a/common/buf/sing.go +++ b/common/buf/sing.go @@ -14,6 +14,7 @@ var NewPacket = buf.NewPacket var NewSize = buf.NewSize var With = buf.With var As = buf.As +var ReleaseMulti = buf.ReleaseMulti var ( Must = common.Must diff --git a/common/net/sing.go b/common/net/sing.go index 2cd1d726..5cf97594 100644 --- a/common/net/sing.go +++ b/common/net/sing.go @@ -22,6 +22,10 @@ type ExtendedReader = network.ExtendedReader var WriteBuffer = bufio.WriteBuffer +type ReadWaitOptions = network.ReadWaitOptions + +var NewReadWaitOptions = network.NewReadWaitOptions + func NewDeadlineConn(conn net.Conn) ExtendedConn { if deadline.IsPipe(conn) || deadline.IsPipe(network.UnwrapReader(conn)) { return NewExtendedConn(conn) // pipe always have correctly deadline implement diff --git a/transport/vless/vision/conn.go b/transport/vless/vision/conn.go index b8367fb9..0c300e05 100644 --- a/transport/vless/vision/conn.go +++ b/transport/vless/vision/conn.go @@ -170,7 +170,7 @@ func (vc *Conn) WriteBuffer(buffer *buf.Buffer) (err error) { if vc.needHandshake { vc.needHandshake = false if buffer.IsEmpty() { - ApplyPadding(buffer, commandPaddingContinue, vc.userUUID, false) + ApplyPadding(buffer, commandPaddingContinue, vc.userUUID, true) // we do a long padding to hide vless header } else { vc.FilterTLS(buffer.Bytes()) ApplyPadding(buffer, commandPaddingContinue, vc.userUUID, vc.isTLS) @@ -190,55 +190,37 @@ func (vc *Conn) WriteBuffer(buffer *buf.Buffer) (err error) { } if vc.writeFilterApplicationData { - buffer2 := ReshapeBuffer(buffer) - defer buffer2.Release() vc.FilterTLS(buffer.Bytes()) - command := commandPaddingContinue - if !vc.isTLS { - command = commandPaddingEnd - - // disable XTLS - //vc.readProcess = false - vc.writeFilterApplicationData = false - vc.packetsToFilter = 0 - } else if buffer.Len() > 6 && bytes.Equal(buffer.To(3), tlsApplicationDataStart) || vc.packetsToFilter <= 0 { - command = commandPaddingEnd - if vc.enableXTLS { - command = commandPaddingDirect - vc.writeDirect = true - } - vc.writeFilterApplicationData = false - } - ApplyPadding(buffer, command, nil, vc.isTLS) - err = vc.ExtendedWriter.WriteBuffer(buffer) - if err != nil { - return err - } - if vc.writeDirect { - vc.ExtendedWriter = N.NewExtendedWriter(vc.netConn) - log.Debugln("XTLS Vision direct write start") - //time.Sleep(5 * time.Millisecond) - } - if buffer2 != nil { - if vc.writeDirect || !vc.isTLS { - return vc.ExtendedWriter.WriteBuffer(buffer2) - } - vc.FilterTLS(buffer2.Bytes()) - command = commandPaddingContinue - if buffer2.Len() > 6 && bytes.Equal(buffer2.To(3), tlsApplicationDataStart) || vc.packetsToFilter <= 0 { - command = commandPaddingEnd - if vc.enableXTLS { - command = commandPaddingDirect - vc.writeDirect = true + buffers := vc.ReshapeBuffer(buffer) + applyPadding := true + for i, buffer := range buffers { + command := commandPaddingContinue + if applyPadding { + if vc.isTLS && buffer.Len() > 6 && bytes.Equal(buffer.To(3), tlsApplicationDataStart) { + command = commandPaddingEnd + if vc.enableXTLS { + command = commandPaddingDirect + vc.writeDirect = true + } + vc.writeFilterApplicationData = false + applyPadding = false + } else if !vc.isTLS12orAbove && vc.packetsToFilter <= 1 { + command = commandPaddingEnd + vc.writeFilterApplicationData = false + applyPadding = false } - vc.writeFilterApplicationData = false + ApplyPadding(buffer, command, nil, vc.isTLS) } - ApplyPadding(buffer2, command, nil, vc.isTLS) - err = vc.ExtendedWriter.WriteBuffer(buffer2) - if vc.writeDirect { + + err = vc.ExtendedWriter.WriteBuffer(buffer) + if err != nil { + buf.ReleaseMulti(buffers[i:]) // release unwritten buffers + return + } + if command == commandPaddingDirect { vc.ExtendedWriter = N.NewExtendedWriter(vc.netConn) log.Debugln("XTLS Vision direct write start") - //time.Sleep(10 * time.Millisecond) + //time.Sleep(5 * time.Millisecond) } } return err diff --git a/transport/vless/vision/padding.go b/transport/vless/vision/padding.go index 8ffb40b3..710f64c2 100644 --- a/transport/vless/vision/padding.go +++ b/transport/vless/vision/padding.go @@ -6,6 +6,7 @@ import ( "github.com/metacubex/mihomo/common/buf" "github.com/metacubex/mihomo/log" + N "github.com/metacubex/sing/common/network" "github.com/gofrs/uuid/v5" "github.com/metacubex/randv2" @@ -42,16 +43,17 @@ func ApplyPadding(buffer *buf.Buffer, command byte, userUUID *uuid.UUID, padding log.Debugln("XTLS Vision write padding: command=%d, payloadLen=%d, paddingLen=%d", command, contentLen, paddingLen) } -func ReshapeBuffer(buffer *buf.Buffer) *buf.Buffer { - if buffer.Len() <= buf.BufferSize-PaddingHeaderLen { - return nil +func (vc *Conn) ReshapeBuffer(buffer *buf.Buffer) []*buf.Buffer { + const xrayBufSize = 8192 + if buffer.Len() <= xrayBufSize-PaddingHeaderLen { + return []*buf.Buffer{buffer} } cutAt := bytes.LastIndex(buffer.Bytes(), tlsApplicationDataStart) if cutAt == -1 { - cutAt = buf.BufferSize / 2 + cutAt = xrayBufSize / 2 } - buffer2 := buf.New() + buffer2 := N.NewReadWaitOptions(nil, vc).NewBuffer() // ensure the new buffer can send used in vc.WriteBuffer buffer2.Write(buffer.From(cutAt)) buffer.Truncate(cutAt) - return buffer2 + return []*buf.Buffer{buffer, buffer2} }