javascript - ICE 在不同网络中的 WebRTC 失败 [Firefox]

标签 javascript firefox webrtc

我遇到了这个问题,我有一个网络应用程序在服务器中运行,具有域并且可以工作,如果我连接并视频通话到同一网络(例如我家)中的另一台电脑(记住我的服务器在 linode 服务器中在线)我没有任何问题,但如果我连接家里的一台笔记本电脑和工作中的另一台笔记本电脑,(不同的网络)连接不起作用,我会尝试每个 STUN/TURN 信号,并继续使用 numb.viagenie.ca具有 STUN 和 TURN 服务器。 当我看到 about:webrtc 时,我的房子和我的笔记本电脑的 IP 和端口都出现连接,但不起作用,并且出现 ICE FAILED。 这是我的 RTCClient.js (我的 webRTC 逻辑):

var PeerManager = (function (room, cbMessages) {
var remote = window.document.getElementById('remote');
var localId,
    config = {
        peerConnectionConfig: {
            iceServers: [
                /* { 'url': 'stun:stun01.sipphone.com' },
                 { 'url': 'stun:stun.ekiga.net' },
                 { 'url': 'stun:stun.fwdnet.net' },
                 { 'url': 'stun:stun.ideasip.com' },
                 { 'url': 'stun:stun.iptel.org' },
                 { 'url': 'stun:stun.rixtelecom.se' },
                 { 'url': 'stun:stun.schlund.de' },
                 { 'url': 'stun:stun.l.google.com:19302' },
                 { 'url': 'stun:stun1.l.google.com:19302' },
                 { 'url': 'stun:stun2.l.google.com:19302' },
                 { 'url': 'stun:stun3.l.google.com:19302' },
                 { 'url': 'stun:stun4.l.google.com:19302' },
                 { 'url': 'stun:stunserver.org' },
                 { 'url': 'stun:stun.softjoys.com' },
                 { 'url': 'stun:stun.voiparound.com' },
                 { 'url': 'stun:stun.voipbuster.com' },
                 { 'url': 'stun:stun.voipstunt.com' },
                 { 'url': 'stun:stun.voxgratia.org' },
                 { 'url': 'stun:stun.xten.com' },
                 { 'url': "stun:stun.services.mozilla.com" },*/
                { 'url': "stun:numb.viagenie.ca" },
                {
                    'url': "turn:numb.viagenie.ca",
                    'credential': 'xxxxxx',
                    'username': 'xxxxxxxx'
                },
                {
                    'url': "turn:numb.viagenie.ca",
                    'credential': 'xxxxxxx',
                    'username': 'xxxxxxxxxxxxxxx'
                },

                /*{
                    'url': 'turn:192.158.29.39:3478?transport=udp',
                    'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
                    'username': '28224511:1379330808'
                },
                {
                    'url': 'turn:192.158.29.39:3478?transport=tcp',
                    'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
                    'username': '28224511:1379330808'
                },*/
            ]
        },
        peerConnectionConstraints: {
            optional: [
                { "DtlsSrtpKeyAgreement": true }
            ]
        }
    },
    peerDatabase = {},
    localStream,
    //remoteVideoContainer = document.getElementById('remoteVideosContainer'),
    socket = io('http://xxxxx');


//METODO CON EL QUE AUTOMATICAMENTE SE DISPARA CUANDO SE ESTABLECE LA CONEXION CON EL SERVIDOR
socket.on('connect', function () {
    console.log('Se ha establecido la conexion con el servidor');
    socket.emit('roomSetup', room);
});
socket.on('id', function (clientId) {
    cbMessages('id', clientId);
})
socket.on('message', handleMessage);
socket.on('numberQueue', function (action) {
    console.log("Recepcion en rtcClient del numberQueue");
    cbMessages('numberQueue', action);
})
socket.on('readytoCall', function (action) {
    console.log("Recepcion en rtcClient del readytoCall");
    cbMessages('readytoCall', action);
})
socket.on('startSession', function (action) {
    console.log('Recepcion en rtcClient del startSession');
    cbMessages('startSession', action);
})
socket.on('syncCounters', function (action) {
    console.log('Recepcion en rtcClient del syncCounters');
    cbMessages('syncCounters', action);
})
socket.on('id', function (id) {
    localId = id;
});

function addPeer(remoteId) {
    var peer = new Peer(config.peerConnectionConfig, config.peerConnectionConstraints);
    peer.pc.onicecandidate = function (event) {
        console.log(event);
        if (event.candidate) {
            send('candidate', remoteId, {
                label: event.candidate.sdpMLineIndex,
                id: event.candidate.sdpMid,
                candidate: event.candidate.candidate
            });
        }
    };
    /* peer.pc.ontrack = function (event) {
         attachMediaStream(remote, event.streams[0]);
         console.log(remote, event.streams[0]);
     }*/
    peer.pc.onaddstream = function (event) {

        attachMediaStream(remote, event.stream); /*peer.remoteVideoEl*/
        // remoteVideosContainer.appendChild(peer.remoteVideoEl);
        console.log(remote, event.stream);
    };
    peer.pc.onremovestream = function (event) {
        peer.remoteVideoEl.src = '';
        remoteVideosContainer.removeChild(peer.remoteVideoEl);
    };
    peer.pc.oniceconnectionstatechange = function (event) {
        switch (
        (event.srcElement // Chrome
            || event.target) // Firefox
            .iceConnectionState) {
            case 'disconnected':
                remoteVideosContainer.removeChild(peer.remoteVideoEl);
                break;
        }
    };
    peerDatabase[remoteId] = peer;

    return peer;
}
function answer(remoteId) {
    var pc = peerDatabase[remoteId].pc;
    pc.createAnswer(
        function (sessionDescription) {
            pc.setLocalDescription(sessionDescription);
            send('answer', remoteId, sessionDescription);
        },
        error
    );
}
function offer(remoteId) {
    var pc = peerDatabase[remoteId].pc;
    pc.createOffer(
        function (sessionDescription) {
            pc.setLocalDescription(sessionDescription);
            send('offer', remoteId, sessionDescription);
        },
        error
    );
}
function handleMessage(message) {
    var type = message.type,
        from = message.from,
        pc = (peerDatabase[from] || addPeer(from)).pc;

    console.log('received ' + type + ' from ' + from);

    switch (type) {
        case 'init':
            toggleLocalStream(pc);
            offer(from);
            break;
        case 'offer':
            pc.setRemoteDescription(new RTCSessionDescription(message.payload), function () { }, error);
            answer(from);
            break;
        case 'answer':
            pc.setRemoteDescription(new RTCSessionDescription(message.payload), function () { }, error);
            break;
        case 'candidate':
            if (pc.remoteDescription) {
                pc.addIceCandidate(new RTCIceCandidate({
                    sdpMLineIndex: message.payload.label,
                    sdpMid: message.payload.id,
                    candidate: message.payload.candidate
                }), function () { }, error);
            }
            break;
    }
}
function send(type, to, payload) {
    console.log('sending ' + type + ' to ' + to);

    socket.emit('message', {
        to: to,
        type: type,
        payload: payload
    });
}
function toggleLocalStream(pc) {
    if (localStream) {
        (!!pc.getLocalStreams().length) ? pc.removeStream(localStream) : pc.addStream(localStream);
    }
}
function error(err) {
    console.log(err);
}

return {
    getId: function () {
        return localId;
    },

    setLocalStream: function (stream) {

        // if local cam has been stopped, remove it from all outgoing streams.
        if (!stream) {
            for (id in peerDatabase) {
                pc = peerDatabase[id].pc;
                if (!!pc.getLocalStreams().length) {
                    pc.removeStream(localStream);
                    offer(id);
                }
            }
        }

        localStream = stream;
    },

    toggleLocalStream: function (remoteId) {
        peer = peerDatabase[remoteId] || addPeer(remoteId);
        toggleLocalStream(peer.pc);
    },

    peerInit: function (remoteId) {
        peer = peerDatabase[remoteId] || addPeer(remoteId);
        console.log('send init');
        send('init', remoteId, null);

    },

    peerRenegociate: function (remoteId) {
        offer(remoteId);
    },

    send: function (type, payload) {
        socket.emit(type, payload);
    }
};

});
var Peer = function (pcConfig, pcConstraints) {
    this.pc = new RTCPeerConnection(pcConfig, pcConstraints);
    this.remoteVideoEl = document.createElement('video');
    this.remoteVideoEl.controls = true;
    this.remoteVideoEl.autoplay = true;
}

