From ff4941daa4bb1148d83c1957750df949b38d46e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Sun, 24 Aug 2025 18:59:55 +0800 Subject: [PATCH] Pass timeout to PrepareConnection --- route_direct.go | 7 ++++--- stack_gvisor_icmp.go | 6 ++++-- stack_gvisor_tcp.go | 2 +- stack_gvisor_udp.go | 2 +- stack_system.go | 8 +++++--- stack_system_nat.go | 2 +- tun.go | 9 ++++++++- 7 files changed, 24 insertions(+), 12 deletions(-) diff --git a/route_direct.go b/route_direct.go index 2279aa8..b043ab5 100644 --- a/route_direct.go +++ b/route_direct.go @@ -25,6 +25,7 @@ type DirectRouteSession struct { type DirectRouteMapping struct { mapping freelru.Cache[DirectRouteSession, DirectRouteDestination] + timeout time.Duration } func NewDirectRouteMapping(timeout time.Duration) *DirectRouteMapping { @@ -36,16 +37,16 @@ func NewDirectRouteMapping(timeout time.Duration) *DirectRouteMapping { action.Close() }) mapping.SetLifetime(timeout) - return &DirectRouteMapping{mapping} + return &DirectRouteMapping{mapping, timeout} } -func (m *DirectRouteMapping) Lookup(session DirectRouteSession, constructor func() (DirectRouteDestination, error)) (DirectRouteDestination, error) { +func (m *DirectRouteMapping) Lookup(session DirectRouteSession, constructor func(timeout time.Duration) (DirectRouteDestination, error)) (DirectRouteDestination, error) { var ( created DirectRouteDestination err error ) action, _, ok := m.mapping.GetAndRefreshOrAdd(session, func() (DirectRouteDestination, bool) { - created, err = constructor() + created, err = constructor(m.timeout) return created, err == nil }) if !ok { diff --git a/stack_gvisor_icmp.go b/stack_gvisor_icmp.go index 3a134a9..c2e369b 100644 --- a/stack_gvisor_icmp.go +++ b/stack_gvisor_icmp.go @@ -59,7 +59,7 @@ func (f *ICMPForwarder) HandlePacket(id stack.TransportEndpointID, pkt *stack.Pa sourceAddr := M.AddrFromIP(ipHdr.SourceAddressSlice()) destinationAddr := M.AddrFromIP(ipHdr.DestinationAddressSlice()) if destinationAddr != f.inet4Address { - action, err := f.mapping.Lookup(DirectRouteSession{Source: sourceAddr, Destination: destinationAddr}, func() (DirectRouteDestination, error) { + action, err := f.mapping.Lookup(DirectRouteSession{Source: sourceAddr, Destination: destinationAddr}, func(timeout time.Duration) (DirectRouteDestination, error) { return f.handler.PrepareConnection( N.NetworkICMPv4, M.SocksaddrFrom(sourceAddr, 0), @@ -70,6 +70,7 @@ func (f *ICMPForwarder) HandlePacket(id stack.TransportEndpointID, pkt *stack.Pa source: ipHdr.SourceAddress(), sourceNetwork: header.IPv4ProtocolNumber, }, + timeout, ) }) if err != nil { @@ -117,7 +118,7 @@ func (f *ICMPForwarder) HandlePacket(id stack.TransportEndpointID, pkt *stack.Pa sourceAddr := M.AddrFromIP(ipHdr.SourceAddressSlice()) destinationAddr := M.AddrFromIP(ipHdr.DestinationAddressSlice()) if destinationAddr != f.inet6Address { - action, err := f.mapping.Lookup(DirectRouteSession{Source: sourceAddr, Destination: destinationAddr}, func() (DirectRouteDestination, error) { + action, err := f.mapping.Lookup(DirectRouteSession{Source: sourceAddr, Destination: destinationAddr}, func(timeout time.Duration) (DirectRouteDestination, error) { return f.handler.PrepareConnection( N.NetworkICMPv6, M.SocksaddrFrom(sourceAddr, 0), @@ -128,6 +129,7 @@ func (f *ICMPForwarder) HandlePacket(id stack.TransportEndpointID, pkt *stack.Pa source: ipHdr.SourceAddress(), sourceNetwork: header.IPv6ProtocolNumber, }, + timeout, ) }) if err != nil { diff --git a/stack_gvisor_tcp.go b/stack_gvisor_tcp.go index 84bc3ff..1592799 100644 --- a/stack_gvisor_tcp.go +++ b/stack_gvisor_tcp.go @@ -79,7 +79,7 @@ func (f *TCPForwarder) HandlePacket(id stack.TransportEndpointID, pkt *stack.Pac func (f *TCPForwarder) Forward(r *tcp.ForwarderRequest) { source := M.SocksaddrFrom(AddrFromAddress(r.ID().RemoteAddress), r.ID().RemotePort) destination := M.SocksaddrFrom(AddrFromAddress(r.ID().LocalAddress), r.ID().LocalPort) - _, pErr := f.handler.PrepareConnection(N.NetworkTCP, source, destination, nil) + _, pErr := f.handler.PrepareConnection(N.NetworkTCP, source, destination, nil, 0) if pErr != nil { r.Complete(!errors.Is(pErr, ErrDrop)) return diff --git a/stack_gvisor_udp.go b/stack_gvisor_udp.go index db06b64..2e8ff3e 100644 --- a/stack_gvisor_udp.go +++ b/stack_gvisor_udp.go @@ -58,7 +58,7 @@ func (f *UDPForwarder) HandlePacket(id stack.TransportEndpointID, pkt *stack.Pac func rangeIterate(r stack.Range, fn func(*buffer.View)) func (f *UDPForwarder) PreparePacketConnection(source M.Socksaddr, destination M.Socksaddr, userData any) (bool, context.Context, N.PacketWriter, N.CloseHandlerFunc) { - _, pErr := f.handler.PrepareConnection(N.NetworkUDP, source, destination, nil) + _, pErr := f.handler.PrepareConnection(N.NetworkUDP, source, destination, nil, 0) if pErr != nil { if !errors.Is(pErr, ErrDrop) { gWriteUnreachable(f.stack, userData.(*stack.PacketBuffer)) diff --git a/stack_system.go b/stack_system.go index be8873a..5797fa9 100644 --- a/stack_system.go +++ b/stack_system.go @@ -609,7 +609,7 @@ func (s *System) processIPv6UDP(ipHdr header.IPv6, udpHdr header.UDP) error { } func (s *System) preparePacketConnection(source M.Socksaddr, destination M.Socksaddr, userData any) (bool, context.Context, N.PacketWriter, N.CloseHandlerFunc) { - _, pErr := s.handler.PrepareConnection(N.NetworkUDP, source, destination, nil) + _, pErr := s.handler.PrepareConnection(N.NetworkUDP, source, destination, nil, 0) if pErr != nil { if !errors.Is(pErr, ErrDrop) { if source.IsIPv4() { @@ -658,12 +658,13 @@ func (s *System) processIPv4ICMP(ipHdr header.IPv4, icmpHdr header.ICMPv4) (bool sourceAddr := ipHdr.SourceAddr() destinationAddr := ipHdr.DestinationAddr() if destinationAddr != s.inet4Address { - action, err := s.directNat.Lookup(DirectRouteSession{Source: sourceAddr, Destination: destinationAddr}, func() (DirectRouteDestination, error) { + action, err := s.directNat.Lookup(DirectRouteSession{Source: sourceAddr, Destination: destinationAddr}, func(timeout time.Duration) (DirectRouteDestination, error) { return s.handler.PrepareConnection( N.NetworkICMPv4, M.SocksaddrFrom(sourceAddr, 0), M.SocksaddrFrom(destinationAddr, 0), &systemICMPDirectPacketWriter4{s.tun, s.frontHeadroom + PacketOffset, sourceAddr}, + timeout, ) }) if err != nil { @@ -729,12 +730,13 @@ func (s *System) processIPv6ICMP(ipHdr header.IPv6, icmpHdr header.ICMPv6) (bool sourceAddr := ipHdr.SourceAddr() destinationAddr := ipHdr.DestinationAddr() if destinationAddr != s.inet6Address { - action, err := s.directNat.Lookup(DirectRouteSession{Source: sourceAddr, Destination: destinationAddr}, func() (DirectRouteDestination, error) { + action, err := s.directNat.Lookup(DirectRouteSession{Source: sourceAddr, Destination: destinationAddr}, func(timeout time.Duration) (DirectRouteDestination, error) { return s.handler.PrepareConnection( N.NetworkICMPv6, M.SocksaddrFrom(sourceAddr, 0), M.SocksaddrFrom(destinationAddr, 0), &systemICMPDirectPacketWriter6{s.tun, s.frontHeadroom + PacketOffset, sourceAddr}, + timeout, ) }) if err != nil { diff --git a/stack_system_nat.go b/stack_system_nat.go index 6b581bc..6a6d6b9 100644 --- a/stack_system_nat.go +++ b/stack_system_nat.go @@ -78,7 +78,7 @@ func (n *TCPNat) Lookup(source netip.AddrPort, destination netip.AddrPort, handl if loaded { return port, nil } - _, pErr := handler.PrepareConnection(N.NetworkTCP, M.SocksaddrFromNetIP(source), M.SocksaddrFromNetIP(destination), nil) + _, pErr := handler.PrepareConnection(N.NetworkTCP, M.SocksaddrFromNetIP(source), M.SocksaddrFromNetIP(destination), nil, 0) if pErr != nil { return 0, pErr } diff --git a/tun.go b/tun.go index 09497f7..d831742 100644 --- a/tun.go +++ b/tun.go @@ -7,6 +7,7 @@ import ( "runtime" "strconv" "strings" + "time" "github.com/sagernet/sing/common/buf" "github.com/sagernet/sing/common/control" @@ -18,7 +19,13 @@ import ( ) type Handler interface { - PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr, routeContext DirectRouteContext) (DirectRouteDestination, error) + PrepareConnection( + network string, + source M.Socksaddr, + destination M.Socksaddr, + routeContext DirectRouteContext, + timeout time.Duration, + ) (DirectRouteDestination, error) N.TCPConnectionHandlerEx N.UDPConnectionHandlerEx }