Procházet zdrojové kódy

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 před 4 roky
rodič
revize
3ac00edfd5

+ 27
- 75
modules/connectivity/IceFailedHandling.js Zobrazit soubor

4
 import * as JitsiConferenceErrors from '../../JitsiConferenceErrors';
4
 import * as JitsiConferenceErrors from '../../JitsiConferenceErrors';
5
 import * as JitsiConferenceEvents from '../../JitsiConferenceEvents';
5
 import * as JitsiConferenceEvents from '../../JitsiConferenceEvents';
6
 
6
 
7
-import { default as networkInfo, NETWORK_INFO_EVENT } from './NetworkInfo';
8
-
9
 const logger = getLogger(__filename);
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
  * This class deals with shenanigans around JVB media session's ICE failed status handling.
10
  * This class deals with shenanigans around JVB media session's ICE failed status handling.
63
  *
11
  *
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
         if (!this._conference.options.config.enableIceRestart) {
36
         if (!this._conference.options.config.enableIceRestart) {
86
             logger.info('ICE failed, but ICE restarts are disabled');
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
             return;
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
         //  Using xmpp.ping allows to handle both XMPP being disconnected and internet offline cases. The ping function
62
         //  Using xmpp.ping allows to handle both XMPP being disconnected and internet offline cases. The ping function
98
         // uses sendIQ2 method which is resilient to XMPP connection disconnected state and will patiently wait until it
63
         // uses sendIQ2 method which is resilient to XMPP connection disconnected state and will patiently wait until it
99
         // gets reconnected.
64
         // gets reconnected.
105
         // to 'item-not-found' error returned by the server.
70
         // to 'item-not-found' error returned by the server.
106
         this._conference.xmpp.ping(65000).then(
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
                     this._iceFailedTimeout = window.setTimeout(() => {
74
                     this._iceFailedTimeout = window.setTimeout(() => {
121
-                        logger.info(`Sending ICE failed - the connection has not recovered: ${jvbConnIceState}`);
122
                         this._iceFailedTimeout = undefined;
75
                         this._iceFailedTimeout = undefined;
123
-                        jvbConnection.sendIceFailedNotification();
76
+                        this._actOnIceFailed();
124
                     }, 2000);
77
                     }, 2000);
125
                 }
78
                 }
126
             },
79
             },
135
     cancel() {
88
     cancel() {
136
         this._canceled = true;
89
         this._canceled = true;
137
         window.clearTimeout(this._iceFailedTimeout);
90
         window.clearTimeout(this._iceFailedTimeout);
138
-        this._delayedIceFailedEvent && this._delayedIceFailedEvent.stop();
139
     }
91
     }
140
 }
92
 }

+ 37
- 38
modules/connectivity/IceFailedHandling.spec.js Zobrazit soubor

4
 import { nextTick } from '../util/TestUtils';
4
 import { nextTick } from '../util/TestUtils';
5
 
5
 
6
 import IceFailedHandling from './IceFailedHandling';
6
 import IceFailedHandling from './IceFailedHandling';
7
-import networkInfo from './NetworkInfo';
8
 
7
 
9
 /**
8
 /**
10
  * Mock conference for the purpose of this test.
9
  * Mock conference for the purpose of this test.
28
 
27
 
29
     beforeEach(() => {
28
     beforeEach(() => {
30
         jasmine.clock().install();
29
         jasmine.clock().install();
31
-        networkInfo.updateNetworkInfo({ isOnline: true });
32
         mockConference = new MockConference();
30
         mockConference = new MockConference();
33
         iceFailedHandling = new IceFailedHandling(mockConference);
31
         iceFailedHandling = new IceFailedHandling(mockConference);
34
         mockConference.eventEmitter = {
32
         mockConference.eventEmitter = {
35
             // eslint-disable-next-line no-empty-function
33
             // eslint-disable-next-line no-empty-function
36
             emit: () => { }
34
             emit: () => { }
37
         };
35
         };
36
+        mockConference.xmpp = {
37
+            ping: () => Promise.resolve()
38
+        };
38
         emitEventSpy = spyOn(mockConference.eventEmitter, 'emit');
39
         emitEventSpy = spyOn(mockConference.eventEmitter, 'emit');
39
     });
40
     });
40
 
41
 
46
         beforeEach(() => {
47
         beforeEach(() => {
47
             mockConference.options.config.enableIceRestart = false;
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
             iceFailedHandling.start();
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
         it('cancel method cancels the ICE failed event', () => {
63
         it('cancel method cancels the ICE failed event', () => {
70
             iceFailedHandling.start();
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
     describe('when ICE restart are enabled', () => {
78
     describe('when ICE restart are enabled', () => {
81
 
80
 
82
         beforeEach(() => {
81
         beforeEach(() => {
83
             mockConference.options.config.enableIceRestart = true;
82
             mockConference.options.config.enableIceRestart = true;
84
-            mockConference.xmpp = {
85
-                ping: () => Promise.resolve()
86
-            };
87
             mockConference.jvbJingleSession = {
83
             mockConference.jvbJingleSession = {
88
                 getIceConnectionState: () => 'failed',
84
                 getIceConnectionState: () => 'failed',
89
                 // eslint-disable-next-line no-empty-function
85
                 // eslint-disable-next-line no-empty-function
94
         it('send ICE failed notification to Jicofo', () => {
90
         it('send ICE failed notification to Jicofo', () => {
95
             iceFailedHandling.start();
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
         it('not send ICE failed notification to Jicofo if canceled', () => {
99
         it('not send ICE failed notification to Jicofo if canceled', () => {
104
             iceFailedHandling.start();
100
             iceFailedHandling.start();
105
 
101
 
106
             // first it send ping which is async - need next tick
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 Zobrazit soubor

1
 /* global process */
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
  * @returns {Promise<void>}
6
  * @returns {Promise<void>}
6
  */
7
  */
7
-export function nextTick() {
8
+export function nextTick(advanceTimer) {
9
+    advanceTimer && jasmine.clock().tick(advanceTimer);
10
+
8
     return new Promise(resolve => process.nextTick(resolve));
11
     return new Promise(resolve => process.nextTick(resolve));
9
 }
12
 }

Načítá se…
Zrušit
Uložit