mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-01-12 13:55:37 +08:00
Fix Vision by processing rawInput before input when switching to direct mode
Per RPRX's feedback, the original code logic was correct, but the processing order matters. When switching to direct copy mode, rawInput (encrypted TLS records from the outer layer) should be processed and merged into the buffer before input (decrypted application data). This ensures proper ordering of data when transitioning from Vision-padded mode to direct copy mode, preventing SSL errors especially with testpre connections. Fixes #4878 Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
This commit is contained in:
@@ -256,26 +256,18 @@ func (w *VisionReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
||||
}
|
||||
|
||||
if *switchToDirectCopy {
|
||||
// Before switching to direct copy, ensure current buffer contains complete TLS records
|
||||
// This prevents corruption when switching mid-record, especially with testpre connections
|
||||
if !buffer.IsEmpty() && w.trafficState.IsTLS && !IsCompleteRecord(buffer) {
|
||||
// Buffer contains incomplete TLS records, cannot safely switch yet
|
||||
// Return the buffer and the switch will be attempted on the next read
|
||||
errors.LogDebug(w.ctx, "Vision: incomplete TLS records in buffer, delaying direct copy switch, len=", buffer.Len())
|
||||
return buffer, err
|
||||
}
|
||||
|
||||
// XTLS Vision processes TLS-like conn's input and rawInput
|
||||
if w.input != nil {
|
||||
if inputBuffer, err := buf.ReadFrom(w.input); err == nil && !inputBuffer.IsEmpty() {
|
||||
buffer, _ = buf.MergeMulti(buffer, inputBuffer)
|
||||
}
|
||||
}
|
||||
// Process rawInput first, then input, then current buffer
|
||||
if w.rawInput != nil {
|
||||
if rawInputBuffer, err := buf.ReadFrom(w.rawInput); err == nil && !rawInputBuffer.IsEmpty() {
|
||||
buffer, _ = buf.MergeMulti(buffer, rawInputBuffer)
|
||||
}
|
||||
}
|
||||
if w.input != nil {
|
||||
if inputBuffer, err := buf.ReadFrom(w.input); err == nil && !inputBuffer.IsEmpty() {
|
||||
buffer, _ = buf.MergeMulti(buffer, inputBuffer)
|
||||
}
|
||||
}
|
||||
if w.input != nil {
|
||||
*w.input = bytes.Reader{} // release memory
|
||||
w.input = nil
|
||||
|
||||
Reference in New Issue
Block a user