|
@@ -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
|
830
|
this._renegotiate(newRemoteSdp)
|
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(
|
|
@@ -1310,9 +1357,19 @@ export default class JingleSessionPC extends JingleSession {
|
1310
|
1357
|
* rejects with an error {string}
|
1311
|
1358
|
*/
|
1312
|
1359
|
_renegotiate(optionalRemoteSdp) {
|
|
1360
|
+ const currentRemoteSdp = this.peerconnection.remoteDescription.sdp;
|
|
1361
|
+
|
|
1362
|
+ // FIXME new SDP() may not be necessary - raw SDP is needed anyway
|
1313
|
1363
|
const remoteSdp
|
1314
|
1364
|
= optionalRemoteSdp
|
1315
|
|
- || new SDP(this.peerconnection.remoteDescription.sdp);
|
|
1365
|
+ || (currentRemoteSdp && new SDP(currentRemoteSdp));
|
|
1366
|
+
|
|
1367
|
+ if (!remoteSdp) {
|
|
1368
|
+ return Promise.reject(
|
|
1369
|
+ 'Can not renegotiate without remote description,'
|
|
1370
|
+ + `- current state: ${this.state}`);
|
|
1371
|
+ }
|
|
1372
|
+
|
1316
|
1373
|
const remoteDescription = new RTCSessionDescription({
|
1317
|
1374
|
type: this.isInitiator ? 'answer' : 'offer',
|
1318
|
1375
|
sdp: remoteSdp.raw
|
|
@@ -1461,7 +1518,8 @@ export default class JingleSessionPC extends JingleSession {
|
1461
|
1518
|
this.peerconnection.addTrack(newTrack);
|
1462
|
1519
|
}
|
1463
|
1520
|
|
1464
|
|
- if ((oldTrack || newTrack) && oldLocalSdp) {
|
|
1521
|
+ if ((oldTrack || newTrack)
|
|
1522
|
+ && this.state === JingleSessionState.ACTIVE) {
|
1465
|
1523
|
this._renegotiate()
|
1466
|
1524
|
.then(() => {
|
1467
|
1525
|
const newLocalSDP
|