diff --git a/proxy/tun/handler.go b/proxy/tun/handler.go index 760d872e752c..d4c6a841c007 100644 --- a/proxy/tun/handler.go +++ b/proxy/tun/handler.go @@ -2,6 +2,7 @@ package tun import ( "context" + "time" "github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common/buf" @@ -10,10 +11,10 @@ import ( "github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/session" + "github.com/xtls/xray-core/common/task" "github.com/xtls/xray-core/core" "github.com/xtls/xray-core/features/policy" "github.com/xtls/xray-core/features/routing" - "github.com/xtls/xray-core/transport" "github.com/xtls/xray-core/transport/internet/stat" ) @@ -106,18 +107,40 @@ func (t *Handler) HandleConnection(conn net.Conn, destination net.Destination) { ctx = session.ContextWithInbound(ctx, &inbound) ctx = session.SubContextFromMuxInbound(ctx) - link := &transport.Link{ - Reader: &buf.TimeoutWrapperReader{Reader: buf.NewReader(conn)}, - Writer: buf.NewWriter(conn), + link, err := t.dispatcher.Dispatch(ctx, destination) + if err != nil { + errors.LogError(ctx, errors.New("connection failed").Base(err)) + _ = conn.Close() + return + } + + timer := &deadlineTimer{conn: conn, timeouts: t.policy().Timeouts} + requestFunc := func() error { + return buf.Copy(link.Reader, buf.NewWriter(conn), buf.UpdateActivity(timer)) + } + responseFunc := func() error { + return buf.Copy(buf.NewReader(conn), link.Writer, buf.UpdateActivity(timer)) } - if err := t.dispatcher.DispatchLink(ctx, destination, link); err != nil { - errors.LogError(ctx, errors.New("connection closed").Base(err)) + responseDonePost := task.OnSuccess(responseFunc, task.Close(link.Writer)) + if err := task.Run(ctx, requestFunc, responseDonePost); err != nil { + _ = common.Interrupt(link.Reader) + _ = common.Interrupt(link.Writer) + errors.LogInfo(ctx, errors.New("connection closed").Base(err)) return } errors.LogInfo(ctx, "connection completed") } +type deadlineTimer struct { + conn net.Conn + timeouts policy.Timeout +} + +func (a *deadlineTimer) Update() { + a.conn.SetDeadline(time.Now().Add(a.timeouts.ConnectionIdle)) +} + // Network implements proxy.Inbound // and exists only to comply to proxy interface, declaring it doesn't listen on any network, // making the process not open any port for this inbound (input will be network interface)