【问题标题】:WebRTC: ICE failed since Firefox v 53WebRTC:ICE 自 Firefox v 53 起失败
【发布时间】:2018-05-16 15:58:27
【问题描述】:

我的 webRTC 项目有问题。我的代码在 Chrome 和 Firefox 上运行良好,直到版本 52。从 Firefox 53 开始,我收到错误:“ICE 失败,请参阅 about:webrtc 了解更多详细信息”。这是我的代码:

let connection;
let dataChannel;

 const initCon = (initiatorBoolean, choosenONE) => {
     createConnection();
     startConnection(initiatorBoolean, choosenONE);
     console.log('initCon(' + initiatorBoolean + ') / choosenONE = ' +choosenONE);
 }
var boolJoin =  false;
var lobbies = [];
var me = prompt("Please enter your name", "Bert");


// Helper für das Errorlogging
const logErrors = err => console.log(err);

// Websockets-Verbindung herstellen
const socket = io.connect('http://7daysclub.de:8080');

/* Methode to send information between to Users
*@param
*receiver= User who get the message
*type= Type of the message: could be init, joined, getUsers, setUsers, offer, answer, candidate
*descr= Content of the message
*/
 const sendMessage = (receiver, type, descr) => {
   message = Object.assign({to: 'default'}, {
       user: receiver,
       type: type,
       descr: descr,
       from: me
   });
   socket.emit('message', message);
   console.log("send: " + message.type + ". to: " + message.user);
};

const createConnection = () => {
    //Verbindung erstellen
    connection = new RTCPeerConnection( {
    'iceServers': [
        {

          /*
          'urls': 'stun:stun.l.google.com:19302'
          */
          'urls': 'stun:185.223.29.90:3478'


        },
        {

          'urls': 'turn:185.223.29.90:3478',
          'credential': '***',
          'username': '***'


        }
    ]
    });
    connection.oniceconnectionstatechange = function(event) {
      console.log('state: '+connection.iceConnectionState );
      if (connection.iceConnectionState === "failed" ||
          connection.iceConnectionState === "disconnected" ||
          connection.iceConnectionState === "closed") {
        // Handle the failure
      }
    };

}

const call = choosenONE => {

    if (!boolJoin) {
        sendMessage(choosenONE, 'joined', null);
    }

};

// Nachricht vom Signaling-Kanal empfangen
const receiveMessage = message => {
   console.log("receive: " + message.type);

   //Filter messages
   if (message.user != 'all' && message.user != me) {
       console.log("Block= " + message.user);
       return;
   }
   // Nachricht verarbeiten
   switch (message.type) {

       // Partner ist verfügbar
      case 'joined':
         choosenONE = message.from;
         sendMessage( choosenONE, 'init', null);
         boolJoin = true;
         initCon(true, choosenONE);
         break;

      case 'getUsers':
         sendMessage(message.from,'setUsers', null)
         lobbies.push(message.from);
         lobbylist();
         console.log('add User: ' + lobbies[lobbies.length-1] + ' to List');
         break;

      case 'setUsers':
         lobbies.push(message.from);
         console.log('add User: ' + lobbies[lobbies.length-1] + ' to List');
         lobbylist();
         break;

      // Verbindungsaufbau wurde vom Partner angefordert
      case 'init':
         choosenONE = message.from;
         boolJoin = true;
         initCon(false, choosenONE);
         break;


      // Ein SDP-Verbindungsangebot ist eingegangen – wir erstellen eine Antwort
      case 'offer':
        connection
          .setRemoteDescription(new RTCSessionDescription(message.descr))
          .then(() => connection.createAnswer())
          .then(answer => connection.setLocalDescription(new RTCSessionDescription(answer)))
          .then(() => sendMessage(message.from,'answer', connection.localDescription, me))
          .catch(logErrors);
         break;

      // Eine SDP-Verbindungsantwort auf unsere Anfrage ist eingegangen.
      case 'answer':
         connection.setRemoteDescription(new RTCSessionDescription(message.descr));
         break;

      // Der Partner hat eine mögliche Host-Port-Kombination ("ICE Candidate") gefunden
      case 'candidate':
         connection.addIceCandidate(new RTCIceCandidate({candidate: message.descr}));
         break;
   }
};

socket.on('message', receiveMessage);



