How do I get information about the type of connection of a WebRTC PeerConnection?
According to the specification, which is currently implemented in Firefox, but not in Chrome, you can indeed suss out the active candidate from the statistics available for candidate pairs, which are:
dictionary RTCIceCandidatePairStats : RTCStats {
DOMString transportId;
DOMString localCandidateId;
DOMString remoteCandidateId;
RTCStatsIceCandidatePairState state;
unsigned long long priority;
boolean nominated;
boolean writable;
boolean readable;
unsigned long long bytesSent;
unsigned long long bytesReceived;
double roundTripTime;
double availableOutgoingBitrate;
double availableIncomingBitrate;
};
Combined with the stats on the individual candidates:
dictionary RTCIceCandidateAttributes : RTCStats {
DOMString ipAddress;
long portNumber;
DOMString transport;
RTCStatsIceCandidateType candidateType;
long priority;
DOMString addressSourceUrl;
};
Use peerConnection.getStats()
to look for an ice candidate pair that is both nominated and has succeeded:
pc.getStats(null))
.then(function(stats) {
return Object.keys(stats).forEach(function(key) {
if (stats[key].type == "candidatepair" &&
stats[key].nominated && stats[key].state == "succeeded") {
var remote = stats[stats[key].remoteCandidateId];
console.log("Connected to: " + remote.ipAddress +":"+
remote.portNumber +" "+ remote.transport +
" "+ remote.candidateType);
}
});
})
.catch(function(e) { console.log(e.name); });
This might output something like:
Connected to: 192.168.1.2:49190 udp host
which you could test against the LAN range. If instead it returned something like:
Connected to: 24.57.143.7:61102 udp relayed
then you'd have a TURN connection.
Here's a jsfiddle that shows this (requires Firefox Developer Edition for other reasons).
It took me a long time to get this right, so hopefully this helps someone.
The new way
You can now get the selected candidate pair from the RTCPeerConnection
without the stats api:
const pair = rtcConnection.sctp.transport.iceTransport.getSelectedCandidatePair();
console.log(pair.remote.type);
At the time of writing (October 2, 2020) this only works in Chromium however. You can still use the stats api for other browsers. Also note the comment below by jib that this only works if you have a DataChannel.
For browsers without getSelectedCandidatePair() support
According to https://developer.mozilla.org/en-US/docs/Web/API/RTCIceCandidatePairStats
(at the bottom of the page at the selected
property.
The spec-compliant way to determine the selected candidate pair is to look for a stats object of type transport, which is an RTCTransportStats object. That object's selectedCandidatePairId property indicates whether or not the specified transport is the one being used.
So trying to find the selected pair using stat.nominated && stats.state == "succeeded"
is not the right way to do it.
Instead, you can get it by looking at the selected pair in the transport
stat. Firefox doesn't support this, but fortunately there is a non-standard selected
property in candidate pairs for firefox.
const stats = await rtcConnection.getStats();
if(stats){
let selectedPairId = null;
for(const [key, stat] of stats){
if(stat.type == "transport"){
selectedPairId = stat.selectedCandidatePairId;
break;
}
}
let candidatePair = stats.get(selectedPairId);
if(!candidatePair){
for(const [key, stat] of stats){
if(stat.type == "candidate-pair" && stat.selected){
candidatePair = stat;
break;
}
}
}
if(candidatePair){
for(const [key, stat] of stats){
if(key == candidatePair.remoteCandidateId){
return stat.candidateType;
}
}
}
}