Cómo depurar WebRTC

En Voximplant, hemos estado usando WebRTC desde su inicio: primero como una alternativa a Flash para llamadas de voz y video, y luego como un reemplazo completo. La tecnología ha recorrido un largo y doloroso camino de desarrollo, solo recientemente todos los principales navegadores han comenzado a admitirla, existen dificultades con la transferencia de pantalla, varias transmisiones de video y, a veces, el navegador se bloquea simplemente si apaga y enciende la transmisión de video. La experiencia acumulada nos permite traducir artículos interesantes para Habr, y hoy le pasamos la voz a Lee Sylvester de Xirsys, quien hablará sobre depuración de llamadas (video) en Chrome, Firefox, Safari y Edge. La depuración de WebRTC no es fácil, incluso tenemos instrucciones especiales para eliminar registros en navegadores populares. Y lo que Lee tiene: lo descubrirá debajo del corte (spoiler: mucho de todo, incluido WireShark).


El lado oscuro de WebRTC


Mientras trabajaba en Xirsys, vi algunas aplicaciones realmente geniales que usaban WebRTC. Pero mientras un pequeño grupo de desarrolladores crea cosas de alta tecnología, la mayoría de los programadores ni siquiera pueden comenzar a usar WebRTC. Por qué Y todo es simple. Es complicado

Muchos de nosotros estamos familiarizados con una aplicación web típica. Dicha aplicación tiene un cliente que envía solicitudes y un servidor que responde a estas solicitudes. Un proceso simple, lineal y fácilmente predecible. Si algo sale mal, generalmente sabemos dónde mirar los registros y qué podría suceder. Pero con WebRTC, no todo es tan simple.

Asincronía


Si alguna vez ha escrito una aplicación multiproceso, entonces probablemente conozca el dolor de cabeza que genera este desarrollo. Vuelos, mala memoria, pero a menudo solo errores que son difíciles de encontrar.

WebRTC es de naturaleza asíncrona. Y esto no es en absoluto la simple asincronía AJAX. Para establecer una analogía, estas son varias solicitudes AJAX lanzadas simultáneamente que intentan conciliar datos en dos computadoras. Eso sigue siendo entretenimiento.

Campo de minas de derivación NAT


La creación de aplicaciones web se reduce al desarrollo de algo que se ejecuta en el servidor y responde a las solicitudes. Lo peor que puede pasar es el puerto que no está abierto en IPTables. Se trata en 2 minutos. No se puede decir sobre WebRTC.

Los servidores web, ni siquiera su software, sino su hardware, son dispositivos con direcciones IP públicas. Están hechos para ser accesibles desde cualquier lugar. Y WebRTC está hecho para enviar y recibir datos de las computadoras de los usuarios. Que suelen tener una dirección IP de 192.168. Algo y no se queman con el deseo de responder a las solicitudes de red.

Los autores de WebRTC lo saben, por lo que el motor clasificará los diferentes métodos de conexión, en un intento de establecer una conexión entre dos computadoras que no están muy diseñadas para ello.

Dónde comenzar a depurar


En este artículo hablo sobre las herramientas básicas para resolver los problemas más populares. Pero antes de eso, veamos cómo WebRTC generalmente establece una conexión.

Cómo WebRTC establece una conexión


Todas las conexiones WebRTC requieren un poco de ayuda del protocolo de señalización. "Pequeña ayuda" es su propio servidor y protocolo con el que la persona que llama podrá comunicarse con la persona a la que llama antes de establecer una conexión punto a punto.

WebRTC utilizará el protocolo de señalización para transmitir información sobre direcciones IP, la capacidad de capturar y reproducir voz y video, topología de red y datos transmitidos.

El protocolo de uso común es COMET (o SIP - nota del traductor) y sockets web. WebRTC no limita a los desarrolladores a nada, por lo que puede usar lo que quiera, al menos transferir datos a través del Bloc de notas y copiar y pegar (hecho en uno de los talleres, funciona, nuevamente un traductor). La señalización conectada a ambas computadoras le permite iniciar una conexión ya a través de WebRTC.

Oferta y respuesta


Las conexiones WebRTC usan "oferta" y "respuesta":

  1. El iniciador de la conexión crea y pasa al otro lado "oferta".
  2. La otra parte recibe una "oferta", crea una "respuesta" y la devuelve.
  3. El iniciador de la conexión recibe una "respuesta".

