Skip to content Skip to sidebar Skip to footer

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 bei

Solution 1:

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

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 notuse 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:

checkingconnectedUses 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 = newRTCPeerConnection(cfg), pc2 = newRTCPeerConnection(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;

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

varstart = () => 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);

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

varwait = ms => newPromise(resolve =>setTimeout(resolve, ms));
varlog = msg => div.innerHTML += msg +"<br>";
varfailed = e => log(e +", line "+ e.lineNumber);
<videoid="v1"width="108"height="81"autoplay></video><videoid="v2"width="108"height="81"autoplay></video><br><buttononclick="start()">Start!</button><br><divid="div"></div><scriptsrc="https://webrtc.github.io/adapter/adapter-latest.js"></script>

Solution 2:

I wrote and tested the below piece of code, works in latest versions of both firefox and chrome, getConnectionDetails returns a promise which resolves to connection details:

functiongetConnectionDetails(peerConnection){


  var connectionDetails = {};   // the final result object.if(window.chrome){  // checking if chromevar reqFields = [   'googLocalAddress',
                        'googLocalCandidateType',   
                        'googRemoteAddress',
                        'googRemoteCandidateType'
                    ];
    returnnewPromise(function(resolve, reject){
      peerConnection.getStats(function(stats){
        var filtered = stats.result().filter(function(e){return e.id.indexOf('Conn-audio')==0 && e.stat('googActiveConnection')=='true'})[0];
        if(!filtered) returnreject('Something is wrong...');
        reqFields.forEach(function(e){connectionDetails[e.replace('goog', '')] = filtered.stat(e)});
        resolve(connectionDetails);
      });
    });

  }else{  // assuming it is firefoxreturn peerConnection.getStats(null).then(function(stats){
        var selectedCandidatePair = stats[Object.keys(stats).filter(function(key){return stats[key].selected})[0]]
          , localICE = stats[selectedCandidatePair.localCandidateId]
          , remoteICE = stats[selectedCandidatePair.remoteCandidateId];
        connectionDetails.LocalAddress = [localICE.ipAddress, localICE.portNumber].join(':');
        connectionDetails.RemoteAddress = [remoteICE.ipAddress, remoteICE.portNumber].join(':');
        connectionDetails.LocalCandidateType = localICE.candidateType;
        connectionDetails.RemoteCandidateType = remoteICE.candidateType;
        return connectionDetails;
    });

  }
}

I would like point out one thing, all these three methods fail in one scenario: two turn servers running from same machine on different ports, only reliable way I found was looking at the turn server logs.

Post a Comment for "Webrtc: Determine Which Turn Server Is Used In Peerconnection"