瀏覽代碼

ref(IceFailedHandling): use ping instead of networkInfo

Simplifies the logic for delayed ICE failed event by relying
on XMPP ping instead of the networkInfo module to check
if the internet is online.
master
paweldomas 4 年之前
父節點
當前提交
3ac00edfd5
共有 3 個檔案被更改,包括 69 行新增115 行删除
  1. 27
    75
      modules/connectivity/IceFailedHandling.js
  2. 37
    38
      modules/connectivity/IceFailedHandling.spec.js
  3. 5
    2
      modules/util/TestUtils.js

+ 27
- 75
modules/connectivity/IceFailedHandling.js 查看文件

@@ -4,60 +4,8 @@ import { getLogger } from 'jitsi-meet-logger';
4 4
 import * as JitsiConferenceErrors from '../../JitsiConferenceErrors';
5 5
 import * as JitsiConferenceEvents from '../../JitsiConferenceEvents';
6 6
 
7
-import { default as networkInfo, NETWORK_INFO_EVENT } from './NetworkInfo';
8
-
9 7
 const logger = getLogger(__filename);
10 8
 
11
-/**
12
- * Helper class for handling ICE event delay in combination with internet online/offline status check.
13
- */
14
-class DelayedIceFailedEvent {
15
-    /**
16
-     * A constructor.
17
-     * @param {function} emitIceFailed - Will be called by this class to emit ICE failed conference event.
18
-     * @param {number} delay - The delay for ICE failed in milliseconds since the event occurred on the peerconnection
19
-     * or the internet came back online.
20
-     */
21
-    constructor(emitIceFailed, delay) {
22
-        this._emitIceFailed = emitIceFailed;
23
-        this._delay = delay;
24
-    }
25
-
26
-    /**
27
-     * Starts the event delay and internet status check logic.
28
-     */
29
-    start() {
30
-        this._onlineListener
31
-            = networkInfo.addEventListener(
32
-                NETWORK_INFO_EVENT,
33
-                () => this._maybeSetDelayTimeout());
34
-        this._maybeSetDelayTimeout();
35
-    }
36
-
37
-    /**
38
-     * Cancels the task.
39
-     */
40
-    stop() {
41
-        this._onlineListener && this._onlineListener();
42
-        this._onlineListener = undefined;
43
-        clearTimeout(this._delayTimeout);
44
-    }
45
-
46
-    /**
47
-     * Resets the timer delay if the internet status is online.
48
-     * @private
49
-     */
50
-    _maybeSetDelayTimeout() {
51
-        clearTimeout(this._delayTimeout);
52
-
53
-        if (networkInfo.isOnline()) {
54
-            logger.info(`Will emit ICE failed in ${this._delay}ms`);
55
-            this._delayTimeout = setTimeout(() => this._emitIceFailed(), this._delay);
56
-        }
57
-    }
58
-}
59
-
60
-
61 9
 /**
62 10
  * This class deals with shenanigans around JVB media session's ICE failed status handling.
63 11
  *
@@ -79,21 +27,38 @@ export default class IceFailedHandling {
79 27
     }
80 28
 
81 29
     /**
82
-     * Starts the task.
30
+     * After making sure there's no way for the ICE connection to recover this method either sends ICE failed
31
+     * notification to Jicofo or emits the ice failed conference event.
32
+     * @private
33
+     * @returns {void}
83 34
      */
