2015-08-21 12 views
5

Scenario: Si desidera sapere se il server TURN viene utilizzato per una particolare chiamata e quale dall'array di server TURN fornito durante la creazione di PeerConnection, viene utilizzato. In questo momento ci sono due opzioni:WebRTC: Determina quale server TURN viene utilizzato in PeerConnection

  • Wireshark: Ma quando si è dietro un proxy aziendale e girare server è al di fuori che, Wireshark avrebbero mostrano l'IP proxy come destinazione (anche senza la menzione l'inconveniente di eseguirlo. sullo sfondo)
  • Passando attraverso la pagina delle statistiche e scoprire, cromo -> chrome: // WebRTC-internals e Firefox -> a proposito di: WebRTC

Vorrei usare un'alternativa al sopra due, determina questo in modo programmatico in modo da non dover uscire dalla pagina dell'applicazione.

+0

https://github.com/webrtc/apprtc/pull/99 mostra come capire il tipo di server TURN utilizzato (UDP, TCP, TLS) - doesn Lavoriamo con Firefox, ma questo è in gran parte un problema del campione apprtc leggermente indietro. –

risposta

3

Aggiornamento: Ho aggiornato l'esempio per seguire le ultime specifiche, con maplikegetStats.

Il seguente approccio segue the specification e attualmente funziona solo in Firefox, poiché Chrome implementa getStats() in modo errato al momento. Speriamo che presto sia disponibile una versione del polyfill adapter.js che farà funzionare anche in Chrome.

Quando si esegue this fiddle in Firefox, vedrete:

checking 
connected 
Does not use TURN 

Questo perché l'esempio fornisce sia uno STUN e un server TURN. Ma quando modifico la configurazione da utilizzare girare solo con iceTransportPolicy: "relay", vedo:

checking 
connected 
Uses TURN server: 10.252.73.50 

Nota che il server di turno che uso è dietro una VPN, quindi non funzionerà per voi, ma sentitevi liberi di modificare la giocare con il tuo server (basta non salvarlo a meno che tu non voglia che le informazioni diventino pubbliche!)

Mentre non ho provato con più di un server di turno, come puoi vedere l'indirizzo IP mostrato corrisponde alla svolta server configurato, quindi dovrebbe essere possibile dire quale server viene utilizzato utilizzando questo approccio.

// 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

commesso un errore nell'assumere che tu abbia sempre bisogno di fornire un mediatrack per ricevere statistiche, grazie per averlo chiarito. – mido

+0

per me il problema è, a volte certe porte non rispondono al server TURN (eseguito su un'istanza EC2), quindi le eseguo su più porte, quindi sebbene possiamo ottenere l'IP da statistiche rtc, la porta sarebbe ancora un mistero – mido

+0

@ mido22 'candidate.portNumber' dovrebbe darti il ​​numero di porta. Vedi [qui] (http://w3c.github.io/webrtc-stats/#idl-def-RTCIceCandidateAttributes). – jib

3

ho scritto e testati il ​​pezzo di sotto del codice, lavora a tutte le versioni di Firefox e Chrome, getConnectionDetails restituisce una promessa che si risolve per i dettagli di connessione:

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; 
    }); 

    } 
} 

vorrei sottolineare una cosa, tutto questi tre metodi non riescono in uno scenario: due server di turno che girano dalla stessa macchina su porte diverse, solo il modo affidabile che ho trovato era osservare i registri del server di turno.

+0

Grazie per questo! Sto trovando che circa il 25% delle volte non ci sono voci "Conn-audio" nei risultati, anche se lo stato della connessione ICE è "completato". Qualche idea sul perché potrebbe essere? –

+0

@RobAgar non è sicuro di quale sia la causa del problema, prova a chiedere jib o hancke, hanno una migliore comprensione – mido

Problemi correlati