Esto es en teoría. En la práctica, el intercambio de cortesías no parece tan simple.

  1. Antes de transmitir la "oferta", el iniciador de conexión crea una instancia de RTCPeerConnection y recibe de él el paquete de texto "SDP" (Protocolo de descripción de sesión) usando rtcPeerConnection.createOffer () ; Este paquete describe la capacidad de recibir / transmitir voz y video para el navegador.
  2. El contenido del paquete SDP se establece como "descripción del lado local de la conexión" utilizando rtcPeerConnection.setLocalDescription () .
  3. El paquete se envía al otro lado, donde su contenido se establece como "la descripción del otro lado de la conexión" mediante rtcPeerConnection.setRemoteDescription () .
  4. En el otro lado de la conexión, su propio paquete SDP se crea usando rtcPeerConnection.createAnswer () , su contenido se establece como la "descripción del lado local de la conexión".
  5. El paquete se pasa al iniciador de la conexión, que establece su contenido como "una descripción del otro lado de la conexión".

Y solo después de todas las acciones, ambas partes conectadas conocen las capacidades del otro para recibir y enviar voz / video.

Candidatos de ICE


Pero la capacidad de trabajar con los medios no es suficiente. Después de todo, las partes contratantes aún no han dicho nada sobre el estado de la red.

Puede averiguar qué códecs de video admite el navegador y si hay una cámara en la computadora portátil casi al instante. Toma tiempo encontrar su dirección IP externa y la lógica de la operación NAT, y la información sobre el estado de la red se intercambia a medida que se recibe esta información.

Gracias a la tecnología Trickle ICE (no es compatible con todos los navegadores - nota del traductor), la conexión entre dos dispositivos WebRTC se puede establecer en cualquier momento, tan pronto como se encuentre un "candidato" adecuado.

El desarrollador debe suscribirse al evento onicecandidate (¡todo en minúsculas!) Y pasar los paquetes SDP recibidos al otro lado, donde deben ser transmitidos por WebRTC utilizando el método addIceCandidate (y aquí, sorpresa, mayúscula). Funciona en ambos sentidos.

Conexión


WebRTC utiliza cosas como STUN (Utilidades transversales de sesión para NAT) y TURN (Transversal mediante retransmisión alrededor de NAT) para establecer una conexión. Suena aterrador, pero en realidad solo hay dos protocolos de red.

Servidor STUN


El primero de los dos protocolos es un poco más complicado que el servidor echo. Cuando los participantes que se conectan desean describir cómo conectarse a ellos, necesitan su dirección IP pública. Y lo más probable es que no sea la dirección IP de la computadora, los dispositivos públicos rara vez se asignan a los dispositivos de los usuarios. Toda la tecnología NAT fue inventada para no aislar. Para averiguar aún su dirección pública, el navegador realiza una solicitud al servidor STUN. Al pasar por NAT, el paquete de red cambia su dirección de retorno a público. Una vez recibido el paquete con la solicitud, el servidor STUN copia la dirección de retorno del paquete a su carga útil y lo devuelve. Al pasar por NAT en la dirección opuesta, el paquete pierde su dirección IP pública, pero una copia de esta dirección permanece en la carga útil, donde WebRTC puede leerlo.


Servidor TURN


El servidor TURN usa la extensión de protocolo STUN. Los mismos paquetes, encabezados, más una cosa nueva: comando . El servidor es un proxy: ambos clientes se conectan a él a través del puerto de asignación UDP y transmiten sus datos a través del servidor.

Los servidores TURN están diseñados de tal manera que el iniciador de la conexión tiene más funciones que el otro lado. Esto lleva a un efecto interesante cuando una llamada a través de un servidor TURN es exitosa o no, dependiendo de quién llama a quién (recuerde todo el traductor de notas de Skype).


Depuración


Entonces, leíste este párrafo. Estamos contentos con el traductor y recordamos que el artículo trata sobre la depuración de WebRTC. Pero todo lo anterior es un mínimo necesario, sin el cual ni siquiera puede comenzar. Pero si comienzas y no tienes suerte inhumana, entonces se romperá.

Se romperá de muchas maneras diferentes. El primero es la falta de conectividad. Pasó la configuración del servidor STUN y TURN a ambos WebRTC, los ayudó a intercambiar ofertas, respuestas y candidatos de ICE, pero no hay video ni voz. Por donde empezar Con problemas de reproducción local.

Depuración local de WebRTC


Como escribí anteriormente, el trabajo principal de WebRTC ocurre en el lado del navegador. Los servidores STUN y TURN son increíblemente simples, por lo que la mayoría de los problemas ocurren en su código JavaScript, que se ejecuta en dos navegadores. Triste pero cierto. Por otro lado, si lo más interesante sucede localmente en los navegadores, ¡entonces tienes muchas oportunidades para depurar!