这是我的 Adapter.js

/*
 *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree.
 */

/*
 *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree.
 */

'use strict';

var RTCPeerConnection = null;
var getUserMedia = null;
var attachMediaStream = null;
var reattachMediaStream = null;
var webrtcDetectedBrowser = null;
var webrtcDetectedVersion = null;

function maybeFixConfiguration(pcConfig) {
  if (!pcConfig) {
    return;
  }
  for (var i = 0; i < pcConfig.iceServers.length; i++) {
    if (pcConfig.iceServers[i].hasOwnProperty('urls')) {
      pcConfig.iceServers[i].url = pcConfig.iceServers[i].urls;
      delete pcConfig.iceServers[i].urls;
    }
  }
}

if (navigator.mozGetUserMedia) {
  console.log('This appears to be Firefox');

  window.webrtcDetectedBrowser = 'firefox';

  window.webrtcDetectedVersion =
    parseInt(navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1], 10);

  // The RTCPeerConnection object.
  RTCPeerConnection = function (pcConfig, pcConstraints) {
    // .urls is not supported in FF yet.
    maybeFixConfiguration(pcConfig);
    return new mozRTCPeerConnection(pcConfig, pcConstraints);
  };

  // The RTCSessionDescription object.
  RTCSessionDescription = mozRTCSessionDescription;

  // The RTCIceCandidate object.
  RTCIceCandidate = mozRTCIceCandidate;

  // Get UserMedia (only difference is the prefix).
  // Code from Adam Barth.
  window.getUserMedia = navigator.mozGetUserMedia.bind(navigator);
  navigator.getUserMedia = getUserMedia;

  // Creates iceServer from the url for FF.
  window.createIceServer = function (url, username, password) {
    var iceServer = null;
    var urlParts = url.split(':');
    if (urlParts[0].indexOf('stun') === 0) {
      // Create iceServer with stun url.
      iceServer = {
        'url': url
      };
    } else if (urlParts[0].indexOf('turn') === 0) {
      if (webrtcDetectedVersion < 27) {
        // Create iceServer with turn url.
        // Ignore the transport parameter from TURN url for FF version <=27.
        var turnUrlParts = url.split('?');
        // Return null for createIceServer if transport=tcp.
        if (turnUrlParts.length === 1 ||
          turnUrlParts[1].indexOf('transport=udp') === 0) {
          iceServer = {
            'url': turnUrlParts[0],
            'credential': password,
            'username': username
          };
        }
      } else {
        // FF 27 and above supports transport parameters in TURN url,
        // So passing in the full url to create iceServer.
        iceServer = {
          'url': url,
          'credential': password,
          'username': username
        };
      }
    }
    return iceServer;
  };

  window.createIceServers = function (urls, username, password) {
    var iceServers = [];
    // Use .url for FireFox.
    for (var i = 0; i < urls.length; i++) {
      var iceServer = createIceServer(urls[i],
        username,
        password);
      if (iceServer !== null) {
        iceServers.push(iceServer);
      }
    }
    return iceServers;
  };

  // Attach a media stream to an element.
  window.attachMediaStream = function (element, stream) {
    console.log('Attaching media stream');
    element.mozSrcObject = stream;
    element.play();
  };

  window.reattachMediaStream = function (to, from) {
    console.log('Reattaching media stream');
    to.mozSrcObject = from.mozSrcObject;
    to.play();
  };

} else if (navigator.webkitGetUserMedia) {
  console.log('This appears to be Chrome');

  window.webrtcDetectedBrowser = 'chrome';
  // Temporary fix until crbug/374263 is fixed.
  // Setting Chrome version to 999, if version is unavailable.
  var result = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);
  if (result !== null) {
    window.webrtcDetectedVersion = parseInt(result[2], 10);
  } else {
    window.webrtcDetectedVersion = 999;
  }

  // Creates iceServer from the url for Chrome M33 and earlier.
  window.createIceServer = function (url, username, password) {
    var iceServer = null;
    var urlParts = url.split(':');
    if (urlParts[0].indexOf('stun') === 0) {
      // Create iceServer with stun url.
      iceServer = {
        'url': url
      };
    } else if (urlParts[0].indexOf('turn') === 0) {
      // Chrome M28 & above uses below TURN format.
      iceServer = {
        'url': url,
        'credential': password,
        'username': username
      };
    }
    return iceServer;
  };

  // Creates iceServers from the urls for Chrome M34 and above.
  window.createIceServers = function (urls, username, password) {
    var iceServers = [];
    if (webrtcDetectedVersion >= 34) {
      // .urls is supported since Chrome M34.
      iceServers = {
        'urls': urls,
        'credential': password,
        'username': username
      };
    } else {
      for (var i = 0; i < urls.length; i++) {
        var iceServer = createIceServer(urls[i],
          username,
          password);
        if (iceServer !== null) {
          iceServers.push(iceServer);
        }
      }
    }
    return iceServers;
  };

  // The RTCPeerConnection object.
  RTCPeerConnection = function (pcConfig, pcConstraints) {
    // .urls is supported since Chrome M34.
    if (webrtcDetectedVersion < 34) {
      maybeFixConfiguration(pcConfig);
    }
    return new webkitRTCPeerConnection(pcConfig, pcConstraints);
  };

  // Get UserMedia (only difference is the prefix).
  // Code from Adam Barth.
  window.getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
  navigator.getUserMedia = getUserMedia;

  // Attach a media stream to an element.
  window.attachMediaStream = function (element, stream) {
    if (typeof element.srcObject !== 'undefined') {
      element.srcObject = stream;
    } else if (typeof element.mozSrcObject !== 'undefined') {
      element.mozSrcObject = stream;
    } else if (typeof element.src !== 'undefined') {
      element.src = URL.createObjectURL(stream);
    } else {
      console.log('Error attaching stream to element.');
    }
  };

  window.reattachMediaStream = function (to, from) {
    to.src = from.src;
  };
} else {
  console.log('Browser does not appear to be WebRTC-capable');
}


