11

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 connection working cross-browser have been taken into consideration, e.g:

  • Waiting until all candidates have been gathered before sending an SDP on Chrome browsers
  • Sending candidates as soon as they are gathered and adding them to the remote connection once a local sdp has been set
  • adding candidates once both a local and remote description have been set (for both remote and local)
  • adding offer candidates upon receive and sending candidates back with an answer
  • resetting the peer connection upon ice failure
  • others (in a rush)

Basically I am asking for somebody to help out with maybe a diagram or step by step of the process in which ice SHOULD be handled in order to have a working solution for both chrome and firefox cross-browser (both up to date as of current posting time).

I have burned myself out of thinking of any other possibilities at this point and any help would be greatly appreciated.

Thanks, Dec :)

3
  • 1
    Without seeing all the code, it's hard to help out. O'Reilly has a free WebRTC e-book with code exapmles that might help you grok the flow .... it-ebooks.info/book/3287 Commented Apr 16, 2015 at 15:03
  • @mtbikemike I've followed the flow/examples within that book and had no luck creating a stable client :(. However I found it to be a really interesting/well written book, thank you :)
    – Dec Murphy
    Commented Apr 22, 2015 at 13:34
  • did you find a good strategy, problem is ice candidates are sent irrelevant of the fact that wether remote peer has set its remoteDescription. So only thing I can think of is to either delay sending on userA side by not setting local description or store them in stack at userB side until remoteDescription has been set. Commented Sep 26, 2017 at 15:54

2 Answers 2

16

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.

1
  • i feel this doesn't answer the question, how do you send ice candidates in trickle approach that doesn't cause error. As soon as you setLocal Description browser starts sending ice messages. and Since at remote peer there is different handlers for sdp msg and ice msg, what happens is that even before sent spd msg is set as remote, lot of ice candidates already have arrived and crashed. So yea how do you handle that. From strategies OP listed i've tried #3, and stack implementation (i put all ice candidates in stack then once remoteDescription is set i add all of them) Commented Sep 26, 2017 at 15:50
6

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))
3
  • I feel this is a hack though, and dont know how waiting for empty candidate indicate that it's right time to start adding ice candidates. Commented Sep 26, 2017 at 15:51
  • 2
    I believe the 'empty ice candidates indicates all have been discovered' behaviour is in the specification. I would not have written it that way, (explicit is better than implicit) but there you go.
    – N. McA.
    Commented Oct 1, 2017 at 14:23
  • can confirm had this explained somewhere else Commented Oct 2, 2017 at 5:07

Not the answer you're looking for? Browse other questions tagged or ask your own question.