Lo primero que debe verificar es su señalización. Es su código el que transmite la configuración de audio con video (oferta, respuesta) e información sobre la configuración de red (candidatos de hielo) entre los navegadores. Debe verificar qué paquetes se enviaron, cuáles recibieron y transmitieron WebRTC:

  • el otro lado de la conexión recibió una oferta? ¿El iniciador de conexión ha recibido una respuesta? No se establecerá una conexión sin este intercambio mínimo de servicios;
  • ¿WebRTC en ambos extremos de la conexión le pasó paquetes con candidatos de ICE? ¿Intercambiaste estos paquetes y los devolviste al lado opuesto usando addIceCandidate ?
  • si todo salió bien con el intercambio de paquetes, ¿se llamó al controlador de eventos onaddstream e instaló el objeto resultante en un elemento HTML para reproducir video (o audio)?

Si el intercambio de paquetes no es sospechoso, puede profundizar en las entrañas de la sesión.

Protocolo de descripción de sesión


WebRTC crea los paquetes de oferta, respuesta e ICE en formato de texto SDP. A primera vista, el contenido de los paquetes parece aterrador, pero con un poco de preparación puede obtener muchos beneficios durante la depuración. Wikipedia describe SDP bastante bien, pero encontré una mejor descripción para ti.

El campo más importante en los paquetes candidatos de ICE SDP es el típico . Para WebRTC, un campo puede tener uno de tres valores:

  • tipo host;
  • Typ srflx;
  • relé típico

host típico


El tipo de host especifica el candidato ICE para una conexión de área local (WebRTC enumera varios candidatos con la esperanza de establecer una conexión, no se sabe de antemano cuál resultará - nota del traductor). Dicha conexión no requiere un servidor STUN o TURN, ya que los dispositivos en la red local a menudo pueden establecer conexiones de red directamente. Al depurar desde la red local, solo necesita verificar y depurar la transmisión de paquetes de host y asegurarse de que los dispositivos puedan enviarse paquetes UDP entre sí. Aunque hay excepciones, en la práctica he visto configuraciones de red en las que el navegador necesitaba un servidor TURN para conectarse ... a sí mismo.

Typ srflx


La combinación de letras "srflx" significa "Server Reflexive" y marca a los candidatos a la conexión utilizando una dirección IP externa, donde un servidor STUN es suficiente para la conexión (utilizando la tecnología de penetración NAT, que tiene éxito en aproximadamente el 80% de los casos, tenga en cuenta el traductor).

relé típico


"Relay" marca la conexión a través de un servidor TURN, que casi siempre es exitoso. Es importante recordar que WebRTC no está obligado a crear exactamente tres paquetes diferentes con el campo "típico"; cómo se seleccionan los candidatos depende de la implementación de WebRTC en una versión específica del navegador.

Probar la conectividad del dispositivo


Google ofrece una aplicación web dedicada para probar las conexiones WebRTC en su dispositivo. Abra la página, haga clic en el botón "Inicio" y el código JavaScript intentará establecer una conexión con el servidor de Google mediante la señalización, los servidores STUN y TURN de Google.

WebRTC Internals


¿Examinó todos los paquetes, comprobó el código, todo parece correcto, pero no funciona? Para tales casos, Google ha proporcionado a su navegador Chrome una sección especial que muestra los aspectos internos de WebRTC durante la configuración de la conexión y algunos gráficos hermosos en caso de una conexión exitosa. Para usar, abra un enlace técnico especial en el navegador:

chrome://webrtc-internals

Si ya tiene abierta una aplicación que usa WebRTC, verá inmediatamente un montón de datos técnicos. De lo contrario, solo abra otra pestaña y hay algo en ella que usa WebRTC. La pestaña muestra todas las llamadas al objeto RTCPeerConnection y le permite ver en tiempo real cómo se establece la conexión.

Configuración ICE


En la parte superior de la página está la cadena ICE que se usó para inicializar la conexión. Si se cometió un error durante su formación, esto será inmediatamente visible (por la "línea ICE" el autor se refiere a la configuración del objeto RTCPeerConnection con una lista de servidores STUN y TURN (el objeto 'iceServers') - nota del traductor). ¿Quizás no hay una lista de servidores? Debe configurar el objeto RTCPeerConnection antes de realizar la primera llamada a createOffer o createAnswer .


RTCPeerConnection Events


La siguiente sección interna muestra las llamadas a los métodos RTCPeerConnection y los eventos recibidos del objeto en orden cronológico. Los errores se resaltan cuidadosamente en rojo. Tenga en cuenta que el addIceCandidateFailed rojo a menudo no es un signo de error y la conexión puede establecerse normalmente. Si la conexión es exitosa, el último evento en la lista será un evento iceconnectionstatechange con un valor de complete .

Sección 'estadísticas'


La siguiente sección es relevante cuando la conexión se establece con éxito. Contiene estadísticas de datos transmitidos y retrasos en la red. Las dos opciones más interesantes son: ssrc y bweforvideo .

  • ssrc , "Stream Source", marca cada una de sus pistas de audio y video. Muestra estadísticas de datos transmitidos y parámetros como el tiempo de ida y vuelta ;
  • bweforvideo , BandWidth Estimate, muestra el ancho del canal de red utilizado.