// Returns the result of getUserMedia as a Promise.
function requestUserMedia(constraints) {
  return new Promise(function (resolve, reject) {
    var onSuccess = function (stream) {
      resolve(stream);
    };
    var onError = function (error) {
      reject(error);
    };

    try {
      getUserMedia(constraints, onSuccess, onError);
    } catch (e) {
      reject(e);
    }
  });
}

if (typeof module !== 'undefined') {
  module.exports = {
    RTCPeerConnection: RTCPeerConnection,
    getUserMedia: getUserMedia,
    attachMediaStream: attachMediaStream,
    reattachMediaStream: reattachMediaStream,
    webrtcDetectedBrowser: webrtcDetectedBrowser,
    webrtcDetectedVersion: webrtcDetectedVersion
    //requestUserMedia: not exposed on purpose.
    //trace: not exposed on purpose.
  };
}

STUN AND TURN ICE Details

SDP

SDP local

v=0

o=mozilla...THIS_IS_SDPARTA-52.0.2 4443962319420549785 0 IN IP4 0.0.0.0

s=-

t=0 0

a=sendrecv

a=fingerprint:sha-256 A0:E0:C7:7E:3A:3B:4E:88:14:A9:D4:1F:A6:08:0B:C6:97:05:BC:33:4B:A5:CE:F8:CC:20:79:B1:BC:96:AF:17

