@electerm/ssh2 1.17.0 → 1.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/client.js +47 -7
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -362,6 +362,10 @@ class Client extends EventEmitter {
|
|
|
362
362
|
},
|
|
363
363
|
onHandshakeComplete: (negotiated) => {
|
|
364
364
|
this.emit('handshake', negotiated);
|
|
365
|
+
// Start keepalive monitoring after handshake
|
|
366
|
+
if (this.config.keepaliveInterval > 0) {
|
|
367
|
+
resetKA();
|
|
368
|
+
}
|
|
365
369
|
if (!ready) {
|
|
366
370
|
ready = true;
|
|
367
371
|
proto.service('ssh-userauth');
|
|
@@ -540,10 +544,14 @@ class Client extends EventEmitter {
|
|
|
540
544
|
}
|
|
541
545
|
},
|
|
542
546
|
REQUEST_SUCCESS: (p, data) => {
|
|
547
|
+
// Reset keepalive on any protocol activity
|
|
548
|
+
this._resetKA();
|
|
543
549
|
if (callbacks.length)
|
|
544
550
|
callbacks.shift()(false, data);
|
|
545
551
|
},
|
|
546
552
|
REQUEST_FAILURE: (p) => {
|
|
553
|
+
// Reset keepalive on any protocol activity
|
|
554
|
+
this._resetKA();
|
|
547
555
|
if (callbacks.length)
|
|
548
556
|
callbacks.shift()(true);
|
|
549
557
|
},
|
|
@@ -748,39 +756,71 @@ class Client extends EventEmitter {
|
|
|
748
756
|
|
|
749
757
|
sock.pause();
|
|
750
758
|
|
|
751
|
-
//
|
|
752
|
-
// Keepalive-related
|
|
759
|
+
// Enhanced keepalive implementation with TCP-level and SSH protocol-level keepalives
|
|
753
760
|
const kainterval = this.config.keepaliveInterval;
|
|
754
761
|
const kacountmax = this.config.keepaliveCountMax;
|
|
755
762
|
let kacount = 0;
|
|
756
763
|
let katimer;
|
|
764
|
+
let lastActivity = Date.now();
|
|
765
|
+
|
|
766
|
+
// Enable TCP keepalive for network-level connection monitoring
|
|
767
|
+
// This helps detect dead connections even when SSH protocol keepalive is not used
|
|
768
|
+
if (typeof sock.setKeepAlive === 'function') {
|
|
769
|
+
sock.setKeepAlive(true, 10000); // Start probing after 10 seconds idle
|
|
770
|
+
}
|
|
771
|
+
|
|
757
772
|
const sendKA = () => {
|
|
773
|
+
const now = Date.now();
|
|
774
|
+
const timeSinceLastActivity = now - lastActivity;
|
|
775
|
+
|
|
776
|
+
// If we've received any activity recently, reset counter and continue
|
|
777
|
+
if (timeSinceLastActivity < kainterval) {
|
|
778
|
+
kacount = 0;
|
|
779
|
+
return;
|
|
780
|
+
}
|
|
781
|
+
|
|
758
782
|
if (++kacount > kacountmax) {
|
|
759
783
|
clearInterval(katimer);
|
|
760
784
|
if (sock.readable) {
|
|
761
|
-
const err = new Error(
|
|
785
|
+
const err = new Error(
|
|
786
|
+
`Keepalive timeout: no response after ${kacountmax} attempts`
|
|
787
|
+
);
|
|
762
788
|
err.level = 'client-timeout';
|
|
763
789
|
this.emit('error', err);
|
|
764
790
|
sock.destroy();
|
|
765
791
|
}
|
|
766
792
|
return;
|
|
767
793
|
}
|
|
794
|
+
|
|
768
795
|
if (isWritable(sock)) {
|
|
769
|
-
|
|
770
|
-
|
|
796
|
+
if (debug) {
|
|
797
|
+
debug(
|
|
798
|
+
`Client: Sending keepalive (${kacount}/${kacountmax}), ` +
|
|
799
|
+
`${timeSinceLastActivity}ms since last activity`
|
|
800
|
+
);
|
|
801
|
+
}
|
|
802
|
+
// Send SSH protocol-level keepalive
|
|
803
|
+
// Use global request instead of relying on callbacks
|
|
771
804
|
proto.ping();
|
|
805
|
+
|
|
806
|
+
// Don't rely on callback - we'll reset based on any activity
|
|
772
807
|
} else {
|
|
773
808
|
clearInterval(katimer);
|
|
774
809
|
}
|
|
775
810
|
};
|
|
811
|
+
|
|
776
812
|
function resetKA() {
|
|
813
|
+
lastActivity = Date.now();
|
|
814
|
+
kacount = 0;
|
|
815
|
+
|
|
777
816
|
if (kainterval > 0) {
|
|
778
|
-
kacount = 0;
|
|
779
817
|
clearInterval(katimer);
|
|
780
|
-
if (isWritable(sock))
|
|
818
|
+
if (isWritable(sock)) {
|
|
781
819
|
katimer = setInterval(sendKA, kainterval);
|
|
820
|
+
}
|
|
782
821
|
}
|
|
783
822
|
}
|
|
823
|
+
|
|
784
824
|
this._resetKA = resetKA;
|
|
785
825
|
|
|
786
826
|
const onDone = (() => {
|
package/package.json
CHANGED