Función GetStats


A menudo no podrá acceder a la página interna. Por ejemplo, cuando ocurre un problema con su usuario. En este caso, puede obtener los mismos datos que muestra la página interna llamando al método getStats en el objeto RTCPeerConnection . Este método configura una función de devolución de llamada que WebRTC llamará cada vez que ocurra algo interesante. La función llamada obtiene un objeto con los campos que muestra la página interna:

 rtcPeerConnection.getStats(function(stats) { document.getElementById("lostpackets").innerText = stats.packetsLost; }); 

Otra herramienta útil es el evento oniceconnectionstatechange de un objeto RTCPeerConnection . El controlador de eventos recibirá información sobre el progreso de la conexión. Posibles opciones:

  • nuevo : WebRTC espera candidatos del segundo lado de la conexión, que deben agregarse utilizando el método addIceCandidate ;
  • comprobación : WebRTC recibió candidatos del segundo lado de la conexión, los compara con los locales e itera sobre las opciones;
  • conectado : se selecciona un par adecuado de candidatos y se establece la conexión. Es de destacar que después de esto, los candidatos pueden continuar viniendo, de acuerdo con el protocolo Trickle ICE;
  • completado : se reciben todos los candidatos y se establece la conexión.
  • desconectado : la conexión está desconectada . En canales inestables, WebRTC puede reconectarse, monitoreamos la bandera conectada ;
  • cerrado : la conexión se desconecta y WebRTC ya no funciona con ella.

Si la conexión terminó en estado fallido , entonces podemos examinar los candidatos recibidos en ambos lados y entender por qué falló la conexión. Por ejemplo, si un lado proporcionó candidatos host y srflx , el otro lado host y retransmisión , pero los dispositivos estaban en redes diferentes.

Rectángulo negro en lugar de video


A menudo hay una situación en la que se establece la conexión, se transmite el sonido, pero en lugar del video, uno o ambos participantes tienen un rectángulo negro. En la mayoría de los casos, esto sucede si asigna el objeto de video recibido a un elemento HTML antes de que la conexión pase al estado completado .

Cómo meter una varita afuera


Además del objeto RTCPeerConnection y las partes internas que muestra el navegador, puede utilizar herramientas de análisis de paquetes de red como Wireshark. Estas herramientas pueden mostrar paquetes de protocolos WebRTC usados. Por ejemplo, Wireshark le mostrará el contenido de los paquetes STUN en la ventana principal, y puede filtrarlos escribiendo la palabra clave "aturdir" en el campo de filtro:


¿Qué mirar en las respuestas del servidor? Si solo ve respuestas con el tipo de enlace , esto significa que solo se admite STUN (conversación de IP externa) y WebRTC solo puede ofrecer candidatos srflx . Si las respuestas contienen la asignación de paquetes específicos de TURN y CreatePermission , WebRTC tendrá la oportunidad de intentar conectarse a través de un servidor proxy. El analizador de paquetes marca la asignación exitosa y no exitosa. Si no hay uno exitoso, lo más probable es que se pasen los parámetros de acceso incorrectos a los servidores TURN (que casi siempre protegen con un nombre de usuario y contraseña, la nota del traductor).

Si hay un paquete CreatePermission Success Response en el registro, entonces podemos suponer que todo está bien con las configuraciones STUN y TURN. Y si también hay un paquete ChannelBind , entonces fue posible establecer una conexión con el servidor TURN a alta velocidad.

Problemas celulares


En mi práctica, muchas soluciones WebRTC que establecen una conexión WiFi no pueden conectarse a través de 3G / 4G. Una aplicación iniciada en un dispositivo móvil es más difícil de depurar: no tenemos un analizador de paquetes tan simple como Wireshark, y Safari no puede mostrar los elementos internos de WebRTC. La lógica sugiere que si la aplicación funciona bien a través de WiFi, entonces el problema no está en la aplicación en sí, sino en la comunicación celular. ¿Cómo depurar? Tome una computadora portátil y conéctele un dongle 3G . Por lo tanto, tiene un analizador de paquetes y registros convenientes con los que puede encontrar la raíz de todos los problemas en un tiempo razonable.

Conclusiones


La depuración de WebRTC no es fácil, pero si busca bien en Internet, puede encontrar muchos artículos y ejemplos. Si trabaja en el campo de las comunicaciones en tiempo real, le recomiendo que lea las especificaciones de RFC para los protocolos STUN , TURN y la tecnología WebRTC . Los documentos son grandes, pero la información contenida en ellos ayuda a tomar decisiones confiables y responder la pregunta "por qué no suena".

Source: https://habr.com/ru/post/es417869/


All Articles