a=group:BUNDLE sdparta_0 sdparta_1

a=ice-options:trickle

a=msid-semantic:WMS *

m=audio 62832 UDP/TLS/RTP/SAVPF 109 101

c=IN IP4 190.117.88.12

a=candidate:0 1 UDP 2122252543 ::38c8:a270:c7ff:d856 62830 typ host

a=candidate:6 1 UDP 2122187007 ::b43e:ec0d:7743:c6 62831 typ host

a=candidate:12 1 UDP 2122121471 192.168.0.38 62832 typ host

a=candidate:13 1 UDP 1685921791 190.117.88.12 62832 typ srflx raddr 192.168.0.38 rport 62832

a=sendrecv

a=end-of-candidates

a=fmtp:109 maxplaybackrate=48000;stereo=1;useinbandfec=1

a=fmtp:101 0-15

a=ice-pwd:51e616b53508d2921fdde4894fe81529

a=ice-ufrag:9bfab4a4

a=mid:sdparta_0

a=msid:{2d638fea-7857-49cb-80a8-985d96460b21} {b82b166d-9a6e-4fc5-a10e-bb597ce567f6}

a=rtcp-mux

a=rtpmap:109 opus/48000/2

a=rtpmap:101 telephone-event/8000

a=setup:active

a=ssrc:2090540075 cname:{794f53ca-9dd9-43f0-8d17-babc96ab5d2d}

