Explorar el Código

Merge pull request #504 from jitsi/misc_session_fixes

Misc session fixes
dev1
Saúl Ibarra Corretgé hace 7 años
padre
commit
05a30aaae1

+ 47
- 42
JitsiConference.js Ver fichero

@@ -6,7 +6,6 @@ import ConnectionQuality from './modules/connectivity/ConnectionQuality';
6 6
 import { getLogger } from 'jitsi-meet-logger';
7 7
 import GlobalOnErrorHandler from './modules/util/GlobalOnErrorHandler';
8 8
 import EventEmitter from 'events';
9
-import * as JingleSessionState from './modules/xmpp/JingleSessionState';
10 9
 import * as JitsiConferenceErrors from './JitsiConferenceErrors';
11 10
 import JitsiConferenceEventManager from './JitsiConferenceEventManager';
12 11
 import * as JitsiConferenceEvents from './JitsiConferenceEvents';
@@ -1235,8 +1234,6 @@ JitsiConference.prototype.onTransportInfo = function(session, transportInfo) {
1235 1234
  * @param {JitsiRemoteTrack} removedTrack
1236 1235
  */
1237 1236
 JitsiConference.prototype.onRemoteTrackRemoved = function(removedTrack) {
1238
-    let consumed = false;
1239
-
1240 1237
     this.getParticipants().forEach(participant => {
1241 1238
         const tracks = participant.getTracks();
1242 1239
 
@@ -1253,29 +1250,10 @@ JitsiConference.prototype.onRemoteTrackRemoved = function(removedTrack) {
1253 1250
                     this.transcriber.removeTrack(removedTrack);
1254 1251
                 }
1255 1252
 
1256
-                consumed = true;
1257
-
1258 1253
                 break;
1259 1254
             }
1260 1255
         }
1261 1256
     }, this);
1262
-
1263
-    if (!consumed) {
1264
-        if ((this.isP2PActive() && !removedTrack.isP2P)
1265
-             || (!this.isP2PActive() && removedTrack.isP2P)) {
1266
-            // A remote track can be removed either as a result of
1267
-            // 'source-remove' or the P2P logic which removes remote tracks
1268
-            // explicitly when switching between JVB and P2P connections.
1269
-            // The check above filters out the P2P logic case which should not
1270
-            // result in an error (which just goes over all remote tracks).
1271
-            return;
1272
-        }
1273
-        logger.error(
1274
-            'Failed to match remote track on remove'
1275
-                + ' with any of the participants',
1276
-            removedTrack.getStreamId(),
1277
-            removedTrack.getParticipantId());
1278
-    }
1279 1257
 };
1280 1258
 
