@ -8,9 +8,7 @@ import (
"crypto/rand"
"io"
"math/big"
"runtime"
"strconv"
"syscall"
"time"
"github.com/xtls/xray-core/common/buf"
@ -20,10 +18,8 @@ import (
"github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/common/signal"
"github.com/xtls/xray-core/features/stats"
"github.com/xtls/xray-core/proxy"
"github.com/xtls/xray-core/proxy/vless"
"github.com/xtls/xray-core/transport/internet/reality"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/transport/internet/tls"
)
const (
@ -206,13 +202,11 @@ func DecodeResponseHeader(reader io.Reader, request *protocol.RequestHeader) (*A
}
// XtlsRead filter and read xtls protocol
func XtlsRead ( reader buf . Reader , writer buf . Writer , timer signal . ActivityUpdater , conn net . Conn , rawConn syscall . RawConn ,
input * bytes . Reader , rawInput * bytes . Buffer ,
counter stats . Counter , ctx context . Context , userUUID [ ] byte , numberOfPacketToFilter * int , enableXtls * bool ,
func XtlsRead ( reader buf . Reader , writer buf . Writer , timer signal . ActivityUpdater , conn net . Conn , input * bytes . Reader , rawInput * bytes . Buffer ,
ctx context . Context , userUUID [ ] byte , numberOfPacketToFilter * int , enableXtls * bool ,
isTLS12orAbove * bool , isTLS * bool , cipher * uint16 , remainingServerHello * int32 ,
) error {
err := func ( ) error {
var ct stats . Counter
withinPaddingBuffers := true
shouldSwitchToDirectCopy := false
var remainingContent int32 = - 1
@ -220,40 +214,14 @@ func XtlsRead(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater
currentCommand := 0
for {
if shouldSwitchToDirectCopy {
shouldSwitchToDirectCopy = false
if inbound := session . InboundFromContext ( ctx ) ; inbound != nil && inbound . Conn != nil && ( runtime . GOOS == "linux" || runtime . GOOS == "android" ) {
if _ , ok := inbound . User . Account . ( * vless . MemoryAccount ) ; inbound . User . Account == nil || ok {
iConn := inbound . Conn
statConn , ok := iConn . ( * stat . CounterConnection )
if ok {
iConn = statConn . Connection
}
if tlsConn , ok := iConn . ( * tls . Conn ) ; ok {
iConn = tlsConn . NetConn ( )
} else if realityConn , ok := iConn . ( * reality . Conn ) ; ok {
iConn = realityConn . NetConn ( )
}
if tc , ok := iConn . ( * net . TCPConn ) ; ok {
newError ( "XtlsRead splice" ) . WriteToLog ( session . ExportIDToError ( ctx ) )
runtime . Gosched ( ) // necessary
w , err := tc . ReadFrom ( conn )
if counter != nil {
counter . Add ( w )
}
if statConn != nil && statConn . WriteCounter != nil {
statConn . WriteCounter . Add ( w )
}
return err
}
var writerConn net . Conn
if inbound := session . InboundFromContext ( ctx ) ; inbound != nil && inbound . Conn != nil {
writerConn = inbound . Conn
if inbound . CanSpliceCopy == 2 {
inbound . CanSpliceCopy = 1 // force the value to 1, don't use setter
}
}
if rawConn != nil {
reader = buf . NewReadVReader ( conn , rawConn , nil )
} else {
reader = buf . NewReader ( conn )
}
ct = counter
newError ( "XtlsRead readV" ) . WriteToLog ( session . ExportIDToError ( ctx ) )
return proxy . CopyRawConnIfExist ( ctx , conn , writerConn , writer , timer )
}
buffer , err := reader . ReadMultiBuffer ( )
if ! buffer . IsEmpty ( ) {
@ -292,9 +260,6 @@ func XtlsRead(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater
if * numberOfPacketToFilter > 0 {
XtlsFilterTls ( buffer , numberOfPacketToFilter , enableXtls , isTLS12orAbove , isTLS , cipher , remainingServerHello , ctx )
}
if ct != nil {
ct . Add ( int64 ( buffer . Len ( ) ) )
}
timer . Update ( )
if werr := writer . WriteMultiBuffer ( buffer ) ; werr != nil {
return werr
@ -312,7 +277,7 @@ func XtlsRead(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater
}
// XtlsWrite filter and write xtls protocol
func XtlsWrite ( reader buf . Reader , writer buf . Writer , timer signal . ActivityUpdater , conn net . Conn , counter stats . Counter ,
func XtlsWrite ( reader buf . Reader , writer buf . Writer , timer signal . ActivityUpdater , conn net . Conn ,
ctx context . Context , numberOfPacketToFilter * int , enableXtls * bool , isTLS12orAbove * bool , isTLS * bool ,
cipher * uint16 , remainingServerHello * int32 ,
) error {
@ -349,18 +314,21 @@ func XtlsWrite(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdate
}
if shouldSwitchToDirectCopy {
encryptBuffer , directBuffer := buf . SplitMulti ( buffer , xtlsSpecIndex + 1 )
length := encryptBuffer . Len ( )
if ! encryptBuffer . IsEmpty ( ) {
timer . Update ( )
if werr := writer . WriteMultiBuffer ( encryptBuffer ) ; werr != nil {
return werr
}
}
buffer = directBuffer
writer = buf . NewWriter ( conn )
ct = counter
newError ( "XtlsWrite writeV " , xtlsSpecIndex , " " , length , " " , buffer . Len ( ) ) . WriteToLog ( session . ExportIDToError ( ctx ) )
time . Sleep ( 5 * time . Millisecond ) // for some device, the first xtls direct packet fails without this delay
if inbound := session . InboundFromContext ( ctx ) ; inbound != nil && inbound . CanSpliceCopy == 2 {
inbound . CanSpliceCopy = 1 // force the value to 1, don't use setter
}
buffer = directBuffer
rawConn , _ , writerCounter := proxy . UnwrapRawConn ( conn )
writer = buf . NewWriter ( rawConn )
ct = writerCounter
}
}
if ! buffer . IsEmpty ( ) {