@@ -129,6 +129,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
129
129
this . client = new SignalClient ( ) ;
130
130
this . client . signalLatency = this . options . expSignalLatency ;
131
131
this . reconnectPolicy = this . options . reconnectPolicy ;
132
+ this . registerOnLineListener ( ) ;
132
133
}
133
134
134
135
async join (
@@ -174,8 +175,9 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
174
175
175
176
close ( ) {
176
177
this . _isClosed = true ;
177
-
178
178
this . removeAllListeners ( ) ;
179
+ this . deregisterOnLineListener ( ) ;
180
+ this . clearPendingReconnect ( ) ;
179
181
if ( this . publisher && this . publisher . pc . signalingState !== 'closed' ) {
180
182
this . publisher . pc . getSenders ( ) . forEach ( ( sender ) => {
181
183
try {
@@ -684,66 +686,74 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
684
686
if ( this . reconnectTimeout ) {
685
687
clearTimeout ( this . reconnectTimeout ) ;
686
688
}
687
- this . reconnectTimeout = setTimeout ( async ( ) => {
688
- if ( this . _isClosed ) {
689
- return ;
689
+ this . reconnectTimeout = setTimeout ( ( ) => this . attemptReconnect ( signalEvents ) , delay ) ;
690
+ } ;
691
+
692
+ private async attemptReconnect ( signalEvents : boolean = false ) {
693
+ if ( this . _isClosed ) {
694
+ return ;
695
+ }
696
+ // guard for attempting reconnection multiple times while one attempt is still not finished
697
+ if ( this . attemptingReconnect ) {
698
+ return ;
699
+ }
700
+ if (
701
+ this . clientConfiguration ?. resumeConnection === ClientConfigSetting . DISABLED ||
702
+ // signaling state could change to closed due to hardware sleep
703
+ // those connections cannot be resumed
704
+ ( this . primaryPC ?. signalingState ?? 'closed' ) === 'closed'
705
+ ) {
706
+ this . fullReconnectOnNext = true ;
707
+ }
708
+
709
+ try {
710
+ this . attemptingReconnect = true ;
711
+ if ( this . fullReconnectOnNext ) {
712
+ await this . restartConnection ( signalEvents ) ;
713
+ } else {
714
+ await this . resumeConnection ( signalEvents ) ;
690
715
}
691
- // guard for attempting reconnection multiple times while one attempt is still not finished
692
- if ( this . attemptingReconnect ) {
693
- return ;
716
+ this . reconnectAttempts = 0 ;
717
+ this . fullReconnectOnNext = false ;
718
+ if ( this . reconnectTimeout ) {
719
+ clearTimeout ( this . reconnectTimeout ) ;
694
720
}
695
- if (
696
- this . clientConfiguration ?. resumeConnection === ClientConfigSetting . DISABLED ||
697
- // signaling state could change to closed due to hardware sleep
698
- // those connections cannot be resumed
699
- ( this . primaryPC ?. signalingState ?? 'closed' ) === 'closed'
700
- ) {
701
- this . fullReconnectOnNext = true ;
721
+ } catch ( e ) {
722
+ this . reconnectAttempts += 1 ;
723
+ let reconnectRequired = false ;
724
+ let recoverable = true ;
725
+ let requireSignalEvents = false ;
726
+ if ( e instanceof UnexpectedConnectionState ) {
727
+ log . debug ( 'received unrecoverable error' , { error : e } ) ;
728
+ // unrecoverable
729
+ recoverable = false ;
730
+ } else if ( ! ( e instanceof SignalReconnectError ) ) {
731
+ // cannot resume
732
+ reconnectRequired = true ;
702
733
}
703
734
704
- try {
705
- this . attemptingReconnect = true ;
706
- if ( this . fullReconnectOnNext ) {
707
- await this . restartConnection ( signalEvents ) ;
708
- } else {
709
- await this . resumeConnection ( signalEvents ) ;
710
- }
711
- this . reconnectAttempts = 0 ;
712
- this . fullReconnectOnNext = false ;
713
- if ( this . reconnectTimeout ) {
714
- clearTimeout ( this . reconnectTimeout ) ;
715
- }
716
- } catch ( e ) {
717
- this . reconnectAttempts += 1 ;
718
- let reconnectRequired = false ;
719
- let recoverable = true ;
720
- let requireSignalEvents = false ;
721
- if ( e instanceof UnexpectedConnectionState ) {
722
- log . debug ( 'received unrecoverable error' , { error : e } ) ;
723
- // unrecoverable
724
- recoverable = false ;
725
- } else if ( ! ( e instanceof SignalReconnectError ) ) {
726
- // cannot resume
727
- reconnectRequired = true ;
728
- }
729
-
730
- // when we flip from resume to reconnect
731
- // we need to fire the right reconnecting events
732
- if ( reconnectRequired && ! this . fullReconnectOnNext ) {
733
- this . fullReconnectOnNext = true ;
734
- requireSignalEvents = true ;
735
- }
735
+ // when we flip from resume to reconnect
736
+ // we need to fire the right reconnecting events
737
+ if ( reconnectRequired && ! this . fullReconnectOnNext ) {
738
+ this . fullReconnectOnNext = true ;
739
+ requireSignalEvents = true ;
740
+ }
736
741
737
- if ( recoverable ) {
738
- this . handleDisconnect ( 'reconnect' , requireSignalEvents ) ;
739
- } else {
740
- disconnect ( Date . now ( ) - this . reconnectStart ) ;
741
- }
742
- } finally {
743
- this . attemptingReconnect = false ;
742
+ if ( recoverable ) {
743
+ this . handleDisconnect ( 'reconnect' , requireSignalEvents ) ;
744
+ } else {
745
+ log . info (
746
+ `could not recover connection after ${ this . reconnectAttempts } attempts, ${
747
+ Date . now ( ) - this . reconnectStart
748
+ } ms. giving up`,
749
+ ) ;
750
+ this . emit ( EngineEvent . Disconnected ) ;
751
+ this . close ( ) ;
744
752
}
745
- } , delay ) ;
746
- } ;
753
+ } finally {
754
+ this . attemptingReconnect = false ;
755
+ }
756
+ }
747
757
748
758
private getNextRetryDelay ( context : ReconnectContext ) {
749
759
try {
@@ -956,6 +966,35 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
956
966
}
957
967
}
958
968
}
969
+
970
+ private clearPendingReconnect ( ) {
971
+ if ( this . reconnectTimeout ) {
972
+ clearTimeout ( this . reconnectTimeout ) ;
973
+ }
974
+ this . reconnectAttempts = 0 ;
975
+ }
976
+
977
+ private handleBrowserOnLine = ( ) => {
978
+ // in case the engine is currently reconnecting, attempt a reconnect immediately after the browser state has changed to 'onLine'
979
+ if ( this . client . isReconnecting ) {
980
+ if ( this . reconnectTimeout ) {
981
+ clearTimeout ( this . reconnectTimeout ) ;
982
+ }
983
+ this . attemptReconnect ( true ) ;
984
+ }
985
+ } ;
986
+
987
+ private registerOnLineListener ( ) {
988
+ if ( isWeb ( ) ) {
989
+ window . addEventListener ( 'online' , this . handleBrowserOnLine ) ;
990
+ }
991
+ }
992
+
993
+ private deregisterOnLineListener ( ) {
994
+ if ( isWeb ( ) ) {
995
+ window . removeEventListener ( 'online' , this . handleBrowserOnLine ) ;
996
+ }
997
+ }
959
998
}
960
999
961
1000
async function getConnectedAddress ( pc : RTCPeerConnection ) : Promise < string | undefined > {
0 commit comments