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

时间:2014-08-19 22:41:49

标签: javascript google-chrome webrtc chromium node-webkit

问题:

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

问题描述:

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

  

无法执行' addIceCandidate' on' RTCPeerConnection':无法添加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();

这是一些peerConnection属性的输出:

peerConn.signalingState     -->  "closed"
peerConn.iceConnectionState -->  "closed"
peerConn.iceGatheringState  -->  "complete"

1 个答案:

答案 0 :(得分:2)

您应该能够进行rollback更改。这只能在角色未更改时发生,即第一次调用中的调用者仍然是后续调用中的调用者,并且在您的情况下可能不合适,因为您获得的错误消息与对等连接接收有关在发出要约之前的答案(即来电者/被叫者之间的不匹配)。

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

在您的情况下,删除原始对等连接并创建新连接是必须的,但还不够。您需要重新发起握手,并确保不会捕获和使用针对原始对等连接的消息,并由其他对等连接使用。多方客户具有相同的设计问题。解决它的一种方法,也是解决眩光问题的方法是添加到“提供”,“回答”,“候选”消息,您可以离线交换“原点”和可能的“目标”字段。您必须自己生成ID,因为默认情况下对等连接对象没有唯一ID。

这是正常的舞蹈(涓涓细流):

  • A即将上线,创建对等连接并在地图中将其疼痛 在索引A_0
  • B上线,与上面的B_0相同(确保ID是唯一的)
  • A正在呼叫B.
    • A发送要约,附加字段“origin”:“A_0”和“target”:“B_0”
    • B收到要约,setLocalDescription(开始ICE收集),发送回答来源:B_0,目标:A_0,完成。
    • 接收答案,设置本地说明(开始ICE收集),完成。
    • 正在与目标和原始字段进行适当交换的ICE候选人。

现在有问题的案例:

  • A在收到B的回答之前删除其A_0对等连接。
  • B发送A_0的答案和ICE候选人,A被丢弃,因为A_0不存在。
  • 用A_1重启舞蹈
眩光案例:

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

请注意,此设计还允许多方调用,因为每个调用都会被映射隔离,并由消息传递逻辑路由。

function handleGenericMsg(msg){
  if(  msg.origin  === username 
    ) {
    trace( 'MAIN - [' + username + '] Ignoring self message: ' + msg.type + '.' );
    return;
  }
  switch(msg.type){
    case 'offer':
      offerHandler(msg);
      break;
    default:
      trace( 'MAIN - [' + targetMid + '] Unsupported message received: ' +     JSON.stringify(msg));
      break;
  }
};

function offerHandler( msg ){
  var targetMid = msg.origin;
  offer = new RTCSessionDescription(msg);
  trace( 'PC   - [' + targetMid + '] Received offer.' )
  var pc = peerConnections[ targetMid ];
  if( !pc ) {
    openPeer( targetMid, false );
    pc = peerConnections[ targetMid ];
  } else {
    // we already had a PC, let's reuse it
  }
  pc.setRemoteDescription( offer );    
  doAnswer( targetMid );
};