WebRTC:确定PeerConnection中使用的TURN服务器
WebRTC: Determine which TURN server is used in PeerConnection
场景:您想知道TURN服务器是否被用于特定的调用,以及在PeerConnection创建期间提供的TURN服务器数组中哪一个正在被使用。现在有两个选项:
- Wireshark:但是当你在一个公司代理和TURN服务器是在外面,Wireshark会显示代理IP作为目的地。(更不用说在后台运行的不便)
- 浏览统计页面并找出,chrome -> chrome://webrtc-internals和Firefox -> about:webrtc
我想使用上述两个的替代方案,通过编程确定这一点,这样我就不必离开我的应用程序页面。
更新:我已经更新了示例以遵循最新规范,使用mappllike getStats
。
以下方法遵循规范,目前只适用于Firefox,因为Chrome目前不正确地实现了getStats()
。希望,一个版本的适配器.js polyfill应该很快可用,将使这项工作在Chrome以及。
当你在Firefox中运行这段代码时,你会看到:
checking
connected
Does not use TURN
这是因为该示例同时提供了一个STUN和一个TURN服务器。但是当我修改配置仅使用iceTransportPolicy: "relay"
的TURN时,我看到:
checking
connected
Uses TURN server: 10.252.73.50
请注意,我使用的转弯服务器是在VPN后面,所以它不会为你工作,但你可以随意修改你自己的服务器(只是不要保存它,除非你想让信息成为公共的!)
虽然我没有使用多个回合服务器进行测试,但正如您可以看到的,显示的IP地址与配置的回合服务器相匹配,因此应该可以使用这种方法来告诉使用哪个服务器。
// 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>
我编写并测试了以下代码,适用于最新版本的firefox和chrome, getConnectionDetails
返回一个解决连接细节的承诺:
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;
});
}
}
我想指出一件事,所有这三种方法在一种情况下都失败了:两个回合服务器从同一台机器在不同的端口上运行,我发现唯一可靠的方法是查看回合服务器日志。
相关文章:
- 使用JSP从服务器检索和显示图像
- 如何使用skip参数使用angular ui引导进行服务器端分页
- 客户端服务器REST API captcha实现
- 正在将base64 jpeg从input-type=file上传到服务器
- Webpack开发服务器和React服务器端渲染
- 提示使用服务器端事件处理程序激活JavaScript
- 使用谷歌应用程序脚本将服务器端数据表返回到客户端
- 如何使用Socket.io将命令从客户端发送到服务器
- jQuery blueimp文件上传:将N-1个文件上传到IE中的服务器
- 使用jasmine模拟对服务器的调用
- 如何轻松地将服务器端变量从Java代码转移到客户端代码
- 从客户端获取修改后的对象,并将其与服务器上的原始对象组合
- 通过ajax将坐标传递到php服务器端,并在处理后检索到javascript
- 如何使用Javascript将空数组发送到PHP服务器
- 如何在HTML中显示服务器对象变量
- 如何配置分析以将数据发送到我自己的服务器
- WebRTC:强制对等方使用TURN服务器
- WebRTC如何决定使用哪些TURN服务器
- WEBRTC:在RtcPeerConnection创建后添加stun/turn服务器配置
- WebRTC:确定PeerConnection中使用的TURN服务器