package bufio import ( "errors" "io" "syscall" "github.com/sagernet/sing/common/buf" M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" ) func copyDirect(source syscall.Conn, destination syscall.Conn, readCounters []N.CountFunc, writeCounters []N.CountFunc) (handed bool, n int64, err error) { rawSource, err := source.SyscallConn() if err != nil { return } rawDestination, err := destination.SyscallConn() if err != nil { return } handed, n, err = splice(rawSource, rawDestination, readCounters, writeCounters) return } func copyWaitWithPool(originSource io.Reader, destination N.ExtendedWriter, source N.ReadWaiter, readCounters []N.CountFunc, writeCounters []N.CountFunc) (handled bool, n int64, err error) { handled = true var ( buffer *buf.Buffer notFirstTime bool ) for { buffer, err = source.WaitReadBuffer() if err != nil { if errors.Is(err, io.EOF) { err = nil return } return } dataLen := buffer.Len() err = destination.WriteBuffer(buffer) if err != nil { buffer.Leak() if !notFirstTime { err = N.ReportHandshakeFailure(originSource, err) } return } n += int64(dataLen) for _, counter := range readCounters { counter(int64(dataLen)) } for _, counter := range writeCounters { counter(int64(dataLen)) } notFirstTime = true } } func copyPacketWaitWithPool(originSource N.PacketReader, destinationConn N.PacketWriter, source N.PacketReadWaiter, readCounters []N.CountFunc, writeCounters []N.CountFunc, notFirstTime bool) (handled bool, n int64, err error) { handled = true var ( buffer *buf.Buffer destination M.Socksaddr ) for { buffer, destination, err = source.WaitReadPacket() if err != nil { return } dataLen := buffer.Len() err = destinationConn.WritePacket(buffer, destination) if err != nil { buffer.Leak() if !notFirstTime { err = N.ReportHandshakeFailure(originSource, err) } return } n += int64(dataLen) for _, counter := range readCounters { counter(int64(dataLen)) } for _, counter := range writeCounters { counter(int64(dataLen)) } notFirstTime = true } }