@@ -166,18 +166,44 @@ func (t *Tunnel) BindRemotes(ctx context.Context, remotes []*settings.Remote) er
166
166
}
167
167
168
168
func (t * Tunnel ) keepAliveLoop (sshConn ssh.Conn ) {
169
- //ping forever
169
+ // ping forever with a timeout
170
+ PingCheckOLoop:
170
171
for {
171
172
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
179
205
}
180
206
}
181
- //close ssh connection on abnormal ping
207
+ // Close the SSH connection on abnormal ping
182
208
sshConn .Close ()
183
209
}
0 commit comments