如何在不刷新页面的情况下重置Chrome/node-webkit中的WebRTC状态?

jmo*_*253 7 javascript google-chrome chromium webrtc node-webkit

题:

如何重置Chrome中的WebRTC组件状态 - 无需重新加载页面 - 当它们被踢入无效状态时如何?有关我如何复制此状态的详细信息,请参阅下文,以及为什么我这样问:

问题描述:

尝试在拨打电话时设置Ice Candidates时,我在Chrome 35/node-webkit 0.10.0中收到以下错误:

无法在"RTCPeerConnection"上执行"addIceCandidate":无法添加ICE候选项.

现在,我知道为什么会这样.我正在制作一个可以处理一些普通用户滥用的ROBUST WebRTC应用程序.要复制这种状态,我基本上必须进行一些WebRTC调用然后快速杀死它们然后立即尝试另一个调用.我猜这必须将PeerConnection和其他组件放到一个不同的状态,在那里它会发生B,但我重新开始用A.这可以通过以下错误消息证明:

无法设置会话描述:无法设置远程应答sdp:调用错误状态:STATE_INIT

现在,我们在互联网上看到的大多数WebRTC演示,如http://apprtc.appspot.com,都是无状态的,浏览器经常刷新,导致重置DOM状态.因此,对于那些开发人员来说,答案很简单.只需重新加载页面并将其称为好.

目前,我必须在DOM进入此状态时重新加载应用程序.但是,这不是一个可接受的解决方案,因为我正在构建单页应用程序,而不是网站,

我想知道是否有办法调用API来告诉它重置抛出这些错误的状态?

一些疑难解答步骤

我尝试了以下命令,从node-webkit(Chrome 35)中的JavaScript控制台,看看我是否可以手动重置PeerConnection的状态,但它没有帮助:

 var properties = {};
 properties.pcConfig = {
     "iceServers": [{
         "url": "stun:stun.l.google.com:19302"
     }]
 };
 properties.pcConstraints = {
    "optional": []
 };

 peerConn = new RTCPeerConnection(properties.pcConfig, properties.pcConstraints);
 peerConn.close();
Run Code Online (Sandbox Code Playgroud)

这是一些peerConnection属性的输出:

peerConn.signalingState     -->  "closed"
peerConn.iceConnectionState -->  "closed"
peerConn.iceGatheringState  -->  "complete"
Run Code Online (Sandbox Code Playgroud)

Dr.*_*ard 3

您应该能够回滚更改。仅当角色未更改时才会发生这种情况,即当第一个调用中的调用者仍然是后续调用中的调用者时,并且可能不适合您的情况,因为您收到的错误消息与接收的对等连接有关在发出报价之前的答案(即呼叫者/被呼叫者之间的不匹配)。

\n

请注意,关闭状态是最终状态,应删除关闭的对等连接,因为它无法重复使用。

\n

就您而言,删除原始对等连接并建立新连接是必须的,但还不够。您需要重新启动握手,并确保针对原始对等连接的消息不会被其他对等连接捕获和使用。多方客户端也有同样的设计问题。解决这个问题以及解决眩光问题的一种方法是在离线交换的“要约”、“应答”、“候选”消息中添加“来源”和可能的“目标”字段。您必须自己生成 ID,因为默认情况下对等连接对象没有唯一 ID。

\n

这是正常的舞蹈(带有细流冰):

\n
    \n
  • A 即将上线,创建对等连接并在索引 A_0 的映射中\n
  • \n
  • B 即将上线,与上面的 B_0 相同(确保 ID 是唯一的)
  • \n
  • A 正在呼叫 B
  • \n
  • A 发送报价,带有附加字段“origin”:“A_0”和“target”:“B_0”
  • \n
  • B 接收报价,设置本地描述(开始 ICE 收集),发送答案,来源:B_0,目标:A_0,完成。
  • \n
  • 接收答案,设置本地描述(开始 ICE 收集),完成。
  • \n
  • ICE 候选人正在与适当设置的目标和来源字段进行交换。
  • \n
\n

现在有问题的情况:

\n
    \n
  • A 在收到 B 的应答之前删除了其 A_0 对等连接。
  • \n
  • B 发送 A_0 的答案和 ICE 候选,由于 A_0 不存在而被 A 丢弃。
  • \n
  • A 与 A_1 重新开始舞蹈
  • \n
\n

眩光情况:

\n
    \n
  • A 和 B 同时向对方发送报价
  • \n
  • 比较 ID 并根据可重现的任意规则选择一个(数字越大,字符串越大,使用字母顺序,\xe2\x80\xa6。)
  • \n
\n

请注意,此设计还允许多方呼叫,因为每个呼叫将由地图隔离,并由消息传递逻辑路由。

\n
function handleGenericMsg(msg){\n  if(  msg.origin  === username \n    ) {\n    trace( \'MAIN - [\' + username + \'] Ignoring self message: \' + msg.type + \'.\' );\n    return;\n  }\n  switch(msg.type){\n    case \'offer\':\n      offerHandler(msg);\n      break;\n    default:\n      trace( \'MAIN - [\' + targetMid + \'] Unsupported message received: \' +     JSON.stringify(msg));\n      break;\n  }\n};\n\nfunction offerHandler( msg ){\n  var targetMid = msg.origin;\n  offer = new RTCSessionDescription(msg);\n  trace( \'PC   - [\' + targetMid + \'] Received offer.\' )\n  var pc = peerConnections[ targetMid ];\n  if( !pc ) {\n    openPeer( targetMid, false );\n    pc = peerConnections[ targetMid ];\n  } else {\n    // we already had a PC, let\'s reuse it\n  }\n  pc.setRemoteDescription( offer );    \n  doAnswer( targetMid );\n};\n
Run Code Online (Sandbox Code Playgroud)\n