即使我们确切知道连接的路由,缓存 ICE 候选者和 sdp 是否也不起作用?
Would caching ICE candidates and sdp not work even if we know exactly the route of the connection?
我知道在 P2P 和更动态的环境中缓存 ICE 候选和 sdp 不是一个好的做法,因为你缓存的东西可能无法申请下一个 WebRTC 连接。但是在我们确切知道连接路线应该如何的情况下呢?
更具体地说,
- 假设我们有 1 个 TURN 服务器(没有负载平衡,所以那里没有内部路由)
- 和 2 个具有固定 IP 的对等点希望不时连接 WebRTC。
在这种情况下,我们确切地知道对等方的 IP 是什么,并且我们确切地知道 TURN 服务器的 IP 是什么(假设它不会改变),是否可以缓存 ICE 候选者( TURN) 和 SDP 或部分 SDP 只是为了绕过 ICE 候选和 SDP 交换部分?
没有。提议和答案不仅仅包含 如何 联系。它们包含此连接 实例 的唯一指纹,因为可以在相同的两个已知 IP 之间建立任意数量的安全连接,甚至可以同时建立。
比较来自两个不同 RTCPeerConnection 对象的 createOffer() 结果,您会发现它们不同。除了指纹,它们还包含本地 RTCPeerConnection 决定 send/receive 个人媒体的哪些端口,这可能会有所不同。
要使用较早的缓存版本,您不仅需要告诉远程 RTCPeerConnection 对象要使用的端口,还需要告诉您本地的端口。这显然是行不通的:
const [pc1, pc2, pc3] = [1,2,3].map(() => new RTCPeerConnection());
(async () => {
try {
[pc1, pc2].forEach(pc => pc.createDataChannel("dummy"));
pc3.ondatachannel = () => console.log("pc3 ondatachannel");
await pc1.createOffer();
await pc1.setLocalDescription(await pc2.createOffer()); // Uh oh! pc2 not pc1
await pc3.setRemoteDescription(pc1.localDescription);
await pc3.setLocalDescription(await pc3.createAnswer());
await pc1.setRemoteDescription(pc3.localDescription);
} catch (e) {
console.log(e);
}
})();
pc1.onicecandidate = e => pc3.addIceCandidate(e.candidate);
pc3.onicecandidate = e => pc1.addIceCandidate(e.candidate);
pc1.oniceconnectionstatechange = e => console.log(pc1.iceConnectionState);
pc3.ontrack = e => video.srcObject = e.streams[0];
在最新的 Chrome 中产生:
InvalidModificationError: The SDP does not match the previously generated SDP for this type
...这是正确的,因为最新的 WebRTC 规范禁止在 createOffer 和 setLocalDescription.
之间进行 SDP 修改
在 Firefox 中,协商实际完成,但没有触发媒体或数据通道事件。
即使使用 TURN 服务器,也无法解决指纹不匹配的问题。
我知道在 P2P 和更动态的环境中缓存 ICE 候选和 sdp 不是一个好的做法,因为你缓存的东西可能无法申请下一个 WebRTC 连接。但是在我们确切知道连接路线应该如何的情况下呢?
更具体地说,
- 假设我们有 1 个 TURN 服务器(没有负载平衡,所以那里没有内部路由)
- 和 2 个具有固定 IP 的对等点希望不时连接 WebRTC。
在这种情况下,我们确切地知道对等方的 IP 是什么,并且我们确切地知道 TURN 服务器的 IP 是什么(假设它不会改变),是否可以缓存 ICE 候选者( TURN) 和 SDP 或部分 SDP 只是为了绕过 ICE 候选和 SDP 交换部分?
没有。提议和答案不仅仅包含 如何 联系。它们包含此连接 实例 的唯一指纹,因为可以在相同的两个已知 IP 之间建立任意数量的安全连接,甚至可以同时建立。
比较来自两个不同 RTCPeerConnection 对象的 createOffer() 结果,您会发现它们不同。除了指纹,它们还包含本地 RTCPeerConnection 决定 send/receive 个人媒体的哪些端口,这可能会有所不同。
要使用较早的缓存版本,您不仅需要告诉远程 RTCPeerConnection 对象要使用的端口,还需要告诉您本地的端口。这显然是行不通的:
const [pc1, pc2, pc3] = [1,2,3].map(() => new RTCPeerConnection());
(async () => {
try {
[pc1, pc2].forEach(pc => pc.createDataChannel("dummy"));
pc3.ondatachannel = () => console.log("pc3 ondatachannel");
await pc1.createOffer();
await pc1.setLocalDescription(await pc2.createOffer()); // Uh oh! pc2 not pc1
await pc3.setRemoteDescription(pc1.localDescription);
await pc3.setLocalDescription(await pc3.createAnswer());
await pc1.setRemoteDescription(pc3.localDescription);
} catch (e) {
console.log(e);
}
})();
pc1.onicecandidate = e => pc3.addIceCandidate(e.candidate);
pc3.onicecandidate = e => pc1.addIceCandidate(e.candidate);
pc1.oniceconnectionstatechange = e => console.log(pc1.iceConnectionState);
pc3.ontrack = e => video.srcObject = e.streams[0];
在最新的 Chrome 中产生:
InvalidModificationError: The SDP does not match the previously generated SDP for this type
...这是正确的,因为最新的 WebRTC 规范禁止在 createOffer 和 setLocalDescription.
之间进行 SDP 修改在 Firefox 中,协商实际完成,但没有触发媒体或数据通道事件。
即使使用 TURN 服务器,也无法解决指纹不匹配的问题。