m=video 62832 UDP/TLS/RTP/SAVPF 120

c=IN IP4 190.117.88.12

a=sendrecv

a=fmtp:120 max-fs=12288;max-fr=60

a=ice-pwd:51e616b53508d2921fdde4894fe81529

a=ice-ufrag:9bfab4a4

a=mid:sdparta_1

a=msid:{2d638fea-7857-49cb-80a8-985d96460b21} {16b00fa2-9fbd-48ed-acd7-f14d80f4fa5d}

a=rtcp-fb:120 nack

a=rtcp-fb:120 nack pli

a=rtcp-fb:120 ccm fir

a=rtcp-fb:120 goog-remb

a=rtcp-mux

a=rtpmap:120 VP8/90000

a=setup:active

a=ssrc:2849290137 cname:{794f53ca-9dd9-43f0-8d17-babc96ab5d2d}

SDP remoto

v=0

o=mozilla...THIS_IS_SDPARTA-52.0.2 4028535757436800601 0 IN IP4 0.0.0.0

s=-

t=0 0

a=sendrecv

a=fingerprint:sha-256 E6:53:BD:DC:C0:74:F0:DE:2B:53:60:BF:41:45:F3:6D:61:64:82:FC:C4:61:0E:52:11:1F:A3:17:EF:58:4C:81

a=group:BUNDLE sdparta_0 sdparta_1

a=ice-options:trickle

a=msid-semantic:WMS *

m=audio 9 UDP/TLS/RTP/SAVPF 109 9 0 8 101

c=IN IP4 0.0.0.0

a=candidate:0 1 UDP 2122252543 192.168.1.101 62841 typ host

a=candidate:0 2 UDP 2122252542 192.168.1.101 62842 typ host

a=candidate:1 1 UDP 1686052863 181.66.165.192 5654 typ srflx raddr 192.168.1.101 rport 62841

a=candidate:1 2 UDP 1686052862 181.66.165.192 5655 typ srflx raddr 192.168.1.101 rport 62842

a=sendrecv

a=extmap:1/sendonly urn:ietf:params:rtp-hdrext:ssrc-audio-level

a=fmtp:109 maxplaybackrate=48000;stereo=1;useinbandfec=1

a=fmtp:101 0-15

a=ice-pwd:84d2a654605c91ba448fc90003f8c79e

a=ice-ufrag:0628a660

a=mid:sdparta_0

a=msid:{e08aacff-06fd-4f6d-ba42-408b4948501d} {209331a1-d401-4dea-8667-cf81750a5a63}

a=rtcp-mux

a=rtpmap:109 opus/48000/2

a=rtpmap:9 G722/8000/1

