123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- import { getLogger } from '@jitsi/logger';
-
- import * as JitsiConferenceErrors from '../../JitsiConferenceErrors';
- import * as JitsiConferenceEvents from '../../JitsiConferenceEvents';
-
- const logger = getLogger(__filename);
-
- /**
- * This class deals with shenanigans around JVB media session's ICE failed status handling.
- *
- * If ICE restarts are NOT explicitly enabled by the {@code enableIceRestart} config option, then the conference will
- * delay emitting the {@JitsiConferenceErrors.ICE_FAILED} event by 15 seconds. If the network info module reports
- * the internet offline status then the time will start counting after the internet comes back online.
- *
- * If ICE restart are enabled, then a delayed ICE failed notification to Jicofo will be sent, only if the ICE connection
- * does not recover soon after or before the XMPP connection is restored (if it was ever broken). If ICE fails while
- * the XMPP connection is not broken then the notifications will be sent after 2 seconds delay.
- */
- export default class IceFailedHandling {
- /**
- * Creates new {@code DelayedIceFailed} task.
- * @param {JitsiConference} conference
- */
- constructor(conference) {
- this._conference = conference;
- }
-
- /**
- * After making sure there's no way for the ICE connection to recover this method either sends ICE failed
- * notification to Jicofo or emits the ice failed conference event.
- * @private
- * @returns {void}
- */
- _actOnIceFailed() {
- if (!this._conference.room) {
- return;
- }
-
- const { enableForcedReload, enableIceRestart } = this._conference.options.config;
- const explicitlyDisabled = typeof enableIceRestart !== 'undefined' && !enableIceRestart;
- const supportsRestartByTerminate = this._conference.room.supportsRestartByTerminate();
- const useTerminateForRestart = supportsRestartByTerminate && !enableIceRestart;
-
- logger.info('ICE failed,'
- + ` enableForcedReload: ${enableForcedReload},`
- + ` enableIceRestart: ${enableIceRestart},`
- + ` supports restart by terminate: ${supportsRestartByTerminate}`);
-
- if (explicitlyDisabled || (!enableIceRestart && !supportsRestartByTerminate) || enableForcedReload) {
- logger.info('ICE failed, but ICE restarts are disabled');
- const reason = enableForcedReload
- ? JitsiConferenceErrors.CONFERENCE_RESTARTED
- : JitsiConferenceErrors.ICE_FAILED;
-
- this._conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, reason);
-
- return;
- }
-
- const jvbConnection = this._conference.jvbJingleSession;
- const jvbConnIceState = jvbConnection && jvbConnection.getIceConnectionState();
-
- if (!jvbConnection) {
- logger.warn('Not sending ICE failed - no JVB connection');
- } else if (jvbConnIceState === 'connected') {
- logger.info('ICE connection restored - not sending ICE failed');
- } else {
- logger.info('Sending ICE failed - the connection did not recover, '
- + `ICE state: ${jvbConnIceState}, `
- + `use 'session-terminate': ${useTerminateForRestart}`);
- if (useTerminateForRestart) {
- this._conference.jvbJingleSession.terminate(
- () => {
- logger.info('session-terminate for ice restart - done');
- },
- error => {
- logger.error(`session-terminate for ice restart - error: ${error.message}`);
- }, {
- reason: 'connectivity-error',
- reasonDescription: 'ICE FAILED',
- requestRestart: true,
- sendSessionTerminate: true
- });
- } else {
- this._conference.jvbJingleSession.sendIceFailedNotification();
- }
- }
- }
-
- /**
- * Starts the task.
- */
- start() {
- // Using xmpp.ping allows to handle both XMPP being disconnected and internet offline cases. The ping function
- // uses sendIQ2 method which is resilient to XMPP connection disconnected state and will patiently wait until it
- // gets reconnected.
- // This also handles the case about waiting for the internet to come back online, because ping
- // will only succeed when the internet is online and then there's a chance for the ICE to recover from FAILED to
- // CONNECTED which is the extra 2 second timeout after ping.
- // The 65 second timeout is given on purpose as there's no chance for XMPP to recover after 65 seconds of no
- // communication with the server. Such resume attempt will result in unrecoverable conference failed event due
- // to 'item-not-found' error returned by the server.
- this._conference.xmpp.ping(65000).then(
- () => {
- if (!this._canceled) {
- this._iceFailedTimeout = window.setTimeout(() => {
- this._iceFailedTimeout = undefined;
- this._actOnIceFailed();
- }, 2000);
- }
- },
- error => {
- logger.error('PING error/timeout - not sending ICE failed', error);
- });
- }
-
- /**
- * Cancels the task.
- */
- cancel() {
- this._canceled = true;
- window.clearTimeout(this._iceFailedTimeout);
- }
- }
|