@@ -10,9 +10,9 @@ import {
10
10
CookieJar ,
11
11
createCookieJar ,
12
12
defaultBinaryType ,
13
+ nextTick ,
13
14
} from "./globals.node.js" ;
14
15
import debugModule from "debug" ; // debug()
15
- import { nextTick } from "./globals.js" ;
16
16
17
17
const debug = debugModule ( "engine.io-client:socket" ) ; // debug()
18
18
@@ -321,8 +321,11 @@ export class SocketWithoutUpgrade extends Emitter<
321
321
private _pingTimeout : number = - 1 ;
322
322
private _maxPayload ?: number = - 1 ;
323
323
private _pingTimeoutTimer : NodeJS . Timer ;
324
- private _pingTimeoutTime : number | null = null ;
325
- private _scheduledDisconnectFromIsResponsive = false ;
324
+ /**
325
+ * The expiration timestamp of the {@link _pingTimeoutTimer} object is tracked, in case the timer is throttled and the
326
+ * callback is not fired on time. This can happen for example when a laptop is suspended or when a phone is locked.
327
+ */
328
+ private _pingTimeoutTime = Infinity ;
326
329
private clearTimeoutFn : typeof clearTimeout ;
327
330
private readonly _beforeunloadEventListener : ( ) => void ;
328
331
private readonly _offlineEventListener : ( ) => void ;
@@ -577,7 +580,6 @@ export class SocketWithoutUpgrade extends Emitter<
577
580
578
581
// Socket is live - any packet counts
579
582
this . emitReserved ( "heartbeat" ) ;
580
- this . _resetPingTimeout ( ) ;
581
583
582
584
switch ( packet . type ) {
583
585
case "open" :
@@ -588,6 +590,7 @@ export class SocketWithoutUpgrade extends Emitter<
588
590
this . _sendPacket ( "pong" ) ;
589
591
this . emitReserved ( "ping" ) ;
590
592
this . emitReserved ( "pong" ) ;
593
+ this . _resetPingTimeout ( ) ;
591
594
break ;
592
595
593
596
case "error" :
@@ -633,8 +636,6 @@ export class SocketWithoutUpgrade extends Emitter<
633
636
*/
634
637
private _resetPingTimeout ( ) {
635
638
this . clearTimeoutFn ( this . _pingTimeoutTimer ) ;
636
- if ( this . _pingInterval <= 0 || this . _pingTimeout <= 0 ) return ;
637
-
638
639
const delay = this . _pingInterval + this . _pingTimeout ;
639
640
this . _pingTimeoutTime = Date . now ( ) + delay ;
640
641
this . _pingTimeoutTimer = this . setTimeoutFn ( ( ) => {
@@ -718,29 +719,28 @@ export class SocketWithoutUpgrade extends Emitter<
718
719
}
719
720
720
721
/**
721
- * Returns `true` if the connection is responding to heartbeats .
722
+ * Checks whether the heartbeat timer has expired but the socket has not yet been notified .
722
723
*
723
- * If heartbeats are disabled this will always return `true`.
724
+ * Note: this method is private for now because it does not really fit the WebSocket API, but if we put it in the
725
+ * `write()` method then the message would not be buffered by the Socket.IO client.
724
726
*
725
727
* @return {boolean }
728
+ * @private
726
729
*/
727
- public isResponsive ( ) {
728
- if ( this . readyState === "closed" ) return false ;
729
- if ( this . _pingTimeoutTime === null ) return true ;
730
+ /* private */ _hasPingExpired ( ) {
731
+ if ( ! this . _pingTimeoutTime ) return true ;
730
732
731
- const responsive = Date . now ( ) < this . _pingTimeoutTime ;
732
- if ( ! responsive && ! this . _scheduledDisconnectFromIsResponsive ) {
733
- debug (
734
- "`isResponsive` detected missed ping so scheduling connection close"
735
- ) ;
736
- this . _scheduledDisconnectFromIsResponsive = true ;
733
+ const hasExpired = Date . now ( ) > this . _pingTimeoutTime ;
734
+ if ( hasExpired ) {
735
+ debug ( "throttled timer detected, scheduling connection close" ) ;
736
+ this . _pingTimeoutTime = 0 ;
737
737
738
738
nextTick ( ( ) => {
739
739
this . _onClose ( "ping timeout" ) ;
740
740
} , this . setTimeoutFn ) ;
741
741
}
742
742
743
- return responsive ;
743
+ return hasExpired ;
744
744
}
745
745
746
746
/**
@@ -752,9 +752,6 @@ export class SocketWithoutUpgrade extends Emitter<
752
752
* @return {Socket } for chaining.
753
753
*/
754
754
public write ( msg : RawData , options ?: WriteOptions , fn ?: ( ) => void ) {
755
- // this will schedule a disconnection on next tick if heartbeat missed
756
- this . isResponsive ( ) ;
757
-
758
755
this . _sendPacket ( "message" , msg , options , fn ) ;
759
756
return this ;
760
757
}
@@ -768,7 +765,8 @@ export class SocketWithoutUpgrade extends Emitter<
768
765
* @return {Socket } for chaining.
769
766
*/
770
767
public send ( msg : RawData , options ?: WriteOptions , fn ?: ( ) => void ) {
771
- return this . write ( msg , options , fn ) ;
768
+ this . _sendPacket ( "message" , msg , options , fn ) ;
769
+ return this ;
772
770
}
773
771
774
772
/**
@@ -895,7 +893,6 @@ export class SocketWithoutUpgrade extends Emitter<
895
893
896
894
// clear timers
897
895
this . clearTimeoutFn ( this . _pingTimeoutTimer ) ;
898
- this . _pingTimeoutTime = null ;
899
896
900
897
// stop event from firing again for transport
901
898
this . transport . removeAllListeners ( "close" ) ;
0 commit comments