我已经为这个问题苦恼了两个星期,并将问题隔离为Twilio服务本身。为了比较,我使用了一个基于Web的WebRTC数据通道演示,使用火狐和Xirsys TURN服务器云。我有wireshark捕获显示火狐与Twilio断开连接,就像我的本地应用程序一样,而完全相同的火狐演示在使用Xirsys服务器时不会断开连接。
我最初使用的是Xirsys,但他们的服务不稳定,所以我转向了Twilio,这就是为什么我宁愿让Twilio解决这个问题而不是回到Xirsys。至少,我希望有两个WebRTC托管提供商可供选择,我知道它们应该可以正常工作。这就是我花时间详细解释问题的原因,以便能够得到解决。
以下是两个wireshark捕获(过滤掉点对点数据消息),显示Firefox使用WebRTC数据通道和Twilio TURN中继服务器: 在第一次捕获中,4分钟后传输停止,第二次捕获后大约11分钟传输停止。在两次捕获中,Firefox检测到流量停止中继(在数据通道级别),并尝试通过发送寿命为零的刷新请求包进行优雅断开连接。两个优雅的断开连接都导致437分配不匹配错误,表明服务器甚至不知道Firefox正在尝试优雅关闭的分配情况。
对于我的本机应用程序,这通常采用创建权限请求消息的形式,该消息会因438“错误的随机数”错误而失败,如果客户端尝试更新不存在的分配上的权限,则基本上应该发生这种情况。错误代码438通常表示“过时的随机数”,这不是真正的错误,而是指示随机数已过期,客户端应使用包含在“错误”消息中的新随机数再次尝试。我花了一些时间才弄清楚,但即使错误代码是438,错误字符串也不同。我已经观察到与Xirsys的真正陈旧的随机数错误,并成功地使用错误响应中的新随机数更新了我的权限,因此我知道我可以在我的实现中正确处理此情况。
这是我使用的WebRTC数据通道演示的源代码: https://github.com/devolutions/webrtc-demo 为了比较,这是使用Xirsys TURN服务器云的相同Firefox数据通道演示: 在这个捕获过程中,我让演示运行了大约16分钟(它可以运行更长时间,我尝试过最长的是两个小时)。我们可以看到,在整个会话期间,流量一直在被中继,并且Firefox不断发送CreatePermission请求并成功。最后,优雅的断开连接是由Firefox关闭WebRTC数据通道触发的(而不是由于流量不再被中继而关闭)。与Twilio捕获不同,生存期为零的刷新请求成功:Xirsys TURN服务器仍然知道分配情况并返回成功响应,正如预期的那样。
值得注意的是,ICMP不可达错误是正常的,因为我认为在这种情况下,当响应返回时,Firefox不再侦听给定端口。换句话说,它发送了生存期为零的刷新请求,但没有等待答案返回。
目前,我别无选择,只能回到Xirsys,但我真的希望Twilio网络遍历服务可以修复。如果您对该问题有更多问题,请告诉我。
我已经上传了wireshark捕获文件here以供参考。
编辑:我修改了webrtc演示页面,使其在冰连接状态设置为“已断开”时不关闭连接。现在,当冰连接状态变为“失败”时,我会真正地断开连接。然而,实际上这并没有改变什么,因为在这种情况下,状态从“已断开”到“失败”只需要几秒钟。
由于我有新的相关截图和捕获内容,我正在更新原始问题以澄清Philipp Hancke指出的某些问题:
首先,这是一个新的捕获状态修复的截图(当状态变为“失败”时,浏览器才会关闭连接):
这次会话持续了整整18分钟,很有趣。这是在一个周六早上进行的,所以我猜问题可能与Twilio服务器当前的工作负载有关。然而,对我来说,它仍然以完全相同的方式失败。作为奖励,我们甚至有一个有效的陈旧nonce响应,并且被Firefox正确处理。但是,如果我们从不同的角度观察相同的捕获,我们可以看到在Firefox认为连接已断开并发送生命周期为零的刷新请求之前,流量停止中继了30秒钟。与先前的捕获一样,服务器响应Allocation Mismatch错误,表示它不知道Firefox正在谈论哪个分配。 最后发送的8个数据包大小相同,因此我猜它们是重传。经过30秒的重传后,SCTP可能会认为传输已中断。
关于生存期为零的刷新请求,我进行了一项测试,在浏览器中早期关闭连接。在这种情况下,服务器识别分配并返回成功响应:
分配不匹配是最容易观察到的症状,但在我的本地应用程序测试中,我发现对于非零生命周期的刷新请求和CreatePermission请求(438“错误nonce”错误),也会出现类似的错误。然而,由于浏览器在30秒未传递数据后关闭连接,因此很难通过当前的webrtc演示观察到这些错误。如果我们可以将该超时时间更改为10分钟,那么我们也将看到这些错误。