@@ -5,11 +5,13 @@ package ping
55import (
66 "context"
77 "net/netip"
8+ "time"
89
910 "github.com/sagernet/gvisor/pkg/tcpip"
1011 "github.com/sagernet/gvisor/pkg/tcpip/adapters/gonet"
1112 "github.com/sagernet/gvisor/pkg/tcpip/header"
1213 "github.com/sagernet/gvisor/pkg/tcpip/stack"
14+ "github.com/sagernet/gvisor/pkg/tcpip/transport"
1315 "github.com/sagernet/gvisor/pkg/waiter"
1416 "github.com/sagernet/sing-tun"
1517 "github.com/sagernet/sing/common"
@@ -23,8 +25,10 @@ var _ tun.DirectRouteDestination = (*GVisorDestination)(nil)
2325type GVisorDestination struct {
2426 ctx context.Context
2527 logger logger.ContextLogger
28+ endpoint tcpip.Endpoint
2629 conn * gonet.TCPConn
2730 rewriter * Rewriter
31+ timeout time.Duration
2832}
2933
3034func ConnectGVisor (
@@ -33,6 +37,7 @@ func ConnectGVisor(
3337 routeContext tun.DirectRouteContext ,
3438 stack * stack.Stack ,
3539 bindAddress4 , bindAddress6 netip.Addr ,
40+ timeout time.Duration ,
3641) (* GVisorDestination , error ) {
3742 var (
3843 bindAddress tcpip.Address
@@ -76,16 +81,23 @@ func ConnectGVisor(
7681 destination := & GVisorDestination {
7782 ctx : ctx ,
7883 logger : logger ,
84+ endpoint : endpoint ,
7985 conn : gonet .NewTCPConn (& wq , endpoint ),
8086 rewriter : rewriter ,
87+ timeout : timeout ,
8188 }
8289 go destination .loopRead ()
8390 return destination , nil
8491}
8592
8693func (d * GVisorDestination ) loopRead () {
94+ defer d .endpoint .Close ()
8795 for {
8896 buffer := buf .NewPacket ()
97+ err := d .conn .SetReadDeadline (time .Now ().Add (d .timeout ))
98+ if err != nil {
99+ d .logger .ErrorContext (d .ctx , E .Cause (err , "set read deadline for ICMP conn" ))
100+ }
89101 n , err := d .conn .Read (buffer .FreeBytes ())
90102 if err != nil {
91103 buffer .Release ()
@@ -111,3 +123,7 @@ func (d *GVisorDestination) WritePacket(packet *buf.Buffer) error {
111123func (d * GVisorDestination ) Close () error {
112124 return d .conn .Close ()
113125}
126+
127+ func (d * GVisorDestination ) IsClosed () bool {
128+ return transport .DatagramEndpointState (d .endpoint .State ()) == transport .DatagramEndpointStateClosed
129+ }
0 commit comments