RTCPeerConnection.iceConnectionState 从检查更改为关闭

RTCPeerConnection.iceConnectionState changed from checking to closed

按照方法 我正在尝试从 iPhone 模拟器(使用 React Native)接听使用 Chrome 浏览器发起的音频呼叫。

事件序列摘要:

  1. 收到来电信号
  2. 获得本地流
  3. 发出加入呼叫信号
  4. 收到远程描述(offer),
  5. 已创建 PeerConnection
  6. 已添加本地流
  7. 收到候选人
  8. 已添加候选人
  9. 7和8重复15次(即一共16次)
  10. 需要触发的谈判
  11. signalingState 更改为 have-remote-offer
  12. onaddstream 触发
  13. 触发了setRemoteDescription的回调函数,创建了answer。
  14. 信号状态变为稳定状态
  15. iceconnectionstate 更改为 checking
  16. 第一次触发了 onicecandidate。
  17. 发出了来自 15
  18. 的候选人
  19. 第二次触发了 onicecandidate。候选人是null
  20. iceconnectionstate 变为closed

步骤 7、8、9 可能会出现在 6 之后和 19 之前的不同位置。

我被这个问题困了好一阵子了。我什至不知道此时要调试什么。连接关闭的可能原因有哪些?如果需要,我可以 post 更多日志。

一个观察是iceconnectionstatechange对应的两个RTCEvent具有以下属性:

isTrusted:false

目标 RTCPeerConnection 有

iceConnectionState:"closed"
iceGatheringState:"complete"

这是我处理 remoteOffer 和 remoteCandidates 的函数:

WebRTCClass.prototype.onRemoteOffer = function(data) {
  var ref;
  if (this.active !== true) {
    return;
  }
  var peerConnection = this.getPeerConnection(data.from);
  console.log('onRemoteOffer', data,peerConnection.signalingState);

  if (peerConnection.iceConnectionState !== 'new') {
    return;
  }
  var onSuccess = (function(_this){
    return function(){
      console.log("setRemoteDescription onSuccess function");
      _this.getLocalUserMedia((function(_this) {
          return function(onSuccess,stream) {
            peerConnection.addStream(_this.localStream);
            var onAnswer = (function(_this) {
              return function(answer) {
                var onLocalDescription = function() {
                  return _this.transport.sendDescription({
                    to: data.from,
                    type: 'answer',
                    ts: peerConnection.createdAt,
                    description: {
                      sdp: answer.sdp,
                      type: answer.type
                    }
                  });
                };
                return peerConnection.setLocalDescription(new RTCSessionDescription(answer), onLocalDescription, _this.onError);
              };
            })(_this);
            return peerConnection.createAnswer(onAnswer, _this.onError);
          }
        })(_this)
      );
    }
  })(this);
  return peerConnection.setRemoteDescription(new RTCSessionDescription(data.description),onSuccess,console.warn);
}; 

WebRTCClass.prototype.onRemoteCandidate = function(data) {
  var peerConnection, ref;
  if (this.active !== true) {
    return;
  }
  if (data.to !== this.selfId) {
    return;
  }
  console.log('onRemoteCandidate', data);
  peerConnection = this.getPeerConnection(data.from);
  if ((ref = peerConnection.iceConnectionState) !== "closed" && ref !== "failed" && ref !== "disconnected" && ref !== "completed") {
    peerConnection.addIceCandidate(new RTCIceCandidate(data.candidate));
  }
};

我发现如果我把下面两个函数一一调用就可以了

peerConnection.setRemoteDescription(new RTCSessionDescription(data.description),onSuccess,console.warn);
(...definition of onAnswer ...)
peerConnection.createAnswer(onAnswer, this.onError); 

我之前的代码在 setRemoteDescriptiononSuccess 回调中调用了 createAnswer。这对 react-native-webrtc 演示有效,但对 Rocket.Chat 无效。还是没有完全理解。但是我的项目现在可以继续了。