2015-08-21 14 views
5

Scenariusz: Chciałbyś wiedzieć, czy serwer TURN jest używany do określonego połączenia, a który z tablicy serwerów TURN podanych podczas tworzenia PeerConnection, jest używany. Nie Ale kiedy jesteś za firmowym pełnomocnika i skręcić serwer jest poza tym, Wireshark pokaże IP proxy jako miejsca docelowego (również wzmianka niedogodności prowadzenia go: teraz istnieją dwie opcje:WebRTC: Określ, który serwer TURN jest używany w PeerConnection

  • Wireshark. w tle)
  • przeżywa strony statystykami i dowiedzieć się, chrom -> chrome: // WebRTC-internals i Firefox -> o: WebRTC

Chciałbym użyć alternatywą dla powyżej dwa, programowo określić to, więc nie muszę opuszczać mojej strony aplikacji.

+0

https://github.com/webrtc/apprtc/pull/99 pokazuje, w jaki sposób dowiedzieć się, rodzaj używanego serwera TURN (UDP, TCP, TLS) - to robi Działa w Firefoksie, ale jest to głównie kwestia, że ​​próbka apprtc jest nieco w tyle. –

Odpowiedz

3

Aktualizacja: Zaktualizowałem przykład, aby śledzić najnowszą specyfikację, z maplikegetStats.

Następujące podejście jest zgodne z the specification i obecnie działa tylko w przeglądarce Firefox, ponieważ Chrome w tej chwili nieprawidłowo implementuje getStats(). Mamy nadzieję, że wkrótce pojawi się wersja polyfillu adapter.js, która sprawi, że będzie działać również w Chrome.

Po uruchomieniu this fiddle w Firefoksie, zobaczysz:

checking 
connected 
Does not use TURN 

To dlatego, że przykładem zapewnia zarówno STUN i serwer TURN. Ale kiedy modyfikować config do korzystania tylko z iceTransportPolicy: "relay" TURN widzę:

checking 
connected 
Uses TURN server: 10.252.73.50 

Należy pamiętać, że serwer kolej używam jest za VPN, więc nie będzie pracować dla Ciebie, ale czuć się swobodnie modyfikować skrzypiec z własnym serwerem (po prostu nie zapisuj go, chyba że chcesz, aby informacje stały się publicznie dostępne).

Chociaż nie testowałem więcej niż z jednym serwerem, jak widać, wyświetlony adres IP odpowiada skrętowi skonfigurowany serwer, więc powinno być możliwe określenie, który serwer jest używany przy użyciu tego podejścia.

// Turn server is on Mozilla's VPN. 
 
var cfg = { iceTransportPolicy: "all", // set to "relay" to force TURN. 
 
      iceServers: [{ urls: "stun:stun.l.google.com:19302" }, 
 
         { urls: "turn:10.252.73.50", 
 
          username:"webrtc", credential:"firefox" }] }; 
 
var pc1 = new RTCPeerConnection(cfg), pc2 = new RTCPeerConnection(cfg); 
 

 
pc1.onicecandidate = e => pc2.addIceCandidate(e.candidate); 
 
pc2.onicecandidate = e => pc1.addIceCandidate(e.candidate); 
 
pc2.oniceconnectionstatechange =() => log(pc2.iceConnectionState); 
 
pc2.onaddstream = e => v2.srcObject = e.stream; 
 

 
var findSelected = stats => 
 
    [...stats.values()].find(s => s.type == "candidate-pair" && s.selected); 
 

 
var start =() => navigator.mediaDevices.getUserMedia({ video: true }) 
 
    .then(stream => pc1.addStream(v1.srcObject = stream)) 
 
    .then(() => pc1.createOffer()).then(d => pc1.setLocalDescription(d)) 
 
    .then(() => pc2.setRemoteDescription(pc1.localDescription)) 
 
    .then(() => pc2.createAnswer()).then(d => pc2.setLocalDescription(d)) 
 
    .then(() => pc1.setRemoteDescription(pc2.localDescription)) 
 
    .then(() => waitUntil(() => pc1.getStats().then(s => findSelected(s)))) 
 
    .then(() => pc1.getStats()) 
 
    .then(stats => { 
 
    var candidate = stats.get(findSelected(stats).localCandidateId); 
 
    if (candidate.candidateType == "relayed") { 
 
     log("Uses TURN server: " + candidate.ipAddress); 
 
    } else { 
 
     log("Does not use TURN (uses " + candidate.candidateType + ")."); 
 
    } 
 
    }) 
 
    .catch(log); 
 

 
