Skip to content

Commit efbc00c

Browse files
committed
fix(connectivity) Force restart client after 3 failed ICE restarts
1 parent 2a5d7fc commit efbc00c

File tree

5 files changed

+43
-8
lines changed

5 files changed

+43
-8
lines changed

JitsiConference.js

+14-1
Original file line numberDiff line numberDiff line change
@@ -54,18 +54,21 @@ import RTCEvents from './service/RTC/RTCEvents';
5454
import { SignalingEvents } from './service/RTC/SignalingEvents';
5555
import { getMediaTypeFromSourceName, getSourceNameForJitsiTrack } from './service/RTC/SignalingLayer';
5656
import { VideoType } from './service/RTC/VideoType';
57+
import { MAX_CONNECTION_RETRIES } from './service/connectivity/Constants';
5758
import {
5859
ACTION_JINGLE_RESTART,
5960
ACTION_JINGLE_SI_RECEIVED,
6061
ACTION_JINGLE_SI_TIMEOUT,
6162
ACTION_JINGLE_TERMINATE,
63+
ACTION_JVB_ICE_FAILED,
6264
ACTION_P2P_DECLINED,
6365
ACTION_P2P_ESTABLISHED,
6466
ACTION_P2P_FAILED,
6567
ACTION_P2P_SWITCH_TO_JVB,
6668
ICE_ESTABLISHMENT_DURATION_DIFF,
6769
createConferenceEvent,
6870
createJingleEvent,
71+
createJvbIceFailedEvent,
6972
createP2PEvent
7073
} from './service/statistics/AnalyticsEvents';
7174
import { XMPPEvents } from './service/xmpp/XMPPEvents';
@@ -2917,7 +2920,7 @@ JitsiConference.prototype._onIceConnectionFailed = function(session) {
29172920
reason: 'connectivity-error',
29182921
reasonDescription: 'ICE FAILED'
29192922
});
2920-
} else if (session && this.jvbJingleSession === session) {
2923+
} else if (session && this.jvbJingleSession === session && this._iceRestarts < MAX_CONNECTION_RETRIES) {
29212924
// Use an exponential backoff timer for ICE restarts.
29222925
const jitterDelay = getJitterDelay(this._iceRestarts, 1000 /* min. delay */);
29232926

@@ -2927,6 +2930,16 @@ JitsiConference.prototype._onIceConnectionFailed = function(session) {
29272930
this._delayedIceFailed.start(session);
29282931
this._iceRestarts++;
29292932
}, jitterDelay);
2933+
} else if (this.jvbJingleSession === session) {
2934+
logger.warn('ICE failed, force reloading the conference after failed attempts to re-establish ICE');
2935+
Statistics.sendAnalyticsAndLog(
2936+
createJvbIceFailedEvent(
2937+
ACTION_JVB_ICE_FAILED,
2938+
{
2939+
participantId: this.myUserId(),
2940+
userRegion: this.options.config.deploymentInfo?.userRegion
2941+
}));
2942+
this.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.ICE_FAILED);
29302943
}
29312944
};
29322945

modules/xmpp/XmppConnection.js

+3-7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { getLogger } from '@jitsi/logger';
22
import { $pres, Strophe } from 'strophe.js';
33
import 'strophejs-plugin-stream-management';
44

5+
import { MAX_CONNECTION_RETRIES } from '../../service/connectivity/Constants';
56
import Listenable from '../util/Listenable';
67

78
import ResumeTask from './ResumeTask';
@@ -10,11 +11,6 @@ import PingConnectionPlugin from './strophe.ping';
1011

1112
const logger = getLogger(__filename);
1213

