Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import { getLogger } from '@jitsi/logger';
  2. import * as JitsiConferenceErrors from '../../JitsiConferenceErrors';
  3. import * as JitsiConferenceEvents from '../../JitsiConferenceEvents';
  4. const logger = getLogger(__filename);
  5. /**
  6. * This class deals with shenanigans around JVB media session's ICE failed status handling.
  7. *
  8. * If ICE restarts are NOT explicitly enabled by the {@code enableIceRestart} config option, then the conference will
  9. * delay emitting the {@JitsiConferenceErrors.ICE_FAILED} event by 15 seconds. If the network info module reports
  10. * the internet offline status then the time will start counting after the internet comes back online.
  11. *
  12. * If ICE restart are enabled, then a delayed ICE failed notification to Jicofo will be sent, only if the ICE connection
  13. * does not recover soon after or before the XMPP connection is restored (if it was ever broken). If ICE fails while
  14. * the XMPP connection is not broken then the notifications will be sent after 2 seconds delay.
  15. */
  16. export default class IceFailedHandling {
  17. /**
  18. * Creates new {@code DelayedIceFailed} task.
  19. * @param {JitsiConference} conference
  20. */
  21. constructor(conference) {
  22. this._conference = conference;
  23. }
  24. /**
  25. * After making sure there's no way for the ICE connection to recover this method either sends ICE failed
  26. * notification to Jicofo or emits the ice failed conference event.
  27. * @private
  28. * @returns {void}
  29. */
  30. _actOnIceFailed() {
  31. if (!this._conference.room) {
  32. return;
  33. }
  34. const { enableForcedReload, enableIceRestart } = this._conference.options.config;
  35. const explicitlyDisabled = typeof enableIceRestart !== 'undefined' && !enableIceRestart;
  36. const supportsRestartByTerminate = this._conference.room.supportsRestartByTerminate();
  37. const useTerminateForRestart = supportsRestartByTerminate && !enableIceRestart;
  38. logger.info('ICE failed,'
  39. + ` enableForcedReload: ${enableForcedReload},`
  40. + ` enableIceRestart: ${enableIceRestart},`
  41. + ` supports restart by terminate: ${supportsRestartByTerminate}`);
  42. if (explicitlyDisabled || (!enableIceRestart && !supportsRestartByTerminate) || enableForcedReload) {
  43. logger.info('ICE failed, but ICE restarts are disabled');
  44. const reason = enableForcedReload
  45. ? JitsiConferenceErrors.CONFERENCE_RESTARTED
  46. : JitsiConferenceErrors.ICE_FAILED;
  47. this._conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, reason);
  48. return;
  49. }
  50. const jvbConnection = this._conference.jvbJingleSession;
  51. const jvbConnIceState = jvbConnection && jvbConnection.getIceConnectionState();
  52. if (!jvbConnection) {
  53. logger.warn('Not sending ICE failed - no JVB connection');
  54. } else if (jvbConnIceState === 'connected') {
  55. logger.info('ICE connection restored - not sending ICE failed');
  56. } else {
  57. logger.info('Sending ICE failed - the connection did not recover, '
  58. + `ICE state: ${jvbConnIceState}, `
  59. + `use 'session-terminate': ${useTerminateForRestart}`);
  60. if (useTerminateForRestart) {
  61. this._conference.jvbJingleSession.terminate(
  62. () => {
  63. logger.info('session-terminate for ice restart - done');
  64. },
  65. error => {
  66. logger.error(`session-terminate for ice restart - error: ${error.message}`);
  67. }, {
  68. reason: 'connectivity-error',
  69. reasonDescription: 'ICE FAILED',
  70. requestRestart: true,
  71. sendSessionTerminate: true
  72. });
  73. } else {
  74. this._conference.jvbJingleSession.sendIceFailedNotification();
  75. }
  76. }
  77. }
  78. /**
  79. * Starts the task.
  80. */
  81. start() {
  82. // Using xmpp.ping allows to handle both XMPP being disconnected and internet offline cases. The ping function
  83. // uses sendIQ2 method which is resilient to XMPP connection disconnected state and will patiently wait until it
  84. // gets reconnected.
  85. // This also handles the case about waiting for the internet to come back online, because ping
  86. // will only succeed when the internet is online and then there's a chance for the ICE to recover from FAILED to
  87. // CONNECTED which is the extra 2 second timeout after ping.
  88. // The 65 second timeout is given on purpose as there's no chance for XMPP to recover after 65 seconds of no
  89. // communication with the server. Such resume attempt will result in unrecoverable conference failed event due
  90. // to 'item-not-found' error returned by the server.
  91. this._conference.xmpp.ping(65000).then(
  92. () => {
  93. if (!this._canceled) {
  94. this._iceFailedTimeout = window.setTimeout(() => {
  95. this._iceFailedTimeout = undefined;
  96. this._actOnIceFailed();
  97. }, 2000);
  98. }
  99. },
  100. error => {
  101. logger.error('PING error/timeout - not sending ICE failed', error);
  102. });
  103. }
  104. /**
  105. * Cancels the task.
  106. */
  107. cancel() {
  108. this._canceled = true;
  109. window.clearTimeout(this._iceFailedTimeout);
  110. }
  111. }