【问题标题】:Kurento WebRTC Connection Fails in ~30% of CasesKurento WebRTC 连接在约 30% 的情况下失败
【发布时间】:2019-01-21 13:55:40
【问题描述】:

我花了几天时间寻找连接问题,但没有任何运气。我正在尝试使用 Kurento 实现一个相对简单的 one2one Call。

下面是Kurento的调试日志,其中有一个可以建立连接的情况和一个连接失败的情况。

如果您需要更多日志(例如客户端、信令服务器、tcpdump 或 Kurento 的跟踪日志,请告诉我,我会提供!)

非常感谢任何帮助或新意见!

问题描述:

在大约 30% 的情况下,无法建立 WebRTC 连接。不幸的是,当可以建立连接时,我缺乏任何类型的模式,而当不能建立时,它似乎完全是随机的。我在同一个网络中,使用相同的设备,使用相同的 TURN 服务器,使用相同的信令协议,但在 30% 的情况下无法建立连接。

当我在本地运行应用程序时,它似乎工作得更加可靠,几乎 100% 的时间都可以建立连接(或者甚至可能 100% 的时间,我已经测试了很多次,我失去了踪迹)。我使用 docker 在本地设置基础设施,并在不同的网络中运行不同的容器(TURN、Kurento、Signalling)以模拟生产部署。

我们在开发和生产环境中遇到相同的行为。在我们的开发环境中,我们绝对没有防火墙,所以这似乎不是问题。

我试图找出问题的原因:

大多数情况下,我一直在比较有效案例和无效案例的日志,但我没有发现它们之间的任何显着差异可以指出我的问题。

我已经通过 TURN 服务器(使用 Firefox 和 force_relay 标志)和 Kurento 直接测试了 WebRTC 连接,但在这两种情况下,大约 30% 的情况下连接失败。

我已尝试过滤所有不是接力候选人的 ICE 候选人。

我已经嗅探了我们的信令服务器(也控制 Kurento)和 Kurento 之间的流量,以查看交换的 JSON RPS 消息的任何差异,但它们似乎基本相同。

我已经使用这个工具测试了我们的 STUN 和 TURN 服务器:https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/,我得到了看起来正确的 serverreflexive 和 relay 候选

我已经嗅探了成功和不成功连接的客户端的流量,但可以发现显着差异

我已经简化了 Kurento 媒体管道(没有录制,没有集线器),但行为是一样的

我使用过不同的浏览器(Chrome、Firefox 和原生 iOS 实现),但行为是相同的

可以建立连接的情况的Kurento调试日志:

https://gist.github.com/omnibrain/2bc7ad54f626d278d3c8bac29767ac4c

无法建立连接的Kurento调试日志:

https://gist.github.com/omnibrain/f7caee04a5c6d77ea22a9ccfa95dd825

