From 95c960977b7d72797fa811727e84e0e67347cb88 Mon Sep 17 00:00:00 2001 From: Meo597 <197331664+Meo597@users.noreply.github.com> Date: Wed, 8 Jul 2026 22:44:16 +0800 Subject: [PATCH] Revert "refactor (remove TimeoutOnly)" This reverts commit 723ef2b8e69ce120acadf3d3881bcfe51f629509. --- common/mux/server.go | 2 +- common/session/context.go | 37 ++++++++++++++++++++---------- proxy/dns/dns.go | 4 ++++ proxy/freedom/freedom.go | 4 ++++ proxy/http/client.go | 4 ++++ proxy/hysteria/client.go | 4 ++++ proxy/shadowsocks/client.go | 4 ++++ proxy/shadowsocks_2022/outbound.go | 4 ++++ proxy/socks/client.go | 4 ++++ proxy/trojan/client.go | 4 ++++ proxy/vless/outbound/outbound.go | 4 ++++ proxy/vmess/outbound/outbound.go | 4 ++++ proxy/wireguard/client.go | 4 ++++ transport/internet/grpc/dial.go | 2 +- 14 files changed, 71 insertions(+), 14 deletions(-) diff --git a/common/mux/server.go b/common/mux/server.go index 0cf5851cf..d1cdac113 100644 --- a/common/mux/server.go +++ b/common/mux/server.go @@ -227,7 +227,7 @@ func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata, errors.LogInfoInner(ctx, err, "XUDP hit ", meta.GlobalID) } if mb != nil { - ctx = context.WithoutCancel(ctx) + ctx = session.ContextWithTimeoutOnly(ctx, true) // Actually, it won't return an error in Xray-core's implementations. link, err := w.dispatcher.Dispatch(ctx, meta.Target) if err != nil { diff --git a/common/session/context.go b/common/session/context.go index 5605980d7..df445ab55 100644 --- a/common/session/context.go +++ b/common/session/context.go @@ -11,18 +11,20 @@ import ( ) const ( - inboundSessionKey ctx.SessionKey = iota - outboundSessionKey - contentSessionKey - isReverseMuxKey // is reverse mux - sockoptSessionKey // used by dokodemo to only receive sockopt.Mark - trackedConnectionErrorKey // used by observer to get outbound error - dispatcherKey // used by ss2022 inbounds to get dispatcher - allowedNetworkKey // muxcool server control incoming request tcp/udp - fullHandlerKey // outbound gets full handler - mitmAlpn11Key // used by TLS dialer - mitmServerNameKey // used by TLS dialer - streamSettingsKey + inboundSessionKey ctx.SessionKey = 1 + outboundSessionKey ctx.SessionKey = 2 + contentSessionKey ctx.SessionKey = 3 + isReverseMuxKey ctx.SessionKey = 4 // is reverse mux + sockoptSessionKey ctx.SessionKey = 5 // used by dokodemo to only receive sockopt.Mark + trackedConnectionErrorKey ctx.SessionKey = 6 // used by observer to get outbound error + dispatcherKey ctx.SessionKey = 7 // used by ss2022 inbounds to get dispatcher + timeoutOnlyKey ctx.SessionKey = 8 // mux context's child contexts to only cancel when its own traffic times out + allowedNetworkKey ctx.SessionKey = 9 // muxcool server control incoming request tcp/udp + fullHandlerKey ctx.SessionKey = 10 // outbound gets full handler + mitmAlpn11Key ctx.SessionKey = 11 // used by TLS dialer + mitmServerNameKey ctx.SessionKey = 12 // used by TLS dialer + + streamSettingsKey ctx.SessionKey = 13 ) func ContextWithInbound(ctx context.Context, inbound *Inbound) context.Context { @@ -135,6 +137,17 @@ func DispatcherFromContext(ctx context.Context) routing.Dispatcher { return nil } +func ContextWithTimeoutOnly(ctx context.Context, only bool) context.Context { + return context.WithValue(ctx, timeoutOnlyKey, only) +} + +func TimeoutOnlyFromContext(ctx context.Context) bool { + if val, ok := ctx.Value(timeoutOnlyKey).(bool); ok { + return val + } + return false +} + func ContextWithAllowedNetwork(ctx context.Context, network net.Network) context.Context { return context.WithValue(ctx, allowedNetworkKey, network) } diff --git a/proxy/dns/dns.go b/proxy/dns/dns.go index 852af3d80..079ac750d 100644 --- a/proxy/dns/dns.go +++ b/proxy/dns/dns.go @@ -214,6 +214,10 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, d internet. } } + if session.TimeoutOnlyFromContext(ctx) { + ctx = context.WithoutCancel(ctx) + } + ctx, cancel := context.WithCancel(ctx) terminate := func() { cancel() diff --git a/proxy/freedom/freedom.go b/proxy/freedom/freedom.go index e5f09aa7e..4b94af5a0 100644 --- a/proxy/freedom/freedom.go +++ b/proxy/freedom/freedom.go @@ -388,6 +388,10 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte defer conn.Close() errors.LogInfo(ctx, "connection opened to ", destination, ", local endpoint ", conn.LocalAddr(), ", remote endpoint ", conn.RemoteAddr()) + if session.TimeoutOnlyFromContext(ctx) { + ctx = context.WithoutCancel(ctx) + } + plcy := h.policy() ctx, cancel := context.WithCancel(ctx) timer := signal.CancelAfterInactivity(ctx, cancel, plcy.Timeouts.ConnectionIdle) diff --git a/proxy/http/client.go b/proxy/http/client.go index 7de166e93..540286e17 100644 --- a/proxy/http/client.go +++ b/proxy/http/client.go @@ -127,6 +127,10 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter p = c.policyManager.ForLevel(user.Level) } + if session.TimeoutOnlyFromContext(ctx) { + ctx = context.WithoutCancel(ctx) + } + ctx, cancel := context.WithCancel(ctx) timer := signal.CancelAfterInactivity(ctx, cancel, p.Timeouts.ConnectionIdle) diff --git a/proxy/hysteria/client.go b/proxy/hysteria/client.go index efe5e2277..8d5634bc1 100644 --- a/proxy/hysteria/client.go +++ b/proxy/hysteria/client.go @@ -67,6 +67,10 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter defer conn.Close() errors.LogInfo(ctx, "tunneling request to ", target, " via ", target.Network, ":", c.server.Destination.NetAddr()) + if session.TimeoutOnlyFromContext(ctx) { + ctx = context.WithoutCancel(ctx) + } + sessionPolicy := c.policyManager.ForLevel(0) ctx, cancel := context.WithCancel(ctx) timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle) diff --git a/proxy/shadowsocks/client.go b/proxy/shadowsocks/client.go index 672fbfb72..075b56824 100644 --- a/proxy/shadowsocks/client.go +++ b/proxy/shadowsocks/client.go @@ -95,6 +95,10 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter } request.User = user + if session.TimeoutOnlyFromContext(ctx) { + ctx = context.WithoutCancel(ctx) + } + sessionPolicy := c.policyManager.ForLevel(user.Level) ctx, cancel := context.WithCancel(ctx) timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle) diff --git a/proxy/shadowsocks_2022/outbound.go b/proxy/shadowsocks_2022/outbound.go index af1c3c367..dd4efce55 100644 --- a/proxy/shadowsocks_2022/outbound.go +++ b/proxy/shadowsocks_2022/outbound.go @@ -83,6 +83,10 @@ func (o *Outbound) Process(ctx context.Context, link *transport.Link, dialer int return errors.New("failed to connect to server").Base(err) } + if session.TimeoutOnlyFromContext(ctx) { + ctx = context.WithoutCancel(ctx) + } + if network == net.Network_TCP { serverConn := o.method.DialEarlyConn(connection, singbridge.ToSocksaddr(destination)) var handshake bool diff --git a/proxy/socks/client.go b/proxy/socks/client.go index c60d10d8a..e74776508 100644 --- a/proxy/socks/client.go +++ b/proxy/socks/client.go @@ -117,6 +117,10 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter errors.LogInfoInner(ctx, err, "failed to clear deadline after handshake") } + if session.TimeoutOnlyFromContext(ctx) { + ctx = context.WithoutCancel(ctx) + } + ctx, cancel := context.WithCancel(ctx) timer := signal.CancelAfterInactivity(ctx, cancel, p.Timeouts.ConnectionIdle) diff --git a/proxy/trojan/client.go b/proxy/trojan/client.go index 6176441fc..0cd450ad5 100644 --- a/proxy/trojan/client.go +++ b/proxy/trojan/client.go @@ -81,6 +81,10 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter return errors.New("user account is not valid") } + if session.TimeoutOnlyFromContext(ctx) { + ctx = context.WithoutCancel(ctx) + } + sessionPolicy := c.policyManager.ForLevel(user.Level) ctx, cancel := context.WithCancel(ctx) timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle) diff --git a/proxy/vless/outbound/outbound.go b/proxy/vless/outbound/outbound.go index 30c9576d1..3103b2eb6 100644 --- a/proxy/vless/outbound/outbound.go +++ b/proxy/vless/outbound/outbound.go @@ -294,6 +294,10 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte ob.CanSpliceCopy = 3 } + if session.TimeoutOnlyFromContext(ctx) { + ctx = context.WithoutCancel(ctx) + } + sessionPolicy := h.policyManager.ForLevel(request.User.Level) ctx, cancel := context.WithCancel(ctx) timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle) diff --git a/proxy/vmess/outbound/outbound.go b/proxy/vmess/outbound/outbound.go index 7681dce4d..65ec65ac6 100644 --- a/proxy/vmess/outbound/outbound.go +++ b/proxy/vmess/outbound/outbound.go @@ -131,6 +131,10 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte behaviorSeed := crc64.Checksum(hashkdf.Sum(nil), crc64.MakeTable(crc64.ISO)) + if session.TimeoutOnlyFromContext(ctx) { + ctx = context.WithoutCancel(ctx) + } + session := encoding.NewClientSession(ctx, int64(behaviorSeed)) sessionPolicy := h.policyManager.ForLevel(request.User.Level) diff --git a/proxy/wireguard/client.go b/proxy/wireguard/client.go index 60dc97102..efcb4a9df 100644 --- a/proxy/wireguard/client.go +++ b/proxy/wireguard/client.go @@ -165,6 +165,10 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte return errors.New("invalid target ", ob.Target) } + if session.TimeoutOnlyFromContext(ctx) { + ctx = context.WithoutCancel(ctx) + } + sessionPolicy := h.policyManager.ForLevel(0) ctx, cancel := context.WithCancel(ctx) timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle) diff --git a/transport/internet/grpc/dial.go b/transport/internet/grpc/dial.go index da8b64996..4883f30ab 100644 --- a/transport/internet/grpc/dial.go +++ b/transport/internet/grpc/dial.go @@ -122,7 +122,7 @@ func getGrpcClient(ctx context.Context, dest net.Destination, streamSettings *in gctx = c.ContextWithID(gctx, c.IDFromContext(ctx)) gctx = session.ContextWithOutbounds(gctx, session.OutboundsFromContext(ctx)) - gctx = context.WithoutCancel(gctx) + gctx = session.ContextWithTimeoutOnly(gctx, true) c, err := internet.DialSystem(gctx, net.TCPDestination(address, port), sockopt) if err == nil {