// Verbindung initialisieren
const startConnection = (isCreator, choosenONE) => {
    // Wenn wir mögliche Kommunikationsendpunkte finden, diese an den Partner weitergeben
    connection.onicecandidate = event => {
        if (event.candidate) {
            sendMessage(choosenONE, 'candidate', event.candidate.candidate);
        }
    };

    // Wenn die Gegenseite einen Stream hinzufügt, diesen an das video-element hängen
   connection.ontrack = (e) => {
      document.getElementById('vidRemote').src = window.URL.createObjectURL(e.stream);
   };

   // Falls wir der erste Teilnehmer sind, starten wir den Verbindungsaufbau
   if (isCreator) {
      // Datenkanal anlegen
      dataChannel = connection.createDataChannel('chat');
      onDataChannelCreated(dataChannel);

      connection
        .createOffer()
        .then(offer => connection.setLocalDescription(new RTCSessionDescription(offer)))
        .then(() => sendMessage(choosenONE, 'offer', connection.localDescription))
        .catch(logErrors);

   } else {

      // Wenn wir nicht der Initiator sind, reagieren wir nur auf das Anlegen eines Datenkanals
      connection.ondatachannel = function (event) {
         dataChannel = event.channel;
         onDataChannelCreated(dataChannel);
      };

   }
};



const onDataChannelCreated = (channel, choosenONE) => {
   // Sobald der Datenkanal verfügbar ist, Chateingaben zulassen
   channel.onopen = () => {
      const enterChat = document.getElementById('enterChat');
      enterChat.disabled = false;
      enterChat.onkeyup = (keyevent) => {
         // Bei "Enter" absenden
         if (keyevent.keyCode === 13) {
            dataChannel.send(enterChat.value);
            appendChatMessage(me+':', enterChat.value);
            enterChat.value = '';
         }
      }
   };
   channel.onmessage = (message) => appendChatMessage(choosenONE+':', message.data);
};

const appendChatMessage = (name, text) => {
   const displayChat = document.getElementById('displayChat');
   const time = new Date().toString('H:i:s');
   displayChat.innerHTML = `<p>${name} - ${time}<br>${text}</p>` + displayChat.innerHTML;
};



function lobbylist() {
    allusers = "";
    lobbies.forEach( element => {
        allusers += "<li><button onclick=\"call('"+element+"')\">"+element+"</button></li>"
    });
    document.getElementById('lobbylist').innerHTML = allusers;
}

//Alle User bei Ankunft erfragen
sendMessage('all','getUsers', null);
lobbylist();

关于:webrtc =

(registry/INFO) insert 'ice' (registry) 成功:ice

(registry/INFO) insert 'ice.pref' (registry) 成功:ice.pref

(registry/INFO) insert 'ice.pref.type' (registry) 成功:ice.pref.type

(registry/INFO) insert 'ice.pref.type.srv_rflx' (UCHAR) 成功:0x64

(registry/INFO) insert 'ice.pref.type.peer_rflx' (UCHAR) 成功:0x6e

(registry/INFO) insert 'ice.pref.type.host' (UCHAR) 成功:0x7e

(registry/INFO) insert 'ice.pref.type.relayed' (UCHAR) 成功:0x05

(registry/INFO) 插入 'ice.pref.type.srv_rflx_tcp' (UCHAR) 成功:0x63

(registry/INFO) 插入 'ice.pref.type.peer_rflx_tcp' (UCHAR) 成功:0x6d

(registry/INFO) insert 'ice.pref.type.host_tcp' (UCHAR) 成功:0x7d

(registry/INFO) insert 'ice.pref.type.relayed_tcp' (UCHAR) 成功:0x00

(registry/INFO) insert 'stun' (registry) 成功:stun

(registry/INFO) 插入 'stun.client' (registry) 成功:stun.client

(registry/INFO) insert 'stun.client.maximum_transmits' (UINT4) 成功:7

(registry/INFO) insert 'ice.trickle_grace_period' (UINT4) 成功:5000

(registry/INFO) insert 'ice.tcp' (registry) 成功:ice.tcp

(registry/INFO) insert 'ice.tcp.so_sock_count' (INT4) 成功:0

(registry/INFO) insert 'ice.tcp.listen_backlog' (INT4) 成功:10

(registry/INFO) insert 'ice.tcp.disable' (char) 成功:\000

(generic/EMERG) 退出连接的 UDP 套接字

(通用/ERR)UDP 套接字错误:z:/build/build/src/dom/network/UDPSocketParent.cpp:283 this=00000000120CC400 的内部错误

(ice/INFO) z:/build/build/src/media/mtransport/third_party/nICEr/src/net/nr_socket_multi_tcp.c:173 函数 nr_socket_multi_tcp_create_stun_server_socket 跳过 UDP STUN 服务器(addr:IP4:185.223.29.90:3478 /UDP)