var waitUntil = f => Promise.resolve(f()) 
 
    .then(done => done || wait(200).then(() => waitUntil(f))); 
 

 
var wait = ms => new Promise(resolve => setTimeout(resolve, ms)); 
 
var log = msg => div.innerHTML += msg +"<br>"; 
 
var failed = e => log(e +", line "+ e.lineNumber);
<video id="v1" width="108" height="81" autoplay></video> 
 
<video id="v2" width="108" height="81" autoplay></video><br> 
 
<button onclick="start()">Start!</button><br><div id="div"></div> 
 
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>

+0

popełniłem błąd zakładając, że zawsze musisz zapewnić mediatrack, aby otrzymywać statystyki, dzięki za wyczyszczenie tego. – mido

+0

dla mnie problem polega na tym, że niektóre porty przestają reagować na serwerze TURN (uruchamianym na instancji EC2), więc uruchamiam je na wielu portach, więc chociaż możemy uzyskać IP ze statystyk rtc, port wciąż pozostaje tajemnicą. – mido

+0

@ mido22 'candidate.portNumber' powinien podać numer portu. Zobacz [tutaj] (http://w3c.github.io/webrtc-stats/#idl-def-RTCIceCandidateAttributes). – jib

3

pisałem i przetestowane poniższy kawałek kodu, pracuje w najnowszych wersjach zarówno Firefox i Chrome, getConnectionDetails zwraca obietnicę, która postanawia szczegóły połączenia:

function getConnectionDetails(peerConnection){ 


    var connectionDetails = {}; // the final result object. 

    if(window.chrome){ // checking if chrome 

    var reqFields = [ 'googLocalAddress', 
         'googLocalCandidateType', 
         'googRemoteAddress', 
         'googRemoteCandidateType' 
        ]; 
    return new Promise(function(resolve, reject){ 
     peerConnection.getStats(function(stats){ 
     var filtered = stats.result().filter(function(e){return e.id.indexOf('Conn-audio')==0 && e.stat('googActiveConnection')=='true'})[0]; 
     if(!filtered) return reject('Something is wrong...'); 
     reqFields.forEach(function(e){connectionDetails[e.replace('goog', '')] = filtered.stat(e)}); 
     resolve(connectionDetails); 
     }); 
    }); 

    }else{ // assuming it is firefox 
    return peerConnection.getStats(null).then(function(stats){ 
     var selectedCandidatePair = stats[Object.keys(stats).filter(function(key){return stats[key].selected})[0]] 
      , localICE = stats[selectedCandidatePair.localCandidateId] 
      , remoteICE = stats[selectedCandidatePair.remoteCandidateId]; 
     connectionDetails.LocalAddress = [localICE.ipAddress, localICE.portNumber].join(':'); 
     connectionDetails.RemoteAddress = [remoteICE.ipAddress, remoteICE.portNumber].join(':'); 
     connectionDetails.LocalCandidateType = localICE.candidateType; 
     connectionDetails.RemoteCandidateType = remoteICE.candidateType; 
     return connectionDetails; 
    }); 

    } 
} 

chciałbym podkreślić jedną rzecz, wszystko te trzy metody kończą się niepowodzeniem w jednym scenariuszu: serwery dwukierunkowe uruchamiane z tego samego komputera na różnych portach, a jedynie niezawodny sposób, w jaki znalazłem przeglądanie dzienników serwera skrętu.

+0

Dzięki za to! Zauważyłem, że około 25% przypadków nie ma wpisów "Conn-audio" w wynikach, mimo że stan połączenia ICE jest "zakończony". Jakiś pomysł, dlaczego tak się dzieje? –

+0

@RobAgar nie jest pewien, co jest przyczyną tego problemu, spytaj jib lub hancke, mają lepsze zrozumienie – mido