Cos’è e come funziona WebRTC
In questa serie di articoli cercherò di spiegare come attivare una comunicazione real-time via web sfruttando WebRTC e condividerò allo scopo anche alcuni esempi per entrare operativamente nel vivo del protocollo. Prima di iniziare con la spiegazione più tecnica voglio precisare che sebbene il protocollo WebRTC siano noto per le comunicazioni audio/video in realtà è uno strumento molto potente e più generale anche per far scambiare semplicemente dati tra due peer.
Che cosa è WebRTC
WebRTC acronimo di Web Real-Time Comunication, è un progetto open source che permette ad un browser web e/o ad applicazioni mobile la comunicazione in real time tramite l’uso di API (Application Programming Interface). Esso garantisce il collegamento audio/video all’interno di pagine web/webview permettendo comunicazioni peer-to-peer senza la necessità di plug-in supplementari.
Il protocollo WebRTC, infatti, è supportato diffusamente dai principali browser ed è stato standardizzato dal World Wide Web Consortium (W3c) e dall’Internet Engineering task Force (IETF).
WebRTC come detto permette la comunicazione peer-to-peer, ma per funzionare ha comunque bisogno di uno o più server a supporto per poter gestire le varie fasi della della comunicazione e per consentire ai client di:
- scambiare metadati e coordinare le comunicazione tra i client ( signaling )
- gestire le comunicazione attraverso i firewall.
Il server di signaling, assume un ruolo molto importante in quanto il meccanismo di segnalazione è fondamentale per la corretta gestione di una connessione WebRTC, perché di fatto è il processo che si occupa di coordinare la comunicazione e di consentire ad un’applicazione WebRTC di instaurare una chiamata. Il processo di signaling gestisce, infatti, l’intero ciclo di vita di una chiamata e consente di scambiare informazioni quali:
- Messaggi di controllo per aprire e chiudere la comunicazione
- Messaggi di errore
- Metadati sulle caratteristiche del media, quali ad esempio codec, impostazioni, larghezza di banda, tipo di media (audio/video)
- Dati per stabilire connessione sicure
- Dati di rete quali ad esempio l’indirizzo ip dei peer e la porte della socket
In una connessione WebRTC possono entrare in gioco , anche altri server quali : il turn e lo stun necessari in taluni casi per risolvere problematiche di rete e di visibilità dei peer derivanti dall’uso di NAT o dalla presenza di Firewall.
Come funziona?
Cerchiamo di capire quali sono le varie fasi per inizializzare una connessione WebRTC e quale entità verranno coinvolte nei vari step.
Come già anticipato per instaurare una connessione, i due client dovranno in prima istanza connettersi ad un server di segnalazione che consentirà ai due peer di entrare in contatto. L’inizializzazione e la terminazione della chiamata, infatti è determinata da messaggi di segnalazione scambiati con il server mediante protocolli HTTP o WebSocket, mentre lo scambio dei contenuti avverrà direttamente tra i client senza l’ausilio di server intermedi, tranne nel caso in cui i due clienti non siano direttamente visibili, in tal caso sarà necessario utilizzare un server intermedio quale il turn. E’ importante ricordare che il protocollo di segnalazione tra il client ed il server non è oggetto di standardizzazione in WebRTC, pertanto l’implementazione viene stata demandata all’applicazione e lasciata libera ad uso del progettista.
Come più volte ripetuto, prima che i due peer possano iniziare a scambiare dati tra di loro tramite WebRTC, è necessario che gli stessi si scambino informazioni preliminari, attraverso il server di segnalazione, necessarie per la negoziazione ed il rilevamento del formato e dei media.
Tutto ciò viene fatto tramite i seguenti protocolli.
- Session Description Protocol (SDP) che viene utilizzato per fornire i metadati del contenuto multimediale come risoluzione, codifica, bitrate, ecc.
- Interactive Connectivity Establishment (ICE) viene utilizzato per instaurare la connessione peer to peer.
N.B. nel caso i cui i due peer non si trovassero sulla stessa rete, si renderà necessario l’utilizzo di un server STUN (Session Traversal Utilities NAT) per ottenere l’indirizzo pubblico dei peer mentre nel caso in cui una qualsiasi delle reti fosse protetta da firewall, allora diventerebbe mandatorio l’ uso di TURN server ( Traversal Using Relays NAT ). |
Ipotizziamo, pertanto, per comprendere il flusso di collocarci nel caso generale, in cui i due peer siano protetti da Firewall e non stiano sulla stessa rete; inoltre darò per scontato, per la descrizione che segue, che i due peer abbiano già stabilito un connessione websocket con il server di segnalazione.
Di seguito riporto un tipico flusso WebRTC:
A questo punto cercherò di approfondire le entità coinvolte nel processo, dando qualche definizione e spiegazione generale, con la speranza di essere il più esaustivo possibile.
Che cosa è lo STUN
Come anticipato l’uso dello STUN si rende necessario quando i due peer non si trovano sulla stessa rete e si trovano su reti private nattate. Un server STUN, infatti, permetterà ai client dietro NAT di impostare opportunamente le chiamate webRTC all’esterno della rete locale ed ha il compito di fornire ai client alcune informazioni, quali il loro indirizzo pubblico, il tipo di NAT dietro al quale si trovano e il lato della porta internet associato dal NAT con una particolare porta locale. Questa informazione è usata per impostare la comunicazione tra i peer in modo da stabilire una connessione. Il protocollo STUN è spiegato nella RFC 3489.
Che cosa è Il NAT
Il NAT ( Network Address Translation) è un meccanismo che consente di mascherare indirizzi di rete privati su rete pubblica e viene implementato sul gateway per consentire ad un host con indirizzo di rete privata di poter comunicare con host su rete pubblica (internet). Il NAT è spiegato nella RFC2663, RFC1631
Che cosa è il TURN
Poiché la maggior parte delle applicazioni WebRTC funzioni, in via generale è necessario utilizzare un server per inoltrare il traffico tra peer, poiché spesso essi non sono in diretto contatto (a meno che non risiedano sulla stessa rete locale). Per risolvere il problema è possibile utilizzare un server TURN ( Traversal Using Relay NAT ) che di fatto implementa un protocollo per l’inoltro del traffico di rete.
Esistono attualmente diverse possibilità per utilizzare server TURN. C’è ne sono, infatti, disponibili online, sia come applicazioni self-hosted (come il progetto COTURN open source) sia come servizi forniti in cloud.
Una volta individuato/installato un server TURN, tutto ciò che serve è la corretta configurazione RTCC affinché l’applicazione client possa utilizzarlo. Il pezzo di codice seguente illustra una configurazione di esempio per RTCPeerConnection il cui server TURN ha il nome host my-turn-server.mycompany.com ed è in esecuzione sulla porta 19403.
const iceConfiguration = { iceServers: [ { urls: 'turn:my-turn-server.mycompany.com:19403', username: 'optional-username', credentials: 'auth-token' } ] } const peerConnection = new RTCPeerConnection(iceConfiguration);
API WebRTC
Di seguito riporto le API principali messe a disposizione dal protocollo WebRTC delle quali proverò a spiegarne il significato ed il modo di utilizzarle:
- getUserMedia: acquisisce i media audio e video, il metodo consente di accedere alla telecamera ed al microfono del pc o dello smartphone.
- RTCPeerConnection: permette il collegamento audio/video tra peer. Questo metodo provvede alla gestione della codifica e della decodifica, alla comunicazione peer-to-peer, alla sicurezza ed alla gestione della banda.
- RTCDataChannel: permette la comunicazione bidirezionale dei dati tra i peer attraverso un connessione WebSocket a bassa latenza.
- getStats, che permettono all’applicazione di raccogliere un insieme di statistiche inerenti la sessione attiva.
getUserMedia
Le Media Stream API (dette anche getUserMedia) danno la possibilità, previo consenso dell’utente, di accedere al flusso video proveniente dalla webcam ed al flusso audio proveniente dal microfono situati sul device che l’utente sta utilizzando in quel momento.
Per usare getUserMedia è molto semplice :
<html> <head> </head> <body> <div id="Container"> <video autoplay="true" width="640" height="480" id="videoElement"></video> <input type="button" id="start" Value="START" /> </div> </body> </html> <script> jQuery(document).ready(function(){ jQuery("#start").click(function () { startVideo(); }) })
function startVideo() { var video = document.querySelector('video'),canvas; imageElement=video; console.log("navigator " + navigator.mediaDevices) if (navigator.mediaDevices) { // access the web cam navigator.mediaDevices.getUserMedia({ video: true }) // permission granted: .then(function(stream) { //video.src = window.URL.createObjectURL(stream); video.srcObject = stream; }) // permission denied: .catch(function(error) { document.body.textContent = 'Could not access the camera.Error:' + error.name; }); } return imageElement; } </script>
Live Demo
Attivazione della connessione
A questo punto dovrebbe essere abbastanza chiara la procedura per ottenere un flusso video da una camera usando getUserMedia, per cui possiamo andare oltre e capire come si può inoltrare il flusso ad un peer remoto. A tal proposito dobbiamo capire come funziona una tipica connessione WebRTC ed approfondire in prima istanza :
RTCPeerConnection
La funzione di RTCPeerConnection è quella di mettere in contatto due device in modalità peer-to-peer. La procedura che ci consente di attuare questo collegamento è la seguente :
Dati due device, A e B. Supponiamo che A voglia contattare B , per aprire un canale peer-to-peer :
- A dovrà creare un oggetto RTCPeerConnection e dovrà mettersi in ascolto dell’evento onicecandidate che verrà restituito da B
- A dovrà comunicare a B l’identificatore univoco del proprio canale peer-to-peer quando riceverà l’evento onicecandidate
- B dovrà utilizzare il metodo addIceCandidate sul proprio oggetto RTCPeerConnection per aggiungere A come destinatario.
- A dovrà invocare createOffer e per generare una stringa SDP (Session Description Protocol) che dovrà essere inviata a B. Nel SDP saranno descritti i costraints al flusso audio/video (codec, etc.) del device.
- B riceverà la stringa SDP di A e genererà una SDP di risposta con il metodo createAnswer, che verrà inviata ad A.
- Sia A che B riceveranno l’evento addstream che conterrà il flusso dati del partner e potranno decidere di caricarlo in un elemento video come visto nell’esempio precedente.
Rivediamo il flusso da un punto di vista operativo:
Step 1 : Creare un’istanza dell’oggetto RTCPeerConnection che userà i server STUN per risolvere i problemi di NAT.
Step 2 : Una volta creta la RTCPeerConnection dovranno essere implementate tre funzioni di callback (onIceCandidate, onNegotiationNeeded e onAddStream) e assegnarle a RTCPeerConnection.
Step 3 : Creare onIceCandidate. Questo evento gestisce le risposte del server STUN al tuo client in merito all’attraversamento NAT / Firewall. Sarà necessario pertanto creare una funzione che accetta un oggetto RTCIceCandidate,
Step 4 : Creare onNegotiationNeeded. Questo evento si attiva nel caso in cui succede qualcosa che richiede una nuova negoziazione di sessione.
Step 5 : Creare onAddStream. Questo evento viene chiamato quando si chiama setRemoteDescription con le informazioni SDP o il proprio peer remoto. Quando scatta questo evento potrai gestire il flusso video.
Add dello stream
Per aggiungere uno stream alla connessione, sarà necessario innanzitutto crearlo, e per farlo dovremo usare getUserMedia che ci consente di ottenere il flusso video della videocamera o del microfono. Tenete in considerazione che il getUserMedia può essere invocato passando dei contraints e restituisce un success o un failure
if (navigator.mediaDevices) { // access the web cam navigator.mediaDevices.getUserMedia({ video: true }) .then(function(stream) { . . addStream(stream); console.log( 'stream ok'); }) .catch(function(error) { console.log( 'Could not access the camera.Error:' + error.name); });
I constraints sono dei parametri per definire ad esempio se la chiamata è video o audio o entrambe. Di che dimensione dovrebbe essere lo stream, il colore delle immagini trasmesse, eventuali filtri.
Success è un evento che scatta qualora sia andato tutto per il meglio ed in tal caso dovresti avere ottenuto la sessione video.
Failure evento che scatta nel caso di errore di accesso al device.
Sono amante della tecnologia e delle tante sfumature del mondo IT, ho partecipato, sin dai primi anni di università ad importanti progetti in ambito Internet proseguendo, negli anni, allo startup, sviluppo e direzione di diverse aziende; Nei primi anni di carriera ho lavorato come consulente nel mondo dell’IT italiano, partecipando attivamente a progetti nazionali ed internazionali per realtà quali Ericsson, Telecom, Tin.it, Accenture, Tiscali, CNR. Dal 2010 mi occupo di startup mediante una delle mie società techintouch S.r.l che grazie alla collaborazione con la Digital Magics SpA, di cui sono Partner la Campania, mi occupo di supportare ed accelerare aziende del territorio .
Attualmente ricopro le cariche di :
– CTO MareGroup
– CTO Innoida
– Co-CEO in Techintouch s.r.l.
– Board member in StepFund GP SA
Manager ed imprenditore dal 2000 sono stato,
CEO e founder di Eclettica S.r.l. , Società specializzata in sviluppo software e System Integration
Partner per la Campania di Digital Magics S.p.A.
CTO e co-founder di Nexsoft S.p.A, società specializzata nella Consulenza di Servizi in ambito Informatico e sviluppo di soluzioni di System Integration, CTO della ITsys S.r.l. Società specializzata nella gestione di sistemi IT per la quale ho partecipato attivamente alla fase di startup.
Sognatore da sempre, curioso di novità ed alla ricerca di “nuovi mondi da esplorare“.
Comments