(ice/INFO) z:/build/build/src/media/mtransport/third_party/nICEr/src/net/nr_socket_multi_tcp.c:173 函数 nr_socket_multi_tcp_create_stun_server_socket 跳过 UDP STUN 服务器(addr:IP4:185.223.29.90:3478 /UDP)

(ice/WARNING) z:/build/build/src/media/mtransport/third_party/nICEr/src/net/nr_socket_multi_tcp.c:617 函数 nr_socket_multi_tcp_listen 失败并出现错误 3

(ice/WARNING) ICE(PC:1512241952789000 (id=19327352835 url=http://7daysclub.de/webrtc2/)): 未能创建被动 TCP 候选主机:3

(ice/NOTICE) ICE(PC:1512241952789000 (id=19327352835 url=http://7daysclub.de/webrtc2/)): peer (PC:1512241952789000 (id=19327352835 url=http://7daysclub.de/webrtc2/):default) 没有非空检查列表的流

p>

(ice/NOTICE) ICE(PC:1512241952789000 (id=19327352835 url=http://7daysclub.de/webrtc2/)): peer (PC:1512241952789000 (id=19327352835 url=http://7daysclub.de/webrtc2/):default) 没有带有预应答请求的流

(ice/NOTICE) ICE(PC:1512241952789000 (id=19327352835 url=http://7daysclub.de/webrtc2/)): peer (PC:1512241952789000 (id=19327352835 url=http://7daysclub.de/webrtc2/):default) 没有检查开始

(ice/ERR) ICE(PC:1512241952789000 (id=19327352835 url=http://7daysclub.de/webrtc2/)): peer (PC:1512241952789000 (id=19327352835 url=http://7daysclub.de/webrtc2/):default) 配对本地trickle ICE候选主机(IP4:192. .0.4:54605/UDP)

(ice/ERR) ICE(PC:1512241952789000 (id=19327352835 url=http://7daysclub.de/webrtc2/)): peer (PC:1512241952789000 (id=19327352835 url=http://7daysclub.de/webrtc2/):default) 配对本地涓流ICE候选主机(IP4:192. .0.4:62417/TCP) 活动

(stun/INFO) 无法识别的属性:0x802b

(stun/INFO) STUN-CLIENT(srflx(IP4:192.168.0.4:54605/UDP|IP4:185.223.29.90:3478/UDP)):收到响应;处理

(ice/ERR) ICE(PC:1512241952789000 (id=19327352835 url=http://7daysclub.de/webrtc2/)): peer (PC:1512241952789000 (id=19327352835 url=http://7daysclub.de/webrtc2/):default) 配对本地涓流 ICE 候选 srflx(IP):192186. .0.4:54605/UDP|IP4:185.223.29.90:3478/UDP)

(stun/INFO) STUN-CLIENT(relay(IP4:192.168.0.4:54605/UDP|IP4:185.223.29.90:3478/UDP)::TURN):收到响应;处理

(stun/WARNING) STUN-CLIENT(relay(IP4:192.168.0.4:54605/UDP|IP4:185.223.29.90:3478/UDP)::TURN):错误处理响应:重试可能,stun错误代码 401。

(stun/INFO) STUN-CLIENT(relay(IP4:192.168.0.4:54605/UDP|IP4:185.223.29.90:3478/UDP)::TURN):收到响应;处理

(stun/WARNING) STUN-CLIENT(relay(IP4:192.168.0.4:54605/UDP|IP4:185.223.29.90:3478/UDP)::TURN):错误处理响应:重试可能,stun错误代码 401。

(turn/WARNING) TURN(relay(IP4:192.168.0.4:54605/UDP|IP4:185.223.29.90:3478/UDP)): 超过重试次数

(turn/WARNING) TURN(relay(IP4:192.168.0.4:54605/UDP|IP4:185.223.29.90:3478/UDP)):模式20,nr_turn_client_error_cb

(转/警告)转(中继(IP4:192.168.0.4:54605/UDP|IP4:185.223.29.90:3478/UDP)) 失败

(转/INFO) TURN(中继(IP4:192.168.0.4:54605/UDP|IP4:185.223.29.90:3478/UDP)): 取消

(turn/WARNING) ICE-CANDIDATE(relay(IP4:192.168.0.4:54605/UDP|IP4:185.223.29.90:3478/UDP)): nr_turn_allocated_cb 以状态 4 调用

(turn/WARNING) ICE-CANDIDATE(relay(IP4:192.168.0.4:54605/UDP|IP4:185.223.29.90:3478/UDP)): nr_turn_allocated_cb 失败

(ice/INFO) ICE(PC:1512241952789000 (id=19327352835 url=http://7daysclub.de/webrtc2/)): peer (PC:1512241952789000 (id=19327352835 url=http://7daysclub.de/webrtc2/):default) 涓流宽限期结束;标记每个组件只有失败的对才失败。

(ice/INFO) ICE-PEER(PC:1512241952789000 (id=19327352835 url=http://7daysclub.de/webrtc2/):default)/STREAM(0-1512241952789000 (id=19327352835 url=http://7daysclub.de/webrtc2/) aLevel=0)/COMP(1): 所有对都失败,并且宽限期已过。将组件标记为失败。

(ice/INFO) ICE-PEER(PC:1512241952789000 (id=19327352835 url=http://7daysclub.de/webrtc2/):default): 所有检查完成成功=0 失败=1

(generic/EMERG) 退出连接的 UDP 套接字

(generic/ERR) UDP socket error:Internal error at z:/build/build/src/dom/network/UDPSocketParent.cpp:283 this=000000000BAE3000

(ice/INFO) z:/build/build/src/media/mtransport/third_party/nICEr/src/net/nr_socket_multi_tcp.c:173 函数 nr_socket_multi_tcp_create_stun_server_socket 跳过 UDP STUN 服务器(addr:IP4:185.223.29.90:3478 /UDP)

(ice/INFO) z:/build/build/src/media/mtransport/third_party/nICEr/src/net/nr_socket_multi_tcp.c:173 函数 nr_socket_multi_tcp_create_stun_server_socket 跳过 UDP STUN 服务器(addr:IP4:185.223.29.90:3478 /UDP)

(ice/WARNING) z:/build/build/src/media/mtransport/third_party/nICEr/src/net/nr_socket_multi_tcp.c:617 函数 nr_socket_multi_tcp_listen 失败并出现错误 3

(ice/WARNING) ICE(PC:1512242125375000 (id=19327352836 url=http://7daysclub.de/webrtc2/)): 未能创建被动 TCP 候选主机:3

(ice/NOTICE) ICE(PC:1512242125375000 (id=19327352836 url=http://7daysclub.de/webrtc2/)): peer (PC:1512242125375000 (id=19327352836 url=http://7daysclub.de/webrtc2/):default) 没有非空检查列表的流

(ice/NOTICE) ICE(PC:1512242125375000 (id=19327352836 url=http://7daysclub.de/webrtc2/)): peer (PC:1512242125375000 (id=19327352836 url=http://7daysclub.de/webrtc2/):default) 没有带有预回答请求的流

(ice/NOTICE) ICE(PC:1512242125375000 (id=19327352836 url=http://7daysclub.de/webrtc2/)): peer (PC:1512242125375000 (id=19327352836 url=http://7daysclub.de/webrtc2/):default) 没有检查开始

(ice/ERR) ICE(PC:1512242125375000 (id=19327352836 url=http://7daysclub.de/webrtc2/)): peer (PC:1512242125375000 (id=19327352836 url=http://7daysclub.de/webrtc2/):default) 配对本地trickle ICE候选主机(IP4:192. .0.4:63286/UDP)

(ice/ERR) ICE(PC:1512242125375000 (id=19327352836 url=http://7daysclub.de/webrtc2/)): peer (PC:1512242125375000 (id=19327352836 url=http://7daysclub.de/webrtc2/):default) 配对本地trickle ICE候选主机(IP4:192. .0.4:54433/TCP) 激活

(stun/INFO) 无法识别的属性:0x802b

(stun/INFO) STUN-CLIENT(srflx(IP4:192.168.0.4:63286/UDP|IP4:185.223.29.90:3478/UDP)):收到响应;处理

(ice/ERR) ICE(PC:1512242125375000 (id=19327352836 url=http://7daysclub.de/webrtc2/)): 对等体 (PC:1512242125375000 (id=19327352836 url=http://7daysclub.de/webrtc2/):default) 配对本地涓流 ICE 候选 srflx(IP:192186. .0.4:63286/UDP|IP4:185.223.29.90:3478/UDP)

(stun/INFO) STUN-CLIENT(relay(IP4:192.168.0.4:63286/UDP|IP4:185.223.29.90:3478/UDP)::TURN):收到响应;处理

(stun/WARNING) STUN-CLIENT(relay(IP4:192.168.0.4:63286/UDP|IP4:185.223.29.90:3478/UDP)::TURN):错误处理响应:重试可能,stun错误代码 401。

(stun/INFO) STUN-CLIENT(relay(IP4:192.168.0.4:63286/UDP|IP4:185.223.29.90:3478/UDP)::TURN):收到响应;处理

(转/INFO) TURN(relay(IP4:192.168.0.4:63286/UDP|IP4:185.223.29.90:3478/UDP)): 成功分配地址IP4:185.223.29.90:50497/UDP生命周期=3600

(ice/ERR) ICE(PC:1512242125375000 (id=19327352836 url=http://7daysclub.de/webrtc2/)): peer (PC:1512242125375000 (id=19327352836 url=http://7daysclub.de/webrtc2/):default) 配对本地涓流 ICE 候选转接继电器(IP4 :192.168.0.4:63286/UDP|IP4:185.223.29.90:50497/UDP)

(ice/INFO) ICE(PC:1512242125375000 (id=19327352836 url=http://7daysclub.de/webrtc2/)): peer (PC:1512242125375000 (id=19327352836 url=http://7daysclub.de/webrtc2/):default) 涓流宽限期结束;标记每个组件只有失败的对才失败。

(ice/INFO) ICE-PEER(PC:1512242125375000 (id=19327352836 url=http://7daysclub.de/webrtc2/):default)/STREAM(0-1512242125375000 (id=19327352836 url=http://7daysclub.de/webrtc2/) aLevel=0)/COMP(1): 所有对都失败,并且宽限期已过。将组件标记为失败。

(ice/INFO) ICE-PEER(PC:1512242125375000 (id=19327352836 url=http://7daysclub.de/webrtc2/):default): 所有检查完成成功=0 失败=1

+++++++结束++++++++

我的 turnserver 配置如下所示:

# TURN listener port for UDP and TCP (Default: 3478).
# Note: actually, TLS & DTLS sessions can connect to the 
# "plain" TCP & UDP port(s), too - if allowed by configuration.
#
listening-port=3478

# TURN listener port for TLS (Default: 5349).
# Note: actually, "plain" TCP & UDP sessions can connect to the TLS & DTLS
# port(s), too - if allowed by configuration. The TURN server 
# "automatically" recognizes the type of traffic. Actually, two listening
# endpoints (the "plain" one and the "tls" one) are equivalent in terms of
# functionality; but we keep both endpoints to satisfy the RFC 5766 specs.
# For secure TCP connections, we currently support SSL version 3 and 
# TLS version 1.0, 1.1 and 1.2. SSL2 "encapculation mode" is also supported.
# For secure UDP connections, we support DTLS version 1.
#
tls-listening-port=5349

# Listener IP address of relay server. Multiple listeners can be specified.
# If no IP(s) specified in the config file or in the command line options, 
# then all IPv4 and IPv6 system IPs will be used for listening.
#
listening-ip=185.223.29.90

# Relay address (the local IP address that will be used to relay the 
# packets to the peer).
# Multiple relay addresses may be used.
# The same IP(s) can be used as both listening IP(s) and relay IP(s).
#
# If no relay IP(s) specified, then the turnserver will apply the default
# policy: it will decide itself which relay addresses to be used, and it 
# will always be using the client socket IP address as the relay IP address
# of the TURN session (if the requested relay address family is the same
# as the family of the client socket).
#
relay-ip=185.223.29.90


lt-cred-mech


# Realm for long-term credentials mechanism and for TURN REST API.
#
realm=7daysclub.de


#Local system IP address to be used for CLI server endpoint. Default value
# is 127.0.0.1.
#
cli-ip=185.223.29.90

# CLI server port. Default is 5766.
#
cli-port=5766

【问题讨论】:

    标签: webrtc


    【解决方案1】:

    查看您的在线演示,远程 SDP 中没有 a=candidate 行,这表明从未添加过候选人。 sendMessage(choosenONE, 'candidate', event.candidate.candidate); 这是丢弃需要向远程对等方发送信号的 sdpMid 和 sdpMLineIndex。将 .catch 添加到您的 addIceCandidate 以记录任何错误。

    【讨论】:

    • 老兄,你是我未来 20 年的官方英雄!非常感谢!
    • 这也是我刚才遇到的问题,因为我正在构建的 google codelab 中缺少 sdpMLineIndex。知道为什么在未设置 sdpMLineIndex 并且 Chrome 没有失败时 FF 有时会失败吗?我还注意到,通常 FF 会提出更多的候选人(我正在通过 LAN 进行测试)
    • 听起来你遇到了bugzilla.mozilla.org/show_bug.cgi?id=1456417 你能在codelab上提出问题吗?
    猜你喜欢
    • 1970-01-01
    • 2015-09-27
    • 1970-01-01
    • 2016-04-16
    • 2013-03-04
    • 1970-01-01
    • 1970-01-01
    • 2012-08-11
    • 1970-01-01
    相关资源
    最近更新 更多