I have exhausted all possibilities to get a stable WebRTC implementation working and am looking to get some advice.
All possible solutions to handling a working connecti
I found this function useful in your situation :)
function waitForAllICE(pc) {
return new Promise((fufill, reject) => {
pc.onicecandidate = (iceEvent) => {
if (iceEvent.candidate === null) fufill()
}
setTimeout(() => reject("Waited a long time for ice candidates..."), 10000)
})
}
You can then do, for something along the lines of
pc.createOffer()
.then(offer => pc.setLocalDescription(offer))
.then( () => waitForAllICE(pc))
.then( () => signallingWire.send(pc.localDescription))
.catch( e => smartErrorHandling(e))
I sympathise with your frustrations.
For a RTCPeerConnection, after you call createOffer() and then setLocalDescription(), the ICE agent will start to gather ICE candidates. At this point you can decide whether to make use of Trickle ICE, where candidates are sent to the remote peer as soon as they are made available, or you can wait for all the candidates to be gathered (most of the tutorials I've come across seem to assume the trickle approach, but miss some details about to handle this correctly).
Trickle approach:
A new candidate is available when a RTCPeerConnectionIceEvent is fired:
peerConnection.onicecandidate = function(newRTCPeerConnectionIceEvent) {
var newCandidate = newRTCPeerConnectionIceEvent.candidate;
// send candidate to remote via signalling channel
}
At the remote end, candidates can be added to their peer connection:
peerConnection.addIceCandidate(RTCIceCandidate);
If you haven't already called setRemoteDescription on the remote peer connection, I believe an attempt to add a candidate too early will generate an error, as this will attempt to add it to the remoteDescription when it has not been set. See this Errors when ICE Candidates are received before answer is sent.
Non-trickle approach:
You can wait for all candidates to be gathered as follows:
peerConnection.onicecandidate = function(newRTCPeerConnectionIceEvent) {
if (newRTCPeerConnectionIceEvent.candidate === null) {
// send the offer (generated previously) to the remote peer
// the offer sdp should contain all the gathered candidates
}
}
See this link for a bit more discussion on this technique: http://muaz-khan.blogspot.co.uk/2015/01/disable-ice-trickling.html (see comment at bottom of the page about generating an answer sdp when the offer already contains all candidates).
Note that the signalling mechanism may influence your approach, ie whether there is any significant latency in your signalling or not. I think the trickle approach assumes that you are using low latency signalling, as it aims to reduce the call set-up time.