Skip to content

Commit dd3b19b

Browse files
committed
Modify keepAliveLoop to async for enabling timeout on no-response ping
jpillora#488
1 parent dfba2dd commit dd3b19b

File tree

1 file changed

+35
-9
lines changed

1 file changed

+35
-9
lines changed

share/tunnel/tunnel.go

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -166,18 +166,44 @@ func (t *Tunnel) BindRemotes(ctx context.Context, remotes []*settings.Remote) er
166166
}
167167

168168
func (t *Tunnel) keepAliveLoop(sshConn ssh.Conn) {
169-
//ping forever
169+
// ping forever with a timeout
170+
PingCheckOLoop:
170171
for {
171172
time.Sleep(t.Config.KeepAlive)
172-
_, b, err := sshConn.SendRequest("ping", true, nil)
173-
if err != nil {
174-
break
175-
}
176-
if len(b) > 0 && !bytes.Equal(b, []byte("pong")) {
177-
t.Debugf("strange ping response")
178-
break
173+
174+
ctx, cancel := context.WithTimeout(context.Background(), t.Config.KeepAlive)
175+
defer cancel()
176+
177+
responseCh := make(chan []byte, 1)
178+
errCh := make(chan error, 1)
179+
180+
// Asynchronously send a 'ping' request via SSH
181+
go func() {
182+
_, b, err := sshConn.SendRequest("ping", true, nil)
183+
if err != nil {
184+
errCh <- err
185+
return
186+
}
187+
responseCh <- b
188+
}()
189+
190+
// Wait for a response, error, or timeout from the asynchronous 'ping' request
191+
select {
192+
case response := <-responseCh:
193+
if len(response) > 0 && !bytes.Equal(response, []byte("pong")) {
194+
t.Debugf("Unexpected ping response: %s", response)
195+
break PingCheckOLoop
196+
}
197+
case err := <-errCh:
198+
if err != nil {
199+
t.Debugf("Failed to send ping: %s", err)
200+
break PingCheckOLoop
201+
}
202+
case <-ctx.Done():
203+
t.Debugf("Ping timed out")
204+
break PingCheckOLoop
179205
}
180206
}
181-
//close ssh connection on abnormal ping
207+
// Close the SSH connection on abnormal ping
182208
sshConn.Close()
183209
}

0 commit comments

Comments
 (0)