I have a webrtc app, and let's say two clients( client1
and client2
), is there any way to find out what ICE candidate given by client1
is used by client2
and vice versa? because, every time to find this out, I have to use wireshark
on both the clients, I thought reading the sdp
might help, but I was wrong, as it gives all possible candidates...
Scenario: all UDP
ports of client1 are blocked( blocked my me for testing purpose).
Client1's SDP:
...
a=rtcp:49407 IN IP4 <client1's IP>
a=candidate:3864409487 1 udp 2122194687 <client1's IP> 49407 typ host generation 0 // this would never work, since the udp ports are blocked...
a=candidate:3864409487 2 udp 2122194687 <client1's IP> 49407 typ host generation 0
a=candidate:2832583039 1 tcp 1518214911 <client1's IP> 0 typ host tcptype active generation 0
a=candidate:2832583039 2 tcp 1518214911 <client1's IP> 0 typ host tcptype active generation 0
a=candidate:973648460 1 udp 25042687 <TURN server IP> 64790 typ relay raddr <Proxy IP> rport 39963 generation 0
a=ice-ufrag:YSvrOiav8TglpCWD
...
I have a webrtc app, and let's say two clients( client1
and client2
), is there any way to find out what ICE candidate given by client1
is used by client2
and vice versa? because, every time to find this out, I have to use wireshark
on both the clients, I thought reading the sdp
might help, but I was wrong, as it gives all possible candidates...
Scenario: all UDP
ports of client1 are blocked( blocked my me for testing purpose).
Client1's SDP:
...
a=rtcp:49407 IN IP4 <client1's IP>
a=candidate:3864409487 1 udp 2122194687 <client1's IP> 49407 typ host generation 0 // this would never work, since the udp ports are blocked...
a=candidate:3864409487 2 udp 2122194687 <client1's IP> 49407 typ host generation 0
a=candidate:2832583039 1 tcp 1518214911 <client1's IP> 0 typ host tcptype active generation 0
a=candidate:2832583039 2 tcp 1518214911 <client1's IP> 0 typ host tcptype active generation 0
a=candidate:973648460 1 udp 25042687 <TURN server IP> 64790 typ relay raddr <Proxy IP> rport 39963 generation 0
a=ice-ufrag:YSvrOiav8TglpCWD
...
Share
Improve this question
edited May 22, 2015 at 7:05
mido
asked Mar 11, 2015 at 2:41
midomido
25k15 gold badges99 silver badges122 bronze badges
1
- 3 Check out this thread: groups.google.com/d/msg/discuss-webrtc/-VReEXf9RBM/h91i7CD-oJ8J – Guy S Commented Mar 11, 2015 at 16:12
3 Answers
Reset to default 10Well, taken from my answer to another question
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:
function getConnectionDetails(peerConnection){
var connectionDetails = {}; // the final result object.
if(window.chrome){ // checking if chrome
var reqFields = [ 'googLocalAddress',
'googLocalCandidateType',
'googRemoteAddress',
'googRemoteCandidateType'
];
return new Promise(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) return reject('Something is wrong...');
reqFields.forEach(function(e){connectionDetails[e.replace('goog', '')] = filtered.stat(e)});
resolve(connectionDetails);
});
});
}else{ // assuming it is firefox
return 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;
});
}
}
//usage example:
getConnectionDetails(pc).then(console.log.bind(console));
This question is very old, but here's what works reliably in 2021! - at least for me.
You can use the RTCIceTransport.getSelectedCandidatePair() method which returns an RTCIceCandidatePair object (local and remote ice-candidate pairs).
Example: To get the selected candidate pairs for sending media from a peer connection.
peerConnection.getSenders().map(sender => {
const kindOfTrack = sender.track?.kind;
if (sender.transport) {
const iceTransport = sender.transport.iceTransport;
const logSelectedCandidate = (e) => {
const selectedCandidatePair = iceTransport.getSelectedCandidatePair();
console.log(`SELECTED ${kindOfTrack || 'unknown'} SENDER CANDIDATE PAIR`, selectedCandidatePair);
};
iceTransport.onselectedcandidatepairchange = logSelectedCandidate;
logSelectedCandidate();
} else {
// retry at some time later
}
});
The above works similarly for received media on the peer connection object.
Use RTCPeerConnection.getReceivers()
instead, in that case
In chrome I used this:
let pc1 = new RTCPeerConnection(cfg);
pc1.addEventListener('connectionstatechange', async (e) => {
if (pc1.connectionState === 'connected') {
// Peers connected!
let stats = await pc1.getStats();
for (const value of stats.values()) {
if(value.type=="local-candidate" || value.type=="remote-candidate")
console.log(value);
}
}
})