Chez Voximplant, nous utilisons WebRTC depuis sa création: d'abord comme alternative à Flash pour les appels vocaux et vidéo, puis comme remplacement complet. La technologie a parcouru un chemin de développement long et douloureux, ce n'est que récemment que tous les principaux navigateurs ont commencé à la prendre en charge, il y a des difficultés avec le transfert d'écran, plusieurs flux vidéo et parfois le navigateur se bloque simplement si vous désactivez et activez le flux vidéo. L'expérience accumulée nous permet de traduire des articles intéressants pour Habr, et aujourd'hui nous passons le mot à Lee Sylvester de Xirsys, qui parlera de débogage (vidéo) des appels dans Chrome, Firefox, Safari et Edge. Le débogage de WebRTC n'est pas facile, nous avons même des
instructions spéciales pour supprimer les journaux dans les navigateurs populaires. Et ce que Lee a - vous le découvrirez sous la coupe (spoiler: beaucoup de tout, y compris WireShark).
Le côté obscur de WebRTC
En travaillant chez Xirsys, j'ai vu des applications vraiment cool qui utilisaient WebRTC. Mais alors qu'un petit groupe de développeurs crée des trucs de haute technologie, la plupart des programmeurs ne peuvent même pas commencer à utiliser WebRTC. Pourquoi? Et tout est simple. C'est compliqué.
Beaucoup d'entre nous connaissent une application Web typique. Une telle application a un client qui envoie des requêtes et un serveur qui répond à ces requêtes. Un processus simple, linéaire et facilement prévisible. En cas de problème, nous savons généralement où consulter les journaux et ce qui pourrait arriver. Mais avec WebRTC, tout n'est pas si simple.
Asynchronie
Si vous avez déjà écrit une application multi-thread, vous connaissez probablement le mal de tête que ce développement apporte. Vols, mauvaise mémoire - mais le plus souvent seulement des bugs difficiles à trouver.
WebRTC est de nature asynchrone. Et ce n'est pas du tout la simple asynchronie AJAX. Pour faire une analogie, ce sont plusieurs requêtes AJAX lancées simultanément qui tentent de réconcilier les données sur deux ordinateurs. C'est toujours du divertissement.
Champ de mines de contournement NAT
La création d'applications Web revient à développer quelque chose qui s'exécute sur le serveur et répond aux demandes. La pire chose qui puisse arriver est le port qui n'est pas ouvert dans IPTables. Il est traité en 2 minutes. Vous ne pouvez pas dire sur WebRTC.
Les serveurs Web, pas même leurs logiciels, mais leur matériel, sont des appareils avec des adresses IP publiques. Ils sont faits pour être accessibles de partout. Et WebRTC est conçu pour envoyer et recevoir des données à partir des ordinateurs des utilisateurs. Qui ont généralement une adresse IP de 192.168. Quelque chose et ne brûle pas avec le désir de répondre aux demandes du réseau.
Les auteurs de WebRTC le savent, de sorte que le moteur triera différentes méthodes de connexion, dans le but d'établir une connexion entre deux ordinateurs qui ne sont pas très conçus pour cela.
Par où commencer le débogage
Dans cet article, je parle des outils de base pour résoudre les problèmes les plus courants. Mais avant cela, voyons comment WebRTC établit généralement une connexion.
Comment WebRTC établit une connexion
Toutes les connexions WebRTC nécessitent un peu d'aide du protocole de signalisation. «Peu d'aide» est votre propre serveur et protocole avec lequel l'appelant pourra communiquer avec la personne qu'il appelle avant d'établir une connexion d'égal à égal.
WebRTC utilisera le protocole de signalisation pour transmettre des informations sur les adresses IP, la capacité de capturer et de lire la voix et la vidéo, la topologie du réseau et les données transmises.
Le protocole couramment utilisé est COMET (ou SIP - note du traducteur) et les sockets Web. WebRTC ne limite pas les développeurs à quoi que ce soit, vous pouvez donc utiliser ce que vous voulez, au moins transférer des données via le Bloc-notes et copier-coller (fait dans l'un des ateliers, cela fonctionne - encore une fois un traducteur). La signalisation connectée aux deux ordinateurs vous permet de démarrer une connexion déjà via WebRTC.
Offrir et répondre
Les connexions WebRTC utilisent "offre" et "réponse":
- L'initiateur de la connexion crée et passe à l'autre côté «offre».
- L'autre partie reçoit une «offre», crée une «réponse» et la renvoie.
- L'initiateur de la connexion reçoit une «réponse».
C'est en théorie. Dans la pratique, l'échange de courtoisies n'est pas si simple.
- Avant de transmettre «offre», l'initiateur de connexion crée une instance de RTCPeerConnection et en reçoit le paquet de texte «SDP» (Session Description Protocol) à l'aide de rtcPeerConnection.createOffer () ; Ce package décrit la capacité de recevoir / transmettre de la voix et de la vidéo pour le navigateur.
- Le contenu du package SDP est défini comme «description du côté local de la connexion» à l'aide de rtcPeerConnection.setLocalDescription () .
- Le paquet est envoyé à l'autre côté, où son contenu est défini comme «la description de l'autre côté de la connexion» à l'aide de rtcPeerConnection.setRemoteDescription () .
- De l'autre côté de la connexion, son propre package SDP est créé à l'aide de rtcPeerConnection.createAnswer () , son contenu est défini comme la «description du côté local de la connexion».
- Le paquet est transmis à l'initiateur de la connexion, qui définit son contenu comme «une description de l'autre côté de la connexion».
Et seulement après toutes les actions, les deux parties connectées connaissent leurs capacités respectives de réception et d'envoi de voix / vidéo.
Candidats ICE
Mais la capacité de travailler avec les médias ne suffit pas. Après tout, les parties contractantes n'ont encore rien dit sur l'état du réseau.
Vous pouvez savoir quels codecs vidéo le navigateur prend en charge et s'il y a une caméra sur l'ordinateur portable presque instantanément. Il faut du temps pour connaître votre adresse IP externe et la logique de fonctionnement NAT, et les informations sur l'état du réseau sont échangées à mesure que ces informations sont reçues.
Grâce à la technologie Trickle ICE (non prise en charge par tous les navigateurs - note du traducteur), la connexion entre deux appareils WebRTC peut être établie à tout moment - dès qu'un «candidat» approprié est trouvé.
Le développeur doit s'abonner à l'événement
onicecandidate (tout en minuscules!) Et passer les paquets SDP reçus de l'autre côté, où ils doivent être transmis par WebRTC en utilisant la méthode
addIceCandidate (et ici, surprise, majuscule). Cela fonctionne dans les deux sens.
Connexion
WebRTC utilise des éléments comme STUN (Session Traversal Utilities for NAT) et TURN (Traversal Using Relay around NAT) pour établir une connexion. Cela semble effrayant, mais en réalité, il n'y a que deux protocoles réseau.
Serveur STUN
Le premier des deux protocoles est un peu plus compliqué que le serveur d'écho. Lors de la connexion, les participants veulent décrire comment s'y connecter, ils ont besoin de leur adresse IP publique. Et ce ne sera probablement pas l'adresse IP de l'ordinateur, les appareils publics sont rarement attribués aux appareils des utilisateurs. Toute la technologie NAT a été inventée pour ne pas isoler. Pour connaître toujours votre adresse publique, le navigateur fait une demande au serveur STUN. En passant par NAT, le paquet réseau change son adresse de retour en public. Après avoir reçu le paquet avec la demande, le serveur STUN copie l'adresse de retour du paquet dans sa charge utile et renvoie le paquet. En passant par NAT dans la direction opposée, le paquet perd son adresse IP publique, mais une copie de cette adresse reste dans la charge utile, où WebRTC peut la lire.
Serveur TURN
Le serveur TURN utilise l'extension de protocole STUN. Les mêmes packages, en-têtes et une nouveauté: la
commande . Le serveur est un proxy: les deux clients s'y connectent via le port d'
allocation UDP et transmettent leurs données via le serveur.
Les serveurs TURN sont conçus de telle manière que l'initiateur de la connexion possède plus de fonctionnalités que l'autre côté. Cela conduit à un effet intéressant lorsqu'un appel via un serveur TURN est réussi ou échoué, selon qui appelle qui (rappelez-vous tous Skype - traducteur de notes).
Débogage
Donc, vous lisez ce paragraphe. Nous sommes satisfaits du traducteur et rappelons que l'article concerne le débogage de WebRTC. Mais tout ce qui précède est un minimum nécessaire, sans lequel vous ne pouvez même pas commencer. Mais si vous commencez et que vous n'avez pas de chance inhumaine, alors cela se cassera.
Il se brisera de différentes manières. Le premier est le manque de connectivité. Vous avez transmis les paramètres de serveur STUN et TURN aux deux WebRTC, les avez aidés à échanger des offres, des réponses et des candidats ICE, mais il n'y a ni vidéo ni voix. Par où commencer? Avec des problèmes de lecture locale.
Débogage local WebRTC
Comme je l'ai écrit ci-dessus, le travail principal de WebRTC se produit du côté du navigateur. Les serveurs STUN et TURN sont incroyablement simples, donc la plupart des problèmes se produisent dans votre code JavaScript, qui s'exécute dans deux navigateurs. Triste mais vrai. D'un autre côté, si la chose la plus intéressante se produit localement dans les navigateurs, vous avez amplement l'occasion de déboguer!
La première chose à vérifier est votre signalisation. C'est votre code qui transmet la configuration de l'audio avec la vidéo (offre, réponse) et les informations sur les paramètres réseau (candidats Ice) entre les navigateurs. Vous devez vérifier quels paquets ont été envoyés, lesquels ont reçu et transmis WebRTC:
- l'autre côté de la connexion a reçu une offre? L'initiateur de la connexion a-t-il reçu une réponse? Une connexion ne sera pas établie sans cet échange minimal de commodités;
- WebRTC aux deux extrémités de la connexion vous at-il transmis des paquets avec des candidats ICE? Avez-vous échangé ces paquets et les avez-vous renvoyés de l'autre côté en utilisant addIceCandidate ?
- si tout s'est bien passé avec l'échange de paquets, le gestionnaire d' événement onaddstream a-t-il été appelé et avez-vous installé l'objet résultant dans un élément HTML pour lire la vidéo (ou l'audio)?
Si l'échange de paquets n'est pas suspect, vous pouvez plonger dans les tripes de la session.
Protocole de description de session
Les packages d'offres, de réponses et de candidats ICE sont créés par WebRTC au format texte SDP. À première vue, le contenu des packages semble effrayant, mais avec un peu de préparation, vous pouvez en tirer beaucoup d'avantages lors du débogage. Wikipedia décrit assez bien le SDP, mais j'ai trouvé une
meilleure description pour vous.
Le champ le plus important dans les paquets SDP ICE candidats est
typ . Pour WebRTC, un champ peut avoir l'une des trois valeurs suivantes:
- hôte de type;
- typ srflx;
- relais de type.
hôte de type
Le type d'
hôte spécifie le candidat ICE pour une connexion locale (WebRTC énumère plusieurs candidats dans l'espoir d'établir une connexion, on ne sait pas à l'avance lequel se révélera - note du traducteur). Une telle connexion ne nécessite ni serveur STUN ni serveur TURN, car les périphériques du réseau local peuvent souvent établir directement des connexions réseau. Lors du débogage à partir du réseau local, il vous suffit de vérifier et de déboguer la transmission des paquets
hôtes et de vous assurer que les périphériques peuvent s’envoyer des paquets UDP. Bien qu'il y ait des exceptions, dans la pratique, j'ai vu des configurations de réseau dans lesquelles le navigateur avait besoin d'un serveur TURN pour se connecter ... à lui-même.
typ srflx
La combinaison des lettres «srflx» signifie «Server Reflexive» et marque les candidats à la connexion en utilisant une adresse IP externe, où un serveur STUN est suffisant pour la connexion (en utilisant la technologie de pénétration NAT, qui réussit dans environ 80% des cas, note le traducteur).
relais type
«Relay» marque la connexion via un serveur TURN, qui est presque toujours réussie. Il est important de se rappeler que WebRTC n'est pas requis pour créer exactement trois packages différents avec le champ «typ»; la façon dont les candidats sont sélectionnés dépend de l'implémentation de WebRTC dans une version de navigateur spécifique.
Test de la connectivité des appareils
Google propose une
application Web dédiée pour tester les connexions WebRTC sur votre appareil. Ouvrez la page, cliquez sur le bouton "Démarrer" et le code JavaScript tentera d'établir une connexion avec le serveur Google en utilisant la signalisation, les serveurs STUN et TURN de Google.
Internes WebRTC
Vous avez examiné tous les packages, vérifié le code, tout semble correct, mais cela ne fonctionne pas? Pour de tels cas, Google a fourni à son navigateur Chrome une section spéciale qui montre les composants internes de WebRTC pendant la configuration de la connexion et quelques beaux graphiques en cas de connexion réussie. Pour l'utiliser, ouvrez un lien technique spécial dans le navigateur:
chrome://webrtc-internals
Si vous avez déjà une application utilisant WebRTC ouverte, vous verrez immédiatement un tas de données techniques. Sinon, ouvrez simplement un autre onglet et il y a quelque chose qui utilise WebRTC. L'onglet affiche tous les appels à l'objet
RTCPeerConnection et vous permet de voir en temps réel comment la connexion est établie.
Configuration ICE
En haut de la page se trouve la chaîne ICE qui a été utilisée pour initialiser la connexion. Si une erreur a été commise lors de sa formation, elle sera immédiatement visible (par la "ligne ICE" l'auteur se réfère à la configuration de l'objet RTCPeerConnection avec une liste de serveurs STUN et TURN (l'objet 'iceServers') - note du traducteur). Peut-être qu'il n'y a pas de liste de serveurs? Vous devez configurer l'objet RTCPeerConnection avant d'effectuer le premier appel à
createOffer ou
createAnswer .
Événements RTCPeerConnection
La section interne suivante montre les appels aux méthodes
RTCPeerConnection et les événements reçus de l'objet dans l'ordre chronologique. Les erreurs sont soigneusement mises en évidence en rouge. Veuillez noter que le rouge
addIceCandidateFailed n'est souvent pas un signe d'erreur et que la connexion peut s'établir normalement. Si la connexion réussit, le dernier événement de la liste sera un événement
iceconnectionstatechange avec la valeur
complete .
Section 'stats'
La section suivante est pertinente lorsque la connexion est établie avec succès. Il contient des statistiques sur les données transmises et les retards du réseau. Les deux options les plus intéressantes sont:
ssrc et
bweforvideo .
- ssrc , "Stream Source", marque chacune de vos pistes audio et vidéo. Affiche les statistiques des données transmises et des paramètres tels que le temps d' aller-retour ;
- bweforvideo , BandWidth Estimate, affiche la largeur du canal réseau utilisé.
Fonction GetStats
Souvent, vous ne pourrez pas accéder à la page des internes. Par exemple, lorsqu'un problème survient avec votre utilisateur. Dans ce cas, vous pouvez obtenir les mêmes données que la page des éléments internes montre en appelant la méthode
getStats sur l'objet
RTCPeerConnection . Cette méthode met en place une fonction de rappel que WebRTC appellera chaque fois que quelque chose d'intéressant se produit. La fonction appelée obtient un objet avec les champs que la page interne affiche:
rtcPeerConnection.getStats(function(stats) { document.getElementById("lostpackets").innerText = stats.packetsLost; });
Un autre outil utile est l'événement
oniceconnectionstatechange d'un objet
RTCPeerConnection . Le gestionnaire d'événements recevra des informations sur la progression de la connexion. Options possibles:
- nouveau : WebRTC attend des candidats du deuxième côté de la connexion, qui doit être ajouté à l'aide de la méthode addIceCandidate ;
- vérification : WebRTC a reçu les candidats du deuxième côté de la connexion, les compare avec les candidats locaux et répète les options;
- connecté : une paire de candidats appropriée est sélectionnée et la connexion est établie. Il est à noter qu'après cela, les candidats peuvent continuer à venir, conformément au protocole Trickle ICE;
- terminé : tous les candidats sont reçus et la connexion est établie.
- déconnecté : la connexion est déconnectée . Sur les canaux instables WebRTC est capable de se reconnecter, nous surveillons l'indicateur connecté ;
- fermée : la connexion est déconnectée et WebRTC ne fonctionne plus avec elle.
Si la connexion s'est terminée dans l'état
défaillant , alors nous pouvons examiner les candidats reçus des deux côtés et comprendre pourquoi la connexion a échoué. Par exemple, si un côté a fourni
des candidats hôte et
srflx , l'autre côté
hôte et
relais , mais les périphériques étaient sur des réseaux différents.
Rectangle noir au lieu de la vidéo
Il y a souvent une situation où la connexion est établie, le son est transmis, mais au lieu de la vidéo, un ou les deux participants ont un rectangle noir. Le plus souvent, cela se produit si vous affectez l'objet vidéo reçu à un élément HTML avant que la connexion ne passe à l'état
terminé .
Comment pousser une baguette à l'extérieur
En plus de l'objet
RTCPeerConnection lui -
même et des éléments internes affichés par le navigateur, vous pouvez utiliser des outils d'analyse de paquets réseau tels que Wireshark. Ces outils peuvent afficher des paquets de protocoles WebRTC utilisés. Par exemple, Wireshark vous montrera le contenu des paquets STUN dans la fenêtre principale, et vous pouvez les filtrer en tapant le mot clé "stun" dans le champ de filtre:
Que regarder dans les réponses du serveur? Si vous ne voyez que des réponses de type
Liaison , cela signifie que seul STUN (conversation IP externe) est pris en charge et WebRTC ne peut proposer que des candidats
srflx . Si les réponses contiennent l'
allocation de packages spécifiques à TURN et
CreatePermission , WebRTC aura la possibilité d'essayer de se connecter via un serveur proxy. L'analyseur de paquets marque l'
allocation réussie et non réussie. S'il n'y en a pas un, il est probable que les mauvais paramètres d'accès aux serveurs TURN (qui se protègent presque toujours avec un nom d'utilisateur et un mot de passe - la note du traducteur) soient transmis.
S'il y a un
package CreatePermission Success Response dans le journal, nous pouvons supposer que tout va bien avec les configurations STUN et TURN. Et s'il existe également un package
ChannelBind , il était possible d'établir une connexion au serveur TURN à grande vitesse.
Problèmes cellulaires
Dans ma pratique, de nombreuses solutions WebRTC qui établissent une connexion WiFi ne peuvent pas se connecter via 3G / 4G. Une application lancée sur un appareil mobile est plus difficile à déboguer: nous n'avons pas un analyseur de paquets aussi simple que Wireshark, et Safari ne peut pas afficher les internes de WebRTC. La logique suggère que si l'application fonctionne correctement via WiFi, le problème ne vient pas de l'application elle-même, mais de la communication cellulaire. Comment déboguer? Prenez un ordinateur portable et connectez-y un
dongle 3G . Vous disposez donc d'un analyseur de paquets et de journaux pratiques avec lesquels vous pouvez trouver la racine de tous les problèmes dans un délai raisonnable.
Conclusions
Le débogage de WebRTC n'est pas facile, mais si vous recherchez bien sur Internet, vous pouvez trouver de nombreux articles et exemples. Si vous travaillez dans le domaine des communications en temps réel, je vous recommande de lire les spécifications RFC pour les protocoles
STUN ,
TURN et la technologie
WebRTC . Les documents sont volumineux, mais les informations qu'ils contiennent aident à prendre des décisions fiables et à répondre à la question «pourquoi ça ne sonne pas».