|
@@ -197,7 +197,7 @@ export default class JingleSessionPC extends JingleSession {
|
197
|
197
|
* The bridge session's identifier. One Jingle session can during
|
198
|
198
|
* it's lifetime participate in multiple bridge sessions managed by
|
199
|
199
|
* Jicofo. A new bridge session is started whenever Jicofo sends
|
200
|
|
- * 'session-initiate' or 'transport-replace'.
|
|
200
|
+ * 'session-initiate'.
|
201
|
201
|
*
|
202
|
202
|
* @type {?string}
|
203
|
203
|
* @private
|
|
@@ -277,8 +277,7 @@ export default class JingleSessionPC extends JingleSession {
|
277
|
277
|
|
278
|
278
|
/**
|
279
|
279
|
* Marks that ICE gathering duration has been reported already. That
|
280
|
|
- * prevents reporting it again, after eventual 'transport-replace' (JVB
|
281
|
|
- * conference migration/ICE restart).
|
|
280
|
+ * prevents reporting it again.
|
282
|
281
|
* @type {boolean}
|
283
|
282
|
* @private
|
284
|
283
|
*/
|
|
@@ -544,13 +543,7 @@ export default class JingleSessionPC extends JingleSession {
|
544
|
543
|
// media connection to the bridge has been restored after an ICE failure by using session-terminate.
|
545
|
544
|
if (this.peerconnection.signalingState === 'stable') {
|
546
|
545
|
isStable = true;
|
547
|
|
- const usesTerminateForRestart = !this.options.enableIceRestart
|
548
|
|
- && this.room.supportsRestartByTerminate();
|
549
|
|
-
|
550
|
|
- if (this.isReconnect || usesTerminateForRestart) {
|
551
|
|
- this.room.eventEmitter.emit(
|
552
|
|
- XMPPEvents.CONNECTION_RESTORED, this);
|
553
|
|
- }
|
|
546
|
+ this.room.eventEmitter.emit(XMPPEvents.CONNECTION_RESTORED, this);
|
554
|
547
|
}
|
555
|
548
|
|
556
|
549
|
// Add a workaround for an issue on chrome in Unified plan when the local endpoint is the offerer.
|
|
@@ -817,45 +810,6 @@ export default class JingleSessionPC extends JingleSession {
|
817
|
810
|
cand, null, this.newJingleErrorHandler(cand), IQ_TIMEOUT);
|
818
|
811
|
}
|
819
|
812
|
|
820
|
|
- /**
|
821
|
|
- * Sends Jingle 'session-info' message which includes custom Jitsi Meet
|
822
|
|
- * 'ice-state' element with the text value 'failed' to let Jicofo know
|
823
|
|
- * that the ICE connection has entered the failed state. It can then
|
824
|
|
- * choose to re-create JVB channels and send 'transport-replace' to
|
825
|
|
- * retry the connection.
|
826
|
|
- */
|
827
|
|
- sendIceFailedNotification() {
|
828
|
|
- const sessionInfo
|
829
|
|
- = $iq({
|
830
|
|
- to: this.remoteJid,
|
831
|
|
- type: 'set' })
|
832
|
|
- .c('jingle', { xmlns: 'urn:xmpp:jingle:1',
|
833
|
|
- action: 'session-info',
|
834
|
|
- initiator: this.initiatorJid,
|
835
|
|
- sid: this.sid })
|
836
|
|
- .c('ice-state', { xmlns: 'http://jitsi.org/protocol/focus' })
|
837
|
|
- .t('failed')
|
838
|
|
- .up();
|
839
|
|
-
|
840
|
|
- this._bridgeSessionId
|
841
|
|
- && sessionInfo.c(
|
842
|
|
- 'bridge-session', {
|
843
|
|
- xmlns: 'http://jitsi.org/protocol/focus',
|
844
|
|
- id: this._bridgeSessionId
|
845
|
|
- });
|
846
|
|
-
|
847
|
|
- this.connection.sendIQ2(
|
848
|
|
- sessionInfo, {
|
849
|
|
- /*
|
850
|
|
- * This message will be often sent when there are connectivity
|
851
|
|
- * issues, so make it slightly longer than Prosody's default BOSH
|
852
|
|
- * inactivity timeout of 60 seconds.
|
853
|
|
- */
|
854
|
|
- timeout: 65
|
855
|
|
- })
|
856
|
|
- .catch(this.newJingleErrorHandler(sessionInfo));
|
857
|
|
- }
|
858
|
|
-
|
859
|
813
|
/**
|
860
|
814
|
* {@inheritDoc}
|
861
|
815
|
*/
|
|
@@ -1233,111 +1187,6 @@ export default class JingleSessionPC extends JingleSession {
|
1233
|
1187
|
}
|
1234
|
1188
|
}
|
1235
|
1189
|
|
1236
|
|
- /* eslint-enable max-params */
|
1237
|
|
-
|
1238
|
|
- /**
|
1239
|
|
- * Although it states "replace transport" it does accept full Jingle offer
|
1240
|
|
- * which should contain new ICE transport details.
|
1241
|
|
- * @param jingleOfferElem an element Jingle IQ that contains new offer and
|
1242
|
|
- * transport info.
|
1243
|
|
- * @param success callback called when we succeed to accept new offer.
|
1244
|
|
- * @param failure function(error) called when we fail to accept new offer.
|
1245
|
|
- */
|
1246
|
|
- replaceTransport(jingleOfferElem, success, failure) {
|
1247
|
|
- if (this.options.enableForcedReload) {
|
1248
|
|
- const sdp = new SDP(this.peerconnection.localDescription.sdp);
|
1249
|
|
-
|
1250
|
|
- this.sendTransportAccept(sdp, success, failure);
|
1251
|
|
- this.room.eventEmitter.emit(XMPPEvents.CONNECTION_RESTARTED, this);
|
1252
|
|
-
|
1253
|
|
- return;
|
1254
|
|
- }
|
1255
|
|
- this.room.eventEmitter.emit(XMPPEvents.ICE_RESTARTING, this);
|
1256
|
|
-
|
1257
|
|
- // We need to first reject the 'data' section to have the SCTP stack
|
1258
|
|
- // cleaned up to signal the known data channel is now invalid. After
|
1259
|
|
- // that the original offer is set to have the SCTP connection
|
1260
|
|
- // established with the new bridge.
|
1261
|
|
- const originalOffer = jingleOfferElem.clone();
|
1262
|
|
-
|
1263
|
|
- jingleOfferElem
|
1264
|
|
- .find('>content[name=\'data\']')
|
1265
|
|
- .attr('senders', 'rejected');
|
1266
|
|
-
|
1267
|
|
- // Remove all remote sources in order to reset the client's state
|
1268
|
|
- // for the remote MediaStreams. When a conference is moved to
|
1269
|
|
- // another bridge it will start streaming with a sequence number
|
1270
|
|
- // that is not in sync with the most recently seen by the client.
|
1271
|
|
- // The symptoms include frozen or black video and lots of "failed to
|
1272
|
|
- // unprotect SRTP packets" in Chrome logs.
|
1273
|
|
- jingleOfferElem
|
1274
|
|
- .find('>content>description>source')
|
1275
|
|
- .remove();
|
1276
|
|
- jingleOfferElem
|
1277
|
|
- .find('>content>description>ssrc-group')
|
1278
|
|
- .remove();
|
1279
|
|
-
|
1280
|
|
- // On the JVB it's not a real ICE restart and all layers are re-initialized from scratch as Jicofo does
|
1281
|
|
- // the restart by re-allocating new channels. Chrome (or WebRTC stack) needs to have the DTLS transport layer
|
1282
|
|
- // reset to start a new handshake with fresh DTLS transport on the bridge. Make it think that the DTLS
|
1283
|
|
- // fingerprint has changed by setting an all zeros key.
|
1284
|
|
- const newFingerprint = jingleOfferElem.find('>content>transport>fingerprint');
|
1285
|
|
-
|
1286
|
|
- newFingerprint.attr('hash', 'sha-1');
|
1287
|
|
- newFingerprint.text('00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00');
|
1288
|
|
-
|
1289
|
|
- const workFunction = finishedCallback => {
|
1290
|
|
- // First set an offer with a rejected 'data' section
|
1291
|
|
- this.setOfferAnswerCycle(
|
1292
|
|
- jingleOfferElem,
|
1293
|
|
- () => {
|
1294
|
|
- // Now set the original offer(with the 'data' section)
|
1295
|
|
- this.setOfferAnswerCycle(
|
1296
|
|
- originalOffer,
|
1297
|
|
- () => {
|
1298
|
|
- const localSDP = new SDP(this.peerconnection.localDescription.sdp);
|
1299
|
|
-
|
1300
|
|
- if (typeof this.options.channelLastN === 'number' && this.options.channelLastN >= 0) {
|
1301
|
|
- localSDP.initialLastN = this.options.channelLastN;
|
1302
|
|
- }
|
1303
|
|
-
|
1304
|
|
- this.sendTransportAccept(localSDP, success, failure);
|
1305
|
|
-
|
1306
|
|
- this.room.eventEmitter.emit(
|
1307
|
|
- XMPPEvents.ICE_RESTART_SUCCESS,
|
1308
|
|
- this,
|
1309
|
|
- originalOffer);
|
1310
|
|
-
|
1311
|
|
- finishedCallback();
|
1312
|
|
- }, error => finishedCallback(error)
|
1313
|
|
- );
|
1314
|
|
- }, error => finishedCallback(error)
|
1315
|
|
- );
|
1316
|
|
- };
|
1317
|
|
-
|
1318
|
|
- logger.debug(`${this} Queued ICE restart task`);
|
1319
|
|
-
|
1320
|
|
- // Queue and execute
|
1321
|
|
- this.modificationQueue.push(
|
1322
|
|
- workFunction,
|
1323
|
|
- error => {
|
1324
|
|
- if (error) {
|
1325
|
|
- if (error instanceof ClearedQueueError) {
|
1326
|
|
- // The session might have been terminated before the task was executed, making it obsolete.
|
1327
|
|
- logger.debug(`${this} ICE restart task aborted: session terminated`);
|
1328
|
|
- success();
|
1329
|
|
-
|
1330
|
|
- return;
|
1331
|
|
- }
|
1332
|
|
- logger.error(`${this} ICE restart task failed: ${error}`);
|
1333
|
|
- failure(error);
|
1334
|
|
- } else {
|
1335
|
|
- logger.debug(`${this} ICE restart task done`);
|
1336
|
|
- success();
|
1337
|
|
- }
|
1338
|
|
- });
|
1339
|
|
- }
|
1340
|
|
-
|
1341
|
1190
|
/**
|
1342
|
1191
|
* Sends Jingle 'session-accept' message.
|
1343
|
1192
|
* @param {function()} success callback called when we receive 'RESULT'
|
|
@@ -1474,83 +1323,6 @@ export default class JingleSessionPC extends JingleSession {
|
1474
|
1323
|
}
|
1475
|
1324
|
}
|
1476
|
1325
|
|
1477
|
|
- /**
|
1478
|
|
- * Sends Jingle 'transport-accept' message which is a response to
|
1479
|
|
- * 'transport-replace'.
|
1480
|
|
- * @param localSDP the 'SDP' object with local session description
|
1481
|
|
- * @param success callback called when we receive 'RESULT' packet for
|
1482
|
|
- * 'transport-replace'
|
1483
|
|
- * @param failure function(error) called when we receive an error response
|
1484
|
|
- * or when the request has timed out.
|
1485
|
|
- * @private
|
1486
|
|
- */
|
1487
|
|
- sendTransportAccept(localSDP, success, failure) {
|
1488
|
|
- const transportAccept = $iq({ to: this.remoteJid,
|
1489
|
|
- type: 'set' })
|
1490
|
|
- .c('jingle', {
|
1491
|
|
- xmlns: 'urn:xmpp:jingle:1',
|
1492
|
|
- action: 'transport-accept',
|
1493
|
|
- initiator: this.initiatorJid,
|
1494
|
|
- sid: this.sid
|
1495
|
|
- });
|
1496
|
|
-
|
1497
|
|
- localSDP.media.forEach((medialines, idx) => {
|
1498
|
|
- const mline = SDPUtil.parseMLine(medialines.split('\r\n')[0]);
|
1499
|
|
-
|
1500
|
|
- transportAccept.c('content',
|
1501
|
|
- {
|
1502
|
|
- creator:
|
1503
|
|
- this.initiatorJid === this.localJid
|
1504
|
|
- ? 'initiator'
|
1505
|
|
- : 'responder',
|
1506
|
|
- name: mline.media
|
1507
|
|
- }
|
1508
|
|
- );
|
1509
|
|
- localSDP.transportToJingle(idx, transportAccept);
|
1510
|
|
- transportAccept.up();
|
1511
|
|
- });
|
1512
|
|
-
|
1513
|
|
- logger.info(`${this} Sending transport-accept`);
|
1514
|
|
- logger.debug(transportAccept.tree());
|
1515
|
|
-
|
1516
|
|
- this.connection.sendIQ(transportAccept,
|
1517
|
|
- success,
|
1518
|
|
- this.newJingleErrorHandler(transportAccept, failure),
|
1519
|
|
- IQ_TIMEOUT);
|
1520
|
|
- }
|
1521
|
|
-
|
1522
|
|
- /**
|
1523
|
|
- * Sends Jingle 'transport-reject' message which is a response to
|
1524
|
|
- * 'transport-replace'.
|
1525
|
|
- * @param success callback called when we receive 'RESULT' packet for
|
1526
|
|
- * 'transport-replace'
|
1527
|
|
- * @param failure function(error) called when we receive an error response
|
1528
|
|
- * or when the request has timed out.
|
1529
|
|
- *
|
1530
|
|
- * FIXME method should be marked as private, but there's some spaghetti that
|
1531
|
|
- * needs to be fixed prior doing that
|
1532
|
|
- */
|
1533
|
|
- sendTransportReject(success, failure) {
|
1534
|
|
- // Send 'transport-reject', so that the focus will
|
1535
|
|
- // know that we've failed
|
1536
|
|
- const transportReject = $iq({ to: this.remoteJid,
|
1537
|
|
- type: 'set' })
|
1538
|
|
- .c('jingle', {
|
1539
|
|
- xmlns: 'urn:xmpp:jingle:1',
|
1540
|
|
- action: 'transport-reject',
|
1541
|
|
- initiator: this.initiatorJid,
|
1542
|
|
- sid: this.sid
|
1543
|
|
- });
|
1544
|
|
-
|
1545
|
|
- logger.info(`${this} Sending 'transport-reject'`);
|
1546
|
|
- logger.debug(transportReject.tree());
|
1547
|
|
-
|
1548
|
|
- this.connection.sendIQ(transportReject,
|
1549
|
|
- success,
|
1550
|
|
- this.newJingleErrorHandler(transportReject, failure),
|
1551
|
|
- IQ_TIMEOUT);
|
1552
|
|
- }
|
1553
|
|
-
|
1554
|
1326
|
/**
|
1555
|
1327
|
* Sets the resolution constraint on the local camera track.
|
1556
|
1328
|
* @param {number} maxFrameHeight - The user preferred max frame height.
|