|
@@ -4,7 +4,6 @@ import {
|
4
|
4
|
ICE_DURATION,
|
5
|
5
|
ICE_STATE_CHANGED
|
6
|
6
|
} from '../../service/statistics/AnalyticsEvents';
|
7
|
|
-import async from 'async';
|
8
|
7
|
import { getLogger } from 'jitsi-meet-logger';
|
9
|
8
|
import { $iq, Strophe } from 'strophe.js';
|
10
|
9
|
import { integerHash } from '../util/StringUtils';
|
|
@@ -19,6 +18,7 @@ import SignalingLayerImpl from './SignalingLayerImpl';
|
19
|
18
|
import RTCEvents from '../../service/RTC/RTCEvents';
|
20
|
19
|
import Statistics from '../statistics/statistics';
|
21
|
20
|
import XMPPEvents from '../../service/xmpp/XMPPEvents';
|
|
21
|
+import AsyncQueue from '../util/AsyncQueue';
|
22
|
22
|
import GlobalOnErrorHandler from '../util/GlobalOnErrorHandler';
|
23
|
23
|
|
24
|
24
|
const logger = getLogger(__filename);
|
|
@@ -212,8 +212,12 @@ export default class JingleSessionPC extends JingleSession {
|
212
|
212
|
*/
|
213
|
213
|
this.signalingLayer = new SignalingLayerImpl();
|
214
|
214
|
|
215
|
|
- this.modificationQueue
|
216
|
|
- = async.queue(this._processQueueTasks.bind(this), 1);
|
|
215
|
+ /**
|
|
216
|
+ * The queue used to serialize operations done on the peerconnection.
|
|
217
|
+ *
|
|
218
|
+ * @type {AsyncQueue}
|
|
219
|
+ */
|
|
220
|
+ this.modificationQueue = new AsyncQueue();
|
217
|
221
|
|
218
|
222
|
/**
|
219
|
223
|
* Flag used to guarantee that the connection established event is
|
|
@@ -234,23 +238,12 @@ export default class JingleSessionPC extends JingleSession {
|
234
|
238
|
/* eslint-enable max-params */
|
235
|
239
|
|
236
|
240
|
/**
|
237
|
|
- * Checks whether or not this session instance has been ended and eventually
|
238
|
|
- * logs a message which mentions that given <tt>actionName</tt> was
|
239
|
|
- * cancelled.
|
240
|
|
- * @param {string} actionName
|
241
|
|
- * @return {boolean} <tt>true</tt> if this {@link JingleSessionPC} has
|
242
|
|
- * entered {@link JingleSessionState.ENDED} or <tt>false</tt> otherwise.
|
|
241
|
+ * Checks whether or not this session instance is still operational.
|
243
|
242
|
* @private
|
|
243
|
+ * @returns {boolean} {@code true} if operation or {@code false} otherwise.
|
244
|
244
|
*/
|
245
|
|
- _assertNotEnded(actionName) {
|
246
|
|
- if (this.state === JingleSessionState.ENDED) {
|
247
|
|
- logger.log(
|
248
|
|
- `The session has ended - cancelling action: ${actionName}`);
|
249
|
|
-
|
250
|
|
- return false;
|
251
|
|
- }
|
252
|
|
-
|
253
|
|
- return true;
|
|
245
|
+ _assertNotEnded() {
|
|
246
|
+ return this.state !== JingleSessionState.ENDED;
|
254
|
247
|
}
|
255
|
248
|
|
256
|
249
|
/**
|
|
@@ -316,7 +309,7 @@ export default class JingleSessionPC extends JingleSession {
|
316
|
309
|
pcOptions);
|
317
|
310
|
|
318
|
311
|
this.peerconnection.onicecandidate = ev => {
|
319
|
|
- if (!ev) {
|
|
312
|
+ if (!ev || !this._assertNotEnded()) {
|
320
|
313
|
// There was an incomplete check for ev before which left
|
321
|
314
|
// the last line of the function unprotected from a potential
|
322
|
315
|
// throw of an exception. Consequently, it may be argued that
|
|
@@ -372,15 +365,13 @@ export default class JingleSessionPC extends JingleSession {
|
372
|
365
|
// "closed" instead.
|
373
|
366
|
// I suppose at some point this will be moved to onconnectionstatechange
|
374
|
367
|
this.peerconnection.onsignalingstatechange = () => {
|
375
|
|
- if (!this.peerconnection) {
|
|
368
|
+ if (!this.peerconnection || !this._assertNotEnded()) {
|
376
|
369
|
return;
|
377
|
370
|
}
|
378
|
371
|
if (this.peerconnection.signalingState === 'stable') {
|
379
|
372
|
this.wasstable = true;
|
380
|
|
- } else if (
|
381
|
|
- (this.peerconnection.signalingState === 'closed'
|
382
|
|
- || this.peerconnection.connectionState === 'closed')
|
383
|
|
- && !this.closed) {
|
|
373
|
+ } else if (this.peerconnection.signalingState === 'closed'
|
|
374
|
+ || this.peerconnection.connectionState === 'closed') {
|
384
|
375
|
this.room.eventEmitter.emit(XMPPEvents.SUSPEND_DETECTED, this);
|
385
|
376
|
}
|
386
|
377
|
};
|
|
@@ -392,8 +383,7 @@ export default class JingleSessionPC extends JingleSession {
|
392
|
383
|
* the value of RTCPeerConnection.iceConnectionState changes.
|
393
|
384
|
*/
|
394
|
385
|
this.peerconnection.oniceconnectionstatechange = () => {
|
395
|
|
- if (!this.peerconnection
|
396
|
|
- || !this._assertNotEnded('oniceconnectionstatechange')) {
|
|
386
|
+ if (!this.peerconnection || !this._assertNotEnded()) {
|
397
|
387
|
return;
|
398
|
388
|
}
|
399
|
389
|
const now = window.performance.now();
|
|
@@ -473,9 +463,6 @@ export default class JingleSessionPC extends JingleSession {
|
473
|
463
|
this.isReconnect = false;
|
474
|
464
|
break;
|
475
|
465
|
case 'disconnected':
|
476
|
|
- if (this.closed) {
|
477
|
|
- break;
|
478
|
|
- }
|
479
|
466
|
this.isReconnect = true;
|
480
|
467
|
|
481
|
468
|
// Informs interested parties that the connection has been
|
|
@@ -1320,9 +1307,6 @@ export default class JingleSessionPC extends JingleSession {
|
1320
|
1307
|
* @param reasonText
|
1321
|
1308
|
*/
|
1322
|
1309
|
onTerminated(reasonCondition, reasonText) {
|
1323
|
|
- this.state = JingleSessionState.ENDED;
|
1324
|
|
- this.establishmentDuration = undefined;
|
1325
|
|
-
|
1326
|
1310
|
// Do something with reason and reasonCondition when we start to care
|
1327
|
1311
|
// this.reasonCondition = reasonCondition;
|
1328
|
1312
|
// this.reasonText = reasonText;
|
|
@@ -1488,24 +1472,6 @@ export default class JingleSessionPC extends JingleSession {
|
1488
|
1472
|
this.modificationQueue.push(workFunction);
|
1489
|
1473
|
}
|
1490
|
1474
|
|
1491
|
|
- /**
|
1492
|
|
- * The 'task' function will be given a callback it MUST call with either:
|
1493
|
|
- * 1) No arguments if it was successful or
|
1494
|
|
- * 2) An error argument if there was an error
|
1495
|
|
- * If the task wants to process the success or failure of the task, it
|
1496
|
|
- * should pass a handler to the .push function, e.g.:
|
1497
|
|
- * queue.push(task, (err) => {
|
1498
|
|
- * if (err) {
|
1499
|
|
- * // error handling
|
1500
|
|
- * } else {
|
1501
|
|
- * // success handling
|
1502
|
|
- * }
|
1503
|
|
- * });
|
1504
|
|
- */
|
1505
|
|
- _processQueueTasks(task, finishedCallback) {
|
1506
|
|
- task(finishedCallback);
|
1507
|
|
- }
|
1508
|
|
-
|
1509
|
1475
|
/**
|
1510
|
1476
|
* Takes in a jingle offer iq, returns the new sdp offer
|
1511
|
1477
|
* @param {jquery xml element} offerIq the incoming offer
|
|
@@ -1695,18 +1661,6 @@ export default class JingleSessionPC extends JingleSession {
|
1695
|
1661
|
*/
|
1696
|
1662
|
replaceTrack(oldTrack, newTrack) {
|
1697
|
1663
|
const workFunction = finishedCallback => {
|
1698
|
|
- // Check if the connection was closed and pretend everything is OK.
|
1699
|
|
- // This can happen if a track removal is scheduled but takes place
|
1700
|
|
- // after the connection is closed.
|
1701
|
|
- if (this.peerconnection.signalingState === 'closed'
|
1702
|
|
- || this.peerconnection.connectionState === 'closed'
|
1703
|
|
- || this.closed) {
|
1704
|
|
-
|
1705
|
|
- finishedCallback();
|
1706
|
|
-
|
1707
|
|
- return;
|
1708
|
|
- }
|
1709
|
|
-
|
1710
|
1664
|
const oldLocalSdp = this.peerconnection.localDescription.sdp;
|
1711
|
1665
|
|
1712
|
1666
|
// NOTE the code below assumes that no more than 1 video track
|
|
@@ -2251,18 +2205,18 @@ export default class JingleSessionPC extends JingleSession {
|
2251
|
2205
|
* Closes the peerconnection.
|
2252
|
2206
|
*/
|
2253
|
2207
|
close() {
|
2254
|
|
- this.closed = true;
|
|
2208
|
+ this.state = JingleSessionState.ENDED;
|
|
2209
|
+ this.establishmentDuration = undefined;
|
2255
|
2210
|
|
2256
|
|
- // The signaling layer will remove it's listeners
|
2257
|
|
- this.signalingLayer.setChatRoom(null);
|
|
2211
|
+ this.modificationQueue.push(finishCallback => {
|
|
2212
|
+ // The signaling layer will remove it's listeners
|
|
2213
|
+ this.signalingLayer.setChatRoom(null);
|
2258
|
2214
|
|
2259
|
|
- // do not try to close if already closed.
|
2260
|
|
- this.peerconnection
|
2261
|
|
- && ((this.peerconnection.signalingState
|
2262
|
|
- && this.peerconnection.signalingState !== 'closed')
|
2263
|
|
- || (this.peerconnection.connectionState
|
2264
|
|
- && this.peerconnection.connectionState !== 'closed'))
|
2265
|
|
- && this.peerconnection.close();
|
|
2215
|
+ // do not try to close if already closed.
|
|
2216
|
+ this.peerconnection && this.peerconnection.close();
|
|
2217
|
+ finishCallback();
|
|
2218
|
+ });
|
|
2219
|
+ this.modificationQueue.shutdown();
|
2266
|
2220
|
}
|
2267
|
2221
|
|
2268
|
2222
|
/**
|