Call establishment improvements.
1. More orderly offer-answer exchange sequence. 2. Cache remote ICE candidates that arrive before call establishment is complete (we use trickle ICE).
This commit is contained in:
@@ -32,22 +32,29 @@ class CallPanel extends React.PureComponent {
|
|||||||
pc: undefined,
|
pc: undefined,
|
||||||
|
|
||||||
previousOnInfo: undefined,
|
previousOnInfo: undefined,
|
||||||
waitingForPeer: false
|
waitingForPeer: false,
|
||||||
|
// If true, the client has received a remote SDP from the peer and has sent a local SDP to the peer.
|
||||||
|
callInitialSetupComplete: false
|
||||||
};
|
};
|
||||||
|
|
||||||
this.localStreamConstraints = {
|
this.localStreamConstraints = {
|
||||||
audio: true,
|
audio: true,
|
||||||
video: true
|
video: true
|
||||||
};
|
};
|
||||||
|
this.isOutgoingCall = props.callState == CALL_STATE_OUTGOING_INITATED;
|
||||||
|
|
||||||
this.localRef = React.createRef();
|
this.localRef = React.createRef();
|
||||||
this.remoteRef = React.createRef();
|
this.remoteRef = React.createRef();
|
||||||
|
// Cache for remote ice candidates until initial setup gets completed.
|
||||||
|
this.remoteIceCandidatesCache = [];
|
||||||
|
|
||||||
this.onInfo = this.onInfo.bind(this);
|
this.onInfo = this.onInfo.bind(this);
|
||||||
this.start = this.start.bind(this);
|
this.start = this.start.bind(this);
|
||||||
this.stop = this.stop.bind(this);
|
this.stop = this.stop.bind(this);
|
||||||
|
|
||||||
this.createPeerConnection = this.createPeerConnection.bind(this);
|
this.createPeerConnection = this.createPeerConnection.bind(this);
|
||||||
|
this.canSendOffer = this.canSendOffer.bind(this);
|
||||||
|
this.drainRemoteIceCandidatesCache = this.drainRemoteIceCandidatesCache.bind(this);
|
||||||
|
|
||||||
this.handleNegotiationNeededEvent = this.handleNegotiationNeededEvent.bind(this);
|
this.handleNegotiationNeededEvent = this.handleNegotiationNeededEvent.bind(this);
|
||||||
this.handleICECandidateEvent = this.handleICECandidateEvent.bind(this);
|
this.handleICECandidateEvent = this.handleICECandidateEvent.bind(this);
|
||||||
@@ -219,14 +226,25 @@ class CallPanel extends React.PureComponent {
|
|||||||
// Configure the remote description, which is the SDP payload
|
// Configure the remote description, which is the SDP payload
|
||||||
// in 'info' message.
|
// in 'info' message.
|
||||||
const desc = new RTCSessionDescription(info.payload);
|
const desc = new RTCSessionDescription(info.payload);
|
||||||
this.state.pc.setRemoteDescription(desc).catch(this.reportError);
|
this.state.pc.setRemoteDescription(desc)
|
||||||
|
.then(_ => {
|
||||||
|
this.setState({ callInitialSetupComplete: true }, () => this.drainRemoteIceCandidatesCache());
|
||||||
|
})
|
||||||
|
.catch(this.reportError);
|
||||||
}
|
}
|
||||||
|
|
||||||
reportError(err) {
|
reportError(err) {
|
||||||
this.props.onError(err.message, 'err');
|
this.props.onError(err.message, 'err');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
canSendOffer() {
|
||||||
|
return this.isOutgoingCall || this.state.callInitialSetupComplete;
|
||||||
|
}
|
||||||
|
|
||||||
handleNegotiationNeededEvent() {
|
handleNegotiationNeededEvent() {
|
||||||
|
if (!this.canSendOffer()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.state.pc.createOffer().then(offer => {
|
this.state.pc.createOffer().then(offer => {
|
||||||
return this.state.pc.setLocalDescription(offer);
|
return this.state.pc.setLocalDescription(offer);
|
||||||
})
|
})
|
||||||
@@ -244,8 +262,20 @@ class CallPanel extends React.PureComponent {
|
|||||||
|
|
||||||
handleNewICECandidateMsg(info) {
|
handleNewICECandidateMsg(info) {
|
||||||
const candidate = new RTCIceCandidate(info.payload);
|
const candidate = new RTCIceCandidate(info.payload);
|
||||||
this.state.pc.addIceCandidate(candidate)
|
if (this.state.callInitialSetupComplete) {
|
||||||
.catch(this.reportError);
|
this.state.pc.addIceCandidate(candidate)
|
||||||
|
.catch(this.reportError);
|
||||||
|
} else {
|
||||||
|
this.remoteIceCandidatesCache.push(candidate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drainRemoteIceCandidatesCache() {
|
||||||
|
this.remoteIceCandidatesCache.forEach(candidate => {
|
||||||
|
this.state.pc.addIceCandidate(candidate)
|
||||||
|
.catch(this.reportError);
|
||||||
|
});
|
||||||
|
this.remoteIceCandidatesCache = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
handleICEConnectionStateChangeEvent(event) {
|
handleICEConnectionStateChangeEvent(event) {
|
||||||
@@ -320,6 +350,7 @@ class CallPanel extends React.PureComponent {
|
|||||||
})
|
})
|
||||||
.then(_ => {
|
.then(_ => {
|
||||||
this.props.onSendAnswer(this.props.topic, this.props.seq, pc.localDescription.toJSON());
|
this.props.onSendAnswer(this.props.topic, this.props.seq, pc.localDescription.toJSON());
|
||||||
|
this.setState({ callInitialSetupComplete: true }, () => this.drainRemoteIceCandidatesCache());
|
||||||
})
|
})
|
||||||
.catch(this.handleGetUserMediaError);
|
.catch(this.handleGetUserMediaError);
|
||||||
}
|
}
|
||||||
|
|||||||
+316
-456
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+56
-89
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user