a=rtpmap:0 PCMU/8000

a=rtpmap:8 PCMA/8000

a=rtpmap:101 telephone-event/8000

a=setup:actpass

a=ssrc:1248822540 cname:{f918048b-0188-438e-b0bb-a223d8d4ae07}

m=video 9 UDP/TLS/RTP/SAVPF 120 121 126 97

c=IN IP4 0.0.0.0

a=candidate:0 1 UDP 2122252543 192.168.1.101 62843 typ host

a=candidate:0 2 UDP 2122252542 192.168.1.101 62844 typ host

a=candidate:1 1 UDP 1686052863 181.66.165.192 5656 typ srflx raddr 192.168.1.101 rport 62843

a=candidate:1 2 UDP 1686052862 181.66.165.192 5657 typ srflx raddr 192.168.1.101 rport 62844

a=sendrecv

a=fmtp:126 profile-level-id=42e01f;level-asymmetry-allowed=1;packetization-mode=1

a=fmtp:97 profile-level-id=42e01f;level-asymmetry-allowed=1

a=fmtp:120 max-fs=12288;max-fr=60

a=fmtp:121 max-fs=12288;max-fr=60

a=ice-pwd:84d2a654605c91ba448fc90003f8c79e

a=ice-ufrag:0628a660

a=mid:sdparta_1

a=msid:{e08aacff-06fd-4f6d-ba42-408b4948501d} {7a9fa748-c382-4134-a3d4-b7e48afa95fa}

a=rtcp-fb:120 nack

a=rtcp-fb:120 nack pli

a=rtcp-fb:120 ccm fir

a=rtcp-fb:120 goog-remb

a=rtcp-fb:121 nack

a=rtcp-fb:121 nack pli

a=rtcp-fb:121 ccm fir

a=rtcp-fb:121 goog-remb

a=rtcp-fb:126 nack

a=rtcp-fb:126 nack pli

a=rtcp-fb:126 ccm fir

a=rtcp-fb:126 goog-remb

a=rtcp-fb:97 nack

a=rtcp-fb:97 nack pli

a=rtcp-fb:97 ccm fir

a=rtcp-fb:97 goog-remb

a=rtcp-mux

a=rtpmap:120 VP8/90000

a=rtpmap:121 VP9/90000

a=rtpmap:126 H264/90000

a=rtpmap:97 H264/90000

a=setup:actpass

a=ssrc:109206018 cname:{f918048b-0188-438e-b0bb-a223d8d4ae07}

Estadísticas RDP
inbound_rtp_audio_0

Local: 19:08:53 GMT-0500 inboundrtp SSRC: 0
inbound_rtp_video_1

Local: 19:08:53 GMT-0500 inboundrtp SSRC: 0
outbound_rtp_video_1

Local: 19:08:53 GMT-0500 outboundrtp SSRC: 2849290137
outbound_rtp_audio_0

Local: 19:08:53 GMT-0500 outboundrtp SSRC: 2090540075

请帮助我

最佳答案

您的浏览器不会收集任何带有“typrelay”的候选者,仅收集“typhost”和“typsrflx”。这表明您使用的凭据是错误的。请参阅"Example 1 - My WebRTC app works locally but not on a different network!"部分

服务器列表看起来您正在尝试使用“免费”服务器并且...不,没有免费服务器。

关于javascript - ICE 在不同网络中的 WebRTC 失败 [Firefox],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43432544/

相关文章:

javascript - 如何将字符串转换为 JavaScript 数组

javascript - 调整内容滚动侧边栏的大小

javascript - 我本地网页上的 moviemodeapp 脚本

javascript - 将 FireBug 用于带框架的网站

javascript - 有人可以解释 WebRTC API 文档吗?

javascript - 使用 Vue 移动 SVG

javascript - FullCalendar anchor 的标题属性为空

laravel - Firefox 强制开发域使用 SSL 和 Chrome

react-native - 如何将选定的文件读入字节或流中

javascript - 无法更改 WebRTC 调用的摄像头/流