chore: rewrite vision client write

This commit is contained in:
wwqgtxx 2025-08-22 11:27:32 +08:00
parent 48f3ea8bc9
commit cdf5e0c73e
4 changed files with 40 additions and 51 deletions

View File

@ -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

View File

@ -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

View File

@ -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,56 +190,38 @@ func (vc *Conn) WriteBuffer(buffer *buf.Buffer) (err error) {
}
if vc.writeFilterApplicationData {
buffer2 := ReshapeBuffer(buffer)
defer buffer2.Release()
vc.FilterTLS(buffer.Bytes())
buffers := vc.ReshapeBuffer(buffer)
applyPadding := true
for i, buffer := range buffers {
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 {
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
}
ApplyPadding(buffer, command, nil, vc.isTLS)
}
err = vc.ExtendedWriter.WriteBuffer(buffer)
if err != nil {
return err
buf.ReleaseMulti(buffers[i:]) // release unwritten buffers
return
}
if vc.writeDirect {
if command == commandPaddingDirect {
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
}
vc.writeFilterApplicationData = false
}
ApplyPadding(buffer2, command, nil, vc.isTLS)
err = vc.ExtendedWriter.WriteBuffer(buffer2)
if vc.writeDirect {
vc.ExtendedWriter = N.NewExtendedWriter(vc.netConn)
log.Debugln("XTLS Vision direct write start")
//time.Sleep(10 * time.Millisecond)
}
}
return err
}

View File

@ -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}
}