Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebRTC: Determine which TURN server is used in PeerConnection

Scenario: You would like to know if TURN server is being used for a particular call and which one from the array of TURN servers you provided during PeerConnection creation, is being used. Right now there are two options:

  • Wireshark: But when you are behind a corporate proxy and TURN server is outside that, wireshark would show the Proxy IP as the destination.( also not the mention the inconvenience of running it in the background)
  • Going through the stats page and finding out, chrome --> chrome://webrtc-internals and Firefox --> about:webrtc

I would like to use a alternative to the above two, programmatically determine this so I do not have to leave my application page.

like image 503
mido Avatar asked Aug 21 '15 09:08

mido


People also ask

Does WebRTC require a turn server?

For most WebRTC applications to function a server is required for relaying the traffic between peers, since a direct socket is often not possible between the clients (unless they reside on the same local network). The common way to solve this is by using a TURN server.

How do I know if my server is STUN and TURN?

You can easily determine if your server works with both tools or with your own JavaScript: A STUN server works if you can gather a candidate with type "srflx" . A TURN server works if you can gather a candidate with type "relay" .

How do I check WebRTC connection?

If you're using Chrome, you can navigate to chrome://webrtc-internals . This will show you the offer, answer, ICE states, and statistics about the connection (once it has been established). Save this answer.


1 Answers

Update: I've updated the example to follow the latest spec, with maplike getStats.

The following approach follows the specification and currently only works in Firefox, because Chrome implements getStats() incorrectly at the moment. Hopefully, a version of the adapter.js polyfill should be available soon that will make this work in Chrome as well.

When you run this fiddle in Firefox, you'll see:

checking
connected
Does not use TURN

This is because the example provides both a STUN and a TURN server. But when I modify the config to use TURN only with iceTransportPolicy: "relay", I see:

checking
connected
Uses TURN server: 10.252.73.50

Note that the turn server I use is behind a VPN, so it won't work for you, but feel free to modify the fiddle with your own server (just don't save it unless you want the info to become public!)

While I haven't tested with more than one turn server, as you can see the IP address shown matches the turn server configured, so it should be possible to tell which server is used using this approach.

// Turn server is on Mozilla's VPN.
var cfg = { iceTransportPolicy: "all", // set to "relay" to force TURN.
            iceServers: [{ urls: "stun:stun.l.google.com:19302" },
                         { urls: "turn:10.252.73.50",
                           username:"webrtc", credential:"firefox" }] };
var pc1 = new RTCPeerConnection(cfg), pc2 = new RTCPeerConnection(cfg);

pc1.onicecandidate = e => pc2.addIceCandidate(e.candidate);
pc2.onicecandidate = e => pc1.addIceCandidate(e.candidate);
pc2.oniceconnectionstatechange = () => log(pc2.iceConnectionState);
pc2.onaddstream = e => v2.srcObject = e.stream;

var findSelected = stats =>
  [...stats.values()].find(s => s.type == "candidate-pair" && s.selected);

var start = () => navigator.mediaDevices.getUserMedia({ video: true })
  .then(stream => pc1.addStream(v1.srcObject = stream))
  .then(() => pc1.createOffer()).then(d => pc1.setLocalDescription(d))
  .then(() => pc2.setRemoteDescription(pc1.localDescription))
  .then(() => pc2.createAnswer()).then(d => pc2.setLocalDescription(d))
  .then(() => pc1.setRemoteDescription(pc2.localDescription))
  .then(() => waitUntil(() => pc1.getStats().then(s => findSelected(s))))
  .then(() => pc1.getStats())
  .then(stats => {
    var candidate = stats.get(findSelected(stats).localCandidateId);
    if (candidate.candidateType == "relayed") {
      log("Uses TURN server: " + candidate.ipAddress);
    } else {
      log("Does not use TURN (uses " + candidate.candidateType + ").");
    }
  })
  .catch(log);

var waitUntil = f => Promise.resolve(f())
  .then(done => done || wait(200).then(() => waitUntil(f)));

var wait = ms => new Promise(resolve => setTimeout(resolve, ms));
var log = msg => div.innerHTML += msg +"<br>";
var failed = e => log(e +", line "+ e.lineNumber);
<video id="v1" width="108" height="81" autoplay></video>
<video id="v2" width="108" height="81" autoplay></video><br>
<button onclick="start()">Start!</button><br><div id="div"></div>
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
like image 166
jib Avatar answered Oct 19 '22 08:10

jib