WebRTC“完美协商"问题 [英] WebRTC "perfect negotiation" issues

查看:88
本文介绍了WebRTC“完美协商"问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试实现 WebRTC完美协商",如 中所述这篇博文.不幸的是,我经常在对话的礼貌方面触发错误(在以下链接代码中,这是最后加入的对等方).

I have been trying to implement WebRTC "perfect negotiation" as explained in this blog post. Unfortunately, I'm very often triggering errors on the polite side of the conversation (in the following linked code, this is the last peer to join).

最常见的两个错误是 InvalidStateError: Cannot rollback local description in stable这一行ONN DOMException: "Cannot set local offer in state have-remote-offer" 触发了 此处这一行.第二个错误对我来说很莫名其妙,因为之前的那行检查我们应该处于 stable 状态,这是之后的第一个异步调用.

The two most frequent errors are InvalidStateError: Cannot rollback local description in stable caused by this line and ONN DOMException: "Cannot set local offer in state have-remote-offer" triggered here and caused by this line. That second error is quite inexplicable to me since the line before checks that we should be in stable state and it is the first async call following that.

如果您想亲自尝试,我的代码是托管在 GitHub 上.可以直接部署在 Heroku 上:

If you want to try it for yourself, my code is hosted on GitHub. It can be deployed directly on Heroku:

heroku create
git push heroku master

或者可以通过更改 server.js 的第 1、7-10 和 15 行,使用自签名证书在本地进行测试.

or can be tested locally with a self-signed certificate by changing lines 1, 7-10 and 15 of server.js.

我在使用 76、73 版桌面版 Firefox、桌面版 Chromium 80 及其最新的 Android 移动版进行测试时遇到了这些问题.对此的任何帮助将不胜感激.我也很想在 iPad(Safari >= 11)上可靠地工作,我无法亲自测试.

I have had those issues when testing with desktop Firefox at versions 76, 73, desktop Chromium 80 and their up-to-date mobile versions on Android. Any help on this would be very much appreciated. And I'd love to also have this reliably working on iPads (Safari >= 11) which I can't personally test.

推荐答案

TL;DR: 浏览器错误 已修复 Firefox 77 &规范,以及Chrome 中的单独错误.

TL;DR: Browser bugs fixed in Firefox 77 & the spec, as well as a separate bug in Chrome.

ONN DOMException:无法在有远程优惠状态下设置本地优惠" ...第二个错误对我来说很莫名其妙,因为之前的那行检查我们应该处于稳定状态,这是之后的第一个异步调用.

ONN DOMException: "Cannot set local offer in state have-remote-offer" ... That second error is quite inexplicable to me since the line before checks that we should be in stable state and it is the first async call following that.

WebRTC 协商代码具有将同步信令消息转换为 RTCPeerConnection 对象上的异步操作的棘手任务.为了确保顺序,这些异步方法在内部链接,因此只有一次运行一个,因为状态机.

WebRTC negotiation code has the tricky task of translating synchronous signaling messages into asynchronous operations on the RTCPeerConnection object. To ensure order, these asynchronous methods are chained internally, so only one runs at a time, because state machine.

在信号压力下,这个内部链有可能被填满,这让事情变得复杂,因为你调用的方法最终会在稍后运行,而不是立即处于你刚刚同步观察到的状态.

Under signaling stress, it's possible for this internal chain to fill up, which complicates things, because methods you invoke end up running later, not immediately in the state you just observed synchronously.

发生第二个错误"是因为浏览器错误地触发了 negotiationneeded 事件,而 RTCPeerConnection 对象的内部 操作链 非空.该规范现已已修复,因此不会发生这种情况.

The "second error" happened because the browser erroneously fired the negotiationneeded event while the RTCPeerConnection object's internal operations chain was non-empty. The spec has now been fixed so this won't happen.

由于浏览器控制何时触发 negotiationneeded 事件,这会处理它.

Since the browser controls when the negotiationneeded event is fired, this takes care of it.

InvalidStateError:无法在稳定版中回滚本地描述

不礼貌方面的第一个错误"同样是超载链的症状:同步状态检查我们不稳定,然后是:

The "first error" on the impolite side is similarly a symptom of an overloaded chain: synchronous state check that we're NOT in stable, followed by this:

if (offerCollision) { // pc.signalingState != "stable"
  await Promise.all([
    pc.setLocalDescription({ type: "rollback" }),
    pc.setRemoteDescription(description),
  ]);
}

我怀疑此时链上还有其他协商方法,可以在此 setLocalDescription 回滚开始运行之前将我们带回稳定"状态.

I suspect other negotiation methods are on the chain at this time that take us back to "stable" before this setLocalDescription rollback gets to run.

为了解决这个问题,规范添加了隐式回滚,所以你可以将上面的替换为:

To solve this, the spec added implicit rollback, so you can replace the above with:

await pc.setRemoteDescription(description); // implicit rollback only if needed

这样效果更好,因为是否需要回滚的决定是在链式方法内部做出的,在那个时间(可能稍后)查看正确的信号状态.

This works better because the decision of whether rollback is needed or not is made inside the chained method, looking at the correct signaling state at that (potentially later) time.

不幸的是,polyfill 并不是那么容易.您可以尝试以下操作:

This unfortunately is not that easy to polyfill. You might attempt something like:

if (offerCollision) { // pc.signalingState != "stable"
  await Promise.all([
    pc.setLocalDescription({type: "rollback"}).catch(() => {}), // ignore failure
    pc.setRemoteDescription(description),
  ]);
}

或者等待浏览器实现隐式回滚.

Or wait for browsers to implement implicit rollback.

这篇关于WebRTC“完美协商"问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