13-
/**
14-
* Maximum number of tries to resume.
15-
*/
16-
const MAX_RESUME_TRIES = 3;
17-
1814
/**
1915
* The lib-jitsi-meet layer for {@link Strophe.Connection}.
2016
*/
@@ -649,10 +645,10 @@ export default class XmppConnection extends Listenable {
649645
if (resumeToken) {
650646
this._resumeTask.schedule();
651647

652-
const r = this._resumeTask.retryCount <= MAX_RESUME_TRIES;
648+
const r = this._resumeTask.retryCount <= MAX_CONNECTION_RETRIES;
653649

654650
if (!r) {
655-
logger.warn(`Maximum resume tries reached (${MAX_RESUME_TRIES}), giving up.`);
651+
logger.warn(`Maximum resume tries reached (${MAX_CONNECTION_RETRIES}), giving up.`);
656652
}
657653

658654
return r;

service/connectivity/Constants.ts

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// Number of times the client attempts to reconnect to the XMPP server or JVB (in case of an ICE failure).
2+
export const MAX_CONNECTION_RETRIES = 3;

service/statistics/AnalyticsEvents.spec.ts

+5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ describe( "/service/statistics/AnalyticsEvents members", () => {
1313
ACTION_JINGLE_SI_RECEIVED,
1414
ACTION_JINGLE_SI_TIMEOUT,
1515
ACTION_JINGLE_TERMINATE,
16+
ACTION_JVB_ICE_FAILED,
1617
ACTION_P2P_DECLINED,
1718
ACTION_P2P_ESTABLISHED,
1819
ACTION_P2P_FAILED,
@@ -33,6 +34,7 @@ describe( "/service/statistics/AnalyticsEvents members", () => {
3334
createE2eRttEvent,
3435
createFocusLeftEvent,
3536
createGetUserMediaEvent,
37+
createJvbIceFailedEvent,
3638
createParticipantConnectionStatusEvent,
3739
createTrackStreamingStatusEvent,
3840
createJingleEvent,
@@ -59,6 +61,7 @@ describe( "/service/statistics/AnalyticsEvents members", () => {
5961
expect( ACTION_JINGLE_SI_RECEIVED ).toBe( 'session-initiate.received' );
6062
expect( ACTION_JINGLE_SI_TIMEOUT ).toBe( 'session-initiate.timeout' );
6163
expect( ACTION_JINGLE_TERMINATE ).toBe( 'terminate' );
64+
expect( ACTION_JVB_ICE_FAILED ).toBe( 'jvb.ice.failed' );
6265
expect( ACTION_P2P_DECLINED ).toBe( 'decline' );
6366
expect( ACTION_P2P_ESTABLISHED ).toBe( 'established' );
6467
expect( ACTION_P2P_FAILED ).toBe( 'failed' );
@@ -84,6 +87,7 @@ describe( "/service/statistics/AnalyticsEvents members", () => {
8487
expect( AnalyticsEvents.ACTION_JINGLE_SI_RECEIVED ).toBe( 'session-initiate.received' );
8588
expect( AnalyticsEvents.ACTION_JINGLE_SI_TIMEOUT ).toBe( 'session-initiate.timeout' );
8689
expect( AnalyticsEvents.ACTION_JINGLE_TERMINATE ).toBe( 'terminate' );
90+
expect( AnalyticsEvents.ACTION_JVB_ICE_FAILED ).toBe( 'jvb.ice.failed' );
8791
expect( AnalyticsEvents.ACTION_P2P_DECLINED ).toBe( 'decline' );
8892
expect( AnalyticsEvents.ACTION_P2P_ESTABLISHED ).toBe( 'established' );
8993
expect( AnalyticsEvents.ACTION_P2P_FAILED ).toBe( 'failed' );
@@ -104,6 +108,7 @@ describe( "/service/statistics/AnalyticsEvents members", () => {
104108
expect( typeof ( createE2eRttEvent ) ).toBe( 'function' );
105109
expect( typeof ( createFocusLeftEvent ) ).toBe( 'function' );
106110
expect( typeof ( createGetUserMediaEvent ) ).toBe( 'function' );
111+
expect( typeof ( createJvbIceFailedEvent ) ).toBe( 'function' );
107112
expect( typeof ( createParticipantConnectionStatusEvent ) ).toBe( 'function' );
108113
expect( typeof ( createTrackStreamingStatusEvent ) ).toBe( 'function' );
109114
expect( typeof ( createJingleEvent ) ).toBe( 'function' );

service/statistics/AnalyticsEvents.ts

+19
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ export enum AnalyticsEvents {
7474
*/
7575
ACTION_JINGLE_TERMINATE = 'terminate',
7676

77+
/**
78+
* The "action" value for JVB events which indicates that the ICE connection has failed after 3 restart attempts
79+
*/
80+
ACTION_JVB_ICE_FAILED = 'jvb.ice.failed',
81+
7782
/**
7883
* The "action" value for P2P events which indicates that P2P session initiate message has been rejected by the client
7984
* because the mandatory requirements were not met.
@@ -221,6 +226,7 @@ export const ACTION_JINGLE_SA_TIMEOUT = AnalyticsEvents.ACTION_JINGLE_SA_TIMEOUT
221226
export const ACTION_JINGLE_SI_RECEIVED = AnalyticsEvents.ACTION_JINGLE_SI_RECEIVED;
222227
export const ACTION_JINGLE_SI_TIMEOUT = AnalyticsEvents.ACTION_JINGLE_SI_TIMEOUT;
223228
export const ACTION_JINGLE_TERMINATE = AnalyticsEvents.ACTION_JINGLE_TERMINATE;
229+
export const ACTION_JVB_ICE_FAILED = AnalyticsEvents.ACTION_JVB_ICE_FAILED;
224230
export const ACTION_P2P_DECLINED = AnalyticsEvents.ACTION_P2P_DECLINED;
225231
export const ACTION_P2P_ESTABLISHED = AnalyticsEvents.ACTION_P2P_ESTABLISHED;
226232
export const ACTION_P2P_FAILED = AnalyticsEvents.ACTION_P2P_FAILED;
@@ -333,6 +339,19 @@ export const createGetUserMediaEvent = ( action: 'error' | 'success' | 'warning'
333339
attributes
334340
} );
335341

342+
/**
343+
* Creates an event which indicates that the JVB ICE connection has failed event after 3 retries.
344+
*
345+
* @param action - The action type of the event.
346+
* @param attributes - The attributes to be added to the event.
347+
* @returns - The event object.
348+
*/
349+
export const createJvbIceFailedEvent = ( action: unknown, attributes: object = {} ) => ( {
350+
action,
351+
attributes,
352+
type: AnalyticsEvents.TYPE_OPERATIONAL,
353+
} );
354+
336355
/**
337356
* Creates an event related to remote participant connection status changes.
338357
*

0 commit comments

Comments
 (0)