@@ -166,18 +166,44 @@ func (t *Tunnel) BindRemotes(ctx context.Context, remotes []*settings.Remote) er
166166}
167167
168168func (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