1281 1259
 /**
@@ -1352,7 +1330,14 @@ JitsiConference.prototype.onIncomingCall
1352 1330
     try {
1353 1331
         jingleSession.acceptOffer(
1354 1332
             jingleOffer,
1355
-            null /* success */,
1333
+            () => {
1334
+                // If for any reason invite for the JVB session arrived after
1335
+                // the P2P has been established already the media transfer needs
1336
+                // to be turned off here.
1337
+                if (this.isP2PActive() && this.jvbJingleSession) {
1338
+                    this._suspendMediaTransferForJvbConnection();
1339
+                }
1340
+            },
1356 1341
             error => {
1357 1342
                 GlobalOnErrorHandler.callErrorHandler(error);
1358 1343
                 logger.error(
@@ -1414,13 +1399,15 @@ JitsiConference.prototype._rejectIncomingCall
1414 1399
 
1415 1400
     // Terminate  the jingle session with a reason
1416 1401
     jingleSession.terminate(
1417
-        options && options.reasonTag,
1418
-        options && options.reasonMsg,
1419 1402
         null /* success callback => we don't care */,
1420 1403
         error => {
1421 1404
             logger.warn(
1422 1405
                 'An error occurred while trying to terminate'
1423 1406
                     + ' invalid Jingle session', error);
1407
+        }, {
1408
+            reason: options.reasonTag,
1409
+            reasonDescription: options.reasonMsg,
1410
+            sendSessionTerminate: true
1424 1411
         });
1425 1412
 };
1426 1413
 
@@ -2264,7 +2251,7 @@ JitsiConference.prototype._maybeStartOrStopP2P = function(userLeftEvent) {
2264 2251
             logger.info(`Will start P2P with: ${jid}`);
2265 2252
             this._startP2PSession(jid);
2266 2253
         }
2267
-    } else if (isModerator && this.p2pJingleSession && !shouldBeInP2P) {
2254
+    } else if (this.p2pJingleSession && !shouldBeInP2P) {
2268 2255
         logger.info(`Will stop P2P with: ${this.p2pJingleSession.peerjid}`);
2269 2256
 
2270 2257
         // Log that there will be a switch back to the JVB connection
@@ -2295,7 +2282,9 @@ JitsiConference.prototype._stopP2PSession
2295 2282
 
2296 2283
     // Swap remote tracks, but only if the P2P has been fully established
2297 2284
     if (wasP2PEstablished) {
2298
-        this._resumeMediaTransferForJvbConnection();
2285
+        if (this.jvbJingleSession) {
2286
+            this._resumeMediaTransferForJvbConnection();
2287
+        }
2299 2288
 
2300 2289
         // Remove remote P2P tracks
2301 2290
         this._removeRemoteP2PTracks();
@@ -2305,23 +2294,39 @@ JitsiConference.prototype._stopP2PSession
2305 2294
     logger.info('Stopping remote stats for P2P connection');
2306 2295
     this.statistics.stopRemoteStats(this.p2pJingleSession.peerconnection);
2307 2296
     logger.info('Stopping CallStats for P2P connection');
2308
-    this.statistics.stopCallStats(
2309
-        this.p2pJingleSession.peerconnection);
2297
+    this.statistics.stopCallStats(this.p2pJingleSession.peerconnection);
2310 2298
 
2311
-    if (JingleSessionState.ENDED !== this.p2pJingleSession.state) {
2312
-        this.p2pJingleSession.terminate(
2313
-            reason ? reason : 'success',
2314
-            reasonDescription
2315
-                ? reasonDescription : 'Turing off P2P session',
2316
-            () => {
2317
-                logger.info('P2P session terminate RESULT');
2318
-            },
2319
-            error => {
2320
-                logger.warn(
2299
+    this.p2pJingleSession.terminate(
2300
+        () => {
2301
+            logger.info('P2P session terminate RESULT');
2302
+        },
2303
+        error => {
2304
+            // Because both initiator and responder are simultaneously
2305
+            // terminating their JingleSessions in case of the 'to JVB switch'
2306
+            // when 3rd participant joins, both will dispose their sessions and
2307
+            // reply with 'item-not-found' (see strophe.jingle.js). We don't
2308
+            // want to log this as an error since it's expected behaviour.
2309
+            //
2310
+            // We want them both to terminate, because in case of initiator's
2311
+            // crash the responder would stay in P2P mode until ICE fails which
2312
+            // could take up to 20 seconds.
2313
+            //
2314
+            // NOTE lack of 'reason' is considered as graceful session terminate
2315
+            // where both initiator and responder terminate their sessions
2316
+            // simultaneously.
2317
+            if (reason) {
2318
+                logger.error(
2321 2319
                     'An error occurred while trying to terminate'
2322
-                    + ' P2P Jingle session', error);
2323
-            });
2324
-    }
2320
+                        + ' P2P Jingle session', error);
2321
+            }
2322
+        }, {
2323
+            reason: reason ? reason : 'success',
2324
+            reasonDescription: reasonDescription
2325
+                ? reasonDescription : 'Turing off P2P session',
2326
+            sendSessionTerminate: this.room
2327
+                && this.getParticipantById(
2328
+                    Strophe.getResourceFromJid(this.p2pJingleSession.peerjid))
2329
+        });
2325 2330
 
2326 2331
     this.p2pJingleSession = null;
2327 2332
 

+ 1
- 1
modules/RTC/DataChannels.js Ver fichero

@@ -49,7 +49,7 @@ DataChannels.prototype.onDataChannel = function(event) {
49 49
     const self = this;
50 50
 
51 51
     dataChannel.onopen = function() {
52
-        logger.info('Data channel opened by the Videobridge!', dataChannel);
52
+        logger.info('Data channel opened by the Videobridge!');
53 53
 
54 54
         // Code sample for sending string and/or binary data
55 55
         // Sends String message to the bridge

+ 38
- 21
modules/RTC/TraceablePeerConnection.js Ver fichero

@@ -666,8 +666,7 @@ TraceablePeerConnection.prototype._createRemoteTrack
666 666
     }
667 667
     remoteTracksMap.set(mediaType, remoteTrack);
668 668
 
669
-    // FIXME not cool to use RTC's eventEmitter
670
-    this.rtc.eventEmitter.emit(RTCEvents.REMOTE_TRACK_ADDED, remoteTrack);
669
+    this.eventEmitter.emit(RTCEvents.REMOTE_TRACK_ADDED, remoteTrack);
671 670
 };
672 671
 
673 672
 /* eslint-enable max-params */
@@ -728,7 +727,7 @@ TraceablePeerConnection.prototype._remoteTrackRemoved
728 727
         return;
729 728
     }
730 729
 
731
-    if (!this._removeRemoteTrack(streamId, trackId)) {
730
+    if (!this._removeRemoteTrackById(streamId, trackId)) {
732 731
         // NOTE this warning is always printed when user leaves the room,
733 732
         // because we remove remote tracks manually on MUC member left event,
734 733
         // before the SSRCs are removed by Jicofo. In most cases it is fine to
@@ -800,6 +799,26 @@ TraceablePeerConnection.prototype.removeRemoteTracks = function(owner) {
800 799
     return removedTracks;
801 800
 };
802 801
 
802
+/**
803
+ * Removes and disposes given <tt>JitsiRemoteTrack</tt> instance. Emits
804
+ * {@link RTCEvents.REMOTE_TRACK_REMOVED}.
805
+ * @param {JitsiRemoteTrack} toBeRemoved
806
+ */
807
+TraceablePeerConnection.prototype._removeRemoteTrack = function(toBeRemoved) {
808
+    toBeRemoved.dispose();
809
+    const participantId = toBeRemoved.getParticipantId();
810
+    const remoteTracksMap = this.remoteTracks.get(participantId);
811
+
812
+    if (!remoteTracksMap) {
813
+        logger.error(
814
+            `removeRemoteTrack: no remote tracks map for ${participantId}`);
815
+    } else if (!remoteTracksMap.delete(toBeRemoved.getType())) {
816
+        logger.error(
817
+            `Failed to remove ${toBeRemoved} - type mapping messed up ?`);
818
+    }
819
+    this.eventEmitter.emit(RTCEvents.REMOTE_TRACK_REMOVED, toBeRemoved);
820
+};
821
+
803 822
 /**
804 823
  * Removes and disposes <tt>JitsiRemoteTrack</tt> identified by given stream and
805 824
  * track ids.
@@ -810,26 +829,12 @@ TraceablePeerConnection.prototype.removeRemoteTracks = function(owner) {
810 829
  * <tt>undefined</tt> if no track matching given stream and track ids was
811 830
  * found.
812 831
  */
813
-TraceablePeerConnection.prototype._removeRemoteTrack
832
+TraceablePeerConnection.prototype._removeRemoteTrackById
814 833
 = function(streamId, trackId) {
815 834
     const toBeRemoved = this._getRemoteTrackById(streamId, trackId);
816 835
 
817 836
     if (toBeRemoved) {
818
-        toBeRemoved.dispose();
819
-
820
-        const remoteTracksMap
821
-            = this.remoteTracks.get(toBeRemoved.getParticipantId());
822
-
823
-        // If _getRemoteTrackById succeeded it must be a valid value or
824
-        // we're good to crash
825
-        if (!remoteTracksMap.delete(toBeRemoved.getType())) {
826
-            logger.error(
827
-                `Failed to remove ${toBeRemoved} - type mapping messed up ?`);
828
-        }
829
-
830
-        // FIXME not cool to use RTC's eventEmitter
831
-        this.rtc.eventEmitter.emit(
832
-            RTCEvents.REMOTE_TRACK_REMOVED, toBeRemoved);
837
+        this._removeRemoteTrack(toBeRemoved);
833 838
     }
834 839
 
835 840
     return toBeRemoved;
@@ -1435,7 +1440,7 @@ TraceablePeerConnection.prototype.setLocalDescription
1435 1440
 
1436 1441
             if (localUfrag !== this.localUfrag) {
1437 1442
                 this.localUfrag = localUfrag;
1438
-                this.rtc.eventEmitter.emit(
1443
+                this.eventEmitter.emit(
1439 1444
                     RTCEvents.LOCAL_UFRAG_CHANGED, this, localUfrag);
1440 1445
             }
1441 1446
             successCallback();
@@ -1508,7 +1513,7 @@ TraceablePeerConnection.prototype.setRemoteDescription
1508 1513
 
1509 1514
             if (remoteUfrag !== this.remoteUfrag) {
1510 1515
                 this.remoteUfrag = remoteUfrag;
1511
-                this.rtc.eventEmitter.emit(
1516
+                this.eventEmitter.emit(
1512 1517
                     RTCEvents.REMOTE_UFRAG_CHANGED, this, remoteUfrag);
1513 1518
             }
1514 1519
             successCallback();
@@ -1543,6 +1548,11 @@ TraceablePeerConnection.prototype.clearRecvonlySsrc = function() {
1543 1548
     this.sdpConsistency.clearVideoSsrcCache();
1544 1549
 };
1545 1550
 
1551
+/**
1552
+ * Closes underlying WebRTC PeerConnection instance and removes all remote
1553
+ * tracks by emitting {@link RTCEvents.REMOTE_TRACK_REMOVED} for each one of
1554
+ * them.
1555
+ */
1546 1556
 TraceablePeerConnection.prototype.close = function() {
1547 1557
     this.trace('stop');
1548 1558
 
@@ -1552,6 +1562,13 @@ TraceablePeerConnection.prototype.close = function() {
1552 1562
     this.signalingLayer.off(
1553 1563
         SignalingEvents.PEER_VIDEO_TYPE_CHANGED, this._peerVideoTypeChanged);
1554 1564
 
1565
+    for (const peerTracks of this.remoteTracks.values()) {
1566
+        for (const remoteTrack of peerTracks.values()) {
1567
+            this._removeRemoteTrack(remoteTrack);
1568
+        }
1569
+    }
1570
+    this.remoteTracks.clear();
1571
+
1555 1572
     if (!this.rtc._removePeerConnection(this)) {
1556 1573
         logger.error('RTC._removePeerConnection returned false');
1557 1574
     }

+ 7
- 7
modules/xmpp/JingleSession.js Ver fichero

@@ -138,20 +138,20 @@ export default class JingleSession {
138 138
      */
139 139
     removeSources(contents) {}
140 140
 
141
-    /* eslint-disable max-params */
142
-
143 141
     /**
144 142
      * Terminates this Jingle session by sending session-terminate
145
-     * @param reason XMPP Jingle error condition
146
-     * @param text some meaningful error message
147 143
      * @param success a callback called once the 'session-terminate' packet has
148 144
      * been acknowledged with RESULT.
149 145
      * @param failure a callback called when either timeout occurs or ERROR
150 146
      * response is received.
147
+     * @param {Object} options
148
+     * @param {string} [options.reason] XMPP Jingle error condition
149
+     * @param {string} [options.reasonDescription] some meaningful error message
150
+     * @param {boolean} [options.sendSessionTerminate=true] set to false to skip
151
+     * sending session-terminate. It may not make sense to send it if the XMPP
152
+     * connection has been closed already or if the remote peer has disconnected
151 153
      */
152
-    terminate(reason, text, success, failure) {}
153
-
154
-    /* eslint-enable max-params */
154
+    terminate(success, failure, options) {}
155 155
 
156 156
     /**
157 157
      * Handles an offer from the remote peer (prepares to accept a session).

+ 118
- 47
modules/xmpp/JingleSessionPC.js Ver fichero

@@ -674,8 +674,6 @@ export default class JingleSessionPC extends JingleSession {
674 674
         this.setOfferAnswerCycle(
675 675
             jingleOffer,
676 676
             () => {
677
-                this.state = JingleSessionState.ACTIVE;
678
-
679 677
                 // FIXME we may not care about RESULT packet for session-accept
680 678
                 // then we should either call 'success' here immediately or
681 679
                 // modify sendSessionAccept method to do that
@@ -697,22 +695,49 @@ export default class JingleSessionPC extends JingleSession {
697 695
         if (!this.isInitiator) {
698 696
             throw new Error('Trying to invite from the responder session');
699 697
         }
700
-        for (const localTrack of localTracks) {
701
-            this.peerconnection.addTrack(localTrack);
702
-        }
703
-        this.peerconnection.createOffer(
704
-            this.sendSessionInitiate.bind(this),
705
-            error => logger.error('Failed to create offer', error),
706
-            this.mediaConstraints);
698
+        const workFunction = finishedCallback => {
699
+            for (const localTrack of localTracks) {
700
+                this.peerconnection.addTrack(localTrack);
701
+            }
702
+            this.peerconnection.createOffer(
703
+                sdp => {
704
+                    this.sendSessionInitiate(
705
+                        sdp,
706
+                        finishedCallback,
707
+                        finishedCallback
708
+                    );
709
+                },
710
+                error => {
711
+                    logger.error(
712
+                        'Failed to create an offer',
713
+                        error,
714
+                        this.mediaConstraints);
715
+                    finishedCallback(error);
716
+                },
717
+                this.mediaConstraints);
718
+        };
719
+
720
+        this.modificationQueue.push(
721
+            workFunction,
722
+            error => {
723
+                if (error) {
724
+                    logger.error('invite error', error);
725
+                } else {
726
+                    logger.debug('invite executed - OK');
727
+                }
728
+            });
707 729
     }
708 730
 
709 731
     /**
710 732
      * Sends 'session-initiate' to the remote peer.
711 733
      * @param {object} sdp the local session description object as defined by
712 734
      * the WebRTC standard.
735
+     * @param {function} success executed when the operation succeeds.
736
+     * @param {function(error)} failure executed when the operation fails with
737
+     * an error passed as an argument.
713 738
      * @private
714 739
      */
715
-    sendSessionInitiate(sdp) {
740
+    sendSessionInitiate(sdp, success, failure) {
716 741
         logger.log('createdOffer', sdp);
717 742
         const sendJingle = () => {
718 743
             let init = $iq({
@@ -740,12 +765,17 @@ export default class JingleSessionPC extends JingleSession {
740 765
                     logger.error('"session-initiate" error', error);
741 766
                 },
742 767
                 IQ_TIMEOUT);
768
+
769
+            // NOTE the callback is executed immediately as we don't want to
770
+            // wait for the XMPP response which would delay the startup process.
771
+            success();
743 772
         };
744 773
 
745 774
         this.peerconnection.setLocalDescription(
746 775
             sdp, sendJingle,
747 776
             error => {
748 777
                 logger.error('session-init setLocalDescription failed', error);
778
+                failure(error);
749 779
             }
750 780
         );
751 781
     }
@@ -761,7 +791,6 @@ export default class JingleSessionPC extends JingleSession {
761 791
         this.setOfferAnswerCycle(
762 792
             jingleAnswer,
763 793
             () => {
764
-                this.state = JingleSessionState.ACTIVE;
765 794
                 logger.info('setAnswer - succeeded');
766 795
             },
767 796
             error => {
@@ -795,9 +824,27 @@ export default class JingleSessionPC extends JingleSession {
795 824
 
796 825
             const newRemoteSdp
797 826
                 = this._processNewJingleOfferIq(jingleOfferAnswerIq);
827
+            const oldLocalSdp
828
+                = this.peerconnection.localDescription.sdp;
798 829
 
799
-            this._renegotiate(newRemoteSdp)
830
+            this._renegotiate(newRemoteSdp.raw)
800 831
                 .then(() => {
832
+                    if (this.state === JingleSessionState.PENDING) {
833
+                        this.state = JingleSessionState.ACTIVE;
834
+                    }
835
+
836
+                    // Old local SDP will be available when we're setting answer
837
+                    // for the first time, but not when offer and it's fine
838
+                    // since we're generating an answer now it will contain all
839
+                    // our SSRCs
840
+                    if (oldLocalSdp) {
841
+                        const newLocalSdp
842
+                            = new SDP(this.peerconnection.localDescription.sdp);
843
+
844
+                        this.notifyMySSRCUpdate(
845
+                            new SDP(oldLocalSdp), newLocalSdp);
846
+                    }
847
+
801 848
                     finishedCallback();
802 849
                 }, error => {
803 850
                     logger.error(
@@ -1004,45 +1051,51 @@ export default class JingleSessionPC extends JingleSession {
1004 1051
             IQ_TIMEOUT);
1005 1052
     }
1006 1053
 
1007
-    /* eslint-disable max-params */
1008
-
1009 1054
     /**
1010 1055
      * @inheritDoc
1011 1056
      */
1012
-    terminate(reason, text, success, failure) {
1013
-        let sessionTerminate = $iq({
1014
-            to: this.peerjid,
1015
-            type: 'set'
1016
-        })
1017
-        .c('jingle', {
1018
-            xmlns: 'urn:xmpp:jingle:1',
1019
-            action: 'session-terminate',
1020
-            initiator: this.initiator,
1021
-            sid: this.sid
1022
-        })
1023
-        .c('reason')
1024
-        .c(reason || 'success');
1025
-
1026
-        if (text) {
1027
-            // eslint-disable-next-line newline-per-chained-call
1028
-            sessionTerminate.up().c('text').t(text);
1057
+    terminate(success, failure, options) {
1058
+        if (this.state === JingleSessionState.ENDED) {
1059
+            return;
1029 1060
         }
1030 1061
 
1031
-        // Calling tree() to print something useful
1032
-        sessionTerminate = sessionTerminate.tree();
1033
-        logger.info('Sending session-terminate', sessionTerminate);
1062
+        if (!options || Boolean(options.sendSessionTerminate)) {
1063
+            let sessionTerminate
1064
+                = $iq({
1065
+                    to: this.peerjid,
1066
+                    type: 'set'
1067
+                })
1068
+                .c('jingle', {
1069
+                    xmlns: 'urn:xmpp:jingle:1',
1070
+                    action: 'session-terminate',
1071
+                    initiator: this.initiator,
1072
+                    sid: this.sid
1073
+                })
1074
+                .c('reason')
1075
+                .c((options && options.reason) || 'success');
1076
+
1077
+            if (options && options.reasonDescription) {
1078
+                sessionTerminate.up()
1079
+                    .c('text')
1080
+                    .t(options.reasonDescription);
1081
+            }
1034 1082
 
1035
-        this.connection.sendIQ(
1036
-            sessionTerminate,
1037
-            success,
1038
-            this.newJingleErrorHandler(sessionTerminate, failure), IQ_TIMEOUT);
1083
+            // Calling tree() to print something useful
1084
+            sessionTerminate = sessionTerminate.tree();
1085
+            logger.info('Sending session-terminate', sessionTerminate);
1086
+            this.connection.sendIQ(
1087
+                sessionTerminate,
1088
+                success,
1089
+                this.newJingleErrorHandler(sessionTerminate, failure),
1090
+                IQ_TIMEOUT);
1091
+        } else {
1092
+            logger.info(`Skipped sending session-terminate for ${this}`);
1093
+        }
1039 1094
 
1040 1095
         // this should result in 'onTerminated' being called by strope.jingle.js
1041 1096
         this.connection.jingle.terminate(this.sid);
1042 1097
     }
1043 1098
 
1044
-    /* eslint-enable max-params */
1045
-
1046 1099
     /**
1047 1100
      *
1048 1101
      * @param reasonCondition
@@ -1197,7 +1250,7 @@ export default class JingleSessionPC extends JingleSession {
1197 1250
                     ? this._processRemoteAddSource(addOrRemoveSsrcInfo)
1198 1251
                     : this._processRemoteRemoveSource(addOrRemoveSsrcInfo);
1199 1252
 
1200
-            this._renegotiate(newRemoteSdp)
1253
+            this._renegotiate(newRemoteSdp.raw)
1201 1254
                 .then(() => {
1202 1255
                     const newLocalSdp
1203 1256
                         = new SDP(this.peerconnection.localDescription.sdp);
@@ -1302,7 +1355,7 @@ export default class JingleSessionPC extends JingleSession {
1302 1355
 
1303 1356
     /**
1304 1357
      * Do a new o/a flow using the existing remote description
1305
-     * @param {SDP object} optionalRemoteSdp optional remote sdp
1358
+     * @param {string} [optionalRemoteSdp] optional, raw remote sdp
1306 1359
      *  to use.  If not provided, the remote sdp from the
1307 1360
      *  peerconnection will be used
1308 1361
      * @returns {Promise} promise which resolves when the
@@ -1311,11 +1364,17 @@ export default class JingleSessionPC extends JingleSession {
1311 1364
      */
1312 1365
     _renegotiate(optionalRemoteSdp) {
1313 1366
         const remoteSdp
1314
-            = optionalRemoteSdp
1315
-                || new SDP(this.peerconnection.remoteDescription.sdp);
1367
+            = optionalRemoteSdp || this.peerconnection.remoteDescription.sdp;
1368
+
1369
+        if (!remoteSdp) {
1370
+            return Promise.reject(
1371
+                'Can not renegotiate without remote description,'
1372
+                    + `- current state: ${this.state}`);
1373
+        }
1374
+
1316 1375
         const remoteDescription = new RTCSessionDescription({
1317 1376
             type: this.isInitiator ? 'answer' : 'offer',
1318
-            sdp: remoteSdp.raw
1377
+            sdp: remoteSdp
1319 1378
         });
1320 1379
 
1321 1380
         return new Promise((resolve, reject) => {
@@ -1461,7 +1520,8 @@ export default class JingleSessionPC extends JingleSession {
1461 1520
                 this.peerconnection.addTrack(newTrack);
1462 1521
             }
1463 1522
 
1464
-            if ((oldTrack || newTrack) && oldLocalSdp) {
1523
+            if ((oldTrack || newTrack)
1524
+                && this.state === JingleSessionState.ACTIVE) {
1465 1525
                 this._renegotiate()
1466 1526
                     .then(() => {
1467 1527
                         const newLocalSDP
@@ -1695,6 +1755,16 @@ export default class JingleSessionPC extends JingleSession {
1695 1755
      */
1696 1756
     setMediaTransferActive(active) {
1697 1757
         const workFunction = finishedCallback => {
1758
+
1759
+            // Because the value is modified on the queue it's impossible to
1760
+            // check it's final value reliably prior to submitting the task.
1761
+            // The rule here is that the last submitted state counts.
1762
+            // Check the value here to avoid unnecessary renegotiation cycle.
1763
+            if (this.mediaTransferActive === active) {
1764
+                finishedCallback();
1765
+
1766
+                return;
1767
+            }
1698 1768
             this.mediaTransferActive = active;
1699 1769
             if (this.peerconnection) {
1700 1770
                 this.peerconnection.setMediaTransferActive(
@@ -1844,9 +1914,10 @@ export default class JingleSessionPC extends JingleSession {
1844 1914
             // FIXME: Maybe we can include part of the session object
1845 1915
             // error.session = this;
1846 1916
 
1847
-            logger.error('Jingle error', error);
1848 1917
             if (failureCb) {
1849 1918
                 failureCb(error);
1919
+            } else {
1920
+                logger.error('Jingle error', error);
1850 1921
             }
1851 1922
         };
1852 1923
     }

+ 0
- 2
modules/xmpp/strophe.jingle.js Ver fichero

@@ -4,7 +4,6 @@ import { getLogger } from 'jitsi-meet-logger';
4 4
 const logger = getLogger(__filename);
5 5
 
6 6
 import JingleSessionPC from './JingleSessionPC';
7
-import * as JingleSessionState from './JingleSessionState';
8 7
 import XMPPEvents from '../../service/xmpp/XMPPEvents';
9 8
 import GlobalOnErrorHandler from '../util/GlobalOnErrorHandler';
10 9
 import RandomUtil from '../util/RandomUtil';
@@ -188,7 +187,6 @@ class JingleConnectionPlugin extends ConnectionPlugin {
188 187
                     = $(iq).find('>jingle>reason>:first')[0].tagName;
189 188
                 reasonText = $(iq).find('>jingle>reason>text').text();
190 189
             }
191
-            sess.state = JingleSessionState.ENDED;
192 190
             this.terminate(sess.sid, reasonCondition, reasonText);
193 191
             this.eventEmitter.emit(XMPPEvents.CALL_ENDED,
194 192
                 sess, reasonCondition, reasonText);

Loading…
Cancelar
Guardar