即使我们确切知道连接的路径,缓存ICE候选者和sdp仍然无法工作吗?

时间:2019-01-22 23:58:33

标签: javascript webrtc stun turn ice

我知道在P2P和更动态的环境中,缓存ICE候选对象和sdp并不是一个好习惯,因为缓存的内容可能无法申请下一个WebRTC连接。但是在我们确切知道连接路线应该如何的情况下呢?

更具体地说,

  1. 假设我们有1个TURN服务器(没有负载平衡,因此那里没有内部路由)
  2. 和两个具有固定IP的对等方,它们希望不时与WebRTC建立连接。

在这种情况下,我们确切地知道对等方的IP,并且我们确切地知道TURN服务器的IP(假设它不会改变),那么可以缓存ICE候选对象(TURN)吗?和SDP或SDP的一部分只是为了绕过ICE候选者和SDP交换部分?

1 个答案:

答案 0 :(得分:2)

不。优惠和答案不仅仅包含如何建立联系。它们包含此连接 instance 的唯一指纹,因为可以在相同的两个已知IP之间建立任意数量的安全连接,甚至可以同时建立。

比较来自两个不同的 RTCPeerConnection 对象的 createOffer()结果,您会发现它们有所不同。除了指纹之外,它们还包含本地 RTCPeerConnection 已决定通过其发送/接收单个媒体的端口,该端口可能会有所不同。

要使用早期的缓存版本,您不仅需要告诉远程 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规范禁止SDP在 createOffer setLocalDescription 之间进行修改。

在Firefox中,协商实际上已经完成,但是没有媒体或数据通道事件触发。

即使使用TURN服务器,也无法避免指纹不匹配。