You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

IceFailedHandling.ts 3.6KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import { getLogger } from '@jitsi/logger';
  2. import JitsiConference from '../../JitsiConference';
  3. const logger = getLogger('modules/connectivity/IceFailedHandling');
  4. /**
  5. * This class deals with shenanigans around JVB media session's ICE failed status handling.
  6. *
  7. * If ICE connection is not re-established within 2 secs after the internet comes back online, the client will initiate
  8. * a session restart via 'session-terminate'. This results in Jicofo re-inviting the participant into the conference by
  9. * recreating the jvb media session so that there is minimla disruption to the user by default.
  10. */
  11. export default class IceFailedHandling {
  12. private _conference: JitsiConference;
  13. private _canceled: boolean = false;
  14. private _iceFailedTimeout?: number;
  15. /**
  16. * Creates new {@code DelayedIceFailed} task.
  17. * @param {JitsiConference} conference
  18. */
  19. constructor(conference: JitsiConference) {
  20. this._conference = conference;
  21. }
  22. /**
  23. * After making sure there's no way for the ICE connection to recover this method either sends ICE failed
  24. * notification to Jicofo or emits the ice failed conference event.
  25. * @private
  26. * @returns {void}
  27. */
  28. _actOnIceFailed(): void {
  29. if (!this._conference.room) {
  30. return;
  31. }
  32. const jvbConnection = this._conference.jvbJingleSession;
  33. const jvbConnIceState = jvbConnection?.getIceConnectionState();
  34. if (!jvbConnection) {
  35. logger.warn('Not sending ICE failed - no JVB connection');
  36. } else if (jvbConnIceState === 'connected') {
  37. logger.info('ICE connection restored - not sending ICE failed');
  38. } else {
  39. logger.info(`Sending ICE failed - the connection did not recover, ICE state: ${jvbConnIceState}`);
  40. this._conference._stopJvbSession({
  41. reason: 'connectivity-error',
  42. reasonDescription: 'ICE FAILED',
  43. requestRestart: true,
  44. sendSessionTerminate: true
  45. });
  46. }
  47. }
  48. /**
  49. * Starts the task.
  50. * @returns {void}
  51. */
  52. start(): void {
  53. // Using xmpp.ping allows to handle both XMPP being disconnected and internet offline cases. The ping function
  54. // uses sendIQ2 method which is resilient to XMPP connection disconnected state and will patiently wait until it
  55. // gets reconnected.
  56. // This also handles the case about waiting for the internet to come back online, because ping
  57. // will only succeed when the internet is online and then there's a chance for the ICE to recover from FAILED to
  58. // CONNECTED which is the extra 2 second timeout after ping.
  59. // The 65 second timeout is given on purpose as there's no chance for XMPP to recover after 65 seconds of no
  60. // communication with the server. Such resume attempt will result in unrecoverable conference failed event due
  61. // to 'item-not-found' error returned by the server.
  62. this._conference.xmpp.ping(65000).then(
  63. () => {
  64. if (!this._canceled) {
  65. this._iceFailedTimeout = window.setTimeout(() => {
  66. this._iceFailedTimeout = undefined;
  67. this._actOnIceFailed();
  68. }, 2000);
  69. }
  70. },
  71. error => {
  72. logger.error('PING error/timeout - not sending ICE failed', error);
  73. });
  74. }
  75. /**
  76. * Cancels the task.
  77. * @returns {void}
  78. */
  79. cancel(): void {
  80. this._canceled = true;
  81. window.clearTimeout(this._iceFailedTimeout);
  82. }
  83. }