【问题讨论】:

    标签: webrtc kurento libnice


    【解决方案1】:

    经过几天的调试和几乎发疯,我们终于找到了问题的原因:

    我们使用了 Socket.IO 的 Swift 客户端和 Socket.IO 的 Java Netty Socket.IO 服务器实现。客户端 (iOS) 使用长轮询与服务器 (Java) 通信。事实证明,Netty Socket.IO 服务器正在对 Swift Socket.IO 客户端的长轮询负载进行 URL 解码,但 Swift Socket.IO 客户端实际上并未对其进行 URL 编码。这意味着从 Swift Socket.IO 客户端发送的每个“+”在服务器上都被替换为“”(空格)。为什么这是个问题?因为客户端的 SDP 报价包含一个 ufrag,它可以包含一个加号!因此,如果 SDP 包含“+”,则在服务器上将其替换为空格,这会导致 STUN ping 失败,因为无法验证消息完整性。

    【讨论】:

    • 感谢您在 Kurento 社区论坛上分享您的经验,我在文档的疑难解答部分添加了您的案例作为示例:doc-kurento.readthedocs.io/en/6.12.0/user/…
    • @j1elo 这可能是我一生中不得不追查的最难的错误。我永远不会忘记这一点。希望这将使一些可怜的灵魂摆脱我们在那段时间不得不忍受的压力和挫折:)
    【解决方案2】:

    查看你的踪迹,你的工作案例选择候选 10然后选择候选 7,非工作只选择候选 10。

    kurento_logs_webrtc_working.txt

    New candidate pair selected, local: 'candidate:10 1 UDP 335544831 10.10.36.134 50589 typ relay raddr 172.19.0.2 rport 9', remote: 'candidate:3993072200 1 UDP 41885695 10.10.36.134 53894 typ relay', stream_id: '1', component_id: 1
    ...
    New candidate pair selected, local: 'candidate:7 1 UDP 1677722111 10.10.36.131 46842 typ srflx raddr 172.19.0.2 rport 46842', remote: 'candidate:266015763 1 UDP 2122260223 10.10.1.57 55125 typ host', stream_id: '1', component_id: 1
    

    kurento_logs_webrtc_NOT_working.txt

    new candidate pair selected, local: 'candidate:10 1 UDP 335544831 10.10.36.134 51280 typ relay raddr 172.19.0.2 rport 9', remote: 'candidate:3993072200 1 UDP 41885695 10.10.36.134 51287 typ relay', stream_id: '1', component_id: 1
    

    我的第一个想法是你在重复使用旧的候选人,但端口已经改变。更改浏览器可能会更改候选编号,我没想到它们在运行之间是确定性的,所以我不得不看两次。

    与日志有一个小的区别 - 不工作的 IceComponentStateChanged 更改为 connecting 之后 candidate:266015763 出现而不是之前。我不知道这是否重要。

    一般说明:

    过去当我们遇到几类问题时:

    • 客户端我们正在失去 ICE 候选人 - 一些候选人在我们准备好之前就已经发送,因此我们需要将它们排队。 IIRC 在 SDP 报价中可能有一些候选人(或回答,抱歉已经有一段时间了),因此您的听众需要在开始之前做好准备。
    • 我们发送了 OLD 候选 - 在信令服务器中使用了错误的重播元素向客户端提供候选,这些元素不再有效。

    我建议您使用带有 chrome://webrtc-internals 的 Chrome 来提供帮助。 ICE 候选问题在 webrtc-internals 中可见,因为您可以看到状态机遍历其状态。在我们的工作案例中,有更多的转换,而不是破碎的案例。

    为三个ice事件添加客户端监听器也很有帮助:

    this.peer.peerConnection.oniceconnectionstatechange = this.logloglog.bind(this, this.peer.peerConnection);
    this.peer.peerConnection.onicegatheringstatechange = this.logloglog.bind(this, this.peer.peerConnection);
    this.peer.peerConnection.onsignalingstatechange = this.logloglog.bind(this, this.peer.peerConnection);
    

    这可以让您了解谈判的进展情况,但基本上是chrome://webrtc-internals 中的内容。

    最后一点,这是我在日志部分使用的/etc/default/kurento-media-server

    
    # ICE debug logging: uncomment to enable in KMS and in the 3rd-party library 'libnice'
    # - Note: This can get very verbose, log size will explode in the long term
    #export GST_DEBUG="$GST_DEBUG,kmsiceniceagent:5,kmswebrtcsession:5,webrtcendpoint:4"
    export G_MESSAGES_DEBUG="libnice,libnice-stun"
    export NICE_DEBUG="$G_MESSAGES_DEBUG"
    

    我不记得它们是否比你用的更好,但我会把它扔在那里。

    【讨论】:

    • 非常感谢您阅读所有内容。我们今天实际上找到了大约三分之一连接失败的原因。我会尽快发布答案
    • 你发布答案了吗?
    • 感谢追踪它。我做了一个解决方法,重试失败,这可能需要几次尝试,但最终会连接。这个错误有修复吗?我在 Chrome 上的 Windows 10 PC 之间进行测试以排除其他变量。将前两个用户连接到群组通话时,它似乎从来没有这样做过,但随着我添加更多,我看到他们失败并重试发送和接收。
    猜你喜欢
    • 2016-05-13
    • 1970-01-01
    • 2019-07-19
    • 1970-01-01
    • 2015-04-28
    • 1970-01-01
    • 2018-05-21
    • 2013-12-31
    • 1970-01-01
    相关资源
    最近更新 更多