84
-    start() {
35
+    _actOnIceFailed() {
85 36
         if (!this._conference.options.config.enableIceRestart) {
86 37
             logger.info('ICE failed, but ICE restarts are disabled');
87
-            this._delayedIceFailedEvent = new DelayedIceFailedEvent(() => {
88
-                this._conference.eventEmitter.emit(
89
-                    JitsiConferenceEvents.CONFERENCE_FAILED,
90
-                    JitsiConferenceErrors.ICE_FAILED);
91
-            }, 15000);
92
-            this._delayedIceFailedEvent.start();
38
+            this._conference.eventEmitter.emit(
39
+                JitsiConferenceEvents.CONFERENCE_FAILED,
40
+                JitsiConferenceErrors.ICE_FAILED);
93 41
 
94 42
             return;
95 43
         }
96 44
 
45
+        const jvbConnection = this._conference.jvbJingleSession;
46
+        const jvbConnIceState = jvbConnection && jvbConnection.getIceConnectionState();
47
+
48
+        if (!jvbConnection) {
49
+            logger.warn('Not sending ICE failed - no JVB connection');
50
+        } else if (jvbConnIceState === 'connected') {
51
+            logger.info('ICE connection restored - not sending ICE failed');
52
+        } else {
53
+            logger.info(`Sending ICE failed - the connection has not recovered: ${jvbConnIceState}`);
54
+            jvbConnection.sendIceFailedNotification();
55
+        }
56
+    }
57
+
58
+    /**
59
+     * Starts the task.
60
+     */
61
+    start() {
97 62
         //  Using xmpp.ping allows to handle both XMPP being disconnected and internet offline cases. The ping function
98 63
         // uses sendIQ2 method which is resilient to XMPP connection disconnected state and will patiently wait until it
99 64
         // gets reconnected.
@@ -105,22 +70,10 @@ export default class IceFailedHandling {
105 70
         // to 'item-not-found' error returned by the server.
106 71
         this._conference.xmpp.ping(65000).then(
107 72
             () => {
108
-                if (this._canceled) {
109
-                    return;
110
-                }
111
-
112
-                const jvbConnection = this._conference.jvbJingleSession;
113
-                const jvbConnIceState = jvbConnection && jvbConnection.getIceConnectionState();
114
-
115
-                if (!jvbConnection) {
116
-                    logger.warn('Not sending ICE failed - no JVB connection');
117
-                } else if (jvbConnIceState === 'connected') {
118
-                    logger.info('ICE connection restored - not sending ICE failed');
119
-                } else {
73
+                if (!this._canceled) {
120 74
                     this._iceFailedTimeout = window.setTimeout(() => {
121
-                        logger.info(`Sending ICE failed - the connection has not recovered: ${jvbConnIceState}`);
122 75
                         this._iceFailedTimeout = undefined;
123
-                        jvbConnection.sendIceFailedNotification();
76
+                        this._actOnIceFailed();
124 77
                     }, 2000);
125 78
                 }
126 79
             },
@@ -135,6 +88,5 @@ export default class IceFailedHandling {
135 88
     cancel() {
136 89
         this._canceled = true;
137 90
         window.clearTimeout(this._iceFailedTimeout);
138
-        this._delayedIceFailedEvent && this._delayedIceFailedEvent.stop();
139 91
     }
140 92
 }

+ 37
- 38
modules/connectivity/IceFailedHandling.spec.js 查看文件

@@ -4,7 +4,6 @@ import Listenable from '../util/Listenable';
4 4
 import { nextTick } from '../util/TestUtils';
5 5
 
6 6
 import IceFailedHandling from './IceFailedHandling';
7
-import networkInfo from './NetworkInfo';
8 7
 
9 8
 /**
10 9
  * Mock conference for the purpose of this test.
@@ -28,13 +27,15 @@ describe('IceFailedHandling', () => {
28 27
 
29 28
     beforeEach(() => {
30 29
         jasmine.clock().install();
31
-        networkInfo.updateNetworkInfo({ isOnline: true });
32 30
         mockConference = new MockConference();
33 31
         iceFailedHandling = new IceFailedHandling(mockConference);
34 32
         mockConference.eventEmitter = {
35 33
             // eslint-disable-next-line no-empty-function
36 34
             emit: () => { }
37 35
         };
36
+        mockConference.xmpp = {
37
+            ping: () => Promise.resolve()
38
+        };
38 39
         emitEventSpy = spyOn(mockConference.eventEmitter, 'emit');
39 40
     });
40 41
 
@@ -46,34 +47,32 @@ describe('IceFailedHandling', () => {
46 47
         beforeEach(() => {
47 48
             mockConference.options.config.enableIceRestart = false;
48 49
         });
49
-        it('emits ICE failed with 15 seconds delay', () => {
50
-            iceFailedHandling.start();
51
-            jasmine.clock().tick(10000);
52
-            expect(emitEventSpy).not.toHaveBeenCalled();
53
-
54
-            jasmine.clock().tick(5100);
55
-            expect(emitEventSpy).toHaveBeenCalled();
56
-        });
57
-        it('starts counting the time after the internet comes back online', () => {
50
+        it('emits ICE failed with 2 seconds delay after XMPP ping comes through', () => {
58 51
             iceFailedHandling.start();
59
-            jasmine.clock().tick(3000);
60 52
 
61
-            networkInfo.updateNetworkInfo({ isOnline: false });
62
-            jasmine.clock().tick(16000);
63
-            expect(emitEventSpy).not.toHaveBeenCalled();
53
+            return nextTick() // tick for ping
54
+                .then(() => {
55
+                    expect(emitEventSpy).not.toHaveBeenCalled();
64 56
 
65
-            networkInfo.updateNetworkInfo({ isOnline: true });
66
-            jasmine.clock().tick(16000);
67
-            expect(emitEventSpy).toHaveBeenCalled();
57
+                    return nextTick(2500); // tick for the 2 sec ice timeout
58
+                })
59
+                .then(() => {
60
+                    expect(emitEventSpy).toHaveBeenCalled();
61
+                });
68 62
         });
69 63
         it('cancel method cancels the ICE failed event', () => {
70 64
             iceFailedHandling.start();
71
-            jasmine.clock().tick(10000);
72
-            expect(emitEventSpy).not.toHaveBeenCalled();
73 65
 
74
-            iceFailedHandling.cancel();
75
-            jasmine.clock().tick(5100);
76
-            expect(emitEventSpy).not.toHaveBeenCalled();
66
+            return nextTick(1000) // tick for ping
67
+                .then(() => {
68
+                    expect(emitEventSpy).not.toHaveBeenCalled();
69
+                    iceFailedHandling.cancel();
70
+
71
+                    return nextTick(2500); // tick for ice timeout
72
+                })
73
+                .then(() => {
74
+                    expect(emitEventSpy).not.toHaveBeenCalled();
75
+                });
77 76
         });
78 77
     });
79 78
     describe('when ICE restart are enabled', () => {
@@ -81,9 +80,6 @@ describe('IceFailedHandling', () => {
81 80
 
82 81
         beforeEach(() => {
83 82
             mockConference.options.config.enableIceRestart = true;
84
-            mockConference.xmpp = {
85
-                ping: () => Promise.resolve()
86
-            };
87 83
             mockConference.jvbJingleSession = {
88 84
                 getIceConnectionState: () => 'failed',
89 85
                 // eslint-disable-next-line no-empty-function
@@ -94,23 +90,26 @@ describe('IceFailedHandling', () => {
94 90
         it('send ICE failed notification to Jicofo', () => {
95 91
             iceFailedHandling.start();
96 92
 
97
-            // first it send ping which is async - need next tick
98
-            return nextTick().then(() => {
99
-                jasmine.clock().tick(3000);
100
-                expect(sendIceFailedSpy).toHaveBeenCalled();
101
-            });
93
+            return nextTick() // tick for ping
94
+                .then(() => nextTick(2500)) // tick for ice timeout
95
+                .then(() => {
96
+                    expect(sendIceFailedSpy).toHaveBeenCalled();
97
+                });
102 98
         });
103 99
         it('not send ICE failed notification to Jicofo if canceled', () => {
104 100
             iceFailedHandling.start();
105 101
 
106 102
             // first it send ping which is async - need next tick
107
-            return nextTick().then(() => {
108
-                jasmine.clock().tick(1000);
109
-                expect(sendIceFailedSpy).not.toHaveBeenCalled();
110
-                iceFailedHandling.cancel();
111
-                jasmine.clock().tick(3000);
112
-                expect(sendIceFailedSpy).not.toHaveBeenCalled();
113
-            });
103
+            return nextTick(1000)
104
+                .then(() => {
105
+                    expect(sendIceFailedSpy).not.toHaveBeenCalled();
106
+                    iceFailedHandling.cancel();
107
+
108
+                    return nextTick(3000); // tick for ice timeout
109
+                })
110
+                .then(() => {
111
+                    expect(sendIceFailedSpy).not.toHaveBeenCalled();
112
+                });
114 113
         });
115 114
     });
116 115
 });

+ 5
- 2
modules/util/TestUtils.js 查看文件

@@ -1,9 +1,12 @@
1 1
 /* global process */
2 2
 /**
3
- * Returns a Promise resolved after {@code process.nextTick}.
3
+ * Returns a Promise resolved after {@code process.nextTick} with the option to advance Jasmine timers.
4 4
  *
5
+ * @param {number} [advanceTimer] - the value to be passed to Jasmine clock's tick method.
5 6
  * @returns {Promise<void>}
6 7
  */
7
-export function nextTick() {
8
+export function nextTick(advanceTimer) {
9
+    advanceTimer && jasmine.clock().tick(advanceTimer);
10
+
8 11
     return new Promise(resolve => process.nextTick(resolve));
9 12
 }

Loading…
取消
儲存